udp: Allow specifying the local IP address

Message ID 1320833054-99986-1-git-send-email-martin@martin.st
State Committed
Commit 65ac51373b7e6a2e2bf4e8131acfda32c0708034
Headers show

Commit Message

Martin Storsjö Nov. 9, 2011, 10:04 a.m.
This is useful if sending multicast data on a host with
multiple interfaces.
---
 doc/protocols.texi |    5 +++++
 libavformat/udp.c  |   15 ++++++++++-----
 2 files changed, 15 insertions(+), 5 deletions(-)

Comments

Luca Barbato Nov. 9, 2011, 5:53 p.m. | #1
On 11/9/11 2:04 AM, Martin Storsjö wrote:
> This is useful if sending multicast data on a host with
> multiple interfaces.

Looks good.

Patch

diff --git a/doc/protocols.texi b/doc/protocols.texi
index 8aee5f6..f06546c 100644
--- a/doc/protocols.texi
+++ b/doc/protocols.texi
@@ -446,6 +446,11 @@  set the UDP buffer size in bytes
 @item localport=@var{port}
 override the local UDP port to bind with
 
+@item localaddr=@var{addr}
+Choose the local IP address. This is useful e.g. if sending multicast
+and the host has multiple interfaces, where the user can choose
+which interface to send on by specifying the IP address of that interface.
+
 @item pkt_size=@var{size}
 set the size in bytes of UDP packets
 
diff --git a/libavformat/udp.c b/libavformat/udp.c
index bd95a81..178cef4 100644
--- a/libavformat/udp.c
+++ b/libavformat/udp.c
@@ -29,6 +29,7 @@ 
 #include "avformat.h"
 #include "avio_internal.h"
 #include "libavutil/parseutils.h"
+#include "libavutil/avstring.h"
 #include <unistd.h>
 #include "internal.h"
 #include "network.h"
@@ -178,8 +179,8 @@  static int udp_set_url(struct sockaddr_storage *addr,
     return addr_len;
 }
 
-static int udp_socket_create(UDPContext *s,
-                             struct sockaddr_storage *addr, int *addr_len)
+static int udp_socket_create(UDPContext *s, struct sockaddr_storage *addr,
+                             int *addr_len, const char *localaddr)
 {
     int udp_fd = -1;
     struct addrinfo *res0 = NULL, *res = NULL;
@@ -187,7 +188,8 @@  static int udp_socket_create(UDPContext *s,
 
     if (((struct sockaddr *) &s->dest_addr)->sa_family)
         family = ((struct sockaddr *) &s->dest_addr)->sa_family;
-    res0 = udp_resolve_host(0, s->local_port, SOCK_DGRAM, family, AI_PASSIVE);
+    res0 = udp_resolve_host(localaddr[0] ? localaddr : NULL, s->local_port,
+                            SOCK_DGRAM, family, AI_PASSIVE);
     if (res0 == 0)
         goto fail;
     for (res = res0; res; res=res->ai_next) {
@@ -302,7 +304,7 @@  static int udp_get_file_handle(URLContext *h)
 /* return non zero if error */
 static int udp_open(URLContext *h, const char *uri, int flags)
 {
-    char hostname[1024];
+    char hostname[1024], localaddr[1024] = "";
     int port, udp_fd = -1, tmp, bind_ret = -1;
     UDPContext *s = NULL;
     int is_output;
@@ -350,6 +352,9 @@  static int udp_open(URLContext *h, const char *uri, int flags)
         if (av_find_info_tag(buf, sizeof(buf), "connect", p)) {
             s->is_connected = strtol(buf, NULL, 10);
         }
+        if (av_find_info_tag(buf, sizeof(buf), "localaddr", p)) {
+            av_strlcpy(localaddr, buf, sizeof(localaddr));
+        }
     }
 
     /* fill the dest addr */
@@ -367,7 +372,7 @@  static int udp_open(URLContext *h, const char *uri, int flags)
 
     if ((s->is_multicast || !s->local_port) && (h->flags & AVIO_FLAG_READ))
         s->local_port = port;
-    udp_fd = udp_socket_create(s, &my_addr, &len);
+    udp_fd = udp_socket_create(s, &my_addr, &len, localaddr);
     if (udp_fd < 0)
         goto fail;