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
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 \

View File

@ -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");

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;
//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;

View File

@ -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*);

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..");
}