Saw a websocket message go across the wire with this.
git-svn-id: https://www.unprompted.com/svn/projects/tildefriends/trunk@4694 ed5197a5-7fde-0310-b194-c3ffbd925b24
This commit is contained in:
		
							
								
								
									
										129
									
								
								src/http.c
									
									
									
									
									
								
							
							
						
						
									
										129
									
								
								src/http.c
									
									
									
									
									
								
							@@ -43,6 +43,7 @@ typedef struct _tf_http_connection_t
 | 
			
		||||
	tf_http_callback_t* callback;
 | 
			
		||||
	void* user_data;
 | 
			
		||||
 | 
			
		||||
	bool is_websocket;
 | 
			
		||||
	void* body;
 | 
			
		||||
	size_t body_length;
 | 
			
		||||
	size_t content_length;
 | 
			
		||||
@@ -170,35 +171,113 @@ static void _http_reset_connection(tf_http_connection_t* connection)
 | 
			
		||||
 | 
			
		||||
static void _http_add_body_bytes(tf_http_connection_t* connection, const void* data, size_t size)
 | 
			
		||||
{
 | 
			
		||||
	size_t fit = tf_min(connection->content_length - connection->body_length, size);
 | 
			
		||||
	if (fit > 0)
 | 
			
		||||
	if (connection->is_websocket)
 | 
			
		||||
	{
 | 
			
		||||
		memcpy((char*)connection->body + connection->body_length, data, fit);
 | 
			
		||||
		connection->body_length += fit;
 | 
			
		||||
	}
 | 
			
		||||
		connection->body = tf_realloc(connection->body, connection->body_length + size);
 | 
			
		||||
		memcpy((char*)connection->body + connection->body_length, data, size);
 | 
			
		||||
		connection->body_length += size;
 | 
			
		||||
 | 
			
		||||
	if (connection->body_length == connection->content_length)
 | 
			
		||||
	{
 | 
			
		||||
		tf_http_request_t* request = tf_malloc(sizeof(tf_http_request_t));
 | 
			
		||||
		*request = (tf_http_request_t)
 | 
			
		||||
		uint8_t* p = connection->body;
 | 
			
		||||
		while (connection->body_length >= 2)
 | 
			
		||||
		{
 | 
			
		||||
			.connection = connection,
 | 
			
		||||
			.phase = k_http_callback_phase_headers_received,
 | 
			
		||||
			.method = connection->method,
 | 
			
		||||
			.path = connection->path,
 | 
			
		||||
			.flags = connection->flags,
 | 
			
		||||
			.query = connection->query,
 | 
			
		||||
			.body = connection->body,
 | 
			
		||||
			.content_length = connection->content_length,
 | 
			
		||||
			.headers = connection->headers,
 | 
			
		||||
			.headers_count = connection->headers_length,
 | 
			
		||||
			.user_data = connection->user_data,
 | 
			
		||||
		};
 | 
			
		||||
			uint8_t bits0 = p[0];
 | 
			
		||||
			uint8_t bits1 = p[1];
 | 
			
		||||
			if ((bits1 & (1 << 7)) == 0)
 | 
			
		||||
			{
 | 
			
		||||
				/* Unmasked message. */
 | 
			
		||||
				_http_connection_destroy(connection);
 | 
			
		||||
				return;
 | 
			
		||||
			}
 | 
			
		||||
			uint8_t opcode = bits0 & 0xf;
 | 
			
		||||
			bool fin = (bits0 & (1 << 7)) != 0;
 | 
			
		||||
			size_t length = bits1 & 0x7f;
 | 
			
		||||
			int mask_start = 2;
 | 
			
		||||
 | 
			
		||||
		tf_http_request_ref(request);
 | 
			
		||||
		connection->callback(request);
 | 
			
		||||
		tf_http_request_release(request);
 | 
			
		||||
		_http_reset_connection(connection);
 | 
			
		||||
			if (length == 126)
 | 
			
		||||
			{
 | 
			
		||||
				length = 0;
 | 
			
		||||
				for (int i = 0; i < 2; i++)
 | 
			
		||||
				{
 | 
			
		||||
					length <<= 8;
 | 
			
		||||
					length |= p[2 + i];
 | 
			
		||||
				}
 | 
			
		||||
				mask_start = 4;
 | 
			
		||||
			}
 | 
			
		||||
			else if (length == 127)
 | 
			
		||||
			{
 | 
			
		||||
				length = 0;
 | 
			
		||||
				for (int i = 0; i < 8; i++)
 | 
			
		||||
				{
 | 
			
		||||
					length <<= 8;
 | 
			
		||||
					length |= p[2 + i];
 | 
			
		||||
				}
 | 
			
		||||
				mask_start = 10;
 | 
			
		||||
			}
 | 
			
		||||
			if (connection->body_length >= length + 2 + 4)
 | 
			
		||||
			{
 | 
			
		||||
				uint32_t mask =
 | 
			
		||||
					p[mask_start + 0] |
 | 
			
		||||
					p[mask_start + 1] << 8 |
 | 
			
		||||
					p[mask_start + 2] << 16 |
 | 
			
		||||
					p[mask_start + 3] << 24;
 | 
			
		||||
				size_t i = 0;
 | 
			
		||||
				for (i = mask_start + 4; i < length; i += 4)
 | 
			
		||||
				{
 | 
			
		||||
					*(uint32_t*)(p + i) ^= mask;
 | 
			
		||||
				}
 | 
			
		||||
				for (; i < length; i++)
 | 
			
		||||
				{
 | 
			
		||||
					p[i] ^= ((mask >> (8 * (i % 4))) & 0xff);
 | 
			
		||||
				}
 | 
			
		||||
				if (fin)
 | 
			
		||||
				{
 | 
			
		||||
					tf_printf("MESSAGE %d [%.*s]\n", opcode, (int)length, p + mask_start + 4);
 | 
			
		||||
				}
 | 
			
		||||
				size_t total_length + mask_Start + 4 + length;
 | 
			
		||||
				memmove(connection->body, (char*)connection->body + total_length, connection->body_length - total_length);
 | 
			
		||||
				connection->body_length -= total_length;
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	else
 | 
			
		||||
	{
 | 
			
		||||
		size_t fit = tf_min(connection->content_length - connection->body_length, size);
 | 
			
		||||
		if (fit > 0)
 | 
			
		||||
		{
 | 
			
		||||
			memcpy((char*)connection->body + connection->body_length, data, fit);
 | 
			
		||||
			connection->body_length += fit;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		if (connection->body_length == connection->content_length)
 | 
			
		||||
		{
 | 
			
		||||
			if (connection->flags & k_tf_http_handler_flag_websocket)
 | 
			
		||||
			{
 | 
			
		||||
				connection->is_websocket = true;
 | 
			
		||||
			}
 | 
			
		||||
			tf_http_request_t* request = tf_malloc(sizeof(tf_http_request_t));
 | 
			
		||||
			*request = (tf_http_request_t)
 | 
			
		||||
			{
 | 
			
		||||
				.connection = connection,
 | 
			
		||||
				.phase = k_http_callback_phase_headers_received,
 | 
			
		||||
				.method = connection->method,
 | 
			
		||||
				.path = connection->path,
 | 
			
		||||
				.flags = connection->flags,
 | 
			
		||||
				.query = connection->query,
 | 
			
		||||
				.body = connection->body,
 | 
			
		||||
				.content_length = connection->content_length,
 | 
			
		||||
				.headers = connection->headers,
 | 
			
		||||
				.headers_count = connection->headers_length,
 | 
			
		||||
				.user_data = connection->user_data,
 | 
			
		||||
			};
 | 
			
		||||
 | 
			
		||||
			tf_http_request_ref(request);
 | 
			
		||||
			connection->callback(request);
 | 
			
		||||
			tf_http_request_release(request);
 | 
			
		||||
			if (!connection->is_websocket)
 | 
			
		||||
			{
 | 
			
		||||
				_http_reset_connection(connection);
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user