summaryrefslogtreecommitdiff
path: root/src/plugins/relay/relay-websocket.c
diff options
context:
space:
mode:
authorSebastien Helleu <flashcode@flashtux.org>2013-10-05 16:49:39 +0200
committerSebastien Helleu <flashcode@flashtux.org>2013-10-05 16:49:39 +0200
commita6c188ce4fb42a12eef068bdcc8e9f7b270c5da8 (patch)
tree00ac627f8e5cff98ef6bf4329d53bd08a2c38cad /src/plugins/relay/relay-websocket.c
parent7bf712d4c921338b5599300170698f92ffe04bf7 (diff)
downloadweechat-a6c188ce4fb42a12eef068bdcc8e9f7b270c5da8.zip
relay: fix decoding of websocket frames when there are multiple frames in a single message received (only the first one was decoded)
Diffstat (limited to 'src/plugins/relay/relay-websocket.c')
-rw-r--r--src/plugins/relay/relay-websocket.c82
1 files changed, 42 insertions, 40 deletions
diff --git a/src/plugins/relay/relay-websocket.c b/src/plugins/relay/relay-websocket.c
index 44b74445f..5ef44e2fa 100644
--- a/src/plugins/relay/relay-websocket.c
+++ b/src/plugins/relay/relay-websocket.c
@@ -262,60 +262,62 @@ 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 (length < 1 + length_frame_size + 4 + length_frame)
- return 0;
+ 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 + i]);
- }
- index += 4;
+ /* 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[i] = (int)((unsigned char)buffer[index + i]) ^ masks[i % 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;
}
- decoded[length_frame] = '\0';
-
- *decoded_length = length_frame;
return 1;
}