diff -r 7fdc9a71d314 -r 8ad140f3dd41 hti/HtiServicePlugins/HtiIpProxyServicePlugin/IPProxyEngine/Src/Csocketrouter.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/hti/HtiServicePlugins/HtiIpProxyServicePlugin/IPProxyEngine/Src/Csocketrouter.cpp Wed Oct 13 16:17:58 2010 +0300 @@ -0,0 +1,738 @@ +/* +* Copyright (c) 2009 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: Routes data from peers to host and vice versa +* +*/ + + + +// INCLUDE FILES +#include "Csocketrouter.h" +#include "CommRouterDefinitions.h" +#include "MSocketRouterObserver.h" +#include "MBPProtocol.h" +#include "CProtocolTCP.h" +#include "CProtocolUDP.h" +#include "CLocalTCPConnection.h" +#include "CUDPSender.h" +#include "IPProxyEngine.pan" + +#include + + +#define DEBUG_FILENAME "IPProxyEngine.log" +#include "DebugPrint.h" + +// LOCAL CONSTANTS +const TInt KSocketRouterSlots = 60; + + +// ============================ MEMBER FUNCTIONS =============================== + +// ----------------------------------------------------------------------------- +// CSocketRouter::CSocketRouter +// ----------------------------------------------------------------------------- +// +CSocketRouter::CSocketRouter( MSocketRouterObserver* aObserver ) + : CActive( EPriorityIdle ), iObserver( aObserver ) + { + __ASSERT_DEBUG( iObserver, User::Invariant() ); + } + +// ----------------------------------------------------------------------------- +// CSocketRouter::ConstructL +// ----------------------------------------------------------------------------- +// +void CSocketRouter::ConstructL() + { + User::LeaveIfError( iSocketServ.Connect( KSocketRouterSlots ) ); + + iReceiveBuffer = HBufC8::NewL( 0 ); + + iWriteEventArray = new (ELeave) CArrayPtrSeg ( 10 ); + iPeerSocketArray = new (ELeave) CArrayPtrFlat ( 10 ); + iProtocolArray = new (ELeave) CArrayPtrFlat ( 2 ); + + // Add the protocols + iProtocolTCP = CProtocolTCP::NewL( this ); + // takes the ownership + iProtocolArray->AppendL( iProtocolTCP ); + + iProtocolUDP = CProtocolUDP::NewL( this ); + // takes the ownership + iProtocolArray->AppendL( iProtocolUDP ); + + iUDPSender = CUDPSender::NewL( this ); + + CActiveScheduler::Add( this ); + } + +// ----------------------------------------------------------------------------- +// CSocketRouter::NewL +// ----------------------------------------------------------------------------- +// +CSocketRouter* CSocketRouter::NewL( MSocketRouterObserver* aObserver ) + { + CSocketRouter* self = CSocketRouter::NewLC( aObserver ); + CleanupStack::Pop(); + + return self; + } + +// ----------------------------------------------------------------------------- +// CSocketRouter::NewLC +// ----------------------------------------------------------------------------- +// +CSocketRouter* CSocketRouter::NewLC( MSocketRouterObserver* aObserver ) + { + CSocketRouter* self = new( ELeave ) CSocketRouter( aObserver ); + CleanupStack::PushL( self ); + + self->ConstructL(); + return self; + } + + +// Destructor +CSocketRouter::~CSocketRouter() + { + Cancel(); + + delete iUDPSender; + delete iReceiveBuffer; + + if ( iProtocolArray ) + { + iProtocolArray->ResetAndDestroy(); + delete iProtocolArray; + } + if ( iPeerSocketArray ) + { + iPeerSocketArray->ResetAndDestroy(); + delete iPeerSocketArray; + } + if ( iWriteEventArray ) + { + iWriteEventArray->ResetAndDestroy(); + delete iWriteEventArray; + } + + iSocketServ.Close(); + } + +// ----------------------------------------------------------------------------- +// CSocketRouter::AddPeerSocketL +// ----------------------------------------------------------------------------- +// +void CSocketRouter::AddPeerSocketL( RSocket* aSocket ) + { + CSocket* newSocket = CSocket::NewLC( aSocket ); + newSocket->SetObserver( this ); + iPeerSocketArray->AppendL( newSocket ); + newSocket->SetSocketOwnershipMode( ETrue ); + + DEBUG_PRINT( DEBUG_STRING( + "CSocketRouter::AddPeerSocketL(), localport=%d, remote port=%d" ), + newSocket->LocalPort(), + newSocket->RemotePort() ); + + CleanupStack::Pop( newSocket ); + } + + +// ----------------------------------------------------------------------------- +// CSocketRouter::AddUDPSocketL +// ----------------------------------------------------------------------------- +// +void CSocketRouter::AddUDPSocketL( TUint aPort ) + { + RSocket* newSocket = new (ELeave) RSocket(); + CleanupStack::PushL( newSocket ); + + // Open the socket + DEBUG_PRINT( DEBUG_STRING( "CSocketRouter::AddUDPSocketL, Trying to open UDP port %d" ), aPort ); + + User::LeaveIfError( newSocket->Open( iSocketServ, KAfInet, KSockDatagram, + KProtocolInetUdp ) ); + + DEBUG_PRINT( DEBUG_STRING( "CSocketRouter::AddUDPSocketL, UDP port opened." ), aPort ); + + // Bind the socket to the correct port. + TInetAddr anyAddrOnPort( KInetAddrAny, aPort ); + newSocket->Bind( anyAddrOnPort ); + + CSocket* cSocket = CSocket::NewLC( newSocket, aPort ); + cSocket->SetObserver( this ); + iPeerSocketArray->AppendL( cSocket ); + cSocket->SetSocketOwnershipMode( ETrue ); + CleanupStack::Pop( cSocket ); + + CleanupStack::Pop( newSocket ); + } + +// ----------------------------------------------------------------------------- +// CSocketRouter::RemovePeerSocket +// ----------------------------------------------------------------------------- +// +void CSocketRouter::RemovePeerSocket( TInt aIndex ) + { + DEBUG_PRINT( DEBUG_STRING( "CSocketRouter::RemovePeerSocket()" ) ); + CSocket* socket = iPeerSocketArray->At( aIndex ); + iPeerSocketArray->Delete( aIndex ); + delete socket; + } + +// ----------------------------------------------------------------------------- +// CSocketRouter::RemovePeerSocket +// ----------------------------------------------------------------------------- +// +void CSocketRouter::RemovePeerSocket( RSocket* aSocket ) + { + DEBUG_PRINT( DEBUG_STRING( "CSocketRouter::RemovePeerSocket()" ) ); + TInt count = iPeerSocketArray->Count(); + for ( TInt i = 0; i < count; i++ ) + { + if ( iPeerSocketArray->At( i )->GetRSocket() == aSocket ) + { + iPeerSocketArray->Delete( i ); + break; + } + } + } + +// ----------------------------------------------------------------------------- +// CSocketRouter::FindPeerSocket +// ----------------------------------------------------------------------------- +// +TInt CSocketRouter::FindPeerSocket( TUint aPort ) + { + DEBUG_PRINT( DEBUG_STRING( "CSocketRouter::FindPeerSocket()" ) ); + TInt count = iPeerSocketArray->Count(); + for ( TInt i = 0; i < count; i++ ) + { + if ( iPeerSocketArray->At( i )->RemotePort() == aPort + || iPeerSocketArray->At( i )->LocalPort() == aPort) + { + return i; + } + } + return -1; + } + +// ----------------------------------------------------------------------------- +// CSocketRouter::RemoveAllPeers +// ----------------------------------------------------------------------------- +// +void CSocketRouter::RemoveAllPeers() + { + iPeerSocketArray->ResetAndDestroy(); + } + +// ----------------------------------------------------------------------------- +// CSocketRouter::SocketCount +// ----------------------------------------------------------------------------- +// +TInt CSocketRouter::SocketCount() const + { + return iPeerSocketArray->Count(); + } + +// ----------------------------------------------------------------------------- +// CSocketRouter::SetHostSocketL +// ----------------------------------------------------------------------------- +// +void CSocketRouter::SetHostSocketL( MSocket* aSocket ) + { + DEBUG_PRINT( DEBUG_STRING( + "CSocketRouter::SetHostSocketL()" ) ); + + iHostSocket = aSocket; + iHostSocket->SetObserver( this ); + } + + +// ----------------------------------------------------------------------------- +// CSocketRouter::RunL +// ----------------------------------------------------------------------------- +// +void CSocketRouter::RunL() + { + WriteQueueL(); + } + +// ----------------------------------------------------------------------------- +// CSocketRouter::DoCancel +// ----------------------------------------------------------------------------- +// +void CSocketRouter::DoCancel() + { + } + +// ----------------------------------------------------------------------------- +// CSocketRouter::StartRouting +// ----------------------------------------------------------------------------- +// +void CSocketRouter::StartRouting() + { + DEBUG_PRINT( DEBUG_STRING( "CSocketRouter::StartRouting()" ) ); + + iRouting = ETrue; + iHostSocket->IssueRead(); + TInt peerSocketArrayCount = iPeerSocketArray->Count(); + for ( TInt i = 0;i < peerSocketArrayCount; i++ ) + { + CSocket* socket = iPeerSocketArray->At( i ); + socket->IssueRead(); + } + IssueHandleQueue(); + } + +// ----------------------------------------------------------------------------- +// CSocketRouter::IssueHandleQueue +// ----------------------------------------------------------------------------- +// +void CSocketRouter::IssueHandleQueue() + { + if ( !IsActive() ) + { + TRequestStatus* status = &iStatus; + User::RequestComplete( status, KErrNone ); + + SetActive(); + } + } + + +// ----------------------------------------------------------------------------- +// CSocketRouter::StopRouting +// ----------------------------------------------------------------------------- +// +void CSocketRouter::StopRouting() + { + DEBUG_PRINT( DEBUG_STRING( "CSocketRouter::StopRouting()" ) ); + + Cancel(); //If HandleQueue is issued + + iRouting = EFalse; + if ( iHostSocket ) + { + iHostSocket->Cancel(); + } + TInt peerSocketArrayCount = iPeerSocketArray->Count(); + for ( TInt i = 0;i < peerSocketArrayCount; i++ ) + { + CSocket* socket = iPeerSocketArray->At( i ); + socket->Cancel(); + } + } + + +// ----------------------------------------------------------------------------- +// CSocketRouter::IsRouting +// ----------------------------------------------------------------------------- +// +TBool CSocketRouter::IsRouting() const + { + return iRouting; + } + +// ----------------------------------------------------------------------------- +// CSocketRouter::ResetQueue +// ----------------------------------------------------------------------------- +// +void CSocketRouter::ResetQueue() + { + iWriteEventArray->ResetAndDestroy(); + } + +// ----------------------------------------------------------------------------- +// CSocketRouter::SendCloseTCPConnection +// ----------------------------------------------------------------------------- +// +void CSocketRouter::SendCloseTCPConnection( TUint aPort ) + { + DEBUG_PRINT( DEBUG_STRING( "CSocketRouter::SendCloseTCPConnection" ) ); + + iProtocolTCP->SendCloseTCPConnection( *iHostSocket, aPort ); + } + +// ----------------------------------------------------------------------------- +// CSocketRouter::WriteCorrectFrame +// ----------------------------------------------------------------------------- +// +void CSocketRouter::WriteCorrectFrameL( TProtocolDesc aProtocolDesc, + TUint aPeerPort, + TUint aOriginalPort, + const TDesC8& aData ) + { + DEBUG_PRINT( DEBUG_STRING( + "CSocketRouter::WriteCorrectFrameL(), protocol = %d" ), + aProtocolDesc.iProtocol ); + + MBPProtocol* protocol; + + if ( aProtocolDesc.iProtocol == KProtocolInetUdp ) + { + // UDP frame + DEBUG_PRINT( DEBUG_STRING( + "CSocketRouter::WriteCorrectFrameL(), UDP" ) ); + protocol = iProtocolUDP; + } + else + { + // TCP frame + DEBUG_PRINT( DEBUG_STRING( + "CSocketRouter::WriteCorrectFrameL(), TCP" ) ); + protocol = iProtocolTCP; + } + + protocol->WriteFrameL( + *iHostSocket, aPeerPort, + aOriginalPort, aData ); + } + +// ----------------------------------------------------------------------------- +// CSocketRouter::DataReceivedL +// ----------------------------------------------------------------------------- +// +void CSocketRouter::DataReceivedL( const MSocket* aSocket, const TDesC8& aData ) + { + DEBUG_PRINT( DEBUG_STRING( "CSocketRouter::DataReceivedL()" ) ); + + __ASSERT_ALWAYS( aSocket, Panic( IPProxyEngineNullSocket ) ); + + if ( iRouting ) + { + //Route all data received from the host socket to protocol data handler. + if ( aSocket == iHostSocket ) + { + // join the previous buffer if there's something left + TInt neededLength = iReceiveBuffer->Length() + aData.Length(); + HBufC8* joinedBuffers = HBufC8::NewLC( neededLength ); + TPtr8 joinedBuffersPtr( joinedBuffers->Des() ); + joinedBuffersPtr.Append( *iReceiveBuffer ); + joinedBuffersPtr.Append( aData ); + + // Check if there's a protocol that can handle this message + TInt length = 0; // length of the full msg + TInt startPos = 0; // where the msg prefix starts + TBool msgHandled = EFalse; + TInt protCount = iProtocolArray->Count(); + + for ( TInt i = 0; i < protCount && !msgHandled; i++ ) + { + msgHandled = iProtocolArray->At( i )->HandleReceivedDataL( + joinedBuffersPtr, + startPos, + length ); + } + if ( msgHandled ) + { + if ( length > 0 ) + { + // Length is set only when whole msg is processed + // and correct. + // Store the rest of the msg for the next round + delete iReceiveBuffer; + iReceiveBuffer = NULL; + iReceiveBuffer = + joinedBuffers->Mid( startPos + length ).AllocL(); + CleanupStack::PopAndDestroy( joinedBuffers ); + + if ( iReceiveBuffer->Length() > 0 ) + { + // Start again to process the rest + iState = EStateWaitingFrameStart; + DataReceivedL( aSocket, KNullDesC8 ); + } + } + else + { + delete iReceiveBuffer; + iReceiveBuffer = joinedBuffers; + CleanupStack::Pop( joinedBuffers ); + } + } + else + { + // Could not find a valid prefix for this protocol + // store data for the next round + HBufC8* newBuffer = HBufC8::NewLC( KMaxPrefixLength -1 ); + TPtr8 newBufferPtr( newBuffer->Des() ); + if ( joinedBuffersPtr.Length() > 3 ) + { + newBufferPtr = + joinedBuffersPtr.Right( KMaxPrefixLength - 1 ); + } + else + { + iState = EStateWaitingFrameStart; + newBufferPtr = joinedBuffersPtr; + } + delete iReceiveBuffer; + iReceiveBuffer = newBuffer; + CleanupStack::Pop( newBuffer ); + CleanupStack::PopAndDestroy( joinedBuffers ); + return; + } + } + else //Route all data received from any other socket to frame writer. + { + WriteQueueL(); + TProtocolDesc info; + aSocket->SocketInfo( info ); + WriteCorrectFrameL( + info, aSocket->RemotePort(), + aSocket->LocalPort(), aData ); + + } + } + else + { + //Add to queue + TProtocolDesc desc; + aSocket->SocketInfo( desc ); + iWriteEventArray->AppendL( CWriteEvent::NewLC( desc, + aData, aSocket->RemotePort(), aSocket->LocalPort() ) ); + + DEBUG_PRINT( DEBUG_STRING( + "Add to queue: peerPort: %d. origPort: %d" ), + aSocket->RemotePort(), + aSocket->LocalPort() ); + + CleanupStack::Pop(); // CWriteEvent + } + } + +// ----------------------------------------------------------------------------- +// CSocketRouter::WriteQueueL +// ----------------------------------------------------------------------------- +// +void CSocketRouter::WriteQueueL() + { + DEBUG_PRINT( DEBUG_STRING( "CSocketRouter::WriteQueueL()" ) ); + + TInt writeEventArrayCount = iWriteEventArray->Count(); + for ( TInt i = 0; i < writeEventArrayCount; i++ ) + { + const CWriteEvent* writeEvent = iWriteEventArray->At( 0 ); + WriteCorrectFrameL( writeEvent->ProtocolDesc(), writeEvent->PeerPort(), + writeEvent->OriginalPort(), writeEvent->Data() ); + DEBUG_PRINT( DEBUG_STRING( + "WriteQueueL(): peerPort: %d. origPort: %d" ), + writeEvent->PeerPort(), + writeEvent->OriginalPort() ); + iWriteEventArray->Delete( 0 ); + delete writeEvent; + } + } + +// ----------------------------------------------------------------------------- +// CSocketRouter::ErrorL +// ----------------------------------------------------------------------------- +// +void CSocketRouter::ErrorL( const MSocket* aSocket, TInt aErrorCode ) + { + DEBUG_PRINT( DEBUG_STRING( "CSocketRouter::ErrorL()" ) ); + + iObserver->SocketRouterErrorL( aSocket, aErrorCode ); + } + +// ----------------------------------------------------------------------------- +// CSocketRouter::ObserverLeaved +// ----------------------------------------------------------------------------- +// +void CSocketRouter::ObserverLeaved( const MSocket* aSocket, TInt aLeaveCode ) + { + iObserver->ObserverLeaved( aSocket, aLeaveCode ); + } + +// ----------------------------------------------------------------------------- +// CSocketRouter::DisconnectedL +// ----------------------------------------------------------------------------- +// +void CSocketRouter::DisconnectedL( const MSocket* aSocket ) + { + DEBUG_PRINT( DEBUG_STRING( "CSocketRouter::DisconnectedL()" ) ); + + if ( aSocket == iHostSocket ) + { + DEBUG_PRINT( DEBUG_STRING( "aSocket == iHostSocket" ) ); + iObserver->HostDisconnectedL( aSocket ); + iHostSocket = NULL; + } + else + { + TInt peerSocketArrayCount = iPeerSocketArray->Count(); + for ( TInt i = 0;i < peerSocketArrayCount; i++ ) + { + CSocket* socket = iPeerSocketArray->At( i ); + if ( socket == aSocket ) + { + SendCloseTCPConnection( socket->RemotePort() ); + iObserver->PeerDisconnectedL( socket ); + RemovePeerSocket( i ); + break; + } + } + } + } + +// ----------------------------------------------------------------------------- +// CSocketRouter::FrameStarted +// ----------------------------------------------------------------------------- +// +void CSocketRouter::FrameStarted() + { + iState = EStateFrameStartFound; + } + +// ----------------------------------------------------------------------------- +// CSocketRouter::TCPFrameParsedL +// ----------------------------------------------------------------------------- +// +void CSocketRouter::TCPFrameParsedL( TUint aPort, const TDesC8& aData ) + { + DEBUG_PRINT( DEBUG_STRING( "CSocketRouter::TCPFrameParsedL()" ) ); + DEBUG_PRINT( DEBUG_STRING( " aPort=%d" ), aPort ); + DEBUG_PRINT( DEBUG_STRING( " aData.Length=%d" ), aData.Length() ); + + for ( TInt i = 0; i < iPeerSocketArray->Count(); i++ ) + { + CSocket* socket = iPeerSocketArray->At( i ); + if ( socket->RemotePort() == aPort && !socket->IsUDP() ) + { + socket->WriteL( aData ); + break; //for + } + } + } + +// ----------------------------------------------------------------------------- +// CSocketRouter::OpenLocalTCPConnectionL +// ----------------------------------------------------------------------------- +// +void CSocketRouter::OpenLocalTCPConnectionL( TUint aPort ) + { + DEBUG_PRINT( DEBUG_STRING( "OpenLocalTCPConnectionL, port = %d" ), aPort ); + if ( iObserver ) + { + iObserver->OpenLocalTCPConnectionL( aPort ); + } + } + +// ----------------------------------------------------------------------------- +// CSocketRouter::OpenListeningTCPConnectionL +// ----------------------------------------------------------------------------- +// +void CSocketRouter::OpenListeningTCPConnectionL( TUint aPort ) + { + DEBUG_PRINT( DEBUG_STRING( "OpenListeningTCPConnectionL, port = %d" ), aPort ); + if ( iObserver ) + { + iObserver->OpenListeningTCPConnectionL( aPort ); + } + } + +// ----------------------------------------------------------------------------- +// CSocketRouter::CloseTCPConnection +// ----------------------------------------------------------------------------- +// +void CSocketRouter::CloseTCPConnectionL( TUint aPort ) + { + DEBUG_PRINT( DEBUG_STRING( "CloseTCPConnection, port = %d" ), aPort ); + + // Close the socket if it exists + CArrayPtr* socketArrayForDestroy = new (ELeave) CArrayPtrFlat ( 10 ); + CleanupStack::PushL(socketArrayForDestroy); + TInt index = FindPeerSocket( aPort ); + while ( index > -1 ) + { + socketArrayForDestroy->AppendL(iPeerSocketArray->At( index )); + iPeerSocketArray->Delete(index); + index = FindPeerSocket( aPort ); + } + socketArrayForDestroy->ResetAndDestroy(); + CleanupStack::PopAndDestroy(socketArrayForDestroy); + + if ( iObserver ) + { + iObserver->CloseTCPConnection( aPort ); + } + } + +// ----------------------------------------------------------------------------- +// CSocketRouter::CloseAllTCPConnections +// ----------------------------------------------------------------------------- +// +void CSocketRouter::CloseAllTCPConnections() + { + DEBUG_PRINT( DEBUG_STRING( "CloseAllTCPConnections" ) ); + if ( iObserver ) + { + iObserver->CloseAllTCPConnections(); + } + } + +// ----------------------------------------------------------------------------- +// CSocketRouter::UDPFrameParsedL +// ----------------------------------------------------------------------------- +// +void CSocketRouter::UDPFrameParsedL( TUint aPort, const TDesC8& aData ) + { + DEBUG_PRINT( DEBUG_STRING( "CSocketRouter::UDPFrameParsedL()" ) ); + DEBUG_PRINT( DEBUG_STRING( " aPort=%d" ), aPort ); + DEBUG_PRINT( DEBUG_STRING( " aData.Length=%d" ), aData.Length() ); + iUDPSender->IssueWriteL( aPort, aData ); + } + +// ----------------------------------------------------------------------------- +// CSocketRouter::ProtocolErrorL +// ----------------------------------------------------------------------------- +// +void CSocketRouter::ProtocolErrorL( + TInt aErrorCode, const TDesC8& /* aReceivedData */ ) + { + DEBUG_PRINT( DEBUG_STRING( "CSocketRouter::ProtocolErrorL()" ) ); + DEBUG_PRINT( DEBUG_STRING( " aErrorCode=%d" ), aErrorCode ); + + if ( iObserver ) + { + iObserver->SocketRouterErrorL( iHostSocket, aErrorCode ); + } + } + +// ----------------------------------------------------------------------------- +// CSocketRouter::UDPSenderErrorL +// ----------------------------------------------------------------------------- +// +void CSocketRouter::UDPSenderErrorL( TInt aErrorCode ) + { + DEBUG_PRINT( DEBUG_STRING( + "CSocketRouter::UDPSenderErrorL(), error code %d" ), aErrorCode ); + iObserver->SocketRouterErrorL( NULL, aErrorCode ); + } + +// ----------------------------------------------------------------------------- +// CSocketRouter::UDPSenderLeavedL +// ----------------------------------------------------------------------------- +// +void CSocketRouter::UDPSenderLeavedL( TInt aLeaveCode ) + { + DEBUG_PRINT( DEBUG_STRING( + "CSocketRouter::UDPSenderLeavedL(), leavecode %d" ), aLeaveCode ); + iObserver->ObserverLeaved( NULL, aLeaveCode ); + } + +// End of File