From 3eada28582b144519e95a44ee3adc3f46d39036e Mon Sep 17 00:00:00 2001 From: cbdev Date: Thu, 5 Dec 2019 21:05:14 +0100 Subject: Add flags parameter to channel parser plugin API (Fixes #31) --- 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 d8b3eb3..2229b8a 100644 --- a/backends/sacn.c +++ b/backends/sacn.c @@ -198,7 +198,7 @@ static instance* sacn_instance(){ return inst; } -static channel* sacn_channel(instance* inst, char* spec){ +static channel* sacn_channel(instance* inst, char* spec, uint8_t flags){ sacn_instance_data* data = (sacn_instance_data*) inst->impl; char* spec_next = spec; -- cgit v1.2.3 From 4ca0acff460c1c02a11cb9f246fb755cd4f4f792 Mon Sep 17 00:00:00 2001 From: cbdev Date: Sun, 8 Dec 2019 02:27:57 +0100 Subject: Minor logic cleanup --- backends/sacn.c | 10 ++-------- 1 file changed, 2 insertions(+), 8 deletions(-) (limited to 'backends/sacn.c') diff --git a/backends/sacn.c b/backends/sacn.c index 2229b8a..edb648d 100644 --- a/backends/sacn.c +++ b/backends/sacn.c @@ -111,16 +111,13 @@ static int sacn_configure(char* option, char* value){ } else if(!strcmp(option, "bind")){ mmbackend_parse_hostspec(value, &host, &port); - if(!port){ - port = SACN_PORT; - } if(!host){ fprintf(stderr, "No valid sACN bind address provided\n"); return 1; } - if(sacn_listener(host, port, flags)){ + if(sacn_listener(host, port ? port : SACN_PORT, flags)){ fprintf(stderr, "Failed to bind sACN descriptor: %s\n", value); return 1; } @@ -155,16 +152,13 @@ static int sacn_configure_instance(instance* inst, char* option, char* value){ } else if(!strcmp(option, "destination")){ mmbackend_parse_hostspec(value, &host, &port); - if(!port){ - port = SACN_PORT; - } if(!host){ fprintf(stderr, "No valid sACN destination for instance %s\n", inst->name); return 1; } - return mmbackend_parse_sockaddr(host, port, &data->dest_addr, &data->dest_len); + return mmbackend_parse_sockaddr(host, port ? port : SACN_PORT, &data->dest_addr, &data->dest_len); } else if(!strcmp(option, "from")){ next = value; -- cgit v1.2.3 From 31cc72f660513b033cc0621782586562bafab08e Mon Sep 17 00:00:00 2001 From: cbdev Date: Tue, 10 Dec 2019 22:35:59 +0100 Subject: Fix bug in sACN config parsing --- backends/sacn.c | 1 + 1 file changed, 1 insertion(+) (limited to 'backends/sacn.c') diff --git a/backends/sacn.c b/backends/sacn.c index edb648d..75c327e 100644 --- a/backends/sacn.c +++ b/backends/sacn.c @@ -171,6 +171,7 @@ static int sacn_configure_instance(instance* inst, char* option, char* value){ } else if(!strcmp(option, "unicast")){ data->unicast_input = strtoul(value, NULL, 10); + return 0; } fprintf(stderr, "Unknown configuration option %s for sACN backend\n", option); -- cgit v1.2.3 From f65fb8baaba285f5ff4b02af111420ba4479f5d9 Mon Sep 17 00:00:00 2001 From: cbdev Date: Wed, 11 Dec 2019 23:02:22 +0100 Subject: Simplify plugin_start API --- backends/sacn.c | 17 ++--------------- 1 file changed, 2 insertions(+), 15 deletions(-) (limited to 'backends/sacn.c') diff --git a/backends/sacn.c b/backends/sacn.c index 75c327e..877cbb0 100644 --- a/backends/sacn.c +++ b/backends/sacn.c @@ -531,10 +531,9 @@ static int sacn_handle(size_t num, managed_fd* fds){ return 0; } -static int sacn_start(){ - size_t n, u, p; +static int sacn_start(size_t n, instance** inst){ + size_t u, p; int rv = 1; - instance** inst = NULL; sacn_instance_data* data = NULL; sacn_instance_id id = { .label = 0 @@ -544,17 +543,6 @@ static int sacn_start(){ }; struct sockaddr_in* dest_v4 = NULL; - //fetch all instances - if(mm_backend_instances(BACKEND_NAME, &n, &inst)){ - fprintf(stderr, "Failed to fetch instance list\n"); - return 1; - } - - if(!n){ - free(inst); - return 0; - } - if(!global_cfg.fds){ fprintf(stderr, "Failed to start sACN backend: no descriptors bound\n"); free(inst); @@ -625,7 +613,6 @@ static int sacn_start(){ rv = 0; bail: - free(inst); return rv; } -- cgit v1.2.3 From f6d6eefe9bb9934f4fa3e665734d746f02471cdb Mon Sep 17 00:00:00 2001 From: cbdev Date: Wed, 11 Dec 2019 23:20:34 +0100 Subject: Simplify plugin_stop API --- backends/sacn.c | 11 ++--------- 1 file changed, 2 insertions(+), 9 deletions(-) (limited to 'backends/sacn.c') diff --git a/backends/sacn.c b/backends/sacn.c index 877cbb0..ef422e8 100644 --- a/backends/sacn.c +++ b/backends/sacn.c @@ -616,19 +616,12 @@ bail: return rv; } -static int sacn_shutdown(){ - size_t n, p; - instance** inst = NULL; - - if(mm_backend_instances(BACKEND_NAME, &n, &inst)){ - fprintf(stderr, "Failed to fetch instance list\n"); - return 1; - } +static int sacn_shutdown(size_t n, instance** inst){ + size_t p; for(p = 0; p < n; p++){ free(inst[p]->impl); } - free(inst); for(p = 0; p < global_cfg.fds; p++){ close(global_cfg.fd[p].fd); -- cgit v1.2.3 From bef4dd78ca2a610b4c669ea2c7a477283769997d Mon Sep 17 00:00:00 2001 From: cbdev Date: Thu, 12 Dec 2019 20:29:03 +0100 Subject: Extend hostspec parsing and implement local mode for sACN (#39) --- backends/sacn.c | 26 +++++++++++++++++++++----- 1 file changed, 21 insertions(+), 5 deletions(-) (limited to 'backends/sacn.c') diff --git a/backends/sacn.c b/backends/sacn.c index ef422e8..2a04245 100644 --- a/backends/sacn.c +++ b/backends/sacn.c @@ -17,6 +17,10 @@ #define MAX_FDS 4096 #define BACKEND_NAME "sacn" +enum /*_sacn_fd_flags*/ { + mcast_loop = 1 +}; + static struct /*_sacn_global_config*/ { uint8_t source_name[64]; uint8_t cid[16]; @@ -58,8 +62,8 @@ MM_PLUGIN_API int init(){ return 0; } -static int sacn_listener(char* host, char* port, uint8_t fd_flags){ - int fd = -1; +static int sacn_listener(char* host, char* port, uint8_t flags){ + int fd = -1, yes = 1; if(global_cfg.fds >= MAX_FDS){ fprintf(stderr, "sACN backend descriptor limit reached\n"); return -1; @@ -80,10 +84,17 @@ static int sacn_listener(char* host, char* port, uint8_t fd_flags){ fprintf(stderr, "sACN backend interface %" PRIsize_t " bound to %s port %s\n", global_cfg.fds, host, port); global_cfg.fd[global_cfg.fds].fd = fd; - global_cfg.fd[global_cfg.fds].flags = fd_flags; global_cfg.fd[global_cfg.fds].universes = 0; global_cfg.fd[global_cfg.fds].universe = NULL; global_cfg.fd[global_cfg.fds].last_frame = NULL; + + if(flags & mcast_loop){ + //set IP_MCAST_LOOP to allow local applications to receive output + if(setsockopt(fd, IPPROTO_IP, IP_MULTICAST_LOOP, (void*)&yes, sizeof(yes)) < 0){ + fprintf(stderr, "Failed to disable IP_MULTICAST_LOOP on socket: %s\n", strerror(errno)); + } + } + global_cfg.fds++; return 0; } @@ -110,17 +121,22 @@ static int sacn_configure(char* option, char* value){ } } else if(!strcmp(option, "bind")){ - mmbackend_parse_hostspec(value, &host, &port); + mmbackend_parse_hostspec(value, &host, &port, &next); if(!host){ fprintf(stderr, "No valid sACN bind address provided\n"); return 1; } + if(next && !strncmp(next, "local", 5)){ + flags = mcast_loop; + } + if(sacn_listener(host, port ? port : SACN_PORT, flags)){ fprintf(stderr, "Failed to bind sACN descriptor: %s\n", value); return 1; } + return 0; } @@ -151,7 +167,7 @@ static int sacn_configure_instance(instance* inst, char* option, char* value){ return 0; } else if(!strcmp(option, "destination")){ - mmbackend_parse_hostspec(value, &host, &port); + mmbackend_parse_hostspec(value, &host, &port, NULL); if(!host){ fprintf(stderr, "No valid sACN destination for instance %s\n", inst->name); -- cgit v1.2.3 From 062c93b1f718730c71bc4d2a1e53e0107dd236ad Mon Sep 17 00:00:00 2001 From: cbdev Date: Fri, 20 Dec 2019 21:29:18 +0100 Subject: Route all backend debug logging through a macro --- backends/sacn.c | 77 +++++++++++++++++++++++++++++---------------------------- 1 file changed, 39 insertions(+), 38 deletions(-) (limited to 'backends/sacn.c') diff --git a/backends/sacn.c b/backends/sacn.c index 2a04245..ff2b61e 100644 --- a/backends/sacn.c +++ b/backends/sacn.c @@ -1,3 +1,5 @@ +#define BACKEND_NAME "sacn" + #include #include #include @@ -15,7 +17,6 @@ //upper limit imposed by using the fd index as 16-bit part of the instance id #define MAX_FDS 4096 -#define BACKEND_NAME "sacn" enum /*_sacn_fd_flags*/ { mcast_loop = 1 @@ -49,13 +50,13 @@ MM_PLUGIN_API int init(){ }; if(sizeof(sacn_instance_id) != sizeof(uint64_t)){ - fprintf(stderr, "sACN instance identification union out of bounds\n"); + LOG("Instance identification union out of bounds"); return 1; } //register the backend if(mm_backend_register(sacn)){ - fprintf(stderr, "Failed to register sACN backend\n"); + LOG("Failed to register backend"); return 1; } @@ -65,7 +66,7 @@ MM_PLUGIN_API int init(){ static int sacn_listener(char* host, char* port, uint8_t flags){ int fd = -1, yes = 1; if(global_cfg.fds >= MAX_FDS){ - fprintf(stderr, "sACN backend descriptor limit reached\n"); + LOG("Descriptor limit reached"); return -1; } @@ -78,11 +79,11 @@ static int sacn_listener(char* host, char* port, uint8_t flags){ global_cfg.fd = realloc(global_cfg.fd, (global_cfg.fds + 1) * sizeof(sacn_fd)); if(!global_cfg.fd){ close(fd); - fprintf(stderr, "Failed to allocate memory\n"); + LOG("Failed to allocate memory"); return -1; } - fprintf(stderr, "sACN backend interface %" PRIsize_t " bound to %s port %s\n", global_cfg.fds, host, port); + LOGPF("Interface %" PRIsize_t " bound to %s port %s", global_cfg.fds, host, port); global_cfg.fd[global_cfg.fds].fd = fd; global_cfg.fd[global_cfg.fds].universes = 0; global_cfg.fd[global_cfg.fds].universe = NULL; @@ -91,7 +92,7 @@ static int sacn_listener(char* host, char* port, uint8_t flags){ if(flags & mcast_loop){ //set IP_MCAST_LOOP to allow local applications to receive output if(setsockopt(fd, IPPROTO_IP, IP_MULTICAST_LOOP, (void*)&yes, sizeof(yes)) < 0){ - fprintf(stderr, "Failed to disable IP_MULTICAST_LOOP on socket: %s\n", strerror(errno)); + LOGPF("Failed to re-enable IP_MULTICAST_LOOP on socket: %s", strerror(errno)); } } @@ -106,7 +107,7 @@ static int sacn_configure(char* option, char* value){ if(!strcmp(option, "name")){ if(strlen(value) > 63){ - fprintf(stderr, "Invalid sACN source name %s, limit is 63 characters\n", value); + LOGPF("Invalid source name %s, limit is 63 characters", value); return 1; } @@ -124,7 +125,7 @@ static int sacn_configure(char* option, char* value){ mmbackend_parse_hostspec(value, &host, &port, &next); if(!host){ - fprintf(stderr, "No valid sACN bind address provided\n"); + LOG("No valid bind address provided"); return 1; } @@ -133,14 +134,14 @@ static int sacn_configure(char* option, char* value){ } if(sacn_listener(host, port ? port : SACN_PORT, flags)){ - fprintf(stderr, "Failed to bind sACN descriptor: %s\n", value); + LOGPF("Failed to bind descriptor: %s", value); return 1; } return 0; } - fprintf(stderr, "Unknown sACN backend option %s\n", option); + LOGPF("Unknown backend configuration option %s", option); return 1; } @@ -157,7 +158,7 @@ static int sacn_configure_instance(instance* inst, char* option, char* value){ data->fd_index = strtoul(value, NULL, 10); if(data->fd_index >= global_cfg.fds){ - fprintf(stderr, "Configured sACN interface index is out of range on instance %s\n", inst->name); + LOGPF("Configured interface index is out of range on instance %s", inst->name); return 1; } return 0; @@ -170,7 +171,7 @@ static int sacn_configure_instance(instance* inst, char* option, char* value){ mmbackend_parse_hostspec(value, &host, &port, NULL); if(!host){ - fprintf(stderr, "No valid sACN destination for instance %s\n", inst->name); + LOGPF("No valid destination for instance %s", inst->name); return 1; } @@ -182,7 +183,7 @@ static int sacn_configure_instance(instance* inst, char* option, char* value){ for(u = 0; u < sizeof(data->cid_filter); u++){ data->cid_filter[u] = (strtoul(next, &next, 0) & 0xFF); } - fprintf(stderr, "Enabled source CID filter for instance %s\n", inst->name); + LOGPF("Enabled source CID filter for instance %s", inst->name); return 0; } else if(!strcmp(option, "unicast")){ @@ -190,7 +191,7 @@ static int sacn_configure_instance(instance* inst, char* option, char* value){ return 0; } - fprintf(stderr, "Unknown configuration option %s for sACN backend\n", option); + LOGPF("Unknown instance configuration option %s for instance %s", option, inst->name); return 1; } @@ -202,7 +203,7 @@ static instance* sacn_instance(){ inst->impl = calloc(1, sizeof(sacn_instance_data)); if(!inst->impl){ - fprintf(stderr, "Failed to allocate memory"); + LOG("Failed to allocate memory"); return NULL; } @@ -217,7 +218,7 @@ static channel* sacn_channel(instance* inst, char* spec, uint8_t flags){ //range check if(!chan_a || chan_a > 512){ - fprintf(stderr, "sACN channel out of range on instance %s: %s\n", inst->name, spec); + LOGPF("Channel out of range on instance %s: %s", inst->name, spec); return NULL; } chan_a--; @@ -226,14 +227,14 @@ static channel* sacn_channel(instance* inst, char* spec, uint8_t flags){ if(*spec_next == '+'){ chan_b = strtoul(spec_next + 1, NULL, 10); if(!chan_b || chan_b > 512){ - fprintf(stderr, "Invalid wide-channel spec on instance %s: %s\n", inst->name, spec); + LOGPF("Invalid wide-channel spec on instance %s: %s", inst->name, spec); return NULL; } chan_b--; //if already mapped, bail if(IS_ACTIVE(data->data.map[chan_b]) && data->data.map[chan_b] != (MAP_FINE | chan_a)){ - fprintf(stderr, "Fine channel %u already mapped on instance %s\n", chan_b, inst->name); + LOGPF("Fine channel %u already mapped on instance %s", chan_b, inst->name); return NULL; } @@ -244,7 +245,7 @@ static channel* sacn_channel(instance* inst, char* spec, uint8_t flags){ if(IS_ACTIVE(data->data.map[chan_a])){ if((*spec_next == '+' && data->data.map[chan_a] != (MAP_COARSE | chan_b)) || (*spec_next != '+' && data->data.map[chan_a] != (MAP_SINGLE | chan_a))){ - fprintf(stderr, "Primary sACN channel %u already mapped in another mode on instance %s\n", chan_a, inst->name); + LOGPF("Primary channel %u already mapped in another mode on instance %s", chan_a, inst->name); return NULL; } } @@ -290,7 +291,7 @@ static int sacn_transmit(instance* inst){ memcpy((((uint8_t*)pdu.data.data) + 1), data->data.out, 512); if(sendto(global_cfg.fd[data->fd_index].fd, (uint8_t*) &pdu, sizeof(pdu), 0, (struct sockaddr*) &data->dest_addr, data->dest_len) < 0){ - fprintf(stderr, "Failed to output sACN frame for instance %s: %s\n", inst->name, strerror(errno)); + LOGPF("Failed to output frame for instance %s: %s", inst->name, strerror(errno)); } //update last transmit timestamp @@ -311,7 +312,7 @@ static int sacn_set(instance* inst, size_t num, channel** c, channel_value* v){ } if(!data->xmit_prio){ - fprintf(stderr, "sACN instance %s not enabled for output (%" PRIsize_t " channel events)\n", inst->name, num); + LOGPF("Instance %s not enabled for output (%" PRIsize_t " channel events)", inst->name, num); return 0; } @@ -357,12 +358,12 @@ static int sacn_process_frame(instance* inst, sacn_frame_root* frame, sacn_frame if(data->format != 0xa1 || data->startcode_offset || be16toh(data->address_increment) != 1){ - fprintf(stderr, "sACN framing not supported\n"); + LOGPF("Framing not supported for incoming data on instance %s\n", inst->name); return 1; } if(be16toh(data->channels) > 513){ - fprintf(stderr, "Invalid sACN frame channel count\n"); + LOGPF("Invalid frame channel count %d on instance %s", be16toh(data->channels), inst->name); return 1; } @@ -396,7 +397,7 @@ static int sacn_process_frame(instance* inst, sacn_frame_root* frame, sacn_frame } if(!chan){ - fprintf(stderr, "Active channel %" PRIsize_t " on %s not known to core", u, inst->name); + LOGPF("Active channel %" PRIsize_t " on %s not known to core", u, inst->name); return 1; } @@ -413,7 +414,7 @@ static int sacn_process_frame(instance* inst, sacn_frame_root* frame, sacn_frame } if(mm_channel_event(chan, val)){ - fprintf(stderr, "Failed to push sACN channel event to core\n"); + LOG("Failed to push event to core"); return 1; } } @@ -464,7 +465,7 @@ static void sacn_discovery(size_t fd){ memcpy(pdu.data.data, global_cfg.fd[fd].universe + page * 512, universes * sizeof(uint16_t)); if(sendto(global_cfg.fd[fd].fd, (uint8_t*) &pdu, sizeof(pdu) - (512 - universes) * sizeof(uint16_t), 0, (struct sockaddr*) &discovery_dest, sizeof(discovery_dest)) < 0){ - fprintf(stderr, "Failed to output sACN universe discovery frame for interface %" PRIsize_t ": %s\n", fd, strerror(errno)); + LOGPF("Failed to output universe discovery frame for interface %" PRIsize_t ": %s", fd, strerror(errno)); } } } @@ -524,7 +525,7 @@ static int sacn_handle(size_t num, managed_fd* fds){ instance_id.fields.uni = be16toh(data->universe); inst = mm_instance_find(BACKEND_NAME, instance_id.label); if(inst && sacn_process_frame(inst, frame, data)){ - fprintf(stderr, "Failed to process sACN frame\n"); + LOG("Failed to process frame"); } } } @@ -535,11 +536,11 @@ static int sacn_handle(size_t num, managed_fd* fds){ #else if(bytes_read < 0 && errno != EAGAIN){ #endif - fprintf(stderr, "sACN failed to receive data: %s\n", strerror(errno)); + LOGPF("Failed to receive data: %s", strerror(errno)); } if(bytes_read == 0){ - fprintf(stderr, "sACN listener closed\n"); + LOG("Listener closed"); return 1; } } @@ -560,7 +561,7 @@ static int sacn_start(size_t n, instance** inst){ struct sockaddr_in* dest_v4 = NULL; if(!global_cfg.fds){ - fprintf(stderr, "Failed to start sACN backend: no descriptors bound\n"); + LOG("Failed to start, no descriptors bound"); free(inst); return 1; } @@ -573,14 +574,14 @@ static int sacn_start(size_t n, instance** inst){ inst[u]->ident = id.label; if(!data->uni){ - fprintf(stderr, "Please specify a universe on instance %s\n", inst[u]->name); + LOGPF("Please specify a universe on instance %s", inst[u]->name); goto bail; } //find duplicates for(p = 0; p < u; p++){ if(inst[u]->ident == inst[p]->ident){ - fprintf(stderr, "Colliding sACN instances, use one: %s - %s\n", inst[u]->name, inst[p]->name); + LOGPF("Colliding instances, use one: %s - %s", inst[u]->name, inst[p]->name); goto bail; } } @@ -588,7 +589,7 @@ 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))){ - fprintf(stderr, "Failed to join Multicast group for sACN universe %u on instance %s: %s\n", data->uni, inst[u]->name, strerror(errno)); + LOGPF("Failed to join Multicast group for universe %u on instance %s: %s", data->uni, inst[u]->name, strerror(errno)); } } @@ -596,7 +597,7 @@ static int sacn_start(size_t n, instance** inst){ //add to list of advertised universes for this fd global_cfg.fd[data->fd_index].universe = realloc(global_cfg.fd[data->fd_index].universe, (global_cfg.fd[data->fd_index].universes + 1) * sizeof(uint16_t)); if(!global_cfg.fd[data->fd_index].universe){ - fprintf(stderr, "Failed to allocate memory\n"); + LOG("Failed to allocate memory"); goto bail; } @@ -614,12 +615,12 @@ static int sacn_start(size_t n, instance** inst){ } } - fprintf(stderr, "sACN backend registering %" PRIsize_t " descriptors to core\n", global_cfg.fds); + LOGPF("Registering %" PRIsize_t " descriptors to core", global_cfg.fds); for(u = 0; u < global_cfg.fds; u++){ //allocate memory for storing last frame transmission timestamp global_cfg.fd[u].last_frame = calloc(global_cfg.fd[u].universes, sizeof(uint64_t)); if(!global_cfg.fd[u].last_frame){ - fprintf(stderr, "Failed to allocate memory\n"); + LOG("Failed to allocate memory"); goto bail; } if(mm_manage_fd(global_cfg.fd[u].fd, BACKEND_NAME, 1, (void*) u)){ @@ -645,6 +646,6 @@ static int sacn_shutdown(size_t n, instance** inst){ free(global_cfg.fd[p].last_frame); } free(global_cfg.fd); - fprintf(stderr, "sACN backend shut down\n"); + LOG("Backend shut down"); return 0; } -- cgit v1.2.3