IMPSengine/engsrv/src/impsalivemanager.cpp
changeset 0 094583676ce7
--- /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    <s32std.h>
+#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
+