📄 ssdp_server.c
字号:
///////////////////////////////////////////////////////////////////////////
//
// Copyright (c) 2000-2003 Intel Corporation
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are met:
//
// * Redistributions of source code must retain the above copyright notice,
// this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above copyright notice,
// this list of conditions and the following disclaimer in the documentation
// and/or other materials provided with the distribution.
// * Neither name of Intel Corporation nor the names of its contributors
// may be used to endorse or promote products derived from this software
// without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL INTEL OR
// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
// OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
///////////////////////////////////////////////////////////////////////////
#include "config.h"
#if EXCLUDE_SSDP == 0
#ifdef _WIN32
#define strcasecmp _stricmp
#endif
#ifdef _WIN32
#define strncasecmp strnicmp
#endif
#include "membuffer.h"
#include "ssdplib.h"
#include <stdio.h>
#include "ThreadPool.h"
#include "miniserver.h"
#ifdef _WIN32
#include <winsock2.h>
#include <Ws2tcpip.h>
#endif
#include "upnpapi.h"
#include "httpparser.h"
#include "httpreadwrite.h"
#define MAX_TIME_TOREAD 45
CLIENTONLY( SOCKET gSsdpReqSocket = 0;
)
void RequestHandler( );
Event ErrotEvt;
enum Listener { Idle, Stopping, Running };
unsigned short ssdpStopPort;
struct SSDPSockArray {
int ssdpSock; //socket for incoming advertisments and search requests
CLIENTONLY( int ssdpReqSock;
) //socket for sending search
//requests and receiving
// search replies
};
#ifdef INCLUDE_DEVICE_APIS
#if EXCLUDE_SSDP == 0
/************************************************************************
* Function : AdvertiseAndReply
*
* Parameters:
* IN int AdFlag: -1 = Send shutdown, 0 = send reply,
* 1 = Send Advertisement
* IN UpnpDevice_Handle Hnd: Device handle
* IN enum SsdpSearchType SearchType:Search type for sending replies
* IN struct sockaddr_in *DestAddr:Destination address
* IN char *DeviceType:Device type
* IN char *DeviceUDN:Device UDN
* IN char *ServiceType:Service type
* IN int Exp:Advertisement age
*
* Description:
* This function sends SSDP advertisements, replies and shutdown messages.
*
* Returns: int
* UPNP_E_SUCCESS if successful else appropriate error
***************************************************************************/
int AdvertiseAndReply( IN int AdFlag,
IN UpnpDevice_Handle Hnd,
IN enum SsdpSearchType SearchType,
IN struct sockaddr_in *DestAddr,
IN char *DeviceType,
IN char *DeviceUDN,
IN char *ServiceType,
int Exp )
{
int i,
j;
int defaultExp = DEFAULT_MAXAGE;
struct Handle_Info *SInfo = NULL;
char UDNstr[100],
devType[100],
servType[100];
IXML_NodeList *nodeList = NULL;
IXML_NodeList *tmpNodeList = NULL;
IXML_Node *tmpNode = NULL;
IXML_Node *tmpNode2 = NULL;
IXML_Node *textNode = NULL;
DOMString tmpStr;
char SERVER[200];
DBGONLY( const DOMString dbgStr;
UpnpPrintf( UPNP_ALL, API, __FILE__, __LINE__,
"Inside AdvertiseAndReply with AdFlag = %d\n",
AdFlag ); )
HandleLock( );
if( GetHandleInfo( Hnd, &SInfo ) != HND_DEVICE ) {
HandleUnlock( );
return UPNP_E_INVALID_HANDLE;
}
defaultExp = SInfo->MaxAge;
//Modifed to prevent more than one thread from accessing the
//UpnpDocument stored with the handle at the same time
// HandleUnlock();
nodeList = NULL;
//get server info
get_sdk_info( SERVER, 200 );
// parse the device list and send advertisements/replies
for( i = 0;; i++ ) {
DBGONLY( UpnpPrintf( UPNP_ALL, API, __FILE__, __LINE__,
"Entering new device list with i = %d\n\n",
i );
)
tmpNode = ixmlNodeList_item( SInfo->DeviceList, i );
if( tmpNode == NULL ) {
DBGONLY( UpnpPrintf( UPNP_ALL, API, __FILE__, __LINE__,
"Exiting new device list with i = %d\n\n",
i );
)
break;
}
DBGONLY( dbgStr = ixmlNode_getNodeName( tmpNode );
UpnpPrintf( UPNP_INFO, API, __FILE__, __LINE__,
"Extracting device type once for %s\n",
dbgStr ); )
// extract device type
ixmlNodeList_free( nodeList );
nodeList = NULL;
nodeList =
ixmlElement_getElementsByTagName( ( IXML_Element * ) tmpNode,
"deviceType" );
if( nodeList == NULL ) {
continue;
}
DBGONLY( dbgStr = ixmlNode_getNodeName( tmpNode );
UpnpPrintf( UPNP_ALL, API, __FILE__, __LINE__,
"Extracting UDN for %s\n", dbgStr ); )
DBGONLY( UpnpPrintf( UPNP_ALL, API, __FILE__, __LINE__,
"Extracting device type\n" );
)
tmpNode2 = ixmlNodeList_item( nodeList, 0 );
if( tmpNode2 == NULL ) {
continue;
}
textNode = ixmlNode_getFirstChild( tmpNode2 );
if( textNode == NULL ) {
continue;
}
DBGONLY( UpnpPrintf( UPNP_ALL, API, __FILE__, __LINE__,
"Extracting device type \n" );
)
tmpStr = ixmlNode_getNodeValue( textNode );
if( tmpStr == NULL ) {
continue;
}
strcpy( devType, tmpStr );
if( devType == NULL ) {
continue;
}
DBGONLY( UpnpPrintf( UPNP_ALL, API, __FILE__, __LINE__,
"Extracting device type = %s\n", devType );
if( tmpNode == NULL ) {
UpnpPrintf( UPNP_ALL, API, __FILE__, __LINE__,
"TempNode is NULL\n" );}
dbgStr = ixmlNode_getNodeName( tmpNode );
UpnpPrintf( UPNP_ALL, API, __FILE__, __LINE__,
"Extracting UDN for %s\n", dbgStr ); )
// extract UDN
ixmlNodeList_free( nodeList );
nodeList = NULL;
nodeList = ixmlElement_getElementsByTagName( ( IXML_Element * )
tmpNode, "UDN" );
if( nodeList == NULL ) {
DBGONLY( UpnpPrintf( UPNP_CRITICAL, API, __FILE__,
__LINE__, "UDN not found!!!\n" );
)
continue;
}
tmpNode2 = ixmlNodeList_item( nodeList, 0 );
if( tmpNode2 == NULL ) {
DBGONLY( UpnpPrintf( UPNP_CRITICAL, API, __FILE__,
__LINE__, "UDN not found!!!\n" );
)
continue;
}
textNode = ixmlNode_getFirstChild( tmpNode2 );
if( textNode == NULL ) {
DBGONLY( UpnpPrintf( UPNP_CRITICAL, API, __FILE__,
__LINE__, "UDN not found!!!\n" );
)
continue;
}
tmpStr = ixmlNode_getNodeValue( textNode );
if( tmpStr == NULL ) {
DBGONLY( UpnpPrintf( UPNP_CRITICAL, API, __FILE__, __LINE__,
"UDN not found!!!!\n" );
)
continue;
}
strcpy( UDNstr, tmpStr );
if( UDNstr == NULL ) {
continue;
}
DBGONLY( UpnpPrintf( UPNP_INFO, API, __FILE__, __LINE__,
"Sending UDNStr = %s \n", UDNstr );
)
if( AdFlag ) {
// send the device advertisement
if( AdFlag == 1 ) {
DeviceAdvertisement( devType, i == 0,
UDNstr, SInfo->DescURL, Exp );
} else // AdFlag == -1
{
//printf("performing device shutdown\n");
DeviceShutdown( devType, i == 0, UDNstr,
SERVER, SInfo->DescURL, Exp );
}
} else {
switch ( SearchType ) {
case SSDP_ALL:
DeviceReply( DestAddr,
devType, i == 0,
UDNstr, SInfo->DescURL, defaultExp );
break;
case SSDP_ROOTDEVICE:
if( i == 0 ) {
SendReply( DestAddr, devType, 1,
UDNstr, SInfo->DescURL, defaultExp, 0 );
}
break;
case SSDP_DEVICEUDN:
{
if( DeviceUDN != NULL && strlen( DeviceUDN ) != 0 ) {
if( strcasecmp( DeviceUDN, UDNstr ) ) {
DBGONLY( UpnpPrintf
( UPNP_INFO, API, __FILE__,
__LINE__,
"DeviceUDN=%s and search "
"UDN=%s did not match\n",
UDNstr, DeviceUDN );
)
break;
} else {
DBGONLY( UpnpPrintf
( UPNP_INFO, API, __FILE__,
__LINE__,
"DeviceUDN=%s and search "
"UDN=%s MATCH\n", UDNstr,
DeviceUDN );
)
SendReply( DestAddr, devType, 0,
UDNstr, SInfo->DescURL,
defaultExp, 0 );
break;
}
}
}
case SSDP_DEVICETYPE:
{
if( !strncasecmp
( DeviceType, devType,
strlen( DeviceType ) ) ) {
DBGONLY( UpnpPrintf
( UPNP_INFO, API, __FILE__, __LINE__,
"DeviceType=%s and search devType=%s MATCH\n",
devType, DeviceType );
)
SendReply( DestAddr, devType, 0, UDNstr,
SInfo->DescURL, defaultExp, 1 );
}
DBGONLY(
else
UpnpPrintf( UPNP_INFO, API, __FILE__,
__LINE__,
"DeviceType=%s and search devType=%s"
" DID NOT MATCH\n",
devType, DeviceType );
)
break;
}
default:
break;
}
}
// send service advertisements for services corresponding
// to the same device
DBGONLY( UpnpPrintf( UPNP_INFO, API, __FILE__, __LINE__,
"Sending service Advertisement\n" );
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -