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
|
||||
!Makefile
|
||||
!.gitignore
|
||||
!CppNet
|
||||
!CppNet/**
|
||||
!README.md
|
||||
|
4
Makefile
4
Makefile
@ -7,11 +7,11 @@ packages:
|
||||
|
||||
compile:
|
||||
@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:
|
||||
@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 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);
|
||||
if (magic == NULL) {
|
||||
fprintf(stderr, ERR_STR "Unable to open magic cookie: %s" CLR_STR "\n", strerror(errno));
|
||||
fflush(stderr);
|
||||
return -1;
|
||||
}
|
||||
if (magic_load(magic, MAGIC_FILE) != 0) {
|
||||
fprintf(stderr, ERR_STR "Unable to load magic cookie: %s" CLR_STR "\n", magic_error(magic));
|
||||
fflush(stderr);
|
||||
return -2;
|
||||
}
|
||||
return 0;
|
||||
@ -35,7 +33,6 @@ int cache_process() {
|
||||
int shm_id = shmget(SHM_KEY, FILE_CACHE_SIZE * sizeof(cache_entry), 0);
|
||||
if (shm_id < 0) {
|
||||
fprintf(stderr, ERR_STR "Unable to create shared memory: %s" CLR_STR "\n", strerror(errno));
|
||||
fflush(stderr);
|
||||
return -1;
|
||||
}
|
||||
|
||||
@ -43,7 +40,6 @@ int cache_process() {
|
||||
void *shm_rw = shmat(shm_id, NULL, 0);
|
||||
if (shm_rw == (void *) -1) {
|
||||
fprintf(stderr, ERR_STR "Unable to attach shared memory (rw): %s" CLR_STR "\n", strerror(errno));
|
||||
fflush(stderr);
|
||||
return -2;
|
||||
}
|
||||
cache = shm_rw;
|
||||
@ -51,7 +47,6 @@ int cache_process() {
|
||||
if (mkdir("/var/necronda-server/", 0755) < 0) {
|
||||
if (errno != EEXIST) {
|
||||
fprintf(stderr, ERR_STR "Unable to create directory '/var/necronda-server/': %s" CLR_STR "\n", strerror(errno));
|
||||
fflush(stderr);
|
||||
return -3;
|
||||
}
|
||||
}
|
||||
@ -106,14 +101,12 @@ int cache_process() {
|
||||
if (comp_file == NULL) {
|
||||
compress = 0;
|
||||
fprintf(stderr, ERR_STR "Unable to open cache file: %s" CLR_STR "\n", strerror(errno));
|
||||
fflush(stderr);
|
||||
} else {
|
||||
strm.zalloc = Z_NULL;
|
||||
strm.zfree = Z_NULL;
|
||||
strm.opaque = Z_NULL;
|
||||
if (deflateInit(&strm, level) != Z_OK) {
|
||||
fprintf(stderr, ERR_STR "Unable to init deflate: %s" CLR_STR "\n", strerror(errno));
|
||||
fflush(stderr);
|
||||
compress = 0;
|
||||
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);
|
||||
if (shm_id < 0) {
|
||||
fprintf(stderr, ERR_STR "Unable to create shared memory: %s" CLR_STR "\n", strerror(errno));
|
||||
fflush(stderr);
|
||||
return -2;
|
||||
}
|
||||
|
||||
void *shm = shmat(shm_id, NULL, SHM_RDONLY);
|
||||
if (shm == (void *) -1) {
|
||||
fprintf(stderr, ERR_STR "Unable to attach shared memory (ro): %s" CLR_STR "\n", strerror(errno));
|
||||
fflush(stderr);
|
||||
return -3;
|
||||
}
|
||||
cache = shm;
|
||||
@ -183,7 +174,6 @@ int cache_init() {
|
||||
void *shm_rw = shmat(shm_id, NULL, 0);
|
||||
if (shm_rw == (void *) -1) {
|
||||
fprintf(stderr, ERR_STR "Unable to attach shared memory (rw): %s" CLR_STR "\n", strerror(errno));
|
||||
fflush(stderr);
|
||||
return -4;
|
||||
}
|
||||
cache = shm_rw;
|
||||
@ -202,11 +192,9 @@ int cache_init() {
|
||||
} else if (pid > 0) {
|
||||
// parent
|
||||
fprintf(stderr, "Started child process with PID %i as cache-updater\n", pid);
|
||||
fflush(stderr);
|
||||
children[0] = pid;
|
||||
} else {
|
||||
fprintf(stderr, ERR_STR "Unable to create child process: %s" CLR_STR "\n", strerror(errno));
|
||||
fflush(stderr);
|
||||
return -5;
|
||||
}
|
||||
|
||||
@ -217,10 +205,8 @@ int cache_unload() {
|
||||
int shm_id = shmget(SHM_KEY, 0, 0);
|
||||
if (shm_id < 0) {
|
||||
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) {
|
||||
fprintf(stderr, ERR_STR "Unable to configure shared memory: %s" CLR_STR "\n", strerror(errno));
|
||||
fflush(stderr);
|
||||
}
|
||||
shmdt(cache);
|
||||
return 0;
|
||||
@ -248,7 +234,7 @@ int cache_update_entry(int entry_num, const char *filename, const char *webroot)
|
||||
char type_new[24];
|
||||
sprintf(type_new, "%s", type);
|
||||
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");
|
||||
} else if (strcmp(filename + strlen(filename) - 3, ".js") == 0) {
|
||||
sprintf(type_new, "text/javascript");
|
||||
|
125
src/client.c
125
src/client.c
@ -15,7 +15,7 @@
|
||||
int server_keep_alive = 1;
|
||||
char *client_addr_str, *client_addr_str_ptr, *server_addr_str, *server_addr_str_ptr,
|
||||
*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};
|
||||
|
||||
@ -25,7 +25,7 @@ char *get_webroot(const char *http_host) {
|
||||
while (webroot_base[len - 1] == '/') len--;
|
||||
long pos = strchr(http_host, ':') - 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() {
|
||||
@ -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");
|
||||
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");
|
||||
if (host == NULL || strchr(host, '/') != NULL) {
|
||||
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;
|
||||
print(BLD_STR "%s %s" CLR_STR, req.method, req.uri);
|
||||
|
||||
// TODO Reverse Proxy
|
||||
webroot = get_webroot(host);
|
||||
if (webroot == NULL) {
|
||||
res.status = http_get_status(307);
|
||||
sprintf(buf0, "https://%s%s", NECRONDA_DEFAULT, req.uri);
|
||||
http_add_header_field(&req.hdr, "Location", buf0);
|
||||
sprintf(buf0, "https://%s%s", DEFAULT_HOST, req.uri);
|
||||
http_add_header_field(&res.hdr, "Location", buf0);
|
||||
goto respond;
|
||||
}
|
||||
|
||||
dir_mode = URI_DIR_MODE_FORBIDDEN;
|
||||
dir_mode = URI_DIR_MODE_INFO;
|
||||
http_uri uri;
|
||||
ret = uri_init(&uri, webroot, req.uri, dir_mode);
|
||||
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);
|
||||
http_add_header_field(&res.hdr, "Allow", "GET, HEAD");
|
||||
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);
|
||||
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_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_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);
|
||||
goto respond;
|
||||
}
|
||||
@ -270,7 +271,7 @@ int client_request_handler(sock *client, unsigned long client_num, unsigned int
|
||||
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");
|
||||
unsigned long client_content_len = 0;
|
||||
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) {
|
||||
goto abort;
|
||||
} else {
|
||||
sprintf(err_msg, "Unable to communicate with PHP-FPM.");
|
||||
}
|
||||
res.status = http_get_status(502);
|
||||
goto respond;
|
||||
}
|
||||
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,
|
||||
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 len = 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) {
|
||||
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");
|
||||
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);
|
||||
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);
|
||||
http_free_req(&req);
|
||||
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;
|
||||
}
|
||||
|
||||
int client_connection_handler(sock *client, unsigned long client_num) {
|
||||
struct timespec begin, end;
|
||||
int ret, req_num;
|
||||
char buf[16];
|
||||
char buf[1024];
|
||||
|
||||
clock_gettime(CLOCK_MONOTONIC, &begin);
|
||||
|
||||
// TODO get geoip data for ip address
|
||||
// TODO Reverse DNS request
|
||||
client_host_str = client_addr_str;
|
||||
if (dns_server != NULL) {
|
||||
sprintf(buf, "dig @%s +short +time=1 -x %s", dns_server, 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_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);
|
||||
free(client_addr_str_ptr);
|
||||
client_addr_str_ptr = NULL;
|
||||
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);
|
||||
log_conn_prefix = NULL;
|
||||
free(log_req_prefix);
|
||||
log_req_prefix = NULL;
|
||||
free(log_client_prefix);
|
||||
log_client_prefix = NULL;
|
||||
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;
|
||||
sprintf(buf0, "%i", addr->sin6_port);
|
||||
param_ptr = fastcgi_add_param(param_ptr, "REMOTE_PORT", buf0);
|
||||
|
||||
char addr_str[INET6_ADDRSTRLEN];
|
||||
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_ADDR", client_addr_str);
|
||||
param_ptr = fastcgi_add_param(param_ptr, "REMOTE_HOST", client_host_str != NULL ? client_host_str : client_addr_str);
|
||||
//param_ptr = fastcgi_add_param(param_ptr, "REMOTE_IDENT", "");
|
||||
//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 : "");
|
||||
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 : "");
|
||||
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++) {
|
||||
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);
|
||||
sprintf(err_msg, "Unable to communicate with PHP-FPM.");
|
||||
print(ERR_STR "Unable to receive from PHP-FPM: %s" CLR_STR, strerror(errno));
|
||||
return -1;
|
||||
return 1;
|
||||
} else if (ret != sizeof(header)) {
|
||||
res->status = http_get_status(502);
|
||||
sprintf(err_msg, "Unable to communicate with PHP-FPM.");
|
||||
print(ERR_STR "Unable to receive from PHP-FPM" CLR_STR);
|
||||
return -1;
|
||||
return 1;
|
||||
}
|
||||
req_id = (header.requestIdB1 << 8) | header.requestIdB0;
|
||||
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.");
|
||||
print(ERR_STR "Unable to receive from PHP-FPM: %s" CLR_STR, strerror(errno));
|
||||
free(content);
|
||||
return -1;
|
||||
return 1;
|
||||
} else if (ret != (content_len + header.paddingLength)) {
|
||||
res->status = http_get_status(502);
|
||||
sprintf(err_msg, "Unable to communicate with PHP-FPM.");
|
||||
print(ERR_STR "Unable to receive from PHP-FPM" CLR_STR);
|
||||
free(content);
|
||||
return -1;
|
||||
return 1;
|
||||
}
|
||||
|
||||
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);
|
||||
conn->socket = 0;
|
||||
free(content);
|
||||
return -2;
|
||||
return 1;
|
||||
} else if (header.type == FCGI_STDERR) {
|
||||
err = err || fastcgi_php_error(content, content_len, err_msg);
|
||||
} else if (header.type == FCGI_STDOUT) {
|
||||
@ -342,7 +336,7 @@ int fastcgi_header(fastcgi_conn *conn, http_res *res, char *err_msg) {
|
||||
}
|
||||
if (err) {
|
||||
res->status = http_get_status(500);
|
||||
return -3;
|
||||
return 2;
|
||||
}
|
||||
|
||||
conn->out_buf = content;
|
||||
@ -519,6 +513,13 @@ int fastcgi_receive(fastcgi_conn *conn, sock *client, unsigned long len) {
|
||||
.paddingLength = 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) {
|
||||
if (client->enc) {
|
||||
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;
|
||||
}
|
||||
}
|
||||
send:
|
||||
rcv_len += ret;
|
||||
header.contentLengthB1 = (ret >> 8) & 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;
|
||||
while (header_len != (ptr - buf)) {
|
||||
while (header_len > (ptr - buf + 2)) {
|
||||
pos0 = strstr(ptr, "\r\n");
|
||||
if (pos0 == NULL) {
|
||||
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 (memcmp(ptr, "GET ", 4) == 0) {
|
||||
strcpy(req->method, "GET");
|
||||
} else if (memcmp(ptr, "HEAD ", 5) == 0) {
|
||||
strcpy(req->method, "HEAD");
|
||||
} else if (memcmp(ptr, "POST ", 5) == 0) {
|
||||
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);
|
||||
pos1 = memchr(ptr, ' ', rcv_len - (ptr - buf)) + 1;
|
||||
if (pos1 == NULL) goto err_hdr_fmt;
|
||||
|
||||
if (pos1 - ptr - 1 >= sizeof(req->method)) {
|
||||
print(ERR_STR "Unable to parse header: Method name too long" CLR_STR);
|
||||
return 2;
|
||||
}
|
||||
|
||||
pos1 = memchr(ptr, ' ', rcv_len - (ptr - buf)) + 1;
|
||||
if (pos1 == NULL) goto err_hdr_fmt;
|
||||
for (int i = 0; i < (pos1 - ptr - 1); i++) {
|
||||
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;
|
||||
if (pos2 == NULL) {
|
||||
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);
|
||||
if (ret != 0) return ret;
|
||||
}
|
||||
if (pos0[2] == '\r' && pos0[3] == '\n') {
|
||||
return 0;
|
||||
}
|
||||
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) {
|
||||
|
@ -32,7 +32,7 @@ typedef struct {
|
||||
} http_hdr;
|
||||
|
||||
typedef struct {
|
||||
char method[8];
|
||||
char method[16];
|
||||
char *uri;
|
||||
char version[3];
|
||||
http_hdr hdr;
|
||||
|
@ -62,7 +62,6 @@ char *ssl_get_error(SSL *ssl, int ret) {
|
||||
|
||||
void destroy() {
|
||||
fprintf(stderr, "\n" ERR_STR "Terminating forcefully!" CLR_STR "\n");
|
||||
fflush(stderr);
|
||||
int status = 0;
|
||||
int ret;
|
||||
int kills = 0;
|
||||
@ -72,13 +71,11 @@ void destroy() {
|
||||
if (ret < 0) {
|
||||
fprintf(stderr, ERR_STR "Unable to wait for child process (PID %i): %s" CLR_STR "\n",
|
||||
children[i], strerror(errno));
|
||||
fflush(stderr);
|
||||
} else if (ret == children[i]) {
|
||||
children[i] = 0;
|
||||
if (status != 0) {
|
||||
fprintf(stderr, ERR_STR "Child process with PID %i terminated with exit code %i" CLR_STR "\n",
|
||||
ret, status);
|
||||
fflush(stderr);
|
||||
}
|
||||
} else {
|
||||
kill(children[i], SIGKILL);
|
||||
@ -88,7 +85,6 @@ void destroy() {
|
||||
}
|
||||
if (kills > 0) {
|
||||
fprintf(stderr, ERR_STR "Killed %i child process(es)" CLR_STR "\n", kills);
|
||||
fflush(stderr);
|
||||
}
|
||||
cache_unload();
|
||||
exit(2);
|
||||
@ -96,7 +92,6 @@ void destroy() {
|
||||
|
||||
void terminate() {
|
||||
fprintf(stderr, "\nTerminating gracefully...\n");
|
||||
fflush(stderr);
|
||||
active = 0;
|
||||
|
||||
signal(SIGINT, destroy);
|
||||
@ -116,13 +111,11 @@ void terminate() {
|
||||
if (ret < 0) {
|
||||
fprintf(stderr, ERR_STR "Unable to wait for child process (PID %i): %s" CLR_STR "\n",
|
||||
children[i], strerror(errno));
|
||||
fflush(stderr);
|
||||
} else if (ret == children[i]) {
|
||||
children[i] = 0;
|
||||
if (status != 0) {
|
||||
fprintf(stderr, ERR_STR "Child process with PID %i terminated with exit code %i" CLR_STR "\n",
|
||||
ret, status);
|
||||
fflush(stderr);
|
||||
}
|
||||
} else {
|
||||
kill(children[i], SIGTERM);
|
||||
@ -133,7 +126,6 @@ void terminate() {
|
||||
|
||||
if (wait_num > 0) {
|
||||
fprintf(stderr, "Waiting for %i child process(es)...\n", wait_num);
|
||||
fflush(stderr);
|
||||
}
|
||||
|
||||
for (int i = 0; i < MAX_CHILDREN; i++) {
|
||||
@ -142,13 +134,11 @@ void terminate() {
|
||||
if (ret < 0) {
|
||||
fprintf(stderr, ERR_STR "Unable to wait for child process (PID %i): %s" CLR_STR "\n",
|
||||
children[i], strerror(errno));
|
||||
fflush(stderr);
|
||||
} else if (ret == children[i]) {
|
||||
children[i] = 0;
|
||||
if (status != 0) {
|
||||
fprintf(stderr, ERR_STR "Child process with PID %i terminated with exit code %i" CLR_STR "\n",
|
||||
ret, status);
|
||||
fflush(stderr);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -161,10 +151,8 @@ void terminate() {
|
||||
struct timespec ts = {.tv_sec = 0, .tv_nsec = 50000000};
|
||||
nanosleep(&ts, &ts);
|
||||
fprintf(stderr, "\nGoodbye\n");
|
||||
fflush(stderr);
|
||||
} else {
|
||||
fprintf(stderr, "Goodbye\n");
|
||||
fflush(stderr);
|
||||
}
|
||||
cache_unload();
|
||||
exit(0);
|
||||
@ -184,6 +172,10 @@ int main(int argc, const char *argv[]) {
|
||||
struct sockaddr_in6 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;
|
||||
|
||||
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)}
|
||||
};
|
||||
|
||||
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");
|
||||
fflush(stdout);
|
||||
|
||||
for (int i = 1; i < argc; i++) {
|
||||
const char *arg = argv[i];
|
||||
unsigned long len = strlen(arg);
|
||||
if ((len == 2 && strncmp(arg, "-h", 2) == 0) || (len == 6 && strncmp(arg, "--help", 6) == 0)) {
|
||||
printf("Usage: necronda-server [-h] -w <PATH> -c <CERT-FILE> -p <KEY-FILE> [-g <DB-FILE>]\n"
|
||||
if (strcmp(arg, "-h") == 0 || strcmp(arg, "--help") == 0) {
|
||||
printf("Usage: necronda-server [-h] -w <PATH> -c <CERT-FILE> -p <KEY-FILE> [-g <DB-DIR>] [-d <DNS-SERVER>]\n"
|
||||
"\n"
|
||||
"Options:\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"
|
||||
" -p, --privkey <KEY-FILE> path to the private key file\n"
|
||||
" -w, --webroot <PATH> path to the web root directory\n");
|
||||
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) {
|
||||
fprintf(stderr, ERR_STR "Unable to parse argument %s, usage: --webroot <WEBROOT>" CLR_STR "\n", arg);
|
||||
fflush(stderr);
|
||||
return 1;
|
||||
}
|
||||
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) {
|
||||
fprintf(stderr, ERR_STR "Unable to parse argument %s, usage: --cert <CERT-FILE>" CLR_STR "\n", arg);
|
||||
fflush(stderr);
|
||||
return 1;
|
||||
}
|
||||
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) {
|
||||
fprintf(stderr, ERR_STR "Unable to parse argument %s, usage: --privkey <KEY-FILE>" CLR_STR "\n", arg);
|
||||
fflush(stderr);
|
||||
return 1;
|
||||
}
|
||||
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) {
|
||||
fprintf(stderr, ERR_STR "Unable to parse argument %s, usage: --geoip <DB-FILE>" CLR_STR "\n", arg);
|
||||
fflush(stderr);
|
||||
fprintf(stderr, ERR_STR "Unable to parse argument %s, usage: --geoip <DB-DIR>" CLR_STR "\n", arg);
|
||||
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 {
|
||||
fprintf(stderr, ERR_STR "Unable to parse argument '%s'" CLR_STR "\n", arg);
|
||||
fflush(stderr);
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
if (webroot_base == NULL) {
|
||||
fprintf(stderr, ERR_STR "Error: --webroot is missing" CLR_STR "\n");
|
||||
fflush(stderr);
|
||||
return 1;
|
||||
}
|
||||
if (cert_file == NULL) {
|
||||
fprintf(stderr, ERR_STR "Error: --cert is missing" CLR_STR "\n");
|
||||
fflush(stderr);
|
||||
return 1;
|
||||
}
|
||||
if (key_file == NULL) {
|
||||
fprintf(stderr, ERR_STR "Error: --privkey is missing" CLR_STR "\n");
|
||||
fflush(stderr);
|
||||
return 1;
|
||||
}
|
||||
|
||||
@ -264,14 +258,12 @@ int main(int argc, const char *argv[]) {
|
||||
if (sockets[1] < 0) {
|
||||
socket_err:
|
||||
fprintf(stderr, ERR_STR "Unable to create socket: %s" CLR_STR "\n", strerror(errno));
|
||||
fflush(stderr);
|
||||
return 1;
|
||||
}
|
||||
|
||||
for (int i = 0; i < NUM_SOCKETS; i++) {
|
||||
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));
|
||||
fflush(stderr);
|
||||
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) {
|
||||
bind_err:
|
||||
fprintf(stderr, ERR_STR "Unable to bind socket to address: %s" CLR_STR "\n", strerror(errno));
|
||||
fflush(stderr);
|
||||
return 1;
|
||||
}
|
||||
|
||||
signal(SIGINT, terminate);
|
||||
signal(SIGTERM, terminate);
|
||||
|
||||
ret = cache_init();
|
||||
if (ret < 0) {
|
||||
return 1;
|
||||
} else if (ret != 0) {
|
||||
return 0;
|
||||
if (geoip_dir != NULL) {
|
||||
DIR *geoip = opendir(geoip_dir);
|
||||
if (geoip == NULL) {
|
||||
fprintf(stderr, ERR_STR "Unable to open GeoIP dir: %s" CLR_STR "\n", strerror(errno));
|
||||
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();
|
||||
|
||||
client.buf = NULL;
|
||||
client.buf_len = 0;
|
||||
client.buf_off = 0;
|
||||
client.ctx = SSL_CTX_new(TLS_server_method());
|
||||
SSL_CTX_set_options(client.ctx, SSL_OP_SINGLE_DH_USE);
|
||||
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) {
|
||||
fprintf(stderr, ERR_STR "Unable to load certificate chain file: %s: %s" CLR_STR "\n",
|
||||
ERR_reason_error_string(ERR_get_error()), cert_file);
|
||||
fflush(stderr);
|
||||
return 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",
|
||||
ERR_reason_error_string(ERR_get_error()), key_file);
|
||||
fflush(stderr);
|
||||
return 1;
|
||||
}
|
||||
|
||||
for (int i = 0; i < NUM_SOCKETS; i++) {
|
||||
if (listen(sockets[i], LISTEN_BACKLOG) < 0) {
|
||||
fprintf(stderr, ERR_STR "Unable to listen on socket %i: %s" CLR_STR "\n", i, strerror(errno));
|
||||
fflush(stderr);
|
||||
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");
|
||||
fflush(stderr);
|
||||
|
||||
while (active) {
|
||||
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);
|
||||
if (ready_sockets_num < 0) {
|
||||
fprintf(stderr, ERR_STR "Unable to select sockets: %s" CLR_STR "\n", strerror(errno));
|
||||
fflush(stderr);
|
||||
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);
|
||||
if (client_fd < 0) {
|
||||
fprintf(stderr, ERR_STR "Unable to accept connection: %s" CLR_STR "\n", strerror(errno));
|
||||
fflush(stderr);
|
||||
continue;
|
||||
}
|
||||
|
||||
@ -379,7 +394,6 @@ int main(int argc, const char *argv[]) {
|
||||
}
|
||||
} else {
|
||||
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) {
|
||||
fprintf(stderr, ERR_STR "Unable to wait for child process (PID %i): %s" CLR_STR "\n",
|
||||
children[i], strerror(errno));
|
||||
fflush(stderr);
|
||||
} else if (ret == children[i]) {
|
||||
children[i] = 0;
|
||||
if (status != 0) {
|
||||
fprintf(stderr, ERR_STR "Child process with PID %i terminated with exit code %i" CLR_STR "\n",
|
||||
ret, status);
|
||||
fflush(stderr);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -25,10 +25,13 @@
|
||||
#include <openssl/conf.h>
|
||||
#include <openssl/engine.h>
|
||||
#include <openssl/dh.h>
|
||||
#include <maxminddb.h>
|
||||
#include <dirent.h>
|
||||
|
||||
|
||||
#define NUM_SOCKETS 2
|
||||
#define MAX_CHILDREN 1024
|
||||
#define MAX_MMDB 3
|
||||
#define LISTEN_BACKLOG 16
|
||||
#define REQ_PER_CONNECTION 100
|
||||
#define CLIENT_TIMEOUT 3600
|
||||
@ -37,6 +40,7 @@
|
||||
#define CLIENT_MAX_HEADER_SIZE 8192
|
||||
#define FILE_CACHE_SIZE 1024
|
||||
#define SHM_KEY 255641
|
||||
#define GEOIP_MAX_SIZE 8192
|
||||
|
||||
#define ERR_STR "\x1B[1;31m"
|
||||
#define CLR_STR "\x1B[0m"
|
||||
@ -51,11 +55,13 @@
|
||||
#define HTTP_4XX_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 NECRONDA_DEFAULT "www.necronda.net"
|
||||
#define NECRONDA_ZLIB_LEVEL 9
|
||||
|
||||
#ifndef DEFAULT_HOST
|
||||
#define DEFAULT_HOST "www.necronda.net"
|
||||
#endif
|
||||
#ifndef MAGIC_FILE
|
||||
#define MAGIC_FILE "/usr/share/file/misc/magic.mgc"
|
||||
#endif
|
||||
@ -65,14 +71,18 @@
|
||||
|
||||
int sockets[NUM_SOCKETS];
|
||||
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 {
|
||||
unsigned int enc:1;
|
||||
int socket;
|
||||
SSL_CTX *ctx;
|
||||
SSL *ssl;
|
||||
char *buf;
|
||||
unsigned long buf_len;
|
||||
unsigned long buf_off;
|
||||
} sock;
|
||||
|
||||
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);
|
||||
strcpy(uri->filename, buf0);
|
||||
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;
|
||||
} 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->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;
|
||||
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__), \
|
||||
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);
|
||||
|
Reference in New Issue
Block a user