diff -r 000000000000 -r f5a58ecadc66 upnp/upnpstack/ssdpserver/src/upnpssdpserver.cpp --- /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 +#include +#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 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; iDes().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& devs + = iSsdpServerObserver->DeviceList(); + + + TInt devCount=0; + // get number of devices + devCount=devs.Count(); + + TInt j=0; + + for(j=0;jLocal()) + { + // 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; iCount(); i++) + { + TPtrC8 serviceType = (*services)[i]; + SingleServiceResponseL(dev, serviceType, aMsg); + } + } + } + } + +// End of File