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 = &expectation;
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