lander/include/http_loop.h

190 lines
4.4 KiB
C
Raw Permalink Normal View History

2023-05-27 11:47:39 +02:00
#ifndef LANDER_HTTP_LOOP
#define LANDER_HTTP_LOOP
2023-05-27 15:38:06 +02:00
#include <regex.h>
2023-05-27 11:47:39 +02:00
#include "event_loop.h"
#include "http/req.h"
#include "http/res.h"
#include "http/types.h"
2023-05-27 11:47:39 +02:00
#include "trie.h"
2023-05-31 16:49:15 +02:00
// Max amount of steps a route can use
2023-05-30 19:36:58 +02:00
#define HTTP_LOOP_MAX_STEPS 17
#define MIN(x, y) (((x) < (y)) ? (x) : (y))
#define MAX(x, y) (((x) > (y)) ? (x) : (y))
2023-05-31 16:49:15 +02:00
/**
* Type of a route
*/
2023-05-27 15:38:06 +02:00
typedef enum http_route_type {
http_route_literal = 0,
http_route_regex = 1,
} http_route_type;
2023-05-31 16:49:15 +02:00
/**
* 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.
*/
2023-05-27 15:38:06 +02:00
typedef struct http_route {
http_route_type type;
http_method method;
2023-05-27 15:38:06 +02:00
char *path;
2023-05-31 16:49:15 +02:00
// Compiled regex for a regex route. This value gets set at runtime when
// starting the http loop
2023-05-27 15:38:06 +02:00
regex_t *regex;
2023-05-31 16:49:15 +02:00
step steps[HTTP_LOOP_MAX_STEPS];
2023-05-27 15:38:06 +02:00
} http_route;
2023-05-31 16:49:15 +02:00
/**
2023-05-27 11:47:39 +02:00
* Global context passed to every connection using the same pointer
*/
typedef struct http_loop_gctx {
2023-05-27 16:42:15 +02:00
http_route *routes;
size_t route_count;
2023-05-27 11:47:39 +02:00
Trie *trie;
2023-05-29 23:37:23 +02:00
const char *api_key;
2023-05-27 11:47:39 +02:00
} http_loop_gctx;
2023-05-31 16:49:15 +02:00
/**
2023-05-27 15:38:06 +02:00
* Initialize a new global context
2023-05-31 16:49:15 +02:00
*
* @return pointer to the newly allocated object.
2023-05-27 15:38:06 +02:00
*/
2023-05-27 11:47:39 +02:00
http_loop_gctx *http_loop_gctx_init();
2023-05-31 16:49:15 +02:00
/**
2023-05-27 11:47:39 +02:00
* Invidivual context initialized for every connection
*/
typedef struct http_loop_ctx {
http_request req;
http_response res;
2023-05-27 15:38:06 +02:00
http_route *route;
size_t current_step;
2023-05-27 11:47:39 +02:00
http_loop_gctx *g;
} http_loop_ctx;
2023-05-31 16:49:15 +02:00
/**
2023-05-27 15:38:06 +02:00
* Initialize a context struct
2023-05-31 16:49:15 +02:00
*
* @param g global context
* @return pointer to the newly allocated context
2023-05-27 15:38:06 +02:00
*/
2023-05-27 11:47:39 +02:00
http_loop_ctx *http_loop_ctx_init(http_loop_gctx *g);
2023-05-31 16:49:15 +02:00
/**
* Resets an already allocated context so that it can be reused for a new
* request.
2023-05-31 16:49:15 +02:00
*
* @param ctx context to reset
*/
void http_loop_ctx_reset(http_loop_ctx *ctx);
2023-05-31 16:49:15 +02:00
/**
* Free a context struct. Internally this first calls http_loop_ctx_reset.
*
* @param ctx context to free
2023-05-27 15:38:06 +02:00
*/
2023-05-27 11:47:39 +02:00
void http_loop_ctx_free(http_loop_ctx *ctx);
2023-05-31 16:49:15 +02:00
/**
* Process incoming data as an HTTP request. This is the "handle_data" function
* for the event loop.
2023-05-31 16:49:15 +02:00
*
* @param conn connection to process
* @return whether another request can be processed immediately.
2023-05-27 15:38:06 +02:00
*/
2023-05-27 11:47:39 +02:00
bool http_loop_handle_request(event_loop_conn *conn);
2023-05-31 16:49:15 +02:00
/**
* Write the HTTP response to the file descriptor. This is the "write_data"
* function for the event loop.
2023-05-31 16:49:15 +02:00
*
* @param conn connection to process
*/
void http_loop_write_response(event_loop_conn *conn);
2023-05-31 16:49:15 +02:00
/**
* Try to parse the incoming data as an HTTP request.
2023-05-31 16:49:15 +02:00
*
* @param conn connection to process
* @return result of the parse
*/
2023-05-27 17:14:49 +02:00
http_parse_error http_loop_parse_request(event_loop_conn *conn);
2023-05-31 16:49:15 +02:00
/**
* Try to match the parsed request with one of the defined routes, aka route the
* request.
2023-05-31 16:49:15 +02:00
*
* @param conn connection to process
*/
void http_loop_route_request(event_loop_conn *conn);
2023-05-27 16:42:15 +02:00
2023-05-31 16:49:15 +02:00
/**
* Advance the processing of the routed request's processing by cycling through
* the request's various steps.
2023-05-31 16:49:15 +02:00
*
* @param conn connection to process
*/
2023-05-27 15:38:06 +02:00
void http_loop_process_request(event_loop_conn *conn);
2023-05-31 16:49:15 +02:00
/**
* 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);
2023-05-31 16:49:15 +02:00
/**
* 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
*/
2023-05-30 10:17:46 +02:00
bool http_loop_step_body_to_file(event_loop_conn *conn);
2023-05-31 16:49:15 +02:00
/**
* Authenticate the request using the X-Api-Key header.
*
* @param conn connection to check
* @return always true
2023-05-29 23:37:23 +02:00
*/
bool http_loop_step_auth(event_loop_conn *conn);
2023-05-31 16:49:15 +02:00
/**
* A step that simply sets the connection's state to res.
*
* @param conn connection to process
* @return always true
*/
2023-05-30 10:17:46 +02:00
bool http_loop_step_switch_res(event_loop_conn *conn);
2023-05-27 15:38:06 +02:00
/**
2023-05-31 16:49:15 +02:00
* Initialize a new http loop.
*
* @param gctx global context for the event loop
* @return pointer to the newly allocated object
2023-05-27 15:38:06 +02:00
*/
2023-05-27 11:47:39 +02:00
event_loop *http_loop_init(http_loop_gctx *gctx);
2023-05-31 16:49:15 +02:00
/**
* Run the HTTP loop. This function never returns.
*
* @param el the event loop
* @param port on what port to listen
*/
2023-05-29 16:55:16 +02:00
void http_loop_run(event_loop *el, int port);
2023-05-27 11:47:39 +02:00
#endif