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 |