gst/goom/: Fix build with MSVC: include glib.h to define inline appropriately, use...
[platform/upstream/gst-plugins-good.git] / gst / udp / gstudpnetutils.c
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>
4  *
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.
9  *
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.
14  *
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.
19  */
20
21 #ifdef HAVE_CONFIG_H
22 #include "config.h"
23 #endif
24
25 #include <errno.h>
26 #include <stdio.h>
27 #include <memory.h>
28
29 /* EAI_ADDRFAMILY was obsoleted in BSD at some point */
30 #ifndef EAI_ADDRFAMILY
31 #define EAI_ADDRFAMILY 1
32 #endif
33
34 #include "gstudpnetutils.h"
35
36 #ifdef G_OS_WIN32
37
38 gboolean
39 gst_udp_net_utils_win32_wsa_startup (GstObject * obj)
40 {
41   WSADATA w;
42   int error;
43
44   error = WSAStartup (0x0202, &w);
45
46   if (error) {
47     GST_WARNING_OBJECT (obj, "WSAStartup error: %d", error);
48     return FALSE;
49   }
50
51   if (w.wVersion != 0x0202) {
52     WSACleanup ();
53     GST_WARNING_OBJECT (obj, "Winsock version wrong : 0x%x", w.wVersion);
54     return FALSE;
55   }
56
57   return TRUE;
58 }
59
60 #endif
61
62 int
63 gst_udp_get_addr (const char *hostname, int port, struct sockaddr_storage *addr)
64 {
65   struct addrinfo hints, *res, *nres;
66   char service[NI_MAXSERV];
67   int ret;
68
69   memset (&hints, 0, sizeof (hints));
70   hints.ai_family = AF_UNSPEC;
71   hints.ai_socktype = SOCK_DGRAM;
72   g_snprintf (service, sizeof (service) - 1, "%d", port);
73   service[sizeof (service) - 1] = '\0';
74
75   if ((ret = getaddrinfo (hostname, (port == -1) ? NULL : service, &hints,
76               &res)) < 0) {
77     return ret;
78   }
79
80   nres = res;
81   while (nres) {
82     if (nres->ai_family == AF_INET || nres->ai_family == AF_INET6)
83       break;
84     nres = nres->ai_next;
85   }
86
87   if (nres) {
88     memcpy (addr, nres->ai_addr, nres->ai_addrlen);
89   } else {
90     errno = EAI_ADDRFAMILY;
91     ret = -1;
92   }
93   freeaddrinfo (res);
94
95   return ret;
96 }
97
98 int
99 gst_udp_set_loop_ttl (int sockfd, gboolean loop, int ttl)
100 {
101   int ret = -1;
102
103 #if 0
104   int l = (loop == FALSE) ? 0 : 1;
105
106   switch (addr->ss_family) {
107     case AF_INET:
108     {
109       if ((ret =
110               setsockopt (sockfd, IPPROTO_IP, IP_MULTICAST_LOOP, &l,
111                   sizeof (l))) < 0)
112         return ret;
113
114       if ((ret =
115               setsockopt (sockfd, IPPROTO_IP, IP_MULTICAST_TTL, &ttl,
116                   sizeof (ttl))) < 0)
117         return ret;
118       break;
119     }
120     case AF_INET6:
121     {
122       if ((ret =
123               setsockopt (sockfd, IPPROTO_IPV6, IPV6_MULTICAST_LOOP, &l,
124                   sizeof (l))) < 0)
125         return ret;
126
127       if ((ret =
128               setsockopt (sockfd, IPPROTO_IPV6, IPV6_MULTICAST_HOPS, &ttl,
129                   sizeof (ttl))) < 0)
130         return ret;
131
132       break;
133     }
134     default:
135       errno = EAFNOSUPPORT;
136   }
137 #endif
138   return ret;
139 }
140
141 int
142 gst_udp_join_group (int sockfd, struct sockaddr_storage *addr)
143 {
144   int ret = -1;
145
146   switch (addr->ss_family) {
147     case AF_INET:
148     {
149       struct ip_mreq mreq4;
150
151       mreq4.imr_multiaddr.s_addr =
152           ((struct sockaddr_in *) addr)->sin_addr.s_addr;
153       mreq4.imr_interface.s_addr = INADDR_ANY;
154
155       if ((ret =
156               setsockopt (sockfd, IPPROTO_IP, IP_ADD_MEMBERSHIP,
157                   (const void *) &mreq4, sizeof (mreq4))) < 0)
158         return ret;
159
160       break;
161     }
162     case AF_INET6:
163     {
164       struct ipv6_mreq mreq6;
165
166       memcpy (&mreq6.ipv6mr_multiaddr,
167           &(((struct sockaddr_in6 *) addr)->sin6_addr),
168           sizeof (struct in6_addr));
169       mreq6.ipv6mr_interface = 0;
170
171       if ((ret =
172               setsockopt (sockfd, IPPROTO_IPV6, IPV6_JOIN_GROUP,
173                   (const void *) &mreq6, sizeof (mreq6))) < 0)
174         return ret;
175
176       break;
177     }
178     default:
179 #ifdef G_OS_WIN32
180       WSASetLastError (WSAEAFNOSUPPORT);
181 #else
182       errno = EAFNOSUPPORT;
183 #endif
184   }
185   return ret;
186 }
187
188 int
189 gst_udp_leave_group (int sockfd, struct sockaddr_storage *addr)
190 {
191   int ret = -1;
192
193   switch (addr->ss_family) {
194     case AF_INET:
195     {
196       struct ip_mreq mreq4;
197
198       mreq4.imr_multiaddr.s_addr =
199           ((struct sockaddr_in *) addr)->sin_addr.s_addr;
200       mreq4.imr_interface.s_addr = INADDR_ANY;
201
202       if ((ret =
203               setsockopt (sockfd, IPPROTO_IP, IP_DROP_MEMBERSHIP,
204                   (const void *) &mreq4, sizeof (mreq4))) < 0)
205         return ret;
206     }
207       break;
208
209     case AF_INET6:
210     {
211       struct ipv6_mreq mreq6;
212
213       memcpy (&mreq6.ipv6mr_multiaddr,
214           &(((struct sockaddr_in6 *) addr)->sin6_addr),
215           sizeof (struct in6_addr));
216       mreq6.ipv6mr_interface = 0;
217
218       if ((ret =
219               setsockopt (sockfd, IPPROTO_IPV6, IPV6_LEAVE_GROUP,
220                   (const void *) &mreq6, sizeof (mreq6))) < 0)
221         return ret;
222     }
223       break;
224
225     default:
226 #ifdef G_OS_WIN32
227       WSASetLastError (WSAEAFNOSUPPORT);
228 #else
229       errno = EAFNOSUPPORT;
230 #endif
231   }
232
233   return ret;
234 }
235
236 int
237 gst_udp_is_multicast (struct sockaddr_storage *addr)
238 {
239   int ret = -1;
240
241   switch (addr->ss_family) {
242     case AF_INET:
243     {
244       struct sockaddr_in *addr4 = (struct sockaddr_in *) addr;
245
246       ret = IN_MULTICAST (g_ntohl (addr4->sin_addr.s_addr));
247     }
248       break;
249
250     case AF_INET6:
251     {
252       struct sockaddr_in6 *addr6 = (struct sockaddr_in6 *) addr;
253
254       ret = IN6_IS_ADDR_MULTICAST (&addr6->sin6_addr);
255     }
256       break;
257
258     default:
259 #ifdef G_OS_WIN32
260       WSASetLastError (WSAEAFNOSUPPORT);
261 #else
262       errno = EAFNOSUPPORT;
263 #endif
264   }
265
266   return ret;
267 }