summaryrefslogtreecommitdiffstats
path: root/gst/udp/gstudpnetutils.c
diff options
context:
space:
mode:
authorBruno Santos <brunof@ua.pt>2008-05-21 09:56:02 +0000
committerWim Taymans <wim.taymans@gmail.com>2008-05-21 09:56:02 +0000
commit570718c2feb3093e2c3a682b48734f4cac20a164 (patch)
treed91a2aac4f2967d3fe9246c4cf0b95e45d06ad00 /gst/udp/gstudpnetutils.c
parent94fb1d987043113b847131f86b3b096d7dbea8a1 (diff)
gst/udp/gstudpnetutils.*: Provide a bunch of helper methods to deal with IPv4 and IPv6 transparently.
Original commit message from CVS: Patch by: Bruno Santos <brunof at ua dot pt> * gst/udp/gstudpnetutils.c: (gst_udp_get_addr), (gst_udp_join_group), (gst_udp_leave_group), (gst_udp_is_multicast): * gst/udp/gstudpnetutils.h: Provide a bunch of helper methods to deal with IPv4 and IPv6 transparently. * gst/udp/gstmultiudpsink.c: (gst_multiudpsink_class_init), (gst_multiudpsink_init), (gst_multiudpsink_set_property), (gst_multiudpsink_get_property), (join_multicast), (gst_multiudpsink_init_send), (gst_multiudpsink_add_internal), (gst_multiudpsink_remove): * gst/udp/gstmultiudpsink.h: Add multicast TTL and loopback properties. Use the helper methods to implement ip4 and ip6. * gst/udp/gstudpsrc.c: (gst_udpsrc_create), (gst_udpsrc_start): * gst/udp/gstudpsrc.h: Use the helper methods to implement ip4 and ip6. Fixes #515962.
Diffstat (limited to 'gst/udp/gstudpnetutils.c')
-rw-r--r--gst/udp/gstudpnetutils.c190
1 files changed, 179 insertions, 11 deletions
diff --git a/gst/udp/gstudpnetutils.c b/gst/udp/gstudpnetutils.c
index 585916d8..b50336f5 100644
--- a/gst/udp/gstudpnetutils.c
+++ b/gst/udp/gstudpnetutils.c
@@ -22,21 +22,14 @@
#include "config.h"
#endif
+#include <errno.h>
+#include <stdio.h>
+#include <memory.h>
+
#include "gstudpnetutils.h"
#ifdef G_OS_WIN32
-int
-gst_udp_net_utils_win32_inet_aton (const char *c, struct in_addr *paddr)
-{
- paddr->s_addr = inet_addr (c);
-
- if (paddr->s_addr == INADDR_NONE)
- return 0;
-
- return 1;
-}
-
gboolean
gst_udp_net_utils_win32_wsa_startup (GstObject * obj)
{
@@ -60,3 +53,178 @@ gst_udp_net_utils_win32_wsa_startup (GstObject * obj)
}
#endif
+
+int
+gst_udp_get_addr (const char *hostname, int port, struct sockaddr_storage *addr)
+{
+ struct addrinfo hints, *res, *nres;
+ char service[NI_MAXSERV];
+ int ret;
+
+ memset (&hints, 0, sizeof (hints));
+ hints.ai_family = AF_UNSPEC;
+ hints.ai_socktype = SOCK_DGRAM;
+ snprintf (service, sizeof (service) - 1, "%d", port);
+ service[sizeof (service) - 1] = '\0';
+
+ if ((ret = getaddrinfo (hostname, (port == -1) ? NULL : service, &hints,
+ &res)) < 0) {
+ return ret;
+ }
+
+ nres = res;
+ while (nres) {
+ if (nres->ai_family == AF_INET || nres->ai_family == AF_INET6)
+ break;
+ nres = nres->ai_next;
+ }
+
+ if (nres) {
+ memcpy (addr, nres->ai_addr, nres->ai_addrlen);
+ } else {
+ errno = EAI_ADDRFAMILY;
+ ret = -1;
+ }
+ freeaddrinfo (res);
+
+ return ret;
+}
+
+int
+gst_udp_join_group (int sockfd, gboolean loop, int ttl,
+ struct sockaddr_storage *addr)
+{
+ int ret = -1;
+ int l = (loop == FALSE) ? 0 : 1;
+
+ switch (addr->ss_family) {
+ case AF_INET:
+ {
+ struct ip_mreq mreq4;
+
+ mreq4.imr_multiaddr.s_addr =
+ ((struct sockaddr_in *) addr)->sin_addr.s_addr;
+ mreq4.imr_interface.s_addr = INADDR_ANY;
+
+ if ((ret =
+ setsockopt (sockfd, IPPROTO_IP, IP_MULTICAST_LOOP, &l,
+ sizeof (l))) < 0)
+ return ret;
+
+ if ((ret =
+ setsockopt (sockfd, IPPROTO_IP, IP_MULTICAST_TTL, &ttl,
+ sizeof (ttl))) < 0)
+ return ret;
+
+ if ((ret =
+ setsockopt (sockfd, IPPROTO_IP, IP_ADD_MEMBERSHIP,
+ (const void *) &mreq4, sizeof (mreq4))) < 0)
+ return ret;
+ }
+ break;
+
+ case AF_INET6:
+ {
+ struct ipv6_mreq mreq6;
+
+ memcpy (&mreq6.ipv6mr_multiaddr,
+ &(((struct sockaddr_in6 *) addr)->sin6_addr),
+ sizeof (struct in6_addr));
+ mreq6.ipv6mr_interface = 0;
+
+ if ((ret =
+ setsockopt (sockfd, IPPROTO_IPV6, IPV6_MULTICAST_LOOP, &l,
+ sizeof (l))) < 0)
+ return ret;
+
+ if ((ret =
+ setsockopt (sockfd, IPPROTO_IPV6, IPV6_MULTICAST_HOPS, &ttl,
+ sizeof (ttl))) < 0)
+ return ret;
+
+ if ((ret =
+ setsockopt (sockfd, IPPROTO_IPV6, IPV6_ADD_MEMBERSHIP,
+ (const void *) &mreq6, sizeof (mreq6))) < 0)
+ return ret;
+ }
+ break;
+
+ default:
+ errno = EAFNOSUPPORT;
+ }
+
+ return ret;
+}
+
+int
+gst_udp_leave_group (int sockfd, struct sockaddr_storage *addr)
+{
+ int ret = -1;
+
+ switch (addr->ss_family) {
+ case AF_INET:
+ {
+ struct ip_mreq mreq4;
+
+ mreq4.imr_multiaddr.s_addr =
+ ((struct sockaddr_in *) addr)->sin_addr.s_addr;
+ mreq4.imr_interface.s_addr = INADDR_ANY;
+
+ if ((ret =
+ setsockopt (sockfd, IPPROTO_IP, IP_DROP_MEMBERSHIP,
+ (const void *) &mreq4, sizeof (mreq4))) < 0)
+ return ret;
+ }
+ break;
+
+ case AF_INET6:
+ {
+ struct ipv6_mreq mreq6;
+
+ memcpy (&mreq6.ipv6mr_multiaddr,
+ &(((struct sockaddr_in6 *) addr)->sin6_addr),
+ sizeof (struct in6_addr));
+ mreq6.ipv6mr_interface = 0;
+
+ if ((ret =
+ setsockopt (sockfd, IPPROTO_IPV6, IPV6_DROP_MEMBERSHIP,
+ (const void *) &mreq6, sizeof (mreq6))) < 0)
+ return ret;
+ }
+ break;
+
+ default:
+ errno = EAFNOSUPPORT;
+ }
+
+ return ret;
+}
+
+int
+gst_udp_is_multicast (struct sockaddr_storage *addr)
+{
+ int ret = -1;
+
+ switch (addr->ss_family) {
+ case AF_INET:
+ {
+ struct sockaddr_in *addr4 = (struct sockaddr_in *) addr;
+
+ ret = IN_MULTICAST (ntohl (addr4->sin_addr.s_addr));
+ }
+ break;
+
+ case AF_INET6:
+ {
+ struct sockaddr_in6 *addr6 = (struct sockaddr_in6 *) addr;
+
+ ret = IN6_IS_ADDR_MULTICAST (&addr6->sin6_addr);
+ }
+ break;
+
+ default:
+ errno = EAFNOSUPPORT;
+ }
+
+ return ret;
+}