diff --git a/Makefile b/Makefile index 461450d..b8c12d1 100644 --- a/Makefile +++ b/Makefile @@ -7,22 +7,23 @@ BIN_NAME = cfloor all: $(BIN_NAME) -$(BIN_NAME): obj/main.o obj/networking.o obj/linked.o obj/logging.o obj/signals.o +$(BIN_NAME): obj/main.o obj/networking.o obj/linked.o obj/logging.o obj/signals.o obj/headers.o $(LD) $(LDFLAGS) -o $@ $^ -test: obj/test.o obj/networking.o obj/linked.o obj/logging.o obj/signals.o +test: obj/test.o obj/networking.o obj/linked.o obj/logging.o obj/signals.o obj/headers.o $(LD) $(LDFLAGS) -o $@ $^ valgrind: CFLAGS += -static -g valgrind: clean test valgrind --leak-check=yes ./test -obj/main.o: src/networking.h src/linked.h src/logging.h src/signals.h src/misc.h -obj/test.o: src/networking.h src/linked.h src/logging.h src/signals.h src/misc.h +obj/main.o: src/networking.h src/linked.h src/logging.h src/signals.h src/misc.h src/headers.h +obj/test.o: src/networking.h src/linked.h src/logging.h src/signals.h src/misc.h src/headers.h obj/networking.o: src/networking.h src/headers.h src/linked.h src/logging.h src/signals.h obj/linked.o: src/linked.h obj/logging.o: src/logging.h obj/signals.o: src/signals.h +obj/headers.o: src/headers.h obj/%.o: src/%.c obj $(CC) $(CFLAGS) -c -o $@ $< diff --git a/src/headers.c b/src/headers.c index e69de29..6ac42b5 100644 --- a/src/headers.c +++ b/src/headers.c @@ -0,0 +1,120 @@ +#include +#include + +#include "headers.h" + +int headers_find(struct headers* headers, const char* key) { + for (int i = 0; i < headers->number; i++) { + if (strcmp(headers->headers[i].key, key) == 0) + return i; + } + return -1; +} + +const char* headers_get(struct headers* headers, const char* key) { + int tmp = headers_find(headers, key); + if (tmp < 0) + return NULL; + return headers->headers[tmp].value; +} + +int headers_mod(struct headers* headers, char* key, char* value) { + int index = headers_find(headers, key); + + if (index < 0) { + struct header* tmp = realloc(headers->headers, (headers->number + 1) * sizeof(struct header)); + if (tmp == NULL) { + // we don't need to clean up this connection gets dropped anyway + return HEADERS_ALLOC_ERROR; + } + + headers->headers = tmp; + + index = headers->number++; + } + + headers->headers[index] = (struct header) { + .key = key, + .value = value + }; + + return index; +} + +int headers_parse(struct headers* headers, const char* _currentHeader, size_t length) { + char* key = NULL; + char* value = NULL; + + char* currentHeader = malloc(length); + if (currentHeader == NULL) + return HEADERS_ALLOC_ERROR; + + memcpy(currentHeader, _currentHeader, length); + // string terminator not needed + + char* keyTmp = currentHeader; + char* valueTmp = NULL; + + for(int i = 0; i < length; i++) { + if (currentHeader[i] == ':') { + keyTmp[i] = '\0'; + valueTmp = currentHeader + i + 1; + length -= i + 1; + break; + } + } + if (length < 0) { + free(currentHeader); + return HEADERS_PARSE_ERROR; + } + if (valueTmp == NULL) { + free(currentHeader); + return HEADERS_PARSE_ERROR; + } + key = malloc(strlen(keyTmp) + 1); + if (key == NULL) { + free(currentHeader); + return HEADERS_ALLOC_ERROR; + } + value = malloc(length + 1); + if (value == NULL) { + free(currentHeader); + return HEADERS_ALLOC_ERROR; + } + strcpy(key, keyTmp); + memcpy(value, valueTmp, length); + value[length] = '\0'; + + free(currentHeader); + + int shift = 0; + for(int i = 0; i < strlen(value); i++) { + if (value[i] != ' ') { + shift = i; + break; + } + } + if (shift > 0) { + memmove(value, value + shift, strlen(value) - shift + 1); + } + for(int i = strlen(value) - 1; i >= 0; i--) { + if (value[i] != ' ') { + value[i + 1] = '\0'; + break; + } + } + + return headers_mod(headers, key, value); +} + +void headers_free(struct headers* headers) { + for (int i = 0; i < headers->number; i++) { + if (headers->headers[i].key != NULL) + free(headers->headers[i].key); + if (headers->headers[i].value != NULL) + free(headers->headers[i].value); + } + + if (headers->headers != NULL) + free(headers->headers); +} diff --git a/src/headers.h b/src/headers.h index bb4a403..362e390 100644 --- a/src/headers.h +++ b/src/headers.h @@ -1,6 +1,9 @@ #ifndef HEADERS_H #define HEADERS_H +#define HEADERS_PARSE_ERROR (-1) +#define HEADERS_ALLOC_ERROR (-2) + struct header { char* key; char* value; @@ -11,4 +14,9 @@ struct headers { struct header* headers; }; +const char* headers_get(struct headers* headers, const char* key); +int headers_mod(struct headers* headers, char* key, char* value); +int headers_parse(struct headers* headers, const char* currentHeader, size_t length); +void headers_free(struct headers* headers); + #endif diff --git a/src/test.c b/src/test.c index e0eb5be..e1cb2cf 100644 --- a/src/test.c +++ b/src/test.c @@ -13,6 +13,7 @@ #include "linked.h" #include "logging.h" #include "signals.h" +#include "headers.h" bool global = true; bool overall = true; @@ -173,7 +174,24 @@ void testTimers() { checkInt(counter, 100, "interval count"); } -handler_t handlerGetter(struct metaData metaData, const char* host) { +void testHeaders() { + struct headers headers = (struct headers) { + .number = 0 + }; + + char* tmp = "test: Hello World "; + checkInt(headers_parse(&headers, tmp, strlen(tmp)), 0, "parse ok"); + tmp = "blablabla"; + checkInt(headers_parse(&headers, tmp, strlen(tmp)), HEADERS_PARSE_ERROR, "parse error"); + tmp = "test2: Hello World2"; + checkInt(headers_parse(&headers, tmp, strlen(tmp)), 1, "parse ok"); + + checkString(headers_get(&headers, "test"), "Hello World", "value check"); + + headers_free(&headers); +} + +handler_t handlerGetter(struct metaData metaData, const char* host, struct bind* bind) { return NULL; } @@ -202,6 +220,7 @@ int main(int argc, char** argv) { test("linked lists", &testLinkedList); test("logging", &testLogging); test("signals", &testTimers); + test("headers", &testHeaders); printf("\nOverall: %s\n", overall ? "OK" : "FAILED");