From 0d5c6d0f39223b64b5d1e6bbee3f6db65e0c3ead Mon Sep 17 00:00:00 2001 From: Chewing_Bever Date: Tue, 30 May 2023 12:14:29 +0200 Subject: [PATCH] refactor: move steps to own file --- .dockerignore | 9 ++- src/http_loop/http_loop_steps.c | 132 ++++++++++++++++++++++++++++++++ src/http_loop/http_loop_tools.c | 131 ------------------------------- 3 files changed, 138 insertions(+), 134 deletions(-) create mode 100644 src/http_loop/http_loop_steps.c diff --git a/.dockerignore b/.dockerignore index 2384fae..5f57aa4 100644 --- a/.dockerignore +++ b/.dockerignore @@ -1,3 +1,6 @@ -CMakeFiles/ -build/ -.git/ +* + +!src/ +!Makefile +!thirdparty/ +!include/ diff --git a/src/http_loop/http_loop_steps.c b/src/http_loop/http_loop_steps.c new file mode 100644 index 0000000..f12dfea --- /dev/null +++ b/src/http_loop/http_loop_steps.c @@ -0,0 +1,132 @@ +#include + +#include "lander.h" + +/* + * Converts a string to a number, returning true if the string contained a valid + * positive number. + */ +static bool string_to_num(size_t *res, const char *s, size_t len) { + *res = 0; + + for (size_t i = 0; i < len; i++) { + int val = s[i] - '0'; + + if (val < 0 || val > 9) { + return false; + } + + *res += val * (int)pow(10, (len - 1) - i); + } + + return true; +} + +/* + * Try to find and parse the Content-Length header. This function returns true + * if it was successful. If false is returned, the underlying step should + * immediately exit. + */ +static bool try_parse_content_length(event_loop_conn *conn) { + http_loop_ctx *ctx = conn->ctx; + + for (size_t i = 0; i < ctx->req.num_headers; i++) { + struct phr_header *header = &ctx->req.headers[i]; + + if (strncmp(header->name, "Content-Length", header->name_len) == 0) { + // If the content length header is present but contains an invalid + // number, we return a bad request error + if (!string_to_num(&ctx->req.body_len, header->value, + header->value_len)) { + ctx->res.status = http_bad_request; + conn->state = event_loop_conn_state_res; + + return false; + } + // The content length was actually 0, so we can instantly return here + else if (ctx->req.body_len == 0) { + return false; + } + } + } + + // A zero here means there's no content length header + if (ctx->req.body_len == 0) { + ctx->res.status = http_length_required; + conn->state = event_loop_conn_state_res; + + return false; + } + + return true; +} + +bool http_loop_step_body_to_buf(event_loop_conn *conn) { + http_loop_ctx *ctx = conn->ctx; + + if (ctx->req.body_len == 0) { + if (!try_parse_content_length(conn)) { + return true; + } + + ctx->req.body_type = http_body_buf; + ctx->req.body.buf = malloc(ctx->req.body_len * sizeof(uint8_t)); + ctx->req.body_received = 0; + } + + size_t bytes_to_copy = MIN(conn->rbuf_size - conn->rbuf_read, + ctx->req.body_len - ctx->req.body_received); + memcpy(&ctx->req.body.buf[ctx->req.body_received], + &conn->rbuf[conn->rbuf_read], bytes_to_copy); + ctx->req.body_received += bytes_to_copy; + conn->rbuf_read += bytes_to_copy; + + return ctx->req.body_received == ctx->req.body_len; +} + +bool http_loop_step_body_to_file(event_loop_conn *conn) { + http_loop_ctx *ctx = conn->ctx; + + if (ctx->req.body_len == 0) { + if (!try_parse_content_length(conn)) { + return true; + } + + ctx->req.body_type = http_body_file; + ctx->req.body.file = fopen(ctx->req.body_file_name, "wb"); + ctx->req.body_received = 0; + } + + size_t bytes_to_write = MIN(conn->rbuf_size - conn->rbuf_read, + ctx->req.body_len - ctx->req.body_received); + size_t bytes_written = fwrite(&conn->rbuf[conn->rbuf_read], sizeof(uint8_t), + bytes_to_write, ctx->req.body.file); + ctx->req.body_received += bytes_written; + conn->rbuf_read += bytes_written; + + return ctx->req.body_received == ctx->req.body_len; +} + +bool http_loop_step_auth(event_loop_conn *conn) { + http_loop_ctx *ctx = conn->ctx; + + for (size_t i = 0; i < ctx->req.num_headers; i++) { + struct phr_header *header = &ctx->req.headers[i]; + + if ((strncmp("X-Api-Key", header->name, header->name_len) == 0) && + (strncmp(header->value, ctx->g->api_key, header->value_len) == 0)) { + return true; + } + } + + ctx->res.status = http_unauthorized; + conn->state = event_loop_conn_state_res; + + return true; +} + +bool http_loop_step_switch_res(event_loop_conn *conn) { + conn->state = event_loop_conn_state_res; + + return true; +} diff --git a/src/http_loop/http_loop_tools.c b/src/http_loop/http_loop_tools.c index aa5a71e..b1c5e8d 100644 --- a/src/http_loop/http_loop_tools.c +++ b/src/http_loop/http_loop_tools.c @@ -1,5 +1,3 @@ -#include -#include #include #include "http_loop.h" @@ -32,132 +30,3 @@ void http_loop_res_add_header(http_loop_ctx *ctx, http_header type, ctx->res.header_count++; } - -/* - * Converts a string to a number, returning true if the string contained a valid - * positive number. - */ -static bool string_to_num(size_t *res, const char *s, size_t len) { - *res = 0; - - for (size_t i = 0; i < len; i++) { - int val = s[i] - '0'; - - if (val < 0 || val > 9) { - return false; - } - - *res += val * (int)pow(10, (len - 1) - i); - } - - return true; -} - -/* - * Try to find and parse the Content-Length header. This function returns true - * if it was successful. If false is returned, the underlying step should - * immediately exit. - */ -static bool try_parse_content_length(event_loop_conn *conn) { - http_loop_ctx *ctx = conn->ctx; - - for (size_t i = 0; i < ctx->req.num_headers; i++) { - struct phr_header *header = &ctx->req.headers[i]; - - if (strncmp(header->name, "Content-Length", header->name_len) == 0) { - // If the content length header is present but contains an invalid - // number, we return a bad request error - if (!string_to_num(&ctx->req.body_len, header->value, - header->value_len)) { - ctx->res.status = http_bad_request; - conn->state = event_loop_conn_state_res; - - return false; - } - // The content length was actually 0, so we can instantly return here - else if (ctx->req.body_len == 0) { - return false; - } - } - } - - // A zero here means there's no content length header - if (ctx->req.body_len == 0) { - ctx->res.status = http_length_required; - conn->state = event_loop_conn_state_res; - - return false; - } - - return true; -} - -bool http_loop_step_body_to_buf(event_loop_conn *conn) { - http_loop_ctx *ctx = conn->ctx; - - if (ctx->req.body_len == 0) { - if (!try_parse_content_length(conn)) { - return true; - } - - ctx->req.body_type = http_body_buf; - ctx->req.body.buf = malloc(ctx->req.body_len * sizeof(uint8_t)); - ctx->req.body_received = 0; - } - - size_t bytes_to_copy = MIN(conn->rbuf_size - conn->rbuf_read, - ctx->req.body_len - ctx->req.body_received); - memcpy(&ctx->req.body.buf[ctx->req.body_received], - &conn->rbuf[conn->rbuf_read], bytes_to_copy); - ctx->req.body_received += bytes_to_copy; - conn->rbuf_read += bytes_to_copy; - - return ctx->req.body_received == ctx->req.body_len; -} - -bool http_loop_step_body_to_file(event_loop_conn *conn) { - http_loop_ctx *ctx = conn->ctx; - - if (ctx->req.body_len == 0) { - if (!try_parse_content_length(conn)) { - return true; - } - - ctx->req.body_type = http_body_file; - ctx->req.body.file = fopen(ctx->req.body_file_name, "wb"); - ctx->req.body_received = 0; - } - - size_t bytes_to_write = MIN(conn->rbuf_size - conn->rbuf_read, - ctx->req.body_len - ctx->req.body_received); - size_t bytes_written = fwrite(&conn->rbuf[conn->rbuf_read], sizeof(uint8_t), - bytes_to_write, ctx->req.body.file); - ctx->req.body_received += bytes_written; - conn->rbuf_read += bytes_written; - - return ctx->req.body_received == ctx->req.body_len; -} - -bool http_loop_step_auth(event_loop_conn *conn) { - http_loop_ctx *ctx = conn->ctx; - - for (size_t i = 0; i < ctx->req.num_headers; i++) { - struct phr_header *header = &ctx->req.headers[i]; - - if ((strncmp("X-Api-Key", header->name, header->name_len) == 0) && - (strncmp(header->value, ctx->g->api_key, header->value_len) == 0)) { - return true; - } - } - - ctx->res.status = http_unauthorized; - conn->state = event_loop_conn_state_res; - - return true; -} - -bool http_loop_step_switch_res(event_loop_conn *conn) { - conn->state = event_loop_conn_state_res; - - return true; -}