]> git.lizzy.rs Git - dragonnet.git/commitdiff
Bug fixes (mainly threading)
authorHimbeerserverDE <himbeerserverde@gmail.com>
Fri, 8 Oct 2021 18:08:52 +0000 (20:08 +0200)
committerHimbeerserverDE <himbeerserverde@gmail.com>
Fri, 8 Oct 2021 18:08:52 +0000 (20:08 +0200)
addr.c
listen.c
listen.h
peer.c
peer.h
recv_thread.c
typegen/main.c

diff --git a/addr.c b/addr.c
index d675674150a9b6e84fccb20e30b0cbbc4a16edb1..29765ddecbcdea877b86f930aa1abb2dd785a5a9 100644 (file)
--- a/addr.c
+++ b/addr.c
@@ -18,11 +18,12 @@ DragonnetAddr dragonnet_addr_parse_str(char *str)
                }
        }
 
+       size_t ip_addr_i = 0, port_i = 0;
        for (size_t i = 0; i < strlen(str); ++i) {
-               if (i < colon_i)
-                       addr.ip[i] = str[i];
+               if (i < colon_i && str[i] != '[' && str[i] != ']')
+                       addr.ip[ip_addr_i++] = str[i];
                else if (i > colon_i)
-                       addr.port[i-colon_i-1] = str[i];
+                       addr.port[port_i++] = str[i];
        }
 
        return addr;
index 4a819a791e8e37197ad1612ab2231bb4d6b13eb5..a4b19bf94d924168dc4408014f38aea031253487 100644 (file)
--- a/listen.c
+++ b/listen.c
@@ -17,9 +17,12 @@ static bool dragonnet_peer_init_accepted(DragonnetPeer *p, int sock,
        pthread_rwlock_init(&p->mu, NULL);
        pthread_rwlock_wrlock(&p->mu);
 
+       pthread_rwlock_rdlock(&l->mu);
        p->sock = sock;
        p->laddr = l->laddr;
        p->raddr = dragonnet_addr_parse_sock(addr);
+       p->on_recv_type = l->on_recv_type;
+       pthread_rwlock_unlock(&l->mu);
 
        pthread_rwlock_unlock(&p->mu);
        return true;
@@ -42,7 +45,8 @@ static DragonnetPeer *dragonnet_peer_accept(int sock, struct sockaddr_in6 addr,
 // --------
 
 DragonnetListener *dragonnet_listener_new(char *addr,
-               void (*on_connect)(DragonnetPeer *p))
+               void (*on_connect)(DragonnetPeer *p),
+               void (*on_recv_type)(struct dragonnet_peer *, u16))
 {
        DragonnetListener *l = malloc(sizeof *l);
        pthread_rwlock_init(&l->mu, NULL);
@@ -50,6 +54,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;
 
        int so_reuseaddr = 1;
        if (setsockopt(l->sock, SOL_SOCKET, SO_REUSEADDR, &so_reuseaddr,
@@ -78,20 +83,24 @@ DragonnetListener *dragonnet_listener_new(char *addr,
        return l;
 }
 
-void dragonnet_listener_run(DragonnetListener *l)
+static void *listener_main(void *g_listener)
 {
-       pthread_rwlock_wrlock(&l->mu);
+       DragonnetListener *l = (DragonnetListener *) g_listener;
 
+       pthread_rwlock_wrlock(&l->mu);
        assert(l->state == DRAGONNET_LISTENER_CREATED);
        l->state++;
-
        pthread_rwlock_unlock(&l->mu);
 
        while (l->state == DRAGONNET_LISTENER_ACTIVE) {
                struct sockaddr_in6 clt_addr;
                socklen_t clt_addrlen = sizeof clt_addr;
 
-               int clt_sock = accept(l->sock, (struct sockaddr *) &clt_addr, &clt_addrlen);
+               pthread_rwlock_rdlock(&l->mu);
+               int sock = l->sock;
+               pthread_rwlock_unlock(&l->mu);
+
+               int clt_sock = accept(sock, (struct sockaddr *) &clt_addr, &clt_addrlen);
                if (clt_sock < 0) {
                        perror("accept");
                        continue;
@@ -101,21 +110,38 @@ void dragonnet_listener_run(DragonnetListener *l)
                if (p == NULL)
                        continue;
 
-               if (l->on_connect != NULL)
-                       l->on_connect(p);
+               dragonnet_peer_run(p);
+
+               pthread_rwlock_rdlock(&l->mu);
+               void (*on_connect)(DragonnetPeer *) = l->on_connect;
+               pthread_rwlock_unlock(&l->mu);
+
+               if (on_connect != NULL)
+                       on_connect(p);
        }
+
+       return NULL;
+}
+
+void dragonnet_listener_run(DragonnetListener *l)
+{
+       pthread_create(&l->accept_thread, NULL, &listener_main, l);
 }
 
 void dragonnet_listener_close(DragonnetListener *l)
 {
        pthread_rwlock_wrlock(&l->mu);
 
+       pthread_t accept_thread = l->accept_thread;
        assert(l->state == DRAGONNET_LISTENER_ACTIVE);
        close(l->sock);
-       l->sock = 0;
+       l->sock = -1;
        l->state++;
 
        pthread_rwlock_unlock(&l->mu);
+
+       pthread_cancel(accept_thread);
+       pthread_join(accept_thread, NULL);
 }
 
 void dragonnet_listener_delete(DragonnetListener *l)
index e1d96a359afa0472f9d0ab4a0f750659330ec342..28c456234939b8239fc488524534db49c92839c3 100644 (file)
--- a/listen.h
+++ b/listen.h
@@ -14,14 +14,18 @@ typedef enum {
 typedef struct {
        int sock;
        DragonnetAddr laddr;
-       void (*on_connect)(DragonnetPeer *p);
        DragonnetListenerState state;
+       pthread_t accept_thread;
+
+       void (*on_connect)(DragonnetPeer *);
+       void (*on_recv_type)(struct dragonnet_peer *, u16);
 
        pthread_rwlock_t mu;
 } DragonnetListener;
 
 DragonnetListener *dragonnet_listener_new(char *addr,
-               void (*on_connect)(DragonnetPeer *p));
+               void (*on_connect)(DragonnetPeer *p),
+               void (*on_recv_type)(struct dragonnet_peer *, u16));
 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 d508f740866f04f605ba727bfd7095c56e615b38..a1bb39d76e861d198698849fabcd0a8c1c47f354 100644 (file)
--- a/peer.c
+++ b/peer.c
@@ -6,13 +6,14 @@
 #include "peer.h"
 #include "recv_thread.h"
 
-static bool dragonnet_peer_init(DragonnetPeer *p, char *addr)
+static bool dragonnet_peer_init(DragonnetPeer *p, char *addr, void (*on_recv_type)(struct dragonnet_peer *, u16))
 {
        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;
 
        struct sockaddr_in6 sock_addr = dragonnet_addr_sock(p->raddr);
        if (connect(p->sock, (const struct sockaddr *) &sock_addr,
@@ -35,10 +36,10 @@ static bool dragonnet_peer_init(DragonnetPeer *p, char *addr)
        return true;
 }
 
-DragonnetPeer *dragonnet_connect(char *addr)
+DragonnetPeer *dragonnet_connect(char *addr, void (*on_recv_type)(struct dragonnet_peer *, u16))
 {
        DragonnetPeer *p = malloc(sizeof *p);
-       if (!dragonnet_peer_init(p, addr)) {
+       if (!dragonnet_peer_init(p, addr, on_recv_type)) {
                dragonnet_peer_delete(p);
                return NULL;
        }
@@ -48,21 +49,25 @@ DragonnetPeer *dragonnet_connect(char *addr)
 
 void dragonnet_peer_run(DragonnetPeer *p)
 {
-       pthread_t recv_thread;
-       pthread_create(&recv_thread, NULL, &dragonnet_peer_recv_thread, p);
-       pthread_join(recv_thread, NULL);
+       pthread_rwlock_wrlock(&p->mu);
+       pthread_create(&p->recv_thread, NULL, &dragonnet_peer_recv_thread, p);
+       pthread_rwlock_unlock(&p->mu);
+
+       while (p->state < DRAGONNET_PEER_ACTIVE);
 }
 
 void dragonnet_peer_close(DragonnetPeer *p)
 {
        pthread_rwlock_wrlock(&p->mu);
 
-       if (p->state == DRAGONNET_PEER_ACTIVE) {
+       pthread_t recv_thread = p->recv_thread;
+       if (p->state == DRAGONNET_PEER_ACTIVE)
                shutdown(p->sock, SHUT_RDWR);
-               p->state++;
-       }
 
        pthread_rwlock_unlock(&p->mu);
+
+       pthread_cancel(recv_thread);
+       pthread_join(recv_thread, NULL);
 }
 
 void dragonnet_peer_delete(DragonnetPeer *p)
diff --git a/peer.h b/peer.h
index 80e5a9518a294546eab64928824df60349053447..16c02f9121e657e4145ff2147f031286040b3aca 100644 (file)
--- a/peer.h
+++ b/peer.h
@@ -2,6 +2,7 @@
 #define _DRAGONNET_PEER_H_
 
 #include <pthread.h>
+#include <dragontype/number.h>
 
 #include "addr.h"
 
@@ -11,15 +12,18 @@ typedef enum {
        DRAGONNET_PEER_CLOSED
 } DragonnetPeerState;
 
-typedef struct {
+typedef struct dragonnet_peer {
        int sock;
        DragonnetAddr laddr, raddr;
        DragonnetPeerState state;
+       pthread_t recv_thread;
+
+       void (*on_recv_type)(struct dragonnet_peer *, u16);
 
        pthread_rwlock_t mu;
 } DragonnetPeer;
 
-DragonnetPeer *dragonnet_connect(char *addr);
+DragonnetPeer *dragonnet_connect(char *addr, void (*on_recv_type)(struct dragonnet_peer *, u16));
 void dragonnet_peer_run(DragonnetPeer *p);
 void dragonnet_peer_close(DragonnetPeer *p);
 void dragonnet_peer_delete(DragonnetPeer *p);
index b50c5a393e73c6b89fb1af4dd26a7aa8f0fecc91..b4975fb315f0d799c930526ad73f87ac26d8aabb 100644 (file)
@@ -18,14 +18,14 @@ void *dragonnet_peer_recv_thread(void *g_peer)
        pthread_rwlock_unlock(&p->mu);
 
        while (true) {
-               u16 msg;
+               u16 type;
 
                // 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, &msg, sizeof msg, MSG_WAITALL);
+               ssize_t len = recv(sock, &type, sizeof type, MSG_WAITALL);
                if (len < 0) {
                        perror("recv");
                        dragonnet_peer_delete(p);
@@ -44,6 +44,13 @@ void *dragonnet_peer_recv_thread(void *g_peer)
                        return NULL;
                }
 
-               // Deserialization
+               type = be16toh(type);
+
+               pthread_rwlock_rdlock(&p->mu);
+               void (*on_recv_type)(struct dragonnet_peer *, u16) = p->on_recv_type;
+               pthread_rwlock_unlock(&p->mu);
+
+               if (on_recv_type != NULL)
+                       on_recv_type(p, type);
        }
 }
index e591a278ad98686dbd251734260fe1bdcf4c457e..acf9f73c58b32734bc93ae5fbd81f87a94e71036 100644 (file)
@@ -38,8 +38,8 @@ static void gen_serializers(FILE *c_fp, FILE *h_fp)
        fprintf(h_fp, "typedef struct {\n\tu32 siz;\n\tu8 *data;\n} Blob;\n\n");
 
        for (u8 bits = 8; bits <= 64; bits *= 2) {
-               char *fmt_u = "static void dragonnet_send_u%d(DragonnetPeer *p, bool submit, u%d v)\n";
-               char *fmt_s = "static void dragonnet_send_s%d(DragonnetPeer *p, bool submit, s%d v)\n";
+               char *fmt_u = "__attribute__((unused)) static void send_u%d(DragonnetPeer *p, bool submit, u%d v)\n";
+               char *fmt_s = "__attribute__((unused)) static void send_s%d(DragonnetPeer *p, bool submit, s%d v)\n";
 
                fprintf(c_fp, fmt_u, bits, bits);
                fprintf(c_fp, "{\n");
@@ -53,41 +53,44 @@ static void gen_serializers(FILE *c_fp, FILE *h_fp)
                fprintf(c_fp, "}\n\n");
 
                if (bits >= 32) {
-                       char *fmt_f = "static void dragonnet_send_f%d(DragonnetPeer *p, bool submit, f%d v)\n";
+                       char *fmt_f = "static void send_f%d(DragonnetPeer *p, bool submit, f%d v)\n";
 
                        fprintf(c_fp, fmt_f, bits, bits);
                        fprintf(c_fp, "{\n");
-                       fprintf(c_fp, "\tdragonnet_send_u%d(p, submit, (u%d) v);\n", bits, bits);
+                       fprintf(c_fp, "\tsend_u%d(p, submit, (u%d) v);\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 = "static void dragonnet_send_v%du%d(DragonnetPeer *p, bool submit, v%du%d v)\n";
-                       char *fmt_s = "static void dragonnet_send_v%ds%d(DragonnetPeer *p, bool submit, v%ds%d v)\n";
+                       char *fmt_u = "__attribute__((unused)) static void send_v%du%d(DragonnetPeer *p, bool submit, v%du%d v)\n";
+                       char *fmt_s = "__attribute__((unused)) static void send_v%ds%d(DragonnetPeer *p, bool submit, v%ds%d v)\n";
 
                        fprintf(c_fp, fmt_u, elems, bits, elems, bits);
                        fprintf(c_fp, "{\n");
+                       fprintf(c_fp, "\tu%d *ptr = &v.x;\n", bits);
                        fprintf(c_fp, "\tfor (u8 i = 0; i < %d; ++i) {\n", elems);
-                       fprintf(c_fp, "\t\tdragonnet_send_u%d(p, (i == %d-1) ? submit : false, v[i]);\n", bits, elems);
+                       fprintf(c_fp, "\t\tsend_u%d(p, (i == %d-1) ? submit : false, *ptr++);\n", bits, elems);
                        fprintf(c_fp, "\t}\n");
                        fprintf(c_fp, "}\n\n");
 
                        fprintf(c_fp, fmt_s, elems, bits, elems, bits);
                        fprintf(c_fp, "{\n");
+                       fprintf(c_fp, "\ts%d *ptr = &v.x;\n", bits);
                        fprintf(c_fp, "\tfor (u8 i = 0; i < %d; ++i) {\n", elems);
-                       fprintf(c_fp, "\t\tdragonnet_send_s%d(p, (i == %d-1) ? submit : false, v[i]);\n", bits, elems);
+                       fprintf(c_fp, "\t\tsend_s%d(p, (i == %d-1) ? submit : false, *ptr++);\n", bits, elems);
                        fprintf(c_fp, "\t}\n");
                        fprintf(c_fp, "}\n\n");
 
                        if (bits >= 32) {
-                               char *fmt_f = "static void dragonnet_send_v%df%d(DragonnetPeer *p, bool submit, v%df%d v)\n";
+                               char *fmt_f = "__attribute__((unused)) static void send_v%df%d(DragonnetPeer *p, bool submit, v%df%d v)\n";
 
                                fprintf(c_fp, fmt_f, elems, bits, elems, bits);
                                fprintf(c_fp, "{\n");
+                               fprintf(c_fp, "\tf%d *ptr = &v.x;\n", bits);
                                fprintf(c_fp, "\tfor (u8 i = 0; i < %d; ++i) {\n", elems);
-                               fprintf(c_fp, "\t\tdragonnet_send_s%d(p, (i == %d-1) ? submit : false, v[i]);\n", bits, elems);
+                               fprintf(c_fp, "\t\tsend_f%d(p, (i == %d-1) ? submit : false, *ptr++);\n", bits, elems);
                                fprintf(c_fp, "\t}\n");
                                fprintf(c_fp, "}\n\n");
                        }
@@ -96,44 +99,47 @@ static void gen_serializers(FILE *c_fp, FILE *h_fp)
 
        for (u8 elems = 2; elems <= 4; ++elems) {
                for (u8 bits = 8; bits <= 64; bits *= 2) {
-                       char *fmt_u = "static void dragonnet_send_aabb%du%d(DragonnetPeer *p, bool submit, aabb%du%d v)\n";
-                       char *fmt_s = "static void dragonnet_send_aabb%ds%d(DragonnetPeer *p, bool submit, aabb%ds%d v)\n";
+                       char *fmt_u = "__attribute__((unused)) static void send_aabb%du%d(DragonnetPeer *p, bool submit, aabb%du%d v)\n";
+                       char *fmt_s = "__attribute__((unused)) static void send_aabb%ds%d(DragonnetPeer *p, bool submit, aabb%ds%d v)\n";
 
                        fprintf(c_fp, fmt_u, elems, bits, elems, bits);
                        fprintf(c_fp, "{\n");
+                       fprintf(c_fp, "\tv%du%d *ptr = &v.min;\n", elems, bits);
                        fprintf(c_fp, "\tfor (u8 i = 0; i < 2; ++i) {\n");
-                       fprintf(c_fp, "\t\tdragonnet_send_v%du%d(p, (i == 1) ? submit : false, v[i]);\n", elems, bits);
+                       fprintf(c_fp, "\t\tsend_v%du%d(p, (i == 1) ? submit : false, *ptr++);\n", elems, bits);
                        fprintf(c_fp, "\t}\n");
                        fprintf(c_fp, "}\n\n");
 
                        fprintf(c_fp, fmt_s, elems, bits, elems, bits);
                        fprintf(c_fp, "{\n");
+                       fprintf(c_fp, "\tv%ds%d *ptr = &v.min;\n", elems, bits);
                        fprintf(c_fp, "\tfor (u8 i = 0; i < 2; ++i) {\n");
-                       fprintf(c_fp, "\t\tdragonnet_send_v%ds%d(p, (i == 1) ? submit : false, v[i]);\n", elems, bits);
+                       fprintf(c_fp, "\t\tsend_v%ds%d(p, (i == 1) ? submit : false, *ptr++);\n", elems, bits);
                        fprintf(c_fp, "\t}\n");
                        fprintf(c_fp, "}\n\n");
 
                        if (bits >= 32) {
-                               char *fmt_f = "static void dragonnet_send_aabb%df%d(DragonnetPeer *p, bool submit, aabb%df%d v);\n";
+                               char *fmt_f = "__attribute__((unused)) static void send_aabb%df%d(DragonnetPeer *p, bool submit, aabb%df%d v)\n";
 
                                fprintf(c_fp, fmt_f, elems, bits, elems, bits);
                                fprintf(c_fp, "{\n");
+                               fprintf(c_fp, "\tv%df%d *ptr = &v.min;\n", elems, bits);
                                fprintf(c_fp, "\tfor (u8 i = 0; i < 2; ++i) {\n");
-                               fprintf(c_fp, "\t\tdragonnet_send_v%df%d(p, (i == 1) ? submit : false, v[i]);\n", elems, bits);
+                               fprintf(c_fp, "\t\tsend_v%df%d(p, (i == 1) ? submit : false, *ptr++);\n", elems, bits);
                                fprintf(c_fp, "\t}\n");
                                fprintf(c_fp, "}\n\n");
                        }
                }
        }
 
-       fprintf(c_fp, "static void dragonnet_send_string(DragonnetPeer *p, bool submit, string v)\n");
+       fprintf(c_fp, "__attribute__((unused)) static void send_string(DragonnetPeer *p, bool submit, string v)\n");
        fprintf(c_fp, "{\n");
        fprintf(c_fp, "\tdragonnet_send_raw(p, submit, v, strlen(v));\n");
        fprintf(c_fp, "}\n\n");
 
-       fprintf(c_fp, "static void dragonnet_send_Blob(DragonnetPeer *p, bool submit, Blob *v)\n\n");
+       fprintf(c_fp, "__attribute__((unused)) static void send_Blob(DragonnetPeer *p, bool submit, Blob *v)\n\n");
        fprintf(c_fp, "{\n");
-       fprintf(c_fp, "\tdragonnet_send_u32(p, false, v->siz);\n");
+       fprintf(c_fp, "\tsend_u32(p, false, v->siz);\n");
        fprintf(c_fp, "\tdragonnet_send_raw(p, submit, v->data, v->siz);\n");
        fprintf(c_fp, "}\n\n");
 }
@@ -141,40 +147,42 @@ static void gen_serializers(FILE *c_fp, FILE *h_fp)
 static void gen_deserializers(FILE *c_fp)
 {
        for (u8 bits = 8; bits <= 64; bits *= 2) {
-               char *fmt_u = "static u%d dragonnet_recv_u%d(DragonnetPeer *p)\n";
-               char *fmt_s = "static s%d dragonnet_recv_s%d(DragonnetPeer *p)\n";
+               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";
 
                fprintf(c_fp, fmt_u, bits, bits);
                fprintf(c_fp, "{\n");
-               fprintf(c_fp, "\tu%d be = dragonnet_recv_raw(p, &be, sizeof be);\n", bits);
+               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) dragonnet_recv_u%d(p);\n", bits, bits);
+               fprintf(c_fp, "\treturn (s%d) recv_u%d(p);\n", bits, bits);
                fprintf(c_fp, "}\n\n");
 
                if (bits >= 32) {
-                       char *fmt_f = "static f%d dragonnet_recv_f%d(DragonnetPeer *p)\n";
+                       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) dragonnet_recv_u%d(p);\n", bits, bits);
+                       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 = "static v%du%d dragonnet_recv_v%du%d(DragonnetPeer *p)\n";
-                       char *fmt_s = "static v%ds%d dragonnet_recv_v%ds%d(DragonnetPeer *p)\n";
+                       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";
 
                        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\tv[i] = dragonnet_recv_u%d(p);\n", bits);
+                       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");
@@ -182,20 +190,22 @@ static void gen_deserializers(FILE *c_fp)
                        fprintf(c_fp, fmt_s, elems, bits, 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\tv[i] = dragonnet_recv_s%d(p);\n", bits);
+                       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, "}\n\n");
 
                        if (bits >= 32) {
-                               char *fmt_f = "static v%df%d dragonnet_recv_v%df%d(DragonnetPeer *p)\n";
+                               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\tv[i] = dragonnet_recv_f%d(p);\n", bits);
+                               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");
@@ -205,14 +215,15 @@ static void gen_deserializers(FILE *c_fp)
 
        for (u8 elems = 2; elems <= 4; ++elems) {
                for (u8 bits = 8; bits <= 64; bits *= 2) {
-                       char *fmt_u = "static aabb%du%d dragonnet_recv_aabb%du%d(DragonnetPeer *p)\n";
-                       char *fmt_s = "static aabb%ds%d dragonnet_recv_aabb%ds%d(DragonnetPeer *p)\n";
+                       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";
 
                        fprintf(c_fp, fmt_u, elems, bits, 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\tv[i] = dragonnet_recv_v%du%d(p);\n", elems, bits);
+                       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, "}\n\n");
@@ -220,20 +231,22 @@ static void gen_deserializers(FILE *c_fp)
                        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\tv[i] = dragonnet_recv_v%ds%d(p);\n", elems, bits);
+                       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 = "static aabb%df%d dragonnet_recv_aabb%df%d(DragonnetPeer *p)\n";
+                               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\tv[i] = dragonnet_recv_v%ds%d(p);\n", elems, bits);
+                               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");
@@ -241,22 +254,22 @@ static void gen_deserializers(FILE *c_fp)
                }
        }
 
-       fprintf(c_fp, "static string dragonnet_recv_string(DragonnetPeer *p)\n");
+       fprintf(c_fp, "__attribute__((unused)) static string recv_string(DragonnetPeer *p)\n");
        fprintf(c_fp, "{\n");
        fprintf(c_fp, "\tstring v = malloc(sizeof(u16));\n\n");
        fprintf(c_fp, "\tchar ch;\n");
        fprintf(c_fp, "\tfor (u16 i = 0; ch != '\\0'; ++i) {\n");
-       fprintf(c_fp, "\t\tch = dragonnet_recv_s8(p);\n");
+       fprintf(c_fp, "\t\tch = recv_s8(p);\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, "}\n\n");
 
-       fprintf(c_fp, "static Blob *dragonnet_recv_Blob(DragonnetPeer *p)\n\n");
+       fprintf(c_fp, "__attribute__((unused)) static Blob *recv_Blob(DragonnetPeer *p)\n\n");
        fprintf(c_fp, "{\n");
        fprintf(c_fp, "\tBlob *v = malloc(sizeof *v);\n");
-       fprintf(c_fp, "\tv->siz = dragonnet_recv_u32(p, false, v->siz);\n");
+       fprintf(c_fp, "\tv->siz = recv_u32(p);\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");
@@ -275,6 +288,8 @@ int main(__attribute((unused)) int argc, __attribute((unused)) char **argv)
        fp = NULL;
 
        FILE *c_fp = fopen("dnet-types.c", "w");
+       fprintf(c_fp, "#include <stdlib.h>\n");
+       fprintf(c_fp, "#include <string.h>\n");
        fprintf(c_fp, "#include <dragonnet/recv.h>\n");
        fprintf(c_fp, "#include <dragonnet/send.h>\n\n");
        fprintf(c_fp, "#include \"dnet-types.h\"\n\n");
@@ -319,12 +334,12 @@ int main(__attribute((unused)) int argc, __attribute((unused)) char **argv)
                                fprintf(c_fp, "}\n\n");
 
                        msg = msgs[i];
-                       fprintf(c_fp, "static void dragonnet_send_%s(DragonnetPeer *p, %s type)\n{\n", msg, msg);
+                       fprintf(c_fp, "__attribute__((unused)) static void send_%s(DragonnetPeer *p, %s type)\n{\n", msg, msg);
                } else {
                        char **tokens;
                        size_t tokens_len = split(&tokens, msgs[i], " ");
 
-                       fprintf(c_fp, "\tdragonnet_send_%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;
@@ -342,14 +357,23 @@ int main(__attribute((unused)) int argc, __attribute((unused)) char **argv)
                        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);
+
+                       char upper[1 + strlen(msgs[i])];
+                       char *ptr = upper;
+                       strcpy(upper, msg);
+
+                       while ((*ptr = *ptr ? toupper(*ptr) : '\0'))
+                               ++ptr;
+
+                       fprintf(c_fp, "\tsend_u16(p, false, DRAGONNET_TYPE_%s);\n", upper);
                } else {
                        char **tokens;
                        size_t tokens_len = split(&tokens, msgs[i], " ");
 
                        if (i >= msgs_len-1 || msgs[1+i][0] != '\t')
-                               fprintf(c_fp, "\tdragonnet_send_%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, "\tdragonnet_send_%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;
@@ -374,7 +398,7 @@ int main(__attribute((unused)) int argc, __attribute((unused)) char **argv)
                        char **tokens;
                        size_t tokens_len = split(&tokens, msgs[i], " ");
 
-                       fprintf(c_fp, "\ttype.%s = dragonnet_recv_%s(p);\n", tokens[1], &tokens[0][1]);
+                       fprintf(c_fp, "\ttype.%s = recv_%s(p);\n", tokens[1], &tokens[0][1]);
                        free_split(tokens, tokens_len);
                        tokens = NULL;
                }