Commit 65ac5137 authored by Martin Storsjö's avatar Martin Storsjö

udp: Allow specifying the local IP address

This is useful if sending multicast data on a host with
multiple interfaces.
Signed-off-by: 's avatarMartin Storsjö <martin@martin.st>
parent c33d4916
...@@ -446,6 +446,11 @@ set the UDP buffer size in bytes ...@@ -446,6 +446,11 @@ set the UDP buffer size in bytes
@item localport=@var{port} @item localport=@var{port}
override the local UDP port to bind with 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} @item pkt_size=@var{size}
set the size in bytes of UDP packets set the size in bytes of UDP packets
......
...@@ -29,6 +29,7 @@ ...@@ -29,6 +29,7 @@
#include "avformat.h" #include "avformat.h"
#include "avio_internal.h" #include "avio_internal.h"
#include "libavutil/parseutils.h" #include "libavutil/parseutils.h"
#include "libavutil/avstring.h"
#include <unistd.h> #include <unistd.h>
#include "internal.h" #include "internal.h"
#include "network.h" #include "network.h"
...@@ -178,8 +179,8 @@ static int udp_set_url(struct sockaddr_storage *addr, ...@@ -178,8 +179,8 @@ static int udp_set_url(struct sockaddr_storage *addr,
return addr_len; return addr_len;
} }
static int udp_socket_create(UDPContext *s, static int udp_socket_create(UDPContext *s, struct sockaddr_storage *addr,
struct sockaddr_storage *addr, int *addr_len) int *addr_len, const char *localaddr)
{ {
int udp_fd = -1; int udp_fd = -1;
struct addrinfo *res0 = NULL, *res = NULL; struct addrinfo *res0 = NULL, *res = NULL;
...@@ -187,7 +188,8 @@ static int udp_socket_create(UDPContext *s, ...@@ -187,7 +188,8 @@ static int udp_socket_create(UDPContext *s,
if (((struct sockaddr *) &s->dest_addr)->sa_family) if (((struct sockaddr *) &s->dest_addr)->sa_family)
family = ((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) if (res0 == 0)
goto fail; goto fail;
for (res = res0; res; res=res->ai_next) { for (res = res0; res; res=res->ai_next) {
...@@ -302,7 +304,7 @@ static int udp_get_file_handle(URLContext *h) ...@@ -302,7 +304,7 @@ static int udp_get_file_handle(URLContext *h)
/* 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)
{ {
char hostname[1024]; char hostname[1024], localaddr[1024] = "";
int port, udp_fd = -1, tmp, bind_ret = -1; int port, udp_fd = -1, tmp, bind_ret = -1;
UDPContext *s = NULL; UDPContext *s = NULL;
int is_output; int is_output;
...@@ -350,6 +352,9 @@ static int udp_open(URLContext *h, const char *uri, int flags) ...@@ -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)) { if (av_find_info_tag(buf, sizeof(buf), "connect", p)) {
s->is_connected = strtol(buf, NULL, 10); 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 */ /* fill the dest addr */
...@@ -367,7 +372,7 @@ static int udp_open(URLContext *h, const char *uri, int flags) ...@@ -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)) if ((s->is_multicast || !s->local_port) && (h->flags & AVIO_FLAG_READ))
s->local_port = port; 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) if (udp_fd < 0)
goto fail; goto fail;
......
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