bunkum

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

commit af9feeba86f4d90d0b5c9917d67e7cbf639ac7c8
parent 9a07959db251f9824d005d5d350eccdf15e339ea
Author: quantumish <freifeld.david@gmail.com>
Date:   Sun,  9 Apr 2023 22:01:46 -0700

Clean up req handling, fix time bug, add free() func for request_t

Diffstat:
Mhttp.c | 112+++++++++++++++++++++++++++++++++++++++++++++++--------------------------------
Mhttp/request.c | 4++++
Mhttp/request.h | 4+++-
Mhttp/response.c | 14++++++++++++++
Mhttp/response.h | 1+
Mutils/log.c | 10+++++++---
Mutils/shitvec.c | 4++++
Mutils/shitvec.h | 1+
8 files changed, 101 insertions(+), 49 deletions(-)

diff --git a/http.c b/http.c @@ -5,6 +5,7 @@ #include <unistd.h> #include <string.h> #include <assert.h> +#include <dirent.h> #include <sys/stat.h> #include <sys/socket.h> @@ -47,10 +48,14 @@ void scuffed_htmlescape(char* dst, char* src, size_t sz) { strcpy(dst+i+offset, "\n</pre>"); } -#define MAX_PATH_SZ 32 +shitvec_t paths; + +// TODO actually respect requests +// TODO handle gzip +// TODO load balancing? + void* handle_conn(void* ctxt) { int ns = *(int*)ctxt; - char pathbuf[MAX_PATH_SZ]; char msgbuf[1024] = {0}; while(true) { if (recv(ns, msgbuf, 1024, 0) == 0) { @@ -66,60 +71,49 @@ void* handle_conn(void* ctxt) { header_line_t hdr = *(header_line_t*)shitvec_get(&req.headers, i); log_debug("Header '%s: %s'", hdr.name, hdr.value); } + + log_info("Got request for %s", req.path); - sscanf(msgbuf, "GET %s HTTP/1.1", (char*)&pathbuf); - log_info("Got request for %s", pathbuf); - - int fd = open(pathbuf+1, O_RDONLY); - if (fd != -1) { + if (shitvec_check(&paths, req.path, (int(*)(void*,void*))strcmp)) { + char path[72] = "./public"; + strcat(path, req.path); + int fd = open(path, O_RDONLY); // TODO handle response_t r = resp_new(OK); struct stat st; fstat(fd, &st); - char* fbuf = malloc(st.st_size); - size_t i; - for (i = 0; read(fd, fbuf+(i*4096), 4096) > 0; i++); - - bool escape = false; - bool compression = true; - char* ext = strchr(pathbuf+1, '.'); - // TODO clean this up some - if (ext == NULL) { - resp_add_hdr(&r, "Content-Type", "text/html"); - escape = true; - } else if (strcmp(ext+1, "html") == 0) { - resp_add_hdr(&r, "Content-Type", "text/html"); - } else if (strcmp(ext+1, "png") == 0) { - compression = false; - resp_add_hdr(&r, "Content-Type", "image/png"); - } else if (strcmp(ext+1, "svg") == 0) { - resp_add_hdr(&r, "Content-Type", "image/svg+xml"); - } else if (strcmp(ext+1, "jpeg") == 0) { - resp_add_hdr(&r, "Content-Type", "image/jpeg"); - } + char* fbuf = malloc(st.st_size); // TODO what if file larger than memory? + for (size_t i = 0; read(fd, fbuf+(i*4096), 4096) > 0; i++); + char* ext = strchr(req.path, '.'); // NOTE breaks if there's a dir with a dot... + resp_set_ctype(&r, ext); + char datebuf[32]; time_to_str(st.st_mtim.tv_sec, datebuf); resp_add_hdr(&r, "Last-Modified", datebuf); + + char* buf = fbuf; // buffer to be written + size_t bufsize = st.st_size; - if (escape) { - char* efbuf = malloc((size_t)(st.st_size * 2)); // FIXME dubious assumption - scuffed_htmlescape(efbuf, fbuf, st.st_size); - free(fbuf); - resp_add_content(&r, efbuf, strlen(efbuf)); - free(efbuf); - } else if (compression) { + if (ext == NULL) { + bufsize = st.st_size * 2; + buf = malloc(bufsize); // FIXME dubious assumption + scuffed_htmlescape(buf, fbuf, st.st_size); + free(fbuf); + } + if (ext == NULL || strcmp(ext, ".png") != 0) { resp_add_hdr(&r, "Content-Encoding", "deflate"); size_t clen = compressBound(st.st_size); char* cbuf = malloc(clen); - compress((Bytef*)cbuf, &clen, (Bytef*)fbuf, st.st_size); - free(fbuf); - resp_add_content(&r, cbuf, clen); - free(cbuf); - } else { - resp_add_content(&r, fbuf, st.st_size); + compress((Bytef*)cbuf, &clen, (Bytef*)buf, bufsize); + free(buf); + + buf = cbuf; + bufsize = clen; } + resp_add_content(&r, buf, bufsize); send(ns, r.content, r.sz, 0); + free(buf); free(r.content); } else { response_t r = __resp_new(NotFound, "Fuck off."); @@ -128,11 +122,35 @@ void* handle_conn(void* ctxt) { send(ns, r.content, r.sz, 0); free(r.content); } - log_info("Handled request for %s", pathbuf); + log_info("Handled request for %s", req.path); + req_free(&req); } } } +int list_files_sv(shitvec_t* sv, char* base, bool dropbase) { + char path[MAX_PATH_LEN] = "/"; + struct dirent* dp; + DIR* dir = opendir(base); + if (!dir) return -1; + + while ((dp = readdir(dir)) != NULL) { + if (strcmp(dp->d_name, ".") != 0 && strcmp(dp->d_name, "..") != 0) { + if (!dropbase) { + strcpy(path+1, base); + strcat(path, "/"); + } + strcat(path, dp->d_name); + log_debug("Pushing %s", path); + shitvec_push(sv, path); + list_files_sv(sv, path, false); + } + } + + closedir(dir); + return 0; +} + int main() { int s = socket(AF_INET, SOCK_STREAM, 0); if (s == -1) die("socket"); @@ -147,11 +165,15 @@ int main() { if (bind(s, (struct sockaddr*)&name, sizeof(name)) < 0) { die("bind"); } - } - log_debug("Open on port 8082."); + } + paths = shitvec_new(MAX_PATH_LEN); + list_files_sv(&paths, "public", true); + + log_debug("Open on port 8082."); + int namelen; - char pathbuf[MAX_PATH_SZ]; + char pathbuf[MAX_PATH_LEN]; struct sockaddr_in client; char msgbuf[512] = {0}; while (true) { diff --git a/http/request.c b/http/request.c @@ -52,3 +52,7 @@ int req_parse(request_t* req) { return 0; } + +void req_free(request_t* req) { + shitvec_free(&req->headers); +} diff --git a/http/request.h b/http/request.h @@ -15,6 +15,7 @@ enum http_method { }; const char* method_name(enum http_method m); +#define MAX_PATH_LEN 64 #define MAX_HEADER_NAME 32 #define MAX_HEADER_VALUE 128 @@ -27,12 +28,13 @@ typedef struct request { char* buf; size_t bufsize; enum http_method method; - char path[64]; + char path[MAX_PATH_LEN]; float ver; shitvec_t headers; } request_t; request_t req_new(char* reqbuf, size_t bufsize); int req_parse(request_t* req); +void req_free(request_t* req); #endif diff --git a/http/response.c b/http/response.c @@ -40,3 +40,17 @@ void resp_add_content(response_t* r, char* content, size_t content_len) { strcpy(r->content, r->header); memcpy(r->content+header_len, content, content_len); } + +void resp_set_ctype(response_t* r, char* ext) { + if (ext == NULL) { + resp_add_hdr(r, "Content-Type", "text/html"); + } else if (strcmp(ext+1, "html") == 0) { + resp_add_hdr(r, "Content-Type", "text/html"); + } else if (strcmp(ext+1, "png") == 0) { + resp_add_hdr(r, "Content-Type", "image/png"); + } else if (strcmp(ext+1, "svg") == 0) { + resp_add_hdr(r, "Content-Type", "image/svg+xml"); + } else if (strcmp(ext+1, "jpeg") == 0) { + resp_add_hdr(r, "Content-Type", "image/jpeg"); + } +} diff --git a/http/response.h b/http/response.h @@ -46,5 +46,6 @@ response_t __resp_new(enum StatusCode code, char* code_name); void resp_add_hdr(response_t* r, char* hdr, char* val); void resp_add_content(response_t* r, char* content, size_t content_len); +void resp_set_ctype(response_t* r, char* ext); #endif diff --git a/utils/log.c b/utils/log.c @@ -1,3 +1,7 @@ + +// TODO: fix wackiness with time functions +// TODO: allow for writing to files + #include <stdio.h> #include <stdarg.h> #include <time.h> @@ -37,9 +41,9 @@ void log_msg(enum log_level lvl, char* lvl_name, char* fmt, ...) { const char* lvl_color = lvl_colors[lvl]; - printf(ANSI_GREY "%02d/%02d/%02d %02d:%02d:%02d %s%s" ANSI_RESET ": %s\n", - local->tm_mon, local->tm_mday, local->tm_year, - local->tm_hour, local->tm_min, local->tm_sec, + printf(ANSI_GREY "%02d/%02d/%04d %02d:%02d:%02d %s%s" ANSI_RESET ": %s\n", + local->tm_mon+1, local->tm_mday, 1900+local->tm_year, + local->tm_hour+1, local->tm_min+1, local->tm_sec, lvl_color, lvl_name, msg); } diff --git a/utils/shitvec.c b/utils/shitvec.c @@ -45,3 +45,7 @@ bool shitvec_check(shitvec_t* sv, void* item, int(cmp)(void*, void*)) { } return false; } + +void shitvec_free(shitvec_t* sv) { + free(sv->arr); +} diff --git a/utils/shitvec.h b/utils/shitvec.h @@ -18,6 +18,7 @@ void* shitvec_get(shitvec_t* sv, size_t index); void shitvec_push(shitvec_t* sv, void* item); void shitvec_subpush(shitvec_t* sv, void* item, size_t sz); bool shitvec_check(shitvec_t* sv, void* item, int(cmp)(void*, void*)); +void shitvec_free(shitvec_t* sv); #endif