support websocket frame fragments (binary data)

This commit is contained in:
lxsang 2016-12-13 16:34:03 +01:00
parent a720d8ff9c
commit 6d32fdfc3d
5 changed files with 118 additions and 6 deletions

View File

@ -20,7 +20,7 @@ ifeq ($(UNAME_S),Darwin)
endif endif
CFLAGS=-W -Wall -g -std=c99 -D DEBUG -D USE_DB $(PF_FLAG) CFLAGS=-W -Wall -g -std=c99 -D DEBUG -D USE_DB $(PF_FLAG)
#-lsocket #-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 \ PLUGINSDEP = plugins/ini.o \
plugins/plugin.o \ plugins/plugin.o \

View File

@ -35,6 +35,7 @@ int request_socket(const char* ip, int port)
perror("Socket"); perror("Socket");
return -1; return -1;
} }
if (setsockopt (sockfd, SOL_SOCKET, SO_RCVTIMEO, &timeout,sizeof(timeout)) < 0) if (setsockopt (sockfd, SOL_SOCKET, SO_RCVTIMEO, &timeout,sizeof(timeout)) < 0)
perror("setsockopt failed\n"); perror("setsockopt failed\n");

View File

@ -102,6 +102,7 @@ void _send_header(int client, ws_msg_header_t header)
for(int i=0; i< 8; i++) bytes[i] = 0; for(int i=0; i< 8; i++) bytes[i] = 0;
//first byte |FIN|000|opcode| //first byte |FIN|000|opcode|
byte = (header.fin << 7) + header.opcode; byte = (header.fin << 7) + header.opcode;
//printf("BYTE: %d\n", byte);
send(client, &byte, 1, 0); send(client, &byte, 1, 0);
// second byte, payload length // second byte, payload length
// mask = 0 // 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 * send a text data frame to client
*/ */
void ws_t(int client, const char* data) void ws_t(int client, const char* data)
@ -138,11 +150,12 @@ void ws_t(int client, const char* data)
header.fin = 1; header.fin = 1;
header.opcode = WS_TEXT; header.opcode = WS_TEXT;
header.plen = strlen(data); header.plen = strlen(data);
_send_header(client,header); //_send_header(client,header);
send(client, data, header.plen,0); //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 * not tested yet, but should work
*/ */
void ws_b(int client, uint8_t* data, int l) 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.fin = 1;
header.opcode = WS_BIN; header.opcode = WS_BIN;
header.plen = l; header.plen = l;
_send_header(client,header); ws_send_frame(client,data, header);
send(client, data, header.plen,0); //_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 * Not tested yet
@ -160,6 +215,7 @@ void ws_b(int client, uint8_t* data, int l)
*/ */
void pong(int client, int len) void pong(int client, int len)
{ {
//printf("PONG\n");
ws_msg_header_t pheader; ws_msg_header_t pheader;
pheader.fin = 1; pheader.fin = 1;
pheader.opcode = WS_PONG; pheader.opcode = WS_PONG;
@ -174,6 +230,7 @@ void pong(int client, int len)
*/ */
void ws_close(int client, unsigned int status) void ws_close(int client, unsigned int status)
{ {
//printf("CLOSED\n");
ws_msg_header_t header; ws_msg_header_t header;
header.fin = 1; header.fin = 1;
header.opcode = WS_CLOSE; header.opcode = WS_CLOSE;

View File

@ -19,8 +19,10 @@ typedef struct{
} ws_msg_header_t; } ws_msg_header_t;
ws_msg_header_t * ws_read_header(int); 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_t(int , const char* );
void ws_b(int , uint8_t* data, int); void ws_b(int , uint8_t* data, int);
void ws_f(int, const char*);
void ws_close(int, unsigned int); void ws_close(int, unsigned int);
void pong(int client, int len); void pong(int client, int len);
int ws_read_data(int , ws_msg_header_t*, int, uint8_t*); int ws_read_data(int , ws_msg_header_t*, int, uint8_t*);

52
plugins/wsimg/wsimg.c Normal file
View File

@ -0,0 +1,52 @@
#include <stdlib.h>
#include <string.h>
#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..");
}