2 * This file is part of the Nice GLib ICE library.
4 * (C) 2008-2009 Collabora Ltd.
5 * Contact: Youness Alaoui
6 * (C) 2008-2009 Nokia Corporation. All rights reserved.
8 * The contents of this file are subject to the Mozilla Public License Version
9 * 1.1 (the "License"); you may not use this file except in compliance with
10 * the License. You may obtain a copy of the License at
11 * http://www.mozilla.org/MPL/
13 * Software distributed under the License is distributed on an "AS IS" basis,
14 * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
15 * for the specific language governing rights and limitations under the
18 * The Original Code is the Nice GLib ICE library.
20 * The Initial Developers of the Original Code are Collabora Ltd and Nokia
21 * Corporation. All Rights Reserved.
24 * Youness Alaoui, Collabora Ltd.
26 * Alternatively, the contents of this file may be used under the terms of the
27 * the GNU Lesser General Public License Version 2.1 (the "LGPL"), in which
28 * case the provisions of LGPL are applicable instead of those above. If you
29 * wish to allow use of your version of this file only under the terms of the
30 * LGPL and not to allow others to use your version of this file under the
31 * MPL, indicate your decision by deleting the provisions above and replace
32 * them with the notice and other provisions required by the LGPL. If you do
33 * not delete the provisions above, a recipient may use your version of this
34 * file under either the MPL or the LGPL.
44 #include "socket-priv.h"
45 #include "agent-priv.h"
53 typedef struct _NiceSocketQueuedSend NiceSocketQueuedSend;
55 struct _NiceSocketQueuedSend {
56 guint8 *buf; /* owned */
62 * nice_socket_recv_messages:
63 * @sock: a #NiceSocket
64 * @recv_messages: (array length=n_recv_messages) (out caller-allocates):
65 * array of #NiceInputMessages to return received messages in
66 * @n_recv_messages: number of elements in the @recv_messages array
68 * Receive up to @n_recv_messages message on the socket, in a non-reliable,
69 * non-blocking fashion. The total size of the buffers in each #NiceInputMessage
70 * must be big enough to contain an entire message (65536 bytes), or excess
71 * bytes will be silently dropped.
73 * On success, the number of messages received into @recv_messages is returned,
74 * which may be less than @n_recv_messages if the call would have blocked
75 * part-way through. If the socket would have blocked to begin with, or if
76 * @n_recv_messages is zero, zero is returned. On failure, a negative value is
77 * returned, but no further error information is available. Calling this
78 * function on a socket which has closed is an error, and a negative value is
81 * If a positive N is returned, the first N messages in @recv_messages are
82 * valid. Each valid message is guaranteed to have a non-zero
83 * #NiceInputMessage::length, and its buffers are guaranteed to be filled
84 * sequentially up to that number of bytes If #NiceInputMessage::from was
85 * non-%NULL for a valid message, it may be set to the address of the sender of
86 * that received message.
88 * If the return value is zero or negative, the from return address and length
89 * in every #NiceInputMessage in @recv_messages are guaranteed to be unmodified.
90 * The buffers may have been modified.
92 * The base addresses and sizes of the buffers in a #NiceInputMessage are never
93 * modified. Neither is the base address of #NiceInputMessage::from, nor the
94 * base address and length of the #NiceInputMessage::buffers array.
96 * Returns: number of valid messages returned in @recv_messages, or a negative
102 nice_socket_recv_messages (NiceSocket *sock,
103 NiceInputMessage *recv_messages, guint n_recv_messages)
105 g_return_val_if_fail (sock != NULL, -1);
106 g_return_val_if_fail (n_recv_messages == 0 || recv_messages != NULL, -1);
108 return sock->recv_messages (sock, recv_messages, n_recv_messages);
112 * nice_socket_send_messages:
113 * @sock: a #NiceSocket
114 * @messages: (array length=n_messages) (in caller-allocates):
115 * array of #NiceOutputMessages containing the messages to send
116 * @n_messages: number of elements in the @messages array
118 * Send up to @n_messages on the socket, in a non-reliable, non-blocking
119 * fashion. The total size of the buffers in each #NiceOutputMessage
120 * must be at most the maximum UDP payload size (65535 bytes), or excess
121 * bytes will be silently dropped.
123 * On success, the number of messages transmitted from @messages is returned,
124 * which may be less than @n_messages if the call would have blocked
125 * part-way through. If the socket would have blocked to begin with, or if
126 * @n_messages is zero, zero is returned. On failure, a negative value is
127 * returned, but no further error information is available. Calling this
128 * function on a socket which has closed is an error, and a negative value is
131 * If a positive N is returned, the first N messages in @messages have been
132 * sent in full, and the remaining messages have not been sent at all.
134 * If #NiceOutputMessage::to is specified for a message, that will be used as
135 * the destination address for the message. Otherwise, if %NULL, the default
136 * destination for @sock will be used.
138 * Every field of every #NiceOutputMessage is guaranteed to be unmodified when
139 * this function returns.
141 * Returns: number of messages successfully sent from @messages, or a negative
147 nice_socket_send_messages (NiceSocket *sock, const NiceAddress *to,
148 const NiceOutputMessage *messages, guint n_messages)
150 g_return_val_if_fail (sock != NULL, -1);
151 g_return_val_if_fail (n_messages == 0 || messages != NULL, -1);
153 return sock->send_messages (sock, to, messages, n_messages);
157 * nice_socket_send_messages_reliable:
158 * @sock: a #NiceSocket
159 * @messages: (array length=n_messages) (in caller-allocates):
160 * array of #NiceOutputMessages containing the messages to send
161 * @n_messages: number of elements in the @messages array
163 * Send @n_messages on the socket, in a reliable, non-blocking fashion.
164 * The total size of the buffers in each #NiceOutputMessage
165 * must be at most the maximum UDP payload size (65535 bytes), or excess
166 * bytes will be silently dropped.
168 * On success, the number of messages transmitted from @messages is returned,
169 * which will be equal to @n_messages. If the call would have blocked part-way
170 * though, the remaining bytes will be queued for sending later.
171 * On failure, a negative value is returned, but no further error information
172 * is available. Calling this function on a socket which has closed is an error,
173 * and a negative value is returned. Calling this function on a socket which
174 * is not TCP or does not have a TCP base socket, will result in an error.
176 * If #NiceOutputMessage::to is specified for a message, that will be used as
177 * the destination address for the message. Otherwise, if %NULL, the default
178 * destination for @sock will be used.
180 * Every field of every #NiceOutputMessage is guaranteed to be unmodified when
181 * this function returns.
183 * Returns: number of messages successfully sent from @messages, or a negative
189 nice_socket_send_messages_reliable (NiceSocket *sock, const NiceAddress *to,
190 const NiceOutputMessage *messages, guint n_messages)
192 g_return_val_if_fail (sock != NULL, -1);
193 g_return_val_if_fail (n_messages == 0 || messages != NULL, -1);
195 return sock->send_messages_reliable (sock, to, messages, n_messages);
198 /* Convenience wrapper around nice_socket_recv_messages(). Returns the number of
199 * bytes received on success (which will be @len), zero if sending would block, or
202 nice_socket_recv (NiceSocket *sock, NiceAddress *from, gsize len,
205 GInputVector local_buf = { buf, len };
206 NiceInputMessage local_message = { &local_buf, 1, from, 0};
209 ret = sock->recv_messages (sock, &local_message, 1);
211 return local_message.length;
215 /* Convenience wrapper around nice_socket_send_messages(). Returns the number of
216 * bytes sent on success (which will be @len), zero if sending would block, or
219 nice_socket_send (NiceSocket *sock, const NiceAddress *to, gsize len,
222 GOutputVector local_buf = { buf, len };
223 NiceOutputMessage local_message = { &local_buf, 1};
226 ret = sock->send_messages (sock, to, &local_message, 1);
233 nice_socket_send_reliable (NiceSocket *sock, const NiceAddress *to, gsize len,
236 GOutputVector local_buf = { buf, len };
237 NiceOutputMessage local_message = { &local_buf, 1};
240 ret = sock->send_messages_reliable (sock, to, &local_message, 1);
247 nice_socket_is_reliable (NiceSocket *sock)
249 return sock->is_reliable (sock);
253 nice_socket_can_send (NiceSocket *sock, NiceAddress *addr)
256 return sock->can_send (sock, addr);
261 nice_socket_set_writable_callback (NiceSocket *sock,
262 NiceSocketWritableCb callback, gpointer user_data)
264 if (sock->set_writable_callback)
265 sock->set_writable_callback (sock, callback, user_data);
269 nice_socket_is_based_on (NiceSocket *sock, NiceSocket *other)
271 if (sock->is_based_on)
272 return sock->is_based_on (sock, other);
273 return (sock == other);
277 nice_socket_free (NiceSocket *sock)
281 g_slice_free (NiceSocket,sock);
286 nice_socket_free_queued_send (NiceSocketQueuedSend *tbs)
289 g_slice_free (NiceSocketQueuedSend, tbs);
293 nice_socket_queue_send (GQueue *send_queue, const NiceAddress *to,
294 const NiceOutputMessage *messages, guint n_messages)
301 /* Compact the message’s buffers before queueing. */
302 for (i = 0; i < n_messages; i++) {
303 NiceSocketQueuedSend *tbs;
304 const NiceOutputMessage *message = &messages[i];
305 gsize message_len_remaining = output_message_get_size (message);
309 if (message_len_remaining == 0)
312 /* Compact the buffer. */
313 tbs = g_slice_new0 (NiceSocketQueuedSend);
314 tbs->buf = g_malloc (message_len_remaining);
315 tbs->length = message_len_remaining;
320 memset (&tbs->to, 0, sizeof(NiceAddress));
321 g_queue_push_tail (send_queue, tbs);
324 (message->n_buffers >= 0 && j < (guint) message->n_buffers) ||
325 (message->n_buffers < 0 && message->buffers[j].buffer != NULL);
327 const GOutputVector *buffer = &message->buffers[j];
330 len = MIN (buffer->size, message_len_remaining);
331 memcpy (tbs->buf + offset, buffer->buffer, len);
332 message_len_remaining -= len;
336 g_assert_cmpint (offset, ==, tbs->length);
340 void nice_socket_queue_send_with_callback (GQueue *send_queue,
341 const NiceOutputMessage *message, gsize message_offset, gsize message_len,
342 gboolean head, GSocket *gsock, GSource **io_source, GMainContext *context,
343 GSocketSourceFunc cb, gpointer user_data)
345 NiceSocketQueuedSend *tbs;
349 if (message_offset >= message_len)
352 tbs = g_slice_new0 (NiceSocketQueuedSend);
353 tbs->length = message_len - message_offset;
354 tbs->buf = g_malloc (tbs->length);
357 g_queue_push_head (send_queue, tbs);
359 g_queue_push_tail (send_queue, tbs);
361 /* Move the data into the buffer. */
363 (message->n_buffers >= 0 && j < (guint) message->n_buffers) ||
364 (message->n_buffers < 0 && message->buffers[j].buffer != NULL);
366 const GOutputVector *buffer = &message->buffers[j];
369 /* Skip this buffer if it’s within @message_offset. */
370 if (buffer->size <= message_offset) {
371 message_offset -= buffer->size;
375 len = MIN (tbs->length - offset, buffer->size - message_offset);
376 memcpy (tbs->buf + offset, (guint8 *) buffer->buffer + message_offset, len);
378 if (message_offset >= len)
379 message_offset -= len;
384 if (io_source && gsock && context && cb && *io_source == NULL) {
385 *io_source = g_socket_create_source(gsock, G_IO_OUT, NULL);
386 g_source_set_callback (*io_source, (GSourceFunc) G_CALLBACK (cb), user_data, NULL);
387 g_source_attach (*io_source, context);
391 void nice_socket_flush_send_queue (NiceSocket *base_socket, GQueue *send_queue)
393 NiceSocketQueuedSend *tbs;
395 while ((tbs = g_queue_pop_head (send_queue))) {
396 NiceAddress *to = &tbs->to;
398 if (!nice_address_is_valid (to))
401 /* We only queue reliable data */
402 nice_socket_send_reliable (base_socket, to,
403 tbs->length, (const gchar *) tbs->buf);
404 nice_socket_free_queued_send (tbs);
408 gboolean nice_socket_flush_send_queue_to_socket (GSocket *gsock,
411 NiceSocketQueuedSend *tbs;
415 while ((tbs = g_queue_pop_head (send_queue)) != NULL) {
418 GOutputVector local_bufs = { tbs->buf, tbs->length };
419 ret = g_socket_send_message (gsock, NULL, &local_bufs, 1, NULL, 0,
420 G_SOCKET_MSG_NONE, NULL, &gerr);
423 if (g_error_matches (gerr, G_IO_ERROR, G_IO_ERROR_WOULD_BLOCK)) {
424 GOutputVector local_buf = { tbs->buf, tbs->length };
425 NiceOutputMessage local_message = {&local_buf, 1};
427 nice_socket_queue_send_with_callback (send_queue, &local_message,
428 0, local_buf.size, TRUE, NULL, NULL, NULL, NULL, NULL);
429 nice_socket_free_queued_send (tbs);
433 g_clear_error (&gerr);
434 } else if (ret < (int) tbs->length) {
435 GOutputVector local_buf = { tbs->buf + ret, tbs->length - ret };
436 NiceOutputMessage local_message = {&local_buf, 1};
438 nice_socket_queue_send_with_callback (send_queue, &local_message,
439 0, local_buf.size, TRUE, NULL, NULL, NULL, NULL, NULL);
440 nice_socket_free_queued_send (tbs);
444 nice_socket_free_queued_send (tbs);
451 nice_socket_free_send_queue (GQueue *send_queue)
453 g_list_free_full (send_queue->head, (GDestroyNotify) nice_socket_free_queued_send);
454 g_queue_init (send_queue);