xref: /third_party/node/src/inspector_socket.cc (revision 1cb0ef41)
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 <algorithm>
10#include <cstring>
11#include <map>
12
13#define ACCEPT_KEY_LENGTH base64_encoded_size(20)
14
15#define DUMP_READS 0
16#define DUMP_WRITES 0
17
18namespace node {
19namespace inspector {
20
21class TcpHolder {
22 public:
23  static void DisconnectAndDispose(TcpHolder* holder);
24  using Pointer = DeleteFnPtr<TcpHolder, DisconnectAndDispose>;
25
26  static Pointer Accept(uv_stream_t* server,
27                        InspectorSocket::DelegatePointer delegate);
28  void SetHandler(ProtocolHandler* handler);
29  int WriteRaw(const std::vector<char>& buffer, uv_write_cb write_cb);
30  uv_tcp_t* tcp() {
31    return &tcp_;
32  }
33  InspectorSocket::Delegate* delegate();
34
35 private:
36  static TcpHolder* From(void* handle) {
37    return node::ContainerOf(&TcpHolder::tcp_,
38                             reinterpret_cast<uv_tcp_t*>(handle));
39  }
40  static void OnClosed(uv_handle_t* handle);
41  static void OnDataReceivedCb(uv_stream_t* stream, ssize_t nread,
42                               const uv_buf_t* buf);
43  explicit TcpHolder(InspectorSocket::DelegatePointer delegate);
44  ~TcpHolder() = default;
45  void ReclaimUvBuf(const uv_buf_t* buf, ssize_t read);
46
47  uv_tcp_t tcp_;
48  const InspectorSocket::DelegatePointer delegate_;
49  ProtocolHandler* handler_;
50  std::vector<char> buffer;
51};
52
53
54class ProtocolHandler {
55 public:
56  ProtocolHandler(InspectorSocket* inspector, TcpHolder::Pointer tcp);
57
58  virtual void AcceptUpgrade(const std::string& accept_key) = 0;
59  virtual void OnData(std::vector<char>* data) = 0;
60  virtual void OnEof() = 0;
61  virtual void Write(const std::vector<char> data) = 0;
62  virtual void CancelHandshake() = 0;
63
64  std::string GetHost() const;
65
66  InspectorSocket* inspector() {
67    return inspector_;
68  }
69  virtual void Shutdown() = 0;
70
71 protected:
72  virtual ~ProtocolHandler() = default;
73  int WriteRaw(const std::vector<char>& buffer, uv_write_cb write_cb);
74  InspectorSocket::Delegate* delegate();
75
76  InspectorSocket* const inspector_;
77  TcpHolder::Pointer tcp_;
78};
79
80namespace {
81
82#if DUMP_READS || DUMP_WRITES
83static void dump_hex(const char* buf, size_t len) {
84  const char* ptr = buf;
85  const char* end = ptr + len;
86  const char* cptr;
87  char c;
88  int i;
89
90  while (ptr < end) {
91    cptr = ptr;
92    for (i = 0; i < 16 && ptr < end; i++) {
93      printf("%2.2X  ", static_cast<unsigned char>(*(ptr++)));
94    }
95    for (i = 72 - (i * 4); i > 0; i--) {
96      printf(" ");
97    }
98    for (i = 0; i < 16 && cptr < end; i++) {
99      c = *(cptr++);
100      printf("%c", (c > 0x19) ? c : '.');
101    }
102    printf("\n");
103  }
104  printf("\n\n");
105}
106#endif
107
108class WriteRequest {
109 public:
110  WriteRequest(ProtocolHandler* handler, const std::vector<char>& buffer)
111      : handler(handler)
112      , storage(buffer)
113      , req(uv_write_t())
114      , buf(uv_buf_init(storage.data(), storage.size())) {}
115
116  static WriteRequest* from_write_req(uv_write_t* req) {
117    return node::ContainerOf(&WriteRequest::req, req);
118  }
119
120  static void Cleanup(uv_write_t* req, int status) {
121    delete WriteRequest::from_write_req(req);
122  }
123
124  ProtocolHandler* const handler;
125  std::vector<char> storage;
126  uv_write_t req;
127  uv_buf_t buf;
128};
129
130void allocate_buffer(uv_handle_t* stream, size_t len, uv_buf_t* buf) {
131  *buf = uv_buf_init(new char[len], len);
132}
133
134static void remove_from_beginning(std::vector<char>* buffer, size_t count) {
135  buffer->erase(buffer->begin(), buffer->begin() + count);
136}
137
138static const char CLOSE_FRAME[] = {'\x88', '\x00'};
139
140enum ws_decode_result {
141  FRAME_OK, FRAME_INCOMPLETE, FRAME_CLOSE, FRAME_ERROR
142};
143
144static void generate_accept_string(const std::string& client_key,
145                                   char (*buffer)[ACCEPT_KEY_LENGTH]) {
146  // Magic string from websockets spec.
147  static const char ws_magic[] = "258EAFA5-E914-47DA-95CA-C5AB0DC85B11";
148  std::string input(client_key + ws_magic);
149  char hash[SHA_DIGEST_LENGTH];
150  USE(SHA1(reinterpret_cast<const unsigned char*>(input.data()),
151           input.size(),
152           reinterpret_cast<unsigned char*>(hash)));
153  node::base64_encode(hash, sizeof(hash), *buffer, sizeof(*buffer));
154}
155
156static std::string TrimPort(const std::string& host) {
157  size_t last_colon_pos = host.rfind(':');
158  if (last_colon_pos == std::string::npos)
159    return host;
160  size_t bracket = host.rfind(']');
161  if (bracket == std::string::npos || last_colon_pos > bracket)
162    return host.substr(0, last_colon_pos);
163  return host;
164}
165
166static bool IsIPAddress(const std::string& host) {
167  // To avoid DNS rebinding attacks, we are aware of the following requirements:
168  // * the host name must be an IP address (CVE-2018-7160, CVE-2022-32212),
169  // * the IP address must be routable (hackerone.com/reports/1632921), and
170  // * the IP address must be formatted unambiguously (CVE-2022-43548).
171
172  // The logic below assumes that the string is null-terminated, so ensure that
173  // we did not somehow end up with null characters within the string.
174  if (host.find('\0') != std::string::npos) return false;
175
176  // All IPv6 addresses must be enclosed in square brackets, and anything
177  // enclosed in square brackets must be an IPv6 address.
178  if (host.length() >= 4 && host.front() == '[' && host.back() == ']') {
179    // INET6_ADDRSTRLEN is the maximum length of the dual format (including the
180    // terminating null character), which is the longest possible representation
181    // of an IPv6 address: xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:ddd.ddd.ddd.ddd
182    if (host.length() - 2 >= INET6_ADDRSTRLEN) return false;
183
184    // Annoyingly, libuv's implementation of inet_pton() deviates from other
185    // implementations of the function in that it allows '%' in IPv6 addresses.
186    if (host.find('%') != std::string::npos) return false;
187
188    // Parse the IPv6 address to ensure it is syntactically valid.
189    char ipv6_str[INET6_ADDRSTRLEN];
190    std::copy(host.begin() + 1, host.end() - 1, ipv6_str);
191    ipv6_str[host.length()] = '\0';
192    unsigned char ipv6[sizeof(struct in6_addr)];
193    if (uv_inet_pton(AF_INET6, ipv6_str, ipv6) != 0) return false;
194
195    // The only non-routable IPv6 address is ::/128. It should not be necessary
196    // to explicitly reject it because it will still be enclosed in square
197    // brackets and not even macOS should make DNS requests in that case, but
198    // history has taught us that we cannot be careful enough.
199    // Note that RFC 4291 defines both "IPv4-Compatible IPv6 Addresses" and
200    // "IPv4-Mapped IPv6 Addresses", which means that there are IPv6 addresses
201    // (other than ::/128) that represent non-routable IPv4 addresses. However,
202    // this translation assumes that the host is interpreted as an IPv6 address
203    // in the first place, at which point DNS rebinding should not be an issue.
204    if (std::all_of(ipv6, ipv6 + sizeof(ipv6), [](auto b) { return b == 0; })) {
205      return false;
206    }
207
208    // It is a syntactically valid and routable IPv6 address enclosed in square
209    // brackets. No client should be able to misinterpret this.
210    return true;
211  }
212
213  // Anything not enclosed in square brackets must be an IPv4 address. It is
214  // important here that inet_pton() accepts only the so-called dotted-decimal
215  // notation, which is a strict subset of the so-called numbers-and-dots
216  // notation that is allowed by inet_aton() and inet_addr(). This subset does
217  // not allow hexadecimal or octal number formats.
218  unsigned char ipv4[sizeof(struct in_addr)];
219  if (uv_inet_pton(AF_INET, host.c_str(), ipv4) != 0) return false;
220
221  // The only strictly non-routable IPv4 address is 0.0.0.0, and macOS will make
222  // DNS requests for this IP address, so we need to explicitly reject it. In
223  // fact, we can safely reject all of 0.0.0.0/8 (see Section 3.2 of RFC 791 and
224  // Section 3.2.1.3 of RFC 1122).
225  // Note that inet_pton() stores the IPv4 address in network byte order.
226  if (ipv4[0] == 0) return false;
227
228  // It is a routable IPv4 address in dotted-decimal notation.
229  return true;
230}
231
232// Constants for hybi-10 frame format.
233
234typedef int OpCode;
235
236const OpCode kOpCodeContinuation = 0x0;
237const OpCode kOpCodeText = 0x1;
238const OpCode kOpCodeBinary = 0x2;
239const OpCode kOpCodeClose = 0x8;
240const OpCode kOpCodePing = 0x9;
241const OpCode kOpCodePong = 0xA;
242
243const unsigned char kFinalBit = 0x80;
244const unsigned char kReserved1Bit = 0x40;
245const unsigned char kReserved2Bit = 0x20;
246const unsigned char kReserved3Bit = 0x10;
247const unsigned char kOpCodeMask = 0xF;
248const unsigned char kMaskBit = 0x80;
249const unsigned char kPayloadLengthMask = 0x7F;
250
251const size_t kMaxSingleBytePayloadLength = 125;
252const size_t kTwoBytePayloadLengthField = 126;
253const size_t kEightBytePayloadLengthField = 127;
254const size_t kMaskingKeyWidthInBytes = 4;
255
256static std::vector<char> encode_frame_hybi17(const std::vector<char>& message) {
257  std::vector<char> frame;
258  OpCode op_code = kOpCodeText;
259  frame.push_back(kFinalBit | op_code);
260  const size_t data_length = message.size();
261  if (data_length <= kMaxSingleBytePayloadLength) {
262    frame.push_back(static_cast<char>(data_length));
263  } else if (data_length <= 0xFFFF) {
264    frame.push_back(kTwoBytePayloadLengthField);
265    frame.push_back((data_length & 0xFF00) >> 8);
266    frame.push_back(data_length & 0xFF);
267  } else {
268    frame.push_back(kEightBytePayloadLengthField);
269    char extended_payload_length[8];
270    size_t remaining = data_length;
271    // Fill the length into extended_payload_length in the network byte order.
272    for (int i = 0; i < 8; ++i) {
273      extended_payload_length[7 - i] = remaining & 0xFF;
274      remaining >>= 8;
275    }
276    frame.insert(frame.end(), extended_payload_length,
277                 extended_payload_length + 8);
278    CHECK_EQ(0, remaining);
279  }
280  frame.insert(frame.end(), message.begin(), message.end());
281  return frame;
282}
283
284static ws_decode_result decode_frame_hybi17(const std::vector<char>& buffer,
285                                            bool client_frame,
286                                            int* bytes_consumed,
287                                            std::vector<char>* output,
288                                            bool* compressed) {
289  *bytes_consumed = 0;
290  if (buffer.size() < 2)
291    return FRAME_INCOMPLETE;
292
293  auto it = buffer.begin();
294
295  unsigned char first_byte = *it++;
296  unsigned char second_byte = *it++;
297
298  bool final = (first_byte & kFinalBit) != 0;
299  bool reserved1 = (first_byte & kReserved1Bit) != 0;
300  bool reserved2 = (first_byte & kReserved2Bit) != 0;
301  bool reserved3 = (first_byte & kReserved3Bit) != 0;
302  int op_code = first_byte & kOpCodeMask;
303  bool masked = (second_byte & kMaskBit) != 0;
304  *compressed = reserved1;
305  if (!final || reserved2 || reserved3)
306    return FRAME_ERROR;  // Only compression extension is supported.
307
308  bool closed = false;
309  switch (op_code) {
310    case kOpCodeClose:
311      closed = true;
312      break;
313    case kOpCodeText:
314      break;
315    case kOpCodeBinary:        // We don't support binary frames yet.
316    case kOpCodeContinuation:  // We don't support binary frames yet.
317    case kOpCodePing:          // We don't support binary frames yet.
318    case kOpCodePong:          // We don't support binary frames yet.
319    default:
320      return FRAME_ERROR;
321  }
322
323  // In Hybi-17 spec client MUST mask its frame.
324  if (client_frame && !masked) {
325    return FRAME_ERROR;
326  }
327
328  uint64_t payload_length64 = second_byte & kPayloadLengthMask;
329  if (payload_length64 > kMaxSingleBytePayloadLength) {
330    int extended_payload_length_size;
331    if (payload_length64 == kTwoBytePayloadLengthField) {
332      extended_payload_length_size = 2;
333    } else if (payload_length64 == kEightBytePayloadLengthField) {
334      extended_payload_length_size = 8;
335    } else {
336      return FRAME_ERROR;
337    }
338    if ((buffer.end() - it) < extended_payload_length_size)
339      return FRAME_INCOMPLETE;
340    payload_length64 = 0;
341    for (int i = 0; i < extended_payload_length_size; ++i) {
342      payload_length64 <<= 8;
343      payload_length64 |= static_cast<unsigned char>(*it++);
344    }
345  }
346
347  static const uint64_t max_payload_length = 0x7FFFFFFFFFFFFFFFull;
348  static const size_t max_length = SIZE_MAX;
349  if (payload_length64 > max_payload_length ||
350      payload_length64 > max_length - kMaskingKeyWidthInBytes) {
351    // WebSocket frame length too large.
352    return FRAME_ERROR;
353  }
354  size_t payload_length = static_cast<size_t>(payload_length64);
355
356  if (buffer.size() - kMaskingKeyWidthInBytes < payload_length)
357    return FRAME_INCOMPLETE;
358
359  std::vector<char>::const_iterator masking_key = it;
360  std::vector<char>::const_iterator payload = it + kMaskingKeyWidthInBytes;
361  for (size_t i = 0; i < payload_length; ++i)  // Unmask the payload.
362    output->insert(output->end(),
363                   payload[i] ^ masking_key[i % kMaskingKeyWidthInBytes]);
364
365  size_t pos = it + kMaskingKeyWidthInBytes + payload_length - buffer.begin();
366  *bytes_consumed = pos;
367  return closed ? FRAME_CLOSE : FRAME_OK;
368}
369
370// WS protocol
371class WsHandler : public ProtocolHandler {
372 public:
373  WsHandler(InspectorSocket* inspector, TcpHolder::Pointer tcp)
374            : ProtocolHandler(inspector, std::move(tcp)),
375              OnCloseSent(&WsHandler::WaitForCloseReply),
376              OnCloseReceived(&WsHandler::CloseFrameReceived),
377              dispose_(false) { }
378
379  void AcceptUpgrade(const std::string& accept_key) override { }
380  void CancelHandshake() override {}
381
382  void OnEof() override {
383    tcp_.reset();
384    if (dispose_)
385      delete this;
386  }
387
388  void OnData(std::vector<char>* data) override {
389    // 1. Parse.
390    int processed = 0;
391    do {
392      processed = ParseWsFrames(*data);
393      // 2. Fix the data size & length
394      if (processed > 0) {
395        remove_from_beginning(data, processed);
396      }
397    } while (processed > 0 && !data->empty());
398  }
399
400  void Write(const std::vector<char> data) override {
401    std::vector<char> output = encode_frame_hybi17(data);
402    WriteRaw(output, WriteRequest::Cleanup);
403  }
404
405 protected:
406  void Shutdown() override {
407    if (tcp_) {
408      dispose_ = true;
409      SendClose();
410    } else {
411      delete this;
412    }
413  }
414
415 private:
416  using Callback = void (WsHandler::*)();
417
418  static void OnCloseFrameWritten(uv_write_t* req, int status) {
419    WriteRequest* wr = WriteRequest::from_write_req(req);
420    WsHandler* handler = static_cast<WsHandler*>(wr->handler);
421    delete wr;
422    Callback cb = handler->OnCloseSent;
423    (handler->*cb)();
424  }
425
426  void WaitForCloseReply() {
427    OnCloseReceived = &WsHandler::OnEof;
428  }
429
430  void SendClose() {
431    WriteRaw(std::vector<char>(CLOSE_FRAME, CLOSE_FRAME + sizeof(CLOSE_FRAME)),
432             OnCloseFrameWritten);
433  }
434
435  void CloseFrameReceived() {
436    OnCloseSent = &WsHandler::OnEof;
437    SendClose();
438  }
439
440  int ParseWsFrames(const std::vector<char>& buffer) {
441    int bytes_consumed = 0;
442    std::vector<char> output;
443    bool compressed = false;
444
445    ws_decode_result r =  decode_frame_hybi17(buffer,
446                                              true /* client_frame */,
447                                              &bytes_consumed, &output,
448                                              &compressed);
449    // Compressed frame means client is ignoring the headers and misbehaves
450    if (compressed || r == FRAME_ERROR) {
451      OnEof();
452      bytes_consumed = 0;
453    } else if (r == FRAME_CLOSE) {
454      (this->*OnCloseReceived)();
455      bytes_consumed = 0;
456    } else if (r == FRAME_OK) {
457      delegate()->OnWsFrame(output);
458    }
459    return bytes_consumed;
460  }
461
462
463  Callback OnCloseSent;
464  Callback OnCloseReceived;
465  bool dispose_;
466};
467
468// HTTP protocol
469class HttpEvent {
470 public:
471  HttpEvent(const std::string& path, bool upgrade, bool isGET,
472            const std::string& ws_key, const std::string& host)
473            : path(path), upgrade(upgrade), isGET(isGET), ws_key(ws_key),
474              host(host) { }
475
476  std::string path;
477  bool upgrade;
478  bool isGET;
479  std::string ws_key;
480  std::string host;
481};
482
483class HttpHandler : public ProtocolHandler {
484 public:
485  explicit HttpHandler(InspectorSocket* inspector, TcpHolder::Pointer tcp)
486                       : ProtocolHandler(inspector, std::move(tcp)),
487                         parsing_value_(false) {
488    llhttp_init(&parser_, HTTP_REQUEST, &parser_settings);
489    llhttp_settings_init(&parser_settings);
490    parser_settings.on_header_field = OnHeaderField;
491    parser_settings.on_header_value = OnHeaderValue;
492    parser_settings.on_message_complete = OnMessageComplete;
493    parser_settings.on_url = OnPath;
494  }
495
496  void AcceptUpgrade(const std::string& accept_key) override {
497    char accept_string[ACCEPT_KEY_LENGTH];
498    generate_accept_string(accept_key, &accept_string);
499    const char accept_ws_prefix[] = "HTTP/1.1 101 Switching Protocols\r\n"
500                                    "Upgrade: websocket\r\n"
501                                    "Connection: Upgrade\r\n"
502                                    "Sec-WebSocket-Accept: ";
503    const char accept_ws_suffix[] = "\r\n\r\n";
504    std::vector<char> reply(accept_ws_prefix,
505                            accept_ws_prefix + sizeof(accept_ws_prefix) - 1);
506    reply.insert(reply.end(), accept_string,
507                 accept_string + sizeof(accept_string));
508    reply.insert(reply.end(), accept_ws_suffix,
509                 accept_ws_suffix + sizeof(accept_ws_suffix) - 1);
510    if (WriteRaw(reply, WriteRequest::Cleanup) >= 0) {
511      inspector_->SwitchProtocol(new WsHandler(inspector_, std::move(tcp_)));
512    } else {
513      tcp_.reset();
514    }
515  }
516
517  void CancelHandshake() override {
518    const char HANDSHAKE_FAILED_RESPONSE[] =
519        "HTTP/1.0 400 Bad Request\r\n"
520        "Content-Type: text/html; charset=UTF-8\r\n\r\n"
521        "WebSockets request was expected\r\n";
522    WriteRaw(std::vector<char>(HANDSHAKE_FAILED_RESPONSE,
523             HANDSHAKE_FAILED_RESPONSE + sizeof(HANDSHAKE_FAILED_RESPONSE) - 1),
524             ThenCloseAndReportFailure);
525  }
526
527
528  void OnEof() override {
529    tcp_.reset();
530  }
531
532  void OnData(std::vector<char>* data) override {
533    llhttp_errno_t err;
534    err = llhttp_execute(&parser_, data->data(), data->size());
535
536    if (err == HPE_PAUSED_UPGRADE) {
537      err = HPE_OK;
538      llhttp_resume_after_upgrade(&parser_);
539    }
540    data->clear();
541    if (err != HPE_OK) {
542      CancelHandshake();
543    }
544    // Event handling may delete *this
545    std::vector<HttpEvent> events;
546    std::swap(events, events_);
547    for (const HttpEvent& event : events) {
548      if (!IsAllowedHost(event.host) || !event.isGET) {
549        CancelHandshake();
550        return;
551      } else if (!event.upgrade) {
552        delegate()->OnHttpGet(event.host, event.path);
553      } else if (event.ws_key.empty()) {
554        CancelHandshake();
555        return;
556      } else {
557        delegate()->OnSocketUpgrade(event.host, event.path, event.ws_key);
558      }
559    }
560  }
561
562  void Write(const std::vector<char> data) override {
563    WriteRaw(data, WriteRequest::Cleanup);
564  }
565
566 protected:
567  void Shutdown() override {
568    delete this;
569  }
570
571 private:
572  static void ThenCloseAndReportFailure(uv_write_t* req, int status) {
573    ProtocolHandler* handler = WriteRequest::from_write_req(req)->handler;
574    WriteRequest::Cleanup(req, status);
575    handler->inspector()->SwitchProtocol(nullptr);
576  }
577
578  static int OnHeaderValue(llhttp_t* parser, const char* at, size_t length) {
579    HttpHandler* handler = From(parser);
580    handler->parsing_value_ = true;
581    handler->headers_[handler->current_header_].append(at, length);
582    return 0;
583  }
584
585  static int OnHeaderField(llhttp_t* parser, const char* at, size_t length) {
586    HttpHandler* handler = From(parser);
587    if (handler->parsing_value_) {
588      handler->parsing_value_ = false;
589      handler->current_header_.clear();
590    }
591    handler->current_header_.append(at, length);
592    return 0;
593  }
594
595  static int OnPath(llhttp_t* parser, const char* at, size_t length) {
596    HttpHandler* handler = From(parser);
597    handler->path_.append(at, length);
598    return 0;
599  }
600
601  static HttpHandler* From(llhttp_t* parser) {
602    return node::ContainerOf(&HttpHandler::parser_, parser);
603  }
604
605  static int OnMessageComplete(llhttp_t* parser) {
606    // Event needs to be fired after the parser is done.
607    HttpHandler* handler = From(parser);
608    handler->events_.emplace_back(handler->path_,
609                                  parser->upgrade,
610                                  parser->method == HTTP_GET,
611                                  handler->HeaderValue("Sec-WebSocket-Key"),
612                                  handler->HeaderValue("Host"));
613    handler->path_ = "";
614    handler->parsing_value_ = false;
615    handler->headers_.clear();
616    handler->current_header_ = "";
617    return 0;
618  }
619
620  std::string HeaderValue(const std::string& header) const {
621    bool header_found = false;
622    std::string value;
623    for (const auto& header_value : headers_) {
624      if (node::StringEqualNoCaseN(header_value.first.data(), header.data(),
625                                   header.length())) {
626        if (header_found)
627          return "";
628        value = header_value.second;
629        header_found = true;
630      }
631    }
632    return value;
633  }
634
635  bool IsAllowedHost(const std::string& host_with_port) const {
636    std::string host = TrimPort(host_with_port);
637    return host.empty() || IsIPAddress(host)
638           || node::StringEqualNoCase(host.data(), "localhost");
639  }
640
641  bool parsing_value_;
642  llhttp_t parser_;
643  llhttp_settings_t parser_settings;
644  std::vector<HttpEvent> events_;
645  std::string current_header_;
646  std::map<std::string, std::string> headers_;
647  std::string path_;
648};
649
650}  // namespace
651
652// Any protocol
653ProtocolHandler::ProtocolHandler(InspectorSocket* inspector,
654                                 TcpHolder::Pointer tcp)
655                                 : inspector_(inspector), tcp_(std::move(tcp)) {
656  CHECK_NOT_NULL(tcp_);
657  tcp_->SetHandler(this);
658}
659
660int ProtocolHandler::WriteRaw(const std::vector<char>& buffer,
661                              uv_write_cb write_cb) {
662  return tcp_->WriteRaw(buffer, write_cb);
663}
664
665InspectorSocket::Delegate* ProtocolHandler::delegate() {
666  return tcp_->delegate();
667}
668
669std::string ProtocolHandler::GetHost() const {
670  char ip[INET6_ADDRSTRLEN];
671  sockaddr_storage addr;
672  int len = sizeof(addr);
673  int err = uv_tcp_getsockname(tcp_->tcp(),
674                               reinterpret_cast<struct sockaddr*>(&addr),
675                               &len);
676  if (err != 0)
677    return "";
678  if (addr.ss_family == AF_INET6) {
679    const sockaddr_in6* v6 = reinterpret_cast<const sockaddr_in6*>(&addr);
680    err = uv_ip6_name(v6, ip, sizeof(ip));
681  } else {
682    const sockaddr_in* v4 = reinterpret_cast<const sockaddr_in*>(&addr);
683    err = uv_ip4_name(v4, ip, sizeof(ip));
684  }
685  if (err != 0)
686    return "";
687  return ip;
688}
689
690// RAII uv_tcp_t wrapper
691TcpHolder::TcpHolder(InspectorSocket::DelegatePointer delegate)
692                     : tcp_(),
693                       delegate_(std::move(delegate)),
694                       handler_(nullptr) { }
695
696// static
697TcpHolder::Pointer TcpHolder::Accept(
698    uv_stream_t* server,
699    InspectorSocket::DelegatePointer delegate) {
700  TcpHolder* result = new TcpHolder(std::move(delegate));
701  uv_stream_t* tcp = reinterpret_cast<uv_stream_t*>(&result->tcp_);
702  int err = uv_tcp_init(server->loop, &result->tcp_);
703  if (err == 0) {
704    err = uv_accept(server, tcp);
705  }
706  if (err == 0) {
707    err = uv_read_start(tcp, allocate_buffer, OnDataReceivedCb);
708  }
709  if (err == 0) {
710    return TcpHolder::Pointer(result);
711  } else {
712    delete result;
713    return nullptr;
714  }
715}
716
717void TcpHolder::SetHandler(ProtocolHandler* handler) {
718  handler_ = handler;
719}
720
721int TcpHolder::WriteRaw(const std::vector<char>& buffer, uv_write_cb write_cb) {
722#if DUMP_WRITES
723  printf("%s (%ld bytes):\n", __FUNCTION__, buffer.size());
724  dump_hex(buffer.data(), buffer.size());
725  printf("\n");
726#endif
727
728  // Freed in write_request_cleanup
729  WriteRequest* wr = new WriteRequest(handler_, buffer);
730  uv_stream_t* stream = reinterpret_cast<uv_stream_t*>(&tcp_);
731  int err = uv_write(&wr->req, stream, &wr->buf, 1, write_cb);
732  if (err < 0)
733    delete wr;
734  return err < 0;
735}
736
737InspectorSocket::Delegate* TcpHolder::delegate() {
738  return delegate_.get();
739}
740
741// static
742void TcpHolder::OnClosed(uv_handle_t* handle) {
743  delete From(handle);
744}
745
746void TcpHolder::OnDataReceivedCb(uv_stream_t* tcp, ssize_t nread,
747                                 const uv_buf_t* buf) {
748#if DUMP_READS
749  if (nread >= 0) {
750    printf("%s (%ld bytes)\n", __FUNCTION__, nread);
751    dump_hex(buf->base, nread);
752  } else {
753    printf("[%s:%d] %s\n", __FUNCTION__, __LINE__, uv_err_name(nread));
754  }
755#endif
756  TcpHolder* holder = From(tcp);
757  holder->ReclaimUvBuf(buf, nread);
758  if (nread < 0 || nread == UV_EOF) {
759    holder->handler_->OnEof();
760  } else {
761    holder->handler_->OnData(&holder->buffer);
762  }
763}
764
765// static
766void TcpHolder::DisconnectAndDispose(TcpHolder* holder) {
767  uv_handle_t* handle = reinterpret_cast<uv_handle_t*>(&holder->tcp_);
768  uv_close(handle, OnClosed);
769}
770
771void TcpHolder::ReclaimUvBuf(const uv_buf_t* buf, ssize_t read) {
772  if (read > 0) {
773    buffer.insert(buffer.end(), buf->base, buf->base + read);
774  }
775  delete[] buf->base;
776}
777
778InspectorSocket::~InspectorSocket() = default;
779
780// static
781void InspectorSocket::Shutdown(ProtocolHandler* handler) {
782  handler->Shutdown();
783}
784
785// static
786InspectorSocket::Pointer InspectorSocket::Accept(uv_stream_t* server,
787                                                 DelegatePointer delegate) {
788  auto tcp = TcpHolder::Accept(server, std::move(delegate));
789  if (tcp) {
790    InspectorSocket* inspector = new InspectorSocket();
791    inspector->SwitchProtocol(new HttpHandler(inspector, std::move(tcp)));
792    return InspectorSocket::Pointer(inspector);
793  } else {
794    return InspectorSocket::Pointer(nullptr);
795  }
796}
797
798void InspectorSocket::AcceptUpgrade(const std::string& ws_key) {
799  protocol_handler_->AcceptUpgrade(ws_key);
800}
801
802void InspectorSocket::CancelHandshake() {
803  protocol_handler_->CancelHandshake();
804}
805
806std::string InspectorSocket::GetHost() {
807  return protocol_handler_->GetHost();
808}
809
810void InspectorSocket::SwitchProtocol(ProtocolHandler* handler) {
811  protocol_handler_.reset(std::move(handler));
812}
813
814void InspectorSocket::Write(const char* data, size_t len) {
815  protocol_handler_->Write(std::vector<char>(data, data + len));
816}
817
818}  // namespace inspector
819}  // namespace node
820