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