IMPSengine/engsrv/src/impsactiveconnmonitor.cpp
changeset 0 094583676ce7
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/IMPSengine/engsrv/src/impsactiveconnmonitor.cpp	Thu Dec 17 08:41:52 2009 +0200
@@ -0,0 +1,502 @@
+/*
+* Copyright (c) 2003-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: Imps connection manager.
+*
+*
+*/
+
+
+
+
+// INCLUDE FILES
+#include    <e32std.h>
+#include    "ImpsSendReceive.h"
+#include    "impsactiveconnmonitor.h"
+#include    "impsutils.h"
+#include    "impserrors.h"
+
+
+// CONSTANTS
+
+// MACROS
+#ifndef _DEBUG
+#define _NO_IMPS_LOGGING_
+#endif
+
+// LOCAL CONSTANTS AND MACROS
+
+// Wait time 8 seconds before IAP re-opened
+const TInt KImpsWaitIAPOpen = 8000000;
+
+
+
+// ================= MEMBER FUNCTIONS =======================
+
+// C++ default constructor can NOT contain any code, that
+// might leave.
+//
+
+//**********************************
+// CImpsConnManager
+//**********************************
+CImpsConnManager::CImpsConnManager(
+    CImpsSendReceive2& aSender,
+    TInt aPriority )
+        : CActive( aPriority ),
+        iSender( aSender ),
+        iState( EImpsNoAP ),
+        iCmd( EImpsTransNone ),
+        iConnState( EMsgBearerActive ),
+        iManager( NULL ),
+        iRunL( EFalse )
+    {
+    ( void ) iTimer.CreateLocal();
+    // Add this to the scheduler
+    CActiveScheduler::Add( this );
+    }
+
+// EPOC default constructor can leave.
+void CImpsConnManager::ConstructL()
+    {
+#ifndef _NO_IMPS_LOGGING_
+    CImpsClientLogger::Log( _L( "CImpsConnManager: CONSTRUCTL rel200540.3f cman=%d" ), ( TInt )this );
+#endif
+    iManager = NewMsgConnManagerL( 0 );
+    }
+
+// Two-phased constructor.
+CImpsConnManager* CImpsConnManager::NewL(
+    CImpsSendReceive2& aSender, TInt aPriority )
+    {
+    CImpsConnManager* self = new ( ELeave ) CImpsConnManager(
+        aSender, aPriority );
+    CleanupStack::PushL( self );
+    self->ConstructL();
+    CleanupStack::Pop();
+    return self;
+    }
+
+
+// Destructor
+CImpsConnManager::~CImpsConnManager()
+    {
+#ifndef _NO_IMPS_LOGGING_
+    CImpsClientLogger::Log( _L( "CImpsConnManager: DESTRUCTOR begins cman=%d" ), ( TInt )this );
+#endif
+    Cancel();
+    iTimer.Close();
+    if ( iManager )
+        {
+        iManager->Destroy();
+        }
+
+#ifndef _NO_IMPS_LOGGING_
+    CImpsClientLogger::Log( _L( "CImpsConnManager: DESTRUCTOR ends cman=%d" ), ( TInt )this );
+#endif
+    }
+
+// ---------------------------------------------------------
+// CImpsConnManager::OpenAPL
+// ---------------------------------------------------------
+//
+void CImpsConnManager::OpenAPL(
+    TInt  aIAP, TBool aDelayed )
+    {
+#ifndef _NO_IMPS_LOGGING_
+    CImpsClientLogger::Log( _L( "CImpsConnManager: OpenAPL iap=%d delay=%d cman=%d" ),
+                            aIAP, aDelayed, ( TInt )this );
+#endif
+    if ( IsActive () )
+        {
+        // Notice: We should not be here
+#ifndef _NO_IMPS_LOGGING_
+        CImpsClientLogger::Log( _L( "CImpsConnManager: BUSY cman=%d ****" ), ( TInt )this );
+#endif
+        User::Leave( KErrNotReady );
+        }
+
+    iConnState = EMsgBearerActive;
+
+    if ( ( aDelayed || iRunL ) && iCmd != EImpsTransWaitOpen )
+        {
+#ifndef _NO_IMPS_LOGGING_
+        CImpsClientLogger::Log( _L( "CImpsConnManager: cman=%d OpenAPL extra wait ****" ), ( TInt )this );
+#endif
+        iCmd = EImpsTransWaitOpen;
+        iState = EImpsNoAP;
+        iIAP = aIAP;
+        SetActive();
+        // Give time for Connection Manager
+        iTimer.After( iStatus, KImpsWaitIAPOpen );
+        return;
+        }
+    iCmd = EImpsTransNone;
+#ifndef _NO_IMPS_LOGGING_
+    CImpsClientLogger::Log( _L( "CImpsConnManager: cman=%d calls SetAccessPointIDL" ), ( TInt )this );
+#endif
+    iManager->SetAccessPointIDL( aIAP );
+#ifndef _NO_IMPS_LOGGING_
+    CImpsClientLogger::Log( _L( "CImpsConnManager: cman=%d calls RemoveEventSubscriber and AddEventSubscriberL" ), ( TInt )this );
+#endif
+    // Verify that in error cases nothing is left hanging
+    iManager->RemoveEventSubscriber( this );
+    iManager->AddEventSubscriberL( this );
+    iStatus = KRequestPending;
+#ifndef _NO_IMPS_LOGGING_
+    CImpsClientLogger::Log( _L( "CImpsConnManager: cman=%d calls StartConnection" ), ( TInt )this );
+#endif
+    iManager->StartConnection( iStatus );
+    iCmd = EImpsTransOpenAP;
+    iState = EImpsNoAP;
+    iIAP = aIAP;
+    SetActive();
+    }
+
+// ---------------------------------------------------------
+// CImpsConnManager::CloseAP
+// ---------------------------------------------------------
+//
+void CImpsConnManager::CloseAP( TBool /*aTotalClose*/ )
+    {
+#ifndef _NO_IMPS_LOGGING_
+    CImpsClientLogger::Log( _L( "CImpsConnManager: CloseAP state=%d %d cman=%d" ),
+                            iState, IsActive(), ( TInt )this );
+#endif
+
+    if ( iState == EImpsNoAP && !IsActive() )
+        {
+#ifndef _NO_IMPS_LOGGING_
+        CImpsClientLogger::Log( _L( "CImpsConnManager: cman=%d CloseAP already closed" ), ( TInt )this );
+#endif
+        iCmd = EImpsTransNone;
+        iConnState = EMsgBearerActive;
+        // Engine core waits any kind of response in shut down
+        iSender.APStatusEvent( EImpsNoAP, KErrNone, ETrue );
+#ifndef _NO_IMPS_LOGGING_
+        CImpsClientLogger::Log( _L( "CImpsConnManager: cman=%d CloseAP ends" ), ( TInt )this );
+#endif
+        return;
+        }
+    else if ( iState == EImpsNoAP && IsActive() )
+        {
+        // Waiting open timer must be cancelled
+        if ( iCmd == EImpsTransWaitOpen )
+            {
+            // This cancels the timer
+#ifndef _NO_IMPS_LOGGING_
+            CImpsClientLogger::Log( _L( "CImpsConnManager: cman=%d err: CANCEL ***" ), ( TInt )this );
+#endif
+            Cancel();
+            iCmd = EImpsTransCloseAP;
+            iIAP = 0;
+            // Now do the trick to go to own RunL and call there appropriate callback.
+            ActivateMe();
+            return;
+            }
+        else if ( iCmd == EImpsTransOpenAP )
+            {
+            // Open APL is pending and must be cancelled
+#ifndef _NO_IMPS_LOGGING_
+            CImpsClientLogger::Log( _L( "CImpsConnManager: cman=%d calls CancelStartL ****" ), ( TInt )this );
+#endif
+            TRAPD( errx, iManager->CancelStartL() );
+            if ( errx )
+                {
+                // Normally this is not needed, but Cancel StartL may leave with
+                // KErrAbort if there is no pending request.
+                // VERY RARE situation.
+                iCmd = EImpsTransNone;
+                iSender.APStatusEvent( EImpsNoAP, KErrNone, ETrue );
+                return;
+                }
+            // Normal case continues in RunL
+#ifndef _NO_IMPS_LOGGING_
+            CImpsClientLogger::Log( _L( "CImpsConnManager: cman=%d CloseAP ends" ), ( TInt )this );
+#endif
+            return;
+            }
+        }
+    else if ( IsActive() )  //
+        {
+        // Previous close is not completed.
+#ifndef _NO_IMPS_LOGGING_
+        CImpsClientLogger::Log( _L( "CImpsConnManager: cman=%d BUSY ***" ), ( TInt )this );
+#endif
+        return;
+        }
+    iCmd = EImpsTransCloseAP;
+    iIAP = 0;
+    iStatus = KRequestPending;
+    SetActive();
+    // Notice: Rest of activities in RunL and destructor
+#ifndef _NO_IMPS_LOGGING_
+    CImpsClientLogger::Log( _L( "CImpsConnManager: cman=%d calls RemoveEventSubscriber" ), ( TInt )this );
+#endif
+    iManager->RemoveEventSubscriber( this );
+#ifndef _NO_IMPS_LOGGING_
+    CImpsClientLogger::Log( _L( "CImpsConnManager: cman=%d calls StopConnection" ), ( TInt )this );
+#endif
+    iManager->StopConnection( iStatus );
+
+#ifndef _NO_IMPS_LOGGING_
+    CImpsClientLogger::Log( _L( "CImpsConnManager: cman=%d CloseAP ends" ), ( TInt )this );
+#endif
+    }
+
+
+// ---------------------------------------------------------
+// CImpsConnManager::HandleBearerEventL
+// ---------------------------------------------------------
+//
+void CImpsConnManager::HandleBearerEventL( TBool aIsAuthClose, TMsgBearerEvent aBearerEvent )
+    {
+#ifndef _NO_IMPS_LOGGING_
+    CImpsClientLogger::Log(
+        _L( "CImpsConnManager: HandleBearerEventL %d authClose=%d cman=%d" ), aBearerEvent, aIsAuthClose, ( TInt )this );
+#endif
+    iConnState = aBearerEvent;
+    if ( IsActive() )
+        {
+        // pending open/close, so wait that instead
+#ifndef _NO_IMPS_LOGGING_
+        CImpsClientLogger::Log(
+            _L( "CImpsConnManager: HandleBearerEventL SPECIAL cmd=%d cman=%d ***" ), iCmd, ( TInt )this );
+#endif
+
+        /* Notice:
+         This is a little bit tricky situation because of Msg ConnManager DLL
+         cannot quarantee the right order of events for us! Thus it is
+         possible that we first get bearer-event and after that response
+         for open/close connection request although the actual order
+         is that open/close is first completed and then the bearer event has
+         taken a place.
+
+               /@
+               \ \
+             ___> \
+            (__O)  \
+           (____@)  \
+           (____@)   \
+            (__o)_    \
+                  \    \
+        */
+
+        switch ( iConnState )
+            {
+            case EMsgBearerActive:
+                iSender.APStatusEvent( EImpsOnline, KErrNone, EFalse );
+                break;
+            case EMsgBearerSuspended:
+                iSender.APStatusEvent( EImpsOffline, KErrNone, EFalse );
+                break;
+            case EMsgBearerLost:
+            default:
+                {
+                // RunL handles rest of the activities
+                // when iConnState == EMsgBearerLost.
+                break;
+                }
+            };
+        }
+    else // regular case
+        {
+        switch ( iConnState )
+            {
+            case EMsgBearerActive:
+                iSender.APStatusEvent( EImpsOnline, KErrNone, EFalse );
+                break;
+            case EMsgBearerSuspended:
+                iSender.APStatusEvent( EImpsOffline, KErrNone, EFalse );
+                break;
+            case EMsgBearerLost:
+            default:
+                {
+                iState = EImpsNoAP;
+                iSender.APStatusEvent( EImpsNoAP, KErrNone, EFalse, aIsAuthClose );
+                break;
+                }
+            }
+        };
+#ifndef _NO_IMPS_LOGGING_
+    CImpsClientLogger::Log( _L( "CImpsConnManager: cman=%d HandleBearerEventL ends" ), ( TInt )this );
+#endif
+    }
+
+// ---------------------------------------------------------
+// CImpsConnManager::ManagerHandleL
+// ---------------------------------------------------------
+//
+MMsgConnManager& CImpsConnManager::ManagerHandleL() const
+    {
+    if ( !iManager )
+        {
+        User::Leave( KErrBadHandle );
+        }
+    return *iManager;
+    }
+
+// ---------------------------------------------------------
+// CImpsConnManager::Destroy
+// ---------------------------------------------------------
+//
+void CImpsConnManager::Destroy()
+    {
+    if ( iManager )
+        {
+        iManager->Destroy();
+        }
+    iManager = NULL;
+    }
+
+// ---------------------------------------------------------
+// CImpsConnManager::RunL
+// ---------------------------------------------------------
+//
+void CImpsConnManager::RunL( )
+    {
+
+#ifndef _NO_IMPS_LOGGING_
+    CImpsClientLogger::Log( _L( "CImpsConnManager: RunL ret=%d cmd=%d state=%d conn=%d cman=%d" ),
+                            iStatus.Int(), iCmd, iState, iConnState, ( TInt )this );
+#endif
+
+    iRunL = ETrue;
+    TInt ret = iStatus.Int();
+
+    // We have delayed and given time for connection manager to work properly
+    if ( iCmd == EImpsTransWaitOpen )
+        {
+        if ( !ret )
+            {
+            TInt errx = KErrNone;
+            TRAP( errx, OpenAPL( iIAP, EFalse ) );
+            }
+        else
+            {
+            iState = EImpsNoAP;
+            iCmd = EImpsTransNone;
+            iSender.APStatusEvent( iState, ret, ETrue );
+            }
+        }
+    else if ( iCmd == EImpsTransOpenAP )
+        {
+        iCmd = EImpsTransNone;
+        iState = EImpsNoAP;
+        if ( ret == KErrNone )
+            {
+            if ( iConnState != EMsgBearerLost )
+                {
+                // AP is opened successfully
+                iState = EImpsOnline;
+                }
+            else // iConnState == EMsgBearerLost
+                {
+#ifndef _NO_IMPS_LOGGING_
+                CImpsClientLogger::Log( _L( "CImpsConnManager: err: cman=%d iConnState==EMsgBearerLost ****" ), ( TInt )this );
+#endif
+                // Special case where order of events from ConnManager is not valid.
+                ret = KImpsErrorNoIAP;
+                // KImpsErrorNoIAP error code has a special error handling
+                // in CSPSession class.
+                }
+            }
+        iSender.APStatusEvent( iState, ret, ETrue );
+        }
+    else if ( iCmd == EImpsTransCloseAP )
+        {
+        iCmd = EImpsTransNone;
+        iState = EImpsNoAP;
+        // Notice that iSender must exist, i.e. DeleteCSP() cancels
+        // everything before deleting CSP session entity referred by iSender.
+        iSender.APStatusEvent( EImpsNoAP, ret, ETrue );
+        }
+    else if ( iCmd == EImpsTransCloseDelay )
+        {
+        // This is a special case where this object is used for yielding.
+        // Actually it calls CloseAP
+        iCmd = EImpsTransNone;
+        iSender.CloseTr( );
+        }
+    else
+        {
+        iCmd = EImpsTransNone;
+        }
+    iRunL = EFalse;
+#ifndef _NO_IMPS_LOGGING_
+    CImpsClientLogger::Log( _L( "CImpsConnManager: cman=%d RunL ends" ), ( TInt )this );
+#endif
+    }
+
+// ---------------------------------------------------------
+// CImpsConnManager::DoCancel
+// ---------------------------------------------------------
+//
+void CImpsConnManager::DoCancel()
+    {
+#ifndef _NO_IMPS_LOGGING_
+    CImpsClientLogger::Log( _L( "CImpsConnManager: cman=%d DoCancel" ), ( TInt )this );
+#endif
+    TImpsTransCmd orig = iCmd;
+    iCmd = EImpsTransNone;
+    if ( orig == EImpsTransOpenAP )
+        {
+        // cancel
+#ifndef _NO_IMPS_LOGGING_
+        CImpsClientLogger::Log( _L( "CImpsConnManager: cman=%d calls CancelStartL *****" ), ( TInt )this );
+#endif
+        TInt errx = KErrNone;
+        TRAP( errx, iManager->CancelStartL() );
+        }
+    else if ( orig == EImpsTransCloseAP )
+        {
+        iState = EImpsNoAP;
+        }
+    // This just waits IAP connection operation to end.
+    else if ( iCmd == EImpsTransWaitOpen )
+        {
+        iTimer.Cancel();
+        }
+    }
+
+TInt CImpsConnManager::ActivateMe(  )
+    {
+    // This yields the control to the server thread active scheduler
+    if ( !IsActive() )
+        {
+        iStatus = KRequestPending;
+        SetActive();
+        TRequestStatus* s = &iStatus;
+        User::RequestComplete( s, KErrNone );
+        return KErrNone;
+        }
+    else
+        {
+#ifndef _NO_IMPS_LOGGING_
+        CImpsClientLogger::Log( _L( "CImpsConnManager: cman=%d KErrNotReady ****" ), ( TInt )this );
+#endif
+        return KErrNotReady;
+        }
+    }
+
+TInt CImpsConnManager::StartDelayed( )
+    {
+#ifndef _NO_IMPS_LOGGING_
+    CImpsClientLogger::Log( _L( "CImpsConnManager: cman=%d StartDelayed" ), ( TInt )this );
+#endif
+    iCmd = EImpsTransCloseDelay;
+    return ActivateMe();
+    }
+
+
+//  End of File