From 3abcc43f1e638608b4b88bbb0ad7881d74940f8d Mon Sep 17 00:00:00 2001 From: Soikk Date: Sat, 22 Nov 2025 16:42:08 +0100 Subject: 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 --- src/config/config.c | 62 ++++++++-- src/config/config.h | 5 +- src/main.c | 205 ++++++++++++++++++++++--------- src/net/net.c | 225 +++++++++------------------------- src/net/net.h | 23 +--- src/rewrites/rewrites.c | 160 ++++++++++++++++++++++++ src/rewrites/rewrites.h | 29 +++++ src/worker.c | 317 +++++++++++++++++++++++++++--------------------- 8 files changed, 633 insertions(+), 393 deletions(-) create mode 100644 src/rewrites/rewrites.c create mode 100644 src/rewrites/rewrites.h (limited to 'src') diff --git a/src/config/config.c b/src/config/config.c index c90364f..4cd4835 100644 --- a/src/config/config.c +++ b/src/config/config.c @@ -69,11 +69,15 @@ static void rotate_logs(str logs){ config_m master_config(char *filename){ config_m conf = {0}; conf.file = map_file(filename); + if(conf.file.ptr == NULL){ + log_error("Unable to open config file '%s'", filename); + return conf; + } 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])) off++; + while(off < conf.file.len && !charislinebreak(conf.file.ptr[off++])); continue; } str key = sread_delim_f(conf.file.ptr + off, charisspace, true); @@ -83,6 +87,7 @@ config_m master_config(char *filename){ 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("port"))){ str val = sread_delim_f(conf.file.ptr + off, charisspace, true); off += val.len; @@ -116,8 +121,7 @@ config_m master_config(char *filename){ }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])) off++; - off++; + while(off < conf.file.len && !charislinebreak(conf.file.ptr[off++])); }; return conf; @@ -135,7 +139,7 @@ config_w worker_config(char *filename){ 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])) off++; + while(off < conf.file.len && !charislinebreak(conf.file.ptr[off++])); continue; } str key = sread_delim_f(conf.file.ptr + off, charisspace, true); @@ -145,20 +149,23 @@ config_w worker_config(char *filename){ 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"))){ - str val = sread_delim_f(conf.file.ptr + off, charisspace, true); - off += val.len; - str trailslash = val.ptr[val.len-1] == '/' ? sstr("") : sstr("/"); - conf.root = dup_strs(val, trailslash); + conf.root = sread_delim_f(conf.file.ptr + off, charisspace, true); + off += conf.root.len; + conf.file.ptr[off] = '\0'; }else if(streq(key, sstr("bundle"))){ conf.bundle = sread_delim_f(conf.file.ptr + off, charisspace, true); off += conf.bundle.len; + conf.file.ptr[off] = '\0'; }else if(streq(key, sstr("cert"))){ conf.cert = sread_delim_f(conf.file.ptr + off, charisspace, true); off += conf.cert.len; + conf.file.ptr[off] = '\0'; }else if(streq(key, sstr("key"))){ conf.key = sread_delim_f(conf.file.ptr + off, charisspace, true); off += conf.key.len; + conf.file.ptr[off] = 0; }else if(streq(key, sstr("https"))){ conf.secure = 1; }else if(streq(key, sstr("http"))){ @@ -181,6 +188,20 @@ config_w worker_config(char *filename){ off += types.len; } read_mime_types(types); + }else if(streq(key, sstr("rewrites"))){ + str val = sread_delim_f(conf.file.ptr + off, charisspace, true); + off += val.len; + str rewrites; + if(val.ptr[0] != '{'){ + str rewritesfile = dup_str(val); + rewrites = map_file(rewritesfile.ptr); + list_push(conf.files, rewrites); + free_str(&rewritesfile); + }else{ + rewrites = sread_delim(conf.file.ptr + off, '}'); + off += rewrites.len; + } + read_url_rewrites(rewrites); }else if(streq(key, sstr("logs"))){ str val = sread_delim_f(conf.file.ptr + off, charisspace, true); off += val.len; @@ -196,13 +217,32 @@ config_w worker_config(char *filename){ rotate_logs(logs); free_str(&logs); } - while(off < conf.file.len && !charislinebreak(conf.file.ptr[off])) off++; - off++; + while(off < conf.file.len && !charislinebreak(conf.file.ptr[off++])); }; return conf; } +str get_key(str file, str key){ + int off = 0; + while(off < file.len){ + while(off < file.len && charisspace(file.ptr[off])) off++; + if(file.ptr[off] == '#'){ + while(off < file.len && !charislinebreak(file.ptr[off])) off++; + continue; + } + str candidate = sread_delim_f(file.ptr + off, charisspace, true); + off += candidate.len; + while(off < file.len && charisspace(file.ptr[off]) && !charislinebreak(file.ptr[off])) off++; + if(streq(key, candidate)){ + return read_delim_f(file.ptr + off, charisspace, true); + } + while(off < file.len && !charislinebreak(file.ptr[off])) off++; + off++; + } + return (str){0}; +} + void free_master_config(config_m *conf){ conf->name = (str){0}; conf->port = (str){0}; @@ -220,6 +260,7 @@ void free_worker_config(config_w *conf){ conf->ipv4 = 0; conf->ipv6 = 0; free_mime_types(); + free_url_rewrites(); for(int i = 0; i < list_size(conf->files); i++){ unmap_file(&conf->files[i]); } @@ -271,6 +312,7 @@ void print_worker_config(config_w conf){ conf.ipv6 ? "yes" : "no" ); print_mime_types(); + print_url_rewrites(); printf("\t- logs: {\n"); for(int i = 0; i < LOG_LEVEL_COUNT; i++){ switch(i){ diff --git a/src/config/config.h b/src/config/config.h index 3f74fc3..70435ac 100644 --- a/src/config/config.h +++ b/src/config/config.h @@ -5,6 +5,7 @@ #include "log/log.h" #include "list/list.h" #include "mime/mime.h" +#include "rewrites/rewrites.h" #include @@ -32,10 +33,12 @@ typedef struct config_w { config_m master_config(char *filename); config_w worker_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 print_master_config(config_m conf); void print_worker_config(config_w conf); -#endif +#endif \ No newline at end of file diff --git a/src/main.c b/src/main.c index 78312c5..98da9d0 100755 --- a/src/main.c +++ b/src/main.c @@ -14,9 +14,9 @@ config_m config; struct { str path; - str sock_path; - str sock_addr; + str socket_file; str ipc_addr; + str config_file; str workers; } dir; http_server *server; @@ -27,10 +27,69 @@ struct worker { } *workers; +static void propagate_signal(int sig, siginfo_t *info, void *ucontext){ + for(int i = 0; i < list_size(workers); i++){ + kill(workers[i].pid, sig); + } +} + +void deinit(void); + +void quit(int sig, siginfo_t *info, void *ucontext){ + log_info("Terminating due to SIG%s (%s)", sigabbrev_np(sig), sigdescr_np(sig)); + propagate_signal(sig, info, ucontext); + deinit(); + exit(0); +} + +static void cleanup_worker(pid_t pid, int cleandir){ + waitpid(pid, NULL, 0); + list_remove_entry(workers, pid); + if(cleandir){ + str spid = utostr(pid, 10); + str workerfile = dup_strs(dir.workers, spid); + if(remove(workerfile.ptr) != 0){ + log_error("Error cleaning up worker's %d file '%.*s': %s", pid, workerfile.len, workerfile.ptr, strerror(errno)); + } + free_str(&workerfile); + free_str(&spid); + } +} + +// TODO: look more into waitpid() +// TODO: make a wrapper for sigabbrev_np 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)); + switch(info->si_code){ + case CLD_EXITED: + cleanup_worker(info->si_pid, 0); + log_info("Worker process %d exited normally with exit value %d",info->si_pid, info->si_status); + break; + case CLD_KILLED: + cleanup_worker(info->si_pid, 1); + log_info("Worker process %d was killed by signal SIG%s (%s)", + info->si_pid, sigabbrev_np(info->si_status), sigdescr_np(info->si_status)); + break; + case CLD_DUMPED: + cleanup_worker(info->si_pid, 1); + log_info("Worker process %d was killed by signal SIG%s (%s) and produced a core dump", + info->si_pid, sigabbrev_np(info->si_status), sigdescr_np(info->si_status)); + break; + case CLD_TRAPPED: + log_info("Worker process %d was trapped by signal %d", info->si_pid, info->si_status); + break; + case CLD_STOPPED: + log_info("Worker process %d was stopped by signal %d", info->si_pid, info->si_status); + break; + case CLD_CONTINUED: + log_info("Worker process %d was continued by signal %d", info->si_pid, info->si_status); + break; + default: + cleanup_worker(info->si_pid, 1); + log_info("Received SIGCHLD for process %d for some reason, with exit code/signal %d", info->si_pid, info->si_status); + break; + } + log_debug("Now workers size is %d", list_size(workers)); } } @@ -42,24 +101,8 @@ int create_server_dir(str name){ return 1; } } - dir.sock_path = dup_strs(dir.path, sstr("socket/")); - log_info("creating sock path in %.*s", dir.sock_path.len, dir.sock_path.ptr); - if(!dir_exists(dir.sock_path.ptr)){ - // TODO: else? how to reattach to socket? how to leave socket reattachable? - // TODO: look at ptrace(2) - if(mkdir(dir.sock_path.ptr, 0777) != 0){ - log_error("Error creating socket directory in '%.*s': %s", dir.sock_path.len, dir.sock_path.ptr, strerror(errno)); - return 1; - } - } - str sssocket = utostr(server->ssocket, 10); - dir.sock_addr = dup_strs(dir.sock_path, sssocket); - free_str(&sssocket); - log_info("creating sock in %.*s", dir.sock_addr.len, dir.sock_addr.ptr); - if(creat(dir.sock_addr.ptr, 0777) == -1){ - log_error("Error creating socket file for server in '%.*s': %s", dir.sock_addr.len, dir.sock_addr.ptr, strerror(errno)); - return 1; - } + dir.socket_file = dup_strs(dir.path, sstr("socket")); + dir.config_file = dup_strs(dir.path, sstr("configfile")); dir.ipc_addr = dup_strs(dir.path, sstr("ipcserver")); if(path_exists(dir.ipc_addr.ptr)){ if(remove(dir.ipc_addr.ptr) != 0){ @@ -77,13 +120,58 @@ int create_server_dir(str name){ return 0; } +int copy_config_file(char *configfile, str dest){ + str cff = map_file(configfile); + if(cff.ptr == NULL){ + log_error("Error opening config file '%s'", configfile); + 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; + } + str_to_fp(cff, cfp); + fclose(cfp); + unmap_file(&cff); + return 0; +} + +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_info("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; + } + 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; + } + return 0; +} + int init(char *configfile){ - config = master_config(configfile); - if(config.name.len == 0){ // TODO: maybe check for this someway else + str file = map_file(configfile); + str name = get_key(file, sstr("name")); + unmap_file(&file); + if(create_server_dir(name) != 0){ + free_str(&name); + return 1; + } + free_str(&name); + if(copy_config_file(configfile, dir.config_file) != 0){ + return 1; + } + config = master_config(dir.config_file.ptr); + if(config.file.ptr == NULL){ log_error("Unable to read config from '%s'", configfile); return 1; } - print_master_config(config); + //print_master_config(config); log_info("Succesfully read master config from '%s'", configfile); // decouple so the whole net.c doesnt get linked? server = setup_http_server(config.port, config.backlog); @@ -91,32 +179,36 @@ int init(char *configfile){ log_error("Error setting up socket server"); return 1; } - if(create_server_dir(config.name) != 0){ + if(write_server_socket(dir.socket_file, server->ssocket)){ return 1; } - // configurable name? sender = setup_ipc_sender(dir.ipc_addr, IPC_BACKLOG); if(sender == NULL){ log_error("Error setting up IPC sender"); return 1; } init_list(workers); - struct sigaction chld = { .sa_sigaction = worker_undertaker, .sa_flags = SA_SIGINFO }; + struct sigaction chld = { .sa_sigaction = worker_undertaker, .sa_flags = SA_SIGINFO | SA_NOCLDSTOP }; if(sigaction(SIGCHLD, &chld, NULL) == -1){ log_error("Error setting up SIGCHLD signal handler: %s", strerror(errno)); 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; + } + if(sigaction(SIGINT, &qit, NULL) == -1){ + log_error("Error setting up SIGINT signal handler: %s", strerror(errno)); + } return 0; } void remove_server_dir(void){ - if(remove(dir.sock_addr.ptr) != 0){ - log_error("Error removing socket file in '%.*s': %s", dir.sock_addr.len, dir.sock_addr.ptr, strerror(errno)); - } - if(remove(dir.sock_path.ptr) != 0){ - log_error("Error removing socket path in '%.*s': %s", dir.sock_path.len, dir.sock_path.ptr, strerror(errno)); - } - // remove workers entries first if(remove(dir.workers.ptr) != 0){ log_error("Error removing workers directory in '%.*s': %s", dir.workers.len, dir.workers.ptr, strerror(errno)); } @@ -125,6 +217,14 @@ void remove_server_dir(void){ log_error("Error removing IPC socket '%.*s': %s", dir.ipc_addr.len, dir.ipc_addr.ptr, strerror(errno)); } free_str(&dir.ipc_addr); + 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(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(remove(dir.path.ptr) != 0){ log_error("Error removing server directory in '%.*s': %s", dir.path.len, dir.path.ptr, strerror(errno)); } @@ -170,10 +270,6 @@ int main(int argc, char *argv[]){ return_value = 1; goto DEINIT; } - log_debug("test"); - log_info("test"); - log_warn("test"); - log_error("test"); #ifdef SHOW_IP system("curl -s http://ipinfo.io/ip && echo"); @@ -206,31 +302,24 @@ int main(int argc, char *argv[]){ case 'f': case 'F': pid_t nw = fork(); if(nw == 0){ - char *args[] = {"./worker.exe", dir.ipc_addr.ptr, NULL}; + char *args[] = {"./worker.exe", config.name.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); - send_ipc_message(w.wsocket, CERT, sstr("ssl/cert.pem")); - send_ipc_message(w.wsocket, KEY, sstr("ssl/key.pem")); - str ss = utostr(server->ssocket, 10); - send_ipc_message(w.wsocket, SOCKET, ss); - free_str(&ss); - send_ipc_message(w.wsocket, REWRITES, sstr("urirewrites")); - //send_ipc_message(w.wsocket, HTTPS, sstr("")); - break; - case 's': - for(int i = 0; i < list_size(workers); i++){ - send_ipc_message(workers[i].wsocket, HTTPS, sstr("")); - } - break; - case 'S': - for(int i = 0; i < list_size(workers); i++){ - send_ipc_message(workers[i].wsocket, HTTP, sstr("")); - } break; + // case 's': + // for(int i = 0; i < list_size(workers); i++){ + // send_ipc_message(workers[i].wsocket, HTTPS, sstr("")); + // } + // break; + // case 'S': + // for(int i = 0; i < list_size(workers); i++){ + // send_ipc_message(workers[i].wsocket, HTTP, sstr("")); + // } + // break; case 'R': for(int i = 0; i < list_size(workers); i++){ send_ipc_message(workers[i].wsocket, RESTART, sstr("")); @@ -256,7 +345,7 @@ int main(int argc, char *argv[]){ case 'q': case 'Q': while(list_size(workers) > 0){ shutdown(workers[0].wsocket, SHUT_RDWR); - //kill(workers[0].pid, SIGQUIT); // redo this PLEASE + kill(workers[0].pid, SIGTERM); // redo this PLEASE waitpid(workers[0].pid, NULL, 0); } while(wait(NULL) > 0); diff --git a/src/net/net.c b/src/net/net.c index 3e70cef..19792f1 100755 --- a/src/net/net.c +++ b/src/net/net.c @@ -12,8 +12,6 @@ str response_headers[] = { sstr("Transfer-Encoding"), }; -LIST(struct uri_mod) uri_rewrites = NULL; - static int pleasesslgivemetheerror(int ssl_get_error){ char *error; switch(ssl_get_error){ @@ -145,11 +143,11 @@ int setup_https(http_worker *hw, str certfile, str keyfile){ return 1; }*/ if(SSL_CTX_use_certificate_file(hw->ssl_ctx, certfile.ptr, SSL_FILETYPE_PEM) <= 0){ - log_error("Using certificate file"); + 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 ){ - log_error("Using private key file"); + log_error("Error while trying to set up key file"); return 1; } hw->ssl = SSL_new(hw->ssl_ctx); @@ -193,7 +191,7 @@ int accept_connection(http_worker *hw, char ip[INET_ADDRSTRLEN]){ int casize = sizeof(caddr); log_info("Waiting..."); if((hw->csocket = accept(hw->ssocket, (struct sockaddr *)&caddr, (socklen_t*)&casize)) == -1){ - log_error("accept_socket() -> accept(): %s", strerror(errno)); + log_error("accept_connection() -> accept(): %s", strerror(errno)); return -1; } log_info("accepted"); @@ -221,46 +219,56 @@ static inline int worker_read(http_worker *hw, str *buf){ int receive_request(http_worker *hw, 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 } }; - while((hw->secure && SSL_has_pending(hw->ssl)) || poll(pfd, 1, 100)){ - int new = worker_read(hw, request); - if(new < 0 || (hw->secure && new == 0)){ - int error = new; - if(hw->secure) error = pleasesslgivemetheerror(SSL_get_error(hw->ssl, new)); - else log_error("http (no s) error: %s", strerror(errno)); - return error; - } - request->len += new; - if(request->len == request->cap){ - log_info("gotta resize buffer"); - if(resize_str(request, request->cap*2) != 0){ - log_error("Not enough memory in reply str"); - return -1; + 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(rb == 0){ + return pleasesslgivemetheerror(SSL_get_error(hw->ssl, rb)); + } + } + }else{ + rb = worker_read(hw, request); + if(rb == 0){ + if(request->len == 0){ + return -1; + } + return 0; + } + if(rb < 0){ + return rb; + } + } + request->len += rb; + if(request->len == request->cap){ + log_debug("gotta resize buffer"); + if(resize_str(request, request->cap*2) != 0){ + log_error("Not enough memory in reply str"); + return -1; + } } + }else{ + log_error("Socket returned revents '%d'", pfd[0].revents); } } return 0; } -str generate_resource(struct uri resource, str url){ - str file = {0}; +str generate_resource(url resource, str rurl){ /* generate if all of these are true 1) no file specified (aka we need index.html) 2) theres an index.html.php 3) index.html isnt cached (future) */ - str phpfile = dnstr(resource.path.len + slen(".php")); - copy_strs(phpfile, resource.path, sstr(".php")); + str phpfile = dup_strs(resource.path, sstr(".php")); if(access(phpfile.ptr, F_OK) == 0){ // we need a str_copy or something - str command = dnstr( - slen("REQUEST_URI='") + resource.path.len + slen("' QUERY_STRING='") + resource.query.len + - slen("' URL='") + url.len + - slen("' php -c ./ ") + phpfile.len + slen(" > ") + resource.path.len - ); - copy_strs(command, + str command = dup_strs(command, sstr("REQUEST_URI='"), resource.path, sstr("' QUERY_STRING='"), resource.query, - sstr("' URL='"), url, + sstr("' URL='"), rurl, sstr("' php -c ./ "), phpfile, sstr(" > "), resource.path ); log_warn("command: %s", command.ptr); @@ -268,7 +276,7 @@ str generate_resource(struct uri resource, str url){ free_str(&command); } free_str(&phpfile); - file = dup_str(resource.path); + str file = dup_str(resource.path); /* if(uri.query.len > 0){ if(access(uri.path.ptr, F_OK) != 0){ @@ -343,8 +351,8 @@ void build_http_message(char *request, int rlen, struct http_message *hm){ while(request < end && *request != ' ') hm->method.len++, request++; if(++request >= end) return; - hm->uri.ptr = request; - while(request < end && *request != ' ') hm->uri.len++, request++; + hm->url.ptr = request; + while(request < end && *request != ' ') hm->url.len++, request++; if(++request >= end) return; hm->req_ver.ptr = request; @@ -393,7 +401,7 @@ __attribute__ ((optimize(3))) http_method get_http_method(str method){ static uint64_t http_len(struct http_message *hm){ uint64_t len = 0; - len += hm->method.len + hm->uri.len + hm->req_ver.len + 5 + 2; + len += hm->method.len + hm->url.len + hm->req_ver.len + 5 + 2; for(int i = 0; i < hm->hlen; ++i){ len += hm->headers[i].name.len + hm->headers[i].value.len + 4; } @@ -420,7 +428,7 @@ static uint64_t http_len(struct http_message *hm){ static str http_header_to_str(struct http_message *hm){ str s = {0}; s.ptr = calloc(http_len(hm) + 1, sizeof(char)); - copy_strs(s, hm->method, sstr(" "), hm->uri, sstr(" "), hm->req_ver, sstr("\r\n")); + copy_strs(s, hm->method, sstr(" "), hm->url, sstr(" "), hm->req_ver, sstr("\r\n")); for(int i = 0; i < hm->hlen; i++){ copy_strs(s, hm->headers[i].name, sstr(": "), hm->headers[i].value, sstr("\r\n")); } @@ -428,110 +436,28 @@ static str http_header_to_str(struct http_message *hm){ return s; } -/* - Given two strings p and u, and a uri (a struct with two strings) o - where p is a pattern, u is a url that is gonna checked for the pattern - and o is the uri output blueprint that must be returned should u follow p - - There is a tokens array where tokens found in the url can be stored (up to 9 tokens) - - In p: - optionally matches a character X and stores it in the tokens array - ^ optionally matches any character and stores it in the tokens array - * optionally matches a string of character until another match is found - or the url to match ends, and stores it in the tokens array - - In o: - $1 through $9 reference the tokens in the token array (I could make it 10 tokens tbh) - Both the strings in the uri can access these tokens - Referencing a token writes it to the output uri - If theres a token before a , say $3 that means that the character - between the less than and greater than signs will only be written - to the output if the token number 3 in the array exists (has length > 0) - All other characters get outputted normally -*/ -static struct uri uri_rewrite(str p, str u, struct uri o){ - int i = 0, j = 0, in = 0, ti = 0; - str tokens[9] = {0}; - for(; j < p.len; i += 1){ - if(i < u.len && p.ptr[j+in] == '<' && p.ptr[j+in+1] == u.ptr[i]){ - if(ti < 9) tokens[ti++] = (str){.ptr = u.ptr+i, .len = 1}; - j += 3+in, in = 0; - }else if(i < u.len && (p.ptr[j+in] == '^' || p.ptr[j+in] == u.ptr[i])){ - if(p.ptr[j] == '^' && ti < 9) tokens[ti++] = (str){.ptr = u.ptr+i, .len = 1}; - j += 1+in, in = 0; - }else if(i < u.len && p.ptr[j] == '*'){ - if(!in){ - if(ti < 9) tokens[ti++] = (str){.ptr = u.ptr+i, .len = 0}; - in = 1; - } - if(ti-in < 9) tokens[ti-in].len++; - }else{ - if(i >= u.len && p.ptr[j] == '*') j++; - else if(i >= u.len && p.ptr[j] == '<') j += 3; - else return (struct uri){0}; - } - } - if(i < u.len) return (struct uri){0}; - struct uri r = {0}; - str *no = &o.path, *nr = &r.path; - for(int k = 0, rlen = 0; k < 2; k++, no = &o.query, nr = &r.query){ - for(int i = 0; i < no->len; i++, rlen++){ - if(no->ptr[i] == '$') rlen += tokens[no->ptr[++i]-'1'].len-1; - } - nr->ptr = calloc(rlen+1, sizeof(char)); - if(nr->ptr == NULL){ - if(r.path.ptr != NULL) free(r.path.ptr); - return (struct uri){0}; - } - - for(int i = 0; i < no->len; i++){ - if(no->ptr[i] == '$'){ - if(++i+1 < no->len && no->ptr[i+1] == '<'){ - if(tokens[no->ptr[i]-'1'].len > 0) i++; - else while(no->ptr[++i] != '>'); - }else{ - copy_str((*nr), tokens[no->ptr[i]-'1']); - } - }else{ - if(no->ptr[i] != '>') nr->ptr[nr->len++] = no->ptr[i]; - } - } - } - - return r; -} - -struct uri sanitize_uri(str uri){ - str suri = {.ptr = calloc(uri.len+1, sizeof(char)), .len = 0}; - if(suri.ptr == NULL) return (struct uri){0}; - int i = 0, o = 0; - while(i+o < uri.len){ - suri.ptr[i] = lowerchar(uri.ptr[i+o]); - if(i > 0 && ( - (uri.ptr[i+o] == '/' && uri.ptr[i+o-1] == '/') || - (uri.ptr[i+o] == '.' && uri.ptr[i+o-1] == '.') || - (uri.ptr[i+o] == '/' && i+o+1 == uri.len) || - uri.ptr[i+o] == '%') +url sanitize_url(str rurl){ + str srurl = dnstr(rurl.len); + if(srurl.ptr == NULL) return (url){0}; + int o = 0; + while(srurl.len+o < rurl.len){ + srurl.ptr[srurl.len] = lowerchar(rurl.ptr[srurl.len+o]); + if(srurl.len > 0 && ( + (rurl.ptr[srurl.len+o] == '/' && rurl.ptr[srurl.len+o-1] == '/') || + (rurl.ptr[srurl.len+o] == '.' && rurl.ptr[srurl.len+o-1] == '.') || + (rurl.ptr[srurl.len+o] == '/' && srurl.len+o+1 == rurl.len) || + rurl.ptr[srurl.len+o] == '%') ){ ++o; }else{ - ++i; + srurl.len++; } } - suri.ptr[suri.len = i] = '\0'; - - struct uri u = {0}; - for(int i = 0; i < list_size(uri_rewrites); i++){ - u = uri_rewrite(uri_rewrites[i].pattern, suri, uri_rewrites[i].output); - if(u.path.len > 0) break; - } - free_str(&suri); - if(u.path.len == 0){ - u.path = dstr("localc/404/index.html"); - free_str(&u.query); - } + log_debug("before:\t'%.*s'", rurl.len, rurl.ptr); + log_debug("after:\t'%.*s'", srurl.len, srurl.ptr); + url u = url_check(srurl); + free_str(&srurl); return u; } @@ -611,36 +537,3 @@ void send_file(http_worker *hw, str filename){ } close(fd); } - -// this shouldnt be here -int read_uri_rewrites(char *map, uint64_t size){ - uint64_t i = 0; - if(strncmp(map, "rewrites", slen("rewrites")) != 0) return 1; - i += slen("rewrites"); - while(charisspace(map[i])) i++; - if(map[i++] != '{') return 1; - list_free(uri_rewrites); - init_nlist(uri_rewrites); - while(i < size && map[i] != '}'){ - struct uri_mod um = {0}; - i += ({sread_delim_f(map+i, charisspace, false);}).len; - i += ({um.pattern = read_delim_f(map+i, charisspace, true);}).len; - i += ({sread_delim_f(map+i, charisblank, false);}).len; - i += ({um.output.path = read_delim_f(map+i, charisspace, true);}).len; - i += ({sread_delim_f(map+i, charisblank, false);}).len; - i += ({um.output.query = read_delim_f(map+i, charisspace, true);}).len; - i += ({sread_delim(map+i, '\n');}).len + 1; - list_push(uri_rewrites, um); - } - return 0; -} - -void free_uri_rewrites(void){ - for(uint32_t i = 0; i < list_size(uri_rewrites); i++){ - free_str(&uri_rewrites[i].pattern); - free_str(&uri_rewrites[i].output.path); - free_str(&uri_rewrites[i].output.query); - } - list_free(uri_rewrites); -} - diff --git a/src/net/net.h b/src/net/net.h index dc7c147..297e417 100755 --- a/src/net/net.h +++ b/src/net/net.h @@ -20,6 +20,7 @@ #include "files/files.h" #include "log/log.h" #include "mime/mime.h" +#include "rewrites/rewrites.h" #include #include #include @@ -35,16 +36,6 @@ typedef enum http_method { } http_method; -struct uri { - str path; - str query; -}; - -struct uri_mod { - str pattern; - struct uri output; -}; - struct header { str name; str value; @@ -59,7 +50,7 @@ struct http_message { str resp_ver; }; union { - str uri; + str url; str status; }; union { @@ -106,7 +97,7 @@ int accept_connection(http_worker *hw, char ip[INET_ADDRSTRLEN]); int receive_request(http_worker *hw, str *request); -str generate_resource(struct uri resource, str url); +str generate_resource(url resource, str rurl); char *handlePOST(char *request); @@ -114,12 +105,8 @@ void build_http_message(char *request, int len, struct http_message *hm); enum http_method get_http_method(str method); -struct uri sanitize_uri(str uri); +url sanitize_url(str rurl); void send_file(http_worker *hw, str filename); -int read_uri_rewrites(char *map, uint64_t size); - -void free_uri_rewrites(void); - -#endif +#endif \ No newline at end of file diff --git a/src/rewrites/rewrites.c b/src/rewrites/rewrites.c new file mode 100644 index 0000000..3a9a762 --- /dev/null +++ b/src/rewrites/rewrites.c @@ -0,0 +1,160 @@ +#include "rewrites.h" + + +static rewrite *rewrites; + +void read_url_rewrites(str file){ + if(rewrites == NULL){ + init_nlist(rewrites); + } + int off = 0; + while(off < file.len){ + while(off < file.len && charisspace(file.ptr[off])) off++; + if(file.ptr[off] == '#'){ + while(off < file.len && !charislinebreak(file.ptr[off])) off++; + continue; + } + rewrite rwt = {0}; + rwt.pattern = sread_delim_f(file.ptr + off, charisspace, true); + off += rwt.pattern.len; + while(off < file.len && charisblank(file.ptr[off])) off++; + rwt.output.path = sread_delim_f(file.ptr + off, charisspace, true); + off += rwt.output.path.len; + while(off < file.len && charisblank(file.ptr[off])) off++; + rwt.output.query = sread_delim_f(file.ptr + off, charisspace, true); + 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); + } + } +} + +void free_url_rewrites(void){ + list_free(rewrites); +} + +int check_pattern(str text, str pattern, str tokens[9]){ + if(tokens == NULL){ + return 0; + } + int i = 0, j = 0, in = 0, ti = 0; + for(; j < pattern.len; i += 1){ + if(i < text.len && pattern.ptr[j+in] == '<' && pattern.ptr[j+in+1] == text.ptr[i]){ + if(ti < 9 && tokens) tokens[ti++] = (str){.ptr = text.ptr+i, .len = 1}; + j += 3+in, in = 0; + }else if(i < text.len && (pattern.ptr[j+in] == '^' || pattern.ptr[j+in] == text.ptr[i])){ + if(pattern.ptr[j] == '^' && ti < 9 && tokens) tokens[ti++] = (str){.ptr = text.ptr+i, .len = 1}; + j += 1+in, in = 0; + }else if(i < text.len && pattern.ptr[j] == '*'){ + if(!in){ + if(ti < 9 && tokens) tokens[ti++] = (str){.ptr = text.ptr+i, .len = 0}; + in = 1; + } + if(ti-in < 9 && tokens) tokens[ti-in].len++; + }else{ + if(i >= text.len && pattern.ptr[j] == '*') j++; + else if(i >= text.len && pattern.ptr[j] == '<') j += 3; + else return 0; + } + } + return (i >= text.len); +} + +str fill_blueprint(str bp, str tokens[9]){ + str r = {0}; + int rlen = 0; + for(int i = 0; i < bp.len; i++, rlen++){ + if(bp.ptr[i] == '$') rlen += tokens[bp.ptr[++i]-'1'].len-1; + } + r.ptr = calloc(rlen+1, sizeof(char)); + if(r.ptr == NULL){ + return r; + } + + for(int i = 0; i < bp.len; i++){ + if(bp.ptr[i] == '$'){ + if(++i+1 < bp.len && bp.ptr[i+1] == '<'){ + if(tokens[bp.ptr[i]-'1'].len > 0) i++; + else while(bp.ptr[++i] != '>'); + }else{ + copy_str(r, tokens[bp.ptr[i]-'1']); + } + }else{ + if(bp.ptr[i] != '>') r.ptr[r.len++] = bp.ptr[i]; + } + } + return r; +} + +/* + Given a rewrite, with a pattern (that is checked against the url) and an output + (that is used as an blueprintfor the output if the raw url follows the pattern) + + There is a tokens array where tokens found in the url can be stored (up to 9 tokens) + + In pattern: + optionally matches a character X and stores it in the tokens array + ^ optionally matches any character and stores it in the tokens array + * optionally matches a string of character until another match is found + or the url to match ends, and stores it in the tokens array + + In the ouput: + $1 through $9 reference the tokens in the token array (I could make it 10 tokens tbh) + Both the strings in the uri can access these tokens + Referencing a token writes it to the output uri + If theres a token before a , say $3 that means that the character + between the less than and greater than signs will only be written + to the output if the token number 3 in the array exists (has length > 0) + All other characters get outputted normally +*/ +url url_rewrite(str rurl, rewrite rwt){ + str tokens[9] = {0}; + if(!check_pattern(rurl, rwt.pattern, tokens)){ + return (url){0}; + } + url r = { + .path = fill_blueprint(rwt.output.path, tokens), + .query = fill_blueprint(rwt.output.query, tokens), + }; + if(r.path.len == 0){ + free_str(&r.path); + free_str(&r.query); + return (url){0}; + } + return r; +} + +url url_check(str rurl){ + str tokens[9] = {0}; + for(int i = 0; i < list_size(rewrites); i++){ + if(check_pattern(rurl, rewrites[i].pattern, tokens)){ + url r = { + .path = fill_blueprint(rewrites[i].output.path, tokens), + .query = fill_blueprint(rewrites[i].output.query, tokens), + }; + if(r.path.len == 0){ + free_str(&r.path); + free_str(&r.query); + } + return r; + } + } + return (url){0}; +} + +void print_url_rewrites(void){ + int size = list_size(rewrites); + printf("\t- rewrites:{\n"); + for(int i = 0; i < size; i++){ + printf("\t\t%.*s\t%.*s\t%.*s\n", + rewrites[i].pattern.len, rewrites[i].pattern.ptr, + rewrites[i].output.path.len, rewrites[i].output.path.ptr, + rewrites[i].output.query.len, rewrites[i].output.query.ptr + ); + } + printf("\t}\n"); +} diff --git a/src/rewrites/rewrites.h b/src/rewrites/rewrites.h new file mode 100644 index 0000000..14b77b2 --- /dev/null +++ b/src/rewrites/rewrites.h @@ -0,0 +1,29 @@ +#ifndef REWRITES_H +#define REWRITES_H + +#include "str/str.h" +#include "list/list.h" + + +typedef struct url { + str path; + str query; +} url; + +typedef struct rewrite { + str pattern; + url output; +} rewrite; + + +void read_url_rewrites(str file); +void free_url_rewrites(void); + +int check_pattern(str text, str pattern, str tokens[9]); +str fill_blueprint(str bp, str tokens[9]); +url url_rewrite(str url, rewrite rwt); +url url_check(str url); + +void print_url_rewrites(void); + +#endif \ No newline at end of file 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; } -- cgit v1.2.3