• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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);
tcp()29   uv_tcp_t* tcp() {
30     return &tcp_;
31   }
32   InspectorSocket::Delegate* delegate();
33 
34  private:
From(void * handle)35   static TcpHolder* From(void* handle) {
36     return node::ContainerOf(&TcpHolder::tcp_,
37                              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   ~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 
inspector()65   InspectorSocket* inspector() {
66     return inspector_;
67   }
68   virtual void Shutdown() = 0;
69 
70  protected:
71   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
dump_hex(const char * buf,size_t len)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:
WriteRequest(ProtocolHandler * handler,const std::vector<char> & buffer)109   WriteRequest(ProtocolHandler* handler, const std::vector<char>& buffer)
110       : handler(handler)
111       , storage(buffer)
112       , req(uv_write_t())
113       , buf(uv_buf_init(storage.data(), storage.size())) {}
114 
from_write_req(uv_write_t * req)115   static WriteRequest* from_write_req(uv_write_t* req) {
116     return node::ContainerOf(&WriteRequest::req, req);
117   }
118 
Cleanup(uv_write_t * req,int status)119   static void Cleanup(uv_write_t* req, int status) {
120     delete WriteRequest::from_write_req(req);
121   }
122 
123   ProtocolHandler* const handler;
124   std::vector<char> storage;
125   uv_write_t req;
126   uv_buf_t buf;
127 };
128 
allocate_buffer(uv_handle_t * stream,size_t len,uv_buf_t * buf)129 void allocate_buffer(uv_handle_t* stream, size_t len, uv_buf_t* buf) {
130   *buf = uv_buf_init(new char[len], len);
131 }
132 
remove_from_beginning(std::vector<char> * buffer,size_t count)133 static void remove_from_beginning(std::vector<char>* buffer, size_t count) {
134   buffer->erase(buffer->begin(), buffer->begin() + count);
135 }
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 
generate_accept_string(const std::string & client_key,char (* buffer)[ACCEPT_KEY_LENGTH])143 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   std::string input(client_key + ws_magic);
148   char hash[SHA_DIGEST_LENGTH];
149   SHA1(reinterpret_cast<const unsigned char*>(&input[0]), input.size(),
150        reinterpret_cast<unsigned char*>(hash));
151   node::base64_encode(hash, sizeof(hash), *buffer, sizeof(*buffer));
152 }
153 
TrimPort(const std::string & host)154 static std::string TrimPort(const std::string& host) {
155   size_t last_colon_pos = host.rfind(':');
156   if (last_colon_pos == std::string::npos)
157     return host;
158   size_t bracket = host.rfind(']');
159   if (bracket == std::string::npos || last_colon_pos > bracket)
160     return host.substr(0, last_colon_pos);
161   return host;
162 }
163 
IsIPAddress(const std::string & host)164 static bool IsIPAddress(const std::string& host) {
165   if (host.length() >= 4 && host.front() == '[' && host.back() == ']')
166     return true;
167   int quads = 0;
168   for (char c : host) {
169     if (c == '.')
170       quads++;
171     else if (!isdigit(c))
172       return false;
173   }
174   return quads == 3;
175 }
176 
177 // Constants for hybi-10 frame format.
178 
179 typedef int OpCode;
180 
181 const OpCode kOpCodeContinuation = 0x0;
182 const OpCode kOpCodeText = 0x1;
183 const OpCode kOpCodeBinary = 0x2;
184 const OpCode kOpCodeClose = 0x8;
185 const OpCode kOpCodePing = 0x9;
186 const OpCode kOpCodePong = 0xA;
187 
188 const unsigned char kFinalBit = 0x80;
189 const unsigned char kReserved1Bit = 0x40;
190 const unsigned char kReserved2Bit = 0x20;
191 const unsigned char kReserved3Bit = 0x10;
192 const unsigned char kOpCodeMask = 0xF;
193 const unsigned char kMaskBit = 0x80;
194 const unsigned char kPayloadLengthMask = 0x7F;
195 
196 const size_t kMaxSingleBytePayloadLength = 125;
197 const size_t kTwoBytePayloadLengthField = 126;
198 const size_t kEightBytePayloadLengthField = 127;
199 const size_t kMaskingKeyWidthInBytes = 4;
200 
encode_frame_hybi17(const std::vector<char> & message)201 static std::vector<char> encode_frame_hybi17(const std::vector<char>& message) {
202   std::vector<char> frame;
203   OpCode op_code = kOpCodeText;
204   frame.push_back(kFinalBit | op_code);
205   const size_t data_length = message.size();
206   if (data_length <= kMaxSingleBytePayloadLength) {
207     frame.push_back(static_cast<char>(data_length));
208   } else if (data_length <= 0xFFFF) {
209     frame.push_back(kTwoBytePayloadLengthField);
210     frame.push_back((data_length & 0xFF00) >> 8);
211     frame.push_back(data_length & 0xFF);
212   } else {
213     frame.push_back(kEightBytePayloadLengthField);
214     char extended_payload_length[8];
215     size_t remaining = data_length;
216     // Fill the length into extended_payload_length in the network byte order.
217     for (int i = 0; i < 8; ++i) {
218       extended_payload_length[7 - i] = remaining & 0xFF;
219       remaining >>= 8;
220     }
221     frame.insert(frame.end(), extended_payload_length,
222                  extended_payload_length + 8);
223     CHECK_EQ(0, remaining);
224   }
225   frame.insert(frame.end(), message.begin(), message.end());
226   return frame;
227 }
228 
decode_frame_hybi17(const std::vector<char> & buffer,bool client_frame,int * bytes_consumed,std::vector<char> * output,bool * compressed)229 static ws_decode_result decode_frame_hybi17(const std::vector<char>& buffer,
230                                             bool client_frame,
231                                             int* bytes_consumed,
232                                             std::vector<char>* output,
233                                             bool* compressed) {
234   *bytes_consumed = 0;
235   if (buffer.size() < 2)
236     return FRAME_INCOMPLETE;
237 
238   auto it = buffer.begin();
239 
240   unsigned char first_byte = *it++;
241   unsigned char second_byte = *it++;
242 
243   bool final = (first_byte & kFinalBit) != 0;
244   bool reserved1 = (first_byte & kReserved1Bit) != 0;
245   bool reserved2 = (first_byte & kReserved2Bit) != 0;
246   bool reserved3 = (first_byte & kReserved3Bit) != 0;
247   int op_code = first_byte & kOpCodeMask;
248   bool masked = (second_byte & kMaskBit) != 0;
249   *compressed = reserved1;
250   if (!final || reserved2 || reserved3)
251     return FRAME_ERROR;  // Only compression extension is supported.
252 
253   bool closed = false;
254   switch (op_code) {
255     case kOpCodeClose:
256       closed = true;
257       break;
258     case kOpCodeText:
259       break;
260     case kOpCodeBinary:        // We don't support binary frames yet.
261     case kOpCodeContinuation:  // We don't support binary frames yet.
262     case kOpCodePing:          // We don't support binary frames yet.
263     case kOpCodePong:          // We don't support binary frames yet.
264     default:
265       return FRAME_ERROR;
266   }
267 
268   // In Hybi-17 spec client MUST mask its frame.
269   if (client_frame && !masked) {
270     return FRAME_ERROR;
271   }
272 
273   uint64_t payload_length64 = second_byte & kPayloadLengthMask;
274   if (payload_length64 > kMaxSingleBytePayloadLength) {
275     int extended_payload_length_size;
276     if (payload_length64 == kTwoBytePayloadLengthField) {
277       extended_payload_length_size = 2;
278     } else if (payload_length64 == kEightBytePayloadLengthField) {
279       extended_payload_length_size = 8;
280     } else {
281       return FRAME_ERROR;
282     }
283     if ((buffer.end() - it) < extended_payload_length_size)
284       return FRAME_INCOMPLETE;
285     payload_length64 = 0;
286     for (int i = 0; i < extended_payload_length_size; ++i) {
287       payload_length64 <<= 8;
288       payload_length64 |= static_cast<unsigned char>(*it++);
289     }
290   }
291 
292   static const uint64_t max_payload_length = 0x7FFFFFFFFFFFFFFFull;
293   static const size_t max_length = SIZE_MAX;
294   if (payload_length64 > max_payload_length ||
295       payload_length64 > max_length - kMaskingKeyWidthInBytes) {
296     // WebSocket frame length too large.
297     return FRAME_ERROR;
298   }
299   size_t payload_length = static_cast<size_t>(payload_length64);
300 
301   if (buffer.size() - kMaskingKeyWidthInBytes < payload_length)
302     return FRAME_INCOMPLETE;
303 
304   std::vector<char>::const_iterator masking_key = it;
305   std::vector<char>::const_iterator payload = it + kMaskingKeyWidthInBytes;
306   for (size_t i = 0; i < payload_length; ++i)  // Unmask the payload.
307     output->insert(output->end(),
308                    payload[i] ^ masking_key[i % kMaskingKeyWidthInBytes]);
309 
310   size_t pos = it + kMaskingKeyWidthInBytes + payload_length - buffer.begin();
311   *bytes_consumed = pos;
312   return closed ? FRAME_CLOSE : FRAME_OK;
313 }
314 
315 // WS protocol
316 class WsHandler : public ProtocolHandler {
317  public:
WsHandler(InspectorSocket * inspector,TcpHolder::Pointer tcp)318   WsHandler(InspectorSocket* inspector, TcpHolder::Pointer tcp)
319             : ProtocolHandler(inspector, std::move(tcp)),
320               OnCloseSent(&WsHandler::WaitForCloseReply),
321               OnCloseReceived(&WsHandler::CloseFrameReceived),
322               dispose_(false) { }
323 
AcceptUpgrade(const std::string & accept_key)324   void AcceptUpgrade(const std::string& accept_key) override { }
CancelHandshake()325   void CancelHandshake() override {}
326 
OnEof()327   void OnEof() override {
328     tcp_.reset();
329     if (dispose_)
330       delete this;
331   }
332 
OnData(std::vector<char> * data)333   void OnData(std::vector<char>* data) override {
334     // 1. Parse.
335     int processed = 0;
336     do {
337       processed = ParseWsFrames(*data);
338       // 2. Fix the data size & length
339       if (processed > 0) {
340         remove_from_beginning(data, processed);
341       }
342     } while (processed > 0 && !data->empty());
343   }
344 
Write(const std::vector<char> data)345   void Write(const std::vector<char> data) override {
346     std::vector<char> output = encode_frame_hybi17(data);
347     WriteRaw(output, WriteRequest::Cleanup);
348   }
349 
350  protected:
Shutdown()351   void Shutdown() override {
352     if (tcp_) {
353       dispose_ = true;
354       SendClose();
355     } else {
356       delete this;
357     }
358   }
359 
360  private:
361   using Callback = void (WsHandler::*)();
362 
OnCloseFrameWritten(uv_write_t * req,int status)363   static void OnCloseFrameWritten(uv_write_t* req, int status) {
364     WriteRequest* wr = WriteRequest::from_write_req(req);
365     WsHandler* handler = static_cast<WsHandler*>(wr->handler);
366     delete wr;
367     Callback cb = handler->OnCloseSent;
368     (handler->*cb)();
369   }
370 
WaitForCloseReply()371   void WaitForCloseReply() {
372     OnCloseReceived = &WsHandler::OnEof;
373   }
374 
SendClose()375   void SendClose() {
376     WriteRaw(std::vector<char>(CLOSE_FRAME, CLOSE_FRAME + sizeof(CLOSE_FRAME)),
377              OnCloseFrameWritten);
378   }
379 
CloseFrameReceived()380   void CloseFrameReceived() {
381     OnCloseSent = &WsHandler::OnEof;
382     SendClose();
383   }
384 
ParseWsFrames(const std::vector<char> & buffer)385   int ParseWsFrames(const std::vector<char>& buffer) {
386     int bytes_consumed = 0;
387     std::vector<char> output;
388     bool compressed = false;
389 
390     ws_decode_result r =  decode_frame_hybi17(buffer,
391                                               true /* client_frame */,
392                                               &bytes_consumed, &output,
393                                               &compressed);
394     // Compressed frame means client is ignoring the headers and misbehaves
395     if (compressed || r == FRAME_ERROR) {
396       OnEof();
397       bytes_consumed = 0;
398     } else if (r == FRAME_CLOSE) {
399       (this->*OnCloseReceived)();
400       bytes_consumed = 0;
401     } else if (r == FRAME_OK) {
402       delegate()->OnWsFrame(output);
403     }
404     return bytes_consumed;
405   }
406 
407 
408   Callback OnCloseSent;
409   Callback OnCloseReceived;
410   bool dispose_;
411 };
412 
413 // HTTP protocol
414 class HttpEvent {
415  public:
HttpEvent(const std::string & path,bool upgrade,bool isGET,const std::string & ws_key,const std::string & host)416   HttpEvent(const std::string& path, bool upgrade, bool isGET,
417             const std::string& ws_key, const std::string& host)
418             : path(path), upgrade(upgrade), isGET(isGET), ws_key(ws_key),
419               host(host) { }
420 
421   std::string path;
422   bool upgrade;
423   bool isGET;
424   std::string ws_key;
425   std::string host;
426 };
427 
428 class HttpHandler : public ProtocolHandler {
429  public:
HttpHandler(InspectorSocket * inspector,TcpHolder::Pointer tcp)430   explicit HttpHandler(InspectorSocket* inspector, TcpHolder::Pointer tcp)
431                        : ProtocolHandler(inspector, std::move(tcp)),
432                          parsing_value_(false) {
433     llhttp_init(&parser_, HTTP_REQUEST, &parser_settings);
434     llhttp_settings_init(&parser_settings);
435     parser_settings.on_header_field = OnHeaderField;
436     parser_settings.on_header_value = OnHeaderValue;
437     parser_settings.on_message_complete = OnMessageComplete;
438     parser_settings.on_url = OnPath;
439   }
440 
AcceptUpgrade(const std::string & accept_key)441   void AcceptUpgrade(const std::string& accept_key) override {
442     char accept_string[ACCEPT_KEY_LENGTH];
443     generate_accept_string(accept_key, &accept_string);
444     const char accept_ws_prefix[] = "HTTP/1.1 101 Switching Protocols\r\n"
445                                     "Upgrade: websocket\r\n"
446                                     "Connection: Upgrade\r\n"
447                                     "Sec-WebSocket-Accept: ";
448     const char accept_ws_suffix[] = "\r\n\r\n";
449     std::vector<char> reply(accept_ws_prefix,
450                             accept_ws_prefix + sizeof(accept_ws_prefix) - 1);
451     reply.insert(reply.end(), accept_string,
452                  accept_string + sizeof(accept_string));
453     reply.insert(reply.end(), accept_ws_suffix,
454                  accept_ws_suffix + sizeof(accept_ws_suffix) - 1);
455     if (WriteRaw(reply, WriteRequest::Cleanup) >= 0) {
456       inspector_->SwitchProtocol(new WsHandler(inspector_, std::move(tcp_)));
457     } else {
458       tcp_.reset();
459     }
460   }
461 
CancelHandshake()462   void CancelHandshake() override {
463     const char HANDSHAKE_FAILED_RESPONSE[] =
464         "HTTP/1.0 400 Bad Request\r\n"
465         "Content-Type: text/html; charset=UTF-8\r\n\r\n"
466         "WebSockets request was expected\r\n";
467     WriteRaw(std::vector<char>(HANDSHAKE_FAILED_RESPONSE,
468              HANDSHAKE_FAILED_RESPONSE + sizeof(HANDSHAKE_FAILED_RESPONSE) - 1),
469              ThenCloseAndReportFailure);
470   }
471 
472 
OnEof()473   void OnEof() override {
474     tcp_.reset();
475   }
476 
OnData(std::vector<char> * data)477   void OnData(std::vector<char>* data) override {
478     llhttp_errno_t err;
479     err = llhttp_execute(&parser_, data->data(), data->size());
480 
481     if (err == HPE_PAUSED_UPGRADE) {
482       err = HPE_OK;
483       llhttp_resume_after_upgrade(&parser_);
484     }
485     data->clear();
486     if (err != HPE_OK) {
487       CancelHandshake();
488     }
489     // Event handling may delete *this
490     std::vector<HttpEvent> events;
491     std::swap(events, events_);
492     for (const HttpEvent& event : events) {
493       if (!IsAllowedHost(event.host) || !event.isGET) {
494         CancelHandshake();
495         return;
496       } else if (!event.upgrade) {
497         delegate()->OnHttpGet(event.host, event.path);
498       } else if (event.ws_key.empty()) {
499         CancelHandshake();
500         return;
501       } else {
502         delegate()->OnSocketUpgrade(event.host, event.path, event.ws_key);
503       }
504     }
505   }
506 
Write(const std::vector<char> data)507   void Write(const std::vector<char> data) override {
508     WriteRaw(data, WriteRequest::Cleanup);
509   }
510 
511  protected:
Shutdown()512   void Shutdown() override {
513     delete this;
514   }
515 
516  private:
ThenCloseAndReportFailure(uv_write_t * req,int status)517   static void ThenCloseAndReportFailure(uv_write_t* req, int status) {
518     ProtocolHandler* handler = WriteRequest::from_write_req(req)->handler;
519     WriteRequest::Cleanup(req, status);
520     handler->inspector()->SwitchProtocol(nullptr);
521   }
522 
OnHeaderValue(llhttp_t * parser,const char * at,size_t length)523   static int OnHeaderValue(llhttp_t* parser, const char* at, size_t length) {
524     HttpHandler* handler = From(parser);
525     handler->parsing_value_ = true;
526     handler->headers_[handler->current_header_].append(at, length);
527     return 0;
528   }
529 
OnHeaderField(llhttp_t * parser,const char * at,size_t length)530   static int OnHeaderField(llhttp_t* parser, const char* at, size_t length) {
531     HttpHandler* handler = From(parser);
532     if (handler->parsing_value_) {
533       handler->parsing_value_ = false;
534       handler->current_header_.clear();
535     }
536     handler->current_header_.append(at, length);
537     return 0;
538   }
539 
OnPath(llhttp_t * parser,const char * at,size_t length)540   static int OnPath(llhttp_t* parser, const char* at, size_t length) {
541     HttpHandler* handler = From(parser);
542     handler->path_.append(at, length);
543     return 0;
544   }
545 
From(llhttp_t * parser)546   static HttpHandler* From(llhttp_t* parser) {
547     return node::ContainerOf(&HttpHandler::parser_, parser);
548   }
549 
OnMessageComplete(llhttp_t * parser)550   static int OnMessageComplete(llhttp_t* parser) {
551     // Event needs to be fired after the parser is done.
552     HttpHandler* handler = From(parser);
553     handler->events_.emplace_back(handler->path_,
554                                   parser->upgrade,
555                                   parser->method == HTTP_GET,
556                                   handler->HeaderValue("Sec-WebSocket-Key"),
557                                   handler->HeaderValue("Host"));
558     handler->path_ = "";
559     handler->parsing_value_ = false;
560     handler->headers_.clear();
561     handler->current_header_ = "";
562     return 0;
563   }
564 
HeaderValue(const std::string & header) const565   std::string HeaderValue(const std::string& header) const {
566     bool header_found = false;
567     std::string value;
568     for (const auto& header_value : headers_) {
569       if (node::StringEqualNoCaseN(header_value.first.data(), header.data(),
570                                    header.length())) {
571         if (header_found)
572           return "";
573         value = header_value.second;
574         header_found = true;
575       }
576     }
577     return value;
578   }
579 
IsAllowedHost(const std::string & host_with_port) const580   bool IsAllowedHost(const std::string& host_with_port) const {
581     std::string host = TrimPort(host_with_port);
582     return host.empty() || IsIPAddress(host)
583            || node::StringEqualNoCase(host.data(), "localhost");
584   }
585 
586   bool parsing_value_;
587   llhttp_t parser_;
588   llhttp_settings_t parser_settings;
589   std::vector<HttpEvent> events_;
590   std::string current_header_;
591   std::map<std::string, std::string> headers_;
592   std::string path_;
593 };
594 
595 }  // namespace
596 
597 // Any protocol
ProtocolHandler(InspectorSocket * inspector,TcpHolder::Pointer tcp)598 ProtocolHandler::ProtocolHandler(InspectorSocket* inspector,
599                                  TcpHolder::Pointer tcp)
600                                  : inspector_(inspector), tcp_(std::move(tcp)) {
601   CHECK_NOT_NULL(tcp_);
602   tcp_->SetHandler(this);
603 }
604 
WriteRaw(const std::vector<char> & buffer,uv_write_cb write_cb)605 int ProtocolHandler::WriteRaw(const std::vector<char>& buffer,
606                               uv_write_cb write_cb) {
607   return tcp_->WriteRaw(buffer, write_cb);
608 }
609 
delegate()610 InspectorSocket::Delegate* ProtocolHandler::delegate() {
611   return tcp_->delegate();
612 }
613 
GetHost() const614 std::string ProtocolHandler::GetHost() const {
615   char ip[INET6_ADDRSTRLEN];
616   sockaddr_storage addr;
617   int len = sizeof(addr);
618   int err = uv_tcp_getsockname(tcp_->tcp(),
619                                reinterpret_cast<struct sockaddr*>(&addr),
620                                &len);
621   if (err != 0)
622     return "";
623   if (addr.ss_family == AF_INET6) {
624     const sockaddr_in6* v6 = reinterpret_cast<const sockaddr_in6*>(&addr);
625     err = uv_ip6_name(v6, ip, sizeof(ip));
626   } else {
627     const sockaddr_in* v4 = reinterpret_cast<const sockaddr_in*>(&addr);
628     err = uv_ip4_name(v4, ip, sizeof(ip));
629   }
630   if (err != 0)
631     return "";
632   return ip;
633 }
634 
635 // RAII uv_tcp_t wrapper
TcpHolder(InspectorSocket::DelegatePointer delegate)636 TcpHolder::TcpHolder(InspectorSocket::DelegatePointer delegate)
637                      : tcp_(),
638                        delegate_(std::move(delegate)),
639                        handler_(nullptr) { }
640 
641 // static
Accept(uv_stream_t * server,InspectorSocket::DelegatePointer delegate)642 TcpHolder::Pointer TcpHolder::Accept(
643     uv_stream_t* server,
644     InspectorSocket::DelegatePointer delegate) {
645   TcpHolder* result = new TcpHolder(std::move(delegate));
646   uv_stream_t* tcp = reinterpret_cast<uv_stream_t*>(&result->tcp_);
647   int err = uv_tcp_init(server->loop, &result->tcp_);
648   if (err == 0) {
649     err = uv_accept(server, tcp);
650   }
651   if (err == 0) {
652     err = uv_read_start(tcp, allocate_buffer, OnDataReceivedCb);
653   }
654   if (err == 0) {
655     return TcpHolder::Pointer(result);
656   } else {
657     delete result;
658     return nullptr;
659   }
660 }
661 
SetHandler(ProtocolHandler * handler)662 void TcpHolder::SetHandler(ProtocolHandler* handler) {
663   handler_ = handler;
664 }
665 
WriteRaw(const std::vector<char> & buffer,uv_write_cb write_cb)666 int TcpHolder::WriteRaw(const std::vector<char>& buffer, uv_write_cb write_cb) {
667 #if DUMP_WRITES
668   printf("%s (%ld bytes):\n", __FUNCTION__, buffer.size());
669   dump_hex(buffer.data(), buffer.size());
670   printf("\n");
671 #endif
672 
673   // Freed in write_request_cleanup
674   WriteRequest* wr = new WriteRequest(handler_, buffer);
675   uv_stream_t* stream = reinterpret_cast<uv_stream_t*>(&tcp_);
676   int err = uv_write(&wr->req, stream, &wr->buf, 1, write_cb);
677   if (err < 0)
678     delete wr;
679   return err < 0;
680 }
681 
delegate()682 InspectorSocket::Delegate* TcpHolder::delegate() {
683   return delegate_.get();
684 }
685 
686 // static
OnClosed(uv_handle_t * handle)687 void TcpHolder::OnClosed(uv_handle_t* handle) {
688   delete From(handle);
689 }
690 
OnDataReceivedCb(uv_stream_t * tcp,ssize_t nread,const uv_buf_t * buf)691 void TcpHolder::OnDataReceivedCb(uv_stream_t* tcp, ssize_t nread,
692                                  const uv_buf_t* buf) {
693 #if DUMP_READS
694   if (nread >= 0) {
695     printf("%s (%ld bytes)\n", __FUNCTION__, nread);
696     dump_hex(buf->base, nread);
697   } else {
698     printf("[%s:%d] %s\n", __FUNCTION__, __LINE__, uv_err_name(nread));
699   }
700 #endif
701   TcpHolder* holder = From(tcp);
702   holder->ReclaimUvBuf(buf, nread);
703   if (nread < 0 || nread == UV_EOF) {
704     holder->handler_->OnEof();
705   } else {
706     holder->handler_->OnData(&holder->buffer);
707   }
708 }
709 
710 // static
DisconnectAndDispose(TcpHolder * holder)711 void TcpHolder::DisconnectAndDispose(TcpHolder* holder) {
712   uv_handle_t* handle = reinterpret_cast<uv_handle_t*>(&holder->tcp_);
713   uv_close(handle, OnClosed);
714 }
715 
ReclaimUvBuf(const uv_buf_t * buf,ssize_t read)716 void TcpHolder::ReclaimUvBuf(const uv_buf_t* buf, ssize_t read) {
717   if (read > 0) {
718     buffer.insert(buffer.end(), buf->base, buf->base + read);
719   }
720   delete[] buf->base;
721 }
722 
723 InspectorSocket::~InspectorSocket() = default;
724 
725 // static
Shutdown(ProtocolHandler * handler)726 void InspectorSocket::Shutdown(ProtocolHandler* handler) {
727   handler->Shutdown();
728 }
729 
730 // static
Accept(uv_stream_t * server,DelegatePointer delegate)731 InspectorSocket::Pointer InspectorSocket::Accept(uv_stream_t* server,
732                                                  DelegatePointer delegate) {
733   auto tcp = TcpHolder::Accept(server, std::move(delegate));
734   if (tcp) {
735     InspectorSocket* inspector = new InspectorSocket();
736     inspector->SwitchProtocol(new HttpHandler(inspector, std::move(tcp)));
737     return InspectorSocket::Pointer(inspector);
738   } else {
739     return InspectorSocket::Pointer(nullptr);
740   }
741 }
742 
AcceptUpgrade(const std::string & ws_key)743 void InspectorSocket::AcceptUpgrade(const std::string& ws_key) {
744   protocol_handler_->AcceptUpgrade(ws_key);
745 }
746 
CancelHandshake()747 void InspectorSocket::CancelHandshake() {
748   protocol_handler_->CancelHandshake();
749 }
750 
GetHost()751 std::string InspectorSocket::GetHost() {
752   return protocol_handler_->GetHost();
753 }
754 
SwitchProtocol(ProtocolHandler * handler)755 void InspectorSocket::SwitchProtocol(ProtocolHandler* handler) {
756   protocol_handler_.reset(std::move(handler));
757 }
758 
Write(const char * data,size_t len)759 void InspectorSocket::Write(const char* data, size_t len) {
760   protocol_handler_->Write(std::vector<char>(data, data + len));
761 }
762 
763 }  // namespace inspector
764 }  // namespace node
765