35 #define FRAME_CHUNK_LENGTH 1024
37 #define WS_OPCODE_CONTINUE 0x0
38 #define WS_OPCODE_TEXT 0x1
39 #define WS_OPCODE_BINARY 0x2
40 #define WS_OPCODE_CLOSE 0x8
41 #define WS_OPCODE_PING 0x9
42 #define WS_OPCODE_PONG 0xa
44 #define WS_FRAGMENT_FIN (1 << 7)
46 #define WS_CLOSE_NORMAL 1000
47 #define WS_CLOSE_GOING_AWAY 1001
48 #define WS_CLOSE_PROTOCOL_ERROR 1002
49 #define WS_CLOSE_NOT_ALLOWED 1003
50 #define WS_CLOSE_RESERVED 1004
51 #define WS_CLOSE_NO_CODE 1005
52 #define WS_CLOSE_DIRTY 1006
53 #define WS_CLOSE_WRONG_TYPE 1007
54 #define WS_CLOSE_POLICY_VIOLATION 1008
55 #define WS_CLOSE_MESSAGE_TOO_BIG 1009
56 #define WS_CLOSE_UNEXPECTED_ERROR 1011
94 frame->
fin = (*(frame->
rawdata) & 0x80) == 0x80 ? 1 : 0;
107 *((
unsigned short int *) (frame->
rawdata + 2)));
135 new_size = frame->
size;
137 new_size |= new_size >> 1;
138 new_size |= new_size >> 2;
139 new_size |= new_size >> 4;
140 new_size |= new_size >> 8;
141 new_size |= new_size >> 16;
154 unsigned int *payload_len_32_be;
155 unsigned short int *payload_len_short_be;
156 unsigned char finNopcode, payload_len_small;
157 unsigned int payload_offset = 2;
158 unsigned int frame_size;
161 finNopcode = flags & 0xff;
163 frame_size = 2 + len;
164 payload_len_small = len & 0xff;
165 }
else if (len > 125 && len <= 0xffff) {
166 frame_size = 4 + len;
167 payload_len_small = 126;
169 }
else if (len > 0xffff && len <= 0xfffffff0) {
170 frame_size = 10 + len;
171 payload_len_small = 127;
175 "libwebsock does not support frame payload sizes over %u bytes long\n",
181 payload_len_small &= 0x7f;
183 *(frame + 1) = payload_len_small;
184 if (payload_len_small == 126) {
186 payload_len_short_be = (
unsigned short *) ((
char *) frame + 2);
187 *payload_len_short_be = htons(len);
189 if (payload_len_small == 127) {
190 payload_len_32_be = (
unsigned int *) ((
char *) frame + 2);
191 *payload_len_32_be++ = 0;
192 *payload_len_32_be = htonl(len);
194 memcpy(frame + payload_offset, data, len);
214 unsigned short code_be;
217 code_be = htobe16(code);
218 memcpy(buf, &code_be, 2);
220 len += snprintf(buf + 2, 124,
"%s", reason);
236 char close_frame[4] = { 0x88, 0x02, 0x00, 0x00 };
237 unsigned short *code_be = (
unsigned short *) &close_frame[2];
241 memcpy(buf->
data, close_frame, buf->
len);
279 _sx_debug(
ZONE,
"HTTP headers complete: %d %s HTTP/%d.%d", parser->status_code, http_method_str(parser->method), parser->http_major, parser->http_minor);
291 "Server: " PACKAGE_STRING
"\r\n"
292 "Expires: Fri, 10 Oct 1997 10:10:10 GMT\r\n"
293 "Pragma: no-cache\r\n"
294 "Cache-control: private\r\n"
300 va_start(args, headers_format);
301 vsnprintf(headers,
sizeof(headers), headers_format, args);
306 buf->
len = sprintf(buf->
data, http, status, headers);
318 unsigned char hash[20];
360 char * accept =
b64_encode(hash,
sizeof(hash));
364 "Upgrade: websocket\r\n"
365 "Connection: Upgrade\r\n"
366 "Sec-WebSocket-Accept: %s\r\n"
367 "Sec-WebSocket-Protocol: xmpp\r\n",
376 }
else if (ret != buf->
len) {
382 char *http_forward = p->
private;
383 _sx_debug(
ZONE,
"bouncing HTTP request to %s", http_forward);
409 char *data = buf->
data;
410 for (i = 0; i < buf->
len;) {
412 if (sc->
frame == NULL) {
467 for (i = 0; i < buf->
len; i++)
471 if (buf->
len >= 7 && strncmp(buf->
data,
"<open", 5) == 0 && strncmp(buf->
data + buf->
len - 2,
"/>", 2) == 0) {
546 http_parser_init(&sc->
parser, HTTP_REQUEST);
582 char *http_forward = va_arg(args,
char*);
enum WS_FRAME_STATE state
void(* free)(sx_t s, sx_plugin_t p)
static void _sx_websocket_http_return(sx_t s, char *status, char *headers_format,...)
#define _sx_event(s, e, data)
void(* server)(sx_t s, sx_plugin_t p)
#define WS_CLOSE_PROTOCOL_ERROR
char * b64_encode(char *buf, int len)
void libwebsock_fail_connection(sx_t s, _sx_websocket_conn_t sc, unsigned short close_code)
int j_atoi(const char *a, int def)
void _sx_chain_io_plugin(sx_t s, sx_plugin_t p)
static int _sx_websocket_http_header_value(http_parser *parser, const char *chars, size_t length)
static void _sx_websocket_new(sx_t s, sx_plugin_t p)
unsigned int payload_len_short
static int libwebsock_read_header(libwebsock_frame *frame)
static int _sx_websocket_http_headers_complete(http_parser *parser)
static int _sx_websocket_http_header_field(http_parser *parser, const char *chars, size_t length)
holds the state for a single stream
void sha1_init(sha1_state_t *ctx)
void jqueue_push(jqueue_t q, void *data, int priority)
void xhash_put(xht h, const char *key, void *val)
_sx_websocket_state_t state
char * strunescape(pool_t p, char *buf)
sx_buf_t _sx_buffer_new(const char *data, int len, _sx_notify_t notify, void *notify_arg)
utility: make a new buffer if len>0 but data is NULL, the buffer will contain that many bytes of garb...
int j_strcmp(const char *a, const char *b)
void sha1_finish(sha1_state_t *ctx, unsigned char hashout[20])
const char * spool_print(spool s)
#define SX_WEBSOCKET_WRAPPER
void sx_error(sx_t s, int err, const char *text)
int libwebsock_close_with_reason(sx_t s, _sx_websocket_conn_t sc, unsigned short code, const char *reason)
#define FRAME_CHUNK_LENGTH
unsigned int payload_offset
struct _libwebsock_frame libwebsock_frame
static http_parser_settings settings
int libwebsock_close(sx_t s, _sx_websocket_conn_t sc)
static int _sx_websocket_rio(sx_t s, sx_plugin_t p, sx_buf_t buf)
int sx_websocket_init(sx_env_t env, sx_plugin_t p, va_list args)
args: none
int(* wio)(sx_t s, sx_plugin_t p, sx_buf_t buf)
sx_buf_t libwebsock_fragment_buffer(const char *data, unsigned int len, int flags)
void _sx_buffer_clear(sx_buf_t buf)
utility: clear out a buffer, but don't deallocate it
#define WS_CLOSE_UNEXPECTED_ERROR
void sha1_append(sha1_state_t *ctx, const unsigned char *dataIn, int len)
static int _sx_websocket_wio(sx_t s, sx_plugin_t p, sx_buf_t buf)
int libwebsock_send_fragment(sx_t s, _sx_websocket_conn_t sc, const char *data, unsigned int len, int flags)
static void _sx_websocket_free(sx_t s, sx_plugin_t p)
cleanup
#define stream_err_BAD_FORMAT
void * xhash_get(xht h, const char *key)
static const char websocket_guid[]
this plugin implements WebSocket C2S access RFC 7395 : An Extensible Messaging and Presence Protocol ...
void _sx_buffer_set(sx_buf_t buf, char *newdata, int newlength, char *newheap)
utility: reset a sx_buf_t's contents.
int(* rio)(sx_t s, sx_plugin_t p, sx_buf_t buf)
int j_strlen(const char *a)
void spool_escape(spool s, const char *raw, int len)
struct _sx_websocket_conn_st * _sx_websocket_conn_t
a single conn
spool spool_new(pool_t p)