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:
parent
4f2075b7c9
commit
2e4a96f034
@ -2,6 +2,9 @@
|
||||
Version 1.8.0
|
||||
*******************************************************************************
|
||||
|
||||
2008-05-02 Marcelo Jimenez <mroberto(at)users.sourceforge.net>
|
||||
* Merged Charles Nepveu's IPv6 work. libupnp now is IPv6 enabled.
|
||||
|
||||
2008-02-06 Marcelo Jimenez <mroberto(at)users.sourceforge.net>
|
||||
* Breaking API so that we now hide internal data structures.
|
||||
|
||||
|
4
TODO
4
TODO
@ -18,6 +18,10 @@ http://sourceforge.net/tracker/?group_id=7189&atid=307189
|
||||
|
||||
- make API clean for large files and 64 bits
|
||||
|
||||
- Why is NUM_HANDLE defined to 200 when we can register only:
|
||||
A) One client(1)
|
||||
B) An IPv4 and IPv6 device (2)
|
||||
NUM_HANDLE should be 3
|
||||
|
||||
To Be Decided
|
||||
=============
|
||||
|
@ -4,6 +4,7 @@
|
||||
Version="8.00"
|
||||
Name="libupnp"
|
||||
ProjectGUID="{6227F51A-1498-4C4A-B213-F6FDED605125}"
|
||||
RootNamespace="libupnp"
|
||||
>
|
||||
<Platforms>
|
||||
<Platform
|
||||
@ -49,7 +50,7 @@
|
||||
Optimization="2"
|
||||
InlineFunctionExpansion="1"
|
||||
AdditionalIncludeDirectories="..\..\pthreads\include,..\ixml\src\inc,..\ixml\inc,..\threadutil\inc,..\upnp\inc,..\upnp\src\inc,.\inc"
|
||||
PreprocessorDefinitions="WIN32;NDEBUG;_WINDOWS;_USRDLL;LIBUPNP_EXPORTS;PTW32_STATIC_LIB;UPNP_STATIC_LIB;UPNP_USE_MSVCPP"
|
||||
PreprocessorDefinitions="WIN32;NDEBUG;_WINDOWS;_USRDLL;LIBUPNP_EXPORTS;PTW32_STATIC_LIB;UPNP_STATIC_LIB;UPNP_USE_MSVCPP;_CRT_SECURE_NO_WARNINGS"
|
||||
StringPooling="true"
|
||||
RuntimeLibrary="0"
|
||||
EnableFunctionLevelLinking="true"
|
||||
@ -74,7 +75,7 @@
|
||||
/>
|
||||
<Tool
|
||||
Name="VCLinkerTool"
|
||||
AdditionalDependencies="odbc32.lib odbccp32.lib ..\..\pthreads\lib\pthreadvc2.lib ws2_32.lib"
|
||||
AdditionalDependencies="odbc32.lib odbccp32.lib ..\..\pthreads\lib\pthreadvc2.lib ws2_32.lib iphlpapi.lib"
|
||||
OutputFile=".\Release/libupnp.dll"
|
||||
LinkIncremental="1"
|
||||
SuppressStartupBanner="true"
|
||||
@ -144,7 +145,7 @@
|
||||
Name="VCCLCompilerTool"
|
||||
Optimization="0"
|
||||
AdditionalIncludeDirectories="..\..\pthreads\include;..\..\ixml\src\inc;..\..\ixml\inc;..\..\threadutil\inc;..\..\upnp\inc;..\..\upnp\src\inc;..\inc;..\msvc"
|
||||
PreprocessorDefinitions="DEBUG;WIN32;_WINDOWS;_USRDLL;LIBUPNP_EXPORTS;UPNP_USE_MSVCPP"
|
||||
PreprocessorDefinitions="DEBUG;WIN32;_WINDOWS;_USRDLL;LIBUPNP_EXPORTS;UPNP_USE_MSVCPP;_CRT_SECURE_NO_WARNINGS"
|
||||
MinimalRebuild="true"
|
||||
BasicRuntimeChecks="3"
|
||||
RuntimeLibrary="1"
|
||||
@ -170,7 +171,7 @@
|
||||
/>
|
||||
<Tool
|
||||
Name="VCLinkerTool"
|
||||
AdditionalDependencies="odbc32.lib odbccp32.lib ..\..\pthreads\lib\pthreadvc2.lib ws2_32.lib"
|
||||
AdditionalDependencies="odbc32.lib odbccp32.lib ..\..\pthreads\lib\pthreadvc2.lib ws2_32.lib iphlpapi.lib"
|
||||
OutputFile="$(OutDir)\libupnp.dll"
|
||||
LinkIncremental="2"
|
||||
SuppressStartupBanner="true"
|
||||
@ -503,6 +504,10 @@
|
||||
RelativePath="..\..\upnp\src\inc\unixutil.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\upnp\inc\upnp.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\upnp\src\inc\upnp_timeout.h"
|
||||
>
|
||||
|
@ -149,7 +149,7 @@ dnl # "current:revision:age"
|
||||
dnl #
|
||||
dnl # - Code has changed in upnp
|
||||
dnl # revision: 5 -> 6
|
||||
dnl # - Interface has changed in upnp
|
||||
dnl # - Interfaces have been changed, added and removed in upnp
|
||||
dnl # current: 3 -> 4
|
||||
dnl # revision: 6 -> 0
|
||||
dnl # - Interface has been removed in upnp
|
||||
|
@ -69,8 +69,8 @@ IXML_Document *UpnpActionRequest_get_ActionResult(const UpnpActionRequest *p);
|
||||
void UpnpActionRequest_set_ActionResult(UpnpActionRequest *p, IXML_Document *d);
|
||||
|
||||
/** IP address of the control point requesting this action */
|
||||
struct in_addr *UpnpActionRequest_get_CtrlPtIPAddr(const UpnpActionRequest *p);
|
||||
void UpnpActionRequest_set_CtrlPtIPAddr(UpnpActionRequest *p, struct in_addr *ia);
|
||||
struct sockaddr_storage *UpnpActionRequest_get_CtrlPtIPAddr(const UpnpActionRequest *p);
|
||||
void UpnpActionRequest_set_CtrlPtIPAddr(UpnpActionRequest *p, struct sockaddr_storage *ia);
|
||||
|
||||
/** The DOM document containing the information from the SOAP header */
|
||||
IXML_Document *UpnpActionRequest_get_SoapHeader(const UpnpActionRequest *p);
|
||||
|
@ -83,8 +83,8 @@ void UpnpDiscovery_strcpy_Ext(UpnpDiscovery *p, const char *s);
|
||||
void UpnpDiscovery_strncpy_Ext(UpnpDiscovery *p, const char *s, int n);
|
||||
|
||||
/** The host address of the device responding to the search. */
|
||||
struct sockaddr_in *UpnpDiscovery_get_DestAddr(const UpnpDiscovery *p);
|
||||
void UpnpDiscovery_set_DestAddr(UpnpDiscovery *p, struct sockaddr_in *sa);
|
||||
struct sockaddr *UpnpDiscovery_get_DestAddr(const UpnpDiscovery *p);
|
||||
void UpnpDiscovery_set_DestAddr(UpnpDiscovery *p, struct sockaddr *sa);
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
|
@ -62,8 +62,8 @@ void UpnpStateVarRequest_set_StateVarName(UpnpStateVarRequest *p, const UpnpStri
|
||||
void UpnpStateVarRequest_strcpy_StateVarName(UpnpStateVarRequest *p, const char *s);
|
||||
|
||||
/** IP address of sender requesting the state variable. */
|
||||
struct in_addr *UpnpStateVarRequest_get_CtrlPtIPAddr(const UpnpStateVarRequest *p);
|
||||
void UpnpStateVarRequest_set_CtrlPtIPAddr(UpnpStateVarRequest *p, struct in_addr *ia);
|
||||
struct sockaddr_storage *UpnpStateVarRequest_get_CtrlPtIPAddr(const UpnpStateVarRequest *p);
|
||||
void UpnpStateVarRequest_set_CtrlPtIPAddr(UpnpStateVarRequest *p, struct sockaddr_storage *ia);
|
||||
|
||||
/** The current value of the variable. This needs to be allocated by
|
||||
* the caller. When finished with it, the SDK frees this {\bf DOMString}. */
|
||||
|
136
upnp/inc/upnp.h
136
upnp/inc/upnp.h
@ -106,13 +106,15 @@
|
||||
#endif
|
||||
#ifndef WIN32
|
||||
#define SOCKET int
|
||||
#define INVALID_SOCKET (SOCKET)(~0)
|
||||
#endif
|
||||
|
||||
|
||||
#ifndef WIN32
|
||||
#include <netinet/in.h>
|
||||
#else
|
||||
#include <winsock2.h>
|
||||
#include <Ws2tcpip.h>
|
||||
#include <iphlpapi.h>
|
||||
#include <time.h>
|
||||
#endif
|
||||
|
||||
@ -296,6 +298,15 @@
|
||||
#define UPNP_E_ALREADY_REGISTERED -120
|
||||
/*! @} */
|
||||
|
||||
/** @name UPNP_E_INVALID_INTERFACE [-121]
|
||||
* {\tt UPNP_E_INVALID_INTERFACE} signifies that the interface provided to
|
||||
* {\bf UpnpInit2} is unknown or does not have a valid IPv4 or IPv6
|
||||
* address configured.
|
||||
*/
|
||||
/*! @{ */
|
||||
#define UPNP_E_INVALID_INTERFACE -121
|
||||
/*! @} */
|
||||
|
||||
/** @name UPNP_E_NETWORK_ERROR [-200]
|
||||
* {\tt UPNP_E_NETWORK_ERROR} signifies that a network error occurred. It
|
||||
* is the generic error code for network problems that are not covered under
|
||||
@ -930,6 +941,51 @@ EXPORT_SPEC int UpnpInit(
|
||||
will pick an arbitrary free port. */
|
||||
);
|
||||
|
||||
|
||||
/*! @name Initialization and Registration */
|
||||
/*! @{ */
|
||||
/** Initializes the Linux SDK for UPnP Devices. This function must be called
|
||||
* before any other API function can be called. It should be called
|
||||
* only once. Subsequent calls to this API return a {\tt UPNP_E_INIT}
|
||||
* error code.
|
||||
*
|
||||
* Optionally, the application can specify an interface name (in the
|
||||
* case of a multi-homed configuration) and a port number to use for
|
||||
* all UPnP operations. Since a port number can be used only by one
|
||||
* process, multiple processes using the SDK must specify
|
||||
* different port numbers.
|
||||
*
|
||||
* If unspecified, the SDK will use the first suitable interface and an
|
||||
* arbitrary port.
|
||||
*
|
||||
* This call is synchronous.
|
||||
*
|
||||
* @return [int] An integer representing one of the following:
|
||||
* \begin{itemize}
|
||||
* \item {\tt UPNP_E_SUCCESS}: The operation completed successfully.
|
||||
* \item {\tt UPNP_E_OUTOF_MEMORY}: Insufficient resources exist
|
||||
* to initialize the SDK.
|
||||
* \item {\tt UPNP_E_INIT}: The SDK is already initialized.
|
||||
* \item {\tt UPNP_E_INIT_FAILED}: The SDK initialization
|
||||
* failed for an unknown reason.
|
||||
* \item {\tt UPNP_E_SOCKET_BIND}: An error occurred binding a socket.
|
||||
* \item {\tt UPNP_E_LISTEN}: An error occurred listening to a socket.
|
||||
* \item {\tt UPNP_E_OUTOF_SOCKET}: An error ocurred creating a socket.
|
||||
* \item {\tt UPNP_E_INTERNAL_ERROR}: An internal error ocurred.
|
||||
* \item {\tt UPNP_E_INVALID_INTERFACE}: IfName is invalid or doees not
|
||||
* have a valid IPv4 or IPv6 addresss configured.
|
||||
* \end{itemize} */
|
||||
|
||||
EXPORT_SPEC int UpnpInit2(
|
||||
IN const char *IfName, /** The interface name to use by the UPnP SDK
|
||||
operations. Examples: "eth0", "xl0",
|
||||
"Local Area Connection", {\tt NULL} to
|
||||
use the first suitable interface. */
|
||||
IN unsigned short DestPort /** The destination port number to use. 0
|
||||
will pick an arbitrary free port. */
|
||||
);
|
||||
|
||||
|
||||
/** Terminates the Linux SDK for UPnP Devices. This function must be the last
|
||||
* API function called. It should be called only once. Subsequent calls to
|
||||
* this API return a {\tt UPNP_E_FINISH} error code.
|
||||
@ -949,20 +1005,40 @@ EXPORT_SPEC int UpnpFinish();
|
||||
* returned.
|
||||
*
|
||||
* @return [unsigned short] The port on which an internal server is
|
||||
* listening for UPnP related requests.
|
||||
* listening for IPv4 UPnP related requests.
|
||||
*/
|
||||
EXPORT_SPEC unsigned short UpnpGetServerPort(void);
|
||||
|
||||
/** If {\tt NULL} is used as the IP address in {\bf UpnpInit}, then this
|
||||
/** If '0' is used as the port number in {\bf UpnpInit}, then this
|
||||
* function can be used to retrieve the actual port allocated to
|
||||
* the SDK. If {\bf UpnpInit} has not succeeded then 0 is
|
||||
* returned.
|
||||
*
|
||||
* @return [unsigned short] The port on which an internal server is
|
||||
* listening for IPv6 UPnP related requests.
|
||||
*/
|
||||
EXPORT_SPEC unsigned short UpnpGetServerPort6(void);
|
||||
|
||||
/** If {\tt NULL} is used as the IPv4 address in {\bf UpnpInit}, then this
|
||||
* function can be used to retrieve the actual interface address
|
||||
* on which device is running. If {\bf UpnpInit} has not succeeded
|
||||
* then {\tt NULL} is returned.
|
||||
*
|
||||
* @return [char*] The IP address on which an internal server is listening
|
||||
* @return [char*] The IPv4 address on which an internal server is listening
|
||||
* for UPnP related requests.
|
||||
*/
|
||||
EXPORT_SPEC char * UpnpGetServerIpAddress(void);
|
||||
|
||||
/** If {\tt NULL} is used as the IPv6 address in {\bf UpnpInit}, then this
|
||||
* function can be used to retrieve the actual interface address
|
||||
* on which device is running. If {\bf UpnpInit} has not succeeded
|
||||
* then {\tt NULL} is returned.
|
||||
*
|
||||
* @return [char*] The IPv6 address on which an internal server is listening
|
||||
* for UPnP related requests.
|
||||
*/
|
||||
EXPORT_SPEC char * UpnpGetServerIp6Address(void);
|
||||
|
||||
/** {\bf UpnpRegisterClient} registers a control point application with the
|
||||
* SDK. A control point application cannot make any other API calls
|
||||
* until it registers using this function.
|
||||
@ -1129,6 +1205,58 @@ EXPORT_SPEC int UpnpRegisterRootDevice2(
|
||||
the new device handle. */
|
||||
);
|
||||
|
||||
|
||||
/** {\bf UpnpRegisterRootDevice3} registers a device application for a
|
||||
* specific address family with the SDK. A device application cannot
|
||||
* make any other API calls until it registers using this function.
|
||||
* Device applications can also register as control points (see
|
||||
* {\bf UpnpRegisterClient} to get a control point handle to perform
|
||||
* control point functionality).
|
||||
*
|
||||
* {\bf UpnpRegisterRootDevice} is synchronous and does not generate
|
||||
* any callbacks. Callbacks can occur as soon as this function returns.
|
||||
*
|
||||
* @return [int] An integer representing one of the following:
|
||||
* \begin{itemize}
|
||||
* \item {\tt UPNP_E_SUCCESS}: The operation completed successfully.
|
||||
* \item {\tt UPNP_E_FINISH}: The SDK is already terminated or
|
||||
* is not initialized.
|
||||
* \item {\tt UPNP_E_INVALID_DESC}: The description document was not
|
||||
* a valid device description.
|
||||
* \item {\tt UPNP_E_INVALID_URL}: The URL for the description document
|
||||
* is not valid.
|
||||
* \item {\tt UPNP_E_INVALID_PARAM}: Either {\bf Callback} or {\bf Hnd}
|
||||
* is not a valid pointer or {\bf DescURL} is {\tt NULL}.
|
||||
* \item {\tt UPNP_E_NETWORK_ERROR}: A network error occurred.
|
||||
* \item {\tt UPNP_E_SOCKET_WRITE}: An error or timeout occurred writing
|
||||
* to a socket.
|
||||
* \item {\tt UPNP_E_SOCKET_READ}: An error or timeout occurred reading
|
||||
* from a socket.
|
||||
* \item {\tt UPNP_E_SOCKET_BIND}: An error occurred binding a socket.
|
||||
* \item {\tt UPNP_E_SOCKET_CONNECT}: An error occurred connecting the
|
||||
* socket.
|
||||
* \item {\tt UPNP_E_OUTOF_SOCKET}: Too many sockets are currently
|
||||
* allocated.
|
||||
* \item {\tt UPNP_E_OUTOF_MEMORY}: There are insufficient resources to
|
||||
* register this root device.
|
||||
* \end{itemize} */
|
||||
|
||||
EXPORT_SPEC int UpnpRegisterRootDevice3(
|
||||
IN const char *DescUrl, /** Pointer to a string containing the
|
||||
description URL for this root device
|
||||
instance. */
|
||||
IN Upnp_FunPtr Callback, /** Pointer to the callback function for
|
||||
receiving asynchronous events. */
|
||||
IN const void *Cookie, /** Pointer to user data returned with the
|
||||
callback function when invoked. */
|
||||
OUT UpnpDevice_Handle *Hnd,/** Pointer to a variable to store the
|
||||
new device handle. */
|
||||
IN const int AddressFamily /** Address family of this device. Can be
|
||||
AF_INET for an IPv4 device, or AF_INET6
|
||||
for an IPv6 device. Defaults to AF_INET. */
|
||||
);
|
||||
|
||||
|
||||
/** {\bf UpnpUnRegisterClient} unregisters a control point application,
|
||||
* unsubscribing all active subscriptions. After this call, the
|
||||
* {\bf UpnpClient_Handle} is no longer valid.
|
||||
|
@ -21,7 +21,7 @@ struct SUpnpActionRequest
|
||||
IXML_Document *m_actionRequest;
|
||||
IXML_Document *m_actionResult;
|
||||
IXML_Document *m_soapHeader;
|
||||
struct in_addr m_ctrlPtIPAddr;
|
||||
struct sockaddr_storage m_ctrlPtIPAddr;
|
||||
};
|
||||
|
||||
|
||||
@ -41,7 +41,7 @@ UpnpActionRequest *UpnpActionRequest_new()
|
||||
p->m_actionRequest = NULL;
|
||||
p->m_actionResult = NULL;
|
||||
p->m_soapHeader = NULL;
|
||||
memset(&p->m_ctrlPtIPAddr, 0, sizeof (struct in_addr));
|
||||
memset(&p->m_ctrlPtIPAddr, 0, sizeof (struct sockaddr_storage));
|
||||
#endif
|
||||
return (UpnpActionRequest *)p;
|
||||
}
|
||||
@ -73,7 +73,7 @@ void UpnpActionRequest_delete(UpnpActionRequest *p)
|
||||
|
||||
UpnpActionRequest_set_SoapHeader(p, NULL);
|
||||
|
||||
memset(&q->m_ctrlPtIPAddr, 0, sizeof (struct in_addr));
|
||||
memset(&q->m_ctrlPtIPAddr, 0, sizeof (struct sockaddr_storage));
|
||||
|
||||
free(p);
|
||||
}
|
||||
@ -224,13 +224,13 @@ void UpnpActionRequest_set_ActionResult(UpnpActionRequest *p, IXML_Document *d)
|
||||
}
|
||||
|
||||
|
||||
struct in_addr *UpnpActionRequest_get_CtrlPtIPAddr(const UpnpActionRequest *p)
|
||||
struct sockaddr_storage *UpnpActionRequest_get_CtrlPtIPAddr(const UpnpActionRequest *p)
|
||||
{
|
||||
return &((struct SUpnpActionRequest *)p)->m_ctrlPtIPAddr;
|
||||
}
|
||||
|
||||
|
||||
void UpnpActionRequest_set_CtrlPtIPAddr(UpnpActionRequest *p, struct in_addr *ia)
|
||||
void UpnpActionRequest_set_CtrlPtIPAddr(UpnpActionRequest *p, struct sockaddr_storage *ia)
|
||||
{
|
||||
((struct SUpnpActionRequest *)p)->m_ctrlPtIPAddr = *ia;
|
||||
}
|
||||
|
@ -22,7 +22,7 @@ struct SUpnpDiscovery
|
||||
UpnpString *m_os;
|
||||
UpnpString *m_date;
|
||||
UpnpString *m_ext;
|
||||
struct sockaddr_in m_destAddr;
|
||||
struct sockaddr m_destAddr;
|
||||
};
|
||||
|
||||
|
||||
@ -332,13 +332,13 @@ void UpnpDiscovery_strncpy_Ext(UpnpDiscovery *p, const char *s, int n)
|
||||
}
|
||||
|
||||
|
||||
struct sockaddr_in *UpnpDiscovery_get_DestAddr(const UpnpDiscovery *p)
|
||||
struct sockaddr *UpnpDiscovery_get_DestAddr(const UpnpDiscovery *p)
|
||||
{
|
||||
return &((struct SUpnpDiscovery *)p)->m_destAddr;
|
||||
}
|
||||
|
||||
|
||||
void UpnpDiscovery_set_DestAddr(UpnpDiscovery *p, struct sockaddr_in *sa)
|
||||
void UpnpDiscovery_set_DestAddr(UpnpDiscovery *p, struct sockaddr *sa)
|
||||
{
|
||||
((struct SUpnpDiscovery *)p)->m_destAddr = *sa;
|
||||
}
|
||||
|
@ -18,7 +18,7 @@ struct SUpnpStateVarRequest
|
||||
UpnpString *m_devUDN;
|
||||
UpnpString *m_serviceID;
|
||||
UpnpString *m_stateVarName;
|
||||
struct in_addr m_ctrlPtIPAddr;
|
||||
struct sockaddr_storage m_ctrlPtIPAddr;
|
||||
DOMString m_currentVal;
|
||||
};
|
||||
|
||||
@ -36,7 +36,7 @@ UpnpStateVarRequest *UpnpStateVarRequest_new()
|
||||
p->m_serviceID = UpnpString_new();
|
||||
p->m_stateVarName = UpnpString_new();
|
||||
#if 0
|
||||
memset(&q->m_ctrlPtIPAddr, 0, sizeof (struct in_addr));
|
||||
memset(&q->m_ctrlPtIPAddr, 0, sizeof (struct sockaddr_storage));
|
||||
p->m_currentVal = NULL;
|
||||
#endif
|
||||
|
||||
@ -64,7 +64,7 @@ void UpnpStateVarRequest_delete(UpnpStateVarRequest *p)
|
||||
UpnpString_delete(q->m_stateVarName);
|
||||
q->m_stateVarName = NULL;
|
||||
|
||||
memset(&q->m_ctrlPtIPAddr, 0, sizeof (struct in_addr));
|
||||
memset(&q->m_ctrlPtIPAddr, 0, sizeof (struct sockaddr_storage));
|
||||
|
||||
ixmlFreeDOMString(q->m_currentVal);
|
||||
q->m_currentVal = NULL;
|
||||
@ -190,13 +190,13 @@ void UpnpStateVarRequest_strcpy_StateVarName(UpnpStateVarRequest *p, const char
|
||||
}
|
||||
|
||||
|
||||
struct in_addr *UpnpStateVarRequest_get_CtrlPtIPAddr(const UpnpStateVarRequest *p)
|
||||
struct sockaddr_storage *UpnpStateVarRequest_get_CtrlPtIPAddr(const UpnpStateVarRequest *p)
|
||||
{
|
||||
return &((struct SUpnpStateVarRequest *)p)->m_ctrlPtIPAddr;
|
||||
}
|
||||
|
||||
|
||||
void UpnpStateVarRequest_set_CtrlPtIPAddr(UpnpStateVarRequest *p, struct in_addr *ia)
|
||||
void UpnpStateVarRequest_set_CtrlPtIPAddr(UpnpStateVarRequest *p, struct sockaddr_storage *ia)
|
||||
{
|
||||
((struct SUpnpStateVarRequest *)p)->m_ctrlPtIPAddr = *ia;
|
||||
}
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -325,13 +325,23 @@ static int gena_subscribe(
|
||||
"TIMEOUT: Second-", timeout_str );
|
||||
} else {
|
||||
// subscribe
|
||||
return_code = http_MakeMessage(
|
||||
&request, 1, 1,
|
||||
"q" "sssdsc" "sc" "sscc",
|
||||
HTTPMETHOD_SUBSCRIBE, &dest_url,
|
||||
"CALLBACK: <http://", LOCAL_HOST, ":", LOCAL_PORT, "/>",
|
||||
"NT: upnp:event",
|
||||
"TIMEOUT: Second-", timeout_str);
|
||||
if( dest_url.hostport.IPaddress.ss_family == AF_INET6 ) {
|
||||
return_code = http_MakeMessage(
|
||||
&request, 1, 1,
|
||||
"q" "sssdsc" "sc" "sscc",
|
||||
HTTPMETHOD_SUBSCRIBE, &dest_url,
|
||||
"CALLBACK: <http://[", gIF_IPV6, "]:", LOCAL_PORT_V6, "/>",
|
||||
"NT: upnp:event",
|
||||
"TIMEOUT: Second-", timeout_str );
|
||||
} else {
|
||||
return_code = http_MakeMessage(
|
||||
&request, 1, 1,
|
||||
"q" "sssdsc" "sc" "sscc",
|
||||
HTTPMETHOD_SUBSCRIBE, &dest_url,
|
||||
"CALLBACK: <http://", gIF_IPV4, ":", LOCAL_PORT_V4, "/>",
|
||||
"NT: upnp:event",
|
||||
"TIMEOUT: Second-", timeout_str);
|
||||
}
|
||||
}
|
||||
if (return_code != 0) {
|
||||
return return_code;
|
||||
|
@ -1352,7 +1352,8 @@ gena_process_subscription_request( IN SOCKINFO * info,
|
||||
HandleLock();
|
||||
|
||||
// CURRENTLY, ONLY ONE DEVICE
|
||||
if( GetDeviceHandleInfo( &device_handle, &handle_info ) != HND_DEVICE ) {
|
||||
if( GetDeviceHandleInfo( info->foreign_sockaddr.ss_family ,
|
||||
&device_handle, &handle_info ) != HND_DEVICE ) {
|
||||
free( event_url_path );
|
||||
error_respond( info, HTTP_INTERNAL_SERVER_ERROR, request );
|
||||
HandleUnlock();
|
||||
@ -1527,7 +1528,8 @@ gena_process_subscription_renewal_request( IN SOCKINFO * info,
|
||||
HandleLock();
|
||||
|
||||
// CURRENTLY, ONLY SUPPORT ONE DEVICE
|
||||
if( GetDeviceHandleInfo( &device_handle, &handle_info ) != HND_DEVICE ) {
|
||||
if( GetDeviceHandleInfo( info->foreign_sockaddr.ss_family,
|
||||
&device_handle, &handle_info ) != HND_DEVICE ) {
|
||||
error_respond( info, HTTP_PRECONDITION_FAILED, request );
|
||||
membuffer_destroy( &event_url_path );
|
||||
return;
|
||||
@ -1650,7 +1652,8 @@ gena_process_unsubscribe_request( IN SOCKINFO * info,
|
||||
HandleLock();
|
||||
|
||||
// CURRENTLY, ONLY SUPPORT ONE DEVICE
|
||||
if( GetDeviceHandleInfo( &device_handle, &handle_info ) != HND_DEVICE ) {
|
||||
if( GetDeviceHandleInfo( info->foreign_sockaddr.ss_family,
|
||||
&device_handle, &handle_info ) != HND_DEVICE ) {
|
||||
error_respond( info, HTTP_PRECONDITION_FAILED, request );
|
||||
membuffer_destroy( &event_url_path );
|
||||
HandleUnlock();
|
||||
|
@ -73,8 +73,7 @@
|
||||
|
||||
struct mserv_request_t {
|
||||
int connfd; // connection handle
|
||||
struct in_addr foreign_ip_addr;
|
||||
unsigned short foreign_ip_port;
|
||||
struct sockaddr_storage foreign_sockaddr;
|
||||
};
|
||||
|
||||
typedef enum { MSERV_IDLE, MSERV_RUNNING, MSERV_STOPPING } MiniServerState;
|
||||
@ -272,8 +271,8 @@ handle_request( void *args )
|
||||
//parser_request_init( &parser ); ////LEAK_FIX_MK
|
||||
hmsg = &parser.msg;
|
||||
|
||||
if( sock_init_with_ip( &info, connfd, request->foreign_ip_addr,
|
||||
request->foreign_ip_port ) != UPNP_E_SUCCESS ) {
|
||||
if( sock_init_with_ip( &info, connfd, (struct sockaddr*)&request->foreign_sockaddr )
|
||||
!= UPNP_E_SUCCESS ) {
|
||||
free( request );
|
||||
httpmsg_destroy( hmsg );
|
||||
return;
|
||||
@ -317,7 +316,7 @@ handle_request( void *args )
|
||||
*
|
||||
* Parameters:
|
||||
* IN int connfd - Socket Descriptor on which connection is accepted
|
||||
* IN struct sockaddr_in* clientAddr - Clients Address information
|
||||
* IN struct sockaddr* clientAddr - Clients Address information
|
||||
*
|
||||
* Description:
|
||||
* Initilize the thread pool to handle a request.
|
||||
@ -327,7 +326,7 @@ handle_request( void *args )
|
||||
************************************************************************/
|
||||
static UPNP_INLINE void
|
||||
schedule_request_job( IN int connfd,
|
||||
IN struct sockaddr_in *clientAddr )
|
||||
IN struct sockaddr *clientAddr )
|
||||
{
|
||||
struct mserv_request_t *request;
|
||||
ThreadPoolJob job;
|
||||
@ -338,14 +337,13 @@ schedule_request_job( IN int connfd,
|
||||
if( request == NULL ) {
|
||||
UpnpPrintf( UPNP_INFO, MSERV, __FILE__, __LINE__,
|
||||
"mserv %d: out of memory\n", connfd );
|
||||
shutdown( request->connfd, SD_BOTH );
|
||||
shutdown( connfd, SD_BOTH );
|
||||
UpnpCloseSocket( connfd );
|
||||
return;
|
||||
}
|
||||
|
||||
request->connfd = connfd;
|
||||
request->foreign_ip_addr = clientAddr->sin_addr;
|
||||
request->foreign_ip_port = ntohs( clientAddr->sin_port );
|
||||
memcpy( &request->foreign_sockaddr, clientAddr, sizeof(request->foreign_sockaddr) );
|
||||
|
||||
TPJobInit( &job, ( start_routine ) handle_request, ( void * )request );
|
||||
TPJobSetFreeFunction( &job, free_handle_request_arg );
|
||||
@ -380,28 +378,41 @@ static void
|
||||
RunMiniServer( MiniServerSockArray *miniSock )
|
||||
{
|
||||
char errorBuffer[ERROR_BUFFER_LEN];
|
||||
struct sockaddr_in clientAddr;
|
||||
struct sockaddr_storage clientAddr;
|
||||
socklen_t clientLen;
|
||||
SOCKET connectHnd;
|
||||
SOCKET miniServSock = miniSock->miniServerSock;
|
||||
SOCKET miniServSock4 = miniSock->miniServerSock4;
|
||||
SOCKET miniServSock6 = miniSock->miniServerSock6;
|
||||
SOCKET miniServStopSock = miniSock->miniServerStopSock;
|
||||
SOCKET ssdpSock = miniSock->ssdpSock;
|
||||
SOCKET ssdpSock4 = miniSock->ssdpSock4;
|
||||
SOCKET ssdpSock6 = miniSock->ssdpSock6;
|
||||
#ifdef INCLUDE_CLIENT_APIS
|
||||
SOCKET ssdpReqSock = miniSock->ssdpReqSock;
|
||||
SOCKET ssdpReqSock4 = miniSock->ssdpReqSock4;
|
||||
SOCKET ssdpReqSock6 = miniSock->ssdpReqSock6;
|
||||
#endif
|
||||
|
||||
char buf_ntop[64];
|
||||
fd_set expSet;
|
||||
fd_set rdSet;
|
||||
unsigned int maxMiniSock;
|
||||
unsigned int maxMiniSock = 0;
|
||||
int byteReceived;
|
||||
char requestBuf[256];
|
||||
int ret = 0;
|
||||
|
||||
maxMiniSock = max( miniServSock, miniServStopSock) ;
|
||||
maxMiniSock = max( maxMiniSock, (SOCKET)(ssdpSock) );
|
||||
if( miniServSock4 != INVALID_SOCKET )
|
||||
maxMiniSock = max( maxMiniSock, miniServSock4 );
|
||||
if( miniServSock6 != INVALID_SOCKET )
|
||||
maxMiniSock = max( maxMiniSock, miniServSock6 );
|
||||
if( ssdpSock4 != INVALID_SOCKET )
|
||||
maxMiniSock = max( maxMiniSock, ssdpSock4 );
|
||||
if( ssdpSock6 != INVALID_SOCKET )
|
||||
maxMiniSock = max( maxMiniSock, ssdpSock6 );
|
||||
#ifdef INCLUDE_CLIENT_APIS
|
||||
maxMiniSock = max( maxMiniSock, (SOCKET)(ssdpReqSock) );
|
||||
if( ssdpReqSock4 != INVALID_SOCKET )
|
||||
maxMiniSock = max( maxMiniSock, ssdpReqSock4 );
|
||||
if( ssdpReqSock6 != INVALID_SOCKET )
|
||||
maxMiniSock = max( maxMiniSock, ssdpReqSock6 );
|
||||
#endif
|
||||
maxMiniSock = max( maxMiniSock, miniServStopSock) ;
|
||||
++maxMiniSock;
|
||||
|
||||
gMServState = MSERV_RUNNING;
|
||||
@ -410,11 +421,20 @@ RunMiniServer( MiniServerSockArray *miniSock )
|
||||
FD_ZERO( &expSet );
|
||||
|
||||
FD_SET( miniServStopSock, &expSet );
|
||||
FD_SET( miniServSock, &rdSet );
|
||||
FD_SET( miniServStopSock, &rdSet );
|
||||
FD_SET( ssdpSock, &rdSet );
|
||||
if( miniServSock4 != INVALID_SOCKET )
|
||||
FD_SET( miniServSock4, &rdSet );
|
||||
if( miniServSock6 != INVALID_SOCKET )
|
||||
FD_SET( miniServSock6, &rdSet );
|
||||
if( ssdpSock4 != INVALID_SOCKET )
|
||||
FD_SET( ssdpSock4, &rdSet );
|
||||
if( ssdpSock6 != INVALID_SOCKET )
|
||||
FD_SET( ssdpSock6, &rdSet );
|
||||
#ifdef INCLUDE_CLIENT_APIS
|
||||
FD_SET( ssdpReqSock, &rdSet );
|
||||
if( ssdpReqSock4 != INVALID_SOCKET )
|
||||
FD_SET( ssdpReqSock4, &rdSet );
|
||||
if( ssdpReqSock6 != INVALID_SOCKET )
|
||||
FD_SET( ssdpReqSock6, &rdSet );
|
||||
#endif
|
||||
|
||||
ret = select( maxMiniSock, &rdSet, NULL, &expSet, NULL );
|
||||
@ -426,9 +446,10 @@ RunMiniServer( MiniServerSockArray *miniSock )
|
||||
isleep( 1 );
|
||||
continue;
|
||||
} else {
|
||||
if( FD_ISSET( miniServSock, &rdSet ) ) {
|
||||
clientLen = sizeof( struct sockaddr_in );
|
||||
connectHnd = accept( miniServSock,
|
||||
if( miniServSock6 != INVALID_SOCKET &&
|
||||
FD_ISSET( miniServSock6, &rdSet ) ) {
|
||||
clientLen = sizeof( clientAddr );
|
||||
connectHnd = accept( miniServSock6,
|
||||
( struct sockaddr * )&clientAddr, &clientLen );
|
||||
if( connectHnd == -1 ) {
|
||||
strerror_r(errno, errorBuffer, ERROR_BUFFER_LEN);
|
||||
@ -436,29 +457,55 @@ RunMiniServer( MiniServerSockArray *miniSock )
|
||||
"miniserver: Error in accept(): %s\n", errorBuffer );
|
||||
continue;
|
||||
}
|
||||
schedule_request_job( connectHnd, &clientAddr );
|
||||
schedule_request_job( connectHnd, (struct sockaddr*)&clientAddr );
|
||||
}
|
||||
if( miniServSock4 != INVALID_SOCKET &&
|
||||
FD_ISSET( miniServSock4, &rdSet ) ) {
|
||||
clientLen = sizeof( clientAddr );
|
||||
connectHnd = accept( miniServSock4,
|
||||
( struct sockaddr * )&clientAddr, &clientLen );
|
||||
if( connectHnd == -1 ) {
|
||||
strerror_r(errno, errorBuffer, ERROR_BUFFER_LEN);
|
||||
UpnpPrintf( UPNP_INFO, MSERV, __FILE__, __LINE__,
|
||||
"miniserver: Error in accept(): %s\n", errorBuffer );
|
||||
continue;
|
||||
}
|
||||
schedule_request_job( connectHnd, (struct sockaddr*)&clientAddr );
|
||||
}
|
||||
#ifdef INCLUDE_CLIENT_APIS
|
||||
// ssdp
|
||||
if( FD_ISSET( ssdpReqSock, &rdSet ) ) {
|
||||
readFromSSDPSocket( ssdpReqSock );
|
||||
if( ssdpReqSock6 != INVALID_SOCKET &&
|
||||
FD_ISSET( ssdpReqSock6, &rdSet ) ) {
|
||||
readFromSSDPSocket( ssdpReqSock6 );
|
||||
}
|
||||
if( ssdpReqSock4 != INVALID_SOCKET &&
|
||||
FD_ISSET( ssdpReqSock4, &rdSet ) ) {
|
||||
readFromSSDPSocket( ssdpReqSock4 );
|
||||
}
|
||||
#endif
|
||||
if( FD_ISSET( ssdpSock, &rdSet ) ) {
|
||||
readFromSSDPSocket( ssdpSock );
|
||||
if( ssdpSock6 != INVALID_SOCKET &&
|
||||
FD_ISSET( ssdpSock6, &rdSet ) ) {
|
||||
readFromSSDPSocket( ssdpSock6 );
|
||||
}
|
||||
if( ssdpSock4 != INVALID_SOCKET &&
|
||||
FD_ISSET( ssdpSock4, &rdSet ) ) {
|
||||
readFromSSDPSocket( ssdpSock4 );
|
||||
}
|
||||
if( FD_ISSET( miniServStopSock, &rdSet ) ) {
|
||||
clientLen = sizeof( struct sockaddr_in );
|
||||
memset( (char *)&clientAddr, 0, sizeof (struct sockaddr_in) );
|
||||
clientLen = sizeof( clientAddr );
|
||||
memset( (char *)&clientAddr, 0, sizeof(clientAddr) );
|
||||
byteReceived =
|
||||
recvfrom( miniServStopSock, requestBuf, 25, 0,
|
||||
( struct sockaddr * )&clientAddr,
|
||||
&clientLen );
|
||||
if( byteReceived > 0 ) {
|
||||
requestBuf[byteReceived] = '\0';
|
||||
inet_ntop(AF_INET,
|
||||
&((struct sockaddr_in*)&clientAddr)->sin_addr,
|
||||
buf_ntop, sizeof(buf_ntop) );
|
||||
UpnpPrintf( UPNP_INFO, MSERV, __FILE__, __LINE__,
|
||||
"Received response: %s From host %s \n",
|
||||
requestBuf, inet_ntoa( clientAddr.sin_addr ) );
|
||||
requestBuf, buf_ntop );
|
||||
UpnpPrintf( UPNP_PACKET, MSERV, __FILE__, __LINE__,
|
||||
"Received multicast packet: \n %s\n",
|
||||
requestBuf );
|
||||
@ -470,15 +517,21 @@ RunMiniServer( MiniServerSockArray *miniSock )
|
||||
}
|
||||
}
|
||||
|
||||
shutdown( miniServSock, SD_BOTH );
|
||||
UpnpCloseSocket( miniServSock );
|
||||
shutdown( miniServSock4, SD_BOTH );
|
||||
UpnpCloseSocket( miniServSock4 );
|
||||
shutdown( miniServSock6, SD_BOTH );
|
||||
UpnpCloseSocket( miniServSock6 );
|
||||
shutdown( miniServStopSock, SD_BOTH );
|
||||
UpnpCloseSocket( miniServStopSock );
|
||||
shutdown( ssdpSock, SD_BOTH );
|
||||
UpnpCloseSocket( ssdpSock );
|
||||
shutdown( ssdpSock4, SD_BOTH );
|
||||
UpnpCloseSocket( ssdpSock4 );
|
||||
shutdown( ssdpSock6, SD_BOTH );
|
||||
UpnpCloseSocket( ssdpSock6 );
|
||||
#ifdef INCLUDE_CLIENT_APIS
|
||||
shutdown( ssdpReqSock, SD_BOTH );
|
||||
UpnpCloseSocket( ssdpReqSock );
|
||||
shutdown( ssdpReqSock4, SD_BOTH );
|
||||
UpnpCloseSocket( ssdpReqSock4 );
|
||||
shutdown( ssdpReqSock6, SD_BOTH );
|
||||
UpnpCloseSocket( ssdpReqSock6 );
|
||||
#endif
|
||||
|
||||
free( miniSock );
|
||||
@ -503,18 +556,22 @@ RunMiniServer( MiniServerSockArray *miniSock )
|
||||
static int
|
||||
get_port( int sockfd )
|
||||
{
|
||||
struct sockaddr_in sockinfo;
|
||||
struct sockaddr_storage sockinfo;
|
||||
socklen_t len;
|
||||
int code;
|
||||
int port;
|
||||
int port = 0;
|
||||
|
||||
len = sizeof( struct sockaddr_in );
|
||||
len = sizeof( sockinfo );
|
||||
code = getsockname( sockfd, ( struct sockaddr * )&sockinfo, &len );
|
||||
if( code == -1 ) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
port = ntohs( sockinfo.sin_port );
|
||||
if( sockinfo.ss_family == AF_INET ) {
|
||||
port = ntohs( ((struct sockaddr_in*)&sockinfo)->sin_port );
|
||||
} else if( sockinfo.ss_family == AF_INET6 ) {
|
||||
port = ntohs( ((struct sockaddr_in6*)&sockinfo)->sin6_port );
|
||||
}
|
||||
UpnpPrintf( UPNP_INFO, MSERV, __FILE__, __LINE__,
|
||||
"sockfd = %d, .... port = %d\n", sockfd, port );
|
||||
|
||||
@ -526,8 +583,10 @@ get_port( int sockfd )
|
||||
*
|
||||
* Parameters:
|
||||
* MiniServerSockArray *out - Socket Array
|
||||
* unsigned short listen_port - port on which the server is
|
||||
* listening for incoming connections
|
||||
* unsigned short listen_port4 - port on which the server is
|
||||
* listening for incoming IPv4 connections
|
||||
* unsigned short listen_port6 - port on which the server is
|
||||
* listening for incoming IPv6 connections
|
||||
*
|
||||
* Description:
|
||||
* Creates a STREAM socket, binds to INADDR_ANY and listens for
|
||||
@ -546,31 +605,47 @@ get_port( int sockfd )
|
||||
************************************************************************/
|
||||
int
|
||||
get_miniserver_sockets( MiniServerSockArray * out,
|
||||
unsigned short listen_port )
|
||||
unsigned short listen_port4,
|
||||
unsigned short listen_port6 )
|
||||
{
|
||||
char errorBuffer[ERROR_BUFFER_LEN];
|
||||
struct sockaddr_in serverAddr;
|
||||
int listenfd;
|
||||
int success;
|
||||
unsigned short actual_port;
|
||||
struct sockaddr_storage __ss_v4;
|
||||
struct sockaddr_storage __ss_v6;
|
||||
struct sockaddr_in* serverAddr4 = (struct sockaddr_in*)&__ss_v4;
|
||||
struct sockaddr_in6* serverAddr6 = (struct sockaddr_in6*)&__ss_v6;
|
||||
SOCKET listenfd4, listenfd6;
|
||||
int ret_code;
|
||||
unsigned short actual_port4, actual_port6;
|
||||
int reuseaddr_on = 0;
|
||||
int sockError = UPNP_E_SUCCESS;
|
||||
int errCode = 0;
|
||||
int miniServerStopSock;
|
||||
int ret = 0;
|
||||
|
||||
listenfd = socket( AF_INET, SOCK_STREAM, 0 );
|
||||
if ( listenfd == -1 ) {
|
||||
return UPNP_E_OUTOF_SOCKET; // error creating socket
|
||||
// Create listen socket for IPv4/IPv6. An error here may indicate
|
||||
// that we don't have an IPv4/IPv6 stack.
|
||||
listenfd4 = socket( AF_INET, SOCK_STREAM, 0 );
|
||||
listenfd6 = socket( AF_INET6, SOCK_STREAM, 0 );
|
||||
if (listenfd4 == INVALID_SOCKET || listenfd6 == INVALID_SOCKET) {
|
||||
return UPNP_E_OUTOF_SOCKET;
|
||||
}
|
||||
|
||||
// As per the IANA specifications for the use of ports by applications
|
||||
// override the listen port passed in with the first available
|
||||
if( listen_port < APPLICATION_LISTENING_PORT )
|
||||
listen_port = APPLICATION_LISTENING_PORT;
|
||||
if (listen_port4 < APPLICATION_LISTENING_PORT) {
|
||||
listen_port4 = APPLICATION_LISTENING_PORT;
|
||||
}
|
||||
if (listen_port6 < APPLICATION_LISTENING_PORT) {
|
||||
listen_port6 = APPLICATION_LISTENING_PORT;
|
||||
}
|
||||
|
||||
memset( &serverAddr, 0, sizeof( serverAddr ) );
|
||||
serverAddr.sin_family = AF_INET;
|
||||
serverAddr.sin_addr.s_addr = htonl( INADDR_ANY );
|
||||
memset( &__ss_v4, 0, sizeof( __ss_v4 ) );
|
||||
serverAddr4->sin_family = AF_INET;
|
||||
serverAddr4->sin_addr.s_addr = htonl( INADDR_ANY );
|
||||
|
||||
memset( &__ss_v6, 0, sizeof( __ss_v6 ) );
|
||||
serverAddr6->sin6_family = AF_INET6;
|
||||
serverAddr6->sin6_addr = in6addr_any;
|
||||
|
||||
// Getting away with implementation of re-using address:port and instead
|
||||
// choosing to increment port numbers.
|
||||
@ -583,95 +658,211 @@ get_miniserver_sockets( MiniServerSockArray * out,
|
||||
// THIS MAY CAUSE TCP TO BECOME LESS RELIABLE
|
||||
// HOWEVER IT HAS BEEN SUGESTED FOR TCP SERVERS
|
||||
UpnpPrintf( UPNP_INFO, MSERV, __FILE__, __LINE__,
|
||||
"mserv start: resuseaddr set\n" );
|
||||
sockError = setsockopt( listenfd, SOL_SOCKET, SO_REUSEADDR,
|
||||
(const char *)&reuseaddr_on, sizeof (int) );
|
||||
if ( sockError == -1 ) {
|
||||
shutdown( listenfd, SD_BOTH );
|
||||
UpnpCloseSocket( listenfd );
|
||||
"get_miniserver_sockets: resuseaddr set\n" );
|
||||
|
||||
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,
|
||||
sizeof (struct sockaddr_in) );
|
||||
} else {
|
||||
do {
|
||||
serverAddr.sin_port = htons( listen_port++ );
|
||||
sockError = bind( listenfd, (struct sockaddr *)&serverAddr,
|
||||
sizeof (struct sockaddr_in) );
|
||||
if( listenfd6 != INVALID_SOCKET ) {
|
||||
sockError = setsockopt( listenfd6, SOL_SOCKET, SO_REUSEADDR,
|
||||
(const char *)&reuseaddr_on, sizeof (int) );
|
||||
if ( sockError == -1 ) {
|
||||
shutdown( listenfd4, SD_BOTH );
|
||||
UpnpCloseSocket( listenfd4 );
|
||||
shutdown( listenfd6, SD_BOTH );
|
||||
UpnpCloseSocket( listenfd6 );
|
||||
|
||||
return UPNP_E_SOCKET_BIND;
|
||||
}
|
||||
|
||||
sockError = bind( listenfd6, (struct sockaddr *)&__ss_v6,
|
||||
sizeof(__ss_v6) );
|
||||
if ( sockError == -1 ) {
|
||||
strerror_r(errno, errorBuffer, ERROR_BUFFER_LEN);
|
||||
UpnpPrintf( UPNP_INFO, MSERV, __FILE__, __LINE__,
|
||||
"get_miniserver_sockets: Error in IPv6 bind(): %s\n",
|
||||
errorBuffer );
|
||||
shutdown( listenfd4, SD_BOTH );
|
||||
UpnpCloseSocket( listenfd4 );
|
||||
shutdown( listenfd6, SD_BOTH );
|
||||
UpnpCloseSocket( listenfd6 );
|
||||
|
||||
return UPNP_E_SOCKET_BIND; // bind failed
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if( listenfd4 != INVALID_SOCKET ) {
|
||||
do {
|
||||
serverAddr4->sin_port = htons( listen_port4++ );
|
||||
sockError = bind( listenfd4, (struct sockaddr *)&__ss_v4,
|
||||
sizeof(__ss_v4) );
|
||||
if ( sockError == -1 ) {
|
||||
#ifdef WIN32
|
||||
errCode = WSAGetLastError();
|
||||
errCode = WSAGetLastError();
|
||||
#else
|
||||
errCode = errno;
|
||||
errCode = errno;
|
||||
#endif
|
||||
if( errno == EADDRINUSE ) {
|
||||
errCode = 1;
|
||||
}
|
||||
} else
|
||||
errCode = 0;
|
||||
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 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 ) {
|
||||
strerror_r(errno, errorBuffer, ERROR_BUFFER_LEN);
|
||||
UpnpPrintf( UPNP_INFO, MSERV, __FILE__, __LINE__,
|
||||
"mserv start: Error in bind(): %s\n", errorBuffer );
|
||||
shutdown( listenfd, SD_BOTH );
|
||||
UpnpCloseSocket( listenfd );
|
||||
if( listenfd6 != INVALID_SOCKET ) {
|
||||
do {
|
||||
serverAddr4->sin_port = htons( listen_port6++ );
|
||||
sockError = bind( listenfd6, (struct sockaddr *)&__ss_v4,
|
||||
sizeof(__ss_v4) );
|
||||
if ( sockError == -1 ) {
|
||||
#ifdef WIN32
|
||||
errCode = WSAGetLastError();
|
||||
#else
|
||||
errCode = errno;
|
||||
#endif
|
||||
if( errno == EADDRINUSE ) {
|
||||
errCode = 1;
|
||||
}
|
||||
} else
|
||||
errCode = 0;
|
||||
} while ( errCode != 0 );
|
||||
if ( sockError == -1 ) {
|
||||
strerror_r(errno, errorBuffer, ERROR_BUFFER_LEN);
|
||||
UpnpPrintf( UPNP_INFO, MSERV, __FILE__, __LINE__,
|
||||
"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__,
|
||||
"mserv start: bind success\n" );
|
||||
"get_miniserver_sockets: bind successful\n" );
|
||||
|
||||
success = listen( listenfd, SOMAXCONN );
|
||||
if ( success == -1 ) {
|
||||
strerror_r(errno, errorBuffer, ERROR_BUFFER_LEN);
|
||||
UpnpPrintf( UPNP_INFO, MSERV, __FILE__, __LINE__,
|
||||
"mserv start: Error in listen(): %s\n", errorBuffer );
|
||||
shutdown( listenfd, SD_BOTH );
|
||||
UpnpCloseSocket( listenfd );
|
||||
if( listenfd4 != INVALID_SOCKET ) {
|
||||
ret_code = listen( listenfd4, SOMAXCONN );
|
||||
if ( ret_code == -1 ) {
|
||||
strerror_r(errno, errorBuffer, ERROR_BUFFER_LEN);
|
||||
UpnpPrintf( UPNP_INFO, MSERV, __FILE__, __LINE__,
|
||||
"mserv start: Error in IPv4 listen(): %s\n", errorBuffer );
|
||||
shutdown( listenfd4, SD_BOTH );
|
||||
UpnpCloseSocket( listenfd4 );
|
||||
shutdown( listenfd6, SD_BOTH );
|
||||
UpnpCloseSocket( listenfd6 );
|
||||
|
||||
return UPNP_E_LISTEN;
|
||||
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( actual_port <= 0 ) {
|
||||
shutdown( listenfd, SD_BOTH );
|
||||
UpnpCloseSocket( listenfd );
|
||||
if( listenfd6 != INVALID_SOCKET ) {
|
||||
ret_code = listen( listenfd6, SOMAXCONN );
|
||||
if ( ret_code == -1 ) {
|
||||
strerror_r(errno, errorBuffer, ERROR_BUFFER_LEN);
|
||||
UpnpPrintf( UPNP_INFO, MSERV, __FILE__, __LINE__,
|
||||
"mserv start: Error in IPv6 listen(): %s\n", errorBuffer );
|
||||
shutdown( listenfd4, SD_BOTH );
|
||||
UpnpCloseSocket( listenfd4 );
|
||||
shutdown( listenfd6, SD_BOTH );
|
||||
UpnpCloseSocket( listenfd6 );
|
||||
|
||||
return UPNP_E_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 );
|
||||
if ( miniServerStopSock == -1 ) {
|
||||
strerror_r(errno, errorBuffer, ERROR_BUFFER_LEN);
|
||||
UpnpPrintf( UPNP_CRITICAL, MSERV, __FILE__, __LINE__,
|
||||
"Error in socket(): %s\n", errorBuffer );
|
||||
shutdown( listenfd, SD_BOTH );
|
||||
UpnpCloseSocket( listenfd );
|
||||
shutdown( listenfd4, SD_BOTH );
|
||||
UpnpCloseSocket( listenfd4 );
|
||||
shutdown( listenfd6, SD_BOTH );
|
||||
UpnpCloseSocket( listenfd6 );
|
||||
|
||||
return UPNP_E_OUTOF_SOCKET;
|
||||
}
|
||||
|
||||
// bind to local socket
|
||||
memset( ( char * )&serverAddr, 0, sizeof( struct sockaddr_in ) );
|
||||
serverAddr.sin_family = AF_INET;
|
||||
serverAddr.sin_addr.s_addr = inet_addr( "127.0.0.1" );
|
||||
ret = bind( miniServerStopSock, (struct sockaddr *)&serverAddr,
|
||||
sizeof (serverAddr) );
|
||||
memset( &__ss_v4, 0, sizeof( __ss_v4 ) );
|
||||
serverAddr4->sin_family = AF_INET;
|
||||
serverAddr4->sin_addr.s_addr = inet_addr( "127.0.0.1" );
|
||||
ret = bind( miniServerStopSock, (struct sockaddr *)&__ss_v4,
|
||||
sizeof(__ss_v4) );
|
||||
if ( ret == -1 ) {
|
||||
UpnpPrintf( UPNP_CRITICAL,
|
||||
MSERV, __FILE__, __LINE__,
|
||||
"Error in binding localhost!!!\n" );
|
||||
shutdown( listenfd, SD_BOTH );
|
||||
UpnpCloseSocket( listenfd );
|
||||
shutdown( listenfd4, SD_BOTH );
|
||||
UpnpCloseSocket( listenfd4 );
|
||||
shutdown( listenfd6, SD_BOTH );
|
||||
UpnpCloseSocket( listenfd6 );
|
||||
shutdown( miniServerStopSock, SD_BOTH );
|
||||
UpnpCloseSocket( miniServerStopSock );
|
||||
|
||||
@ -682,14 +873,17 @@ get_miniserver_sockets( MiniServerSockArray * out,
|
||||
if ( miniStopSockPort <= 0 ) {
|
||||
shutdown( miniServerStopSock, SD_BOTH );
|
||||
UpnpCloseSocket( miniServerStopSock );
|
||||
shutdown( listenfd, SD_BOTH );
|
||||
UpnpCloseSocket( listenfd );
|
||||
shutdown( listenfd4, SD_BOTH );
|
||||
UpnpCloseSocket( listenfd4 );
|
||||
shutdown( listenfd6, SD_BOTH );
|
||||
UpnpCloseSocket( listenfd6 );
|
||||
|
||||
return UPNP_E_INTERNAL_ERROR;
|
||||
}
|
||||
|
||||
out->stopPort = miniStopSockPort;
|
||||
out->miniServerSock = listenfd;
|
||||
out->miniServerSock4 = listenfd4;
|
||||
out->miniServerSock6 = listenfd6;
|
||||
out->miniServerStopSock = miniServerStopSock;
|
||||
|
||||
return UPNP_E_SUCCESS;
|
||||
@ -698,27 +892,29 @@ get_miniserver_sockets( MiniServerSockArray * out,
|
||||
/************************************************************************
|
||||
* Function: StartMiniServer
|
||||
*
|
||||
* Parameters :
|
||||
* unsigned short listen_port - Port on which the server listens for
|
||||
* incoming connections
|
||||
* Parameters:
|
||||
* IN OUT unsigned short *listen_port4 ; Port on which the server
|
||||
* listens for incoming IPv4 connections.
|
||||
* IN OUT unsigned short *listen_port6 ; Port on which the server
|
||||
* listens for incoming IPv6 connections.
|
||||
*
|
||||
* Description:
|
||||
* Initialize the sockets functionality for the
|
||||
* Description: Initialize the sockets functionality for the
|
||||
* Miniserver. Initialize a thread pool job to run the MiniServer
|
||||
* and the job to the thread pool. If listen port is 0, port is
|
||||
* dynamically picked
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* Return: int
|
||||
* Actual port socket is bound to - On Success
|
||||
* A negative number UPNP_E_XXX - On Error
|
||||
* Return: int;
|
||||
* On success: UPNP_E_SUCCESS
|
||||
* On error: PNP_E_XXX
|
||||
************************************************************************/
|
||||
int
|
||||
StartMiniServer( unsigned short listen_port )
|
||||
StartMiniServer( unsigned short* listen_port4,
|
||||
unsigned short* listen_port6 )
|
||||
{
|
||||
int success;
|
||||
int ret_code;
|
||||
int count;
|
||||
int max_count = 10000;
|
||||
|
||||
@ -733,39 +929,48 @@ StartMiniServer( unsigned short listen_port )
|
||||
if( miniSocket == NULL ) {
|
||||
return UPNP_E_OUTOF_MEMORY;
|
||||
}
|
||||
memset( miniSocket, 0, sizeof(*miniSocket) );
|
||||
|
||||
success = get_miniserver_sockets( miniSocket, listen_port );
|
||||
if( success != UPNP_E_SUCCESS ) {
|
||||
ret_code = get_miniserver_sockets( miniSocket, *listen_port4, *listen_port6 );
|
||||
if( ret_code != UPNP_E_SUCCESS ) {
|
||||
free( miniSocket );
|
||||
return success;
|
||||
return ret_code;
|
||||
}
|
||||
|
||||
success = get_ssdp_sockets( miniSocket );
|
||||
if( success != UPNP_E_SUCCESS ) {
|
||||
shutdown( miniSocket->miniServerSock, SD_BOTH );
|
||||
UpnpCloseSocket( miniSocket->miniServerSock );
|
||||
ret_code = get_ssdp_sockets( miniSocket );
|
||||
if( ret_code != UPNP_E_SUCCESS ) {
|
||||
shutdown( miniSocket->miniServerSock4, SD_BOTH );
|
||||
UpnpCloseSocket( miniSocket->miniServerSock4 );
|
||||
shutdown( miniSocket->miniServerSock6, SD_BOTH );
|
||||
UpnpCloseSocket( miniSocket->miniServerSock6 );
|
||||
shutdown( miniSocket->miniServerStopSock, SD_BOTH );
|
||||
UpnpCloseSocket( miniSocket->miniServerStopSock );
|
||||
free( miniSocket );
|
||||
|
||||
return success;
|
||||
return ret_code;
|
||||
}
|
||||
|
||||
TPJobInit( &job, (start_routine)RunMiniServer, (void *)miniSocket );
|
||||
TPJobSetPriority( &job, MED_PRIORITY );
|
||||
TPJobSetFreeFunction( &job, ( free_routine ) free );
|
||||
|
||||
success = ThreadPoolAddPersistent( &gMiniServerThreadPool, &job, NULL );
|
||||
if ( success < 0 ) {
|
||||
shutdown( miniSocket->miniServerSock, SD_BOTH );
|
||||
UpnpCloseSocket( miniSocket->miniServerSock );
|
||||
ret_code = ThreadPoolAddPersistent( &gMiniServerThreadPool, &job, NULL );
|
||||
if ( ret_code < 0 ) {
|
||||
shutdown( miniSocket->miniServerSock4, SD_BOTH );
|
||||
UpnpCloseSocket( miniSocket->miniServerSock4 );
|
||||
shutdown( miniSocket->miniServerSock6, SD_BOTH );
|
||||
UpnpCloseSocket( miniSocket->miniServerSock6 );
|
||||
shutdown( miniSocket->miniServerStopSock, SD_BOTH );
|
||||
UpnpCloseSocket( miniSocket->miniServerStopSock );
|
||||
shutdown( miniSocket->ssdpSock, SD_BOTH );
|
||||
UpnpCloseSocket( miniSocket->ssdpSock );
|
||||
shutdown( miniSocket->ssdpSock4, SD_BOTH );
|
||||
UpnpCloseSocket( miniSocket->ssdpSock4 );
|
||||
shutdown( miniSocket->ssdpSock6, SD_BOTH );
|
||||
UpnpCloseSocket( miniSocket->ssdpSock6 );
|
||||
#ifdef INCLUDE_CLIENT_APIS
|
||||
shutdown( miniSocket->ssdpReqSock, SD_BOTH );
|
||||
UpnpCloseSocket( miniSocket->ssdpReqSock );
|
||||
shutdown( miniSocket->ssdpReqSock4, SD_BOTH );
|
||||
UpnpCloseSocket( miniSocket->ssdpReqSock4 );
|
||||
shutdown( miniSocket->ssdpReqSock6, SD_BOTH );
|
||||
UpnpCloseSocket( miniSocket->ssdpReqSock6 );
|
||||
#endif
|
||||
|
||||
return UPNP_E_OUTOF_MEMORY;
|
||||
@ -779,21 +984,29 @@ StartMiniServer( unsigned short listen_port )
|
||||
|
||||
// taking too long to start that thread
|
||||
if ( count >= max_count ) {
|
||||
shutdown( miniSocket->miniServerSock, SD_BOTH );
|
||||
UpnpCloseSocket( miniSocket->miniServerSock );
|
||||
shutdown( miniSocket->miniServerSock4, SD_BOTH );
|
||||
UpnpCloseSocket( miniSocket->miniServerSock4 );
|
||||
shutdown( miniSocket->miniServerSock6, SD_BOTH );
|
||||
UpnpCloseSocket( miniSocket->miniServerSock6 );
|
||||
shutdown( miniSocket->miniServerStopSock, SD_BOTH );
|
||||
UpnpCloseSocket( miniSocket->miniServerStopSock );
|
||||
shutdown( miniSocket->ssdpSock, SD_BOTH );
|
||||
UpnpCloseSocket( miniSocket->ssdpSock );
|
||||
shutdown( miniSocket->ssdpSock4, SD_BOTH );
|
||||
UpnpCloseSocket( miniSocket->ssdpSock4 );
|
||||
shutdown( miniSocket->ssdpSock6, SD_BOTH );
|
||||
UpnpCloseSocket( miniSocket->ssdpSock6 );
|
||||
#ifdef INCLUDE_CLIENT_APIS
|
||||
shutdown( miniSocket->ssdpReqSock, SD_BOTH );
|
||||
UpnpCloseSocket( miniSocket->ssdpReqSock );
|
||||
shutdown( miniSocket->ssdpReqSock4, SD_BOTH );
|
||||
UpnpCloseSocket( miniSocket->ssdpReqSock4 );
|
||||
shutdown( miniSocket->ssdpReqSock6, SD_BOTH );
|
||||
UpnpCloseSocket( miniSocket->ssdpReqSock6 );
|
||||
#endif
|
||||
|
||||
return UPNP_E_INTERNAL_ERROR;
|
||||
}
|
||||
*listen_port4 = miniSocket->miniServerPort4;
|
||||
*listen_port6 = miniSocket->miniServerPort6;
|
||||
|
||||
return miniSocket->miniServerPort;
|
||||
return UPNP_E_SUCCESS;
|
||||
}
|
||||
|
||||
/************************************************************************
|
||||
@ -814,7 +1027,7 @@ StopMiniServer()
|
||||
{
|
||||
char errorBuffer[ERROR_BUFFER_LEN];
|
||||
int socklen = sizeof( struct sockaddr_in );
|
||||
int sock;
|
||||
SOCKET sock;
|
||||
struct sockaddr_in ssdpAddr;
|
||||
char buf[256] = "ShutDown";
|
||||
int bufLen = strlen( buf );
|
||||
|
@ -175,13 +175,13 @@ http_Connect( IN uri_type * destination_url,
|
||||
|
||||
http_FixUrl( destination_url, url );
|
||||
|
||||
connfd = socket( AF_INET, SOCK_STREAM, 0 );
|
||||
connfd = socket( url->hostport.IPaddress.ss_family, SOCK_STREAM, 0 );
|
||||
if( connfd == -1 ) {
|
||||
return UPNP_E_OUTOF_SOCKET;
|
||||
}
|
||||
|
||||
if( connect( connfd, ( struct sockaddr * )&url->hostport.IPv4address,
|
||||
sizeof( struct sockaddr_in ) ) == -1 ) {
|
||||
if( connect( connfd, ( struct sockaddr * )&url->hostport.IPaddress,
|
||||
sizeof( url->hostport.IPaddress ) ) == -1 ) {
|
||||
#ifdef WIN32
|
||||
UpnpPrintf(UPNP_CRITICAL, HTTP, __FILE__, __LINE__,
|
||||
"connect error: %d\n", WSAGetLastError());
|
||||
@ -521,7 +521,7 @@ http_RequestAndResponse( IN uri_type * destination,
|
||||
int http_error_code;
|
||||
SOCKINFO info;
|
||||
|
||||
tcp_connection = socket( AF_INET, SOCK_STREAM, 0 );
|
||||
tcp_connection = socket( destination->hostport.IPaddress.ss_family, SOCK_STREAM, 0 );
|
||||
if( tcp_connection == -1 ) {
|
||||
parser_response_init( response, req_method );
|
||||
return UPNP_E_SOCKET_ERROR;
|
||||
@ -535,7 +535,7 @@ http_RequestAndResponse( IN uri_type * destination,
|
||||
// connect
|
||||
ret_code = connect( info.socket,
|
||||
( struct sockaddr * )&destination->hostport.
|
||||
IPv4address, sizeof( struct sockaddr_in ) );
|
||||
IPaddress, sizeof( struct sockaddr_storage ) );
|
||||
|
||||
if( ret_code == -1 ) {
|
||||
sock_destroy( &info, SD_BOTH );
|
||||
@ -1005,7 +1005,7 @@ http_OpenHttpPost( IN const char *url_str,
|
||||
|
||||
handle->contentLength = contentLength;
|
||||
|
||||
tcp_connection = socket( AF_INET, SOCK_STREAM, 0 );
|
||||
tcp_connection = socket( url.hostport.IPaddress.ss_family, SOCK_STREAM, 0 );
|
||||
if( tcp_connection == -1 ) {
|
||||
ret_code = UPNP_E_SOCKET_ERROR;
|
||||
goto errorHandler;
|
||||
@ -1019,8 +1019,8 @@ http_OpenHttpPost( IN const char *url_str,
|
||||
}
|
||||
|
||||
ret_code = connect( handle->sock_info.socket,
|
||||
( struct sockaddr * )&url.hostport.IPv4address,
|
||||
sizeof( struct sockaddr_in ) );
|
||||
( struct sockaddr * )&url.hostport.IPaddress,
|
||||
sizeof( struct sockaddr_storage ) );
|
||||
|
||||
if( ret_code == -1 ) {
|
||||
sock_destroy( &handle->sock_info, SD_BOTH );
|
||||
@ -1587,7 +1587,7 @@ http_OpenHttpGetProxy( IN const char *url_str,
|
||||
handle->cancel = 0;
|
||||
parser_response_init( &handle->response, HTTPMETHOD_GET );
|
||||
|
||||
tcp_connection = socket( AF_INET, SOCK_STREAM, 0 );
|
||||
tcp_connection = socket( peer->hostport.IPaddress.ss_family, SOCK_STREAM, 0 );
|
||||
if( tcp_connection == -1 ) {
|
||||
ret_code = UPNP_E_SOCKET_ERROR;
|
||||
goto errorHandler;
|
||||
@ -1601,8 +1601,8 @@ http_OpenHttpGetProxy( IN const char *url_str,
|
||||
}
|
||||
|
||||
ret_code = connect( handle->sock_info.socket,
|
||||
( struct sockaddr * )&peer->hostport.IPv4address,
|
||||
sizeof( struct sockaddr_in ) );
|
||||
( struct sockaddr * )&peer->hostport.IPaddress,
|
||||
sizeof( struct sockaddr_storage ) );
|
||||
|
||||
if( ret_code == -1 ) {
|
||||
sock_destroy( &handle->sock_info, SD_BOTH );
|
||||
@ -2236,7 +2236,7 @@ http_OpenHttpGetEx( IN const char *url_str,
|
||||
handle->entity_offset = 0;
|
||||
parser_response_init( &handle->response, HTTPMETHOD_GET );
|
||||
|
||||
tcp_connection = socket( AF_INET, SOCK_STREAM, 0 );
|
||||
tcp_connection = socket( url.hostport.IPaddress.ss_family, SOCK_STREAM, 0 );
|
||||
if( tcp_connection == -1 ) {
|
||||
errCode = UPNP_E_SOCKET_ERROR;
|
||||
free( handle );
|
||||
@ -2252,8 +2252,8 @@ http_OpenHttpGetEx( IN const char *url_str,
|
||||
}
|
||||
|
||||
errCode = connect( handle->sock_info.socket,
|
||||
( struct sockaddr * )&url.hostport.IPv4address,
|
||||
sizeof( struct sockaddr_in ) );
|
||||
( struct sockaddr * )&url.hostport.IPaddress,
|
||||
sizeof( struct sockaddr_storage ) );
|
||||
if( errCode == -1 ) {
|
||||
sock_destroy( &handle->sock_info, SD_BOTH );
|
||||
errCode = UPNP_E_SOCKET_CONNECT;
|
||||
|
@ -62,7 +62,7 @@
|
||||
*
|
||||
* Parameters :
|
||||
* OUT SOCKINFO* info ; Socket Information Object
|
||||
* IN int sockfd ; Socket Descriptor
|
||||
* IN SOCKET sockfd ; Socket Descriptor
|
||||
*
|
||||
* Description : Assign the passed in socket descriptor to socket
|
||||
* descriptor in the SOCKINFO structure.
|
||||
@ -76,7 +76,7 @@
|
||||
************************************************************************/
|
||||
int
|
||||
sock_init( OUT SOCKINFO * info,
|
||||
IN int sockfd )
|
||||
IN SOCKET sockfd )
|
||||
{
|
||||
assert( info );
|
||||
|
||||
@ -91,10 +91,9 @@ sock_init( OUT SOCKINFO * info,
|
||||
* Function : sock_init_with_ip
|
||||
*
|
||||
* Parameters :
|
||||
* OUT SOCKINFO* info ; Socket Information Object
|
||||
* IN int sockfd ; Socket Descriptor
|
||||
* IN struct in_addr foreign_ip_addr ; Remote IP Address
|
||||
* IN unsigned short foreign_ip_port ; Remote Port number
|
||||
* OUT SOCKINFO* info ; Socket Information Object
|
||||
* IN SOCKET sockfd ; Socket Descriptor
|
||||
* IN struct sockaddr* foreign_sockaddr; remote socket address.
|
||||
*
|
||||
* Description : Calls the sock_init function and assigns the passed in
|
||||
* IP address and port to the IP address and port in the SOCKINFO
|
||||
@ -109,9 +108,8 @@ sock_init( OUT SOCKINFO * info,
|
||||
************************************************************************/
|
||||
int
|
||||
sock_init_with_ip( OUT SOCKINFO * info,
|
||||
IN int sockfd,
|
||||
IN struct in_addr foreign_ip_addr,
|
||||
IN unsigned short foreign_ip_port )
|
||||
IN SOCKET sockfd,
|
||||
IN struct sockaddr* foreign_sockaddr )
|
||||
{
|
||||
int ret;
|
||||
|
||||
@ -120,8 +118,8 @@ sock_init_with_ip( OUT SOCKINFO * info,
|
||||
return ret;
|
||||
}
|
||||
|
||||
info->foreign_ip_addr = foreign_ip_addr;
|
||||
info->foreign_ip_port = foreign_ip_port;
|
||||
memcpy( &info->foreign_sockaddr, foreign_sockaddr,
|
||||
sizeof( info->foreign_sockaddr) );
|
||||
|
||||
return UPNP_E_SUCCESS;
|
||||
}
|
||||
@ -149,9 +147,11 @@ int
|
||||
sock_destroy( INOUT SOCKINFO * info,
|
||||
int ShutdownMethod )
|
||||
{
|
||||
shutdown( info->socket, ShutdownMethod );
|
||||
if( UpnpCloseSocket( info->socket ) == -1 ) {
|
||||
return UPNP_E_SOCKET_ERROR;
|
||||
if( info->socket != INVALID_SOCKET ) {
|
||||
shutdown( info->socket, ShutdownMethod );
|
||||
if( UpnpCloseSocket( info->socket ) == -1 ) {
|
||||
return UPNP_E_SOCKET_ERROR;
|
||||
}
|
||||
}
|
||||
|
||||
return UPNP_E_SUCCESS;
|
||||
@ -190,7 +190,7 @@ sock_read_write( IN SOCKINFO * info,
|
||||
struct timeval timeout;
|
||||
int numBytes;
|
||||
time_t start_time = time( NULL );
|
||||
int sockfd = info->socket;
|
||||
SOCKET sockfd = info->socket;
|
||||
long bytes_sent = 0,
|
||||
byte_left = 0,
|
||||
num_written;
|
||||
@ -202,9 +202,9 @@ sock_read_write( IN SOCKINFO * info,
|
||||
FD_ZERO( &readSet );
|
||||
FD_ZERO( &writeSet );
|
||||
if( bRead ) {
|
||||
FD_SET( ( unsigned )sockfd, &readSet );
|
||||
FD_SET( sockfd, &readSet );
|
||||
} else {
|
||||
FD_SET( ( unsigned )sockfd, &writeSet );
|
||||
FD_SET( sockfd, &writeSet );
|
||||
}
|
||||
|
||||
timeout.tv_sec = *timeoutSecs;
|
||||
|
@ -41,10 +41,7 @@
|
||||
#endif
|
||||
#include "config.h"
|
||||
#include "uri.h"
|
||||
|
||||
#ifdef WIN32
|
||||
#include "inet_pton.h"
|
||||
#endif
|
||||
#include "upnpapi.h"
|
||||
|
||||
|
||||
/************************************************************************
|
||||
@ -224,28 +221,6 @@ parse_uric( const char *in,
|
||||
return i;
|
||||
}
|
||||
|
||||
/************************************************************************
|
||||
* Function : copy_sockaddr_in
|
||||
*
|
||||
* Parameters :
|
||||
* const struct sockaddr_in *in ; Source socket address object
|
||||
* struct sockaddr_in *out ; Destination socket address object
|
||||
*
|
||||
* Description : Copies one socket address into another
|
||||
*
|
||||
* Return : void ;
|
||||
*
|
||||
* Note :
|
||||
************************************************************************/
|
||||
void
|
||||
copy_sockaddr_in( const struct sockaddr_in *in,
|
||||
struct sockaddr_in *out )
|
||||
{
|
||||
memset( out->sin_zero, 0, 8 );
|
||||
out->sin_family = in->sin_family;
|
||||
out->sin_port = in->sin_port;
|
||||
out->sin_addr.s_addr = in->sin_addr.s_addr;
|
||||
}
|
||||
|
||||
/************************************************************************
|
||||
* Function : copy_token
|
||||
@ -328,8 +303,9 @@ copy_URL_list( URL_list * in,
|
||||
in->URLs, &out->parsedURLs[i].hostport.text,
|
||||
out->URLs );
|
||||
|
||||
copy_sockaddr_in( &in->parsedURLs[i].hostport.IPv4address,
|
||||
&out->parsedURLs[i].hostport.IPv4address );
|
||||
memcpy( &out->parsedURLs[i].hostport.IPaddress,
|
||||
&in->parsedURLs[i].hostport.IPaddress,
|
||||
sizeof(struct sockaddr_storage) );
|
||||
}
|
||||
out->size = in->size;
|
||||
return HTTP_SUCCESS;
|
||||
@ -490,48 +466,13 @@ token_cmp( token * in1,
|
||||
return memcmp( in1->buff, in2->buff, in1->size );
|
||||
}
|
||||
|
||||
/************************************************************************
|
||||
* Function : parse_port
|
||||
*
|
||||
* Parameters :
|
||||
* int max ; sets a maximum limit
|
||||
* char * port ; port to be parsed.
|
||||
* unsigned short * out ; out parameter where the port is parsed
|
||||
* and converted into network format
|
||||
*
|
||||
* Description : parses a port (i.e. '4000') and converts it into a
|
||||
* network ordered unsigned short int.
|
||||
*
|
||||
* Return : int ;
|
||||
*
|
||||
* Note :
|
||||
************************************************************************/
|
||||
int
|
||||
parse_port( int max,
|
||||
const char *port,
|
||||
unsigned short *out )
|
||||
{
|
||||
|
||||
const char *finger = port;
|
||||
const char *max_ptr = finger + max;
|
||||
unsigned short temp = 0;
|
||||
|
||||
while( ( finger < max_ptr ) && ( isdigit( *finger ) ) ) {
|
||||
temp = temp * 10;
|
||||
temp += ( *finger ) - '0';
|
||||
finger++;
|
||||
}
|
||||
|
||||
*out = htons( temp );
|
||||
return finger - port;
|
||||
}
|
||||
|
||||
/************************************************************************
|
||||
* Function : parse_hostport
|
||||
*
|
||||
* Parameters :
|
||||
* char *in ; string of characters representing host and port
|
||||
* int max ; sets a maximum limit
|
||||
* int max ; sets a maximum limit (not used).
|
||||
* hostport_type *out ; out parameter where the host and port
|
||||
* are represented as an internet address
|
||||
*
|
||||
@ -540,7 +481,8 @@ parse_port( int max,
|
||||
* hostport_type struct with internet address and a token
|
||||
* representing the full host and port. uses gethostbyname.
|
||||
*
|
||||
* Return : int ;
|
||||
* Returns: The number of characters that form up the host and port.
|
||||
* UPNP_E_INVALID_URL on error.
|
||||
*
|
||||
* Note :
|
||||
************************************************************************/
|
||||
@ -549,165 +491,145 @@ parse_hostport( const char *in,
|
||||
int max,
|
||||
hostport_type * out )
|
||||
{
|
||||
#define BUFFER_SIZE 8192
|
||||
char workbuf[256];
|
||||
char* c;
|
||||
struct sockaddr_in* sai4 = (struct sockaddr_in*)&out->IPaddress;
|
||||
struct sockaddr_in6* sai6 = (struct sockaddr_in6*)&out->IPaddress;
|
||||
char *srvname = NULL;
|
||||
char *srvport = NULL;
|
||||
char *last_dot = NULL;
|
||||
unsigned short int port;
|
||||
int af = AF_UNSPEC;
|
||||
int hostport_size;
|
||||
int has_port = 0;
|
||||
int ret;
|
||||
|
||||
int i = 0;
|
||||
int begin_port;
|
||||
int hostport_size = 0;
|
||||
int host_size = 0;
|
||||
#if !defined(WIN32) && !(defined(__OSX__) || defined(__APPLE__))
|
||||
char temp_hostbyname_buff[BUFFER_SIZE];
|
||||
struct hostent h_buf;
|
||||
#endif
|
||||
struct hostent *h = NULL;
|
||||
int errcode = 0;
|
||||
char *temp_host_name = NULL;
|
||||
int last_dot = -1;
|
||||
memset( out, 0, sizeof(hostport_type) );
|
||||
|
||||
out->text.size = 0;
|
||||
out->text.buff = NULL;
|
||||
// Work on a copy of the input string.
|
||||
strncpy( workbuf, in, sizeof(workbuf) );
|
||||
|
||||
out->IPv4address.sin_port = htons( 80 ); //default port is 80
|
||||
memset( &out->IPv4address.sin_zero, 0, 8 );
|
||||
|
||||
while( ( i < max ) && ( in[i] != ':' ) && ( in[i] != '/' )
|
||||
&& ( ( isalnum( in[i] ) ) || ( in[i] == '.' )
|
||||
|| ( in[i] == '-' ) ) ) {
|
||||
i++;
|
||||
if( in[i] == '.' ) {
|
||||
last_dot = i;
|
||||
c = workbuf;
|
||||
if( *c == '[' ) {
|
||||
// IPv6 addresses are enclosed in square brackets.
|
||||
srvname = ++c;
|
||||
while( *c != '\0' && *c != ']' ) {
|
||||
c++;
|
||||
}
|
||||
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;
|
||||
}
|
||||
|
||||
host_size = i;
|
||||
|
||||
if( ( i < max ) && ( in[i] == ':' ) ) {
|
||||
begin_port = i + 1;
|
||||
//convert port
|
||||
if( !( hostport_size = parse_port( max - begin_port,
|
||||
&in[begin_port],
|
||||
&out->IPv4address.sin_port ) ) )
|
||||
{
|
||||
return UPNP_E_INVALID_URL;
|
||||
else {
|
||||
// IPv4 address -OR- host name.
|
||||
srvname = c;
|
||||
while( (*c != ':') && (*c != '/') && ( (isalnum(*c)) || (*c == '.') || (*c == '-') ) ) {
|
||||
if( *c == '.' )
|
||||
last_dot = c;
|
||||
c++;
|
||||
}
|
||||
hostport_size += begin_port;
|
||||
} else
|
||||
hostport_size = host_size;
|
||||
has_port = (*c == ':') ? 1 : 0;
|
||||
// NULL terminate the srvname
|
||||
*c = '\0';
|
||||
if( has_port == 1 )
|
||||
c++;
|
||||
|
||||
//convert to temporary null terminated string
|
||||
temp_host_name = ( char * )malloc( host_size + 1 );
|
||||
|
||||
if( temp_host_name == NULL )
|
||||
return UPNP_E_OUTOF_MEMORY;
|
||||
|
||||
memcpy( temp_host_name, in, host_size );
|
||||
temp_host_name[host_size] = '\0';
|
||||
|
||||
//check to see if host name is an ipv4 address
|
||||
if( ( last_dot != -1 ) && ( last_dot + 1 < host_size )
|
||||
&& ( isdigit( temp_host_name[last_dot + 1] ) ) ) {
|
||||
//must be ipv4 address
|
||||
|
||||
errcode = inet_pton( AF_INET,
|
||||
temp_host_name, &out->IPv4address.sin_addr );
|
||||
if( errcode == 1 ) {
|
||||
out->IPv4address.sin_family = AF_INET;
|
||||
} else {
|
||||
out->IPv4address.sin_addr.s_addr = 0;
|
||||
out->IPv4address.sin_family = AF_INET;
|
||||
free( temp_host_name );
|
||||
temp_host_name = NULL;
|
||||
return UPNP_E_INVALID_URL;
|
||||
if( last_dot != NULL && isdigit(*(last_dot+1)) ) {
|
||||
// Must be an IPv4 address.
|
||||
af = AF_INET;
|
||||
}
|
||||
} else {
|
||||
int errCode = 0;
|
||||
else {
|
||||
// Must be a host name.
|
||||
struct addrinfo hints, *res, *res0;
|
||||
|
||||
//call gethostbyname_r (reentrant form of gethostbyname)
|
||||
// TODO: Use autoconf to discover this rather than the
|
||||
// platform-specific stuff below
|
||||
#if defined(WIN32) || defined(__CYGWIN__)
|
||||
h = gethostbyname(temp_host_name);
|
||||
#elif defined(SPARC_SOLARIS)
|
||||
errCode = gethostbyname_r(
|
||||
temp_host_name,
|
||||
&h,
|
||||
temp_hostbyname_buff,
|
||||
BUFFER_SIZE, &errcode );
|
||||
#elif defined(__FreeBSD__) && __FreeBSD_version < 601103
|
||||
h = lwres_gethostbyname_r(
|
||||
temp_host_name,
|
||||
&h_buf,
|
||||
temp_hostbyname_buff,
|
||||
BUFFER_SIZE, &errcode );
|
||||
if ( h == NULL ) {
|
||||
errCode = 1;
|
||||
}
|
||||
#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;
|
||||
memset(&hints, 0, sizeof(hints));
|
||||
hints.ai_family = AF_UNSPEC;
|
||||
hints.ai_socktype = SOCK_STREAM;
|
||||
|
||||
h = NULL;
|
||||
memset(&hints, 0, sizeof(hints));
|
||||
hints.ai_family = PF_INET;
|
||||
hints.ai_socktype = SOCK_STREAM;
|
||||
errCode = getaddrinfo(temp_host_name, "http", &hints, &res0);
|
||||
|
||||
if (!errCode) {
|
||||
for (res = res0; res; res = res->ai_next) {
|
||||
if (res->ai_family == PF_INET &&
|
||||
res->ai_addr->sa_family == AF_INET)
|
||||
{
|
||||
h = &h_buf;
|
||||
h->h_addrtype = res->ai_addr->sa_family;
|
||||
h->h_length = 4;
|
||||
h->h_addr = (void *) temp_hostbyname_buff;
|
||||
*(struct in_addr *)h->h_addr =
|
||||
((struct sockaddr_in *)res->ai_addr)->sin_addr;
|
||||
ret = getaddrinfo(srvname, NULL, &hints, &res0);
|
||||
if( ret == 0 ) {
|
||||
for (res = res0; res; res = res->ai_next) {
|
||||
if( res->ai_family == AF_INET ||
|
||||
res->ai_family == AF_INET6 ) {
|
||||
// Found a valid IPv4 or IPv6 address.
|
||||
memcpy( &out->IPaddress, res->ai_addr,
|
||||
res->ai_addrlen );
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
freeaddrinfo(res0);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
if( errCode == 0 ) {
|
||||
if( h ) {
|
||||
if( ( h->h_addrtype == AF_INET ) && ( h->h_length == 4 ) ) {
|
||||
out->IPv4address.sin_addr =
|
||||
( *( struct in_addr * )h->h_addr );
|
||||
out->IPv4address.sin_family = AF_INET;
|
||||
freeaddrinfo(res0);
|
||||
|
||||
if( res == NULL ) {
|
||||
// Didn't find an AF_INET or AF_INET6 address.
|
||||
return UPNP_E_INVALID_URL;
|
||||
}
|
||||
}
|
||||
} 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 {
|
||||
// getaddrinfo failed.
|
||||
return UPNP_E_INVALID_URL;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if( temp_host_name ) {
|
||||
free( temp_host_name );
|
||||
temp_host_name = NULL;
|
||||
// Check if a port is specified.
|
||||
if( has_port == 1 ) {
|
||||
// Port is specified.
|
||||
srvport = c;
|
||||
while( *c != '\0' && isdigit(*c) ) {
|
||||
c++;
|
||||
}
|
||||
port = (unsigned short int)atoi(srvport);
|
||||
if( port == 0 ) {
|
||||
// Bad port number.
|
||||
return UPNP_E_INVALID_URL;
|
||||
}
|
||||
}
|
||||
else {
|
||||
// Port was not specified, use default port.
|
||||
port = 80;
|
||||
}
|
||||
|
||||
// The length of the host and port string can be calculated by
|
||||
// subtracting pointers.
|
||||
hostport_size = (int)(c - workbuf);
|
||||
|
||||
// Fill in the 'out' information.
|
||||
if( af == AF_INET ) {
|
||||
sai4->sin_family = AF_INET;
|
||||
sai4->sin_port = htons(port);
|
||||
ret = inet_pton(AF_INET, srvname, &sai4->sin_addr);
|
||||
}
|
||||
else if( af == AF_INET6 ) {
|
||||
sai6->sin6_family = AF_INET6;
|
||||
sai6->sin6_port = htons(port);
|
||||
sai6->sin6_scope_id = gIF_INDEX;
|
||||
ret = inet_pton(AF_INET6, srvname, &sai6->sin6_addr);
|
||||
} else {
|
||||
// IP address was set by the hostname (getaddrinfo).
|
||||
// Override port:
|
||||
if( out->IPaddress.ss_family == AF_INET )
|
||||
sai4->sin_port = htons(port);
|
||||
else
|
||||
sai6->sin6_port = htons(port);
|
||||
ret = 1;
|
||||
}
|
||||
|
||||
// Check if address was converted successfully.
|
||||
if( ret <= 0 ) {
|
||||
return UPNP_E_INVALID_URL;
|
||||
}
|
||||
|
||||
out->text.size = hostport_size;
|
||||
out->text.buff = in;
|
||||
return hostport_size;
|
||||
|
||||
}
|
||||
|
||||
/************************************************************************
|
||||
@ -1069,10 +991,7 @@ parse_uri( const char *in,
|
||||
return begin_path;
|
||||
|
||||
} else {
|
||||
out->hostport.IPv4address.sin_port = 0;
|
||||
out->hostport.IPv4address.sin_addr.s_addr = 0;
|
||||
out->hostport.text.size = 0;
|
||||
out->hostport.text.buff = 0;
|
||||
memset( &out->hostport, 0, sizeof(out->hostport) );
|
||||
begin_path = begin_hostport;
|
||||
}
|
||||
|
||||
|
@ -106,7 +106,7 @@ typedef struct TOKEN {
|
||||
//the full string representation
|
||||
typedef struct HOSTPORT {
|
||||
token text; //full host port
|
||||
struct sockaddr_in IPv4address; //Network Byte Order
|
||||
struct sockaddr_storage IPaddress; //Network Byte Order
|
||||
} hostport_type;
|
||||
|
||||
//Represents a URI
|
||||
|
@ -42,17 +42,21 @@ extern SOCKET gMiniServerStopSock;
|
||||
|
||||
typedef struct MServerSockArray {
|
||||
/* socket for listening for miniserver requests */
|
||||
int miniServerSock;
|
||||
SOCKET miniServerSock4;
|
||||
SOCKET miniServerSock6;
|
||||
/* socket for stopping miniserver */
|
||||
int miniServerStopSock;
|
||||
SOCKET miniServerStopSock;
|
||||
/* socket for incoming advertisments and search requests */
|
||||
int ssdpSock;
|
||||
SOCKET ssdpSock4;
|
||||
SOCKET ssdpSock6;
|
||||
|
||||
int stopPort;
|
||||
int miniServerPort;
|
||||
SOCKET stopPort;
|
||||
SOCKET miniServerPort4;
|
||||
SOCKET miniServerPort6;
|
||||
|
||||
/* socket for sending search requests and receiving search replies */
|
||||
CLIENTONLY(int ssdpReqSock;)
|
||||
CLIENTONLY(SOCKET ssdpReqSock4;)
|
||||
CLIENTONLY(SOCKET ssdpReqSock6;)
|
||||
} MiniServerSockArray;
|
||||
|
||||
|
||||
@ -110,8 +114,10 @@ void SetGenaCallback( MiniServerCallback callback );
|
||||
* Function: StartMiniServer
|
||||
*
|
||||
* Parameters:
|
||||
* unsigned short listen_port ; Port on which the server listens for
|
||||
* incoming connections
|
||||
* IN OUT unsigned short *listen_port4 ; Port on which the server
|
||||
* listens for incoming IPv4 connections.
|
||||
* IN OUT unsigned short *listen_port6 ; Port on which the server
|
||||
* listens for incoming IPv6 connections.
|
||||
*
|
||||
* Description: Initialize the sockets functionality for the
|
||||
* Miniserver. Initialize a thread pool job to run the MiniServer
|
||||
@ -122,10 +128,11 @@ void SetGenaCallback( MiniServerCallback callback );
|
||||
* allowed delay aborts the attempt to launch the MiniServer.
|
||||
*
|
||||
* Return: int;
|
||||
* Actual port socket is bound to - On Success:
|
||||
* A negative number UPNP_E_XXX - On Error
|
||||
* On success: UPNP_E_SUCCESS
|
||||
* On error: UPNP_E_XXX
|
||||
************************************************************************/
|
||||
int StartMiniServer( unsigned short listen_port );
|
||||
int StartMiniServer( IN OUT unsigned short* listen_port4,
|
||||
IN OUT unsigned short* listen_port6 );
|
||||
|
||||
/************************************************************************
|
||||
* Function: StopMiniServer
|
||||
|
@ -48,11 +48,10 @@
|
||||
|
||||
typedef struct
|
||||
{
|
||||
int socket; // handle/descriptor to a socket
|
||||
SOCKET socket; // handle/descriptor to a socket
|
||||
|
||||
// the following two fields are filled only in incoming requests;
|
||||
struct in_addr foreign_ip_addr;
|
||||
unsigned short foreign_ip_port;
|
||||
struct sockaddr_storage foreign_sockaddr;
|
||||
|
||||
} SOCKINFO;
|
||||
|
||||
@ -65,7 +64,7 @@ typedef struct
|
||||
*
|
||||
* Parameters :
|
||||
* OUT SOCKINFO* info ; Socket Information Object
|
||||
* IN int sockfd ; Socket Descriptor
|
||||
* IN SOCKET sockfd ; Socket Descriptor
|
||||
*
|
||||
* Description : Assign the passed in socket descriptor to socket
|
||||
* descriptor in the SOCKINFO structure.
|
||||
@ -76,16 +75,15 @@ typedef struct
|
||||
* UPNP_E_SOCKET_ERROR
|
||||
* Note :
|
||||
************************************************************************/
|
||||
int sock_init( OUT SOCKINFO* info, IN int sockfd );
|
||||
int sock_init(OUT SOCKINFO* info, IN SOCKET sockfd);
|
||||
|
||||
/************************************************************************
|
||||
* Function : sock_init_with_ip
|
||||
*
|
||||
* Parameters :
|
||||
* OUT SOCKINFO* info ; Socket Information Object
|
||||
* IN int sockfd ; Socket Descriptor
|
||||
* IN struct in_addr foreign_ip_addr ; Remote IP Address
|
||||
* IN unsigned short foreign_ip_port ; Remote Port number
|
||||
* OUT SOCKINFO* info ; Socket Information Object
|
||||
* IN SOCKET sockfd ; Socket Descriptor
|
||||
* IN struct sockaddr* foreign_sockaddr; Remote socket address
|
||||
*
|
||||
* Description : Calls the sock_init function and assigns the passed in
|
||||
* IP address and port to the IP address and port in the SOCKINFO
|
||||
@ -98,8 +96,10 @@ int sock_init( OUT SOCKINFO* info, IN int sockfd );
|
||||
*
|
||||
* Note :
|
||||
************************************************************************/
|
||||
int sock_init_with_ip( OUT SOCKINFO* info, IN int sockfd,
|
||||
IN struct in_addr foreign_ip_addr, IN unsigned short foreign_ip_port );
|
||||
int sock_init_with_ip(
|
||||
OUT SOCKINFO* info,
|
||||
IN SOCKET sockfd,
|
||||
IN struct sockaddr *foreign_sockaddr);
|
||||
|
||||
/************************************************************************
|
||||
* Function : sock_read
|
||||
@ -162,7 +162,7 @@ int sock_write( IN SOCKINFO *info, IN char* buffer, IN size_t bufsize,
|
||||
*
|
||||
* Note :
|
||||
************************************************************************/
|
||||
int sock_destroy( INOUT SOCKINFO* info,int );
|
||||
int sock_destroy(INOUT SOCKINFO* info, int);
|
||||
|
||||
#ifdef __cplusplus
|
||||
} // #extern "C"
|
||||
|
@ -78,6 +78,7 @@ typedef enum SsdpCmdType{SSDP_ERROR=-1,
|
||||
//Constant
|
||||
#define BUFSIZE 2500
|
||||
#define SSDP_IP "239.255.255.250"
|
||||
#define SSDP_IPV6_LINKLOCAL "FF02::C"
|
||||
#define SSDP_PORT 1900
|
||||
#define NUM_TRY 3
|
||||
#define NUM_COPY 1
|
||||
@ -121,7 +122,7 @@ typedef struct SsdpEventStruct
|
||||
char Os[LINE_SIZE];
|
||||
char Ext[LINE_SIZE];
|
||||
char Date[LINE_SIZE];
|
||||
struct sockaddr_in * DestAddr;
|
||||
struct sockaddr *DestAddr;
|
||||
void * Cookie;
|
||||
} Event;
|
||||
|
||||
@ -134,7 +135,7 @@ typedef struct TData
|
||||
int Mx;
|
||||
void * Cookie;
|
||||
char * Data;
|
||||
struct sockaddr_in DestAddr;
|
||||
struct sockaddr_storage DestAddr;
|
||||
|
||||
}ThreadData;
|
||||
|
||||
@ -142,7 +143,7 @@ typedef struct ssdpsearchreply
|
||||
{
|
||||
int MaxAge;
|
||||
UpnpDevice_Handle handle;
|
||||
struct sockaddr_in dest_addr;
|
||||
struct sockaddr_storage dest_addr;
|
||||
SsdpEvent event;
|
||||
|
||||
}SsdpSearchReply;
|
||||
@ -159,13 +160,14 @@ typedef struct ssdpsearcharg
|
||||
typedef struct
|
||||
{
|
||||
http_parser_t parser;
|
||||
struct sockaddr_in dest_addr;
|
||||
struct sockaddr_storage dest_addr;
|
||||
} ssdp_thread_data;
|
||||
|
||||
|
||||
/* globals */
|
||||
|
||||
CLIENTONLY(extern SOCKET gSsdpReqSocket;);
|
||||
CLIENTONLY(extern SOCKET gSsdpReqSocket4;);
|
||||
CLIENTONLY(extern SOCKET gSsdpReqSocket6;);
|
||||
|
||||
typedef int (*ParserFun)(char *, Event *);
|
||||
|
||||
@ -205,11 +207,11 @@ int Make_Socket_NoBlocking (int sock);
|
||||
#ifdef INCLUDE_DEVICE_APIS
|
||||
void ssdp_handle_device_request(
|
||||
IN http_message_t* hmsg,
|
||||
IN struct sockaddr_in* dest_addr );
|
||||
IN struct sockaddr* dest_addr );
|
||||
#else
|
||||
static inline void ssdp_handle_device_request(
|
||||
IN http_message_t* hmsg,
|
||||
IN struct sockaddr_in* dest_addr ) {}
|
||||
IN struct sockaddr* dest_addr ) {}
|
||||
#endif
|
||||
|
||||
/************************************************************************
|
||||
@ -217,7 +219,7 @@ static inline void ssdp_handle_device_request(
|
||||
*
|
||||
* Parameters:
|
||||
* IN http_message_t* hmsg: SSDP message from the device
|
||||
* IN struct sockaddr_in* dest_addr: Address of the device
|
||||
* IN struct sockaddr* dest_addr: Address of the device
|
||||
* IN xboolean timeout: timeout kept by the control point while sending
|
||||
* search message
|
||||
* IN void* cookie: Cookie stored by the control point application.
|
||||
@ -234,7 +236,7 @@ static inline void ssdp_handle_device_request(
|
||||
***************************************************************************/
|
||||
void ssdp_handle_ctrlpt_msg(
|
||||
IN http_message_t* hmsg,
|
||||
IN struct sockaddr_in* dest_addr,
|
||||
IN struct sockaddr* dest_addr,
|
||||
IN xboolean timeout,
|
||||
IN void* cookie );
|
||||
|
||||
@ -347,6 +349,7 @@ int SearchByTarget(IN int Mx, IN char *St, IN void *Cookie);
|
||||
* IN char *Udn :
|
||||
* IN char *Location: Location URL.
|
||||
* IN int Duration : Service duration in sec.
|
||||
* IN int AddressFamily: Device address family.
|
||||
*
|
||||
* Description:
|
||||
* This function creates the device advertisement request based on
|
||||
@ -360,7 +363,8 @@ int DeviceAdvertisement(
|
||||
IN int RootDev,
|
||||
IN char *Udn,
|
||||
IN char *Location,
|
||||
IN int Duration);
|
||||
IN int Duration,
|
||||
IN int AddressFamily);
|
||||
|
||||
|
||||
/************************************************************************
|
||||
@ -373,6 +377,7 @@ int DeviceAdvertisement(
|
||||
* IN char *_Server:
|
||||
* IN char *Location: Location URL
|
||||
* IN int Duration :Device duration in sec.
|
||||
* IN int AddressFamily: Device address family.
|
||||
*
|
||||
* Description:
|
||||
* This function creates a HTTP device shutdown request packet
|
||||
@ -387,13 +392,14 @@ int DeviceShutdown(
|
||||
IN char *Udn,
|
||||
IN char *_Server,
|
||||
IN char *Location,
|
||||
IN int Duration);
|
||||
IN int Duration,
|
||||
IN int AddressFamily);
|
||||
|
||||
/************************************************************************
|
||||
* Function : DeviceReply
|
||||
*
|
||||
* Parameters:
|
||||
* IN struct sockaddr_in * DestAddr:destination IP address.
|
||||
* IN struct sockaddr *DestAddr: destination IP address.
|
||||
* IN char *DevType: Device type
|
||||
* IN int RootDev: 1 means root device 0 means embedded device.
|
||||
* IN char *Udn: Device UDN
|
||||
@ -408,17 +414,18 @@ int DeviceShutdown(
|
||||
* UPNP_E_SUCCESS if successful else appropriate error
|
||||
***************************************************************************/
|
||||
int DeviceReply(
|
||||
IN struct sockaddr_in * DestAddr,
|
||||
IN struct sockaddr *DestAddr,
|
||||
IN char *DevType,
|
||||
IN int RootDev,
|
||||
IN char *Udn,
|
||||
IN char *Location, IN int Duration);
|
||||
IN char *Location,
|
||||
IN int Duration);
|
||||
|
||||
/************************************************************************
|
||||
* Function : SendReply
|
||||
*
|
||||
* Parameters:
|
||||
* IN struct sockaddr_in * DestAddr:destination IP address.
|
||||
* IN struct sockaddr *DestAddr: destination IP address.
|
||||
* IN char *DevType: Device type
|
||||
* IN int RootDev: 1 means root device 0 means embedded device.
|
||||
* IN char * Udn: Device UDN
|
||||
@ -435,7 +442,7 @@ int DeviceReply(
|
||||
* UPNP_E_SUCCESS if successful else appropriate error
|
||||
***************************************************************************/
|
||||
int SendReply(
|
||||
IN struct sockaddr_in * DestAddr,
|
||||
IN struct sockaddr *DestAddr,
|
||||
IN char *DevType,
|
||||
IN int RootDev,
|
||||
IN char *Udn,
|
||||
@ -450,7 +457,8 @@ int SendReply(
|
||||
* IN char * Udn: Device UDN
|
||||
* IN char *ServType: Service Type.
|
||||
* IN char * Location: Location of Device description document.
|
||||
* IN int Duration :Life time of this device.
|
||||
* IN int Duration: Life time of this device.
|
||||
* IN int AddressFamily: Device address family
|
||||
*
|
||||
* Description:
|
||||
* This function creates the advertisement packet based
|
||||
@ -463,13 +471,14 @@ int ServiceAdvertisement(
|
||||
IN char *Udn,
|
||||
IN char *ServType,
|
||||
IN char *Location,
|
||||
IN int Duration);
|
||||
IN int Duration,
|
||||
IN int AddressFamily);
|
||||
|
||||
/************************************************************************
|
||||
* Function : ServiceReply
|
||||
*
|
||||
* Parameters:
|
||||
* IN struct sockaddr_in *DestAddr:
|
||||
* IN struct sockaddr *DestAddr:
|
||||
* IN char *Udn: Device UDN
|
||||
* IN char *ServType: Service Type.
|
||||
* IN char *Server: Not used
|
||||
@ -484,7 +493,7 @@ int ServiceAdvertisement(
|
||||
* UPNP_E_SUCCESS if successful else appropriate error
|
||||
***************************************************************************/
|
||||
int ServiceReply(
|
||||
IN struct sockaddr_in *DestAddr,
|
||||
IN struct sockaddr *DestAddr,
|
||||
IN char *ServType,
|
||||
IN char *Udn,
|
||||
IN char *Location,
|
||||
@ -498,6 +507,7 @@ int ServiceReply(
|
||||
* IN char *ServType: Service Type.
|
||||
* IN char *Location: Location of Device description document.
|
||||
* IN int Duration :Service duration in sec.
|
||||
* IN int AddressFamily: Device address family
|
||||
*
|
||||
* Description:
|
||||
* This function creates a HTTP service shutdown request packet
|
||||
@ -510,7 +520,8 @@ int ServiceShutdown(
|
||||
IN char *Udn,
|
||||
IN char *ServType,
|
||||
IN char *Location,
|
||||
IN int Duration);
|
||||
IN int Duration,
|
||||
IN int AddressFamily);
|
||||
|
||||
|
||||
/************************************************************************
|
||||
@ -537,7 +548,7 @@ void *advertiseAndReplyThread(IN void * data);
|
||||
* 1 = Send Advertisement
|
||||
* IN UpnpDevice_Handle Hnd: Device handle
|
||||
* IN enum SsdpSearchType SearchType:Search type for sending replies
|
||||
* IN struct sockaddr_in *DestAddr:Destination address
|
||||
* IN struct sockaddr *DestAddr:Destination address
|
||||
* IN char *DeviceType:Device type
|
||||
* IN char *DeviceUDN:Device UDN
|
||||
* IN char *ServiceType:Service type
|
||||
@ -553,10 +564,9 @@ int AdvertiseAndReply(
|
||||
IN int AdFlag,
|
||||
IN UpnpDevice_Handle Hnd,
|
||||
IN enum SsdpSearchType SearchType,
|
||||
IN struct sockaddr_in *DestAddr,
|
||||
IN struct sockaddr *DestAddr,
|
||||
IN char *DeviceType,
|
||||
IN char *DeviceUDN,
|
||||
IN char *ServiceType, int Exp);
|
||||
|
||||
#endif
|
||||
|
||||
|
@ -84,11 +84,12 @@ struct Handle_Info
|
||||
//URL information
|
||||
int MaxSubscriptions;
|
||||
int MaxSubscriptionTimeOut;
|
||||
int DeviceAf; // Address family: AF_INET or AF_INET6
|
||||
#endif
|
||||
|
||||
// Client only
|
||||
#ifdef INCLUDE_CLIENT_APIS
|
||||
ClientSubscription *ClientSubList; //client subscription list
|
||||
ClientSubscription *ClientSubList; // client subscription list
|
||||
LinkedList SsdpSearchList; // active ssdp searches
|
||||
#endif
|
||||
int aliasInstalled; // 0 = not installed; otherwise installed
|
||||
@ -116,13 +117,20 @@ Upnp_Handle_Type GetHandleInfo(int Hnd, struct Handle_Info **HndInfo);
|
||||
|
||||
Upnp_Handle_Type GetClientHandleInfo(int *client_handle_out,
|
||||
struct Handle_Info **HndInfo);
|
||||
Upnp_Handle_Type GetDeviceHandleInfo(int *device_handle_out,
|
||||
struct Handle_Info **HndInfo);
|
||||
Upnp_Handle_Type GetDeviceHandleInfo( const int AddressFamily,
|
||||
int *device_handle_out,
|
||||
struct Handle_Info **HndInfo);
|
||||
|
||||
|
||||
extern char LOCAL_HOST[LINE_SIZE];
|
||||
extern char gIF_NAME[LINE_SIZE];
|
||||
extern char gIF_IPV4[22]; // INET_ADDRSTRLEN
|
||||
extern char gIF_IPV6[65]; // INET6_ADDRSTRLEN
|
||||
extern int gIF_INDEX;
|
||||
|
||||
extern unsigned short LOCAL_PORT;
|
||||
extern unsigned short LOCAL_PORT_V4;
|
||||
extern unsigned short LOCAL_PORT_V6;
|
||||
|
||||
extern Upnp_SID gUpnpSdkNLSuuid; // NLS uuid.
|
||||
|
||||
extern TimerThread gTimerThread;
|
||||
extern ThreadPool gRecvThreadPool;
|
||||
@ -170,6 +178,14 @@ typedef enum { WEB_SERVER_DISABLED, WEB_SERVER_ENABLED } WebServerState;
|
||||
|
||||
#define E_HTTP_SYNTAX -6
|
||||
|
||||
#ifdef WIN32
|
||||
int WinsockInit();
|
||||
#endif
|
||||
int UpnpInitPreamble();
|
||||
int UpnpInitMutexes();
|
||||
int UpnpInitThreadPools();
|
||||
int UpnpInitStartServers(unsigned short DestPort);
|
||||
int UpnpGetIfInfo(const char *IfName);
|
||||
void InitHandleList();
|
||||
int GetFreeHandle();
|
||||
int FreeHandle(int Handle);
|
||||
@ -177,7 +193,7 @@ void UpnpThreadDistribution(struct UpnpNonblockParam * Param);
|
||||
|
||||
|
||||
void AutoAdvertise(void *input);
|
||||
int getlocalhostname(char *out);
|
||||
int getlocalhostname(char *out, const int out_len);
|
||||
|
||||
extern WebServerState bWebServerState;
|
||||
|
||||
|
@ -95,7 +95,7 @@ typedef struct TOKEN {
|
||||
* text is a token pointing to the full string representation */
|
||||
typedef struct HOSTPORT {
|
||||
token text; //full host port
|
||||
struct sockaddr_in IPv4address; //Network Byte Order
|
||||
struct sockaddr_storage IPaddress; //Network Byte Order
|
||||
} hostport_type;
|
||||
|
||||
/* Represents a URI used in parse_uri and elsewhere */
|
||||
|
@ -50,13 +50,13 @@ extern "C" {
|
||||
*
|
||||
* Parameters :
|
||||
* INOUT IXML_Document *doc ; IXML Description document
|
||||
* IN const struct sockaddr_in* serverAddr ; socket address object
|
||||
* providing the IP address and port information
|
||||
* IN const char* alias ; string containing the alias
|
||||
* IN const struct sockaddr *serverAddr; socket address object
|
||||
* providing the IP address and port information
|
||||
* IN const char* alias ; string containing the alias
|
||||
* IN time_t last_modified ; time when the XML document was
|
||||
* downloaded
|
||||
* downloaded
|
||||
* OUT char docURL[LINE_SIZE] ; buffer to hold the URL of the
|
||||
* document.
|
||||
* document.
|
||||
*
|
||||
* Description : Configure the full URL for the description document.
|
||||
* Create the URL document and add alias, description information.
|
||||
@ -70,10 +70,10 @@ extern "C" {
|
||||
* Note :
|
||||
****************************************************************************/
|
||||
int configure_urlbase( INOUT IXML_Document *doc,
|
||||
IN const struct sockaddr_in* serverAddr,
|
||||
IN const char* alias,
|
||||
IN const struct sockaddr* serverAddr,
|
||||
IN const char* alias,
|
||||
IN time_t last_modified,
|
||||
OUT char docURL[LINE_SIZE] );
|
||||
OUT char docURL[LINE_SIZE]);
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
@ -81,4 +81,3 @@ int configure_urlbase( INOUT IXML_Document *doc,
|
||||
#endif
|
||||
|
||||
#endif /* URLCONFIG_H */
|
||||
|
||||
|
@ -592,6 +592,7 @@ static int
|
||||
get_device_info( IN http_message_t *request,
|
||||
IN int isQuery,
|
||||
IN IXML_Document *actionDoc,
|
||||
IN int AddressFamily,
|
||||
OUT UpnpString *device_udn,
|
||||
OUT UpnpString *service_id,
|
||||
OUT Upnp_FunPtr *callback,
|
||||
@ -612,7 +613,8 @@ get_device_info( IN http_message_t *request,
|
||||
|
||||
HandleLock();
|
||||
|
||||
if( GetDeviceHandleInfo( &device_hnd, &device_info ) != HND_DEVICE ) {
|
||||
if( GetDeviceHandleInfo( AddressFamily,
|
||||
&device_hnd, &device_info ) != HND_DEVICE ) {
|
||||
goto error_handler;
|
||||
}
|
||||
|
||||
@ -843,10 +845,10 @@ error_handler:
|
||||
*
|
||||
* Note :
|
||||
****************************************************************************/
|
||||
static UPNP_INLINE void
|
||||
handle_query_variable( IN SOCKINFO * info,
|
||||
IN http_message_t * request,
|
||||
IN IXML_Document * xml_doc )
|
||||
static UPNP_INLINE void handle_query_variable(
|
||||
IN SOCKINFO *info,
|
||||
IN http_message_t *request,
|
||||
IN IXML_Document *xml_doc )
|
||||
{
|
||||
UpnpStateVarRequest *variable = UpnpStateVarRequest_new();
|
||||
Upnp_FunPtr soap_event_callback;
|
||||
@ -864,6 +866,7 @@ handle_query_variable( IN SOCKINFO * info,
|
||||
// get info for event
|
||||
err_code = get_device_info(
|
||||
request, 1, xml_doc,
|
||||
info->foreign_sockaddr.ss_family,
|
||||
(UpnpString *)UpnpStateVarRequest_get_DevUDN(variable),
|
||||
(UpnpString *)UpnpStateVarRequest_get_ServiceID(variable),
|
||||
&soap_event_callback,
|
||||
@ -876,7 +879,7 @@ handle_query_variable( IN SOCKINFO * info,
|
||||
|
||||
UpnpStateVarRequest_set_ErrCode(variable, UPNP_E_SUCCESS);
|
||||
UpnpStateVarRequest_strcpy_StateVarName(variable, var_name);
|
||||
UpnpStateVarRequest_set_CtrlPtIPAddr(variable, &info->foreign_ip_addr);
|
||||
UpnpStateVarRequest_set_CtrlPtIPAddr(variable, &info->foreign_sockaddr);
|
||||
|
||||
// send event
|
||||
soap_event_callback( UPNP_CONTROL_GET_VAR_REQUEST, variable, cookie );
|
||||
@ -960,6 +963,7 @@ handle_invoke_action( IN SOCKINFO * info,
|
||||
request,
|
||||
0,
|
||||
xml_doc,
|
||||
info->foreign_sockaddr.ss_family,
|
||||
devUDN,
|
||||
serviceID,
|
||||
&soap_event_callback,
|
||||
@ -975,7 +979,7 @@ handle_invoke_action( IN SOCKINFO * info,
|
||||
UpnpActionRequest_set_DevUDN(action, devUDN);
|
||||
UpnpActionRequest_set_ServiceID(action, serviceID);
|
||||
UpnpActionRequest_set_ActionRequest(action, actionRequestDoc);
|
||||
UpnpActionRequest_set_CtrlPtIPAddr(action, &info->foreign_ip_addr);
|
||||
UpnpActionRequest_set_CtrlPtIPAddr(action, &info->foreign_sockaddr);
|
||||
|
||||
UpnpPrintf(UPNP_INFO, SOAP, __FILE__, __LINE__, "Calling Callback\n");
|
||||
|
||||
|
@ -80,7 +80,7 @@ void send_search_result(IN void *data)
|
||||
* Parameters:
|
||||
* IN http_message_t *hmsg:
|
||||
* SSDP message from the device
|
||||
* IN struct sockaddr_in *dest_addr:
|
||||
* IN struct sockaddr *dest_addr:
|
||||
* Address of the device
|
||||
* IN xboolean timeout:
|
||||
* timeout kept by the control point while
|
||||
@ -100,9 +100,9 @@ void send_search_result(IN void *data)
|
||||
***************************************************************************/
|
||||
void ssdp_handle_ctrlpt_msg(
|
||||
IN http_message_t *hmsg,
|
||||
IN struct sockaddr_in *dest_addr,
|
||||
IN struct sockaddr *dest_addr,
|
||||
IN xboolean timeout, // only in search reply
|
||||
IN void *cookie ) // only in search reply
|
||||
IN void *cookie) // only in search reply
|
||||
{
|
||||
int handle;
|
||||
struct Handle_Info *ctrlpt_info = NULL;
|
||||
@ -336,50 +336,6 @@ end_ssdp_handle_ctrlpt_msg:
|
||||
UpnpDiscovery_delete(param);
|
||||
}
|
||||
|
||||
/************************************************************************
|
||||
* Function : process_reply
|
||||
*
|
||||
* Parameters:
|
||||
* IN char* request_buf: the response came from the device
|
||||
* IN int buf_len: The length of the response buffer
|
||||
* IN struct sockaddr_in* dest_addr: The address of the device
|
||||
* IN void *cookie : cookie passed by the control point application
|
||||
* at the time of sending search message
|
||||
*
|
||||
* Description:
|
||||
* This function processes reply recevied from a search
|
||||
*
|
||||
* Returns: void
|
||||
*
|
||||
***************************************************************************/
|
||||
#ifndef WIN32
|
||||
#warning There are currently no uses of the function 'process_reply()' in the code.
|
||||
#warning 'process_reply()' is a candidate for removal.
|
||||
#else
|
||||
#pragma message("There are currently no uses of the function 'process_reply()' in the code.")
|
||||
#pragma message("'process_reply()' is a candidate for removal.")
|
||||
#endif
|
||||
static UPNP_INLINE void
|
||||
process_reply( IN char *request_buf,
|
||||
IN int buf_len,
|
||||
IN struct sockaddr_in *dest_addr,
|
||||
IN void *cookie )
|
||||
{
|
||||
http_parser_t parser;
|
||||
|
||||
parser_response_init( &parser, HTTPMETHOD_MSEARCH );
|
||||
|
||||
// parse
|
||||
if( parser_append( &parser, request_buf, buf_len ) != PARSE_SUCCESS ) {
|
||||
httpmsg_destroy( &parser.msg );
|
||||
return;
|
||||
}
|
||||
// handle reply
|
||||
ssdp_handle_ctrlpt_msg( &parser.msg, dest_addr, FALSE, cookie );
|
||||
|
||||
// done
|
||||
httpmsg_destroy( &parser.msg );
|
||||
}
|
||||
|
||||
/************************************************************************
|
||||
* Function : CreateClientRequestPacket
|
||||
@ -389,6 +345,7 @@ process_reply( IN char *request_buf,
|
||||
* IN char *SearchTarget:Search Target
|
||||
* IN int Mx dest_addr: Number of seconds to wait to
|
||||
* collect all the responses
|
||||
* IN int AddressFamily: search address family
|
||||
*
|
||||
* Description:
|
||||
* This function creates a HTTP search request packet
|
||||
@ -400,13 +357,18 @@ process_reply( IN char *request_buf,
|
||||
static void
|
||||
CreateClientRequestPacket( IN char *RqstBuf,
|
||||
IN int Mx,
|
||||
IN char *SearchTarget )
|
||||
IN char *SearchTarget,
|
||||
IN int AddressFamily )
|
||||
{
|
||||
char TempBuf[COMMAND_LEN];
|
||||
|
||||
strcpy( RqstBuf, "M-SEARCH * HTTP/1.1\r\n" );
|
||||
|
||||
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, "MAN: \"ssdp:discover\"\r\n" );
|
||||
|
||||
@ -495,7 +457,17 @@ searchExpired( void *arg )
|
||||
* This cokie will be returned to application in the callback.
|
||||
*
|
||||
* Description:
|
||||
* This function creates and send the search request for a specific URL.
|
||||
* This function implements the search request of the discovery phase.
|
||||
* A M-SEARCH request is sent on the SSDP channel for both IPv4 and
|
||||
* IPv6 addresses. The search target(ST) is required and must be one of
|
||||
* the following:
|
||||
* - "ssdp:all" : Search for all devices and services.
|
||||
* - "ssdp:rootdevice" : Search for root devices only.
|
||||
* - "uuid:<device-uuid>" : Search for a particular device.
|
||||
* - "urn:schemas-upnp-org:device:<deviceType:v>"
|
||||
* - "urn:schemas-upnp-org:service:<serviceType:v>"
|
||||
* - "urn:<domain-name>:device:<deviceType:v>"
|
||||
* - "urn:<domain-name>:service:<serviceType:v>"
|
||||
*
|
||||
* Returns: int
|
||||
* 1 if successful else appropriate error
|
||||
@ -506,18 +478,23 @@ SearchByTarget( IN int Mx,
|
||||
IN void *Cookie )
|
||||
{
|
||||
char errorBuffer[ERROR_BUFFER_LEN];
|
||||
int socklen = sizeof( struct sockaddr_in );
|
||||
int socklen = sizeof( struct sockaddr_storage );
|
||||
int *id = NULL;
|
||||
int ret = 0;
|
||||
char *ReqBuf;
|
||||
struct sockaddr_in destAddr;
|
||||
char ReqBufv4[BUFSIZE];
|
||||
char ReqBufv6[BUFSIZE];
|
||||
struct sockaddr_storage __ss_v4;
|
||||
struct sockaddr_storage __ss_v6;
|
||||
struct sockaddr_in* destAddr4 = (struct sockaddr_in*)&__ss_v4;
|
||||
struct sockaddr_in6* destAddr6 = (struct sockaddr_in6*)&__ss_v6;
|
||||
fd_set wrSet;
|
||||
SsdpSearchArg *newArg = NULL;
|
||||
int timeTillRead = 0;
|
||||
int handle;
|
||||
struct Handle_Info *ctrlpt_info = NULL;
|
||||
enum SsdpSearchType requestType;
|
||||
unsigned long addr = inet_addr( LOCAL_HOST );
|
||||
unsigned long addrv4 = inet_addr( gIF_IPV4 );
|
||||
int max_fd = 0;
|
||||
|
||||
//ThreadData *ThData;
|
||||
ThreadPoolJob job;
|
||||
@ -527,12 +504,7 @@ SearchByTarget( IN int Mx,
|
||||
return UPNP_E_INVALID_PARAM;
|
||||
}
|
||||
|
||||
ReqBuf = (char *)malloc( BUFSIZE );
|
||||
if( ReqBuf == NULL ) {
|
||||
return UPNP_E_OUTOF_MEMORY;
|
||||
}
|
||||
|
||||
UpnpPrintf(UPNP_INFO, SSDP, __FILE__, __LINE__, ">>> SSDP SEND >>>\n");
|
||||
UpnpPrintf(UPNP_INFO, SSDP, __FILE__, __LINE__, "Inside SearchByTarget\n");
|
||||
|
||||
timeTillRead = Mx;
|
||||
|
||||
@ -542,21 +514,24 @@ SearchByTarget( IN int Mx,
|
||||
timeTillRead = MAX_SEARCH_TIME;
|
||||
}
|
||||
|
||||
CreateClientRequestPacket( ReqBuf, timeTillRead, St );
|
||||
memset( ( char * )&destAddr, 0, sizeof( struct sockaddr_in ) );
|
||||
CreateClientRequestPacket( ReqBufv4, timeTillRead, St, AF_INET );
|
||||
CreateClientRequestPacket( ReqBufv6, timeTillRead, St, AF_INET6 );
|
||||
|
||||
destAddr.sin_family = AF_INET;
|
||||
destAddr.sin_addr.s_addr = inet_addr( SSDP_IP );
|
||||
destAddr.sin_port = htons( SSDP_PORT );
|
||||
memset( &__ss_v4, 0, sizeof( __ss_v4 ) );
|
||||
destAddr4->sin_family = AF_INET;
|
||||
inet_pton( AF_INET, SSDP_IP, &destAddr4->sin_addr );
|
||||
destAddr4->sin_port = htons( SSDP_PORT );
|
||||
|
||||
FD_ZERO( &wrSet );
|
||||
FD_SET( gSsdpReqSocket, &wrSet );
|
||||
memset( &__ss_v6, 0, sizeof( __ss_v6 ) );
|
||||
destAddr6->sin6_family = AF_INET6;
|
||||
inet_pton( AF_INET6, SSDP_IPV6_LINKLOCAL, &destAddr6->sin6_addr );
|
||||
destAddr6->sin6_port = htons( SSDP_PORT );
|
||||
destAddr6->sin6_scope_id = gIF_INDEX;
|
||||
|
||||
// add search criteria to list
|
||||
HandleLock();
|
||||
if( GetClientHandleInfo( &handle, &ctrlpt_info ) != HND_CLIENT ) {
|
||||
HandleUnlock();
|
||||
free( ReqBuf );
|
||||
return UPNP_E_INTERNAL_ERROR;
|
||||
}
|
||||
|
||||
@ -578,34 +553,56 @@ SearchByTarget( IN int Mx,
|
||||
ListAddTail( &ctrlpt_info->SsdpSearchList, newArg );
|
||||
HandleUnlock();
|
||||
|
||||
ret = setsockopt( gSsdpReqSocket, IPPROTO_IP, IP_MULTICAST_IF,
|
||||
(char *)&addr, sizeof (addr) );
|
||||
FD_ZERO( &wrSet );
|
||||
if( gSsdpReqSocket4 != INVALID_SOCKET ) {
|
||||
setsockopt( gSsdpReqSocket4, IPPROTO_IP, IP_MULTICAST_IF,
|
||||
(char *)&addrv4, sizeof (addrv4) );
|
||||
FD_SET( gSsdpReqSocket4, &wrSet );
|
||||
max_fd = max(max_fd, gSsdpReqSocket4);
|
||||
}
|
||||
if( gSsdpReqSocket6 != INVALID_SOCKET ) {
|
||||
setsockopt( gSsdpReqSocket6, IPPROTO_IPV6, IPV6_MULTICAST_IF,
|
||||
(char *)&gIF_INDEX, sizeof(gIF_INDEX) );
|
||||
FD_SET( gSsdpReqSocket6, &wrSet );
|
||||
max_fd = max(max_fd, gSsdpReqSocket6);
|
||||
}
|
||||
|
||||
ret = select( gSsdpReqSocket + 1, NULL, &wrSet, NULL, NULL );
|
||||
ret = select( max_fd + 1, NULL, &wrSet, NULL, NULL );
|
||||
if( ret == -1 ) {
|
||||
strerror_r(errno, errorBuffer, ERROR_BUFFER_LEN);
|
||||
UpnpPrintf( UPNP_INFO, SSDP, __FILE__, __LINE__,
|
||||
"SSDP_LIB: Error in select(): %s\n",
|
||||
errorBuffer );
|
||||
shutdown( gSsdpReqSocket, SD_BOTH );
|
||||
UpnpCloseSocket( gSsdpReqSocket );
|
||||
free( ReqBuf );
|
||||
shutdown( gSsdpReqSocket4, SD_BOTH );
|
||||
UpnpCloseSocket( gSsdpReqSocket4 );
|
||||
shutdown( gSsdpReqSocket6, SD_BOTH );
|
||||
UpnpCloseSocket( gSsdpReqSocket6 );
|
||||
|
||||
return UPNP_E_INTERNAL_ERROR;
|
||||
} else if( FD_ISSET( gSsdpReqSocket, &wrSet ) ) {
|
||||
}
|
||||
if( gSsdpReqSocket6 != INVALID_SOCKET &&
|
||||
FD_ISSET( gSsdpReqSocket6, &wrSet ) ) {
|
||||
int NumCopy = 0;
|
||||
while( NumCopy < NUM_SSDP_COPY ) {
|
||||
sendto( gSsdpReqSocket, ReqBuf, strlen( ReqBuf ), 0,
|
||||
(struct sockaddr *)&destAddr, socklen );
|
||||
sendto( gSsdpReqSocket6, ReqBufv6, strlen( ReqBufv6 ), 0,
|
||||
(struct sockaddr *)&__ss_v6, socklen );
|
||||
NumCopy++;
|
||||
imillisleep( SSDP_PAUSE );
|
||||
}
|
||||
}
|
||||
if( gSsdpReqSocket4 != INVALID_SOCKET &&
|
||||
FD_ISSET( gSsdpReqSocket4, &wrSet ) ) {
|
||||
int NumCopy = 0;
|
||||
while( NumCopy < NUM_SSDP_COPY ) {
|
||||
sendto( gSsdpReqSocket4, ReqBufv4, strlen( ReqBufv4 ), 0,
|
||||
(struct sockaddr *)&__ss_v4, socklen );
|
||||
NumCopy++;
|
||||
imillisleep( SSDP_PAUSE );
|
||||
}
|
||||
}
|
||||
|
||||
free( ReqBuf );
|
||||
return 1;
|
||||
}
|
||||
|
||||
#endif // EXCLUDE_SSDP
|
||||
#endif // INCLUDE_CLIENT_APIS
|
||||
|
||||
|
@ -75,7 +75,7 @@ advertiseAndReplyThread( IN void *data )
|
||||
|
||||
AdvertiseAndReply( 0, arg->handle,
|
||||
arg->event.RequestType,
|
||||
&arg->dest_addr,
|
||||
(struct sockaddr*)&arg->dest_addr,
|
||||
arg->event.DeviceType,
|
||||
arg->event.UDN,
|
||||
arg->event.ServiceType, arg->MaxAge );
|
||||
@ -88,8 +88,8 @@ advertiseAndReplyThread( IN void *data )
|
||||
* Function : ssdp_handle_device_request
|
||||
*
|
||||
* Parameters:
|
||||
* IN http_message_t* hmsg: SSDP search request from the control point
|
||||
* IN struct sockaddr_in* dest_addr: The address info of control point
|
||||
* IN http_message_t *hmsg: SSDP search request from the control point
|
||||
* IN struct sockaddr *dest_addr: The address info of control point
|
||||
*
|
||||
* Description:
|
||||
* This function handles the search request. It do the sanity checks of
|
||||
@ -101,8 +101,8 @@ advertiseAndReplyThread( IN void *data )
|
||||
***************************************************************************/
|
||||
#ifdef INCLUDE_DEVICE_APIS
|
||||
void
|
||||
ssdp_handle_device_request( IN http_message_t * hmsg,
|
||||
IN struct sockaddr_in *dest_addr )
|
||||
ssdp_handle_device_request( IN http_message_t *hmsg,
|
||||
IN struct sockaddr *dest_addr )
|
||||
{
|
||||
#define MX_FUDGE_FACTOR 10
|
||||
|
||||
@ -142,7 +142,8 @@ ssdp_handle_device_request( IN http_message_t * hmsg,
|
||||
|
||||
HandleLock();
|
||||
// device info
|
||||
if( GetDeviceHandleInfo( &handle, &dev_info ) != HND_DEVICE ) {
|
||||
if( GetDeviceHandleInfo( dest_addr->sa_family,
|
||||
&handle, &dev_info ) != HND_DEVICE ) {
|
||||
HandleUnlock();
|
||||
return; // no info found
|
||||
}
|
||||
@ -170,7 +171,7 @@ ssdp_handle_device_request( IN http_message_t * hmsg,
|
||||
return;
|
||||
}
|
||||
threadArg->handle = handle;
|
||||
threadArg->dest_addr = ( *dest_addr );
|
||||
memcpy( &threadArg->dest_addr, dest_addr, sizeof(threadArg->dest_addr) );
|
||||
threadArg->event = event;
|
||||
threadArg->MaxAge = maxAge;
|
||||
|
||||
@ -201,7 +202,7 @@ ssdp_handle_device_request( IN http_message_t * hmsg,
|
||||
* Function : NewRequestHandler
|
||||
*
|
||||
* Parameters:
|
||||
* IN struct sockaddr_in * DestAddr: Ip address, to send the reply.
|
||||
* IN struct sockaddr *DestAddr: Ip address, to send the reply.
|
||||
* IN int NumPacket: Number of packet to be sent.
|
||||
* IN char **RqPacket:Number of packet to be sent.
|
||||
*
|
||||
@ -213,19 +214,21 @@ ssdp_handle_device_request( IN http_message_t * hmsg,
|
||||
* 1 if successful else appropriate error
|
||||
***************************************************************************/
|
||||
static int
|
||||
NewRequestHandler( IN struct sockaddr_in *DestAddr,
|
||||
NewRequestHandler( IN struct sockaddr *DestAddr,
|
||||
IN int NumPacket,
|
||||
IN char **RqPacket )
|
||||
{
|
||||
char errorBuffer[ERROR_BUFFER_LEN];
|
||||
int ReplySock;
|
||||
int socklen = sizeof( struct sockaddr_in );
|
||||
SOCKET ReplySock;
|
||||
int socklen = sizeof( struct sockaddr_storage );
|
||||
int NumCopy;
|
||||
int Index;
|
||||
unsigned long replyAddr = inet_addr( LOCAL_HOST );
|
||||
unsigned long replyAddr = inet_addr( gIF_IPV4 );
|
||||
int ttl = 4; // a/c to UPNP Spec
|
||||
int hops = 1;
|
||||
char buf_ntop[64];
|
||||
|
||||
ReplySock = socket( AF_INET, SOCK_DGRAM, 0 );
|
||||
ReplySock = socket( DestAddr->sa_family, SOCK_DGRAM, 0 );
|
||||
if ( ReplySock == -1 ) {
|
||||
strerror_r(errno, errorBuffer, ERROR_BUFFER_LEN);
|
||||
UpnpPrintf( UPNP_INFO, SSDP, __FILE__, __LINE__,
|
||||
@ -234,11 +237,25 @@ NewRequestHandler( IN struct sockaddr_in *DestAddr,
|
||||
|
||||
return UPNP_E_OUTOF_SOCKET;
|
||||
}
|
||||
|
||||
setsockopt( ReplySock, IPPROTO_IP, IP_MULTICAST_IF,
|
||||
(char *)&replyAddr, sizeof (replyAddr) );
|
||||
setsockopt( ReplySock, IPPROTO_IP, IP_MULTICAST_TTL,
|
||||
(char *)&ttl, sizeof (int) );
|
||||
|
||||
if( DestAddr->sa_family == AF_INET ) {
|
||||
inet_ntop(AF_INET, &((struct sockaddr_in*)DestAddr)->sin_addr,
|
||||
buf_ntop, sizeof(buf_ntop));
|
||||
setsockopt( ReplySock, IPPROTO_IP, IP_MULTICAST_IF,
|
||||
(char *)&replyAddr, sizeof (replyAddr) );
|
||||
setsockopt( ReplySock, IPPROTO_IP, IP_MULTICAST_TTL,
|
||||
(char *)&ttl, sizeof (int) );
|
||||
} else if( DestAddr->sa_family == AF_INET6 ) {
|
||||
inet_ntop(AF_INET6, &((struct sockaddr_in6*)DestAddr)->sin6_addr,
|
||||
buf_ntop, sizeof(buf_ntop));
|
||||
setsockopt( ReplySock, IPPROTO_IPV6, IPV6_MULTICAST_IF,
|
||||
(char *)&gIF_INDEX, sizeof(gIF_INDEX) );
|
||||
setsockopt( ReplySock, IPPROTO_IPV6, IPV6_MULTICAST_HOPS,
|
||||
(char *)&hops, sizeof(hops) );
|
||||
} else {
|
||||
UpnpPrintf( UPNP_CRITICAL, SSDP, __FILE__, __LINE__,
|
||||
"Invalid destination address specified." );
|
||||
}
|
||||
|
||||
for( Index = 0; Index < NumPacket; Index++ ) {
|
||||
int rc;
|
||||
@ -256,11 +273,11 @@ NewRequestHandler( IN struct sockaddr_in *DestAddr,
|
||||
NumCopy = 0;
|
||||
while( NumCopy < NUM_COPY ) {
|
||||
UpnpPrintf( UPNP_INFO, SSDP, __FILE__, __LINE__,
|
||||
">>> SSDP SEND >>>\n%s\n",
|
||||
*( RqPacket + Index ) );
|
||||
">>> SSDP SEND to %s >>>\n%s\n",
|
||||
buf_ntop, *( RqPacket + Index ) );
|
||||
rc = sendto( ReplySock, *( RqPacket + Index ),
|
||||
strlen( *( RqPacket + Index ) ),
|
||||
0, ( struct sockaddr * )DestAddr, socklen );
|
||||
0, DestAddr, socklen );
|
||||
imillisleep( SSDP_PAUSE );
|
||||
++NumCopy;
|
||||
}
|
||||
@ -283,6 +300,7 @@ NewRequestHandler( IN struct sockaddr_in *DestAddr,
|
||||
* IN char * location :Location URL.
|
||||
* IN int duration :Service duration in sec.
|
||||
* OUT char** packet :Output buffer filled with HTTP statement.
|
||||
* IN int AddressFamily: Address family of the HTTP request.
|
||||
*
|
||||
* Description:
|
||||
* This function creates a HTTP request packet. Depending
|
||||
@ -298,7 +316,8 @@ CreateServicePacket( IN int msg_type,
|
||||
IN char *usn,
|
||||
IN char *location,
|
||||
IN int duration,
|
||||
OUT char **packet )
|
||||
OUT char **packet,
|
||||
IN int AddressFamily)
|
||||
{
|
||||
int ret_code;
|
||||
char *nts;
|
||||
@ -315,11 +334,13 @@ CreateServicePacket( IN int msg_type,
|
||||
if( msg_type == MSGTYPE_REPLY ) {
|
||||
ret_code = http_MakeMessage(
|
||||
&buf, 1, 1,
|
||||
"R" "sdc" "D" "sc" "ssc" "S" "Xc" "ssc" "sscc",
|
||||
"R" "sdc" "D" "sc" "ssc" "ssc" "ssc" "S" "Xc" "ssc" "sscc",
|
||||
HTTP_OK,
|
||||
"CACHE-CONTROL: max-age=", duration,
|
||||
"EXT:",
|
||||
"LOCATION: ", location,
|
||||
"OPT: ", "\"http://schemas.upnp.org/upnp/1/0/\"; ns=01",
|
||||
"01-NLS: ", gUpnpSdkNLSuuid,
|
||||
X_USER_AGENT,
|
||||
"ST: ", nt,
|
||||
"USN: ", usn);
|
||||
@ -337,14 +358,18 @@ CreateServicePacket( IN int msg_type,
|
||||
|
||||
// NOTE: The CACHE-CONTROL and LOCATION headers are not present in
|
||||
// a shutdown msg, but are present here for MS WinMe interop.
|
||||
|
||||
|
||||
ret_code = http_MakeMessage(
|
||||
&buf, 1, 1,
|
||||
"Q" "sssdc" "sdc" "ssc" "ssc" "ssc" "S" "Xc" "sscc",
|
||||
"Q" "sssdc" "sdc" "ssc" "ssc" "ssc" "ssc" "ssc" "S" "Xc" "sscc",
|
||||
HTTPMETHOD_NOTIFY, "*", (size_t)1,
|
||||
"HOST: ", SSDP_IP, ":", SSDP_PORT,
|
||||
"HOST: ",
|
||||
(AddressFamily==AF_INET) ? SSDP_IP : "[" SSDP_IPV6_LINKLOCAL "]",
|
||||
":", SSDP_PORT,
|
||||
"CACHE-CONTROL: max-age=", duration,
|
||||
"LOCATION: ", location,
|
||||
"OPT: ", "\"http://schemas.upnp.org/upnp/1/0/\"; ns=01",
|
||||
"01-NLS: ", gUpnpSdkNLSuuid,
|
||||
"NT: ", nt,
|
||||
"NTS: ", nts,
|
||||
X_USER_AGENT,
|
||||
@ -387,9 +412,12 @@ DeviceAdvertisement( IN char *DevType,
|
||||
int RootDev,
|
||||
char *Udn,
|
||||
IN char *Location,
|
||||
IN int Duration )
|
||||
IN int Duration,
|
||||
IN int AddressFamily)
|
||||
{
|
||||
struct sockaddr_in DestAddr;
|
||||
struct sockaddr_storage __ss;
|
||||
struct sockaddr_in* DestAddr4 = (struct sockaddr_in*)&__ss;
|
||||
struct sockaddr_in6* DestAddr6 = (struct sockaddr_in6*)&__ss;
|
||||
|
||||
//char Mil_Nt[LINE_SIZE]
|
||||
char Mil_Usn[LINE_SIZE];
|
||||
@ -397,11 +425,22 @@ DeviceAdvertisement( IN char *DevType,
|
||||
int ret_code;
|
||||
|
||||
UpnpPrintf( UPNP_INFO, SSDP, __FILE__, __LINE__,
|
||||
"In function SendDeviceAdvertisemenrt\n" );
|
||||
"In function DeviceAdvertisement\n" );
|
||||
|
||||
DestAddr.sin_family = AF_INET;
|
||||
DestAddr.sin_addr.s_addr = inet_addr( SSDP_IP );
|
||||
DestAddr.sin_port = htons( SSDP_PORT );
|
||||
memset( &__ss, 0, sizeof(__ss) );
|
||||
if( AddressFamily == AF_INET ) {
|
||||
DestAddr4->sin_family = AF_INET;
|
||||
inet_pton( AF_INET, SSDP_IP, &DestAddr4->sin_addr );
|
||||
DestAddr4->sin_port = htons( SSDP_PORT );
|
||||
} else if( AddressFamily == AF_INET6 ) {
|
||||
DestAddr6->sin6_family = AF_INET6;
|
||||
inet_pton( AF_INET6, SSDP_IPV6_LINKLOCAL, &DestAddr6->sin6_addr );
|
||||
DestAddr6->sin6_port = htons( SSDP_PORT );
|
||||
DestAddr6->sin6_scope_id = gIF_INDEX;
|
||||
} else {
|
||||
UpnpPrintf( UPNP_CRITICAL, SSDP, __FILE__, __LINE__,
|
||||
"Invalid device address family.\n" );
|
||||
}
|
||||
|
||||
msgs[0] = NULL;
|
||||
msgs[1] = NULL;
|
||||
@ -412,17 +451,17 @@ DeviceAdvertisement( IN char *DevType,
|
||||
if( RootDev ) {
|
||||
sprintf( Mil_Usn, "%s::upnp:rootdevice", Udn );
|
||||
CreateServicePacket( MSGTYPE_ADVERTISEMENT, "upnp:rootdevice",
|
||||
Mil_Usn, Location, Duration, &msgs[0] );
|
||||
Mil_Usn, Location, Duration, &msgs[0], AddressFamily );
|
||||
}
|
||||
// both root and sub-devices need to send these two messages
|
||||
//
|
||||
|
||||
CreateServicePacket( MSGTYPE_ADVERTISEMENT, Udn, Udn,
|
||||
Location, Duration, &msgs[1] );
|
||||
Location, Duration, &msgs[1], AddressFamily );
|
||||
|
||||
sprintf( Mil_Usn, "%s::%s", Udn, DevType );
|
||||
CreateServicePacket( MSGTYPE_ADVERTISEMENT, DevType, Mil_Usn,
|
||||
Location, Duration, &msgs[2] );
|
||||
Location, Duration, &msgs[2], AddressFamily );
|
||||
|
||||
// check error
|
||||
if( ( RootDev && msgs[0] == NULL ) ||
|
||||
@ -435,11 +474,11 @@ DeviceAdvertisement( IN char *DevType,
|
||||
// send packets
|
||||
if( RootDev ) {
|
||||
// send 3 msg types
|
||||
ret_code = NewRequestHandler( &DestAddr, 3, &msgs[0] );
|
||||
ret_code = NewRequestHandler( (struct sockaddr*)&__ss, 3, &msgs[0] );
|
||||
} else // sub-device
|
||||
{
|
||||
// send 2 msg types
|
||||
ret_code = NewRequestHandler( &DestAddr, 2, &msgs[1] );
|
||||
ret_code = NewRequestHandler( (struct sockaddr*)&__ss, 2, &msgs[1] );
|
||||
}
|
||||
|
||||
// free msgs
|
||||
@ -454,7 +493,7 @@ DeviceAdvertisement( IN char *DevType,
|
||||
* Function : SendReply
|
||||
*
|
||||
* Parameters:
|
||||
* IN struct sockaddr_in * DestAddr:destination IP address.
|
||||
* IN struct sockaddr * DestAddr:destination IP address.
|
||||
* IN char *DevType: Device type
|
||||
* IN int RootDev: 1 means root device 0 means embedded device.
|
||||
* IN char * Udn: Device UDN
|
||||
@ -470,7 +509,7 @@ DeviceAdvertisement( IN char *DevType,
|
||||
* UPNP_E_SUCCESS if successful else appropriate error
|
||||
***************************************************************************/
|
||||
int
|
||||
SendReply( IN struct sockaddr_in *DestAddr,
|
||||
SendReply( IN struct sockaddr *DestAddr,
|
||||
IN char *DevType,
|
||||
IN int RootDev,
|
||||
IN char *Udn,
|
||||
@ -493,7 +532,7 @@ SendReply( IN struct sockaddr_in *DestAddr,
|
||||
|
||||
sprintf( Mil_Usn, "%s::upnp:rootdevice", Udn );
|
||||
CreateServicePacket( MSGTYPE_REPLY, "upnp:rootdevice",
|
||||
Mil_Usn, Location, Duration, &msgs[0] );
|
||||
Mil_Usn, Location, Duration, &msgs[0], DestAddr->sa_family );
|
||||
} else {
|
||||
// two msgs for embedded devices
|
||||
num_msgs = 1;
|
||||
@ -501,11 +540,11 @@ SendReply( IN struct sockaddr_in *DestAddr,
|
||||
//NK: FIX for extra response when someone searches by udn
|
||||
if( !ByType ) {
|
||||
CreateServicePacket( MSGTYPE_REPLY, Udn, Udn, Location,
|
||||
Duration, &msgs[0] );
|
||||
Duration, &msgs[0], DestAddr->sa_family );
|
||||
} else {
|
||||
sprintf( Mil_Usn, "%s::%s", Udn, DevType );
|
||||
CreateServicePacket( MSGTYPE_REPLY, DevType, Mil_Usn,
|
||||
Location, Duration, &msgs[0] );
|
||||
Location, Duration, &msgs[0], DestAddr->sa_family );
|
||||
}
|
||||
}
|
||||
|
||||
@ -531,7 +570,7 @@ SendReply( IN struct sockaddr_in *DestAddr,
|
||||
* Function : DeviceReply
|
||||
*
|
||||
* Parameters:
|
||||
* IN struct sockaddr_in * DestAddr:destination IP address.
|
||||
* IN struct sockaddr *DestAddr:destination IP address.
|
||||
* IN char *DevType: Device type
|
||||
* IN int RootDev: 1 means root device 0 means embedded device.
|
||||
* IN char * Udn: Device UDN
|
||||
@ -545,12 +584,12 @@ SendReply( IN struct sockaddr_in *DestAddr,
|
||||
* UPNP_E_SUCCESS if successful else appropriate error
|
||||
***************************************************************************/
|
||||
int
|
||||
DeviceReply( IN struct sockaddr_in *DestAddr,
|
||||
DeviceReply( IN struct sockaddr *DestAddr,
|
||||
IN char *DevType,
|
||||
IN int RootDev,
|
||||
IN char *Udn,
|
||||
IN char *Location,
|
||||
IN int Duration )
|
||||
IN int Duration)
|
||||
{
|
||||
char *szReq[3],
|
||||
Mil_Nt[LINE_SIZE],
|
||||
@ -568,18 +607,18 @@ DeviceReply( IN struct sockaddr_in *DestAddr,
|
||||
strcpy( Mil_Nt, "upnp:rootdevice" );
|
||||
sprintf( Mil_Usn, "%s::upnp:rootdevice", Udn );
|
||||
CreateServicePacket( MSGTYPE_REPLY, Mil_Nt, Mil_Usn,
|
||||
Location, Duration, &szReq[0] );
|
||||
Location, Duration, &szReq[0], DestAddr->sa_family );
|
||||
}
|
||||
|
||||
sprintf( Mil_Nt, "%s", Udn );
|
||||
sprintf( Mil_Usn, "%s", Udn );
|
||||
CreateServicePacket( MSGTYPE_REPLY, Mil_Nt, Mil_Usn,
|
||||
Location, Duration, &szReq[1] );
|
||||
Location, Duration, &szReq[1], DestAddr->sa_family );
|
||||
|
||||
sprintf( Mil_Nt, "%s", DevType );
|
||||
sprintf( Mil_Usn, "%s::%s", Udn, DevType );
|
||||
CreateServicePacket( MSGTYPE_REPLY, Mil_Nt, Mil_Usn,
|
||||
Location, Duration, &szReq[2] );
|
||||
Location, Duration, &szReq[2], DestAddr->sa_family );
|
||||
|
||||
// check error
|
||||
|
||||
@ -613,6 +652,7 @@ DeviceReply( IN struct sockaddr_in *DestAddr,
|
||||
* IN char *ServType: Service Type.
|
||||
* IN char * Location: Location of Device description document.
|
||||
* IN int Duration :Life time of this device.
|
||||
* IN int AddressFamily: Device address family
|
||||
* Description:
|
||||
* This function creates the advertisement packet based
|
||||
* on the input parameter, and send it to the multicast channel.
|
||||
@ -624,28 +664,42 @@ int
|
||||
ServiceAdvertisement( IN char *Udn,
|
||||
IN char *ServType,
|
||||
IN char *Location,
|
||||
IN int Duration )
|
||||
IN int Duration,
|
||||
IN int AddressFamily)
|
||||
{
|
||||
char Mil_Usn[LINE_SIZE];
|
||||
char *szReq[1];
|
||||
struct sockaddr_in DestAddr;
|
||||
int RetVal;
|
||||
struct sockaddr_storage __ss;
|
||||
struct sockaddr_in* DestAddr4 = (struct sockaddr_in*)&__ss;
|
||||
struct sockaddr_in6* DestAddr6 = (struct sockaddr_in6*)&__ss;
|
||||
|
||||
DestAddr.sin_family = AF_INET;
|
||||
DestAddr.sin_addr.s_addr = inet_addr( SSDP_IP );
|
||||
DestAddr.sin_port = htons( SSDP_PORT );
|
||||
memset( &__ss, 0, sizeof(__ss) );
|
||||
if( AddressFamily == AF_INET ) {
|
||||
DestAddr4->sin_family = AF_INET;
|
||||
inet_pton( AF_INET, SSDP_IP, &DestAddr4->sin_addr );
|
||||
DestAddr4->sin_port = htons( SSDP_PORT );
|
||||
} else if( AddressFamily == AF_INET6 ) {
|
||||
DestAddr6->sin6_family = AF_INET6;
|
||||
inet_pton( AF_INET6, SSDP_IPV6_LINKLOCAL, &DestAddr6->sin6_addr );
|
||||
DestAddr6->sin6_port = htons( SSDP_PORT );
|
||||
DestAddr6->sin6_scope_id = gIF_INDEX;
|
||||
} else {
|
||||
UpnpPrintf( UPNP_CRITICAL, SSDP, __FILE__, __LINE__,
|
||||
"Invalid device address family.\n" );
|
||||
}
|
||||
|
||||
sprintf( Mil_Usn, "%s::%s", Udn, ServType );
|
||||
|
||||
//CreateServiceRequestPacket(1,szReq[0],Mil_Nt,Mil_Usn,
|
||||
//Server,Location,Duration);
|
||||
CreateServicePacket( MSGTYPE_ADVERTISEMENT, ServType, Mil_Usn,
|
||||
Location, Duration, &szReq[0] );
|
||||
Location, Duration, &szReq[0], AddressFamily );
|
||||
if( szReq[0] == NULL ) {
|
||||
return UPNP_E_OUTOF_MEMORY;
|
||||
}
|
||||
|
||||
RetVal = NewRequestHandler( &DestAddr, 1, szReq );
|
||||
RetVal = NewRequestHandler( (struct sockaddr*)&__ss, 1, szReq );
|
||||
|
||||
free( szReq[0] );
|
||||
return RetVal;
|
||||
@ -655,7 +709,7 @@ ServiceAdvertisement( IN char *Udn,
|
||||
* Function : ServiceReply
|
||||
*
|
||||
* Parameters:
|
||||
* IN struct sockaddr_in *DestAddr:
|
||||
* IN struct sockaddr *DestAddr:
|
||||
* IN char * Udn: Device UDN
|
||||
* IN char *ServType: Service Type.
|
||||
* IN char * Location: Location of Device description document.
|
||||
@ -668,7 +722,7 @@ ServiceAdvertisement( IN char *Udn,
|
||||
* UPNP_E_SUCCESS if successful else appropriate error
|
||||
***************************************************************************/
|
||||
int
|
||||
ServiceReply( IN struct sockaddr_in *DestAddr,
|
||||
ServiceReply( IN struct sockaddr *DestAddr,
|
||||
IN char *ServType,
|
||||
IN char *Udn,
|
||||
IN char *Location,
|
||||
@ -683,7 +737,7 @@ ServiceReply( IN struct sockaddr_in *DestAddr,
|
||||
sprintf( Mil_Usn, "%s::%s", Udn, ServType );
|
||||
|
||||
CreateServicePacket( MSGTYPE_REPLY, ServType, Mil_Usn,
|
||||
Location, Duration, &szReq[0] );
|
||||
Location, Duration, &szReq[0], DestAddr->sa_family );
|
||||
if( szReq[0] == NULL ) {
|
||||
return UPNP_E_OUTOF_MEMORY;
|
||||
}
|
||||
@ -702,6 +756,7 @@ ServiceReply( IN struct sockaddr_in *DestAddr,
|
||||
* IN char *ServType: Service Type.
|
||||
* IN char * Location: Location of Device description document.
|
||||
* IN int Duration :Service duration in sec.
|
||||
* IN int AddressFamily: Device address family
|
||||
* Description:
|
||||
* This function creates a HTTP service shutdown request packet
|
||||
* and sent it to the multicast channel through RequestHandler.
|
||||
@ -713,27 +768,41 @@ int
|
||||
ServiceShutdown( IN char *Udn,
|
||||
IN char *ServType,
|
||||
IN char *Location,
|
||||
IN int Duration )
|
||||
IN int Duration,
|
||||
IN int AddressFamily)
|
||||
{
|
||||
char Mil_Usn[LINE_SIZE];
|
||||
char *szReq[1];
|
||||
struct sockaddr_in DestAddr;
|
||||
struct sockaddr_storage __ss;
|
||||
struct sockaddr_in* DestAddr4 = (struct sockaddr_in*)&__ss;
|
||||
struct sockaddr_in6* DestAddr6 = (struct sockaddr_in6*)&__ss;
|
||||
int RetVal;
|
||||
|
||||
DestAddr.sin_family = AF_INET;
|
||||
DestAddr.sin_addr.s_addr = inet_addr( SSDP_IP );
|
||||
DestAddr.sin_port = htons( SSDP_PORT );
|
||||
memset( &__ss, 0, sizeof(__ss) );
|
||||
if( AddressFamily == AF_INET ) {
|
||||
DestAddr4->sin_family = AF_INET;
|
||||
inet_pton( AF_INET, SSDP_IP, &DestAddr4->sin_addr );
|
||||
DestAddr4->sin_port = htons( SSDP_PORT );
|
||||
} else if( AddressFamily == AF_INET6 ) {
|
||||
DestAddr6->sin6_family = AF_INET6;
|
||||
inet_pton( AF_INET6, SSDP_IPV6_LINKLOCAL, &DestAddr6->sin6_addr );
|
||||
DestAddr6->sin6_port = htons( SSDP_PORT );
|
||||
DestAddr6->sin6_scope_id = gIF_INDEX;
|
||||
} else {
|
||||
UpnpPrintf( UPNP_CRITICAL, SSDP, __FILE__, __LINE__,
|
||||
"Invalid device address family.\n" );
|
||||
}
|
||||
|
||||
//sprintf(Mil_Nt,"%s",ServType);
|
||||
sprintf( Mil_Usn, "%s::%s", Udn, ServType );
|
||||
//CreateServiceRequestPacket(0,szReq[0],Mil_Nt,Mil_Usn,
|
||||
//Server,Location,Duration);
|
||||
CreateServicePacket( MSGTYPE_SHUTDOWN, ServType, Mil_Usn,
|
||||
Location, Duration, &szReq[0] );
|
||||
Location, Duration, &szReq[0], AddressFamily );
|
||||
if( szReq[0] == NULL ) {
|
||||
return UPNP_E_OUTOF_MEMORY;
|
||||
}
|
||||
RetVal = NewRequestHandler( &DestAddr, 1, szReq );
|
||||
RetVal = NewRequestHandler( (struct sockaddr*)&__ss, 1, szReq );
|
||||
|
||||
free( szReq[0] );
|
||||
return RetVal;
|
||||
@ -748,6 +817,7 @@ ServiceShutdown( IN char *Udn,
|
||||
* IN char * Udn: Device UDN
|
||||
* IN char * Location: Location URL
|
||||
* IN int Duration :Device duration in sec.
|
||||
* IN int AddressFamily: Device address family.
|
||||
*
|
||||
* Description:
|
||||
* This function creates a HTTP device shutdown request packet
|
||||
@ -762,9 +832,12 @@ DeviceShutdown( IN char *DevType,
|
||||
IN char *Udn,
|
||||
IN char *_Server,
|
||||
IN char *Location,
|
||||
IN int Duration )
|
||||
IN int Duration,
|
||||
IN int AddressFamily)
|
||||
{
|
||||
struct sockaddr_in DestAddr;
|
||||
struct sockaddr_storage __ss;
|
||||
struct sockaddr_in* DestAddr4 = (struct sockaddr_in*)&__ss;
|
||||
struct sockaddr_in6* DestAddr6 = (struct sockaddr_in6*)&__ss;
|
||||
char *msgs[3];
|
||||
char Mil_Usn[LINE_SIZE];
|
||||
int ret_code;
|
||||
@ -773,26 +846,37 @@ DeviceShutdown( IN char *DevType,
|
||||
msgs[1] = NULL;
|
||||
msgs[2] = NULL;
|
||||
|
||||
DestAddr.sin_family = AF_INET;
|
||||
DestAddr.sin_addr.s_addr = inet_addr( SSDP_IP );
|
||||
DestAddr.sin_port = htons( SSDP_PORT );
|
||||
memset( &__ss, 0, sizeof(__ss) );
|
||||
if( AddressFamily == AF_INET ) {
|
||||
DestAddr4->sin_family = AF_INET;
|
||||
inet_pton( AF_INET, SSDP_IP, &DestAddr4->sin_addr );
|
||||
DestAddr4->sin_port = htons( SSDP_PORT );
|
||||
} else if( AddressFamily == AF_INET6 ) {
|
||||
DestAddr6->sin6_family = AF_INET6;
|
||||
inet_pton( AF_INET6, SSDP_IPV6_LINKLOCAL, &DestAddr6->sin6_addr );
|
||||
DestAddr6->sin6_port = htons( SSDP_PORT );
|
||||
DestAddr6->sin6_scope_id = gIF_INDEX;
|
||||
} else {
|
||||
UpnpPrintf( UPNP_CRITICAL, SSDP, __FILE__, __LINE__,
|
||||
"Invalid device address family.\n" );
|
||||
}
|
||||
|
||||
// root device has one extra msg
|
||||
if( RootDev ) {
|
||||
sprintf( Mil_Usn, "%s::upnp:rootdevice", Udn );
|
||||
CreateServicePacket( MSGTYPE_SHUTDOWN, "upnp:rootdevice",
|
||||
Mil_Usn, Location, Duration, &msgs[0] );
|
||||
Mil_Usn, Location, Duration, &msgs[0], AddressFamily );
|
||||
}
|
||||
|
||||
UpnpPrintf( UPNP_INFO, SSDP, __FILE__, __LINE__,
|
||||
"In function DeviceShutdown\n" );
|
||||
// both root and sub-devices need to send these two messages
|
||||
CreateServicePacket( MSGTYPE_SHUTDOWN, Udn, Udn,
|
||||
Location, Duration, &msgs[1] );
|
||||
Location, Duration, &msgs[1], AddressFamily );
|
||||
|
||||
sprintf( Mil_Usn, "%s::%s", Udn, DevType );
|
||||
CreateServicePacket( MSGTYPE_SHUTDOWN, DevType, Mil_Usn,
|
||||
Location, Duration, &msgs[2] );
|
||||
Location, Duration, &msgs[2], AddressFamily );
|
||||
|
||||
// check error
|
||||
if( ( RootDev && msgs[0] == NULL ) ||
|
||||
@ -805,11 +889,11 @@ DeviceShutdown( IN char *DevType,
|
||||
// send packets
|
||||
if( RootDev ) {
|
||||
// send 3 msg types
|
||||
ret_code = NewRequestHandler( &DestAddr, 3, &msgs[0] );
|
||||
ret_code = NewRequestHandler( (struct sockaddr*)&__ss, 3, &msgs[0] );
|
||||
} else // sub-device
|
||||
{
|
||||
// send 2 msg types
|
||||
ret_code = NewRequestHandler( &DestAddr, 2, &msgs[1] );
|
||||
ret_code = NewRequestHandler( (struct sockaddr*)&__ss, 2, &msgs[1] );
|
||||
}
|
||||
|
||||
// free msgs
|
||||
|
@ -42,27 +42,25 @@
|
||||
#include "httpparser.h"
|
||||
#include "httpreadwrite.h"
|
||||
|
||||
#ifdef WIN32
|
||||
#include <string.h>
|
||||
#include <winsock2.h>
|
||||
#include <ws2tcpip.h>
|
||||
#include "unixutil.h"
|
||||
#endif
|
||||
|
||||
#define MAX_TIME_TOREAD 45
|
||||
|
||||
CLIENTONLY( SOCKET gSsdpReqSocket = 0; )
|
||||
CLIENTONLY( SOCKET gSsdpReqSocket4 = INVALID_SOCKET; )
|
||||
CLIENTONLY( SOCKET gSsdpReqSocket6 = INVALID_SOCKET; )
|
||||
|
||||
void RequestHandler();
|
||||
int create_ssdp_sock_v4( SOCKET* ssdpSock );
|
||||
int create_ssdp_sock_v6( SOCKET* ssdpSock );
|
||||
#if INCLUDE_CLIENT_APIS
|
||||
int create_ssdp_sock_reqv4( SOCKET* ssdpReqSock );
|
||||
int create_ssdp_sock_reqv6( SOCKET* ssdpReqSock );
|
||||
#endif
|
||||
Event ErrotEvt;
|
||||
|
||||
enum Listener { Idle, Stopping, Running };
|
||||
|
||||
unsigned short ssdpStopPort;
|
||||
|
||||
struct SSDPSockArray {
|
||||
// socket for incoming advertisments and search requests
|
||||
int ssdpSock;
|
||||
SOCKET ssdpSock;
|
||||
// socket for sending search requests and receiving search replies
|
||||
CLIENTONLY( int ssdpReqSock; )
|
||||
};
|
||||
@ -80,10 +78,10 @@ struct SSDPSockArray {
|
||||
* 1 = Send Advertisement
|
||||
* IN UpnpDevice_Handle Hnd: Device handle
|
||||
* IN enum SsdpSearchType SearchType:Search type for sending replies
|
||||
* IN struct sockaddr_in *DestAddr:Destination address
|
||||
* IN char *DeviceType:Device type
|
||||
* IN struct sockaddr *DestAddr:Destination address
|
||||
* IN char *DeviceType:Device type
|
||||
* IN char *DeviceUDN:Device UDN
|
||||
* IN char *ServiceType:Service type
|
||||
* IN char *ServiceType:Service type
|
||||
* IN int Exp:Advertisement age
|
||||
*
|
||||
* Description:
|
||||
@ -95,7 +93,7 @@ struct SSDPSockArray {
|
||||
int AdvertiseAndReply( IN int AdFlag,
|
||||
IN UpnpDevice_Handle Hnd,
|
||||
IN enum SsdpSearchType SearchType,
|
||||
IN struct sockaddr_in *DestAddr,
|
||||
IN struct sockaddr *DestAddr,
|
||||
IN char *DeviceType,
|
||||
IN char *DeviceUDN,
|
||||
IN char *ServiceType,
|
||||
@ -234,10 +232,10 @@ int AdvertiseAndReply( IN int AdFlag,
|
||||
// send the device advertisement
|
||||
if( AdFlag == 1 ) {
|
||||
DeviceAdvertisement( devType, i == 0,
|
||||
UDNstr, SInfo->DescURL, Exp );
|
||||
UDNstr, SInfo->DescURL, Exp, SInfo->DeviceAf );
|
||||
} else { // AdFlag == -1
|
||||
DeviceShutdown( devType, i == 0, UDNstr,
|
||||
SERVER, SInfo->DescURL, Exp );
|
||||
SERVER, SInfo->DescURL, Exp, SInfo->DeviceAf );
|
||||
}
|
||||
} else {
|
||||
switch ( SearchType ) {
|
||||
@ -353,10 +351,10 @@ int AdvertiseAndReply( IN int AdFlag,
|
||||
if( AdFlag ) {
|
||||
if( AdFlag == 1 ) {
|
||||
ServiceAdvertisement( UDNstr, servType,
|
||||
SInfo->DescURL, Exp );
|
||||
SInfo->DescURL, Exp, SInfo->DeviceAf );
|
||||
} else { // AdFlag == -1
|
||||
ServiceShutdown( UDNstr, servType,
|
||||
SInfo->DescURL, Exp );
|
||||
SInfo->DescURL, Exp, SInfo->DeviceAf );
|
||||
}
|
||||
} else {
|
||||
switch ( SearchType ) {
|
||||
@ -403,7 +401,7 @@ int AdvertiseAndReply( IN int AdFlag,
|
||||
* Function : Make_Socket_NoBlocking
|
||||
*
|
||||
* Parameters:
|
||||
* IN int sock: socket
|
||||
* IN SOCKET sock: socket
|
||||
*
|
||||
* Description:
|
||||
* This function makes socket non-blocking.
|
||||
@ -412,7 +410,7 @@ int AdvertiseAndReply( IN int AdFlag,
|
||||
* 0 if successful else -1
|
||||
***************************************************************************/
|
||||
int
|
||||
Make_Socket_NoBlocking( int sock )
|
||||
Make_Socket_NoBlocking( SOCKET sock )
|
||||
{
|
||||
#ifdef WIN32
|
||||
u_long val=1;
|
||||
@ -655,8 +653,11 @@ valid_ssdp_msg( IN http_message_t * hmsg )
|
||||
}
|
||||
// check HOST header
|
||||
if( ( httpmsg_find_hdr( hmsg, HDR_HOST, &hdr_value ) == NULL ) ||
|
||||
( memptr_cmp( &hdr_value, "239.255.255.250:1900" ) != 0 )
|
||||
( ( memptr_cmp( &hdr_value, "239.255.255.250:1900" ) != 0 ) &&
|
||||
( memptr_cmp( &hdr_value, "[FF02::C]:1900" ) != 0 ) )
|
||||
) {
|
||||
UpnpPrintf( UPNP_INFO, SSDP, __FILE__, __LINE__,
|
||||
"Invalid HOST header from SSDP message\n" );
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
@ -705,7 +706,7 @@ start_event_handler( void *Data )
|
||||
goto error_handler;
|
||||
}
|
||||
// check msg
|
||||
if( !valid_ssdp_msg( &parser->msg ) ) {
|
||||
if( valid_ssdp_msg( &parser->msg ) != TRUE ) {
|
||||
goto error_handler;
|
||||
}
|
||||
return 0; //////// done; thread will free 'data'
|
||||
@ -740,9 +741,10 @@ ssdp_event_handler_thread( void *the_data )
|
||||
// send msg to device or ctrlpt
|
||||
if( ( hmsg->method == HTTPMETHOD_NOTIFY ) ||
|
||||
( hmsg->request_method == HTTPMETHOD_MSEARCH ) ) {
|
||||
CLIENTONLY( ssdp_handle_ctrlpt_msg( hmsg, &data->dest_addr, FALSE, NULL );)
|
||||
CLIENTONLY( ssdp_handle_ctrlpt_msg( hmsg,
|
||||
(struct sockaddr*)&data->dest_addr, FALSE, NULL );)
|
||||
} else {
|
||||
ssdp_handle_device_request( hmsg, &data->dest_addr );
|
||||
ssdp_handle_device_request( hmsg, (struct sockaddr*)&data->dest_addr );
|
||||
}
|
||||
|
||||
// free data
|
||||
@ -766,11 +768,12 @@ readFromSSDPSocket( SOCKET socket )
|
||||
{
|
||||
char *requestBuf = NULL;
|
||||
char staticBuf[BUFSIZE];
|
||||
struct sockaddr_in clientAddr;
|
||||
struct sockaddr_storage __ss;
|
||||
ThreadPoolJob job;
|
||||
ssdp_thread_data *data = NULL;
|
||||
socklen_t socklen = 0;
|
||||
socklen_t socklen = sizeof( __ss );
|
||||
int byteReceived = 0;
|
||||
char ntop_buf[64];
|
||||
|
||||
requestBuf = staticBuf;
|
||||
|
||||
@ -778,8 +781,6 @@ readFromSSDPSocket( SOCKET socket )
|
||||
//can't be allocated, still drain the
|
||||
//socket using a static buffer
|
||||
|
||||
socklen = sizeof( struct sockaddr_in );
|
||||
|
||||
data = ( ssdp_thread_data * )
|
||||
malloc( sizeof( ssdp_thread_data ) );
|
||||
|
||||
@ -787,7 +788,7 @@ readFromSSDPSocket( SOCKET socket )
|
||||
//initialize parser
|
||||
|
||||
#ifdef INCLUDE_CLIENT_APIS
|
||||
if( socket == gSsdpReqSocket ) {
|
||||
if( socket == gSsdpReqSocket4 || socket == gSsdpReqSocket6 ) {
|
||||
parser_response_init( &data->parser, HTTPMETHOD_MSEARCH );
|
||||
} else {
|
||||
parser_request_init( &data->parser );
|
||||
@ -809,10 +810,18 @@ readFromSSDPSocket( SOCKET socket )
|
||||
}
|
||||
byteReceived = recvfrom( socket, requestBuf,
|
||||
BUFSIZE - 1, 0,
|
||||
( struct sockaddr * )&clientAddr, &socklen );
|
||||
(struct sockaddr *)&__ss, &socklen );
|
||||
|
||||
if( byteReceived > 0 ) {
|
||||
requestBuf[byteReceived] = '\0';
|
||||
|
||||
if( __ss.ss_family == AF_INET )
|
||||
inet_ntop( AF_INET, &((struct sockaddr_in*)&__ss)->sin_addr, ntop_buf, sizeof(ntop_buf) );
|
||||
else if( __ss.ss_family == AF_INET6 )
|
||||
inet_ntop( AF_INET6, &((struct sockaddr_in6*)&__ss)->sin6_addr, ntop_buf, sizeof(ntop_buf) );
|
||||
else
|
||||
strncpy( ntop_buf, "<Invalid address family>", sizeof(ntop_buf) );
|
||||
|
||||
UpnpPrintf( UPNP_INFO, SSDP,
|
||||
__FILE__, __LINE__,
|
||||
"Start of received response ----------------------------------------------------\n"
|
||||
@ -820,7 +829,7 @@ readFromSSDPSocket( SOCKET socket )
|
||||
"End of received response ------------------------------------------------------\n"
|
||||
"From host %s\n",
|
||||
requestBuf,
|
||||
inet_ntoa( clientAddr.sin_addr ) );
|
||||
ntop_buf );
|
||||
UpnpPrintf( UPNP_PACKET, SSDP, __FILE__, __LINE__,
|
||||
"Start of received multicast packet --------------------------------------------\n"
|
||||
"%s\n"
|
||||
@ -831,7 +840,7 @@ readFromSSDPSocket( SOCKET socket )
|
||||
data->parser.msg.msg.length += byteReceived;
|
||||
// null-terminate
|
||||
data->parser.msg.msg.buf[byteReceived] = 0;
|
||||
data->dest_addr = clientAddr;
|
||||
memcpy( &data->dest_addr, &__ss, sizeof(__ss) );
|
||||
TPJobInit( &job, ( start_routine )
|
||||
ssdp_event_handler_thread, data );
|
||||
TPJobSetFreeFunction( &job, free_ssdp_event_handler_data );
|
||||
@ -846,132 +855,261 @@ readFromSSDPSocket( SOCKET socket )
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/************************************************************************
|
||||
* Function : get_ssdp_sockets
|
||||
*
|
||||
* Parameters:
|
||||
* OUT MiniServerSockArray *out: Arrays of SSDP sockets
|
||||
* OUT MiniServerSockArray *out: Array of SSDP sockets
|
||||
*
|
||||
* Description:
|
||||
* This function creates the ssdp sockets. It set their option to listen
|
||||
* for multicast traffic.
|
||||
* This function creates the IPv4 and IPv6 ssdp sockets required by the
|
||||
* control point and device operation.
|
||||
*
|
||||
* Returns: int
|
||||
* return UPNP_E_SUCCESS if successful else returns appropriate error
|
||||
***************************************************************************/
|
||||
int
|
||||
get_ssdp_sockets( MiniServerSockArray * out )
|
||||
int get_ssdp_sockets( MiniServerSockArray * out )
|
||||
{
|
||||
char errorBuffer[ERROR_BUFFER_LEN];
|
||||
int onOff = 1;
|
||||
u_char ttl = 4;
|
||||
struct ip_mreq ssdpMcastAddr;
|
||||
struct sockaddr_in ssdpAddr;
|
||||
int option = 1;
|
||||
int ret = 0;
|
||||
struct in_addr addr;
|
||||
SOCKET ssdpSock;
|
||||
int retVal;
|
||||
|
||||
#if INCLUDE_CLIENT_APIS
|
||||
SOCKET ssdpReqSock;
|
||||
|
||||
ssdpReqSock = socket( AF_INET, SOCK_DGRAM, 0 );
|
||||
if ( ssdpReqSock == -1 ) {
|
||||
strerror_r(errno, errorBuffer, ERROR_BUFFER_LEN);
|
||||
UpnpPrintf( UPNP_CRITICAL, SSDP, __FILE__, __LINE__,
|
||||
"Error in socket(): %s\n", errorBuffer );
|
||||
|
||||
return UPNP_E_OUTOF_SOCKET;
|
||||
// Create the IPv4 socket for SSDP REQUESTS
|
||||
if( strlen( gIF_IPV4 ) > 0 ) {
|
||||
retVal = create_ssdp_sock_reqv4( &out->ssdpReqSock4 );
|
||||
if( retVal != UPNP_E_SUCCESS ) {
|
||||
return retVal;
|
||||
}
|
||||
// For use by ssdp control point.
|
||||
gSsdpReqSocket4 = out->ssdpReqSock4;
|
||||
} else {
|
||||
out->ssdpReqSock4 = INVALID_SOCKET;
|
||||
}
|
||||
|
||||
// Create the IPv6 socket for SSDP REQUESTS
|
||||
if( strlen( gIF_IPV6 ) > 0 ) {
|
||||
retVal = create_ssdp_sock_reqv6( &out->ssdpReqSock6 );
|
||||
if( retVal != UPNP_E_SUCCESS ) {
|
||||
CLIENTONLY( shutdown( out->ssdpReqSock4, SD_BOTH ); )
|
||||
CLIENTONLY( UpnpCloseSocket( out->ssdpReqSock4 ); )
|
||||
return retVal;
|
||||
}
|
||||
// For use by ssdp control point.
|
||||
gSsdpReqSocket6 = out->ssdpReqSock6;
|
||||
} else {
|
||||
out->ssdpReqSock6 = INVALID_SOCKET;
|
||||
}
|
||||
ret = setsockopt( ssdpReqSock, IPPROTO_IP, IP_MULTICAST_TTL,
|
||||
&ttl, sizeof (ttl) );
|
||||
// just do it, regardless if fails or not.
|
||||
Make_Socket_NoBlocking( ssdpReqSock );
|
||||
gSsdpReqSocket = ssdpReqSock;
|
||||
#endif /* INCLUDE_CLIENT_APIS */
|
||||
|
||||
ssdpSock = socket( AF_INET, SOCK_DGRAM, 0 );
|
||||
if ( ssdpSock == -1 ) {
|
||||
// Create the IPv4 socket for SSDP
|
||||
if( strlen( gIF_IPV4 ) > 0 ) {
|
||||
retVal = create_ssdp_sock_v4( &out->ssdpSock4 );
|
||||
if( retVal != UPNP_E_SUCCESS ) {
|
||||
CLIENTONLY( shutdown( out->ssdpReqSock4, SD_BOTH ); )
|
||||
CLIENTONLY( UpnpCloseSocket( out->ssdpReqSock4 ); )
|
||||
CLIENTONLY( shutdown( out->ssdpReqSock6, SD_BOTH ); )
|
||||
CLIENTONLY( UpnpCloseSocket( out->ssdpReqSock6 ); )
|
||||
return retVal;
|
||||
}
|
||||
} else {
|
||||
out->ssdpSock4 = INVALID_SOCKET;
|
||||
}
|
||||
|
||||
// Create the IPv6 socket for SSDP
|
||||
if( strlen( gIF_IPV6 ) > 0 ) {
|
||||
retVal = create_ssdp_sock_v6( &out->ssdpSock6 );
|
||||
if( retVal != UPNP_E_SUCCESS ) {
|
||||
shutdown( out->ssdpSock4, SD_BOTH );
|
||||
UpnpCloseSocket( out->ssdpSock4 );
|
||||
CLIENTONLY( shutdown( out->ssdpReqSock4, SD_BOTH ); )
|
||||
CLIENTONLY( UpnpCloseSocket( out->ssdpReqSock4 ); )
|
||||
CLIENTONLY( shutdown( out->ssdpReqSock6, SD_BOTH ); )
|
||||
CLIENTONLY( UpnpCloseSocket( out->ssdpReqSock6 ); )
|
||||
return retVal;
|
||||
}
|
||||
} else {
|
||||
out->ssdpSock6 = INVALID_SOCKET;
|
||||
}
|
||||
|
||||
return UPNP_E_SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
#if INCLUDE_CLIENT_APIS
|
||||
/************************************************************************
|
||||
* Function : create_ssdp_sock_reqv4
|
||||
*
|
||||
* Parameters:
|
||||
* IN SOCKET* ssdpReqSock: SSDP IPv4 request socket to be created
|
||||
*
|
||||
* Description:
|
||||
* This function creates the SSDP IPv4 socket to be used by the control
|
||||
* point.
|
||||
*
|
||||
* Returns:
|
||||
* UPNP_E_SUCCESS on successful socket creation.
|
||||
***************************************************************************/
|
||||
int create_ssdp_sock_reqv4( SOCKET* ssdpReqSock )
|
||||
{
|
||||
char errorBuffer[ERROR_BUFFER_LEN];
|
||||
u_char ttl = 4;
|
||||
|
||||
*ssdpReqSock = socket( AF_INET, SOCK_DGRAM, 0 );
|
||||
if ( *ssdpReqSock == -1 ) {
|
||||
strerror_r(errno, errorBuffer, ERROR_BUFFER_LEN);
|
||||
UpnpPrintf( UPNP_CRITICAL, SSDP, __FILE__, __LINE__,
|
||||
"Error in socket(): %s\n", errorBuffer );
|
||||
return UPNP_E_OUTOF_SOCKET;
|
||||
}
|
||||
|
||||
setsockopt( *ssdpReqSock, IPPROTO_IP, IP_MULTICAST_TTL,
|
||||
&ttl, sizeof (ttl) );
|
||||
|
||||
// just do it, regardless if fails or not.
|
||||
Make_Socket_NoBlocking( *ssdpReqSock );
|
||||
|
||||
return UPNP_E_SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
/************************************************************************
|
||||
* Function : create_ssdp_sock_reqv6
|
||||
*
|
||||
* Parameters:
|
||||
* IN SOCKET* ssdpReqSock: SSDP IPv6 request socket to be created
|
||||
*
|
||||
* Description:
|
||||
* This function creates the SSDP IPv6 socket to be used by the control
|
||||
* point.
|
||||
*
|
||||
* Returns: void
|
||||
*
|
||||
***************************************************************************/
|
||||
int create_ssdp_sock_reqv6( SOCKET* ssdpReqSock )
|
||||
{
|
||||
char errorBuffer[ERROR_BUFFER_LEN];
|
||||
char hops = 1;
|
||||
|
||||
*ssdpReqSock = socket( AF_INET6, SOCK_DGRAM, 0 );
|
||||
if ( *ssdpReqSock == -1 ) {
|
||||
strerror_r(errno, errorBuffer, ERROR_BUFFER_LEN);
|
||||
UpnpPrintf( UPNP_CRITICAL, SSDP, __FILE__, __LINE__,
|
||||
"Error in socket(): %s\n", errorBuffer );
|
||||
return UPNP_E_OUTOF_SOCKET;
|
||||
}
|
||||
|
||||
// MUST use scoping of IPv6 addresses to control the propagation os SSDP
|
||||
// messages instead of relying on the Hop Limit (Equivalent to the TTL
|
||||
// limit in IPv4).
|
||||
setsockopt( *ssdpReqSock, IPPROTO_IPV6, IPV6_MULTICAST_HOPS,
|
||||
&hops, sizeof(hops) );
|
||||
|
||||
// just do it, regardless if fails or not.
|
||||
Make_Socket_NoBlocking( *ssdpReqSock );
|
||||
|
||||
return UPNP_E_SUCCESS;
|
||||
}
|
||||
#endif /* INCLUDE_CLIENT_APIS */
|
||||
|
||||
|
||||
/************************************************************************
|
||||
* Function : create_ssdp_sock_v4
|
||||
*
|
||||
* Parameters:
|
||||
* IN SOCKET* ssdpSock: SSDP IPv4 socket to be created
|
||||
*
|
||||
* Description:
|
||||
* This function ...
|
||||
*
|
||||
* Returns: void
|
||||
*
|
||||
***************************************************************************/
|
||||
int create_ssdp_sock_v4( SOCKET* ssdpSock )
|
||||
{
|
||||
char errorBuffer[ERROR_BUFFER_LEN];
|
||||
int onOff;
|
||||
u_char ttl = 4;
|
||||
struct ip_mreq ssdpMcastAddr;
|
||||
struct sockaddr_storage __ss;
|
||||
struct sockaddr_in* ssdpAddr4 = (struct sockaddr_in*)&__ss;
|
||||
int ret = 0;
|
||||
struct in_addr addr;
|
||||
|
||||
|
||||
*ssdpSock = socket( AF_INET, SOCK_DGRAM, 0 );
|
||||
if ( *ssdpSock == -1 ) {
|
||||
strerror_r(errno, errorBuffer, ERROR_BUFFER_LEN);
|
||||
UpnpPrintf( UPNP_CRITICAL, SSDP, __FILE__, __LINE__,
|
||||
"Error in socket(): %s\n", errorBuffer );
|
||||
CLIENTONLY( shutdown( ssdpReqSock, SD_BOTH ); )
|
||||
CLIENTONLY( UpnpCloseSocket( ssdpReqSock ); )
|
||||
|
||||
return UPNP_E_OUTOF_SOCKET;
|
||||
}
|
||||
|
||||
onOff = 1;
|
||||
ret = setsockopt( ssdpSock, SOL_SOCKET, SO_REUSEADDR,
|
||||
(char *)&onOff, sizeof(onOff) );
|
||||
ret = setsockopt( *ssdpSock, SOL_SOCKET, SO_REUSEADDR,
|
||||
(char*)&onOff, sizeof(onOff) );
|
||||
if ( ret == -1) {
|
||||
strerror_r(errno, errorBuffer, ERROR_BUFFER_LEN);
|
||||
UpnpPrintf( UPNP_CRITICAL, SSDP, __FILE__, __LINE__,
|
||||
"Error in setsockopt() SO_REUSEADDR: %s\n", errorBuffer );
|
||||
CLIENTONLY( shutdown( ssdpReqSock, SD_BOTH ); )
|
||||
CLIENTONLY( UpnpCloseSocket( ssdpReqSock ); )
|
||||
shutdown( ssdpSock, SD_BOTH );
|
||||
UpnpCloseSocket( ssdpSock );
|
||||
shutdown( *ssdpSock, SD_BOTH );
|
||||
UpnpCloseSocket( *ssdpSock );
|
||||
|
||||
return UPNP_E_SOCKET_ERROR;
|
||||
}
|
||||
|
||||
#if defined(__FreeBSD__) || defined(__OSX__) || defined(__APPLE__)
|
||||
ret = setsockopt( ssdpSock, SOL_SOCKET, SO_REUSEPORT,
|
||||
(char *)&onOff, sizeof (onOff) );
|
||||
onOff = 1;
|
||||
ret = setsockopt( *ssdpSock, SOL_SOCKET, SO_REUSEPORT,
|
||||
(char *)&onOff, sizeof(onOff) );
|
||||
if ( ret == -1 ) {
|
||||
strerror_r(errno, errorBuffer, ERROR_BUFFER_LEN);
|
||||
UpnpPrintf( UPNP_CRITICAL, SSDP, __FILE__, __LINE__,
|
||||
"Error in setsockopt() SO_REUSEPORT: %s\n", errorBuffer );
|
||||
CLIENTONLY( shutdown( ssdpReqSock, SD_BOTH ); )
|
||||
CLIENTONLY( UpnpCloseSocket( ssdpReqSock ); )
|
||||
shutdown( ssdpSock, SD_BOTH );
|
||||
UpnpCloseSocket( ssdpSock );
|
||||
shutdown( *ssdpSock, SD_BOTH );
|
||||
UpnpCloseSocket( *ssdpSock );
|
||||
|
||||
return UPNP_E_SOCKET_ERROR;
|
||||
}
|
||||
#endif /* __FreeBSD__ */
|
||||
|
||||
memset( (void *)&ssdpAddr, 0, sizeof( struct sockaddr_in ) );
|
||||
ssdpAddr.sin_family = AF_INET;
|
||||
// ssdpAddr.sin_addr.s_addr = inet_addr(LOCAL_HOST);
|
||||
ssdpAddr.sin_addr.s_addr = htonl( INADDR_ANY );
|
||||
ssdpAddr.sin_port = htons( SSDP_PORT );
|
||||
ret = bind( ssdpSock, (struct sockaddr *)&ssdpAddr, sizeof (ssdpAddr) );
|
||||
memset( &__ss, 0, sizeof( __ss ) );
|
||||
ssdpAddr4->sin_family = AF_INET;
|
||||
// ssdpAddr.sin_addr.s_addr = inet_addr(gIF_IPV4);
|
||||
ssdpAddr4->sin_addr.s_addr = htonl( INADDR_ANY );
|
||||
ssdpAddr4->sin_port = htons( SSDP_PORT );
|
||||
ret = bind( *ssdpSock, (struct sockaddr *)&__ss, sizeof(__ss) );
|
||||
if ( ret == -1 ) {
|
||||
strerror_r(errno, errorBuffer, ERROR_BUFFER_LEN);
|
||||
UpnpPrintf( UPNP_CRITICAL, SSDP, __FILE__, __LINE__,
|
||||
"Error in bind(), addr=0x%08X, port=%d: %s\n",
|
||||
INADDR_ANY, SSDP_PORT, errorBuffer );
|
||||
shutdown( ssdpSock, SD_BOTH );
|
||||
UpnpCloseSocket( ssdpSock );
|
||||
CLIENTONLY( shutdown( ssdpReqSock, SD_BOTH ); )
|
||||
CLIENTONLY( UpnpCloseSocket( ssdpReqSock ); )
|
||||
shutdown( *ssdpSock, SD_BOTH );
|
||||
UpnpCloseSocket( *ssdpSock );
|
||||
|
||||
return UPNP_E_SOCKET_BIND;
|
||||
}
|
||||
|
||||
memset( (void *)&ssdpMcastAddr, 0, sizeof (struct ip_mreq) );
|
||||
ssdpMcastAddr.imr_interface.s_addr = inet_addr( LOCAL_HOST );
|
||||
ssdpMcastAddr.imr_interface.s_addr = inet_addr( gIF_IPV4 );
|
||||
ssdpMcastAddr.imr_multiaddr.s_addr = inet_addr( SSDP_IP );
|
||||
ret = setsockopt( ssdpSock, IPPROTO_IP, IP_ADD_MEMBERSHIP,
|
||||
(char *)&ssdpMcastAddr, sizeof (struct ip_mreq) );
|
||||
ret = setsockopt( *ssdpSock, IPPROTO_IP, IP_ADD_MEMBERSHIP,
|
||||
(char *)&ssdpMcastAddr, sizeof(struct ip_mreq) );
|
||||
if ( ret == -1 ) {
|
||||
strerror_r(errno, errorBuffer, ERROR_BUFFER_LEN);
|
||||
UpnpPrintf( UPNP_CRITICAL, SSDP, __FILE__, __LINE__,
|
||||
"Error in setsockopt() IP_ADD_MEMBERSHIP (join multicast group): %s\n",
|
||||
errorBuffer );
|
||||
shutdown( ssdpSock, SD_BOTH );
|
||||
CLIENTONLY( shutdown( ssdpReqSock, SD_BOTH ); )
|
||||
UpnpCloseSocket( ssdpSock );
|
||||
CLIENTONLY( UpnpCloseSocket( ssdpReqSock ); )
|
||||
shutdown( *ssdpSock, SD_BOTH );
|
||||
UpnpCloseSocket( *ssdpSock );
|
||||
|
||||
return UPNP_E_SOCKET_ERROR;
|
||||
}
|
||||
|
||||
/* Set multicast interface. */
|
||||
memset( (void *)&addr, 0, sizeof (struct in_addr) );
|
||||
addr.s_addr = inet_addr(LOCAL_HOST);
|
||||
ret = setsockopt(ssdpSock, IPPROTO_IP, IP_MULTICAST_IF,
|
||||
addr.s_addr = inet_addr(gIF_IPV4);
|
||||
ret = setsockopt(*ssdpSock, IPPROTO_IP, IP_MULTICAST_IF,
|
||||
(char *)&addr, sizeof addr);
|
||||
if ( ret == -1 ) {
|
||||
strerror_r(errno, errorBuffer, ERROR_BUFFER_LEN);
|
||||
@ -982,26 +1120,132 @@ get_ssdp_sockets( MiniServerSockArray * out )
|
||||
}
|
||||
|
||||
/* result is not checked becuase it will fail in WinMe and Win9x. */
|
||||
ret = setsockopt( ssdpSock, IPPROTO_IP,
|
||||
ret = setsockopt( *ssdpSock, IPPROTO_IP,
|
||||
IP_MULTICAST_TTL, &ttl, sizeof (ttl) );
|
||||
|
||||
ret = setsockopt( ssdpSock, SOL_SOCKET, SO_BROADCAST,
|
||||
(char *)&option, sizeof (option) );
|
||||
onOff = 1;
|
||||
ret = setsockopt( *ssdpSock, SOL_SOCKET, SO_BROADCAST,
|
||||
(char*)&onOff, sizeof(onOff) );
|
||||
if( ret == -1) {
|
||||
strerror_r(errno, errorBuffer, ERROR_BUFFER_LEN);
|
||||
UpnpPrintf( UPNP_CRITICAL, SSDP, __FILE__, __LINE__,
|
||||
"Error in setsockopt() SO_BROADCAST (set broadcast): %s\n",
|
||||
errorBuffer );
|
||||
shutdown( ssdpSock, SD_BOTH );
|
||||
CLIENTONLY( shutdown( ssdpReqSock, SD_BOTH ); )
|
||||
UpnpCloseSocket( ssdpSock );
|
||||
CLIENTONLY( UpnpCloseSocket( ssdpReqSock ); )
|
||||
shutdown( *ssdpSock, SD_BOTH );
|
||||
UpnpCloseSocket( *ssdpSock );
|
||||
|
||||
return UPNP_E_NETWORK_ERROR;
|
||||
}
|
||||
|
||||
CLIENTONLY( out->ssdpReqSock = ssdpReqSock; )
|
||||
out->ssdpSock = ssdpSock;
|
||||
return UPNP_E_SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
/************************************************************************
|
||||
* Function : create_ssdp_sock_v6
|
||||
*
|
||||
* Parameters:
|
||||
* IN SOCKET* ssdpSock: SSDP IPv6 socket to be created
|
||||
*
|
||||
* Description:
|
||||
* This function ...
|
||||
*
|
||||
* Returns: void
|
||||
*
|
||||
***************************************************************************/
|
||||
int create_ssdp_sock_v6( SOCKET* ssdpSock )
|
||||
{
|
||||
char errorBuffer[ERROR_BUFFER_LEN];
|
||||
struct ipv6_mreq ssdpMcastAddr;
|
||||
struct sockaddr_storage __ss;
|
||||
struct sockaddr_in6* ssdpAddr6 = (struct sockaddr_in6*)&__ss;
|
||||
int onOff;
|
||||
int ret = 0;
|
||||
|
||||
*ssdpSock = socket( AF_INET6, SOCK_DGRAM, 0 );
|
||||
if ( *ssdpSock == -1 ) {
|
||||
strerror_r(errno, errorBuffer, ERROR_BUFFER_LEN);
|
||||
UpnpPrintf( UPNP_CRITICAL, SSDP, __FILE__, __LINE__,
|
||||
"Error in socket(): %s\n", errorBuffer );
|
||||
|
||||
return UPNP_E_OUTOF_SOCKET;
|
||||
}
|
||||
|
||||
onOff = 1;
|
||||
ret = setsockopt( *ssdpSock, SOL_SOCKET, SO_REUSEADDR,
|
||||
(char*)&onOff, sizeof(onOff) );
|
||||
if ( ret == -1) {
|
||||
strerror_r(errno, errorBuffer, ERROR_BUFFER_LEN);
|
||||
UpnpPrintf( UPNP_CRITICAL, SSDP, __FILE__, __LINE__,
|
||||
"Error in setsockopt() SO_REUSEADDR: %s\n", errorBuffer );
|
||||
shutdown( *ssdpSock, SD_BOTH );
|
||||
UpnpCloseSocket( *ssdpSock );
|
||||
|
||||
return UPNP_E_SOCKET_ERROR;
|
||||
}
|
||||
|
||||
#if defined(__FreeBSD__) || defined(__OSX__) || defined(__APPLE__)
|
||||
onOff = 1;
|
||||
ret = setsockopt( *ssdpSock, SOL_SOCKET, SO_REUSEPORT,
|
||||
(char*)&onOff, sizeof (onOff) );
|
||||
if ( ret == -1 ) {
|
||||
strerror_r(errno, errorBuffer, ERROR_BUFFER_LEN);
|
||||
UpnpPrintf( UPNP_CRITICAL, SSDP, __FILE__, __LINE__,
|
||||
"Error in setsockopt() SO_REUSEPORT: %s\n", errorBuffer );
|
||||
shutdown( *ssdpSock, SD_BOTH );
|
||||
UpnpCloseSocket( *ssdpSock );
|
||||
|
||||
return UPNP_E_SOCKET_ERROR;
|
||||
}
|
||||
#endif /* __FreeBSD__ */
|
||||
|
||||
memset( &__ss, 0, sizeof( __ss ) );
|
||||
ssdpAddr6->sin6_family = AF_INET6;
|
||||
ssdpAddr6->sin6_addr = in6addr_any;
|
||||
//inet_pton( AF_INET6, gIF_IPV6, &ssdpAddr6->sin6_addr );
|
||||
ssdpAddr6->sin6_scope_id = gIF_INDEX;
|
||||
ssdpAddr6->sin6_port = htons( SSDP_PORT );
|
||||
ret = bind( *ssdpSock, (struct sockaddr *)&__ss, sizeof(__ss) );
|
||||
if ( ret == -1 ) {
|
||||
strerror_r(errno, errorBuffer, ERROR_BUFFER_LEN);
|
||||
UpnpPrintf( UPNP_CRITICAL, SSDP, __FILE__, __LINE__,
|
||||
"Error in bind(), addr=0x%032lX, port=%d: %s\n",
|
||||
0lu, SSDP_PORT, errorBuffer );
|
||||
shutdown( *ssdpSock, SD_BOTH );
|
||||
UpnpCloseSocket( *ssdpSock );
|
||||
|
||||
return UPNP_E_SOCKET_BIND;
|
||||
}
|
||||
|
||||
memset( (void *)&ssdpMcastAddr, 0, sizeof(ssdpMcastAddr) );
|
||||
ssdpMcastAddr.ipv6mr_interface = gIF_INDEX;
|
||||
inet_pton( AF_INET6, SSDP_IPV6_LINKLOCAL, &ssdpMcastAddr.ipv6mr_multiaddr );
|
||||
ret = setsockopt( *ssdpSock, IPPROTO_IPV6, IPV6_JOIN_GROUP,
|
||||
(char *)&ssdpMcastAddr, sizeof(ssdpMcastAddr) );
|
||||
if ( ret == -1 ) {
|
||||
strerror_r(errno, errorBuffer, ERROR_BUFFER_LEN);
|
||||
UpnpPrintf( UPNP_CRITICAL, SSDP, __FILE__, __LINE__,
|
||||
"Error in setsockopt() IPV6_JOIN_GROUP (join multicast group): %s\n",
|
||||
errorBuffer );
|
||||
shutdown( *ssdpSock, SD_BOTH );
|
||||
UpnpCloseSocket( *ssdpSock );
|
||||
|
||||
return UPNP_E_SOCKET_ERROR;
|
||||
}
|
||||
|
||||
onOff = 1;
|
||||
ret = setsockopt( *ssdpSock, SOL_SOCKET, SO_BROADCAST,
|
||||
(char*)&onOff, sizeof(onOff) );
|
||||
if( ret == -1) {
|
||||
strerror_r(errno, errorBuffer, ERROR_BUFFER_LEN);
|
||||
UpnpPrintf( UPNP_CRITICAL, SSDP, __FILE__, __LINE__,
|
||||
"Error in setsockopt() SO_BROADCAST (set broadcast): %s\n",
|
||||
errorBuffer );
|
||||
shutdown( *ssdpSock, SD_BOTH );
|
||||
UpnpCloseSocket( *ssdpSock );
|
||||
|
||||
return UPNP_E_NETWORK_ERROR;
|
||||
}
|
||||
|
||||
return UPNP_E_SUCCESS;
|
||||
}
|
||||
|
@ -51,7 +51,7 @@
|
||||
* Function : addrToString
|
||||
*
|
||||
* Parameters :
|
||||
* IN const struct sockaddr_in* addr ; socket address object with
|
||||
* IN const struct sockaddr* addr ; socket address object with
|
||||
* the IP Address and port information
|
||||
* OUT char ipaddr_port[] ; character array which will hold the
|
||||
* IP Address in a string format.
|
||||
@ -64,11 +64,20 @@
|
||||
* Note :
|
||||
************************************************************************/
|
||||
static UPNP_INLINE void
|
||||
addrToString( IN const struct sockaddr_in *addr,
|
||||
addrToString( IN const struct sockaddr *addr,
|
||||
OUT char ipaddr_port[] )
|
||||
{
|
||||
sprintf( ipaddr_port, "%s:%d", inet_ntoa( addr->sin_addr ),
|
||||
ntohs( addr->sin_port ) );
|
||||
char buf_ntop[64];
|
||||
|
||||
if( addr->sa_family == AF_INET ) {
|
||||
struct sockaddr_in* sa4 = (struct sockaddr_in*)addr;
|
||||
inet_ntop(AF_INET, &sa4->sin_addr, buf_ntop, sizeof(buf_ntop) );
|
||||
sprintf( ipaddr_port, "%s:%d", buf_ntop, ntohs( sa4->sin_port ) );
|
||||
} else if( addr->sa_family == AF_INET6 ) {
|
||||
struct sockaddr_in6* sa6 = (struct sockaddr_in6*)addr;
|
||||
inet_ntop(AF_INET6, &sa6->sin6_addr, buf_ntop, sizeof(buf_ntop) );
|
||||
sprintf( ipaddr_port, "[%s]:%d", buf_ntop, ntohs( sa6->sin6_port ) );
|
||||
}
|
||||
}
|
||||
|
||||
/************************************************************************
|
||||
@ -344,7 +353,7 @@ config_description_doc( INOUT IXML_Document * doc,
|
||||
*
|
||||
* Parameters :
|
||||
* INOUT IXML_Document *doc ; IXML Description document
|
||||
* IN const struct sockaddr_in* serverAddr ; socket address object
|
||||
* IN const struct sockaddr* serverAddr ; socket address object
|
||||
* providing the IP address and port information
|
||||
* IN const char* alias ; string containing the alias
|
||||
* IN time_t last_modified ; time when the XML document was
|
||||
@ -352,7 +361,7 @@ config_description_doc( INOUT IXML_Document * doc,
|
||||
* OUT char docURL[LINE_SIZE] ; buffer to hold the URL of the
|
||||
* document.
|
||||
* INOUT IXML_Document *doc:dom document whose urlbase is to be modified
|
||||
* IN const struct sockaddr_in* serverAddr : ip address and port of
|
||||
* IN const struct sockaddr* serverAddr : ip address and port of
|
||||
* the miniserver
|
||||
* IN const char* alias : a name to be used for the temp; e.g.:"foo.xml"
|
||||
* IN time_t last_modified : time
|
||||
@ -371,7 +380,7 @@ config_description_doc( INOUT IXML_Document * doc,
|
||||
************************************************************************/
|
||||
int
|
||||
configure_urlbase( INOUT IXML_Document * doc,
|
||||
IN const struct sockaddr_in *serverAddr,
|
||||
IN const struct sockaddr *serverAddr,
|
||||
IN const char *alias,
|
||||
IN time_t last_modified,
|
||||
OUT char docURL[LINE_SIZE] )
|
||||
|
Loading…
x
Reference in New Issue
Block a user