72#define DEFAULT_MAX_UDP_READER_QUEUE_LEN (1920/3*8*1080/1152)
80#define ERRBUF_SIZE 255
81#define MOD_NAME "[RTP UDP] "
84const struct in6_addr in6addr_any = { IN6ADDR_ANY_INIT };
98#define IPPROTO_IPV6 IPPROTO_IP
99struct in6_addr in6addr_any = { IN6ADDR_ANY_INIT };
107#define IP_MULTICAST_LOOP 11
108#define IP_MULTICAST_IF 9
109#define IP_MULTICAST_TTL 10
110#define IP_MULTICAST_LOOP 11
111#define IP_ADD_MEMBERSHIP 12
112#define IP_DROP_MEMBERSHIP 13
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))
119 struct in_addr imr_multiaddr;
120 struct in_addr imr_interface;
125#define INADDR_NONE 0xffffffff
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))
149 bool is_wsa_overlapped;
176 WSAOVERLAPPED *overlapped;
177 WSAEVENT *overlapped_events;
178 void **dispose_udata;
179 bool overlapping_active;
181 int overlapped_count;
192#define SETSOCKOPT winsock_versions_setsockopt
194#define SETSOCKOPT setsockopt
197#define GETSOCKOPT getsockopt
209#define WSERR(x) {#x,x}
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),
229 int e = WSAGetLastError();
230 if (e == WSAECONNRESET) {
233 while (ws_errs[i].errno_code && ws_errs[i].errno_code != e) {
237 _vsnprintf(buffer,
sizeof buffer,
msg, ap);
240 const char *errname = ws_errs[i].errno_code == 0 ? get_win32_error(e)
241 : ws_errs[i].errname;
248#if ! defined _POSIX_C_SOURCE || (_POSIX_C_SOURCE >= 200112L && ! _GNU_SOURCE)
249 strerror_r(errno, strerror_buf,
sizeof strerror_buf);
258#define socket_herror socket_error
264 uint32_t blen =
sizeof(buffer) /
sizeof(buffer[0]);
279#define WS1_IP_MULTICAST_IF 2
280#define WS1_IP_MULTICAST_TTL 3
281#define WS1_IP_MULTICAST_LOOP 4
282#define WS1_IP_ADD_MEMBERSHIP 5
283#define WS1_IP_DROP_MEMBERSHIP 6
290winsock_versions_setsockopt(SOCKET s,
int level,
int optname,
291 const char FAR * optval,
int optlen)
295 case IP_MULTICAST_IF:
297 setsockopt(s, level, WS1_IP_MULTICAST_IF, optval, optlen);
299 case IP_MULTICAST_TTL:
301 setsockopt(s, level, WS1_IP_MULTICAST_TTL, optval, optlen);
303 case IP_MULTICAST_LOOP:
305 setsockopt(s, level, WS1_IP_MULTICAST_LOOP, optval, optlen);
307 case IP_ADD_MEMBERSHIP:
309 setsockopt(s, level, WS1_IP_ADD_MEMBERSHIP, optval, optlen);
311 case IP_DROP_MEMBERSHIP:
313 setsockopt(s, level, WS1_IP_DROP_MEMBERSHIP, optval,
320 return setsockopt(s, level, optname, optval, optlen);
325#ifdef NEED_INET_ATON_STATIC
328int inet_aton(
const char *
name,
struct in_addr *addr);
330int inet_aton(
const char *
name,
struct in_addr *addr)
332 addr->s_addr = inet_addr(
name);
337#ifdef NEED_IN6_IS_ADDR_MULTICAST
338#define IN6_IS_ADDR_MULTICAST(addr) ((addr)->s6_addr[0] == 0xffU)
341#if defined(NEED_IN6_IS_ADDR_UNSPECIFIED) && defined(MUSICA_IPV6)
342#define IN6_IS_ADDR_UNSPECIFIED(addr) IS_UNSPEC_IN6_ADDR(*addr)
351 struct in_addr addr4;
354 if (inet_pton(AF_INET, dst, &addr4)) {
358 h = gethostbyname(dst);
369 if (IN_MULTICAST(ntohl(addr))) {
375 imr.imr_multiaddr.s_addr = addr;
376 imr.imr_interface.s_addr = ifindex;
379 (rx_fd, IPPROTO_IP, IP_ADD_MEMBERSHIP, (
char *)&imr,
380 sizeof(
struct ip_mreq)) != 0) {
386 (tx_fd, IPPROTO_IP, IP_MULTICAST_LOOP, &loop,
387 sizeof(loop)) != 0) {
394 (tx_fd, IPPROTO_IP, IP_MULTICAST_TTL, (
char *)&ttl,
403 (tx_fd, IPPROTO_IP, IP_MULTICAST_IF,
404 (
char *)&ifindex,
sizeof(ifindex)) != 0) {
414 if (IN_MULTICAST(ntohl(addr))) {
416 imr.imr_multiaddr.s_addr = addr;
417 imr.imr_interface.s_addr = INADDR_ANY;
419 (fd, IPPROTO_IP, IP_DROP_MEMBERSHIP, (
char *)&imr,
420 sizeof(
struct ip_mreq)) != 0) {
423 debug_msg(
"Dropped membership of multicast group\n");
429 char *hname = (
char *) calloc(MAXHOSTNAMELEN + 1, 1);
430 struct hostent *hent;
431 struct in_addr iaddr;
433 if (gethostname(hname, MAXHOSTNAMELEN) != 0) {
437 hent = gethostbyname(hname);
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);
456 struct in6_addr addr6;
457 switch (inet_pton(AF_INET6, dst, &addr6)) {
473static bool udp_join_mcast_grp6(
struct in6_addr sin6_addr,
int rx_fd,
int tx_fd,
int ttl,
unsigned int ifindex)
476 if (IN6_IS_ADDR_MULTICAST(&sin6_addr)) {
477 unsigned int loop = 1;
478 struct ipv6_mreq imr;
480 imr.i6mr_interface = 1;
481 imr.i6mr_multiaddr = sin6_addr;
483 imr.ipv6mr_multiaddr = sin6_addr;
484 imr.ipv6mr_interface = ifindex;
488 (rx_fd, IPPROTO_IPV6, IPV6_ADD_MEMBERSHIP, (
char *)&imr,
489 sizeof(
struct ipv6_mreq)) != 0) {
495 (tx_fd, IPPROTO_IPV6, IPV6_MULTICAST_LOOP, (
char *)&loop,
496 sizeof(loop)) != 0) {
502 (tx_fd, IPPROTO_IPV6, IPV6_MULTICAST_HOPS, (
char *)&ttl,
510 if (
SETSOCKOPT(tx_fd, IPPROTO_IPV6, IPV6_MULTICAST_IF,
511 (
char *)&ifindex,
sizeof(ifindex)) != 0) {
524 if (IN6_IS_ADDR_MULTICAST(&sin6_addr)) {
525 struct ipv6_mreq imr;
527 imr.i6mr_interface = 1;
528 imr.i6mr_multiaddr = sin6_addr;
530 imr.ipv6mr_multiaddr = sin6_addr;
531 imr.ipv6mr_interface = ifindex;
535 (fd, IPPROTO_IPV6, IPV6_DROP_MEMBERSHIP, (
char *)&imr,
536 sizeof(
struct ipv6_mreq)) != 0) {
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);
555 newsock = socket(AF_INET6, SOCK_DGRAM, 0);
562 if (
SETSOCKOPT(newsock, IPPROTO_IPV6, IPV6_V6ONLY,
564 sizeof(ipv6only)) != 0) {
567 memset((
char *)&addr6, 0,
len);
568 addr6.sin6_family = AF_INET6;
570 addr6.sin6_len =
len;
572 addr6.sin6_addr = in6addr_any;
573 result = bind(newsock, (
struct sockaddr *)&addr6,
len);
577 addr6.sin6_addr = ((
struct sockaddr_in6 *)&s->
sock)->sin6_addr;
579 if (getsockname(s->
local->
rx_fd, (
struct sockaddr *)&bound, &
len) == -1) {
583 addr6.sin6_port = bound.sin6_port;
585 addr6.sin6_scope_id = ((
struct sockaddr_in6 *)&s->
sock)->sin6_scope_id;
587 result = connect(newsock, (
struct sockaddr *)&addr6,
len);
592 memset((
char *)&local, 0,
len);
594 getsockname(newsock, (
struct sockaddr *)&local, &
len)) < 0) {
595 local.sin6_addr = in6addr_any;
602 if (IN6_IS_ADDR_UNSPECIFIED(&local.sin6_addr)
603 || IN6_IS_ADDR_MULTICAST(&local.sin6_addr)) {
604 if (gethostname(hname, MAXHOSTNAMELEN) != 0) {
610 hints.ai_protocol = 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;
619 if ((gai_err = getaddrinfo(hname, NULL, &hints, &ai))) {
626 struct sockaddr_in6 *addr6 = (
struct sockaddr_in6 *)(
void *)
631 hname, MAXHOSTNAMELEN) == NULL) {
640 if (inet_ntop(AF_INET6, &local.sin6_addr, hname, MAXHOSTNAMELEN) ==
682 int ttl,
int force_ip_version,
bool multithreaded)
684 return udp_init_if(addr, NULL, rx_port, tx_port, ttl, force_ip_version, multithreaded);
689 struct sockaddr_storage s_in;
690 memset(&s_in, 0,
sizeof s_in);
696 if (
SETSOCKOPT(fd, IPPROTO_IPV6, IPV6_V6ONLY, (
char *)&ipv6only,
697 sizeof(ipv6only)) != 0) {
701 if (ttl > 0 &&
SETSOCKOPT(fd, IPPROTO_IPV6, IPV6_UNICAST_HOPS, (
char *)&ttl,
713 SETSOCKOPT(fd, IPPROTO_IP, IP_TTL, (
char *)&ttl,
720 (fd, SOL_SOCKET, SO_REUSEPORT, (
int *)&reuse,
721 sizeof(reuse)) != 0) {
727 (fd, SOL_SOCKET, SO_REUSEADDR, (
char *)&reuse,
728 sizeof(reuse)) != 0) {
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);
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);
746 s_in6->sin6_len =
sizeof(
struct sockaddr_in6);
748 sin_len =
sizeof(
struct sockaddr_in6);
751 if (bind(fd, (
struct sockaddr *)&s_in, sin_len) != 0) {
755 if (rx_port == 5004 || rx_port == 5005)
765 "* udp-queue-len=<l>\n"
766 " Use different queue size than default DEFAULT_MAX_UDP_READER_QUEUE_LEN\n");
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");
790 uint16_t tx_port,
int ttl,
int force_ip_version,
bool multithreaded)
798 pthread_mutex_init(&s->
local->
lock, NULL);
802 assert(force_ip_version == 0 || force_ip_version == 4 || force_ip_version == 6);
805 s->
local->
mode = strchr(addr,
'.') != NULL ? 4 : 6;
814 if ((s->
ifindex = if_nametoindex(iface)) == 0) {
815 error_msg(
"Illegal interface specification\n");
823 s->
local->is_wsa_overlapped =
true;
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);
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);
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) {
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;
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;
913 struct in6_addr ipv6_blackhole_server_mode;
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;
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)) {
963 FD_ZERO(&fd_struct->
rfd);
1031 assert(buffer != NULL);
1034 return sendto(s->
local->
tx_fd, buffer, buflen, 0, (
struct sockaddr *)&s->
sock,
1048 assert(!s->overlapping_active || s->overlapped_count < s->overlapped_max);
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;
1059 s->overlapped_count++;
1060 if (ret == 0 || WSAGetLastError() == WSA_IO_PENDING)
1073 msg.msg_name = (
void *) & s->
sock;
1075 msg.msg_iov = vector;
1078 msg.msg_control = 0;
1079 msg.msg_controllen = 0;
1104 int rc = select(nfds, &fds, NULL, NULL, NULL);
1115 socklen_t addrlen =
sizeof(
struct sockaddr_storage);
1116 int size = recvfrom(s->
local->
rx_fd, (
char *) buffer,
1118 0, src_addr, &addrlen);
1161 assert(buffer != NULL);
1168 if (errno != ECONNREFUSED) {
1187 return udp_do_recv(s, buffer, buflen, MSG_PEEK, 0, 0);
1204 gettimeofday(&tv, NULL);
1205 tv.tv_sec += timeout->tv_sec;
1206 tv.tv_usec += timeout->tv_usec;
1207 if (tv.tv_usec >= 1000000) {
1209 tv.tv_usec -= 1000000;
1211 struct timespec tmout_ts = { tv.tv_sec, tv.tv_usec * 1000 };
1247 return udp_do_recv(s, buffer, buflen, 0, src_addr, addrlen);
1258 struct sockaddr *src_addr, socklen_t *addrlen)
1265 *buffer = (
char *) it->
buf;
1352 return select(
max_fd + 1, &
rfd, NULL, NULL, timeout);
1357 return select(fd_struct->
max_fd + 1, &fd_struct->
rfd, NULL, NULL, timeout);
1398 struct sockaddr_storage *dst, socklen_t *
len,
int *
mode)
1400 struct addrinfo hints, *res0;
1402 memset(&hints, 0,
sizeof(hints));
1405 hints.ai_family = AF_INET6;
1406 hints.ai_flags = AI_V4MAPPED | AI_ALL;
1409 hints.ai_family = AF_INET;
1412 hints.ai_family = AF_INET6;
1417 hints.ai_socktype = SOCK_DGRAM;
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) {
1427 memcpy(dst, res0->ai_addr, res0->ai_addrlen);
1428 *
len = res0->ai_addrlen;
1448 socklen_t opt_size =
sizeof opt;
1460 assert(sockopt == SO_RCVBUF || sockopt == SO_SNDBUF);
1464 sizeof(size)) != 0) {
1470 socklen_t opt_size =
sizeof opt;
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 ?
")" :
"!");
1502 const int len = 1024 * 1024;
1504 struct timeval timeout;
1506 char *buf = (
char *) malloc(
len);
1508 assert (buf != NULL);
1511 timeout.tv_usec = 0;
1513 FD_ZERO(&select_fd);
1516 while(select(s->
local->
rx_fd + 1, &select_fd, NULL, NULL, &timeout) > 0) {
1533 if (!s->
local->is_wsa_overlapped) {
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);
1546 s->overlapped_max = nr_packets;
1549 s->overlapped_count = 0;
1550 s->overlapping_active =
true;
1560 if (!s->overlapping_active)
1562 for(
int i = 0; i < s->overlapped_count; i += WSA_MAXIMUM_WAIT_EVENTS)
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) {
1572 for (
int i = 0; i < s->overlapped_count; i++) {
1573 if (WSAResetEvent(s->overlapped[i].hEvent) ==
FALSE) {
1576 free(s->dispose_udata[i]);
1578 s->overlapping_active =
false;
1587 for (
int i = 0; i < s->overlapped_max; i++) {
1588 WSACloseEvent(s->overlapped[i].hEvent);
1590 free(s->overlapped);
1591 free(s->overlapped_events);
1592 free(s->dispose_udata);
1600 return s->
local->
mode ==
IPv6 && !IN6_IS_ADDR_V4MAPPED(&((
struct sockaddr_in6 *) &s->
sock)->sin6_addr);
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);
1626 for (
int i = 0; i < 2; ++i) {
1627 struct sockaddr *sin = res0->ai_addr;
1630 if (sin->sa_family == AF_INET6) {
1631 struct sockaddr_in6 *s_in6 = (
struct sockaddr_in6 *)(
void *) sin;
1633 s_in6->sin6_port = htons(even_port + i);
1634 fd = socket(AF_INET6, SOCK_DGRAM, 0);
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);
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);
1652 socket_error(
"%s - unable to initialize socket for port %d", __func__, even_port + 1);
1657 if (bind(fd, (
struct sockaddr *) sin, res0->ai_addrlen) != 0) {
1660 if (WSAGetLastError() == WSAEADDRINUSE) {
1662 if (errno == EADDRINUSE) {
1667 socket_error(
"%s - cannot bind port %d", __func__, even_port + 1);
1689int udp_sendto_wsa_async(
socket_udp *s,
char *buffer,
int buflen, LPWSAOVERLAPPED_COMPLETION_ROUTINE l, LPWSAOVERLAPPED o,
struct sockaddr *addr, socklen_t addrlen)
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)
1705int udp_send_wsa_async(
socket_udp *s,
char *buffer,
int buflen, LPWSAOVERLAPPED_COMPLETION_ROUTINE l, LPWSAOVERLAPPED o)
1707 return udp_sendto_wsa_async(s, buffer, buflen, l, o, (
struct sockaddr *) &s->
sock, s->
sock_len);
1716 struct timeval *timeout,
1717 struct sockaddr *src_addr, socklen_t *addrlen)
1727 memcpy(buffer, data,
len);
1758 struct sockaddr_storage ss;
1759 socklen_t
len =
sizeof ss;
1760 if (getsockname(s->
local->
rx_fd, (
struct sockaddr *) &ss, &
len) != 0) {
1764 assert(ss.ss_family == AF_INET || ss.ss_family == AF_INET6);
1766 return htons(ss.ss_family == AF_INET ? ((
struct sockaddr_in *) &ss)->sin_port : ((
struct sockaddr_in6 *) &ss)->sin6_port);
const char unsigned int flags
void log_msg(int level, const char *format,...)
#define LOG_LEVEL_ERROR
general errors
#define LOG_LEVEL_VERBOSE
#define debug_msg(...)
#define debug_msg(...) log_msg(LOG_LEVEL_DEBUG, "[pid/%d +%d %s] ", getpid(), LINE,...
#define LOG_LEVEL_WARNING
less severe errors
void handle_error(int status)
const char * get_commandline_param(const char *key)
#define EXIT_FAIL_NETWORK
#define ADD_TO_PARAM(param, doc)
void simple_linked_list_append(struct simple_linked_list *l, void *data)
int simple_linked_list_size(struct simple_linked_list *l)
struct simple_linked_list * simple_linked_list_init(void)
void simple_linked_list_destroy(struct simple_linked_list *l)
void * simple_linked_list_pop(struct simple_linked_list *l)
bool is_addr_multicast(const char *addr)
bool is_host_loopback(const char *hostname)
const char * ug_gai_strerror(int errcode)
#define IN6_BLACKHOLE_SERVER_MODE_STR
bool udp_addr_valid(const char *addr)
static char * udp_host_addr4(void)
void udp_set_receiver(socket_udp *s, struct sockaddr *sa, socklen_t len)
static bool udp_join_mcast_grp4(unsigned long addr, int rx_fd, int tx_fd, int ttl, unsigned int ifindex)
static void udp_leave_mcast_grp6(struct in6_addr sin6_addr, int fd, unsigned int ifindex)
static void * udp_reader(void *arg)
#define DEFAULT_MAX_UDP_READER_QUEUE_LEN
void udp_exit(socket_udp *s)
static char * udp_host_addr6(socket_udp *s)
static bool set_sock_opts_and_bind(fd_t fd, bool ipv6, uint16_t rx_port, int ttl)
int udp_recvfrom(socket_udp *s, char *buffer, int buflen, struct sockaddr *src_addr, socklen_t *addrlen)
static int resolve_address(socket_udp *s, const char *addr, uint16_t tx_port)
int udp_recv(socket_udp *s, char *buffer, int buflen)
int udp_select_r(struct timeval *timeout, struct udp_fd_r *fd_struct)
int udp_get_udp_rx_port(socket_udp *s)
struct socket_udp_local * udp_get_local(socket_udp *s)
static void socket_herror(const char *msg,...)
int udp_recv_data(socket_udp *s, char **buffer)
int udp_recvfrom_timeout(socket_udp *s, char *buffer, int buflen, struct timeval *timeout, struct sockaddr *src_addr, socklen_t *addrlen)
void udp_async_start(socket_udp *s, int nr_packets)
void udp_async_wait(socket_udp *s)
int udp_recvfrom_data(socket_udp *s, char **buffer, struct sockaddr *src_addr, socklen_t *addrlen)
socket_udp * udp_init(const char *addr, uint16_t rx_port, uint16_t tx_port, int ttl, int force_ip_version, bool multithreaded)
static void udp_leave_mcast_grp4(unsigned long addr, int fd)
char * udp_host_addr(socket_udp *s)
int udp_peek(socket_udp *s, char *buffer, int buflen)
int udp_sendto(socket_udp *s, char *buffer, int buflen, struct sockaddr *dst_addr, socklen_t addrlen)
int udp_sendv(socket_udp *s, struct iovec *vector, int count, void *d)
socket_udp * udp_init_with_local(struct socket_udp_local *l, struct sockaddr *sa, socklen_t len)
static int udp_do_recv(socket_udp *s, char *buffer, int buflen, int flags, struct sockaddr *src_addr, socklen_t *addrlen)
static bool udp_addr_valid6(const char *dst)
bool udp_set_recv_buf(socket_udp *s, int size)
bool udp_not_empty(socket_udp *s, struct timeval *timeout)
Checks whether there are data ready to read in socket.
void udp_fd_zero_r(struct udp_fd_r *fd_struct)
int udp_send(socket_udp *s, char *buffer, int buflen)
int udp_recvv(socket_udp *s, struct msghdr *m)
void udp_fd_set(socket_udp *s)
int udp_fd_isset(socket_udp *s)
bool udp_set_send_buf(socket_udp *s, int size)
int udp_port_pair_is_free(int force_ip_version, int even_port)
#define ALIGNED_SOCKADDR_STORAGE_OFF
int udp_get_recv_buf(socket_udp *s)
void udp_fd_set_r(socket_udp *s, struct udp_fd_r *fd_struct)
bool udp_is_ipv6(socket_udp *s)
static bool udp_join_mcast_grp6(struct in6_addr sin6_addr, int rx_fd, int tx_fd, int ttl, unsigned int ifindex)
static void udp_clean_async_state(socket_udp *s)
void udp_flush_recv_buf(socket_udp *s)
static bool udp_set_buf(socket_udp *s, int sockopt, int size)
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)
int resolve_addrinfo(const char *addr, uint16_t tx_port, struct sockaddr_storage *dst, socklen_t *len, int *mode)
int udp_fd(socket_udp *s)
bool udp_is_server_mode_blackhole(socket_udp *s)
int udp_recv_timeout(socket_udp *s, char *buffer, int buflen, struct timeval *timeout)
int udp_select(struct timeval *timeout)
static bool udp_addr_valid4(const char *dst)
int udp_fd_isset_r(socket_udp *s, struct udp_fd_r *fd_struct)
#define RTP_PACKET_HEADER_SIZE
#define RTP_MAX_PACKET_LEN
struct sockaddr_storage sock
struct socket_udp_local * local
unsigned int ifindex
iface index for multicast
struct sockaddr * src_addr
struct simple_linked_list * packets
void set_thread_name(const char *name)
int vsnprintf(char *s, size_t buf_size, const char *format, va_list ap)