libdiscord

libdiscord.git
git clone git://git.lenczewski.org/libdiscord.git
Log | Files | Refs | README | LICENSE

commit 6c4c23bef86201c766f832a25eb6a7abb867789c
parent 9369de7d8bbf430bbb8b6552e776c5898250bb69
Author: MikoĊ‚aj Lenczewski <mblenczewski@gmail.com>
Date:   Sat, 21 Jun 2025 14:26:12 +0100

Simplified source files

Diffstat:
Minclude/libdiscord.h | 3---
Dsrc/arena.c | 7-------
Dsrc/arena.h | 51---------------------------------------------------
Dsrc/conn.c | 33---------------------------------
Msrc/gateway.c | 57+++++++++++++++++++++++++++++++++++++++++++++++++--------
Msrc/internal.c | 105++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++---
Msrc/internal.h | 101+++++++++++++++++++++++++++++++++++++++++++++++++++----------------------------
Dsrc/ioreq.c | 69---------------------------------------------------------------------
Msrc/libdiscord.c | 44+++++++++++++-------------------------------
Dsrc/list.c | 23-----------------------
Dsrc/list.h | 99-------------------------------------------------------------------------------
Dsrc/stringview.c | 1-
Dsrc/stringview.h | 29-----------------------------
Msrc/utils.c | 38+++++++++++++++++++++++++++++++++++---
Msrc/utils.h | 177+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++--
Msrc/voice.c | 37++++++++++++++++++++++++++++++-------
16 files changed, 468 insertions(+), 406 deletions(-)

diff --git a/include/libdiscord.h b/include/libdiscord.h @@ -99,9 +99,6 @@ int discord_poll_events(struct discord *ctx, struct discord_event *evs, size_t cap); -void -discord_error(struct discord *ctx); - // discord api calls // ======================================================================== diff --git a/src/arena.c b/src/arena.c @@ -1,7 +0,0 @@ -#include "arena.h" - -extern inline void -arena_reset(struct arena *arena); - -extern inline void * -arena_alloc(struct arena *arena, size_t size, size_t alignment); diff --git a/src/arena.h b/src/arena.h @@ -1,51 +0,0 @@ -#ifndef ARENA_H -#define ARENA_H - -#include <assert.h> -#include <stdalign.h> -#include <stddef.h> -#include <stdint.h> - -#define IS_POW2(v) (((v) & ((v) - 1)) == 0) - -#define IS_ALIGNED(v, align) (((v) & ((align) - 1)) == 0) -#define ALIGN_PREV(v, align) ((v) & ~((align) - 1)) -#define ALIGN_NEXT(v, align) ALIGN_PREV((v) + ((align) - 1), (align)) - -struct arena { - void *ptr; - size_t cap, len; -}; - -inline void -arena_reset(struct arena *arena) -{ - arena->len = 0; -} - -inline void * -arena_alloc(struct arena *arena, size_t size, size_t alignment) -{ - assert(size); - assert(alignment); - assert(IS_POW2(alignment)); - - uintptr_t base = (uintptr_t) arena->ptr; - uintptr_t end = base + arena->cap; - - uintptr_t aligned_ptr = ALIGN_NEXT(base + arena->len, alignment); - if (end < aligned_ptr + size) - return NULL; - - arena->len = (aligned_ptr + size) - base; - - return (void *) aligned_ptr; -} - -#define ARENA_ALLOC_ARRAY(arena, T, n) \ - arena_alloc((arena), sizeof(T) * (n), alignof(T)) - -#define ARENA_ALLOC_SIZED(arena, T) \ - ARENA_ALLOC_ARRAY((arena), T, 1) - -#endif /* ARENA_H */ diff --git a/src/conn.c b/src/conn.c @@ -1,33 +0,0 @@ -#include "internal.h" - -extern inline int -conn_queue_connect(struct conn *conn, struct io_uring *uring); - -extern inline void -conn_finish_connect(struct conn *conn, int result); - -extern inline int -conn_queue_recv(struct conn *conn, struct io_uring *uring); - -extern inline void -conn_finish_recv(struct conn *conn, int result); - -extern inline int -conn_queue_send(struct conn *conn, struct io_uring *uring); - -extern inline void -conn_finish_send(struct conn *conn, int result); - -extern inline int -conn_queue_close(struct conn *conn, struct io_uring *uring); - -extern inline void -conn_finish_close(struct conn *conn, int result); - -extern inline int -conn_do_tls_handshake(struct conn *conn, struct io_uring *uring, - struct discord_event *ev); - -extern inline int -conn_handle_io(struct conn *conn, struct io_uring *uring, int result, - struct discord_event *ev); diff --git a/src/gateway.c b/src/gateway.c @@ -2,7 +2,25 @@ int gateway_connect(struct conn *conn, struct io_uring *uring, - struct discord_event *ev) + char const *host, char const *port) +{ + struct addrinfo hints = { + .ai_family = AF_UNSPEC, + .ai_socktype = SOCK_STREAM, + .ai_protocol = IPPROTO_TCP, + .ai_flags = AI_CANONNAME | AI_NUMERICSERV, + }, *addrinfo; + + if (getaddrinfo(host, port, &hints, &addrinfo)) + return -1; + + conn->addrinfo = conn->ai_ptr = addrinfo; + + return conn_queue_connect(conn, uring); +} + +int +gateway_on_connect(struct conn *conn, struct io_uring *uring) { if (conn->socket < 0 && !conn->ai_ptr->ai_next) { freeaddrinfo(conn->addrinfo); @@ -22,28 +40,51 @@ gateway_connect(struct conn *conn, struct io_uring *uring, freeaddrinfo(conn->addrinfo); - return conn_do_tls_handshake(conn, uring, ev); + return conn_do_tls_handshake(conn, uring); } int -gateway_tls_handshake(struct conn *conn, struct io_uring *uring, - struct discord_event *ev) +gateway_on_tls_handshake(struct conn *conn, struct io_uring *uring) { printf("discord: connected over tls\n"); + struct discord_gateway *gateway = + TO_PARENT_PTR(conn, struct discord_gateway, conn); + + gateway->state = GATEWAY_CONN; + gateway->http.foo = gateway->ws.foo = 0; + + return conn_queue_close(conn, uring); +} + +int +gateway_on_close(struct conn *conn, struct io_uring *uring) +{ return -1; } int -gateway_recv(struct conn *conn, struct io_uring *uring, - struct discord_event *ev) +gateway_recv(struct conn *conn, struct io_uring *uring) +{ + return conn_queue_recv(conn, uring); +} + +int +gateway_on_recv(struct conn *conn, struct io_uring *uring, + struct discord_event *ev) { return -1; } int -gateway_send(struct conn *conn, struct io_uring *uring, - struct discord_event *ev) +gateway_send(struct conn *conn, struct io_uring *uring) +{ + return conn_queue_send(conn, uring); +} + +int +gateway_on_send(struct conn *conn, struct io_uring *uring, + struct discord_event *ev) { return -1; } diff --git a/src/internal.c b/src/internal.c @@ -1,5 +1,102 @@ +#include "internal.h" + +int +queue_ioreqs(struct io_uring *uring, struct ioreq *reqs, size_t len) +{ + for (size_t i = 0; i < len; i++) { + struct ioreq *ioreq = &reqs[i]; + + struct io_uring_sqe *sqe = io_uring_get_sqe(uring); + if (!sqe) + return -1; + + switch (ioreq->type) { + case IOREQ_CONNECT: + io_uring_prep_connect(sqe, + ioreq->tag.connect.fd, + ioreq->tag.connect.addr, + ioreq->tag.connect.addrlen); + break; + + case IOREQ_RECV: + io_uring_prep_recv(sqe, + ioreq->tag.recv.fd, + ioreq->tag.recv.buf, + ioreq->tag.recv.len, + ioreq->tag.recv.flags); + break; + + case IOREQ_RECVFROM: +#if 0 + io_uring_prep_recvfrom(sqe, + ioreq->tag.recvfrom.fd, + ioreq->tag.recvfrom.buf, + ioreq->tag.recvfrom.len, + ioreq->tag.recvfrom.flags, + ioreq->tag.recvfrom.addr, + ioreq->tag.recvfrom.addrlen); +#endif + break; + + case IOREQ_SEND: + io_uring_prep_send(sqe, + ioreq->tag.send.fd, + ioreq->tag.recv.buf, + ioreq->tag.recv.len, + ioreq->tag.recv.flags); + break; + + case IOREQ_SENDTO: + io_uring_prep_sendto(sqe, + ioreq->tag.sendto.fd, + ioreq->tag.sendto.buf, + ioreq->tag.sendto.len, + ioreq->tag.sendto.flags, + ioreq->tag.sendto.addr, + ioreq->tag.sendto.addrlen); + break; + + case IOREQ_CLOSE: + io_uring_prep_close(sqe, + ioreq->tag.close.fd); + break; + } + + io_uring_sqe_set_data(sqe, ioreq); + } + + return 0; +} + +extern inline int +conn_queue_connect(struct conn *conn, struct io_uring *uring); + +extern inline void +conn_finish_connect(struct conn *conn, int result); + +extern inline int +conn_queue_recv(struct conn *conn, struct io_uring *uring); + +extern inline void +conn_finish_recv(struct conn *conn, int result); + +extern inline int +conn_queue_send(struct conn *conn, struct io_uring *uring); + +extern inline void +conn_finish_send(struct conn *conn, int result); + +extern inline int +conn_queue_close(struct conn *conn, struct io_uring *uring); + +extern inline void +conn_finish_close(struct conn *conn, int result); + +extern inline int +conn_do_tls_handshake(struct conn *conn, struct io_uring *uring); + +extern inline int +conn_do_io(struct conn *conn, struct io_uring *uring, int result, + struct discord_event *ev); + #include "utils.c" -#include "ioreq.c" -#include "conn.c" -#include "gateway.c" -#include "voice.c" diff --git a/src/internal.h b/src/internal.h @@ -2,6 +2,7 @@ #define INTERNAL_H #define _GNU_SOURCE 1 +#define _POSIX_SOURCE 1 #define _XOPEN_SOURCE 700 #include <unistd.h> @@ -90,17 +91,15 @@ int queue_ioreqs(struct io_uring *uring, struct ioreq *reqs, size_t len); struct conn_ops { - int (*connect)(struct conn *conn, struct io_uring *uring, - struct discord_event *ev); - - int (*tls_handshake)(struct conn *conn, struct io_uring *uring, - struct discord_event *ev); + int (*on_connect)(struct conn *conn, struct io_uring *uring); + int (*on_tls_handshake)(struct conn *conn, struct io_uring *uring); + int (*on_close)(struct conn *conn, struct io_uring *uring); - int (*recv)(struct conn *conn, struct io_uring *uring, - struct discord_event *ev); + int (*on_recv)(struct conn *conn, struct io_uring *uring, + struct discord_event *ev); - int (*send)(struct conn *conn, struct io_uring *uring, - struct discord_event *ev); + int (*on_send)(struct conn *conn, struct io_uring *uring, + struct discord_event *ev); }; struct conn { @@ -220,12 +219,11 @@ conn_finish_close(struct conn *conn, int result) } inline int -conn_do_tls_handshake(struct conn *conn, struct io_uring *uring, - struct discord_event *ev) +conn_do_tls_handshake(struct conn *conn, struct io_uring *uring) { int ret = SSL_do_handshake(conn->ssl); if (ret == 1) /* handshake completed */ - return conn->ops->tls_handshake(conn, uring, ev); + return conn->ops->on_tls_handshake(conn, uring); if (ret == 0) /* connection closed */ return -1; @@ -243,29 +241,29 @@ conn_do_tls_handshake(struct conn *conn, struct io_uring *uring, return conn_queue_recv(conn, uring); error: - fprintf(stderr, "discord: failed to complete tls handshake: %d\n", err); + fprintf(stderr, "discord: failed tls handshake: %d\n", err); ERR_print_errors_fp(stderr); return -1; } inline int -conn_handle_io(struct conn *conn, struct io_uring *uring, int result, - struct discord_event *ev) +conn_do_io(struct conn *conn, struct io_uring *uring, int result, + struct discord_event *ev) { switch (conn->ioreq.type) { case IOREQ_CONNECT: { conn_finish_connect(conn, result); - return conn->ops->connect(conn, uring, ev); + return conn->ops->on_connect(conn, uring); } break; case IOREQ_RECV: { conn_finish_recv(conn, result); if (!SSL_is_init_finished(conn->ssl)) - return conn_do_tls_handshake(conn, uring, ev); + return conn_do_tls_handshake(conn, uring); - return conn->ops->recv(conn, uring, ev); + return conn->ops->on_recv(conn, uring, ev); } break; case IOREQ_RECVFROM: { @@ -278,9 +276,9 @@ conn_handle_io(struct conn *conn, struct io_uring *uring, int result, conn_finish_send(conn, result); if (!SSL_is_init_finished(conn->ssl)) - return conn_do_tls_handshake(conn, uring, ev); + return conn_do_tls_handshake(conn, uring); - return conn->ops->send(conn, uring, ev); + return conn->ops->on_send(conn, uring, ev); } break; case IOREQ_SENDTO: { @@ -291,7 +289,8 @@ conn_handle_io(struct conn *conn, struct io_uring *uring, int result, case IOREQ_CLOSE: { conn_finish_close(conn, result); - return 0; + + return conn->ops->on_close(conn, uring); } break; } } @@ -302,6 +301,16 @@ conn_handle_io(struct conn *conn, struct io_uring *uring, int result, struct discord_gateway { struct conn conn; + enum { GATEWAY_CONN, GATEWAY_HTTP, GATEWAY_WS, } state; + + struct { + int foo; + } http; + + struct { + int foo; + } ws; + unsigned char buf[4096]; }; @@ -330,34 +339,56 @@ struct discord { int gateway_connect(struct conn *conn, struct io_uring *uring, - struct discord_event *ev); + char const *host, char const *port); + +int +gateway_on_connect(struct conn *conn, struct io_uring *uring); int -gateway_tls_handshake(struct conn *conn, struct io_uring *uring, - struct discord_event *ev); +gateway_on_tls_handshake(struct conn *conn, struct io_uring *uring); int -gateway_recv(struct conn *conn, struct io_uring *uring, - struct discord_event *ev); +gateway_on_close(struct conn *conn, struct io_uring *uring); int -gateway_send(struct conn *conn, struct io_uring *uring, - struct discord_event *ev); +gateway_recv(struct conn *conn, struct io_uring *uring); + +int +gateway_on_recv(struct conn *conn, struct io_uring *uring, + struct discord_event *ev); + +int +gateway_send(struct conn *conn, struct io_uring *uring); + +int +gateway_on_send(struct conn *conn, struct io_uring *uring, + struct discord_event *ev); int voice_connect(struct conn *conn, struct io_uring *uring, - struct discord_event *ev); + char const *host, char const *port); + +int +voice_on_connect(struct conn *conn, struct io_uring *uring); int -voice_tls_handshake(struct conn *conn, struct io_uring *uring, - struct discord_event *ev); +voice_on_tls_handshake(struct conn *conn, struct io_uring *uring); int -voice_recv(struct conn *conn, struct io_uring *uring, - struct discord_event *ev); +voice_on_close(struct conn *conn, struct io_uring *uring); int -voice_send(struct conn *conn, struct io_uring *uring, - struct discord_event *ev); +voice_recv(struct conn *conn, struct io_uring *uring); + +int +voice_on_recv(struct conn *conn, struct io_uring *uring, + struct discord_event *ev); + +int +voice_send(struct conn *conn, struct io_uring *uring); + +int +voice_on_send(struct conn *conn, struct io_uring *uring, + struct discord_event *ev); #endif /* INTERNAL_H */ diff --git a/src/ioreq.c b/src/ioreq.c @@ -1,69 +0,0 @@ -#include "internal.h" - -int -queue_ioreqs(struct io_uring *uring, struct ioreq *reqs, size_t len) -{ - for (size_t i = 0; i < len; i++) { - struct ioreq *ioreq = &reqs[i]; - - struct io_uring_sqe *sqe = io_uring_get_sqe(uring); - if (!sqe) - return -1; - - switch (ioreq->type) { - case IOREQ_CONNECT: - io_uring_prep_connect(sqe, - ioreq->tag.connect.fd, - ioreq->tag.connect.addr, - ioreq->tag.connect.addrlen); - break; - - case IOREQ_RECV: - io_uring_prep_recv(sqe, - ioreq->tag.recv.fd, - ioreq->tag.recv.buf, - ioreq->tag.recv.len, - ioreq->tag.recv.flags); - break; - - case IOREQ_RECVFROM: -#if 0 - io_uring_prep_recvfrom(sqe, - ioreq->tag.recvfrom.fd, - ioreq->tag.recvfrom.buf, - ioreq->tag.recvfrom.len, - ioreq->tag.recvfrom.flags, - ioreq->tag.recvfrom.addr, - ioreq->tag.recvfrom.addrlen); -#endif - break; - - case IOREQ_SEND: - io_uring_prep_send(sqe, - ioreq->tag.send.fd, - ioreq->tag.recv.buf, - ioreq->tag.recv.len, - ioreq->tag.recv.flags); - break; - - case IOREQ_SENDTO: - io_uring_prep_sendto(sqe, - ioreq->tag.sendto.fd, - ioreq->tag.sendto.buf, - ioreq->tag.sendto.len, - ioreq->tag.sendto.flags, - ioreq->tag.sendto.addr, - ioreq->tag.sendto.addrlen); - break; - - case IOREQ_CLOSE: - io_uring_prep_close(sqe, - ioreq->tag.close.fd); - break; - } - - io_uring_sqe_set_data(sqe, ioreq); - } - - return 0; -} diff --git a/src/libdiscord.c b/src/libdiscord.c @@ -65,7 +65,7 @@ discord_free(struct discord *ctx) } static SSL * -create_ssl(SSL_CTX *ctx, BIO **ssl_bio, BIO **net_bio, size_t buffer_size, +create_ssl(SSL_CTX *ctx, BIO **ssl_bio, BIO **net_bio, size_t bufsz, char const *host) { SSL *ssl; @@ -76,7 +76,7 @@ create_ssl(SSL_CTX *ctx, BIO **ssl_bio, BIO **net_bio, size_t buffer_size, SSL_set_tlsext_host_name(ssl, host); SSL_set1_host(ssl, host); - if (BIO_new_bio_pair(ssl_bio, buffer_size, net_bio, buffer_size) < 0) + if (BIO_new_bio_pair(ssl_bio, bufsz, net_bio, bufsz) < 0) goto error; SSL_set_bio(ssl, *ssl_bio, *ssl_bio); @@ -93,42 +93,29 @@ int discord_connect_gateway(struct discord *ctx) { static struct conn_ops gateway_ops = { - .connect = gateway_connect, - .tls_handshake = gateway_tls_handshake, - .recv = gateway_recv, - .send = gateway_send, + .on_connect = gateway_on_connect, + .on_tls_handshake = gateway_on_tls_handshake, + .on_close = gateway_on_close, + .on_recv = gateway_on_recv, + .on_send = gateway_on_send, }; struct conn *conn = &ctx->gateway.conn; - struct addrinfo hints = { - .ai_family = AF_UNSPEC, - .ai_socktype = SOCK_STREAM, - .ai_protocol = IPPROTO_TCP, - .ai_flags = AI_CANONNAME | AI_NUMERICSERV, - }, *addrinfo; - - if (getaddrinfo(GATEWAY_HOST, GATEWAY_PORT, &hints, &addrinfo)) { - return -1; - } - - conn->addrinfo = conn->ai_ptr = addrinfo; - conn->ssl = create_ssl(ctx->ssl_ctx, &conn->ssl_bio, &conn->net_bio, conn->cap, GATEWAY_HOST); - if (!conn->ssl) { - freeaddrinfo(conn->addrinfo); + if (!conn->ssl) return -1; - } conn->buf = ctx->gateway.buf; conn->cap = sizeof ctx->gateway.buf; conn->ops = &gateway_ops; - return conn_queue_connect(conn, &ctx->io_uring); + return gateway_connect(conn, &ctx->io_uring, + GATEWAY_HOST, GATEWAY_PORT); } int @@ -158,8 +145,7 @@ discord_poll_events(struct discord *ctx, struct conn, ioreq); - ret = conn_handle_io(conn, &ctx->io_uring, - cqe->res, evs); + ret = conn_do_io(conn, &ctx->io_uring, cqe->res, evs); seen++; @@ -184,10 +170,6 @@ discord_poll_events(struct discord *ctx, return ret; } -void -discord_error(struct discord *ctx) -{ - fprintf(stderr, "internal discord error\n"); -} - #include "internal.c" +#include "gateway.c" +#include "voice.c" diff --git a/src/list.c b/src/list.c @@ -1,23 +0,0 @@ -#include "list.h" - -extern inline void -list_node_link(struct list_node *node, - struct list_node *prev, - struct list_node *next); - -extern inline struct list_node * -list_node_unlink(struct list_node *node); - -extern inline void -list_push_head(struct list_node *restrict list, - struct list_node *restrict node); - -extern inline void -list_push_tail(struct list_node *restrict list, - struct list_node *restrict node); - -extern inline struct list_node * -list_pop_head(struct list_node *list); - -extern inline struct list_node * -list_pop_tail(struct list_node *list); diff --git a/src/list.h b/src/list.h @@ -1,99 +0,0 @@ -#ifndef LIST_H -#define LIST_H - -#include <stddef.h> -#include <stdint.h> - -#define TYPEOF(v) (__typeof__ (v)) - -#define TO_PARENT_PTR(ptr, T, member) \ - ((T *) (((uintptr_t) (ptr)) - offsetof(T, member))) - -struct list_node { - struct list_node *prev, *next; -}; - -#define LIST_INIT(list) ((struct list_node) { &(list), &(list), }) - -#define LIST_HEAD(list) ((list)->next) -#define LIST_TAIL(list) ((list)->prev) - -#define LIST_EMPTY(list) \ - (LIST_HEAD(list) == (list) && LIST_TAIL(list) == (list)) - -#define LIST_NODE_ITER(list, it) \ - for ((it) = LIST_HEAD(list); (it) != (list); (it) = LIST_HEAD(it)) - -#define LIST_NODE_RITER(list, it) \ - for ((it) = LIST_TAIL(list); (it) != (list); (it) = LIST_TAIL(it)) - -#define LIST_NODE_ENTRY(node, T, member) \ - TO_PARENT_PTR((node), T, member) - -#define LIST_ENTRY_ITER(list, it, member) \ - for ((it) = LIST_NODE_ENTRY(LIST_HEAD(list), \ - __typeof__ (*(it)), \ - member); \ - &(it)->member != (list); \ - (it) = LIST_NODE_ENTRY(LIST_HEAD(&(it)->member), \ - __typeof__ (*(it)), \ - member)) - -#define LIST_ENTRY_RITER(list, it, member) \ - for ((it) = LIST_NODE_ENTRY(LIST_TAIL(list), \ - __typeof__ (*(it)), \ - member); \ - &(it)->member != (list); \ - (it) = LIST_NODE_ENTRY(LIST_TAIL(&(it)->member), \ - __typeof__ (*(it)), \ - member)) - - -inline void -list_node_link(struct list_node *node, - struct list_node *prev, - struct list_node *next) -{ - node->prev = prev; - prev->next = node; - node->next = next; - next->prev = node; -} - -inline struct list_node * -list_node_unlink(struct list_node *node) -{ - node->prev->next = node->next; - node->next->prev = node->prev; - return node; -} - -inline void -list_push_head(struct list_node *restrict list, - struct list_node *restrict node) -{ - list_node_link(node, list, LIST_HEAD(list)); -} - -inline void -list_push_tail(struct list_node *restrict list, - struct list_node *restrict node) -{ - list_node_link(node, LIST_TAIL(list), list); -} - -inline struct list_node * -list_pop_head(struct list_node *list) -{ - struct list_node *res = list_node_unlink(LIST_HEAD(list)); - return res; -} - -inline struct list_node * -list_pop_tail(struct list_node *list) -{ - struct list_node *res = list_node_unlink(LIST_TAIL(list)); - return res; -} - -#endif /* LIST_H */ diff --git a/src/stringview.c b/src/stringview.c @@ -1 +0,0 @@ -#include "stringview.h" diff --git a/src/stringview.h b/src/stringview.h @@ -1,29 +0,0 @@ -#ifndef STRINGVIEW_H -#define STRINGVIEW_H - -#include <stddef.h> -#include <string.h> - -struct stringview { - unsigned char *ptr; - size_t len; -}; - -#define FROM_CSTR(cstr) ((struct stringview) { (cstr), strlen(cstr), }) - -inline int -svcmp(struct stringview *a, struct stringview *b) -{ - if (a->len != b->len) - return a->len - b->len; - - return strncmp((char *) a->ptr, (char *) b->ptr, a->len); -} - -inline unsigned char * -svstr(struct stringview *haystack, struct stringview *needle) -{ - return NULL; -} - -#endif /* STRINGVIEW_H */ diff --git a/src/utils.c b/src/utils.c @@ -1,3 +1,35 @@ -#include "arena.c" -#include "list.c" -#include "stringview.c" +#include "utils.h" + +extern inline void +arena_reset(struct arena *arena); + +extern inline void * +arena_alloc(struct arena *arena, size_t size, size_t alignment); + +extern inline void +list_node_link(struct list_node *node, + struct list_node *prev, + struct list_node *next); + +extern inline struct list_node * +list_node_unlink(struct list_node *node); + +extern inline void +list_push_head(struct list_node *restrict list, + struct list_node *restrict node); + +extern inline void +list_push_tail(struct list_node *restrict list, + struct list_node *restrict node); + +extern inline struct list_node * +list_pop_head(struct list_node *list); + +extern inline struct list_node * +list_pop_tail(struct list_node *list); + +extern inline int +svcmp(struct stringview a, struct stringview b); + +extern inline unsigned char * +svstr(struct stringview haystack, struct stringview needle); diff --git a/src/utils.h b/src/utils.h @@ -1,8 +1,179 @@ #ifndef UTILS_H #define UTILS_H -#include "arena.h" -#include "list.h" -#include "stringview.h" +#include <assert.h> +#include <stdalign.h> +#include <stddef.h> +#include <stdint.h> +#include <string.h> + +#define KiB (1024ull) +#define MiB (1024 * KiB) +#define GiB (1024 * MiB) +#define TiB (1024 * GiB) + +#define ARRLEN(arr) (sizeof (arr) / sizeof (arr)[0]) + +#define MIN(a, b) (((a) < (b)) ? (a) : (b)) +#define MAX(a, b) (((a) > (b)) ? (a) : (b)) +#define CLAMP(min, max, v) MIN((max), MAX((min), (v))) + +#define IS_POW2(v) (((v) & ((v) - 1)) == 0) + +#define IS_ALIGNED(v, align) (((v) & ((align) - 1)) == 0) +#define ALIGN_PREV(v, align) ((v) & ~((align) - 1)) +#define ALIGN_NEXT(v, align) ALIGN_PREV((v) + ((align) - 1), (align)) + +#define TYPEOF(v) (__typeof__ (v)) + +#define TO_PARENT_PTR(ptr, T, member) \ + ((T *) (((uintptr_t) (ptr)) - offsetof(T, member))) + +// ======================================================================= + +struct arena { + void *ptr; + size_t cap, len; +}; + +inline void +arena_reset(struct arena *arena) +{ + arena->len = 0; +} + +inline void * +arena_alloc(struct arena *arena, size_t size, size_t alignment) +{ + assert(size); + assert(alignment); + assert(IS_POW2(alignment)); + + uintptr_t base = (uintptr_t) arena->ptr; + uintptr_t end = base + arena->cap; + + uintptr_t aligned_ptr = ALIGN_NEXT(base + arena->len, alignment); + if (end < aligned_ptr + size) + return NULL; + + arena->len = (aligned_ptr + size) - base; + + return (void *) aligned_ptr; +} + +#define ARENA_ALLOC_ARRAY(arena, T, n) \ + arena_alloc((arena), sizeof(T) * (n), alignof(T)) + +#define ARENA_ALLOC_SIZED(arena, T) \ + ARENA_ALLOC_ARRAY((arena), T, 1) + +// ======================================================================= + +struct list_node { + struct list_node *prev, *next; +}; + +#define LIST_INIT(list) ((struct list_node) { &(list), &(list), }) + +#define LIST_HEAD(list) ((list)->next) +#define LIST_TAIL(list) ((list)->prev) + +#define LIST_EMPTY(list) \ + (LIST_HEAD(list) == (list) && LIST_TAIL(list) == (list)) + +#define LIST_NODE_ITER(list, it) \ + for ((it) = LIST_HEAD(list); (it) != (list); (it) = LIST_HEAD(it)) + +#define LIST_NODE_RITER(list, it) \ + for ((it) = LIST_TAIL(list); (it) != (list); (it) = LIST_TAIL(it)) + +#define LIST_NODE_ENTRY(node, T, member) \ + TO_PARENT_PTR((node), T, member) + +#define LIST_ENTRY_ITER(list, it, member) \ + for ((it) = LIST_NODE_ENTRY(LIST_HEAD(list), \ + TYPEOF(*(it)), member); \ + &(it)->member != (list); \ + (it) = LIST_NODE_ENTRY(LIST_HEAD(&(it)->member), \ + TYPEOF(*(it)), member)) + +#define LIST_ENTRY_RITER(list, it, member) \ + for ((it) = LIST_NODE_ENTRY(LIST_TAIL(list), \ + TYPEOF(*(it)), member); \ + &(it)->member != (list); \ + (it) = LIST_NODE_ENTRY(LIST_TAIL(&(it)->member), \ + TYPEOF(*(it)), member)) + + +inline void +list_node_link(struct list_node *node, + struct list_node *prev, + struct list_node *next) +{ + node->prev = prev; + prev->next = node; + node->next = next; + next->prev = node; +} + +inline struct list_node * +list_node_unlink(struct list_node *node) +{ + node->prev->next = node->next; + node->next->prev = node->prev; + return node; +} + +inline void +list_push_head(struct list_node *restrict list, + struct list_node *restrict node) +{ + list_node_link(node, list, LIST_HEAD(list)); +} + +inline void +list_push_tail(struct list_node *restrict list, + struct list_node *restrict node) +{ + list_node_link(node, LIST_TAIL(list), list); +} + +inline struct list_node * +list_pop_head(struct list_node *list) +{ + struct list_node *res = list_node_unlink(LIST_HEAD(list)); + return res; +} + +inline struct list_node * +list_pop_tail(struct list_node *list) +{ + struct list_node *res = list_node_unlink(LIST_TAIL(list)); + return res; +} + +// ====================================================================== + +struct stringview { + unsigned char *ptr; + size_t len; +}; + +#define FROM_CSTR(cstr) ((struct stringview) { (cstr), strlen(cstr), }) + +inline int +svcmp(struct stringview a, struct stringview b) +{ + if (a.len != b.len) + return a.len - b.len; + + return strncmp((char *) a.ptr, (char *) b.ptr, a.len); +} + +inline unsigned char * +svstr(struct stringview haystack, struct stringview needle) +{ + return NULL; +} #endif /* UTILS_H */ diff --git a/src/voice.c b/src/voice.c @@ -2,28 +2,51 @@ int voice_connect(struct conn *conn, struct io_uring *uring, - struct discord_event *ev) + char const *host, char const *port) +{ + return -1; +} + +int +voice_on_connect(struct conn *conn, struct io_uring *uring) { return -1; } int -voice_tls_handshake(struct conn *conn, struct io_uring *uring, - struct discord_event *ev) +voice_on_tls_handshake(struct conn *conn, struct io_uring *uring) { return -1; } int -voice_recv(struct conn *conn, struct io_uring *uring, - struct discord_event *ev) +voice_on_close(struct conn *conn, struct io_uring *uring) { return -1; } int -voice_send(struct conn *conn, struct io_uring *uring, - struct discord_event *ev) +voice_recv(struct conn *conn, struct io_uring *uring) +{ + return -1; +} + +int +voice_on_recv(struct conn *conn, struct io_uring *uring, + struct discord_event *ev) +{ + return -1; +} + +int +voice_send(struct conn *conn, struct io_uring *uring) +{ + return -1; +} + +int +voice_on_send(struct conn *conn, struct io_uring *uring, + struct discord_event *ev) { return -1; }