summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJens Georg <mail@jensge.org>2021-06-14 22:55:53 +0200
committerJens Georg <mail@jensge.org>2021-06-14 22:55:53 +0200
commitbb5eb1ca1bda27b0c21435af85e2ad390ce58479 (patch)
treefefa7c1d417e6813df8ba9d0062c4d606987c67a
parent0490ea5a65683397816eb03188c0b78806a238c4 (diff)
downloadgupnp-wip/phako/25.tar.gz
wip: Allow subdevices to have the same UDN as parentwip/phako/25
This is ambigous in the spec. You could either read that you need a UDN per sub-device or one UDN for the root device
-rw-r--r--libgupnp/gupnp-control-point.c69
1 files changed, 55 insertions, 14 deletions
diff --git a/libgupnp/gupnp-control-point.c b/libgupnp/gupnp-control-point.c
index dc04732..80f7e2e 100644
--- a/libgupnp/gupnp-control-point.c
+++ b/libgupnp/gupnp-control-point.c
@@ -31,6 +31,13 @@
#define GUPNP_MAX_DESCRIPTION_DOWNLOAD_RETRIES 4
#define GUPNP_INITIAL_DESCRIPTION_RETRY_TIMEOUT 5
+typedef enum
+{
+ RESOURCE_TYPE_UNSPECIFIED,
+ RESOURCE_TYPE_DEVICE,
+ RESOURCE_TYPE_SERVICE,
+} ResourceType;
+
struct _GUPnPControlPointPrivate {
GUPnPResourceFactory *factory;
@@ -66,6 +73,7 @@ typedef struct {
GUPnPControlPoint *control_point;
char *udn;
+ ResourceType type;
char *service_type;
char *description_url;
@@ -261,7 +269,8 @@ find_service_node (GUPnPControlPoint *control_point,
static GList *
find_device_node (GUPnPControlPoint *control_point,
- const char *udn)
+ const char *udn,
+ const char *type_string)
{
GList *l;
GUPnPControlPointPrivate *priv;
@@ -274,7 +283,10 @@ find_device_node (GUPnPControlPoint *control_point,
info = GUPNP_DEVICE_INFO (l->data);
- if (strcmp (udn, gupnp_device_info_get_udn (info)) == 0)
+ if (g_str_equal (udn, gupnp_device_info_get_udn (info)) &&
+ ((type_string == NULL) ||
+ g_str_equal (type_string,
+ gupnp_device_info_get_device_type (info))))
break;
l = l->next;
@@ -328,6 +340,7 @@ create_and_report_device_proxy (GUPnPControlPoint *control_point,
GUPnPXMLDoc *doc,
xmlNode *element,
const char *udn,
+ const char *type_string,
const char *description_url,
SoupURI *url_base)
{
@@ -336,7 +349,7 @@ create_and_report_device_proxy (GUPnPControlPoint *control_point,
GUPnPContext *context;
GUPnPControlPointPrivate *priv;
- if (find_device_node (control_point, udn) != NULL)
+ if (find_device_node (control_point, udn, type_string) != NULL)
/* We already have a proxy for this device */
return;
@@ -450,6 +463,7 @@ process_device_list (xmlNode *element,
GUPnPControlPoint *control_point,
GUPnPXMLDoc *doc,
const char *udn,
+ ResourceType type,
const char *service_type,
const char *description_url,
SoupURI *url_base)
@@ -474,6 +488,7 @@ process_device_list (xmlNode *element,
control_point,
doc,
udn,
+ type,
service_type,
description_url,
url_base);
@@ -493,7 +508,7 @@ process_device_list (xmlNode *element,
/* Match */
- if (service_type) {
+ if (type == RESOURCE_TYPE_SERVICE) {
/* Dive into serviceList */
children = xml_util_get_element (element,
"serviceList",
@@ -508,13 +523,20 @@ process_device_list (xmlNode *element,
description_url,
url_base);
}
- } else
+ } else {
+ prop = xml_util_get_child_element_content (
+ element,
+ "deviceType");
+
create_and_report_device_proxy (control_point,
doc,
element,
udn,
+ (char *) prop,
description_url,
url_base);
+ xmlFree (prop);
+ }
}
g_object_unref (control_point);
@@ -527,6 +549,7 @@ static void
description_loaded (GUPnPControlPoint *control_point,
GUPnPXMLDoc *doc,
const char *udn,
+ ResourceType type,
const char *service_type,
const char *description_url)
{
@@ -558,6 +581,7 @@ description_loaded (GUPnPControlPoint *control_point,
control_point,
doc,
udn,
+ type,
service_type,
description_url,
url_base);
@@ -595,6 +619,7 @@ got_description_url (SoupSession *session,
description_loaded (data->control_point,
doc,
data->udn,
+ data->type,
data->service_type,
data->description_url);
@@ -616,6 +641,7 @@ got_description_url (SoupSession *session,
description_loaded (data->control_point,
doc,
data->udn,
+ data->type,
data->service_type,
data->description_url);
@@ -676,6 +702,7 @@ static void
load_description (GUPnPControlPoint *control_point,
const char *description_url,
const char *udn,
+ ResourceType type,
const char *service_type,
guint max_tries,
guint timeout)
@@ -691,6 +718,7 @@ load_description (GUPnPControlPoint *control_point,
description_loaded (control_point,
doc,
udn,
+ type,
service_type,
description_url);
} else {
@@ -728,6 +756,7 @@ load_description (GUPnPControlPoint *control_point,
data->control_point = control_point;
data->udn = g_strdup (udn);
+ data->type = type;
data->service_type = g_strdup (service_type);
data->description_url = g_strdup (description_url);
data->timeout_source = NULL;
@@ -754,6 +783,7 @@ description_url_retry_timeout (gpointer user_data)
load_description (data->control_point,
data->description_url,
data->udn,
+ data->type,
data->service_type,
data->tries,
data->timeout);
@@ -765,6 +795,7 @@ description_url_retry_timeout (gpointer user_data)
static gboolean
parse_usn (const char *usn,
+ ResourceType *type,
char **udn,
char **service_type)
{
@@ -774,6 +805,7 @@ parse_usn (const char *usn,
ret = FALSE;
+ *type = RESOURCE_TYPE_UNSPECIFIED;
*udn = *service_type = NULL;
/* Verify we have a valid USN */
@@ -793,6 +825,7 @@ parse_usn (const char *usn,
/* uuid:device-UUID */
*udn = bits[0];
+ *type = RESOURCE_TYPE_DEVICE;
ret = TRUE;
@@ -804,11 +837,12 @@ parse_usn (const char *usn,
n_second_bits = g_strv_length (second_bits);
if (n_second_bits >= 2 &&
- !strcmp (second_bits[0], "upnp") &&
- !strcmp (second_bits[1], "rootdevice")) {
+ g_str_equal(second_bits[0], "upnp") &&
+ g_str_equal(second_bits[1], "rootdevice")) {
/* uuid:device-UUID::upnp:rootdevice */
*udn = bits[0];
+ *type = RESOURCE_TYPE_DEVICE;
ret = TRUE;
} else if (n_second_bits >= 3 &&
@@ -816,12 +850,15 @@ parse_usn (const char *usn,
/* uuid:device-UIID::urn:domain-name:service/device:
* type:v */
- if (!strcmp (second_bits[2], "device")) {
+ if (g_str_equal (second_bits[2], "device")) {
*udn = bits[0];
+ *type = RESOURCE_TYPE_DEVICE;
+ *service_type = bits[1];
ret = TRUE;
- } else if (!strcmp (second_bits[2], "service")) {
+ } else if (g_str_equal (second_bits[2], "service")) {
*udn = bits[0];
+ *type = RESOURCE_TYPE_SERVICE;
*service_type = bits[1];
ret = TRUE;
@@ -861,13 +898,16 @@ gupnp_control_point_resource_available (GSSDPResourceBrowser *resource_browser,
return;
}
+ ResourceType type;
+
/* Parse USN */
- if (!parse_usn (usn, &udn, &service_type))
+ if (!parse_usn (usn, &type, &udn, &service_type))
return;
load_description (control_point,
locations->data,
udn,
+ type,
service_type,
GUPNP_MAX_DESCRIPTION_DOWNLOAD_RETRIES,
GUPNP_INITIAL_DESCRIPTION_RETRY_TIMEOUT);
@@ -885,16 +925,17 @@ gupnp_control_point_resource_unavailable
char *udn, *service_type;
GetDescriptionURLData *get_data;
GUPnPControlPointPrivate *priv;
+ ResourceType type;
control_point = GUPNP_CONTROL_POINT (resource_browser);
priv = gupnp_control_point_get_instance_private (control_point);
/* Parse USN */
- if (!parse_usn (usn, &udn, &service_type))
+ if (!parse_usn (usn, &type, &udn, &service_type))
return;
/* Find proxy */
- if (service_type) {
+ if (type == RESOURCE_TYPE_SERVICE) {
GList *l = find_service_node (control_point, udn, service_type);
if (l) {
@@ -913,8 +954,8 @@ gupnp_control_point_resource_unavailable
g_object_unref (proxy);
}
- } else {
- GList *l = find_device_node (control_point, udn);
+ } else if (type == RESOURCE_TYPE_DEVICE){
+ GList *l = find_device_node (control_point, udn, service_type);
if (l) {
GUPnPDeviceProxy *proxy;