On Fri, 25 May 2012, Martin Storsjö wrote:

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...

Attached is a slightly cleaned up version, although I haven't tested it. Aviad, does this still work for you?

// Martin
From b800fb171c6e73200d53aee0e214d8bdbff75dff 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: Support IGMPv3 source specific multicast and source
 blocking

TODO:
- Docs
---
 configure         |    3 ++
 libavformat/udp.c |   88 +++++++++++++++++++++++++++++++++++++++++++++++++++--
 2 files changed, 89 insertions(+), 2 deletions(-)

diff --git a/configure b/configure
index 67371c8..b9cdbaf 100755
--- a/configure
+++ b/configure
@@ -1124,6 +1124,7 @@ HAVE_LIST="
     strptime
     strtok_r
     struct_addrinfo
+    struct_ip_mreq_source
     struct_ipv6_mreq
     struct_rusage_ru_maxrss
     struct_sockaddr_in6
@@ -2786,6 +2787,7 @@ fi
 if enabled network; then
     check_type "sys/types.h sys/socket.h" socklen_t
     check_type netdb.h "struct addrinfo"
+    check_type netinet/in.h "struct ip_mreq_source" -D_BSD_SOURCE
     check_type netinet/in.h "struct ipv6_mreq" -D_DARWIN_C_SOURCE
     check_type netinet/in.h "struct sockaddr_in6"
     check_type "sys/types.h sys/socket.h" "struct sockaddr_storage"
@@ -2801,6 +2803,7 @@ if enabled network; then
             network_extralibs="-lws2_32"; }
         check_type ws2tcpip.h socklen_t
         check_type ws2tcpip.h "struct addrinfo"
+        check_type ws2tcpip.h "struct ip_mreq_source"
         check_type ws2tcpip.h "struct ipv6_mreq"
         check_type ws2tcpip.h "struct sockaddr_in6"
         check_type ws2tcpip.h "struct sockaddr_storage"
diff --git a/libavformat/udp.c b/libavformat/udp.c
index 6571ab5..bba2d95 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
@@ -163,6 +166,48 @@ static struct addrinfo* udp_resolve_host(const char *hostname, int port,
     return res;
 }
 
+static int udp_set_multicast_sources(int sockfd, struct sockaddr *addr,
+                                     char **sources, int nb_sources,
+                                     int include)
+{
+    int i;
+    if (addr->sa_family != AF_INET) {
+        av_log(NULL, AV_LOG_ERROR,
+               "Setting multicast sources only supported for IPv4 for now\n");
+        return -1;
+    }
+#if HAVE_STRUCT_IP_MREQ_SOURCE && defined(IP_BLOCK_SOURCE)
+    for (i = 0; i < nb_sources; i++) {
+        struct ip_mreq_source mreqs;
+        struct addrinfo *sourceaddr = udp_resolve_host(sources[i], 0,
+                                                       SOCK_DGRAM, AF_UNSPEC,
+                                                       AI_NUMERICHOST);
+        if (!sourceaddr)
+            return -1;
+        if (sourceaddr->ai_addr->sa_family != AF_INET) {
+            freeaddrinfo(sourceaddr);
+            av_log(NULL, AV_LOG_ERROR, "%s is of incorrect protocol family\n",
+                   sources[i]);
+            return -1;
+        }
+
+        mreqs.imr_multiaddr.s_addr = ((struct sockaddr_in *)addr)->sin_addr.s_addr;
+        mreqs.imr_interface.s_addr = INADDR_ANY;
+        mreqs.imr_sourceaddr.s_addr = ((struct sockaddr_in *)sourceaddr->ai_addr)->sin_addr.s_addr;
+        freeaddrinfo(sourceaddr);
+
+        if (setsockopt(sockfd, IPPROTO_IP,
+                       include ? IP_ADD_SOURCE_MEMBERSHIP : IP_BLOCK_SOURCE,
+                       (const void *)&mreqs, sizeof(mreqs)) < 0) {
+            av_log(NULL, AV_LOG_ERROR, "setsockopt(%s): %s\n",
+                   include ? "IP_ADD_SOURCE_MEMBERSHIP" : "IP_BLOCK_SOURCE",
+                   strerror(errno));
+            return -1;
+        }
+    }
+#endif
+    return 0;
+}
 static int udp_set_url(struct sockaddr_storage *addr,
                        const char *hostname, int port)
 {
@@ -310,7 +355,7 @@ static int udp_open(URLContext *h, const char *uri, int flags)
     const char *p;
     char buf[256];
     struct sockaddr_storage my_addr;
-    int len;
+    int len, i;
     int reuse_specified = 0;
 
     h->is_streamed = 1;
@@ -349,6 +394,26 @@ 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)) {
+            char *source_start;
+
+            source_start = buf;
+            while (1) {
+                char *next = strchr(source_start, ',');
+                if (next)
+                    *next = '\0';
+                s->sources[s->num_sources] = av_strdup(source_start);
+                if (!s->sources[s->num_sources])
+                    goto fail;
+                source_start = next + 1;
+                s->num_sources++;
+                if (s->num_sources >= FF_ARRAY_ELEMS(s->sources) || !next)
+                    break;
+            }
+        }
     }
 
     /* fill the dest addr */
@@ -406,8 +471,21 @@ static int udp_open(URLContext *h, const char *uri, int flags)
         }
         if (h->flags & AVIO_FLAG_READ) {
             /* input */
-            if (udp_join_multicast_group(udp_fd, (struct sockaddr *)&s->dest_addr) < 0)
+            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_set_multicast_sources(udp_fd, (struct sockaddr *)&s->dest_addr, s->sources, s->num_sources, 0) < 0)
+                        goto fail;
+                }
+            } else if (s->include && s->num_sources) {
+                if (udp_set_multicast_sources(udp_fd, (struct sockaddr *)&s->dest_addr, s->sources, s->num_sources, 1) < 0)
+                    goto fail;
+            } else {
+                av_log(NULL, AV_LOG_ERROR, "invalid udp settings: inclusive multicast but no sources given\n");
                 goto fail;
+            }
         }
     }
 
@@ -440,6 +518,8 @@ static int udp_open(URLContext *h, const char *uri, int flags)
  fail:
     if (udp_fd >= 0)
         closesocket(udp_fd);
+    for (i = 0; i < s->num_sources; i++)
+        av_free(s->sources[i]);
     return AVERROR(EIO);
 }
 
@@ -481,6 +561,10 @@ 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

Reply via email to