--- 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 <lcsessionobserver.h>
+#include <lcuiprovider.h>
#include <mcestreambundle.h>
#include <mcemediastream.h>
#include <mceoutsession.h>
@@ -40,20 +41,14 @@
#include <mcedisplaysink.h>
#include <mcevideocodec.h>
#include <mceaudiocodec.h>
+#include <e32property.h>
#include <sipprofile.h>
#include <sipextensionheader.h>
#include <sipaddress.h>
#include <uri8.h>
-#include <e32property.h>
-
-
-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<RProperty::KMaxPropertySize> 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<CMceOutSession*>( 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<CMceOutSession*>( 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<TInt&>( 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<CMusEngMceOutSession*>( 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<KMusEngSipAddressMaxLength> 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<RProperty::KMaxPropertySize> 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