bunkum

an old and silly c99 web server with some fun features
Log | Files | Refs | README

commit e6baea87a494775c0f245e77ca254c395db56d54
parent dbaa680f3819391269a520637d013d145dce3177
Author: quantumish <freifeld.david@gmail.com>
Date:   Sun, 19 Nov 2023 15:44:00 -0500

Add README, tweak language

Diffstat:
Mhttp.c | 28++++++++++++++--------------
Mhttp/request.c | 22+++++++++++-----------
Mhttp/request.h | 4++--
Mphf.py | 44+++++++++++++++++++++++++-------------------
Mutils/html.c | 14+++++++-------
Mutils/html.h | 8++++----
Mutils/profile.c | 20++++++++++----------
Mutils/profile.h | 8++++----
Dutils/shitvec.c | 73-------------------------------------------------------------------------
Dutils/shitvec.h | 29-----------------------------
Mutils/sync.c | 6+++---
Mutils/sync.h | 4++--
12 files changed, 82 insertions(+), 178 deletions(-)

diff --git a/http.c b/http.c @@ -22,7 +22,7 @@ #include "utils/log.h" #include "utils/time.h" -#include "utils/shitvec.h" +#include "utils/vec.h" #include "utils/sync.h" #include "utils/html.h" #include "utils/compress.h" @@ -48,7 +48,7 @@ response_t serve_error(enum StatusCode c) { return r; } -shitvec_t paths; +vec_t paths; hashmap_t path_redirs; char* get_file_ext(char* filename) { @@ -79,9 +79,9 @@ response_t serve_file(request_t* req) { char* hdr; if ((hdr = hashmap_get(&req->headers, "Accept"))) { ok = false; - shitvec_t mtypes = hdr_parse_accept(hdr); + vec_t mtypes = hdr_parse_accept(hdr); for (int j = 0; j < mtypes.vec_sz; j++) { - struct req_mimetype* a_mtype = shitvec_get(&mtypes, j); + struct req_mimetype* a_mtype = vec_get(&mtypes, j); // TODO doesn't handle stuff like image/* (is that even allowed?) if (strcmp(a_mtype->item, mtype) == 0 || strcmp(a_mtype->item, "*/*") == 0) { ok = true; @@ -95,9 +95,9 @@ response_t serve_file(request_t* req) { if (ok && (hdr = hashmap_get(&req->headers, "Accept-Encoding"))) { ok = false; - shitvec_t mtypes = hdr_parse_accept(hdr); // abuse of this func + vec_t mtypes = hdr_parse_accept(hdr); // abuse of this func for (int j = 0; j < mtypes.vec_sz; j++) { - struct req_mimetype* a_mtype = shitvec_get(&mtypes, j); + struct req_mimetype* a_mtype = vec_get(&mtypes, j); if (strcmp(a_mtype->item, "gzip") == 0) { resp_add_hdr(&r, "Content-Encoding", "gzip"); buf = gzip_compress(buf, &bufsize); @@ -152,7 +152,7 @@ response_t make_response (request_t* req, int pfd) { strcpy(req->path, mapped_path); } - if (shitvec_check(&paths, req->path, (sv_cmp_t)strcmp) == -1) { + if (vec_check(&paths, req->path, (sv_cmp_t)strcmp) == -1) { return serve_error(NotFound); } @@ -192,7 +192,7 @@ void* handle_conn(int ns, int pfd) { } } -int list_files_sv(shitvec_t* sv, char* base) { +int list_files_sv(vec_t* sv, char* base) { char path[MAX_PATH_LEN] = "/"; struct dirent* dp; DIR* dir = opendir(base); @@ -203,7 +203,7 @@ int list_files_sv(shitvec_t* sv, char* base) { strcpy(path+1, base); strcat(path, "/"); strcat(path, dp->d_name); - shitvec_push(sv, strchr(path+1, '/')); + vec_push(sv, strchr(path+1, '/')); list_files_sv(sv, path+1); } } @@ -247,7 +247,7 @@ int main() { name.sin_port = htons(portnum); } - paths = shitvec_new(MAX_PATH_LEN); + paths = vec_new(MAX_PATH_LEN); path_redirs = hashmap_new(MAX_PATH_LEN, MAX_PATH_LEN); path_redirs.vark = true; hashmap_set(&path_redirs, "/", "/index.html"); @@ -266,7 +266,7 @@ int main() { int namelen; struct sockaddr_in client; - shitvec_t conns = shitvec_new(sizeof(struct conn_ctxt)); + vec_t conns = vec_new(sizeof(struct conn_ctxt)); while (true) { int* ptr = channel_try_recv(&listen_chan); if (ptr != NULL) { @@ -281,15 +281,15 @@ int main() { exit(0); } struct conn_ctxt ctxt = {.fd = pfds[0], .pid = pid }; - shitvec_push(&conns, &ctxt); + vec_push(&conns, &ctxt); } for (int i = 0; i < conns.vec_sz; i++) { - struct conn_ctxt* ctxt = shitvec_get(&conns, i); + struct conn_ctxt* ctxt = vec_get(&conns, i); char msg[8] = {0}; if (read(ctxt->fd, &msg, 8) != 8 || strcmp(msg, "profile") != 0) continue; struct profile_node prof_res = profile_res_new(); while(true) { - shitvec_t stack = profile(ctxt->pid); + vec_t stack = profile(ctxt->pid); profile_proc_stack(&prof_res, &stack); usleep(3); if (read(ctxt->fd, &msg, 5) == 5 && strcmp(msg, "stop") == 0) break; diff --git a/http/request.c b/http/request.c @@ -26,12 +26,12 @@ enum http_method method_enum(char* p) { /* struct parse_qvals_res { */ /* enum parse_qval_err err; */ /* union { */ -/* shitvec_t items; */ +/* vec_t items; */ /* } data; */ /* }; */ -/* shitvec_t parse_qvalues(char* str) { */ +/* vec_t parse_qvalues(char* str) { */ /* } */ @@ -57,8 +57,8 @@ int cmp_r_mimetype(const void* a, const void* b) { } // TODO handle parse errors -shitvec_t hdr_parse_accept(char* val) { - shitvec_t mimetypes = shitvec_new(sizeof(struct req_mimetype)); +vec_t hdr_parse_accept(char* val) { + vec_t mimetypes = vec_new(sizeof(struct req_mimetype)); char* start = strtok(val, ","); char* next; do { @@ -76,9 +76,9 @@ shitvec_t hdr_parse_accept(char* val) { if (qptr != NULL) strncpy(mtype.item, start, qptr-start); else if (next != NULL) strncpy(mtype.item, start, next-start); else strcpy(mtype.item, start); - shitvec_push(&mimetypes, &mtype); + vec_push(&mimetypes, &mtype); } while ((start = next)); - shitvec_sort(&mimetypes, cmp_r_mimetype); + vec_sort(&mimetypes, cmp_r_mimetype); return mimetypes; } @@ -142,22 +142,22 @@ void test_method_str_to_enum() { void test_hdr_parse_accept() { char hdr[MAX_HEADER_VALUE] = "text/html,application/xml;q=0.9,image/webp,*/*;q=0.8"; - shitvec_t mtypes = hdr_parse_accept(hdr); + vec_t mtypes = hdr_parse_accept(hdr); assert_size_eq(mtypes.vec_sz, 4); - struct req_mimetype* mtype = shitvec_get(&mtypes, 0); + struct req_mimetype* mtype = vec_get(&mtypes, 0); assert_str_eq("text/html", mtype->item); assert_float_eq(1.0, mtype->q); - mtype = shitvec_get(&mtypes, 1); + mtype = vec_get(&mtypes, 1); assert_str_eq("image/webp", mtype->item); assert_float_eq(1.0, mtype->q); - mtype = shitvec_get(&mtypes, 2); + mtype = vec_get(&mtypes, 2); assert_str_eq("application/xml", mtype->item); assert_float_eq(0.9, mtype->q); - mtype = shitvec_get(&mtypes, 3); + mtype = vec_get(&mtypes, 3); assert_str_eq("*/*", mtype->item); assert_float_eq(0.8, mtype->q); } diff --git a/http/request.h b/http/request.h @@ -1,7 +1,7 @@ #ifndef REQUEST_H #define REQUEST_H -#include "../utils/shitvec.h" +#include "../utils/vec.h" #include "../utils/hashmap.h" enum http_method { @@ -49,7 +49,7 @@ struct req_mimetype { /* char value[MAX_HEADER_VALUE]; */ /* } header_line_t; */ -shitvec_t hdr_parse_accept(char* val); +vec_t hdr_parse_accept(char* val); typedef struct request { char* buf; diff --git a/phf.py b/phf.py @@ -1,36 +1,42 @@ import random -inputs = ["GET", "HEAD", "POST", "PUT", "DELETE", - "CONNECT", "OPTIONS", "TRACE"] +# inputs = ["GET", "HEAD", "POST", "PUT", "DELETE", +# "CONNECT", "OPTIONS", "TRACE"] -int_inputs = [int.from_bytes(bytes(i, 'ascii'), 'little') for i in inputs] +# int_inputs = [int.from_bytes(bytes(i, 'ascii'), 'little') for i in inputs] -answers = list(range(8)) +# answers = list(range(8)) + +inps = [random.randrange(2**32) for i in range(100000)] def is_phf(h, inputs): return len({h(x) for x in inputs}) == len(inputs) -print(next(m for m in range(9, 2**32) if is_phf(lambda x: x % m, int_inputs))) +def colls(h, inputs): + return len({h(x) for x in inputs}) + +# print(next(m for m in range(9, 2**32) if is_phf(lambda x: x % m, int_inputs))) def h(x, c): m = (x * c) % 2**32 - return m >> 28 + return m -out = [0]*8 -idxs = list(h(x, 0x1b8b6e6d) for x in int_inputs) +# out = [0]*8 +# idxs = list(h(x, 0x1b8b6e6d) for x in int_inputs) -for i, idx in enumerate(idxs): - out[idx] = answers[i] +# for i, idx in enumerate(idxs): +# out[idx] = answers[i] -print([inputs[i] for i in out]) -print(list(out[h(x, 0x1b8b6e6d)] for x in int_inputs)) +# print([inputs[i] for i in out]) +# print(list(out[h(x, 0x1b8b6e6d)] for x in int_inputs)) -# best = float('inf') -# while best >= len(int_inputs): -# c = random.randrange(2**32) -# max_idx = max(h(x, c) for x in int_inputs) -# if max_idx < best and is_phf(lambda x: h(x, c), int_inputs): -# print(max_idx, hex(c)) -# best = max_idx +best = float('-inf') +while best < len(inps): + c = random.randrange(2**32) + # max_idx = max(h(x, c) for x in int_inputs) + cls = colls(lambda x: h(x, c), inps) + if cls > best: + print(cls, hex(c)) + best = cls diff --git a/utils/html.c b/utils/html.c @@ -3,9 +3,9 @@ html_t html_new() { html_t out; - out._buf = shitvec_new(sizeof(char)); + out._buf = vec_new(sizeof(char)); html_body_t body; - body.content = shitvec_new(sizeof(html_fc_t)); + body.content = vec_new(sizeof(html_fc_t)); out.body = body; return out; } @@ -25,12 +25,12 @@ html_fc_t html_h1_new(char* content) { } void html_body_add(html_body_t* body, html_fc_t fc) { - shitvec_push(&body->content, &fc); + vec_push(&body->content, &fc); } -void c_sv_pushs(shitvec_t* sv, char* str) { +void c_sv_pushs(vec_t* sv, char* str) { for (int i = 0; str[i] != '\0'; i++) { - shitvec_push(sv, &str[i]); + vec_push(sv, &str[i]); } } @@ -38,7 +38,7 @@ char* html_render(html_t* html) { c_sv_pushs(&html->_buf, "<!DOCTYPE html><html>"); c_sv_pushs(&html->_buf, "<body>"); for (int i = 0; i < html->body.content.vec_sz; i++) { - html_fc_t* elem = shitvec_get(&html->body.content, i); + html_fc_t* elem = vec_get(&html->body.content, i); switch (elem->type) { case HTML_TEXT: @@ -58,7 +58,7 @@ char* html_render(html_t* html) { } c_sv_pushs(&html->_buf, "</body>"); c_sv_pushs(&html->_buf, "</html>"); - shitvec_push(&html->_buf, "\0"); + vec_push(&html->_buf, "\0"); return html->_buf.arr; } diff --git a/utils/html.h b/utils/html.h @@ -1,7 +1,7 @@ #ifndef HTML_H #define HTML_H -#include "shitvec.h" +#include "vec.h" enum html_fc_type { HTML_TEXT, @@ -29,15 +29,15 @@ typedef struct base { } html_base_t; typedef struct head { - shitvec_t meta; + vec_t meta; } html_head_t; typedef struct body { - shitvec_t content; + vec_t content; } html_body_t; typedef struct html { - shitvec_t _buf; + vec_t _buf; html_body_t body; } html_t; diff --git a/utils/profile.c b/utils/profile.c @@ -19,8 +19,8 @@ #include "log.h" #include "profile.h" -shitvec_t profile(pid_t tid) { - shitvec_t stack = shitvec_new(MAX_SYMLEN); +vec_t profile(pid_t tid) { + vec_t stack = vec_new(MAX_SYMLEN); errno = 0; ptrace(PTRACE_ATTACH, tid); kill(tid, SIGSTOP); @@ -33,7 +33,7 @@ shitvec_t profile(pid_t tid) { unw_word_t offset; char fname[MAX_SYMLEN] = {0}; int resp = unw_get_proc_name(&c, fname, sizeof(fname), &offset); - shitvec_push(&stack, fname); + vec_push(&stack, fname); } while(unw_step(&c) > 0); _UPT_resume(as, &c, ui); _UPT_destroy(ui); @@ -45,7 +45,7 @@ shitvec_t profile(pid_t tid) { struct profile_node profile_node_new(char* name) { struct profile_node out = { - .children = shitvec_new(sizeof(struct profile_node)), + .children = vec_new(sizeof(struct profile_node)), .samples = 0, .symbol = {0} }; @@ -63,18 +63,18 @@ int cmp_prof_node(void* _a, void* _b) { return strcmp(a->symbol, b->symbol); } -void profile_proc_stack(struct profile_node* prof_res, shitvec_t* stack) { +void profile_proc_stack(struct profile_node* prof_res, vec_t* stack) { if (stack->vec_sz == 0) return; struct profile_node* node = prof_res; for (int i = stack->vec_sz-1; i > 0; i--) { - char* sym = shitvec_get(stack, i); - int index = shitvec_check(&node->children, sym, cmp_prof_node); + char* sym = vec_get(stack, i); + int index = vec_check(&node->children, sym, cmp_prof_node); if (index == -1) { struct profile_node new = profile_node_new(sym); - shitvec_push(&node->children, &new); + vec_push(&node->children, &new); index = node->children.vec_sz - 1; } - node = shitvec_get(&node->children, index); + node = vec_get(&node->children, index); node->samples += 1; } } @@ -86,6 +86,6 @@ void profile_dump(struct profile_node* prof_res, int indent) { printf("%s (%d) \n", node->symbol, node->samples); } for (int i = 0; i < node->children.vec_sz; i++) { - profile_dump(shitvec_get(&node->children, i), indent+1); + profile_dump(vec_get(&node->children, i), indent+1); } } diff --git a/utils/profile.h b/utils/profile.h @@ -3,19 +3,19 @@ #include <sys/types.h> -#include "shitvec.h" +#include "vec.h" #define MAX_SYMLEN 32 -shitvec_t profile(pid_t pid); +vec_t profile(pid_t pid); struct profile_node { char symbol[MAX_SYMLEN]; unsigned int samples; - shitvec_t children; + vec_t children; }; struct profile_node profile_res_new(); -void profile_proc_stack(struct profile_node* prof_res, shitvec_t* stack); +void profile_proc_stack(struct profile_node* prof_res, vec_t* stack); void profile_dump(struct profile_node* prof_res, int indent); #endif diff --git a/utils/shitvec.c b/utils/shitvec.c @@ -1,73 +0,0 @@ -#include <stdlib.h> -#include <string.h> - -#include "shitvec.h" - -shitvec_t shitvec_new(size_t e_sz) { - shitvec_t sv; - sv.alloc_sz = SHITVEC_INIT_SZ; - sv.vec_sz = 0; - sv.e_sz = e_sz; - sv.arr = malloc(sv.alloc_sz); - memset(sv.arr, 0, sv.alloc_sz); - return sv; -} - -void* shitvec_get(shitvec_t* sv, size_t index) { - if (index > sv->vec_sz) return 0x0; - return sv->arr+(sv->e_sz * index); -} - -void* shitvec_last(shitvec_t* sv) { - return shitvec_get(sv, sv->vec_sz-1); -} - -void shitvec_push(shitvec_t* sv, void* item) { - // FIXME sketchy af - if ((sv->arr+(2 * sv->e_sz * sv->vec_sz)) > sv->arr+sv->alloc_sz) { - sv->arr = realloc(sv->arr, sv->alloc_sz * 2); - sv->alloc_sz *= 2; - } - memcpy(sv->arr+(sv->vec_sz * sv->e_sz), item, sv->e_sz); - sv->vec_sz += 1; -} - -void shitvec_subpush(shitvec_t* sv, void* item, size_t sz) { - sv->vec_sz += 1; - if ((sv->arr+(sv->e_sz * sv->vec_sz)) > sv->arr+sv->alloc_sz) { - sv->arr = realloc(sv->arr, sv->alloc_sz * 2); - } - memcpy(sv->arr+(sv->vec_sz * sv->e_sz), item, sz); -} - -int shitvec_check(shitvec_t* sv, void* item, sv_cmp_t cmp) { - for (size_t i = 0; i < sv->vec_sz; i++) { - if (cmp(sv->arr+(i*sv->e_sz), item) == 0) { - return i; - } - } - return -1; -} - -void shitvec_sort(shitvec_t* sv, int(*cmp)(const void*, const void*)) { - qsort(sv->arr, sv->vec_sz, sv->e_sz, cmp); -} - -void shitvec_free(shitvec_t* sv) { - free(sv->arr); -} - -#ifdef TEST -#include "../test.h" - -void test_shitvec_sanity() { - shitvec_t sv = shitvec_new(8); - shitvec_push(&sv, "whee"); - shitvec_push(&sv, "whoo"); - assert_str_eq("whee", shitvec_get(&sv, 0)); - assert_str_eq("whoo", shitvec_get(&sv, 1)); - assert_size_eq(2, sv.vec_sz); - assert_size_eq(8, sv.e_sz); - assert_bool(shitvec_check(&sv, "whoo", (sv_cmp_t)strcmp)); -}; -#endif diff --git a/utils/shitvec.h b/utils/shitvec.h @@ -1,29 +0,0 @@ -#ifndef SHITVEC_H -#define SHITVEC_H - -#include <stddef.h> -#include <stdbool.h> - -#define SHITVEC_INIT_SZ 1024 - -typedef struct shitvec { - void* arr; - size_t e_sz; - size_t alloc_sz; - size_t vec_sz; -} shitvec_t; - -typedef int(*sv_cmp_t)(void*, void*); - -shitvec_t shitvec_new(size_t e_sz); -void* shitvec_get(shitvec_t* sv, size_t index); -void* shitvec_last(shitvec_t* sv); -void shitvec_push(shitvec_t* sv, void* item); -void shitvec_subpush(shitvec_t* sv, void* item, size_t sz); -int shitvec_check(shitvec_t* sv, void* item, sv_cmp_t cmp); -void shitvec_sort(shitvec_t* sv, int(*cmp)(const void*, const void*)); -void shitvec_free(shitvec_t* sv); - -#endif - - diff --git a/utils/sync.c b/utils/sync.c @@ -5,14 +5,14 @@ channel_t channel_new(size_t msg_sz) { channel_t out; out.msg_sz = msg_sz; pthread_mutex_init(&out.mutex, NULL); - out.queue = shitvec_new(msg_sz); + out.queue = vec_new(msg_sz); out.sz = 0; return out; } void channel_push(channel_t* chan, void* msg) { pthread_mutex_lock(&chan->mutex); - shitvec_push(&chan->queue, msg); + vec_push(&chan->queue, msg); pthread_mutex_unlock(&chan->mutex); __atomic_fetch_add(&chan->sz, 1, __ATOMIC_RELAXED); } @@ -20,7 +20,7 @@ void channel_push(channel_t* chan, void* msg) { void* channel_pop(channel_t* chan) { void* out; pthread_mutex_lock(&chan->mutex); - out = shitvec_get(&chan->queue, chan->queue.vec_sz-1); + out = vec_get(&chan->queue, chan->queue.vec_sz-1); chan->queue.vec_sz -= 1; pthread_mutex_unlock(&chan->mutex); __atomic_fetch_sub(&chan->sz, 1, __ATOMIC_RELAXED); diff --git a/utils/sync.h b/utils/sync.h @@ -2,11 +2,11 @@ #define UTIL_SYNC_H #include <pthread.h> -#include "shitvec.h" +#include "vec.h" typedef struct channel { pthread_mutex_t mutex; - shitvec_t queue; + vec_t queue; size_t msg_sz; size_t sz; } channel_t;