diff -r 000000000000 -r 094583676ce7 IMPSengine/ImpsIpCirWatcher/ImpsTcpIpCirWatcher/src/TcpCirWatcher.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/IMPSengine/ImpsIpCirWatcher/ImpsTcpIpCirWatcher/src/TcpCirWatcher.cpp Thu Dec 17 08:41:52 2009 +0200 @@ -0,0 +1,1011 @@ +/* +* Copyright (c) 2005 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: Tcp CirWatcher +* +* +*/ + + +// INCLUDE FILES +#include +#include +#ifdef _DEBUG +#include +#endif +#include +#include +#include "TcpCirWatcher.h" +#include "CirWatcherDefines.h" +#include "TcpCirWatcherTimer.h" + +// ================= MEMBER FUNCTIONS ======================= +// + + +// ---------------------------------------------------------- +// CTcpCirWatcher::CTcpCirWatcher +// +// ---------------------------------------------------------- +// +CTcpCirWatcher::CTcpCirWatcher( const TInt aPingInterval, + MImpsCirReceiver& aCirReceiver, + MMsgConnManager& aConnManager ) : + iPingInterval( aPingInterval ), + iCirReceiver( aCirReceiver ), + iConnectionManager( aConnManager ), + iClientRequestPending( EFalse ), + iWatcherStatus( EImpsCIRWatcherIdle ), + iLastGoodWatcherStatus( EImpsCIRWatcherUnknown ) + + { + } + +// ---------------------------------------------------------- +// CTcpCirWatcher::FinishConstructL +// +// ---------------------------------------------------------- +// +CTcpCirWatcher* CTcpCirWatcher::NewL( TTcpWatcherParameters* aParameters ) + { + CTcpCirWatcher* self = new ( ELeave ) CTcpCirWatcher( aParameters->iPingInterval, + aParameters->iCirReceiver, + aParameters->iConnManager ); + CleanupStack::PushL( self ); + self->ConstructL(); + CleanupStack::Pop(); + return self; + } + +// ---------------------------------------------------------- +// CImpsConnectionMonitor::ConstructL +// +// ---------------------------------------------------------- +// +void CTcpCirWatcher::ConstructL() + { +#ifdef _DEBUG + DeleteLogFileL(); +#endif + iWatcherTimer = CTcpCirWatcherTimer::NewL( this ); + CActiveScheduler::Add( this ); + } + +// ---------------------------------------------------- +// CTcpCirWatcher::~CTcpCirWatcher +// Destructor +// ---------------------------------------------------- +// +CTcpCirWatcher::~CTcpCirWatcher() + { +#ifdef _DEBUG + WriteToLog( _L8( "CTcpCirWatcher::~CTcpCirWatcher()" ) ); +#endif + Cancel(); + delete iPacket; + delete iWatcherTimer; + delete iCSPSessionID; + delete iSocketSendBuffer; + delete iAddressBuffer; + iTCPCIRSocket.Close(); +#ifdef _DEBUG + WriteToLog( _L8( " Destructor ended" ) ); +#endif + } + +// ---------------------------------------------------------- +// CTcpCirWatcher::DeleteLogFileL() +// +// ---------------------------------------------------------- +// +void CTcpCirWatcher::DeleteLogFileL() + { + RFs session; + User::LeaveIfError( session.Connect() ); + CFileMan* manager = CFileMan::NewL( session ); + manager->Delete( _L( "C:\\Logs\\ImpsTcpWatcher\\*.*" ) ); + session.Close(); + delete manager; + manager = NULL; + } + +// ---------------------------------------------------- +// CTcpCirWatcher::SetPingInterval +// +// ---------------------------------------------------- +// +void CTcpCirWatcher::SetPingInterval( const TInt aPingInterval ) + { +#ifdef _DEBUG + WriteToLog( _L8( "CTcpCirWatcher::SetPingInterval() Interval: %d" ), aPingInterval ); +#endif + if ( aPingInterval > 0 ) + iPingInterval = aPingInterval; + } + +// ---------------------------------------------------- +// CTcpCirWatcher::StartTCPWatcherL +// +// ---------------------------------------------------- +// +void CTcpCirWatcher::StartTCPWatcherL( TRequestStatus& aStatus, + const TUint aServerPort, + const TDesC& aServerAddress, + const TDesC8& aCSPSessionID ) + { +#ifdef _DEBUG + HBufC8* id = HBufC8::NewL( aCSPSessionID.Length() ); + TPtr8 idPtr( id->Des() ); + idPtr.Copy( aCSPSessionID ); + TBuf8<200> eightBuf; + eightBuf.Copy( aServerAddress ); + WriteToLog( _L8( "CTcpCirWatcher::StartTCPWatcher()" ) ); + WriteToLog( _L8( " Server: %S" ), &eightBuf ); + WriteToLog( _L8( " Port: %d" ), aServerPort ); + WriteToLog( _L8( " Session ID: %S" ), &idPtr ); + delete id; + id = NULL; +#endif + aStatus = KRequestPending; + iClientStatus = &aStatus; + if ( iWatcherStatus == EImpsCIRWatcherIdle ) + { + Reset(); + SetConnectionDetailsL( aServerAddress, aCSPSessionID, aServerPort ); + if ( iConnectionManager.Status() ) + { + iClientRequestPending = ETrue; + iConnectionManager.AddEventSubscriberL( this ); + //Might be DNS name, must make sure we get an IP address + User::LeaveIfError( iHostResolver.Open( iConnectionManager.SocketSession(), + KAfInet, KProtocolInetUdp, + iConnectionManager.Connection() ) ); + iHostResolver.GetByName( *iAddressBuffer, iHostAddressDnsEntry, iStatus ); + iWatcherStatus = EImpsCIRWatcherAwaitingDNS; + SetActive(); +#ifdef _DEBUG + WriteToLog( _L8( " Waiting for host resolver to complete" ) ); +#endif + } + else + { +#ifdef _DEBUG + WriteToLog( _L8( " Bearer is not ready, complete with KErrCouldNotConnect." ) ); +#endif + User::RequestComplete( iClientStatus, KErrCouldNotConnect ); + } + } + else + { +#ifdef _DEBUG + WriteToLog( _L8( " Watcher is not ready, complete with KErrNotReady." ) ); +#endif + User::RequestComplete( iClientStatus, KErrNotReady ); + } + } + +// ---------------------------------------------------- +// CTcpCirWatcher::SetConnectionDetails +// +// ---------------------------------------------------- +// +void CTcpCirWatcher::SetConnectionDetailsL( const TDesC& aServerAddress, + const TDesC8& aCSPSessionID, + const TUint aServerPort ) + { +#ifdef _DEBUG + WriteToLog( _L8( "CTcpCirWatcher::SetConnectionDetails" ) ); +#endif + iServerPort = aServerPort; + iCSPSessionID = HBufC8::NewL( aCSPSessionID.Length() ); + iCSPSessionID->Des().Copy( aCSPSessionID ); + iAddressBuffer = HBufC::NewL( aServerAddress.Length() ); + iAddressBuffer->Des().Copy( aServerAddress ); + } + + +// --------------------------------------------------------- +// CTcpCirWatcher::Reset +// +// --------------------------------------------------------- +// +void CTcpCirWatcher::Reset() + { +#ifdef _DEBUG + WriteToLog( _L8( "CTcpCirWatcher::Reset()" ) ); +#endif + delete iCSPSessionID; + iCSPSessionID = NULL; + delete iAddressBuffer; + iAddressBuffer = NULL; + iPingRetries = 0; + iConnRetries = 0; + } + +// ---------------------------------------------------- +// CTcpCirWatcher::StopTCPWatcher +// Destructor +// ---------------------------------------------------- +// +void CTcpCirWatcher::StopTCPWatcher() + { +#ifdef _DEBUG + WriteToLog( _L8( "StopTCPWatcher()" ) ); +#endif + if ( iWatcherStatus == EImpsCIRWatcherAwaitingDNS ) + { +#ifdef _DEBUG + WriteToLog( _L8( " Status is EImpsCIRWatcherAwaitingDNS, cancel resolver" ) ); +#endif + iHostResolver.Cancel(); + //If the client requests another start inside the scheduler + //loop that completes the previous Start() request, the second + //request will fail with KErrNotReady, since this component must + //wait for the host resolver to return in RunL(). The method will + //alter the state of this component to EImpsCIRWatcherIdle. + //iClientRequestPending = EFalse; + //iWatcherStatus = EImpsCIRWatcherStopping; + //User::RequestComplete( iClientStatus, KErrCancel ); +#ifdef _DEBUG + WriteToLog( _L8( " Resolver cancelled, request not completed" ) ); +#endif + } + else + { + if ( iWatcherStatus != KImpsCIRWatcherStopping && + iWatcherStatus != EImpsCIRWatcherIdle ) + { + iWatcherTimer->Cancel(); + if ( iConnectionManager.NumberOfActiveConns() > 0 ) + { + + // Socket Connection is getting disconnected and closed when Ending the PacketDataConnection + // if active connection is not exists not required to cancel. + iTCPCIRSocket.CancelAll(); + } + if ( iClientRequestPending && + ( iWatcherStatus == EImpsCIRWatcherConnectingTCPSocket || + iWatcherStatus == EImpsCIRWatcherSendingHELOMessage || + iWatcherStatus == EImpsCIRWatcherReceivingHELOResponse ) ) + { +#ifdef _DEBUG + WriteToLog( _L8( " A request is pending, complete with KErrCancel" ) ); +#endif + User::RequestComplete( iClientStatus, KErrCancel ); + iWatcherStatus = EImpsCIRWatcherIdle; + } + else + iWatcherStatus = EImpsCIRWatcherStopping; + iConnectionManager.RemoveEventSubscriber( this ); + } + else + { +#ifdef _DEBUG + WriteToLog( _L8( " Status is %d" ), iWatcherStatus ); +#endif + } + } + } + +// ---------------------------------------------------- +// CTcpCirWatcher::WatcherStatus +// +// ---------------------------------------------------- +// +TUint CTcpCirWatcher::WatcherStatus() const + { +#ifdef _DEBUG + WriteToLog( _L8( "CTcpCirWatcher::WatcherStatus()" ) ); +#endif + return iWatcherStatus; + } + +#ifdef _DEBUG + +// ---------------------------------------------------- +// CTcpCirWatcher::WriteToLog +// +// ---------------------------------------------------- +// +void CTcpCirWatcher::WriteToLog( TRefByValue aFmt, ... ) + { + VA_LIST list; + VA_START( list, aFmt ); + TBuf8 buf; + buf.FormatList( aFmt, list ); + RFileLogger::Write( KTcpLogDir, KTcpWatcherLogFile, EFileLoggingModeAppend, buf ); + } + +#endif + +// --------------------------------------------------------- +// CTcpCirWatcher::WaitForHELOResponse +// +// --------------------------------------------------------- +// +void CTcpCirWatcher::WaitForHELOResponse() + { +#ifdef _DEBUG + WriteToLog( _L8( "CTcpCirWatcher::WaitForHELOResponse()" ) ); +#endif + iSocketReceiveBuffer.Zero(); + iStatus = KRequestPending; + iWatcherStatus = EImpsCIRWatcherReceivingHELOResponse; + iTCPCIRSocket.RecvOneOrMore( iSocketReceiveBuffer, 0, iStatus, iRecvLength ); + iWatcherTimer->ActivateTimer( 10000000, KWaitForHELOResponse ); + SetActive(); + } + +// --------------------------------------------------------- +// CTcpCirWatcher::ConnectTCPSocket +// +// --------------------------------------------------------- +// +void CTcpCirWatcher::ConnectTCPSocketL() + { +#ifdef _DEBUG + WriteToLog( _L8( "CTcpCirWatcher::ConnectTCPSocket() iConnRetries: %d" ), iConnRetries ); +#endif + iWatcherStatus = EImpsCIRWatcherConnectingTCPSocket; + User::LeaveIfError( iTCPCIRSocket.Open( iConnectionManager.SocketSession(), + KAfInet, KSockStream, KProtocolInetTcp, + iConnectionManager.Connection() ) ); + if ( iConnRetries < KMaxNumberOfConnAttempts ) + { + iTCPCIRSocket.Connect( iSocketAddress, iStatus ); + iConnRetries++; + SetActive(); + iWatcherTimer->ActivateTimer( 20000000, KWaitForFirstConnectAttempt ); + } + else + { + iTCPCIRSocket.Close(); + iCirReceiver.HandleErrorL( KErrCouldNotConnect, EImpsTcpCir ); + iWatcherStatus = EImpsCIRWatcherIdle; + iConnectionManager.RemoveEventSubscriber( this ); +#ifdef _DEBUG + WriteToLog( _L8( " Connect retry limit encountered, stop." ) ); +#endif + } + } + +// --------------------------------------------------------- +// CTcpCirWatcher::SendHELOMessageL +// +// --------------------------------------------------------- +// +void CTcpCirWatcher::SendHELOMessageL() + { +#ifdef _DEBUG + WriteToLog( _L8( "CTcpCirWatcher::SendHELOMessageL()" ) ); +#endif + iWatcherStatus = EImpsCIRWatcherSendingHELOMessage; + delete iSocketSendBuffer; + iSocketSendBuffer = NULL; + iSocketSendBuffer = HBufC8::NewL( 7 + iCSPSessionID->Length() ); + iSocketSendBuffer->Des().Copy( KHELOMessage ); + iSocketSendBuffer->Des().Append( *iCSPSessionID ); + iSocketSendBuffer->Des().Append( KMessageTermination ); + iStatus = KRequestPending; + iTCPCIRSocket.Write( iSocketSendBuffer->Des(), iStatus ); + iWatcherTimer->ActivateTimer( 10000000, KWaitForHELOSendAttempt ); + SetActive(); + } + +// --------------------------------------------------------- +// CTcpCirWatcher::SendPing +// +// --------------------------------------------------------- +// +void CTcpCirWatcher::SendPingL() + { +#ifdef _DEBUG + WriteToLog( _L8( "CTcpCirWatcher::SendPing() iPingRetries: %d/%d" ), iPingRetries, KMaxNumberOfPingAttempts ); +#endif + if ( iPingRetries < KMaxNumberOfPingAttempts ) + { + iWatcherStatus = EImpsCIRWatcherSendingPINGRequest; + iTCPCIRSocket.Write( KImpsPingData, iStatus ); + iPingRetries++; + SetActive(); + } + else + { + //The server is down, close the socket and report error + iTCPCIRSocket.Close(); + iCirReceiver.HandleErrorL( KErrDisconnected, EImpsTcpCir ); + iWatcherStatus = EImpsCIRWatcherIdle; + iConnectionManager.RemoveEventSubscriber( this ); +#ifdef _DEBUG + WriteToLog( _L8( " Ping retry limit encountered, stop." ) ); +#endif + } + } + +// --------------------------------------------------------- +// CTcpCirWatcher::RunL +// +// --------------------------------------------------------- +// +void CTcpCirWatcher::RunL() + { +#ifdef _DEBUG + WriteToLog( _L8( "CTcpCirWatcher::RunL(), iStatus: %d" ), iStatus ); +#endif + iWatcherTimer->Cancel(); + switch ( iWatcherStatus ) + { + case EImpsCIRWatcherAwaitingDNS: + if ( iStatus == KErrNone ) + { + iSocketAddress = TInetAddr( iHostAddressDnsEntry().iAddr ); +#ifdef _DEBUG + TBuf<200> buffer; + TBuf8<200> eightBuffer; + iSocketAddress.Output( buffer ); + eightBuffer.Copy( buffer ); + WriteToLog( _L8( " IP address resolved (%S), starting to connect." ), &eightBuffer ); +#endif + iSocketAddress.SetPort( iServerPort ); + iHostResolver.Close(); + ConnectTCPSocketL(); + } + else + { +#ifdef _DEBUG + WriteToLog( _L8( " IP address resolving failed, complete with %d." ), iStatus.Int() ); +#endif + iConnectionManager.RemoveEventSubscriber( this ); + User::RequestComplete( iClientStatus, iStatus.Int() ); + iWatcherStatus = EImpsCIRWatcherIdle; + } + break; + default: + if ( iStatus == KErrNone ) + HandleRequestCompletionL(); + else + HandleErrorL( iStatus.Int() ); + } + } + +// --------------------------------------------------------- +// CTcpCirWatcher::HandleRequestCompletionL +// +// --------------------------------------------------------- +// +void CTcpCirWatcher::HandleRequestCompletionL() + { + switch ( iWatcherStatus ) + { + case EImpsCIRWatcherConnectingTCPSocket: +#ifdef _DEBUG + WriteToLog( _L8( " TCP Socket is connected, starting to send HELO." ) ); +#endif + iConnRetries = 0; + SendHELOMessageL(); + break; + case EImpsCIRWatcherSendingHELOMessage: +#ifdef _DEBUG + WriteToLog( _L8( " HELO Message sent, waiting for response." ) ); +#endif + WaitForHELOResponse(); + break; + case EImpsCIRWatcherReceivingHELOResponse: +#ifdef _DEBUG + WriteToLog( _L8( " Server responded with the message: %S" ), &iSocketReceiveBuffer ); +#endif + if ( iClientRequestPending ) + { +#ifdef _DEBUG + WriteToLog( _L8( " Completing request & starting to PING the server in %d second intervals." ), iPingInterval ); +#endif + User::RequestComplete( iClientStatus, KErrNone ); + iClientRequestPending = EFalse; + } + WaitForNextPing(); + break; + case EImpsCIRWatcherSendingPINGRequest: +#ifdef _DEBUG + WriteToLog( _L8( " Ping sent succesfully, wait for response" ) ); +#endif + iWatcherStatus = EImpsCIRWatcherWaitingPINGResponse; + iWatcherTimer->ActivateTimer( 5000000, KWaitForPingReply ); + ReceiveFromSocket(); + break; + case EImpsCIRWatcherWaitingPINGResponse: +#ifdef _DEBUG + WriteToLog( _L8( " Server responded to ping with the message: %S" ), &iSocketReceiveBuffer ); +#endif + if ( iSocketReceiveBuffer.Find( KImpsPingResponseWVCI ) == 0 ) + ReportCirL(); + else if ( iSocketReceiveBuffer.Find( KImpsPingResponseOK ) == 0 ) +#ifdef _DEBUG + WriteToLog( _L8( " Server is OK." ) ) +#endif + ; + else + //Should this case include a reset/closure of the connection? + //Clearly the received data does not comply to any of + //the rules set by the OMA IMPS specification. +#ifdef _DEBUG + WriteToLog( _L8( " Do not talk to me like that.. learn some manners!" ) ); +#endif + ; + iPingRetries = 0; + WaitForNextPing(); + break; + case KImpsCIRWatcherReceivingFromSocket: +#ifdef _DEBUG + WriteToLog( _L8( " Server sent: %S" ), &iSocketReceiveBuffer ); +#endif + if ( iSocketReceiveBuffer.Find( KImpsPingResponseWVCI ) == 0 ) + ReportCirL(); + if ( iWatcherStatus == KImpsCIRWatcherReceivingFromSocket ) + WaitForNextPing(); + break; + default: +#ifdef _DEBUG + WriteToLog( _L8( " Default case, something's wrong." ) ); +#endif + break; + } + } + +// --------------------------------------------------------- +// CTcpCirWatcher::HandleErrorL +// +// --------------------------------------------------------- +// +void CTcpCirWatcher::HandleErrorL( const TInt aError ) + { +#ifdef _DEBUG + WriteToLog( _L8( " CTcpCirWatcher::HandleErrorL(), error: %d iWatcherStatus: %d" ), aError, iWatcherStatus ); +#endif + switch ( iWatcherStatus ) + { + case EImpsCIRWatcherConnectingTCPSocket: + case EImpsCIRWatcherSendingHELOMessage: + case EImpsCIRWatcherReceivingHELOResponse: +#ifdef _DEBUG + WriteToLog( _L8( " Error when establishing connection to CIR Server: %d Client pending: %d" ), iStatus.Int(), iClientRequestPending ); +#endif + if ( iClientRequestPending ) + { + iCompletionCode = iStatus == KErrCancel ? iCompletionCode : aError; + CompleteWithError( iCompletionCode ); + } + else + iWatcherTimer->ActivateTimer( 10000000, KWaitForNextConnectAttempt ); + break; + case EImpsCIRWatcherReceivingFromSocket: + if ( aError == KErrCancel ) + { +#ifdef _DEBUG + WriteToLog( _L8( " Time to send the next ping request" ) ); +#endif + SendPingL(); + } + else + { +#ifdef _DEBUG + WriteToLog( _L8( " Socket read returned with error" ) ); +#endif + DetermineSocketStateL( aError ); + } + break; + case EImpsCIRWatcherSendingPINGRequest: +#ifdef _DEBUG + WriteToLog( _L8( " Error when sending PING: %d, try again." ), aError ); +#endif + SendPingL(); + break; + case EImpsCIRWatcherWaitingPINGResponse: +#ifdef _DEBUG + WriteToLog( _L8( " Error when receiving PING response: %d, check socket state" ), aError ); +#endif + DetermineSocketStateL( aError ); + break; + case EImpsCIRWatcherStopping: + //Client has called StopTCPWatcher() + if ( iStatus == KErrCancel ) + { +#ifdef _DEBUG + WriteToLog( _L8( " Watcher shutdown requested" ) ); +#endif + if ( iClientRequestPending ) + { +#ifdef _DEBUG + WriteToLog( _L8( " A request is pending, complete" ) ); +#endif + User::RequestComplete( iClientStatus, KErrCancel ); + } + iTCPCIRSocket.Close(); + iHostResolver.Close(); + iWatcherStatus = EImpsCIRWatcherIdle; + } + break; + default: +#ifdef _DEBUG + WriteToLog( _L8( " Default case, do nothing" ), aError ); +#endif + break; + } + } + +// --------------------------------------------------------- +// CTcpCirWatcher::DetermineSocketStateL +// NOTE: Close()s the current socket and opens a new one in +// each case. The aError parameter is used only for debug info. +// Change this feature if needed, since for instance a socket +// receive operation may fail/time out, in which case the socket +// is most probably still as good as new. Closing a perfectly +// good socket should not consume resources that prodigiously. +// That might not, however, be the most elegant solution, but it +// works fine just the same... +// --------------------------------------------------------- +// +void CTcpCirWatcher::DetermineSocketStateL( const TInt aError ) + { +#ifdef _DEBUG + WriteToLog( _L8( " CTcpCirWatcher::DetermineSocketStateL()" ) ); + switch ( aError ) + { + //The socket has been closed for some reason, try to connect again + case KErrEof: + case KErrDisconnected: + WriteToLog( _L8( " The socket was disconnected, re-open." ) ); + break; + //Something seriously wrong, close the socket & open a new one + case KErrNotReady: + WriteToLog( _L8( " Socket cannot be re-used anymore, close & re-open." ) ); + break; + //Something timed out. + case KErrTimedOut: + WriteToLog( _L8( " Socket operation timed out, close & re-open." ) ); + break; + case KErrConnectionTerminated: + WriteToLog( _L8( " Socket Connection Terminated (Received KErrConnectionTerminated (-17210) )" ) ); + break; + default: + WriteToLog( _L8( " Default case - Error: %d" ), aError ); + break; + } +#endif + if ( aError == KErrConnectionTerminated ) + { + // KErrConnectionTerminated = -17210 is declared in es_sock.h + // Received this error when ending the packed data connection. in this case not required to connect again. + // if received in other situations other than EndPacketDataConnection, may need to connect again + iTCPCIRSocket.Close(); +#ifdef _DEBUG + WriteToLog( _L8( "Received Socket Connection Terminated Error - Closed the Socket Connection " ) ); +#endif + } + else + { + iTCPCIRSocket.Close(); + ConnectTCPSocketL(); + } + } + +// --------------------------------------------------------- +// CTcpCirWatcher::WaitForNextPing +// +// --------------------------------------------------------- +// +void CTcpCirWatcher::WaitForNextPing() + { +#ifdef _DEBUG + WriteToLog( _L8( "CTcpCirWatcher::WaitForNextPing()" ) ); +#endif + iWatcherTimer->ActivateTimer( iPingInterval * 1000000, KWaitForNextPing ); + iWatcherStatus = EImpsCIRWatcherReceivingFromSocket; + ReceiveFromSocket(); + } + +// --------------------------------------------------------- +// CTcpCirWatcher::CheckAddressValidity +// +// --------------------------------------------------------- +// +TBool CTcpCirWatcher::CheckAddressValidity() + { +#ifdef _DEBUG + WriteToLog( _L8( "CTcpCirWatcher::CheckAddressValidity()" ) ); +#endif + TInetAddr destination; + iTCPCIRSocket.RemoteName( destination ); + if ( destination == iSocketAddress ) + return ETrue; + else return EFalse; + } + +// --------------------------------------------------------- +// CTcpCirWatcher::ReportCirL +// +// --------------------------------------------------------- +// +void CTcpCirWatcher::ReportCirL() + { +#ifdef _DEBUG + WriteToLog( _L8( "CTcpCirWatcher::ReportCirL()" ) ); +#endif + //Just a precaution: if the address has changed somewhere + //along the line, our connection has been hijacked... + //Though any serious attacker would probably spoof the IP + //address, but it doesn't hurt to try. + if ( CheckAddressValidity() ) + iCirReceiver.CirReceivedL( iSocketReceiveBuffer, EImpsTcpCir ); + else + { +#ifdef _DEBUG + WriteToLog( _L8( " Wrong address, something's wrong. Close & report error" ) ); +#endif + iTCPCIRSocket.Close(); + iWatcherStatus = EImpsCIRWatcherIdle; + iCirReceiver.HandleErrorL( KErrAbort, EImpsTcpCir ); + } + } + +// --------------------------------------------------------- +// CTcpCirWatcher::ReceiveFromSocket +// +// --------------------------------------------------------- +// +void CTcpCirWatcher::ReceiveFromSocket() + { +#ifdef _DEBUG + WriteToLog( _L8( "CTcpCirWatcher::ReceiveFromSocket()" ) ); +#endif + TUint flags = 0; + iSocketReceiveBuffer.Zero(); + iStatus = KRequestPending; + iTCPCIRSocket.RecvOneOrMore( iSocketReceiveBuffer, flags, iStatus, iRecvLength ); + SetActive(); + } + +// ---------------------------------------------------- +// CTcpCirWatcher::CompleteWithError +// +// ---------------------------------------------------- +// +void CTcpCirWatcher::CompleteWithError( const TInt aError ) + { +#ifdef _DEBUG + WriteToLog( _L8( "CTcpCirWatcher::CompleteWithError()" ) ); +#endif + iWatcherTimer->Cancel(); + User::RequestComplete( iClientStatus, aError ); + iConnectionManager.RemoveEventSubscriber( this ); + iWatcherStatus = EImpsCIRWatcherIdle; + } + +// ---------------------------------------------------- +// CTcpCirWatcher::HandleTimerEventL +// +// ---------------------------------------------------- +// +void CTcpCirWatcher::HandleTimerEventL( const TUint aExpiredRequest ) + { +#ifdef _DEBUG + WriteToLog( _L8( "CTcpCirWatcher::HandleTimerEventL()" ) ); +#endif + switch ( aExpiredRequest ) + { + case KWaitForFirstConnectAttempt: +#ifdef _DEBUG + WriteToLog( _L8( " Socket connect timed out, complete with KErrTimedOut" ) ); +#endif + iCompletionCode = KErrTimedOut; + iTCPCIRSocket.CancelConnect(); + break; +#ifdef _DEBUG + case KWaitForNextPing: + //This will return in RunL() with KErrCancel + WriteToLog( _L8( " Socket read timed out, time to send the next ping" ) ); + iTCPCIRSocket.CancelRecv(); + break; + case KWaitForPingReply: + //This will return in RunL() with KErrCancel + WriteToLog( _L8( " Server didn't reply to ping, try again" ) ); + iTCPCIRSocket.CancelRecv(); + break; +#else + case KWaitForNextPing: + case KWaitForPingReply: + //This will return in RunL() with KErrCancel + iTCPCIRSocket.CancelRecv(); + break; +#endif + case KWaitForHELOResponse: + //The server didn't reply to the HELO response +#ifdef _DEBUG + WriteToLog( _L8( " Server didn't reply to HELO request, quit." ) ); +#endif + iTCPCIRSocket.CancelRecv(); + break; + case KWaitForHELOSendAttempt: + //Socket server is fooked... +#ifdef _DEBUG + WriteToLog( _L8( " Socket server didn't reply, quit." ) ); +#endif + iTCPCIRSocket.CancelWrite(); + break; + case KWaitForNextConnectAttempt: + ConnectTCPSocketL(); + break; + default: +#ifdef _DEBUG + WriteToLog( _L8( " Default case" ) ); +#endif + break; + } + } + +// --------------------------------------------------------- +// CTcpCirWatcher::DoCancel +// +// --------------------------------------------------------- +// +void CTcpCirWatcher::DoCancel() + { +#ifdef _DEBUG + WriteToLog( _L8( "CTcpCirWatcher::DoCancel() Status: %d" ), iWatcherStatus ); +#endif + iWatcherTimer->Cancel(); + switch ( iWatcherStatus ) + { + case EImpsCIRWatcherConnectingTCPSocket: + case EImpsCIRWatcherSendingHELOMessage: + case EImpsCIRWatcherReceivingHELOResponse: +#ifdef _DEBUG + WriteToLog( _L8( " Cancelling all socket operations" ) ); +#endif + iTCPCIRSocket.CancelAll(); + iWatcherStatus = EImpsCIRWatcherIdle; + break; + case EImpsCIRWatcherBearerSuspended: + iTCPCIRSocket.CancelAll(); + break; + default: +#ifdef _DEBUG + WriteToLog( _L8( " Default case, cancels all socket operations." ) ); +#endif + iTCPCIRSocket.CancelAll(); + break; + } + } + +// --------------------------------------------------------- +// CTcpCirWatcher::HandleBearerSuspension +// +// --------------------------------------------------------- +// +void CTcpCirWatcher::HandleBearerSuspension() + { +#ifdef _DEBUG + WriteToLog( _L8( "CTcpCirWatcher::HandleBearerSuspension()" ) ); +#endif + iLastGoodWatcherStatus = iWatcherStatus; + iWatcherStatus = EImpsCIRWatcherBearerSuspended; + Cancel(); + iWatcherTimer->Cancel(); + switch ( iLastGoodWatcherStatus ) + { + case EImpsCIRWatcherConnectingTCPSocket: + case EImpsCIRWatcherSendingHELOMessage: + case EImpsCIRWatcherReceivingHELOResponse: + //If we're connecting & client is pending, complete with error + if ( iClientRequestPending ) + { + User::RequestComplete( iClientStatus, KErrCouldNotConnect ); + iLastGoodWatcherStatus = EImpsCIRWatcherUnknown; + } + break; + default: +#ifdef _DEBUG + WriteToLog( _L8( " Default case." ) ); +#endif + break; + } + } + +// --------------------------------------------------------- +// CTcpCirWatcher::HandleBearerActivationLL +// +// --------------------------------------------------------- +// +void CTcpCirWatcher::HandleBearerActivationL() + { +#ifdef _DEBUG + WriteToLog( _L8( "CTcpCirWatcher::HandleBearerActivationL()" ) ); +#endif + iWatcherStatus = iLastGoodWatcherStatus; + switch ( iWatcherStatus ) + { + case EImpsCIRWatcherUnknown: +#ifdef _DEBUG + WriteToLog( _L8( " No active CIR channel exists, ignore." ) ); +#endif + iWatcherStatus = EImpsCIRWatcherIdle; + break; + case EImpsCIRWatcherSendingPINGRequest: + case EImpsCIRWatcherWaitingPINGResponse: + case KImpsCIRWatcherReceivingFromSocket: +#ifdef _DEBUG + WriteToLog( _L8( " Last good state was sending a request, send another." ) ); +#endif + SendPingL(); + break; + case EImpsCIRWatcherConnectingTCPSocket: +#ifdef _DEBUG + WriteToLog( _L8( " Last good state was opening a socket, re-open." ) ); +#endif + iTCPCIRSocket.Close(); + ConnectTCPSocketL(); + break; + default: +#ifdef _DEBUG + WriteToLog( _L8( " Default case." ) ); +#endif + break; + } + } + +// --------------------------------------------------------- +// CTcpCirWatcher::HandleBearerEventL +// +// --------------------------------------------------------- +// +void CTcpCirWatcher::HandleBearerEventL( TBool aIsAuthClose, TMsgBearerEvent aBearerEvent ) + { +#ifdef _DEBUG + WriteToLog( _L8( "CTcpCirWatcher::HandleBearerEventL() Event: %d AuthClose: %d" ), + aBearerEvent, aIsAuthClose ); +#endif + switch ( aBearerEvent ) + { + case EMsgBearerSuspended: +#ifdef _DEBUG + WriteToLog( _L8( " Bearer suspended - State: %d" ), iWatcherStatus ); +#endif + //Do nothing if already in suspend state + if ( iWatcherStatus != EImpsCIRWatcherBearerSuspended ) + HandleBearerSuspension(); + break; + case EMsgBearerActive: +#ifdef _DEBUG + WriteToLog( _L8( " Bearer activated - State: %d." ), iWatcherStatus ); +#endif + //Act only if in suspend state + if ( iWatcherStatus == EImpsCIRWatcherBearerSuspended ) + HandleBearerActivationL(); + break; + case EMsgBearerLost: +#ifdef _DEBUG + WriteToLog( _L8( " Bearer lost, call it a day." ) ); +#endif + Cancel(); + iWatcherStatus = EImpsCIRWatcherIdle; + iCirReceiver.HandleErrorL( EMsgBearerLost, EImpsTcpCir ); + break; + default: +#ifdef _DEBUG + WriteToLog( _L8( " Default case, shouldn't be here..." ) ); +#endif + break; + } + } + + +// End of File \ No newline at end of file