158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)// Copyright 2013 The Chromium Authors. All rights reserved. 25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be 35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file. 45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/websockets/websocket_frame_parser.h" 65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <algorithm> 85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <vector> 95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/basictypes.h" 115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/memory/scoped_vector.h" 125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/port.h" 135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/base/io_buffer.h" 145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/websockets/websocket_frame.h" 155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "testing/gtest/include/gtest/gtest.h" 165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace net { 185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace { 205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const char kHello[] = "Hello, world!"; 225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const uint64 kHelloLength = arraysize(kHello) - 1; 235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const char kHelloFrame[] = "\x81\x0DHello, world!"; 245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const uint64 kHelloFrameLength = arraysize(kHelloFrame) - 1; 255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const char kMaskedHelloFrame[] = 265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "\x81\x8D\xDE\xAD\xBE\xEF" 275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "\x96\xC8\xD2\x83\xB1\x81\x9E\x98\xB1\xDF\xD2\x8B\xFF"; 285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const uint64 kMaskedHelloFrameLength = arraysize(kMaskedHelloFrame) - 1; 295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)struct FrameHeaderTestCase { 315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const char* frame_header; 325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) size_t frame_header_length; 335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) uint64 frame_length; 345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) WebSocketError error_code; 355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}; 365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const FrameHeaderTestCase kFrameHeaderTests[] = { 38b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) { "\x81\x00", 2, GG_UINT64_C(0), kWebSocketNormalClosure }, 39b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) { "\x81\x7D", 2, GG_UINT64_C(125), kWebSocketNormalClosure }, 40b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) { "\x81\x7E\x00\x7E", 4, GG_UINT64_C(126), kWebSocketNormalClosure }, 41b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) { "\x81\x7E\xFF\xFF", 4, GG_UINT64_C(0xFFFF), kWebSocketNormalClosure }, 425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) { "\x81\x7F\x00\x00\x00\x00\x00\x01\x00\x00", 10, GG_UINT64_C(0x10000), 43b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) kWebSocketNormalClosure }, 445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) { "\x81\x7F\x00\x00\x00\x00\x7F\xFF\xFF\xFF", 10, GG_UINT64_C(0x7FFFFFFF), 45b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) kWebSocketNormalClosure }, 465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) { "\x81\x7F\x00\x00\x00\x00\x80\x00\x00\x00", 10, GG_UINT64_C(0x80000000), 47b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) kWebSocketErrorMessageTooBig }, 485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) { "\x81\x7F\x7F\xFF\xFF\xFF\xFF\xFF\xFF\xFF", 10, 49b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) GG_UINT64_C(0x7FFFFFFFFFFFFFFF), kWebSocketErrorMessageTooBig } 505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}; 515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const int kNumFrameHeaderTests = arraysize(kFrameHeaderTests); 525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST(WebSocketFrameParserTest, DecodeNormalFrame) { 545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) WebSocketFrameParser parser; 555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ScopedVector<WebSocketFrameChunk> frames; 575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_TRUE(parser.Decode(kHelloFrame, kHelloFrameLength, &frames)); 58b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) EXPECT_EQ(kWebSocketNormalClosure, parser.websocket_error()); 595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ASSERT_EQ(1u, frames.size()); 605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) WebSocketFrameChunk* frame = frames[0]; 615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ASSERT_TRUE(frame != NULL); 625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const WebSocketFrameHeader* header = frame->header.get(); 635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_TRUE(header != NULL); 645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (header) { 655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_TRUE(header->final); 665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_FALSE(header->reserved1); 675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_FALSE(header->reserved2); 685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_FALSE(header->reserved3); 695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_EQ(WebSocketFrameHeader::kOpCodeText, header->opcode); 705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_FALSE(header->masked); 715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_EQ(kHelloLength, header->payload_length); 725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_TRUE(frame->final_chunk); 745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ASSERT_EQ(static_cast<int>(kHelloLength), frame->data->size()); 765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_TRUE(std::equal(kHello, kHello + kHelloLength, frame->data->data())); 775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST(WebSocketFrameParserTest, DecodeMaskedFrame) { 805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) WebSocketFrameParser parser; 815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ScopedVector<WebSocketFrameChunk> frames; 8390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) EXPECT_TRUE( 8490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) parser.Decode(kMaskedHelloFrame, kMaskedHelloFrameLength, &frames)); 85b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) EXPECT_EQ(kWebSocketNormalClosure, parser.websocket_error()); 865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ASSERT_EQ(1u, frames.size()); 875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) WebSocketFrameChunk* frame = frames[0]; 885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ASSERT_TRUE(frame != NULL); 895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const WebSocketFrameHeader* header = frame->header.get(); 905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_TRUE(header != NULL); 915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (header) { 925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_TRUE(header->final); 935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_FALSE(header->reserved1); 945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_FALSE(header->reserved2); 955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_FALSE(header->reserved3); 965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_EQ(WebSocketFrameHeader::kOpCodeText, header->opcode); 975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_TRUE(header->masked); 985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_EQ(kHelloLength, header->payload_length); 995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_TRUE(frame->final_chunk); 1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ASSERT_EQ(static_cast<int>(kHelloLength), frame->data->size()); 1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_TRUE(std::equal(kHello, kHello + kHelloLength, frame->data->data())); 1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST(WebSocketFrameParserTest, DecodeManyFrames) { 1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) struct Input { 1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const char* frame; 1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) size_t frame_length; 1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const char* expected_payload; 1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) size_t expected_payload_length; 1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) }; 1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) static const Input kInputs[] = { 1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Each |frame| data is split into two string literals because C++ lexers 1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // consume unlimited number of hex characters in a hex character escape 1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // (e.g. "\x05F" is not treated as { '\x5', 'F', '\0' } but as 1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // { '\x5F', '\0' }). 1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) { "\x81\x05" "First", 7, "First", 5 }, 1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) { "\x81\x06" "Second", 8, "Second", 6 }, 1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) { "\x81\x05" "Third", 7, "Third", 5 }, 1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) { "\x81\x06" "Fourth", 8, "Fourth", 6 }, 1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) { "\x81\x05" "Fifth", 7, "Fifth", 5 }, 1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) { "\x81\x05" "Sixth", 7, "Sixth", 5 }, 1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) { "\x81\x07" "Seventh", 9, "Seventh", 7 }, 1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) { "\x81\x06" "Eighth", 8, "Eighth", 6 }, 1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) { "\x81\x05" "Ninth", 7, "Ninth", 5 }, 1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) { "\x81\x05" "Tenth", 7, "Tenth", 5 } 1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) }; 1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) static const int kNumInputs = ARRAYSIZE_UNSAFE(kInputs); 1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::vector<char> input; 1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Concatenate all frames. 1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (int i = 0; i < kNumInputs; ++i) { 1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) input.insert(input.end(), 1355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) kInputs[i].frame, 1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) kInputs[i].frame + kInputs[i].frame_length); 1375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) WebSocketFrameParser parser; 1405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ScopedVector<WebSocketFrameChunk> frames; 1425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_TRUE(parser.Decode(&input.front(), input.size(), &frames)); 143b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) EXPECT_EQ(kWebSocketNormalClosure, parser.websocket_error()); 1445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ASSERT_EQ(static_cast<size_t>(kNumInputs), frames.size()); 1455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (int i = 0; i < kNumInputs; ++i) { 1475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) WebSocketFrameChunk* frame = frames[i]; 1485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_TRUE(frame != NULL); 1495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!frame) 1505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) continue; 1515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_TRUE(frame->final_chunk); 1525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ASSERT_EQ(kInputs[i].expected_payload_length, 1535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) static_cast<uint64>(frame->data->size())); 1545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_TRUE(std::equal( 1555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) kInputs[i].expected_payload, 1565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) kInputs[i].expected_payload + kInputs[i].expected_payload_length, 1575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) frame->data->data())); 1585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const WebSocketFrameHeader* header = frame->header.get(); 1605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_TRUE(header != NULL); 1615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!header) 1625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) continue; 1635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_TRUE(header->final); 1645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_FALSE(header->reserved1); 1655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_FALSE(header->reserved2); 1665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_FALSE(header->reserved3); 1675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_EQ(WebSocketFrameHeader::kOpCodeText, header->opcode); 1685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_FALSE(header->masked); 1695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_EQ(kInputs[i].expected_payload_length, header->payload_length); 1705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST(WebSocketFrameParserTest, DecodePartialFrame) { 1745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) static const size_t kFrameHeaderSize = 2; 1755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (size_t cutting_pos = 0; cutting_pos < kHelloLength; ++cutting_pos) { 1775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::vector<char> input1(kHelloFrame, 1785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) kHelloFrame + kFrameHeaderSize + cutting_pos); 1795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::vector<char> input2(kHelloFrame + input1.size(), 1805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) kHelloFrame + kHelloFrameLength); 1815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::vector<char> expected1(kHello, kHello + cutting_pos); 1835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::vector<char> expected2(kHello + cutting_pos, kHello + kHelloLength); 1845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) WebSocketFrameParser parser; 1865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ScopedVector<WebSocketFrameChunk> frames1; 1885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_TRUE(parser.Decode(&input1.front(), input1.size(), &frames1)); 189b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) EXPECT_EQ(kWebSocketNormalClosure, parser.websocket_error()); 1905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_EQ(1u, frames1.size()); 1915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (frames1.size() != 1u) 1925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) continue; 1935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) WebSocketFrameChunk* frame1 = frames1[0]; 1945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_TRUE(frame1 != NULL); 1955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!frame1) 1965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) continue; 1975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_FALSE(frame1->final_chunk); 1985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (expected1.size() == 0) { 1995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_EQ(NULL, frame1->data.get()); 2005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 2015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ASSERT_EQ(cutting_pos, static_cast<size_t>(frame1->data->size())); 20290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) EXPECT_TRUE( 20390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) std::equal(expected1.begin(), expected1.end(), frame1->data->data())); 2045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const WebSocketFrameHeader* header1 = frame1->header.get(); 2065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_TRUE(header1 != NULL); 2075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!header1) 2085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) continue; 2095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_TRUE(header1->final); 2105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_FALSE(header1->reserved1); 2115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_FALSE(header1->reserved2); 2125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_FALSE(header1->reserved3); 2135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_EQ(WebSocketFrameHeader::kOpCodeText, header1->opcode); 2145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_FALSE(header1->masked); 2155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_EQ(kHelloLength, header1->payload_length); 2165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ScopedVector<WebSocketFrameChunk> frames2; 2185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_TRUE(parser.Decode(&input2.front(), input2.size(), &frames2)); 219b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) EXPECT_EQ(kWebSocketNormalClosure, parser.websocket_error()); 2205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_EQ(1u, frames2.size()); 2215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (frames2.size() != 1u) 2225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) continue; 2235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) WebSocketFrameChunk* frame2 = frames2[0]; 2245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_TRUE(frame2 != NULL); 2255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!frame2) 2265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) continue; 2275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_TRUE(frame2->final_chunk); 2285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (expected2.size() == 0) { 2295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_EQ(NULL, frame2->data.get()); 2305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 2315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ASSERT_EQ(expected2.size(), static_cast<uint64>(frame2->data->size())); 23290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) EXPECT_TRUE( 23390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) std::equal(expected2.begin(), expected2.end(), frame2->data->data())); 2345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const WebSocketFrameHeader* header2 = frame2->header.get(); 2365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_TRUE(header2 == NULL); 2375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST(WebSocketFrameParserTest, DecodePartialMaskedFrame) { 2415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) static const size_t kFrameHeaderSize = 6; 2425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (size_t cutting_pos = 0; cutting_pos < kHelloLength; ++cutting_pos) { 2445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::vector<char> input1( 24590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) kMaskedHelloFrame, kMaskedHelloFrame + kFrameHeaderSize + cutting_pos); 2465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::vector<char> input2(kMaskedHelloFrame + input1.size(), 2475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) kMaskedHelloFrame + kMaskedHelloFrameLength); 2485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::vector<char> expected1(kHello, kHello + cutting_pos); 2505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::vector<char> expected2(kHello + cutting_pos, kHello + kHelloLength); 2515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) WebSocketFrameParser parser; 2535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ScopedVector<WebSocketFrameChunk> frames1; 2555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_TRUE(parser.Decode(&input1.front(), input1.size(), &frames1)); 256b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) EXPECT_EQ(kWebSocketNormalClosure, parser.websocket_error()); 2575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_EQ(1u, frames1.size()); 2585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (frames1.size() != 1u) 2595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) continue; 2605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) WebSocketFrameChunk* frame1 = frames1[0]; 2615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_TRUE(frame1 != NULL); 2625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!frame1) 2635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) continue; 2645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_FALSE(frame1->final_chunk); 2655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (expected1.size() == 0) { 2665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_EQ(NULL, frame1->data.get()); 2675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 2685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ASSERT_EQ(expected1.size(), static_cast<uint64>(frame1->data->size())); 26990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) EXPECT_TRUE( 27090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) std::equal(expected1.begin(), expected1.end(), frame1->data->data())); 2715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const WebSocketFrameHeader* header1 = frame1->header.get(); 2735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_TRUE(header1 != NULL); 2745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!header1) 2755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) continue; 2765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_TRUE(header1->final); 2775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_FALSE(header1->reserved1); 2785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_FALSE(header1->reserved2); 2795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_FALSE(header1->reserved3); 2805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_EQ(WebSocketFrameHeader::kOpCodeText, header1->opcode); 2815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_TRUE(header1->masked); 2825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_EQ(kHelloLength, header1->payload_length); 2835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ScopedVector<WebSocketFrameChunk> frames2; 2855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_TRUE(parser.Decode(&input2.front(), input2.size(), &frames2)); 286b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) EXPECT_EQ(kWebSocketNormalClosure, parser.websocket_error()); 2875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_EQ(1u, frames2.size()); 2885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (frames2.size() != 1u) 2895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) continue; 2905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) WebSocketFrameChunk* frame2 = frames2[0]; 2915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_TRUE(frame2 != NULL); 2925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!frame2) 2935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) continue; 2945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_TRUE(frame2->final_chunk); 2955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (expected2.size() == 0) { 2965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_EQ(NULL, frame2->data.get()); 2975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 2985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ASSERT_EQ(expected2.size(), static_cast<uint64>(frame2->data->size())); 29990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) EXPECT_TRUE( 30090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) std::equal(expected2.begin(), expected2.end(), frame2->data->data())); 3015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const WebSocketFrameHeader* header2 = frame2->header.get(); 3035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_TRUE(header2 == NULL); 3045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST(WebSocketFrameParserTest, DecodeFramesOfVariousLengths) { 3085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (int i = 0; i < kNumFrameHeaderTests; ++i) { 3095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const char* frame_header = kFrameHeaderTests[i].frame_header; 3105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) size_t frame_header_length = kFrameHeaderTests[i].frame_header_length; 3115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) uint64 frame_length = kFrameHeaderTests[i].frame_length; 3125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::vector<char> input(frame_header, frame_header + frame_header_length); 3145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Limit the payload size not to flood the console on failure. 3155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) static const uint64 kMaxPayloadSize = 200; 3165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) uint64 input_payload_size = std::min(frame_length, kMaxPayloadSize); 3175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) input.insert(input.end(), input_payload_size, 'a'); 3185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) WebSocketFrameParser parser; 3205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ScopedVector<WebSocketFrameChunk> frames; 322b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) EXPECT_EQ(kFrameHeaderTests[i].error_code == kWebSocketNormalClosure, 32390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) parser.Decode(&input.front(), input.size(), &frames)); 3245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_EQ(kFrameHeaderTests[i].error_code, parser.websocket_error()); 325b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) if (kFrameHeaderTests[i].error_code != kWebSocketNormalClosure) { 3265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_EQ(0u, frames.size()); 3275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 3285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_EQ(1u, frames.size()); 3295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (frames.size() != 1u) 3315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) continue; 3325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) WebSocketFrameChunk* frame = frames[0]; 3335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_TRUE(frame != NULL); 3345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!frame) 3355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) continue; 3365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (frame_length == input_payload_size) { 3375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_TRUE(frame->final_chunk); 3385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 3395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_FALSE(frame->final_chunk); 3405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::vector<char> expected_payload(input_payload_size, 'a'); 3425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (expected_payload.size() == 0) { 3435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_EQ(NULL, frame->data.get()); 3445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 3455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ASSERT_EQ(expected_payload.size(), 3465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) static_cast<uint64>(frame->data->size())); 34790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) EXPECT_TRUE(std::equal(expected_payload.begin(), 34890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) expected_payload.end(), 34990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) frame->data->data())); 3505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const WebSocketFrameHeader* header = frame->header.get(); 3525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_TRUE(header != NULL); 3535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!header) 3545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) continue; 3555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_TRUE(header->final); 3565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_FALSE(header->reserved1); 3575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_FALSE(header->reserved2); 3585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_FALSE(header->reserved3); 3595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_EQ(WebSocketFrameHeader::kOpCodeText, header->opcode); 3605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_FALSE(header->masked); 3615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_EQ(frame_length, header->payload_length); 3625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST(WebSocketFrameParserTest, DecodePartialHeader) { 3665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (int i = 0; i < kNumFrameHeaderTests; ++i) { 3675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const char* frame_header = kFrameHeaderTests[i].frame_header; 3685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) size_t frame_header_length = kFrameHeaderTests[i].frame_header_length; 3695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) uint64 frame_length = kFrameHeaderTests[i].frame_length; 3705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) WebSocketFrameParser parser; 3725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ScopedVector<WebSocketFrameChunk> frames; 3745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Feed each byte to the parser to see if the parser behaves correctly 3755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // when it receives partial frame header. 3765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) size_t last_byte_offset = frame_header_length - 1; 3775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (size_t j = 0; j < frame_header_length; ++j) { 378b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) bool failed = 379b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) kFrameHeaderTests[i].error_code != kWebSocketNormalClosure && 3805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) j == last_byte_offset; 3815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_EQ(!failed, parser.Decode(frame_header + j, 1, &frames)); 3825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (failed) { 3835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_EQ(kFrameHeaderTests[i].error_code, parser.websocket_error()); 3845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 385b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) EXPECT_EQ(kWebSocketNormalClosure, parser.websocket_error()); 3865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 387b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) if (kFrameHeaderTests[i].error_code == kWebSocketNormalClosure && 3885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) j == last_byte_offset) { 3895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_EQ(1u, frames.size()); 3905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 3915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_EQ(0u, frames.size()); 3925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (frames.size() != 1u) 3955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) continue; 3965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) WebSocketFrameChunk* frame = frames[0]; 3975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_TRUE(frame != NULL); 3985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!frame) 3995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) continue; 4005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (frame_length == 0u) { 4015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_TRUE(frame->final_chunk); 4025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 4035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_FALSE(frame->final_chunk); 4045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 4055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_EQ(NULL, frame->data.get()); 4065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const WebSocketFrameHeader* header = frame->header.get(); 4075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_TRUE(header != NULL); 4085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!header) 4095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) continue; 4105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_TRUE(header->final); 4115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_FALSE(header->reserved1); 4125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_FALSE(header->reserved2); 4135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_FALSE(header->reserved3); 4145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_EQ(WebSocketFrameHeader::kOpCodeText, header->opcode); 4155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_FALSE(header->masked); 4165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_EQ(frame_length, header->payload_length); 4175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 4185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 4195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST(WebSocketFrameParserTest, InvalidLengthEncoding) { 4215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) struct TestCase { 4225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const char* frame_header; 4235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) size_t frame_header_length; 4245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) }; 4255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) static const TestCase kTests[] = { 4265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // For frames with two-byte extended length field, the payload length 4275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // should be 126 (0x7E) bytes or more. 4285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) { "\x81\x7E\x00\x00", 4 }, 4295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) { "\x81\x7E\x00\x7D", 4 }, 4305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // For frames with eight-byte extended length field, the payload length 4315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // should be 0x10000 bytes or more. 4325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) { "\x81\x7F\x00\x00\x00\x00\x00\x00\x00\x00", 10 }, 4335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) { "\x81\x7E\x00\x00\x00\x00\x00\x00\xFF\xFF", 10 }, 4345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) }; 4355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) static const int kNumTests = ARRAYSIZE_UNSAFE(kTests); 4365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (int i = 0; i < kNumTests; ++i) { 4385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const char* frame_header = kTests[i].frame_header; 4395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) size_t frame_header_length = kTests[i].frame_header_length; 4405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) WebSocketFrameParser parser; 4425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ScopedVector<WebSocketFrameChunk> frames; 444b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) EXPECT_EQ(kWebSocketNormalClosure, parser.websocket_error()); 4455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_FALSE(parser.Decode(frame_header, frame_header_length, &frames)); 446b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) EXPECT_EQ(kWebSocketErrorProtocolError, parser.websocket_error()); 4475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_EQ(0u, frames.size()); 4485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Once the parser has failed, it no longer accepts any input (even if 4505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // the input is empty). 4515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_FALSE(parser.Decode("", 0, &frames)); 452b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) EXPECT_EQ(kWebSocketErrorProtocolError, parser.websocket_error()); 4535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_EQ(0u, frames.size()); 4545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 4555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 4565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST(WebSocketFrameParserTest, FrameTypes) { 4585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) struct TestCase { 4595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const char* frame_header; 4605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) size_t frame_header_length; 4615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) WebSocketFrameHeader::OpCode opcode; 4625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) }; 4635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) static const TestCase kTests[] = { 4645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) { "\x80\x00", 2, WebSocketFrameHeader::kOpCodeContinuation }, 4655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) { "\x81\x00", 2, WebSocketFrameHeader::kOpCodeText }, 4665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) { "\x82\x00", 2, WebSocketFrameHeader::kOpCodeBinary }, 4675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) { "\x88\x00", 2, WebSocketFrameHeader::kOpCodeClose }, 4685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) { "\x89\x00", 2, WebSocketFrameHeader::kOpCodePing }, 4695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) { "\x8A\x00", 2, WebSocketFrameHeader::kOpCodePong }, 4705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // These are undefined opcodes, but the parser needs to be able to parse 4715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // them anyway. 4725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) { "\x83\x00", 2, 0x3 }, 4735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) { "\x84\x00", 2, 0x4 }, 4745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) { "\x85\x00", 2, 0x5 }, 4755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) { "\x86\x00", 2, 0x6 }, 4765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) { "\x87\x00", 2, 0x7 }, 4775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) { "\x8B\x00", 2, 0xB }, 4785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) { "\x8C\x00", 2, 0xC }, 4795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) { "\x8D\x00", 2, 0xD }, 4805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) { "\x8E\x00", 2, 0xE }, 4815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) { "\x8F\x00", 2, 0xF } 4825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) }; 4835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) static const int kNumTests = ARRAYSIZE_UNSAFE(kTests); 4845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (int i = 0; i < kNumTests; ++i) { 4865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const char* frame_header = kTests[i].frame_header; 4875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) size_t frame_header_length = kTests[i].frame_header_length; 4885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) WebSocketFrameHeader::OpCode opcode = kTests[i].opcode; 4895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) WebSocketFrameParser parser; 4915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ScopedVector<WebSocketFrameChunk> frames; 4935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_TRUE(parser.Decode(frame_header, frame_header_length, &frames)); 494b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) EXPECT_EQ(kWebSocketNormalClosure, parser.websocket_error()); 4955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_EQ(1u, frames.size()); 4965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (frames.size() != 1u) 4975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) continue; 4985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) WebSocketFrameChunk* frame = frames[0]; 4995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_TRUE(frame != NULL); 5005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!frame) 5015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) continue; 5025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_TRUE(frame->final_chunk); 5035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_EQ(NULL, frame->data.get()); 5045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const WebSocketFrameHeader* header = frame->header.get(); 5055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_TRUE(header != NULL); 5065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!header) 5075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) continue; 5085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_TRUE(header->final); 5095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_FALSE(header->reserved1); 5105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_FALSE(header->reserved2); 5115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_FALSE(header->reserved3); 5125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_EQ(opcode, header->opcode); 5135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_FALSE(header->masked); 5145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_EQ(0u, header->payload_length); 5155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 5165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 5175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST(WebSocketFrameParserTest, FinalBitAndReservedBits) { 5195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) struct TestCase { 5205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const char* frame_header; 5215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) size_t frame_header_length; 5225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool final; 5235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool reserved1; 5245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool reserved2; 5255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool reserved3; 5265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) }; 5275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) static const TestCase kTests[] = { 5285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) { "\x81\x00", 2, true, false, false, false }, 5295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) { "\x01\x00", 2, false, false, false, false }, 5305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) { "\xC1\x00", 2, true, true, false, false }, 5315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) { "\xA1\x00", 2, true, false, true, false }, 5325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) { "\x91\x00", 2, true, false, false, true }, 5335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) { "\x71\x00", 2, false, true, true, true }, 5345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) { "\xF1\x00", 2, true, true, true, true } 5355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) }; 5365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) static const int kNumTests = ARRAYSIZE_UNSAFE(kTests); 5375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (int i = 0; i < kNumTests; ++i) { 5395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const char* frame_header = kTests[i].frame_header; 5405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) size_t frame_header_length = kTests[i].frame_header_length; 5415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool final = kTests[i].final; 5425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool reserved1 = kTests[i].reserved1; 5435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool reserved2 = kTests[i].reserved2; 5445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool reserved3 = kTests[i].reserved3; 5455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) WebSocketFrameParser parser; 5475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ScopedVector<WebSocketFrameChunk> frames; 5495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_TRUE(parser.Decode(frame_header, frame_header_length, &frames)); 550b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) EXPECT_EQ(kWebSocketNormalClosure, parser.websocket_error()); 5515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_EQ(1u, frames.size()); 5525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (frames.size() != 1u) 5535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) continue; 5545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) WebSocketFrameChunk* frame = frames[0]; 5555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_TRUE(frame != NULL); 5565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!frame) 5575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) continue; 5585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_TRUE(frame->final_chunk); 5595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_EQ(NULL, frame->data.get()); 5605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const WebSocketFrameHeader* header = frame->header.get(); 5615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_TRUE(header != NULL); 5625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!header) 5635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) continue; 5645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_EQ(final, header->final); 5655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_EQ(reserved1, header->reserved1); 5665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_EQ(reserved2, header->reserved2); 5675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_EQ(reserved3, header->reserved3); 5685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_EQ(WebSocketFrameHeader::kOpCodeText, header->opcode); 5695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_FALSE(header->masked); 5705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_EQ(0u, header->payload_length); 5715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 5725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 5735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} // Unnamed namespace 5755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} // namespace net 577