aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--plugins/framing_dynamic32.c74
-rw-r--r--plugins/framing_dynamic32.md21
-rw-r--r--plugins/makefile2
3 files changed, 96 insertions, 1 deletions
diff --git a/plugins/framing_dynamic32.c b/plugins/framing_dynamic32.c
new file mode 100644
index 0000000..3b66588
--- /dev/null
+++ b/plugins/framing_dynamic32.c
@@ -0,0 +1,74 @@
+#include <stdio.h>
+#include <string.h>
+#include <endian.h>
+
+#include "../websocksy.h"
+
+typedef struct /*_framing_config*/ {
+ uint32_t offset;
+ int32_t fixed;
+ uint8_t endian;
+} dynamic32_config_t;
+
+static int64_t framing_dynamic32(uint8_t* data, size_t length, size_t last_read, ws_operation* opcode, void** framing_data, const char* config){
+ size_t u;
+ uint32_t* size_p, size = 0;
+ //get the current config if set
+ dynamic32_config_t* conncfg = (*framing_data) ? ((dynamic32_config_t*) (*framing_data)) : NULL;
+
+ //configure framing for this connection
+ if(data && !conncfg){
+ conncfg = calloc(1, sizeof(dynamic32_config_t));
+ if(!conncfg){
+ fprintf(stderr, "Failed to allocate memory\n");
+ return -1;
+ }
+
+ //parse config string
+ for(u = 0; config[u];){
+ if(!strncmp(config + u, "offset=", 7)){
+ conncfg->offset = strtoul(config + u + 7, NULL, 0);
+ }
+ else if(!strncmp(config + u, "static=", 7)){
+ conncfg->fixed = strtoul(config + u + 7, NULL, 0);
+ }
+ else if(!strncmp(config + u, "endian=", 7)){
+ conncfg->endian = 0;
+ if(!strncmp(config + u + 7, "big", 3)){
+ conncfg->endian = 1;
+ }
+ }
+
+ //skip to next item
+ for(; config[u] && config[u] != ','; u++){
+ }
+ }
+
+ //store configuration
+ *framing_data = conncfg;
+ }
+ //clean up configuration
+ else if(!data && conncfg){
+ free(*framing_data);
+ *framing_data = NULL;
+ }
+
+ if(length > conncfg->offset + 4){
+ //read size field
+ size_p = (uint32_t*) (data + conncfg->offset);
+ size = le32toh(*size_p);
+ if(conncfg->endian){
+ size = be32toh(*size_p);
+ }
+
+ if(length >= conncfg->offset + 4 + conncfg->fixed + size){
+ return conncfg->offset + 4 + conncfg->fixed + size;
+ }
+ }
+
+ return 0;
+}
+
+static void __attribute__((constructor)) init(){
+ core_register_framing("dynamic32", framing_dynamic32);
+}
diff --git a/plugins/framing_dynamic32.md b/plugins/framing_dynamic32.md
new file mode 100644
index 0000000..51ca04c
--- /dev/null
+++ b/plugins/framing_dynamic32.md
@@ -0,0 +1,21 @@
+# The `dynamic32` framing function
+
+The `dynamic32` peer stream framing function segments the peer stream into binary frames
+at dynamic byte boundaries inferred from the stream data itself. The function will read
+a 32bit length value at a specified offset from the stream and treat it as the length
+of the next segment to be framed.
+
+## Configuration
+
+The framing configuration string may be a comma-separated list of options of the form
+`<key>=<value>`, containing one or more of the following keys:
+
+* `offset`: Set the offset (in bytes) of the 32-bit segment size in the stream, counted from the start of a segment/stream (Default: `0`)
+* `static`: Static amount to add to the segment length, e.g. to account for fixed headers (Default: `0`)
+* `endian`: Set the byte order of the transmitteed size to either `big` or `little` (Default: `little`)
+
+The total size of the segment sent to the Websocket peer can be calculated using the formula
+
+```
+offset + 4 /*32bit size field*/ + static + size field content
+```
diff --git a/plugins/makefile b/plugins/makefile
index b09466d..f0b38cb 100644
--- a/plugins/makefile
+++ b/plugins/makefile
@@ -1,5 +1,5 @@
.PHONY: all clean
-PLUGINS = backend_file.so framing_fixedlength.so framing_json.so
+PLUGINS = backend_file.so framing_fixedlength.so framing_json.so framing_dynamic32.so
CFLAGS += -fPIC -g -I../
LDFLAGS += -shared