[gssdp] resource-browser: Implement ssdp:update handling



commit 7c8675e065019016946c4b84115072a19ca8820b
Author: Jens Georg <mail jensge org>
Date:   Mon Jan 28 22:04:16 2019 +0100

    resource-browser: Implement ssdp:update handling

 libgssdp/gssdp-resource-browser.c | 89 +++++++++++++++++++++++++++++++++++++++
 libgssdp/gssdp-resource-browser.h |  7 ++-
 2 files changed, 95 insertions(+), 1 deletion(-)
---
diff --git a/libgssdp/gssdp-resource-browser.c b/libgssdp/gssdp-resource-browser.c
index ebe501a..1b3966c 100644
--- a/libgssdp/gssdp-resource-browser.c
+++ b/libgssdp/gssdp-resource-browser.c
@@ -85,6 +85,7 @@ enum {
 enum {
         RESOURCE_AVAILABLE,
         RESOURCE_UNAVAILABLE,
+        RESOURCE_UPDATE,
         LAST_SIGNAL
 };
 
@@ -384,6 +385,30 @@ gssdp_resource_browser_class_init (GSSDPResourceBrowserClass *klass)
                               G_TYPE_NONE,
                               1,
                               G_TYPE_STRING);
+
+        /**
+         * GSSDPResourceBrowser::resource-update:
+         * @resource_browser: The #GSSDPResourceBrowser that received the
+         * signal
+         * @usn: The USN of the resource
+         * @boot_id: The current boot-id
+         * @next_boot_id : The next boot-id
+         *
+         * The ::resource-update signal is emitted whenever an UPnP 1.1
+         * device is about to change it's BOOTID.
+         **/
+        signals[RESOURCE_UPDATE] =
+                g_signal_new ("resource-update",
+                              GSSDP_TYPE_RESOURCE_BROWSER,
+                              G_SIGNAL_RUN_LAST,
+                              G_STRUCT_OFFSET (GSSDPResourceBrowserClass,
+                                               resource_update),
+                              NULL, NULL, NULL,
+                              G_TYPE_NONE,
+                              3,
+                              G_TYPE_STRING,
+                              G_TYPE_UINT,
+                              G_TYPE_UINT);
 }
 
 /**
@@ -909,6 +934,66 @@ resource_available (GSSDPResourceBrowser *resource_browser,
                 g_list_free_full (locations, g_free);
 }
 
+static void
+resource_update (GSSDPResourceBrowser *resource_browser,
+                 SoupMessageHeaders   *headers)
+{
+        GSSDPResourceBrowserPrivate *priv;
+        const char *usn;
+        const char *boot_id_header;
+        const char *next_boot_id_header;
+        char *canonical_usn;
+        guint boot_id;
+        guint next_boot_id;
+        gint64 out;
+
+        priv = gssdp_resource_browser_get_instance_private (resource_browser);
+        usn = soup_message_headers_get_one (headers, "USN");
+        boot_id_header = soup_message_headers_get_one (headers, "BOOTID.UPNP.ORG");
+        next_boot_id_header = soup_message_headers_get_one (headers, "NEXTBOOTID.UPNP.ORG");
+
+        if (!usn)
+                return; /* No USN specified */
+
+        if (!boot_id_header)
+                return;
+
+        if (!next_boot_id_header)
+                return;
+
+        if (!g_ascii_string_to_signed (boot_id_header, 10, 0, G_MAXINT32, &out, NULL))
+                return;
+        boot_id = out;
+
+        if (!g_ascii_string_to_signed (next_boot_id_header, 10, 0, G_MAXINT32, &out, NULL))
+                return;
+        next_boot_id = out;
+
+        if (priv->version > 0) {
+                char *version;
+                version = g_strrstr (usn, ":");
+                canonical_usn = g_strndup (usn, version - usn);
+        } else {
+                canonical_usn = g_strdup (usn);
+        }
+
+        /* Only continue if we know about this. if not, there will be an
+         * announcement afterwards anyway */
+        if (!g_hash_table_lookup (priv->resources,
+                                  canonical_usn))
+                goto out;
+
+        g_signal_emit (resource_browser,
+                       signals[RESOURCE_UPDATE],
+                       0,
+                       usn,
+                       boot_id,
+                       next_boot_id);
+out:
+        g_free (canonical_usn);
+
+}
+
 static void
 resource_unavailable (GSSDPResourceBrowser *resource_browser,
                       SoupMessageHeaders   *headers)
@@ -1037,6 +1122,10 @@ received_announcement (GSSDPResourceBrowser *resource_browser,
                           SSDP_BYEBYE_NTS,
                           strlen (SSDP_BYEBYE_NTS)) == 0)
                 resource_unavailable (resource_browser, headers);
+        else if (strncmp (header,
+                          SSDP_UPDATE_NTS,
+                          strlen (SSDP_UPDATE_NTS)) == 0)
+                resource_update (resource_browser, headers);
 }
 
 /*
diff --git a/libgssdp/gssdp-resource-browser.h b/libgssdp/gssdp-resource-browser.h
index 78a646b..f04c429 100644
--- a/libgssdp/gssdp-resource-browser.h
+++ b/libgssdp/gssdp-resource-browser.h
@@ -43,7 +43,12 @@ struct _GSSDPResourceBrowserClass {
         void (* resource_available)   (GSSDPResourceBrowser *resource_browser,
                                        const char           *usn,
                                        const GList          *locations);
-        
+
+        void (* resource_update)      (GSSDPResourceBrowser *resource_browser,
+                                       const char           *usn,
+                                       guint                 boot_id,
+                                       guint                 next_boot_id);
+
         void (* resource_unavailable) (GSSDPResourceBrowser *resource_browser,
                                        const char           *usn);
 


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]