New UpnpRegisterRootDevice4 for legacy CPs.
Add a new UpnpRegisterRootDevice4 which allow user to specify a
description URL to be returned for legacy CPs (for example, CPs
searching for a v1 when the device is v2). Most of those CPs does not
work if they found a v2 in the XML description, so this new function is
only used to solve interoperability issues.
(cherry picked from commit 11f9a2bafe
)
This commit is contained in:
parent
bbe6d49b46
commit
daec6a0321
10
ChangeLog
10
ChangeLog
@ -255,6 +255,16 @@ Version 1.8.0
|
|||||||
Version 1.6.13
|
Version 1.6.13
|
||||||
*******************************************************************************
|
*******************************************************************************
|
||||||
|
|
||||||
|
2011-03-15 Fabrice Fontaine <fabrice.fontaine(at)orange-ftgroup.com>
|
||||||
|
|
||||||
|
New UpnpRegisterRootDevice4 for legacy CPs.
|
||||||
|
|
||||||
|
Add a new UpnpRegisterRootDevice4 which allow user to specify a
|
||||||
|
description URL to be returned for legacy CPs (for example, CPs
|
||||||
|
searching for a v1 when the device is v2). Most of those CPs does not
|
||||||
|
work if they found a v2 in the XML description, so this new function is
|
||||||
|
only used to solve interoperability issues.
|
||||||
|
|
||||||
2011-03-08 Iain Denniston <iain.denniston(at)gmail.com>
|
2011-03-08 Iain Denniston <iain.denniston(at)gmail.com>
|
||||||
Fix for memory leak.
|
Fix for memory leak.
|
||||||
|
|
||||||
|
@ -128,8 +128,9 @@
|
|||||||
#define UPNP_E_BUFFER_TOO_SMALL -106
|
#define UPNP_E_BUFFER_TOO_SMALL -106
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* \brief The description document passed to \b UpnpRegisterRootDevice or
|
* \brief The description document passed to \b UpnpRegisterRootDevice,
|
||||||
* \b UpnpRegisterRootDevice2 is invalid.
|
* \b UpnpRegisterRootDevice2 \b UpnpRegisterRootDevice3 or
|
||||||
|
* \b UpnpRegisterRootDevice4 is invalid.
|
||||||
*/
|
*/
|
||||||
#define UPNP_E_INVALID_DESC -107
|
#define UPNP_E_INVALID_DESC -107
|
||||||
|
|
||||||
@ -418,7 +419,8 @@ typedef int UpnpClient_Handle;
|
|||||||
|
|
||||||
/*!
|
/*!
|
||||||
* \brief Returned when a device application registers with
|
* \brief Returned when a device application registers with
|
||||||
* \b UpnpRegisterRootDevice or \b UpnpRegisterRootDevice2.
|
* \b UpnpRegisterRootDevice, \b UpnpRegisterRootDevice2,
|
||||||
|
* \b UpnpRegisterRootDevice3 or \b UpnpRegisterRootDevice4.
|
||||||
*
|
*
|
||||||
* Device handles can only be used with functions that operate with a device
|
* Device handles can only be used with functions that operate with a device
|
||||||
* handle.
|
* handle.
|
||||||
@ -840,8 +842,62 @@ EXPORT_SPEC int UpnpRegisterRootDevice3(
|
|||||||
const int AddressFamily);
|
const int AddressFamily);
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* \brief Unregisters a root device registered with \b UpnpRegisterRootDevice or
|
* \brief Registers a device application for a specific address family with
|
||||||
* \b UpnpRegisterRootDevice2.
|
* the UPnP library. This function can also be used to specify a dedicated
|
||||||
|
* description URL to be returned for legacy CPs.
|
||||||
|
*
|
||||||
|
* A device application cannot make any other API calls until it registers
|
||||||
|
* using this function. Device applications can also register as control
|
||||||
|
* points (see \b UpnpRegisterClient to get a control point handle to perform
|
||||||
|
* control point functionality).
|
||||||
|
*
|
||||||
|
* This is synchronous and does not generate any callbacks. Callbacks can occur
|
||||||
|
* as soon as this function returns.
|
||||||
|
*
|
||||||
|
* \return An integer representing one of the following:
|
||||||
|
* \li \c UPNP_E_SUCCESS: The operation completed successfully.
|
||||||
|
* \li \c UPNP_E_FINISH: The SDK is already terminated or
|
||||||
|
* is not initialized.
|
||||||
|
* \li \c UPNP_E_INVALID_DESC: The description document was not
|
||||||
|
* a valid device description.
|
||||||
|
* \li \c UPNP_E_INVALID_URL: The URL for the description document
|
||||||
|
* is not valid.
|
||||||
|
* \li \c UPNP_E_INVALID_PARAM: Either \b Callback or \b Hnd
|
||||||
|
* is not a valid pointer or \b DescURL is \c NULL.
|
||||||
|
* \li \c UPNP_E_NETWORK_ERROR: A network error occurred.
|
||||||
|
* \li \c UPNP_E_SOCKET_WRITE: An error or timeout occurred writing
|
||||||
|
* to a socket.
|
||||||
|
* \li \c UPNP_E_SOCKET_READ: An error or timeout occurred reading
|
||||||
|
* from a socket.
|
||||||
|
* \li \c UPNP_E_SOCKET_BIND: An error occurred binding a socket.
|
||||||
|
* \li \c UPNP_E_SOCKET_CONNECT: An error occurred connecting the
|
||||||
|
* socket.
|
||||||
|
* \li \c UPNP_E_OUTOF_SOCKET: Too many sockets are currently
|
||||||
|
* allocated.
|
||||||
|
* \li \c UPNP_E_OUTOF_MEMORY: There are insufficient resources to
|
||||||
|
* register this root device.
|
||||||
|
*/
|
||||||
|
EXPORT_SPEC int UpnpRegisterRootDevice4(
|
||||||
|
/*! [in] Pointer to a string containing the description URL for this root
|
||||||
|
* device instance. */
|
||||||
|
const char *DescUrl,
|
||||||
|
/*! [in] Pointer to the callback function for receiving asynchronous events. */
|
||||||
|
Upnp_FunPtr Callback,
|
||||||
|
/*! [in] Pointer to user data returned with the callback function when invoked. */
|
||||||
|
const void *Cookie,
|
||||||
|
/*! [out] Pointer to a variable to store the new device handle. */
|
||||||
|
UpnpDevice_Handle *Hnd,
|
||||||
|
/*! [in] Address family of this device. Can be AF_INET for an IPv4 device, or
|
||||||
|
* AF_INET6 for an IPv6 device. Defaults to AF_INET. */
|
||||||
|
const int AddressFamily,
|
||||||
|
/*! [in] Pointer to a string containing the description URL to be returned for
|
||||||
|
* legacy CPs for this root device instance. */
|
||||||
|
const char *LowerDescUrl);
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* \brief Unregisters a root device registered with \b UpnpRegisterRootDevice,
|
||||||
|
* \b UpnpRegisterRootDevice2, \b UpnpRegisterRootDevice3 or
|
||||||
|
* \b UpnpRegisterRootDevice4.
|
||||||
*
|
*
|
||||||
* After this call, the \b UpnpDevice_Handle is no longer valid. For all
|
* After this call, the \b UpnpDevice_Handle is no longer valid. For all
|
||||||
* advertisements that have not yet expired, the SDK sends a device unavailable
|
* advertisements that have not yet expired, the SDK sends a device unavailable
|
||||||
|
@ -790,6 +790,10 @@ int UpnpRegisterRootDevice(
|
|||||||
HInfo->aliasInstalled = 0;
|
HInfo->aliasInstalled = 0;
|
||||||
HInfo->HType = HND_DEVICE;
|
HInfo->HType = HND_DEVICE;
|
||||||
strcpy(HInfo->DescURL, DescUrl);
|
strcpy(HInfo->DescURL, DescUrl);
|
||||||
|
strcpy(HInfo->LowerDescURL, DescUrl);
|
||||||
|
UpnpPrintf(UPNP_ALL, API, __FILE__, __LINE__,
|
||||||
|
"Following Root Device URL will be used when answering to legacy CPs %s\n",
|
||||||
|
HInfo->LowerDescURL);
|
||||||
HInfo->Callback = Fun;
|
HInfo->Callback = Fun;
|
||||||
HInfo->Cookie = (void *)Cookie;
|
HInfo->Cookie = (void *)Cookie;
|
||||||
HInfo->MaxAge = DEFAULT_MAXAGE;
|
HInfo->MaxAge = DEFAULT_MAXAGE;
|
||||||
@ -952,6 +956,10 @@ int UpnpRegisterRootDevice2(
|
|||||||
goto exit_function;
|
goto exit_function;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
strcpy(HInfo->LowerDescURL, HInfo->DescURL);
|
||||||
|
UpnpPrintf(UPNP_ALL, API, __FILE__, __LINE__,
|
||||||
|
"Following Root Device URL will be used when answering to legacy CPs %s\n",
|
||||||
|
HInfo->LowerDescURL);
|
||||||
HInfo->aliasInstalled = config_baseURL != 0;
|
HInfo->aliasInstalled = config_baseURL != 0;
|
||||||
HInfo->HType = HND_DEVICE;
|
HInfo->HType = HND_DEVICE;
|
||||||
HInfo->Callback = Fun;
|
HInfo->Callback = Fun;
|
||||||
@ -1034,6 +1042,23 @@ int UpnpRegisterRootDevice3(
|
|||||||
const void *Cookie,
|
const void *Cookie,
|
||||||
UpnpDevice_Handle *Hnd,
|
UpnpDevice_Handle *Hnd,
|
||||||
const int AddressFamily)
|
const int AddressFamily)
|
||||||
|
{
|
||||||
|
UpnpPrintf(UPNP_ALL, API, __FILE__, __LINE__,
|
||||||
|
"Inside UpnpRegisterRootDevice3\n");
|
||||||
|
return UpnpRegisterRootDevice4(DescUrl, Fun, Cookie, Hnd,
|
||||||
|
AddressFamily, NULL);
|
||||||
|
}
|
||||||
|
#endif /* INCLUDE_DEVICE_APIS */
|
||||||
|
|
||||||
|
|
||||||
|
#ifdef INCLUDE_DEVICE_APIS
|
||||||
|
int UpnpRegisterRootDevice4(
|
||||||
|
const char *DescUrl,
|
||||||
|
Upnp_FunPtr Fun,
|
||||||
|
const void *Cookie,
|
||||||
|
UpnpDevice_Handle *Hnd,
|
||||||
|
const int AddressFamily,
|
||||||
|
const char *LowerDescUrl)
|
||||||
{
|
{
|
||||||
struct Handle_Info *HInfo;
|
struct Handle_Info *HInfo;
|
||||||
int retVal = 0;
|
int retVal = 0;
|
||||||
@ -1043,7 +1068,7 @@ int UpnpRegisterRootDevice3(
|
|||||||
HandleLock();
|
HandleLock();
|
||||||
|
|
||||||
UpnpPrintf(UPNP_ALL, API, __FILE__, __LINE__,
|
UpnpPrintf(UPNP_ALL, API, __FILE__, __LINE__,
|
||||||
"Inside UpnpRegisterRootDevice3\n");
|
"Inside UpnpRegisterRootDevice4\n");
|
||||||
if (UpnpSdkInit != 1) {
|
if (UpnpSdkInit != 1) {
|
||||||
retVal = UPNP_E_FINISH;
|
retVal = UPNP_E_FINISH;
|
||||||
goto exit_function;
|
goto exit_function;
|
||||||
@ -1087,6 +1112,13 @@ int UpnpRegisterRootDevice3(
|
|||||||
HInfo->aliasInstalled = 0;
|
HInfo->aliasInstalled = 0;
|
||||||
HInfo->HType = HND_DEVICE;
|
HInfo->HType = HND_DEVICE;
|
||||||
strcpy(HInfo->DescURL, DescUrl);
|
strcpy(HInfo->DescURL, DescUrl);
|
||||||
|
if (LowerDescUrl == NULL)
|
||||||
|
strcpy(HInfo->LowerDescURL, DescUrl);
|
||||||
|
else
|
||||||
|
strcpy(HInfo->LowerDescURL, LowerDescUrl);
|
||||||
|
UpnpPrintf(UPNP_ALL, API, __FILE__, __LINE__,
|
||||||
|
"Following Root Device URL will be used when answering to legacy CPs %s\n",
|
||||||
|
HInfo->LowerDescURL);
|
||||||
HInfo->Callback = Fun;
|
HInfo->Callback = Fun;
|
||||||
HInfo->Cookie = (void *)Cookie;
|
HInfo->Cookie = (void *)Cookie;
|
||||||
HInfo->MaxAge = DEFAULT_MAXAGE;
|
HInfo->MaxAge = DEFAULT_MAXAGE;
|
||||||
@ -1109,8 +1141,8 @@ int UpnpRegisterRootDevice3(
|
|||||||
goto exit_function;
|
goto exit_function;
|
||||||
}
|
}
|
||||||
UpnpPrintf(UPNP_ALL, API, __FILE__, __LINE__,
|
UpnpPrintf(UPNP_ALL, API, __FILE__, __LINE__,
|
||||||
"UpnpRegisterRootDevice3: Valid Description\n"
|
"UpnpRegisterRootDevice4: Valid Description\n"
|
||||||
"UpnpRegisterRootDevice3: DescURL : %s\n",
|
"UpnpRegisterRootDevice4: DescURL : %s\n",
|
||||||
HInfo->DescURL);
|
HInfo->DescURL);
|
||||||
|
|
||||||
HInfo->DeviceList = ixmlDocument_getElementsByTagName(
|
HInfo->DeviceList = ixmlDocument_getElementsByTagName(
|
||||||
@ -1122,7 +1154,7 @@ int UpnpRegisterRootDevice3(
|
|||||||
ixmlDocument_free(HInfo->DescDocument);
|
ixmlDocument_free(HInfo->DescDocument);
|
||||||
FreeHandle(*Hnd);
|
FreeHandle(*Hnd);
|
||||||
UpnpPrintf(UPNP_CRITICAL, API, __FILE__, __LINE__,
|
UpnpPrintf(UPNP_CRITICAL, API, __FILE__, __LINE__,
|
||||||
"UpnpRegisterRootDevice3: No devices found for RootDevice\n");
|
"UpnpRegisterRootDevice4: No devices found for RootDevice\n");
|
||||||
retVal = UPNP_E_INVALID_DESC;
|
retVal = UPNP_E_INVALID_DESC;
|
||||||
goto exit_function;
|
goto exit_function;
|
||||||
}
|
}
|
||||||
@ -1131,26 +1163,26 @@ int UpnpRegisterRootDevice3(
|
|||||||
HInfo->DescDocument, "serviceList" );
|
HInfo->DescDocument, "serviceList" );
|
||||||
if (!HInfo->ServiceList) {
|
if (!HInfo->ServiceList) {
|
||||||
UpnpPrintf(UPNP_CRITICAL, API, __FILE__, __LINE__,
|
UpnpPrintf(UPNP_CRITICAL, API, __FILE__, __LINE__,
|
||||||
"UpnpRegisterRootDevice3: No services found for RootDevice\n");
|
"UpnpRegisterRootDevice4: No services found for RootDevice\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* GENA SET UP
|
* GENA SET UP
|
||||||
*/
|
*/
|
||||||
UpnpPrintf(UPNP_ALL, API, __FILE__, __LINE__,
|
UpnpPrintf(UPNP_ALL, API, __FILE__, __LINE__,
|
||||||
"UpnpRegisterRootDevice3: Gena Check\n" );
|
"UpnpRegisterRootDevice4: Gena Check\n" );
|
||||||
hasServiceTable = getServiceTable(
|
hasServiceTable = getServiceTable(
|
||||||
(IXML_Node *)HInfo->DescDocument,
|
(IXML_Node *)HInfo->DescDocument,
|
||||||
&HInfo->ServiceTable,
|
&HInfo->ServiceTable,
|
||||||
HInfo->DescURL);
|
HInfo->DescURL);
|
||||||
if (hasServiceTable) {
|
if (hasServiceTable) {
|
||||||
UpnpPrintf(UPNP_ALL, API, __FILE__, __LINE__,
|
UpnpPrintf(UPNP_ALL, API, __FILE__, __LINE__,
|
||||||
"UpnpRegisterRootDevice3: GENA Service Table \n"
|
"UpnpRegisterRootDevice4: GENA Service Table \n"
|
||||||
"Here are the known services: \n" );
|
"Here are the known services: \n" );
|
||||||
printServiceTable(&HInfo->ServiceTable, UPNP_ALL, API);
|
printServiceTable(&HInfo->ServiceTable, UPNP_ALL, API);
|
||||||
} else {
|
} else {
|
||||||
UpnpPrintf(UPNP_ALL, API, __FILE__, __LINE__,
|
UpnpPrintf(UPNP_ALL, API, __FILE__, __LINE__,
|
||||||
"\nUpnpRegisterRootDevice3: Empty service table\n");
|
"\nUpnpRegisterRootDevice4: Empty service table\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
if (AddressFamily == AF_INET) {
|
if (AddressFamily == AF_INET) {
|
||||||
@ -1163,7 +1195,7 @@ int UpnpRegisterRootDevice3(
|
|||||||
|
|
||||||
exit_function:
|
exit_function:
|
||||||
UpnpPrintf(UPNP_ALL, API, __FILE__, __LINE__,
|
UpnpPrintf(UPNP_ALL, API, __FILE__, __LINE__,
|
||||||
"Exiting RegisterRootDevice3, return value == %d\n", retVal);
|
"Exiting RegisterRootDevice4, return value == %d\n", retVal);
|
||||||
HandleUnlock();
|
HandleUnlock();
|
||||||
|
|
||||||
return retVal;
|
return retVal;
|
||||||
|
@ -80,6 +80,9 @@ struct Handle_Info
|
|||||||
#ifdef INCLUDE_DEVICE_APIS
|
#ifdef INCLUDE_DEVICE_APIS
|
||||||
/*! URL for the use of SSDP. */
|
/*! URL for the use of SSDP. */
|
||||||
char DescURL[LINE_SIZE];
|
char DescURL[LINE_SIZE];
|
||||||
|
/*! URL for the use of SSDP when answering to legacy CPs (CP searching
|
||||||
|
* for a v1 when the device is v2). */
|
||||||
|
char LowerDescURL[LINE_SIZE];
|
||||||
/*! XML file path for device description. */
|
/*! XML file path for device description. */
|
||||||
char DescXML[LINE_SIZE];
|
char DescXML[LINE_SIZE];
|
||||||
/* Advertisement timeout */
|
/* Advertisement timeout */
|
||||||
|
@ -366,10 +366,13 @@ static int check_soap_body(
|
|||||||
if (actionNode) {
|
if (actionNode) {
|
||||||
ns = ixmlNode_getNamespaceURI(actionNode);
|
ns = ixmlNode_getNamespaceURI(actionNode);
|
||||||
name = ixmlNode_getLocalName(actionNode);
|
name = ixmlNode_getLocalName(actionNode);
|
||||||
|
/* Don't check version number, to accept a
|
||||||
|
* request comming on a v1 service when
|
||||||
|
* publishing a v2 service */
|
||||||
if (name &&
|
if (name &&
|
||||||
ns &&
|
ns &&
|
||||||
!strcmp(actionName, name) &&
|
!strcmp(actionName, name) &&
|
||||||
!strcmp(urn, ns))
|
!strncmp(urn, ns, strlen (urn) - 2))
|
||||||
ret_code = UPNP_E_SUCCESS;
|
ret_code = UPNP_E_SUCCESS;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -440,7 +443,9 @@ static int check_soap_action_header(
|
|||||||
return ret_code;
|
return ret_code;
|
||||||
}
|
}
|
||||||
snprintf(ns_compare, tempSize, "\"%s", urn);
|
snprintf(ns_compare, tempSize, "\"%s", urn);
|
||||||
if (strcmp(temp_header_value, ns_compare))
|
/* Don't check version number, to accept a request comming on a v1
|
||||||
|
* service when publishing a v2 service */
|
||||||
|
if (strncmp(temp_header_value, ns_compare, strlen(ns_compare) - 2))
|
||||||
ret_code = UPNP_E_INVALID_ACTION;
|
ret_code = UPNP_E_INVALID_ACTION;
|
||||||
else {
|
else {
|
||||||
ret_code = UPNP_E_SUCCESS;
|
ret_code = UPNP_E_SUCCESS;
|
||||||
|
@ -245,10 +245,18 @@ int AdvertiseAndReply(int AdFlag, UpnpDevice_Handle Hnd,
|
|||||||
}
|
}
|
||||||
case SSDP_DEVICETYPE: {
|
case SSDP_DEVICETYPE: {
|
||||||
if (!strncasecmp(DeviceType, devType, strlen(DeviceType) - 2)) {
|
if (!strncasecmp(DeviceType, devType, strlen(DeviceType) - 2)) {
|
||||||
if (atoi(&DeviceType[strlen(DeviceType)
|
if (atoi(strrchr(DeviceType, ':') + 1)
|
||||||
- 1]) <= atoi(&devType[strlen(devType) - 1])) {
|
< atoi(&devType[strlen(devType) - 1])) {
|
||||||
/* the requested version is lower than the device version
|
/* the requested version is lower than the device version
|
||||||
* must reply with the lower version number */
|
* must reply with the lower version number and the lower
|
||||||
|
* description URL */
|
||||||
|
UpnpPrintf(UPNP_INFO, API, __FILE__, __LINE__,
|
||||||
|
"DeviceType=%s and search devType=%s MATCH\n",
|
||||||
|
devType, DeviceType);
|
||||||
|
SendReply(DestAddr, DeviceType, 0, UDNstr, SInfo->LowerDescURL,
|
||||||
|
defaultExp, 1);
|
||||||
|
} else if (atoi(strrchr(DeviceType, ':') + 1)
|
||||||
|
== atoi(&devType[strlen(devType) - 1])) {
|
||||||
UpnpPrintf(UPNP_INFO, API, __FILE__, __LINE__,
|
UpnpPrintf(UPNP_INFO, API, __FILE__, __LINE__,
|
||||||
"DeviceType=%s and search devType=%s MATCH\n",
|
"DeviceType=%s and search devType=%s MATCH\n",
|
||||||
devType, DeviceType);
|
devType, DeviceType);
|
||||||
@ -347,10 +355,18 @@ int AdvertiseAndReply(int AdFlag, UpnpDevice_Handle Hnd,
|
|||||||
case SSDP_SERVICE:
|
case SSDP_SERVICE:
|
||||||
if (ServiceType) {
|
if (ServiceType) {
|
||||||
if (!strncasecmp(ServiceType, servType, strlen(ServiceType) - 2)) {
|
if (!strncasecmp(ServiceType, servType, strlen(ServiceType) - 2)) {
|
||||||
if (atoi(&ServiceType[strlen(ServiceType) - 1]) <=
|
if (atoi(strrchr(ServiceType, ':') + 1) <
|
||||||
atoi(&servType[strlen(servType) - 1])) {
|
atoi(&servType[strlen(servType) - 1])) {
|
||||||
/* the requested version is lower than the service version
|
/* the requested version is lower than the service version
|
||||||
* must reply with the lower version number */
|
* must reply with the lower version number and the lower
|
||||||
|
* description URL */
|
||||||
|
UpnpPrintf(UPNP_INFO, API, __FILE__, __LINE__,
|
||||||
|
"ServiceType=%s and search servType=%s MATCH\n",
|
||||||
|
ServiceType, servType);
|
||||||
|
SendReply(DestAddr, ServiceType, 0, UDNstr, SInfo->LowerDescURL,
|
||||||
|
defaultExp, 1);
|
||||||
|
} else if (atoi(strrchr (ServiceType, ':') + 1) ==
|
||||||
|
atoi(&servType[strlen(servType) - 1])) {
|
||||||
UpnpPrintf(UPNP_INFO, API, __FILE__, __LINE__,
|
UpnpPrintf(UPNP_INFO, API, __FILE__, __LINE__,
|
||||||
"ServiceType=%s and search servType=%s MATCH\n",
|
"ServiceType=%s and search servType=%s MATCH\n",
|
||||||
ServiceType, servType);
|
ServiceType, servType);
|
||||||
|
Loading…
Reference in New Issue
Block a user