65974c208bea9ceddd0e621662ef6526b08cbbbc
[platform/upstream/libnice.git] / socket / udp-bsd.c
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 *
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
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
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 gssize
251 socket_send_message (NiceSocket *sock, const NiceAddress *to,
252     const NiceOutputMessage *message)
253 {
254   struct UdpBsdSocketPrivate *priv = sock->priv;
255   GError *child_error = NULL;
256   gssize len;
257   GSocketAddress *gaddr = NULL;
258
259   /* Make sure socket has not been freed: */
260   g_assert (sock->priv != NULL);
261
262   g_mutex_lock (&priv->mutex);
263   if (!nice_address_is_valid (&priv->niceaddr) ||
264       !nice_address_equal (&priv->niceaddr, to)) {
265     union {
266       struct sockaddr_storage storage;
267       struct sockaddr addr;
268     } sa;
269
270     g_clear_object (&priv->gaddr);
271
272     nice_address_copy_to_sockaddr (to, &sa.addr);
273     gaddr = g_socket_address_new_from_native (&sa.addr, sizeof(sa));
274     if (gaddr)
275       priv->gaddr = g_object_ref (gaddr);
276
277     if (gaddr == NULL) {
278       g_mutex_unlock (&priv->mutex);
279       return -1;
280     }
281
282     priv->niceaddr = *to;
283   } else {
284     if (priv->gaddr)
285       gaddr = g_object_ref (priv->gaddr);
286   }
287   g_mutex_unlock (&priv->mutex);
288
289   len = g_socket_send_message (sock->fileno, gaddr, message->buffers,
290       message->n_buffers, NULL, 0, G_SOCKET_MSG_NONE, NULL, &child_error);
291
292   if (len < 0) {
293     if (g_error_matches (child_error, G_IO_ERROR, G_IO_ERROR_WOULD_BLOCK)) {
294       len = 0;
295     } else if (nice_debug_is_verbose()) {
296       union {
297         struct sockaddr_storage ss;
298         struct sockaddr sa;
299       } sa;
300       GSocketAddress *gsocket;
301       NiceAddress local_addr;
302       NiceAddress remote_addr;
303       char remote_addr_str[INET6_ADDRSTRLEN];
304       char local_addr_str[INET6_ADDRSTRLEN];
305
306       g_socket_address_to_native (gaddr, &sa, sizeof (sa), NULL);
307       nice_address_set_from_sockaddr (&remote_addr, &sa.sa);
308       nice_address_to_string (&remote_addr, remote_addr_str);
309
310       gsocket = g_socket_get_local_address (sock->fileno, NULL);
311       g_socket_address_to_native (gsocket, &sa, sizeof (sa), NULL);
312       nice_address_set_from_sockaddr (&local_addr, &sa.sa);
313       nice_address_to_string (&local_addr, local_addr_str);
314       g_object_unref (gsocket);
315
316       nice_debug_verbose ("%s: udp-bsd socket %p %s:%u -> %s:%u: error: %s",
317           G_STRFUNC, sock,
318           local_addr_str, nice_address_get_port (&local_addr),
319           remote_addr_str, nice_address_get_port (&remote_addr),
320           child_error->message);
321     }
322
323     g_error_free (child_error);
324   }
325
326   g_clear_object (&gaddr);
327
328   return len;
329 }
330
331 static gint
332 socket_send_messages (NiceSocket *sock, const NiceAddress *to,
333     const NiceOutputMessage *messages, guint n_messages)
334 {
335   guint i;
336
337   /* Make sure socket has not been freed: */
338   g_assert (sock->priv != NULL);
339
340   for (i = 0; i < n_messages; i++) {
341     const NiceOutputMessage *message = &messages[i];
342     gssize len;
343
344     len = socket_send_message (sock, to, message);
345
346     if (len < 0) {
347       /* Error. */
348       if (i > 0)
349         break;
350       return len;
351     } else if (len == 0) {
352       /* EWOULDBLOCK. */
353       break;
354     }
355   }
356
357   return i;
358 }
359
360 static gint
361 socket_send_messages_reliable (NiceSocket *sock, const NiceAddress *to,
362     const NiceOutputMessage *messages, guint n_messages)
363 {
364   return -1;
365 }
366
367 static gboolean
368 socket_is_reliable (NiceSocket *sock)
369 {
370   return FALSE;
371 }
372
373 static gboolean
374 socket_can_send (NiceSocket *sock, NiceAddress *addr)
375 {
376   return TRUE;
377 }
378
379 static void
380 socket_set_writable_callback (NiceSocket *sock,
381     NiceSocketWritableCb callback, gpointer user_data)
382 {
383 }
384