31 #include "libavutil/parseutils.h"
32 #include "libavutil/avstring.h"
38 #ifndef IPV6_ADD_MEMBERSHIP
39 #define IPV6_ADD_MEMBERSHIP IPV6_JOIN_GROUP
40 #define IPV6_DROP_MEMBERSHIP IPV6_LEAVE_GROUP
55 #define UDP_TX_BUF_SIZE 32768
56 #define UDP_MAX_PKT_SIZE 65536
62 av_log(ctx, level,
"%s: %s\n", prefix, errbuf);
66 struct sockaddr *addr)
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) {
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) {
89 #ifdef IP_ADD_MEMBERSHIP
90 if (addr->sa_family == AF_INET) {
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) {
101 #if HAVE_STRUCT_IPV6_MREQ && defined(IPPROTO_IPV6)
102 if (addr->sa_family == AF_INET6) {
103 struct ipv6_mreq mreq6;
105 memcpy(&mreq6.ipv6mr_multiaddr, &(((
struct sockaddr_in6 *)addr)->sin6_addr),
sizeof(
struct in6_addr));
106 mreq6.ipv6mr_interface= 0;
118 #ifdef IP_DROP_MEMBERSHIP
119 if (addr->sa_family == AF_INET) {
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) {
130 #if HAVE_STRUCT_IPV6_MREQ && defined(IPPROTO_IPV6)
131 if (addr->sa_family == AF_INET6) {
132 struct ipv6_mreq mreq6;
134 memcpy(&mreq6.ipv6mr_multiaddr, &(((
struct sockaddr_in6 *)addr)->sin6_addr),
sizeof(
struct in6_addr));
135 mreq6.ipv6mr_interface= 0;
146 int type,
int family,
int flags)
148 struct addrinfo hints = { 0 }, *res = 0;
151 const char *node = 0, *service =
"0";
154 snprintf(sport,
sizeof(sport),
"%d", port);
157 if ((hostname) && (hostname[0] !=
'\0') && (hostname[0] !=
'?')) {
163 if ((error =
getaddrinfo(node, service, &hints, &res))) {
172 int addr_len,
char **sources,
173 int nb_sources,
int include)
175 #if HAVE_STRUCT_GROUP_SOURCE_REQ && defined(MCAST_BLOCK_SOURCE) && !defined(_WIN32)
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;
183 SOCK_DGRAM, AF_UNSPEC,
188 mreqs.gsr_interface = 0;
189 memcpy(&mreqs.gsr_group, addr, addr_len);
193 if (setsockopt(sockfd, level,
194 include ? MCAST_JOIN_SOURCE_GROUP : MCAST_BLOCK_SOURCE,
195 (
const void *)&mreqs,
sizeof(mreqs)) < 0) {
203 #elif HAVE_STRUCT_IP_MREQ_SOURCE && defined(IP_BLOCK_SOURCE)
205 if (addr->sa_family != AF_INET) {
207 "Setting multicast sources only supported for IPv4\n");
210 for (i = 0; i < nb_sources; i++) {
211 struct ip_mreq_source mreqs;
213 SOCK_DGRAM, AF_UNSPEC,
217 if (sourceaddr->
ai_addr->sa_family != AF_INET) {
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;
229 if (setsockopt(sockfd, IPPROTO_IP,
230 include ? IP_ADD_SOURCE_MEMBERSHIP : IP_BLOCK_SOURCE,
231 (
const void *)&mreqs,
sizeof(mreqs)) < 0) {
245 const char *hostname,
int port)
251 if (res0 == 0)
return AVERROR(EIO);
260 socklen_t *addr_len,
const char *localaddr)
264 int family = AF_UNSPEC;
266 if (((
struct sockaddr *) &s->
dest_addr)->sa_family)
267 family = ((
struct sockaddr *) &s->
dest_addr)->sa_family;
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;
281 memcpy(addr, res->ai_addr, res->ai_addrlen);
282 *addr_len = res->ai_addrlen;
298 char sbuf[
sizeof(int)*3+1];
306 return strtol(sbuf,
NULL, 10);
328 char hostname[256], buf[10];
340 p = strchr(uri,
'?');
388 char *next = strchr(source_start,
',');
391 sources[*num_sources] =
av_strdup(source_start);
392 if (!sources[*num_sources])
394 source_start = next + 1;
396 if (*num_sources >= max_sources || !next)
406 char hostname[1024], localaddr[1024] =
"";
407 int port, udp_fd = -1, tmp, bind_ret = -1;
414 int reuse_specified = 0;
415 int i, num_include_sources = 0, num_exclude_sources = 0;
416 char *include_sources[32], *exclude_sources[32];
426 p = strchr(uri,
'?');
437 s->
ttl = strtol(buf,
NULL, 10);
452 av_strlcpy(localaddr, buf,
sizeof(localaddr));
470 if (hostname[0] ==
'\0' || hostname[0] ==
'?') {
499 bind_ret = bind(udp_fd,(
struct sockaddr *)&s->
dest_addr, len);
504 if (bind_ret < 0 && bind(udp_fd,(
struct sockaddr *)&my_addr, len) < 0) {
509 len =
sizeof(my_addr);
510 getsockname(udp_fd, (
struct sockaddr *)&my_addr, &len);
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");
525 if (num_include_sources) {
532 if (num_exclude_sources) {
542 if (setsockopt(udp_fd, SOL_SOCKET, SO_SNDBUF, &tmp,
sizeof(tmp)) < 0) {
550 if (setsockopt(udp_fd, SOL_SOCKET, SO_RCVBUF, &tmp,
sizeof(tmp)) < 0) {
563 for (i = 0; i < num_include_sources; i++)
565 for (i = 0; i < num_exclude_sources; i++)
573 for (i = 0; i < num_include_sources; i++)
575 for (i = 0; i < num_exclude_sources; i++)
590 ret = recv(s->
udp_fd, buf, size, 0);
606 ret = sendto (s->
udp_fd, buf, size, 0,
610 ret = send(s->
udp_fd, buf, size, 0);
static int udp_open(URLContext *h, const char *uri, int flags)
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.
static void log_net_error(void *ctx, int level, const char *prefix)
#define URL_PROTOCOL_FLAG_NETWORK
#define AV_LOG_WARNING
Something somehow does not look correct.
char * av_strdup(const char *s) av_malloc_attrib
Duplicate the string s.
static int udp_set_multicast_sources(int sockfd, struct sockaddr *addr, int addr_len, char **sources, int nb_sources, int include)
int is_streamed
true if streamed (no seek possible), default = false
static int parse_source_list(char *buf, char **sources, int *num_sources, int max_sources)
void av_log(void *avcl, int level, const char *fmt,...) av_printf_format(3
Send the specified message to the log if the level is less than or equal to the current av_log_level...
int ff_socket(int af, int type, int proto)
void av_freep(void *ptr)
Free a memory block which has been allocated with av_malloc(z)() or av_realloc() and set the pointer ...
static struct addrinfo * udp_resolve_host(const char *hostname, int port, int type, int family, int flags)
miscellaneous OS support macros and functions.
int ff_udp_get_local_port(URLContext *h)
Return the local port used by the UDP connection.
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.
static int udp_port(struct sockaddr_storage *addr, int addr_len)
static int udp_close(URLContext *h)
#define AV_LOG_ERROR
Something went wrong and cannot losslessly be recovered.
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...
int ff_is_multicast_address(struct sockaddr *addr)
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.
static int udp_socket_create(UDPContext *s, struct sockaddr_storage *addr, socklen_t *addr_len, const char *localaddr)
#define FF_ARRAY_ELEMS(a)
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...
int ff_socket_nonblock(int socket, int enable)
static int udp_leave_multicast_group(int sockfd, struct sockaddr *addr)
#define IPV6_ADD_MEMBERSHIP
#define IPV6_DROP_MEMBERSHIP
static int udp_set_url(struct sockaddr_storage *addr, const char *hostname, int port)
int av_strerror(int errnum, char *errbuf, size_t errbuf_size)
Put a description of the AVERROR code errnum in errbuf.
URLProtocol ff_udp_protocol
struct sockaddr_storage dest_addr
static int udp_read(URLContext *h, uint8_t *buf, int size)
struct addrinfo * ai_next
static int udp_set_multicast_ttl(int sockfd, int mcastTTL, struct sockaddr *addr)
int max_packet_size
if non zero, the stream is packetized with this max packet size
int ff_network_wait_fd(int fd, int write)
unbuffered private I/O API
static int udp_join_multicast_group(int sockfd, struct sockaddr *addr)
struct sockaddr * ai_addr
static int udp_write(URLContext *h, const uint8_t *buf, int size)