| 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 <stdint.h> | 7 #include <stdint.h> |
| 8 #include <algorithm> | 8 #include <algorithm> |
| 9 #include <vector> | 9 #include <vector> |
| 10 | 10 |
| 11 #include "base/basictypes.h" | 11 #include "base/basictypes.h" |
| 12 #include "base/memory/scoped_vector.h" | 12 #include "base/memory/scoped_vector.h" |
| 13 #include "net/base/io_buffer.h" | 13 #include "net/base/io_buffer.h" |
| 14 #include "net/websockets/websocket_frame.h" | 14 #include "net/websockets/websocket_frame.h" |
| 15 #include "testing/gtest/include/gtest/gtest.h" | 15 #include "testing/gtest/include/gtest/gtest.h" |
| 16 | 16 |
| 17 namespace net { | 17 namespace net { |
| 18 | 18 |
| 19 namespace { | 19 namespace { |
| 20 | 20 |
| 21 const char kHello[] = "Hello, world!"; | 21 const char kHello[] = "Hello, world!"; |
| 22 const uint64 kHelloLength = arraysize(kHello) - 1; | 22 const uint64_t kHelloLength = arraysize(kHello) - 1; |
| 23 const char kHelloFrame[] = "\x81\x0DHello, world!"; | 23 const char kHelloFrame[] = "\x81\x0DHello, world!"; |
| 24 const uint64 kHelloFrameLength = arraysize(kHelloFrame) - 1; | 24 const uint64_t kHelloFrameLength = arraysize(kHelloFrame) - 1; |
| 25 const char kMaskedHelloFrame[] = | 25 const char kMaskedHelloFrame[] = |
| 26 "\x81\x8D\xDE\xAD\xBE\xEF" | 26 "\x81\x8D\xDE\xAD\xBE\xEF" |
| 27 "\x96\xC8\xD2\x83\xB1\x81\x9E\x98\xB1\xDF\xD2\x8B\xFF"; | 27 "\x96\xC8\xD2\x83\xB1\x81\x9E\x98\xB1\xDF\xD2\x8B\xFF"; |
| 28 const uint64 kMaskedHelloFrameLength = arraysize(kMaskedHelloFrame) - 1; | 28 const uint64_t 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_t 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, UINT64_C(0), kWebSocketNormalClosure }, | 38 { "\x81\x00", 2, UINT64_C(0), kWebSocketNormalClosure }, |
| 39 { "\x81\x7D", 2, UINT64_C(125), kWebSocketNormalClosure }, | 39 { "\x81\x7D", 2, UINT64_C(125), kWebSocketNormalClosure }, |
| 40 { "\x81\x7E\x00\x7E", 4, UINT64_C(126), kWebSocketNormalClosure }, | 40 { "\x81\x7E\x00\x7E", 4, UINT64_C(126), kWebSocketNormalClosure }, |
| 41 { "\x81\x7E\xFF\xFF", 4, UINT64_C(0xFFFF), kWebSocketNormalClosure }, | 41 { "\x81\x7E\xFF\xFF", 4, UINT64_C(0xFFFF), kWebSocketNormalClosure }, |
| 42 { "\x81\x7F\x00\x00\x00\x00\x00\x01\x00\x00", 10, UINT64_C(0x10000), | 42 { "\x81\x7F\x00\x00\x00\x00\x00\x01\x00\x00", 10, UINT64_C(0x10000), |
| 43 kWebSocketNormalClosure }, | 43 kWebSocketNormalClosure }, |
| (...skipping 99 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 143 EXPECT_EQ(kWebSocketNormalClosure, parser.websocket_error()); | 143 EXPECT_EQ(kWebSocketNormalClosure, parser.websocket_error()); |
| 144 ASSERT_EQ(static_cast<size_t>(kNumInputs), frames.size()); | 144 ASSERT_EQ(static_cast<size_t>(kNumInputs), frames.size()); |
| 145 | 145 |
| 146 for (int i = 0; i < kNumInputs; ++i) { | 146 for (int i = 0; i < kNumInputs; ++i) { |
| 147 WebSocketFrameChunk* frame = frames[i]; | 147 WebSocketFrameChunk* frame = frames[i]; |
| 148 EXPECT_TRUE(frame != NULL); | 148 EXPECT_TRUE(frame != NULL); |
| 149 if (!frame) | 149 if (!frame) |
| 150 continue; | 150 continue; |
| 151 EXPECT_TRUE(frame->final_chunk); | 151 EXPECT_TRUE(frame->final_chunk); |
| 152 ASSERT_EQ(kInputs[i].expected_payload_length, | 152 ASSERT_EQ(kInputs[i].expected_payload_length, |
| 153 static_cast<uint64>(frame->data->size())); | 153 static_cast<uint64_t>(frame->data->size())); |
| 154 EXPECT_TRUE(std::equal( | 154 EXPECT_TRUE(std::equal( |
| 155 kInputs[i].expected_payload, | 155 kInputs[i].expected_payload, |
| 156 kInputs[i].expected_payload + kInputs[i].expected_payload_length, | 156 kInputs[i].expected_payload + kInputs[i].expected_payload_length, |
| 157 frame->data->data())); | 157 frame->data->data())); |
| 158 | 158 |
| 159 const WebSocketFrameHeader* header = frame->header.get(); | 159 const WebSocketFrameHeader* header = frame->header.get(); |
| 160 EXPECT_TRUE(header != NULL); | 160 EXPECT_TRUE(header != NULL); |
| 161 if (!header) | 161 if (!header) |
| 162 continue; | 162 continue; |
| 163 EXPECT_TRUE(header->final); | 163 EXPECT_TRUE(header->final); |
| (...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 221 if (frames2.size() != 1u) | 221 if (frames2.size() != 1u) |
| 222 continue; | 222 continue; |
| 223 WebSocketFrameChunk* frame2 = frames2[0]; | 223 WebSocketFrameChunk* frame2 = frames2[0]; |
| 224 EXPECT_TRUE(frame2 != NULL); | 224 EXPECT_TRUE(frame2 != NULL); |
| 225 if (!frame2) | 225 if (!frame2) |
| 226 continue; | 226 continue; |
| 227 EXPECT_TRUE(frame2->final_chunk); | 227 EXPECT_TRUE(frame2->final_chunk); |
| 228 if (expected2.size() == 0) { | 228 if (expected2.size() == 0) { |
| 229 EXPECT_EQ(NULL, frame2->data.get()); | 229 EXPECT_EQ(NULL, frame2->data.get()); |
| 230 } else { | 230 } else { |
| 231 ASSERT_EQ(expected2.size(), static_cast<uint64>(frame2->data->size())); | 231 ASSERT_EQ(expected2.size(), static_cast<uint64_t>(frame2->data->size())); |
| 232 EXPECT_TRUE( | 232 EXPECT_TRUE( |
| 233 std::equal(expected2.begin(), expected2.end(), frame2->data->data())); | 233 std::equal(expected2.begin(), expected2.end(), frame2->data->data())); |
| 234 } | 234 } |
| 235 const WebSocketFrameHeader* header2 = frame2->header.get(); | 235 const WebSocketFrameHeader* header2 = frame2->header.get(); |
| 236 EXPECT_TRUE(header2 == NULL); | 236 EXPECT_TRUE(header2 == NULL); |
| 237 } | 237 } |
| 238 } | 238 } |
| 239 | 239 |
| 240 TEST(WebSocketFrameParserTest, DecodePartialMaskedFrame) { | 240 TEST(WebSocketFrameParserTest, DecodePartialMaskedFrame) { |
| 241 static const size_t kFrameHeaderSize = 6; | 241 static const size_t kFrameHeaderSize = 6; |
| (...skipping 16 matching lines...) Expand all Loading... |
| 258 if (frames1.size() != 1u) | 258 if (frames1.size() != 1u) |
| 259 continue; | 259 continue; |
| 260 WebSocketFrameChunk* frame1 = frames1[0]; | 260 WebSocketFrameChunk* frame1 = frames1[0]; |
| 261 EXPECT_TRUE(frame1 != NULL); | 261 EXPECT_TRUE(frame1 != NULL); |
| 262 if (!frame1) | 262 if (!frame1) |
| 263 continue; | 263 continue; |
| 264 EXPECT_FALSE(frame1->final_chunk); | 264 EXPECT_FALSE(frame1->final_chunk); |
| 265 if (expected1.size() == 0) { | 265 if (expected1.size() == 0) { |
| 266 EXPECT_EQ(NULL, frame1->data.get()); | 266 EXPECT_EQ(NULL, frame1->data.get()); |
| 267 } else { | 267 } else { |
| 268 ASSERT_EQ(expected1.size(), static_cast<uint64>(frame1->data->size())); | 268 ASSERT_EQ(expected1.size(), static_cast<uint64_t>(frame1->data->size())); |
| 269 EXPECT_TRUE( | 269 EXPECT_TRUE( |
| 270 std::equal(expected1.begin(), expected1.end(), frame1->data->data())); | 270 std::equal(expected1.begin(), expected1.end(), frame1->data->data())); |
| 271 } | 271 } |
| 272 const WebSocketFrameHeader* header1 = frame1->header.get(); | 272 const WebSocketFrameHeader* header1 = frame1->header.get(); |
| 273 EXPECT_TRUE(header1 != NULL); | 273 EXPECT_TRUE(header1 != NULL); |
| 274 if (!header1) | 274 if (!header1) |
| 275 continue; | 275 continue; |
| 276 EXPECT_TRUE(header1->final); | 276 EXPECT_TRUE(header1->final); |
| 277 EXPECT_FALSE(header1->reserved1); | 277 EXPECT_FALSE(header1->reserved1); |
| 278 EXPECT_FALSE(header1->reserved2); | 278 EXPECT_FALSE(header1->reserved2); |
| 279 EXPECT_FALSE(header1->reserved3); | 279 EXPECT_FALSE(header1->reserved3); |
| 280 EXPECT_EQ(WebSocketFrameHeader::kOpCodeText, header1->opcode); | 280 EXPECT_EQ(WebSocketFrameHeader::kOpCodeText, header1->opcode); |
| 281 EXPECT_TRUE(header1->masked); | 281 EXPECT_TRUE(header1->masked); |
| 282 EXPECT_EQ(kHelloLength, header1->payload_length); | 282 EXPECT_EQ(kHelloLength, header1->payload_length); |
| 283 | 283 |
| 284 ScopedVector<WebSocketFrameChunk> frames2; | 284 ScopedVector<WebSocketFrameChunk> frames2; |
| 285 EXPECT_TRUE(parser.Decode(&input2.front(), input2.size(), &frames2)); | 285 EXPECT_TRUE(parser.Decode(&input2.front(), input2.size(), &frames2)); |
| 286 EXPECT_EQ(kWebSocketNormalClosure, parser.websocket_error()); | 286 EXPECT_EQ(kWebSocketNormalClosure, parser.websocket_error()); |
| 287 EXPECT_EQ(1u, frames2.size()); | 287 EXPECT_EQ(1u, frames2.size()); |
| 288 if (frames2.size() != 1u) | 288 if (frames2.size() != 1u) |
| 289 continue; | 289 continue; |
| 290 WebSocketFrameChunk* frame2 = frames2[0]; | 290 WebSocketFrameChunk* frame2 = frames2[0]; |
| 291 EXPECT_TRUE(frame2 != NULL); | 291 EXPECT_TRUE(frame2 != NULL); |
| 292 if (!frame2) | 292 if (!frame2) |
| 293 continue; | 293 continue; |
| 294 EXPECT_TRUE(frame2->final_chunk); | 294 EXPECT_TRUE(frame2->final_chunk); |
| 295 if (expected2.size() == 0) { | 295 if (expected2.size() == 0) { |
| 296 EXPECT_EQ(NULL, frame2->data.get()); | 296 EXPECT_EQ(NULL, frame2->data.get()); |
| 297 } else { | 297 } else { |
| 298 ASSERT_EQ(expected2.size(), static_cast<uint64>(frame2->data->size())); | 298 ASSERT_EQ(expected2.size(), static_cast<uint64_t>(frame2->data->size())); |
| 299 EXPECT_TRUE( | 299 EXPECT_TRUE( |
| 300 std::equal(expected2.begin(), expected2.end(), frame2->data->data())); | 300 std::equal(expected2.begin(), expected2.end(), frame2->data->data())); |
| 301 } | 301 } |
| 302 const WebSocketFrameHeader* header2 = frame2->header.get(); | 302 const WebSocketFrameHeader* header2 = frame2->header.get(); |
| 303 EXPECT_TRUE(header2 == NULL); | 303 EXPECT_TRUE(header2 == NULL); |
| 304 } | 304 } |
| 305 } | 305 } |
| 306 | 306 |
| 307 TEST(WebSocketFrameParserTest, DecodeFramesOfVariousLengths) { | 307 TEST(WebSocketFrameParserTest, DecodeFramesOfVariousLengths) { |
| 308 for (int i = 0; i < kNumFrameHeaderTests; ++i) { | 308 for (int i = 0; i < kNumFrameHeaderTests; ++i) { |
| 309 const char* frame_header = kFrameHeaderTests[i].frame_header; | 309 const char* frame_header = kFrameHeaderTests[i].frame_header; |
| 310 size_t frame_header_length = kFrameHeaderTests[i].frame_header_length; | 310 size_t frame_header_length = kFrameHeaderTests[i].frame_header_length; |
| 311 uint64 frame_length = kFrameHeaderTests[i].frame_length; | 311 uint64_t frame_length = kFrameHeaderTests[i].frame_length; |
| 312 | 312 |
| 313 std::vector<char> input(frame_header, frame_header + frame_header_length); | 313 std::vector<char> input(frame_header, frame_header + frame_header_length); |
| 314 // Limit the payload size not to flood the console on failure. | 314 // Limit the payload size not to flood the console on failure. |
| 315 static const uint64 kMaxPayloadSize = 200; | 315 static const uint64_t kMaxPayloadSize = 200; |
| 316 uint64 input_payload_size = std::min(frame_length, kMaxPayloadSize); | 316 uint64_t input_payload_size = std::min(frame_length, kMaxPayloadSize); |
| 317 input.insert(input.end(), input_payload_size, 'a'); | 317 input.insert(input.end(), input_payload_size, 'a'); |
| 318 | 318 |
| 319 WebSocketFrameParser parser; | 319 WebSocketFrameParser parser; |
| 320 | 320 |
| 321 ScopedVector<WebSocketFrameChunk> frames; | 321 ScopedVector<WebSocketFrameChunk> frames; |
| 322 EXPECT_EQ(kFrameHeaderTests[i].error_code == kWebSocketNormalClosure, | 322 EXPECT_EQ(kFrameHeaderTests[i].error_code == kWebSocketNormalClosure, |
| 323 parser.Decode(&input.front(), input.size(), &frames)); | 323 parser.Decode(&input.front(), input.size(), &frames)); |
| 324 EXPECT_EQ(kFrameHeaderTests[i].error_code, parser.websocket_error()); | 324 EXPECT_EQ(kFrameHeaderTests[i].error_code, parser.websocket_error()); |
| 325 if (kFrameHeaderTests[i].error_code != kWebSocketNormalClosure) { | 325 if (kFrameHeaderTests[i].error_code != kWebSocketNormalClosure) { |
| 326 EXPECT_EQ(0u, frames.size()); | 326 EXPECT_EQ(0u, frames.size()); |
| 327 } else { | 327 } else { |
| 328 EXPECT_EQ(1u, frames.size()); | 328 EXPECT_EQ(1u, frames.size()); |
| 329 } | 329 } |
| 330 if (frames.size() != 1u) | 330 if (frames.size() != 1u) |
| 331 continue; | 331 continue; |
| 332 WebSocketFrameChunk* frame = frames[0]; | 332 WebSocketFrameChunk* frame = frames[0]; |
| 333 EXPECT_TRUE(frame != NULL); | 333 EXPECT_TRUE(frame != NULL); |
| 334 if (!frame) | 334 if (!frame) |
| 335 continue; | 335 continue; |
| 336 if (frame_length == input_payload_size) { | 336 if (frame_length == input_payload_size) { |
| 337 EXPECT_TRUE(frame->final_chunk); | 337 EXPECT_TRUE(frame->final_chunk); |
| 338 } else { | 338 } else { |
| 339 EXPECT_FALSE(frame->final_chunk); | 339 EXPECT_FALSE(frame->final_chunk); |
| 340 } | 340 } |
| 341 std::vector<char> expected_payload(input_payload_size, 'a'); | 341 std::vector<char> expected_payload(input_payload_size, 'a'); |
| 342 if (expected_payload.size() == 0) { | 342 if (expected_payload.size() == 0) { |
| 343 EXPECT_EQ(NULL, frame->data.get()); | 343 EXPECT_EQ(NULL, frame->data.get()); |
| 344 } else { | 344 } else { |
| 345 ASSERT_EQ(expected_payload.size(), | 345 ASSERT_EQ(expected_payload.size(), |
| 346 static_cast<uint64>(frame->data->size())); | 346 static_cast<uint64_t>(frame->data->size())); |
| 347 EXPECT_TRUE(std::equal(expected_payload.begin(), | 347 EXPECT_TRUE(std::equal(expected_payload.begin(), |
| 348 expected_payload.end(), | 348 expected_payload.end(), |
| 349 frame->data->data())); | 349 frame->data->data())); |
| 350 } | 350 } |
| 351 const WebSocketFrameHeader* header = frame->header.get(); | 351 const WebSocketFrameHeader* header = frame->header.get(); |
| 352 EXPECT_TRUE(header != NULL); | 352 EXPECT_TRUE(header != NULL); |
| 353 if (!header) | 353 if (!header) |
| 354 continue; | 354 continue; |
| 355 EXPECT_TRUE(header->final); | 355 EXPECT_TRUE(header->final); |
| 356 EXPECT_FALSE(header->reserved1); | 356 EXPECT_FALSE(header->reserved1); |
| 357 EXPECT_FALSE(header->reserved2); | 357 EXPECT_FALSE(header->reserved2); |
| 358 EXPECT_FALSE(header->reserved3); | 358 EXPECT_FALSE(header->reserved3); |
| 359 EXPECT_EQ(WebSocketFrameHeader::kOpCodeText, header->opcode); | 359 EXPECT_EQ(WebSocketFrameHeader::kOpCodeText, header->opcode); |
| 360 EXPECT_FALSE(header->masked); | 360 EXPECT_FALSE(header->masked); |
| 361 EXPECT_EQ(frame_length, header->payload_length); | 361 EXPECT_EQ(frame_length, header->payload_length); |
| 362 } | 362 } |
| 363 } | 363 } |
| 364 | 364 |
| 365 TEST(WebSocketFrameParserTest, DecodePartialHeader) { | 365 TEST(WebSocketFrameParserTest, DecodePartialHeader) { |
| 366 for (int i = 0; i < kNumFrameHeaderTests; ++i) { | 366 for (int i = 0; i < kNumFrameHeaderTests; ++i) { |
| 367 const char* frame_header = kFrameHeaderTests[i].frame_header; | 367 const char* frame_header = kFrameHeaderTests[i].frame_header; |
| 368 size_t frame_header_length = kFrameHeaderTests[i].frame_header_length; | 368 size_t frame_header_length = kFrameHeaderTests[i].frame_header_length; |
| 369 uint64 frame_length = kFrameHeaderTests[i].frame_length; | 369 uint64_t frame_length = kFrameHeaderTests[i].frame_length; |
| 370 | 370 |
| 371 WebSocketFrameParser parser; | 371 WebSocketFrameParser parser; |
| 372 | 372 |
| 373 ScopedVector<WebSocketFrameChunk> frames; | 373 ScopedVector<WebSocketFrameChunk> frames; |
| 374 // Feed each byte to the parser to see if the parser behaves correctly | 374 // Feed each byte to the parser to see if the parser behaves correctly |
| 375 // when it receives partial frame header. | 375 // when it receives partial frame header. |
| 376 size_t last_byte_offset = frame_header_length - 1; | 376 size_t last_byte_offset = frame_header_length - 1; |
| 377 for (size_t j = 0; j < frame_header_length; ++j) { | 377 for (size_t j = 0; j < frame_header_length; ++j) { |
| 378 bool failed = | 378 bool failed = |
| 379 kFrameHeaderTests[i].error_code != kWebSocketNormalClosure && | 379 kFrameHeaderTests[i].error_code != kWebSocketNormalClosure && |
| (...skipping 187 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 567 EXPECT_EQ(reserved3, header->reserved3); | 567 EXPECT_EQ(reserved3, header->reserved3); |
| 568 EXPECT_EQ(WebSocketFrameHeader::kOpCodeText, header->opcode); | 568 EXPECT_EQ(WebSocketFrameHeader::kOpCodeText, header->opcode); |
| 569 EXPECT_FALSE(header->masked); | 569 EXPECT_FALSE(header->masked); |
| 570 EXPECT_EQ(0u, header->payload_length); | 570 EXPECT_EQ(0u, header->payload_length); |
| 571 } | 571 } |
| 572 } | 572 } |
| 573 | 573 |
| 574 } // Unnamed namespace | 574 } // Unnamed namespace |
| 575 | 575 |
| 576 } // namespace net | 576 } // namespace net |
| OLD | NEW |