Libav
udp.c
Go to the documentation of this file.
1 /*
2  * UDP prototype streaming system
3  * Copyright (c) 2000, 2001, 2002 Fabrice Bellard
4  *
5  * This file is part of Libav.
6  *
7  * Libav is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU Lesser General Public
9  * License as published by the Free Software Foundation; either
10  * version 2.1 of the License, or (at your option) any later version.
11  *
12  * Libav is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15  * Lesser General Public License for more details.
16  *
17  * You should have received a copy of the GNU Lesser General Public
18  * License along with Libav; if not, write to the Free Software
19  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
20  */
21 
27 #define _BSD_SOURCE /* Needed for using struct ip_mreq with recent glibc */
28 
29 #include "avformat.h"
30 #include "avio_internal.h"
31 #include "libavutil/parseutils.h"
32 #include "libavutil/avstring.h"
33 #include "internal.h"
34 #include "network.h"
35 #include "os_support.h"
36 #include "url.h"
37 
38 #ifndef IPV6_ADD_MEMBERSHIP
39 #define IPV6_ADD_MEMBERSHIP IPV6_JOIN_GROUP
40 #define IPV6_DROP_MEMBERSHIP IPV6_LEAVE_GROUP
41 #endif
42 
43 typedef struct {
44  int udp_fd;
45  int ttl;
50  struct sockaddr_storage dest_addr;
53 } UDPContext;
54 
55 #define UDP_TX_BUF_SIZE 32768
56 #define UDP_MAX_PKT_SIZE 65536
57 
58 static void log_net_error(void *ctx, int level, const char* prefix)
59 {
60  char errbuf[100];
61  av_strerror(ff_neterrno(), errbuf, sizeof(errbuf));
62  av_log(ctx, level, "%s: %s\n", prefix, errbuf);
63 }
64 
65 static int udp_set_multicast_ttl(int sockfd, int mcastTTL,
66  struct sockaddr *addr)
67 {
68 #ifdef IP_MULTICAST_TTL
69  if (addr->sa_family == AF_INET) {
70  if (setsockopt(sockfd, IPPROTO_IP, IP_MULTICAST_TTL, &mcastTTL, sizeof(mcastTTL)) < 0) {
71  log_net_error(NULL, AV_LOG_ERROR, "setsockopt(IP_MULTICAST_TTL)");
72  return -1;
73  }
74  }
75 #endif
76 #if defined(IPPROTO_IPV6) && defined(IPV6_MULTICAST_HOPS)
77  if (addr->sa_family == AF_INET6) {
78  if (setsockopt(sockfd, IPPROTO_IPV6, IPV6_MULTICAST_HOPS, &mcastTTL, sizeof(mcastTTL)) < 0) {
79  log_net_error(NULL, AV_LOG_ERROR, "setsockopt(IPV6_MULTICAST_HOPS)");
80  return -1;
81  }
82  }
83 #endif
84  return 0;
85 }
86 
87 static int udp_join_multicast_group(int sockfd, struct sockaddr *addr)
88 {
89 #ifdef IP_ADD_MEMBERSHIP
90  if (addr->sa_family == AF_INET) {
91  struct ip_mreq mreq;
92 
93  mreq.imr_multiaddr.s_addr = ((struct sockaddr_in *)addr)->sin_addr.s_addr;
94  mreq.imr_interface.s_addr= INADDR_ANY;
95  if (setsockopt(sockfd, IPPROTO_IP, IP_ADD_MEMBERSHIP, (const void *)&mreq, sizeof(mreq)) < 0) {
96  log_net_error(NULL, AV_LOG_ERROR, "setsockopt(IP_ADD_MEMBERSHIP)");
97  return -1;
98  }
99  }
100 #endif
101 #if HAVE_STRUCT_IPV6_MREQ && defined(IPPROTO_IPV6)
102  if (addr->sa_family == AF_INET6) {
103  struct ipv6_mreq mreq6;
104 
105  memcpy(&mreq6.ipv6mr_multiaddr, &(((struct sockaddr_in6 *)addr)->sin6_addr), sizeof(struct in6_addr));
106  mreq6.ipv6mr_interface= 0;
107  if (setsockopt(sockfd, IPPROTO_IPV6, IPV6_ADD_MEMBERSHIP, &mreq6, sizeof(mreq6)) < 0) {
108  log_net_error(NULL, AV_LOG_ERROR, "setsockopt(IPV6_ADD_MEMBERSHIP)");
109  return -1;
110  }
111  }
112 #endif
113  return 0;
114 }
115 
116 static int udp_leave_multicast_group(int sockfd, struct sockaddr *addr)
117 {
118 #ifdef IP_DROP_MEMBERSHIP
119  if (addr->sa_family == AF_INET) {
120  struct ip_mreq mreq;
121 
122  mreq.imr_multiaddr.s_addr = ((struct sockaddr_in *)addr)->sin_addr.s_addr;
123  mreq.imr_interface.s_addr= INADDR_ANY;
124  if (setsockopt(sockfd, IPPROTO_IP, IP_DROP_MEMBERSHIP, (const void *)&mreq, sizeof(mreq)) < 0) {
125  log_net_error(NULL, AV_LOG_ERROR, "setsockopt(IP_DROP_MEMBERSHIP)");
126  return -1;
127  }
128  }
129 #endif
130 #if HAVE_STRUCT_IPV6_MREQ && defined(IPPROTO_IPV6)
131  if (addr->sa_family == AF_INET6) {
132  struct ipv6_mreq mreq6;
133 
134  memcpy(&mreq6.ipv6mr_multiaddr, &(((struct sockaddr_in6 *)addr)->sin6_addr), sizeof(struct in6_addr));
135  mreq6.ipv6mr_interface= 0;
136  if (setsockopt(sockfd, IPPROTO_IPV6, IPV6_DROP_MEMBERSHIP, &mreq6, sizeof(mreq6)) < 0) {
137  log_net_error(NULL, AV_LOG_ERROR, "setsockopt(IPV6_DROP_MEMBERSHIP)");
138  return -1;
139  }
140  }
141 #endif
142  return 0;
143 }
144 
145 static struct addrinfo* udp_resolve_host(const char *hostname, int port,
146  int type, int family, int flags)
147 {
148  struct addrinfo hints = { 0 }, *res = 0;
149  int error;
150  char sport[16];
151  const char *node = 0, *service = "0";
152 
153  if (port > 0) {
154  snprintf(sport, sizeof(sport), "%d", port);
155  service = sport;
156  }
157  if ((hostname) && (hostname[0] != '\0') && (hostname[0] != '?')) {
158  node = hostname;
159  }
160  hints.ai_socktype = type;
161  hints.ai_family = family;
162  hints.ai_flags = flags;
163  if ((error = getaddrinfo(node, service, &hints, &res))) {
164  res = NULL;
165  av_log(NULL, AV_LOG_ERROR, "udp_resolve_host: %s\n", gai_strerror(error));
166  }
167 
168  return res;
169 }
170 
171 static int udp_set_multicast_sources(int sockfd, struct sockaddr *addr,
172  int addr_len, char **sources,
173  int nb_sources, int include)
174 {
175 #if HAVE_STRUCT_GROUP_SOURCE_REQ && defined(MCAST_BLOCK_SOURCE) && !defined(_WIN32)
176  /* These ones are available in the microsoft SDK, but don't seem to work
177  * as on linux, so just prefer the v4-only approach there for now. */
178  int i;
179  for (i = 0; i < nb_sources; i++) {
180  struct group_source_req mreqs;
181  int level = addr->sa_family == AF_INET ? IPPROTO_IP : IPPROTO_IPV6;
182  struct addrinfo *sourceaddr = udp_resolve_host(sources[i], 0,
183  SOCK_DGRAM, AF_UNSPEC,
184  0);
185  if (!sourceaddr)
186  return AVERROR(ENOENT);
187 
188  mreqs.gsr_interface = 0;
189  memcpy(&mreqs.gsr_group, addr, addr_len);
190  memcpy(&mreqs.gsr_source, sourceaddr->ai_addr, sourceaddr->ai_addrlen);
191  freeaddrinfo(sourceaddr);
192 
193  if (setsockopt(sockfd, level,
194  include ? MCAST_JOIN_SOURCE_GROUP : MCAST_BLOCK_SOURCE,
195  (const void *)&mreqs, sizeof(mreqs)) < 0) {
196  if (include)
197  log_net_error(NULL, AV_LOG_ERROR, "setsockopt(MCAST_JOIN_SOURCE_GROUP)");
198  else
199  log_net_error(NULL, AV_LOG_ERROR, "setsockopt(MCAST_BLOCK_SOURCE)");
200  return ff_neterrno();
201  }
202  }
203 #elif HAVE_STRUCT_IP_MREQ_SOURCE && defined(IP_BLOCK_SOURCE)
204  int i;
205  if (addr->sa_family != AF_INET) {
207  "Setting multicast sources only supported for IPv4\n");
208  return AVERROR(EINVAL);
209  }
210  for (i = 0; i < nb_sources; i++) {
211  struct ip_mreq_source mreqs;
212  struct addrinfo *sourceaddr = udp_resolve_host(sources[i], 0,
213  SOCK_DGRAM, AF_UNSPEC,
214  0);
215  if (!sourceaddr)
216  return AVERROR(ENOENT);
217  if (sourceaddr->ai_addr->sa_family != AF_INET) {
218  freeaddrinfo(sourceaddr);
219  av_log(NULL, AV_LOG_ERROR, "%s is of incorrect protocol family\n",
220  sources[i]);
221  return AVERROR(EINVAL);
222  }
223 
224  mreqs.imr_multiaddr.s_addr = ((struct sockaddr_in *)addr)->sin_addr.s_addr;
225  mreqs.imr_interface.s_addr = INADDR_ANY;
226  mreqs.imr_sourceaddr.s_addr = ((struct sockaddr_in *)sourceaddr->ai_addr)->sin_addr.s_addr;
227  freeaddrinfo(sourceaddr);
228 
229  if (setsockopt(sockfd, IPPROTO_IP,
230  include ? IP_ADD_SOURCE_MEMBERSHIP : IP_BLOCK_SOURCE,
231  (const void *)&mreqs, sizeof(mreqs)) < 0) {
232  if (include)
233  log_net_error(NULL, AV_LOG_ERROR, "setsockopt(IP_ADD_SOURCE_MEMBERSHIP)");
234  else
235  log_net_error(NULL, AV_LOG_ERROR, "setsockopt(IP_BLOCK_SOURCE)");
236  return ff_neterrno();
237  }
238  }
239 #else
240  return AVERROR(ENOSYS);
241 #endif
242  return 0;
243 }
244 static int udp_set_url(struct sockaddr_storage *addr,
245  const char *hostname, int port)
246 {
247  struct addrinfo *res0;
248  int addr_len;
249 
250  res0 = udp_resolve_host(hostname, port, SOCK_DGRAM, AF_UNSPEC, 0);
251  if (res0 == 0) return AVERROR(EIO);
252  memcpy(addr, res0->ai_addr, res0->ai_addrlen);
253  addr_len = res0->ai_addrlen;
254  freeaddrinfo(res0);
255 
256  return addr_len;
257 }
258 
259 static int udp_socket_create(UDPContext *s, struct sockaddr_storage *addr,
260  socklen_t *addr_len, const char *localaddr)
261 {
262  int udp_fd = -1;
263  struct addrinfo *res0 = NULL, *res = NULL;
264  int family = AF_UNSPEC;
265 
266  if (((struct sockaddr *) &s->dest_addr)->sa_family)
267  family = ((struct sockaddr *) &s->dest_addr)->sa_family;
268  res0 = udp_resolve_host(localaddr[0] ? localaddr : NULL, s->local_port,
269  SOCK_DGRAM, family, AI_PASSIVE);
270  if (res0 == 0)
271  goto fail;
272  for (res = res0; res; res=res->ai_next) {
273  udp_fd = ff_socket(res->ai_family, SOCK_DGRAM, 0);
274  if (udp_fd != -1) break;
275  log_net_error(NULL, AV_LOG_ERROR, "socket");
276  }
277 
278  if (udp_fd < 0)
279  goto fail;
280 
281  memcpy(addr, res->ai_addr, res->ai_addrlen);
282  *addr_len = res->ai_addrlen;
283 
284  freeaddrinfo(res0);
285 
286  return udp_fd;
287 
288  fail:
289  if (udp_fd >= 0)
290  closesocket(udp_fd);
291  if(res0)
292  freeaddrinfo(res0);
293  return -1;
294 }
295 
296 static int udp_port(struct sockaddr_storage *addr, int addr_len)
297 {
298  char sbuf[sizeof(int)*3+1];
299  int error;
300 
301  if ((error = getnameinfo((struct sockaddr *)addr, addr_len, NULL, 0, sbuf, sizeof(sbuf), NI_NUMERICSERV)) != 0) {
302  av_log(NULL, AV_LOG_ERROR, "getnameinfo: %s\n", gai_strerror(error));
303  return -1;
304  }
305 
306  return strtol(sbuf, NULL, 10);
307 }
308 
309 
325 int ff_udp_set_remote_url(URLContext *h, const char *uri)
326 {
327  UDPContext *s = h->priv_data;
328  char hostname[256], buf[10];
329  int port;
330  const char *p;
331 
332  av_url_split(NULL, 0, NULL, 0, hostname, sizeof(hostname), &port, NULL, 0, uri);
333 
334  /* set the destination address */
335  s->dest_addr_len = udp_set_url(&s->dest_addr, hostname, port);
336  if (s->dest_addr_len < 0) {
337  return AVERROR(EIO);
338  }
339  s->is_multicast = ff_is_multicast_address((struct sockaddr*) &s->dest_addr);
340  p = strchr(uri, '?');
341  if (p) {
342  if (av_find_info_tag(buf, sizeof(buf), "connect", p)) {
343  int was_connected = s->is_connected;
344  s->is_connected = strtol(buf, NULL, 10);
345  if (s->is_connected && !was_connected) {
346  if (connect(s->udp_fd, (struct sockaddr *) &s->dest_addr,
347  s->dest_addr_len)) {
348  s->is_connected = 0;
349  log_net_error(h, AV_LOG_ERROR, "connect");
350  return AVERROR(EIO);
351  }
352  }
353  }
354  }
355 
356  return 0;
357 }
358 
365 {
366  UDPContext *s = h->priv_data;
367  return s->local_port;
368 }
369 
376 {
377  UDPContext *s = h->priv_data;
378  return s->udp_fd;
379 }
380 
381 static int parse_source_list(char *buf, char **sources, int *num_sources,
382  int max_sources)
383 {
384  char *source_start;
385 
386  source_start = buf;
387  while (1) {
388  char *next = strchr(source_start, ',');
389  if (next)
390  *next = '\0';
391  sources[*num_sources] = av_strdup(source_start);
392  if (!sources[*num_sources])
393  return AVERROR(ENOMEM);
394  source_start = next + 1;
395  (*num_sources)++;
396  if (*num_sources >= max_sources || !next)
397  break;
398  }
399  return 0;
400 }
401 
402 /* put it in UDP context */
403 /* return non zero if error */
404 static int udp_open(URLContext *h, const char *uri, int flags)
405 {
406  char hostname[1024], localaddr[1024] = "";
407  int port, udp_fd = -1, tmp, bind_ret = -1;
408  UDPContext *s = h->priv_data;
409  int is_output;
410  const char *p;
411  char buf[256];
412  struct sockaddr_storage my_addr;
413  socklen_t len;
414  int reuse_specified = 0;
415  int i, num_include_sources = 0, num_exclude_sources = 0;
416  char *include_sources[32], *exclude_sources[32];
417 
418  h->is_streamed = 1;
419  h->max_packet_size = 1472;
420 
421  is_output = !(flags & AVIO_FLAG_READ);
422 
423  s->ttl = 16;
424  s->buffer_size = is_output ? UDP_TX_BUF_SIZE : UDP_MAX_PKT_SIZE;
425 
426  p = strchr(uri, '?');
427  if (p) {
428  if (av_find_info_tag(buf, sizeof(buf), "reuse", p)) {
429  char *endptr = NULL;
430  s->reuse_socket = strtol(buf, &endptr, 10);
431  /* assume if no digits were found it is a request to enable it */
432  if (buf == endptr)
433  s->reuse_socket = 1;
434  reuse_specified = 1;
435  }
436  if (av_find_info_tag(buf, sizeof(buf), "ttl", p)) {
437  s->ttl = strtol(buf, NULL, 10);
438  }
439  if (av_find_info_tag(buf, sizeof(buf), "localport", p)) {
440  s->local_port = strtol(buf, NULL, 10);
441  }
442  if (av_find_info_tag(buf, sizeof(buf), "pkt_size", p)) {
443  h->max_packet_size = strtol(buf, NULL, 10);
444  }
445  if (av_find_info_tag(buf, sizeof(buf), "buffer_size", p)) {
446  s->buffer_size = strtol(buf, NULL, 10);
447  }
448  if (av_find_info_tag(buf, sizeof(buf), "connect", p)) {
449  s->is_connected = strtol(buf, NULL, 10);
450  }
451  if (av_find_info_tag(buf, sizeof(buf), "localaddr", p)) {
452  av_strlcpy(localaddr, buf, sizeof(localaddr));
453  }
454  if (av_find_info_tag(buf, sizeof(buf), "sources", p)) {
455  if (parse_source_list(buf, include_sources, &num_include_sources,
456  FF_ARRAY_ELEMS(include_sources)))
457  goto fail;
458  }
459  if (av_find_info_tag(buf, sizeof(buf), "block", p)) {
460  if (parse_source_list(buf, exclude_sources, &num_exclude_sources,
461  FF_ARRAY_ELEMS(exclude_sources)))
462  goto fail;
463  }
464  }
465 
466  /* fill the dest addr */
467  av_url_split(NULL, 0, NULL, 0, hostname, sizeof(hostname), &port, NULL, 0, uri);
468 
469  /* XXX: fix av_url_split */
470  if (hostname[0] == '\0' || hostname[0] == '?') {
471  /* only accepts null hostname if input */
472  if (!(flags & AVIO_FLAG_READ))
473  goto fail;
474  } else {
475  if (ff_udp_set_remote_url(h, uri) < 0)
476  goto fail;
477  }
478 
479  if ((s->is_multicast || !s->local_port) && (h->flags & AVIO_FLAG_READ))
480  s->local_port = port;
481  udp_fd = udp_socket_create(s, &my_addr, &len, localaddr);
482  if (udp_fd < 0)
483  goto fail;
484 
485  /* Follow the requested reuse option, unless it's multicast in which
486  * case enable reuse unless explicitly disabled.
487  */
488  if (s->reuse_socket || (s->is_multicast && !reuse_specified)) {
489  s->reuse_socket = 1;
490  if (setsockopt (udp_fd, SOL_SOCKET, SO_REUSEADDR, &(s->reuse_socket), sizeof(s->reuse_socket)) != 0)
491  goto fail;
492  }
493 
494  /* If multicast, try binding the multicast address first, to avoid
495  * receiving UDP packets from other sources aimed at the same UDP
496  * port. This fails on windows. This makes sending to the same address
497  * using sendto() fail, so only do it if we're opened in read-only mode. */
498  if (s->is_multicast && !(h->flags & AVIO_FLAG_WRITE)) {
499  bind_ret = bind(udp_fd,(struct sockaddr *)&s->dest_addr, len);
500  }
501  /* bind to the local address if not multicast or if the multicast
502  * bind failed */
503  /* the bind is needed to give a port to the socket now */
504  if (bind_ret < 0 && bind(udp_fd,(struct sockaddr *)&my_addr, len) < 0) {
505  log_net_error(h, AV_LOG_ERROR, "bind failed");
506  goto fail;
507  }
508 
509  len = sizeof(my_addr);
510  getsockname(udp_fd, (struct sockaddr *)&my_addr, &len);
511  s->local_port = udp_port(&my_addr, len);
512 
513  if (s->is_multicast) {
514  if (h->flags & AVIO_FLAG_WRITE) {
515  /* output */
516  if (udp_set_multicast_ttl(udp_fd, s->ttl, (struct sockaddr *)&s->dest_addr) < 0)
517  goto fail;
518  }
519  if (h->flags & AVIO_FLAG_READ) {
520  /* input */
521  if (num_include_sources && num_exclude_sources) {
522  av_log(h, AV_LOG_ERROR, "Simultaneously including and excluding multicast sources is not supported\n");
523  goto fail;
524  }
525  if (num_include_sources) {
526  if (udp_set_multicast_sources(udp_fd, (struct sockaddr *)&s->dest_addr, s->dest_addr_len, include_sources, num_include_sources, 1) < 0)
527  goto fail;
528  } else {
529  if (udp_join_multicast_group(udp_fd, (struct sockaddr *)&s->dest_addr) < 0)
530  goto fail;
531  }
532  if (num_exclude_sources) {
533  if (udp_set_multicast_sources(udp_fd, (struct sockaddr *)&s->dest_addr, s->dest_addr_len, exclude_sources, num_exclude_sources, 0) < 0)
534  goto fail;
535  }
536  }
537  }
538 
539  if (is_output) {
540  /* limit the tx buf size to limit latency */
541  tmp = s->buffer_size;
542  if (setsockopt(udp_fd, SOL_SOCKET, SO_SNDBUF, &tmp, sizeof(tmp)) < 0) {
543  log_net_error(h, AV_LOG_ERROR, "setsockopt(SO_SNDBUF)");
544  goto fail;
545  }
546  } else {
547  /* set udp recv buffer size to the largest possible udp packet size to
548  * avoid losing data on OSes that set this too low by default. */
549  tmp = s->buffer_size;
550  if (setsockopt(udp_fd, SOL_SOCKET, SO_RCVBUF, &tmp, sizeof(tmp)) < 0) {
551  log_net_error(h, AV_LOG_WARNING, "setsockopt(SO_RECVBUF)");
552  }
553  /* make the socket non-blocking */
554  ff_socket_nonblock(udp_fd, 1);
555  }
556  if (s->is_connected) {
557  if (connect(udp_fd, (struct sockaddr *) &s->dest_addr, s->dest_addr_len)) {
558  log_net_error(h, AV_LOG_ERROR, "connect");
559  goto fail;
560  }
561  }
562 
563  for (i = 0; i < num_include_sources; i++)
564  av_freep(&include_sources[i]);
565  for (i = 0; i < num_exclude_sources; i++)
566  av_freep(&exclude_sources[i]);
567 
568  s->udp_fd = udp_fd;
569  return 0;
570  fail:
571  if (udp_fd >= 0)
572  closesocket(udp_fd);
573  for (i = 0; i < num_include_sources; i++)
574  av_freep(&include_sources[i]);
575  for (i = 0; i < num_exclude_sources; i++)
576  av_freep(&exclude_sources[i]);
577  return AVERROR(EIO);
578 }
579 
580 static int udp_read(URLContext *h, uint8_t *buf, int size)
581 {
582  UDPContext *s = h->priv_data;
583  int ret;
584 
585  if (!(h->flags & AVIO_FLAG_NONBLOCK)) {
586  ret = ff_network_wait_fd(s->udp_fd, 0);
587  if (ret < 0)
588  return ret;
589  }
590  ret = recv(s->udp_fd, buf, size, 0);
591  return ret < 0 ? ff_neterrno() : ret;
592 }
593 
594 static int udp_write(URLContext *h, const uint8_t *buf, int size)
595 {
596  UDPContext *s = h->priv_data;
597  int ret;
598 
599  if (!(h->flags & AVIO_FLAG_NONBLOCK)) {
600  ret = ff_network_wait_fd(s->udp_fd, 1);
601  if (ret < 0)
602  return ret;
603  }
604 
605  if (!s->is_connected) {
606  ret = sendto (s->udp_fd, buf, size, 0,
607  (struct sockaddr *) &s->dest_addr,
608  s->dest_addr_len);
609  } else
610  ret = send(s->udp_fd, buf, size, 0);
611 
612  return ret < 0 ? ff_neterrno() : ret;
613 }
614 
615 static int udp_close(URLContext *h)
616 {
617  UDPContext *s = h->priv_data;
618 
619  if (s->is_multicast && (h->flags & AVIO_FLAG_READ))
620  udp_leave_multicast_group(s->udp_fd, (struct sockaddr *)&s->dest_addr);
621  closesocket(s->udp_fd);
622  return 0;
623 }
624 
626  .name = "udp",
627  .url_open = udp_open,
628  .url_read = udp_read,
629  .url_write = udp_write,
630  .url_close = udp_close,
631  .url_get_file_handle = udp_get_file_handle,
632  .priv_data_size = sizeof(UDPContext),
634 };
static int udp_open(URLContext *h, const char *uri, int flags)
Definition: udp.c:404
void av_url_split(char *proto, int proto_size, char *authorization, int authorization_size, char *hostname, int hostname_size, int *port_ptr, char *path, int path_size, const char *url)
Split a URL string into components.
Definition: utils.c:2705
static void log_net_error(void *ctx, int level, const char *prefix)
Definition: udp.c:58
int size
#define URL_PROTOCOL_FLAG_NETWORK
Definition: url.h:35
#define NI_NUMERICSERV
Definition: network.h:168
#define AV_LOG_WARNING
Something somehow does not look correct.
Definition: log.h:129
static int udp_set_multicast_sources(int sockfd, struct sockaddr *addr, int addr_len, char **sources, int nb_sources, int include)
Definition: udp.c:171
int is_streamed
true if streamed (no seek possible), default = false
Definition: url.h:48
static int parse_source_list(char *buf, char **sources, int *num_sources, int max_sources)
Definition: udp.c:381
#define AVIO_FLAG_READ
read-only
Definition: avio.h:292
#define AVIO_FLAG_WRITE
write-only
Definition: avio.h:293
#define AI_PASSIVE
Definition: network.h:144
int flags
Definition: url.h:46
#define FF_ARRAY_ELEMS(a)
#define freeaddrinfo
Definition: network.h:183
int ff_socket(int af, int type, int proto)
Definition: network.c:214
void av_freep(void *arg)
Free a memory block which has been allocated with av_malloc(z)() or av_realloc() and set the pointer ...
Definition: mem.c:198
static struct addrinfo * udp_resolve_host(const char *hostname, int port, int type, int family, int flags)
Definition: udp.c:145
uint8_t
miscellaneous OS support macros and functions.
int ff_udp_get_local_port(URLContext *h)
Return the local port used by the UDP connection.
Definition: udp.c:364
static int udp_port(struct sockaddr_storage *addr, int addr_len)
Definition: udp.c:296
static int flags
Definition: log.c:44
int av_find_info_tag(char *arg, int arg_size, const char *tag1, const char *info)
Attempt to find a specific tag in a URL.
Definition: parseutils.c:606
static int udp_close(URLContext *h)
Definition: udp.c:615
#define AV_LOG_ERROR
Something went wrong and cannot losslessly be recovered.
Definition: log.h:123
int ff_udp_set_remote_url(URLContext *h, const char *uri)
If no filename is given to av_open_input_file because you want to get the local port first...
Definition: udp.c:325
#define AVERROR(e)
Definition: error.h:43
int reuse_socket
Definition: udp.c:49
#define UDP_TX_BUF_SIZE
Definition: udp.c:55
void av_log(void *avcl, int level, const char *fmt,...)
Definition: log.c:168
int dest_addr_len
Definition: udp.c:51
int ff_is_multicast_address(struct sockaddr *addr)
Definition: network.c:179
size_t av_strlcpy(char *dst, const char *src, size_t size)
Copy the string src to dst, but no more than size - 1 bytes, and null-terminate dst.
Definition: avstring.c:81
int ai_addrlen
Definition: network.h:107
static int udp_socket_create(UDPContext *s, struct sockaddr_storage *addr, socklen_t *addr_len, const char *localaddr)
Definition: udp.c:259
#define ff_neterrno()
Definition: network.h:63
static int udp_get_file_handle(URLContext *h)
Return the udp file handle for select() usage to wait for several RTP streams at the same time...
Definition: udp.c:375
int is_connected
Definition: udp.c:52
Definition: udp.c:43
int ff_socket_nonblock(int socket, int enable)
static int udp_leave_multicast_group(int sockfd, struct sockaddr *addr)
Definition: udp.c:116
int ttl
Definition: udp.c:45
NULL
Definition: eval.c:55
#define IPV6_ADD_MEMBERSHIP
Definition: udp.c:39
char * av_strdup(const char *s)
Duplicate the string s.
Definition: mem.c:213
#define AVIO_FLAG_NONBLOCK
Use non-blocking mode.
Definition: avio.h:311
int local_port
Definition: udp.c:48
#define IPV6_DROP_MEMBERSHIP
Definition: udp.c:40
Definition: url.h:41
static int udp_set_url(struct sockaddr_storage *addr, const char *hostname, int port)
Definition: udp.c:244
void * priv_data
Definition: url.h:44
#define gai_strerror
Definition: network.h:190
misc parsing utilities
const char * name
Definition: url.h:54
int ai_socktype
Definition: network.h:105
uint8_t level
Definition: svq3.c:147
int av_strerror(int errnum, char *errbuf, size_t errbuf_size)
Put a description of the AVERROR code errnum in errbuf.
Definition: error.c:23
#define getaddrinfo
Definition: network.h:182
Main libavformat public API header.
URLProtocol ff_udp_protocol
Definition: udp.c:625
struct sockaddr_storage dest_addr
Definition: udp.c:50
static int udp_read(URLContext *h, uint8_t *buf, int size)
Definition: udp.c:580
struct addrinfo * ai_next
Definition: network.h:110
static int udp_set_multicast_ttl(int sockfd, int mcastTTL, struct sockaddr *addr)
Definition: udp.c:65
int udp_fd
Definition: udp.c:44
#define getnameinfo
Definition: network.h:184
int len
int buffer_size
Definition: udp.c:46
int is_multicast
Definition: udp.c:47
int ai_flags
Definition: network.h:103
int max_packet_size
if non zero, the stream is packetized with this max packet size
Definition: url.h:47
#define UDP_MAX_PKT_SIZE
Definition: udp.c:56
int ff_network_wait_fd(int fd, int write)
Definition: network.c:141
unbuffered private I/O API
static int udp_join_multicast_group(int sockfd, struct sockaddr *addr)
Definition: udp.c:87
struct sockaddr * ai_addr
Definition: network.h:108
static int udp_write(URLContext *h, const uint8_t *buf, int size)
Definition: udp.c:594
int ai_family
Definition: network.h:104