summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRiko Yamada <rik0yamada@yahoo.co.jp>2012-08-19 14:56:02 +0900
committerJens Georg <mail@jensge.org>2014-03-15 10:01:23 +0100
commit3030bf4cb97db33fcdfe7e69706fdb0f19b0f446 (patch)
treeecd53bc8a5de8de0e03688ffaa2e7357e1a9b0d1
parent3a257bafe5f5eb4b488ee30213d47221b81c60fa (diff)
downloadgssdp-3030bf4cb97db33fcdfe7e69706fdb0f19b0f446.tar.gz
Port to glib multicast socket functions
https://bugzilla.gnome.org/show_bug.cgi?id=678660 Signed-off-by: Jens Georg <mail@jensge.org>
-rw-r--r--libgssdp/gssdp-client.c3
-rw-r--r--libgssdp/gssdp-socket-functions.c138
-rw-r--r--libgssdp/gssdp-socket-functions.h17
-rw-r--r--libgssdp/gssdp-socket-source.c69
-rw-r--r--libgssdp/gssdp-socket-source.h1
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*