Esempio n. 1
0
int websocket_parse(Websocket *websocket, void *buffer, int length) {
	switch (websocket->state) {
	case WEBSOCKET_STATE_WAIT_FOR_HANDSHAKE:
	case WEBSOCKET_STATE_FOUND_HANDSHAKE_KEY:
		return websocket_parse_handshake(websocket, buffer, length);

	case WEBSOCKET_STATE_HANDSHAKE_DONE:
		return websocket_parse_header(websocket, buffer, length);

	case WEBSOCKET_STATE_HEADER_DONE:
		return websocket_parse_data(websocket, buffer, length);
	}

	log_error("In invalid WebSocket state (%d)", websocket->state);

	return -1;
}
uint8_t ethernet_websocket_read_data_tcp(const uint8_t socket, uint8_t *buffer, const uint8_t length) {
	uint8_t read_length = 0;
	switch(ethernet_websocket_state[socket]) {
		case WEBSOCKET_STATE_WAIT_FOR_HANDSHAKE: {
			uint8_t data[100];
			uint8_t handshake_length = ethernet_low_level_read_data_tcp(socket, data, 100);
			if(handshake_length != 0) {
				websocket_parse_handshake((char*)data, handshake_length, ethernet_websocket_answer_callback, ethernet_websocket_answer_error, socket);
			}

			return 0;
		}

		case WEBSOCKET_STATE_HANDSHAKE_DONE: {
			// buffer with max possible size of websocket header
			ethernet_websocket_frame[socket].fin = 1;
			ethernet_websocket_to_read[socket] -= ethernet_low_level_read_data_tcp(socket,
			                                                                       ((uint8_t*)&ethernet_websocket_frame[socket]) + (sizeof(WebsocketFrame) - ethernet_websocket_to_read[socket]),
			                                                                       ethernet_websocket_to_read[socket]);

			if(ethernet_websocket_to_read[socket] != 0) {
				return 0;
			}

			ethernet_websocket_state[socket] = WEBSOCKET_STATE_WEBSOCKET_HEADER_DONE;

			if(ethernet_websocket_frame[socket].mask != 1) {
				// mask = 0 from browser is not allowed!
				logethe("Mask=0 not allowed\n\r");
				ethernet_low_level_emergency_disconnect(socket);
				return 0;
			}

			// We currently don't support 16 bit or 64 bit length
			if(ethernet_websocket_frame[socket].payload_length == 126 || ethernet_websocket_frame[socket].payload_length == 127) {
				ethernet_low_level_emergency_disconnect(socket);
				return 0;
			}

			switch(ethernet_websocket_frame[socket].opcode) {
				case WEBSOCKET_OPCODE_CONTINUATION_FRAME:
				case WEBSOCKET_OPCODE_TEXT_FRAME: {
					// Continuation and text frame not allowed
					logethe("Opcode not supported: %d\n\r", ethernet_websocket_frame[socket].opcode);
					ethernet_low_level_emergency_disconnect(socket);
					return 0;
				}

				case WEBSOCKET_OPCODE_BINARY_FRAME: {
					ethernet_websocket_mask_mod[socket] = 0;
					ethernet_websocket_to_read[socket] = ethernet_websocket_frame[socket].payload_length;
					break;
				}

				case WEBSOCKET_OPCODE_CLOSE_FRAME: {
					ethernet_websocket_close_frame(&ethernet_websocket_frame[socket], socket);
					break;
				}

				case WEBSOCKET_OPCODE_PING_FRAME: {
					logethe("Opcode not supported: %d\n\r", ethernet_websocket_frame[socket].opcode);
					ethernet_low_level_emergency_disconnect(socket);
					break;
				}

				case WEBSCOKET_OPCODE_PONG_FRAME: {
					logethe("Opcode not supported: %d\n\r", ethernet_websocket_frame[socket].opcode);
					ethernet_low_level_emergency_disconnect(socket);
					break;
				}
			}

			return 0;
		}

		case WEBSOCKET_STATE_WEBSOCKET_HEADER_DONE: {
			// Websocket header is done, we can just read the data
			read_length = ethernet_low_level_read_data_tcp(socket, buffer, MIN(length, ethernet_websocket_to_read[socket]));

			for(uint8_t i = 0; i < read_length; i++) {
				buffer[i] ^= ethernet_websocket_frame[socket].masking_key[ethernet_websocket_mask_mod[socket]];
				ethernet_websocket_mask_mod[socket]++;
				if(ethernet_websocket_mask_mod[socket] >= WEBSOCKET_MASK_LENGTH) {
					ethernet_websocket_mask_mod[socket] = 0;
				}
			}

			ethernet_websocket_to_read[socket] -= read_length;
			if(ethernet_websocket_to_read[socket] == 0) {
				ethernet_websocket_state[socket] = WEBSOCKET_STATE_HANDSHAKE_DONE;
				ethernet_websocket_to_read[socket] = sizeof(WebsocketFrame);
			}

			break;
		}

		default: {
			logethe("Invalid Ethernet Websocket state: %d\n\r", (int)ethernet_websocket_state);
			break;
		}
	}

	return read_length;
}