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