wlanutilities/wlansniffer/engine/server/src/wsfwlanbearerconnectionmonitor.cpp
changeset 0 56b72877c1cb
child 1 d07e190ed096
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/wlanutilities/wlansniffer/engine/server/src/wsfwlanbearerconnectionmonitor.cpp	Thu Dec 17 09:20:28 2009 +0200
@@ -0,0 +1,1153 @@
+/*
+* Copyright (c) 2007-2008 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:  Implementation of CWsfWlanBearerConnectionMonitor
+*
+*/
+
+
+
+//  EXTERNAL INCLUDES
+#include <utf.h>
+#include <cmpluginwlandef.h>
+#include <commdbconnpref.h>
+#include <wlanerrorcodes.h>
+#include <cmconnectionmethodext.h>
+#include <commdb.h>
+#include <WlanCdbCols.h>
+
+
+
+//  CLASS HEADER
+#include "wsfwlanbearerconnectionmonitor.h"
+
+//  INTERNAL INCLUDES
+#include "wsfwlanmonitorobserver.h"
+#include "wsflogger.h"
+#include "wsfactivewaiter.h"
+#include "wsfservercloseradapter.h"
+#include "wsfcommon.h"
+
+
+//  LOCAL DEFINITIONS
+using namespace CMManager;
+
+
+#ifdef _DEBUG
+    _LIT( KWlanConnMonPanic, "wsfwlanconnmon" );
+    #define __ASSERTD(x) __ASSERT_DEBUG( (x), \
+                                User::Panic( KWlanConnMonPanic, __LINE__ ) );
+#else
+    #define __ASSERTD(x)
+#endif                                
+
+
+//  LOCAL CONSTANTS
+/**
+* Connection id referring to a non-existing connection
+*/
+static const TInt KNoConnection = -1;
+
+/**
+* Max allowed connection inactivity time in seconds
+*/
+static const TUint KMaxConnectionInactivityTime = 60;
+
+
+/**
+* Client polling interval in microseconds
+*/
+static const TUint KClientPollInterval = 5 * 1000 * 1000;
+
+
+/**
+* Number of trivial clients of a connection (Sniffer, AI/CP plugin etc)
+*/
+static const TUint KTrivialClientCount = 2;
+
+/**
+* List of UIDs of the trivial clients
+*/
+static const TUid KTrivialClientUids[KTrivialClientCount] = 
+    {
+    { 0x10281CAB },         // Sniffer server (wsfserver.exe)
+    { 0x101fD9C5 }          // DHCP server (dhcpserv.exe)
+    };
+
+
+
+//  CONSTRUCTION AND DESTRUCTION
+
+
+// ---------------------------------------------------------------------------
+// CWsfWlanBearerConnectionMonitor::NewL
+// ---------------------------------------------------------------------------
+//
+CWsfWlanBearerConnectionMonitor* CWsfWlanBearerConnectionMonitor::NewL( 
+                                  MWsfServerCloserAdapter& aServerCloser )
+    {
+    CWsfWlanBearerConnectionMonitor* thisPtr = NewLC( aServerCloser );
+    CleanupStack::Pop( thisPtr );
+    return thisPtr;
+    }
+    
+
+// ---------------------------------------------------------------------------
+// CWsfWlanBearerConnectionMonitor::NewLC
+// ---------------------------------------------------------------------------
+//
+CWsfWlanBearerConnectionMonitor* CWsfWlanBearerConnectionMonitor::NewLC( 
+                                  MWsfServerCloserAdapter& aServerCloser )
+    {
+    CWsfWlanBearerConnectionMonitor* thisPtr = 
+           new (ELeave) CWsfWlanBearerConnectionMonitor( aServerCloser );
+    CleanupStack::PushL( thisPtr );
+    thisPtr->ConstructL();
+    return thisPtr;
+    }
+    
+
+// ---------------------------------------------------------------------------
+// CWsfWlanBearerConnectionMonitor::~CWsfWlanBearerConnectionMonitor
+// ---------------------------------------------------------------------------
+//
+CWsfWlanBearerConnectionMonitor::~CWsfWlanBearerConnectionMonitor()
+    {
+    LOG_ENTERFN( "CWsfWlanBearerConnectionMonitor::"
+                 L"~CWsfWlanBearerConnectionMonitor" );
+    iMonitor.CancelNotifications();
+    iMonitor.Close();
+
+    Cancel();
+
+    if ( iConnectionOwned )
+        {
+        // in case Cancel() hasn't done the job
+        TRAP_IGNORE( ShutdownOwnedConnectionL() );
+        }
+    else if ( iMonitoredAp )
+        {
+        
+        }
+
+    delete iClientPoll;
+
+    iCmMgr.Close();
+    }
+    
+
+// ---------------------------------------------------------------------------
+// CWsfWlanBearerConnectionMonitor::CWsfWlanBearerConnectionMonitor
+// ---------------------------------------------------------------------------
+//
+CWsfWlanBearerConnectionMonitor::CWsfWlanBearerConnectionMonitor( 
+                                MWsfServerCloserAdapter& aServerCloser ):
+    CActive( CActive::EPriorityStandard ),
+    iConnectionId( KNoConnection ),
+    iMonitoring( EFalse ),
+    iConnectingState( ECsIdle ),
+    iServerCloser( aServerCloser )
+    {
+    CActiveScheduler::Add( this );
+    }
+    
+
+// ---------------------------------------------------------------------------
+// CWsfWlanBearerConnectionMonitor::ConstructL
+// ---------------------------------------------------------------------------
+//
+void CWsfWlanBearerConnectionMonitor::ConstructL()
+    {
+    LOG_ENTERFN( "CWsfWlanBearerConnectionMonitor::ConstructL" );
+    iCmMgr.OpenL();
+    iMonitor.ConnectL();
+    iClientPoll = CPeriodic::NewL( CActive::EPriorityLow );
+    FindWlanBearerConnectedL();
+    }
+    
+
+// ---------------------------------------------------------------------------
+// CWsfWlanBearerConnectionMonitor::GetWlanBearerNameL
+// ---------------------------------------------------------------------------
+//
+const TDesC& CWsfWlanBearerConnectionMonitor::GetWlanBearerNameL()
+    {
+    LOG_ENTERFN( "CWsfWlanBearerConnectionMonitor::GetWlanBearerNameL" );
+    if ( iConnectionId == KNoConnection )
+        {
+        LOG_WRITE( "[no connection]" );
+        return KNullDesC();
+        }
+        
+    LOG_WRITEF( "connection name: %S", &iWlanNetworkName );
+    return iWlanNetworkName;
+    }
+
+
+// ---------------------------------------------------------------------------
+// CWsfWlanBearerConnectionMonitor::FindWlanBearerConnectedL
+// ---------------------------------------------------------------------------
+//
+void CWsfWlanBearerConnectionMonitor::FindWlanBearerConnectedL()
+    {
+    LOG_ENTERFN( "CWsfWlanBearerConnectionMonitor::FindWlanBearerConnectedL" );
+    CWsfActiveWaiter* waiter = CWsfActiveWaiter::NewLC();
+    TUint connectionNumber( 0 );
+
+    iMonitor.GetConnectionCount( connectionNumber, waiter->iStatus );
+    waiter->WaitForRequest();
+    
+    if ( !waiter->iStatus.Int() )
+        {
+        TBool connectionIDFound = EFalse;
+        for ( TUint i = 1; i <= connectionNumber; ++i )
+            {
+            TUint connectionId( 0 );
+            TUint subConnectionCount( 0 );
+            
+            User::LeaveIfError( iMonitor.GetConnectionInfo( i, connectionId, 
+                                                        subConnectionCount ) );
+            if ( CheckConnectionDetailsL( connectionId ) )
+                {
+                LOG_WRITEF( "found connection %d", connectionId );
+                connectionIDFound = ETrue;
+                iConnectionId = connectionId;
+                break;
+                }
+            }
+        if ( !connectionIDFound )
+            {
+            LOG_WRITE( "Reset connection ID" );
+            iConnectionId = KNoConnection;
+            }
+        }
+    else
+        {
+        LOG_WRITEF( "GetConnectionCount failed error = %d", 
+                                                    waiter->iStatus.Int() );
+        }
+        
+    CleanupStack::PopAndDestroy( waiter );
+    }
+ 
+            
+// ---------------------------------------------------------------------------
+// CWsfWlanBearerConnectionMonitor::EventL
+// ---------------------------------------------------------------------------
+//
+void CWsfWlanBearerConnectionMonitor::EventL( 
+                                       const CConnMonEventBase& aConnMonEvent )
+    {
+    LOG_ENTERFN( "CWsfWlanBearerConnectionMonitor::EventL" );
+
+    TConnMonEvent event = TConnMonEvent( aConnMonEvent.EventType() );
+    TInt connectionId = aConnMonEvent.ConnectionId();
+
+    LOG_WRITEF( "event = %d", (TInt)event );
+    
+    switch ( event )
+        {
+        case EConnMonCreateConnection:
+            {
+            LOG_WRITEF( "EConnMonCreateConnection id = %d", 
+                        connectionId );
+            break;
+            }
+
+        case EConnMonConnectionStatusChange:
+            {
+            LOG_WRITEF( "EConnMonConnectionStatusChange id = %d", 
+                        connectionId );
+                        
+            const CConnMonConnectionStatusChange* statusChangeEvent = 
+                        static_cast<const CConnMonConnectionStatusChange*>( 
+                                                              &aConnMonEvent );
+                        
+            LOG_WRITEF( "EConnMonConnectionStatusChange status = %d", 
+                        statusChangeEvent->ConnectionStatus() );
+            
+            if ( statusChangeEvent->ConnectionStatus() == KConnectionOpen &&
+                 !iConnectionOwned )
+                {
+                LOG_WRITE( "connection status: open" );
+                TBool wlanEvent( EFalse );
+                
+                wlanEvent = CheckConnectionDetailsL( connectionId );
+                if ( wlanEvent )
+                    {
+                    LOG_WRITEF( "[%S] connected, id = %d", 
+                                &iWlanNetworkName, connectionId );
+
+                    // notify observer ...
+                    iConnectionId = connectionId;
+                    iObserver->ConnectionEstablishedL( iWlanNetworkName );
+                    }
+                }
+            break;
+            }                
+            
+        case EConnMonDeleteConnection:
+            {
+            LOG_WRITEF( "EConnMonDeleteConnection id = %d", connectionId );
+
+            if ( connectionId == iConnectionId )
+                {
+                if ( iConnectionOwned )
+                    {
+                    LOG_WRITE( "connection was owned, manual closing" );
+                    ShutdownOwnedConnectionL();
+                    }
+                else
+                    {
+                    LOG_WRITE( "connection was not owned" );
+                    iWlanNetworkName.Zero();
+                    iConnectionId = KNoConnection;
+                    
+                    // notify observer
+                    iObserver->ConnectionLostL();
+                    }
+                }
+            break;
+            }
+        
+        default:
+            {
+            }
+        }
+    }
+    
+
+// ---------------------------------------------------------------------------
+// CWsfWlanBearerConnectionMonitor::CheckConnectionDetailsL
+// ---------------------------------------------------------------------------
+//
+TBool CWsfWlanBearerConnectionMonitor::CheckConnectionDetailsL( 
+                                                         TUint aConnectionId )
+    {
+    LOG_ENTERFN( "CWsfWlanBearerConnectionMonitor::CheckConnectionDetailsL" );
+    LOG_WRITEF( "aConnectionId: %d", aConnectionId );
+    TConnMonBearerType bearerType( EBearerUnknown );
+
+    TBool foundWlanBearer( EFalse );
+
+    // Add only connections with valid id
+    if ( aConnectionId > 0 )
+        {
+        CWsfActiveWaiter* waiter = CWsfActiveWaiter::NewLC();
+        iMonitor.GetIntAttribute( aConnectionId, 0, KBearer, 
+                                  (TInt&)bearerType, 
+                                  waiter->iStatus );
+        waiter->WaitForRequest();
+        LOG_WRITEF( "found bearer: %d", bearerType );        
+
+        if ( waiter->iStatus.Int() == KErrNone )
+            {
+            LOG_WRITE( "status: KErrNone" );
+            if ( bearerType == EBearerWLAN )
+                {
+                
+                iMonitor.GetStringAttribute( aConnectionId, 0, KNetworkName, 
+                                         iWlanNetworkName, waiter->iStatus );
+                waiter->WaitForRequest();        
+                if ( waiter->iStatus.Int() == KErrNone )
+                    {
+                    LOG_WRITEF( "WLAN network name: %S", &iWlanNetworkName );
+                    foundWlanBearer = ETrue;
+                    }
+                
+                }
+            }
+        else
+            {
+            LOG_WRITEF( "status: %d", waiter->iStatus.Int() );
+            }
+        CleanupStack::PopAndDestroy( waiter );
+        }
+
+    return foundWlanBearer;
+    }
+    
+
+// ---------------------------------------------------------------------------
+// CWsfWlanBearerConnectionMonitor::StartMonitoringL
+// ---------------------------------------------------------------------------
+//
+void CWsfWlanBearerConnectionMonitor::StartMonitoringL( 
+                                           MWsfWlanMonitorObserver* aObserver )
+    {
+    LOG_ENTERFN( "CWsfWlanBearerConnectionMonitor::StartMonitoringL" );        
+    __ASSERTD( aObserver );
+
+    iObserver = aObserver;
+    if ( !iMonitoring )
+        {
+        iMonitoring = ETrue;
+        iMonitor.NotifyEventL( *this );
+        }
+    }
+    
+
+// ---------------------------------------------------------------------------
+// CWsfWlanBearerConnectionMonitor::StopMonitoring
+// ---------------------------------------------------------------------------
+//
+void CWsfWlanBearerConnectionMonitor::StopMonitoring()
+    {
+    LOG_ENTERFN( "CWsfWlanBearerConnectionMonitor::StopMonitoring" );        
+
+    if ( iMonitoring )
+        {
+        iMonitoredAp = 0;
+        iMonitoring = EFalse;
+        iMonitor.CancelNotifications();
+        }
+    }
+    
+
+// ---------------------------------------------------------------------------
+// CWsfWlanBearerConnectionMonitor::ConnectBearer
+// ---------------------------------------------------------------------------
+//
+TInt CWsfWlanBearerConnectionMonitor::ConnectBearer( TUint32 aIapId )
+    {
+    LOG_ENTERFN( "CWsfWlanBearerConnectionMonitor::ConnectBearer" );
+    
+    if ( iConnectionId != KNoConnection || iConnectingState != ECsIdle )
+        {
+        // there is already a connection
+        LOG_WRITE( "there is already a WLAN connection" );
+        return KErrWlanConnAlreadyActive;
+        }
+    
+    // self-completion
+    if ( iConnectingState == ECsIdle )
+        {
+        LOG_WRITE( "initiating connection process" );
+        iConnIap = aIapId;
+        iConnectingState = ECsNotConnected;
+        iConnectionOwned = ETrue;
+        iServerCloser.WaitForOwnedConnection( ETrue );
+
+        SetActive();
+        TRequestStatus* status = &iStatus;
+        User::RequestComplete( status, KErrNone );
+        }
+    
+    return KErrNone;
+    }
+
+
+// ---------------------------------------------------------------------------
+// CWsfWlanBearerConnectionMonitor::DisconnectBearer
+// ---------------------------------------------------------------------------
+//
+TBool CWsfWlanBearerConnectionMonitor::DisconnectBearer()
+    {
+    LOG_ENTERFN( "CWsfWlanBearerConnectionMonitor::DisconnectBearer" );
+
+    if ( iConnectionId != KNoConnection )
+        {
+        LOG_WRITEF( "closing connection id = %d", iConnectionId );
+        iMonitor.SetBoolAttribute( iConnectionId, 0, KConnectionStop, ETrue );
+        }
+
+    return ( iConnectionId != KNoConnection );
+    }
+
+
+// ---------------------------------------------------------------------------
+// CWsfWlanBearerConnectionMonitor::AbortConnecting
+// ---------------------------------------------------------------------------
+//
+void CWsfWlanBearerConnectionMonitor::AbortConnecting()
+    {
+    LOG_ENTERFN( "CWsfWlanBearerConnectionMonitor::AbortConnecting" );
+    
+    if ( iConnectingState != ECsIdle )
+        {
+        LOG_WRITE( "connection in progress, aborting");
+        iAborting = ETrue;
+        
+        if ( IsActive() && iConnectingState == ECsSocketOpened )
+            {
+            LOG_WRITE( "forcing connection to stop" );
+            iConnection.Stop();
+            }
+        }
+    }
+    
+
+// ---------------------------------------------------------------------------
+// CWsfWlanBearerConnectionMonitor::MonitorAccessPoint
+// ---------------------------------------------------------------------------
+//
+void CWsfWlanBearerConnectionMonitor::MonitorAccessPoint( TUint32 aIapId )    
+    {
+    LOG_ENTERFN( "CWsfWlanBearerConnectionMonitor::MonitorAccessPoint" );
+    iMonitoredAp = aIapId;
+    }
+
+
+// ---------------------------------------------------------------------------
+// CWsfWlanBearerConnectionMonitor::ConnectedWlanConnectionDetailsL
+// ---------------------------------------------------------------------------
+//
+TBool CWsfWlanBearerConnectionMonitor::ConnectedWlanConnectionDetailsL( 
+                                                     TWsfWlanInfo* aWlanInfo )
+    {
+    LOG_ENTERFN( "CWsfWlanBearerConnectionMonitor::"
+                 L"ConnectedWlanConnectionDetailsL" );
+    
+    LOG_WRITEF( "Monitor iConnectingState =%d and iConnectionId = %d", 
+                         iConnectingState, iConnectionId );
+    
+    if ( iConnectingState == ECsIdle )
+        {
+        // Make sure that we have connection id
+        FindWlanBearerConnectedL();
+        }
+    
+    if ( iConnectionId == KNoConnection )
+        {
+        return EFalse;
+        }
+    
+    // get the data's from the monitor add them to aWlanInfo..
+    aWlanInfo->iConnectionState = EConnected;
+    aWlanInfo->iVisibility = 1;
+    aWlanInfo->iCoverage = 1;
+    aWlanInfo->iNetworkName = KNullDesC8;
+    
+    CWsfActiveWaiter* waiter = CWsfActiveWaiter::NewLC();
+    
+    // security mode
+    TInt securityAttribute( EWlanConnectionSecurityOpen );
+    iMonitor.GetIntAttribute( iConnectionId, 0, KSecurityMode, 
+                              securityAttribute, waiter->iStatus );
+    waiter->WaitForRequest();
+    
+    if ( waiter->iStatus.Int() != KErrNone )
+        {
+        aWlanInfo->iConnectionState = ENotConnected;
+        CleanupStack::PopAndDestroy( waiter );
+        return EFalse;
+        }
+
+    switch ( securityAttribute )
+        {
+        case EConnMonSecurityWep:
+            {
+            aWlanInfo->iSecurityMode = EWlanSecModeWep;
+            break;
+            }
+
+        case EConnMonSecurity802d1x:
+            {
+            aWlanInfo->iSecurityMode = EWlanSecMode802_1x;
+            break;
+            }
+
+        case EConnMonSecurityWpa:       // fall-through
+        case EConnMonSecurityWpaPsk:
+            {
+            aWlanInfo->iSecurityMode = EWlanSecModeWpa;
+            break;
+            }
+
+        case EConnMonSecurityOpen:      // fall-through
+        default:
+            {
+            aWlanInfo->iSecurityMode = EWlanSecModeOpen;
+            }
+        }    
+    LOG_WRITEF( "conn.secmode = %d", aWlanInfo->iSecurityMode );
+
+    // network mode    
+    TInt networkModeAttribute( 0 );
+    
+    iMonitor.GetIntAttribute( iConnectionId, 0, KNetworkMode, 
+                              networkModeAttribute, waiter->iStatus );
+    waiter->WaitForRequest();  
+    
+    if ( waiter->iStatus.Int() != KErrNone )
+        {
+        aWlanInfo->iConnectionState = ENotConnected;
+        CleanupStack::PopAndDestroy( waiter );
+        return EFalse;
+        }
+
+    if ( networkModeAttribute == EConnMonAdHoc )
+        {
+        aWlanInfo->iNetMode = EAdhoc;
+        }
+    else
+        {
+        aWlanInfo->iNetMode = EInfra;
+        }
+        
+    LOG_WRITEF( "conn.netmode = %d", aWlanInfo->iNetMode );
+
+    // iap id
+    TUint iapIdAttribute( 0 );
+    iMonitor.GetUintAttribute( iConnectionId, 0, KIAPId, 
+                              iapIdAttribute, waiter->iStatus );
+    waiter->WaitForRequest();  
+    
+    if ( waiter->iStatus.Int() != KErrNone )
+        {
+        aWlanInfo->iConnectionState = ENotConnected;
+        CleanupStack::PopAndDestroy( waiter );
+        return EFalse;
+        }
+    
+    aWlanInfo->iIapId = iapIdAttribute;
+    
+    LOG_WRITEF( "conn.iap = %d", aWlanInfo->iIapId );
+
+    // signal strength
+    TInt signStrengthAttribute( 0 );          
+    iMonitor.GetIntAttribute( iConnectionId, 0, KSignalStrength, 
+                              signStrengthAttribute, waiter->iStatus );
+    waiter->WaitForRequest(); 
+	
+	if ( waiter->iStatus.Int() != KErrNone )
+        {
+        aWlanInfo->iConnectionState = ENotConnected;
+        CleanupStack::PopAndDestroy( waiter );
+        return EFalse;
+        }
+	
+    aWlanInfo->iStrengthLevel = signStrengthAttribute;
+    LOG_WRITEF( "conn.signalstrength = %d", aWlanInfo->iStrengthLevel );
+    
+    if ( aWlanInfo->iIapId )
+        {
+        LOG_WRITE( "IAP id != 0" );
+        
+        RCmConnectionMethodExt cm = iCmMgr.ConnectionMethodL( aWlanInfo->iIapId );
+        CleanupClosePushL( cm );
+        HBufC* buf = NULL;
+        
+        if ( iCmMgr.EasyWlanIdL() != aWlanInfo->iIapId )
+            {
+            LOG_WRITE( "not EasyWLAN" );
+            buf = cm.GetStringAttributeL( ECmName );
+            }
+        else
+            {
+            LOG_WRITE("Sniffer:EasyWLAN IAP ");
+            aWlanInfo->iIapId = 0;
+            buf = cm.GetStringAttributeL( EWlanUsedSSID );
+            }
+        
+        if ( buf )
+            {
+            TInt error = CnvUtfConverter::ConvertFromUnicodeToUtf8( 
+                                                        aWlanInfo->iSsid, 
+                                                        *buf  );
+            if ( error )
+                {
+                LOG_WRITE( "ConvertFromUnicodeToUtf8 failed");
+                aWlanInfo->iSsid.Copy( *buf );
+                }
+            delete buf;
+            }
+        CleanupStack::PopAndDestroy( &cm ); //cm
+        }
+    else
+        {
+        LOG_WRITE( "IAP id = 0" );
+        }
+
+#ifdef _DEBUG
+    // Iap & Ssid logging   
+    HBufC* nameUnicode = aWlanInfo->GetIapNameAsUnicodeLC();
+    LOG_WRITEF( "aWlanInfo->iNetworkName: [%S]", nameUnicode );
+    CleanupStack::PopAndDestroy( nameUnicode );
+    
+    HBufC* ssidUnicode = aWlanInfo->GetSsidAsUnicodeLC();
+    LOG_WRITEF( "aWlanInfo->tmpSsid: [%S]", ssidUnicode );
+    CleanupStack::PopAndDestroy( ssidUnicode );
+#endif
+
+    CleanupStack::PopAndDestroy( waiter );
+    
+    return ETrue;    
+    }
+
+   
+// ---------------------------------------------------------------------------
+// CWsfWlanBearerConnectionMonitor::IsConnected
+// ---------------------------------------------------------------------------
+//
+TBool CWsfWlanBearerConnectionMonitor::IsConnected()
+    {
+    return ( iConnectionId != KNoConnection );
+    }
+
+
+// ---------------------------------------------------------------------------
+// CWsfWlanBearerConnectionMonitor::CheckClientCount
+// ---------------------------------------------------------------------------
+//
+TInt CWsfWlanBearerConnectionMonitor::CheckClientCount( TAny* aPtr )
+    {
+    LOG_ENTERFN( "CWsfWlanBearerConnectionMonitor::CheckClientCount" );
+    CWsfWlanBearerConnectionMonitor* self = 
+                         static_cast<CWsfWlanBearerConnectionMonitor*>( aPtr );
+    TInt err( KErrNone );
+    
+    if ( !self->iClientCountMutex )
+        {
+        // in some rare cases this function is reentered because of the 
+        // active scheduler waits, so we need a mutex
+        self->iClientCountMutex = ETrue;
+        
+        TRAP( err, self->CheckClientCountL() );
+        
+        self->iClientCountMutex = EFalse;
+        }    
+
+    return err;
+    }
+
+
+// ---------------------------------------------------------------------------
+// CWsfWlanBearerConnectionMonitor::CheckClientCountL
+// ---------------------------------------------------------------------------
+//
+void CWsfWlanBearerConnectionMonitor::CheckClientCountL()
+    {
+    LOG_ENTERFN( "CWsfWlanBearerConnectionMonitor::CheckClientCountL" );
+    
+    CWsfActiveWaiter* waiter = CWsfActiveWaiter::NewL();
+    
+    TConnMonClientEnumBuf clientInfo;
+
+    iMonitor.GetPckgAttribute( iConnectionId, 0, 
+                               KClientInfo, 
+                               clientInfo, 
+                               waiter->iStatus );
+    waiter->WaitForRequest();
+    delete waiter;
+    
+    // get the client count
+    iClientCount = clientInfo().iCount;
+    
+    // decrease count by each trivial client (Sniffer server, DHCP etc)
+    for ( TInt i( 0 ); i < clientInfo().iCount; ++i )
+        {
+        for ( TInt j( 0 ); j < KTrivialClientCount; ++j )
+            {
+            if ( clientInfo().iUid[i] == KTrivialClientUids[j] )
+                {
+                --iClientCount;
+                LOG_WRITEF( "trivial client [0x%08X] discarded", 
+                            clientInfo().iUid[i].iUid );                
+                break;
+                }
+            }
+        }
+    
+    
+    LOG_WRITEF( "iClientCount = %d (trivial clients:%d)", 
+                iClientCount,
+                clientInfo().iCount - iClientCount );
+
+    if ( iAutoDisconnect )
+        {
+        if ( iClientCount )
+            {
+            // there are more clients than the default ones ->
+            // connection is considered active ->
+            // reset the inactivity start time to current time
+            iInactivityStart.UniversalTime();
+            
+            }
+        else
+            {
+            // there are only trivial clients of the connection
+            // this means inactivity, so check the time elapsed
+            LOG_WRITEF( "Connection monitor state = %d", iConnectingState );
+            TTime now;
+            now.UniversalTime();
+
+            if ( iInactivityStart + TTimeIntervalSeconds( 
+                                       KMaxConnectionInactivityTime ) <= now )
+                {
+                // inactivity time limit elapsed, connection should be stopped
+                LOG_WRITE( "inactivity threshold reached, disconnecting..." );
+                DisconnectBearer();
+                }
+            }
+        
+        }
+
+    }
+
+
+// ---------------------------------------------------------------------------
+// CWsfWlanBearerConnectionMonitor::ControlDisconnectTimer
+// ---------------------------------------------------------------------------
+//
+TBool CWsfWlanBearerConnectionMonitor::ControlDisconnectTimer( 
+                                                           TUint aAdcCommand )
+    {
+    LOG_ENTERFN("CWsfWlanBearerConnectionMonitor::ControlDisconnectTimer");    
+    
+    if ( iConnectionOwned )
+        {
+        if ( aAdcCommand & EAdcTimerReset )
+            {
+            // reset inactivity time
+            LOG_WRITE( "timer reset" );
+            iInactivityStart.UniversalTime();
+            }
+
+        if ( aAdcCommand & EAdcStartTimer ) 
+            {
+            if ( !iAutoDisconnect )
+                {
+                LOG_WRITE( "timer started" );
+                iAutoDisconnect = ETrue;
+                }
+            else
+                {
+                LOG_WRITE( "timer had already been started!" );
+                }
+            }
+        else
+            {
+            iAutoDisconnect = EFalse;
+            LOG_WRITE( "timer stopped" );
+            }
+
+        }
+    else
+        {
+        LOG_WRITE( "connection is not owned!" );
+        }
+        
+    return iAutoDisconnect;
+    }
+    
+
+// ---------------------------------------------------------------------------
+// CWsfWlanBearerConnectionMonitor::ReleaseShutdownMutex
+// ---------------------------------------------------------------------------
+//
+void CWsfWlanBearerConnectionMonitor::ReleaseShutdownMutex( TAny* aPtr )
+    {
+    CWsfWlanBearerConnectionMonitor* self = 
+                        static_cast<CWsfWlanBearerConnectionMonitor*>( aPtr );
+    self->iShutdownMutex = EFalse;
+    }
+
+
+// ---------------------------------------------------------------------------
+// CWsfWlanBearerConnectionMonitor::ShutdownOwnedConnectionL
+// ---------------------------------------------------------------------------
+//
+void CWsfWlanBearerConnectionMonitor::ShutdownOwnedConnectionL()
+    {
+    LOG_ENTERFN( "CWsfWlanBearerConnectionMonitor::ShutdownOwnedConnectionL" );
+    
+    // Make sure that the internal status is reset.
+    iConnectionId = KNoConnection;
+    
+    if ( iShutdownMutex )
+        {
+        return;
+        }
+        
+    // make sure we don't lock ourselves forever
+    CleanupStack::PushL( TCleanupItem( ReleaseShutdownMutex, this ) );
+    iShutdownMutex = ETrue;
+    
+    
+    // roll-back the changes
+    switch ( iConnectingState )
+        {
+        case ECsConnected:
+            {
+            // cancelling the periodic callback
+            iClientPoll->Cancel();
+            }
+            
+        case ECsPreferencesChanged:         // fall-through
+            {
+            // restoring default connection
+            TCmDefConnValue defConn;
+            TInt error = KErrNone;
+            
+            LOG_WRITE( "reading default connection" );
+            TRAP( error, iCmMgr.ReadDefConnL( defConn ) );
+            if ( error )
+                {
+                // Ignore possible failure and continue the cleanup
+                LOG_WRITEF( "ReadDefConnL returned error %d", error );
+                }
+            
+            if ( error == KErrNone && defConn == iCurrentDefConn )
+                {
+                // nobody has overwritten our setting so it's our duty to
+                // restore the original value
+                LOG_WRITE( "restoring default connection" );
+                TRAP( error, iCmMgr.WriteDefConnL( iOriginalDefConn ) );
+                if ( error )
+                    {
+                    // Ignore possible failure and continue the cleanup
+                    LOG_WRITEF( "WriteDefConnL returned error %d", error );
+                    }
+                }
+            }
+            
+        case ECsConnectionCreated:          // fall-through
+            {
+
+            }
+            
+        case ECsSocketOpened:               // fall-through
+            {
+            // closing the connection handle
+            iConnection.Close();
+            iSocketServ.Close();
+            }
+            
+        case ECsNotConnected:               // fall-through
+            {
+            // nothing to put here
+            }
+            
+        }
+
+
+    // reset the state machine
+    iConnectingState = ECsIdle;
+    iConnectionOwned = EFalse;
+
+    // tell the engine we have released the IAP 
+    iObserver->ConnectedIapReleasedL();
+
+    
+    iServerCloser.WaitForOwnedConnection( EFalse );
+    
+    if ( !iAborting )
+        {
+        // notify observers only if connection creation 
+        // was not aborted
+        iObserver->ConnectionLostL();
+        }
+
+    iAborting = EFalse;
+    
+    CleanupStack::PopAndDestroy( 1 ); // ReleaseShutdownMutex()
+    }
+
+
+// ---------------------------------------------------------------------------
+// CWsfWlanBearerConnectionMonitor::RunL
+// ---------------------------------------------------------------------------
+//
+void CWsfWlanBearerConnectionMonitor::RunL()
+    {
+    LOG_ENTERFN( "CWsfWlanBearerConnectionMonitor::RunL" );
+
+    if ( iAborting )
+        {
+        // if connection creation was aborted, do the cleanup
+        ShutdownOwnedConnectionL();
+        return;
+        }
+       
+    switch ( iConnectingState )
+        {
+        case ECsNotConnected:
+            {
+#ifdef __WINSCW__
+            User::After(5000000);
+#endif
+            LOG_WRITE( "<ENotConnected>" );
+
+            TInt err( KErrNone );
+            err = iSocketServ.Connect();
+            
+            if ( !err )
+                {
+                err = iConnection.Open( iSocketServ );
+                }
+            
+            if ( err )
+                {
+                // there was an error while connecting
+                LOG_WRITEF( "connection.Open error = %d", err );
+                ShutdownOwnedConnectionL();
+        
+                iObserver->ConnectingFailedL( err );
+                break;
+                }            
+
+            TCommDbConnPref connPref;
+            connPref.SetIapId( iConnIap );
+            connPref.SetDialogPreference( ECommDbDialogPrefDoNotPrompt );
+
+            iConnectingState = ECsSocketOpened;
+            SetActive();
+            iConnection.Start( connPref, iStatus );
+            break;
+            }
+            
+        case ECsSocketOpened:
+            {
+            LOG_WRITE( "<ESocketOpened>" );
+            if ( iStatus.Int() != KErrNone )
+                {
+                // there was an error while connecting
+                LOG_WRITE( "connection.Start error" );
+                ShutdownOwnedConnectionL();
+        
+                iObserver->ConnectingFailedL( iStatus.Int() );
+
+                break;
+                }
+
+            LOG_WRITE( "connection.Start OK" );
+
+            // get the connection id
+            TRAPD( error, FindWlanBearerConnectedL(); );
+            if ( error || iConnectionId == KNoConnection )
+                {
+                // At this point we really need the connection id if it exists
+                // without connection id server is in very unbalanced state
+                LOG_WRITEF( "FindWlanBearerConnectedL error=%d", error );
+                ShutdownOwnedConnectionL();
+                        
+                iObserver->ConnectingFailedL( ( error )? error : KErrGeneral );
+
+                break;
+                }
+
+            iConnectingState = ECsConnectionCreated;
+            SetActive();
+            TRequestStatus* status = &iStatus;
+            User::RequestComplete( status, KErrNone );
+            break;
+            }
+            
+        case ECsConnectionCreated:
+            {
+            LOG_WRITE( "<EConnectionCreated>" );
+            
+            // changing connection preferences
+            // start monitoring the iap
+            MonitorAccessPoint( iConnIap );
+            
+            TInt error = KErrNone;
+
+            // store previous default connection value
+            TRAP( error, iCmMgr.ReadDefConnL( iOriginalDefConn ) );
+            if ( error )
+                {
+                // Ignore possible failure and continue
+                LOG_WRITEF( "RunL ReadDefConnL returned error %d", error );
+                }
+            else 
+                {
+                LOG_WRITEF( "original default connection type/id = %d/%d", 
+                            iOriginalDefConn.iType,
+                            iOriginalDefConn.iId );
+                
+                // set the new connection as default
+                iCurrentDefConn.iType = ECmDefConnConnectionMethod;
+                iCurrentDefConn.iId = iConnIap;
+    
+                TRAP( error, iCmMgr.WriteDefConnL( iCurrentDefConn ) );
+                if ( error )
+                    {
+                    // Ignore possible failure and continue
+                    LOG_WRITEF( "RunL WriteDefConnL returned error %d", error );
+                    }
+    
+                LOG_WRITEF( "current default connection set to type/id = %d/%d", 
+                            iCurrentDefConn.iType,
+                            iCurrentDefConn.iId );
+                }
+            
+            iConnectingState = ECsPreferencesChanged;
+            SetActive();
+            TRequestStatus* status = &iStatus;
+            User::RequestComplete( status, KErrNone );
+            break;
+            }
+            
+        case ECsPreferencesChanged:
+            {
+            LOG_WRITE( "<EPreferencesChanged>" );
+            
+            // reset inactivity time
+            iInactivityStart.UniversalTime();
+            iAutoDisconnect = EFalse;
+            
+            iClientPoll->Start( 
+                           TTimeIntervalMicroSeconds32( KClientPollInterval ),
+                           TTimeIntervalMicroSeconds32( KClientPollInterval ),
+                           TCallBack( CheckClientCount, this ) );
+                                
+            LOG_WRITE( "connection client polling started" );
+
+            // notify observers of the connection name
+            iObserver->ConnectionEstablishedL( iWlanNetworkName );
+            
+            iConnectingState = ECsConnected;
+            break;
+            }
+            
+        default:
+            {
+            }
+        }
+    
+    }
+
+
+// ---------------------------------------------------------------------------
+// CWsfWlanBearerConnectionMonitor::DoCancel
+// ---------------------------------------------------------------------------
+//
+void CWsfWlanBearerConnectionMonitor::DoCancel()
+    {
+    LOG_ENTERFN( "CWsfWlanBearerConnectionMonitor::DoCancel" );
+
+    // we were in the middle of a connection creation process    
+    iAborting = ETrue;
+    TRAP_IGNORE( ShutdownOwnedConnectionL() );
+    }
+
+
+// ---------------------------------------------------------------------------
+// CWsfWlanBearerConnectionMonitor::RunError
+// ---------------------------------------------------------------------------
+//
+#ifdef _DEBUG
+TInt CWsfWlanBearerConnectionMonitor::RunError( TInt aError )
+    {
+    LOG_ENTERFN( "CWsfWlanBearerConnectionMonitor::RunError" );    
+    LOG_WRITEF( "error = %d", aError );
+#else
+TInt CWsfWlanBearerConnectionMonitor::RunError( TInt /*aError*/ )
+    {
+#endif
+    return KErrNone;
+    }
+
+