[gssdp] Port to glib multicast socket functions



commit 3030bf4cb97db33fcdfe7e69706fdb0f19b0f446
Author: Riko Yamada <rik0yamada yahoo co jp>
Date:   Sun Aug 19 14:56:02 2012 +0900

    Port to glib multicast socket functions
    
    https://bugzilla.gnome.org/show_bug.cgi?id=678660
    
    Signed-off-by: Jens Georg <mail jensge org>

 libgssdp/gssdp-client.c           |    3 +
 libgssdp/gssdp-socket-functions.c |  138 -------------------------------------
 libgssdp/gssdp-socket-functions.h |   17 -----
 libgssdp/gssdp-socket-source.c    |   69 ++++++++++--------
 libgssdp/gssdp-socket-source.h    |    1 +
 5 files changed, 42 insertions(+), 186 deletions(-)
---
diff --git a/libgssdp/gssdp-client.c b/libgssdp/gssdp-client.c
index c4d745b..f24e57a 100644
--- a/libgssdp/gssdp-client.c
+++ b/libgssdp/gssdp-client.c
@@ -220,6 +220,7 @@ gssdp_client_initable_init (GInitable                   *initable,
                 gssdp_socket_source_new (GSSDP_SOCKET_SOURCE_TYPE_REQUEST,
                                          gssdp_client_get_host_ip (client),
                                          client->priv->socket_ttl,
+                                         client->priv->device.iface_name,
                                          &internal_error);
         if (client->priv->request_socket != NULL) {
                 gssdp_socket_source_set_callback
@@ -234,6 +235,7 @@ gssdp_client_initable_init (GInitable                   *initable,
                 gssdp_socket_source_new (GSSDP_SOCKET_SOURCE_TYPE_MULTICAST,
                                          gssdp_client_get_host_ip (client),
                                          client->priv->socket_ttl,
+                                         client->priv->device.iface_name,
                                          &internal_error);
         if (client->priv->multicast_socket != NULL) {
                 gssdp_socket_source_set_callback
@@ -254,6 +256,7 @@ gssdp_client_initable_init (GInitable                   *initable,
                                          "host-ip", gssdp_client_get_host_ip (client),
                                          "ttl", client->priv->socket_ttl,
                                          "port", client->priv->msearch_port,
+                                         "device-name", client->priv->device.iface_name,
                                          NULL));
 
         if (client->priv->search_socket != NULL) {
diff --git a/libgssdp/gssdp-socket-functions.c b/libgssdp/gssdp-socket-functions.c
index 5919e2b..e1ffaaa 100644
--- a/libgssdp/gssdp-socket-functions.c
+++ b/libgssdp/gssdp-socket-functions.c
@@ -89,52 +89,6 @@ gssdp_socket_option_set (GSocket    *socket,
 }
 
 gboolean
-gssdp_socket_enable_loop (GSocket *socket,
-                          gboolean _enable,
-                          GError **error) {
-#if defined(__OpenBSD__)
-        guint8 enable = (guint8) _enable;
-#else
-        gboolean enable = _enable;
-#endif
-        return gssdp_socket_option_set (socket,
-                                        IPPROTO_IP,
-                                        IP_MULTICAST_LOOP,
-                                        (char *) &enable,
-                                        sizeof (enable),
-                                        error);
-}
-
-gboolean
-gssdp_socket_set_ttl (GSocket *socket,
-                      int      _ttl,
-                      GError **error) {
-#if defined(__OpenBSD__)
-        guint8 ttl = (guint8) _ttl;
-#else
-        int ttl = _ttl;
-#endif
-        return gssdp_socket_option_set (socket,
-                                        IPPROTO_IP,
-                                        IP_MULTICAST_TTL,
-                                        (char *) &ttl,
-                                        sizeof (ttl),
-                                        error);
-}
-
-gboolean
-gssdp_socket_enable_broadcast (GSocket *socket,
-                               gboolean enable,
-                               GError **error) {
-        return gssdp_socket_option_set (socket,
-                                        SOL_SOCKET,
-                                        SO_BROADCAST,
-                                        (char *) &enable,
-                                        sizeof (enable),
-                                        error);
-}
-
-gboolean
 gssdp_socket_mcast_interface_set (GSocket      *socket,
                                   GInetAddress *iface_address,
                                   GError      **error) {
@@ -178,95 +132,3 @@ gssdp_socket_reuse_address (GSocket *socket,
 #endif
         return TRUE;
 }
-
-
-/*
- * Iface may be NULL if no special interface is wanted
- */
-gboolean
-gssdp_socket_mcast_group_join (GSocket       *socket,
-                               GInetAddress  *group,
-                               GInetAddress  *iface,
-                               GError       **error) {
-        struct ip_mreq mreq;
-        GError *inner_error = NULL;
-        gboolean result;
-#ifdef G_OS_WIN32
-        GSocketAddress *local_address;
-#endif
-        if (group == NULL || ! G_IS_INET_ADDRESS (group)) {
-                g_set_error_literal (error,
-                                     GSSDP_ERROR,
-                                     GSSDP_ERROR_NO_IP_ADDRESS,
-                                     "Address is not a valid address");
-
-                return FALSE;
-        }
-
-        if (!g_inet_address_get_is_multicast (group)) {
-                char *address;
-
-                address = g_inet_address_to_string (group);
-                g_set_error (error,
-                             GSSDP_ERROR,
-                             GSSDP_ERROR_FAILED,
-                             "Address '%s' is not a multicast address",
-                             address);
-                g_free (address);
-
-                return FALSE;
-        }
-
-        if (g_inet_address_get_family (group) != G_SOCKET_FAMILY_IPV4) {
-                g_set_error_literal (error,
-                                     GSSDP_ERROR,
-                                     GSSDP_ERROR_FAILED,
-                                     "IPv6 not supported");
-
-                return FALSE;
-        }
-#ifdef G_OS_WIN32
-        /* On Window, it is only possible to join multicast groups on a bound
-         * socket
-         * Note: This test is valid on Windows only. On linux, local_addres
-         * will be the ANY address (0.0.0.0 for IPv4)
-         */
-        local_address = g_socket_get_local_address (socket, &inner_error);
-        if (local_address == NULL) {
-                g_set_error_literal (error,
-                                     GSSDP_ERROR,
-                                     GSSDP_ERROR_FAILED,
-                                     "Cannot join multicast group;"
-                                     "socket is not bound");
-
-                return FALSE;
-        }
-        g_object_unref (local_address);
-#endif
-
-        memset (&mreq, 0, sizeof (struct ip_mreq));
-        memcpy (&(mreq.imr_multiaddr),
-                g_inet_address_to_bytes (group),
-                g_inet_address_get_native_size (group));
-
-        /* if omitted, join will fail if there isn't an explicit multicast
-         * route or a default route
-         */
-        if (iface != NULL)
-                memcpy (&(mreq.imr_interface),
-                        g_inet_address_to_bytes (iface),
-                        g_inet_address_get_native_size (iface));
-
-        result = gssdp_socket_option_set (socket,
-                                          IPPROTO_IP,
-                                          IP_ADD_MEMBERSHIP,
-                                          (char *) &mreq,
-                                          sizeof (mreq),
-                                          &inner_error);
-        if (!result)
-                g_propagate_error (error, inner_error);
-
-        return result;
-}
-
-
diff --git a/libgssdp/gssdp-socket-functions.h b/libgssdp/gssdp-socket-functions.h
index 47b1095..14f0650 100644
--- a/libgssdp/gssdp-socket-functions.h
+++ b/libgssdp/gssdp-socket-functions.h
@@ -25,27 +25,10 @@
 #include <gio/gio.h>
 
 G_GNUC_INTERNAL gboolean
-gssdp_socket_enable_loop         (GSocket       *socket,
-                                  gboolean       enable,
-                                  GError       **error);
-G_GNUC_INTERNAL gboolean
-gssdp_socket_set_ttl             (GSocket       *socket,
-                                  int            ttl,
-                                  GError       **error);
-G_GNUC_INTERNAL gboolean
-gssdp_socket_enable_broadcast    (GSocket       *socket,
-                                  gboolean       enable,
-                                  GError       **error);
-G_GNUC_INTERNAL gboolean
 gssdp_socket_mcast_interface_set (GSocket       *socket,
                                   GInetAddress  *iface_address,
                                   GError       **error);
 G_GNUC_INTERNAL gboolean
-gssdp_socket_mcast_group_join    (GSocket       *socket,
-                                  GInetAddress  *group,
-                                  GInetAddress  *iface,
-                                  GError       **error);
-G_GNUC_INTERNAL gboolean
 gssdp_socket_reuse_address       (GSocket *socket,
                                   gboolean enable,
                                   GError **error);
diff --git a/libgssdp/gssdp-socket-source.c b/libgssdp/gssdp-socket-source.c
index c7e9585..a51b1a7 100644
--- a/libgssdp/gssdp-socket-source.c
+++ b/libgssdp/gssdp-socket-source.c
@@ -27,11 +27,19 @@
 #include <config.h>
 #include <glib.h>
 
+#ifndef G_OS_WIN32
+#include <arpa/inet.h>
+#include <net/if.h>
+#include <ifaddrs.h>
+#endif
 #include "gssdp-socket-functions.h"
 #include "gssdp-socket-source.h"
 #include "gssdp-protocol.h"
 #include "gssdp-error.h"
 
+#include <string.h>
+#include <stdio.h>
+
 static void
 gssdp_socket_source_initable_init (gpointer g_iface,
                                    gpointer iface_data);
@@ -49,6 +57,7 @@ struct _GSSDPSocketSourcePrivate {
         GSSDPSocketSourceType type;
 
         char                 *host_ip;
+        char                 *device_name;
         guint                 ttl;
         guint                 port;
 };
@@ -58,7 +67,8 @@ enum {
     PROP_TYPE,
     PROP_HOST_IP,
     PROP_TTL,
-    PROP_PORT
+    PROP_PORT,
+    PROP_IFA_NAME
 };
 
 static void
@@ -113,6 +123,9 @@ gssdp_socket_source_set_property (GObject          *object,
         case PROP_HOST_IP:
                 self->priv->host_ip = g_value_dup_string (value);
                 break;
+        case PROP_IFA_NAME:
+                self->priv->device_name = g_value_dup_string (value);
+                break;
         case PROP_TTL:
                 self->priv->ttl = g_value_get_uint (value);
                 break;
@@ -134,6 +147,7 @@ GSSDPSocketSource *
 gssdp_socket_source_new (GSSDPSocketSourceType type,
                          const char           *host_ip,
                          guint                 ttl,
+                         const char           *device_name,
                          GError              **error)
 {
         return g_initable_new (GSSDP_TYPE_SOCKET_SOURCE,
@@ -145,6 +159,8 @@ gssdp_socket_source_new (GSSDPSocketSourceType type,
                                host_ip,
                                "ttl",
                                ttl,
+                               "device-name",
+                               device_name,
                                NULL);
 }
 
@@ -202,43 +218,20 @@ gssdp_socket_source_do_init (GInitable                   *initable,
         }
 
         /* Enable broadcasting */
-        if (!gssdp_socket_enable_broadcast (self->priv->socket,
-                                            TRUE,
-                                            &inner_error)) {
-                g_propagate_prefixed_error (error,
-                                            inner_error,
-                                            "Failed to enable broadcast");
-                goto error;
-        }
+        g_socket_set_broadcast (self->priv->socket, TRUE);
 
         /* TTL */
         if (!self->priv->ttl)
                 /* UDA/1.0 says 4, UDA/1.1 says 2 */
                 self->priv->ttl = 4;
 
-        if (!gssdp_socket_set_ttl (self->priv->socket,
-                                   self->priv->ttl,
-                                   &inner_error)) {
-                g_propagate_prefixed_error (error,
-                                            inner_error,
-                                            "Failed to set TTL to %u", self->priv->ttl);
+        g_socket_set_multicast_ttl (self->priv->socket, 4);
 
-                goto error;
-        }
 
         /* Set up additional things according to the type of socket desired */
         if (self->priv->type == GSSDP_SOCKET_SOURCE_TYPE_MULTICAST) {
                 /* Enable multicast loopback */
-                if (!gssdp_socket_enable_loop (self->priv->socket,
-                                               TRUE,
-                                               &inner_error)) {
-                        g_propagate_prefixed_error (
-                                        error,
-                                        inner_error,
-                                        "Failed to enable loop-back");
-
-                        goto error;
-                }
+                g_socket_set_multicast_loopback (self->priv->socket, TRUE);
 
                 if (!gssdp_socket_mcast_interface_set (self->priv->socket,
                                                        iface_address,
@@ -299,11 +292,13 @@ gssdp_socket_source_do_init (GInitable                   *initable,
         }
 
         if (self->priv->type == GSSDP_SOCKET_SOURCE_TYPE_MULTICAST) {
-
-                 /* Subscribe to multicast channel */
-                if (!gssdp_socket_mcast_group_join (self->priv->socket,
+                /* The 4th argument 'iface_name' can't be NULL even though Glib API doc says you
+                 * can. 'NULL' will fail the test.
+                 */
+                if (!g_socket_join_multicast_group (self->priv->socket,
                                                     group,
-                                                    iface_address,
+                                                    FALSE,
+                                                    self->priv->device_name,  /*   e.g. 'lo' */
                                                     &inner_error)) {
                         char *address = g_inet_address_to_string (group);
                         g_propagate_prefixed_error (error,
@@ -446,6 +441,18 @@ gssdp_socket_source_class_init (GSSDPSocketSourceClass *klass)
 
         g_object_class_install_property
                 (object_class,
+                 PROP_IFA_NAME,
+                 g_param_spec_string
+                        ("device-name",
+                         "Interface name",
+                         "Name of associated network interface",
+                         NULL,
+                         G_PARAM_WRITABLE | G_PARAM_CONSTRUCT_ONLY |
+                         G_PARAM_STATIC_NAME | G_PARAM_STATIC_NICK |
+                         G_PARAM_STATIC_BLURB));
+
+        g_object_class_install_property
+                (object_class,
                  PROP_TTL,
                  g_param_spec_uint
                         ("ttl",
diff --git a/libgssdp/gssdp-socket-source.h b/libgssdp/gssdp-socket-source.h
index ed9ef42..d2e9611 100644
--- a/libgssdp/gssdp-socket-source.h
+++ b/libgssdp/gssdp-socket-source.h
@@ -76,6 +76,7 @@ G_GNUC_INTERNAL GSSDPSocketSource *
 gssdp_socket_source_new        (GSSDPSocketSourceType  type,
                                 const char            *host_ip,
                                 guint                  ttl,
+                                const char            *device_name,
                                 GError               **error);
 
 G_GNUC_INTERNAL GSocket*


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