diff options
-rw-r--r-- | index.html | 2 | ||||
-rw-r--r-- | makefile | 5 | ||||
-rw-r--r-- | plugin.c | 2 | ||||
-rw-r--r-- | plugins/backend_file.c | 111 | ||||
-rw-r--r-- | plugins/makefile | 2 | ||||
-rw-r--r-- | websocksy.c | 28 | ||||
-rw-r--r-- | websocksy.h | 3 |
7 files changed, 136 insertions, 17 deletions
@@ -6,7 +6,7 @@ function openSocket(){ setTimeout(function(){ - webSocket = new WebSocket("ws://localhost:8001/foo/bar", ["p1", "p2"]); + webSocket = new WebSocket("ws://localhost:8001/test", ["p1", "p2"]); webSocket.onclose = openSocket; webSocket.onmessage = function(event){ console.log(event.data); @@ -1,5 +1,5 @@ .PHONY: all clean plugins -PLUGINPATH=plugins/ +PLUGINPATH?=plugins/ CFLAGS=-g -Wall -Wpedantic -DPLUGINS=\"$(PLUGINPATH)\" LDLIBS=-lnettle -ldl @@ -11,8 +11,9 @@ all: websocksy plugins: $(MAKE) -C plugins +websocksy: LDFLAGS += -Wl,-export-dynamic websocksy: websocksy.c websocksy.h $(OBJECTS) plugins - $(CC) $(CFLAGS) $(LDLIBS) $< -o $@ $(OBJECTS) + $(CC) $(CFLAGS) $(LDFLAGS) $(LDLIBS) $< -o $@ $(OBJECTS) clean: $(RM) $(OBJECTS) @@ -19,7 +19,7 @@ static size_t attached_libraries = 0; static void** attached_library = NULL; static void* plugin_attach(char* path){ - void* module = dlopen(path, RTLD_LAZY); + void* module = dlopen(path, RTLD_NOW); if(!module){ fprintf(stderr, "Failed to load module %s\n", dlerror()); diff --git a/plugins/backend_file.c b/plugins/backend_file.c index c3ed8ea..a858ef4 100644 --- a/plugins/backend_file.c +++ b/plugins/backend_file.c @@ -84,7 +84,11 @@ static int expression_resolve(char* template, size_t length, char* endpoint, siz return 1; } - //TODO rtrim slash + //rtrim slash so test and test/ are the same file + if(strlen(endpoint) >= 2 && endpoint[strlen(endpoint) - 1] == '/'){ + endpoint[strlen(endpoint) - 1] = 0; + } + //replace with sanitized endpoint string for(p = 0; endpoint[p]; p++){ if(endpoint[p] == '/'){ @@ -106,7 +110,45 @@ static int expression_resolve(char* template, size_t length, char* endpoint, siz return 1; } - //TODO iterate cookies + //find the cookie header + for(p = 0; p < headers; p++){ + if(!strcmp(header[p].tag, "Cookie")){ + value = header[p].value; + break; + } + } + + //no cookie header, fail the expression + if(p == headers){ + return 1; + } + + do{ + //ensure min length of cookie name + if(strlen(value) < index_len + 1){ + return 1; + } + //check if cookie found + if(value[index_len] == '=' + && !strncmp(value, index, index_len)){ + value += index_len + 1; + for(value_len = 0; value[value_len] && value[value_len] != ';'; value_len++){ + } + break; + } + //skip to next cookie + for(; *value && strncmp(value, "; ", 2); value++){ + } + if(*value){ + value += 2; + } + } while(*value); + + if(!*value){ + return 1; + } + + variable_len = 8 + index_len + 1; } else if(!strncmp(template + u, "%header:", 8)){ //scan headers @@ -140,9 +182,10 @@ static int expression_resolve(char* template, size_t length, char* endpoint, siz fprintf(stderr, "Expression replacement failed\n"); return 1; } - - //skip the inserted value - u += value_len - 1; + if(value){ + //skip the inserted value + u += value_len - 1; + } } } @@ -150,13 +193,14 @@ static int expression_resolve(char* template, size_t length, char* endpoint, siz } ws_peer_info query(char* endpoint, size_t protocols, char** protocol, size_t headers, ws_http_header* header, websocket* ws){ - size_t u, line_alloc = 0; + size_t u, p, line_alloc = 0; ssize_t line_length = 0; - char* line = NULL; + char* line = NULL, *components[3]; FILE* input = NULL; char target_path[BACKEND_FILE_MAX_PATH]; ws_peer_info peer = { .transport = peer_transport_detect, + .protocol = protocols }; for(u = 0; u < expressions; u++){ @@ -165,7 +209,7 @@ ws_peer_info query(char* endpoint, size_t protocols, char** protocol, size_t hea if(expression_resolve(target_path + strlen(backend_path) + 1, sizeof(target_path) - strlen(backend_path) - 1, endpoint, headers, header)){ continue; } - + //check whether the file exists input = fopen(target_path, "r"); if(!input){ @@ -174,8 +218,55 @@ ws_peer_info query(char* endpoint, size_t protocols, char** protocol, size_t hea //read it for(line_length = getline(&line, &line_alloc, input); line_length >= 0; line_length = getline(&line, &line_alloc, input)){ - //TODO evaluate line in file - fprintf(stderr, "File %s, line %s\n", target_path, line); + memset(components, 0, sizeof(components)); + //TODO rtrim line + + //read lines of host subproto framing framing-config + components[0] = strchr(line, ' '); + if(protocols && !components[0]){ + continue; + } + + //terminate host + components[0][0] = 0; + components[0]++; + + //find framing, terminate subprotocol + components[1] = strchr(components[0], ' '); + if(components[1]){ + components[1][0] = 0; + components[1]++; + + //find find framing config, terminate framing + components[2] = strchr(components[1], ' '); + if(components[2]){ + components[2][0] = 0; + components[2]++; + } + } + + //find a match for any indicated protocol + for(p = 0; p < protocols; p++){ + if(!strcmp(components[0], protocol[p])){ + peer.protocol = p; + break; + } + } + + //for '*' use the first available protocol + if(components[0] && !strcmp(components[0], "*")){ + peer.protocol = 0; + } + + //the current line does not match any indicated protocols + if(protocols && peer.protocol == protocols){ + continue; + } + + peer.host = strdup(line); + peer.framing = core_framing(components[1]); + peer.framing_config = components[2] ? strdup(components[2]) : NULL; + break; } fclose(input); diff --git a/plugins/makefile b/plugins/makefile index 6b413db..1a6ef36 100644 --- a/plugins/makefile +++ b/plugins/makefile @@ -1,7 +1,7 @@ .PHONY: all clean PLUGINS = backend_file.so -CFLAGS += -fPIC -I../ +CFLAGS += -fPIC -g -I../ LDFLAGS += -shared %.so :: %.c %.h diff --git a/websocksy.c b/websocksy.c index c635ca7..7727ef0 100644 --- a/websocksy.c +++ b/websocksy.c @@ -125,12 +125,23 @@ static peer_transport client_detect_transport(char* host){ return peer_tcp_client; } +static char* client_detect_port(char* host){ + size_t u; + + for(u = 0; host[u]; u++){ + if(host[u] == ':'){ + host[u] = 0; + return strdup(host + u + 1); + } + } + + return NULL; +} + /* Establish peer connection for negotiated websocket */ int client_connect(websocket* ws){ ws->peer = config.backend.query(ws->request_path, ws->protocols, ws->protocol, ws->headers, ws->header, ws); if(!ws->peer.host){ - //TODO check port if network socket - //TODO try to extract port from host if none given //no peer provided return 1; } @@ -145,6 +156,15 @@ int client_connect(websocket* ws){ ws->peer.transport = client_detect_transport(ws->peer.host); } + if((ws->peer.transport == peer_tcp_client || ws->peer.transport == peer_udp_client) + && !ws->peer.port){ + ws->peer.port = client_detect_port(ws->peer.host); + if(!ws->peer.port){ + //no port provided + return 1; + } + } + //TODO connection establishment should be async in the future switch(ws->peer.transport){ case peer_tcp_client: @@ -172,6 +192,10 @@ int client_connect(websocket* ws){ return (ws->peer_fd == -1) ? 1 : 0; } +ws_framing core_framing(char* name){ + return plugin_framing(name); +} + /* Signal handler, attached to SIGINT */ static void signal_handler(int signum){ shutdown_requested = 1; diff --git a/websocksy.h b/websocksy.h index 39ce9c7..b2b2285 100644 --- a/websocksy.h +++ b/websocksy.h @@ -196,6 +196,9 @@ typedef struct /*_ws_backend*/ { ws_backend_cleanup cleanup; } ws_backend; +/* Core API */ +ws_framing core_framing(char* name); + /* Internal helper functions */ char* xstr_lower(char* in); int client_register(websocket* ws); |