diff options
author | Sebastien Helleu <flashcode@flashtux.org> | 2013-10-05 16:49:39 +0200 |
---|---|---|
committer | Sebastien Helleu <flashcode@flashtux.org> | 2013-10-05 16:49:39 +0200 |
commit | a6c188ce4fb42a12eef068bdcc8e9f7b270c5da8 (patch) | |
tree | 00ac627f8e5cff98ef6bf4329d53bd08a2c38cad /src/plugins/relay/relay-websocket.c | |
parent | 7bf712d4c921338b5599300170698f92ffe04bf7 (diff) | |
download | weechat-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.c | 82 |
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; } |