1 /* GStreamer UDP network utility functions
2 * Copyright (C) 2006 Tim-Philipp Müller <tim centricular net>
3 * Copyright (C) 2006 Joni Valtanen <joni.valtanen@movial.fi>
5 * This library is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU Library General Public
7 * License as published by the Free Software Foundation; either
8 * version 2 of the License, or (at your option) any later version.
10 * This library is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * Library General Public License for more details.
15 * You should have received a copy of the GNU Library General Public
16 * License along with this library; if not, write to the
17 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
18 * Boston, MA 02111-1307, USA.
29 /* EAI_ADDRFAMILY was obsoleted in BSD at some point */
30 #ifndef EAI_ADDRFAMILY
31 #define EAI_ADDRFAMILY 1
34 #include "gstudpnetutils.h"
39 gst_udp_net_utils_win32_wsa_startup (GstObject * obj)
44 error = WSAStartup (0x0202, &w);
47 GST_WARNING_OBJECT (obj, "WSAStartup error: %d", error);
51 if (w.wVersion != 0x0202) {
53 GST_WARNING_OBJECT (obj, "Winsock version wrong : 0x%x", w.wVersion);
63 gst_udp_get_sockaddr_length (struct sockaddr_storage *addr)
65 /* MacOS is picky about passing precisely the correct length,
66 * so we calculate it here for the given socket type.
68 switch (addr->ss_family) {
70 return sizeof (struct sockaddr_in);
72 return sizeof (struct sockaddr_in6);
74 /* don't know, Screw MacOS and use the full length */
75 return sizeof (*addr);
80 gst_udp_get_addr (const char *hostname, int port, struct sockaddr_storage *addr)
82 struct addrinfo hints, *res, *nres;
83 char service[NI_MAXSERV];
86 memset (&hints, 0, sizeof (hints));
87 hints.ai_family = AF_UNSPEC;
88 hints.ai_socktype = SOCK_DGRAM;
89 g_snprintf (service, sizeof (service) - 1, "%d", port);
90 service[sizeof (service) - 1] = '\0';
92 if ((ret = getaddrinfo (hostname, (port == -1) ? NULL : service, &hints,
99 if (nres->ai_family == AF_INET || nres->ai_family == AF_INET6)
101 nres = nres->ai_next;
105 memcpy (addr, nres->ai_addr, nres->ai_addrlen);
107 ret = EAI_ADDRFAMILY;
116 gst_udp_set_loop_ttl (int sockfd, gboolean loop, int ttl)
119 struct sockaddr_storage addr;
121 int l = (loop == FALSE) ? 0 : 1;
123 socklen = sizeof (addr);
124 if ((ret = getsockname (sockfd, (struct sockaddr *) &addr, &socklen)) < 0) {
128 switch (addr.ss_family) {
132 setsockopt (sockfd, IPPROTO_IP, IP_MULTICAST_LOOP, &l,
137 setsockopt (sockfd, IPPROTO_IP, IP_MULTICAST_TTL, &ttl,
145 setsockopt (sockfd, IPPROTO_IPV6, IPV6_MULTICAST_LOOP, &l,
150 setsockopt (sockfd, IPPROTO_IPV6, IPV6_MULTICAST_HOPS, &ttl,
158 WSASetLastError (WSAEAFNOSUPPORT);
160 errno = EAFNOSUPPORT;
166 /* FIXME: Add interface selection for windows hosts. */
168 gst_udp_join_group (int sockfd, struct sockaddr_storage *addr, gchar * iface)
172 switch (addr->ss_family) {
176 struct ip_mreq mreq4;
178 struct ip_mreqn mreq4;
181 mreq4.imr_multiaddr.s_addr =
182 ((struct sockaddr_in *) addr)->sin_addr.s_addr;
184 mreq4.imr_interface.s_addr = INADDR_ANY;
187 mreq4.imr_ifindex = if_nametoindex (iface);
189 mreq4.imr_ifindex = 0; /* Pick any. */
193 setsockopt (sockfd, IPPROTO_IP, IP_ADD_MEMBERSHIP,
194 (const void *) &mreq4, sizeof (mreq4))) < 0)
201 struct ipv6_mreq mreq6;
203 memcpy (&mreq6.ipv6mr_multiaddr,
204 &(((struct sockaddr_in6 *) addr)->sin6_addr),
205 sizeof (struct in6_addr));
206 mreq6.ipv6mr_interface = 0;
207 #if !defined(G_OS_WIN32)
209 mreq6.ipv6mr_interface = if_nametoindex (iface);
213 setsockopt (sockfd, IPPROTO_IPV6, IPV6_JOIN_GROUP,
214 (const void *) &mreq6, sizeof (mreq6))) < 0)
221 WSASetLastError (WSAEAFNOSUPPORT);
223 errno = EAFNOSUPPORT;
230 gst_udp_leave_group (int sockfd, struct sockaddr_storage *addr)
234 switch (addr->ss_family) {
237 struct ip_mreq mreq4;
239 mreq4.imr_multiaddr.s_addr =
240 ((struct sockaddr_in *) addr)->sin_addr.s_addr;
241 mreq4.imr_interface.s_addr = INADDR_ANY;
244 setsockopt (sockfd, IPPROTO_IP, IP_DROP_MEMBERSHIP,
245 (const void *) &mreq4, sizeof (mreq4))) < 0)
252 struct ipv6_mreq mreq6;
254 memcpy (&mreq6.ipv6mr_multiaddr,
255 &(((struct sockaddr_in6 *) addr)->sin6_addr),
256 sizeof (struct in6_addr));
257 mreq6.ipv6mr_interface = 0;
260 setsockopt (sockfd, IPPROTO_IPV6, IPV6_LEAVE_GROUP,
261 (const void *) &mreq6, sizeof (mreq6))) < 0)
268 WSASetLastError (WSAEAFNOSUPPORT);
270 errno = EAFNOSUPPORT;
278 gst_udp_is_multicast (struct sockaddr_storage *addr)
282 switch (addr->ss_family) {
285 struct sockaddr_in *addr4 = (struct sockaddr_in *) addr;
287 ret = IN_MULTICAST (g_ntohl (addr4->sin_addr.s_addr));
293 struct sockaddr_in6 *addr6 = (struct sockaddr_in6 *) addr;
295 ret = IN6_IS_ADDR_MULTICAST (&addr6->sin6_addr);
301 WSASetLastError (WSAEAFNOSUPPORT);
303 errno = EAFNOSUPPORT;