On Thu, 24 May 2012, Martin Storsjö wrote:
On Thu, 24 May 2012, aviad rozenhek wrote:
On Sun, May 20, 2012 at 8:10 PM, aviad rozenhek <[email protected]> wrote:
>> I had a copy of the old mail and have added it to
my local git repo. I'll
>> add it to my todo list to try to rebase it on top
of the latest version and
>> have a look at it...
>>
>> // Martin
>
>
> thanks! I actually just managed to find it by
including omitted search
> results from google ... :-)
>
Seems straightforward, just needs some changes to fit with the
new udp
proto indeed.
lu
did you have a chance to rebase the patch?
if you can provide a build, I have a test environment I can run it on.
Sorry, haven't gotten to this yet.
Here's a rebased version. I haven't touched at all yet, it doesn't compile
on OS X, but seems to compile on Linux. I'll try to have a closer look at
it later...
// Martin
From f7b949a97b136ece3e7a433728d8f5f9ae034294 Mon Sep 17 00:00:00 2001
From: Stephen D'Angelo <[email protected]>
Date: Tue, 15 May 2012 14:07:05 +0300
Subject: [PATCH] UDP IGMPv3 source specific multicast and source blocking
---
libavformat/udp.c | 101 +++++++++++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 101 insertions(+)
diff --git a/libavformat/udp.c b/libavformat/udp.c
index 6571ab5..cbfab8c 100644
--- a/libavformat/udp.c
+++ b/libavformat/udp.c
@@ -52,6 +52,9 @@ typedef struct {
struct sockaddr_storage dest_addr;
int dest_addr_len;
int is_connected;
+ int include;
+ char * sources[32];
+ int num_sources;
} UDPContext;
#define UDP_TX_BUF_SIZE 32768
@@ -137,6 +140,53 @@ static int udp_leave_multicast_group(int sockfd, struct sockaddr *addr)
return 0;
}
+
+static int udp_block_multicast_sources(int sockfd, struct sockaddr *addr, char **sources, int nb_sources)
+{
+ int i;
+ for(i=0; i<nb_sources; ++i) {
+ struct ip_mreq_source mreqs;
+
+ mreqs.imr_multiaddr.s_addr = ((struct sockaddr_in *)addr)->sin_addr.s_addr;
+ mreqs.imr_interface.s_addr = INADDR_ANY;
+ if (inet_pton(AF_INET, sources[i], &mreqs.imr_sourceaddr.s_addr) < 0) {
+ av_log(NULL, AV_LOG_ERROR, "inet_pton(%s): %s\n", sources[i], strerror(errno));
+ return -1;
+ }
+
+ if (setsockopt(sockfd, IPPROTO_IP, IP_BLOCK_SOURCE, (const void *)&mreqs, sizeof(mreqs)) < 0) {
+ av_log(NULL, AV_LOG_ERROR, "setsockopt(IP_BLOCK_SOURCE): %s\n", strerror(errno));
+ return -1;
+ }
+ }
+
+ return 0;
+}
+
+
+static int udp_add_multicast_sources(int sockfd, struct sockaddr *addr, char **sources, int nb_sources)
+{
+ int i;
+ for(i=0; i<nb_sources; ++i) {
+ struct ip_mreq_source mreqs;
+
+ mreqs.imr_multiaddr.s_addr = ((struct sockaddr_in *)addr)->sin_addr.s_addr;
+ mreqs.imr_interface.s_addr = INADDR_ANY;
+ if (inet_pton(AF_INET, sources[i], &mreqs.imr_sourceaddr.s_addr) < 0) {
+ av_log(NULL, AV_LOG_ERROR, "inet_pton(%s): %s\n", sources[i], strerror(errno));
+ return -1;
+ }
+
+ if (setsockopt(sockfd, IPPROTO_IP, IP_ADD_SOURCE_MEMBERSHIP, (const void *)&mreqs, sizeof(mreqs)) < 0) {
+ av_log(NULL, AV_LOG_ERROR, "setsockopt(IP_ADD_SOURCE_MEMBERSHIP): %s\n", strerror(errno));
+ return -1;
+ }
+ }
+
+ return 0;
+}
+
+
static struct addrinfo* udp_resolve_host(const char *hostname, int port,
int type, int family, int flags)
{
@@ -320,6 +370,7 @@ static int udp_open(URLContext *h, const char *uri, int flags)
s->ttl = 16;
s->buffer_size = is_output ? UDP_TX_BUF_SIZE : UDP_MAX_PKT_SIZE;
+ s->num_sources = 0;
p = strchr(uri, '?');
if (p) {
@@ -349,6 +400,37 @@ static int udp_open(URLContext *h, const char *uri, int flags)
if (av_find_info_tag(buf, sizeof(buf), "localaddr", p)) {
av_strlcpy(localaddr, buf, sizeof(localaddr));
}
+ if (av_find_info_tag(buf, sizeof(buf), "include", p)) {
+ s->include = strtol(buf, NULL, 10);
+ }
+ if (av_find_info_tag(buf, sizeof(buf), "sources", p)) {
+ int source_num;
+ int source_len;
+ char *p1;
+ char *source_start;
+
+ p1 = buf;
+ source_start = p1;
+ source_num = 0;
+ for(;;) {
+ if (p1 == (buf + sizeof(buf))) {
+ break;
+ }
+ if (*p1 == ',' || *p1 == '\0') {
+ source_len = p1 - source_start;
+ s->sources[source_num] = av_malloc(sizeof(char)*source_len+1);
+ memcpy(s->sources[source_num], source_start, source_len);
+ s->sources[source_num][source_len] = 0;
+ source_start = p1 + 1;
+ ++source_num;
+ if (source_num > 32 || *p1 == '\0') {
+ break;
+ }
+ }
+ ++p1;
+ }
+ s->num_sources = source_num;
+ }
}
/* fill the dest addr */
@@ -406,8 +488,22 @@ static int udp_open(URLContext *h, const char *uri, int flags)
}
if (h->flags & AVIO_FLAG_READ) {
/* input */
+ if (s->num_sources == 0 || !s->include) {
if (udp_join_multicast_group(udp_fd, (struct sockaddr *)&s->dest_addr) < 0)
goto fail;
+
+ if (s->num_sources) {
+ if (udp_block_multicast_sources(udp_fd, (struct sockaddr *)&s->dest_addr, s->sources, s->num_sources) < 0)
+ goto fail;
+ }
+ } else if (s->include && s->num_sources) {
+ if (udp_add_multicast_sources(udp_fd, (struct sockaddr *)&s->dest_addr, s->sources, s->num_sources) < 0)
+ goto fail;
+ }
+ else {
+ av_log(NULL, AV_LOG_ERROR, "invalid udp settings: inclusive multicast but no sources given\n");
+ goto fail;
+ }
}
}
@@ -481,6 +577,11 @@ static int udp_write(URLContext *h, const uint8_t *buf, int size)
static int udp_close(URLContext *h)
{
UDPContext *s = h->priv_data;
+ int i;
+
+ for(i=0; i<s->num_sources; ++i) {
+ av_free(s->sources[i]);
+ }
if (s->is_multicast && (h->flags & AVIO_FLAG_READ))
udp_leave_multicast_group(s->udp_fd, (struct sockaddr *)&s->dest_addr);
--
1.7.9.4
_______________________________________________
libav-devel mailing list
[email protected]
https://lists.libav.org/mailman/listinfo/libav-devel