Beispiel #1
0
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);
	
}
Beispiel #3
0
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;
}
Beispiel #4
0
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;

	}

}