UltraGrid
UltraGrid Low-Latency High-Resolution Transmission System
Loading...
Searching...
No Matches
net_udp.c
Go to the documentation of this file.
1/*
2 * FILE: net_udp.c
3 * AUTHOR: Colin Perkins
4 * MODIFIED: Orion Hodson & Piers O'Hanlon
5 * David Cassany <david.cassany@i2cat.net>
6 * Gerard Castillo <gerard.castillo@i2cat.net>
7 * Martin Pulec <pulec@cesnet.cz>
8 *
9 * Copyright (c) 2005-2010 Fundació i2CAT, Internet I Innovació Digital a Catalunya
10 * Copyright (c) 2005-2023 CESNET z.s.p.o.
11 * Copyright (c) 1998-2000 University College London
12 * All rights reserved.
13 *
14 * Redistribution and use in source and binary forms, with or without
15 * modification, is permitted provided that the following conditions
16 * are met:
17 * 1. Redistributions of source code must retain the above copyright
18 * notice, this list of conditions and the following disclaimer.
19 * 2. Redistributions in binary form must reproduce the above copyright
20 * notice, this list of conditions and the following disclaimer in the
21 * documentation and/or other materials provided with the distribution.
22 * 3. All advertising materials mentioning features or use of this software
23 * must display the following acknowledgement:
24 * This product includes software developed by the Computer Science
25 * Department at University College London
26 * 4. Neither the name of the University nor of the Department may be used
27 * to endorse or promote products derived from this software without
28 * specific prior written permission.
29 * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
30 * ANY EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
31 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
32 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
33 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
34 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
35 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
36 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
37 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
38 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
39 * SUCH DAMAGE.
40 */
41
42/* If this machine supports IPv6 the symbol HAVE_IPv6 should */
43/* be defined in either config_unix.h or config_win32.h. The */
44/* appropriate system header files should also be included */
45/* by those files. */
46
47#include "config.h"
48#include "config_unix.h"
49#include "config_win32.h"
50
51#include <pthread.h>
52#include <stdalign.h>
53
54#include "debug.h"
55#include "host.h"
56#include "memory.h"
58#include "compat/vsnprintf.h"
59#include "net_udp.h"
60#include "rtp.h"
61#include "utils/list.h"
62#include "utils/macros.h"
63#include "utils/misc.h"
64#include "utils/net.h"
65#include "utils/thread.h"
66#include "utils/windows.h"
67
68#ifdef NEED_ADDRINFO_H
69#include "addrinfo.h"
70#endif
71
72#define DEFAULT_MAX_UDP_READER_QUEUE_LEN (1920/3*8*1080/1152) //< 10-bit FullHD frame divided by 1280 MTU packets (minus headers)
73
74static int resolve_address(socket_udp *s, const char *addr, uint16_t tx_port);
75static void *udp_reader(void *arg);
76
77#define IPv4 4
78#define IPv6 6
79
80#define ERRBUF_SIZE 255
81#define MOD_NAME "[RTP UDP] "
82
83#ifdef WIN2K_IPV6
84const struct in6_addr in6addr_any = { IN6ADDR_ANY_INIT };
85#endif
86
87#ifdef _WIN32
88typedef char *sockopt_t;
89#else
90typedef void *sockopt_t;
91#endif
92
93/* This is pretty nasty but it's the simplest way to get round */
94/* the Detexis bug that means their MUSICA IPv6 stack uses */
95/* IPPROTO_IP instead of IPPROTO_IPV6 in setsockopt calls */
96/* We also need to define in6addr_any */
97#ifdef MUSICA_IPV6
98#define IPPROTO_IPV6 IPPROTO_IP
99struct in6_addr in6addr_any = { IN6ADDR_ANY_INIT };
100
101/* These DEF's are required as MUSICA's winsock6.h causes a clash with some of the
102 * standard ws2tcpip.h definitions (eg struct in_addr6).
103 * Note: winsock6.h defines AF_INET6 as 24 NOT 23 as in winsock2.h - I have left it
104 * set to the MUSICA value as this is used in some of their function calls.
105 */
106//#define AF_INET6 23
107#define IP_MULTICAST_LOOP 11 /*set/get IP multicast loopback */
108#define IP_MULTICAST_IF 9 /* set/get IP multicast i/f */
109#define IP_MULTICAST_TTL 10 /* set/get IP multicast ttl */
110#define IP_MULTICAST_LOOP 11 /*set/get IP multicast loopback */
111#define IP_ADD_MEMBERSHIP 12 /* add an IP group membership */
112#define IP_DROP_MEMBERSHIP 13 /* drop an IP group membership */
113
114#define IN6_IS_ADDR_UNSPECIFIED(a) (((a)->s6_addr32[0] == 0) && \
115 ((a)->s6_addr32[1] == 0) && \
116 ((a)->s6_addr32[2] == 0) && \
117 ((a)->s6_addr32[3] == 0))
118struct ip_mreq {
119 struct in_addr imr_multiaddr; /* IP multicast address of group */
120 struct in_addr imr_interface; /* local IP address of interface */
121};
122#endif
123
124#ifndef INADDR_NONE
125#define INADDR_NONE 0xffffffff
126#endif
127
128struct item {
129 uint8_t *buf;
130 int size;
131 struct sockaddr *src_addr;
132 socklen_t addrlen;
133};
134
135#define ALIGNED_SOCKADDR_STORAGE_OFF ((RTP_MAX_PACKET_LEN + alignof(struct sockaddr_storage) - 1) / alignof(struct sockaddr_storage) * alignof(struct sockaddr_storage))
136#define ALIGNED_ITEM_OFF (((ALIGNED_SOCKADDR_STORAGE_OFF + sizeof(struct sockaddr_storage)) + alignof(struct item) - 1) / alignof(struct item) * alignof(struct item))
137
138/*
139 * Local part of the socket
140 *
141 * Can be shared across multiple RTP sessions.
142 */
144 int mode; /* IPv4 or IPv6 */
148#ifdef _WIN32
149 bool is_wsa_overlapped;
150#endif
151
152 // for multithreaded receiving
153 pthread_t thread_id;
155 unsigned int max_packets;
156 pthread_mutex_t lock;
157 pthread_cond_t boss_cv;
158 pthread_cond_t reader_cv;
159
162};
163
164/*
165 * Complete socket including remote host
166 */
168 struct sockaddr_storage sock;
169 socklen_t sock_len;
170 unsigned int ifindex;
171
173 bool local_is_slave; // whether is the local
174
175#ifdef _WIN32
176 WSAOVERLAPPED *overlapped;
177 WSAEVENT *overlapped_events;
178 void **dispose_udata;
179 bool overlapping_active;
180 int overlapped_max;
181 int overlapped_count;
182#endif
183};
184
185static void udp_clean_async_state(socket_udp *s);
186
187#ifdef _WIN32
188/* Want to use both Winsock 1 and 2 socket options, but since
189* IPv6 support requires Winsock 2 we have to add own backwards
190* compatibility for Winsock 1.
191*/
192#define SETSOCKOPT winsock_versions_setsockopt
193#else
194#define SETSOCKOPT setsockopt
195#endif /* _WIN32 */
196
197#define GETSOCKOPT getsockopt
198
199/*****************************************************************************/
200/* Support functions... */
201/*****************************************************************************/
202
203void socket_error(const char *msg, ...)
204{
205 va_list ap;
206 char buffer[ERRBUF_SIZE] = "";
207
208#ifdef _WIN32
209#define WSERR(x) {#x,x}
210 struct wse {
211 char errname[20];
212 int errno_code;
213 };
214 struct wse ws_errs[] = {
215 WSERR(WSANOTINITIALISED), WSERR(WSAENETDOWN), WSERR(WSAEACCES),
216 WSERR(WSAEINVAL), WSERR(WSAEINTR), WSERR(WSAEINPROGRESS),
217 WSERR(WSAEFAULT), WSERR(WSAENETRESET), WSERR(WSAENOBUFS),
218 WSERR(WSAENOTCONN), WSERR(WSAENOTSOCK), WSERR(WSAEOPNOTSUPP),
219 WSERR(WSAESHUTDOWN), WSERR(WSAEWOULDBLOCK), WSERR(WSAEMSGSIZE),
220 WSERR(WSAEHOSTUNREACH), WSERR(WSAECONNABORTED),
221 WSERR(WSAECONNRESET), WSERR(WSAEADDRINUSE),
222 WSERR(WSAEADDRNOTAVAIL), WSERR(WSAEAFNOSUPPORT),
223 WSERR(WSAEDESTADDRREQ),
224 WSERR(WSAENETUNREACH), WSERR(WSAETIMEDOUT), WSERR(WSAENOPROTOOPT),
225 WSERR(0)
226 };
227
228 int i = 0;
229 int e = WSAGetLastError();
230 if (e == WSAECONNRESET) {
231 return;
232 }
233 while (ws_errs[i].errno_code && ws_errs[i].errno_code != e) {
234 i++;
235 }
236 va_start(ap, msg);
237 _vsnprintf(buffer, sizeof buffer, msg, ap);
238 va_end(ap);
239
240 const char *errname = ws_errs[i].errno_code == 0 ? get_win32_error(e)
241 : ws_errs[i].errname;
242 log_msg(LOG_LEVEL_ERROR, "ERROR: %s, (%d - %s)\n", buffer, e, errname);
243#else
244 char strerror_buf[ERRBUF_SIZE] = "unknown";
245 va_start(ap, msg);
246 vsnprintf(buffer, sizeof buffer, msg, ap);
247 va_end(ap);
248#if ! defined _POSIX_C_SOURCE || (_POSIX_C_SOURCE >= 200112L && ! _GNU_SOURCE)
249 strerror_r(errno, strerror_buf, sizeof strerror_buf); // XSI version
250 log_msg(LOG_LEVEL_ERROR, "%s: %s\n", buffer, strerror_buf);
251#else // GNU strerror_r version
252 log_msg(LOG_LEVEL_ERROR, "%s: %s\n", buffer, strerror_r(errno, strerror_buf, sizeof strerror_buf));
253#endif
254#endif
255}
256
257#ifdef _WIN32
258#define socket_herror socket_error
259#else
260static void socket_herror(const char *msg, ...)
261{
262 va_list ap;
263 char buffer[255];
264 uint32_t blen = sizeof(buffer) / sizeof(buffer[0]);
265
266 va_start(ap, msg);
267 vsnprintf(buffer, blen, msg, ap);
268 va_end(ap);
269 herror(buffer);
270}
271#endif
272
273#ifdef _WIN32
274/* ws2tcpip.h defines these constants with different values from
275* winsock.h so files that use winsock 2 values but try to use
276* winsock 1 fail. So what was the motivation in changing the
277* constants ?
278*/
279#define WS1_IP_MULTICAST_IF 2 /* set/get IP multicast interface */
280#define WS1_IP_MULTICAST_TTL 3 /* set/get IP multicast timetolive */
281#define WS1_IP_MULTICAST_LOOP 4 /* set/get IP multicast loopback */
282#define WS1_IP_ADD_MEMBERSHIP 5 /* add an IP group membership */
283#define WS1_IP_DROP_MEMBERSHIP 6 /* drop an IP group membership */
284
285/* winsock_versions_setsockopt tries 1 winsock version of option
286* optname and then winsock 2 version if that failed.
287*/
288
289static int
290winsock_versions_setsockopt(SOCKET s, int level, int optname,
291 const char FAR * optval, int optlen)
292{
293 int success = -1;
294 switch (optname) {
295 case IP_MULTICAST_IF:
296 success =
297 setsockopt(s, level, WS1_IP_MULTICAST_IF, optval, optlen);
298 break;
299 case IP_MULTICAST_TTL:
300 success =
301 setsockopt(s, level, WS1_IP_MULTICAST_TTL, optval, optlen);
302 break;
303 case IP_MULTICAST_LOOP:
304 success =
305 setsockopt(s, level, WS1_IP_MULTICAST_LOOP, optval, optlen);
306 break;
307 case IP_ADD_MEMBERSHIP:
308 success =
309 setsockopt(s, level, WS1_IP_ADD_MEMBERSHIP, optval, optlen);
310 break;
311 case IP_DROP_MEMBERSHIP:
312 success =
313 setsockopt(s, level, WS1_IP_DROP_MEMBERSHIP, optval,
314 optlen);
315 break;
316 }
317 if (success != -1) {
318 return success;
319 }
320 return setsockopt(s, level, optname, optval, optlen);
321}
322#endif
323
324#ifdef NEED_INET_ATON
325#ifdef NEED_INET_ATON_STATIC
326static
327#endif
328int inet_aton(const char *name, struct in_addr *addr);
329
330int inet_aton(const char *name, struct in_addr *addr)
331{
332 addr->s_addr = inet_addr(name);
333 return (addr->s_addr != (in_addr_t) INADDR_NONE);
334}
335#endif
336
337#ifdef NEED_IN6_IS_ADDR_MULTICAST
338#define IN6_IS_ADDR_MULTICAST(addr) ((addr)->s6_addr[0] == 0xffU)
339#endif
340
341#if defined(NEED_IN6_IS_ADDR_UNSPECIFIED) && defined(MUSICA_IPV6)
342#define IN6_IS_ADDR_UNSPECIFIED(addr) IS_UNSPEC_IN6_ADDR(*addr)
343#endif
344
345/*****************************************************************************/
346/* IPv4 specific functions... */
347/*****************************************************************************/
348
349static bool udp_addr_valid4(const char *dst)
350{
351 struct in_addr addr4;
352 struct hostent *h;
353
354 if (inet_pton(AF_INET, dst, &addr4)) {
355 return true;
356 }
357
358 h = gethostbyname(dst);
359 if (h != NULL) {
360 return true;
361 }
362 socket_herror("Can't resolve IP address for %s", dst);
363
364 return false;
365}
366
367static bool udp_join_mcast_grp4(unsigned long addr, int rx_fd, int tx_fd, int ttl, unsigned int ifindex)
368{
369 if (IN_MULTICAST(ntohl(addr))) {
370#ifndef _WIN32
371 char loop = 1;
372#endif
373 struct ip_mreq imr;
374
375 imr.imr_multiaddr.s_addr = addr;
376 imr.imr_interface.s_addr = ifindex;
377
378 if (SETSOCKOPT
379 (rx_fd, IPPROTO_IP, IP_ADD_MEMBERSHIP, (char *)&imr,
380 sizeof(struct ip_mreq)) != 0) {
381 socket_error("setsockopt IP_ADD_MEMBERSHIP");
382 return false;
383 }
384#ifndef _WIN32
385 if (SETSOCKOPT
386 (tx_fd, IPPROTO_IP, IP_MULTICAST_LOOP, &loop,
387 sizeof(loop)) != 0) {
388 socket_error("setsockopt IP_MULTICAST_LOOP");
389 return false;
390 }
391#endif
392 if (ttl > -1) {
393 if (SETSOCKOPT
394 (tx_fd, IPPROTO_IP, IP_MULTICAST_TTL, (char *)&ttl,
395 sizeof(ttl)) != 0) {
396 socket_error("setsockopt IP_MULTICAST_TTL");
397 return false;
398 }
399 } else {
400 log_msg(LOG_LEVEL_WARNING, "Using IPv4 multicast but not setting TTL.\n");
401 }
402 if (SETSOCKOPT
403 (tx_fd, IPPROTO_IP, IP_MULTICAST_IF,
404 (char *)&ifindex, sizeof(ifindex)) != 0) {
405 socket_error("setsockopt IP_MULTICAST_IF");
406 return false;
407 }
408 }
409 return true;
410}
411
412static void udp_leave_mcast_grp4(unsigned long addr, int fd)
413{
414 if (IN_MULTICAST(ntohl(addr))) {
415 struct ip_mreq imr;
416 imr.imr_multiaddr.s_addr = addr;
417 imr.imr_interface.s_addr = INADDR_ANY;
418 if (SETSOCKOPT
419 (fd, IPPROTO_IP, IP_DROP_MEMBERSHIP, (char *)&imr,
420 sizeof(struct ip_mreq)) != 0) {
421 socket_error("setsockopt IP_DROP_MEMBERSHIP");
422 }
423 debug_msg("Dropped membership of multicast group\n");
424 }
425}
426
427static char *udp_host_addr4(void)
428{
429 char *hname = (char *) calloc(MAXHOSTNAMELEN + 1, 1);
430 struct hostent *hent;
431 struct in_addr iaddr;
432
433 if (gethostname(hname, MAXHOSTNAMELEN) != 0) {
434 debug_msg("Cannot get hostname!");
435 abort();
436 }
437 hent = gethostbyname(hname);
438 if (hent == NULL) {
439 socket_herror("Can't resolve IP address for %s", hname);
440 free(hname);
441 return NULL;
442 }
443 assert(hent->h_addrtype == AF_INET);
444 memcpy(&iaddr.s_addr, hent->h_addr, sizeof(iaddr.s_addr));
445 strncpy(hname, inet_ntoa(iaddr), MAXHOSTNAMELEN);
446 return hname;
447}
448
449/*****************************************************************************/
450/* IPv6 specific functions... */
451/*****************************************************************************/
452
453static bool udp_addr_valid6(const char *dst)
454{
455#ifdef HAVE_IPv6
456 struct in6_addr addr6;
457 switch (inet_pton(AF_INET6, dst, &addr6)) {
458 case 1:
459 return true;
460 break;
461 case 0:
462 return false;
463 break;
464 case -1:
465 debug_msg("inet_pton failed\n");
466 errno = 0;
467 }
468#endif /* HAVE_IPv6 */
469 UNUSED(dst);
470 return false;
471}
472
473static bool udp_join_mcast_grp6(struct in6_addr sin6_addr, int rx_fd, int tx_fd, int ttl, unsigned int ifindex)
474{
475#ifdef HAVE_IPv6
476 if (IN6_IS_ADDR_MULTICAST(&sin6_addr)) {
477 unsigned int loop = 1;
478 struct ipv6_mreq imr;
479#ifdef MUSICA_IPV6
480 imr.i6mr_interface = 1;
481 imr.i6mr_multiaddr = sin6_addr;
482#else
483 imr.ipv6mr_multiaddr = sin6_addr;
484 imr.ipv6mr_interface = ifindex;
485#endif
486
487 if (SETSOCKOPT
488 (rx_fd, IPPROTO_IPV6, IPV6_ADD_MEMBERSHIP, (char *)&imr,
489 sizeof(struct ipv6_mreq)) != 0) {
490 socket_error("setsockopt IPV6_ADD_MEMBERSHIP");
491 return false;
492 }
493
494 if (SETSOCKOPT
495 (tx_fd, IPPROTO_IPV6, IPV6_MULTICAST_LOOP, (char *)&loop,
496 sizeof(loop)) != 0) {
497 socket_error("setsockopt IPV6_MULTICAST_LOOP");
498 return false;
499 }
500 if (ttl > -1) {
501 if (SETSOCKOPT
502 (tx_fd, IPPROTO_IPV6, IPV6_MULTICAST_HOPS, (char *)&ttl,
503 sizeof(ttl)) != 0) {
504 socket_error("setsockopt IPV6_MULTICAST_HOPS");
505 return false;
506 } else {
507 log_msg(LOG_LEVEL_WARNING, "Using IPv6 multicast but not setting TTL.\n");
508 }
509 }
510 if (SETSOCKOPT(tx_fd, IPPROTO_IPV6, IPV6_MULTICAST_IF,
511 (char *)&ifindex, sizeof(ifindex)) != 0) {
512 socket_error("setsockopt IPV6_MULTICAST_IF");
513 return false;
514 }
515 }
516
517 return true;
518#endif
519}
520
521static void udp_leave_mcast_grp6(struct in6_addr sin6_addr, int fd, unsigned int ifindex)
522{
523#ifdef HAVE_IPv6
524 if (IN6_IS_ADDR_MULTICAST(&sin6_addr)) {
525 struct ipv6_mreq imr;
526#ifdef MUSICA_IPV6
527 imr.i6mr_interface = 1;
528 imr.i6mr_multiaddr = sin6_addr;
529#else
530 imr.ipv6mr_multiaddr = sin6_addr;
531 imr.ipv6mr_interface = ifindex;
532#endif
533
534 if (SETSOCKOPT
535 (fd, IPPROTO_IPV6, IPV6_DROP_MEMBERSHIP, (char *)&imr,
536 sizeof(struct ipv6_mreq)) != 0) {
537 socket_error("setsockopt IPV6_DROP_MEMBERSHIP");
538 }
539 }
540#else
541 UNUSED(s);
542#endif /* HAVE_IPv6 */
543}
544
545static char *udp_host_addr6(socket_udp * s)
546{
547#ifdef HAVE_IPv6
548 char *hname = (char *) calloc(MAXHOSTNAMELEN + 1, 1);
549 int gai_err, newsock;
550 struct addrinfo hints, *ai;
551 struct sockaddr_in6 local, addr6, bound;
552 socklen_t len = sizeof(local);
553 int result = 0;
554
555 newsock = socket(AF_INET6, SOCK_DGRAM, 0);
556 if (newsock == -1) {
557 socket_error("socket");
558 free(hname);
559 return NULL;
560 }
561 int ipv6only = 0;
562 if (SETSOCKOPT(newsock, IPPROTO_IPV6, IPV6_V6ONLY,
563 (char *) &ipv6only,
564 sizeof(ipv6only)) != 0) {
565 socket_error("newsock setsockopt IPV6_V6ONLY");
566 }
567 memset((char *)&addr6, 0, len);
568 addr6.sin6_family = AF_INET6;
569#ifdef HAVE_SIN6_LEN
570 addr6.sin6_len = len;
571#endif
572 addr6.sin6_addr = in6addr_any;
573 result = bind(newsock, (struct sockaddr *)&addr6, len);
574 if (result != 0) {
575 socket_error("Cannot bind");
576 }
577 addr6.sin6_addr = ((struct sockaddr_in6 *)&s->sock)->sin6_addr;
578 len = sizeof bound;
579 if (getsockname(s->local->rx_fd, (struct sockaddr *)&bound, &len) == -1) {
580 socket_error("getsockname");
581 addr6.sin6_port = 0;
582 } else {
583 addr6.sin6_port = bound.sin6_port;
584 }
585 addr6.sin6_scope_id = ((struct sockaddr_in6 *)&s->sock)->sin6_scope_id;
586 len = sizeof addr6;
587 result = connect(newsock, (struct sockaddr *)&addr6, len);
588 if (result != 0) {
589 socket_error("connect");
590 }
591
592 memset((char *)&local, 0, len);
593 if ((result =
594 getsockname(newsock, (struct sockaddr *)&local, &len)) < 0) {
595 local.sin6_addr = in6addr_any;
596 local.sin6_port = 0;
597 error_msg("getsockname failed\n");
598 }
599
600 CLOSESOCKET(newsock);
601
602 if (IN6_IS_ADDR_UNSPECIFIED(&local.sin6_addr)
603 || IN6_IS_ADDR_MULTICAST(&local.sin6_addr)) {
604 if (gethostname(hname, MAXHOSTNAMELEN) != 0) {
605 error_msg("gethostname failed\n");
606 free(hname);
607 return NULL;
608 }
609
610 hints.ai_protocol = 0;
611 hints.ai_flags = 0;
612 hints.ai_family = AF_INET6;
613 hints.ai_socktype = SOCK_DGRAM;
614 hints.ai_addrlen = 0;
615 hints.ai_canonname = NULL;
616 hints.ai_addr = NULL;
617 hints.ai_next = NULL;
618
619 if ((gai_err = getaddrinfo(hname, NULL, &hints, &ai))) {
620 error_msg(MOD_NAME "udp_host_addr6: getaddrinfo: %s: %s\n", hname,
621 ug_gai_strerror(gai_err));
622 free(hname);
623 return NULL;
624 }
625
626 struct sockaddr_in6 *addr6 = (struct sockaddr_in6 *)(void *)
627 ai->ai_addr;
628 if (inet_ntop
629 (AF_INET6,
630 &(addr6->sin6_addr),
631 hname, MAXHOSTNAMELEN) == NULL) {
632 error_msg("inet_ntop: %s: \n", hname);
633 freeaddrinfo(ai);
634 free(hname);
635 return NULL;
636 }
637 freeaddrinfo(ai);
638 return hname;
639 }
640 if (inet_ntop(AF_INET6, &local.sin6_addr, hname, MAXHOSTNAMELEN) ==
641 NULL) {
642 error_msg("inet_ntop: %s: \n", hname);
643 free(hname);
644 return NULL;
645 }
646 return hname;
647#else /* HAVE_IPv6 */
648 UNUSED(s);
649 return strdup("::"); /* The unspecified address... */
650#endif /* HAVE_IPv6 */
651}
652
653/*****************************************************************************/
654/* Generic functions, which call the appropriate protocol specific routines. */
655/*****************************************************************************/
656
664bool udp_addr_valid(const char *addr)
665{
666 return udp_addr_valid4(addr) || udp_addr_valid6(addr);
667}
668
681socket_udp *udp_init(const char *addr, uint16_t rx_port, uint16_t tx_port,
682 int ttl, int force_ip_version, bool multithreaded)
683{
684 return udp_init_if(addr, NULL, rx_port, tx_port, ttl, force_ip_version, multithreaded);
685}
686
688static bool set_sock_opts_and_bind(fd_t fd, bool ipv6, uint16_t rx_port, int ttl) {
689 struct sockaddr_storage s_in;
690 memset(&s_in, 0, sizeof s_in);
691 socklen_t sin_len;
692 int reuse = 1;
693 int ipv6only = 0;
694
695 if (ipv6) {
696 if (SETSOCKOPT(fd, IPPROTO_IPV6, IPV6_V6ONLY, (char *)&ipv6only,
697 sizeof(ipv6only)) != 0) {
698 socket_error("setsockopt IPV6_V6ONLY");
699 return false;
700 }
701 if (ttl > 0 && SETSOCKOPT(fd, IPPROTO_IPV6, IPV6_UNICAST_HOPS, (char *)&ttl,
702 sizeof(ttl)) != 0) {
703 socket_error("setsockopt IPV6_UNICAST_HOPS");
704 return false;
705 }
706 }
707 // For macs, this is set only for IPv4 socket (not IPv4-mapped IPv6), on the other
708 // hand, Linux+Win requires this setting for IPv4-mapped IPv6 sockets for the TTL work.
709 if (ttl > 0 &&
710#ifdef __APPLE__
711 !ipv6 &&
712#endif
713 SETSOCKOPT(fd, IPPROTO_IP, IP_TTL, (char *)&ttl,
714 sizeof(ttl)) != 0) {
715 socket_error("setsockopt IP_TTL");
716 return false;
717 }
718#ifdef SO_REUSEPORT
719 if (SETSOCKOPT
720 (fd, SOL_SOCKET, SO_REUSEPORT, (int *)&reuse,
721 sizeof(reuse)) != 0) {
722 socket_error("setsockopt SO_REUSEPORT");
724 }
725#endif
726 if (SETSOCKOPT
727 (fd, SOL_SOCKET, SO_REUSEADDR, (char *)&reuse,
728 sizeof(reuse)) != 0) {
729 socket_error("setsockopt SO_REUSEADDR");
731 }
732
733 if (!ipv6) {
734 struct sockaddr_in *s_in4 = (struct sockaddr_in *) &s_in;
735 s_in4->sin_family = AF_INET;
736 s_in4->sin_addr.s_addr = htonl(INADDR_ANY);
737 s_in4->sin_port = htons(rx_port);
738 sin_len = sizeof(struct sockaddr_in);
739 } else {
740#ifdef HAVE_IPv6
741 struct sockaddr_in6 *s_in6 = (struct sockaddr_in6 *) &s_in;
742 s_in6->sin6_family = AF_INET6;
743 s_in6->sin6_addr = in6addr_any;
744 s_in6->sin6_port = htons(rx_port);
745#ifdef HAVE_SIN6_LEN
746 s_in6->sin6_len = sizeof(struct sockaddr_in6);
747#endif
748 sin_len = sizeof(struct sockaddr_in6);
749#endif
750 }
751 if (bind(fd, (struct sockaddr *)&s_in, sin_len) != 0) {
752 socket_error("bind");
753#ifdef _WIN32
754 log_msg(LOG_LEVEL_ERROR, "Check if there is no service running on UDP port %d. ", rx_port);
755 if (rx_port == 5004 || rx_port == 5005)
756 log_msg(LOG_LEVEL_ERROR, "Windows Media Services is usually a good candidate to check and disable.\n");
757#endif
758 return false;
759 }
760
761 return true;
762}
763
764ADD_TO_PARAM("udp-queue-len",
765 "* udp-queue-len=<l>\n"
766 " Use different queue size than default DEFAULT_MAX_UDP_READER_QUEUE_LEN\n");
767#ifdef _WIN32
768ADD_TO_PARAM("udp-disable-multi-socket",
769 "* udp-disable-multi-socket\n"
770 " Disable separate sockets for RX and TX (Win only). Separated RX/TX is a workaround\n"
771 " to some locking issues (thr. in recv() while no data are received and concurr. send()).\n");
772#endif
789socket_udp *udp_init_if(const char *addr, const char *iface, uint16_t rx_port,
790 uint16_t tx_port, int ttl, int force_ip_version, bool multithreaded)
791{
792 int ret;
793 socket_udp *s = (socket_udp *) calloc(1, sizeof *s);
794 s->local = (struct socket_udp_local*) calloc(1, sizeof(*s->local));
796 s->local->rx_fd =
798 pthread_mutex_init(&s->local->lock, NULL);
799 pthread_cond_init(&s->local->boss_cv, NULL);
800 pthread_cond_init(&s->local->reader_cv, NULL);
801
802 assert(force_ip_version == 0 || force_ip_version == 4 || force_ip_version == 6);
803 s->local->mode = force_ip_version;
804 if (s->local->mode == 0 && is_addr_multicast(addr)) {
805 s->local->mode = strchr(addr, '.') != NULL ? 4 : 6;
806 }
807
808 if ((ret = resolve_address(s, addr, tx_port)) != 0) {
809 log_msg(LOG_LEVEL_ERROR, MOD_NAME "Can't resolve IP address for %s: %s\n", addr,
810 ug_gai_strerror(ret));
811 goto error;
812 }
813 if (iface != NULL) {
814 if ((s->ifindex = if_nametoindex(iface)) == 0) {
815 error_msg("Illegal interface specification\n");
816 goto error;
817 }
818 } else {
819 s->ifindex = 0;
820 }
821#ifdef _WIN32
822 if (!is_host_loopback(addr)) {
823 s->local->is_wsa_overlapped = true;
824 }
825
826 s->local->rx_fd = WSASocket(s->sock.ss_family, SOCK_DGRAM, IPPROTO_UDP, NULL, 0, s->local->is_wsa_overlapped ? WSA_FLAG_OVERLAPPED : 0);
827 if (get_commandline_param("udp-disable-multi-socket")) {
828 s->local->tx_fd = s->local->rx_fd;
829 } else {
830 s->local->tx_fd = WSASocket(s->sock.ss_family, SOCK_DGRAM, IPPROTO_UDP, NULL, 0, s->local->is_wsa_overlapped ? WSA_FLAG_OVERLAPPED : 0);
831 }
832#else
833 s->local->rx_fd =
834 s->local->tx_fd = socket(s->sock.ss_family, SOCK_DGRAM, 0);
835#endif
836 if (s->local->rx_fd == INVALID_SOCKET ||
837 s->local->tx_fd == INVALID_SOCKET) {
838 socket_error("Unable to initialize socket");
839 goto error;
840 }
841 // Set properties and bind
842 // The order here is important if using separate socket for RX and TX - in
843 // MSW, first bound socket receives data, in Linux (with Wine) the
844 // second.
845 if (!set_sock_opts_and_bind(s->local->rx_fd, s->local->mode == IPv6, rx_port, ttl) ||
846 (s->local->rx_fd != s->local->tx_fd && !set_sock_opts_and_bind(s->local->tx_fd, s->local->mode == IPv6, rx_port, ttl))) {
847 goto error;
848 }
849 if (is_wine()) {
850 SWAP(s->local->rx_fd, s->local->tx_fd);
851 }
852
853 // if we do not set tx port, fake that is the same as we are bound to
854 if (tx_port == 0) {
855 struct sockaddr_storage sin;
856 socklen_t addrlen = sizeof(sin);
857 if (getsockname(s->local->rx_fd, (struct sockaddr *)&sin, &addrlen) == 0 &&
858 sin.ss_family == s->sock.ss_family) {
859 if (s->local->mode == IPv4) {
860 struct sockaddr_in *s_in4 = (struct sockaddr_in *) &sin;
861 tx_port = ntohs(s_in4->sin_port);
862 ((struct sockaddr_in *) &s->sock)->sin_port = s_in4->sin_port;
863 } else if (s->local->mode == IPv6) {
864#ifdef HAVE_IPv6
865 struct sockaddr_in6 *s_in6 = (struct sockaddr_in6 *) &sin;
866 tx_port = ntohs(s_in6->sin6_port);
867 ((struct sockaddr_in6 *) &s->sock)->sin6_port = s_in6->sin6_port;
868#endif
869 } else {
870 abort();
871 }
872 }
873 }
874
875 switch (s->local->mode) {
876 case IPv4:
877 if (!udp_join_mcast_grp4(((struct sockaddr_in *)&s->sock)->sin_addr.s_addr, s->local->rx_fd, s->local->tx_fd, ttl, s->ifindex)) {
878 goto error;
879 }
880 break;
881 case IPv6:
882 if (!udp_join_mcast_grp6(((struct sockaddr_in6 *)&s->sock)->sin6_addr, s->local->rx_fd, s->local->tx_fd, ttl, s->ifindex)) {
883 goto error;
884 }
885 break;
886 default:
887 abort();
888 }
889
890 s->local->multithreaded = multithreaded;
891 if (multithreaded) {
892 if (!get_commandline_param("udp-queue-len")) {
894 } else {
895 s->local->max_packets = atoi(get_commandline_param("udp-queue-len"));
896 }
898 pthread_create(&s->local->thread_id, NULL, udp_reader, s);
899 }
900
901 return s;
902
903error:
904 udp_exit(s);
905 return NULL;
906}
907
910bool
912{
913 struct in6_addr ipv6_blackhole_server_mode;
914 inet_pton(AF_INET6, IN6_BLACKHOLE_SERVER_MODE_STR,
915 &ipv6_blackhole_server_mode);
916 return s->sock.ss_family == AF_INET6 &&
917 memcmp(&((struct sockaddr_in6 *) &s->sock)->sin6_addr,
918 &ipv6_blackhole_server_mode,
919 sizeof ipv6_blackhole_server_mode) == 0;
920}
921
922void udp_set_receiver(socket_udp *s, struct sockaddr *sa, socklen_t len) {
923 memcpy(&s->sock, sa, len);
924 s->sock_len = len;
925}
926
927socket_udp *udp_init_with_local(struct socket_udp_local *l, struct sockaddr *sa, socklen_t len)
928{
929 if ((sa->sa_family == AF_INET && l->mode != IPv4) ||
930 (sa->sa_family == AF_INET6 && l->mode != IPv6) ||
931 (sa->sa_family != AF_INET && sa->sa_family != AF_INET6)) {
932 log_msg(LOG_LEVEL_ERROR, "[NET UDP] udp_init_with_local: Protocol mismatch!\n");
933 return NULL;
934 }
935
936 struct _socket_udp *s = (socket_udp *) calloc(1, sizeof *s);
937 s->local = l;
938 s->local_is_slave = true;
939
940 udp_set_receiver(s, sa, len);
941
942 return s;
943}
944
945
946static fd_set rfd;
948
955void udp_fd_zero(void)
956{
957 FD_ZERO(&rfd);
958 max_fd = 0;
959}
960
961void udp_fd_zero_r(struct udp_fd_r *fd_struct)
962{
963 FD_ZERO(&fd_struct->rfd);
964 fd_struct->max_fd = 0;
965}
966
975{
976 if (s == NULL) {
977 return;
978 }
979 switch (s->local->mode) {
980 case IPv4:
981 udp_leave_mcast_grp4(((struct sockaddr_in *)&s->sock)->sin_addr.s_addr, s->local->rx_fd);
982 break;
983 case IPv6:
984 udp_leave_mcast_grp6(((struct sockaddr_in6 *)&s->sock)->sin6_addr, s->local->rx_fd, s->ifindex);
985 break;
986 }
987
988 if (!s->local_is_slave) {
989 if (s->local->multithreaded) {
990 char c = 0;
991 int ret = PLATFORM_PIPE_WRITE(s->local->should_exit_fd[1], &c, 1);
992 assert (ret == 1);
993 s->local->should_exit = true;
994 pthread_cond_signal(&s->local->reader_cv);
995 pthread_join(s->local->thread_id, NULL);
996 while (simple_linked_list_size(s->local->packets) > 0) {
997 struct item *item = (struct item *) simple_linked_list_pop(s->local->packets);
998 free(item->buf);
999 }
1001 }
1002 CLOSESOCKET(s->local->rx_fd);
1003 if (s->local->tx_fd != s->local->rx_fd) {
1004 CLOSESOCKET(s->local->tx_fd);
1005 }
1007 pthread_mutex_destroy(&s->local->lock);
1008 pthread_cond_destroy(&s->local->boss_cv);
1009 pthread_cond_destroy(&s->local->reader_cv);
1010 free(s->local);
1011 }
1012
1014
1015 free(s);
1016}
1017
1028int udp_send(socket_udp * s, char *buffer, int buflen)
1029{
1030 assert(s != NULL);
1031 assert(buffer != NULL);
1032 assert(buflen > 0);
1033
1034 return sendto(s->local->tx_fd, buffer, buflen, 0, (struct sockaddr *)&s->sock,
1035 s->sock_len);
1036}
1037
1038int udp_sendto(socket_udp * s, char *buffer, int buflen, struct sockaddr *dst_addr, socklen_t addrlen)
1039{
1040 return sendto(s->local->tx_fd, buffer, buflen, 0, dst_addr, addrlen);
1041}
1042
1043#ifdef _WIN32
1044int udp_sendv(socket_udp * s, LPWSABUF vector, int count, void *d)
1045{
1046 assert(s != NULL);
1047
1048 assert(!s->overlapping_active || s->overlapped_count < s->overlapped_max);
1049
1050 DWORD bytesSent;
1051 int ret = WSASendTo(s->local->tx_fd, vector, count, &bytesSent, 0,
1052 (struct sockaddr *) &s->sock,
1053 s->sock_len, s->overlapping_active ? &s->overlapped[s->overlapped_count] : NULL, NULL);
1054 if (s->overlapping_active) {
1055 s->dispose_udata[s->overlapped_count] = d;
1056 } else {
1057 free(d);
1058 }
1059 s->overlapped_count++;
1060 if (ret == 0 || WSAGetLastError() == WSA_IO_PENDING)
1061 return 0;
1062 else {
1063 return ret;
1064 }
1065}
1066#else
1067int udp_sendv(socket_udp * s, struct iovec *vector, int count, void *d)
1068{
1069 struct msghdr msg;
1070
1071 assert(s != NULL);
1072
1073 msg.msg_name = (void *) & s->sock;
1074 msg.msg_namelen = s->sock_len;
1075 msg.msg_iov = vector;
1076 msg.msg_iovlen = count;
1077 /* Linux needs these... solaris does something different... */
1078 msg.msg_control = 0;
1079 msg.msg_controllen = 0;
1080 msg.msg_flags = 0;
1081
1082 int ret = sendmsg(s->local->tx_fd, &msg, 0);
1083 free(d);
1084 return ret;
1085}
1086#endif // _WIN32
1087
1092static void *udp_reader(void *arg)
1093{
1094 set_thread_name(__func__);
1095 socket_udp *s = (socket_udp *) arg;
1096
1097 while (1) {
1098 fd_set fds;
1099 FD_ZERO(&fds);
1100 FD_SET(s->local->rx_fd, &fds);
1101 FD_SET(s->local->should_exit_fd[0], &fds);
1102 int nfds = MAX(s->local->rx_fd, s->local->should_exit_fd[0]) + 1;
1103
1104 int rc = select(nfds, &fds, NULL, NULL, NULL);
1105 if (rc <= 0) {
1106 socket_error("select");
1107 continue;
1108 }
1109 if (FD_ISSET(s->local->should_exit_fd[0], &fds)) {
1110 break;
1111 }
1112 uint8_t *packet = (uint8_t *) malloc(ALIGNED_ITEM_OFF + sizeof(struct item));
1113 uint8_t *buffer = ((uint8_t *) packet) + RTP_PACKET_HEADER_SIZE;
1114 struct sockaddr *src_addr = (struct sockaddr *)(void *)(packet + ALIGNED_SOCKADDR_STORAGE_OFF);
1115 socklen_t addrlen = sizeof(struct sockaddr_storage);
1116 int size = recvfrom(s->local->rx_fd, (char *) buffer,
1118 0, src_addr, &addrlen);
1119
1120 if (size <= 0) {
1125 socket_error("recvfrom");
1126 free(packet);
1127 continue;
1128 }
1129
1130 pthread_mutex_lock(&s->local->lock);
1131 while (simple_linked_list_size(s->local->packets) >= (int) s->local->max_packets && !s->local->should_exit) {
1132 pthread_cond_wait(&s->local->reader_cv, &s->local->lock);
1133 }
1134 if (s->local->should_exit) {
1135 free(packet);
1136 pthread_mutex_unlock(&s->local->lock);
1137 break;
1138 }
1139
1140 struct item *i = (struct item *)(void *)(packet + ALIGNED_ITEM_OFF);
1141 *i = (struct item){packet, size, src_addr, addrlen};
1143
1144 pthread_mutex_unlock(&s->local->lock);
1145 pthread_cond_signal(&s->local->boss_cv);
1146 }
1147
1149
1150 return NULL;
1151}
1152
1153static int udp_do_recv(socket_udp * s, char *buffer, int buflen, int flags, struct sockaddr *src_addr, socklen_t *addrlen)
1154{
1155 /* Reads data into the buffer, returning the number of bytes read. */
1156 /* If no data is available, this returns the value zero immediately. */
1157 /* Note: since we don't care about the source address of the packet */
1158 /* we receive, this function becomes protocol independent. */
1159 int len;
1160
1161 assert(buffer != NULL);
1162 assert(buflen > 0);
1163
1164 len = recvfrom(s->local->rx_fd, buffer, buflen, flags, src_addr, addrlen);
1165 if (len > 0) {
1166 return len;
1167 }
1168 if (errno != ECONNREFUSED) {
1169 socket_error("recvfrom");
1170 }
1171 return 0;
1172}
1173
1185int udp_peek(socket_udp * s, char *buffer, int buflen)
1186{
1187 return udp_do_recv(s, buffer, buflen, MSG_PEEK, 0, 0);
1188}
1189
1197bool udp_not_empty(socket_udp * s, struct timeval *timeout)
1198{
1199 assert(s->local->multithreaded);
1200
1201 pthread_mutex_lock(&s->local->lock);
1202 if (timeout) {
1203 struct timeval tv;
1204 gettimeofday(&tv, NULL);
1205 tv.tv_sec += timeout->tv_sec;
1206 tv.tv_usec += timeout->tv_usec;
1207 if (tv.tv_usec >= 1000000) {
1208 tv.tv_sec += 1;
1209 tv.tv_usec -= 1000000;
1210 }
1211 struct timespec tmout_ts = { tv.tv_sec, tv.tv_usec * 1000 };
1212 int rc = 0;
1213 while (rc != ETIMEDOUT && simple_linked_list_size(s->local->packets) == 0) {
1214 rc = pthread_cond_timedwait(&s->local->boss_cv, &s->local->lock, &tmout_ts);
1215 }
1216 } else {
1217 while (simple_linked_list_size(s->local->packets) == 0) {
1218 pthread_cond_wait(&s->local->boss_cv, &s->local->lock);
1219 }
1220 }
1221 bool ret = simple_linked_list_size(s->local->packets) > 0;
1222 pthread_mutex_unlock(&s->local->lock);
1223 return ret;
1224}
1225
1236int udp_recv(socket_udp * s, char *buffer, int buflen)
1237{
1238 /* Reads data into the buffer, returning the number of bytes read. */
1239 /* If no data is available, this returns the value zero immediately. */
1240 /* Note: since we don't care about the source address of the packet */
1241 /* we receive, this function becomes protocol independent. */
1242 return udp_do_recv(s, buffer, buflen, 0, 0, 0);
1243}
1244
1245int udp_recvfrom(socket_udp *s, char *buffer, int buflen, struct sockaddr *src_addr, socklen_t *addrlen)
1246{
1247 return udp_do_recv(s, buffer, buflen, 0, src_addr, addrlen);
1248}
1249
1257int udp_recvfrom_data(socket_udp * s, char **buffer,
1258 struct sockaddr *src_addr, socklen_t *addrlen)
1259{
1260 assert(s->local->multithreaded);
1261 int ret;
1262
1263 pthread_mutex_lock(&s->local->lock);
1264 struct item *it = (struct item *)(simple_linked_list_pop(s->local->packets));
1265 *buffer = (char *) it->buf;
1266 if(src_addr){
1267 if(it->src_addr){
1268 memcpy(src_addr, it->src_addr, it->addrlen);
1269 *addrlen = it->addrlen;
1270 } else {
1271 *addrlen = 0;
1272 }
1273 }
1274 ret = it->size;
1275
1276 pthread_mutex_unlock(&s->local->lock);
1277 pthread_cond_signal(&s->local->reader_cv);
1278
1279 return ret;
1280}
1281int udp_recv_data(socket_udp * s, char **buffer){
1282 return udp_recvfrom_data(s, buffer, NULL, NULL);
1283}
1284
1285#ifndef _WIN32
1286int udp_recvv(socket_udp * s, struct msghdr *m)
1287{
1288 if (recvmsg(s->local->rx_fd, m, 0) == -1) {
1289 perror("recvmsg");
1290 return 1;
1291 }
1292 return 0;
1293}
1294#endif // _WIN32
1295
1305{
1306 FD_SET(s->local->rx_fd, &rfd);
1307 if (s->local->rx_fd > (fd_t) max_fd) {
1308 max_fd = s->local->rx_fd;
1309 }
1310}
1311
1312void udp_fd_set_r(socket_udp *s, struct udp_fd_r *fd_struct)
1313{
1314 FD_SET(s->local->rx_fd, &fd_struct->rfd);
1315 if (s->local->rx_fd > (fd_t) fd_struct->max_fd) {
1316 fd_struct->max_fd = s->local->rx_fd;
1317 }
1318}
1319
1332{
1333 return FD_ISSET(s->local->rx_fd, &rfd);
1334}
1335
1336int udp_fd_isset_r(socket_udp *s, struct udp_fd_r *fd_struct)
1337{
1338 return FD_ISSET(s->local->rx_fd, &fd_struct->rfd);
1339}
1340
1341
1350int udp_select(struct timeval *timeout)
1351{
1352 return select(max_fd + 1, &rfd, NULL, NULL, timeout);
1353}
1354
1355int udp_select_r(struct timeval *timeout, struct udp_fd_r * fd_struct)
1356{
1357 return select(fd_struct->max_fd + 1, &fd_struct->rfd, NULL, NULL, timeout);
1358}
1359
1368{
1369 switch (s->local->mode) {
1370 case IPv4:
1371 return udp_host_addr4();
1372 case IPv6:
1373 return udp_host_addr6(s);
1374 default:
1375 abort();
1376 }
1377 return NULL;
1378}
1379
1390{
1391 if (s && s->local->rx_fd > 0) {
1392 return s->local->rx_fd;
1393 }
1394 return 0;
1395}
1396
1397int resolve_addrinfo(const char *addr, uint16_t tx_port,
1398 struct sockaddr_storage *dst, socklen_t *len, int *mode)
1399{
1400 struct addrinfo hints, *res0;
1401 int err;
1402 memset(&hints, 0, sizeof(hints));
1403 switch (*mode) {
1404 case 0:
1405 hints.ai_family = AF_INET6;
1406 hints.ai_flags = AI_V4MAPPED | AI_ALL;
1407 break;
1408 case IPv4:
1409 hints.ai_family = AF_INET;
1410 break;
1411 case IPv6:
1412 hints.ai_family = AF_INET6;
1413 break;
1414 default:
1415 abort();
1416 }
1417 hints.ai_socktype = SOCK_DGRAM;
1418
1419 char tx_port_str[7];
1420 snprintf(tx_port_str, sizeof tx_port_str, "%u", tx_port);
1421 if ((err = getaddrinfo(addr, tx_port_str, &hints, &res0)) != 0) {
1422 /* We should probably try to do a DNS lookup on the name */
1423 /* here, but I'm trying to get the basics going first... */
1424 log_msg(LOG_LEVEL_ERROR, MOD_NAME "resolve_address: getaddrinfo: %s: %s\n", addr, ug_gai_strerror(err));
1425 return err;
1426 }
1427 memcpy(dst, res0->ai_addr, res0->ai_addrlen);
1428 *len = res0->ai_addrlen;
1429 *mode = (res0->ai_family == AF_INET ? IPv4 : IPv6);
1430 freeaddrinfo(res0);
1431
1432 return 0;
1433}
1434
1435static int resolve_address(socket_udp *s, const char *addr, uint16_t tx_port)
1436{
1437 int ret = resolve_addrinfo(addr, tx_port, &s->sock, &s->sock_len, &s->local->mode);
1438 if(ret == 0)
1439 verbose_msg("Connected IP version %d\n", s->local->mode);
1440
1441 return ret;
1442}
1443
1444int
1446{
1447 int opt = 0;
1448 socklen_t opt_size = sizeof opt;
1449 if (GETSOCKOPT(s->local->tx_fd, SOL_SOCKET, SO_RCVBUF, (sockopt_t) &opt,
1450 &opt_size) != 0) {
1451 socket_error("Unable to get socket buffer size");
1452 return -1;
1453 }
1454 return opt;
1455}
1456
1457static bool
1458udp_set_buf(socket_udp *s, int sockopt, int size)
1459{
1460 assert(sockopt == SO_RCVBUF || sockopt == SO_SNDBUF);
1461 const fd_t fd =
1462 sockopt == SO_RCVBUF ? s->local->rx_fd : s->local->tx_fd;
1463 if (SETSOCKOPT(fd, SOL_SOCKET, sockopt, (sockopt_t) &size,
1464 sizeof(size)) != 0) {
1465 socket_error("Unable to set socket buffer size");
1466 return false;
1467 }
1468
1469 int opt = 0;
1470 socklen_t opt_size = sizeof opt;
1471 if (GETSOCKOPT(fd, SOL_SOCKET, sockopt, (sockopt_t) &opt, &opt_size) !=
1472 0) {
1473 socket_error("Unable to get socket buffer size");
1474 return false;
1475 }
1476
1477 const bool ret = opt >= size;
1479 "Socket %s buffer size set to %d B%srequested %d B%s\n",
1480 sockopt == SO_RCVBUF ? "recv" : "send", opt,
1481 ret ? " (" : ", ", size, ret ? ")" : "!");
1482 return ret;
1483}
1484
1485bool
1487{
1488 return udp_set_buf(s, SO_RCVBUF, size);
1489}
1490
1491bool
1493{
1494 return udp_set_buf(s, SO_SNDBUF, size);
1495}
1496
1497/*
1498 * TODO: This should be definitely removed. We need to solve audio burst avoidance first.
1499 */
1501{
1502 const int len = 1024 * 1024;
1503 fd_set select_fd;
1504 struct timeval timeout;
1505
1506 char *buf = (char *) malloc(len);
1507
1508 assert (buf != NULL);
1509
1510 timeout.tv_sec = 0;
1511 timeout.tv_usec = 0;
1512
1513 FD_ZERO(&select_fd);
1514 FD_SET(s->local->rx_fd, &select_fd);
1515
1516 while(select(s->local->rx_fd + 1, &select_fd, NULL, NULL, &timeout) > 0) {
1517 ssize_t bytes = recv(s->local->rx_fd, buf, len, 0);
1518 if(bytes <= 0)
1519 break;
1520 }
1521
1522 free(buf);
1523}
1524
1530void udp_async_start(socket_udp *s, int nr_packets)
1531{
1532#ifdef _WIN32
1533 if (!s->local->is_wsa_overlapped) {
1534 return;
1535 }
1536
1537 if (nr_packets > s->overlapped_max) {
1538 s->overlapped = (OVERLAPPED *) realloc(s->overlapped, nr_packets * sizeof(WSAOVERLAPPED));
1539 s->overlapped_events = (void **) realloc(s->overlapped_events, nr_packets * sizeof(WSAEVENT));
1540 s->dispose_udata = (void **) realloc(s->dispose_udata, nr_packets * sizeof(void *));
1541 for (int i = s->overlapped_max; i < nr_packets; ++i) {
1542 memset(&s->overlapped[i], 0, sizeof(WSAOVERLAPPED));
1543 s->overlapped[i].hEvent = s->overlapped_events[i] = WSACreateEvent();
1544 assert(s->overlapped[i].hEvent != WSA_INVALID_EVENT);
1545 }
1546 s->overlapped_max = nr_packets;
1547 }
1548
1549 s->overlapped_count = 0;
1550 s->overlapping_active = true;
1551#else
1552 UNUSED(nr_packets);
1553 UNUSED(s);
1554#endif
1555}
1556
1558{
1559#ifdef _WIN32
1560 if (!s->overlapping_active)
1561 return;
1562 for(int i = 0; i < s->overlapped_count; i += WSA_MAXIMUM_WAIT_EVENTS)
1563 {
1564 int count = WSA_MAXIMUM_WAIT_EVENTS;
1565 if (s->overlapped_count - i < WSA_MAXIMUM_WAIT_EVENTS)
1566 count = s->overlapped_count - i;
1567 DWORD ret = WSAWaitForMultipleEvents(count, s->overlapped_events + i, TRUE, INFINITE, TRUE);
1568 if (ret == WSA_WAIT_FAILED) {
1569 socket_error("WSAWaitForMultipleEvents");
1570 }
1571 }
1572 for (int i = 0; i < s->overlapped_count; i++) {
1573 if (WSAResetEvent(s->overlapped[i].hEvent) == FALSE) {
1574 socket_error("WSAResetEvent");
1575 }
1576 free(s->dispose_udata[i]);
1577 }
1578 s->overlapping_active = false;
1579#else
1580 UNUSED(s);
1581#endif
1582}
1583
1585{
1586#ifdef _WIN32
1587 for (int i = 0; i < s->overlapped_max; i++) {
1588 WSACloseEvent(s->overlapped[i].hEvent);
1589 }
1590 free(s->overlapped);
1591 free(s->overlapped_events);
1592 free(s->dispose_udata);
1593#else
1594 UNUSED(s);
1595#endif
1596}
1597
1599{
1600 return s->local->mode == IPv6 && !IN6_IS_ADDR_V4MAPPED(&((struct sockaddr_in6 *) &s->sock)->sin6_addr);
1601}
1602
1608int udp_port_pair_is_free(int force_ip_version, int even_port)
1609{
1610 struct addrinfo hints;
1611 memset(&hints, 0, sizeof hints);
1612 struct addrinfo *res0 = NULL;
1613 hints.ai_family = force_ip_version == 4 ? AF_INET : AF_INET6;
1614 hints.ai_flags = AI_NUMERICSERV | AI_PASSIVE;
1615 hints.ai_socktype = SOCK_DGRAM;
1616 char tx_port_str[7];
1617 snprintf(tx_port_str, sizeof tx_port_str, "%hu", (uint16_t) even_port);
1618 int err = getaddrinfo(NULL, tx_port_str, &hints, &res0);
1619 if (err) {
1620 /* We should probably try to do a DNS lookup on the name */
1621 /* here, but I'm trying to get the basics going first... */
1622 log_msg(LOG_LEVEL_ERROR, MOD_NAME "%s getaddrinfo port %d: %s\n", __func__, even_port, gai_strerror(err));
1623 return -2;
1624 }
1625
1626 for (int i = 0; i < 2; ++i) {
1627 struct sockaddr *sin = res0->ai_addr;
1628 fd_t fd;
1629
1630 if (sin->sa_family == AF_INET6) {
1631 struct sockaddr_in6 *s_in6 = (struct sockaddr_in6 *)(void *) sin;
1632 int ipv6only = 0;
1633 s_in6->sin6_port = htons(even_port + i);
1634 fd = socket(AF_INET6, SOCK_DGRAM, 0);
1635 if (fd != INVALID_SOCKET) {
1636 if (SETSOCKOPT
1637 (fd, IPPROTO_IPV6, IPV6_V6ONLY, (char *)&ipv6only,
1638 sizeof(ipv6only)) != 0) {
1639 socket_error("%s - setsockopt IPV6_V6ONLY for port %d", __func__, even_port + 1);
1640 CLOSESOCKET(fd);
1641 freeaddrinfo(res0);
1642 return -2;
1643 }
1644 }
1645 } else {
1646 struct sockaddr_in *s_in = (struct sockaddr_in *)(void *) sin;
1647 s_in->sin_port = htons(even_port + i);
1648 fd = socket(AF_INET, SOCK_DGRAM, 0);
1649 }
1650
1651 if (fd == INVALID_SOCKET) {
1652 socket_error("%s - unable to initialize socket for port %d", __func__, even_port + 1);
1653 freeaddrinfo(res0);
1654 return -2;
1655 }
1656
1657 if (bind(fd, (struct sockaddr *) sin, res0->ai_addrlen) != 0) {
1658 int ret = 0;
1659#ifdef _WIN32
1660 if (WSAGetLastError() == WSAEADDRINUSE) {
1661#else
1662 if (errno == EADDRINUSE) {
1663#endif
1664 ret = -1;
1665 } else {
1666 ret = -2;
1667 socket_error("%s - cannot bind port %d", __func__, even_port + 1);
1668 }
1669 freeaddrinfo(res0);
1670 CLOSESOCKET(fd);
1671 return ret;
1672 }
1673
1674 CLOSESOCKET(fd);
1675 }
1676
1677 freeaddrinfo(res0);
1678
1679 return 0;
1680}
1681
1682#ifdef _WIN32
1689int udp_sendto_wsa_async(socket_udp *s, char *buffer, int buflen, LPWSAOVERLAPPED_COMPLETION_ROUTINE l, LPWSAOVERLAPPED o, struct sockaddr *addr, socklen_t addrlen)
1690{
1691 assert(s != NULL);
1692
1693 DWORD bytesSent;
1694 WSABUF vector;
1695 vector.buf = buffer;
1696 vector.len = buflen;
1697 int ret = WSASendTo(s->local->tx_fd, &vector, 1, &bytesSent, 0, addr, addrlen, o, l);
1698 if (ret == 0 || WSAGetLastError() == WSA_IO_PENDING)
1699 return 0;
1700 else {
1701 return ret;
1702 }
1703}
1704
1705int udp_send_wsa_async(socket_udp *s, char *buffer, int buflen, LPWSAOVERLAPPED_COMPLETION_ROUTINE l, LPWSAOVERLAPPED o)
1706{
1707 return udp_sendto_wsa_async(s, buffer, buflen, l, o, (struct sockaddr *) &s->sock, s->sock_len);
1708}
1709#endif
1710
1715int udp_recvfrom_timeout(socket_udp *s, char *buffer, int buflen,
1716 struct timeval *timeout,
1717 struct sockaddr *src_addr, socklen_t *addrlen)
1718{
1719 struct udp_fd_r fd;
1720 int len = 0;
1721
1722 if (s->local->multithreaded) {
1723 if (udp_not_empty(s, timeout)) {
1724 char *data = NULL;
1725 len = udp_recvfrom_data(s, (char **) &data, src_addr, addrlen);
1726 if (len > 0) {
1727 memcpy(buffer, data, len);
1728 }
1729 free(data);
1730 }
1731 } else {
1732 udp_fd_zero_r(&fd);
1733 udp_fd_set_r(s, &fd);
1734 if (udp_select_r(timeout, &fd) > 0) {
1735 if (udp_fd_isset_r(s, &fd)) {
1736 len = udp_recvfrom(s, buffer, buflen, src_addr, addrlen);
1737 if (len < 0) {
1738 len = 0;
1739 }
1740 }
1741 }
1742 }
1743 return len;
1744}
1745
1746int udp_recv_timeout(socket_udp *s, char *buffer, int buflen, struct timeval *timeout)
1747{
1748 return udp_recvfrom_timeout(s, buffer, buflen, timeout, NULL, NULL);
1749}
1750
1752{
1753 return s->local;
1754}
1755
1757{
1758 struct sockaddr_storage ss;
1759 socklen_t len = sizeof ss;
1760 if (getsockname(s->local->rx_fd, (struct sockaddr *) &ss, &len) != 0) {
1761 socket_error(__func__);
1762 return -1;
1763 }
1764 assert(ss.ss_family == AF_INET || ss.ss_family == AF_INET6);
1765
1766 return htons(ss.ss_family == AF_INET ? ((struct sockaddr_in *) &ss)->sin_port : ((struct sockaddr_in6 *) &ss)->sin6_port);
1767}
1768
#define UNUSED(x)
int void size_t * len
const char unsigned int flags
int fd_t
#define INVALID_SOCKET
#define CLOSESOCKET
#define TRUE
#define FALSE
void log_msg(int level, const char *format,...)
Definition debug.cpp:130
#define error_msg(...)
Definition debug.h:89
#define LOG_LEVEL_ERROR
general errors
Definition debug.h:59
#define LOG_LEVEL_VERBOSE
Definition debug.h:63
#define verbose_msg(...)
Definition debug.h:90
#define debug_msg(...)
#define debug_msg(...) log_msg(LOG_LEVEL_DEBUG, "[pid/%d +%d %s] ", getpid(), LINE,...
Definition debug.h:92
#define LOG_LEVEL_WARNING
less severe errors
Definition debug.h:60
int count
Definition hd-rum.c:44
void handle_error(int status)
Definition host.cpp:1184
const char * get_commandline_param(const char *key)
Definition host.cpp:894
#define EXIT_FAIL_NETWORK
Definition host.h:69
#define ADD_TO_PARAM(param, doc)
Definition host.h:203
void simple_linked_list_append(struct simple_linked_list *l, void *data)
Definition list.cpp:68
int simple_linked_list_size(struct simple_linked_list *l)
Definition list.cpp:93
struct simple_linked_list * simple_linked_list_init(void)
Definition list.cpp:53
void simple_linked_list_destroy(struct simple_linked_list *l)
Definition list.cpp:58
void * simple_linked_list_pop(struct simple_linked_list *l)
Definition list.cpp:82
#define SWAP(a, b)
Definition macros.h:57
#define MAX(a, b)
Definition macros.h:65
bool is_wine()
Definition misc.cpp:172
bool is_addr_multicast(const char *addr)
Definition net.c:382
bool is_host_loopback(const char *hostname)
Definition net.c:174
const char * ug_gai_strerror(int errcode)
Definition net.c:466
#define IN6_BLACKHOLE_SERVER_MODE_STR
Definition net.h:52
bool udp_addr_valid(const char *addr)
Definition net_udp.c:664
static char * udp_host_addr4(void)
Definition net_udp.c:427
void udp_set_receiver(socket_udp *s, struct sockaddr *sa, socklen_t len)
Definition net_udp.c:922
static bool udp_join_mcast_grp4(unsigned long addr, int rx_fd, int tx_fd, int ttl, unsigned int ifindex)
Definition net_udp.c:367
static void udp_leave_mcast_grp6(struct in6_addr sin6_addr, int fd, unsigned int ifindex)
Definition net_udp.c:521
static void * udp_reader(void *arg)
Definition net_udp.c:1092
#define DEFAULT_MAX_UDP_READER_QUEUE_LEN
Definition net_udp.c:72
void udp_exit(socket_udp *s)
Definition net_udp.c:974
#define IPv6
Definition net_udp.c:78
static char * udp_host_addr6(socket_udp *s)
Definition net_udp.c:545
static bool set_sock_opts_and_bind(fd_t fd, bool ipv6, uint16_t rx_port, int ttl)
Definition net_udp.c:688
int udp_recvfrom(socket_udp *s, char *buffer, int buflen, struct sockaddr *src_addr, socklen_t *addrlen)
Definition net_udp.c:1245
static int resolve_address(socket_udp *s, const char *addr, uint16_t tx_port)
Definition net_udp.c:1435
int udp_recv(socket_udp *s, char *buffer, int buflen)
Definition net_udp.c:1236
int udp_select_r(struct timeval *timeout, struct udp_fd_r *fd_struct)
Definition net_udp.c:1355
#define INADDR_NONE
Definition net_udp.c:125
int udp_get_udp_rx_port(socket_udp *s)
Definition net_udp.c:1756
static fd_set rfd
Definition net_udp.c:946
struct socket_udp_local * udp_get_local(socket_udp *s)
Definition net_udp.c:1751
static void socket_herror(const char *msg,...)
Definition net_udp.c:260
int udp_recv_data(socket_udp *s, char **buffer)
Definition net_udp.c:1281
static fd_t max_fd
Definition net_udp.c:947
int udp_recvfrom_timeout(socket_udp *s, char *buffer, int buflen, struct timeval *timeout, struct sockaddr *src_addr, socklen_t *addrlen)
Definition net_udp.c:1715
void udp_async_start(socket_udp *s, int nr_packets)
Definition net_udp.c:1530
void udp_async_wait(socket_udp *s)
Definition net_udp.c:1557
int udp_recvfrom_data(socket_udp *s, char **buffer, struct sockaddr *src_addr, socklen_t *addrlen)
Definition net_udp.c:1257
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
static void udp_leave_mcast_grp4(unsigned long addr, int fd)
Definition net_udp.c:412
char * udp_host_addr(socket_udp *s)
Definition net_udp.c:1367
int udp_peek(socket_udp *s, char *buffer, int buflen)
Definition net_udp.c:1185
int udp_sendto(socket_udp *s, char *buffer, int buflen, struct sockaddr *dst_addr, socklen_t addrlen)
Definition net_udp.c:1038
int udp_sendv(socket_udp *s, struct iovec *vector, int count, void *d)
Definition net_udp.c:1067
socket_udp * udp_init_with_local(struct socket_udp_local *l, struct sockaddr *sa, socklen_t len)
Definition net_udp.c:927
static int udp_do_recv(socket_udp *s, char *buffer, int buflen, int flags, struct sockaddr *src_addr, socklen_t *addrlen)
Definition net_udp.c:1153
static bool udp_addr_valid6(const char *dst)
Definition net_udp.c:453
bool udp_set_recv_buf(socket_udp *s, int size)
Definition net_udp.c:1486
bool udp_not_empty(socket_udp *s, struct timeval *timeout)
Checks whether there are data ready to read in socket.
Definition net_udp.c:1197
void udp_fd_zero_r(struct udp_fd_r *fd_struct)
Definition net_udp.c:961
int udp_send(socket_udp *s, char *buffer, int buflen)
Definition net_udp.c:1028
#define ERRBUF_SIZE
Definition net_udp.c:80
#define ALIGNED_ITEM_OFF
Definition net_udp.c:136
void * sockopt_t
Definition net_udp.c:90
int udp_recvv(socket_udp *s, struct msghdr *m)
Definition net_udp.c:1286
void udp_fd_set(socket_udp *s)
Definition net_udp.c:1304
int udp_fd_isset(socket_udp *s)
Definition net_udp.c:1331
bool udp_set_send_buf(socket_udp *s, int size)
Definition net_udp.c:1492
#define IPv4
Definition net_udp.c:77
int udp_port_pair_is_free(int force_ip_version, int even_port)
Definition net_udp.c:1608
#define MOD_NAME
Definition net_udp.c:81
#define ALIGNED_SOCKADDR_STORAGE_OFF
Definition net_udp.c:135
#define GETSOCKOPT
Definition net_udp.c:197
int udp_get_recv_buf(socket_udp *s)
Definition net_udp.c:1445
void udp_fd_set_r(socket_udp *s, struct udp_fd_r *fd_struct)
Definition net_udp.c:1312
bool udp_is_ipv6(socket_udp *s)
Definition net_udp.c:1598
static bool udp_join_mcast_grp6(struct in6_addr sin6_addr, int rx_fd, int tx_fd, int ttl, unsigned int ifindex)
Definition net_udp.c:473
#define SETSOCKOPT
Definition net_udp.c:194
static void udp_clean_async_state(socket_udp *s)
Definition net_udp.c:1584
void udp_flush_recv_buf(socket_udp *s)
Definition net_udp.c:1500
static bool udp_set_buf(socket_udp *s, int sockopt, int size)
Definition net_udp.c:1458
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
int resolve_addrinfo(const char *addr, uint16_t tx_port, struct sockaddr_storage *dst, socklen_t *len, int *mode)
Definition net_udp.c:1397
int udp_fd(socket_udp *s)
Definition net_udp.c:1389
bool udp_is_server_mode_blackhole(socket_udp *s)
Definition net_udp.c:911
int udp_recv_timeout(socket_udp *s, char *buffer, int buflen, struct timeval *timeout)
Definition net_udp.c:1746
void udp_fd_zero(void)
Definition net_udp.c:955
int udp_select(struct timeval *timeout)
Definition net_udp.c:1350
static bool udp_addr_valid4(const char *dst)
Definition net_udp.c:349
int udp_fd_isset_r(socket_udp *s, struct udp_fd_r *fd_struct)
Definition net_udp.c:1336
enum openssl_mode mode
int platform_pipe_init(fd_t p[2])
#define socket_error(...)
void * sockopt_t
void platform_pipe_close(fd_t pipe)
#define PLATFORM_PIPE_WRITE
#define RTP_PACKET_HEADER_SIZE
Definition rtp.h:128
#define RTP_MAX_PACKET_LEN
Definition rtp.h:61
const char * name
Definition settings.cpp:193
socklen_t sock_len
Definition net_udp.c:169
bool local_is_slave
Definition net_udp.c:173
struct sockaddr_storage sock
Definition net_udp.c:168
struct socket_udp_local * local
Definition net_udp.c:172
unsigned int ifindex
iface index for multicast
Definition net_udp.c:170
Definition hd-rum.c:27
int size
Definition net_udp.c:130
socklen_t addrlen
Definition net_udp.c:132
long size
Definition hd-rum.c:29
uint8_t * buf
Definition net_udp.c:129
char buf[SIZE]
Definition hd-rum.c:30
struct sockaddr * src_addr
Definition net_udp.c:131
pthread_t thread_id
Definition net_udp.c:153
fd_t should_exit_fd[2]
Definition net_udp.c:161
pthread_cond_t boss_cv
Definition net_udp.c:157
unsigned int max_packets
Definition net_udp.c:155
pthread_cond_t reader_cv
Definition net_udp.c:158
struct simple_linked_list * packets
Definition net_udp.c:154
pthread_mutex_t lock
Definition net_udp.c:156
fd_t max_fd
Definition net_udp.h:102
fd_set rfd
Definition net_udp.h:101
void set_thread_name(const char *name)
Definition thread.c:72
int vsnprintf(char *s, size_t buf_size, const char *format, va_list ap)
Definition vsnprintf.c:46