relay: fix decoding of websocket frames when there are multiple frames in a single message received (only the first one was decoded)

This commit is contained in:
Sebastien Helleu 2013-10-05 16:49:39 +02:00
parent 7bf712d4c9
commit a6c188ce4f
2 changed files with 48 additions and 44 deletions

View File

@ -1,7 +1,7 @@
WeeChat ChangeLog
=================
Sébastien Helleu <flashcode@flashtux.org>
v0.4.2-rc2, 2013-09-30
v0.4.2-rc2, 2013-10-05
This document lists all changes for each version.
@ -119,6 +119,8 @@ Version 0.4.2 (under dev!)
buffer per nick
* logger: add option "flush" for command /logger
* lua: fix interpreter used in API functions (bug #39470)
* relay: fix decoding of websocket frames when there are multiple frames in a
single message received (only the first one was decoded)
* relay: add command "ping" in weechat protocol (task #12689)
* relay: fix binding to an IP address (bug #39119)
* rmodifier: add option "missing" for command /rmodifier

View File

@ -262,61 +262,63 @@ relay_websocket_send_http (struct t_relay_client *client,
int
relay_websocket_decode_frame (const unsigned char *buffer,
unsigned long long length,
unsigned long long buffer_length,
unsigned char *decoded,
unsigned long long *decoded_length)
{
unsigned long long i, index, length_frame_size, length_frame;
unsigned long long i, index_buffer, length_frame_size, length_frame;
*decoded_length = 0;
index_buffer = 0;
if (length < 2)
return 0;
/*
* check if frame is masked: client MUST send a masked frame; if frame is
* not masked, we MUST reject it and close the connection (see RFC 6455)
*/
if (!(buffer[1] & 128))
return 0;
/* decode frame */
index = 2;
length_frame_size = 1;
length_frame = buffer[1] & 127;
if ((length_frame == 126) || (length_frame == 127))
/* loop to decode all frames in message */
while (index_buffer + 2 <= buffer_length)
{
length_frame_size = (length_frame == 126) ? 2 : 8;
if (length < 1 + length_frame_size)
/*
* check if frame is masked: client MUST send a masked frame; if frame is
* not masked, we MUST reject it and close the connection (see RFC 6455)
*/
if (!(buffer[index_buffer + 1] & 128))
return 0;
length_frame = 0;
for (i = 0; i < length_frame_size; i++)
/* decode frame */
length_frame_size = 1;
length_frame = buffer[index_buffer + 1] & 127;
index_buffer += 2;
if ((length_frame == 126) || (length_frame == 127))
{
length_frame += (unsigned long long)buffer[index + i] << ((length_frame_size - i - 1) * 8);
length_frame_size = (length_frame == 126) ? 2 : 8;
if (buffer_length < 1 + length_frame_size)
return 0;
length_frame = 0;
for (i = 0; i < length_frame_size; i++)
{
length_frame += (unsigned long long)buffer[index_buffer + i] << ((length_frame_size - i - 1) * 8);
}
index_buffer += length_frame_size;
}
index += length_frame_size;
if (buffer_length < 1 + length_frame_size + 4 + length_frame)
return 0;
/* read masks (4 bytes) */
int masks[4];
for (i = 0; i < 4; i++)
{
masks[i] = (int)((unsigned char)buffer[index_buffer + i]);
}
index_buffer += 4;
/* decode data using masks */
for (i = 0; i < length_frame; i++)
{
decoded[*decoded_length + i] = (int)((unsigned char)buffer[index_buffer + i]) ^ masks[i % 4];
}
decoded[*decoded_length + length_frame] = '\0';
*decoded_length += length_frame;
index_buffer += length_frame;
}
if (length < 1 + length_frame_size + 4 + length_frame)
return 0;
/* read masks (4 bytes) */
int masks[4];
for (i = 0; i < 4; i++)
{
masks[i] = (int)((unsigned char)buffer[index + i]);
}
index += 4;
/* decode data using masks */
for (i = 0; i < length_frame; i++)
{
decoded[i] = (int)((unsigned char)buffer[index + i]) ^ masks[i % 4];
}
decoded[length_frame] = '\0';
*decoded_length = length_frame;
return 1;
}