diff --git a/Makefile b/Makefile index 3b2ccb6..74fc972 100644 --- a/Makefile +++ b/Makefile @@ -36,7 +36,7 @@ bin/res: mkdir -p bin/res bin/test: test/mock_*.c test/test_*.c \ - src/lib/utils.c src/lib/sock.c src/lib/list.c src/lib/http.c src/lib/http_static.c src/logger.c + src/lib/utils.c src/lib/sock.c src/lib/list.c src/lib/http.c src/lib/http_static.c src/logger.c src/lib/error.c $(CC) -o $@ $(CFLAGS) $^ -lcriterion diff --git a/src/lib/compress.c b/src/lib/compress.c index 8769180..a91f632 100644 --- a/src/lib/compress.c +++ b/src/lib/compress.c @@ -69,6 +69,9 @@ int compress_free(compress_ctx *ctx) { BrotliEncoderDestroyInstance(ctx->brotli); ctx->brotli = NULL; } + if (ctx->mode & COMPRESS_GZ) { + deflateEnd(&ctx->gzip); + } ctx->mode = 0; return 0; } diff --git a/src/lib/config.c b/src/lib/config.c index f6c8ca1..4c79a11 100644 --- a/src/lib/config.c +++ b/src/lib/config.c @@ -42,7 +42,7 @@ int config_load(const char *filename) { if (comment != NULL) comment[0] = 0; unsigned long len = strlen(ptr); - char *end_ptr = ptr + len - 1; + char *end_ptr = (len > 0) ? ptr + len - 1 : ptr; while (end_ptr[0] == ' ' || end_ptr[0] == '\t') { end_ptr[0] = 0; end_ptr--; @@ -161,6 +161,8 @@ int config_load(const char *filename) { if (strlen(source) == 0) { err: critical("Unable to parse config file (line %i)", line); + free(line); + fclose(file); return -2; } @@ -182,6 +184,7 @@ int config_load(const char *filename) { } free(line); + fclose(file); for (int k = 0; k < i; k++) { host_config_t *hc = &config.hosts[k]; diff --git a/src/lib/list.c b/src/lib/list.c index ace0c2c..0b3296c 100644 --- a/src/lib/list.c +++ b/src/lib/list.c @@ -6,6 +6,8 @@ #include #define FACTOR 4 +#define meta(ptr) ((list_meta_t *) ((unsigned char *) (ptr) - sizeof(list_meta_t))) +#define data(ptr) ((unsigned char *) (ptr) + sizeof(list_meta_t)) typedef struct { int init_size, elem_size, max_size, size; @@ -30,21 +32,24 @@ void *list_create(int elem_size, int init_elem_n) { } void *list_ptr = malloc(sizeof(list_meta_t) + elem_size * init_elem_n); + if (list_ptr == NULL) + return NULL; + + memset(list_ptr, 0, sizeof(list_meta_t) + elem_size * init_elem_n); list_meta_t *list = list_ptr; list->init_size = init_elem_n; list->elem_size = elem_size; list->max_size = init_elem_n; list->size = 0; - return (unsigned char *) list_ptr + sizeof(list_meta_t); + return data(list_ptr); } int list_size(const void *list_ptr) { - list_meta_t *list = (void *) ((unsigned char *) list_ptr - sizeof(list_meta_t)); - return list->size; + return meta(list_ptr)->size; } int list_find(void *list_ptr, void *elem) { - list_meta_t *list = (void *) ((unsigned char *) list_ptr - sizeof(list_meta_t)); + list_meta_t *list = meta(list_ptr); unsigned char *array = list_ptr; for (int i = 0; i < list->size; i++) { @@ -60,32 +65,31 @@ void *list_insert(void *list_ptr, void *elem, int n) { void *ptr = NULL; list_ptr = list_insert_ptr(list_ptr, &ptr, n); if (list_ptr != NULL && ptr != NULL) { - list_meta_t *list = (void *) ((unsigned char *) list_ptr - sizeof(list_meta_t)); - memcpy(ptr, elem, list->elem_size); + memcpy(ptr, elem, meta(list_ptr)->elem_size); } return list_ptr; } void *list_insert_ptr(void *list_ptr, void **elem, int n) { - list_meta_t *list = (void *) ((unsigned char *) list_ptr - sizeof(list_meta_t)); + list_meta_t *list = meta(list_ptr); if (n < 0) n = list->size + n + 1; if (list->size >= list->max_size) { - if ((list = list_resize(list, list->max_size * FACTOR)) == NULL) { + if ((list = list_resize(list, list->max_size * FACTOR)) == NULL) return NULL; - } } - unsigned char *array = (unsigned char *) list + sizeof(list_meta_t); + unsigned char *array = data(list); if (n < list->size) memmove(array + (n + 1) * list->elem_size, array + n * list->elem_size, (list->size - n) * list->elem_size); *elem = array + n * list->elem_size; + memset(*elem, 0, list->elem_size); list->size++; - return (unsigned char *) list + sizeof(list_meta_t); + return array; } void *list_append(void *list_ptr, void *elem) { @@ -97,7 +101,7 @@ void *list_append_ptr(void *list_ptr, void **elem) { } void *list_remove(void *list_ptr, int n) { - list_meta_t *list = (void *) ((unsigned char *) list_ptr - sizeof(list_meta_t)); + list_meta_t *list = meta(list_ptr); if (n < 0) n = list->size + n; @@ -106,6 +110,8 @@ void *list_remove(void *list_ptr, int n) { if (list->size > 1 && n < list->size) memmove(array + n * list->elem_size, array + (n + 1) * list->elem_size, (list->size - n - 1) * list->elem_size); + memset(array + list->size * list->elem_size, 0, list->elem_size); + list->size--; if (list->size < list->max_size / FACTOR / 2 && list->max_size / FACTOR >= list->init_size) { if ((list = list_resize(list, list->max_size / FACTOR)) == NULL) { @@ -113,7 +119,7 @@ void *list_remove(void *list_ptr, int n) { } } - return (unsigned char *) list + sizeof(list_meta_t); + return data(list); } void *list_delete(void *list_ptr, void *elem) { @@ -126,14 +132,13 @@ void *list_delete(void *list_ptr, void *elem) { } void *list_clear(void *list_ptr) { - list_meta_t *list = (void *) ((unsigned char *) list_ptr - sizeof(list_meta_t)); + list_meta_t *list = meta(list_ptr); list->size = 0; memset(list_ptr, 0, list->max_size * list->elem_size); list->max_size = list->init_size; - return (unsigned char *) list_resize(list, list->max_size * list->elem_size) + sizeof(list_meta_t); + return data(list_resize(list, list->max_size)); } void list_free(void *list_ptr) { - list_meta_t *list = (void *) ((unsigned char *) list_ptr - sizeof(list_meta_t)); - free(list); + free(meta(list_ptr)); } diff --git a/src/lib/proxy.c b/src/lib/proxy.c index aa313ad..1429e57 100644 --- a/src/lib/proxy.c +++ b/src/lib/proxy.c @@ -462,7 +462,7 @@ int proxy_init(proxy_ctx_t **proxy_ptr, http_req *req, http_res *res, http_statu return -1; } - ret = sock_recv(&proxy->proxy, buffer, sizeof(buffer), MSG_PEEK); + ret = sock_recv(&proxy->proxy, buffer, sizeof(buffer) - 1, MSG_PEEK); if (ret <= 0) { int e_sys = error_get_sys(), e_ssl = error_get_ssl(); if (e_sys == EAGAIN || e_sys == EINPROGRESS || e_ssl == SSL_ERROR_WANT_READ || e_ssl == SSL_ERROR_WANT_WRITE) { @@ -477,6 +477,7 @@ int proxy_init(proxy_ctx_t **proxy_ptr, http_req *req, http_res *res, http_statu retry = tries < 4; goto proxy_err; } + buffer[ret] = 0; char *buf = buffer; unsigned short header_len = (unsigned short) (strstr(buffer, "\r\n\r\n") - buffer + 4); diff --git a/src/server.c b/src/server.c index ca9e77a..6169d78 100644 --- a/src/server.c +++ b/src/server.c @@ -79,15 +79,18 @@ static int ssl_servername_cb(SSL *ssl, int *ad, void *arg) { } void server_free_client(client_ctx_t *ctx) { - for (int i = 0; i < list_size(clients); i++) { - if (clients[i] == ctx) { - clients = list_remove(clients, i); - break; - } - } + clients = list_delete(clients, &ctx); free(ctx); } +static void ssl_free() { + for (int i = 0; i < CONFIG_MAX_CERT_CONFIG; i++) { + const cert_config_t *conf = &config.certs[i]; + if (conf->name[0] == 0) break; + SSL_CTX_free(contexts[i]); + } +} + static void accept_cb(void *arg) { int i = (int) (((int *) arg) - sockets); int fd = sockets[i]; @@ -98,14 +101,6 @@ static void accept_cb(void *arg) { errno = 0; return; } - - clients = list_append(clients, &client_ctx); - if (clients == NULL) { - critical("Unable to add client context to list"); - errno = 0; - return; - } - client_ctx->in_use = 1; sock *client = &client_ctx->socket; @@ -124,6 +119,13 @@ static void accept_cb(void *arg) { client_ctx->cnx_s = client->ts_start; client_ctx->cnx_e = -1, client_ctx->req_s = -1, client_ctx->req_e = -1, client_ctx->res_ts = -1; + clients = list_append(clients, &client_ctx); + if (clients == NULL) { + critical("Unable to add client context to list"); + errno = 0; + return; + } + tcp_accept(client_ctx); } @@ -160,9 +162,9 @@ static void terminate_gracefully(int sig) { workers_stop(); workers_destroy(); - for (int i = 0; i < list_size(clients); i++) { - tcp_close(clients[i]); - } + while (list_size(clients) > 0) + server_free_client(clients[0]); + proxy_close_all(); logger_set_prefix(""); @@ -177,11 +179,6 @@ int main(int argc, char *const argv[]) { int mode = 0; memset(sockets, 0, sizeof(sockets)); - clients = list_create(sizeof(void *), 64); - if (clients == NULL) { - critical("Unable to initialize client list"); - return 1; - } const struct sockaddr_in6 addresses[2] = { {.sin6_family = AF_INET6, .sin6_addr = IN6ADDR_ANY_INIT, .sin6_port = htons(80)}, @@ -309,15 +306,26 @@ int main(int argc, char *const argv[]) { } } + clients = list_create(sizeof(client_ctx_t *), 64); + if (clients == NULL) { + critical("Unable to initialize client list"); + ssl_free(); + return 1; + } + if (async_init() != 0) { critical("Unable to initialize async thread"); + ssl_free(); geoip_free(); + list_free(clients); return 1; } if (proxy_preload() != 0) { critical("Unable to initialize proxy"); + ssl_free(); geoip_free(); + list_free(clients); async_free(); return 1; } @@ -325,7 +333,10 @@ int main(int argc, char *const argv[]) { for (int i = 0; i < NUM_SOCKETS; i++) { if (listen(sockets[i], LISTEN_BACKLOG) < 0) { critical("Unable to listen on socket %i", i); + ssl_free(); geoip_free(); + list_free(clients); + async_free(); proxy_unload(); return 1; } @@ -347,6 +358,7 @@ int main(int argc, char *const argv[]) { notice("Goodbye!"); // cleanup + ssl_free(); list_free(clients); geoip_free(); proxy_unload(); diff --git a/src/worker/proxy_handler.c b/src/worker/proxy_handler.c index 4b1bc4a..beb6891 100644 --- a/src/worker/proxy_handler.c +++ b/src/worker/proxy_handler.c @@ -29,12 +29,14 @@ void proxy_handler_func(client_ctx_t *ctx) { if (ret == 1) { proxy_unlock_ctx(ctx->proxy); + ctx->proxy->client = NULL; ctx->proxy = NULL; } else if (ctx->use_proxy == 0) { proxy_close(ctx->proxy); } else if (ctx->use_proxy == 1) { proxy_handler_2(ctx); proxy_unlock_ctx(ctx->proxy); + ctx->proxy->client = NULL; ctx->proxy = NULL; } else if (ctx->use_proxy == 2) { // WebSocket