diff -r 33a5d2bbf6fc -r 73a1feb507fb mmsharing/mmshengine/src/musengmceoutsession.cpp --- a/mmsharing/mmshengine/src/musengmceoutsession.cpp Thu Aug 19 09:51:39 2010 +0300 +++ b/mmsharing/mmshengine/src/musengmceoutsession.cpp Tue Aug 31 15:12:07 2010 +0300 @@ -18,16 +18,17 @@ // USER #include "musengmceoutsession.h" -#include "musengoutsessionobserver.h" -#include "musenglivesessionobserver.h" #include "mussettings.h" #include "musengmceutils.h" #include "musenguriparser.h" #include "musenglogger.h" -#include "mussesseioninformationapi.h" #include "mussipprofilehandler.h" +#include "mussessionproperties.h" +#include "musresourceproperties.h" // SYSTEM +#include +#include #include #include #include @@ -40,20 +41,14 @@ #include #include #include +#include #include #include #include #include -#include - - -const TInt KMusEngSipReasonCodeBadRequest = 400; -const TInt KMusEngSipReasonCodeUnauthorized = 401; -const TInt KMusEngSipReasonCodePaymentRequired = 402; const TInt KMusEngSipReasonCodeRecipientNotFound = 404; -const TInt KMusEngSipReasonCodeProxyAuthenticationRequired = 407; const TInt KMusEngSipReasonCodeRequestTimeout = 408; const TInt KMusEngSipReasonCodeUnsupportedMediaType = 415; const TInt KMusEngSipReasonCodeUnsupportedUriScheme = 416; @@ -64,9 +59,6 @@ const TInt KMusEngSipReasonCodeDecline = 603; const TInt KMusEngSipReasonCodeNotAcceptable = 606; // The next code represents unofficial sip error code -// "478 Unresolveable Destination, we were not able to process the URI (478/TM) -const TInt KMusEngSipReasonCode478NotAbleToProcessURI = 478; -// The next code represents unofficial sip error code // "479 Regretfuly, we were not able to process the URI (479/SL) const TInt KMusEngSipReasonCode479NotAbleToProcessURI = 479; @@ -74,7 +66,66 @@ const TUint8 KMusEngPayloadTypeAudio = 97; const TUint8 KMusEngPayloadTypeVideoAvc = 98; -using namespace NMusSessionInformationApi; +const TInt KMusEngSipAddressMaxLength = 256; +const TInt KMusEngSipAddressesMaxAmount = 8; +_LIT( KMusEngCommaSymbol, "," ); + +// ----------------------------------------------------------------------------- +// +// ----------------------------------------------------------------------------- +// +CMusEngMceOutSession::CMusEngMceOutSession() + : CMusEngMceSession(), + iTriedInvitations( 0 ), + iAsyncBrakeCallBack( AsyncBrakeCompleted, this ), + iRegistrationCallBack( RegistrationTimerExpired, this ), + iInvitationResponseCallBack( InvitationResponseTimerExpired, this ) + { + iAsyncBrakeEntry.Set( iAsyncBrakeCallBack ); + iRegistrationEntry.Set( iRegistrationCallBack ); + iInvitationResponseEntry.Set( iInvitationResponseCallBack ); + } + +// ----------------------------------------------------------------------------- +// +// ----------------------------------------------------------------------------- +// +void CMusEngMceOutSession::ConstructL() + { + MUS_LOG( "mus: [ENGINE] -> CMusEngMceOutSession::ConstructL()" ) + + CMusEngMceSession::ConstructL(); + TInt sipProfileId; + TInt error = KErrNone; + error = ( RProperty::Get( NMusSessionApi::KCategoryUid, + NMusSessionApi::KSipProfileId, sipProfileId ) ); + if ( error != KErrNone ) + { + sipProfileId = KErrNone; + error = KErrNone; + } + iSipProfileHandler->CreateProfileL( sipProfileId ); + iVideoCodecList = NULL; + TBuf buffer; + error = ( RProperty::Get( NMusSessionApi::KCategoryUid, + NMusSessionApi::KVideoCodecs, buffer ) ); + if ( error == KErrNone && buffer.Length() ) + { + iVideoCodecList = + CnvUtfConverter::ConvertFromUnicodeToUtf8L( buffer ); + } + + iDeltaTimer = CDeltaTimer::NewL( CActive::EPriorityStandard ); + + /* Read the contact name set by availability plugin */ + error = RProperty::Get( NMusSessionApi::KCategoryUid, + NMusSessionApi::KContactName, + buffer ); + iRemoteDisplayName = ( error == KErrNone && buffer.Length() ) + ? buffer.AllocL() : KNullDesC().AllocL(); + + MUS_LOG( "mus: [ENGINE] <- CMusEngMceOutSession::ConstructL()" ) + } // ----------------------------------------------------------------------------- // @@ -83,105 +134,77 @@ CMusEngMceOutSession::~CMusEngMceOutSession() { MUS_LOG( "mus: [ENGINE] -> CMusEngMceOutSession::~CMusEngMceOutSession()" ) - + + if ( iAddressQueried && iRecipient ) + { + TRAP_IGNORE( SaveContactL( *iRecipient ) ) + } + + delete iDeltaTimer; delete iRecipient; delete iVideoCodecList; - + delete iRemoteSipAddressProposal; + delete iRemoteDisplayName; MUS_LOG( "mus: [ENGINE] <- CMusEngMceOutSession::~CMusEngMceOutSession()" ) } +// ----------------------------------------------------------------------------- +// From MLcSession +// ----------------------------------------------------------------------------- +// +void CMusEngMceOutSession::EstablishLcSessionL() + { + MUS_LOG( "mus: [ENGINE] -> CMusEngMceOutSession::EstablishLcSessionL()") + + iAddressQueried = EFalse; + if ( LcUiProvider() && !IsBackgroundStartup() ) + { + LcUiProvider()->HandleForegroundStatus( ETrue ); + } + TRAPD( err, DoInviteL() ); + + // If address is in wrong format, Manual Address Entry Dialog is displayed + if ( ( err == KErrArgument ) && DoSyncRetryL() ) + { + err = KErrNone; // Doing retry + } + + User::LeaveIfError( err ); + + MUS_LOG( "mus: [ENGINE] <- CMusEngMceOutSession::EstablishLcSessionL") + } + +// ----------------------------------------------------------------------------- +// From MLcSession +// ----------------------------------------------------------------------------- +// +void CMusEngMceOutSession::TerminateLcSessionL() + { + MUS_LOG( "mus: [ENGINE] -> CMusEngMceOutSession::TerminateLcSessionL" ) + + __ASSERT_ALWAYS( iSession, User::Leave( KErrNotReady ) ); + + if( iSession->State() == CMceSession::EOffering ) + { + static_cast< CMceOutSession* >( iSession )->CancelL(); + } + else + { + iSession->TerminateL(); + } + + MUS_LOG( "mus: [ENGINE] <- CMusEngMceOutSession::TerminateLcSessionL" ) + } // ----------------------------------------------------------------------------- // // ----------------------------------------------------------------------------- // -EXPORT_C void CMusEngMceOutSession::InviteL( const TDesC& aRecipient ) +void CMusEngMceOutSession::AddDisplayL( CMceMediaStream& aStream ) { - MUS_LOG( "mus: [ENGINE] -> CMusEngMceOutSession::InviteL()") - - if ( iSession ) - { - MUS_ENG_LOG_SESSION_STATE( *iSession ) - - if ( iSession->State() == CMceSession::EIdle || - iSession->State() == CMceSession::ETerminated ) - { - // This is the case when last invite has ended up to an error, - // last sharing has ended normally, or construction of the session - // stucture has not been completed. Delete old session and try to - // continue normally. - delete iSession; - iSession = NULL; - MUS_LOG( "mus: [ENGINE] Existing session deleted") - } - else - { - // Session is already ongoing. Leave. - User::Leave( KErrAlreadyExists ); - } - - } - - MUS_LOG_TDESC( "mus: [ENGINE] CMusEngMceOutSession::InviteL() recipient=", - aRecipient ) - - // delete possibly existing recipient - delete iRecipient; - iRecipient = NULL; - - TMusEngUriParser parser( aRecipient ); - parser.ParseUriL(); - iRecipient = parser.GetUri8L(); - - CreateMceSessionStructureL(); - - EstablishSessionL(); - - MUS_LOG( "mus: [ENGINE] <- CMusEngMceOutSession::InviteL()") + MusEngMceUtils::AddDisplayL( aStream, *iManager, Rect() ); } - -// ----------------------------------------------------------------------------- -// -// ----------------------------------------------------------------------------- -// -EXPORT_C void CMusEngMceOutSession::CancelInviteL() - { - MUS_LOG( "mus: [ENGINE] -> CMusEngMceOutSession::CancelInviteL()" ) - - __ASSERT_ALWAYS( iSession, User::Leave( KErrNotReady ) ); - - MUS_ENG_LOG_SESSION_STATE( *iSession ) - - if( iSession->State() == CMceSession::EOffering ) - { - MUS_LOG( "mus: [ENGINE] CMceOutSession->CancelL()" ) - static_cast( iSession )->CancelL(); - } - - MUS_LOG( "mus: [ENGINE] <- CMusEngMceOutSession::CancelInviteL()" ) - } - - -// ----------------------------------------------------------------------------- -// -// ----------------------------------------------------------------------------- -// -EXPORT_C void CMusEngMceOutSession::SetSupportedVideoCodecListL( - const TDesC& aVideoCodecs ) - { - MUS_LOG_TDESC( "mus: [ENGINE] -> CMusEngMceOutSession::SetSupportedVideoCodecListL: ", - aVideoCodecs ) - - HBufC8* newVideoCodecList = - CnvUtfConverter::ConvertFromUnicodeToUtf8L( aVideoCodecs ); - delete iVideoCodecList; - iVideoCodecList = newVideoCodecList; - - MUS_LOG( "mus: [ENGINE] <- CMusEngMceOutSession::SetSupportedVideoCodecListL" ) - } - - // ----------------------------------------------------------------------------- // Calls MCE function EstablishL with feature tag in Accept-Contact header. // Adjusts stream and codec values. @@ -214,18 +237,13 @@ CleanupStack::PopAndDestroy( headInText ); } - /* Add the privacy header if cs call privacy setting is switched on */ - if ( iPrivate && iPrivateNumber ) - { - AddPrivacyHeaderL( *headers ); - } + static_cast( iSession )->EstablishL( 0, headers ); CleanupStack::Pop( headers ); MUS_LOG( "mus: [ENGINE] <- CMusEngMceOutSession::EstablishSessionL()" ) } - // ----------------------------------------------------------------------------- // Handle MCE session termination. Called by MCE observer function of the // base class. @@ -238,41 +256,18 @@ switch ( aStatusCode ) { - - case KMusEngSipReasonCodeBadRequest : - { - iOutSessionObserver.SessionBadRequest(); - break; - } - case KMusEngSipReasonCodeUnauthorized : - { - iOutSessionObserver.SessionUnauthorized(); - break; - } - case KMusEngSipReasonCodePaymentRequired : - { - iOutSessionObserver.SessionPaymentRequired(); - break; - } - case KMusEngSipReasonCodeRecipientNotFound : - //lint -fallthrough - case KMusEngSipReasonCode478NotAbleToProcessURI: + case KMusEngSipReasonCodeRecipientNotFound : //lint -fallthrough case KMusEngSipReasonCode479NotAbleToProcessURI: //lint -fallthrough case KMusEngSipReasonCodeUnsupportedUriScheme : { - iOutSessionObserver.SessionRecipientNotFound(); - break; - } - case KMusEngSipReasonCodeProxyAuthenticationRequired : - { - iOutSessionObserver.SessionProxyAuthenticationRequired(); + InitRecipientNotFoundHandling(); break; } case KMusEngSipReasonCodeRequestTimeout : { - iOutSessionObserver.SessionRequestTimeOut(); + InformObserverAboutSessionFailure( MLcSession::ENoAnswer ); break; } case KMusEngSipReasonCodeUnsupportedMediaType : @@ -281,7 +276,7 @@ //lint -fallthrough case KMusEngSipReasonCodeNotAcceptable: { - iOutSessionObserver.SessionUnsupportedMediaType(); + InformObserverAboutSessionFailure( MLcSession::ESessionRejected ); break; } case KMusEngSipReasonCodeBusyHere : @@ -289,27 +284,30 @@ // Operator variant uses 486 to rejection instead of 603 if ( iOperatorVariant ) { - iOutSessionObserver.SessionRejected(); + InformObserverAboutSessionFailure( + MLcSession::ESessionRejected ); } else { - iOutSessionObserver.SessionBusyHere(); + InformObserverAboutSessionFailure( + MLcSession::ERecipientBusy ); } break; } case KMusEngSipReasonCodeRequestCancelled : { - iOutSessionObserver.SessionRequestCancelled(); + InformObserverAboutSessionFailure( MLcSession::ESessionCancelled ); break; } case KMusEngSipReasonCodeDecline : { - iOutSessionObserver.SessionRejected(); + InformObserverAboutSessionFailure( MLcSession::ESessionRejected ); break; } case KMusEngSipReasonCodeTemporarilyNotAvailable : { - iOutSessionObserver.SessionTemporarilyNotAvailable(); + InformObserverAboutSessionFailure( + MLcSession::ERecipientTemporarilyNotAvailable ); break; } default: @@ -324,16 +322,16 @@ MUS_LOG( "mus: [ENGINE] <- CMusEngMceOutSession::HandleTermination()" ) } - // ----------------------------------------------------------------------------- // Sets payload type and calls overridden base class version // ----------------------------------------------------------------------------- // -void CMusEngMceOutSession::AdjustVideoCodecL( CMceVideoCodec& aVideoCodec ) +void CMusEngMceOutSession::AdjustVideoCodecL( CMceVideoCodec& aVideoCodec, + TMceSourceType aSourceType ) { MUS_LOG( "mus: [ENGINE] -> CMusEngMceOutSession::AdjustVideoCodecL()" ) - CMusEngMceSession::AdjustVideoCodecL( aVideoCodec ); + CMusEngMceSession::AdjustVideoCodecL( aVideoCodec, aSourceType ); if ( aVideoCodec.SdpName() == KMceSDPNameH263() || aVideoCodec.SdpName() == KMceSDPNameH2632000() ) @@ -354,7 +352,6 @@ MUS_LOG( "mus: [ENGINE] <- CMusEngMceOutSession::AdjustVideoCodecL()" ) } - // ----------------------------------------------------------------------------- // Sets payload type and calls overridden base class version // ----------------------------------------------------------------------------- @@ -368,71 +365,64 @@ User::LeaveIfError( aAudioCodec.SetPayloadType( KMusEngPayloadTypeAudio ) ); MUS_LOG( "mus: [ENGINE] <- CMusEngMceOutSession::AdjustAudioCodecL()" ) - } - - -// ----------------------------------------------------------------------------- -// -// ----------------------------------------------------------------------------- -// -CMusEngMceOutSession::CMusEngMceOutSession( - const TRect& aRect, - MMusEngSessionObserver& aSessionObserver, - MMusEngOutSessionObserver& aOutSessionObserver ) - : CMusEngMceSession( aRect, aSessionObserver ), - iOutSessionObserver( aOutSessionObserver ) - { - } - + } // ----------------------------------------------------------------------------- // // ----------------------------------------------------------------------------- // -void CMusEngMceOutSession::ConstructL( TUint aSipProfileId ) +void CMusEngMceOutSession::ProfileRegistered() { - MUS_LOG( "mus: [ENGINE] -> CMusEngMceOutSession::ConstructL()" ) - - CMusEngMceSession::ConstructL(); - iSipProfileHandler->CreateProfileL( aSipProfileId ); + MUS_LOG( "mus: [ENGINE] -> CMusEngMceOutSession::ProfileRegistered()" ) - // Check if feature specific behavior is expected - iPrivate = ( MultimediaSharingSettings::PrivacySetting()); + if ( iRegistrationPending ) + { + iDeltaTimer->Remove( iRegistrationEntry ); + iRegistrationPending = EFalse; + - NMusSessionInformationApi::TMusClirSetting clir; - // Ignore RProperty::Get return value.Incase of error it should behave default. - RProperty::Get( NMusSessionInformationApi::KCategoryUid, - NMusSessionInformationApi::KMusClirSetting, - reinterpret_cast( clir ) ); - iPrivateNumber = ( clir == NMusSessionInformationApi::ESendOwnNumber )? EFalse: ETrue; - - MUS_LOG( "mus: [ENGINE] <- CMusEngMceOutSession::ConstructL()" ) + HBufC* resolvedRecipient = NULL; + TRAPD( error, resolvedRecipient = RemoteAddressL() ) + if ( error != KErrNone ) + { + InformObserverAboutSessionFailure( error ); + } + else + { + TRAP( error, DoInviteL( *resolvedRecipient ) ) + delete resolvedRecipient; + if ( error != KErrNone ) + { + InformObserverAboutSessionFailure( error ); + } + } + } + + MUS_LOG( "mus: [ENGINE] <- CMusEngMceOutSession::ProfileRegistered()" ) } - // ----------------------------------------------------------------------------- // // ----------------------------------------------------------------------------- // -void CMusEngMceOutSession::CreateMceSessionStructureL() +TBool CMusEngMceOutSession::IsH264Supported() const + { + return ( iVideoCodecList && iVideoCodecList->FindF( KMceSDPNameH264() ) >= 0 ); + } + +// ----------------------------------------------------------------------------- +// +// ----------------------------------------------------------------------------- +// +void CMusEngMceOutSession::CreateMceSessionStructureL( TBool aForceSdpBandwidth ) { MUS_LOG( "mus: [ENGINE] -> CMusEngMceOutSession::CreateMceSessionStructureL()" ) - CSIPProfile* profile = iSipProfileHandler->Profile(); + CSIPProfile* profile = iSipProfileHandler->Profile(); __ASSERT_ALWAYS( profile != NULL, User::Leave( KErrNotReady ) ); // Create session - if ( iPrivate && iPrivateNumber ) - { - HBufC8* originator = KMusAnonymousHeader().AllocLC(); - iSession = CMceOutSession::NewL( *iManager, *profile, *iRecipient, originator ); - CleanupStack::Pop(); - } - else - { - iSession = CMceOutSession::NewL( *iManager, *profile, *iRecipient ); - } - + iSession = CMceOutSession::NewL( *iManager, *profile, *iRecipient ); // Remove QoS-lines if needed if ( profile->Type().iSIPProfileClass == @@ -445,7 +435,7 @@ MUS_LOG( "mus: [ENGINE] Usage of preconditions denied" ) } - SetSessionSdpLinesL( *iSession ); + SetSessionSdpLinesL( *iSession, aForceSdpBandwidth ); // Create bundle for local streams @@ -461,11 +451,11 @@ CMceVideoStream* videoOut = MusEngMceUtils::GetVideoOutStreamL( *iSession ); - SetMediaSdpLinesL( *videoOut ); + SetMediaSdpLinesL( *videoOut, aForceSdpBandwidth ); streamForDisplay->SetSourceL( videoOut->Source() ); - MusEngMceUtils::AddDisplayL( *streamForDisplay, *iManager, Rect() ); + AddDisplayL( *streamForDisplay ); iSession->AddStreamL( streamForDisplay ); CleanupStack::Pop( streamForDisplay ); @@ -485,22 +475,386 @@ MUS_LOG( "mus: [ENGINE] <- CMusEngMceOutSession::CreateMceSessionStructureL()" ) } +// ----------------------------------------------------------------------------- +// +// ----------------------------------------------------------------------------- +// +void CMusEngMceOutSession::DoInviteL( const TDesC& aRecipient ) + { + MUS_LOG_TDESC( "mus: [ENGINE] -> CMusEngMceOutSession::DoInviteL(): ", + aRecipient ) + + HBufC* resolvedRecipient = NULL; + if ( aRecipient.Length() > 0 ) + { + resolvedRecipient = aRecipient.AllocLC(); + } + else + { + resolvedRecipient = ResolveRecipientLC(); + } + + // delete possibly existing recipient + delete iRecipient; + iRecipient = NULL; + + TMusEngUriParser parser( *resolvedRecipient ); + parser.ParseUriL(); + iRecipient = parser.GetUri8L(); + + /* Set the display name to recipient address if displayname is empty */ + if ( !iRemoteDisplayName || iRemoteDisplayName->Length() == 0 ) + { + HBufC* tmp = parser.GetUri16L( ETrue ); + delete iRemoteDisplayName; + iRemoteDisplayName = tmp; + } + + CleanupStack::PopAndDestroy( resolvedRecipient ); + + if ( iSession ) + { + MUS_ENG_LOG_SESSION_STATE( *iSession ) + + if ( iSession->State() == CMceSession::EIdle || + iSession->State() == CMceSession::ETerminated ) + { + // This is the case when last invite has ended up to an error, + // last sharing has ended normally, or construction of the session + // stucture has not been completed. Delete old session and try to + // continue normally. + delete iSession; + iSession = NULL; + MUS_LOG( "mus: [ENGINE] Existing session deleted") + } + else + { + // Session is already ongoing. Leave. + User::Leave( KErrAlreadyExists ); + } + } + + const TUint KMusEngOneMinuteTimeout = 60000000; + if ( iSipProfileHandler->IsRegistered() ) + { + CreateMceSessionStructureL(); + EstablishSessionL(); + // Start one minute expiration timer + TTimeIntervalMicroSeconds32 interval( KMusEngOneMinuteTimeout ); + iDeltaTimer->Remove( iInvitationResponseEntry ); + iDeltaTimer->Queue( interval, iInvitationResponseEntry ); + } + else + { + iRegistrationPending = ETrue; + // Start one minute expiration timer + TTimeIntervalMicroSeconds32 interval( KMusEngOneMinuteTimeout ); + iDeltaTimer->Remove( iRegistrationEntry ); + iDeltaTimer->Queue( interval, iRegistrationEntry ); + } + + MUS_LOG( "mus: [ENGINE] <- CMusEngMceOutSession::DoInviteL()" ) + } // ----------------------------------------------------------------------------- -// Add Privacy header if own phone number/id should not be sent to remote party +// +// ----------------------------------------------------------------------------- +// +HBufC* CMusEngMceOutSession::ResolveRecipientLC() + { + MUS_LOG( "mus: [ENGINE] -> CMusEngMceOutSession::ResolveRecipientLC()" ) + + HBufC* resolvedRecipient = NULL; + TRAPD( err, + resolvedRecipient = + ReadDescPropertyL( NMusSessionApi::KRemoteSipAddress ) ); + if ( err != KErrNone ) + { + __ASSERT_ALWAYS( err != KErrNoMemory, User::Leave( KErrNoMemory ) ); + resolvedRecipient = KNullDesC().AllocL(); + } + CleanupStack::PushL( resolvedRecipient ); + + delete iRemoteSipAddressProposal; + iRemoteSipAddressProposal = NULL; + TRAP( err, + iRemoteSipAddressProposal = + ReadDescPropertyL( NMusSessionApi::KRemoteSipAddressProposal ) ); + if ( err != KErrNone ) + { + __ASSERT_ALWAYS( err != KErrNoMemory, User::Leave( KErrNoMemory ) ); + iRemoteSipAddressProposal = KNullDesC().AllocL(); + } + + if ( resolvedRecipient->Length() > 0 ) + { + if ( resolvedRecipient->Find( KMusEngCommaSymbol ) != KErrNotFound ) + { + // Split the addresses using KMusCommaSymbol as a separator + CDesCArray* addresses = + new( ELeave )CDesCArrayFlat( KMusEngSipAddressesMaxAmount ); + CleanupStack::PushL( addresses ); + SplitL( *resolvedRecipient, KMusEngCommaSymbol, addresses ); + + // Show List Query Dialog + CleanupStack::Pop( addresses ); + CleanupStack::PopAndDestroy( resolvedRecipient ); + CleanupStack::PushL( addresses ); + resolvedRecipient = HBufC::NewLC( KMusEngSipAddressMaxLength ); + TPtr ptrRetryAddr( resolvedRecipient->Des() ); + if ( !LcUiProviderL().SelectRecipient( *addresses, ptrRetryAddr ) ) + { + // Address not selected from provided list + User::Leave( KErrNotFound ); + } + CleanupStack::Pop( resolvedRecipient ); + CleanupStack::PopAndDestroy( addresses ); + CleanupStack::PushL( resolvedRecipient ); + } + } + else + { + __ASSERT_ALWAYS( ++iTriedInvitations < 2, User::Leave( KErrNotFound ) ); + + CleanupStack::PopAndDestroy( resolvedRecipient ); + resolvedRecipient = NULL; + resolvedRecipient = HBufC::NewLC( KMusEngSipAddressMaxLength ); + __ASSERT_ALWAYS( + iRemoteSipAddressProposal->Length() < KMusEngSipAddressMaxLength, + User::Leave( KErrOverflow ) ); + resolvedRecipient->Des().Copy( *iRemoteSipAddressProposal ); + TPtr ptrRetryAddr( resolvedRecipient->Des() ); + InputRecipientL( ptrRetryAddr ); + iAddressQueried = ETrue; + } + + MUS_LOG( "mus: [ENGINE] -> CMusEngMceOutSession::ResolveRecipientLC()" ) + + return resolvedRecipient; + } + +// ----------------------------------------------------------------------------- +// +// ----------------------------------------------------------------------------- +// +TInt CMusEngMceOutSession::AsyncBrakeCompleted( TAny* aPtr ) + { + if ( aPtr ) + { + reinterpret_cast( aPtr )->HandleRecipientNotFound(); + } + return KErrNone; + } + +// ----------------------------------------------------------------------------- +// +// ----------------------------------------------------------------------------- +// +TInt CMusEngMceOutSession::RegistrationTimerExpired( TAny* aPtr ) + { + if ( aPtr ) + { + CMusEngMceOutSession* session = + reinterpret_cast< CMusEngMceOutSession* >( aPtr ); + session->InformObserverAboutSessionFailure( KErrGeneral ); + } + return KErrNone; + } + +// ----------------------------------------------------------------------------- +// // ----------------------------------------------------------------------------- // -void CMusEngMceOutSession::AddPrivacyHeaderL( CDesC8Array& aHeaders ) +TInt CMusEngMceOutSession::InvitationResponseTimerExpired( TAny* aPtr ) + { + if ( aPtr ) + { + CMusEngMceOutSession* session = + reinterpret_cast< CMusEngMceOutSession* >( aPtr ); + if ( !session->IgnoreErrorNote() ) + { + session->InformObserverAboutSessionFailure( MLcSession::ENoAnswer ); + } + } + return KErrNone; + } + +// ----------------------------------------------------------------------------- +// +// ----------------------------------------------------------------------------- +// +TBool CMusEngMceOutSession::IgnoreErrorNote() + { + TBool ignore = ETrue; + if ( iSession && + ( iSession->State() == CMceSession::EOffering || + iSession->State() == CMceSession::EProceeding ) ) + { + ignore = EFalse; + } + return ignore; + } + +// ----------------------------------------------------------------------------- +// +// ----------------------------------------------------------------------------- +// +void CMusEngMceOutSession::InitRecipientNotFoundHandling() + { + MUS_LOG( "mus: [ENGINE] -> CMusEngMceOutSession::InitRecipientNotFoundHandling()" ) + + iDeltaTimer->Remove( iAsyncBrakeEntry ); + const TUint KMusEngAsyncBrakeTimeout = 1; + TTimeIntervalMicroSeconds32 interval( KMusEngAsyncBrakeTimeout ); + iDeltaTimer->Queue( interval, iAsyncBrakeEntry ); + + MUS_LOG( "mus: [ENGINE] <- CMusEngMceOutSession::InitRecipientNotFoundHandling()" ) + } + +// ----------------------------------------------------------------------------- +// +// ----------------------------------------------------------------------------- +// +void CMusEngMceOutSession::HandleRecipientNotFound() + { + MUS_LOG( "mus: [ENGINE] -> CMusEngMceOutSession::HandleRecipientNotFound()" ) + + TInt err( KErrNotFound ); + + TBool retry( EFalse ); + TRAP( err, retry = DoSyncRetryL() ); + + if ( err != KErrNone || !retry ) + { + InformObserverAboutSessionFailure( MLcSession::ERecipientNotFound ); + } + + MUS_LOG( "mus: [ENGINE] <- CMusEngMceOutSession::HandleRecipientNotFound()" ) + } + +// ----------------------------------------------------------------------------- +// +// ----------------------------------------------------------------------------- +// +TBool CMusEngMceOutSession::DoSyncRetryL() { - MUS_LOG( "mus: [ENGINE] -> AddPrivacyHeaderL()" ) - _LIT8( KMusPrivacyHeaderValue, "id" ); - CSIPExtensionHeader* header = CSIPExtensionHeader::NewLC( - KMusPrivacyHeader, KMusPrivacyHeaderValue ); - HBufC8* headInText = header->ToTextL(); - MUS_LOG_TDESC8( " mus: [ENGINE] Privacy header : ", headInText->Des() ); - CleanupStack::PopAndDestroy( header ); - CleanupStack::PushL( headInText ); - aHeaders.AppendL( *headInText ); - CleanupStack::PopAndDestroy( headInText ); - MUS_LOG( "mus: [ENGINE] <- AddPrivacyHeaderL()" ) + __ASSERT_ALWAYS( iRemoteSipAddressProposal, User::Leave( KErrNotFound ) ); + __ASSERT_ALWAYS( + iRemoteSipAddressProposal->Length() < KMusEngSipAddressMaxLength, + User::Leave( KErrOverflow ) ); + + TBool retry( EFalse ); + + if ( ++iTriedInvitations < 2 ) + { + TBuf retryAddress; + retryAddress.Copy( *iRemoteSipAddressProposal ); + InputRecipientL( retryAddress ); + DoInviteL( retryAddress ); + + retry = ETrue; + iAddressQueried = ETrue; + } + return retry; + } + +// ----------------------------------------------------------------------------- +// +// ----------------------------------------------------------------------------- +// +void CMusEngMceOutSession::SplitL( const TDesC& aDes, + const TDesC& aChar, + CDesCArray* aArray ) + { + TInt charPos( 0 ); + TPtrC ptr( aDes ); + TBool found = EFalse; + while( ( charPos = ptr.Find( aChar ) ) > 0 ) + { + found = ETrue; + TPtrC str = ptr.Left( charPos ); + aArray->AppendL( str ); + ptr.Set( ptr.Right( ptr.Length() - str.Length() - 1 ) ); + } + if ( found && ptr.Length() > 0 ) + { + aArray->AppendL( ptr ); + } } + +// ----------------------------------------------------------------------------- +// +// ----------------------------------------------------------------------------- +// +HBufC* CMusEngMceOutSession::ReadDescPropertyL( TUint aKey ) + { + MUS_LOG1( "mus: [ENGINE] -> CMusEngMceOutSession::ReadDescPropertyL: aKey: [%d]", + aKey ); + + TBuf buffer; + + User::LeaveIfError( RProperty::Get( NMusSessionApi::KCategoryUid, + aKey, + buffer ) ); + HBufC* desc = buffer.AllocL(); + MUS_LOG_TDESC( "mus: [ENGINE] <- CMusEngMceOutSession::ReadDescPropertyL: val: ", + (*desc) ); + return desc; + } + +// ----------------------------------------------------------------------------- +// +// ----------------------------------------------------------------------------- +// +HBufC* CMusEngMceOutSession::RemoteAddressL() const + { + MUS_LOG( "mus: [ENGINE] -> CMusEngMceOutSession::RemoteAddressL()" ) + + __ASSERT_ALWAYS( iRecipient, User::Leave( KErrNotReady ) ); + + HBufC* remoteAddr = HBufC::NewLC( iRecipient->Length() ); + TPtr ptrRemoteAddr( remoteAddr->Des() ); + User::LeaveIfError( + CnvUtfConverter::ConvertToUnicodeFromUtf8( + ptrRemoteAddr, *iRecipient ) ); + + MUS_LOG( "mus: [ENGINE] <- CMusEngMceOutSession::RemoteAddressL()" ) + + CleanupStack::Pop( remoteAddr ); + return remoteAddr; + } + +// ----------------------------------------------------------------------------- +// From MLcSession, Should return the displayname of the remote terminal +// If found in phone book than contactname else user entered sip address +// ----------------------------------------------------------------------------- +// +const TDesC& CMusEngMceOutSession::RemoteDisplayName() + { + if ( !iRemoteDisplayName ) + { + return KNullDesC; + } + return *iRemoteDisplayName; + } + +// ----------------------------------------------------------------------------- +// Query to the user for sip address of the remote party. +// If the user entered a new sip address then reset the displayname +// to user entered sip address. +// ----------------------------------------------------------------------------- +// +void CMusEngMceOutSession::InputRecipientL( TDes& aRecipientAddress ) + { + if ( !LcUiProviderL().InputRecipient( aRecipientAddress ) ) + { + User::Leave( KErrCancel ); + } + /* displayname is no longer valid since user entered a new sip address + * and displayname will be set to sip address when invitation sent. + */ + delete iRemoteDisplayName; + iRemoteDisplayName = NULL; + } + +// End of file