diff --git a/Makefile b/Makefile index fbb3d45..7f8b4f3 100644 --- a/Makefile +++ b/Makefile @@ -2,7 +2,7 @@ Q=@ CC=gcc GCCCFLAGS=-Wno-format-truncation -CFLAGS=-std=c11 -pedantic -g -Wall -pthread -D_GNU_SOURCE +CFLAGS=-std=gnu11 -pedantic -g -Wall -pthread -D_GNU_SOURCE -fsanitize=address LDFLAGS=-lm # The root for /sys and /dev needs to be moved in docker, this should stay empty in most cases diff --git a/client.c b/client.c index 726c8d7..5a3d212 100644 --- a/client.c +++ b/client.c @@ -37,13 +37,13 @@ static struct pollfd *socket_poll = &poll_fds[1]; static int fifo = -1; static int sock = -1; // static to avoid having this on the stack because a message is about 2kb in memory -static Message message; +static DeviceMessage message; static Vec devices_fd; static Vec devices_info; -static ClientConfig config; -static MessageRequest device_request; +static ClientConfig config; +static DeviceRequest device_request; static void default_fifo_path(void *ptr) { *(char **)ptr = (char *)FIFO_PATH; } static void default_retry_delay(void *ptr) { *(struct timespec *)ptr = CONNECTION_RETRY_DELAY; } @@ -58,17 +58,17 @@ static void default_to_white(void *ptr) { } static const JSONPropertyAdapter ControllerStateAdapterProps[] = { - {".led_color", &StringAdapter, offsetof(MessageControllerState, led), default_to_white, tsf_hex_to_color }, - {".rumble.0", &NumberAdapter, offsetof(MessageControllerState, small_rumble), default_to_zero_u8, tsf_num_to_u8_clamp}, - {".rumble.1", &NumberAdapter, offsetof(MessageControllerState, big_rumble), default_to_zero_u8, tsf_num_to_u8_clamp}, - {".flash.0", &NumberAdapter, offsetof(MessageControllerState, flash_on), default_to_zero_u8, tsf_num_to_u8_clamp}, - {".flash.1", &NumberAdapter, offsetof(MessageControllerState, flash_off), default_to_zero_u8, tsf_num_to_u8_clamp}, - {".index", &NumberAdapter, offsetof(MessageControllerState, index), default_to_zero_u32, tsf_num_to_int } + {".led_color", &StringAdapter, offsetof(DeviceControllerState, led), default_to_white, tsf_hex_to_color }, + {".rumble.0", &NumberAdapter, offsetof(DeviceControllerState, small_rumble), default_to_zero_u8, tsf_num_to_u8_clamp}, + {".rumble.1", &NumberAdapter, offsetof(DeviceControllerState, big_rumble), default_to_zero_u8, tsf_num_to_u8_clamp}, + {".flash.0", &NumberAdapter, offsetof(DeviceControllerState, flash_on), default_to_zero_u8, tsf_num_to_u8_clamp}, + {".flash.1", &NumberAdapter, offsetof(DeviceControllerState, flash_off), default_to_zero_u8, tsf_num_to_u8_clamp}, + {".index", &NumberAdapter, offsetof(DeviceControllerState, index), default_to_zero_u32, tsf_num_to_int } }; static const JSONAdapter ControllerStateAdapter = { .props = (JSONPropertyAdapter *)ControllerStateAdapterProps, .prop_count = sizeof(ControllerStateAdapterProps) / sizeof(JSONPropertyAdapter), - .size = sizeof(MessageControllerState), + .size = sizeof(DeviceControllerState), }; static const JSONPropertyAdapter ControllerAdapterProps[] = { @@ -127,12 +127,12 @@ static void print_config() { void destroy_devices(void) { for (int i = 0; i < config.slot_count; i++) { - int fd = *(int *)vec_get(&devices_fd, i); - MessageDeviceInfo *info = vec_get(&devices_info, i); + int fd = *(int *)vec_get(&devices_fd, i); + DeviceInfo *info = vec_get(&devices_info, i); - if (info->code == DeviceInfo) { + if (info->tag == DeviceTagInfo) { ioctl(fd, UI_DEV_DESTROY); - info->code = NoMessage; + info->tag = DeviceTagNone; } } } @@ -142,8 +142,8 @@ bool device_exists(int index) { return false; } - MessageDeviceInfo *info = vec_get(&devices_info, index); - return info->code == DeviceInfo; + DeviceInfo *info = vec_get(&devices_info, index); + return info->tag == DeviceTagInfo; } void device_destroy(int slot) { @@ -153,15 +153,15 @@ void device_destroy(int slot) { int fd = *(int *)vec_get(&devices_fd, slot); - MessageDeviceInfo *info = vec_get(&devices_info, slot); + DeviceInfo *info = vec_get(&devices_info, slot); - if (info->code == DeviceInfo) { + if (info->tag == DeviceTagInfo) { ioctl(fd, UI_DEV_DESTROY); - info->code = NoMessage; + info->tag = DeviceTagNone; } } -void device_init(MessageDeviceInfo *dev) { +void device_init(DeviceInfo *dev) { if (dev->slot >= devices_info.len) { printf("CLIENT: Got wrong device index\n"); return; @@ -172,35 +172,36 @@ void device_init(MessageDeviceInfo *dev) { int fd = *(int *)vec_get(&devices_fd, dev->slot); // Abs - if (dev->abs_count > 0) { + if (dev->abs.len > 0) { ioctl(fd, UI_SET_EVBIT, EV_ABS); - for (int i = 0; i < dev->abs_count; i++) { + for (int i = 0; i < dev->abs.len; i++) { struct uinput_abs_setup setup = {0}; - setup.code = dev->abs_id[i]; - setup.absinfo.minimum = dev->abs_min[i]; - setup.absinfo.maximum = dev->abs_max[i]; - setup.absinfo.fuzz = dev->abs_fuzz[i]; - setup.absinfo.flat = dev->abs_flat[i]; - setup.absinfo.resolution = dev->abs_res[i]; + Abs abs = dev->abs.data[i]; + setup.code = abs.id; + setup.absinfo.minimum = abs.min; + setup.absinfo.maximum = abs.max; + setup.absinfo.fuzz = abs.fuzz; + setup.absinfo.flat = abs.flat; + setup.absinfo.resolution = abs.res; setup.absinfo.value = 0; ioctl(fd, UI_ABS_SETUP, &setup); } } // Rel - if (dev->rel_count > 0) { + if (dev->rel.len > 0) { ioctl(fd, UI_SET_EVBIT, EV_REL); - for (int i = 0; i < dev->rel_count; i++) { - ioctl(fd, UI_SET_RELBIT, dev->rel_id[i]); + for (int i = 0; i < dev->rel.len; i++) { + ioctl(fd, UI_SET_RELBIT, dev->rel.data[i].id); } } // Key - if (dev->key_count > 0) { + if (dev->key.len > 0) { ioctl(fd, UI_SET_EVBIT, EV_KEY); - for (int i = 0; i < dev->key_count; i++) { - ioctl(fd, UI_SET_KEYBIT, dev->key_id[i]); + for (int i = 0; i < dev->key.len; i++) { + ioctl(fd, UI_SET_KEYBIT, dev->key.data[i].id); } } @@ -217,11 +218,11 @@ void device_init(MessageDeviceInfo *dev) { ioctl(fd, UI_DEV_SETUP, &setup); ioctl(fd, UI_DEV_CREATE); - MessageDeviceInfo *dst = vec_get(&devices_info, dev->slot); + DeviceInfo *dst = vec_get(&devices_info, dev->slot); - memcpy(dst, dev, sizeof(MessageDeviceInfo)); - printf("CLIENT: Got device [%d]: '%s' (abs: %d, rel: %d, key: %d)\n", dev->slot, ctr->device_name, dev->abs_count, - dev->rel_count, dev->key_count); + memcpy(dst, dev, sizeof(DeviceInfo)); + printf("CLIENT: Got device [%d]: '%s' (abs: %d, rel: %d, key: %d)\n", dev->slot, ctr->device_name, dev->abs.len, dev->rel.len, + dev->key.len); } // Send an event to uinput, device must exist @@ -241,33 +242,34 @@ bool device_emit(int index, uint16_t type, uint16_t id, uint32_t value) { } // Update device with report -void device_handle_report(MessageDeviceReport *report) { +void device_handle_report(DeviceReport *report) { if (!device_exists(report->slot)) { printf("CLIENT: [%d] Got report before device info\n", report->slot); return; } - MessageDeviceInfo *info = vec_get(&devices_info, report->slot); + DeviceInfo *info = vec_get(&devices_info, report->slot); - if (report->abs_count != info->abs_count || report->rel_count != info->rel_count || report->key_count != info->key_count) { - printf("CLIENT: Report doesn't match with device info\n"); + if (report->abs.len != info->abs.len || report->rel.len != info->rel.len || report->key.len != info->key.len) { + printf("CLIENT: Report doesn't match with device info (expected %u/%u/%u, got %u/%u/%u)\n", info->abs.len, info->rel.len, + info->key.len, report->abs.len, report->rel.len, report->key.len); return; } - for (int i = 0; i < report->abs_count; i++) { - if (device_emit(report->slot, EV_ABS, info->abs_id[i], report->abs[i]) != 0) { + for (int i = 0; i < report->abs.len; i++) { + if (device_emit(report->slot, EV_ABS, info->abs.data[i].id, report->abs.data[i]) != 0) { printf("CLIENT: Error writing abs event to uinput\n"); } } - for (int i = 0; i < report->rel_count; i++) { - if (device_emit(report->slot, EV_REL, info->rel_id[i], report->rel[i]) != 0) { + for (int i = 0; i < report->rel.len; i++) { + if (device_emit(report->slot, EV_REL, info->rel.data[i].id, report->rel.data[i]) != 0) { printf("CLIENT: Error writing rel event to uinput\n"); } } - for (int i = 0; i < report->key_count; i++) { - if (device_emit(report->slot, EV_KEY, info->key_id[i], (uint32_t)(!report->key[i]) - 1) != 0) { + for (int i = 0; i < report->key.len; i++) { + if (device_emit(report->slot, EV_KEY, info->key.data[i].id, (uint32_t)(!report->key.data[i]) - 1) != 0) { printf("CLIENT: Error writing key event to uinput\n"); } } @@ -278,10 +280,10 @@ void device_handle_report(MessageDeviceReport *report) { void setup_devices(void) { devices_fd = vec_of(int); - devices_info = vec_of(MessageDeviceInfo); + devices_info = vec_of(DeviceInfo); - MessageDeviceInfo no_info = {0}; - no_info.code = NoMessage; + DeviceInfo no_info = {0}; + no_info.tag = DeviceTagNone; for (int i = 0; i < config.slot_count; i++) { int fd = open(FSROOT "/dev/uinput", O_WRONLY | O_NONBLOCK); @@ -350,9 +352,9 @@ void connect_server(void) { socket_poll->fd = sock; printf("CLIENT: Connected !\n"); - uint8_t buf[2048] __attribute__((aligned(4))) = {0}; + uint8_t buf[2048] __attribute__((aligned(8))) = {0}; - int len = msg_serialize(buf, 2048, (Message *)&device_request); + int len = msg_device_serialize(buf, 2048, (DeviceMessage *)&device_request); if (len > 0) { if (send(sock, buf, len, 0) > 0) { printf("CLIENT: Sent device request\n"); @@ -382,20 +384,20 @@ void setup_server(char *address, uint16_t port) { } void build_device_request(void) { - TagList *reqs = malloc(config.slot_count * sizeof(TagList)); + device_request.tag = DeviceTagRequest; + device_request.requests.len = config.slot_count; + device_request.requests.data = malloc(config.slot_count * sizeof(TagList)); for (int i = 0; i < config.slot_count; i++) { - TagList *req = &reqs[i]; - req->count = config.slots[i].controller_count; - req->tags = malloc(req->count * sizeof(char *)); + TagList *list = &device_request.requests.data[i]; + list->tags.len = config.slots[i].controller_count; + list->tags.data = malloc(list->tags.len * sizeof(typeof(*list->tags.data))); - for (int j = 0; j < req->count; j++) { - req->tags[j] = config.slots[i].controllers[j].tag; + for (int j = 0; j < list->tags.len; j++) { + char *name = config.slots[i].controllers[j].tag; + list->tags.data[j].name.len = strlen(name); + list->tags.data[j].name.data = name; } } - - device_request.code = Request; - device_request.request_count = config.slot_count; - device_request.requests = reqs; } void client_run(char *address, uint16_t port, char *config_path) { @@ -431,10 +433,10 @@ void client_run(char *address, uint16_t port, char *config_path) { setup_devices(); setup_server(address, port); - uint8_t buf[2048] __attribute__((aligned(4))); + uint8_t buf[2048] __attribute__((aligned(8))); uint8_t json_buf[2048] __attribute__((aligned(8))); - while (1) { + while (true) { int rc = poll(poll_fds, 2, -1); if (rc < 0) { perror("CLIENT: Error on poll"); @@ -451,11 +453,11 @@ void client_run(char *address, uint16_t port, char *config_path) { if (rc < 0) { printf("CLIENT: Error when parsing fifo message as json (%s at index %lu)\n", json_strerr(), json_errloc()); } else { - MessageControllerState msg; - msg.code = ControllerState; + DeviceControllerState msg; + msg.tag = DeviceTagControllerState; json_adapt(json_buf, &ControllerStateAdapter, &msg); - int len = msg_serialize(buf, 2048, (Message *)&msg); + int len = msg_device_serialize(buf, 2048, (DeviceMessage *)&msg); if (len > 0) { if (send(sock, buf, len, 0) > 0) { printf("CLIENT: Sent controller state: #%02x%02x%02x flash: (%d, %d) rumble: " @@ -479,7 +481,7 @@ void client_run(char *address, uint16_t port, char *config_path) { continue; } - int msg_len = msg_deserialize(buf, len, &message); + int msg_len = msg_device_deserialize(buf, len, &message); // We've got data from the server if (msg_len < 0) { recv(sock, buf, 2048, 0); @@ -500,15 +502,15 @@ void client_run(char *address, uint16_t port, char *config_path) { recv(sock, buf, msg_len, 0); - if (message.code == DeviceInfo) { - if (device_exists(message.device_info.slot)) { + if (message.tag == DeviceTagInfo) { + if (device_exists(message.info.slot)) { printf("CLIENT: Got more than one device info for same device\n"); } - device_init((MessageDeviceInfo *)&message); - } else if (message.code == DeviceReport) { - device_handle_report((MessageDeviceReport *)&message); - } else if (message.code == DeviceDestroy) { + device_init((DeviceInfo *)&message); + } else if (message.tag == DeviceTagReport) { + device_handle_report((DeviceReport *)&message); + } else if (message.tag == DeviceTagDestroy) { device_destroy(message.destroy.index); printf("CLIENT: Lost device %d\n", message.destroy.index); } else { diff --git a/hid.c b/hid.c index 27c0050..da1ae42 100644 --- a/hid.c +++ b/hid.c @@ -55,10 +55,10 @@ uniq_t parse_uniq(char uniq[17]) { // Finish setup of a partially initialized device (set device_info and mapping) void setup_device(PhysicalDevice *dev) { - dev->device_info.code = DeviceInfo; - dev->device_info.abs_count = 0; - dev->device_info.rel_count = 0; - dev->device_info.key_count = 0; + dev->device_info.tag = DeviceTagInfo; + dev->device_info.abs.len = 0; + dev->device_info.rel.len = 0; + dev->device_info.key.len = 0; for (int i = 0; i < ABS_CNT; i++) dev->mapping.abs_indices[i] = -1; @@ -93,26 +93,27 @@ void setup_device(PhysicalDevice *dev) { struct input_absinfo abs; ioctl(dev->event, EVIOCGABS(i), &abs); - uint16_t index = dev->device_info.abs_count++; + uint16_t index = dev->device_info.abs.len++; - dev->device_info.abs_min[index] = abs.minimum; - dev->device_info.abs_max[index] = abs.maximum; - dev->device_info.abs_fuzz[index] = abs.fuzz; - dev->device_info.abs_flat[index] = abs.flat; - dev->device_info.abs_res[index] = abs.resolution; + Abs *dev_abs = &dev->device_info.abs.data[index]; + dev_abs->min = abs.minimum; + dev_abs->max = abs.maximum; + dev_abs->fuzz = abs.fuzz; + dev_abs->flat = abs.flat; + dev_abs->res = abs.resolution; + dev_abs->id = i; // Bidirectional mapping id <-> index // We need this to avoid wasting space in packets because ids are sparse - dev->device_info.abs_id[index] = i; - dev->mapping.abs_indices[i] = index; + dev->mapping.abs_indices[i] = index; } else if (type == EV_REL) { - uint16_t index = dev->device_info.rel_count++; + uint16_t index = dev->device_info.rel.len++; - dev->device_info.rel_id[index] = i; + dev->device_info.rel.data[index].id = i; dev->mapping.rel_indices[i] = index; } else if (type == EV_KEY) { - uint16_t index = dev->device_info.key_count++; + uint16_t index = dev->device_info.key.len++; - dev->device_info.key_id[index] = i; + dev->device_info.key.data[index].id = i; dev->mapping.key_indices[i] = index; } } @@ -445,7 +446,7 @@ void poll_devices(void) { } // "Execute" a MessageControllerState: set the led color, rumble and flash using the hidraw interface (Dualshock 4 only) -void apply_controller_state(Controller *c, MessageControllerState *state) { +void apply_controller_state(Controller *c, DeviceControllerState *state) { if (c->ctr.ps4_hidraw && c->dev.hidraw < 0) { printf("HID: Trying to apply controller state on incompatible device (%lu)\n", c->dev.id); return; diff --git a/hid.h b/hid.h index daf6191..8bc308b 100644 --- a/hid.h +++ b/hid.h @@ -30,7 +30,7 @@ typedef struct { uint64_t id; char *name; DeviceMap mapping; - MessageDeviceInfo device_info; + DeviceInfo device_info; } PhysicalDevice; typedef struct { @@ -42,6 +42,6 @@ void *hid_thread(void *arg); void return_device(Controller *c); void forget_device(Controller *c); bool get_device(char **tags, size_t tag_count, bool *stop, Controller *res, uint8_t *index); -void apply_controller_state(Controller *c, MessageControllerState *state); +void apply_controller_state(Controller *c, DeviceControllerState *state); #endif diff --git a/net.c b/net.c index 00f8a6e..b6c4022 100644 --- a/net.c +++ b/net.c @@ -1,434 +1,286 @@ +// Generated file, do not edit (its not like it'll explode if you do, but its better not to) #include "net.h" - -#include "util.h" - -#include #include -#include -// Deserialize the message in buf, buf must be at least 4 aligned. Returns -1 on error, otherwise returns 0 -// and writes result to dst -int msg_deserialize(const uint8_t *buf, size_t len, Message *restrict dst) { - { - if (len <= MAGIC_SIZE) { - return -1; - } - - if (*(MAGIC_TYPE *)buf != MAGIC_BEG) { - printf("NET: No magic in message\n"); - return -1; - } - - buf += MAGIC_SIZE; - len -= MAGIC_SIZE; - } - // Decrement len so that it becomes the len of the data without the code. - if (len-- < 1) +int msg_device_serialize(byte *buf, size_t len, DeviceMessage *msg) { + const byte *base_buf = buf; + if(len < 2 * MSG_MAGIC_SIZE) return -1; - // This ensures that only a byte is read instead of a full enum value - uint8_t code_byte = buf[0]; - MessageCode code = (MessageCode)code_byte; - uint32_t size = 0; - - uint16_t abs, rel, key, *buf16; - uint8_t index, slot; - - switch (code) { - case DeviceInfo: - if (len < 7) - return -1; - slot = buf[2]; - index = buf[3]; - // buf + 4: a byte for, code, padding, slot, index - buf16 = (uint16_t *)(buf + 4); - abs = buf16[0]; - rel = buf16[1]; - key = buf16[2]; - buf += 12; - if (MSS_DEVICE_INFO(abs, rel, key) > len) - return -1; - - dst->device_info.code = code; - dst->device_info.slot = slot; - dst->device_info.index = index; - dst->device_info.abs_count = abs; - dst->device_info.rel_count = rel; - dst->device_info.key_count = key; - - // SOA in c but serialized as AOS - for (int i = 0; i < abs; i++) { - // buf + 4: 2 bytes for id and 2 bytes of padding - uint32_t *buf32 = (uint32_t *)(buf + 4); - - dst->device_info.abs_id[i] = *(uint16_t *)buf; - dst->device_info.abs_min[i] = buf32[0]; - dst->device_info.abs_max[i] = buf32[1]; - dst->device_info.abs_fuzz[i] = buf32[2]; - dst->device_info.abs_flat[i] = buf32[3]; - dst->device_info.abs_res[i] = buf32[4]; - + *(MsgMagic*)buf = MSG_MAGIC_START; + buf += MSG_MAGIC_SIZE; + switch(msg->tag) { + case DeviceTagNone: + break; + case DeviceTagInfo: { + *(uint16_t *)buf = DeviceTagInfo; + *(uint16_t *)&buf[2] = msg->info.key.len; + *(uint8_t *)&buf[4] = msg->info.slot; + *(uint8_t *)&buf[5] = msg->info.index; + *(uint8_t *)&buf[6] = msg->info.abs.len; + *(uint8_t *)&buf[7] = msg->info.rel.len; + buf += 8; + for(size_t i = 0; i < msg->info.abs.len; i++) { + typeof(msg->info.abs.data[i]) e0 = msg->info.abs.data[i]; + *(uint32_t *)&buf[0] = e0.min; + *(uint32_t *)&buf[4] = e0.max; + *(uint32_t *)&buf[8] = e0.fuzz; + *(uint32_t *)&buf[12] = e0.flat; + *(uint32_t *)&buf[16] = e0.res; + *(uint16_t *)&buf[20] = e0.id; buf += 24; } - - for (int i = 0; i < rel; i++) { - dst->device_info.rel_id[i] = *(uint16_t *)buf; + for(size_t i = 0; i < msg->info.rel.len; i++) { + typeof(msg->info.rel.data[i]) e0 = msg->info.rel.data[i]; + *(uint16_t *)&buf[0] = e0.id; buf += 2; } - - for (int i = 0; i < key; i++) { - dst->device_info.key_id[i] = *(uint16_t *)buf; + for(size_t i = 0; i < msg->info.key.len; i++) { + typeof(msg->info.key.data[i]) e0 = msg->info.key.data[i]; + *(uint16_t *)&buf[0] = e0.id; buf += 2; } - - size = MSS_DEVICE_INFO(abs, rel, key) + 1; + buf = (byte*)(((((uintptr_t)buf - 1) >> 3) + 1) << 3); break; - case DeviceReport: - if (len < 7) - return -1; - - slot = buf[2]; - index = buf[3]; - // buf + 4: a byte for, code, padding, slot and index - buf16 = (uint16_t *)(buf + 4); - abs = buf16[0]; - rel = buf16[1]; - key = buf16[2]; - buf += 12; - if (len < MSS_DEVICE_REPORT(abs, rel, key)) - return -1; - - dst->device_report.code = code; - dst->device_report.slot = slot; - dst->device_report.index = index; - dst->device_report.abs_count = abs; - dst->device_report.rel_count = rel; - dst->device_report.key_count = key; - - for (int i = 0; i < abs; i++) { - dst->device_report.abs[i] = *(uint32_t *)buf; + } + case DeviceTagReport: { + *(uint16_t *)buf = DeviceTagReport; + *(uint16_t *)&buf[2] = msg->report.key.len; + *(uint8_t *)&buf[4] = msg->report.slot; + *(uint8_t *)&buf[5] = msg->report.index; + *(uint8_t *)&buf[6] = msg->report.abs.len; + *(uint8_t *)&buf[7] = msg->report.rel.len; + buf += 8; + for(size_t i = 0; i < msg->report.abs.len; i++) { + typeof(msg->report.abs.data[i]) e0 = msg->report.abs.data[i]; + *(uint32_t *)&buf[0] = e0; buf += 4; } - - for (int i = 0; i < rel; i++) { - dst->device_report.rel[i] = *(uint32_t *)buf; + for(size_t i = 0; i < msg->report.rel.len; i++) { + typeof(msg->report.rel.data[i]) e0 = msg->report.rel.data[i]; + *(uint32_t *)&buf[0] = e0; buf += 4; } - - for (int i = 0; i < key; i++) - dst->device_report.key[i] = *(buf++); - - buf += align_4(key) - key; - - size = MSS_DEVICE_REPORT(abs, rel, key) + 1; + for(size_t i = 0; i < msg->report.key.len; i++) { + typeof(msg->report.key.data[i]) e0 = msg->report.key.data[i]; + *(uint8_t *)&buf[0] = e0; + buf += 1; + } + buf = (byte*)(((((uintptr_t)buf - 1) >> 3) + 1) << 3); break; - case ControllerState: - if (len < MSS_CONTROLLER_STATE) - return -1; - - dst->code = code; - dst->controller_state.index = *(uint16_t *)(buf + 2); - dst->controller_state.led[0] = buf[4]; - dst->controller_state.led[1] = buf[5]; - dst->controller_state.led[2] = buf[6]; - dst->controller_state.small_rumble = buf[7]; - dst->controller_state.big_rumble = buf[8]; - dst->controller_state.flash_on = buf[9]; - dst->controller_state.flash_off = buf[10]; - size = MSS_CONTROLLER_STATE + 1; - buf += size; + } + case DeviceTagControllerState: { + *(uint16_t *)buf = DeviceTagControllerState; + *(uint16_t *)&buf[2] = msg->controller_state.index; + *(uint8_t *)&buf[4] = msg->controller_state.led[0]; + *(uint8_t *)&buf[5] = msg->controller_state.led[1]; + *(uint8_t *)&buf[6] = msg->controller_state.led[2]; + *(uint8_t *)&buf[7] = msg->controller_state.small_rumble; + *(uint8_t *)&buf[8] = msg->controller_state.big_rumble; + *(uint8_t *)&buf[9] = msg->controller_state.flash_on; + *(uint8_t *)&buf[10] = msg->controller_state.flash_off; + buf += 16; break; - case Request: { - if (len < 3) - return -1; - - dst->code = code; - dst->request.request_count = *(uint16_t *)(buf + 2); - buf += 4; // 1 bytes for code, 1 byte for padding and 2 bytes for count - - int count = dst->request.request_count; - TagList *reqs = malloc(count * sizeof(TagList)); - // The length of the message, will be updated as we read more. - int expected_len = 3; - - for (int i = 0; i < dst->request.request_count; i++) { - expected_len += 2; - if (len < expected_len) { - return -1; - } - - TagList *tags = &reqs[i]; - tags->count = *(uint16_t *)buf; - tags->tags = malloc(tags->count * sizeof(char *)); + } + case DeviceTagRequest: { + *(uint16_t *)buf = DeviceTagRequest; + msg->request._version = 1UL; + *(uint64_t *)&buf[8] = msg->request._version; + *(uint16_t *)&buf[16] = msg->request.requests.len; + buf += 18; + for(size_t i = 0; i < msg->request.requests.len; i++) { + typeof(msg->request.requests.data[i]) e0 = msg->request.requests.data[i]; + *(uint16_t *)&buf[0] = e0.tags.len; buf += 2; - - for (int j = 0; j < tags->count; j++) { - expected_len += 2; - if (len < expected_len) { - return -1; - } - - uint16_t str_len = *(uint16_t *)buf; + for(size_t i = 0; i < e0.tags.len; i++) { + typeof(e0.tags.data[i]) e1 = e0.tags.data[i]; + *(uint16_t *)&buf[0] = e1.name.len; buf += 2; - - expected_len += align_2(str_len); - if (len < expected_len) { - return -1; + for(size_t i = 0; i < e1.name.len; i++) { + typeof(e1.name.data[i]) e2 = e1.name.data[i]; + *(char *)&buf[0] = e2; + buf += 1; } - - char *str = malloc(str_len + 1); - str[str_len] = '\0'; - - strncpy(str, (char *)buf, str_len); - - tags->tags[j] = str; - - buf += align_2(str_len); + buf = (byte*)(((((uintptr_t)buf - 1) >> 1) + 1) << 1); } + buf = (byte*)(((((uintptr_t)buf - 1) >> 1) + 1) << 1); } - - dst->request.requests = reqs; - size = expected_len + 1; + buf = (byte*)(((((uintptr_t)buf - 1) >> 3) + 1) << 3); break; } - case DeviceDestroy: - if (len < MSS_DESTROY) - return -1; - - dst->code = code; - dst->destroy.index = *(uint16_t *)(buf + 2); - size = MSS_DESTROY + 1; - buf += size; + case DeviceTagDestroy: { + *(uint16_t *)buf = DeviceTagDestroy; + *(uint16_t *)&buf[2] = msg->destroy.index; + buf += 8; break; - default: - return -1; } - - if (align_m(size) + MAGIC_SIZE > len + 1) { - return -1; } - - // WARN: This is technically bad, but should be ok nonetheless - MAGIC_TYPE *mbuf = (MAGIC_TYPE *)align_m((uintptr_t)buf); - - if (*mbuf != MAGIC_END) { - printf("NET: Magic not found\n"); + *(MsgMagic*)buf = MSG_MAGIC_END; + buf += MSG_MAGIC_SIZE; + if(buf > base_buf + len) return -1; - } - - return align_m(size) + 2 * MAGIC_SIZE; + return (int)(buf - base_buf); } -// Serialize the message msg in buf, buf must be at least 4 aligned. Returns -1 on error (buf not big enough); -int msg_serialize(uint8_t *restrict buf, size_t len, const Message *msg) { - // If len is less than the two magic and the code we can't serialize any message - if (len < MAGIC_SIZE * 2 + 1) +int msg_device_deserialize(const byte *buf, size_t len, DeviceMessage *msg) { + const byte *base_buf = buf; + if(len < 2 * MSG_MAGIC_SIZE) return -1; - - *(MAGIC_TYPE *)buf = MAGIC_BEG; - buf += MAGIC_SIZE; - len -= MAGIC_SIZE + 1; - - uint16_t abs, rel, key, *buf16; - uint32_t size; - - switch (msg->code) { - case DeviceInfo: - abs = msg->device_info.abs_count; - rel = msg->device_info.rel_count; - key = msg->device_info.key_count; - if (len < MSS_DEVICE_INFO(abs, rel, key)) - return -1; - - buf[0] = (uint8_t)msg->code; - // 1 byte of padding - buf[2] = (uint8_t)msg->device_info.slot; - buf[3] = (uint8_t)msg->device_info.index; - // buf + 4: a byte for, code, padding, slot, index - buf16 = (uint16_t *)(buf + 4); - buf16[0] = abs; - buf16[1] = rel; - buf16[2] = key; - buf += 12; - - // Back to 4 aligned - for (int i = 0; i < abs; i++) { - // buf + 4: 2 bytes for id and 2 bytes of padding - uint32_t *buf32 = (uint32_t *)(buf + 4); - - *(uint16_t *)buf = msg->device_info.abs_id[i]; - - buf32[0] = msg->device_info.abs_min[i]; - buf32[1] = msg->device_info.abs_max[i]; - buf32[2] = msg->device_info.abs_fuzz[i]; - buf32[3] = msg->device_info.abs_flat[i]; - buf32[4] = msg->device_info.abs_res[i]; - + if(*(MsgMagic*)buf != MSG_MAGIC_START) + return -1; + buf += MSG_MAGIC_SIZE; + DeviceTag tag = *(uint16_t*)buf; + switch(tag) { + case DeviceTagNone: + break; + case DeviceTagInfo: { + msg->tag = DeviceTagInfo; + msg->info.key.len = *(uint16_t *)&buf[2]; + msg->info.slot = *(uint8_t *)&buf[4]; + msg->info.index = *(uint8_t *)&buf[5]; + msg->info.abs.len = *(uint8_t *)&buf[6]; + msg->info.rel.len = *(uint8_t *)&buf[7]; + buf += 8; + for(size_t i = 0; i < msg->info.abs.len; i++) { + typeof(&msg->info.abs.data[i]) e0 = &msg->info.abs.data[i]; + e0->min = *(uint32_t *)&buf[0]; + e0->max = *(uint32_t *)&buf[4]; + e0->fuzz = *(uint32_t *)&buf[8]; + e0->flat = *(uint32_t *)&buf[12]; + e0->res = *(uint32_t *)&buf[16]; + e0->id = *(uint16_t *)&buf[20]; buf += 24; } - // Still 4 aligned - for (int i = 0; i < rel; i++) { - *(uint16_t *)buf = msg->device_info.rel_id[i]; + for(size_t i = 0; i < msg->info.rel.len; i++) { + typeof(&msg->info.rel.data[i]) e0 = &msg->info.rel.data[i]; + e0->id = *(uint16_t *)&buf[0]; buf += 2; } - - for (int i = 0; i < key; i++) { - *(uint16_t *)buf = msg->device_info.key_id[i]; + for(size_t i = 0; i < msg->info.key.len; i++) { + typeof(&msg->info.key.data[i]) e0 = &msg->info.key.data[i]; + e0->id = *(uint16_t *)&buf[0]; buf += 2; } - - size = MSS_DEVICE_INFO(abs, rel, key) + 1; + buf = (byte*)(((((uintptr_t)buf - 1) >> 3) + 1) << 3); break; - case DeviceReport: - abs = msg->device_report.abs_count; - rel = msg->device_report.rel_count; - key = msg->device_report.key_count; - if (len < MSS_DEVICE_REPORT(abs, rel, key)) - return -1; - - buf[0] = (uint8_t)msg->code; - // 1 byte of padding - buf[2] = msg->device_report.slot; - buf[3] = msg->device_report.index; - // buf + 4: a byte for, code, padding, slot and index - buf16 = (uint16_t *)(buf + 4); - buf16[0] = abs; - buf16[1] = rel; - buf16[2] = key; - buf += 12; - // We're 4 aligned already - for (int i = 0; i < abs; i++) { - *(uint32_t *)buf = msg->device_report.abs[i]; + } + case DeviceTagReport: { + msg->tag = DeviceTagReport; + msg->report.key.len = *(uint16_t *)&buf[2]; + msg->report.slot = *(uint8_t *)&buf[4]; + msg->report.index = *(uint8_t *)&buf[5]; + msg->report.abs.len = *(uint8_t *)&buf[6]; + msg->report.rel.len = *(uint8_t *)&buf[7]; + buf += 8; + for(size_t i = 0; i < msg->report.abs.len; i++) { + typeof(&msg->report.abs.data[i]) e0 = &msg->report.abs.data[i]; + *e0 = *(uint32_t *)&buf[0]; buf += 4; } - // Still 4 aligned - for (int i = 0; i < rel; i++) { - *(uint32_t *)buf = msg->device_report.rel[i]; + for(size_t i = 0; i < msg->report.rel.len; i++) { + typeof(&msg->report.rel.data[i]) e0 = &msg->report.rel.data[i]; + *e0 = *(uint32_t *)&buf[0]; buf += 4; } - // Doesn't matter since we're writing individual bytes - for (int i = 0; i < key; i++) - *(buf++) = msg->device_report.key[i]; - - size = MSS_DEVICE_REPORT(abs, rel, key) + 1; - buf += align_4(key) - key; + for(size_t i = 0; i < msg->report.key.len; i++) { + typeof(&msg->report.key.data[i]) e0 = &msg->report.key.data[i]; + *e0 = *(uint8_t *)&buf[0]; + buf += 1; + } + buf = (byte*)(((((uintptr_t)buf - 1) >> 3) + 1) << 3); break; - case ControllerState: - if (len < MSS_CONTROLLER_STATE) - return -1; - - buf[0] = (uint8_t)msg->code; - - *(uint16_t *)(buf + 2) = msg->controller_state.index; - - buf[4] = msg->controller_state.led[0]; - buf[5] = msg->controller_state.led[1]; - buf[6] = msg->controller_state.led[2]; - buf[7] = msg->controller_state.small_rumble; - buf[8] = msg->controller_state.big_rumble; - buf[9] = msg->controller_state.flash_on; - buf[10] = msg->controller_state.flash_off; - size = MSS_CONTROLLER_STATE + 1; - buf += size; + } + case DeviceTagControllerState: { + msg->tag = DeviceTagControllerState; + msg->controller_state.index = *(uint16_t *)&buf[2]; + msg->controller_state.led[0] = *(uint8_t *)&buf[4]; + msg->controller_state.led[1] = *(uint8_t *)&buf[5]; + msg->controller_state.led[2] = *(uint8_t *)&buf[6]; + msg->controller_state.small_rumble = *(uint8_t *)&buf[7]; + msg->controller_state.big_rumble = *(uint8_t *)&buf[8]; + msg->controller_state.flash_on = *(uint8_t *)&buf[9]; + msg->controller_state.flash_off = *(uint8_t *)&buf[10]; + buf += 16; break; - case Request: { - int expected_len = MSS_REQUEST(msg->request.request_count); - if (len < expected_len) - return -1; - - buf[0] = (uint8_t)msg->code; - buf += 2; - *(uint16_t *)buf = msg->request.request_count; - buf += 2; - - for (int i = 0; i < msg->request.request_count; i++) { - - uint16_t tag_count = msg->request.requests[i].count; - char **tags = msg->request.requests[i].tags; - - *(uint16_t *)buf = tag_count; - + } + case DeviceTagRequest: { + msg->tag = DeviceTagRequest; + msg->request._version = *(uint64_t *)&buf[8]; + msg->request.requests.len = *(uint16_t *)&buf[16]; + buf += 18; + msg->request.requests.data = malloc(msg->request.requests.len * sizeof(typeof(*msg->request.requests.data))); + for(size_t i = 0; i < msg->request.requests.len; i++) { + typeof(&msg->request.requests.data[i]) e0 = &msg->request.requests.data[i]; + e0->tags.len = *(uint16_t *)&buf[0]; buf += 2; - - for (int j = 0; j < tag_count; j++) { - int str_len = strlen(tags[j]); - int byte_len = align_2(str_len); - - expected_len += 2 + byte_len; - if (len < expected_len) { - return -1; - } - - *(uint16_t *)buf = str_len; + e0->tags.data = malloc(e0->tags.len * sizeof(typeof(*e0->tags.data))); + for(size_t i = 0; i < e0->tags.len; i++) { + typeof(&e0->tags.data[i]) e1 = &e0->tags.data[i]; + e1->name.len = *(uint16_t *)&buf[0]; buf += 2; - - strncpy((char *)buf, tags[j], str_len); - buf += byte_len; + e1->name.data = malloc(e1->name.len * sizeof(typeof(*e1->name.data))); + for(size_t i = 0; i < e1->name.len; i++) { + typeof(&e1->name.data[i]) e2 = &e1->name.data[i]; + *e2 = *(char *)&buf[0]; + buf += 1; + } + buf = (byte*)(((((uintptr_t)buf - 1) >> 1) + 1) << 1); } + buf = (byte*)(((((uintptr_t)buf - 1) >> 1) + 1) << 1); } - - size = expected_len + 1; - break; - } - case DeviceDestroy: - if (len < MSS_DESTROY) + buf = (byte*)(((((uintptr_t)buf - 1) >> 3) + 1) << 3); + if(msg->request._version != 1UL) { + printf("Mismatched version: peers aren't the same version, expected 1 got %lu.\n", msg->request._version); + msg_device_free(msg); return -1; - - buf[0] = (uint8_t)msg->code; - - *(uint16_t *)(buf + 2) = msg->controller_state.index; - size = MSS_DESTROY + 1; - buf += size; + } break; - default: - printf("ERR(msg_serialize): Trying to serialize unknown message of code %d\n", msg->code); + } + case DeviceTagDestroy: { + msg->tag = DeviceTagDestroy; + msg->destroy.index = *(uint16_t *)&buf[2]; + buf += 8; + break; + } + } + if(*(MsgMagic*)buf != MSG_MAGIC_END) { + msg_device_free(msg); return -1; } - - if (align_m(size) + MAGIC_SIZE > len) { + buf += MSG_MAGIC_SIZE; + if(buf > base_buf + len) { + msg_device_free(msg); return -1; } - - MAGIC_TYPE *mbuf = (MAGIC_TYPE *)align_m((uintptr_t)buf); - - *mbuf = MAGIC_END; - - return align_m(size) + MAGIC_SIZE * 2; + return (int)(buf - base_buf); } -void msg_free(Message *msg) { - if (msg->code == Request) { - for (int i = 0; i < msg->request.request_count; i++) { - for (int j = 0; j < msg->request.requests[i].count; j++) { - free(msg->request.requests[i].tags[j]); +void msg_device_free(DeviceMessage *msg) { + switch(msg->tag) { + case DeviceTagNone: + break; + case DeviceTagInfo: { + break; + } + case DeviceTagReport: { + break; + } + case DeviceTagControllerState: { + break; + } + case DeviceTagRequest: { + for(size_t i = 0; i < msg->request.requests.len; i++) { + typeof(msg->request.requests.data[i]) e0 = msg->request.requests.data[i]; + for(size_t i = 0; i < e0.tags.len; i++) { + typeof(e0.tags.data[i]) e1 = e0.tags.data[i]; + free(e1.name.data); } - free(msg->request.requests[i].tags); - } - free(msg->request.requests); - } -} - -void print_message_buffer(const uint8_t *buf, int len) { - bool last_beg = false; - for (int i = 0; i < len; i++) { - if (i + MAGIC_SIZE <= len) { - MAGIC_TYPE magic = *(MAGIC_TYPE *)(&buf[i]); - if (magic == MAGIC_BEG) { - printf(" \033[32m%08X\033[0m", magic); - i += MAGIC_SIZE - 1; - last_beg = true; - continue; - } else if (magic == MAGIC_END) { - printf(" \033[32m%08X\033[0m", magic); - i += MAGIC_SIZE - 1; - continue; - } - } - - if (last_beg) { - last_beg = false; - printf(" \033[034m%02X\033[0m", buf[i]); - } else { - printf(" %02X", buf[i]); + free(e0.tags.data); } + free(msg->request.requests.data); + break; + } + case DeviceTagDestroy: { + break; + } } } diff --git a/net.h b/net.h index 1ae50ce..115064b 100644 --- a/net.h +++ b/net.h @@ -1,122 +1,133 @@ -// vi:ft=c -#ifndef NET_H_ -#define NET_H_ -#include "util.h" - -#include +// Generated file, do not edit (its not like it'll explode if you do, but its better not to) +#ifndef NET_H +#define NET_H #include #include +#include -#define MAGIC_TYPE uint32_t -#define MAGIC_SIZE sizeof(MAGIC_TYPE) -static const MAGIC_TYPE MAGIC_BEG = 0xDEADCAFE; -static const MAGIC_TYPE MAGIC_END = 0xCAFEDEAD; -// Align n to the next MAGIC boundary -static inline size_t align_m(uintptr_t n) { return (((n - 1) >> 2) + 1) << 2; } +typedef unsigned char byte; +typedef uint64_t MsgMagic; -typedef enum { - NoMessage = 0, - DeviceInfo = 1, - DeviceReport = 2, - DeviceDestroy = 3, - ControllerState = 4, - Request = 5, -} MessageCode; +#define MSG_MAGIC_SIZE sizeof(MsgMagic) +static const MsgMagic MSG_MAGIC_START = 0xCAFEF00DBEEFDEAD; +static const MsgMagic MSG_MAGIC_END = 0xF00DBEEFCAFEDEAD; -// Alignment 4 -typedef struct { - MessageCode code; - // + 1 byte of padding +typedef struct Abs { + uint16_t id; + uint32_t min; + uint32_t max; + uint32_t fuzz; + uint32_t flat; + uint32_t res; +} Abs; - uint8_t slot; - uint8_t index; +typedef struct Key { + uint16_t id; +} Key; - uint16_t abs_count; - uint16_t rel_count; - uint16_t key_count; +typedef struct Rel { + uint16_t id; +} Rel; - uint16_t abs_id[ABS_CNT]; - // + 2 bytes of padding per abs - uint32_t abs_min[ABS_CNT]; - uint32_t abs_max[ABS_CNT]; - uint32_t abs_fuzz[ABS_CNT]; - uint32_t abs_flat[ABS_CNT]; - uint32_t abs_res[ABS_CNT]; +typedef struct Tag { + struct { + uint16_t len; + char *data; + } name; +} Tag; - uint16_t rel_id[REL_CNT]; - - uint16_t key_id[KEY_CNT]; -} MessageDeviceInfo; -#define MSS_DEVICE_INFO(abs, rel, key) (10 + abs * 24 + rel * 2 + key * 2 + 1) -// MSS -> Message Serialized Size: -// Size of the data of the message when serialized (no alignment / padding) - -// 4 aligned -typedef struct { - MessageCode code; - // + 1 byte of padding - - uint8_t slot; - uint8_t index; - - uint16_t abs_count; - uint16_t rel_count; - uint16_t key_count; - - uint32_t abs[ABS_CNT]; - uint32_t rel[REL_CNT]; - uint8_t key[KEY_CNT]; -} MessageDeviceReport; -#define MSS_DEVICE_REPORT(abs, rel, key) (11 + abs * 4 + rel * 4 + align_4(key)) - -// 1 aligned -typedef struct { - MessageCode code; - // + 1 byte of padding - - uint16_t index; - uint8_t led[3]; - uint8_t small_rumble; - uint8_t big_rumble; - uint8_t flash_on; - uint8_t flash_off; -} MessageControllerState; -#define MSS_CONTROLLER_STATE 10 - -typedef struct { - char **tags; - uint16_t count; +typedef struct TagList { + struct { + uint16_t len; + struct Tag *data; + } tags; } TagList; -typedef struct { - MessageCode code; - // + 1 byte of padding +// Device - TagList *requests; - uint16_t request_count; -} MessageRequest; -#define MSS_REQUEST(count) (2 + 2 * count + 1) +typedef enum DeviceTag { + DeviceTagNone = 0, + DeviceTagInfo = 1, + DeviceTagReport = 2, + DeviceTagControllerState = 3, + DeviceTagRequest = 4, + DeviceTagDestroy = 5, +} DeviceTag; -typedef struct { - MessageCode code; - // + 1 byte of padding +typedef struct DeviceInfo { + DeviceTag tag; + uint8_t slot; + uint8_t index; + struct { + uint8_t len; + struct Abs data[64]; + } abs; + struct { + uint8_t len; + struct Rel data[16]; + } rel; + struct { + uint16_t len; + struct Key data[768]; + } key; +} DeviceInfo; +typedef struct DeviceReport { + DeviceTag tag; + uint8_t slot; + uint8_t index; + struct { + uint8_t len; + uint32_t data[64]; + } abs; + struct { + uint8_t len; + uint32_t data[16]; + } rel; + struct { + uint16_t len; + uint8_t data[768]; + } key; +} DeviceReport; + +typedef struct DeviceControllerState { + DeviceTag tag; uint16_t index; -} MessageDestroy; -#define MSS_DESTROY 3 + uint8_t led[3]; + uint8_t small_rumble; + uint8_t big_rumble; + uint8_t flash_on; + uint8_t flash_off; +} DeviceControllerState; -typedef union { - MessageCode code; - MessageRequest request; - MessageDestroy destroy; - MessageDeviceInfo device_info; - MessageDeviceReport device_report; - MessageControllerState controller_state; -} Message; +typedef struct DeviceRequest { + DeviceTag tag; + struct { + uint16_t len; + struct TagList *data; + } requests; + uint64_t _version; +} DeviceRequest; -int msg_deserialize(const uint8_t *buf, size_t len, Message *restrict dst); -int msg_serialize(uint8_t *restrict buf, size_t len, const Message *msg); -void msg_free(Message *msg); -void print_message_buffer(const uint8_t *buf, int len); +typedef struct DeviceDestroy { + DeviceTag tag; + uint16_t index; +} DeviceDestroy; +typedef union DeviceMessage { + DeviceTag tag; + DeviceInfo info; + DeviceReport report; + DeviceControllerState controller_state; + DeviceRequest request; + DeviceDestroy destroy; +} DeviceMessage; + +// Serialize the message msg to buffer dst of size len, returns the length of the serialized message, or -1 on error (buffer overflow) +int msg_device_serialize(byte *dst, size_t len, DeviceMessage *msg); +// Deserialize the message in the buffer src of size len into dst, return the length of the serialized message or -1 on error. +int msg_device_deserialize(const byte *src, size_t len, DeviceMessage *dst); + +// Free the message (created by msg_device_deserialize) +void msg_device_free(DeviceMessage *msg); #endif diff --git a/net.ser b/net.ser index 4ebcf0f..6ce0422 100644 --- a/net.ser +++ b/net.ser @@ -1,63 +1,3 @@ -// Abs -> { whatever: u16, field1: { a: (invalid)[^1] }, field2: A[1] } - -// AbsArr -> { whatever: u16, field1: { a: (invalid)[^1] }, field2: A[1] }&[] -// AbsArrArr -> { whatever: u16, field1: { a: (invalid)[^1] }, field2: A[1] }&[]&[][4] - -// A -> { a: (invalid)[^1] } - -// AA -> { a: (invalid)[^1] }[1] - -// RBASIC -> (invalid) -// RM1 -> (invalid) -// RM2 -> (invalid) -// RM3 -> (invalid) - -// R1 -> (invalid)&[4]&[] -// R2 -> (invalid)&[4] -// R3 -> (invalid)&[4] -// R4 -> (invalid) -// R5 -> (invalid) - -// SA -> { field: { field: SA } } -// SC -> { field: SC&[] } -// Node -> { data: u8, children: Node&[] } -// Recur -> { field: Recur } -// SB -> { field: { field: SB } } - -// bool -> bool -// char -> char -// i16 -> i16 -// i32 -> i32 -// i64 -> i64 -// i8 -> i8 -// u16 -> u16 -// u32 -> u32 -// u64 -> u64 -// u8 -> u8 - -// Struct Layout: S2 -// field[0].field.len align(2) size(2) -// field[1].field.len align(2) size(2) -// field[0].field.data align(0) size(0) -// field[1].field.data align(0) size(0) -// Struct Layout: SC -// field.len align(2) size(2) -// field.data align(0) size(0) -// Struct Layout: Node -// children.len align(2) size(2) -// data align(1) size(1) -// children.data align(0) size(0) -// Struct Layout: S1 -// field.len align(1) size(1) -// field.data align(0) size(0) -// Struct Layout: Abs -// whatever align(2) size(2) -// Struct Layout: S3 -// field.len align(2) size(2) -// field.data align(0) size(0) -// Struct Layout: Rel -// a align(2) size(2) - struct Abs { id: u16, min: u32, @@ -83,6 +23,11 @@ struct Tag { name: char[], } +struct TagList { + tags: Tag[], +} + +version(1); messages Device { Info { slot: u8, @@ -110,8 +55,7 @@ messages Device { } #[versioned] Request { - requests: Tag[][], - request_count: u16, + requests: TagList[], } Destroy { index: u16, diff --git a/ser/codegen.c b/ser/codegen.c index f14ff3d..1b6c70d 100644 --- a/ser/codegen.c +++ b/ser/codegen.c @@ -166,3 +166,19 @@ char *pascal_to_snake_case(StringSlice str) { return res.data; } + +char *snake_case_to_screaming_snake_case(StringSlice str) { + CharVec res = vec_init(); + vec_grow(&res, str.len + 4); + for(size_t i = 0; i < str.len; i++) { + char c = str.ptr[i]; + if('a' <= c && c <= 'z') { + vec_push(&res, c - 'a' + 'A'); + } else { + vec_push(&res, c); + } + } + vec_push(&res, '\0'); + + return res.data; +} diff --git a/ser/codegen.h b/ser/codegen.h index 5692463..4d6833f 100644 --- a/ser/codegen.h +++ b/ser/codegen.h @@ -41,6 +41,7 @@ void wt_format(Writer *w, const char *fmt, ...); // Define the structs of a program in the correct order (respecting direct dependencies) void define_structs(Program *p, Writer *w, void (*define)(Writer *w, StructObject *)); char *pascal_to_snake_case(StringSlice str); +char *snake_case_to_screaming_snake_case(StringSlice str); // Check if c is aligned to alignment to static inline bool calign_is_aligned(CurrentAlignment c, Alignment to) { diff --git a/ser/codegen_c.c b/ser/codegen_c.c index 686d03e..8be3276 100644 --- a/ser/codegen_c.c +++ b/ser/codegen_c.c @@ -195,6 +195,10 @@ void write_struct(Writer *w, StructObject *obj) { wt_format(w, "} %.*s;\n\n", obj->name.len, obj->name.ptr); } +void write_align(Writer *w, const char *var, const Alignment align, size_t indent) { + wt_format(w, "%*s%s = (byte*)(((((uintptr_t)%s - 1) >> %u) + 1) << %u);\n", indent, "", var, var, align.po2, align.po2); +} + void write_accessor(Writer *w, TypeObject *base_type, FieldAccessor fa, bool ptr) { if (fa.indices.len == 0) return; @@ -245,6 +249,37 @@ void write_accessor(Writer *w, TypeObject *base_type, FieldAccessor fa, bool ptr } } +bool is_field_accessor_heap_array(FieldAccessor fa, TypeObject *base_type) { + if (fa.indices.len == 0) + return base_type->kind == TypeArray && base_type->type.array.heap; + + // In the case of a heap array the last index will choose between length and data, + // but since we only care about the array + fa.indices.len--; + + TypeObject *t = base_type; + for (size_t i = 0; i < fa.indices.len; i++) { + uint64_t index = fa.indices.data[i]; + + if (t->kind == TypeStruct) { + StructObject *st = (StructObject *)&t->type.struct_; + t = st->fields.data[index].type; + } else if (t->kind == TypeArray) { + if (t->type.array.sizing == SizingMax) { + if (index == 0) { + return false; + } else { + t = t->type.array.type; + } + } else { + t = t->type.array.type; + } + } + } + + return t->kind == TypeArray && t->type.array.heap; +} + void write_type_serialization( Writer *w, const char *base, bool ptr, Layout *layout, CurrentAlignment al, Hashmap *layouts, size_t indent, size_t depth ) { @@ -275,14 +310,15 @@ void write_type_serialization( for (; i < layout->fields.len; i++) { FieldAccessor farr = layout->fields.data[i]; - wt_format(w, "%*sfor(size_t i = 0; i < %s", indent, "", base); FieldAccessor flen = field_accessor_clone(&farr); // Access the length instead of data flen.indices.data[flen.indices.len - 1] = 0; + + wt_format(w, "%*sfor(size_t i = 0; i < %s", indent, "", base); write_accessor(w, layout->type, flen, ptr); field_accessor_drop(flen); char *vname = msprintf("e%lu", depth); - wt_format(w, "; i++) {\n%*stypeof(%s", indent, "", base); + wt_format(w, "; i++) {\n%*stypeof(%s", indent + INDENT, "", base); write_accessor(w, layout->type, farr, ptr); wt_format(w, "[i]) %s = %s", vname, base); write_accessor(w, layout->type, farr, ptr); @@ -303,7 +339,7 @@ void write_type_serialization( wt_format(w, "%*s}\n", indent, ""); free(vname); } - wt_format(w, "%*sbuf = (byte*)(((uintptr_t)buf - %u) & -%u);\n", indent, "", align.mask, align.value); + write_align(w, "buf", align, indent); } else { offset += calign_to(al, align); wt_format(w, "%*sbuf += %lu;\n", indent, "", offset); @@ -346,10 +382,20 @@ void write_type_deserialization( for (; i < layout->fields.len; i++) { FieldAccessor farr = layout->fields.data[i]; - wt_format(w, "%*sfor(size_t i = 0; i < %s", indent, "", base); FieldAccessor flen = field_accessor_clone(&farr); // Access the length instead of data flen.indices.data[flen.indices.len - 1] = 0; + + if (is_field_accessor_heap_array(farr, layout->type)) { + wt_format(w, "%*s%s", indent, "", base); + write_accessor(w, layout->type, farr, ptr); + wt_format(w, " = malloc(%s", base); + write_accessor(w, layout->type, flen, ptr); + wt_format(w, " * sizeof(typeof(*%s", base); + write_accessor(w, layout->type, farr, ptr); + wt_format(w, ")));\n"); + } + wt_format(w, "%*sfor(size_t i = 0; i < %s", indent, "", base); write_accessor(w, layout->type, flen, ptr); field_accessor_drop(flen); char *vname = msprintf("e%lu", depth); @@ -374,24 +420,86 @@ void write_type_deserialization( wt_format(w, "%*s}\n", indent, ""); free(vname); } - wt_format(w, "%*sbuf = (byte*)(((uintptr_t)buf - %u) & -%u);\n", indent, "", align.mask, align.value); + write_align(w, "buf", align, indent); } else { offset += calign_to(al, align); wt_format(w, "%*sbuf += %lu;\n", indent, "", offset); } } +int write_type_free(Writer *w, const char *base, TypeObject *type, size_t indent, size_t depth) { + if (type->kind == TypePrimitif) { + return 0; + } else if (type->kind == TypeArray) { + BufferedWriter b = buffered_writer_init(); + Writer *w2 = (Writer *)&b; + + int total = 0; + + wt_format(w2, "%*sfor(size_t i = 0; i < ", indent, ""); + if (type->type.array.sizing == SizingMax) { + wt_format(w2, "%s.len; i++) {\n", base); + wt_format(w2, "%*stypeof(%s.data[i]) e%lu = %s.data[i];\n", indent + INDENT, "", base, depth, base); + } else { + wt_format(w2, "%lu; i++) {\n", type->type.array.size); + wt_format(w2, "%*stypeof(%s[i]) e%lu = %s[i];\n", indent + INDENT, "", base, depth, base); + } + + char *new_base = msprintf("e%lu", depth); + total += write_type_free(w2, new_base, type->type.array.type, indent + INDENT, depth + 1); + free(new_base); + wt_format(w2, "%*s}\n", indent, ""); + + if (total > 0) { + wt_write(w, b.buf.data, b.buf.len); + } + buffered_writer_drop(b); + + if (type->type.array.heap) { + wt_format(w, "%*sfree(%s.data);\n", indent, "", base); + total++; + } + + return total; + } else if (type->kind == TypeStruct) { + StructObject *s = (StructObject *)&type->type.struct_; + int total = 0; + + for (size_t i = 0; i < s->fields.len; i++) { + Field f = s->fields.data[i]; + char *new_base = msprintf("%s.%.*s", base, f.name.len, f.name.ptr); + total += write_type_free(w, new_base, f.type, indent, depth); + free(new_base); + } + + return total; + } + + return 0; +} + void codegen_c(Writer *header, Writer *source, const char *name, Program *p) { + char *uc_name = snake_case_to_screaming_snake_case((StringSlice){.ptr = name, .len = strlen(name)}); wt_format( header, "// Generated file, do not edit (its not like it'll explode if you do, but its better not to)\n" + "#ifndef %s_H\n" + "#define %s_H\n" "#include \n" "#include \n" "#include \n" "\n" "typedef unsigned char byte;\n" + "typedef uint64_t MsgMagic;\n" "\n" + "#define MSG_MAGIC_SIZE sizeof(MsgMagic)\n" + "static const MsgMagic MSG_MAGIC_START = 0xCAFEF00DBEEFDEAD;\n" + "static const MsgMagic MSG_MAGIC_END = 0xF00DBEEFCAFEDEAD;\n" + "\n", + uc_name, + uc_name ); + free(uc_name); wt_format( source, "// Generated file, do not edit (its not like it'll explode if you do, but its better not to)\n" @@ -407,7 +515,16 @@ void codegen_c(Writer *header, Writer *source, const char *name, Program *p) { MessagesObject msgs = p->messages.data[i]; wt_format(header, "// %.*s\n\n", msgs.name.len, msgs.name.ptr); - wt_format(header, "typedef enum %.*sTag {\n", msgs.name.len, msgs.name.ptr); + wt_format( + header, + "typedef enum %.*sTag {\n%*s%.*sTagNone = 0,\n", + msgs.name.len, + msgs.name.ptr, + INDENT, + "", + msgs.name.len, + msgs.name.ptr + ); for (size_t j = 0; j < msgs.messages.len; j++) { wt_format( header, @@ -418,7 +535,7 @@ void codegen_c(Writer *header, Writer *source, const char *name, Program *p) { msgs.name.ptr, msgs.messages.data[j].name.len, msgs.messages.data[j].name.ptr, - j + j + 1 ); } wt_format(header, "} %.*sTag;\n\n", msgs.name.len, msgs.name.ptr); @@ -477,6 +594,15 @@ void codegen_c(Writer *header, Writer *source, const char *name, Program *p) { msgs.name.len, msgs.name.ptr ); + wt_format( + header, + "// Free the message (created by msg_%s_deserialize)\n" + "void msg_%s_free(%.*sMessage *msg);\n", + name, + name, + msgs.name.len, + msgs.name.ptr + ); char *tag_type = msprintf("%.*sTag", msgs.name.len, msgs.name.ptr); PointerVec message_tos = vec_init(); @@ -509,8 +635,13 @@ void codegen_c(Writer *header, Writer *source, const char *name, Program *p) { msgs.name.ptr ); - wt_format(source, "%*sbyte *base_buf = buf;\n%*s%s tag = msg->tag;\n", INDENT, "", INDENT, "", tag_type); - wt_format(source, "%*sswitch(tag) {\n", INDENT, ""); + wt_format(source, "%*sconst byte *base_buf = buf;\n", INDENT, ""); + wt_format(source, "%*sif(len < 2 * MSG_MAGIC_SIZE)\n", INDENT, ""); + wt_format(source, "%*sreturn -1;\n", INDENT * 2, ""); + wt_format(source, "%*s*(MsgMagic*)buf = MSG_MAGIC_START;\n", INDENT, ""); + wt_format(source, "%*sbuf += MSG_MAGIC_SIZE;\n", INDENT, ""); + wt_format(source, "%*sswitch(msg->tag) {\n", INDENT, ""); + wt_format(source, "%*scase %sNone:\n%*sbreak;\n", INDENT, "", tag_type, INDENT * 2, ""); for (size_t j = 0; j < msgs.messages.len; j++) { MessageObject m = msgs.messages.data[j]; @@ -541,7 +672,10 @@ void codegen_c(Writer *header, Writer *source, const char *name, Program *p) { free(snake_case_name); } wt_format(source, "%*s}\n", INDENT, ""); - wt_format(source, "%*sbuf = (byte*)(((uintptr_t)buf - %u) & -%u);\n", INDENT, "", ALIGN_8.mask, ALIGN_8.value); + wt_format(source, "%*s*(MsgMagic*)buf = MSG_MAGIC_END;\n", INDENT, ""); + wt_format(source, "%*sbuf += MSG_MAGIC_SIZE;\n", INDENT, ""); + wt_format(source, "%*sif(buf > base_buf + len)\n", INDENT, ""); + wt_format(source, "%*sreturn -1;\n", INDENT * 2, ""); wt_format(source, "%*sreturn (int)(buf - base_buf);\n", INDENT, ""); wt_format(source, "}\n"); } @@ -555,8 +689,16 @@ void codegen_c(Writer *header, Writer *source, const char *name, Program *p) { msgs.name.ptr ); - wt_format(source, "%*sconst byte *base_buf = buf;\n%*s%s tag = *(uint16_t*)buf;\n", INDENT, "", INDENT, "", tag_type); + wt_format(source, "%*sconst byte *base_buf = buf;\n", INDENT, ""); + wt_format(source, "%*sif(len < 2 * MSG_MAGIC_SIZE)\n", INDENT, ""); + wt_format(source, "%*sreturn -1;\n", INDENT * 2, ""); + wt_format(source, "%*sif(*(MsgMagic*)buf != MSG_MAGIC_START)\n", INDENT, ""); + wt_format(source, "%*sreturn -1;\n", INDENT * 2, ""); + wt_format(source, "%*sbuf += MSG_MAGIC_SIZE;\n", INDENT, ""); + wt_format(source, "%*s%s tag = *(uint16_t*)buf;\n", INDENT, "", tag_type); wt_format(source, "%*sswitch(tag) {\n", INDENT, ""); + wt_format(source, "%*scase %sNone:\n%*sbreak;\n", INDENT, "", tag_type, INDENT * 2, ""); + for (size_t j = 0; j < msgs.messages.len; j++) { MessageObject m = msgs.messages.data[j]; @@ -579,19 +721,12 @@ void codegen_c(Writer *header, Writer *source, const char *name, Program *p) { 0 ); if (m.attributes & Attr_versioned) { - wt_format( - source, - "%*sif(msg->%s._version != %luUL) {\n%*sprintf(\"Mismatched message version: peers aren't the same " - "version.\\n\");\n%*s}\n", - INDENT * 2, - "", - snake_case_name, - msgs.version, - INDENT * 3, - "", - INDENT * 2, - "" - ); + wt_format(source, "%*sif(msg->%s._version != %luUL) {\n", INDENT * 2, "", snake_case_name, msgs.version); + wt_format(source, "%*sprintf(\"Mismatched version: peers aren't the same version", INDENT * 3, ""); + wt_format(source, ", expected %lu got %%lu.\\n\", msg->%s._version);\n", msgs.version, snake_case_name); + wt_format(source, "%*smsg_%s_free(msg);\n", INDENT * 3, "", name); + wt_format(source, "%*sreturn -1;\n", INDENT * 3, ""); + wt_format(source, "%*s}\n", INDENT * 2, ""); } wt_format(source, "%*sbreak;\n%*s}\n", INDENT * 2, "", INDENT, ""); @@ -599,10 +734,43 @@ void codegen_c(Writer *header, Writer *source, const char *name, Program *p) { free(snake_case_name); } wt_format(source, "%*s}\n", INDENT, ""); + wt_format(source, "%*sif(*(MsgMagic*)buf != MSG_MAGIC_END) {\n", INDENT, ""); + wt_format(source, "%*smsg_%s_free(msg);\n", INDENT * 2, "", name); + wt_format(source, "%*sreturn -1;\n", INDENT * 2, ""); + wt_format(source, "%*s}\n", INDENT, ""); + wt_format(source, "%*sbuf += MSG_MAGIC_SIZE;\n", INDENT, ""); + wt_format(source, "%*sif(buf > base_buf + len) {\n", INDENT, ""); + wt_format(source, "%*smsg_%s_free(msg);\n", INDENT * 2, "", name); + wt_format(source, "%*sreturn -1;\n", INDENT * 2, ""); + wt_format(source, "%*s}\n", INDENT, ""); wt_format(source, "%*sreturn (int)(buf - base_buf);\n", INDENT, ""); wt_format(source, "}\n"); } + { + wt_format(source, "\nvoid msg_%s_free(%.*sMessage *msg) {\n", name, msgs.name.len, msgs.name.ptr); + + wt_format(source, "%*sswitch(msg->tag) {\n", INDENT, ""); + wt_format(source, "%*scase %sNone:\n%*sbreak;\n", INDENT, "", tag_type, INDENT * 2, ""); + + for (size_t j = 0; j < msgs.messages.len; j++) { + MessageObject m = msgs.messages.data[j]; + TypeObject *mtype = message_tos.data[j]; + + char *snake_case_name = pascal_to_snake_case(m.name); + char *base = msprintf("msg->%s", snake_case_name); + + wt_format(source, "%*scase %s%.*s: {\n", INDENT, "", tag_type, m.name.len, m.name.ptr); + write_type_free(source, base, mtype, INDENT * 2, 0); + wt_format(source, "%*sbreak;\n%*s}\n", INDENT * 2, "", INDENT, ""); + + free(base); + free(snake_case_name); + } + wt_format(source, "%*s}\n", INDENT, ""); + wt_format(source, "}\n"); + } + for (size_t j = 0; j < message_tos.len; j++) { TypeObject *to = message_tos.data[j]; StructObject *s = (StructObject *)&to->type.struct_; @@ -616,6 +784,8 @@ void codegen_c(Writer *header, Writer *source, const char *name, Program *p) { free(tag_type); free(name); } + + wt_format(header, "#endif\n"); } typedef struct { diff --git a/ser/eval.c b/ser/eval.c index a88c2df..85590ff 100644 --- a/ser/eval.c +++ b/ser/eval.c @@ -11,7 +11,7 @@ #define PRIMITIF_TO(name, al) \ const TypeObject PRIMITIF_##name = {.kind = TypePrimitif, .align = _ALIGN_##al, .type.primitif = Primitif_##name} -PRIMITIF_TO(u8, 2); +PRIMITIF_TO(u8, 1); PRIMITIF_TO(u16, 2); PRIMITIF_TO(u32, 4); PRIMITIF_TO(u64, 8); @@ -444,7 +444,7 @@ static uint64_t get_ast_number_value(EvaluationContext *ctx, AstNumber number) { // If the constant is invalid we make up a value to continue checking for errors // (Since it is invalid there already has been at least one and we know this code // can't go to the next stage) - return c->valid ? c->valid : 0; + return c->valid ? c->value : 0; } else { // This constant doesn't exist: raise an error and return dummy value to continue vec_push(&ctx->errors, err_unknown(number.token.span, ATConstant, ident)); diff --git a/server.c b/server.c index 8b0e689..8307d06 100644 --- a/server.c +++ b/server.c @@ -118,6 +118,33 @@ static void print_config() { printf("\n"); } +void print_message_buffer(const uint8_t *buf, int len) { + bool last_beg = false; + for (int i = 0; i < len; i++) { + if (i + MSG_MAGIC_SIZE <= len) { + MsgMagic magic = *(MsgMagic *)(&buf[i]); + if (magic == MSG_MAGIC_START) { + printf(" \033[32m%08lX\033[0m", magic); + i += MSG_MAGIC_SIZE - 1; + last_beg = true; + continue; + } else if (magic == MSG_MAGIC_END) { + printf(" \033[32m%08lX\033[0m", magic); + i += MSG_MAGIC_SIZE - 1; + continue; + } + } + + if (last_beg) { + last_beg = false; + printf(" \033[034m%04X\033[0m", *(uint16_t*)&buf[i]); + i++; + } else { + printf(" %02X", buf[i]); + } + } +} + void device_thread_exit(int _sig) { struct DeviceThreadArgs *args = pthread_getspecific(device_args_key); printf("CONN(%d): [%d] exiting\n", args->conn->id, args->index); @@ -145,8 +172,8 @@ void *device_thread(void *args_) { TRAP_IGN(SIGPIPE); TRAP(SIGTERM, device_thread_exit); - uint8_t buf[2048] __attribute__((aligned(4))) = {0}; - MessageDeviceInfo dev_info; + uint8_t buf[2048] __attribute__((aligned(4))) = {0}; + DeviceInfo dev_info; while (true) { if (*args->controller != NULL) { @@ -169,21 +196,21 @@ void *device_thread(void *args_) { // Send over device info { - int len = msg_serialize(buf, 2048, (Message *)&dev_info); + int len = msg_device_serialize(buf, 2048, (DeviceMessage *)&dev_info); if (write(args->conn->socket, buf, len) == -1) { printf("CONN(%d): [%d] Couldn't send device info\n", args->conn->id, args->index); break; } } - MessageDeviceReport report = {0}; + DeviceReport report = {0}; - report.code = DeviceReport; - report.abs_count = ctr->dev.device_info.abs_count; - report.rel_count = ctr->dev.device_info.rel_count; - report.key_count = ctr->dev.device_info.key_count; - report.slot = args->index; - report.index = controller_index; + report.tag = DeviceTagReport; + report.abs.len = ctr->dev.device_info.abs.len; + report.rel.len = ctr->dev.device_info.rel.len; + report.key.len = ctr->dev.device_info.key.len; + report.slot = args->index; + report.index = controller_index; while (true) { struct input_event event; @@ -203,13 +230,12 @@ void *device_thread(void *args_) { } if (event.type == EV_SYN) { - int len = msg_serialize(buf, 2048, (Message *)&report); + int len = msg_device_serialize(buf, 2048, (DeviceMessage *)&report); if (len < 0) { printf("CONN(%d): [%d] Couldn't serialize report %d\n", args->conn->id, args->index, len); continue; }; - send(args->conn->socket, buf, len, 0); } else if (event.type == EV_ABS) { int index = ctr->dev.mapping.abs_indices[event.code]; @@ -219,7 +245,7 @@ void *device_thread(void *args_) { continue; }; - report.abs[index] = event.value; + report.abs.data[index] = event.value; } else if (event.type == EV_REL) { int index = ctr->dev.mapping.rel_indices[event.code]; @@ -228,7 +254,7 @@ void *device_thread(void *args_) { continue; }; - report.rel[index] = event.value; + report.rel.data[index] = event.value; } else if (event.type == EV_KEY) { int index = ctr->dev.mapping.key_indices[event.code]; @@ -236,17 +262,17 @@ void *device_thread(void *args_) { printf("CONN(%d): [%d] Invalid key\n", args->conn->id, args->index); continue; }; - report.key[index] = !!event.value; + report.key.data[index] = !!event.value; } } // Send device destroy message { - MessageDestroy dstr; - dstr.code = DeviceDestroy; + DeviceDestroy dstr; + dstr.tag = DeviceTagDestroy; dstr.index = args->index; - int len = msg_serialize(buf, 2048, (Message *)&dstr); + int len = msg_device_serialize(buf, 2048, (DeviceMessage *)&dstr); if (write(args->conn->socket, buf, len) == -1) { printf("CONN(%d): [%d] Couldn't send device destroy message\n", args->conn->id, args->index); break; @@ -310,7 +336,7 @@ void *server_handle_conn(void *args_) { if (len <= 0) { closing_message = "Lost peer (from recv)"; goto conn_end; - } else if (len > 1 + MAGIC_SIZE * 2) { + } else if (len > 1) { printf("CONN(%d): Got message: ", args->id); printf("\n"); } else { @@ -318,10 +344,10 @@ void *server_handle_conn(void *args_) { } // Parse message - Message msg; - int msg_len = msg_deserialize(buf, len, &msg); + DeviceMessage msg; + int msg_len = msg_device_deserialize(buf, len, &msg); if (msg_len < 0) { - if (len > 1 + MAGIC_SIZE * 2) { + if (len > 1) { printf("CONN(%d): Couldn't parse message: ", args->id); print_message_buffer(buf, len); printf("\n"); @@ -332,7 +358,7 @@ void *server_handle_conn(void *args_) { } // Handle message - if (msg.code == ControllerState) { + if (msg.tag == DeviceTagControllerState) { int i = msg.controller_state.index; if (i >= device_controllers.len) { printf("CONN(%d): Invalid controller index in controller state message\n", args->id); @@ -346,10 +372,10 @@ void *server_handle_conn(void *args_) { } apply_controller_state(ctr, &msg.controller_state); - } else if (msg.code == Request) { + } else if (msg.tag == DeviceTagRequest) { if (got_request) { printf("CONN(%d): Illegal Request message after initial request\n", args->id); - msg_free(&msg); + msg_device_free(&msg); continue; } @@ -357,7 +383,7 @@ void *server_handle_conn(void *args_) { printf("CONN(%d): Got client request\n", args->id); - for (int i = 0; i < msg.request.request_count; i++) { + for (int i = 0; i < msg.request.requests.len; i++) { int index = device_controllers.len; Controller *ctr = NULL; vec_push(&device_controllers, &ctr); @@ -365,13 +391,14 @@ void *server_handle_conn(void *args_) { struct DeviceThreadArgs *dev_args = malloc(sizeof(struct DeviceThreadArgs)); dev_args->controller = vec_get(&device_controllers, index); - dev_args->tag_count = msg.request.requests[i].count; + dev_args->tag_count = msg.request.requests.data[i].tags.len; dev_args->tags = malloc(dev_args->tag_count * sizeof(char *)); dev_args->conn = args; dev_args->index = index; for (int j = 0; j < dev_args->tag_count; j++) { - dev_args->tags[j] = strdup(msg.request.requests[i].tags[j]); + Tag t = msg.request.requests.data[i].tags.data[j]; + dev_args->tags[j] = strndup(t.name.data, t.name.len); } pthread_t thread; @@ -379,7 +406,7 @@ void *server_handle_conn(void *args_) { vec_push(&device_threads, &thread); } - msg_free(&msg); + msg_device_free(&msg); } else { printf("CONN(%d): Illegal message\n", args->id); }