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:
parent
606e82d718
commit
adf8c14536
129
src/http.c
129
src/http.c
@ -43,6 +43,7 @@ typedef struct _tf_http_connection_t
|
|||||||
tf_http_callback_t* callback;
|
tf_http_callback_t* callback;
|
||||||
void* user_data;
|
void* user_data;
|
||||||
|
|
||||||
|
bool is_websocket;
|
||||||
void* body;
|
void* body;
|
||||||
size_t body_length;
|
size_t body_length;
|
||||||
size_t content_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)
|
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 (connection->is_websocket)
|
||||||
if (fit > 0)
|
|
||||||
{
|
{
|
||||||
memcpy((char*)connection->body + connection->body_length, data, fit);
|
connection->body = tf_realloc(connection->body, connection->body_length + size);
|
||||||
connection->body_length += fit;
|
memcpy((char*)connection->body + connection->body_length, data, size);
|
||||||
}
|
connection->body_length += size;
|
||||||
|
|
||||||
if (connection->body_length == connection->content_length)
|
uint8_t* p = connection->body;
|
||||||
{
|
while (connection->body_length >= 2)
|
||||||
tf_http_request_t* request = tf_malloc(sizeof(tf_http_request_t));
|
|
||||||
*request = (tf_http_request_t)
|
|
||||||
{
|
{
|
||||||
.connection = connection,
|
uint8_t bits0 = p[0];
|
||||||
.phase = k_http_callback_phase_headers_received,
|
uint8_t bits1 = p[1];
|
||||||
.method = connection->method,
|
if ((bits1 & (1 << 7)) == 0)
|
||||||
.path = connection->path,
|
{
|
||||||
.flags = connection->flags,
|
/* Unmasked message. */
|
||||||
.query = connection->query,
|
_http_connection_destroy(connection);
|
||||||
.body = connection->body,
|
return;
|
||||||
.content_length = connection->content_length,
|
}
|
||||||
.headers = connection->headers,
|
uint8_t opcode = bits0 & 0xf;
|
||||||
.headers_count = connection->headers_length,
|
bool fin = (bits0 & (1 << 7)) != 0;
|
||||||
.user_data = connection->user_data,
|
size_t length = bits1 & 0x7f;
|
||||||
};
|
int mask_start = 2;
|
||||||
|
|
||||||
tf_http_request_ref(request);
|
if (length == 126)
|
||||||
connection->callback(request);
|
{
|
||||||
tf_http_request_release(request);
|
length = 0;
|
||||||
_http_reset_connection(connection);
|
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);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user