static void ws_read_cb(evbev_t * bev, void *arg) { size_t data_len = 0; wshtp_conn_t *conn = (wshtp_conn_t*)arg; evbuf_t *in = bufferevent_get_input(bev); bufferevent_lock(bev); while ( (data_len = evbuffer_get_length(in)) ){ void *data = evbuffer_pullup(in, data_len); ws_frame_t frame; size_t nread = ws_parse_frame(data, data_len, &frame); if (frame.status == STATUS_OK) { if (frame.opcode == OP_TEXT) { conn->data.type = WS_DATA_TEXT; conn->method = WSHTP_ON_MESSAGE; } else if (frame.opcode == OP_BIN) { conn->data.type = WS_DATA_BINARY; conn->method = WSHTP_ON_MESSAGE; } else if (frame.opcode == OP_CLOSE) { conn->method = WSHTP_ON_CLOSE; } if (frame.fin == 0 || frame.opcode == OP_CONT) { if (conn->data.ws_frames == NULL) { conn->data.ws_frames = ws_buffer_new(); } ws_buffer_append_data(conn->data.ws_frames, frame.data, frame.payload_len); } if (conn->method == WSHTP_ON_CLOSE) { evbuffer_drain(in, data_len); } else { evbuffer_drain(in, nread); } if (frame.fin) { if (conn->data.ws_frames) { conn->data.content = ws_buffer_get_data(conn->data.ws_frames, &conn->data.size); ws_buffer_free(conn->data.ws_frames); conn->data.ws_frames = NULL; } else { conn->data.content = frame.data; conn->data.size = frame.payload_len; } bufferevent_unlock(bev); wshtp_hooks_call(conn->server, conn->method, conn); bufferevent_lock(bev); free(conn->data.content); conn->data.content = NULL; conn->data.size = 0; } } else { break; } } // free fragments bufferevent_unlock(bev); }
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; } }