--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/natfw/natfwstunplugin/src/natfwstunconnectionhandler.cpp Tue Feb 02 01:04:58 2010 +0200
@@ -0,0 +1,1243 @@
+/*
+* 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: Creates connection to Connection Multiplexer and STUN client.
+* Handles connection specific issues and receives notifications
+* through implemented observers. Sends notifications to NAT FW
+* Client through NAT Protocol Plug-in observer.
+*
+*/
+
+
+
+
+#include "mncmconnectionmultiplexer.h"
+#include <cnatfwsettingsapi.h>
+#include <mnatfwserversettings.h>
+#include "natfwcandidate.h"
+#include "mnatfwpluginobserver.h"
+#include "natfwstunbinding.h"
+#include "natfwstunclient.h"
+#include <mnatfwstunsettings.h>
+
+#include "natfwstunconnectionhandler.h"
+#include "natfwstunpluginlogs.h"
+#include "natfwstunrefreshtimer.h"
+#include "natfwstunstreamdata.h"
+#include "cstunasynccallback.h"
+#include "cnatfwstunserversettings.h"
+
+const TUint KDefaultRefreshInterval = 28000000;
+const TUint KDefaultStunSrvPort = 3478;
+const TUint KMicrosecFactor = 1000000;
+const TUint KTryAlternate = 300;
+const TInt KClientSpecificError = -11000;
+
+// ======== MEMBER FUNCTIONS ========
+
+// ---------------------------------------------------------------------------
+// C++ default constructor
+// ---------------------------------------------------------------------------
+//
+CNATFWStunConnectionHandler::CNATFWStunConnectionHandler(
+ const CNATFWPluginApi& aStunPlugin )
+ :
+ iStunRefreshInterval( KDefaultRefreshInterval ),
+ iStunPlugin( aStunPlugin )
+ {
+ }
+
+
+// ---------------------------------------------------------------------------
+// Symbian constructor
+// ---------------------------------------------------------------------------
+//
+void CNATFWStunConnectionHandler::ConstructL(
+ MNATFWPluginObserver& aPluginObserver )
+ {
+ iTimerServ = CDeltaTimer::NewL( CActive::EPriorityStandard );
+ iStunRefreshTimer = CNATFWStunRefreshTimer::NewL( *this );
+ iAsyncCallback = CStunAsyncCallback::NewL( iStunPlugin, aPluginObserver );
+ }
+
+
+// ---------------------------------------------------------------------------
+// Symbian constructor
+// ---------------------------------------------------------------------------
+//
+CNATFWStunConnectionHandler* CNATFWStunConnectionHandler::NewL(
+ const CNATFWPluginApi& aStunPlugin,
+ MNATFWPluginObserver& aPluginObserver )
+ {
+ __STUNPLUGIN( "CNATFWStunConnectionHandler::NewL" )
+ CNATFWStunConnectionHandler* self = CNATFWStunConnectionHandler::NewLC(
+ aStunPlugin, aPluginObserver );
+ CleanupStack::Pop( self );
+ return self;
+ }
+
+
+// ---------------------------------------------------------------------------
+// Symbian constructor
+// ---------------------------------------------------------------------------
+//
+CNATFWStunConnectionHandler* CNATFWStunConnectionHandler::NewLC(
+ const CNATFWPluginApi& aStunPlugin,
+ MNATFWPluginObserver& aPluginObserver )
+ {
+ __STUNPLUGIN( "CNATFWStunConnectionHandler::NewLC" )
+ CNATFWStunConnectionHandler* self = new( ELeave )
+ CNATFWStunConnectionHandler( aStunPlugin );
+ CleanupStack::PushL( self );
+ self->ConstructL( aPluginObserver );
+ return self;
+ }
+
+
+// ---------------------------------------------------------------------------
+// Destructor
+// ---------------------------------------------------------------------------
+//
+CNATFWStunConnectionHandler::~CNATFWStunConnectionHandler()
+ {
+ __STUNPLUGIN(
+ "CNATFWStunConnectionHandler::~CNATFWStunConnectionHandler start" )
+
+ iServerList.ResetAndDestroy();
+
+ delete iDomain;
+ delete iNatSettings;
+ iStunSettings = NULL;
+ delete iStunRefreshTimer;
+
+ TInt count( iStreamArray.Count() );
+ for ( TInt index = count - 1; index >= 0; index-- )
+ {
+ DeleteStream( index, ETrue );
+ }
+
+ iStreamArray.Close();
+ delete iStunClient;
+ delete iTimerServ;
+ iConnection.Close();
+ iConnMux = NULL;
+ delete iAsyncCallback;
+
+ __STUNPLUGIN(
+ "CNATFWStunConnectionHandler::~CNATFWStunConnectionHandler end" )
+ }
+
+
+// ---------------------------------------------------------------------------
+// CNATFWStunConnectionHandler::PluginInitializeL
+// ---------------------------------------------------------------------------
+//
+void CNATFWStunConnectionHandler::PluginInitializeL(
+ TUint32 aIapId,
+ const TDesC8& aDomain,
+ MNcmConnectionMultiplexer& aMultiplexer )
+ {
+ __STUNPLUGIN( "CNATFWStunConnectionHandler::PluginInitializeL start" )
+
+ iConnMux = &aMultiplexer;
+ iDomain = aDomain.AllocL();
+ iNatSettings = CNATFWNatSettingsApi::NewL( *iDomain );
+
+ iStunSettings = &iNatSettings->StunSettingsL();
+
+ iNatSettings->RetrieveIapSettingsL( aIapId );
+
+ // Generates Server list
+ this->GenerateServerListL();
+
+ __STUNPLUGIN( "CNATFWStunConnectionHandler::PluginInitializeL end" )
+ }
+
+
+// ---------------------------------------------------------------------------
+// CNATFWStunConnectionHandler::ConnectServerL
+// ---------------------------------------------------------------------------
+//
+void CNATFWStunConnectionHandler::ConnectServerL(
+ const RSocketServ& aSocketServ,
+ const TName& aConnectionName )
+ {
+ __STUNPLUGIN( "CNATFWStunConnectionHandler::ConnectServerL start" )
+
+ iSocketServ = aSocketServ;
+ TName name( aConnectionName );
+ User::LeaveIfError( iConnection.Open( iSocketServ, name ) );
+
+ this->TryNextServerL();
+
+ // wait MNATFWStunClientObserver::STUNClientInitCompleted
+ __STUNPLUGIN( "CNATFWStunConnectionHandler::ConnectServerL end" )
+ }
+
+
+// ---------------------------------------------------------------------------
+// CNATFWStunConnectionHandler::FetchCandidateL
+// ---------------------------------------------------------------------------
+//
+void CNATFWStunConnectionHandler::FetchCandidateL( TUint aStreamId,
+ TUint aRtoValue, TUint aAddrFamily, const TInetAddr& aBaseAddr )
+ {
+ __STUNPLUGIN( "CNATFWStunConnectionHandler::FetchCandidateL start" )
+
+ __ASSERT_ALWAYS( iStunClient, User::Leave( KErrNotReady) );
+ __ASSERT_ALWAYS(
+ iStunClient->IsInitialized(), User::Leave( KErrNotReady) );
+
+ TUint connectionId( aBaseAddr.IsUnspecified() ?
+ iConnMux->CreateConnectionL( aStreamId, aAddrFamily ) :
+ iConnMux->CreateConnectionL( aStreamId, aBaseAddr ) );
+
+ TConnectionData connData;
+ connData.iConnectionId = connectionId;
+ connData.iStunSrvAddr.SetAddress( iStunClient->STUNServerAddrL().
+ Address() );
+ connData.iStunSrvAddr.SetPort( iStunClient->STUNServerAddrL().Port() );
+
+ TInt index( IndexByStreamId( aStreamId ) );
+
+ if ( KErrNotFound == index )
+ {
+ TUint32 iapID( 0 );
+ TInt qos( 0 );
+
+ // The stream is new for the plug-in
+ iConnMux->RegisterIncomingConnectionObserverL( aStreamId, *this );
+ iConnMux->RegisterConnectionObserverL( aStreamId, *this );
+
+ TStreamData streamData;
+ streamData.iStreamId = aStreamId;
+ iConnMux->GetStreamInfoL( aStreamId, iapID, qos,
+ streamData.iTransportProtocol );
+ streamData.iRtoValue = aRtoValue;
+ streamData.iConnArray.AppendL( connData );
+ CleanupClosePushL( streamData.iConnArray );
+ iStreamArray.AppendL( streamData );
+ CleanupStack::Pop( &streamData.iConnArray );
+ }
+ else
+ {
+ // Store new connection for the existing stream in array
+ iStreamArray[index].iConnArray.AppendL( connData );
+ }
+
+ // Accept data only from STUN server
+ iConnMux->SetAcceptedFromAddressL( aStreamId, connectionId,
+ connData.iStunSrvAddr );
+
+ // Set receiving and sending state active for the created connection
+ iConnMux->SetReceivingStateL( aStreamId, connectionId,
+ EStreamingStateActive );
+
+ iConnMux->SetSendingStateL( aStreamId, connectionId,
+ connData.iStunSrvAddr, EStreamingStateActive );
+ // wait MNcmConnectionObserver::ConnectionNotify
+
+ __STUNPLUGIN( "CNATFWStunConnectionHandler::FetchCandidateL end" )
+ }
+
+
+// ---------------------------------------------------------------------------
+// CNATFWStunConnectionHandler::GetConnectionIdL
+// ---------------------------------------------------------------------------
+//
+void CNATFWStunConnectionHandler::GetConnectionIdL(
+ const CNATFWCandidate& aLocalCandidate,
+ TUint aStreamId,
+ TUint& aConnectionId )
+ {
+ __STUNPLUGIN( "CNATFWStunConnectionHandler::GetConnectionIdL start" )
+
+ TInt streamInd( IndexByStreamId( aStreamId ) );
+ TInt connInd( KErrNotFound );
+ TBool connFound( EFalse );
+
+ if ( KErrNotFound != streamInd )
+ {
+ connInd = iStreamArray[streamInd].iConnArray.Count() - 1;
+ }
+
+ while ( KErrNotFound != streamInd && !connFound && ( 0 <= connInd ) )
+ {
+ TConnectionData* connection = ConnectionByIndex( streamInd, connInd );
+
+ if ( CNATFWCandidate::EServerReflexive == aLocalCandidate.Type() &&
+ MatchAddresses( aLocalCandidate.Base(), connection->
+ iLocalCandidate->Base() ) && MatchAddresses( aLocalCandidate.
+ TransportAddr(), connection->iLocalCandidate->TransportAddr() ) )
+ {
+ connFound = ETrue;
+ aConnectionId = connection->iConnectionId;
+ }
+
+ connInd--;
+ }
+
+ __ASSERT_ALWAYS( connFound, User::Leave( KErrNotFound ) );
+
+ __STUNPLUGIN( "CNATFWStunConnectionHandler::GetConnectionIdL end" )
+ }
+
+
+// ---------------------------------------------------------------------------
+// CNATFWStunConnectionHandler::StartStunRefresh
+// ---------------------------------------------------------------------------
+//
+void CNATFWStunConnectionHandler::StartStunRefresh()
+ {
+ __STUNPLUGIN( "CNATFWStunConnectionHandler::StartStunRefresh start" )
+
+ iStunRefreshStarted = EFalse;
+ iStunRefreshTimer->StartStunRefresh( iStunRefreshInterval );
+
+ if ( iStunRefreshTimer->IsRunning() )
+ {
+ iStunRefreshStarted = ETrue;
+ }
+
+ __STUNPLUGIN( "CNATFWStunConnectionHandler::StartStunRefresh end" )
+ }
+
+
+// ---------------------------------------------------------------------------
+// CNATFWStunConnectionHandler::CreateSTUNBindingL
+// ---------------------------------------------------------------------------
+//
+void CNATFWStunConnectionHandler::CreateSTUNBindingL( TUint aStreamId,
+ TUint aConnectionId )
+ {
+ __STUNPLUGIN( "CNATFWStunConnectionHandler::CreateSTUNBindingL" )
+
+ TInt streamInd( IndexByStreamId( aStreamId ) );
+ TConnectionData* connection( NULL );
+
+ if ( KErrNotFound != streamInd )
+ {
+ connection = ConnectionById( streamInd, aConnectionId );
+ }
+
+ if ( connection )
+ {
+ CSTUNBinding* stunBinding = CSTUNBinding::NewL( *iStunClient,
+ aStreamId,
+ aConnectionId );
+ CleanupStack::PushL( stunBinding );
+ connection->iStunBinding = stunBinding;
+
+ stunBinding->SendRequestL( connection->iStunSrvAddr, EFalse,
+ iStreamArray[streamInd].iRtoValue );
+
+ CleanupStack::Pop( stunBinding );
+ // wait MStunClientObserver::STUNBindingEventOccurredL
+ }
+ }
+
+
+// ---------------------------------------------------------------------------
+// CNATFWStunConnectionHandler::SetReceivingStateL
+// ---------------------------------------------------------------------------
+//
+void CNATFWStunConnectionHandler::SetReceivingStateL(
+ const CNATFWCandidate& aLocalCandidate,
+ TNATFWStreamingState aState )
+ {
+ __STUNPLUGIN( "CNATFWStunConnectionHandler::SetReceivingStateL start" )
+
+ TUint streamId( aLocalCandidate.StreamId() );
+ TUint connId( 0 );
+ TConnectionData* connection = NULL;
+ TRAPD( err, GetConnectionIdL( aLocalCandidate, streamId, connId ) );
+
+ if ( !err )
+ {
+ TInt streamInd( IndexByStreamId( streamId ) );
+ connection = ConnectionById( streamInd, connId );
+ }
+
+ if ( connection )
+ {
+ if ( EStreamingStateActive == aState )
+ {
+ if ( connection->iReceivingActivated )
+ {
+ iAsyncCallback->MakeCallbackL( TStunPluginCallbackInfo::
+ EActiveReceiving, streamId, KErrNone, NULL );
+ }
+ else
+ {
+ iConnMux->SetReceivingStateL( streamId, connId,
+ EStreamingStateActive );
+ }
+ }
+ else
+ {
+ if ( !connection->iReceivingActivated )
+ {
+ iAsyncCallback->MakeCallbackL( TStunPluginCallbackInfo::
+ EDeactiveReceiving, streamId, KErrNone, NULL );
+ }
+ else
+ {
+ iConnMux->SetReceivingStateL( streamId, connId,
+ EStreamingStatePassive );
+ }
+ }
+ }
+ else
+ {
+ if ( EStreamingStateActive == aState )
+ {
+ iAsyncCallback->MakeCallbackL( TStunPluginCallbackInfo::
+ EActiveReceiving, streamId, KErrNotFound, NULL );
+ }
+ else
+ {
+ iAsyncCallback->MakeCallbackL( TStunPluginCallbackInfo::
+ EDeactiveReceiving, streamId, KErrNotFound, NULL );
+ }
+ }
+
+ __STUNPLUGIN( "CNATFWStunConnectionHandler::SetReceivingStateL end" )
+ }
+
+
+// ---------------------------------------------------------------------------
+// CNATFWStunConnectionHandler::SetSendingStateL
+// ---------------------------------------------------------------------------
+//
+void CNATFWStunConnectionHandler::SetSendingStateL(
+ const CNATFWCandidate& aLocalCandidate,
+ TNATFWStreamingState aState,
+ const TInetAddr& aDestAddr )
+ {
+ __STUNPLUGIN( "CNATFWStunConnectionHandler::SetSendingStateL start" )
+
+ TUint streamId( aLocalCandidate.StreamId() );
+ TUint connId( 0 );
+ TConnectionData* connection = NULL;
+ TRAPD( err, GetConnectionIdL( aLocalCandidate, streamId, connId ) );
+
+ if ( !err )
+ {
+ TInt streamInd( IndexByStreamId( streamId ) );
+ connection = ConnectionById( streamInd, connId );
+ }
+
+ if ( connection )
+ {
+ // Client controls media connection, set address filtering
+ iConnMux->SetAcceptedFromAddressL( streamId, connId, aDestAddr );
+
+ if ( EStreamingStateActive == aState )
+ {
+ if ( connection->iSendingActivated && MatchAddresses(
+ connection->iDestAddr, aDestAddr ) )
+ {
+ iAsyncCallback->MakeCallbackL( TStunPluginCallbackInfo::
+ EActiveSending, streamId, KErrNone, NULL );
+ }
+ else
+ {
+ connection->iDestAddr.SetAddress( aDestAddr.Address() );
+ connection->iDestAddr.SetPort( aDestAddr.Port() );
+
+ iConnMux->SetSendingStateL( streamId, connId, aDestAddr,
+ EStreamingStateActive );
+ }
+ }
+ else
+ {
+ if ( !connection->iSendingActivated )
+ {
+ iAsyncCallback->MakeCallbackL( TStunPluginCallbackInfo::
+ EDeactiveSending, streamId, KErrNone, NULL );
+ }
+ else
+ {
+ iConnMux->SetSendingStateL( streamId, connId, aDestAddr,
+ EStreamingStatePassive );
+ }
+ }
+ }
+ else
+ {
+ if ( EStreamingStateActive == aState )
+ {
+ iAsyncCallback->MakeCallbackL( TStunPluginCallbackInfo::
+ EActiveSending, streamId, KErrNotFound, NULL );
+ }
+ else
+ {
+ iAsyncCallback->MakeCallbackL( TStunPluginCallbackInfo::
+ EDeactiveSending, streamId, KErrNotFound, NULL );
+ }
+ }
+
+ __STUNPLUGIN( "CNATFWStunConnectionHandler::SetSendingStateL end" )
+ }
+
+
+// ---------------------------------------------------------------------------
+// From base class MStunClientObserver.
+// CNATFWStunConnectionHandler::STUNClientInitCompleted
+// ---------------------------------------------------------------------------
+//
+void CNATFWStunConnectionHandler::STUNClientInitCompleted(
+ const CSTUNClient& /*aClient*/, TInt aCompletionCode )
+ {
+ __STUNPLUGIN_INT1( "CNATFWStunConnectionHandler::STUNClientInitCompleted \
+ start - Completion code:", aCompletionCode )
+
+ TUint streamId( 0 );
+
+ if ( KErrNone == aCompletionCode )
+ {
+ TRAP_IGNORE( iAsyncCallback->MakeCallbackL(
+ TStunPluginCallbackInfo::EConnectServer, streamId,
+ aCompletionCode, NULL ) )
+ }
+ else
+ {
+ TInt error( KErrNone );
+
+ TRAP( error, TryNextServerL() );
+
+ if ( KErrNone != error )
+ {
+ delete iStunClient;
+ iStunClient = NULL;
+
+ TRAP_IGNORE( iAsyncCallback->MakeCallbackL(
+ TStunPluginCallbackInfo::EConnectServer, streamId,
+ ( KClientSpecificError + aCompletionCode ), NULL ) )
+ }
+ }
+
+ __STUNPLUGIN(
+ "CNATFWStunConnectionHandler::STUNClientInitCompleted end" )
+ }
+
+
+// ---------------------------------------------------------------------------
+// From base class MStunClientObserver
+// CNATFWStunConnectionHandler::STUNBindingEventOccurredL
+// ---------------------------------------------------------------------------
+//
+void CNATFWStunConnectionHandler::STUNBindingEventOccurredL(
+ TSTUNBindingEvent aEvent,
+ const CBinding& aBinding )
+ {
+ __STUNPLUGIN(
+ "CNATFWStunConnectionHandler::STUNBindingEventOccurredL start" )
+
+ const CSTUNBinding& stunBinding =
+ static_cast<const CSTUNBinding&>( aBinding );
+ TUint streamId( stunBinding.StreamId() );
+ TUint connId( stunBinding.ConnectionId() );
+
+ TInt streamInd( IndexByStreamId( streamId ) );
+ TConnectionData* connection( NULL );
+
+ if ( KErrNotFound != streamInd )
+ {
+ connection = ConnectionById( streamInd, connId );
+ }
+
+ if ( connection )
+ {
+ switch ( aEvent )
+ {
+ case EPublicAddressResolved:
+ {
+ if ( !connection->iLocalCandidate )
+ {
+ if ( iStunRefreshTimer && !iStunRefreshStarted )
+ {
+ StartStunRefresh();
+ }
+
+ TInetAddr publicAddr;
+ publicAddr.SetAddress( stunBinding.PublicAddr().
+ Address() );
+ publicAddr.SetPort( stunBinding.PublicAddr().Port() );
+
+ __STUNPLUGIN_ADDRLOG( "CNATFWStunConnectionHandler::\
+ STUNBindingEventOccurredL Adress Resolved ADDRESS: ",
+ publicAddr )
+
+ CNATFWCandidate* newCandidate = CNATFWCandidate::NewL();
+ CleanupStack::PushL( newCandidate );
+
+ // Set candidate parameters
+ newCandidate->SetStreamId( streamId );
+ newCandidate->SetType(
+ CNATFWCandidate::EServerReflexive );
+ TInetAddr baseAddr = iConnMux->LocalIPAddressL(
+ streamId, connId );
+
+ newCandidate->SetBase( baseAddr );
+ newCandidate->SetTransportAddrL( publicAddr );
+ newCandidate->SetTransportProtocol(
+ iStreamArray[streamInd].iTransportProtocol );
+
+ CNATFWCandidate* copyCandidate = CNATFWCandidate::NewL(
+ *newCandidate );
+ connection->iLocalCandidate = copyCandidate;
+
+ iAsyncCallback->MakeCallbackL(
+ TStunPluginCallbackInfo::ELocalCandidateFound,
+ streamId, KErrNone, newCandidate );
+
+ iAsyncCallback->MakeCallbackL(
+ TStunPluginCallbackInfo::EFetchingEnd, streamId,
+ KErrNone, NULL );
+
+ CleanupStack::Pop( newCandidate );
+ }
+ }
+ break;
+
+ case ECredentialsRejected:
+ {
+ // STUN server rejected the credentials provided that were
+ // set with CSTUNClient::SetCredentialsL. Application
+ // should obtain valid credentials and then use
+ // CSTUNClient::SetCredentialsL.
+ iAsyncCallback->MakeCallbackL(
+ TStunPluginCallbackInfo::EFetchingEnd, streamId,
+ ( KClientSpecificError + KErrPermissionDenied ),
+ NULL );
+
+ // Remove failed entry from array
+ DeleteStream( streamInd, ETrue );
+ }
+ break;
+ }
+ }
+
+ __STUNPLUGIN(
+ "CNATFWStunConnectionHandler::STUNBindingEventOccurredL end" )
+ }
+
+
+// ---------------------------------------------------------------------------
+// From base class MStunClientObserver
+// CNATFWStunConnectionHandler::STUNBindingErrorOccurred
+// ---------------------------------------------------------------------------
+//
+void CNATFWStunConnectionHandler::STUNBindingErrorOccurred(
+ const CBinding& aBinding,
+ TInt aError )
+ {
+ __STUNPLUGIN(
+ "CNATFWStunConnectionHandler::STUNBindingErrorOccurred start" )
+
+ const CSTUNBinding& stunBinding =
+ static_cast<const CSTUNBinding&>( aBinding );
+ TUint streamId( stunBinding.StreamId() );
+ TUint connId( stunBinding.ConnectionId() );
+
+ TInt streamInd( IndexByStreamId( streamId ) );
+ TConnectionData* connection( NULL );
+
+ if ( KErrNotFound != streamInd )
+ {
+ connection = ConnectionById( streamInd, connId );
+ }
+
+ if ( connection )
+ {
+ if ( !connection->iLocalCandidate )
+ {
+ if ( KTryAlternate == aError )
+ {
+ __STUNPLUGIN( "CNATFWStunConnectionHandler::\
+ STUNBindingErrorOccurred KTryAlternate == aError" )
+
+ connection->iStunSrvAddr.SetAddress( stunBinding.
+ AlternateServerAddr().Address() );
+ connection->iStunSrvAddr.SetPort( stunBinding.
+ AlternateServerAddr().Port() );
+
+ delete connection->iStunBinding;
+ connection->iStunBinding = NULL;
+
+ TRAP_IGNORE( iConnMux->SetSendingStateL( streamId, connId,
+ connection->iStunSrvAddr, EStreamingStateActive ) )
+ // wait MNcmConnectionObserver::ConnectionNotify
+ }
+ else
+ {
+ // If error occurs when trying to fetch candidate
+ TInt errcode( KClientSpecificError + ( aError ) );
+ TRAP_IGNORE( iAsyncCallback->MakeCallbackL(
+ TStunPluginCallbackInfo::EFetchingEnd, streamId,
+ errcode, NULL ) )
+
+ // Remove failed entry from array
+ DeleteStream( streamInd, ETrue );
+ }
+ }
+ else
+ {
+ // Do nothing if error occurs when doing binding refresh
+ }
+ }
+
+ __STUNPLUGIN(
+ "CNATFWStunConnectionHandler::STUNBindingErrorOccurred end" )
+ }
+
+
+// ---------------------------------------------------------------------------
+// from base class MNcmIncomingConnectionObserver
+// CNATFWStunConnectionHandler::IncomingMessageL
+// ---------------------------------------------------------------------------
+//
+void CNATFWStunConnectionHandler::IncomingMessageL(
+ TUint aStreamId,
+ const TDesC8& aMessage,
+ const TInetAddr& /*aLocalAddr*/,
+#ifdef _DEBUG
+ const TInetAddr& aFromAddr,
+ const TInetAddr& aPeerRemoteAddr,
+#else
+ const TInetAddr& /*aFromAddr*/,
+ const TInetAddr& /*aPeerRemoteAddr*/,
+#endif
+ TBool& aConsumed )
+ {
+ __STUNPLUGIN_ADDRLOG(
+ "CNATFWStunConnectionHandler::IncomingMessageL FROMADDR", aFromAddr )
+ __STUNPLUGIN_ADDRLOG(
+ "CNATFWStunConnectionHandler::IncomingMessageL PEERADDR",
+ aPeerRemoteAddr )
+
+ TInetAddr peerAddrFromIndication( KAFUnspec );
+ HBufC8* indicationData( NULL );
+ TInt consumingBindingInd( KErrNotFound );
+
+ TInt streamInd( IndexByStreamId( aStreamId ) );
+ TInt connInd( KErrNotFound );
+
+ if ( KErrNotFound != streamInd )
+ {
+ connInd = iStreamArray[streamInd].iConnArray.Count() - 1;
+ }
+
+ // Offer message for every binding in the stream until consumed
+ while ( KErrNotFound != streamInd && KErrNotFound == consumingBindingInd
+ && ( 0 <= connInd ) )
+ {
+ __STUNPLUGIN( "CNATFWStunConnectionHandler::IncomingMessageL\
+ HandleDataL method to be called" )
+
+ TBool consumed( EFalse );
+ TConnectionData* connection = ConnectionByIndex( streamInd, connInd );
+
+ if ( connection->iStunBinding )
+ {
+ if ( indicationData )
+ {
+ connection->iStunBinding->HandleDataL( *indicationData,
+ consumed, peerAddrFromIndication );
+ }
+ else
+ {
+ indicationData = connection->iStunBinding->HandleDataL(
+ aMessage, consumed, peerAddrFromIndication );
+ }
+ }
+
+ if ( consumed )
+ {
+ consumingBindingInd = connInd;
+ aConsumed = ETrue;
+ }
+
+ connInd--;
+ }
+
+ delete indicationData;
+ }
+
+
+// ---------------------------------------------------------------------------
+// from base class MNcmConnectionObserver
+// CNATFWStunConnectionHandler::ConnectionNotify
+// ---------------------------------------------------------------------------
+//
+void CNATFWStunConnectionHandler::ConnectionNotify(
+ TUint aStreamId,
+ TUint aConnectionId,
+ TConnectionNotifyType aType,
+ TInt aError )
+ {
+ __STUNPLUGIN( "CNATFWStunConnectionHandler::ConnectionNotify start" )
+
+ TInt streamInd( IndexByStreamId( aStreamId ) );
+ TConnectionData* connection( NULL );
+
+ if ( KErrNotFound != streamInd )
+ {
+ connection = ConnectionById( streamInd, aConnectionId );
+ }
+
+ if ( connection )
+ {
+ if ( aError || EConnectionError == aType )
+ {
+ if ( !connection->iLocalCandidate )
+ {
+ // If error occurs when trying to fetch candidate
+ TInt errcode( KClientSpecificError + ( aError ) );
+ TRAP_IGNORE( iAsyncCallback->MakeCallbackL(
+ TStunPluginCallbackInfo::EFetchingEnd, aStreamId, errcode,
+ NULL ) )
+ }
+ else
+ {
+ TRAP_IGNORE( iAsyncCallback->MakeCallbackL(
+ TStunPluginCallbackInfo::EError, aStreamId, aError,
+ NULL ) )
+ }
+
+ // Remove failed entry from array
+ DeleteStream( streamInd, ETrue );
+ }
+ else
+ {
+ switch ( aType )
+ {
+ case ESendingActivated:
+ {
+ connection->iSendingActivated = ETrue;
+
+ if ( connection->iLocalCandidate )
+ {
+ TRAP_IGNORE( iAsyncCallback->MakeCallbackL(
+ TStunPluginCallbackInfo::EActiveSending,
+ aStreamId, KErrNone, NULL ) )
+ }
+ else
+ {
+ // Candidate fetching ongoing
+ if ( !connection->iStunBinding )
+ {
+ TRAP_IGNORE( CreateSTUNBindingL( aStreamId,
+ aConnectionId ) )
+ }
+ }
+ }
+ break;
+
+ case EReceivingActivated:
+ {
+ connection->iReceivingActivated = ETrue;
+
+ if ( connection->iLocalCandidate )
+ {
+ TRAP_IGNORE( iAsyncCallback->MakeCallbackL(
+ TStunPluginCallbackInfo::EActiveReceiving,
+ aStreamId, KErrNone, NULL ) )
+ }
+ }
+ break;
+
+ case ESendingDeactivated:
+ {
+ connection->iSendingActivated = EFalse;
+
+ if ( connection->iLocalCandidate )
+ {
+ TRAP_IGNORE( iAsyncCallback->MakeCallbackL(
+ TStunPluginCallbackInfo::EDeactiveSending,
+ aStreamId, KErrNone, NULL ) )
+ }
+ }
+ break;
+
+ case EReceivingDeactivated:
+ {
+ connection->iReceivingActivated = EFalse;
+
+ if ( connection->iLocalCandidate )
+ {
+ TRAP_IGNORE( iAsyncCallback->MakeCallbackL(
+ TStunPluginCallbackInfo::EDeactiveReceiving,
+ aStreamId, KErrNone, NULL ) )
+ }
+ }
+ break;
+
+ case EConnectionRemoved:
+ {
+ DeleteStream( streamInd, EFalse );
+ }
+ break;
+
+ case EFirstMediaPacketSent:
+ {
+ connection->iMediaSendingActivated = ETrue;
+ }
+ break;
+ }
+ }
+ }
+
+ __STUNPLUGIN( "CNATFWStunConnectionHandler::ConnectionNotify end" )
+ }
+
+
+// ---------------------------------------------------------------------------
+// from base class MNATFWRefreshObserver
+// CNATFWStunConnectionHandler::BindingRefreshL
+// ---------------------------------------------------------------------------
+//
+void CNATFWStunConnectionHandler::BindingRefreshL()
+ {
+ TInt streamCount( iStreamArray.Count() );
+
+ for ( TInt streamInd = 0; streamInd < streamCount; streamInd++ )
+ {
+ TInt connCount( iStreamArray[streamInd].iConnArray.Count() );
+
+ for ( TInt connInd = 0; connInd < connCount; connInd++ )
+ {
+ TConnectionData* connection = ConnectionByIndex( streamInd,
+ connInd );
+
+ if ( !connection->iMediaSendingActivated )
+ {
+ connection->iStunBinding->SendRequestL( connection->
+ iStunSrvAddr, EFalse, iStreamArray[streamInd].iRtoValue );
+ }
+ }
+ }
+ }
+
+
+// ---------------------------------------------------------------------------
+// CNATFWStunConnectionHandler::DeleteStream
+// ---------------------------------------------------------------------------
+//
+void CNATFWStunConnectionHandler::DeleteStream( TUint aStreamInd,
+ TBool aRemoveMuxConn )
+ {
+ __STUNPLUGIN( "CNATFWStunConnectionHandler::DeleteStream, start" )
+ ASSERT( aStreamInd < TUint( iStreamArray.Count() ) );
+
+ TRAP_IGNORE(
+ iConnMux->UnregisterIncomingConnectionObserverL(
+ iStreamArray[aStreamInd].iStreamId, *this ) )
+ TRAP_IGNORE(
+ iConnMux->UnregisterConnectionObserverL(
+ iStreamArray[aStreamInd].iStreamId, *this ) )
+
+ // Remove the stream's connections
+ TInt connIndex( iStreamArray[aStreamInd].iConnArray.Count() - 1 );
+
+ for ( TInt i( connIndex ); i >= 0; i-- )
+ {
+ TConnectionData* connection = ConnectionByIndex( aStreamInd, i );
+
+ if( connection->iStunBinding )
+ {
+ connection->iStunBinding->CancelRequest();
+
+ delete connection->iStunBinding;
+ connection->iStunBinding = NULL;
+ delete connection->iLocalCandidate;
+ connection->iLocalCandidate = NULL;
+ }
+
+ if ( aRemoveMuxConn )
+ {
+ TRAP_IGNORE( iConnMux->RemoveConnectionL(
+ iStreamArray[aStreamInd].iStreamId, connection->
+ iConnectionId ) )
+ }
+
+ iStreamArray[aStreamInd].iConnArray.Remove( i );
+ }
+
+ iStreamArray[aStreamInd].iConnArray.Close();
+ iStreamArray.Remove( aStreamInd );
+
+ __STUNPLUGIN( "CNATFWStunConnectionHandler::DeleteStream, end" )
+ }
+
+
+// ---------------------------------------------------------------------------
+// CNATFWStunConnectionHandler::IndexByStreamId
+// ---------------------------------------------------------------------------
+//
+TInt CNATFWStunConnectionHandler::IndexByStreamId( TUint aStreamId )
+ {
+ __STUNPLUGIN( "CNATFWStunConnectionHandler::IndexByStreamId" )
+
+ TInt index( iStreamArray.Count() - 1 );
+
+ while ( 0 <= index )
+ {
+ if ( aStreamId == iStreamArray[index].iStreamId )
+ {
+ return index;
+ }
+
+ index--;
+ }
+
+ return KErrNotFound;
+ }
+
+
+// ---------------------------------------------------------------------------
+// CNATFWStunConnectionHandler::GenerateServerListL
+// ---------------------------------------------------------------------------
+//
+void CNATFWStunConnectionHandler::GenerateServerListL()
+ {
+ __STUNPLUGIN( "CNATFWStunConnectionHandler::GenerateServerListL start" )
+
+ RPointerArray<MNATFWServerSettings> serverArray;
+ iStunSettings->GetStunServerArrayL( serverArray );
+
+ CleanupClosePushL( serverArray );
+ TInt count( serverArray.Count() );
+
+ HBufC8* serverAddress =
+ iStunSettings->LatestConnectedServerAddr().AllocLC();
+ TUint latestPort = iStunSettings->LatestConnectedServerPort();
+
+ // Add Latest connected STUN server
+ if ( serverAddress->Compare( KNullDesC8 ) )
+ {
+ __STUNPLUGIN( "CNATFWStunConnectionHandler::GenerateServerListL\
+ - Latest stun server added" )
+
+ CStunServerSettings* settings = CStunServerSettings::NewLC();
+ settings->SetAddressL( *serverAddress );
+ settings->SetPort( latestPort );
+
+ for ( TInt index( 0 ); index < count; index++ )
+ {
+ if ( *serverAddress == serverArray[index]->Address() &&
+ serverArray[index]->Username().Length() &&
+ serverArray[index]->Password().Length() )
+ {
+ settings->SetUsernameL( serverArray[index]->Username() );
+ settings->SetPasswordL( serverArray[index]->Password() );
+ break;
+ }
+ }
+
+ iServerList.AppendL( settings );
+ CleanupStack::Pop( settings );
+ }
+
+ CleanupStack::PopAndDestroy( serverAddress );
+
+ // Add provisioned servers
+ for ( TInt index( 0 ); index < count; index++ )
+ {
+ CStunServerSettings* settings = CStunServerSettings::NewLC();
+
+ settings->SetAddressL( serverArray[index]->Address() );
+ settings->SetPort( serverArray[index]->Port() );
+
+ if ( serverArray[index]->Username().Length() &&
+ serverArray[index]->Password().Length() )
+ {
+ settings->SetUsernameL( serverArray[index]->Username() );
+ settings->SetPasswordL( serverArray[index]->Password() );
+ }
+
+ if ( settings->Address().Compare( KNullDesC8 ) )
+ {
+ __STUNPLUGIN( "CNATFWStunConnectionHandler::GenerateServerListL\
+ - provisioned server added" )
+ iServerList.AppendL( settings );
+ }
+
+ CleanupStack::Pop( settings );
+ }
+
+ // Domain
+ CStunServerSettings* settings = CStunServerSettings::NewLC();
+ settings->SetAddressL( *iDomain );
+ settings->SetPort( ( latestPort ) ? latestPort : KDefaultStunSrvPort );
+
+ for ( TInt index( 0 ); index < count; index++ )
+ {
+ if ( *iDomain == serverArray[index]->Address() &&
+ serverArray[index]->Username().Length() &&
+ serverArray[index]->Password().Length() )
+ {
+ settings->SetUsernameL( serverArray[index]->Username() );
+ settings->SetPasswordL( serverArray[index]->Password() );
+ break;
+ }
+ }
+
+ iServerList.AppendL( settings );
+ CleanupStack::Pop( settings );
+
+ CleanupStack::PopAndDestroy( &serverArray );
+ __STUNPLUGIN( "CNATFWStunConnectionHandler::GenerateServerListL end" )
+ }
+
+
+// ---------------------------------------------------------------------------
+// CNATFWStunConnectionHandler::TryNextServerL
+// ---------------------------------------------------------------------------
+//
+void CNATFWStunConnectionHandler::TryNextServerL()
+ {
+ __STUNPLUGIN( "CNATFWStunConnectionHandler::TryNextServerL start" )
+
+ delete iStunClient;
+ iStunClient = NULL;
+
+ _LIT8( KZeroAddrIpv4_1, "0" );
+ _LIT8( KZeroAddrIpv4_2, "0.0" );
+ _LIT8( KZeroAddrIpv4_3, "0.0.0" );
+ _LIT8( KZeroAddrIpv4_4, "0.0.0.0" );
+ _LIT8( KZeroAddrIpv6, "::" );
+
+ if ( iServerIndex < iServerList.Count() )
+ {
+ TInt index( iServerIndex );
+ iServerIndex++;
+
+ if ( iServerList[index]->Address().Compare( KZeroAddrIpv4_1 ) == 0 ||
+ iServerList[index]->Address().Compare( KZeroAddrIpv4_2 ) == 0 ||
+ iServerList[index]->Address().Compare( KZeroAddrIpv4_3 ) == 0 ||
+ iServerList[index]->Address().Compare( KZeroAddrIpv4_4 ) == 0 ||
+ iServerList[index]->Address().Compare( KZeroAddrIpv6 ) == 0 )
+ {
+ __STUNPLUGIN("CNATFWStunConnectionHandler::TryNextServerL address\
+ '0.0.0.0' or '::' are not accepted, stop public IP resolving..")
+ User::Leave( KErrCouldNotConnect );
+ }
+
+ TInt refresh( iNatSettings->RefreshIntervalUdp() );
+ iStunRefreshInterval =
+ ( refresh ) ? ( refresh * KMicrosecFactor ) :
+ KDefaultRefreshInterval;
+
+ TInt retransmitInterval( iStunSettings->RetransmissionTimeout() );
+ TBool useSharedSecret( iNatSettings->UseSharedSecret() );
+
+ TBool useLongTerm( EFalse );
+
+ if ( useSharedSecret &&
+ iServerList[index]->Username() &&
+ iServerList[index]->Password() )
+ {
+ useLongTerm = ETrue;
+ }
+
+ TUint port = iServerList[index]->Port() ?
+ iServerList[index]->Port() : KDefaultStunSrvPort;
+
+ iStunClient = CSTUNClient::NewL( retransmitInterval,
+ iServerList[index]->Address(),
+ port,
+ KStun,
+ iSocketServ,
+ iConnection,
+ *iTimerServ,
+ *this,
+ useSharedSecret,
+ EFalse,
+ EFalse,
+ iConnMux );
+
+ if ( useLongTerm )
+ {
+ TRAP_IGNORE( iStunClient->SetCredentialsL( *iServerList[index]->
+ Username(), *iServerList[index]->Password() ) )
+ }
+ }
+ else
+ {
+ User::Leave( KErrNotFound );
+ }
+
+ __STUNPLUGIN( "CNATFWStunConnectionHandler::TryNextServerL end" )
+ }
+
+
+// ---------------------------------------------------------------------------
+// CNATFWStunConnectionHandler::ConnectionById
+// ---------------------------------------------------------------------------
+//
+TConnectionData* CNATFWStunConnectionHandler::ConnectionById(
+ TUint aStreamInd,
+ TUint aConnectionId )
+ {
+ __STUNPLUGIN( "CNATFWStunConnectionHandler::ConnectionById" )
+
+ TInt index( iStreamArray[aStreamInd].iConnArray.Count() - 1 );
+
+ while ( 0 <= index )
+ {
+ if ( aConnectionId == iStreamArray[aStreamInd].iConnArray[index].
+ iConnectionId )
+ {
+ return &iStreamArray[aStreamInd].iConnArray[index];
+ }
+
+ index--;
+ }
+
+ return NULL;
+ }
+
+
+// ---------------------------------------------------------------------------
+// CNATFWStunConnectionHandler::ConnectionByIndex
+// ---------------------------------------------------------------------------
+//
+TConnectionData* CNATFWStunConnectionHandler::ConnectionByIndex(
+ TUint aStreamInd,
+ TUint aConnectionInd )
+ {
+ __STUNPLUGIN( "CNATFWStunConnectionHandler::ConnectionByIndex" )
+
+ return &iStreamArray[aStreamInd].iConnArray[aConnectionInd];
+ }
+
+
+// ---------------------------------------------------------------------------
+// CNATFWStunConnectionHandler::MatchAddresses
+// ---------------------------------------------------------------------------
+//
+TBool CNATFWStunConnectionHandler::MatchAddresses( const TInetAddr& aAddr1,
+ const TInetAddr& aAddr2 ) const
+ {
+ // CmpAddr does not interpret IPv4 and IPv4 mapped/compatible addresses
+ // as same even if they represent same address. Thus extra testing is
+ // needed to handle that case.
+ TBool isMatch = ( aAddr1.CmpAddr( aAddr2 ) || ( aAddr1.Address() ==
+ aAddr2.Address() && aAddr1.Port() == aAddr2.Port() ) );
+
+ return isMatch;
+ }
+
+// End of file