hotspotfw/hsserver/src/hotspotsession.cpp
author Dremov Kirill (Nokia-D-MSW/Tampere) <kirill.dremov@nokia.com>
Mon, 18 Jan 2010 21:21:32 +0200
changeset 2 6e4b6261703d
parent 0 56b72877c1cb
child 3 ff3b37722600
permissions -rw-r--r--
Revision: 201001 Kit: 201003

/*
* Copyright (c) 2002-2006 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 HotSpot Server Session
*
*/



// INCLUDE FILES
#include "hotspotserver.h"
#include "hotspotsession.h"
#include "hssnotif.h"
#include "hsslogintimer.h"
#include "hsslogouttimer.h"
#include "hssclientinterface.h"
#include "am_debug.h"
#include <internetconnectivitycrkeys.h>
#include <WlanCdbCols.h>
#include <starterclient.h>
#include <cmmanagerext.h>
#include <e32std.h>
#include <ecom.h>
#include <f32file.h>
#include <apgcli.h>

// Forward declarations
class CWlanMgmtClient;
class MWlanMgmtNotifications;

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

// -----------------------------------------------------------------------------
// CHotSpotPluginSession
// -----------------------------------------------------------------------------
//
CHotSpotSession::CHotSpotSession( CHotSpotServer& aServer ) :
    iServer( aServer ), iClient( NULL ), iSrvNotifications ( NULL ), 
    iNotificationHandle( NULL ), iAllowNotifications( ETrue ), iHotspotExtension( ETrue )
	{
	
	}

// -----------------------------------------------------------------------------
// ConstructL
// -----------------------------------------------------------------------------
//
void CHotSpotSession::ConstructL()
    {
    DEBUG( "CHotSpotSession::ConstructL()" );
    iIapSettingsHandler = CHssIapSettingsHandler::NewL();
    iLoginTimer = CHssLoginTimer::NewL( *this );
    iLogoutTimer = CHssLogoutTimer::NewL( *this );
    
    iMgtClient = CWlanMgmtClient::NewL();
    }

// -----------------------------------------------------------------------------
// NewL
// -----------------------------------------------------------------------------
//
CHotSpotSession* CHotSpotSession::NewL( CHotSpotServer& aServer )
    {
    CHotSpotSession* self = new( ELeave ) CHotSpotSession( aServer );
    CleanupStack::PushL( self );
    self->ConstructL();
    CleanupStack::Pop( self ); // Should this class have a 2-way constructor?
    return self;
    }
    
// ----------------------------------------------------------------------------------------
// ~CHotSpotSession
// ----------------------------------------------------------------------------------------
//
CHotSpotSession::~CHotSpotSession()
	{
	DEBUG( "CHotSpotSession::~CHotSpotSession()" );
	iPendingNotifications.Close();
 	if ( iMgtClient != NULL )
        {
        iMgtClient->CancelNotifications();
        delete iMgtClient;
        }
 	iMgtClient = NULL;
 	
 	if ( iIapSettingsHandler != NULL )
        {
        delete iIapSettingsHandler;
        }
 	iIapSettingsHandler = NULL;
    
 	   
    if ( iClient != NULL )
        {
        delete iClient;
        }
    iClient = NULL;
    
    if ( iNotifications != NULL )
        {
        delete iNotifications;
        }
    iNotifications = NULL;
    
    if ( iLoginTimer != NULL )
        {
        iLoginTimer->Cancel();
        delete iLoginTimer;
        }
    iLoginTimer = NULL;
    
    if ( iLogoutTimer != NULL )
        {
        iLogoutTimer->Cancel();
        delete iLogoutTimer;
        }
    iLogoutTimer = NULL;
    
    if ( iIcts != NULL )
        {
        delete iIcts;
        }
    iIcts = NULL;
    DEBUG( "CHotSpotSession::~CHotSpotSession() Done" );
	}
	
// ----------------------------------------------------------------------------------------
// ServiceL
// ----------------------------------------------------------------------------------------
//
void CHotSpotSession::ServiceL( const RMessage2& aMessage )
	{
	DEBUG1( "CHotSpotSession::ServiceL message: %d", aMessage.Function() );
	TRAPD( err, DispatchMessageL( aMessage) );
	if (err != KErrNone)
        {
        // Something went wrong. Complete message to let
        // the client to continue
        aMessage.Complete(err);
        } 
	}
// ----------------------------------------------------------------------------------------
// ServiceL
// ----------------------------------------------------------------------------------------
//
void CHotSpotSession::DispatchMessageL( const RMessage2& aMessage )
    {
    DEBUG( "CHotSpotSession::DispatchMessageL()" );
    TUint value1(NULL);
    TInt value2(NULL);
    TInt err(KErrNone);
    TInt indx(KErrNone);
    TPckgBuf<TInt> iapPackage( iIapId );
	
    switch ( aMessage.Function() )
        {
        case EHssActivateNotifications :
            iAllowNotifications = EFalse;
   			DEBUG( "CHotSpotSession::ActivateNotificationsL" );
   			if ( iNotifications == NULL )
   				{
   				DEBUG( "CHotSpotSession::DispatchMessageL activated !!!" );
   				iNotifications = new (ELeave) HssNotifications(*this);
				iMgtClient->ActivateNotificationsL( *iNotifications );
 				}
            HandleOrderNotifications( aMessage );
            break;
        case EHssCancelNotifications :
		    iAllowNotifications = EFalse;
   			DEBUG( "CHotSpotSession::CancelNotifications" );
   			iMgtClient->CancelNotifications( );
   			if ( iNotifications != NULL )
   		    	{
   		    	delete iNotifications;
   		    	}
   		    iNotifications = NULL;
   			HandleCancelNotifications( aMessage );
            break;
        case EHssGetScanResults :
            // Handled now in client side. Left here for future use.
            break;
        case EHssRegister :
        	ProcessRegisterL( aMessage );
            break;
        case EHssUnRegister :
        	ProcessUnRegisterL( aMessage );
            break;
        case EHssJoin :
		    iAllowNotifications = EFalse;
            // IAP id
            value1 = ( TInt )aMessage.Int0();
            iIapId = value1;
            indx = iServer.FindMessage(value1, EHssStart );
            if ( indx >= 0 )
                {
            	iServer.CompleteMessage( indx , KErrNone );
                }
            else
                {
                indx = iServer.FindMessage(value1, EHssStartAgain );
                if ( indx >= 0 )
                    {
                    iServer.CompleteMessage( indx , KErrNone );
                    }
                }
            aMessage.Complete( KErrNone );
            break;
        case EHssCancelStart :
            iServer.SetLogoutFlag( ETrue );
            // Do not send association status to client
            iServer.SetAssociationFlag( EFalse ); 
             // IAP id
            iIapId = ( TInt )aMessage.Int0();
            indx = iServer.FindMessage(iIapId, EHssStart );
            if ( indx >= 0 )
            {
            	iServer.CompleteMessage( indx , KErrAbort);
            }
	        else
            {
             	indx = iServer.FindMessage(iIapId, EHssStartAgain );
                if ( indx >= 0 )
                {
                	iServer.CompleteMessage( indx , KErrAbort );
                }
            }
            
            aMessage.Complete( KErrNone );
            break;
        case EHssStop :
            iAllowNotifications = EFalse;
           	iServer.SetLogoutFlag( ETrue );
           		
           	iLoginTimer->Cancel();
            iLogoutTimer->Cancel();
            // IAP id
            value1 = ( TInt )aMessage.Int0();
            for (TInt counter = EHssGetScanResults; counter <EHssServerShutdown ;counter++)
            {
            	indx = iServer.FindMessage(value1, THotSpotCommands(counter ));
            	if ( indx >= 0 )
            	{
            		iServer.CompleteMessage( indx , KErrCancel);
            	}
            }
                        
            aMessage.Complete( KErrNone );
            break;
        case EHssLoginComplete :
		    iAllowNotifications = EFalse;
            // IAP id
            value1 = ( TInt )aMessage.Int0();
            // ret value
            value2 = ( TInt )aMessage.Int1();
            
            iLoginTimer->Cancel();
            
            DEBUG1( "EHssLoginComplete value2: %d", value2 );
            indx = iServer.FindMessage( value1, EHssStartLogin );
            if ( KErrNotFound != indx )
                {
            	if (value2 == KErrNone)
            	    {
            	    DEBUG( "EHssLoginComplete1" );
                	iServer.CompleteMessage( indx, KErrNone );
            	    }
            	else
            	    {
            	    DEBUG( "EHssLoginComplete2" );
            		iServer.CompleteMessage( indx, KErrCancel );
                    iServer.SetLogoutFlag( ETrue );
            	    }
            	    
                }
            
            aMessage.Complete( KErrNone );
            break;
        case EHssLogoutComplete :
		    iAllowNotifications = EFalse;
		    iLogoutTimer->Cancel();
		    
            // IAP id
            value1 = ( TInt )aMessage.Int0();
            
            indx = iServer.FindMessage( value1, EHssCloseConnection );
            if ( KErrNotFound != indx )
                {
                iServer.CompleteMessage( indx, KErrNone );    
                }
            
            aMessage.Complete( KErrNone );
            break;
        case EHssStartLogin :
            // Do not send association status, since it's already done.
            iServer.SetAssociationFlag( EFalse ); 
            // IAP id
            iIapId = ( TInt )aMessage.Int0();
            // Network id
            iNetId = ( TInt )aMessage.Int1();
            err = iServer.SaveMessage( iIapId, aMessage, EHssStartLogin ); 
            if ( KErrNone != err )
                {
                aMessage.Complete( err );  
                }
            else
                {
                err = ProcessStartLoginL( iIapId, iNetId );
                // If client not found, an error was returned. 
                // Otherwise message completed elsewhere. 
                if ( KErrNone != err )
                    {
                    indx = iServer.FindMessage(iIapId, EHssStartLogin );
                    if ( indx >= 0 )
                        {
                        iServer.CompleteMessage( indx , KErrNone );
                        }
                    else
                        {
                        aMessage.Complete( KErrNone );
                        }
                    }
                }
            break;
        case EHssCancelLogin :
        	iLoginTimer->Cancel();
            // if client doesn't exist (is NULL), Login(.) has not been 
            // called to client -> that is CancelLogin() not needed to call
            if ( iClient != NULL )
                {
                iClient->CancelLogin( iIapId );
                }
            
            indx = iServer.FindMessage(iIapId, EHssStartLogin );
            if ( indx >= 0 )
                {
                iServer.CompleteMessage( indx , err );
                }
            aMessage.Complete( KErrNone );
            break;
        case EHssStart:
        	// IAP id
        	iServer.SetLoginFlag( ETrue );
        	iIapId = ( TInt )aMessage.Int0();
            err = iServer.SaveMessage( iIapId, aMessage, EHssStart ); 
           if ( err != KErrNone)
                {
                aMessage.Complete( err );  
                }
            else
                {
                TRAPD( startLeaved, err = ProcessStartL( iIapId ) );
                
                if ( startLeaved != KErrNone)
                    {
                    indx = iServer.FindMessage(iIapId, EHssStart );
                    if ( indx >= 0 )
                        {
                        iServer.CompleteMessage( indx , KErrNotSupported );
                        }
                    else
                        {
                        aMessage.Complete( KErrNotSupported );
                        }
                    }
                
                else if ( err != KErrNone)
                    {
                    indx = iServer.FindMessage(iIapId, EHssStart );
                    if ( indx >= 0 )
                        {
                        iServer.CompleteMessage( indx , KErrNotSupported );
                        }
                    else
                        {
                        aMessage.Complete( KErrNotSupported );
                        }
                    }
                // else -> client is created and called 
                // WLAN agent waits for 30 seconds before continuing connection setup.
                }
            break;
        case EHssStartAgain:
        	// IAP id
        	iServer.SetLoginFlag( ETrue );
        	iIapId = ( TInt )aMessage.Int0();
            err = iServer.SaveMessage( iIapId, aMessage, EHssStartAgain ); 
           if ( err != KErrNone)
                {
                aMessage.Complete( err );  
                }
            else
                {
                err = ProcessStartAgain( iIapId );
                if (   err != KErrNone)
                    {
                    indx = iServer.FindMessage(iIapId, EHssStartAgain );
                    if ( indx >= 0 )
                        {
                        iServer.CompleteMessage( indx , err );
                        }
                    else
                        {
                        aMessage.Complete( err );
                        }
                    }
                }
        	break;
        	
        case EHssCancel:
       		iLoginTimer->Cancel();
            iLogoutTimer->Cancel();
         	// IAP id
        	iIapId = ( TInt )aMessage.Int0();
            if ( iServer.GetAssociationFlagValue() )
                {
                // We are in association phase and Agent failed it for some reason
                ProcessAssociationStatus( iIapId, EFalse );
                }
            
            indx = iServer.FindMessage(iIapId, EHssStart );
            if ( indx >= 0 )
            	{
            	iServer.CompleteMessage( indx , KErrCancel );
            	}
            indx = iServer.FindMessage(iIapId, EHssStartAgain );
            if ( indx >= 0 )
            	{
            	iServer.CompleteMessage( indx , KErrCancel );
            	}
            indx = iServer.FindMessage(iIapId, EHssCloseConnection );
            if ( indx >= 0 )
            	{
            	iServer.CompleteMessage( indx , KErrCancel );
            	}
            //Not needed to send Logout()
            //iServer.SetLogoutFlag( ETrue )
            //ProcessCloseL( iIapId )
			aMessage.Complete( KErrNone );
        break;
        
        case EHssCloseConnection:
            iLoginTimer->Cancel();
            iLogoutTimer->Cancel();       	
        
        	// IAP id
        	iIapId = ( TInt )aMessage.Int0();

            if ( iServer.GetAssociationFlagValue() )
                {
                // We are in association phase and Agent failed it for some reason
                ProcessAssociationStatus( iIapId, EFalse );
                }
            
            err = iServer.SaveMessage( iIapId, aMessage, EHssCloseConnection ); 
            if ( KErrNone != err )
                {
                aMessage.Complete( err );  
                }
            else
                {
                err = ProcessCloseL( iIapId );
                // If client not found, an error was returned. 
                // Otherwise message completed elsewhere. 
                if ( KErrNone != err )
                    {
                    indx = iServer.FindMessage(iIapId, EHssCloseConnection );
                    if ( indx >= 0 )
                        {
                        iServer.CompleteMessage( indx , KErrNone );
                        }
                    else
                        {
                        aMessage.Complete( KErrNone );
                        }
                    }
                }
            break;

        case EHssServerShutdown:
            ProcessServerShutdown( aMessage );
            break;
            
        case EHssGetIAP:
	        aMessage.WriteL( 0, iapPackage );
            aMessage.Complete( KErrNone );
            break;
            
        case EHssUiState:
            ProcessUiState( aMessage );
            break;
        case EHssStartBrowser:
            {   
        	TInt len = aMessage.GetDesLength( 0 );
        	iIapId = ( TInt )aMessage.Int1();
        	iNetId = ( TInt )aMessage.Int2();
        	err = iServer.SaveMessage( iIapId, aMessage, EHssStartBrowser );
        	HBufC* buf = HBufC::NewLC( len ); 
            TPtr ptr( buf->Des() );
            User::LeaveIfError( aMessage.Read( 0, ptr ) );     
            
            AuthenticateL( ptr );
            
            CleanupStack::PopAndDestroy(buf);
            }
        	break;
        	
        case EHssSetTimerValues:
            {
            TUid clientUid( TUid::Uid( aMessage.Int0() ) );
            TUint loginTimerValue = aMessage.Int1();
            TUint logoutTimerValue = aMessage.Int2();
            iServer.SetTimerValues( clientUid, loginTimerValue, logoutTimerValue );
            aMessage.Complete( KErrNone );
            }
            break;

        default:
            aMessage.Complete( KErrNotSupported );  
            //PanicClient( aMessage, EBadRequest )
            break;
        }
       iAllowNotifications = TRUE;

    }

// ---------------------------------------------------------
// HandleOrderNotifications
// ---------------------------------------------------------
//
void CHotSpotSession::HandleOrderNotifications( const RMessage2& aMessage )
    {
    iPendingNotificationRequest = aMessage;
    iIsNotificationRequestPending = ETrue;
    if( !iNotificationHandle ) // == NULL i.e. is not activated
        {
        TRAPD( err, iNotificationHandle = CSessionNotification::NewL( *this ) );
        if ( err == KErrNone )
            {
            iServer.NotifyAdd( *iNotificationHandle );
            }
        else
            {
            iIsNotificationRequestPending = EFalse;
            aMessage.Complete( err );
            return;
            }
        }
    HandleNotification(); // check is there any unsent notifications
    }

// ---------------------------------------------------------
// HandleCancelNotifications
// ---------------------------------------------------------
//
void CHotSpotSession::HandleCancelNotifications( const RMessage2& aMessage )
    {
    if( iIsNotificationRequestPending )
        {
        iPendingNotificationRequest.Complete( KErrNone /*EWLMNotificationsCancelled*/ );
        iIsNotificationRequestPending = EFalse;
        iPendingNotifications.Reset();
        }
    if( iNotificationHandle )
        {
        iServer.NotifyRemove( *iNotificationHandle );
        delete iNotificationHandle;
        iNotificationHandle = NULL;
        }
    aMessage.Complete( KErrNone );
    }
        
// ---------------------------------------------------------
// AddNotification
// ---------------------------------------------------------
//
void CHotSpotSession::AddNotification( TInt aNotification, TDes8& aData )
    {
    DEBUG( "CHotSpotSession::AddNotification" );

    TNotification notif;
    notif.id = aNotification;
    notif.data = aData;
	if ( iIsNotificationRequestPending )
        {
		DEBUG( "CHotSpotSession::AddNotification added to array. Request found..." );
    	iPendingNotifications.Append( notif );
    	HandleNotification(); // check is there client waiting for notification
  		}
    }

// ---------------------------------------------------------
// HandleNotification
// ---------------------------------------------------------
//
void CHotSpotSession::HandleNotification()
    {
    DEBUG( "CHotSpotSession::HandleNotification" );

	// Check if we allow notifications
	if (iAllowNotifications == TRUE)
		{
    	// Check is there message to wait notification and 
    	// notification that is not sent.
    	if ( iIsNotificationRequestPending && iPendingNotifications.Count() != 0 )
        	{
        	DEBUG( "CHotSpotSession::HandleNotification - sending response..." );
        	iIsNotificationRequestPending = EFalse;

        	THssPckgData data;
        	TPckg<THssPckgData> pckg( data );
        	data.data = iPendingNotifications[0].data;
        	TInt ret( iPendingNotificationRequest.Write( 0, pckg ) );
        	if ( ret != KErrNone )
            	{
            	iPendingNotificationRequest.Complete( ret );
            	return;
            	}
        	iPendingNotificationRequest.Complete( iPendingNotifications[0].id );
        	iPendingNotifications.Reset();
        	}
		}
	}

// -----------------------------------------------------------------------------
// TestInternetConnectivityL
// -----------------------------------------------------------------------------
//
void CHotSpotSession::TestInternetConnectivityL()
    {
    DEBUG("CHotSpotSession::TestInternetConnectivityL");
    if ( iIcts != NULL )
        {
        delete iIcts;
        }
   
    iIcts = CIctsClientInterface::NewL( iIapId, iNetId, *this );
    iIcts->StartL();
    }

// -----------------------------------------------------------------------------
// ConnectivityObserver
// -----------------------------------------------------------------------------
//    
void CHotSpotSession::ConnectivityObserver( TIctsTestResult aResult, 
                                            const TDesC& aString )
    {
    DEBUG1("CHotSpotSession::ConnectivityObserver result: %d", aResult);
    TInt indx( KErrNone );
    switch ( aResult )
        {
        case EConnectionOk :
            indx = iServer.FindMessage( iIapId, EHssStartLogin );
            if ( KErrNotFound != indx )
                {
                iServer.CompleteMessage( indx, KErrNone );    
                }
            TRAP_IGNORE( iIapSettingsHandler->CreateIapL() );
            break;
        case EHttpAuthenticationNeeded :
            // Start browser for authentication
            TRAP_IGNORE( AuthenticateL( aString ) );
            break;
        case EConnectionNotOk :
            indx = iServer.FindMessage( iIapId, EHssStartLogin );
            if ( KErrNotFound != indx )
                {
                iServer.CompleteMessage( indx, KErrNone );    
                }
            break;
        case ETimeout :
            indx = iServer.FindMessage( iIapId, EHssStartLogin );
            if ( KErrNotFound != indx )
                {
                iServer.CompleteMessage( indx, KErrNone );    
                }
            
            break;
        default:
            break;
        }
    }

// -----------------------------------------------------------------------------
// LoginTimeout
// -----------------------------------------------------------------------------
//   
void CHotSpotSession::LoginTimeout()
    {
    DEBUG1("CHotSpotSession::LoginTimeout iIapId :%d", iIapId );
    iServer.SetLogoutFlag( ETrue );
    
    // if message is not found, client has not completed it (LoginComplete(..))
    TInt indx = iServer.FindMessage( iIapId, EHssStartLogin );
    if ( KErrNotFound != indx )
        {
        iServer.CompleteMessage( indx, KErrCancel );    
        }
        
    TUid clientUid;
    TBuf8<KExtensionAPILength> extAPI;
    TRAP_IGNORE( iIapSettingsHandler->FindClientL( iIapId, clientUid, extAPI ) );
    
    // 3rd party client was found
    if ( clientUid != TUid::Null() )
        {
        DEBUG("CHotSpotSession::LoginTimeout clientUid = CLIENT");
        TBuf8<KExtensionAPILength> nullBuf;
        TInt ret = CreateClient( clientUid, nullBuf );
        DEBUG1("CHotSpotSession::LoginTimeout CreateClient ret: %d", ret);
        if ( KErrNone == ret )
            {
            iClient->CancelLogin( iIapId );           
            }
        }

    DEBUG("CHotSpotSession::LoginTimeout Done");
    }
    
// -----------------------------------------------------------------------------
// LogoutTimeout
// -----------------------------------------------------------------------------
//   
void CHotSpotSession::LogoutTimeout()
    {
    DEBUG("CHotSpotSession::LogoutTimeout");
    // if message is not found, client has not completed it (LogoutComplete(..))
    TInt indx = iServer.FindMessage( iIapId, EHssCloseConnection );
    if ( KErrNotFound != indx )
        {
        iServer.CompleteMessage( indx, KErrNone );    
        }
    }

// ---------------------------------------------------------
// ProcessRegisterL
// ---------------------------------------------------------
//
void CHotSpotSession::ProcessRegisterL( const RMessage2& aMessage )
	{
	DEBUG("CHotSpotSession::ProcessRegisterL");
	
	iAllowNotifications = EFalse;
    TBufC< KIapNameLength > iapName;
    TPckgBuf< TIapName > iapPckg;
    TUid clientUid;
    TPckgBuf< TClientUid > uidPckg;
    TPckgBuf<TInt> iapPackage( iIapId );
	
    // Read message
    aMessage.ReadL( 0, uidPckg );
    clientUid = uidPckg().ClientUid();
    aMessage.ReadL( 1, iapPckg );
    iapName = iapPckg().IapName();
    
    TUint32 iapId( 0 );
    // TRAPD needed here so that 0 can be returned if DeleteIapL leaves
    TInt ret( KErrNone );
    TRAP( ret, iIapSettingsHandler->CreateClientIapL( iapName, iapId, clientUid ));
    DEBUG1( "CHotSpotSession::EHssRegister iapId: %d", iapId );
    DEBUG1( "CHotSpotSession::EHssRegister ret: %d", ret );
    if ( KErrNone == ret )
        {
        aMessage.Complete( iapId );
        }

    else 
        {
        // TRAP needed here so that 0 can be returned if DeleteIapL leaves
        //TRAP(err, iIapSettingsHandler->DeleteIapL( iapId ))
        // Error, we are returning 0 to client
        // and no IAP is created
        aMessage.Complete( KErrNone );
        }
	}

// ---------------------------------------------------------
// ProcessUnRegisterL
// ---------------------------------------------------------
//
void CHotSpotSession::ProcessUnRegisterL( const RMessage2& aMessage )
	{
	DEBUG("CHotSpotSession::ProcessUnRegisterL");
	iAllowNotifications = EFalse;
    TInt ret( KErrNone );

    // Read message
    TInt iapId = ( TInt )aMessage.Int0();
    
    // Check that this is not Easy WLAN
    TRAP_IGNORE( EasyWlanIdL() );
    if ( iEasyWlanId != iapId  )
        {
        TRAPD( err, iIapSettingsHandler->DeleteIapL( iapId ) );
        // return KErrGeneral if IAP removal is not successful
        if ( err != KErrNone )
            {
            ret = KErrGeneral;
            }
        }
    else
        {
        ret = KErrPermissionDenied;
        }
        
    aMessage.Complete( ret ); 
	}

// -----------------------------------------------------------------------------
// ProcessStartLogin
// -----------------------------------------------------------------------------
//   
TInt CHotSpotSession::ProcessStartLoginL( const TUint aIapId, const TUint aNetId )
    {
    DEBUG("CHotSpotSession::ProcessStartLogin");
    TInt ret( KErrNotFound );
    TUid clientUid;
    TBuf8<KExtensionAPILength> extAPI;
    iIapId = aIapId;
    
    // Check if Easy WLAN.
    TRAP_IGNORE( EasyWlanIdL() );
    if ( iEasyWlanId == aIapId )
    	{
    	 DEBUG("CHotSpotSession::ProcessStartLogin Easy WLAN detected");
        // Just test internet connectivity and complete message later
        TestInternetConnectivityL();
		ret = KErrNone;
        return ret;
    	}
    
    iIapSettingsHandler->FindClientL( aIapId, clientUid, extAPI );
    
    // 3rd party client was found
    if ( clientUid != TUid::Null() )
        {
        DEBUG("CHotSpotSession::ProcessStartLogin clientUid = CLIENT");
        TBuf8<KExtensionAPILength> nullBuf;
        ret = CreateClient( clientUid, nullBuf );
        
        if ( KErrNone == ret && iServer.GetLoginFlagValue() )
            {
            iLoginTimer->After( iServer.GetLoginTimeMicroSecs( clientUid ) );
            DEBUG("CHotSpotSession::ProcessStartLogin iClient->Login( iIapId, iNetId );");
            iClient->Login( aIapId, aNetId );
            iServer.SetLogoutFlag( EFalse );           
            }
        else
            {
            ret = KErrNotFound;
            }
        }
    DEBUG("CHotSpotSession::ProcessStartLogin DONE");
    return ret;
    }

// -----------------------------------------------------------------------------
// ProcessStart
// -----------------------------------------------------------------------------
//   
TInt CHotSpotSession::ProcessStartL( const TUint aIapId )
    {
    DEBUG("CHotSpotSession::ProcessStart");
    
    TInt ret( KErrNone );
   	TBuf8<KExtensionAPILength> extAPI;
    
    iIapSettingsHandler->FindClientL( aIapId, iClientUid, extAPI );
    if ( iClientUid == TUid::Null() )
        {
        DEBUG("CHotSpotSession::ProcessStartL clientUid = EMPTY");
        
        ret = KErrNotSupported;
        }
    else
        {
        DEBUG("CHotSpotSession::ProcessStartL clientUid = CLIENT");
        
        // Try first with API extension defined
        ret = CreateClient( iClientUid, extAPI );
        
        if ( ret != KErrNone )
            {
            // Client exists, but hasn't implemented API extension
            // Let's try again without API extension definition
            TBuf8<KExtensionAPILength> nullBuf;
            ret = CreateClient( iClientUid, nullBuf );
            }
        
        if ( ret == KErrNone )
    		{
    		iServer.SetAssociationFlag( ETrue ); 
    		iMgtClient->ActivateNotificationsL( *this );
         	iClient->Start( aIapId );    
        	}
        }
    DEBUG1("CHotSpotSession::ProcessStartL DONE ret%d", ret);
	return ret;
    }
    
// -----------------------------------------------------------------------------
// ProcessStartAgain
// -----------------------------------------------------------------------------
//   
TInt CHotSpotSession::ProcessStartAgain( const TUint aIapId )
    {
    DEBUG("CHotSpotSession::ProcessStartAgain");
    TInt ret( KErrNone );
      
    // Client exists if StartAgain is called.
    if ( iClient == NULL )
        {	
       	TBuf8<KExtensionAPILength> nullBuf;
        ret = CreateClient( iClientUid, nullBuf );
        }
    
 	if (  ret == KErrNone )
   		{
   		iServer.SetAssociationFlag( ETrue ); // Send association status
   		iClient->Update( aIapId );   
   		}    

	return ret;
    }
// -----------------------------------------------------------------------------
// ProcessAssociationStatus
// -----------------------------------------------------------------------------
//   
TInt CHotSpotSession::ProcessAssociationStatus( const TUint aIapId, TBool aResult )
    {
    DEBUG("CHotSpotSession::ProcessAssociationStatus");
    TInt ret( KErrNone );
    iServer.SetAssociationFlag( EFalse );
    if ( iHotspotExtension )
        { 
        iHotspotExtension = EFalse;
        if ( iClient != NULL )
            {
            DEBUG("CHotSpotSession::ProcessAssociationStatus sent to client");
            iClient->WlanAssociationStatus( aIapId, aResult );
            }
       }
    DEBUG("CHotSpotSession::ProcessAssociationStatus Done");
    return ret;
    }

// -----------------------------------------------------------------------------
// CreateClient
// -----------------------------------------------------------------------------
//   
TInt CHotSpotSession::CreateClient( const TUid aUid, TDesC8& aUidText )
    {
    DEBUG("CHotSpotSession::CreateClient");
    TInt err( KErrNone );
    if ( aUidText == KNullDesC8 )
        {
       	DEBUG("CHotSpotSession::CreateClient iHotspotExtension = EFalse;");
        iHotspotExtension = EFalse;
        TRAP( err, iClient = CHssClientPlugin::NewL( aUid, aUidText ) );
        DEBUG1("CHotSpotSession::CreateClient err: %d", err );
        }
    else
        {
        DEBUG("CHotSpotSession::CreateClient iHotspotExtension = ETrue;");
        iHotspotExtension = ETrue;
        TRAP( err, iClient = CHssClientPlugin::NewL( aUid, aUidText ) );
        DEBUG1("CHotSpotSession::CreateClient err: %d", err );
        }
    return err;
    }
    
// -----------------------------------------------------------------------------
// ProcessClose
// -----------------------------------------------------------------------------
//   
TInt CHotSpotSession::ProcessCloseL( const TUint aIapId )
    {
    DEBUG("CHotSpotSession::ProcessCloseL");
    TInt ret( KErrNone );
    TUid clientUid;
    TBuf8<KExtensionAPILength> extAPI;
  
    iIapSettingsHandler->FindClientL( aIapId, clientUid, extAPI );
    if ( clientUid == TUid::Null() )
        {
        DEBUG("CHotSpotSession::ProcessCloseL clientUid = EMPTY");
        // do nothing
        ret = KErrNotSupported;
        }
    else
        {
        DEBUG("CHotSpotSession::ProcessCloseL clientUid = CLIENT");
        if ( iClient == NULL )
            {
            TBuf8<KExtensionAPILength> nullBuf;
            ret = CreateClient( clientUid, nullBuf );
            }
		else
		    {
		    ret = KErrNone;   
		    }
		iLogoutTimer->After( iServer.GetLogoutTimeMicroSecs( clientUid ) );
        if ( ret == KErrNone && !iServer.GetLogoutFlagValue() )
        	{
        	DEBUG("CHotSpotSession::ProcessCloseL send Logout()");
            iClient->Logout( aIapId );
        	iServer.SetLogoutFlag( ETrue );
        	iServer.SetLoginFlag( EFalse );
            }
        else
            {
            ret = KErrNotFound;
            }    
      
        }
	return ret;
    }
 
// -----------------------------------------------------------------------------
// ProcessServerShutdown
// -----------------------------------------------------------------------------
//    
void CHotSpotSession::ProcessServerShutdown( const RMessage2& aMessage )
    {
    DEBUG("CHotSpotSession::ProcessServerShutdown");
    TInt shutdown;
    
    shutdown = ( TInt )aMessage.Int0();
    if ( KHssShutdown == shutdown )
        {
        DEBUG("CHotSpotSession::ProcessServerShutdown shutdown ");
        aMessage.Complete( KErrNone );
        RProcess server; // Sets the handle-number to the KCurrentProcessHandle
        server.Kill( KErrNone );
        }
    else
        {
        DEBUG("CHotSpotSession::ProcessServerShutdown else ");
        aMessage.Complete( KErrNone );
        }
    }
    
// -----------------------------------------------------------------------------
// ProcessUiState
// -----------------------------------------------------------------------------
//    
void CHotSpotSession::ProcessUiState( const RMessage2& aMessage )
	{
    DEBUG( "CHotSpotSession::ProcessUiState()" );
    TBool completeMsg = EFalse;
    TInt indx( KErrNone );
    TInt indxBrowser( KErrNone );
    TInt ret( KErrNone );
    iIapId = ( TInt )aMessage.Int0();

    indx = iServer.FindMessage( iIapId, EHssStartLogin );
    indxBrowser = iServer.FindMessage( iIapId, EHssStartBrowser );
    THsBrowserUiStates uiState = ( THsBrowserUiStates ) aMessage.Int1(); // UI state
    switch ( uiState )
   		{
   		case EHsBrowserUiRunning:
   			{
   			DEBUG( "CHotSpotSession::ProcessUiState() EHsBrowserUiRunning" );
   			break;
   			}
   	    case EHsBrowserUiAuthenticatedOk:
   	        {
   	        DEBUG( "CHotSpotSession::ProcessUiState() EHsBrowserUiAuthenticatedOk" );

            completeMsg = ETrue;
            break;
   	        }
   	    case EHsBrowserUiAuthenticatedNok:
   	        {
   		    DEBUG( "CHotSpotSession::ProcessUiState() EHsBrowserUiAuthenticatedNok" );
   		    completeMsg = ETrue;
   		    break;
   		    }
   	    case EHsBrowserUiClosed:
   	        {
   	        DEBUG( "CHotSpotSession::ProcessUiState() EHsBrowserUiClosed" );
            completeMsg = ETrue;
            break;
   	        }
   	    default:
   	    	{
   	    	DEBUG( "CHotSpotSession::ProcessUiState() default" );
            completeMsg = ETrue;
   	    	}
   	    }
    if ( completeMsg )
   	    {
        // complete messages EHssStartLogin/EHssStartBrowser
        if ( indx >= 0 )
           {
           DEBUG( "CHotSpotSession::ProcessUiState() completing EHssStartLogin" );
           iServer.CompleteMessage( indx , KErrNone );
           aMessage.Complete( KErrNone );
           }
        else if ( indxBrowser >= 0 )
        	{
        	DEBUG( "CHotSpotSession::ProcessUiState() completing EHssStartBrowser" );
            iServer.CompleteMessage( indxBrowser, ret );
            aMessage.Complete( KErrNone );
        	}
           else
           {
           DEBUG( "CHotSpotSession::ProcessUiState() completing EHssUiState" );
           aMessage.Complete( KErrNotFound );
           }
        }
    }    
    
// -----------------------------------------------------------------------------
// Authenticate()
// -----------------------------------------------------------------------------
//    
void CHotSpotSession::AuthenticateL( const TDesC& aString )
    {
    DEBUG("CHotSpotSession::AuthenticateL()");

    const TInt KBrowserUid = 0x2000AFCC; // hotspot browser application
    HBufC* param = HBufC::NewLC( KMaxFileName );
    _LIT(tmpString, "%d, %d, %S");
    param->Des().Format( tmpString, iIapId, iNetId, &aString );
    TUid uid( TUid::Uid( KBrowserUid ) );
    RApaLsSession appArcSession;
    User::LeaveIfError( appArcSession.Connect() ); // connect to AppArc server
    CleanupClosePushL( appArcSession );
    TThreadId id;
    TInt err = appArcSession.StartDocument( *param, TUid::Uid( KBrowserUid ), id );
    if ( err != KErrNone )
        {
        DEBUG1( "CHotSpotSession::AuthenticateL() StartDocument: %d", err );
        }
    CleanupStack::PopAndDestroy( &appArcSession );
    CleanupStack::PopAndDestroy( param );

    DEBUG("CHotSpotSession::AuthenticateLC() done");
    }

// -----------------------------------------------------------------------------
// EasyWlanIdL
// -----------------------------------------------------------------------------
//
void CHotSpotSession::EasyWlanIdL()
    {
    DEBUG("CHotSpotSession::EasyWlanIdL()");
    // Set to default value just in case
    iEasyWlanId = KEasyWlanServiceId; 
    
    RCmManagerExt cmManager;
    cmManager.OpenL();
    CleanupClosePushL( cmManager );
    
    iEasyWlanId = cmManager.EasyWlanIdL();
    DEBUG1("CHotSpotSession::EasyWlanIdL() ret: % d", iEasyWlanId);
    CleanupStack::PopAndDestroy( &cmManager );
    }

// -----------------------------------------------------------------------------
// ConnectionStateChanged
// -----------------------------------------------------------------------------
//
void CHotSpotSession::ConnectionStateChanged( TWlanConnectionMode  aNewState ) 
    {
    DEBUG1( "CHotSpotSession::ConnectionStateChanged() aNewState=%d", aNewState );
    switch ( aNewState )
            {
            case EWlanConnectionModeSearching:
                {
                break;
                }
            case EWlanConnectionModeInfrastructure:
            case EWlanConnectionModeSecureInfra:
                {
                iMgtClient->CancelNotifications();
                ProcessAssociationStatus( iIapId, ETrue );
                break;
                }
            case EWlanConnectionModeAdhoc:
            case EWlanConnectionModeNotConnected:
                {
                iMgtClient->CancelNotifications();
                iServer.SetAssociationFlag( EFalse );
                break;
                }
            default:
                {
                iMgtClient->CancelNotifications();
                iServer.SetAssociationFlag( EFalse );
                }
            }
    
    }

// end of file