diff --git a/include/event_loop.h b/include/event_loop.h index 1830cb2..43d21a7 100644 --- a/include/event_loop.h +++ b/include/event_loop.h @@ -9,7 +9,7 @@ #define EVENT_LOOP_BUFFER_SIZE 1024 /** - * Represents an active connection managed by the event loop + * State of a connection */ typedef enum { event_loop_conn_state_req = 0, @@ -17,14 +17,17 @@ typedef enum { event_loop_conn_state_end = 2, } event_loop_conn_state; +/** + * Represents an active connection managed by the event loop + */ typedef struct event_loop_conn { int fd; event_loop_conn_state state; - // buffer for reading + // Read buffer size_t rbuf_size; size_t rbuf_read; uint8_t rbuf[EVENT_LOOP_BUFFER_SIZE]; - // buffer for writing + // Write buffer size_t wbuf_size; size_t wbuf_sent; uint8_t wbuf[EVENT_LOOP_BUFFER_SIZE]; @@ -32,6 +35,7 @@ typedef struct event_loop_conn { // If true, the server will close the connection after the final write buffer // has been written bool close_after_write; + // Context for a request void *ctx; } event_loop_conn; @@ -47,23 +51,27 @@ typedef struct event_loop { void *(*ctx_init)(void *gctx); // Function to free a context for a connection void (*ctx_free)(void *ctx); + // Function that processes incoming data bool (*handle_data)(event_loop_conn *conn); } event_loop; /* - * Initialize a new event_loop_conn struct + * Initialize a new connection struct */ event_loop_conn *event_loop_conn_init(event_loop *el); +/* + * Free a connection struct + */ void event_loop_conn_free(event_loop *el, event_loop_conn *conn); /* - * Process data on a connection + * Handle I/O for a connection, be it reading input or writing output. */ void event_loop_conn_io(event_loop *el, event_loop_conn *conn); /* - * Initialize a new event_loop struct + * Initialize a new event loop struct */ event_loop *event_loop_init(); diff --git a/include/http.h b/include/http.h index 435e2dd..51735d9 100644 --- a/include/http.h +++ b/include/http.h @@ -6,7 +6,8 @@ #include "picohttpparser.h" #include "event_loop.h" -#include "http_req.h" + +#define HTTP_MAX_ALLOWED_HEADERS 8 extern const char http_404[]; extern const size_t http_404_len; @@ -15,6 +16,27 @@ extern const size_t http_405_len; extern const char http_500[]; extern const size_t http_500_len; +typedef enum http_request_method { + http_request_method_get = 0, + http_request_method_post = 1, + http_request_method_put = 2, + http_request_method_patch = 3, + http_request_method_delete = 4 +} http_request_method; + +/* + * Struct representing the specific type of request + */ +typedef struct http_request { + size_t len; + int minor_version; + const char *method; + size_t method_len; + const char *path; + size_t path_len; + struct phr_header headers[HTTP_MAX_ALLOWED_HEADERS]; +} http_request; + typedef enum http_parse_error { http_parse_error_ok = 0, http_parse_error_incomplete = 1, @@ -24,7 +46,7 @@ typedef enum http_parse_error { http_parse_error http_parse_request(http_request *req, const char *path, size_t path_len); -void http_route(event_loop_conn *conn); +/* void http_route(event_loop_conn *conn); */ typedef enum http_response_type { http_not_found = 404, diff --git a/include/http_loop.h b/include/http_loop.h index 8291c81..7b41d4a 100644 --- a/include/http_loop.h +++ b/include/http_loop.h @@ -1,17 +1,36 @@ #ifndef LANDER_HTTP_LOOP #define LANDER_HTTP_LOOP +#include + #include "event_loop.h" -#include "http_req.h" +#include "http.h" #include "trie.h" +typedef enum http_route_type { + http_route_literal = 0, + http_route_regex = 1, +} http_route_type; + +typedef struct http_route { + http_route_type type; + char *path; + regex_t *regex; + size_t step_count; + void (**steps)(event_loop_conn *); +} http_route; + /* * Global context passed to every connection using the same pointer */ typedef struct http_loop_gctx { + http_route **routes; Trie *trie; } http_loop_gctx; +/* + * Initialize a new global context + */ http_loop_gctx *http_loop_gctx_init(); /* @@ -19,15 +38,31 @@ http_loop_gctx *http_loop_gctx_init(); */ typedef struct http_loop_ctx { http_request req; + http_route *route; + size_t current_step; http_loop_gctx *g; } http_loop_ctx; +/* + * Initialize a context struct + */ http_loop_ctx *http_loop_ctx_init(http_loop_gctx *g); +/* + * Free a context struct + */ void http_loop_ctx_free(http_loop_ctx *ctx); +/** + * Process incoming data as an HTTP request + */ bool http_loop_handle_request(event_loop_conn *conn); +void http_loop_process_request(event_loop_conn *conn); + +/** + * Initialize a new http loop + */ event_loop *http_loop_init(http_loop_gctx *gctx); #endif diff --git a/include/http_req.h b/include/http_req.h deleted file mode 100644 index 7069142..0000000 --- a/include/http_req.h +++ /dev/null @@ -1,31 +0,0 @@ -#ifndef HTTP_REQ -#define HTTP_REQ - -#include - -#include "picohttpparser.h" - -#define HTTP_MAX_ALLOWED_HEADERS 16 - -typedef enum http_request_method { - http_request_method_get = 0, - http_request_method_post = 1, - http_request_method_put = 2, - http_request_method_patch = 3, - http_request_method_delete = 4 -} http_request_method; - -/* - * Struct representing the specific type of request - */ -typedef struct http_request { - size_t len; - int minor_version; - const char *method; - size_t method_len; - const char *path; - size_t path_len; - struct phr_header headers[HTTP_MAX_ALLOWED_HEADERS]; -} http_request; - -#endif diff --git a/src/event_loop/event_loop.c b/src/event_loop/event_loop.c index 6142d22..53317bc 100644 --- a/src/event_loop/event_loop.c +++ b/src/event_loop/event_loop.c @@ -172,7 +172,7 @@ void event_loop_run(event_loop *el, int port) { // poll for active fds // the timeout argument doesn't matter here - int rv = poll(poll_args, (nfds_t)poll_args_count, 0); + int rv = poll(poll_args, (nfds_t)poll_args_count, -1); if (rv < 0) { critical(1, "Poll failed, errno: %i", errno); diff --git a/src/event_loop/event_loop_io.c b/src/event_loop/event_loop_io.c index ab116d6..50c625f 100644 --- a/src/event_loop/event_loop_io.c +++ b/src/event_loop/event_loop_io.c @@ -109,7 +109,6 @@ void event_loop_conn_io(event_loop *el, event_loop_conn *conn) { case event_loop_conn_state_res: event_loop_conn_io_res(conn); break; - case event_loop_conn_state_end: - break; + case event_loop_conn_state_end:; } } diff --git a/src/http_loop/http_loop.c b/src/http_loop/http_loop.c index 7f796de..aab5bf2 100644 --- a/src/http_loop/http_loop.c +++ b/src/http_loop/http_loop.c @@ -31,7 +31,7 @@ bool http_loop_handle_request(event_loop_conn *conn) { if (res == http_parse_error_ok) { // Perform the request - http_route(conn); + /* http_route(conn); */ } // Both in the case of an invalid HTTP request or one that's larger than the // read buffer, we cannot determine when the next, possibly valid, HTTP diff --git a/src/http_loop/http_loop_route.c b/src/http_loop/http_loop_route.c index cbd5f49..a8eb86e 100644 --- a/src/http_loop/http_loop_route.c +++ b/src/http_loop/http_loop_route.c @@ -3,11 +3,11 @@ #include "event_loop.h" #include "http.h" -typedef void (*routing_func)(event_loop_conn *); +void http_loop_process_request(event_loop_conn *conn) {} -void http_route(event_loop_conn *conn) { - // TODO routing +/* void http_route(event_loop_conn *conn) { */ +/* // TODO routing */ - // Fallthrough is to return a 404 - http_write_standard_response(conn, http_not_found); -} +/* // Fallthrough is to return a 404 */ +/* http_write_standard_response(conn, http_not_found); */ +/* } */ diff --git a/src/main.c b/src/main.c index 3fa415d..c72e604 100644 --- a/src/main.c +++ b/src/main.c @@ -1,8 +1,21 @@ #include +#include "http.h" #include "http_loop.h" #include "log.h" +void http_write_404(event_loop_conn *conn) { + memcpy(conn->wbuf, http_404, http_404_len); + + conn->state = event_loop_conn_state_res; + conn->wbuf_size = http_404_len; + conn->wbuf_sent = 0; +} + +void (*steps[])(event_loop_conn *) = {http_write_404, NULL}; +http_route routes[] = { + {.type = http_route_literal, .path = "/", .step_count = 1, .steps = steps}}; + int main() { setvbuf(stdout, NULL, _IONBF, 0);