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