lander/include/event_loop.h

138 lines
3.3 KiB
C

#ifndef LANDER_EVENT_LOOP
#define LANDER_EVENT_LOOP
#include <stdbool.h>
#include <stdint.h>
#include <stdlib.h>
// Size of the read and write buffers for each connection, in bytes
#define EVENT_LOOP_BUFFER_SIZE 2048
/**
* State of a connection
*/
typedef enum {
event_loop_conn_state_req = 0,
event_loop_conn_state_res = 1,
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;
// Read buffer
size_t rbuf_size;
size_t rbuf_read;
uint8_t rbuf[EVENT_LOOP_BUFFER_SIZE];
// Write buffer
size_t wbuf_size;
size_t wbuf_sent;
uint8_t wbuf[EVENT_LOOP_BUFFER_SIZE];
// 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;
/*
* Main struct object representing the event loop
*/
typedef struct event_loop {
event_loop_conn **connections;
size_t connection_count;
// Global context passed to every connection
void *gctx;
/**
* 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 connection context object.
*
* @param ctx context to free
*/
void (*ctx_free)(void *ctx);
/**
* 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 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.
*
* @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);
#endif