void event_handler(switch_event_t *event) { char *json; wsh_t *wsh = (TSession *)event->bind_user_data; switch_event_serialize_json(event, &json); ws_write_frame(wsh, WSOC_TEXT, json, strlen(json)); free(json); }
void ICACHE_FLASH_ATTR http_ws_push_bin(http_connection *c,char *msg,size_t msgLen){ ws_frame frame; ws_output_frame(&frame,WS_BINARY,msg,msgLen); ws_write_frame(&frame,ws_output_write_function,c); http_transmit(c); }
ssize_t ws_send_buf(wsh_t *wsh, ws_opcode_t oc) { ssize_t r = 0; if (!wsh->wdatalen) { return -1; } r = ws_write_frame(wsh, oc, wsh->wbuffer, wsh->wdatalen); wsh->wdatalen = 0; return r; }
ssize_t ws_read_frame(wsh_t *wsh, ws_opcode_t *oc, uint8_t **data) { ssize_t need = 2; char *maskp; int ll = 0; int frag = 0; again: need = 2; maskp = NULL; *data = NULL; ll = establish_logical_layer(wsh); if (ll < 0) { return ll; } if (wsh->down) { return -1; } if (!wsh->handshake) { return ws_close(wsh, WS_PROTO_ERR); } if ((wsh->datalen = ws_raw_read(wsh, wsh->buffer, 9, wsh->block)) < 0) { if (wsh->datalen == -2) { return -2; } return ws_close(wsh, WS_PROTO_ERR); } if (wsh->datalen < need) { if ((wsh->datalen += ws_raw_read(wsh, wsh->buffer + wsh->datalen, 9 - wsh->datalen, WS_BLOCK)) < need) { /* too small - protocol err */ return ws_close(wsh, WS_PROTO_ERR); } } *oc = *wsh->buffer & 0xf; switch(*oc) { case WSOC_CLOSE: { wsh->plen = wsh->buffer[1] & 0x7f; *data = (uint8_t *) &wsh->buffer[2]; return ws_close(wsh, 1000); } break; case WSOC_CONTINUATION: case WSOC_TEXT: case WSOC_BINARY: case WSOC_PING: case WSOC_PONG: { int fin = (wsh->buffer[0] >> 7) & 1; int mask = (wsh->buffer[1] >> 7) & 1; if (fin) { if (*oc == WSOC_CONTINUATION) { frag = 1; } else { frag = 0; } } if (mask) { need += 4; if (need > wsh->datalen) { /* too small - protocol err */ *oc = WSOC_CLOSE; return ws_close(wsh, WS_PROTO_ERR); } } wsh->plen = wsh->buffer[1] & 0x7f; wsh->payload = &wsh->buffer[2]; if (wsh->plen == 127) { uint64_t *u64; need += 8; if (need > wsh->datalen) { /* too small - protocol err */ *oc = WSOC_CLOSE; return ws_close(wsh, WS_PROTO_ERR); } u64 = (uint64_t *) wsh->payload; wsh->payload += 8; wsh->plen = ntohl((u_long)*u64); } else if (wsh->plen == 126) { uint16_t *u16; need += 2; if (need > wsh->datalen) { /* too small - protocol err */ *oc = WSOC_CLOSE; return ws_close(wsh, WS_PROTO_ERR); } u16 = (uint16_t *) wsh->payload; wsh->payload += 2; wsh->plen = ntohs(*u16); } if (mask) { maskp = (char *)wsh->payload; wsh->payload += 4; } need = (wsh->plen - (wsh->datalen - need)); if (need < 0) { /* invalid read - protocol err .. */ *oc = WSOC_CLOSE; return ws_close(wsh, WS_PROTO_ERR); } if ((need + wsh->datalen) > (ssize_t)wsh->buflen) { /* too big - Ain't nobody got time fo' dat */ *oc = WSOC_CLOSE; return ws_close(wsh, WS_DATA_TOO_BIG); } wsh->rplen = wsh->plen - need; while(need) { ssize_t r = ws_raw_read(wsh, wsh->payload + wsh->rplen, need, WS_BLOCK); if (r < 1) { /* invalid read - protocol err .. */ *oc = WSOC_CLOSE; return ws_close(wsh, WS_PROTO_ERR); } wsh->datalen += r; wsh->rplen += r; need -= r; } if (mask && maskp) { ssize_t i; for (i = 0; i < wsh->datalen; i++) { wsh->payload[i] ^= maskp[i % 4]; } } if (*oc == WSOC_PING) { ws_write_frame(wsh, WSOC_PONG, wsh->payload, wsh->rplen); goto again; } if (frag) { goto again; } *(wsh->payload+wsh->rplen) = '\0'; *data = (uint8_t *)wsh->payload; //printf("READ[%ld][%d]-----------------------------:\n[%s]\n-------------------------------\n", wsh->rplen, *oc, (char *)*data); return wsh->rplen; } break; default: { /* invalid op code - protocol err .. */ *oc = WSOC_CLOSE; return ws_close(wsh, WS_PROTO_ERR); } break; } }
static int ICACHE_FLASH_ATTR http_ws_cgi_execute(http_connection * c){ NODE_DBG("http_ws_cgi_execute c =%p",c); if(!c->handshake_ok) { int r = http_ws_handle_connect(c); if(r==HTTP_WS_CGI_DONE) c->cgi.done=1; //mark for destruction http_transmit(c); } else{ if(c->body.data==NULL){ if(c->state==HTTPD_STATE_WS_DATA_SENT){ if(data_sent_callback!=NULL) data_sent_callback(c); } } else if(c->state==HTTPD_STATE_WS_DATA){ NODE_DBG("websocket frame size %d",c->body.len); ws_frame frame; ws_parse_frame(&frame,c->body.data,c->body.len); switch(frame.TYPE){ case WS_INVALID: NODE_DBG("\treceived invalid frame"); break; case WS_PING: //send ping ws_output_frame(&frame,WS_PING,"PING",strlen("PING")); ws_write_frame(&frame,ws_output_write_function,c); http_transmit(c); case WS_CLOSE: //send close back ws_output_frame(&frame,WS_PING,"\0\0",2); ws_write_frame(&frame,ws_output_write_function,c); http_transmit(c); //mark as done c->cgi.done=1; break; case WS_TEXT: case WS_BINARY: http_ws_handle_message(c,&frame); break; case WS_CONTINUATION: break; // TODO: Implement continuation logic } } else if(c->state == HTTPD_STATE_WS_CLIENT_DISCONNECT){ if(client_disconnected_callback!=NULL) client_disconnected_callback(c); } return 1; } }