hotspotfw/hsserver/src/hotspotserver.cpp
author Dremov Kirill (Nokia-D-MSW/Tampere) <kirill.dremov@nokia.com>
Thu, 17 Dec 2009 09:20:28 +0200
changeset 0 56b72877c1cb
child 2 6e4b6261703d
permissions -rw-r--r--
Revision: 200949 Kit: 200951

/*
* 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 Plugin Server
*
*/






// INCLUDE FILES
#include <e32std.h>
#include <f32file.h>
#include <wlanmgmtclient.h>
#include <wlanmgmtinterface.h>
#include <e32std.h>
#include <commsdattypesv1_1.h>

#include <cmconnectionmethodext.h>
#include <cmconnectionmethoddef.h>
#include <cmpluginwlandef.h>
#include <cmmanagerext.h>
#include <cmmanagerdef.h>
#include <cmdestinationext.h>

#include "hotspotserver.h"
#include "am_debug.h"
#include "hotspotsession.h"
#include "hssclientplugin.h"
#include "hssiapsettingshandler.h"

// LOCAL FUNCTION PROTOTYPES
GLDEF_C TInt E32Main();

using namespace CMManager;

// CONSTANTS
// Panic codes for HotSpot server
const TInt KHotSpotPanicCleanupStackCreationFailed  = 1;
const TInt KHotSpotPanicOpenSemaforeFailed          = 2;
const TInt KHotSpotPanicCreationOfSchedulerFailed   = 3;

// Default timeout values

const TUint KMillion = 1000000;
const TUint KHssDefaultLoginTimeMicroSecs = 180 * KMillion;  // 180 seconds (3 mins)
const TUint KHssMinLoginTime =      5;   // 5 seconds
const TUint KHssMaxLoginTime =      1200; // 1200 seconds (20 mins)
const TUint KHssDefaultLogoutTimeMicroSecs  = 12 * KMillion;   // 12 seconds
const TUint KHssMinLogoutTime =     1;    // 1 seconds
const TUint KHssMaxLogoutTime =     30;   // 30 seconds

// Panic category of HotSpot server 
_LIT( KHotSpotModuleName, "HOTSPOTSRV" );

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

// -----------------------------------------------------------------------------
// RunServerL
// -----------------------------------------------------------------------------
// 
static void RunServerL()
    {
    User::LeaveIfError( User::RenameThread( KHotSpotServerName ) );

    CActiveScheduler* s=new(ELeave) CActiveScheduler;
    if ( !s )
        {
        User::Panic( KHotSpotModuleName, KHotSpotPanicCreationOfSchedulerFailed );
        }
    CleanupStack::PushL(s);
    CActiveScheduler::Install(s);

    CHotSpotServer::NewLC(); // Is NewLC: Server was pushed into cleanup stack.

    RSemaphore started;
    TInt err = started.CreateGlobal( KHotSpotServerSemaphore, 0 );
    if ( err != KErrNone )
        {
        err = started.OpenGlobal( KHotSpotServerSemaphore );
        }
    
    __ASSERT_ALWAYS(
        err == KErrNone, 
        User::Panic( KHotSpotModuleName, KHotSpotPanicOpenSemaforeFailed )
        );
        
    // lets everyone know that the thread is ready to deal with requests            
    RProcess::Rendezvous(KErrNone);
        
    started.Signal();
    started.Close();

    DEBUG("**** HotspotServer: server fully running");
    CActiveScheduler::Start();
    CleanupStack::PopAndDestroy( 2, s ); // Cleanup both server and scheduler
    REComSession::FinalClose();
    }

// -----------------------------------------------------------------------------
// PanicClient
// -----------------------------------------------------------------------------
//    
void PanicClient(const RMessagePtr2& aMessage,THotspotPanic aPanic)
	{
	_LIT(KPanic,"HotspotServer");
	aMessage.Panic(KPanic,aPanic);
	}

// ============================ MEMBER FUNCTIONS ===============================
    
// -----------------------------------------------------------------------------
// CHotSpotServer
// -----------------------------------------------------------------------------
//
CHotSpotServer::CHotSpotServer()
	:CPolicyServer( EPriorityStandard, THotSpotServerPlatSecPolicy, ESharableSessions )
    {
	}

// -----------------------------------------------------------------------------
// NewLC
// -----------------------------------------------------------------------------
//
CHotSpotServer* CHotSpotServer::NewLC()
	{
	DEBUG("**** HotSpotServer: CHotSpotServer::NewLC");
	CHotSpotServer* self = new(ELeave) CHotSpotServer;
	CleanupStack::PushL(self);
	self->ConstructL();
	return self;
	}

// -----------------------------------------------------------------------------
// ~CHotSpotServer
// -----------------------------------------------------------------------------
//
CHotSpotServer::~CHotSpotServer()
	{
	DEBUG("**** HotSpotServer: CHotSpotServer::~CHotSpotServer");
    
    iMap.Close();
    iNotificationArray.Close();
    iLoginLogoutTimerArray.Close();
    
 	if ( iMgtClient != NULL )
        {
#ifndef __WINS__	
        iMgtClient->CancelNotifications();
#endif
        delete iMgtClient;
        }
 	iMgtClient = NULL;
 	
	}

// -----------------------------------------------------------------------------
// ConstructL
// -----------------------------------------------------------------------------
//
void CHotSpotServer::ConstructL()
    {
  
    DEBUG("**** HotSpotServer: CHotSpotServer::ConstructL");
	StartL( KHotSpotServerName );
	
	iIapCheckValue = EFalse;
    iLogoutSent = EFalse;
    iLoginValue = ETrue;
    iAssociationValue = EFalse;
	
#ifndef __WINS__

    // Change config daemon for Easy WLAN access point
    iConfigDaemonChanged = KErrNone;
    TBool retVal( EFalse );
    iEasyWlanId = KEasyWlanServiceId; // Set to default value
    TRAPD( leave, retVal = EasyWlanIdL() );
    if ( KErrNone != leave )
        {
        iConfigDaemonChanged = leave;
        }
    if ( !retVal )
        {
        iConfigDaemonChanged = KErrGeneral;
        }
    DEBUG1("**** HotSpotServer: CHotSpotServer::ConstructL iConfigDaemonChanged: %d", iConfigDaemonChanged );
#endif        
    // Activate notifications for IAP check purposes
    // When EWlanConnectionModeNotConnected is received we can cancel this and 
    // we know that it safe to go through IAPs.
    iMgtClient = CWlanMgmtClient::NewL();
#ifndef __WINS__
 	iMgtClient->ActivateNotificationsL( *this );
#endif 
    }

// -----------------------------------------------------------------------------
// ConnectionStateChanged
// -----------------------------------------------------------------------------
//
void CHotSpotServer::ConnectionStateChanged( TWlanConnectionMode  aNewState ) 
	{
	DEBUG1( "CHotSpotServer::ConnectionStateChanged() aNewState=%d", aNewState );
    if ( aNewState == EWlanConnectionModeNotConnected )
    	{
    	if ( iMgtClient != NULL )
            {
#ifndef __WINS__
            iMgtClient->CancelNotifications();
#endif
            DEBUG("CHotSpotServer::ConnectionStateChanged2");
            }
    	
     	TRAPD(err, CheckIapsL());
     	if ( err != KErrNone )
     		{
     		DEBUG1("CHotSpotServer::ConnectionStateChanged(): %d", err);
     		}
     	if ( iConfigDaemonChanged != KErrNone )
     	    {
     	    // ConstructL call leaved. Let's call again once more.
     	    TRAP_IGNORE( EasyWlanIdL() );
     	    }
     	}
    }

// -----------------------------------------------------------------------------
// CheckIapsL
// -----------------------------------------------------------------------------
//
void CHotSpotServer::CheckIapsL()
    {
    DEBUG("CHotSpotServer::CheckIapsL");
 	 	
 	_LIT(KMarkFirst, "[" );
 	_LIT(KMarkLast, "]" );
 	// This is needed to be checked only once per boot
	if ( iIapCheckValue == EFalse )
	    {
		iIapCheckValue = ETrue;
		
		RCmManagerExt cmManager;
	    cmManager.OpenL();
	    CleanupClosePushL(cmManager);

	    TBool supportedBearersOnly = ETrue;
	    TBool legacyCmsOnly = EFalse;
	    
	    RArray<TUint32> cmArray;
        CleanupClosePushL( cmArray );
	    
	    cmManager.ConnectionMethodL( cmArray, supportedBearersOnly, legacyCmsOnly );
	    DEBUG1("CHotSpotServer::CheckIapsL count: %d", cmArray.Count());  
	    for( TInt i = 0; i < cmArray.Count(); i++ )
	    	{
	    	RCmConnectionMethodExt cm;
		    TRAPD( err, cm = cmManager.ConnectionMethodL( cmArray[i] ) );
		    DEBUG1("CHotSpotServer::CheckIapsL: err %d", err ); 
		    if ( KErrNone == err )
		    	{
		    	HBufC* client( NULL );
		    	TRAPD( errr, client = cm.GetStringAttributeL( EWlanServiceExtensionTableName ));
		    	DEBUG1("CHotSpotServer::CheckIapsL: errr %d", errr );  
		    	if( KErrNone == errr )
		    		{
		    		TBuf<KIapNameLength> clientUid;
		    		TUid uid(TUid::Null());
		    		
		    		clientUid.Copy( client->Des() );
                    delete client;
		    		TInt indx = clientUid.Find( KMarkFirst );
		    		if ( KErrNotFound != indx )
						{
						DEBUG("CHotSpotServer::CheckIapsL Client is found");
						clientUid.Delete( indx, 1 );
					    indx = clientUid.Find( KMarkLast );
						if ( KErrNotFound != indx )
							{
							clientUid.Delete( indx, 1 );
							}
						// Convert TBuf to TUid
						TLex lex( clientUid );
						TUint value( 0 );
						User::LeaveIfError( lex.Val( value, EHex ) );
						uid.iUid = value; 
						 	   		
						// Try to find if 3rd party client exists.
						// Delete IAP if no client.
						CHssClientPlugin* plugin(NULL);
						TBuf8<KExtensionAPILength> nullBuf;
						TRAPD( error, plugin = CHssClientPlugin::NewL( uid, nullBuf ) );
				        delete plugin;

						DEBUG1("CHotSpotServer::CheckIapsL find client error: %d", error );
						if ( error == KErrNotFound )
							{
		    	   			cm.DeleteL();
							}
		    	   		}
		    		}
		    	}
		    DEBUG("CHotSpotServer::CheckIapsLOK");
	    	}
        CleanupStack::PopAndDestroy( &cmArray );
        CleanupStack::PopAndDestroy( &cmManager );
		}
	DEBUG("CHotSpotServer::CheckIapsL Done");
    }

// -----------------------------------------------------------------------------
// NewSessionL
// -----------------------------------------------------------------------------
//
CSession2* CHotSpotServer::NewSessionL( const TVersion& aVersion, 
                                        const RMessage2& /* aMessage */ ) const
    {
	TVersion version( KHotSpotMajorVersionNumber,
                      KHotSpotMinorVersionNumber,
                      KHotSpotBuildVersionNumber );

    if ( !User::QueryVersionSupported( version, aVersion ) )
        {
        User::Leave( KErrNotSupported );
        }

	DEBUG("**** CHotSpotServer::NewSessionL");
	CHotSpotSession* session = 
        CHotSpotSession::NewL( const_cast<CHotSpotServer&>( *this ) );
    return session;
    }

// ---------------------------------------------------------
// NotifyAdd
// ---------------------------------------------------------
//
void CHotSpotServer::NotifyAdd(
    CNotificationBase& aNotification )
    {
    DEBUG( "CHotSpotServer::NotifyAdd()" );
    iNotificationArray.Insert( &aNotification, 0 );
    }

// ---------------------------------------------------------
// NotifyRemove
// ---------------------------------------------------------
//
void CHotSpotServer::NotifyRemove(
    CNotificationBase& aNotification )
    {
    DEBUG( "CHotSpotServer::NotifyRemove()" );
    TInt index = iNotificationArray.Find( &aNotification );
    iNotificationArray.Remove( index );
    }

// -----------------------------------------------------------------------------
// SaveMessage
// -----------------------------------------------------------------------------
//
TInt CHotSpotServer::SaveMessage( TUint aIapId, const RMessage2& aMessage, 
                                  THotSpotCommands aCommand )
    {
    DEBUG("**** HotspotServer: SaveMessage");
    TInt ret( KErrNone );
    SRequestMapEntry entry;
    entry.iMessage = aMessage;
    entry.iFunction = aCommand;
    entry.iIapId = aIapId;
    ret = iMap.Append(entry);
    return ret;
    }

// -----------------------------------------------------------------------------
// CompleteMessage
// -----------------------------------------------------------------------------
//
void CHotSpotServer::CompleteMessage( TInt aIndex, TInt aResult )
    {
    DEBUG("**** HotspotServer: CompleteMessage");
    SRequestMapEntry entry = iMap[aIndex];
    
    RMessagePtr2 message = entry.iMessage;
    message.Complete( aResult );
    iMap.Remove( aIndex );
    }

// -----------------------------------------------------------------------------
// EditMessage
// -----------------------------------------------------------------------------
//
TInt CHotSpotServer::EditMessage( TInt aIndex, TPckg<HssScanList>& aData)
    {
    DEBUG("**** HotspotServer: EditMessage");
    TInt ret( KErrNone );
    
    iMap[aIndex].iMessage.Write(0, aData);
    
    DEBUG1("**** HotspotServer: EditMessage ret: %d", ret);
    return ret;
    }


// -----------------------------------------------------------------------------
// FindMessage
// -----------------------------------------------------------------------------
//
TInt CHotSpotServer::FindMessage( TUint aIapId, THotSpotCommands aCommand )
    {
    DEBUG("**** HotspotServer: FindMessage");
    TInt ret( KErrNotFound );
    SRequestMapEntry entry;
    
    for ( TInt i = 0; i < iMap.Count(); i++ ) 
        {
        entry = iMap[i];
        if ( ( entry.iFunction == aCommand ) && ( entry.iIapId == aIapId ) )
            {
            // Correct message found
            // Now stop loop and return index value, so that CompeteMessage can
            // be called with that
            ret = i;
            i = iMap.Count();
            }
        }
    DEBUG1("**** HotspotServer: FindMessage ret: %d", ret);
    return ret;
    }

// -----------------------------------------------------------------------------
// SetLogoutFlag
// -----------------------------------------------------------------------------
//
void CHotSpotServer::SetLogoutFlag( TBool aValue )
    {
    DEBUG("HotspotServer::SetLogoutFlag");
    iLogoutSent = aValue;
    }
    
// -----------------------------------------------------------------------------
// GetLogoutFlagValue
// -----------------------------------------------------------------------------
//
TBool CHotSpotServer::GetLogoutFlagValue()
    {
    DEBUG("HotspotServer::GetLogoutFlagValue()");
    return iLogoutSent;
    }

// -----------------------------------------------------------------------------
// SetLoginFlag
// -----------------------------------------------------------------------------
//
void CHotSpotServer::SetLoginFlag( TBool aValue )
    {
    DEBUG("HotspotServer::SetLoginFlag");
    iLoginValue = aValue;
    }
    
// -----------------------------------------------------------------------------
// GetLoginFlagValue
// -----------------------------------------------------------------------------
//
TBool CHotSpotServer::GetLoginFlagValue()
    {
    DEBUG("HotspotServer::GetLoginFlagValue()");
    return iLoginValue;
    }


// -----------------------------------------------------------------------------
// SetAssociationFlag
// -----------------------------------------------------------------------------
//
void CHotSpotServer::SetAssociationFlag( TBool aValue )
    {
    DEBUG("HotspotServer::SetAssociationFlag");
    iAssociationValue = aValue;
    }
        
// -----------------------------------------------------------------------------
// GetAssociationFlagValue
// -----------------------------------------------------------------------------
//
TBool CHotSpotServer::GetAssociationFlagValue()
    {
    DEBUG("HotspotServer::GetAssociationFlagValue()");
    return iAssociationValue;
    }

// -----------------------------------------------------------------------------
// SetServiceId
// -----------------------------------------------------------------------------
//
void CHotSpotServer::SetServiceId( TInt aServiceId )
    {
    DEBUG("HotspotServer::SetServiceId");
    iCurrentServiceIdInUse = aServiceId;
    }
    
// -----------------------------------------------------------------------------
// GetServiceId
// -----------------------------------------------------------------------------
//
TInt CHotSpotServer::GetServiceId()
    {
    DEBUG("HotspotServer::GetServiceId()");
    return iCurrentServiceIdInUse;
    }
    
// -----------------------------------------------------------------------------
// RunError
// -----------------------------------------------------------------------------
//
TInt CHotSpotServer::RunError( TInt aError )
	{
    // error from CHotSpotSession::ServiceL
    Message().Complete( aError );
    // Continue  reading client requests
    ReStart();
    return (KErrNone);
	}

// -----------------------------------------------------------------------------
// EasyWlanIdL
// -----------------------------------------------------------------------------
//
TBool CHotSpotServer::EasyWlanIdL()
    {
    TBool ret( EFalse );
    DEBUG("CHotSpotServer::EasyWlanIdL()");
    RCmManagerExt cmManager;
    cmManager.OpenL();
    CleanupClosePushL( cmManager );
    
    iEasyWlanId = cmManager.EasyWlanIdL();
    DEBUG1("CHotSpotServer::EasyWlanIdL() ret: % d", iEasyWlanId);
    // if iEasyWlanId is 0, then it was not found
    if ( iEasyWlanId > 0 )
        {
        RCmConnectionMethodExt plugin = cmManager.ConnectionMethodL( iEasyWlanId );
        CleanupClosePushL( plugin );
        //iEasyWlanId = plugin.GetIntAttributeL( /*ECmIapServiceId*/EWlanServiceId )
        plugin.SetStringAttributeL( ECmConfigDaemonManagerName, KHotSpotPlugin );
        // commit changes
        plugin.UpdateL();
        CleanupStack::PopAndDestroy( &plugin ); // Close() called on "plugin"
        ret = ETrue;
        }
    CleanupStack::PopAndDestroy( &cmManager );
    DEBUG("CHotSpotServer::EasyWlanIdL() DONE");
    return ret;
    }

// -----------------------------------------------------------------------------
// GetEasyWlanId
// -----------------------------------------------------------------------------
//
TUint32 CHotSpotServer::GetEasyWlanId()
    {
    return iEasyWlanId;
    }

// -----------------------------------------------------------------------------
// GetLoginTimerMicroSecs
// -----------------------------------------------------------------------------
//
TUint CHotSpotServer::GetLoginTimeMicroSecs( TUid aClientUid )
    {
    // Default timer value will be returned if matching client UID isn't found.
    TUint retval = KHssDefaultLoginTimeMicroSecs ;
    
    TInt ret = CHotSpotServer::FindClientUid( aClientUid );
    if (ret != KErrNotFound)
        {
        // ret is the matching element's index.
        retval = iLoginLogoutTimerArray[ret].loginTimeMicroSecs;
        }

    return retval;
    }

// -----------------------------------------------------------------------------
// GetLogoutTimerMicroSecs
// -----------------------------------------------------------------------------
//
TUint CHotSpotServer::GetLogoutTimeMicroSecs( TUid aClientUid )
    {
    // Default timer value will be returned if matching client UID isn't found.
    TUint retval = KHssDefaultLogoutTimeMicroSecs ;
    
    TInt ret = CHotSpotServer::FindClientUid( aClientUid );
    if (ret != KErrNotFound)
        {
        // ret is the matching element's index.
        retval = iLoginLogoutTimerArray[ret].logoutTimeMicroSecs;
        }

    return retval;
    }

// -----------------------------------------------------------------------------
// SetTimerValues
// -----------------------------------------------------------------------------
//
void CHotSpotServer::SetTimerValues(
        TUid aClientUid,
        TUint aLoginTimerValue,   // in seconds
        TUint aLogoutTimerValue ) // in seconds
    {    
    TInt ret = CHotSpotServer::FindClientUid( aClientUid );
    TUint loginTimeMicroSecs = KHssDefaultLoginTimeMicroSecs ;
    TUint logoutTimeMicroSecs = KHssDefaultLogoutTimeMicroSecs ;
    
    // Check that values are in bounds and modify them into micro seconds.
    if( aLoginTimerValue >= KHssMinLoginTime &&
            aLoginTimerValue <= KHssMaxLoginTime )
        {
        loginTimeMicroSecs = KMillion * aLoginTimerValue;
        }

    if( aLogoutTimerValue >= KHssMinLogoutTime &&
            aLogoutTimerValue <= KHssMaxLogoutTime )
        {
        logoutTimeMicroSecs = KMillion * aLogoutTimerValue;
        }

    if (ret != KErrNotFound)
        {
        DEBUG("CHotSpotServer::SetTimerValues(): Existing client modified.");
        // ret is the matching element's index.
        iLoginLogoutTimerArray[ret].loginTimeMicroSecs = loginTimeMicroSecs;
        iLoginLogoutTimerArray[ret].logoutTimeMicroSecs = logoutTimeMicroSecs;
        }
    else
        {
        DEBUG("CHotSpotServer::SetTimerValues(): New Client added.");
        // Create a new element and append it to the array.
        const SLoginLogoutTimers addedElement = {
                aClientUid,
                loginTimeMicroSecs,
                logoutTimeMicroSecs };
        iLoginLogoutTimerArray.Append( addedElement );
        }
    }

// -----------------------------------------------------------------------------
// FindClientUid
// -----------------------------------------------------------------------------
//
TInt CHotSpotServer::FindClientUid( TUid aClientUid )
    {
    TInt count = iLoginLogoutTimerArray.Count();
    TInt i = 0;
    TInt ret = KErrNotFound;
    
    while (i < count)
        {
        if (aClientUid == iLoginLogoutTimerArray[i].clientUid)
            {
            ret = i;
            break;
            }
        i++;
        }

    return ret;    
    }

// ========================== OTHER EXPORTED FUNCTIONS =========================

// -----------------------------------------------------------------------------
// E32Main implements the executable entry function.
// Note that because the target type of the IPWServer Hss
// is EXEDLL, the entry point has different signature depending
// on the build platform.
// Creates a cleanup stack and runs the server. 
// Returns: Zero
// -----------------------------------------------------------------------------
//
GLDEF_C TInt E32Main()
    {
    __UHEAP_MARK;
    DEBUG("**** HotspotServer: E32Main");
    CTrapCleanup* cleanup=CTrapCleanup::New();
    TInt r=KErrNoMemory;
    if (cleanup)
        {
        TRAP(r,RunServerL());
        delete cleanup;
        }
    else
        {
        User::Panic( KHotSpotModuleName, KHotSpotPanicCleanupStackCreationFailed );
        }
    __UHEAP_MARKEND;
    return r;
    }
 
// end of file