diff --git a/.clang-format b/.clang-format index 80d3293..44bced6 100644 --- a/.clang-format +++ b/.clang-format @@ -1,2 +1,6 @@ BasedOnStyle: LLVM IndentWidth: 4 +AlignConsecutiveDeclarations: true +AlignConsecutiveAssignments: true +PointerAlignment: Right +ColumnLimit: 110 diff --git a/.gitignore b/.gitignore index 1716794..a51f196 100644 --- a/.gitignore +++ b/.gitignore @@ -1,4 +1,3 @@ .ccls-cache objects jsfw -plan diff --git a/client.h b/client.h index 80e029f..f76b042 100644 --- a/client.h +++ b/client.h @@ -1,3 +1,4 @@ +// vi: set ft=c #ifndef CLIENT_H #define CLIENT_H diff --git a/hashmap.c b/hashmap.c deleted file mode 100644 index 06d5567..0000000 --- a/hashmap.c +++ /dev/null @@ -1,346 +0,0 @@ -#include -#include -#include - -#include "hashmap.h" -#include "util.h" - -uint32_t seed = 0; - -void init_seed() { - if (seed) - return; - seed = random(); -} - -// All the code from here: -// Is taken from the internet because I needed a simple hash function -// -------------------------------------------------------- - -#define PRIME1 0x9E3779B1U /*!< 0b10011110001101110111100110110001 */ -#define PRIME2 0x85EBCA77U /*!< 0b10000101111010111100101001110111 */ -#define PRIME3 0xC2B2AE3DU /*!< 0b11000010101100101010111000111101 */ -#define PRIME4 0x27D4EB2FU /*!< 0b00100111110101001110101100101111 */ -#define PRIME5 0x165667B1U /*!< 0b00010110010101100110011110110001 */ - -uint32_t xxhash32(uint8_t *data, size_t len) { - size_t end = len; - size_t offset = 0; - uint32_t h32; - if (len >= 16) { - int limit = end - 16; - uint32_t v1 = seed + PRIME1 + PRIME2; - uint32_t v2 = seed + PRIME2; - uint32_t v3 = seed; - uint32_t v4 = seed - PRIME1; - - do { - v1 += (*(uint32_t *)(data + offset)) * PRIME2; - v1 = rotl(v1, 13); - v1 *= PRIME1; - offset += 4; - v2 += (*(uint32_t *)(data + offset)) * PRIME2; - v2 = rotl(v2, 13); - v2 *= PRIME1; - offset += 4; - v3 += (*(uint32_t *)(data + offset)) * PRIME2; - v3 = rotl(v3, 13); - v3 *= PRIME1; - offset += 4; - v4 += (*(uint32_t *)(data + offset)) * PRIME2; - v4 = rotl(v4, 13); - v4 *= PRIME1; - offset += 4; - } while (offset <= limit); - // main loop ends - // mix - h32 = rotl(v1, 1) + rotl(v2, 7) + rotl(v3, 12) + rotl(v4, 18); - } else { - h32 = seed + PRIME5; - } - - if (end > 4) { - for (h32 += len; offset <= end - 4; offset += 4) { - h32 += (*(uint32_t *)(data + offset)) * PRIME3; - h32 = rotl(h32, 17) * PRIME4; - } - } - - while (offset < end) { - h32 += (data[offset] & 255) * PRIME5; - h32 = rotl(h32, 11) * PRIME1; - ++offset; - } - - h32 ^= h32 >> 15; - h32 *= PRIME2; - h32 ^= h32 >> 13; - h32 *= PRIME3; - h32 ^= h32 >> 16; - return h32; -} - -// -------------------------------------------------------- -// To here - -// Po2 -#define INIT_BUCKET_COUNT 32 -#define HEADER_SIZE sizeof(void *) -#define GROW_THRESHOLD 75 -// The size of an entry for a data size of -#define ENTRY(size) (HEADER_SIZE + size) -// Each entry is composed of a 8 bytes header and the data (or garbage if there -// is none). The 8 bytes header is either a non null pointer to the key or zero -// if the bucket is empty - -static inline void handle_alloc_error() { - printf("Error when allocating (OOM?)\n"); - exit(1); -} - -Map map_new(size_t data_size) { - Map map = {}; - map.bucket_count = INIT_BUCKET_COUNT; - map.data_size = data_size; - map.used = 0; - map.buckets = calloc(INIT_BUCKET_COUNT, ENTRY(data_size)); - map.mask = INIT_BUCKET_COUNT - 1; - if (!map.buckets) - handle_alloc_error(); - return map; -} - -// Double the size of the map -void map_grow(Map *map) { - size_t entry_size = ENTRY(map->data_size); - - size_t new_bucket_count = map->bucket_count * 2; - void *new_alloc = calloc(new_bucket_count, entry_size); - size_t new_mask = (map->mask << 1) + 1; - if (!new_alloc) - handle_alloc_error(); - void *current = map->buckets; - - for (int i = 0; i < map->bucket_count; i++) { - void *header = *(void **)current; - if (header == NULL) - continue; // skip if unused - size_t len = *(size_t *)header; - void *key = header + sizeof(size_t); - - uint32_t hash = xxhash32(key, len); - uint32_t index = hash & new_mask; - void *dst_bucket = new_alloc + index * entry_size; - - while (*(void **)dst_bucket != NULL) { - dst_bucket += entry_size; - index++; - if (index == new_bucket_count) { - index = 0; - dst_bucket = new_alloc; - } - } - - *(void **)dst_bucket = header; // set key of new bucket - memcpy(dst_bucket + HEADER_SIZE, current + HEADER_SIZE, - map->data_size); // set value of new bucket - - current += entry_size; - } - - free(map->buckets); - map->buckets = new_alloc; - map->mask = new_mask; - map->bucket_count = new_bucket_count; -} - -void map_insert(Map *map, uint8_t *key, size_t key_len, void *data) { - uint32_t hash = xxhash32(key, key_len); - size_t index = hash & map->mask; - size_t entry_size = ENTRY(map->data_size); - void *bucket = map->buckets + index * entry_size; - // Go to next empty bucket - while (*(void **)bucket != NULL) { - bucket += entry_size; - index++; - if (index == map->bucket_count) { - index = 0; - bucket = map->buckets; - } - } - // memory for the key: the size + the data - void *key_buf = malloc(sizeof(size_t) + key_len); - if (!key_buf) - handle_alloc_error(); - *(size_t *)key_buf = key_len; // write key_len - memcpy(key_buf + sizeof(size_t), key, key_len); // write key - - *(void **)bucket = key_buf; - memcpy(bucket + HEADER_SIZE, data, map->data_size); - map->used++; - - if (map->used * 100 / map->bucket_count > GROW_THRESHOLD) { - map_grow(map); - } -} - -inline static void *map_find(Map *map, uint8_t *key, size_t key_len) { - uint32_t hash = xxhash32(key, key_len); - size_t index = hash & map->mask; - size_t entry_size = ENTRY(map->data_size); - void *bucket = map->buckets + index * entry_size; - size_t start_index = index; - while (1) { - void *header = *(void **)bucket; - if (header) { - size_t cur_key_len = *(size_t *)header; - void *cur_key = header + sizeof(size_t); - if (cur_key_len == key_len && memcmp(cur_key, key, key_len) == 0) - break; // We found the bucket (usally the first one) - } - - bucket += entry_size; - index++; - // Go back to begining if we went to the end; - if (index == map->bucket_count) { - index = 0; - bucket = map->buckets; - } - // If we went over every entry without finding the bucket - if (index == start_index) { - return NULL; - } - } - return bucket; -} - -bool map_contains(Map *map, uint8_t *key, size_t key_len) { - return map_find(map, key, key_len) != NULL; -} - -void map_get(Map *map, uint8_t *key, size_t key_len, void *data) { - void *bucket = map_find(map, key, key_len); - if (!bucket) { - printf("ERR (map_get): key not in map\n"); - return; - } - memcpy(data, bucket + HEADER_SIZE, map->data_size); -} - -void map_remove(Map *map, uint8_t *key, size_t key_len, void *data) { - void *bucket = map_find(map, key, key_len); - if (!bucket) { - printf("ERR (map_remove): key not in map\n"); - return; - } - - if (data != NULL) - memcpy(data, bucket + HEADER_SIZE, map->data_size); - - void *key_ptr = *(void **)bucket; - free(key_ptr); - *(void **)bucket = NULL; - map->used--; -} - -static inline size_t map_next_index_from(Map *map, size_t from) { - if (from >= map->bucket_count) - return -1; - for (int i = from; i < map->bucket_count; i++) { - void *bucket = map->buckets + i * ENTRY(map->data_size); - if (*(void **)bucket != NULL) - return i; - } - return -1; -} - -MapIter map_iter(Map *map) { - MapIter iter; - iter.map = map; - iter.next = map_next_index_from(map, 0); - return iter; -} - -bool map_iter_has_next(MapIter *iter) { return iter->next != -1; } - -void map_iter_next(MapIter *iter, void **key, size_t *key_len, void **data) { - void *bucket = - iter->map->buckets + ENTRY(iter->map->data_size) * iter->next; - if (key) - *key = (*(void **)bucket) + sizeof(size_t); - if (key_len) - *key_len = **(size_t **)bucket; - if (data) - *data = bucket + HEADER_SIZE; - iter->next = map_next_index_from(iter->map, iter->next + 1); -} - -void _center(size_t length, char *format, uintmax_t value) { - size_t l = snprintf(NULL, 0, format, value); - char str[l + 1]; - int padleft = (length - l) / 2; - int padright = length - l - padleft; - snprintf(str, l + 1, format, value); - printf("%*s%s%*s", padleft, "", str, padright, ""); -} - -void _centers(size_t length, char * s) { - size_t l = strlen(s); - char str[l + 1]; - int padleft = (length - l) / 2; - int padright = length - l - padleft; - snprintf(str, l + 1, "%s", s); - printf("%*s%s%*s", padleft, "", str, padright, ""); -} - -void map_debug(Map map, char *format) { - printf("%s", "┌────────┬───────────────┬───────────┬─────────┐\n"); - printf("%s", "│ map │ buckets count │ data size │ members │\n"); - printf("%s", "├────────┼───────────────┼───────────┼─────────┤\n"); - printf("%s", "│ values │"); - _center(15, "%lu", map.bucket_count); - printf("%s", "│"); - _center(11, "%lu", map.data_size); - printf("%s", "│"); - _center(9, "%lu", map.used); - printf("%s", "│\n"); - printf("%s", "└────────┴───────────────┴───────────┴─────────┘\n"); - bool last_occ = true; - bool last_n = false; - for (size_t i = 0; i < map.bucket_count; i++) { - void * e = map.buckets + map.data_size * i; - bool locc = last_occ; - last_occ = *(void**)e != NULL; - if (!locc && !last_occ) - continue; - if (locc && !last_occ) { - if (i == 0) { - printf("%s", "┌──────────────────────────────────────────┐\n"); - } else if (!last_n) { - printf("%s", - "\033[1A├────┴──────────────────┴──────────────────┤\n"); - } else { - printf("%s", - "\033[1A┌────┴──────────────────┴──────────────────┤\n"); - } - printf("%s", "│ ..... │\n"); - printf("%s", "├────┬──────────────────┬──────────────────┤\n"); - continue; - } - printf("%s", "│"); - _center(4, "%lu", i); - printf("%s", "│"); - void * ptr = *(void**)e; - _centers(18, ptr == NULL ? "N/A" : ptr + sizeof(size_t)); - printf("%s", "│"); - _center(18, format, *(uint32_t *)(e + HEADER_SIZE)); - printf("%s", "│\n"); - printf("├────┼──────────────────┼──────────────────┤\n"); - } - if (last_occ) { - printf("\033[1A└────┴──────────────────┴──────────────────┘\n"); - } else { - printf("\033[1A└──────────────────────────────────────────┘\n"); - } - printf("\n\n"); -} diff --git a/hashmap.h b/hashmap.h deleted file mode 100644 index cdcc489..0000000 --- a/hashmap.h +++ /dev/null @@ -1,68 +0,0 @@ -#ifndef HASHMAP_H -#define HASHMAP_H -#include -#include -#include -#include - -// A hashmap -typedef struct { - // Pointer to allocation for buckets - void * buckets; - // Typically sizeof(T) for Map<_, T> - size_t data_size; - // Always a power of 2 - size_t bucket_count; - // How many used buckets are there - size_t used; - size_t mask; -} Map; - -typedef struct { - Map * map; - size_t next; -} MapIter; - -// Create a new map of a type -#define map_of(type) map_new(sizeof(type)) -// Create a new map holding value of a size -Map map_new(size_t data_size); -// Insert a key value pair in the map -void map_insert(Map * map, uint8_t * key, size_t key_len, void * data); -// Test if a key exist within a map -bool map_contains(Map * map, uint8_t * key, size_t key_len); -// Get the value of a key in the map into data -void map_get(Map * map, uint8_t * key, size_t key_len, void * data); -// Remove a key value pair from the map, if data is not NULL, write value to it. -void map_remove(Map * map, uint8_t * key, size_t key_len, void * data); -// Get an iterator of the map -MapIter map_iter(Map * map); -// Test if there is a next -bool map_iter_has_next(MapIter * iter); -// Get the next value, if key is not NULL, put a pointer to the key in key, if key_len is not NULL -// put the len of the key in key_len, if data is not null, put a pointer to the data in data. -void map_iter_next(MapIter * iter, void ** key, size_t * key_len, void ** data); - -// map_insert with a string key -static inline void map_insert_str(Map * map, const char * key, void * data) { - size_t len = strlen(key) + 1; - map_insert(map, (void *)key, len, data); -} -// map_contains with a string key -static inline bool map_contains_str(Map * map, const char * key) { - size_t len = strlen(key) + 1; - return map_contains(map, (void *)key, len); -} -// map_get with a string key -static inline void map_get_str(Map * map, const char * key, void * data) { - size_t len = strlen(key) + 1; - map_get(map, (void *)key, len, data); -} -// map_remove with a string key -static inline void map_remove_str(Map * map, const char * key, void * data) { - size_t len = strlen(key) + 1; - map_remove(map, (void *)key, len, data); -} - -void map_debug(Map map, char *format); -#endif diff --git a/hid.c b/hid.c index d0fac66..b21c219 100644 --- a/hid.c +++ b/hid.c @@ -28,6 +28,8 @@ static pthread_cond_t devices_queue_cond = PTHREAD_COND_INITIALIZER; // Mutex for devices static pthread_mutex_t devices_mutex = PTHREAD_MUTEX_INITIALIZER; +static char * DEFAULT_NAME = "Unnamed Device"; + // uniqs are just hexadecimal numbers with colons in between each byte uniq_t parse_uniq(char uniq[17]) { uniq_t res = 0; @@ -59,6 +61,8 @@ bool filter_event(int fd, char * event) { } } + closedir(device_dir); + if(!found) { return false; } @@ -97,6 +101,12 @@ PhysicalDevice get_device() { } void return_device(PhysicalDevice * dev) { + if(dev->name != NULL && dev->name != DEFAULT_NAME) { + printf("HID: Returning device '%s' (%012lx)\n", dev->name, dev->uniq); + free(dev->name); + } else { + printf("HID: Returning device %012lx\n", dev->uniq); + } close(dev->event); close(dev->hidraw); pthread_mutex_lock(&devices_mutex); @@ -132,8 +142,12 @@ void poll_devices() { continue; } - char name[256] = {}; - ioctl(dev.event, EVIOCGNAME(256), name); + char name_buf[256] = {}; + char * name; + if(ioctl(dev.event, EVIOCGNAME(256), name_buf) >= 0) + name = name_buf; + else + name = DEFAULT_NAME; if(!filter_event(dev.event, input->d_name)) goto skip; @@ -198,6 +212,12 @@ void poll_devices() { dev.hidraw = open(hidraw_path, O_WRONLY); if(dev.hidraw < 0) goto skip; + dev.name = malloc(256); + if(dev.name == NULL) + dev.name = DEFAULT_NAME; + else + strcpy(dev.name, name); + pthread_mutex_lock(&devices_mutex); vec_push(&devices, &uniq); pthread_mutex_unlock(&devices_mutex); diff --git a/hid.h b/hid.h index 77bae69..7c22d92 100644 --- a/hid.h +++ b/hid.h @@ -1,3 +1,4 @@ +// vi: set ft=c #ifndef HID_H #define HID_H #include @@ -10,6 +11,7 @@ typedef struct { int event; int hidraw; uniq_t uniq; + char * name; } PhysicalDevice; void * hid_thread(); diff --git a/main.h b/main.h index dd67f7c..39775d1 100644 --- a/main.h +++ b/main.h @@ -1,3 +1,4 @@ +// vi: set ft=c #ifndef MAIN_H #define MAIN_H #include diff --git a/net.h b/net.h index da5df48..ffb0ee5 100644 --- a/net.h +++ b/net.h @@ -1,3 +1,4 @@ +// vi: set ft=c #ifndef NET_H #define NET_H #include diff --git a/server.c b/server.c index 58a40d5..dca9444 100644 --- a/server.c +++ b/server.c @@ -1,69 +1,96 @@ -#include -#include -#include -#include -#include -#include +#include +#include +#include +#include +#include +#include +#include +#include "hid.h" #include "main.h" -#include "vec.h" #include "net.h" +#include "vec.h" struct Connection { - int socket; + int socket; uint32_t id; }; -void * server_handle_conn(void * args_) { - struct Connection * args = args_; +void *server_handle_conn(void *args_) { + struct Connection *args = args_; printf("THREAD(%u): start\n", args->id); - while(1) { - uint8_t buf[1024]; - while(1) { - int len = recv(args->socket, buf, 1024, MSG_WAITALL); - if(len <= 0) break; - Message msg; - if(msg_deserialize(buf, len, &msg) == 0) { - - } else { - printf("Couldn't parse message.\n"); - } - } - printf("THREAD(%u): connection closed\n", args->id); - } + int enable = 1; + int idle_time = 10; + int keep_count = 5; + int keep_interval = 5; + if (setsockopt(args->socket, SOL_SOCKET, SO_KEEPALIVE, &enable, sizeof(enable)) != 0) + printf("ERR(server_handle_conn): Enabling socket keepalives on client\n"); + if (setsockopt(args->socket, SOL_TCP, TCP_KEEPIDLE, &idle_time, sizeof(idle_time)) != 0) + printf("ERR(server_handle_conn): Setting initial ERR()-time value\n"); + if (setsockopt(args->socket, SOL_TCP, TCP_KEEPCNT, &keep_count, sizeof(keep_count)) != 0) + printf("ERR(server_handle_conn): Setting idle retry count\n"); + if (setsockopt(args->socket, SOL_TCP, TCP_KEEPINTVL, &keep_interval, sizeof(keep_interval)) != 0) + printf("ERR(server_handle_conn): Setting idle retry interval\n"); + + PhysicalDevice dev = get_device(); + printf("THREAD(%u): got device '%s'\n", args->id, dev.name); + + uint8_t buf[1024]; + while (1) { + int len = recv(args->socket, buf, 1024, MSG_WAITALL); + + if (len <= 0) + goto conn_end; + + Message msg; + if (msg_deserialize(buf, len, &msg) == 0) { + + } else { + printf("Couldn't parse message.\n"); + } + } + printf("THREAD(%u): connection closed\n", args->id); + +conn_end: + return_device(&dev); free(args); return NULL; } void server_run(uint16_t port) { printf("SERVER: start\n"); + int sock = socket(AF_INET, SOCK_STREAM, 0); - if(sock < 0) panicf("Couldn't open socket\n"); + if (sock < 0) + panicf("Couldn't open socket\n"); + struct sockaddr_in addr = {}; - addr.sin_family = AF_INET; - addr.sin_addr.s_addr = htonl(INADDR_ANY); - addr.sin_port = htons(port); - if(bind(sock, (struct sockaddr*)&addr, sizeof(addr)) != 0) + addr.sin_family = AF_INET; + addr.sin_addr.s_addr = htonl(INADDR_ANY); + addr.sin_port = htons(port); + + if (bind(sock, (struct sockaddr *)&addr, sizeof(addr)) != 0) panicf("Couldn't bind to the socket\n"); - if(listen(sock, 16) != 0) + + if (listen(sock, 16) != 0) panicf("Couldn't listen on socket\n"); uint32_t ids = 0; - while(1) { - struct sockaddr con_addr; - socklen_t con_len = sizeof(con_addr); + while (1) { + struct sockaddr con_addr; + socklen_t con_len = sizeof(con_addr); struct Connection conn; conn.socket = accept(sock, &con_addr, &con_len); - if(conn.socket >= 0) { + if (conn.socket >= 0) { printf("SERVER: got connection\n"); conn.id = ids++; - struct Connection * conn_ptr = malloc(sizeof(struct Connection)); + struct Connection *conn_ptr = malloc(sizeof(struct Connection)); memcpy(conn_ptr, &conn, sizeof(struct Connection)); pthread_t thread; diff --git a/server.h b/server.h index 469f00e..6839fa6 100644 --- a/server.h +++ b/server.h @@ -1,3 +1,4 @@ +// vi: set ft=c #ifndef SERVER_H #define SERVER_H #include diff --git a/util.h b/util.h index c2c10db..7c0b8e0 100644 --- a/util.h +++ b/util.h @@ -1,3 +1,4 @@ +// vi: set ft=c #ifndef UTIL_H #define UTIL_H #include diff --git a/vec.h b/vec.h index 19b65d1..fbc7c7e 100644 --- a/vec.h +++ b/vec.h @@ -1,3 +1,4 @@ +// vi: set ft=c #ifndef VEC_H #define VEC_H #include