[gssdp] Add support for additionnal vendor specific headers in messages



commit 9f02229ad7322a4c5b285b393e06ddc54b56ad8c
Author: Louis-Francis Ratté-Boulianne <lfrb collabora com>
Date:   Mon May 5 23:35:44 2014 -0400

    Add support for additionnal vendor specific headers in messages
    
    Add new API to GSSDPClient to add custom headers to every message
    sent. It allows support for applications that need non-standard
    headers.
    
    https://bugzilla.gnome.org/show_bug.cgi?id=729613

 libgssdp/gssdp-client.c       |  117 ++++++++++++++++++++++++++++++++++++++++-
 libgssdp/gssdp-client.h       |   12 ++++
 libgssdp/gssdp-protocol.h     |    8 ++--
 tests/gtest/test-functional.c |    4 +-
 tests/gtest/test-regression.c |    4 +-
 5 files changed, 135 insertions(+), 10 deletions(-)
---
diff --git a/libgssdp/gssdp-client.c b/libgssdp/gssdp-client.c
index 144ebaf..698af15 100644
--- a/libgssdp/gssdp-client.c
+++ b/libgssdp/gssdp-client.c
@@ -113,12 +113,19 @@ struct _GSSDPNetworkDevice {
 };
 typedef struct _GSSDPNetworkDevice GSSDPNetworkDevice;
 
+struct _GSSDPHeaderField {
+        char *name;
+        char *value;
+};
+typedef struct _GSSDPHeaderField GSSDPHeaderField;
+
 struct _GSSDPClientPrivate {
         char              *server_id;
 
         guint              socket_ttl;
         guint              msearch_port;
         GSSDPNetworkDevice device;
+        GList             *headers;
 
         GSSDPSocketSource *request_socket;
         GSSDPSocketSource *multicast_socket;
@@ -832,6 +839,109 @@ gssdp_client_get_active (GSSDPClient *client)
         return client->priv->active;
 }
 
+static void
+header_field_free (GSSDPHeaderField *header)
+{
+        g_free (header->name);
+        g_free (header->value);
+        g_slice_free (GSSDPHeaderField, header);
+}
+
+static gchar *
+append_header_fields (GSSDPClient *client,
+                      const gchar *message)
+{
+        GString *str;
+        GList *iter;
+
+        str = g_string_new (message);
+
+        for (iter = client->priv->headers; iter; iter = iter->next) {
+                GSSDPHeaderField *header = (GSSDPHeaderField *) iter->data;
+                g_string_append_printf (str, "%s: %s\r\n",
+                                        header->name,
+                                        header->value ?: "");
+        }
+
+        g_string_append (str, "\r\n");
+
+        return g_string_free (str, FALSE);
+}
+
+/**
+ * gssdp_client_append_header:
+ * @client: A #GSSDPClient
+ * @name: Header name
+ * @value: Header value
+ *
+ * Adds a header field to the message sent by this @client. It is intended to
+ * be used by clients requiring vendor specific header fields. (If there is an
+ * existing header with name name , then this creates a second one).
+ **/
+void
+gssdp_client_append_header (GSSDPClient *client,
+                            const char  *name,
+                            const char  *value)
+{
+        GSSDPHeaderField *header;
+
+        g_return_if_fail (GSSDP_IS_CLIENT (client));
+        g_return_if_fail (name != NULL);
+
+        header = g_slice_new (GSSDPHeaderField);
+        header->name = g_strdup (name);
+        header->value = g_strdup (value);
+        client->priv->headers = g_list_append (client->priv->headers, header);
+}
+
+/**
+ * gssdp_client_remove_header:
+ * @client: A #GSSDPClient
+ * @name: Header name
+ *
+ * Removes @name from the list of headers . If there are multiple values for
+ * @name, they are all removed.
+ **/
+void
+gssdp_client_remove_header (GSSDPClient *client,
+                            const char  *name)
+{
+        GSSDPClientPrivate *priv;
+        GList *l;
+
+        g_return_if_fail (GSSDP_IS_CLIENT (client));
+        g_return_if_fail (name != NULL);
+
+        priv = client->priv;
+        l = priv->headers;
+        while (l != NULL)
+        {
+                GList *next = l->next;
+                GSSDPHeaderField *header = l->data;
+
+                if (!g_strcmp0 (header->name, name)) {
+                        header_field_free (header);
+                        priv->headers = g_list_delete_link (priv->headers, l);
+                }
+                l = next;
+        }
+}
+
+/**
+ * gssdp_client_clear_headers:
+ * @client: A #GSSDPClient
+ *
+ * Removes all the headers for this @client.
+ **/
+void
+gssdp_client_clear_headers (GSSDPClient *client)
+{
+        g_return_if_fail (GSSDP_IS_CLIENT (client));
+
+        g_list_free_full (client->priv->headers,
+                          (GDestroyNotify) header_field_free);
+}
+
 /**
  * _gssdp_client_send_message:
  * @client: A #GSSDPClient
@@ -853,6 +963,7 @@ _gssdp_client_send_message (GSSDPClient      *client,
         GInetAddress *inet_address = NULL;
         GSocketAddress *address = NULL;
         GSocket *socket;
+        char *extended_message;
 
         g_return_if_fail (GSSDP_IS_CLIENT (client));
         g_return_if_fail (message != NULL);
@@ -878,11 +989,12 @@ _gssdp_client_send_message (GSSDPClient      *client,
 
         inet_address = g_inet_address_new_from_string (dest_ip);
         address = g_inet_socket_address_new (inet_address, dest_port);
+        extended_message = append_header_fields (client, message);
 
         res = g_socket_send_to (socket,
                                 address,
-                                message,
-                                strlen (message),
+                                extended_message,
+                                strlen (extended_message),
                                 NULL,
                                 &error);
 
@@ -893,6 +1005,7 @@ _gssdp_client_send_message (GSSDPClient      *client,
                 g_error_free (error);
         }
 
+        g_free (extended_message);
         g_object_unref (address);
         g_object_unref (inet_address);
 }
diff --git a/libgssdp/gssdp-client.h b/libgssdp/gssdp-client.h
index 59a344d..ef51334 100644
--- a/libgssdp/gssdp-client.h
+++ b/libgssdp/gssdp-client.h
@@ -108,6 +108,18 @@ gssdp_client_get_network      (GSSDPClient  *client);
 gboolean
 gssdp_client_get_active       (GSSDPClient  *client);
 
+void
+gssdp_client_append_header    (GSSDPClient *client,
+                               const char  *name,
+                               const char  *value);
+
+void
+gssdp_client_remove_header    (GSSDPClient *client,
+                               const char  *name);
+
+void
+gssdp_client_clear_headers    (GSSDPClient *client);
+
 G_END_DECLS
 
 #endif /* __GSSDP_CLIENT_H__ */
diff --git a/libgssdp/gssdp-protocol.h b/libgssdp/gssdp-protocol.h
index 190bfd3..d679314 100644
--- a/libgssdp/gssdp-protocol.h
+++ b/libgssdp/gssdp-protocol.h
@@ -34,7 +34,7 @@ G_BEGIN_DECLS
         "Man: \"ssdp:discover\"\r\n"                \
         "ST: %s\r\n"                                \
         "MX: %d\r\n"                                \
-        "User-Agent: %s GSSDP/" VERSION "\r\n\r\n"  \
+        "User-Agent: %s GSSDP/" VERSION "\r\n"  \
 
 #define SSDP_DISCOVERY_RESPONSE                     \
         "HTTP/1.1 200 OK\r\n"                       \
@@ -46,7 +46,7 @@ G_BEGIN_DECLS
         "Cache-Control: max-age=%d\r\n"             \
         "ST: %s\r\n"                                \
         "Date: %s\r\n"                              \
-        "Content-Length: 0\r\n\r\n"
+        "Content-Length: 0\r\n"
 
 #define SSDP_ALIVE_MESSAGE                          \
         "NOTIFY * HTTP/1.1\r\n"                     \
@@ -57,14 +57,14 @@ G_BEGIN_DECLS
         "Server: %s\r\n"                            \
         "NTS: ssdp:alive\r\n"                       \
         "NT: %s\r\n"                                \
-        "USN: %s\r\n\r\n"
+        "USN: %s\r\n"
 
 #define SSDP_BYEBYE_MESSAGE                         \
         "NOTIFY * HTTP/1.1\r\n"                     \
         "Host: " SSDP_ADDR ":" SSDP_PORT_STR "\r\n" \
         "NTS: ssdp:byebye\r\n"                     \
         "NT: %s\r\n"                                \
-        "USN: %s\r\n\r\n"
+        "USN: %s\r\n"
 
 #define SSDP_SEARCH_METHOD "M-SEARCH"
 #define GENA_NOTIFY_METHOD "NOTIFY"
diff --git a/tests/gtest/test-functional.c b/tests/gtest/test-functional.c
index 243caee..d1fd3ff 100644
--- a/tests/gtest/test-functional.c
+++ b/tests/gtest/test-functional.c
@@ -71,7 +71,7 @@ create_alive_message (const char *nt)
         else
                 usn = g_strconcat (UUID_1, "::", nt, NULL);
 
-        msg = g_strdup_printf (SSDP_ALIVE_MESSAGE,
+        msg = g_strdup_printf (SSDP_ALIVE_MESSAGE "\r\n",
                                1800,
                                "http://127.0.0.1:1234";,
                                "",
@@ -93,7 +93,7 @@ create_byebye_message (const char *nt)
         else
                 usn = g_strconcat (UUID_1, "::", nt, NULL);
 
-        msg = g_strdup_printf (SSDP_BYEBYE_MESSAGE, nt, usn);
+        msg = g_strdup_printf (SSDP_BYEBYE_MESSAGE "\r\n", nt, usn);
         g_free (usn);
 
         return msg;
diff --git a/tests/gtest/test-regression.c b/tests/gtest/test-regression.c
index aabba51..01a984a 100644
--- a/tests/gtest/test-regression.c
+++ b/tests/gtest/test-regression.c
@@ -71,7 +71,7 @@ create_alive_message (const char *nt, int max_life)
         else
                 usn = g_strconcat (UUID_1, "::", nt, NULL);
 
-        msg = g_strdup_printf (SSDP_ALIVE_MESSAGE,
+        msg = g_strdup_printf (SSDP_ALIVE_MESSAGE "\r\n",
                                max_life,
                                "http://127.0.0.1:1234";,
                                "",
@@ -268,7 +268,7 @@ create_alive_message_bgo724030 (const char *location)
 {
         char *msg;
 
-        msg = g_strdup_printf (SSDP_ALIVE_MESSAGE,
+        msg = g_strdup_printf (SSDP_ALIVE_MESSAGE "\r\n",
                                5,
                                location,
                                "",


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