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 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> 2008-02-06 Marcelo Jimenez <mroberto(at)users.sourceforge.net>
* Breaking API so that we now hide internal data structures. * 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 - 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 To Be Decided
============= =============

View File

@ -4,6 +4,7 @@
Version="8.00" Version="8.00"
Name="libupnp" Name="libupnp"
ProjectGUID="{6227F51A-1498-4C4A-B213-F6FDED605125}" ProjectGUID="{6227F51A-1498-4C4A-B213-F6FDED605125}"
RootNamespace="libupnp"
> >
<Platforms> <Platforms>
<Platform <Platform
@ -49,7 +50,7 @@
Optimization="2" Optimization="2"
InlineFunctionExpansion="1" InlineFunctionExpansion="1"
AdditionalIncludeDirectories="..\..\pthreads\include,..\ixml\src\inc,..\ixml\inc,..\threadutil\inc,..\upnp\inc,..\upnp\src\inc,.\inc" 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" StringPooling="true"
RuntimeLibrary="0" RuntimeLibrary="0"
EnableFunctionLevelLinking="true" EnableFunctionLevelLinking="true"
@ -74,7 +75,7 @@
/> />
<Tool <Tool
Name="VCLinkerTool" 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" OutputFile=".\Release/libupnp.dll"
LinkIncremental="1" LinkIncremental="1"
SuppressStartupBanner="true" SuppressStartupBanner="true"
@ -144,7 +145,7 @@
Name="VCCLCompilerTool" Name="VCCLCompilerTool"
Optimization="0" Optimization="0"
AdditionalIncludeDirectories="..\..\pthreads\include;..\..\ixml\src\inc;..\..\ixml\inc;..\..\threadutil\inc;..\..\upnp\inc;..\..\upnp\src\inc;..\inc;..\msvc" 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" MinimalRebuild="true"
BasicRuntimeChecks="3" BasicRuntimeChecks="3"
RuntimeLibrary="1" RuntimeLibrary="1"
@ -170,7 +171,7 @@
/> />
<Tool <Tool
Name="VCLinkerTool" 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" OutputFile="$(OutDir)\libupnp.dll"
LinkIncremental="2" LinkIncremental="2"
SuppressStartupBanner="true" SuppressStartupBanner="true"
@ -503,6 +504,10 @@
RelativePath="..\..\upnp\src\inc\unixutil.h" RelativePath="..\..\upnp\src\inc\unixutil.h"
> >
</File> </File>
<File
RelativePath="..\..\upnp\inc\upnp.h"
>
</File>
<File <File
RelativePath="..\..\upnp\src\inc\upnp_timeout.h" RelativePath="..\..\upnp\src\inc\upnp_timeout.h"
> >

View File

@ -149,7 +149,7 @@ dnl # "current:revision:age"
dnl # dnl #
dnl # - Code has changed in upnp dnl # - Code has changed in upnp
dnl # revision: 5 -> 6 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 # current: 3 -> 4
dnl # revision: 6 -> 0 dnl # revision: 6 -> 0
dnl # - Interface has been removed in upnp 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); void UpnpActionRequest_set_ActionResult(UpnpActionRequest *p, IXML_Document *d);
/** IP address of the control point requesting this action */ /** IP address of the control point requesting this action */
struct in_addr *UpnpActionRequest_get_CtrlPtIPAddr(const UpnpActionRequest *p); struct sockaddr_storage *UpnpActionRequest_get_CtrlPtIPAddr(const UpnpActionRequest *p);
void UpnpActionRequest_set_CtrlPtIPAddr(UpnpActionRequest *p, struct in_addr *ia); void UpnpActionRequest_set_CtrlPtIPAddr(UpnpActionRequest *p, struct sockaddr_storage *ia);
/** The DOM document containing the information from the SOAP header */ /** The DOM document containing the information from the SOAP header */
IXML_Document *UpnpActionRequest_get_SoapHeader(const UpnpActionRequest *p); 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); void UpnpDiscovery_strncpy_Ext(UpnpDiscovery *p, const char *s, int n);
/** The host address of the device responding to the search. */ /** The host address of the device responding to the search. */
struct sockaddr_in *UpnpDiscovery_get_DestAddr(const UpnpDiscovery *p); struct sockaddr *UpnpDiscovery_get_DestAddr(const UpnpDiscovery *p);
void UpnpDiscovery_set_DestAddr(UpnpDiscovery *p, struct sockaddr_in *sa); void UpnpDiscovery_set_DestAddr(UpnpDiscovery *p, struct sockaddr *sa);
#ifdef __cplusplus #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); void UpnpStateVarRequest_strcpy_StateVarName(UpnpStateVarRequest *p, const char *s);
/** IP address of sender requesting the state variable. */ /** IP address of sender requesting the state variable. */
struct in_addr *UpnpStateVarRequest_get_CtrlPtIPAddr(const UpnpStateVarRequest *p); struct sockaddr_storage *UpnpStateVarRequest_get_CtrlPtIPAddr(const UpnpStateVarRequest *p);
void UpnpStateVarRequest_set_CtrlPtIPAddr(UpnpStateVarRequest *p, struct in_addr *ia); void UpnpStateVarRequest_set_CtrlPtIPAddr(UpnpStateVarRequest *p, struct sockaddr_storage *ia);
/** The current value of the variable. This needs to be allocated by /** The current value of the variable. This needs to be allocated by
* the caller. When finished with it, the SDK frees this {\bf DOMString}. */ * the caller. When finished with it, the SDK frees this {\bf DOMString}. */

View File

@ -106,13 +106,15 @@
#endif #endif
#ifndef WIN32 #ifndef WIN32
#define SOCKET int #define SOCKET int
#define INVALID_SOCKET (SOCKET)(~0)
#endif #endif
#ifndef WIN32 #ifndef WIN32
#include <netinet/in.h> #include <netinet/in.h>
#else #else
#include <winsock2.h> #include <Ws2tcpip.h>
#include <iphlpapi.h>
#include <time.h> #include <time.h>
#endif #endif
@ -296,6 +298,15 @@
#define UPNP_E_ALREADY_REGISTERED -120 #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] /** @name UPNP_E_NETWORK_ERROR [-200]
* {\tt UPNP_E_NETWORK_ERROR} signifies that a network error occurred. It * {\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 * 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. */ 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 /** 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 * API function called. It should be called only once. Subsequent calls to
* this API return a {\tt UPNP_E_FINISH} error code. * this API return a {\tt UPNP_E_FINISH} error code.
@ -949,20 +1005,40 @@ EXPORT_SPEC int UpnpFinish();
* returned. * returned.
* *
* @return [unsigned short] The port on which an internal server is * @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); 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 * function can be used to retrieve the actual interface address
* on which device is running. If {\bf UpnpInit} has not succeeded * on which device is running. If {\bf UpnpInit} has not succeeded
* then {\tt NULL} is returned. * 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. * for UPnP related requests.
*/ */
EXPORT_SPEC char * UpnpGetServerIpAddress(void); 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 /** {\bf UpnpRegisterClient} registers a control point application with the
* SDK. A control point application cannot make any other API calls * SDK. A control point application cannot make any other API calls
* until it registers using this function. * until it registers using this function.
@ -1129,6 +1205,58 @@ EXPORT_SPEC int UpnpRegisterRootDevice2(
the new device handle. */ 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, /** {\bf UpnpUnRegisterClient} unregisters a control point application,
* unsubscribing all active subscriptions. After this call, the * unsubscribing all active subscriptions. After this call, the
* {\bf UpnpClient_Handle} is no longer valid. * {\bf UpnpClient_Handle} is no longer valid.

View File

@ -21,7 +21,7 @@ struct SUpnpActionRequest
IXML_Document *m_actionRequest; IXML_Document *m_actionRequest;
IXML_Document *m_actionResult; IXML_Document *m_actionResult;
IXML_Document *m_soapHeader; 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_actionRequest = NULL;
p->m_actionResult = NULL; p->m_actionResult = NULL;
p->m_soapHeader = NULL; p->m_soapHeader = NULL;
memset(&p->m_ctrlPtIPAddr, 0, sizeof (struct in_addr)); memset(&p->m_ctrlPtIPAddr, 0, sizeof (struct sockaddr_storage));
#endif #endif
return (UpnpActionRequest *)p; return (UpnpActionRequest *)p;
} }
@ -73,7 +73,7 @@ void UpnpActionRequest_delete(UpnpActionRequest *p)
UpnpActionRequest_set_SoapHeader(p, NULL); 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); 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; 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; ((struct SUpnpActionRequest *)p)->m_ctrlPtIPAddr = *ia;
} }

View File

@ -22,7 +22,7 @@ struct SUpnpDiscovery
UpnpString *m_os; UpnpString *m_os;
UpnpString *m_date; UpnpString *m_date;
UpnpString *m_ext; 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; 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; ((struct SUpnpDiscovery *)p)->m_destAddr = *sa;
} }

View File

@ -18,7 +18,7 @@ struct SUpnpStateVarRequest
UpnpString *m_devUDN; UpnpString *m_devUDN;
UpnpString *m_serviceID; UpnpString *m_serviceID;
UpnpString *m_stateVarName; UpnpString *m_stateVarName;
struct in_addr m_ctrlPtIPAddr; struct sockaddr_storage m_ctrlPtIPAddr;
DOMString m_currentVal; DOMString m_currentVal;
}; };
@ -36,7 +36,7 @@ UpnpStateVarRequest *UpnpStateVarRequest_new()
p->m_serviceID = UpnpString_new(); p->m_serviceID = UpnpString_new();
p->m_stateVarName = UpnpString_new(); p->m_stateVarName = UpnpString_new();
#if 0 #if 0
memset(&q->m_ctrlPtIPAddr, 0, sizeof (struct in_addr)); memset(&q->m_ctrlPtIPAddr, 0, sizeof (struct sockaddr_storage));
p->m_currentVal = NULL; p->m_currentVal = NULL;
#endif #endif
@ -64,7 +64,7 @@ void UpnpStateVarRequest_delete(UpnpStateVarRequest *p)
UpnpString_delete(q->m_stateVarName); UpnpString_delete(q->m_stateVarName);
q->m_stateVarName = NULL; 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); ixmlFreeDOMString(q->m_currentVal);
q->m_currentVal = NULL; 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; 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; ((struct SUpnpStateVarRequest *)p)->m_ctrlPtIPAddr = *ia;
} }

File diff suppressed because it is too large Load Diff

View File

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

View File

@ -1352,7 +1352,8 @@ gena_process_subscription_request( IN SOCKINFO * info,
HandleLock(); HandleLock();
// CURRENTLY, ONLY ONE DEVICE // 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 ); free( event_url_path );
error_respond( info, HTTP_INTERNAL_SERVER_ERROR, request ); error_respond( info, HTTP_INTERNAL_SERVER_ERROR, request );
HandleUnlock(); HandleUnlock();
@ -1527,7 +1528,8 @@ gena_process_subscription_renewal_request( IN SOCKINFO * info,
HandleLock(); HandleLock();
// CURRENTLY, ONLY SUPPORT ONE DEVICE // 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 ); error_respond( info, HTTP_PRECONDITION_FAILED, request );
membuffer_destroy( &event_url_path ); membuffer_destroy( &event_url_path );
return; return;
@ -1650,7 +1652,8 @@ gena_process_unsubscribe_request( IN SOCKINFO * info,
HandleLock(); HandleLock();
// CURRENTLY, ONLY SUPPORT ONE DEVICE // 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 ); error_respond( info, HTTP_PRECONDITION_FAILED, request );
membuffer_destroy( &event_url_path ); membuffer_destroy( &event_url_path );
HandleUnlock(); HandleUnlock();

View File

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

View File

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

View File

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

View File

@ -41,10 +41,7 @@
#endif #endif
#include "config.h" #include "config.h"
#include "uri.h" #include "uri.h"
#include "upnpapi.h"
#ifdef WIN32
#include "inet_pton.h"
#endif
/************************************************************************ /************************************************************************
@ -224,28 +221,6 @@ parse_uric( const char *in,
return i; 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 * Function : copy_token
@ -328,8 +303,9 @@ copy_URL_list( URL_list * in,
in->URLs, &out->parsedURLs[i].hostport.text, in->URLs, &out->parsedURLs[i].hostport.text,
out->URLs ); out->URLs );
copy_sockaddr_in( &in->parsedURLs[i].hostport.IPv4address, memcpy( &out->parsedURLs[i].hostport.IPaddress,
&out->parsedURLs[i].hostport.IPv4address ); &in->parsedURLs[i].hostport.IPaddress,
sizeof(struct sockaddr_storage) );
} }
out->size = in->size; out->size = in->size;
return HTTP_SUCCESS; return HTTP_SUCCESS;
@ -490,48 +466,13 @@ token_cmp( token * in1,
return memcmp( in1->buff, in2->buff, in1->size ); 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 * Function : parse_hostport
* *
* Parameters : * Parameters :
* char *in ; string of characters representing host and port * 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 * hostport_type *out ; out parameter where the host and port
* are represented as an internet address * are represented as an internet address
* *
@ -540,7 +481,8 @@ parse_port( int max,
* hostport_type struct with internet address and a token * hostport_type struct with internet address and a token
* representing the full host and port. uses gethostbyname. * 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 : * Note :
************************************************************************/ ************************************************************************/
@ -549,165 +491,145 @@ parse_hostport( const char *in,
int max, int max,
hostport_type * out ) 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; memset( out, 0, sizeof(hostport_type) );
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;
out->text.size = 0; // Work on a copy of the input string.
out->text.buff = NULL; strncpy( workbuf, in, sizeof(workbuf) );
out->IPv4address.sin_port = htons( 80 ); //default port is 80 c = workbuf;
memset( &out->IPv4address.sin_zero, 0, 8 ); if( *c == '[' ) {
// IPv6 addresses are enclosed in square brackets.
while( ( i < max ) && ( in[i] != ':' ) && ( in[i] != '/' ) srvname = ++c;
&& ( ( isalnum( in[i] ) ) || ( in[i] == '.' ) while( *c != '\0' && *c != ']' ) {
|| ( in[i] == '-' ) ) ) { c++;
i++;
if( in[i] == '.' ) {
last_dot = i;
} }
if( *c == '\0' ) {
// did not find closing bracket.
return UPNP_E_INVALID_URL;
}
// NULL terminate the srvname and then increment c.
*c++ = '\0'; // overwrite the ']'
if( *c == ':' ) {
has_port = 1;
c++;
}
af = AF_INET6;
} }
else {
host_size = i; // IPv4 address -OR- host name.
srvname = c;
if( ( i < max ) && ( in[i] == ':' ) ) { while( (*c != ':') && (*c != '/') && ( (isalnum(*c)) || (*c == '.') || (*c == '-') ) ) {
begin_port = i + 1; if( *c == '.' )
//convert port last_dot = c;
if( !( hostport_size = parse_port( max - begin_port, c++;
&in[begin_port],
&out->IPv4address.sin_port ) ) )
{
return UPNP_E_INVALID_URL;
} }
hostport_size += begin_port; has_port = (*c == ':') ? 1 : 0;
} else // NULL terminate the srvname
hostport_size = host_size; *c = '\0';
if( has_port == 1 )
c++;
//convert to temporary null terminated string if( last_dot != NULL && isdigit(*(last_dot+1)) ) {
temp_host_name = ( char * )malloc( host_size + 1 ); // Must be an IPv4 address.
af = AF_INET;
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;
} }
} else { else {
int errCode = 0; // Must be a host name.
struct addrinfo hints, *res, *res0;
//call gethostbyname_r (reentrant form of gethostbyname) memset(&hints, 0, sizeof(hints));
// TODO: Use autoconf to discover this rather than the hints.ai_family = AF_UNSPEC;
// platform-specific stuff below hints.ai_socktype = SOCK_STREAM;
#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;
}
#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
{
struct addrinfo hints, *res, *res0;
h = NULL; ret = getaddrinfo(srvname, NULL, &hints, &res0);
memset(&hints, 0, sizeof(hints)); if( ret == 0 ) {
hints.ai_family = PF_INET; for (res = res0; res; res = res->ai_next) {
hints.ai_socktype = SOCK_STREAM; if( res->ai_family == AF_INET ||
errCode = getaddrinfo(temp_host_name, "http", &hints, &res0); res->ai_family == AF_INET6 ) {
// Found a valid IPv4 or IPv6 address.
if (!errCode) { memcpy( &out->IPaddress, res->ai_addr,
for (res = res0; res; res = res->ai_next) { res->ai_addrlen );
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;
break; break;
}
} }
} freeaddrinfo(res0);
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;
if( res == NULL ) {
// Didn't find an AF_INET or AF_INET6 address.
return UPNP_E_INVALID_URL;
} }
} }
} else { else {
out->IPv4address.sin_addr.s_addr = 0; // getaddrinfo failed.
out->IPv4address.sin_family = AF_INET; return UPNP_E_INVALID_URL;
free( temp_host_name ); }
temp_host_name = NULL;
return UPNP_E_INVALID_URL;
} }
} }
if( temp_host_name ) { // Check if a port is specified.
free( temp_host_name ); if( has_port == 1 ) {
temp_host_name = NULL; // 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.size = hostport_size;
out->text.buff = in; out->text.buff = in;
return hostport_size; return hostport_size;
} }
/************************************************************************ /************************************************************************
@ -1069,10 +991,7 @@ parse_uri( const char *in,
return begin_path; return begin_path;
} else { } else {
out->hostport.IPv4address.sin_port = 0; memset( &out->hostport, 0, sizeof(out->hostport) );
out->hostport.IPv4address.sin_addr.s_addr = 0;
out->hostport.text.size = 0;
out->hostport.text.buff = 0;
begin_path = begin_hostport; begin_path = begin_hostport;
} }

View File

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

View File

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

View File

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

View File

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

View File

@ -84,11 +84,12 @@ struct Handle_Info
//URL information //URL information
int MaxSubscriptions; int MaxSubscriptions;
int MaxSubscriptionTimeOut; int MaxSubscriptionTimeOut;
int DeviceAf; // Address family: AF_INET or AF_INET6
#endif #endif
// Client only // Client only
#ifdef INCLUDE_CLIENT_APIS #ifdef INCLUDE_CLIENT_APIS
ClientSubscription *ClientSubList; //client subscription list ClientSubscription *ClientSubList; // client subscription list
LinkedList SsdpSearchList; // active ssdp searches LinkedList SsdpSearchList; // active ssdp searches
#endif #endif
int aliasInstalled; // 0 = not installed; otherwise installed 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, Upnp_Handle_Type GetClientHandleInfo(int *client_handle_out,
struct Handle_Info **HndInfo); struct Handle_Info **HndInfo);
Upnp_Handle_Type GetDeviceHandleInfo(int *device_handle_out, Upnp_Handle_Type GetDeviceHandleInfo( const int AddressFamily,
struct Handle_Info **HndInfo); 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 TimerThread gTimerThread;
extern ThreadPool gRecvThreadPool; extern ThreadPool gRecvThreadPool;
@ -170,6 +178,14 @@ typedef enum { WEB_SERVER_DISABLED, WEB_SERVER_ENABLED } WebServerState;
#define E_HTTP_SYNTAX -6 #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(); void InitHandleList();
int GetFreeHandle(); int GetFreeHandle();
int FreeHandle(int Handle); int FreeHandle(int Handle);
@ -177,7 +193,7 @@ void UpnpThreadDistribution(struct UpnpNonblockParam * Param);
void AutoAdvertise(void *input); void AutoAdvertise(void *input);
int getlocalhostname(char *out); int getlocalhostname(char *out, const int out_len);
extern WebServerState bWebServerState; extern WebServerState bWebServerState;

View File

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

View File

@ -50,13 +50,13 @@ extern "C" {
* *
* Parameters : * Parameters :
* INOUT IXML_Document *doc ; IXML Description document * 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 * providing the IP address and port information
* IN const char* alias ; string containing the alias * IN const char* alias ; string containing the alias
* IN time_t last_modified ; time when the XML document was * IN time_t last_modified ; time when the XML document was
* downloaded * downloaded
* OUT char docURL[LINE_SIZE] ; buffer to hold the URL of the * OUT char docURL[LINE_SIZE] ; buffer to hold the URL of the
* document. * document.
* *
* Description : Configure the full URL for the description document. * Description : Configure the full URL for the description document.
* Create the URL document and add alias, description information. * Create the URL document and add alias, description information.
@ -70,10 +70,10 @@ extern "C" {
* Note : * Note :
****************************************************************************/ ****************************************************************************/
int configure_urlbase( 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 const char* alias,
IN time_t last_modified, IN time_t last_modified,
OUT char docURL[LINE_SIZE] ); OUT char docURL[LINE_SIZE]);
#ifdef __cplusplus #ifdef __cplusplus
@ -81,4 +81,3 @@ int configure_urlbase( INOUT IXML_Document *doc,
#endif #endif
#endif /* URLCONFIG_H */ #endif /* URLCONFIG_H */

View File

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

View File

@ -80,7 +80,7 @@ void send_search_result(IN void *data)
* Parameters: * Parameters:
* IN http_message_t *hmsg: * IN http_message_t *hmsg:
* SSDP message from the device * SSDP message from the device
* IN struct sockaddr_in *dest_addr: * IN struct sockaddr *dest_addr:
* Address of the device * Address of the device
* IN xboolean timeout: * IN xboolean timeout:
* timeout kept by the control point while * timeout kept by the control point while
@ -100,9 +100,9 @@ void send_search_result(IN void *data)
***************************************************************************/ ***************************************************************************/
void ssdp_handle_ctrlpt_msg( void ssdp_handle_ctrlpt_msg(
IN http_message_t *hmsg, IN http_message_t *hmsg,
IN struct sockaddr_in *dest_addr, IN struct sockaddr *dest_addr,
IN xboolean timeout, // only in search reply IN xboolean timeout, // only in search reply
IN void *cookie ) // only in search reply IN void *cookie) // only in search reply
{ {
int handle; int handle;
struct Handle_Info *ctrlpt_info = NULL; struct Handle_Info *ctrlpt_info = NULL;
@ -336,50 +336,6 @@ end_ssdp_handle_ctrlpt_msg:
UpnpDiscovery_delete(param); 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 * Function : CreateClientRequestPacket
@ -389,6 +345,7 @@ process_reply( IN char *request_buf,
* IN char *SearchTarget:Search Target * IN char *SearchTarget:Search Target
* IN int Mx dest_addr: Number of seconds to wait to * IN int Mx dest_addr: Number of seconds to wait to
* collect all the responses * collect all the responses
* IN int AddressFamily: search address family
* *
* Description: * Description:
* This function creates a HTTP search request packet * This function creates a HTTP search request packet
@ -400,13 +357,18 @@ process_reply( IN char *request_buf,
static void static void
CreateClientRequestPacket( IN char *RqstBuf, CreateClientRequestPacket( IN char *RqstBuf,
IN int Mx, IN int Mx,
IN char *SearchTarget ) IN char *SearchTarget,
IN int AddressFamily )
{ {
char TempBuf[COMMAND_LEN]; char TempBuf[COMMAND_LEN];
strcpy( RqstBuf, "M-SEARCH * HTTP/1.1\r\n" ); strcpy( RqstBuf, "M-SEARCH * HTTP/1.1\r\n" );
sprintf( TempBuf, "HOST: %s:%d\r\n", SSDP_IP, SSDP_PORT ); 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, TempBuf );
strcat( RqstBuf, "MAN: \"ssdp:discover\"\r\n" ); strcat( RqstBuf, "MAN: \"ssdp:discover\"\r\n" );
@ -495,7 +457,17 @@ searchExpired( void *arg )
* This cokie will be returned to application in the callback. * This cokie will be returned to application in the callback.
* *
* Description: * 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 * Returns: int
* 1 if successful else appropriate error * 1 if successful else appropriate error
@ -506,18 +478,23 @@ SearchByTarget( IN int Mx,
IN void *Cookie ) IN void *Cookie )
{ {
char errorBuffer[ERROR_BUFFER_LEN]; char errorBuffer[ERROR_BUFFER_LEN];
int socklen = sizeof( struct sockaddr_in ); int socklen = sizeof( struct sockaddr_storage );
int *id = NULL; int *id = NULL;
int ret = 0; int ret = 0;
char *ReqBuf; char ReqBufv4[BUFSIZE];
struct sockaddr_in destAddr; 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; fd_set wrSet;
SsdpSearchArg *newArg = NULL; SsdpSearchArg *newArg = NULL;
int timeTillRead = 0; int timeTillRead = 0;
int handle; int handle;
struct Handle_Info *ctrlpt_info = NULL; struct Handle_Info *ctrlpt_info = NULL;
enum SsdpSearchType requestType; enum SsdpSearchType requestType;
unsigned long addr = inet_addr( LOCAL_HOST ); unsigned long addrv4 = inet_addr( gIF_IPV4 );
int max_fd = 0;
//ThreadData *ThData; //ThreadData *ThData;
ThreadPoolJob job; ThreadPoolJob job;
@ -527,12 +504,7 @@ SearchByTarget( IN int Mx,
return UPNP_E_INVALID_PARAM; return UPNP_E_INVALID_PARAM;
} }
ReqBuf = (char *)malloc( BUFSIZE ); UpnpPrintf(UPNP_INFO, SSDP, __FILE__, __LINE__, "Inside SearchByTarget\n");
if( ReqBuf == NULL ) {
return UPNP_E_OUTOF_MEMORY;
}
UpnpPrintf(UPNP_INFO, SSDP, __FILE__, __LINE__, ">>> SSDP SEND >>>\n");
timeTillRead = Mx; timeTillRead = Mx;
@ -542,21 +514,24 @@ SearchByTarget( IN int Mx,
timeTillRead = MAX_SEARCH_TIME; timeTillRead = MAX_SEARCH_TIME;
} }
CreateClientRequestPacket( ReqBuf, timeTillRead, St ); CreateClientRequestPacket( ReqBufv4, timeTillRead, St, AF_INET );
memset( ( char * )&destAddr, 0, sizeof( struct sockaddr_in ) ); CreateClientRequestPacket( ReqBufv6, timeTillRead, St, AF_INET6 );
destAddr.sin_family = AF_INET; memset( &__ss_v4, 0, sizeof( __ss_v4 ) );
destAddr.sin_addr.s_addr = inet_addr( SSDP_IP ); destAddr4->sin_family = AF_INET;
destAddr.sin_port = htons( SSDP_PORT ); inet_pton( AF_INET, SSDP_IP, &destAddr4->sin_addr );
destAddr4->sin_port = htons( SSDP_PORT );
FD_ZERO( &wrSet ); memset( &__ss_v6, 0, sizeof( __ss_v6 ) );
FD_SET( gSsdpReqSocket, &wrSet ); 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 // add search criteria to list
HandleLock(); HandleLock();
if( GetClientHandleInfo( &handle, &ctrlpt_info ) != HND_CLIENT ) { if( GetClientHandleInfo( &handle, &ctrlpt_info ) != HND_CLIENT ) {
HandleUnlock(); HandleUnlock();
free( ReqBuf );
return UPNP_E_INTERNAL_ERROR; return UPNP_E_INTERNAL_ERROR;
} }
@ -578,34 +553,56 @@ SearchByTarget( IN int Mx,
ListAddTail( &ctrlpt_info->SsdpSearchList, newArg ); ListAddTail( &ctrlpt_info->SsdpSearchList, newArg );
HandleUnlock(); HandleUnlock();
ret = setsockopt( gSsdpReqSocket, IPPROTO_IP, IP_MULTICAST_IF, FD_ZERO( &wrSet );
(char *)&addr, sizeof (addr) ); 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 ) { if( ret == -1 ) {
strerror_r(errno, errorBuffer, ERROR_BUFFER_LEN); strerror_r(errno, errorBuffer, ERROR_BUFFER_LEN);
UpnpPrintf( UPNP_INFO, SSDP, __FILE__, __LINE__, UpnpPrintf( UPNP_INFO, SSDP, __FILE__, __LINE__,
"SSDP_LIB: Error in select(): %s\n", "SSDP_LIB: Error in select(): %s\n",
errorBuffer ); errorBuffer );
shutdown( gSsdpReqSocket, SD_BOTH ); shutdown( gSsdpReqSocket4, SD_BOTH );
UpnpCloseSocket( gSsdpReqSocket ); UpnpCloseSocket( gSsdpReqSocket4 );
free( ReqBuf ); shutdown( gSsdpReqSocket6, SD_BOTH );
UpnpCloseSocket( gSsdpReqSocket6 );
return UPNP_E_INTERNAL_ERROR; return UPNP_E_INTERNAL_ERROR;
} else if( FD_ISSET( gSsdpReqSocket, &wrSet ) ) { }
if( gSsdpReqSocket6 != INVALID_SOCKET &&
FD_ISSET( gSsdpReqSocket6, &wrSet ) ) {
int NumCopy = 0; int NumCopy = 0;
while( NumCopy < NUM_SSDP_COPY ) { while( NumCopy < NUM_SSDP_COPY ) {
sendto( gSsdpReqSocket, ReqBuf, strlen( ReqBuf ), 0, sendto( gSsdpReqSocket6, ReqBufv6, strlen( ReqBufv6 ), 0,
(struct sockaddr *)&destAddr, socklen ); (struct sockaddr *)&__ss_v6, socklen );
NumCopy++; NumCopy++;
imillisleep( SSDP_PAUSE ); 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; return 1;
} }
#endif // EXCLUDE_SSDP #endif // EXCLUDE_SSDP
#endif // INCLUDE_CLIENT_APIS #endif // INCLUDE_CLIENT_APIS

View File

@ -75,7 +75,7 @@ advertiseAndReplyThread( IN void *data )
AdvertiseAndReply( 0, arg->handle, AdvertiseAndReply( 0, arg->handle,
arg->event.RequestType, arg->event.RequestType,
&arg->dest_addr, (struct sockaddr*)&arg->dest_addr,
arg->event.DeviceType, arg->event.DeviceType,
arg->event.UDN, arg->event.UDN,
arg->event.ServiceType, arg->MaxAge ); arg->event.ServiceType, arg->MaxAge );
@ -88,8 +88,8 @@ advertiseAndReplyThread( IN void *data )
* Function : ssdp_handle_device_request * Function : ssdp_handle_device_request
* *
* Parameters: * Parameters:
* IN http_message_t* hmsg: SSDP search request from the control point * 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 struct sockaddr *dest_addr: The address info of control point
* *
* Description: * Description:
* This function handles the search request. It do the sanity checks of * This function handles the search request. It do the sanity checks of
@ -101,8 +101,8 @@ advertiseAndReplyThread( IN void *data )
***************************************************************************/ ***************************************************************************/
#ifdef INCLUDE_DEVICE_APIS #ifdef INCLUDE_DEVICE_APIS
void void
ssdp_handle_device_request( IN http_message_t * hmsg, ssdp_handle_device_request( IN http_message_t *hmsg,
IN struct sockaddr_in *dest_addr ) IN struct sockaddr *dest_addr )
{ {
#define MX_FUDGE_FACTOR 10 #define MX_FUDGE_FACTOR 10
@ -142,7 +142,8 @@ ssdp_handle_device_request( IN http_message_t * hmsg,
HandleLock(); HandleLock();
// device info // device info
if( GetDeviceHandleInfo( &handle, &dev_info ) != HND_DEVICE ) { if( GetDeviceHandleInfo( dest_addr->sa_family,
&handle, &dev_info ) != HND_DEVICE ) {
HandleUnlock(); HandleUnlock();
return; // no info found return; // no info found
} }
@ -170,7 +171,7 @@ ssdp_handle_device_request( IN http_message_t * hmsg,
return; return;
} }
threadArg->handle = handle; threadArg->handle = handle;
threadArg->dest_addr = ( *dest_addr ); memcpy( &threadArg->dest_addr, dest_addr, sizeof(threadArg->dest_addr) );
threadArg->event = event; threadArg->event = event;
threadArg->MaxAge = maxAge; threadArg->MaxAge = maxAge;
@ -201,7 +202,7 @@ ssdp_handle_device_request( IN http_message_t * hmsg,
* Function : NewRequestHandler * Function : NewRequestHandler
* *
* Parameters: * 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 int NumPacket: Number of packet to be sent.
* IN char **RqPacket: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 * 1 if successful else appropriate error
***************************************************************************/ ***************************************************************************/
static int static int
NewRequestHandler( IN struct sockaddr_in *DestAddr, NewRequestHandler( IN struct sockaddr *DestAddr,
IN int NumPacket, IN int NumPacket,
IN char **RqPacket ) IN char **RqPacket )
{ {
char errorBuffer[ERROR_BUFFER_LEN]; char errorBuffer[ERROR_BUFFER_LEN];
int ReplySock; SOCKET ReplySock;
int socklen = sizeof( struct sockaddr_in ); int socklen = sizeof( struct sockaddr_storage );
int NumCopy; int NumCopy;
int Index; 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 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 ) { if ( ReplySock == -1 ) {
strerror_r(errno, errorBuffer, ERROR_BUFFER_LEN); strerror_r(errno, errorBuffer, ERROR_BUFFER_LEN);
UpnpPrintf( UPNP_INFO, SSDP, __FILE__, __LINE__, UpnpPrintf( UPNP_INFO, SSDP, __FILE__, __LINE__,
@ -234,11 +237,25 @@ NewRequestHandler( IN struct sockaddr_in *DestAddr,
return UPNP_E_OUTOF_SOCKET; return UPNP_E_OUTOF_SOCKET;
} }
setsockopt( ReplySock, IPPROTO_IP, IP_MULTICAST_IF, if( DestAddr->sa_family == AF_INET ) {
(char *)&replyAddr, sizeof (replyAddr) ); inet_ntop(AF_INET, &((struct sockaddr_in*)DestAddr)->sin_addr,
setsockopt( ReplySock, IPPROTO_IP, IP_MULTICAST_TTL, buf_ntop, sizeof(buf_ntop));
(char *)&ttl, sizeof (int) ); 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++ ) { for( Index = 0; Index < NumPacket; Index++ ) {
int rc; int rc;
@ -256,11 +273,11 @@ NewRequestHandler( IN struct sockaddr_in *DestAddr,
NumCopy = 0; NumCopy = 0;
while( NumCopy < NUM_COPY ) { while( NumCopy < NUM_COPY ) {
UpnpPrintf( UPNP_INFO, SSDP, __FILE__, __LINE__, UpnpPrintf( UPNP_INFO, SSDP, __FILE__, __LINE__,
">>> SSDP SEND >>>\n%s\n", ">>> SSDP SEND to %s >>>\n%s\n",
*( RqPacket + Index ) ); buf_ntop, *( RqPacket + Index ) );
rc = sendto( ReplySock, *( RqPacket + Index ), rc = sendto( ReplySock, *( RqPacket + Index ),
strlen( *( RqPacket + Index ) ), strlen( *( RqPacket + Index ) ),
0, ( struct sockaddr * )DestAddr, socklen ); 0, DestAddr, socklen );
imillisleep( SSDP_PAUSE ); imillisleep( SSDP_PAUSE );
++NumCopy; ++NumCopy;
} }
@ -283,6 +300,7 @@ NewRequestHandler( IN struct sockaddr_in *DestAddr,
* IN char * location :Location URL. * IN char * location :Location URL.
* IN int duration :Service duration in sec. * IN int duration :Service duration in sec.
* OUT char** packet :Output buffer filled with HTTP statement. * OUT char** packet :Output buffer filled with HTTP statement.
* IN int AddressFamily: Address family of the HTTP request.
* *
* Description: * Description:
* This function creates a HTTP request packet. Depending * This function creates a HTTP request packet. Depending
@ -298,7 +316,8 @@ CreateServicePacket( IN int msg_type,
IN char *usn, IN char *usn,
IN char *location, IN char *location,
IN int duration, IN int duration,
OUT char **packet ) OUT char **packet,
IN int AddressFamily)
{ {
int ret_code; int ret_code;
char *nts; char *nts;
@ -315,11 +334,13 @@ CreateServicePacket( IN int msg_type,
if( msg_type == MSGTYPE_REPLY ) { if( msg_type == MSGTYPE_REPLY ) {
ret_code = http_MakeMessage( ret_code = http_MakeMessage(
&buf, 1, 1, &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, HTTP_OK,
"CACHE-CONTROL: max-age=", duration, "CACHE-CONTROL: max-age=", duration,
"EXT:", "EXT:",
"LOCATION: ", location, "LOCATION: ", location,
"OPT: ", "\"http://schemas.upnp.org/upnp/1/0/\"; ns=01",
"01-NLS: ", gUpnpSdkNLSuuid,
X_USER_AGENT, X_USER_AGENT,
"ST: ", nt, "ST: ", nt,
"USN: ", usn); "USN: ", usn);
@ -337,14 +358,18 @@ CreateServicePacket( IN int msg_type,
// NOTE: The CACHE-CONTROL and LOCATION headers are not present in // NOTE: The CACHE-CONTROL and LOCATION headers are not present in
// a shutdown msg, but are present here for MS WinMe interop. // a shutdown msg, but are present here for MS WinMe interop.
ret_code = http_MakeMessage( ret_code = http_MakeMessage(
&buf, 1, 1, &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, 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, "CACHE-CONTROL: max-age=", duration,
"LOCATION: ", location, "LOCATION: ", location,
"OPT: ", "\"http://schemas.upnp.org/upnp/1/0/\"; ns=01",
"01-NLS: ", gUpnpSdkNLSuuid,
"NT: ", nt, "NT: ", nt,
"NTS: ", nts, "NTS: ", nts,
X_USER_AGENT, X_USER_AGENT,
@ -387,9 +412,12 @@ DeviceAdvertisement( IN char *DevType,
int RootDev, int RootDev,
char *Udn, char *Udn,
IN char *Location, 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_Nt[LINE_SIZE]
char Mil_Usn[LINE_SIZE]; char Mil_Usn[LINE_SIZE];
@ -397,11 +425,22 @@ DeviceAdvertisement( IN char *DevType,
int ret_code; int ret_code;
UpnpPrintf( UPNP_INFO, SSDP, __FILE__, __LINE__, UpnpPrintf( UPNP_INFO, SSDP, __FILE__, __LINE__,
"In function SendDeviceAdvertisemenrt\n" ); "In function DeviceAdvertisement\n" );
DestAddr.sin_family = AF_INET; memset( &__ss, 0, sizeof(__ss) );
DestAddr.sin_addr.s_addr = inet_addr( SSDP_IP ); if( AddressFamily == AF_INET ) {
DestAddr.sin_port = htons( SSDP_PORT ); 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[0] = NULL;
msgs[1] = NULL; msgs[1] = NULL;
@ -412,17 +451,17 @@ DeviceAdvertisement( IN char *DevType,
if( RootDev ) { if( RootDev ) {
sprintf( Mil_Usn, "%s::upnp:rootdevice", Udn ); sprintf( Mil_Usn, "%s::upnp:rootdevice", Udn );
CreateServicePacket( MSGTYPE_ADVERTISEMENT, "upnp:rootdevice", 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 // both root and sub-devices need to send these two messages
// //
CreateServicePacket( MSGTYPE_ADVERTISEMENT, Udn, Udn, CreateServicePacket( MSGTYPE_ADVERTISEMENT, Udn, Udn,
Location, Duration, &msgs[1] ); Location, Duration, &msgs[1], AddressFamily );
sprintf( Mil_Usn, "%s::%s", Udn, DevType ); sprintf( Mil_Usn, "%s::%s", Udn, DevType );
CreateServicePacket( MSGTYPE_ADVERTISEMENT, DevType, Mil_Usn, CreateServicePacket( MSGTYPE_ADVERTISEMENT, DevType, Mil_Usn,
Location, Duration, &msgs[2] ); Location, Duration, &msgs[2], AddressFamily );
// check error // check error
if( ( RootDev && msgs[0] == NULL ) || if( ( RootDev && msgs[0] == NULL ) ||
@ -435,11 +474,11 @@ DeviceAdvertisement( IN char *DevType,
// send packets // send packets
if( RootDev ) { if( RootDev ) {
// send 3 msg types // send 3 msg types
ret_code = NewRequestHandler( &DestAddr, 3, &msgs[0] ); ret_code = NewRequestHandler( (struct sockaddr*)&__ss, 3, &msgs[0] );
} else // sub-device } else // sub-device
{ {
// send 2 msg types // send 2 msg types
ret_code = NewRequestHandler( &DestAddr, 2, &msgs[1] ); ret_code = NewRequestHandler( (struct sockaddr*)&__ss, 2, &msgs[1] );
} }
// free msgs // free msgs
@ -454,7 +493,7 @@ DeviceAdvertisement( IN char *DevType,
* Function : SendReply * Function : SendReply
* *
* Parameters: * Parameters:
* IN struct sockaddr_in * DestAddr:destination IP address. * IN struct sockaddr * DestAddr:destination IP address.
* IN char *DevType: Device type * IN char *DevType: Device type
* IN int RootDev: 1 means root device 0 means embedded device. * IN int RootDev: 1 means root device 0 means embedded device.
* IN char * Udn: Device UDN * IN char * Udn: Device UDN
@ -470,7 +509,7 @@ DeviceAdvertisement( IN char *DevType,
* UPNP_E_SUCCESS if successful else appropriate error * UPNP_E_SUCCESS if successful else appropriate error
***************************************************************************/ ***************************************************************************/
int int
SendReply( IN struct sockaddr_in *DestAddr, SendReply( IN struct sockaddr *DestAddr,
IN char *DevType, IN char *DevType,
IN int RootDev, IN int RootDev,
IN char *Udn, IN char *Udn,
@ -493,7 +532,7 @@ SendReply( IN struct sockaddr_in *DestAddr,
sprintf( Mil_Usn, "%s::upnp:rootdevice", Udn ); sprintf( Mil_Usn, "%s::upnp:rootdevice", Udn );
CreateServicePacket( MSGTYPE_REPLY, "upnp:rootdevice", CreateServicePacket( MSGTYPE_REPLY, "upnp:rootdevice",
Mil_Usn, Location, Duration, &msgs[0] ); Mil_Usn, Location, Duration, &msgs[0], DestAddr->sa_family );
} else { } else {
// two msgs for embedded devices // two msgs for embedded devices
num_msgs = 1; num_msgs = 1;
@ -501,11 +540,11 @@ SendReply( IN struct sockaddr_in *DestAddr,
//NK: FIX for extra response when someone searches by udn //NK: FIX for extra response when someone searches by udn
if( !ByType ) { if( !ByType ) {
CreateServicePacket( MSGTYPE_REPLY, Udn, Udn, Location, CreateServicePacket( MSGTYPE_REPLY, Udn, Udn, Location,
Duration, &msgs[0] ); Duration, &msgs[0], DestAddr->sa_family );
} else { } else {
sprintf( Mil_Usn, "%s::%s", Udn, DevType ); sprintf( Mil_Usn, "%s::%s", Udn, DevType );
CreateServicePacket( MSGTYPE_REPLY, DevType, Mil_Usn, 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 * Function : DeviceReply
* *
* Parameters: * Parameters:
* IN struct sockaddr_in * DestAddr:destination IP address. * IN struct sockaddr *DestAddr:destination IP address.
* IN char *DevType: Device type * IN char *DevType: Device type
* IN int RootDev: 1 means root device 0 means embedded device. * IN int RootDev: 1 means root device 0 means embedded device.
* IN char * Udn: Device UDN * IN char * Udn: Device UDN
@ -545,12 +584,12 @@ SendReply( IN struct sockaddr_in *DestAddr,
* UPNP_E_SUCCESS if successful else appropriate error * UPNP_E_SUCCESS if successful else appropriate error
***************************************************************************/ ***************************************************************************/
int int
DeviceReply( IN struct sockaddr_in *DestAddr, DeviceReply( IN struct sockaddr *DestAddr,
IN char *DevType, IN char *DevType,
IN int RootDev, IN int RootDev,
IN char *Udn, IN char *Udn,
IN char *Location, IN char *Location,
IN int Duration ) IN int Duration)
{ {
char *szReq[3], char *szReq[3],
Mil_Nt[LINE_SIZE], Mil_Nt[LINE_SIZE],
@ -568,18 +607,18 @@ DeviceReply( IN struct sockaddr_in *DestAddr,
strcpy( Mil_Nt, "upnp:rootdevice" ); strcpy( Mil_Nt, "upnp:rootdevice" );
sprintf( Mil_Usn, "%s::upnp:rootdevice", Udn ); sprintf( Mil_Usn, "%s::upnp:rootdevice", Udn );
CreateServicePacket( MSGTYPE_REPLY, Mil_Nt, Mil_Usn, 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_Nt, "%s", Udn );
sprintf( Mil_Usn, "%s", Udn ); sprintf( Mil_Usn, "%s", Udn );
CreateServicePacket( MSGTYPE_REPLY, Mil_Nt, Mil_Usn, 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_Nt, "%s", DevType );
sprintf( Mil_Usn, "%s::%s", Udn, DevType ); sprintf( Mil_Usn, "%s::%s", Udn, DevType );
CreateServicePacket( MSGTYPE_REPLY, Mil_Nt, Mil_Usn, CreateServicePacket( MSGTYPE_REPLY, Mil_Nt, Mil_Usn,
Location, Duration, &szReq[2] ); Location, Duration, &szReq[2], DestAddr->sa_family );
// check error // check error
@ -613,6 +652,7 @@ DeviceReply( IN struct sockaddr_in *DestAddr,
* IN char *ServType: Service Type. * IN char *ServType: Service Type.
* IN char * Location: Location of Device description document. * 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: * Description:
* This function creates the advertisement packet based * This function creates the advertisement packet based
* on the input parameter, and send it to the multicast channel. * on the input parameter, and send it to the multicast channel.
@ -624,28 +664,42 @@ int
ServiceAdvertisement( IN char *Udn, ServiceAdvertisement( IN char *Udn,
IN char *ServType, IN char *ServType,
IN char *Location, IN char *Location,
IN int Duration ) IN int Duration,
IN int AddressFamily)
{ {
char Mil_Usn[LINE_SIZE]; char Mil_Usn[LINE_SIZE];
char *szReq[1]; char *szReq[1];
struct sockaddr_in DestAddr;
int RetVal; 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; memset( &__ss, 0, sizeof(__ss) );
DestAddr.sin_addr.s_addr = inet_addr( SSDP_IP ); if( AddressFamily == AF_INET ) {
DestAddr.sin_port = htons( SSDP_PORT ); 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 ); sprintf( Mil_Usn, "%s::%s", Udn, ServType );
//CreateServiceRequestPacket(1,szReq[0],Mil_Nt,Mil_Usn, //CreateServiceRequestPacket(1,szReq[0],Mil_Nt,Mil_Usn,
//Server,Location,Duration); //Server,Location,Duration);
CreateServicePacket( MSGTYPE_ADVERTISEMENT, ServType, Mil_Usn, CreateServicePacket( MSGTYPE_ADVERTISEMENT, ServType, Mil_Usn,
Location, Duration, &szReq[0] ); Location, Duration, &szReq[0], AddressFamily );
if( szReq[0] == NULL ) { if( szReq[0] == NULL ) {
return UPNP_E_OUTOF_MEMORY; return UPNP_E_OUTOF_MEMORY;
} }
RetVal = NewRequestHandler( &DestAddr, 1, szReq ); RetVal = NewRequestHandler( (struct sockaddr*)&__ss, 1, szReq );
free( szReq[0] ); free( szReq[0] );
return RetVal; return RetVal;
@ -655,7 +709,7 @@ ServiceAdvertisement( IN char *Udn,
* Function : ServiceReply * Function : ServiceReply
* *
* Parameters: * Parameters:
* IN struct sockaddr_in *DestAddr: * IN struct sockaddr *DestAddr:
* IN char * Udn: Device UDN * IN char * Udn: Device UDN
* IN char *ServType: Service Type. * IN char *ServType: Service Type.
* IN char * Location: Location of Device description document. * IN char * Location: Location of Device description document.
@ -668,7 +722,7 @@ ServiceAdvertisement( IN char *Udn,
* UPNP_E_SUCCESS if successful else appropriate error * UPNP_E_SUCCESS if successful else appropriate error
***************************************************************************/ ***************************************************************************/
int int
ServiceReply( IN struct sockaddr_in *DestAddr, ServiceReply( IN struct sockaddr *DestAddr,
IN char *ServType, IN char *ServType,
IN char *Udn, IN char *Udn,
IN char *Location, IN char *Location,
@ -683,7 +737,7 @@ ServiceReply( IN struct sockaddr_in *DestAddr,
sprintf( Mil_Usn, "%s::%s", Udn, ServType ); sprintf( Mil_Usn, "%s::%s", Udn, ServType );
CreateServicePacket( MSGTYPE_REPLY, ServType, Mil_Usn, CreateServicePacket( MSGTYPE_REPLY, ServType, Mil_Usn,
Location, Duration, &szReq[0] ); Location, Duration, &szReq[0], DestAddr->sa_family );
if( szReq[0] == NULL ) { if( szReq[0] == NULL ) {
return UPNP_E_OUTOF_MEMORY; return UPNP_E_OUTOF_MEMORY;
} }
@ -702,6 +756,7 @@ ServiceReply( IN struct sockaddr_in *DestAddr,
* IN char *ServType: Service Type. * IN char *ServType: Service Type.
* IN char * Location: Location of Device description document. * IN char * Location: Location of Device description document.
* IN int Duration :Service duration in sec. * IN int Duration :Service duration in sec.
* IN int AddressFamily: Device address family
* Description: * Description:
* This function creates a HTTP service shutdown request packet * This function creates a HTTP service shutdown request packet
* and sent it to the multicast channel through RequestHandler. * and sent it to the multicast channel through RequestHandler.
@ -713,27 +768,41 @@ int
ServiceShutdown( IN char *Udn, ServiceShutdown( IN char *Udn,
IN char *ServType, IN char *ServType,
IN char *Location, IN char *Location,
IN int Duration ) IN int Duration,
IN int AddressFamily)
{ {
char Mil_Usn[LINE_SIZE]; char Mil_Usn[LINE_SIZE];
char *szReq[1]; 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; int RetVal;
DestAddr.sin_family = AF_INET; memset( &__ss, 0, sizeof(__ss) );
DestAddr.sin_addr.s_addr = inet_addr( SSDP_IP ); if( AddressFamily == AF_INET ) {
DestAddr.sin_port = htons( SSDP_PORT ); 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_Nt,"%s",ServType);
sprintf( Mil_Usn, "%s::%s", Udn, ServType ); sprintf( Mil_Usn, "%s::%s", Udn, ServType );
//CreateServiceRequestPacket(0,szReq[0],Mil_Nt,Mil_Usn, //CreateServiceRequestPacket(0,szReq[0],Mil_Nt,Mil_Usn,
//Server,Location,Duration); //Server,Location,Duration);
CreateServicePacket( MSGTYPE_SHUTDOWN, ServType, Mil_Usn, CreateServicePacket( MSGTYPE_SHUTDOWN, ServType, Mil_Usn,
Location, Duration, &szReq[0] ); Location, Duration, &szReq[0], AddressFamily );
if( szReq[0] == NULL ) { if( szReq[0] == NULL ) {
return UPNP_E_OUTOF_MEMORY; return UPNP_E_OUTOF_MEMORY;
} }
RetVal = NewRequestHandler( &DestAddr, 1, szReq ); RetVal = NewRequestHandler( (struct sockaddr*)&__ss, 1, szReq );
free( szReq[0] ); free( szReq[0] );
return RetVal; return RetVal;
@ -748,6 +817,7 @@ ServiceShutdown( IN char *Udn,
* IN char * Udn: Device UDN * IN char * Udn: Device UDN
* IN char * Location: Location URL * IN char * Location: Location URL
* IN int Duration :Device duration in sec. * IN int Duration :Device duration in sec.
* IN int AddressFamily: Device address family.
* *
* Description: * Description:
* This function creates a HTTP device shutdown request packet * This function creates a HTTP device shutdown request packet
@ -762,9 +832,12 @@ DeviceShutdown( IN char *DevType,
IN char *Udn, IN char *Udn,
IN char *_Server, IN char *_Server,
IN char *Location, 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 *msgs[3];
char Mil_Usn[LINE_SIZE]; char Mil_Usn[LINE_SIZE];
int ret_code; int ret_code;
@ -773,26 +846,37 @@ DeviceShutdown( IN char *DevType,
msgs[1] = NULL; msgs[1] = NULL;
msgs[2] = NULL; msgs[2] = NULL;
DestAddr.sin_family = AF_INET; memset( &__ss, 0, sizeof(__ss) );
DestAddr.sin_addr.s_addr = inet_addr( SSDP_IP ); if( AddressFamily == AF_INET ) {
DestAddr.sin_port = htons( SSDP_PORT ); 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 // root device has one extra msg
if( RootDev ) { if( RootDev ) {
sprintf( Mil_Usn, "%s::upnp:rootdevice", Udn ); sprintf( Mil_Usn, "%s::upnp:rootdevice", Udn );
CreateServicePacket( MSGTYPE_SHUTDOWN, "upnp:rootdevice", CreateServicePacket( MSGTYPE_SHUTDOWN, "upnp:rootdevice",
Mil_Usn, Location, Duration, &msgs[0] ); Mil_Usn, Location, Duration, &msgs[0], AddressFamily );
} }
UpnpPrintf( UPNP_INFO, SSDP, __FILE__, __LINE__, UpnpPrintf( UPNP_INFO, SSDP, __FILE__, __LINE__,
"In function DeviceShutdown\n" ); "In function DeviceShutdown\n" );
// both root and sub-devices need to send these two messages // both root and sub-devices need to send these two messages
CreateServicePacket( MSGTYPE_SHUTDOWN, Udn, Udn, CreateServicePacket( MSGTYPE_SHUTDOWN, Udn, Udn,
Location, Duration, &msgs[1] ); Location, Duration, &msgs[1], AddressFamily );
sprintf( Mil_Usn, "%s::%s", Udn, DevType ); sprintf( Mil_Usn, "%s::%s", Udn, DevType );
CreateServicePacket( MSGTYPE_SHUTDOWN, DevType, Mil_Usn, CreateServicePacket( MSGTYPE_SHUTDOWN, DevType, Mil_Usn,
Location, Duration, &msgs[2] ); Location, Duration, &msgs[2], AddressFamily );
// check error // check error
if( ( RootDev && msgs[0] == NULL ) || if( ( RootDev && msgs[0] == NULL ) ||
@ -805,11 +889,11 @@ DeviceShutdown( IN char *DevType,
// send packets // send packets
if( RootDev ) { if( RootDev ) {
// send 3 msg types // send 3 msg types
ret_code = NewRequestHandler( &DestAddr, 3, &msgs[0] ); ret_code = NewRequestHandler( (struct sockaddr*)&__ss, 3, &msgs[0] );
} else // sub-device } else // sub-device
{ {
// send 2 msg types // send 2 msg types
ret_code = NewRequestHandler( &DestAddr, 2, &msgs[1] ); ret_code = NewRequestHandler( (struct sockaddr*)&__ss, 2, &msgs[1] );
} }
// free msgs // free msgs

View File

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

View File

@ -51,7 +51,7 @@
* Function : addrToString * Function : addrToString
* *
* Parameters : * 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 * the IP Address and port information
* OUT char ipaddr_port[] ; character array which will hold the * OUT char ipaddr_port[] ; character array which will hold the
* IP Address in a string format. * IP Address in a string format.
@ -64,11 +64,20 @@
* Note : * Note :
************************************************************************/ ************************************************************************/
static UPNP_INLINE void static UPNP_INLINE void
addrToString( IN const struct sockaddr_in *addr, addrToString( IN const struct sockaddr *addr,
OUT char ipaddr_port[] ) OUT char ipaddr_port[] )
{ {
sprintf( ipaddr_port, "%s:%d", inet_ntoa( addr->sin_addr ), char buf_ntop[64];
ntohs( addr->sin_port ) );
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 : * Parameters :
* INOUT IXML_Document *doc ; IXML Description document * 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 * providing the IP address and port information
* IN const char* alias ; string containing the alias * IN const char* alias ; string containing the alias
* IN time_t last_modified ; time when the XML document was * 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 * OUT char docURL[LINE_SIZE] ; buffer to hold the URL of the
* document. * document.
* INOUT IXML_Document *doc:dom document whose urlbase is to be modified * 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 * the miniserver
* IN const char* alias : a name to be used for the temp; e.g.:"foo.xml" * IN const char* alias : a name to be used for the temp; e.g.:"foo.xml"
* IN time_t last_modified : time * IN time_t last_modified : time
@ -371,7 +380,7 @@ config_description_doc( INOUT IXML_Document * doc,
************************************************************************/ ************************************************************************/
int int
configure_urlbase( INOUT IXML_Document * doc, configure_urlbase( INOUT IXML_Document * doc,
IN const struct sockaddr_in *serverAddr, IN const struct sockaddr *serverAddr,
IN const char *alias, IN const char *alias,
IN time_t last_modified, IN time_t last_modified,
OUT char docURL[LINE_SIZE] ) OUT char docURL[LINE_SIZE] )