diff -r 000000000000 -r f5a58ecadc66 upnp/upnpstack/controlpointbase/src/upnpcontrolpoint.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/upnp/upnpstack/controlpointbase/src/upnpcontrolpoint.cpp Tue Feb 02 01:12:20 2010 +0200 @@ -0,0 +1,1276 @@ +/** @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: Declares ControlPoint class. + * +*/ + + +// INCLUDE FILES + +#include +#include +#include +#include +#include +#include + +#include "upnpdispatcher.h" +#include "upnphttpmessage.h" +#include "upnpsoapmessage.h" +#include "upnpicon.h" +#include "upnpdevice.h" +#include "upnpstring.h" +#include "upnphttpmessagefactory.h" +#include "upnpsoapmessagefactory.h" +#include "upnpgenamessagefactory.h" +#include "upnpserviceinfo.h" +#include "upnpcontrolpoint.h" +#include "upnpcommonupnplits.h" +#include "upnpcons.h" +#include "upnpcpbhttpmessagecontroller.h" +#include "upnpcpbcurrenthttpclient.h" +#include "upnpcpbdescriptionagent.h" +#include "upnpcpbdiscoveryagent.h" +#include "upnpcpbdevicerepository.h" +#include "upnpcpstackrequestor.h" +#include "upnpcontenthandlerscontroller.h" +#include "upnpconnectionmanagernetworkeventprovider.h" +#include "upnpcpbinitialeventretryhandler.h" + +#define KLogFile _L("UPnPCP.txt") +#include "upnpcustomlog.h" + +using namespace UpnpHTTP; + +static const TInt KDTargetDeviceTypesGranularity = 1; + +// ============================ MEMBER FUNCTIONS =============================== + +// ----------------------------------------------------------------------------- +// CUpnpControlPoint::CUpnpControlPoint +// C++ default constructor +// ----------------------------------------------------------------------------- +// +EXPORT_C CUpnpControlPoint::CUpnpControlPoint() + : iPredefinedStackRequestor( NULL ), iPredefinedHttpRequestor( NULL ) + { + } + +// ----------------------------------------------------------------------------- +// CUpnpControlPoint::CUpnpControlPoint +// C++ constructor for internal, automated test cases use +// ----------------------------------------------------------------------------- +// +EXPORT_C CUpnpControlPoint::CUpnpControlPoint( + MUpnpCpStackRequestor& aStackRequestor, MUpnpCpHttpRequestor& aHttpRequestor ) + : iPredefinedStackRequestor( &aStackRequestor ), + iPredefinedHttpRequestor( &aHttpRequestor ) + { + } + +// ----------------------------------------------------------------------------- +// CUpnpControlPoint::~CUpnpControlPoint +// C++ default destructor +// ----------------------------------------------------------------------------- +// +EXPORT_C CUpnpControlPoint::~CUpnpControlPoint() + { + LOG_FUNC_NAME; + + delete iCpbHttpClient; + + iSubscribedServicesInfos.ResetAndDestroy(); + iActionList.ResetAndDestroy(); + + if ( iTargetDeviceTypes ) + { + iTargetDeviceTypes->Reset(); + delete iTargetDeviceTypes; + } + + delete iDescriptionAgent; + delete iDiscoveryAgent; + + delete iNetworkEventProvider; + + delete iSaxController; + delete iDeviceRepository; + delete iInitialEventRetry; + LOGS("CUpnpControlPoint::~CUpnpControlPoint - END"); + } + +// ----------------------------------------------------------------------------- +// CUpnpControlPoint::ConstructL +// Two-phased constructor +// ----------------------------------------------------------------------------- +// +EXPORT_C void CUpnpControlPoint::ConstructL( const CDesC8Array& aTargetDeviceTypes ) + { + iNetworkEventProvider = CUpnpConnectionManagerNetworkEventProvider::NewL( *this ); + + iCpbHttpClient = + CUpnpCpbCurrentHttpClient::NewL( + *this, iPredefinedHttpRequestor, iPredefinedStackRequestor ); + iTargetDeviceTypes = new( ELeave ) CDesC8ArrayFlat( KDTargetDeviceTypesGranularity ); + + for ( TInt i( 0 ); i < aTargetDeviceTypes.Count(); i++ ) + { + iTargetDeviceTypes->AppendL( aTargetDeviceTypes[i]); + } + iDeviceRepository = CUpnpCpbDeviceRepository::NewL(*iTargetDeviceTypes); + + iSaxController = CUpnpContentHandlersController::NewL(); + iDiscoveryAgent = CUpnpCpbDiscoveryAgent::NewL( *iCpbHttpClient ); + iDescriptionAgent = + CUpnpCpbDescriptionAgent::NewL( + *this, *iCpbHttpClient, *iDeviceRepository ); + + iInitialEventRetry = new( ELeave ) CUpnpCpbInitialEventRetryHandler( *this ); + + } + +// ----------------------------------------------------------------------------- +// CUpnpControlPoint::ConstructL +// Two-phased constructor +// ----------------------------------------------------------------------------- +// +EXPORT_C void CUpnpControlPoint::ConstructL( const TDesC8& aTargetDeviceType ) + { + CDesC8ArrayFlat* targetDeviceTypes = + new (ELeave) CDesC8ArrayFlat( KDTargetDeviceTypesGranularity ); + CleanupStack::PushL( targetDeviceTypes ); + targetDeviceTypes->AppendL( aTargetDeviceType ); + ConstructL( *targetDeviceTypes ); + CleanupStack::PopAndDestroy( targetDeviceTypes ); + } + +// ----------------------------------------------------------------------------- +// CUpnpControlPoint::SearchL +// Search intresting Device Types from network +// ----------------------------------------------------------------------------- +// +EXPORT_C void CUpnpControlPoint::SearchL( const TDesC8& aSearchString ) + { + if( aSearchString.Length() == 0 ) + { + User::Leave( KErrCorrupt ); + } + iDiscoveryAgent->SearchL( aSearchString ); + } + +// ----------------------------------------------------------------------------- +// CUpnpControlPoint::SendL +// Send an action message. +// ----------------------------------------------------------------------------- +// +EXPORT_C void CUpnpControlPoint::SendL( CUpnpAction* aAction ) + { + iCpbHttpClient->SendActionL( aAction ); + iActionList.AppendL( aAction ); + } + +// ----------------------------------------------------------------------------- +// CUpnpControlPoint::SendL +// Send HTTP message +// ----------------------------------------------------------------------------- +// +EXPORT_C void CUpnpControlPoint::SendL( CUpnpHttpMessage* aHttpMessage ) + { + iCpbHttpClient->SendFileByPostL(aHttpMessage); + } + +// ----------------------------------------------------------------------------- +// CUpnpControlPoint::SendResponseMessageLD +// Send HTTP message and destroy it (leave safe) +// ----------------------------------------------------------------------------- +// +void CUpnpControlPoint::SendResponseMessageLD( CUpnpHttpMessage* aHttpMessage ) + { + CleanupStack::PushL( aHttpMessage ); + iCpbHttpClient->SendL( aHttpMessage ); + CleanupStack::PopAndDestroy( aHttpMessage ); + } + +// ----------------------------------------------------------------------------- +// CUpnpControlPoint::DeviceList +// +// ----------------------------------------------------------------------------- +// +EXPORT_C const RPointerArray& CUpnpControlPoint::DeviceList() const + { + return iDeviceRepository->DiscoveredDeviceList(); + } + +// ----------------------------------------------------------------------------- +// CUpnpControlPoint::SubscribeL +// +// ----------------------------------------------------------------------------- +// +EXPORT_C void CUpnpControlPoint::SubscribeL( CUpnpService* aService ) + { + LOG_FUNC_NAME; + + if ( !aService ) + { + return; + } + + if( FindServiceInfoByService( aService ) ) + { + return; + } + + LOGS("CUpnpControlPoint::SubscribeL - Subscribing service"); + + CUpnpServiceInfo* serviceInfo = CUpnpServiceInfo::NewLC( this, aService ); + iSubscribedServicesInfos.AppendL( serviceInfo ); + CleanupStack::Pop( serviceInfo ); + + iCpbHttpClient->SendSubscribeL( serviceInfo ); + + LOGS("CUpnpControlPoint::SubscribeL - end"); + + } + +// ----------------------------------------------------------------------------- +// CUpnpControlPoint::UnsubscribeL +// +// ----------------------------------------------------------------------------- +// +EXPORT_C void CUpnpControlPoint::UnsubscribeL( const CUpnpService* aService ) + { + UnsubscribeL( const_cast( aService ) , ETrue ); + } + +// ----------------------------------------------------------------------------- +// CUpnpControlPoint::UnsubscribeL +// +// ----------------------------------------------------------------------------- +// +void CUpnpControlPoint::UnsubscribeL( CUpnpService* aService, + TBool aSendUnsubscribeMessage ) + { + LOG_FUNC_NAME; + + if ( !aService ) + { + return; + } + + CUpnpServiceInfo* subscribedServiceInfo = + FindServiceInfoByService( aService ); + if ( !subscribedServiceInfo ) + { + return; + } + + LOGS("CUpnpControlPoint::UnsubscribeL - Unsubscribing service"); + + RemoveFromSubscribedList( subscribedServiceInfo ); + + if ( aSendUnsubscribeMessage ) + { + CleanupStack::PushL( subscribedServiceInfo ); + iCpbHttpClient->SendUnsubscribeL( subscribedServiceInfo ); + CleanupStack::Pop( subscribedServiceInfo ); + } + + delete subscribedServiceInfo; + + LOGS("CUpnpControlPoint::UnsubscribeL - end"); + } + +// ----------------------------------------------------------------------------- +// CUpnpControlPoint::ResubscribeL +// +// ----------------------------------------------------------------------------- +// +void CUpnpControlPoint::ResubscribeL( CUpnpServiceInfo* aServiceInfo ) + { + iCpbHttpClient->SendResubscribeL( aServiceInfo ); + } + +// ----------------------------------------------------------------------------- +// CUpnpControlPoint::RemoveFromSubscribedList +// +// ----------------------------------------------------------------------------- +// +void CUpnpControlPoint::RemoveFromSubscribedList( + CUpnpServiceInfo* aServiceInfoToRemove ) + { + const TInt idx = iSubscribedServicesInfos.Find( aServiceInfoToRemove ); + if ( KErrNotFound != idx ) + { + iSubscribedServicesInfos.Remove( idx ); + } + iSubscribedServicesInfos.GranularCompress(); + } + +// ----------------------------------------------------------------------------- +// CUpnpControlPoint::DeviceFoundL +// +// ----------------------------------------------------------------------------- +// +EXPORT_C void CUpnpControlPoint::DeviceFoundL( CUpnpDevice& aDevice ) + { + iDescriptionAgent->DeviceAliveNotificationL(&aDevice); + } + +// ----------------------------------------------------------------------------- +// CUpnpControlPoint::DeviceLostL +// Callback function - remove device +// ----------------------------------------------------------------------------- +// +EXPORT_C void CUpnpControlPoint::DeviceLostL( CUpnpDevice& aDevice ) + { + LOG_FUNC_NAME; + + //device from ssdp + CUpnpDevice* ssdpDevice = + iDeviceRepository->RemoveIncomingDevice( aDevice.Uuid() ); + if ( ssdpDevice ) + { + delete ssdpDevice; + } + CUpnpDevice* device = NULL; + + device = iDeviceRepository->FindDevice( aDevice.Uuid() ); + + if ( !device ) + { + return; + } + + if ( aDevice.Expired() ) + { + device->SetExpired( ETrue ); + if ( !AllDevicesExpired( device ) ) + { + return; + } + } + + // always remove whole device tree + if ( device->IsEmbeddDevice() ) + { + CUpnpDevice* rootDevice = iDeviceRepository->FindRoot( device->Uuid() ); + // In case of error when root device is not found during discovery + if ( rootDevice ) + { + device = rootDevice; + } + } + + RemoveRootDeviceLD( device ); + } + +// ----------------------------------------------------------------------------- +// CUpnpControlPoint::AllDevicesExpired +// +// ----------------------------------------------------------------------------- +// +TBool CUpnpControlPoint::AllDevicesExpired( CUpnpDevice* aDevice ) + { + // notification about expiration of cache-control time of aDevice + if ( aDevice->IsEmbeddDevice() ) // take root device + { + aDevice = iDeviceRepository->FindRoot( aDevice->Uuid() ); + } + // if root device not expired then return + if ( !aDevice || !aDevice->Expired() ) + { + return EFalse; + } + RPointerArray devices; + aDevice->GetAllDevices( devices ); // take all embedded devices + for ( TInt k = 0; k < devices.Count(); k++ ) + { + // if not all embedded devices expired then return + if ( !devices[k]->Expired() ) + { + devices.Close(); + return EFalse; + } + } + devices.Close(); + return ETrue; + } + +// ----------------------------------------------------------------------------- +// CUpnpControlPoint::Path +// +// ----------------------------------------------------------------------------- +// +EXPORT_C const TDesC8& CUpnpControlPoint::Path() + { + return KPath(); + } + +// ----------------------------------------------------------------------------- +// CUpnpControlPoint::MessageReceived +// Callback funtion - HTTP message received +// ----------------------------------------------------------------------------- +// +void CUpnpControlPoint::MessageReceived( CUpnpHttpMessage* aHttpMessage ) + { + HttpResponseReceived( aHttpMessage ); + } + +// ----------------------------------------------------------------------------- +// CUpnpControlPoint::MapHttpError +// +// ----------------------------------------------------------------------------- +// +TInt CUpnpControlPoint::MapHttpError( TInt aError ) + { + if ( aError >= EHttpBadRequest && aError < EHttpInternalServerError ) + { + return KErrCouldNotConnect; + } + else if ( aError > EHttpInternalServerError ) + { + return KErrServerBusy; + } + else + { + return KErrUnknown; + } + + } + +// ----------------------------------------------------------------------------- +// CUpnpControlPoint::CheckEventKey +// +// ----------------------------------------------------------------------------- +// +TInt CUpnpControlPoint::CheckEventKey( const TDesC8& aIncomingSeq, + TUint32 aExistingSeq ) + { + const TUint KMaxSeq = 2146583647; + const TUint KMinSeq = 1; + + TUint IncomingSeq; + TInt error = KErrNone; + + TLex8 lex(aIncomingSeq); + lex.Mark(); + error = lex.Val( IncomingSeq ); + + //--- check if SEQ is a number + if ( !error ) + { + lex.UnGetToMark(); + + for ( TInt i(0); i < aIncomingSeq.Length(); i++ ) + { + TChar character = lex.Get(); + if ( !(character.IsDigit() ) ) + { + error = KErrGeneral; + break; + } + } + } + + //--- check SEQ incrementing/wrapping + if ( !error ) + { + // when initial event appears, don't check SEQ increment + if ( (IncomingSeq == 0 ) && (aExistingSeq == 0 ) ) + return KErrNone; + + if ( aExistingSeq < KMaxSeq ) + { + aExistingSeq++; + } + else + { + aExistingSeq = KMinSeq; + } + + // if 'incoming SEQ' == 'incremented existing SEQ' -> OK + if ( IncomingSeq == aExistingSeq ) + { + error = KErrNone; + } + else + { + error = KErrCancel; + } + } + + return error; + } + +// ----------------------------------------------------------------------------- +// CUpnpControlPoint::ThrowErrorL +// +// ----------------------------------------------------------------------------- +// +void CUpnpControlPoint::SendErrorResponseL( CUpnpHttpMessage* aHttpMessage, + THttpStatusCode aCode ) + { + CUpnpHttpMessage* msg = RUpnpHttpMessageFactory::HttpResponseErrorL( + aHttpMessage, aCode ); + SendResponseMessageLD( msg ); + } + +// ----------------------------------------------------------------------------- +// CUpnpControlPoint::SubscriptionResponseReceivedL +// +// ----------------------------------------------------------------------------- +// +void CUpnpControlPoint::SubscriptionResponseReceivedL( + CUpnpHttpMessage& aHttpMessage ) + { + LOG_FUNC_NAME; + CUpnpGenaMessage* genaMsg = + reinterpret_cast ( &aHttpMessage ); + + CUpnpServiceInfo* tmpServiceInfo = FindServiceInfoByGenaMessage( genaMsg ); + if ( !tmpServiceInfo ) + { + return; + } + + tmpServiceInfo->SetSidL( genaMsg->Sid() ); + tmpServiceInfo->StartTimerL( genaMsg->Timeout() ); + if(iDeviceRepository->MatchTargetDevice(_L8("*"))) + { + aHttpMessage.SetType(ESubscription); + aHttpMessage.SetDestinationPathL(tmpServiceInfo->Service()->SubscriptionUrl()); + TRAP_IGNORE( HttpResponseReceivedL( &aHttpMessage ) ); + } + + LOGS("CUpnpControlPoint::SubscRespRcvdL - end"); + } + +// ----------------------------------------------------------------------------- +// CUpnpControlPoint::HandlePostponedInitialEventL +// +// ----------------------------------------------------------------------------- +// +void CUpnpControlPoint::HandlePostponedInitialEventL( CUpnpGenaMessage& aGenaMsg ) + { + CUpnpServiceInfo* serviceInfo = FindServiceInfoBySid( + iSubscribedServicesInfos, aGenaMsg.Sid() ); + if ( serviceInfo ) + { + if(iDeviceRepository->MatchTargetDevice(_L8("*"))) + { + aGenaMsg.SetDestinationPathL(serviceInfo->Service()->SubscriptionUrl()); + TRAP_IGNORE( HttpResponseReceivedL( &aGenaMsg) ); + } + ParseEventUpdateStateVariablesL( aGenaMsg, *serviceInfo ); + SendResponseMessageLD( RUpnpHttpMessageFactory::HttpResponseOkL( + &aGenaMsg ) ); + } + else + { + SendErrorResponseL( &aGenaMsg, EHttpPreconditionFailed ); + } + } + +// ----------------------------------------------------------------------------- +// CUpnpControlPoint::UnSubscriptionResponseReceived +// +// ----------------------------------------------------------------------------- +// +void CUpnpControlPoint::UnSubscriptionResponseReceived() + { + LOG_FUNC_NAME; + } + +// ----------------------------------------------------------------------------- +// CUpnpControlPoint::NotifyReceivedL +// +// ----------------------------------------------------------------------------- +// +void CUpnpControlPoint::NotifyReceivedL( CUpnpHttpMessage& aHttpMessage ) + { + LOGS( "CUpnpControlPoint::NotifyReceivedL - start" ); + CUpnpGenaMessage* genaMsg = + reinterpret_cast ( &aHttpMessage ); + CleanupStack::PushL(genaMsg); + + THttpStatusCode code = ValidateEventResolveHttpResponseCode( *genaMsg ); + if ( code != EHttp200Ok ) + { + //--- If some of conditions are not fulfilled, send error + SendErrorResponseL(genaMsg, code); + CleanupStack::PopAndDestroy(genaMsg); + LOGS( "CUpnpControlPoint::NotifyReceivedL - end" ); + return; + } + //--- checking if genaMsg SID is the same like the one in subscribed service. + CUpnpServiceInfo* subscribedServiceInfo = FindServiceInfoBySid( + iSubscribedServicesInfos, genaMsg->Sid()); + + if ( subscribedServiceInfo ) + { + //===== Checking validity of SEQ header + TInt seqError = KErrNone; + seqError = CheckEventKey( genaMsg->Seq(), subscribedServiceInfo->Seq() ); + if ( seqError ) + { + if ( seqError == KErrCancel ) + { + //------ if SEQ's order invalid + //-> e.g 0,1,2 and then 1 -> Unsubscribe/Subscribe + ResubscribeL( *subscribedServiceInfo ); + } + else + { + LOGS( "CUpnpControlPoint::NotifyReceivedL - SEQ INAVLID" ); + SendErrorResponseL( genaMsg, EHttpBadRequest ); + User::Leave(seqError); + } + } + else + { + if(iDeviceRepository->MatchTargetDevice(_L8("*"))) + { + genaMsg->SetDestinationPathL(subscribedServiceInfo->Service()->SubscriptionUrl()); + TRAP_IGNORE( HttpResponseReceivedL( genaMsg) ); + } + ParseEventUpdateStateVariablesL( *genaMsg, *subscribedServiceInfo ); + SendResponseMessageLD(RUpnpHttpMessageFactory::HttpResponseOkL( genaMsg )); + LOGS( "CUpnpControlPoint::NotifyReceivedL - send OK" ); + } + CleanupStack::PopAndDestroy( genaMsg ); + + } + else + { + TInt seq; + TLex8 lex( genaMsg->Seq() ); + TInt error = lex.Val(seq); + + if ( !error && seq == 0 ) + { + CleanupStack::Pop( genaMsg ); + //ownership is passed through + iInitialEventRetry->AddL( genaMsg ); + } + else + { + SendErrorResponseL( genaMsg, EHttpPreconditionFailed ); + CleanupStack::PopAndDestroy( genaMsg ); + } + } + + } + + +// ----------------------------------------------------------------------------- +// CUpnpControlPoint::Device +// This function returns a pointer to device identified by UUID. +// (other items were commented in a header).es +// ----------------------------------------------------------------------------- +// +CUpnpServiceInfo* CUpnpControlPoint::FindServiceInfoBySid( RPointerArray& aInfos, + const TDesC8& aSid ) + { + for ( TInt i=0; i < aInfos.Count(); i++ ) + { + CUpnpServiceInfo* subscribedServiceInfo = aInfos[i]; + if ( (subscribedServiceInfo->Sid().Length()> 0 ) + && (subscribedServiceInfo->Sid() == aSid ) ) + { + return subscribedServiceInfo; + } + } + return NULL; + } + +// ----------------------------------------------------------------------------- +// CUpnpControlPoint::ResubscribeL +// +// ----------------------------------------------------------------------------- +// +void CUpnpControlPoint::ResubscribeL( CUpnpServiceInfo& aInfo ) + { + //------ if SEQ's order invalid + //-> e.g 0,1,2 and then 1 -> Unsubscribe/Subscribe + CUpnpService* service = + aInfo.Service(); // remember the service + + UnsubscribeL( service ); + // after unsubscribing -> subscribe again + SubscribeL( service ); + + } + +// ----------------------------------------------------------------------------- +// CUpnpControlPoint::ParseEventUpdateStateVariablesL +// +// ----------------------------------------------------------------------------- +// +void CUpnpControlPoint::ParseEventUpdateStateVariablesL( + CUpnpGenaMessage& aGenaMsg, CUpnpServiceInfo& aInfo ) + { + TInt parsingError = KErrNone; + TRAP( parsingError, iSaxController->AttachL( + aGenaMsg.Body(), *( aInfo.Service() ) ) ); + if ( parsingError ) + { + LOGS( "CUpnpControlPoint::NotifyReceivedL - " + "parsing gena or parsing SEQ - FAILED" ); + SendErrorResponseL( &aGenaMsg, EHttpBadRequest ); + User::Leave( parsingError ); + } + + // if SEQ ok -> put the value to the service + TInt seq; + TLex8 lex( aGenaMsg.Seq() ); + TInt error = lex.Val( seq ); + // error ignored, it is fully checked in CheckEventKey() + + aInfo.SetSeq( seq ); + StateUpdated( aInfo.Service() ); + + } + + // ----------------------------------------------------------------------------- +// CUpnpControlPoint::ValidateEventResolveHttpResponseCode +// +// ----------------------------------------------------------------------------- +// +THttpStatusCode CUpnpControlPoint::ValidateEventResolveHttpResponseCode( + CUpnpGenaMessage& aGenaMsg ) + + { + THttpStatusCode code = EHttp200Ok; + //--- NOTIFY message syntax - checking if headers: NT and NTS exists + + if ( aGenaMsg.Method() != UpnpGENA::KGenaNotify() + || aGenaMsg.Nt() == KNoHeader + || aGenaMsg.Nts() == KNoHeader ) + { + // headers NT or NTS are missing + code = EHttpBadRequest; + LOGS( "CUpnpControlPoint::NotifyReceivedL - bad request" ); + } + + //--- NOTIFY message syntax + //- checking if headers: NT and NTS has proper structure [name: value] + else if (aGenaMsg.Nt() != UpnpGENA::KDefaultNt || aGenaMsg.Nts() + != UpnpGENA::KDefaultNts) + { + // headers NT or NTS are invalid + code = EHttpPreconditionFailed; + LOGS( "CUpnpControlPoint::NotifyReceivedL - headers NT or NTS are invalid" ); + } + return code; + } + + +// ----------------------------------------------------------------------------- +// CUpnpControlPoint::Device +// This function returns a pointer to device identified by UUID. +// (other items were commented in a header).es +// ----------------------------------------------------------------------------- +// +EXPORT_C const CUpnpDevice* CUpnpControlPoint::Device(const TDesC8& aUuid) + { + RPointerArray devices = DeviceList(); + for( TInt i(0); i < devices.Count(); i++) + { + if(aUuid.Compare( devices[i]->Uuid() ) == 0) + { + return devices[i]; + } + } + return NULL; + } + +// ----------------------------------------------------------------------------- +// CUpnpControlPoint::AddressChangedL +// +// ----------------------------------------------------------------------------- +// +void CUpnpControlPoint::AddressChangedL() + { + LOG_FUNC_NAME; + TInt i(0); + RPointerArray devices = iDeviceRepository->DiscoveredDeviceList(); + RPointerArray rootDevices; + CleanupClosePushL(rootDevices); + for( i = 0; i < devices.Count(); i++) + { + if(!devices[i]->IsEmbeddDevice()) + { + rootDevices.AppendL(devices[i]); + } + } + devices = iDeviceRepository->UnneddedDeviceList(); + for( i = 0; i < devices.Count(); i++) + { + if(!devices[i]->IsEmbeddDevice()) + { + rootDevices.AppendL(devices[i]); + } + } + devices = iDeviceRepository->UninterestingDeviceList(); + for( i = 0; i < devices.Count(); i++) + { + if(!devices[i]->IsEmbeddDevice()) + { + rootDevices.AppendL(devices[i]); + } + } + devices = iDeviceRepository->IncompliteDeviceList(); + for( i = 0; i < devices.Count(); i++) + { + if(!devices[i]->IsEmbeddDevice()) + { + rootDevices.AppendL(devices[i]); + } + } + + for( i = 0; i < rootDevices.Count(); i++) + { + RemoveRootDeviceLD( rootDevices[i] ); + } + CleanupStack::PopAndDestroy(&rootDevices); + + } + +// ----------------------------------------------------------------------------- +// CUpnpControlPoint::GiveAddressL +// +// ----------------------------------------------------------------------------- +// +TInetAddr CUpnpControlPoint::GiveAddressL( const TDesC8& aUrl ) + { + TInetAddr result= INET_ADDR(0,0,0,0); + result.SetPort( 0 ); + TInt colonPos = aUrl.Find( KColon() ) ; + if ( colonPos != KErrNotFound ) + { + TPtrC8 addressStr = aUrl.Left( colonPos ); + HBufC* buffer = HBufC::NewL( addressStr.Length() ); + TPtr bufferPtr(buffer->Des() ); + bufferPtr.Copy( addressStr ); + result.Input( *buffer ); + delete buffer; + const TDesC8& portStr = aUrl.Mid( colonPos + 1 ); + TLex8 lexer(portStr); + TInt port(0); + lexer.Val( port ); + result.SetPort( port ); + } + else + { + HBufC* buffer = HBufC::NewL( aUrl.Length() ); + TPtr bufferPtr(buffer->Des() ); + bufferPtr.Copy( aUrl ); + result.Input( *buffer ); + delete buffer; + } + return result; + } + +// ----------------------------------------------------------------------------- +// CUpnpControlPoint::RemoveRootDeviceLD +// +// ----------------------------------------------------------------------------- +// +void CUpnpControlPoint::RemoveRootDeviceLD( CUpnpDevice* aDevice ) + { + TBool isDiscovered = EFalse; + + iCpbHttpClient->StopIgnoringL( aDevice ); + + RemoveActionsL( aDevice ); + RemoveServicesL( aDevice ); + + //find all children of the device to be removed + RPointerArray devices; + aDevice->GetAllDevices( devices ); + CleanupClosePushL( devices ); + + for ( TInt k = 0; k < devices.Count(); k++ ) + { + RemoveActionsL( devices[k] ); + isDiscovered + = iDeviceRepository->IsDiscoveredDevice( devices[k]->Uuid() ); + iDeviceRepository->RemoveDevice( devices[k] ); + if ( isDiscovered ) + { + DeviceDisappeared( devices[k] ); + } + RemoveServicesL( devices[k] ); + } + + CleanupStack::PopAndDestroy( &devices ); + + iActionList.Compress(); + isDiscovered = iDeviceRepository->IsDiscoveredDevice( aDevice->Uuid() ); + iDeviceRepository->RemoveDevice( aDevice ); + if ( isDiscovered ) + { + DeviceDisappeared( aDevice ); + } + + delete aDevice; + aDevice = NULL; + } + +// ----------------------------------------------------------------------------- +// CUpnpControlPoint::RemoveActionsL +// +// ----------------------------------------------------------------------------- +// +void CUpnpControlPoint::RemoveActionsL( CUpnpDevice* aDevice ) + { + for ( TInt i = 0; i < iActionList.Count(); ++i ) + { + if( ( iActionList[i]->Service().Device().Uuid()).Compare( + aDevice->Uuid() ) == 0 ) + { + CUpnpAction* action = iActionList[i]; + + CUpnpSoapMessage* errorMsg = + RUpnpSoapMessageFactory::SoapResponseL( action, + EActionFailed ); + + CleanupStack::PushL( errorMsg ); + iSaxController->UpdateActionWithErrorResponseL( errorMsg, action ); + ActionResponseReceived( action ); + iActionList.Remove( i ); + delete action; + CleanupStack::PopAndDestroy( errorMsg ); + //as a action is removed from the list the + //index is kept as same for the next loop. + --i; + } + } + } + +// ----------------------------------------------------------------------------- +// CUpnpControlPoint::RemoveServicesL +// +// ----------------------------------------------------------------------------- +// +void CUpnpControlPoint::RemoveServicesL( CUpnpDevice* aDevice ) + { + RPointerArray& services = aDevice->ServiceList(); + for ( TInt j = 0; j < services.Count(); j++ ) + { + UnsubscribeL( services[j], EFalse ); + } + } + +// ----------------------------------------------------------------------------- +// CUpnpControlPoint::FindServiceInfoByService +// +// ----------------------------------------------------------------------------- +// +CUpnpServiceInfo* CUpnpControlPoint::FindServiceInfoByService( + CUpnpService* aService ) + { + for ( TInt i=0; i < iSubscribedServicesInfos.Count() ; i++ ) + { + if ( iSubscribedServicesInfos[i]->Service() == aService ) + { + return iSubscribedServicesInfos[i]; + } + } + return NULL; + } + +// ----------------------------------------------------------------------------- +// CUpnpControlPoint::FindServiceInfoByHttpMessage +// +// ----------------------------------------------------------------------------- +// +CUpnpServiceInfo* CUpnpControlPoint::FindServiceInfoByGenaMessage( + CUpnpGenaMessage* aGenaMsg ) + { + for ( TInt i=0; i < iSubscribedServicesInfos.Count() ; i++ ) + { + if ( iSubscribedServicesInfos[i]->SessionId() + == aGenaMsg->SessionId() ) + { + return iSubscribedServicesInfos[i]; + } + } + return NULL; + } + +void CUpnpControlPoint::ProcessDeviceMessageL( CUpnpHttpMessage* aHttpMessage ) + { + iDescriptionAgent->ProcessDeviceMessageL( aHttpMessage ); + } + +void CUpnpControlPoint::ProcessServiceMessageL( CUpnpHttpMessage* aHttpMessage ) + { + iDescriptionAgent->ProcessServiceMessageL( aHttpMessage ); + } + +void CUpnpControlPoint::ProcessActionMessageL( CUpnpHttpMessage* aHttpMessage ) + { + + TInt idx(0); + // Match request action + for ( ; idx < iActionList.Count() && iActionList[idx]->SessionId() + != aHttpMessage->SessionId(); idx++ ) + { + } + if ( idx == iActionList.Count() ) + { + return; + } + + CUpnpAction* tmpAction = iActionList[idx]; + + + TInt error(KErrNone); + switch ( aHttpMessage->Error() ) + { + case EHttp200Ok: + { + TRAP( error, + iSaxController->UpdateActionWithOKResponseL( + static_cast(aHttpMessage), tmpAction ); + ); + } + break; + case EHttpInternalServerError: + { + TRAP( error, + iSaxController->UpdateActionWithErrorResponseL( + static_cast(aHttpMessage), tmpAction ); + ); + break; + } + default: + { + if ( aHttpMessage->InternalError() ) + { + tmpAction->SetError( aHttpMessage->InternalError() ); + } + else + { + tmpAction->SetError( MapHttpError( aHttpMessage->Error() ) ); + } + break; + } + } + if ( KErrNone != error ) + { + tmpAction->SetError( error ); + } + + ActionResponseReceived( tmpAction ); + delete tmpAction; + iActionList.Remove( idx ); + } + +// ----------------------------------------------------------------------------- +// CUpnpControlPoint::StateUpdated +// +// ----------------------------------------------------------------------------- +// +void CUpnpControlPoint::StateUpdated( CUpnpService* aService ) + { + TRAP_IGNORE( StateUpdatedL( aService ) ); + } + +// ----------------------------------------------------------------------------- +// CUpnpControlPoint::DeviceDiscovered +// +// ----------------------------------------------------------------------------- +// +void CUpnpControlPoint::DeviceDiscovered( CUpnpDevice* aDevice ) + { + TRAP_IGNORE( DeviceDiscoveredL( aDevice ) ); + } + +// ----------------------------------------------------------------------------- +// CUpnpControlPoint::DeviceDisappeared +// +// ----------------------------------------------------------------------------- +// +void CUpnpControlPoint::DeviceDisappeared( CUpnpDevice* aDevice ) + { + TRAP_IGNORE( DeviceDisappearedL( aDevice ) ); + } + +// ----------------------------------------------------------------------------- +// CUpnpControlPoint::ActionResponseReceived +// +// ----------------------------------------------------------------------------- +// +void CUpnpControlPoint::ActionResponseReceived( CUpnpAction* aAction ) + { + TRAP_IGNORE( ActionResponseReceivedL( aAction ) ); + } + +// ----------------------------------------------------------------------------- +// CUpnpControlPoint::HttpResponseReceived +// +// ----------------------------------------------------------------------------- +// +void CUpnpControlPoint::HttpResponseReceived( CUpnpHttpMessage* aMessage ) + { + TRAP_IGNORE( HttpResponseReceivedL( aMessage ) ); + } + +// ----------------------------------------------------------------------------- +// CUpnpControlPoint::EnableRadaDeviceL +// +// ----------------------------------------------------------------------------- +// +#ifdef RD_UPNP_REMOTE_ACCESS +EXPORT_C void CUpnpControlPoint::EnableRadaDeviceL( TRequestStatus& aStatus ) +#else +EXPORT_C void CUpnpControlPoint::EnableRadaDeviceL( TRequestStatus& /*aStatus*/ ) +#endif + { + #ifdef RD_UPNP_REMOTE_ACCESS + iDiscoveryAgent->EnableRadaDeviceL( aStatus ); + #endif + } + +// ----------------------------------------------------------------------------- +// CUpnpControlPoint::EnableRadaDeviceL +// +// ----------------------------------------------------------------------------- +// +EXPORT_C TInt CUpnpControlPoint::EnableRadaDeviceL() + { + #ifdef RD_UPNP_REMOTE_ACCESS + return iDiscoveryAgent->EnableRadaDeviceL(); + #else + return KErrNotSupported; + #endif + } + +// ----------------------------------------------------------------------------- +// CUpnpControlPoint::DisableRadaDeviceL +// +// ----------------------------------------------------------------------------- +// +EXPORT_C void CUpnpControlPoint::DisableRadaDeviceL() + { + #ifdef RD_UPNP_REMOTE_ACCESS + iDiscoveryAgent->DisableRadaDeviceL(); + #endif + } + +// ----------------------------------------------------------------------------- +// CUpnpControlPoint::StartIPFilteringL +// +// ----------------------------------------------------------------------------- +// +#ifdef RD_UPNP_REMOTE_ACCESS +EXPORT_C void CUpnpControlPoint::StartIPFilteringL( TFilteringMode aMode ) +#else +EXPORT_C void CUpnpControlPoint::StartIPFilteringL( TFilteringMode /*aMode*/ ) +#endif + { + #ifdef RD_UPNP_REMOTE_ACCESS + switch( aMode ) + { + case EBoth: + { + iCpbHttpClient->StartIPFilteringL(); + iDiscoveryAgent->StartIPFilteringL(); + break; + } + case ERada: + { + iDiscoveryAgent->StartIPFilteringL(); + break; + } + case EControlPoint: + { + iCpbHttpClient->StartIPFilteringL(); + break; + } + default: + { + User::Leave( KErrNotSupported ); + break; + } + } + #endif + } + +// ----------------------------------------------------------------------------- +// CUpnpControlPoint::StopIPFilteringL +// +// ----------------------------------------------------------------------------- +// +#ifdef RD_UPNP_REMOTE_ACCESS +EXPORT_C void CUpnpControlPoint::StopIPFilteringL( TFilteringMode aMode ) +#else +EXPORT_C void CUpnpControlPoint::StopIPFilteringL( TFilteringMode /*aMode*/ ) +#endif + { + #ifdef RD_UPNP_REMOTE_ACCESS + switch( aMode ) + { + case EBoth: + { + iCpbHttpClient->StopIPFiltering(); + iDiscoveryAgent->StopIPFiltering(); + break; + } + case ERada: + { + iDiscoveryAgent->StopIPFiltering(); + break; + } + case EControlPoint: + { + iCpbHttpClient->StopIPFiltering(); + break; + } + default: + { + User::Leave( KErrNotSupported ); + break; + } + } + #endif + } + +// ----------------------------------------------------------------------------- +// CUpnpControlPoint::NetworkEvent +// ----------------------------------------------------------------------------- +// +EXPORT_C void CUpnpControlPoint::NetworkEvent( CUpnpNetworkEventBase* aEvent ) + { + LOG_FUNC_NAME; + + switch ( aEvent->Type() ) + { + case EWlanLostEvent: + { + iCpbHttpClient->WlanLostOccurs(); + } + break; + + case EAddressChangeEvent: + { + TRAP_IGNORE( iCpbHttpClient->AddressChangedL(); AddressChangedL() ); + } + break; + } + } + +// End of File