upnp/upnpstack/ssdpserver/src/upnpssdpserver.cpp
changeset 0 f5a58ecadc66
child 31 b51a6f4f15ba
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/upnp/upnpstack/ssdpserver/src/upnpssdpserver.cpp	Tue Feb 02 01:12:20 2010 +0200
@@ -0,0 +1,1123 @@
+/** @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:  CUpnpSsdpServer
+*
+*/
+
+
+// INCLUDE FILES
+#include <in_sock.h>
+#include <upnpsettings.h>
+#include "upnpssdpserver.h"
+#include "upnpcons.h"
+#define KLogFile _L("DLNAWebServer.txt")
+#include "upnpcustomlog.h"
+#include "upnplist.h"
+
+
+using namespace UpnpSSDP;
+using namespace UpnpString;
+
+
+// ============================ MEMBER FUNCTIONS ===============================
+
+// -----------------------------------------------------------------------------
+// CUpnpSsdpServer::CUpnpSsdpServer
+// C++ default constructor can NOT contain any code, that
+// might leave.
+// -----------------------------------------------------------------------------
+//
+CUpnpSsdpServer::CUpnpSsdpServer( MUpnpSsdpServerObserver* aSsdpServerObserver,
+                          RSocketServ* aSocketServ,
+                          TInt aListeningPort,
+                          CUpnpSsdpServer* aMasterServer )
+   : CUpnpUdpServer( aSocketServ, this, aListeningPort )
+    {
+    iMasterServer=aMasterServer;
+
+    iSsdpServerObserver = aSsdpServerObserver;
+    }
+
+// -----------------------------------------------------------------------------
+// CUpnpSsdpServer::CUpnpSsdpServer
+// C++ default constructor can NOT contain any code, that
+// might leave.
+// -----------------------------------------------------------------------------
+//
+CUpnpSsdpServer::CUpnpSsdpServer( MUpnpSsdpServerObserver* aSsdpServerObserver,
+                          RSocketServ* aSocketServ,
+                          TInt aListeningPort )
+        : CUpnpUdpServer( aSocketServ, this, aListeningPort )
+    {
+    iMasterServer = NULL;
+
+    iSsdpServerObserver = aSsdpServerObserver;
+    }
+
+// -----------------------------------------------------------------------------
+// CUpnpSsdpServer::ConstructL
+// Symbian 2nd phase constructor can leave.
+// -----------------------------------------------------------------------------
+//
+void CUpnpSsdpServer::ConstructL()
+    {
+    UdpConstructL();    
+    iServerDescription =  CUpnpSettings::GetServerHeaderL();    
+    }
+
+// -----------------------------------------------------------------------------
+// CUpnpSsdpServer::NewL
+// Two-phased constructor.
+// -----------------------------------------------------------------------------
+//
+EXPORT_C CUpnpSsdpServer* CUpnpSsdpServer::NewL( MUpnpSsdpServerObserver*
+                                                         aSsdpServerObserver,
+                                         RSocketServ* aSocketServ,
+                                         TInt aListeningPort )
+    {
+    CUpnpSsdpServer* self = new (ELeave) CUpnpSsdpServer( aSsdpServerObserver,
+                                                  aSocketServ,
+                                                  aListeningPort );
+    
+    CleanupStack::PushL(self);
+    self->ConstructL();
+    CleanupStack::Pop(self);
+    
+    return self;
+    }
+
+// -----------------------------------------------------------------------------
+// CUpnpSsdpServer::NewL
+// Two-phased constructor.
+// -----------------------------------------------------------------------------
+//
+EXPORT_C CUpnpSsdpServer* CUpnpSsdpServer::NewL( MUpnpSsdpServerObserver* 
+                                                        aSsdpServerObserver,
+                                         RSocketServ* aSocketServ,
+                                         TInt aListeningPort,
+                                         CUpnpSsdpServer* aMasterServer )
+    {
+    CUpnpSsdpServer* self = new (ELeave) CUpnpSsdpServer( aSsdpServerObserver,
+                                                  aSocketServ,
+                                                  aListeningPort,
+                                                  aMasterServer );
+    
+    CleanupStack::PushL(self);
+    self->ConstructL();
+    CleanupStack::Pop(self);
+    
+    return self;
+    }
+
+// -----------------------------------------------------------------------------
+// Destructor
+// -----------------------------------------------------------------------------
+// 
+EXPORT_C CUpnpSsdpServer::~CUpnpSsdpServer()
+    {
+    delete iServerDescription;
+    }
+
+// -----------------------------------------------------------------------------
+// CUpnpSsdpServer::MessageFromMulticastL
+// Message from multicast.
+// -----------------------------------------------------------------------------
+//
+void CUpnpSsdpServer::MessageFromMulticastL( CUpnpSsdpMessage* aMessage )
+    {
+    UdpMessageReceivedL( aMessage );
+    }
+
+// -----------------------------------------------------------------------------
+// CUpnpSsdpServer::UdpMessageReceivedL
+// UDP message received.
+// -----------------------------------------------------------------------------
+//
+void CUpnpSsdpServer::UdpMessageReceivedL( CUdpMessage* aMessage )
+    {
+    if ( !aMessage )
+        {
+        return;
+        }
+    CUpnpSsdpMessage* message = ( CUpnpSsdpMessage* ) aMessage;
+   
+       // Unless it's response, check if HOST header has explicitly specified port number - 1900
+       // If not, then add this port
+       if ( !message->IsSsdpResponse() )
+           {
+           TPtrC8 host = message->GetHeaderValue( KHdrHost );
+           
+           // : Not found so port is not specified
+           if( host.Find( UpnpString::KColon() ) == KErrNotFound )
+            {
+            TBuf8<KMaxIntegerLength> defaultPort;
+               defaultPort.Num( KMulticastPort );
+               
+               HBufC8* newHost = HBufC8::NewLC( host.Length() +
+                                       UpnpString::KColon().Length() +
+                                       defaultPort.Length() );
+               
+               newHost->Des().Zero();
+               newHost->Des().Append( host );
+               newHost->Des().Append( UpnpString::KColon() );
+               newHost->Des().Append( defaultPort );
+                   
+               message->AddHostL( *newHost );
+               CleanupStack::PopAndDestroy(newHost);
+            }
+           }
+   
+    if ( iMasterServer )
+        {
+        iMasterServer->MessageFromMulticastL( message );
+        }
+    else
+        {
+        if ( message->IsSsdpMSearch() )
+            {
+            LOGS( "SSDP *** Search received");
+            ResponseL( message );
+            // add additional notification to upper-layer 
+            // used for detection IP address change
+            iSsdpServerObserver->SsdpEventL( message );
+            }
+        else if (message->IsSsdpNotify())
+            {
+            LOGS( "SSDP *** Notify received");
+            iSsdpServerObserver->SsdpEventL( message );
+            }
+        else if (message->IsSsdpResponse())
+            {
+            LOGS( "SSDP *** Response received");
+            iSsdpServerObserver->SsdpEventL( message );
+            }
+        else
+            {
+            LOGS( "SSDP *** UNKNOWN MESSAGE RECEIVED");
+            }
+        }
+    }
+
+// -----------------------------------------------------------------------------
+// CUpnpSsdpServer::StartL
+// Start.
+// -----------------------------------------------------------------------------
+//
+EXPORT_C void CUpnpSsdpServer::StartL()
+    {
+    LOGS( "SSDP *** StartL");
+    OpenL();    
+    }
+
+// -----------------------------------------------------------------------------
+// CUpnpSsdpServer::StopL
+// Stop.
+// -----------------------------------------------------------------------------
+//
+EXPORT_C void CUpnpSsdpServer::Stop()
+    {
+    LOGS( "SSDP *** Stop");
+    Close();
+    }
+
+// -----------------------------------------------------------------------------
+// CUpnpSsdpServer::AdvertiseAliveL
+// 
+// -----------------------------------------------------------------------------
+//
+EXPORT_C void CUpnpSsdpServer::AdvertiseAliveL( CUpnpDeviceLibraryElement& aDev )
+    {
+    LOGS( "SSDP *** AdvertiseAliveL");
+    // advertise this device
+    SingleDeviceAdvertiseAliveL( aDev );
+    SingleDeviceAdvertiseAliveL( aDev );
+    }
+
+// -----------------------------------------------------------------------------
+// CUpnpSsdpServer::AdvertiseByebyeL
+// 
+// -----------------------------------------------------------------------------
+//
+EXPORT_C void CUpnpSsdpServer::AdvertiseByebyeL( CUpnpDeviceLibraryElement& aDev )
+    {
+    SingleDeviceAdvertiseByebyeL( aDev );
+    }
+
+// -----------------------------------------------------------------------------
+// CUpnpSsdpServer::SearchL
+// 
+// -----------------------------------------------------------------------------
+//
+EXPORT_C void CUpnpSsdpServer::SearchL( TDesC8& aTarget )
+    {
+    SearchL(aTarget, (TDesC8&)UpnpSSDP::KDefaultResponseDelay());
+    }
+
+// -----------------------------------------------------------------------------
+// CUpnpSsdpServer::SearchL
+// 
+// -----------------------------------------------------------------------------
+//
+EXPORT_C void CUpnpSsdpServer::SearchL( TDesC8& aTarget, TDesC8& aMaximumWaitTime )
+    {
+    CUpnpSsdpMessage* msg = RUpnpSsdpMessageFactory::SearchL( aTarget );
+    CleanupStack::PushL( msg );
+    msg->AddMxL(aMaximumWaitTime);
+    
+    HBufC8* str = HBufC8::NewLC( KMaxSsdpMessageLength );
+    
+    HBufC8* msgStr = ( ( CUpnpSsdpMessage* ) msg )->ToStringL();
+    CleanupStack::PushL( msgStr );
+    
+    str->Des().Append( *msgStr );
+    
+    CleanupStack::PopAndDestroy( msgStr );
+    
+    TInetAddr addr( KDefaultMulticastAddress, KDefaultMulticastPort );
+    
+    SendL( *str, addr );
+    
+    CleanupStack::PopAndDestroy( str );
+    CleanupStack::PopAndDestroy( msg );
+    }
+
+// -----------------------------------------------------------------------------
+// CUpnpSsdpServer::SendAdvertiseAliveL
+//
+// -----------------------------------------------------------------------------
+//
+void CUpnpSsdpServer::SendAdvertiseAliveL( TDesC8& aNt, TDesC8& aUsn, TDesC8& aLoc )
+    {
+    TInetAddr addr( KDefaultMulticastAddress, KDefaultMulticastPort );
+    
+    CUpnpSsdpMessage* msg = RUpnpSsdpMessageFactory::AdvertiseAliveL( 
+                                            aLoc, aNt, aUsn, *iServerDescription);
+    CleanupStack::PushL( msg );
+    HBufC8* str = msg->ToStringL();
+    CleanupStack::PushL( str );
+    
+    SendL( *str, addr );
+    
+    CleanupStack::PopAndDestroy( str );
+    str=NULL;
+    
+    CleanupStack::PopAndDestroy( msg );
+    msg=NULL;    
+    }
+
+// -----------------------------------------------------------------------------
+// CUpnpSsdpServer::SendAdvertiseByebyeL
+//
+// -----------------------------------------------------------------------------
+//
+void CUpnpSsdpServer::SendAdvertiseByebyeL( TDesC8& aNt, TDesC8& aUsn )
+    {
+    TInetAddr addr( KDefaultMulticastAddress, KDefaultMulticastPort );
+    
+    CUpnpSsdpMessage* msg = RUpnpSsdpMessageFactory::AdvertiseByebyeL( aNt, aUsn );
+    CleanupStack::PushL( msg );
+    HBufC8* str = msg->ToStringL();
+    CleanupStack::PushL( str );    
+    
+    SendL( *str, addr );
+    
+    CleanupStack::PopAndDestroy( str );
+    str=NULL;
+    
+    CleanupStack::PopAndDestroy( msg );
+    msg=NULL;
+    }
+
+// -----------------------------------------------------------------------------
+// CUpnpSsdpServer::SendResponseL
+//
+// -----------------------------------------------------------------------------
+//
+void CUpnpSsdpServer::SendResponseL( TInetAddr& aDest, 
+                                 TDesC8& aSt, 
+                                 TDesC8& aUsn, 
+                                 TDesC8& aLoc )
+    {
+    CUpnpSsdpMessage* msg = RUpnpSsdpMessageFactory::ResponseL( 
+                                        aSt, aUsn, aLoc, *iServerDescription );
+    CleanupStack::PushL( msg );
+    HBufC8* str = msg->ToStringL();
+    CleanupStack::PushL( str );
+    
+    SendL( *str, aDest );
+    
+    CleanupStack::PopAndDestroy( str );
+    str=NULL;
+    
+    CleanupStack::PopAndDestroy( msg );
+    msg=NULL;    
+    }
+
+// -----------------------------------------------------------------------------
+// CUpnpSsdpServer::SingleDeviceAdvertiseAliveL
+//
+// -----------------------------------------------------------------------------
+//
+void CUpnpSsdpServer::SingleDeviceAdvertiseAliveL( CUpnpDeviceLibraryElement& aDev )
+    {
+    HBufC8* nt=NULL;
+    HBufC8* usn=NULL;
+    HBufC8* loc=NULL;
+    
+    loc=HBufC8::NewLC( aDev.DescriptionUrl().Length() );
+    loc->Des().Zero();
+    loc->Des().Append( aDev.DescriptionUrl() );
+    
+    CDesC8Array* services = &aDev.ServiceList();
+    
+    if ( aDev.IsRootDevice() )
+        {
+        
+        nt = HBufC8::NewLC( KUPnPRootDevice().Length() );
+        nt->Des().Zero();
+        nt->Des().Append( KUPnPRootDevice() );
+        
+        usn = HBufC8::NewLC( KUPnPUuid().Length()
+            + aDev.UUID().Length()
+            + KDblColon().Length()
+            + KUPnPRootDevice().Length() );
+
+        usn->Des().Zero();
+        usn->Des().Append( KUPnPUuid() );
+        usn->Des().Append( aDev.UUID() );
+        usn->Des().Append( KDblColon() );
+        usn->Des().Append( KUPnPRootDevice() );
+        
+        SendAdvertiseAliveL( *nt, *usn, *loc );
+        
+        CleanupStack::PopAndDestroy( usn );
+        usn = NULL;
+        
+        CleanupStack::PopAndDestroy( nt );
+        nt = NULL;
+        }
+    
+    nt=HBufC8::NewLC( KUPnPUuid().Length() + aDev.UUID().Length() );
+    nt->Des().Zero();
+    nt->Des().Append( KUPnPUuid() );
+    nt->Des().Append( aDev.UUID() );
+    
+    usn=HBufC8::NewLC( KUPnPUuid().Length() + aDev.UUID().Length() );
+    usn->Des().Zero();
+    usn->Des().Append( KUPnPUuid() );
+    usn->Des().Append( aDev.UUID() );
+    
+    SendAdvertiseAliveL( *nt, *usn, *loc );
+    
+    CleanupStack::PopAndDestroy( usn );
+    usn = NULL;
+    
+    CleanupStack::PopAndDestroy( nt );
+    nt = NULL;
+    
+    nt = HBufC8::NewLC( aDev.DeviceType().Length() );
+
+    nt->Des().Zero();
+    nt->Des().Append( aDev.DeviceType() );
+    
+    usn = HBufC8::NewLC( KUPnPUuid().Length()
+        + aDev.UUID().Length()
+        + KDblColon().Length()
+        + aDev.DeviceType().Length() );
+
+    usn->Des().Zero();
+    usn->Des().Append( KUPnPUuid() );
+    usn->Des().Append( aDev.UUID() );
+    usn->Des().Append( KDblColon() );
+    usn->Des().Append( aDev.DeviceType() );
+    
+    SendAdvertiseAliveL( *nt, *usn, *loc );
+    
+    CleanupStack::PopAndDestroy( usn );
+    usn = NULL;
+    
+    CleanupStack::PopAndDestroy( nt );
+    nt = NULL;
+    
+    if(!services)
+        {
+        return;
+        }
+    
+    TInt NumOfServices = services->Count();
+    
+    TInt i = 0;
+    
+    for( i = 0; i < NumOfServices; i++ )
+        {
+        
+        nt = HBufC8::NewLC( KUPnPServiceSchema().Length()
+            + (*services)[i].Length() );
+
+        nt->Des().Zero();
+        nt->Des().Append( KUPnPServiceSchema() );
+        nt->Des().Append( (*services)[i] );
+        
+        usn=HBufC8::NewLC( KUPnPUuid().Length()
+            + aDev.UUID().Length()
+            + KDblColon().Length()
+            + KUPnPServiceSchema().Length()
+            + (*services)[i].Length() );
+
+        usn->Des().Zero();
+        usn->Des().Append( KUPnPUuid() );
+        usn->Des().Append( aDev.UUID() );
+        usn->Des().Append( KDblColon() );
+        usn->Des().Append( KUPnPServiceSchema() );
+        usn->Des().Append( (*services)[i] );
+        
+        SendAdvertiseAliveL( *nt, *usn, *loc );
+        
+        CleanupStack::PopAndDestroy( usn );
+        usn = NULL;
+        
+        CleanupStack::PopAndDestroy( nt );
+        nt = NULL;
+        }
+    
+    CleanupStack::PopAndDestroy( loc );
+    loc = NULL;
+    }
+
+// -----------------------------------------------------------------------------
+// CUpnpSsdpServer::SingleDeviceAdvertiseByebyeL
+//
+// -----------------------------------------------------------------------------
+//
+void CUpnpSsdpServer::SingleDeviceAdvertiseByebyeL(CUpnpDeviceLibraryElement& aDev)
+    {
+    HBufC8* nt=NULL;
+    HBufC8* usn=NULL;
+    
+    CDesC8Array* services = &aDev.ServiceList();
+    
+    if (aDev.IsRootDevice())
+        {
+        nt=HBufC8::NewLC(KUPnPRootDevice().Length());
+        nt->Des().Copy(KUPnPRootDevice());
+        
+        usn=HBufC8::NewLC(KUPnPUuid().Length()
+            +aDev.UUID().Length()
+            +UpnpString::KDblColon().Length()
+            +KUPnPRootDevice().Length());
+
+        usn->Des().Zero();
+        usn->Des().Append(KUPnPUuid());
+        usn->Des().Append(aDev.UUID());
+        usn->Des().Append(UpnpString::KDblColon());
+        usn->Des().Append(KUPnPRootDevice());
+        
+        SendAdvertiseByebyeL(*nt, *usn);
+        
+        CleanupStack::PopAndDestroy(usn); 
+        usn=NULL;
+        
+        CleanupStack::PopAndDestroy(nt);
+        nt=NULL;
+        }
+    
+    nt=HBufC8::NewLC(KUPnPUuid().Length()+aDev.UUID().Length());
+    nt->Des().Zero();
+    nt->Des().Append(KUPnPUuid());
+    nt->Des().Append(aDev.UUID());
+    
+    usn=HBufC8::NewLC(KUPnPUuid().Length()+aDev.UUID().Length());
+    usn->Des().Zero();
+    usn->Des().Append(KUPnPUuid());
+    usn->Des().Append(aDev.UUID());
+    
+    
+    SendAdvertiseByebyeL(*nt, *usn);
+    
+    
+    CleanupStack::PopAndDestroy(usn);
+    usn=NULL;
+    
+    CleanupStack::PopAndDestroy(nt);
+    nt=NULL;
+    
+    nt=HBufC8::NewLC(aDev.DeviceType().Length());
+
+    nt->Des().Zero();
+    nt->Des().Append(aDev.DeviceType());    
+    
+    usn=HBufC8::NewLC(KUPnPUuid().Length()
+        +aDev.UUID().Length()
+        +UpnpString::KDblColon().Length()
+        +aDev.DeviceType().Length());
+
+    usn->Des().Zero();
+    usn->Des().Append(KUPnPUuid());
+    usn->Des().Append(aDev.UUID());
+    usn->Des().Append(UpnpString::KDblColon());
+    usn->Des().Append(aDev.DeviceType());
+    
+    
+    SendAdvertiseByebyeL(*nt, *usn);
+    
+    
+    CleanupStack::PopAndDestroy(usn);
+    usn=NULL;
+    
+    CleanupStack::PopAndDestroy(nt); 
+    nt=NULL;
+    
+    TInt i=0;
+    
+    if(!services)
+        {
+        return;
+        }
+    
+    TInt NumOfServices=services->Count();
+    
+    for(i=0; i<NumOfServices; i++)
+        {
+        
+        nt=HBufC8::NewLC(KUPnPServiceSchema().Length()
+            +(*services)[i].Length());
+
+        nt->Des().Zero();
+        nt->Des().Append(KUPnPServiceSchema());
+        nt->Des().Append((*services)[i]);
+        
+        usn=HBufC8::NewLC(KUPnPUuid().Length()
+            +aDev.UUID().Length()
+            +UpnpString::KDblColon().Length()
+            +KUPnPServiceSchema().Length()
+            +(*services)[i].Length());
+
+        usn->Des().Zero();
+        usn->Des().Append(KUPnPUuid());
+        usn->Des().Append(aDev.UUID());
+        usn->Des().Append(UpnpString::KDblColon());
+        usn->Des().Append(KUPnPServiceSchema());
+        usn->Des().Append((*services)[i]);
+        
+        
+        SendAdvertiseByebyeL(*nt, *usn);
+        
+        
+        CleanupStack::PopAndDestroy(usn);
+        usn=NULL;
+        
+        CleanupStack::PopAndDestroy(nt);
+        nt=NULL;
+        }
+    }
+
+// -----------------------------------------------------------------------------
+// CUpnpSsdpServer::SingleServiceResponseL
+//
+// -----------------------------------------------------------------------------
+//
+void CUpnpSsdpServer::SingleServiceResponseL( CUpnpDeviceLibraryElement* aDevice, 
+                                          const TDesC8& aServiceType, 
+                                          CUpnpSsdpMessage* aMsg )
+    {
+    if ( !aDevice || !aMsg  )
+        {
+        return;
+        }
+    // name buffers
+    HBufC8* nt=NULL;
+    HBufC8* usn=NULL;
+    HBufC8* loc=NULL;
+    
+    // set location buffer to point to the 
+    // service description file of this service
+    // e.g. loc = 192.168.100.2/mediaserver/desc.xml
+    
+    loc=HBufC8::NewLC(aDevice->DescriptionUrl().Length());
+    loc->Des().Zero();
+    loc->Des().Append(aDevice->DescriptionUrl());
+    
+
+    // separate different search targets
+    switch(aMsg->SearchTarget())
+        {
+        case CUpnpSsdpMessage::ESsdpNone:
+            
+            break;
+            
+        case CUpnpSsdpMessage::ESsdpAll:
+            // In case of Ssdp:all search, 
+            // every service should send a device uuid response
+            
+            // 1. service type response
+            /*
+            NT:     urn:schemas-upnp-org:service:serviceType:v
+            USN:     uuid:device-UUID::urn:schemas-upnp-org:service:serviceType:v
+            */
+            
+            // nt = urn:schemas-upnp-org:service:serviceType:v
+             nt = HBufC8::NewLC( KUPnPServiceSchema().Length() +
+                                 aServiceType.Length() );
+            nt->Des().Zero();
+            nt->Des().Append(KUPnPServiceSchema());
+            nt->Des().Append(aServiceType);
+            
+            // usn = uuid:device-UUID::urn:schemas-upnp
+            // -org:service:serviceType:v
+            
+            usn=HBufC8::NewLC(KUPnPUuid().Length()
+                +aDevice->UUID().Length()
+                +UpnpString::KDblColon().Length()
+                +KUPnPServiceSchema().Length()
+                +aServiceType.Length());
+
+            usn->Des().Zero();
+            usn->Des().Append(KUPnPUuid());
+            usn->Des().Append(aDevice->UUID());
+            usn->Des().Append(UpnpString::KDblColon());
+            usn->Des().Append(KUPnPServiceSchema());
+            usn->Des().Append(aServiceType);    
+            
+            // send response to sender
+            SendResponseL(aMsg->Sender() ,*nt, *usn, *loc);
+            
+            CleanupStack::PopAndDestroy(usn);
+            usn=NULL;
+            
+            CleanupStack::PopAndDestroy(nt);
+            nt=NULL;
+            
+            break;
+            
+        case CUpnpSsdpMessage::EUPnPRootDevice:
+            
+            break;
+            
+        case CUpnpSsdpMessage::EDeviceUid:
+            
+            break;
+            
+        case CUpnpSsdpMessage::EDeviceType:
+            
+            break;
+            
+        case CUpnpSsdpMessage::EServiceType:
+            {
+            /*
+            NT:     urn:schemas-upnp-org:service:serviceType:v
+            USN:     uuid:device-UUID::urn:schemas-upnp-
+                         org:service:serviceType:v
+            */
+                
+             // nt = urn:schemas-upnp-org:service:serviceType:v
+             nt = HBufC8::NewLC( KUPnPServiceSchema().Length() + 
+                                    aServiceType.Length());
+
+             nt->Des().Zero();
+             nt->Des().Append(KUPnPServiceSchema());
+             nt->Des().Append(aServiceType);
+            
+            if (aMsg->St().Compare(*nt) == 0)
+                {
+                
+                // usn = uuid:device-UUID::urn:schemas-upnp
+                //       -org:service:serviceType:v
+                usn=HBufC8::NewLC(KUPnPUuid().Length()
+                    +aDevice->UUID().Length()
+                    +UpnpString::KDblColon().Length()
+                    +KUPnPServiceSchema().Length()
+                    +aServiceType.Length());
+
+                usn->Des().Zero();
+                usn->Des().Append(KUPnPUuid());
+                usn->Des().Append(aDevice->UUID());
+                usn->Des().Append(UpnpString::KDblColon());
+                usn->Des().Append(KUPnPServiceSchema());
+                usn->Des().Append(aServiceType);    
+                
+                
+                // send response to sender
+                SendResponseL(aMsg->Sender() ,*nt, *usn, *loc);
+                
+                
+                CleanupStack::PopAndDestroy(usn);
+                usn=NULL;
+                
+                
+                }        
+            
+            CleanupStack::PopAndDestroy(nt);
+            nt=NULL;
+            }
+            break;
+        default:
+            
+            break;
+        }
+        
+        CleanupStack::PopAndDestroy(loc);
+        loc=NULL;
+    }
+
+// -----------------------------------------------------------------------------
+// CUpnpSsdpServer::SingleDeviceResponseL
+//
+// -----------------------------------------------------------------------------
+//
+void CUpnpSsdpServer::SingleDeviceResponseL( CUpnpDeviceLibraryElement* aDevice, 
+                                         CUpnpSsdpMessage* aMsg )
+    {
+    if ( !aDevice || !aMsg )
+        {
+        return;
+        }
+    
+    // name buffers
+    HBufC8* nt=NULL;
+    HBufC8* usn=NULL;
+    HBufC8* loc=NULL;
+    
+    // format location buffer to point 
+    // to the device description file of this device
+    
+    loc=HBufC8::NewLC(aDevice->DescriptionUrl().Length());
+    loc->Des().Zero();
+    loc->Des().Append(aDevice->DescriptionUrl());
+    
+    // separate different search targets
+    switch( aMsg->SearchTarget() )
+        {
+        case CUpnpSsdpMessage::ESsdpNone:
+            
+            
+            break;
+            
+        case CUpnpSsdpMessage::ESsdpAll:
+            // In case of Ssdp:all search, every device should 
+            // send following responses:
+            // 1. if a root device, a root device response
+            // 2. a device uuid response
+            // 3. a device type response
+            
+            //************************
+            // 1. root device response        
+            /*
+            NT:     upnp:rootdevice
+            USN:     uuid:device-UUID::upnp:rootdevice
+            */
+            // if a root device
+            if (aDevice->IsRootDevice())
+                {
+                
+                
+                nt=HBufC8::NewLC(KUPnPRootDevice().Length());
+                nt->Des().Zero();
+                nt->Des().Append(KUPnPRootDevice());
+                
+                // nt = upnp:rootdevice
+                
+                // usn = uuid:device-UUID::upnp:rootdevice
+                
+                usn=HBufC8::NewLC(KUPnPUuid().Length()
+                    +aDevice->UUID().Length()
+                    +UpnpString::KDblColon().Length()
+                    +KUPnPRootDevice().Length());
+
+                usn->Des().Zero();
+                usn->Des().Append(KUPnPUuid());
+                usn->Des().Append(aDevice->UUID());
+                usn->Des().Append(UpnpString::KDblColon());
+                usn->Des().Append(KUPnPRootDevice());
+                
+                // send response to sender
+                SendResponseL(aMsg->Sender(), *nt, *usn, *loc);
+                
+                CleanupStack::PopAndDestroy(usn);
+                usn=NULL;
+                
+                CleanupStack::PopAndDestroy(nt);
+                nt=NULL;
+                }
+            
+            
+            //************************
+            // 2. device uuid response
+            /*
+            NT:     uuid:device-UUID
+            USN:     uuid:device-UUID
+            */
+            
+            nt=HBufC8::NewLC(KUPnPUuid().Length()+aDevice->UUID().Length());
+            nt->Des().Zero();
+            nt->Des().Append(KUPnPUuid());
+            nt->Des().Append(aDevice->UUID());
+            
+            // nt = uuid:device-UUID
+            
+            // usn = uuid:device-UUID
+            
+            usn=HBufC8::NewLC(KUPnPUuid().Length()+aDevice->UUID().Length());
+            usn->Des().Zero();
+            usn->Des().Append(KUPnPUuid());
+            usn->Des().Append(aDevice->UUID());
+            
+            // send response to sender
+            SendResponseL(aMsg->Sender(), *nt, *usn, *loc);
+            
+            CleanupStack::PopAndDestroy(usn);
+            usn=NULL;
+            
+            CleanupStack::PopAndDestroy(nt);
+            nt=NULL;
+            
+            
+            //************************
+            // 3. device type response
+            /*
+            NT:     urn:schemas-upnp-org:device:deviceType:v
+            USN:     uuid:device-UUID::urn:schemas-upnp-org:device:deviceType:v
+            */
+            
+            nt=HBufC8::NewLC(aDevice->DeviceType().Length());
+
+            nt->Des().Zero();
+            nt->Des().Append(aDevice->DeviceType());
+            
+            // nt = urn:schemas-upnp-org:device:deviceType:v
+            
+            // usn = uuid:device-UUID::urn:schemas-upnp-org:device:deviceType:v
+            
+            usn=HBufC8::NewLC(KUPnPUuid().Length()
+                +aDevice->UUID().Length()
+                +UpnpString::KDblColon().Length()
+                +aDevice->DeviceType().Length());
+
+            usn->Des().Zero();
+            usn->Des().Append(KUPnPUuid());
+            usn->Des().Append(aDevice->UUID());
+            usn->Des().Append(UpnpString::KDblColon());
+            usn->Des().Append(aDevice->DeviceType());
+            
+            // send response to sender
+            SendResponseL(aMsg->Sender(), *nt, *usn, *loc);
+            
+            
+            CleanupStack::PopAndDestroy(usn);
+            usn=NULL;
+            
+            CleanupStack::PopAndDestroy(nt);
+            nt=NULL;
+            
+            
+            break;
+            
+        case CUpnpSsdpMessage::EUPnPRootDevice:
+            // if the search is done for only root devices, 
+            // every root device should answer with a root device response
+            
+            //************************
+            // 1. root device response        
+            /*
+            NT:     upnp:rootdevice
+            USN:     uuid:device-UUID::upnp:rootdevice
+            */
+            // if device is a root device
+            if (aDevice->IsRootDevice())
+                {
+                
+                nt=HBufC8::NewLC(KUPnPRootDevice().Length());
+                nt->Des().Zero();
+                nt->Des().Append(KUPnPRootDevice());
+                
+                usn=HBufC8::NewLC(KUPnPUuid().Length()
+                    +aDevice->UUID().Length()
+                    +UpnpString::KDblColon().Length()
+                    +KUPnPRootDevice().Length());
+
+                usn->Des().Zero();
+                usn->Des().Append(KUPnPUuid());
+                usn->Des().Append(aDevice->UUID());
+                usn->Des().Append(UpnpString::KDblColon());
+                usn->Des().Append(KUPnPRootDevice());
+                
+                // send response to sender
+                SendResponseL(aMsg->Sender(), *nt, *usn, *loc);
+                
+                CleanupStack::PopAndDestroy(usn);
+                usn=NULL;
+                
+                CleanupStack::PopAndDestroy(nt); 
+                nt=NULL;
+                }
+            
+            
+            break;
+            
+        case CUpnpSsdpMessage::EDeviceUid:
+            {
+            // if the search is done for only devices with specific uuid,
+            // response if the uuids match
+            
+            //************************
+            // 2. device uuid response
+            /*
+            NT:     uuid:device-UUID
+            USN:     uuid:device-UUID
+            */
+            
+            // nt = uuid:device-UUID
+            nt=HBufC8::NewLC(KUPnPUuid().Length()
+                    +aDevice->UUID().Length());
+
+            nt->Des().Zero();
+            nt->Des().Append(KUPnPUuid());
+            nt->Des().Append(aDevice->UUID());
+            
+            
+            // if device uuids match
+            if (aMsg->St().Compare(*nt) == 0)
+                {
+
+                usn=HBufC8::NewLC(KUPnPUuid().Length()
+                    +aDevice->UUID().Length());
+
+                usn->Des().Zero();
+                usn->Des().Append(KUPnPUuid());
+                usn->Des().Append(aDevice->UUID());
+                
+                // send response to sender
+                SendResponseL(aMsg->Sender(), *nt, *usn, *loc);
+                
+                CleanupStack::PopAndDestroy(usn);
+                usn=NULL;
+                
+                
+                }
+                CleanupStack::PopAndDestroy(nt);
+                nt=NULL;
+            
+            }
+            break;
+            
+        case CUpnpSsdpMessage::EDeviceType:
+            {
+            // if the search is done for only devices of specific type,
+            // response if types match
+            
+            //************************
+            // 3. device type response
+            /*
+            NT:     urn:schemas-upnp-org:device:deviceType:v
+            USN:     uuid:device-UUID::urn:schemas-upnp-org:device:deviceType:v
+            */
+                        
+            // nt = urn:schemas-upnp-org:device:deviceType:v                
+             nt=HBufC8::NewLC(aDevice->DeviceType().Length());
+
+             nt->Des().Zero();
+             nt->Des().Append(aDevice->DeviceType());
+            
+            // if device types match
+            if (aMsg->St().Compare(*nt) == 0)
+                {         
+                
+                // usn = uuid:device-UUID::urn:schemas-upnp-org:device:deviceType:v                
+                usn=HBufC8::NewLC(KUPnPUuid().Length()
+                    +aDevice->UUID().Length()
+                    +KDblColon().Length()
+                    +aDevice->DeviceType().Length());
+
+                usn->Des().Zero();
+                usn->Des().Append(KUPnPUuid());
+                usn->Des().Append(aDevice->UUID());
+                usn->Des().Append(KDblColon());
+                usn->Des().Append(aDevice->DeviceType());
+                
+                // send response to sender
+                SendResponseL(aMsg->Sender(), *nt, *usn, *loc);
+                
+                CleanupStack::PopAndDestroy(usn);
+                usn=NULL;
+                
+                
+                }
+                CleanupStack::PopAndDestroy(nt);
+                nt=NULL;
+
+            
+            }
+            break;
+            
+        case CUpnpSsdpMessage::EServiceType:
+            // devices do not answer if searching services
+            
+            break;
+        default:
+            
+            break;
+        }
+        
+    CleanupStack::PopAndDestroy( loc );
+    loc = NULL;
+    }
+
+// -----------------------------------------------------------------------------
+// CUpnpSsdpServer::ResponseL
+//
+// -----------------------------------------------------------------------------
+//
+void CUpnpSsdpServer::ResponseL(CUpnpSsdpMessage* aMsg)
+    {
+    if ( !aMsg )
+        {
+        return;
+        }
+    
+    // a search message is received
+    // seek for devices and services matching to the search
+    
+    // get device list from message handler
+    RPointerArray<CUpnpDeviceLibraryElement>& devs 
+        = iSsdpServerObserver->DeviceList();
+   
+
+    TInt devCount=0;
+     // get number of devices
+    devCount=devs.Count();
+    
+    TInt j=0;
+    
+    for(j=0;j<devCount;j++)
+        {
+        CUpnpDeviceLibraryElement* dev = (CUpnpDeviceLibraryElement*) devs[j];
+        
+        if (dev->Local())
+            {
+            // for every device
+            // make this device respond if needed
+            SingleDeviceResponseL(dev, aMsg);
+            // get the service list of this device
+            CDesC8Array* services = &dev->ServiceList();
+            // get the first service
+            
+            for(TInt i=0; i<services->Count(); i++)
+                {
+                TPtrC8 serviceType = (*services)[i];
+                SingleServiceResponseL(dev, serviceType, aMsg);
+                }
+            }
+        }
+    }
+
+//  End of File