allow specifiing multicast iface

This commit is contained in:
Martin Pulec
2012-07-30 15:45:18 +02:00
parent dab475dab7
commit 92e24dd02f
5 changed files with 61 additions and 34 deletions

View File

@@ -121,7 +121,8 @@ typedef void (*audio_device_help_t)(void);
static void *audio_sender_thread(void *arg);
static void *audio_receiver_thread(void *arg);
static struct rtp *initialize_audio_network(char *addr, int recv_port,
int send_port, struct pdb *participants, bool use_ipv6);
int send_port, struct pdb *participants, bool use_ipv6,
char *mcast_if);
static void audio_channel_map_usage(void);
static void audio_scale_usage(void);
@@ -159,7 +160,7 @@ static void audio_scale_usage(void)
*/
struct state_audio * audio_cfg_init(char *addrs, int recv_port, int send_port, char *send_cfg, char *recv_cfg,
char *jack_cfg, char *fec_cfg, char *audio_channel_map, const char *audio_scale,
bool echo_cancellation, bool use_ipv6)
bool echo_cancellation, bool use_ipv6, char *mcast_if)
{
struct state_audio *s = NULL;
char *tmp, *unused = NULL;
@@ -227,8 +228,8 @@ struct state_audio * audio_cfg_init(char *addrs, int recv_port, int send_port, c
addr = strtok_r(tmp, ",", &unused);
if ((s->audio_network_device =
initialize_audio_network(addr, recv_port, send_port,
s->audio_participants, use_ipv6)) ==
NULL) {
s->audio_participants, use_ipv6, mcast_if))
== NULL) {
printf("Unable to open audio network\n");
goto error;
}
@@ -344,13 +345,15 @@ void audio_done(struct state_audio *s)
}
static struct rtp *initialize_audio_network(char *addr, int recv_port,
int send_port, struct pdb *participants, bool use_ipv6) // GiX
int send_port, struct pdb *participants, bool use_ipv6,
char *mcast_if) // GiX
{
struct rtp *r;
double rtcp_bw = 1024 * 512; // FIXME: something about 5% for rtcp is said in rfc
r = rtp_init(addr, recv_port, send_port, 255, rtcp_bw, FALSE, rtp_recv_callback,
(void *)participants, use_ipv6);
r = rtp_init_if(addr, mcast_if, recv_port, send_port, 255, rtcp_bw,
FALSE, rtp_recv_callback, (void *)participants,
use_ipv6);
if (r != NULL) {
pdb_add(participants, rtp_my_ssrc(r));
rtp_set_option(r, RTP_OPT_WEAK_VALIDATION, TRUE);

View File

@@ -72,7 +72,7 @@ audio_frame;
struct state_audio * audio_cfg_init(char *addrs, int recv_port, int send_port, char *send_cfg, char *recv_cfg,
char *jack_cfg, char *fec_cfg, char *audio_channel_map, const char *audio_scale,
bool echo_cancellation, bool use_ipv6);
bool echo_cancellation, bool use_ipv6, char *mcast_iface);
void audio_finish(struct state_audio *s);
void audio_done(struct state_audio *s);
void audio_join(struct state_audio *s);

View File

@@ -127,6 +127,7 @@
#include <sys/socket.h>
#include <sys/uio.h>
#include <netinet/in.h>
#include <net/if.h>
#include <unistd.h>
#include <sys/param.h>
#include <sys/fcntl.h>

View File

@@ -106,6 +106,7 @@
#define AUDIO_SCALE (('a' << 8) | 's')
#define ECHO_CANCELLATION (('E' << 8) | 'C')
#define CUDA_DEVICE (('C' << 8) | 'D')
#define MCAST_IF (('M' << 8) | 'I')
#ifdef HAVE_MACOSX
#define INITIAL_VIDEO_RECV_BUFFER_SIZE 5944320
@@ -175,7 +176,8 @@ static struct state_uv *uv_state;
// prototypes
//
static struct rtp **initialize_network(char *addrs, int recv_port_base,
int send_port_base, struct pdb *participants, bool use_ipv6);
int send_port_base, struct pdb *participants, bool use_ipv6,
char *mcast_if);
void list_video_display_devices(void);
void list_video_capture_devices(void);
@@ -228,9 +230,9 @@ static void usage(void)
printf("\nUsage: uv [-d <display_device>] [-t <capture_device>] [-r <audio_playout>]\n");
printf(" [-s <audio_caputre>] [-l <limit_bitrate>] "
"[-m <mtu>] [-c] [-i] [-6]\n");
printf(" [-M <video_mode>] [-p <postprocess>] "
"[-f <FEC_options>] [-P <port>]\n");
printf(" address(es)\n\n");
printf(" [-m <video_mode>] [-p <postprocess>] "
"[-f <fec_options>] [-p <port>]\n");
printf(" [--mcast-if <iface>] address(es)\n\n");
printf
("\t-d <display_device> \tselect display device, use '-d help'\n");
printf("\t \tto get list of supported devices\n");
@@ -247,6 +249,8 @@ static void usage(void)
printf("\t-6 \tUse IPv6\n");
printf("\n");
#endif // HAVE_IPv6
printf("\t--mcast-if <iface> \tBind to specified interface for multicast\n");
printf("\n");
printf("\t-r <playback_device> \tAudio playback device (see '-r help')\n");
printf("\n");
printf("\t-s <capture_device> \tAudio capture device (see '-s help')\n");
@@ -414,7 +418,8 @@ static void display_buf_increase_warning(int size)
}
static struct rtp **initialize_network(char *addrs, int recv_port_base,
int send_port_base, struct pdb *participants, bool use_ipv6)
int send_port_base, struct pdb *participants, bool use_ipv6,
char *mcast_if)
{
struct rtp **devices = NULL;
double rtcp_bw = 5 * 1024 * 1024; /* FIXME */
@@ -451,9 +456,10 @@ static struct rtp **initialize_network(char *addrs, int recv_port_base,
if (send_port == send_port_base + 2)
send_port += 2;
devices[index] = rtp_init(addr, recv_port, send_port, ttl, rtcp_bw,
FALSE, rtp_recv_callback,
(void *)participants, use_ipv6);
devices[index] = rtp_init_if(addr, mcast_if, recv_port,
send_port, ttl, rtcp_bw, FALSE,
rtp_recv_callback, (void *)participants,
use_ipv6);
if (devices[index] != NULL) {
rtp_set_option(devices[index], RTP_OPT_WEAK_VALIDATION,
TRUE);
@@ -861,6 +867,7 @@ int main(int argc, char *argv[])
bool echo_cancellation = false;
bool use_ipv6 = false;
char *mcast_if = NULL;
int bitrate = 0;
@@ -906,6 +913,7 @@ int main(int argc, char *argv[])
{"audio-capture-channels", required_argument, 0, AUDIO_CAPTURE_CHANNELS},
{"echo-cancellation", no_argument, 0, ECHO_CANCELLATION},
{"cuda-device", required_argument, 0, CUDA_DEVICE},
{"mcast-if", required_argument, 0, MCAST_IF},
{0, 0, 0, 0}
};
int option_index = 0;
@@ -1058,6 +1066,9 @@ int main(int argc, char *argv[])
fprintf(stderr, "CUDA support is not enabled!\n");
return EXIT_FAIL_USAGE;
#endif // HAVE_CUDA
case MCAST_IF:
mcast_if = optarg;
break;
default:
usage();
return EXIT_FAIL_USAGE;
@@ -1104,8 +1115,10 @@ int main(int argc, char *argv[])
}
char *tmp_requested_fec = strdup(DEFAULT_AUDIO_FEC);
uv->audio = audio_cfg_init (network_device, uv->recv_port_number + 2, uv->send_port_number + 2, audio_send, audio_recv, jack_cfg,
tmp_requested_fec, audio_channel_map, audio_scale, echo_cancellation, use_ipv6);
uv->audio = audio_cfg_init (network_device, uv->recv_port_number + 2,
uv->send_port_number + 2, audio_send, audio_recv,
jack_cfg, tmp_requested_fec, audio_channel_map,
audio_scale, echo_cancellation, use_ipv6, mcast_if);
free(tmp_requested_fec);
if(!uv->audio)
goto cleanup;
@@ -1226,7 +1239,7 @@ int main(int argc, char *argv[])
} else {
if ((uv->network_devices =
initialize_network(network_device, uv->recv_port_number,
uv->send_port_number, uv->participants, use_ipv6))
uv->send_port_number, uv->participants, use_ipv6, mcast_if))
== NULL) {
printf("Unable to open network\n");
exit_uv(EXIT_FAIL_NETWORK);

View File

@@ -271,7 +271,7 @@ static socket_udp *udp_init4(const char *addr, const char *iface,
int reuse = 1;
int udpbufsize = 16 * 1024 * 1024;
struct sockaddr_in s_in;
struct in_addr iface_addr;
unsigned int ifindex;
socket_udp *s = (socket_udp *) malloc(sizeof(socket_udp));
s->mode = IPv4;
s->addr = NULL;
@@ -288,13 +288,13 @@ static socket_udp *udp_init4(const char *addr, const char *iface,
memcpy(&(s->addr4), h->h_addr_list[0], sizeof(s->addr4));
}
if (iface != NULL) {
if (inet_pton(AF_INET, iface, &iface_addr) != 1) {
if ((ifindex = if_nametoindex(iface)) == 0) {
debug_msg("Illegal interface specification\n");
free(s);
return NULL;
}
} else {
iface_addr.s_addr = 0;
ifindex = 0;
}
s->fd = socket(AF_INET, SOCK_DGRAM, 0);
if (s->fd < 0) {
@@ -337,7 +337,7 @@ static socket_udp *udp_init4(const char *addr, const char *iface,
struct ip_mreq imr;
imr.imr_multiaddr.s_addr = s->addr4.s_addr;
imr.imr_interface.s_addr = iface_addr.s_addr;
imr.imr_interface.s_addr = ifindex;
if (SETSOCKOPT
(s->fd, IPPROTO_IP, IP_ADD_MEMBERSHIP, (char *)&imr,
@@ -359,13 +359,11 @@ static socket_udp *udp_init4(const char *addr, const char *iface,
socket_error("setsockopt IP_MULTICAST_TTL");
return NULL;
}
if (iface_addr.s_addr != 0) {
if (SETSOCKOPT
(s->fd, IPPROTO_IP, IP_MULTICAST_IF,
(char *)&iface_addr, sizeof(iface_addr)) != 0) {
socket_error("setsockopt IP_MULTICAST_IF");
return NULL;
}
if (SETSOCKOPT
(s->fd, IPPROTO_IP, IP_MULTICAST_IF,
(char *)&ifindex, sizeof(ifindex)) != 0) {
socket_error("setsockopt IP_MULTICAST_IF");
return NULL;
}
}
s->addr = strdup(addr);
@@ -541,11 +539,17 @@ static socket_udp *udp_init6(const char *addr, const char *iface,
s->tx_port = tx_port;
s->ttl = ttl;
struct addrinfo hints, *res0;
unsigned int ifindex;
int err;
if (iface != NULL) {
debug_msg("Not yet implemented\n");
abort();
if ((ifindex = if_nametoindex(iface)) == 0) {
debug_msg("Illegal interface specification\n");
free(s);
return NULL;
}
} else {
ifindex = 0;
}
memset(&hints, 0, sizeof(hints));
@@ -607,7 +611,7 @@ static socket_udp *udp_init6(const char *addr, const char *iface,
imr.i6mr_multiaddr = s->addr6;
#else
imr.ipv6mr_multiaddr = s->addr6;
imr.ipv6mr_interface = 0;
imr.ipv6mr_interface = ifindex;
#endif
if (SETSOCKOPT
@@ -629,6 +633,11 @@ static socket_udp *udp_init6(const char *addr, const char *iface,
socket_error("setsockopt IPV6_MULTICAST_HOPS");
return NULL;
}
if (SETSOCKOPT(s->fd, IPPROTO_IPV6, IPV6_MULTICAST_IF,
(char *)&ifindex, sizeof(ifindex)) != 0) {
socket_error("setsockopt IPV6_MULTICAST_IF");
return NULL;
}
}
assert(s != NULL);
@@ -722,7 +731,8 @@ static const char *udp_host_addr6(socket_udp * s)
int gai_err, newsock;
struct addrinfo hints, *ai;
struct sockaddr_in6 local, addr6;
int len = sizeof(local), result = 0;
socklen_t len = sizeof(local);
int result = 0;
newsock = socket(AF_INET6, SOCK_DGRAM, 0);
memset((char *)&addr6, 0, len);