--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/IMPSengine/ImpsIpCirWatcher/ImpsTcpIpCirWatcher/src/TcpCirWatcher.cpp Wed Sep 01 12:31:13 2010 +0100
@@ -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 <ecom/ecom.h>
+#include <f32file.h>
+#ifdef _DEBUG
+#include <flogger.h>
+#endif
+#include <msgconnmanagerapi.h>
+#include <msgbearerObscallback.h>
+#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<const TDesC8> aFmt, ... )
+ {
+ VA_LIST list;
+ VA_START( list, aFmt );
+ TBuf8<KTcpLogBufferMaxSize> 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