diff --git a/Makefile b/Makefile index 097a5db..8a046bd 100644 --- a/Makefile +++ b/Makefile @@ -1,7 +1,11 @@ Q=@ -CC=gcc -CFLAGS=-std=c11 -pedantic -g -Wall -Wno-format-truncation -pthread -lm -D_GNU_SOURCE -LDFLAGS=-lm +CC=clang + +GCCCFLAGS=-Wno-format-truncation +CLANGCFLAGS=-fsanitize=memory +CFLAGS=-std=c11 -pedantic -g -Wall -pthread -D_GNU_SOURCE +LDFLAGS=-lm -fsanitize=memory + BUILD_DIR=./objects BIN=jsfw @@ -11,6 +15,14 @@ SOURCES=$(wildcard *.c) OBJECTS:=$(patsubst %.c,$(BUILD_DIR)/%.o,$(SOURCES)) +ifeq ($(CC),gcc) + CFLAGS:=$(CFLAGS) $(GCCCFLAGS) +endif + +ifeq ($(CC),clang) + CFLAGS:=$(CFLAGS) $(CLANGCFLAGS) +endif + .PHONY: run run: $(BIN) @echo "RUN $(BIN) $(RUNARGS)" diff --git a/client.c b/client.c index d99bed4..441fc59 100644 --- a/client.c +++ b/client.c @@ -94,7 +94,7 @@ static const JSONAdapter ConfigAdapter = { .size = sizeof(ClientConfig), }; -void destroy_devices() { +void destroy_devices(void) { for (int i = 0; i < config.controller_count; i++) { int fd = *(int *)vec_get(&devices_fd, i); MessageDeviceInfo *info = vec_get(&devices_info, i); @@ -245,7 +245,7 @@ void device_handle_report(MessageDeviceReport *report) { device_emit(report->index, EV_SYN, 0, 0); } -void setup_devices() { +void setup_devices(void) { devices_fd = vec_of(int); devices_info = vec_of(MessageDeviceInfo); @@ -264,10 +264,10 @@ void setup_devices() { } } -void setup_fifo(); +void setup_fifo(void); // (Re)Open the fifo -void open_fifo() { +void open_fifo(void) { close(fifo); fifo = open(config.fifo_path, O_RDONLY | O_NONBLOCK); if (fifo < 0 && fifo_attempt == 0) { @@ -281,7 +281,7 @@ void open_fifo() { } // Ensure the fifo exists and opens it (also setup poll_fd) -void setup_fifo() { +void setup_fifo(void) { mode_t prev = umask(0); mkfifo(config.fifo_path, 0666); umask(prev); @@ -293,7 +293,7 @@ void setup_fifo() { } // (Re)Connect to the server -void connect_server() { +void connect_server(void) { while (true) { if (sock > 0) { // Close previous connection @@ -319,7 +319,7 @@ void connect_server() { socket_poll->fd = sock; printf("CLIENT: Connected !\n"); - uint8_t buf[2048] __attribute__((aligned(4))); + uint8_t buf[2048] __attribute__((aligned(4))) = {0}; int len = msg_serialize(buf, 2048, (Message *)&device_request); if (len > 0) { @@ -350,7 +350,7 @@ void setup_server(char *address, uint16_t port) { connect_server(); } -void build_device_request() { +void build_device_request(void) { char **tags = malloc(config.controller_count * sizeof(char *)); for (int i = 0; i < config.controller_count; i++) { tags[i] = config.controllers[i].tag; @@ -387,8 +387,8 @@ void client_run(char *address, uint16_t port, char *config_path) { setup_fifo(); build_device_request(); - setup_server(address, port); setup_devices(); + setup_server(address, port); uint8_t buf[2048] __attribute__((aligned(4))); uint8_t json_buf[2048] __attribute__((aligned(8))); @@ -429,7 +429,7 @@ void client_run(char *address, uint16_t port, char *config_path) { // A broken or closed socket produces a POLLIN event, so we check for error on the recv if (socket_poll->revents & POLLIN) { - int len = recv(sock, buf, 2048, 0); + int len = recv(sock, buf, 2048, MSG_PEEK); if (len <= 0) { printf("CLIENT: Lost connection to server, reconnecting\n"); connect_server(); @@ -438,9 +438,11 @@ void client_run(char *address, uint16_t port, char *config_path) { continue; } + int msg_len = msg_deserialize(buf, len, &message); // We've got data from the server - if (msg_deserialize(buf, len, &message) != 0) { - printf("CLIENT: Couldn't parse message (code: %d, len: %d)\n", buf[0], len); + if (msg_len < 0) { + recv(sock, buf, 2048, 0); + printf("CLIENT: Couldn't parse message (code: %d, len: %d)\n", buf[4], len); int l = len > 100 ? 100 : len; for (int i = 0; i < l; i++) { @@ -455,6 +457,8 @@ void client_run(char *address, uint16_t port, char *config_path) { continue; } + recv(sock, buf, msg_len, 0); + if (message.code == DeviceInfo) { if (device_exists(message.device_info.index)) { printf("CLIENT: Got more than one device info for same device\n"); diff --git a/client_config.json b/client_config.json index f86d9b0..1387a61 100644 --- a/client_config.json +++ b/client_config.json @@ -1,18 +1,12 @@ { "controllers": [ { - "tag": "Admin", - "vendor": "054c", - "product": "09cc", - "name": "JSFW PS4 Controller (Admin)" - }, - { - "tag": "User", - "vendor": "6942", - "product": "1337", - "name": "JSFW PS4 Controller (User)" + "tag": "Mouse", + "vendor": "6969", + "product": "0001", + "name": "JSFW Mouse" } ], "fifo_path": "/tmp/jsfw_fifo_2", - "retry_delay": 2.5 + "retry_delay": 1 } diff --git a/hid.c b/hid.c index 4327d8f..5233451 100644 --- a/hid.c +++ b/hid.c @@ -18,7 +18,7 @@ #include #include -// List of uniq of the currently known devices +// List of ids of the currently known devices static Vec known_devices; // Queue of available devices, devices that can only be given to one client static Vec available_devices; @@ -119,7 +119,7 @@ void setup_device(PhysicalDevice *dev) { } } -bool filter_event(int fd, char *event, ControllerFilter *filter) { +bool filter_event(int fd, char *event, ControllerFilter *filter, uniq_t uniq) { if (filter->js) { char device_path[64]; snprintf(device_path, 64, "/sys/class/input/%s/device", event); @@ -142,6 +142,18 @@ bool filter_event(int fd, char *event, ControllerFilter *filter) { } } + if (filter->name != NULL) { + char name[256] = {0}; + ioctl(fd, EVIOCGNAME(256), name); + if (strcmp(name, filter->name) != 0) { + return false; + } + } + + if (filter->uniq > 0 && uniq != filter->uniq) { + return false; + } + struct input_id ids; ioctl(fd, EVIOCGID, &ids); @@ -154,18 +166,25 @@ bool filter_event(int fd, char *event, ControllerFilter *filter) { } // Initialize vectors for polling -void poll_devices_init() { +void poll_devices_init(void) { known_devices = vec_of(Controller); cloneable_devices = vec_of(Controller *); available_devices = vec_of(Controller *); } // Block to get a device, this is thread safe -Controller *get_device(char *tag) { +// stop: additional condition to check before doing anything, +// if the condition is ever found to be true the function will return immediately with a NULL pointer. +Controller *get_device(char *tag, bool *stop) { // Check if we can get one right away pthread_mutex_lock(&devices_mutex); while (1) { + if (*stop) { + pthread_mutex_unlock(&devices_mutex); + return NULL; + } + for (int i = 0; i < available_devices.len; i++) { Controller *c = *(Controller **)vec_get(&available_devices, i); if (strcmp(c->ctr.tag, tag) == 0) { @@ -210,7 +229,7 @@ void forget_device(Controller *c) { pthread_mutex_lock(&devices_mutex); for (int i = 0; i < cloneable_devices.len; i++) { Controller *d = *(Controller **)vec_get(&cloneable_devices, i); - if (d->dev.uniq == c->dev.uniq) { + if (d->dev.id == c->dev.id) { vec_remove(&cloneable_devices, i, NULL); break; } @@ -220,10 +239,10 @@ void forget_device(Controller *c) { // Free the name if it was allocated if (c->dev.name != NULL && c->dev.name != DEVICE_DEFAULT_NAME) { - printf("HID: Forgetting device '%s' (%012lx)\n", c->dev.name, c->dev.uniq); + printf("HID: Forgetting device '%s' (%016lx)\n", c->dev.name, c->dev.id); free(c->dev.name); } else { - printf("HID: Forgetting device %012lx\n", c->dev.uniq); + printf("HID: Forgetting device %016lx\n", c->dev.id); } // try to close the file descriptor, they may be already closed if the device was unpugged. @@ -234,7 +253,7 @@ void forget_device(Controller *c) { pthread_mutex_lock(&known_devices_mutex); for (int i = 0; i < known_devices.len; i++) { Controller *d = vec_get(&known_devices, i); - if (d->dev.uniq == c->dev.uniq) { + if (d->dev.id == c->dev.id) { vec_remove(&known_devices, i, NULL); break; } @@ -243,7 +262,7 @@ void forget_device(Controller *c) { } // Find all available devices and pick up on new ones -void poll_devices() { +void poll_devices(void) { // loop over all entries of /sys/class/input DIR *input_dir = opendir("/sys/class/input"); struct dirent *input; @@ -256,6 +275,7 @@ void poll_devices() { PhysicalDevice dev; dev.hidraw = -1; + dev.uniq = 0; // Open /dev/input/eventXX { @@ -280,6 +300,14 @@ void poll_devices() { } } + // Try to get uniq, drop device if we can't + { + char uniq_str[17] = {0}; + + ioctl(dev.event, EVIOCGUNIQ(17), uniq_str); + dev.uniq = parse_uniq(uniq_str); + } + // Used for linear searches bool found; @@ -290,7 +318,7 @@ void poll_devices() { for (int i = 0; i < config->controller_count; i++) { ctr = &config->controllers[i]; - if (filter_event(dev.event, input->d_name, &ctr->filter)) { + if (filter_event(dev.event, input->d_name, &ctr->filter, dev.uniq)) { found = true; break; } @@ -301,17 +329,11 @@ void poll_devices() { } } - // Try to get uniq, drop device if we can't + // Get the id { - char uniq_str[17] = {0}; - - ioctl(dev.event, EVIOCGUNIQ(17), uniq_str); - dev.uniq = parse_uniq(uniq_str); - - // If we couldn't parse the uniq (this assumes uniq can't be zero, which is probably alright) - if (dev.uniq == 0) { - goto skip; - } + struct input_id id; + ioctl(dev.event, EVIOCGID, &id); + dev.id = *(uint64_t *)&id; } // Check if we already know of this device @@ -321,7 +343,7 @@ void poll_devices() { pthread_mutex_lock(&known_devices_mutex); for (int i = 0; i < known_devices.len; i++) { Controller *c = vec_get(&known_devices, i); - if (c->dev.uniq == dev.uniq) { + if (c->dev.id == dev.id) { found = true; break; } @@ -390,7 +412,7 @@ void poll_devices() { // Pointer to the device in known_devices Controller *p = vec_get(&known_devices, index); - printf("HID: New device, %s [%s] (%s: %012lx)\n", name, ctr->tag, input->d_name, dev.uniq); + printf("HID: New device, %s [%s] (%s: %016lx)\n", name, ctr->tag, input->d_name, dev.id); if (ctr->duplicate) { pthread_mutex_lock(&devices_mutex); @@ -419,11 +441,11 @@ void poll_devices() { // "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) { if (c->ctr.ps4_hidraw && c->dev.hidraw < 0) { - printf("HID: Trying to apply controller state on incompatible device (%012lx)\n", c->dev.uniq); + printf("HID: Trying to apply controller state on incompatible device (%016lx)\n", c->dev.id); return; } - printf("HID: (%012lx) Controller state: #%02x%02x%02x flash: (%d, %d) rumble: (%d, %d)\n", c->dev.uniq, state->led[0], + printf("HID: (%016lx) Controller state: #%02x%02x%02x flash: (%d, %d) rumble: (%d, %d)\n", c->dev.id, state->led[0], state->led[1], state->led[2], state->flash_on, state->flash_off, state->small_rumble, state->big_rumble); uint8_t buf[32] = {0x05, 0xff, 0x00, 0x00}; diff --git a/hid.h b/hid.h index d0d64de..c3b2395 100644 --- a/hid.h +++ b/hid.h @@ -25,6 +25,7 @@ typedef struct { int event; int hidraw; uniq_t uniq; + uint64_t id; char *name; DeviceMap mapping; MessageDeviceInfo device_info; @@ -38,7 +39,7 @@ typedef struct { void *hid_thread(void *arg); void return_device(Controller *c); void forget_device(Controller *c); -Controller *get_device(char *tag); +Controller *get_device(char *tag, bool *stop); void apply_controller_state(Controller *c, MessageControllerState *state); #endif diff --git a/json.c b/json.c index b12412b..c619dad 100644 --- a/json.c +++ b/json.c @@ -16,11 +16,11 @@ static JSONError jerrno = NoError; static size_t jerr_index = 0; // Get a string explaining the last json parsing error -const char *json_strerr() { return JSONErrorMessage[jerrno]; } +const char *json_strerr(void) { return JSONErrorMessage[jerrno]; } // Get the code of the last json parsing error -JSONError json_errno() { return jerrno; } +JSONError json_errno(void) { return jerrno; } // Get the location of the last json parsing error -size_t json_errloc() { return jerr_index; } +size_t json_errloc(void) { return jerr_index; } static inline bool is_primitive(const JSONAdapter *adapter) { return adapter->props == NULL; } diff --git a/json.h b/json.h index 916741f..0a298d7 100644 --- a/json.h +++ b/json.h @@ -60,9 +60,9 @@ typedef struct JSONAdapter JSONAdapter; void json_adapt(uint8_t *buf, const JSONAdapter *adapter, void *ptr); int json_parse(const char *src, size_t src_len, uint8_t *dst, size_t dst_len); void json_print_value(uint8_t *buf); -const char *json_strerr(); -size_t json_errloc(); -JSONError json_errno(); +const char *json_strerr(void); +size_t json_errloc(void); +JSONError json_errno(void); extern const JSONAdapter NumberAdapter; extern const JSONAdapter StringAdapter; diff --git a/net.c b/net.c index 6da8fc5..76c93aa 100644 --- a/net.c +++ b/net.c @@ -5,15 +5,30 @@ #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) 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; + uint8_t code_byte = buf[0]; + MessageCode code = (MessageCode)code_byte; + uint32_t size = 0; uint16_t abs, rel, key, index, *buf16; @@ -62,7 +77,8 @@ int msg_deserialize(const uint8_t *buf, size_t len, Message *restrict dst) { buf += 2; } - return 0; + size = MSS_DEVICE_INFO(abs, rel, key) + 1; + break; case DeviceReport: if (len < 7) return -1; @@ -96,7 +112,10 @@ int msg_deserialize(const uint8_t *buf, size_t len, Message *restrict dst) { for (int i = 0; i < key; i++) dst->device_report.key[i] = *(buf++); - return 0; + buf += align_4(key) - key; + + size = MSS_DEVICE_REPORT(abs, rel, key) + 1; + break; case ControllerState: if (len < MSS_CONTROLLER_STATE) return -1; @@ -110,7 +129,9 @@ int msg_deserialize(const uint8_t *buf, size_t len, Message *restrict dst) { dst->controller_state.big_rumble = buf[8]; dst->controller_state.flash_on = buf[9]; dst->controller_state.flash_off = buf[10]; - return 0; + size = MSS_CONTROLLER_STATE + 1; + buf += size; + break; case Request: { if (len < 3) return -1; @@ -138,16 +159,19 @@ int msg_deserialize(const uint8_t *buf, size_t len, Message *restrict dst) { return -1; } - char *str = malloc(str_len + 1); - str[len] = '\0'; + char *str = malloc(str_len + 1); + str[str_len] = '\0'; strncpy(str, (char *)buf, str_len); + tags[i] = str; + buf += align_2(str_len); } dst->request.requests = tags; - return 0; + size = expected_len + 1; + break; } case DeviceDestroy: if (len < MSS_DESTROY) @@ -155,19 +179,37 @@ int msg_deserialize(const uint8_t *buf, size_t len, Message *restrict dst) { dst->code = code; dst->destroy.index = *(uint16_t *)(buf + 2); - return 0; + size = MSS_DESTROY + 1; + buf += size; + break; default: return -1; } + + if(size + MAGIC_SIZE > len + 1) { + return -1; + } + + if(*(MAGIC_TYPE*)buf != MAGIC_END) { + printf("NET: Magic not found\n"); + return -1; + } + + return size + 2 * MAGIC_SIZE; } // 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 0 we can't serialize any message - if (len-- == 0) + // If len is less than the two magic and the code we can't serialize any message + if (len < MAGIC_SIZE * 2 + 1) 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: @@ -214,7 +256,8 @@ int msg_serialize(uint8_t *restrict buf, size_t len, const Message *msg) { buf += 2; } - return MSS_DEVICE_INFO(abs, rel, key) + 1; + size = MSS_DEVICE_INFO(abs, rel, key) + 1; + break; case DeviceReport: abs = msg->device_report.abs_count; rel = msg->device_report.rel_count; @@ -244,7 +287,9 @@ int msg_serialize(uint8_t *restrict buf, size_t len, const Message *msg) { for (int i = 0; i < key; i++) *(buf++) = msg->device_report.key[i]; - return MSS_DEVICE_REPORT(abs, rel, key) + 1; + size = MSS_DEVICE_REPORT(abs, rel, key) + 1; + buf += align_4(key) - key; + break; case ControllerState: if (len < MSS_CONTROLLER_STATE) return -1; @@ -260,7 +305,9 @@ int msg_serialize(uint8_t *restrict buf, size_t len, const Message *msg) { buf[8] = msg->controller_state.big_rumble; buf[9] = msg->controller_state.flash_on; buf[10] = msg->controller_state.flash_off; - return MSS_CONTROLLER_STATE + 1; + size = MSS_CONTROLLER_STATE + 1; + buf += size; + break; case Request: { int expected_len = MSS_REQUEST(msg->request.request_count); if (len < expected_len) @@ -279,7 +326,7 @@ int msg_serialize(uint8_t *restrict buf, size_t len, const Message *msg) { *buf16++ = str_len; buf = (uint8_t *)buf16; - expected_len += byte_len; + expected_len += byte_len + 2; if (len < expected_len) { return -1; } @@ -290,7 +337,8 @@ int msg_serialize(uint8_t *restrict buf, size_t len, const Message *msg) { buf16 = (uint16_t *)buf; } - return expected_len; + size = expected_len; + break; } case DeviceDestroy: if (len < MSS_DESTROY) @@ -299,11 +347,21 @@ int msg_serialize(uint8_t *restrict buf, size_t len, const Message *msg) { buf[0] = (uint8_t)msg->code; *(uint16_t *)(buf + 2) = msg->controller_state.index; - return MSS_DESTROY + 1; + size = MSS_DESTROY + 1; + buf += size; + break; default: printf("ERR(msg_serialize): Trying to serialize unknown message of code %d\n", msg->code); return -1; } + + if(size + MAGIC_SIZE > len) { + return -1; + } + + *(MAGIC_TYPE*)buf = MAGIC_END; + + return size + MAGIC_SIZE * 2; } void msg_free(Message *msg) { @@ -314,3 +372,29 @@ void msg_free(Message *msg) { 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]); + } + } +} diff --git a/net.h b/net.h index 1ed918a..625e416 100644 --- a/net.h +++ b/net.h @@ -5,6 +5,11 @@ #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; + typedef enum { NoMessage = 0, DeviceInfo = 1, @@ -55,7 +60,7 @@ typedef struct { uint32_t rel[REL_CNT]; uint8_t key[KEY_CNT]; } MessageDeviceReport; -#define MSS_DEVICE_REPORT(abs, rel, key) (8 + abs * 4 + rel * 4 + key * 1 + 1) +#define MSS_DEVICE_REPORT(abs, rel, key) (11 + abs * 4 + rel * 4 + align_4(key)) // 1 aligned typedef struct { @@ -99,5 +104,6 @@ typedef union { 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); #endif diff --git a/server.c b/server.c index 5c7b858..06e3643 100644 --- a/server.c +++ b/server.c @@ -26,6 +26,7 @@ struct Connection { int socket; uint32_t id; + bool closed; }; struct DeviceThreadArgs { @@ -39,10 +40,11 @@ static void default_timespec(void *ptr) { *(struct timespec *)ptr = POLL_DEVICE_ static void default_request_timeout(void *ptr) { *(uint32_t *)ptr = REQUEST_TIMEOUT; } const JSONPropertyAdapter FilterAdapterProps[] = { - {".mac_address", &StringAdapter, offsetof(ControllerFilter, mac_address), default_to_zero_u64, tsf_strmac_to_u64}, - {".vendor", &StringAdapter, offsetof(ControllerFilter, vendor), default_to_negative_one_i32, tsf_hex_to_i32 }, - {".product", &StringAdapter, offsetof(ControllerFilter, product), default_to_negative_one_i32, tsf_hex_to_i32 }, - {".js", &BooleanAdapter, offsetof(ControllerFilter, js), default_to_false, NULL }, + {".uniq", &StringAdapter, offsetof(ControllerFilter, uniq), default_to_zero_u64, tsf_uniq_to_u64}, + {".vendor", &StringAdapter, offsetof(ControllerFilter, vendor), default_to_negative_one_i32, tsf_hex_to_i32 }, + {".product", &StringAdapter, offsetof(ControllerFilter, product), default_to_negative_one_i32, tsf_hex_to_i32 }, + {".js", &BooleanAdapter, offsetof(ControllerFilter, js), default_to_false, NULL }, + {".name", &StringAdapter, offsetof(ControllerFilter, name), default_to_null, NULL }, }; const JSONAdapter FilterAdapter = { .props = FilterAdapterProps, @@ -80,12 +82,16 @@ static sigset_t empty_sigset; #define TRAP(sig, handler) \ if (sigaction(sig, &(struct sigaction){.sa_handler = handler, .sa_mask = empty_sigset, .sa_flags = 0}, NULL) != 0) \ printf("SERVER: can't trap " #sig ".\n") +#define TRAP_IGN(sig) \ + if (sigaction(sig, &(struct sigaction){{SIG_IGN}}, NULL) != 0) \ + printf("SERVER: can't ignore " #sig ".\n") -void device_thread_exit() { +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); - Controller * ctr = *args->controller; - if(ctr != NULL) { + Controller *ctr = *args->controller; + if (ctr != NULL) { return_device(ctr); } @@ -99,6 +105,7 @@ void *device_thread(void *args_) { pthread_setspecific(device_args_key, args); + TRAP_IGN(SIGPIPE); TRAP(SIGTERM, device_thread_exit); uint8_t buf[2048] __attribute__((aligned(4))) = {0}; @@ -106,13 +113,16 @@ void *device_thread(void *args_) { while (true) { *args->controller = NULL; - Controller *ctr = get_device(args->tag); + Controller *ctr = get_device(args->tag, &args->conn->closed); + if(ctr == NULL) { + break; + } *args->controller = ctr; dev_info = ctr->dev.device_info; dev_info.index = args->index; - printf("CONN(%d): [%d] Found suitable [%s] device: '%s' (%012lx)\n", args->conn->id, args->index, args->tag, - ctr->dev.name, ctr->dev.uniq); + printf("CONN(%d): [%d] Found suitable [%s] device: '%s' (%016lx)\n", args->conn->id, args->index, args->tag, + ctr->dev.name, ctr->dev.id); // Send over device info { @@ -129,6 +139,7 @@ void *device_thread(void *args_) { 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.index = args->index; while (true) { struct input_event event; @@ -188,7 +199,7 @@ void *device_thread(void *args_) { // Send device destroy message { MessageDestroy dstr; - dstr.code = DeviceDestroy; + dstr.code = DeviceDestroy; dstr.index = args->index; int len = msg_serialize(buf, 2048, (Message *)&dstr); @@ -199,7 +210,7 @@ void *device_thread(void *args_) { } } - device_thread_exit(); + device_thread_exit(SIGTERM); return NULL; } @@ -255,12 +266,24 @@ 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) { + printf("CONN(%d): Got message: ", args->id); + printf("\n"); + } else { + printf("CONN(%d): Malformed message\n", args->id); } // Parse message Message msg; - if (msg_deserialize(buf, len, &msg) != 0) { - printf("CONN(%d): Couldn't parse message.\n", args->id); + int msg_len = msg_deserialize(buf, len, &msg); + if (msg_len < 0) { + if (len > 1 + MAGIC_SIZE * 2) { + printf("CONN(%d): Couldn't parse message: ", args->id); + print_message_buffer(buf, len); + printf("\n"); + } else { + printf("CONN(%d): Couldn't parse message", args->id); + } continue; } @@ -315,18 +338,19 @@ void *server_handle_conn(void *args_) { conn_end: shutdown(args->socket, SHUT_RDWR); printf("CONN(%u): connection closed (%s)\n", args->id, closing_message); - free(args); + args->closed = true; for (int i = 0; i < device_threads.len; i++) { pthread_t thread = *(pthread_t *)vec_get(&device_threads, i); pthread_kill(thread, SIGTERM); pthread_join(thread, NULL); } + free(args); return NULL; } static int sockfd; -void clean_exit() { +void clean_exit(int _sig) { printf("\rSERVER: exiting\n"); close(sockfd); exit(0); @@ -405,6 +429,7 @@ void server_run(uint16_t port, char *config_path) { struct Connection conn; conn.socket = accept(sock, &con_addr, &con_len); + conn.closed = false; if (conn.socket >= 0) { printf("SERVER: got connection\n"); diff --git a/server.h b/server.h index a58ff38..99fbbec 100644 --- a/server.h +++ b/server.h @@ -6,13 +6,15 @@ #include typedef struct { - // the 0 mac_address represents no filter - uint64_t mac_address; + // the 0 uniq represents no filter + uint64_t uniq; // negative values means no filter int32_t vendor; // negative values means no filter int32_t product; bool js; + // NULL means no filter + char * name; } ControllerFilter; typedef struct { diff --git a/server_config.json b/server_config.json index a363332..3ba51a5 100644 --- a/server_config.json +++ b/server_config.json @@ -1,16 +1,7 @@ { "controllers": [ { - "filter": { "mac_address": "00:b0:d0:63:c2:26" }, - "tag": "Admin", - "properties": { "duplicate": true } - }, - { - "filter": { "vendor": "054c", "product": "05c4", "js": true }, - "tag": "User" - }, - { - "filter": { "vendor": "046d", "product": "c332"}, + "filter": { "name": "SteelSeries SteelSeries Rival 310 eSports Mouse" }, "tag": "Mouse" } ], diff --git a/util.c b/util.c index 35b23fa..a845ba1 100644 --- a/util.c +++ b/util.c @@ -64,10 +64,10 @@ void tsf_numsec_to_intms(void *arg, void *ptr) { *(uint32_t *)ptr = seconds * 1000; } -void tsf_strmac_to_u64(void *arg, void *ptr) { +void tsf_uniq_to_u64(void *arg, void *ptr) { char *s = *(char **)arg; if (strnlen(s, 18) != 17) { - printf("JSON: wrong length for mac address, expected 'xx:xx:xx:xx:xx:xx'\n"); + printf("JSON: wrong length for uniq, expected 'xx:xx:xx:xx:xx:xx'\n"); free(s); return; } @@ -85,7 +85,7 @@ void tsf_strmac_to_u64(void *arg, void *ptr) { else if (c == ':') continue; else { - printf("JSON: unexpected character '%c' in mac address at position %i (%s)\n", c, i, s); + printf("JSON: unexpected character '%c' in uniq at position %i (%s)\n", c, i, s); free(s); return; } diff --git a/util.h b/util.h index 11148d0..e724f2d 100644 --- a/util.h +++ b/util.h @@ -13,7 +13,9 @@ uint16_t parse_port(const char *str); static inline bool bit_set(uint8_t *bits, int i) { return bits[i / 8] & (1 << (i % 8)); } // Align n to the next 8 boundary static inline size_t align_8(size_t n) { return (((n - 1) >> 3) + 1) << 3; } -// Align n to the next 8 boundary +// Align n to the next 4 boundary +static inline size_t align_4(size_t n) { return (((n - 1) >> 2) + 1) << 2; } +// Align n to the next 2 boundary static inline size_t align_2(size_t n) { return (((n - 1) >> 1) + 1) << 1; } uint8_t parse_hex_digit(char h); @@ -29,7 +31,7 @@ void default_to_negative_one_i32(void *ptr); void tsf_numsec_to_timespec(void *arg, void *ptr); void tsf_numsec_to_intms(void *arg, void *ptr); -void tsf_strmac_to_u64(void *arg, void *ptr); +void tsf_uniq_to_u64(void *arg, void *ptr); void tsf_hex_to_i32(void *arg, void *ptr); void tsf_double_to_size(void * arg, void * ptr); void tsf_hex_to_color(void *arg, void *ptr); diff --git a/vec.c b/vec.c index 95b6715..fc84e26 100644 --- a/vec.c +++ b/vec.c @@ -6,7 +6,7 @@ #define INIT_CAP 8 -static void handle_alloc_error() { +static void handle_alloc_error(void) { printf("Error when allocating memory.\n"); exit(2); }