diff options
Diffstat (limited to 'src/main.c')
| -rwxr-xr-x | src/main.c | 196 |
1 files changed, 196 insertions, 0 deletions
diff --git a/src/main.c b/src/main.c new file mode 100755 index 0000000..65367d6 --- /dev/null +++ b/src/main.c @@ -0,0 +1,196 @@ +#include <stdio.h> +#include <stdlib.h> +#include <sys/wait.h> +#include <time.h> +#include "str/str.h" +#include "list/list.h" +#include "net/net.h" +#include "log/log.h" +#include "ipc/ipc.h" + +#define BACKLOG 15 + +struct str ipcaddr = sstr(".ipcserver"); +struct str port; +http_server *server; +ipc_sender *sender; +struct worker { + pid_t pid; + int wsocket; +} *workers; + + +void worker_undertaker(int sig, siginfo_t *info, void *ucontext){ + if(sig == SIGCHLD && list_entry_exists(workers, info->si_pid)){ + list_remove_entry(workers, info->si_pid); + log_warn("worker %d is dead. now workers size is %d", info->si_pid, list_size(workers)); + } +} + +int init(char *argv[]){ + port = snstr(argv[1], len(argv[1])); // error check + if(port.len <= 0 || port.len > 5){ + log_error("wrong server port: '%.*s'", port.len, port.ptr); + return 1; + } + // decouple so the whole net.c doesnt get linked? + server = setup_http_server(port, BACKLOG); + if(server == NULL){ + log_error("Setting up socket server"); + return 1; + } + // configurable name? + sender = setup_ipc_sender(ipcaddr, BACKLOG); + if(sender == NULL){ + log_error("setting up ipc sender"); + return 1; + } + init_list(workers); + struct sigaction chld = { .sa_sigaction = worker_undertaker, .sa_flags = SA_SIGINFO }; + if(sigaction(SIGCHLD, &chld, NULL) == -1){ + log_error("init: SIGCHLD: %s", strerror(errno)); + return 1; + } + return 0; +} + +void deinit(void){ + destroy_http_server(&server); + destroy_ipc_sender(&sender); + list_free(workers); +} + +void print_usage(void){ + printf("server [port]\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(); + return 1; + } + + int return_value = 0; + + if(init(argv) != 0){ + return_value = 1; + goto DEINIT; + } + log_info("Config done"); + +#ifdef SHOW_IP + system("curl -s http://ipinfo.io/ip && echo"); +#endif + +/* + sqlite3 *db = setupDatabase("src/db/db.db"); + if(db == NULL){ + fprintf(stderr, "error setting up database\n"); + return 1; + } + + if(getNEntries("archive") != getCount(db, FILE_TABLE)){ + int n = getNEntries("archive"); + char **entries = getFiles("archive"); // getFiles deprecated btw + for(int i = 0; i < n; ++i){ + insertName(db, FILE_TABLE, entries[i]); + } + printf("%d, %d\n", getNEntries("archive"), getCount(db, FILE_TABLE)); + } +*/ + + + printf("press h for help\n"); + bool end = false; + while(!end){ + char c = getchar(); + switch(c){ + case 'f': case 'F': + pid_t nw = fork(); + if(nw == 0){ + char *args[] = {"./worker.exe", ipcaddr.ptr, NULL}; + execv("./worker.exe", args); + log_error("Cannot exec worker: %s", strerror(errno)); + return 1; + } + struct worker w = { .pid = nw, .wsocket = accept(sender->ssocket, NULL, NULL) }; + list_push(workers, w); + ipc_message msg = { .key = sstr("socket"), .val = utostr(server->ssocket, 10) }; + send_ipc_message(w.wsocket, msg); + free_ipc_message(msg); + msg = (ipc_message){ .key = sstr("rewrites"), .val = sstr("urirewrites") }; + send_ipc_message(w.wsocket, msg); + break; + case 's': case 'S': + kill(0, SIGUSR1); + break; + case 'l': case 'L': + printf("|-%3d workers working for us rn-|\n", list_size(workers)); + char *faces[] = { + "(^__^)", "(·__·)", "(>__>)", "(~ _~)", "(T__T)", "(º__º)" + }; + 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]); + } + printf("|-------------------------------|\n"); + break; + case 'c': case 'C': + system("clear"); + break; + case 'h': case 'H': + show_commands(); + break; + case 'q': case 'Q': + while(list_size(workers) > 0){ + kill(workers[0].pid, SIGKILL); // redo this PLEASE + waitpid(workers[0].pid, NULL, 0); + } + while(wait(NULL) > 0); + close(server->ssocket); + end = true; + log_info("%d children remaining alive (lie)\n", 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\n", c-'0', workers[c-'0'].pid); + sigqueue(workers[c-'0'].pid, SIGRTMIN, (union sigval){.sival_int = 0}); + } + break; + } + } + +DEINIT: + deinit(); + + return return_value; +} + +// inspiration: https://www.youtube.com/watch?v=cEH_ipqHbUw (https://github.com/infraredCoding/cerveur) +// thanks to +/* + https://beej.us/guide/bgnet/ + https://dev.to/lloyds-digital/how-you-can-host-websites-from-home-4pke + https://developer.mozilla.org/en-US/docs/Web/HTTP/Messages + https://www.favicon.cc + https://www.cssscript.com/demo/animated-snowfall-effect/ + https://www.cssscript.com/demo/animated-snowfall-effect/PureSnow.js + https://www.tutorialspoint.com/http/http_requests.htm + https://codepen.io/afarrar/pen/JRaEjP +*/ + |
