wlanutilities/wlansniffer/wlansnifferkeepalive/src/wsfkeepalive.cpp
author Dremov Kirill (Nokia-D-MSW/Tampere) <kirill.dremov@nokia.com>
Tue, 31 Aug 2010 16:18:40 +0300
branchRCL_3
changeset 24 63be7eb3fc78
permissions -rw-r--r--
Revision: 201029 Kit: 201035

/*
* Copyright (c) 2010 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:
* Main implementation of Wlan Sniffer Keepalive application.
*/

// System include files

#include <rconnmon.h>

// User include files

#include "wsfkeepalivetimer.h"
#include "wsfkeepalivecmm.h"
#include "wsfkeepaliveconnmon.h"
#include "wsfkeepaliveconnmondisc.h"
#include "wsfkeepaliveesock.h"
#include "wsfkeepalive.h"
#include "OstTraceDefinitions.h"
#ifdef OST_TRACE_COMPILER_IN_USE
#include "wsfkeepaliveTraces.h"
#endif

// External function prototypes

// Local constants

// We need to poll for client info every 5 seconds
static const int KKeepalivePollInterval = 5000000;

// We can close a connection after 5 minutes of inactivity
static const int KKeepaliveInactivityInterval = 300;

// UID of Wlan sniffer application
static const TUid KWlanSnifferUid = { 0x10281CAA };

// UID of Wlan login application
static const TUid KWlanloginUid = { 0x2002E6D0 };

// List of UIDs of clients not considered as "real"
static const TUid KDiscardedClientUids[] = 
    {
        { 0x2002FF5F }, // Sniffer keepalive process, that is, us
        KWlanSnifferUid, // Sniffer application (wlansniffer.exe)
        KWlanloginUid, //   Wlan Login application (wlanlogin.exe)
        { 0x101fD9C5 }  // DHCP server (dhcpserv.exe)
    };

// ======== LOCAL FUNCTIONS ========

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

CWsfKeepalive* CWsfKeepalive::NewL()
    {
    OstTraceFunctionEntry0( CWSFKEEPALIVE_NEWL_ENTRY );
    
    CWsfKeepalive* me = new ( ELeave ) CWsfKeepalive();
    CleanupStack::PushL( me );
    me->ConstructL();
    CleanupStack::Pop( me );
    
    OstTraceFunctionExit0( CWSFKEEPALIVE_NEWL_EXIT );
    return me;
    }

CWsfKeepalive::~CWsfKeepalive()
    {
    OstTraceFunctionEntry0( DUP1_CWSFKEEPALIVE_CWSFKEEPALIVE_ENTRY );

    delete iEsock;
    delete iConnMonDisc;
    delete iCmMgr;
    delete iConnMon;
    delete iTimer;
    
    OstTraceFunctionExit0( DUP1_CWSFKEEPALIVE_CWSFKEEPALIVE_EXIT );
    }

void CWsfKeepalive::TimerExpired( TInt aError )
    {
    OstTraceFunctionEntry0( CWSFKEEPALIVE_TIMEREXPIRED_ENTRY );

    TBool restartTimer = ETrue; // Should we restart timer or not?
    if ( aError == KErrNone )
        {
        // Timer successfully completed, handle it
        if ( NoRealClients( iConnectionId ) )
            {
            TTime now;
            now.UniversalTime();
            
            // Check whether we are moving from EActiveWithClients to
            // EActiveNoClients
            if ( iState == EActiveWithClients )
                {
                OstTrace0(
                    TRACE_NORMAL,
                    CWSFKEEPALIVE_TIMEREXPIRED_RESET,
                    "CWsfKeepalive::TimerExpired Keepalive time reset" );
        
                // Connection had clients, but doesn't anymore. Keepalive
                // inactivity time starts now
                iKeepaliveStart = now;
                }
            // Check whether keepalive time has been reached
            else if ( iKeepaliveStart +
                TTimeIntervalSeconds( KKeepaliveInactivityInterval ) <= now )
                {
                OstTrace0(
                    TRACE_NORMAL,
                    CWSFKEEPALIVE_TIMEREXPIRED_DONE,
                    "CWsfKeepalive::TimerExpired Keepalive time expired" );
                
                // Keepalive time limit expired, connection should be stopped
                iEsock->Disconnect();
                iConnMonDisc->Disconnect( iConnectionId );
                restartTimer = EFalse;
                }
            
            // There are now no real clients for the connection
            SetState( EActiveNoClients );
            }
        else
            {
            // One or more real clients are using the connection
            SetState( EActiveWithClients );
            }
        }
    else
        {
        // Timer not successful, probably because we stopped it
        restartTimer = EFalse;
        }

    if ( restartTimer )
        {
        TTimeIntervalMicroSeconds32 interval( KKeepalivePollInterval );
        iTimer->After( interval );
        }
    
    OstTraceFunctionExit0( CWSFKEEPALIVE_TIMEREXPIRED_EXIT );
    }

void CWsfKeepalive::WlanConnectionOpenedL( TUint aConnectionId, TUint aIapId )
    {
    OstTraceFunctionEntry0( CWSFKEEPALIVE_WLANCONNECTIONOPENEDL_ENTRY );
    
    OstTraceExt2(
        TRACE_NORMAL,
        CWSFKEEPALIVE_WLANCONNECTIONOPENED,
        "CWsfKeepalive::WlanConnectionOpened;aConnectionId=%u;aIapId=%u",
        aConnectionId,
        aIapId );

    // We are only interested in connections opened by the Wlan Sniffer
    if ( OpenedByWlanSniffer( aConnectionId ) )
        {
        // Start to monitor this connection, and add us as a user to the
        // connection
        iConnectionId = aConnectionId;
        iIapId = aIapId;
        iEsock->ConnectL( aIapId );

        // Assume there are no real clients yet. Setup timer for polling
        // when real clients might be added to the connection
        SetState( EActiveNoClients );
        iKeepaliveStart.UniversalTime();
        
        OstTrace0(
            TRACE_NORMAL,
            CWSFKEEPALIVE_WLANCONNECTIONOPENED_RESET,
            "CWsfKeepalive::WlanConnectionOpened Keepalive time reset" );
        
        TTimeIntervalMicroSeconds32 interval( KKeepalivePollInterval );
        iTimer->After( interval );
        }
    
    OstTraceFunctionExit0( CWSFKEEPALIVE_WLANCONNECTIONOPENEDL_EXIT );
    }

void CWsfKeepalive::WlanConnectionClosed()
    {
    OstTraceFunctionEntry0( CWSFKEEPALIVE_WLANCONNECTIONCLOSED_ENTRY );

    // No need to monitor anything anymore
    SetState( EInactive );
    iConnectionId = KInvalidConnectionId;
    // Stop also the polling timer
    iTimer->Stop();
    
    OstTrace1(
        TRACE_NORMAL,
        CWSFKEEPALIVE_WLANCONNECTIONCLOSED_IAPID,
        "CWsfKeepalive::WlanConnectionClosed iapId=%d",
        iIapId );
    
    // If connected to hotspot IAP, the IAP must be deleted
    if ( iCmMgr->GetHotspotInfoL( iIapId ) )
        {
        OstTrace0(
            TRACE_NORMAL,
            CWSFKEEPALIVE_WLANCONNECTIONCLOSED_HOTSPOTDETECTED,
            "CWsfKeepalive::WlanConnectionClosed Hotspot IAP detected" );

        if ( !iCmMgr->DeleteHotspotIapL( iIapId ) )
            {
            OstTrace0(
                TRACE_NORMAL,
                CWSFKEEPALIVE_WLANCONNECTIONCLOSED_HOTSPOTDELETEFAILED,
                "CWsfKeepalive::WlanConnectionClosed Hotspot delete failed" );
            }
        iIapId = 0;
        }
    
    OstTraceFunctionExit0( CWSFKEEPALIVE_WLANCONNECTIONCLOSED_EXIT );
    }

// ---------------------------------------------------------------------------
// Default constructor
// ---------------------------------------------------------------------------
//
CWsfKeepalive::CWsfKeepalive() :
    iConnectionId( KInvalidConnectionId ),
    iState( EInactive ),
    iIapId( 0 )
    {
    OstTraceFunctionEntry0( CWSFKEEPALIVE_CWSFKEEPALIVE_ENTRY );
    OstTraceFunctionExit0( CWSFKEEPALIVE_CWSFKEEPALIVE_EXIT );
    }

// ---------------------------------------------------------------------------
// Leaving constructor
// ---------------------------------------------------------------------------
//
void CWsfKeepalive::ConstructL()
    {
    OstTraceFunctionEntry0( CWSFKEEPALIVE_CONSTRUCTL_ENTRY );
    
    iTimer = CWsfKeepaliveTimer::NewL( *this );
    iConnMon = CWsfKeepaliveConnMon::NewL( *this );
    iConnMonDisc = CWsfKeepaliveConnMonDisc::NewL();
    iEsock = CWsfKeepaliveEsock::NewL();
    iCmMgr = CWsfKeepaliveCmm::NewL();
    
    OstTraceFunctionExit0( CWSFKEEPALIVE_CONSTRUCTL_EXIT );
    }
 
// ---------------------------------------------------------------------------
// Checks whether the given connection was opened by the Wlan Sniffer
// application
// ---------------------------------------------------------------------------
//
TBool CWsfKeepalive::OpenedByWlanSniffer( TUint aConnectionId )
    {
    OstTraceFunctionEntry0( CWSFKEEPALIVE_OPENEDBYWLANSNIFFER_ENTRY );
    
    TBool retVal = EFalse;

    // Get all clients of this connection
    TConnMonClientEnumBuf clientInfo;
    iConnMon->GetClientInfo( clientInfo, aConnectionId );

    // Check whether Wlan sniffer is one of the clients
    for ( TInt i( 0 ); i < clientInfo().iCount; ++i )
        {
        if ( clientInfo().iUid[i] == KWlanSnifferUid )
            {
            // Match found, stop looking
            retVal = ETrue;
            break;
            }
        }
    
    OstTraceExt2(
        TRACE_NORMAL,
        CWSFKEEPALIVE_OPENEDBYWLANSNIFFER,
        "CWsfKeepalive::OpenedByWlanSniffer;aConnectionId=%u;retVal=%u",
        aConnectionId,
        retVal );
    
    OstTraceFunctionExit0( CWSFKEEPALIVE_OPENEDBYWLANSNIFFER_EXIT );
    return retVal;
    }

// ---------------------------------------------------------------------------
// Checks whether there are any real clients using the given connection
// ---------------------------------------------------------------------------
//
TBool CWsfKeepalive::NoRealClients( TUint aConnectionId )
    {
    OstTraceFunctionEntry0( CWSFKEEPALIVE_NOREALCLIENTS_ENTRY );
    
    // Get all clients of this connection
    TConnMonClientEnumBuf clientInfo;
    iConnMon->GetClientInfo( clientInfo, aConnectionId );

    // Get the client count
    TInt clientCount = clientInfo().iCount;

    TInt discardedClientCount = sizeof( KDiscardedClientUids ) / sizeof( TUid );
    
    // Decrease count by each non-real client we must discard
    for ( TInt i( 0 ); i < clientInfo().iCount; ++i )
        {
        for ( TInt j( 0 ); j < discardedClientCount; ++j )
            {
            if ( clientInfo().iUid[i] == KDiscardedClientUids[j] )
                {
                OstTrace1(
                    TRACE_NORMAL,
                    CWSFKEEPALIVE_NOREALCLIENTS_DISCARD,
                    "CWsfKeepalive::NoRealClients Client discarded;clientInfo().iUid[i].iUid=%x",
                    clientInfo().iUid[i].iUid );
                --clientCount;
                break;
                }
            }
        }

    // If we reached zero, there were no real clients
    TBool retVal = clientCount == 0 ? ETrue : EFalse;
    OstTraceExt2(
        TRACE_NORMAL,
        CWSFKEEPALIVE_NOREALCLIENTS,
        "CWsfKeepalive::NoRealClients;aConnectionId=%u;retVal=%u",
        aConnectionId,
        retVal );
    
    OstTraceFunctionExit0( CWSFKEEPALIVE_NOREALCLIENTS_EXIT );
    return retVal;
    }

// ---------------------------------------------------------------------------
// Sets the given state and traces the transition, if state changed.
// ---------------------------------------------------------------------------
//
void CWsfKeepalive::SetState( TUint aState )
    {
    OstTraceFunctionEntry0( CWSFKEEPALIVE_SETSTATE_ENTRY );

#ifdef OST_TRACE_COMPILER_IN_USE
    if ( aState != iState )
        {
        OstTrace1(
            TRACE_NORMAL,
            CWSFKEEPALIVE_SETSTATE,
            "CWsfKeepalive::SetState;aState=%{State}",
            aState );
        }
#endif
    iState = aState;
    
    OstTraceFunctionExit0( CWSFKEEPALIVE_SETSTATE_EXIT );
    }