2 * This file is part of the Nice GLib ICE library.
4 * (C) 2006, 2007, 2014 Collabora Ltd.
5 * Contact: Dafydd Harries
6 * (C) 2006, 2007 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 * Philip Withnall, 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.
47 socket_recv (NiceSocket *sock, NiceAddress *addr, gsize buf_len, gchar *buf)
49 GInputVector local_buf = { buf, buf_len };
50 NiceInputMessage local_message = { &local_buf, 1, addr, 0 };
53 ret = nice_socket_recv_messages (sock, &local_message, 1);
57 return local_buf.size;
61 test_socket_initial_properties (void)
65 sock = nice_udp_bsd_socket_new (NULL);
66 g_assert (sock != NULL);
68 // not bound to a particular interface
69 g_assert_cmpint (sock->addr.s.ip4.sin_addr.s_addr, ==, 0);
70 // is bound to a particular port
71 g_assert_cmpuint (nice_address_get_port (&sock->addr), !=, 0);
73 nice_socket_free (sock);
77 test_socket_address_properties (void)
82 sock = nice_udp_bsd_socket_new (NULL);
83 g_assert (sock != NULL);
85 g_assert (nice_address_set_from_string (&tmp, "127.0.0.1"));
86 g_assert_cmpuint (nice_address_get_port (&sock->addr), !=, 0);
87 nice_address_set_port (&tmp, nice_address_get_port (&sock->addr));
88 g_assert_cmpuint (nice_address_get_port (&tmp), !=, 0);
90 nice_socket_free (sock);
94 test_simple_send_recv (void)
101 server = nice_udp_bsd_socket_new (NULL);
102 g_assert (server != NULL);
104 client = nice_udp_bsd_socket_new (NULL);
105 g_assert (client != NULL);
107 g_assert (nice_address_set_from_string (&tmp, "127.0.0.1"));
108 nice_address_set_port (&tmp, nice_address_get_port (&server->addr));
110 /* Send and receive stuff. */
111 g_assert_cmpint (nice_socket_send (client, &tmp, 5, "hello"), ==, 5);
113 g_assert_cmpint (socket_recv (server, &tmp, 5, buf), ==, 5);
114 g_assert_cmpint (strncmp (buf, "hello", 5), ==, 0);
116 g_assert_cmpint (nice_socket_send (server, &tmp, 5, "uryyb"), ==, 5);
118 g_assert_cmpint (socket_recv (client, &tmp, 5, buf), ==, 5);
119 g_assert_cmpint (strncmp (buf, "uryyb", 5), ==, 0);
121 nice_socket_free (client);
122 nice_socket_free (server);
125 /* Check that sending and receiving to/from zero-length buffers returns
128 test_zero_send_recv (void)
133 NiceOutputMessage local_out_message;
134 NiceInputMessage local_in_message;
136 sock = nice_udp_bsd_socket_new (NULL);
137 g_assert (sock != NULL);
139 g_assert (nice_address_set_from_string (&tmp, "127.0.0.1"));
140 g_assert_cmpuint (nice_address_get_port (&sock->addr), !=, 0);
141 nice_address_set_port (&tmp, nice_address_get_port (&sock->addr));
142 g_assert_cmpuint (nice_address_get_port (&tmp), !=, 0);
144 g_assert_cmpint (nice_socket_send (sock, &tmp, 0, "ignore-me"), ==, 0);
145 g_assert_cmpint (nice_socket_send (sock, &tmp, 0, NULL), ==, 0);
147 g_assert_cmpint (socket_recv (sock, &tmp, 0, buf), ==, 0);
148 g_assert_cmpint (socket_recv (sock, &tmp, 0, NULL), ==, 0);
150 /* And again with messages. */
151 g_assert_cmpint (nice_socket_send_messages (sock, &tmp,
152 &local_out_message, 0), ==, 0);
153 g_assert_cmpint (nice_socket_send_messages (sock, &tmp, NULL, 0), ==, 0);
155 g_assert_cmpint (nice_socket_recv_messages (sock,
156 &local_in_message, 0), ==, 0);
157 g_assert_cmpint (nice_socket_recv_messages (sock, NULL, 0), ==, 0);
159 nice_socket_free (sock);
162 /* Test receiving into multiple tiny buffers. */
164 test_multi_buffer_recv (void)
172 server = nice_udp_bsd_socket_new (NULL);
173 g_assert (server != NULL);
175 client = nice_udp_bsd_socket_new (NULL);
176 g_assert (client != NULL);
178 g_assert (nice_address_set_from_string (&tmp, "127.0.0.1"));
179 nice_address_set_port (&tmp, nice_address_get_port (&server->addr));
181 /* Send and receive stuff. */
183 GInputVector bufs[7] = {
186 { &buf[1], 0 }, /* should be unused (zero-length) */
189 { &buf[11], 9 }, /* should be unused (message fits in prior buffers) */
190 { &buf[11], 0 }, /* should be unused (zero-length) */
192 NiceInputMessage message = { bufs, G_N_ELEMENTS (bufs), NULL, 0 };
194 /* Initialise the buffers so we can try and catch out-of-bounds accesses. */
195 memset (buf, 0xaa, sizeof (buf));
196 memset (dummy_buf, 0xaa, sizeof (dummy_buf));
198 /* Send and receive. */
199 g_assert_cmpint (nice_socket_send (client, &tmp, 11, "hello-world"), ==, 11);
200 g_assert_cmpuint (nice_socket_recv_messages (server, &message, 1), ==, 1);
201 g_assert_cmpuint (message.length, ==, 11);
203 /* Check all of the things. The sizes should not have been modified. */
204 g_assert_cmpuint (bufs[0].size, ==, 1);
205 g_assert_cmpuint (bufs[1].size, ==, 4);
206 g_assert_cmpuint (bufs[2].size, ==, 0);
207 g_assert_cmpuint (bufs[3].size, ==, 1);
208 g_assert_cmpuint (bufs[4].size, ==, 5);
209 g_assert_cmpuint (bufs[5].size, ==, 9);
210 g_assert_cmpuint (bufs[6].size, ==, 0);
212 g_assert_cmpint (strncmp ((gchar *) buf, "hello-world", 11), ==, 0);
213 g_assert_cmpmem (buf + 11, 9, dummy_buf, 9);
216 nice_socket_free (client);
217 nice_socket_free (server);
220 /* Fill a buffer with deterministic but non-repeated data, so that transmission
221 * and reception corruption is more likely to be detected. */
223 fill_send_buf (guint8 *buf, gsize buf_len, guint seed)
227 for (i = 0; i < buf_len; i++) {
228 buf[i] = '0' + (seed % 10);
233 /* Test receiving multiple messages in a single call. */
235 test_multi_message_recv (guint n_sends, guint n_receives,
236 guint n_bufs_per_message, gsize send_buf_size, gsize recv_buf_size,
237 guint expected_n_received_messages, guint expected_n_sent_messages)
243 server = nice_udp_bsd_socket_new (NULL);
244 g_assert (server != NULL);
246 client = nice_udp_bsd_socket_new (NULL);
247 g_assert (client != NULL);
249 g_assert (nice_address_set_from_string (&tmp, "127.0.0.1"));
250 nice_address_set_port (&tmp, nice_address_get_port (&server->addr));
252 /* Send and receive stuff. */
254 GInputVector *recv_bufs;
255 NiceInputMessage *recv_messages;
256 GOutputVector *send_bufs;
257 NiceOutputMessage *send_messages;
259 guint8 *_expected_recv_buf;
260 gsize expected_recv_buf_len;
262 /* Set up the send buffers. */
263 send_bufs = g_malloc0_n (n_sends * n_bufs_per_message,
264 sizeof (GOutputVector));
265 send_messages = g_malloc0_n (n_sends, sizeof (NiceOutputMessage));
267 for (i = 0; i < n_sends; i++) {
268 for (j = 0; j < n_bufs_per_message; j++) {
269 guint8 *buf = g_slice_alloc (send_buf_size);
271 send_bufs[i * n_bufs_per_message + j].buffer = buf;
272 send_bufs[i * n_bufs_per_message + j].size = send_buf_size;
274 /* Set up the buffer data. */
275 fill_send_buf (buf, send_buf_size, i);
278 send_messages[i].buffers = send_bufs + i * n_bufs_per_message;
279 send_messages[i].n_buffers = n_bufs_per_message;
282 /* Set up the receive buffers. Yay for dynamic tests! */
283 recv_bufs = g_malloc0_n (n_receives * n_bufs_per_message,
284 sizeof (GInputVector));
285 recv_messages = g_malloc0_n (n_receives, sizeof (NiceInputMessage));
287 for (i = 0; i < n_receives; i++) {
288 for (j = 0; j < n_bufs_per_message; j++) {
289 recv_bufs[i * n_bufs_per_message + j].buffer =
290 g_slice_alloc (recv_buf_size);
291 recv_bufs[i * n_bufs_per_message + j].size = recv_buf_size;
293 /* Initialise the buffer to try to catch out-of-bounds accesses. */
294 memset (recv_bufs[i * n_bufs_per_message + j].buffer, 0xaa,
298 recv_messages[i].buffers = recv_bufs + i * n_bufs_per_message;
299 recv_messages[i].n_buffers = n_bufs_per_message;
300 recv_messages[i].from = NULL;
301 recv_messages[i].length = 0;
304 /* Send multiple packets. */
306 nice_socket_send_messages (client, &tmp, send_messages, n_sends), ==,
307 expected_n_sent_messages);
309 /* Receive things. */
311 nice_socket_recv_messages (server, recv_messages, n_receives), ==,
312 expected_n_received_messages);
314 /* Check all of the things. The sizes should not have been modified. */
315 expected_recv_buf_len = recv_buf_size * n_bufs_per_message;
316 _expected_recv_buf = g_slice_alloc (expected_recv_buf_len);
318 for (i = 0; i < expected_n_received_messages; i++) {
319 NiceInputMessage *message = &recv_messages[i];
320 guint8 *expected_recv_buf = _expected_recv_buf;
323 expected_len = MIN (send_buf_size * n_bufs_per_message,
324 expected_recv_buf_len);
325 g_assert_cmpuint (message->length, ==, expected_len);
327 /* Build the expected buffer as a concatenation of the expected values of
328 * all receive buffers in the message. */
329 memset (expected_recv_buf, 0xaa, expected_recv_buf_len);
330 fill_send_buf (expected_recv_buf, expected_len, i);
332 for (j = 0; j < n_bufs_per_message; j++) {
333 g_assert_cmpuint (message->buffers[j].size, ==, recv_buf_size);
335 memcmp (message->buffers[j].buffer, expected_recv_buf,
336 recv_buf_size), ==, 0);
338 expected_recv_buf += recv_buf_size;
342 g_slice_free1 (expected_recv_buf_len, _expected_recv_buf);
344 for (i = 0; i < n_receives; i++) {
345 for (j = 0; j < n_bufs_per_message; j++) {
346 g_slice_free1 (recv_buf_size,
347 recv_bufs[i * n_bufs_per_message + j].buffer);
351 for (i = 0; i < n_sends; i++) {
352 for (j = 0; j < n_bufs_per_message; j++) {
353 g_slice_free1 (send_buf_size,
354 (gpointer) send_bufs[i * n_bufs_per_message + j].buffer);
358 g_free (recv_messages);
360 g_free (send_messages);
364 nice_socket_free (client);
365 nice_socket_free (server);
371 test_socket_initial_properties ();
372 test_socket_address_properties ();
373 test_simple_send_recv ();
374 test_zero_send_recv ();
375 test_multi_buffer_recv ();
377 /* Multi-message testing. Serious business. */
381 guint n_sends; /* messages */
382 guint expected_n_sent_messages;
384 guint n_receives; /* messages */
385 guint expected_n_received_messages;
387 guint n_bufs_per_message;
391 /* same number of sends and receives */
392 { 2, 2, 2, 2, 1, 100, 100 }, /* send 200B, receive 200B */
393 /* more sends than receives */
394 { 4, 4, 2, 2, 2, 100, 77 }, /* send 800B, receive 308B */
395 /* more receives than sends */
396 { 1, 1, 4, 1, 4, 10, 100 }, /* send 40B, receive 1600B */
397 /* small receive buffer (data loss) */
398 { 100, 100, 100, 100, 1, 100, 64 }, /* send 10000B, receive 6400B */
399 /* small receive buffers (data loss) */
400 { 50, 50, 50, 50, 10, 100, 8 }, /* send 50000B, receive 4000B */
403 for (i = 0; i < G_N_ELEMENTS (test_cases); i++) {
404 test_multi_message_recv (test_cases[i].n_sends, test_cases[i].n_receives,
405 test_cases[i].n_bufs_per_message, test_cases[i].send_buf_size,
406 test_cases[i].recv_buf_size,
407 test_cases[i].expected_n_received_messages,
408 test_cases[i].expected_n_sent_messages);