chore: copy over original source files
This commit is contained in:
commit
2681801a1e
27 changed files with 3082 additions and 0 deletions
89
include/lnm/common.h
Normal file
89
include/lnm/common.h
Normal file
|
|
@ -0,0 +1,89 @@
|
|||
#ifndef LNM_COMMON
|
||||
#define LNM_COMMON
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#define LNM_RES(x) \
|
||||
{ \
|
||||
lnm_err res = x; \
|
||||
if (res != lnm_err_ok) \
|
||||
return res; \
|
||||
}
|
||||
|
||||
#define LNM_RES2(x, e) \
|
||||
{ \
|
||||
lnm_err res = x; \
|
||||
if (res != lnm_err_ok) { \
|
||||
e; \
|
||||
return res; \
|
||||
} \
|
||||
}
|
||||
|
||||
#define LNM_MIN(x, y) ((x) < (y) ? (x) : (y))
|
||||
#define LNM_MAX(x, y) ((x) > (y) ? (x) : (y))
|
||||
|
||||
typedef enum lnm_err {
|
||||
lnm_err_ok = 0,
|
||||
lnm_err_failed_alloc,
|
||||
lnm_err_failed_network,
|
||||
lnm_err_failed_poll,
|
||||
lnm_err_not_setup,
|
||||
lnm_err_bad_regex,
|
||||
lnm_err_not_found,
|
||||
} lnm_err;
|
||||
|
||||
typedef struct lnm_loop lnm_http_loop;
|
||||
|
||||
typedef struct lnm_loop_conn lnm_http_conn;
|
||||
|
||||
typedef struct lnm_http_step lnm_http_step;
|
||||
|
||||
typedef struct lnm_http_route lnm_http_route;
|
||||
|
||||
/**
|
||||
* Returns whether the two strings are equal.
|
||||
*
|
||||
* @param s1 first string to compare
|
||||
* @param s1_len length of `s1`
|
||||
* @param s2 second string to compare
|
||||
* @param s2_len length of `s2`
|
||||
*/
|
||||
bool lnm_strneq(const char *s1, size_t s1_len, const char *s2, size_t s2_len);
|
||||
|
||||
/**
|
||||
* Returns whether the two strings are equal, ignoring capitalisation.
|
||||
*
|
||||
* @param s1 first string to compare
|
||||
* @param s1_len length of `s1`
|
||||
* @param s2 second string to compare
|
||||
* @param s2_len length of `s2`
|
||||
*/
|
||||
bool lnm_strnieq(const char *s1, size_t s1_len, const char *s2, size_t s2_len);
|
||||
|
||||
/**
|
||||
* Calculate integer exponentation.
|
||||
*
|
||||
* @param base
|
||||
* @param power
|
||||
*/
|
||||
uint64_t lnm_ipow(uint64_t base, uint64_t power);
|
||||
|
||||
/**
|
||||
* Parse the given string into a number.
|
||||
*
|
||||
* @param s string to parse
|
||||
* @param len length of s
|
||||
* @return the parsed number, or 0 if the number is invalid
|
||||
*/
|
||||
uint64_t lnm_atoi(const char *s, size_t len);
|
||||
|
||||
/**
|
||||
* Calculate how many base 10 digits the given number consists of.
|
||||
*
|
||||
* @param num number to use
|
||||
*/
|
||||
uint64_t lnm_digits(uint64_t num);
|
||||
|
||||
#endif
|
||||
98
include/lnm/http/consts.h
Normal file
98
include/lnm/http/consts.h
Normal file
|
|
@ -0,0 +1,98 @@
|
|||
#ifndef LNM_HTTP_CONSTS
|
||||
#define LNM_HTTP_CONSTS
|
||||
|
||||
#include <stdlib.h>
|
||||
|
||||
extern const char *lnm_http_method_names[];
|
||||
extern const size_t lnm_http_method_names_len;
|
||||
|
||||
typedef enum lnm_http_method {
|
||||
lnm_http_method_get = 0,
|
||||
lnm_http_method_post,
|
||||
lnm_http_method_put,
|
||||
lnm_http_method_patch,
|
||||
lnm_http_method_delete,
|
||||
lnm_http_method_head,
|
||||
} lnm_http_method;
|
||||
|
||||
extern const char *lnm_http_status_names[][32];
|
||||
|
||||
typedef enum lnm_http_status {
|
||||
// 1xx
|
||||
lnm_http_status_continue = 100,
|
||||
lnm_http_status_switching_protocols = 101,
|
||||
lnm_http_status_processing = 102,
|
||||
lnm_http_status_early_hints = 103,
|
||||
// 2xx
|
||||
lnm_http_status_ok = 200,
|
||||
lnm_http_status_created = 201,
|
||||
lnm_http_status_accepted = 202,
|
||||
lnm_http_status_non_authoritative_information = 203,
|
||||
lnm_http_status_no_content = 204,
|
||||
lnm_http_status_reset_content = 205,
|
||||
lnm_http_status_partial_content = 206,
|
||||
lnm_http_status_multi_status = 207,
|
||||
lnm_http_status_already_reported = 208,
|
||||
// 3xx
|
||||
lnm_http_status_multiple_choices = 300,
|
||||
lnm_http_status_moved_permanently = 301,
|
||||
lnm_http_status_found = 302,
|
||||
lnm_http_status_see_other = 303,
|
||||
lnm_http_status_not_modified = 304,
|
||||
lnm_http_status_temporary_redirect = 307,
|
||||
lnm_http_status_permanent_redirect = 308,
|
||||
// 4xx
|
||||
lnm_http_status_bad_request = 400,
|
||||
lnm_http_status_unauthorized = 401,
|
||||
lnm_http_status_payment_required = 402,
|
||||
lnm_http_status_forbidden = 403,
|
||||
lnm_http_status_not_found = 404,
|
||||
lnm_http_status_method_not_allowed = 405,
|
||||
lnm_http_status_not_acceptable = 406,
|
||||
lnm_http_status_proxy_authentication_required = 407,
|
||||
lnm_http_status_request_timeout = 408,
|
||||
lnm_http_status_conflict = 409,
|
||||
lnm_http_status_gone = 410,
|
||||
lnm_http_status_length_required = 411,
|
||||
lnm_http_status_precondition_failed = 412,
|
||||
lnm_http_status_content_too_large = 413,
|
||||
lnm_http_status_uri_too_long = 414,
|
||||
lnm_http_status_unsupported_media_type = 415,
|
||||
lnm_http_status_range_not_satisfiable = 416,
|
||||
lnm_http_status_expection_failed = 417,
|
||||
lnm_http_status_im_a_teapot = 418,
|
||||
lnm_http_status_misdirected_request = 421,
|
||||
lnm_http_status_unprocessable_content = 422,
|
||||
lnm_http_status_locked = 423,
|
||||
lnm_http_status_failed_dependency = 424,
|
||||
lnm_http_status_too_early = 425,
|
||||
lnm_http_status_upgrade_required = 426,
|
||||
lnm_http_status_precondition_required = 428,
|
||||
lnm_http_status_too_many_requests = 429,
|
||||
lnm_http_status_request_header_fields_too_large = 431,
|
||||
// 5xx
|
||||
lnm_http_status_internal_server_error = 500,
|
||||
lnm_http_status_method_not_implemented = 501,
|
||||
lnm_http_status_bad_gateway = 502,
|
||||
lnm_http_status_service_unavailable = 503,
|
||||
lnm_http_status_gateway_timeout = 504,
|
||||
lnm_http_status_http_status_version_not_supported = 505,
|
||||
lnm_http_status_variant_also_negotiates = 506,
|
||||
lnm_http_status_insufficient_storage = 507,
|
||||
lnm_http_status_loop_detected = 508,
|
||||
lnm_http_status_not_extended = 510,
|
||||
lnm_http_status_network_authentication_required = 511
|
||||
} lnm_http_status;
|
||||
|
||||
extern const char *lnm_http_header_names[];
|
||||
|
||||
typedef enum lnm_http_header {
|
||||
lnm_http_header_connection = 0,
|
||||
lnm_http_header_location,
|
||||
lnm_http_header_content_type,
|
||||
lnm_http_header_content_disposition,
|
||||
lnm_http_header_server,
|
||||
lnm_http_header_content_length
|
||||
} lnm_http_header;
|
||||
|
||||
#endif
|
||||
141
include/lnm/http/loop.h
Normal file
141
include/lnm/http/loop.h
Normal file
|
|
@ -0,0 +1,141 @@
|
|||
#ifndef LNM_HTTP_LOOP
|
||||
#define LNM_HTTP_LOOP
|
||||
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "lnm/common.h"
|
||||
#include "lnm/http/req.h"
|
||||
#include "lnm/http/res.h"
|
||||
|
||||
typedef enum lnm_http_step_err {
|
||||
lnm_http_step_err_done = 0,
|
||||
lnm_http_step_err_io_needed,
|
||||
lnm_http_step_err_close,
|
||||
lnm_http_step_err_res,
|
||||
} lnm_http_step_err;
|
||||
|
||||
typedef lnm_http_step_err (*lnm_http_step_fn)(lnm_http_conn *conn);
|
||||
|
||||
typedef lnm_err (*lnm_http_ctx_init_fn)(void **c_ctx, void *gctx);
|
||||
|
||||
typedef void (*lnm_http_ctx_reset_fn)(void *c_ctx);
|
||||
|
||||
typedef void (*lnm_http_ctx_free_fn)(void *c_ctx);
|
||||
|
||||
/**
|
||||
* Initialize a new `lnm_http_loop`.
|
||||
*
|
||||
* @param out where to store pointer to new `lnm_http_loop`
|
||||
*/
|
||||
lnm_err lnm_http_loop_init(lnm_http_loop **out, void *c_gctx,
|
||||
lnm_http_ctx_init_fn ctx_init,
|
||||
lnm_http_ctx_reset_fn ctx_reset,
|
||||
lnm_http_ctx_free_fn ctx_free);
|
||||
|
||||
/**
|
||||
* Initialize a new step.
|
||||
*
|
||||
* @param out where to store pointer to new `lnm_http_step`
|
||||
* @param fn step function
|
||||
*/
|
||||
lnm_err lnm_http_step_init(lnm_http_step **out, lnm_http_step_fn fn);
|
||||
|
||||
/**
|
||||
* Append the given step fn to the step.
|
||||
*
|
||||
* @param out where to store pointer to new `lnm_http_step`
|
||||
* @param step step to append new step to
|
||||
* @param fn step function
|
||||
*/
|
||||
lnm_err lnm_http_step_append(lnm_http_step **out, lnm_http_step *step,
|
||||
lnm_http_step_fn fn);
|
||||
|
||||
/**
|
||||
* Initialize a new route of type literal.
|
||||
*
|
||||
* @param out where to store pointer to new `lnm_http_route`
|
||||
* @param path literal path to match
|
||||
* @param step step to process request with
|
||||
*/
|
||||
lnm_err lnm_http_route_init_literal(lnm_http_route **out,
|
||||
lnm_http_method method, const char *path,
|
||||
lnm_http_step *step);
|
||||
|
||||
/**
|
||||
* Initialize a new route of type regex.
|
||||
*
|
||||
* @param out where to store pointer to new `lnm_http_route`
|
||||
* @param pattern regex pattern
|
||||
* @param regex_group_count how many regex groups are contained in the pattern
|
||||
* @param step step to process request with
|
||||
*/
|
||||
lnm_err lnm_http_route_init_regex(lnm_http_route **out, lnm_http_method method,
|
||||
const char *pattern, int regex_group_count,
|
||||
lnm_http_step *step);
|
||||
|
||||
/**
|
||||
* Add a new route to the HTTP route.
|
||||
*
|
||||
* @param hl HTTP loop to modify
|
||||
* @param route route to add
|
||||
*/
|
||||
lnm_err lnm_http_loop_route_add(lnm_http_loop *hl, lnm_http_route *route);
|
||||
|
||||
lnm_err lnm_http_loop_run(lnm_http_loop *hl, uint16_t port, int thread_count);
|
||||
|
||||
void lnm_http_loop_set_api_key(lnm_http_loop *hl, const char *api_key);
|
||||
|
||||
void lnm_http_loop_set_server(lnm_http_loop *hl, const char *value);
|
||||
|
||||
/**
|
||||
* Represents what state an HTTP loop request is currently in.
|
||||
*/
|
||||
typedef enum lnm_http_loop_state {
|
||||
// Parse the HTTP request
|
||||
lnm_http_loop_state_parse_req = 0,
|
||||
// Route the request
|
||||
lnm_http_loop_state_route,
|
||||
// Parse specific headers (e.g. Content-Length)
|
||||
lnm_http_loop_state_parse_headers,
|
||||
// Execute the various steps defined for the route
|
||||
lnm_http_loop_state_steps,
|
||||
// Add certain automatically added headers
|
||||
lnm_http_loop_state_add_headers,
|
||||
// Write the response status line
|
||||
lnm_http_loop_state_write_status_line,
|
||||
// Write the various response headers
|
||||
lnm_http_loop_state_write_headers,
|
||||
// Write the request body
|
||||
lnm_http_loop_state_write_body,
|
||||
// Clean up the request and reset the state for a next request
|
||||
lnm_http_loop_state_finish,
|
||||
} lnm_http_loop_state;
|
||||
|
||||
typedef struct lnm_http_loop_gctx {
|
||||
struct {
|
||||
lnm_http_route **arr;
|
||||
size_t len;
|
||||
} routes;
|
||||
lnm_http_ctx_init_fn ctx_init;
|
||||
lnm_http_ctx_reset_fn ctx_reset;
|
||||
lnm_http_ctx_free_fn ctx_free;
|
||||
const char *api_key;
|
||||
const char *server;
|
||||
void *c;
|
||||
} lnm_http_loop_gctx;
|
||||
|
||||
typedef struct lnm_http_loop_ctx {
|
||||
lnm_http_loop_state state;
|
||||
lnm_http_req req;
|
||||
lnm_http_res res;
|
||||
lnm_http_route *route;
|
||||
lnm_http_step *cur_step;
|
||||
lnm_http_loop_gctx *g;
|
||||
void *c;
|
||||
} lnm_http_loop_ctx;
|
||||
|
||||
lnm_http_step_err lnm_http_loop_step_body_to_buf(lnm_http_conn *conn);
|
||||
|
||||
lnm_http_step_err lnm_http_loop_step_auth(lnm_http_conn *conn);
|
||||
|
||||
#endif
|
||||
111
include/lnm/http/req.h
Normal file
111
include/lnm/http/req.h
Normal file
|
|
@ -0,0 +1,111 @@
|
|||
#ifndef LNM_HTTP_REQ
|
||||
#define LNM_HTTP_REQ
|
||||
|
||||
#include <regex.h>
|
||||
#include <stdint.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "picohttpparser.h"
|
||||
|
||||
#include "lnm/common.h"
|
||||
#include "lnm/http/consts.h"
|
||||
|
||||
#define LNM_HTTP_MAX_REQ_HEADERS 32
|
||||
#define LNM_HTTP_MAX_REGEX_GROUPS 4
|
||||
|
||||
typedef struct lnm_http_req_header {
|
||||
struct {
|
||||
size_t o;
|
||||
size_t len;
|
||||
} name;
|
||||
struct {
|
||||
size_t o;
|
||||
size_t len;
|
||||
} value;
|
||||
} lnm_http_req_header;
|
||||
|
||||
/**
|
||||
* Represents the parsed HTTP request
|
||||
*/
|
||||
typedef struct lnm_http_req {
|
||||
struct {
|
||||
char *s;
|
||||
size_t len;
|
||||
bool owned;
|
||||
} buf;
|
||||
int minor_version;
|
||||
lnm_http_method method;
|
||||
struct {
|
||||
size_t o;
|
||||
size_t len;
|
||||
regmatch_t groups[LNM_HTTP_MAX_REGEX_GROUPS];
|
||||
} path;
|
||||
struct {
|
||||
size_t o;
|
||||
size_t len;
|
||||
} query;
|
||||
struct {
|
||||
lnm_http_req_header arr[LNM_HTTP_MAX_REQ_HEADERS];
|
||||
size_t len;
|
||||
} headers;
|
||||
struct {
|
||||
uint64_t expected_len;
|
||||
uint64_t len;
|
||||
char *buf;
|
||||
bool owned;
|
||||
} body;
|
||||
} lnm_http_req;
|
||||
|
||||
typedef enum lnm_http_parse_err {
|
||||
lnm_http_parse_err_ok = 0,
|
||||
lnm_http_parse_err_incomplete,
|
||||
lnm_http_parse_err_invalid,
|
||||
lnm_http_parse_err_unknown_method,
|
||||
} lnm_http_parse_err;
|
||||
|
||||
/**
|
||||
* Try to parse the given buffer into an HTTP request.
|
||||
*
|
||||
* @param req request to store parsed data in
|
||||
* @param buf buffer to parse; might be modified
|
||||
* @param len length of buf
|
||||
*/
|
||||
lnm_http_parse_err lnm_http_req_parse(lnm_http_req *req, char *buf, size_t len);
|
||||
|
||||
/**
|
||||
* Reset the given request object, free'ing all its relevant parts and allowing
|
||||
* it to be reused as a new object.
|
||||
*
|
||||
* @param req object to reset
|
||||
*/
|
||||
void lnm_http_req_reset(lnm_http_req *req);
|
||||
|
||||
/**
|
||||
* Retrieve a specific header from the request.
|
||||
*
|
||||
* Pointers retrieved from this function should never be used between step
|
||||
* functions; simply request the header again if you need to.
|
||||
*
|
||||
* @param out where to write pointer to header value
|
||||
* @param out_len where to store length of out value
|
||||
* @param req request to look for header in
|
||||
* @param type type of header to look for
|
||||
*/
|
||||
lnm_err lnm_http_req_header_get(const char **out, size_t *out_len,
|
||||
lnm_http_req *req, lnm_http_header type);
|
||||
|
||||
/**
|
||||
* Retrieve a specific header from the request by specifying its name.
|
||||
*
|
||||
* Pointers retrieved from this function should never be used between step
|
||||
* functions; simply request the header again if you need to.
|
||||
*
|
||||
* @param out where to write pointer to header value
|
||||
* @param out_len where to store length of out value
|
||||
* @param req request to look for header in
|
||||
* @param name name of the header; matches case-insensitive
|
||||
*/
|
||||
lnm_err lnm_http_req_header_get_s(const char **out, size_t *out_len,
|
||||
lnm_http_req *req, const char *name);
|
||||
|
||||
#endif
|
||||
119
include/lnm/http/res.h
Normal file
119
include/lnm/http/res.h
Normal file
|
|
@ -0,0 +1,119 @@
|
|||
#ifndef LNM_HTTP_RES
|
||||
#define LNM_HTTP_RES
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#include "lnm/common.h"
|
||||
#include "lnm/http/consts.h"
|
||||
|
||||
typedef lnm_err (*data_fn)(uint64_t *written, char *buf, lnm_http_conn *conn,
|
||||
uint64_t offset, uint64_t len);
|
||||
|
||||
/**
|
||||
* Linked list elements used to store the response headers
|
||||
*/
|
||||
typedef struct lnm_http_res_header {
|
||||
struct {
|
||||
char *s;
|
||||
size_t len;
|
||||
bool owned;
|
||||
} name;
|
||||
struct {
|
||||
char *s;
|
||||
size_t len;
|
||||
bool owned;
|
||||
} value;
|
||||
struct lnm_http_res_header *next;
|
||||
} lnm_http_res_header;
|
||||
|
||||
typedef enum lnm_http_res_body_type {
|
||||
lnm_http_res_body_type_file = 0,
|
||||
lnm_http_res_body_type_buf,
|
||||
lnm_http_res_body_type_fn,
|
||||
} lnm_http_res_body_type;
|
||||
|
||||
typedef struct lnm_http_res {
|
||||
lnm_http_status status;
|
||||
struct {
|
||||
lnm_http_res_header *head;
|
||||
lnm_http_res_header *current;
|
||||
} headers;
|
||||
struct {
|
||||
struct {
|
||||
char *buf;
|
||||
FILE *f;
|
||||
data_fn fn;
|
||||
} data;
|
||||
uint64_t len;
|
||||
bool owned;
|
||||
lnm_http_res_body_type type;
|
||||
} body;
|
||||
// General-purpose; meaning depends on the current state
|
||||
uint64_t written;
|
||||
} lnm_http_res;
|
||||
|
||||
/**
|
||||
* Add a new header of a known type to the response
|
||||
*
|
||||
* @param type type of header
|
||||
* @param value null-terminated string containing the value of the header
|
||||
* @param value_owned whether to take ownership of the value pointer; if false,
|
||||
* free'ing the buffer is the caller's responsibility
|
||||
*/
|
||||
lnm_err lnm_http_res_add_header(lnm_http_res *res, lnm_http_header type,
|
||||
char *value, bool value_owned);
|
||||
|
||||
/**
|
||||
* Add a new header of a known type to the response with a given value length.
|
||||
*
|
||||
* @param type type of header
|
||||
* @param value string of length `value_len` containing the value of the header
|
||||
* @param value_len length of value
|
||||
* @param value_owned whether to take ownership of the value pointer; if false,
|
||||
* free'ing the buffer is the caller's responsibility
|
||||
*/
|
||||
lnm_err lnm_http_res_add_header_len(lnm_http_res *res, lnm_http_header type,
|
||||
char *value, size_t value_len,
|
||||
bool value_owned);
|
||||
|
||||
/**
|
||||
* Set the request body to the given file pointer.
|
||||
*
|
||||
* @param res response to modify
|
||||
* @param f file pointer to use as data
|
||||
* @param len expected length of the file
|
||||
* @param owned whether to take ownership of the file pointer
|
||||
*/
|
||||
void lnm_http_res_body_set_file(lnm_http_res *res, FILE *f, size_t len,
|
||||
bool owned);
|
||||
|
||||
/**
|
||||
* Set the request body to the given buffer.
|
||||
*
|
||||
* @param res response to modify
|
||||
* @param buf buffer to use as data
|
||||
* @param len length of the buffer
|
||||
* @param owned whether to take ownership of the file pointer
|
||||
*/
|
||||
void lnm_http_res_body_set_buf(lnm_http_res *res, char *buf, size_t len,
|
||||
bool owned);
|
||||
|
||||
/**
|
||||
* Set the request body to be read from the given data function.
|
||||
*
|
||||
* @param res response to modify
|
||||
* @param fn data reader function
|
||||
* @param len expected length of the response
|
||||
*/
|
||||
void lnm_http_res_body_set_fn(lnm_http_res *res, data_fn fn, size_t len);
|
||||
|
||||
/**
|
||||
* Reset the given response object, properly free'ing any allocated buffers,
|
||||
* allowing it to be reused for later connections.
|
||||
*
|
||||
* @param res res to reset
|
||||
*/
|
||||
void lnm_http_res_reset(lnm_http_res *res);
|
||||
|
||||
#endif
|
||||
47
include/lnm/log.h
Normal file
47
include/lnm/log.h
Normal file
|
|
@ -0,0 +1,47 @@
|
|||
#ifndef LNM_LOG
|
||||
#define LOG
|
||||
|
||||
#include <stdarg.h>
|
||||
|
||||
#include "lnm/common.h"
|
||||
|
||||
typedef struct lnm_logger lnm_logger;
|
||||
|
||||
typedef enum lnm_log_level {
|
||||
lnm_log_level_debug = 0,
|
||||
lnm_log_level_info,
|
||||
lnm_log_level_notice,
|
||||
lnm_log_level_warning,
|
||||
lnm_log_level_error,
|
||||
lnm_log_level_critical
|
||||
} lnm_log_level;
|
||||
|
||||
extern const char *lnm_log_level_names[];
|
||||
|
||||
/**
|
||||
* Initialize the global logger.
|
||||
*/
|
||||
lnm_err lnm_log_init_global();
|
||||
|
||||
/**
|
||||
* Register stdout as one of the streams for the global logger.
|
||||
*/
|
||||
lnm_err lnm_log_register_stdout(lnm_log_level level);
|
||||
|
||||
void lnm_log(lnm_log_level level, const char *section, const char *fmt, ...)
|
||||
__attribute__((format(printf, 3, 4)));
|
||||
|
||||
#define lnm_ldebug(section, fmt, ...) \
|
||||
lnm_log(lnm_log_level_debug, section, fmt, __VA_ARGS__)
|
||||
#define lnm_linfo(section, fmt, ...) \
|
||||
lnm_log(lnm_log_level_info, section, fmt, __VA_ARGS__)
|
||||
#define lnm_lnotice(section, fmt, ...) \
|
||||
lnm_log(lnm_log_level_notice, section, fmt, __VA_ARGS__)
|
||||
#define lnm_lwarning(section, fmt, ...) \
|
||||
lnm_log(lnm_log_level_warning, section, fmt, __VA_ARGS__)
|
||||
#define lnm_lerror(section, fmt, ...) \
|
||||
lnm_log(lnm_log_level_error, section, fmt, __VA_ARGS__)
|
||||
#define lnm_lcritical(section, fmt, ...) \
|
||||
lnm_log(lnm_log_level_critical, section, fmt, __VA_ARGS__)
|
||||
|
||||
#endif
|
||||
54
include/lnm/loop.h
Normal file
54
include/lnm/loop.h
Normal file
|
|
@ -0,0 +1,54 @@
|
|||
#ifndef LNM_LOOP
|
||||
#define LNM_LOOP
|
||||
|
||||
#include <stdatomic.h>
|
||||
#include <stdint.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "lnm/common.h"
|
||||
|
||||
#define LNM_LOOP_BUF_SIZE 2048
|
||||
|
||||
typedef enum {
|
||||
lnm_loop_state_req = 0,
|
||||
lnm_loop_state_res,
|
||||
lnm_loop_state_end,
|
||||
} lnm_loop_state;
|
||||
|
||||
typedef struct lnm_loop_conn {
|
||||
int fd;
|
||||
lnm_loop_state state;
|
||||
void *ctx;
|
||||
struct {
|
||||
char buf[LNM_LOOP_BUF_SIZE];
|
||||
size_t size;
|
||||
size_t read;
|
||||
} r;
|
||||
struct {
|
||||
char buf[LNM_LOOP_BUF_SIZE];
|
||||
size_t size;
|
||||
} w;
|
||||
} lnm_loop_conn;
|
||||
|
||||
typedef struct lnm_loop {
|
||||
int listen_fd;
|
||||
int epoll_fd;
|
||||
atomic_int open;
|
||||
void *gctx;
|
||||
lnm_err (*ctx_init)(void **out, void *gctx);
|
||||
void (*ctx_free)(void *ctx);
|
||||
void (*data_read)(lnm_loop_conn *conn);
|
||||
void (*data_write)(lnm_loop_conn *conn);
|
||||
} lnm_loop;
|
||||
|
||||
lnm_err lnm_loop_init(lnm_loop **out, void *gctx,
|
||||
lnm_err (*ctx_init)(void **out, void *gctx),
|
||||
void (*ctx_free)(void *ctx),
|
||||
void (*data_read)(lnm_loop_conn *conn),
|
||||
void (*data_write)(lnm_loop_conn *conn));
|
||||
|
||||
lnm_err lnm_loop_setup(lnm_loop *l, uint16_t port);
|
||||
|
||||
lnm_err lnm_loop_run(lnm_loop *l, int thread_count);
|
||||
|
||||
#endif
|
||||
87
include/picohttpparser.h
Normal file
87
include/picohttpparser.h
Normal file
|
|
@ -0,0 +1,87 @@
|
|||
/*
|
||||
* Copyright (c) 2009-2014 Kazuho Oku, Tokuhiro Matsuno, Daisuke Murase,
|
||||
* Shigeo Mitsunari
|
||||
*
|
||||
* The software is licensed under either the MIT License (below) or the Perl
|
||||
* license.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to
|
||||
* deal in the Software without restriction, including without limitation the
|
||||
* rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
||||
* sell copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
||||
* IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#ifndef picohttpparser_h
|
||||
#define picohttpparser_h
|
||||
|
||||
#include <sys/types.h>
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#define ssize_t intptr_t
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/* contains name and value of a header (name == NULL if is a continuing line
|
||||
* of a multiline header */
|
||||
struct phr_header {
|
||||
const char *name;
|
||||
size_t name_len;
|
||||
const char *value;
|
||||
size_t value_len;
|
||||
};
|
||||
|
||||
/* returns number of bytes consumed if successful, -2 if request is partial,
|
||||
* -1 if failed */
|
||||
int phr_parse_request(const char *buf, size_t len, const char **method, size_t *method_len, const char **path, size_t *path_len,
|
||||
int *minor_version, struct phr_header *headers, size_t *num_headers, size_t last_len);
|
||||
|
||||
/* ditto */
|
||||
int phr_parse_response(const char *_buf, size_t len, int *minor_version, int *status, const char **msg, size_t *msg_len,
|
||||
struct phr_header *headers, size_t *num_headers, size_t last_len);
|
||||
|
||||
/* ditto */
|
||||
int phr_parse_headers(const char *buf, size_t len, struct phr_header *headers, size_t *num_headers, size_t last_len);
|
||||
|
||||
/* should be zero-filled before start */
|
||||
struct phr_chunked_decoder {
|
||||
size_t bytes_left_in_chunk; /* number of bytes left in current chunk */
|
||||
char consume_trailer; /* if trailing headers should be consumed */
|
||||
char _hex_count;
|
||||
char _state;
|
||||
};
|
||||
|
||||
/* the function rewrites the buffer given as (buf, bufsz) removing the chunked-
|
||||
* encoding headers. When the function returns without an error, bufsz is
|
||||
* updated to the length of the decoded data available. Applications should
|
||||
* repeatedly call the function while it returns -2 (incomplete) every time
|
||||
* supplying newly arrived data. If the end of the chunked-encoded data is
|
||||
* found, the function returns a non-negative number indicating the number of
|
||||
* octets left undecoded, that starts from the offset returned by `*bufsz`.
|
||||
* Returns -1 on error.
|
||||
*/
|
||||
ssize_t phr_decode_chunked(struct phr_chunked_decoder *decoder, char *buf, size_t *bufsz);
|
||||
|
||||
/* returns if the chunked decoder is in middle of chunked data */
|
||||
int phr_decode_chunked_is_in_data(struct phr_chunked_decoder *decoder);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
Loading…
Add table
Add a link
Reference in a new issue