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:
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