1#include "inspector_socket.h" 2#include "util-inl.h" 3#include "gtest/gtest.h" 4 5#include <queue> 6 7#define PORT 9444 8 9namespace { 10 11using node::inspector::InspectorSocket; 12 13static const int MAX_LOOP_ITERATIONS = 10000; 14 15static uv_loop_t loop; 16 17class Timeout { 18 public: 19 explicit Timeout(uv_loop_t* loop) : timed_out(false), done_(false) { 20 uv_timer_init(loop, &timer_); 21 uv_timer_start(&timer_, Timeout::set_flag, 5000, 0); 22 } 23 24 ~Timeout() { 25 uv_timer_stop(&timer_); 26 uv_close(reinterpret_cast<uv_handle_t*>(&timer_), mark_done); 27 while (!done_) { 28 uv_run(&loop, UV_RUN_NOWAIT); 29 } 30 } 31 32 bool timed_out; 33 34 private: 35 static void set_flag(uv_timer_t* timer) { 36 Timeout* t = node::ContainerOf(&Timeout::timer_, timer); 37 t->timed_out = true; 38 } 39 40 static void mark_done(uv_handle_t* timer) { 41 Timeout* t = node::ContainerOf(&Timeout::timer_, 42 reinterpret_cast<uv_timer_t*>(timer)); 43 t->done_ = true; 44 } 45 46 bool done_; 47 uv_timer_t timer_; 48}; 49 50#define SPIN_WHILE(condition) \ 51 { \ 52 Timeout timeout(&loop); \ 53 while ((condition) && !timeout.timed_out) { \ 54 uv_run(&loop, UV_RUN_NOWAIT); \ 55 } \ 56 ASSERT_FALSE((condition)); \ 57 } 58 59enum inspector_handshake_event { 60 kInspectorHandshakeHttpGet, 61 kInspectorHandshakeUpgraded, 62 kInspectorHandshakeNoEvents 63}; 64 65static bool waiting_to_close = true; 66 67void handle_closed(uv_handle_t* handle) { 68 waiting_to_close = false; 69} 70 71static void really_close(uv_handle_t* handle) { 72 waiting_to_close = true; 73 if (!uv_is_closing(handle)) { 74 uv_close(handle, handle_closed); 75 SPIN_WHILE(waiting_to_close); 76 } 77} 78 79static void buffer_alloc_cb(uv_handle_t* stream, size_t len, uv_buf_t* buf) { 80 buf->base = new char[len]; 81 buf->len = len; 82} 83 84class TestInspectorDelegate; 85 86static TestInspectorDelegate* delegate = nullptr; 87 88// Gtest asserts can't be used in dtor directly. 89static void assert_is_delegate(TestInspectorDelegate* d) { 90 GTEST_ASSERT_EQ(delegate, d); 91} 92 93class TestInspectorDelegate : public InspectorSocket::Delegate { 94 public: 95 using delegate_fn = void(*)(inspector_handshake_event, const std::string&, 96 bool* should_continue); 97 98 TestInspectorDelegate() : inspector_ready(false), 99 last_event(kInspectorHandshakeNoEvents), 100 handshake_events(0), 101 handshake_delegate_(stop_if_stop_path), 102 fail_on_ws_frame_(false) { } 103 104 ~TestInspectorDelegate() override { 105 assert_is_delegate(this); 106 delegate = nullptr; 107 } 108 109 void OnHttpGet(const std::string& host, const std::string& path) override { 110 process(kInspectorHandshakeHttpGet, path); 111 } 112 113 void OnSocketUpgrade(const std::string& host, const std::string& path, 114 const std::string& ws_key) override { 115 ws_key_ = ws_key; 116 process(kInspectorHandshakeUpgraded, path); 117 } 118 119 void OnWsFrame(const std::vector<char>& buffer) override { 120 ASSERT_FALSE(fail_on_ws_frame_); 121 frames.push(buffer); 122 } 123 124 void SetDelegate(delegate_fn d) { 125 handshake_delegate_ = d; 126 } 127 128 void SetInspector(InspectorSocket::Pointer inspector) { 129 socket_ = std::move(inspector); 130 } 131 132 void Write(const char* buf, size_t len) { 133 socket_->Write(buf, len); 134 } 135 136 void ExpectReadError() { 137 SPIN_WHILE(frames.empty() || !frames.back().empty()); 138 } 139 140 void ExpectData(const char* data, size_t len) { 141 const char* cur = data; 142 const char* end = data + len; 143 while (cur < end) { 144 SPIN_WHILE(frames.empty()); 145 const std::vector<char>& frame = frames.front(); 146 EXPECT_FALSE(frame.empty()); 147 auto c = frame.begin(); 148 for (; c < frame.end() && cur < end; c++) { 149 GTEST_ASSERT_EQ(*cur, *c) << "Character #" << cur - data; 150 cur = cur + 1; 151 } 152 EXPECT_EQ(c, frame.end()); 153 frames.pop(); 154 } 155 } 156 157 void FailOnWsFrame() { 158 fail_on_ws_frame_ = true; 159 } 160 161 void WaitForDispose() { 162 SPIN_WHILE(delegate != nullptr); 163 } 164 165 void Close() { 166 socket_.reset(); 167 } 168 169 bool inspector_ready; 170 std::string last_path; // NOLINT(runtime/string) 171 inspector_handshake_event last_event; 172 int handshake_events; 173 std::queue<std::vector<char>> frames; 174 175 private: 176 static void stop_if_stop_path(enum inspector_handshake_event state, 177 const std::string& path, bool* cont) { 178 *cont = path.empty() || path != "/close"; 179 } 180 181 void process(inspector_handshake_event event, const std::string& path); 182 183 delegate_fn handshake_delegate_; 184 InspectorSocket::Pointer socket_; 185 std::string ws_key_; 186 bool fail_on_ws_frame_; 187}; 188 189static bool connected = false; 190static uv_tcp_t server, client_socket; 191static const char SERVER_CLOSE_FRAME[] = {'\x88', '\x00'}; 192 193struct read_expects { 194 const char* expected; 195 size_t expected_len; 196 size_t pos; 197 bool read_expected; 198 bool callback_called; 199}; 200 201static const char HANDSHAKE_REQ[] = "GET /ws/path HTTP/1.1\r\n" 202 "Host: localhost:9229\r\n" 203 "Upgrade: websocket\r\n" 204 "Connection: Upgrade\r\n" 205 "Sec-WebSocket-Key: aaa==\r\n" 206 "Sec-WebSocket-Version: 13\r\n\r\n"; 207 208void TestInspectorDelegate::process(inspector_handshake_event event, 209 const std::string& path) { 210 inspector_ready = event == kInspectorHandshakeUpgraded; 211 last_event = event; 212 if (path.empty()) { 213 last_path = "@@@ Nothing received @@@"; 214 } else { 215 last_path = path; 216 } 217 handshake_events++; 218 bool should_continue = true; 219 handshake_delegate_(event, path, &should_continue); 220 if (should_continue) { 221 if (inspector_ready) 222 socket_->AcceptUpgrade(ws_key_); 223 } else { 224 socket_->CancelHandshake(); 225 } 226} 227 228static void on_new_connection(uv_stream_t* server, int status) { 229 GTEST_ASSERT_EQ(0, status); 230 connected = true; 231 delegate = new TestInspectorDelegate(); 232 delegate->SetInspector( 233 InspectorSocket::Accept(server, 234 InspectorSocket::DelegatePointer(delegate))); 235 GTEST_ASSERT_NE(nullptr, delegate); 236} 237 238void write_done(uv_write_t* req, int status) { req->data = nullptr; } 239 240static void do_write(const char* data, int len) { 241 uv_write_t req; 242 bool done = false; 243 req.data = &done; 244 uv_buf_t buf[1]; 245 buf[0].base = const_cast<char*>(data); 246 buf[0].len = len; 247 GTEST_ASSERT_EQ(0, 248 uv_write(&req, reinterpret_cast<uv_stream_t*>(&client_socket), 249 buf, 1, write_done)); 250 SPIN_WHILE(req.data); 251} 252 253static void check_data_cb(read_expects* expectation, ssize_t nread, 254 const uv_buf_t* buf, bool* retval) { 255 *retval = false; 256 EXPECT_TRUE(nread >= 0 && nread != UV_EOF); 257 ssize_t i; 258 char c, actual; 259 CHECK_GT(expectation->expected_len, 0); 260 for (i = 0; i < nread && expectation->pos <= expectation->expected_len; i++) { 261 c = expectation->expected[expectation->pos++]; 262 actual = buf->base[i]; 263 if (c != actual) { 264 fprintf(stderr, "Unexpected character at position %zd\n", 265 expectation->pos - 1); 266 GTEST_ASSERT_EQ(c, actual); 267 } 268 } 269 GTEST_ASSERT_EQ(i, nread); 270 delete[] buf->base; 271 if (expectation->pos == expectation->expected_len) { 272 expectation->read_expected = true; 273 *retval = true; 274 } 275} 276 277static void check_data_cb(uv_stream_t* stream, ssize_t nread, 278 const uv_buf_t* buf) { 279 bool retval = false; 280 read_expects* expects = static_cast<read_expects*>(stream->data); 281 expects->callback_called = true; 282 check_data_cb(expects, nread, buf, &retval); 283 if (retval) { 284 stream->data = nullptr; 285 uv_read_stop(stream); 286 } 287} 288 289static read_expects prepare_expects(const char* data, size_t len) { 290 read_expects expectation; 291 expectation.expected = data; 292 expectation.expected_len = len; 293 expectation.pos = 0; 294 expectation.read_expected = false; 295 expectation.callback_called = false; 296 return expectation; 297} 298 299static void fail_callback(uv_stream_t* stream, ssize_t nread, 300 const uv_buf_t* buf) { 301 if (nread < 0) { 302 fprintf(stderr, "IO error: %s\n", uv_strerror(nread)); 303 } else { 304 fprintf(stderr, "Read %zd bytes\n", nread); 305 } 306 ASSERT_TRUE(false); // Shouldn't have been called 307} 308 309static void expect_nothing_on_client() { 310 uv_stream_t* stream = reinterpret_cast<uv_stream_t*>(&client_socket); 311 int err = uv_read_start(stream, buffer_alloc_cb, fail_callback); 312 GTEST_ASSERT_EQ(0, err); 313 for (int i = 0; i < MAX_LOOP_ITERATIONS; i++) 314 uv_run(&loop, UV_RUN_NOWAIT); 315 uv_read_stop(stream); 316} 317 318static void expect_on_client(const char* data, size_t len) { 319 read_expects expectation = prepare_expects(data, len); 320 client_socket.data = ℰ 321 uv_read_start(reinterpret_cast<uv_stream_t*>(&client_socket), 322 buffer_alloc_cb, check_data_cb); 323 SPIN_WHILE(!expectation.read_expected); 324} 325 326static void expect_handshake() { 327 const char UPGRADE_RESPONSE[] = 328 "HTTP/1.1 101 Switching Protocols\r\n" 329 "Upgrade: websocket\r\n" 330 "Connection: Upgrade\r\n" 331 "Sec-WebSocket-Accept: Dt87H1OULVZnSJo/KgMUYI7xPCg=\r\n\r\n"; 332 expect_on_client(UPGRADE_RESPONSE, sizeof(UPGRADE_RESPONSE) - 1); 333} 334 335static void expect_handshake_failure() { 336 const char UPGRADE_RESPONSE[] = 337 "HTTP/1.0 400 Bad Request\r\n" 338 "Content-Type: text/html; charset=UTF-8\r\n\r\n" 339 "WebSockets request was expected\r\n"; 340 expect_on_client(UPGRADE_RESPONSE, sizeof(UPGRADE_RESPONSE) - 1); 341} 342 343static void on_connection(uv_connect_t* connect, int status) { 344 GTEST_ASSERT_EQ(0, status); 345 connect->data = connect; 346} 347 348class InspectorSocketTest : public ::testing::Test { 349 protected: 350 void SetUp() override { 351 connected = false; 352 GTEST_ASSERT_EQ(0, uv_loop_init(&loop)); 353 server = uv_tcp_t(); 354 client_socket = uv_tcp_t(); 355 sockaddr_in addr; 356 uv_tcp_init(&loop, &server); 357 uv_tcp_init(&loop, &client_socket); 358 GTEST_ASSERT_EQ(0, uv_ip4_addr("127.0.0.1", PORT, &addr)); 359 uv_tcp_bind(&server, reinterpret_cast<const struct sockaddr*>(&addr), 0); 360 GTEST_ASSERT_EQ(0, uv_listen(reinterpret_cast<uv_stream_t*>(&server), 361 1, on_new_connection)); 362 uv_connect_t connect; 363 connect.data = nullptr; 364 GTEST_ASSERT_EQ(0, uv_tcp_connect(&connect, &client_socket, 365 reinterpret_cast<const sockaddr*>(&addr), 366 on_connection)); 367 uv_tcp_nodelay(&client_socket, 1); // The buffering messes up the test 368 SPIN_WHILE(!connect.data || !connected); 369 really_close(reinterpret_cast<uv_handle_t*>(&server)); 370 } 371 372 void TearDown() override { 373 really_close(reinterpret_cast<uv_handle_t*>(&client_socket)); 374 SPIN_WHILE(delegate != nullptr); 375 const int err = uv_loop_close(&loop); 376 if (err != 0) { 377 uv_print_all_handles(&loop, stderr); 378 } 379 EXPECT_EQ(0, err); 380 } 381}; 382 383TEST_F(InspectorSocketTest, ReadsAndWritesInspectorMessage) { 384 ASSERT_TRUE(connected); 385 ASSERT_FALSE(delegate->inspector_ready); 386 do_write(const_cast<char*>(HANDSHAKE_REQ), sizeof(HANDSHAKE_REQ) - 1); 387 SPIN_WHILE(!delegate->inspector_ready); 388 expect_handshake(); 389 390 // 2. Brief exchange 391 const char SERVER_MESSAGE[] = "abcd"; 392 const char CLIENT_FRAME[] = {'\x81', '\x04', 'a', 'b', 'c', 'd'}; 393 delegate->Write(SERVER_MESSAGE, sizeof(SERVER_MESSAGE) - 1); 394 expect_on_client(CLIENT_FRAME, sizeof(CLIENT_FRAME)); 395 396 const char SERVER_FRAME[] = {'\x81', '\x84', '\x7F', '\xC2', '\x66', 397 '\x31', '\x4E', '\xF0', '\x55', '\x05'}; 398 const char CLIENT_MESSAGE[] = "1234"; 399 do_write(SERVER_FRAME, sizeof(SERVER_FRAME)); 400 delegate->ExpectData(CLIENT_MESSAGE, sizeof(CLIENT_MESSAGE) - 1); 401 402 // 3. Close 403 const char CLIENT_CLOSE_FRAME[] = {'\x88', '\x80', '\x2D', 404 '\x0E', '\x1E', '\xFA'}; 405 const char SERVER_CLOSE_FRAME[] = {'\x88', '\x00'}; 406 do_write(CLIENT_CLOSE_FRAME, sizeof(CLIENT_CLOSE_FRAME)); 407 expect_on_client(SERVER_CLOSE_FRAME, sizeof(SERVER_CLOSE_FRAME)); 408 GTEST_ASSERT_EQ(0, uv_is_active( 409 reinterpret_cast<uv_handle_t*>(&client_socket))); 410} 411 412TEST_F(InspectorSocketTest, BufferEdgeCases) { 413 do_write(const_cast<char*>(HANDSHAKE_REQ), sizeof(HANDSHAKE_REQ) - 1); 414 expect_handshake(); 415 416 const char MULTIPLE_REQUESTS[] = { 417 '\x81', '\xCB', '\x76', '\xCA', '\x06', '\x0C', '\x0D', '\xE8', '\x6F', 418 '\x68', '\x54', '\xF0', '\x37', '\x3E', '\x5A', '\xE8', '\x6B', '\x69', 419 '\x02', '\xA2', '\x69', '\x68', '\x54', '\xF0', '\x24', '\x5B', '\x19', 420 '\xB8', '\x6D', '\x69', '\x04', '\xE4', '\x75', '\x69', '\x02', '\x8B', 421 '\x73', '\x78', '\x19', '\xA9', '\x69', '\x62', '\x18', '\xAF', '\x65', 422 '\x78', '\x22', '\xA5', '\x51', '\x63', '\x04', '\xA1', '\x63', '\x7E', 423 '\x05', '\xE8', '\x2A', '\x2E', '\x06', '\xAB', '\x74', '\x6D', '\x1B', 424 '\xB9', '\x24', '\x36', '\x0D', '\xE8', '\x70', '\x6D', '\x1A', '\xBF', 425 '\x63', '\x2E', '\x4C', '\xBE', '\x74', '\x79', '\x13', '\xB7', '\x7B', 426 '\x81', '\xA2', '\xFC', '\x9E', '\x0D', '\x15', '\x87', '\xBC', '\x64', 427 '\x71', '\xDE', '\xA4', '\x3C', '\x26', '\xD0', '\xBC', '\x60', '\x70', 428 '\x88', '\xF6', '\x62', '\x71', '\xDE', '\xA4', '\x2F', '\x42', '\x93', 429 '\xEC', '\x66', '\x70', '\x8E', '\xB0', '\x68', '\x7B', '\x9D', '\xFC', 430 '\x61', '\x70', '\xDE', '\xE3', '\x81', '\xA4', '\x4E', '\x37', '\xB0', 431 '\x22', '\x35', '\x15', '\xD9', '\x46', '\x6C', '\x0D', '\x81', '\x16', 432 '\x62', '\x15', '\xDD', '\x47', '\x3A', '\x5F', '\xDF', '\x46', '\x6C', 433 '\x0D', '\x92', '\x72', '\x3C', '\x58', '\xD6', '\x4B', '\x22', '\x52', 434 '\xC2', '\x0C', '\x2B', '\x59', '\xD1', '\x40', '\x22', '\x52', '\x92', 435 '\x5F', '\x81', '\xCB', '\xCD', '\xF0', '\x30', '\xC5', '\xB6', '\xD2', 436 '\x59', '\xA1', '\xEF', '\xCA', '\x01', '\xF0', '\xE1', '\xD2', '\x5D', 437 '\xA0', '\xB9', '\x98', '\x5F', '\xA1', '\xEF', '\xCA', '\x12', '\x95', 438 '\xBF', '\x9F', '\x56', '\xAC', '\xA1', '\x95', '\x42', '\xEB', '\xBE', 439 '\x95', '\x44', '\x96', '\xAC', '\x9D', '\x40', '\xA9', '\xA4', '\x9E', 440 '\x57', '\x8C', '\xA3', '\x84', '\x55', '\xB7', '\xBB', '\x91', '\x5C', 441 '\xE7', '\xE1', '\xD2', '\x40', '\xA4', '\xBF', '\x91', '\x5D', '\xB6', 442 '\xEF', '\xCA', '\x4B', '\xE7', '\xA4', '\x9E', '\x44', '\xA0', '\xBF', 443 '\x86', '\x51', '\xA9', '\xEF', '\xCA', '\x01', '\xF5', '\xFD', '\x8D', 444 '\x4D', '\x81', '\xA9', '\x74', '\x6B', '\x72', '\x43', '\x0F', '\x49', 445 '\x1B', '\x27', '\x56', '\x51', '\x43', '\x75', '\x58', '\x49', '\x1F', 446 '\x26', '\x00', '\x03', '\x1D', '\x27', '\x56', '\x51', '\x50', '\x10', 447 '\x11', '\x19', '\x04', '\x2A', '\x17', '\x0E', '\x25', '\x2C', '\x06', 448 '\x00', '\x17', '\x31', '\x5A', '\x0E', '\x1C', '\x22', '\x16', '\x07', 449 '\x17', '\x61', '\x09', '\x81', '\xB8', '\x7C', '\x1A', '\xEA', '\xEB', 450 '\x07', '\x38', '\x83', '\x8F', '\x5E', '\x20', '\xDB', '\xDC', '\x50', 451 '\x38', '\x87', '\x8E', '\x08', '\x72', '\x85', '\x8F', '\x5E', '\x20', 452 '\xC8', '\xA5', '\x19', '\x6E', '\x9D', '\x84', '\x0E', '\x71', '\xC4', 453 '\x88', '\x1D', '\x74', '\xAF', '\x86', '\x09', '\x76', '\x8B', '\x9F', 454 '\x19', '\x54', '\x8F', '\x9F', '\x0B', '\x75', '\x98', '\x80', '\x3F', 455 '\x75', '\x84', '\x8F', '\x15', '\x6E', '\x83', '\x84', '\x12', '\x69', 456 '\xC8', '\x96'}; 457 458 const char EXPECT[] = { 459 "{\"id\":12,\"method\":\"Worker.setAutoconnectToWorkers\"," 460 "\"params\":{\"value\":true}}" 461 "{\"id\":13,\"method\":\"Worker.enable\"}" 462 "{\"id\":14,\"method\":\"Profiler.enable\"}" 463 "{\"id\":15,\"method\":\"Profiler.setSamplingInterval\"," 464 "\"params\":{\"interval\":100}}" 465 "{\"id\":16,\"method\":\"ServiceWorker.enable\"}" 466 "{\"id\":17,\"method\":\"Network.canEmulateNetworkConditions\"}"}; 467 468 do_write(MULTIPLE_REQUESTS, sizeof(MULTIPLE_REQUESTS)); 469 delegate->ExpectData(EXPECT, sizeof(EXPECT) - 1); 470} 471 472TEST_F(InspectorSocketTest, AcceptsRequestInSeveralWrites) { 473 ASSERT_TRUE(connected); 474 ASSERT_FALSE(delegate->inspector_ready); 475 // Specifically, break up the request in the "Sec-WebSocket-Key" header name 476 // and value 477 const int write1 = 95; 478 const int write2 = 5; 479 const int write3 = sizeof(HANDSHAKE_REQ) - write1 - write2 - 1; 480 do_write(const_cast<char*>(HANDSHAKE_REQ), write1); 481 ASSERT_FALSE(delegate->inspector_ready); 482 do_write(const_cast<char*>(HANDSHAKE_REQ) + write1, write2); 483 ASSERT_FALSE(delegate->inspector_ready); 484 do_write(const_cast<char*>(HANDSHAKE_REQ) + write1 + write2, write3); 485 SPIN_WHILE(!delegate->inspector_ready); 486 expect_handshake(); 487 GTEST_ASSERT_EQ(uv_is_active(reinterpret_cast<uv_handle_t*>(&client_socket)), 488 0); 489} 490 491TEST_F(InspectorSocketTest, ExtraTextBeforeRequest) { 492 delegate->last_event = kInspectorHandshakeUpgraded; 493 char UNCOOL_BRO[] = "Text before the first req, shouldn't be her\r\n"; 494 do_write(const_cast<char*>(UNCOOL_BRO), sizeof(UNCOOL_BRO) - 1); 495 expect_handshake_failure(); 496 GTEST_ASSERT_EQ(nullptr, delegate); 497} 498 499TEST_F(InspectorSocketTest, RequestWithoutKey) { 500 const char BROKEN_REQUEST[] = "GET / HTTP/1.1\r\n" 501 "Host: localhost:9229\r\n" 502 "Upgrade: websocket\r\n" 503 "Connection: Upgrade\r\n" 504 "Sec-WebSocket-Version: 13\r\n\r\n"; 505 506 do_write(const_cast<char*>(BROKEN_REQUEST), sizeof(BROKEN_REQUEST) - 1); 507 expect_handshake_failure(); 508} 509 510TEST_F(InspectorSocketTest, KillsConnectionOnProtocolViolation) { 511 ASSERT_TRUE(connected); 512 ASSERT_FALSE(delegate->inspector_ready); 513 do_write(const_cast<char*>(HANDSHAKE_REQ), sizeof(HANDSHAKE_REQ) - 1); 514 SPIN_WHILE(!delegate->inspector_ready); 515 ASSERT_TRUE(delegate->inspector_ready); 516 expect_handshake(); 517 const char SERVER_FRAME[] = "I'm not a good WS frame. Nope!"; 518 do_write(SERVER_FRAME, sizeof(SERVER_FRAME)); 519 SPIN_WHILE(delegate != nullptr); 520 GTEST_ASSERT_EQ(uv_is_active(reinterpret_cast<uv_handle_t*>(&client_socket)), 521 0); 522} 523 524TEST_F(InspectorSocketTest, CanStopReadingFromInspector) { 525 ASSERT_TRUE(connected); 526 ASSERT_FALSE(delegate->inspector_ready); 527 do_write(const_cast<char*>(HANDSHAKE_REQ), sizeof(HANDSHAKE_REQ) - 1); 528 expect_handshake(); 529 ASSERT_TRUE(delegate->inspector_ready); 530 531 // 2. Brief exchange 532 const char SERVER_FRAME[] = {'\x81', '\x84', '\x7F', '\xC2', '\x66', 533 '\x31', '\x4E', '\xF0', '\x55', '\x05'}; 534 const char CLIENT_MESSAGE[] = "1234"; 535 do_write(SERVER_FRAME, sizeof(SERVER_FRAME)); 536 delegate->ExpectData(CLIENT_MESSAGE, sizeof(CLIENT_MESSAGE) - 1); 537 538 do_write(SERVER_FRAME, sizeof(SERVER_FRAME)); 539 GTEST_ASSERT_EQ(uv_is_active( 540 reinterpret_cast<uv_handle_t*>(&client_socket)), 0); 541} 542 543TEST_F(InspectorSocketTest, CloseDoesNotNotifyReadCallback) { 544 do_write(const_cast<char*>(HANDSHAKE_REQ), sizeof(HANDSHAKE_REQ) - 1); 545 expect_handshake(); 546 547 delegate->Close(); 548 char CLOSE_FRAME[] = {'\x88', '\x00'}; 549 expect_on_client(CLOSE_FRAME, sizeof(CLOSE_FRAME)); 550 const char CLIENT_CLOSE_FRAME[] = {'\x88', '\x80', '\x2D', 551 '\x0E', '\x1E', '\xFA'}; 552 delegate->FailOnWsFrame(); 553 do_write(CLIENT_CLOSE_FRAME, sizeof(CLIENT_CLOSE_FRAME)); 554 SPIN_WHILE(delegate != nullptr); 555} 556 557TEST_F(InspectorSocketTest, CloseWorksWithoutReadEnabled) { 558 do_write(const_cast<char*>(HANDSHAKE_REQ), sizeof(HANDSHAKE_REQ) - 1); 559 expect_handshake(); 560 delegate->Close(); 561 char CLOSE_FRAME[] = {'\x88', '\x00'}; 562 expect_on_client(CLOSE_FRAME, sizeof(CLOSE_FRAME)); 563 const char CLIENT_CLOSE_FRAME[] = {'\x88', '\x80', '\x2D', 564 '\x0E', '\x1E', '\xFA'}; 565 do_write(CLIENT_CLOSE_FRAME, sizeof(CLIENT_CLOSE_FRAME)); 566} 567 568// Make sure buffering works 569static void send_in_chunks(const char* data, size_t len) { 570 const int step = 7; 571 size_t i = 0; 572 // Do not send it all at once - test the buffering! 573 for (; i < len - step; i += step) { 574 do_write(data + i, step); 575 } 576 if (i < len) { 577 do_write(data + i, len - i); 578 } 579} 580 581static const char TEST_SUCCESS[] = "Test Success\n\n"; 582static int ReportsHttpGet_eventsCount = 0; 583 584static void ReportsHttpGet_handshake(enum inspector_handshake_event state, 585 const std::string& path, bool* cont) { 586 *cont = true; 587 enum inspector_handshake_event expected_state = kInspectorHandshakeHttpGet; 588 std::string expected_path; 589 switch (delegate->handshake_events) { 590 case 1: 591 expected_path = "/some/path"; 592 break; 593 case 2: 594 expected_path = "/respond/withtext"; 595 delegate->Write(TEST_SUCCESS, sizeof(TEST_SUCCESS) - 1); 596 break; 597 case 3: 598 expected_path = "/some/path2"; 599 break; 600 case 4: 601 expected_path = "/close"; 602 *cont = false; 603 break; 604 default: 605 ASSERT_TRUE(false); 606 } 607 EXPECT_EQ(expected_state, state); 608 EXPECT_EQ(expected_path, path); 609 ReportsHttpGet_eventsCount = delegate->handshake_events; 610} 611 612TEST_F(InspectorSocketTest, ReportsHttpGet) { 613 delegate->SetDelegate(ReportsHttpGet_handshake); 614 615 const char GET_REQ[] = "GET /some/path HTTP/1.1\r\n" 616 "Host: localhost:9229\r\n" 617 "Sec-WebSocket-Key: aaa==\r\n" 618 "Sec-WebSocket-Version: 13\r\n\r\n"; 619 send_in_chunks(GET_REQ, sizeof(GET_REQ) - 1); 620 621 expect_nothing_on_client(); 622 const char WRITE_REQUEST[] = "GET /respond/withtext HTTP/1.1\r\n" 623 "Host: localhost:9229\r\n\r\n"; 624 send_in_chunks(WRITE_REQUEST, sizeof(WRITE_REQUEST) - 1); 625 626 expect_on_client(TEST_SUCCESS, sizeof(TEST_SUCCESS) - 1); 627 const char GET_REQS[] = "GET /some/path2 HTTP/1.1\r\n" 628 "Host: localhost:9229\r\n" 629 "Sec-WebSocket-Key: aaa==\r\n" 630 "Sec-WebSocket-Version: 13\r\n\r\n" 631 "GET /close HTTP/1.1\r\n" 632 "Host: localhost:9229\r\n" 633 "Sec-WebSocket-Key: aaa==\r\n" 634 "Sec-WebSocket-Version: 13\r\n\r\n"; 635 send_in_chunks(GET_REQS, sizeof(GET_REQS) - 1); 636 expect_handshake_failure(); 637 EXPECT_EQ(4, ReportsHttpGet_eventsCount); 638 EXPECT_EQ(nullptr, delegate); 639} 640 641static int HandshakeCanBeCanceled_eventCount = 0; 642 643static 644void HandshakeCanBeCanceled_handshake(enum inspector_handshake_event state, 645 const std::string& path, bool* cont) { 646 switch (delegate->handshake_events - 1) { 647 case 0: 648 EXPECT_EQ(kInspectorHandshakeUpgraded, state); 649 EXPECT_EQ("/ws/path", path); 650 break; 651 default: 652 EXPECT_TRUE(false); 653 break; 654 } 655 *cont = false; 656 HandshakeCanBeCanceled_eventCount = delegate->handshake_events; 657} 658 659TEST_F(InspectorSocketTest, HandshakeCanBeCanceled) { 660 delegate->SetDelegate(HandshakeCanBeCanceled_handshake); 661 662 do_write(const_cast<char*>(HANDSHAKE_REQ), sizeof(HANDSHAKE_REQ) - 1); 663 664 expect_handshake_failure(); 665 EXPECT_EQ(1, HandshakeCanBeCanceled_eventCount); 666 EXPECT_EQ(nullptr, delegate); 667} 668 669static void GetThenHandshake_handshake(enum inspector_handshake_event state, 670 const std::string& path, bool* cont) { 671 *cont = true; 672 std::string expected_path = "/ws/path"; 673 switch (delegate->handshake_events - 1) { 674 case 0: 675 EXPECT_EQ(kInspectorHandshakeHttpGet, state); 676 expected_path = "/respond/withtext"; 677 delegate->Write(TEST_SUCCESS, sizeof(TEST_SUCCESS) - 1); 678 break; 679 case 1: 680 EXPECT_EQ(kInspectorHandshakeUpgraded, state); 681 break; 682 default: 683 EXPECT_TRUE(false); 684 break; 685 } 686 EXPECT_EQ(expected_path, path); 687} 688 689TEST_F(InspectorSocketTest, GetThenHandshake) { 690 delegate->SetDelegate(GetThenHandshake_handshake); 691 const char WRITE_REQUEST[] = "GET /respond/withtext HTTP/1.1\r\n" 692 "Host: localhost:9229\r\n\r\n"; 693 send_in_chunks(WRITE_REQUEST, sizeof(WRITE_REQUEST) - 1); 694 695 expect_on_client(TEST_SUCCESS, sizeof(TEST_SUCCESS) - 1); 696 697 do_write(const_cast<char*>(HANDSHAKE_REQ), sizeof(HANDSHAKE_REQ) - 1); 698 expect_handshake(); 699 EXPECT_EQ(2, delegate->handshake_events); 700} 701 702TEST_F(InspectorSocketTest, WriteBeforeHandshake) { 703 const char MESSAGE1[] = "Message 1"; 704 const char MESSAGE2[] = "Message 2"; 705 const char EXPECTED[] = "Message 1Message 2"; 706 707 delegate->Write(MESSAGE1, sizeof(MESSAGE1) - 1); 708 delegate->Write(MESSAGE2, sizeof(MESSAGE2) - 1); 709 expect_on_client(EXPECTED, sizeof(EXPECTED) - 1); 710 really_close(reinterpret_cast<uv_handle_t*>(&client_socket)); 711 SPIN_WHILE(delegate != nullptr); 712} 713 714TEST_F(InspectorSocketTest, CleanupSocketAfterEOF) { 715 do_write(const_cast<char*>(HANDSHAKE_REQ), sizeof(HANDSHAKE_REQ) - 1); 716 expect_handshake(); 717 718 for (int i = 0; i < MAX_LOOP_ITERATIONS; ++i) { 719 uv_run(&loop, UV_RUN_NOWAIT); 720 } 721 722 uv_close(reinterpret_cast<uv_handle_t*>(&client_socket), nullptr); 723 SPIN_WHILE(delegate != nullptr); 724} 725 726TEST_F(InspectorSocketTest, EOFBeforeHandshake) { 727 const char MESSAGE[] = "We'll send EOF afterwards"; 728 delegate->Write(MESSAGE, sizeof(MESSAGE) - 1); 729 expect_on_client(MESSAGE, sizeof(MESSAGE) - 1); 730 uv_close(reinterpret_cast<uv_handle_t*>(&client_socket), nullptr); 731 SPIN_WHILE(delegate != nullptr); 732} 733 734static void fill_message(std::string* buffer) { 735 for (size_t i = 0; i < buffer->size(); i += 1) { 736 (*buffer)[i] = 'a' + (i % ('z' - 'a')); 737 } 738} 739 740static void mask_message(const std::string& message, 741 char* buffer, const char mask[]) { 742 const size_t mask_len = 4; 743 for (size_t i = 0; i < message.size(); i += 1) { 744 buffer[i] = message[i] ^ mask[i % mask_len]; 745 } 746} 747 748TEST_F(InspectorSocketTest, Send1Mb) { 749 ASSERT_TRUE(connected); 750 ASSERT_FALSE(delegate->inspector_ready); 751 do_write(const_cast<char*>(HANDSHAKE_REQ), sizeof(HANDSHAKE_REQ) - 1); 752 SPIN_WHILE(!delegate->inspector_ready); 753 expect_handshake(); 754 755 // 2. Brief exchange 756 std::string message(1000000, '\0'); 757 fill_message(&message); 758 759 // 1000000 is 0xF4240 hex 760 const char EXPECTED_FRAME_HEADER[] = { 761 '\x81', '\x7f', '\x00', '\x00', '\x00', '\x00', '\x00', '\x0F', 762 '\x42', '\x40' 763 }; 764 std::string expected(EXPECTED_FRAME_HEADER, sizeof(EXPECTED_FRAME_HEADER)); 765 expected.append(message); 766 767 delegate->Write(message.data(), message.size()); 768 expect_on_client(expected.data(), expected.size()); 769 770 char MASK[4] = {'W', 'h', 'O', 'a'}; 771 772 const char FRAME_TO_SERVER_HEADER[] = { 773 '\x81', '\xff', '\x00', '\x00', '\x00', '\x00', '\x00', '\x0F', 774 '\x42', '\x40', MASK[0], MASK[1], MASK[2], MASK[3] 775 }; 776 777 std::string outgoing(FRAME_TO_SERVER_HEADER, sizeof(FRAME_TO_SERVER_HEADER)); 778 outgoing.resize(outgoing.size() + message.size()); 779 mask_message(message, &outgoing[sizeof(FRAME_TO_SERVER_HEADER)], MASK); 780 781 do_write(outgoing.data(), outgoing.size()); 782 delegate->ExpectData(message.data(), message.size()); 783 784 // 3. Close 785 const char CLIENT_CLOSE_FRAME[] = {'\x88', '\x80', '\x2D', 786 '\x0E', '\x1E', '\xFA'}; 787 do_write(CLIENT_CLOSE_FRAME, sizeof(CLIENT_CLOSE_FRAME)); 788 expect_on_client(SERVER_CLOSE_FRAME, sizeof(SERVER_CLOSE_FRAME)); 789 GTEST_ASSERT_EQ(0, uv_is_active( 790 reinterpret_cast<uv_handle_t*>(&client_socket))); 791} 792 793TEST_F(InspectorSocketTest, ErrorCleansUpTheSocket) { 794 do_write(const_cast<char*>(HANDSHAKE_REQ), sizeof(HANDSHAKE_REQ) - 1); 795 expect_handshake(); 796 const char NOT_A_GOOD_FRAME[] = {'H', 'e', 'l', 'l', 'o'}; 797 do_write(NOT_A_GOOD_FRAME, sizeof(NOT_A_GOOD_FRAME)); 798 SPIN_WHILE(delegate != nullptr); 799} 800 801TEST_F(InspectorSocketTest, NoCloseResponseFromClient) { 802 ASSERT_TRUE(connected); 803 ASSERT_FALSE(delegate->inspector_ready); 804 do_write(const_cast<char*>(HANDSHAKE_REQ), sizeof(HANDSHAKE_REQ) - 1); 805 SPIN_WHILE(!delegate->inspector_ready); 806 expect_handshake(); 807 808 // 2. Brief exchange 809 const char SERVER_MESSAGE[] = "abcd"; 810 const char CLIENT_FRAME[] = {'\x81', '\x04', 'a', 'b', 'c', 'd'}; 811 delegate->Write(SERVER_MESSAGE, sizeof(SERVER_MESSAGE) - 1); 812 expect_on_client(CLIENT_FRAME, sizeof(CLIENT_FRAME)); 813 814 delegate->Close(); 815 expect_on_client(SERVER_CLOSE_FRAME, sizeof(SERVER_CLOSE_FRAME)); 816 uv_close(reinterpret_cast<uv_handle_t*>(&client_socket), nullptr); 817 GTEST_ASSERT_EQ(0, uv_is_active( 818 reinterpret_cast<uv_handle_t*>(&client_socket))); 819 delegate->WaitForDispose(); 820} 821 822static bool delegate_called = false; 823 824void shouldnt_be_called(enum inspector_handshake_event state, 825 const std::string& path, bool* cont) { 826 delegate_called = true; 827} 828 829void expect_failure_no_delegate(const std::string& request) { 830 delegate->SetDelegate(shouldnt_be_called); 831 delegate_called = false; 832 send_in_chunks(request.c_str(), request.length()); 833 expect_handshake_failure(); 834 SPIN_WHILE(delegate != nullptr); 835 ASSERT_FALSE(delegate_called); 836} 837 838TEST_F(InspectorSocketTest, HostCheckedForGET) { 839 const char GET_REQUEST[] = "GET /respond/withtext HTTP/1.1\r\n" 840 "Host: notlocalhost:9229\r\n\r\n"; 841 expect_failure_no_delegate(GET_REQUEST); 842} 843 844TEST_F(InspectorSocketTest, HostCheckedForUPGRADE) { 845 const char UPGRADE_REQUEST[] = "GET /ws/path HTTP/1.1\r\n" 846 "Host: nonlocalhost:9229\r\n" 847 "Upgrade: websocket\r\n" 848 "Connection: Upgrade\r\n" 849 "Sec-WebSocket-Key: aaa==\r\n" 850 "Sec-WebSocket-Version: 13\r\n\r\n"; 851 expect_failure_no_delegate(UPGRADE_REQUEST); 852} 853 854TEST_F(InspectorSocketTest, HostIPChecked) { 855 const std::string INVALID_HOST_IP_REQUEST = "GET /json HTTP/1.1\r\n" 856 "Host: 10.0.2.555:9229\r\n\r\n"; 857 send_in_chunks(INVALID_HOST_IP_REQUEST.c_str(), 858 INVALID_HOST_IP_REQUEST.length()); 859 expect_handshake_failure(); 860} 861 862TEST_F(InspectorSocketTest, HostNegativeIPChecked) { 863 const std::string INVALID_HOST_IP_REQUEST = "GET /json HTTP/1.1\r\n" 864 "Host: 10.0.-23.255:9229\r\n\r\n"; 865 send_in_chunks(INVALID_HOST_IP_REQUEST.c_str(), 866 INVALID_HOST_IP_REQUEST.length()); 867 expect_handshake_failure(); 868} 869 870TEST_F(InspectorSocketTest, HostIpOctetOutOfIntRangeChecked) { 871 const std::string INVALID_HOST_IP_REQUEST = 872 "GET /json HTTP/1.1\r\n" 873 "Host: 127.0.0.4294967296:9229\r\n\r\n"; 874 send_in_chunks(INVALID_HOST_IP_REQUEST.c_str(), 875 INVALID_HOST_IP_REQUEST.length()); 876 expect_handshake_failure(); 877} 878 879TEST_F(InspectorSocketTest, HostIpOctetFarOutOfIntRangeChecked) { 880 const std::string INVALID_HOST_IP_REQUEST = 881 "GET /json HTTP/1.1\r\n" 882 "Host: 127.0.0.18446744073709552000:9229\r\n\r\n"; 883 send_in_chunks(INVALID_HOST_IP_REQUEST.c_str(), 884 INVALID_HOST_IP_REQUEST.length()); 885 expect_handshake_failure(); 886} 887 888TEST_F(InspectorSocketTest, HostIpEmptyOctetStartChecked) { 889 const std::string INVALID_HOST_IP_REQUEST = "GET /json HTTP/1.1\r\n" 890 "Host: .0.0.1:9229\r\n\r\n"; 891 send_in_chunks(INVALID_HOST_IP_REQUEST.c_str(), 892 INVALID_HOST_IP_REQUEST.length()); 893 expect_handshake_failure(); 894} 895 896TEST_F(InspectorSocketTest, HostIpEmptyOctetMidChecked) { 897 const std::string INVALID_HOST_IP_REQUEST = "GET /json HTTP/1.1\r\n" 898 "Host: 127..0.1:9229\r\n\r\n"; 899 send_in_chunks(INVALID_HOST_IP_REQUEST.c_str(), 900 INVALID_HOST_IP_REQUEST.length()); 901 expect_handshake_failure(); 902} 903 904TEST_F(InspectorSocketTest, HostIpEmptyOctetEndChecked) { 905 const std::string INVALID_HOST_IP_REQUEST = "GET /json HTTP/1.1\r\n" 906 "Host: 127.0.0.:9229\r\n\r\n"; 907 send_in_chunks(INVALID_HOST_IP_REQUEST.c_str(), 908 INVALID_HOST_IP_REQUEST.length()); 909 expect_handshake_failure(); 910} 911 912TEST_F(InspectorSocketTest, HostIpTooFewOctetsChecked) { 913 const std::string INVALID_HOST_IP_REQUEST = "GET /json HTTP/1.1\r\n" 914 "Host: 127.0.1:9229\r\n\r\n"; 915 send_in_chunks(INVALID_HOST_IP_REQUEST.c_str(), 916 INVALID_HOST_IP_REQUEST.length()); 917 expect_handshake_failure(); 918} 919 920TEST_F(InspectorSocketTest, HostIpTooManyOctetsChecked) { 921 const std::string INVALID_HOST_IP_REQUEST = "GET /json HTTP/1.1\r\n" 922 "Host: 127.0.0.0.1:9229\r\n\r\n"; 923 send_in_chunks(INVALID_HOST_IP_REQUEST.c_str(), 924 INVALID_HOST_IP_REQUEST.length()); 925 expect_handshake_failure(); 926} 927 928TEST_F(InspectorSocketTest, HostIpInvalidOctalOctetStartChecked) { 929 const std::string INVALID_HOST_IP_REQUEST = "GET /json HTTP/1.1\r\n" 930 "Host: 08.1.1.1:9229\r\n\r\n"; 931 send_in_chunks(INVALID_HOST_IP_REQUEST.c_str(), 932 INVALID_HOST_IP_REQUEST.length()); 933 expect_handshake_failure(); 934} 935 936TEST_F(InspectorSocketTest, HostIpInvalidOctalOctetMidChecked) { 937 const std::string INVALID_HOST_IP_REQUEST = "GET /json HTTP/1.1\r\n" 938 "Host: 1.09.1.1:9229\r\n\r\n"; 939 send_in_chunks(INVALID_HOST_IP_REQUEST.c_str(), 940 INVALID_HOST_IP_REQUEST.length()); 941 expect_handshake_failure(); 942} 943 944TEST_F(InspectorSocketTest, HostIpInvalidOctalOctetEndChecked) { 945 const std::string INVALID_HOST_IP_REQUEST = "GET /json HTTP/1.1\r\n" 946 "Host: 1.1.1.009:9229\r\n\r\n"; 947 send_in_chunks(INVALID_HOST_IP_REQUEST.c_str(), 948 INVALID_HOST_IP_REQUEST.length()); 949 expect_handshake_failure(); 950} 951 952TEST_F(InspectorSocketTest, HostIpLeadingZeroStartChecked) { 953 const std::string INVALID_HOST_IP_REQUEST = "GET /json HTTP/1.1\r\n" 954 "Host: 01.1.1.1:9229\r\n\r\n"; 955 send_in_chunks(INVALID_HOST_IP_REQUEST.c_str(), 956 INVALID_HOST_IP_REQUEST.length()); 957 expect_handshake_failure(); 958} 959 960TEST_F(InspectorSocketTest, HostIpLeadingZeroMidChecked) { 961 const std::string INVALID_HOST_IP_REQUEST = "GET /json HTTP/1.1\r\n" 962 "Host: 1.1.001.1:9229\r\n\r\n"; 963 send_in_chunks(INVALID_HOST_IP_REQUEST.c_str(), 964 INVALID_HOST_IP_REQUEST.length()); 965 expect_handshake_failure(); 966} 967 968TEST_F(InspectorSocketTest, HostIpLeadingZeroEndChecked) { 969 const std::string INVALID_HOST_IP_REQUEST = "GET /json HTTP/1.1\r\n" 970 "Host: 1.1.1.01:9229\r\n\r\n"; 971 send_in_chunks(INVALID_HOST_IP_REQUEST.c_str(), 972 INVALID_HOST_IP_REQUEST.length()); 973 expect_handshake_failure(); 974} 975 976TEST_F(InspectorSocketTest, HostIPNonRoutable) { 977 const std::string INVALID_HOST_IP_REQUEST = "GET /json HTTP/1.1\r\n" 978 "Host: 0.0.0.0:9229\r\n\r\n"; 979 send_in_chunks(INVALID_HOST_IP_REQUEST.c_str(), 980 INVALID_HOST_IP_REQUEST.length()); 981 expect_handshake_failure(); 982} 983 984TEST_F(InspectorSocketTest, HostIPv6NonRoutable) { 985 const std::string INVALID_HOST_IP_REQUEST = "GET /json HTTP/1.1\r\n" 986 "Host: [::]:9229\r\n\r\n"; 987 send_in_chunks(INVALID_HOST_IP_REQUEST.c_str(), 988 INVALID_HOST_IP_REQUEST.length()); 989 expect_handshake_failure(); 990} 991 992TEST_F(InspectorSocketTest, HostIPv6NonRoutableDual) { 993 const std::string INVALID_HOST_IP_REQUEST = "GET /json HTTP/1.1\r\n" 994 "Host: [::0.0.0.0]:9229\r\n\r\n"; 995 send_in_chunks(INVALID_HOST_IP_REQUEST.c_str(), 996 INVALID_HOST_IP_REQUEST.length()); 997 expect_handshake_failure(); 998} 999 1000TEST_F(InspectorSocketTest, HostIPv4InSquareBrackets) { 1001 const std::string INVALID_HOST_IP_REQUEST = "GET /json HTTP/1.1\r\n" 1002 "Host: [127.0.0.1]:9229\r\n\r\n"; 1003 send_in_chunks(INVALID_HOST_IP_REQUEST.c_str(), 1004 INVALID_HOST_IP_REQUEST.length()); 1005 expect_handshake_failure(); 1006} 1007 1008TEST_F(InspectorSocketTest, HostIPv6InvalidAbbreviation) { 1009 const std::string INVALID_HOST_IP_REQUEST = "GET /json HTTP/1.1\r\n" 1010 "Host: [:::1]:9229\r\n\r\n"; 1011 send_in_chunks(INVALID_HOST_IP_REQUEST.c_str(), 1012 INVALID_HOST_IP_REQUEST.length()); 1013 expect_handshake_failure(); 1014} 1015 1016} // anonymous namespace 1017