Added brotli compression
This commit is contained in:
		
							
								
								
									
										2
									
								
								Makefile
									
									
									
									
									
								
							
							
						
						
									
										2
									
								
								Makefile
									
									
									
									
									
								
							@@ -1,6 +1,6 @@
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
CFLAGS=-std=c11 -Wall
 | 
					CFLAGS=-std=c11 -Wall
 | 
				
			||||||
INCLUDE=-lssl -lcrypto -lmagic -lz -lmaxminddb
 | 
					INCLUDE=-lssl -lcrypto -lmagic -lz -lmaxminddb -lbrotlienc
 | 
				
			||||||
LIBS=src/lib/*.c
 | 
					LIBS=src/lib/*.c
 | 
				
			||||||
 | 
					
 | 
				
			||||||
DEBIAN_OPTS=-D MAGIC_FILE="\"/usr/share/file/magic.mgc\"" -D PHP_FPM_SOCKET="\"/var/run/php/php7.3-fpm.sock\""
 | 
					DEBIAN_OPTS=-D MAGIC_FILE="\"/usr/share/file/magic.mgc\"" -D PHP_FPM_SOCKET="\"/var/run/php/php7.3-fpm.sock\""
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										29
									
								
								src/client.c
									
									
									
									
									
								
							
							
						
						
									
										29
									
								
								src/client.c
									
									
									
									
									
								
							@@ -5,7 +5,6 @@
 | 
				
			|||||||
 * Lorenz Stechauner, 2020-12-03
 | 
					 * Lorenz Stechauner, 2020-12-03
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#include "client.h"
 | 
					 | 
				
			||||||
#include "lib/utils.h"
 | 
					#include "lib/utils.h"
 | 
				
			||||||
#include "lib/config.h"
 | 
					#include "lib/config.h"
 | 
				
			||||||
#include "lib/sock.h"
 | 
					#include "lib/sock.h"
 | 
				
			||||||
@@ -13,6 +12,7 @@
 | 
				
			|||||||
#include "lib/rev_proxy.h"
 | 
					#include "lib/rev_proxy.h"
 | 
				
			||||||
#include "lib/fastcgi.h"
 | 
					#include "lib/fastcgi.h"
 | 
				
			||||||
#include "lib/cache.h"
 | 
					#include "lib/cache.h"
 | 
				
			||||||
 | 
					#include "lib/geoip.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#include <string.h>
 | 
					#include <string.h>
 | 
				
			||||||
#include <sys/select.h>
 | 
					#include <sys/select.h>
 | 
				
			||||||
@@ -32,7 +32,7 @@ char *client_addr_str, *client_addr_str_ptr, *server_addr_str, *server_addr_str_
 | 
				
			|||||||
struct timeval client_timeout;
 | 
					struct timeval client_timeout;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
host_config *get_host_config(const char *host) {
 | 
					host_config *get_host_config(const char *host) {
 | 
				
			||||||
    for (int i = 0; i < MAX_HOST_CONFIG; i++) {
 | 
					    for (int i = 0; i < CONFIG_MAX_HOST_CONFIG; i++) {
 | 
				
			||||||
        host_config *hc = &config[i];
 | 
					        host_config *hc = &config[i];
 | 
				
			||||||
        if (hc->type == CONFIG_TYPE_UNSET) break;
 | 
					        if (hc->type == CONFIG_TYPE_UNSET) break;
 | 
				
			||||||
        if (strcmp(hc->name, host) == 0) return hc;
 | 
					        if (strcmp(hc->name, host) == 0) return hc;
 | 
				
			||||||
@@ -326,16 +326,23 @@ int client_request_handler(sock *client, unsigned long client_num, unsigned int
 | 
				
			|||||||
            }
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            char *accept_encoding = http_get_header_field(&req.hdr, "Accept-Encoding");
 | 
					            char *accept_encoding = http_get_header_field(&req.hdr, "Accept-Encoding");
 | 
				
			||||||
            if (uri.meta->filename_comp[0] != 0 && accept_encoding != NULL &&
 | 
					            if (accept_encoding != NULL) {
 | 
				
			||||||
                    strstr(accept_encoding, "deflate") != NULL) {
 | 
					                if (uri.meta->filename_comp_br[0] != 0 && strstr(accept_encoding, "br") != NULL) {
 | 
				
			||||||
                file = fopen(uri.meta->filename_comp, "rb");
 | 
					                    file = fopen(uri.meta->filename_comp_br, "rb");
 | 
				
			||||||
                if (file == NULL) {
 | 
					                    if (file == NULL) {
 | 
				
			||||||
                    cache_filename_comp_invalid(uri.filename);
 | 
					                        printf("asdf\n");
 | 
				
			||||||
                    goto not_compressed;
 | 
					                        cache_filename_comp_invalid(uri.filename);
 | 
				
			||||||
 | 
					                    }
 | 
				
			||||||
 | 
					                    http_add_header_field(&res.hdr, "Content-Encoding", "br");
 | 
				
			||||||
 | 
					                } else if (uri.meta->filename_comp_gz[0] != 0 && strstr(accept_encoding, "gzip") != NULL) {
 | 
				
			||||||
 | 
					                    file = fopen(uri.meta->filename_comp_gz, "rb");
 | 
				
			||||||
 | 
					                    if (file == NULL) {
 | 
				
			||||||
 | 
					                        cache_filename_comp_invalid(uri.filename);
 | 
				
			||||||
 | 
					                    }
 | 
				
			||||||
 | 
					                    http_add_header_field(&res.hdr, "Content-Encoding", "gzip");
 | 
				
			||||||
                }
 | 
					                }
 | 
				
			||||||
                http_add_header_field(&res.hdr, "Content-Encoding", "deflate");
 | 
					            }
 | 
				
			||||||
            } else {
 | 
					            if (file == NULL) {
 | 
				
			||||||
                not_compressed:
 | 
					 | 
				
			||||||
                file = fopen(uri.filename, "rb");
 | 
					                file = fopen(uri.filename, "rb");
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
            fseek(file, 0, SEEK_END);
 | 
					            fseek(file, 0, SEEK_END);
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										18
									
								
								src/client.h
									
									
									
									
									
								
							
							
						
						
									
										18
									
								
								src/client.h
									
									
									
									
									
								
							@@ -1,18 +0,0 @@
 | 
				
			|||||||
/**
 | 
					 | 
				
			||||||
 * Necronda Web Server
 | 
					 | 
				
			||||||
 * Client connection and request handlers (header file)
 | 
					 | 
				
			||||||
 * src/client.h
 | 
					 | 
				
			||||||
 * Lorenz Stechauner, 2021-01-17
 | 
					 | 
				
			||||||
 */
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#ifndef NECRONDA_SERVER_CLIENT_H
 | 
					 | 
				
			||||||
#define NECRONDA_SERVER_CLIENT_H
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#include <sys/time.h>
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
extern int server_keep_alive;
 | 
					 | 
				
			||||||
extern char *log_client_prefix, *log_conn_prefix, *log_req_prefix, *client_geoip;
 | 
					 | 
				
			||||||
extern char *client_addr_str, *client_addr_str_ptr, *server_addr_str, *server_addr_str_ptr, *client_host_str;
 | 
					 | 
				
			||||||
extern struct timeval client_timeout;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#endif //NECRONDA_SERVER_CLIENT_H
 | 
					 | 
				
			||||||
							
								
								
									
										24
									
								
								src/lib/brotli.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										24
									
								
								src/lib/brotli.c
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,24 @@
 | 
				
			|||||||
 | 
					/**
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include "brotli.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					int brotli_init(BrotliEncoderState **state) {
 | 
				
			||||||
 | 
					    *state = BrotliEncoderCreateInstance(NULL, NULL, NULL);
 | 
				
			||||||
 | 
					    if (*state == NULL) return -1;
 | 
				
			||||||
 | 
					    BrotliEncoderSetParameter(*state, BROTLI_PARAM_MODE, BROTLI_MODE_GENERIC);
 | 
				
			||||||
 | 
					    BrotliEncoderSetParameter(*state, BROTLI_PARAM_MODE, BROTLI_MODE_GENERIC);
 | 
				
			||||||
 | 
					    return 0;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					int brotli_compress(BrotliEncoderState *state, const char *in, unsigned long *in_len, char *out, unsigned long *out_len, int finish) {
 | 
				
			||||||
 | 
					    int ret = BrotliEncoderCompressStream(state, finish ? BROTLI_OPERATION_FINISH : BROTLI_OPERATION_PROCESS,
 | 
				
			||||||
 | 
					            in_len, (const unsigned char**) &in, out_len, (unsigned char **) &out, NULL);
 | 
				
			||||||
 | 
					    return (ret == BROTLI_TRUE) ? 0 : -1;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					int brotli_free(BrotliEncoderState *state) {
 | 
				
			||||||
 | 
					    BrotliEncoderDestroyInstance(state);
 | 
				
			||||||
 | 
					    return 0;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										11
									
								
								src/lib/brotli.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										11
									
								
								src/lib/brotli.h
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,11 @@
 | 
				
			|||||||
 | 
					/**
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include <brotli/encode.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					int brotli_init(BrotliEncoderState **state);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					int brotli_compress(BrotliEncoderState *state, const char *in, unsigned long *in_len, char *out, unsigned long *out_len, int finish);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					int brotli_free(BrotliEncoderState *state);
 | 
				
			||||||
							
								
								
									
										123
									
								
								src/lib/cache.c
									
									
									
									
									
								
							
							
						
						
									
										123
									
								
								src/lib/cache.c
									
									
									
									
									
								
							@@ -7,9 +7,9 @@
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
#include "cache.h"
 | 
					#include "cache.h"
 | 
				
			||||||
#include "utils.h"
 | 
					#include "utils.h"
 | 
				
			||||||
#include "../necronda-server.h"
 | 
					#include "gzip.h"
 | 
				
			||||||
 | 
					#include "brotli.h"
 | 
				
			||||||
#include <stdio.h>
 | 
					#include <stdio.h>
 | 
				
			||||||
#include <zlib.h>
 | 
					 | 
				
			||||||
#include <magic.h>
 | 
					#include <magic.h>
 | 
				
			||||||
#include <sys/ipc.h>
 | 
					#include <sys/ipc.h>
 | 
				
			||||||
#include <sys/shm.h>
 | 
					#include <sys/shm.h>
 | 
				
			||||||
@@ -28,7 +28,7 @@ int magic_init() {
 | 
				
			|||||||
        fprintf(stderr, ERR_STR "Unable to open magic cookie: %s" CLR_STR "\n", strerror(errno));
 | 
					        fprintf(stderr, ERR_STR "Unable to open magic cookie: %s" CLR_STR "\n", strerror(errno));
 | 
				
			||||||
        return -1;
 | 
					        return -1;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    if (magic_load(magic, MAGIC_FILE) != 0) {
 | 
					    if (magic_load(magic, CACHE_MAGIC_FILE) != 0) {
 | 
				
			||||||
        fprintf(stderr, ERR_STR "Unable to load magic cookie: %s" CLR_STR "\n", magic_error(magic));
 | 
					        fprintf(stderr, ERR_STR "Unable to load magic cookie: %s" CLR_STR "\n", magic_error(magic));
 | 
				
			||||||
        return -2;
 | 
					        return -2;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
@@ -43,7 +43,7 @@ int cache_process() {
 | 
				
			|||||||
    signal(SIGINT, cache_process_term);
 | 
					    signal(SIGINT, cache_process_term);
 | 
				
			||||||
    signal(SIGTERM, cache_process_term);
 | 
					    signal(SIGTERM, cache_process_term);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    int shm_id = shmget(SHM_KEY_CACHE, FILE_CACHE_SIZE * sizeof(cache_entry), 0);
 | 
					    int shm_id = shmget(CACHE_SHM_KEY, CACHE_ENTRIES * sizeof(cache_entry), 0);
 | 
				
			||||||
    if (shm_id < 0) {
 | 
					    if (shm_id < 0) {
 | 
				
			||||||
        fprintf(stderr, ERR_STR "Unable to create shared memory: %s" CLR_STR "\n", strerror(errno));
 | 
					        fprintf(stderr, ERR_STR "Unable to create shared memory: %s" CLR_STR "\n", strerror(errno));
 | 
				
			||||||
        return -1;
 | 
					        return -1;
 | 
				
			||||||
@@ -66,26 +66,28 @@ int cache_process() {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
    FILE *cache_file = fopen("/var/necronda-server/cache", "rb");
 | 
					    FILE *cache_file = fopen("/var/necronda-server/cache", "rb");
 | 
				
			||||||
    if (cache_file != NULL) {
 | 
					    if (cache_file != NULL) {
 | 
				
			||||||
        fread(cache, sizeof(cache_entry), FILE_CACHE_SIZE, cache_file);
 | 
					        fread(cache, sizeof(cache_entry), CACHE_ENTRIES, cache_file);
 | 
				
			||||||
        fclose(cache_file);
 | 
					        fclose(cache_file);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    for (int i = 0; i < FILE_CACHE_SIZE; i++) {
 | 
					    for (int i = 0; i < CACHE_ENTRIES; i++) {
 | 
				
			||||||
        cache[i].is_updating = 0;
 | 
					        cache[i].is_updating = 0;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    FILE *file;
 | 
					    FILE *file;
 | 
				
			||||||
    char buf[16384];
 | 
					    char buf[16384];
 | 
				
			||||||
    char comp_buf[16384];
 | 
					    char comp_buf[16384];
 | 
				
			||||||
    char filename_comp[256];
 | 
					    char filename_comp_gz[256];
 | 
				
			||||||
 | 
					    char filename_comp_br[256];
 | 
				
			||||||
    unsigned long read;
 | 
					    unsigned long read;
 | 
				
			||||||
    int compress;
 | 
					    int compress;
 | 
				
			||||||
    SHA_CTX ctx;
 | 
					    SHA_CTX ctx;
 | 
				
			||||||
    unsigned char hash[SHA_DIGEST_LENGTH];
 | 
					    unsigned char hash[SHA_DIGEST_LENGTH];
 | 
				
			||||||
    int cache_changed = 0;
 | 
					    int cache_changed = 0;
 | 
				
			||||||
    int p_len;
 | 
					    int p_len_gz, p_len_br;
 | 
				
			||||||
 | 
					    int ret_1, ret_2;
 | 
				
			||||||
    while (cache_continue) {
 | 
					    while (cache_continue) {
 | 
				
			||||||
        for (int i = 0; i < FILE_CACHE_SIZE; i++) {
 | 
					        for (int i = 0; i < CACHE_ENTRIES; i++) {
 | 
				
			||||||
            if (cache[i].filename[0] != 0 && cache[i].meta.etag[0] == 0 && !cache[i].is_updating) {
 | 
					            if (cache[i].filename[0] != 0 && cache[i].meta.etag[0] == 0 && !cache[i].is_updating) {
 | 
				
			||||||
                cache[i].is_updating = 1;
 | 
					                cache[i].is_updating = 1;
 | 
				
			||||||
                fprintf(stdout, "[cache] Hashing file %s\n", cache[i].filename);
 | 
					                fprintf(stdout, "[cache] Hashing file %s\n", cache[i].filename);
 | 
				
			||||||
@@ -93,9 +95,10 @@ int cache_process() {
 | 
				
			|||||||
                file = fopen(cache[i].filename, "rb");
 | 
					                file = fopen(cache[i].filename, "rb");
 | 
				
			||||||
                compress = mime_is_compressible(cache[i].meta.type);
 | 
					                compress = mime_is_compressible(cache[i].meta.type);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                int level = NECRONDA_ZLIB_LEVEL;
 | 
					                z_stream gz_state;
 | 
				
			||||||
                z_stream strm;
 | 
					                BrotliEncoderState *br_state = NULL;
 | 
				
			||||||
                FILE *comp_file = NULL;
 | 
					                FILE *comp_file_gz = NULL;
 | 
				
			||||||
 | 
					                FILE *comp_file_br = NULL;
 | 
				
			||||||
                if (compress) {
 | 
					                if (compress) {
 | 
				
			||||||
                    sprintf(buf, "%.*s/.necronda-server", cache[i].webroot_len, cache[i].filename);
 | 
					                    sprintf(buf, "%.*s/.necronda-server", cache[i].webroot_len, cache[i].filename);
 | 
				
			||||||
                    mkdir(buf, 0755);
 | 
					                    mkdir(buf, 0755);
 | 
				
			||||||
@@ -110,27 +113,41 @@ int cache_process() {
 | 
				
			|||||||
                        buf[j] = ch;
 | 
					                        buf[j] = ch;
 | 
				
			||||||
                    }
 | 
					                    }
 | 
				
			||||||
                    buf[strlen(rel_path)] = 0;
 | 
					                    buf[strlen(rel_path)] = 0;
 | 
				
			||||||
                    p_len = snprintf(filename_comp, sizeof(filename_comp), "%.*s/.necronda-server/cache/%s.z",
 | 
					
 | 
				
			||||||
                                     cache[i].webroot_len, cache[i].filename, buf);
 | 
					                    p_len_gz = snprintf(filename_comp_gz, sizeof(filename_comp_gz),
 | 
				
			||||||
                    if (p_len < 0 || p_len >= sizeof(filename_comp)) {
 | 
					                                        "%.*s/.necronda-server/cache/%s.gz",
 | 
				
			||||||
 | 
					                                        cache[i].webroot_len, cache[i].filename, buf);
 | 
				
			||||||
 | 
					                    p_len_br = snprintf(filename_comp_br, sizeof(filename_comp_br),
 | 
				
			||||||
 | 
					                                        "%.*s/.necronda-server/cache/%s.br",
 | 
				
			||||||
 | 
					                                        cache[i].webroot_len, cache[i].filename, buf);
 | 
				
			||||||
 | 
					                    if (p_len_gz < 0 || p_len_gz >= sizeof(filename_comp_gz) ||
 | 
				
			||||||
 | 
					                            p_len_br < 0 || p_len_br >= sizeof(filename_comp_br)) {
 | 
				
			||||||
                        fprintf(stderr, ERR_STR "Unable to open cached file: "
 | 
					                        fprintf(stderr, ERR_STR "Unable to open cached file: "
 | 
				
			||||||
                                                "File name for compressed file too long" CLR_STR "\n");
 | 
					                                                "File name for compressed file too long" CLR_STR "\n");
 | 
				
			||||||
                        goto comp_err;
 | 
					                        goto comp_err;
 | 
				
			||||||
                    }
 | 
					                    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                    fprintf(stdout, "[cache] Compressing file %s\n", cache[i].filename);
 | 
					                    fprintf(stdout, "[cache] Compressing file %s\n", cache[i].filename);
 | 
				
			||||||
                    comp_file = fopen(filename_comp, "wb");
 | 
					
 | 
				
			||||||
                    if (comp_file == NULL) {
 | 
					                    comp_file_gz = fopen(filename_comp_gz, "wb");
 | 
				
			||||||
 | 
					                    comp_file_br = fopen(filename_comp_br, "wb");
 | 
				
			||||||
 | 
					                    if (comp_file_gz == NULL || comp_file_br == NULL) {
 | 
				
			||||||
                        fprintf(stderr, ERR_STR "Unable to open cached file: %s" CLR_STR "\n", strerror(errno));
 | 
					                        fprintf(stderr, ERR_STR "Unable to open cached file: %s" CLR_STR "\n", strerror(errno));
 | 
				
			||||||
                        comp_err:
 | 
					                        comp_err:
 | 
				
			||||||
                        compress = 0;
 | 
					                        compress = 0;
 | 
				
			||||||
                    } else {
 | 
					                    } else {
 | 
				
			||||||
                        strm.zalloc = Z_NULL;
 | 
					                        ret_1 = gzip_init(&gz_state);
 | 
				
			||||||
                        strm.zfree = Z_NULL;
 | 
					                        ret_2 = brotli_init(&br_state);
 | 
				
			||||||
                        strm.opaque = Z_NULL;
 | 
					                        if (ret_1 != 0) {
 | 
				
			||||||
                        if (deflateInit(&strm, level) != Z_OK) {
 | 
					                            fprintf(stderr, ERR_STR "Unable to init gzip: %s" CLR_STR "\n", strerror(errno));
 | 
				
			||||||
                            fprintf(stderr, ERR_STR "Unable to init deflate: %s" CLR_STR "\n", strerror(errno));
 | 
					 | 
				
			||||||
                            compress = 0;
 | 
					                            compress = 0;
 | 
				
			||||||
                            fclose(comp_file);
 | 
					                            fclose(comp_file_gz);
 | 
				
			||||||
 | 
					                            fclose(comp_file_br);
 | 
				
			||||||
 | 
					                        } else if (ret_2 != 0) {
 | 
				
			||||||
 | 
					                            fprintf(stderr, ERR_STR "Unable to init brotli: %s" CLR_STR "\n", strerror(errno));
 | 
				
			||||||
 | 
					                            compress = 0;
 | 
				
			||||||
 | 
					                            fclose(comp_file_gz);
 | 
				
			||||||
 | 
					                            fclose(comp_file_br);
 | 
				
			||||||
                        }
 | 
					                        }
 | 
				
			||||||
                    }
 | 
					                    }
 | 
				
			||||||
                }
 | 
					                }
 | 
				
			||||||
@@ -138,25 +155,33 @@ int cache_process() {
 | 
				
			|||||||
                while ((read = fread(buf, 1, sizeof(buf), file)) > 0) {
 | 
					                while ((read = fread(buf, 1, sizeof(buf), file)) > 0) {
 | 
				
			||||||
                    SHA1_Update(&ctx, buf, read);
 | 
					                    SHA1_Update(&ctx, buf, read);
 | 
				
			||||||
                    if (compress) {
 | 
					                    if (compress) {
 | 
				
			||||||
                        strm.avail_in = read;
 | 
					                        unsigned long avail_in, avail_out;
 | 
				
			||||||
                        strm.next_in = (unsigned char *) buf;
 | 
					                        avail_in = read;
 | 
				
			||||||
                        do {
 | 
					                        do {
 | 
				
			||||||
                            strm.avail_out = sizeof(comp_buf);
 | 
					                            avail_out = sizeof(comp_buf);
 | 
				
			||||||
                            strm.next_out = (unsigned char *) comp_buf;
 | 
					                            gzip_compress(&gz_state, buf + read - avail_in, &avail_in, comp_buf, &avail_out, feof(file));
 | 
				
			||||||
                            deflate(&strm, feof(file) ? Z_FINISH : Z_NO_FLUSH);
 | 
					                            fwrite(comp_buf, 1, sizeof(comp_buf) - avail_out, comp_file_gz);
 | 
				
			||||||
                            fwrite(comp_buf, 1, sizeof(comp_buf) - strm.avail_out, comp_file);
 | 
					                        } while (avail_in != 0);
 | 
				
			||||||
                            strm.avail_in = 0;
 | 
					                        avail_in = read;
 | 
				
			||||||
                        } while (strm.avail_out == 0);
 | 
					                        do {
 | 
				
			||||||
 | 
					                            avail_out = sizeof(comp_buf);
 | 
				
			||||||
 | 
					                            brotli_compress(br_state, buf + read - avail_in, &avail_in, comp_buf, &avail_out, feof(file));
 | 
				
			||||||
 | 
					                            fwrite(comp_buf, 1, sizeof(comp_buf) - avail_out, comp_file_br);
 | 
				
			||||||
 | 
					                        } while (avail_in != 0);
 | 
				
			||||||
                    }
 | 
					                    }
 | 
				
			||||||
                }
 | 
					                }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                if (compress) {
 | 
					                if (compress) {
 | 
				
			||||||
                    deflateEnd(&strm);
 | 
					                    gzip_free(&gz_state);
 | 
				
			||||||
                    fclose(comp_file);
 | 
					                    brotli_free(br_state);
 | 
				
			||||||
 | 
					                    fclose(comp_file_gz);
 | 
				
			||||||
 | 
					                    fclose(comp_file_br);
 | 
				
			||||||
                    fprintf(stdout, "[cache] Finished compressing file %s\n", cache[i].filename);
 | 
					                    fprintf(stdout, "[cache] Finished compressing file %s\n", cache[i].filename);
 | 
				
			||||||
                    strcpy(cache[i].meta.filename_comp, filename_comp);
 | 
					                    strcpy(cache[i].meta.filename_comp_gz, filename_comp_gz);
 | 
				
			||||||
 | 
					                    strcpy(cache[i].meta.filename_comp_br, filename_comp_br);
 | 
				
			||||||
                } else {
 | 
					                } else {
 | 
				
			||||||
                    memset(cache[i].meta.filename_comp, 0, sizeof(cache[i].meta.filename_comp));
 | 
					                    memset(cache[i].meta.filename_comp_gz, 0, sizeof(cache[i].meta.filename_comp_gz));
 | 
				
			||||||
 | 
					                    memset(cache[i].meta.filename_comp_br, 0, sizeof(cache[i].meta.filename_comp_br));
 | 
				
			||||||
                }
 | 
					                }
 | 
				
			||||||
                SHA1_Final(hash, &ctx);
 | 
					                SHA1_Final(hash, &ctx);
 | 
				
			||||||
                memset(cache[i].meta.etag, 0, sizeof(cache[i].meta.etag));
 | 
					                memset(cache[i].meta.etag, 0, sizeof(cache[i].meta.etag));
 | 
				
			||||||
@@ -173,7 +198,11 @@ int cache_process() {
 | 
				
			|||||||
        if (cache_changed) {
 | 
					        if (cache_changed) {
 | 
				
			||||||
            cache_changed = 0;
 | 
					            cache_changed = 0;
 | 
				
			||||||
            cache_file = fopen("/var/necronda-server/cache", "wb");
 | 
					            cache_file = fopen("/var/necronda-server/cache", "wb");
 | 
				
			||||||
            fwrite(cache, sizeof(cache_entry), FILE_CACHE_SIZE, cache_file);
 | 
					            if (cache_file == NULL) {
 | 
				
			||||||
 | 
					                fprintf(stderr, ERR_STR "Unable to open cache file: %s" CLR_STR "\n", strerror(errno));
 | 
				
			||||||
 | 
					                return -1;
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					            fwrite(cache, sizeof(cache_entry), CACHE_ENTRIES, cache_file);
 | 
				
			||||||
            fclose(cache_file);
 | 
					            fclose(cache_file);
 | 
				
			||||||
        } else {
 | 
					        } else {
 | 
				
			||||||
            sleep(1);
 | 
					            sleep(1);
 | 
				
			||||||
@@ -187,7 +216,7 @@ int cache_init() {
 | 
				
			|||||||
        return -1;
 | 
					        return -1;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    int shm_id = shmget(SHM_KEY_CACHE, FILE_CACHE_SIZE * sizeof(cache_entry), IPC_CREAT | IPC_EXCL | 0600);
 | 
					    int shm_id = shmget(CACHE_SHM_KEY, CACHE_ENTRIES * sizeof(cache_entry), IPC_CREAT | IPC_EXCL | 0600);
 | 
				
			||||||
    if (shm_id < 0) {
 | 
					    if (shm_id < 0) {
 | 
				
			||||||
        fprintf(stderr, ERR_STR "Unable to create shared memory: %s" CLR_STR "\n", strerror(errno));
 | 
					        fprintf(stderr, ERR_STR "Unable to create shared memory: %s" CLR_STR "\n", strerror(errno));
 | 
				
			||||||
        return -2;
 | 
					        return -2;
 | 
				
			||||||
@@ -206,7 +235,7 @@ int cache_init() {
 | 
				
			|||||||
        return -4;
 | 
					        return -4;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    cache = shm_rw;
 | 
					    cache = shm_rw;
 | 
				
			||||||
    memset(cache, 0, FILE_CACHE_SIZE * sizeof(cache_entry));
 | 
					    memset(cache, 0, CACHE_ENTRIES * sizeof(cache_entry));
 | 
				
			||||||
    shmdt(shm_rw);
 | 
					    shmdt(shm_rw);
 | 
				
			||||||
    cache = shm;
 | 
					    cache = shm;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -229,7 +258,7 @@ int cache_init() {
 | 
				
			|||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
int cache_unload() {
 | 
					int cache_unload() {
 | 
				
			||||||
    int shm_id = shmget(SHM_KEY_CACHE, 0, 0);
 | 
					    int shm_id = shmget(CACHE_SHM_KEY, 0, 0);
 | 
				
			||||||
    if (shm_id < 0) {
 | 
					    if (shm_id < 0) {
 | 
				
			||||||
        fprintf(stderr, ERR_STR "Unable to get shared memory id: %s" CLR_STR "\n", strerror(errno));
 | 
					        fprintf(stderr, ERR_STR "Unable to get shared memory id: %s" CLR_STR "\n", strerror(errno));
 | 
				
			||||||
        shmdt(cache);
 | 
					        shmdt(cache);
 | 
				
			||||||
@@ -245,7 +274,7 @@ int cache_unload() {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
int cache_update_entry(int entry_num, const char *filename, const char *webroot) {
 | 
					int cache_update_entry(int entry_num, const char *filename, const char *webroot) {
 | 
				
			||||||
    void *cache_ro = cache;
 | 
					    void *cache_ro = cache;
 | 
				
			||||||
    int shm_id = shmget(SHM_KEY_CACHE, 0, 0);
 | 
					    int shm_id = shmget(CACHE_SHM_KEY, 0, 0);
 | 
				
			||||||
    void *shm_rw = shmat(shm_id, NULL, 0);
 | 
					    void *shm_rw = shmat(shm_id, NULL, 0);
 | 
				
			||||||
    if (shm_rw == (void *) -1) {
 | 
					    if (shm_rw == (void *) -1) {
 | 
				
			||||||
        print(ERR_STR "Unable to attach shared memory (rw): %s" CLR_STR, strerror(errno));
 | 
					        print(ERR_STR "Unable to attach shared memory (rw): %s" CLR_STR, strerror(errno));
 | 
				
			||||||
@@ -277,7 +306,8 @@ int cache_update_entry(int entry_num, const char *filename, const char *webroot)
 | 
				
			|||||||
    strcpy(cache[entry_num].meta.charset, magic_file(magic, filename));
 | 
					    strcpy(cache[entry_num].meta.charset, magic_file(magic, filename));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    memset(cache[entry_num].meta.etag, 0, sizeof(cache[entry_num].meta.etag));
 | 
					    memset(cache[entry_num].meta.etag, 0, sizeof(cache[entry_num].meta.etag));
 | 
				
			||||||
    memset(cache[entry_num].meta.filename_comp, 0, sizeof(cache[entry_num].meta.filename_comp));
 | 
					    memset(cache[entry_num].meta.filename_comp_gz, 0, sizeof(cache[entry_num].meta.filename_comp_gz));
 | 
				
			||||||
 | 
					    memset(cache[entry_num].meta.filename_comp_br, 0, sizeof(cache[entry_num].meta.filename_comp_br));
 | 
				
			||||||
    cache[entry_num].is_updating = 0;
 | 
					    cache[entry_num].is_updating = 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    shmdt(shm_rw);
 | 
					    shmdt(shm_rw);
 | 
				
			||||||
@@ -287,7 +317,7 @@ int cache_update_entry(int entry_num, const char *filename, const char *webroot)
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
int cache_filename_comp_invalid(const char *filename) {
 | 
					int cache_filename_comp_invalid(const char *filename) {
 | 
				
			||||||
    void *cache_ro = cache;
 | 
					    void *cache_ro = cache;
 | 
				
			||||||
    int shm_id = shmget(SHM_KEY_CACHE, 0, 0);
 | 
					    int shm_id = shmget(CACHE_SHM_KEY, 0, 0);
 | 
				
			||||||
    void *shm_rw = shmat(shm_id, NULL, 0);
 | 
					    void *shm_rw = shmat(shm_id, NULL, 0);
 | 
				
			||||||
    if (shm_rw == (void *) -1) {
 | 
					    if (shm_rw == (void *) -1) {
 | 
				
			||||||
        print(ERR_STR "Unable to attach shared memory (rw): %s" CLR_STR, strerror(errno));
 | 
					        print(ERR_STR "Unable to attach shared memory (rw): %s" CLR_STR, strerror(errno));
 | 
				
			||||||
@@ -296,7 +326,7 @@ int cache_filename_comp_invalid(const char *filename) {
 | 
				
			|||||||
    cache = shm_rw;
 | 
					    cache = shm_rw;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    int i;
 | 
					    int i;
 | 
				
			||||||
    for (i = 0; i < FILE_CACHE_SIZE; i++) {
 | 
					    for (i = 0; i < CACHE_ENTRIES; i++) {
 | 
				
			||||||
        if (cache[i].filename[0] != 0 && strlen(cache[i].filename) == strlen(filename) &&
 | 
					        if (cache[i].filename[0] != 0 && strlen(cache[i].filename) == strlen(filename) &&
 | 
				
			||||||
                strcmp(cache[i].filename, filename) == 0) {
 | 
					                strcmp(cache[i].filename, filename) == 0) {
 | 
				
			||||||
            if (cache[i].is_updating) {
 | 
					            if (cache[i].is_updating) {
 | 
				
			||||||
@@ -308,7 +338,8 @@ int cache_filename_comp_invalid(const char *filename) {
 | 
				
			|||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    memset(cache[i].meta.etag, 0, sizeof(cache[i].meta.etag));
 | 
					    memset(cache[i].meta.etag, 0, sizeof(cache[i].meta.etag));
 | 
				
			||||||
    memset(cache[i].meta.filename_comp, 0, sizeof(cache[i].meta.filename_comp));
 | 
					    memset(cache[i].meta.filename_comp_gz, 0, sizeof(cache[i].meta.filename_comp_gz));
 | 
				
			||||||
 | 
					    memset(cache[i].meta.filename_comp_br, 0, sizeof(cache[i].meta.filename_comp_br));
 | 
				
			||||||
    cache[i].is_updating = 0;
 | 
					    cache[i].is_updating = 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    shmdt(shm_rw);
 | 
					    shmdt(shm_rw);
 | 
				
			||||||
@@ -322,7 +353,7 @@ int uri_cache_init(http_uri *uri) {
 | 
				
			|||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    int i;
 | 
					    int i;
 | 
				
			||||||
    for (i = 0; i < FILE_CACHE_SIZE; i++) {
 | 
					    for (i = 0; i < CACHE_ENTRIES; i++) {
 | 
				
			||||||
        if (cache[i].filename[0] != 0 && strlen(cache[i].filename) == strlen(uri->filename) &&
 | 
					        if (cache[i].filename[0] != 0 && strlen(cache[i].filename) == strlen(uri->filename) &&
 | 
				
			||||||
                strcmp(cache[i].filename, uri->filename) == 0) {
 | 
					                strcmp(cache[i].filename, uri->filename) == 0) {
 | 
				
			||||||
            uri->meta = &cache[i].meta;
 | 
					            uri->meta = &cache[i].meta;
 | 
				
			||||||
@@ -335,7 +366,7 @@ int uri_cache_init(http_uri *uri) {
 | 
				
			|||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    if (uri->meta == NULL) {
 | 
					    if (uri->meta == NULL) {
 | 
				
			||||||
        for (i = 0; i < FILE_CACHE_SIZE; i++) {
 | 
					        for (i = 0; i < CACHE_ENTRIES; i++) {
 | 
				
			||||||
            if (cache[i].filename[0] == 0) {
 | 
					            if (cache[i].filename[0] == 0) {
 | 
				
			||||||
                if (cache_update_entry(i, uri->filename, uri->webroot) != 0) {
 | 
					                if (cache_update_entry(i, uri->filename, uri->webroot) != 0) {
 | 
				
			||||||
                    return -1;
 | 
					                    return -1;
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -10,6 +10,18 @@
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
#include "uri.h"
 | 
					#include "uri.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#define CACHE_SHM_KEY 255641
 | 
				
			||||||
 | 
					#define CACHE_ENTRIES 1024
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#ifndef CACHE_MAGIC_FILE
 | 
				
			||||||
 | 
					#   define CACHE_MAGIC_FILE "/usr/share/file/misc/magic.mgc"
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#ifndef DEFAULT_CONFIG_FILE
 | 
				
			||||||
 | 
					#   define DEFAULT_CONFIG_FILE "/etc/necronda-server/necronda-server.conf"
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
typedef struct {
 | 
					typedef struct {
 | 
				
			||||||
    char filename[256];
 | 
					    char filename[256];
 | 
				
			||||||
    unsigned char webroot_len;
 | 
					    unsigned char webroot_len;
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -6,20 +6,19 @@
 | 
				
			|||||||
 */
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#include "config.h"
 | 
					#include "config.h"
 | 
				
			||||||
#include "../necronda-server.h"
 | 
					#include "utils.h"
 | 
				
			||||||
#include <stdio.h>
 | 
					#include <stdio.h>
 | 
				
			||||||
#include <sys/ipc.h>
 | 
					#include <sys/ipc.h>
 | 
				
			||||||
#include <sys/shm.h>
 | 
					#include <sys/shm.h>
 | 
				
			||||||
#include <string.h>
 | 
					#include <string.h>
 | 
				
			||||||
#include <errno.h>
 | 
					#include <errno.h>
 | 
				
			||||||
#include <malloc.h>
 | 
					 | 
				
			||||||
#include <stdlib.h>
 | 
					#include <stdlib.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
host_config *config;
 | 
					host_config *config;
 | 
				
			||||||
char cert_file[256], key_file[256], geoip_dir[256], dns_server[256];
 | 
					char cert_file[256], key_file[256], geoip_dir[256], dns_server[256];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
int config_init() {
 | 
					int config_init() {
 | 
				
			||||||
    int shm_id = shmget(SHM_KEY_CONFIG, MAX_HOST_CONFIG * sizeof(host_config), IPC_CREAT | IPC_EXCL | 0640);
 | 
					    int shm_id = shmget(CONFIG_SHM_KEY, CONFIG_MAX_HOST_CONFIG * sizeof(host_config), IPC_CREAT | IPC_EXCL | 0640);
 | 
				
			||||||
    if (shm_id < 0) {
 | 
					    if (shm_id < 0) {
 | 
				
			||||||
        fprintf(stderr, ERR_STR "Unable to create shared memory: %s" CLR_STR "\n", strerror(errno));
 | 
					        fprintf(stderr, ERR_STR "Unable to create shared memory: %s" CLR_STR "\n", strerror(errno));
 | 
				
			||||||
        return -1;
 | 
					        return -1;
 | 
				
			||||||
@@ -38,14 +37,14 @@ int config_init() {
 | 
				
			|||||||
        return -3;
 | 
					        return -3;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    config = shm_rw;
 | 
					    config = shm_rw;
 | 
				
			||||||
    memset(config, 0, MAX_HOST_CONFIG * sizeof(host_config));
 | 
					    memset(config, 0, CONFIG_MAX_HOST_CONFIG * sizeof(host_config));
 | 
				
			||||||
    shmdt(shm_rw);
 | 
					    shmdt(shm_rw);
 | 
				
			||||||
    config = shm;
 | 
					    config = shm;
 | 
				
			||||||
    return 0;
 | 
					    return 0;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
int config_unload() {
 | 
					int config_unload() {
 | 
				
			||||||
    int shm_id = shmget(SHM_KEY_CONFIG, 0, 0);
 | 
					    int shm_id = shmget(CONFIG_SHM_KEY, 0, 0);
 | 
				
			||||||
    if (shm_id < 0) {
 | 
					    if (shm_id < 0) {
 | 
				
			||||||
        fprintf(stderr, ERR_STR "Unable to get shared memory id: %s" CLR_STR "\n", strerror(errno));
 | 
					        fprintf(stderr, ERR_STR "Unable to get shared memory id: %s" CLR_STR "\n", strerror(errno));
 | 
				
			||||||
        shmdt(config);
 | 
					        shmdt(config);
 | 
				
			||||||
@@ -73,8 +72,8 @@ int config_load(const char *filename) {
 | 
				
			|||||||
    fread(conf, 1, len, file);
 | 
					    fread(conf, 1, len, file);
 | 
				
			||||||
    fclose(file);
 | 
					    fclose(file);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    host_config *tmp_config = malloc(MAX_HOST_CONFIG * sizeof(host_config));
 | 
					    host_config *tmp_config = malloc(CONFIG_MAX_HOST_CONFIG * sizeof(host_config));
 | 
				
			||||||
    memset(tmp_config, 0, MAX_HOST_CONFIG * sizeof(host_config));
 | 
					    memset(tmp_config, 0, CONFIG_MAX_HOST_CONFIG * sizeof(host_config));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    int i = 0;
 | 
					    int i = 0;
 | 
				
			||||||
    int mode = 0;
 | 
					    int mode = 0;
 | 
				
			||||||
@@ -195,7 +194,7 @@ int config_load(const char *filename) {
 | 
				
			|||||||
        }
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    int shm_id = shmget(SHM_KEY_CONFIG, 0, 0);
 | 
					    int shm_id = shmget(CONFIG_SHM_KEY, 0, 0);
 | 
				
			||||||
    if (shm_id < 0) {
 | 
					    if (shm_id < 0) {
 | 
				
			||||||
        fprintf(stderr, ERR_STR "Unable to get shared memory id: %s" CLR_STR "\n", strerror(errno));
 | 
					        fprintf(stderr, ERR_STR "Unable to get shared memory id: %s" CLR_STR "\n", strerror(errno));
 | 
				
			||||||
        shmdt(config);
 | 
					        shmdt(config);
 | 
				
			||||||
@@ -208,7 +207,7 @@ int config_load(const char *filename) {
 | 
				
			|||||||
        fprintf(stderr, ERR_STR "Unable to attach shared memory (rw): %s" CLR_STR "\n", strerror(errno));
 | 
					        fprintf(stderr, ERR_STR "Unable to attach shared memory (rw): %s" CLR_STR "\n", strerror(errno));
 | 
				
			||||||
        return -4;
 | 
					        return -4;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    memcpy(shm_rw, tmp_config, MAX_HOST_CONFIG * sizeof(host_config));
 | 
					    memcpy(shm_rw, tmp_config, CONFIG_MAX_HOST_CONFIG * sizeof(host_config));
 | 
				
			||||||
    free(tmp_config);
 | 
					    free(tmp_config);
 | 
				
			||||||
    shmdt(shm_rw);
 | 
					    shmdt(shm_rw);
 | 
				
			||||||
    return 0;
 | 
					    return 0;
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -10,6 +10,9 @@
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
#include "uri.h"
 | 
					#include "uri.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#define CONFIG_SHM_KEY 255642
 | 
				
			||||||
 | 
					#define CONFIG_MAX_HOST_CONFIG 64
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#define CONFIG_TYPE_UNSET 0
 | 
					#define CONFIG_TYPE_UNSET 0
 | 
				
			||||||
#define CONFIG_TYPE_LOCAL 1
 | 
					#define CONFIG_TYPE_LOCAL 1
 | 
				
			||||||
#define CONFIG_TYPE_REVERSE_PROXY 2
 | 
					#define CONFIG_TYPE_REVERSE_PROXY 2
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -7,10 +7,10 @@
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
#include "fastcgi.h"
 | 
					#include "fastcgi.h"
 | 
				
			||||||
#include "utils.h"
 | 
					#include "utils.h"
 | 
				
			||||||
#include "../client.h"
 | 
					#include "gzip.h"
 | 
				
			||||||
 | 
					#include "brotli.h"
 | 
				
			||||||
#include "../necronda-server.h"
 | 
					#include "../necronda-server.h"
 | 
				
			||||||
#include <sys/un.h>
 | 
					#include <sys/un.h>
 | 
				
			||||||
#include <zlib.h>
 | 
					 | 
				
			||||||
#include <sys/socket.h>
 | 
					#include <sys/socket.h>
 | 
				
			||||||
#include <errno.h>
 | 
					#include <errno.h>
 | 
				
			||||||
#include <string.h>
 | 
					#include <string.h>
 | 
				
			||||||
@@ -385,7 +385,7 @@ int fastcgi_header(fastcgi_conn *conn, http_res *res, char *err_msg) {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
int fastcgi_send(fastcgi_conn *conn, sock *client, int flags) {
 | 
					int fastcgi_send(fastcgi_conn *conn, sock *client, int flags) {
 | 
				
			||||||
    FCGI_Header header;
 | 
					    FCGI_Header header;
 | 
				
			||||||
    int ret;
 | 
					    long ret;
 | 
				
			||||||
    char buf0[256];
 | 
					    char buf0[256];
 | 
				
			||||||
    int len;
 | 
					    int len;
 | 
				
			||||||
    char *content, *ptr;
 | 
					    char *content, *ptr;
 | 
				
			||||||
@@ -393,15 +393,19 @@ int fastcgi_send(fastcgi_conn *conn, sock *client, int flags) {
 | 
				
			|||||||
    char comp_out[4096];
 | 
					    char comp_out[4096];
 | 
				
			||||||
    int finish_comp = 0;
 | 
					    int finish_comp = 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    z_stream strm;
 | 
					    z_stream gz_state;
 | 
				
			||||||
    if (flags & FASTCGI_COMPRESS) {
 | 
					    BrotliEncoderState *br_state = NULL;
 | 
				
			||||||
        int level = NECRONDA_ZLIB_LEVEL;
 | 
					    if (flags & FASTCGI_COMPRESS_BR) {
 | 
				
			||||||
        strm.zalloc = Z_NULL;
 | 
					        flags &= !FASTCGI_COMPRESS_GZ;
 | 
				
			||||||
        strm.zfree = Z_NULL;
 | 
					        if (brotli_init(&br_state) != 0) {
 | 
				
			||||||
        strm.opaque = Z_NULL;
 | 
					            print(ERR_STR "Unable to init brotli: %s" CLR_STR, strerror(errno));
 | 
				
			||||||
        if (deflateInit(&strm, level) != Z_OK) {
 | 
					            flags &= !FASTCGI_COMPRESS_BR;
 | 
				
			||||||
            print(ERR_STR "Unable to init deflate: %s" CLR_STR, strerror(errno));
 | 
					        }
 | 
				
			||||||
            flags &= !FASTCGI_COMPRESS;
 | 
					    } else if (flags & FASTCGI_COMPRESS_GZ) {
 | 
				
			||||||
 | 
					        flags &= !FASTCGI_COMPRESS_BR;
 | 
				
			||||||
 | 
					        if (gzip_init(&gz_state) != 0) {
 | 
				
			||||||
 | 
					            print(ERR_STR "Unable to init gzip: %s" CLR_STR, strerror(errno));
 | 
				
			||||||
 | 
					            flags &= !FASTCGI_COMPRESS_GZ;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -455,7 +459,8 @@ int fastcgi_send(fastcgi_conn *conn, sock *client, int flags) {
 | 
				
			|||||||
                content_len = 0;
 | 
					                content_len = 0;
 | 
				
			||||||
                goto out;
 | 
					                goto out;
 | 
				
			||||||
                finish:
 | 
					                finish:
 | 
				
			||||||
                deflateEnd(&strm);
 | 
					                if (flags & FASTCGI_COMPRESS_GZ) gzip_free(&gz_state);
 | 
				
			||||||
 | 
					                if (flags & FASTCGI_COMPRESS_BR) brotli_free(br_state);
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            if (flags & FASTCGI_CHUNKED) {
 | 
					            if (flags & FASTCGI_CHUNKED) {
 | 
				
			||||||
@@ -466,20 +471,20 @@ int fastcgi_send(fastcgi_conn *conn, sock *client, int flags) {
 | 
				
			|||||||
        } else if (header.type == FCGI_STDERR) {
 | 
					        } else if (header.type == FCGI_STDERR) {
 | 
				
			||||||
            fastcgi_php_error(content, content_len, buf0);
 | 
					            fastcgi_php_error(content, content_len, buf0);
 | 
				
			||||||
        } else if (header.type == FCGI_STDOUT) {
 | 
					        } else if (header.type == FCGI_STDOUT) {
 | 
				
			||||||
 | 
					            unsigned long avail_in = content_len, avail_out;
 | 
				
			||||||
 | 
					            void *next_in = ptr;
 | 
				
			||||||
            out:
 | 
					            out:
 | 
				
			||||||
            if (flags & FASTCGI_COMPRESS) {
 | 
					 | 
				
			||||||
                strm.avail_in = content_len;
 | 
					 | 
				
			||||||
                strm.next_in = (unsigned char *) ptr;
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
            do {
 | 
					            do {
 | 
				
			||||||
                int buf_len = content_len;
 | 
					                int buf_len = content_len;
 | 
				
			||||||
                if (flags & FASTCGI_COMPRESS) {
 | 
					                if (flags & FASTCGI_COMPRESS) {
 | 
				
			||||||
                    strm.avail_out = sizeof(comp_out);
 | 
					                    avail_out = sizeof(comp_out);
 | 
				
			||||||
                    strm.next_out = (unsigned char *) comp_out;
 | 
					                    if (flags & FASTCGI_COMPRESS_GZ) {
 | 
				
			||||||
                    deflate(&strm, finish_comp ? Z_FINISH : Z_NO_FLUSH);
 | 
					                        gzip_compress(&gz_state, next_in + content_len - avail_in, &avail_in, comp_out, &avail_out, finish_comp);
 | 
				
			||||||
                    strm.avail_in = 0;
 | 
					                    } else if (flags & FASTCGI_COMPRESS_BR) {
 | 
				
			||||||
 | 
					                        brotli_compress(br_state, next_in + content_len - avail_in, &avail_in, comp_out, &avail_out, finish_comp);
 | 
				
			||||||
 | 
					                    }
 | 
				
			||||||
                    ptr = comp_out;
 | 
					                    ptr = comp_out;
 | 
				
			||||||
                    buf_len = (int) (sizeof(comp_out) - strm.avail_out);
 | 
					                    buf_len = (int) (sizeof(comp_out) - avail_out);
 | 
				
			||||||
                }
 | 
					                }
 | 
				
			||||||
                if (buf_len != 0) {
 | 
					                if (buf_len != 0) {
 | 
				
			||||||
                    len = sprintf(buf0, "%X\r\n", buf_len);
 | 
					                    len = sprintf(buf0, "%X\r\n", buf_len);
 | 
				
			||||||
@@ -487,7 +492,7 @@ int fastcgi_send(fastcgi_conn *conn, sock *client, int flags) {
 | 
				
			|||||||
                    sock_send(client, ptr, buf_len, 0);
 | 
					                    sock_send(client, ptr, buf_len, 0);
 | 
				
			||||||
                    if (flags & FASTCGI_CHUNKED) sock_send(client, "\r\n", 2, 0);
 | 
					                    if (flags & FASTCGI_CHUNKED) sock_send(client, "\r\n", 2, 0);
 | 
				
			||||||
                }
 | 
					                }
 | 
				
			||||||
            } while ((flags & FASTCGI_COMPRESS) && strm.avail_out == 0);
 | 
					            } while ((flags & FASTCGI_COMPRESS) && avail_in != 0);
 | 
				
			||||||
            if (finish_comp) goto finish;
 | 
					            if (finish_comp) goto finish;
 | 
				
			||||||
        } else {
 | 
					        } else {
 | 
				
			||||||
            print(ERR_STR "Unknown FastCGI type: %i" CLR_STR, header.type);
 | 
					            print(ERR_STR "Unknown FastCGI type: %i" CLR_STR, header.type);
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -13,7 +13,13 @@
 | 
				
			|||||||
#include "uri.h"
 | 
					#include "uri.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#define FASTCGI_CHUNKED 1
 | 
					#define FASTCGI_CHUNKED 1
 | 
				
			||||||
#define FASTCGI_COMPRESS 2
 | 
					#define FASTCGI_COMPRESS_GZ 2
 | 
				
			||||||
 | 
					#define FASTCGI_COMPRESS_BR 4
 | 
				
			||||||
 | 
					#define FASTCGI_COMPRESS 6
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#ifndef PHP_FPM_SOCKET
 | 
				
			||||||
 | 
					#   define PHP_FPM_SOCKET "/var/run/php-fpm/php-fpm.sock"
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
typedef struct {
 | 
					typedef struct {
 | 
				
			||||||
    int socket;
 | 
					    int socket;
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										69
									
								
								src/lib/geoip.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										69
									
								
								src/lib/geoip.c
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,69 @@
 | 
				
			|||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * Necronda Web Server
 | 
				
			||||||
 | 
					 * MaxMind GeoIP Database interface
 | 
				
			||||||
 | 
					 * src/lib/geoip.c
 | 
				
			||||||
 | 
					 * Lorenz Stechauner, 2021-05-04
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include "geoip.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					MMDB_entry_data_list_s *mmdb_json(MMDB_entry_data_list_s *list, char *str, long *str_off, long str_len) {
 | 
				
			||||||
 | 
					    switch (list->entry_data.type) {
 | 
				
			||||||
 | 
					        case MMDB_DATA_TYPE_MAP:
 | 
				
			||||||
 | 
					            *str_off += sprintf(str + *str_off, "{");
 | 
				
			||||||
 | 
					            break;
 | 
				
			||||||
 | 
					        case MMDB_DATA_TYPE_ARRAY:
 | 
				
			||||||
 | 
					            *str_off += sprintf(str + *str_off, "[");
 | 
				
			||||||
 | 
					            break;
 | 
				
			||||||
 | 
					        case MMDB_DATA_TYPE_UTF8_STRING:
 | 
				
			||||||
 | 
					            *str_off += sprintf(str + *str_off, "\"%.*s\"", list->entry_data.data_size, list->entry_data.utf8_string);
 | 
				
			||||||
 | 
					            break;
 | 
				
			||||||
 | 
					        case MMDB_DATA_TYPE_UINT16:
 | 
				
			||||||
 | 
					            *str_off += sprintf(str + *str_off, "%u", list->entry_data.uint16);
 | 
				
			||||||
 | 
					            break;
 | 
				
			||||||
 | 
					        case MMDB_DATA_TYPE_UINT32:
 | 
				
			||||||
 | 
					            *str_off += sprintf(str + *str_off, "%u", list->entry_data.uint32);
 | 
				
			||||||
 | 
					            break;
 | 
				
			||||||
 | 
					        case MMDB_DATA_TYPE_UINT64:
 | 
				
			||||||
 | 
					            *str_off += sprintf(str + *str_off, "%lu", list->entry_data.uint64);
 | 
				
			||||||
 | 
					            break;
 | 
				
			||||||
 | 
					        case MMDB_DATA_TYPE_UINT128:
 | 
				
			||||||
 | 
					            *str_off += sprintf(str + *str_off, "%llu", (unsigned long long) list->entry_data.uint128);
 | 
				
			||||||
 | 
					            break;
 | 
				
			||||||
 | 
					        case MMDB_DATA_TYPE_INT32:
 | 
				
			||||||
 | 
					            *str_off += sprintf(str + *str_off, "%i", list->entry_data.uint32);
 | 
				
			||||||
 | 
					            break;
 | 
				
			||||||
 | 
					        case MMDB_DATA_TYPE_BOOLEAN:
 | 
				
			||||||
 | 
					            *str_off += sprintf(str + *str_off, "%s", list->entry_data.boolean ? "true" : "false");
 | 
				
			||||||
 | 
					            break;
 | 
				
			||||||
 | 
					        case MMDB_DATA_TYPE_FLOAT:
 | 
				
			||||||
 | 
					            *str_off += sprintf(str + *str_off, "%f", list->entry_data.float_value);
 | 
				
			||||||
 | 
					            break;
 | 
				
			||||||
 | 
					        case MMDB_DATA_TYPE_DOUBLE:
 | 
				
			||||||
 | 
					            *str_off += sprintf(str + *str_off, "%f", list->entry_data.double_value);
 | 
				
			||||||
 | 
					            break;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    if (list->entry_data.type != MMDB_DATA_TYPE_MAP && list->entry_data.type != MMDB_DATA_TYPE_ARRAY) {
 | 
				
			||||||
 | 
					        return list->next;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    MMDB_entry_data_list_s *next = list->next;
 | 
				
			||||||
 | 
					    int stat = 0;
 | 
				
			||||||
 | 
					    for (int i = 0; i < list->entry_data.data_size; i++) {
 | 
				
			||||||
 | 
					        next = mmdb_json(next, str, str_off, str_len);
 | 
				
			||||||
 | 
					        if (list->entry_data.type == MMDB_DATA_TYPE_MAP) {
 | 
				
			||||||
 | 
					            stat = !stat;
 | 
				
			||||||
 | 
					            if (stat) {
 | 
				
			||||||
 | 
					                i--;
 | 
				
			||||||
 | 
					                *str_off += sprintf(str + *str_off, ":");
 | 
				
			||||||
 | 
					                continue;
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        if (i != list->entry_data.data_size - 1) *str_off += sprintf(str + *str_off, ",");
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    if (list->entry_data.type == MMDB_DATA_TYPE_MAP) {
 | 
				
			||||||
 | 
					        *str_off += sprintf(str + *str_off, "}");
 | 
				
			||||||
 | 
					    } else {
 | 
				
			||||||
 | 
					        *str_off += sprintf(str + *str_off, "]");
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    return next;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										18
									
								
								src/lib/geoip.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										18
									
								
								src/lib/geoip.h
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,18 @@
 | 
				
			|||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * Necronda Web Server
 | 
				
			||||||
 | 
					 * MaxMind GeoIP Database interface (header file)
 | 
				
			||||||
 | 
					 * src/lib/geoip.h
 | 
				
			||||||
 | 
					 * Lorenz Stechauner, 2021-05-04
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#ifndef NECRONDA_SERVER_GEOIP_H
 | 
				
			||||||
 | 
					#define NECRONDA_SERVER_GEOIP_H
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include <maxminddb.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#define GEOIP_MAX_SIZE 8192
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					MMDB_entry_data_list_s *mmdb_json(MMDB_entry_data_list_s *list, char *str, long *str_off, long str_len);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#endif //NECRONDA_SERVER_GEOIP_H
 | 
				
			||||||
							
								
								
									
										28
									
								
								src/lib/gzip.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										28
									
								
								src/lib/gzip.c
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,28 @@
 | 
				
			|||||||
 | 
					/**
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include "gzip.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					int gzip_init(z_stream *stream) {
 | 
				
			||||||
 | 
					    stream->zalloc = Z_NULL;
 | 
				
			||||||
 | 
					    stream->zfree = Z_NULL;
 | 
				
			||||||
 | 
					    stream->opaque = Z_NULL;
 | 
				
			||||||
 | 
					    int ret = deflateInit2(stream, GZIP_LEVEL, Z_DEFLATED, 15 + 16, 9, Z_DEFAULT_STRATEGY);
 | 
				
			||||||
 | 
					    return (ret == Z_OK) ? 0 : -1;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					int gzip_compress(z_stream *stream, const char *in, unsigned long *in_len, char *out, unsigned long *out_len, int finish) {
 | 
				
			||||||
 | 
					    stream->next_in = (unsigned char*) in;
 | 
				
			||||||
 | 
					    stream->avail_in = *in_len;
 | 
				
			||||||
 | 
					    stream->next_out = (unsigned char*) out;
 | 
				
			||||||
 | 
					    stream->avail_out = *out_len;
 | 
				
			||||||
 | 
					    int ret = deflate(stream, finish ? Z_FINISH : Z_NO_FLUSH);
 | 
				
			||||||
 | 
					    *in_len = stream->avail_in;
 | 
				
			||||||
 | 
					    *out_len = stream->avail_out;
 | 
				
			||||||
 | 
					    return ret;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					int gzip_free(z_stream *stream) {
 | 
				
			||||||
 | 
					    return deflateEnd(stream);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										18
									
								
								src/lib/gzip.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										18
									
								
								src/lib/gzip.h
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,18 @@
 | 
				
			|||||||
 | 
					/**
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#ifndef NECRONDA_SERVER_GZIP_H
 | 
				
			||||||
 | 
					#define NECRONDA_SERVER_GZIP_H
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include <zlib.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#define GZIP_LEVEL 9
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					int gzip_init(z_stream *stream);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					int gzip_compress(z_stream *stream, const char *in, unsigned long *in_len, char *out, unsigned long *out_len, int finish);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					int gzip_free(z_stream *stream);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#endif //NECRONDA_SERVER_GZIP_H
 | 
				
			||||||
@@ -18,11 +18,25 @@
 | 
				
			|||||||
#define HTTP_REMOVE_ALL 1
 | 
					#define HTTP_REMOVE_ALL 1
 | 
				
			||||||
#define HTTP_REMOVE_LAST 2
 | 
					#define HTTP_REMOVE_LAST 2
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#define HTTP_1XX_STR "\x1B[1;32m"
 | 
				
			||||||
 | 
					#define HTTP_2XX_STR "\x1B[1;32m"
 | 
				
			||||||
 | 
					#define HTTP_3XX_STR "\x1B[1;33m"
 | 
				
			||||||
 | 
					#define HTTP_4XX_STR "\x1B[1;31m"
 | 
				
			||||||
 | 
					#define HTTP_5XX_STR "\x1B[1;31m"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#define HTTP_COLOR_SUCCESS "#008000"
 | 
					#define HTTP_COLOR_SUCCESS "#008000"
 | 
				
			||||||
#define HTTP_COLOR_INFO "#606060"
 | 
					#define HTTP_COLOR_INFO "#606060"
 | 
				
			||||||
#define HTTP_COLOR_WARNING "#E0C000"
 | 
					#define HTTP_COLOR_WARNING "#E0C000"
 | 
				
			||||||
#define HTTP_COLOR_ERROR "#C00000"
 | 
					#define HTTP_COLOR_ERROR "#C00000"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#ifndef SERVER_STR
 | 
				
			||||||
 | 
					#   define SERVER_STR "Necronda"
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#ifndef SERVER_STR_HTML
 | 
				
			||||||
 | 
					#   define SERVER_STR_HTML "Necronda web server"
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
typedef struct {
 | 
					typedef struct {
 | 
				
			||||||
    unsigned short code;
 | 
					    unsigned short code;
 | 
				
			||||||
    char type[16];
 | 
					    char type[16];
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -6,7 +6,7 @@
 | 
				
			|||||||
 */
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#include "http.h"
 | 
					#include "http.h"
 | 
				
			||||||
#include "../necronda-server.h"
 | 
					#include "utils.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
const http_status http_statuses[] = {
 | 
					const http_status http_statuses[] = {
 | 
				
			||||||
        {100, "Informational", "Continue"},
 | 
					        {100, "Informational", "Continue"},
 | 
				
			||||||
@@ -137,7 +137,7 @@ const char http_default_document[] =
 | 
				
			|||||||
        "\t<main>\n"
 | 
					        "\t<main>\n"
 | 
				
			||||||
        "\t\t<section>\n"
 | 
					        "\t\t<section>\n"
 | 
				
			||||||
        "%3$s"
 | 
					        "%3$s"
 | 
				
			||||||
        "\t\t\t<div class=\"footer\"><a href=\"https://%7$s/\">%7$s</a> - Necronda web server " NECRONDA_VERSION "</div>\n"
 | 
					        "\t\t\t<div class=\"footer\"><a href=\"https://%7$s/\">%7$s</a> - " SERVER_STR_HTML "</div>\n"
 | 
				
			||||||
        "\t\t</section>\n"
 | 
					        "\t\t</section>\n"
 | 
				
			||||||
        "\t</main>\n"
 | 
					        "\t</main>\n"
 | 
				
			||||||
        "</body>\n"
 | 
					        "</body>\n"
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -7,7 +7,6 @@
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
#include "rev_proxy.h"
 | 
					#include "rev_proxy.h"
 | 
				
			||||||
#include "utils.h"
 | 
					#include "utils.h"
 | 
				
			||||||
#include "../client.h"
 | 
					 | 
				
			||||||
#include "../necronda-server.h"
 | 
					#include "../necronda-server.h"
 | 
				
			||||||
#include <openssl/ssl.h>
 | 
					#include <openssl/ssl.h>
 | 
				
			||||||
#include <string.h>
 | 
					#include <string.h>
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -19,7 +19,8 @@ typedef struct {
 | 
				
			|||||||
    char etag[64];
 | 
					    char etag[64];
 | 
				
			||||||
    char type[24];
 | 
					    char type[24];
 | 
				
			||||||
    char charset[16];
 | 
					    char charset[16];
 | 
				
			||||||
    char filename_comp[256];
 | 
					    char filename_comp_gz[256];
 | 
				
			||||||
 | 
					    char filename_comp_br[256];
 | 
				
			||||||
    struct stat stat;
 | 
					    struct stat stat;
 | 
				
			||||||
} meta_data;
 | 
					} meta_data;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -6,6 +6,7 @@
 | 
				
			|||||||
 */
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#include "utils.h"
 | 
					#include "utils.h"
 | 
				
			||||||
 | 
					#include <stdio.h>
 | 
				
			||||||
#include <string.h>
 | 
					#include <string.h>
 | 
				
			||||||
#include <stdlib.h>
 | 
					#include <stdlib.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -26,7 +27,7 @@ char *format_duration(unsigned long micros, char *buf) {
 | 
				
			|||||||
    return buf;
 | 
					    return buf;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
int url_encode_component(const char *str, char *enc, ssize_t *size) {
 | 
					int url_encode_component(const char *str, char *enc, long *size) {
 | 
				
			||||||
    char *ptr = enc;
 | 
					    char *ptr = enc;
 | 
				
			||||||
    char ch;
 | 
					    char ch;
 | 
				
			||||||
    memset(enc, 0, *size);
 | 
					    memset(enc, 0, *size);
 | 
				
			||||||
@@ -53,7 +54,7 @@ int url_encode_component(const char *str, char *enc, ssize_t *size) {
 | 
				
			|||||||
    return 0;
 | 
					    return 0;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
int url_encode(const char *str, char *enc, ssize_t *size) {
 | 
					int url_encode(const char *str, char *enc, long *size) {
 | 
				
			||||||
    char *ptr = enc;
 | 
					    char *ptr = enc;
 | 
				
			||||||
    unsigned char ch;
 | 
					    unsigned char ch;
 | 
				
			||||||
    memset(enc, 0, *size);
 | 
					    memset(enc, 0, *size);
 | 
				
			||||||
@@ -76,7 +77,7 @@ int url_encode(const char *str, char *enc, ssize_t *size) {
 | 
				
			|||||||
    return 0;
 | 
					    return 0;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
int url_decode(const char *str, char *dec, ssize_t *size) {
 | 
					int url_decode(const char *str, char *dec, long *size) {
 | 
				
			||||||
    char *ptr = dec;
 | 
					    char *ptr = dec;
 | 
				
			||||||
    char ch, buf[3];
 | 
					    char ch, buf[3];
 | 
				
			||||||
    memset(dec, 0, *size);
 | 
					    memset(dec, 0, *size);
 | 
				
			||||||
@@ -107,72 +108,21 @@ int mime_is_compressible(const char *type) {
 | 
				
			|||||||
        strncmp(type, "text/", 5) == 0 ||
 | 
					        strncmp(type, "text/", 5) == 0 ||
 | 
				
			||||||
        strncmp(type, "message/", 7) == 0 ||
 | 
					        strncmp(type, "message/", 7) == 0 ||
 | 
				
			||||||
        strstr(type, "+xml") != NULL ||
 | 
					        strstr(type, "+xml") != NULL ||
 | 
				
			||||||
 | 
					        strstr(type, "+json") != NULL ||
 | 
				
			||||||
        strcmp(type, "application/javascript") == 0 ||
 | 
					        strcmp(type, "application/javascript") == 0 ||
 | 
				
			||||||
        strcmp(type, "application/json") == 0 ||
 | 
					        strcmp(type, "application/json") == 0 ||
 | 
				
			||||||
        strcmp(type, "application/xml") == 0 ||
 | 
					        strcmp(type, "application/xml") == 0 ||
 | 
				
			||||||
        strcmp(type, "application/x-www-form-urlencoded") == 0 ||
 | 
					        strcmp(type, "application/x-www-form-urlencoded") == 0 ||
 | 
				
			||||||
        strcmp(type, "application/x-tex") == 0 ||
 | 
					        strcmp(type, "application/x-tex") == 0 ||
 | 
				
			||||||
        strcmp(type, "application/x-httpd-php") == 0 ||
 | 
					        strcmp(type, "application/x-httpd-php") == 0 ||
 | 
				
			||||||
        strcmp(type, "application/x-latex") == 0;
 | 
					        strcmp(type, "application/x-latex") == 0 ||
 | 
				
			||||||
}
 | 
					        strcmp(type, "application/vnd.ms-fontobject") == 0 ||
 | 
				
			||||||
 | 
					        strcmp(type, "application/x-font-ttf") == 0 ||
 | 
				
			||||||
MMDB_entry_data_list_s *mmdb_json(MMDB_entry_data_list_s *list, char *str, long *str_off, long str_len) {
 | 
					        strcmp(type, "application/x-javascript") == 0 ||
 | 
				
			||||||
    switch (list->entry_data.type) {
 | 
					        strcmp(type, "application/x-web-app-manifest+json") == 0 ||
 | 
				
			||||||
        case MMDB_DATA_TYPE_MAP:
 | 
					        strcmp(type, "font/eot") == 0 ||
 | 
				
			||||||
            *str_off += sprintf(str + *str_off, "{");
 | 
					        strcmp(type, "font/opentype") == 0 ||
 | 
				
			||||||
            break;
 | 
					        strcmp(type, "image/bmp") == 0 ||
 | 
				
			||||||
        case MMDB_DATA_TYPE_ARRAY:
 | 
					        strcmp(type, "image/vnd.microsoft.icon") == 0 ||
 | 
				
			||||||
            *str_off += sprintf(str + *str_off, "[");
 | 
					        strcmp(type, "image/x-icon") == 0;
 | 
				
			||||||
            break;
 | 
					 | 
				
			||||||
        case MMDB_DATA_TYPE_UTF8_STRING:
 | 
					 | 
				
			||||||
            *str_off += sprintf(str + *str_off, "\"%.*s\"", list->entry_data.data_size, list->entry_data.utf8_string);
 | 
					 | 
				
			||||||
            break;
 | 
					 | 
				
			||||||
        case MMDB_DATA_TYPE_UINT16:
 | 
					 | 
				
			||||||
            *str_off += sprintf(str + *str_off, "%u", list->entry_data.uint16);
 | 
					 | 
				
			||||||
            break;
 | 
					 | 
				
			||||||
        case MMDB_DATA_TYPE_UINT32:
 | 
					 | 
				
			||||||
            *str_off += sprintf(str + *str_off, "%u", list->entry_data.uint32);
 | 
					 | 
				
			||||||
            break;
 | 
					 | 
				
			||||||
        case MMDB_DATA_TYPE_UINT64:
 | 
					 | 
				
			||||||
            *str_off += sprintf(str + *str_off, "%lu", list->entry_data.uint64);
 | 
					 | 
				
			||||||
            break;
 | 
					 | 
				
			||||||
        case MMDB_DATA_TYPE_UINT128:
 | 
					 | 
				
			||||||
            *str_off += sprintf(str + *str_off, "%llu", (unsigned long long) list->entry_data.uint128);
 | 
					 | 
				
			||||||
            break;
 | 
					 | 
				
			||||||
        case MMDB_DATA_TYPE_INT32:
 | 
					 | 
				
			||||||
            *str_off += sprintf(str + *str_off, "%i", list->entry_data.uint32);
 | 
					 | 
				
			||||||
            break;
 | 
					 | 
				
			||||||
        case MMDB_DATA_TYPE_BOOLEAN:
 | 
					 | 
				
			||||||
            *str_off += sprintf(str + *str_off, "%s", list->entry_data.boolean ? "true" : "false");
 | 
					 | 
				
			||||||
            break;
 | 
					 | 
				
			||||||
        case MMDB_DATA_TYPE_FLOAT:
 | 
					 | 
				
			||||||
            *str_off += sprintf(str + *str_off, "%f", list->entry_data.float_value);
 | 
					 | 
				
			||||||
            break;
 | 
					 | 
				
			||||||
        case MMDB_DATA_TYPE_DOUBLE:
 | 
					 | 
				
			||||||
            *str_off += sprintf(str + *str_off, "%f", list->entry_data.double_value);
 | 
					 | 
				
			||||||
            break;
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
    if (list->entry_data.type != MMDB_DATA_TYPE_MAP && list->entry_data.type != MMDB_DATA_TYPE_ARRAY) {
 | 
					 | 
				
			||||||
        return list->next;
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
    MMDB_entry_data_list_s *next = list->next;
 | 
					 | 
				
			||||||
    int stat = 0;
 | 
					 | 
				
			||||||
    for (int i = 0; i < list->entry_data.data_size; i++) {
 | 
					 | 
				
			||||||
        next = mmdb_json(next, str, str_off, str_len);
 | 
					 | 
				
			||||||
        if (list->entry_data.type == MMDB_DATA_TYPE_MAP) {
 | 
					 | 
				
			||||||
            stat = !stat;
 | 
					 | 
				
			||||||
            if (stat) {
 | 
					 | 
				
			||||||
                i--;
 | 
					 | 
				
			||||||
                *str_off += sprintf(str + *str_off, ":");
 | 
					 | 
				
			||||||
                continue;
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
        if (i != list->entry_data.data_size - 1) *str_off += sprintf(str + *str_off, ",");
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
    if (list->entry_data.type == MMDB_DATA_TYPE_MAP) {
 | 
					 | 
				
			||||||
        *str_off += sprintf(str + *str_off, "}");
 | 
					 | 
				
			||||||
    } else {
 | 
					 | 
				
			||||||
        *str_off += sprintf(str + *str_off, "]");
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
    return next;
 | 
					 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -8,7 +8,15 @@
 | 
				
			|||||||
#ifndef NECRONDA_SERVER_UTILS_H
 | 
					#ifndef NECRONDA_SERVER_UTILS_H
 | 
				
			||||||
#define NECRONDA_SERVER_UTILS_H
 | 
					#define NECRONDA_SERVER_UTILS_H
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#include <maxminddb.h>
 | 
					#include <stdio.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#define ERR_STR "\x1B[1;31m"
 | 
				
			||||||
 | 
					#define CLR_STR "\x1B[0m"
 | 
				
			||||||
 | 
					#define BLD_STR "\x1B[1m"
 | 
				
			||||||
 | 
					#define WRN_STR "\x1B[1;33m"
 | 
				
			||||||
 | 
					#define BLUE_STR "\x1B[34m"
 | 
				
			||||||
 | 
					#define HTTP_STR "\x1B[1;31m"
 | 
				
			||||||
 | 
					#define HTTPS_STR "\x1B[1;32m"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
extern char *log_prefix;
 | 
					extern char *log_prefix;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -24,14 +32,12 @@ extern char *log_prefix;
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
char *format_duration(unsigned long micros, char *buf);
 | 
					char *format_duration(unsigned long micros, char *buf);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
int url_encode_component(const char *str, char *enc, ssize_t *size);
 | 
					int url_encode_component(const char *str, char *enc, long *size);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
int url_encode(const char *str, char *enc, ssize_t *size);
 | 
					int url_encode(const char *str, char *enc, long *size);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
int url_decode(const char *str, char *dec, ssize_t *size);
 | 
					int url_decode(const char *str, char *dec, long *size);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
int mime_is_compressible(const char *type);
 | 
					int mime_is_compressible(const char *type);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
MMDB_entry_data_list_s *mmdb_json(MMDB_entry_data_list_s *list, char *str, long *str_off, long str_len);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#endif //NECRONDA_SERVER_UTILS_H
 | 
					#endif //NECRONDA_SERVER_UTILS_H
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -7,6 +7,7 @@
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
#define _POSIX_C_SOURCE 199309L
 | 
					#define _POSIX_C_SOURCE 199309L
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include "necronda.h"
 | 
				
			||||||
#include "necronda-server.h"
 | 
					#include "necronda-server.h"
 | 
				
			||||||
#include "client.c"
 | 
					#include "client.c"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -14,6 +15,7 @@
 | 
				
			|||||||
#include "lib/config.h"
 | 
					#include "lib/config.h"
 | 
				
			||||||
#include "lib/sock.h"
 | 
					#include "lib/sock.h"
 | 
				
			||||||
#include "lib/rev_proxy.h"
 | 
					#include "lib/rev_proxy.h"
 | 
				
			||||||
 | 
					#include "lib/geoip.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#include <stdio.h>
 | 
					#include <stdio.h>
 | 
				
			||||||
#include <sys/socket.h>
 | 
					#include <sys/socket.h>
 | 
				
			||||||
@@ -29,7 +31,6 @@
 | 
				
			|||||||
#include <openssl/pem.h>
 | 
					#include <openssl/pem.h>
 | 
				
			||||||
#include <openssl/ssl.h>
 | 
					#include <openssl/ssl.h>
 | 
				
			||||||
#include <openssl/conf.h>
 | 
					#include <openssl/conf.h>
 | 
				
			||||||
#include <maxminddb.h>
 | 
					 | 
				
			||||||
#include <dirent.h>
 | 
					#include <dirent.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
int active = 1;
 | 
					int active = 1;
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,20 +1,19 @@
 | 
				
			|||||||
/**
 | 
					/**
 | 
				
			||||||
 * Necronda Web Server
 | 
					 * Necronda Web Server
 | 
				
			||||||
 * Main executable (header file)
 | 
					 * Main executable (header file)
 | 
				
			||||||
 * src/necronda-server.c
 | 
					 * src/necronda-server.h
 | 
				
			||||||
 * Lorenz Stechauner, 2020-12-03
 | 
					 * Lorenz Stechauner, 2020-12-03
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#ifndef NECRONDA_SERVER_NECRONDA_SERVER_H
 | 
					#ifndef NECRONDA_SERVER_NECRONDA_SERVER_H
 | 
				
			||||||
#define NECRONDA_SERVER_NECRONDA_SERVER_H
 | 
					#define NECRONDA_SERVER_NECRONDA_SERVER_H
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#include <sys/types.h>
 | 
					#include <sys/time.h>
 | 
				
			||||||
#include <maxminddb.h>
 | 
					#include <maxminddb.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#define NUM_SOCKETS 2
 | 
					#define NUM_SOCKETS 2
 | 
				
			||||||
#define MAX_CHILDREN 1024
 | 
					#define MAX_CHILDREN 1024
 | 
				
			||||||
#define MAX_MMDB 3
 | 
					#define MAX_MMDB 3
 | 
				
			||||||
#define MAX_HOST_CONFIG 64
 | 
					 | 
				
			||||||
#define LISTEN_BACKLOG 16
 | 
					#define LISTEN_BACKLOG 16
 | 
				
			||||||
#define REQ_PER_CONNECTION 100
 | 
					#define REQ_PER_CONNECTION 100
 | 
				
			||||||
#define CLIENT_TIMEOUT 3600
 | 
					#define CLIENT_TIMEOUT 3600
 | 
				
			||||||
@@ -22,45 +21,18 @@
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
#define CHUNK_SIZE 8192
 | 
					#define CHUNK_SIZE 8192
 | 
				
			||||||
#define CLIENT_MAX_HEADER_SIZE 8192
 | 
					#define CLIENT_MAX_HEADER_SIZE 8192
 | 
				
			||||||
#define FILE_CACHE_SIZE 1024
 | 
					 | 
				
			||||||
#define GEOIP_MAX_SIZE 8192
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#define SHM_KEY_CACHE 255641
 | 
					 | 
				
			||||||
#define SHM_KEY_CONFIG 255642
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#define ERR_STR "\x1B[1;31m"
 | 
					 | 
				
			||||||
#define CLR_STR "\x1B[0m"
 | 
					 | 
				
			||||||
#define BLD_STR "\x1B[1m"
 | 
					 | 
				
			||||||
#define WRN_STR "\x1B[1;33m"
 | 
					 | 
				
			||||||
#define BLUE_STR "\x1B[34m"
 | 
					 | 
				
			||||||
#define HTTP_STR "\x1B[1;31m"
 | 
					 | 
				
			||||||
#define HTTPS_STR "\x1B[1;32m"
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#define HTTP_1XX_STR "\x1B[1;32m"
 | 
					 | 
				
			||||||
#define HTTP_2XX_STR "\x1B[1;32m"
 | 
					 | 
				
			||||||
#define HTTP_3XX_STR "\x1B[1;33m"
 | 
					 | 
				
			||||||
#define HTTP_4XX_STR "\x1B[1;31m"
 | 
					 | 
				
			||||||
#define HTTP_5XX_STR "\x1B[1;31m"
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#define NECRONDA_VERSION "4.3"
 | 
					 | 
				
			||||||
#define SERVER_STR "Necronda/" NECRONDA_VERSION
 | 
					 | 
				
			||||||
#define NECRONDA_ZLIB_LEVEL 9
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
#ifndef DEFAULT_HOST
 | 
					#ifndef DEFAULT_HOST
 | 
				
			||||||
#define DEFAULT_HOST "www.necronda.net"
 | 
					#   define DEFAULT_HOST "www.necronda.net"
 | 
				
			||||||
#endif
 | 
					 | 
				
			||||||
#ifndef MAGIC_FILE
 | 
					 | 
				
			||||||
#define MAGIC_FILE "/usr/share/file/misc/magic.mgc"
 | 
					 | 
				
			||||||
#endif
 | 
					 | 
				
			||||||
#ifndef PHP_FPM_SOCKET
 | 
					 | 
				
			||||||
#define PHP_FPM_SOCKET "/var/run/php-fpm/php-fpm.sock"
 | 
					 | 
				
			||||||
#endif
 | 
					 | 
				
			||||||
#ifndef DEFAULT_CONFIG_FILE
 | 
					 | 
				
			||||||
#define DEFAULT_CONFIG_FILE "/etc/necronda-server/necronda-server.conf"
 | 
					 | 
				
			||||||
#endif
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
extern int sockets[NUM_SOCKETS];
 | 
					extern int sockets[NUM_SOCKETS];
 | 
				
			||||||
extern pid_t children[MAX_CHILDREN];
 | 
					extern pid_t children[MAX_CHILDREN];
 | 
				
			||||||
extern MMDB_s mmdbs[MAX_MMDB];
 | 
					extern MMDB_s mmdbs[MAX_MMDB];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					extern int server_keep_alive;
 | 
				
			||||||
 | 
					extern char *log_client_prefix, *log_conn_prefix, *log_req_prefix, *client_geoip;
 | 
				
			||||||
 | 
					extern char *client_addr_str, *client_addr_str_ptr, *server_addr_str, *server_addr_str_ptr, *client_host_str;
 | 
				
			||||||
 | 
					extern struct timeval client_timeout;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#endif //NECRONDA_SERVER_NECRONDA_SERVER_H
 | 
					#endif //NECRONDA_SERVER_NECRONDA_SERVER_H
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										15
									
								
								src/necronda.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										15
									
								
								src/necronda.h
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,15 @@
 | 
				
			|||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * Necronda Web Server
 | 
				
			||||||
 | 
					 * Definitions
 | 
				
			||||||
 | 
					 * src/necronda.h
 | 
				
			||||||
 | 
					 * Lorenz Stechauner, 2021-05-04
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#ifndef NECRONDA_SERVER_NECRONDA_H
 | 
				
			||||||
 | 
					#define NECRONDA_SERVER_NECRONDA_H
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#define NECRONDA_VERSION "4.3"
 | 
				
			||||||
 | 
					#define SERVER_STR "Necronda/" NECRONDA_VERSION
 | 
				
			||||||
 | 
					#define SERVER_STR_HTML "Necronda web server " NECRONDA_VERSION
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#endif //NECRONDA_SERVER_NECRONDA_H
 | 
				
			||||||
		Reference in New Issue
	
	Block a user