From e2f46e15df9ef19be4f05583b5a9513cdbf09720 Mon Sep 17 00:00:00 2001 From: Max Christian Pohle Date: Tue, 16 Nov 2021 12:18:36 +0100 Subject: First refactoring round Still open: Split the header/body parser, but this is more complicated, so maybe some automated tests first. --- main.c | 104 ++++++++++++++++++++++++++++++++++++----------------------------- 1 file changed, 57 insertions(+), 47 deletions(-) diff --git a/main.c b/main.c index 69ac01e..2bf2e14 100644 --- a/main.c +++ b/main.c @@ -16,6 +16,7 @@ #include #include +#include void send_answer(FILE * f) { @@ -36,34 +37,34 @@ void send_answer(FILE * f) { fputs("", f); } -void * next_customer(size_t new_socket) { - char * output_buffer = NULL; - size_t output_buffer_length = 0; - FILE * output = open_memstream(&output_buffer, &output_buffer_length); +#define EWOULDBLOCK_DELAY 1000 +#define READ_BUFFER_LENGTH 10 +#define DEBUG_SLEEP_TIME 50000 - const int read_buffer_length = 10; - char read_buffer[read_buffer_length]; +static inline int verbose(const char * format, ...) { + va_list va; va_start(va, format); usleep(DEBUG_SLEEP_TIME); return vprintf(format, va); +} - puts("\n\n########################################## Content Reader"); - FILE * q = fdopen((size_t) new_socket, "r"); - printf("fd : %p\n", q); - for(size_t size = -2 ; ; size = fread(read_buffer, read_buffer_length, 1, q)) { +void read_everything(FILE * f_r, FILE * output) { + const int read_buffer_length = READ_BUFFER_LENGTH; + char read_buffer[read_buffer_length]; + for(size_t size = -2 ; ; size = fread(read_buffer, read_buffer_length, 1, f_r)) { if(-2 == size || (-1 == size && EWOULDBLOCK == errno)) { - usleep(1000); + usleep(EWOULDBLOCK_DELAY); // try again a little later continue; } else if (1 != size) { // I expect one nmemb of data break; } fwrite(read_buffer, read_buffer_length, 1, output); - fwrite(read_buffer, read_buffer_length, 1, stdout); } fflush(output); +} - - puts("\n\n########################################## Content Parser"); +void header_next(const char * key, const char * value) { + // this sample function will be removed later typedef struct { const char * name; const char * value; @@ -73,6 +74,27 @@ void * next_customer(size_t new_socket) { {"Content-Type", NULL}, {"Content-Length", NULL} }; + for(int i=0; i < sizeof(namevalue) / sizeof(NameValue); i++) { + // printf("next name: %s\n", namevalue[i].name); + if(NULL == namevalue[i].value && 0 == strcasecmp(namevalue[i].name, key)) { + namevalue[i].value = value; + break; + } + } +} + +void * next_customer(size_t new_socket) { + FILE * f_r = fdopen((size_t) new_socket, "r"); + FILE * f_w = fdopen((size_t) new_socket, "w"); + + char * output_buffer = NULL; + size_t output_buffer_length = 0; + FILE * output = open_memstream(&output_buffer, &output_buffer_length); + + verbose("\n\n########################################## Content Reader [%d]\n", f_r); + read_everything(f_r, output); + verbose("\n\n########################################## Content Parser"); + // token parser... const char * boundary = NULL; @@ -84,10 +106,8 @@ void * next_customer(size_t new_socket) { char * content_start = NULL; char * content_end = NULL; - while(1) { - - printf("NEXT ITERATION with search '%s'\n", search); - + while(key ? key[0] != '\0' : 1) { + verbose("> [!] Next iteration with search '%s'\n", search); for(char * token = strtok_r(NULL == saveptr ? output_buffer : saveptr, NULL == search ? "\n\r" : search, &saveptr); token != NULL; @@ -95,8 +115,7 @@ void * next_customer(size_t new_socket) { { if(!search) { // first round: HTTP status code - puts("FIRST ITERATION"); - printf("HTTP sanity check: %s\n", token); + verbose("> First Iteration: HTTP sanity check of: %s\n", token); search = ":"; continue; } @@ -119,18 +138,12 @@ void * next_customer(size_t new_socket) { if(!boundary && strstr(key, "Content-Type") && strncmp(value, pattern, sizeof(pattern))) { boundary = &value[sizeof(pattern) + strspn(&value[sizeof(pattern)], "-")]; boundary_length = strlen(boundary); - printf("> [!] boundary detected '%s' ", boundary); + verbose("> [!] boundary detected '%s' ", boundary); } - for(int i=0; i < sizeof(namevalue) / sizeof(NameValue); i++) { - // printf("next name: %s\n", namevalue[i].name); - if(NULL == namevalue[i].value && 0 == strcasecmp(namevalue[i].name, key)) { - namevalue[i].value = value; - break; - } - } + header_next(key, value); - printf("> [%ld] \"%s\" :: \"%s\"\n", key - output_buffer, key, value); fflush(stdout); + verbose("> [%ld] \"%s\" :: \"%s\"\n", key - output_buffer, key, value); fflush(stdout); search = ":"; key = NULL; @@ -140,13 +153,13 @@ void * next_customer(size_t new_socket) { if(!key) break; // printf("We are now here: %ld\n", key - output_buffer); - printf("We are now here: %s\n", key); + verbose("We are now here: %s\n", key); // jump over the content... content_start = key; while((key = memchr(key, '\n', output_buffer_length - (key - output_buffer)))) { if(!key) { - warnx("out at %p\n", key); + verbose("out at %p\n", key); break; } else { key++; @@ -154,7 +167,7 @@ void * next_customer(size_t new_socket) { if(key[0] == '-') { if(0 == strncmp(&key[strspn(key, "-")], boundary, boundary_length)) { - puts("GEIL1"); + verbose("> boundary found."); if(key[-1] == '\n') key--; if(key[-1] == '\r') key--; @@ -171,7 +184,7 @@ void * next_customer(size_t new_socket) { } } - printf("content is %p - %p = %ld in size\n", content_end, content_start, content_end - content_start); + verbose("content is %p - %p = %ld in size\n", content_end, content_start, content_end - content_start); if(content_end - content_start > 1000) { FILE * f_w = fopen("/tmp/test.gif", "w"); fwrite(content_start, content_end - content_start, 1, f_w); @@ -186,16 +199,13 @@ void * next_customer(size_t new_socket) { // usleep(100000); } - - puts("> sending answer..."); - FILE * f_w = fdopen((size_t) new_socket, "w"); + verbose("> sending answer..."); send_answer(f_w); fclose(f_w); - fclose(q); - puts("> answer sent."); + fclose(f_r); - printf("still in knowledge of out boundary: %s\n", namevalue[0].value); + verbose("> answer sent."); return NULL; } @@ -206,19 +216,19 @@ int serve(int server_fd) { struct sockaddr_in address; socklen_t address_len = sizeof(address); - warnx("waiting for connections on server file descriptor %d", server_fd); + verbose("waiting for connections on server file descriptor %d", server_fd); size_t new_socket = -1; - while(-1 != - (new_socket = accept(server_fd, - (struct sockaddr*) &address, - &address_len))) + while(-1 != (new_socket = accept(server_fd, (struct sockaddr*) &address, &address_len))) { - warnx("> Client %ld is connected via port %d", new_socket, address.sin_port); + verbose("> Client %ld is connected via port %d", new_socket, address.sin_port); // set non blocking mode... - fcntl((size_t) new_socket, F_SETFL, - fcntl((size_t) new_socket, F_GETFL) | O_NONBLOCK); + fcntl( + (size_t) new_socket, + F_SETFL, + fcntl((size_t) new_socket, F_GETFL) | O_NONBLOCK + ); next_customer(new_socket); -- cgit v1.2.3