summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/config/config.c93
-rw-r--r--src/config/config.h18
-rwxr-xr-xsrc/main.c204
-rwxr-xr-xsrc/net/net.c161
-rwxr-xr-xsrc/net/net.h27
-rw-r--r--src/rewrites/rewrites.c3
-rwxr-xr-xsrc/worker.c101
7 files changed, 190 insertions, 417 deletions
diff --git a/src/config/config.c b/src/config/config.c
index 4cd4835..9ed20f3 100644
--- a/src/config/config.c
+++ b/src/config/config.c
@@ -66,13 +66,14 @@ static void rotate_logs(str logs){
read_logs(logs);
}
-config_m master_config(char *filename){
- config_m conf = {0};
+config read_config(char *filename){
+ config conf = {0};
conf.file = map_file(filename);
if(conf.file.ptr == NULL){
log_error("Unable to open config file '%s'", filename);
return conf;
}
+ init_nlist(conf.files);
int off = 0;
while(off < conf.file.len){
while(off < conf.file.len && charisspace(conf.file.ptr[off])) off++;
@@ -97,59 +98,6 @@ config_m master_config(char *filename){
str val = sread_delim_f(conf.file.ptr + off, charisspace, true);
off += val.len;
conf.backlog = (int)strtou(val);
- }else if(streq(key, sstr("logs"))){
- str val = sread_delim_f(conf.file.ptr + off, charisspace, true);
- off += val.len;
- str logs;
- if(val.ptr[0] != '{'){
- str logfile = dup_str(val);
- logs = file_to_str(logfile.ptr);
- free_str(&logfile);
- }else{
- logs = read_delim(conf.file.ptr + off, '}');
- off += logs.len;
- }
- rotate_logs(logs);
- free_str(&logs);
- }else if(streq(key, sstr("worker"))){
- int bcount = 1;
- while(off < conf.file.len && bcount > 0){
- if(conf.file.ptr[off] == '{') bcount++;
- if(conf.file.ptr[off] == '}') bcount--;
- off++;
- }
- }else if(key.len != 0){
- log_warn("Unexpected entry in configuration: '%.*s'", key.len, key.ptr);
- }
- while(off < conf.file.len && !charislinebreak(conf.file.ptr[off++]));
- };
-
- return conf;
-}
-
-config_w worker_config(char *filename){
- config_w conf = {0};
- conf.file = map_file(filename);
- if(conf.file.ptr == NULL){
- log_error("Unable to open config file '%s'", filename);
- return conf;
- }
- init_nlist(conf.files);
- int off = 0;
- while(off < conf.file.len){
- while(off < conf.file.len && charisspace(conf.file.ptr[off])) off++;
- if(conf.file.ptr[off] == '#'){
- while(off < conf.file.len && !charislinebreak(conf.file.ptr[off++]));
- continue;
- }
- str key = sread_delim_f(conf.file.ptr + off, charisspace, true);
- off += key.len;
- while(off < conf.file.len && charisspace(conf.file.ptr[off]) && !charislinebreak(conf.file.ptr[off])) off++;
-
- if(streq(key, sstr("name"))){
- conf.name = sread_delim_f(conf.file.ptr + off, charisspace, true);
- off += conf.name.len;
- conf.file.ptr[off] = '\0';
}else if(streq(key, sstr("root"))){
conf.root = sread_delim_f(conf.file.ptr + off, charisspace, true);
off += conf.root.len;
@@ -243,15 +191,10 @@ str get_key(str file, str key){
return (str){0};
}
-void free_master_config(config_m *conf){
+void free_config(config *conf){
conf->name = (str){0};
conf->port = (str){0};
conf->backlog = 0;
- unmap_file(&conf->file);
-}
-
-void free_worker_config(config_w *conf){
- conf->name = (str){0};
conf->root = (str){0};
conf->bundle = (str){0};
conf->cert = (str){0};
@@ -268,33 +211,12 @@ void free_worker_config(config_w *conf){
unmap_file(&conf->file);
}
-void print_master_config(config_m conf){
+void print_config(config conf){
printf(
- "MASTER CONFIGURATION:\n"
+ "CONFIGURATION:\n"
"\t- name: %.*s\n"
"\t- port: %.*s\n"
"\t- backlog: %d\n"
- "\t- logs: {\n",
- conf.name.len, conf.name.ptr,
- conf.port.len, conf.port.ptr,
- conf.backlog
- );
- for(int i = 0; i < LOG_LEVEL_COUNT; i++){
- switch(i){
- case LOG_DEBUG: printf("\t\tDEBUG:\t"); break;
- case LOG_INFO: printf("\t\tINFO:\t"); break;
- case LOG_WARN: printf("\t\tWARN:\t"); break;
- case LOG_ERROR: printf("\t\tERROR:\t"); break;
- }
- printf("%d files%s\n", log_get_files(i), log_get_stderr(i) ? " + stderr" : "");
- }
- printf("\t}\n");
-}
-
-void print_worker_config(config_w conf){
- printf(
- "WORKER CONFIGURATION:\n"
- "\t- name: %.*s\n"
"\t- root: %.*s\n"
"\t- bundle: %.*s\n"
"\t- cert: %.*s\n"
@@ -303,6 +225,8 @@ void print_worker_config(config_w conf){
"\t- ipv4: %s\n"
"\t- ipv6: %s\n",
conf.name.len, conf.name.ptr,
+ conf.port.len, conf.name.ptr,
+ conf.backlog,
conf.root.len, conf.root.ptr,
conf.bundle.len, conf.bundle.ptr,
conf.cert.len, conf.cert.ptr,
@@ -325,4 +249,3 @@ void print_worker_config(config_w conf){
}
printf("\t}\n");
}
-
diff --git a/src/config/config.h b/src/config/config.h
index 70435ac..508d5ae 100644
--- a/src/config/config.h
+++ b/src/config/config.h
@@ -9,16 +9,11 @@
#include <errno.h>
-typedef struct config_m {
+typedef struct config {
str file;
str name;
str port;
int backlog;
-} config_m;
-
-typedef struct config_w {
- str file;
- str name;
str root;
str bundle;
str cert;
@@ -27,18 +22,15 @@ typedef struct config_w {
uint ipv4 : 1;
uint ipv6 : 1;
str *files;
-} config_w;
+} config;
-config_m master_config(char *filename);
-config_w worker_config(char *filename);
+config read_config(char *filename);
str get_key(str file, str key);
-void free_master_config(config_m *conf);
-void free_worker_config(config_w *conf);
+void free_config(config *conf);
-void print_master_config(config_m conf);
-void print_worker_config(config_w conf);
+void print_config(config conf);
#endif \ No newline at end of file
diff --git a/src/main.c b/src/main.c
index ddc8e35..916b4cb 100755
--- a/src/main.c
+++ b/src/main.c
@@ -1,24 +1,21 @@
#include <stdio.h>
#include <stdlib.h>
-#include <sys/wait.h>
+#include <signal.h>
#include <libgen.h>
+#include <sys/wait.h>
#include "str/str.h"
-#include "list/list.h"
-#include "net/net.h"
#include "log/log.h"
+#include "list/list.h"
#include "config/config.h"
-str name;
-str orig_config_file;
struct {
+ str name;
str path;
- str socket_file;
str config_file;
str workers;
} dir;
-config_m config;
-http_server *server;
+str orig_config_file;
struct worker {
pid_t pid;
} *workers;
@@ -91,16 +88,31 @@ static void worker_undertaker(int sig, siginfo_t *info, void *ucontext){
}
}
-static int create_server_dir(str name){
- dir.path = dup_strs(sstr("/var/run/"), name, sstr("/"));
+static int create_server_dir(char *configfile){
+ str cff = map_file(configfile);
+ if(cff.ptr == NULL){
+ log_error("Error opening config file '%s'", configfile);
+ return 1;
+ }
+ dir.name = get_key(cff, sstr("name"));
+ dir.path = dup_strs(sstr("/var/run/"), dir.name, sstr("/"));
if(!dir_exists(dir.path.ptr)){
if(mkdir(dir.path.ptr, 0777) != 0){
log_error("Error creating server directory in '%.*s': %s", dir.path.len, dir.path.ptr, strerror(errno));
+ unmap_file(&cff);
return 1;
}
}
- dir.socket_file = dup_strs(dir.path, sstr("socket"));
dir.config_file = dup_strs(dir.path, sstr("configfile"));
+ FILE *cfp = fopen(dir.config_file.ptr, "w");
+ if(cfp == NULL){
+ log_error("Error copying config file to '%.*s': %s", dir.config_file.len, dir.config_file.ptr, strerror(errno));
+ unmap_file(&cff);
+ return 1;
+ }
+ str_to_fp(cff, cfp);
+ fclose(cfp);
+ unmap_file(&cff);
dir.workers = dup_strs(dir.path, sstr("workers/"));
if(!dir_exists(dir.workers.ptr)){
if(mkdir(dir.workers.ptr, 0777) != 0){
@@ -111,97 +123,54 @@ static int create_server_dir(str name){
return 0;
}
-static int copy_config_file(str configfile, str dest){
- str cff = map_file(configfile.ptr);
- if(cff.ptr == NULL){
- log_error("Error opening config file '%.*s'", configfile.len, configfile.ptr);
- return 1;
- }
- FILE *cfp = fopen(dest.ptr, "w");
- if(cfp == NULL){
- log_error("Error creating config file in '%.*s': %s", dest.len, dest.ptr, strerror(errno));
- unmap_file(&cff);
- return 1;
+static void remove_server_dir(void){
+ if(dir_exists(dir.workers.ptr)){
+ if(remove(dir.workers.ptr) != 0){
+ log_error("Error removing workers directory in '%.*s': %s", dir.workers.len, dir.workers.ptr, strerror(errno));
+ }
}
- str_to_fp(cff, cfp);
- fclose(cfp);
- unmap_file(&cff);
- return 0;
-}
-
-static int write_server_socket(str socket_file, int ssocket){
- // TODO: how to reattach to socket? how to leave socket reattachable? look at ptrace(2)
- log_debug("Creating socket file in %.*s", socket_file.len, socket_file.ptr);
- int sfd = creat(socket_file.ptr, 0777);
- if(sfd == -1){
- log_error("Error creating socket file in '%.*s': %s", socket_file.len, socket_file.ptr, strerror(errno));
- return 1;
+ free_str(&dir.workers);
+ if(file_exists(dir.config_file.ptr)){
+ if(remove(dir.config_file.ptr) != 0){
+ log_error("Error removing config file in '%.*s': %s", dir.config_file.len, dir.config_file.ptr, strerror(errno));
+ }
}
- write(sfd, &ssocket, sizeof(ssocket));
- if(close(sfd) == -1){
- log_error("Error closing the socket file '%.*s': %s", socket_file.len, socket_file.ptr, strerror(errno));
- return 1;
+ free_str(&dir.config_file);
+ if(dir_exists(dir.path.ptr)){
+ if(remove(dir.path.ptr) != 0){
+ log_error("Error removing server directory in '%.*s': %s", dir.path.len, dir.path.ptr, strerror(errno));
+ }
}
- return 0;
+ free_str(&dir.path);
+ free_str(&dir.name);
}
static void reinit(int sig, siginfo_t *info, void *ucontext){
if(sig == SIGUSR1){
log_info("Reinitializing server");
propagate_signal(sig);
- free_master_config(&config);
- destroy_http_server(&server);
- if(copy_config_file(orig_config_file, dir.config_file)){
- log_error("Unable to create configuration file in server directory");
- quit(SIGTERM, NULL, NULL);
- }
- config = master_config(dir.config_file.ptr);
- if(config.file.ptr == NULL){
- log_error("Unable to read config from '%.*s'", dir.config_file.len, dir.config_file.ptr);
- quit(SIGTERM, NULL, NULL);
- }
- server = setup_http_server(config.port, config.backlog);
- if(server == NULL){
- log_error("Unable to set up socket server");
- quit(SIGTERM, NULL, NULL);
- }
- if(write_server_socket(dir.socket_file, server->ssocket)){
- log_error("Unable to write socket to socket file");
+ str cff = map_file(orig_config_file.ptr);
+ FILE *cfp = fopen(dir.config_file.ptr, "w");
+ if(cfp == NULL){
+ log_error("Error copying config file to '%.*s': %s", dir.config_file.len, dir.config_file.ptr, strerror(errno));
+ unmap_file(&cff);
quit(SIGTERM, NULL, NULL);
}
+ str_to_fp(cff, cfp);
+ fclose(cfp);
+ unmap_file(&cff);
propagate_signal(SIGCONT);
}
}
int init(char *configfile){
- name = dsstr(basename(configfile));
orig_config_file = dsstr(configfile);
- if(create_server_dir(name) != 0){
+ if(create_server_dir(configfile) != 0){
log_error("Unable to create server directory");
return 1;
}
- if(copy_config_file(orig_config_file, dir.config_file) != 0){
- log_error("Unable to create configuration file in server directory");
- return 1;
- }
- config = master_config(dir.config_file.ptr);
- if(config.file.ptr == NULL){
- log_error("Unable to read config from '%.*s'", dir.config_file.len, dir.config_file.ptr);
- return 1;
- }
- log_info("Succesfully read master config from '%.*s'", dir.config_file.len, dir.config_file.ptr);
- // decouple so the whole net.c doesnt get linked?
- server = setup_http_server(config.port, config.backlog);
- if(server == NULL){
- log_error("Unable to set up socket server");
- return 1;
- }
- if(write_server_socket(dir.socket_file, server->ssocket)){
- log_error("Unable to write socket to socket file");
- return 1;
- }
init_list(workers);
struct sigaction rnit = { .sa_sigaction = reinit, .sa_flags = SA_SIGINFO };
if(sigaction(SIGUSR1, &rnit, NULL) == -1){
@@ -228,69 +197,23 @@ int init(char *configfile){
return 0;
}
-static void remove_server_dir(void){
- if(dir_exists(dir.workers.ptr)){
- if(remove(dir.workers.ptr) != 0){
- log_error("Error removing workers directory in '%.*s': %s", dir.workers.len, dir.workers.ptr, strerror(errno));
- }
- }
- free_str(&dir.workers);
- if(file_exists(dir.config_file.ptr)){
- if(remove(dir.config_file.ptr) != 0){
- log_error("Error removing config file in '%.*s': %s", dir.config_file.len, dir.config_file.ptr, strerror(errno));
- }
- }
- free_str(&dir.config_file);
- if(file_exists(dir.socket_file.ptr)){
- if(remove(dir.socket_file.ptr) != 0){
- log_error("Error removing socket file in '%.*s': %s", dir.socket_file.len, dir.socket_file.ptr, strerror(errno));
- }
- }
- free_str(&dir.socket_file);
- if(dir_exists(dir.path.ptr)){
- if(remove(dir.path.ptr) != 0){
- log_error("Error removing server directory in '%.*s': %s", dir.path.len, dir.path.ptr, strerror(errno));
- }
- }
- free_str(&dir.path);
-}
-
void deinit(void){
- free_master_config(&config);
remove_server_dir();
- destroy_http_server(&server);
list_free(workers);
}
-void print_usage(void){
- printf("server [config]\n");
-}
-
-void show_commands(void){
- printf(
- "(case insensitive)\n"
- "f: fork\n"
- "s: signal\n"
- "l: list\n"
- "c: clear\n"
- "[0-9]: turn off ssl for worker\n"
- "h: help\n"
- "q: quit\n"
- );
-}
-
int main(int argc, char *argv[]){
if(argc < 2){
- print_usage();
+ printf("server [config]\n");
return 1;
}
- int return_value = 0;
+ int ret = 0;
if(init(argv[1]) != 0){
- return_value = 1;
+ ret = 1;
goto DEINIT;
}
@@ -325,7 +248,7 @@ int main(int argc, char *argv[]){
case 'f': case 'F':
pid_t nw = fork();
if(nw == 0){
- char *args[] = {"./worker.exe", name.ptr, "&", NULL};
+ char *args[] = {"./worker.exe", dir.name.ptr, "&", NULL};
execv("./worker.exe", args);
log_error("Cannot exec worker: %s", strerror(errno));
return 1;
@@ -337,10 +260,10 @@ int main(int argc, char *argv[]){
kill(getpid(), SIGUSR1);
break;
case 'l': case 'L':
- printf("|-%3d workers working for us rn-|\n", list_size(workers));
char *faces[] = {
"(^__^)", "(·__·)", "(>__>)", "(~ _~)", "(T__T)", "(º__º)"
};
+ printf("|-%3d workers working for us rn-|\n", list_size(workers));
for(int i = 0; i < list_size(workers); i++){
int index = rand()%sizeof(faces)/sizeof(faces[0]);
printf("| %d %s\t\t\t|\n", workers[i].pid, faces[index]);
@@ -351,7 +274,14 @@ int main(int argc, char *argv[]){
system("clear");
break;
case 'h': case 'H':
- show_commands();
+ printf(
+ "(case insensitive)\n"
+ "f: fork\n"
+ "l: list\n"
+ "c: clear\n"
+ "h: help\n"
+ "q: quit\n"
+ );
break;
case 'q': case 'Q':
while(list_size(workers) > 0){
@@ -359,17 +289,9 @@ int main(int argc, char *argv[]){
waitpid(workers[0].pid, NULL, 0);
}
while(wait(NULL) > 0);
- close(server->ssocket);
end = true;
log_info("%d children remaining alive (lie)", list_size(workers));
break;
- case '0': case '1': case '2': case '3': case '4':
- case '5': case '6': case '7': case '8': case '9':
- if(list_size(workers) > c-'0'){
- log_info("signaling worker[%d] %d to turn off ssl", c-'0', workers[c-'0'].pid);
- sigqueue(workers[c-'0'].pid, SIGRTMIN, (union sigval){.sival_int = 0});
- }
- break;
}
}
@@ -377,7 +299,7 @@ DEINIT:
deinit();
log_info("Finished cleaning up");
- return return_value;
+ return ret;
}
// inspiration: https://www.youtube.com/watch?v=cEH_ipqHbUw (https://github.com/infraredCoding/cerveur)
diff --git a/src/net/net.c b/src/net/net.c
index f03e4f8..526d1a7 100755
--- a/src/net/net.c
+++ b/src/net/net.c
@@ -38,6 +38,7 @@ http_server *setup_http_server(str port, int backlog){
hs->port = dup_str(port);
hs->backlog = backlog;
hs->ssocket = -1;
+ hs->csocket = -1;
int ec, val = 1;
struct addrinfo *res, hints = { .ai_family = AF_INET, .ai_socktype = SOCK_STREAM, .ai_flags = AI_PASSIVE };
@@ -51,8 +52,8 @@ http_server *setup_http_server(str port, int backlog){
goto error;
}
- if(setsockopt(hs->ssocket, SOL_SOCKET, SO_REUSEADDR, &val, sizeof(val))){
- log_error("server: SO_REUSEADDR: %s", strerror(errno));
+ if(setsockopt(hs->ssocket, SOL_SOCKET, SO_REUSEPORT, &val, sizeof(val))){
+ log_error("server: SO_REUSEPORT: %s", strerror(errno));
goto error;
}
@@ -80,41 +81,15 @@ void destroy_http_server(http_server **hs){
free_str(&(*hs)->port);
(*hs)->backlog = 0;
close((*hs)->ssocket);
+ (*hs)->ssocket = -1;
+ close((*hs)->csocket);
+ (*hs)->csocket = -1;
free(*hs);
*hs = NULL;
}
}
-http_worker *setup_http_worker(int ssocket, int secure, str certfile, str keyfile){
- http_worker *hw = calloc(1, sizeof(http_worker));
- hw->ssocket = ssocket;
- hw->csocket = -1;
- hw->secure = secure;
-
- if(secure){
- if(setup_https(hw, certfile, keyfile) != 0){
- log_error("Setting up HTTPS");
- terminate_https(hw);
- destroy_http_worker(&hw);
- }
- }
-
- return hw;
-}
-
-void destroy_http_worker(http_worker **hw){
- if(*hw != NULL){
- (*hw)->ssocket = -1;
- close((*hw)->csocket);
- (*hw)->csocket = -1;
- (*hw)->secure = 0;
- terminate_https(*hw);
- free(*hw);
- *hw = NULL;
- }
-}
-
-int setup_https(http_worker *hw, str certfile, str keyfile){
+int setup_https(http_server *hs, str certfile, str keyfile){
if(certfile.len == 0){
log_error("Missing certificate file");
return 1;
@@ -124,113 +99,113 @@ int setup_https(http_worker *hw, str certfile, str keyfile){
return 1;
}
- if(hw->ssl != NULL){
- SSL_free(hw->ssl);
+ if(hs->ssl != NULL){
+ SSL_free(hs->ssl);
}
- if(hw->ssl_ctx != NULL){
- SSL_CTX_free(hw->ssl_ctx);
+ if(hs->ssl_ctx != NULL){
+ SSL_CTX_free(hs->ssl_ctx);
}
- hw->ssl_ctx = SSL_CTX_new(TLS_server_method());
+ hs->ssl_ctx = SSL_CTX_new(TLS_server_method());
// need to compile openssl with ktls on for this (v) to work
- SSL_CTX_set_options(hw->ssl_ctx, SSL_OP_ENABLE_KTLS | SSL_OP_IGNORE_UNEXPECTED_EOF);
- if(hw->ssl_ctx == NULL){
+ SSL_CTX_set_options(hs->ssl_ctx, SSL_OP_ENABLE_KTLS | SSL_OP_IGNORE_UNEXPECTED_EOF);
+ if(hs->ssl_ctx == NULL){
return 1;
}
- //SSL_CTX_set_verify(hw->ssl_ctx, SSL_VERIFY_PEER, NULL);
- /*if(SSL_CTX_load_verify_locations(hw->ssl_ctx, "ssl/mkarchive.net/ca_bundle.crt", NULL) <= 0){
+ //SSL_CTX_set_verify(hs->ssl_ctx, SSL_VERIFY_PEER, NULL);
+ /*if(SSL_CTX_load_verify_locations(hs->ssl_ctx, "ssl/mkarchive.net/ca_bundle.crt", NULL) <= 0){
log_error("Verifying certificate locations");
return 1;
}*/
- if(SSL_CTX_use_certificate_file(hw->ssl_ctx, certfile.ptr, SSL_FILETYPE_PEM) <= 0){
+ if(SSL_CTX_use_certificate_file(hs->ssl_ctx, certfile.ptr, SSL_FILETYPE_PEM) <= 0){
log_error("Error while trying to set up certificate file");
return 1;
}
- if(SSL_CTX_use_PrivateKey_file(hw->ssl_ctx, keyfile.ptr, SSL_FILETYPE_PEM) <= 0 ){
+ if(SSL_CTX_use_PrivateKey_file(hs->ssl_ctx, keyfile.ptr, SSL_FILETYPE_PEM) <= 0 ){
log_error("Error while trying to set up key file");
return 1;
}
- hw->ssl = SSL_new(hw->ssl_ctx);
- if(hw->ssl == NULL){
+ hs->ssl = SSL_new(hs->ssl_ctx);
+ if(hs->ssl == NULL){
log_error("Creating SSL*");
return 1;
}
- SSL_set_accept_state(hw->ssl);
- hw->secure = 1;
+ SSL_set_accept_state(hs->ssl);
+ hs->secure = 1;
return 0;
}
-void reset_https(http_worker *hw){
- if(hw != NULL){
- close(hw->csocket);
- if(hw->ssl != NULL){
- SSL_free(hw->ssl);
+void reset_https(http_server *hs){
+ if(hs != NULL){
+ close(hs->csocket);
+ if(hs->ssl != NULL){
+ SSL_free(hs->ssl);
}
- hw->ssl = SSL_new(hw->ssl_ctx);
- SSL_set_accept_state(hw->ssl);
+ hs->ssl = SSL_new(hs->ssl_ctx);
+ SSL_set_accept_state(hs->ssl);
}
}
-void terminate_https(http_worker *hw){
- if(hw != NULL){
- hw->secure = 0;
- if(hw->ssl != NULL){
- SSL_free(hw->ssl);
- hw->ssl = NULL;
+void terminate_https(http_server *hs){
+ if(hs != NULL){
+ hs->secure = 0;
+ if(hs->ssl != NULL){
+ SSL_free(hs->ssl);
+ hs->ssl = NULL;
}
- if(hw->ssl_ctx != NULL){
- SSL_CTX_free(hw->ssl_ctx);
- hw->ssl_ctx = NULL;
+ if(hs->ssl_ctx != NULL){
+ SSL_CTX_free(hs->ssl_ctx);
+ hs->ssl_ctx = NULL;
}
}
}
-int accept_connection(http_worker *hw, char ip[INET_ADDRSTRLEN]){
+int accept_connection(http_server *hs, char ip[INET_ADDRSTRLEN]){
struct sockaddr_storage caddr;
int casize = sizeof(caddr);
log_info("Waiting...");
- if((hw->csocket = accept(hw->ssocket, (struct sockaddr *)&caddr, (socklen_t*)&casize)) == -1){
+ if((hs->csocket = accept(hs->ssocket, (struct sockaddr *)&caddr, (socklen_t*)&casize)) == -1){
log_error("accept_connection() -> accept(): %s", strerror(errno));
return -1;
}
log_info("accepted");
- if(hw->secure){
- int err = SSL_set_fd(hw->ssl, hw->csocket);
+ if(hs->secure){
+ int err = SSL_set_fd(hs->ssl, hs->csocket);
if(err != 1){
- log_error("setting fd %d", hw->csocket);
- return pleasesslgivemetheerror(SSL_get_error(hw->ssl, err));
+ log_error("setting fd %d", hs->csocket);
+ return pleasesslgivemetheerror(SSL_get_error(hs->ssl, err));
}
- if((err = SSL_accept(hw->ssl)) != 1){
+ if((err = SSL_accept(hs->ssl)) != 1){
log_error("couldnt accept");
- return pleasesslgivemetheerror(SSL_get_error(hw->ssl, err));
+ return pleasesslgivemetheerror(SSL_get_error(hs->ssl, err));
}
}
inet_ntop(caddr.ss_family, &(((struct sockaddr_in*)&caddr)->sin_addr), ip, INET_ADDRSTRLEN);
return 0;
}
-static inline int worker_read(http_worker *hw, str *buf){
- return hw->secure ?
- SSL_read(hw->ssl, buf->ptr+buf->len, buf->cap-buf->len) :
- recv(hw->csocket, buf->ptr+buf->len, buf->cap-buf->len, 0);
+static inline int server_read(http_server *hs, str *buf){
+ return hs->secure ?
+ SSL_read(hs->ssl, buf->ptr+buf->len, buf->cap-buf->len) :
+ recv(hs->csocket, buf->ptr+buf->len, buf->cap-buf->len, 0);
}
-int receive_request(http_worker *hw, str *request){
+int receive_request(http_server *hs, str *request){
// SSL_has_pending can return 0 if you havent read any bytes yet (https://stackoverflow.com/questions/6616976/why-does-this-ssl-pending-call-always-return-zero)
- struct pollfd pfd[1] = { {.fd = hw->csocket, .events = POLLIN } };
+ struct pollfd pfd[1] = { {.fd = hs->csocket, .events = POLLIN } };
while(poll(pfd, 1, 100)){
if(pfd[0].revents & POLLIN){
int rb = 0;
- if(hw->secure){
- if(SSL_has_pending(hw->ssl)){
- rb = worker_read(hw, request);
+ if(hs->secure){
+ if(SSL_has_pending(hs->ssl)){
+ rb = server_read(hs, request);
if(rb == 0){
- return pleasesslgivemetheerror(SSL_get_error(hw->ssl, rb));
+ return pleasesslgivemetheerror(SSL_get_error(hs->ssl, rb));
}
}
}else{
- rb = worker_read(hw, request);
+ rb = server_read(hs, request);
if(rb == 0){
if(request->len == 0){
return -1;
@@ -461,10 +436,10 @@ url sanitize_url(str rurl){
return u;
}
-static inline int worker_write(http_worker *hw, str buf){
- return hw->secure ?
- SSL_write(hw->ssl, buf.ptr, buf.len) :
- send(hw->csocket, buf.ptr, buf.len, 0);
+static inline int server_write(http_server *hs, str buf){
+ return hs->secure ?
+ SSL_write(hs->ssl, buf.ptr, buf.len) :
+ send(hs->csocket, buf.ptr, buf.len, 0);
}
// use sendfile(2). reason:
@@ -472,7 +447,7 @@ static inline int worker_write(http_worker *hw, str buf){
// Because this copying is done within the kernel, sendfile() is
// more efficient than the combination of read(2) and write(2),
// which would require transferring data to and from user space."
-void send_file(http_worker *hw, str filename){
+void send_file(http_server *hs, str filename){
log_info("requested '%.*s' -> ", filename.len, filename.ptr);
uint64_t fsize = get_file_size(filename.ptr);
if(fsize == 0){
@@ -497,10 +472,10 @@ void send_file(http_worker *hw, str filename){
str header = http_header_to_str(&hm);
free_str(&hm.headers[1].value);
- int sent = worker_write(hw, header);
+ int sent = server_write(hs, header);
if(sent != header.len){
- if(hw->secure){
- pleasesslgivemetheerror(SSL_get_error(hw->ssl, sent));
+ if(hs->secure){
+ pleasesslgivemetheerror(SSL_get_error(hs->ssl, sent));
}else{
log_error("send_file: %s", strerror(errno));
}
@@ -521,14 +496,14 @@ void send_file(http_worker *hw, str filename){
// we're ignoring MAX_BODY_SIZE
str fuckcygwinineedsendfile = fd_to_nstr(fd, fsize);
- sent = worker_write(hw, fuckcygwinineedsendfile);
+ sent = server_write(hs, fuckcygwinineedsendfile);
free_str(&fuckcygwinineedsendfile);
if(sent > 0){ fsize -= sent;
}else if(sent == 0){ break;
}else{
- if(hw->secure){
- pleasesslgivemetheerror(SSL_get_error(hw->ssl, sent));
+ if(hs->secure){
+ pleasesslgivemetheerror(SSL_get_error(hs->ssl, sent));
}else{
perror("send_file (fuck cygwin btw)");
}
diff --git a/src/net/net.h b/src/net/net.h
index 297e417..d23c970 100755
--- a/src/net/net.h
+++ b/src/net/net.h
@@ -66,36 +66,23 @@ typedef struct http_server {
str port;
int backlog;
int ssocket;
-} http_server;
-
-typedef struct http_worker {
- int ssocket;
int csocket;
int secure;
SSL_CTX *ssl_ctx;
SSL *ssl;
-} http_worker;
-
-#define MAX_RESPONSE_SIZE 0x0FFFFFFF
-#define MAX_BODY_SIZE (MAX_RESPONSE_SIZE - 0x0FFF)
-
-#define insert_header(hm, h) \
- (hm).headers[(hm).hlen++] = (h)
+} http_server;
http_server *setup_http_server(str port, int backlog);
void destroy_http_server(http_server **hs);
-http_worker *setup_http_worker(int ssocket, int secure, str certfile, str keyfile);
-void destroy_http_worker(http_worker **hw);
-
-int setup_https(http_worker *hw, str certfile, str keyfile);
-void reset_https(http_worker *hw);
-void terminate_https(http_worker *hw);
+int setup_https(http_server*hs, str certfile, str keyfile);
+void reset_https(http_server *hs);
+void terminate_https(http_server *hs);
-int accept_connection(http_worker *hw, char ip[INET_ADDRSTRLEN]);
+int accept_connection(http_server *hs, char ip[INET_ADDRSTRLEN]);
-int receive_request(http_worker *hw, str *request);
+int receive_request(http_server *hs, str *request);
str generate_resource(url resource, str rurl);
@@ -107,6 +94,6 @@ enum http_method get_http_method(str method);
url sanitize_url(str rurl);
-void send_file(http_worker *hw, str filename);
+void send_file(http_server *hs, str filename);
#endif \ No newline at end of file
diff --git a/src/rewrites/rewrites.c b/src/rewrites/rewrites.c
index 3a9a762..cf7f4f0 100644
--- a/src/rewrites/rewrites.c
+++ b/src/rewrites/rewrites.c
@@ -25,9 +25,6 @@ void read_url_rewrites(str file){
off += rwt.output.query.len;
while(off < file.len && !charislinebreak(file.ptr[off++]));
if(rwt.pattern.len != 0 && rwt.output.path.len != 0){
- rwt.pattern.ptr[rwt.pattern.len] = '\0';
- rwt.output.path.ptr[rwt.output.path.len] = '\0';
- rwt.output.query.ptr[rwt.output.query.len] = '\0';
list_push(rewrites, rwt);
}
}
diff --git a/src/worker.c b/src/worker.c
index b919b64..ce185bd 100755
--- a/src/worker.c
+++ b/src/worker.c
@@ -6,14 +6,13 @@
#include "config/config.h"
-config_w config;
struct {
str path;
- str socket_path;
str config_file;
str self;
} dir;
-http_worker *worker;
+config conf;
+http_server *server;
// remove these or something
int secure = 0;
@@ -21,13 +20,13 @@ int secure = 0;
void deinit(void);
-void quit(int sig, siginfo_t *info, void *ucontext){
+static void quit(int sig, siginfo_t *info, void *ucontext){
log_info("Terminating due to SIG%s (%s)", sigabbrev_np(sig), sigdescr_np(sig));
deinit();
exit(0);
}
-int signal_wait(int sig){
+static int signal_wait(int sig){
sigset_t old, new;
sigemptyset(&new);
sigaddset(&new, sig);
@@ -45,27 +44,23 @@ int signal_wait(int sig){
return 0;
}
-void reinit(int sig, siginfo_t *info, void *ucontext){
+static void reinit(int sig, siginfo_t *info, void *ucontext){
if(sig == SIGUSR1){
log_info("Reinitializing worker");
- free_worker_config(&config);
- destroy_http_worker(&worker);
+ free_config(&conf);
+ destroy_http_server(&server);
if(signal_wait(SIGCONT) != 0){
log_error("You should probably look at signal_wait to see wtf is going on");
}
- config = worker_config(dir.config_file.ptr);
- if(config.file.ptr == NULL){
+ conf = read_config(dir.config_file.ptr);
+ if(conf.file.ptr == NULL){
log_error("Unable to read config from '%.*s'", dir.config_file.len, dir.config_file.ptr);
quit(SIGTERM, NULL, NULL);
}
- int sfd = open(dir.socket_path.ptr, O_RDONLY);
- int ssocket;
- read(sfd, &ssocket, sizeof(int));
- close(sfd);
- worker = setup_http_worker(ssocket, secure, config.cert, config.key);
- if(worker == NULL){
+ server = setup_http_server(conf.port, conf.backlog);
+ if(server == NULL){
log_error("Error setting up worker server");
quit(SIGTERM, NULL, NULL);
}
@@ -73,17 +68,12 @@ void reinit(int sig, siginfo_t *info, void *ucontext){
}
// possibly change name
-int read_server_dir(str name){
+static int read_server_dir(str name){
dir.path = dup_strs(sstr("/var/run/"), name, sstr("/"));
if(!dir_exists(dir.path.ptr)){
log_error("No server directory in '%.*s'", dir.path.len, dir.path.ptr);
return 1;
}
- dir.socket_path = dup_strs(dir.path, sstr("socket"));
- if(!file_exists(dir.socket_path.ptr)){
- log_error("No socket file in '%.*s'", dir.socket_path.len, dir.socket_path.ptr);
- return 1;
- }
dir.config_file = dup_strs(dir.path, sstr("configfile"));
if(!file_exists(dir.config_file.ptr)){
log_error("No config file in '%.*s'", dir.config_file.len, dir.config_file.ptr);
@@ -93,10 +83,6 @@ int read_server_dir(str name){
str pid = utostr(getpid(), 10);
dir.self = dup_strs(dir.path, sstr("workers/"), pid);
free_str(&pid);
- if(file_exists(dir.self.ptr)){
- log_error("Error creating PID record for self in '%.*s': it already exists", dir.self.len, dir.self.ptr);
- return 1;
- }
if(creat(dir.self.ptr, 0777) == -1){
log_error("Error creating PID record for self in '%.*s': %s", dir.self.len, dir.self.ptr, strerror(errno));
return 1;
@@ -104,25 +90,29 @@ int read_server_dir(str name){
return 0;
}
+// possibly change name
+static void remove_server_dir(void){
+ if(remove(dir.self.ptr) != 0){
+ log_error("Error removing PID record for self in '%.*s': %s", dir.self.len, dir.self.ptr, strerror(errno));
+ }
+ free_str(&dir.self);
+ free_str(&dir.config_file);
+ free_str(&dir.path);
+}
+
int init(str name){
if(read_server_dir(name) != 0){
log_error("Error reading server directory");
return 1;
}
- config = worker_config(dir.config_file.ptr);
- if(config.file.ptr == NULL){
+ conf = read_config(dir.config_file.ptr);
+ if(conf.file.ptr == NULL){
log_error("Unable to read config from '%.*s'", dir.config_file.len, dir.config_file.ptr);
return 1;
}
//print_worker_config(config);
- // TODO: remove "successful" messages or add them all
- log_info("Succesfully read worker config from '%.*s'", dir.config_file.len, dir.config_file.ptr);
- int sfd = open(dir.socket_path.ptr, O_RDONLY);
- int ssocket;
- read(sfd, &ssocket, sizeof(int));
- close(sfd);
- worker = setup_http_worker(ssocket, secure, config.cert, config.key);
- if(worker == NULL){
+ server = setup_http_server(conf.port, conf.backlog);
+ if(server == NULL){
log_error("Error setting up worker server");
return 1;
}
@@ -147,30 +137,17 @@ int init(str name){
return 0;
}
-// possibly change name
-void remove_server_dir(void){
- if(remove(dir.self.ptr) != 0){
- log_error("Error removing PID record for self in '%.*s': %s", dir.self.len, dir.self.ptr, strerror(errno));
- }
- free_str(&dir.self);
- free_str(&dir.path);
-}
-
void deinit(void){
- free_worker_config(&config);
+ destroy_http_server(&server);
+ free_config(&conf);
remove_server_dir();
- destroy_http_worker(&worker);
-}
-
-void print_usage(void){
- printf("worker [server name]\n");
}
int main(int argc, char **argv){
if(argc < 2){
- print_usage();
+ printf("worker [server name]\n");
return 1;
}
@@ -187,24 +164,24 @@ int main(int argc, char **argv){
while(1){
char cip[INET_ADDRSTRLEN] = {0};
- return_value = accept_connection(worker, cip);
+ return_value = accept_connection(server, cip);
switch(return_value){
case -1: // couldnt accept, do something ig
continue;
case SSL_ERROR_SSL:
- reset_https(worker);
+ reset_https(server);
log_info("continuing\n");
continue;
}
- log_info("socket %d accepted with ip %s", worker->csocket, cip);
- return_value = receive_request(worker, &request);
+ log_info("socket %d accepted with ip %s", server->csocket, cip);
+ return_value = receive_request(server, &request);
log_debug("received %d from receive_request", return_value);
switch(return_value){
case -1: // couldnt accept, do something ig
goto finish_request;
break;
case SSL_ERROR_SSL:
- reset_https(worker);
+ reset_https(server);
log_info("continuing\n");
continue;
}
@@ -221,13 +198,13 @@ int main(int argc, char **argv){
switch(method){
case GET:
str resource = generate_resource(surl, hm.url);
- send_file(worker, resource);
+ send_file(server, resource);
//if(resource.temp == true) remove(resource.name.ptr);
free_str(&resource);
break;
case POST:
//handlePOST(request);
- send(worker->csocket, "HTTP/1.1 201 Created\r\n\r\n", len("HTTP/1.1 201 Created\r\n\r\n"), 0);
+ send(server->csocket, "HTTP/1.1 201 Created\r\n\r\n", len("HTTP/1.1 201 Created\r\n\r\n"), 0);
break;
case PUT:
break;
@@ -243,10 +220,10 @@ finish_request:
log_debug("query freed");
request.len = 0;
- if(worker->secure){
- SSL_clear(worker->ssl);
+ if(server->secure){
+ SSL_clear(server->ssl);
}
- close(worker->csocket);
+ close(server->csocket);
//SSL_shutdown(config.ssl); // look into SSL_clear()