--- /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 <e32base.h>
+#include <e32cons.h>
+#include <e32std.h>
+#include <in_sock.h>
+#include <charconv.h>
+#include <utf.h>
+
+#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<CUpnpDevice>& 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<CUpnpService*>( 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<CUpnpDevice> 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 <CUpnpGenaMessage*> ( &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<CUpnpGenaMessage*> ( &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<CUpnpServiceInfo>& 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<CUpnpDevice> 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<CUpnpDevice> devices = iDeviceRepository->DiscoveredDeviceList();
+ RPointerArray<CUpnpDevice> 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<CUpnpDevice> 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<CUpnpService>& 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<CUpnpSoapMessage*>(aHttpMessage), tmpAction );
+ );
+ }
+ break;
+ case EHttpInternalServerError:
+ {
+ TRAP( error,
+ iSaxController->UpdateActionWithErrorResponseL(
+ static_cast<CUpnpSoapMessage*>(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