--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/upnp/upnpstack/serviceframework/src/upnpdispatcherengine.cpp Tue Feb 02 01:12:20 2010 +0200
@@ -0,0 +1,1151 @@
+/** @file
+* Copyright (c) 2005-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: Message dispacher engine
+*
+*/
+
+
+// INCLUDE FILES
+
+#include "upnpdispatcherengine.h"
+#include "upnphttpmessagefactory.h"
+#include "upnphttpfileaccess.h"
+#include "upnpdispatcherrequest.h"
+#include "upnpdispatcherengineobserver.h"
+#include "upnpcustomlog.h"
+#include "upnphttpserversession.h"
+#include "upnphttpserverruntime.h"
+#include "upnpsettings.h"
+
+#ifdef _DEBUG
+#define KLogFile _L("UPnPStack.txt")
+#endif
+
+// CONSTANTS
+const TInt KPortBufferLength = 10;
+_LIT8(KMSearchConfig,"1,1,5,5,10");
+
+// ============================ MEMBER FUNCTIONS ===============================
+
+// -----------------------------------------------------------------------------
+// CUpnpDispatcherEngine::CUpnpDispatcherEngine
+// C++ default constructor can NOT contain any code, that
+// might leave.
+// -----------------------------------------------------------------------------
+//
+CUpnpDispatcherEngine::CUpnpDispatcherEngine(
+ MDispatcherEngineObserver& aObserver )
+ : CActive( EPriorityStandard ),
+ iAddLocalPtr( NULL, 0 ),
+ iObserver( aObserver ),
+ iGetDevPtr( NULL, 0 ),
+ iGetServPtr( NULL, 0 ),
+ iRemoveUuidPtr( NULL, 0 ),
+ iIsSessionOpen( EFalse )
+ {
+ CActiveScheduler::Add( this );
+ iDeviceGetState = ENoOperation;
+ iAddLocalBuffer = NULL;
+ iRemoveUuid = NULL;
+ }
+
+// -----------------------------------------------------------------------------
+// CUpnpDispatcherEngine::ConstructL
+// Symbian 2nd phase constructor can leave.
+// -----------------------------------------------------------------------------
+//
+void CUpnpDispatcherEngine::ConstructL()
+ {
+#ifdef _DEBUG
+ iReqsInStart = RThread().RequestCount();
+ RThread().HandleCount( iProcessHandlesInStart, iThreadHandlesInStart );
+#endif // _DEBUG
+
+ User::LeaveIfError( iSession.Connect() );
+ iIsSessionOpen = ETrue;
+ iSession.RequestStartSsdpL();
+
+ iActiveRequest = NULL;
+ iSearch = NULL;
+
+ ConstructHttpL();
+
+ iDeviceGetState = ENoOperation;
+ }
+
+// -----------------------------------------------------------------------------
+// CUpnpDispatcherEngine::ConstructHttpL
+// -----------------------------------------------------------------------------
+//
+void CUpnpDispatcherEngine::ConstructHttpL()
+ {
+ TInt iapId = CUpnpSettings::GetIapL();
+ iHttpServerSession = CUpnpHttpServerSession::NewL( iapId, *this );
+ }
+
+// -----------------------------------------------------------------------------
+// CUpnpDispatcherEngine::NewL
+// Two-phased constructor.
+// -----------------------------------------------------------------------------
+//
+CUpnpDispatcherEngine* CUpnpDispatcherEngine::NewL(
+ MDispatcherEngineObserver& aObserver )
+ {
+ CUpnpDispatcherEngine* self = NewLC( aObserver );
+ CleanupStack::Pop( self );
+ return self;
+ }
+
+// -----------------------------------------------------------------------------
+// CUpnpDispatcherEngine::NewLC
+// Two-phased constructor.
+// -----------------------------------------------------------------------------
+//
+CUpnpDispatcherEngine* CUpnpDispatcherEngine::NewLC(
+ MDispatcherEngineObserver& aObserver )
+ {
+ CUpnpDispatcherEngine* self =
+ new ( ELeave ) CUpnpDispatcherEngine( aObserver );
+ CleanupStack::PushL( self );
+ self->ConstructL();
+ return self;
+ }
+
+// -----------------------------------------------------------------------------
+// CUpnpDispatcherEngine::~CUpnpDispatcherEngine
+// -----------------------------------------------------------------------------
+//
+CUpnpDispatcherEngine::~CUpnpDispatcherEngine()
+ {
+ // If active, calls DoCancel
+ Cancel();
+
+ delete iRemoveUuid;
+ iRemoveUuid = NULL;
+
+ delete iAddLocalBuffer;
+ iAddLocalBuffer = NULL;
+
+ delete iSearch;
+ iSearch = NULL;
+
+ delete iUuids;
+ iUuids = NULL;
+
+ delete [] iDevs;
+ delete [] iServs;
+
+ iSession.Close();
+ iIsSessionOpen = EFalse;
+ iCustomers.Reset();
+
+ if ( iHttpServerSession )
+ {
+ iHttpServerSession->Stop();
+ delete iHttpServerSession;
+ }
+
+ iPendingRequests.ResetAndDestroy();
+
+ iNewDevices.ResetAndDestroy();
+
+ RemoveHandledRequest();
+
+ delete iMXString;
+ }
+
+// -----------------------------------------------------------------------------
+// CUpnpDispatcherEngine::AddCustomer
+// -----------------------------------------------------------------------------
+//
+void CUpnpDispatcherEngine::AddCustomer( const MUpnpDispatcherCustomer& aCustomer )
+ {
+ // adds a new customer for CUpnpDispatcherEngine
+ if ( iCustomers.Find( &aCustomer ) == KErrNotFound )
+ {
+ iCustomers.Append( &aCustomer );
+ }
+ }
+// -----------------------------------------------------------------------------
+// CUpnpDispatcherEngine::RemoveCustomer
+// -----------------------------------------------------------------------------
+//
+void CUpnpDispatcherEngine::RemoveCustomer( const MUpnpDispatcherCustomer& aCustomer )
+ {
+ TInt pos = iCustomers.Find( &aCustomer );
+ if ( pos != KErrNotFound )
+ {
+ LOGS2("CUpnpDispatcherEngine::RemoveCustomer, removing customer 0x%x from position %d", &aCustomer, pos);
+ iCustomers.Remove( pos );
+ iCustomers.Compress();
+ LOGS("CUpnpDispatcherEngine::RemoveCustomer done");
+ }
+ else
+ LOGS1("CUpnpDispatcherEngine::RemoveCustomer, customer 0x%x not found", &aCustomer);
+ }
+
+// -----------------------------------------------------------------------------
+// CUpnpDispatcherEngine::SendMessageL
+// -----------------------------------------------------------------------------
+//
+void CUpnpDispatcherEngine::SendMessageL( CUpnpHttpMessage* aMessage )
+ {
+ // Sends a Http message
+ iHttpServerSession->SendMessageL( aMessage );
+ }
+
+// -----------------------------------------------------------------------------
+// CUpnpDispatcherEngine::UpdateDevicesL
+// -----------------------------------------------------------------------------
+//
+void CUpnpDispatcherEngine::UpdateDevicesL( TInt aUpdateId )
+ {
+ // checking if new list size is called.
+ if ( iDeviceGetState != EGetListSize )
+ {
+ if ( IsActive() )
+ {
+ return;
+ }
+
+ // setting information for message handler
+ // iSize contains information about last known
+ // update id. On return, it will contain also
+ // number of new devices and servises.
+
+ if( iSize.iUpdateId > iOldUpdateId )
+ {
+ iDeviceGetState = EGetList;
+ SetActive();
+ iStatus = KRequestPending;
+ TRequestStatus* stat = &iStatus;
+ User::RequestComplete( stat, KErrNone );
+ }
+ else
+ {
+ iSize.iUpdateId = aUpdateId;
+ iOldUpdateId = aUpdateId;
+
+ iStatus = KRequestPending;
+ // connection restoring
+ if(!iIsSessionOpen)
+ {
+ User::LeaveIfError( iSession.Connect() );
+ iIsSessionOpen = ETrue;
+ }
+
+ iSession.RequestGetDeviceListSize( iStatus, iSize );
+ if( !IsActive() )
+ {
+ SetActive();
+ }
+ iDeviceGetState = EGetList;
+ }
+ }
+ }
+
+// -----------------------------------------------------------------------------
+// CUpnpDispatcherEngine::GetDevicesL
+//
+// (other items were commented in a header).
+// -----------------------------------------------------------------------------
+//
+CUpnpDispatcherEngine::TDispatcherRequest CUpnpDispatcherEngine::GetDevicesL()
+ {
+ LOG_FUNC_NAME;
+
+ TDispatcherRequest status( ENewDevices );
+ if ( iDevs )
+ {
+ delete [] iDevs;
+ iDevs = NULL;
+ }
+
+ if ( iServs )
+ {
+ delete [] iServs;
+ iServs = NULL;
+ }
+
+ // checking if new devices or services has been found.
+ if ( iSize.iUpdateId > iOldUpdateId )
+ {
+ if( IsActive() )
+ {
+ Cancel();
+ }
+
+ // constructing buffers for getting the information
+ // for new devices and services.
+ // iDevs is an array, that will have number of
+ // devices as we have just received from Message Handler
+ // Same with iServs for services.
+
+ iDevs = new (ELeave) TUpnpDevice[iSize.iDeviceCount];
+ iServs = new (ELeave) TUpnpService[iSize.iServiceCount];
+
+ TPtr8 devPtr( reinterpret_cast<TUint8*>( iDevs ),
+ iSize.iDeviceCount*sizeof( TUpnpDevice ),
+ iSize.iDeviceCount*sizeof( TUpnpDevice ) );
+ TPtr8 servPtr( reinterpret_cast<TUint8*>( iServs ),
+ iSize.iServiceCount*sizeof( TUpnpService ),
+ iSize.iServiceCount*sizeof( TUpnpService ) );
+
+ // setting member pointers to point to strictures that will be
+ // filled with device and service information as call returns.
+ iGetDevPtr.Set(devPtr);
+ iGetServPtr.Set(servPtr);
+
+ // connection restoring
+ if(!iIsSessionOpen)
+ {
+ User::LeaveIfError( iSession.Connect() );
+ iIsSessionOpen = ETrue;
+ }
+
+ iStatus = KRequestPending;
+ iSession.RequestGetDeviceList( iStatus, iGetDevPtr, iGetServPtr );
+ if( !IsActive() )
+ {
+ SetActive();
+ }
+
+ status = ENewDevices;
+ }
+ else
+ {
+ // if no new devices, return the request for Message Handler,
+ // so it can complete message when there will be new devices.
+ UpdateDevicesL(iSize.iUpdateId);
+
+ status = EDeviceList;
+ }
+
+ return status;
+ }
+
+// -----------------------------------------------------------------------------
+// CUpnpDispatcherEngine::DevicesReceivedL
+// -----------------------------------------------------------------------------
+//
+TInt CUpnpDispatcherEngine::DevicesReceivedL()
+ {
+ if( iDevs && iServs)
+ {
+ TInt servIndex = 0;
+
+ // parsing data to devices and services.
+ for ( TInt i = 0; i < iSize.iDeviceCount; i++ )
+ {
+ RPointerArray<TUpnpService> currServs;
+ CleanupClosePushL( currServs );
+ for ( TInt j = 0; j < iDevs[i].iServiceCount; j++ )
+ {
+ currServs.Append( (const TUpnpService*)&iServs[servIndex+j] );
+ }
+ CleanupStack::Check(&currServs);
+ servIndex += iDevs[i].iServiceCount;
+
+ // creating CUpnpDevice objects from this information.
+
+ CUpnpDevice* device = CUpnpDevice::NewL( &iDevs[i], currServs );
+ CleanupStack::Check(&currServs);
+ device->SetAlive( iDevs[i].iAlive );
+ CleanupStack::Check(&currServs);
+ currServs.Reset();
+ CleanupStack::Pop( &currServs );
+
+ iNewDevices.Append( device );
+ }
+
+ delete[] iDevs;
+ iDevs = NULL;
+
+ delete[] iServs;
+ iServs = NULL;
+
+ iOldUpdateId = iSize.iUpdateId;
+
+ // inform CUpnpDispatcher that new devices and services has been found.
+ iObserver.DeviceListReceivedL(iOldUpdateId);
+ }
+ //The UpdateId should be passed back to the DispatcherEngine
+ //(Through Observer)
+ return iOldUpdateId;
+ }
+
+// -----------------------------------------------------------------------------
+// CUpnpDispatcherEngine::NewDevices
+// -----------------------------------------------------------------------------
+//
+const RPointerArray<CUpnpDevice>& CUpnpDispatcherEngine::NewDevices() const
+ {
+ return iNewDevices;
+ }
+
+// -----------------------------------------------------------------------------
+// CUpnpDispatcherEngine::RemoveDevices
+// -----------------------------------------------------------------------------
+//
+void CUpnpDispatcherEngine::RemoveDevices()
+ {
+ iNewDevices.ResetAndDestroy();
+ }
+
+// -----------------------------------------------------------------------------
+// CUpnpDispatcherEngine::AddLocalDeviceL
+// -----------------------------------------------------------------------------
+//
+void CUpnpDispatcherEngine::AddLocalDeviceL( const TDesC8& aUuid,
+ const TDesC8& aDeviceType,
+ const TDesC8& aDescriptionPath,
+ const CDesC8Array& aServices,
+ const TBool aIsRootDevice )
+ {
+ // checking if client is busy.
+ if ( iDeviceGetState != EOtherOperation &&
+ iDeviceGetState != EListReceived)
+ {
+ if ( IsActive() )
+ {
+ Cancel();
+ }
+
+ TBuf8<KPortBufferLength> port;
+ port.Num( HttpServerAddress().Port() );
+
+ _LIT8( KRootDevice, "r" );
+
+ TInt bufLen = aUuid.Length() +
+ aDeviceType.Length() +
+ aDescriptionPath.Length() +
+ port.Length() + KRootDevice().Length();
+
+ TInt i=0;
+ for ( i = 0; i < aServices.Count(); i++ )
+ {
+ bufLen += aServices[i].Length();
+ }
+
+ if(iAddLocalBuffer)
+ {
+ delete iAddLocalBuffer;
+ iAddLocalBuffer = NULL;
+ }
+
+ // creating a buffer that will hold information about device
+ // that is to be added.
+
+ iAddLocalBuffer = HBufC8::NewL( bufLen );
+ iAddLocalPtr.Set( iAddLocalBuffer->Des() );
+
+ // iAddLocalDevice is a struct, that will hold length of each
+ // data in the buffer. When we have length of each data and
+ // the data buffer, we can parse the data back to separate
+ // buffers on server side.
+
+ iAddLocalDevice.iUuidLength = aUuid.Length();
+ iAddLocalDevice.iDeviceTypeLength = aDeviceType.Length();
+ iAddLocalDevice.iDescriptionUrlLength = aDescriptionPath.Length();
+ iAddLocalDevice.iDomainLength = 0;
+ iAddLocalDevice.iPortNumberLength = port.Length();
+ iAddLocalDevice.iRootDeviceLength = 0;
+
+ iAddLocalPtr.Append( aUuid );
+ iAddLocalPtr.Append( aDeviceType );
+ iAddLocalPtr.Append( aDescriptionPath );
+ iAddLocalPtr.Append( port );
+
+ if ( aIsRootDevice )
+ {
+ iAddLocalPtr.Append( KRootDevice() );
+ iAddLocalDevice.iRootDeviceLength = KRootDevice().Length();
+ }
+
+ for ( i = 0; i < aServices.Count(); i++ )
+ {
+ iAddLocalDevice.iServiceLength[i] = aServices[i].Length();
+ iAddLocalPtr.Append( aServices[i] );
+ }
+
+ for ( ; i < KMaxServiceCount; i++ )
+ {
+ iAddLocalDevice.iServiceLength[i] = 0;
+ }
+
+ iAddLocalDevice.iBufferLength = iAddLocalPtr.Length();
+
+ // connection restoring
+ if(!iIsSessionOpen)
+ {
+ User::LeaveIfError( iSession.Connect() );
+ iIsSessionOpen = ETrue;
+ }
+
+ iStatus = KRequestPending;
+ iSession.RequestAddLocalDevice( iStatus, iAddLocalDevice,
+ iAddLocalPtr );
+ if( !IsActive() )
+ {
+ SetActive();
+ }
+
+ iDeviceGetState = EOtherOperation;
+ }
+ else
+ {
+ // if client is busy, making a request to request queue.
+ CUpnpDispatcherRequest* request = CUpnpDispatcherRequest::NewLC(
+ EAddLocalDevice );
+
+ request->AddArgumentL( aUuid );
+ request->AddArgumentL( aDeviceType );
+ request->AddArgumentL( aDescriptionPath );
+
+ _LIT8( KRootDevice, "r" );
+
+ if ( aIsRootDevice )
+ {
+ request->AddArgumentL( KRootDevice );
+ }
+ else
+ {
+ request->AddArgumentL( KNullDesC8 );
+ }
+
+ TInt granularity = aServices.Count();
+ if( 0 == granularity )
+ {
+ granularity = 1;
+ }
+ CDesC8ArrayFlat* array = new (ELeave) CDesC8ArrayFlat( granularity );
+
+ CleanupStack::PushL(array);
+
+ for ( TInt k = 0; k < aServices.Count(); k++ )
+ {
+ array->AppendL( aServices[k] );
+ }
+
+ CleanupStack::Pop(array);
+ request->AddServices(array);
+
+ CleanupStack::Pop(request);
+ iPendingRequests.Append(request);
+ }
+ }
+
+// -----------------------------------------------------------------------------
+// CUpnpDispatcherEngine::AddControlPointClientL
+// -----------------------------------------------------------------------------
+//
+void CUpnpDispatcherEngine::AddControlPointClientL()
+ {
+ // checking if client is busy.
+ if ( iDeviceGetState != EOtherOperation &&
+ iDeviceGetState != EListReceived )
+ {
+ if ( IsActive() )
+ {
+ Cancel();
+ }
+
+ // connection restoring
+ if ( !iIsSessionOpen )
+ {
+ User::LeaveIfError( iSession.Connect() );
+ iIsSessionOpen = ETrue;
+ }
+
+ iStatus = KRequestPending;
+ iSession.RequestAddControlPoint( iStatus );
+
+ if ( !IsActive() )
+ {
+ SetActive();
+ }
+ iDeviceGetState = EOtherOperation;
+ }
+ else
+ {
+ // client is busy, making a request and adding it to queue.
+ CUpnpDispatcherRequest* request =
+ CUpnpDispatcherRequest::NewLC( EAddControlPointClient );
+ iPendingRequests.AppendL( request );
+ CleanupStack::Pop( request );
+ }
+ }
+
+void CUpnpDispatcherEngine::RemoveControlPointClientL()
+ {
+ // checking if client is busy.
+ if ( iDeviceGetState != EOtherOperation &&
+ iDeviceGetState != EListReceived )
+ {
+ if ( IsActive() )
+ {
+ Cancel();
+ }
+
+ // connection restoring
+ if ( !iIsSessionOpen )
+ {
+ User::LeaveIfError( iSession.Connect() );
+ iIsSessionOpen = ETrue;
+ }
+
+ iStatus = KRequestPending;
+ iSession.RequestRemoveControlPoint( iStatus );
+
+ if ( !IsActive() )
+ {
+ SetActive();
+ }
+ iDeviceGetState = EOtherOperation;
+ }
+ else
+ {
+ // client is busy, making a request and adding it to queue.
+ CUpnpDispatcherRequest* request =
+ CUpnpDispatcherRequest::NewLC( ERemoveControlPointClient );
+ iPendingRequests.AppendL( request );
+ CleanupStack::Pop( request );
+ }
+ }
+
+// -----------------------------------------------------------------------------
+// CUpnpDispatcherEngine::SsdpSearchL
+//
+// (other items were commented in a header).
+// -----------------------------------------------------------------------------
+//
+void CUpnpDispatcherEngine::SsdpSearchL( const TDesC8& aString )
+ {
+ if(!iMXString)
+ {
+ TRAPD(err,iMXString = CUpnpSettings::GetMSearchConfigurationL());
+ if(err == KErrNotFound)
+ {
+ iMXString = KMSearchConfig().AllocL();
+ }
+ else
+ {
+ User::LeaveIfError(err);
+ }
+ }
+
+ if( aString.Length() <= 0 )
+ {
+ return;
+ }
+
+ // checking if client is busy.
+ if ( iDeviceGetState != EOtherOperation &&
+ iDeviceGetState != EListReceived )
+ {
+ if ( IsActive() )
+ {
+ Cancel();
+ }
+
+ if( iSearch )
+ {
+ delete iSearch;
+ iSearch = NULL;
+ }
+
+ iSearch = HBufC8::NewL( aString.Length() );
+ iSearch->Des().Zero();
+ iSearch->Des().Append( aString );
+ // connection restoring
+ if(!iIsSessionOpen)
+ {
+ User::LeaveIfError( iSession.Connect() );
+ iIsSessionOpen = ETrue;
+ }
+
+ iStatus = KRequestPending;
+ iSession.RequestSsdpSearch( iStatus, *iSearch, *iMXString );
+
+ if( !IsActive() )
+ {
+ SetActive();
+ }
+
+ iDeviceGetState = EOtherOperation;
+ }
+ else
+ {
+ // client is busy, making a request and adding it to queue.
+ CUpnpDispatcherRequest* request = CUpnpDispatcherRequest::NewLC( ESsdpSearch );
+
+ request->AddArgumentL( aString );
+
+ CleanupStack::Pop(request);
+ iPendingRequests.Append(request);
+ }
+ }
+
+// -----------------------------------------------------------------------------
+// CUpnpDispatcherEngine::SsdpStopFilteringL
+//
+// (other items were commented in a header).
+// -----------------------------------------------------------------------------
+//
+void CUpnpDispatcherEngine::SsdpStopFilteringL( const TDesC8& aString )
+ {
+ if( aString.Length() <= 0 )
+ {
+ return;
+ }
+ if( iUuids )
+ {
+ delete iUuids;
+ iUuids = NULL;
+ }
+ iUuids = HBufC8::NewL( aString.Length() );
+ iUuids->Des().Zero();
+ iUuids->Des().Append( aString );
+ // connection restoring
+ if(!iIsSessionOpen)
+ {
+ User::LeaveIfError( iSession.Connect() );
+ iIsSessionOpen = ETrue;
+ }
+ iSession.RequestStopFiltering( *iUuids );
+ }
+
+// -----------------------------------------------------------------------------
+// CUpnpDispatcherEngine::HttpEventLD
+// -----------------------------------------------------------------------------
+//
+void CUpnpDispatcherEngine::HttpEventLD( CUpnpHttpMessage* aMessage )
+ {
+ if( !aMessage )
+ {
+ return;
+ }
+ CleanupStack::PushL( aMessage );
+
+ HBufC8* customerPath = aMessage->ServicePath().AllocLC();
+ for ( TInt i = 0; i < iCustomers.Count(); i++ )
+ {
+ MUpnpDispatcherCustomer* customer = iCustomers[i];
+ if ( customerPath->CompareF( customer->Path() ) == 0 )
+ {
+ CleanupStack::PopAndDestroy(customerPath);
+ CleanupStack::Pop( aMessage );
+ customer->MessageReceivedLD( aMessage );
+ return;
+ }
+ }
+ CleanupStack::PopAndDestroy(customerPath);
+
+ if ( aMessage->Type() <= ETransferStart )
+ {
+ CUpnpHttpMessage* reply = RUpnpHttpMessageFactory::HttpResponseErrorL(
+ aMessage->Sender(), EHttpBadRequest );
+ CleanupStack::PushL( reply );
+ reply->SetSessionId( aMessage->SessionId() );
+ SendMessageL( reply );
+ CleanupStack::PopAndDestroy( reply );
+ }
+ CleanupStack::PopAndDestroy( aMessage );
+ }
+
+// -----------------------------------------------------------------------------
+// CUpnpDispatcherEngine::HttpServerAddressL
+// -----------------------------------------------------------------------------
+//
+TInetAddr CUpnpDispatcherEngine::HttpServerAddress()
+ {
+ TInetAddr addr;
+ iHttpServerSession->GetAddress( addr );
+ return addr;
+ }
+
+// CUpnpDispatcherEngine::RemoveLocalDeviceL
+// -----------------------------------------------------------------------------
+//
+void CUpnpDispatcherEngine::RemoveLocalDeviceL( const TDesC8& aUuid, TBool aSilent )
+ {
+ // checking if client is busy.
+ if ( iDeviceGetState != EOtherOperation &&
+ iDeviceGetState != EListReceived )
+ {
+ if ( IsActive() )
+ {
+ Cancel();
+ }
+
+ if(iRemoveUuid)
+ {
+ delete iRemoveUuid;
+ iRemoveUuid = NULL;
+ }
+
+ iRemoveUuid = aUuid.AllocL();
+ iRemoveUuidPtr.Set(iRemoveUuid->Des());
+
+ // connection restoring
+ if(!iIsSessionOpen)
+ {
+ User::LeaveIfError( iSession.Connect() );
+ iIsSessionOpen = ETrue;
+ }
+
+ iStatus = KRequestPending;
+
+ if (!aSilent)
+ {
+ iSession.RequestRemoveLocalDevice( iStatus, iRemoveUuidPtr );
+ }
+ else
+ {
+ iSession.RequestRemoveSilentLocalDevice( iStatus, iRemoveUuidPtr );
+ }
+ iDeviceGetState = EOtherOperation;
+
+ if( !IsActive() )
+ {
+ SetActive();
+ }
+ }
+ else
+ {
+ // client is busy, making a request and adding it to queue.
+ CUpnpDispatcherRequest* request = CUpnpDispatcherRequest::NewLC(
+ ERemoveLocalDevice );
+
+ request->AddArgumentL( aUuid );
+
+ // we need to store information if the removal should be silent
+ if ( aSilent )
+ {
+ request->AddArgumentL( KNullDesC8 );
+ }
+
+ CleanupStack::Pop(request);
+ iPendingRequests.Append(request);
+ }
+ }
+
+// -----------------------------------------------------------------------------
+// CUpnpDispatcherEngine::MacAddressL
+// -----------------------------------------------------------------------------
+//
+const HBufC8* CUpnpDispatcherEngine::MacAddressL()
+ {
+ TSockAddr* addr;
+ addr = iHttpServerSession->HWAddressL();
+ CleanupStack::PushL( addr);
+ TInt i = 0;
+ HBufC8* hwAddr = NULL;
+ hwAddr = HBufC8::NewL( 2 * addr->GetUserLen() );
+ hwAddr->Des().Zero();
+
+ for ( i = sizeof(SSockAddr); i < sizeof(SSockAddr) + addr->GetUserLen(); i++ )
+ {
+ hwAddr->Des().AppendNumFixedWidth((*addr)[i], EHex, 2);
+ }
+
+ CleanupStack::PopAndDestroy( addr);
+
+ hwAddr->Des().UpperCase();
+
+ return hwAddr;
+ }
+
+// -----------------------------------------------------------------------------
+// CUpnpDispatcherEngine::RunL
+// -----------------------------------------------------------------------------
+//
+void CUpnpDispatcherEngine::RunL()
+ {
+ if ( iStatus.Int() == KErrServerTerminated || iStatus.Int() == KErrCancel )
+ {
+ LOGS("CUpnpDispatcherEngine::RunL, Server terminated or canceled, trying to restart");
+ iSession.Close();
+ iIsSessionOpen = EFalse;
+ return;
+ }
+
+ switch( iDeviceGetState )
+ {
+ case EOtherOperation:
+ if ( iPendingRequests.Count() > 0 )
+ {
+ HandlePendingRequestL();
+ }
+ else
+ {
+ UpdateDevicesL(iOldUpdateId);
+ }
+ break;
+ case EGetListSize:
+ UpdateDevicesL(iOldUpdateId);
+ break;
+ case EGetList:
+ if( GetDevicesL() == EDeviceList)
+ {
+ iDeviceGetState = EGetList;
+ }
+ else
+ {
+ iDeviceGetState = EListReceived;
+ }
+
+ break;
+ case EListReceived:
+ if( iSize.iUpdateId >= iOldUpdateId )
+ {
+ DevicesReceivedL();
+ }
+ if( iPendingRequests.Count() > 0 && !IsActive())
+ {
+ iDeviceGetState = EOtherOperation;
+ //Re-execute RunL to launch HandlePendingRequest
+ SetActive();
+ iStatus = KRequestPending;
+ TRequestStatus* stat = &iStatus;
+ User::RequestComplete( stat, KErrNone );
+ break;
+ }
+ UpdateDevicesL(iOldUpdateId);
+
+ break;
+ default: //NoOperation
+ break;
+ }
+ }
+
+// -----------------------------------------------------------------------------
+// CUpnpDispatcherEngine::RunError
+// RunError in case RunL leaves.
+// -----------------------------------------------------------------------------
+//
+TInt CUpnpDispatcherEngine::RunError( TInt /*aError*/ )
+ {
+ return KErrNone;
+ }
+
+// -----------------------------------------------------------------------------
+// CUpnpDispatcherEngine::DoCancel
+// -----------------------------------------------------------------------------
+//
+void CUpnpDispatcherEngine::DoCancel()
+ {
+ TRAP_IGNORE( StopRequestL() );
+
+ if(iDevs)
+ {
+ delete [] iDevs;
+ iDevs = NULL;
+ }
+ if(iServs)
+ {
+ delete [] iServs;
+ iServs = NULL;
+ }
+
+ iDeviceGetState = ENoOperation;
+ }
+
+// -----------------------------------------------------------------------------
+// CUpnpDispatcherEngine::HandlePendingRequestL
+// -----------------------------------------------------------------------------
+//
+void CUpnpDispatcherEngine::HandlePendingRequestL()
+ {
+ ASSERT( iPendingRequests.Count() > 0 );
+ RemoveHandledRequest();
+ iActiveRequest = iPendingRequests[0];
+ CDesC8ArrayFlat& arguments = iActiveRequest->Arguments();
+ switch( iActiveRequest->Request() )
+ {
+ case EAddLocalDevice:
+ {
+ if( iDeviceGetState == EOtherOperation )
+ {
+ iDeviceGetState = ENoOperation;
+ }
+
+ if ( arguments[3].Length() > 0 )
+ {
+ AddLocalDeviceL(
+ arguments[0],
+ arguments[1],
+ arguments[2],
+ iActiveRequest->Services(),
+ ETrue );
+ }
+ else
+ {
+ AddLocalDeviceL(
+ arguments[0],
+ arguments[1],
+ arguments[2],
+ iActiveRequest->Services(),
+ EFalse );
+ }
+
+ }
+ break;
+
+ case ERemoveLocalDevice:
+ {
+
+ if( iDeviceGetState == EOtherOperation )
+ {
+ iDeviceGetState = ENoOperation;
+ }
+
+ // the presence of 2nd argument means the removal should be silent
+ TBool silent = EFalse;
+ if ( arguments.Count() == 2 )
+ {
+ silent = ETrue;
+ }
+ RemoveLocalDeviceL( arguments[0], silent );
+ }
+ break;
+
+ case EAddControlPointClient:
+ {
+ if( iDeviceGetState == EOtherOperation )
+ {
+ iDeviceGetState = ENoOperation;
+ }
+ AddControlPointClientL();
+ }
+ break;
+
+ case ERemoveControlPointClient:
+ {
+ if( iDeviceGetState == EOtherOperation )
+ {
+ iDeviceGetState = ENoOperation;
+ }
+
+ RemoveControlPointClientL();
+ }
+ break;
+
+ case ESsdpSearch:
+ {
+
+ if( iDeviceGetState == EOtherOperation )
+ {
+ iDeviceGetState = ENoOperation;
+ }
+
+ SsdpSearchL( arguments[0] );
+
+ }
+ default:
+ break;
+ }
+ iPendingRequests.Remove( 0 );
+ iPendingRequests.Compress();
+ iDeviceGetState = EOtherOperation;
+ }
+
+// -----------------------------------------------------------------------------
+// CUpnpDispatcherEngine::RemoveHandledRequest
+// -----------------------------------------------------------------------------
+//
+TInt CUpnpDispatcherEngine::RemoveHandledRequest()
+ {
+ if(iActiveRequest)
+ {
+ // If last message was ssdp search, now it is safe
+ // to delete iSearch also.
+ if( iActiveRequest->Request() == ESsdpSearch )
+ {
+ if( iSearch )
+ {
+ delete iSearch;
+ iSearch = NULL;
+ }
+ }
+ delete iActiveRequest;
+ iActiveRequest = NULL;
+ return KErrNone;
+ }
+ return KErrNotFound;
+ }
+
+// -----------------------------------------------------------------------------
+// CUpnpDispatcherEngine::StopRequestL
+// -----------------------------------------------------------------------------
+//
+void CUpnpDispatcherEngine::StopRequestL()
+ {
+ //LOGSH( iHandle, "Disp Request Cancelled");
+
+ if( iDeviceGetState == EGetList )
+ {
+ // connection restoring
+ if(!iIsSessionOpen)
+ {
+ User::LeaveIfError( iSession.Connect() );
+ iIsSessionOpen = ETrue;
+ }
+
+ iDeviceGetState = ENoOperation;
+ iSession.RequestStop();
+ }
+ }
+
+// -----------------------------------------------------------------------------
+// CUpnpDispatcherEngine::SetTransactionCreator
+// -----------------------------------------------------------------------------
+//
+void CUpnpDispatcherEngine::SetTransactionCreator(
+ MUpnpHttpServerTransactionCreator* aTransactionCreator )
+ {
+ iHttpServerSession->DefaultRuntime().SetCreator( *aTransactionCreator );
+ }
+
+// -----------------------------------------------------------------------------
+// CUpnpDispatcher::StartHttpServerL
+// -----------------------------------------------------------------------------
+//
+void CUpnpDispatcherEngine::StartHttpServerL( TBool aRegister , const TInt aPort )
+ {
+ iHttpServerSession->StartL( aPort );
+ CheckErrorL( aRegister );
+ }
+
+// -----------------------------------------------------------------------------
+// CUpnpDispatcher::CheckErrorL
+// -----------------------------------------------------------------------------
+//
+void CUpnpDispatcherEngine::CheckErrorL( TBool /*aRegister*/ )
+ {
+ TInt error = KErrNone;
+ iSession.RequestCheckError(error);
+ User::LeaveIfError(error);
+ }
+
+// -----------------------------------------------------------------------------
+// CUpnpDispatcher::StopHttpServer
+// -----------------------------------------------------------------------------
+//
+void CUpnpDispatcherEngine::StopHttpServer()
+ {
+ iHttpServerSession->Stop();
+ }
+
+// End of File