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