Commit 7d99c929 authored by Ed Torbett's avatar Ed Torbett Committed by Martin Storsjö

udp: Keep track of include and exclude sources separately

This allows us to explicitly fail if the caller tried to set
both inclusions and exclusions at the same time.
Signed-off-by: 's avatarMartin Storsjö <martin@martin.st>
parent 3357bccc
...@@ -378,6 +378,27 @@ static int udp_get_file_handle(URLContext *h) ...@@ -378,6 +378,27 @@ static int udp_get_file_handle(URLContext *h)
return s->udp_fd; return s->udp_fd;
} }
static int parse_source_list(char *buf, char **sources, int *num_sources,
int max_sources)
{
char *source_start;
source_start = buf;
while (1) {
char *next = strchr(source_start, ',');
if (next)
*next = '\0';
sources[*num_sources] = av_strdup(source_start);
if (!sources[*num_sources])
return AVERROR(ENOMEM);
source_start = next + 1;
(*num_sources)++;
if (*num_sources >= max_sources || !next)
break;
}
return 0;
}
/* put it in UDP context */ /* put it in UDP context */
/* return non zero if error */ /* return non zero if error */
static int udp_open(URLContext *h, const char *uri, int flags) static int udp_open(URLContext *h, const char *uri, int flags)
...@@ -391,8 +412,8 @@ static int udp_open(URLContext *h, const char *uri, int flags) ...@@ -391,8 +412,8 @@ static int udp_open(URLContext *h, const char *uri, int flags)
struct sockaddr_storage my_addr; struct sockaddr_storage my_addr;
socklen_t len; socklen_t len;
int reuse_specified = 0; int reuse_specified = 0;
int i, include = 0, num_sources = 0; int i, num_include_sources = 0, num_exclude_sources = 0;
char *sources[32]; char *include_sources[32], *exclude_sources[32];
h->is_streamed = 1; h->is_streamed = 1;
h->max_packet_size = 1472; h->max_packet_size = 1472;
...@@ -430,24 +451,15 @@ static int udp_open(URLContext *h, const char *uri, int flags) ...@@ -430,24 +451,15 @@ static int udp_open(URLContext *h, const char *uri, int flags)
if (av_find_info_tag(buf, sizeof(buf), "localaddr", p)) { if (av_find_info_tag(buf, sizeof(buf), "localaddr", p)) {
av_strlcpy(localaddr, buf, sizeof(localaddr)); av_strlcpy(localaddr, buf, sizeof(localaddr));
} }
if (av_find_info_tag(buf, sizeof(buf), "sources", p)) if (av_find_info_tag(buf, sizeof(buf), "sources", p)) {
include = 1; if (parse_source_list(buf, include_sources, &num_include_sources,
if (include || av_find_info_tag(buf, sizeof(buf), "block", p)) { FF_ARRAY_ELEMS(include_sources)))
char *source_start; goto fail;
}
source_start = buf; if (av_find_info_tag(buf, sizeof(buf), "block", p)) {
while (1) { if (parse_source_list(buf, exclude_sources, &num_exclude_sources,
char *next = strchr(source_start, ','); FF_ARRAY_ELEMS(exclude_sources)))
if (next) goto fail;
*next = '\0';
sources[num_sources] = av_strdup(source_start);
if (!sources[num_sources])
goto fail;
source_start = next + 1;
num_sources++;
if (num_sources >= FF_ARRAY_ELEMS(sources) || !next)
break;
}
} }
} }
...@@ -506,20 +518,20 @@ static int udp_open(URLContext *h, const char *uri, int flags) ...@@ -506,20 +518,20 @@ static int udp_open(URLContext *h, const char *uri, int flags)
} }
if (h->flags & AVIO_FLAG_READ) { if (h->flags & AVIO_FLAG_READ) {
/* input */ /* input */
if (num_sources == 0 || !include) { if (num_include_sources && num_exclude_sources) {
av_log(h, AV_LOG_ERROR, "Simultaneously including and excluding multicast sources is not supported\n");
goto fail;
}
if (num_include_sources) {
if (udp_set_multicast_sources(udp_fd, (struct sockaddr *)&s->dest_addr, s->dest_addr_len, include_sources, num_include_sources, 1) < 0)
goto fail;
} else {
if (udp_join_multicast_group(udp_fd, (struct sockaddr *)&s->dest_addr) < 0) if (udp_join_multicast_group(udp_fd, (struct sockaddr *)&s->dest_addr) < 0)
goto fail; goto fail;
}
if (num_sources) { if (num_exclude_sources) {
if (udp_set_multicast_sources(udp_fd, (struct sockaddr *)&s->dest_addr, s->dest_addr_len, sources, num_sources, 0) < 0) if (udp_set_multicast_sources(udp_fd, (struct sockaddr *)&s->dest_addr, s->dest_addr_len, exclude_sources, num_exclude_sources, 0) < 0)
goto fail;
}
} else if (include && num_sources) {
if (udp_set_multicast_sources(udp_fd, (struct sockaddr *)&s->dest_addr, s->dest_addr_len, sources, num_sources, 1) < 0)
goto fail; goto fail;
} else {
av_log(NULL, AV_LOG_ERROR, "invalid udp settings: inclusive multicast but no sources given\n");
goto fail;
} }
} }
} }
...@@ -548,16 +560,20 @@ static int udp_open(URLContext *h, const char *uri, int flags) ...@@ -548,16 +560,20 @@ static int udp_open(URLContext *h, const char *uri, int flags)
} }
} }
for (i = 0; i < num_sources; i++) for (i = 0; i < num_include_sources; i++)
av_free(sources[i]); av_freep(&include_sources[i]);
for (i = 0; i < num_exclude_sources; i++)
av_freep(&exclude_sources[i]);
s->udp_fd = udp_fd; s->udp_fd = udp_fd;
return 0; return 0;
fail: fail:
if (udp_fd >= 0) if (udp_fd >= 0)
closesocket(udp_fd); closesocket(udp_fd);
for (i = 0; i < num_sources; i++) for (i = 0; i < num_include_sources; i++)
av_free(sources[i]); av_freep(&include_sources[i]);
for (i = 0; i < num_exclude_sources; i++)
av_freep(&exclude_sources[i]);
return AVERROR(EIO); return AVERROR(EIO);
} }
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment