Merged Charles Nepveu's IPv6 work. libupnp now is IPv6 enabled.

git-svn-id: https://pupnp.svn.sourceforge.net/svnroot/pupnp/trunk@358 119443c7-1b9e-41f8-b6fc-b9c35fce742c
This commit is contained in:
Marcelo Roberto Jimenez 2008-05-02 17:04:22 +00:00
parent 4f2075b7c9
commit 2e4a96f034
30 changed files with 2457 additions and 981 deletions

View File

@ -2,6 +2,9 @@
Version 1.8.0
*******************************************************************************
2008-05-02 Marcelo Jimenez <mroberto(at)users.sourceforge.net>
* Merged Charles Nepveu's IPv6 work. libupnp now is IPv6 enabled.
2008-02-06 Marcelo Jimenez <mroberto(at)users.sourceforge.net>
* Breaking API so that we now hide internal data structures.

4
TODO
View File

@ -18,6 +18,10 @@ http://sourceforge.net/tracker/?group_id=7189&atid=307189
- make API clean for large files and 64 bits
- Why is NUM_HANDLE defined to 200 when we can register only:
A) One client(1)
B) An IPv4 and IPv6 device (2)
NUM_HANDLE should be 3
To Be Decided
=============

View File

@ -4,6 +4,7 @@
Version="8.00"
Name="libupnp"
ProjectGUID="{6227F51A-1498-4C4A-B213-F6FDED605125}"
RootNamespace="libupnp"
>
<Platforms>
<Platform
@ -49,7 +50,7 @@
Optimization="2"
InlineFunctionExpansion="1"
AdditionalIncludeDirectories="..\..\pthreads\include,..\ixml\src\inc,..\ixml\inc,..\threadutil\inc,..\upnp\inc,..\upnp\src\inc,.\inc"
PreprocessorDefinitions="WIN32;NDEBUG;_WINDOWS;_USRDLL;LIBUPNP_EXPORTS;PTW32_STATIC_LIB;UPNP_STATIC_LIB;UPNP_USE_MSVCPP"
PreprocessorDefinitions="WIN32;NDEBUG;_WINDOWS;_USRDLL;LIBUPNP_EXPORTS;PTW32_STATIC_LIB;UPNP_STATIC_LIB;UPNP_USE_MSVCPP;_CRT_SECURE_NO_WARNINGS"
StringPooling="true"
RuntimeLibrary="0"
EnableFunctionLevelLinking="true"
@ -74,7 +75,7 @@
/>
<Tool
Name="VCLinkerTool"
AdditionalDependencies="odbc32.lib odbccp32.lib ..\..\pthreads\lib\pthreadvc2.lib ws2_32.lib"
AdditionalDependencies="odbc32.lib odbccp32.lib ..\..\pthreads\lib\pthreadvc2.lib ws2_32.lib iphlpapi.lib"
OutputFile=".\Release/libupnp.dll"
LinkIncremental="1"
SuppressStartupBanner="true"
@ -144,7 +145,7 @@
Name="VCCLCompilerTool"
Optimization="0"
AdditionalIncludeDirectories="..\..\pthreads\include;..\..\ixml\src\inc;..\..\ixml\inc;..\..\threadutil\inc;..\..\upnp\inc;..\..\upnp\src\inc;..\inc;..\msvc"
PreprocessorDefinitions="DEBUG;WIN32;_WINDOWS;_USRDLL;LIBUPNP_EXPORTS;UPNP_USE_MSVCPP"
PreprocessorDefinitions="DEBUG;WIN32;_WINDOWS;_USRDLL;LIBUPNP_EXPORTS;UPNP_USE_MSVCPP;_CRT_SECURE_NO_WARNINGS"
MinimalRebuild="true"
BasicRuntimeChecks="3"
RuntimeLibrary="1"
@ -170,7 +171,7 @@
/>
<Tool
Name="VCLinkerTool"
AdditionalDependencies="odbc32.lib odbccp32.lib ..\..\pthreads\lib\pthreadvc2.lib ws2_32.lib"
AdditionalDependencies="odbc32.lib odbccp32.lib ..\..\pthreads\lib\pthreadvc2.lib ws2_32.lib iphlpapi.lib"
OutputFile="$(OutDir)\libupnp.dll"
LinkIncremental="2"
SuppressStartupBanner="true"
@ -503,6 +504,10 @@
RelativePath="..\..\upnp\src\inc\unixutil.h"
>
</File>
<File
RelativePath="..\..\upnp\inc\upnp.h"
>
</File>
<File
RelativePath="..\..\upnp\src\inc\upnp_timeout.h"
>

View File

@ -149,7 +149,7 @@ dnl # "current:revision:age"
dnl #
dnl # - Code has changed in upnp
dnl # revision: 5 -> 6
dnl # - Interface has changed in upnp
dnl # - Interfaces have been changed, added and removed in upnp
dnl # current: 3 -> 4
dnl # revision: 6 -> 0
dnl # - Interface has been removed in upnp

View File

@ -69,8 +69,8 @@ IXML_Document *UpnpActionRequest_get_ActionResult(const UpnpActionRequest *p);
void UpnpActionRequest_set_ActionResult(UpnpActionRequest *p, IXML_Document *d);
/** IP address of the control point requesting this action */
struct in_addr *UpnpActionRequest_get_CtrlPtIPAddr(const UpnpActionRequest *p);
void UpnpActionRequest_set_CtrlPtIPAddr(UpnpActionRequest *p, struct in_addr *ia);
struct sockaddr_storage *UpnpActionRequest_get_CtrlPtIPAddr(const UpnpActionRequest *p);
void UpnpActionRequest_set_CtrlPtIPAddr(UpnpActionRequest *p, struct sockaddr_storage *ia);
/** The DOM document containing the information from the SOAP header */
IXML_Document *UpnpActionRequest_get_SoapHeader(const UpnpActionRequest *p);

View File

@ -83,8 +83,8 @@ void UpnpDiscovery_strcpy_Ext(UpnpDiscovery *p, const char *s);
void UpnpDiscovery_strncpy_Ext(UpnpDiscovery *p, const char *s, int n);
/** The host address of the device responding to the search. */
struct sockaddr_in *UpnpDiscovery_get_DestAddr(const UpnpDiscovery *p);
void UpnpDiscovery_set_DestAddr(UpnpDiscovery *p, struct sockaddr_in *sa);
struct sockaddr *UpnpDiscovery_get_DestAddr(const UpnpDiscovery *p);
void UpnpDiscovery_set_DestAddr(UpnpDiscovery *p, struct sockaddr *sa);
#ifdef __cplusplus

View File

@ -62,8 +62,8 @@ void UpnpStateVarRequest_set_StateVarName(UpnpStateVarRequest *p, const UpnpStri
void UpnpStateVarRequest_strcpy_StateVarName(UpnpStateVarRequest *p, const char *s);
/** IP address of sender requesting the state variable. */
struct in_addr *UpnpStateVarRequest_get_CtrlPtIPAddr(const UpnpStateVarRequest *p);
void UpnpStateVarRequest_set_CtrlPtIPAddr(UpnpStateVarRequest *p, struct in_addr *ia);
struct sockaddr_storage *UpnpStateVarRequest_get_CtrlPtIPAddr(const UpnpStateVarRequest *p);
void UpnpStateVarRequest_set_CtrlPtIPAddr(UpnpStateVarRequest *p, struct sockaddr_storage *ia);
/** The current value of the variable. This needs to be allocated by
* the caller. When finished with it, the SDK frees this {\bf DOMString}. */

View File

@ -106,13 +106,15 @@
#endif
#ifndef WIN32
#define SOCKET int
#define INVALID_SOCKET (SOCKET)(~0)
#endif
#ifndef WIN32
#include <netinet/in.h>
#else
#include <winsock2.h>
#include <Ws2tcpip.h>
#include <iphlpapi.h>
#include <time.h>
#endif
@ -296,6 +298,15 @@
#define UPNP_E_ALREADY_REGISTERED -120
/*! @} */
/** @name UPNP_E_INVALID_INTERFACE [-121]
* {\tt UPNP_E_INVALID_INTERFACE} signifies that the interface provided to
* {\bf UpnpInit2} is unknown or does not have a valid IPv4 or IPv6
* address configured.
*/
/*! @{ */
#define UPNP_E_INVALID_INTERFACE -121
/*! @} */
/** @name UPNP_E_NETWORK_ERROR [-200]
* {\tt UPNP_E_NETWORK_ERROR} signifies that a network error occurred. It
* is the generic error code for network problems that are not covered under
@ -930,6 +941,51 @@ EXPORT_SPEC int UpnpInit(
will pick an arbitrary free port. */
);
/*! @name Initialization and Registration */
/*! @{ */
/** Initializes the Linux SDK for UPnP Devices. This function must be called
* before any other API function can be called. It should be called
* only once. Subsequent calls to this API return a {\tt UPNP_E_INIT}
* error code.
*
* Optionally, the application can specify an interface name (in the
* case of a multi-homed configuration) and a port number to use for
* all UPnP operations. Since a port number can be used only by one
* process, multiple processes using the SDK must specify
* different port numbers.
*
* If unspecified, the SDK will use the first suitable interface and an
* arbitrary port.
*
* This call is synchronous.
*
* @return [int] An integer representing one of the following:
* \begin{itemize}
* \item {\tt UPNP_E_SUCCESS}: The operation completed successfully.
* \item {\tt UPNP_E_OUTOF_MEMORY}: Insufficient resources exist
* to initialize the SDK.
* \item {\tt UPNP_E_INIT}: The SDK is already initialized.
* \item {\tt UPNP_E_INIT_FAILED}: The SDK initialization
* failed for an unknown reason.
* \item {\tt UPNP_E_SOCKET_BIND}: An error occurred binding a socket.
* \item {\tt UPNP_E_LISTEN}: An error occurred listening to a socket.
* \item {\tt UPNP_E_OUTOF_SOCKET}: An error ocurred creating a socket.
* \item {\tt UPNP_E_INTERNAL_ERROR}: An internal error ocurred.
* \item {\tt UPNP_E_INVALID_INTERFACE}: IfName is invalid or doees not
* have a valid IPv4 or IPv6 addresss configured.
* \end{itemize} */
EXPORT_SPEC int UpnpInit2(
IN const char *IfName, /** The interface name to use by the UPnP SDK
operations. Examples: "eth0", "xl0",
"Local Area Connection", {\tt NULL} to
use the first suitable interface. */
IN unsigned short DestPort /** The destination port number to use. 0
will pick an arbitrary free port. */
);
/** Terminates the Linux SDK for UPnP Devices. This function must be the last
* API function called. It should be called only once. Subsequent calls to
* this API return a {\tt UPNP_E_FINISH} error code.
@ -949,20 +1005,40 @@ EXPORT_SPEC int UpnpFinish();
* returned.
*
* @return [unsigned short] The port on which an internal server is
* listening for UPnP related requests.
* listening for IPv4 UPnP related requests.
*/
EXPORT_SPEC unsigned short UpnpGetServerPort(void);
/** If {\tt NULL} is used as the IP address in {\bf UpnpInit}, then this
/** If '0' is used as the port number in {\bf UpnpInit}, then this
* function can be used to retrieve the actual port allocated to
* the SDK. If {\bf UpnpInit} has not succeeded then 0 is
* returned.
*
* @return [unsigned short] The port on which an internal server is
* listening for IPv6 UPnP related requests.
*/
EXPORT_SPEC unsigned short UpnpGetServerPort6(void);
/** If {\tt NULL} is used as the IPv4 address in {\bf UpnpInit}, then this
* function can be used to retrieve the actual interface address
* on which device is running. If {\bf UpnpInit} has not succeeded
* then {\tt NULL} is returned.
*
* @return [char*] The IP address on which an internal server is listening
* @return [char*] The IPv4 address on which an internal server is listening
* for UPnP related requests.
*/
EXPORT_SPEC char * UpnpGetServerIpAddress(void);
/** If {\tt NULL} is used as the IPv6 address in {\bf UpnpInit}, then this
* function can be used to retrieve the actual interface address
* on which device is running. If {\bf UpnpInit} has not succeeded
* then {\tt NULL} is returned.
*
* @return [char*] The IPv6 address on which an internal server is listening
* for UPnP related requests.
*/
EXPORT_SPEC char * UpnpGetServerIp6Address(void);
/** {\bf UpnpRegisterClient} registers a control point application with the
* SDK. A control point application cannot make any other API calls
* until it registers using this function.
@ -1129,6 +1205,58 @@ EXPORT_SPEC int UpnpRegisterRootDevice2(
the new device handle. */
);
/** {\bf UpnpRegisterRootDevice3} registers a device application for a
* specific address family with the SDK. A device application cannot
* make any other API calls until it registers using this function.
* Device applications can also register as control points (see
* {\bf UpnpRegisterClient} to get a control point handle to perform
* control point functionality).
*
* {\bf UpnpRegisterRootDevice} is synchronous and does not generate
* any callbacks. Callbacks can occur as soon as this function returns.
*
* @return [int] An integer representing one of the following:
* \begin{itemize}
* \item {\tt UPNP_E_SUCCESS}: The operation completed successfully.
* \item {\tt UPNP_E_FINISH}: The SDK is already terminated or
* is not initialized.
* \item {\tt UPNP_E_INVALID_DESC}: The description document was not
* a valid device description.
* \item {\tt UPNP_E_INVALID_URL}: The URL for the description document
* is not valid.
* \item {\tt UPNP_E_INVALID_PARAM}: Either {\bf Callback} or {\bf Hnd}
* is not a valid pointer or {\bf DescURL} is {\tt NULL}.
* \item {\tt UPNP_E_NETWORK_ERROR}: A network error occurred.
* \item {\tt UPNP_E_SOCKET_WRITE}: An error or timeout occurred writing
* to a socket.
* \item {\tt UPNP_E_SOCKET_READ}: An error or timeout occurred reading
* from a socket.
* \item {\tt UPNP_E_SOCKET_BIND}: An error occurred binding a socket.
* \item {\tt UPNP_E_SOCKET_CONNECT}: An error occurred connecting the
* socket.
* \item {\tt UPNP_E_OUTOF_SOCKET}: Too many sockets are currently
* allocated.
* \item {\tt UPNP_E_OUTOF_MEMORY}: There are insufficient resources to
* register this root device.
* \end{itemize} */
EXPORT_SPEC int UpnpRegisterRootDevice3(
IN const char *DescUrl, /** Pointer to a string containing the
description URL for this root device
instance. */
IN Upnp_FunPtr Callback, /** Pointer to the callback function for
receiving asynchronous events. */
IN const void *Cookie, /** Pointer to user data returned with the
callback function when invoked. */
OUT UpnpDevice_Handle *Hnd,/** Pointer to a variable to store the
new device handle. */
IN const int AddressFamily /** Address family of this device. Can be
AF_INET for an IPv4 device, or AF_INET6
for an IPv6 device. Defaults to AF_INET. */
);
/** {\bf UpnpUnRegisterClient} unregisters a control point application,
* unsubscribing all active subscriptions. After this call, the
* {\bf UpnpClient_Handle} is no longer valid.

View File

@ -21,7 +21,7 @@ struct SUpnpActionRequest
IXML_Document *m_actionRequest;
IXML_Document *m_actionResult;
IXML_Document *m_soapHeader;
struct in_addr m_ctrlPtIPAddr;
struct sockaddr_storage m_ctrlPtIPAddr;
};
@ -41,7 +41,7 @@ UpnpActionRequest *UpnpActionRequest_new()
p->m_actionRequest = NULL;
p->m_actionResult = NULL;
p->m_soapHeader = NULL;
memset(&p->m_ctrlPtIPAddr, 0, sizeof (struct in_addr));
memset(&p->m_ctrlPtIPAddr, 0, sizeof (struct sockaddr_storage));
#endif
return (UpnpActionRequest *)p;
}
@ -73,7 +73,7 @@ void UpnpActionRequest_delete(UpnpActionRequest *p)
UpnpActionRequest_set_SoapHeader(p, NULL);
memset(&q->m_ctrlPtIPAddr, 0, sizeof (struct in_addr));
memset(&q->m_ctrlPtIPAddr, 0, sizeof (struct sockaddr_storage));
free(p);
}
@ -224,13 +224,13 @@ void UpnpActionRequest_set_ActionResult(UpnpActionRequest *p, IXML_Document *d)
}
struct in_addr *UpnpActionRequest_get_CtrlPtIPAddr(const UpnpActionRequest *p)
struct sockaddr_storage *UpnpActionRequest_get_CtrlPtIPAddr(const UpnpActionRequest *p)
{
return &((struct SUpnpActionRequest *)p)->m_ctrlPtIPAddr;
}
void UpnpActionRequest_set_CtrlPtIPAddr(UpnpActionRequest *p, struct in_addr *ia)
void UpnpActionRequest_set_CtrlPtIPAddr(UpnpActionRequest *p, struct sockaddr_storage *ia)
{
((struct SUpnpActionRequest *)p)->m_ctrlPtIPAddr = *ia;
}

View File

@ -22,7 +22,7 @@ struct SUpnpDiscovery
UpnpString *m_os;
UpnpString *m_date;
UpnpString *m_ext;
struct sockaddr_in m_destAddr;
struct sockaddr m_destAddr;
};
@ -332,13 +332,13 @@ void UpnpDiscovery_strncpy_Ext(UpnpDiscovery *p, const char *s, int n)
}
struct sockaddr_in *UpnpDiscovery_get_DestAddr(const UpnpDiscovery *p)
struct sockaddr *UpnpDiscovery_get_DestAddr(const UpnpDiscovery *p)
{
return &((struct SUpnpDiscovery *)p)->m_destAddr;
}
void UpnpDiscovery_set_DestAddr(UpnpDiscovery *p, struct sockaddr_in *sa)
void UpnpDiscovery_set_DestAddr(UpnpDiscovery *p, struct sockaddr *sa)
{
((struct SUpnpDiscovery *)p)->m_destAddr = *sa;
}

View File

@ -18,7 +18,7 @@ struct SUpnpStateVarRequest
UpnpString *m_devUDN;
UpnpString *m_serviceID;
UpnpString *m_stateVarName;
struct in_addr m_ctrlPtIPAddr;
struct sockaddr_storage m_ctrlPtIPAddr;
DOMString m_currentVal;
};
@ -36,7 +36,7 @@ UpnpStateVarRequest *UpnpStateVarRequest_new()
p->m_serviceID = UpnpString_new();
p->m_stateVarName = UpnpString_new();
#if 0
memset(&q->m_ctrlPtIPAddr, 0, sizeof (struct in_addr));
memset(&q->m_ctrlPtIPAddr, 0, sizeof (struct sockaddr_storage));
p->m_currentVal = NULL;
#endif
@ -64,7 +64,7 @@ void UpnpStateVarRequest_delete(UpnpStateVarRequest *p)
UpnpString_delete(q->m_stateVarName);
q->m_stateVarName = NULL;
memset(&q->m_ctrlPtIPAddr, 0, sizeof (struct in_addr));
memset(&q->m_ctrlPtIPAddr, 0, sizeof (struct sockaddr_storage));
ixmlFreeDOMString(q->m_currentVal);
q->m_currentVal = NULL;
@ -190,13 +190,13 @@ void UpnpStateVarRequest_strcpy_StateVarName(UpnpStateVarRequest *p, const char
}
struct in_addr *UpnpStateVarRequest_get_CtrlPtIPAddr(const UpnpStateVarRequest *p)
struct sockaddr_storage *UpnpStateVarRequest_get_CtrlPtIPAddr(const UpnpStateVarRequest *p)
{
return &((struct SUpnpStateVarRequest *)p)->m_ctrlPtIPAddr;
}
void UpnpStateVarRequest_set_CtrlPtIPAddr(UpnpStateVarRequest *p, struct in_addr *ia)
void UpnpStateVarRequest_set_CtrlPtIPAddr(UpnpStateVarRequest *p, struct sockaddr_storage *ia)
{
((struct SUpnpStateVarRequest *)p)->m_ctrlPtIPAddr = *ia;
}

File diff suppressed because it is too large Load Diff

View File

@ -325,14 +325,24 @@ static int gena_subscribe(
"TIMEOUT: Second-", timeout_str );
} else {
// subscribe
if( dest_url.hostport.IPaddress.ss_family == AF_INET6 ) {
return_code = http_MakeMessage(
&request, 1, 1,
"q" "sssdsc" "sc" "sscc",
HTTPMETHOD_SUBSCRIBE, &dest_url,
"CALLBACK: <http://", LOCAL_HOST, ":", LOCAL_PORT, "/>",
"CALLBACK: <http://[", gIF_IPV6, "]:", LOCAL_PORT_V6, "/>",
"NT: upnp:event",
"TIMEOUT: Second-", timeout_str );
} else {
return_code = http_MakeMessage(
&request, 1, 1,
"q" "sssdsc" "sc" "sscc",
HTTPMETHOD_SUBSCRIBE, &dest_url,
"CALLBACK: <http://", gIF_IPV4, ":", LOCAL_PORT_V4, "/>",
"NT: upnp:event",
"TIMEOUT: Second-", timeout_str);
}
}
if (return_code != 0) {
return return_code;
}

View File

@ -1352,7 +1352,8 @@ gena_process_subscription_request( IN SOCKINFO * info,
HandleLock();
// CURRENTLY, ONLY ONE DEVICE
if( GetDeviceHandleInfo( &device_handle, &handle_info ) != HND_DEVICE ) {
if( GetDeviceHandleInfo( info->foreign_sockaddr.ss_family ,
&device_handle, &handle_info ) != HND_DEVICE ) {
free( event_url_path );
error_respond( info, HTTP_INTERNAL_SERVER_ERROR, request );
HandleUnlock();
@ -1527,7 +1528,8 @@ gena_process_subscription_renewal_request( IN SOCKINFO * info,
HandleLock();
// CURRENTLY, ONLY SUPPORT ONE DEVICE
if( GetDeviceHandleInfo( &device_handle, &handle_info ) != HND_DEVICE ) {
if( GetDeviceHandleInfo( info->foreign_sockaddr.ss_family,
&device_handle, &handle_info ) != HND_DEVICE ) {
error_respond( info, HTTP_PRECONDITION_FAILED, request );
membuffer_destroy( &event_url_path );
return;
@ -1650,7 +1652,8 @@ gena_process_unsubscribe_request( IN SOCKINFO * info,
HandleLock();
// CURRENTLY, ONLY SUPPORT ONE DEVICE
if( GetDeviceHandleInfo( &device_handle, &handle_info ) != HND_DEVICE ) {
if( GetDeviceHandleInfo( info->foreign_sockaddr.ss_family,
&device_handle, &handle_info ) != HND_DEVICE ) {
error_respond( info, HTTP_PRECONDITION_FAILED, request );
membuffer_destroy( &event_url_path );
HandleUnlock();

View File

@ -73,8 +73,7 @@
struct mserv_request_t {
int connfd; // connection handle
struct in_addr foreign_ip_addr;
unsigned short foreign_ip_port;
struct sockaddr_storage foreign_sockaddr;
};
typedef enum { MSERV_IDLE, MSERV_RUNNING, MSERV_STOPPING } MiniServerState;
@ -272,8 +271,8 @@ handle_request( void *args )
//parser_request_init( &parser ); ////LEAK_FIX_MK
hmsg = &parser.msg;
if( sock_init_with_ip( &info, connfd, request->foreign_ip_addr,
request->foreign_ip_port ) != UPNP_E_SUCCESS ) {
if( sock_init_with_ip( &info, connfd, (struct sockaddr*)&request->foreign_sockaddr )
!= UPNP_E_SUCCESS ) {
free( request );
httpmsg_destroy( hmsg );
return;
@ -317,7 +316,7 @@ handle_request( void *args )
*
* Parameters:
* IN int connfd - Socket Descriptor on which connection is accepted
* IN struct sockaddr_in* clientAddr - Clients Address information
* IN struct sockaddr* clientAddr - Clients Address information
*
* Description:
* Initilize the thread pool to handle a request.
@ -327,7 +326,7 @@ handle_request( void *args )
************************************************************************/
static UPNP_INLINE void
schedule_request_job( IN int connfd,
IN struct sockaddr_in *clientAddr )
IN struct sockaddr *clientAddr )
{
struct mserv_request_t *request;
ThreadPoolJob job;
@ -338,14 +337,13 @@ schedule_request_job( IN int connfd,
if( request == NULL ) {
UpnpPrintf( UPNP_INFO, MSERV, __FILE__, __LINE__,
"mserv %d: out of memory\n", connfd );
shutdown( request->connfd, SD_BOTH );
shutdown( connfd, SD_BOTH );
UpnpCloseSocket( connfd );
return;
}
request->connfd = connfd;
request->foreign_ip_addr = clientAddr->sin_addr;
request->foreign_ip_port = ntohs( clientAddr->sin_port );
memcpy( &request->foreign_sockaddr, clientAddr, sizeof(request->foreign_sockaddr) );
TPJobInit( &job, ( start_routine ) handle_request, ( void * )request );
TPJobSetFreeFunction( &job, free_handle_request_arg );
@ -380,28 +378,41 @@ static void
RunMiniServer( MiniServerSockArray *miniSock )
{
char errorBuffer[ERROR_BUFFER_LEN];
struct sockaddr_in clientAddr;
struct sockaddr_storage clientAddr;
socklen_t clientLen;
SOCKET connectHnd;
SOCKET miniServSock = miniSock->miniServerSock;
SOCKET miniServSock4 = miniSock->miniServerSock4;
SOCKET miniServSock6 = miniSock->miniServerSock6;
SOCKET miniServStopSock = miniSock->miniServerStopSock;
SOCKET ssdpSock = miniSock->ssdpSock;
SOCKET ssdpSock4 = miniSock->ssdpSock4;
SOCKET ssdpSock6 = miniSock->ssdpSock6;
#ifdef INCLUDE_CLIENT_APIS
SOCKET ssdpReqSock = miniSock->ssdpReqSock;
SOCKET ssdpReqSock4 = miniSock->ssdpReqSock4;
SOCKET ssdpReqSock6 = miniSock->ssdpReqSock6;
#endif
char buf_ntop[64];
fd_set expSet;
fd_set rdSet;
unsigned int maxMiniSock;
unsigned int maxMiniSock = 0;
int byteReceived;
char requestBuf[256];
int ret = 0;
maxMiniSock = max( miniServSock, miniServStopSock) ;
maxMiniSock = max( maxMiniSock, (SOCKET)(ssdpSock) );
if( miniServSock4 != INVALID_SOCKET )
maxMiniSock = max( maxMiniSock, miniServSock4 );
if( miniServSock6 != INVALID_SOCKET )
maxMiniSock = max( maxMiniSock, miniServSock6 );
if( ssdpSock4 != INVALID_SOCKET )
maxMiniSock = max( maxMiniSock, ssdpSock4 );
if( ssdpSock6 != INVALID_SOCKET )
maxMiniSock = max( maxMiniSock, ssdpSock6 );
#ifdef INCLUDE_CLIENT_APIS
maxMiniSock = max( maxMiniSock, (SOCKET)(ssdpReqSock) );
if( ssdpReqSock4 != INVALID_SOCKET )
maxMiniSock = max( maxMiniSock, ssdpReqSock4 );
if( ssdpReqSock6 != INVALID_SOCKET )
maxMiniSock = max( maxMiniSock, ssdpReqSock6 );
#endif
maxMiniSock = max( maxMiniSock, miniServStopSock) ;
++maxMiniSock;
gMServState = MSERV_RUNNING;
@ -410,11 +421,20 @@ RunMiniServer( MiniServerSockArray *miniSock )
FD_ZERO( &expSet );
FD_SET( miniServStopSock, &expSet );
FD_SET( miniServSock, &rdSet );
FD_SET( miniServStopSock, &rdSet );
FD_SET( ssdpSock, &rdSet );
if( miniServSock4 != INVALID_SOCKET )
FD_SET( miniServSock4, &rdSet );
if( miniServSock6 != INVALID_SOCKET )
FD_SET( miniServSock6, &rdSet );
if( ssdpSock4 != INVALID_SOCKET )
FD_SET( ssdpSock4, &rdSet );
if( ssdpSock6 != INVALID_SOCKET )
FD_SET( ssdpSock6, &rdSet );
#ifdef INCLUDE_CLIENT_APIS
FD_SET( ssdpReqSock, &rdSet );
if( ssdpReqSock4 != INVALID_SOCKET )
FD_SET( ssdpReqSock4, &rdSet );
if( ssdpReqSock6 != INVALID_SOCKET )
FD_SET( ssdpReqSock6, &rdSet );
#endif
ret = select( maxMiniSock, &rdSet, NULL, &expSet, NULL );
@ -426,9 +446,10 @@ RunMiniServer( MiniServerSockArray *miniSock )
isleep( 1 );
continue;
} else {
if( FD_ISSET( miniServSock, &rdSet ) ) {
clientLen = sizeof( struct sockaddr_in );
connectHnd = accept( miniServSock,
if( miniServSock6 != INVALID_SOCKET &&
FD_ISSET( miniServSock6, &rdSet ) ) {
clientLen = sizeof( clientAddr );
connectHnd = accept( miniServSock6,
( struct sockaddr * )&clientAddr, &clientLen );
if( connectHnd == -1 ) {
strerror_r(errno, errorBuffer, ERROR_BUFFER_LEN);
@ -436,29 +457,55 @@ RunMiniServer( MiniServerSockArray *miniSock )
"miniserver: Error in accept(): %s\n", errorBuffer );
continue;
}
schedule_request_job( connectHnd, &clientAddr );
schedule_request_job( connectHnd, (struct sockaddr*)&clientAddr );
}
if( miniServSock4 != INVALID_SOCKET &&
FD_ISSET( miniServSock4, &rdSet ) ) {
clientLen = sizeof( clientAddr );
connectHnd = accept( miniServSock4,
( struct sockaddr * )&clientAddr, &clientLen );
if( connectHnd == -1 ) {
strerror_r(errno, errorBuffer, ERROR_BUFFER_LEN);
UpnpPrintf( UPNP_INFO, MSERV, __FILE__, __LINE__,
"miniserver: Error in accept(): %s\n", errorBuffer );
continue;
}
schedule_request_job( connectHnd, (struct sockaddr*)&clientAddr );
}
#ifdef INCLUDE_CLIENT_APIS
// ssdp
if( FD_ISSET( ssdpReqSock, &rdSet ) ) {
readFromSSDPSocket( ssdpReqSock );
if( ssdpReqSock6 != INVALID_SOCKET &&
FD_ISSET( ssdpReqSock6, &rdSet ) ) {
readFromSSDPSocket( ssdpReqSock6 );
}
if( ssdpReqSock4 != INVALID_SOCKET &&
FD_ISSET( ssdpReqSock4, &rdSet ) ) {
readFromSSDPSocket( ssdpReqSock4 );
}
#endif
if( FD_ISSET( ssdpSock, &rdSet ) ) {
readFromSSDPSocket( ssdpSock );
if( ssdpSock6 != INVALID_SOCKET &&
FD_ISSET( ssdpSock6, &rdSet ) ) {
readFromSSDPSocket( ssdpSock6 );
}
if( ssdpSock4 != INVALID_SOCKET &&
FD_ISSET( ssdpSock4, &rdSet ) ) {
readFromSSDPSocket( ssdpSock4 );
}
if( FD_ISSET( miniServStopSock, &rdSet ) ) {
clientLen = sizeof( struct sockaddr_in );
memset( (char *)&clientAddr, 0, sizeof (struct sockaddr_in) );
clientLen = sizeof( clientAddr );
memset( (char *)&clientAddr, 0, sizeof(clientAddr) );
byteReceived =
recvfrom( miniServStopSock, requestBuf, 25, 0,
( struct sockaddr * )&clientAddr,
&clientLen );
if( byteReceived > 0 ) {
requestBuf[byteReceived] = '\0';
inet_ntop(AF_INET,
&((struct sockaddr_in*)&clientAddr)->sin_addr,
buf_ntop, sizeof(buf_ntop) );
UpnpPrintf( UPNP_INFO, MSERV, __FILE__, __LINE__,
"Received response: %s From host %s \n",
requestBuf, inet_ntoa( clientAddr.sin_addr ) );
requestBuf, buf_ntop );
UpnpPrintf( UPNP_PACKET, MSERV, __FILE__, __LINE__,
"Received multicast packet: \n %s\n",
requestBuf );
@ -470,15 +517,21 @@ RunMiniServer( MiniServerSockArray *miniSock )
}
}
shutdown( miniServSock, SD_BOTH );
UpnpCloseSocket( miniServSock );
shutdown( miniServSock4, SD_BOTH );
UpnpCloseSocket( miniServSock4 );
shutdown( miniServSock6, SD_BOTH );
UpnpCloseSocket( miniServSock6 );
shutdown( miniServStopSock, SD_BOTH );
UpnpCloseSocket( miniServStopSock );
shutdown( ssdpSock, SD_BOTH );
UpnpCloseSocket( ssdpSock );
shutdown( ssdpSock4, SD_BOTH );
UpnpCloseSocket( ssdpSock4 );
shutdown( ssdpSock6, SD_BOTH );
UpnpCloseSocket( ssdpSock6 );
#ifdef INCLUDE_CLIENT_APIS
shutdown( ssdpReqSock, SD_BOTH );
UpnpCloseSocket( ssdpReqSock );
shutdown( ssdpReqSock4, SD_BOTH );
UpnpCloseSocket( ssdpReqSock4 );
shutdown( ssdpReqSock6, SD_BOTH );
UpnpCloseSocket( ssdpReqSock6 );
#endif
free( miniSock );
@ -503,18 +556,22 @@ RunMiniServer( MiniServerSockArray *miniSock )
static int
get_port( int sockfd )
{
struct sockaddr_in sockinfo;
struct sockaddr_storage sockinfo;
socklen_t len;
int code;
int port;
int port = 0;
len = sizeof( struct sockaddr_in );
len = sizeof( sockinfo );
code = getsockname( sockfd, ( struct sockaddr * )&sockinfo, &len );
if( code == -1 ) {
return -1;
}
port = ntohs( sockinfo.sin_port );
if( sockinfo.ss_family == AF_INET ) {
port = ntohs( ((struct sockaddr_in*)&sockinfo)->sin_port );
} else if( sockinfo.ss_family == AF_INET6 ) {
port = ntohs( ((struct sockaddr_in6*)&sockinfo)->sin6_port );
}
UpnpPrintf( UPNP_INFO, MSERV, __FILE__, __LINE__,
"sockfd = %d, .... port = %d\n", sockfd, port );
@ -526,8 +583,10 @@ get_port( int sockfd )
*
* Parameters:
* MiniServerSockArray *out - Socket Array
* unsigned short listen_port - port on which the server is
* listening for incoming connections
* unsigned short listen_port4 - port on which the server is
* listening for incoming IPv4 connections
* unsigned short listen_port6 - port on which the server is
* listening for incoming IPv6 connections
*
* Description:
* Creates a STREAM socket, binds to INADDR_ANY and listens for
@ -546,31 +605,47 @@ get_port( int sockfd )
************************************************************************/
int
get_miniserver_sockets( MiniServerSockArray * out,
unsigned short listen_port )
unsigned short listen_port4,
unsigned short listen_port6 )
{
char errorBuffer[ERROR_BUFFER_LEN];
struct sockaddr_in serverAddr;
int listenfd;
int success;
unsigned short actual_port;
struct sockaddr_storage __ss_v4;
struct sockaddr_storage __ss_v6;
struct sockaddr_in* serverAddr4 = (struct sockaddr_in*)&__ss_v4;
struct sockaddr_in6* serverAddr6 = (struct sockaddr_in6*)&__ss_v6;
SOCKET listenfd4, listenfd6;
int ret_code;
unsigned short actual_port4, actual_port6;
int reuseaddr_on = 0;
int sockError = UPNP_E_SUCCESS;
int errCode = 0;
int miniServerStopSock;
int ret = 0;
listenfd = socket( AF_INET, SOCK_STREAM, 0 );
if ( listenfd == -1 ) {
return UPNP_E_OUTOF_SOCKET; // error creating socket
// Create listen socket for IPv4/IPv6. An error here may indicate
// that we don't have an IPv4/IPv6 stack.
listenfd4 = socket( AF_INET, SOCK_STREAM, 0 );
listenfd6 = socket( AF_INET6, SOCK_STREAM, 0 );
if (listenfd4 == INVALID_SOCKET || listenfd6 == INVALID_SOCKET) {
return UPNP_E_OUTOF_SOCKET;
}
// As per the IANA specifications for the use of ports by applications
// override the listen port passed in with the first available
if( listen_port < APPLICATION_LISTENING_PORT )
listen_port = APPLICATION_LISTENING_PORT;
if (listen_port4 < APPLICATION_LISTENING_PORT) {
listen_port4 = APPLICATION_LISTENING_PORT;
}
if (listen_port6 < APPLICATION_LISTENING_PORT) {
listen_port6 = APPLICATION_LISTENING_PORT;
}
memset( &serverAddr, 0, sizeof( serverAddr ) );
serverAddr.sin_family = AF_INET;
serverAddr.sin_addr.s_addr = htonl( INADDR_ANY );
memset( &__ss_v4, 0, sizeof( __ss_v4 ) );
serverAddr4->sin_family = AF_INET;
serverAddr4->sin_addr.s_addr = htonl( INADDR_ANY );
memset( &__ss_v6, 0, sizeof( __ss_v6 ) );
serverAddr6->sin6_family = AF_INET6;
serverAddr6->sin6_addr = in6addr_any;
// Getting away with implementation of re-using address:port and instead
// choosing to increment port numbers.
@ -583,23 +658,69 @@ get_miniserver_sockets( MiniServerSockArray * out,
// THIS MAY CAUSE TCP TO BECOME LESS RELIABLE
// HOWEVER IT HAS BEEN SUGESTED FOR TCP SERVERS
UpnpPrintf( UPNP_INFO, MSERV, __FILE__, __LINE__,
"mserv start: resuseaddr set\n" );
sockError = setsockopt( listenfd, SOL_SOCKET, SO_REUSEADDR,
"get_miniserver_sockets: resuseaddr set\n" );
if( listenfd4 != INVALID_SOCKET ) {
sockError = setsockopt( listenfd4, SOL_SOCKET, SO_REUSEADDR,
(const char *)&reuseaddr_on, sizeof (int) );
if ( sockError == -1 ) {
shutdown( listenfd, SD_BOTH );
UpnpCloseSocket( listenfd );
shutdown( listenfd4, SD_BOTH );
UpnpCloseSocket( listenfd4 );
shutdown( listenfd6, SD_BOTH );
UpnpCloseSocket( listenfd6 );
return UPNP_E_SOCKET_BIND;
}
sockError = bind( listenfd, (struct sockaddr *)&serverAddr,
sizeof (struct sockaddr_in) );
sockError = bind( listenfd4, (struct sockaddr *)&__ss_v4,
sizeof(__ss_v4) );
if ( sockError == -1 ) {
strerror_r(errno, errorBuffer, ERROR_BUFFER_LEN);
UpnpPrintf( UPNP_INFO, MSERV, __FILE__, __LINE__,
"get_miniserver_sockets: Error in IPv4 bind(): %s\n",
errorBuffer );
shutdown( listenfd4, SD_BOTH );
UpnpCloseSocket( listenfd4 );
shutdown( listenfd6, SD_BOTH );
UpnpCloseSocket( listenfd6 );
return UPNP_E_SOCKET_BIND; // bind failed
}
}
if( listenfd6 != INVALID_SOCKET ) {
sockError = setsockopt( listenfd6, SOL_SOCKET, SO_REUSEADDR,
(const char *)&reuseaddr_on, sizeof (int) );
if ( sockError == -1 ) {
shutdown( listenfd4, SD_BOTH );
UpnpCloseSocket( listenfd4 );
shutdown( listenfd6, SD_BOTH );
UpnpCloseSocket( listenfd6 );
return UPNP_E_SOCKET_BIND;
}
sockError = bind( listenfd6, (struct sockaddr *)&__ss_v6,
sizeof(__ss_v6) );
if ( sockError == -1 ) {
strerror_r(errno, errorBuffer, ERROR_BUFFER_LEN);
UpnpPrintf( UPNP_INFO, MSERV, __FILE__, __LINE__,
"get_miniserver_sockets: Error in IPv6 bind(): %s\n",
errorBuffer );
shutdown( listenfd4, SD_BOTH );
UpnpCloseSocket( listenfd4 );
shutdown( listenfd6, SD_BOTH );
UpnpCloseSocket( listenfd6 );
return UPNP_E_SOCKET_BIND; // bind failed
}
}
} else {
if( listenfd4 != INVALID_SOCKET ) {
do {
serverAddr.sin_port = htons( listen_port++ );
sockError = bind( listenfd, (struct sockaddr *)&serverAddr,
sizeof (struct sockaddr_in) );
serverAddr4->sin_port = htons( listen_port4++ );
sockError = bind( listenfd4, (struct sockaddr *)&__ss_v4,
sizeof(__ss_v4) );
if ( sockError == -1 ) {
#ifdef WIN32
errCode = WSAGetLastError();
@ -611,67 +732,137 @@ get_miniserver_sockets( MiniServerSockArray * out,
}
} else
errCode = 0;
} while ( errCode != 0 );
}
if ( sockError == -1 ) {
strerror_r(errno, errorBuffer, ERROR_BUFFER_LEN);
UpnpPrintf( UPNP_INFO, MSERV, __FILE__, __LINE__,
"mserv start: Error in bind(): %s\n", errorBuffer );
shutdown( listenfd, SD_BOTH );
UpnpCloseSocket( listenfd );
"get_miniserver_sockets: Error in IPv4 bind(): %s\n",
errorBuffer );
shutdown( listenfd4, SD_BOTH );
UpnpCloseSocket( listenfd4 );
shutdown( listenfd6, SD_BOTH );
UpnpCloseSocket( listenfd6 );
return UPNP_E_SOCKET_BIND; // bind failed
}
}
UpnpPrintf( UPNP_INFO, MSERV, __FILE__, __LINE__,
"mserv start: bind success\n" );
success = listen( listenfd, SOMAXCONN );
if ( success == -1 ) {
if( listenfd6 != INVALID_SOCKET ) {
do {
serverAddr4->sin_port = htons( listen_port6++ );
sockError = bind( listenfd6, (struct sockaddr *)&__ss_v4,
sizeof(__ss_v4) );
if ( sockError == -1 ) {
#ifdef WIN32
errCode = WSAGetLastError();
#else
errCode = errno;
#endif
if( errno == EADDRINUSE ) {
errCode = 1;
}
} else
errCode = 0;
} while ( errCode != 0 );
if ( sockError == -1 ) {
strerror_r(errno, errorBuffer, ERROR_BUFFER_LEN);
UpnpPrintf( UPNP_INFO, MSERV, __FILE__, __LINE__,
"mserv start: Error in listen(): %s\n", errorBuffer );
shutdown( listenfd, SD_BOTH );
UpnpCloseSocket( listenfd );
"get_miniserver_sockets: Error in IPv6 bind(): %s\n",
errorBuffer );
shutdown( listenfd4, SD_BOTH );
UpnpCloseSocket( listenfd4 );
shutdown( listenfd6, SD_BOTH );
UpnpCloseSocket( listenfd6 );
return UPNP_E_SOCKET_BIND; // bind failed
}
}
}
UpnpPrintf( UPNP_INFO, MSERV, __FILE__, __LINE__,
"get_miniserver_sockets: bind successful\n" );
if( listenfd4 != INVALID_SOCKET ) {
ret_code = listen( listenfd4, SOMAXCONN );
if ( ret_code == -1 ) {
strerror_r(errno, errorBuffer, ERROR_BUFFER_LEN);
UpnpPrintf( UPNP_INFO, MSERV, __FILE__, __LINE__,
"mserv start: Error in IPv4 listen(): %s\n", errorBuffer );
shutdown( listenfd4, SD_BOTH );
UpnpCloseSocket( listenfd4 );
shutdown( listenfd6, SD_BOTH );
UpnpCloseSocket( listenfd6 );
return UPNP_E_LISTEN;
}
actual_port = get_port( listenfd );
if( actual_port <= 0 ) {
shutdown( listenfd, SD_BOTH );
UpnpCloseSocket( listenfd );
actual_port4 = get_port( listenfd4 );
if( actual_port4 <= 0 ) {
shutdown( listenfd4, SD_BOTH );
UpnpCloseSocket( listenfd4 );
shutdown( listenfd6, SD_BOTH );
UpnpCloseSocket( listenfd6 );
return UPNP_E_INTERNAL_ERROR;
}
out->miniServerPort = actual_port;
out->miniServerPort4 = actual_port4;
}
if( listenfd6 != INVALID_SOCKET ) {
ret_code = listen( listenfd6, SOMAXCONN );
if ( ret_code == -1 ) {
strerror_r(errno, errorBuffer, ERROR_BUFFER_LEN);
UpnpPrintf( UPNP_INFO, MSERV, __FILE__, __LINE__,
"mserv start: Error in IPv6 listen(): %s\n", errorBuffer );
shutdown( listenfd4, SD_BOTH );
UpnpCloseSocket( listenfd4 );
shutdown( listenfd6, SD_BOTH );
UpnpCloseSocket( listenfd6 );
return UPNP_E_LISTEN;
}
actual_port6 = get_port( listenfd6 );
if( actual_port6 <= 0 ) {
shutdown( listenfd4, SD_BOTH );
UpnpCloseSocket( listenfd4 );
shutdown( listenfd6, SD_BOTH );
UpnpCloseSocket( listenfd6 );
return UPNP_E_INTERNAL_ERROR;
}
out->miniServerPort6 = actual_port6;
}
miniServerStopSock = socket( AF_INET, SOCK_DGRAM, 0 );
if ( miniServerStopSock == -1 ) {
strerror_r(errno, errorBuffer, ERROR_BUFFER_LEN);
UpnpPrintf( UPNP_CRITICAL, MSERV, __FILE__, __LINE__,
"Error in socket(): %s\n", errorBuffer );
shutdown( listenfd, SD_BOTH );
UpnpCloseSocket( listenfd );
shutdown( listenfd4, SD_BOTH );
UpnpCloseSocket( listenfd4 );
shutdown( listenfd6, SD_BOTH );
UpnpCloseSocket( listenfd6 );
return UPNP_E_OUTOF_SOCKET;
}
// bind to local socket
memset( ( char * )&serverAddr, 0, sizeof( struct sockaddr_in ) );
serverAddr.sin_family = AF_INET;
serverAddr.sin_addr.s_addr = inet_addr( "127.0.0.1" );
ret = bind( miniServerStopSock, (struct sockaddr *)&serverAddr,
sizeof (serverAddr) );
memset( &__ss_v4, 0, sizeof( __ss_v4 ) );
serverAddr4->sin_family = AF_INET;
serverAddr4->sin_addr.s_addr = inet_addr( "127.0.0.1" );
ret = bind( miniServerStopSock, (struct sockaddr *)&__ss_v4,
sizeof(__ss_v4) );
if ( ret == -1 ) {
UpnpPrintf( UPNP_CRITICAL,
MSERV, __FILE__, __LINE__,
"Error in binding localhost!!!\n" );
shutdown( listenfd, SD_BOTH );
UpnpCloseSocket( listenfd );
shutdown( listenfd4, SD_BOTH );
UpnpCloseSocket( listenfd4 );
shutdown( listenfd6, SD_BOTH );
UpnpCloseSocket( listenfd6 );
shutdown( miniServerStopSock, SD_BOTH );
UpnpCloseSocket( miniServerStopSock );
@ -682,14 +873,17 @@ get_miniserver_sockets( MiniServerSockArray * out,
if ( miniStopSockPort <= 0 ) {
shutdown( miniServerStopSock, SD_BOTH );
UpnpCloseSocket( miniServerStopSock );
shutdown( listenfd, SD_BOTH );
UpnpCloseSocket( listenfd );
shutdown( listenfd4, SD_BOTH );
UpnpCloseSocket( listenfd4 );
shutdown( listenfd6, SD_BOTH );
UpnpCloseSocket( listenfd6 );
return UPNP_E_INTERNAL_ERROR;
}
out->stopPort = miniStopSockPort;
out->miniServerSock = listenfd;
out->miniServerSock4 = listenfd4;
out->miniServerSock6 = listenfd6;
out->miniServerStopSock = miniServerStopSock;
return UPNP_E_SUCCESS;
@ -698,12 +892,13 @@ get_miniserver_sockets( MiniServerSockArray * out,
/************************************************************************
* Function: StartMiniServer
*
* Parameters :
* unsigned short listen_port - Port on which the server listens for
* incoming connections
* Parameters:
* IN OUT unsigned short *listen_port4 ; Port on which the server
* listens for incoming IPv4 connections.
* IN OUT unsigned short *listen_port6 ; Port on which the server
* listens for incoming IPv6 connections.
*
* Description:
* Initialize the sockets functionality for the
* Description: Initialize the sockets functionality for the
* Miniserver. Initialize a thread pool job to run the MiniServer
* and the job to the thread pool. If listen port is 0, port is
* dynamically picked
@ -711,14 +906,15 @@ get_miniserver_sockets( MiniServerSockArray * out,
* Use timer mechanism to start the MiniServer, failure to meet the
* allowed delay aborts the attempt to launch the MiniServer.
*
* Return: int
* Actual port socket is bound to - On Success
* A negative number UPNP_E_XXX - On Error
* Return: int;
* On success: UPNP_E_SUCCESS
* On error: PNP_E_XXX
************************************************************************/
int
StartMiniServer( unsigned short listen_port )
StartMiniServer( unsigned short* listen_port4,
unsigned short* listen_port6 )
{
int success;
int ret_code;
int count;
int max_count = 10000;
@ -733,39 +929,48 @@ StartMiniServer( unsigned short listen_port )
if( miniSocket == NULL ) {
return UPNP_E_OUTOF_MEMORY;
}
memset( miniSocket, 0, sizeof(*miniSocket) );
success = get_miniserver_sockets( miniSocket, listen_port );
if( success != UPNP_E_SUCCESS ) {
ret_code = get_miniserver_sockets( miniSocket, *listen_port4, *listen_port6 );
if( ret_code != UPNP_E_SUCCESS ) {
free( miniSocket );
return success;
return ret_code;
}
success = get_ssdp_sockets( miniSocket );
if( success != UPNP_E_SUCCESS ) {
shutdown( miniSocket->miniServerSock, SD_BOTH );
UpnpCloseSocket( miniSocket->miniServerSock );
ret_code = get_ssdp_sockets( miniSocket );
if( ret_code != UPNP_E_SUCCESS ) {
shutdown( miniSocket->miniServerSock4, SD_BOTH );
UpnpCloseSocket( miniSocket->miniServerSock4 );
shutdown( miniSocket->miniServerSock6, SD_BOTH );
UpnpCloseSocket( miniSocket->miniServerSock6 );
shutdown( miniSocket->miniServerStopSock, SD_BOTH );
UpnpCloseSocket( miniSocket->miniServerStopSock );
free( miniSocket );
return success;
return ret_code;
}
TPJobInit( &job, (start_routine)RunMiniServer, (void *)miniSocket );
TPJobSetPriority( &job, MED_PRIORITY );
TPJobSetFreeFunction( &job, ( free_routine ) free );
success = ThreadPoolAddPersistent( &gMiniServerThreadPool, &job, NULL );
if ( success < 0 ) {
shutdown( miniSocket->miniServerSock, SD_BOTH );
UpnpCloseSocket( miniSocket->miniServerSock );
ret_code = ThreadPoolAddPersistent( &gMiniServerThreadPool, &job, NULL );
if ( ret_code < 0 ) {
shutdown( miniSocket->miniServerSock4, SD_BOTH );
UpnpCloseSocket( miniSocket->miniServerSock4 );
shutdown( miniSocket->miniServerSock6, SD_BOTH );
UpnpCloseSocket( miniSocket->miniServerSock6 );
shutdown( miniSocket->miniServerStopSock, SD_BOTH );
UpnpCloseSocket( miniSocket->miniServerStopSock );
shutdown( miniSocket->ssdpSock, SD_BOTH );
UpnpCloseSocket( miniSocket->ssdpSock );
shutdown( miniSocket->ssdpSock4, SD_BOTH );
UpnpCloseSocket( miniSocket->ssdpSock4 );
shutdown( miniSocket->ssdpSock6, SD_BOTH );
UpnpCloseSocket( miniSocket->ssdpSock6 );
#ifdef INCLUDE_CLIENT_APIS
shutdown( miniSocket->ssdpReqSock, SD_BOTH );
UpnpCloseSocket( miniSocket->ssdpReqSock );
shutdown( miniSocket->ssdpReqSock4, SD_BOTH );
UpnpCloseSocket( miniSocket->ssdpReqSock4 );
shutdown( miniSocket->ssdpReqSock6, SD_BOTH );
UpnpCloseSocket( miniSocket->ssdpReqSock6 );
#endif
return UPNP_E_OUTOF_MEMORY;
@ -779,21 +984,29 @@ StartMiniServer( unsigned short listen_port )
// taking too long to start that thread
if ( count >= max_count ) {
shutdown( miniSocket->miniServerSock, SD_BOTH );
UpnpCloseSocket( miniSocket->miniServerSock );
shutdown( miniSocket->miniServerSock4, SD_BOTH );
UpnpCloseSocket( miniSocket->miniServerSock4 );
shutdown( miniSocket->miniServerSock6, SD_BOTH );
UpnpCloseSocket( miniSocket->miniServerSock6 );
shutdown( miniSocket->miniServerStopSock, SD_BOTH );
UpnpCloseSocket( miniSocket->miniServerStopSock );
shutdown( miniSocket->ssdpSock, SD_BOTH );
UpnpCloseSocket( miniSocket->ssdpSock );
shutdown( miniSocket->ssdpSock4, SD_BOTH );
UpnpCloseSocket( miniSocket->ssdpSock4 );
shutdown( miniSocket->ssdpSock6, SD_BOTH );
UpnpCloseSocket( miniSocket->ssdpSock6 );
#ifdef INCLUDE_CLIENT_APIS
shutdown( miniSocket->ssdpReqSock, SD_BOTH );
UpnpCloseSocket( miniSocket->ssdpReqSock );
shutdown( miniSocket->ssdpReqSock4, SD_BOTH );
UpnpCloseSocket( miniSocket->ssdpReqSock4 );
shutdown( miniSocket->ssdpReqSock6, SD_BOTH );
UpnpCloseSocket( miniSocket->ssdpReqSock6 );
#endif
return UPNP_E_INTERNAL_ERROR;
}
*listen_port4 = miniSocket->miniServerPort4;
*listen_port6 = miniSocket->miniServerPort6;
return miniSocket->miniServerPort;
return UPNP_E_SUCCESS;
}
/************************************************************************
@ -814,7 +1027,7 @@ StopMiniServer()
{
char errorBuffer[ERROR_BUFFER_LEN];
int socklen = sizeof( struct sockaddr_in );
int sock;
SOCKET sock;
struct sockaddr_in ssdpAddr;
char buf[256] = "ShutDown";
int bufLen = strlen( buf );

View File

@ -175,13 +175,13 @@ http_Connect( IN uri_type * destination_url,
http_FixUrl( destination_url, url );
connfd = socket( AF_INET, SOCK_STREAM, 0 );
connfd = socket( url->hostport.IPaddress.ss_family, SOCK_STREAM, 0 );
if( connfd == -1 ) {
return UPNP_E_OUTOF_SOCKET;
}
if( connect( connfd, ( struct sockaddr * )&url->hostport.IPv4address,
sizeof( struct sockaddr_in ) ) == -1 ) {
if( connect( connfd, ( struct sockaddr * )&url->hostport.IPaddress,
sizeof( url->hostport.IPaddress ) ) == -1 ) {
#ifdef WIN32
UpnpPrintf(UPNP_CRITICAL, HTTP, __FILE__, __LINE__,
"connect error: %d\n", WSAGetLastError());
@ -521,7 +521,7 @@ http_RequestAndResponse( IN uri_type * destination,
int http_error_code;
SOCKINFO info;
tcp_connection = socket( AF_INET, SOCK_STREAM, 0 );
tcp_connection = socket( destination->hostport.IPaddress.ss_family, SOCK_STREAM, 0 );
if( tcp_connection == -1 ) {
parser_response_init( response, req_method );
return UPNP_E_SOCKET_ERROR;
@ -535,7 +535,7 @@ http_RequestAndResponse( IN uri_type * destination,
// connect
ret_code = connect( info.socket,
( struct sockaddr * )&destination->hostport.
IPv4address, sizeof( struct sockaddr_in ) );
IPaddress, sizeof( struct sockaddr_storage ) );
if( ret_code == -1 ) {
sock_destroy( &info, SD_BOTH );
@ -1005,7 +1005,7 @@ http_OpenHttpPost( IN const char *url_str,
handle->contentLength = contentLength;
tcp_connection = socket( AF_INET, SOCK_STREAM, 0 );
tcp_connection = socket( url.hostport.IPaddress.ss_family, SOCK_STREAM, 0 );
if( tcp_connection == -1 ) {
ret_code = UPNP_E_SOCKET_ERROR;
goto errorHandler;
@ -1019,8 +1019,8 @@ http_OpenHttpPost( IN const char *url_str,
}
ret_code = connect( handle->sock_info.socket,
( struct sockaddr * )&url.hostport.IPv4address,
sizeof( struct sockaddr_in ) );
( struct sockaddr * )&url.hostport.IPaddress,
sizeof( struct sockaddr_storage ) );
if( ret_code == -1 ) {
sock_destroy( &handle->sock_info, SD_BOTH );
@ -1587,7 +1587,7 @@ http_OpenHttpGetProxy( IN const char *url_str,
handle->cancel = 0;
parser_response_init( &handle->response, HTTPMETHOD_GET );
tcp_connection = socket( AF_INET, SOCK_STREAM, 0 );
tcp_connection = socket( peer->hostport.IPaddress.ss_family, SOCK_STREAM, 0 );
if( tcp_connection == -1 ) {
ret_code = UPNP_E_SOCKET_ERROR;
goto errorHandler;
@ -1601,8 +1601,8 @@ http_OpenHttpGetProxy( IN const char *url_str,
}
ret_code = connect( handle->sock_info.socket,
( struct sockaddr * )&peer->hostport.IPv4address,
sizeof( struct sockaddr_in ) );
( struct sockaddr * )&peer->hostport.IPaddress,
sizeof( struct sockaddr_storage ) );
if( ret_code == -1 ) {
sock_destroy( &handle->sock_info, SD_BOTH );
@ -2236,7 +2236,7 @@ http_OpenHttpGetEx( IN const char *url_str,
handle->entity_offset = 0;
parser_response_init( &handle->response, HTTPMETHOD_GET );
tcp_connection = socket( AF_INET, SOCK_STREAM, 0 );
tcp_connection = socket( url.hostport.IPaddress.ss_family, SOCK_STREAM, 0 );
if( tcp_connection == -1 ) {
errCode = UPNP_E_SOCKET_ERROR;
free( handle );
@ -2252,8 +2252,8 @@ http_OpenHttpGetEx( IN const char *url_str,
}
errCode = connect( handle->sock_info.socket,
( struct sockaddr * )&url.hostport.IPv4address,
sizeof( struct sockaddr_in ) );
( struct sockaddr * )&url.hostport.IPaddress,
sizeof( struct sockaddr_storage ) );
if( errCode == -1 ) {
sock_destroy( &handle->sock_info, SD_BOTH );
errCode = UPNP_E_SOCKET_CONNECT;

View File

@ -62,7 +62,7 @@
*
* Parameters :
* OUT SOCKINFO* info ; Socket Information Object
* IN int sockfd ; Socket Descriptor
* IN SOCKET sockfd ; Socket Descriptor
*
* Description : Assign the passed in socket descriptor to socket
* descriptor in the SOCKINFO structure.
@ -76,7 +76,7 @@
************************************************************************/
int
sock_init( OUT SOCKINFO * info,
IN int sockfd )
IN SOCKET sockfd )
{
assert( info );
@ -92,9 +92,8 @@ sock_init( OUT SOCKINFO * info,
*
* Parameters :
* OUT SOCKINFO* info ; Socket Information Object
* IN int sockfd ; Socket Descriptor
* IN struct in_addr foreign_ip_addr ; Remote IP Address
* IN unsigned short foreign_ip_port ; Remote Port number
* IN SOCKET sockfd ; Socket Descriptor
* IN struct sockaddr* foreign_sockaddr; remote socket address.
*
* Description : Calls the sock_init function and assigns the passed in
* IP address and port to the IP address and port in the SOCKINFO
@ -109,9 +108,8 @@ sock_init( OUT SOCKINFO * info,
************************************************************************/
int
sock_init_with_ip( OUT SOCKINFO * info,
IN int sockfd,
IN struct in_addr foreign_ip_addr,
IN unsigned short foreign_ip_port )
IN SOCKET sockfd,
IN struct sockaddr* foreign_sockaddr )
{
int ret;
@ -120,8 +118,8 @@ sock_init_with_ip( OUT SOCKINFO * info,
return ret;
}
info->foreign_ip_addr = foreign_ip_addr;
info->foreign_ip_port = foreign_ip_port;
memcpy( &info->foreign_sockaddr, foreign_sockaddr,
sizeof( info->foreign_sockaddr) );
return UPNP_E_SUCCESS;
}
@ -149,10 +147,12 @@ int
sock_destroy( INOUT SOCKINFO * info,
int ShutdownMethod )
{
if( info->socket != INVALID_SOCKET ) {
shutdown( info->socket, ShutdownMethod );
if( UpnpCloseSocket( info->socket ) == -1 ) {
return UPNP_E_SOCKET_ERROR;
}
}
return UPNP_E_SUCCESS;
}
@ -190,7 +190,7 @@ sock_read_write( IN SOCKINFO * info,
struct timeval timeout;
int numBytes;
time_t start_time = time( NULL );
int sockfd = info->socket;
SOCKET sockfd = info->socket;
long bytes_sent = 0,
byte_left = 0,
num_written;
@ -202,9 +202,9 @@ sock_read_write( IN SOCKINFO * info,
FD_ZERO( &readSet );
FD_ZERO( &writeSet );
if( bRead ) {
FD_SET( ( unsigned )sockfd, &readSet );
FD_SET( sockfd, &readSet );
} else {
FD_SET( ( unsigned )sockfd, &writeSet );
FD_SET( sockfd, &writeSet );
}
timeout.tv_sec = *timeoutSecs;

View File

@ -41,10 +41,7 @@
#endif
#include "config.h"
#include "uri.h"
#ifdef WIN32
#include "inet_pton.h"
#endif
#include "upnpapi.h"
/************************************************************************
@ -224,28 +221,6 @@ parse_uric( const char *in,
return i;
}
/************************************************************************
* Function : copy_sockaddr_in
*
* Parameters :
* const struct sockaddr_in *in ; Source socket address object
* struct sockaddr_in *out ; Destination socket address object
*
* Description : Copies one socket address into another
*
* Return : void ;
*
* Note :
************************************************************************/
void
copy_sockaddr_in( const struct sockaddr_in *in,
struct sockaddr_in *out )
{
memset( out->sin_zero, 0, 8 );
out->sin_family = in->sin_family;
out->sin_port = in->sin_port;
out->sin_addr.s_addr = in->sin_addr.s_addr;
}
/************************************************************************
* Function : copy_token
@ -328,8 +303,9 @@ copy_URL_list( URL_list * in,
in->URLs, &out->parsedURLs[i].hostport.text,
out->URLs );
copy_sockaddr_in( &in->parsedURLs[i].hostport.IPv4address,
&out->parsedURLs[i].hostport.IPv4address );
memcpy( &out->parsedURLs[i].hostport.IPaddress,
&in->parsedURLs[i].hostport.IPaddress,
sizeof(struct sockaddr_storage) );
}
out->size = in->size;
return HTTP_SUCCESS;
@ -490,48 +466,13 @@ token_cmp( token * in1,
return memcmp( in1->buff, in2->buff, in1->size );
}
/************************************************************************
* Function : parse_port
*
* Parameters :
* int max ; sets a maximum limit
* char * port ; port to be parsed.
* unsigned short * out ; out parameter where the port is parsed
* and converted into network format
*
* Description : parses a port (i.e. '4000') and converts it into a
* network ordered unsigned short int.
*
* Return : int ;
*
* Note :
************************************************************************/
int
parse_port( int max,
const char *port,
unsigned short *out )
{
const char *finger = port;
const char *max_ptr = finger + max;
unsigned short temp = 0;
while( ( finger < max_ptr ) && ( isdigit( *finger ) ) ) {
temp = temp * 10;
temp += ( *finger ) - '0';
finger++;
}
*out = htons( temp );
return finger - port;
}
/************************************************************************
* Function : parse_hostport
*
* Parameters :
* char *in ; string of characters representing host and port
* int max ; sets a maximum limit
* int max ; sets a maximum limit (not used).
* hostport_type *out ; out parameter where the host and port
* are represented as an internet address
*
@ -540,7 +481,8 @@ parse_port( int max,
* hostport_type struct with internet address and a token
* representing the full host and port. uses gethostbyname.
*
* Return : int ;
* Returns: The number of characters that form up the host and port.
* UPNP_E_INVALID_URL on error.
*
* Note :
************************************************************************/
@ -549,165 +491,145 @@ parse_hostport( const char *in,
int max,
hostport_type * out )
{
#define BUFFER_SIZE 8192
char workbuf[256];
char* c;
struct sockaddr_in* sai4 = (struct sockaddr_in*)&out->IPaddress;
struct sockaddr_in6* sai6 = (struct sockaddr_in6*)&out->IPaddress;
char *srvname = NULL;
char *srvport = NULL;
char *last_dot = NULL;
unsigned short int port;
int af = AF_UNSPEC;
int hostport_size;
int has_port = 0;
int ret;
int i = 0;
int begin_port;
int hostport_size = 0;
int host_size = 0;
#if !defined(WIN32) && !(defined(__OSX__) || defined(__APPLE__))
char temp_hostbyname_buff[BUFFER_SIZE];
struct hostent h_buf;
#endif
struct hostent *h = NULL;
int errcode = 0;
char *temp_host_name = NULL;
int last_dot = -1;
memset( out, 0, sizeof(hostport_type) );
out->text.size = 0;
out->text.buff = NULL;
// Work on a copy of the input string.
strncpy( workbuf, in, sizeof(workbuf) );
out->IPv4address.sin_port = htons( 80 ); //default port is 80
memset( &out->IPv4address.sin_zero, 0, 8 );
while( ( i < max ) && ( in[i] != ':' ) && ( in[i] != '/' )
&& ( ( isalnum( in[i] ) ) || ( in[i] == '.' )
|| ( in[i] == '-' ) ) ) {
i++;
if( in[i] == '.' ) {
last_dot = i;
c = workbuf;
if( *c == '[' ) {
// IPv6 addresses are enclosed in square brackets.
srvname = ++c;
while( *c != '\0' && *c != ']' ) {
c++;
}
}
host_size = i;
if( ( i < max ) && ( in[i] == ':' ) ) {
begin_port = i + 1;
//convert port
if( !( hostport_size = parse_port( max - begin_port,
&in[begin_port],
&out->IPv4address.sin_port ) ) )
{
if( *c == '\0' ) {
// did not find closing bracket.
return UPNP_E_INVALID_URL;
}
hostport_size += begin_port;
} else
hostport_size = host_size;
//convert to temporary null terminated string
temp_host_name = ( char * )malloc( host_size + 1 );
if( temp_host_name == NULL )
return UPNP_E_OUTOF_MEMORY;
memcpy( temp_host_name, in, host_size );
temp_host_name[host_size] = '\0';
//check to see if host name is an ipv4 address
if( ( last_dot != -1 ) && ( last_dot + 1 < host_size )
&& ( isdigit( temp_host_name[last_dot + 1] ) ) ) {
//must be ipv4 address
errcode = inet_pton( AF_INET,
temp_host_name, &out->IPv4address.sin_addr );
if( errcode == 1 ) {
out->IPv4address.sin_family = AF_INET;
} else {
out->IPv4address.sin_addr.s_addr = 0;
out->IPv4address.sin_family = AF_INET;
free( temp_host_name );
temp_host_name = NULL;
return UPNP_E_INVALID_URL;
// NULL terminate the srvname and then increment c.
*c++ = '\0'; // overwrite the ']'
if( *c == ':' ) {
has_port = 1;
c++;
}
} else {
int errCode = 0;
af = AF_INET6;
}
else {
// IPv4 address -OR- host name.
srvname = c;
while( (*c != ':') && (*c != '/') && ( (isalnum(*c)) || (*c == '.') || (*c == '-') ) ) {
if( *c == '.' )
last_dot = c;
c++;
}
has_port = (*c == ':') ? 1 : 0;
// NULL terminate the srvname
*c = '\0';
if( has_port == 1 )
c++;
//call gethostbyname_r (reentrant form of gethostbyname)
// TODO: Use autoconf to discover this rather than the
// platform-specific stuff below
#if defined(WIN32) || defined(__CYGWIN__)
h = gethostbyname(temp_host_name);
#elif defined(SPARC_SOLARIS)
errCode = gethostbyname_r(
temp_host_name,
&h,
temp_hostbyname_buff,
BUFFER_SIZE, &errcode );
#elif defined(__FreeBSD__) && __FreeBSD_version < 601103
h = lwres_gethostbyname_r(
temp_host_name,
&h_buf,
temp_hostbyname_buff,
BUFFER_SIZE, &errcode );
if ( h == NULL ) {
errCode = 1;
if( last_dot != NULL && isdigit(*(last_dot+1)) ) {
// Must be an IPv4 address.
af = AF_INET;
}
#elif defined(__OSX__) || defined(__APPLE__)
h = gethostbyname(temp_host_name);
if ( h == NULL ) {
errCode = 1;
}
#elif defined(__linux__)
errCode = gethostbyname_r(
temp_host_name,
&h_buf,
temp_hostbyname_buff,
BUFFER_SIZE, &h, &errcode );
#else
{
else {
// Must be a host name.
struct addrinfo hints, *res, *res0;
h = NULL;
memset(&hints, 0, sizeof(hints));
hints.ai_family = PF_INET;
hints.ai_family = AF_UNSPEC;
hints.ai_socktype = SOCK_STREAM;
errCode = getaddrinfo(temp_host_name, "http", &hints, &res0);
if (!errCode) {
ret = getaddrinfo(srvname, NULL, &hints, &res0);
if( ret == 0 ) {
for (res = res0; res; res = res->ai_next) {
if (res->ai_family == PF_INET &&
res->ai_addr->sa_family == AF_INET)
{
h = &h_buf;
h->h_addrtype = res->ai_addr->sa_family;
h->h_length = 4;
h->h_addr = (void *) temp_hostbyname_buff;
*(struct in_addr *)h->h_addr =
((struct sockaddr_in *)res->ai_addr)->sin_addr;
if( res->ai_family == AF_INET ||
res->ai_family == AF_INET6 ) {
// Found a valid IPv4 or IPv6 address.
memcpy( &out->IPaddress, res->ai_addr,
res->ai_addrlen );
break;
}
}
freeaddrinfo(res0);
}
}
#endif
if( errCode == 0 ) {
if( h ) {
if( ( h->h_addrtype == AF_INET ) && ( h->h_length == 4 ) ) {
out->IPv4address.sin_addr =
( *( struct in_addr * )h->h_addr );
out->IPv4address.sin_family = AF_INET;
}
}
} else {
out->IPv4address.sin_addr.s_addr = 0;
out->IPv4address.sin_family = AF_INET;
free( temp_host_name );
temp_host_name = NULL;
if( res == NULL ) {
// Didn't find an AF_INET or AF_INET6 address.
return UPNP_E_INVALID_URL;
}
}
else {
// getaddrinfo failed.
return UPNP_E_INVALID_URL;
}
}
}
if( temp_host_name ) {
free( temp_host_name );
temp_host_name = NULL;
// Check if a port is specified.
if( has_port == 1 ) {
// Port is specified.
srvport = c;
while( *c != '\0' && isdigit(*c) ) {
c++;
}
port = (unsigned short int)atoi(srvport);
if( port == 0 ) {
// Bad port number.
return UPNP_E_INVALID_URL;
}
}
else {
// Port was not specified, use default port.
port = 80;
}
// The length of the host and port string can be calculated by
// subtracting pointers.
hostport_size = (int)(c - workbuf);
// Fill in the 'out' information.
if( af == AF_INET ) {
sai4->sin_family = AF_INET;
sai4->sin_port = htons(port);
ret = inet_pton(AF_INET, srvname, &sai4->sin_addr);
}
else if( af == AF_INET6 ) {
sai6->sin6_family = AF_INET6;
sai6->sin6_port = htons(port);
sai6->sin6_scope_id = gIF_INDEX;
ret = inet_pton(AF_INET6, srvname, &sai6->sin6_addr);
} else {
// IP address was set by the hostname (getaddrinfo).
// Override port:
if( out->IPaddress.ss_family == AF_INET )
sai4->sin_port = htons(port);
else
sai6->sin6_port = htons(port);
ret = 1;
}
// Check if address was converted successfully.
if( ret <= 0 ) {
return UPNP_E_INVALID_URL;
}
out->text.size = hostport_size;
out->text.buff = in;
return hostport_size;
}
/************************************************************************
@ -1069,10 +991,7 @@ parse_uri( const char *in,
return begin_path;
} else {
out->hostport.IPv4address.sin_port = 0;
out->hostport.IPv4address.sin_addr.s_addr = 0;
out->hostport.text.size = 0;
out->hostport.text.buff = 0;
memset( &out->hostport, 0, sizeof(out->hostport) );
begin_path = begin_hostport;
}

View File

@ -106,7 +106,7 @@ typedef struct TOKEN {
//the full string representation
typedef struct HOSTPORT {
token text; //full host port
struct sockaddr_in IPv4address; //Network Byte Order
struct sockaddr_storage IPaddress; //Network Byte Order
} hostport_type;
//Represents a URI

View File

@ -42,17 +42,21 @@ extern SOCKET gMiniServerStopSock;
typedef struct MServerSockArray {
/* socket for listening for miniserver requests */
int miniServerSock;
SOCKET miniServerSock4;
SOCKET miniServerSock6;
/* socket for stopping miniserver */
int miniServerStopSock;
SOCKET miniServerStopSock;
/* socket for incoming advertisments and search requests */
int ssdpSock;
SOCKET ssdpSock4;
SOCKET ssdpSock6;
int stopPort;
int miniServerPort;
SOCKET stopPort;
SOCKET miniServerPort4;
SOCKET miniServerPort6;
/* socket for sending search requests and receiving search replies */
CLIENTONLY(int ssdpReqSock;)
CLIENTONLY(SOCKET ssdpReqSock4;)
CLIENTONLY(SOCKET ssdpReqSock6;)
} MiniServerSockArray;
@ -110,8 +114,10 @@ void SetGenaCallback( MiniServerCallback callback );
* Function: StartMiniServer
*
* Parameters:
* unsigned short listen_port ; Port on which the server listens for
* incoming connections
* IN OUT unsigned short *listen_port4 ; Port on which the server
* listens for incoming IPv4 connections.
* IN OUT unsigned short *listen_port6 ; Port on which the server
* listens for incoming IPv6 connections.
*
* Description: Initialize the sockets functionality for the
* Miniserver. Initialize a thread pool job to run the MiniServer
@ -122,10 +128,11 @@ void SetGenaCallback( MiniServerCallback callback );
* allowed delay aborts the attempt to launch the MiniServer.
*
* Return: int;
* Actual port socket is bound to - On Success:
* A negative number UPNP_E_XXX - On Error
* On success: UPNP_E_SUCCESS
* On error: UPNP_E_XXX
************************************************************************/
int StartMiniServer( unsigned short listen_port );
int StartMiniServer( IN OUT unsigned short* listen_port4,
IN OUT unsigned short* listen_port6 );
/************************************************************************
* Function: StopMiniServer

View File

@ -48,11 +48,10 @@
typedef struct
{
int socket; // handle/descriptor to a socket
SOCKET socket; // handle/descriptor to a socket
// the following two fields are filled only in incoming requests;
struct in_addr foreign_ip_addr;
unsigned short foreign_ip_port;
struct sockaddr_storage foreign_sockaddr;
} SOCKINFO;
@ -65,7 +64,7 @@ typedef struct
*
* Parameters :
* OUT SOCKINFO* info ; Socket Information Object
* IN int sockfd ; Socket Descriptor
* IN SOCKET sockfd ; Socket Descriptor
*
* Description : Assign the passed in socket descriptor to socket
* descriptor in the SOCKINFO structure.
@ -76,16 +75,15 @@ typedef struct
* UPNP_E_SOCKET_ERROR
* Note :
************************************************************************/
int sock_init( OUT SOCKINFO* info, IN int sockfd );
int sock_init(OUT SOCKINFO* info, IN SOCKET sockfd);
/************************************************************************
* Function : sock_init_with_ip
*
* Parameters :
* OUT SOCKINFO* info ; Socket Information Object
* IN int sockfd ; Socket Descriptor
* IN struct in_addr foreign_ip_addr ; Remote IP Address
* IN unsigned short foreign_ip_port ; Remote Port number
* IN SOCKET sockfd ; Socket Descriptor
* IN struct sockaddr* foreign_sockaddr; Remote socket address
*
* Description : Calls the sock_init function and assigns the passed in
* IP address and port to the IP address and port in the SOCKINFO
@ -98,8 +96,10 @@ int sock_init( OUT SOCKINFO* info, IN int sockfd );
*
* Note :
************************************************************************/
int sock_init_with_ip( OUT SOCKINFO* info, IN int sockfd,
IN struct in_addr foreign_ip_addr, IN unsigned short foreign_ip_port );
int sock_init_with_ip(
OUT SOCKINFO* info,
IN SOCKET sockfd,
IN struct sockaddr *foreign_sockaddr);
/************************************************************************
* Function : sock_read
@ -162,7 +162,7 @@ int sock_write( IN SOCKINFO *info, IN char* buffer, IN size_t bufsize,
*
* Note :
************************************************************************/
int sock_destroy( INOUT SOCKINFO* info,int );
int sock_destroy(INOUT SOCKINFO* info, int);
#ifdef __cplusplus
} // #extern "C"

View File

@ -78,6 +78,7 @@ typedef enum SsdpCmdType{SSDP_ERROR=-1,
//Constant
#define BUFSIZE 2500
#define SSDP_IP "239.255.255.250"
#define SSDP_IPV6_LINKLOCAL "FF02::C"
#define SSDP_PORT 1900
#define NUM_TRY 3
#define NUM_COPY 1
@ -121,7 +122,7 @@ typedef struct SsdpEventStruct
char Os[LINE_SIZE];
char Ext[LINE_SIZE];
char Date[LINE_SIZE];
struct sockaddr_in * DestAddr;
struct sockaddr *DestAddr;
void * Cookie;
} Event;
@ -134,7 +135,7 @@ typedef struct TData
int Mx;
void * Cookie;
char * Data;
struct sockaddr_in DestAddr;
struct sockaddr_storage DestAddr;
}ThreadData;
@ -142,7 +143,7 @@ typedef struct ssdpsearchreply
{
int MaxAge;
UpnpDevice_Handle handle;
struct sockaddr_in dest_addr;
struct sockaddr_storage dest_addr;
SsdpEvent event;
}SsdpSearchReply;
@ -159,13 +160,14 @@ typedef struct ssdpsearcharg
typedef struct
{
http_parser_t parser;
struct sockaddr_in dest_addr;
struct sockaddr_storage dest_addr;
} ssdp_thread_data;
/* globals */
CLIENTONLY(extern SOCKET gSsdpReqSocket;);
CLIENTONLY(extern SOCKET gSsdpReqSocket4;);
CLIENTONLY(extern SOCKET gSsdpReqSocket6;);
typedef int (*ParserFun)(char *, Event *);
@ -205,11 +207,11 @@ int Make_Socket_NoBlocking (int sock);
#ifdef INCLUDE_DEVICE_APIS
void ssdp_handle_device_request(
IN http_message_t* hmsg,
IN struct sockaddr_in* dest_addr );
IN struct sockaddr* dest_addr );
#else
static inline void ssdp_handle_device_request(
IN http_message_t* hmsg,
IN struct sockaddr_in* dest_addr ) {}
IN struct sockaddr* dest_addr ) {}
#endif
/************************************************************************
@ -217,7 +219,7 @@ static inline void ssdp_handle_device_request(
*
* Parameters:
* IN http_message_t* hmsg: SSDP message from the device
* IN struct sockaddr_in* dest_addr: Address of the device
* IN struct sockaddr* dest_addr: Address of the device
* IN xboolean timeout: timeout kept by the control point while sending
* search message
* IN void* cookie: Cookie stored by the control point application.
@ -234,7 +236,7 @@ static inline void ssdp_handle_device_request(
***************************************************************************/
void ssdp_handle_ctrlpt_msg(
IN http_message_t* hmsg,
IN struct sockaddr_in* dest_addr,
IN struct sockaddr* dest_addr,
IN xboolean timeout,
IN void* cookie );
@ -347,6 +349,7 @@ int SearchByTarget(IN int Mx, IN char *St, IN void *Cookie);
* IN char *Udn :
* IN char *Location: Location URL.
* IN int Duration : Service duration in sec.
* IN int AddressFamily: Device address family.
*
* Description:
* This function creates the device advertisement request based on
@ -360,7 +363,8 @@ int DeviceAdvertisement(
IN int RootDev,
IN char *Udn,
IN char *Location,
IN int Duration);
IN int Duration,
IN int AddressFamily);
/************************************************************************
@ -373,6 +377,7 @@ int DeviceAdvertisement(
* IN char *_Server:
* 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
@ -387,13 +392,14 @@ int DeviceShutdown(
IN char *Udn,
IN char *_Server,
IN char *Location,
IN int Duration);
IN int Duration,
IN int AddressFamily);
/************************************************************************
* Function : DeviceReply
*
* Parameters:
* IN struct sockaddr_in * DestAddr:destination IP address.
* 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
@ -408,17 +414,18 @@ int DeviceShutdown(
* UPNP_E_SUCCESS if successful else appropriate error
***************************************************************************/
int DeviceReply(
IN struct sockaddr_in * DestAddr,
IN struct sockaddr *DestAddr,
IN char *DevType,
IN int RootDev,
IN char *Udn,
IN char *Location, IN int Duration);
IN char *Location,
IN int Duration);
/************************************************************************
* Function : SendReply
*
* Parameters:
* IN struct sockaddr_in * DestAddr:destination IP address.
* 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
@ -435,7 +442,7 @@ int DeviceReply(
* UPNP_E_SUCCESS if successful else appropriate error
***************************************************************************/
int SendReply(
IN struct sockaddr_in * DestAddr,
IN struct sockaddr *DestAddr,
IN char *DevType,
IN int RootDev,
IN char *Udn,
@ -450,7 +457,8 @@ int SendReply(
* 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 Duration: Life time of this device.
* IN int AddressFamily: Device address family
*
* Description:
* This function creates the advertisement packet based
@ -463,13 +471,14 @@ int ServiceAdvertisement(
IN char *Udn,
IN char *ServType,
IN char *Location,
IN int Duration);
IN int Duration,
IN int AddressFamily);
/************************************************************************
* Function : ServiceReply
*
* Parameters:
* IN struct sockaddr_in *DestAddr:
* IN struct sockaddr *DestAddr:
* IN char *Udn: Device UDN
* IN char *ServType: Service Type.
* IN char *Server: Not used
@ -484,7 +493,7 @@ int ServiceAdvertisement(
* UPNP_E_SUCCESS if successful else appropriate error
***************************************************************************/
int ServiceReply(
IN struct sockaddr_in *DestAddr,
IN struct sockaddr *DestAddr,
IN char *ServType,
IN char *Udn,
IN char *Location,
@ -498,6 +507,7 @@ int ServiceReply(
* 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
@ -510,7 +520,8 @@ int ServiceShutdown(
IN char *Udn,
IN char *ServType,
IN char *Location,
IN int Duration);
IN int Duration,
IN int AddressFamily);
/************************************************************************
@ -537,7 +548,7 @@ void *advertiseAndReplyThread(IN void * data);
* 1 = Send Advertisement
* IN UpnpDevice_Handle Hnd: Device handle
* IN enum SsdpSearchType SearchType:Search type for sending replies
* IN struct sockaddr_in *DestAddr:Destination address
* IN struct sockaddr *DestAddr:Destination address
* IN char *DeviceType:Device type
* IN char *DeviceUDN:Device UDN
* IN char *ServiceType:Service type
@ -553,10 +564,9 @@ int AdvertiseAndReply(
IN int AdFlag,
IN UpnpDevice_Handle Hnd,
IN enum SsdpSearchType SearchType,
IN struct sockaddr_in *DestAddr,
IN struct sockaddr *DestAddr,
IN char *DeviceType,
IN char *DeviceUDN,
IN char *ServiceType, int Exp);
#endif

View File

@ -84,11 +84,12 @@ struct Handle_Info
//URL information
int MaxSubscriptions;
int MaxSubscriptionTimeOut;
int DeviceAf; // Address family: AF_INET or AF_INET6
#endif
// Client only
#ifdef INCLUDE_CLIENT_APIS
ClientSubscription *ClientSubList; //client subscription list
ClientSubscription *ClientSubList; // client subscription list
LinkedList SsdpSearchList; // active ssdp searches
#endif
int aliasInstalled; // 0 = not installed; otherwise installed
@ -116,13 +117,20 @@ Upnp_Handle_Type GetHandleInfo(int Hnd, struct Handle_Info **HndInfo);
Upnp_Handle_Type GetClientHandleInfo(int *client_handle_out,
struct Handle_Info **HndInfo);
Upnp_Handle_Type GetDeviceHandleInfo(int *device_handle_out,
Upnp_Handle_Type GetDeviceHandleInfo( const int AddressFamily,
int *device_handle_out,
struct Handle_Info **HndInfo);
extern char LOCAL_HOST[LINE_SIZE];
extern char gIF_NAME[LINE_SIZE];
extern char gIF_IPV4[22]; // INET_ADDRSTRLEN
extern char gIF_IPV6[65]; // INET6_ADDRSTRLEN
extern int gIF_INDEX;
extern unsigned short LOCAL_PORT;
extern unsigned short LOCAL_PORT_V4;
extern unsigned short LOCAL_PORT_V6;
extern Upnp_SID gUpnpSdkNLSuuid; // NLS uuid.
extern TimerThread gTimerThread;
extern ThreadPool gRecvThreadPool;
@ -170,6 +178,14 @@ typedef enum { WEB_SERVER_DISABLED, WEB_SERVER_ENABLED } WebServerState;
#define E_HTTP_SYNTAX -6
#ifdef WIN32
int WinsockInit();
#endif
int UpnpInitPreamble();
int UpnpInitMutexes();
int UpnpInitThreadPools();
int UpnpInitStartServers(unsigned short DestPort);
int UpnpGetIfInfo(const char *IfName);
void InitHandleList();
int GetFreeHandle();
int FreeHandle(int Handle);
@ -177,7 +193,7 @@ void UpnpThreadDistribution(struct UpnpNonblockParam * Param);
void AutoAdvertise(void *input);
int getlocalhostname(char *out);
int getlocalhostname(char *out, const int out_len);
extern WebServerState bWebServerState;

View File

@ -95,7 +95,7 @@ typedef struct TOKEN {
* text is a token pointing to the full string representation */
typedef struct HOSTPORT {
token text; //full host port
struct sockaddr_in IPv4address; //Network Byte Order
struct sockaddr_storage IPaddress; //Network Byte Order
} hostport_type;
/* Represents a URI used in parse_uri and elsewhere */

View File

@ -50,7 +50,7 @@ extern "C" {
*
* Parameters :
* INOUT IXML_Document *doc ; IXML Description document
* IN const struct sockaddr_in* serverAddr ; socket address object
* IN const struct sockaddr *serverAddr; socket address object
* providing the IP address and port information
* IN const char* alias ; string containing the alias
* IN time_t last_modified ; time when the XML document was
@ -70,10 +70,10 @@ extern "C" {
* Note :
****************************************************************************/
int configure_urlbase( INOUT IXML_Document *doc,
IN const struct sockaddr_in* serverAddr,
IN const struct sockaddr* serverAddr,
IN const char* alias,
IN time_t last_modified,
OUT char docURL[LINE_SIZE] );
OUT char docURL[LINE_SIZE]);
#ifdef __cplusplus
@ -81,4 +81,3 @@ int configure_urlbase( INOUT IXML_Document *doc,
#endif
#endif /* URLCONFIG_H */

View File

@ -592,6 +592,7 @@ static int
get_device_info( IN http_message_t *request,
IN int isQuery,
IN IXML_Document *actionDoc,
IN int AddressFamily,
OUT UpnpString *device_udn,
OUT UpnpString *service_id,
OUT Upnp_FunPtr *callback,
@ -612,7 +613,8 @@ get_device_info( IN http_message_t *request,
HandleLock();
if( GetDeviceHandleInfo( &device_hnd, &device_info ) != HND_DEVICE ) {
if( GetDeviceHandleInfo( AddressFamily,
&device_hnd, &device_info ) != HND_DEVICE ) {
goto error_handler;
}
@ -843,10 +845,10 @@ error_handler:
*
* Note :
****************************************************************************/
static UPNP_INLINE void
handle_query_variable( IN SOCKINFO * info,
IN http_message_t * request,
IN IXML_Document * xml_doc )
static UPNP_INLINE void handle_query_variable(
IN SOCKINFO *info,
IN http_message_t *request,
IN IXML_Document *xml_doc )
{
UpnpStateVarRequest *variable = UpnpStateVarRequest_new();
Upnp_FunPtr soap_event_callback;
@ -864,6 +866,7 @@ handle_query_variable( IN SOCKINFO * info,
// get info for event
err_code = get_device_info(
request, 1, xml_doc,
info->foreign_sockaddr.ss_family,
(UpnpString *)UpnpStateVarRequest_get_DevUDN(variable),
(UpnpString *)UpnpStateVarRequest_get_ServiceID(variable),
&soap_event_callback,
@ -876,7 +879,7 @@ handle_query_variable( IN SOCKINFO * info,
UpnpStateVarRequest_set_ErrCode(variable, UPNP_E_SUCCESS);
UpnpStateVarRequest_strcpy_StateVarName(variable, var_name);
UpnpStateVarRequest_set_CtrlPtIPAddr(variable, &info->foreign_ip_addr);
UpnpStateVarRequest_set_CtrlPtIPAddr(variable, &info->foreign_sockaddr);
// send event
soap_event_callback( UPNP_CONTROL_GET_VAR_REQUEST, variable, cookie );
@ -960,6 +963,7 @@ handle_invoke_action( IN SOCKINFO * info,
request,
0,
xml_doc,
info->foreign_sockaddr.ss_family,
devUDN,
serviceID,
&soap_event_callback,
@ -975,7 +979,7 @@ handle_invoke_action( IN SOCKINFO * info,
UpnpActionRequest_set_DevUDN(action, devUDN);
UpnpActionRequest_set_ServiceID(action, serviceID);
UpnpActionRequest_set_ActionRequest(action, actionRequestDoc);
UpnpActionRequest_set_CtrlPtIPAddr(action, &info->foreign_ip_addr);
UpnpActionRequest_set_CtrlPtIPAddr(action, &info->foreign_sockaddr);
UpnpPrintf(UPNP_INFO, SOAP, __FILE__, __LINE__, "Calling Callback\n");

View File

@ -80,7 +80,7 @@ void send_search_result(IN void *data)
* Parameters:
* IN http_message_t *hmsg:
* SSDP message from the device
* IN struct sockaddr_in *dest_addr:
* IN struct sockaddr *dest_addr:
* Address of the device
* IN xboolean timeout:
* timeout kept by the control point while
@ -100,9 +100,9 @@ void send_search_result(IN void *data)
***************************************************************************/
void ssdp_handle_ctrlpt_msg(
IN http_message_t *hmsg,
IN struct sockaddr_in *dest_addr,
IN struct sockaddr *dest_addr,
IN xboolean timeout, // only in search reply
IN void *cookie ) // only in search reply
IN void *cookie) // only in search reply
{
int handle;
struct Handle_Info *ctrlpt_info = NULL;
@ -336,50 +336,6 @@ end_ssdp_handle_ctrlpt_msg:
UpnpDiscovery_delete(param);
}
/************************************************************************
* Function : process_reply
*
* Parameters:
* IN char* request_buf: the response came from the device
* IN int buf_len: The length of the response buffer
* IN struct sockaddr_in* dest_addr: The address of the device
* IN void *cookie : cookie passed by the control point application
* at the time of sending search message
*
* Description:
* This function processes reply recevied from a search
*
* Returns: void
*
***************************************************************************/
#ifndef WIN32
#warning There are currently no uses of the function 'process_reply()' in the code.
#warning 'process_reply()' is a candidate for removal.
#else
#pragma message("There are currently no uses of the function 'process_reply()' in the code.")
#pragma message("'process_reply()' is a candidate for removal.")
#endif
static UPNP_INLINE void
process_reply( IN char *request_buf,
IN int buf_len,
IN struct sockaddr_in *dest_addr,
IN void *cookie )
{
http_parser_t parser;
parser_response_init( &parser, HTTPMETHOD_MSEARCH );
// parse
if( parser_append( &parser, request_buf, buf_len ) != PARSE_SUCCESS ) {
httpmsg_destroy( &parser.msg );
return;
}
// handle reply
ssdp_handle_ctrlpt_msg( &parser.msg, dest_addr, FALSE, cookie );
// done
httpmsg_destroy( &parser.msg );
}
/************************************************************************
* Function : CreateClientRequestPacket
@ -389,6 +345,7 @@ process_reply( IN char *request_buf,
* 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
@ -400,13 +357,18 @@ process_reply( IN char *request_buf,
static void
CreateClientRequestPacket( IN char *RqstBuf,
IN int Mx,
IN char *SearchTarget )
IN char *SearchTarget,
IN int AddressFamily )
{
char TempBuf[COMMAND_LEN];
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" );
@ -495,7 +457,17 @@ searchExpired( void *arg )
* This cokie will be returned to application in the callback.
*
* Description:
* This function 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:
* - "ssdp:all" : Search for all devices and services.
* - "ssdp:rootdevice" : Search for root devices only.
* - "uuid:<device-uuid>" : Search for a particular device.
* - "urn:schemas-upnp-org:device:<deviceType:v>"
* - "urn:schemas-upnp-org:service:<serviceType:v>"
* - "urn:<domain-name>:device:<deviceType:v>"
* - "urn:<domain-name>:service:<serviceType:v>"
*
* Returns: int
* 1 if successful else appropriate error
@ -506,18 +478,23 @@ SearchByTarget( IN int Mx,
IN void *Cookie )
{
char errorBuffer[ERROR_BUFFER_LEN];
int socklen = sizeof( struct sockaddr_in );
int socklen = sizeof( struct sockaddr_storage );
int *id = NULL;
int ret = 0;
char *ReqBuf;
struct sockaddr_in destAddr;
char ReqBufv4[BUFSIZE];
char ReqBufv6[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;
fd_set wrSet;
SsdpSearchArg *newArg = NULL;
int timeTillRead = 0;
int handle;
struct Handle_Info *ctrlpt_info = NULL;
enum SsdpSearchType requestType;
unsigned long addr = inet_addr( LOCAL_HOST );
unsigned long addrv4 = inet_addr( gIF_IPV4 );
int max_fd = 0;
//ThreadData *ThData;
ThreadPoolJob job;
@ -527,12 +504,7 @@ SearchByTarget( IN int Mx,
return UPNP_E_INVALID_PARAM;
}
ReqBuf = (char *)malloc( BUFSIZE );
if( ReqBuf == NULL ) {
return UPNP_E_OUTOF_MEMORY;
}
UpnpPrintf(UPNP_INFO, SSDP, __FILE__, __LINE__, ">>> SSDP SEND >>>\n");
UpnpPrintf(UPNP_INFO, SSDP, __FILE__, __LINE__, "Inside SearchByTarget\n");
timeTillRead = Mx;
@ -542,21 +514,24 @@ SearchByTarget( IN int Mx,
timeTillRead = MAX_SEARCH_TIME;
}
CreateClientRequestPacket( ReqBuf, timeTillRead, St );
memset( ( char * )&destAddr, 0, sizeof( struct sockaddr_in ) );
CreateClientRequestPacket( ReqBufv4, timeTillRead, St, AF_INET );
CreateClientRequestPacket( ReqBufv6, timeTillRead, St, AF_INET6 );
destAddr.sin_family = AF_INET;
destAddr.sin_addr.s_addr = inet_addr( SSDP_IP );
destAddr.sin_port = htons( SSDP_PORT );
memset( &__ss_v4, 0, sizeof( __ss_v4 ) );
destAddr4->sin_family = AF_INET;
inet_pton( AF_INET, SSDP_IP, &destAddr4->sin_addr );
destAddr4->sin_port = htons( SSDP_PORT );
FD_ZERO( &wrSet );
FD_SET( gSsdpReqSocket, &wrSet );
memset( &__ss_v6, 0, sizeof( __ss_v6 ) );
destAddr6->sin6_family = AF_INET6;
inet_pton( AF_INET6, SSDP_IPV6_LINKLOCAL, &destAddr6->sin6_addr );
destAddr6->sin6_port = htons( SSDP_PORT );
destAddr6->sin6_scope_id = gIF_INDEX;
// add search criteria to list
HandleLock();
if( GetClientHandleInfo( &handle, &ctrlpt_info ) != HND_CLIENT ) {
HandleUnlock();
free( ReqBuf );
return UPNP_E_INTERNAL_ERROR;
}
@ -578,34 +553,56 @@ SearchByTarget( IN int Mx,
ListAddTail( &ctrlpt_info->SsdpSearchList, newArg );
HandleUnlock();
ret = setsockopt( gSsdpReqSocket, IPPROTO_IP, IP_MULTICAST_IF,
(char *)&addr, sizeof (addr) );
FD_ZERO( &wrSet );
if( gSsdpReqSocket4 != INVALID_SOCKET ) {
setsockopt( gSsdpReqSocket4, IPPROTO_IP, IP_MULTICAST_IF,
(char *)&addrv4, sizeof (addrv4) );
FD_SET( gSsdpReqSocket4, &wrSet );
max_fd = max(max_fd, gSsdpReqSocket4);
}
if( gSsdpReqSocket6 != INVALID_SOCKET ) {
setsockopt( gSsdpReqSocket6, IPPROTO_IPV6, IPV6_MULTICAST_IF,
(char *)&gIF_INDEX, sizeof(gIF_INDEX) );
FD_SET( gSsdpReqSocket6, &wrSet );
max_fd = max(max_fd, gSsdpReqSocket6);
}
ret = select( gSsdpReqSocket + 1, NULL, &wrSet, NULL, NULL );
ret = select( max_fd + 1, NULL, &wrSet, NULL, NULL );
if( ret == -1 ) {
strerror_r(errno, errorBuffer, ERROR_BUFFER_LEN);
UpnpPrintf( UPNP_INFO, SSDP, __FILE__, __LINE__,
"SSDP_LIB: Error in select(): %s\n",
errorBuffer );
shutdown( gSsdpReqSocket, SD_BOTH );
UpnpCloseSocket( gSsdpReqSocket );
free( ReqBuf );
shutdown( gSsdpReqSocket4, SD_BOTH );
UpnpCloseSocket( gSsdpReqSocket4 );
shutdown( gSsdpReqSocket6, SD_BOTH );
UpnpCloseSocket( gSsdpReqSocket6 );
return UPNP_E_INTERNAL_ERROR;
} else if( FD_ISSET( gSsdpReqSocket, &wrSet ) ) {
}
if( gSsdpReqSocket6 != INVALID_SOCKET &&
FD_ISSET( gSsdpReqSocket6, &wrSet ) ) {
int NumCopy = 0;
while( NumCopy < NUM_SSDP_COPY ) {
sendto( gSsdpReqSocket, ReqBuf, strlen( ReqBuf ), 0,
(struct sockaddr *)&destAddr, socklen );
sendto( gSsdpReqSocket6, ReqBufv6, strlen( ReqBufv6 ), 0,
(struct sockaddr *)&__ss_v6, socklen );
NumCopy++;
imillisleep( SSDP_PAUSE );
}
}
if( gSsdpReqSocket4 != INVALID_SOCKET &&
FD_ISSET( gSsdpReqSocket4, &wrSet ) ) {
int NumCopy = 0;
while( NumCopy < NUM_SSDP_COPY ) {
sendto( gSsdpReqSocket4, ReqBufv4, strlen( ReqBufv4 ), 0,
(struct sockaddr *)&__ss_v4, socklen );
NumCopy++;
imillisleep( SSDP_PAUSE );
}
}
free( ReqBuf );
return 1;
}
#endif // EXCLUDE_SSDP
#endif // INCLUDE_CLIENT_APIS

View File

@ -75,7 +75,7 @@ advertiseAndReplyThread( IN void *data )
AdvertiseAndReply( 0, arg->handle,
arg->event.RequestType,
&arg->dest_addr,
(struct sockaddr*)&arg->dest_addr,
arg->event.DeviceType,
arg->event.UDN,
arg->event.ServiceType, arg->MaxAge );
@ -88,8 +88,8 @@ advertiseAndReplyThread( IN void *data )
* Function : ssdp_handle_device_request
*
* Parameters:
* IN http_message_t* hmsg: SSDP search request from the control point
* IN struct sockaddr_in* dest_addr: The address info of control point
* 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
@ -101,8 +101,8 @@ advertiseAndReplyThread( IN void *data )
***************************************************************************/
#ifdef INCLUDE_DEVICE_APIS
void
ssdp_handle_device_request( IN http_message_t * hmsg,
IN struct sockaddr_in *dest_addr )
ssdp_handle_device_request( IN http_message_t *hmsg,
IN struct sockaddr *dest_addr )
{
#define MX_FUDGE_FACTOR 10
@ -142,7 +142,8 @@ ssdp_handle_device_request( IN http_message_t * hmsg,
HandleLock();
// device info
if( GetDeviceHandleInfo( &handle, &dev_info ) != HND_DEVICE ) {
if( GetDeviceHandleInfo( dest_addr->sa_family,
&handle, &dev_info ) != HND_DEVICE ) {
HandleUnlock();
return; // no info found
}
@ -170,7 +171,7 @@ ssdp_handle_device_request( IN http_message_t * hmsg,
return;
}
threadArg->handle = handle;
threadArg->dest_addr = ( *dest_addr );
memcpy( &threadArg->dest_addr, dest_addr, sizeof(threadArg->dest_addr) );
threadArg->event = event;
threadArg->MaxAge = maxAge;
@ -201,7 +202,7 @@ ssdp_handle_device_request( IN http_message_t * hmsg,
* Function : NewRequestHandler
*
* Parameters:
* IN struct sockaddr_in * DestAddr: Ip address, to send the reply.
* 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.
*
@ -213,19 +214,21 @@ ssdp_handle_device_request( IN http_message_t * hmsg,
* 1 if successful else appropriate error
***************************************************************************/
static int
NewRequestHandler( IN struct sockaddr_in *DestAddr,
NewRequestHandler( IN struct sockaddr *DestAddr,
IN int NumPacket,
IN char **RqPacket )
{
char errorBuffer[ERROR_BUFFER_LEN];
int ReplySock;
int socklen = sizeof( struct sockaddr_in );
SOCKET ReplySock;
int socklen = sizeof( struct sockaddr_storage );
int NumCopy;
int Index;
unsigned long replyAddr = inet_addr( LOCAL_HOST );
unsigned long replyAddr = inet_addr( gIF_IPV4 );
int ttl = 4; // a/c to UPNP Spec
int hops = 1;
char buf_ntop[64];
ReplySock = socket( AF_INET, SOCK_DGRAM, 0 );
ReplySock = socket( DestAddr->sa_family, SOCK_DGRAM, 0 );
if ( ReplySock == -1 ) {
strerror_r(errno, errorBuffer, ERROR_BUFFER_LEN);
UpnpPrintf( UPNP_INFO, SSDP, __FILE__, __LINE__,
@ -235,10 +238,24 @@ NewRequestHandler( IN struct sockaddr_in *DestAddr,
return UPNP_E_OUTOF_SOCKET;
}
if( DestAddr->sa_family == AF_INET ) {
inet_ntop(AF_INET, &((struct sockaddr_in*)DestAddr)->sin_addr,
buf_ntop, sizeof(buf_ntop));
setsockopt( ReplySock, IPPROTO_IP, IP_MULTICAST_IF,
(char *)&replyAddr, sizeof (replyAddr) );
setsockopt( ReplySock, IPPROTO_IP, IP_MULTICAST_TTL,
(char *)&ttl, sizeof (int) );
} else if( DestAddr->sa_family == AF_INET6 ) {
inet_ntop(AF_INET6, &((struct sockaddr_in6*)DestAddr)->sin6_addr,
buf_ntop, sizeof(buf_ntop));
setsockopt( ReplySock, IPPROTO_IPV6, IPV6_MULTICAST_IF,
(char *)&gIF_INDEX, sizeof(gIF_INDEX) );
setsockopt( ReplySock, IPPROTO_IPV6, IPV6_MULTICAST_HOPS,
(char *)&hops, sizeof(hops) );
} else {
UpnpPrintf( UPNP_CRITICAL, SSDP, __FILE__, __LINE__,
"Invalid destination address specified." );
}
for( Index = 0; Index < NumPacket; Index++ ) {
int rc;
@ -256,11 +273,11 @@ NewRequestHandler( IN struct sockaddr_in *DestAddr,
NumCopy = 0;
while( NumCopy < NUM_COPY ) {
UpnpPrintf( UPNP_INFO, SSDP, __FILE__, __LINE__,
">>> SSDP SEND >>>\n%s\n",
*( RqPacket + Index ) );
">>> SSDP SEND to %s >>>\n%s\n",
buf_ntop, *( RqPacket + Index ) );
rc = sendto( ReplySock, *( RqPacket + Index ),
strlen( *( RqPacket + Index ) ),
0, ( struct sockaddr * )DestAddr, socklen );
0, DestAddr, socklen );
imillisleep( SSDP_PAUSE );
++NumCopy;
}
@ -283,6 +300,7 @@ NewRequestHandler( IN struct sockaddr_in *DestAddr,
* 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
@ -298,7 +316,8 @@ CreateServicePacket( IN int msg_type,
IN char *usn,
IN char *location,
IN int duration,
OUT char **packet )
OUT char **packet,
IN int AddressFamily)
{
int ret_code;
char *nts;
@ -315,11 +334,13 @@ CreateServicePacket( IN int msg_type,
if( msg_type == MSGTYPE_REPLY ) {
ret_code = http_MakeMessage(
&buf, 1, 1,
"R" "sdc" "D" "sc" "ssc" "S" "Xc" "ssc" "sscc",
"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);
@ -340,11 +361,15 @@ CreateServicePacket( IN int msg_type,
ret_code = http_MakeMessage(
&buf, 1, 1,
"Q" "sssdc" "sdc" "ssc" "ssc" "ssc" "S" "Xc" "sscc",
"Q" "sssdc" "sdc" "ssc" "ssc" "ssc" "ssc" "ssc" "S" "Xc" "sscc",
HTTPMETHOD_NOTIFY, "*", (size_t)1,
"HOST: ", SSDP_IP, ":", SSDP_PORT,
"HOST: ",
(AddressFamily==AF_INET) ? SSDP_IP : "[" SSDP_IPV6_LINKLOCAL "]",
":", 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,
@ -387,9 +412,12 @@ DeviceAdvertisement( IN char *DevType,
int RootDev,
char *Udn,
IN char *Location,
IN int Duration )
IN int Duration,
IN int AddressFamily)
{
struct sockaddr_in DestAddr;
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];
@ -397,11 +425,22 @@ DeviceAdvertisement( IN char *DevType,
int ret_code;
UpnpPrintf( UPNP_INFO, SSDP, __FILE__, __LINE__,
"In function SendDeviceAdvertisemenrt\n" );
"In function DeviceAdvertisement\n" );
DestAddr.sin_family = AF_INET;
DestAddr.sin_addr.s_addr = inet_addr( SSDP_IP );
DestAddr.sin_port = htons( SSDP_PORT );
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, 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;
@ -412,17 +451,17 @@ DeviceAdvertisement( IN char *DevType,
if( RootDev ) {
sprintf( Mil_Usn, "%s::upnp:rootdevice", Udn );
CreateServicePacket( MSGTYPE_ADVERTISEMENT, "upnp:rootdevice",
Mil_Usn, Location, Duration, &msgs[0] );
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] );
Location, Duration, &msgs[1], AddressFamily );
sprintf( Mil_Usn, "%s::%s", Udn, DevType );
CreateServicePacket( MSGTYPE_ADVERTISEMENT, DevType, Mil_Usn,
Location, Duration, &msgs[2] );
Location, Duration, &msgs[2], AddressFamily );
// check error
if( ( RootDev && msgs[0] == NULL ) ||
@ -435,11 +474,11 @@ DeviceAdvertisement( IN char *DevType,
// send packets
if( RootDev ) {
// send 3 msg types
ret_code = NewRequestHandler( &DestAddr, 3, &msgs[0] );
ret_code = NewRequestHandler( (struct sockaddr*)&__ss, 3, &msgs[0] );
} else // sub-device
{
// send 2 msg types
ret_code = NewRequestHandler( &DestAddr, 2, &msgs[1] );
ret_code = NewRequestHandler( (struct sockaddr*)&__ss, 2, &msgs[1] );
}
// free msgs
@ -454,7 +493,7 @@ DeviceAdvertisement( IN char *DevType,
* Function : SendReply
*
* Parameters:
* IN struct sockaddr_in * DestAddr:destination IP address.
* 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
@ -470,7 +509,7 @@ DeviceAdvertisement( IN char *DevType,
* UPNP_E_SUCCESS if successful else appropriate error
***************************************************************************/
int
SendReply( IN struct sockaddr_in *DestAddr,
SendReply( IN struct sockaddr *DestAddr,
IN char *DevType,
IN int RootDev,
IN char *Udn,
@ -493,7 +532,7 @@ SendReply( IN struct sockaddr_in *DestAddr,
sprintf( Mil_Usn, "%s::upnp:rootdevice", Udn );
CreateServicePacket( MSGTYPE_REPLY, "upnp:rootdevice",
Mil_Usn, Location, Duration, &msgs[0] );
Mil_Usn, Location, Duration, &msgs[0], DestAddr->sa_family );
} else {
// two msgs for embedded devices
num_msgs = 1;
@ -501,11 +540,11 @@ SendReply( IN struct sockaddr_in *DestAddr,
//NK: FIX for extra response when someone searches by udn
if( !ByType ) {
CreateServicePacket( MSGTYPE_REPLY, Udn, Udn, Location,
Duration, &msgs[0] );
Duration, &msgs[0], DestAddr->sa_family );
} else {
sprintf( Mil_Usn, "%s::%s", Udn, DevType );
CreateServicePacket( MSGTYPE_REPLY, DevType, Mil_Usn,
Location, Duration, &msgs[0] );
Location, Duration, &msgs[0], DestAddr->sa_family );
}
}
@ -531,7 +570,7 @@ SendReply( IN struct sockaddr_in *DestAddr,
* Function : DeviceReply
*
* Parameters:
* IN struct sockaddr_in * DestAddr:destination IP address.
* 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
@ -545,12 +584,12 @@ SendReply( IN struct sockaddr_in *DestAddr,
* UPNP_E_SUCCESS if successful else appropriate error
***************************************************************************/
int
DeviceReply( IN struct sockaddr_in *DestAddr,
DeviceReply( IN struct sockaddr *DestAddr,
IN char *DevType,
IN int RootDev,
IN char *Udn,
IN char *Location,
IN int Duration )
IN int Duration)
{
char *szReq[3],
Mil_Nt[LINE_SIZE],
@ -568,18 +607,18 @@ DeviceReply( IN struct sockaddr_in *DestAddr,
strcpy( Mil_Nt, "upnp:rootdevice" );
sprintf( Mil_Usn, "%s::upnp:rootdevice", Udn );
CreateServicePacket( MSGTYPE_REPLY, Mil_Nt, Mil_Usn,
Location, Duration, &szReq[0] );
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] );
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] );
Location, Duration, &szReq[2], DestAddr->sa_family );
// check error
@ -613,6 +652,7 @@ DeviceReply( IN struct sockaddr_in *DestAddr,
* 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.
@ -624,28 +664,42 @@ int
ServiceAdvertisement( IN char *Udn,
IN char *ServType,
IN char *Location,
IN int Duration )
IN int Duration,
IN int AddressFamily)
{
char Mil_Usn[LINE_SIZE];
char *szReq[1];
struct sockaddr_in DestAddr;
int RetVal;
struct sockaddr_storage __ss;
struct sockaddr_in* DestAddr4 = (struct sockaddr_in*)&__ss;
struct sockaddr_in6* DestAddr6 = (struct sockaddr_in6*)&__ss;
DestAddr.sin_family = AF_INET;
DestAddr.sin_addr.s_addr = inet_addr( SSDP_IP );
DestAddr.sin_port = htons( SSDP_PORT );
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, 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] );
Location, Duration, &szReq[0], AddressFamily );
if( szReq[0] == NULL ) {
return UPNP_E_OUTOF_MEMORY;
}
RetVal = NewRequestHandler( &DestAddr, 1, szReq );
RetVal = NewRequestHandler( (struct sockaddr*)&__ss, 1, szReq );
free( szReq[0] );
return RetVal;
@ -655,7 +709,7 @@ ServiceAdvertisement( IN char *Udn,
* Function : ServiceReply
*
* Parameters:
* IN struct sockaddr_in *DestAddr:
* IN struct sockaddr *DestAddr:
* IN char * Udn: Device UDN
* IN char *ServType: Service Type.
* IN char * Location: Location of Device description document.
@ -668,7 +722,7 @@ ServiceAdvertisement( IN char *Udn,
* UPNP_E_SUCCESS if successful else appropriate error
***************************************************************************/
int
ServiceReply( IN struct sockaddr_in *DestAddr,
ServiceReply( IN struct sockaddr *DestAddr,
IN char *ServType,
IN char *Udn,
IN char *Location,
@ -683,7 +737,7 @@ ServiceReply( IN struct sockaddr_in *DestAddr,
sprintf( Mil_Usn, "%s::%s", Udn, ServType );
CreateServicePacket( MSGTYPE_REPLY, ServType, Mil_Usn,
Location, Duration, &szReq[0] );
Location, Duration, &szReq[0], DestAddr->sa_family );
if( szReq[0] == NULL ) {
return UPNP_E_OUTOF_MEMORY;
}
@ -702,6 +756,7 @@ ServiceReply( IN struct sockaddr_in *DestAddr,
* 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.
@ -713,27 +768,41 @@ int
ServiceShutdown( IN char *Udn,
IN char *ServType,
IN char *Location,
IN int Duration )
IN int Duration,
IN int AddressFamily)
{
char Mil_Usn[LINE_SIZE];
char *szReq[1];
struct sockaddr_in DestAddr;
struct sockaddr_storage __ss;
struct sockaddr_in* DestAddr4 = (struct sockaddr_in*)&__ss;
struct sockaddr_in6* DestAddr6 = (struct sockaddr_in6*)&__ss;
int RetVal;
DestAddr.sin_family = AF_INET;
DestAddr.sin_addr.s_addr = inet_addr( SSDP_IP );
DestAddr.sin_port = htons( SSDP_PORT );
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, 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] );
Location, Duration, &szReq[0], AddressFamily );
if( szReq[0] == NULL ) {
return UPNP_E_OUTOF_MEMORY;
}
RetVal = NewRequestHandler( &DestAddr, 1, szReq );
RetVal = NewRequestHandler( (struct sockaddr*)&__ss, 1, szReq );
free( szReq[0] );
return RetVal;
@ -748,6 +817,7 @@ ServiceShutdown( IN char *Udn,
* 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
@ -762,9 +832,12 @@ DeviceShutdown( IN char *DevType,
IN char *Udn,
IN char *_Server,
IN char *Location,
IN int Duration )
IN int Duration,
IN int AddressFamily)
{
struct sockaddr_in DestAddr;
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;
@ -773,26 +846,37 @@ DeviceShutdown( IN char *DevType,
msgs[1] = NULL;
msgs[2] = NULL;
DestAddr.sin_family = AF_INET;
DestAddr.sin_addr.s_addr = inet_addr( SSDP_IP );
DestAddr.sin_port = htons( SSDP_PORT );
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, 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] );
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] );
Location, Duration, &msgs[1], AddressFamily );
sprintf( Mil_Usn, "%s::%s", Udn, DevType );
CreateServicePacket( MSGTYPE_SHUTDOWN, DevType, Mil_Usn,
Location, Duration, &msgs[2] );
Location, Duration, &msgs[2], AddressFamily );
// check error
if( ( RootDev && msgs[0] == NULL ) ||
@ -805,11 +889,11 @@ DeviceShutdown( IN char *DevType,
// send packets
if( RootDev ) {
// send 3 msg types
ret_code = NewRequestHandler( &DestAddr, 3, &msgs[0] );
ret_code = NewRequestHandler( (struct sockaddr*)&__ss, 3, &msgs[0] );
} else // sub-device
{
// send 2 msg types
ret_code = NewRequestHandler( &DestAddr, 2, &msgs[1] );
ret_code = NewRequestHandler( (struct sockaddr*)&__ss, 2, &msgs[1] );
}
// free msgs

View File

@ -42,27 +42,25 @@
#include "httpparser.h"
#include "httpreadwrite.h"
#ifdef WIN32
#include <string.h>
#include <winsock2.h>
#include <ws2tcpip.h>
#include "unixutil.h"
#endif
#define MAX_TIME_TOREAD 45
CLIENTONLY( SOCKET gSsdpReqSocket = 0; )
CLIENTONLY( SOCKET gSsdpReqSocket4 = INVALID_SOCKET; )
CLIENTONLY( SOCKET gSsdpReqSocket6 = INVALID_SOCKET; )
void RequestHandler();
int create_ssdp_sock_v4( SOCKET* ssdpSock );
int create_ssdp_sock_v6( SOCKET* ssdpSock );
#if INCLUDE_CLIENT_APIS
int create_ssdp_sock_reqv4( SOCKET* ssdpReqSock );
int create_ssdp_sock_reqv6( SOCKET* ssdpReqSock );
#endif
Event ErrotEvt;
enum Listener { Idle, Stopping, Running };
unsigned short ssdpStopPort;
struct SSDPSockArray {
// socket for incoming advertisments and search requests
int ssdpSock;
SOCKET ssdpSock;
// socket for sending search requests and receiving search replies
CLIENTONLY( int ssdpReqSock; )
};
@ -80,7 +78,7 @@ struct SSDPSockArray {
* 1 = Send Advertisement
* IN UpnpDevice_Handle Hnd: Device handle
* IN enum SsdpSearchType SearchType:Search type for sending replies
* IN struct sockaddr_in *DestAddr:Destination address
* IN struct sockaddr *DestAddr:Destination address
* IN char *DeviceType:Device type
* IN char *DeviceUDN:Device UDN
* IN char *ServiceType:Service type
@ -95,7 +93,7 @@ struct SSDPSockArray {
int AdvertiseAndReply( IN int AdFlag,
IN UpnpDevice_Handle Hnd,
IN enum SsdpSearchType SearchType,
IN struct sockaddr_in *DestAddr,
IN struct sockaddr *DestAddr,
IN char *DeviceType,
IN char *DeviceUDN,
IN char *ServiceType,
@ -234,10 +232,10 @@ int AdvertiseAndReply( IN int AdFlag,
// send the device advertisement
if( AdFlag == 1 ) {
DeviceAdvertisement( devType, i == 0,
UDNstr, SInfo->DescURL, Exp );
UDNstr, SInfo->DescURL, Exp, SInfo->DeviceAf );
} else { // AdFlag == -1
DeviceShutdown( devType, i == 0, UDNstr,
SERVER, SInfo->DescURL, Exp );
SERVER, SInfo->DescURL, Exp, SInfo->DeviceAf );
}
} else {
switch ( SearchType ) {
@ -353,10 +351,10 @@ int AdvertiseAndReply( IN int AdFlag,
if( AdFlag ) {
if( AdFlag == 1 ) {
ServiceAdvertisement( UDNstr, servType,
SInfo->DescURL, Exp );
SInfo->DescURL, Exp, SInfo->DeviceAf );
} else { // AdFlag == -1
ServiceShutdown( UDNstr, servType,
SInfo->DescURL, Exp );
SInfo->DescURL, Exp, SInfo->DeviceAf );
}
} else {
switch ( SearchType ) {
@ -403,7 +401,7 @@ int AdvertiseAndReply( IN int AdFlag,
* Function : Make_Socket_NoBlocking
*
* Parameters:
* IN int sock: socket
* IN SOCKET sock: socket
*
* Description:
* This function makes socket non-blocking.
@ -412,7 +410,7 @@ int AdvertiseAndReply( IN int AdFlag,
* 0 if successful else -1
***************************************************************************/
int
Make_Socket_NoBlocking( int sock )
Make_Socket_NoBlocking( SOCKET sock )
{
#ifdef WIN32
u_long val=1;
@ -655,8 +653,11 @@ valid_ssdp_msg( IN http_message_t * hmsg )
}
// check HOST header
if( ( httpmsg_find_hdr( hmsg, HDR_HOST, &hdr_value ) == NULL ) ||
( memptr_cmp( &hdr_value, "239.255.255.250:1900" ) != 0 )
( ( memptr_cmp( &hdr_value, "239.255.255.250:1900" ) != 0 ) &&
( memptr_cmp( &hdr_value, "[FF02::C]:1900" ) != 0 ) )
) {
UpnpPrintf( UPNP_INFO, SSDP, __FILE__, __LINE__,
"Invalid HOST header from SSDP message\n" );
return FALSE;
}
}
@ -705,7 +706,7 @@ start_event_handler( void *Data )
goto error_handler;
}
// check msg
if( !valid_ssdp_msg( &parser->msg ) ) {
if( valid_ssdp_msg( &parser->msg ) != TRUE ) {
goto error_handler;
}
return 0; //////// done; thread will free 'data'
@ -740,9 +741,10 @@ ssdp_event_handler_thread( void *the_data )
// send msg to device or ctrlpt
if( ( hmsg->method == HTTPMETHOD_NOTIFY ) ||
( hmsg->request_method == HTTPMETHOD_MSEARCH ) ) {
CLIENTONLY( ssdp_handle_ctrlpt_msg( hmsg, &data->dest_addr, FALSE, NULL );)
CLIENTONLY( ssdp_handle_ctrlpt_msg( hmsg,
(struct sockaddr*)&data->dest_addr, FALSE, NULL );)
} else {
ssdp_handle_device_request( hmsg, &data->dest_addr );
ssdp_handle_device_request( hmsg, (struct sockaddr*)&data->dest_addr );
}
// free data
@ -766,11 +768,12 @@ readFromSSDPSocket( SOCKET socket )
{
char *requestBuf = NULL;
char staticBuf[BUFSIZE];
struct sockaddr_in clientAddr;
struct sockaddr_storage __ss;
ThreadPoolJob job;
ssdp_thread_data *data = NULL;
socklen_t socklen = 0;
socklen_t socklen = sizeof( __ss );
int byteReceived = 0;
char ntop_buf[64];
requestBuf = staticBuf;
@ -778,8 +781,6 @@ readFromSSDPSocket( SOCKET socket )
//can't be allocated, still drain the
//socket using a static buffer
socklen = sizeof( struct sockaddr_in );
data = ( ssdp_thread_data * )
malloc( sizeof( ssdp_thread_data ) );
@ -787,7 +788,7 @@ readFromSSDPSocket( SOCKET socket )
//initialize parser
#ifdef INCLUDE_CLIENT_APIS
if( socket == gSsdpReqSocket ) {
if( socket == gSsdpReqSocket4 || socket == gSsdpReqSocket6 ) {
parser_response_init( &data->parser, HTTPMETHOD_MSEARCH );
} else {
parser_request_init( &data->parser );
@ -809,10 +810,18 @@ readFromSSDPSocket( SOCKET socket )
}
byteReceived = recvfrom( socket, requestBuf,
BUFSIZE - 1, 0,
( struct sockaddr * )&clientAddr, &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) );
else if( __ss.ss_family == AF_INET6 )
inet_ntop( AF_INET6, &((struct sockaddr_in6*)&__ss)->sin6_addr, ntop_buf, sizeof(ntop_buf) );
else
strncpy( ntop_buf, "<Invalid address family>", sizeof(ntop_buf) );
UpnpPrintf( UPNP_INFO, SSDP,
__FILE__, __LINE__,
"Start of received response ----------------------------------------------------\n"
@ -820,7 +829,7 @@ readFromSSDPSocket( SOCKET socket )
"End of received response ------------------------------------------------------\n"
"From host %s\n",
requestBuf,
inet_ntoa( clientAddr.sin_addr ) );
ntop_buf );
UpnpPrintf( UPNP_PACKET, SSDP, __FILE__, __LINE__,
"Start of received multicast packet --------------------------------------------\n"
"%s\n"
@ -831,7 +840,7 @@ readFromSSDPSocket( SOCKET socket )
data->parser.msg.msg.length += byteReceived;
// null-terminate
data->parser.msg.msg.buf[byteReceived] = 0;
data->dest_addr = clientAddr;
memcpy( &data->dest_addr, &__ss, sizeof(__ss) );
TPJobInit( &job, ( start_routine )
ssdp_event_handler_thread, data );
TPJobSetFreeFunction( &job, free_ssdp_event_handler_data );
@ -846,132 +855,261 @@ readFromSSDPSocket( SOCKET socket )
}
}
/************************************************************************
* Function : get_ssdp_sockets
*
* Parameters:
* OUT MiniServerSockArray *out: Arrays of SSDP sockets
* OUT MiniServerSockArray *out: Array of SSDP sockets
*
* Description:
* This function creates the ssdp sockets. It set their option to listen
* for multicast traffic.
* 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 )
int get_ssdp_sockets( MiniServerSockArray * out )
{
char errorBuffer[ERROR_BUFFER_LEN];
int onOff = 1;
u_char ttl = 4;
struct ip_mreq ssdpMcastAddr;
struct sockaddr_in ssdpAddr;
int option = 1;
int ret = 0;
struct in_addr addr;
SOCKET ssdpSock;
int retVal;
#if INCLUDE_CLIENT_APIS
SOCKET ssdpReqSock;
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;
// Create the IPv4 socket for SSDP REQUESTS
if( strlen( gIF_IPV4 ) > 0 ) {
retVal = create_ssdp_sock_reqv4( &out->ssdpReqSock4 );
if( retVal != UPNP_E_SUCCESS ) {
return retVal;
}
// For use by ssdp control point.
gSsdpReqSocket4 = out->ssdpReqSock4;
} else {
out->ssdpReqSock4 = INVALID_SOCKET;
}
// Create the IPv6 socket for SSDP REQUESTS
if( strlen( gIF_IPV6 ) > 0 ) {
retVal = create_ssdp_sock_reqv6( &out->ssdpReqSock6 );
if( retVal != UPNP_E_SUCCESS ) {
CLIENTONLY( shutdown( out->ssdpReqSock4, SD_BOTH ); )
CLIENTONLY( UpnpCloseSocket( out->ssdpReqSock4 ); )
return retVal;
}
// For use by ssdp control point.
gSsdpReqSocket6 = out->ssdpReqSock6;
} else {
out->ssdpReqSock6 = INVALID_SOCKET;
}
ret = setsockopt( ssdpReqSock, IPPROTO_IP, IP_MULTICAST_TTL,
&ttl, sizeof (ttl) );
// just do it, regardless if fails or not.
Make_Socket_NoBlocking( ssdpReqSock );
gSsdpReqSocket = ssdpReqSock;
#endif /* INCLUDE_CLIENT_APIS */
ssdpSock = socket( AF_INET, SOCK_DGRAM, 0 );
if ( ssdpSock == -1 ) {
// Create the IPv4 socket for SSDP
if( strlen( gIF_IPV4 ) > 0 ) {
retVal = create_ssdp_sock_v4( &out->ssdpSock4 );
if( retVal != UPNP_E_SUCCESS ) {
CLIENTONLY( shutdown( out->ssdpReqSock4, SD_BOTH ); )
CLIENTONLY( UpnpCloseSocket( out->ssdpReqSock4 ); )
CLIENTONLY( shutdown( out->ssdpReqSock6, SD_BOTH ); )
CLIENTONLY( UpnpCloseSocket( out->ssdpReqSock6 ); )
return retVal;
}
} else {
out->ssdpSock4 = INVALID_SOCKET;
}
// Create the IPv6 socket for SSDP
if( strlen( gIF_IPV6 ) > 0 ) {
retVal = create_ssdp_sock_v6( &out->ssdpSock6 );
if( retVal != UPNP_E_SUCCESS ) {
shutdown( out->ssdpSock4, SD_BOTH );
UpnpCloseSocket( out->ssdpSock4 );
CLIENTONLY( shutdown( out->ssdpReqSock4, SD_BOTH ); )
CLIENTONLY( UpnpCloseSocket( out->ssdpReqSock4 ); )
CLIENTONLY( shutdown( out->ssdpReqSock6, SD_BOTH ); )
CLIENTONLY( UpnpCloseSocket( out->ssdpReqSock6 ); )
return retVal;
}
} else {
out->ssdpSock6 = INVALID_SOCKET;
}
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
*
***************************************************************************/
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 /* 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 );
CLIENTONLY( shutdown( ssdpReqSock, SD_BOTH ); )
CLIENTONLY( UpnpCloseSocket( ssdpReqSock ); )
return UPNP_E_OUTOF_SOCKET;
}
onOff = 1;
ret = setsockopt( ssdpSock, SOL_SOCKET, SO_REUSEADDR,
(char *)&onOff, sizeof(onOff) );
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 );
CLIENTONLY( shutdown( ssdpReqSock, SD_BOTH ); )
CLIENTONLY( UpnpCloseSocket( ssdpReqSock ); )
shutdown( ssdpSock, SD_BOTH );
UpnpCloseSocket( ssdpSock );
shutdown( *ssdpSock, SD_BOTH );
UpnpCloseSocket( *ssdpSock );
return UPNP_E_SOCKET_ERROR;
}
#if defined(__FreeBSD__) || defined(__OSX__) || defined(__APPLE__)
ret = setsockopt( ssdpSock, SOL_SOCKET, SO_REUSEPORT,
(char *)&onOff, sizeof (onOff) );
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 );
CLIENTONLY( shutdown( ssdpReqSock, SD_BOTH ); )
CLIENTONLY( UpnpCloseSocket( ssdpReqSock ); )
shutdown( ssdpSock, SD_BOTH );
UpnpCloseSocket( ssdpSock );
shutdown( *ssdpSock, SD_BOTH );
UpnpCloseSocket( *ssdpSock );
return UPNP_E_SOCKET_ERROR;
}
#endif /* __FreeBSD__ */
memset( (void *)&ssdpAddr, 0, sizeof( struct sockaddr_in ) );
ssdpAddr.sin_family = AF_INET;
// ssdpAddr.sin_addr.s_addr = inet_addr(LOCAL_HOST);
ssdpAddr.sin_addr.s_addr = htonl( INADDR_ANY );
ssdpAddr.sin_port = htons( SSDP_PORT );
ret = bind( ssdpSock, (struct sockaddr *)&ssdpAddr, sizeof (ssdpAddr) );
memset( &__ss, 0, sizeof( __ss ) );
ssdpAddr4->sin_family = AF_INET;
// ssdpAddr.sin_addr.s_addr = inet_addr(gIF_IPV4);
ssdpAddr4->sin_addr.s_addr = htonl( INADDR_ANY );
ssdpAddr4->sin_port = htons( SSDP_PORT );
ret = bind( *ssdpSock, (struct sockaddr *)&__ss, sizeof(__ss) );
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 );
CLIENTONLY( shutdown( ssdpReqSock, SD_BOTH ); )
CLIENTONLY( UpnpCloseSocket( ssdpReqSock ); )
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( LOCAL_HOST );
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) );
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 );
CLIENTONLY( shutdown( ssdpReqSock, SD_BOTH ); )
UpnpCloseSocket( ssdpSock );
CLIENTONLY( UpnpCloseSocket( ssdpReqSock ); )
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(LOCAL_HOST);
ret = setsockopt(ssdpSock, IPPROTO_IP, IP_MULTICAST_IF,
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);
@ -982,26 +1120,132 @@ get_ssdp_sockets( MiniServerSockArray * out )
}
/* result is not checked becuase it will fail in WinMe and Win9x. */
ret = setsockopt( ssdpSock, IPPROTO_IP,
ret = setsockopt( *ssdpSock, IPPROTO_IP,
IP_MULTICAST_TTL, &ttl, sizeof (ttl) );
ret = setsockopt( ssdpSock, SOL_SOCKET, SO_BROADCAST,
(char *)&option, sizeof (option) );
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 );
CLIENTONLY( shutdown( ssdpReqSock, SD_BOTH ); )
UpnpCloseSocket( ssdpSock );
CLIENTONLY( UpnpCloseSocket( ssdpReqSock ); )
shutdown( *ssdpSock, SD_BOTH );
UpnpCloseSocket( *ssdpSock );
return UPNP_E_NETWORK_ERROR;
}
CLIENTONLY( out->ssdpReqSock = ssdpReqSock; )
out->ssdpSock = ssdpSock;
return UPNP_E_SUCCESS;
}
/************************************************************************
* Function : create_ssdp_sock_v6
*
* Parameters:
* IN SOCKET* ssdpSock: SSDP IPv6 socket to be created
*
* Description:
* This function ...
*
* Returns: void
*
***************************************************************************/
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(__FreeBSD__) || 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 /* __FreeBSD__ */
memset( &__ss, 0, sizeof( __ss ) );
ssdpAddr6->sin6_family = AF_INET6;
ssdpAddr6->sin6_addr = in6addr_any;
//inet_pton( AF_INET6, gIF_IPV6, &ssdpAddr6->sin6_addr );
ssdpAddr6->sin6_scope_id = gIF_INDEX;
ssdpAddr6->sin6_port = htons( SSDP_PORT );
ret = bind( *ssdpSock, (struct sockaddr *)&__ss, sizeof(__ss) );
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;
}

View File

@ -51,7 +51,7 @@
* Function : addrToString
*
* Parameters :
* IN const struct sockaddr_in* addr ; socket address object with
* IN const struct sockaddr* addr ; socket address object with
* the IP Address and port information
* OUT char ipaddr_port[] ; character array which will hold the
* IP Address in a string format.
@ -64,11 +64,20 @@
* Note :
************************************************************************/
static UPNP_INLINE void
addrToString( IN const struct sockaddr_in *addr,
addrToString( IN const struct sockaddr *addr,
OUT char ipaddr_port[] )
{
sprintf( ipaddr_port, "%s:%d", inet_ntoa( addr->sin_addr ),
ntohs( addr->sin_port ) );
char buf_ntop[64];
if( addr->sa_family == AF_INET ) {
struct sockaddr_in* sa4 = (struct sockaddr_in*)addr;
inet_ntop(AF_INET, &sa4->sin_addr, buf_ntop, sizeof(buf_ntop) );
sprintf( ipaddr_port, "%s:%d", buf_ntop, ntohs( sa4->sin_port ) );
} else if( addr->sa_family == AF_INET6 ) {
struct sockaddr_in6* sa6 = (struct sockaddr_in6*)addr;
inet_ntop(AF_INET6, &sa6->sin6_addr, buf_ntop, sizeof(buf_ntop) );
sprintf( ipaddr_port, "[%s]:%d", buf_ntop, ntohs( sa6->sin6_port ) );
}
}
/************************************************************************
@ -344,7 +353,7 @@ config_description_doc( INOUT IXML_Document * doc,
*
* Parameters :
* INOUT IXML_Document *doc ; IXML Description document
* IN const struct sockaddr_in* serverAddr ; socket address object
* IN const struct sockaddr* serverAddr ; socket address object
* providing the IP address and port information
* IN const char* alias ; string containing the alias
* IN time_t last_modified ; time when the XML document was
@ -352,7 +361,7 @@ config_description_doc( INOUT IXML_Document * doc,
* OUT char docURL[LINE_SIZE] ; buffer to hold the URL of the
* document.
* INOUT IXML_Document *doc:dom document whose urlbase is to be modified
* IN const struct sockaddr_in* serverAddr : ip address and port of
* IN const struct sockaddr* serverAddr : ip address and port of
* the miniserver
* IN const char* alias : a name to be used for the temp; e.g.:"foo.xml"
* IN time_t last_modified : time
@ -371,7 +380,7 @@ config_description_doc( INOUT IXML_Document * doc,
************************************************************************/
int
configure_urlbase( INOUT IXML_Document * doc,
IN const struct sockaddr_in *serverAddr,
IN const struct sockaddr *serverAddr,
IN const char *alias,
IN time_t last_modified,
OUT char docURL[LINE_SIZE] )