⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 ssdp_device.c

📁 原来由英特尔制定的UPnP SDK的
💻 C
📖 第 1 页 / 共 2 页
字号:
/////////////////////////////////////////////////////////////////////////////// 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"#ifdef INCLUDE_DEVICE_APIS#if EXCLUDE_SSDP == 0#include <assert.h>#include <stdio.h>#include <string.h>#include "ssdplib.h"#include "upnpapi.h"#include "ThreadPool.h"#include "httpparser.h"#include "httpreadwrite.h"#include "statcodes.h"#include "unixutil.h"#ifdef WIN32	#include <ws2tcpip.h>	#include <winsock2.h>#endif /* WIN32 */#define MSGTYPE_SHUTDOWN	0#define MSGTYPE_ADVERTISEMENT	1#define MSGTYPE_REPLY		2/************************************************************************* Function : advertiseAndReplyThread** Parameters:*	IN void *data: Structure containing the search request** Description:*	This function is a wrapper function to reply the search request*	coming from the control point.** Returns: void **	always return NULL***************************************************************************/void *advertiseAndReplyThread( IN void *data ){    SsdpSearchReply *arg = ( SsdpSearchReply * ) data;    AdvertiseAndReply( 0, arg->handle,                       arg->event.RequestType,                       &arg->dest_addr,                       arg->event.DeviceType,                       arg->event.UDN,                       arg->event.ServiceType, arg->MaxAge );    free( arg );    return NULL;}/************************************************************************* Function : ssdp_handle_device_request** Parameters:*	IN http_message_t* hmsg: SSDP search request from the control point*	IN struct sockaddr_in* dest_addr: The address info of control point** Description:*	This function handles the search request. It do the sanity checks of*	the request and then schedules a thread to send a random time reply (*	random within maximum time given by the control point to reply).** Returns: void **	1 if successful else appropriate error***************************************************************************/#ifdef INCLUDE_DEVICE_APISvoidssdp_handle_device_request( IN http_message_t * hmsg,                            IN struct sockaddr_in *dest_addr ){#define MX_FUDGE_FACTOR 10    int handle;    struct Handle_Info *dev_info = NULL;    memptr hdr_value;    int mx;    char save_char;    SsdpEvent event;    int ret_code;    SsdpSearchReply *threadArg = NULL;    ThreadPoolJob job;    int replyTime;    int maxAge;    // check man hdr    if( httpmsg_find_hdr( hmsg, HDR_MAN, &hdr_value ) == NULL ||        memptr_cmp( &hdr_value, "\"ssdp:discover\"" ) != 0 ) {        return;                 // bad or missing hdr    }    // MX header    if( httpmsg_find_hdr( hmsg, HDR_MX, &hdr_value ) == NULL ||        ( mx = raw_to_int( &hdr_value, 10 ) ) < 0 ) {        return;    }    // ST header    if( httpmsg_find_hdr( hmsg, HDR_ST, &hdr_value ) == NULL ) {        return;    }    save_char = hdr_value.buf[hdr_value.length];    hdr_value.buf[hdr_value.length] = '\0';    ret_code = ssdp_request_type( hdr_value.buf, &event );    hdr_value.buf[hdr_value.length] = save_char;    // restore    if( ret_code == -1 ) {        return;                 // bad ST header    }    HandleLock();    // device info    if( GetDeviceHandleInfo( &handle, &dev_info ) != HND_DEVICE ) {        HandleUnlock();        return;                 // no info found    }    maxAge = dev_info->MaxAge;    HandleUnlock();    UpnpPrintf( UPNP_PACKET, API, __FILE__, __LINE__,        "ssdp_handle_device_request with Cmd %d SEARCH\n",        event.Cmd );    UpnpPrintf( UPNP_PACKET, API, __FILE__, __LINE__,        "MAX-AGE     =  %d\n", maxAge );    UpnpPrintf( UPNP_PACKET, API, __FILE__, __LINE__,        "MX     =  %d\n", event.Mx );    UpnpPrintf( UPNP_PACKET, API, __FILE__, __LINE__,        "DeviceType   =  %s\n", event.DeviceType );    UpnpPrintf( UPNP_PACKET, API, __FILE__, __LINE__,        "DeviceUuid   =  %s\n", event.UDN );    UpnpPrintf( UPNP_PACKET, API, __FILE__, __LINE__,        "ServiceType =  %s\n", event.ServiceType );    threadArg =        ( SsdpSearchReply * ) malloc( sizeof( SsdpSearchReply ) );    if( threadArg == NULL ) {        return;    }    threadArg->handle = handle;    threadArg->dest_addr = ( *dest_addr );    threadArg->event = event;    threadArg->MaxAge = maxAge;    TPJobInit( &job, advertiseAndReplyThread, threadArg );    TPJobSetFreeFunction( &job, ( free_routine ) free );    //Subtract a percentage from the mx    //to allow for network and processing delays    // (i.e. if search is for 30 seconds,     //       respond withing 0 - 27 seconds)    if( mx >= 2 ) {        mx -= MAXVAL( 1, mx / MX_FUDGE_FACTOR );    }    if( mx < 1 ) {        mx = 1;    }    replyTime = rand() % mx;    TimerThreadSchedule( &gTimerThread, replyTime, REL_SEC, &job,                         SHORT_TERM, NULL );}#endif/************************************************************************* Function : NewRequestHandler** Parameters:*		IN struct sockaddr_in * DestAddr: Ip address, to send the reply.*		IN int NumPacket: Number of packet to be sent.*		IN char **RqPacket:Number of packet to be sent.** Description:*	This function works as a request handler which passes the HTTP*	request string to multicast channel then** Returns: void **	1 if successful else appropriate error***************************************************************************/static intNewRequestHandler( IN struct sockaddr_in *DestAddr,                   IN int NumPacket,                   IN char **RqPacket ){    char errorBuffer[ERROR_BUFFER_LEN];    int ReplySock;    int socklen = sizeof( struct sockaddr_in );    int NumCopy;    int Index;    unsigned long replyAddr = inet_addr( LOCAL_HOST );    int ttl = 4; // a/c to UPNP Spec    ReplySock = socket( AF_INET, SOCK_DGRAM, 0 );    if ( ReplySock == -1 ) {        strerror_r(errno, errorBuffer, ERROR_BUFFER_LEN);        UpnpPrintf( UPNP_INFO, SSDP, __FILE__, __LINE__,            "SSDP_LIB: New Request Handler:"            "Error in socket(): %s\n", errorBuffer );        return UPNP_E_OUTOF_SOCKET;    }    setsockopt( ReplySock, IPPROTO_IP, IP_MULTICAST_IF,        (char *)&replyAddr, sizeof (replyAddr) );    setsockopt( ReplySock, IPPROTO_IP, IP_MULTICAST_TTL,        (char *)&ttl, sizeof (int) );    for( Index = 0; Index < NumPacket; Index++ ) {        int rc;        // The reason to keep this loop is purely historical/documentation,        // according to section 9.2 of HTTPU spec:        //         // "If a multicast resource would send a response(s) to any copy of the         //  request, it SHOULD send its response(s) to each copy of the request         //  it receives. It MUST NOT repeat its response(s) per copy of the         //  request."        //          // http://www.upnp.org/download/draft-goland-http-udp-04.txt        //        // So, NUM_COPY has been changed from 2 to 1.        NumCopy = 0;        while( NumCopy < NUM_COPY ) {            UpnpPrintf( UPNP_INFO, SSDP, __FILE__, __LINE__,                ">>> SSDP SEND >>>\n%s\n",                *( RqPacket + Index ) );            rc = sendto( ReplySock, *( RqPacket + Index ),                         strlen( *( RqPacket + Index ) ),                         0, ( struct sockaddr * )DestAddr, socklen );            imillisleep( SSDP_PAUSE );            ++NumCopy;        }    }    shutdown( ReplySock, SD_BOTH );    UpnpCloseSocket( ReplySock );    return UPNP_E_SUCCESS;}/************************************************************************* Function : CreateServiceRequestPacket** Parameters:*	IN int msg_type : type of the message ( Search Reply, Advertisement*		or Shutdown )*	IN char * nt : ssdp type*	IN char * usn : unique service name ( go in the HTTP Header)*	IN char * location :Location URL.*	IN int  duration :Service duration in sec.*	OUT char** packet :Output buffer filled with HTTP statement.** Description:*	This function creates a HTTP request packet.  Depending*	on the input parameter it either creates a service advertisement*	request or service shutdown request etc.** Returns: void****************************************************************************/voidCreateServicePacket( IN int msg_type,                     IN char *nt,                     IN char *usn,                     IN char *location,                     IN int duration,                     OUT char **packet ){    int ret_code;    char *nts;    membuffer buf;    //Notf=0 means service shutdown,     //Notf=1 means service advertisement, Notf =2 means reply       membuffer_init( &buf );    buf.size_inc = 30;    *packet = NULL;    if( msg_type == MSGTYPE_REPLY ) {        ret_code = http_MakeMessage(            &buf, 1, 1,            "R" "sdc" "D" "sc" "ssc" "S" "Xc" "ssc" "sscc",            HTTP_OK,            "CACHE-CONTROL: max-age=", duration,	    "EXT:",            "LOCATION: ", location,            X_USER_AGENT,            "ST: ", nt,            "USN: ", usn);        if( ret_code != 0 ) {            return;        }    } else if( msg_type == MSGTYPE_ADVERTISEMENT ||               msg_type == MSGTYPE_SHUTDOWN ) {        if( msg_type == MSGTYPE_ADVERTISEMENT ) {            nts = "ssdp:alive";        } else                  // shutdown        {            nts = "ssdp:byebye";        }        // NOTE: The CACHE-CONTROL and LOCATION headers are not present in        //  a shutdown msg, but are present here for MS WinMe interop.                ret_code = http_MakeMessage(            &buf, 1, 1,            "Q" "sssdc" "sdc" "ssc" "ssc" "ssc" "S" "Xc" "sscc",            HTTPMETHOD_NOTIFY, "*", (size_t)1,            "HOST: ", SSDP_IP, ":", SSDP_PORT,            "CACHE-CONTROL: max-age=", duration,            "LOCATION: ", location,            "NT: ", nt,            "NTS: ", nts,            X_USER_AGENT,            "USN: ", usn );        if( ret_code != 0 ) {            return;        }    } else {        assert( 0 );            // unknown msg    }    *packet = membuffer_detach( &buf ); // return msg    membuffer_destroy( &buf );    return;}/************************************************************************* Function : DeviceAdvertisement** Parameters:*	IN char * DevType : type of the device*	IN int RootDev: flag to indicate if the device is root device*	IN char * nt : ssdp type*	IN char * usn : unique service name*	IN char * location :Location URL.*	IN int  duration :Service duration in sec.** Description:*	This function creates the device advertisement request based on *	the input parameter, and send it to the multicast channel.** Returns: int*	UPNP_E_SUCCESS if successful else appropriate error***************************************************************************/intDeviceAdvertisement( IN char *DevType,                     int RootDev,                     char *Udn,                     IN char *Location,                     IN int Duration ){    struct sockaddr_in DestAddr;    //char Mil_Nt[LINE_SIZE]    char Mil_Usn[LINE_SIZE];    char *msgs[3];    int ret_code;    UpnpPrintf( UPNP_INFO, SSDP, __FILE__, __LINE__,        "In function SendDeviceAdvertisemenrt\n" );    DestAddr.sin_family = AF_INET;    DestAddr.sin_addr.s_addr = inet_addr( SSDP_IP );    DestAddr.sin_port = htons( SSDP_PORT );    msgs[0] = NULL;    msgs[1] = NULL;    msgs[2] = NULL;    //If deviceis a root device , here we need to     //send 3 advertisement or reply    if( RootDev ) {        sprintf( Mil_Usn, "%s::upnp:rootdevice", Udn );

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -