diff -r 000000000000 -r f5a58ecadc66 upnp/upnpstack/serviceframework/src/upnpdispatcherengine.cpp --- /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( iDevs ), + iSize.iDeviceCount*sizeof( TUpnpDevice ), + iSize.iDeviceCount*sizeof( TUpnpDevice ) ); + TPtr8 servPtr( reinterpret_cast( 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 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& 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 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