From: Elias Fleckenstein Date: Mon, 25 Apr 2022 10:12:32 +0000 (+0200) Subject: Add CMake config X-Git-Url: https://git.lizzy.rs/?a=commitdiff_plain;h=72fd472f45d9589269d7786877dff8d45586c006;p=dragonnet.git Add CMake config --- diff --git a/.gitignore b/.gitignore index c6127b3..5a5f2d0 100644 --- a/.gitignore +++ b/.gitignore @@ -1,52 +1,12 @@ -# Prerequisites -*.d - -# Object files -*.o -*.ko -*.obj -*.elf - -# Linker output -*.ilk -*.map -*.exp - -# Precompiled Headers -*.gch -*.pch - -# Libraries -*.lib +CMakeLists.txt.user +CMakeCache.txt +CMakeFiles +CMakeScripts +Testing +Makefile +cmake_install.cmake +install_manifest.txt +compile_commands.json +CTestTestfile.cmake +_deps *.a -*.la -*.lo - -# Shared objects (inc. Windows DLLs) -*.dll -*.so -*.so.* -*.dylib - -# Executables -*.exe -*.out -*.app -*.i*86 -*.x86_64 -*.hex - -# Debug files -*.dSYM/ -*.su -*.idb -*.pdb - -# Kernel Module Compile Results -*.mod* -*.cmd -.tmp_versions/ -modules.order -Module.symvers -Mkfile.old -dkms.conf diff --git a/.gitmodules b/.gitmodules new file mode 100644 index 0000000..e626dc6 --- /dev/null +++ b/.gitmodules @@ -0,0 +1,3 @@ +[submodule "endian.h"] + path = endian.h + url = https://github.com/dragonblocks/endian.h diff --git a/CMakeLists.txt b/CMakeLists.txt new file mode 100644 index 0000000..9690a50 --- /dev/null +++ b/CMakeLists.txt @@ -0,0 +1,32 @@ +cmake_minimum_required(VERSION 3.14) +project(Dragonnet) + +add_compile_options( + -Wall + -Wextra + -Werror +) + +add_library(dragonnet + dragonnet/addr.c + dragonnet/listen.c + dragonnet/peer.c + dragonnet/recv.c + dragonnet/recv_thread.c + dragonnet/send.c +) + +target_link_libraries(dragonnet + pthread +) + +target_include_directories(dragonnet + PUBLIC "${CMAKE_CURRENT_SOURCE_DIR}" + PRIVATE "${CMAKE_CURRENT_SOURCE_DIR}/endian.h" +) + +if("${CMAKE_SYSTEM_NAME}" STREQUAL "Windows") + target_link_libraries(dragonnet + ws2_32 + ) +endif() diff --git a/addr.c b/addr.c deleted file mode 100644 index 04c4537..0000000 --- a/addr.c +++ /dev/null @@ -1,56 +0,0 @@ -#include -#include -#include -#include -#include - -struct addrinfo *dragonnet_str2addr(const char *str) -{ - const char *port = str + strlen(str) - 1; - while (port >= str && *port != ':') - port--; - port++; - - const char *host_begin = str; - if (*host_begin == '[') - host_begin++; - - const char *host_end = port - 2; - if (host_end >= str && *host_end == ']') - host_end--; - - ssize_t host_len = host_end - host_begin + 1; - if (host_len < 0) - host_len = 0; - - char host[host_len + 1]; - host[host_len] = '\0'; - memcpy(host, host_begin, host_len); - - struct addrinfo *result, hints = {0}; - hints.ai_family = AF_UNSPEC; - hints.ai_socktype = SOCK_STREAM; - - int err; - if ((err = getaddrinfo(host, port, &hints, &result))) { - fprintf(stderr, "getaddrinfo: %s\n", gai_strerror(err)); - return NULL; - } - - return result; -} - -char *dragonnet_addr2str(struct sockaddr *addr, socklen_t addr_len) -{ - char host[NI_MAXHOST], port[NI_MAXSERV]; - - int err; - if ((err = getnameinfo(addr, addr_len, host, NI_MAXHOST, port, NI_MAXSERV, NI_NUMERICHOST | NI_NUMERICSERV))) { - fprintf(stderr, "getnameinfo: %s\n", gai_strerror(err)); - return NULL; - } - - char str[1 + strlen(host) + 1 + 1 + strlen(port) + 1]; - sprintf(str, "[%s]:%s", host, port); - return strdup(str); -} diff --git a/addr.h b/addr.h deleted file mode 100644 index 2bc21cc..0000000 --- a/addr.h +++ /dev/null @@ -1,9 +0,0 @@ -#ifndef _DRAGONNET_ADDR_H_ -#define _DRAGONNET_ADDR_H_ - -#include "sock.h" - -struct addrinfo *dragonnet_str2addr(const char *str); -char *dragonnet_addr2str(struct sockaddr *addr, socklen_t addr_len); - -#endif diff --git a/dragonnet/addr.c b/dragonnet/addr.c new file mode 100644 index 0000000..e555f1b --- /dev/null +++ b/dragonnet/addr.c @@ -0,0 +1,56 @@ +#include +#include +#include +#include +#include "addr.h" + +struct addrinfo *dragonnet_str2addr(const char *str) +{ + const char *port = str + strlen(str) - 1; + while (port >= str && *port != ':') + port--; + port++; + + const char *host_begin = str; + if (*host_begin == '[') + host_begin++; + + const char *host_end = port - 2; + if (host_end >= str && *host_end == ']') + host_end--; + + ssize_t host_len = host_end - host_begin + 1; + if (host_len < 0) + host_len = 0; + + char host[host_len + 1]; + host[host_len] = '\0'; + memcpy(host, host_begin, host_len); + + struct addrinfo *result, hints = {0}; + hints.ai_family = AF_UNSPEC; + hints.ai_socktype = SOCK_STREAM; + + int err; + if ((err = getaddrinfo(host, port, &hints, &result))) { + fprintf(stderr, "getaddrinfo: %s\n", gai_strerror(err)); + return NULL; + } + + return result; +} + +char *dragonnet_addr2str(struct sockaddr *addr, socklen_t addr_len) +{ + char host[NI_MAXHOST], port[NI_MAXSERV]; + + int err; + if ((err = getnameinfo(addr, addr_len, host, NI_MAXHOST, port, NI_MAXSERV, NI_NUMERICHOST | NI_NUMERICSERV))) { + fprintf(stderr, "getnameinfo: %s\n", gai_strerror(err)); + return NULL; + } + + char str[1 + strlen(host) + 1 + 1 + strlen(port) + 1]; + sprintf(str, "[%s]:%s", host, port); + return strdup(str); +} diff --git a/dragonnet/addr.h b/dragonnet/addr.h new file mode 100644 index 0000000..2bc21cc --- /dev/null +++ b/dragonnet/addr.h @@ -0,0 +1,9 @@ +#ifndef _DRAGONNET_ADDR_H_ +#define _DRAGONNET_ADDR_H_ + +#include "sock.h" + +struct addrinfo *dragonnet_str2addr(const char *str); +char *dragonnet_addr2str(struct sockaddr *addr, socklen_t addr_len); + +#endif diff --git a/dragonnet/listen.c b/dragonnet/listen.c new file mode 100644 index 0000000..a42066f --- /dev/null +++ b/dragonnet/listen.c @@ -0,0 +1,144 @@ +#define _GNU_SOURCE +#include +#include +#include +#include +#include +#include "addr.h" +#include "listen.h" +#include "recv.h" +#include "sock.h" + +// ---- +// Peer +// ---- + +static bool dragonnet_peer_init_accepted(DragonnetPeer *p, int sock, + char *addr, DragonnetListener *l) +{ + pthread_mutex_init(&p->mtx, NULL); + + p->sock = sock; + p->address = addr; + p->on_disconnect = l->on_disconnect; + p->on_recv = l->on_recv; + p->on_recv_type = l->on_recv_type; + + return true; +} + +static DragonnetPeer *dragonnet_peer_accept(int sock, char *addr, + DragonnetListener *l) +{ + DragonnetPeer *p = malloc(sizeof *p); + if (!dragonnet_peer_init_accepted(p, sock, addr, l)) { + pthread_mutex_destroy(&p->mtx); + free(p); + free(addr); + return NULL; + } + + return p; +} + +// -------- +// Listener +// -------- + +DragonnetListener *dragonnet_listener_new(char *addr) +{ + struct addrinfo *info = dragonnet_str2addr(addr); + if (!info) + return NULL; + + DragonnetListener *l = malloc(sizeof *l); + + l->active = true; + l->sock = socket(info->ai_family, info->ai_socktype, info->ai_protocol); + l->address = dragonnet_addr2str(info->ai_addr, info->ai_addrlen); + l->on_connect = NULL; + l->on_disconnect = NULL; + l->on_recv = NULL; + 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, (void *) &so_reuseaddr, + sizeof so_reuseaddr) < 0) { + perror("setsockopt"); + freeaddrinfo(info); + dragonnet_listener_delete(l); + return NULL; + } + + if (bind(l->sock, info->ai_addr, info->ai_addrlen) < 0) { + perror("bind"); + freeaddrinfo(info); + dragonnet_listener_delete(l); + return NULL; + } + + freeaddrinfo(info); + + if (listen(l->sock, 10) < 0) { + perror("listen"); + dragonnet_listener_delete(l); + return NULL; + } + + return l; +} + +static void *listener_main(void *g_listener) +{ +#ifdef __GLIBC__ + pthread_setname_np(pthread_self(), "listen"); +#endif + + DragonnetListener *l = (DragonnetListener *) g_listener; + + while (l->active) { + struct sockaddr_storage clt_addr; + socklen_t clt_addrlen = sizeof clt_addr; + + int clt_sock = accept(l->sock, (struct sockaddr *) &clt_addr, &clt_addrlen); + if (clt_sock < 0) { + if (errno != EINTR) + perror("accept"); + continue; + } + + char *clt_addstr = dragonnet_addr2str((struct sockaddr *) &clt_addr, clt_addrlen); + DragonnetPeer *p = dragonnet_peer_accept(clt_sock, clt_addstr, l); + if (p == NULL) + continue; + + void (*on_connect)(DragonnetPeer *) = l->on_connect; + + if (on_connect != NULL) + on_connect(p); + + dragonnet_peer_run(p); + } + + return NULL; +} + +void dragonnet_listener_run(DragonnetListener *l) +{ + pthread_create(&l->accept_thread, NULL, &listener_main, l); +} + +void dragonnet_listener_close(DragonnetListener *l) +{ + l->active = false; + + pthread_kill(l->accept_thread, SIGINT); + pthread_join(l->accept_thread, NULL); +} + +void dragonnet_listener_delete(DragonnetListener *l) +{ + free(l->on_recv_type); + free(l->address); + free(l); +} diff --git a/dragonnet/listen.h b/dragonnet/listen.h new file mode 100644 index 0000000..03a2305 --- /dev/null +++ b/dragonnet/listen.h @@ -0,0 +1,25 @@ +#ifndef _DRAGONNET_LISTEN_H_ +#define _DRAGONNET_LISTEN_H_ + +#include +#include "peer.h" + +typedef struct { + int sock; + char *address; + + pthread_t accept_thread; + bool active; + + void (*on_connect)(DragonnetPeer *); + void (*on_disconnect)(DragonnetPeer *); + bool (*on_recv)(DragonnetPeer *, DragonnetTypeId, void *); + void (**on_recv_type)(DragonnetPeer *, void *); +} DragonnetListener; + +DragonnetListener *dragonnet_listener_new(char *addr); +void dragonnet_listener_run(DragonnetListener *l); +void dragonnet_listener_close(DragonnetListener *l); +void dragonnet_listener_delete(DragonnetListener *l); + +#endif diff --git a/dragonnet/peer.c b/dragonnet/peer.c new file mode 100644 index 0000000..f4c5685 --- /dev/null +++ b/dragonnet/peer.c @@ -0,0 +1,57 @@ +#include +#include +#include +#include +#include "addr.h" +#include "peer.h" +#include "recv.h" +#include "recv_thread.h" +#include "sock.h" + +static bool dragonnet_peer_init(DragonnetPeer *p, char *addr) +{ + pthread_mutex_init(&p->mtx, NULL); + + struct addrinfo *info = dragonnet_str2addr(addr); + if (!info) + return false; + + p->sock = socket(info->ai_family, info->ai_socktype, info->ai_protocol); + p->address = dragonnet_addr2str(info->ai_addr, info->ai_addrlen); + + if (connect(p->sock, info->ai_addr, info->ai_addrlen) < 0) { + freeaddrinfo(info); + perror("connect"); + return false; + } + + freeaddrinfo(info); + + p->on_disconnect = NULL; + p->on_recv = NULL; + p->on_recv_type = calloc(sizeof *p->on_recv_type, dragonnet_num_types); // fixme: memory leak + + return true; +} + +DragonnetPeer *dragonnet_connect(char *addr) +{ + DragonnetPeer *p = malloc(sizeof *p); + if (!dragonnet_peer_init(p, addr)) { + pthread_mutex_destroy(&p->mtx); + free(p); + return NULL; + } + + return p; +} + +void dragonnet_peer_run(DragonnetPeer *p) +{ + pthread_create(&p->recv_thread, NULL, &dragonnet_peer_recv_thread, p); +} + +void dragonnet_peer_shutdown(DragonnetPeer *p) +{ + shutdown(p->sock, SHUT_RDWR); +} diff --git a/dragonnet/peer.h b/dragonnet/peer.h new file mode 100644 index 0000000..ce6100b --- /dev/null +++ b/dragonnet/peer.h @@ -0,0 +1,28 @@ +#ifndef _DRAGONNET_PEER_H_ +#define _DRAGONNET_PEER_H_ + +#include +#include +#include + +typedef uint16_t DragonnetTypeId; + +typedef struct dragonnet_peer { + int sock; + char *address; + + pthread_t recv_thread; + pthread_mutex_t mtx; + + void (*on_disconnect)(struct dragonnet_peer *); + bool (*on_recv)(struct dragonnet_peer *, DragonnetTypeId, void *); + void (**on_recv_type)(struct dragonnet_peer *, void *); + + void *extra; +} DragonnetPeer; + +DragonnetPeer *dragonnet_connect(char *addr); +void dragonnet_peer_run(DragonnetPeer *p); +void dragonnet_peer_shutdown(DragonnetPeer *p); + +#endif diff --git a/dragonnet/recv.c b/dragonnet/recv.c new file mode 100644 index 0000000..ffad396 --- /dev/null +++ b/dragonnet/recv.c @@ -0,0 +1,20 @@ +#include +#include +#include +#include +#include "recv.h" +#include "sock.h" + +bool dragonnet_recv_raw(DragonnetPeer *p, void *buf, size_t n) +{ + if (n == 0) + return true; + + ssize_t len = recv(p->sock, buf, n, MSG_WAITALL); + if (len < 0) { + perror("recv"); + abort(); + } + + return len != 0; +} diff --git a/dragonnet/recv.h b/dragonnet/recv.h new file mode 100644 index 0000000..eae26d3 --- /dev/null +++ b/dragonnet/recv.h @@ -0,0 +1,17 @@ +#ifndef _DRAGONNET_RECV_H_ +#define _DRAGONNET_RECV_H_ + +#include "peer.h" + +typedef struct { + size_t siz; + bool (*deserialize)(DragonnetPeer *, void *); + void (*free)(void *); +} DragonnetType; + +extern DragonnetTypeId dragonnet_num_types; +extern DragonnetType dragonnet_types[]; + +bool dragonnet_recv_raw(DragonnetPeer *p, void *buf, size_t n); + +#endif diff --git a/dragonnet/recv_thread.c b/dragonnet/recv_thread.c new file mode 100644 index 0000000..48f02ef --- /dev/null +++ b/dragonnet/recv_thread.c @@ -0,0 +1,85 @@ +#define _GNU_SOURCE +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "peer.h" +#include "recv.h" +#include "recv_thread.h" +#include "sock.h" + +void *dragonnet_peer_recv_thread(void *g_peer) +{ +#ifdef __GLIBC__ + pthread_setname_np(pthread_self(), "recv"); +#endif + + DragonnetPeer *p = (DragonnetPeer *) g_peer; + + while (true) { + DragonnetTypeId type_id; + + bool reset = false; + + ssize_t len = recv(p->sock, (void *) &type_id, sizeof type_id, MSG_WAITALL); + if (len < 0) { + if (errno == ECONNRESET || errno == EPIPE || errno == ETIMEDOUT) { + reset = true; + } else { + perror("recv"); + abort(); + } + } + + // Connection closed + if (len == 0 || reset) { + if (p->on_disconnect) + p->on_disconnect(p); + + close(p->sock); + free(p->address); + + pthread_mutex_destroy(&p->mtx); + free(p); + return NULL; + } + + type_id = be16toh(type_id); + + if (type_id >= dragonnet_num_types) { + fprintf(stderr, "[warning] received invalid type id %d\n", type_id); + continue; + } + + DragonnetType type = dragonnet_types[type_id]; + + unsigned char buf[type.siz]; + memset(buf, 0, type.siz); + + if (!type.deserialize(p, buf)) { + if (type.free != NULL) + type.free(buf); + + fprintf(stderr, "[warning] failed to deserialize package of type %d\n", type_id); + + continue; + } + + bool (*on_recv)(struct dragonnet_peer *, DragonnetTypeId, void *) = p->on_recv; + void (*on_recv_type)(DragonnetPeer *, void *) = p->on_recv_type[type_id]; + + if (on_recv != NULL && !on_recv(p, type_id, buf)) + on_recv_type = NULL; + + if (on_recv_type != NULL) + on_recv_type(p, buf); + + if (type.free != NULL) + type.free(buf); + } +} diff --git a/dragonnet/recv_thread.h b/dragonnet/recv_thread.h new file mode 100644 index 0000000..ea847ba --- /dev/null +++ b/dragonnet/recv_thread.h @@ -0,0 +1,6 @@ +#ifndef _DRAGONNET_RECV_THREAD_H_ +#define _DRAGONNET_RECV_THREAD_H + +void *dragonnet_peer_recv_thread(void *g_peer); + +#endif diff --git a/dragonnet/send.c b/dragonnet/send.c new file mode 100644 index 0000000..2305ff1 --- /dev/null +++ b/dragonnet/send.c @@ -0,0 +1,27 @@ +#include +#include +#include +#include +#include "send.h" +#include "sock.h" + +bool dragonnet_send_raw(DragonnetPeer *p, bool submit, const void *buf, size_t n) +{ + ssize_t len = send(p->sock, buf, n, MSG_NOSIGNAL | (submit ? 0 : MSG_MORE)); + + if (len < 0) { + if (errno == ECONNRESET || errno == EPIPE || errno == ETIMEDOUT) { + shutdown(p->sock, SHUT_RDWR); + pthread_mutex_unlock(&p->mtx); + return false; + } + + perror("send"); + abort(); + } + + if (submit) + pthread_mutex_unlock(&p->mtx); + + return true; +} diff --git a/dragonnet/send.h b/dragonnet/send.h new file mode 100644 index 0000000..c07f4b4 --- /dev/null +++ b/dragonnet/send.h @@ -0,0 +1,9 @@ +#ifndef _DRAGONNET_SEND_H_ +#define _DRAGONNET_SEND_H_ + +#include +#include "peer.h" + +bool dragonnet_send_raw(DragonnetPeer *p, bool submit, const void *buf, size_t n); + +#endif diff --git a/dragonnet/sock.h b/dragonnet/sock.h new file mode 100644 index 0000000..de1eb91 --- /dev/null +++ b/dragonnet/sock.h @@ -0,0 +1,17 @@ +#ifdef _WIN32 +#include +#include +#include +#include +#include +#include +#define SHUT_RDWR SD_BOTH +#define MSG_NOSIGNAL 0 +#define MSG_MORE 0 +#else +#include +#include +#include +#include +#include +#endif diff --git a/endian.h b/endian.h new file mode 160000 index 0000000..f24960e --- /dev/null +++ b/endian.h @@ -0,0 +1 @@ +Subproject commit f24960eca3bb806fa72d8de2b9a761a889fdeee3 diff --git a/listen.c b/listen.c deleted file mode 100644 index f8f212b..0000000 --- a/listen.c +++ /dev/null @@ -1,144 +0,0 @@ -#define _GNU_SOURCE -#include -#include -#include -#include -#include -#include -#include -#include -#include "sock.h" - -// ---- -// Peer -// ---- - -static bool dragonnet_peer_init_accepted(DragonnetPeer *p, int sock, - char *addr, DragonnetListener *l) -{ - pthread_mutex_init(&p->mtx, NULL); - - p->sock = sock; - p->address = addr; - p->on_disconnect = l->on_disconnect; - p->on_recv = l->on_recv; - p->on_recv_type = l->on_recv_type; - - return true; -} - -static DragonnetPeer *dragonnet_peer_accept(int sock, char *addr, - DragonnetListener *l) -{ - DragonnetPeer *p = malloc(sizeof *p); - if (!dragonnet_peer_init_accepted(p, sock, addr, l)) { - pthread_mutex_destroy(&p->mtx); - free(p); - free(addr); - return NULL; - } - - return p; -} - -// -------- -// Listener -// -------- - -DragonnetListener *dragonnet_listener_new(char *addr) -{ - struct addrinfo *info = dragonnet_str2addr(addr); - if (!info) - return NULL; - - DragonnetListener *l = malloc(sizeof *l); - - l->active = true; - l->sock = socket(info->ai_family, info->ai_socktype, info->ai_protocol); - l->address = dragonnet_addr2str(info->ai_addr, info->ai_addrlen); - l->on_connect = NULL; - l->on_disconnect = NULL; - l->on_recv = NULL; - 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, (void *) &so_reuseaddr, - sizeof so_reuseaddr) < 0) { - perror("setsockopt"); - freeaddrinfo(info); - dragonnet_listener_delete(l); - return NULL; - } - - if (bind(l->sock, info->ai_addr, info->ai_addrlen) < 0) { - perror("bind"); - freeaddrinfo(info); - dragonnet_listener_delete(l); - return NULL; - } - - freeaddrinfo(info); - - if (listen(l->sock, 10) < 0) { - perror("listen"); - dragonnet_listener_delete(l); - return NULL; - } - - return l; -} - -static void *listener_main(void *g_listener) -{ -#ifdef __GLIBC__ - pthread_setname_np(pthread_self(), "listen"); -#endif - - DragonnetListener *l = (DragonnetListener *) g_listener; - - while (l->active) { - struct sockaddr_storage clt_addr; - socklen_t clt_addrlen = sizeof clt_addr; - - int clt_sock = accept(l->sock, (struct sockaddr *) &clt_addr, &clt_addrlen); - if (clt_sock < 0) { - if (errno != EINTR) - perror("accept"); - continue; - } - - char *clt_addstr = dragonnet_addr2str((struct sockaddr *) &clt_addr, clt_addrlen); - DragonnetPeer *p = dragonnet_peer_accept(clt_sock, clt_addstr, l); - if (p == NULL) - continue; - - void (*on_connect)(DragonnetPeer *) = l->on_connect; - - if (on_connect != NULL) - on_connect(p); - - dragonnet_peer_run(p); - } - - return NULL; -} - -void dragonnet_listener_run(DragonnetListener *l) -{ - pthread_create(&l->accept_thread, NULL, &listener_main, l); -} - -void dragonnet_listener_close(DragonnetListener *l) -{ - l->active = false; - - pthread_kill(l->accept_thread, SIGINT); - pthread_join(l->accept_thread, NULL); -} - -void dragonnet_listener_delete(DragonnetListener *l) -{ - free(l->on_recv_type); - free(l->address); - free(l); -} diff --git a/listen.h b/listen.h deleted file mode 100644 index 6d31eaa..0000000 --- a/listen.h +++ /dev/null @@ -1,25 +0,0 @@ -#ifndef _DRAGONNET_LISTEN_H_ -#define _DRAGONNET_LISTEN_H_ - -#include -#include - -typedef struct { - int sock; - char *address; - - pthread_t accept_thread; - bool active; - - void (*on_connect)(DragonnetPeer *); - void (*on_disconnect)(DragonnetPeer *); - bool (*on_recv)(DragonnetPeer *, DragonnetTypeId, void *); - void (**on_recv_type)(DragonnetPeer *, void *); -} DragonnetListener; - -DragonnetListener *dragonnet_listener_new(char *addr); -void dragonnet_listener_run(DragonnetListener *l); -void dragonnet_listener_close(DragonnetListener *l); -void dragonnet_listener_delete(DragonnetListener *l); - -#endif diff --git a/peer.c b/peer.c deleted file mode 100644 index 7c5ce29..0000000 --- a/peer.c +++ /dev/null @@ -1,57 +0,0 @@ -#include -#include -#include -#include -#include -#include -#include -#include -#include "sock.h" - -static bool dragonnet_peer_init(DragonnetPeer *p, char *addr) -{ - pthread_mutex_init(&p->mtx, NULL); - - struct addrinfo *info = dragonnet_str2addr(addr); - if (!info) - return false; - - p->sock = socket(info->ai_family, info->ai_socktype, info->ai_protocol); - p->address = dragonnet_addr2str(info->ai_addr, info->ai_addrlen); - - if (connect(p->sock, info->ai_addr, info->ai_addrlen) < 0) { - freeaddrinfo(info); - perror("connect"); - return false; - } - - freeaddrinfo(info); - - p->on_disconnect = NULL; - p->on_recv = NULL; - p->on_recv_type = calloc(sizeof *p->on_recv_type, dragonnet_num_types); // fixme: memory leak - - return true; -} - -DragonnetPeer *dragonnet_connect(char *addr) -{ - DragonnetPeer *p = malloc(sizeof *p); - if (!dragonnet_peer_init(p, addr)) { - pthread_mutex_destroy(&p->mtx); - free(p); - return NULL; - } - - return p; -} - -void dragonnet_peer_run(DragonnetPeer *p) -{ - pthread_create(&p->recv_thread, NULL, &dragonnet_peer_recv_thread, p); -} - -void dragonnet_peer_shutdown(DragonnetPeer *p) -{ - shutdown(p->sock, SHUT_RDWR); -} diff --git a/peer.h b/peer.h deleted file mode 100644 index ce6100b..0000000 --- a/peer.h +++ /dev/null @@ -1,28 +0,0 @@ -#ifndef _DRAGONNET_PEER_H_ -#define _DRAGONNET_PEER_H_ - -#include -#include -#include - -typedef uint16_t DragonnetTypeId; - -typedef struct dragonnet_peer { - int sock; - char *address; - - pthread_t recv_thread; - pthread_mutex_t mtx; - - void (*on_disconnect)(struct dragonnet_peer *); - bool (*on_recv)(struct dragonnet_peer *, DragonnetTypeId, void *); - void (**on_recv_type)(struct dragonnet_peer *, void *); - - void *extra; -} DragonnetPeer; - -DragonnetPeer *dragonnet_connect(char *addr); -void dragonnet_peer_run(DragonnetPeer *p); -void dragonnet_peer_shutdown(DragonnetPeer *p); - -#endif diff --git a/recv.c b/recv.c deleted file mode 100644 index 7a2dfbe..0000000 --- a/recv.c +++ /dev/null @@ -1,20 +0,0 @@ -#include -#include -#include -#include -#include -#include "sock.h" - -bool dragonnet_recv_raw(DragonnetPeer *p, void *buf, size_t n) -{ - if (n == 0) - return true; - - ssize_t len = recv(p->sock, buf, n, MSG_WAITALL); - if (len < 0) { - perror("recv"); - abort(); - } - - return len != 0; -} diff --git a/recv.h b/recv.h deleted file mode 100644 index adb39aa..0000000 --- a/recv.h +++ /dev/null @@ -1,17 +0,0 @@ -#ifndef _DRAGONNET_RECV_H_ -#define _DRAGONNET_RECV_H_ - -#include - -typedef struct { - size_t siz; - bool (*deserialize)(DragonnetPeer *, void *); - void (*free)(void *); -} DragonnetType; - -extern DragonnetTypeId dragonnet_num_types; -extern DragonnetType dragonnet_types[]; - -bool dragonnet_recv_raw(DragonnetPeer *p, void *buf, size_t n); - -#endif diff --git a/recv_thread.c b/recv_thread.c deleted file mode 100644 index 578c4e8..0000000 --- a/recv_thread.c +++ /dev/null @@ -1,85 +0,0 @@ -#define _GNU_SOURCE -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include "sock.h" - -void *dragonnet_peer_recv_thread(void *g_peer) -{ -#ifdef __GLIBC__ - pthread_setname_np(pthread_self(), "recv"); -#endif - - DragonnetPeer *p = (DragonnetPeer *) g_peer; - - while (true) { - DragonnetTypeId type_id; - - bool reset = false; - - ssize_t len = recv(p->sock, (void *) &type_id, sizeof type_id, MSG_WAITALL); - if (len < 0) { - if (errno == ECONNRESET || errno == EPIPE || errno == ETIMEDOUT) { - reset = true; - } else { - perror("recv"); - abort(); - } - } - - // Connection closed - if (len == 0 || reset) { - if (p->on_disconnect) - p->on_disconnect(p); - - close(p->sock); - free(p->address); - - pthread_mutex_destroy(&p->mtx); - free(p); - return NULL; - } - - type_id = be16toh(type_id); - - if (type_id >= dragonnet_num_types) { - fprintf(stderr, "[warning] received invalid type id %d\n", type_id); - continue; - } - - DragonnetType type = dragonnet_types[type_id]; - - unsigned char buf[type.siz]; - memset(buf, 0, type.siz); - - if (!type.deserialize(p, buf)) { - if (type.free != NULL) - type.free(buf); - - fprintf(stderr, "[warning] failed to deserialize package of type %d\n", type_id); - - continue; - } - - bool (*on_recv)(struct dragonnet_peer *, DragonnetTypeId, void *) = p->on_recv; - void (*on_recv_type)(DragonnetPeer *, void *) = p->on_recv_type[type_id]; - - if (on_recv != NULL && !on_recv(p, type_id, buf)) - on_recv_type = NULL; - - if (on_recv_type != NULL) - on_recv_type(p, buf); - - if (type.free != NULL) - type.free(buf); - } -} diff --git a/recv_thread.h b/recv_thread.h deleted file mode 100644 index ea847ba..0000000 --- a/recv_thread.h +++ /dev/null @@ -1,6 +0,0 @@ -#ifndef _DRAGONNET_RECV_THREAD_H_ -#define _DRAGONNET_RECV_THREAD_H - -void *dragonnet_peer_recv_thread(void *g_peer); - -#endif diff --git a/send.c b/send.c deleted file mode 100644 index caeb7c8..0000000 --- a/send.c +++ /dev/null @@ -1,27 +0,0 @@ -#include -#include -#include -#include -#include -#include "sock.h" - -bool dragonnet_send_raw(DragonnetPeer *p, bool submit, const void *buf, size_t n) -{ - ssize_t len = send(p->sock, buf, n, MSG_NOSIGNAL | (submit ? 0 : MSG_MORE)); - - if (len < 0) { - if (errno == ECONNRESET || errno == EPIPE || errno == ETIMEDOUT) { - shutdown(p->sock, SHUT_RDWR); - pthread_mutex_unlock(&p->mtx); - return false; - } - - perror("send"); - abort(); - } - - if (submit) - pthread_mutex_unlock(&p->mtx); - - return true; -} diff --git a/send.h b/send.h deleted file mode 100644 index 206a198..0000000 --- a/send.h +++ /dev/null @@ -1,9 +0,0 @@ -#ifndef _DRAGONNET_SEND_H_ -#define _DRAGONNET_SEND_H_ - -#include -#include - -bool dragonnet_send_raw(DragonnetPeer *p, bool submit, const void *buf, size_t n); - -#endif diff --git a/sock.h b/sock.h deleted file mode 100644 index de1eb91..0000000 --- a/sock.h +++ /dev/null @@ -1,17 +0,0 @@ -#ifdef _WIN32 -#include -#include -#include -#include -#include -#include -#define SHUT_RDWR SD_BOTH -#define MSG_NOSIGNAL 0 -#define MSG_MORE 0 -#else -#include -#include -#include -#include -#include -#endif