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("", 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