commit 6c4c23bef86201c766f832a25eb6a7abb867789c
parent 9369de7d8bbf430bbb8b6552e776c5898250bb69
Author: MikoĊaj Lenczewski <mblenczewski@gmail.com>
Date: Sat, 21 Jun 2025 14:26:12 +0100
Simplified source files
Diffstat:
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;
}