Compare commits
12 Commits
4fe067ed7d
...
v4.6
Author | SHA1 | Date | |
---|---|---|---|
a2f4bf57e0
|
|||
635271ec50
|
|||
2b4569aabe
|
|||
f361fce561
|
|||
c92742275a
|
|||
041e4d43a7
|
|||
170337d4d5
|
|||
f0b27b3b37
|
|||
ee8aedce91
|
|||
0648c75baa | |||
b6ba58d406
|
|||
abe0e326cb
|
14
Makefile
14
Makefile
@@ -11,16 +11,16 @@ packages:
|
||||
@echo "Finished downloading!"
|
||||
|
||||
permit:
|
||||
sudo setcap 'cap_net_bind_service=+ep' "$(shell pwd)/bin/necronda-server"
|
||||
sudo setcap 'cap_net_bind_service=+ep' "$(shell pwd)/bin/sesimos"
|
||||
|
||||
compile:
|
||||
@mkdir -p bin
|
||||
$(CC) src/lib/*.c -o bin/libnecrondaserver.so --shared -fPIC $(CFLAGS) $(LIBS)
|
||||
$(CC) src/server.c src/client.c -o bin/necronda-server $(CFLAGS) $(LIBS) \
|
||||
-Lbin -lnecrondaserver -Wl,-rpath=$(shell pwd)/bin
|
||||
$(CC) src/lib/*.c -o bin/libsesimos.so --shared -fPIC $(CFLAGS) $(LIBS)
|
||||
$(CC) src/server.c src/client.c -o bin/sesimos $(CFLAGS) $(LIBS) \
|
||||
-Lbin -lsesimos -Wl,-rpath=$(shell pwd)/bin
|
||||
|
||||
compile-prod:
|
||||
@mkdir -p bin
|
||||
$(CC) src/lib/*.c -o bin/libnecrondaserver.so --shared -fPIC $(CFLAGS) $(LIBS) $(DEBIAN_OPTS) -O3
|
||||
$(CC) src/server.c src/client.c -o bin/necronda-server $(CFLAGS) $(LIBS) $(DEBIAN_OPTS) -O3 \
|
||||
-Lbin -lnecrondaserver -Wl,-rpath=$(shell pwd)/bin
|
||||
$(CC) src/lib/*.c -o bin/libsesimos.so --shared -fPIC $(CFLAGS) $(LIBS) $(DEBIAN_OPTS) -O3
|
||||
$(CC) src/server.c src/client.c -o bin/sesimos $(CFLAGS) $(LIBS) $(DEBIAN_OPTS) -O3 \
|
||||
-Lbin -lsesimos -Wl,-rpath=$(shell pwd)/bin
|
||||
|
@@ -1,6 +1,6 @@
|
||||
|
||||
Necronda web server
|
||||
===================
|
||||
Sesimos – Secure, simple, modern web server
|
||||
===========================================
|
||||
|
||||
## Features
|
||||
|
||||
@@ -10,7 +10,7 @@ Necronda web server
|
||||
* File compression ([gzip](https://www.gzip.org/), [Brotli](https://www.brotli.org/))
|
||||
* Disk cache for compressed files
|
||||
* Reverse proxy for other HTTP and HTTPS servers
|
||||
* Transparent WebSocket reverse proxy **[WIP]**
|
||||
* Transparent WebSocket reverse proxy
|
||||
* FastCGI support (e.g. [PHP-FPM](https://php-fpm.org/))
|
||||
* Automatic path info detection (e.g. `/my/file/extra/path` -> script: `/my/file.php`, path info: `extra/path`)
|
||||
* Support for [MaxMind's GeoIP Database](https://www.maxmind.com/en/geoip2-services-and-databases)
|
||||
|
92
src/client.c
92
src/client.c
@@ -1,12 +1,12 @@
|
||||
/**
|
||||
* Necronda Web Server
|
||||
* sesimos - secure, simple, modern web server
|
||||
* Client connection and request handlers
|
||||
* src/client.c
|
||||
* Lorenz Stechauner, 2020-12-03
|
||||
*/
|
||||
|
||||
#include "defs.h"
|
||||
#include "client.h"
|
||||
#include "necronda.h"
|
||||
#include "server.h"
|
||||
|
||||
#include "lib/utils.h"
|
||||
@@ -18,9 +18,9 @@
|
||||
#include "lib/cache.h"
|
||||
#include "lib/geoip.h"
|
||||
#include "lib/compress.h"
|
||||
#include "lib/websocket.h"
|
||||
|
||||
#include <string.h>
|
||||
#include <sys/select.h>
|
||||
#include <errno.h>
|
||||
#include <unistd.h>
|
||||
#include <openssl/ssl.h>
|
||||
@@ -28,13 +28,12 @@
|
||||
#include <signal.h>
|
||||
#include <arpa/inet.h>
|
||||
|
||||
|
||||
int server_keep_alive = 1;
|
||||
struct timeval client_timeout = {.tv_sec = CLIENT_TIMEOUT, .tv_usec = 0};
|
||||
|
||||
int server_keep_alive;
|
||||
char *log_client_prefix, *log_conn_prefix, *log_req_prefix, *client_geoip;
|
||||
char *client_addr_str, *client_addr_str_ptr, *server_addr_str, *server_addr_str_ptr, *client_host_str;
|
||||
struct timeval client_timeout;
|
||||
|
||||
host_config *get_host_config(const char *host) {
|
||||
for (int i = 0; i < CONFIG_MAX_HOST_CONFIG; i++) {
|
||||
@@ -53,11 +52,6 @@ void client_terminate() {
|
||||
server_keep_alive = 0;
|
||||
}
|
||||
|
||||
int client_websocket_handler() {
|
||||
// TODO implement client_websocket_handler
|
||||
return 0;
|
||||
}
|
||||
|
||||
int client_request_handler(sock *client, unsigned long client_num, unsigned int req_num) {
|
||||
struct timespec begin, end;
|
||||
long ret;
|
||||
@@ -87,16 +81,12 @@ int client_request_handler(sock *client, unsigned long client_num, unsigned int
|
||||
http_status custom_status;
|
||||
|
||||
http_res res = {.version = "1.1", .status = http_get_status(501), .hdr.field_num = 0, .hdr.last_field_num = -1};
|
||||
http_status_ctx ctx = {.status = 0, .origin = NONE};
|
||||
http_status_ctx ctx = {.status = 0, .origin = NONE, .ws_key = NULL};
|
||||
|
||||
clock_gettime(CLOCK_MONOTONIC, &begin);
|
||||
|
||||
fd_set socket_fds;
|
||||
FD_ZERO(&socket_fds);
|
||||
FD_SET(client->socket, &socket_fds);
|
||||
client_timeout.tv_sec = CLIENT_TIMEOUT;
|
||||
client_timeout.tv_usec = 0;
|
||||
ret = select(client->socket + 1, &socket_fds, NULL, NULL, &client_timeout);
|
||||
ret = sock_poll_read(&client, NULL, 1, CLIENT_TIMEOUT * 1000);
|
||||
|
||||
http_add_header_field(&res.hdr, "Date", http_get_date(buf0, sizeof(buf0)));
|
||||
http_add_header_field(&res.hdr, "Server", SERVER_STR);
|
||||
if (ret <= 0) {
|
||||
@@ -130,7 +120,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 && (strcmp(hdr_connection, "keep-alive") == 0 || strcmp(hdr_connection, "Keep-Alive") == 0));
|
||||
client_keep_alive = (hdr_connection != NULL && (strstr(hdr_connection, "keep-alive") != NULL || strstr(hdr_connection, "Keep-Alive") != NULL));
|
||||
host_ptr = http_get_header_field(&req.hdr, "Host");
|
||||
if (host_ptr != NULL && strlen(host_ptr) > 255) {
|
||||
host[0] = 0;
|
||||
@@ -384,7 +374,7 @@ int client_request_handler(sock *client, unsigned long client_num, unsigned int
|
||||
} else {
|
||||
int mode;
|
||||
if (strcmp(uri.filename + strlen(uri.filename) - 4, ".ncr") == 0) {
|
||||
mode = FASTCGI_NECRONDA;
|
||||
mode = FASTCGI_SESIMOS;
|
||||
} else if (strcmp(uri.filename + strlen(uri.filename) - 4, ".php") == 0) {
|
||||
mode = FASTCGI_PHP;
|
||||
} else {
|
||||
@@ -493,18 +483,37 @@ int client_request_handler(sock *client, unsigned long client_num, unsigned int
|
||||
ret = rev_proxy_init(&req, &res, &ctx, conf, client, &custom_status, err_msg);
|
||||
use_rev_proxy = (ret == 0);
|
||||
|
||||
if (res.status->code == 101) {
|
||||
const char *connection = http_get_header_field(&res.hdr, "Connection");
|
||||
const char *upgrade = http_get_header_field(&res.hdr, "Upgrade");
|
||||
if (connection != NULL && upgrade != NULL &&
|
||||
(strstr(connection, "upgrade") != NULL || strstr(connection, "Upgrade") != NULL) &&
|
||||
strcmp(upgrade, "websocket") == 0)
|
||||
{
|
||||
const char *ws_accept = http_get_header_field(&res.hdr, "Sec-WebSocket-Accept");
|
||||
if (ws_calc_accept_key(ctx.ws_key, buf0) == 0) {
|
||||
use_rev_proxy = (strcmp(buf0, ws_accept) == 0) ? 2 : 1;
|
||||
}
|
||||
} else {
|
||||
print("Fail Test1");
|
||||
ctx.status = 101;
|
||||
ctx.origin = INTERNAL;
|
||||
res.status = http_get_status(501);
|
||||
}
|
||||
}
|
||||
|
||||
// Let 300 be formatted by origin server
|
||||
if (use_rev_proxy && res.status->code >= 301 && res.status->code < 600) {
|
||||
const char *content_type = http_get_header_field(&res.hdr, "Content-Type");
|
||||
const char *content_length_f = http_get_header_field(&res.hdr, "Content-Length");
|
||||
const char *content_encoding = http_get_header_field(&res.hdr, "Content-Encoding");
|
||||
if (content_encoding == NULL && content_type != NULL && content_length_f != NULL &&
|
||||
strncmp(content_type, "text/html", 9) == 0)
|
||||
{
|
||||
if (content_encoding == NULL && content_type != NULL && content_length_f != NULL && strncmp(content_type, "text/html", 9) == 0) {
|
||||
long content_len = strtol(content_length_f, NULL, 10);
|
||||
if (content_len <= sizeof(msg_content) - 1) {
|
||||
ctx.status = res.status->code;
|
||||
ctx.origin = res.status->code >= 400 ? SERVER : NONE;
|
||||
if (ctx.status != 101) {
|
||||
ctx.status = res.status->code;
|
||||
ctx.origin = res.status->code >= 400 ? SERVER : NONE;
|
||||
}
|
||||
use_rev_proxy = 0;
|
||||
rev_proxy_dump(msg_content, content_len);
|
||||
}
|
||||
@@ -611,16 +620,19 @@ int client_request_handler(sock *client, unsigned long client_num, unsigned int
|
||||
}
|
||||
}
|
||||
|
||||
const char *conn = http_get_header_field(&res.hdr, "Connection");
|
||||
int close_proxy = (conn == NULL || (strcmp(conn, "keep-alive") != 0 && strcmp(conn, "Keep-Alive") != 0));
|
||||
http_remove_header_field(&res.hdr, "Connection", HTTP_REMOVE_ALL);
|
||||
http_remove_header_field(&res.hdr, "Keep-Alive", HTTP_REMOVE_ALL);
|
||||
if (server_keep_alive && client_keep_alive) {
|
||||
http_add_header_field(&res.hdr, "Connection", "keep-alive");
|
||||
sprintf(buf0, "timeout=%i, max=%i", CLIENT_TIMEOUT, REQ_PER_CONNECTION);
|
||||
http_add_header_field(&res.hdr, "Keep-Alive", buf0);
|
||||
} else {
|
||||
http_add_header_field(&res.hdr, "Connection", "close");
|
||||
int close_proxy = 0;
|
||||
if (use_rev_proxy != 2) {
|
||||
const char *conn = http_get_header_field(&res.hdr, "Connection");
|
||||
close_proxy = (conn == NULL || (strstr(conn, "keep-alive") == NULL && strstr(conn, "Keep-Alive") == NULL));
|
||||
http_remove_header_field(&res.hdr, "Connection", HTTP_REMOVE_ALL);
|
||||
http_remove_header_field(&res.hdr, "Keep-Alive", HTTP_REMOVE_ALL);
|
||||
if (server_keep_alive && client_keep_alive) {
|
||||
http_add_header_field(&res.hdr, "Connection", "keep-alive");
|
||||
sprintf(buf0, "timeout=%i, max=%i", CLIENT_TIMEOUT, REQ_PER_CONNECTION);
|
||||
http_add_header_field(&res.hdr, "Keep-Alive", buf0);
|
||||
} else {
|
||||
http_add_header_field(&res.hdr, "Connection", "close");
|
||||
}
|
||||
}
|
||||
|
||||
http_send_response(client, &res);
|
||||
@@ -633,7 +645,17 @@ int client_request_handler(sock *client, unsigned long client_num, unsigned int
|
||||
|
||||
// TODO access/error log file
|
||||
|
||||
if (strcmp(req.method, "HEAD") != 0) {
|
||||
if (use_rev_proxy == 2) {
|
||||
// WebSocket
|
||||
print("Upgrading connection to WebSocket connection");
|
||||
ret = ws_handle_connection(client, &rev_proxy);
|
||||
if (ret != 0) {
|
||||
client_keep_alive = 0;
|
||||
close_proxy = 1;
|
||||
}
|
||||
print("WebSocket connection closed");
|
||||
} else if (strcmp(req.method, "HEAD") != 0) {
|
||||
// default response
|
||||
unsigned long snd_len = 0;
|
||||
unsigned long len;
|
||||
if (msg_buf[0] != 0) {
|
||||
|
@@ -1,12 +1,12 @@
|
||||
/**
|
||||
* Necronda Web Server
|
||||
* sesimos - secure, simple, modern web server
|
||||
* Client connection and request handlers (header file)
|
||||
* src/client.h
|
||||
* Lorenz Stechauner, 2022-08-16
|
||||
*/
|
||||
|
||||
#ifndef NECRONDA_SERVER_NECRONDA_CLIENT_H
|
||||
#define NECRONDA_SERVER_NECRONDA_CLIENT_H
|
||||
#ifndef SESIMOS_CLIENT_H
|
||||
#define SESIMOS_CLIENT_H
|
||||
|
||||
#include "lib/config.h"
|
||||
#include "lib/sock.h"
|
||||
@@ -17,4 +17,4 @@ host_config *get_host_config(const char *host);
|
||||
|
||||
int client_handler(sock *client, unsigned long client_num, struct sockaddr_in6 *client_addr);
|
||||
|
||||
#endif //NECRONDA_SERVER_NECRONDA_CLIENT_H
|
||||
#endif //SESIMOS_CLIENT_H
|
||||
|
25
src/defs.h
Normal file
25
src/defs.h
Normal file
@@ -0,0 +1,25 @@
|
||||
/**
|
||||
* sesimos - secure, simple, modern web server
|
||||
* Definitions
|
||||
* src/defs.h
|
||||
* Lorenz Stechauner, 2021-05-04
|
||||
*/
|
||||
|
||||
#ifndef SESIMOS_DEF_H
|
||||
#define SESIMOS_DEF_H
|
||||
|
||||
#define SERVER_VERSION "4.6"
|
||||
#define SERVER_STR "Sesimos/" SERVER_VERSION
|
||||
#define SERVER_STR_HTML "Sesimos web server " SERVER_VERSION
|
||||
|
||||
#define CHUNK_SIZE 8192
|
||||
|
||||
#ifndef DEFAULT_HOST
|
||||
# define DEFAULT_HOST "www.necronda.net"
|
||||
#endif
|
||||
|
||||
#ifndef SERVER_NAME
|
||||
# define SERVER_NAME DEFAULT_HOST
|
||||
#endif
|
||||
|
||||
#endif //SESIMOS_DEF_H
|
@@ -1,5 +1,5 @@
|
||||
/**
|
||||
* Necronda Web Server
|
||||
* sesimos - secure, simple, modern web server
|
||||
* File cache implementation
|
||||
* src/lib/cache.c
|
||||
* Lorenz Stechauner, 2020-12-19
|
||||
@@ -8,6 +8,7 @@
|
||||
#include "cache.h"
|
||||
#include "utils.h"
|
||||
#include "compress.h"
|
||||
|
||||
#include <stdio.h>
|
||||
#include <magic.h>
|
||||
#include <sys/ipc.h>
|
||||
@@ -18,6 +19,7 @@
|
||||
#include <openssl/sha.h>
|
||||
#include <malloc.h>
|
||||
|
||||
|
||||
int cache_continue = 1;
|
||||
magic_t magic;
|
||||
cache_entry *cache;
|
||||
@@ -57,17 +59,17 @@ int cache_process() {
|
||||
}
|
||||
cache = shm_rw;
|
||||
|
||||
if (mkdir("/var/necronda/", 0755) < 0 && errno != EEXIST) {
|
||||
fprintf(stderr, ERR_STR "Unable to create directory '/var/necronda/': %s" CLR_STR "\n", strerror(errno));
|
||||
if (mkdir("/var/sesimos/", 0755) < 0 && errno != EEXIST) {
|
||||
fprintf(stderr, ERR_STR "Unable to create directory '/var/sesimos/': %s" CLR_STR "\n", strerror(errno));
|
||||
return -3;
|
||||
}
|
||||
|
||||
if (mkdir("/var/necronda/server/", 0755) < 0 && errno != EEXIST) {
|
||||
fprintf(stderr, ERR_STR "Unable to create directory '/var/necronda/server/': %s" CLR_STR "\n", strerror(errno));
|
||||
if (mkdir("/var/sesimos/server/", 0755) < 0 && errno != EEXIST) {
|
||||
fprintf(stderr, ERR_STR "Unable to create directory '/var/sesimos/server/': %s" CLR_STR "\n", strerror(errno));
|
||||
return -3;
|
||||
}
|
||||
|
||||
FILE *cache_file = fopen("/var/necronda/server/cache", "rb");
|
||||
FILE *cache_file = fopen("/var/sesimos/server/cache", "rb");
|
||||
if (cache_file != NULL) {
|
||||
fread(cache, sizeof(cache_entry), CACHE_ENTRIES, cache_file);
|
||||
fclose(cache_file);
|
||||
@@ -102,13 +104,13 @@ int cache_process() {
|
||||
FILE *comp_file_gz = NULL;
|
||||
FILE *comp_file_br = NULL;
|
||||
if (compress) {
|
||||
sprintf(buf, "%.*s/.necronda-server", cache[i].webroot_len, cache[i].filename);
|
||||
sprintf(buf, "%.*s/.sesimos", cache[i].webroot_len, cache[i].filename);
|
||||
if (mkdir(buf, 0755) != 0 && errno != EEXIST) {
|
||||
fprintf(stderr, ERR_STR "Unable to create directory %s: %s" CLR_STR "\n", buf, strerror(errno));
|
||||
goto comp_err;
|
||||
}
|
||||
|
||||
sprintf(buf, "%.*s/.necronda-server/cache", cache[i].webroot_len, cache[i].filename);
|
||||
sprintf(buf, "%.*s/.sesimos/cache", cache[i].webroot_len, cache[i].filename);
|
||||
if (mkdir(buf, 0700) != 0 && errno != EEXIST) {
|
||||
fprintf(stderr, ERR_STR "Unable to create directory %s: %s" CLR_STR "\n", buf, strerror(errno));
|
||||
goto comp_err;
|
||||
@@ -123,10 +125,10 @@ int cache_process() {
|
||||
buf[strlen(rel_path)] = 0;
|
||||
|
||||
p_len_gz = snprintf(filename_comp_gz, sizeof(filename_comp_gz),
|
||||
"%.*s/.necronda-server/cache/%s.gz",
|
||||
"%.*s/.sesimos/cache/%s.gz",
|
||||
cache[i].webroot_len, cache[i].filename, buf);
|
||||
p_len_br = snprintf(filename_comp_br, sizeof(filename_comp_br),
|
||||
"%.*s/.necronda-server/cache/%s.br",
|
||||
"%.*s/.sesimos/cache/%s.br",
|
||||
cache[i].webroot_len, cache[i].filename, buf);
|
||||
if (p_len_gz < 0 || p_len_gz >= sizeof(filename_comp_gz) ||
|
||||
p_len_br < 0 || p_len_br >= sizeof(filename_comp_br))
|
||||
@@ -201,7 +203,7 @@ int cache_process() {
|
||||
|
||||
if (cache_changed) {
|
||||
cache_changed = 0;
|
||||
cache_file = fopen("/var/necronda/server/cache", "wb");
|
||||
cache_file = fopen("/var/sesimos/server/cache", "wb");
|
||||
if (cache_file == NULL) {
|
||||
fprintf(stderr, ERR_STR "Unable to open cache file: %s" CLR_STR "\n", strerror(errno));
|
||||
free(buf);
|
||||
|
@@ -1,12 +1,12 @@
|
||||
/**
|
||||
* Necronda Web Server
|
||||
* sesimos - secure, simple, modern web server
|
||||
* File cache implementation (header file)
|
||||
* src/lib/cache.h
|
||||
* Lorenz Stechauner, 2020-12-19
|
||||
*/
|
||||
|
||||
#ifndef NECRONDA_SERVER_CACHE_H
|
||||
#define NECRONDA_SERVER_CACHE_H
|
||||
#ifndef SESIMOS_CACHE_H
|
||||
#define SESIMOS_CACHE_H
|
||||
|
||||
#include "uri.h"
|
||||
|
||||
@@ -46,4 +46,4 @@ int cache_filename_comp_invalid(const char *filename);
|
||||
|
||||
int uri_cache_init(http_uri *uri);
|
||||
|
||||
#endif //NECRONDA_SERVER_CACHE_H
|
||||
#endif //SESIMOS_CACHE_H
|
||||
|
@@ -1,14 +1,16 @@
|
||||
/**
|
||||
* Necronda Web Server
|
||||
* sesimos - secure, simple, modern web server
|
||||
* Compression interface
|
||||
* src/lib/compress.c
|
||||
* Lorenz Stechauner, 2021-05-05
|
||||
*/
|
||||
|
||||
#include "compress.h"
|
||||
|
||||
#include <malloc.h>
|
||||
#include <errno.h>
|
||||
|
||||
|
||||
int compress_init(compress_ctx *ctx, int mode) {
|
||||
ctx->gzip = NULL;
|
||||
ctx->brotli = NULL;
|
||||
|
@@ -1,12 +1,12 @@
|
||||
/**
|
||||
* Necronda Web Server
|
||||
* sesimos - secure, simple, modern web server
|
||||
* Compression interface (header file)
|
||||
* src/lib/compress.h
|
||||
* Lorenz Stechauner, 2021-05-05
|
||||
*/
|
||||
|
||||
#ifndef NECRONDA_SERVER_COMPRESS_H
|
||||
#define NECRONDA_SERVER_COMPRESS_H
|
||||
#ifndef SESIMOS_COMPRESS_H
|
||||
#define SESIMOS_COMPRESS_H
|
||||
|
||||
#include <zlib.h>
|
||||
#include <brotli/encode.h>
|
||||
@@ -34,4 +34,4 @@ int compress_compress_mode(compress_ctx *ctx, int mode, const char *in, unsigned
|
||||
|
||||
int compress_free(compress_ctx *ctx);
|
||||
|
||||
#endif //NECRONDA_SERVER_COMPRESS_H
|
||||
#endif //SESIMOS_COMPRESS_H
|
||||
|
@@ -1,5 +1,5 @@
|
||||
/**
|
||||
* Necronda Web Server
|
||||
* sesimos - secure, simple, modern web server
|
||||
* Configuration file loader
|
||||
* src/lib/config.c
|
||||
* Lorenz Stechauner, 2021-01-05
|
||||
@@ -7,6 +7,7 @@
|
||||
|
||||
#include "config.h"
|
||||
#include "utils.h"
|
||||
|
||||
#include <stdio.h>
|
||||
#include <sys/ipc.h>
|
||||
#include <sys/shm.h>
|
||||
@@ -14,6 +15,7 @@
|
||||
#include <errno.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
|
||||
t_config *config;
|
||||
char geoip_dir[256], dns_server[256];
|
||||
|
||||
|
@@ -1,12 +1,12 @@
|
||||
/**
|
||||
* Necronda Web Server
|
||||
* sesimos - secure, simple, modern web server
|
||||
* Configuration file loader (header file)
|
||||
* src/lib/config.h
|
||||
* Lorenz Stechauner, 2021-01-05
|
||||
*/
|
||||
|
||||
#ifndef NECRONDA_SERVER_CONFIG_H
|
||||
#define NECRONDA_SERVER_CONFIG_H
|
||||
#ifndef SESIMOS_CONFIG_H
|
||||
#define SESIMOS_CONFIG_H
|
||||
|
||||
#include "uri.h"
|
||||
|
||||
@@ -19,7 +19,7 @@
|
||||
#define CONFIG_TYPE_REVERSE_PROXY 2
|
||||
|
||||
#ifndef DEFAULT_CONFIG_FILE
|
||||
# define DEFAULT_CONFIG_FILE "/etc/necronda/server.conf"
|
||||
# define DEFAULT_CONFIG_FILE "/etc/sesimos/server.conf"
|
||||
#endif
|
||||
|
||||
|
||||
@@ -61,4 +61,4 @@ int config_load(const char *filename);
|
||||
|
||||
int config_unload();
|
||||
|
||||
#endif //NECRONDA_SERVER_CONFIG_H
|
||||
#endif //SESIMOS_CONFIG_H
|
||||
|
@@ -1,5 +1,5 @@
|
||||
/**
|
||||
* Necronda Web Server
|
||||
* sesimos - secure, simple, modern web server
|
||||
* FastCGI interface implementation
|
||||
* src/lib/fastcgi.c
|
||||
* Lorenz Stechauner, 2020-12-26
|
||||
@@ -9,11 +9,13 @@
|
||||
#include "utils.h"
|
||||
#include "compress.h"
|
||||
#include "../server.h"
|
||||
|
||||
#include <sys/un.h>
|
||||
#include <sys/socket.h>
|
||||
#include <errno.h>
|
||||
#include <string.h>
|
||||
|
||||
|
||||
char *fastcgi_add_param(char *buf, const char *key, const char *value) {
|
||||
char *ptr = buf;
|
||||
unsigned long key_len = strlen(key);
|
||||
@@ -71,8 +73,8 @@ int fastcgi_init(fastcgi_conn *conn, int mode, unsigned int client_num, unsigned
|
||||
conn->socket = fcgi_sock;
|
||||
|
||||
struct sockaddr_un sock_addr = {AF_UNIX};
|
||||
if (conn->mode == FASTCGI_NECRONDA) {
|
||||
snprintf(sock_addr.sun_path, sizeof(sock_addr.sun_path) - 1, "%s", NECRONDA_BACKEND_SOCKET);
|
||||
if (conn->mode == FASTCGI_SESIMOS) {
|
||||
snprintf(sock_addr.sun_path, sizeof(sock_addr.sun_path) - 1, "%s", SESIMOS_BACKEND_SOCKET);
|
||||
} else if (conn->mode == FASTCGI_PHP) {
|
||||
snprintf(sock_addr.sun_path, sizeof(sock_addr.sun_path) - 1, "%s", PHP_FPM_SOCKET);
|
||||
}
|
||||
@@ -342,7 +344,7 @@ int fastcgi_header(fastcgi_conn *conn, http_res *res, char *err_msg) {
|
||||
free(content);
|
||||
return 1;
|
||||
} else if (header.type == FCGI_STDERR) {
|
||||
// TODO implement Necronda backend error handling
|
||||
// TODO implement Sesimos backend error handling
|
||||
if (conn->mode == FASTCGI_PHP) {
|
||||
err = err || fastcgi_php_error(conn, content, content_len, err_msg);
|
||||
}
|
||||
@@ -385,7 +387,7 @@ int fastcgi_header(fastcgi_conn *conn, http_res *res, char *err_msg) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
ret = http_parse_header_field(&res->hdr, ptr, pos0);
|
||||
ret = http_parse_header_field(&res->hdr, ptr, pos0, 0);
|
||||
if (ret != 0) return (int) ret;
|
||||
if (pos0[2] == '\r' && pos0[3] == '\n') {
|
||||
return 0;
|
||||
@@ -483,7 +485,7 @@ int fastcgi_send(fastcgi_conn *conn, sock *client, int flags) {
|
||||
|
||||
return 0;
|
||||
} else if (header.type == FCGI_STDERR) {
|
||||
// TODO implement Necronda backend error handling
|
||||
// TODO implement Sesimos backend error handling
|
||||
if (conn->mode == FASTCGI_PHP) {
|
||||
fastcgi_php_error(conn, content, content_len, buf0);
|
||||
}
|
||||
@@ -569,7 +571,7 @@ int fastcgi_dump(fastcgi_conn *conn, char *buf, long len) {
|
||||
|
||||
return 0;
|
||||
} else if (header.type == FCGI_STDERR) {
|
||||
// TODO implement Necronda backend error handling
|
||||
// TODO implement Sesimos backend error handling
|
||||
if (conn->mode == FASTCGI_PHP) {
|
||||
fastcgi_php_error(conn, content, content_len, buf0);
|
||||
}
|
||||
|
@@ -1,12 +1,12 @@
|
||||
/**
|
||||
* Necronda Web Server
|
||||
* sesimos - secure, simple, modern web server
|
||||
* FastCGI interface implementation (header file)
|
||||
* src/lib/fastcgi.h
|
||||
* Lorenz Stechauner, 2020-12-26
|
||||
*/
|
||||
|
||||
#ifndef NECRONDA_SERVER_FASTCGI_H
|
||||
#define NECRONDA_SERVER_FASTCGI_H
|
||||
#ifndef SESIMOS_FASTCGI_H
|
||||
#define SESIMOS_FASTCGI_H
|
||||
|
||||
#include "include/fastcgi.h"
|
||||
#include "http.h"
|
||||
@@ -19,13 +19,13 @@
|
||||
#define FASTCGI_COMPRESS_HOLD 8
|
||||
|
||||
#define FASTCGI_PHP 1
|
||||
#define FASTCGI_NECRONDA 2
|
||||
#define FASTCGI_SESIMOS 2
|
||||
|
||||
#ifndef PHP_FPM_SOCKET
|
||||
# define PHP_FPM_SOCKET "/var/run/php-fpm/php-fpm.sock"
|
||||
#endif
|
||||
|
||||
#define NECRONDA_BACKEND_SOCKET "/var/run/necronda/necronda-backend.sock"
|
||||
#define SESIMOS_BACKEND_SOCKET "/var/run/sesimos/backend.sock"
|
||||
|
||||
typedef struct {
|
||||
int mode;
|
||||
@@ -54,4 +54,4 @@ int fastcgi_dump(fastcgi_conn *conn, char *buf, long len);
|
||||
|
||||
int fastcgi_receive(fastcgi_conn *conn, sock *client, unsigned long len);
|
||||
|
||||
#endif //NECRONDA_SERVER_FASTCGI_H
|
||||
#endif //SESIMOS_FASTCGI_H
|
||||
|
@@ -1,5 +1,5 @@
|
||||
/**
|
||||
* Necronda Web Server
|
||||
* sesimos - secure, simple, modern web server
|
||||
* MaxMind GeoIP Database interface
|
||||
* src/lib/geoip.c
|
||||
* Lorenz Stechauner, 2021-05-04
|
||||
@@ -7,6 +7,7 @@
|
||||
|
||||
#include "geoip.h"
|
||||
|
||||
|
||||
MMDB_entry_data_list_s *mmdb_json(MMDB_entry_data_list_s *list, char *str, long *str_off, long str_len) {
|
||||
switch (list->entry_data.type) {
|
||||
case MMDB_DATA_TYPE_MAP:
|
||||
|
@@ -1,13 +1,13 @@
|
||||
/**
|
||||
* Necronda Web Server
|
||||
* sesimos - secure, simple, modern web server
|
||||
* MaxMind GeoIP Database interface (header file)
|
||||
* src/lib/geoip.h
|
||||
* Lorenz Stechauner, 2021-05-04
|
||||
*/
|
||||
|
||||
|
||||
#ifndef NECRONDA_SERVER_GEOIP_H
|
||||
#define NECRONDA_SERVER_GEOIP_H
|
||||
#ifndef SESIMOS_GEOIP_H
|
||||
#define SESIMOS_GEOIP_H
|
||||
|
||||
#include <maxminddb.h>
|
||||
|
||||
@@ -15,4 +15,4 @@
|
||||
|
||||
MMDB_entry_data_list_s *mmdb_json(MMDB_entry_data_list_s *list, char *str, long *str_off, long str_len);
|
||||
|
||||
#endif //NECRONDA_SERVER_GEOIP_H
|
||||
#endif //SESIMOS_GEOIP_H
|
||||
|
@@ -1,5 +1,5 @@
|
||||
/**
|
||||
* Necronda Web Server
|
||||
* sesimos - secure, simple, modern web server
|
||||
* HTTP implementation
|
||||
* src/lib/http.c
|
||||
* Lorenz Stechauner, 2020-12-09
|
||||
@@ -8,8 +8,10 @@
|
||||
#include "http.h"
|
||||
#include "utils.h"
|
||||
#include "compress.h"
|
||||
|
||||
#include <string.h>
|
||||
|
||||
|
||||
void http_to_camel_case(char *str, int mode) {
|
||||
if (mode == HTTP_PRESERVE)
|
||||
return;
|
||||
@@ -48,22 +50,25 @@ const char *http_field_get_value(const http_field *field) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void http_free_field(http_field *f) {
|
||||
if (f->type == HTTP_FIELD_NORMAL) {
|
||||
f->normal.name[0] = 0;
|
||||
f->normal.value[0] = 0;
|
||||
} else if (f->type == HTTP_FIELD_EX_VALUE) {
|
||||
f->ex_value.name[0] = 0;
|
||||
free(f->ex_value.value);
|
||||
f->ex_value.value = NULL;
|
||||
} else if (f->type == HTTP_FIELD_EX_NAME) {
|
||||
free(f->ex_name.name);
|
||||
free(f->ex_name.value);
|
||||
f->ex_name.name = NULL;
|
||||
f->ex_name.value = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
void http_free_hdr(http_hdr *hdr) {
|
||||
for (int i = 0; i < hdr->field_num; i++) {
|
||||
http_field *f = &hdr->fields[i];
|
||||
if (f->type == HTTP_FIELD_NORMAL) {
|
||||
f->normal.name[0] = 0;
|
||||
f->normal.value[0] = 0;
|
||||
} else if (f->type == HTTP_FIELD_EX_VALUE) {
|
||||
f->ex_value.name[0] = 0;
|
||||
free(f->ex_value.value);
|
||||
f->ex_value.value = NULL;
|
||||
} else if (f->type == HTTP_FIELD_EX_NAME) {
|
||||
free(f->ex_name.name);
|
||||
free(f->ex_name.value);
|
||||
f->ex_name.name = NULL;
|
||||
f->ex_name.value = NULL;
|
||||
}
|
||||
http_free_field(&hdr->fields[i]);
|
||||
}
|
||||
hdr->field_num = 0;
|
||||
hdr->last_field_num = -1;
|
||||
@@ -79,7 +84,7 @@ void http_free_res(http_res *res) {
|
||||
http_free_hdr(&res->hdr);
|
||||
}
|
||||
|
||||
int http_parse_header_field(http_hdr *hdr, const char *buf, const char *end_ptr) {
|
||||
int http_parse_header_field(http_hdr *hdr, const char *buf, const char *end_ptr, int flags) {
|
||||
if (hdr->last_field_num > hdr->field_num) {
|
||||
print(ERR_STR "Unable to parse header: Invalid state" CLR_STR);
|
||||
return 3;
|
||||
@@ -112,7 +117,7 @@ int http_parse_header_field(http_hdr *hdr, const char *buf, const char *end_ptr)
|
||||
|
||||
char field_num = hdr->field_num;
|
||||
int found = http_get_header_field_num_len(hdr, buf, len1);
|
||||
if (found == -1) {
|
||||
if (!(flags & HTTP_MERGE_FIELDS) || found == -1) {
|
||||
if (http_add_header_field_len(hdr, buf, len1, pos1, len2 < 0 ? 0 : len2) != 0) {
|
||||
print(ERR_STR "Unable to parse header: Too many header fields" CLR_STR);
|
||||
return 3;
|
||||
@@ -200,7 +205,7 @@ int http_receive_request(sock *client, http_req *req) {
|
||||
sprintf(req->uri, "%.*s", (int) len, pos1);
|
||||
sprintf(req->version, "%.3s", pos2 + 5);
|
||||
} else {
|
||||
int ret = http_parse_header_field(&req->hdr, ptr, pos0);
|
||||
int ret = http_parse_header_field(&req->hdr, ptr, pos0, HTTP_MERGE_FIELDS);
|
||||
if (ret != 0) return ret;
|
||||
}
|
||||
ptr = pos0 + 2;
|
||||
@@ -326,6 +331,7 @@ void http_remove_header_field(http_hdr *hdr, const char *field_name, int mode) {
|
||||
strcpy(field_name_2, http_field_get_name(&hdr->fields[i]));
|
||||
http_to_camel_case(field_name_2, HTTP_LOWER);
|
||||
if (strcmp(field_name_1, field_name_2) == 0) {
|
||||
http_free_field(&hdr->fields[i]);
|
||||
memmove(&hdr->fields[i], &hdr->fields[i + 1], sizeof(hdr->fields[0]) * (hdr->field_num - i));
|
||||
hdr->field_num--;
|
||||
if (mode == HTTP_REMOVE_ALL) {
|
||||
|
@@ -1,12 +1,12 @@
|
||||
/**
|
||||
* Necronda Web Server
|
||||
* sesimos - secure, simple, modern web server
|
||||
* HTTP implementation (header file)
|
||||
* src/lib/http.h
|
||||
* Lorenz Stechauner, 2020-12-09
|
||||
*/
|
||||
|
||||
#ifndef NECRONDA_SERVER_HTTP_H
|
||||
#define NECRONDA_SERVER_HTTP_H
|
||||
#ifndef SESIMOS_HTTP_H
|
||||
#define SESIMOS_HTTP_H
|
||||
|
||||
#include "sock.h"
|
||||
|
||||
@@ -22,6 +22,8 @@
|
||||
#define HTTP_FIELD_EX_VALUE 1
|
||||
#define HTTP_FIELD_EX_NAME 2
|
||||
|
||||
#define HTTP_MERGE_FIELDS 1
|
||||
|
||||
#define HTTP_1XX_STR "\x1B[1;32m"
|
||||
#define HTTP_2XX_STR "\x1B[1;32m"
|
||||
#define HTTP_3XX_STR "\x1B[1;33m"
|
||||
@@ -37,11 +39,11 @@
|
||||
#define HTTP_MAX_HEADER_FIELD_NUM 64
|
||||
|
||||
#ifndef SERVER_STR
|
||||
# define SERVER_STR "Necronda"
|
||||
# define SERVER_STR "Sesimos"
|
||||
#endif
|
||||
|
||||
#ifndef SERVER_STR_HTML
|
||||
# define SERVER_STR_HTML "Necronda web server"
|
||||
# define SERVER_STR_HTML "Sesimos web server"
|
||||
#endif
|
||||
|
||||
typedef struct {
|
||||
@@ -106,6 +108,7 @@ typedef enum {
|
||||
typedef struct {
|
||||
unsigned short status;
|
||||
http_error_origin origin;
|
||||
const char* ws_key;
|
||||
} http_status_ctx;
|
||||
|
||||
extern const http_status http_statuses[];
|
||||
@@ -130,6 +133,8 @@ const char *http_field_get_name(const http_field *field);
|
||||
|
||||
const char *http_field_get_value(const http_field *field);
|
||||
|
||||
void http_free_field(http_field *f);
|
||||
|
||||
void http_free_hdr(http_hdr *hdr);
|
||||
|
||||
void http_free_req(http_req *req);
|
||||
@@ -138,7 +143,7 @@ void http_free_res(http_res *res);
|
||||
|
||||
int http_receive_request(sock *client, http_req *req);
|
||||
|
||||
int http_parse_header_field(http_hdr *hdr, const char *buf, const char *end_ptr) ;
|
||||
int http_parse_header_field(http_hdr *hdr, const char *buf, const char *end_ptr, int flags);
|
||||
|
||||
const char *http_get_header_field(const http_hdr *hdr, const char *field_name);
|
||||
|
||||
@@ -174,4 +179,4 @@ const http_doc_info *http_get_status_info(const http_status *status);
|
||||
|
||||
int http_get_compression(const http_req *req, const http_res *res);
|
||||
|
||||
#endif //NECRONDA_SERVER_HTTP_H
|
||||
#endif //SESIMOS_HTTP_H
|
||||
|
@@ -1,13 +1,14 @@
|
||||
/**
|
||||
* Necronda Web Server
|
||||
* sesimos - secure, simple, modern web server
|
||||
* HTTP static implementation
|
||||
* src/lib/http_static.c
|
||||
* Lorenz Stechauner, 2021-05-03
|
||||
*/
|
||||
|
||||
#include "../necronda.h"
|
||||
#include "../defs.h"
|
||||
#include "http.h"
|
||||
|
||||
|
||||
const http_status http_statuses[] = {
|
||||
{100, "Informational", "Continue"},
|
||||
{101, "Informational", "Switching Protocols"},
|
||||
|
@@ -1,12 +1,12 @@
|
||||
/**
|
||||
* Necronda Web Server
|
||||
* sesimos - secure, simple, modern web server
|
||||
* FastCGI header file
|
||||
* src/lib/include/fastcgi.h
|
||||
* Lorenz Stechauner, 2021-05-03
|
||||
*/
|
||||
|
||||
#ifndef NECRONDA_SERVER_EXTERN_FASTCGI_H
|
||||
#define NECRONDA_SERVER_EXTERN_FASTCGI_H
|
||||
#ifndef SESIMOS_EXTERN_FASTCGI_H
|
||||
#define SESIMOS_EXTERN_FASTCGI_H
|
||||
|
||||
/*
|
||||
* Listening socket file number
|
||||
@@ -119,4 +119,4 @@ typedef struct {
|
||||
FCGI_UnknownTypeBody body;
|
||||
} FCGI_UnknownTypeRecord;
|
||||
|
||||
#endif //NECRONDA_SERVER_EXTERN_FASTCGI_H
|
||||
#endif //SESIMOS_EXTERN_FASTCGI_H
|
||||
|
@@ -1,14 +1,16 @@
|
||||
/**
|
||||
* Necronda Web Server
|
||||
* sesimos - secure, simple, modern web server
|
||||
* Reverse proxy
|
||||
* src/lib/rev_proxy.c
|
||||
* Lorenz Stechauner, 2021-01-07
|
||||
*/
|
||||
|
||||
#include "../defs.h"
|
||||
#include "../server.h"
|
||||
#include "rev_proxy.h"
|
||||
#include "utils.h"
|
||||
#include "compress.h"
|
||||
#include "../server.h"
|
||||
|
||||
#include <openssl/ssl.h>
|
||||
#include <string.h>
|
||||
#include <errno.h>
|
||||
@@ -16,6 +18,7 @@
|
||||
#include <arpa/inet.h>
|
||||
#include <sys/time.h>
|
||||
|
||||
|
||||
sock rev_proxy;
|
||||
char *rev_proxy_host = NULL;
|
||||
struct timeval server_timeout = {.tv_sec = SERVER_TIMEOUT, .tv_usec = 0};
|
||||
@@ -29,11 +32,8 @@ int rev_proxy_preload() {
|
||||
}
|
||||
|
||||
int rev_proxy_request_header(http_req *req, int enc) {
|
||||
char buf1[256];
|
||||
char buf2[256];
|
||||
char buf1[256], buf2[256];
|
||||
int p_len;
|
||||
http_remove_header_field(&req->hdr, "Connection", HTTP_REMOVE_ALL);
|
||||
http_add_header_field(&req->hdr, "Connection", "keep-alive");
|
||||
|
||||
const char *via = http_get_header_field(&req->hdr, "Via");
|
||||
sprintf(buf1, "HTTP/%s %s", req->version, SERVER_NAME);
|
||||
@@ -52,7 +52,7 @@ int rev_proxy_request_header(http_req *req, int enc) {
|
||||
const char *host = http_get_header_field(&req->hdr, "Host");
|
||||
const char *forwarded = http_get_header_field(&req->hdr, "Forwarded");
|
||||
int client_ipv6 = strchr(client_addr_str, ':') != NULL;
|
||||
int server_ipv6 = strchr(server_addr_str, ':') != NULL;
|
||||
int server_ipv6 = strchr(server_addr_str, ':') != NULL;
|
||||
|
||||
p_len = snprintf(buf1, sizeof(buf1), "by=%s%s%s;for=%s%s%s;host=%s;proto=%s",
|
||||
server_ipv6 ? "\"[" : "", server_addr_str, server_ipv6 ? "]\"" : "",
|
||||
@@ -62,6 +62,7 @@ int rev_proxy_request_header(http_req *req, int enc) {
|
||||
print(ERR_STR "Appended part of header field 'Forwarded' too long" CLR_STR);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (forwarded == NULL) {
|
||||
http_add_header_field(&req->hdr, "Forwarded", buf1);
|
||||
} else {
|
||||
@@ -129,8 +130,7 @@ int rev_proxy_request_header(http_req *req, int enc) {
|
||||
}
|
||||
|
||||
int rev_proxy_response_header(http_req *req, http_res *res, host_config *conf) {
|
||||
char buf1[256];
|
||||
char buf2[256];
|
||||
char buf1[256], buf2[256];
|
||||
int p_len;
|
||||
|
||||
const char *via = http_get_header_field(&res->hdr, "Via");
|
||||
@@ -172,24 +172,23 @@ int rev_proxy_response_header(http_req *req, http_res *res, host_config *conf) {
|
||||
|
||||
if (0) {
|
||||
match:
|
||||
strcpy(buf1, location + p_len - 1);
|
||||
http_remove_header_field(&res->hdr, "Location", HTTP_REMOVE_ALL);
|
||||
http_add_header_field(&res->hdr, "Location", location + p_len - 1);
|
||||
http_add_header_field(&res->hdr, "Location", buf1);
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int rev_proxy_init(http_req *req, http_res *res, http_status_ctx *ctx, host_config *conf, sock *client,
|
||||
http_status *custom_status, char *err_msg) {
|
||||
int rev_proxy_init(http_req *req, http_res *res, http_status_ctx *ctx, host_config *conf, sock *client, http_status *custom_status, char *err_msg) {
|
||||
char buffer[CHUNK_SIZE];
|
||||
const char *connection, *upgrade, *ws_version;
|
||||
long ret;
|
||||
int tries = 0;
|
||||
int retry = 0;
|
||||
int tries = 0, retry = 0;
|
||||
|
||||
if (rev_proxy.socket != 0 && strcmp(rev_proxy_host, conf->name) == 0 && sock_check(&rev_proxy) == 0) {
|
||||
if (rev_proxy.socket != 0 && strcmp(rev_proxy_host, conf->name) == 0 && sock_check(&rev_proxy) == 0)
|
||||
goto rev_proxy;
|
||||
}
|
||||
|
||||
retry:
|
||||
if (rev_proxy.socket != 0) {
|
||||
@@ -290,6 +289,22 @@ int rev_proxy_init(http_req *req, http_res *res, http_status_ctx *ctx, host_conf
|
||||
print(BLUE_STR "Established new connection with " BLD_STR "[%s]:%i" CLR_STR, buffer, conf->rev_proxy.port);
|
||||
|
||||
rev_proxy:
|
||||
connection = http_get_header_field(&req->hdr, "Connection");
|
||||
if (connection != NULL && (strstr(connection, "upgrade") != NULL || strstr(connection, "Upgrade") != NULL)) {
|
||||
upgrade = http_get_header_field(&req->hdr, "Upgrade");
|
||||
ws_version = http_get_header_field(&req->hdr, "Sec-WebSocket-Version");
|
||||
if (upgrade != NULL && ws_version != NULL && strcmp(upgrade, "websocket") == 0 && strcmp(ws_version, "13") == 0) {
|
||||
ctx->ws_key = http_get_header_field(&req->hdr, "Sec-WebSocket-Key");
|
||||
} else {
|
||||
res->status = http_get_status(501);
|
||||
ctx->origin = INTERNAL;
|
||||
return -1;
|
||||
}
|
||||
} else {
|
||||
http_remove_header_field(&req->hdr, "Connection", HTTP_REMOVE_ALL);
|
||||
http_add_header_field(&req->hdr, "Connection", "keep-alive");
|
||||
}
|
||||
|
||||
ret = rev_proxy_request_header(req, (int) client->enc);
|
||||
if (ret != 0) {
|
||||
res->status = http_get_status(500);
|
||||
@@ -423,7 +438,7 @@ int rev_proxy_init(http_req *req, http_res *res, http_status_ctx *ctx, host_conf
|
||||
goto proxy_err;
|
||||
}
|
||||
} else {
|
||||
ret = http_parse_header_field(&res->hdr, ptr, pos0);
|
||||
ret = http_parse_header_field(&res->hdr, ptr, pos0, 0);
|
||||
if (ret != 0) {
|
||||
res->status = http_get_status(502);
|
||||
ctx->origin = SERVER_RES;
|
||||
@@ -454,14 +469,9 @@ int rev_proxy_init(http_req *req, http_res *res, http_status_ctx *ctx, host_conf
|
||||
}
|
||||
|
||||
int rev_proxy_send(sock *client, unsigned long len_to_send, int flags) {
|
||||
// TODO handle websockets
|
||||
long ret = 0;
|
||||
char buffer[CHUNK_SIZE];
|
||||
char comp_out[CHUNK_SIZE];
|
||||
char buf[256];
|
||||
long len, snd_len;
|
||||
char buffer[CHUNK_SIZE], comp_out[CHUNK_SIZE], buf[256], *ptr;
|
||||
long ret = 0, len, snd_len;
|
||||
int finish_comp = 0;
|
||||
char *ptr;
|
||||
|
||||
compress_ctx comp_ctx;
|
||||
if (flags & REV_PROXY_COMPRESS_BR) {
|
||||
|
@@ -1,12 +1,12 @@
|
||||
/**
|
||||
* Necronda Web Server
|
||||
* sesimos - secure, simple, modern web server
|
||||
* Reverse proxy (header file)
|
||||
* src/lib/rev_proxy.h
|
||||
* Lorenz Stechauner, 2021-01-07
|
||||
*/
|
||||
|
||||
#ifndef NECRONDA_SERVER_REV_PROXY_H
|
||||
#define NECRONDA_SERVER_REV_PROXY_H
|
||||
#ifndef SESIMOS_REV_PROXY_H
|
||||
#define SESIMOS_REV_PROXY_H
|
||||
|
||||
#define REV_PROXY_CHUNKED 1
|
||||
#define REV_PROXY_COMPRESS_GZ 2
|
||||
@@ -35,4 +35,4 @@ int rev_proxy_send(sock *client, unsigned long len_to_send, int flags);
|
||||
|
||||
int rev_proxy_dump(char *buf, long len);
|
||||
|
||||
#endif //NECRONDA_SERVER_REV_PROXY_H
|
||||
#endif //SESIMOS_REV_PROXY_H
|
||||
|
@@ -1,16 +1,19 @@
|
||||
/**
|
||||
* Necronda Web Server
|
||||
* sesimos - secure, simple, modern web server
|
||||
* Basic TCP and TLS socket
|
||||
* src/lib/sock.c
|
||||
* Lorenz Stechauner, 2021-01-07
|
||||
*/
|
||||
|
||||
#include "sock.h"
|
||||
|
||||
#include <openssl/err.h>
|
||||
#include <openssl/ssl.h>
|
||||
#include <string.h>
|
||||
#include <sys/socket.h>
|
||||
#include <unistd.h>
|
||||
#include <poll.h>
|
||||
|
||||
|
||||
int sock_enc_error(sock *s) {
|
||||
return (int) s->enc ? SSL_get_error(s->ssl, (int) s->_last_ret) : 0;
|
||||
@@ -116,3 +119,29 @@ int sock_check(sock *s) {
|
||||
char buf;
|
||||
return recv(s->socket, &buf, 1, MSG_PEEK | MSG_DONTWAIT) == 1;
|
||||
}
|
||||
|
||||
int sock_poll(sock *sockets[], sock *ready[], short events, int n_sock, int timeout_ms) {
|
||||
struct pollfd fds[n_sock];
|
||||
for (int i = 0; i < n_sock; i++) {
|
||||
fds[i].fd = sockets[i]->socket;
|
||||
fds[i].events = events;
|
||||
}
|
||||
|
||||
int ret = poll(fds, n_sock, timeout_ms);
|
||||
if (ret < 0 || ready == NULL) return ret;
|
||||
|
||||
int j = 0;
|
||||
for (int i = 0; i < n_sock; i++) {
|
||||
if (fds[i].revents & events)
|
||||
ready[j++] = sockets[i];
|
||||
}
|
||||
return j;
|
||||
}
|
||||
|
||||
int sock_poll_read(sock *sockets[], sock *readable[], int n_sock, int timeout_ms) {
|
||||
return sock_poll(sockets, readable, POLLIN, n_sock, timeout_ms);
|
||||
}
|
||||
|
||||
int sock_poll_write(sock *sockets[], sock *writable[], int n_sock, int timeout_ms) {
|
||||
return sock_poll(sockets, writable, POLLOUT, n_sock, timeout_ms);
|
||||
}
|
||||
|
@@ -1,14 +1,15 @@
|
||||
/**
|
||||
* Necronda Web Server
|
||||
* sesimos - secure, simple, modern web server
|
||||
* Basic TCP and TLS socket (header file)
|
||||
* src/lib/sock.h
|
||||
* Lorenz Stechauner, 2021-01-07
|
||||
*/
|
||||
|
||||
#ifndef NECRONDA_SERVER_SOCK_H
|
||||
#define NECRONDA_SERVER_SOCK_H
|
||||
#ifndef SESIMOS_SOCK_H
|
||||
#define SESIMOS_SOCK_H
|
||||
|
||||
#include <openssl/crypto.h>
|
||||
#include <sys/socket.h>
|
||||
|
||||
typedef struct {
|
||||
unsigned int enc:1;
|
||||
@@ -37,4 +38,10 @@ int sock_close(sock *s);
|
||||
|
||||
int sock_check(sock *s);
|
||||
|
||||
#endif //NECRONDA_SERVER_SOCK_H
|
||||
int sock_poll(sock *sockets[], sock *readable[], short events, int n_sock, int timeout_ms);
|
||||
|
||||
int sock_poll_read(sock *sockets[], sock *readable[], int n_sock, int timeout_ms);
|
||||
|
||||
int sock_poll_write(sock *sockets[], sock *writable[], int n_sock, int timeout_ms);
|
||||
|
||||
#endif //SESIMOS_SOCK_H
|
||||
|
@@ -1,5 +1,5 @@
|
||||
/**
|
||||
* Necronda Web Server
|
||||
* sesimos - secure, simple, modern web server
|
||||
* URI and path handlers
|
||||
* src/lib/uri.c
|
||||
* Lorenz Stechauner, 2020-12-13
|
||||
@@ -7,9 +7,11 @@
|
||||
|
||||
#include "uri.h"
|
||||
#include "utils.h"
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
|
||||
int path_is_directory(const char *path) {
|
||||
struct stat statbuf;
|
||||
return stat(path, &statbuf) == 0 && S_ISDIR(statbuf.st_mode) != 0;
|
||||
|
@@ -1,12 +1,12 @@
|
||||
/**
|
||||
* Necronda Web Server
|
||||
* sesimos - secure, simple, modern web server
|
||||
* URI and path handlers (header file)
|
||||
* src/lib/uri.h
|
||||
* Lorenz Stechauner, 2020-12-13
|
||||
*/
|
||||
|
||||
#ifndef NECRONDA_SERVER_URI_H
|
||||
#define NECRONDA_SERVER_URI_H
|
||||
#ifndef SESIMOS_URI_H
|
||||
#define SESIMOS_URI_H
|
||||
|
||||
#include <sys/stat.h>
|
||||
|
||||
@@ -44,4 +44,4 @@ int uri_init_cache(http_uri *uri);
|
||||
|
||||
void uri_free(http_uri *uri);
|
||||
|
||||
#endif //NECRONDA_SERVER_URI_H
|
||||
#endif //SESIMOS_URI_H
|
||||
|
@@ -1,15 +1,17 @@
|
||||
/**
|
||||
* Necronda Web Server
|
||||
* sesimos - secure, simple, modern web server
|
||||
* Utilities
|
||||
* src/lib/utils.c
|
||||
* Lorenz Stechauner, 2020-12-03
|
||||
*/
|
||||
|
||||
#include "utils.h"
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
|
||||
char *log_prefix;
|
||||
|
||||
char *format_duration(unsigned long micros, char *buf) {
|
||||
@@ -124,7 +126,6 @@ int mime_is_compressible(const char *type) {
|
||||
strcmp(type_parsed, "application/vnd.ms-fontobject") == 0 ||
|
||||
strcmp(type_parsed, "application/x-font-ttf") == 0 ||
|
||||
strcmp(type_parsed, "application/x-javascript") == 0 ||
|
||||
strcmp(type_parsed, "application/x-web-app-manifest+json") == 0 ||
|
||||
strcmp(type_parsed, "font/eot") == 0 ||
|
||||
strcmp(type_parsed, "font/opentype") == 0 ||
|
||||
strcmp(type_parsed, "image/bmp") == 0 ||
|
||||
@@ -173,3 +174,25 @@ int str_trim_lws(char **start, char **end) {
|
||||
(*end)++;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int base64_encode(void *data, unsigned long data_len, char *output, unsigned long *output_len) {
|
||||
unsigned long out_len = 4 * ((data_len + 2) / 3);
|
||||
if (output_len != NULL) *output_len = out_len;
|
||||
|
||||
for (int i = 0, j = 0; i < data_len;) {
|
||||
unsigned int octet_a = (i < data_len) ? ((unsigned char *) data)[i++] : 0;
|
||||
unsigned int octet_b = (i < data_len) ? ((unsigned char *) data)[i++] : 0;
|
||||
unsigned int octet_c = (i < data_len) ? ((unsigned char *) data)[i++] : 0;
|
||||
unsigned int triple = (octet_a << 0x10) + (octet_b << 0x08) + octet_c;
|
||||
output[j++] = base64_encode_table[(triple >> 3 * 6) & 0x3F];
|
||||
output[j++] = base64_encode_table[(triple >> 2 * 6) & 0x3F];
|
||||
output[j++] = base64_encode_table[(triple >> 1 * 6) & 0x3F];
|
||||
output[j++] = base64_encode_table[(triple >> 0 * 6) & 0x3F];
|
||||
}
|
||||
|
||||
for (int i = 0; i < base64_mod_table[data_len % 3]; i++)
|
||||
output[out_len - 1 - i] = '=';
|
||||
output[out_len] = 0;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@@ -1,12 +1,12 @@
|
||||
/**
|
||||
* Necronda Web Server
|
||||
* sesimos - secure, simple, modern web server
|
||||
* Utilities (header file)
|
||||
* src/lib/utils.h
|
||||
* Lorenz Stechauner, 2020-12-03
|
||||
*/
|
||||
|
||||
#ifndef NECRONDA_SERVER_UTILS_H
|
||||
#define NECRONDA_SERVER_UTILS_H
|
||||
#ifndef SESIMOS_UTILS_H
|
||||
#define SESIMOS_UTILS_H
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
@@ -20,6 +20,10 @@
|
||||
|
||||
extern char *log_prefix;
|
||||
|
||||
static const char base64_encode_table[64] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
|
||||
static const int base64_mod_table[3] = {0, 2, 1};
|
||||
|
||||
|
||||
#define out_1(fmt) fprintf(stdout, "%s" fmt "\n", log_prefix)
|
||||
#define out_2(fmt, args...) fprintf(stdout, "%s" fmt "\n", log_prefix, args)
|
||||
|
||||
@@ -46,4 +50,6 @@ int str_trim(char **start, char **end);
|
||||
|
||||
int str_trim_lws(char **start, char **end);
|
||||
|
||||
#endif //NECRONDA_SERVER_UTILS_H
|
||||
int base64_encode(void *data, unsigned long data_len, char *output, unsigned long *output_len);
|
||||
|
||||
#endif //SESIMOS_UTILS_H
|
||||
|
201
src/lib/websocket.c
Normal file
201
src/lib/websocket.c
Normal file
@@ -0,0 +1,201 @@
|
||||
/**
|
||||
* sesimos - secure, simple, modern web server
|
||||
* WebSocket reverse proxy
|
||||
* src/lib/websocket.c
|
||||
* Lorenz Stechauner, 2022-08-16
|
||||
*/
|
||||
|
||||
#include "../defs.h"
|
||||
#include "websocket.h"
|
||||
#include "utils.h"
|
||||
|
||||
#include <string.h>
|
||||
#include <openssl/sha.h>
|
||||
#include <errno.h>
|
||||
#include <signal.h>
|
||||
|
||||
|
||||
int terminate = 0;
|
||||
|
||||
void ws_terminate() {
|
||||
terminate = 1;
|
||||
}
|
||||
|
||||
int ws_calc_accept_key(const char *key, char *accept_key) {
|
||||
if (key == NULL || accept_key == NULL)
|
||||
return -1;
|
||||
|
||||
char input[256] = "";
|
||||
unsigned char output[SHA_DIGEST_LENGTH];
|
||||
strcat(input, key);
|
||||
strcat(input, ws_key_uuid);
|
||||
|
||||
if (SHA1((unsigned char *) input, strlen(input), output) == NULL) {
|
||||
return -2;
|
||||
}
|
||||
|
||||
base64_encode(output, sizeof(output), accept_key, NULL);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int ws_recv_frame_header(sock *s, ws_frame *frame) {
|
||||
unsigned char buf[12];
|
||||
|
||||
long ret = sock_recv(s, buf, 2, 0);
|
||||
if (ret < 0) {
|
||||
print(ERR_STR "Unable to receive from socket: %s" CLR_STR, strerror(errno));
|
||||
return -1;
|
||||
} else if (ret != 2) {
|
||||
print(ERR_STR "Unable to receive 2 bytes from socket" CLR_STR);
|
||||
return -2;
|
||||
}
|
||||
|
||||
unsigned short bits = (buf[0] << 8) | buf[1];
|
||||
frame->f_fin = (bits >> 15) & 1;
|
||||
frame->f_rsv1 = (bits >> 14) & 1;
|
||||
frame->f_rsv2 = (bits >> 13) & 1;
|
||||
frame->f_rsv3 = (bits >> 12) & 1;
|
||||
frame->opcode = (bits >> 8) & 0xF;
|
||||
frame->f_mask = (bits >> 7) & 1;
|
||||
unsigned short len = (bits & 0x7F);
|
||||
|
||||
int remaining = frame->f_mask ? 4 : 0;
|
||||
if (len == 126) {
|
||||
remaining += 2;
|
||||
} else if (len == 127) {
|
||||
remaining += 8;
|
||||
}
|
||||
|
||||
ret = sock_recv(s, buf, remaining, 0);
|
||||
if (ret < 0) {
|
||||
print(ERR_STR "Unable to receive from socket: %s" CLR_STR, strerror(errno));
|
||||
return -1;
|
||||
} else if (ret != remaining) {
|
||||
print(ERR_STR "Unable to receive correct number of bytes from socket" CLR_STR);
|
||||
return -2;
|
||||
}
|
||||
|
||||
if (len == 126) {
|
||||
frame->len = (((unsigned long) buf[0]) << 8) | ((unsigned long) buf[1]);
|
||||
} else if (len == 127) {
|
||||
frame->len =
|
||||
(((unsigned long) buf[0]) << 56) |
|
||||
(((unsigned long) buf[1]) << 48) |
|
||||
(((unsigned long) buf[2]) << 40) |
|
||||
(((unsigned long) buf[3]) << 32) |
|
||||
(((unsigned long) buf[4]) << 24) |
|
||||
(((unsigned long) buf[5]) << 16) |
|
||||
(((unsigned long) buf[6]) << 8) |
|
||||
(((unsigned long) buf[7]) << 0);
|
||||
} else {
|
||||
frame->len = len;
|
||||
}
|
||||
|
||||
if (frame->f_mask) memcpy(frame->masking_key, buf + (remaining - 4), 4);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int ws_send_frame_header(sock *s, ws_frame *frame) {
|
||||
unsigned char buf[14], *ptr = buf;
|
||||
|
||||
unsigned short len;
|
||||
if (frame->len > 0x7FFF) {
|
||||
len = 127;
|
||||
} else if (frame->len > 125) {
|
||||
len = 126;
|
||||
} else {
|
||||
len = frame->len;
|
||||
}
|
||||
|
||||
unsigned short bits =
|
||||
(frame->f_fin << 15) |
|
||||
(frame->f_rsv1 << 14) |
|
||||
(frame->f_rsv2 << 13) |
|
||||
(frame->f_rsv3 << 12) |
|
||||
(frame->opcode << 8) |
|
||||
(frame->f_mask << 7) |
|
||||
len;
|
||||
|
||||
ptr++[0] = bits >> 8;
|
||||
ptr++[0] = bits & 0xFF;
|
||||
|
||||
if (len >= 126) {
|
||||
for (int i = (len == 126 ? 2 : 8) - 1; i >= 0; i--)
|
||||
ptr++[0] = (unsigned char) ((frame->len >> (i * 8)) & 0xFF);
|
||||
}
|
||||
|
||||
if (frame->f_mask) {
|
||||
memcpy(ptr, frame->masking_key, 4);
|
||||
ptr += 4;
|
||||
}
|
||||
|
||||
long ret = sock_send(s, buf, ptr - buf, frame->len != 0 ? MSG_MORE : 0);
|
||||
if (ret < 0) {
|
||||
print(ERR_STR "Unable to send to socket: %s" CLR_STR, strerror(errno));
|
||||
return -1;
|
||||
} else if (ret != ptr - buf) {
|
||||
print(ERR_STR "Unable to send to socket" CLR_STR);
|
||||
return -2;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int ws_handle_connection(sock *s1, sock *s2) {
|
||||
sock *poll_socks[2] = {s1, s2};
|
||||
sock *readable[2];
|
||||
int n_sock = 2;
|
||||
ws_frame frame;
|
||||
char buf[CHUNK_SIZE];
|
||||
int poll, closes = 0;
|
||||
long ret;
|
||||
|
||||
signal(SIGINT, ws_terminate);
|
||||
signal(SIGTERM, ws_terminate);
|
||||
|
||||
while (!terminate && closes != 3) {
|
||||
poll = sock_poll_read(poll_socks, readable, n_sock, WS_TIMEOUT * 1000);
|
||||
if (terminate) {
|
||||
break;
|
||||
} else if (poll < 0) {
|
||||
print(ERR_STR "Unable to poll sockets: %s" CLR_STR, strerror(errno));
|
||||
return -1;
|
||||
} else if (poll == 0) {
|
||||
print(ERR_STR "Connection timed out" CLR_STR);
|
||||
return -2;
|
||||
}
|
||||
|
||||
for (int i = 0; i < poll; i++) {
|
||||
sock *s = readable[i];
|
||||
sock *o = (s == s1) ? s2 : s1;
|
||||
if (ws_recv_frame_header(s, &frame) != 0) return -3;
|
||||
|
||||
if (frame.opcode == 0x8) {
|
||||
n_sock--;
|
||||
if (s == s1) {
|
||||
poll_socks[0] = s2;
|
||||
closes |= 1;
|
||||
} else {
|
||||
closes |= 2;
|
||||
}
|
||||
}
|
||||
|
||||
if (ws_send_frame_header(o, &frame) != 0) return -3;
|
||||
|
||||
if (frame.len > 0) {
|
||||
ret = sock_splice(o, s, buf, sizeof(buf), frame.len);
|
||||
if (ret < 0) {
|
||||
print(ERR_STR "Unable to forward data in WebSocket: %s" CLR_STR, strerror(errno));
|
||||
return -3;
|
||||
} else if (ret != frame.len) {
|
||||
print(ERR_STR "Unable to forward correct number of bytes in WebSocket" CLR_STR);
|
||||
return -3;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
36
src/lib/websocket.h
Normal file
36
src/lib/websocket.h
Normal file
@@ -0,0 +1,36 @@
|
||||
/**
|
||||
* sesimos - secure, simple, modern web server
|
||||
* WebSocket reverse proxy (header file)
|
||||
* src/lib/websocket.h
|
||||
* Lorenz Stechauner, 2022-08-16
|
||||
*/
|
||||
|
||||
#ifndef SESIMOS_WEBSOCKET_H
|
||||
#define SESIMOS_WEBSOCKET_H
|
||||
|
||||
#include "sock.h"
|
||||
|
||||
#define WS_TIMEOUT 3600
|
||||
|
||||
const char *ws_key_uuid = "258EAFA5-E914-47DA-95CA-C5AB0DC85B11";
|
||||
|
||||
typedef struct {
|
||||
unsigned char f_fin:1;
|
||||
unsigned char f_rsv1:1;
|
||||
unsigned char f_rsv2:1;
|
||||
unsigned char f_rsv3:1;
|
||||
unsigned char opcode:4;
|
||||
unsigned char f_mask:1;
|
||||
unsigned long len;
|
||||
char masking_key[4];
|
||||
} ws_frame;
|
||||
|
||||
int ws_calc_accept_key(const char *key, char *accept_key);
|
||||
|
||||
int ws_recv_frame_header(sock *s, ws_frame *frame);
|
||||
|
||||
int ws_send_frame_header(sock *s, ws_frame *frame);
|
||||
|
||||
int ws_handle_connection(sock *s1, sock *s2);
|
||||
|
||||
#endif //SESIMOS_WEBSOCKET_H
|
@@ -1,23 +0,0 @@
|
||||
/**
|
||||
* Necronda Web Server
|
||||
* Definitions
|
||||
* src/necronda.h
|
||||
* Lorenz Stechauner, 2021-05-04
|
||||
*/
|
||||
|
||||
#ifndef NECRONDA_SERVER_NECRONDA_H
|
||||
#define NECRONDA_SERVER_NECRONDA_H
|
||||
|
||||
#define NECRONDA_VERSION "4.5"
|
||||
#define SERVER_STR "Necronda/" NECRONDA_VERSION
|
||||
#define SERVER_STR_HTML "Necronda web server " NECRONDA_VERSION
|
||||
|
||||
#ifndef DEFAULT_HOST
|
||||
# define DEFAULT_HOST "www.necronda.net"
|
||||
#endif
|
||||
|
||||
#ifndef SERVER_NAME
|
||||
# define SERVER_NAME DEFAULT_HOST
|
||||
#endif
|
||||
|
||||
#endif //NECRONDA_SERVER_NECRONDA_H
|
34
src/server.c
34
src/server.c
@@ -1,13 +1,13 @@
|
||||
/**
|
||||
* Necronda Web Server
|
||||
* Sesimos - secure, simple, modern web server
|
||||
* Main executable
|
||||
* src/necronda-server.c
|
||||
* src/server.c
|
||||
* Lorenz Stechauner, 2020-12-03
|
||||
*/
|
||||
|
||||
#define _POSIX_C_SOURCE 199309L
|
||||
|
||||
#include "necronda.h"
|
||||
#include "defs.h"
|
||||
#include "server.h"
|
||||
#include "client.h"
|
||||
|
||||
@@ -22,7 +22,7 @@
|
||||
#include <sys/socket.h>
|
||||
#include <signal.h>
|
||||
#include <unistd.h>
|
||||
#include <sys/select.h>
|
||||
#include <poll.h>
|
||||
#include <string.h>
|
||||
#include <errno.h>
|
||||
#include <arpa/inet.h>
|
||||
@@ -34,6 +34,7 @@
|
||||
#include <openssl/conf.h>
|
||||
#include <dirent.h>
|
||||
|
||||
|
||||
int active = 1;
|
||||
const char *config_file;
|
||||
int sockets[NUM_SOCKETS];
|
||||
@@ -153,8 +154,7 @@ void terminate() {
|
||||
|
||||
int main(int argc, const char *argv[]) {
|
||||
const int YES = 1;
|
||||
fd_set socket_fds, read_socket_fds;
|
||||
int max_socket_fd = 0;
|
||||
struct pollfd poll_fds[NUM_SOCKETS];
|
||||
int ready_sockets_num;
|
||||
long client_num = 0;
|
||||
char buf[1024];
|
||||
@@ -169,8 +169,6 @@ int main(int argc, const char *argv[]) {
|
||||
memset(children, 0, sizeof(children));
|
||||
memset(mmdbs, 0, sizeof(mmdbs));
|
||||
|
||||
struct timeval timeout;
|
||||
|
||||
const struct sockaddr_in6 addresses[2] = {
|
||||
{.sin6_family = AF_INET6, .sin6_addr = IN6ADDR_ANY_INIT, .sin6_port = htons(80)},
|
||||
{.sin6_family = AF_INET6, .sin6_addr = IN6ADDR_ANY_INIT, .sin6_port = htons(443)}
|
||||
@@ -180,7 +178,7 @@ int main(int argc, const char *argv[]) {
|
||||
fprintf(stderr, ERR_STR "Unable to set stdout to line-buffered mode: %s" CLR_STR, strerror(errno));
|
||||
return 1;
|
||||
}
|
||||
printf("Necronda Web Server " NECRONDA_VERSION "\n");
|
||||
printf("Sesimos web server " SERVER_VERSION "\n");
|
||||
|
||||
ret = config_init();
|
||||
if (ret != 0) {
|
||||
@@ -191,7 +189,7 @@ int main(int argc, const char *argv[]) {
|
||||
for (int i = 1; i < argc; i++) {
|
||||
const char *arg = argv[i];
|
||||
if (strcmp(arg, "-h") == 0 || strcmp(arg, "--help") == 0) {
|
||||
printf("Usage: necronda-server [-h] [-c <CONFIG-FILE>]\n"
|
||||
printf("Usage: sesimos [-h] [-c <CONFIG-FILE>]\n"
|
||||
"\n"
|
||||
"Options:\n"
|
||||
" -c, --config <CONFIG-FILE> path to the config file. If not provided, default will be used\n"
|
||||
@@ -338,29 +336,23 @@ int main(int argc, const char *argv[]) {
|
||||
}
|
||||
}
|
||||
|
||||
FD_ZERO(&socket_fds);
|
||||
for (int i = 0; i < NUM_SOCKETS; i++) {
|
||||
FD_SET(sockets[i], &socket_fds);
|
||||
if (sockets[i] > max_socket_fd) {
|
||||
max_socket_fd = sockets[i];
|
||||
}
|
||||
poll_fds[i].fd = sockets[i];
|
||||
poll_fds[i].events = POLLIN;
|
||||
}
|
||||
|
||||
fprintf(stderr, "Ready to accept connections\n");
|
||||
|
||||
while (active) {
|
||||
timeout.tv_sec = 1;
|
||||
timeout.tv_usec = 0;
|
||||
read_socket_fds = socket_fds;
|
||||
ready_sockets_num = select(max_socket_fd + 1, &read_socket_fds, NULL, NULL, &timeout);
|
||||
ready_sockets_num = poll(poll_fds, NUM_SOCKETS, 1000);
|
||||
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 poll sockets: %s" CLR_STR "\n", strerror(errno));
|
||||
terminate();
|
||||
return 1;
|
||||
}
|
||||
|
||||
for (int i = 0; i < NUM_SOCKETS; i++) {
|
||||
if (FD_ISSET(sockets[i], &read_socket_fds)) {
|
||||
if (poll_fds[i].revents & POLLIN) {
|
||||
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));
|
||||
|
11
src/server.h
11
src/server.h
@@ -1,12 +1,12 @@
|
||||
/**
|
||||
* Necronda Web Server
|
||||
* sesimos - secure, simple, modern web server
|
||||
* Main executable (header file)
|
||||
* src/necronda-server.h
|
||||
* src/server.h
|
||||
* Lorenz Stechauner, 2020-12-03
|
||||
*/
|
||||
|
||||
#ifndef NECRONDA_SERVER_SERVER_H
|
||||
#define NECRONDA_SERVER_SERVER_H
|
||||
#ifndef SESIMOS_SERVER_H
|
||||
#define SESIMOS_SERVER_H
|
||||
|
||||
#include <sys/time.h>
|
||||
#include <maxminddb.h>
|
||||
@@ -20,7 +20,6 @@
|
||||
#define SERVER_TIMEOUT_INIT 4
|
||||
#define SERVER_TIMEOUT 3600
|
||||
|
||||
#define CHUNK_SIZE 8192
|
||||
|
||||
extern int sockets[NUM_SOCKETS];
|
||||
extern pid_t children[MAX_CHILDREN];
|
||||
@@ -31,4 +30,4 @@ extern char *log_client_prefix, *log_conn_prefix, *log_req_prefix, *client_geoip
|
||||
extern char *client_addr_str, *client_addr_str_ptr, *server_addr_str, *server_addr_str_ptr, *client_host_str;
|
||||
extern struct timeval client_timeout;
|
||||
|
||||
#endif //NECRONDA_SERVER_SERVER_H
|
||||
#endif //SESIMOS_SERVER_H
|
||||
|
Reference in New Issue
Block a user