From 469aced5810b094f05d628d1d447b6430ae0d483 Mon Sep 17 00:00:00 2001 From: "Edgar E. Iglesias" Date: Fri, 13 Mar 2009 18:28:59 +0100 Subject: udpsrc: Add network interface selection Add network interface selection when joining multicast groups. Useful when using the udpsrc on multihomed hosts. Fixes #575234. API: GstUDPSrc::multicast-iface --- gst/udp/gstmultiudpsink.c | 4 ++-- gst/udp/gstudpnetutils.c | 18 +++++++++++++++++- gst/udp/gstudpnetutils.h | 4 +++- gst/udp/gstudpsrc.c | 21 ++++++++++++++++++++- gst/udp/gstudpsrc.h | 1 + 5 files changed, 43 insertions(+), 5 deletions(-) (limited to 'gst/udp') diff --git a/gst/udp/gstmultiudpsink.c b/gst/udp/gstmultiudpsink.c index a4821ffe..9cfea957 100644 --- a/gst/udp/gstmultiudpsink.c +++ b/gst/udp/gstmultiudpsink.c @@ -635,7 +635,7 @@ gst_multiudpsink_init_send (GstMultiUDPSink * sink) for (clients = sink->clients; clients; clients = g_list_next (clients)) { client = (GstUDPClient *) clients->data; if (sink->auto_multicast && gst_udp_is_multicast (&client->theiraddr)) - gst_udp_join_group (*(client->sock), &client->theiraddr); + gst_udp_join_group (*(client->sock), &client->theiraddr, NULL); } return TRUE; @@ -687,7 +687,7 @@ gst_multiudpsink_add_internal (GstMultiUDPSink * sink, const gchar * host, GST_DEBUG_OBJECT (sink, "multicast address detected"); if (sink->auto_multicast) { GST_DEBUG_OBJECT (sink, "joining multicast group"); - gst_udp_join_group (*(client->sock), &client->theiraddr); + gst_udp_join_group (*(client->sock), &client->theiraddr, NULL); } } else { GST_DEBUG_OBJECT (sink, "normal address detected"); diff --git a/gst/udp/gstudpnetutils.c b/gst/udp/gstudpnetutils.c index 5fa7593a..e1f8297a 100644 --- a/gst/udp/gstudpnetutils.c +++ b/gst/udp/gstudpnetutils.c @@ -163,19 +163,31 @@ gst_udp_set_loop_ttl (int sockfd, gboolean loop, int ttl) return ret; } +/* FIXME: Add interface selection for windows hosts. */ int -gst_udp_join_group (int sockfd, struct sockaddr_storage *addr) +gst_udp_join_group (int sockfd, struct sockaddr_storage *addr, gchar * iface) { int ret = -1; switch (addr->ss_family) { case AF_INET: { +#ifdef G_OS_WIN32 struct ip_mreq mreq4; +#else + struct ip_mreqn mreq4; +#endif mreq4.imr_multiaddr.s_addr = ((struct sockaddr_in *) addr)->sin_addr.s_addr; +#ifdef G_OS_WIN32 mreq4.imr_interface.s_addr = INADDR_ANY; +#else + if (iface) + mreq4.imr_ifindex = if_nametoindex (iface); + else + mreq4.imr_ifindex = 0; /* Pick any. */ +#endif if ((ret = setsockopt (sockfd, IPPROTO_IP, IP_ADD_MEMBERSHIP, @@ -192,6 +204,10 @@ gst_udp_join_group (int sockfd, struct sockaddr_storage *addr) &(((struct sockaddr_in6 *) addr)->sin6_addr), sizeof (struct in6_addr)); mreq6.ipv6mr_interface = 0; +#if !defined(G_OS_WIN32) + if (iface) + mreq6.ipv6mr_interface = if_nametoindex (iface); +#endif if ((ret = setsockopt (sockfd, IPPROTO_IPV6, IPV6_JOIN_GROUP, diff --git a/gst/udp/gstudpnetutils.h b/gst/udp/gstudpnetutils.h index 3e5b297a..04d847cd 100644 --- a/gst/udp/gstudpnetutils.h +++ b/gst/udp/gstudpnetutils.h @@ -40,6 +40,7 @@ #else #include #include +#include #include #include #include @@ -81,7 +82,8 @@ int gst_udp_is_multicast (struct sockaddr_storage *addr); int gst_udp_set_loop_ttl (int sockfd, gboolean loop, int ttl); -int gst_udp_join_group (int sockfd, struct sockaddr_storage *addr); +int gst_udp_join_group (int sockfd, struct sockaddr_storage *addr, + gchar *iface); int gst_udp_leave_group (int sockfd, struct sockaddr_storage *addr); #endif /* __GST_UDP_NET_UTILS_H__*/ diff --git a/gst/udp/gstudpsrc.c b/gst/udp/gstudpsrc.c index 8d92241e..087e3384 100644 --- a/gst/udp/gstudpsrc.c +++ b/gst/udp/gstudpsrc.c @@ -142,6 +142,7 @@ GST_ELEMENT_DETAILS ("UDP packet receiver", #define UDP_DEFAULT_PORT 4951 #define UDP_DEFAULT_MULTICAST_GROUP "0.0.0.0" +#define UDP_DEFAULT_MULTICAST_IFACE NULL #define UDP_DEFAULT_URI "udp://"UDP_DEFAULT_MULTICAST_GROUP":"G_STRINGIFY(UDP_DEFAULT_PORT) #define UDP_DEFAULT_CAPS NULL #define UDP_DEFAULT_SOCKFD -1 @@ -158,6 +159,7 @@ enum PROP_PORT, PROP_MULTICAST_GROUP, + PROP_MULTICAST_IFACE, PROP_URI, PROP_CAPS, PROP_SOCKFD, @@ -253,6 +255,10 @@ gst_udpsrc_class_init (GstUDPSrcClass * klass) g_param_spec_string ("multicast_group", "Multicast Group", "The Address of multicast group to join", UDP_DEFAULT_MULTICAST_GROUP, G_PARAM_READWRITE)); + g_object_class_install_property (gobject_class, PROP_MULTICAST_IFACE, + g_param_spec_string ("multicast_iface", "Multicast Interface", + "The network interface on which to join the multicast group", + UDP_DEFAULT_MULTICAST_IFACE, G_PARAM_READWRITE)); g_object_class_install_property (gobject_class, PROP_URI, g_param_spec_string ("uri", "URI", "URI in the form of udp://multicast_group:port", UDP_DEFAULT_URI, @@ -306,6 +312,7 @@ gst_udpsrc_init (GstUDPSrc * udpsrc, GstUDPSrcClass * g_class) udpsrc->port = UDP_DEFAULT_PORT; udpsrc->sockfd = UDP_DEFAULT_SOCKFD; udpsrc->multi_group = g_strdup (UDP_DEFAULT_MULTICAST_GROUP); + udpsrc->multi_iface = g_strdup (UDP_DEFAULT_MULTICAST_IFACE); udpsrc->uri = g_strdup (UDP_DEFAULT_URI); udpsrc->buffer_size = UDP_DEFAULT_BUFFER_SIZE; udpsrc->timeout = UDP_DEFAULT_TIMEOUT; @@ -334,6 +341,7 @@ gst_udpsrc_finalize (GObject * object) if (udpsrc->caps) gst_caps_unref (udpsrc->caps); g_free (udpsrc->multi_group); + g_free (udpsrc->multi_iface); g_free (udpsrc->uri); if (udpsrc->sockfd >= 0 && udpsrc->closefd) @@ -667,6 +675,14 @@ gst_udpsrc_set_property (GObject * object, guint prop_id, const GValue * value, udpsrc->multi_group = g_value_dup_string (value); gst_udpsrc_update_uri (udpsrc); break; + case PROP_MULTICAST_IFACE: + g_free (udpsrc->multi_iface); + + if (g_value_get_string (value) == NULL) + udpsrc->multi_iface = g_strdup (UDP_DEFAULT_MULTICAST_IFACE); + else + udpsrc->multi_iface = g_value_dup_string (value); + break; case PROP_URI: gst_udpsrc_set_uri (udpsrc, g_value_get_string (value)); break; @@ -731,6 +747,9 @@ gst_udpsrc_get_property (GObject * object, guint prop_id, GValue * value, case PROP_MULTICAST_GROUP: g_value_set_string (value, udpsrc->multi_group); break; + case PROP_MULTICAST_IFACE: + g_value_set_string (value, udpsrc->multi_iface); + break; case PROP_URI: g_value_set_string (value, udpsrc->uri); break; @@ -871,7 +890,7 @@ gst_udpsrc_start (GstBaseSrc * bsrc) if (src->auto_multicast && gst_udp_is_multicast (&src->myaddr)) { GST_DEBUG_OBJECT (src, "joining multicast group %s", src->multi_group); - ret = gst_udp_join_group (src->sock.fd, &src->myaddr); + ret = gst_udp_join_group (src->sock.fd, &src->myaddr, src->multi_iface); if (ret < 0) goto membership; } diff --git a/gst/udp/gstudpsrc.h b/gst/udp/gstudpsrc.h index cdf7b35e..aec167ed 100644 --- a/gst/udp/gstudpsrc.h +++ b/gst/udp/gstudpsrc.h @@ -56,6 +56,7 @@ struct _GstUDPSrc { gchar *uri; int port; gchar *multi_group; + gchar *multi_iface; gint ttl; GstCaps *caps; gint buffer_size; -- cgit