IMPSengine/engsrv/src/impsactivecirmonitor.cpp
author Dremov Kirill (Nokia-D-MSW/Tampere) <kirill.dremov@nokia.com>
Fri, 19 Feb 2010 22:44:11 +0200
branchRCL_3
changeset 6 d96c135bc497
parent 0 094583676ce7
permissions -rw-r--r--
Revision: 201002 Kit: 201007

/*
* 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:  Im circle Manager.
*
*
*/


// INCLUDE FILES
#include    <e32std.h>
#include    "impsactivecirmonitor.h"
#include    "impsutils.h"
#include    <msgconnmanagerapi.h>


// CONSTANTS

// TCP/IP CIR ping interval in seconds
const TInt KImpsPingInt = 900;

// MACROS
#ifndef _DEBUG
#define _NO_IMPS_LOGGING_
#endif

// LOCAL CONSTANTS AND MACROS

// MODULE DATA STRUCTURES


// ================= MEMBER FUNCTIONS =======================

// C++ default constructor can NOT contain any code, that
// might leave.
//

//**********************************
// CImpsCirManager
//**********************************
CImpsCirManager::CImpsCirManager(
    MImpsCSPSession& aServer,
    TInt aPriority )
        : CActive( aPriority ),
        iServer( aServer ),
        iState( EImpsCirOffline ),
        iCanceled( EFalse ),
        iManager( NULL ),
        iTCPWatcher( NULL ),
        iUDPWatcher( NULL ),
        iChannels ( 0 ),
        iReqChannels ( 0 )
    {
    // Add this to the scheduler
    CActiveScheduler::Add( this );
    }

// EPOC default constructor can leave.
void CImpsCirManager::ConstructL()
    {
#ifndef _NO_IMPS_LOGGING_
    CImpsClientLogger::Log( _L( "CImpsCirManager: Constructor rel200517.1+" ) );
#endif
    }

// Two-phased constructor.
CImpsCirManager* CImpsCirManager::NewL(
    MImpsCSPSession& aServer,
    TInt aPriority )
    {
    CImpsCirManager* self = new ( ELeave ) CImpsCirManager(
        aServer, aPriority );
    CleanupStack::PushL( self );
    self->ConstructL();
    CleanupStack::Pop();
    return self;
    }


// Destructor
CImpsCirManager::~CImpsCirManager()
    {
#ifndef _NO_IMPS_LOGGING_
    CImpsClientLogger::Log( _L( "CImpsCirManager: Destructor" ) );
#endif
    Cancel();
    if ( iTCPWatcher )
        {
        delete iTCPWatcher;
        iTCPWatcher = NULL;
        }
    if ( iUDPWatcher )
        {
        iUDPWatcher->Destroy();
        iUDPWatcher = NULL;
        }

    // REcomSession::FinalClose() is not called here but in the engine core
    // just before active acheduler is stopped.

    }  //lint !e1740 iManager is not deleted here, it's only reference

// ---------------------------------------------------------
// CImpsCirManager::OpenChL
// ---------------------------------------------------------
//
void CImpsCirManager::OpenChL(
    TImpsCirChannels aChannels,
    MMsgConnManager& aManager,
    TUint aServerport,
    const TDesC& aServerAddress,
    const TDesC8& aCSPSessionID,
    TUint aUDPPort )
    {
    if  ( ( iState == EImpsCirOnline ) || ( aChannels == 0 ) )
        {
#ifndef _NO_IMPS_LOGGING_
        CImpsClientLogger::Log( _L( "CImpsCirManager: OpenChL ignored" ) );
#endif
        iServer.CirChOpened();
        // Nothing to open
        return;
        }

#ifndef _NO_IMPS_LOGGING_
    CImpsClientLogger::Log( _L( "CImpsCirManager: OpenChL" ) );
#endif

    iManager = &aManager;
    iReqChannels = aChannels;
    iUDPPort = aUDPPort;

    // Start TCP watcher first if required
    if ( ( aChannels & KImpsCirTcp ) && ~( iChannels & KImpsCirTcp ) )
        {
        DoOpenTCPL( aServerport, aServerAddress,
                    aCSPSessionID );
        // Another watcher started in RunL if needed
        }
    // UPD start here if TCP not required
    else if ( ( aChannels & KImpsCirUdp ) && ~( iChannels & KImpsCirUdp ) )
        {
        DoOpenUDP( iUDPPort );
        }
    }

// ---------------------------------------------------------
// CImpsCirManager::DoOpenTCPL
// ---------------------------------------------------------
//
void CImpsCirManager::DoOpenTCPL(
    TUint aServerport,
    const TDesC& aServerAddress,
    const TDesC8& aCSPSessionID )
    {
#ifndef _NO_IMPS_LOGGING_
    CImpsClientLogger::Log( _L( "CImpsCirManager: DoOpenTCPL" ) );
#endif
    // If opening fails then this method leaves. TCP is tried to open
    // so CSP session gets information about failure.
    // Start watchers, TCP watcher first
    iTCPWatcher = CImpsTcpCirWatcher::NewL( KImpsPingInt, *this, *iManager );
    iState = EImpsCirOpeningTcp;
    ActivateMe();
    iTCPWatcher->StartTCPWatcherL( iStatus, aServerport, aServerAddress, aCSPSessionID );
    }

// ---------------------------------------------------------
// CImpsCirManager::DoOpenUDP
// ---------------------------------------------------------
//
void CImpsCirManager::DoOpenUDP(
    TUint aUDPPort )
    {
#ifndef _NO_IMPS_LOGGING_
    CImpsClientLogger::Log( _L( "CImpsCirManager: DoOpenUDP" ) );
#endif
    // UPD watcher registeration
    TInt err = KErrNone;
    TRAP( err, iUDPWatcher = CImpsUdpCirWatcher::NewL() );
    if ( err )
        {
        // UDP open erros are reported to csp session asynchronously via RunL
        DoHandleError( err, EImpsUdpCir );
        }
    TRAP( err, iUDPWatcher->RegisterCirReceiverL( *this, aUDPPort ) );
    if ( err )
        {
        // UDP open erros are reported to csp session asynchronously via RunL
        DoHandleError( err, EImpsUdpCir );
        }
    else
        {
        iChannels = iChannels | KImpsCirUdp;
        }
    }

// ---------------------------------------------------------
// CImpsCirManager::CloseCh
// ---------------------------------------------------------
//
void CImpsCirManager::CloseCh(
    TImpsCirChannels aChannels )
    {
#ifndef _NO_IMPS_LOGGING_
    CImpsClientLogger::Log( _L( "CImpsCirManager: CloseCh" ) );
#endif

    // If active then have to wait
    Cancel();

    if ( !( aChannels & iChannels ) ||
         iState == EImpsCirOffline ||
         ( !iTCPWatcher && !iUDPWatcher ) )
        {
        // Nothing to close
        return;
        }

    // Channels that required to be closed
    iReqChannels = aChannels;

    // Close TCP
    if ( ( iReqChannels & KImpsCirTcp ) &&
         ( iChannels & KImpsCirTcp ) )
        {
        iTCPWatcher->StopTCPWatcher();
        iChannels = iChannels & ~KImpsCirTcp;
        }
    // Close UDP
    if ( ( iReqChannels & KImpsCirUdp ) &&
         ( iChannels & KImpsCirUdp ) )
        {
        TInt err = KErrNone;
        TRAP( err, iUDPWatcher->UnregisterCirReceiverL( *this ) );
        iChannels = iChannels & ~KImpsCirUdp;
        }

    // Destructor handles the rest of the shut down activies

    iState = EImpsCirOffline;
    }

// ---------------------------------------------------------
// CImpsCirManager::CirReceivedL
// ---------------------------------------------------------
//
void CImpsCirManager::CirReceivedL(
    const TDesC8& aMessage,
    const TImpsSupportedCirTypes aCirType )
    {
#ifndef _NO_IMPS_LOGGING_
    CImpsClientLogger::Log( _L( "CImpsCirManager: CirReceivedL type=%d" ), aCirType );
#endif

    // notice: This is not very clear how to handle multiple IP-CIR channels
    // Better keep on listening them
    /*
    if ( ( aCirType == EImpsTcpCir ) && ( iChannels & KImpsCirUdp ) )
        {
        // Stop UDP if another CIR channel in use
        iUDPWatcher->StopUDPWatcher();
        }
    else if ( ( aCirType == EImpsUdpCir ) && ( iChannels & KImpsCirTcp ) )
        {
        // Stop TCP if another CIR channel in use
        iTCPWatcher->StopTCPWatcher();
        }
        */

    iServer.CirMessageL( aMessage );

    }

// ---------------------------------------------------------
// CImpsCirManager::HandleErrorL
// ---------------------------------------------------------
//
void CImpsCirManager::HandleErrorL(
    const TInt aReceiverError,
    const TImpsSupportedCirTypes aCirType )
    {
    DoHandleError( aReceiverError, aCirType );
    }

// ---------------------------------------------------------
// CImpsCirManager::DoHandleError
// ---------------------------------------------------------
//
void CImpsCirManager::DoHandleError(
    const TInt aReceiverError,
    const TImpsSupportedCirTypes aCirType )
    {

#ifndef _NO_IMPS_LOGGING_
    CImpsClientLogger::Log( _L( "CImpsCirManager: DoHandleError %d type=%d" ),
                            aReceiverError, aCirType );
#endif

    // We suppose that this is not called if this is active, but
    // better to check anyway. Then do the following actions.
    // - Yield to ifself with an error code.
    // - In RunL stop channels
    // - Then call iServer.CirChError() that destroys us.

    if ( !IsActive() )
        {
        iStatus = KRequestPending;
        SetActive();
        iCanceled = EFalse;
        TRequestStatus* s = &iStatus;
        User::RequestComplete( s, aReceiverError );
        }
    }

// ---------------------------------------------------------
// CImpsCirManager::RunL
// ---------------------------------------------------------
//
void CImpsCirManager::RunL( )
    {

#ifndef _NO_IMPS_LOGGING_
    CImpsClientLogger::Log( _L( "CImpsCirManager: RunL %d" ), iStatus.Int() );
#endif

    if ( iCanceled )
        {
#ifndef _NO_IMPS_LOGGING_
        CImpsClientLogger::Log( _L( "CImpsCirManager: RunL ignored" ) );
#endif
        iCanceled = EFalse;
        if ( iChannels )
            {
            iState = EImpsCirOnline;
            }
        else
            {
            iState = EImpsCirOffline;
            }
        return;
        }

    // Error handling, common for both open methods and HandleErrorL methods.
    // CSP session entity will call destrcutor, so no need to do else than
    // close watcher
    if ( iStatus.Int() != KErrNone )
        {
        if ( iState == EImpsCirOnline )
            {
            if ( iChannels & KImpsCirTcp )
                {
                iTCPWatcher->StopTCPWatcher();
                }
            if ( iChannels & KImpsCirUdp )
                {
                TInt err = KErrNone;
                TRAP( err, iUDPWatcher->UnregisterCirReceiverL( *this ) );
                }
            iState = EImpsCirOffline;
            }
        iServer.CirChError();
        return;
        }

    // asynchronous TCP CIR opening completed
    if ( iState == EImpsCirOpeningTcp )
        {
        iChannels = iChannels | KImpsCirTcp;
        // if UDP were supported
        if ( ( iReqChannels & KImpsCirUdp ) &&
             !( iChannels & KImpsCirUdp ) )
            {
            // load UDP listener synchronously
            DoOpenUDP( iUDPPort );
            }
        }

    // Everything is OK and opened
    iState = EImpsCirOnline;
    iServer.CirChOpened();
    }

// ---------------------------------------------------------
// CImpsCirManager::DoCancel
// ---------------------------------------------------------
//
void CImpsCirManager::DoCancel()
    {
#ifndef _NO_IMPS_LOGGING_
    CImpsClientLogger::Log( _L( "CImpsCirManager: DoCancel" ) );
#endif
    // This just waits IAP connection operation to end.
    iCanceled = ETrue;
    if ( iState == EImpsCirOpeningTcp )
        {
        // This returns KErrCancel if an operation is not ready
        iTCPWatcher->StopTCPWatcher();
        }
    }

// ---------------------------------------------------------
// CImpsCirManager::ActivateMe
// ---------------------------------------------------------
//
TInt CImpsCirManager::ActivateMe(  )
    {
    if ( !IsActive() )
        {
        iStatus = KRequestPending;
        SetActive();
        iCanceled = EFalse;
        return KErrNone;
        }
    else
        {
        return KErrNotReady;
        }
    }



//  End of File