upnp/upnpstack/upnputils/src/upnpdevicelibrary.cpp
changeset 0 f5a58ecadc66
child 9 5c72fd91570d
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/upnp/upnpstack/upnputils/src/upnpdevicelibrary.cpp	Tue Feb 02 01:12:20 2010 +0200
@@ -0,0 +1,763 @@
+/** @file
+* Copyright (c) 2005-2008 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:  CUpnpDeviceLibrary
+*
+*/
+
+
+// INCLUDE FILES
+#include "upnpdevicelibrary.h"
+#include "upnpssdpmessage.h"
+#define KLogFile _L("DLNAWebServer.txt")
+#include "upnpcustomlog.h"
+
+static const TInt KIntervalBetweenByeAndAlive = 1;
+static const TInt KIntervalBeforeFirstAlive = 1;
+// prevents treating SSDP alive messages sent by local device
+// as an external device messages in case of quick local device restarting
+// heuristic value 
+static const TInt KLocalDeviceHysteresisWindow  = 20;
+// used for IPC communication 2 phase request
+// heuristic value 
+static const TInt KIpcCommunicationTimeout = 2;
+
+// ============================ MEMBER FUNCTIONS ===============================
+
+// -----------------------------------------------------------------------------
+// CUpnpDeviceLibrary::CUpnpDeviceLibrary
+// C++ default constructor can NOT contain any code, that
+// might leave.
+// -----------------------------------------------------------------------------
+//
+CUpnpDeviceLibrary::CUpnpDeviceLibrary( MUpnpDeviceLibraryObserver& aObserver,
+                                TInt aHandle )
+    : iObserver(aObserver),
+      iHandle( aHandle )
+    {
+    }
+
+// -----------------------------------------------------------------------------
+// CUpnpDeviceLibrary::ConstructL
+// Symbian 2nd phase constructor can leave.
+// -----------------------------------------------------------------------------
+//
+void CUpnpDeviceLibrary::ConstructL()
+    {
+    }
+
+// -----------------------------------------------------------------------------
+// CUpnpDeviceLibrary::NewL
+// Two-phased constructor.
+// -----------------------------------------------------------------------------
+//
+EXPORT_C CUpnpDeviceLibrary* CUpnpDeviceLibrary::NewL( 
+                                        MUpnpDeviceLibraryObserver& aObserver,
+                                        TInt aHandle )
+    {
+    CUpnpDeviceLibrary* self = new (ELeave) CUpnpDeviceLibrary( aObserver, aHandle );
+
+    CleanupStack::PushL( self );
+    self->ConstructL();
+    CleanupStack::Pop( self );
+    
+    return self;
+    }
+// -----------------------------------------------------------------------------
+// CUpnpDeviceLibrary::~CUpnpDeviceLibrary
+// Destructor
+// -----------------------------------------------------------------------------
+//
+EXPORT_C CUpnpDeviceLibrary::~CUpnpDeviceLibrary()
+    {
+    LOGSH( iHandle, "Devicelibrary ~CUpnpDeviceLibrary");
+
+    iElementArray.ResetAndDestroy();
+    iElementArray.Close();
+    }
+
+// -----------------------------------------------------------------------------
+// CUpnpDeviceLibrary::PrepareShutdown
+// Prepare devices for shutdown.
+// -----------------------------------------------------------------------------
+//
+EXPORT_C void CUpnpDeviceLibrary::PrepareShutdown()
+    {
+    LOGSH( iHandle, "Devicelibrary PrepareShutdown" );
+
+    }
+
+// -----------------------------------------------------------------------------
+// CUpnpDeviceLibrary::AddInfoL
+// Add device info.
+// -----------------------------------------------------------------------------
+//
+EXPORT_C void CUpnpDeviceLibrary::AddInfoL( const TUpnpAddLocalDevice* aIndex, 
+                                        const TDesC8& aBuffer, 
+                                        const TInetAddr& aLocalAddr )
+    {
+    LOGSH( iHandle, "Devicelibrary AddInfoL" );
+    if ( !aIndex )
+        {
+        return;
+        }
+    
+    TPtrC8 uuid = aBuffer.Left(aIndex->iUuidLength);    
+    TInt index = Find( uuid );
+    
+    if ( index != KErrNotFound )
+        {        
+        CUpnpDeviceLibraryElement* elem = iElementArray[index];
+        
+        if ( elem->Local() )
+            {            
+            CUpnpTimeoutElement::TRenew state = elem->Renew();          
+            elem->AddInfoL( aIndex, aBuffer, aLocalAddr );                        
+            elem->SetRenew( CUpnpTimeoutElement::ERenew );
+            elem->SetTimeout( KIntervalBeforeFirstAlive );        
+            elem->SetUpdateId( iUpdateId );
+                 
+            if ( state == CUpnpTimeoutElement::ERemove ) 
+                {   
+                elem->SetAlive( ETrue );                
+                elem->SetUpdateId( ++iUpdateId );
+                iObserver.DeviceListChangedL();
+                }        
+            }
+        else
+            {
+            InvalidateNonLocalDevice( *elem );
+            AppendLocalDeviceL( aIndex, aBuffer, aLocalAddr );                            
+            iObserver.DeviceListChangedL();            
+            }                
+        }
+    else
+        {        
+        AppendLocalDeviceL( aIndex, aBuffer, aLocalAddr );                
+        iObserver.DeviceListChangedL();
+        }
+    }
+
+// -----------------------------------------------------------------------------
+// CUpnpDeviceLibrary::InvalidateNonLocalDevice
+// -----------------------------------------------------------------------------
+//
+void CUpnpDeviceLibrary::InvalidateNonLocalDevice( CUpnpDeviceLibraryElement& aElem )
+    {
+    aElem.SetAlive( EFalse );
+    aElem.SetUpdateId( ++iUpdateId );
+    aElem.SetTimeout( KIpcCommunicationTimeout );                            
+    }
+
+// -----------------------------------------------------------------------------
+// CUpnpDeviceLibrary::AppendLocalDeviceL
+// -----------------------------------------------------------------------------
+//
+void CUpnpDeviceLibrary::AppendLocalDeviceL( const TUpnpAddLocalDevice* aIndex, 
+                         const TDesC8& aBuffer, 
+                         const TInetAddr& aLocalAddr )
+    {    
+    CUpnpDeviceLibraryElement* element = CUpnpDeviceLibraryElement::NewL(*this);
+    CleanupStack::PushL( element );
+    element->AddInfoL( aIndex, aBuffer, aLocalAddr );
+    element->SetRenew( CUpnpTimeoutElement::ERenew );
+    element->SetTimeout( KIntervalBeforeFirstAlive );
+    element->SetLocal( ETrue );
+    element->SetUpdateId( ++iUpdateId );
+    iElementArray.AppendL( element );
+    CleanupStack::Pop( element );    
+    }
+// -----------------------------------------------------------------------------
+// CUpnpDeviceLibrary::AddInfoL
+// Add device info.
+// -----------------------------------------------------------------------------
+//
+EXPORT_C void CUpnpDeviceLibrary::AddInfoL( const TUpnpAddLocalDevice* aIndex, 
+                                        const TDesC8& aBuffer )
+    {
+    LOGSH( iHandle, "Devicelibrary AddInfoL");
+
+    if ( !aIndex )
+        {
+        return;
+        }
+    
+    TPtrC8 uuid = aBuffer.Left(aIndex->iUuidLength);
+    
+    TInt index = Find( uuid );
+    
+    if ( index != KErrNotFound )
+        {
+        CUpnpDeviceLibraryElement* elem = iElementArray[index];
+        
+        CUpnpTimeoutElement::TRenew state = elem->Renew();
+        
+        elem->AddInfoL( aIndex, aBuffer );                        
+        elem->SetRenew( CUpnpTimeoutElement::ERenew );
+        elem->SetTimeout( 1 );        
+        elem->SetUpdateId( iUpdateId );
+             
+        if (state == CUpnpTimeoutElement::ERemove) 
+            {   
+            iUpdateId++; 
+            elem->SetAlive( ETrue );                
+            elem->SetUpdateId( iUpdateId );
+            iObserver.DeviceListChangedL();
+            }        
+        }
+    else
+        {
+        iUpdateId++;
+        
+        CUpnpDeviceLibraryElement* element = CUpnpDeviceLibraryElement::NewL(*this);
+        CleanupStack::PushL( element );
+        element->AddInfoL( aIndex, aBuffer );
+        element->SetRenew( CUpnpTimeoutElement::ERenew );
+        element->SetTimeout( 1 );
+        element->SetLocal( EFalse );
+        element->SetUpdateId( iUpdateId );
+        iElementArray.AppendL( element );
+        CleanupStack::Pop( element );
+        
+        iObserver.DeviceListChangedL();
+        }
+    }
+// -----------------------------------------------------------------------------
+// CUpnpDeviceLibrary::AddInfoL
+// Add device info.
+// -----------------------------------------------------------------------------
+//
+EXPORT_C void CUpnpDeviceLibrary::AddInfoL( CUpnpSsdpMessage* aMessage )
+    {
+    LOGSH( iHandle, "Devicelibrary AddInfoL");
+    if ( aMessage )
+        {
+        if ( aMessage->IsSsdpAlive() )
+            {       
+            if( AddDeviceL(aMessage) )
+                {  
+                iObserver.DeviceListChangedL();
+                }
+            }
+        else
+            {
+            RemoveDeviceL( aMessage );
+            iObserver.DeviceListChangedL();
+            }
+        }
+    }
+
+// -----------------------------------------------------------------------------
+// CUpnpDeviceLibrary::Find
+// Find device given by UUID.
+// -----------------------------------------------------------------------------
+//
+EXPORT_C TInt CUpnpDeviceLibrary::Find( const TDesC8& aUuid )
+    {
+    LOGSH( iHandle, "Devicelibrary Find");
+
+    for ( TInt i=0; i<iElementArray.Count(); i++ )
+        {
+        if ( aUuid.FindC( iElementArray[i]->UUID() ) == 0 
+             && aUuid.Length() == iElementArray[i]->UUID().Length() )
+            {
+            return i;
+            }
+        }
+    return KErrNotFound;
+    }
+
+// -----------------------------------------------------------------------------
+// CUpnpDeviceLibrary::RemoveL
+// Remove device by given UID. Used for local devices only.
+// -----------------------------------------------------------------------------
+//
+EXPORT_C void CUpnpDeviceLibrary::RemoveL( const TDesC8& aUuid )
+    {
+    LOGSH( iHandle, "Devicelibrary RemoveL");
+
+    TInt result = Find( aUuid );
+    
+    if ( result != KErrNotFound )
+        {
+        CUpnpDeviceLibraryElement* elem = iElementArray[result];
+
+        iObserver.AdvertiseDeviceL( EFalse, *elem );
+        iObserver.AdvertiseDeviceL( EFalse, *elem );        
+
+        elem->AdvertisingFinished();
+        
+        elem->SetRenew( CUpnpTimeoutElement::ERemove );
+        elem->SetTimeout( KLocalDeviceHysteresisWindow );
+        elem->SetUpdateId( ++iUpdateId );
+        elem->SetAlive( EFalse );            
+
+        iObserver.DeviceListChangedL();
+        }
+    }
+// -----------------------------------------------------------------------------
+// CUpnpDeviceLibrary::RemoveSilentL
+// Remove device by given UID. Used for local devices only.
+// -----------------------------------------------------------------------------
+//
+EXPORT_C void CUpnpDeviceLibrary::RemoveSilentL( const TDesC8& aUuid )
+    {
+    //LOGS( iHandle, "Devicelibrary RemoveSilentL");
+    
+   LOGS("CUpnpDeviceLibrary::RemoveSilentL( const TDesC8& aUuid )");
+    TInt result = Find( aUuid );
+    
+    if ( result != KErrNotFound )
+        {
+        CUpnpDeviceLibraryElement* elem = iElementArray[result];
+
+        
+        elem->SetRenew( CUpnpTimeoutElement::ERemove );
+        elem->SetTimeout( KLocalDeviceHysteresisWindow );
+        elem->SetUpdateId( ++iUpdateId );
+        elem->SetAlive( EFalse );            
+
+        iObserver.DeviceListChangedL();
+        }
+         LOGS("CUpnpDeviceLibrary::RemoveSilentL( const TDesC8& aUuid ) passed");
+    }
+
+// -----------------------------------------------------------------------------
+// CUpnpDeviceLibrary::TimeoutExpiredL
+// Timeout expired for advertisement.
+// -----------------------------------------------------------------------------
+//
+void CUpnpDeviceLibrary::TimeoutExpiredL( CUpnpTimeoutElement* anElement )
+    {
+    LOGSH( iHandle, "Devicelibrary TimeoutExpiredL");
+
+    if ( !anElement )
+        {
+        return;
+        }
+    
+    CUpnpDeviceLibraryElement* elem = 
+        static_cast<CUpnpDeviceLibraryElement*>(anElement);
+    
+    switch ( elem->Renew() )
+        {
+        case CUpnpTimeoutElement::ERenew:
+            {
+            if ( !elem->Advertised() )
+                {
+                elem->Advertising();
+                // whatever happends we don't want to have leave here
+                TRAP_IGNORE( iObserver.AdvertiseDeviceL( EFalse, *elem ));
+                TRAP_IGNORE( iObserver.AdvertiseDeviceL( EFalse, *elem ));
+                elem->SetTimeout( KIntervalBetweenByeAndAlive );
+                }
+            else 
+                {
+                // whatever happends we don't want to have leave here
+                TRAP_IGNORE( iObserver.AdvertiseDeviceL( ETrue, *elem ));
+                elem->SetTimeout( KDeviceTimeout );
+                }
+            }
+            break;
+            
+        case CUpnpTimeoutElement::EOnce: // after cache control expires
+            {    
+            // Set the timeout for the device to be removed
+            iUpdateId++;
+            elem->SetRenew( CUpnpTimeoutElement::ERemove );
+            if( elem->Local() )
+                {
+                elem->SetTimeout( KLocalDeviceHysteresisWindow );    
+                }
+            else
+                {
+                elem->SetTimeout( KIpcCommunicationTimeout );
+                }
+            elem->SetUpdateId( iUpdateId );
+            elem->SetAlive( EFalse );
+            elem->SetExpired( ETrue );
+
+            iObserver.DeviceListChangedL();
+            }
+            break;
+
+        case CUpnpTimeoutElement::ERemove:
+            {
+            // Remove device from the element array
+            for ( TInt i=0; i<iElementArray.Count(); i++ )
+                {
+                if ( elem == iElementArray[i] )
+                    {
+                    iElementArray.Remove( i );
+                    iElementArray.Compress();
+                    
+                    delete elem;
+                    break;
+                    }
+                }
+            }
+            break;
+
+        default:
+            break;
+        }
+    }
+
+// -----------------------------------------------------------------------------
+// CUpnpDeviceLibrary::DeviceList
+// Return device list.
+// -----------------------------------------------------------------------------
+//
+EXPORT_C RPointerArray<CUpnpDeviceLibraryElement>& CUpnpDeviceLibrary::DeviceList()
+    {
+    LOGSH( iHandle, "Devicelibrary DeviceList");
+
+    return iElementArray;
+    }
+
+// -----------------------------------------------------------------------------
+// CUpnpDeviceLibrary::GetUpdate
+// Get update.
+// -----------------------------------------------------------------------------
+//
+EXPORT_C void CUpnpDeviceLibrary::GetUpdate( TInt& aUpdateId, 
+                                         TUpnpDevice *&aDevices, 
+                                         TUpnpService *&aServices,
+                                         TInt& aDeviceCount,
+                                         TInt& aServiceCount )
+    {
+    aDevices = NULL;
+    aServices = NULL;
+    
+    TUpnpDevice* devices = NULL;
+    TUpnpService* services = NULL;
+    
+    aDeviceCount = 0;
+    aServiceCount = 0;
+    
+    for ( TInt i = 0; i < iElementArray.Count(); i++ )
+        {
+        CUpnpDeviceLibraryElement* elem = iElementArray[i];
+        
+        if (elem->UpdateId() > aUpdateId)
+            {
+            TUpnpDevice* temp = new TUpnpDevice[aDeviceCount+1];
+            if ( !temp )
+                {
+                continue;
+                }
+            
+            TPtr8 destPtr(reinterpret_cast<TUint8*>(temp), 
+                0,
+                sizeof(TUpnpDevice)*(aDeviceCount+1));
+            TPtr8 srcPtr(reinterpret_cast<TUint8*>(devices),
+                sizeof(TUpnpDevice)*aDeviceCount,
+                sizeof(TUpnpDevice)*aDeviceCount);
+            
+            destPtr.Copy(srcPtr);
+            
+            if (devices)
+                {
+                delete[] devices;
+                devices = NULL;
+                }
+            
+            devices = temp;
+            
+            TUpnpDevice devtemp;
+            destPtr.Set(reinterpret_cast<TUint8*>(&devices[aDeviceCount]),
+                0,
+                sizeof(TUpnpDevice));
+            srcPtr.Set(reinterpret_cast<TUint8*>(&devtemp), 
+                sizeof(TUpnpDevice),
+                sizeof(TUpnpDevice));
+            destPtr.Copy(srcPtr);
+            
+            devices[aDeviceCount].Set(elem);
+            
+            TInt servs = elem->ServiceList().Count();
+            
+            TUpnpService* tempServ = new TUpnpService[aServiceCount+servs];
+            if ( !tempServ )
+                {
+                delete [] temp;
+                temp = NULL;
+                devices = NULL;
+                continue;
+                }
+            
+            destPtr.Set(reinterpret_cast<TUint8*>(tempServ), 
+                0,
+                sizeof(TUpnpService)*(aServiceCount+servs));
+            srcPtr.Set(reinterpret_cast<TUint8*>(services),
+                sizeof(TUpnpService)*aServiceCount,
+                sizeof(TUpnpService)*aServiceCount);
+            
+            destPtr.Copy(srcPtr);
+            
+            if (services)
+                {
+                delete[] services;
+                services = NULL;
+                }
+            
+            services = tempServ;
+            
+            for (TInt j=0; j<servs; j++)
+                {
+                TUpnpService service;
+                destPtr.Set(reinterpret_cast<TUint8*>(&services[aServiceCount]),
+                    0,
+                    sizeof(TUpnpService));
+                srcPtr.Set(reinterpret_cast<TUint8*>(&service), 
+                    sizeof(TUpnpService),
+                    sizeof(TUpnpService));
+                destPtr.Copy(srcPtr);
+                
+                services[aServiceCount].iServiceType.Zero();
+                services[aServiceCount].iServiceType.Append(
+                    elem->ServiceList()[j] );
+                
+                aServiceCount++;
+                }
+            
+            aDeviceCount++;
+            }
+        }
+    
+    aUpdateId = iUpdateId;
+    
+    aDevices = devices;
+    aServices = services;
+    }
+    
+// -----------------------------------------------------------------------------
+// CUpnpDeviceLibrary::RemoveAllDevicesL
+// Removes all remote devices from device library.
+// -----------------------------------------------------------------------------
+//
+EXPORT_C void CUpnpDeviceLibrary::RemoveAllDevicesL()
+    {
+    for (TInt i = 0; i < iElementArray.Count(); i++)
+        {
+        CUpnpDeviceLibraryElement* elem = iElementArray[i];
+        if ( elem->Alive() )
+            {
+            iUpdateId++;
+            elem->SetAlive(EFalse);
+            elem->SetUpdateId( iUpdateId );
+            if( elem->Renew() == CUpnpTimeoutElement::EOnce )
+                {
+                elem->SetRenew( CUpnpTimeoutElement::ERemove );
+                elem->SetTimeout( KIpcCommunicationTimeout );
+                }
+            }
+        }
+    iObserver.DeviceListChangedL();        
+    }    
+
+// -----------------------------------------------------------------------------
+// TUpnpDevice::Set
+// Set device.
+// -----------------------------------------------------------------------------
+//
+EXPORT_C void TUpnpDevice::Set(CUpnpDeviceLibraryElement* aElem)
+    {
+    LOGS("Devicelibrary Set");
+
+    if ( !aElem )
+        {
+        return;
+        }
+
+    iDescriptionURL = aElem->DescriptionUrl().Left( iDescriptionURL.MaxLength() );
+    iUUID = aElem->UUID().Left( iUUID.MaxLength() );
+    iDeviceType = aElem->DeviceType().Left( iDeviceType.MaxLength() );
+    iDomain = aElem->Domain().Left( iDomain.MaxLength() );
+
+    iServiceCount = aElem->ServiceList().Count();
+    iLocal = aElem->Local();
+    iRemote = EFalse;
+    iAlive = aElem->Alive();
+    iExpired = aElem->Expired();
+    }
+
+// -----------------------------------------------------------------------------
+// CUpnpDeviceLibrary::AddDeviceL
+// Add a device.
+// -----------------------------------------------------------------------------
+//
+TBool CUpnpDeviceLibrary::AddDeviceL(CUpnpSsdpMessage *aMessage)
+    {
+    TBool update = EFalse;
+
+    LOGSH( iHandle, "Devicelibrary AddDeviceL");
+
+    if ( !aMessage )
+        {
+        return update;
+        }
+    
+    TPtr8 uuidPtr = aMessage->Uuid();
+    TInt index = Find( uuidPtr );
+    
+    if (index != KErrNotFound)
+        {
+        CUpnpDeviceLibraryElement* elem = iElementArray[index];
+        if ( !elem->Local() )
+        {
+            if( elem->Renew() == CUpnpTimeoutElement::ERemove )
+                {
+                iElementArray.Remove( index );
+                iElementArray.Compress();
+                
+                delete elem;
+                
+                CUpnpDeviceLibraryElement* element = CUpnpDeviceLibraryElement::NewL(*this);
+                CleanupStack::PushL(element);
+                
+                update = element->AddInfoL(aMessage, iUpdateId);
+                
+                element->SetRenew(CUpnpTimeoutElement::EOnce);
+                element->SetTimeout(aMessage->CacheControl());
+                element->SetLocal(EFalse);
+                iElementArray.Append(element);
+                
+                CleanupStack::Pop(); // element
+                }
+            
+            else 
+                {
+                if(elem->Filter())
+                    {
+                    //Alive message from 
+                    if(elem->AddInfoL(aMessage, iUpdateId))
+                        {
+                        update=ETrue;
+                        }
+                    elem->SetTimeout(aMessage->CacheControl());    
+                    }
+                else
+                    {
+                    iElementArray.Remove( index );
+                    iElementArray.Compress();
+                
+                    delete elem;
+                
+                    CUpnpDeviceLibraryElement* element = CUpnpDeviceLibraryElement::NewL(*this);
+                    CleanupStack::PushL(element);
+                
+                    update = element->AddInfoL(aMessage, iUpdateId);
+                
+                    element->SetRenew(CUpnpTimeoutElement::EOnce);
+                    element->SetTimeout(aMessage->CacheControl());
+                    element->SetLocal(EFalse);
+                    iElementArray.Append(element);
+                
+                    CleanupStack::Pop(); // element
+                    }
+                }
+            }
+        }
+    else
+        {    
+        CUpnpDeviceLibraryElement* element = CUpnpDeviceLibraryElement::NewL(*this);
+        CleanupStack::PushL(element);
+        
+        update = element->AddInfoL(aMessage, iUpdateId);
+        
+        element->SetRenew(CUpnpTimeoutElement::EOnce);
+        element->SetTimeout(aMessage->CacheControl());
+        element->SetLocal(EFalse);
+        iElementArray.Append(element);
+        
+        CleanupStack::Pop(); // element
+        }
+    return update;
+    }
+
+// -----------------------------------------------------------------------------
+// CUpnpDeviceLibrary::RemoveDevice
+// Remove a device.
+// -----------------------------------------------------------------------------
+//
+void CUpnpDeviceLibrary::RemoveDeviceL( CUpnpSsdpMessage *aMessage )
+    {
+    LOGSH( iHandle, "Devicelibrary RemoveDevice" );
+
+    if ( !aMessage )
+        {
+        return;
+        }
+    
+    TPtr8 uuidPtr = aMessage->Uuid();
+    TInt index = Find( uuidPtr );
+    
+    if ( index != KErrNotFound )
+        {
+        CUpnpDeviceLibraryElement* elem = iElementArray[index];
+        if ( !elem->Local() )
+            {
+            if ( elem->Alive() )
+                {
+                iUpdateId++;
+                elem->SetAlive(EFalse);
+                elem->SetUpdateId( iUpdateId );
+                if( elem->Renew() == CUpnpTimeoutElement::EOnce )
+                    {
+                    elem->SetRenew( CUpnpTimeoutElement::ERemove );
+                    elem->SetTimeout( KIpcCommunicationTimeout );
+                    }
+                }
+            iObserver.DeviceListChangedL();
+            }
+        }
+    else
+        {        
+        CUpnpDeviceLibraryElement* element = CUpnpDeviceLibraryElement::NewL( *this );
+        CleanupStack::PushL( element );
+
+        element->AddInfoL( aMessage, iUpdateId );
+
+        iUpdateId++;
+        element->SetAlive( EFalse );
+        element->SetUpdateId( iUpdateId );
+        element->SetRenew( CUpnpTimeoutElement::ERemove );
+        element->SetTimeout( KIpcCommunicationTimeout );
+        element->SetLocal( EFalse );
+        iElementArray.AppendL( element );
+        
+        CleanupStack::Pop( element );
+        
+        iObserver.DeviceListChangedL();
+        }
+    }
+
+// -----------------------------------------------------------------------------
+// CUpnpDeviceLibrary::StopFilteringDeviceL
+// -----------------------------------------------------------------------------
+//
+EXPORT_C void CUpnpDeviceLibrary::StopFilteringDeviceL( const TDesC8& aUuid )
+    {
+    LOGSH( iHandle, "Devicelibrary RemoveDevice" );
+
+    TInt index = Find( aUuid );
+    
+    if ( index != KErrNotFound )
+        {
+        CUpnpDeviceLibraryElement* elem = iElementArray[index];
+        elem->SetFilter(EFalse);
+        }
+    }
+
+//  End of File