diff --git a/CONFIG.h b/CONFIG.h index 1caa56e..5dc665b 100644 --- a/CONFIG.h +++ b/CONFIG.h @@ -7,4 +7,6 @@ # define CONFIG_LISTEN_URL "http://localhost:5000" #endif +#define BUNDLE_ZIP_COMPRESSION 10 + #endif // CONFIG_H_ diff --git a/baked.c b/baked.c index e6eba49..79fee55 100644 --- a/baked.c +++ b/baked.c @@ -3,10 +3,11 @@ #include "gebs/gebs.h" #include "incbin/incbin.h" #include "stb/stb_ds.h" +#include "zip.h" #include "baked.h" #include "locked.h" -#include "zip.h" +#include "CONFIG.h" INCBIN(bundle_zip, "./bundle.zip"); @@ -37,7 +38,7 @@ void init_baked_resources(void) { lockx(&baked_resources); - struct zip_t *zip = zip_stream_open(bundle_zip_data, bundle_zip_size, ZIP_DEFAULT_COMPRESSION_LEVEL, 'r'); + struct zip_t *zip = zip_stream_open(bundle_zip_data, bundle_zip_size, BUNDLE_ZIP_COMPRESSION, 'r'); size_t n = zip_entries_total(zip); for (size_t i = 0; i < n; i++) { zip_entry_openbyindex(zip, i); @@ -73,7 +74,6 @@ bool get_baked_resource_path(char *key, char *buf, size_t size) if (shgeti(baked_resources.value, key) != -1) { Baked_Resource_Value brv = shget(baked_resources.value, key); snprintf(buf, size, "/proc/%d/fd/%d", getpid(), brv.memfd); - unlockx(&baked_resources); return true; } return false; diff --git a/build.c b/build.c index bbe3971..bba40ea 100644 --- a/build.c +++ b/build.c @@ -3,6 +3,7 @@ #define GEBS_IMPLEMENTATION #include "gebs/gebs.h" #include "./zip/src/zip.c" +#include "CONFIG.h" char *prog = NULL; @@ -44,7 +45,6 @@ int main(int argc, char ** argv) "./routes.h", "./baked.c", "./baked.h", - "./clonestr.h", "./commit.h", "./timer.c", "./timer.h", @@ -102,7 +102,7 @@ int main(int argc, char ** argv) CMD("cc", "-DHAVE_STRDUP", "-DHAVE_FNMATCH_H", "-o", "gpp1", "gpp/gpp.c"); } - struct zip_t *zip = zip_open("./bundle.zip", ZIP_DEFAULT_COMPRESSION_LEVEL, 'w'); + struct zip_t *zip = zip_open("./bundle.zip", BUNDLE_ZIP_COMPRESSION, 'w'); defer { zip_close(zip); } for (size_t i = 0; i < sizeof(bundle_zip_deps)/sizeof(bundle_zip_deps[0]); i++) { @@ -125,11 +125,13 @@ int main(int argc, char ** argv) #define TARGET "-o", "aboba" #if MY_DEBUG #define CFLAGS "-fsanitize=address", "-fPIC", "-ggdb" - #define DEFINES "-DMY_DEBUG=1", "-D_GNU_SOURCE", "-DGEBS_NO_PREFIX", "-DINCBIN_PREFIX=", "-DINCBIN_STYLE=INCBIN_STYLE_SNAKE" + #define DEFINES "-DMY_DEBUG=1", "-D_GNU_SOURCE", "-DGEBS_NO_PREFIX", "-DINCBIN_PREFIX=", "-DINCBIN_STYLE=INCBIN_STYLE_SNAKE", \ + "-DGEBS_ENABLE_PTHREAD_FEATURES" #define EXTRA_SOURCES "./cJSON/cJSON.c", "./zip/src/zip.c", "./md5-c/md5.c" #else #define CFLAGS "-fPIC" - #define DEFINES "-DMY_DEBUG=0", "-D_GNU_SOURCE", "-DGEBS_NO_PREFIX", "-DINCBIN_PREFIX=", "-DINCBIN_STYLE=INCBIN_STYLE_SNAKE" + #define DEFINES "-DMY_DEBUG=0", "-D_GNU_SOURCE", "-DGEBS_NO_PREFIX", "-DINCBIN_PREFIX=", "-DINCBIN_STYLE=INCBIN_STYLE_SNAKE", \ + "-DGEBS_ENABLE_PTHREAD_FEATURES" #define EXTRA_SOURCES "./cJSON/cJSON.c", "./zip/src/zip.c" #endif #define SOURCES "./main.c", "./routes.c", "./baked.c", "./timer.c" diff --git a/clonestr.h b/clonestr.h index d11f4e1..2aaf5aa 100644 --- a/clonestr.h +++ b/clonestr.h @@ -1,11 +1,5 @@ #ifndef CLONESTR_H_ #define CLONESTR_H_ -#define clonestr(str) \ -({ \ - char *__p = malloc(strlen((str))+1); \ - strcpy(__p, (str)); \ - (__p); \ -}) #endif // CLONESTR_H_ diff --git a/gebs b/gebs index 596bb1e..db8389f 160000 --- a/gebs +++ b/gebs @@ -1 +1 @@ -Subproject commit 596bb1ef766e63b7acf06deb46868786463cbe5b +Subproject commit db8389f7d5e95d9b6ac49c42a218f56d444201f4 diff --git a/locked.h b/locked.h index 5e892a7..5871582 100644 --- a/locked.h +++ b/locked.h @@ -3,7 +3,7 @@ #include -#define locked_init(x) { .value = (x), .lock = PTHREAD_MUTEX_INITIALIZER } +#define locked_init(x) { .value = x, .lock = PTHREAD_MUTEX_INITIALIZER } #define locked(T) struct { T value; pthread_mutex_t lock; } #define lockx(x) pthread_mutex_lock(&(x)->lock) diff --git a/main.c b/main.c index 4b7111d..92d27db 100644 --- a/main.c +++ b/main.c @@ -9,23 +9,39 @@ #include "mongoose/mongoose.h" #define STB_DS_IMPLEMENTATION #include "stb/stb_ds.h" +#include "md5-c/md5.h" #include "routes.h" #include "baked.h" #include "timer.h" #include "CONFIG.h" -#include "clonestr.h" #include "locked.h" static locked(Route *) route_hashtable = locked_init(nil); static locked(char *) baked_dump_path = locked_init(nil); +char *clonestr_alloc(Allocator *alloc, char *s) +{ + char *p = gebs_malloc(alloc, strlen(s)+1); + strcpy(p, s); + return p; +} + +void *zmalloc_alloc(Allocator *alloc, size_t size) +{ + void *p = gebs_malloc(alloc, size); + memset(p, 0, size); + return p; +} + void run_in_thread(void *(*f)(void *), void *p) { pthread_t tid = 0; + pthread_attr_t attr; pthread_attr_init(&attr); pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED); + pthread_create(&tid, &attr, f, p); pthread_attr_destroy(&attr); } @@ -33,60 +49,61 @@ void run_in_thread(void *(*f)(void *), void *p) void *route_thread_function(void *param) { Route_Thread_Data *data = (Route_Thread_Data *)param; + Arena *arena = data->arena; struct mg_http_message http_msg = {0}; int r = mg_http_parse(data->message.buf, data->message.len, &http_msg); if (r <= 0) { - Route_Result result = {0}; - result.status_code = 400; - result.type = ROUTE_RESULT_DYNAMIC; - /* list_append(&result.headers, clonestr("Content-Type: text/plain")); */ - sb_append_nstr(&result.body, "Could not parse HTTP request"); - sb_finish(&result.body); + Route_Result *result = zmalloc_alloc((Allocator *)arena, sizeof(*result)); + result->arena = arena; + result->status_code = 400; + result->type = ROUTE_RESULT_DYNAMIC; + sb_append_nstr_alloc(arena, &result->body, "Could not parse HTTP request"); + sb_finish_alloc(arena, &result->body); mg_wakeup(data->mgr, data->conn_id, &result, sizeof(result)); free(data->message.buf); free(data); - return nil; + pthread_exit(nil); + } else { + if (mg_match(http_msg.uri, mg_str("/bakedres/*"), nil)) { + Route_Result *result = zmalloc_alloc((Allocator *)arena, sizeof(*result)); + result->arena = arena; + result->type = ROUTE_RESULT_STATIC; + + char *p = gebs_malloc(arena, http_msg.uri.len+1); + strncpy(p, http_msg.uri.buf, http_msg.uri.len); + p[http_msg.uri.len] = 0; + + char *file = basename(p); + char *full_path = gebs_malloc(arena, PATH_MAX); + + lockx(&baked_dump_path); + snprintf(full_path, PATH_MAX, "%s/%s", baked_dump_path.value, file); + unlockx(&baked_dump_path); + + sb_append_nstr_alloc(arena, &result->body, full_path); + sb_finish_alloc(arena, &result->body); + mg_wakeup(data->mgr, data->conn_id, &result, sizeof(result)); + free(data->message.buf); + free(data); + pthread_exit(nil); + } else { + char key[MG_PATH_MAX] = {0}; + strncpy(key, http_msg.uri.buf, http_msg.uri.len); + lockx(&route_hashtable); + ssize_t idx = shgeti(route_hashtable.value, key); + + Route_Result *result = zmalloc_alloc((Allocator *)arena, sizeof(*result)); + result->arena = arena; + route_hashtable.value[idx].value((Allocator *)arena, &http_msg, result, route_hashtable.value[idx].context_data); + unlockx(&route_hashtable); + mg_wakeup(data->mgr, data->conn_id, &result, sizeof(result)); + + free(data->message.buf); + free(data); + pthread_exit(nil); + } } - - if (mg_match(http_msg.uri, mg_str("/bakedres/*"), nil)) { - Route_Result result = {0}; - result.type = ROUTE_RESULT_STATIC; - - char *p = malloc(http_msg.uri.len+1); - strncpy(p, http_msg.uri.buf, http_msg.uri.len); - p[http_msg.uri.len] = 0; - - char *file = basename(p); - char *full_path = malloc(PATH_MAX); - - lockx(&baked_dump_path); - snprintf(full_path, PATH_MAX, "%s/%s", baked_dump_path.value, file); - unlockx(&baked_dump_path); - - sb_append_nstr(&result.body, full_path); - sb_finish(&result.body); - free(full_path); - free(p); - mg_wakeup(data->mgr, data->conn_id, &result, sizeof(result)); - free(data->message.buf); - free(data); - return nil; - } - - char key[MG_PATH_MAX] = {0}; - strncpy(key, http_msg.uri.buf, http_msg.uri.len); - lockx(&route_hashtable); - ssize_t idx = shgeti(route_hashtable.value, key); - - Route_Result result = {0}; - route_hashtable.value[idx].value(&http_msg, &result, route_hashtable.value[idx].context_data); - unlockx(&route_hashtable); - mg_wakeup(data->mgr, data->conn_id, &result, sizeof(result)); - - free(data->message.buf); - free(data); - return nil; } @@ -99,18 +116,20 @@ void event_handler(struct mg_connection *conn, int ev, void *ev_data) data->message = mg_strdup(msg->message); data->conn_id = conn->id; data->mgr = conn->mgr; + data->arena = malloc(sizeof(*data->arena)); + *data->arena = arena_get(); run_in_thread(&route_thread_function, data); } else if (ev == MG_EV_WAKEUP) { struct mg_str *data = (struct mg_str *)ev_data; - Route_Result *result = (Route_Result *)data->buf; - + Route_Result *result = *(Route_Result **)data->buf; + Arena *arena = result->arena; + Gebs_String_Builder sb = {0}; - defer { sb_free(&sb); } - nsl_join(&result->headers, &sb, "\r\n"); + nsl_join_alloc(arena, &result->headers, &sb, "\r\n"); if (result->headers.count > 0) { - sb_append_nstr(&sb, "\r\n"); + sb_append_nstr_alloc(arena, &sb, "\r\n"); } - sb_finish(&sb); + sb_finish_alloc(arena, &sb); if (result->type == ROUTE_RESULT_DYNAMIC) { mg_http_reply(conn, result->status_code, sb.items, "%s", result->body.items); @@ -119,11 +138,8 @@ void event_handler(struct mg_connection *conn, int ev, void *ev_data) mg_http_serve_file(conn, ev_data, path, &(struct mg_http_serve_opts){0}); } - for (size_t i = 0; i < result->headers.count; i++) { - free(result->headers.items[i]); - } - list_free(&result->headers); - sb_free(&result->body); + arena_destroy(arena); + free(arena); } } @@ -143,11 +159,11 @@ void init_route_hashtable(void) { lockx(&route_hashtable); shdefault(route_hashtable.value, &route_page_not_found); - shput(route_hashtable.value, clonestr("/"), &route_home); - shput(route_hashtable.value, clonestr("/page-missing"), &route_page_not_found); - shput(route_hashtable.value, clonestr("/blog"), &route_blog); + shput(route_hashtable.value, clonestr_alloc(&default_allocator, "/"), &route_home); + shput(route_hashtable.value, clonestr_alloc(&default_allocator, "/page-missing"), &route_page_not_found); + shput(route_hashtable.value, clonestr_alloc(&default_allocator, "/blog"), &route_blog); #if MY_DEBUG - shput(route_hashtable.value, clonestr("/build-id"), &route_build_id); + shput(route_hashtable.value, clonestr_alloc(&default_allocator, "/build-id"), &route_build_id); #endif baked_resource_each(&route_hashtable_put_blogs, nil); @@ -250,13 +266,18 @@ void populate_baked_dump(char *baked_dump) unlock_baked_resources(); } -volatile bool alive = true; +volatile sig_atomic_t alive = true; void graceful_shutdown(int no) { alive = false; } int main(int argc, char ** argv) { - signal(SIGINT, &graceful_shutdown); + struct sigaction sa; + sa.sa_handler = &graceful_shutdown; + sa.sa_flags = 0; + sigemptyset(&sa.sa_mask); + sigaction(SIGINT, &sa, nil); + start_timer(); init_baked_resources(); diff --git a/routes.c b/routes.c index e38ca62..b5c1691 100644 --- a/routes.c +++ b/routes.c @@ -7,10 +7,11 @@ #include "routes.h" #include "baked.h" -#include "clonestr.h" #include "commit.h" #include "timer.h" +extern char *clonestr_alloc(Allocator *alloc, char *s); + #define INTERNAL_SERVER_ERROR_MSG "Internal server error ;(. Try again later..." #define META_TAGS \ @@ -19,65 +20,61 @@ "" \ "" -void make_internal_server_error(Route_Result *result) +void make_application_json(Allocator *alloc, Route_Result *result, int code, cJSON *root) { - result->status_code = 500; - result->type = ROUTE_RESULT_DYNAMIC; - list_append(&result->headers, "Content-Type: text/plain"); - sb_append_nstr(&result->body, INTERNAL_SERVER_ERROR_MSG); - sb_finish(&result->body); -} + size_t buf_size = 512; + char *buf = gebs_malloc(alloc, buf_size); -void make_application_json(Route_Result *result, int code, cJSON *root) -{ - char *root_text = cJSON_PrintUnformatted(root); - defer { free(root_text); } + cJSON_PrintPreallocated(root, buf, buf_size, false); result->status_code = code; result->type = ROUTE_RESULT_DYNAMIC; - list_append(&result->headers, clonestr("Content-Type: application/json")); - sb_append_nstr(&result->body, root_text); - sb_finish(&result->body); + list_append(&result->headers, clonestr_alloc(alloc, "Content-Type: application/json")); + sb_append_nstr_alloc(alloc, &result->body, buf); + sb_finish_alloc(alloc, &result->body); } -void make_text(Route_Result *result, char *subtype, int code, char *in) +void make_text(Allocator *alloc, Route_Result *result, char *subtype, int code, char *in) { - char type[100]; - snprintf(type, sizeof(type), "Content-Type: text/%s", subtype); - result->status_code = code; result->type = ROUTE_RESULT_DYNAMIC; - list_append(&result->headers, clonestr(type)); - sb_append_nstr(&result->body, in); + list_append_alloc(alloc, &result->headers, + clonestr_alloc(alloc, fmt("Content-Type: text/%s", subtype))); + sb_append_nstr_alloc(alloc, &result->body, in); sb_finish(&result->body); } -bool gpp_run(char *path, NString_List *env, String_Builder *out) +void make_internal_server_error(Allocator *alloc, Route_Result *result) +{ + make_text(alloc, result, "plain", 500, INTERNAL_SERVER_ERROR_MSG); +} + +bool gpp_run(Allocator *alloc, char *path, NString_List *env, String_Builder *out) { Cmd cmd = {0}; - defer { cmd_free(&cmd); } char gpp1[PATH_MAX]; if (!get_baked_resource_path("gpp1", gpp1, sizeof(gpp1))) { return false; } - cmd_append(&cmd, gpp1); - cmd_append(&cmd, "-H"); - cmd_append(&cmd, "-x"); - cmd_append(&cmd, "--nostdinc"); - cmd_append(&cmd, path); + cmd_append_alloc(alloc, &cmd, gpp1); + cmd_append_alloc(alloc, &cmd, "-H"); + cmd_append_alloc(alloc, &cmd, "-x"); + cmd_append_alloc(alloc, &cmd, "--nostdinc"); + cmd_append_alloc(alloc, &cmd, path); for (size_t i = 0; i < env->count; i++) { - cmd_append(&cmd, env->items[i]); + cmd_append_alloc(alloc, &cmd, env->items[i]); } - return cmd_run_collect(&cmd, out) == 0; + return cmd_run_collect_alloc(alloc, &cmd, out) == 0; } #if MY_DEBUG -void route_build_id(struct mg_http_message *msg, Route_Result *result, void *context_data) +void route_build_id(Allocator *alloc, struct mg_http_message *msg, Route_Result *result, void *context_data) { + // TODO: Somehow use our arena in here. This will require a slight rework of the way cJSON works. cJSON *root = cJSON_CreateObject(); defer { cJSON_Delete(root); } @@ -85,226 +82,215 @@ void route_build_id(struct mg_http_message *msg, Route_Result *result, void *con uchar md5_buf[16]; md5String(time, md5_buf); String_Builder sb = {0}; - defer { sb_free(&sb); } for (size_t i = 0; i < 16; i++) { - sb_append_nstr(&sb, fmt("%02x", md5_buf[i])); + sb_append_nstr_alloc(alloc, &sb, clonestr_alloc(alloc, fmt("%02x", md5_buf[i]))); } - sb_finish(&sb); + sb_finish_alloc(alloc, &sb); cJSON_AddItemToObject(root, "build_id", cJSON_CreateString(sb.items)); - make_application_json(result, 200, root); + make_application_json(alloc, result, 200, root); } #endif -void route_page_not_found(struct mg_http_message *msg, Route_Result *result, void *context_data) +void route_page_not_found(Allocator *alloc, struct mg_http_message *msg, Route_Result *result, void *context_data) { lock_baked_resources(); defer { unlock_baked_resources(); } NString_List env = {0}; - defer { list_free(&env); } - list_append(&env, fmt("-DURL=%.*s", msg->uri.len, msg->uri.buf)); + list_append_alloc(alloc, &env, clonestr_alloc(alloc, fmt("-DURL=%.*s", msg->uri.len, msg->uri.buf))); String_Builder out = {0}; - defer { sb_free(&out); } char path[PATH_MAX] = {0}; if (!get_baked_resource_path("page-missing.html", path, sizeof(path))) { - make_internal_server_error(result); + make_internal_server_error(alloc, result); return; } - list_append(&env, fmt("-DCOMMIT=%s", COMMIT_STRING)); + list_append_alloc(alloc, &env, clonestr_alloc(alloc, fmt("-DCOMMIT=%s", COMMIT_STRING))); char timer[100]; get_timer_string(timer, sizeof(timer)); - list_append(&env, fmt("-DRUNNING_SINCE=%s", timer)); + list_append_alloc(alloc, &env, clonestr_alloc(alloc, fmt("-DRUNNING_SINCE=%s", timer))); - list_append(&env, fmt("-DMETA_TAGS=%s", META_TAGS)); + list_append_alloc(alloc, &env, clonestr_alloc(alloc, fmt("-DMETA_TAGS=%s", META_TAGS))); #if MY_DEBUG - list_append(&env, "-DHOTRELOAD"); + list_append_alloc(alloc, &env, "-DHOTRELOAD"); #endif - bool ok = gpp_run(path, &env, &out); - sb_finish(&out); + bool ok = gpp_run(alloc, path, &env, &out); + sb_finish_alloc(alloc, &out); if (!ok) { - make_internal_server_error(result); + make_internal_server_error(alloc, result); } else { - make_text(result, "html", 200, out.items); + make_text(alloc, result, "html", 200, out.items); } } -void route_home(struct mg_http_message *msg, Route_Result *result, void *context_data) +void route_home(Allocator *alloc, struct mg_http_message *msg, Route_Result *result, void *context_data) { lock_baked_resources(); defer { unlock_baked_resources(); } NString_List env = {0}; - defer { list_free(&env); } String_Builder out = {0}; - defer { sb_free(&out); } char path[PATH_MAX] = {0}; if (!get_baked_resource_path("home.html", path, sizeof(path))) { - make_internal_server_error(result); + make_internal_server_error(alloc, result); return; } - list_append(&env, fmt("-DCOMMIT=%s", COMMIT_STRING)); + list_append_alloc(alloc, &env, clonestr_alloc(alloc, fmt("-DCOMMIT=%s", COMMIT_STRING))); char timer[100]; get_timer_string(timer, sizeof(timer)); - list_append(&env, fmt("-DRUNNING_SINCE=%s", timer)); + list_append_alloc(alloc, &env, clonestr_alloc(alloc, fmt("-DRUNNING_SINCE=%s", timer))); - list_append(&env, fmt("-DMETA_TAGS=%s", META_TAGS)); + list_append_alloc(alloc, &env, clonestr_alloc(alloc, fmt("-DMETA_TAGS=%s", META_TAGS))); #if MY_DEBUG - list_append(&env, "-DHOTRELOAD"); + list_append_alloc(alloc, &env, "-DHOTRELOAD"); #endif - bool ok = gpp_run(path, &env, &out); - sb_finish(&out); + bool ok = gpp_run(alloc, path, &env, &out); + sb_finish_alloc(alloc, &out); if (!ok) { - make_internal_server_error(result); + make_internal_server_error(alloc, result); } else { - make_text(result, "html", 200, out.items); + make_text(alloc, result, "html", 200, out.items); } } -void route_generic_blog(struct mg_http_message *msg, Route_Result *result, void *context_data) +void route_generic_blog(Allocator *alloc, struct mg_http_message *msg, Route_Result *result, void *context_data) { lock_baked_resources(); defer { unlock_baked_resources(); } NString_List env = {0}; - defer { list_free(&env); } String_Builder out = {0}; - defer { sb_free(&out); } Baked_Resource *resource = (Baked_Resource *)context_data; char md_path[PATH_MAX] = {0}; if (!get_baked_resource_path(resource->key, md_path, sizeof(md_path))) { - make_internal_server_error(result); + make_internal_server_error(alloc, result); return; } - list_append(&env, fmt("-DCOMMIT=%s", COMMIT_STRING)); + list_append_alloc(alloc, &env, clonestr_alloc(alloc, fmt("-DCOMMIT=%s", COMMIT_STRING))); char timer[100]; get_timer_string(timer, sizeof(timer)); - list_append(&env, fmt("-DRUNNING_SINCE=%s", timer)); + list_append_alloc(alloc, &env, clonestr_alloc(alloc, fmt("-DRUNNING_SINCE=%s", timer))); - list_append(&env, fmt("-DMETA_TAGS=%s", META_TAGS)); + list_append_alloc(alloc, &env, clonestr_alloc(alloc, fmt("-DMETA_TAGS=%s", META_TAGS))); #if MY_DEBUG - list_append(&env, "-DHOTRELOAD"); + list_append_alloc(alloc, &env, "-DHOTRELOAD"); #endif String_Builder md = {0}; - defer { sb_free(&md); } if (!sb_read_file(&md, md_path)) { - make_internal_server_error(result); + make_internal_server_error(alloc, result); return; } String_Builder md_prepared = {0}; - defer { sb_free(&md_prepared); } for (size_t i = 0; i < md.count; i++) { char c = md.items[i]; switch (c) { - case '\"': sb_append_nstr(&md_prepared, "\\\""); break; - case '\'': sb_append_nstr(&md_prepared, "\\\'"); break; - case '\\': sb_append_nstr(&md_prepared, "\\\\"); break; - case '\a': sb_append_nstr(&md_prepared, "\\a"); break; - case '\b': sb_append_nstr(&md_prepared, "\\b"); break; - case '\r': sb_append_nstr(&md_prepared, "\\r"); break; - case '\n': sb_append_nstr(&md_prepared, "\\n"); break; - case '\t': sb_append_nstr(&md_prepared, "\\t"); break; + case '\"': sb_append_nstr_alloc(alloc, &md_prepared, "\\\""); break; + case '\'': sb_append_nstr_alloc(alloc, &md_prepared, "\\\'"); break; + case '\\': sb_append_nstr_alloc(alloc, &md_prepared, "\\\\"); break; + case '\a': sb_append_nstr_alloc(alloc, &md_prepared, "\\a"); break; + case '\b': sb_append_nstr_alloc(alloc, &md_prepared, "\\b"); break; + case '\r': sb_append_nstr_alloc(alloc, &md_prepared, "\\r"); break; + case '\n': sb_append_nstr_alloc(alloc, &md_prepared, "\\n"); break; + case '\t': sb_append_nstr_alloc(alloc, &md_prepared, "\\t"); break; default: if (iscntrl(md.items[i])) { - sb_append_nstr(&md_prepared, fmt("\\%03o", c)); + sb_append_nstr_alloc(alloc, &md_prepared, clonestr_alloc(alloc, fmt("\\%03o", c))); } else { - sb_append_char(&md_prepared, c); + sb_append_char_alloc(alloc, &md_prepared, c); } break; } } - sb_finish(&md_prepared); + sb_finish_alloc(alloc, &md_prepared); - list_append(&env, fmt("-DBLOG_POST_TITLE=%s", resource->key)); - list_append(&env, fmt("-DBLOG_POST_MARKDOWN=%s", md_prepared.items)); + list_append_alloc(alloc, &env, clonestr_alloc(alloc, fmt("-DBLOG_POST_TITLE=%s", resource->key))); + list_append_alloc(alloc, &env, clonestr_alloc(alloc, fmt("-DBLOG_POST_MARKDOWN=%s", md_prepared.items))); char tmpl_file[PATH_MAX] = {0}; if (!get_baked_resource_path("template-blog.html", tmpl_file, sizeof(tmpl_file))) { - make_internal_server_error(result); + make_internal_server_error(alloc, result); return; } - bool ok = gpp_run(tmpl_file, &env, &out); - sb_finish(&out); + bool ok = gpp_run(alloc, tmpl_file, &env, &out); + sb_finish_alloc(alloc, &out); if (!ok) { - make_internal_server_error(result); + make_internal_server_error(alloc, result); } else { - make_text(result, "html", 200, out.items); + make_text(alloc, result, "html", 200, out.items); } } void collect_blogs(Baked_Resource *resource, void *udata) { - struct { Arena *tmp; String_Builder *sb; } *ud = udata; + struct { Allocator *alloc; String_Builder *sb; } *ud = udata; if ((strlen(resource->key) >= strlen("blog-")) && strncmp(resource->key, "blog-", strlen("blog-")) == 0) { - sb_append_nstr_alloc(ud->tmp, ud->sb, fmt("
  • %s
  • ", resource->key, resource->key)); + sb_append_nstr_alloc(ud->alloc, ud->sb, + clonestr_alloc(ud->alloc, fmt("
  • %s
  • ", resource->key, resource->key))); } } -void route_blog(struct mg_http_message *msg, Route_Result *result, void *context_data) +void route_blog(Allocator *alloc, struct mg_http_message *msg, Route_Result *result, void *context_data) { + lock_baked_resources(); + defer { unlock_baked_resources(); } NString_List env = {0}; - defer { list_free(&env); } String_Builder out = {0}; - defer { sb_free(&out); } - - Arena tmp = arena_get(); - defer { arena_destroy(&tmp); } String_Builder sb = {0}; - struct { Arena *tmp; String_Builder *sb; } collect_blogs_data = { - .tmp = &tmp, + struct { Allocator *alloc; String_Builder *sb; } collect_blogs_data = { + .alloc = alloc, .sb = &sb, }; baked_resource_each(&collect_blogs, &collect_blogs_data); - sb_finish_alloc(&tmp, &sb); - list_append(&env, fmt("-DBLOG_POSTS=%s", sb.items)); + sb_finish_alloc(alloc, &sb); + list_append_alloc(alloc, &env, clonestr_alloc(alloc, fmt("-DBLOG_POSTS=%s", sb.items))); char path[PATH_MAX] = {0}; if (!get_baked_resource_path("blog.html", path, sizeof(path))) { - make_internal_server_error(result); + make_internal_server_error(alloc, result); return; } - list_append(&env, fmt("-DCOMMIT=%s", COMMIT_STRING)); + list_append_alloc(alloc, &env, clonestr_alloc(alloc, fmt("-DCOMMIT=%s", COMMIT_STRING))); char timer[100]; get_timer_string(timer, sizeof(timer)); - list_append(&env, fmt("-DRUNNING_SINCE=%s", timer)); + list_append_alloc(alloc, &env, clonestr_alloc(alloc, fmt("-DRUNNING_SINCE=%s", timer))); - list_append(&env, fmt("-DMETA_TAGS=%s", META_TAGS)); + list_append_alloc(alloc, &env, clonestr_alloc(alloc, fmt("-DMETA_TAGS=%s", META_TAGS))); #if MY_DEBUG - list_append(&env, "-DHOTRELOAD"); + list_append_alloc(alloc, &env, "-DHOTRELOAD"); #endif - bool ok = gpp_run(path, &env, &out); - sb_finish(&out); + bool ok = gpp_run(alloc, path, &env, &out); + sb_finish_alloc(alloc, &out); if (!ok) { - make_internal_server_error(result); + make_internal_server_error(alloc, result); } else { - make_text(result, "html", 200, out.items); + make_text(alloc, result, "html", 200, out.items); } } diff --git a/routes.h b/routes.h index 55d8b9d..81dea64 100644 --- a/routes.h +++ b/routes.h @@ -12,15 +12,17 @@ typedef struct { int status_code; NString_List headers; String_Builder body; + Arena *arena; } Route_Result; typedef struct { struct mg_mgr *mgr; ulong conn_id; struct mg_str message; + Arena *arena; } Route_Thread_Data; -typedef void (*Route_Handler)(struct mg_http_message *msg, Route_Result *result, void *context_data); +typedef void (*Route_Handler)(Allocator *alloc, struct mg_http_message *msg, Route_Result *result, void *context_data); typedef struct { char *key; // path @@ -29,11 +31,11 @@ typedef struct { } Route; #if MY_DEBUG -void route_build_id(struct mg_http_message *msg, Route_Result *result, void *context_data); +void route_build_id(Allocator *alloc, struct mg_http_message *msg, Route_Result *result, void *context_data); #endif -void route_page_not_found(struct mg_http_message *msg, Route_Result *result, void *context_data); -void route_home(struct mg_http_message *msg, Route_Result *result, void *context_data); -void route_generic_blog(struct mg_http_message *msg, Route_Result *result, void *context_data); -void route_blog(struct mg_http_message *msg, Route_Result *result, void *context_data); +void route_page_not_found(Allocator *alloc, struct mg_http_message *msg, Route_Result *result, void *context_data); +void route_home(Allocator *alloc, struct mg_http_message *msg, Route_Result *result, void *context_data); +void route_generic_blog(Allocator *alloc, struct mg_http_message *msg, Route_Result *result, void *context_data); +void route_blog(Allocator *alloc, struct mg_http_message *msg, Route_Result *result, void *context_data); #endif // ROUTES_H_