UltraGrid
UltraGrid Low-Latency High-Resolution Transmission System
Loading...
Searching...
No Matches
test_net_udp.c
Go to the documentation of this file.
1/*
2 * FILE: test_net_udp.c
3 * AUTHORS: Colin Perkins
4 *
5 * Copyright (c) 2004 University of Glasgow
6 * Copyright (c) 2000 University College London
7 * All rights reserved.
8 *
9 * Redistribution and use in source and binary forms, with or without
10 * modification, is permitted provided that the following conditions
11 * are met:
12 * 1. Redistributions of source code must retain the above copyright
13 * notice, this list of conditions and the following disclaimer.
14 * 2. Redistributions in binary form must reproduce the above copyright
15 * notice, this list of conditions and the following disclaimer in the
16 * documentation and/or other materials provided with the distribution.
17 * 3. All advertising materials mentioning features or use of this software
18 * must display the following acknowledgement:
19 * This product includes software developed by the Computer Science
20 * Department at University College London
21 * 4. Neither the name of the University nor of the Department may be used
22 * to endorse or promote products derived from this software without
23 * specific prior written permission.
24 * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
25 * ANY EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
26 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
27 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
28 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
29 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
30 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
31 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
32 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
33 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
34 * SUCH DAMAGE.
35 */
36
37#include "config.h"
38#include "config_unix.h"
39#include "config_win32.h"
40
41#include <stdlib.h>
42#ifndef WIN32
43#include <sys/wait.h>
44#endif
45
46#include "debug.h"
47#include "rtp/net_udp.h"
48#include "test_net_udp.h"
49
50#define BUFSIZE 1024
51
52static void randomize(char buf[], int buflen)
53{
54 int i;
55
56 for (i = 0; i < buflen; i++) {
57 buf[i] = rand() & 0xff;
58 }
59}
60
61int test_net_udp(void)
62{
63 struct timeval timeout;
64 socket_udp *s1, *s2;
65 char buf1[BUFSIZE], buf2[BUFSIZE];
66 const char *hname;
67 int rc, i;
68
69#ifndef WIN32
70
71 /* "BSD" bug test that appears in this function uses fork and
72 * exec, that are not present on WIN32. Since the original
73 * bug has not been seen on Win32 it's probably not worth
74 * converting to use CreateProcess() */
75
76 int status_parent, status_child;
77
78#endif /* WIN32 */
79
80 srand(time(NULL));
81
82 /**********************************************************************/
83 /* The first test is to loopback a packet to ourselves... */
84 printf
85 ("Testing UDP/IP networking (IPv4 loopback) ................................ ");
86 fflush(stdout);
87 s1 = udp_init("127.0.0.1", 5004, 5004, 1, 0, false);
88 if (s1 == NULL) {
89 printf("FAIL\n");
90 printf(" Cannot initialize socket\n");
91 return -1;
92 }
93 randomize(buf1, BUFSIZE);
94 randomize(buf2, BUFSIZE);
95 if (udp_send(s1, buf1, BUFSIZE) < 0) {
96 printf("FAIL\n");
97 perror(" Cannot send packet");
98 goto abort_loopback;
99 }
100 timeout.tv_sec = 1;
101 timeout.tv_usec = 0;
102 udp_fd_zero();
103 udp_fd_set(s1);
104 rc = udp_select(&timeout);
105 if (rc < 0) {
106 printf("FAIL\n");
107 perror(" Select failed");
108 goto abort_loopback;
109 }
110 if (rc == 0) {
111 printf("FAIL\n");
112 printf(" No data waiting\n");
113 goto abort_loopback;
114 }
115 if (!udp_fd_isset(s1)) {
116 printf("FAIL\n");
117 printf(" No data on file descriptor\n");
118 goto abort_loopback;
119 }
120 if (udp_recv(s1, buf2, BUFSIZE) < 0) {
121 printf("FAIL\n");
122 perror(" Receive failed");
123 goto abort_loopback;
124 }
125 if (memcmp(buf1, buf2, BUFSIZE) != 0) {
126 printf("FAIL\n");
127 printf(" Buffer corrupt\n");
128 goto abort_loopback;
129 }
130 printf("Ok\n");
131 abort_loopback:
132 hname = udp_host_addr(s1); /* we need this for the unicast test... */
133 udp_exit(s1);
134
135 /**********************************************************************/
136 /* Now we send a packet to ourselves via our real network address... */
137 printf
138 ("Testing UDP/IP networking (IPv4 unicast) ................................. ");
139 fflush(stdout);
140 s1 = udp_init(hname, 5004, 5005, 1, 0, false);
141 if (s1 == NULL) {
142 printf("FAIL\n");
143 printf(" Cannot initialize socket\n");
144 return -1;
145 }
146
147 s2 = udp_init(hname, 5005, 5004, 1, 0, false);
148 if (s2 == NULL) {
149 printf("FAIL\n");
150 printf(" Cannot initialize socket\n");
151 return -1;
152 }
153
154 randomize(buf1, BUFSIZE);
155 randomize(buf2, BUFSIZE);
156 if (udp_send(s1, buf1, BUFSIZE) < 0) {
157 printf("FAIL\n");
158 perror(" Cannot send");
159 goto abort_unicast;
160 }
161 timeout.tv_sec = 1;
162 timeout.tv_usec = 0;
163 udp_fd_zero();
164 udp_fd_set(s1);
165 udp_fd_set(s2);
166 rc = udp_select(&timeout);
167 if (rc < 0) {
168 printf("FAIL\n");
169 perror(" Select failed");
170 goto abort_unicast;
171 }
172 if (rc == 0) {
173 printf("FAIL\n");
174 printf(" No data waiting (no route to %s?)\n", hname);
175 goto abort_unicast;
176 }
177 if (!udp_fd_isset(s2)) {
178 printf("FAIL\n");
179 printf(" No data on file descriptor\n");
180 goto abort_unicast;
181 }
182 if (udp_recv(s2, buf2, BUFSIZE) < 0) {
183 printf("FAIL\n");
184 perror(" Cannot receive");
185 goto abort_unicast;
186 }
187 if (memcmp(buf1, buf2, BUFSIZE) != 0) {
188 printf("FAIL\n");
189 printf(" Buffer corrupt\n");
190 goto abort_unicast;
191 }
192 printf("Ok\n");
193 abort_unicast:
194 udp_exit(s1);
195 udp_exit(s2);
196
197 // skip mcast tests in GitHub CI
198 if (getenv("GITHUB_REPOSITORY")) {
199 printf("Testing UDP/IP networking multicast tests ................................ --\n");
200 return 0;
201 }
202
203 /**********************************************************************/
204 /* Loopback a packet to ourselves via multicast... */
205 printf
206 ("Testing UDP/IP networking (IPv4 multicast) ............................... ");
207 fflush(stdout);
208 s1 = udp_init("224.2.0.1", 5004, 5004, 1, 0, false);
209 if (s1 == NULL) {
210 printf("FAIL\n");
211 printf(" Cannot initialize socket\n");
212 return -1;
213 }
214 randomize(buf1, BUFSIZE);
215 randomize(buf2, BUFSIZE);
216 if (udp_send(s1, buf1, BUFSIZE) < 0) {
217 printf("FAIL\n");
218 perror(" Cannot send");
219 goto abort_multicast;
220 }
221 timeout.tv_sec = 1;
222 timeout.tv_usec = 0;
223 udp_fd_zero();
224 udp_fd_set(s1);
225 rc = udp_select(&timeout);
226 if (rc < 0) {
227 printf("FAIL\n");
228 perror(" Select failed");
229 goto abort_multicast;
230 }
231 if (rc == 0) {
232 printf("FAIL\n");
233 printf(" No data waiting (no multicast loopback route?)\n");
234 goto abort_multicast;
235 }
236 if (!udp_fd_isset(s1)) {
237 printf("FAIL\n");
238 printf(" No data on file descriptor\n");
239 goto abort_multicast;
240 }
241 if (udp_recv(s1, buf2, BUFSIZE) < 0) {
242 printf("FAIL\n");
243 perror(" Cannot receive");
244 goto abort_multicast;
245 }
246 if (memcmp(buf1, buf2, BUFSIZE) != 0) {
247 printf("FAIL\n");
248 printf(" Buffer corrupt\n");
249 goto abort_multicast;
250 }
251 printf("Ok\n");
252 abort_multicast:
253 udp_exit(s1);
254
255 /**********************************************************************/
256 /* Loopback a packet to ourselves via multicast, checking lengths... */
257 printf
258 ("Testing UDP/IP networking (IPv4 length check) ............................ ");
259 fflush(stdout);
260 s1 = udp_init("224.2.0.1", 5004, 5004, 1, 0, false);
261 if (s1 == NULL) {
262 printf("FAIL\n");
263 printf(" Cannot initialize socket\n");
264 return -1;
265 }
266 for (i = 1; i < BUFSIZE; i++) {
267 randomize(buf1, i);
268 randomize(buf2, i);
269 if (udp_send(s1, buf1, i) < 0) {
270 printf("FAIL\n");
271 perror(" Cannot send");
272 goto abort_length;
273 }
274 timeout.tv_sec = 1;
275 timeout.tv_usec = 0;
276 udp_fd_zero();
277 udp_fd_set(s1);
278 rc = udp_select(&timeout);
279 if (rc < 0) {
280 printf("FAIL\n");
281 perror(" Select failed");
282 goto abort_length;
283 }
284 if (rc == 0) {
285 printf("FAIL\n");
286 printf
287 (" No data waiting (no multicast loopback route?)\n");
288 goto abort_length;
289 }
290 if (!udp_fd_isset(s1)) {
291 printf("FAIL\n");
292 printf(" No data on file descriptor\n");
293 goto abort_length;
294 }
295 if (udp_recv(s1, buf2, BUFSIZE) != i) {
296 printf("FAIL\n");
297 perror(" Cannot receive");
298 goto abort_length;
299 }
300 if (memcmp(buf1, buf2, i) != 0) {
301 printf("FAIL\n");
302 printf(" Buffer corrupt\n");
303 goto abort_length;
304 }
305 }
306 printf("Ok\n");
307 abort_length:
308 udp_exit(s1);
309
310#ifdef HAVE_IPv6
311 /**********************************************************************/
312 /* The first test is to loopback a packet to ourselves... */
313 printf
314 ("Testing UDP/IP networking (IPv6 loopback) ................................ ");
315 fflush(stdout);
316 s1 = udp_init("::1", 5004, 5004, 1, 0, false);
317 if (s1 == NULL) {
318 printf("FAIL\n");
319 printf(" Cannot initialize socket\n");
320 return -1;
321 }
322 randomize(buf1, BUFSIZE);
323 randomize(buf2, BUFSIZE);
324 if (udp_send(s1, buf1, BUFSIZE) < 0) {
325 printf("FAIL\n");
326 perror(" Cannot send");
327 goto abort_loopback_ipv6;
328 }
329 timeout.tv_sec = 1;
330 timeout.tv_usec = 0;
331 udp_fd_zero();
332 udp_fd_set(s1);
333 rc = udp_select(&timeout);
334 if (rc < 0) {
335 printf("FAIL\n");
336 perror(" Select failed");
337 goto abort_loopback_ipv6;
338 }
339 if (rc == 0) {
340 printf("FAIL\n");
341 printf(" No data waiting\n");
342 goto abort_loopback_ipv6;
343 }
344 if (!udp_fd_isset(s1)) {
345 printf("FAIL\n");
346 printf(" No data on file descriptor\n");
347 goto abort_loopback_ipv6;
348 }
349 if (udp_recv(s1, buf2, BUFSIZE) < 0) {
350 printf("FAIL\n");
351 perror(" Cannot receive");
352 goto abort_loopback_ipv6;
353 }
354 if (memcmp(buf1, buf2, BUFSIZE) != 0) {
355 printf("FAIL\n");
356 printf(" Buffer corrupt\n");
357 goto abort_loopback_ipv6;
358 }
359 printf("Ok\n");
360 abort_loopback_ipv6:
361 udp_exit(s1);
362
363 /**********************************************************************/
364 /* Loopback a packet to ourselves via multicast. The address is the */
365 /* SAP address, but we use a different port. */
366 printf
367 ("Testing UDP/IP networking (IPv6 multicast) ............................... ");
368 fflush(stdout);
369 const char *iface = NULL;
370#ifdef HAVE_MACOSX
371 iface = "en0";
372#endif
373 s1 = udp_init_if("ff01::2:7ffe", iface, 5004, 5004, 1, 0, false);
374 if (s1 == NULL) {
375 printf("FAIL\n");
376 printf(" Cannot initialize socket\n");
377 return -1;
378 }
379 randomize(buf1, BUFSIZE);
380 randomize(buf2, BUFSIZE);
381 if (udp_send(s1, buf1, BUFSIZE) < 0) {
382 printf("FAIL\n");
383 perror(" Cannot send");
384 goto abort_multicast_ipv6;
385 }
386 timeout.tv_sec = 1;
387 timeout.tv_usec = 0;
388 udp_fd_zero();
389 udp_fd_set(s1);
390 rc = udp_select(&timeout);
391 if (rc < 0) {
392 printf("FAIL\n");
393 perror(" Select failed");
394 goto abort_multicast_ipv6;
395 }
396 if (rc == 0) {
397 printf("FAIL\n");
398 printf(" No data waiting (no multicast loopback route?)\n");
399 goto abort_multicast_ipv6;
400 }
401 if (!udp_fd_isset(s1)) {
402 printf("FAIL\n");
403 printf(" No data on file descriptor\n");
404 goto abort_multicast_ipv6;
405 }
406 if (udp_recv(s1, buf2, BUFSIZE) < 0) {
407 printf("FAIL\n");
408 perror(" Cannot receive");
409 goto abort_multicast_ipv6;
410 }
411 if (memcmp(buf1, buf2, BUFSIZE) != 0) {
412 printf("FAIL\n");
413 printf(" Buffer corrupt\n");
414 goto abort_multicast_ipv6;
415 }
416 hname = udp_host_addr(s1); /* we need this for the unicast test... */
417 printf("Ok\n");
418 abort_multicast_ipv6:
419 udp_exit(s1);
420#else
421 printf
422 ("Testing UDP/IP networking (IPv6 loopback) ................................ --\n");
423 printf
424 ("Testing UDP/IP networking (IPv6 unicast) ................................. --\n");
425 printf
426 ("Testing UDP/IP networking (IPv6 multicast) ............................... --\n");
427#endif
428
429 /**********************************************************************/
430
431#ifdef WIN32
432 printf
433 ("Testing UDP/IP networking (FreeBSD bug) .................................. --\n");
434#else
435 printf
436 ("Testing UDP/IP networking (FreeBSD bug) .................................. ");
437 fflush(stdout);
438 status_parent = 0;
439 randomize(buf1, 64);
440 s1 = udp_init("224.2.0.1", 5004, 5004, 1, 0, false);
441 if (s1 == NULL) {
442 printf("fail (parent): cannot initialize socket\n");
443 return -1;
444 }
445 rc = fork();
446 if (rc == -1) {
447 printf("fail: cannot fork\n");
448 goto abort_bsd;
449 } else if (rc == 0) {
450 /* child */
451 s2 = udp_init("224.2.0.1", 5004, 5004, 1, 0, false);
452 if (s2 == NULL) {
453 printf("FAIL\n");
454 printf(" Child cannot initialize socket\n");
455 exit(0);
456 }
457 if (udp_send(s2, buf1, 64) < 0) {
458 printf("FAIL\n");
459 perror(" Child cannot send");
460 exit(0);
461 }
462 timeout.tv_sec = 10;
463 timeout.tv_usec = 0;
464 udp_fd_zero();
465 udp_fd_set(s2);
466 rc = udp_select(&timeout);
467 if (rc < 0) {
468 printf("FAIL\n");
469 perror(" Child select");
470 exit(0);
471 }
472 if (rc == 0) {
473 printf("FAIL\n");
474 printf
475 (" Child: no data waiting (no multicast loopback route?)\n");
476 exit(0);
477 }
478 if (!udp_fd_isset(s2)) {
479 printf("FAIL\n");
480 printf(" Child: no data on file descriptor\n");
481 exit(0);
482 }
483 rc = udp_recv(s2, buf2, BUFSIZE);
484 if (rc < 0) {
485 printf("FAIL\n");
486 perror(" Child cannot receive");
487 exit(0);
488 }
489 if (rc != 64) {
490 printf("FAIL\n");
491 printf(" Child: read size incorrect (%d != %d)\n", rc,
492 64);
493 exit(0);
494 }
495 if (memcmp(buf1, buf2, 64) != 0) {
496 printf("FAIL\n");
497 printf(" Child: buffer corrupt\n");
498 exit(0);
499 }
500 udp_exit(s2);
501 exit(1);
502 } else {
503 /* parent */
504 timeout.tv_sec = 10;
505 timeout.tv_usec = 0;
506 udp_fd_zero();
507 udp_fd_set(s1);
508 rc = udp_select(&timeout);
509 if (rc < 0) {
510 printf("FAIL\n");
511 perror(" Parent select");
512 goto abort_bsd;
513 }
514 if (rc == 0) {
515 printf("FAIL\n");
516 printf
517 (" Parent: no data waiting (no multicast loopback route?)\n");
518 goto abort_bsd;
519 }
520 if (!udp_fd_isset(s1)) {
521 printf("FAIL\n");
522 printf(" Parent: no data on file descriptor\n");
523 goto abort_bsd;
524 }
525 rc = udp_recv(s1, buf2, BUFSIZE);
526 if (rc < 0) {
527 printf("FAIL\n");
528 perror(" Parent cannot receive");
529 goto abort_bsd;
530 }
531 if (rc != 64) {
532 printf("FAIL\n");
533 printf(" Parent: read size incorrect (%d != %d)\n", rc,
534 64);
535 goto abort_bsd;
536 }
537 if (memcmp(buf1, buf2, 64) != 0) {
538 printf("FAIL\n");
539 printf(" Parent: buffer corrupt\n");
540 goto abort_bsd;
541 }
542 status_parent = 1;
543 }
544 abort_bsd:
545 wait(&status_child);
546 if (status_parent && status_child) {
547 printf("Ok\n");
548 }
549 udp_exit(s1);
550#endif /* WIN32 */
551
552 return 0;
553}
void udp_exit(socket_udp *s)
Definition net_udp.c:974
int udp_recv(socket_udp *s, char *buffer, int buflen)
Definition net_udp.c:1236
socket_udp * udp_init(const char *addr, uint16_t rx_port, uint16_t tx_port, int ttl, int force_ip_version, bool multithreaded)
Definition net_udp.c:681
char * udp_host_addr(socket_udp *s)
Definition net_udp.c:1367
int udp_send(socket_udp *s, char *buffer, int buflen)
Definition net_udp.c:1028
void udp_fd_set(socket_udp *s)
Definition net_udp.c:1304
int udp_fd_isset(socket_udp *s)
Definition net_udp.c:1331
socket_udp * udp_init_if(const char *addr, const char *iface, uint16_t rx_port, uint16_t tx_port, int ttl, int force_ip_version, bool multithreaded)
Definition net_udp.c:789
void udp_fd_zero(void)
Definition net_udp.c:955
int udp_select(struct timeval *timeout)
Definition net_udp.c:1350
int test_net_udp(void)
static void randomize(char buf[], int buflen)
#define BUFSIZE