From 755bdcd189bb2df1f5a5b1a4c5bbbebe50f90841 Mon Sep 17 00:00:00 2001 From: overflowerror Date: Sat, 24 Feb 2024 23:41:59 +0100 Subject: [PATCH] feat(LSP): Begin of header parsing --- lsp/Makefile | 10 ++-- lsp/src/header.c | 116 +++++++++++++++++++++++++++++++++++++++++++ lsp/src/header.h | 20 ++++++++ lsp/src/main.c | 4 ++ lsp/src/networking.c | 16 ++---- lsp/src/networking.h | 3 ++ 6 files changed, 153 insertions(+), 16 deletions(-) create mode 100644 lsp/src/header.c create mode 100644 lsp/src/header.h diff --git a/lsp/Makefile b/lsp/Makefile index 9cb3922..af8c860 100644 --- a/lsp/Makefile +++ b/lsp/Makefile @@ -1,5 +1,5 @@ CC = gcc -CFLAGS = -std=c11 -D_POSIX_C_SOURCE=200809L -Wall -Wpedantic -g -I./src -I./gen +CFLAGS = -std=c11 -D_POSIX_C_SOURCE=200809L -Wall -Wpedantic -g -I./src -I./../common/src/ LD = gcc LDFLAGS = YACC = bison @@ -8,7 +8,7 @@ LEX = lex LEXFLAGS = -OBJS = obj/networking.o obj/main.o +OBJS = obj/networking.o obj/header.o obj/main.o DEPS = $(OBJS:%.o=%.d) -include $(DEPS) @@ -18,12 +18,16 @@ all: macrofuck-lsp obj/%.o: src/%.c $(CC) $(CFLAGS) -c -o $@ $< -macrofuck-lsp: $(OBJS) +macrofuck-lsp: $(OBJS) ../common/common.a $(LD) $(LDFLAGS) -o $@ $^ +../common/common.a: FORCE + cd ../common/ && $(MAKE) common.a + FORCE: ; clean: + @cd ../common/ && $(MAKE) clean @echo "Cleaning up" @rm -f obj/*.o @rm -f obj/*.d diff --git a/lsp/src/header.c b/lsp/src/header.c new file mode 100644 index 0000000..2bfbbca --- /dev/null +++ b/lsp/src/header.c @@ -0,0 +1,116 @@ +#include +#include +#include +#include +#include + +#include +#include + +#include "header.h" + +header_t* header_new(void) { + header_t* header = safe_malloc(sizeof (header_t)); + header->method = NULL; + header->uri = NULL; + header->headers = dict_new(); + + return header; +} + +header_t* header_parse(FILE* conn) { + fprintf(stderr, "parsing headers\n"); + header_t* header = header_new(); + + #define HEADER_BUFFER_LENGTH (1<<10) + char* buffer = alloca(HEADER_BUFFER_LENGTH); + size_t buffer_index = 0; + + char* key = NULL; + char* value = NULL; + + bool is_first_line = true; + bool last_line_was_empty = false; + while (true) { + int c = fgetc(conn); + fprintf(stderr, "c: %c, %d, %d, %s, %s, %s\n", c, is_first_line, last_line_was_empty, buffer, key, value); + if (c == EOF) { + break; + } + if (c == '\r') { + c = fgetc(conn); + if (c == '\n') { + if (last_line_was_empty) { + break; + } else { + if (is_first_line) { + char* method = strtok(buffer, " "); + char* uri = strtok(NULL, " "); + char* proto = strtok(NULL, " "); + + // defer fail to when fields are read + if (method) { + header->method = strdup(method); + } + if (uri) { + header->uri = strdup(uri); + } + if (proto) { + header->proto = strdup(proto); + } + + is_first_line = false; + } else { + if (!key) { + fprintf(stderr, "no key for value - ignoring\n"); + } else { + value = strdup(buffer); + if (!value) { + fprintf(stderr, "unable to dup header value: %s\n", strerror(errno)); + return NULL; + } + header_add(header, key, value); + } + } + } + } else { + fprintf(stderr, "header parse error, unexpected %d at header %s\n", c, key); + } + + *buffer = '\0'; + buffer_index = 0; + key = NULL; + value = NULL; + last_line_was_empty = true; + } else if (key == NULL && c == ':' && !is_first_line) { + c = fgetc(conn); + if (c == ' ') { + key = strdup(buffer); + if (!key) { + fprintf(stderr, "unable to dup header key: %s\n", strerror(errno)); + return NULL; + } + *buffer = '\0'; + buffer_index = 0; + } + } else { + last_line_was_empty = false; + if (buffer_index + 1 >= HEADER_BUFFER_LENGTH) { + fprintf(stderr, "header too long - truncating\n"); + } else { + buffer[buffer_index] = c; + buffer[++buffer_index] = '\0'; + } + } + } + + return header; +} + +void header_add(header_t* header, const char* key, const char* value) { + dict_put(header->headers, key, (void*) value); +} + +const char* header_get(header_t* header, const char* key) { + return dict_get(header->headers, key); +} diff --git a/lsp/src/header.h b/lsp/src/header.h new file mode 100644 index 0000000..ae5380d --- /dev/null +++ b/lsp/src/header.h @@ -0,0 +1,20 @@ +#ifndef HEADER_H +#define HEADER_H + +#include + +#include + +typedef struct { + char* method; + char* uri; + char* proto; + dict_t* headers; +} header_t; + +header_t* header_new(void); +header_t* header_parse(FILE*); +void header_add(header_t*, const char*, const char*); +const char* header_get(header_t*, const char*); + +#endif diff --git a/lsp/src/main.c b/lsp/src/main.c index 67bb84a..9dc15a0 100644 --- a/lsp/src/main.c +++ b/lsp/src/main.c @@ -6,6 +6,10 @@ void hello_handler(request_t* request) { fprintf(request->response_body, "HTTP/1.0 200 OK\r\n"); fprintf(request->response_body, "\r\n"); fprintf(request->response_body, "Hello, World!\n"); + fprintf(request->response_body, "Method: %s\n", request->request_header->method); + fprintf(request->response_body, "URI: %s\n", request->request_header->uri); + fprintf(request->response_body, "Host: %s\n", header_get(request->request_header, "Host")); + fprintf(request->response_body, "User-Agent: %s\n", header_get(request->request_header, "User-Agent")); } int main(void) { diff --git a/lsp/src/networking.c b/lsp/src/networking.c index 9427f34..23b47fe 100644 --- a/lsp/src/networking.c +++ b/lsp/src/networking.c @@ -98,19 +98,7 @@ static request_t prepare_request_obj(int fd) { request.request_body = fdopen(fd, "r"); request.response_body = fdopen(fd2, "w"); - #define HEADER_BUFFER_LENGTH (128) - char* buffer = alloca(HEADER_BUFFER_LENGTH); - - // skip headers (for now) - while (true) { - fgets(buffer, HEADER_BUFFER_LENGTH - 1, request.request_body); - - if (strcmp(buffer, "\r\n")) { - break; - } - - printf(" discarded header: %s\n", buffer); - } + request.request_header = header_parse(request.request_body); return request; } @@ -150,8 +138,10 @@ int run_server(const char* bind_addr, handler_t handler) { while (true) { // we don't care for the remote address right now int fd = accept(sock, NULL, 0); + fprintf(stderr, "new connection: %d\n", fd); if (fd < 0) { fprintf(stderr, "warn: accept failed: %s\n", strerror(errno)); + } handle_connection(fd, handler); diff --git a/lsp/src/networking.h b/lsp/src/networking.h index 3ae4027..2847f60 100644 --- a/lsp/src/networking.h +++ b/lsp/src/networking.h @@ -3,7 +3,10 @@ #include +#include "header.h" + typedef struct { + header_t* request_header; FILE* request_body; FILE* response_body; } request_t;