Compare commits
13 Commits
Author | SHA1 | Date | |
---|---|---|---|
bcdf36527f
|
|||
75ef4110c8
|
|||
f1064692a8
|
|||
f0ec64b629
|
|||
0db781e823
|
|||
798c41f1c8
|
|||
bc4a764bd5
|
|||
105e11d31d
|
|||
15530b642a
|
|||
e856f3f091
|
|||
b04c787df4
|
|||
ee7d1e086b
|
|||
cf8862100a
|
2
.gitignore
vendored
2
.gitignore
vendored
@ -4,6 +4,4 @@
|
|||||||
!run.sh
|
!run.sh
|
||||||
!Makefile
|
!Makefile
|
||||||
!.gitignore
|
!.gitignore
|
||||||
!CppNet
|
|
||||||
!CppNet/**
|
|
||||||
!README.md
|
!README.md
|
||||||
|
4
Makefile
4
Makefile
@ -7,11 +7,11 @@ packages:
|
|||||||
|
|
||||||
compile:
|
compile:
|
||||||
@mkdir -p bin
|
@mkdir -p bin
|
||||||
gcc src/necronda-server.c -o bin/necronda-server -std=c11 -lssl -lcrypto -lmagic -lz
|
gcc src/necronda-server.c -o bin/necronda-server -std=c11 -lssl -lcrypto -lmagic -lz -lmaxminddb
|
||||||
|
|
||||||
compile-debian:
|
compile-debian:
|
||||||
@mkdir -p bin
|
@mkdir -p bin
|
||||||
gcc src/necronda-server.c -o bin/necronda-server -std=c11 -lssl -lcrypto -lmagic -lz \
|
gcc src/necronda-server.c -o bin/necronda-server -std=c11 -lssl -lcrypto -lmagic -lz -lmaxminddb \
|
||||||
-D MAGIC_FILE="\"/usr/share/file/magic.mgc\"" \
|
-D MAGIC_FILE="\"/usr/share/file/magic.mgc\"" \
|
||||||
-D PHP_FPM_SOCKET="\"/var/run/php/php7.3-fpm.sock\""
|
-D PHP_FPM_SOCKET="\"/var/run/php/php7.3-fpm.sock\""
|
||||||
|
|
||||||
|
16
src/cache.c
16
src/cache.c
@ -13,12 +13,10 @@ int magic_init() {
|
|||||||
magic = magic_open(MAGIC_MIME);
|
magic = magic_open(MAGIC_MIME);
|
||||||
if (magic == NULL) {
|
if (magic == NULL) {
|
||||||
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));
|
||||||
fflush(stderr);
|
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
if (magic_load(magic, MAGIC_FILE) != 0) {
|
if (magic_load(magic, 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));
|
||||||
fflush(stderr);
|
|
||||||
return -2;
|
return -2;
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
@ -35,7 +33,6 @@ int cache_process() {
|
|||||||
int shm_id = shmget(SHM_KEY, FILE_CACHE_SIZE * sizeof(cache_entry), 0);
|
int shm_id = shmget(SHM_KEY, FILE_CACHE_SIZE * 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));
|
||||||
fflush(stderr);
|
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -43,7 +40,6 @@ int cache_process() {
|
|||||||
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) {
|
||||||
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));
|
||||||
fflush(stderr);
|
|
||||||
return -2;
|
return -2;
|
||||||
}
|
}
|
||||||
cache = shm_rw;
|
cache = shm_rw;
|
||||||
@ -51,7 +47,6 @@ int cache_process() {
|
|||||||
if (mkdir("/var/necronda-server/", 0755) < 0) {
|
if (mkdir("/var/necronda-server/", 0755) < 0) {
|
||||||
if (errno != EEXIST) {
|
if (errno != EEXIST) {
|
||||||
fprintf(stderr, ERR_STR "Unable to create directory '/var/necronda-server/': %s" CLR_STR "\n", strerror(errno));
|
fprintf(stderr, ERR_STR "Unable to create directory '/var/necronda-server/': %s" CLR_STR "\n", strerror(errno));
|
||||||
fflush(stderr);
|
|
||||||
return -3;
|
return -3;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -106,14 +101,12 @@ int cache_process() {
|
|||||||
if (comp_file == NULL) {
|
if (comp_file == NULL) {
|
||||||
compress = 0;
|
compress = 0;
|
||||||
fprintf(stderr, ERR_STR "Unable to open cache file: %s" CLR_STR "\n", strerror(errno));
|
fprintf(stderr, ERR_STR "Unable to open cache file: %s" CLR_STR "\n", strerror(errno));
|
||||||
fflush(stderr);
|
|
||||||
} else {
|
} else {
|
||||||
strm.zalloc = Z_NULL;
|
strm.zalloc = Z_NULL;
|
||||||
strm.zfree = Z_NULL;
|
strm.zfree = Z_NULL;
|
||||||
strm.opaque = Z_NULL;
|
strm.opaque = Z_NULL;
|
||||||
if (deflateInit(&strm, level) != Z_OK) {
|
if (deflateInit(&strm, level) != Z_OK) {
|
||||||
fprintf(stderr, ERR_STR "Unable to init deflate: %s" CLR_STR "\n", strerror(errno));
|
fprintf(stderr, ERR_STR "Unable to init deflate: %s" CLR_STR "\n", strerror(errno));
|
||||||
fflush(stderr);
|
|
||||||
compress = 0;
|
compress = 0;
|
||||||
fclose(comp_file);
|
fclose(comp_file);
|
||||||
}
|
}
|
||||||
@ -168,14 +161,12 @@ int cache_init() {
|
|||||||
int shm_id = shmget(SHM_KEY, FILE_CACHE_SIZE * sizeof(cache_entry), IPC_CREAT | IPC_EXCL | 0600);
|
int shm_id = shmget(SHM_KEY, FILE_CACHE_SIZE * 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));
|
||||||
fflush(stderr);
|
|
||||||
return -2;
|
return -2;
|
||||||
}
|
}
|
||||||
|
|
||||||
void *shm = shmat(shm_id, NULL, SHM_RDONLY);
|
void *shm = shmat(shm_id, NULL, SHM_RDONLY);
|
||||||
if (shm == (void *) -1) {
|
if (shm == (void *) -1) {
|
||||||
fprintf(stderr, ERR_STR "Unable to attach shared memory (ro): %s" CLR_STR "\n", strerror(errno));
|
fprintf(stderr, ERR_STR "Unable to attach shared memory (ro): %s" CLR_STR "\n", strerror(errno));
|
||||||
fflush(stderr);
|
|
||||||
return -3;
|
return -3;
|
||||||
}
|
}
|
||||||
cache = shm;
|
cache = shm;
|
||||||
@ -183,7 +174,6 @@ int cache_init() {
|
|||||||
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) {
|
||||||
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));
|
||||||
fflush(stderr);
|
|
||||||
return -4;
|
return -4;
|
||||||
}
|
}
|
||||||
cache = shm_rw;
|
cache = shm_rw;
|
||||||
@ -202,11 +192,9 @@ int cache_init() {
|
|||||||
} else if (pid > 0) {
|
} else if (pid > 0) {
|
||||||
// parent
|
// parent
|
||||||
fprintf(stderr, "Started child process with PID %i as cache-updater\n", pid);
|
fprintf(stderr, "Started child process with PID %i as cache-updater\n", pid);
|
||||||
fflush(stderr);
|
|
||||||
children[0] = pid;
|
children[0] = pid;
|
||||||
} else {
|
} else {
|
||||||
fprintf(stderr, ERR_STR "Unable to create child process: %s" CLR_STR "\n", strerror(errno));
|
fprintf(stderr, ERR_STR "Unable to create child process: %s" CLR_STR "\n", strerror(errno));
|
||||||
fflush(stderr);
|
|
||||||
return -5;
|
return -5;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -217,10 +205,8 @@ int cache_unload() {
|
|||||||
int shm_id = shmget(SHM_KEY, 0, 0);
|
int shm_id = shmget(SHM_KEY, 0, 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));
|
||||||
fflush(stderr);
|
|
||||||
} else if (shmctl(shm_id, IPC_RMID, NULL) < 0) {
|
} else if (shmctl(shm_id, IPC_RMID, NULL) < 0) {
|
||||||
fprintf(stderr, ERR_STR "Unable to configure shared memory: %s" CLR_STR "\n", strerror(errno));
|
fprintf(stderr, ERR_STR "Unable to configure shared memory: %s" CLR_STR "\n", strerror(errno));
|
||||||
fflush(stderr);
|
|
||||||
}
|
}
|
||||||
shmdt(cache);
|
shmdt(cache);
|
||||||
return 0;
|
return 0;
|
||||||
@ -248,7 +234,7 @@ int cache_update_entry(int entry_num, const char *filename, const char *webroot)
|
|||||||
char type_new[24];
|
char type_new[24];
|
||||||
sprintf(type_new, "%s", type);
|
sprintf(type_new, "%s", type);
|
||||||
if (strcmp(type, "text/plain") == 0) {
|
if (strcmp(type, "text/plain") == 0) {
|
||||||
if (strncmp(filename + strlen(filename) - 4, ".css", 4) == 0) {
|
if (strcmp(filename + strlen(filename) - 4, ".css") == 0) {
|
||||||
sprintf(type_new, "text/css");
|
sprintf(type_new, "text/css");
|
||||||
} else if (strcmp(filename + strlen(filename) - 3, ".js") == 0) {
|
} else if (strcmp(filename + strlen(filename) - 3, ".js") == 0) {
|
||||||
sprintf(type_new, "text/javascript");
|
sprintf(type_new, "text/javascript");
|
||||||
|
125
src/client.c
125
src/client.c
@ -15,7 +15,7 @@
|
|||||||
int server_keep_alive = 1;
|
int server_keep_alive = 1;
|
||||||
char *client_addr_str, *client_addr_str_ptr, *server_addr_str, *server_addr_str_ptr,
|
char *client_addr_str, *client_addr_str_ptr, *server_addr_str, *server_addr_str_ptr,
|
||||||
*log_client_prefix, *log_conn_prefix, *log_req_prefix,
|
*log_client_prefix, *log_conn_prefix, *log_req_prefix,
|
||||||
*client_host_str;
|
*client_host_str, *client_geoip;
|
||||||
|
|
||||||
struct timeval client_timeout = {.tv_sec = CLIENT_TIMEOUT, .tv_usec = 0};
|
struct timeval client_timeout = {.tv_sec = CLIENT_TIMEOUT, .tv_usec = 0};
|
||||||
|
|
||||||
@ -25,7 +25,7 @@ char *get_webroot(const char *http_host) {
|
|||||||
while (webroot_base[len - 1] == '/') len--;
|
while (webroot_base[len - 1] == '/') len--;
|
||||||
long pos = strchr(http_host, ':') - http_host;
|
long pos = strchr(http_host, ':') - http_host;
|
||||||
sprintf(webroot, "%.*s/%.*s", (int) len, webroot_base, (int) (pos < 0 ? strlen(http_host) : pos), http_host);
|
sprintf(webroot, "%.*s/%.*s", (int) len, webroot_base, (int) (pos < 0 ? strlen(http_host) : pos), http_host);
|
||||||
return webroot;
|
return path_is_directory(webroot) ? webroot : NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
void client_terminate() {
|
void client_terminate() {
|
||||||
@ -99,7 +99,7 @@ int client_request_handler(sock *client, unsigned long client_num, unsigned int
|
|||||||
}
|
}
|
||||||
|
|
||||||
hdr_connection = http_get_header_field(&req.hdr, "Connection");
|
hdr_connection = http_get_header_field(&req.hdr, "Connection");
|
||||||
client_keep_alive = hdr_connection != NULL && strncmp(hdr_connection, "keep-alive", 10) == 0;
|
client_keep_alive = hdr_connection != NULL && strcmp(hdr_connection, "keep-alive") == 0;
|
||||||
host = http_get_header_field(&req.hdr, "Host");
|
host = http_get_header_field(&req.hdr, "Host");
|
||||||
if (host == NULL || strchr(host, '/') != NULL) {
|
if (host == NULL || strchr(host, '/') != NULL) {
|
||||||
res.status = http_get_status(400);
|
res.status = http_get_status(400);
|
||||||
@ -111,15 +111,16 @@ int client_request_handler(sock *client, unsigned long client_num, unsigned int
|
|||||||
log_prefix = log_req_prefix;
|
log_prefix = log_req_prefix;
|
||||||
print(BLD_STR "%s %s" CLR_STR, req.method, req.uri);
|
print(BLD_STR "%s %s" CLR_STR, req.method, req.uri);
|
||||||
|
|
||||||
|
// TODO Reverse Proxy
|
||||||
webroot = get_webroot(host);
|
webroot = get_webroot(host);
|
||||||
if (webroot == NULL) {
|
if (webroot == NULL) {
|
||||||
res.status = http_get_status(307);
|
res.status = http_get_status(307);
|
||||||
sprintf(buf0, "https://%s%s", NECRONDA_DEFAULT, req.uri);
|
sprintf(buf0, "https://%s%s", DEFAULT_HOST, req.uri);
|
||||||
http_add_header_field(&req.hdr, "Location", buf0);
|
http_add_header_field(&res.hdr, "Location", buf0);
|
||||||
goto respond;
|
goto respond;
|
||||||
}
|
}
|
||||||
|
|
||||||
dir_mode = URI_DIR_MODE_FORBIDDEN;
|
dir_mode = URI_DIR_MODE_INFO;
|
||||||
http_uri uri;
|
http_uri uri;
|
||||||
ret = uri_init(&uri, webroot, req.uri, dir_mode);
|
ret = uri_init(&uri, webroot, req.uri, dir_mode);
|
||||||
if (ret != 0) {
|
if (ret != 0) {
|
||||||
@ -166,7 +167,7 @@ int client_request_handler(sock *client, unsigned long client_num, unsigned int
|
|||||||
res.status = http_get_status(200);
|
res.status = http_get_status(200);
|
||||||
http_add_header_field(&res.hdr, "Allow", "GET, HEAD");
|
http_add_header_field(&res.hdr, "Allow", "GET, HEAD");
|
||||||
http_add_header_field(&res.hdr, "Accept-Ranges", "bytes");
|
http_add_header_field(&res.hdr, "Accept-Ranges", "bytes");
|
||||||
if (strncmp(req.method, "GET", 3) != 0 && strncmp(req.method, "HEAD", 4) != 0) {
|
if (strcmp(req.method, "GET") != 0 && strcmp(req.method, "HEAD") != 0) {
|
||||||
res.status = http_get_status(405);
|
res.status = http_get_status(405);
|
||||||
goto respond;
|
goto respond;
|
||||||
}
|
}
|
||||||
@ -193,7 +194,7 @@ int client_request_handler(sock *client, unsigned long client_num, unsigned int
|
|||||||
char *if_modified_since = http_get_header_field(&req.hdr, "If-Modified-Since");
|
char *if_modified_since = http_get_header_field(&req.hdr, "If-Modified-Since");
|
||||||
char *if_none_match = http_get_header_field(&req.hdr, "If-None-Match");
|
char *if_none_match = http_get_header_field(&req.hdr, "If-None-Match");
|
||||||
if ((if_none_match != NULL && strstr(if_none_match, uri.meta->etag) == NULL) || (accept_if_modified_since &&
|
if ((if_none_match != NULL && strstr(if_none_match, uri.meta->etag) == NULL) || (accept_if_modified_since &&
|
||||||
if_modified_since != NULL && strncmp(if_modified_since, last_modified, strlen(last_modified)) == 0)) {
|
if_modified_since != NULL && strcmp(if_modified_since, last_modified) == 0)) {
|
||||||
res.status = http_get_status(304);
|
res.status = http_get_status(304);
|
||||||
goto respond;
|
goto respond;
|
||||||
}
|
}
|
||||||
@ -270,7 +271,7 @@ int client_request_handler(sock *client, unsigned long client_num, unsigned int
|
|||||||
goto respond;
|
goto respond;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (strncmp(req.method, "POST", 4) == 0 || strncmp(req.method, "PUT", 3) == 0) {
|
if (strcmp(req.method, "POST") == 0 || strcmp(req.method, "PUT") == 0) {
|
||||||
char *client_content_length = http_get_header_field(&req.hdr, "Content-Length");
|
char *client_content_length = http_get_header_field(&req.hdr, "Content-Length");
|
||||||
unsigned long client_content_len = 0;
|
unsigned long client_content_len = 0;
|
||||||
if (client_content_length == NULL) {
|
if (client_content_length == NULL) {
|
||||||
@ -295,10 +296,7 @@ int client_request_handler(sock *client, unsigned long client_num, unsigned int
|
|||||||
if (ret != 0) {
|
if (ret != 0) {
|
||||||
if (ret < 0) {
|
if (ret < 0) {
|
||||||
goto abort;
|
goto abort;
|
||||||
} else {
|
|
||||||
sprintf(err_msg, "Unable to communicate with PHP-FPM.");
|
|
||||||
}
|
}
|
||||||
res.status = http_get_status(502);
|
|
||||||
goto respond;
|
goto respond;
|
||||||
}
|
}
|
||||||
char *status = http_get_header_field(&res.hdr, "Status");
|
char *status = http_get_header_field(&res.hdr, "Status");
|
||||||
@ -359,7 +357,7 @@ int client_request_handler(sock *client, unsigned long client_num, unsigned int
|
|||||||
print("%s%03i %s%s%s (%s)%s", http_get_status_color(res.status), res.status->code, res.status->msg,
|
print("%s%03i %s%s%s (%s)%s", http_get_status_color(res.status), res.status->code, res.status->msg,
|
||||||
location != NULL ? " -> " : "", location != NULL ? location : "", format_duration(micros, buf0), CLR_STR);
|
location != NULL ? " -> " : "", location != NULL ? location : "", format_duration(micros, buf0), CLR_STR);
|
||||||
|
|
||||||
if (strncmp(req.method, "HEAD", 4) != 0) {
|
if (strcmp(req.method, "HEAD") != 0) {
|
||||||
unsigned long snd_len = 0;
|
unsigned long snd_len = 0;
|
||||||
unsigned long len = 0;
|
unsigned long len = 0;
|
||||||
if (msg_buf[0] != 0) {
|
if (msg_buf[0] != 0) {
|
||||||
@ -404,9 +402,9 @@ int client_request_handler(sock *client, unsigned long client_num, unsigned int
|
|||||||
}
|
}
|
||||||
} else if (use_fastcgi) {
|
} else if (use_fastcgi) {
|
||||||
char *transfer_encoding = http_get_header_field(&res.hdr, "Transfer-Encoding");
|
char *transfer_encoding = http_get_header_field(&res.hdr, "Transfer-Encoding");
|
||||||
int chunked = transfer_encoding != NULL && strncmp(transfer_encoding, "chunked", 7) == 0;
|
int chunked = transfer_encoding != NULL && strcmp(transfer_encoding, "chunked") == 0;
|
||||||
char *content_encoding = http_get_header_field(&res.hdr, "Content-Encoding");
|
char *content_encoding = http_get_header_field(&res.hdr, "Content-Encoding");
|
||||||
int comp = content_encoding != NULL && strncmp(content_encoding, "deflate", 7) == 0;
|
int comp = content_encoding != NULL && strcmp(content_encoding, "deflate") == 0;
|
||||||
int flags = (chunked ? FASTCGI_CHUNKED : 0) | (comp ? FASTCGI_COMPRESS : 0);
|
int flags = (chunked ? FASTCGI_CHUNKED : 0) | (comp ? FASTCGI_COMPRESS : 0);
|
||||||
fastcgi_send(&php_fpm, client, flags);
|
fastcgi_send(&php_fpm, client, flags);
|
||||||
}
|
}
|
||||||
@ -421,21 +419,99 @@ int client_request_handler(sock *client, unsigned long client_num, unsigned int
|
|||||||
if (php_fpm.socket != 0) close(php_fpm.socket);
|
if (php_fpm.socket != 0) close(php_fpm.socket);
|
||||||
http_free_req(&req);
|
http_free_req(&req);
|
||||||
http_free_res(&res);
|
http_free_res(&res);
|
||||||
|
if (client->buf != NULL) {
|
||||||
|
free(client->buf);
|
||||||
|
client->buf = NULL;
|
||||||
|
client->buf_off = 0;
|
||||||
|
client->buf_len = 0;
|
||||||
|
}
|
||||||
return !client_keep_alive;
|
return !client_keep_alive;
|
||||||
}
|
}
|
||||||
|
|
||||||
int client_connection_handler(sock *client, unsigned long client_num) {
|
int client_connection_handler(sock *client, unsigned long client_num) {
|
||||||
struct timespec begin, end;
|
struct timespec begin, end;
|
||||||
int ret, req_num;
|
int ret, req_num;
|
||||||
char buf[16];
|
char buf[1024];
|
||||||
|
|
||||||
clock_gettime(CLOCK_MONOTONIC, &begin);
|
clock_gettime(CLOCK_MONOTONIC, &begin);
|
||||||
|
|
||||||
// TODO get geoip data for ip address
|
if (dns_server != NULL) {
|
||||||
// TODO Reverse DNS request
|
sprintf(buf, "dig @%s +short +time=1 -x %s", dns_server, client_addr_str);
|
||||||
client_host_str = client_addr_str;
|
FILE *dig = popen(buf, "r");
|
||||||
|
if (dig == NULL) {
|
||||||
|
fprintf(stderr, ERR_STR "Unable to start dig: %s" CLR_STR "\n", strerror(errno));
|
||||||
|
goto dig_err;
|
||||||
|
}
|
||||||
|
unsigned long read = fread(buf, 1, sizeof(buf), dig);
|
||||||
|
ret = pclose(dig);
|
||||||
|
if (ret != 0) {
|
||||||
|
fprintf(stderr, ERR_STR "Dig terminated with exit code %i" CLR_STR "\n", ret);
|
||||||
|
goto dig_err;
|
||||||
|
}
|
||||||
|
char *ptr = memchr(buf, '\n', read);
|
||||||
|
if (ptr == buf || ptr == NULL) {
|
||||||
|
goto dig_err;
|
||||||
|
}
|
||||||
|
ptr[-1] = 0;
|
||||||
|
client_host_str = malloc(strlen(buf) + 1);
|
||||||
|
strcpy(client_host_str, buf);
|
||||||
|
} else {
|
||||||
|
dig_err:
|
||||||
|
client_host_str = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
print("Connection accepted from %s (%s) [%s]", client_addr_str, client_host_str, "N/A");
|
client_geoip = malloc(GEOIP_MAX_SIZE);
|
||||||
|
long str_off = 0;
|
||||||
|
for (int i = 0; i < MAX_MMDB && mmdbs[i].filename != NULL; i++) {
|
||||||
|
int gai_error, mmdb_res;
|
||||||
|
MMDB_lookup_result_s result = MMDB_lookup_string(&mmdbs[i], client_addr_str, &gai_error, &mmdb_res);
|
||||||
|
if (mmdb_res != MMDB_SUCCESS) {
|
||||||
|
print(ERR_STR "Unable to lookup geoip info: %s" CLR_STR "\n", MMDB_strerror(mmdb_res));
|
||||||
|
continue;
|
||||||
|
} else if (gai_error != 0) {
|
||||||
|
print(ERR_STR "Unable to lookup geoip info" CLR_STR "\n");
|
||||||
|
continue;
|
||||||
|
} else if (!result.found_entry) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
MMDB_entry_data_list_s *list;
|
||||||
|
mmdb_res = MMDB_get_entry_data_list(&result.entry, &list);
|
||||||
|
if (mmdb_res != MMDB_SUCCESS) {
|
||||||
|
print(ERR_STR "Unable to lookup geoip info: %s" CLR_STR "\n", MMDB_strerror(mmdb_res));
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
long prev = str_off;
|
||||||
|
if (str_off != 0) {
|
||||||
|
str_off--;
|
||||||
|
}
|
||||||
|
mmdb_json(list, client_geoip, &str_off, GEOIP_MAX_SIZE);
|
||||||
|
if (prev != 0) {
|
||||||
|
client_geoip[prev - 1] = ',';
|
||||||
|
}
|
||||||
|
|
||||||
|
MMDB_free_entry_data_list(list);
|
||||||
|
}
|
||||||
|
|
||||||
|
char client_cc[3];
|
||||||
|
client_cc[0] = 0;
|
||||||
|
if (str_off == 0) {
|
||||||
|
free(client_geoip);
|
||||||
|
client_geoip = NULL;
|
||||||
|
} else {
|
||||||
|
char *pos = client_geoip;
|
||||||
|
pos = strstr(pos, "\"country\":");
|
||||||
|
if (pos != NULL) {
|
||||||
|
pos = strstr(pos, "\"iso_code\":");
|
||||||
|
pos += 12;
|
||||||
|
strncpy(client_cc, pos, 2);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
print("Connection accepted from %s %s%s%s[%s]", client_addr_str, client_host_str != NULL ? "(" : "",
|
||||||
|
client_host_str != NULL ? client_host_str : "", client_host_str != NULL ? ") " : "",
|
||||||
|
client_cc[0] != 0 ? client_cc : "N/A");
|
||||||
|
|
||||||
client_timeout.tv_sec = CLIENT_TIMEOUT;
|
client_timeout.tv_sec = CLIENT_TIMEOUT;
|
||||||
client_timeout.tv_usec = 0;
|
client_timeout.tv_usec = 0;
|
||||||
@ -524,9 +600,18 @@ int client_handler(sock *client, unsigned long client_num, struct sockaddr_in6 *
|
|||||||
|
|
||||||
ret = client_connection_handler(client, client_num);
|
ret = client_connection_handler(client, client_num);
|
||||||
free(client_addr_str_ptr);
|
free(client_addr_str_ptr);
|
||||||
|
client_addr_str_ptr = NULL;
|
||||||
free(server_addr_str_ptr);
|
free(server_addr_str_ptr);
|
||||||
|
server_addr_str_ptr = NULL;
|
||||||
|
if (client_host_str != NULL) {
|
||||||
|
free(client_host_str);
|
||||||
|
client_host_str = NULL;
|
||||||
|
}
|
||||||
free(log_conn_prefix);
|
free(log_conn_prefix);
|
||||||
|
log_conn_prefix = NULL;
|
||||||
free(log_req_prefix);
|
free(log_req_prefix);
|
||||||
|
log_req_prefix = NULL;
|
||||||
free(log_client_prefix);
|
free(log_client_prefix);
|
||||||
|
log_client_prefix = NULL;
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
@ -118,17 +118,8 @@ int fastcgi_init(fastcgi_conn *conn, unsigned int client_num, unsigned int req_n
|
|||||||
addr = (struct sockaddr_in6 *) &addr_storage;
|
addr = (struct sockaddr_in6 *) &addr_storage;
|
||||||
sprintf(buf0, "%i", addr->sin6_port);
|
sprintf(buf0, "%i", addr->sin6_port);
|
||||||
param_ptr = fastcgi_add_param(param_ptr, "REMOTE_PORT", buf0);
|
param_ptr = fastcgi_add_param(param_ptr, "REMOTE_PORT", buf0);
|
||||||
|
param_ptr = fastcgi_add_param(param_ptr, "REMOTE_ADDR", client_addr_str);
|
||||||
char addr_str[INET6_ADDRSTRLEN];
|
param_ptr = fastcgi_add_param(param_ptr, "REMOTE_HOST", client_host_str != NULL ? client_host_str : client_addr_str);
|
||||||
char *addr_ptr;
|
|
||||||
inet_ntop(addr->sin6_family, (void *) &addr->sin6_addr, addr_str, INET6_ADDRSTRLEN);
|
|
||||||
if (strncmp(addr_str, "::ffff:", 7) == 0) {
|
|
||||||
addr_ptr = addr_str + 7;
|
|
||||||
} else {
|
|
||||||
addr_ptr = addr_str;
|
|
||||||
}
|
|
||||||
param_ptr = fastcgi_add_param(param_ptr, "REMOTE_ADDR", addr_ptr);
|
|
||||||
param_ptr = fastcgi_add_param(param_ptr, "REMOTE_HOST", addr_ptr);
|
|
||||||
//param_ptr = fastcgi_add_param(param_ptr, "REMOTE_IDENT", "");
|
//param_ptr = fastcgi_add_param(param_ptr, "REMOTE_IDENT", "");
|
||||||
//param_ptr = fastcgi_add_param(param_ptr, "REMOTE_USER", "");
|
//param_ptr = fastcgi_add_param(param_ptr, "REMOTE_USER", "");
|
||||||
|
|
||||||
@ -151,6 +142,9 @@ int fastcgi_init(fastcgi_conn *conn, unsigned int client_num, unsigned int req_n
|
|||||||
param_ptr = fastcgi_add_param(param_ptr, "CONTENT_LENGTH", content_length != NULL ? content_length : "");
|
param_ptr = fastcgi_add_param(param_ptr, "CONTENT_LENGTH", content_length != NULL ? content_length : "");
|
||||||
char *content_type = http_get_header_field(&req->hdr, "Content-Type");
|
char *content_type = http_get_header_field(&req->hdr, "Content-Type");
|
||||||
param_ptr = fastcgi_add_param(param_ptr, "CONTENT_TYPE", content_type != NULL ? content_type : "");
|
param_ptr = fastcgi_add_param(param_ptr, "CONTENT_TYPE", content_type != NULL ? content_type : "");
|
||||||
|
if (client_geoip != NULL) {
|
||||||
|
param_ptr = fastcgi_add_param(param_ptr, "REMOTE_INFO", client_geoip);
|
||||||
|
}
|
||||||
|
|
||||||
for (int i = 0; i < req->hdr.field_num; i++) {
|
for (int i = 0; i < req->hdr.field_num; i++) {
|
||||||
char *ptr = buf0;
|
char *ptr = buf0;
|
||||||
@ -287,12 +281,12 @@ int fastcgi_header(fastcgi_conn *conn, http_res *res, char *err_msg) {
|
|||||||
res->status = http_get_status(502);
|
res->status = http_get_status(502);
|
||||||
sprintf(err_msg, "Unable to communicate with PHP-FPM.");
|
sprintf(err_msg, "Unable to communicate with PHP-FPM.");
|
||||||
print(ERR_STR "Unable to receive from PHP-FPM: %s" CLR_STR, strerror(errno));
|
print(ERR_STR "Unable to receive from PHP-FPM: %s" CLR_STR, strerror(errno));
|
||||||
return -1;
|
return 1;
|
||||||
} else if (ret != sizeof(header)) {
|
} else if (ret != sizeof(header)) {
|
||||||
res->status = http_get_status(502);
|
res->status = http_get_status(502);
|
||||||
sprintf(err_msg, "Unable to communicate with PHP-FPM.");
|
sprintf(err_msg, "Unable to communicate with PHP-FPM.");
|
||||||
print(ERR_STR "Unable to receive from PHP-FPM" CLR_STR);
|
print(ERR_STR "Unable to receive from PHP-FPM" CLR_STR);
|
||||||
return -1;
|
return 1;
|
||||||
}
|
}
|
||||||
req_id = (header.requestIdB1 << 8) | header.requestIdB0;
|
req_id = (header.requestIdB1 << 8) | header.requestIdB0;
|
||||||
content_len = (header.contentLengthB1 << 8) | header.contentLengthB0;
|
content_len = (header.contentLengthB1 << 8) | header.contentLengthB0;
|
||||||
@ -303,13 +297,13 @@ int fastcgi_header(fastcgi_conn *conn, http_res *res, char *err_msg) {
|
|||||||
sprintf(err_msg, "Unable to communicate with PHP-FPM.");
|
sprintf(err_msg, "Unable to communicate with PHP-FPM.");
|
||||||
print(ERR_STR "Unable to receive from PHP-FPM: %s" CLR_STR, strerror(errno));
|
print(ERR_STR "Unable to receive from PHP-FPM: %s" CLR_STR, strerror(errno));
|
||||||
free(content);
|
free(content);
|
||||||
return -1;
|
return 1;
|
||||||
} else if (ret != (content_len + header.paddingLength)) {
|
} else if (ret != (content_len + header.paddingLength)) {
|
||||||
res->status = http_get_status(502);
|
res->status = http_get_status(502);
|
||||||
sprintf(err_msg, "Unable to communicate with PHP-FPM.");
|
sprintf(err_msg, "Unable to communicate with PHP-FPM.");
|
||||||
print(ERR_STR "Unable to receive from PHP-FPM" CLR_STR);
|
print(ERR_STR "Unable to receive from PHP-FPM" CLR_STR);
|
||||||
free(content);
|
free(content);
|
||||||
return -1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (req_id != conn->req_id) {
|
if (req_id != conn->req_id) {
|
||||||
@ -329,7 +323,7 @@ int fastcgi_header(fastcgi_conn *conn, http_res *res, char *err_msg) {
|
|||||||
close(conn->socket);
|
close(conn->socket);
|
||||||
conn->socket = 0;
|
conn->socket = 0;
|
||||||
free(content);
|
free(content);
|
||||||
return -2;
|
return 1;
|
||||||
} else if (header.type == FCGI_STDERR) {
|
} else if (header.type == FCGI_STDERR) {
|
||||||
err = err || fastcgi_php_error(content, content_len, err_msg);
|
err = err || fastcgi_php_error(content, content_len, err_msg);
|
||||||
} else if (header.type == FCGI_STDOUT) {
|
} else if (header.type == FCGI_STDOUT) {
|
||||||
@ -342,7 +336,7 @@ int fastcgi_header(fastcgi_conn *conn, http_res *res, char *err_msg) {
|
|||||||
}
|
}
|
||||||
if (err) {
|
if (err) {
|
||||||
res->status = http_get_status(500);
|
res->status = http_get_status(500);
|
||||||
return -3;
|
return 2;
|
||||||
}
|
}
|
||||||
|
|
||||||
conn->out_buf = content;
|
conn->out_buf = content;
|
||||||
@ -519,6 +513,13 @@ int fastcgi_receive(fastcgi_conn *conn, sock *client, unsigned long len) {
|
|||||||
.paddingLength = 0,
|
.paddingLength = 0,
|
||||||
.reserved = 0
|
.reserved = 0
|
||||||
};
|
};
|
||||||
|
|
||||||
|
if (client->buf != NULL && client->buf_len - client->buf_off > 0) {
|
||||||
|
ret = (int) (client->buf_len - client->buf_off);
|
||||||
|
memcpy(buf, client->buf + client->buf_off, ret);
|
||||||
|
goto send;
|
||||||
|
}
|
||||||
|
|
||||||
while (rcv_len < len) {
|
while (rcv_len < len) {
|
||||||
if (client->enc) {
|
if (client->enc) {
|
||||||
ret = SSL_read(client->ssl, buf, sizeof(buf));
|
ret = SSL_read(client->ssl, buf, sizeof(buf));
|
||||||
@ -533,6 +534,7 @@ int fastcgi_receive(fastcgi_conn *conn, sock *client, unsigned long len) {
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
send:
|
||||||
rcv_len += ret;
|
rcv_len += ret;
|
||||||
header.contentLengthB1 = (ret >> 8) & 0xFF;
|
header.contentLengthB1 = (ret >> 8) & 0xFF;
|
||||||
header.contentLengthB0 = ret & 0xFF;
|
header.contentLengthB0 = ret & 0xFF;
|
||||||
|
50
src/http.c
50
src/http.c
@ -115,7 +115,7 @@ int http_receive_request(sock *client, http_req *req) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
ptr = buf;
|
ptr = buf;
|
||||||
while (header_len != (ptr - buf)) {
|
while (header_len > (ptr - buf + 2)) {
|
||||||
pos0 = strstr(ptr, "\r\n");
|
pos0 = strstr(ptr, "\r\n");
|
||||||
if (pos0 == NULL) {
|
if (pos0 == NULL) {
|
||||||
print(ERR_STR "Unable to parse header: Invalid header format" CLR_STR);
|
print(ERR_STR "Unable to parse header: Invalid header format" CLR_STR);
|
||||||
@ -123,29 +123,22 @@ int http_receive_request(sock *client, http_req *req) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (req->version[0] == 0) {
|
if (req->version[0] == 0) {
|
||||||
if (memcmp(ptr, "GET ", 4) == 0) {
|
pos1 = memchr(ptr, ' ', rcv_len - (ptr - buf)) + 1;
|
||||||
strcpy(req->method, "GET");
|
if (pos1 == NULL) goto err_hdr_fmt;
|
||||||
} else if (memcmp(ptr, "HEAD ", 5) == 0) {
|
|
||||||
strcpy(req->method, "HEAD");
|
if (pos1 - ptr - 1 >= sizeof(req->method)) {
|
||||||
} else if (memcmp(ptr, "POST ", 5) == 0) {
|
print(ERR_STR "Unable to parse header: Method name too long" CLR_STR);
|
||||||
strcpy(req->method, "POST");
|
|
||||||
} else if (memcmp(ptr, "PUT ", 4) == 0) {
|
|
||||||
strcpy(req->method, "PUT");
|
|
||||||
} else if (memcmp(ptr, "DELETE ", 7) == 0) {
|
|
||||||
strcpy(req->method, "DELETE");
|
|
||||||
} else if (memcmp(ptr, "CONNECT ", 7) == 0) {
|
|
||||||
strcpy(req->method, "CONNECT");
|
|
||||||
} else if (memcmp(ptr, "OPTIONS ", 7) == 0) {
|
|
||||||
strcpy(req->method, "OPTIONS");
|
|
||||||
} else if (memcmp(ptr, "TRACE ", 6) == 0) {
|
|
||||||
strcpy(req->method, "TRACE");
|
|
||||||
} else {
|
|
||||||
print(ERR_STR "Unable to parse header: Invalid method" CLR_STR);
|
|
||||||
return 2;
|
return 2;
|
||||||
}
|
}
|
||||||
|
|
||||||
pos1 = memchr(ptr, ' ', rcv_len - (ptr - buf)) + 1;
|
for (int i = 0; i < (pos1 - ptr - 1); i++) {
|
||||||
if (pos1 == NULL) goto err_hdr_fmt;
|
if (ptr[i] < 'A' || ptr[i] > 'Z') {
|
||||||
|
print(ERR_STR "Unable to parse header: Invalid method" CLR_STR);
|
||||||
|
return 2;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
strncpy(req->method, ptr, pos1 - ptr - 1);
|
||||||
|
|
||||||
pos2 = memchr(pos1, ' ', rcv_len - (pos1 - buf)) + 1;
|
pos2 = memchr(pos1, ' ', rcv_len - (pos1 - buf)) + 1;
|
||||||
if (pos2 == NULL) {
|
if (pos2 == NULL) {
|
||||||
err_hdr_fmt:
|
err_hdr_fmt:
|
||||||
@ -166,12 +159,21 @@ int http_receive_request(sock *client, http_req *req) {
|
|||||||
int ret = http_parse_header_field(&req->hdr, ptr, pos0);
|
int ret = http_parse_header_field(&req->hdr, ptr, pos0);
|
||||||
if (ret != 0) return ret;
|
if (ret != 0) return ret;
|
||||||
}
|
}
|
||||||
if (pos0[2] == '\r' && pos0[3] == '\n') {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
ptr = pos0 + 2;
|
ptr = pos0 + 2;
|
||||||
}
|
}
|
||||||
|
if (pos0[2] == '\r' && pos0[3] == '\n') {
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
client->buf_len = rcv_len - (pos0 - buf + 4);
|
||||||
|
if (client->buf_len > 0) {
|
||||||
|
client->buf = malloc(client->buf_len);
|
||||||
|
client->buf_off = 0;
|
||||||
|
memcpy(client->buf, pos0 + 4, client->buf_len);
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
char *http_get_header_field(const http_hdr *hdr, const char *field_name) {
|
char *http_get_header_field(const http_hdr *hdr, const char *field_name) {
|
||||||
|
@ -32,7 +32,7 @@ typedef struct {
|
|||||||
} http_hdr;
|
} http_hdr;
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
char method[8];
|
char method[16];
|
||||||
char *uri;
|
char *uri;
|
||||||
char version[3];
|
char version[3];
|
||||||
http_hdr hdr;
|
http_hdr hdr;
|
||||||
|
@ -62,7 +62,6 @@ char *ssl_get_error(SSL *ssl, int ret) {
|
|||||||
|
|
||||||
void destroy() {
|
void destroy() {
|
||||||
fprintf(stderr, "\n" ERR_STR "Terminating forcefully!" CLR_STR "\n");
|
fprintf(stderr, "\n" ERR_STR "Terminating forcefully!" CLR_STR "\n");
|
||||||
fflush(stderr);
|
|
||||||
int status = 0;
|
int status = 0;
|
||||||
int ret;
|
int ret;
|
||||||
int kills = 0;
|
int kills = 0;
|
||||||
@ -72,13 +71,11 @@ void destroy() {
|
|||||||
if (ret < 0) {
|
if (ret < 0) {
|
||||||
fprintf(stderr, ERR_STR "Unable to wait for child process (PID %i): %s" CLR_STR "\n",
|
fprintf(stderr, ERR_STR "Unable to wait for child process (PID %i): %s" CLR_STR "\n",
|
||||||
children[i], strerror(errno));
|
children[i], strerror(errno));
|
||||||
fflush(stderr);
|
|
||||||
} else if (ret == children[i]) {
|
} else if (ret == children[i]) {
|
||||||
children[i] = 0;
|
children[i] = 0;
|
||||||
if (status != 0) {
|
if (status != 0) {
|
||||||
fprintf(stderr, ERR_STR "Child process with PID %i terminated with exit code %i" CLR_STR "\n",
|
fprintf(stderr, ERR_STR "Child process with PID %i terminated with exit code %i" CLR_STR "\n",
|
||||||
ret, status);
|
ret, status);
|
||||||
fflush(stderr);
|
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
kill(children[i], SIGKILL);
|
kill(children[i], SIGKILL);
|
||||||
@ -88,7 +85,6 @@ void destroy() {
|
|||||||
}
|
}
|
||||||
if (kills > 0) {
|
if (kills > 0) {
|
||||||
fprintf(stderr, ERR_STR "Killed %i child process(es)" CLR_STR "\n", kills);
|
fprintf(stderr, ERR_STR "Killed %i child process(es)" CLR_STR "\n", kills);
|
||||||
fflush(stderr);
|
|
||||||
}
|
}
|
||||||
cache_unload();
|
cache_unload();
|
||||||
exit(2);
|
exit(2);
|
||||||
@ -96,7 +92,6 @@ void destroy() {
|
|||||||
|
|
||||||
void terminate() {
|
void terminate() {
|
||||||
fprintf(stderr, "\nTerminating gracefully...\n");
|
fprintf(stderr, "\nTerminating gracefully...\n");
|
||||||
fflush(stderr);
|
|
||||||
active = 0;
|
active = 0;
|
||||||
|
|
||||||
signal(SIGINT, destroy);
|
signal(SIGINT, destroy);
|
||||||
@ -116,13 +111,11 @@ void terminate() {
|
|||||||
if (ret < 0) {
|
if (ret < 0) {
|
||||||
fprintf(stderr, ERR_STR "Unable to wait for child process (PID %i): %s" CLR_STR "\n",
|
fprintf(stderr, ERR_STR "Unable to wait for child process (PID %i): %s" CLR_STR "\n",
|
||||||
children[i], strerror(errno));
|
children[i], strerror(errno));
|
||||||
fflush(stderr);
|
|
||||||
} else if (ret == children[i]) {
|
} else if (ret == children[i]) {
|
||||||
children[i] = 0;
|
children[i] = 0;
|
||||||
if (status != 0) {
|
if (status != 0) {
|
||||||
fprintf(stderr, ERR_STR "Child process with PID %i terminated with exit code %i" CLR_STR "\n",
|
fprintf(stderr, ERR_STR "Child process with PID %i terminated with exit code %i" CLR_STR "\n",
|
||||||
ret, status);
|
ret, status);
|
||||||
fflush(stderr);
|
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
kill(children[i], SIGTERM);
|
kill(children[i], SIGTERM);
|
||||||
@ -133,7 +126,6 @@ void terminate() {
|
|||||||
|
|
||||||
if (wait_num > 0) {
|
if (wait_num > 0) {
|
||||||
fprintf(stderr, "Waiting for %i child process(es)...\n", wait_num);
|
fprintf(stderr, "Waiting for %i child process(es)...\n", wait_num);
|
||||||
fflush(stderr);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
for (int i = 0; i < MAX_CHILDREN; i++) {
|
for (int i = 0; i < MAX_CHILDREN; i++) {
|
||||||
@ -142,13 +134,11 @@ void terminate() {
|
|||||||
if (ret < 0) {
|
if (ret < 0) {
|
||||||
fprintf(stderr, ERR_STR "Unable to wait for child process (PID %i): %s" CLR_STR "\n",
|
fprintf(stderr, ERR_STR "Unable to wait for child process (PID %i): %s" CLR_STR "\n",
|
||||||
children[i], strerror(errno));
|
children[i], strerror(errno));
|
||||||
fflush(stderr);
|
|
||||||
} else if (ret == children[i]) {
|
} else if (ret == children[i]) {
|
||||||
children[i] = 0;
|
children[i] = 0;
|
||||||
if (status != 0) {
|
if (status != 0) {
|
||||||
fprintf(stderr, ERR_STR "Child process with PID %i terminated with exit code %i" CLR_STR "\n",
|
fprintf(stderr, ERR_STR "Child process with PID %i terminated with exit code %i" CLR_STR "\n",
|
||||||
ret, status);
|
ret, status);
|
||||||
fflush(stderr);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -161,10 +151,8 @@ void terminate() {
|
|||||||
struct timespec ts = {.tv_sec = 0, .tv_nsec = 50000000};
|
struct timespec ts = {.tv_sec = 0, .tv_nsec = 50000000};
|
||||||
nanosleep(&ts, &ts);
|
nanosleep(&ts, &ts);
|
||||||
fprintf(stderr, "\nGoodbye\n");
|
fprintf(stderr, "\nGoodbye\n");
|
||||||
fflush(stderr);
|
|
||||||
} else {
|
} else {
|
||||||
fprintf(stderr, "Goodbye\n");
|
fprintf(stderr, "Goodbye\n");
|
||||||
fflush(stderr);
|
|
||||||
}
|
}
|
||||||
cache_unload();
|
cache_unload();
|
||||||
exit(0);
|
exit(0);
|
||||||
@ -184,6 +172,10 @@ int main(int argc, const char *argv[]) {
|
|||||||
struct sockaddr_in6 client_addr;
|
struct sockaddr_in6 client_addr;
|
||||||
unsigned int client_addr_len = sizeof(client_addr);
|
unsigned int client_addr_len = sizeof(client_addr);
|
||||||
|
|
||||||
|
memset(sockets, 0, sizeof(sockets));
|
||||||
|
memset(children, 0, sizeof(children));
|
||||||
|
memset(mmdbs, 0, sizeof(mmdbs));
|
||||||
|
|
||||||
struct timeval timeout;
|
struct timeval timeout;
|
||||||
|
|
||||||
const struct sockaddr_in6 addresses[2] = {
|
const struct sockaddr_in6 addresses[2] = {
|
||||||
@ -191,70 +183,72 @@ int main(int argc, const char *argv[]) {
|
|||||||
{.sin6_family = AF_INET6, .sin6_addr = IN6ADDR_ANY_INIT, .sin6_port = htons(443)}
|
{.sin6_family = AF_INET6, .sin6_addr = IN6ADDR_ANY_INIT, .sin6_port = htons(443)}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
if (setvbuf(stdout, NULL, _IONBF, 0) != 0) {
|
||||||
|
fprintf(stderr, ERR_STR "Unable to set stdout to unbuffered mode: %s" CLR_STR, strerror(errno));
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
printf("Necronda Web Server\n");
|
printf("Necronda Web Server\n");
|
||||||
fflush(stdout);
|
|
||||||
|
|
||||||
for (int i = 1; i < argc; i++) {
|
for (int i = 1; i < argc; i++) {
|
||||||
const char *arg = argv[i];
|
const char *arg = argv[i];
|
||||||
unsigned long len = strlen(arg);
|
unsigned long len = strlen(arg);
|
||||||
if ((len == 2 && strncmp(arg, "-h", 2) == 0) || (len == 6 && strncmp(arg, "--help", 6) == 0)) {
|
if (strcmp(arg, "-h") == 0 || strcmp(arg, "--help") == 0) {
|
||||||
printf("Usage: necronda-server [-h] -w <PATH> -c <CERT-FILE> -p <KEY-FILE> [-g <DB-FILE>]\n"
|
printf("Usage: necronda-server [-h] -w <PATH> -c <CERT-FILE> -p <KEY-FILE> [-g <DB-DIR>] [-d <DNS-SERVER>]\n"
|
||||||
"\n"
|
"\n"
|
||||||
"Options:\n"
|
"Options:\n"
|
||||||
" -c, --cert <CERT-FILE> path to the full chain certificate file\n"
|
" -c, --cert <CERT-FILE> path to the full chain certificate file\n"
|
||||||
" -g, --geoip <DB-FILE> path to a Maxmind GeoIP Database file\n"
|
" -d, --dns <DNS-SERVER> ip address or hostname of a DNS server for dig\n"
|
||||||
|
" -g, --geoip <DB-DIR> path to a Maxmind GeoIP Database file\n"
|
||||||
" -h, --help print this dialogue\n"
|
" -h, --help print this dialogue\n"
|
||||||
" -p, --privkey <KEY-FILE> path to the private key file\n"
|
" -p, --privkey <KEY-FILE> path to the private key file\n"
|
||||||
" -w, --webroot <PATH> path to the web root directory\n");
|
" -w, --webroot <PATH> path to the web root directory\n");
|
||||||
return 0;
|
return 0;
|
||||||
} else if ((len == 2 && strncmp(arg, "-w", 2) == 0) || (len == 9 && strncmp(arg, "--webroot", 9) == 0)) {
|
} else if (strcmp(arg, "-w") == 0 || strcmp(arg, "--webroot") == 0) {
|
||||||
if (i == argc - 1) {
|
if (i == argc - 1) {
|
||||||
fprintf(stderr, ERR_STR "Unable to parse argument %s, usage: --webroot <WEBROOT>" CLR_STR "\n", arg);
|
fprintf(stderr, ERR_STR "Unable to parse argument %s, usage: --webroot <WEBROOT>" CLR_STR "\n", arg);
|
||||||
fflush(stderr);
|
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
webroot_base = argv[++i];
|
webroot_base = argv[++i];
|
||||||
} else if ((len == 2 && strncmp(arg, "-c", 2) == 0) || (len == 6 && strncmp(arg, "--cert", 6) == 0)) {
|
} else if (strcmp(arg, "-c") == 0 || strcmp(arg, "--cert") == 0) {
|
||||||
if (i == argc - 1) {
|
if (i == argc - 1) {
|
||||||
fprintf(stderr, ERR_STR "Unable to parse argument %s, usage: --cert <CERT-FILE>" CLR_STR "\n", arg);
|
fprintf(stderr, ERR_STR "Unable to parse argument %s, usage: --cert <CERT-FILE>" CLR_STR "\n", arg);
|
||||||
fflush(stderr);
|
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
cert_file = argv[++i];
|
cert_file = argv[++i];
|
||||||
} else if ((len == 2 && strncmp(arg, "-p", 2) == 0) || (len == 9 && strncmp(arg, "--privkey", 9) == 0)) {
|
} else if (strcmp(arg, "-p") == 0 || strcmp(arg, "--privkey") == 0) {
|
||||||
if (i == argc - 1) {
|
if (i == argc - 1) {
|
||||||
fprintf(stderr, ERR_STR "Unable to parse argument %s, usage: --privkey <KEY-FILE>" CLR_STR "\n", arg);
|
fprintf(stderr, ERR_STR "Unable to parse argument %s, usage: --privkey <KEY-FILE>" CLR_STR "\n", arg);
|
||||||
fflush(stderr);
|
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
key_file = argv[++i];
|
key_file = argv[++i];
|
||||||
} else if ((len == 2 && strncmp(arg, "-g", 2) == 0) || (len == 7 && strncmp(arg, "--geoip", 7) == 0)) {
|
} else if (strcmp(arg, "-g") == 0 || strcmp(arg, "--geoip") == 0) {
|
||||||
if (i == argc - 1) {
|
if (i == argc - 1) {
|
||||||
fprintf(stderr, ERR_STR "Unable to parse argument %s, usage: --geoip <DB-FILE>" CLR_STR "\n", arg);
|
fprintf(stderr, ERR_STR "Unable to parse argument %s, usage: --geoip <DB-DIR>" CLR_STR "\n", arg);
|
||||||
fflush(stderr);
|
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
geoip_file = argv[++i];
|
geoip_dir = argv[++i];
|
||||||
|
} else if (strcmp(arg, "-d") == 0 || strcmp(arg, "--dns") == 0) {
|
||||||
|
if (i == argc - 1) {
|
||||||
|
fprintf(stderr, ERR_STR "Unable to parse argument %s, usage: --dns <DNS-SERVER>" CLR_STR "\n", arg);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
dns_server = argv[++i];
|
||||||
} else {
|
} else {
|
||||||
fprintf(stderr, ERR_STR "Unable to parse argument '%s'" CLR_STR "\n", arg);
|
fprintf(stderr, ERR_STR "Unable to parse argument '%s'" CLR_STR "\n", arg);
|
||||||
fflush(stderr);
|
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (webroot_base == NULL) {
|
if (webroot_base == NULL) {
|
||||||
fprintf(stderr, ERR_STR "Error: --webroot is missing" CLR_STR "\n");
|
fprintf(stderr, ERR_STR "Error: --webroot is missing" CLR_STR "\n");
|
||||||
fflush(stderr);
|
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
if (cert_file == NULL) {
|
if (cert_file == NULL) {
|
||||||
fprintf(stderr, ERR_STR "Error: --cert is missing" CLR_STR "\n");
|
fprintf(stderr, ERR_STR "Error: --cert is missing" CLR_STR "\n");
|
||||||
fflush(stderr);
|
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
if (key_file == NULL) {
|
if (key_file == NULL) {
|
||||||
fprintf(stderr, ERR_STR "Error: --privkey is missing" CLR_STR "\n");
|
fprintf(stderr, ERR_STR "Error: --privkey is missing" CLR_STR "\n");
|
||||||
fflush(stderr);
|
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -264,14 +258,12 @@ int main(int argc, const char *argv[]) {
|
|||||||
if (sockets[1] < 0) {
|
if (sockets[1] < 0) {
|
||||||
socket_err:
|
socket_err:
|
||||||
fprintf(stderr, ERR_STR "Unable to create socket: %s" CLR_STR "\n", strerror(errno));
|
fprintf(stderr, ERR_STR "Unable to create socket: %s" CLR_STR "\n", strerror(errno));
|
||||||
fflush(stderr);
|
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (int i = 0; i < NUM_SOCKETS; i++) {
|
for (int i = 0; i < NUM_SOCKETS; i++) {
|
||||||
if (setsockopt(sockets[i], SOL_SOCKET, SO_REUSEADDR, &YES, sizeof(YES)) < 0) {
|
if (setsockopt(sockets[i], SOL_SOCKET, SO_REUSEADDR, &YES, sizeof(YES)) < 0) {
|
||||||
fprintf(stderr, ERR_STR "Unable to set options for socket %i: %s" CLR_STR "\n", i, strerror(errno));
|
fprintf(stderr, ERR_STR "Unable to set options for socket %i: %s" CLR_STR "\n", i, strerror(errno));
|
||||||
fflush(stderr);
|
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -280,24 +272,46 @@ int main(int argc, const char *argv[]) {
|
|||||||
if (bind(sockets[1], (struct sockaddr *) &addresses[1], sizeof(addresses[1])) < 0) {
|
if (bind(sockets[1], (struct sockaddr *) &addresses[1], sizeof(addresses[1])) < 0) {
|
||||||
bind_err:
|
bind_err:
|
||||||
fprintf(stderr, ERR_STR "Unable to bind socket to address: %s" CLR_STR "\n", strerror(errno));
|
fprintf(stderr, ERR_STR "Unable to bind socket to address: %s" CLR_STR "\n", strerror(errno));
|
||||||
fflush(stderr);
|
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
signal(SIGINT, terminate);
|
signal(SIGINT, terminate);
|
||||||
signal(SIGTERM, terminate);
|
signal(SIGTERM, terminate);
|
||||||
|
|
||||||
ret = cache_init();
|
if (geoip_dir != NULL) {
|
||||||
if (ret < 0) {
|
DIR *geoip = opendir(geoip_dir);
|
||||||
return 1;
|
if (geoip == NULL) {
|
||||||
} else if (ret != 0) {
|
fprintf(stderr, ERR_STR "Unable to open GeoIP dir: %s" CLR_STR "\n", strerror(errno));
|
||||||
return 0;
|
return 1;
|
||||||
|
}
|
||||||
|
struct dirent *dir;
|
||||||
|
int i = 0;
|
||||||
|
while ((dir = readdir(geoip)) != NULL) {
|
||||||
|
if (strcmp(dir->d_name + strlen(dir->d_name) - 5, ".mmdb") != 0) continue;
|
||||||
|
if (i >= MAX_MMDB) {
|
||||||
|
fprintf(stderr, ERR_STR "Too many .mmdb files" CLR_STR "\n");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
sprintf(buf, "%s/%s", geoip_dir, dir->d_name);
|
||||||
|
ret = MMDB_open(buf, 0, &mmdbs[i]);
|
||||||
|
if (ret != MMDB_SUCCESS) {
|
||||||
|
fprintf(stderr, ERR_STR "Unable to open .mmdb file: %s" CLR_STR "\n", MMDB_strerror(ret));
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
if (i == 0) {
|
||||||
|
fprintf(stderr, ERR_STR "No .mmdb files found in %s" CLR_STR "\n", geoip_dir);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
closedir(geoip);
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO init geoip database
|
|
||||||
|
|
||||||
openssl_init();
|
openssl_init();
|
||||||
|
|
||||||
|
client.buf = NULL;
|
||||||
|
client.buf_len = 0;
|
||||||
|
client.buf_off = 0;
|
||||||
client.ctx = SSL_CTX_new(TLS_server_method());
|
client.ctx = SSL_CTX_new(TLS_server_method());
|
||||||
SSL_CTX_set_options(client.ctx, SSL_OP_SINGLE_DH_USE);
|
SSL_CTX_set_options(client.ctx, SSL_OP_SINGLE_DH_USE);
|
||||||
SSL_CTX_set_verify(client.ctx, SSL_VERIFY_NONE, NULL);
|
SSL_CTX_set_verify(client.ctx, SSL_VERIFY_NONE, NULL);
|
||||||
@ -309,20 +323,17 @@ int main(int argc, const char *argv[]) {
|
|||||||
if (SSL_CTX_use_certificate_chain_file(client.ctx, cert_file) != 1) {
|
if (SSL_CTX_use_certificate_chain_file(client.ctx, cert_file) != 1) {
|
||||||
fprintf(stderr, ERR_STR "Unable to load certificate chain file: %s: %s" CLR_STR "\n",
|
fprintf(stderr, ERR_STR "Unable to load certificate chain file: %s: %s" CLR_STR "\n",
|
||||||
ERR_reason_error_string(ERR_get_error()), cert_file);
|
ERR_reason_error_string(ERR_get_error()), cert_file);
|
||||||
fflush(stderr);
|
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
if (SSL_CTX_use_PrivateKey_file(client.ctx, key_file, SSL_FILETYPE_PEM) != 1) {
|
if (SSL_CTX_use_PrivateKey_file(client.ctx, key_file, SSL_FILETYPE_PEM) != 1) {
|
||||||
fprintf(stderr, ERR_STR "Unable to load private key file: %s: %s" CLR_STR "\n",
|
fprintf(stderr, ERR_STR "Unable to load private key file: %s: %s" CLR_STR "\n",
|
||||||
ERR_reason_error_string(ERR_get_error()), key_file);
|
ERR_reason_error_string(ERR_get_error()), key_file);
|
||||||
fflush(stderr);
|
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (int i = 0; i < NUM_SOCKETS; i++) {
|
for (int i = 0; i < NUM_SOCKETS; i++) {
|
||||||
if (listen(sockets[i], LISTEN_BACKLOG) < 0) {
|
if (listen(sockets[i], LISTEN_BACKLOG) < 0) {
|
||||||
fprintf(stderr, ERR_STR "Unable to listen on socket %i: %s" CLR_STR "\n", i, strerror(errno));
|
fprintf(stderr, ERR_STR "Unable to listen on socket %i: %s" CLR_STR "\n", i, strerror(errno));
|
||||||
fflush(stderr);
|
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -335,8 +346,14 @@ int main(int argc, const char *argv[]) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ret = cache_init();
|
||||||
|
if (ret < 0) {
|
||||||
|
return 1;
|
||||||
|
} else if (ret != 0) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
fprintf(stderr, "Ready to accept connections\n");
|
fprintf(stderr, "Ready to accept connections\n");
|
||||||
fflush(stderr);
|
|
||||||
|
|
||||||
while (active) {
|
while (active) {
|
||||||
timeout.tv_sec = 1;
|
timeout.tv_sec = 1;
|
||||||
@ -345,7 +362,6 @@ int main(int argc, const char *argv[]) {
|
|||||||
ready_sockets_num = select(max_socket_fd + 1, &read_socket_fds, NULL, NULL, &timeout);
|
ready_sockets_num = select(max_socket_fd + 1, &read_socket_fds, NULL, NULL, &timeout);
|
||||||
if (ready_sockets_num < 0) {
|
if (ready_sockets_num < 0) {
|
||||||
fprintf(stderr, ERR_STR "Unable to select sockets: %s" CLR_STR "\n", strerror(errno));
|
fprintf(stderr, ERR_STR "Unable to select sockets: %s" CLR_STR "\n", strerror(errno));
|
||||||
fflush(stderr);
|
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -354,7 +370,6 @@ int main(int argc, const char *argv[]) {
|
|||||||
client_fd = accept(sockets[i], (struct sockaddr *) &client_addr, &client_addr_len);
|
client_fd = accept(sockets[i], (struct sockaddr *) &client_addr, &client_addr_len);
|
||||||
if (client_fd < 0) {
|
if (client_fd < 0) {
|
||||||
fprintf(stderr, ERR_STR "Unable to accept connection: %s" CLR_STR "\n", strerror(errno));
|
fprintf(stderr, ERR_STR "Unable to accept connection: %s" CLR_STR "\n", strerror(errno));
|
||||||
fflush(stderr);
|
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -379,7 +394,6 @@ int main(int argc, const char *argv[]) {
|
|||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
fprintf(stderr, ERR_STR "Unable to create child process: %s" CLR_STR "\n", strerror(errno));
|
fprintf(stderr, ERR_STR "Unable to create child process: %s" CLR_STR "\n", strerror(errno));
|
||||||
fflush(stderr);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -391,13 +405,11 @@ int main(int argc, const char *argv[]) {
|
|||||||
if (ret < 0) {
|
if (ret < 0) {
|
||||||
fprintf(stderr, ERR_STR "Unable to wait for child process (PID %i): %s" CLR_STR "\n",
|
fprintf(stderr, ERR_STR "Unable to wait for child process (PID %i): %s" CLR_STR "\n",
|
||||||
children[i], strerror(errno));
|
children[i], strerror(errno));
|
||||||
fflush(stderr);
|
|
||||||
} else if (ret == children[i]) {
|
} else if (ret == children[i]) {
|
||||||
children[i] = 0;
|
children[i] = 0;
|
||||||
if (status != 0) {
|
if (status != 0) {
|
||||||
fprintf(stderr, ERR_STR "Child process with PID %i terminated with exit code %i" CLR_STR "\n",
|
fprintf(stderr, ERR_STR "Child process with PID %i terminated with exit code %i" CLR_STR "\n",
|
||||||
ret, status);
|
ret, status);
|
||||||
fflush(stderr);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -25,10 +25,13 @@
|
|||||||
#include <openssl/conf.h>
|
#include <openssl/conf.h>
|
||||||
#include <openssl/engine.h>
|
#include <openssl/engine.h>
|
||||||
#include <openssl/dh.h>
|
#include <openssl/dh.h>
|
||||||
|
#include <maxminddb.h>
|
||||||
|
#include <dirent.h>
|
||||||
|
|
||||||
|
|
||||||
#define NUM_SOCKETS 2
|
#define NUM_SOCKETS 2
|
||||||
#define MAX_CHILDREN 1024
|
#define MAX_CHILDREN 1024
|
||||||
|
#define MAX_MMDB 3
|
||||||
#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
|
||||||
@ -37,6 +40,7 @@
|
|||||||
#define CLIENT_MAX_HEADER_SIZE 8192
|
#define CLIENT_MAX_HEADER_SIZE 8192
|
||||||
#define FILE_CACHE_SIZE 1024
|
#define FILE_CACHE_SIZE 1024
|
||||||
#define SHM_KEY 255641
|
#define SHM_KEY 255641
|
||||||
|
#define GEOIP_MAX_SIZE 8192
|
||||||
|
|
||||||
#define ERR_STR "\x1B[1;31m"
|
#define ERR_STR "\x1B[1;31m"
|
||||||
#define CLR_STR "\x1B[0m"
|
#define CLR_STR "\x1B[0m"
|
||||||
@ -51,11 +55,13 @@
|
|||||||
#define HTTP_4XX_STR "\x1B[1;31m"
|
#define HTTP_4XX_STR "\x1B[1;31m"
|
||||||
#define HTTP_5XX_STR "\x1B[1;31m"
|
#define HTTP_5XX_STR "\x1B[1;31m"
|
||||||
|
|
||||||
#define NECRONDA_VERSION "4.0"
|
#define NECRONDA_VERSION "4.1"
|
||||||
#define SERVER_STR "Necronda/" NECRONDA_VERSION
|
#define SERVER_STR "Necronda/" NECRONDA_VERSION
|
||||||
#define NECRONDA_DEFAULT "www.necronda.net"
|
|
||||||
#define NECRONDA_ZLIB_LEVEL 9
|
#define NECRONDA_ZLIB_LEVEL 9
|
||||||
|
|
||||||
|
#ifndef DEFAULT_HOST
|
||||||
|
#define DEFAULT_HOST "www.necronda.net"
|
||||||
|
#endif
|
||||||
#ifndef MAGIC_FILE
|
#ifndef MAGIC_FILE
|
||||||
#define MAGIC_FILE "/usr/share/file/misc/magic.mgc"
|
#define MAGIC_FILE "/usr/share/file/misc/magic.mgc"
|
||||||
#endif
|
#endif
|
||||||
@ -65,14 +71,18 @@
|
|||||||
|
|
||||||
int sockets[NUM_SOCKETS];
|
int sockets[NUM_SOCKETS];
|
||||||
pid_t children[MAX_CHILDREN];
|
pid_t children[MAX_CHILDREN];
|
||||||
|
MMDB_s mmdbs[MAX_MMDB];
|
||||||
|
|
||||||
const char *cert_file, *key_file, *webroot_base, *geoip_file;
|
const char *cert_file, *key_file, *webroot_base, *geoip_dir, *dns_server;
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
unsigned int enc:1;
|
unsigned int enc:1;
|
||||||
int socket;
|
int socket;
|
||||||
SSL_CTX *ctx;
|
SSL_CTX *ctx;
|
||||||
SSL *ssl;
|
SSL *ssl;
|
||||||
|
char *buf;
|
||||||
|
unsigned long buf_len;
|
||||||
|
unsigned long buf_off;
|
||||||
} sock;
|
} sock;
|
||||||
|
|
||||||
char *ssl_get_error(SSL *ssl, int ret);
|
char *ssl_get_error(SSL *ssl, int ret);
|
||||||
|
@ -101,9 +101,9 @@ int uri_init(http_uri *uri, const char *webroot, const char *uri_str, int dir_mo
|
|||||||
uri->filename = malloc(strlen(buf0) + 1);
|
uri->filename = malloc(strlen(buf0) + 1);
|
||||||
strcpy(uri->filename, buf0);
|
strcpy(uri->filename, buf0);
|
||||||
ssize_t len = strlen(uri->path);
|
ssize_t len = strlen(uri->path);
|
||||||
if (strncmp(uri->path + len - 5, ".html", 5) == 0) {
|
if (strcmp(uri->path + len - 5, ".html") == 0) {
|
||||||
uri->path[len - 5] = 0;
|
uri->path[len - 5] = 0;
|
||||||
} else if (strncmp(uri->path + len - 4, ".php", 4) == 0) {
|
} else if (strcmp(uri->path + len - 4, ".php") == 0) {
|
||||||
uri->path[len - 4] = 0;
|
uri->path[len - 4] = 0;
|
||||||
uri->is_static = 0;
|
uri->is_static = 0;
|
||||||
}
|
}
|
||||||
|
61
src/utils.c
61
src/utils.c
@ -94,3 +94,64 @@ int url_decode(const char *str, char *dec, ssize_t *size) {
|
|||||||
*size = ptr - dec;
|
*size = ptr - dec;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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", 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;
|
||||||
|
}
|
||||||
|
@ -17,7 +17,7 @@ char *log_prefix;
|
|||||||
|
|
||||||
#define print(...) out_x(, ##__VA_ARGS__, out_2(__VA_ARGS__), out_2(__VA_ARGS__), out_2(__VA_ARGS__), \
|
#define print(...) out_x(, ##__VA_ARGS__, out_2(__VA_ARGS__), out_2(__VA_ARGS__), out_2(__VA_ARGS__), \
|
||||||
out_2(__VA_ARGS__), out_2(__VA_ARGS__), out_2(__VA_ARGS__), out_2(__VA_ARGS__), \
|
out_2(__VA_ARGS__), out_2(__VA_ARGS__), out_2(__VA_ARGS__), out_2(__VA_ARGS__), \
|
||||||
out_2(__VA_ARGS__), out_1(__VA_ARGS__)); fflush(stdout)
|
out_2(__VA_ARGS__), out_1(__VA_ARGS__))
|
||||||
|
|
||||||
|
|
||||||
char *format_duration(unsigned long micros, char *buf);
|
char *format_duration(unsigned long micros, char *buf);
|
||||||
|
Reference in New Issue
Block a user