wlanutilities/wlansniffer/engine/server/src/wsfengine.cpp
author Dremov Kirill (Nokia-D-MSW/Tampere) <kirill.dremov@nokia.com>
Mon, 21 Jun 2010 16:55:05 +0300
branchRCL_3
changeset 20 a9524956f6b5
parent 12 981afc7d3841
permissions -rw-r--r--
Revision: 201023 Kit: 2010125

/*
* 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 CWsfEngine
*
*/



//  EXTERNAL INCLUDES
#include <commsdattypesv1_1.h>
#include <commsdat.h>
#include <cmconnectionmethodext.h>
#include <cmpluginwlandef.h>

//  CLASS HEADER
#include "wsfengine.h"


//  INTERNAL INCLUDES
#include "wsfwlanscanner.h"
#include "wsfwlansettingsaccessor.h"
#include "wsfwlanbearerconnectionmonitor.h"
#include "wsfengineobserver.h"
#include "wsfservercloseradapter.h"
#include "wsfactivewaiter.h"

#include "wsflogger.h"



//  LOCAL DEFINITIONS
using namespace CommsDat;


/**
* Maximum number of retries when trying to delete a temporary IAP but
* the connection is locking it
*/
static const TInt KMaxIapDeletionRetries = 10;


/**
* Time to wait betweed two IAP deletion retries, in microseconds
*/
static const TUint KDelayBetweenDeletionRetries = 500 * 1000;





//  CONSTRUCTION AND DESTRUCTION

// ----------------------------------------------------------------------------
// CWsfEngine::NewL
// ----------------------------------------------------------------------------
//
CWsfEngine* CWsfEngine::NewL( MWsfServerCloserAdapter& aServerCloser )
    {
    CWsfEngine* self = CWsfEngine::NewLC( aServerCloser );
    CleanupStack::Pop( self );
    return self;
    }


// ----------------------------------------------------------------------------
// CWsfEngine::NewLC
// ----------------------------------------------------------------------------
//
CWsfEngine* CWsfEngine::NewLC( MWsfServerCloserAdapter& aServerCloser )
    {
    CWsfEngine* self = new ( ELeave ) CWsfEngine( aServerCloser );
    CleanupStack::PushL( self );
    self->ConstructL();
    return self;
    }


// ----------------------------------------------------------------------------
// CWsfEngine::~CWsfEngine
// ----------------------------------------------------------------------------
//
CWsfEngine::~CWsfEngine()
    {
    LOG_ENTERFN( "CWsfEngine::~CWsfEngine" );
    
    delete iWlanBearerMonitor;
    delete iScanner;
    delete iDbSession;
    iObservers.Reset();
    
    if ( iMonitoredIap && 
         ( iIapPersistence == EIapExpireOnDisconnect ||
           iIapPersistence == EIapNestedExpireOnDisconnect ||
           iIapPersistence == EIapExpireOnBrowserExit ||
           iIapPersistence == EIapExpireOnShutdown ) )
        {
        TRAP_IGNORE( DeleteIapL( iMonitoredIap ) );
        }
    }


// ----------------------------------------------------------------------------
// CWsfEngine::CWsfEngine
// ----------------------------------------------------------------------------
//
CWsfEngine::CWsfEngine( MWsfServerCloserAdapter& aServerCloser ):
    iServerCloser( aServerCloser ),
    iEnableScanning( 0 ),
    iIapPersistence( EIapDeleted )
    {
    }


// ----------------------------------------------------------------------------
// CWsfEngine::ConstructL
// ----------------------------------------------------------------------------
//
void CWsfEngine::ConstructL()
    {
    LOG_CREATE;
    LOG_ENTERFN( "CWsfEngine::ConstructL" );
    iDbSession = CMDBSession::NewL( CMDBSession::LatestVersion() );
    iScanner = CWsfWlanScanner::NewL( *iDbSession );
 
    iScanner->SetObserver( *this );

    iWlanBearerMonitor = CWsfWlanBearerConnectionMonitor::NewL( iServerCloser );
    iScanner->SetConnectionDetailProvider( *iWlanBearerMonitor );

    iWlanBearerMonitor->StartMonitoringL( this );

    if ( iWlanBearerMonitor->GetWlanBearerNameL() != KNullDesC() )
        {
        HBufC* name = ConnectedWlanSsidL();
        CleanupStack::PushL( name );
        iScanner->ConnectionEstablishedL( *name );
        CleanupStack::PopAndDestroy( name );
        }
    }


// ----------------------------------------------------------------------------
// CWsfEngine::AttachL
// ----------------------------------------------------------------------------
//
void CWsfEngine::AttachL( MWsfEngineObserver* aObserver )
    {
    LOG_ENTERFN( "CWsfEngine::AttachL" );
    
    iObservers.AppendL( aObserver );
    }


// ----------------------------------------------------------------------------
// CWsfEngine::Detach
// ----------------------------------------------------------------------------
//
void CWsfEngine::Detach( MWsfEngineObserver* aObserver )
    {
    LOG_ENTERFN( "CWsfEngine::Detach" );
    TInt index = iObservers.Find( aObserver );
    if ( index != KErrNotFound )
        {
        iObservers.Remove( index );
        }
    }


// ----------------------------------------------------------------------------
// CWsfEngine::GetScanResults
// ----------------------------------------------------------------------------
//
HBufC8* CWsfEngine::GetScanResults()
    {
    LOG_ENTERFN( "CWsfEngine::GetScanResults" );
    return iScanner->ScanResults();
    }


// ----------------------------------------------------------------------------
// CWsfEngine::EnableScanningL
// ----------------------------------------------------------------------------
//
void CWsfEngine::EnableScanningL()
    {
    LOG_ENTERFN( "CWsfEngine::EnableScanningL" );

    iEnableScanning++;
    LOG_WRITEF( "++iEnableScanning = %d", iEnableScanning );
    
    if ( iEnableScanning == 1 )
        {
        LOG_WRITE( "CWsfEngine::EnableScanningL - start scanner" );
        if ( !iScanner->IsActive() )
            {
            iScanner->StartScanningL();
            }
        LOG_WRITE( "CWsfEngine::EnableScanningL start scanner done" );
        for ( TInt i( 0 ); i< iObservers.Count(); ++i )
            {
            (iObservers[i])->ScanEnabledL();
            }
        }
    else 
        {
        // the scanning is already active - stop and reactivate to complete the
        // new monitor in sensible time        
        if ( iScanner->IsActive() )
            {
            iScanner->StopScanning();
            }
        iScanner->StartScanningL();
        }
    }


// ----------------------------------------------------------------------------
// CWsfEngine::IsScanning
// ----------------------------------------------------------------------------
//
TBool CWsfEngine::IsScanning()
    {
    return iEnableScanning;
    }
    

// ----------------------------------------------------------------------------
// CWsfEngine::RefreshScanResults
// ----------------------------------------------------------------------------
//
TBool CWsfEngine::RefreshScanResults()
    {
    LOG_ENTERFN( "CWsfEngine::RefreshScanResults" );
    return iScanner->RestartScanning();
    }


// ----------------------------------------------------------------------------
// CWsfEngine::MonitorAccessPointL
// ----------------------------------------------------------------------------
//
void CWsfEngine::MonitorAccessPointL( TUint32 aIapId )
    {
    LOG_ENTERFN( "CWsfEngine::MonitorAccessPointL" );
    
    iMonitoredIap = aIapId;

    if ( iIapPersistence == EIapExpireOnShutdown )
        {
        // web browsing with a temporary IAP
        LOG_WRITE( "EIapExpireOnShutdown => EIapExpireOnBrowserExit" );
        SetIapPersistenceL( EIapExpireOnBrowserExit );
        iServerCloser.WaitForBrowserExit( ETrue );
        
        // semaphore to keep the order of calls
        iSuppressIapDeletion = ETrue;  
        }
    else if ( iIapPersistence == EIapExpireOnDisconnect )
        {
        LOG_WRITE( "EIapExpireOnDisconnect => EIapNestedExpireOnDisconnect" );
        SetIapPersistenceL( EIapNestedExpireOnDisconnect );
        }
 
    
    LOG_WRITEF( "iMonitoredIap = %d", iMonitoredIap );
    }


// ----------------------------------------------------------------------------
// CWsfEngine::DisableScanningL
// ----------------------------------------------------------------------------
//
void CWsfEngine::DisableScanningL()
    {
    LOG_ENTERFN( "CWsfEngine::DisableScanningL" );

    iEnableScanning--;
    LOG_WRITEF( "--iEnableScanning = %d", iEnableScanning );

    if ( !iEnableScanning )
        {
        LOG_WRITE( "CWsfEngine::DisableScanning stop scanner" );

        iScanner->StopScanning();
        LOG_WRITE( "CWsfEngine::DisableScanning stopped scanner" );

        for ( TInt i( 0 ); i < iObservers.Count(); ++i )
            {
            (iObservers[i])->ScanDisabledL();
            }
        }
    }


// ----------------------------------------------------------------------------
// CWsfEngine::ConnectedWlanSsidL
// ----------------------------------------------------------------------------
//
HBufC* CWsfEngine::ConnectedWlanSsidL()
    {
    LOG_ENTERFN( "CWsfEngine::ConnectedWlanIapNameL" );
    return iWlanBearerMonitor->GetWlanBearerNameL().AllocL();
    }


// ----------------------------------------------------------------------------
// CWsfEngine::ConnectedWlanConnectionDetailsL
// ----------------------------------------------------------------------------
//
TBool CWsfEngine::ConnectedWlanConnectionDetailsL( TWsfWlanInfo& aWlanInfo )
    {
    LOG_ENTERFN( "CWsfEngine::ConnectedWlanConnectionDetailsL" );
    return iWlanBearerMonitor->ConnectedWlanConnectionDetailsL( &aWlanInfo );
    }


// ----------------------------------------------------------------------------
// CWsfEngine::WlanScanCompleteL
// ----------------------------------------------------------------------------
//
void CWsfEngine::WlanScanCompleteL()
    {
    LOG_ENTERFN( "CWsfEngine::WlanScanCompleteL" );

    for ( TInt i( 0 ); i < iObservers.Count(); ++i )
        {
        (iObservers[i])->WlanListChangedL();
        }
    }


// ----------------------------------------------------------------------------
// CWsfEngine::WlanScanStarted
// ----------------------------------------------------------------------------
//
void CWsfEngine::WlanScanStarted()
    {
    LOG_ENTERFN( "CWsfEngine::WlanScanStarted" );
    }


// ----------------------------------------------------------------------------
// CWsfEngine::NotifyError
// ----------------------------------------------------------------------------
//
void CWsfEngine::NotifyError( TInt aError )
    {
    LOG_ENTERFN( "CWsfEngine::NotifyError" );

    for ( TInt i( 0 ); i < iObservers.Count(); ++i )
        {
        TRAP_IGNORE( (iObservers)[i]->NotifyErrorL( aError ) );
        }
    }


// ----------------------------------------------------------------------------
// CWsfEngine::ConnectionEstablishedL
// ----------------------------------------------------------------------------
//
void CWsfEngine::ConnectionEstablishedL( const TDesC& aConnectionName )
    {
    LOG_ENTERFN( "CWsfEngine::ConnectionEstablishedL" );
    // set the scanner to check connected accounts
    iScanner->ConnectionEstablishedL( aConnectionName );
    
    iScanner->RestartScanning();

    // notify the observers
    for ( TInt i( 0 ); i < iObservers.Count(); ++i )
        {
        (iObservers)[i]->ConnectedL();
        }
    }


// ----------------------------------------------------------------------------
// CWsfEngine::ConnectionLostL
// ----------------------------------------------------------------------------
//
void CWsfEngine::ConnectionLostL()
    {
    LOG_ENTERFN( "CWsfEngine::ConnectionLostL" );

    // check temporarity here as well since it is not guaranteed that 
    // the connection was owned and ConnectedIapReleasedL was called
    if ( iSuppressIapDeletion )
        {
        // web browsing with a temporary IAP
        LOG_WRITE( "IAP deletion suppressed" );
        iSuppressIapDeletion = EFalse;
        }
    else if ( iMonitoredIap )
        {
        if ( iIapPersistence == EIapExpireOnDisconnect ||
             iIapPersistence == EIapExpireOnBrowserExit )
            {
            DeleteIapL( iMonitoredIap );
            iIapPersistence = EIapDeleted;
            iMonitoredIap = 0;        
            }
        else if ( iIapPersistence == EIapNestedExpireOnDisconnect )
            {
            iIapPersistence = EIapExpireOnBrowserExit;
            }
        }

    iScanner->ConnectionLostL();
    iScanner->RestartScanning();

    // notify the observers
    for ( TInt i( 0 ); i < iObservers.Count(); ++i )
        {
        (iObservers)[i]->DisconnectedL();
        }
    }


// ----------------------------------------------------------------------------
// CWsfEngine::ConnectingFailedL
// ----------------------------------------------------------------------------
//
void CWsfEngine::ConnectingFailedL( TInt aError )
    {
    LOG_ENTERFN( "CWsfEngine::ConnectingFailedL" );

    for ( TInt i( 0 ); i < iObservers.Count(); ++i )
        {
        (iObservers)[i]->ConnectingFailedL( aError );
        }
    }


// ----------------------------------------------------------------------------
// CWsfEngine::ConnectedIapReleasedL
// ----------------------------------------------------------------------------
//
void CWsfEngine::ConnectedIapReleasedL()
    {
    LOG_ENTERFN( "CWsfEngine::ConnectedIapReleasedL" );
    
    // deleting temporary IAP if necessary
    if ( !iSuppressIapDeletion && iMonitoredIap )
        {
        if ( iIapPersistence == EIapExpireOnDisconnect ||
             iIapPersistence == EIapExpireOnBrowserExit )
            {
            DeleteIapL( iMonitoredIap );
            iIapPersistence = EIapDeleted;
            iMonitoredIap = 0;        
            }
        else if ( iIapPersistence == EIapNestedExpireOnDisconnect )
            {
            iIapPersistence = EIapExpireOnBrowserExit;
            iSuppressIapDeletion = ETrue;
            }
        }
    }


// ----------------------------------------------------------------------------
// CWsfEngine::DeleteIapL
// ----------------------------------------------------------------------------
//
void CWsfEngine::DeleteIapL( TUint32 aIapId )
    {
    LOG_ENTERFN( "CWsfEngine::DeleteIapL" );

    LOG_WRITEF( "deleting temporary IAP id = %d", aIapId );
    RCmManagerExt cmMgr;
    cmMgr.OpenLC();
    
    RArray<TUint32> cmIds;
    CleanupClosePushL( cmIds );
    cmMgr.ConnectionMethodL( cmIds, ETrue, ETrue, EFalse );
    TBool foundFromUncategorized = EFalse;
    
    for ( TInt k = 0; k < cmIds.Count(); k++ )
        {
        RCmConnectionMethodExt cm;
        TRAPD( error, cm = cmMgr.ConnectionMethodL( cmIds[k] ) );
        if ( KErrNone == error )
            {
            CleanupClosePushL( cm );

            TUint iapId = cm.GetIntAttributeL( CMManager::ECmIapId );
            if ( iapId == aIapId )
                {
                LOG_WRITE( "IAP is uncategorized" );
                foundFromUncategorized = ETrue;
                }
            CleanupStack::PopAndDestroy( &cm );
            }
        }
    
    CleanupStack::PopAndDestroy( &cmIds );
    
    if ( !foundFromUncategorized )
        {
        LOG_WRITE( "Not deleting IAP since it is in SNAP" );
        CleanupStack::PopAndDestroy( &cmMgr );
        return;
        }
    
    RCmConnectionMethodExt ictCm = cmMgr.ConnectionMethodL( aIapId );
    CleanupClosePushL( ictCm );

    CWsfActiveWaiter* waiter = CWsfActiveWaiter::NewLC();

    RTimer timer;
    timer.CreateLocal();

    // trying to delete the temporary IAP
    // sometimes the RConnection is still locking the IAP when 
    // we want to delete it, so we might have to try a couple of times
    TInt counter( KMaxIapDeletionRetries );
    TInt err( KErrNone );
    
    while ( counter )
        {
        LOG_WRITEF( "trying to delete (#%d)", 
                    KMaxIapDeletionRetries - counter );
                    
        TRAP( err, ictCm.DeleteL() );

        if ( !err || err == KErrNotFound )
            {
            // if success or the IAP was not found (strange but happens), break
            break;
            }

        --counter;
        if ( err && counter )
            {
            LOG_WRITEF( "deletion failed with error = %d", err );
            LOG_WRITE( "RConnection is still locking the IAP, waiting..." );
            
            timer.After( waiter->iStatus, TTimeIntervalMicroSeconds32( 
                                      KDelayBetweenDeletionRetries ) );
            waiter->WaitForRequest();
            }
        }
    

    timer.Close();
    CleanupStack::PopAndDestroy( waiter );
    
    if ( !err )
        {
        LOG_WRITE( "IAP deleted." );
        }
    else
        {
        LOG_WRITE( "IAP couldn't be deleted!" );
        }
        
    CleanupStack::PopAndDestroy( &ictCm );
    CleanupStack::PopAndDestroy( &cmMgr );    
    }


// ----------------------------------------------------------------------------
// CWsfEngine::ConnectWlanL
// ----------------------------------------------------------------------------
//
TInt CWsfEngine::ConnectWlanL( TUint32 aIapId,
                               TBool aConnectOnly,
                               TWsfIapPersistence aPersistence )
    {
    LOG_ENTERFN( "CWsfEngine::ConnectWlanL" );
    LOG_WRITEF( "iapId = %d, persistence = %d", aIapId, aPersistence );
    
    // if we have already been monitoring an IAP (different from the 
    // new one), clean that one up properly
    if ( iMonitoredIap && iIapPersistence == EIapExpireOnBrowserExit )
        {
        // user switched back from browser to sniffer and issued connect
        if ( iMonitoredIap != aIapId )
            {
            // selected network is different, so we must clean up the old one
            DeleteIapL( iMonitoredIap );
            iIapPersistence = EIapDeleted;
            iMonitoredIap = 0;        
            }
        else if ( iMonitoredIap == aIapId )
            {
            // selected networks are the same
            aPersistence = EIapNestedExpireOnDisconnect;
            }
        iSuppressIapDeletion = EFalse;
        }

    TInt ret = iWlanBearerMonitor->ConnectBearer( aIapId, 
                                                  aConnectOnly,
                                                  aPersistence != EIapPersistent );
    
    if ( !ret )
        {
        // successfully initiated connection
        LOG_WRITE( "connection init succeded" );
        iMonitoredIap = aIapId;
        SetIapPersistenceL( aPersistence );
        }
    
    return ret;
    }


// ----------------------------------------------------------------------------
// CWsfEngine::DisconnectWlan
// ----------------------------------------------------------------------------
//
TBool CWsfEngine::DisconnectWlan()
    {
    LOG_ENTERFN( "CWsfEngine::DisconnectWlan" );
    return iWlanBearerMonitor->DisconnectBearer();
    }
    

// ----------------------------------------------------------------------------
// CWsfEngine::IsConnected
// ----------------------------------------------------------------------------
//
TBool CWsfEngine::IsConnected()
    {
    return iWlanBearerMonitor->IsConnected();
    } 


// ---------------------------------------------------------------------------
// CWsfEngine::AbortConnectingL
// ---------------------------------------------------------------------------
//
void CWsfEngine::AbortConnectingL()
    {
    LOG_ENTERFN("CWsfEngine::AbortConnectingL");

    TInt result = iWlanBearerMonitor->AbortConnecting();
    
    LOG_WRITEF( "abort connection result = %d", result );
    
    if ( result == KErrNone && iMonitoredIap )
        {
        if ( iIapPersistence == EIapExpireOnDisconnect )
            {
            LOG_WRITE( "EIapNestedExpireOnDisconnect => EIapDeleted" );
            DeleteIapL( iMonitoredIap );
            iIapPersistence = EIapDeleted;
            iMonitoredIap = 0;        
            }
        else if ( iIapPersistence == EIapNestedExpireOnDisconnect )
            {
            LOG_WRITE( "EIapNestedExpireOnDisconnect => "
                       L"EIapExpireOnBrowserExit" );
            iIapPersistence = EIapExpireOnBrowserExit;
            }
        }
    else if ( result != KErrNone )
        {
        LOG_WRITE( "abort connection did not stopped connection" );
        // Try to disconnect via normal disconnect if engine is  
        // connected and and there is connection id
        DisconnectWlan();
        }
    }
    

// ---------------------------------------------------------------------------
// CWsfEngine::AbortScanning
// ---------------------------------------------------------------------------
//
void CWsfEngine::AbortScanning()
    {
    LOG_ENTERFN("CWsfEngine::AbortScanning");    
    
    iScanner->AbortScanning();
    }


// ---------------------------------------------------------------------------
// CWsfEngine::SetIapPersistenceL
// ---------------------------------------------------------------------------
//
TBool CWsfEngine::SetIapPersistenceL( TWsfIapPersistence aPersistence )
    {
    LOG_ENTERFN("CWsfEngine::SetIapPersistenceL");
    if ( aPersistence == EIapForcedExpiry )
        {
        if ( iMonitoredIap && 
             ( iIapPersistence == EIapExpireOnBrowserExit ||
               iIapPersistence == EIapExpireOnShutdown ) )
            {
            LOG_WRITE( "forced IAP expiry" );
            DeleteIapL( iMonitoredIap );
            iIapPersistence = EIapDeleted;
            iMonitoredIap = 0;
            }
        else if ( iIapPersistence == EIapNestedExpireOnDisconnect )
            {
            LOG_WRITE( "reverting to EIapExpireOnDisconnect" );
            iIapPersistence = EIapExpireOnDisconnect;
            }

        iServerCloser.WaitForBrowserExit( EFalse );
        }
    else 
        {
        LOG_WRITEF( "persistence = %d", aPersistence );
        iIapPersistence = aPersistence;
        }        
    
    return ( iMonitoredIap );
    }


// ---------------------------------------------------------------------------
// CWsfEngine::ControlDisconnectTimer
// ---------------------------------------------------------------------------
//
TBool CWsfEngine::ControlDisconnectTimer( TUint aAdcCommand )
    {
    LOG_ENTERFN("CWsfEngine::ControlDisconnectTimer");    
    
    return iWlanBearerMonitor->ControlDisconnectTimer( aAdcCommand );
    }

// ---------------------------------------------------------------------------
// CWsfEngine::ResetSuppressIapDeletion
// ---------------------------------------------------------------------------
//
void CWsfEngine::ResetSuppressIapDeletion()
    {
    LOG_ENTERFN( "CWsfEngine::ResetSuppresIapDeletion" );
    
    iSuppressIapDeletion = EFalse;
    }

// End of file