diff options
author | Bruno Santos <brunof@ua.pt> | 2008-05-21 09:56:02 +0000 |
---|---|---|
committer | Wim Taymans <wim.taymans@gmail.com> | 2008-05-21 09:56:02 +0000 |
commit | 570718c2feb3093e2c3a682b48734f4cac20a164 (patch) | |
tree | d91a2aac4f2967d3fe9246c4cf0b95e45d06ad00 /gst/udp/gstudpnetutils.c | |
parent | 94fb1d987043113b847131f86b3b096d7dbea8a1 (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.c | 190 |
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; +} |