From 6d32fdfc3d88ff4472897e2a825fa8818c5f8cb0 Mon Sep 17 00:00:00 2001 From: lxsang Date: Tue, 13 Dec 2016 16:34:03 +0100 Subject: [PATCH] support websocket frame fragments (binary data) --- Makefile | 2 +- plugins/nodedaemon/nodedaemon.c | 1 + plugins/ws.c | 67 ++++++++++++++++++++++++++++++--- plugins/ws.h | 2 + plugins/wsimg/wsimg.c | 52 +++++++++++++++++++++++++ 5 files changed, 118 insertions(+), 6 deletions(-) create mode 100644 plugins/wsimg/wsimg.c diff --git a/Makefile b/Makefile index bcc4d67..2ab0146 100644 --- a/Makefile +++ b/Makefile @@ -20,7 +20,7 @@ ifeq ($(UNAME_S),Darwin) endif CFLAGS=-W -Wall -g -std=c99 -D DEBUG -D USE_DB $(PF_FLAG) #-lsocket -PLUGINS= dummy.$(EXT) fileman.$(EXT) pluginsman.$(EXT) wterm.$(EXT) nodedaemon.$(EXT) cookiex.$(EXT) +PLUGINS= dummy.$(EXT) fileman.$(EXT) pluginsman.$(EXT) wterm.$(EXT) nodedaemon.$(EXT) cookiex.$(EXT) wsimg.$(EXT) PLUGINSDEP = plugins/ini.o \ plugins/plugin.o \ diff --git a/plugins/nodedaemon/nodedaemon.c b/plugins/nodedaemon/nodedaemon.c index 497141c..dd01bae 100644 --- a/plugins/nodedaemon/nodedaemon.c +++ b/plugins/nodedaemon/nodedaemon.c @@ -35,6 +35,7 @@ int request_socket(const char* ip, int port) perror("Socket"); return -1; } + if (setsockopt (sockfd, SOL_SOCKET, SO_RCVTIMEO, &timeout,sizeof(timeout)) < 0) perror("setsockopt failed\n"); diff --git a/plugins/ws.c b/plugins/ws.c index 88f0773..e64c23f 100644 --- a/plugins/ws.c +++ b/plugins/ws.c @@ -102,6 +102,7 @@ void _send_header(int client, ws_msg_header_t header) for(int i=0; i< 8; i++) bytes[i] = 0; //first byte |FIN|000|opcode| byte = (header.fin << 7) + header.opcode; + //printf("BYTE: %d\n", byte); send(client, &byte, 1, 0); // second byte, payload length // mask = 0 @@ -130,6 +131,17 @@ void _send_header(int client, ws_msg_header_t header) } } /** +* Send a frame to client +*/ +void ws_send_frame(int client, uint8_t* data, ws_msg_header_t header) +{ + _send_header(client, header); + if(header.opcode == WS_TEXT) + send(client,(char*)data,header.plen,0); + else + send(client,(uint8_t*)data,header.plen,0); +} +/** * send a text data frame to client */ void ws_t(int client, const char* data) @@ -138,11 +150,12 @@ void ws_t(int client, const char* data) header.fin = 1; header.opcode = WS_TEXT; header.plen = strlen(data); - _send_header(client,header); - send(client, data, header.plen,0); + //_send_header(client,header); + //send(client, data, header.plen,0); + ws_send_frame(client,data,header); } /** -* send a binary data fram to client +* send a single binary data fram to client * not tested yet, but should work */ void ws_b(int client, uint8_t* data, int l) @@ -151,8 +164,50 @@ void ws_b(int client, uint8_t* data, int l) header.fin = 1; header.opcode = WS_BIN; header.plen = l; - _send_header(client,header); - send(client, data, header.plen,0); + ws_send_frame(client,data, header); + //_send_header(client,header); + //send(client, data, header.plen,0); +} +/* +* send a file as binary data +*/ +void ws_f(int client, const char* file) +{ + uint8_t buff[1024]; + FILE *ptr; + ptr = fopen(file,"rb"); + if(!ptr) + { + return; + } + + ws_msg_header_t header; + size_t size; + int first_frame = 1; + //ws_send_frame(client,buff,header); + while(!feof(ptr)) + { + size = fread(buff,1,1024,ptr); + if(size >= 0) + { + if(feof(ptr)) + header.fin = 1; + else + header.fin = 0; + // clear opcode + if(first_frame) + { + header.opcode = WS_BIN; + first_frame = 0; + } + else + header.opcode = 0; + header.plen = size; + //printf("FIN: %d OC:%d\n", header.fin, header.opcode); + ws_send_frame(client,buff,header); + } + } + fclose(ptr); } /** * Not tested yet @@ -160,6 +215,7 @@ void ws_b(int client, uint8_t* data, int l) */ void pong(int client, int len) { + //printf("PONG\n"); ws_msg_header_t pheader; pheader.fin = 1; pheader.opcode = WS_PONG; @@ -174,6 +230,7 @@ void pong(int client, int len) */ void ws_close(int client, unsigned int status) { + //printf("CLOSED\n"); ws_msg_header_t header; header.fin = 1; header.opcode = WS_CLOSE; diff --git a/plugins/ws.h b/plugins/ws.h index 3cc5825..2a343ff 100644 --- a/plugins/ws.h +++ b/plugins/ws.h @@ -19,8 +19,10 @@ typedef struct{ } ws_msg_header_t; ws_msg_header_t * ws_read_header(int); +void ws_send_frame(int , uint8_t* , ws_msg_header_t ); void ws_t(int , const char* ); void ws_b(int , uint8_t* data, int); +void ws_f(int, const char*); void ws_close(int, unsigned int); void pong(int client, int len); int ws_read_data(int , ws_msg_header_t*, int, uint8_t*); diff --git a/plugins/wsimg/wsimg.c b/plugins/wsimg/wsimg.c new file mode 100644 index 0000000..0ee1afc --- /dev/null +++ b/plugins/wsimg/wsimg.c @@ -0,0 +1,52 @@ +#include +#include +#include "../plugin.h" + +void pexit() +{ + +} +void handler(int cl, const char* m, const char* rqp, dictionary rq) +{ + char* path = NULL; + int nimg = 19; + ws_msg_header_t* h = NULL; + uint8_t buff[8]; + if(ws_enable(rq)) + { + while(1) + { + h = ws_read_header(cl); + if(h) + { + if(h->opcode == WS_CLOSE) + { + LOG("%s\n","Websocket: connection closed"); + ws_close(cl, 1011); + break; + } + else if(h->opcode == WS_BIN) + { + int l; + if((l = ws_read_data(cl,h,sizeof(buff),buff)) > 0) + { + + path = __s("%s/ws/img%d.jpg",__plugin__.htdocs,buff[0]); + LOG("%s : %s\n", "send back data of", path); + ws_f(cl,path); + free(path); + } + else + { + LOG("%s\n","Invalid request"); + ws_close(cl, 1011); + break; + } + } + + free(h); + } + } + } + LOG("%s\n", "EXIT Streaming.."); +} \ No newline at end of file