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
|
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
|
LD = gcc
|
||||||
LDFLAGS =
|
LDFLAGS =
|
||||||
YACC = bison
|
YACC = bison
|
||||||
|
@ -8,7 +8,7 @@ LEX = lex
|
||||||
LEXFLAGS =
|
LEXFLAGS =
|
||||||
|
|
||||||
|
|
||||||
OBJS = obj/networking.o obj/main.o
|
OBJS = obj/networking.o obj/header.o obj/main.o
|
||||||
DEPS = $(OBJS:%.o=%.d)
|
DEPS = $(OBJS:%.o=%.d)
|
||||||
|
|
||||||
-include $(DEPS)
|
-include $(DEPS)
|
||||||
|
@ -18,12 +18,16 @@ all: macrofuck-lsp
|
||||||
obj/%.o: src/%.c
|
obj/%.o: src/%.c
|
||||||
$(CC) $(CFLAGS) -c -o $@ $<
|
$(CC) $(CFLAGS) -c -o $@ $<
|
||||||
|
|
||||||
macrofuck-lsp: $(OBJS)
|
macrofuck-lsp: $(OBJS) ../common/common.a
|
||||||
$(LD) $(LDFLAGS) -o $@ $^
|
$(LD) $(LDFLAGS) -o $@ $^
|
||||||
|
|
||||||
|
../common/common.a: FORCE
|
||||||
|
cd ../common/ && $(MAKE) common.a
|
||||||
|
|
||||||
FORCE: ;
|
FORCE: ;
|
||||||
|
|
||||||
clean:
|
clean:
|
||||||
|
@cd ../common/ && $(MAKE) clean
|
||||||
@echo "Cleaning up"
|
@echo "Cleaning up"
|
||||||
@rm -f obj/*.o
|
@rm -f obj/*.o
|
||||||
@rm -f obj/*.d
|
@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, "HTTP/1.0 200 OK\r\n");
|
||||||
fprintf(request->response_body, "\r\n");
|
fprintf(request->response_body, "\r\n");
|
||||||
fprintf(request->response_body, "Hello, World!\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) {
|
int main(void) {
|
||||||
|
|
|
@ -98,19 +98,7 @@ static request_t prepare_request_obj(int fd) {
|
||||||
request.request_body = fdopen(fd, "r");
|
request.request_body = fdopen(fd, "r");
|
||||||
request.response_body = fdopen(fd2, "w");
|
request.response_body = fdopen(fd2, "w");
|
||||||
|
|
||||||
#define HEADER_BUFFER_LENGTH (128)
|
request.request_header = header_parse(request.request_body);
|
||||||
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);
|
|
||||||
}
|
|
||||||
|
|
||||||
return request;
|
return request;
|
||||||
}
|
}
|
||||||
|
@ -150,8 +138,10 @@ int run_server(const char* bind_addr, handler_t handler) {
|
||||||
while (true) {
|
while (true) {
|
||||||
// we don't care for the remote address right now
|
// we don't care for the remote address right now
|
||||||
int fd = accept(sock, NULL, 0);
|
int fd = accept(sock, NULL, 0);
|
||||||
|
fprintf(stderr, "new connection: %d\n", fd);
|
||||||
if (fd < 0) {
|
if (fd < 0) {
|
||||||
fprintf(stderr, "warn: accept failed: %s\n", strerror(errno));
|
fprintf(stderr, "warn: accept failed: %s\n", strerror(errno));
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
handle_connection(fd, handler);
|
handle_connection(fd, handler);
|
||||||
|
|
|
@ -3,7 +3,10 @@
|
||||||
|
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
|
|
||||||
|
#include "header.h"
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
|
header_t* request_header;
|
||||||
FILE* request_body;
|
FILE* request_body;
|
||||||
FILE* response_body;
|
FILE* response_body;
|
||||||
} request_t;
|
} request_t;
|
||||||
|
|
Loading…
Reference in a new issue