diff --git a/include/event_loop.h b/include/event_loop.h index c18cd41..e57f523 100644 --- a/include/event_loop.h +++ b/include/event_loop.h @@ -47,50 +47,90 @@ typedef struct event_loop { size_t connection_count; // Global context passed to every connection void *gctx; - // Function to initialize a context for a connection + /** + * Function to initialize a connection context. + * + * @param gctx global context of the event loop + * @return pointer to the allocated object. + */ void *(*ctx_init)(void *gctx); - // Function to free a context for a connection + /** + * Function to free a connection context object. + * + * @param ctx context to free + */ void (*ctx_free)(void *ctx); - // Function that processes incoming data + /** + * Function to process incoming data while in the req state. + * + * @param conn connection to process + * @return whether the function can be called again immediately in the same + * event loop cycle. This allows quicly processing multiple requests without + * waiting for I/O. + */ bool (*handle_data)(event_loop_conn *conn); - // Function that writes outgoing data + /** + * Function to process outgoing data while in the res state. + * + * @param conn connection to proces + */ void (*write_data)(event_loop_conn *conn); } event_loop; /* * Initialize a new connection struct + * + * @param el the event loop + * @return pointer to the newly allocated connection struct */ event_loop_conn *event_loop_conn_init(event_loop *el); /* * Free a connection struct + * + * @param el the event loop + * @param conn connection struct to free */ void event_loop_conn_free(event_loop *el, event_loop_conn *conn); /* * Handle I/O for a connection, be it reading input or writing output. + * + * @param el the event loop + * @param conn the connection to process */ void event_loop_conn_io(event_loop *el, event_loop_conn *conn); /* * Initialize a new event loop struct + * + * @return pointer to the newly allocated event loop struct */ event_loop *event_loop_init(); /* * Place a new connection into the event loop's internal array. * - * Returns -1 if the internal realloc failed + * @param el the event loop + * @param conn connection to insert + * @return 0 on success, -1 if the internal realloc failed. */ int event_loop_put(event_loop *el, event_loop_conn *conn); /** * Accept a new connection for the given file descriptor. + * + * @param el the event loop + * @param fd file descriptor for the connection + * @return 0 if successful, negative value otherwise */ int event_loop_accept(event_loop *el, int fd); /* * Run the event loop. This function never returns. + * + * @param el the event loop + * @param port on what port to listen */ void event_loop_run(event_loop *el, int port); diff --git a/include/http/req.h b/include/http/req.h index c7ead87..15e3d98 100644 --- a/include/http/req.h +++ b/include/http/req.h @@ -12,7 +12,7 @@ #define HTTP_MAX_ALLOWED_HEADERS 16 #define HTTP_MAX_REGEX_GROUPS 4 -/* +/** * Struct representing the specific type of request */ typedef struct http_request { @@ -29,6 +29,9 @@ typedef struct http_request { size_t num_headers; } http_request; +/** + * Result of the HTTP parse function + */ typedef enum http_parse_error { http_parse_error_ok = 0, http_parse_error_incomplete = 1, diff --git a/include/http/res.h b/include/http/res.h index 6552541..6fda002 100644 --- a/include/http/res.h +++ b/include/http/res.h @@ -6,12 +6,18 @@ #include "http/types.h" +/** + * Struct describing a header for the response. + */ typedef struct http_response_header { http_header type; const char *value; bool owned; } http_response_header; +/** + * Struct representing an HTTP response. + */ typedef struct http_response { http_status status; const char *head; @@ -22,26 +28,41 @@ typedef struct http_response { size_t header_count; } http_response; -/* - * Set the request body to the given buffer. If owned is set to true, the body - * buffer will be free'd after the request has finished. +/** + * Set the request body to the given buffer. + * + * @param res response to modify + * @param body pointer to the buf containing the body + * @param body_len length of the body + * @owned whether the body should be freed after processing the request */ void http_res_set_body_buf(http_response *res, const char *body, size_t body_len, bool owned); -/* +/** * Set the request body to the given filename. + * + * @param res response to modify + * @param filename path to the file to return */ void http_res_set_body_file(http_response *res, const char *filename); -/* +/** * Add a header to the response. + * + * @param res response to modify + * @param type type of the header + * @param value value of the header + * @param owned whether the value should be freed after processing the request */ void http_res_add_header(http_response *res, http_header type, const char *value, bool owned); -/* +/** * Add a Content-Type header corresponding to the mime type. + * + * @param res response to modiy + * @param mime_type mime type of the response */ void http_res_set_mime_type(http_response *res, http_mime_type mime_type); diff --git a/include/http/types.h b/include/http/types.h index 06e3da8..25a3b54 100644 --- a/include/http/types.h +++ b/include/http/types.h @@ -147,10 +147,25 @@ typedef struct http_body { size_t len; } http_body; +/** + * Initialize a new body struct. + * + * @return pointer to the newly allocated object. + */ http_body *http_body_init(); +/** + * Reset a body, allowing it to be reused as if newly allocated. + * + * @param body body to reset + */ void http_body_reset(http_body *body); +/** + * Free a body. Internally, this calls http_body_reset. + * + * @param body body to free + */ void http_body_free(http_body *body); #endif diff --git a/include/http_loop.h b/include/http_loop.h index 9a588c5..b4b785a 100644 --- a/include/http_loop.h +++ b/include/http_loop.h @@ -9,25 +9,44 @@ #include "http/types.h" #include "trie.h" +// Max amount of steps a route can use #define HTTP_LOOP_MAX_STEPS 17 #define MIN(x, y) (((x) < (y)) ? (x) : (y)) #define MAX(x, y) (((x) > (y)) ? (x) : (y)) +/** + * Type of a route + */ typedef enum http_route_type { http_route_literal = 0, http_route_regex = 1, } http_route_type; +/** + * Function describing a step in a route's processing. + * + * @param conn connection to process + * @return whether the processing can immediately advance to the next step. A + * step should return false if it's e.g. waiting for I/O, and can therefore not + * finish its task in the current cycle of the event loop. + */ +typedef bool (*step)(event_loop_conn *conn); + +/** + * Struct describing a route a request can take. + */ typedef struct http_route { http_route_type type; http_method method; char *path; + // Compiled regex for a regex route. This value gets set at runtime when + // starting the http loop regex_t *regex; - bool (*steps[HTTP_LOOP_MAX_STEPS])(event_loop_conn *); + step steps[HTTP_LOOP_MAX_STEPS]; } http_route; -/* +/** * Global context passed to every connection using the same pointer */ typedef struct http_loop_gctx { @@ -37,12 +56,14 @@ typedef struct http_loop_gctx { const char *api_key; } http_loop_gctx; -/* +/** * Initialize a new global context + * + * @return pointer to the newly allocated object. */ http_loop_gctx *http_loop_gctx_init(); -/* +/** * Invidivual context initialized for every connection */ typedef struct http_loop_ctx { @@ -53,70 +74,116 @@ typedef struct http_loop_ctx { http_loop_gctx *g; } http_loop_ctx; -/* +/** * Initialize a context struct + * + * @param g global context + * @return pointer to the newly allocated context */ http_loop_ctx *http_loop_ctx_init(http_loop_gctx *g); -/* +/** * Resets an already allocated context so that it can be reused for a new * request. + * + * @param ctx context to reset */ void http_loop_ctx_reset(http_loop_ctx *ctx); -/* - * Free a context struct +/** + * Free a context struct. Internally this first calls http_loop_ctx_reset. + * + * @param ctx context to free */ void http_loop_ctx_free(http_loop_ctx *ctx); -/* +/** * Process incoming data as an HTTP request. This is the "handle_data" function * for the event loop. + * + * @param conn connection to process + * @return whether another request can be processed immediately. */ bool http_loop_handle_request(event_loop_conn *conn); -/* +/** * Write the HTTP response to the file descriptor. This is the "write_data" * function for the event loop. + * + * @param conn connection to process */ void http_loop_write_response(event_loop_conn *conn); -/* +/** * Try to parse the incoming data as an HTTP request. + * + * @param conn connection to process + * @return result of the parse */ http_parse_error http_loop_parse_request(event_loop_conn *conn); -/* +/** * Try to match the parsed request with one of the defined routes, aka route the * request. + * + * @param conn connection to process */ void http_loop_route_request(event_loop_conn *conn); -/* +/** * Advance the processing of the routed request's processing by cycling through * the request's various steps. + * + * @param conn connection to process */ void http_loop_process_request(event_loop_conn *conn); -/* - * Request step that consumes the request body and stores it in a buffer +/** + * Request step that consumes the request body and stores it in a buffer. + * + * @param conn connection to process + * @return true if the body has been fully received, false otherwise */ bool http_loop_step_body_to_buf(event_loop_conn *conn); +/** + * Request step that consumes the request body and stores it in a file. + * + * @param conn connection to process + * @return true if the body has been fully received, false otherwise + */ bool http_loop_step_body_to_file(event_loop_conn *conn); -/* - * Authenticate the request using the X-Api-Key header +/** + * Authenticate the request using the X-Api-Key header. + * + * @param conn connection to check + * @return always true */ bool http_loop_step_auth(event_loop_conn *conn); +/** + * A step that simply sets the connection's state to res. + * + * @param conn connection to process + * @return always true + */ bool http_loop_step_switch_res(event_loop_conn *conn); /** - * Initialize a new http loop + * Initialize a new http loop. + * + * @param gctx global context for the event loop + * @return pointer to the newly allocated object */ event_loop *http_loop_init(http_loop_gctx *gctx); +/** + * Run the HTTP loop. This function never returns. + * + * @param el the event loop + * @param port on what port to listen + */ void http_loop_run(event_loop *el, int port); #endif diff --git a/src/http_loop/http_loop_steps.c b/src/http_loop/http_loop_steps.c index bd91109..474cb72 100644 --- a/src/http_loop/http_loop_steps.c +++ b/src/http_loop/http_loop_steps.c @@ -115,7 +115,7 @@ bool http_loop_step_auth(event_loop_conn *conn) { if ((strncmp("X-Api-Key", header->name, header->name_len) == 0) && (strncmp(header->value, ctx->g->api_key, header->value_len) == 0) && - strlen(ctx->g->api_key) == header->value_len) { + (strlen(ctx->g->api_key) == header->value_len)) { return true; } }