diff -r 000000000000 -r 1bce908db942 natfw/natfwclient/src/natfwsession.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/natfw/natfwclient/src/natfwsession.cpp Tue Feb 02 01:04:58 2010 +0200 @@ -0,0 +1,834 @@ +/* +* Copyright (c) 2007 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: +* +*/ + + + + +#include +#include "natfwpluginapi.h" +#include "mnatfwconnectivityobserver.h" +#include "natfwcandidatepair.h" +#include "natfwcandidate.h" +#include "natfwsession.h" +#include "natfwstream.h" +#include "mnatfwregistrationcontroller.h" +#include +#include "natfwclientlogs.h" +#include "cncmconnectionmultiplexer.h" +#include "cnatfwasynccallback.h" + +const TUint KSendingActivationsNeeded = 2; + +const TUint KReceivingActivationsNeeded = 2; + +// ======== MEMBER FUNCTIONS ======== + +// --------------------------------------------------------------------------- +// CNATFWSession::CNATFWSession +// --------------------------------------------------------------------------- +// +CNATFWSession::CNATFWSession( CNcmConnectionMultiplexer& aMultiplexer, + MNATFWRegistrationController& aController, + CNatFwAsyncCallback& aAsyncCallback, + TUint32 aIapId ) + : + iIapId( aIapId ), + iController( aController ), + iMultiplexer( aMultiplexer ), + iAsyncCallback( aAsyncCallback ), + iServerConnectionState( EConnectionUnspecified ) + { + } + + +// --------------------------------------------------------------------------- +// CNATFWSession::ConstructL +// --------------------------------------------------------------------------- +// +void CNATFWSession::ConstructL( const TDesC8& aDomain ) + { + iDomain = aDomain.AllocL(); + TUint startPort( 0 ); + TUint endPort( 0 ); + + iNatSettings = CNATFWNatSettingsApi::NewL( aDomain ); + + iNatSettings->GetPortArea( startPort, endPort ); + + iSessionId = iMultiplexer.CreateSessionL( iIapId, startPort, endPort ); + } + + +// --------------------------------------------------------------------------- +// CNATFWSession::NewL +// --------------------------------------------------------------------------- +// +CNATFWSession* CNATFWSession::NewL( CNcmConnectionMultiplexer& aMultiplexer, + MNATFWRegistrationController& aController, + CNatFwAsyncCallback& aAsyncCallback, + const TDesC8& aDomain, + TUint32 aIapId ) + { + CNATFWSession* self = + CNATFWSession::NewLC( aMultiplexer, aController, aAsyncCallback, + aDomain, aIapId ); + CleanupStack::Pop( self ); + return self; + } + + +// --------------------------------------------------------------------------- +// CNATFWSession::NewLC +// --------------------------------------------------------------------------- +// +CNATFWSession* CNATFWSession::NewLC( CNcmConnectionMultiplexer& aMultiplexer, + MNATFWRegistrationController& aController, + CNatFwAsyncCallback& aAsyncCallback, + const TDesC8& aDomain, + TUint32 aIapId ) + { + CNATFWSession* self = new ( ELeave ) CNATFWSession( aMultiplexer, + aController, aAsyncCallback, aIapId ); + CleanupStack::PushL( self ); + self->ConstructL( aDomain ); + return self; + } + + +// --------------------------------------------------------------------------- +// Destructor +// --------------------------------------------------------------------------- +// +CNATFWSession::~CNATFWSession() + { + iSendingStatusCounts.Close(); + iReceivingStatusCounts.Close(); + iFetchCandidateQueue.Close(); + iStreams.ResetAndDestroy(); + delete iDomain; + delete iPlugin; + delete iNatSettings; + + REComSession::FinalClose(); + + TInt err = KErrNone; + TRAP( err, iMultiplexer.RemoveSessionL( iSessionId ) ); + __NATFWCLIENT_INT1("CNATFWSession::~CNATFWSession, ERR:", err ) + } + + +// Non-derived function + +// --------------------------------------------------------------------------- +// CNATFWSession::LoadPluginL() +// --------------------------------------------------------------------------- +// +void CNATFWSession::LoadPluginL( const CDesC8Array& aPlugins, + TInt& aLoadedPluginInd ) + { + __NATFWCLIENT("CNATFWSession::LoadPluginL") + __ASSERT_ALWAYS( aPlugins.Count(), User::Leave( KErrArgument ) ); + + CNATFWPluginApi::TNATFWPluginInitParams + initParams( *this, iMultiplexer, *iDomain, iIapId ); + + TInt error( KErrNotFound ); + TInt count( aPlugins.Count() ); + TInt index( 0 ); + + delete iPlugin; + iPlugin = NULL; + + while ( !iPlugin && index < count ) + { + TRAP( error, iPlugin = + CNATFWPluginApi::NewL( aPlugins[index], initParams ) ); + index++; + } + + TInt ind( iStreams.Count() ); + while ( ind-- ) + { + iStreams[ind]->SetProtocolPlugin( iPlugin ); + } + + User::LeaveIfError( error ); + aLoadedPluginInd = --index; + + RSocketServ* socketServ = NULL; + TName connectionName; + + socketServ = iMultiplexer.GetSessionInfoL( iSessionId, connectionName ); + iPlugin->ConnectServerL( *socketServ, connectionName ); + iServerConnectionState = EConnectionInProgress; + + __NATFWCLIENT("CNATFWSession::LoadPluginL Exit") + } + + +// --------------------------------------------------------------------------- +// CNATFWSession::FetchCandidateL +// --------------------------------------------------------------------------- +// +void CNATFWSession::FetchCandidateL( TUint aStreamId, TUint aAddrFamily ) + { + __ASSERT_ALWAYS( iServerConnectionState != EConnectionUnspecified, + User::Leave( KErrNotReady ) ); + __ASSERT_ALWAYS( iServerConnectionState != EConnectionFailed, + User::Leave( KErrNotReady ) ); + + if ( iServerConnectionState == EConnectionConnected ) + { + StreamByIdL( aStreamId )->FetchCandidateL( aAddrFamily ); + } + else + { + TFetchingData data( aStreamId, 0, 0, aAddrFamily, EFalse ); + iFetchCandidateQueue.InsertL( data, 0 ); + } + } + + +// --------------------------------------------------------------------------- +// CNATFWSession::FetchCandidatesL +// --------------------------------------------------------------------------- +// +void CNATFWSession::FetchCandidatesL( TUint aStreamId, TUint aCollectionId, + TUint aComponentId, TUint aAddrFamily ) + { + __ASSERT_ALWAYS( iServerConnectionState != EConnectionUnspecified, + User::Leave( KErrNotReady ) ); + __ASSERT_ALWAYS( iServerConnectionState != EConnectionFailed, + User::Leave( KErrNotReady ) ); + + if ( iServerConnectionState == EConnectionConnected ) + { + StreamByIdL( aStreamId )->FetchCandidatesL( + aCollectionId, aComponentId, aAddrFamily ); + } + else + { + TFetchingData data( aStreamId, aCollectionId, + aComponentId, aAddrFamily, ETrue ); + + iFetchCandidateQueue.InsertL( data, 0 ); + } + } + +// --------------------------------------------------------------------------- +// CNATFWSession::SessionId +// --------------------------------------------------------------------------- +// +TUint CNATFWSession::SessionId() const + { + __NATFWCLIENT("CNATFWSession::SessionId") + + return iSessionId; + } + + +// --------------------------------------------------------------------------- +// CNATFWSession::CreateStreamL +// --------------------------------------------------------------------------- +// +TUint CNATFWSession::CreateStreamL( + TUint aProtocol, TInt aQoS ) + { + __NATFWCLIENT("CNATFWSession::CreateStreamL") + + CNATFWStream* stream = CNATFWStream::NewL( iController, iMultiplexer, + iAsyncCallback, *this, aProtocol, aQoS ); + CleanupStack::PushL( stream ); + + iStreams.AppendL( stream ); + stream->SetProtocolPlugin( iPlugin ); + + CleanupStack::Pop( stream ); + return stream->StreamId(); + } + + +// --------------------------------------------------------------------------- +// CNATFWSession::SetRoleL +// --------------------------------------------------------------------------- +// +void CNATFWSession::SetRoleL( TNATFWIceRole aRole ) + { + __NATFWCLIENT("CNATFWSession::SetRoleL") + + iPlugin->SetRoleL( aRole ); + } + + +// --------------------------------------------------------------------------- +// CNATFWSession::PerformConnectivityChecksL +// --------------------------------------------------------------------------- +// +void CNATFWSession::PerformConnectivityChecksL( + RPointerArray& aRemoteCandidates ) + { + __NATFWCLIENT("CNATFWSession::PerformConnectivityChecksL") + + iPlugin->PerformConnectivityChecksL( aRemoteCandidates ); + } + + +// --------------------------------------------------------------------------- +// CNATFWSession::UpdateIceProcessingL +// --------------------------------------------------------------------------- +// +void CNATFWSession::UpdateIceProcessingL( + RPointerArray& aPeerSelectedPairs ) + { + iPlugin->UpdateIceProcessingL( aPeerSelectedPairs ); + } + + +// --------------------------------------------------------------------------- +// CNATFWSession::UpdateIceProcessingL +// --------------------------------------------------------------------------- +// +void CNATFWSession::UpdateIceProcessingL( + RPointerArray& aRemoteCands ) + { + iPlugin->UpdateIceProcessingL( aRemoteCands ); + } + + +// --------------------------------------------------------------------------- +// CNATFWSession::CloseStream +// --------------------------------------------------------------------------- +// +void CNATFWSession::CloseStreamL( TUint aStreamId ) + { + __NATFWCLIENT("CNATFWSession::CloseStreamL") + + CNATFWStream* stream = StreamByIdL( aStreamId ); + iStreams.Remove( iStreams.FindL( stream ) ); + delete stream; + } + + +// --------------------------------------------------------------------------- +// CNATFWSession::StreamById +// --------------------------------------------------------------------------- +// +CNATFWStream* CNATFWSession::StreamById( TUint aStreamId ) + { + __NATFWCLIENT("CNATFWSession::StreamById") + + TInt ind( iStreams.Count() ); + + while ( ind-- ) + { + if ( iStreams[ind]->StreamId() == aStreamId ) + { + return iStreams[ind]; + } + } + + return NULL; + } + + +// --------------------------------------------------------------------------- +// CNATFWSession::StreamByIdL +// --------------------------------------------------------------------------- +// +CNATFWStream* CNATFWSession::StreamByIdL( TUint aStreamId ) + { + __NATFWCLIENT("CNATFWSession::StreamByIdL") + + CNATFWStream* stream = StreamById( aStreamId ); + if ( !stream ) + { + User::Leave( KErrNotFound ); + } + + return stream; + } + + +// --------------------------------------------------------------------------- +// From class MNATFWPluginObserver. +// CNATFWSession::Error +// --------------------------------------------------------------------------- +// +void CNATFWSession::Error( const CNATFWPluginApi& /*aPlugin*/, + TUint aStreamId, TInt aErrorCode ) + { + __NATFWCLIENT("CNATFWSession::Error") + + DoNotify( aStreamId, MNATFWConnectivityObserver::EGeneralError, + aErrorCode, NULL ); + } + + +// --------------------------------------------------------------------------- +// From class MNATFWPluginObserver. +// CNATFWSession::Notify +// --------------------------------------------------------------------------- +// +void CNATFWSession::Notify( const CNATFWPluginApi& /*aPlugin*/, + TUint aStreamId, TNATFWPluginEvent aEvent, TInt aErrCode ) + { + __NATFWCLIENT("CNATFWSession::Notify") + + // Activation notify must be waited from both plugin + // and mediastream before notifying NATFW client + + switch ( aEvent ) + { + case MNATFWPluginObserver::EServerConnected: + { + __NATFWCLIENT_INT1( + "CNATFWSession::Notify EServerConnected, ERR:", aErrCode ) + + if ( KErrNone != aErrCode ) + { + iServerConnectionState = EConnectionFailed; + } + else + { + iServerConnectionState = EConnectionConnected; + } + HandleQueuedItems(); + } + break; + + case MNATFWPluginObserver::ESendingActivated: + { + __NATFWCLIENT_INT1( + "CNATFWSession::Notify ESendingActivated, ERR:", aErrCode ) + + TInt index = iSendingStatusCounts.Count() - 1; + TInt foundStreamInd( KErrNotFound ); + + while ( 0 <= index && KErrNotFound == foundStreamInd ) + { + if ( aStreamId == iSendingStatusCounts[index].iStreamId ) + { + foundStreamInd = index; + + if ( KErrNone != aErrCode ) + { + iSendingStatusCounts[foundStreamInd].iErrorOccurred + = ETrue; + } + + iSendingStatusCounts[foundStreamInd].iActivatedCount++; + } + + index--; + } + + if ( KErrNotFound != foundStreamInd ) + { + if ( KSendingActivationsNeeded == + iSendingStatusCounts[foundStreamInd].iActivatedCount ) + { + // The second notify for current stream's sending + // activation has occurred so NATFW Stream can be + // notified + CNATFWStream* stream = StreamById( aStreamId ); + if ( stream ) + { + if ( iSendingStatusCounts[foundStreamInd]. + iErrorOccurred ) + { + // Reset the error occurred flag + iSendingStatusCounts[foundStreamInd].iErrorOccurred + = EFalse; + // Do notification with error code + stream->Notify( iSessionId, aStreamId, + MNcmConnectionMultiplexerObserver:: + ESendingActivated, KErrGeneral ); + } + else + { + stream->Notify( iSessionId, aStreamId, + MNcmConnectionMultiplexerObserver:: + ESendingActivated, KErrNone ); + } + } + } + } + else + { + // The first notify for stream's sending activation has + // occurred so store stream's status data in array + TStatusCounter sendingActivated; + sendingActivated.iActivatedCount++; + sendingActivated.iStreamId = aStreamId; + + if ( KErrNone != aErrCode ) + { + sendingActivated.iErrorOccurred = ETrue; + } + + iSendingStatusCounts.Append( sendingActivated ); + } + } + break; + + case MNATFWPluginObserver::ESendingDeactivated: + { + __NATFWCLIENT_INT1( + "CNATFWSession::Notify ESendingDeactivated, ERR:", aErrCode ) + + TInt index = iSendingStatusCounts.Count() - 1; + TInt foundStreamInd( KErrNotFound ); + + while ( 0 <= index && KErrNotFound == foundStreamInd ) + { + if ( aStreamId == iSendingStatusCounts[index].iStreamId && + iSendingStatusCounts[index].iActivatedCount != 0 ) + { + foundStreamInd = index; + + if ( aErrCode != KErrNone ) + { + iSendingStatusCounts[foundStreamInd].iErrorOccurred + = ETrue; + } + + iSendingStatusCounts[foundStreamInd].iActivatedCount--; + } + + index--; + } + + if ( KErrNotFound != foundStreamInd ) + { + if ( 0 == iSendingStatusCounts[foundStreamInd]. + iActivatedCount ) + { + CNATFWStream* stream = StreamById( aStreamId ); + if ( stream ) + { + if ( iSendingStatusCounts[foundStreamInd]. + iErrorOccurred ) + { + // Reset the error occurred flag + iSendingStatusCounts[foundStreamInd].iErrorOccurred + = EFalse; + // Do notification with error code + stream->Notify( iSessionId, aStreamId, + MNcmConnectionMultiplexerObserver:: + ESendingDeactivated, KErrGeneral ); + } + else + { + stream->Notify( iSessionId, aStreamId, + MNcmConnectionMultiplexerObserver:: + ESendingDeactivated, KErrNone ); + } + } + } + } + } + break; + + case MNATFWPluginObserver::EReceivingActivated: + { + __NATFWCLIENT_INT1( + "CNATFWSession::Notify EReceivingActivated, ERR:", aErrCode ) + + TInt index = iReceivingStatusCounts.Count() - 1; + TInt foundStreamInd( KErrNotFound ); + + while ( 0 <= index && KErrNotFound == foundStreamInd ) + { + if ( aStreamId == iReceivingStatusCounts[index].iStreamId ) + { + foundStreamInd = index; + + if ( KErrNone != aErrCode ) + { + iReceivingStatusCounts[foundStreamInd].iErrorOccurred + = ETrue; + } + + iReceivingStatusCounts[foundStreamInd].iActivatedCount++; + } + + index--; + } + + if ( KErrNotFound != foundStreamInd ) + { + if ( KReceivingActivationsNeeded == + iReceivingStatusCounts[foundStreamInd].iActivatedCount ) + { + // The second notify for current stream's receiving + // activation has occurred so NATFW Stream can be + // notified + CNATFWStream* stream = StreamById( aStreamId ); + if ( stream ) + { + if ( iReceivingStatusCounts[foundStreamInd]. + iErrorOccurred ) + { + // Reset the error occurred flag + iReceivingStatusCounts[foundStreamInd].iErrorOccurred + = EFalse; + // Do notification with error code + stream->Notify( iSessionId, aStreamId, + MNcmConnectionMultiplexerObserver:: + EReceivingActivated, KErrGeneral ); + } + else + { + stream->Notify( iSessionId, aStreamId, + MNcmConnectionMultiplexerObserver:: + EReceivingActivated, KErrNone ); + } + } + } + } + else + { + // The first notify for stream's receiving activation has + // occurred so store stream's status data in array + TStatusCounter receivingActivated; + receivingActivated.iActivatedCount++; + receivingActivated.iStreamId = aStreamId; + + if ( KErrNone != aErrCode ) + { + receivingActivated.iErrorOccurred = ETrue; + } + + iReceivingStatusCounts.Append( receivingActivated ); + } + } + break; + + case MNATFWPluginObserver::EReceivingDeactivated: + { + __NATFWCLIENT_INT1( + "CNATFWSession::Notify EReceivingDeactivated, ERR:", aErrCode ) + + TInt index = iReceivingStatusCounts.Count() - 1; + TInt foundStreamInd( KErrNotFound ); + + while ( 0 <= index && KErrNotFound == foundStreamInd ) + { + if ( aStreamId == iReceivingStatusCounts[index].iStreamId && + iReceivingStatusCounts[index].iActivatedCount != 0 ) + { + foundStreamInd = index; + + if ( aErrCode != KErrNone ) + { + iReceivingStatusCounts[foundStreamInd].iErrorOccurred + = ETrue; + } + + iReceivingStatusCounts[foundStreamInd].iActivatedCount--; + } + + index--; + } + + if ( KErrNotFound != foundStreamInd ) + { + if ( 0 == iReceivingStatusCounts[foundStreamInd]. + iActivatedCount ) + { + CNATFWStream* stream = StreamById( aStreamId ); + if ( stream ) + { + if ( iReceivingStatusCounts[foundStreamInd]. + iErrorOccurred ) + { + // Reset the error occurred flag + iReceivingStatusCounts[foundStreamInd].iErrorOccurred + = EFalse; + // Do notification with error code + stream->Notify( iSessionId, aStreamId, + MNcmConnectionMultiplexerObserver:: + EReceivingDeactivated, KErrGeneral ); + } + else + { + stream->Notify( iSessionId, aStreamId, + MNcmConnectionMultiplexerObserver:: + EReceivingDeactivated, KErrNone ); + } + } + } + } + } + break; + + case MNATFWPluginObserver::EFetchingCompleted: + { + __NATFWCLIENT_INT1( + "CNATFWSession::Notify EFetchingCompleted, ERR:", aErrCode ) + + DoNotify( aStreamId, MNATFWConnectivityObserver::EFetchingCompleted, + aErrCode, NULL ); + } + break; + + case MNATFWPluginObserver::EConnChecksCompleted: + { + __NATFWCLIENT_INT1( + "CNATFWSession::Notify EConnChecksCompleted, ERR:", aErrCode ) + + DoNotify( aStreamId, MNATFWConnectivityObserver::EConnChecksCompleted, + aErrCode, NULL ); + } + break; + + default: + { + __NATFWCLIENT("CNATFWSession::Notify DEFAULT") + ASSERT( EFalse ); + } + break; + } + + __NATFWCLIENT("CNATFWSession::Notify Exit") + } + + +// --------------------------------------------------------------------------- +// From class MNATFWPluginObserver. +// CNATFWSession::NewCandidatePairFound +// --------------------------------------------------------------------------- +// +void CNATFWSession::NewCandidatePairFound( + const CNATFWPluginApi& /*aPlugin*/, + CNATFWCandidatePair* aCandidatePair ) + { + __NATFWCLIENT("CNATFWSession::NewCandidatePairFound") + + if ( aCandidatePair ) + { + const_cast( + aCandidatePair->RemoteCandidate() ).SetSessionId( iSessionId ); + const_cast( + aCandidatePair->LocalCandidate() ).SetSessionId( iSessionId ); + DoNotify( aCandidatePair->LocalCandidate().StreamId(), + MNATFWConnectivityObserver::ECandidatePairFound, + KErrNone, aCandidatePair ); + } + else + { + __NATFWCLIENT("CNATFWSession::NewCandidatePairFound - NULL POINTER") + } + } + + +// --------------------------------------------------------------------------- +// From class MNATFWPluginObserver. +// CNATFWSession::NewLocalCandidateFound +// --------------------------------------------------------------------------- +// +void CNATFWSession::NewLocalCandidateFound( + const CNATFWPluginApi& /*aPlugin*/, + CNATFWCandidate* aCandidate ) + { + __NATFWCLIENT("CNATFWSession::NewLocalCandidateFound") + + if ( aCandidate ) + { + aCandidate->SetSessionId( iSessionId ); + DoNotify( aCandidate->StreamId(), + MNATFWConnectivityObserver::ELocalCandidateFound, + KErrNone, aCandidate ); + } + else + { + __NATFWCLIENT("CNATFWSession::NewLocalCandidateFound - NULL POINTER") + } + } + + +// --------------------------------------------------------------------------- +// CNATFWSession::HandleQueuedItems +// --------------------------------------------------------------------------- +// +void CNATFWSession::HandleQueuedItems() + { + __NATFWCLIENT("CNATFWSession::HandleQueuedItems - ENTRY") + + TInt index( iFetchCandidateQueue.Count() - 1 ); + TUint streamId( 0 ); + TUint collectionId( 0 ); + TUint componentId( 0 ); + TUint addrFamily( KAFUnspec ); + TBool iceSpecific( EFalse ); + + while ( 0 <= index ) + { + streamId = iFetchCandidateQueue[index].iStreamId; + collectionId = iFetchCandidateQueue[index].iCollectionId; + componentId = iFetchCandidateQueue[index].iComponentId; + addrFamily = iFetchCandidateQueue[index].iAddrFamily; + iceSpecific = iFetchCandidateQueue[index].iICESpecific; + iFetchCandidateQueue.Remove( index ); + + CNATFWStream* str( NULL ); + str = StreamById( streamId ); + + TInt error( KErrNone ); + if ( str ) + { + if( iceSpecific ) + { + TRAP( error, + str->FetchCandidatesL( + collectionId, componentId, addrFamily ) ); + } + else + { + TRAP( error, str->FetchCandidateL( addrFamily ) ); + } + } + + if ( KErrNone != error ) + { + DoNotify( streamId, MNATFWConnectivityObserver::EFetchingCompleted, + error, NULL ); + } + + --index; + } + + __NATFWCLIENT("CNATFWSession::HandleQueuedItems - EXIT") + } + + +// --------------------------------------------------------------------------- +// CNATFWSession::DoNotify +// --------------------------------------------------------------------------- +// +void CNATFWSession::DoNotify( TUint aStreamId, + MNATFWConnectivityObserver::TNATFWConnectivityEvent aEvent, + TInt aErrCode, + TAny* aEventData ) + { + CNatFwCallbackInfo::TFunction func = + static_cast( aEvent ); + + TRAP_IGNORE( iAsyncCallback.MakeCallbackL( iController, func, + iSessionId, aStreamId, aErrCode, aEventData ) ) + + }