localconnectivityservice/dun/server/src/DunServerUtils.cpp
author Pat Downey <patd@symbian.org>
Wed, 01 Sep 2010 12:20:40 +0100
branchRCL_3
changeset 40 52a167391590
parent 0 c3e98f10fcf4
permissions -rw-r--r--
Revert incorrect RCL_3 drop: Revision: 201033 Kit: 201035

/*
* Copyright (c) 2006-2007 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:  Utility class for CDunServer
*
*/


#include <e32uid.h>
#include "DunServer.h"
#include "DunServerUtils.h"
#include "DunDebug.h"

// ---------------------------------------------------------------------------
// Two-phased constructor.
// ---------------------------------------------------------------------------
//
CDunServerUtils* CDunServerUtils::NewL( CDunServer& aParent )
    {
    CDunServerUtils* self = new (ELeave) CDunServerUtils( aParent );
    CleanupStack::PushL( self );
    self->ConstructL();
    CleanupStack::Pop( self );
    return self;
    }

// ---------------------------------------------------------------------------
// Destructor.
// ---------------------------------------------------------------------------
//
CDunServerUtils::~CDunServerUtils()
    {
    FTRACE(FPrint(_L("CDunServerUtils::~CDunServerUtils()")));
    FTRACE(FPrint(_L("CDunServerUtils::~CDunServerUtils() complete")));
    }

// ---------------------------------------------------------------------------
// CDunServerUtils::CDunServerUtils
// ---------------------------------------------------------------------------
//
CDunServerUtils::CDunServerUtils( CDunServer& aParent ) :
    iParent( aParent ),
    iTransporter( aParent.iTransporter ),
    iCloseWait( aParent.iCloseWait ),
    iConnData( aParent.iConnData ),
    iPluginQueue( aParent.iPluginQueue ),
    iClosedQueue( aParent.iClosedQueue )
    {
    }

// ---------------------------------------------------------------------------
// CDunServerUtils::ConstructL
// ---------------------------------------------------------------------------
//
void CDunServerUtils::ConstructL()
    {
    FTRACE(FPrint( _L("CDunServerUtils::ConstructL()" ) ));
    FTRACE(FPrint( _L("CDunServerUtils::ConstructL() complete" ) ));
    }

// ---------------------------------------------------------------------------
// From class MDunServerUtility.
// Closes plugins with state marked as zombie
// ---------------------------------------------------------------------------
//
TInt CDunServerUtils::RemoveZombiePlugins()
    {
    FTRACE(FPrint(_L("CDunServerUtils::RemoveZombiePlugins()")));
    TInt i;
    TInt retVal = KErrNone;
    for ( i=iConnData.Count()-1; i>=0; i-- )
        {
        if ( iConnData[i].iPluginState == EDunStateZombie )
            {
            // Following closes and removes if remove ok
            FTRACE(FPrint(_L("CDunServerUtils::RemoveZombiePlugins() trying close at index %d"), i));
            TInt retTemp = TryClosePlugin( i, ETrue, EFalse, EFalse );
            if ( retTemp != KErrNone )
                {
                retVal = KErrGeneral;
                }
            }
        }
    FTRACE(FPrint(_L("CDunServerUtils::RemoveZombiePlugins() complete")));
    return retVal;
    }

// ---------------------------------------------------------------------------
// From class MDunServerUtility.
// Loads local media module
// ---------------------------------------------------------------------------
//
TInt CDunServerUtils::CreateNewPlugin( TUid aPluginUid )
    {
    FTRACE(FPrint(_L("CDunServerUtils::CreateNewPlugin()")));
    // plugin not constructed, construct now
    TFileName pluginFile;
    switch ( aPluginUid.iUid )
        {
        case KDunBtPluginUidValue:
            pluginFile.Copy( KDunPluginBt );
            break;
        case KDunIrPluginUidValue:
            pluginFile.Copy( KDunPluginIrda );
            break;
        case KDunUsbPluginUidValue:
            pluginFile.Copy( KDunPluginUsb );
            break;
        default:
            FTRACE(FPrint(_L("CDunServerUtils::CreateNewPlugin() (not supported) complete")));
            return KErrNotSupported;
        }
    TDunConnectionData emptyConn;
    emptyConn.iLocalModulePtr = NULL;
    emptyConn.iLocalModuleUid = TUid::Null();
    emptyConn.iPluginState = EDunStateNone;
    TInt retTemp = iConnData.Append( emptyConn );
    if ( retTemp != KErrNone )
        {
        FTRACE(FPrint(_L("CDunServerUtils::CreateNewPlugin() (append failed!) complete")));
        return retTemp;
        }
    retTemp = ConstructLocalMediaModule( aPluginUid, pluginFile );
    if ( retTemp != KErrNone )
        {
        iConnData.Remove( iConnData.Count()-1 );
        FTRACE(FPrint(_L("CDunServerUtils::CreateNewPlugin() (ERROR) complete")));
        return retTemp;
        }
    FTRACE(FPrint(_L("CDunServerUtils::CreateNewPlugin() complete")));
    return KErrNone;
    }

// ---------------------------------------------------------------------------
// From class MDunServerUtility.
// Constructs local media module
// ---------------------------------------------------------------------------
//
TInt CDunServerUtils::ConstructLocalMediaModule( const TUid& aPluginUid,
                                                 const TPtrC& aDllName )
    {
    FTRACE(FPrint(_L("CDunServerUtils::ConstructLocalMediaModule()")));
    // Create a new library object
    if ( iConnData.Count() == 0 )
        {
        FTRACE(FPrint(_L("CDunServerUtils::ConstructLocalMediaModule() (not ready) complete")));
        return KErrNotReady;
        }
    TInt index = iConnData.Count() - 1;
    iConnData[index].iLocalModuleUid = aPluginUid;
    iConnData[index].iPluginState = EDunStateTryLoad;
    // Load the DLL containing the plug-in
    TUidType uidType( KDynamicLibraryUid,
                      KDunLocalMediaPluginInterfaceUid,
                      aPluginUid );
    FTRACE(FPrint(_L("CDunServerUtils::ConstructLocalMediaModule() loading")));
    TInt retTemp = iConnData[index].iModuleLibrary.Load( aDllName, uidType );
    if ( retTemp != KErrNone )
        {
        FTRACE(FPrint(_L("CDunServerUtils::ConstructLocalMediaModule() (ERROR) complete")));
        return retTemp;
        }
    FTRACE(FPrint(_L("CDunServerUtils::ConstructLocalMediaModule() plugin 0x%08X loaded"), aPluginUid.iUid));
    // Create the plugin object.
    FTRACE(FPrint(_L("CDunServerUtils::ConstructLocalMediaModule() looking up")));
    TLibraryFunction factoryFunction = iConnData[index].iModuleLibrary.Lookup( 1 );
    if ( !factoryFunction )
        {
        iConnData[index].iModuleLibrary.Close();
        FTRACE(FPrint(_L("CDunServerUtils::ConstructLocalMediaModule() (ERROR) complete")));
        return KErrNotFound;
        }
    MDunLocalMediaPlugin* localPlugin =
        reinterpret_cast<MDunLocalMediaPlugin*>( factoryFunction() );
    if ( !localPlugin )
        {
        iConnData[index].iModuleLibrary.Close();
        FTRACE(FPrint(_L("CDunServerUtils::ConstructLocalMediaModule() (ERROR) complete")));
        return KErrGeneral;
        }
    iConnData[index].iLocalModulePtr = localPlugin;
    FTRACE(FPrint(_L("CDunServerUtils::ConstructLocalMediaModule() constructing")));
    TRAPD( retTrap, localPlugin->ConstructL(&iParent, iTransporter) );
    if ( retTrap != KErrNone )
        {
        delete iConnData[index].iLocalModulePtr;
        iConnData[index].iLocalModulePtr = NULL;
        iConnData[index].iModuleLibrary.Close();
        FTRACE(FPrint(_L("CDunServerUtils::ConstructLocalMediaModule() (ERROR) complete")));
        return retTrap;
        }
    iConnData[index].iPluginState = EDunStateLoaded;
    FTRACE(FPrint(_L("CDunServerUtils::ConstructLocalMediaModule() complete")));
    return KErrNone;
    }

// ---------------------------------------------------------------------------
// From class MDunServerUtility.
// Clears queued UIDs
// ---------------------------------------------------------------------------
//
TBool CDunServerUtils::ClearQueuedUIDs( TUid aPluginUid,
                                        TBool aClearClosed,
                                        TBool aClearQueued )
    {
    FTRACE(FPrint(_L("CDunServerUtils::ClearQueuedUIDs()")));
    TInt i;
    TBool cleared = EFalse;
    if ( aClearClosed )
        {
        for ( i=iClosedQueue.Count()-1; i>=0; i-- )
            {
            if ( iClosedQueue[i] == aPluginUid )
                {
                iClosedQueue.Remove( i );
                cleared = ETrue;
                FTRACE(FPrint(_L("CDunServerUtils::ClearQueuedUIDs() removed from closed queue at %d"), i));
                }
            }
        }
    if ( aClearQueued )
        {
        for ( i=iPluginQueue.Count()-1; i>=0; i-- )
            {
            if ( iPluginQueue[i] == aPluginUid )
                {
                iPluginQueue.Remove( i );
                cleared = ETrue;
                FTRACE(FPrint(_L("CDunServerUtils::ClearQueuedUIDs() removed from plugin queue at %d"), i));
                }
            }
        }
    FTRACE(FPrint(_L("CDunServerUtils::ClearQueuedUIDs() complete")));
    return cleared;
    }

// ---------------------------------------------------------------------------
// From class MDunServerUtility.
// Tries to close loaded local media plugin
// ---------------------------------------------------------------------------
//
TInt CDunServerUtils::TryClosePlugin( TInt aIndex,
                                      TBool aDequeue,
                                      TBool aClientClose,
                                      TBool aSelfClose )
    {
    FTRACE(FPrint(_L("CDunServerUtils::TryClosePlugin()")));
    if ( aIndex < 0 ||
         aIndex >= iConnData.Count() )
        {
        FTRACE(FPrint(_L("CDunServerUtils::TryClosePlugin() (not found) complete")));
        return KErrNotFound;
        }
    TInt retTemp = TryUninitialize( aIndex );
    if ( retTemp != KErrNone )
        {
        FTRACE(FPrint(_L("CDunServerUtils::TryClosePlugin() (ERROR) complete")));
        return retTemp;
        }
    if ( !aSelfClose )
        {
        retTemp = DoClosePlugin( aIndex, aDequeue, aClientClose );
        FTRACE(FPrint(_L("CDunServerUtils::TryClosePlugin() complete")));
        return retTemp;
        }
    retTemp = iCloseWait->AddPluginToClose( iConnData[aIndex].iLocalModulePtr );
    if ( retTemp != KErrNone )
        {
        iConnData[aIndex].iPluginState = EDunStateZombie;
        FTRACE(FPrint(_L("CDunServerUtils::TryClosePlugin() state changed to %d"), EDunStateZombie));
        return retTemp;
        }
    retTemp = iCloseWait->IssueRequest();
    if ( retTemp != KErrNone )
        {
        iConnData[aIndex].iPluginState = EDunStateZombie;
        FTRACE(FPrint(_L("CDunServerUtils::TryClosePlugin() state changed to %d"), EDunStateZombie));
        return retTemp;
        }
    FTRACE(FPrint(_L("CDunServerUtils::TryClosePlugin() (waiting) complete")));
    return KErrNone;
    }

// ---------------------------------------------------------------------------
// From class MDunServerUtility.
// Closes a plugin directly without uninitializing it
// ---------------------------------------------------------------------------
//
TInt CDunServerUtils::DoClosePlugin(
    TInt aIndex,
    TBool aDequeue,
    TBool aClientClose )
    {
    FTRACE(FPrint(_L("CDunServerUtils::DoClosePlugin()")));
    if ( aIndex < 0 ||
         aIndex >= iConnData.Count() )
        {
        FTRACE(FPrint(_L("CDunServerUtils::DoClosePlugin() (not found) complete")));
        return KErrNotFound;
        }
    TUid pluginUid = iConnData[aIndex].iLocalModuleUid;
    DoImmediatePluginClose( aIndex, aDequeue );
    if ( !aClientClose )
        {
        // Plugin was closed by something else than client
        // Enqueue it to closed queue
        TInt i;
        TInt count = iClosedQueue.Count();
        for ( i=0; i<count; i++ )
            {
            if ( iClosedQueue[i] == pluginUid )
                {
                FTRACE(FPrint(_L("CDunServerUtils::DoClosePlugin() (already exists) complete")));
                return KErrAlreadyExists;
                }
            }
        TInt retTemp = iClosedQueue.Append( pluginUid );
        if ( retTemp != KErrNone )
            {
            FTRACE(FPrint(_L("CDunServerUtils::DoClosePlugin() (append failed!) complete")));
            return retTemp;
            }
        FTRACE(FPrint(_L("CDunServerUtils::DoClosePlugin() appended to index %d"), iClosedQueue.Count()-1));
        }
    FTRACE(FPrint(_L("CDunServerUtils::DoClosePlugin() complete")));
    return KErrNone;
    }

// ---------------------------------------------------------------------------
// From class MDunServerUtility.
// Does immediate close of plugin
// ---------------------------------------------------------------------------
//
TInt CDunServerUtils::DoImmediatePluginClose( TInt aIndex, TBool aDequeue )
    {
    FTRACE(FPrint(_L("CDunServerUtils::DoImmediatePluginClose()")));
    if ( aIndex < 0 ||
         aIndex >= iConnData.Count() )
        {
        FTRACE(FPrint(_L("CDunServerUtils::DoImmediatePluginClose() (not found) complete")));
        return KErrNotFound;
        }
    delete iConnData[aIndex].iLocalModulePtr;
    iConnData[aIndex].iLocalModulePtr = NULL;
    if ( iConnData[aIndex].iModuleLibrary.Handle() != KNullHandle )
        {
        iConnData[aIndex].iModuleLibrary.Close();
        }
    iConnData.Remove( aIndex );
    // Now, the following check is needed to avoid recursion by:
    // ReopenQueuedPlugins()->OpenMediaByUid()->TryClosePlugin()->
    // DoImmediatePluginClose()->ReopenQueuedPlugins()
    if ( aDequeue )
        {
        iParent.ReopenQueuedPlugins();
        }
    // Ignore error(s); this function must only report it's own operation status
    FTRACE(FPrint(_L("CDunServerUtils::DoImmediatePluginClose() complete")));
    return KErrNone;
    }

// ---------------------------------------------------------------------------
// From class MDunServerUtility.
// Tries uninitialization and after that listening state switch on a plugin
// ---------------------------------------------------------------------------
//
TInt CDunServerUtils::TryInitializeToListening( TUid aPluginUid )
    {
    FTRACE(FPrint(_L("CDunServerUtils::TryInitializeToListening()")));
    TInt i;
    TInt count = iConnData.Count();
    for ( i=0; i<count; i++ )
        {
        if ( iConnData[i].iLocalModuleUid == aPluginUid )
            {
            break;
            }
        }
    if ( i >= count )
        {
        FTRACE(FPrint(_L("CDunServerUtils::TryInitializeToListening() (not found) complete")));
        return KErrNotFound;
        }
    TInt retTemp = TryUninitialize( i );
    if ( retTemp != KErrNone )
        {
        FTRACE(FPrint(_L("CDunServerUtils::TryInitializeToListening() (uninitialize error) complete")));
        return retTemp;
        }
    // Change from Uninitialized to Loaded because listening mode needs it
    // (plugin is already loaded anyway)
    iConnData[i].iPluginState = EDunStateLoaded;
    retTemp = TryListening( i );
    if ( retTemp != KErrNone )
        {
        FTRACE(FPrint(_L("CDunServerUtils::TryInitializeToListening() (listening error) complete")));
        return retTemp;
        }
    FTRACE(FPrint(_L("CDunServerUtils::TryInitializeToListening() complete")));
    return KErrNone;
    }

// ---------------------------------------------------------------------------
// From class MDunServerUtility.
// Tries listening state switch on a plugin
// ---------------------------------------------------------------------------
//
TInt CDunServerUtils::TryListening( TInt aIndex )
    {
    FTRACE(FPrint(_L("CDunServerUtils::TryListening()")));
    if ( aIndex < 0 ||
         aIndex >= iConnData.Count() )
        {
        FTRACE(FPrint(_L("CDunServerUtils::TryListening() (not found) complete")));
        return KErrNotFound;
        }
    if ( iConnData[aIndex].iPluginState != EDunStateLoaded )
        {
        FTRACE(FPrint(_L("CDunServerUtils::TryListening() (not ready) complete")));
        return KErrNotReady;
        }
    FTRACE(FPrint(_L("CDunServerUtils::TryListening() notifying server state change (%d)"), EDunStateTryListen));
    TInt retTemp =
        iConnData[aIndex].iLocalModulePtr->NotifyServerStateChange( EDunStateTryListen );
    if ( retTemp != KErrNone )
        {
        iConnData[aIndex].iPluginState = EDunStateZombie;
        FTRACE(FPrint(_L("CDunServerUtils::TryListening() state changed to %d"), EDunStateZombie));
        FTRACE(FPrint(_L("CDunServerUtils::TryListening() (ERROR) complete")));
        return retTemp;
        }
    // Plugin could have changed state, only change state if possible
    // This can happen if plugin has no real listening and switches directly
    // from listening mode to channeled mode
    if ( iConnData[aIndex].iPluginState == EDunStateTryListen )
        {
        iConnData[aIndex].iPluginState = EDunStateListening;
        }
    FTRACE(FPrint(_L("CDunServerUtils::TryListening() state changed to %d"), EDunStateListening));
    FTRACE(FPrint(_L("CDunServerUtils::TryListening() complete")));
    return KErrNone;
    }

// ---------------------------------------------------------------------------
// From class MDunServerUtility.
// Tries uninitialization of a plugin
// ---------------------------------------------------------------------------
//
TInt CDunServerUtils::TryUninitialize( TInt aIndex )
    {
    FTRACE(FPrint(_L("CDunServerUtils::TryUninitialize()")));
    if ( aIndex < 0 ||
         aIndex >= iConnData.Count() )
        {
        FTRACE(FPrint(_L("CDunServerUtils::TryUninitialize() (not found) complete")));
        return KErrNotFound;
        }
    if ( iConnData[aIndex].iPluginState == EDunStateUninitialized )
        {
        FTRACE(FPrint(_L("CDunServerUtils::TryUninitialize() (already uninitialized) complete")));
        return KErrNotReady;
        }
    FTRACE(FPrint(_L("CDunServerUtils::TryUninitialize() notifying server state change (%d)"), EDunStateTryUninitialize));
    TInt retTemp =
        iConnData[aIndex].iLocalModulePtr->NotifyServerStateChange( EDunStateTryUninitialize );
    if ( retTemp != KErrNone )
        {
        iConnData[aIndex].iPluginState = EDunStateZombie;
        FTRACE(FPrint(_L("CDunServerUtils::TryUninitialize() state changed to %d"), EDunStateZombie));
        FTRACE(FPrint(_L("CDunServerUtils::TryUninitialize() (ERROR) complete")));
        return retTemp;
        }
    // Plugin state must be EDunStateLoaded after uninitialization
    if ( iConnData[aIndex].iPluginState == EDunStateLoaded )
        {
        iConnData[aIndex].iPluginState = EDunStateUninitialized;
        FTRACE(FPrint(_L("CDunServerUtils::TryUninitialize() state changed to %d"), EDunStateUninitialized));
        }
    else
        {
        // Should never come here
        iConnData[aIndex].iPluginState = EDunStateZombie;
        FTRACE(FPrint(_L("CDunServerUtils::TryUninitialize() state changed to %d"), EDunStateZombie));
        }
    FTRACE(FPrint(_L("CDunServerUtils::TryUninitialize() complete")));
    return KErrNone;
    }