1 /*
2 * This file is part of the Nice GLib ICE library.
3 *
4 * (C) 2006-2009 Collabora Ltd.
5 * Contact: Youness Alaoui
6 * (C) 2006-2009 Nokia Corporation. All rights reserved.
7 * Contact: Kai Vehmanen
8 *
9 * The contents of this file are subject to the Mozilla Public License Version
10 * 1.1 (the "License"); you may not use this file except in compliance with
11 * the License. You may obtain a copy of the License at
12 * http://www.mozilla.org/MPL/
13 *
14 * Software distributed under the License is distributed on an "AS IS" basis,
15 * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
16 * for the specific language governing rights and limitations under the
17 * License.
18 *
19 * The Original Code is the Nice GLib ICE library.
20 *
21 * The Initial Developers of the Original Code are Collabora Ltd and Nokia
22 * Corporation. All Rights Reserved.
23 *
24 * Contributors:
25 * Dafydd Harries, Collabora Ltd.
26 * Youness Alaoui, Collabora Ltd.
27 *
28 * Alternatively, the contents of this file may be used under the terms of the
29 * the GNU Lesser General Public License Version 2.1 (the "LGPL"), in which
30 * case the provisions of LGPL are applicable instead of those above. If you
31 * wish to allow use of your version of this file only under the terms of the
32 * LGPL and not to allow others to use your version of this file under the
33 * MPL, indicate your decision by deleting the provisions above and replace
34 * them with the notice and other provisions required by the LGPL. If you do
35 * not delete the provisions above, a recipient may use your version of this
36 * file under either the MPL or the LGPL.
37 */
38
39 /*
40 * Implementation of UDP socket interface using Berkeley sockets. (See
41 * http://en.wikipedia.org/wiki/Berkeley_sockets.)
42 */
43 #ifdef HAVE_CONFIG_H
44 # include "config.h"
45 #endif
46
47
48 #include <string.h>
49 #include <errno.h>
50 #include <fcntl.h>
51
52 #include "udp-bsd.h"
53 #include "agent-priv.h"
54
55 #ifndef G_OS_WIN32
56 #include <unistd.h>
57 #endif
58
59
60 static void socket_close (NiceSocket *sock);
61 static gint socket_recv_messages (NiceSocket *sock,
62 NiceInputMessage *recv_messages, guint n_recv_messages);
63 static gint socket_send_messages (NiceSocket *sock, const NiceAddress *to,
64 const NiceOutputMessage *messages, guint n_messages);
65 static gint socket_send_messages_reliable (NiceSocket *sock,
66 const NiceAddress *to, const NiceOutputMessage *messages, guint n_messages);
67 static gboolean socket_is_reliable (NiceSocket *sock);
68 static gboolean socket_can_send (NiceSocket *sock, NiceAddress *addr);
69 static void socket_set_writable_callback (NiceSocket *sock,
70 NiceSocketWritableCb callback, gpointer user_data);
71
72 struct UdpBsdSocketPrivate
73 {
74 GMutex mutex;
75
76 /* protected by mutex */
77 NiceAddress niceaddr;
78 GSocketAddress *gaddr;
79 };
80
81 NiceSocket *
nice_udp_bsd_socket_new(NiceAddress * addr)82 nice_udp_bsd_socket_new (NiceAddress *addr)
83 {
84 union {
85 struct sockaddr_storage storage;
86 struct sockaddr addr;
87 } name;
88 NiceSocket *sock = g_slice_new0 (NiceSocket);
89 GSocket *gsock = NULL;
90 gboolean gret = FALSE;
91 GSocketAddress *gaddr;
92 struct UdpBsdSocketPrivate *priv;
93
94 if (addr != NULL) {
95 nice_address_copy_to_sockaddr(addr, &name.addr);
96 } else {
97 memset (&name, 0, sizeof (name));
98 name.storage.ss_family = AF_UNSPEC;
99 }
100
101 if (name.storage.ss_family == AF_UNSPEC || name.storage.ss_family == AF_INET) {
102 gsock = g_socket_new (G_SOCKET_FAMILY_IPV4, G_SOCKET_TYPE_DATAGRAM,
103 G_SOCKET_PROTOCOL_UDP, NULL);
104 name.storage.ss_family = AF_INET;
105 #ifdef HAVE_SA_LEN
106 name.storage.ss_len = sizeof (struct sockaddr_in);
107 #endif
108 } else if (name.storage.ss_family == AF_INET6) {
109 gsock = g_socket_new (G_SOCKET_FAMILY_IPV6, G_SOCKET_TYPE_DATAGRAM,
110 G_SOCKET_PROTOCOL_UDP, NULL);
111 name.storage.ss_family = AF_INET6;
112 #ifdef HAVE_SA_LEN
113 name.storage.ss_len = sizeof (struct sockaddr_in6);
114 #endif
115 }
116
117 if (gsock == NULL) {
118 g_slice_free (NiceSocket, sock);
119 return NULL;
120 }
121
122 /* GSocket: All socket file descriptors are set to be close-on-exec. */
123 g_socket_set_blocking (gsock, false);
124 gaddr = g_socket_address_new_from_native (&name.addr, sizeof (name));
125 if (gaddr != NULL) {
126 gret = g_socket_bind (gsock, gaddr, FALSE, NULL);
127 g_object_unref (gaddr);
128 }
129
130 if (gret == FALSE) {
131 g_slice_free (NiceSocket, sock);
132 g_socket_close (gsock, NULL);
133 g_object_unref (gsock);
134 return NULL;
135 }
136
137 gaddr = g_socket_get_local_address (gsock, NULL);
138 if (gaddr == NULL ||
139 !g_socket_address_to_native (gaddr, &name, sizeof(name), NULL)) {
140 g_slice_free (NiceSocket, sock);
141 g_socket_close (gsock, NULL);
142 g_object_unref (gsock);
143 return NULL;
144 }
145
146 g_object_unref (gaddr);
147
148 nice_address_set_from_sockaddr (&sock->addr, &name.addr);
149
150 priv = sock->priv = g_slice_new0 (struct UdpBsdSocketPrivate);
151 nice_address_init (&priv->niceaddr);
152
153 sock->type = NICE_SOCKET_TYPE_UDP_BSD;
154 sock->fileno = gsock;
155 sock->send_messages = socket_send_messages;
156 sock->send_messages_reliable = socket_send_messages_reliable;
157 sock->recv_messages = socket_recv_messages;
158 sock->is_reliable = socket_is_reliable;
159 sock->can_send = socket_can_send;
160 sock->set_writable_callback = socket_set_writable_callback;
161 sock->close = socket_close;
162
163 g_mutex_init (&priv->mutex);
164
165 return sock;
166 }
167
168 static void
socket_close(NiceSocket * sock)169 socket_close (NiceSocket *sock)
170 {
171 struct UdpBsdSocketPrivate *priv = sock->priv;
172
173 g_clear_object (&priv->gaddr);
174 g_mutex_clear (&priv->mutex);
175 g_slice_free (struct UdpBsdSocketPrivate, sock->priv);
176 sock->priv = NULL;
177
178 if (sock->fileno) {
179 g_socket_close (sock->fileno, NULL);
180 g_object_unref (sock->fileno);
181 sock->fileno = NULL;
182 }
183 }
184
185 static gint
socket_recv_messages(NiceSocket * sock,NiceInputMessage * recv_messages,guint n_recv_messages)186 socket_recv_messages (NiceSocket *sock,
187 NiceInputMessage *recv_messages, guint n_recv_messages)
188 {
189 guint i;
190 gboolean error = FALSE;
191
192 /* Make sure socket has not been freed: */
193 g_assert (sock->priv != NULL);
194
195 /* Read messages into recv_messages until one fails or would block, or we
196 * reach the end. */
197 for (i = 0; i < n_recv_messages; i++) {
198 NiceInputMessage *recv_message = &recv_messages[i];
199 GSocketAddress *gaddr = NULL;
200 GError *gerr = NULL;
201 gssize recvd;
202 gint flags = G_SOCKET_MSG_NONE;
203
204 recvd = g_socket_receive_message (sock->fileno,
205 (recv_message->from != NULL) ? &gaddr : NULL,
206 recv_message->buffers, recv_message->n_buffers, NULL, NULL,
207 &flags, NULL, &gerr);
208
209 if (recvd < 0) {
210 /* Handle ECONNRESET here as if it were EWOULDBLOCK; see
211 * https://phabricator.freedesktop.org/T121 */
212 if (g_error_matches (gerr, G_IO_ERROR, G_IO_ERROR_WOULD_BLOCK) ||
213 g_error_matches (gerr, G_IO_ERROR, G_IO_ERROR_CONNECTION_CLOSED))
214 recvd = 0;
215 else if (g_error_matches (gerr, G_IO_ERROR, G_IO_ERROR_MESSAGE_TOO_LARGE))
216 recvd = input_message_get_size (recv_message);
217 else
218 error = TRUE;
219
220 g_error_free (gerr);
221 }
222
223 recv_message->length = MAX (recvd, 0);
224
225 if (recvd > 0 && recv_message->from != NULL && gaddr != NULL) {
226 union {
227 struct sockaddr_storage storage;
228 struct sockaddr addr;
229 } sa;
230
231 g_socket_address_to_native (gaddr, &sa, sizeof (sa), NULL);
232 nice_address_set_from_sockaddr (recv_message->from, &sa.addr);
233 }
234
235 if (gaddr != NULL)
236 g_object_unref (gaddr);
237
238 /* Return early on error or EWOULDBLOCK. */
239 if (recvd <= 0)
240 break;
241 }
242
243 /* Was there an error processing the first message? */
244 if (error && i == 0)
245 return -1;
246
247 return i;
248 }
249
250 static gint
socket_send_messages(NiceSocket * sock,const NiceAddress * to,const NiceOutputMessage * messages,guint n_messages)251 socket_send_messages (NiceSocket *sock, const NiceAddress *to,
252 const NiceOutputMessage *messages, guint n_messages)
253 {
254 guint i;
255
256 struct UdpBsdSocketPrivate *priv = sock->priv;
257 GError *child_error = NULL;
258 gint len;
259 GSocketAddress *gaddr = NULL;
260
261 /* Make sure socket has not been freed: */
262 g_assert (sock->priv != NULL);
263
264 g_mutex_lock (&priv->mutex);
265 if (!nice_address_is_valid (&priv->niceaddr) ||
266 !nice_address_equal (&priv->niceaddr, to)) {
267 union {
268 struct sockaddr_storage storage;
269 struct sockaddr addr;
270 } sa;
271
272 g_clear_object (&priv->gaddr);
273
274 nice_address_copy_to_sockaddr (to, &sa.addr);
275 gaddr = g_socket_address_new_from_native (&sa.addr, sizeof(sa));
276 if (gaddr)
277 priv->gaddr = g_object_ref (gaddr);
278
279 if (gaddr == NULL) {
280 g_mutex_unlock (&priv->mutex);
281 return -1;
282 }
283
284 priv->niceaddr = *to;
285 } else {
286 if (priv->gaddr)
287 gaddr = g_object_ref (priv->gaddr);
288 }
289 g_mutex_unlock (&priv->mutex);
290
291 if (n_messages == 1) {
292 /* Single message: use g_socket_send_message */
293 len = g_socket_send_message (sock->fileno, gaddr, messages->buffers,
294 messages->n_buffers, NULL, 0, G_SOCKET_MSG_NONE, NULL, &child_error);
295 if(len > 0)
296 len = 1;
297 } else {
298 /* Multiple messages: use g_socket_send_messages, which might use
299 * the more efficient sendmmsg if supported by the platform */
300 GOutputMessage *go_messages = g_alloca (n_messages * sizeof (GOutputMessage));
301 for (i = 0; i < n_messages; i++) {
302 const NiceOutputMessage *message = &messages[i];
303 go_messages[i].address = gaddr;
304 go_messages[i].vectors = message->buffers;
305 go_messages[i].num_vectors = message->n_buffers;
306 go_messages[i].bytes_sent = 0;
307 go_messages[i].control_messages = NULL;
308 go_messages[i].num_control_messages = 0;
309 }
310 len = g_socket_send_messages (sock->fileno, go_messages,
311 n_messages, G_SOCKET_MSG_NONE, NULL, &child_error);
312 }
313
314 if (len < 0) {
315 if (g_error_matches (child_error, G_IO_ERROR, G_IO_ERROR_WOULD_BLOCK)) {
316 len = 0;
317 } else if (nice_debug_is_verbose()) {
318 union {
319 struct sockaddr_storage ss;
320 struct sockaddr sa;
321 } sa;
322 GSocketAddress *gsocket;
323 NiceAddress local_addr;
324 NiceAddress remote_addr;
325 char remote_addr_str[INET6_ADDRSTRLEN];
326 char local_addr_str[INET6_ADDRSTRLEN];
327
328 g_socket_address_to_native (gaddr, &sa, sizeof (sa), NULL);
329 nice_address_set_from_sockaddr (&remote_addr, &sa.sa);
330 nice_address_to_string (&remote_addr, remote_addr_str);
331
332 gsocket = g_socket_get_local_address (sock->fileno, NULL);
333 g_socket_address_to_native (gsocket, &sa, sizeof (sa), NULL);
334 nice_address_set_from_sockaddr (&local_addr, &sa.sa);
335 nice_address_to_string (&local_addr, local_addr_str);
336 g_object_unref (gsocket);
337
338 nice_debug_verbose ("%s: udp-bsd socket %p %s:%u -> %s:%u: error: %s",
339 G_STRFUNC, sock,
340 local_addr_str, nice_address_get_port (&local_addr),
341 remote_addr_str, nice_address_get_port (&remote_addr),
342 child_error->message);
343 }
344
345 g_error_free (child_error);
346 }
347
348 g_clear_object (&gaddr);
349
350 return len;
351 }
352
353 static gint
socket_send_messages_reliable(NiceSocket * sock,const NiceAddress * to,const NiceOutputMessage * messages,guint n_messages)354 socket_send_messages_reliable (NiceSocket *sock, const NiceAddress *to,
355 const NiceOutputMessage *messages, guint n_messages)
356 {
357 return -1;
358 }
359
360 static gboolean
socket_is_reliable(NiceSocket * sock)361 socket_is_reliable (NiceSocket *sock)
362 {
363 return FALSE;
364 }
365
366 static gboolean
socket_can_send(NiceSocket * sock,NiceAddress * addr)367 socket_can_send (NiceSocket *sock, NiceAddress *addr)
368 {
369 return TRUE;
370 }
371
372 static void
socket_set_writable_callback(NiceSocket * sock,NiceSocketWritableCb callback,gpointer user_data)373 socket_set_writable_callback (NiceSocket *sock,
374 NiceSocketWritableCb callback, gpointer user_data)
375 {
376 }
377
378