• 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   if (host.front() == '0') return false;
168   uint_fast16_t accum = 0;
169   uint_fast8_t quads = 0;
170   bool empty = true;
171   auto endOctet = [&accum, &quads, &empty](bool final = false) {
172     return !empty && accum <= 0xff && ++quads <= 4 && final == (quads == 4) &&
173            (empty = true) && !(accum = 0);
174   };
175   for (char c : host) {
176     if (isdigit(c)) {
177       if ((accum = (accum * 10) + (c - '0')) > 0xff) return false;
178       empty = false;
179     } else if (c != '.' || !endOctet()) {
180       return false;
181     }
182   }
183   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 
encode_frame_hybi17(const std::vector<char> & message)210 static std::vector<char> encode_frame_hybi17(const std::vector<char>& message) {
211   std::vector<char> frame;
212   OpCode op_code = kOpCodeText;
213   frame.push_back(kFinalBit | op_code);
214   const size_t data_length = message.size();
215   if (data_length <= kMaxSingleBytePayloadLength) {
216     frame.push_back(static_cast<char>(data_length));
217   } else if (data_length <= 0xFFFF) {
218     frame.push_back(kTwoBytePayloadLengthField);
219     frame.push_back((data_length & 0xFF00) >> 8);
220     frame.push_back(data_length & 0xFF);
221   } else {
222     frame.push_back(kEightBytePayloadLengthField);
223     char extended_payload_length[8];
224     size_t remaining = data_length;
225     // Fill the length into extended_payload_length in the network byte order.
226     for (int i = 0; i < 8; ++i) {
227       extended_payload_length[7 - i] = remaining & 0xFF;
228       remaining >>= 8;
229     }
230     frame.insert(frame.end(), extended_payload_length,
231                  extended_payload_length + 8);
232     CHECK_EQ(0, remaining);
233   }
234   frame.insert(frame.end(), message.begin(), message.end());
235   return frame;
236 }
237 
decode_frame_hybi17(const std::vector<char> & buffer,bool client_frame,int * bytes_consumed,std::vector<char> * output,bool * compressed)238 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   *bytes_consumed = 0;
244   if (buffer.size() < 2)
245     return FRAME_INCOMPLETE;
246 
247   auto it = buffer.begin();
248 
249   unsigned char first_byte = *it++;
250   unsigned char second_byte = *it++;
251 
252   bool final = (first_byte & kFinalBit) != 0;
253   bool reserved1 = (first_byte & kReserved1Bit) != 0;
254   bool reserved2 = (first_byte & kReserved2Bit) != 0;
255   bool reserved3 = (first_byte & kReserved3Bit) != 0;
256   int op_code = first_byte & kOpCodeMask;
257   bool masked = (second_byte & kMaskBit) != 0;
258   *compressed = reserved1;
259   if (!final || reserved2 || reserved3)
260     return FRAME_ERROR;  // Only compression extension is supported.
261 
262   bool closed = false;
263   switch (op_code) {
264     case kOpCodeClose:
265       closed = true;
266       break;
267     case kOpCodeText:
268       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   if (client_frame && !masked) {
279     return FRAME_ERROR;
280   }
281 
282   uint64_t payload_length64 = second_byte & kPayloadLengthMask;
283   if (payload_length64 > kMaxSingleBytePayloadLength) {
284     int extended_payload_length_size;
285     if (payload_length64 == kTwoBytePayloadLengthField) {
286       extended_payload_length_size = 2;
287     } else if (payload_length64 == kEightBytePayloadLengthField) {
288       extended_payload_length_size = 8;
289     } else {
290       return FRAME_ERROR;
291     }
292     if ((buffer.end() - it) < extended_payload_length_size)
293       return FRAME_INCOMPLETE;
294     payload_length64 = 0;
295     for (int i = 0; i < extended_payload_length_size; ++i) {
296       payload_length64 <<= 8;
297       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   if (payload_length64 > max_payload_length ||
304       payload_length64 > max_length - kMaskingKeyWidthInBytes) {
305     // WebSocket frame length too large.
306     return FRAME_ERROR;
307   }
308   size_t payload_length = static_cast<size_t>(payload_length64);
309 
310   if (buffer.size() - kMaskingKeyWidthInBytes < payload_length)
311     return FRAME_INCOMPLETE;
312 
313   std::vector<char>::const_iterator masking_key = it;
314   std::vector<char>::const_iterator payload = it + kMaskingKeyWidthInBytes;
315   for (size_t i = 0; i < payload_length; ++i)  // Unmask the payload.
316     output->insert(output->end(),
317                    payload[i] ^ masking_key[i % kMaskingKeyWidthInBytes]);
318 
319   size_t pos = it + kMaskingKeyWidthInBytes + payload_length - buffer.begin();
320   *bytes_consumed = pos;
321   return closed ? FRAME_CLOSE : FRAME_OK;
322 }
323 
324 // WS protocol
325 class WsHandler : public ProtocolHandler {
326  public:
WsHandler(InspectorSocket * inspector,TcpHolder::Pointer tcp)327   WsHandler(InspectorSocket* inspector, TcpHolder::Pointer tcp)
328             : ProtocolHandler(inspector, std::move(tcp)),
329               OnCloseSent(&WsHandler::WaitForCloseReply),
330               OnCloseReceived(&WsHandler::CloseFrameReceived),
331               dispose_(false) { }
332 
AcceptUpgrade(const std::string & accept_key)333   void AcceptUpgrade(const std::string& accept_key) override { }
CancelHandshake()334   void CancelHandshake() override {}
335 
OnEof()336   void OnEof() override {
337     tcp_.reset();
338     if (dispose_)
339       delete this;
340   }
341 
OnData(std::vector<char> * data)342   void OnData(std::vector<char>* data) override {
343     // 1. Parse.
344     int processed = 0;
345     do {
346       processed = ParseWsFrames(*data);
347       // 2. Fix the data size & length
348       if (processed > 0) {
349         remove_from_beginning(data, processed);
350       }
351     } while (processed > 0 && !data->empty());
352   }
353 
Write(const std::vector<char> data)354   void Write(const std::vector<char> data) override {
355     std::vector<char> output = encode_frame_hybi17(data);
356     WriteRaw(output, WriteRequest::Cleanup);
357   }
358 
359  protected:
Shutdown()360   void Shutdown() override {
361     if (tcp_) {
362       dispose_ = true;
363       SendClose();
364     } else {
365       delete this;
366     }
367   }
368 
369  private:
370   using Callback = void (WsHandler::*)();
371 
OnCloseFrameWritten(uv_write_t * req,int status)372   static void OnCloseFrameWritten(uv_write_t* req, int status) {
373     WriteRequest* wr = WriteRequest::from_write_req(req);
374     WsHandler* handler = static_cast<WsHandler*>(wr->handler);
375     delete wr;
376     Callback cb = handler->OnCloseSent;
377     (handler->*cb)();
378   }
379 
WaitForCloseReply()380   void WaitForCloseReply() {
381     OnCloseReceived = &WsHandler::OnEof;
382   }
383 
SendClose()384   void SendClose() {
385     WriteRaw(std::vector<char>(CLOSE_FRAME, CLOSE_FRAME + sizeof(CLOSE_FRAME)),
386              OnCloseFrameWritten);
387   }
388 
CloseFrameReceived()389   void CloseFrameReceived() {
390     OnCloseSent = &WsHandler::OnEof;
391     SendClose();
392   }
393 
ParseWsFrames(const std::vector<char> & buffer)394   int ParseWsFrames(const std::vector<char>& buffer) {
395     int bytes_consumed = 0;
396     std::vector<char> output;
397     bool compressed = false;
398 
399     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     if (compressed || r == FRAME_ERROR) {
405       OnEof();
406       bytes_consumed = 0;
407     } else if (r == FRAME_CLOSE) {
408       (this->*OnCloseReceived)();
409       bytes_consumed = 0;
410     } else if (r == FRAME_OK) {
411       delegate()->OnWsFrame(output);
412     }
413     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:
HttpEvent(const std::string & path,bool upgrade,bool isGET,const std::string & ws_key,const std::string & host)425   HttpEvent(const std::string& path, bool upgrade, bool isGET,
426             const std::string& ws_key, const std::string& host)
427             : path(path), upgrade(upgrade), isGET(isGET), ws_key(ws_key),
428               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:
HttpHandler(InspectorSocket * inspector,TcpHolder::Pointer tcp)439   explicit HttpHandler(InspectorSocket* inspector, TcpHolder::Pointer tcp)
440                        : ProtocolHandler(inspector, std::move(tcp)),
441                          parsing_value_(false) {
442     llhttp_init(&parser_, HTTP_REQUEST, &parser_settings);
443     llhttp_settings_init(&parser_settings);
444     parser_settings.on_header_field = OnHeaderField;
445     parser_settings.on_header_value = OnHeaderValue;
446     parser_settings.on_message_complete = OnMessageComplete;
447     parser_settings.on_url = OnPath;
448   }
449 
AcceptUpgrade(const std::string & accept_key)450   void AcceptUpgrade(const std::string& accept_key) override {
451     char accept_string[ACCEPT_KEY_LENGTH];
452     generate_accept_string(accept_key, &accept_string);
453     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     const char accept_ws_suffix[] = "\r\n\r\n";
458     std::vector<char> reply(accept_ws_prefix,
459                             accept_ws_prefix + sizeof(accept_ws_prefix) - 1);
460     reply.insert(reply.end(), accept_string,
461                  accept_string + sizeof(accept_string));
462     reply.insert(reply.end(), accept_ws_suffix,
463                  accept_ws_suffix + sizeof(accept_ws_suffix) - 1);
464     if (WriteRaw(reply, WriteRequest::Cleanup) >= 0) {
465       inspector_->SwitchProtocol(new WsHandler(inspector_, std::move(tcp_)));
466     } else {
467       tcp_.reset();
468     }
469   }
470 
CancelHandshake()471   void CancelHandshake() override {
472     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     WriteRaw(std::vector<char>(HANDSHAKE_FAILED_RESPONSE,
477              HANDSHAKE_FAILED_RESPONSE + sizeof(HANDSHAKE_FAILED_RESPONSE) - 1),
478              ThenCloseAndReportFailure);
479   }
480 
481 
OnEof()482   void OnEof() override {
483     tcp_.reset();
484   }
485 
OnData(std::vector<char> * data)486   void OnData(std::vector<char>* data) override {
487     llhttp_errno_t err;
488     err = llhttp_execute(&parser_, data->data(), data->size());
489 
490     if (err == HPE_PAUSED_UPGRADE) {
491       err = HPE_OK;
492       llhttp_resume_after_upgrade(&parser_);
493     }
494     data->clear();
495     if (err != HPE_OK) {
496       CancelHandshake();
497     }
498     // Event handling may delete *this
499     std::vector<HttpEvent> events;
500     std::swap(events, events_);
501     for (const HttpEvent& event : events) {
502       if (!IsAllowedHost(event.host) || !event.isGET) {
503         CancelHandshake();
504         return;
505       } else if (!event.upgrade) {
506         delegate()->OnHttpGet(event.host, event.path);
507       } else if (event.ws_key.empty()) {
508         CancelHandshake();
509         return;
510       } else {
511         delegate()->OnSocketUpgrade(event.host, event.path, event.ws_key);
512       }
513     }
514   }
515 
Write(const std::vector<char> data)516   void Write(const std::vector<char> data) override {
517     WriteRaw(data, WriteRequest::Cleanup);
518   }
519 
520  protected:
Shutdown()521   void Shutdown() override {
522     delete this;
523   }
524 
525  private:
ThenCloseAndReportFailure(uv_write_t * req,int status)526   static void ThenCloseAndReportFailure(uv_write_t* req, int status) {
527     ProtocolHandler* handler = WriteRequest::from_write_req(req)->handler;
528     WriteRequest::Cleanup(req, status);
529     handler->inspector()->SwitchProtocol(nullptr);
530   }
531 
OnHeaderValue(llhttp_t * parser,const char * at,size_t length)532   static int OnHeaderValue(llhttp_t* parser, const char* at, size_t length) {
533     HttpHandler* handler = From(parser);
534     handler->parsing_value_ = true;
535     handler->headers_[handler->current_header_].append(at, length);
536     return 0;
537   }
538 
OnHeaderField(llhttp_t * parser,const char * at,size_t length)539   static int OnHeaderField(llhttp_t* parser, const char* at, size_t length) {
540     HttpHandler* handler = From(parser);
541     if (handler->parsing_value_) {
542       handler->parsing_value_ = false;
543       handler->current_header_.clear();
544     }
545     handler->current_header_.append(at, length);
546     return 0;
547   }
548 
OnPath(llhttp_t * parser,const char * at,size_t length)549   static int OnPath(llhttp_t* parser, const char* at, size_t length) {
550     HttpHandler* handler = From(parser);
551     handler->path_.append(at, length);
552     return 0;
553   }
554 
From(llhttp_t * parser)555   static HttpHandler* From(llhttp_t* parser) {
556     return node::ContainerOf(&HttpHandler::parser_, parser);
557   }
558 
OnMessageComplete(llhttp_t * parser)559   static int OnMessageComplete(llhttp_t* parser) {
560     // Event needs to be fired after the parser is done.
561     HttpHandler* handler = From(parser);
562     handler->events_.emplace_back(handler->path_,
563                                   parser->upgrade,
564                                   parser->method == HTTP_GET,
565                                   handler->HeaderValue("Sec-WebSocket-Key"),
566                                   handler->HeaderValue("Host"));
567     handler->path_ = "";
568     handler->parsing_value_ = false;
569     handler->headers_.clear();
570     handler->current_header_ = "";
571     return 0;
572   }
573 
HeaderValue(const std::string & header) const574   std::string HeaderValue(const std::string& header) const {
575     bool header_found = false;
576     std::string value;
577     for (const auto& header_value : headers_) {
578       if (node::StringEqualNoCaseN(header_value.first.data(), header.data(),
579                                    header.length())) {
580         if (header_found)
581           return "";
582         value = header_value.second;
583         header_found = true;
584       }
585     }
586     return value;
587   }
588 
IsAllowedHost(const std::string & host_with_port) const589   bool IsAllowedHost(const std::string& host_with_port) const {
590     std::string host = TrimPort(host_with_port);
591     return host.empty() || IsIPAddress(host)
592            || 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
ProtocolHandler(InspectorSocket * inspector,TcpHolder::Pointer tcp)607 ProtocolHandler::ProtocolHandler(InspectorSocket* inspector,
608                                  TcpHolder::Pointer tcp)
609                                  : inspector_(inspector), tcp_(std::move(tcp)) {
610   CHECK_NOT_NULL(tcp_);
611   tcp_->SetHandler(this);
612 }
613 
WriteRaw(const std::vector<char> & buffer,uv_write_cb write_cb)614 int ProtocolHandler::WriteRaw(const std::vector<char>& buffer,
615                               uv_write_cb write_cb) {
616   return tcp_->WriteRaw(buffer, write_cb);
617 }
618 
delegate()619 InspectorSocket::Delegate* ProtocolHandler::delegate() {
620   return tcp_->delegate();
621 }
622 
GetHost() const623 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
TcpHolder(InspectorSocket::DelegatePointer delegate)645 TcpHolder::TcpHolder(InspectorSocket::DelegatePointer delegate)
646                      : tcp_(),
647                        delegate_(std::move(delegate)),
648                        handler_(nullptr) { }
649 
650 // static
Accept(uv_stream_t * server,InspectorSocket::DelegatePointer delegate)651 TcpHolder::Pointer TcpHolder::Accept(
652     uv_stream_t* server,
653     InspectorSocket::DelegatePointer delegate) {
654   TcpHolder* result = new TcpHolder(std::move(delegate));
655   uv_stream_t* tcp = reinterpret_cast<uv_stream_t*>(&result->tcp_);
656   int err = uv_tcp_init(server->loop, &result->tcp_);
657   if (err == 0) {
658     err = uv_accept(server, tcp);
659   }
660   if (err == 0) {
661     err = uv_read_start(tcp, allocate_buffer, OnDataReceivedCb);
662   }
663   if (err == 0) {
664     return TcpHolder::Pointer(result);
665   } else {
666     delete result;
667     return nullptr;
668   }
669 }
670 
SetHandler(ProtocolHandler * handler)671 void TcpHolder::SetHandler(ProtocolHandler* handler) {
672   handler_ = handler;
673 }
674 
WriteRaw(const std::vector<char> & buffer,uv_write_cb write_cb)675 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   WriteRequest* wr = new WriteRequest(handler_, buffer);
684   uv_stream_t* stream = reinterpret_cast<uv_stream_t*>(&tcp_);
685   int err = uv_write(&wr->req, stream, &wr->buf, 1, write_cb);
686   if (err < 0)
687     delete wr;
688   return err < 0;
689 }
690 
delegate()691 InspectorSocket::Delegate* TcpHolder::delegate() {
692   return delegate_.get();
693 }
694 
695 // static
OnClosed(uv_handle_t * handle)696 void TcpHolder::OnClosed(uv_handle_t* handle) {
697   delete From(handle);
698 }
699 
OnDataReceivedCb(uv_stream_t * tcp,ssize_t nread,const uv_buf_t * buf)700 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   TcpHolder* holder = From(tcp);
711   holder->ReclaimUvBuf(buf, nread);
712   if (nread < 0 || nread == UV_EOF) {
713     holder->handler_->OnEof();
714   } else {
715     holder->handler_->OnData(&holder->buffer);
716   }
717 }
718 
719 // static
DisconnectAndDispose(TcpHolder * holder)720 void TcpHolder::DisconnectAndDispose(TcpHolder* holder) {
721   uv_handle_t* handle = reinterpret_cast<uv_handle_t*>(&holder->tcp_);
722   uv_close(handle, OnClosed);
723 }
724 
ReclaimUvBuf(const uv_buf_t * buf,ssize_t read)725 void TcpHolder::ReclaimUvBuf(const uv_buf_t* buf, ssize_t read) {
726   if (read > 0) {
727     buffer.insert(buffer.end(), buf->base, buf->base + read);
728   }
729   delete[] buf->base;
730 }
731 
732 InspectorSocket::~InspectorSocket() = default;
733 
734 // static
Shutdown(ProtocolHandler * handler)735 void InspectorSocket::Shutdown(ProtocolHandler* handler) {
736   handler->Shutdown();
737 }
738 
739 // static
Accept(uv_stream_t * server,DelegatePointer delegate)740 InspectorSocket::Pointer InspectorSocket::Accept(uv_stream_t* server,
741                                                  DelegatePointer delegate) {
742   auto tcp = TcpHolder::Accept(server, std::move(delegate));
743   if (tcp) {
744     InspectorSocket* inspector = new InspectorSocket();
745     inspector->SwitchProtocol(new HttpHandler(inspector, std::move(tcp)));
746     return InspectorSocket::Pointer(inspector);
747   } else {
748     return InspectorSocket::Pointer(nullptr);
749   }
750 }
751 
AcceptUpgrade(const std::string & ws_key)752 void InspectorSocket::AcceptUpgrade(const std::string& ws_key) {
753   protocol_handler_->AcceptUpgrade(ws_key);
754 }
755 
CancelHandshake()756 void InspectorSocket::CancelHandshake() {
757   protocol_handler_->CancelHandshake();
758 }
759 
GetHost()760 std::string InspectorSocket::GetHost() {
761   return protocol_handler_->GetHost();
762 }
763 
SwitchProtocol(ProtocolHandler * handler)764 void InspectorSocket::SwitchProtocol(ProtocolHandler* handler) {
765   protocol_handler_.reset(std::move(handler));
766 }
767 
Write(const char * data,size_t len)768 void InspectorSocket::Write(const char* data, size_t len) {
769   protocol_handler_->Write(std::vector<char>(data, data + len));
770 }
771 
772 }  // namespace inspector
773 }  // namespace node
774