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