From 67cab819782fe6d24fff94c42110b091ba027573 Mon Sep 17 00:00:00 2001 From: HimbeerserverDE Date: Sat, 9 Oct 2021 17:07:38 +0200 Subject: [PATCH] Refactor type hooks --- listen.c | 24 +++++-- listen.h | 7 +- peer.c | 29 ++++++-- peer.h | 9 +-- recv.h | 8 +++ recv_thread.c | 19 +++--- typegen/main.c | 177 ++++++++++++++++++------------------------------- 7 files changed, 132 insertions(+), 141 deletions(-) diff --git a/listen.c b/listen.c index a4b19bf..e040efa 100644 --- a/listen.c +++ b/listen.c @@ -1,12 +1,12 @@ #include +#include +#include #include #include #include #include #include -#include "listen.h" - // ---- // Peer // ---- @@ -45,8 +45,7 @@ static DragonnetPeer *dragonnet_peer_accept(int sock, struct sockaddr_in6 addr, // -------- DragonnetListener *dragonnet_listener_new(char *addr, - void (*on_connect)(DragonnetPeer *p), - void (*on_recv_type)(struct dragonnet_peer *, u16)) + void (*on_connect)(DragonnetPeer *p)) { DragonnetListener *l = malloc(sizeof *l); pthread_rwlock_init(&l->mu, NULL); @@ -54,7 +53,7 @@ DragonnetListener *dragonnet_listener_new(char *addr, l->sock = socket(AF_INET6, SOCK_STREAM, 0); l->on_connect = on_connect; - l->on_recv_type = on_recv_type; + l->on_recv_type = calloc(sizeof *l->on_recv_type, dragonnet_num_types); int so_reuseaddr = 1; if (setsockopt(l->sock, SOL_SOCKET, SO_REUSEADDR, &so_reuseaddr, @@ -83,6 +82,21 @@ DragonnetListener *dragonnet_listener_new(char *addr, return l; } +void dragonnet_listener_set_recv_hook(DragonnetListener *l, u16 type_id, + void (*on_recv)(struct dragonnet_peer *, void *)) +{ + pthread_rwlock_rdlock(&l->mu); + DragonnetListenerState state = l->state; + pthread_rwlock_unlock(&l->mu); + + if (state >= DRAGONNET_LISTENER_ACTIVE) + return; + + pthread_rwlock_wrlock(&l->mu); + l->on_recv_type[type_id] = on_recv; + pthread_rwlock_unlock(&l->mu); +} + static void *listener_main(void *g_listener) { DragonnetListener *l = (DragonnetListener *) g_listener; diff --git a/listen.h b/listen.h index 28c4562..f1fae8d 100644 --- a/listen.h +++ b/listen.h @@ -18,14 +18,15 @@ typedef struct { pthread_t accept_thread; void (*on_connect)(DragonnetPeer *); - void (*on_recv_type)(struct dragonnet_peer *, u16); + void (**on_recv_type)(DragonnetPeer *, void *); pthread_rwlock_t mu; } DragonnetListener; DragonnetListener *dragonnet_listener_new(char *addr, - void (*on_connect)(DragonnetPeer *p), - void (*on_recv_type)(struct dragonnet_peer *, u16)); + void (*on_connect)(DragonnetPeer *p)); +void dragonnet_listener_set_recv_hook(DragonnetListener *l, u16 type_id, + void (*on_recv)(struct dragonnet_peer *, void *)); void dragonnet_listener_run(DragonnetListener *l); void dragonnet_listener_close(DragonnetListener *l); void dragonnet_listener_delete(DragonnetListener *l); diff --git a/peer.c b/peer.c index a1bb39d..83e9122 100644 --- a/peer.c +++ b/peer.c @@ -1,19 +1,19 @@ #include +#include +#include +#include #include #include #include -#include "peer.h" -#include "recv_thread.h" - -static bool dragonnet_peer_init(DragonnetPeer *p, char *addr, void (*on_recv_type)(struct dragonnet_peer *, u16)) +static bool dragonnet_peer_init(DragonnetPeer *p, char *addr) { pthread_rwlock_init(&p->mu, NULL); pthread_rwlock_wrlock(&p->mu); p->sock = socket(AF_INET6, SOCK_STREAM, 0); p->raddr = dragonnet_addr_parse_str(addr); - p->on_recv_type = on_recv_type; + p->on_recv_type = calloc(sizeof *p->on_recv_type, dragonnet_num_types); struct sockaddr_in6 sock_addr = dragonnet_addr_sock(p->raddr); if (connect(p->sock, (const struct sockaddr *) &sock_addr, @@ -36,10 +36,10 @@ static bool dragonnet_peer_init(DragonnetPeer *p, char *addr, void (*on_recv_typ return true; } -DragonnetPeer *dragonnet_connect(char *addr, void (*on_recv_type)(struct dragonnet_peer *, u16)) +DragonnetPeer *dragonnet_connect(char *addr) { DragonnetPeer *p = malloc(sizeof *p); - if (!dragonnet_peer_init(p, addr, on_recv_type)) { + if (!dragonnet_peer_init(p, addr)) { dragonnet_peer_delete(p); return NULL; } @@ -47,6 +47,21 @@ DragonnetPeer *dragonnet_connect(char *addr, void (*on_recv_type)(struct dragonn return p; } +void dragonnet_peer_set_recv_hook(DragonnetPeer *p, u16 type_id, + void (*on_recv)(struct dragonnet_peer *, void *)) +{ + pthread_rwlock_rdlock(&p->mu); + DragonnetPeerState state = p->state; + pthread_rwlock_unlock(&p->mu); + + if (state >= DRAGONNET_PEER_ACTIVE) + return; + + pthread_rwlock_wrlock(&p->mu); + p->on_recv_type[type_id] = on_recv; + pthread_rwlock_unlock(&p->mu); +} + void dragonnet_peer_run(DragonnetPeer *p) { pthread_rwlock_wrlock(&p->mu); diff --git a/peer.h b/peer.h index 16c02f9..5dc06fe 100644 --- a/peer.h +++ b/peer.h @@ -3,8 +3,7 @@ #include #include - -#include "addr.h" +#include typedef enum { DRAGONNET_PEER_CREATED, @@ -18,12 +17,14 @@ typedef struct dragonnet_peer { DragonnetPeerState state; pthread_t recv_thread; - void (*on_recv_type)(struct dragonnet_peer *, u16); + void (**on_recv_type)(struct dragonnet_peer *, void *); pthread_rwlock_t mu; } DragonnetPeer; -DragonnetPeer *dragonnet_connect(char *addr, void (*on_recv_type)(struct dragonnet_peer *, u16)); +DragonnetPeer *dragonnet_connect(char *addr); +void dragonnet_peer_set_recv_hook(DragonnetPeer *p, u16 type_id, + void (*on_recv)(struct dragonnet_peer *, void *)); void dragonnet_peer_run(DragonnetPeer *p); void dragonnet_peer_close(DragonnetPeer *p); void dragonnet_peer_delete(DragonnetPeer *p); diff --git a/recv.h b/recv.h index 22b3b97..b0938d9 100644 --- a/recv.h +++ b/recv.h @@ -3,6 +3,14 @@ #include +typedef struct { + size_t siz; + void (*deserialize)(DragonnetPeer *, void *); +} DragonnetType; + +extern u16 dragonnet_num_types; +extern DragonnetType dragonnet_types[]; + void dragonnet_recv_raw(DragonnetPeer *p, void *buf, size_t n); void dragonnet_read_raw(u8 **buf, size_t *n, void *data, size_t len); diff --git a/recv_thread.c b/recv_thread.c index b4975fb..437105e 100644 --- a/recv_thread.c +++ b/recv_thread.c @@ -1,13 +1,13 @@ #include +#include +#include +#include #include #include #include #include #include -#include "peer.h" -#include "recv_thread.h" - void *dragonnet_peer_recv_thread(void *g_peer) { DragonnetPeer *p = (DragonnetPeer *) g_peer; @@ -18,14 +18,14 @@ void *dragonnet_peer_recv_thread(void *g_peer) pthread_rwlock_unlock(&p->mu); while (true) { - u16 type; + u16 type_id; // Copy socket fd so that shutdown doesn't block pthread_rwlock_rdlock(&p->mu); int sock = p->sock; pthread_rwlock_unlock(&p->mu); - ssize_t len = recv(sock, &type, sizeof type, MSG_WAITALL); + ssize_t len = recv(sock, &type_id, sizeof type_id, MSG_WAITALL); if (len < 0) { perror("recv"); dragonnet_peer_delete(p); @@ -44,13 +44,16 @@ void *dragonnet_peer_recv_thread(void *g_peer) return NULL; } - type = be16toh(type); + type_id = be16toh(type_id); + DragonnetType type = dragonnet_types[type_id]; + u8 buf[type.siz]; + type.deserialize(p, buf); pthread_rwlock_rdlock(&p->mu); - void (*on_recv_type)(struct dragonnet_peer *, u16) = p->on_recv_type; + void (*on_recv_type)(DragonnetPeer *, void *) = p->on_recv_type[type_id]; pthread_rwlock_unlock(&p->mu); if (on_recv_type != NULL) - on_recv_type(p, type); + on_recv_type(p, buf); } } diff --git a/typegen/main.c b/typegen/main.c index 183d7f3..2f045bd 100644 --- a/typegen/main.c +++ b/typegen/main.c @@ -1,4 +1,5 @@ #include +#include #include #include #include @@ -146,132 +147,60 @@ static void gen_serializers(FILE *c_fp) static void gen_deserializers(FILE *c_fp) { for (u8 bits = 8; bits <= 64; bits *= 2) { - char *fmt_u = "__attribute__((unused)) static u%d recv_u%d(DragonnetPeer *p)\n"; - char *fmt_s = "__attribute__((unused)) static s%d recv_s%d(DragonnetPeer *p)\n"; + char *fmt = "__attribute__((unused)) static void recv_n%d(DragonnetPeer *p, void *buf)\n"; - fprintf(c_fp, fmt_u, bits, bits); + fprintf(c_fp, fmt, bits); fprintf(c_fp, "{\n"); fprintf(c_fp, "\tu%d be;\n", bits); fprintf(c_fp, "\tdragonnet_recv_raw(p, &be, sizeof be);\n"); - fprintf(c_fp, "\treturn be%dtoh(be);\n", bits); - fprintf(c_fp, "}\n\n"); - - fprintf(c_fp, fmt_s, bits, bits); - fprintf(c_fp, "{\n"); - fprintf(c_fp, "\treturn (s%d) recv_u%d(p);\n", bits, bits); + fprintf(c_fp, "\tbe = be%dtoh(be);\n", bits); + fprintf(c_fp, "\tmemcpy(buf, &be, sizeof be);\n"); fprintf(c_fp, "}\n\n"); - - if (bits >= 32) { - char *fmt_f = "__attribute__((unused)) static f%d recv_f%d(DragonnetPeer *p)\n"; - - fprintf(c_fp, fmt_f, bits, bits); - fprintf(c_fp, "{\n"); - fprintf(c_fp, "\treturn (f%d) recv_u%d(p);\n", bits, bits); - fprintf(c_fp, "}\n\n"); - } } for (u8 elems = 2; elems <= 4; ++elems) { for (u8 bits = 8; bits <= 64; bits *= 2) { - char *fmt_u = "__attribute__((unused)) static v%du%d recv_v%du%d(DragonnetPeer *p)\n"; - char *fmt_s = "__attribute__((unused)) static v%ds%d recv_v%ds%d(DragonnetPeer *p)\n"; + char *fmt = "__attribute__((unused)) static void recv_v%dn%d(DragonnetPeer *p, void *buf)\n"; - fprintf(c_fp, fmt_u, elems, bits, elems, bits); - fprintf(c_fp, "{\n"); - fprintf(c_fp, "\tv%du%d v = {0};\n", elems, bits); - fprintf(c_fp, "\tu%d *ptr = &v.x;\n\n", bits); - fprintf(c_fp, "\tfor (u8 i = 0; i < %d; ++i) {\n", elems); - fprintf(c_fp, "\t\t*ptr++ = recv_u%d(p);\n", bits); - fprintf(c_fp, "\t}\n\n"); - fprintf(c_fp, "\treturn v;\n"); - fprintf(c_fp, "}\n\n"); - - fprintf(c_fp, fmt_s, elems, bits, elems, bits); + fprintf(c_fp, fmt, elems, bits); fprintf(c_fp, "{\n"); - fprintf(c_fp, "\tv%ds%d v = {0};\n", elems, bits); - fprintf(c_fp, "\ts%d *ptr = &v.x;\n\n", bits); - fprintf(c_fp, "\tfor (u8 i = 0; i < %d; ++i) {\n", elems); - fprintf(c_fp, "\t\t*ptr++ = recv_s%d(p);\n", bits); - fprintf(c_fp, "\t}\n\n"); - fprintf(c_fp, "\treturn v;\n"); + fprintf(c_fp, "\tfor (u8 i = 0; i < %d; ++i)\n", elems); + fprintf(c_fp, "\t\trecv_n%d(p, buf);\n", bits); fprintf(c_fp, "}\n\n"); - - if (bits >= 32) { - char *fmt_f = "__attribute__((unused)) static v%df%d recv_v%df%d(DragonnetPeer *p)\n"; - - fprintf(c_fp, fmt_f, elems, bits, elems, bits); - fprintf(c_fp, "{\n"); - fprintf(c_fp, "\tv%df%d v = {0};\n", elems, bits); - fprintf(c_fp, "\tf%d *ptr = &v.x;\n\n", bits); - fprintf(c_fp, "\tfor (u8 i = 0; i < %d; ++i) {\n", elems); - fprintf(c_fp, "\t\t*ptr++ = recv_f%d(p);\n", bits); - fprintf(c_fp, "\t}\n\n"); - fprintf(c_fp, "\treturn v;\n"); - fprintf(c_fp, "}\n\n"); - } } } for (u8 elems = 2; elems <= 4; ++elems) { for (u8 bits = 8; bits <= 64; bits *= 2) { - char *fmt_u = "__attribute__((unused)) static aabb%du%d recv_aabb%du%d(DragonnetPeer *p)\n"; - char *fmt_s = "__attribute__((unused)) static aabb%ds%d recv_aabb%ds%d(DragonnetPeer *p)\n"; + char *fmt = "__attribute__((unused)) static void recv_aabb%dn%d(DragonnetPeer *p, void *buf)\n"; - fprintf(c_fp, fmt_u, elems, bits, elems, bits); + fprintf(c_fp, fmt, elems, bits); fprintf(c_fp, "{\n"); - fprintf(c_fp, "\taabb%du%d v = {0};\n", elems, bits); - fprintf(c_fp, "\tv%du%d *ptr = &v.min;\n\n", elems, bits); - fprintf(c_fp, "\tfor (u8 i = 0; i < 2; ++i) {\n"); - fprintf(c_fp, "\t\t*ptr++ = recv_v%du%d(p);\n", elems, bits); - fprintf(c_fp, "\t}\n\n"); - fprintf(c_fp, "\treturn v;\n"); + fprintf(c_fp, "\tfor (u8 i = 0; i < 2; ++i)\n"); + fprintf(c_fp, "\t\trecv_v%dn%d(p, buf);\n", elems, bits); fprintf(c_fp, "}\n\n"); - - fprintf(c_fp, fmt_s, elems, bits, elems, bits); - fprintf(c_fp, "{\n"); - fprintf(c_fp, "\taabb%ds%d v = {0};\n", elems, bits); - fprintf(c_fp, "\tv%ds%d *ptr = &v.min;\n\n", elems, bits); - fprintf(c_fp, "\tfor (u8 i = 0; i < 2; ++i) {\n"); - fprintf(c_fp, "\t\t*ptr++ = recv_v%ds%d(p);\n", elems, bits); - fprintf(c_fp, "\t}\n\n"); - fprintf(c_fp, "\treturn v;\n"); - fprintf(c_fp, "}\n\n"); - - if (bits >= 32) { - char *fmt_f = "__attribute__((unused)) static aabb%df%d recv_aabb%df%d(DragonnetPeer *p)\n"; - - fprintf(c_fp, fmt_f, elems, bits, elems, bits); - fprintf(c_fp, "{\n"); - fprintf(c_fp, "\taabb%df%d v = {0};\n", elems, bits); - fprintf(c_fp, "\tv%df%d *ptr = &v.min;\n\n", elems, bits); - fprintf(c_fp, "\tfor (u8 i = 0; i < 2; ++i) {\n"); - fprintf(c_fp, "\t\t*ptr++ = recv_v%df%d(p);\n", elems, bits); - fprintf(c_fp, "\t}\n\n"); - fprintf(c_fp, "\treturn v;\n"); - fprintf(c_fp, "}\n\n"); - } } } - fprintf(c_fp, "__attribute__((unused)) static string recv_string(DragonnetPeer *p)\n"); + fprintf(c_fp, "__attribute__((unused)) static void recv_string(DragonnetPeer *p, void *buf)\n"); fprintf(c_fp, "{\n"); - fprintf(c_fp, "\tstring v = malloc(sizeof(u16));\n\n"); + fprintf(c_fp, "\tstring v = malloc(1 + (u16) ~0);\n\n"); fprintf(c_fp, "\tchar ch;\n"); fprintf(c_fp, "\tfor (u16 i = 0; ch != '\\0'; ++i) {\n"); - fprintf(c_fp, "\t\tch = recv_s8(p);\n"); + fprintf(c_fp, "\t\trecv_n8(p, &ch);\n"); fprintf(c_fp, "\t\tv[i] = ch;\n"); fprintf(c_fp, "\t}\n\n"); fprintf(c_fp, "\tv = realloc(v, strlen(v));\n"); - fprintf(c_fp, "\treturn v;\n"); + fprintf(c_fp, "\tmemcpy(buf, v, strlen(v));\n"); fprintf(c_fp, "}\n\n"); - fprintf(c_fp, "__attribute__((unused)) static Blob *recv_Blob(DragonnetPeer *p)\n\n"); + fprintf(c_fp, "__attribute__((unused)) static void recv_Blob(DragonnetPeer *p, void *buf)\n\n"); fprintf(c_fp, "{\n"); fprintf(c_fp, "\tBlob *v = malloc(sizeof *v);\n"); - fprintf(c_fp, "\tv->siz = recv_u32(p);\n"); + fprintf(c_fp, "\trecv_n32(p, &v->siz);\n"); fprintf(c_fp, "\tv->data = malloc(v->siz);\n"); fprintf(c_fp, "\tdragonnet_recv_raw(p, v->data, v->siz);\n\n"); - fprintf(c_fp, "\treturn v;\n"); + fprintf(c_fp, "\tmemcpy(buf, v->data, v->siz);\n"); fprintf(c_fp, "}\n\n"); } @@ -587,7 +516,6 @@ int main(__attribute((unused)) int argc, __attribute((unused)) char **argv) size_t tokens_len = split(&tokens, msgs[i], " "); fprintf(c_fp, "\tsend_%s(p, false, type.%s);\n", &tokens[0][1], tokens[1]); - free_split(tokens, tokens_len); tokens = NULL; } @@ -602,8 +530,8 @@ int main(__attribute((unused)) int argc, __attribute((unused)) char **argv) fprintf(c_fp, "}\n\n"); msg = msgs[i]; - fprintf(h_fp, "void dragonnet_peer_send_%s(DragonnetPeer *p, %s type);\n", msg, msg); - fprintf(c_fp, "void dragonnet_peer_send_%s(DragonnetPeer *p, %s type)\n{\n", msg, msg); + fprintf(h_fp, "void dragonnet_peer_send_%s(DragonnetPeer *p, %s *type);\n", msg, msg); + fprintf(c_fp, "void dragonnet_peer_send_%s(DragonnetPeer *p, %s *type)\n{\n", msg, msg); char upper[1 + strlen(msgs[i])]; char *ptr = upper; @@ -618,9 +546,9 @@ int main(__attribute((unused)) int argc, __attribute((unused)) char **argv) size_t tokens_len = split(&tokens, msgs[i], " "); if (i >= msgs_len-1 || msgs[1+i][0] != '\t') - fprintf(c_fp, "\tsend_%s(p, true, type.%s);\n", &tokens[0][1], tokens[1]); + fprintf(c_fp, "\tsend_%s(p, true, type->%s);\n", &tokens[0][1], tokens[1]); else - fprintf(c_fp, "\tsend_%s(p, false, type.%s);\n", &tokens[0][1], tokens[1]); + fprintf(c_fp, "\tsend_%s(p, false, type->%s);\n", &tokens[0][1], tokens[1]); free_split(tokens, tokens_len); tokens = NULL; @@ -633,26 +561,38 @@ int main(__attribute((unused)) int argc, __attribute((unused)) char **argv) for (size_t i = 0; i < msgs_len; ++i) { if (msgs[i][0] != '\t') { if (msg != NULL) { - fprintf(c_fp, "\treturn type;\n"); fprintf(c_fp, "}\n\n"); } msg = msgs[i]; - fprintf(h_fp, "%s dragonnet_peer_recv_%s(DragonnetPeer *p);\n", msg, msg); - fprintf(c_fp, "%s dragonnet_peer_recv_%s(DragonnetPeer *p)\n{\n", msg, msg); - fprintf(c_fp, "\t%s type = {0};\n", msg); + fprintf(c_fp, "static void dragonnet_peer_recv_%s(DragonnetPeer *p, void *buf)\n{\n", msg); + fprintf(c_fp, "\t%s *type = (%s *) buf;\n", msg, msg); } else { char **tokens; size_t tokens_len = split(&tokens, msgs[i], " "); - fprintf(c_fp, "\ttype.%s = recv_%s(p);\n", tokens[1], &tokens[0][1]); + char type[strlen(&tokens[0][1])]; + strcpy(type, &tokens[0][1]); + + for (size_t bits = 8; bits <= 64; bits *= 2) { + const char *fmt[] = {"u%d", "s%d", "f%d"}; + for (size_t j = 0; j < sizeof fmt / sizeof *fmt; ++j) { + char *cmp; + asprintf(&cmp, fmt[j], bits); + + if (strcmp(type, cmp) == 0) + sprintf(type, "n%ld", bits); + + free(cmp); + } + } + + fprintf(c_fp, "\trecv_%s(p, &type->%s);\n", type, tokens[1]); free_split(tokens, tokens_len); tokens = NULL; } } - fprintf(h_fp, "\n"); - fprintf(c_fp, "\treturn type;\n"); fprintf(c_fp, "}\n"); msg = NULL; @@ -701,15 +641,10 @@ int main(__attribute((unused)) int argc, __attribute((unused)) char **argv) fprintf(h_fp, "\n"); fprintf(c_fp, "\treturn type;\n"); - fprintf(c_fp, "}\n"); + fprintf(c_fp, "}\n\n"); msg = NULL; // Create type enum - size_t last_msg = 0; - for (size_t i = 0; i < msgs_len; ++i) - if (msgs[i][0] != '\t') - last_msg = i; - fprintf(h_fp, "typedef enum {\n"); for (size_t i = 0; i < msgs_len; ++i) { if (msgs[i][0] == '\t') @@ -722,13 +657,27 @@ int main(__attribute((unused)) int argc, __attribute((unused)) char **argv) while ((*ptr = *ptr ? toupper(*ptr) : '\0')) ++ptr; - if (i == last_msg) - fprintf(h_fp, "\tDRAGONNET_TYPE_%s\n", upper); - else - fprintf(h_fp, "\tDRAGONNET_TYPE_%s,\n", upper); + fprintf(h_fp, "\tDRAGONNET_TYPE_%s,\n", upper); + } + + fprintf(h_fp, "\tDRAGONNET_NUM_TYPES\n"); + fprintf(h_fp, "} DragonnetTypeNum;\n"); + + // ABI + fprintf(c_fp, "u16 dragonnet_num_types = DRAGONNET_NUM_TYPES;\n"); + fprintf(c_fp, "DragonnetType dragonnet_types[] = {\n"); + + for (size_t i = 0; i < msgs_len; ++i) { + if (msgs[i][0] == '\t') + continue; + + fprintf(c_fp, "\t{\n"); + fprintf(c_fp, "\t\t.siz = sizeof(%s),\n", msgs[i]); + fprintf(c_fp, "\t\t.deserialize = &dragonnet_peer_recv_%s\n", msgs[i]); + fprintf(c_fp, "\t},\n"); } - fprintf(h_fp, "} DragonnetType;\n"); + fprintf(c_fp, "};\n"); free_split(msgs, msgs_len); msgs = NULL; -- 2.44.0