/*
* 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 TURN 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 "natfwstunrelaybinding.h"
#include "natfwstunclient.h"
#include <mnatfwturnsettings.h>
#include "natfwturnconnectionhandler.h"
#include "natfwturnpluginlogs.h"
#include "natfwturnrefreshtimer.h"
#include "natfwturnstreamdata.h"
#include "natfwturnactivedestinationtimer.h"
#include "cturnasynccallback.h"
#include "cnatfwturnserversettings.h"
#include "natfwunsafmessage.h"
#include "natfwunsafmessagefactory.h"
#include "natfwunsafremoteaddressattribute.h"
#include "natfwunsafdataattribute.h"
#include "natfwunsaftcprelaypacket.h"
const TUint KDefaultStunSrvPort = 3478;
const TUint KDefaultRefreshInterval = 28000000;
const TUint KMicrosecFactor = 1000000;
const TUint32 KWaitTimeAfterReset = 5000000;
// transitioning time changed from 3000000=>0 to get ICE work
const TUint32 KDefaultSrvTransitioningTime = 0;
const TUint32 KRetryTimeAfter439 = 5000;
const TUint KNoBinding = 437;
const TUint KServerTransitioning = 439;
const TUint KTryAlternate = 300;
const TInt KClientSpecificError = -11000;
// ======== MEMBER FUNCTIONS ========
// ---------------------------------------------------------------------------
// C++ default constructor
// ---------------------------------------------------------------------------
//
CNATFWTurnConnectionHandler::CNATFWTurnConnectionHandler(
const CNATFWPluginApi& aTurnPlugin )
:
iTurnPlugin( aTurnPlugin )
{
}
// ---------------------------------------------------------------------------
// Symbian constructor
// ---------------------------------------------------------------------------
//
void CNATFWTurnConnectionHandler::ConstructL(
MNATFWPluginObserver& aPluginObserver )
{
iTimerServ = CDeltaTimer::NewL( CActive::EPriorityStandard );
iTurnRefreshTimer = CNATFWTurnRefreshTimer::NewL( *this );
iActiveDestinationTimer = CNATFWTurnActiveDestinationTimer::NewL( *this );
iAsyncCallback = CTurnAsyncCallback::NewL( iTurnPlugin, aPluginObserver );
}
// ---------------------------------------------------------------------------
// Symbian constructor
// ---------------------------------------------------------------------------
//
CNATFWTurnConnectionHandler* CNATFWTurnConnectionHandler::NewL(
const CNATFWPluginApi& aTurnPlugin,
MNATFWPluginObserver& aPluginObserver )
{
__TURNPLUGIN( "CNATFWTurnConnectionHandler::NewL" )
CNATFWTurnConnectionHandler* self = CNATFWTurnConnectionHandler::NewLC(
aTurnPlugin, aPluginObserver );
CleanupStack::Pop( self );
return self;
}
// ---------------------------------------------------------------------------
// Symbian constructor
// ---------------------------------------------------------------------------
//
CNATFWTurnConnectionHandler* CNATFWTurnConnectionHandler::NewLC(
const CNATFWPluginApi& aTurnPlugin,
MNATFWPluginObserver& aPluginObserver )
{
__TURNPLUGIN( "CNATFWTurnConnectionHandler::NewLC" )
CNATFWTurnConnectionHandler* self =
new( ELeave ) CNATFWTurnConnectionHandler( aTurnPlugin );
CleanupStack::PushL( self );
self->ConstructL( aPluginObserver );
return self;
}
// ---------------------------------------------------------------------------
// Destructor
// ---------------------------------------------------------------------------
//
CNATFWTurnConnectionHandler::~CNATFWTurnConnectionHandler()
{
__TURNPLUGIN(
"CNATFWTurnConnectionHandler::~CNATFWTurnConnectionHandler start" )
iServerList.ResetAndDestroy();
delete iDomain;
delete iNatSettings;
delete iTurnRefreshTimer;
delete iActiveDestinationTimer;
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;
__TURNPLUGIN(
"CNATFWTurnConnectionHandler::~CNATFWTurnConnectionHandler end" )
}
// ---------------------------------------------------------------------------
// CNATFWTurnConnectionHandler::PluginInitializeL
// ---------------------------------------------------------------------------
//
void CNATFWTurnConnectionHandler::PluginInitializeL(
TUint32 aIapId,
const TDesC8& aDomain,
MNcmConnectionMultiplexer& aMultiplexer )
{
__TURNPLUGIN( "CNATFWTurnConnectionHandler::PluginInitializeL start" )
iConnMux = &aMultiplexer;
delete iDomain;
iDomain = NULL;
iDomain = aDomain.AllocL();
delete iNatSettings;
iNatSettings = NULL;
iNatSettings = CNATFWNatSettingsApi::NewL( *iDomain );
iNatSettings->RetrieveIapSettingsL( aIapId );
iTurnSettings = &iNatSettings->TurnSettingsL();
// Generates Server list
this->GenerateServerListL();
__TURNPLUGIN( "CNATFWTurnConnectionHandler::PluginInitializeL end" )
}
// ---------------------------------------------------------------------------
// CNATFWTurnConnectionHandler::ConnectServerL
// ---------------------------------------------------------------------------
//
void CNATFWTurnConnectionHandler::ConnectServerL(
const RSocketServ& aSocketServ,
const TName& aConnectionName )
{
__TURNPLUGIN( "CNATFWTurnConnectionHandler::ConnectServerL start" )
iSocketServ = aSocketServ;
TName name( aConnectionName );
User::LeaveIfError( iConnection.Open( iSocketServ, name ) );
this->TryNextServerL();
// wait MNATFWStunClientObserver::STUNClientInitCompleted
__TURNPLUGIN( "CNATFWTurnConnectionHandler::ConnectServerL end" )
}
// ---------------------------------------------------------------------------
// CNATFWTurnConnectionHandler::FetchCandidateL
// ---------------------------------------------------------------------------
//
void CNATFWTurnConnectionHandler::FetchCandidateL( TUint aStreamId,
TUint aRtoValue, TUint aAddrFamily, const TInetAddr& aBaseAddr )
{
__TURNPLUGIN( "CNATFWTurnConnectionHandler::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.iServerAddr.SetAddress( iStunClient->STUNServerAddrL().
Address() );
connData.iServerAddr.SetPort( iStunClient->STUNServerAddrL().Port() );
connData.iLocalAddr = iConnMux->LocalIPAddressL( aStreamId,
connectionId );
TInt index( IndexByStreamId( aStreamId ) );
if ( KErrNotFound == index )
{
TUint32 iapID( 0 );
TInt qos( 0 );
// The stream is new for the plug-in
iConnMux->RegisterConnectionObserverL( aStreamId, *this );
iConnMux->RegisterIncomingConnectionObserverL( aStreamId, *this );
iConnMux->RegisterOutgoingConnectionObserverL( aStreamId, *this );
iConnMux->RegisterMessageObserverL( 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 TURN server
iConnMux->SetAcceptedFromAddressL( aStreamId, connectionId,
connData.iServerAddr );
// Set receiving and sending state active for the created connection
iConnMux->SetReceivingStateL( aStreamId, connectionId,
EStreamingStateActive );
iConnMux->SetSendingStateL( aStreamId, connectionId, connData.iServerAddr,
EStreamingStateActive );
// wait MNcmConnectionObserver::ConnectionNotify
__TURNPLUGIN( "CNATFWTurnConnectionHandler::FetchCandidateL end" )
}
// ---------------------------------------------------------------------------
// CNATFWTurnConnectionHandler::GetConnectionIdL
// ---------------------------------------------------------------------------
//
void CNATFWTurnConnectionHandler::GetConnectionIdL(
const CNATFWCandidate& aLocalCandidate,
TUint aStreamId,
TUint& aConnectionId )
{
__TURNPLUGIN( "CNATFWTurnConnectionHandler::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::ERelay == 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 ) );
__TURNPLUGIN( "CNATFWTurnConnectionHandler::GetConnectionIdL end" )
}
// ---------------------------------------------------------------------------
// CNATFWTurnConnectionHandler::StartTurnRefresh
// ---------------------------------------------------------------------------
//
void CNATFWTurnConnectionHandler::StartTurnRefresh()
{
__TURNPLUGIN( "CNATFWTurnConnectionHandler::StartTurnRefresh start" )
iTurnRefreshStarted = EFalse;
iTurnRefreshTimer->StartTurnRefresh( iTurnRefreshInterval );
if ( iTurnRefreshTimer->IsRunning() )
{
iTurnRefreshStarted = ETrue;
}
__TURNPLUGIN( "CNATFWTurnConnectionHandler::StartTurnRefresh end" )
}
// ---------------------------------------------------------------------------
// CNATFWTurnConnectionHandler::CreateTURNBindingL
// ---------------------------------------------------------------------------
//
void CNATFWTurnConnectionHandler::CreateTURNBindingL( TUint aStreamId,
TUint aConnectionId )
{
__TURNPLUGIN( "CNATFWTurnConnectionHandler::CreateTURNBindingL" )
TInt streamInd( IndexByStreamId( aStreamId ) );
TConnectionData* connection( NULL );
if ( KErrNotFound != streamInd )
{
connection = ConnectionById( streamInd, aConnectionId );
}
if ( connection )
{
CSTUNRelayBinding* turnBinding = CSTUNRelayBinding::NewL(
*iStunClient, aStreamId, aConnectionId );
CleanupStack::PushL( turnBinding );
delete connection->iTurnBinding;
connection->iTurnBinding = turnBinding;
turnBinding->AllocateRequestL( iStreamArray[streamInd].iRtoValue );
CleanupStack::Pop( turnBinding );
// wait MStunClientObserver::STUNBindingEventOccurredL
}
}
// ---------------------------------------------------------------------------
// CNATFWTurnConnectionHandler::SetReceivingStateL
// ---------------------------------------------------------------------------
//
void CNATFWTurnConnectionHandler::SetReceivingStateL(
const CNATFWCandidate& aLocalCandidate,
TNATFWStreamingState aState )
{
__TURNPLUGIN( "CNATFWTurnConnectionHandler::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( TTurnPluginCallbackInfo::
EActiveReceiving, streamId, KErrNone, NULL );
}
else
{
iConnMux->SetReceivingStateL( streamId, connId,
EStreamingStateActive );
}
}
else
{
if ( !connection->iReceivingActivated )
{
iAsyncCallback->MakeCallbackL( TTurnPluginCallbackInfo::
EDeactiveReceiving, streamId, KErrNone, NULL );
}
else
{
iConnMux->SetReceivingStateL( streamId, connId,
EStreamingStatePassive );
}
}
}
else
{
if ( EStreamingStateActive == aState )
{
iAsyncCallback->MakeCallbackL( TTurnPluginCallbackInfo::
EActiveReceiving, streamId, KErrNotFound, NULL );
}
else
{
iAsyncCallback->MakeCallbackL( TTurnPluginCallbackInfo::
EDeactiveReceiving, streamId, KErrNotFound, NULL );
}
}
__TURNPLUGIN( "CNATFWTurnConnectionHandler::SetReceivingStateL end" )
}
// ---------------------------------------------------------------------------
// CNATFWTurnConnectionHandler::SetSendingStateL
// ---------------------------------------------------------------------------
//
void CNATFWTurnConnectionHandler::SetSendingStateL(
const CNATFWCandidate& aLocalCandidate,
TNATFWStreamingState aState,
const TInetAddr& aDestAddr )
{
__TURNPLUGIN_ADDRLOG(
"CNATFWTurnConnectionHandler::SetSendingStateL start",
aDestAddr )
TUint streamId( aLocalCandidate.StreamId() );
TUint connId( 0 );
TConnectionData* connection = NULL;
TInt streamInd( IndexByStreamId( streamId ) );
TRAPD( err, GetConnectionIdL( aLocalCandidate, streamId, connId ) );
if ( !err )
{
connection = ConnectionById( streamInd, connId );
}
if ( connection )
{
if ( EStreamingStateActive == aState && TConnectionData::
EActDestTransitioning == connection->iActDestState )
{
// Only Active Destination reset (sending passivation)
// can be done when in "Transitioning" state.
iAsyncCallback->MakeCallbackL( TTurnPluginCallbackInfo::
EActiveSending, streamId, KErrNotReady, NULL );
}
else
{
if ( EStreamingStateActive == aState )
{
// Do Set Active Destination Request if the remote
// address differs from current active destination
if ( !MatchAddresses( connection->iCurrentActDest,
aDestAddr ) )
{
connection->iPeerAddr.SetAddress( aDestAddr.Address() );
connection->iPeerAddr.SetPort( aDestAddr.Port() );
if ( KProtocolInetTcp == iStreamArray[streamInd].
iTransportProtocol )
{
// We need to do the Connect Request first
// and have successfull response to it.
connection->iTurnBinding->ConnectRequestL(
connection->iPeerAddr );
}
else
{
connection->iTurnBinding
->SetActiveDestinationRequestL(
connection->iPeerAddr,
connection->iTimerValue );
}
}
else
{
// No need to set this destination active again
iAsyncCallback->MakeCallbackL( TTurnPluginCallbackInfo::
EActiveSending, streamId, KErrNone, NULL );
}
}
else
{
// Plug-in's client wants to reset Active Destination.
connection->iPeerAddr = KAFUnspec;
connection->iTurnBinding->SetActiveDestinationRequestL(
connection->iPeerAddr, connection->iTimerValue );
}
}
}
else
{
if ( EStreamingStateActive == aState )
{
iAsyncCallback->MakeCallbackL( TTurnPluginCallbackInfo::
EActiveSending, streamId, KErrNotFound, NULL );
}
else
{
iAsyncCallback->MakeCallbackL( TTurnPluginCallbackInfo::
EDeactiveSending, streamId, KErrNotFound, NULL );
}
}
__TURNPLUGIN(
"CNATFWTurnConnectionHandler::SetSendingStateL end" )
}
// ---------------------------------------------------------------------------
// CNATFWTurnConnectionHandler::IsRequestOrIndicationL
// ---------------------------------------------------------------------------
//
TBool CNATFWTurnConnectionHandler::IsRequestOrIndicationL(
const TDesC8& aMessage ) const
{
__TURNPLUGIN( "CNATFWTurnConnectionHandler::IsRequestOrIndicationL" )
CNATFWUNSAFMessageFactory* decoder = CNATFWUNSAFMessageFactory::NewLC();
CNATFWUNSAFMessage* msg = decoder->DecodeL( aMessage );
CleanupStack::PopAndDestroy( decoder );
if ( CNATFWUNSAFMessage::EAllocateRequest == msg->Type() ||
CNATFWUNSAFMessage::EConnectRequest == msg->Type() ||
CNATFWUNSAFMessage::ESetActiveDestinationRequest == msg->Type() ||
CNATFWUNSAFMessage::ESendIndication == msg->Type() )
{
delete msg;
return ETrue;
}
else
{
delete msg;
return EFalse;
}
}
// ---------------------------------------------------------------------------
// CNATFWTurnConnectionHandler::IsTurnResponseL
// ---------------------------------------------------------------------------
//
TBool CNATFWTurnConnectionHandler::IsTurnResponseL(
const TDesC8& aMessage ) const
{
__TURNPLUGIN( "CNATFWTurnConnectionHandler::IsTurnResponseL" )
CNATFWUNSAFMessageFactory* decoder = CNATFWUNSAFMessageFactory::NewLC();
CNATFWUNSAFMessage* msg = decoder->DecodeL( aMessage );
CleanupStack::PopAndDestroy( decoder );
if ( CNATFWUNSAFMessage::EAllocateResponse == msg->Type() ||
CNATFWUNSAFMessage::EAllocateErrorResponse == msg->Type() ||
CNATFWUNSAFMessage::ESetActiveDestinationResponse == msg->Type() ||
CNATFWUNSAFMessage::ESetActiveDestinationErrorResponse ==
msg->Type() ||
CNATFWUNSAFMessage::EConnectResponse == msg->Type() ||
CNATFWUNSAFMessage::EConnectErrorResponse == msg->Type() )
{
delete msg;
return ETrue;
}
else
{
delete msg;
return EFalse;
}
}
// ---------------------------------------------------------------------------
// From base class MStunClientObserver.
// CNATFWTurnConnectionHandler::STUNClientInitCompleted
// ---------------------------------------------------------------------------
//
void CNATFWTurnConnectionHandler::STUNClientInitCompleted(
const CSTUNClient& /*aClient*/,
TInt aCompletionCode )
{
__TURNPLUGIN(
"CNATFWTurnConnectionHandler::STUNClientInitCompleted start" )
if ( KErrNone == aCompletionCode )
{
TRAP_IGNORE( iAsyncCallback->MakeCallbackL(
TTurnPluginCallbackInfo::EConnectServer, 0,
aCompletionCode, NULL ) )
}
else
{
TInt error( KErrNone );
TRAP( error, TryNextServerL() );
if ( KErrNone != error )
{
delete iStunClient;
iStunClient = NULL;
TRAP_IGNORE( iAsyncCallback->MakeCallbackL(
TTurnPluginCallbackInfo::EConnectServer, 0,
( KClientSpecificError + aCompletionCode), NULL ) )
}
}
__TURNPLUGIN(
"CNATFWTurnConnectionHandler::STUNClientInitCompleted end" )
}
// ---------------------------------------------------------------------------
// From base class MStunClientObserver
// CNATFWTurnConnectionHandler::STUNBindingEventOccurredL
// ---------------------------------------------------------------------------
//
void CNATFWTurnConnectionHandler::STUNBindingEventOccurredL(
TSTUNBindingEvent aEvent,
const CBinding& aBinding )
{
__TURNPLUGIN(
"CNATFWTurnConnectionHandler::STUNBindingEventOccurredL start" )
const CSTUNRelayBinding& turnBinding =
static_cast<const CSTUNRelayBinding&>( aBinding );
TUint streamId( turnBinding.StreamId() );
TUint connId( turnBinding.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 ( iTurnRefreshTimer && !iTurnRefreshStarted )
{
StartTurnRefresh();
}
TInetAddr relayAddr;
relayAddr.SetAddress( turnBinding.RelayAddr().Address() );
relayAddr.SetPort( turnBinding.RelayAddr().Port() );
__TURNPLUGIN_ADDRLOG( "CNATFWTurnConnectionHandler::\
STUNBindingEventOccurredL Adress Resolved ADDRESS: ",
relayAddr )
CNATFWCandidate* newCandidate = CNATFWCandidate::NewL();
CleanupStack::PushL( newCandidate );
// Set candidate parameters
newCandidate->SetStreamId( streamId );
newCandidate->SetType( CNATFWCandidate::ERelay );
newCandidate->SetBase( relayAddr );
newCandidate->SetTransportAddrL( relayAddr );
newCandidate->SetTransportProtocol(
iStreamArray[streamInd].iTransportProtocol );
CNATFWCandidate* copyCandidate = CNATFWCandidate::NewL(
*newCandidate );
connection->iLocalCandidate = copyCandidate;
iAsyncCallback->MakeCallbackL(
TTurnPluginCallbackInfo::ELocalCandidateFound,
streamId, KErrNone, newCandidate );
iAsyncCallback->MakeCallbackL(
TTurnPluginCallbackInfo::EFetchingEnd, streamId,
KErrNone, NULL );
CleanupStack::Pop( newCandidate );
}
}
break;
case ECredentialsRejected:
{
__TURNPLUGIN( "CNATFWTurnConnectionHandler::\
STUNBindingEventOccurredL Credentials Rejected" )
// TURN server rejected the credentials provided that were
// set with CSTUNClient::SetCredentialsL. Application
// should obtain valid credentials and then use
// CSTUNClient::SetCredentialsL.
iAsyncCallback->MakeCallbackL( TTurnPluginCallbackInfo::
EFetchingEnd, streamId, ( KClientSpecificError +
KErrPermissionDenied ), NULL );
// Remove failed entry from array
DeleteStream( streamInd, ETrue );
}
break;
case ETCPConnectOk:
{
__TURNPLUGIN( "CNATFWTurnConnectionHandler::\
STUNBindingEventOccurredL TCP Connect Ok" )
// After TCP connect is OK we can set Active Destination.
connection->iTurnBinding->SetActiveDestinationRequestL(
connection->iPeerAddr, connection->iTimerValue );
}
break;
// Success
case EActiveDestinationSet:
{
__TURNPLUGIN( "CNATFWTurnConnectionHandler::\
STUNBindingEventOccurredL Active Destination Set" )
if ( TConnectionData::EActDestNoneSet == connection->
iActDestState && !connection->iPeerAddr.IsUnspecified() )
{
if ( connection->iActDestAlreadySetOnServer )
{
// Active Destination was reset on server. Media
// flows in indications while trying to set the
// Active Destination again after 5 seconds.
iAsyncCallback->MakeCallbackL(
TTurnPluginCallbackInfo::EActiveSending,
iStreamArray[streamInd].iStreamId, KErrNone,
NULL );
iActiveDestinationTimer->StartTimer(
KWaitTimeAfterReset, iStreamArray[streamInd].
iStreamId, connection->iConnectionId );
}
else
{
iAsyncCallback->MakeCallbackL(
TTurnPluginCallbackInfo::EActiveSending,
iStreamArray[streamInd].iStreamId, KErrNone,
NULL );
iActiveDestinationTimer->StartTimer(
KDefaultSrvTransitioningTime,
iStreamArray[streamInd].iStreamId,
connection->iConnectionId );
// If a successful response was received, but
// there was a REMOTE-ADDRESS in the request, the
// state machine transitions to the "Set" state
// after three seconds, and the client sets the
// active destination to the value of the REMOTE-
// ADDRESS attribute that was in the request.
}
}
// else If, while in the "None Set" state, the client
// sent a Set Active Destination request without a
// REMOTE-ADDRESS, and got a successful response,
// there is no change in state.
else if ( TConnectionData::EActDestSet == connection->
iActDestState )
{
if ( connection->iPeerAddr.IsUnspecified() ||
!MatchAddresses( connection->iPeerAddr, connection->
iCurrentActDest ) )
{
connection->iActDestState = TConnectionData::
EActDestTransitioning;
// the client enters the "Transitioning" state.
// While in this state, the client MUST NOT send
// a new Set Active Destination request. The value
// of the active destination remains unchanged. In
// addition, the client sets a timer. This timer
// MUST have a value equal to the value of the
// TIMER-VAL attribute from the Set Active
// Destination response. This is necessary for
// coordinating the state machines between client
// and server.
iActiveDestinationTimer->StartTimer(
connection->iTimerValue, iStreamArray[streamInd].
iStreamId, connection->iConnectionId );
}
// In addition, if, while in the "Set" state, the
// client sends a Set Active Destination request whose
// REMOTE-ADDRESS attribute equals the current active
// destination, and that request generates a success
// response, the client remains in the "Set" state.
}
else
{
// Only Active Destination reset request can be done when
// in "Transitioning" state.
if ( connection->iPeerAddr.IsUnspecified() )
{
iActiveDestinationTimer->StartTimer( connection->
iTimerValue, iStreamArray[streamInd].iStreamId,
connection->iConnectionId );
}
}
}
break;
}
}
__TURNPLUGIN(
"CNATFWTurnConnectionHandler::STUNBindingEventOccurredL end" )
}
// ---------------------------------------------------------------------------
// From base class MStunClientObserver
// CNATFWTurnConnectionHandler::STUNBindingErrorOccurred
// ---------------------------------------------------------------------------
//
void CNATFWTurnConnectionHandler::STUNBindingErrorOccurred(
const CBinding& aBinding,
TInt aError )
{
__TURNPLUGIN(
"CNATFWTurnConnectionHandler::STUNBindingErrorOccurred start" )
const CSTUNRelayBinding& turnBinding =
static_cast<const CSTUNRelayBinding&>( aBinding );
TUint streamId( turnBinding.StreamId() );
TUint connId( turnBinding.ConnectionId() );
TInt streamInd( IndexByStreamId( streamId ) );
TConnectionData* connection( NULL );
if ( KErrNotFound != streamInd )
{
connection = ConnectionById( streamInd, connId );
}
if ( connection )
{
if ( KNoBinding == aError && connection->iLocalCandidate )
{
// A 437 response implies that the allocation has been
// removed, and thus the state machine destroyed. A client
// MUST NOT send a new Set Active Destination request prior
// to the receipt of a response to the previous. The state
// machine will further limit the transmission of subsequent
// Set Active Destination requests.
TRAP_IGNORE( iAsyncCallback->MakeCallbackL(
TTurnPluginCallbackInfo::EActiveSending, streamId,
KErrNotFound, NULL ) )
// Remove entry from array as binding does not exist anymore
DeleteStream( streamInd, ETrue );
}
else if ( KServerTransitioning == aError && connection->
iLocalCandidate )
{
if ( TConnectionData::EActDestSet == connection->iActDestState )
{
// When this error is received, the client remains in the
// "Set" state. The client SHOULD retry its Set Active
// Destination request, but no sooner than 500ms after
// receipt of the 439 response.
iActiveDestinationTimer->StartTimer(
KRetryTimeAfter439, iStreamArray[streamInd].iStreamId,
connection->iConnectionId );
}
else if ( TConnectionData::EActDestNoneSet == connection->
iActDestState )
{
// Set Active Destination request was received by the
// server over UDP. However, the active destination is
// already set to another value. The client should reset
// the active destination, wait for 5 seconds and set the
// active destination to the new value.
connection->iActDestAlreadySetOnServer = ETrue;
TRAP_IGNORE( connection->iTurnBinding->
SetActiveDestinationRequestL( KAFUnspec, connection->
iTimerValue ) )
}
else
{
// Not possible that this error occurs when in
// "transitioning" state
}
}
else
{
if ( !connection->iLocalCandidate )
{
if( KTryAlternate == aError )
{
__TURNPLUGIN( "CNATFWTurnConnectionHandler::\
STUNBindingErrorOccurred KTryAlternate == aError" )
connection->iServerAddr.SetAddress( turnBinding.
AlternateServerAddr().Address() );
connection->iServerAddr.SetPort( turnBinding.
AlternateServerAddr().Port() );
delete connection->iTurnBinding;
connection->iTurnBinding = NULL;
TRAP_IGNORE( iConnMux->SetSendingStateL( streamId, connId,
connection->iServerAddr, EStreamingStateActive ) )
// wait MNcmConnectionObserver::ConnectionNotify
}
else
{
// If error occurs when trying to fetch candidate
TInt errcode( KClientSpecificError + ( aError ) );
TRAP_IGNORE( iAsyncCallback->MakeCallbackL(
TTurnPluginCallbackInfo::EFetchingEnd, streamId,
errcode, NULL ) )
// Remove failed entry from array
DeleteStream( streamInd, ETrue );
}
}
else
{
// Do nothing if error occurs when doing binding refresh
}
}
}
__TURNPLUGIN(
"CNATFWTurnConnectionHandler::STUNBindingErrorOccurred end" )
}
// ---------------------------------------------------------------------------
// from base class MNcmIncomingConnectionObserver
// CNATFWTurnConnectionHandler::IncomingMessageL
// ---------------------------------------------------------------------------
//
void CNATFWTurnConnectionHandler::IncomingMessageL(
TUint aStreamId,
const TDesC8& aMessage,
const TInetAddr& /*aLocalAddr*/,
#ifdef _DEBUG
const TInetAddr& aFromAddr,
const TInetAddr& aPeerAddr,
#else
const TInetAddr& /*aFromAddr*/,
const TInetAddr& /*aPeerAddr*/,
#endif
TBool& aConsumed )
{
__TURNPLUGIN_ADDRLOG(
"CNATFWTurnConnectionHandler::IncomingMessageL FROMADDR", aFromAddr )
__TURNPLUGIN_ADDRLOG(
"CNATFWTurnConnectionHandler::IncomingMessageL PEERADDR", aPeerAddr )
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 ) )
{
__TURNPLUGIN( "CNATFWTurnConnectionHandler::IncomingMessageL\
HandleDataL method to be called" )
TBool consumed( EFalse );
TConnectionData* connection = ConnectionByIndex( streamInd, connInd );
if ( connection->iTurnBinding )
{
if ( indicationData )
{
connection->iTurnBinding->HandleDataL( *indicationData,
consumed, peerAddrFromIndication );
}
else
{
indicationData = connection->iTurnBinding->HandleDataL(
aMessage, consumed, peerAddrFromIndication );
}
}
if ( consumed )
{
consumingBindingInd = connInd;
aConsumed = ETrue;
}
connInd--;
}
delete indicationData;
}
// ---------------------------------------------------------------------------
// from base class MNcmOutgoingConnectionObserver
// CNATFWTurnConnectionHandler::OutgoingMessageL
// ---------------------------------------------------------------------------
//
void CNATFWTurnConnectionHandler::OutgoingMessageL(
TUint aStreamId,
TUint aConnectionId,
const TInetAddr& aPeerAddr,
const TDesC8& aMessage,
TBool& aConsumed )
{
__TURNPLUGIN( "CNATFWTurnConnectionHandler::OutgoingMessageL" )
aConsumed = EFalse;
TBool controlMsgDetected( EFalse );
TRAPD( err, controlMsgDetected = IsRequestOrIndicationL( aMessage ) )
if ( !controlMsgDetected || err ) // Prevent loopback in msg handling
{
TInt streamInd( IndexByStreamId( aStreamId ) );
TConnectionData* connection( NULL );
if ( KErrNotFound != streamInd )
{
connection = ConnectionById( streamInd, aConnectionId );
}
if ( connection )
{
aConsumed = ETrue;
if ( aPeerAddr.IsUnspecified() )
{
if ( TConnectionData::EActDestNoneSet == connection->
iActDestState || TConnectionData::EActDestTransitioning ==
connection->iActDestState )
{
__TURNPLUGIN( "CNATFWTurnConnectionHandler::\
OutgoingMessageL Media will be sent in indication" )
connection->iTurnBinding->SendIndicationL( connection->
iPeerAddr, aMessage, EFalse );
}
else
{
__TURNPLUGIN( "CNATFWTurnConnectionHandler::\
OutgoingMessageL Media will be sent directly" )
if ( KProtocolInetTcp == iStreamArray[streamInd].
iTransportProtocol )
{
CNATFWUNSAFTcpRelayPacket* packet =
CNATFWUNSAFTcpRelayPacket::NewLC( aMessage,
CNATFWUNSAFTcpRelayPacket::EFrameTypeData);
CBufBase* message = packet->EncodeL();
CleanupStack::PopAndDestroy( packet );
CleanupStack::PushL( message );
iConnMux->SendL( aStreamId, connection->iConnectionId,
message->Ptr(0), ETrue );
CleanupStack::PopAndDestroy( message );
}
else
{
iConnMux->SendL( aStreamId, connection->iConnectionId,
aMessage, ETrue );
}
}
}
else
{
// Must be protocol message, send in indication(TURNbis-03, 4)
__TURNPLUGIN( "CNATFWTurnConnectionHandler::\
OutgoingMessageL PROTOCOL MSG will be sent" )
__TURNPLUGIN_ADDRLOG(
"CNATFWTurnConnectionHandler::OutgoingMessageL PEERADDR",
aPeerAddr )
connection->iTurnBinding->SendIndicationL( aPeerAddr,
aMessage, EFalse );
}
}
}
}
// ---------------------------------------------------------------------------
// from base class MNcmMessageObserver
// CNATFWTurnConnectionHandler::IncomingMessageNotify
// ---------------------------------------------------------------------------
//
HBufC8* CNATFWTurnConnectionHandler::IncomingMessageNotify(
TUint aStreamId,
const TDesC8& aMessage,
const TInetAddr& aLocalAddr,
const TInetAddr& aFromAddr,
TInetAddr& aPeerAddr )
{
__TURNPLUGIN( "CNATFWTurnConnectionHandler::IncomingMessageNotify" )
HBufC8* modifiedMessage( NULL );
TRAPD( error, modifiedMessage = HandleIncomingMessageL(
aStreamId, aMessage, aLocalAddr, aFromAddr, aPeerAddr ) )
if ( KErrNone == error )
{
return modifiedMessage;
}
else
{
__TURNPLUGIN_INT1(
"CNATFWTurnConnectionHandler::IncomingMessageNotify ERR", error )
return NULL;
}
}
// ---------------------------------------------------------------------------
// from base class MNcmMessageObserver
// CNATFWTurnConnectionHandler::OutgoingMessageNotify
// ---------------------------------------------------------------------------
//
HBufC8* CNATFWTurnConnectionHandler::OutgoingMessageNotify(
TUint /*aStreamId*/,
TUint /*aConnectionId*/,
const TInetAddr& /*aDestinationAddress*/,
const TDesC8& /*aMessage*/ )
{
__TURNPLUGIN( "CNATFWTurnConnectionHandler::OutgoingMessageNotify" )
return NULL;
}
// ---------------------------------------------------------------------------
// from base class MNcmConnectionObserver
// CNATFWTurnConnectionHandler::ConnectionNotify
// ---------------------------------------------------------------------------
//
void CNATFWTurnConnectionHandler::ConnectionNotify(
TUint aStreamId,
TUint aConnectionId,
TConnectionNotifyType aType,
TInt aError )
{
__TURNPLUGIN( "CNATFWTurnConnectionHandler::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(
TTurnPluginCallbackInfo::EFetchingEnd, aStreamId,
errcode, NULL ) )
}
else
{
TRAP_IGNORE( iAsyncCallback->MakeCallbackL(
TTurnPluginCallbackInfo::EError, aStreamId,
aError, NULL ) )
}
// Remove failed entry from array
DeleteStream( streamInd, ETrue );
}
else
{
switch ( aType )
{
case ESendingActivated:
{
connection->iSendingActivated = ETrue;
if ( !connection->iTurnBinding )
{
TRAP_IGNORE( CreateTURNBindingL( aStreamId,
aConnectionId ) )
}
}
break;
case EReceivingActivated:
{
connection->iReceivingActivated = ETrue;
if ( connection->iLocalCandidate )
{
TRAP_IGNORE( iAsyncCallback->MakeCallbackL(
TTurnPluginCallbackInfo::EActiveReceiving,
aStreamId, KErrNone, NULL ) )
}
}
break;
case ESendingDeactivated:
{
connection->iSendingActivated = EFalse;
}
break;
case EReceivingDeactivated:
{
connection->iReceivingActivated = EFalse;
if ( connection->iLocalCandidate )
{
TRAP_IGNORE( iAsyncCallback->MakeCallbackL(
TTurnPluginCallbackInfo::EDeactiveReceiving,
aStreamId, KErrNone, NULL ) )
}
}
break;
case EConnectionRemoved:
{
DeleteStream( streamInd, EFalse );
}
break;
}
}
}
__TURNPLUGIN( "CNATFWTurnConnectionHandler::ConnectionNotify end" )
}
// ---------------------------------------------------------------------------
// from base class MNATFWRefreshObserver
// CNATFWTurnConnectionHandler::BindingRefreshL
// ---------------------------------------------------------------------------
//
void CNATFWTurnConnectionHandler::BindingRefreshL()
{
__TURNPLUGIN( "CNATFWTurnConnectionHandler::BindingRefreshL start" )
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 );
connection->iTurnBinding->AllocateRequestL(
iStreamArray[streamInd].iRtoValue );
}
}
__TURNPLUGIN( "CNATFWTurnConnectionHandler::BindingRefreshL end" )
}
// ---------------------------------------------------------------------------
// from base class MNATFWTimerObserver
// CNATFWTurnConnectionHandler::TimerTriggeredL
// ---------------------------------------------------------------------------
//
void CNATFWTurnConnectionHandler::TimerTriggeredL( TUint aStreamId,
TUint aConnectionId )
{
__TURNPLUGIN( "CNATFWTurnConnectionHandler::TimerTriggeredL start" )
TInt streamInd( IndexByStreamId( aStreamId ) );
TConnectionData* connection( NULL );
if ( KErrNotFound != streamInd )
{
connection = ConnectionById( streamInd, aConnectionId );
}
if ( connection )
{
if ( TConnectionData::EActDestTransitioning == connection->
iActDestState )
{
// Once the timer fires, if the REMOTE-ADDRESS was not absent
// from the Set Active Destination request which caused the
// client to start the timer, the client moves back to the
// "Set" state, and then updates the value of the active
// destination to the value of REMOTE-ADDRESS.
if ( !connection->iPeerAddr.IsUnspecified() )
{
// Plug-in's client changed Active Destination on
// server successfully.
connection->iActDestState = TConnectionData::EActDestSet;
connection->iCurrentActDest.SetAddress( connection->iPeerAddr.
Address() );
connection->iCurrentActDest.SetPort( connection->iPeerAddr.
Port() );
iAsyncCallback->MakeCallbackL( TTurnPluginCallbackInfo::
EActiveSending, iStreamArray[streamInd].iStreamId,
KErrNone, NULL );
}
else
// If REMOTE-ADDRESS was absent, the client sets the Active
// Destination to null and enders the "None Set" state.
{
// Plug-in's client resetted Active Destination on
// server successfully.
connection->iActDestState = TConnectionData::EActDestNoneSet;
connection->iCurrentActDest = KAFUnspec;
iAsyncCallback->MakeCallbackL( TTurnPluginCallbackInfo::
EDeactiveSending, iStreamArray[streamInd].iStreamId,
KErrNone, NULL );
}
}
else if ( TConnectionData::EActDestNoneSet == connection->
iActDestState )
{
if ( !connection->iActDestAlreadySetOnServer )
{
connection->iActDestState = TConnectionData::EActDestSet;
connection->iCurrentActDest.SetAddress( connection->iPeerAddr.
Address() );
connection->iCurrentActDest.SetPort( connection->iPeerAddr.
Port() );
}
else
{
connection->iActDestAlreadySetOnServer = EFalse;
// Active Destination was reset on server so now
// try to set Active Destination to remote address.
connection->iTurnBinding->SetActiveDestinationRequestL(
connection->iPeerAddr, connection->iTimerValue );
}
}
else
{
if ( !connection->iActDestReqResent )
{
// As server was on "transitioning" state for the first
// Set Active Destination Request, a new request will
// be sent only once.
connection->iActDestReqResent = ETrue;
connection->iTurnBinding->SetActiveDestinationRequestL(
connection->iPeerAddr, connection->iTimerValue );
}
else
{
iAsyncCallback->MakeCallbackL( TTurnPluginCallbackInfo::
EActiveSending, aStreamId, KErrNotReady, NULL );
}
}
}
__TURNPLUGIN( "CNATFWTurnConnectionHandler::TimerTriggeredL end" )
}
// ---------------------------------------------------------------------------
// CNATFWTurnConnectionHandler::DeleteStream
// ---------------------------------------------------------------------------
//
void CNATFWTurnConnectionHandler::DeleteStream( TUint aStreamInd,
TBool aRemoveMuxConn )
{
__TURNPLUGIN( "CNATFWTurnConnectionHandler::DeleteStream, start" )
ASSERT( aStreamInd < TUint( iStreamArray.Count() ) );
TRAP_IGNORE(
iConnMux->UnregisterConnectionObserverL(
iStreamArray[aStreamInd].iStreamId, *this ) )
TRAP_IGNORE(
iConnMux->UnregisterIncomingConnectionObserverL(
iStreamArray[aStreamInd].iStreamId, *this ) )
TRAP_IGNORE(
iConnMux->UnregisterOutgoingConnectionObserverL(
iStreamArray[aStreamInd].iStreamId, *this ) )
TRAP_IGNORE(
iConnMux->UnregisterMessageObserverL(
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->iTurnBinding )
{
connection->iTurnBinding->CancelRequest();
delete connection->iTurnBinding;
connection->iTurnBinding = 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 );
__TURNPLUGIN( "CNATFWTurnConnectionHandler::DeleteStream, end" )
}
// ---------------------------------------------------------------------------
// CNATFWTurnConnectionHandler::FindConnection
// Function expects that system does not have multiple TURN-connections bound
// to the same local address and stream.
// ---------------------------------------------------------------------------
//
TConnectionData* CNATFWTurnConnectionHandler::FindConnection(
TUint aStreamId,
const TInetAddr& aLocalAddr )
{
// find stream index
TInt foundStreamInd( KErrNotFound );
TInt streamInd( iStreamArray.Count() - 1 );
while ( KErrNotFound == foundStreamInd && 0 <= streamInd )
{
if ( iStreamArray[streamInd].iStreamId == aStreamId )
{
foundStreamInd = streamInd;
}
streamInd--;
}
TInt foundConnectionInd( KErrNotFound );
if ( KErrNotFound != foundStreamInd )
{
// find connection inside stream
const RArray<TConnectionData>& connArray(
iStreamArray[foundStreamInd].iConnArray );
TInt connectionInd( connArray.Count() - 1 );
while ( KErrNotFound == foundConnectionInd && 0 <= connectionInd )
{
const TInetAddr& localAddr( connArray[connectionInd].iLocalAddr );
if ( MatchAddresses( localAddr, aLocalAddr ) )
{
foundConnectionInd = connectionInd;
}
connectionInd--;
}
}
if ( ( KErrNotFound != foundStreamInd ) &&
( KErrNotFound != foundConnectionInd ) )
{
return &(iStreamArray[foundStreamInd].iConnArray[foundConnectionInd]);
}
else
{
return NULL;
}
}
// ---------------------------------------------------------------------------
// CNATFWTurnConnectionHandler::HandleIncomingMessageL
// ---------------------------------------------------------------------------
//
HBufC8* CNATFWTurnConnectionHandler::HandleIncomingMessageL(
TUint aStreamId,
const TDesC8& aMessage,
const TInetAddr& aLocalAddr,
const TInetAddr& aFromAddr,
TInetAddr& aPeerAddr )
{
CNATFWUNSAFMessageFactory* decoder = CNATFWUNSAFMessageFactory::NewLC();
CNATFWUNSAFMessage* msg( NULL );
TRAPD( error, msg = decoder->DecodeL( aMessage ) )
CleanupStack::PopAndDestroy( decoder );
CleanupStack::PushL( msg );
if ( error || NULL == msg )
{
// Not STUN message, must be media
TConnectionData* activeConnection( NULL );
TInt streamInd( iStreamArray.Count() - 1 );
while ( !activeConnection && 0 <= streamInd )
{
TInt connInd = iStreamArray[streamInd].iConnArray.Count() - 1;
while ( !activeConnection && 0 <= connInd )
{
activeConnection = ConnectionByIndex( streamInd, connInd );
if ( TConnectionData::EActDestSet != activeConnection->
iActDestState )
{
activeConnection = NULL;
}
connInd--;
}
streamInd--;
}
if ( activeConnection )
{
aPeerAddr = activeConnection->iCurrentActDest;
}
else
{
aPeerAddr = aFromAddr;
}
CleanupStack::PopAndDestroy( msg );
return NULL;
}
if ( msg->Type() == CNATFWUNSAFMessage::EDataIndication )
{
// Must be data from peer, either protocol message or media
// from nonactivated peer address
CNATFWUNSAFRemoteAddressAttribute* remoteAddress =
static_cast<CNATFWUNSAFRemoteAddressAttribute*>
( msg->Attribute( CNATFWUNSAFAttribute::ERemoteAddress ) );
if ( remoteAddress )
{
aPeerAddr = remoteAddress->Address();
__TURNPLUGIN_ADDRLOG(
"CNATFWTurnConnectionHandler::HandleIncomingMessageL DATAIND",
aPeerAddr )
}
else
{
__TURNPLUGIN(
"CNATFWTurnConnectionHandler::HandleIncomingMessageL, \
NO REMOTE ADDR FIELD" )
}
const TDesC8& data = static_cast<CNATFWUNSAFDataAttribute*>(
msg->Attribute( CNATFWUNSAFAttribute::EData ) )->Value();
HBufC8* modifiedMsg = data.AllocL();
CleanupStack::PopAndDestroy( msg );
return modifiedMsg;
}
else
{
// This is either response from physical TURN-server or STUN-data from
// peer address which is set as active destination.
TConnectionData* activeConnection
= FindConnection( aStreamId, aLocalAddr );
if ( activeConnection &&
!activeConnection->iCurrentActDest.IsUnspecified() )
{
aPeerAddr = activeConnection->iCurrentActDest;
}
else
{
aPeerAddr = aFromAddr;
}
__TURNPLUGIN_ADDRLOG(
"CNATFWTurnConnectionHandler::HandleIncomingMessageL NOT DATAIND",
aPeerAddr )
CleanupStack::PopAndDestroy( msg );
return NULL;
}
}
// ---------------------------------------------------------------------------
// CNATFWTurnConnectionHandler::IndexByStreamId
// ---------------------------------------------------------------------------
//
TInt CNATFWTurnConnectionHandler::IndexByStreamId( TUint aStreamId )
{
__TURNPLUGIN( "CNATFWTurnConnectionHandler::IndexByStreamId" )
TInt index( iStreamArray.Count() - 1 );
while ( 0 <= index )
{
if ( aStreamId == iStreamArray[index].iStreamId )
{
return index;
}
index--;
}
return KErrNotFound;
}
// ---------------------------------------------------------------------------
// CNATFWTurnConnectionHandler::ConnectionById
// ---------------------------------------------------------------------------
//
TConnectionData* CNATFWTurnConnectionHandler::ConnectionById(
TUint aStreamInd,
TUint aConnectionId )
{
__TURNPLUGIN( "CNATFWTurnConnectionHandler::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;
}
// ---------------------------------------------------------------------------
// CNATFWTurnConnectionHandler::ConnectionByIndex
// ---------------------------------------------------------------------------
//
TConnectionData* CNATFWTurnConnectionHandler::ConnectionByIndex(
TUint aStreamInd,
TUint aConnectionInd )
{
__TURNPLUGIN( "CNATFWTurnConnectionHandler::ConnectionByIndex" )
return &iStreamArray[aStreamInd].iConnArray[aConnectionInd];
}
// ---------------------------------------------------------------------------
// CNATFWTurnConnectionHandler::GenerateServerListL
// ---------------------------------------------------------------------------
//
void CNATFWTurnConnectionHandler::GenerateServerListL()
{
__TURNPLUGIN( "CNATFWTurnConnectionHandler::GenerateServerListL start" )
RPointerArray<MNATFWServerSettings> serverArray;
iTurnSettings->GetTurnServerArrayL( serverArray );
CleanupClosePushL( serverArray );
TInt count( serverArray.Count() );
HBufC8* serverAddress =
iTurnSettings->LatestConnectedServerAddr().AllocLC();
TUint latestPort = iTurnSettings->LatestConnectedServerPort();
// Add Latest connected server
if ( serverAddress->Compare( KNullDesC8 ) )
{
CTurnServerSettings* settings = CTurnServerSettings::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;
}
}
if ( settings->Address().Compare( KNullDesC8 ) )
{
__TURNPLUGIN( "CNATFWStunConnectionHandler::GenerateServerListL\
- provisioned server added" )
}
iServerList.AppendL( settings );
CleanupStack::Pop( settings );
}
CleanupStack::PopAndDestroy( serverAddress );
// Add provisioned servers
for ( TInt index( 0 ); index < count; index++ )
{
CTurnServerSettings* settings = CTurnServerSettings::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() );
}
iServerList.AppendL( settings );
CleanupStack::Pop( settings );
}
// Domain
CTurnServerSettings* settings = CTurnServerSettings::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 );
__TURNPLUGIN( "CNATFWTurnConnectionHandler::GenerateServerListL end" )
}
// ---------------------------------------------------------------------------
// CNATFWStunConnectionHandler::TryNextServerL
// ---------------------------------------------------------------------------
//
void CNATFWTurnConnectionHandler::TryNextServerL()
{
__TURNPLUGIN( "CNATFWTurnConnectionHandler::TryNextServerL start" )
delete iStunClient;
iStunClient = NULL;
if ( iServerIndex < iServerList.Count() )
{
TInt index( iServerIndex );
iServerIndex++;
TInt refresh( iNatSettings->RefreshIntervalUdp() );
iTurnRefreshInterval = ( refresh ) ? ( refresh * KMicrosecFactor ) :
KDefaultRefreshInterval;
TInt retransmitInterval( iTurnSettings->RetransmissionTimeout() );
TUint port = iServerList[index]->Port() ? iServerList[index]->Port() :
KDefaultStunSrvPort;
iStunClient = CSTUNClient::NewL( retransmitInterval,
iServerList[index]->Address(),
port,
KStunRelay,
iSocketServ,
iConnection,
*iTimerServ,
*this,
ETrue,
EFalse,
EFalse,
iConnMux );
if ( iServerList[index]->Username() && iServerList[index]->
Password() )
{
TRAP_IGNORE( iStunClient->SetCredentialsL( *iServerList[index]->
Username(), *iServerList[index]->Password() ) )
}
}
else
{
User::Leave( KErrNotFound );
}
__TURNPLUGIN( "CNATFWTurnConnectionHandler::TryNextServerL end" )
}
// ---------------------------------------------------------------------------
// CNATFWTurnConnectionHandler::MatchAddresses
// ---------------------------------------------------------------------------
//
TBool CNATFWTurnConnectionHandler::MatchAddresses( const TInetAddr& aAddr1,
const TInetAddr& aAddr2 )
{
// 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