summaryrefslogtreecommitdiffstats
path: root/gst/udp
diff options
context:
space:
mode:
authorEdgar E. Iglesias <edgar.iglesias@gmail.com>2009-03-13 18:28:59 +0100
committerWim Taymans <wim.taymans@collabora.co.uk>2009-03-13 18:28:59 +0100
commit469aced5810b094f05d628d1d447b6430ae0d483 (patch)
tree9274017c566c5a71a29451bf15cfb2b451be1ad4 /gst/udp
parenta32581abeea9264bba014f5e03063ee60f9c4bdb (diff)
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
Diffstat (limited to 'gst/udp')
-rw-r--r--gst/udp/gstmultiudpsink.c4
-rw-r--r--gst/udp/gstudpnetutils.c18
-rw-r--r--gst/udp/gstudpnetutils.h4
-rw-r--r--gst/udp/gstudpsrc.c21
-rw-r--r--gst/udp/gstudpsrc.h1
5 files changed, 43 insertions, 5 deletions
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 <sys/time.h>
#include <netinet/in.h>
+#include <net/if.h>
#include <netdb.h>
#include <sys/socket.h>
#include <sys/wait.h>
@@ -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;