aboutsummaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
authorspl3g <spleefer6@yandex.ru>2025-03-22 21:41:16 +0300
committerspl3g <spleefer6@yandex.ru>2025-03-22 21:41:16 +0300
commit62454373db4cd2add82ded0cf7b21f7d69ade597 (patch)
tree1627133fe4567e9a3abb707af5e7289353410d5f /lib
parentef5f52fb739c9f0d71c579f08363ef0dfd5c227d (diff)
Reorganize the lib
Diffstat (limited to 'lib')
-rw-r--r--lib/arena.c84
-rw-r--r--lib/arena.h65
-rw-r--r--lib/arena_strings.c53
-rw-r--r--lib/arena_strings.h36
-rw-r--r--lib/const_strings.c86
-rw-r--r--lib/const_strings.h28
-rw-r--r--lib/http.c586
-rw-r--r--lib/http.h177
8 files changed, 0 insertions, 1115 deletions
diff --git a/lib/arena.c b/lib/arena.c
deleted file mode 100644
index 8cd1748..0000000
--- a/lib/arena.c
+++ /dev/null
@@ -1,84 +0,0 @@
-#include "arena.h"
-
-region *new_region(size_t cap) {
- size_t size_bytes = sizeof(region) + sizeof(uintptr_t)*cap;
- region *r = (region *)malloc(size_bytes);
- assert(r);
- r->next = NULL;
- r->len = 0;
- r->cap = cap;
- return r;
-}
-
-arena arena_init_cap(size_t cap) {
- arena a = {0};
- a.region_cap = cap;
- return a;
-}
-
-void *arena_alloc(arena *a, size_t size_bytes) {
- size_t size = (size_bytes + sizeof(uintptr_t)-1)/sizeof(uintptr_t);
-
- if (a->end == NULL) {
- assert(a->beg == NULL);
- size_t capacity = a->region_cap ? a->region_cap : ARENA_REGION_DEFAULT_CAPACITY;
- if (capacity < size) capacity = size;
- a->beg = new_region(capacity);
- a->end = a->beg;
- }
-
- while (a->end->len + size < a->end->cap && a->end->next != NULL) {
- a->end = a->end->next;
- }
-
- if (a->end->len + size > a->end->cap) {
- size_t capacity = a->region_cap ? a->region_cap : ARENA_REGION_DEFAULT_CAPACITY;
- if (capacity < size) capacity = size;
- a->beg = new_region(capacity);
- a->end->next = new_region(capacity);
- a->end = a->end->next;
- }
-
- void *p = &a->end->data[a->end->len];
- a->end->len += size;
- return memset(p, 0, size);
-}
-
-void arena_free(arena *a) {
- region *r = a->beg;
- while (r != NULL) {
- region *r0 = r;
- r = r0->next;
- free(r0);
- }
-}
-
-void *arena_realloc(arena *a, void *oldptr, size_t oldsz, size_t newsz) {
- if (newsz <= oldsz) return oldptr;
- void *newptr = arena_alloc(a, newsz);
- char *newptr_char = (char*)newptr;
- char *oldptr_char = (char*)oldptr;
- for (size_t i = 0; i < oldsz; ++i) {
- newptr_char[i] = oldptr_char[i];
- }
- return newptr;
-}
-
-void grow_da(void *slice, size_t size, arena *arena) {
- struct {
- void *data;
- size_t len;
- size_t cap;
- } replica;
- memcpy(&replica, slice, sizeof(replica));
-
- replica.cap = replica.cap ? replica.cap : 1;
- void *data = arena_alloc(arena, size*2*replica.cap);
- replica.cap *= 2;
- if (replica.len) {
- memcpy(data, replica.data, size*replica.len);
- }
- replica.data = data;
-
- memcpy(slice, &replica, sizeof(replica));
-}
diff --git a/lib/arena.h b/lib/arena.h
deleted file mode 100644
index 1f53355..0000000
--- a/lib/arena.h
+++ /dev/null
@@ -1,65 +0,0 @@
-// Most of the code is from https://github.com/tsoding/arena
-
-#ifndef ARENA_H_
-#define ARENA_H_
-
-#include <stdlib.h>
-#include <stddef.h>
-#include <stdint.h>
-#include <assert.h>
-#include <string.h>
-
-typedef struct region region;
-
-struct region {
- region *next;
- size_t cap;
- size_t len;
- uintptr_t data[];
-};
-
-typedef struct {
- region *beg;
- region *end;
- size_t region_cap;
-} arena;
-
-arena arena_init_cap(size_t cap);
-void *arena_alloc(arena *a, size_t size);
-void arena_free(arena *a);
-void *arena_realloc(arena *a, void *oldptr, size_t oldsz, size_t newsz);
-
-#define new(a, t, c) (t *)arena_alloc(a, sizeof(t)*c)
-
-#define ARENA_REGION_DEFAULT_CAPACITY (8*1024)
-#define ARENA_DA_INIT_CAP (2)
-
-#define arena_da_reserve(a, da, expected_size) \
- do { \
- if ((expected_size) >= (da)->cap) { \
- size_t new_cap = (da)->cap == 0 ? ARENA_DA_INIT_CAP : (da)->cap*2; \
- while (new_cap < expected_size) { \
- new_cap *= 2; \
- } \
- (da)->data = arena_realloc( \
- (a), (da)->data, \
- (da)->cap*sizeof(*(da)->data), \
- new_cap*sizeof(*(da)->data)); \
- (da)->cap = new_cap; \
- } \
- } while (0)
-
-#define arena_da_append(a, da, item) \
- do { \
- arena_da_reserve((a), (da), (da)->len + 1); \
- (da)->data[(da)->len++] = (item); \
- } while (0)
-
-#define arena_da_append_many(a, da, items, items_len) \
- do { \
- arena_da_reserve((a), (da), (da)->len+len); \
- memcpy((da)->data+(da)->len, (items), sizeof(*(da)->data)*items_len); \
- (da)->len += len; \
- } while (0)
-
-#endif //ARENA_H_
diff --git a/lib/arena_strings.c b/lib/arena_strings.c
deleted file mode 100644
index 3497c2e..0000000
--- a/lib/arena_strings.c
+++ /dev/null
@@ -1,53 +0,0 @@
-#include "arena_strings.h"
-
-const_string arena_cs_init(arena *a, int len) {
- char *str = new(a, char, len+1);
- const_string cs = {0};
- cs.data = str;
- cs.len = len;
- return cs;
-}
-
-const_string arena_cs_append(arena *a, const_string dst, const_string src) {
- char *str = new(a, char, dst.len+src.len + 1);
- memcpy(str, dst.data, dst.len);
- memcpy(str + dst.len, src.data, src.len + 1);
- const_string cs = {0};
- cs.data = str;
- cs.len = dst.len + src.len;
- return cs;
-}
-
-const_string arena_cs_concat(arena *a, const_string_da strings, const_string sep) {
- if (strings.len == 0) {
- return CS("");
- } else if (strings.len == 0) {
- return *strings.data;
- }
-
- int len = sep.len * (strings.len - 1);
- for (size_t i = 0; i < strings.len; i++) {
- len += (strings.data + i)->len;
- };
-
- char* str = arena_alloc(a, len);
- int offset = 0;
-
- for (size_t i = 0; i < strings.len; i++) {
- int curr_strlen = (strings.data + i)->len;
- memcpy(str + offset,
- (strings.data + i)->data,
- curr_strlen);
-
- offset += curr_strlen;
-
- if (i != strings.len - 1) {
- memcpy(str + offset,
- sep.data, sep.len);
- offset += sep.len;
- }
- };
- *(str + len + 1) = '\0';
-
- return (const_string){str, len};
-};
diff --git a/lib/arena_strings.h b/lib/arena_strings.h
deleted file mode 100644
index b25435d..0000000
--- a/lib/arena_strings.h
+++ /dev/null
@@ -1,36 +0,0 @@
-#ifndef ARENA_STRINGS_H_
-#define ARENA_STRINGS_H_
-
-#include "arena.h"
-#include "const_strings.h"
-
-typedef struct {
- const_string *data;
- size_t len;
- size_t cap;
-} const_string_da;
-
-typedef struct {
- char* data;
- size_t len;
- size_t cap;
-} string_builder;
-
-const_string arena_cs_append(arena *a, const_string dst, const_string src);
-const_string arena_cs_init(arena *a, int len);
-const_string arena_cs_concat(arena *a, const_string_da strings, const_string sep);
-
-#define arena_sb_append_buf(a, sb, buf, len) arena_da_append_many((a), (sb), (buf), (len))
-
-#define arena_sb_append_cstr(a, sb, cstr) \
- do { \
- const char * str = (cstr); \
- size_t len = strlen((cstr)); \
- arena_da_append_many((a), (sb), (str), len); \
- } while (0)
-
-#define arena_sb_append_null(a, sb) arena_da_append_many((a), (sb), "", 1)
-
-#define arena_sb_to_cs(sb) cs_from_parts((sb).data, (sb).len)
-
-#endif // ARENA_STRINGS_H_
diff --git a/lib/const_strings.c b/lib/const_strings.c
deleted file mode 100644
index 2d743b1..0000000
--- a/lib/const_strings.c
+++ /dev/null
@@ -1,86 +0,0 @@
-#include "const_strings.h"
-
-const_string cs_from_parts(const char* data, int len) {
- const_string str;
- str.data = data;
- str.len = len;
-
- return str;
-}
-
-const_string cs_from_cstr(const char* cstr) {
- return cs_from_parts(cstr, strlen(cstr));
-}
-
-const_string cs_slice(const_string src, int from, int to) {
- if (from > src.len) {
- return src;
- }
-
- int new_from;
- if (from <= 0) {
- new_from = 1;
- }
- new_from -= 1;
-
- int new_len;
- if (to > src.len) {
- new_len = src.len;
- } else {
- new_len = to;
- }
-
- return cs_from_parts(src.data + new_from, new_len);
-}
-
-const_string cs_chop_delim(const_string *str, char delim) {
- int n;
- for (n = 0; n < str->len && str->data[n] != delim; n++) {}
-
- const_string result = cs_from_parts(str->data, n);
-
- if (n < str->len) {
- str->len -= n + 1;
- str->data += n + 1;
- } else {
- str->len -= n;
- str->data += n;
- }
-
- return result;
-}
-
-bool cs_try_chop_delim(const_string *str, char delim, const_string *dst) {
- const_string str_copy = *str;
- const_string tmp = cs_chop_delim(&str_copy, delim);
- if (str_copy.len == 0) {
- return false;
- }
- *str = str_copy;
- *dst = tmp;
- return true;
-}
-
-int cs_find_delim(const_string str, char delim) {
- int n;
- for (n = 0; n < str.len && str.data[n] != delim; n++) {}
-
- if (n < str.len) {
- return n;
- }
- return -1;
-}
-
-bool cs_eq(const_string str1, const_string str2) {
- if (str1.len != str2.len) {
- return false;
- }
- return memcmp(str1.data, str2.data, str1.len) == 0;
-}
-
-void cs_print(char *format, const_string str) {
- char buf[str.len + 1];
- memcpy(buf, str.data, str.len);
- buf[str.len] = '\0';
- printf(format, buf);
-}
diff --git a/lib/const_strings.h b/lib/const_strings.h
deleted file mode 100644
index cb92442..0000000
--- a/lib/const_strings.h
+++ /dev/null
@@ -1,28 +0,0 @@
-#ifndef CONST_STRINGS_H_
-#define CONST_STRINGS_H_
-
-#include <string.h>
-#include <stdio.h>
-#include <stdbool.h>
-
-typedef struct {
- const char* data;
- int len;
-} const_string;
-
-const_string cs_from_parts(const char* data, int len);
-const_string cs_from_cstr(const char* cstr);
-const_string cs_slice(const_string src, int from, int to);
-const_string cs_chop_delim(const_string *src, char delim);
-bool cs_try_chop_delim(const_string *str, char delim, const_string *dst);
-int cs_find_delim(const_string str, char delim);
-bool cs_eq(const_string str1, const_string str2);
-void cs_print(char *format, const_string str);
-
-#define CS(cstr) cs_from_parts(cstr, sizeof(cstr) - 1)
-#define CS_STATIC(cstr) {.data = cstr, .len = sizeof(cstr) - 1}
-
-#define CS_FMT "%.*s"
-#define CS_ARG(cs) (int) (cs).len, (cs).data
-
-#endif // STRINGS_H_
diff --git a/lib/http.c b/lib/http.c
deleted file mode 100644
index 64b357b..0000000
--- a/lib/http.c
+++ /dev/null
@@ -1,586 +0,0 @@
-#include "http.h"
-
-#define MAX_DATA_SIZE 256
-#define BUFFER_SIZE 4096
-#define REQUEST_ARENA_SIZE 1024
-
-int volatile keepRunning = 1;
-
-struct {
- http_response_code code;
- const_string string;
-} response_strings [] = {
- {100, CS_STATIC("Continue")},
- {101, CS_STATIC("Switching Protocols")},
- {102, CS_STATIC("Processing")},
- {103, CS_STATIC("Early Hints")},
- {200, CS_STATIC("OK")},
- {201, CS_STATIC("Created")},
- {202, CS_STATIC("Accepted")},
- {204, CS_STATIC("No Content")},
- {300, CS_STATIC("Multiple Choices")},
- {301, CS_STATIC("Moved Permanently")},
- {302, CS_STATIC("Found")},
- {303, CS_STATIC("See Other")},
- {304, CS_STATIC("Not Modified")},
- {307, CS_STATIC("Temporary Redirect")},
- {308, CS_STATIC("Permanent Redirect")},
- {400, CS_STATIC("Bad Request")},
- {401, CS_STATIC("Unauthorized")},
- {402, CS_STATIC("Payment Required")},
- {403, CS_STATIC("Forbidden")},
- {404, CS_STATIC("Not Found")},
- {405, CS_STATIC("Method Not Allowed")},
- {406, CS_STATIC("Not Acceptable")},
- {408, CS_STATIC("Request Timeout")},
- {418, CS_STATIC("Im A Teepot")},
- {500, CS_STATIC("Internal Server Error")},
- {501, CS_STATIC("Not Implemented")},
- {502, CS_STATIC("Bad Gateway")},
- {503, CS_STATIC("Service Unavailable")},
- {505, CS_STATIC("Http Version Not Suppported")},
-};
-
-const_string get_response_string(http_response_code code) {
- for (int i = 0; sizeof(response_strings)/sizeof(response_strings[0]) ;i++) {
- if (response_strings[i].code == code) {
- return response_strings[i].string;
- }
- }
- return CS("");
-}
-
-
-void sigchld_handler() {
- // waitpid() might overwrite errno, so we save and restore it:
- int saved_errno = errno;
-
- while(waitpid(-1, NULL, WNOHANG) > 0);
-
- errno = saved_errno;
-}
-
-void http_log(http_log_level log, char *fmt, ...) {
- switch (log) {
- case HTTP_INFO:
- fprintf(stderr, "[INFO] ");
- break;
-
- case HTTP_WARNING:
- fprintf(stderr, "[WARNING] ");
- break;
-
- case HTTP_ERROR:
- fprintf(stderr, "[ERROR] ");
- break;
- }
-
- va_list args;
- va_start(args, fmt);
- vfprintf(stderr, fmt, args);
- va_end(args);
-}
-
-
-void *get_in_addr(struct sockaddr *sa) {
- if (sa->sa_family == AF_INET) {
- return &(((struct sockaddr_in*)sa)->sin_addr);
- }
-
- return &(((struct sockaddr_in6*)sa)->sin6_addr);
-}
-
-int get_in_port(struct sockaddr *sa) {
- if (sa->sa_family == AF_INET) {
- return ntohs((((struct sockaddr_in*)sa)->sin_port));
- }
-
- return (((struct sockaddr_in6*)sa)->sin6_port);
-}
-
-void set_context_value(arena *arena, http_context *ctx, http_context_value kv) {
- for (size_t i = 0; i < ctx->len; i++) {
- http_context_value *ctx_val = (ctx->data + i);
- if (cs_eq(kv.key, ctx_val->key)) {
- ctx_val->val = kv.val;
- return;
- }
- }
- arena_da_append(arena, ctx, kv);
-}
-
-void *get_context_value(http_context *ctx, char* key) {
- if (ctx == NULL) {
- return NULL;
- }
-
- const_string key_cs = cs_from_cstr(key);
- for (size_t i = 0; i < ctx->len; i++) {
- http_context_value *ctx_val = (ctx->data + i);
- if (cs_eq(key_cs, ctx_val->key)) {
- return ctx_val->val;
- }
- }
- return NULL;
-}
-
-void http_internal_server_error_handler(http_request req) {
- const_string *error = get_context_value(req.ctx, "error");
- req.resp->code = INTERNAL_SERVER_ERROR;
- req.resp->body = *error;
- http_send(req);
-}
-
-void http_not_found_handler(http_request req) {
- req.resp->code = NOT_FOUND;
- http_send(req);
-}
-
-void http_run_next(http_middleware *self, http_request req) {
- if (self->next == NULL) {
- (self->handler)(req);
- return;
- }
-
- (self->next->func)(self->next, req);
-};
-
-void http_register_handler_middleware(arena *arena, http_handler *hand, http_middleware_func func) {
- http_middleware *middleware = arena_alloc(arena, sizeof(http_middleware));
- middleware->func = func;
- middleware->handler = hand->func;
- if (hand->middleware == NULL) {
- hand->middleware = middleware;
- return;
- }
-
- http_middleware **prev = &hand->middleware;
- http_middleware *next = hand->middleware;
- while (next->next != NULL) {
- prev = &next;
- next = next->next;
- }
- middleware->next = next;
- *prev = middleware;
-}
-
-void http_register_global_middleware(http_server *serv, http_middleware_func func) {
- arena *arena = serv->arena;
-
- http_middleware *middleware = arena_alloc(arena, sizeof(http_middleware));
- http_handler_func *handler = arena_alloc(arena, sizeof(http_handler_func));
- middleware->func = func;
- middleware->handler = *handler;
- if (serv->global_middleware == NULL) {
- http_global_middleware *global_middleware = arena_alloc(arena, sizeof(http_global_middleware));
- global_middleware->start = middleware;
- global_middleware->end = middleware;
- serv->global_middleware = global_middleware;
- return;
- }
-
- serv->global_middleware->end->next = middleware;
- serv->global_middleware->end = middleware;
-}
-
-int init_server(arena *arena, http_server *serv, char *addr, char *port) {
- // serv initialization
- struct addrinfo hints, *res;
-
- memset(&hints, 0, sizeof hints);
- hints.ai_family = AF_UNSPEC;
- hints.ai_socktype = SOCK_STREAM;
- hints.ai_flags = AI_PASSIVE;
-
- int status = getaddrinfo(addr, port, &hints, &res);
- if (status != 0) {
- fprintf(stderr, "getaddrinfo: %s\n", gai_strerror(status));
- return 1;
- }
-
- int sockfd = socket(res->ai_family, res->ai_socktype, 0);
- if (sockfd < 0) {
- perror("socket");
- return 1;
- }
-
- int yes = 1;
- if (setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, &yes, sizeof yes) == -1) {
- perror("setsockopt");
- return 1;
- }
-
- if (bind(sockfd, res->ai_addr, res->ai_addrlen)) {
- perror("bind");
- return 1;
- }
-
- serv->arena = arena;
- serv->addr = (struct sockaddr *)res->ai_addr;
- serv->sockfd = sockfd;
-
- freeaddrinfo(res);
-
- struct sigaction sa;
- sa.sa_handler = sigchld_handler;
- sigemptyset(&sa.sa_mask);
- sa.sa_flags = SA_RESTART;
- if (sigaction(SIGCHLD, &sa, NULL) == -1) {
- perror("sigaction");
- return 1;
- }
-
- return 0;
-}
-
-http_handler *http_handle_path(http_server *serv, char* method, char* path, http_handler_func handler) {
- http_handler hand = {
- .method = cs_from_cstr(method),
- .path = cs_from_cstr(path),
- .func = handler,
- };
-
- arena_da_append(serv->arena, &serv->handlers, hand);
- return &serv->handlers.data[serv->handlers.len-1];
-}
-
-const_string http_compose_response(arena *arena, http_response *resp) {
- const_string_da header_da = {0};
- arena_da_append(arena, &header_da, CS("HTTP/1.1"));
-
- if (resp->code != 0) {
- char buf[4];
- sprintf(buf, "%ld", resp->code);
- arena_da_append(arena, &header_da, cs_from_cstr(buf));
- arena_da_append(arena, &header_da, get_response_string(resp->code));
- } else {
- printf("Response is handeled, but no code is given\n");
- arena_da_append(arena, &header_da, CS("500"));
- arena_da_append(arena, &header_da, get_response_string(INTERNAL_SERVER_ERROR));
- }
-
- const_string_da resp_da= {0};
-
- const_string http_header = arena_cs_concat(arena, header_da, CS(" "));
- arena_da_append(arena, &resp_da, http_header);
-
- for (size_t i = 0; i < resp->headers.len; i++) {
- KV *header = (resp->headers.data + i);
- const_string header_str = {0};
- header_str = arena_cs_append(arena, header_str, header->key);
- header_str = arena_cs_append(arena, header_str, CS(": "));
- header_str = arena_cs_append(arena, header_str, header->value);
- arena_da_append(arena, &resp_da, header_str);
- }
-
- arena_da_append(arena, &resp_da, CS(""));
- if (resp->body.len != 0) {
- arena_da_append(arena, &resp_da, resp->body);
- }
-
- const_string str = arena_cs_concat(arena, resp_da, CS("\r\n"));
-
- return str;
-}
-
-
-void http_send_response(size_t inc_fd, const_string resp) {
- const char *resp_cstr = resp.data;
- int resp_len = resp.len;
-
- int sent = send(inc_fd, resp_cstr, resp_len, 0);
- while (sent > 0 && resp_len - sent > 0) {
- resp_len -= sent;
- sent = send(inc_fd, resp_cstr, resp_len, 0);
- }
-
- if (sent < 0) {
- perror("send");
- }
-}
-
-void http_send(http_request req) {
- arena *arena = req.arena;
-
- assert(req.resp->code);
- const_string response = http_compose_response(arena, req.resp);
- http_send_response(req.inc_fd, response);
- req.resp->sent = true;
-}
-
-void http_send_json(http_request req, const_string json) {
- arena *arena = req.arena;
-
- int num_str_len = snprintf(NULL, 0, "%d", json.len);
- char* len_str = arena_alloc(arena, snprintf(NULL, 0, "%d", json.len));
- sprintf(len_str, "%d", json.len);
- const_string len_cs = {len_str, num_str_len};
-
- arena_da_append(arena, &req.resp->headers, ((KV){CS("Content-Length"), len_cs}));
- arena_da_append(arena, &req.resp->headers, ((KV){CS("Content-Type"), CS("application/json")}));
- req.resp->body = json;
-
- http_send(req);
-}
-void http_send_body(http_request req, const_string body) {
- arena *arena = req.arena;
-
- int num_str_len = snprintf(NULL, 0, "%d", body.len+2);
- char* len_str = arena_alloc(arena, snprintf(NULL, 0, "%d", body.len));
- sprintf(len_str, "%d", body.len);
- const_string len_cs = {len_str, num_str_len};
-
- arena_da_append(arena, &req.resp->headers, ((KV){CS("Content-Length"), len_cs}));
- arena_da_append(arena, &req.resp->headers, ((KV){CS("Content-Type"), CS("application/text")}));
- req.resp->body = body;
-
- http_send(req);
-}
-
-int chop_query(arena *arena, const_string *path, http_query_da *queries) {
- const_string queries_str = *path;
- int query_count = 0;
-
- if (!cs_try_chop_delim(&queries_str, '?', path)) {
- return 0;
- }
-
- const_string query_str;
-
- if (!cs_try_chop_delim(&queries_str, '&', &query_str)) {
- query_str = queries_str;
- }
-
- do {
- KV query = {0};
- const_string key;
- if (!cs_try_chop_delim(&query_str, '=', &key)) {
- return -1;
- }
-
- query.key = key;
- query.value = query_str;
- arena_da_append(arena, queries, query);
- query_count++;
- } while (cs_try_chop_delim(&queries_str, '&', &query_str));
-
- return query_count;
-}
-
-const_string chop_request(const_string *req_str, char delim, bool *parse_err) {
- if (*parse_err) {
- return CS("");
- }
- const_string str;
- if (!cs_try_chop_delim(req_str, delim, &str)) {
- *parse_err = true;
- return CS("");
- }
- return str;
-}
-
-int parse_request(arena *arena, size_t inc_fd, http_request *req) {
- char buf[MAX_DATA_SIZE];
- const_string req_str = {0};
-
- int got = recv(inc_fd, &buf, MAX_DATA_SIZE - 1, 0);
- if (got < 0) {
- perror("recv");
- return REQUEST_TIMEOUT;
- }
-
- buf[got] = '\0';
-
- req_str = arena_cs_append(arena, req_str, cs_from_cstr(buf));
-
- while (got == MAX_DATA_SIZE - 1) {
- got = recv(inc_fd, &buf, MAX_DATA_SIZE - 1, 0);
- if (got < 0) {
- perror("recv");
- return REQUEST_TIMEOUT;
- }
-
- buf[got] = '\0';
-
- const_string tmp = cs_from_parts(buf, got);
- req_str = arena_cs_append(arena, req_str, tmp);
- }
-
- bool parse_err = false;
-
- const_string method = chop_request(&req_str, ' ', &parse_err);
- const_string path = chop_request(&req_str, ' ', &parse_err);
- chop_request(&req_str, '\r', &parse_err);
- req_str.data += 1;
-
- header_da headers = {0};
- while (!parse_err && req_str.data[0] != '\r') {
- const_string header_str = chop_request(&req_str, '\r', &parse_err);
- req_str.data += 1;
-
- KV header;
- header.key = chop_request(&header_str, ':', &parse_err);
- header_str.data++;
- header.value = header_str;
-
- arena_da_append(arena, &headers, header);
- }
- chop_request(&req_str, '\n', &parse_err);
-
- if (parse_err) {
- return BAD_REQUEST;
- }
-
- http_query_da queries = {0};
-
- if (chop_query(arena, &path, &queries) < 0) {
- return BAD_REQUEST;
- }
-
-
- req->method = method;
- req->path = path;
- req->query = queries;
- req->headers = headers;
- req->body = req_str;
-
- return 0;
-}
-
-bool check_handler(http_handler hand, http_request req) {
- arena *arena = req.arena;
- http_context *ctx = req.ctx;
-
- const_string handler_path = hand.path;
- const_string req_path = req.path;
- if (!(cs_eq(hand.method, req.method) ||
- (cs_eq(hand.method, CS("GET")) && cs_eq(req.method, CS("HEAD"))))) {
- return false;
- }
-
- const_string path;
- bool entered = false;
-
- while (cs_try_chop_delim(&handler_path, ':', &path)) {
- entered = true;
-
- const_string req_byte = {req_path.data, path.len};
- if (!cs_eq(path, req_byte)) {
- return false;
- }
-
- req_path.data += path.len;
- req_path.len -= path.len;
-
- const_string name = cs_chop_delim(&handler_path, '/');
- const_string tmp = cs_chop_delim(&req_path, '/');
- const_string *value = arena_alloc(arena, sizeof(const_string));
- *value = tmp;
- set_context_value(arena, ctx, (http_context_value){name, (void *)value});
- }
-
- if (!entered && !cs_eq(handler_path, req_path)) {
- return false;
- }
-
- return true;
-}
-
-struct process_request_args {
- http_server serv;
- size_t inc_fd;
-};
-
-void *process_request(void *args) {
- struct process_request_args *pargs = args;
- http_server serv = pargs->serv;
- size_t inc_fd = pargs->inc_fd;
-
- arena req_arena = {0};
-
- http_request req = {0};
- req.inc_fd = inc_fd;
- req.arena = &req_arena;
-
- http_response resp = {0};
- req.resp = &resp;
-
- int parse_res = parse_request(&req_arena, inc_fd, &req);
- if (parse_res != 0) {
- resp.code = parse_res;
- http_send(req);
- }
-
- http_context req_context = {0};
- for (size_t i = 0; i < serv.global_ctx.len; i++) {
- set_context_value(&req_arena, &req_context, *(serv.global_ctx.data + i));
- }
- req.ctx = &req_context;
-
- http_global_middleware *g_mid = serv.global_middleware;
- if (!resp.sent) {
- for (size_t i = 0; i < serv.handlers.len; i++) {
- http_handler handler = serv.handlers.data[i];
- if (check_handler(handler, req)) {
- if (serv.global_middleware != NULL) {
- g_mid->end->next = handler.middleware;
- g_mid->end->handler = handler.func;
- g_mid->start->func(g_mid->start, req);
- } else if (handler.middleware != NULL) {
- handler.middleware->func(handler.middleware, req);
- } else {
- handler.func(req);
- }
-
- if (!resp.sent) {
- const_string error = CS("Server handled the request but did not send anything\n");
- http_log(HTTP_ERROR, "%s", error.data);
- set_context_value(&req_arena, &req_context, (http_context_value){CS("error"), (void *)&error});
- g_mid->end->handler = http_internal_server_error_handler;
- g_mid->start->func(g_mid->start, req);
- }
- break;
- }
- }
- }
-
- if (!resp.code) {
- g_mid->end->handler = http_not_found_handler;
- g_mid->start->func(g_mid->start, req);
- }
-
- close(inc_fd);
- arena_free(&req_arena);
-
- pthread_exit(NULL);
-}
-
-int listen_and_serve(http_server *serv) {
- if (listen(serv->sockfd, 10) != 0) {
- perror("listen");
- return 1;
- }
-
- char my_ipstr[INET6_ADDRSTRLEN];
- inet_ntop(serv->addr->sa_family, get_in_addr(serv->addr), my_ipstr, sizeof my_ipstr);
- http_log(HTTP_INFO, "Listening on %s:%d\n", my_ipstr, get_in_port(serv->addr));
-
- while (keepRunning) {
- struct sockaddr inc_addr;
- socklen_t addr_size = sizeof inc_addr;
- int inc_fd = accept(serv->sockfd, &inc_addr, &addr_size);
- if (inc_fd < 0) {
- perror("accept");
- return 1;
- }
-
- struct process_request_args args = {
- .serv = *serv,
- .inc_fd = inc_fd,
- };
-
- pthread_t thread_id;
- pthread_create(&thread_id, NULL, process_request, (void *)&args);
- }
- return 0;
-}
diff --git a/lib/http.h b/lib/http.h
deleted file mode 100644
index 4fcc418..0000000
--- a/lib/http.h
+++ /dev/null
@@ -1,177 +0,0 @@
-#ifndef HTTP_H_
-#define HTTP_H_
-
-#include <stdio.h>
-#include <string.h>
-#include <netinet/in.h>
-#include <netinet/ip.h>
-#include <sys/socket.h>
-#include <sys/types.h>
-#include <netdb.h>
-#include <arpa/inet.h>
-#include <errno.h>
-#include <unistd.h>
-#include <sys/wait.h>
-#include <signal.h>
-#include <stdlib.h>
-#include <stdarg.h>
-#include <pthread.h>
-
-#include "const_strings.h"
-#include "arena_strings.h"
-#include "arena.h"
-
-typedef struct {
- const_string key;
- const_string value;
-} KV;
-
-typedef struct {
- KV *data;
- size_t len;
- size_t cap;
-} header_da;
-
-typedef struct {
- const_string key;
- const_string val;
-} http_query;
-
-typedef struct {
- KV *data;
- size_t len;
- size_t cap;
-} http_query_da;
-
-typedef struct {
- const_string key;
- void *val;
-} http_context_value;
-
-typedef struct {
- http_context_value *data;
- size_t len;
- size_t cap;
-} http_context;
-
-typedef struct {
- size_t code;
- header_da headers;
- const_string body;
- bool sent;
-} http_response;
-
-typedef struct {
- size_t inc_fd;
- const_string method;
- const_string path;
- http_query_da query;
- header_da headers;
- const_string body;
-
- arena *arena;
- http_response* resp;
- http_context *ctx;
-} http_request;
-
-typedef void (*http_handler_func)(http_request);
-
-typedef struct http_handler_da http_handler_da;
-typedef struct http_middleware http_middleware;
-typedef struct http_handler http_handler;
-
-typedef void (*http_middleware_func)(http_middleware *, http_request);
-
-struct http_middleware {
- http_middleware_func func;
- http_middleware *next;
- http_handler_func handler;
-};
-
-struct http_handler {
- const_string method;
- const_string path;
- http_middleware *middleware;
- http_handler_func func;
-};
-
-struct http_handler_da {
- http_handler *data;
- size_t len;
- size_t cap;
-};
-
-typedef struct {
- http_middleware *start;
- http_middleware *end;
-} http_global_middleware;
-
-typedef struct {
- size_t sockfd;
- struct sockaddr *addr;
- arena *arena;
- http_handler_da handlers;
- http_context global_ctx;
- http_global_middleware *global_middleware;
-} http_server;
-
-typedef enum {
- HTTP_INFO = 0,
- HTTP_WARNING,
- HTTP_ERROR,
-} http_log_level;
-
-typedef enum {
- CONTINUE = 100,
- SWITCHING_PROTOCOLS = 101,
- PROCESSING = 102,
- EARLY_HINTS = 103,
- OK = 200,
- CREATED = 201,
- ACCEPTED = 202,
- NO_CONTENT = 204,
- MULTIPLE_CHOICES = 300,
- MOVED_PERMANENTLY = 301,
- FOUND = 302,
- SEE_OTHER = 303,
- NOT_MODIFIED = 304,
- TEMPORARY_REDIRECT = 307,
- PERMANENT_REDIRECT = 308,
- BAD_REQUEST = 400,
- UNAUTHORIZED = 401,
- PAYMENT_REQUIRED = 402,
- FORBIDDEN = 403,
- NOT_FOUND = 404,
- METHOD_NOT_ALLOWED = 405,
- NOT_ACCEPTABLE = 406,
- REQUEST_TIMEOUT = 408,
- IM_A_TEEPOT = 418,
- INTERNAL_SERVER_ERROR = 500,
- NOT_IMPLEMENTED = 501,
- BAD_GATEWAY = 502,
- SERVICE_UNAVAILABLE = 503,
- HTTP_VERSION_NOT_SUPPPORTED = 505,
-} http_response_code;
-
-const_string get_response_string(http_response_code code);
-void *get_in_addr(struct sockaddr *sa);
-int get_in_port(struct sockaddr *sa);
-void http_log(http_log_level log, char *fmt, ...);
-
-void set_context_value(arena *arena, http_context *ctx, http_context_value kv);
-void *get_context_value(http_context *ctx, char* key);
-
-void http_send(http_request req);
-void http_send_json(http_request req, const_string json);
-void http_send_body(http_request req, const_string body);
-
-int init_server(arena *arena, http_server *serv, char *addr, char *port);
-int listen_and_serve(http_server *serv);
-
-http_handler *http_handle_path(http_server *serv, char *method, char *path, http_handler_func handler);
-
-void http_run_next(http_middleware *self, http_request req);
-void http_register_global_middleware(http_server *hand, http_middleware_func func);
-void http_register_handler_middleware(arena *arena, http_handler *hand, http_middleware_func func);
-
-#endif // HTTP_H_