summaryrefslogtreecommitdiff
path: root/src/net
diff options
context:
space:
mode:
authorSoikk2025-11-22 16:42:08 +0100
committerSoikk2025-11-22 16:42:08 +0100
commit3abcc43f1e638608b4b88bbb0ad7881d74940f8d (patch)
treed5b5e2bf93ff0bbcf3c3d860c2266516e91492c4 /src/net
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/net')
-rwxr-xr-xsrc/net/net.c225
-rwxr-xr-xsrc/net/net.h23
2 files changed, 64 insertions, 184 deletions
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:
- <X> 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 <X>, say $3<a> 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 <openssl/ssl.h>
#include <openssl/err.h>
#include <poll.h>
@@ -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