| OLD | NEW |
| 1 // Copyright 2013 The Chromium Authors. All rights reserved. | 1 // Copyright 2013 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "net/websockets/websocket_frame_parser.h" | 5 #include "net/websockets/websocket_frame_parser.h" |
| 6 | 6 |
| 7 #include <algorithm> | 7 #include <algorithm> |
| 8 #include <vector> | 8 #include <vector> |
| 9 | 9 |
| 10 #include "base/basictypes.h" | 10 #include "base/basictypes.h" |
| (...skipping 17 matching lines...) Expand all Loading... |
| 28 const uint64 kMaskedHelloFrameLength = arraysize(kMaskedHelloFrame) - 1; | 28 const uint64 kMaskedHelloFrameLength = arraysize(kMaskedHelloFrame) - 1; |
| 29 | 29 |
| 30 struct FrameHeaderTestCase { | 30 struct FrameHeaderTestCase { |
| 31 const char* frame_header; | 31 const char* frame_header; |
| 32 size_t frame_header_length; | 32 size_t frame_header_length; |
| 33 uint64 frame_length; | 33 uint64 frame_length; |
| 34 WebSocketError error_code; | 34 WebSocketError error_code; |
| 35 }; | 35 }; |
| 36 | 36 |
| 37 const FrameHeaderTestCase kFrameHeaderTests[] = { | 37 const FrameHeaderTestCase kFrameHeaderTests[] = { |
| 38 { "\x81\x00", 2, GG_UINT64_C(0), kWebSocketNormalClosure }, | 38 {"\x81\x00", 2, GG_UINT64_C(0), kWebSocketNormalClosure}, |
| 39 { "\x81\x7D", 2, GG_UINT64_C(125), kWebSocketNormalClosure }, | 39 {"\x81\x7D", 2, GG_UINT64_C(125), kWebSocketNormalClosure}, |
| 40 { "\x81\x7E\x00\x7E", 4, GG_UINT64_C(126), kWebSocketNormalClosure }, | 40 {"\x81\x7E\x00\x7E", 4, GG_UINT64_C(126), kWebSocketNormalClosure}, |
| 41 { "\x81\x7E\xFF\xFF", 4, GG_UINT64_C(0xFFFF), kWebSocketNormalClosure }, | 41 {"\x81\x7E\xFF\xFF", 4, GG_UINT64_C(0xFFFF), kWebSocketNormalClosure}, |
| 42 { "\x81\x7F\x00\x00\x00\x00\x00\x01\x00\x00", 10, GG_UINT64_C(0x10000), | 42 {"\x81\x7F\x00\x00\x00\x00\x00\x01\x00\x00", 10, GG_UINT64_C(0x10000), |
| 43 kWebSocketNormalClosure }, | 43 kWebSocketNormalClosure}, |
| 44 { "\x81\x7F\x00\x00\x00\x00\x7F\xFF\xFF\xFF", 10, GG_UINT64_C(0x7FFFFFFF), | 44 {"\x81\x7F\x00\x00\x00\x00\x7F\xFF\xFF\xFF", 10, GG_UINT64_C(0x7FFFFFFF), |
| 45 kWebSocketNormalClosure }, | 45 kWebSocketNormalClosure}, |
| 46 { "\x81\x7F\x00\x00\x00\x00\x80\x00\x00\x00", 10, GG_UINT64_C(0x80000000), | 46 {"\x81\x7F\x00\x00\x00\x00\x80\x00\x00\x00", 10, GG_UINT64_C(0x80000000), |
| 47 kWebSocketErrorMessageTooBig }, | 47 kWebSocketErrorMessageTooBig}, |
| 48 { "\x81\x7F\x7F\xFF\xFF\xFF\xFF\xFF\xFF\xFF", 10, | 48 {"\x81\x7F\x7F\xFF\xFF\xFF\xFF\xFF\xFF\xFF", 10, |
| 49 GG_UINT64_C(0x7FFFFFFFFFFFFFFF), kWebSocketErrorMessageTooBig } | 49 GG_UINT64_C(0x7FFFFFFFFFFFFFFF), kWebSocketErrorMessageTooBig}}; |
| 50 }; | |
| 51 const int kNumFrameHeaderTests = arraysize(kFrameHeaderTests); | 50 const int kNumFrameHeaderTests = arraysize(kFrameHeaderTests); |
| 52 | 51 |
| 53 TEST(WebSocketFrameParserTest, DecodeNormalFrame) { | 52 TEST(WebSocketFrameParserTest, DecodeNormalFrame) { |
| 54 WebSocketFrameParser parser; | 53 WebSocketFrameParser parser; |
| 55 | 54 |
| 56 ScopedVector<WebSocketFrameChunk> frames; | 55 ScopedVector<WebSocketFrameChunk> frames; |
| 57 EXPECT_TRUE(parser.Decode(kHelloFrame, kHelloFrameLength, &frames)); | 56 EXPECT_TRUE(parser.Decode(kHelloFrame, kHelloFrameLength, &frames)); |
| 58 EXPECT_EQ(kWebSocketNormalClosure, parser.websocket_error()); | 57 EXPECT_EQ(kWebSocketNormalClosure, parser.websocket_error()); |
| 59 ASSERT_EQ(1u, frames.size()); | 58 ASSERT_EQ(1u, frames.size()); |
| 60 WebSocketFrameChunk* frame = frames[0]; | 59 WebSocketFrameChunk* frame = frames[0]; |
| (...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 104 } | 103 } |
| 105 | 104 |
| 106 TEST(WebSocketFrameParserTest, DecodeManyFrames) { | 105 TEST(WebSocketFrameParserTest, DecodeManyFrames) { |
| 107 struct Input { | 106 struct Input { |
| 108 const char* frame; | 107 const char* frame; |
| 109 size_t frame_length; | 108 size_t frame_length; |
| 110 const char* expected_payload; | 109 const char* expected_payload; |
| 111 size_t expected_payload_length; | 110 size_t expected_payload_length; |
| 112 }; | 111 }; |
| 113 static const Input kInputs[] = { | 112 static const Input kInputs[] = { |
| 114 // Each |frame| data is split into two string literals because C++ lexers | 113 // Each |frame| data is split into two string literals because C++ lexers |
| 115 // consume unlimited number of hex characters in a hex character escape | 114 // consume unlimited number of hex characters in a hex character escape |
| 116 // (e.g. "\x05F" is not treated as { '\x5', 'F', '\0' } but as | 115 // (e.g. "\x05F" is not treated as { '\x5', 'F', '\0' } but as |
| 117 // { '\x5F', '\0' }). | 116 // { '\x5F', '\0' }). |
| 118 { "\x81\x05" "First", 7, "First", 5 }, | 117 {"\x81\x05" |
| 119 { "\x81\x06" "Second", 8, "Second", 6 }, | 118 "First", |
| 120 { "\x81\x05" "Third", 7, "Third", 5 }, | 119 7, "First", 5}, |
| 121 { "\x81\x06" "Fourth", 8, "Fourth", 6 }, | 120 {"\x81\x06" |
| 122 { "\x81\x05" "Fifth", 7, "Fifth", 5 }, | 121 "Second", |
| 123 { "\x81\x05" "Sixth", 7, "Sixth", 5 }, | 122 8, "Second", 6}, |
| 124 { "\x81\x07" "Seventh", 9, "Seventh", 7 }, | 123 {"\x81\x05" |
| 125 { "\x81\x06" "Eighth", 8, "Eighth", 6 }, | 124 "Third", |
| 126 { "\x81\x05" "Ninth", 7, "Ninth", 5 }, | 125 7, "Third", 5}, |
| 127 { "\x81\x05" "Tenth", 7, "Tenth", 5 } | 126 {"\x81\x06" |
| 128 }; | 127 "Fourth", |
| 128 8, "Fourth", 6}, |
| 129 {"\x81\x05" |
| 130 "Fifth", |
| 131 7, "Fifth", 5}, |
| 132 {"\x81\x05" |
| 133 "Sixth", |
| 134 7, "Sixth", 5}, |
| 135 {"\x81\x07" |
| 136 "Seventh", |
| 137 9, "Seventh", 7}, |
| 138 {"\x81\x06" |
| 139 "Eighth", |
| 140 8, "Eighth", 6}, |
| 141 {"\x81\x05" |
| 142 "Ninth", |
| 143 7, "Ninth", 5}, |
| 144 {"\x81\x05" |
| 145 "Tenth", |
| 146 7, "Tenth", 5}}; |
| 129 static const int kNumInputs = ARRAYSIZE_UNSAFE(kInputs); | 147 static const int kNumInputs = ARRAYSIZE_UNSAFE(kInputs); |
| 130 | 148 |
| 131 std::vector<char> input; | 149 std::vector<char> input; |
| 132 // Concatenate all frames. | 150 // Concatenate all frames. |
| 133 for (int i = 0; i < kNumInputs; ++i) { | 151 for (int i = 0; i < kNumInputs; ++i) { |
| 134 input.insert(input.end(), | 152 input.insert(input.end(), |
| 135 kInputs[i].frame, | 153 kInputs[i].frame, |
| 136 kInputs[i].frame + kInputs[i].frame_length); | 154 kInputs[i].frame + kInputs[i].frame_length); |
| 137 } | 155 } |
| 138 | 156 |
| (...skipping 277 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 416 EXPECT_EQ(frame_length, header->payload_length); | 434 EXPECT_EQ(frame_length, header->payload_length); |
| 417 } | 435 } |
| 418 } | 436 } |
| 419 | 437 |
| 420 TEST(WebSocketFrameParserTest, InvalidLengthEncoding) { | 438 TEST(WebSocketFrameParserTest, InvalidLengthEncoding) { |
| 421 struct TestCase { | 439 struct TestCase { |
| 422 const char* frame_header; | 440 const char* frame_header; |
| 423 size_t frame_header_length; | 441 size_t frame_header_length; |
| 424 }; | 442 }; |
| 425 static const TestCase kTests[] = { | 443 static const TestCase kTests[] = { |
| 426 // For frames with two-byte extended length field, the payload length | 444 // For frames with two-byte extended length field, the payload length |
| 427 // should be 126 (0x7E) bytes or more. | 445 // should be 126 (0x7E) bytes or more. |
| 428 { "\x81\x7E\x00\x00", 4 }, | 446 {"\x81\x7E\x00\x00", 4}, |
| 429 { "\x81\x7E\x00\x7D", 4 }, | 447 {"\x81\x7E\x00\x7D", 4}, |
| 430 // For frames with eight-byte extended length field, the payload length | 448 // For frames with eight-byte extended length field, the payload length |
| 431 // should be 0x10000 bytes or more. | 449 // should be 0x10000 bytes or more. |
| 432 { "\x81\x7F\x00\x00\x00\x00\x00\x00\x00\x00", 10 }, | 450 {"\x81\x7F\x00\x00\x00\x00\x00\x00\x00\x00", 10}, |
| 433 { "\x81\x7E\x00\x00\x00\x00\x00\x00\xFF\xFF", 10 }, | 451 {"\x81\x7E\x00\x00\x00\x00\x00\x00\xFF\xFF", 10}, |
| 434 }; | 452 }; |
| 435 static const int kNumTests = ARRAYSIZE_UNSAFE(kTests); | 453 static const int kNumTests = ARRAYSIZE_UNSAFE(kTests); |
| 436 | 454 |
| 437 for (int i = 0; i < kNumTests; ++i) { | 455 for (int i = 0; i < kNumTests; ++i) { |
| 438 const char* frame_header = kTests[i].frame_header; | 456 const char* frame_header = kTests[i].frame_header; |
| 439 size_t frame_header_length = kTests[i].frame_header_length; | 457 size_t frame_header_length = kTests[i].frame_header_length; |
| 440 | 458 |
| 441 WebSocketFrameParser parser; | 459 WebSocketFrameParser parser; |
| 442 | 460 |
| 443 ScopedVector<WebSocketFrameChunk> frames; | 461 ScopedVector<WebSocketFrameChunk> frames; |
| (...skipping 10 matching lines...) Expand all Loading... |
| 454 } | 472 } |
| 455 } | 473 } |
| 456 | 474 |
| 457 TEST(WebSocketFrameParserTest, FrameTypes) { | 475 TEST(WebSocketFrameParserTest, FrameTypes) { |
| 458 struct TestCase { | 476 struct TestCase { |
| 459 const char* frame_header; | 477 const char* frame_header; |
| 460 size_t frame_header_length; | 478 size_t frame_header_length; |
| 461 WebSocketFrameHeader::OpCode opcode; | 479 WebSocketFrameHeader::OpCode opcode; |
| 462 }; | 480 }; |
| 463 static const TestCase kTests[] = { | 481 static const TestCase kTests[] = { |
| 464 { "\x80\x00", 2, WebSocketFrameHeader::kOpCodeContinuation }, | 482 {"\x80\x00", 2, WebSocketFrameHeader::kOpCodeContinuation}, |
| 465 { "\x81\x00", 2, WebSocketFrameHeader::kOpCodeText }, | 483 {"\x81\x00", 2, WebSocketFrameHeader::kOpCodeText}, |
| 466 { "\x82\x00", 2, WebSocketFrameHeader::kOpCodeBinary }, | 484 {"\x82\x00", 2, WebSocketFrameHeader::kOpCodeBinary}, |
| 467 { "\x88\x00", 2, WebSocketFrameHeader::kOpCodeClose }, | 485 {"\x88\x00", 2, WebSocketFrameHeader::kOpCodeClose}, |
| 468 { "\x89\x00", 2, WebSocketFrameHeader::kOpCodePing }, | 486 {"\x89\x00", 2, WebSocketFrameHeader::kOpCodePing}, |
| 469 { "\x8A\x00", 2, WebSocketFrameHeader::kOpCodePong }, | 487 {"\x8A\x00", 2, WebSocketFrameHeader::kOpCodePong}, |
| 470 // These are undefined opcodes, but the parser needs to be able to parse | 488 // These are undefined opcodes, but the parser needs to be able to parse |
| 471 // them anyway. | 489 // them anyway. |
| 472 { "\x83\x00", 2, 0x3 }, | 490 {"\x83\x00", 2, 0x3}, |
| 473 { "\x84\x00", 2, 0x4 }, | 491 {"\x84\x00", 2, 0x4}, |
| 474 { "\x85\x00", 2, 0x5 }, | 492 {"\x85\x00", 2, 0x5}, |
| 475 { "\x86\x00", 2, 0x6 }, | 493 {"\x86\x00", 2, 0x6}, |
| 476 { "\x87\x00", 2, 0x7 }, | 494 {"\x87\x00", 2, 0x7}, |
| 477 { "\x8B\x00", 2, 0xB }, | 495 {"\x8B\x00", 2, 0xB}, |
| 478 { "\x8C\x00", 2, 0xC }, | 496 {"\x8C\x00", 2, 0xC}, |
| 479 { "\x8D\x00", 2, 0xD }, | 497 {"\x8D\x00", 2, 0xD}, |
| 480 { "\x8E\x00", 2, 0xE }, | 498 {"\x8E\x00", 2, 0xE}, |
| 481 { "\x8F\x00", 2, 0xF } | 499 {"\x8F\x00", 2, 0xF}}; |
| 482 }; | |
| 483 static const int kNumTests = ARRAYSIZE_UNSAFE(kTests); | 500 static const int kNumTests = ARRAYSIZE_UNSAFE(kTests); |
| 484 | 501 |
| 485 for (int i = 0; i < kNumTests; ++i) { | 502 for (int i = 0; i < kNumTests; ++i) { |
| 486 const char* frame_header = kTests[i].frame_header; | 503 const char* frame_header = kTests[i].frame_header; |
| 487 size_t frame_header_length = kTests[i].frame_header_length; | 504 size_t frame_header_length = kTests[i].frame_header_length; |
| 488 WebSocketFrameHeader::OpCode opcode = kTests[i].opcode; | 505 WebSocketFrameHeader::OpCode opcode = kTests[i].opcode; |
| 489 | 506 |
| 490 WebSocketFrameParser parser; | 507 WebSocketFrameParser parser; |
| 491 | 508 |
| 492 ScopedVector<WebSocketFrameChunk> frames; | 509 ScopedVector<WebSocketFrameChunk> frames; |
| (...skipping 24 matching lines...) Expand all Loading... |
| 517 | 534 |
| 518 TEST(WebSocketFrameParserTest, FinalBitAndReservedBits) { | 535 TEST(WebSocketFrameParserTest, FinalBitAndReservedBits) { |
| 519 struct TestCase { | 536 struct TestCase { |
| 520 const char* frame_header; | 537 const char* frame_header; |
| 521 size_t frame_header_length; | 538 size_t frame_header_length; |
| 522 bool final; | 539 bool final; |
| 523 bool reserved1; | 540 bool reserved1; |
| 524 bool reserved2; | 541 bool reserved2; |
| 525 bool reserved3; | 542 bool reserved3; |
| 526 }; | 543 }; |
| 527 static const TestCase kTests[] = { | 544 static const TestCase kTests[] = {{"\x81\x00", 2, true, false, false, false}, |
| 528 { "\x81\x00", 2, true, false, false, false }, | 545 {"\x01\x00", 2, false, false, false, false}, |
| 529 { "\x01\x00", 2, false, false, false, false }, | 546 {"\xC1\x00", 2, true, true, false, false}, |
| 530 { "\xC1\x00", 2, true, true, false, false }, | 547 {"\xA1\x00", 2, true, false, true, false}, |
| 531 { "\xA1\x00", 2, true, false, true, false }, | 548 {"\x91\x00", 2, true, false, false, true}, |
| 532 { "\x91\x00", 2, true, false, false, true }, | 549 {"\x71\x00", 2, false, true, true, true}, |
| 533 { "\x71\x00", 2, false, true, true, true }, | 550 {"\xF1\x00", 2, true, true, true, true}}; |
| 534 { "\xF1\x00", 2, true, true, true, true } | |
| 535 }; | |
| 536 static const int kNumTests = ARRAYSIZE_UNSAFE(kTests); | 551 static const int kNumTests = ARRAYSIZE_UNSAFE(kTests); |
| 537 | 552 |
| 538 for (int i = 0; i < kNumTests; ++i) { | 553 for (int i = 0; i < kNumTests; ++i) { |
| 539 const char* frame_header = kTests[i].frame_header; | 554 const char* frame_header = kTests[i].frame_header; |
| 540 size_t frame_header_length = kTests[i].frame_header_length; | 555 size_t frame_header_length = kTests[i].frame_header_length; |
| 541 bool final = kTests[i].final; | 556 bool final = kTests[i].final; |
| 542 bool reserved1 = kTests[i].reserved1; | 557 bool reserved1 = kTests[i].reserved1; |
| 543 bool reserved2 = kTests[i].reserved2; | 558 bool reserved2 = kTests[i].reserved2; |
| 544 bool reserved3 = kTests[i].reserved3; | 559 bool reserved3 = kTests[i].reserved3; |
| 545 | 560 |
| (...skipping 21 matching lines...) Expand all Loading... |
| 567 EXPECT_EQ(reserved3, header->reserved3); | 582 EXPECT_EQ(reserved3, header->reserved3); |
| 568 EXPECT_EQ(WebSocketFrameHeader::kOpCodeText, header->opcode); | 583 EXPECT_EQ(WebSocketFrameHeader::kOpCodeText, header->opcode); |
| 569 EXPECT_FALSE(header->masked); | 584 EXPECT_FALSE(header->masked); |
| 570 EXPECT_EQ(0u, header->payload_length); | 585 EXPECT_EQ(0u, header->payload_length); |
| 571 } | 586 } |
| 572 } | 587 } |
| 573 | 588 |
| 574 } // Unnamed namespace | 589 } // Unnamed namespace |
| 575 | 590 |
| 576 } // namespace net | 591 } // namespace net |
| OLD | NEW |