2 * This file is part of the Nice GLib ICE library.
4 * (C) 2006-2009 Collabora Ltd.
5 * Contact: Youness Alaoui
6 * (C) 2006-2009 Nokia Corporation. All rights reserved.
7 * Contact: Kai Vehmanen
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/
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
19 * The Original Code is the Nice GLib ICE library.
21 * The Initial Developers of the Original Code are Collabora Ltd and Nokia
22 * Corporation. All Rights Reserved.
25 * Dafydd Harries, Collabora Ltd.
26 * Youness Alaoui, Collabora Ltd.
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.
40 * Implementation of UDP socket interface using Berkeley sockets. (See
41 * http://en.wikipedia.org/wiki/Berkeley_sockets.)
53 #include "agent-priv.h"
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);
72 struct UdpBsdSocketPrivate
76 /* protected by mutex */
78 GSocketAddress *gaddr;
82 nice_udp_bsd_socket_new (NiceAddress *addr)
85 struct sockaddr_storage storage;
88 NiceSocket *sock = g_slice_new0 (NiceSocket);
89 GSocket *gsock = NULL;
90 gboolean gret = FALSE;
91 GSocketAddress *gaddr;
92 struct UdpBsdSocketPrivate *priv;
95 nice_address_copy_to_sockaddr(addr, &name.addr);
97 memset (&name, 0, sizeof (name));
98 name.storage.ss_family = AF_UNSPEC;
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;
106 name.storage.ss_len = sizeof (struct sockaddr_in);
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;
113 name.storage.ss_len = sizeof (struct sockaddr_in6);
118 g_slice_free (NiceSocket, sock);
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));
126 gret = g_socket_bind (gsock, gaddr, FALSE, NULL);
127 g_object_unref (gaddr);
131 g_slice_free (NiceSocket, sock);
132 g_socket_close (gsock, NULL);
133 g_object_unref (gsock);
137 gaddr = g_socket_get_local_address (gsock, 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);
146 g_object_unref (gaddr);
148 nice_address_set_from_sockaddr (&sock->addr, &name.addr);
150 priv = sock->priv = g_slice_new0 (struct UdpBsdSocketPrivate);
151 nice_address_init (&priv->niceaddr);
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;
163 g_mutex_init (&priv->mutex);
169 socket_close (NiceSocket *sock)
171 struct UdpBsdSocketPrivate *priv = sock->priv;
173 g_clear_object (&priv->gaddr);
174 g_mutex_clear (&priv->mutex);
175 g_slice_free (struct UdpBsdSocketPrivate, sock->priv);
179 g_socket_close (sock->fileno, NULL);
180 g_object_unref (sock->fileno);
186 socket_recv_messages (NiceSocket *sock,
187 NiceInputMessage *recv_messages, guint n_recv_messages)
190 gboolean error = FALSE;
192 /* Make sure socket has not been freed: */
193 g_assert (sock->priv != NULL);
195 /* Read messages into recv_messages until one fails or would block, or we
197 for (i = 0; i < n_recv_messages; i++) {
198 NiceInputMessage *recv_message = &recv_messages[i];
199 GSocketAddress *gaddr = NULL;
202 gint flags = G_SOCKET_MSG_NONE;
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);
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))
215 else if (g_error_matches (gerr, G_IO_ERROR, G_IO_ERROR_MESSAGE_TOO_LARGE))
216 recvd = input_message_get_size (recv_message);
223 recv_message->length = MAX (recvd, 0);
225 if (recvd > 0 && recv_message->from != NULL && gaddr != NULL) {
227 struct sockaddr_storage storage;
228 struct sockaddr addr;
231 g_socket_address_to_native (gaddr, &sa, sizeof (sa), NULL);
232 nice_address_set_from_sockaddr (recv_message->from, &sa.addr);
236 g_object_unref (gaddr);
238 /* Return early on error or EWOULDBLOCK. */
243 /* Was there an error processing the first message? */
251 socket_send_message (NiceSocket *sock, const NiceAddress *to,
252 const NiceOutputMessage *message)
254 struct UdpBsdSocketPrivate *priv = sock->priv;
255 GError *child_error = NULL;
257 GSocketAddress *gaddr = NULL;
259 /* Make sure socket has not been freed: */
260 g_assert (sock->priv != NULL);
262 g_mutex_lock (&priv->mutex);
263 if (!nice_address_is_valid (&priv->niceaddr) ||
264 !nice_address_equal (&priv->niceaddr, to)) {
266 struct sockaddr_storage storage;
267 struct sockaddr addr;
270 g_clear_object (&priv->gaddr);
272 nice_address_copy_to_sockaddr (to, &sa.addr);
273 gaddr = g_socket_address_new_from_native (&sa.addr, sizeof(sa));
275 priv->gaddr = g_object_ref (gaddr);
278 g_mutex_unlock (&priv->mutex);
282 priv->niceaddr = *to;
285 gaddr = g_object_ref (priv->gaddr);
287 g_mutex_unlock (&priv->mutex);
289 len = g_socket_send_message (sock->fileno, gaddr, message->buffers,
290 message->n_buffers, NULL, 0, G_SOCKET_MSG_NONE, NULL, &child_error);
293 if (g_error_matches (child_error, G_IO_ERROR, G_IO_ERROR_WOULD_BLOCK)) {
295 } else if (nice_debug_is_verbose()) {
297 struct sockaddr_storage ss;
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];
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);
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);
316 nice_debug_verbose ("%s: udp-bsd socket %p %s:%u -> %s:%u: error: %s",
318 local_addr_str, nice_address_get_port (&local_addr),
319 remote_addr_str, nice_address_get_port (&remote_addr),
320 child_error->message);
323 g_error_free (child_error);
326 g_clear_object (&gaddr);
332 socket_send_messages (NiceSocket *sock, const NiceAddress *to,
333 const NiceOutputMessage *messages, guint n_messages)
337 /* Make sure socket has not been freed: */
338 g_assert (sock->priv != NULL);
340 for (i = 0; i < n_messages; i++) {
341 const NiceOutputMessage *message = &messages[i];
344 len = socket_send_message (sock, to, message);
351 } else if (len == 0) {
361 socket_send_messages_reliable (NiceSocket *sock, const NiceAddress *to,
362 const NiceOutputMessage *messages, guint n_messages)
368 socket_is_reliable (NiceSocket *sock)
374 socket_can_send (NiceSocket *sock, NiceAddress *addr)
380 socket_set_writable_callback (NiceSocket *sock,
381 NiceSocketWritableCb callback, gpointer user_data)