--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/sipvoipprovider/src/svpmosession.cpp Mon Jan 18 20:12:36 2010 +0200
@@ -0,0 +1,917 @@
+/*
+* Copyright (c) 2006-2008 Nokia Corporation and/or its subsidiary(-ies).
+* All rights reserved.
+* This component and the accompanying materials are made available
+* under the terms of "Eclipse Public License v1.0"
+* which accompanies this distribution, and is available
+* at the URL "http://www.eclipse.org/legal/epl-v10.html".
+*
+* Initial Contributors:
+* Nokia Corporation - initial contribution.
+*
+* Contributors:
+*
+* Description: Representation of SVP Mo session
+*
+*/
+
+#include <mcesecureoutsession.h>
+#include <badesca.h>
+#include <mccpforwardobserver.h>
+#include <uriutilscommon.h> // TUriUtilsError
+#include <sipcodecerr.h>
+#include <crcseprofileentry.h>
+#include <crcseprofileregistry.h>
+
+#include "svpmosession.h"
+#include "svpuriparser.h"
+#include "svpforwardprovider.h"
+#include "svpsipconsts.h"
+#include "svplogger.h"
+#include "svputility.h"
+#include "svpcleanupresetanddestroy.h"
+
+
+// ---------------------------------------------------------------------------
+// CSVPMoSession::CSVPMoSession
+// ---------------------------------------------------------------------------
+//
+CSVPMoSession::CSVPMoSession( TUint32 aSessionExpires,
+ TMceTransactionDataContainer& aContainer,
+ MSVPSessionObserver& aObserver,
+ CSVPUtility& aSVPUtility,
+ CSVPRtpObserver& aRtpObserver )
+ : CSVPSessionBase( aContainer, aObserver, aSVPUtility, aRtpObserver ),
+ iSessionExpires( aSessionExpires )
+ {
+ SVPDEBUG1( "CSVPMoSession::CSVPMoSession In" )
+ SVPDEBUG1( "CSVPMoSession::CSVPMoSession Out" )
+ }
+
+// ---------------------------------------------------------------------------
+// CSVPMoSession::ConstructL
+// ---------------------------------------------------------------------------
+//
+void CSVPMoSession::ConstructL(
+ CMceManager& aMceManager,
+ CRCSEProfileEntry& aVoipProfile,
+ const CCCPCallParameters& aParameters,
+ const TDesC8& aRecipient,
+ TUint32& aSecurityStatus,
+ CDesC8Array* aUserHeaders )
+ {
+ SVPDEBUG1( "CSVPMoSession::ConstructL In" )
+
+ TBool userEqphone = EFalse;
+ TInt err = KErrNone;
+
+ __ASSERT_ALWAYS( aVoipProfile.iIds.Count(), User::Leave( KErrArgument ) );
+ iSipProfileId = aVoipProfile.iIds[ 0 ].iProfileId; // save Sip profile id
+ iVoIPProfileId = aVoipProfile.iId; // save VoIP profile id
+
+ iSecondCallRecipient.Copy( aRecipient ); // save recipient
+ SVPDEBUG2( "CSVPMoSession::ConstructL iSecondCallRecipient length: %d",
+ iSecondCallRecipient.Length() )
+
+ // Copy call parameters
+ iCallParameters = aParameters.CloneL();
+
+ // create SIP and ProfileRegistry for URI handling
+ CSIP* sip = CSIP::NewL( KSVPUid, *this );
+ CleanupStack::PushL( sip );
+ SVPDEBUG1( "CSVPMoSession::ConstructL sip CREATED" )
+
+ CSIPProfileRegistry* sipProfileRegistry = CSIPProfileRegistry::NewL( *sip, *this );
+ CleanupStack::PushL( sipProfileRegistry );
+ SVPDEBUG1( "CSVPMoSession::ConstructL sipProfileRegistry CREATED" )
+
+ // retrieve SIP profile by using sip profile id
+ CSIPProfile* profile = sipProfileRegistry->ProfileL( iSipProfileId );
+ CleanupStack::PushL( profile );
+
+ // Not secure call event is sent later according this
+ iCallEventToBeSent = MCCPCallObserver::ECCPSecureNotSpecified;
+
+ if ( KSVPStatusNonSecure != aSecurityStatus )
+ {
+ // set secure status to 0 if no security mechanism found from SIP profile
+ iSVPUtility.ResolveSecurityMechanismL( *profile, aSecurityStatus );
+ }
+
+ // Check CLIR setting and add relevant information in fromheader.
+ HBufC8* fromheader = iSVPUtility.SetMoFromHeaderLC( aSecurityStatus );
+
+ // check if user=phone needs to be added to outgoing INVITE
+ if ( CRCSEProfileEntry::EOn == aVoipProfile.iUserPhoneUriParameter )
+ {
+ userEqphone = ETrue;
+ }
+
+ // complete sip uri according to the security status
+ HBufC8* uri = CompleteUriL( aRecipient,
+ *profile,
+ aSecurityStatus,
+ userEqphone );
+ CleanupStack::PushL( uri );
+
+ // create Mce out session
+ if ( KSVPStatusNonSecure == aSecurityStatus )
+ {
+ // create non-secure session
+ // must be trapped, so that leave code can be changed to KErrArgument
+ // if uri contains error-causing characters
+ TRAP( err, iSession = CMceOutSession::NewL( aMceManager,
+ *profile, *uri, fromheader ) );
+ SVPDEBUG2( "CSVPMoSession::ConstructL NonSecure trapped: %d", err )
+
+ if ( KErrNone == err )
+ {
+ // set iSecured flag so UI can show right icon
+ iSecured = EFalse;
+ }
+ }
+ else if ( KSVPStatusSecurePreferred == aSecurityStatus )
+ {
+ TRAP( err, iSession = CMceSecureOutSession::NewL(
+ aMceManager, *profile, *uri, fromheader ) );
+ SVPDEBUG2( "CSVPMoSession::ConstructL SecurePreferred trapped: %d", err )
+
+ if ( KErrNone == err )
+ {
+ // set crypto contexts
+ SetCryptoContextL();
+ // Set AVP to use instead of SAVP
+ iSession->SetModifierL( KMceSecureSession, KMceSecurePlainAVP );
+ // set secured flag to ETrue to indicate that this is secure session
+ SetSecurePreferred( ETrue );
+ // set iSecured flag so UI can show right icon
+ iSecured = ETrue;
+ }
+ }
+ else
+ {
+ TRAP( err, iSession = CMceSecureOutSession::NewL(
+ aMceManager, *profile, *uri, fromheader ) );
+ SVPDEBUG2( "CSVPMoSession::ConstructL SetSecureMandatory trapped: %d", err )
+
+ if ( KErrNone == err )
+ {
+ // set crypto contexts
+ SetCryptoContextL();
+ // Set AVP to use instead of SAVP
+ iSession->SetModifierL( KMceSecureSession, KMceSecurePlainAVP );
+ // set secure mandatory flag ETrue, only secure session allowed
+ SetSecureMandatory( ETrue );
+ // set iSecured flag so UI can show right icon
+ iSecured = ETrue;
+ }
+ }
+
+ if ( KUriUtilsErrInvalidUserInfo == err || // -5016
+ KUriUtilsErrInvalidHost == err || // -5017
+ KUriUtilsErrInvalidPort == err || // -5018
+ KUriUtilsErrInvalidHeaders == err || // -5022
+ KErrSipCodecTokenizer == err || // -17751
+ KErrSipCodecFromOrToParams == err ) // -17775
+ {
+ User::Leave( KErrArgument );
+ }
+ else if ( KErrNone != err )
+ {
+ User::Leave( KErrDisconnected );
+ }
+ else
+ {
+ //For PC-Lint Note: #961
+ }
+
+ CleanupStack::PopAndDestroy( uri );
+ CleanupStack::Pop( fromheader );
+
+ // Get keep-alive timer value
+ TUint32 iapId = 0;
+ TBool found = EFalse;
+
+ profile->GetParameter( KSIPAccessPointId, iapId );
+ TRAPD( errKeepAlive, found = iSVPUtility.GetKeepAliveByIapIdL( iapId, iKeepAliveValue ) );
+ SVPDEBUG3( "CSVPMoSession::ConstructL:GetKeepAliveByIapIdL: errKeepAlive = %d found = %d",
+ errKeepAlive, found )
+
+ if ( !found )
+ {
+ const TDesC8* aor;
+ profile->GetParameter( KSIPUserAor, aor );
+ TRAP( errKeepAlive, found = iSVPUtility.GetKeepAliveByAORL( *aor, iKeepAliveValue ) );
+ SVPDEBUG3( "CSVPMoSession::ConstructL:GetKeepAliveByAORL: errKeepAlive = %d found = %d",
+ errKeepAlive, found )
+ }
+
+ CleanupStack::PopAndDestroy( profile );
+ CleanupStack::PopAndDestroy( sipProfileRegistry );
+ CleanupStack::PopAndDestroy( sip );
+
+ // constructs audio streams for this session and adds codecs to streams and
+ // streams to session
+ ConstructAudioStreamsL();
+ InitializePropertyWatchingL();
+
+ // Create forward provider
+ iForwardProvider = CSVPForwardProvider::NewL( *this );
+ iForwardAddressList = new (ELeave) CDesC8ArrayFlat( KSVPContactArrayGranularity );
+
+ // Cant leave anymore, store heap data
+ iUserHeaders = aUserHeaders; // save userheaders
+ iMceManager = &aMceManager; // not own
+
+ SVPDEBUG1( "CSVPMoSession::ConstructL Out" )
+ }
+
+// ---------------------------------------------------------------------------
+// CSVPMoSession::NewL
+// ---------------------------------------------------------------------------
+//
+CSVPMoSession* CSVPMoSession::NewL(
+ CMceManager& aMceManager,
+ const TDesC8& aRecipient,
+ CRCSEProfileEntry& aVoipProfile,
+ const CCCPCallParameters& aParameters,
+ TMceTransactionDataContainer& aContainer,
+ MSVPSessionObserver& aObserver,
+ CSVPUtility& aSVPUtility,
+ CSVPRtpObserver& aRtpObserver,
+ TUint32& aSecurityStatus,
+ CDesC8Array* aUserHeaders )
+ {
+ CSVPMoSession* self = new( ELeave ) CSVPMoSession(
+ aVoipProfile.iSIPSessionExpires, aContainer, aObserver,
+ aSVPUtility, aRtpObserver );
+ CleanupStack::PushL( self );
+ self->ConstructL( aMceManager,
+ aVoipProfile,
+ aParameters,
+ aRecipient,
+ aSecurityStatus,
+ aUserHeaders );
+ CleanupStack::Pop( self );
+ return self;
+ }
+
+// ---------------------------------------------------------------------------
+// CSVPMoSession::~CSVPMoSession
+// ---------------------------------------------------------------------------
+//
+CSVPMoSession::~CSVPMoSession()
+ {
+ SVPDEBUG1( "CSVPMoSession::~CSVPMoSession In" )
+
+ delete iForwardProvider;
+
+ if ( iUserHeaders )
+ {
+ iUserHeaders->Reset();
+ delete iUserHeaders;
+ }
+
+ if ( iForwardAddressList )
+ {
+ iForwardAddressList->Reset();
+ delete iForwardAddressList;
+ }
+
+ SVPDEBUG1( "CSVPMoSession::~CSVPMoSession Out" )
+ }
+
+// ---------------------------------------------------------------------------
+// CSVPMoSession::CompleteUriL
+// ---------------------------------------------------------------------------
+//
+HBufC8* CSVPMoSession::CompleteUriL( const TDesC8& aRecipient,
+ const CSIPProfile& aSIPProfile,
+ const TUint32& aSecurityStatus,
+ TBool aUserEqualsPhoneRequired )
+ {
+ SVPDEBUG1( "CSVPMoSession::CompleteUriL In" )
+
+ // create instance of uri parser
+ CSVPUriParser* uriParser = CSVPUriParser::NewLC();
+
+ const TDesC8* userAor = NULL;
+ aSIPProfile.GetParameter( KSIPUserAor, userAor );
+
+ // set service id to uri parser, needed for setting user=phone
+ uriParser->SetUserEqualsPhoneRequiredL( aUserEqualsPhoneRequired );
+
+ // complete URI by security status preference
+ HBufC8* uri = NULL;
+ if ( KSVPStatusNonSecure == aSecurityStatus )
+ {
+ SVPDEBUG1( "CSVPMoSession::CompleteUriL Completing SIP URI..." )
+
+ // user tries to call to sips: -uri, secpref -> 0
+ // so iTLSNotInUse is set, so that user can be notified
+ // about non secure session
+ if ( KErrNotFound != aRecipient.Find( KSVPSipsPrefix ) )
+ {
+ iTLSNotInUse = ETrue;
+ }
+ uri = uriParser->CompleteSipUriL( aRecipient, *userAor );
+ }
+ else
+ {
+ SVPDEBUG1( "CSVPMoSession::CompleteUriL Completing SIPS URI..." )
+ uri = uriParser->CompleteSecureSipUriL( aRecipient, *userAor );
+ }
+
+ CleanupStack::PopAndDestroy( uriParser );
+
+ SVPDEBUG1( "CSVPMoSession::CompleteUriL Out" )
+ return uri;
+ }
+
+
+
+// ---------------------------------------------------------------------------
+// CSVPMoSession::CreateNonSecureSessionL
+// ---------------------------------------------------------------------------
+//
+void CSVPMoSession::CreateNonSecureSessionL( CMceManager& aMceManager )
+ {
+ SVPDEBUG1( "CSVPMoSession::CreateNonSecureSessionL In" )
+
+ TBool userEqphone = EFalse;
+
+ // save old secure session first, will be deleted later from SVPController
+ delete iTempSecSession;
+ iTempSecSession = iSession;
+
+ // set iSecured flag so UI can show right icon
+ iSecured = EFalse;
+
+ // set correct event to be sent later on.
+ iCallEventToBeSent = MCCPCallObserver::ECCPNotSecureCall;
+
+ // clear secure preferred flag, needed when deciding whether
+ // old session should be deleted
+ SetSecurePreferred( EFalse );
+
+ // create SIP and ProfileRegistry for URI handling
+ CSIP* sip = CSIP::NewL( KSVPUid, *this );
+ CleanupStack::PushL( sip );
+ CSIPProfileRegistry* sipProfileRegistry =
+ CSIPProfileRegistry::NewL( *sip, *this );
+ CleanupStack::PushL( sipProfileRegistry );
+
+ // retrieve SIP profile by using sip profile id
+ CSIPProfile* profile = sipProfileRegistry->ProfileL( iSipProfileId );
+ CleanupStack::PushL( profile );
+
+ // secure preference to 0
+ TUint32 securePreference = 0;
+
+ RPointerArray< CRCSEProfileEntry > entryArray;
+ CleanupResetAndDestroy< RPointerArray<CRCSEProfileEntry> >::PushL( entryArray );
+ CRCSEProfileRegistry* reg = CRCSEProfileRegistry::NewLC();
+ reg->FindByServiceIdL( iCallParameters->ServiceId(), entryArray ); // Get VoIP profile by service id
+
+ // Take first entry from array
+ __ASSERT_ALWAYS( entryArray.Count(), User::Leave( KErrArgument ) );
+ CRCSEProfileEntry* entry = entryArray[0];
+
+ // check if user=phone needs to be added to outgoing INVITE
+ if ( CRCSEProfileEntry::EOn == entry->iUserPhoneUriParameter )
+ {
+ userEqphone = ETrue;
+ }
+
+ // cleanup
+ CleanupStack::PopAndDestroy( 2, &entryArray ); // reg, entryArray
+
+ // complete sip uri according to the security status
+ HBufC8* uri = CompleteUriL( iSecondCallRecipient,
+ *profile,
+ securePreference,
+ userEqphone );
+ CleanupStack::PushL( uri );
+
+ // nullify iSession member, but do not delete
+ iSession = NULL;
+ iSession = CMceOutSession::NewL( aMceManager, *profile, *uri );
+
+ CleanupStack::PopAndDestroy( uri );
+ CleanupStack::PopAndDestroy( profile );
+ CleanupStack::PopAndDestroy( 2 ); // sip & sipProfileRegistry
+
+ // constructs audio streams for this Mo session
+ // adds codecs to streams and streams to session
+ ConstructAudioStreamsL();
+
+ // Dial, finally
+ User::LeaveIfError( Dial() );
+
+ SVPDEBUG1( "CSVPMoSession::CreateNonSecureSessionL Out" )
+ }
+
+// ---------------------------------------------------------------------------
+// CSVPMoSession::Dial
+// ---------------------------------------------------------------------------
+//
+TInt CSVPMoSession::Dial()
+ {
+ SVPDEBUG1("CSVPMoSession::Dial In" )
+
+ TRAPD( errDial, DialL() );
+
+ SVPDEBUG2("CSVPMoSession::Dial Out return=%d", errDial )
+ return errDial;
+ }
+
+// ---------------------------------------------------------------------------
+// CSVPMoSession::DialL
+// ---------------------------------------------------------------------------
+//
+void CSVPMoSession::DialL()
+ {
+ SVPDEBUG1( "CSVPMoSession::DialL In" )
+
+ ExecCbCallStateChanged( MCCPCallObserver::ECCPStateDialling );
+
+ // inform client about non secure session
+ if ( iTLSNotInUse )
+ {
+ ExecCbCallEventOccurred( MCCPCallObserver::ECCPNotSecureSessionWithSips );
+ }
+
+ if ( iUserHeaders && iUserHeaders->MdcaCount() )
+ {
+ CDesC8ArrayFlat* userHeaders = new ( ELeave ) CDesC8ArrayFlat(
+ iUserHeaders->MdcaCount() );
+ CleanupStack::PushL( userHeaders ); // CS:1
+ for ( TInt i = 0; i < iUserHeaders->MdcaCount(); i++ )
+ {
+ userHeaders->AppendL( iUserHeaders->MdcaPoint( i ) );
+ }
+ static_cast<CMceOutSession*>( iSession )->EstablishL(
+ iSessionExpires, userHeaders, NULL, NULL );
+ CleanupStack::Pop( userHeaders ); // CS:0, ownership transferred
+ }
+ else
+ {
+ static_cast<CMceOutSession*>( iSession )->EstablishL(
+ iSessionExpires, NULL, NULL, NULL );
+ }
+
+ // start INVITE timer in case remote end does not repond
+ StartTimerL( KSVPInviteTimer, KSVPInviteTimerExpired );
+
+ SVPDEBUG1( "CSVPMoSession::DialL Out" )
+ }
+
+// ---------------------------------------------------------------------------
+// CSVPMoSession::Cancel
+// ---------------------------------------------------------------------------
+//
+TInt CSVPMoSession::Cancel()
+ {
+ SVPDEBUG1( "CSVPMoSession::Cancel() Cancel dial" )
+ TRAPD( cancelErr, static_cast<CMceOutSession*>( iSession )->CancelL() );
+ return cancelErr;
+ }
+
+// ---------------------------------------------------------------------------
+// CSVPMoSession::HangUp
+// ---------------------------------------------------------------------------
+//
+TInt CSVPMoSession::HangUp()
+ {
+ SVPDEBUG1( "CSVPMoSession::HangUp In" )
+
+ if ( CMceSession::EOffering == iSession->State() )
+ {
+ SVPDEBUG1( "CSVPMoSession::HangUp CancelL" )
+ TRAPD( err, static_cast<CMceOutSession*>( iSession )->CancelL() );
+
+ ExecCbCallStateChanged( MCCPCallObserver::ECCPStateDisconnecting );
+
+ if( !err )
+ {
+ TRAPD( errTimer, StartTimerL( KSVPMoHangupTerminatingTime,
+ KSVPHangUpTimerExpired ) );
+
+ if ( errTimer )
+ {
+ SVPDEBUG2("CSVPSessionBase::HangUp - timer leave code=%d", errTimer )
+ ExecCbCallStateChanged( MCCPCallObserver::ECCPStateIdle );
+ }
+ else
+ {
+ iAlreadyTerminating = ETrue;
+ }
+ }
+ else
+ {
+ ExecCbCallStateChanged( MCCPCallObserver::ECCPStateIdle );
+ }
+
+ SVPDEBUG2( "CSVPMoSession::HangUp Out return=%d", err )
+ return err;
+ }
+ else
+ {
+ TInt status = CSVPSessionBase::HangUp();
+ SVPDEBUG2( "CSVPMoSession::HangUp Out return=%d", status )
+ return status;
+ }
+ }
+
+// ---------------------------------------------------------------------------
+// CSVPMoSession::Release
+// ---------------------------------------------------------------------------
+//
+TInt CSVPMoSession::Release()
+ {
+ SVPDEBUG1( "CSVPMoSession::Release" )
+ delete this;
+ return KErrNone;
+ }
+
+// ---------------------------------------------------------------------------
+// CSVPMoSession::Hold
+// ---------------------------------------------------------------------------
+//
+TInt CSVPMoSession::Hold()
+ {
+ SVPDEBUG1( "CSVPMoSession::Hold" )
+ return CSVPSessionBase::Hold();
+ }
+
+// ---------------------------------------------------------------------------
+// CSVPMoSession::Resume
+// ---------------------------------------------------------------------------
+//
+TInt CSVPMoSession::Resume()
+ {
+ SVPDEBUG1( "CSVPMoSession::Resume" )
+ return CSVPSessionBase::Resume();
+ }
+
+// ---------------------------------------------------------------------------
+// CSVPMoSession::IsMobileOriginated
+// ---------------------------------------------------------------------------
+//
+TBool CSVPMoSession::IsMobileOriginated() const
+ {
+ SVPDEBUG1( "CSVPMoSession::IsMobileOriginated = ETrue" )
+ return ETrue;
+ }
+
+// ---------------------------------------------------------------------------
+// CSVPMoSession::SessionStateChangedL
+// ---------------------------------------------------------------------------
+//
+void CSVPMoSession::SessionStateChangedL( TInt aOrigStatus,
+ TCCPError aError, TInt aModStatus )
+ {
+ SVPDEBUG1( "CSVPMoSession::SessionStateChangedL In" )
+ SVPDEBUG2( "CSVPMoSession::SessionStateChangedL aOrigStatus=%d",
+ aOrigStatus )
+ SVPDEBUG2( "CSVPMoSession::SessionStateChangedL aError=%d",
+ aError )
+ SVPDEBUG2( "CSVPMoSession::SessionStateChangedL aModStatus=%d",
+ aModStatus )
+
+ // Check security level, cancel secure mandatory call if the control path
+ // is unsecure and the response is 1XX or 2XX
+ CMceSession::TControlPathSecurityLevel secLevel =
+ iSession->ControlPathSecurityLevel();
+
+ SVPDEBUG2( "CSVPMoSession::SessionStateChangedL, security level=%d", secLevel )
+
+ if ( SecureMandatory() && CMceSession::EControlPathUnsecure == secLevel )
+ {
+ switch ( aOrigStatus )
+ {
+ case KSVPRingingVal:
+ case KSVPForwardedVal:
+ case KSVPQueuedVal:
+ case KSVPSessionProgressVal:
+ case KSVPOKVal:
+ case KSVPAcceptedVal:
+ {
+ SVPDEBUG1( "CSVPMoSession::SessionStateChangedL, path not secure, cancel call" )
+ HangUp();
+ ExecCbErrorOccurred( ECCPSecureCallFailed );
+ return;
+ }
+ default:
+ {
+ break;
+ }
+ }
+ }
+
+ if ( KSVPForwardedVal == aOrigStatus )
+ {
+ SVPDEBUG1( "CSVPMoSession::SessionStateChangedL 181 Call is Being Forwarded received" )
+
+ if ( iForwardObserver )
+ {
+ iForwardObserver->ForwardEventOccurred(
+ MCCPForwardObserver::ECCPRemoteForwarding );
+ }
+ }
+
+ CSVPSessionBase::SessionStateChangedL( aOrigStatus, aError, aModStatus );
+ SVPDEBUG1("CSVPMoSession::SessionStateChangedL Out" )
+ }
+
+// ---------------------------------------------------------------------------
+// CSVPMoSession::ForwardProviderL
+// ---------------------------------------------------------------------------
+//
+MCCPForwardProvider* CSVPMoSession::ForwardProviderL( const MCCPForwardObserver& aObserver )
+ {
+ SVPDEBUG1( "CSVPMoSession::ForwardProviderL" )
+ iForwardObserver = const_cast< MCCPForwardObserver* >( &aObserver );
+ return iForwardProvider;
+ }
+
+// ---------------------------------------------------------------------------
+// CSVPMoSession::GetForwardAddressChoicesL
+// ---------------------------------------------------------------------------
+//
+const CDesC8Array& CSVPMoSession::GetForwardAddressChoicesL()
+ {
+ SVPDEBUG1( "CSVPMoSession::GetForwardAddressChoicesL" )
+ return *iForwardAddressList;
+ }
+
+// ---------------------------------------------------------------------------
+// CSVPMoSession::ForwardToAddressL
+// ---------------------------------------------------------------------------
+//
+void CSVPMoSession::ForwardToAddressL( const TInt aIndex )
+ {
+ SVPDEBUG1( "CSVPMoSession::ForwardToAddressL In" )
+ SVPDEBUG2( "CSVPMoSession::ForwardToAddressL aIndex=%d", aIndex )
+
+ if ( iForwardAddressList->MdcaCount() - 1 < aIndex ||
+ KErrNone > aIndex )
+ {
+ SVPDEBUG1( "CSVPMoSession::ForwardToAddressL - Index err! -> Leave!" )
+ User::Leave( KErrArgument );
+ }
+ else
+ {
+ SVPDEBUG1( "CSVPMoSession::ForwardToAddressL - New mce session" )
+
+ // create SIP and ProfileRegistry for URI handling
+ CSIP* sip = CSIP::NewLC( KSVPUid, *this );
+
+ CSIPProfileRegistry* sipProfileRegistry =
+ CSIPProfileRegistry::NewLC( *sip, *this );
+
+ // retrieve SIP profile by using sip profile id
+ CSIPProfile* profile = sipProfileRegistry->ProfileL( iSipProfileId );
+ CleanupStack::PushL( profile );
+
+ RPointerArray< CRCSEProfileEntry > entryArray;
+ CleanupResetAndDestroy<
+ RPointerArray<CRCSEProfileEntry> >::PushL( entryArray );
+
+ CRCSEProfileRegistry* reg = CRCSEProfileRegistry::NewLC();
+
+ // Get VoIP profile by service id
+ reg->FindByServiceIdL( iCallParameters->ServiceId(), entryArray );
+
+ // Take first entry from array
+ CRCSEProfileEntry* entry = entryArray[0];
+
+ // check if user=phone needs to be added to outgoing INVITE
+ TBool userEqphone = EFalse;
+ if ( CRCSEProfileEntry::EOn == entry->iUserPhoneUriParameter )
+ {
+ userEqphone = ETrue;
+ }
+
+ // cleanup
+ CleanupStack::PopAndDestroy( 2, &entryArray ); // reg, entryArray
+
+ // complete sip uri according to the security status
+ HBufC8* uri = CompleteUriL( iForwardAddressList->MdcaPoint( aIndex ),
+ *profile, SecurePreferred(), userEqphone );
+ CleanupStack::PushL( uri );
+
+ // Delete old mce session and create a new one
+ if ( iSession )
+ {
+ delete iSession;
+ iSession = NULL;
+ }
+
+ TRAPD( err, iSession = CMceOutSession::NewL( *iMceManager, *profile, *uri ) );
+
+ if ( KUriUtilsErrInvalidUserInfo == err ||
+ KUriUtilsErrInvalidHost == err )
+ {
+ SVPDEBUG1( "CSVPMoSession::ForwardToAddressL KSVPBadUriError" )
+ User::Leave( KErrArgument );
+ }
+ if ( err )
+ {
+ SVPDEBUG1( "CSVPMoSession::ForwardToAddressL KErrDisconnected" )
+ User::Leave( KErrDisconnected );
+ }
+
+ // constructs audio streams for this Mo session
+ // adds codecs to streams and streams to session
+ ConstructAudioStreamsL();
+
+ CleanupStack::PopAndDestroy( 4 ); // uri, profile, sipProfileRegistry, sip
+
+ User::LeaveIfError( Dial() );
+
+ SVPDEBUG1( "CSVPMoSession::ForwardToAddressL Out" )
+ }
+ }
+
+// ---------------------------------------------------------------------------
+// CSVPMoSession::AddForwardObserverL
+// ---------------------------------------------------------------------------
+//
+void CSVPMoSession::AddForwardObserverL( const MCCPForwardObserver& aObserver )
+ {
+ SVPDEBUG1( "CSVPMoSession::AddForwardObserverL" )
+ iForwardObserver = const_cast<MCCPForwardObserver*>( &aObserver );
+ }
+
+// ---------------------------------------------------------------------------
+// CSVPMoSession::RemoveForwardObserver
+// ---------------------------------------------------------------------------
+//
+TInt CSVPMoSession::RemoveForwardObserver( const MCCPForwardObserver& aObserver )
+ {
+ SVPDEBUG1( "CSVPMoSession::RemoveForwardObserver In" )
+
+ TInt err = KErrNone;
+
+ if ( const_cast<MCCPForwardObserver*>( &aObserver ) == iForwardObserver )
+ {
+ iForwardObserver = NULL;
+ }
+ else
+ {
+ err = KErrNotFound;
+ }
+
+ SVPDEBUG2( "CSVPMoSession::AddForwardObserverL Out return=%d", err )
+ return err;
+ }
+
+// ---------------------------------------------------------------------------
+// CSVPMoSession::NotifyForwardEvent
+// ---------------------------------------------------------------------------
+//
+void CSVPMoSession::NotifyForwardEvent( TInt aEventCode )
+ {
+ SVPDEBUG1( "CSVPMoSession::NotifyForwardEvent In" )
+ SVPDEBUG2( "CSVPMoSession::NotifyForwardEvent aEventCode=%d", aEventCode )
+
+ if ( iForwardObserver )
+ {
+ switch ( aEventCode )
+ {
+ case KSVPMultipleChoicesVal: // 300
+ {
+ iForwardObserver->ForwardEventOccurred(
+ MCCPForwardObserver::ECCPMultipleChoices );
+ break;
+ }
+ case KSVPMovedPermanentlyVal: // 301
+ {
+ iForwardObserver->ForwardEventOccurred(
+ MCCPForwardObserver::ECCPMovedPermanentlyEvent );
+ break;
+ }
+ case KSVPMovedTemporarilyVal: // 302
+ {
+ iForwardObserver->ForwardEventOccurred(
+ MCCPForwardObserver::ECCPMovedTemporarily );
+ break;
+ }
+ default:
+ {
+ SVPDEBUG1( "CSVPMoSession::NotifyForwardEvent unknown event" )
+ break;
+ }
+ }
+ }
+ else
+ {
+ SVPDEBUG1( "CSVPMoSession::NotifyForwardEvent iForwardObserver not exists" )
+ }
+
+ SVPDEBUG1( "CSVPMoSession::NotifyForwardEvent Out" )
+ }
+
+// ---------------------------------------------------------------------------
+// CSVPMoSession::AddForwardAddressL
+// ---------------------------------------------------------------------------
+//
+TInt CSVPMoSession::AddForwardAddressL( const TDesC8& aFwdAddress )
+ {
+ SVPDEBUG1("CSVPMoSession::AddForwardAddressL In" )
+
+ // On return, result contains count of appended forward addresses
+ // or an error code
+ TInt result( 0 );
+ TInt count( 0 );
+
+ // Indicates length of unsearched part of string
+ TInt lenRight( aFwdAddress.Length() );
+ TBool ready( EFalse );
+
+ while ( !ready )
+ {
+ TPtrC8 remainingBuf = aFwdAddress.Right( lenRight );
+
+ // Search comma
+ TInt offset = remainingBuf.Find( KSVPComma );
+
+ if ( KErrNotFound != offset )
+ {
+ lenRight -= offset + 1; // Remove comma from remaining string
+ }
+ else
+ {
+ // Only one forward address remains
+ offset = lenRight;
+ ready = ETrue;
+ }
+
+ // Remove unnecessary spaces from the string
+ HBufC8* address = remainingBuf.Left( offset ).AllocLC();
+ TPtr8 modAddress = address->Des();
+ modAddress.TrimAll();
+
+ iForwardAddressList->AppendL( *address );
+ CleanupStack::PopAndDestroy( address );
+
+ count++;
+ result = count;
+ }
+
+ SVPDEBUG2( "CSVPMoSession::AddForwardAddressL Out return=%d", result )
+ return result;
+ }
+
+// ---------------------------------------------------------------------------
+// CSVPMoSession::ResetForwardAddressChoices
+// ---------------------------------------------------------------------------
+//
+void CSVPMoSession::ResetForwardAddressChoices()
+ {
+ SVPDEBUG1( "CSVPMoSession::ResetForwardAddressChoices" )
+ iForwardAddressList->Reset();
+ }
+
+// SIP
+
+// ---------------------------------------------------------------------------
+// CSVPMoSession::IncomingRequest
+// ---------------------------------------------------------------------------
+//
+void CSVPMoSession::IncomingRequest( TUint32 /*aIapId*/,
+ CSIPServerTransaction* /*aTransaction*/ )
+ {
+ SVPDEBUG1( "CSVPMoSession::IncomingRequest" )
+ }
+
+// ---------------------------------------------------------------------------
+// CSVPMoSession::TimedOut
+// ---------------------------------------------------------------------------
+//
+void CSVPMoSession::TimedOut( CSIPServerTransaction& /*aSIPServerTransaction*/ )
+ {
+ SVPDEBUG1( "CSVPMoSession::TimedOut SIPServerTransaction timed out" )
+ }
+
+// ---------------------------------------------------------------------------
+// CSVPMoSession::ProfileRegistryErrorOccurred
+// ---------------------------------------------------------------------------
+//
+void CSVPMoSession::ProfileRegistryErrorOccurred( TUint32 /*aSIPProfileId*/,
+ TInt /*aError*/ )
+ {
+ SVPDEBUG1( "CSVPMoSession::ProfileRegistryErrorOccurred" )
+ }
+
+// ---------------------------------------------------------------------------
+// CSVPMoSession::ProfileRegistryEventOccurred
+// ---------------------------------------------------------------------------
+//
+void CSVPMoSession::ProfileRegistryEventOccurred( TUint32 /*aProfileId*/,
+ TEvent /*aEvent*/ )
+ {
+ SVPDEBUG1( "CSVPMoSession::ProfileRegistryEventOccurred" )
+ }
+