diff options
author | cbdev <cb@cbcdn.com> | 2020-07-24 07:46:14 +0200 |
---|---|---|
committer | cbdev <cb@cbcdn.com> | 2020-07-24 07:46:14 +0200 |
commit | 4e7acb39c73bd2108e55e4075350ddb82629fa26 (patch) | |
tree | 09fc2951dfc71a1d28eafc83a1a0b2b90702b7d9 | |
parent | 7734eb3947df0ba586ff6c3ee7e1098b04f53bab (diff) | |
download | midimonster-4e7acb39c73bd2108e55e4075350ddb82629fa26.tar.gz midimonster-4e7acb39c73bd2108e55e4075350ddb82629fa26.tar.bz2 midimonster-4e7acb39c73bd2108e55e4075350ddb82629fa26.zip |
Select multicast interface for sACN where possible (#69)
-rw-r--r-- | backends/sacn.c | 51 |
1 files changed, 42 insertions, 9 deletions
diff --git a/backends/sacn.c b/backends/sacn.c index 5858f16..170769f 100644 --- a/backends/sacn.c +++ b/backends/sacn.c @@ -604,6 +604,45 @@ static int sacn_handle(size_t num, managed_fd* fds){ return 0; } +static int sacn_start_multicast(instance* inst){ + sacn_instance_data* data = (sacn_instance_data*) inst->impl; + struct sockaddr_storage bound_name = { + 0 + }; + #ifdef _WIN32 + struct ip_mreq mcast_req = { + .imr_interface.s_addr = INADDR_ANY, + #else + struct ip_mreqn mcast_req = { + .imr_address.s_addr = INADDR_ANY, + #endif + .imr_multiaddr.s_addr = htobe32(((uint32_t) 0xefff0000) | ((uint32_t) data->uni)) + }; + socklen_t bound_length = sizeof(bound_name); + + //select the specific interface to join the mcast group on based on the bind address + if(getsockname(global_cfg.fd[data->fd_index].fd, (struct sockaddr*) &bound_name, &bound_length)){ + LOGPF("Failed to read back local bind address on socket %" PRIsize_t, data->fd_index); + return 1; + } + else if(bound_name.ss_family != AF_INET || !((struct sockaddr_in*) &bound_name)->sin_addr.s_addr){ + LOGPF("Socket %" PRIsize_t " not bound to a specific IPv4 address, joining multicast input group for instance %s (universe %u) on default interface", data->fd_index, inst->name, data->uni); + } + else{ + #ifdef _WIN32 + mcast_req.imr_interface = ((struct sockaddr_in*) &bound_name)->sin_addr; + #else + mcast_req.imr_address = ((struct sockaddr_in*) &bound_name)->sin_addr; + #endif + } + + if(setsockopt(global_cfg.fd[data->fd_index].fd, IPPROTO_IP, IP_ADD_MEMBERSHIP, (uint8_t*) &mcast_req, sizeof(mcast_req))){ + LOGPF("Failed to join Multicast group for universe %u on instance %s: %s", data->uni, inst->name, mmbackend_socket_strerror(errno)); + } + + return 0; +} + static int sacn_start(size_t n, instance** inst){ size_t u, p; int rv = 1; @@ -611,9 +650,6 @@ static int sacn_start(size_t n, instance** inst){ sacn_instance_id id = { .label = 0 }; - struct ip_mreq mcast_req = { - .imr_interface.s_addr = INADDR_ANY - }; struct sockaddr_in* dest_v4 = NULL; if(!global_cfg.fds){ @@ -641,11 +677,8 @@ static int sacn_start(size_t n, instance** inst){ } } - if(!data->unicast_input){ - mcast_req.imr_multiaddr.s_addr = htobe32(((uint32_t) 0xefff0000) | ((uint32_t) data->uni)); - if(setsockopt(global_cfg.fd[data->fd_index].fd, IPPROTO_IP, IP_ADD_MEMBERSHIP, (uint8_t*) &mcast_req, sizeof(mcast_req))){ - LOGPF("Failed to join Multicast group for universe %u on instance %s: %s", data->uni, inst[u]->name, mmbackend_socket_strerror(errno)); - } + if(!data->unicast_input && sacn_start_multicast(inst[u])){ + return 1; } if(data->xmit_prio){ @@ -667,7 +700,7 @@ static int sacn_start(size_t n, instance** inst){ dest_v4 = (struct sockaddr_in*) (&data->dest_addr); dest_v4->sin_family = AF_INET; dest_v4->sin_port = htobe16(strtoul(SACN_PORT, NULL, 10)); - dest_v4->sin_addr = mcast_req.imr_multiaddr; + dest_v4->sin_addr.s_addr = htobe32(((uint32_t) 0xefff0000) | ((uint32_t) data->uni)); } } } |