GCC Code Coverage Report
Directory: ./ Exec Total Coverage
File: inspector_socket.cc Lines: 354 388 91.2 %
Date: 2022-09-25 04:23:55 Branches: 132 183 72.1 %

Line Branch Exec Source
1
#include "inspector_socket.h"
2
#include "llhttp.h"
3
4
#include "base64-inl.h"
5
#include "util-inl.h"
6
7
#include "openssl/sha.h"  // Sha-1 hash
8
9
#include <cstring>
10
#include <map>
11
12
#define ACCEPT_KEY_LENGTH base64_encoded_size(20)
13
14
#define DUMP_READS 0
15
#define DUMP_WRITES 0
16
17
namespace node {
18
namespace inspector {
19
20
class TcpHolder {
21
 public:
22
  static void DisconnectAndDispose(TcpHolder* holder);
23
  using Pointer = DeleteFnPtr<TcpHolder, DisconnectAndDispose>;
24
25
  static Pointer Accept(uv_stream_t* server,
26
                        InspectorSocket::DelegatePointer delegate);
27
  void SetHandler(ProtocolHandler* handler);
28
  int WriteRaw(const std::vector<char>& buffer, uv_write_cb write_cb);
29
  uv_tcp_t* tcp() {
30
    return &tcp_;
31
  }
32
  InspectorSocket::Delegate* delegate();
33
34
 private:
35
541
  static TcpHolder* From(void* handle) {
36
541
    return node::ContainerOf(&TcpHolder::tcp_,
37
541
                             reinterpret_cast<uv_tcp_t*>(handle));
38
  }
39
  static void OnClosed(uv_handle_t* handle);
40
  static void OnDataReceivedCb(uv_stream_t* stream, ssize_t nread,
41
                               const uv_buf_t* buf);
42
  explicit TcpHolder(InspectorSocket::DelegatePointer delegate);
43
89
  ~TcpHolder() = default;
44
  void ReclaimUvBuf(const uv_buf_t* buf, ssize_t read);
45
46
  uv_tcp_t tcp_;
47
  const InspectorSocket::DelegatePointer delegate_;
48
  ProtocolHandler* handler_;
49
  std::vector<char> buffer;
50
};
51
52
53
class ProtocolHandler {
54
 public:
55
  ProtocolHandler(InspectorSocket* inspector, TcpHolder::Pointer tcp);
56
57
  virtual void AcceptUpgrade(const std::string& accept_key) = 0;
58
  virtual void OnData(std::vector<char>* data) = 0;
59
  virtual void OnEof() = 0;
60
  virtual void Write(const std::vector<char> data) = 0;
61
  virtual void CancelHandshake() = 0;
62
63
  std::string GetHost() const;
64
65
21
  InspectorSocket* inspector() {
66
21
    return inspector_;
67
  }
68
  virtual void Shutdown() = 0;
69
70
 protected:
71
252
  virtual ~ProtocolHandler() = default;
72
  int WriteRaw(const std::vector<char>& buffer, uv_write_cb write_cb);
73
  InspectorSocket::Delegate* delegate();
74
75
  InspectorSocket* const inspector_;
76
  TcpHolder::Pointer tcp_;
77
};
78
79
namespace {
80
81
#if DUMP_READS || DUMP_WRITES
82
static void dump_hex(const char* buf, size_t len) {
83
  const char* ptr = buf;
84
  const char* end = ptr + len;
85
  const char* cptr;
86
  char c;
87
  int i;
88
89
  while (ptr < end) {
90
    cptr = ptr;
91
    for (i = 0; i < 16 && ptr < end; i++) {
92
      printf("%2.2X  ", static_cast<unsigned char>(*(ptr++)));
93
    }
94
    for (i = 72 - (i * 4); i > 0; i--) {
95
      printf(" ");
96
    }
97
    for (i = 0; i < 16 && cptr < end; i++) {
98
      c = *(cptr++);
99
      printf("%c", (c > 0x19) ? c : '.');
100
    }
101
    printf("\n");
102
  }
103
  printf("\n\n");
104
}
105
#endif
106
107
class WriteRequest {
108
 public:
109
2294
  WriteRequest(ProtocolHandler* handler, const std::vector<char>& buffer)
110
2294
      : handler(handler)
111
      , storage(buffer)
112
      , req(uv_write_t())
113
2294
      , buf(uv_buf_init(storage.data(), storage.size())) {}
114
115
2315
  static WriteRequest* from_write_req(uv_write_t* req) {
116
2315
    return node::ContainerOf(&WriteRequest::req, req);
117
  }
118
119
2285
  static void Cleanup(uv_write_t* req, int status) {
120
2285
    delete WriteRequest::from_write_req(req);
121
2285
  }
122
123
  ProtocolHandler* const handler;
124
  std::vector<char> storage;
125
  uv_write_t req;
126
  uv_buf_t buf;
127
};
128
129
452
void allocate_buffer(uv_handle_t* stream, size_t len, uv_buf_t* buf) {
130
452
  *buf = uv_buf_init(new char[len], len);
131
452
}
132
133
149
static void remove_from_beginning(std::vector<char>* buffer, size_t count) {
134
149
  buffer->erase(buffer->begin(), buffer->begin() + count);
135
149
}
136
137
static const char CLOSE_FRAME[] = {'\x88', '\x00'};
138
139
enum ws_decode_result {
140
  FRAME_OK, FRAME_INCOMPLETE, FRAME_CLOSE, FRAME_ERROR
141
};
142
143
37
static void generate_accept_string(const std::string& client_key,
144
                                   char (*buffer)[ACCEPT_KEY_LENGTH]) {
145
  // Magic string from websockets spec.
146
  static const char ws_magic[] = "258EAFA5-E914-47DA-95CA-C5AB0DC85B11";
147
74
  std::string input(client_key + ws_magic);
148
  char hash[SHA_DIGEST_LENGTH];
149
37
  USE(SHA1(reinterpret_cast<const unsigned char*>(&input[0]), input.size(),
150
       reinterpret_cast<unsigned char*>(hash)));
151
37
  node::base64_encode(hash, sizeof(hash), *buffer, sizeof(*buffer));
152
37
}
153
154
91
static std::string TrimPort(const std::string& host) {
155
91
  size_t last_colon_pos = host.rfind(':');
156
91
  if (last_colon_pos == std::string::npos)
157
    return host;
158
91
  size_t bracket = host.rfind(']');
159

91
  if (bracket == std::string::npos || last_colon_pos > bracket)
160
91
    return host.substr(0, last_colon_pos);
161
  return host;
162
}
163
164
91
static bool IsIPAddress(const std::string& host) {
165


91
  if (host.length() >= 4 && host.front() == '[' && host.back() == ']')
166
    return true;
167
91
  if (host.front() == '0') return false;
168
90
  uint_fast16_t accum = 0;
169
90
  uint_fast8_t quads = 0;
170
90
  bool empty = true;
171
203
  auto endOctet = [&accum, &quads, &empty](bool final = false) {
172

34
    return !empty && accum <= 0xff && ++quads <= 4 && final == (quads == 4) &&
173

71
           (empty = true) && !(accum = 0);
174
90
  };
175
180
  for (char c : host) {
176

175
    if (isdigit(c)) {
177
146
      if ((accum = (accum * 10) + (c - '0')) > 0xff) return false;
178
61
      empty = false;
179

111
    } else if (c != '.' || !endOctet()) {
180
82
      return false;
181
    }
182
  }
183
5
  return endOctet(true);
184
}
185
186
// Constants for hybi-10 frame format.
187
188
typedef int OpCode;
189
190
const OpCode kOpCodeContinuation = 0x0;
191
const OpCode kOpCodeText = 0x1;
192
const OpCode kOpCodeBinary = 0x2;
193
const OpCode kOpCodeClose = 0x8;
194
const OpCode kOpCodePing = 0x9;
195
const OpCode kOpCodePong = 0xA;
196
197
const unsigned char kFinalBit = 0x80;
198
const unsigned char kReserved1Bit = 0x40;
199
const unsigned char kReserved2Bit = 0x20;
200
const unsigned char kReserved3Bit = 0x10;
201
const unsigned char kOpCodeMask = 0xF;
202
const unsigned char kMaskBit = 0x80;
203
const unsigned char kPayloadLengthMask = 0x7F;
204
205
const size_t kMaxSingleBytePayloadLength = 125;
206
const size_t kTwoBytePayloadLengthField = 126;
207
const size_t kEightBytePayloadLengthField = 127;
208
const size_t kMaskingKeyWidthInBytes = 4;
209
210
2160
static std::vector<char> encode_frame_hybi17(const std::vector<char>& message) {
211
2160
  std::vector<char> frame;
212
2160
  OpCode op_code = kOpCodeText;
213
2160
  frame.push_back(kFinalBit | op_code);
214
2160
  const size_t data_length = message.size();
215
2160
  if (data_length <= kMaxSingleBytePayloadLength) {
216
175
    frame.push_back(static_cast<char>(data_length));
217
1985
  } else if (data_length <= 0xFFFF) {
218
1984
    frame.push_back(kTwoBytePayloadLengthField);
219
1984
    frame.push_back((data_length & 0xFF00) >> 8);
220
1984
    frame.push_back(data_length & 0xFF);
221
  } else {
222
1
    frame.push_back(kEightBytePayloadLengthField);
223
    char extended_payload_length[8];
224
1
    size_t remaining = data_length;
225
    // Fill the length into extended_payload_length in the network byte order.
226
9
    for (int i = 0; i < 8; ++i) {
227
8
      extended_payload_length[7 - i] = remaining & 0xFF;
228
8
      remaining >>= 8;
229
    }
230
2
    frame.insert(frame.end(), extended_payload_length,
231
1
                 extended_payload_length + 8);
232
1
    CHECK_EQ(0, remaining);
233
  }
234
2160
  frame.insert(frame.end(), message.begin(), message.end());
235
2160
  return frame;
236
}
237
238
174
static ws_decode_result decode_frame_hybi17(const std::vector<char>& buffer,
239
                                            bool client_frame,
240
                                            int* bytes_consumed,
241
                                            std::vector<char>* output,
242
                                            bool* compressed) {
243
174
  *bytes_consumed = 0;
244
174
  if (buffer.size() < 2)
245
    return FRAME_INCOMPLETE;
246
247
174
  auto it = buffer.begin();
248
249
174
  unsigned char first_byte = *it++;
250
174
  unsigned char second_byte = *it++;
251
252
174
  bool final = (first_byte & kFinalBit) != 0;
253
174
  bool reserved1 = (first_byte & kReserved1Bit) != 0;
254
174
  bool reserved2 = (first_byte & kReserved2Bit) != 0;
255
174
  bool reserved3 = (first_byte & kReserved3Bit) != 0;
256
174
  int op_code = first_byte & kOpCodeMask;
257
174
  bool masked = (second_byte & kMaskBit) != 0;
258
174
  *compressed = reserved1;
259

174
  if (!final || reserved2 || reserved3)
260
2
    return FRAME_ERROR;  // Only compression extension is supported.
261
262
172
  bool closed = false;
263
172
  switch (op_code) {
264
8
    case kOpCodeClose:
265
8
      closed = true;
266
8
      break;
267
164
    case kOpCodeText:
268
164
      break;
269
    case kOpCodeBinary:        // We don't support binary frames yet.
270
    case kOpCodeContinuation:  // We don't support binary frames yet.
271
    case kOpCodePing:          // We don't support binary frames yet.
272
    case kOpCodePong:          // We don't support binary frames yet.
273
    default:
274
      return FRAME_ERROR;
275
  }
276
277
  // In Hybi-17 spec client MUST mask its frame.
278

172
  if (client_frame && !masked) {
279
1
    return FRAME_ERROR;
280
  }
281
282
171
  uint64_t payload_length64 = second_byte & kPayloadLengthMask;
283
171
  if (payload_length64 > kMaxSingleBytePayloadLength) {
284
    int extended_payload_length_size;
285
34
    if (payload_length64 == kTwoBytePayloadLengthField) {
286
18
      extended_payload_length_size = 2;
287
16
    } else if (payload_length64 == kEightBytePayloadLengthField) {
288
16
      extended_payload_length_size = 8;
289
    } else {
290
      return FRAME_ERROR;
291
    }
292
34
    if ((buffer.end() - it) < extended_payload_length_size)
293
      return FRAME_INCOMPLETE;
294
34
    payload_length64 = 0;
295
198
    for (int i = 0; i < extended_payload_length_size; ++i) {
296
164
      payload_length64 <<= 8;
297
164
      payload_length64 |= static_cast<unsigned char>(*it++);
298
    }
299
  }
300
301
  static const uint64_t max_payload_length = 0x7FFFFFFFFFFFFFFFull;
302
  static const size_t max_length = SIZE_MAX;
303

171
  if (payload_length64 > max_payload_length ||
304
      payload_length64 > max_length - kMaskingKeyWidthInBytes) {
305
    // WebSocket frame length too large.
306
    return FRAME_ERROR;
307
  }
308
171
  size_t payload_length = static_cast<size_t>(payload_length64);
309
310
171
  if (buffer.size() - kMaskingKeyWidthInBytes < payload_length)
311
15
    return FRAME_INCOMPLETE;
312
313
156
  std::vector<char>::const_iterator masking_key = it;
314
156
  std::vector<char>::const_iterator payload = it + kMaskingKeyWidthInBytes;
315
1010861
  for (size_t i = 0; i < payload_length; ++i)  // Unmask the payload.
316
2021410
    output->insert(output->end(),
317
1010705
                   payload[i] ^ masking_key[i % kMaskingKeyWidthInBytes]);
318
319
156
  size_t pos = it + kMaskingKeyWidthInBytes + payload_length - buffer.begin();
320
156
  *bytes_consumed = pos;
321
156
  return closed ? FRAME_CLOSE : FRAME_OK;
322
}
323
324
// WS protocol
325
class WsHandler : public ProtocolHandler {
326
 public:
327
37
  WsHandler(InspectorSocket* inspector, TcpHolder::Pointer tcp)
328
74
            : ProtocolHandler(inspector, std::move(tcp)),
329
              OnCloseSent(&WsHandler::WaitForCloseReply),
330
              OnCloseReceived(&WsHandler::CloseFrameReceived),
331
37
              dispose_(false) { }
332
333
  void AcceptUpgrade(const std::string& accept_key) override { }
334
  void CancelHandshake() override {}
335
336
37
  void OnEof() override {
337
37
    tcp_.reset();
338
37
    if (dispose_)
339
6
      delete this;
340
37
  }
341
342
156
  void OnData(std::vector<char>* data) override {
343
    // 1. Parse.
344
156
    int processed = 0;
345
18
    do {
346
174
      processed = ParseWsFrames(*data);
347
      // 2. Fix the data size & length
348
174
      if (processed > 0) {
349
149
        remove_from_beginning(data, processed);
350
      }
351

174
    } while (processed > 0 && !data->empty());
352
156
  }
353
354
2160
  void Write(const std::vector<char> data) override {
355
4320
    std::vector<char> output = encode_frame_hybi17(data);
356
2160
    WriteRaw(output, WriteRequest::Cleanup);
357
2160
  }
358
359
 protected:
360
37
  void Shutdown() override {
361
37
    if (tcp_) {
362
6
      dispose_ = true;
363
6
      SendClose();
364
    } else {
365
31
      delete this;
366
    }
367
37
  }
368
369
 private:
370
  using Callback = void (WsHandler::*)();
371
372
9
  static void OnCloseFrameWritten(uv_write_t* req, int status) {
373
9
    WriteRequest* wr = WriteRequest::from_write_req(req);
374
9
    WsHandler* handler = static_cast<WsHandler*>(wr->handler);
375
9
    delete wr;
376
9
    Callback cb = handler->OnCloseSent;
377
9
    (handler->*cb)();
378
9
  }
379
380
6
  void WaitForCloseReply() {
381
6
    OnCloseReceived = &WsHandler::OnEof;
382
6
  }
383
384
9
  void SendClose() {
385
9
    WriteRaw(std::vector<char>(CLOSE_FRAME, CLOSE_FRAME + sizeof(CLOSE_FRAME)),
386
             OnCloseFrameWritten);
387
9
  }
388
389
3
  void CloseFrameReceived() {
390
3
    OnCloseSent = &WsHandler::OnEof;
391
3
    SendClose();
392
3
  }
393
394
174
  int ParseWsFrames(const std::vector<char>& buffer) {
395
174
    int bytes_consumed = 0;
396
174
    std::vector<char> output;
397
174
    bool compressed = false;
398
399
174
    ws_decode_result r =  decode_frame_hybi17(buffer,
400
                                              true /* client_frame */,
401
                                              &bytes_consumed, &output,
402
                                              &compressed);
403
    // Compressed frame means client is ignoring the headers and misbehaves
404

174
    if (compressed || r == FRAME_ERROR) {
405
3
      OnEof();
406
3
      bytes_consumed = 0;
407
171
    } else if (r == FRAME_CLOSE) {
408
7
      (this->*OnCloseReceived)();
409
7
      bytes_consumed = 0;
410
164
    } else if (r == FRAME_OK) {
411
149
      delegate()->OnWsFrame(output);
412
    }
413
174
    return bytes_consumed;
414
  }
415
416
417
  Callback OnCloseSent;
418
  Callback OnCloseReceived;
419
  bool dispose_;
420
};
421
422
// HTTP protocol
423
class HttpEvent {
424
 public:
425
91
  HttpEvent(const std::string& path, bool upgrade, bool isGET,
426
            const std::string& ws_key, const std::string& host)
427
91
            : path(path), upgrade(upgrade), isGET(isGET), ws_key(ws_key),
428
91
              host(host) { }
429
430
  std::string path;
431
  bool upgrade;
432
  bool isGET;
433
  std::string ws_key;
434
  std::string host;
435
};
436
437
class HttpHandler : public ProtocolHandler {
438
 public:
439
89
  explicit HttpHandler(InspectorSocket* inspector, TcpHolder::Pointer tcp)
440
178
                       : ProtocolHandler(inspector, std::move(tcp)),
441
89
                         parsing_value_(false) {
442
89
    llhttp_init(&parser_, HTTP_REQUEST, &parser_settings);
443
89
    llhttp_settings_init(&parser_settings);
444
89
    parser_settings.on_header_field = OnHeaderField;
445
89
    parser_settings.on_header_value = OnHeaderValue;
446
89
    parser_settings.on_message_complete = OnMessageComplete;
447
89
    parser_settings.on_url = OnPath;
448
89
  }
449
450
37
  void AcceptUpgrade(const std::string& accept_key) override {
451
    char accept_string[ACCEPT_KEY_LENGTH];
452
37
    generate_accept_string(accept_key, &accept_string);
453
37
    const char accept_ws_prefix[] = "HTTP/1.1 101 Switching Protocols\r\n"
454
                                    "Upgrade: websocket\r\n"
455
                                    "Connection: Upgrade\r\n"
456
                                    "Sec-WebSocket-Accept: ";
457
37
    const char accept_ws_suffix[] = "\r\n\r\n";
458
    std::vector<char> reply(accept_ws_prefix,
459
74
                            accept_ws_prefix + sizeof(accept_ws_prefix) - 1);
460
74
    reply.insert(reply.end(), accept_string,
461
37
                 accept_string + sizeof(accept_string));
462
74
    reply.insert(reply.end(), accept_ws_suffix,
463
37
                 accept_ws_suffix + sizeof(accept_ws_suffix) - 1);
464
37
    if (WriteRaw(reply, WriteRequest::Cleanup) >= 0) {
465
37
      inspector_->SwitchProtocol(new WsHandler(inspector_, std::move(tcp_)));
466
    } else {
467
      tcp_.reset();
468
    }
469
37
  }
470
471
21
  void CancelHandshake() override {
472
21
    const char HANDSHAKE_FAILED_RESPONSE[] =
473
        "HTTP/1.0 400 Bad Request\r\n"
474
        "Content-Type: text/html; charset=UTF-8\r\n\r\n"
475
        "WebSockets request was expected\r\n";
476
21
    WriteRaw(std::vector<char>(HANDSHAKE_FAILED_RESPONSE,
477
             HANDSHAKE_FAILED_RESPONSE + sizeof(HANDSHAKE_FAILED_RESPONSE) - 1),
478
             ThenCloseAndReportFailure);
479
21
  }
480
481
482
31
  void OnEof() override {
483
31
    tcp_.reset();
484
31
  }
485
486
238
  void OnData(std::vector<char>* data) override {
487
    llhttp_errno_t err;
488
238
    err = llhttp_execute(&parser_, data->data(), data->size());
489
490
238
    if (err == HPE_PAUSED_UPGRADE) {
491
41
      err = HPE_OK;
492
41
      llhttp_resume_after_upgrade(&parser_);
493
    }
494
238
    data->clear();
495
238
    if (err != HPE_OK) {
496
2
      CancelHandshake();
497
    }
498
    // Event handling may delete *this
499
238
    std::vector<HttpEvent> events;
500
238
    std::swap(events, events_);
501
316
    for (const HttpEvent& event : events) {
502

91
      if (!IsAllowedHost(event.host) || !event.isGET) {
503
12
        CancelHandshake();
504
13
        return;
505
79
      } else if (!event.upgrade) {
506
39
        delegate()->OnHttpGet(event.host, event.path);
507
40
      } else if (event.ws_key.empty()) {
508
1
        CancelHandshake();
509
1
        return;
510
      } else {
511
39
        delegate()->OnSocketUpgrade(event.host, event.path, event.ws_key);
512
      }
513
    }
514
  }
515
516
67
  void Write(const std::vector<char> data) override {
517
67
    WriteRaw(data, WriteRequest::Cleanup);
518
67
  }
519
520
 protected:
521
89
  void Shutdown() override {
522
89
    delete this;
523
89
  }
524
525
 private:
526
21
  static void ThenCloseAndReportFailure(uv_write_t* req, int status) {
527
21
    ProtocolHandler* handler = WriteRequest::from_write_req(req)->handler;
528
21
    WriteRequest::Cleanup(req, status);
529
21
    handler->inspector()->SwitchProtocol(nullptr);
530
21
  }
531
532
339
  static int OnHeaderValue(llhttp_t* parser, const char* at, size_t length) {
533
339
    HttpHandler* handler = From(parser);
534
339
    handler->parsing_value_ = true;
535
339
    handler->headers_[handler->current_header_].append(at, length);
536
339
    return 0;
537
  }
538
539
333
  static int OnHeaderField(llhttp_t* parser, const char* at, size_t length) {
540
333
    HttpHandler* handler = From(parser);
541
333
    if (handler->parsing_value_) {
542
197
      handler->parsing_value_ = false;
543
197
      handler->current_header_.clear();
544
    }
545
333
    handler->current_header_.append(at, length);
546
333
    return 0;
547
  }
548
549
117
  static int OnPath(llhttp_t* parser, const char* at, size_t length) {
550
117
    HttpHandler* handler = From(parser);
551
117
    handler->path_.append(at, length);
552
117
    return 0;
553
  }
554
555
880
  static HttpHandler* From(llhttp_t* parser) {
556
880
    return node::ContainerOf(&HttpHandler::parser_, parser);
557
  }
558
559
91
  static int OnMessageComplete(llhttp_t* parser) {
560
    // Event needs to be fired after the parser is done.
561
91
    HttpHandler* handler = From(parser);
562
91
    handler->events_.emplace_back(handler->path_,
563
91
                                  parser->upgrade,
564
182
                                  parser->method == HTTP_GET,
565
182
                                  handler->HeaderValue("Sec-WebSocket-Key"),
566
273
                                  handler->HeaderValue("Host"));
567
91
    handler->path_ = "";
568
91
    handler->parsing_value_ = false;
569
91
    handler->headers_.clear();
570
91
    handler->current_header_ = "";
571
91
    return 0;
572
  }
573
574
182
  std::string HeaderValue(const std::string& header) const {
575
182
    bool header_found = false;
576
364
    std::string value;
577
758
    for (const auto& header_value : headers_) {
578
576
      if (node::StringEqualNoCaseN(header_value.first.data(), header.data(),
579
                                   header.length())) {
580
134
        if (header_found)
581
          return "";
582
134
        value = header_value.second;
583
134
        header_found = true;
584
      }
585
    }
586
182
    return value;
587
  }
588
589
91
  bool IsAllowedHost(const std::string& host_with_port) const {
590
91
    std::string host = TrimPort(host_with_port);
591
182
    return host.empty() || IsIPAddress(host)
592

182
           || node::StringEqualNoCase(host.data(), "localhost");
593
  }
594
595
  bool parsing_value_;
596
  llhttp_t parser_;
597
  llhttp_settings_t parser_settings;
598
  std::vector<HttpEvent> events_;
599
  std::string current_header_;
600
  std::map<std::string, std::string> headers_;
601
  std::string path_;
602
};
603
604
}  // namespace
605
606
// Any protocol
607
126
ProtocolHandler::ProtocolHandler(InspectorSocket* inspector,
608
126
                                 TcpHolder::Pointer tcp)
609
126
                                 : inspector_(inspector), tcp_(std::move(tcp)) {
610
126
  CHECK_NOT_NULL(tcp_);
611
126
  tcp_->SetHandler(this);
612
126
}
613
614
2294
int ProtocolHandler::WriteRaw(const std::vector<char>& buffer,
615
                              uv_write_cb write_cb) {
616
2294
  return tcp_->WriteRaw(buffer, write_cb);
617
}
618
619
227
InspectorSocket::Delegate* ProtocolHandler::delegate() {
620
227
  return tcp_->delegate();
621
}
622
623
std::string ProtocolHandler::GetHost() const {
624
  char ip[INET6_ADDRSTRLEN];
625
  sockaddr_storage addr;
626
  int len = sizeof(addr);
627
  int err = uv_tcp_getsockname(tcp_->tcp(),
628
                               reinterpret_cast<struct sockaddr*>(&addr),
629
                               &len);
630
  if (err != 0)
631
    return "";
632
  if (addr.ss_family == AF_INET6) {
633
    const sockaddr_in6* v6 = reinterpret_cast<const sockaddr_in6*>(&addr);
634
    err = uv_ip6_name(v6, ip, sizeof(ip));
635
  } else {
636
    const sockaddr_in* v4 = reinterpret_cast<const sockaddr_in*>(&addr);
637
    err = uv_ip4_name(v4, ip, sizeof(ip));
638
  }
639
  if (err != 0)
640
    return "";
641
  return ip;
642
}
643
644
// RAII uv_tcp_t wrapper
645
89
TcpHolder::TcpHolder(InspectorSocket::DelegatePointer delegate)
646
                     : tcp_(),
647
89
                       delegate_(std::move(delegate)),
648
89
                       handler_(nullptr) { }
649
650
// static
651
89
TcpHolder::Pointer TcpHolder::Accept(
652
    uv_stream_t* server,
653
    InspectorSocket::DelegatePointer delegate) {
654
89
  TcpHolder* result = new TcpHolder(std::move(delegate));
655
89
  uv_stream_t* tcp = reinterpret_cast<uv_stream_t*>(&result->tcp_);
656
89
  int err = uv_tcp_init(server->loop, &result->tcp_);
657
89
  if (err == 0) {
658
89
    err = uv_accept(server, tcp);
659
  }
660
89
  if (err == 0) {
661
89
    err = uv_read_start(tcp, allocate_buffer, OnDataReceivedCb);
662
  }
663
89
  if (err == 0) {
664
89
    return TcpHolder::Pointer(result);
665
  } else {
666
    delete result;
667
    return nullptr;
668
  }
669
}
670
671
126
void TcpHolder::SetHandler(ProtocolHandler* handler) {
672
126
  handler_ = handler;
673
126
}
674
675
2294
int TcpHolder::WriteRaw(const std::vector<char>& buffer, uv_write_cb write_cb) {
676
#if DUMP_WRITES
677
  printf("%s (%ld bytes):\n", __FUNCTION__, buffer.size());
678
  dump_hex(buffer.data(), buffer.size());
679
  printf("\n");
680
#endif
681
682
  // Freed in write_request_cleanup
683
2294
  WriteRequest* wr = new WriteRequest(handler_, buffer);
684
2294
  uv_stream_t* stream = reinterpret_cast<uv_stream_t*>(&tcp_);
685
2294
  int err = uv_write(&wr->req, stream, &wr->buf, 1, write_cb);
686
2294
  if (err < 0)
687
    delete wr;
688
2294
  return err < 0;
689
}
690
691
227
InspectorSocket::Delegate* TcpHolder::delegate() {
692
227
  return delegate_.get();
693
}
694
695
// static
696
89
void TcpHolder::OnClosed(uv_handle_t* handle) {
697
89
  delete From(handle);
698
89
}
699
700
452
void TcpHolder::OnDataReceivedCb(uv_stream_t* tcp, ssize_t nread,
701
                                 const uv_buf_t* buf) {
702
#if DUMP_READS
703
  if (nread >= 0) {
704
    printf("%s (%ld bytes)\n", __FUNCTION__, nread);
705
    dump_hex(buf->base, nread);
706
  } else {
707
    printf("[%s:%d] %s\n", __FUNCTION__, __LINE__, uv_err_name(nread));
708
  }
709
#endif
710
452
  TcpHolder* holder = From(tcp);
711
452
  holder->ReclaimUvBuf(buf, nread);
712

452
  if (nread < 0 || nread == UV_EOF) {
713
58
    holder->handler_->OnEof();
714
  } else {
715
394
    holder->handler_->OnData(&holder->buffer);
716
  }
717
452
}
718
719
// static
720
89
void TcpHolder::DisconnectAndDispose(TcpHolder* holder) {
721
89
  uv_handle_t* handle = reinterpret_cast<uv_handle_t*>(&holder->tcp_);
722
89
  uv_close(handle, OnClosed);
723
89
}
724
725
452
void TcpHolder::ReclaimUvBuf(const uv_buf_t* buf, ssize_t read) {
726
452
  if (read > 0) {
727
394
    buffer.insert(buffer.end(), buf->base, buf->base + read);
728
  }
729
452
  delete[] buf->base;
730
452
}
731
732
InspectorSocket::~InspectorSocket() = default;
733
734
// static
735
126
void InspectorSocket::Shutdown(ProtocolHandler* handler) {
736
126
  handler->Shutdown();
737
126
}
738
739
// static
740
89
InspectorSocket::Pointer InspectorSocket::Accept(uv_stream_t* server,
741
                                                 DelegatePointer delegate) {
742
178
  auto tcp = TcpHolder::Accept(server, std::move(delegate));
743
89
  if (tcp) {
744
89
    InspectorSocket* inspector = new InspectorSocket();
745
89
    inspector->SwitchProtocol(new HttpHandler(inspector, std::move(tcp)));
746
89
    return InspectorSocket::Pointer(inspector);
747
  } else {
748
    return InspectorSocket::Pointer(nullptr);
749
  }
750
}
751
752
37
void InspectorSocket::AcceptUpgrade(const std::string& ws_key) {
753
37
  protocol_handler_->AcceptUpgrade(ws_key);
754
37
}
755
756
6
void InspectorSocket::CancelHandshake() {
757
6
  protocol_handler_->CancelHandshake();
758
6
}
759
760
std::string InspectorSocket::GetHost() {
761
  return protocol_handler_->GetHost();
762
}
763
764
147
void InspectorSocket::SwitchProtocol(ProtocolHandler* handler) {
765
147
  protocol_handler_.reset(std::move(handler));
766
147
}
767
768
2227
void InspectorSocket::Write(const char* data, size_t len) {
769
2227
  protocol_handler_->Write(std::vector<char>(data, data + len));
770
2227
}
771
772
}  // namespace inspector
773
}  // namespace node