upnp/upnpstack/controlpointbase/src/upnpcontrolpoint.cpp
changeset 0 f5a58ecadc66
--- /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