commit 3f66d6c58d16dd0065b63e0f9f03d947048be793
parent 11a6e4ad93d37e2479f40dddb54237b6c016d89c
Author: quantumish <freifeld.david@gmail.com>
Date: Sun, 9 Apr 2023 16:32:05 -0700
Request parsing, minor cleanups
Diffstat:
5 files changed, 108 insertions(+), 3 deletions(-)
diff --git a/http.c b/http.c
@@ -20,6 +20,7 @@
#include "utils/time.h"
#include "utils/shitvec.h"
#include "http/response.h"
+#include "http/request.h"
void scuffed_htmlescape(char* dst, char* src, size_t sz) {
strcpy(dst, "<pre>\n");
@@ -50,13 +51,22 @@ void scuffed_htmlescape(char* dst, char* src, size_t sz) {
void* handle_conn(void* ctxt) {
int ns = *(int*)ctxt;
char pathbuf[MAX_PATH_SZ];
- char msgbuf[512] = {0};
+ char msgbuf[1024] = {0};
while(true) {
- if (recv(ns, msgbuf, 512, 0) == 0) {
+ if (recv(ns, msgbuf, 1024, 0) == 0) {
log_info("Closing connection.");
return 0x0;
}
if (strlen(msgbuf) > 0) {
+ request_t req = req_new(msgbuf, 1024);
+ int err = req_parse(&req);
+ if (err < 0) log_error("Failed to parse incoming request.");
+ log_debug("Req: %s, %s, %f", method_name(req.method), req.path, req.ver);
+ for (size_t i = 0; i < req.headers.vec_sz; i++) {
+ header_line_t hdr = *(header_line_t*)shitvec_get(&req.headers, i);
+ log_debug("Header '%s: %s'", hdr.name, hdr.value);
+ }
+
sscanf(msgbuf, "GET %s HTTP/1.1", (char*)&pathbuf);
log_info("Got request for %s", pathbuf);
diff --git a/http/request.c b/http/request.c
@@ -0,0 +1,54 @@
+#include <stdio.h>
+#include <string.h>
+#include <stdint.h>
+
+#include "../utils/shitvec.h"
+#include "request.h"
+
+const char* method_names[] = {"GET", "HEAD", "POST", "PUT", "DELETE", "CONNECT", "OPTIONS", "TRACE"};
+
+const char* method_name(enum http_method m) {
+ return method_names[m];
+}
+
+const enum http_method method_codes[] = {DELETE, CONNECT, PUT, POST, TRACE, HEAD, OPTIONS, GET};
+enum http_method method_enum(char* p) {
+ return method_codes[((*(uint64_t*)p*0x1b8b6e6d) % 0x100000000) >> 28];
+}
+
+header_line_t header_line_new() {
+ header_line_t hl;
+ memset(hl.name, 0, MAX_HEADER_NAME);
+ memset(hl.value, 0, MAX_HEADER_VALUE);
+ return hl;
+}
+
+request_t req_new(char* reqbuf, size_t bufsize) {
+ request_t req;
+ req.buf = reqbuf;
+ req.bufsize = bufsize;
+ return req;
+}
+
+int req_parse(request_t* req) {
+ char method[8] = {0};
+ int matched = sscanf(req->buf, "%s %s HTTP/%f\r\n", (char*)method, (char*)req->path, &req->ver);
+ if (matched < 3 || matched == EOF) return -1;
+ req->method = method_enum((char*)method);
+
+ req->headers = shitvec_new(sizeof(header_line_t));
+ char* start = memchr(req->buf, '\n', MAX_HEADER_NAME+MAX_HEADER_VALUE)+1;
+ while (start+MAX_HEADER_NAME+MAX_HEADER_VALUE < req->buf+req->bufsize) {
+ header_line_t hdr;
+ int matched = sscanf(start, "%32[^:]: %s", hdr.name, hdr.value);
+ if (matched == 0) return 0; // No more headers;
+ else if (matched == 1) {
+ if (hdr.name[0] == '\r') return 0; // TODO sketch
+ return -1; // Uhh... half a header.
+ }
+ shitvec_push(&req->headers, &hdr);
+ start = memchr(start, '\n', MAX_HEADER_NAME+MAX_HEADER_VALUE)+1;
+ }
+
+ return 0;
+}
diff --git a/http/request.h b/http/request.h
@@ -0,0 +1,38 @@
+#ifndef REQUEST_H
+#define REQUEST_H
+
+#include "../utils/shitvec.h"
+
+enum http_method {
+ GET,
+ HEAD,
+ POST,
+ PUT,
+ DELETE,
+ CONNECT,
+ OPTIONS,
+ TRACE,
+};
+const char* method_name(enum http_method m);
+
+#define MAX_HEADER_NAME 32
+#define MAX_HEADER_VALUE 128
+
+typedef struct header_line {
+ char name[MAX_HEADER_NAME];
+ char value[MAX_HEADER_VALUE];
+} header_line_t;
+
+typedef struct request {
+ char* buf;
+ size_t bufsize;
+ enum http_method method;
+ char path[64];
+ float ver;
+ shitvec_t headers;
+} request_t;
+
+request_t req_new(char* reqbuf, size_t bufsize);
+int req_parse(request_t* req);
+
+#endif
diff --git a/utils/log.h b/utils/log.h
@@ -18,5 +18,7 @@ void log_msg(enum log_level lvl, char* lvl_name, char* fmt, ...);
#define log_warn(fmt, ...) log_msg(LOG_WARN, "WARN", fmt, ##__VA_ARGS__)
#define log_error(fmt, ...) log_msg(LOG_ERROR, "ERROR", fmt, ##__VA_ARGS__)
#define log_fatal(fmt, ...) log_msg(LOG_FATAL, "FATAL", fmt, ##__VA_ARGS__)
+void log_set_min_lvl(enum log_level lvl);
+void die(char* p);
#endif
diff --git a/utils/shitvec.c b/utils/shitvec.c
@@ -20,7 +20,8 @@ void* shitvec_get(shitvec_t* sv, size_t index) {
}
void shitvec_push(shitvec_t* sv, void* item) {
- if ((sv->arr+(sv->e_sz * sv->vec_sz)) > sv->arr+sv->alloc_sz) {
+ // 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);
}
memcpy(sv->arr+(sv->vec_sz * sv->e_sz), item, sv->e_sz);