diff --git a/upnp/inc/upnp.h b/upnp/inc/upnp.h index 0354ac6..57daf5a 100644 --- a/upnp/inc/upnp.h +++ b/upnp/inc/upnp.h @@ -1,3 +1,6 @@ +#ifndef UPNP_H +#define UPNP_H + /******************************************************************************* * * Copyright (c) 2000-2003 Intel Corporation @@ -29,11 +32,6 @@ * ******************************************************************************/ - -#ifndef UPNP_H -#define UPNP_H - - /*! * \file * @@ -42,13 +40,11 @@ * @{ */ - #include "ixml.h" #include "upnpconfig.h" #include "UpnpGlobal.h" #include "UpnpInet.h" - /* * \todo Document the exact reason of these include files and solve this * include mess in an include file like UpnpTime.h @@ -61,14 +57,12 @@ /* Other systems ??? */ #endif - #ifdef WIN32 /* Do not #include */ #else #include #endif - #define LINE_SIZE 180 #define NAME_SIZE 256 #define MNFT_NAME_SIZE 64 @@ -79,7 +73,6 @@ #define UPNP_USING_CHUNKED -3 #define UPNP_UNTIL_CLOSE -4 - /*! * \name Error codes * @@ -423,7 +416,6 @@ #include "SubscriptionRequest.h" #endif /* UPNP_VERSION >= 10800 */ - /*! * \name Constants and Types * diff --git a/upnp/src/genlib/net/http/httpreadwrite.c b/upnp/src/genlib/net/http/httpreadwrite.c index 17bd0b0..ad9cffa 100644 --- a/upnp/src/genlib/net/http/httpreadwrite.c +++ b/upnp/src/genlib/net/http/httpreadwrite.c @@ -60,7 +60,6 @@ #define fseeko fseek #else #include - #include #include #include #include @@ -84,78 +83,17 @@ const int CHUNK_TAIL_SIZE = 10; /* in seconds */ #define DEFAULT_TCP_CONNECT_TIMEOUT 5 -/************************************************************************ - * Function : Make_Socket_NoBlocking +/*! + * \brief Checks socket connection and wait if it is not connected. + * It should be called just after connect. * - * Parameters: - * IN int sock: socket - * - * Description: - * This function makes socket non-blocking. - * - * Returns: int - * 0 if successful else -1 - ***************************************************************************/ -static int Make_Socket_NoBlocking(SOCKET sock) -{ -#ifdef WIN32 - u_long val = 1; - return ioctlsocket(sock, FIONBIO, &val); -#else - int val; - - val = fcntl(sock, F_GETFL, 0); - if (fcntl(sock, F_SETFL, val | O_NONBLOCK) == -1) { - return -1; - } -#endif - return 0; -} - -/************************************************************************ - * Function : Make_Socket_Blocking - * - * Parameters: - * IN int sock: socket - * - * Description: - * This function makes socket blocking. - * - * Returns: int - * 0 if successful else -1 - ***************************************************************************/ -static int Make_Socket_Blocking(int sock) -{ -#ifdef WIN32 - u_long val = 0; - return ioctlsocket(sock, FIONBIO, &val); -#else - int val; - - val = fcntl(sock, F_GETFL, 0); - if (fcntl(sock, F_SETFL, val & ~O_NONBLOCK) == -1) { - return -1; - } -#endif - return 0; -} - - -/************************************************************************ - * Function : Check_Connect_And_Wait_Connection - * - * Parameters: - * IN int sock: socket - * IN int connect_res: result of connect - * - * Description: - * This function checks socket connection and wait if it is not connected - * It should be called just after connect - * - * Returns: int - * 0 if successful else -1 - ***************************************************************************/ -static int Check_Connect_And_Wait_Connection(int sock, int connect_res) + * \return 0 if successful, else -1. + */ +static int Check_Connect_And_Wait_Connection( + /*! [in] socket. */ + SOCKET sock, + /*! [in] result of connect. */ + int connect_res) { struct timeval tmvTimeout = {DEFAULT_TCP_CONNECT_TIMEOUT, 0}; int result; @@ -210,12 +148,12 @@ static int private_connect( socklen_t addrlen) { #ifndef UPNP_ENABLE_BLOCKING_TCP_CONNECTIONS - int ret = Make_Socket_NoBlocking(sockfd); + int ret = sock_make_no_blocking(sockfd); if (ret != - 1) { ret = connect(sockfd, serv_addr, addrlen); ret = Check_Connect_And_Wait_Connection(sockfd, ret); if (ret != - 1) { - ret = Make_Socket_Blocking(sockfd); + ret = sock_make_blocking(sockfd); } } diff --git a/upnp/src/genlib/net/sock.c b/upnp/src/genlib/net/sock.c index 7f9bbad..562639a 100644 --- a/upnp/src/genlib/net/sock.c +++ b/upnp/src/genlib/net/sock.c @@ -39,11 +39,12 @@ #include "sock.h" -#include "unixutil.h" /* for socklen_t, EAFNOSUPPORT */ +#include "unixutil.h" /* for socklen_t, EAFNOSUPPORT */ #include "upnp.h" #include #include +#include /* for F_GETFL, F_SETFL, O_NONBLOCK */ #include #include @@ -207,3 +208,35 @@ int sock_write(IN SOCKINFO *info, IN const char *buffer, IN int bufsize, return sock_read_write(info, (char *)buffer, bufsize, timeoutSecs, FALSE); } +int sock_make_blocking(SOCKET sock) +{ +#ifdef WIN32 + u_long val = 0; + return ioctlsocket(sock, FIONBIO, &val); +#else + int val; + + val = fcntl(sock, F_GETFL, 0); + if (fcntl(sock, F_SETFL, val & ~O_NONBLOCK) == -1) { + return -1; + } +#endif + return 0; +} + + +int sock_make_no_blocking(SOCKET sock) +{ +#ifdef WIN32 + u_long val = 1; + return ioctlsocket(sock, FIONBIO, &val); +#else /* WIN32 */ + int val; + + val = fcntl(sock, F_GETFL, 0); + if (fcntl(sock, F_SETFL, val | O_NONBLOCK) == -1) { + return -1; + } +#endif /* WIN32 */ + return 0; +} diff --git a/upnp/src/inc/sock.h b/upnp/src/inc/sock.h index a1ec42c..ad44b48 100644 --- a/upnp/src/inc/sock.h +++ b/upnp/src/inc/sock.h @@ -34,6 +34,10 @@ /*! * \file + * + * \defgroup Sock Network Socket Library + * + * @{ */ #include "upnputil.h" @@ -64,6 +68,23 @@ typedef struct #extern "C" { #endif +/*! + * \brief Closes the socket if it is different from -1. + * + * \return -1 if an error occurred or if the socket is -1. + */ +static UPNP_INLINE int sock_close( + /*! Socket descriptor. */ + SOCKET sock) +{ + int ret = -1; + + if (sock != -1) + ret = UpnpCloseSocket(sock); + + return ret; +} + /*! * \brief Assign the passed in socket descriptor to socket descriptor in the * SOCKINFO structure. @@ -96,6 +117,23 @@ int sock_init_with_ip( /*! Remote socket address. */ IN struct sockaddr *foreign_sockaddr); +/*! + * \brief Shutsdown the socket using the ShutdownMethod to indicate whether + * sends and receives on the socket will be dis-allowed. + * + * After shutting down the socket, closesocket is called to release system + * resources used by the socket calls. + * + * \return Integer: + * \li \c UPNP_E_SOCKET_ERROR on failure. + * \li \c UPNP_E_SUCCESS on success. + */ +int sock_destroy( + /*! Socket Information Object. */ + INOUT SOCKINFO* info, + /*! How to shutdown the socket. Used by sockets's shutdown(). */ + int ShutdownMethod); + /*! * \brief Reads data on socket in sockinfo. * @@ -133,42 +171,27 @@ int sock_write( INOUT int *timeoutSecs); /*! - * \brief Shutsdown the socket using the ShutdownMethod to indicate whether - * sends and receives on the socket will be dis-allowed. - * - * After shutting down the socket, closesocket is called to release system - * resources used by the socket calls. - * - * \return Integer: - * \li \c UPNP_E_SOCKET_ERROR on failure. - * \li \c UPNP_E_SUCCESS on success. + * \brief Make socket blocking. + * + * \return 0 if successful, -1 otherwise. */ -int sock_destroy( - /*! Socket Information Object. */ - INOUT SOCKINFO* info, - /*! How to shutdown the socket. Used by sockets's shutdown(). */ - int ShutdownMethod); +int sock_make_blocking( + /* [in] socket. */ + SOCKET sock); /*! - * \brief Closes the socket if it is different from -1. - * - * \return -1 if an error occurred or if the socket is -1. + * \brief Make socket non-blocking. + * + * \return 0 if successful, -1 otherwise. */ -static UPNP_INLINE int sock_close( - /*! Socket descriptor. */ - SOCKET sock) -{ - int ret = -1; - - if (sock != -1) { - ret = UpnpCloseSocket(sock); - } - - return ret; -} +int sock_make_no_blocking( + /* [in] socket. */ + SOCKET sock); #ifdef __cplusplus } /* #extern "C" */ #endif +/* @} Sock Network Socket Library */ + #endif /* GENLIB_NET_SOCK_H */ diff --git a/upnp/src/inc/ssdplib.h b/upnp/src/inc/ssdplib.h index 91c73af..98a33ff 100644 --- a/upnp/src/inc/ssdplib.h +++ b/upnp/src/inc/ssdplib.h @@ -33,6 +33,10 @@ **************************************************************************/ /*! + * \defgroup SSDPlib SSDP Library + * + * @{ + * * \file */ @@ -44,7 +48,6 @@ #include #include #include -#include #include #ifdef WIN32 @@ -184,48 +187,33 @@ typedef struct typedef int (*ParserFun)(char *, Event *); /*! - * \brief Make ssdp socket non-blocking. - * - * \return 0 if successful, -1 otherwise. + * \name SSDP Server Functions + * + * @{ */ -int Make_Socket_NoBlocking( - /* [in] socket. */ - SOCKET sock); /*! - * \brief Handles the search request. It does 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). + * \brief Sends SSDP advertisements, replies and shutdown messages. + * + * \return UPNP_E_SUCCESS if successful else appropriate error. */ -#ifdef INCLUDE_DEVICE_APIS -void ssdp_handle_device_request( - /* [in] . */ - http_message_t *hmsg, - /* [in] . */ - struct sockaddr *dest_addr); -#else -static inline void ssdp_handle_device_request( - /* [in] . */ - http_message_t *hmsg, - /* [in] . */ - struct sockaddr* dest_addr) {} -#endif - -/*! - * \brief This function handles the ssdp messages from the devices. These - * messages includes the search replies, advertisement of device coming alive - * and bye byes. - */ -void ssdp_handle_ctrlpt_msg( - /* [in] SSDP message from the device. */ - http_message_t *hmsg, - /* [in] Address of the device. */ - struct sockaddr *dest_addr, - /* [in] timeout kept by the control point while sending search message. */ - int timeout, - /* [in] Cookie stored by the control point application. This cookie will - * be returned to the control point in the callback. */ - void *cookie); +int AdvertiseAndReply( + /* [in] -1 = Send shutdown, 0 = send reply, 1 = Send Advertisement. */ + int AdFlag, + /* [in] Device handle. */ + UpnpDevice_Handle Hnd, + /* [in] Search type for sending replies. */ + enum SsdpSearchType SearchType, + /* [in] Destination address. */ + struct sockaddr *DestAddr, + /* [in] Device type. */ + char *DeviceType, + /* [in] Device UDN. */ + char *DeviceUDN, + /* [in] Service type. */ + char *ServiceType, + /* [in] Advertisement age. */ + int Exp); /*! * \brief Fills the fields of the event structure like DeviceType, Device UDN @@ -240,24 +228,6 @@ int unique_service_name( * function. */ SsdpEvent *Evt); -/*! - * \brief Creates the ssdp sockets. It set their option to listen for - * multicast traffic. - * - * \return UPNP_E_SUCCESS if successful else returns appropriate error. - */ -int get_ssdp_sockets( - /* [out] Array of SSDP sockets. */ - MiniServerSockArray *out); - -/*! - * \brief This function reads the data from the ssdp socket. - */ -void readFromSSDPSocket( - /* [in] SSDP socket. */ - SOCKET socket); - - /*! * \brief This function figures out the type of the SSDP search in the in the * request. @@ -269,7 +239,6 @@ enum SsdpSearchType ssdp_request_type1( /* [in] command came in the ssdp request. */ char *cmd); - /*! * \brief Starts filling the SSDP event structure based upon the * request received. @@ -282,9 +251,64 @@ int ssdp_request_type( /* [out] The event structure partially filled by this function. */ SsdpEvent *Evt); +/*! + * \brief This function reads the data from the ssdp socket. + */ +void readFromSSDPSocket( + /* [in] SSDP socket. */ + SOCKET socket); + +/*! + * \brief Creates the IPv4 and IPv6 ssdp sockets required by the + * control point and device operation. + * + * \return UPNP_E_SUCCESS if successful else returns appropriate error. + */ +int get_ssdp_sockets( + /* [out] Array of SSDP sockets. */ + MiniServerSockArray *out); + +/* @} SSDP Server Functions */ + +/*! + * \name SSDP Control Point Functions + * + * @{ + */ + +/*! + * \brief This function handles the ssdp messages from the devices. These + * messages includes the search replies, advertisement of device coming alive + * and bye byes. + */ +void ssdp_handle_ctrlpt_msg( + /* [in] SSDP message from the device. */ + http_message_t *hmsg, + /* [in] Address of the device. */ + struct sockaddr *dest_addr, + /* [in] timeout kept by the control point while sending search message. + * Only in search reply. */ + int timeout, + /* [in] Cookie stored by the control point application. This cookie will + * be returned to the control point in the callback. + * Only in search reply. */ + void *cookie); + /*! * \brief Creates and send the search request for a specific URL. * + * This function implements the search request of the discovery phase. + * A M-SEARCH request is sent on the SSDP channel for both IPv4 and + * IPv6 addresses. The search target(ST) is required and must be one of + * the following: + * \li "ssdp:all" : Search for all devices and services. + * \li "ssdp:rootdevice" : Search for root devices only. + * \li "uuid:" : Search for a particular device. + * \li "urn:schemas-upnp-org:device:" + * \li "urn:schemas-upnp-org:service:" + * \li "urn::device:" + * \li "urn::service:" + * * \return 1 if successful else appropriate error. */ int SearchByTarget( @@ -296,6 +320,43 @@ int SearchByTarget( * be returned to application in the callback. */ void *Cookie); +/* @} SSDP Control Point Functions */ + +/*! + * \name SSDP Device Functions + * + * @{ + */ + +/*! + * \brief Wrapper function to reply the search request coming from the + * control point. + * + * \return always return NULL + */ +void *advertiseAndReplyThread( + /* [in] Structure containing the search request. */ + void *data); + +/*! + * \brief Handles the search request. It does 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). + */ +#ifdef INCLUDE_DEVICE_APIS +void ssdp_handle_device_request( + /* [in] . */ + http_message_t *hmsg, + /* [in] . */ + struct sockaddr *dest_addr); +#else /* INCLUDE_DEVICE_APIS */ +static inline void ssdp_handle_device_request( + /* [in] . */ + http_message_t *hmsg, + /* [in] . */ + struct sockaddr* dest_addr) {} +#endif /* INCLUDE_DEVICE_APIS */ + /*! * \brief Creates the device advertisement request based on the input * parameter, and send it to the multicast channel. @@ -316,48 +377,6 @@ int DeviceAdvertisement( /* [in] Device address family. */ int AddressFamily); -/*! - * \brief Creates a HTTP device shutdown request packet and send it to the - * multicast channel through RequestHandler. - * - * \return UPNP_E_SUCCESS if successful else appropriate error. - */ -int DeviceShutdown( - /* [in] Device Type. */ - char *DevType, - /* [in] 1 means root device. */ - int RootDev, - /* [in] Device UDN. */ - char *Udn, - /* [in] . */ - char *_Server, - /* [in] Location URL. */ - char *Location, - /* [in] Device duration in sec. */ - int Duration, - /* [in] Device address family. */ - int AddressFamily); - -/*! - * \brief Creates the reply packet based on the input parameter, and send it - * to the client address given in its input parameter DestAddr. - * - * \return UPNP_E_SUCCESS if successful else appropriate error. - */ -int DeviceReply( - /* [in] destination IP address. */ - struct sockaddr *DestAddr, - /* [in] Device type. */ - char *DevType, - /* [in] 1 means root device 0 means embedded device. */ - int RootDev, - /* [in] Device UDN. */ - char *Udn, - /* [in] Location of Device description document. */ - char *Location, - /* [in] Life time of this device. */ - int Duration); - /*! * \brief Creates the reply packet based on the input parameter, and send it * to the client addesss given in its input parameter DestAddr. @@ -380,6 +399,26 @@ int SendReply( /* [in] . */ int ByType ); +/*! + * \brief Creates the reply packet based on the input parameter, and send it + * to the client address given in its input parameter DestAddr. + * + * \return UPNP_E_SUCCESS if successful else appropriate error. + */ +int DeviceReply( + /* [in] destination IP address. */ + struct sockaddr *DestAddr, + /* [in] Device type. */ + char *DevType, + /* [in] 1 means root device 0 means embedded device. */ + int RootDev, + /* [in] Device UDN. */ + char *Udn, + /* [in] Location of Device description document. */ + char *Location, + /* [in] Life time of this device. */ + int Duration); + /*! * \brief Creates the advertisement packet based on the input parameter, * and send it to the multicast channel. @@ -435,36 +474,29 @@ int ServiceShutdown( int AddressFamily); /*! - * \brief Wrapper function to reply the search request coming from the - * control point. - * - * \return always return NULL - */ -void *advertiseAndReplyThread( - /* [in] Structure containing the search request. */ - void *data); - -/*! - * \brief Sends SSDP advertisements, replies and shutdown messages. + * \brief Creates a HTTP device shutdown request packet and send it to the + * multicast channel through RequestHandler. * * \return UPNP_E_SUCCESS if successful else appropriate error. */ -int AdvertiseAndReply( - /* [in] -1 = Send shutdown, 0 = send reply, 1 = Send Advertisement. */ - int AdFlag, - /* [in] Device handle. */ - UpnpDevice_Handle Hnd, - /* [in] Search type for sending replies. */ - enum SsdpSearchType SearchType, - /* [in] Destination address. */ - struct sockaddr *DestAddr, - /* [in] Device type. */ - char *DeviceType, +int DeviceShutdown( + /* [in] Device Type. */ + char *DevType, + /* [in] 1 means root device. */ + int RootDev, /* [in] Device UDN. */ - char *DeviceUDN, - /* [in] Service type. */ - char *ServiceType, - /* [in] Advertisement age. */ - int Exp); + char *Udn, + /* [in] . */ + char *_Server, + /* [in] Location URL. */ + char *Location, + /* [in] Device duration in sec. */ + int Duration, + /* [in] Device address family. */ + int AddressFamily); + +/* @} SSDP Device Functions */ + +/* @} SSDPlib SSDP Library */ #endif /* SSDPLIB_H */ diff --git a/upnp/src/ssdp/ssdp_ctrlpt.c b/upnp/src/ssdp/ssdp_ctrlpt.c index 043d551..12a2a36 100644 --- a/upnp/src/ssdp/ssdp_ctrlpt.c +++ b/upnp/src/ssdp/ssdp_ctrlpt.c @@ -29,6 +29,14 @@ * **************************************************************************/ +/*! + * \addtogroup SSDPlib + * + * @{ + * + * \file + */ + #include "config.h" #include "upnputil.h" @@ -49,61 +57,26 @@ #include #ifdef WIN32 - #include +#include #endif /* WIN32 */ -/************************************************************************ - * Function: send_search_result - * - * Parameters: - * IN void *data: Search reply from the device - * - * Description: - * This function sends a callback to the control point application with - * a SEARCH result - * - * Returns: void - * - ***************************************************************************/ -void send_search_result(IN void *data) +/*! + * \brief Sends a callback to the control point application with a SEARCH + * result. + */ +static void send_search_result( + /* [in] Search reply from the device. */ + IN void *data) { - ResultData *temp = ( ResultData * ) data; + ResultData *temp = (ResultData *) data; - temp->ctrlpt_callback(UPNP_DISCOVERY_SEARCH_RESULT, &temp->param, temp->cookie); + temp->ctrlpt_callback(UPNP_DISCOVERY_SEARCH_RESULT, &temp->param, + temp->cookie); free(temp); } -/************************************************************************ - * Function: ssdp_handle_ctrlpt_msg - * - * Parameters: - * IN http_message_t *hmsg: - * SSDP message from the device - * IN struct sockaddr *dest_addr: - * Address of the device - * IN int timeout: - * timeout kept by the control point while - * sending search message - * IN void* cookie: - * Cookie stored by the control point application. - * This cookie will be returned to the control point - * in the callback - * - * Description: - * This function handles the ssdp messages from the devices. These - * messages includes the search replies, advertisement of device coming - * alive and bye byes. - * - * Returns: void - * - ***************************************************************************/ -void ssdp_handle_ctrlpt_msg( - IN http_message_t *hmsg, - IN struct sockaddr *dest_addr, - /* only in search reply */ - IN int timeout, - /* only in search reply */ - IN void *cookie) +void ssdp_handle_ctrlpt_msg(http_message_t *hmsg, struct sockaddr *dest_addr, + int timeout, void *cookie) { int handle; struct Handle_Info *ctrlpt_info = NULL; @@ -272,25 +245,27 @@ void ssdp_handle_ctrlpt_msg( break; case SSDP_DEVICEUDN: matched = !strncmp(searchArg->searchTarget, - hdr_value.buf, - hdr_value.length); + hdr_value.buf, + hdr_value.length); break; case SSDP_DEVICETYPE:{ - size_t m = min(hdr_value.length, - strlen(searchArg-> - searchTarget)); - matched = !strncmp(searchArg->searchTarget, - hdr_value.buf, m); - break; - } + size_t m = min(hdr_value.length, + strlen + (searchArg->searchTarget)); + matched = + !strncmp(searchArg->searchTarget, + hdr_value.buf, m); + break; + } case SSDP_SERVICE:{ - size_t m = min(hdr_value.length, - strlen(searchArg-> - searchTarget)); - matched = !strncmp(searchArg->searchTarget, - hdr_value.buf, m); - break; - } + size_t m = min(hdr_value.length, + strlen + (searchArg->searchTarget)); + matched = + !strncmp(searchArg->searchTarget, + hdr_value.buf, m); + break; + } default: matched = 0; break; @@ -304,8 +279,7 @@ void ssdp_handle_ctrlpt_msg( threadData->cookie = searchArg->cookie; threadData->ctrlpt_callback = ctrlpt_callback; - TPJobInit(&job, - (start_routine) + TPJobInit(&job, (start_routine) send_search_result, threadData); TPJobSetPriority(&job, MED_PRIORITY); @@ -324,60 +298,57 @@ void ssdp_handle_ctrlpt_msg( } } - -/************************************************************************ -* Function : CreateClientRequestPacket -* -* Parameters: -* IN char * RqstBuf:Output string in HTTP format. -* IN char *SearchTarget:Search Target -* IN int Mx dest_addr: Number of seconds to wait to -* collect all the responses -* IN int AddressFamily: search address family -* -* Description: -* This function creates a HTTP search request packet -* depending on the input parameter. -* -* Returns: void -* -***************************************************************************/ -static void -CreateClientRequestPacket( IN char *RqstBuf, - IN int Mx, - IN char *SearchTarget, - IN int AddressFamily ) +/*! + * \brief Creates a HTTP search request packet depending on the input + * parameter. + */ +static void CreateClientRequestPacket( + /*! [in] Output string in HTTP format. */ + IN char *RqstBuf, + /*! [in] Search Target. */ + IN int Mx, + /*! [in] Number of seconds to wait to collect all the responses. */ + IN char *SearchTarget, + /*! [in] search address family. */ + IN int AddressFamily) { - char TempBuf[COMMAND_LEN]; + char TempBuf[COMMAND_LEN]; - strcpy( RqstBuf, "M-SEARCH * HTTP/1.1\r\n" ); + strcpy(RqstBuf, "M-SEARCH * HTTP/1.1\r\n"); - if (AddressFamily == AF_INET) { - sprintf( TempBuf, "HOST: %s:%d\r\n", SSDP_IP, SSDP_PORT ); - } else if (AddressFamily == AF_INET6) { - sprintf( TempBuf, "HOST: [%s]:%d\r\n", SSDP_IPV6_LINKLOCAL, SSDP_PORT ); - } - strcat( RqstBuf, TempBuf ); - strcat( RqstBuf, "MAN: \"ssdp:discover\"\r\n" ); + if (AddressFamily == AF_INET) { + sprintf(TempBuf, "HOST: %s:%d\r\n", SSDP_IP, SSDP_PORT); + } else if (AddressFamily == AF_INET6) { + sprintf(TempBuf, "HOST: [%s]:%d\r\n", SSDP_IPV6_LINKLOCAL, + SSDP_PORT); + } + strcat(RqstBuf, TempBuf); + strcat(RqstBuf, "MAN: \"ssdp:discover\"\r\n"); - if( Mx > 0 ) { - sprintf( TempBuf, "MX: %d\r\n", Mx ); - strcat( RqstBuf, TempBuf ); - } + if (Mx > 0) { + sprintf(TempBuf, "MX: %d\r\n", Mx); + strcat(RqstBuf, TempBuf); + } - if( SearchTarget != NULL ) { - sprintf( TempBuf, "ST: %s\r\n", SearchTarget ); - strcat( RqstBuf, TempBuf ); - } - strcat( RqstBuf, "\r\n" ); + if (SearchTarget != NULL) { + sprintf(TempBuf, "ST: %s\r\n", SearchTarget); + strcat(RqstBuf, TempBuf); + } + strcat(RqstBuf, "\r\n"); } - +/*! + * \brief + */ static void CreateClientRequestPacketUlaGua( - IN char *RqstBuf, - IN int Mx, - IN char *SearchTarget, - IN int AddressFamily) + /*! [in] . */ + char *RqstBuf, + /*! [in] . */ + int Mx, + /*! [in] . */ + char *SearchTarget, + /*! [in] . */ + int AddressFamily) { char TempBuf[COMMAND_LEN]; @@ -385,7 +356,8 @@ static void CreateClientRequestPacketUlaGua( if (AddressFamily == AF_INET) { sprintf(TempBuf, "HOST: %s:%d\r\n", SSDP_IP, SSDP_PORT); } else if (AddressFamily == AF_INET6) { - sprintf(TempBuf, "HOST: [%s]:%d\r\n", SSDP_IPV6_SITELOCAL, SSDP_PORT); + sprintf(TempBuf, "HOST: [%s]:%d\r\n", SSDP_IPV6_SITELOCAL, + SSDP_PORT); } strcat(RqstBuf, TempBuf); strcat(RqstBuf, "MAN: \"ssdp:discover\"\r\n"); @@ -400,94 +372,58 @@ static void CreateClientRequestPacketUlaGua( strcat(RqstBuf, "\r\n"); } - -/************************************************************************ -* Function : searchExpired -* -* Parameters: -* IN void * arg: -* -* Description: -* This function -* -* Returns: void -* -***************************************************************************/ -void searchExpired(void *arg) +/*! + * \brief + */ +static void searchExpired( + /* [in] . */ + void *arg) { - int *id = (int *)arg; - int handle = -1; - struct Handle_Info *ctrlpt_info = NULL; + int *id = (int *)arg; + int handle = -1; + struct Handle_Info *ctrlpt_info = NULL; - /* remove search Target from list and call client back */ - ListNode *node = NULL; - SsdpSearchArg *item; - Upnp_FunPtr ctrlpt_callback; - void *cookie = NULL; - int found = 0; + /* remove search Target from list and call client back */ + ListNode *node = NULL; + SsdpSearchArg *item; + Upnp_FunPtr ctrlpt_callback; + void *cookie = NULL; + int found = 0; - HandleLock(); + HandleLock(); - /* remove search target from search list */ - if( GetClientHandleInfo( &handle, &ctrlpt_info ) != HND_CLIENT ) { - free( id ); - HandleUnlock(); - return; - } - ctrlpt_callback = ctrlpt_info->Callback; - node = ListHead( &ctrlpt_info->SsdpSearchList ); - while( node != NULL ) { - item = ( SsdpSearchArg * ) node->item; - if( item->timeoutEventId == ( *id ) ) { - free( item->searchTarget ); - cookie = item->cookie; - found = 1; - item->searchTarget = NULL; - free( item ); - ListDelNode( &ctrlpt_info->SsdpSearchList, node, 0 ); - break; - } - node = ListNext( &ctrlpt_info->SsdpSearchList, node ); - } - HandleUnlock(); + /* remove search target from search list */ + if (GetClientHandleInfo(&handle, &ctrlpt_info) != HND_CLIENT) { + free(id); + HandleUnlock(); + return; + } + ctrlpt_callback = ctrlpt_info->Callback; + node = ListHead(&ctrlpt_info->SsdpSearchList); + while (node != NULL) { + item = (SsdpSearchArg *) node->item; + if (item->timeoutEventId == (*id)) { + free(item->searchTarget); + cookie = item->cookie; + found = 1; + item->searchTarget = NULL; + free(item); + ListDelNode(&ctrlpt_info->SsdpSearchList, node, 0); + break; + } + node = ListNext(&ctrlpt_info->SsdpSearchList, node); + } + HandleUnlock(); - if( found ) { - ctrlpt_callback( UPNP_DISCOVERY_SEARCH_TIMEOUT, NULL, cookie ); - } + if (found) { + ctrlpt_callback(UPNP_DISCOVERY_SEARCH_TIMEOUT, NULL, cookie); + } - free( id ); + free(id); } -/************************************************************************ -* Function : SearchByTarget -* -* Parameters: -* IN int Mx:Number of seconds to wait, to collect all the responses. -* IN char *St: Search target. -* IN void *Cookie: cookie provided by control point application. -* This cokie will be returned to application in the callback. -* -* Description: -* This function implements the search request of the discovery phase. -* A M-SEARCH request is sent on the SSDP channel for both IPv4 and -* IPv6 addresses. The search target(ST) is required and must be one of -* the following: -* - "ssdp:all" : Search for all devices and services. -* - "ssdp:rootdevice" : Search for root devices only. -* - "uuid:" : Search for a particular device. -* - "urn:schemas-upnp-org:device:" -* - "urn:schemas-upnp-org:service:" -* - "urn::device:" -* - "urn::service:" -* -* Returns: int -* 1 if successful else appropriate error -***************************************************************************/ -int SearchByTarget( - IN int Mx, - IN char *St, - IN void *Cookie) +int SearchByTarget(int Mx, char *St, void *Cookie) { char errorBuffer[ERROR_BUFFER_LEN]; int *id = NULL; @@ -497,8 +433,8 @@ int SearchByTarget( char ReqBufv6UlaGua[BUFSIZE]; struct sockaddr_storage __ss_v4; struct sockaddr_storage __ss_v6; - struct sockaddr_in* destAddr4 = (struct sockaddr_in*)&__ss_v4; - struct sockaddr_in6* destAddr6 = (struct sockaddr_in6*)&__ss_v6; + struct sockaddr_in *destAddr4 = (struct sockaddr_in *)&__ss_v4; + struct sockaddr_in6 *destAddr6 = (struct sockaddr_in6 *)&__ss_v6; fd_set wrSet; SsdpSearchArg *newArg = NULL; int timeTillRead = 0; @@ -508,7 +444,7 @@ int SearchByTarget( unsigned long addrv4 = inet_addr(gIF_IPV4); int max_fd = 0; - /*ThreadData *ThData;*/ + /*ThreadData *ThData; */ ThreadPoolJob job; requestType = ssdp_request_type1(St); @@ -516,7 +452,8 @@ int SearchByTarget( return UPNP_E_INVALID_PARAM; } - UpnpPrintf(UPNP_INFO, SSDP, __FILE__, __LINE__, "Inside SearchByTarget\n"); + UpnpPrintf(UPNP_INFO, SSDP, __FILE__, __LINE__, + "Inside SearchByTarget\n"); timeTillRead = Mx; if (timeTillRead < MIN_SEARCH_TIME) { @@ -527,7 +464,8 @@ int SearchByTarget( CreateClientRequestPacket(ReqBufv4, timeTillRead, St, AF_INET); CreateClientRequestPacket(ReqBufv6, timeTillRead, St, AF_INET6); - CreateClientRequestPacketUlaGua(ReqBufv6UlaGua, timeTillRead, St, AF_INET6); + CreateClientRequestPacketUlaGua(ReqBufv6UlaGua, timeTillRead, St, + AF_INET6); memset(&__ss_v4, 0, sizeof(__ss_v4)); destAddr4->sin_family = AF_INET; @@ -548,19 +486,19 @@ int SearchByTarget( return UPNP_E_INTERNAL_ERROR; } - newArg = (SsdpSearchArg *)malloc(sizeof(SsdpSearchArg)); + newArg = (SsdpSearchArg *) malloc(sizeof(SsdpSearchArg)); newArg->searchTarget = strdup(St); newArg->cookie = Cookie; newArg->requestType = requestType; id = (int *)malloc(sizeof(int)); - TPJobInit(&job, (start_routine)searchExpired, id); + TPJobInit(&job, (start_routine) searchExpired, id); TPJobSetPriority(&job, MED_PRIORITY); - TPJobSetFreeFunction(&job, (free_routine)free); + TPJobSetFreeFunction(&job, (free_routine) free); /* Schedule a timeout event to remove search Arg */ TimerThreadSchedule(&gTimerThread, timeTillRead, - REL_SEC, &job, SHORT_TERM, id); + REL_SEC, &job, SHORT_TERM, id); newArg->timeoutEventId = *id; ListAddTail(&ctrlpt_info->SsdpSearchList, newArg); @@ -570,14 +508,14 @@ int SearchByTarget( FD_ZERO(&wrSet); if (gSsdpReqSocket4 != INVALID_SOCKET) { setsockopt(gSsdpReqSocket4, IPPROTO_IP, IP_MULTICAST_IF, - (char *)&addrv4, sizeof (addrv4)); + (char *)&addrv4, sizeof(addrv4)); FD_SET(gSsdpReqSocket4, &wrSet); max_fd = max(max_fd, gSsdpReqSocket4); } #ifdef UPNP_ENABLE_IPV6 if (gSsdpReqSocket6 != INVALID_SOCKET) { setsockopt(gSsdpReqSocket6, IPPROTO_IPV6, IPV6_MULTICAST_IF, - (char *)&gIF_INDEX, sizeof (gIF_INDEX)); + (char *)&gIF_INDEX, sizeof(gIF_INDEX)); FD_SET(gSsdpReqSocket6, &wrSet); max_fd = max(max_fd, gSsdpReqSocket6); } @@ -587,8 +525,7 @@ int SearchByTarget( if (ret == -1) { strerror_r(errno, errorBuffer, ERROR_BUFFER_LEN); UpnpPrintf(UPNP_INFO, SSDP, __FILE__, __LINE__, - "SSDP_LIB: Error in select(): %s\n", - errorBuffer); + "SSDP_LIB: Error in select(): %s\n", errorBuffer); shutdown(gSsdpReqSocket4, SD_BOTH); UpnpCloseSocket(gSsdpReqSocket4); #ifdef UPNP_ENABLE_IPV6 @@ -598,53 +535,53 @@ int SearchByTarget( return UPNP_E_INTERNAL_ERROR; } #ifdef UPNP_ENABLE_IPV6 - if (gSsdpReqSocket6 != INVALID_SOCKET && + if (gSsdpReqSocket6 != INVALID_SOCKET && FD_ISSET(gSsdpReqSocket6, &wrSet)) { int NumCopy = 0; while (NumCopy < NUM_SSDP_COPY) { sendto(gSsdpReqSocket6, - ReqBufv6UlaGua, strlen(ReqBufv6UlaGua), 0, - (struct sockaddr *)&__ss_v6, - sizeof(struct sockaddr_in)); + ReqBufv6UlaGua, strlen(ReqBufv6UlaGua), 0, + (struct sockaddr *)&__ss_v6, + sizeof(struct sockaddr_in)); NumCopy++; imillisleep(SSDP_PAUSE); } NumCopy = 0; inet_pton(AF_INET6, SSDP_IPV6_LINKLOCAL, &destAddr6->sin6_addr); while (NumCopy < NUM_SSDP_COPY) { - UpnpPrintf( UPNP_INFO, SSDP, __FILE__, __LINE__, - ">>> SSDP SEND M-SEARCH >>>\n%s\n", - ReqBufv6); + UpnpPrintf(UPNP_INFO, SSDP, __FILE__, __LINE__, + ">>> SSDP SEND M-SEARCH >>>\n%s\n", + ReqBufv6); sendto(gSsdpReqSocket6, - ReqBufv6, strlen(ReqBufv6), 0, - (struct sockaddr *)&__ss_v6, - sizeof(struct sockaddr_in6)); + ReqBufv6, strlen(ReqBufv6), 0, + (struct sockaddr *)&__ss_v6, + sizeof(struct sockaddr_in6)); NumCopy++; imillisleep(SSDP_PAUSE); } } -#endif /* IPv6 */ +#endif /* IPv6 */ - if (gSsdpReqSocket4 != INVALID_SOCKET && + if (gSsdpReqSocket4 != INVALID_SOCKET && FD_ISSET(gSsdpReqSocket4, &wrSet)) { int NumCopy = 0; while (NumCopy < NUM_SSDP_COPY) { - UpnpPrintf( UPNP_INFO, SSDP, __FILE__, __LINE__, - ">>> SSDP SEND M-SEARCH >>>\n%s\n", - ReqBufv4); + UpnpPrintf(UPNP_INFO, SSDP, __FILE__, __LINE__, + ">>> SSDP SEND M-SEARCH >>>\n%s\n", + ReqBufv4); sendto(gSsdpReqSocket4, - ReqBufv4, strlen(ReqBufv4), 0, - (struct sockaddr *)&__ss_v4, - sizeof(struct sockaddr_in)); + ReqBufv4, strlen(ReqBufv4), 0, + (struct sockaddr *)&__ss_v4, + sizeof(struct sockaddr_in)); NumCopy++; imillisleep(SSDP_PAUSE); } - } + } return 1; } - #endif /* EXCLUDE_SSDP */ #endif /* INCLUDE_CLIENT_APIS */ +/* @} SSDPlib */ diff --git a/upnp/src/ssdp/ssdp_device.c b/upnp/src/ssdp/ssdp_device.c index 202623a..662b501 100644 --- a/upnp/src/ssdp/ssdp_device.c +++ b/upnp/src/ssdp/ssdp_device.c @@ -29,14 +29,19 @@ * **************************************************************************/ +/*! + * \addtogroup SSDPlib + * + * @{ + * + * \file + */ #include "config.h" - #ifdef INCLUDE_DEVICE_APIS #if EXCLUDE_SSDP == 0 - #include "httpparser.h" #include "httpreadwrite.h" #include "ssdplib.h" @@ -46,179 +51,126 @@ #include "upnpapi.h" #include "UpnpInet.h" - #include #include #include - #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 ) +void *advertiseAndReplyThread(void *data) { - SsdpSearchReply *arg = ( SsdpSearchReply * ) data; + SsdpSearchReply *arg = (SsdpSearchReply *) data; - AdvertiseAndReply( 0, arg->handle, - arg->event.RequestType, - (struct sockaddr*)&arg->dest_addr, - arg->event.DeviceType, - arg->event.UDN, - arg->event.ServiceType, arg->MaxAge ); - free( arg ); + AdvertiseAndReply(0, arg->handle, + arg->event.RequestType, + (struct sockaddr *)&arg->dest_addr, + arg->event.DeviceType, + arg->event.UDN, arg->event.ServiceType, arg->MaxAge); + free(arg); - return NULL; + return NULL; } -/************************************************************************ -* Function : ssdp_handle_device_request -* -* Parameters: -* IN http_message_t *hmsg: SSDP search request from the control point -* IN struct sockaddr *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_APIS -void ssdp_handle_device_request( - IN http_message_t *hmsg, - IN struct sockaddr *dest_addr) +void ssdp_handle_device_request(http_message_t *hmsg, struct sockaddr *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; - 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) + /* bad or missing hdr. */ + return; + /* 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); + /* restore. */ + hdr_value.buf[hdr_value.length] = save_char; + if (ret_code == -1) + /* bad ST header. */ + return; - /* check man hdr. */ - if( httpmsg_find_hdr( hmsg, HDR_MAN, &hdr_value ) == NULL || - memptr_cmp( &hdr_value, "\"ssdp:discover\"" ) != 0 ) { - /* bad or missing hdr. */ - return; - } - /* 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 ); - /* restore. */ - hdr_value.buf[hdr_value.length] = save_char; - if( ret_code == -1 ) { - /* bad ST header. */ - return; - } + HandleLock(); + /* device info. */ + if (GetDeviceHandleInfo(dest_addr->sa_family, + &handle, &dev_info) != HND_DEVICE) { + HandleUnlock(); + /* no info found. */ + return; + } + maxAge = dev_info->MaxAge; + HandleUnlock(); - HandleLock(); - /* device info. */ - if( GetDeviceHandleInfo( dest_addr->sa_family, - &handle, &dev_info ) != HND_DEVICE ) { - HandleUnlock(); - /* no info found. */ - return; - } - 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; + memcpy(&threadArg->dest_addr, dest_addr, sizeof(threadArg->dest_addr)); + threadArg->event = event; + threadArg->MaxAge = maxAge; - 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 ); + TPJobInit(&job, advertiseAndReplyThread, threadArg); + TPJobSetFreeFunction(&job, (free_routine) free); - threadArg = - ( SsdpSearchReply * ) malloc( sizeof( SsdpSearchReply ) ); - - if( threadArg == NULL ) { - return; - } - threadArg->handle = handle; - memcpy( &threadArg->dest_addr, dest_addr, sizeof(threadArg->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 - * within 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 ); + /* Subtract a percentage from the mx to allow for network and processing + * delays (i.e. if search is for 30 seconds, respond + * within 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 *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 int NewRequestHandler(IN struct sockaddr *DestAddr, IN int NumPacket, - IN char **RqPacket) +/*! + * \brief Works as a request handler which passes the HTTP request string + * to multicast channel. + * + * \return 1 if successful else appropriate error. + */ +static int NewRequestHandler( + /*! [in] Ip address, to send the reply. */ + struct sockaddr *DestAddr, + /*! [in] Number of packet to be sent. */ + int NumPacket, + /*! [in] . */ + char **RqPacket) { char errorBuffer[ERROR_BUFFER_LEN]; SOCKET ReplySock; @@ -288,10 +240,12 @@ static int NewRequestHandler(IN struct sockaddr *DestAddr, IN int NumPacket, return ret; } -/** - * return 1 if an inet6 @ has been found +/*! + * \brief + * + * \return 1 if an inet6 @ has been found. */ -int extractIPv6address(char *url, char *address) +static int extractIPv6address(char *url, char *address) { int i = 0; int j = 0; @@ -300,13 +254,13 @@ int extractIPv6address(char *url, char *address) while (url[i] != '[' && url[i] != '\0') { i++; } - if( url[i] == '\0') { + if (url[i] == '\0') { goto exit_function; } /* bracket has been found, we deal with an IPv6 address */ i++; - while (url[i] != '\0' && url[i] != ']' ) { + while (url[i] != '\0' && url[i] != ']') { address[j] = url[i]; i++; j++; @@ -320,16 +274,16 @@ int extractIPv6address(char *url, char *address) ret = 1; } -exit_function: + exit_function: return ret; } - -/** - * return 1 if the Url contains an ULA or GUA IPv6 address - * 0 otherwise +/*! + * \brief + * + * \return 1 if the Url contains an ULA or GUA IPv6 address, 0 otherwise. */ -int isUrlV6UlaGua(char *descdocUrl) +static int isUrlV6UlaGua(char *descdocUrl) { char address[INET6_ADDRSTRLEN]; struct in6_addr v6_addr; @@ -342,36 +296,27 @@ int isUrlV6UlaGua(char *descdocUrl) return 0; } - -/************************************************************************ -* 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. -* IN int AddressFamily: Address family of the HTTP request. -* -* 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 -* -***************************************************************************/ +/*! + * \brief Creates a HTTP request packet. Depending on the input parameter, + * it either creates a service advertisement request or service shutdown + * request etc. + */ static void CreateServicePacket( - IN int msg_type, - const IN char *nt, - IN char *usn, - IN char *location, - IN int duration, - OUT char **packet, - IN int AddressFamily) + /*! [in] type of the message (Search Reply, Advertisement + * or Shutdown). */ + int msg_type, + /*! [in] ssdp type. */ + const char *nt, + /*! [in] unique service name ( go in the HTTP Header). */ + char *usn, + /*! [in] Location URL. */ + char *location, + /*! [in] Service duration in sec. */ + int duration, + /*! [out] Output buffer filled with HTTP statement. */ + char **packet, + /*! [in] Address family of the HTTP request. */ + int AddressFamily) { int ret_code; const char *nts; @@ -383,20 +328,17 @@ static void CreateServicePacket( 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" "ssc" "ssc" "S" "Xc" "ssc" "sscc", - HTTP_OK, - "CACHE-CONTROL: max-age=", duration, - "EXT:", - "LOCATION: ", location, - "OPT: ", "\"http://schemas.upnp.org/upnp/1/0/\"; ns=01", - "01-NLS: ", gUpnpSdkNLSuuid, - X_USER_AGENT, - "ST: ", nt, - "USN: ", usn); + ret_code = http_MakeMessage(&buf, 1, 1, + "R" "sdc" "D" "sc" "ssc" "ssc" "ssc" + "S" "Xc" "ssc" "sscc", HTTP_OK, + "CACHE-CONTROL: max-age=", duration, + "EXT:", "LOCATION: ", location, + "OPT: ", + "\"http://schemas.upnp.org/upnp/1/0/\"; ns=01", + "01-NLS: ", gUpnpSdkNLSuuid, + X_USER_AGENT, "ST: ", nt, "USN: ", + usn); if (ret_code != 0) { return; } @@ -407,7 +349,7 @@ static void CreateServicePacket( if (msg_type == MSGTYPE_ADVERTISEMENT) nts = "ssdp:alive"; else - /* shutdown */ + /* 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. */ @@ -419,20 +361,17 @@ static void CreateServicePacket( else host = "[" SSDP_IPV6_LINKLOCAL "]"; } - ret_code = http_MakeMessage( - &buf, 1, 1, - "Q" "sssdc" "sdc" "ssc" "ssc" "ssc" "ssc" "ssc" "S" "Xc" "sscc", - HTTPMETHOD_NOTIFY, "*", (size_t)1, - "HOST: ", host, - ":", SSDP_PORT, - "CACHE-CONTROL: max-age=", duration, - "LOCATION: ", location, - "OPT: ", "\"http://schemas.upnp.org/upnp/1/0/\"; ns=01", - "01-NLS: ", gUpnpSdkNLSuuid, - "NT: ", nt, - "NTS: ", nts, - X_USER_AGENT, - "USN: ", usn ); + ret_code = http_MakeMessage(&buf, 1, 1, + "Q" "sssdc" "sdc" "ssc" "ssc" "ssc" + "ssc" "ssc" "S" "Xc" "sscc", + HTTPMETHOD_NOTIFY, "*", (size_t) 1, + "HOST: ", host, ":", SSDP_PORT, + "CACHE-CONTROL: max-age=", duration, + "LOCATION: ", location, "OPT: ", + "\"http://schemas.upnp.org/upnp/1/0/\"; ns=01", + "01-NLS: ", gUpnpSdkNLSuuid, "NT: ", + nt, "NTS: ", nts, X_USER_AGENT, + "USN: ", usn); if (ret_code) return; } else @@ -445,516 +384,348 @@ static void CreateServicePacket( 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 -***************************************************************************/ -int -DeviceAdvertisement( IN char *DevType, - int RootDev, - char *Udn, - IN char *Location, - IN int Duration, - IN int AddressFamily) +int DeviceAdvertisement(char *DevType, int RootDev, char *Udn, char *Location, + int Duration, int AddressFamily) { - struct sockaddr_storage __ss; - struct sockaddr_in* DestAddr4 = (struct sockaddr_in*)&__ss; - struct sockaddr_in6* DestAddr6 = (struct sockaddr_in6*)&__ss; + struct sockaddr_storage __ss; + struct sockaddr_in *DestAddr4 = (struct sockaddr_in *)&__ss; + struct sockaddr_in6 *DestAddr6 = (struct sockaddr_in6 *)&__ss; + /* char Mil_Nt[LINE_SIZE] */ + char Mil_Usn[LINE_SIZE]; + char *msgs[3]; + int ret_code = UPNP_E_SUCCESS; - /* char Mil_Nt[LINE_SIZE] */ - char Mil_Usn[LINE_SIZE]; - char *msgs[3]; - int ret_code = UPNP_E_SUCCESS; + UpnpPrintf(UPNP_INFO, SSDP, __FILE__, __LINE__, + "In function DeviceAdvertisement\n"); + memset(&__ss, 0, sizeof(__ss)); + if (AddressFamily == AF_INET) { + DestAddr4->sin_family = AF_INET; + inet_pton(AF_INET, SSDP_IP, &DestAddr4->sin_addr); + DestAddr4->sin_port = htons(SSDP_PORT); + } else if (AddressFamily == AF_INET6) { + DestAddr6->sin6_family = AF_INET6; + inet_pton(AF_INET6, + (isUrlV6UlaGua(Location)) ? SSDP_IPV6_SITELOCAL : + SSDP_IPV6_LINKLOCAL, &DestAddr6->sin6_addr); + DestAddr6->sin6_port = htons(SSDP_PORT); + DestAddr6->sin6_scope_id = gIF_INDEX; + } else { + UpnpPrintf(UPNP_CRITICAL, SSDP, __FILE__, __LINE__, + "Invalid device address family.\n"); + } + 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); + CreateServicePacket(MSGTYPE_ADVERTISEMENT, "upnp:rootdevice", + Mil_Usn, Location, Duration, &msgs[0], + AddressFamily); + } + /* both root and sub-devices need to send these two messages */ + CreateServicePacket(MSGTYPE_ADVERTISEMENT, Udn, Udn, + Location, Duration, &msgs[1], AddressFamily); + sprintf(Mil_Usn, "%s::%s", Udn, DevType); + CreateServicePacket(MSGTYPE_ADVERTISEMENT, DevType, Mil_Usn, + Location, Duration, &msgs[2], AddressFamily); + /* check error */ + if ((RootDev && msgs[0] == NULL) || msgs[1] == NULL || msgs[2] == NULL) { + free(msgs[0]); + free(msgs[1]); + free(msgs[2]); + return UPNP_E_OUTOF_MEMORY; + } + /* send packets */ + if (RootDev) { + /* send 3 msg types */ + ret_code = + NewRequestHandler((struct sockaddr *)&__ss, 3, &msgs[0]); + } else { /* sub-device */ - UpnpPrintf( UPNP_INFO, SSDP, __FILE__, __LINE__, - "In function DeviceAdvertisement\n" ); + /* send 2 msg types */ + ret_code = + NewRequestHandler((struct sockaddr *)&__ss, 2, &msgs[1]); + } + /* free msgs */ + free(msgs[0]); + free(msgs[1]); + free(msgs[2]); - memset( &__ss, 0, sizeof(__ss) ); - if( AddressFamily == AF_INET ) { - DestAddr4->sin_family = AF_INET; - inet_pton( AF_INET, SSDP_IP, &DestAddr4->sin_addr ); - DestAddr4->sin_port = htons( SSDP_PORT ); - } else if( AddressFamily == AF_INET6 ) { - DestAddr6->sin6_family = AF_INET6; - inet_pton(AF_INET6, - (isUrlV6UlaGua(Location)) ? SSDP_IPV6_SITELOCAL : SSDP_IPV6_LINKLOCAL, - &DestAddr6->sin6_addr ); - DestAddr6->sin6_port = htons( SSDP_PORT ); - DestAddr6->sin6_scope_id = gIF_INDEX; - } else { - UpnpPrintf( UPNP_CRITICAL, SSDP, __FILE__, __LINE__, - "Invalid device address family.\n" ); - } - - 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 ); - CreateServicePacket( MSGTYPE_ADVERTISEMENT, "upnp:rootdevice", - Mil_Usn, Location, Duration, &msgs[0], AddressFamily ); - } - /* both root and sub-devices need to send these two messages */ - CreateServicePacket( MSGTYPE_ADVERTISEMENT, Udn, Udn, - Location, Duration, &msgs[1], AddressFamily ); - sprintf( Mil_Usn, "%s::%s", Udn, DevType ); - CreateServicePacket( MSGTYPE_ADVERTISEMENT, DevType, Mil_Usn, - Location, Duration, &msgs[2], AddressFamily ); - /* check error */ - if( ( RootDev && msgs[0] == NULL ) || - msgs[1] == NULL || msgs[2] == NULL ) { - free( msgs[0] ); - free( msgs[1] ); - free( msgs[2] ); - return UPNP_E_OUTOF_MEMORY; - } - /* send packets */ - if( RootDev ) { - /* send 3 msg types */ - ret_code = NewRequestHandler( (struct sockaddr*)&__ss, 3, &msgs[0] ); - } else /* sub-device */ - { - /* send 2 msg types */ - ret_code = NewRequestHandler( (struct sockaddr*)&__ss, 2, &msgs[1] ); - } - - /* free msgs */ - free( msgs[0] ); - free( msgs[1] ); - free( msgs[2] ); - - return ret_code; + return ret_code; } -/************************************************************************ -* Function : SendReply -* -* Parameters: -* IN struct sockaddr * DestAddr:destination IP address. -* IN char *DevType: Device type -* IN int RootDev: 1 means root device 0 means embedded device. -* IN char * Udn: Device UDN -* IN char * Location: Location of Device description document. -* IN int Duration :Life time of this device. -* IN int ByType: -* -* Description: -* This function creates the reply packet based on the input parameter, -* and send it to the client addesss given in its input parameter DestAddr. -* -* Returns: int -* UPNP_E_SUCCESS if successful else appropriate error -***************************************************************************/ -int -SendReply( IN struct sockaddr *DestAddr, - IN char *DevType, - IN int RootDev, - IN char *Udn, - IN char *Location, - IN int Duration, - IN int ByType ) +int SendReply(struct sockaddr *DestAddr, char *DevType, int RootDev, + char *Udn, char *Location, int Duration, int ByType) { - int ret_code; - char *msgs[2]; - int num_msgs; - char Mil_Usn[LINE_SIZE]; - int i; + int ret_code; + char *msgs[2]; + int num_msgs; + char Mil_Usn[LINE_SIZE]; + int i; - msgs[0] = NULL; - msgs[1] = NULL; + msgs[0] = NULL; + msgs[1] = NULL; + if (RootDev) { + /* one msg for root device */ + num_msgs = 1; - if( RootDev ) { - /* one msg for root device */ - num_msgs = 1; + sprintf(Mil_Usn, "%s::upnp:rootdevice", Udn); + CreateServicePacket(MSGTYPE_REPLY, "upnp:rootdevice", + Mil_Usn, Location, Duration, &msgs[0], + DestAddr->sa_family); + } else { + /* two msgs for embedded devices */ + num_msgs = 1; - sprintf( Mil_Usn, "%s::upnp:rootdevice", Udn ); - CreateServicePacket( MSGTYPE_REPLY, "upnp:rootdevice", - Mil_Usn, Location, Duration, &msgs[0], DestAddr->sa_family ); - } else { - /* two msgs for embedded devices */ - num_msgs = 1; + /*NK: FIX for extra response when someone searches by udn */ + if (!ByType) { + CreateServicePacket(MSGTYPE_REPLY, Udn, Udn, Location, + Duration, &msgs[0], + DestAddr->sa_family); + } else { + sprintf(Mil_Usn, "%s::%s", Udn, DevType); + CreateServicePacket(MSGTYPE_REPLY, DevType, Mil_Usn, + Location, Duration, &msgs[0], + DestAddr->sa_family); + } + } + /* check error */ + for (i = 0; i < num_msgs; i++) { + if (msgs[i] == NULL) { + free(msgs[0]); + return UPNP_E_OUTOF_MEMORY; + } + } + /* send msgs */ + ret_code = NewRequestHandler(DestAddr, num_msgs, msgs); + for (i = 0; i < num_msgs; i++) { + if (msgs[i] != NULL) + free(msgs[i]); + } - /*NK: FIX for extra response when someone searches by udn */ - if( !ByType ) { - CreateServicePacket( MSGTYPE_REPLY, Udn, Udn, Location, - Duration, &msgs[0], DestAddr->sa_family ); - } else { - sprintf( Mil_Usn, "%s::%s", Udn, DevType ); - CreateServicePacket( MSGTYPE_REPLY, DevType, Mil_Usn, - Location, Duration, &msgs[0], DestAddr->sa_family ); - } - } - - /* check error */ - for( i = 0; i < num_msgs; i++ ) { - if( msgs[i] == NULL ) { - free( msgs[0] ); - return UPNP_E_OUTOF_MEMORY; - } - } - - /* send msgs */ - ret_code = NewRequestHandler( DestAddr, num_msgs, msgs ); - for( i = 0; i < num_msgs; i++ ) { - if( msgs[i] != NULL ) - free( msgs[i] ); - } - - return ret_code; + return ret_code; } -/************************************************************************ -* Function : DeviceReply -* -* Parameters: -* IN struct sockaddr *DestAddr:destination IP address. -* IN char *DevType: Device type -* IN int RootDev: 1 means root device 0 means embedded device. -* IN char * Udn: Device UDN -* IN char * Location: Location of Device description document. -* IN int Duration :Life time of this device. -* Description: -* This function creates the reply packet based on the input parameter, -* and send it to the client address given in its input parameter DestAddr. -* -* Returns: int -* UPNP_E_SUCCESS if successful else appropriate error -***************************************************************************/ -int -DeviceReply( IN struct sockaddr *DestAddr, - IN char *DevType, - IN int RootDev, - IN char *Udn, - IN char *Location, - IN int Duration) +int DeviceReply(struct sockaddr *DestAddr, char *DevType, int RootDev, + char *Udn, char *Location, int Duration) { - char *szReq[3], - Mil_Nt[LINE_SIZE], - Mil_Usn[LINE_SIZE]; - int RetVal; + char *szReq[3], Mil_Nt[LINE_SIZE], Mil_Usn[LINE_SIZE]; + int RetVal; - szReq[0] = NULL; - szReq[1] = NULL; - szReq[2] = NULL; + szReq[0] = NULL; + szReq[1] = NULL; + szReq[2] = NULL; + /* create 2 or 3 msgs */ + if (RootDev) { + /* 3 replies for root device */ + strcpy(Mil_Nt, "upnp:rootdevice"); + sprintf(Mil_Usn, "%s::upnp:rootdevice", Udn); + CreateServicePacket(MSGTYPE_REPLY, Mil_Nt, Mil_Usn, + Location, Duration, &szReq[0], + DestAddr->sa_family); + } + sprintf(Mil_Nt, "%s", Udn); + sprintf(Mil_Usn, "%s", Udn); + CreateServicePacket(MSGTYPE_REPLY, Mil_Nt, Mil_Usn, + Location, Duration, &szReq[1], DestAddr->sa_family); + sprintf(Mil_Nt, "%s", DevType); + sprintf(Mil_Usn, "%s::%s", Udn, DevType); + CreateServicePacket(MSGTYPE_REPLY, Mil_Nt, Mil_Usn, + Location, Duration, &szReq[2], DestAddr->sa_family); + /* check error */ + if ((RootDev && szReq[0] == NULL) || + szReq[1] == NULL || szReq[2] == NULL) { + free(szReq[0]); + free(szReq[1]); + free(szReq[2]); + return UPNP_E_OUTOF_MEMORY; + } + /* send replies */ + if (RootDev) { + RetVal = NewRequestHandler(DestAddr, 3, szReq); + } else { + RetVal = NewRequestHandler(DestAddr, 2, &szReq[1]); + } + /* free */ + free(szReq[0]); + free(szReq[1]); + free(szReq[2]); - /* create 2 or 3 msgs */ - if( RootDev ) { - /* 3 replies for root device */ - strcpy( Mil_Nt, "upnp:rootdevice" ); - sprintf( Mil_Usn, "%s::upnp:rootdevice", Udn ); - CreateServicePacket( MSGTYPE_REPLY, Mil_Nt, Mil_Usn, - Location, Duration, &szReq[0], DestAddr->sa_family ); - } - sprintf( Mil_Nt, "%s", Udn ); - sprintf( Mil_Usn, "%s", Udn ); - CreateServicePacket( MSGTYPE_REPLY, Mil_Nt, Mil_Usn, - Location, Duration, &szReq[1], DestAddr->sa_family ); - sprintf( Mil_Nt, "%s", DevType ); - sprintf( Mil_Usn, "%s::%s", Udn, DevType ); - CreateServicePacket( MSGTYPE_REPLY, Mil_Nt, Mil_Usn, - Location, Duration, &szReq[2], DestAddr->sa_family ); - /* check error */ - if( ( RootDev && szReq[0] == NULL ) || - szReq[1] == NULL || szReq[2] == NULL ) { - free( szReq[0] ); - free( szReq[1] ); - free( szReq[2] ); - return UPNP_E_OUTOF_MEMORY; - } - /* send replies */ - if( RootDev ) { - RetVal = NewRequestHandler( DestAddr, 3, szReq ); - } else { - RetVal = NewRequestHandler( DestAddr, 2, &szReq[1] ); - } - /* free */ - free( szReq[0] ); - free( szReq[1] ); - free( szReq[2] ); - - return RetVal; + return RetVal; } -/************************************************************************ -* Function : ServiceAdvertisement -* -* Parameters: -* IN char * Udn: Device UDN -* IN char *ServType: Service Type. -* IN char * Location: Location of Device description document. -* IN int Duration :Life time of this device. -* IN int AddressFamily: Device address family -* Description: -* This function creates the advertisement packet based -* on the input parameter, and send it to the multicast channel. -* -* Returns: int -* UPNP_E_SUCCESS if successful else appropriate error -***************************************************************************/ -int -ServiceAdvertisement( IN char *Udn, - IN char *ServType, - IN char *Location, - IN int Duration, - IN int AddressFamily) +int ServiceAdvertisement(char *Udn, char *ServType, char *Location, + int Duration, int AddressFamily) { - char Mil_Usn[LINE_SIZE]; - char *szReq[1]; - int RetVal = UPNP_E_SUCCESS; - struct sockaddr_storage __ss; - struct sockaddr_in* DestAddr4 = (struct sockaddr_in*)&__ss; - struct sockaddr_in6* DestAddr6 = (struct sockaddr_in6*)&__ss; + char Mil_Usn[LINE_SIZE]; + char *szReq[1]; + int RetVal = UPNP_E_SUCCESS; + struct sockaddr_storage __ss; + struct sockaddr_in *DestAddr4 = (struct sockaddr_in *)&__ss; + struct sockaddr_in6 *DestAddr6 = (struct sockaddr_in6 *)&__ss; - memset( &__ss, 0, sizeof(__ss) ); - if( AddressFamily == AF_INET ) { - DestAddr4->sin_family = AF_INET; - inet_pton( AF_INET, SSDP_IP, &DestAddr4->sin_addr ); - DestAddr4->sin_port = htons( SSDP_PORT ); - } else if( AddressFamily == AF_INET6 ) { - DestAddr6->sin6_family = AF_INET6; - inet_pton(AF_INET6, - (isUrlV6UlaGua(Location)) ? SSDP_IPV6_SITELOCAL : SSDP_IPV6_LINKLOCAL, - &DestAddr6->sin6_addr ); - DestAddr6->sin6_port = htons( SSDP_PORT ); - DestAddr6->sin6_scope_id = gIF_INDEX; - } else { - UpnpPrintf( UPNP_CRITICAL, SSDP, __FILE__, __LINE__, - "Invalid device address family.\n" ); - } + memset(&__ss, 0, sizeof(__ss)); + if (AddressFamily == AF_INET) { + DestAddr4->sin_family = AF_INET; + inet_pton(AF_INET, SSDP_IP, &DestAddr4->sin_addr); + DestAddr4->sin_port = htons(SSDP_PORT); + } else if (AddressFamily == AF_INET6) { + DestAddr6->sin6_family = AF_INET6; + inet_pton(AF_INET6, + (isUrlV6UlaGua(Location)) ? SSDP_IPV6_SITELOCAL : + SSDP_IPV6_LINKLOCAL, &DestAddr6->sin6_addr); + DestAddr6->sin6_port = htons(SSDP_PORT); + DestAddr6->sin6_scope_id = gIF_INDEX; + } else { + UpnpPrintf(UPNP_CRITICAL, SSDP, __FILE__, __LINE__, + "Invalid device address family.\n"); + } + sprintf(Mil_Usn, "%s::%s", Udn, ServType); + /* CreateServiceRequestPacket(1,szReq[0],Mil_Nt,Mil_Usn, + * Server,Location,Duration); */ + CreateServicePacket(MSGTYPE_ADVERTISEMENT, ServType, Mil_Usn, + Location, Duration, &szReq[0], AddressFamily); + if (szReq[0] == NULL) { + return UPNP_E_OUTOF_MEMORY; + } + RetVal = NewRequestHandler((struct sockaddr *)&__ss, 1, szReq); + free(szReq[0]); - sprintf( Mil_Usn, "%s::%s", Udn, ServType ); - - /* CreateServiceRequestPacket(1,szReq[0],Mil_Nt,Mil_Usn, - * Server,Location,Duration); */ - CreateServicePacket( MSGTYPE_ADVERTISEMENT, ServType, Mil_Usn, - Location, Duration, &szReq[0], AddressFamily ); - if( szReq[0] == NULL ) { - return UPNP_E_OUTOF_MEMORY; - } - - RetVal = NewRequestHandler( (struct sockaddr*)&__ss, 1, szReq ); - - free( szReq[0] ); - return RetVal; + return RetVal; } -/************************************************************************ -* Function : ServiceReply -* -* Parameters: -* IN struct sockaddr *DestAddr: -* IN char * Udn: Device UDN -* IN char *ServType: Service Type. -* IN char * Location: Location of Device description document. -* IN int Duration :Life time of this device. -* Description: -* This function creates the advertisement packet based -* on the input parameter, and send it to the multicast channel. -* -* Returns: int -* UPNP_E_SUCCESS if successful else appropriate error -***************************************************************************/ -int -ServiceReply( IN struct sockaddr *DestAddr, - IN char *ServType, - IN char *Udn, - IN char *Location, - IN int Duration ) +int ServiceReply(struct sockaddr *DestAddr, char *ServType, char *Udn, + char *Location, int Duration) { - char Mil_Usn[LINE_SIZE]; - char *szReq[1]; - int RetVal; + char Mil_Usn[LINE_SIZE]; + char *szReq[1]; + int RetVal; - szReq[0] = NULL; + szReq[0] = NULL; + sprintf(Mil_Usn, "%s::%s", Udn, ServType); + CreateServicePacket(MSGTYPE_REPLY, ServType, Mil_Usn, + Location, Duration, &szReq[0], DestAddr->sa_family); + if (szReq[0] == NULL) + return UPNP_E_OUTOF_MEMORY; + RetVal = NewRequestHandler(DestAddr, 1, szReq); + free(szReq[0]); - sprintf( Mil_Usn, "%s::%s", Udn, ServType ); - - CreateServicePacket( MSGTYPE_REPLY, ServType, Mil_Usn, - Location, Duration, &szReq[0], DestAddr->sa_family ); - if( szReq[0] == NULL ) { - return UPNP_E_OUTOF_MEMORY; - } - - RetVal = NewRequestHandler( DestAddr, 1, szReq ); - - free( szReq[0] ); - return RetVal; + return RetVal; } -/************************************************************************ -* Function : ServiceShutdown -* -* Parameters: -* IN char * Udn: Device UDN -* IN char *ServType: Service Type. -* IN char * Location: Location of Device description document. -* IN int Duration :Service duration in sec. -* IN int AddressFamily: Device address family -* Description: -* This function creates a HTTP service shutdown request packet -* and sent it to the multicast channel through RequestHandler. -* -* Returns: int -* UPNP_E_SUCCESS if successful else appropriate error -***************************************************************************/ -int -ServiceShutdown( IN char *Udn, - IN char *ServType, - IN char *Location, - IN int Duration, - IN int AddressFamily) +int ServiceShutdown(char *Udn, char *ServType, char *Location, int Duration, + int AddressFamily) { - char Mil_Usn[LINE_SIZE]; - char *szReq[1]; - struct sockaddr_storage __ss; - struct sockaddr_in* DestAddr4 = (struct sockaddr_in*)&__ss; - struct sockaddr_in6* DestAddr6 = (struct sockaddr_in6*)&__ss; - int RetVal = UPNP_E_SUCCESS; + char Mil_Usn[LINE_SIZE]; + char *szReq[1]; + struct sockaddr_storage __ss; + struct sockaddr_in *DestAddr4 = (struct sockaddr_in *)&__ss; + struct sockaddr_in6 *DestAddr6 = (struct sockaddr_in6 *)&__ss; + int RetVal = UPNP_E_SUCCESS; - memset( &__ss, 0, sizeof(__ss) ); - if( AddressFamily == AF_INET ) { - DestAddr4->sin_family = AF_INET; - inet_pton( AF_INET, SSDP_IP, &DestAddr4->sin_addr ); - DestAddr4->sin_port = htons( SSDP_PORT ); - } else if( AddressFamily == AF_INET6 ) { - DestAddr6->sin6_family = AF_INET6; - inet_pton(AF_INET6, - (isUrlV6UlaGua(Location)) ? SSDP_IPV6_SITELOCAL : SSDP_IPV6_LINKLOCAL, - &DestAddr6->sin6_addr ); - DestAddr6->sin6_port = htons( SSDP_PORT ); - DestAddr6->sin6_scope_id = gIF_INDEX; - } else { - UpnpPrintf( UPNP_CRITICAL, SSDP, __FILE__, __LINE__, - "Invalid device address family.\n" ); - } + memset(&__ss, 0, sizeof(__ss)); + if (AddressFamily == AF_INET) { + DestAddr4->sin_family = AF_INET; + inet_pton(AF_INET, SSDP_IP, &DestAddr4->sin_addr); + DestAddr4->sin_port = htons(SSDP_PORT); + } else if (AddressFamily == AF_INET6) { + DestAddr6->sin6_family = AF_INET6; + inet_pton(AF_INET6, + (isUrlV6UlaGua(Location)) ? SSDP_IPV6_SITELOCAL : + SSDP_IPV6_LINKLOCAL, &DestAddr6->sin6_addr); + DestAddr6->sin6_port = htons(SSDP_PORT); + DestAddr6->sin6_scope_id = gIF_INDEX; + } else { + UpnpPrintf(UPNP_CRITICAL, SSDP, __FILE__, __LINE__, + "Invalid device address family.\n"); + } + /* sprintf(Mil_Nt,"%s",ServType); */ + sprintf(Mil_Usn, "%s::%s", Udn, ServType); + /* CreateServiceRequestPacket(0,szReq[0],Mil_Nt,Mil_Usn, + * Server,Location,Duration); */ + CreateServicePacket(MSGTYPE_SHUTDOWN, ServType, Mil_Usn, + Location, Duration, &szReq[0], AddressFamily); + if (szReq[0] == NULL) + return UPNP_E_OUTOF_MEMORY; + RetVal = NewRequestHandler((struct sockaddr *)&__ss, 1, szReq); + free(szReq[0]); - /* sprintf(Mil_Nt,"%s",ServType); */ - sprintf( Mil_Usn, "%s::%s", Udn, ServType ); - /* CreateServiceRequestPacket(0,szReq[0],Mil_Nt,Mil_Usn, - * Server,Location,Duration); */ - CreateServicePacket( MSGTYPE_SHUTDOWN, ServType, Mil_Usn, - Location, Duration, &szReq[0], AddressFamily ); - if( szReq[0] == NULL ) { - return UPNP_E_OUTOF_MEMORY; - } - RetVal = NewRequestHandler( (struct sockaddr*)&__ss, 1, szReq ); - - free( szReq[0] ); - return RetVal; + return RetVal; } -/************************************************************************ -* Function : DeviceShutdown -* -* Parameters: -* IN char *DevType: Device Type. -* IN int RootDev:1 means root device. -* IN char * Udn: Device UDN -* IN char * Location: Location URL -* IN int Duration :Device duration in sec. -* IN int AddressFamily: Device address family. -* -* Description: -* This function creates a HTTP device shutdown request packet -* and sent it to the multicast channel through RequestHandler. -* -* Returns: int -* UPNP_E_SUCCESS if successful else appropriate error -***************************************************************************/ -int -DeviceShutdown( IN char *DevType, - IN int RootDev, - IN char *Udn, - IN char *_Server, - IN char *Location, - IN int Duration, - IN int AddressFamily) +int DeviceShutdown(char *DevType, int RootDev, char *Udn, char *_Server, + char *Location, int Duration, int AddressFamily) { - struct sockaddr_storage __ss; - struct sockaddr_in* DestAddr4 = (struct sockaddr_in*)&__ss; - struct sockaddr_in6* DestAddr6 = (struct sockaddr_in6*)&__ss; - char *msgs[3]; - char Mil_Usn[LINE_SIZE]; - int ret_code = UPNP_E_SUCCESS; + struct sockaddr_storage __ss; + struct sockaddr_in *DestAddr4 = (struct sockaddr_in *)&__ss; + struct sockaddr_in6 *DestAddr6 = (struct sockaddr_in6 *)&__ss; + char *msgs[3]; + char Mil_Usn[LINE_SIZE]; + int ret_code = UPNP_E_SUCCESS; - msgs[0] = NULL; - msgs[1] = NULL; - msgs[2] = NULL; + msgs[0] = NULL; + msgs[1] = NULL; + msgs[2] = NULL; + memset(&__ss, 0, sizeof(__ss)); + if (AddressFamily == AF_INET) { + DestAddr4->sin_family = AF_INET; + inet_pton(AF_INET, SSDP_IP, &DestAddr4->sin_addr); + DestAddr4->sin_port = htons(SSDP_PORT); + } else if (AddressFamily == AF_INET6) { + DestAddr6->sin6_family = AF_INET6; + inet_pton(AF_INET6, + (isUrlV6UlaGua(Location)) ? SSDP_IPV6_SITELOCAL : + SSDP_IPV6_LINKLOCAL, &DestAddr6->sin6_addr); + DestAddr6->sin6_port = htons(SSDP_PORT); + DestAddr6->sin6_scope_id = gIF_INDEX; + } else { + UpnpPrintf(UPNP_CRITICAL, SSDP, __FILE__, __LINE__, + "Invalid device address family.\n"); + } + /* root device has one extra msg */ + if (RootDev) { + sprintf(Mil_Usn, "%s::upnp:rootdevice", Udn); + CreateServicePacket(MSGTYPE_SHUTDOWN, "upnp:rootdevice", + Mil_Usn, Location, Duration, &msgs[0], + AddressFamily); + } + UpnpPrintf(UPNP_INFO, SSDP, __FILE__, __LINE__, + "In function DeviceShutdown\n"); + /* both root and sub-devices need to send these two messages */ + CreateServicePacket(MSGTYPE_SHUTDOWN, Udn, Udn, + Location, Duration, &msgs[1], AddressFamily); + sprintf(Mil_Usn, "%s::%s", Udn, DevType); + CreateServicePacket(MSGTYPE_SHUTDOWN, DevType, Mil_Usn, + Location, Duration, &msgs[2], AddressFamily); + /* check error */ + if ((RootDev && msgs[0] == NULL) || msgs[1] == NULL || msgs[2] == NULL) { + free(msgs[0]); + free(msgs[1]); + free(msgs[2]); + return UPNP_E_OUTOF_MEMORY; + } + /* send packets */ + if (RootDev) { + /* send 3 msg types */ + ret_code = + NewRequestHandler((struct sockaddr *)&__ss, 3, &msgs[0]); + } else { + /* sub-device */ + /* send 2 msg types */ + ret_code = + NewRequestHandler((struct sockaddr *)&__ss, 2, &msgs[1]); + } + /* free msgs */ + free(msgs[0]); + free(msgs[1]); + free(msgs[2]); - memset( &__ss, 0, sizeof(__ss) ); - if( AddressFamily == AF_INET ) { - DestAddr4->sin_family = AF_INET; - inet_pton( AF_INET, SSDP_IP, &DestAddr4->sin_addr ); - DestAddr4->sin_port = htons( SSDP_PORT ); - } else if( AddressFamily == AF_INET6 ) { - DestAddr6->sin6_family = AF_INET6; - inet_pton(AF_INET6, - (isUrlV6UlaGua(Location)) ? SSDP_IPV6_SITELOCAL : SSDP_IPV6_LINKLOCAL, - &DestAddr6->sin6_addr ); - DestAddr6->sin6_port = htons( SSDP_PORT ); - DestAddr6->sin6_scope_id = gIF_INDEX; - } else { - UpnpPrintf( UPNP_CRITICAL, SSDP, __FILE__, __LINE__, - "Invalid device address family.\n" ); - } - /* root device has one extra msg */ - if( RootDev ) { - sprintf( Mil_Usn, "%s::upnp:rootdevice", Udn ); - CreateServicePacket( MSGTYPE_SHUTDOWN, "upnp:rootdevice", - Mil_Usn, Location, Duration, &msgs[0], AddressFamily ); - } - UpnpPrintf( UPNP_INFO, SSDP, __FILE__, __LINE__, - "In function DeviceShutdown\n" ); - /* both root and sub-devices need to send these two messages */ - CreateServicePacket( MSGTYPE_SHUTDOWN, Udn, Udn, - Location, Duration, &msgs[1], AddressFamily ); - sprintf( Mil_Usn, "%s::%s", Udn, DevType ); - CreateServicePacket( MSGTYPE_SHUTDOWN, DevType, Mil_Usn, - Location, Duration, &msgs[2], AddressFamily ); - /* check error */ - if( ( RootDev && msgs[0] == NULL ) || - msgs[1] == NULL || msgs[2] == NULL ) { - free( msgs[0] ); - free( msgs[1] ); - free( msgs[2] ); - return UPNP_E_OUTOF_MEMORY; - } - /* send packets */ - if( RootDev ) { - /* send 3 msg types */ - ret_code = NewRequestHandler( (struct sockaddr*)&__ss, 3, &msgs[0] ); - } else { - /* sub-device */ - /* send 2 msg types */ - ret_code = NewRequestHandler( (struct sockaddr*)&__ss, 2, &msgs[1] ); - } - /* free msgs */ - free( msgs[0] ); - free( msgs[1] ); - free( msgs[2] ); - - return ret_code; - _Server = _Server; + return ret_code; + _Server = _Server; } - #endif /* EXCLUDE_SSDP */ #endif /* INCLUDE_DEVICE_APIS */ +/* @} SSDPlib */ diff --git a/upnp/src/ssdp/ssdp_server.c b/upnp/src/ssdp/ssdp_server.c index 19e77d2..545e30a 100644 --- a/upnp/src/ssdp/ssdp_server.c +++ b/upnp/src/ssdp/ssdp_server.c @@ -29,24 +29,33 @@ * **************************************************************************/ -#if !defined(WIN32) +/*! + * \addtogroup SSDPlib + * + * @{ + * + * \file + */ + +#ifndef WIN32 #include -#endif +#endif /* WIN32 */ #include "config.h" - #if EXCLUDE_SSDP == 0 -#include "membuffer.h" #include "ssdplib.h" -#include -#include "ThreadPool.h" -#include "miniserver.h" -#include "upnpapi.h" #include "httpparser.h" #include "httpreadwrite.h" +#include "membuffer.h" +#include "miniserver.h" +#include "sock.h" +#include "ThreadPool.h" +#include "upnpapi.h" + +#include #define MAX_TIME_TOREAD 45 @@ -58,66 +67,31 @@ #endif /* INCLUDE_CLIENT_APIS */ void RequestHandler(); -int create_ssdp_sock_v4( SOCKET* ssdpSock ); -#ifdef UPNP_ENABLE_IPV6 -int create_ssdp_sock_v6( SOCKET* ssdpSock ); -int create_ssdp_sock_v6_ula_gua( SOCKET* ssdpSock ); -#endif -#if INCLUDE_CLIENT_APIS -int create_ssdp_sock_reqv4( SOCKET* ssdpReqSock ); -#ifdef UPNP_ENABLE_IPV6 -int create_ssdp_sock_reqv6( SOCKET* ssdpReqSock ); -#endif -#endif + Event ErrotEvt; -enum Listener { Idle, Stopping, Running }; +enum Listener { + Idle, + Stopping, + Running +}; struct SSDPSockArray { - /* socket for incoming advertisments and search requests */ + /*! socket for incoming advertisments and search requests */ SOCKET ssdpSock; #ifdef INCLUDE_CLIENT_APIS - /* socket for sending search requests and receiving search replies */ + /*! socket for sending search requests and receiving search replies */ int ssdpReqSock; #endif /* INCLUDE_CLIENT_APIS */ }; #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 *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 - ***************************************************************************/ static const char SERVICELIST_STR[] = "serviceList"; -int AdvertiseAndReply( - IN int AdFlag, - IN UpnpDevice_Handle Hnd, - IN enum SsdpSearchType SearchType, - IN struct sockaddr *DestAddr, - IN char *DeviceType, - IN char *DeviceUDN, - IN char *ServiceType, - int Exp) +int AdvertiseAndReply(int AdFlag, UpnpDevice_Handle Hnd, + enum SsdpSearchType SearchType, + struct sockaddr *DestAddr, char *DeviceType, + char *DeviceUDN, char *ServiceType, int Exp) { int retVal = UPNP_E_SUCCESS; long unsigned int i; @@ -138,7 +112,7 @@ int AdvertiseAndReply( int NumCopy = 0; UpnpPrintf(UPNP_ALL, API, __FILE__, __LINE__, - "Inside AdvertiseAndReply with AdFlag = %d\n", AdFlag); + "Inside AdvertiseAndReply with AdFlag = %d\n", AdFlag); /* Use a read lock */ HandleReadLock(); @@ -146,12 +120,9 @@ int AdvertiseAndReply( retVal = UPNP_E_INVALID_HANDLE; goto end_function; } - defaultExp = SInfo->MaxAge; - /* get server info */ get_sdk_info(SERVER); - /* parse the device list and send advertisements/replies */ while (NumCopy == 0 || (AdFlag && NumCopy < NUM_SSDP_COPY)) { if (NumCopy != 0) @@ -159,98 +130,103 @@ int AdvertiseAndReply( NumCopy++; for (i = 0;; i++) { UpnpPrintf(UPNP_ALL, API, __FILE__, __LINE__, - "Entering new device list with i = %lu\n\n", i); + "Entering new device list with i = %lu\n\n", + i); tmpNode = ixmlNodeList_item(SInfo->DeviceList, i); if (!tmpNode) { UpnpPrintf(UPNP_ALL, API, __FILE__, __LINE__, - "Exiting new device list with i = %lu\n\n", i); + "Exiting new device list with i = %lu\n\n", + i); break; } dbgStr = ixmlNode_getNodeName(tmpNode); UpnpPrintf(UPNP_INFO, API, __FILE__, __LINE__, - "Extracting device type once for %s\n", dbgStr); + "Extracting device type once for %s\n", + dbgStr); ixmlNodeList_free(nodeList); - nodeList = ixmlElement_getElementsByTagName( - (IXML_Element *)tmpNode, "deviceType"); + nodeList = ixmlElement_getElementsByTagName((IXML_Element *) tmpNode, "deviceType"); if (!nodeList) continue; UpnpPrintf(UPNP_ALL, API, __FILE__, __LINE__, - "Extracting UDN for %s\n", dbgStr); + "Extracting UDN for %s\n", dbgStr); dbgStr = ixmlNode_getNodeName(tmpNode); UpnpPrintf(UPNP_ALL, API, __FILE__, __LINE__, - "Extracting device type\n"); + "Extracting device type\n"); tmpNode2 = ixmlNodeList_item(nodeList, 0); if (!tmpNode2) continue; textNode = ixmlNode_getFirstChild(tmpNode2); - if (!textNode) continue; - + if (!textNode) + continue; UpnpPrintf(UPNP_ALL, API, __FILE__, __LINE__, - "Extracting device type \n"); + "Extracting device type \n"); tmpStr = ixmlNode_getNodeValue(textNode); if (!tmpStr) continue; strcpy(devType, tmpStr); - UpnpPrintf( UPNP_ALL, API, __FILE__, __LINE__, - "Extracting device type = %s\n", devType); + UpnpPrintf(UPNP_ALL, API, __FILE__, __LINE__, + "Extracting device type = %s\n", devType); if (!tmpNode) { UpnpPrintf(UPNP_ALL, API, __FILE__, __LINE__, - "TempNode is NULL\n"); + "TempNode is NULL\n"); } dbgStr = ixmlNode_getNodeName(tmpNode); UpnpPrintf(UPNP_ALL, API, __FILE__, __LINE__, - "Extracting UDN for %s\n", dbgStr); + "Extracting UDN for %s\n", dbgStr); ixmlNodeList_free(nodeList); - nodeList = ixmlElement_getElementsByTagName( - (IXML_Element *)tmpNode, "UDN"); + nodeList = ixmlElement_getElementsByTagName((IXML_Element *) tmpNode, "UDN"); if (!nodeList) { UpnpPrintf(UPNP_CRITICAL, API, __FILE__, - __LINE__, "UDN not found!\n"); + __LINE__, "UDN not found!\n"); continue; } tmpNode2 = ixmlNodeList_item(nodeList, 0); if (!tmpNode2) { UpnpPrintf(UPNP_CRITICAL, API, __FILE__, - __LINE__, "UDN not found!\n"); + __LINE__, "UDN not found!\n"); continue; } textNode = ixmlNode_getFirstChild(tmpNode2); if (!textNode) { UpnpPrintf(UPNP_CRITICAL, API, __FILE__, - __LINE__, "UDN not found!\n"); + __LINE__, "UDN not found!\n"); continue; } tmpStr = ixmlNode_getNodeValue(textNode); if (!tmpStr) { UpnpPrintf(UPNP_CRITICAL, API, __FILE__, - __LINE__, "UDN not found!\n"); + __LINE__, "UDN not found!\n"); continue; } strcpy(UDNstr, tmpStr); UpnpPrintf(UPNP_INFO, API, __FILE__, __LINE__, - "Sending UDNStr = %s \n", UDNstr); + "Sending UDNStr = %s \n", UDNstr); if (AdFlag) { /* send the device advertisement */ if (AdFlag == 1) { DeviceAdvertisement(devType, i == 0, - UDNstr, SInfo->DescURL, Exp, - SInfo->DeviceAf); + UDNstr, + SInfo->DescURL, Exp, + SInfo->DeviceAf); } else { - /* AdFlag == -1 */ + /* AdFlag == -1 */ DeviceShutdown(devType, i == 0, UDNstr, - SERVER, SInfo->DescURL, Exp, - SInfo->DeviceAf); + SERVER, SInfo->DescURL, + Exp, SInfo->DeviceAf); } } else { switch (SearchType) { case SSDP_ALL: DeviceReply(DestAddr, devType, i == 0, - UDNstr, SInfo->DescURL, defaultExp); + UDNstr, SInfo->DescURL, + defaultExp); break; case SSDP_ROOTDEVICE: if (i == 0) { SendReply(DestAddr, devType, 1, - UDNstr, SInfo->DescURL, defaultExp, 0); + UDNstr, + SInfo->DescURL, + defaultExp, 0); } break; case SSDP_DEVICEUDN: { @@ -264,31 +240,31 @@ int AdvertiseAndReply( 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); + SendReply(DestAddr, devType, 0, UDNstr, SInfo->DescURL, defaultExp, 0); break; } } } case SSDP_DEVICETYPE: { - if (!strncasecmp(DeviceType, devType, strlen(DeviceType)-2)) { - if (atoi(&DeviceType[strlen(DeviceType)-1]) <= atoi(&devType[strlen(devType)-1])) { + if (!strncasecmp(DeviceType, devType, strlen(DeviceType) - 2)) { + if (atoi(&DeviceType[strlen(DeviceType) + - 1]) <= atoi(&devType[strlen(devType) - 1])) { /* the requested version is lower than the device version * must reply with the lower version number */ UpnpPrintf(UPNP_INFO, API, __FILE__, __LINE__, - "DeviceType=%s and search devType=%s MATCH\n", - devType, DeviceType); - SendReply(DestAddr, DeviceType, 0, UDNstr, SInfo->DescURL, defaultExp, 1); + "DeviceType=%s and search devType=%s MATCH\n", + devType, DeviceType); + SendReply(DestAddr, DeviceType, 0, UDNstr, SInfo->DescURL, + defaultExp, 1); } else { UpnpPrintf(UPNP_INFO, API, __FILE__, __LINE__, - "DeviceType=%s and search devType=%s DID NOT MATCH\n", - devType, DeviceType); + "DeviceType=%s and search devType=%s DID NOT MATCH\n", + devType, DeviceType); } } else { UpnpPrintf(UPNP_INFO, API, __FILE__, __LINE__, - "DeviceType=%s and search devType=%s DID NOT MATCH\n", - devType, DeviceType); + "DeviceType=%s and search devType=%s DID NOT MATCH\n", + devType, DeviceType); } break; } @@ -299,8 +275,7 @@ int AdvertiseAndReply( /* send service advertisements for services corresponding * to the same device */ UpnpPrintf(UPNP_INFO, API, __FILE__, __LINE__, - "Sending service Advertisement\n"); - + "Sending service Advertisement\n"); /* Correct service traversal such that each device's serviceList * is directly traversed as a child of its parent device. This * ensures that the service's alive message uses the UDN of @@ -308,7 +283,9 @@ int AdvertiseAndReply( tmpNode = ixmlNode_getFirstChild(tmpNode); while (tmpNode) { dbgStr = ixmlNode_getNodeName(tmpNode); - if (!strncmp(dbgStr, SERVICELIST_STR, sizeof SERVICELIST_STR)) { + if (!strncmp + (dbgStr, SERVICELIST_STR, + sizeof SERVICELIST_STR)) { break; } tmpNode = ixmlNode_getNextSibling(tmpNode); @@ -318,11 +295,10 @@ int AdvertiseAndReply( nodeList = NULL; continue; } - nodeList = ixmlElement_getElementsByTagName( - (IXML_Element *)tmpNode, "service"); + nodeList = ixmlElement_getElementsByTagName((IXML_Element *) tmpNode, "service"); if (!nodeList) { - UpnpPrintf( UPNP_INFO, API, __FILE__, __LINE__, - "Service not found 3\n" ); + UpnpPrintf(UPNP_INFO, API, __FILE__, __LINE__, + "Service not found 3\n"); continue; } for (j = 0;; j++) { @@ -331,58 +307,66 @@ int AdvertiseAndReply( break; } ixmlNodeList_free(tmpNodeList); - tmpNodeList = ixmlElement_getElementsByTagName( - (IXML_Element *)tmpNode, "serviceType"); + tmpNodeList = ixmlElement_getElementsByTagName((IXML_Element *) tmpNode, "serviceType"); if (!tmpNodeList) { - UpnpPrintf(UPNP_CRITICAL, API, __FILE__, __LINE__, - "ServiceType not found \n"); + UpnpPrintf(UPNP_CRITICAL, API, __FILE__, + __LINE__, + "ServiceType not found \n"); continue; } tmpNode2 = ixmlNodeList_item(tmpNodeList, 0); - if (!tmpNode2) continue; + if (!tmpNode2) + continue; textNode = ixmlNode_getFirstChild(tmpNode2); - if (!textNode) continue; + if (!textNode) + continue; /* servType is of format Servicetype:ServiceVersion */ tmpStr = ixmlNode_getNodeValue(textNode); - if (!tmpStr) continue; + if (!tmpStr) + continue; strcpy(servType, tmpStr); UpnpPrintf(UPNP_INFO, API, __FILE__, __LINE__, - "ServiceType = %s\n", servType); + "ServiceType = %s\n", servType); if (AdFlag) { if (AdFlag == 1) { - ServiceAdvertisement(UDNstr, servType, - SInfo->DescURL, Exp, SInfo->DeviceAf ); - } else { + ServiceAdvertisement(UDNstr, + servType, SInfo->DescURL, + Exp, SInfo->DeviceAf); + } else { /* AdFlag == -1 */ - ServiceShutdown(UDNstr, servType, - SInfo->DescURL, Exp, SInfo->DeviceAf ); + ServiceShutdown(UDNstr, + servType, SInfo->DescURL, + Exp, SInfo->DeviceAf); } } else { switch (SearchType) { case SSDP_ALL: ServiceReply(DestAddr, servType, - UDNstr, SInfo->DescURL, - defaultExp); + UDNstr, + SInfo->DescURL, + defaultExp); break; case SSDP_SERVICE: if (ServiceType) { if (!strncasecmp(ServiceType, servType, strlen(ServiceType) - 2)) { - if (atoi(&ServiceType[strlen(ServiceType)-1]) <= atoi(&servType[strlen(servType)-1])) { + if (atoi(&ServiceType[strlen(ServiceType) - 1]) <= + atoi(&servType[strlen(servType) - 1])) { /* the requested version is lower than the service version * must reply with the lower version number */ UpnpPrintf(UPNP_INFO, API, __FILE__, __LINE__, - "ServiceType=%s and search servType=%s MATCH\n", - ServiceType, servType); - SendReply(DestAddr, ServiceType, 0, UDNstr, SInfo->DescURL, defaultExp, 1); + "ServiceType=%s and search servType=%s MATCH\n", + ServiceType, servType); + SendReply(DestAddr, ServiceType, 0, UDNstr, SInfo->DescURL, + defaultExp, 1); } else { UpnpPrintf(UPNP_INFO, API, __FILE__, __LINE__, - "ServiceType=%s and search servType=%s DID NOT MATCH\n", - ServiceType, servType); + "ServiceType=%s and search servType=%s DID NOT MATCH\n", + ServiceType, servType); } } else { UpnpPrintf(UPNP_INFO, API, __FILE__, __LINE__, - "ServiceType=%s and search servType=%s DID NOT MATCH\n", - ServiceType, servType); + "ServiceType=%s and search servType=%s DID NOT MATCH\n", + ServiceType, servType); } } break; @@ -401,63 +385,15 @@ int AdvertiseAndReply( end_function: ixmlNodeList_free(tmpNodeList); ixmlNodeList_free(nodeList); - UpnpPrintf(UPNP_ALL, API, __FILE__, __LINE__, - "Exiting AdvertiseAndReply.\n"); - + "Exiting AdvertiseAndReply.\n"); HandleUnlock(); return retVal; } - -#endif /* EXCLUDE_SSDP == 0 */ #endif /* INCLUDE_DEVICE_APIS */ -/************************************************************************ - * Function : Make_Socket_NoBlocking - * - * Parameters: - * IN SOCKET sock: socket - * - * Description: - * This function makes socket non-blocking. - * - * Returns: int - * 0 if successful else -1 - ***************************************************************************/ -int -Make_Socket_NoBlocking( SOCKET sock ) -{ -#ifdef WIN32 - u_long val=1; - return ioctlsocket(sock, FIONBIO, &val); -#else - int val; - - val = fcntl( sock, F_GETFL, 0 ); - if( fcntl( sock, F_SETFL, val | O_NONBLOCK ) == -1 ) { - return -1; - } -#endif - return 0; -} - -/************************************************************************ - * Function : unique_service_name - * - * Parameters: - * IN char *cmd: Service Name string - * OUT SsdpEvent *Evt: The SSDP event structure partially filled - * by all the function. - * - * Description: - * This function fills the fields of the event structure like DeviceType, - * Device UDN and Service Type - * - * Returns: int - * 0 if successful else -1 - ***************************************************************************/ -int unique_service_name(IN char *cmd, IN SsdpEvent *Evt) +int unique_service_name(char *cmd, SsdpEvent *Evt) { char TempBuf[COMMAND_LEN]; char *TempPtr = NULL; @@ -484,7 +420,7 @@ int unique_service_name(IN char *cmd, IN SsdpEvent *Evt) return -1; ptr1 = strstr(cmd, ":"); if (ptr1 != NULL) { - n = (size_t)(ptr3 - ptr1); + n = (size_t) (ptr3 - ptr1); strncpy(TempBuf, ptr1, n); TempBuf[n] = '\0'; sprintf(Evt->DeviceType, "urn%s", TempBuf); @@ -494,7 +430,7 @@ int unique_service_name(IN char *cmd, IN SsdpEvent *Evt) } if ((TempPtr = strstr(cmd, "uuid")) != NULL) { if ((Ptr = strstr(cmd, "::")) != NULL) { - n = (size_t)(Ptr - TempPtr); + n = (size_t) (Ptr - TempPtr); strncpy(Evt->UDN, TempPtr, n); Evt->UDN[n] = '\0'; } else @@ -516,7 +452,7 @@ int unique_service_name(IN char *cmd, IN SsdpEvent *Evt) if ((TempPtr = strstr(cmd, "::upnp:rootdevice")) != NULL) { /* Everything before "::upnp::rootdevice" is the UDN. */ if (TempPtr != cmd) { - n = (size_t)(TempPtr - cmd); + n = (size_t) (TempPtr - cmd); strncpy(Evt->UDN, cmd, n); Evt->UDN[n] = 0; CommandFound = 1; @@ -528,110 +464,61 @@ int unique_service_name(IN char *cmd, IN SsdpEvent *Evt) return 0; } -/************************************************************************ - * Function : ssdp_request_type1 - * - * Parameters: - * IN char *cmd: command came in the ssdp request - * - * Description: - * This function figures out the type of the SSDP search in the - * in the request. - * - * Returns: enum SsdpSearchType - * return appropriate search type else returns SSDP_ERROR - ***************************************************************************/ -enum SsdpSearchType -ssdp_request_type1( IN char *cmd ) +enum SsdpSearchType ssdp_request_type1(char *cmd) { - if( strstr( cmd, ":all" ) != NULL ) { - return SSDP_ALL; - } - if( strstr( cmd, ":rootdevice" ) != NULL ) { - return SSDP_ROOTDEVICE; - } - if( strstr( cmd, "uuid:" ) != NULL ) { - return SSDP_DEVICEUDN; - } - if( ( strstr( cmd, "urn:" ) != NULL ) - && ( strstr( cmd, ":device:" ) != NULL ) ) { - return SSDP_DEVICETYPE; - } - if( ( strstr( cmd, "urn:" ) != NULL ) - && ( strstr( cmd, ":service:" ) != NULL ) ) { - return SSDP_SERVICE; - } - return SSDP_SERROR; + if (strstr(cmd, ":all")) + return SSDP_ALL; + if (strstr(cmd, ":rootdevice")) + return SSDP_ROOTDEVICE; + if (strstr(cmd, "uuid:")) + return SSDP_DEVICEUDN; + if (strstr(cmd, "urn:") && strstr(cmd, ":device:")) + return SSDP_DEVICETYPE; + if (strstr(cmd, "urn:") && strstr(cmd, ":service:")) + return SSDP_SERVICE; + return SSDP_SERROR; } -/************************************************************************ - * Function : ssdp_request_type - * - * Parameters: - * IN char *cmd: command came in the ssdp request - * OUT SsdpEvent *Evt: The event structure partially filled by - * this function. - * - * Description: - * This function starts filling the SSDP event structure based upon the - * request received. - * - * Returns: int - * 0 on success; -1 on error - ***************************************************************************/ -int ssdp_request_type(IN char *cmd, OUT SsdpEvent *Evt) +int ssdp_request_type(char *cmd, SsdpEvent *Evt) { - /* clear event */ - memset( Evt, 0, sizeof( SsdpEvent ) ); - unique_service_name( cmd, Evt ); - Evt->ErrCode = NO_ERROR_FOUND; - - if( ( Evt->RequestType = ssdp_request_type1( cmd ) ) == SSDP_SERROR ) { - Evt->ErrCode = E_HTTP_SYNTEX; - return -1; - } - return 0; + /* clear event */ + memset(Evt, 0, sizeof(SsdpEvent)); + unique_service_name(cmd, Evt); + Evt->ErrCode = NO_ERROR_FOUND; + if ((Evt->RequestType = ssdp_request_type1(cmd)) == SSDP_SERROR) { + Evt->ErrCode = E_HTTP_SYNTEX; + return -1; + } + return 0; } -/************************************************************************ - * Function : free_ssdp_event_handler_data - * - * Parameters: - * IN void *the_data: ssdp_thread_data structure. This structure contains - * SSDP request message. - * - * Description: - * This function frees the ssdp request - * - * Returns: VOID - * - ***************************************************************************/ -static void free_ssdp_event_handler_data(void *the_data) +/*! + * \brief Frees the ssdp request. + */ +static void free_ssdp_event_handler_data( + /*! [in] ssdp_thread_data structure. This structure contains SSDP + * request message. */ + void *the_data) { - ssdp_thread_data *data = ( ssdp_thread_data * ) the_data; + ssdp_thread_data *data = (ssdp_thread_data *) the_data; - if( data != NULL ) { - http_message_t *hmsg = &data->parser.msg; - /* free data */ - httpmsg_destroy( hmsg ); - free( data ); - } + if (data != NULL) { + http_message_t *hmsg = &data->parser.msg; + /* free data */ + httpmsg_destroy(hmsg); + free(data); + } } -/************************************************************************ - * Function : valid_ssdp_msg +/*! + * \brief Does some quick checking of the ssdp msg. * - * Parameters: - * IN void *the_data: ssdp_thread_data structure. This structure contains - * SSDP request message. - * - * Description: - * This function do some quick checking of the ssdp msg - * - * Returns: int - * returns TRUE if msg is valid else FALSE - ***************************************************************************/ -static UPNP_INLINE int valid_ssdp_msg(IN http_message_t *hmsg) + * \return TRUE if msg is valid, else FALSE. + */ +static UPNP_INLINE int valid_ssdp_msg( + /*! [in] ssdp_thread_data structure. This structure contains SSDP + * request message. */ + http_message_t * hmsg) { memptr hdr_value; @@ -644,8 +531,9 @@ static UPNP_INLINE int valid_ssdp_msg(IN http_message_t *hmsg) if (hmsg->request_method != HTTPMETHOD_MSEARCH) { /* check PATH == "*" */ if (hmsg->uri.type != RELATIVE || - strncmp("*", hmsg->uri.pathquery.buff, hmsg->uri.pathquery.size) != 0) { - return FALSE; + strncmp("*", hmsg->uri.pathquery.buff, + hmsg->uri.pathquery.size) != 0) { + return FALSE; } /* check HOST header */ if (httpmsg_find_hdr(hmsg, HDR_HOST, &hdr_value) == NULL || @@ -655,7 +543,7 @@ static UPNP_INLINE int valid_ssdp_msg(IN http_message_t *hmsg) memptr_cmp(&hdr_value, "[FF05::C]:1900") != 0 && memptr_cmp(&hdr_value, "[ff05::c]:1900") != 0)) { UpnpPrintf(UPNP_INFO, SSDP, __FILE__, __LINE__, - "Invalid HOST header from SSDP message\n"); + "Invalid HOST header from SSDP message\n"); return FALSE; } @@ -665,104 +553,80 @@ static UPNP_INLINE int valid_ssdp_msg(IN http_message_t *hmsg) return TRUE; } -/************************************************************************ - * Function : start_event_handler +/*! + * \brief Parses the message and dispatches it to a handler which handles the + * ssdp request msg. * - * Parameters: - * IN void *the_data: ssdp_thread_data structure. This structure contains - * SSDP request message. - * - * Description: - * This function parses the message and dispatches it to a handler - * which handles the ssdp request msg - * - * Returns: int - * 0 if successful -1 if error - ***************************************************************************/ -static UPNP_INLINE int start_event_handler(void *Data) + * \return 0 if successful, -1 if error. + */ +static UPNP_INLINE int start_event_handler( + /*! [in] ssdp_thread_data structure. This structure contains SSDP + * request message. */ + void *Data) { + http_parser_t *parser = NULL; + parse_status_t status; + ssdp_thread_data *data = (ssdp_thread_data *) Data; - http_parser_t *parser = NULL; - parse_status_t status; - ssdp_thread_data *data = ( ssdp_thread_data * ) Data; + parser = &data->parser; + status = parser_parse(parser); + if (status == PARSE_FAILURE) { + if (parser->msg.method != HTTPMETHOD_NOTIFY || + !parser->valid_ssdp_notify_hack) { + UpnpPrintf(UPNP_INFO, SSDP, __FILE__, __LINE__, + "SSDP recvd bad msg code = %d\n", status); + /* ignore bad msg, or not enuf mem */ + goto error_handler; + } + /* valid notify msg */ + } else if (status != PARSE_SUCCESS) { + UpnpPrintf(UPNP_INFO, SSDP, __FILE__, __LINE__, + "SSDP recvd bad msg code = %d\n", status); - parser = &data->parser; + goto error_handler; + } + /* check msg */ + if (valid_ssdp_msg(&parser->msg) != TRUE) { + goto error_handler; + } + /* done; thread will free 'data' */ + return 0; - status = parser_parse( parser ); - if( status == PARSE_FAILURE ) { - if( parser->msg.method != HTTPMETHOD_NOTIFY || - !parser->valid_ssdp_notify_hack ) { - UpnpPrintf( UPNP_INFO, SSDP, __FILE__, __LINE__, - "SSDP recvd bad msg code = %d\n", - status ); - /* ignore bad msg, or not enuf mem */ - goto error_handler; - } - /* valid notify msg */ - } else if( status != PARSE_SUCCESS ) { - UpnpPrintf( UPNP_INFO, SSDP, __FILE__, __LINE__, - "SSDP recvd bad msg code = %d\n", status ); - - goto error_handler; - } - /* check msg */ - if( valid_ssdp_msg( &parser->msg ) != TRUE ) { - goto error_handler; - } - return 0; /* done; thread will free 'data' */ - -error_handler: - free_ssdp_event_handler_data( data ); - return -1; + error_handler: + free_ssdp_event_handler_data(data); + return -1; } -/************************************************************************ - * Function : ssdp_event_handler_thread - * - * Parameters: - * IN void *the_data: ssdp_thread_data structure. This structure contains - * SSDP request message. - * - * Description: - * This function is a thread that handles SSDP requests. - * - * Returns: void - * - ***************************************************************************/ -static void ssdp_event_handler_thread(void *the_data) +/*! + * \brief This function is a thread that handles SSDP requests. + */ +static void ssdp_event_handler_thread( + /*! [] ssdp_thread_data structure. This structure contains SSDP + * request message. */ + void *the_data) { - ssdp_thread_data *data = (ssdp_thread_data *)the_data; + ssdp_thread_data *data = (ssdp_thread_data *) the_data; http_message_t *hmsg = &data->parser.msg; - if (start_event_handler(the_data) != 0) { + if (start_event_handler(the_data) != 0) return; - } /* send msg to device or ctrlpt */ if (hmsg->method == HTTPMETHOD_NOTIFY || hmsg->request_method == HTTPMETHOD_MSEARCH) { #ifdef INCLUDE_CLIENT_APIS - ssdp_handle_ctrlpt_msg(hmsg, (struct sockaddr *)&data->dest_addr, FALSE, NULL); + ssdp_handle_ctrlpt_msg(hmsg, + (struct sockaddr *)&data->dest_addr, + FALSE, NULL); #endif /* INCLUDE_CLIENT_APIS */ } else { - ssdp_handle_device_request(hmsg, (struct sockaddr *)&data->dest_addr); + ssdp_handle_device_request(hmsg, + (struct sockaddr *)&data->dest_addr); } /* free data */ free_ssdp_event_handler_data(data); } -/************************************************************************ - * Function : readFromSSDPSocket - * - * Parameters: - * IN SOCKET socket: SSDP socket - * - * Description: - * This function reads the data from the ssdp socket. - * - * Returns: void - * - ***************************************************************************/ void readFromSSDPSocket(SOCKET socket) { char *requestBuf = NULL; @@ -781,17 +645,14 @@ void readFromSSDPSocket(SOCKET socket) if (data) { /* initialize parser */ #ifdef INCLUDE_CLIENT_APIS -#ifdef UPNP_ENABLE_IPV6 - if (socket == gSsdpReqSocket4 || socket == gSsdpReqSocket6) + if (socket == gSsdpReqSocket4 + #ifdef UPNP_ENABLE_IPV6 + || socket == gSsdpReqSocket6 + #endif /* UPNP_ENABLE_IPV6 */ + ) parser_response_init(&data->parser, HTTPMETHOD_MSEARCH); else parser_request_init(&data->parser); -#else /* UPNP_ENABLE_IPV6 */ - if (socket == gSsdpReqSocket4) - parser_response_init(&data->parser, HTTPMETHOD_MSEARCH); - else - parser_request_init(&data->parser); -#endif /* UPNP_ENABLE_IPV6 */ #else /* INCLUDE_CLIENT_APIS */ parser_request_init(&data->parser); #endif /* INCLUDE_CLIENT_APIS */ @@ -805,30 +666,30 @@ void readFromSSDPSocket(SOCKET socket) } } byteReceived = recvfrom(socket, requestBuf, BUFSIZE - 1, 0, - (struct sockaddr *)&__ss, &socklen); + (struct sockaddr *)&__ss, &socklen); if (byteReceived > 0) { requestBuf[byteReceived] = '\0'; if (__ss.ss_family == AF_INET) inet_ntop(AF_INET, - &((struct sockaddr_in *)&__ss)->sin_addr, - ntop_buf, sizeof(ntop_buf)); + &((struct sockaddr_in *)&__ss)->sin_addr, + ntop_buf, sizeof(ntop_buf)); #ifdef UPNP_ENABLE_IPV6 else if (__ss.ss_family == AF_INET6) inet_ntop(AF_INET6, - &((struct sockaddr_in6 *)&__ss)->sin6_addr, - ntop_buf, sizeof(ntop_buf)); -#endif + &((struct sockaddr_in6 *)&__ss)->sin6_addr, + ntop_buf, sizeof(ntop_buf)); +#endif /* UPNP_ENABLE_IPV6 */ else strncpy(ntop_buf, "", sizeof(ntop_buf)); UpnpPrintf(UPNP_INFO, SSDP, __FILE__, __LINE__, - "Start of received response ----------------------------------------------------\n" - "%s\n" - "End of received response ------------------------------------------------------\n" - "From host %s\n", requestBuf, ntop_buf); + "Start of received response ----------------------------------------------------\n" + "%s\n" + "End of received response ------------------------------------------------------\n" + "From host %s\n", requestBuf, ntop_buf); /* add thread pool job to handle request */ if (data != NULL) { - data->parser.msg.msg.length += (size_t)byteReceived; + data->parser.msg.msg.length += (size_t) byteReceived; /* null-terminate */ data->parser.msg.msg.buf[byteReceived] = 0; memcpy(&data->dest_addr, &__ss, sizeof(__ss)); @@ -844,34 +705,394 @@ void readFromSSDPSocket(SOCKET socket) free_ssdp_event_handler_data(data); } +/*! + * \brief + */ +static int create_ssdp_sock_v4( + /*! [] SSDP IPv4 socket to be created. */ + SOCKET *ssdpSock) +{ + char errorBuffer[ERROR_BUFFER_LEN]; + int onOff; + u_char ttl = 4; + struct ip_mreq ssdpMcastAddr; + struct sockaddr_storage __ss; + struct sockaddr_in *ssdpAddr4 = (struct sockaddr_in *)&__ss; + int ret = 0; + struct in_addr addr; -/************************************************************************ - * Function : get_ssdp_sockets + *ssdpSock = socket(AF_INET, SOCK_DGRAM, 0); + if (*ssdpSock == -1) { + strerror_r(errno, errorBuffer, ERROR_BUFFER_LEN); + UpnpPrintf(UPNP_CRITICAL, SSDP, __FILE__, __LINE__, + "Error in socket(): %s\n", errorBuffer); + + return UPNP_E_OUTOF_SOCKET; + } + onOff = 1; + ret = setsockopt(*ssdpSock, SOL_SOCKET, SO_REUSEADDR, + (char *)&onOff, sizeof(onOff)); + if (ret == -1) { + strerror_r(errno, errorBuffer, ERROR_BUFFER_LEN); + UpnpPrintf(UPNP_CRITICAL, SSDP, __FILE__, __LINE__, + "Error in setsockopt() SO_REUSEADDR: %s\n", + errorBuffer); + shutdown(*ssdpSock, SD_BOTH); + UpnpCloseSocket(*ssdpSock); + + return UPNP_E_SOCKET_ERROR; + } +#if defined(BSD) || defined(__OSX__) || defined(__APPLE__) + onOff = 1; + ret = setsockopt(*ssdpSock, SOL_SOCKET, SO_REUSEPORT, + (char *)&onOff, sizeof(onOff)); + if (ret == -1) { + strerror_r(errno, errorBuffer, ERROR_BUFFER_LEN); + UpnpPrintf(UPNP_CRITICAL, SSDP, __FILE__, __LINE__, + "Error in setsockopt() SO_REUSEPORT: %s\n", + errorBuffer); + shutdown(*ssdpSock, SD_BOTH); + UpnpCloseSocket(*ssdpSock); + + return UPNP_E_SOCKET_ERROR; + } +#endif /* BSD, __OSX__, __APPLE__ */ + memset(&__ss, 0, sizeof(__ss)); + ssdpAddr4->sin_family = AF_INET; + ssdpAddr4->sin_addr.s_addr = htonl(INADDR_ANY); + ssdpAddr4->sin_port = htons(SSDP_PORT); + ret = bind(*ssdpSock, (struct sockaddr *)ssdpAddr4, sizeof(*ssdpAddr4)); + if (ret == -1) { + strerror_r(errno, errorBuffer, ERROR_BUFFER_LEN); + UpnpPrintf(UPNP_CRITICAL, SSDP, __FILE__, __LINE__, + "Error in bind(), addr=0x%08X, port=%d: %s\n", + INADDR_ANY, SSDP_PORT, errorBuffer); + shutdown(*ssdpSock, SD_BOTH); + UpnpCloseSocket(*ssdpSock); + + return UPNP_E_SOCKET_BIND; + } + memset((void *)&ssdpMcastAddr, 0, sizeof(struct ip_mreq)); + ssdpMcastAddr.imr_interface.s_addr = inet_addr(gIF_IPV4); + ssdpMcastAddr.imr_multiaddr.s_addr = inet_addr(SSDP_IP); + ret = setsockopt(*ssdpSock, IPPROTO_IP, IP_ADD_MEMBERSHIP, + (char *)&ssdpMcastAddr, sizeof(struct ip_mreq)); + if (ret == -1) { + strerror_r(errno, errorBuffer, ERROR_BUFFER_LEN); + UpnpPrintf(UPNP_CRITICAL, SSDP, __FILE__, __LINE__, + "Error in setsockopt() IP_ADD_MEMBERSHIP (join multicast group): %s\n", + errorBuffer); + shutdown(*ssdpSock, SD_BOTH); + UpnpCloseSocket(*ssdpSock); + + return UPNP_E_SOCKET_ERROR; + } + /* Set multicast interface. */ + memset((void *)&addr, 0, sizeof(struct in_addr)); + addr.s_addr = inet_addr(gIF_IPV4); + ret = setsockopt(*ssdpSock, IPPROTO_IP, IP_MULTICAST_IF, + (char *)&addr, sizeof addr); + if (ret == -1) { + strerror_r(errno, errorBuffer, ERROR_BUFFER_LEN); + UpnpPrintf(UPNP_INFO, SSDP, __FILE__, __LINE__, + "Error in setsockopt() IP_MULTICAST_IF (set multicast interface): %s\n", + errorBuffer); + /* This is probably not a critical error, so let's continue. */ + } + /* result is not checked becuase it will fail in WinMe and Win9x. */ + ret = setsockopt(*ssdpSock, IPPROTO_IP, + IP_MULTICAST_TTL, &ttl, sizeof(ttl)); + onOff = 1; + ret = setsockopt(*ssdpSock, SOL_SOCKET, SO_BROADCAST, + (char *)&onOff, sizeof(onOff)); + if (ret == -1) { + strerror_r(errno, errorBuffer, ERROR_BUFFER_LEN); + UpnpPrintf(UPNP_CRITICAL, SSDP, __FILE__, __LINE__, + "Error in setsockopt() SO_BROADCAST (set broadcast): %s\n", + errorBuffer); + shutdown(*ssdpSock, SD_BOTH); + UpnpCloseSocket(*ssdpSock); + + return UPNP_E_NETWORK_ERROR; + } + + return UPNP_E_SUCCESS; +} + +#if INCLUDE_CLIENT_APIS +/*! + * \brief Creates the SSDP IPv4 socket to be used by the control point. * - * Parameters: - * OUT MiniServerSockArray *out: Array of SSDP sockets - * - * Description: - * This function creates the IPv4 and IPv6 ssdp sockets required by the - * control point and device operation. - * - * Returns: int - * return UPNP_E_SUCCESS if successful else returns appropriate error - ***************************************************************************/ -int get_ssdp_sockets(MiniServerSockArray *out) + * \return UPNP_E_SUCCESS on successful socket creation. + */ +static int create_ssdp_sock_reqv4( + /*! [out] SSDP IPv4 request socket to be created. */ + SOCKET *ssdpReqSock) +{ + char errorBuffer[ERROR_BUFFER_LEN]; + u_char ttl = 4; + + *ssdpReqSock = socket(AF_INET, SOCK_DGRAM, 0); + if (*ssdpReqSock == -1) { + strerror_r(errno, errorBuffer, ERROR_BUFFER_LEN); + UpnpPrintf(UPNP_CRITICAL, SSDP, __FILE__, __LINE__, + "Error in socket(): %s\n", errorBuffer); + return UPNP_E_OUTOF_SOCKET; + } + setsockopt(*ssdpReqSock, IPPROTO_IP, IP_MULTICAST_TTL, + &ttl, sizeof(ttl)); + /* just do it, regardless if fails or not. */ + sock_make_no_blocking(*ssdpReqSock); + + return UPNP_E_SUCCESS; +} + +#ifdef UPNP_ENABLE_IPV6 +/*! + * \brief This function ... + */ +static int create_ssdp_sock_v6( + /* [] SSDP IPv6 socket to be created. */ + SOCKET *ssdpSock) +{ + char errorBuffer[ERROR_BUFFER_LEN]; + struct ipv6_mreq ssdpMcastAddr; + struct sockaddr_storage __ss; + struct sockaddr_in6 *ssdpAddr6 = (struct sockaddr_in6 *)&__ss; + int onOff; + int ret = 0; + + *ssdpSock = socket(AF_INET6, SOCK_DGRAM, 0); + if (*ssdpSock == -1) { + strerror_r(errno, errorBuffer, ERROR_BUFFER_LEN); + UpnpPrintf(UPNP_CRITICAL, SSDP, __FILE__, __LINE__, + "Error in socket(): %s\n", errorBuffer); + + return UPNP_E_OUTOF_SOCKET; + } + onOff = 1; + ret = setsockopt(*ssdpSock, SOL_SOCKET, SO_REUSEADDR, + (char *)&onOff, sizeof(onOff)); + if (ret == -1) { + strerror_r(errno, errorBuffer, ERROR_BUFFER_LEN); + UpnpPrintf(UPNP_CRITICAL, SSDP, __FILE__, __LINE__, + "Error in setsockopt() SO_REUSEADDR: %s\n", + errorBuffer); + shutdown(*ssdpSock, SD_BOTH); + UpnpCloseSocket(*ssdpSock); + + return UPNP_E_SOCKET_ERROR; + } +#if defined(BSD) || defined(__OSX__) || defined(__APPLE__) + onOff = 1; + ret = setsockopt(*ssdpSock, SOL_SOCKET, SO_REUSEPORT, + (char *)&onOff, sizeof(onOff)); + if (ret == -1) { + strerror_r(errno, errorBuffer, ERROR_BUFFER_LEN); + UpnpPrintf(UPNP_CRITICAL, SSDP, __FILE__, __LINE__, + "Error in setsockopt() SO_REUSEPORT: %s\n", + errorBuffer); + shutdown(*ssdpSock, SD_BOTH); + UpnpCloseSocket(*ssdpSock); + + return UPNP_E_SOCKET_ERROR; + } +#endif /* BSD, __OSX__, __APPLE__ */ + memset(&__ss, 0, sizeof(__ss)); + ssdpAddr6->sin6_family = AF_INET6; + ssdpAddr6->sin6_addr = in6addr_any; + ssdpAddr6->sin6_scope_id = gIF_INDEX; + ssdpAddr6->sin6_port = htons(SSDP_PORT); + ret = bind(*ssdpSock, (struct sockaddr *)ssdpAddr6, sizeof(*ssdpAddr6)); + if (ret == -1) { + strerror_r(errno, errorBuffer, ERROR_BUFFER_LEN); + UpnpPrintf(UPNP_CRITICAL, SSDP, __FILE__, __LINE__, + "Error in bind(), addr=0x%032lX, port=%d: %s\n", + 0lu, SSDP_PORT, errorBuffer); + shutdown(*ssdpSock, SD_BOTH); + UpnpCloseSocket(*ssdpSock); + + return UPNP_E_SOCKET_BIND; + } + memset((void *)&ssdpMcastAddr, 0, sizeof(ssdpMcastAddr)); + ssdpMcastAddr.ipv6mr_interface = gIF_INDEX; + inet_pton(AF_INET6, SSDP_IPV6_LINKLOCAL, + &ssdpMcastAddr.ipv6mr_multiaddr); + ret = setsockopt(*ssdpSock, IPPROTO_IPV6, IPV6_JOIN_GROUP, + (char *)&ssdpMcastAddr, sizeof(ssdpMcastAddr)); + if (ret == -1) { + strerror_r(errno, errorBuffer, ERROR_BUFFER_LEN); + UpnpPrintf(UPNP_CRITICAL, SSDP, __FILE__, __LINE__, + "Error in setsockopt() IPV6_JOIN_GROUP (join multicast group): %s\n", + errorBuffer); + shutdown(*ssdpSock, SD_BOTH); + UpnpCloseSocket(*ssdpSock); + + return UPNP_E_SOCKET_ERROR; + } + onOff = 1; + ret = setsockopt(*ssdpSock, SOL_SOCKET, SO_BROADCAST, + (char *)&onOff, sizeof(onOff)); + if (ret == -1) { + strerror_r(errno, errorBuffer, ERROR_BUFFER_LEN); + UpnpPrintf(UPNP_CRITICAL, SSDP, __FILE__, __LINE__, + "Error in setsockopt() SO_BROADCAST (set broadcast): %s\n", + errorBuffer); + shutdown(*ssdpSock, SD_BOTH); + UpnpCloseSocket(*ssdpSock); + + return UPNP_E_NETWORK_ERROR; + } + + return UPNP_E_SUCCESS; +} +#endif /* IPv6 */ + +#ifdef UPNP_ENABLE_IPV6 +/*! + * \brief This function ... + */ +static int create_ssdp_sock_v6_ula_gua( + /*! [] SSDP IPv6 socket to be created. */ + SOCKET * ssdpSock) +{ + char errorBuffer[ERROR_BUFFER_LEN]; + struct ipv6_mreq ssdpMcastAddr; + struct sockaddr_storage __ss; + struct sockaddr_in6 *ssdpAddr6 = (struct sockaddr_in6 *)&__ss; + int onOff; + int ret = 0; + + *ssdpSock = socket(AF_INET6, SOCK_DGRAM, 0); + if (*ssdpSock == -1) { + strerror_r(errno, errorBuffer, ERROR_BUFFER_LEN); + UpnpPrintf(UPNP_CRITICAL, SSDP, __FILE__, __LINE__, + "Error in socket(): %s\n", errorBuffer); + + return UPNP_E_OUTOF_SOCKET; + } + onOff = 1; + ret = setsockopt(*ssdpSock, SOL_SOCKET, SO_REUSEADDR, + (char *)&onOff, sizeof(onOff)); + if (ret == -1) { + strerror_r(errno, errorBuffer, ERROR_BUFFER_LEN); + UpnpPrintf(UPNP_CRITICAL, SSDP, __FILE__, __LINE__, + "Error in setsockopt() SO_REUSEADDR: %s\n", + errorBuffer); + shutdown(*ssdpSock, SD_BOTH); + UpnpCloseSocket(*ssdpSock); + + return UPNP_E_SOCKET_ERROR; + } +#if defined(BSD) || defined(__OSX__) || defined(__APPLE__) + onOff = 1; + ret = setsockopt(*ssdpSock, SOL_SOCKET, SO_REUSEPORT, + (char *)&onOff, sizeof(onOff)); + if (ret == -1) { + strerror_r(errno, errorBuffer, ERROR_BUFFER_LEN); + UpnpPrintf(UPNP_CRITICAL, SSDP, __FILE__, __LINE__, + "Error in setsockopt() SO_REUSEPORT: %s\n", + errorBuffer); + shutdown(*ssdpSock, SD_BOTH); + UpnpCloseSocket(*ssdpSock); + + return UPNP_E_SOCKET_ERROR; + } +#endif /* BSD, __OSX__, __APPLE__ */ + memset(&__ss, 0, sizeof(__ss)); + ssdpAddr6->sin6_family = AF_INET6; + ssdpAddr6->sin6_addr = in6addr_any; + ssdpAddr6->sin6_scope_id = gIF_INDEX; + ssdpAddr6->sin6_port = htons(SSDP_PORT); + ret = bind(*ssdpSock, (struct sockaddr *)ssdpAddr6, sizeof(*ssdpAddr6)); + if (ret == -1) { + strerror_r(errno, errorBuffer, ERROR_BUFFER_LEN); + UpnpPrintf(UPNP_CRITICAL, SSDP, __FILE__, __LINE__, + "Error in bind(), addr=0x%032lX, port=%d: %s\n", + 0lu, SSDP_PORT, errorBuffer); + shutdown(*ssdpSock, SD_BOTH); + UpnpCloseSocket(*ssdpSock); + + return UPNP_E_SOCKET_BIND; + } + memset((void *)&ssdpMcastAddr, 0, sizeof(ssdpMcastAddr)); + ssdpMcastAddr.ipv6mr_interface = gIF_INDEX; + /* SITE LOCAL */ + inet_pton(AF_INET6, SSDP_IPV6_SITELOCAL, + &ssdpMcastAddr.ipv6mr_multiaddr); + ret = setsockopt(*ssdpSock, IPPROTO_IPV6, IPV6_JOIN_GROUP, + (char *)&ssdpMcastAddr, sizeof(ssdpMcastAddr)); + if (ret == -1) { + strerror_r(errno, errorBuffer, ERROR_BUFFER_LEN); + UpnpPrintf(UPNP_CRITICAL, SSDP, __FILE__, __LINE__, + "Error in setsockopt() IPV6_JOIN_GROUP (join multicast group): %s\n", + errorBuffer); + shutdown(*ssdpSock, SD_BOTH); + UpnpCloseSocket(*ssdpSock); + + return UPNP_E_SOCKET_ERROR; + } + onOff = 1; + ret = setsockopt(*ssdpSock, SOL_SOCKET, SO_BROADCAST, + (char *)&onOff, sizeof(onOff)); + if (ret == -1) { + strerror_r(errno, errorBuffer, ERROR_BUFFER_LEN); + UpnpPrintf(UPNP_CRITICAL, SSDP, __FILE__, __LINE__, + "Error in setsockopt() SO_BROADCAST (set broadcast): %s\n", + errorBuffer); + shutdown(*ssdpSock, SD_BOTH); + UpnpCloseSocket(*ssdpSock); + + return UPNP_E_NETWORK_ERROR; + } + + return UPNP_E_SUCCESS; +} +#endif /* IPv6 */ + +/*! + * \brief Creates the SSDP IPv6 socket to be used by the control point. + */ +#ifdef UPNP_ENABLE_IPV6 +static int create_ssdp_sock_reqv6( + /* [out] SSDP IPv6 request socket to be created. */ + SOCKET *ssdpReqSock) +{ + char errorBuffer[ERROR_BUFFER_LEN]; + char hops = 1; + + *ssdpReqSock = socket(AF_INET6, SOCK_DGRAM, 0); + if (*ssdpReqSock == -1) { + strerror_r(errno, errorBuffer, ERROR_BUFFER_LEN); + UpnpPrintf(UPNP_CRITICAL, SSDP, __FILE__, __LINE__, + "Error in socket(): %s\n", errorBuffer); + return UPNP_E_OUTOF_SOCKET; + } + /* MUST use scoping of IPv6 addresses to control the propagation os SSDP + * messages instead of relying on the Hop Limit (Equivalent to the TTL + * limit in IPv4). */ + setsockopt(*ssdpReqSock, IPPROTO_IPV6, IPV6_MULTICAST_HOPS, + &hops, sizeof(hops)); + /* just do it, regardless if fails or not. */ + sock_make_no_blocking(*ssdpReqSock); + + return UPNP_E_SUCCESS; +} +#endif /* IPv6 */ +#endif /* INCLUDE_CLIENT_APIS */ + +int get_ssdp_sockets(MiniServerSockArray * out) { int retVal; - out->ssdpReqSock4 = INVALID_SOCKET; - out->ssdpReqSock6 = INVALID_SOCKET; - + out->ssdpReqSock4 = INVALID_SOCKET; + out->ssdpReqSock6 = INVALID_SOCKET; #if INCLUDE_CLIENT_APIS /* Create the IPv4 socket for SSDP REQUESTS */ - if(strlen(gIF_IPV4) > 0) { + if (strlen(gIF_IPV4) > 0) { retVal = create_ssdp_sock_reqv4(&out->ssdpReqSock4); - if(retVal != UPNP_E_SUCCESS) { + if (retVal != UPNP_E_SUCCESS) return retVal; - } /* For use by ssdp control point. */ gSsdpReqSocket4 = out->ssdpReqSock4; } else @@ -889,7 +1110,7 @@ int get_ssdp_sockets(MiniServerSockArray *out) gSsdpReqSocket6 = out->ssdpReqSock6; } else out->ssdpReqSock6 = INVALID_SOCKET; -#endif /* IPv6 */ +#endif /* IPv6 */ #endif /* INCLUDE_CLIENT_APIS */ /* Create the IPv4 socket for SSDP */ if (strlen(gIF_IPV4) > 0) { @@ -900,7 +1121,7 @@ int get_ssdp_sockets(MiniServerSockArray *out) UpnpCloseSocket(out->ssdpReqSock4); shutdown(out->ssdpReqSock6, SD_BOTH); UpnpCloseSocket(out->ssdpReqSock6); -#endif +#endif /* INCLUDE_CLIENT_APIS */ return retVal; } } else @@ -917,7 +1138,7 @@ int get_ssdp_sockets(MiniServerSockArray *out) UpnpCloseSocket(out->ssdpReqSock4); shutdown(out->ssdpReqSock6, SD_BOTH); UpnpCloseSocket(out->ssdpReqSock6); -#endif +#endif /* INCLUDE_CLIENT_APIS */ return retVal; } } else @@ -934,445 +1155,15 @@ int get_ssdp_sockets(MiniServerSockArray *out) UpnpCloseSocket(out->ssdpReqSock4); shutdown(out->ssdpReqSock6, SD_BOTH); UpnpCloseSocket(out->ssdpReqSock6); -#endif +#endif /* INCLUDE_CLIENT_APIS */ return retVal; } } else out->ssdpSock6UlaGua = INVALID_SOCKET; -#endif /* IPv6 */ +#endif /* UPNP_ENABLE_IPV6 */ return UPNP_E_SUCCESS; } - - -#if INCLUDE_CLIENT_APIS -/************************************************************************ - * Function : create_ssdp_sock_reqv4 - * - * Parameters: - * IN SOCKET* ssdpReqSock: SSDP IPv4 request socket to be created - * - * Description: - * This function creates the SSDP IPv4 socket to be used by the control - * point. - * - * Returns: - * UPNP_E_SUCCESS on successful socket creation. - ***************************************************************************/ -int create_ssdp_sock_reqv4(SOCKET *ssdpReqSock) -{ - char errorBuffer[ERROR_BUFFER_LEN]; - u_char ttl = 4; - - *ssdpReqSock = socket(AF_INET, SOCK_DGRAM, 0); - if (*ssdpReqSock == -1) { - strerror_r(errno, errorBuffer, ERROR_BUFFER_LEN); - UpnpPrintf(UPNP_CRITICAL, SSDP, __FILE__, __LINE__, - "Error in socket(): %s\n", errorBuffer); - return UPNP_E_OUTOF_SOCKET; - } - setsockopt(*ssdpReqSock, IPPROTO_IP, IP_MULTICAST_TTL, - &ttl, sizeof(ttl)); - /* just do it, regardless if fails or not. */ - Make_Socket_NoBlocking(*ssdpReqSock); - - return UPNP_E_SUCCESS; -} - - -/************************************************************************ - * Function : create_ssdp_sock_reqv6 - * - * Parameters: - * IN SOCKET* ssdpReqSock: SSDP IPv6 request socket to be created - * - * Description: - * This function creates the SSDP IPv6 socket to be used by the control - * point. - * - * Returns: void - * - ***************************************************************************/ -#ifdef UPNP_ENABLE_IPV6 -int create_ssdp_sock_reqv6( SOCKET* ssdpReqSock ) -{ - char errorBuffer[ERROR_BUFFER_LEN]; - char hops = 1; - - *ssdpReqSock = socket( AF_INET6, SOCK_DGRAM, 0 ); - if ( *ssdpReqSock == -1 ) { - strerror_r(errno, errorBuffer, ERROR_BUFFER_LEN); - UpnpPrintf( UPNP_CRITICAL, SSDP, __FILE__, __LINE__, - "Error in socket(): %s\n", errorBuffer ); - return UPNP_E_OUTOF_SOCKET; - } - - /* MUST use scoping of IPv6 addresses to control the propagation os SSDP - * messages instead of relying on the Hop Limit (Equivalent to the TTL - * limit in IPv4). */ - setsockopt( *ssdpReqSock, IPPROTO_IPV6, IPV6_MULTICAST_HOPS, - &hops, sizeof(hops) ); - - /* just do it, regardless if fails or not. */ - Make_Socket_NoBlocking( *ssdpReqSock ); - - return UPNP_E_SUCCESS; -} -#endif /* IPv6 */ - -#endif /* INCLUDE_CLIENT_APIS */ - - -/************************************************************************ - * Function : create_ssdp_sock_v4 - * - * Parameters: - * IN SOCKET* ssdpSock: SSDP IPv4 socket to be created - * - * Description: - * This function ... - * - * Returns: void - * - ***************************************************************************/ -int create_ssdp_sock_v4( SOCKET* ssdpSock ) -{ - char errorBuffer[ERROR_BUFFER_LEN]; - int onOff; - u_char ttl = 4; - struct ip_mreq ssdpMcastAddr; - struct sockaddr_storage __ss; - struct sockaddr_in *ssdpAddr4 = (struct sockaddr_in *)&__ss; - int ret = 0; - struct in_addr addr; - - - *ssdpSock = socket( AF_INET, SOCK_DGRAM, 0 ); - if ( *ssdpSock == -1 ) { - strerror_r(errno, errorBuffer, ERROR_BUFFER_LEN); - UpnpPrintf( UPNP_CRITICAL, SSDP, __FILE__, __LINE__, - "Error in socket(): %s\n", errorBuffer ); - - return UPNP_E_OUTOF_SOCKET; - } - - onOff = 1; - ret = setsockopt( *ssdpSock, SOL_SOCKET, SO_REUSEADDR, - (char*)&onOff, sizeof(onOff) ); - if ( ret == -1) { - strerror_r(errno, errorBuffer, ERROR_BUFFER_LEN); - UpnpPrintf( UPNP_CRITICAL, SSDP, __FILE__, __LINE__, - "Error in setsockopt() SO_REUSEADDR: %s\n", errorBuffer ); - shutdown( *ssdpSock, SD_BOTH ); - UpnpCloseSocket( *ssdpSock ); - - return UPNP_E_SOCKET_ERROR; - } - -#if defined(BSD) || defined(__OSX__) || defined(__APPLE__) - onOff = 1; - ret = setsockopt( *ssdpSock, SOL_SOCKET, SO_REUSEPORT, - (char *)&onOff, sizeof(onOff) ); - if ( ret == -1 ) { - strerror_r(errno, errorBuffer, ERROR_BUFFER_LEN); - UpnpPrintf( UPNP_CRITICAL, SSDP, __FILE__, __LINE__, - "Error in setsockopt() SO_REUSEPORT: %s\n", errorBuffer ); - shutdown( *ssdpSock, SD_BOTH ); - UpnpCloseSocket( *ssdpSock ); - - return UPNP_E_SOCKET_ERROR; - } -#endif /* BSD */ - - memset( &__ss, 0, sizeof( __ss ) ); - ssdpAddr4->sin_family = AF_INET; - ssdpAddr4->sin_addr.s_addr = htonl( INADDR_ANY ); - ssdpAddr4->sin_port = htons( SSDP_PORT ); - ret = bind( *ssdpSock, (struct sockaddr *)ssdpAddr4, sizeof(*ssdpAddr4) ); - if ( ret == -1 ) { - strerror_r(errno, errorBuffer, ERROR_BUFFER_LEN); - UpnpPrintf( UPNP_CRITICAL, SSDP, __FILE__, __LINE__, - "Error in bind(), addr=0x%08X, port=%d: %s\n", - INADDR_ANY, SSDP_PORT, errorBuffer ); - shutdown( *ssdpSock, SD_BOTH ); - UpnpCloseSocket( *ssdpSock ); - - return UPNP_E_SOCKET_BIND; - } - - memset( (void *)&ssdpMcastAddr, 0, sizeof (struct ip_mreq) ); - ssdpMcastAddr.imr_interface.s_addr = inet_addr( gIF_IPV4 ); - ssdpMcastAddr.imr_multiaddr.s_addr = inet_addr( SSDP_IP ); - ret = setsockopt( *ssdpSock, IPPROTO_IP, IP_ADD_MEMBERSHIP, - (char *)&ssdpMcastAddr, sizeof(struct ip_mreq) ); - if ( ret == -1 ) { - strerror_r(errno, errorBuffer, ERROR_BUFFER_LEN); - UpnpPrintf( UPNP_CRITICAL, SSDP, __FILE__, __LINE__, - "Error in setsockopt() IP_ADD_MEMBERSHIP (join multicast group): %s\n", - errorBuffer ); - shutdown( *ssdpSock, SD_BOTH ); - UpnpCloseSocket( *ssdpSock ); - - return UPNP_E_SOCKET_ERROR; - } - - /* Set multicast interface. */ - memset( (void *)&addr, 0, sizeof (struct in_addr) ); - addr.s_addr = inet_addr(gIF_IPV4); - ret = setsockopt(*ssdpSock, IPPROTO_IP, IP_MULTICAST_IF, - (char *)&addr, sizeof addr); - if ( ret == -1 ) { - strerror_r(errno, errorBuffer, ERROR_BUFFER_LEN); - UpnpPrintf( UPNP_INFO, SSDP, __FILE__, __LINE__, - "Error in setsockopt() IP_MULTICAST_IF (set multicast interface): %s\n", - errorBuffer ); - /* This is probably not a critical error, so let's continue. */ - } - - /* result is not checked becuase it will fail in WinMe and Win9x. */ - ret = setsockopt( *ssdpSock, IPPROTO_IP, - IP_MULTICAST_TTL, &ttl, sizeof (ttl) ); - - onOff = 1; - ret = setsockopt( *ssdpSock, SOL_SOCKET, SO_BROADCAST, - (char*)&onOff, sizeof(onOff) ); - if( ret == -1) { - strerror_r(errno, errorBuffer, ERROR_BUFFER_LEN); - UpnpPrintf( UPNP_CRITICAL, SSDP, __FILE__, __LINE__, - "Error in setsockopt() SO_BROADCAST (set broadcast): %s\n", - errorBuffer ); - shutdown( *ssdpSock, SD_BOTH ); - UpnpCloseSocket( *ssdpSock ); - - return UPNP_E_NETWORK_ERROR; - } - - return UPNP_E_SUCCESS; -} - - -/************************************************************************ - * Function : create_ssdp_sock_v6 - * - * Parameters: - * IN SOCKET* ssdpSock: SSDP IPv6 socket to be created - * - * Description: - * This function ... - * - * Returns: void - * - ***************************************************************************/ -#ifdef UPNP_ENABLE_IPV6 -int create_ssdp_sock_v6( SOCKET* ssdpSock ) -{ - char errorBuffer[ERROR_BUFFER_LEN]; - struct ipv6_mreq ssdpMcastAddr; - struct sockaddr_storage __ss; - struct sockaddr_in6 *ssdpAddr6 = (struct sockaddr_in6 *)&__ss; - int onOff; - int ret = 0; - - *ssdpSock = socket( AF_INET6, SOCK_DGRAM, 0 ); - if ( *ssdpSock == -1 ) { - strerror_r(errno, errorBuffer, ERROR_BUFFER_LEN); - UpnpPrintf( UPNP_CRITICAL, SSDP, __FILE__, __LINE__, - "Error in socket(): %s\n", errorBuffer ); - - return UPNP_E_OUTOF_SOCKET; - } - - onOff = 1; - ret = setsockopt( *ssdpSock, SOL_SOCKET, SO_REUSEADDR, - (char*)&onOff, sizeof(onOff) ); - if ( ret == -1) { - strerror_r(errno, errorBuffer, ERROR_BUFFER_LEN); - UpnpPrintf( UPNP_CRITICAL, SSDP, __FILE__, __LINE__, - "Error in setsockopt() SO_REUSEADDR: %s\n", errorBuffer ); - shutdown( *ssdpSock, SD_BOTH ); - UpnpCloseSocket( *ssdpSock ); - - return UPNP_E_SOCKET_ERROR; - } - -#if defined(BSD) || defined(__OSX__) || defined(__APPLE__) - onOff = 1; - ret = setsockopt( *ssdpSock, SOL_SOCKET, SO_REUSEPORT, - (char*)&onOff, sizeof (onOff) ); - if ( ret == -1 ) { - strerror_r(errno, errorBuffer, ERROR_BUFFER_LEN); - UpnpPrintf( UPNP_CRITICAL, SSDP, __FILE__, __LINE__, - "Error in setsockopt() SO_REUSEPORT: %s\n", errorBuffer ); - shutdown( *ssdpSock, SD_BOTH ); - UpnpCloseSocket( *ssdpSock ); - - return UPNP_E_SOCKET_ERROR; - } -#endif /* BSD */ - - memset( &__ss, 0, sizeof( __ss ) ); - ssdpAddr6->sin6_family = AF_INET6; - ssdpAddr6->sin6_addr = in6addr_any; - ssdpAddr6->sin6_scope_id = gIF_INDEX; - ssdpAddr6->sin6_port = htons( SSDP_PORT ); - ret = bind( *ssdpSock, (struct sockaddr *)ssdpAddr6, sizeof(*ssdpAddr6) ); - if ( ret == -1 ) { - strerror_r(errno, errorBuffer, ERROR_BUFFER_LEN); - UpnpPrintf( UPNP_CRITICAL, SSDP, __FILE__, __LINE__, - "Error in bind(), addr=0x%032lX, port=%d: %s\n", - 0lu, SSDP_PORT, errorBuffer ); - shutdown( *ssdpSock, SD_BOTH ); - UpnpCloseSocket( *ssdpSock ); - - return UPNP_E_SOCKET_BIND; - } - - memset( (void *)&ssdpMcastAddr, 0, sizeof(ssdpMcastAddr) ); - ssdpMcastAddr.ipv6mr_interface = gIF_INDEX; - inet_pton( AF_INET6, SSDP_IPV6_LINKLOCAL, &ssdpMcastAddr.ipv6mr_multiaddr ); - ret = setsockopt( *ssdpSock, IPPROTO_IPV6, IPV6_JOIN_GROUP, - (char *)&ssdpMcastAddr, sizeof(ssdpMcastAddr) ); - if ( ret == -1 ) { - strerror_r(errno, errorBuffer, ERROR_BUFFER_LEN); - UpnpPrintf( UPNP_CRITICAL, SSDP, __FILE__, __LINE__, - "Error in setsockopt() IPV6_JOIN_GROUP (join multicast group): %s\n", - errorBuffer ); - shutdown( *ssdpSock, SD_BOTH ); - UpnpCloseSocket( *ssdpSock ); - - return UPNP_E_SOCKET_ERROR; - } - - onOff = 1; - ret = setsockopt( *ssdpSock, SOL_SOCKET, SO_BROADCAST, - (char*)&onOff, sizeof(onOff) ); - if( ret == -1) { - strerror_r(errno, errorBuffer, ERROR_BUFFER_LEN); - UpnpPrintf( UPNP_CRITICAL, SSDP, __FILE__, __LINE__, - "Error in setsockopt() SO_BROADCAST (set broadcast): %s\n", - errorBuffer ); - shutdown( *ssdpSock, SD_BOTH ); - UpnpCloseSocket( *ssdpSock ); - - return UPNP_E_NETWORK_ERROR; - } - - return UPNP_E_SUCCESS; -} - -#endif /* IPv6 */ - -/************************************************************************ - * Function : create_ssdp_sock_v6_ula_gua - * - * Parameters: - * IN SOCKET* ssdpSock: SSDP IPv6 socket to be created - * - * Description: - * This function ... - * - * Returns: void - * - ***************************************************************************/ -#ifdef UPNP_ENABLE_IPV6 -int create_ssdp_sock_v6_ula_gua(SOCKET *ssdpSock) -{ - char errorBuffer[ERROR_BUFFER_LEN]; - struct ipv6_mreq ssdpMcastAddr; - struct sockaddr_storage __ss; - struct sockaddr_in6 *ssdpAddr6 = (struct sockaddr_in6 *)&__ss; - int onOff; - int ret = 0; - - *ssdpSock = socket(AF_INET6, SOCK_DGRAM, 0); - if (*ssdpSock == -1) { - strerror_r(errno, errorBuffer, ERROR_BUFFER_LEN); - UpnpPrintf(UPNP_CRITICAL, SSDP, __FILE__, __LINE__, - "Error in socket(): %s\n", errorBuffer); - - return UPNP_E_OUTOF_SOCKET; - } - - onOff = 1; - ret = setsockopt(*ssdpSock, SOL_SOCKET, SO_REUSEADDR, - (char*)&onOff, sizeof(onOff) ); - if (ret == -1) { - strerror_r(errno, errorBuffer, ERROR_BUFFER_LEN); - UpnpPrintf(UPNP_CRITICAL, SSDP, __FILE__, __LINE__, - "Error in setsockopt() SO_REUSEADDR: %s\n", errorBuffer); - shutdown(*ssdpSock, SD_BOTH); - UpnpCloseSocket(*ssdpSock); - - return UPNP_E_SOCKET_ERROR; - } - -#if defined(BSD) || defined(__OSX__) || defined(__APPLE__) - onOff = 1; - ret = setsockopt( *ssdpSock, SOL_SOCKET, SO_REUSEPORT, - (char*)&onOff, sizeof (onOff) ); - if ( ret == -1 ) { - strerror_r(errno, errorBuffer, ERROR_BUFFER_LEN); - UpnpPrintf( UPNP_CRITICAL, SSDP, __FILE__, __LINE__, - "Error in setsockopt() SO_REUSEPORT: %s\n", errorBuffer ); - shutdown( *ssdpSock, SD_BOTH ); - UpnpCloseSocket( *ssdpSock ); - - return UPNP_E_SOCKET_ERROR; - } -#endif /* BSD */ - - memset( &__ss, 0, sizeof( __ss ) ); - ssdpAddr6->sin6_family = AF_INET6; - ssdpAddr6->sin6_addr = in6addr_any; - ssdpAddr6->sin6_scope_id = gIF_INDEX; - ssdpAddr6->sin6_port = htons( SSDP_PORT ); - ret = bind( *ssdpSock, (struct sockaddr *)ssdpAddr6, sizeof(*ssdpAddr6) ); - if ( ret == -1 ) { - strerror_r(errno, errorBuffer, ERROR_BUFFER_LEN); - UpnpPrintf( UPNP_CRITICAL, SSDP, __FILE__, __LINE__, - "Error in bind(), addr=0x%032lX, port=%d: %s\n", - 0lu, SSDP_PORT, errorBuffer ); - shutdown( *ssdpSock, SD_BOTH ); - UpnpCloseSocket( *ssdpSock ); - - return UPNP_E_SOCKET_BIND; - } - - memset( (void *)&ssdpMcastAddr, 0, sizeof(ssdpMcastAddr) ); - ssdpMcastAddr.ipv6mr_interface = gIF_INDEX; - - /* SITE LOCAL */ - inet_pton( AF_INET6, SSDP_IPV6_SITELOCAL, &ssdpMcastAddr.ipv6mr_multiaddr ); - ret = setsockopt( *ssdpSock, IPPROTO_IPV6, IPV6_JOIN_GROUP, - (char *)&ssdpMcastAddr, sizeof(ssdpMcastAddr) ); - if ( ret == -1 ) { - strerror_r(errno, errorBuffer, ERROR_BUFFER_LEN); - UpnpPrintf( UPNP_CRITICAL, SSDP, __FILE__, __LINE__, - "Error in setsockopt() IPV6_JOIN_GROUP (join multicast group): %s\n", - errorBuffer ); - shutdown( *ssdpSock, SD_BOTH ); - UpnpCloseSocket( *ssdpSock ); - - return UPNP_E_SOCKET_ERROR; - } - - onOff = 1; - ret = setsockopt( *ssdpSock, SOL_SOCKET, SO_BROADCAST, - (char*)&onOff, sizeof(onOff) ); - if( ret == -1) { - strerror_r(errno, errorBuffer, ERROR_BUFFER_LEN); - UpnpPrintf( UPNP_CRITICAL, SSDP, __FILE__, __LINE__, - "Error in setsockopt() SO_BROADCAST (set broadcast): %s\n", - errorBuffer ); - shutdown( *ssdpSock, SD_BOTH ); - UpnpCloseSocket( *ssdpSock ); - - return UPNP_E_NETWORK_ERROR; - } - - return UPNP_E_SUCCESS; -} -#endif /* IPv6 */ - #endif /* EXCLUDE_SSDP */ +/* @} SSDPlib */