mirror of
https://github.com/sigmasternchen/macrofuck
synced 2025-03-15 07:08:56 +00:00
feat(LSP): Begin of header parsing
This commit is contained in:
parent
c61076b835
commit
755bdcd189
6 changed files with 153 additions and 16 deletions
10
lsp/Makefile
10
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
|
||||
|
|
116
lsp/src/header.c
Normal file
116
lsp/src/header.c
Normal file
|
@ -0,0 +1,116 @@
|
|||
#include <stdio.h>
|
||||
#include <alloca.h>
|
||||
#include <stdbool.h>
|
||||
#include <string.h>
|
||||
#include <errno.h>
|
||||
|
||||
#include <alloc.h>
|
||||
#include <dict.h>
|
||||
|
||||
#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);
|
||||
}
|
20
lsp/src/header.h
Normal file
20
lsp/src/header.h
Normal file
|
@ -0,0 +1,20 @@
|
|||
#ifndef HEADER_H
|
||||
#define HEADER_H
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
#include <dict.h>
|
||||
|
||||
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
|
|
@ -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) {
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -3,7 +3,10 @@
|
|||
|
||||
#include <stdio.h>
|
||||
|
||||
#include "header.h"
|
||||
|
||||
typedef struct {
|
||||
header_t* request_header;
|
||||
FILE* request_body;
|
||||
FILE* response_body;
|
||||
} request_t;
|
||||
|
|
Loading…
Reference in a new issue