Browse code

udp: Allow specifying the local IP address

This is useful if sending multicast data on a host with
multiple interfaces.

Signed-off-by: Martin Storsjö <martin@martin.st>

Martin Storsjö authored on 2011/11/09 18:45:01
Showing 2 changed files
... ...
@@ -446,6 +446,11 @@ set the UDP buffer size in bytes
446 446
 @item localport=@var{port}
447 447
 override the local UDP port to bind with
448 448
 
449
+@item localaddr=@var{addr}
450
+Choose the local IP address. This is useful e.g. if sending multicast
451
+and the host has multiple interfaces, where the user can choose
452
+which interface to send on by specifying the IP address of that interface.
453
+
449 454
 @item pkt_size=@var{size}
450 455
 set the size in bytes of UDP packets
451 456
 
... ...
@@ -29,6 +29,7 @@
29 29
 #include "avformat.h"
30 30
 #include "avio_internal.h"
31 31
 #include "libavutil/parseutils.h"
32
+#include "libavutil/avstring.h"
32 33
 #include <unistd.h>
33 34
 #include "internal.h"
34 35
 #include "network.h"
... ...
@@ -178,8 +179,8 @@ static int udp_set_url(struct sockaddr_storage *addr,
178 178
     return addr_len;
179 179
 }
180 180
 
181
-static int udp_socket_create(UDPContext *s,
182
-                             struct sockaddr_storage *addr, int *addr_len)
181
+static int udp_socket_create(UDPContext *s, struct sockaddr_storage *addr,
182
+                             int *addr_len, const char *localaddr)
183 183
 {
184 184
     int udp_fd = -1;
185 185
     struct addrinfo *res0 = NULL, *res = NULL;
... ...
@@ -187,7 +188,8 @@ static int udp_socket_create(UDPContext *s,
187 187
 
188 188
     if (((struct sockaddr *) &s->dest_addr)->sa_family)
189 189
         family = ((struct sockaddr *) &s->dest_addr)->sa_family;
190
-    res0 = udp_resolve_host(0, s->local_port, SOCK_DGRAM, family, AI_PASSIVE);
190
+    res0 = udp_resolve_host(localaddr[0] ? localaddr : NULL, s->local_port,
191
+                            SOCK_DGRAM, family, AI_PASSIVE);
191 192
     if (res0 == 0)
192 193
         goto fail;
193 194
     for (res = res0; res; res=res->ai_next) {
... ...
@@ -302,7 +304,7 @@ static int udp_get_file_handle(URLContext *h)
302 302
 /* return non zero if error */
303 303
 static int udp_open(URLContext *h, const char *uri, int flags)
304 304
 {
305
-    char hostname[1024];
305
+    char hostname[1024], localaddr[1024] = "";
306 306
     int port, udp_fd = -1, tmp, bind_ret = -1;
307 307
     UDPContext *s = NULL;
308 308
     int is_output;
... ...
@@ -350,6 +352,9 @@ static int udp_open(URLContext *h, const char *uri, int flags)
350 350
         if (av_find_info_tag(buf, sizeof(buf), "connect", p)) {
351 351
             s->is_connected = strtol(buf, NULL, 10);
352 352
         }
353
+        if (av_find_info_tag(buf, sizeof(buf), "localaddr", p)) {
354
+            av_strlcpy(localaddr, buf, sizeof(localaddr));
355
+        }
353 356
     }
354 357
 
355 358
     /* fill the dest addr */
... ...
@@ -367,7 +372,7 @@ static int udp_open(URLContext *h, const char *uri, int flags)
367 367
 
368 368
     if ((s->is_multicast || !s->local_port) && (h->flags & AVIO_FLAG_READ))
369 369
         s->local_port = port;
370
-    udp_fd = udp_socket_create(s, &my_addr, &len);
370
+    udp_fd = udp_socket_create(s, &my_addr, &len, localaddr);
371 371
     if (udp_fd < 0)
372 372
         goto fail;
373 373