diff options
| author | spl3g <spleefer6@yandex.ru> | 2025-03-22 21:41:16 +0300 |
|---|---|---|
| committer | spl3g <spleefer6@yandex.ru> | 2025-03-22 21:41:16 +0300 |
| commit | 62454373db4cd2add82ded0cf7b21f7d69ade597 (patch) | |
| tree | 1627133fe4567e9a3abb707af5e7289353410d5f /include | |
| parent | ef5f52fb739c9f0d71c579f08363ef0dfd5c227d (diff) | |
Reorganize the lib
Diffstat (limited to 'include')
| -rw-r--r-- | include/chttp/arena.h | 65 | ||||
| -rw-r--r-- | include/chttp/arena_strings.h | 36 | ||||
| -rw-r--r-- | include/chttp/const_strings.h | 28 | ||||
| -rw-r--r-- | include/chttp/hashmap.h | 27 | ||||
| -rw-r--r-- | include/chttp/http.h | 177 |
5 files changed, 333 insertions, 0 deletions
diff --git a/include/chttp/arena.h b/include/chttp/arena.h new file mode 100644 index 0000000..1f53355 --- /dev/null +++ b/include/chttp/arena.h @@ -0,0 +1,65 @@ +// Most of the code is from https://github.com/tsoding/arena + +#ifndef ARENA_H_ +#define ARENA_H_ + +#include <stdlib.h> +#include <stddef.h> +#include <stdint.h> +#include <assert.h> +#include <string.h> + +typedef struct region region; + +struct region { + region *next; + size_t cap; + size_t len; + uintptr_t data[]; +}; + +typedef struct { + region *beg; + region *end; + size_t region_cap; +} arena; + +arena arena_init_cap(size_t cap); +void *arena_alloc(arena *a, size_t size); +void arena_free(arena *a); +void *arena_realloc(arena *a, void *oldptr, size_t oldsz, size_t newsz); + +#define new(a, t, c) (t *)arena_alloc(a, sizeof(t)*c) + +#define ARENA_REGION_DEFAULT_CAPACITY (8*1024) +#define ARENA_DA_INIT_CAP (2) + +#define arena_da_reserve(a, da, expected_size) \ + do { \ + if ((expected_size) >= (da)->cap) { \ + size_t new_cap = (da)->cap == 0 ? ARENA_DA_INIT_CAP : (da)->cap*2; \ + while (new_cap < expected_size) { \ + new_cap *= 2; \ + } \ + (da)->data = arena_realloc( \ + (a), (da)->data, \ + (da)->cap*sizeof(*(da)->data), \ + new_cap*sizeof(*(da)->data)); \ + (da)->cap = new_cap; \ + } \ + } while (0) + +#define arena_da_append(a, da, item) \ + do { \ + arena_da_reserve((a), (da), (da)->len + 1); \ + (da)->data[(da)->len++] = (item); \ + } while (0) + +#define arena_da_append_many(a, da, items, items_len) \ + do { \ + arena_da_reserve((a), (da), (da)->len+len); \ + memcpy((da)->data+(da)->len, (items), sizeof(*(da)->data)*items_len); \ + (da)->len += len; \ + } while (0) + +#endif //ARENA_H_ diff --git a/include/chttp/arena_strings.h b/include/chttp/arena_strings.h new file mode 100644 index 0000000..b25435d --- /dev/null +++ b/include/chttp/arena_strings.h @@ -0,0 +1,36 @@ +#ifndef ARENA_STRINGS_H_ +#define ARENA_STRINGS_H_ + +#include "arena.h" +#include "const_strings.h" + +typedef struct { + const_string *data; + size_t len; + size_t cap; +} const_string_da; + +typedef struct { + char* data; + size_t len; + size_t cap; +} string_builder; + +const_string arena_cs_append(arena *a, const_string dst, const_string src); +const_string arena_cs_init(arena *a, int len); +const_string arena_cs_concat(arena *a, const_string_da strings, const_string sep); + +#define arena_sb_append_buf(a, sb, buf, len) arena_da_append_many((a), (sb), (buf), (len)) + +#define arena_sb_append_cstr(a, sb, cstr) \ + do { \ + const char * str = (cstr); \ + size_t len = strlen((cstr)); \ + arena_da_append_many((a), (sb), (str), len); \ + } while (0) + +#define arena_sb_append_null(a, sb) arena_da_append_many((a), (sb), "", 1) + +#define arena_sb_to_cs(sb) cs_from_parts((sb).data, (sb).len) + +#endif // ARENA_STRINGS_H_ diff --git a/include/chttp/const_strings.h b/include/chttp/const_strings.h new file mode 100644 index 0000000..cb92442 --- /dev/null +++ b/include/chttp/const_strings.h @@ -0,0 +1,28 @@ +#ifndef CONST_STRINGS_H_ +#define CONST_STRINGS_H_ + +#include <string.h> +#include <stdio.h> +#include <stdbool.h> + +typedef struct { + const char* data; + int len; +} const_string; + +const_string cs_from_parts(const char* data, int len); +const_string cs_from_cstr(const char* cstr); +const_string cs_slice(const_string src, int from, int to); +const_string cs_chop_delim(const_string *src, char delim); +bool cs_try_chop_delim(const_string *str, char delim, const_string *dst); +int cs_find_delim(const_string str, char delim); +bool cs_eq(const_string str1, const_string str2); +void cs_print(char *format, const_string str); + +#define CS(cstr) cs_from_parts(cstr, sizeof(cstr) - 1) +#define CS_STATIC(cstr) {.data = cstr, .len = sizeof(cstr) - 1} + +#define CS_FMT "%.*s" +#define CS_ARG(cs) (int) (cs).len, (cs).data + +#endif // STRINGS_H_ diff --git a/include/chttp/hashmap.h b/include/chttp/hashmap.h new file mode 100644 index 0000000..eefb5ee --- /dev/null +++ b/include/chttp/hashmap.h @@ -0,0 +1,27 @@ +#ifndef HASHMAP_H_ +#define HASHMAP_H_ + +#include <stddef.h> +#include "const_strings.h" +#include "arena.h" + +#define HASHMAP_DEFAULT_R 31 + +typedef struct hashitem hashitem; +struct hashitem { + hashitem *next; + const_string key; + void* val; +}; + +typedef struct { + size_t cap; + hashitem data[]; +} hashmap; + +size_t hash_str(const_string str, size_t cap); +hashmap *hashmap_init(arena *a, size_t cap); +size_t hashmap_kstr_insert(arena *a, hashmap* map, const_string key, void* val); +void *hashmap_kstr_get(hashmap *map, const_string key); + +#endif // HASHMAP_H_ diff --git a/include/chttp/http.h b/include/chttp/http.h new file mode 100644 index 0000000..4fcc418 --- /dev/null +++ b/include/chttp/http.h @@ -0,0 +1,177 @@ +#ifndef HTTP_H_ +#define HTTP_H_ + +#include <stdio.h> +#include <string.h> +#include <netinet/in.h> +#include <netinet/ip.h> +#include <sys/socket.h> +#include <sys/types.h> +#include <netdb.h> +#include <arpa/inet.h> +#include <errno.h> +#include <unistd.h> +#include <sys/wait.h> +#include <signal.h> +#include <stdlib.h> +#include <stdarg.h> +#include <pthread.h> + +#include "const_strings.h" +#include "arena_strings.h" +#include "arena.h" + +typedef struct { + const_string key; + const_string value; +} KV; + +typedef struct { + KV *data; + size_t len; + size_t cap; +} header_da; + +typedef struct { + const_string key; + const_string val; +} http_query; + +typedef struct { + KV *data; + size_t len; + size_t cap; +} http_query_da; + +typedef struct { + const_string key; + void *val; +} http_context_value; + +typedef struct { + http_context_value *data; + size_t len; + size_t cap; +} http_context; + +typedef struct { + size_t code; + header_da headers; + const_string body; + bool sent; +} http_response; + +typedef struct { + size_t inc_fd; + const_string method; + const_string path; + http_query_da query; + header_da headers; + const_string body; + + arena *arena; + http_response* resp; + http_context *ctx; +} http_request; + +typedef void (*http_handler_func)(http_request); + +typedef struct http_handler_da http_handler_da; +typedef struct http_middleware http_middleware; +typedef struct http_handler http_handler; + +typedef void (*http_middleware_func)(http_middleware *, http_request); + +struct http_middleware { + http_middleware_func func; + http_middleware *next; + http_handler_func handler; +}; + +struct http_handler { + const_string method; + const_string path; + http_middleware *middleware; + http_handler_func func; +}; + +struct http_handler_da { + http_handler *data; + size_t len; + size_t cap; +}; + +typedef struct { + http_middleware *start; + http_middleware *end; +} http_global_middleware; + +typedef struct { + size_t sockfd; + struct sockaddr *addr; + arena *arena; + http_handler_da handlers; + http_context global_ctx; + http_global_middleware *global_middleware; +} http_server; + +typedef enum { + HTTP_INFO = 0, + HTTP_WARNING, + HTTP_ERROR, +} http_log_level; + +typedef enum { + CONTINUE = 100, + SWITCHING_PROTOCOLS = 101, + PROCESSING = 102, + EARLY_HINTS = 103, + OK = 200, + CREATED = 201, + ACCEPTED = 202, + NO_CONTENT = 204, + MULTIPLE_CHOICES = 300, + MOVED_PERMANENTLY = 301, + FOUND = 302, + SEE_OTHER = 303, + NOT_MODIFIED = 304, + TEMPORARY_REDIRECT = 307, + PERMANENT_REDIRECT = 308, + BAD_REQUEST = 400, + UNAUTHORIZED = 401, + PAYMENT_REQUIRED = 402, + FORBIDDEN = 403, + NOT_FOUND = 404, + METHOD_NOT_ALLOWED = 405, + NOT_ACCEPTABLE = 406, + REQUEST_TIMEOUT = 408, + IM_A_TEEPOT = 418, + INTERNAL_SERVER_ERROR = 500, + NOT_IMPLEMENTED = 501, + BAD_GATEWAY = 502, + SERVICE_UNAVAILABLE = 503, + HTTP_VERSION_NOT_SUPPPORTED = 505, +} http_response_code; + +const_string get_response_string(http_response_code code); +void *get_in_addr(struct sockaddr *sa); +int get_in_port(struct sockaddr *sa); +void http_log(http_log_level log, char *fmt, ...); + +void set_context_value(arena *arena, http_context *ctx, http_context_value kv); +void *get_context_value(http_context *ctx, char* key); + +void http_send(http_request req); +void http_send_json(http_request req, const_string json); +void http_send_body(http_request req, const_string body); + +int init_server(arena *arena, http_server *serv, char *addr, char *port); +int listen_and_serve(http_server *serv); + +http_handler *http_handle_path(http_server *serv, char *method, char *path, http_handler_func handler); + +void http_run_next(http_middleware *self, http_request req); +void http_register_global_middleware(http_server *hand, http_middleware_func func); +void http_register_handler_middleware(arena *arena, http_handler *hand, http_middleware_func func); + +#endif // HTTP_H_ |
