summaryrefslogtreecommitdiff
path: root/src/worker.c
diff options
context:
space:
mode:
authorSoikk2025-11-22 16:42:08 +0100
committerSoikk2025-11-22 16:42:08 +0100
commit3abcc43f1e638608b4b88bbb0ad7881d74940f8d (patch)
treed5b5e2bf93ff0bbcf3c3d860c2266516e91492c4 /src/worker.c
parentc2e397b6ee390d06f1af8921a514fdcf90e3f2fa (diff)
downloadsoikk-server-3abcc43f1e638608b4b88bbb0ad7881d74940f8d.tar.xz
soikk-server-3abcc43f1e638608b4b88bbb0ad7881d74940f8d.tar.zst
Rewrites and IPC rework
- Moved functionality to temporary server directory - Separated rewrites - Moved IPC back to signals - Added get_key() in config - Reworked receive_request() - Improved error handling
Diffstat (limited to 'src/worker.c')
-rwxr-xr-xsrc/worker.c317
1 files changed, 177 insertions, 140 deletions
diff --git a/src/worker.c b/src/worker.c
index f4b67c2..64403ac 100755
--- a/src/worker.c
+++ b/src/worker.c
@@ -10,66 +10,64 @@
config_w config;
struct {
str path;
+ str socket_path;
str ipc_addr;
+ str config_file;
str self;
} dir;
ipc_listener *listener;
http_worker *worker;
// remove these or something
-int secure;
+int secure = 0;
str rewritesfile;
-str rootdir;
-str bundlefile;
-str certfile;
-str keyfile;
-struct pollfd fds[2] = {0};
+// TODO: remove?
// make int for errors?
void handle_message(ipc_msg im){
log_debug("received message: [%d] (%d) %s", im.type, im.msg.len, im.msg.ptr);
switch(im.type){
case NONE: break;
case SOCKET:
- if(worker != NULL){
- destroy_http_worker(&worker);
- }
- int ssocket = strtou(im.msg);
- worker = setup_http_worker(ssocket, secure, certfile, keyfile);
- fds[1] = (struct pollfd){ .fd = worker->ssocket, .events = POLLIN };
+ // if(worker != NULL){
+ // destroy_http_worker(&worker);
+ // }
+ // int ssocket = strtou(im.msg);
+ // worker = setup_http_worker(ssocket, secure, certfile, keyfile);
+ // fds[1] = (struct pollfd){ .fd = worker->ssocket, .events = POLLIN };
break;
case REWRITES:
- int fsize = get_file_size(im.msg.ptr);
- int fd = open(im.msg.ptr, O_RDONLY | O_NONBLOCK);
- char *rewrites = mmap(NULL, fsize, PROT_READ, MAP_SHARED, fd, 0);
- if(rewrites == (void*)-1){
- log_error("cant mmap rewrites: %s", strerror(errno));
- return;
- }
- if(read_uri_rewrites(rewrites, fsize) != 0){
- log_error("init: read_uri_rewrites: %s", strerror(errno));
- return;
- }
- munmap(rewritesfile.ptr, fsize);
- close(fd);
+ //int fsize = get_file_size(im.msg.ptr);
+ //int fd = open(im.msg.ptr, O_RDONLY | O_NONBLOCK);
+ //char *rewrites = mmap(NULL, fsize, PROT_READ, MAP_SHARED, fd, 0);
+ //if(rewrites == (void*)-1){
+ // log_error("cant mmap rewrites: %s", strerror(errno));
+ // return;
+ //}
+ //if(read_uri_rewrites(rewrites, fsize) != 0){
+ // log_error("init: read_uri_rewrites: %s", strerror(errno));
+ // return;
+ //}
+ //munmap(rewritesfile.ptr, fsize);
+ //close(fd);
break;
//case ROOT:
// free_str(&rootdir);
// rootdir = dup_str(im.msg);
// break;
case BUNDLE: // look into reinitializing the worker when receiving this
- free_str(&bundlefile);
- bundlefile = dup_str(im.msg);
- break;
+ // free_str(&bundlefile);
+ // bundlefile = dup_str(im.msg);
+ // break;
case CERT: // look into reinitializing the worker when receiving this
- free_str(&certfile);
- certfile = dup_str(im.msg);
- break;
+ // free_str(&certfile);
+ // certfile = dup_str(im.msg);
+ // break;
case KEY: // look into reinitializing the worker when receiving this
- free_str(&keyfile);
- keyfile = dup_str(im.msg);
- break;
+ // free_str(&keyfile);
+ // keyfile = dup_str(im.msg);
+ // break;
case RESTART:
char *args[] = {"./worker.exe", listener->saddr.ptr, NULL};
execv("./worker.exe", args);
@@ -81,18 +79,20 @@ void handle_message(ipc_msg im){
// re-requests entire config;
break;
case HTTP:
- log_info("received http signal");
- if(secure != 0){
- secure = 0;
- terminate_https(worker);
- }
+ // TODO: revise this
+ // log_info("received http signal");
+ // if(secure != 0){
+ // secure = 0;
+ // terminate_https(worker);
+ // }
break;
case HTTPS:
- log_info("received https signal");
- if(secure == 0){
- secure = 1;
- setup_https(worker, certfile, keyfile);
- }
+ // TODO: revise this
+ // log_info("received https signal");
+ // if(secure == 0){
+ // secure = 1;
+ // setup_https(worker, certfile, keyfile);
+ // }
break;
case LOG:
break;
@@ -103,18 +103,39 @@ void handle_message(ipc_msg im){
}
}
-// possibly change name
+void deinit(void);
-int create_server_dir(str name){
+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);
+}
+
+// possibly change name
+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': %s", dir.path.len, 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.ipc_addr = dup_strs(dir.path, sstr("ipcserver"));
+ if(!file_exists(dir.ipc_addr.ptr)){
+ log_error("No IPC socket in '%.*s'", dir.ipc_addr.len, dir.ipc_addr.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);
+ return 1;
+ }
+ // TODO: revise this
str pid = utostr(getpid(), 10);
dir.self = dup_strs(dir.path, sstr("workers/"), pid);
- printf("WE'RE GONNA CREATE THE FILE %s\n", dir.self.ptr);
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);
@@ -127,15 +148,44 @@ int create_server_dir(str name){
return 0;
}
-int init(char *configfile){
- config = worker_config(configfile);
- if(config.name.len == 0){ // TODO: maybe check for this someway else
- log_error("Unable to read config from '%s'", configfile);
+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){
+ 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 ssocket;
+ int sfd = open(dir.socket_path.ptr, O_RDONLY);
+ read(sfd, &ssocket, sizeof(int));
+ close(sfd);
+ worker = setup_http_worker(ssocket, secure, config.cert, config.key);
+ if(worker == NULL){
+ log_error("Error setting up worker server");
+ return 1;
+ }
+ listener = setup_ipc_listener(dir.ipc_addr);
+ if(listener == NULL){
+ log_error("Can't set up ipc listener on self");
+ return 1;
+ }
+ struct sigaction qit = { .sa_sigaction = quit, .sa_flags = SA_SIGINFO };
+ if(sigaction(SIGTERM, &qit, NULL) == -1){
+ log_error("Error setting up SIGTERM signal handler: %s", strerror(errno));
+ return 1;
+ }
+ if(sigaction(SIGQUIT, &qit, NULL) == -1){
+ log_error("Error setting up SIGQUIT signal handler: %s", strerror(errno));
return 1;
}
- print_worker_config(config);
- log_info("Succesfully read worker config from '%s'", configfile);
- if(create_server_dir(config.name) != 0){
+ if(sigaction(SIGINT, &qit, NULL) == -1){
+ log_error("Error setting up SIGINT signal handler: %s", strerror(errno));
return 1;
}
return 0;
@@ -146,126 +196,113 @@ 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));
}
- printf("%s IS NO MORE!", dir.self.ptr);
free_str(&dir.self);
free_str(&dir.ipc_addr);
free_str(&dir.path);
}
void deinit(void){
+ destroy_ipc_listener(&listener);
+ destroy_http_worker(&worker);
free_worker_config(&config);
remove_server_dir();
}
+void print_usage(void){
+ printf("worker [server name]\n");
+}
+
int main(int argc, char **argv){
- int return_value = 0;
+ if(argc < 2){
+ print_usage();
+ return 1;
+ }
- init("config.example");
+ int return_value = 0;
- listener = setup_ipc_listener((str){.cap = 0, .len = len(argv[1]), .ptr = argv[1]});
- if(listener == NULL){
- log_error("Can't set up ipc listener on worker %d", getpid());
+ if(init(dsstr(argv[1])) != 0){
return_value = 1;
goto DEINIT;
}
log_info("init'd");
//bool end = false;
- log_debug("erm");
str request = {.cap = 8192, .len = 0, .ptr = alloca(8192)};
- fds[0] = (struct pollfd){ .fd = listener->csocket, .events = POLLIN };
-
- int r;
- while((r = poll(fds, 2, 0)) != -1){
- if(r > 0){
- log_info("[%d] %d\t-\t%d", fds[1].fd, fds[1].events & POLLIN, fds[1].revents & POLLIN);
+ while(1){
+ char cip[INET_ADDRSTRLEN] = {0};
+ return_value = accept_connection(worker, cip);
+ switch(return_value){
+ case -1: // couldnt accept, do something ig
+ continue;
+ case SSL_ERROR_SSL:
+ reset_https(worker);
+ log_info("continuing\n");
+ continue;
+ }
+ log_info("socket %d accepted with ip %s", worker->csocket, cip);
+ return_value = receive_request(worker, &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);
+ log_info("continuing\n");
+ continue;
}
- if(fds[0].revents & POLLHUP){
- log_info("RECEIVED POLLHUP!!!!!!");
- // end? or something idk
- }else if(fds[0].revents & POLLIN){
- ipc_msg msg = receive_ipc_message(listener);
- handle_message(msg);
- free_ipc_message(&msg);
- continue;
- }else if(fds[1].revents & POLLIN){
- log_info("ermmm");
- char cip[INET_ADDRSTRLEN] = {0};
- return_value = accept_connection(worker, cip);
- switch(return_value){
- case -1: // couldnt accept, do something ig
- continue;
- case SSL_ERROR_SSL:
- reset_https(worker);
- log_info("continuing\n");
- continue;
- }
- log_info("socket %d accepted with ip %s", worker->csocket, cip);
- return_value = receive_request(worker, &request);
- switch(return_value){
- case -1: // couldnt accept, do something ig
- continue;
- case SSL_ERROR_SSL:
- reset_https(worker);
- log_info("continuing\n");
- continue;
- }
-
- printf("'%.*s'\n", request.len, request.ptr);
- struct http_message hm = {0};
- build_http_message(request.ptr, request.len, &hm);
- log_info("uri before: %.*s", hm.uri.len, hm.uri.ptr);
- struct uri suri = sanitize_uri(hm.uri);
- log_info("uri after: %.*s", suri.path.len, suri.path.ptr);
- enum http_method method = get_http_method(hm.method);
+ printf("%d: '%.*s'\n", request.len, request.len, request.ptr);
- switch(method){
- case GET:
- str resource = generate_resource(suri, hm.uri);
- send_file(worker, 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);
- break;
- case PUT:
- break;
- case DELETE:
- break;
- default:
- break;
- }
- free_str(&suri.path);
- free_str(&suri.query);
- log_debug("query freed");
- request.len = 0;
+ struct http_message hm = {0};
+ build_http_message(request.ptr, request.len, &hm);
+ log_info("url before: %.*s", hm.url.len, hm.url.ptr);
+ url surl = sanitize_url(hm.url);
+ log_info("uri after: '%.*s' ? '%.*s'", surl.path.len, surl.path.ptr, surl.query.len, surl.query.ptr);
+ enum http_method method = get_http_method(hm.method);
- if(worker->secure){
- SSL_clear(worker->ssl);
- }
- close(worker->csocket);
+ switch(method){
+ case GET:
+ str resource = generate_resource(surl, hm.url);
+ send_file(worker, 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);
+ break;
+ case PUT:
+ break;
+ case DELETE:
+ break;
+ default:
+ break;
+ }
- //SSL_shutdown(config.ssl); // look into SSL_clear()
+finish_request:
+ free_str(&surl.path);
+ free_str(&surl.query);
+ log_debug("query freed");
+ request.len = 0;
- log_debug("end of loop");
- }else if(fds[1].revents & POLLHUP){
- // like restart the worker
+ if(worker->secure){
+ SSL_clear(worker->ssl);
}
+ close(worker->csocket);
+
+ //SSL_shutdown(config.ssl); // look into SSL_clear()
+
+ log_debug("end of loop");
}
DEINIT:
deinit();
- log_info("dieing :(");
- destroy_ipc_listener(&listener);
- destroy_http_worker(&worker);
free_str(&rewritesfile);
- free_uri_rewrites();
+ log_info("dieing :(");
return return_value;
}