From ace7e4b05e917056a787e7dbdf1a495bffe8c87a Mon Sep 17 00:00:00 2001 From: Alexander Rosenberg Date: Tue, 26 May 2026 00:59:38 -0700 Subject: [PATCH] Stuff for now --- http.c | 63 +++++++++++++++++---------------------- main.c | 93 ++++++++++++++++++++++------------------------------------ 2 files changed, 62 insertions(+), 94 deletions(-) diff --git a/http.c b/http.c index d36acd6..55a99aa 100644 --- a/http.c +++ b/http.c @@ -5,11 +5,10 @@ #include #include -static const char* EMPTY_STRING = ""; +static const char *EMPTY_STRING = ""; -HTTPHeaderList* http_header_list_push(HTTPHeaderList* list, const char* key, const char* value) -{ - HTTPHeaderList* new = malloc(sizeof(HTTPHeaderList)); +HTTPHeaderList *http_header_list_push(HTTPHeaderList *list, const char *key, const char *value) { + HTTPHeaderList *new = malloc(sizeof(HTTPHeaderList)); if (!new) { return NULL; } @@ -32,10 +31,9 @@ HTTPHeaderList* http_header_list_push(HTTPHeaderList* list, const char* key, con return new; } -void free_http_header_list(HTTPHeaderList* list) -{ +void free_http_header_list(HTTPHeaderList *list) { while (list) { - HTTPHeaderList* next = list->next; + HTTPHeaderList *next = list->next; free(list->key); free(list->value); free(list); @@ -43,8 +41,7 @@ void free_http_header_list(HTTPHeaderList* list) } } -const char* http_header_list_search(HTTPHeaderList* list, const char* key, const char* def) -{ +const char *http_header_list_search(HTTPHeaderList *list, const char *key, const char *def) { while (list) { if (strcmp(list->key, key) == 0) { return list->value; @@ -54,22 +51,21 @@ const char* http_header_list_search(HTTPHeaderList* list, const char* key, const return def; } -#define MAX_REQUEST_LENGTH 16384 -#define MAX_METHOD_LENGTH 16 -#define MAX_URI_LENGTH 256 -#define MAX_VERSION_LENGTH 3 -#define MAX_HEADER_KEY_LENGTH 2048 +#define MAX_REQUEST_LENGTH 16384 +#define MAX_METHOD_LENGTH 16 +#define MAX_URI_LENGTH 256 +#define MAX_VERSION_LENGTH 3 +#define MAX_HEADER_KEY_LENGTH 2048 #define MAX_HEADER_VALUE_LENGTH 2048 -#define RETURN_IF_READ_ERROR(s) \ - if (ferror((s))) { \ - return HRPR_READ_FAILED; \ +#define RETURN_IF_READ_ERROR(s) \ + if (ferror((s))) { \ + return HRPR_READ_FAILED; \ } // if an error occured, req->uri is not allocated static HTTPRequestParseResult parse_method_uri_line( - FILE* stream, size_t* restrict bytes_read, HTTPRequest* restrict req) -{ + FILE *stream, size_t *restrict bytes_read, HTTPRequest *restrict req) { // allow for some leeway in passing incorrect methods char method[MAX_METHOD_LENGTH + 1]; char uri[MAX_URI_LENGTH + 1]; @@ -77,7 +73,7 @@ static HTTPRequestParseResult parse_method_uri_line( char whitespace[4]; ssize_t signed_bytes_read; #define S1(s) #s -#define S(s) S1(s) +#define S(s) S1(s) int nconv = fscanf(stream, // clang-format off "%" S(MAX_METHOD_LENGTH) "[A-Z]" @@ -113,9 +109,8 @@ static HTTPRequestParseResult parse_method_uri_line( // return true if there are more headers and no error occurred, false otherwise // this will *not* free LIST if an error occurs -static bool next_header(FILE* stream, size_t* restrict bytes_read, - HTTPRequestParseResult* restrict res, HTTPHeaderList* restrict* restrict list) -{ +static bool next_header(FILE *stream, size_t *restrict bytes_read, + HTTPRequestParseResult *restrict res, HTTPHeaderList *restrict *restrict list) { char c = fgetc(stream); RETURN_IF_READ_ERROR(stream); if (c == '\r') { @@ -135,7 +130,7 @@ static bool next_header(FILE* stream, size_t* restrict bytes_read, char whitespace[3]; ssize_t signed_bytes_read; #define S1(s) #s -#define S(s) S1(s) +#define S(s) S1(s) int nconv = fscanf(stream, // clang-format off "%" S(MAX_HEADER_KEY_LENGTH) "[a-zA-Z0-9.-]" @@ -159,8 +154,7 @@ static bool next_header(FILE* stream, size_t* restrict bytes_read, return true; } -HTTPRequestParseResult parse_http_request(FILE* stream, HTTPRequest* restrict out) -{ +HTTPRequestParseResult parse_http_request(FILE *stream, HTTPRequest *restrict out) { out->uri = EMPTY_STRING; out->path = EMPTY_STRING; out->method = EMPTY_STRING; @@ -180,22 +174,20 @@ HTTPRequestParseResult parse_http_request(FILE* stream, HTTPRequest* restrict ou return res; } -void free_http_request(HTTPRequest* restrict req) -{ +void free_http_request(HTTPRequest *restrict req) { if (req->method != EMPTY_STRING) { - free((char*)req->method); + free((char *) req->method); } if (req->uri != EMPTY_STRING) { - free((char*)req->uri); + free((char *) req->uri); } free_http_header_list(req->headers); } -const char* status_code_to_message(int status, size_t* restrict length) -{ +const char *status_code_to_message(int status, size_t *restrict length) { static const struct { int code; - const char* msg; + const char *msg; size_t size; } CODES[] = { #define P(s, m) { s, m, sizeof(m) - 1 } @@ -221,13 +213,12 @@ const char* status_code_to_message(int status, size_t* restrict length) return NULL; } -void format_http_response(FILE* stream, HTTPResponse* restrict resp) -{ +void format_http_response(FILE *stream, HTTPResponse *restrict resp) { assert(status_code_to_message(resp->status, NULL)); dprintf(fileno(stream), "HTTP/1.1 %d %s\r\n", resp->status, status_code_to_message(resp->status, NULL)); dprintf(fileno(stream), "Content-Length: %zu\r\n", resp->body_length); - for (HTTPHeaderList* h = resp->headers; h; h = h->next) { + for (HTTPHeaderList *h = resp->headers; h; h = h->next) { write(fileno(stream), h->key, h->key_length); write(fileno(stream), ": ", 2); write(fileno(stream), h->value, h->value_length); diff --git a/main.c b/main.c index bde5907..8671588 100644 --- a/main.c +++ b/main.c @@ -30,7 +30,7 @@ typedef struct { bool help_flag; uint32_t port; size_t parallelism; - const char* address; + const char *address; } GlobalFlags; static const GlobalFlags DEFAULT_FLAGS = { @@ -42,8 +42,7 @@ static const GlobalFlags DEFAULT_FLAGS = { }; // Return false on failure, true on success -static bool parse_uint(const char* str, uintmax_t min, uintmax_t max, uintmax_t* output) -{ +static bool parse_uint(const char *str, uintmax_t min, uintmax_t max, uintmax_t *output) { if (isspace(*str) || *str == '+' || *str == '-') { #ifdef BAD_ERROR_REPORTING_FOR_AUTOGRADER fprintf(stderr, "Invalid Port\n"); @@ -53,7 +52,7 @@ static bool parse_uint(const char* str, uintmax_t min, uintmax_t max, uintmax_t* return false; } errno = 0; - char* endptr; + char *endptr; uintmax_t conv = strtoumax(str, &endptr, 10); if (!*str || *endptr) { #ifdef BAD_ERROR_REPORTING_FOR_AUTOGRADER @@ -74,14 +73,13 @@ static bool parse_uint(const char* str, uintmax_t min, uintmax_t max, uintmax_t* return true; } -static void parse_cli_options(int argc, const char** argv, GlobalFlags* flags) -{ +static void parse_cli_options(int argc, const char **argv, GlobalFlags *flags) { #define MAX_PARALLELISM SIZE_MAX -#define MAX_PORT 65535 +#define MAX_PORT 65535 opterr = false; int c; char pretty_flag[8]; - while ((c = getopt(argc, (char* const*)argv, ":ha:p:")) >= 0) { + while ((c = getopt(argc, (char *const *) argv, ":ha:p:")) >= 0) { if (isprint(c)) { snprintf(pretty_flag, sizeof(pretty_flag), "%c", optopt); } else { @@ -93,9 +91,7 @@ static void parse_cli_options(int argc, const char** argv, GlobalFlags* flags) #pragma GCC diagnostic pop } switch (c) { - case 'h': - flags->help_flag = true; - return; + case 'h': flags->help_flag = true; return; case 'p': { uintmax_t conv; if (!parse_uint(optarg, 1, MAX_PARALLELISM, &conv)) { @@ -103,9 +99,7 @@ static void parse_cli_options(int argc, const char** argv, GlobalFlags* flags) } flags->parallelism = conv; } break; - case 'a': - flags->address = optarg; - break; + case 'a': flags->address = optarg; break; case ':': flags->opt_error = true; log_error("flag requires argument: '%s'", pretty_flag); @@ -132,8 +126,7 @@ static void parse_cli_options(int argc, const char** argv, GlobalFlags* flags) } } -static void print_help(FILE* file) -{ +static void print_help(FILE *file) { fprintf(file, "usage: httpserver [-h] [-a ADDRESS] [-p PARALLELISM] \n"); fprintf(file, " -h print this message, then exit\n"); fprintf(file, " -p use PARALLELISM threads for processing requests (default: 1)\n"); @@ -144,16 +137,14 @@ static const int WORKER_BLOCKED_SIGNALS[] = { SIGTERM, SIGINT, SIGHUP }; static const size_t N_WORKER_BLOCKED_SIGNALS = sizeof(WORKER_BLOCKED_SIGNALS) / sizeof(int); static bool shutdown_flag = false; -static void signal_handler(int signal) -{ +static void signal_handler(int signal) { if (shutdown_flag) { _exit(signal == SIGTERM ? 0 : EXIT_FAILURE); } shutdown_flag = true; } -static void setup_signals() -{ +static void setup_signals() { struct sigaction pipe_act = { .sa_flags = 0, .sa_handler = SIG_IGN, @@ -176,27 +167,20 @@ static void setup_signals() } } -static int parse_result_to_status(HTTPRequestParseResult res) -{ +static int parse_result_to_status(HTTPRequestParseResult res) { switch (res) { - case HRPR_OK: - return 200; + case HRPR_OK: return 200; case HRPR_NO_MEM: - case HRPR_READ_FAILED: - return 500; - case HRPR_BAD_VERSION: - return 505; - case HRPR_BAD_FORMAT: - return 400; - default: - abort(); + case HRPR_READ_FAILED: return 500; + case HRPR_BAD_VERSION: return 505; + case HRPR_BAD_FORMAT: return 400; + default: abort(); } } -static void send_simple_response(FILE* stream, int status) -{ +static void send_simple_response(FILE *stream, int status) { size_t status_msg_len; - const char* status_msg = status_code_to_message(status, &status_msg_len); + const char *status_msg = status_code_to_message(status, &status_msg_len); HTTPResponse resp = { .status = status, .headers = NULL, @@ -207,20 +191,18 @@ static void send_simple_response(FILE* stream, int status) write(fileno(stream), "\n", 1); } -static void write_audit_log_entry(HTTPRequest* restrict req, int status) -{ +static void write_audit_log_entry(HTTPRequest *restrict req, int status) { fprintf(stderr, "%s,%s,%d,%s\n", req->method, req->uri, status, http_header_list_search(req->headers, "Request-ID", "0")); } static pthread_mutex_t file_access_mutex = PTHREAD_MUTEX_INITIALIZER; -static void handle_get_request(FILE* conn, HTTPRequest* restrict req) -{ +static void handle_get_request(FILE *conn, HTTPRequest *restrict req) { int status = 200; struct stat statbuf; pthread_mutex_lock(&file_access_mutex); - FILE* file_handle = fopen(req->path, "r"); + FILE *file_handle = fopen(req->path, "r"); if (!file_handle) { if (errno == ENOENT) { status = 404; @@ -262,15 +244,14 @@ static void handle_get_request(FILE* conn, HTTPRequest* restrict req) fclose(file_handle); } -static ssize_t get_content_length(HTTPRequest* restrict req) -{ - const char* text = http_header_list_search(req->headers, "Content-Length", NULL); +static ssize_t get_content_length(HTTPRequest *restrict req) { + const char *text = http_header_list_search(req->headers, "Content-Length", NULL); if (!text) { return 0; } else if (isspace(*text) || *text == '-' || *text == '+') { return -1; } - char* endptr; + char *endptr; uintmax_t conv = strtoumax(text, &endptr, 10); if (*endptr || (conv == UINTMAX_MAX && errno == ERANGE) || conv > SIZE_MAX) { return -1; @@ -278,8 +259,7 @@ static ssize_t get_content_length(HTTPRequest* restrict req) return conv; } -static void handle_put_request(FILE* conn, HTTPRequest* restrict req) -{ +static void handle_put_request(FILE *conn, HTTPRequest *restrict req) { ssize_t content_length = get_content_length(req); if (content_length < 0) { write_audit_log_entry(req, 400); @@ -297,8 +277,8 @@ static void handle_put_request(FILE* conn, HTTPRequest* restrict req) char read_buff[4096]; while (content_length) { ssize_t read_size = fread(read_buff, 1, - (size_t)content_length < sizeof(read_buff) ? (size_t)content_length - : sizeof(read_buff), + (size_t) content_length < sizeof(read_buff) ? (size_t) content_length + : sizeof(read_buff), conn); if (ferror(conn) || write(temp_fd, read_buff, read_size) < 0) { write_audit_log_entry(req, 500); @@ -340,9 +320,8 @@ write_status_and_unlock: } } -static void handle_connection(void* arg) -{ - FILE* conn = arg; +static void handle_connection(void *arg) { + FILE *conn = arg; HTTPRequest req; HTTPRequestParseResult res = parse_http_request(conn, &req); if (res != HRPR_OK) { @@ -365,13 +344,11 @@ static void handle_connection(void* arg) fclose(conn); } -static void fclose_free_func(void* file) -{ +static void fclose_free_func(void *file) { fclose(file); } -int main(int argc, const char** argv) -{ +int main(int argc, const char **argv) { setenv("POSIXLY_CORRECT", "1", true); GlobalFlags flags = DEFAULT_FLAGS; parse_cli_options(argc, argv, &flags); @@ -386,11 +363,11 @@ int main(int argc, const char** argv) for (size_t i = 0; i < N_WORKER_BLOCKED_SIGNALS; ++i) { sigaddset(&worker_block_set, WORKER_BLOCKED_SIGNALS[i]); } - Server* server = make_server(flags.address, flags.port); + Server *server = make_server(flags.address, flags.port); if (!server) { return EXIT_FAILURE; } - ThreadPool* pool = make_thread_pool(flags.parallelism, worker_block_set); + ThreadPool *pool = make_thread_pool(flags.parallelism, worker_block_set); if (!pool) { destroy_server(server); return EXIT_FAILURE; @@ -406,7 +383,7 @@ int main(int argc, const char** argv) } else if (conn_fd < 0) { continue; } - FILE* conn = fdopen(conn_fd, "r+"); + FILE *conn = fdopen(conn_fd, "r+"); if (!conn) { close(conn_fd); continue;