diff -r 000000000000 -r 094583676ce7 IMPSengine/engsrv/src/impsalivemanager.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/IMPSengine/engsrv/src/impsalivemanager.cpp Thu Dec 17 08:41:52 2009 +0200 @@ -0,0 +1,482 @@ +/* +* Copyright (c) 2003 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: Alive manager for IMPS engine. +* +* +*/ + + +// INCLUDE FILES +#include +#include "impsalivemanager.h" +#include "impsutils.h" +#include "impscspsessionapi.h" +#include "impstimer.h" +#include "impserrors.h" + +// MACROS +#ifndef _DEBUG +#define _NO_IMPS_LOGGING_ +#endif + +// ================= MEMBER FUNCTIONS ======================= + + +// --------------------------------------------------------- +// CImpsAliveManager::CImpsAliveManager +// --------------------------------------------------------- +// +CImpsAliveManager::CImpsAliveManager( MImpsCSPSession& aServer ) + : CActive( 0 ), + iState( EImpsAliveIdle ), + iServer( aServer ), + iTimer( NULL ), + iScheduled( EFalse ), + iTid( KNullDesC ), + iSeconds( 0 ) + { + // Add this to the scheduler + CActiveScheduler::Add( this ); + } + +// Two-phased constructor. +CImpsAliveManager* CImpsAliveManager::NewL( MImpsCSPSession& aServer ) + { + CImpsAliveManager* self = new ( ELeave ) CImpsAliveManager( aServer ); + + CleanupStack::PushL( self ); + self->ConstructL( ); + CleanupStack::Pop( ); + + return self; + } + + +// --------------------------------------------------------- +// CImpsAliveManager::ConstructL +// --------------------------------------------------------- +// +void CImpsAliveManager::ConstructL() + { + iTimer = new ( ELeave ) CImpsAliveTimer( *this, CActive::EPriorityStandard ); + } + +// --------------------------------------------------------- +// CImpsAliveManager::~CImpsAliveManager +// --------------------------------------------------------- +// +CImpsAliveManager::~CImpsAliveManager( ) + { + Cancel(); + delete iTimer; + } + +// --------------------------------------------------------- +// CImpsAliveManager::StartTimer +// Server core calls this always when receving KeepAliveResp. +// --------------------------------------------------------- +// +void CImpsAliveManager::StartTimer( TInt aInterval ) + { +#ifndef _NO_IMPS_LOGGING_ + CImpsClientLogger::Log( _L( "AliveManager: StartTimer" ) ); +#endif + iState = EImpsAliveActive; +#ifndef _NO_IMPS_LOGGING_ + CImpsClientLogger::Log( _L( "AliveManager: iState = %d " ), iState ); +#endif + iFailCount = 0; + iTimerFail = 0; + // Some time needed to open PDP, that's why 60 seconds decreased + TInt myInterval = ( aInterval / 2 ) - 60; + if ( myInterval < 60 ) + { + myInterval = aInterval / 2; + } + iSeconds = myInterval; + iTimer->Start( iSeconds ); + } + +// --------------------------------------------------------- +// CImpsAliveManager::StopTimer +// --------------------------------------------------------- +// +void CImpsAliveManager::StopTimer( ) + { +#ifndef _NO_IMPS_LOGGING_ + CImpsClientLogger::Log( _L( "AliveManager: StopTimer" ) ); +#endif + iTimer->Stop(); + iState = EImpsAliveIdle; +#ifndef _NO_IMPS_LOGGING_ + CImpsClientLogger::Log( _L( "AliveManager: iState = %d " ), iState ); +#endif + } + +// --------------------------------------------------------- +// CImpsAliveManager::CheckResp +// --------------------------------------------------------- +// +void CImpsAliveManager::CheckResp( TInt aCode ) + { + // Session id check should already be done in engine core. + // Any normal transport response resets the timer + if ( iState != EImpsAlivePending ) + { + iTimer->Start( iSeconds ); + return; + } + + // Something is received within the session. + // We are not interested to get the particular response for + // KeepAliveReq transaction. + if ( aCode != 600 && + aCode != 601 && + aCode != 604 ) + { + iState = EImpsAliveActive; +#ifndef _NO_IMPS_LOGGING_ + CImpsClientLogger::Log( _L( "AliveManager: CheckResp resets iState = %d " ), iState ); +#endif + iFailCount = 0; + iTimerFail = 0; + return; + } + else + { +#ifndef _NO_IMPS_LOGGING_ + CImpsClientLogger::Log( _L( "AliveManager: CheckResp 60x" ) ); +#endif + // Just stop timer here. DoLogout is called later in engine core, + // after the possible response event is created for the client. + StopTimer(); + } + } + +// --------------------------------------------------------- +// CImpsAliveManager::CheckError +// --------------------------------------------------------- +// +void CImpsAliveManager::CheckError( const TDesC& aTid ) + { +#ifndef _NO_IMPS_LOGGING_ + CImpsClientLogger::Log( _L( "AliveManager: CheckError %d" ), + iState ); +#endif + if ( iState != EImpsAlivePending ) + { + return; + } + // Open PDP errors come here without TID and then error handling is required. + if ( aTid.Length() && iTid.Compare( aTid ) ) + { + // This was not KeepAliveReguest transaction + return; + } + iState = EImpsAliveActive; +#ifndef _NO_IMPS_LOGGING_ + CImpsClientLogger::Log( _L( "AliveManager: iState = %d " ), iState ); +#endif + DoHandleError( ); + } + +// --------------------------------------------------------- +// CImpsAliveManager::SendKeepAlive +// --------------------------------------------------------- +// +void CImpsAliveManager::SendKeepAlive( + TBool aSchedule ) + { +#ifndef _NO_IMPS_LOGGING_ + CImpsClientLogger::Log( _L( "AliveManager: SendKeepAlive sch=%d state=%d fc=%d tf=%d" ), + aSchedule, iState, iFailCount, iTimerFail ); +#endif + + if ( iState == EImpsAliveActive ) + { + iState = EImpsAlivePending; + iScheduled = aSchedule; +#ifndef _NO_IMPS_LOGGING_ + CImpsClientLogger::Log( _L( "AliveManager: iState = %d " ), iState ); +#endif + + TRAPD( err, ( iTid = iServer.SendAliveL( ) ) ); + if ( err ) + { + // Error received immediately and + // since going back to active state. + iState = EImpsAliveActive; + DoHandleError( ); + } + } + else if ( iState == EImpsAliveIdle ) + { + return; + } + else // if ( iState == EImpsAlivePending ) + { + if ( aSchedule ) + { + // Previous request not complete! + iTimerFail++; + iFailCount = 0; + if ( iTimerFail > KImpsMaxAliveScheduleErr ) + { + // current CSP session seems to be lost! + DoSessionClose(); + return; + } + } + TRAPD( err, ( iTid = iServer.SendAliveL( ) ) ); + if ( err ) + { + DoHandleError( ); + } + } + } + +// --------------------------------------------------------- +// CImpsAliveManager::DoHandleError +// --------------------------------------------------------- +// +void CImpsAliveManager::DoHandleError( ) + { +#ifndef _NO_IMPS_LOGGING_ + CImpsClientLogger::Log( _L( "AliveManager: DoHandleError" ) ); +#endif + if ( IsActive() ) + { +#ifndef _NO_IMPS_LOGGING_ + CImpsClientLogger::Log( _L( "AliveManager: DoHandleError was active" ) ); +#endif + return; + } + TRequestStatus* s = &iStatus; + iFailCount++; + if ( iFailCount > KImpsMaxAliveRetryOnce ) + { + if ( !iScheduled ) + { +#ifndef _NO_IMPS_LOGGING_ + CImpsClientLogger::Log( _L( "AliveManager: DoHandleError !scheduled" ) ); +#endif + return; + } + iTimerFail++; + iFailCount = 0; + if ( iTimerFail > KImpsMaxAliveScheduleErr ) + { + // current CSP session seems to be lost! + // Yield control to scheduler +#ifndef _NO_IMPS_LOGGING_ + CImpsClientLogger::Log( _L( "AliveManager: DoHandleError NOK stop" ) ); +#endif + iStatus = KRequestPending; + SetActive(); + User::RequestComplete( s, KImpsNotLoggedStatus ); + } + // else not try more until scheduled by the timer + } + else + { +#ifndef _NO_IMPS_LOGGING_ + CImpsClientLogger::Log( _L( "AliveManager: DoHandleError OK retry" ) ); +#endif + // Tell CSP session to send KeepAlive when GPRS resumes + iServer.SendAliveInResume(); + // Yield control to scheduler and retry in RunL + iStatus = KRequestPending; + SetActive(); + User::RequestComplete( s, KErrNone ); + } + +#ifndef _NO_IMPS_LOGGING_ + CImpsClientLogger::Log( _L( "AliveManager: DoHandleError END" ) ); +#endif + } + +// --------------------------------------------------------- +// CImpsAliveManager::DoSessionClose +// --------------------------------------------------------- +// +void CImpsAliveManager::DoSessionClose( ) + { +#ifndef _NO_IMPS_LOGGING_ + CImpsClientLogger::Log( _L( "AliveManager: DoSessionClose" ) ); +#endif + iTimer->Stop(); + iState = EImpsAliveIdle; +#ifndef _NO_IMPS_LOGGING_ + CImpsClientLogger::Log( _L( "AliveManager: iState = %d " ), iState ); +#endif + iServer.DoLogout(); + } + +// --------------------------------------------------------- +// CImpsAliveManager::DoCancel +// --------------------------------------------------------- +// +void CImpsAliveManager::DoCancel() + { + iTimer->Stop(); + iState = EImpsAliveIdle; +#ifndef _NO_IMPS_LOGGING_ + CImpsClientLogger::Log( _L( "AliveManager: iState = %d " ), iState ); +#endif + } + +// --------------------------------------------------------- +// CImpsAliveManager::RunL +// --------------------------------------------------------- +// +void CImpsAliveManager::RunL() + { +#ifndef _NO_IMPS_LOGGING_ + CImpsClientLogger::Log( _L( "AliveManager: RunL %d" ), iState ); +#endif + if ( iState == EImpsAliveIdle ) + { + // Cancelled + return; + } + if ( iStatus == KImpsNotLoggedStatus ) + { + // current CSP session is lost + DoSessionClose(); + } + else + { + // Retry + SendKeepAlive( iScheduled ); + } +#ifndef _NO_IMPS_LOGGING_ + CImpsClientLogger::Log( _L( "AliveManager: RunL ends" ) ); +#endif + } + +//********************************** +// CImpsAliveTimer +//********************************** + +CImpsAliveTimer::CImpsAliveTimer( + CImpsAliveManager& aServer, + TInt aPriority ) + : CActive( aPriority ), + iMgr( aServer ), + iReset( EFalse ), + iCanceled( EFalse ) + { + // Add this to the scheduler + ( void ) iTimer.CreateLocal(); + CActiveScheduler::Add( this ); + } + +CImpsAliveTimer::~CImpsAliveTimer() + { + Cancel(); + iTimer.Close(); + } + +// --------------------------------------------------------- +// CImpsAliveTimer::Start +// --------------------------------------------------------- +// +void CImpsAliveTimer::Start( TInt aWaitSeconds ) + { +#ifndef _NO_IMPS_LOGGING_ + CImpsClientLogger::Log( _L( "AliveTimer: Start %d sec" ), aWaitSeconds ); +#endif + iReset = EFalse; + if ( aWaitSeconds <= 0 ) + { + return; + } + // Cancel is needed because of the timer may be reset. + Cancel(); + iSeconds = aWaitSeconds; + + // The At function caused a CUserbase-Panic 46 in very small + // time values. 1-4 seconds. Now if the KeepAlive time + // is smaller than UseAfterLimit, then we use the After function + // If it is larger then use the At function + // The reason not to use the After function for every situation is + // that the TInt overflows after 35 minutes. 1000000*60*36 > 2^31 + if ( iSeconds < KUseAfterLimit ) + { + iTimer.After( iStatus, iSeconds * 1000000 ); + } + else + { + TTime myKeepAlive; + myKeepAlive.HomeTime(); + myKeepAlive += TTimeIntervalSeconds( iSeconds ); + iTimer.At( iStatus, myKeepAlive ); + } + + iStatus = KRequestPending; + SetActive(); + + } + +// --------------------------------------------------------- +// CImpsAliveTimer::Stop +// --------------------------------------------------------- +// +void CImpsAliveTimer::Stop( ) + { +#ifndef _NO_IMPS_LOGGING_ + CImpsClientLogger::Log( _L( "AliveTimer: Stop" ) ); +#endif + iReset = ETrue; + Cancel(); + // The following is needed because of the timer may just + // have triggered and thus it is not active, but the request is + // waiting in the scheduler and coming to RunL later. + iCanceled = ETrue; + } + +// --------------------------------------------------------- +// CImpsAliveTimer::DoCancel +// --------------------------------------------------------- +// +void CImpsAliveTimer::DoCancel() + { + iTimer.Cancel(); + } + +// --------------------------------------------------------- +// CImpsAliveTimer::RunL +// --------------------------------------------------------- +// +void CImpsAliveTimer::RunL() + { +#ifndef _NO_IMPS_LOGGING_ + CImpsClientLogger::Log( _L( "AliveTimer: RunL" ) ); +#endif + if ( iCanceled ) + { + return; + } + if ( !iReset ) + { + iMgr.SendKeepAlive( ETrue ); + } + iReset = EFalse; + Start( iSeconds ); + } + +// ================= OTHER EXPORTED FUNCTIONS ============== + +// End of File +