From 63f226019991479ee03b230ba567c8ccc69bb9db Mon Sep 17 00:00:00 2001 From: cbdev Date: Sat, 9 May 2020 20:55:58 +0200 Subject: Fix sACN compile-time warning --- backends/sacn.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'backends/sacn.c') diff --git a/backends/sacn.c b/backends/sacn.c index 0c0fd10..5858f16 100644 --- a/backends/sacn.c +++ b/backends/sacn.c @@ -612,7 +612,7 @@ static int sacn_start(size_t n, instance** inst){ .label = 0 }; struct ip_mreq mcast_req = { - .imr_interface = { INADDR_ANY } + .imr_interface.s_addr = INADDR_ANY }; struct sockaddr_in* dest_v4 = NULL; -- cgit v1.2.3 From 4e7acb39c73bd2108e55e4075350ddb82629fa26 Mon Sep 17 00:00:00 2001 From: cbdev Date: Fri, 24 Jul 2020 07:46:14 +0200 Subject: Select multicast interface for sACN where possible (#69) --- backends/sacn.c | 51 ++++++++++++++++++++++++++++++++++++++++++--------- 1 file changed, 42 insertions(+), 9 deletions(-) (limited to 'backends/sacn.c') 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)); } } } -- cgit v1.2.3 From 6291031a98539bdf51262329b0dc20604c2bad70 Mon Sep 17 00:00:00 2001 From: cbdev Date: Sun, 26 Jul 2020 23:01:35 +0200 Subject: Implement rudimentary detect mode for sACN (#70) --- backends/sacn.c | 39 ++++++++++++++++++++++++++++++++++++--- 1 file changed, 36 insertions(+), 3 deletions(-) (limited to 'backends/sacn.c') diff --git a/backends/sacn.c b/backends/sacn.c index 170769f..247dfc7 100644 --- a/backends/sacn.c +++ b/backends/sacn.c @@ -1,4 +1,5 @@ #define BACKEND_NAME "sacn" +#define DEBUG #include #include @@ -29,13 +30,15 @@ static struct /*_sacn_global_config*/ { sacn_fd* fd; uint64_t last_announce; uint32_t next_frame; + uint8_t detect; } global_cfg = { .source_name = "MIDIMonster", .cid = {'M', 'I', 'D', 'I', 'M', 'o', 'n', 's', 't', 'e', 'r'}, .fds = 0, .fd = NULL, .last_announce = 0, - .next_frame = 0 + .next_frame = 0, + .detect = 0 }; MM_PLUGIN_API int init(){ @@ -130,6 +133,16 @@ static int sacn_configure(char* option, char* value){ global_cfg.cid[u] = (strtoul(next, &next, 0) & 0xFF); } } + else if(!strcmp(option, "detect")){ + global_cfg.detect = 0; + if(!strcmp(value, "on")){ + global_cfg.detect = 1; + } + else if(!strcmp(value, "verbose")){ + global_cfg.detect = 2; + } + return 0; + } else if(!strcmp(option, "bind")){ mmbackend_parse_hostspec(value, &host, &port, &next); @@ -138,8 +151,13 @@ static int sacn_configure(char* option, char* value){ return 1; } - if(next && !strncmp(next, "local", 5)){ - flags = mcast_loop; + //parse additional socket options + if(next){ + for(next = strtok(next, " "); next; next = strtok(NULL, " ")){ + if(!strcmp(next, "local")){ + flags |= mcast_loop; + } + } } if(sacn_listener(host, port ? port : SACN_PORT, flags)){ @@ -401,6 +419,9 @@ static int sacn_process_frame(instance* inst, sacn_frame_root* frame, sacn_frame //source filtering if(inst_data->filter_enabled && memcmp(inst_data->cid_filter, frame->sender_cid, 16)){ + if(global_cfg.detect > 1){ + LOGPF("Discarding data for instance %s due to source filter rule", inst->name); + } return 0; } @@ -418,11 +439,19 @@ static int sacn_process_frame(instance* inst, sacn_frame_root* frame, sacn_frame //handle source priority (currently a 1-bit counter) if(inst_data->data.last_priority > data->priority){ + if(global_cfg.detect > 1){ + LOGPF("Ignoring lower-priority (%d) source on %s, current source is %d", data->priority, inst->name, inst_data->data.last_priority); + } inst_data->data.last_priority = data->priority; return 0; } inst_data->data.last_priority = data->priority; + if(!inst_data->last_input && global_cfg.detect){ + LOGPF("Valid data on instance %s (Universe %u): Source name %.*s, priority %d", inst->name, inst_data->uni, 64, data->source_name, data->priority); + } + inst_data->last_input = mm_timestamp(); + //read data (except start code), mark changed channels for(u = 1; u < be16toh(data->channels); u++){ if(IS_ACTIVE(inst_data->data.map[u - 1]) @@ -583,6 +612,10 @@ static int sacn_handle(size_t num, managed_fd* fds){ if(inst && sacn_process_frame(inst, frame, data)){ LOG("Failed to process frame"); } + else if(!inst && global_cfg.detect > 1){ + //this will only happen with unicast input + LOGPF("Received data for unconfigured universe %d on descriptor %" PRIsize_t, be16toh(data->universe), ((uint64_t) fds[u].impl) & 0xFFFF); + } } } } while(bytes_read > 0); -- cgit v1.2.3 From 39dfd02d5daa8ce7cf749f6235cf6450b2171214 Mon Sep 17 00:00:00 2001 From: cbdev Date: Fri, 7 Aug 2020 22:34:31 +0200 Subject: Implement detect mode for artnet (#70) --- backends/sacn.c | 1 - 1 file changed, 1 deletion(-) (limited to 'backends/sacn.c') diff --git a/backends/sacn.c b/backends/sacn.c index 247dfc7..0ea7b58 100644 --- a/backends/sacn.c +++ b/backends/sacn.c @@ -1,5 +1,4 @@ #define BACKEND_NAME "sacn" -#define DEBUG #include #include -- cgit v1.2.3 From 70f1ca5bbb3156d9d2b90a115ba88495e5151b55 Mon Sep 17 00:00:00 2001 From: cbdev Date: Sat, 10 Oct 2020 17:30:15 +0200 Subject: Update some comments --- backends/sacn.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'backends/sacn.c') diff --git a/backends/sacn.c b/backends/sacn.c index 0ea7b58..e395ae2 100644 --- a/backends/sacn.c +++ b/backends/sacn.c @@ -385,7 +385,7 @@ static int sacn_set(instance* inst, size_t num, channel** c, channel_value* v){ //send packet if required if(mark){ - //find output instance data + //find output control data for the instance for(u = 0; u < global_cfg.fd[data->fd_index].universes; u++){ if(global_cfg.fd[data->fd_index].universe[u].universe == data->uni){ break; -- cgit v1.2.3