From 18db3856a3a3e81f3e2050e3f137e6e15103f9a4 Mon Sep 17 00:00:00 2001 From: cbdev Date: Tue, 24 Mar 2020 23:04:12 +0100 Subject: Simplify backend code according to new guarantees --- backends/osc.c | 14 +++++--------- 1 file changed, 5 insertions(+), 9 deletions(-) (limited to 'backends/osc.c') diff --git a/backends/osc.c b/backends/osc.c index 754c290..f40f3f5 100644 --- a/backends/osc.c +++ b/backends/osc.c @@ -231,7 +231,7 @@ static int osc_path_validate(char* path, uint8_t allow_patterns){ char pattern_chars[] = "?[]{}*"; size_t u, c; uint8_t square_open = 0, curly_open = 0; - + if(path[0] != '/'){ LOGPF("%s is not a valid OSC path: Missing root /", path); return 1; @@ -331,7 +331,7 @@ static int osc_path_match(char* pattern, char* path){ } if(pattern[match_end + 1] == '-' && pattern[match_end + 2] != ']'){ - if((pattern[match_end] > pattern[match_end + 2] + if((pattern[match_end] > pattern[match_end + 2] && path[u] >= pattern[match_end + 2] && path[u] <= pattern[match_end]) || (pattern[match_end] <= pattern[match_end + 2] @@ -666,7 +666,7 @@ static int osc_output_channel(instance* inst, size_t channel){ memcpy(xmit_buf, data->root, strlen(data->root)); offset += strlen(data->root); } - + memcpy(xmit_buf + offset, data->channel[channel].path, strlen(data->channel[channel].path)); offset += strlen(data->channel[channel].path) + 1; offset = osc_align(offset); @@ -703,16 +703,12 @@ static int osc_output_channel(instance* inst, size_t channel){ static int osc_set(instance* inst, size_t num, channel** c, channel_value* v){ size_t evt = 0, mark = 0; int rv = 0; + osc_instance_data* data = (osc_instance_data*) inst->impl; osc_channel_ident ident = { .label = 0 }; osc_parameter_value current; - if(!num){ - return 0; - } - - osc_instance_data* data = (osc_instance_data*) inst->impl; if(!data->dest_len){ LOGPF("Instance %s does not have a destination, output is disabled (%" PRIsize_t " channels)", inst->name, num); return 0; @@ -747,7 +743,7 @@ static int osc_set(instance* inst, size_t num, channel** c, channel_value* v){ mark = 1; } } - + if(mark){ //output all marked channels for(evt = 0; !rv && evt < num; evt++){ -- cgit v1.2.3 From 11c0c32ec8d7e9185baf733436c221e6742cea84 Mon Sep 17 00:00:00 2001 From: cbdev Date: Fri, 10 Apr 2020 22:43:34 +0200 Subject: Implement OSC bundle format reception (#56) --- backends/osc.c | 105 ++++++++++++++++++++++++++++++++++++++++----------------- 1 file changed, 75 insertions(+), 30 deletions(-) (limited to 'backends/osc.c') diff --git a/backends/osc.c b/backends/osc.c index f40f3f5..72a7b50 100644 --- a/backends/osc.c +++ b/backends/osc.c @@ -10,6 +10,7 @@ /* * TODO * ping method + * bundle output */ #define osc_align(a) ((((a) / 4) + (((a) % 4) ? 1 : 0)) * 4) @@ -720,7 +721,7 @@ static int osc_set(instance* inst, size_t num, channel** c, channel_value* v){ //sanity check if(ident.fields.channel >= data->channels || ident.fields.parameter >= data->channel[ident.fields.channel].params){ - LOG("Channel identifier out of range"); + LOG("Channel identifier out of range, possibly an output channel was not pre-configured"); return 1; } @@ -757,7 +758,7 @@ static int osc_set(instance* inst, size_t num, channel** c, channel_value* v){ return rv; } -static int osc_process_packet(instance* inst, char* local_path, char* format, uint8_t* payload, size_t payload_len){ +static int osc_process_message(instance* inst, char* local_path, char* format, uint8_t* payload, size_t payload_len){ osc_instance_data* data = (osc_instance_data*) inst->impl; size_t c, p, offset = 0; osc_parameter_value min, max, cur; @@ -809,15 +810,82 @@ static int osc_process_packet(instance* inst, char* local_path, char* format, ui return 0; } +static int osc_process_packet(instance* inst, uint8_t* buffer, size_t len){ + osc_instance_data* data = (osc_instance_data*) inst->impl; + size_t offset = 0, message_length = len; + char* osc_local = NULL, *osc_fmt = NULL; + uint8_t* osc_data = NULL; + uint32_t* bundle_size = NULL; + uint8_t decode_bundle = 0; + + //bundles need at least a header and timestamp + if(len >= 16 && !memcmp(buffer, "#bundle\0", 8)){ + decode_bundle = 1; + offset = 16; + } + + do{ + if(decode_bundle){ + if(len - offset < 4){ + LOGPF("Failed to decode bundle size: %" PRIsize_t " bytes left at %" PRIsize_t " of %" PRIsize_t, len - offset, offset, len); + break; + } + bundle_size = (uint32_t*) (buffer + offset); + message_length = be32toh(*bundle_size); + DBGPF("Next bundle entry has %" PRIsize_t " bytes", message_length); + offset += 4; + + if(len - offset < message_length){ + LOGPF("Bundle member size out of bounds: %" PRIsize_t " bytes left", len - offset); + break; + } + } + + //check for recursive bundles + if(message_length >= 16 && !memcmp(buffer + offset, "#bundle\0", 8)){ + DBGPF("Recursing into sub-bundle of size %" PRIsize_t " on %s", message_length, inst->name); + osc_process_packet(inst, buffer + offset, message_length); + } + //ignore messages if root filter active + else if(data->root && strncmp((char*) (buffer + offset), data->root, min(message_length, strlen(data->root)))){ + DBGPF("Ignoring message due to active root filter %s: data is for %s", data->root, buffer + offset); + } + else{ + //FIXME all these accesses should be checked against message_length + osc_local = (char*) (buffer + offset + (data->root ? strlen(data->root) : 0)); + osc_fmt = (char*) (buffer + offset + osc_align(strlen((char*) (buffer + offset)) + 1)); + + if(*osc_fmt != ','){ + //invalid format string + LOGPF("Invalid format string in packet for instance %s: %s", inst->name, osc_fmt); + } + else{ + osc_fmt++; + + if(osc_global_config.detect){ + LOGPF("Incoming data: Path %s.%s Format %s", inst->name, osc_local, osc_fmt); + } + + osc_data = (uint8_t*) osc_fmt + (osc_align(strlen(osc_fmt) + 2) - 1); + if(osc_process_message(inst, osc_local, osc_fmt, osc_data, message_length - (osc_data - (uint8_t*) buffer))){ + LOGPF("Failed to process OSC message on %s", inst->name); + } + } + } + + offset += message_length; + } + while(offset < len); + + return 0; +} + static int osc_handle(size_t num, managed_fd* fds){ size_t fd; - char recv_buf[OSC_RECV_BUF]; + uint8_t recv_buf[OSC_RECV_BUF]; instance* inst = NULL; osc_instance_data* data = NULL; ssize_t bytes_read = 0; - char* osc_fmt = NULL; - char* osc_local = NULL; - uint8_t* osc_data = NULL; for(fd = 0; fd < num; fd++){ inst = (instance*) fds[fd].impl; @@ -841,30 +909,7 @@ static int osc_handle(size_t num, managed_fd* fds){ break; } - if(data->root && strncmp(recv_buf, data->root, min(bytes_read, strlen(data->root)))){ - //ignore packet for different root - continue; - } - osc_local = recv_buf + (data->root ? strlen(data->root) : 0); - - osc_fmt = recv_buf + osc_align(strlen(recv_buf) + 1); - if(*osc_fmt != ','){ - //invalid format string - LOGPF("Invalid format string in packet for instance %s", inst->name); - continue; - } - osc_fmt++; - - if(osc_global_config.detect){ - LOGPF("Incoming data: Path %s.%s Format %s", inst->name, osc_local, osc_fmt); - } - - //FIXME check supplied data length - osc_data = (uint8_t*) osc_fmt + (osc_align(strlen(osc_fmt) + 2) - 1); - - if(osc_process_packet(inst, osc_local, osc_fmt, osc_data, bytes_read - (osc_data - (uint8_t*) recv_buf))){ - return 1; - } + osc_process_packet(inst, recv_buf, bytes_read); } while(bytes_read > 0); #ifdef _WIN32 -- cgit v1.2.3