76 lines
2.0 KiB
C++
76 lines
2.0 KiB
C++
|
#include "WebSocketParser.h"
|
||
|
|
||
|
#include "websocket_parser.h"
|
||
|
#include "hdef.h"
|
||
|
|
||
|
#define MAX_PAYLOAD_LENGTH (1 << 24) // 16M
|
||
|
|
||
|
static int on_frame_header(websocket_parser* parser) {
|
||
|
WebSocketParser* wp = (WebSocketParser*)parser->data;
|
||
|
int opcode = parser->flags & WS_OP_MASK;
|
||
|
// printf("on_frame_header opcode=%d\n", opcode);
|
||
|
if (opcode != WS_OP_CONTINUE) {
|
||
|
wp->opcode = opcode;
|
||
|
}
|
||
|
int length = parser->length;
|
||
|
int reserve_length = MIN(length + 1, MAX_PAYLOAD_LENGTH);
|
||
|
if (reserve_length > wp->message.capacity()) {
|
||
|
wp->message.reserve(reserve_length);
|
||
|
}
|
||
|
if (wp->state == WS_FRAME_BEGIN ||
|
||
|
wp->state == WS_FRAME_FIN) {
|
||
|
wp->message.clear();
|
||
|
}
|
||
|
wp->state = WS_FRAME_HEADER;
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
static int on_frame_body(websocket_parser* parser, const char * at, size_t length) {
|
||
|
// printf("on_frame_body length=%d\n", (int)length);
|
||
|
WebSocketParser* wp = (WebSocketParser*)parser->data;
|
||
|
wp->state = WS_FRAME_BODY;
|
||
|
if (wp->parser->flags & WS_HAS_MASK) {
|
||
|
websocket_parser_decode((char*)at, at, length, wp->parser);
|
||
|
}
|
||
|
wp->message.append(at, length);
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
static int on_frame_end(websocket_parser* parser) {
|
||
|
// printf("on_frame_end\n");
|
||
|
WebSocketParser* wp = (WebSocketParser*)parser->data;
|
||
|
wp->state = WS_FRAME_END;
|
||
|
if (wp->parser->flags & WS_FIN) {
|
||
|
wp->state = WS_FRAME_FIN;
|
||
|
if (wp->onMessage) {
|
||
|
wp->onMessage(wp->opcode, wp->message);
|
||
|
}
|
||
|
}
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
static websocket_parser_settings cbs = {
|
||
|
on_frame_header,
|
||
|
on_frame_body,
|
||
|
on_frame_end
|
||
|
};
|
||
|
|
||
|
WebSocketParser::WebSocketParser() {
|
||
|
parser = (websocket_parser*)malloc(sizeof(websocket_parser));
|
||
|
websocket_parser_init(parser);
|
||
|
parser->data = this;
|
||
|
state = WS_FRAME_BEGIN;
|
||
|
opcode = WS_OP_CLOSE;
|
||
|
}
|
||
|
|
||
|
WebSocketParser::~WebSocketParser() {
|
||
|
if (parser) {
|
||
|
free(parser);
|
||
|
parser = NULL;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
int WebSocketParser::FeedRecvData(const char* data, size_t len) {
|
||
|
return websocket_parser_execute(parser, &cbs, data, len);
|
||
|
}
|