aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorcbdev <cb@cbcdn.com>2019-06-02 15:45:12 +0200
committercbdev <cb@cbcdn.com>2019-06-02 15:45:12 +0200
commitedcec9fa9086599d56bffe7fdb2c1f05ae7a3ad8 (patch)
tree4e2bb02bbe8a2db9d4f217a664e73c25c37c7633
parentb9297647c68c963a977e2c18f421211e24f9e85a (diff)
downloadwebsocksy-edcec9fa9086599d56bffe7fdb2c1f05ae7a3ad8.tar.gz
websocksy-edcec9fa9086599d56bffe7fdb2c1f05ae7a3ad8.tar.bz2
websocksy-edcec9fa9086599d56bffe7fdb2c1f05ae7a3ad8.zip
File backend peer query
-rw-r--r--index.html2
-rw-r--r--makefile5
-rw-r--r--plugin.c2
-rw-r--r--plugins/backend_file.c111
-rw-r--r--plugins/makefile2
-rw-r--r--websocksy.c28
-rw-r--r--websocksy.h3
7 files changed, 136 insertions, 17 deletions
diff --git a/index.html b/index.html
index 1981b83..71cd697 100644
--- a/index.html
+++ b/index.html
@@ -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);
diff --git a/makefile b/makefile
index c389148..20b6579 100644
--- a/makefile
+++ b/makefile
@@ -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)
diff --git a/plugin.c b/plugin.c
index 674e992..d8500fe 100644
--- a/plugin.c
+++ b/plugin.c
@@ -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);