From 3d65bba1403b940c5336921aad64d938f89b5713 Mon Sep 17 00:00:00 2001 From: Max Christian Pohle Date: Sat, 20 Nov 2021 03:18:51 +0100 Subject: A little code cleaning and commenting --- main.c | 96 +++++++++++++++++++++++++++++------------------------------------- 1 file changed, 42 insertions(+), 54 deletions(-) diff --git a/main.c b/main.c index 2a01a4e..3388a36 100644 --- a/main.c +++ b/main.c @@ -36,13 +36,13 @@ static inline int verbose(const char * format, ...) { // }}} typedef struct { - int newline_length; // lenght of one newline in bytes (\n has 1, CR/LF has 2) - char * method; - char * boundary; - size_t boundary_size; - char * content_type; - char * content_disposition; - char * url; + int newline_length; // lenght of one newline in bytes (\n has 1, CR/LF has 2) + char * method; // GET/POST or something like that + char * url; // request URL (e.g. /index.html) + char * boundary; // usually looks similar to ------1234 + size_t boundary_size; // size in bytes, calculated after first header complete; is an indicator for the first header + char * content_type; // sometimes 'text/html', also sometimes 'text/html; boundary=------1234' + char * content_disposition; // includes file names of uploaded files or field names with form-data (e.g. curl -F) } Http_Header; void send_answer(int fd_socket, Http_Header * http_header) { @@ -57,24 +57,11 @@ void send_answer(int fd_socket, Http_Header * http_header) { fstat(file, &stat); sendfile (fileno(f), file, NULL, stat.st_size); } else { - fprintf(f, "could not open file \"%s\"\n", &http_header->url[1]); + if(http_header->url) // TODO: too dangerous to check that here, that is too late. + fprintf(f, "could not open file \"%s\"\n", &http_header->url[1]); } fclose(f); - - // fputs("", f); - // fputs("", f); - // fputs("test", f); - // fputs("", f); - // fputs("", f); - // fputs("
", f); - // fputs("
\n", f); - // fputs("", f); - // fputs("", f); - // fputs("
", f); - // fputs("", f); } int read_everything(FILE * f_r, FILE * output) { @@ -106,10 +93,8 @@ void * next_customer(size_t new_socket) { size_t output_buffer_length = 0; FILE * output = open_memstream(&output_buffer, &output_buffer_length); - DEBUG("\n\n########################################## Content Reader [%d]\n", f_r); - read_everything(f_r, output); + read_everything(f_r, output); // TODO: catch return value and error handling shutdown(new_socket, SHUT_RD); // shutdown the reading half of the connection - DEBUG("\n\n########################################## Content Parser\n"); char * start = output_buffer; char * end = NULL; @@ -118,24 +103,25 @@ void * next_customer(size_t new_socket) { Http_Header http_header = {0}; char * name = NULL; - while(NULL != (end = strpbrk(start, search))) { + while(NULL != (end = strpbrk(start, search))) { // TODO: try harder to break things (are SEGFAULTs possible?) size_t matchlen = strspn(end, search); switch(end[0]) { case ':': end[0] = '\0'; // {{{ remember header 'names' and search for the value - end++; + end++; // jump over the colon - name = start; + name = start; // remember, where name starts, will be important in the newline case if (0 == strcasecmp("Content-Type", start)) { - search = "\r\n;"; + search = "\r\n;"; // (more unlikely) also search for a semicolon in Content-Type: [...]; boundary=[...] } else { - search = "\r\n"; + search = "\r\n"; // (likely) search for some kind of newline } // }}} break; case ';': - start += strspn(start, "; "); // {{{ find the form-data boundary in the main header + // {{{ find the form-data boundary in the main header + start += strspn(start, "; "); // remove spaces and semicolons (boundary check implicit; also stops at '\0') const char s_multipart_form_data[] = "boundary="; if(NULL == http_header.boundary && 0 < strcasecmp(start, s_multipart_form_data)) @@ -248,14 +234,14 @@ void * next_customer(size_t new_socket) { int serve(int server_fd) { - struct sockaddr_in address; + struct sockaddr_in address; socklen_t address_len = sizeof(address); - DEBUG("waiting for connections on server file descriptor %d", server_fd); + DEBUG("> Waiting for connections on server file descriptor %d\n", server_fd); size_t new_socket = -1; - while(-1 != (new_socket = accept(server_fd, (struct sockaddr*) &address, &address_len))) - { - DEBUG("> Client %ld is connected via port %d", new_socket, address.sin_port); + while(-1 != (new_socket = accept(server_fd, (struct sockaddr*) &address, &address_len))) + { + DEBUG("> Client %ld is connected via port %d\n", new_socket, address.sin_port); // set non blocking mode... fcntl( @@ -269,33 +255,35 @@ int serve(int server_fd) #ifdef VALGRIND break; // only run once, so that valgrind can test allocations&frees #endif - } + } err(errno, "error serving"); close(server_fd); } -#define PORT 8080 -int main(int argc, char const *argv[]) -{ - int server_fd = -1, opt = 1; +int main(const int argc, char const * argv[]) { + int server_fd = -1, opt = 1; + + int port = atoi(argc > 1 ? argv[1] : "8080"); + 0 == port ? port = 8080 : port; - struct sockaddr_in address = { - .sin_family = AF_INET, - .sin_addr.s_addr = INADDR_ANY, - .sin_port = htons(PORT) + + struct sockaddr_in address = { + .sin_family = AF_INET, + .sin_addr.s_addr = INADDR_ANY, + .sin_port = htons(port) }; // I <3 C - 0 == (server_fd = socket(AF_INET, SOCK_STREAM, 0)) - ? err(errno, NULL) - : setsockopt(server_fd, SOL_SOCKET, SO_REUSEADDR | SO_REUSEPORT, &opt, sizeof(opt)) - ? err(errno, "setsockopt failed on socket with fileno %d", server_fd) - : bind(server_fd, (struct sockaddr*) &address, sizeof(address)) - ? err(errno, NULL) - : listen(server_fd, SOMAXCONN) - ? err(errno, NULL) - : serve(server_fd) + 0 == (server_fd = socket(AF_INET, SOCK_STREAM, 0)) + ? err(errno, NULL) + : setsockopt(server_fd, SOL_SOCKET, SO_REUSEADDR | SO_REUSEPORT, &opt, sizeof(opt)) + ? err(errno, "setsockopt failed on socket with fileno %d", server_fd) + : bind(server_fd, (struct sockaddr*) &address, sizeof(address)) + ? err(errno, NULL) + : listen(server_fd, SOMAXCONN) + ? err(errno, NULL) + : serve(server_fd) ? err(errno, NULL) : exit(EXIT_SUCCESS) ; return EXIT_FAILURE; -- cgit v1.2.3