Node.js  v8.x
Node.js is a JavaScript runtime built on Chrome's V8 JavaScript engine
inspector_socket.cc
Go to the documentation of this file.
1 #include "inspector_socket.h"
2 #include "util.h"
3 #include "util-inl.h"
4 
5 #define NODE_WANT_INTERNALS 1
6 #include "base64.h"
7 
8 #include "openssl/sha.h" // Sha-1 hash
9 
10 #include <string.h>
11 #include <vector>
12 
13 #define ACCEPT_KEY_LENGTH base64_encoded_size(20)
14 #define BUFFER_GROWTH_CHUNK_SIZE 1024
15 
16 #define DUMP_READS 0
17 #define DUMP_WRITES 0
18 
19 namespace node {
20 namespace inspector {
21 
22 static const char CLOSE_FRAME[] = {'\x88', '\x00'};
23 
26 };
27 
28 #if DUMP_READS || DUMP_WRITES
29 static void dump_hex(const char* buf, size_t len) {
30  const char* ptr = buf;
31  const char* end = ptr + len;
32  const char* cptr;
33  char c;
34  int i;
35 
36  while (ptr < end) {
37  cptr = ptr;
38  for (i = 0; i < 16 && ptr < end; i++) {
39  printf("%2.2X ", static_cast<unsigned char>(*(ptr++)));
40  }
41  for (i = 72 - (i * 4); i > 0; i--) {
42  printf(" ");
43  }
44  for (i = 0; i < 16 && cptr < end; i++) {
45  c = *(cptr++);
46  printf("%c", (c > 0x19) ? c : '.');
47  }
48  printf("\n");
49  }
50  printf("\n\n");
51 }
52 #endif
53 
54 static void remove_from_beginning(std::vector<char>* buffer, size_t count) {
55  buffer->erase(buffer->begin(), buffer->begin() + count);
56 }
57 
58 static void dispose_inspector(uv_handle_t* handle) {
59  InspectorSocket* inspector = inspector_from_stream(handle);
60  inspector_cb close =
61  inspector->ws_mode ? inspector->ws_state->close_cb : nullptr;
62  inspector->buffer.clear();
63  delete inspector->ws_state;
64  inspector->ws_state = nullptr;
65  if (close) {
66  close(inspector, 0);
67  }
68 }
69 
70 static void close_connection(InspectorSocket* inspector) {
71  uv_handle_t* socket = reinterpret_cast<uv_handle_t*>(&inspector->tcp);
72  if (!uv_is_closing(socket)) {
73  uv_read_stop(reinterpret_cast<uv_stream_t*>(socket));
74  uv_close(socket, dispose_inspector);
75  }
76 }
77 
78 struct WriteRequest {
79  WriteRequest(InspectorSocket* inspector, const char* data, size_t size)
80  : inspector(inspector)
81  , storage(data, data + size)
82  , buf(uv_buf_init(&storage[0], storage.size())) {}
83 
84  static WriteRequest* from_write_req(uv_write_t* req) {
85  return node::ContainerOf(&WriteRequest::req, req);
86  }
87 
89  std::vector<char> storage;
90  uv_write_t req;
91  uv_buf_t buf;
92 };
93 
94 // Cleanup
95 static void write_request_cleanup(uv_write_t* req, int status) {
96  delete WriteRequest::from_write_req(req);
97 }
98 
99 static int write_to_client(InspectorSocket* inspector,
100  const char* msg,
101  size_t len,
102  uv_write_cb write_cb = write_request_cleanup) {
103 #if DUMP_WRITES
104  printf("%s (%ld bytes):\n", __FUNCTION__, len);
105  dump_hex(msg, len);
106 #endif
107 
108  // Freed in write_request_cleanup
109  WriteRequest* wr = new WriteRequest(inspector, msg, len);
110  uv_stream_t* stream = reinterpret_cast<uv_stream_t*>(&inspector->tcp);
111  return uv_write(&wr->req, stream, &wr->buf, 1, write_cb) < 0;
112 }
113 
114 // Constants for hybi-10 frame format.
115 
116 typedef int OpCode;
117 
118 const OpCode kOpCodeContinuation = 0x0;
119 const OpCode kOpCodeText = 0x1;
120 const OpCode kOpCodeBinary = 0x2;
121 const OpCode kOpCodeClose = 0x8;
122 const OpCode kOpCodePing = 0x9;
123 const OpCode kOpCodePong = 0xA;
124 
125 const unsigned char kFinalBit = 0x80;
126 const unsigned char kReserved1Bit = 0x40;
127 const unsigned char kReserved2Bit = 0x20;
128 const unsigned char kReserved3Bit = 0x10;
129 const unsigned char kOpCodeMask = 0xF;
130 const unsigned char kMaskBit = 0x80;
131 const unsigned char kPayloadLengthMask = 0x7F;
132 
133 const size_t kMaxSingleBytePayloadLength = 125;
134 const size_t kTwoBytePayloadLengthField = 126;
135 const size_t kEightBytePayloadLengthField = 127;
136 const size_t kMaskingKeyWidthInBytes = 4;
137 
138 static std::vector<char> encode_frame_hybi17(const char* message,
139  size_t data_length) {
140  std::vector<char> frame;
141  OpCode op_code = kOpCodeText;
142  frame.push_back(kFinalBit | op_code);
143  if (data_length <= kMaxSingleBytePayloadLength) {
144  frame.push_back(static_cast<char>(data_length));
145  } else if (data_length <= 0xFFFF) {
146  frame.push_back(kTwoBytePayloadLengthField);
147  frame.push_back((data_length & 0xFF00) >> 8);
148  frame.push_back(data_length & 0xFF);
149  } else {
150  frame.push_back(kEightBytePayloadLengthField);
151  char extended_payload_length[8];
152  size_t remaining = data_length;
153  // Fill the length into extended_payload_length in the network byte order.
154  for (int i = 0; i < 8; ++i) {
155  extended_payload_length[7 - i] = remaining & 0xFF;
156  remaining >>= 8;
157  }
158  frame.insert(frame.end(), extended_payload_length,
159  extended_payload_length + 8);
160  CHECK_EQ(0, remaining);
161  }
162  frame.insert(frame.end(), message, message + data_length);
163  return frame;
164 }
165 
166 static ws_decode_result decode_frame_hybi17(const std::vector<char>& buffer,
167  bool client_frame,
168  int* bytes_consumed,
169  std::vector<char>* output,
170  bool* compressed) {
171  *bytes_consumed = 0;
172  if (buffer.size() < 2)
173  return FRAME_INCOMPLETE;
174 
175  auto it = buffer.begin();
176 
177  unsigned char first_byte = *it++;
178  unsigned char second_byte = *it++;
179 
180  bool final = (first_byte & kFinalBit) != 0;
181  bool reserved1 = (first_byte & kReserved1Bit) != 0;
182  bool reserved2 = (first_byte & kReserved2Bit) != 0;
183  bool reserved3 = (first_byte & kReserved3Bit) != 0;
184  int op_code = first_byte & kOpCodeMask;
185  bool masked = (second_byte & kMaskBit) != 0;
186  *compressed = reserved1;
187  if (!final || reserved2 || reserved3)
188  return FRAME_ERROR; // Only compression extension is supported.
189 
190  bool closed = false;
191  switch (op_code) {
192  case kOpCodeClose:
193  closed = true;
194  break;
195  case kOpCodeText:
196  break;
197  case kOpCodeBinary: // We don't support binary frames yet.
198  case kOpCodeContinuation: // We don't support binary frames yet.
199  case kOpCodePing: // We don't support binary frames yet.
200  case kOpCodePong: // We don't support binary frames yet.
201  default:
202  return FRAME_ERROR;
203  }
204 
205  // In Hybi-17 spec client MUST mask its frame.
206  if (client_frame && !masked) {
207  return FRAME_ERROR;
208  }
209 
210  uint64_t payload_length64 = second_byte & kPayloadLengthMask;
211  if (payload_length64 > kMaxSingleBytePayloadLength) {
212  int extended_payload_length_size;
213  if (payload_length64 == kTwoBytePayloadLengthField) {
214  extended_payload_length_size = 2;
215  } else if (payload_length64 == kEightBytePayloadLengthField) {
216  extended_payload_length_size = 8;
217  } else {
218  return FRAME_ERROR;
219  }
220  if ((buffer.end() - it) < extended_payload_length_size)
221  return FRAME_INCOMPLETE;
222  payload_length64 = 0;
223  for (int i = 0; i < extended_payload_length_size; ++i) {
224  payload_length64 <<= 8;
225  payload_length64 |= static_cast<unsigned char>(*it++);
226  }
227  }
228 
229  static const uint64_t max_payload_length = 0x7FFFFFFFFFFFFFFFull;
230  static const size_t max_length = SIZE_MAX;
231  if (payload_length64 > max_payload_length ||
232  payload_length64 > max_length - kMaskingKeyWidthInBytes) {
233  // WebSocket frame length too large.
234  return FRAME_ERROR;
235  }
236  size_t payload_length = static_cast<size_t>(payload_length64);
237 
238  if (buffer.size() - kMaskingKeyWidthInBytes < payload_length)
239  return FRAME_INCOMPLETE;
240 
241  std::vector<char>::const_iterator masking_key = it;
242  std::vector<char>::const_iterator payload = it + kMaskingKeyWidthInBytes;
243  for (size_t i = 0; i < payload_length; ++i) // Unmask the payload.
244  output->insert(output->end(),
245  payload[i] ^ masking_key[i % kMaskingKeyWidthInBytes]);
246 
247  size_t pos = it + kMaskingKeyWidthInBytes + payload_length - buffer.begin();
248  *bytes_consumed = pos;
249  return closed ? FRAME_CLOSE : FRAME_OK;
250 }
251 
252 static void invoke_read_callback(InspectorSocket* inspector,
253  int status, const uv_buf_t* buf) {
254  if (inspector->ws_state->read_cb) {
255  inspector->ws_state->read_cb(
256  reinterpret_cast<uv_stream_t*>(&inspector->tcp), status, buf);
257  }
258 }
259 
260 static void shutdown_complete(InspectorSocket* inspector) {
261  close_connection(inspector);
262 }
263 
264 static void on_close_frame_written(uv_write_t* req, int status) {
266  InspectorSocket* inspector = wr->inspector;
267  delete wr;
268  inspector->ws_state->close_sent = true;
269  if (inspector->ws_state->received_close) {
270  shutdown_complete(inspector);
271  }
272 }
273 
274 static void close_frame_received(InspectorSocket* inspector) {
275  inspector->ws_state->received_close = true;
276  if (!inspector->ws_state->close_sent) {
277  invoke_read_callback(inspector, 0, 0);
278  write_to_client(inspector, CLOSE_FRAME, sizeof(CLOSE_FRAME),
279  on_close_frame_written);
280  } else {
281  shutdown_complete(inspector);
282  }
283 }
284 
285 static int parse_ws_frames(InspectorSocket* inspector) {
286  int bytes_consumed = 0;
287  std::vector<char> output;
288  bool compressed = false;
289 
290  ws_decode_result r = decode_frame_hybi17(inspector->buffer,
291  true /* client_frame */,
292  &bytes_consumed, &output,
293  &compressed);
294  // Compressed frame means client is ignoring the headers and misbehaves
295  if (compressed || r == FRAME_ERROR) {
296  invoke_read_callback(inspector, UV_EPROTO, nullptr);
297  close_connection(inspector);
298  bytes_consumed = 0;
299  } else if (r == FRAME_CLOSE) {
300  close_frame_received(inspector);
301  bytes_consumed = 0;
302  } else if (r == FRAME_OK && inspector->ws_state->alloc_cb
303  && inspector->ws_state->read_cb) {
304  uv_buf_t buffer;
305  size_t len = output.size();
306  inspector->ws_state->alloc_cb(
307  reinterpret_cast<uv_handle_t*>(&inspector->tcp),
308  len, &buffer);
309  CHECK_GE(buffer.len, len);
310  memcpy(buffer.base, &output[0], len);
311  invoke_read_callback(inspector, len, &buffer);
312  }
313  return bytes_consumed;
314 }
315 
316 static void prepare_buffer(uv_handle_t* stream, size_t len, uv_buf_t* buf) {
317  *buf = uv_buf_init(new char[len], len);
318 }
319 
320 static void reclaim_uv_buf(InspectorSocket* inspector, const uv_buf_t* buf,
321  ssize_t read) {
322  if (read > 0) {
323  std::vector<char>& buffer = inspector->buffer;
324  buffer.insert(buffer.end(), buf->base, buf->base + read);
325  }
326  delete[] buf->base;
327 }
328 
329 static void websockets_data_cb(uv_stream_t* stream, ssize_t nread,
330  const uv_buf_t* buf) {
331  InspectorSocket* inspector = inspector_from_stream(stream);
332  reclaim_uv_buf(inspector, buf, nread);
333  if (nread < 0 || nread == UV_EOF) {
334  inspector->connection_eof = true;
335  if (!inspector->shutting_down && inspector->ws_state->read_cb) {
336  inspector->ws_state->read_cb(stream, nread, nullptr);
337  }
338  if (inspector->ws_state->close_sent &&
339  !inspector->ws_state->received_close) {
340  shutdown_complete(inspector); // invoke callback
341  }
342  } else {
343  #if DUMP_READS
344  printf("%s read %ld bytes\n", __FUNCTION__, nread);
345  if (nread > 0) {
346  dump_hex(inspector->buffer.data() + inspector->buffer.size() - nread,
347  nread);
348  }
349  #endif
350  // 2. Parse.
351  int processed = 0;
352  do {
353  processed = parse_ws_frames(inspector);
354  // 3. Fix the buffer size & length
355  if (processed > 0) {
356  remove_from_beginning(&inspector->buffer, processed);
357  }
358  } while (processed > 0 && !inspector->buffer.empty());
359  }
360 }
361 
363  uv_alloc_cb alloc_cb, uv_read_cb read_cb) {
364  CHECK(inspector->ws_mode);
365  CHECK(!inspector->shutting_down || read_cb == nullptr);
366  inspector->ws_state->close_sent = false;
367  inspector->ws_state->alloc_cb = alloc_cb;
368  inspector->ws_state->read_cb = read_cb;
369  int err =
370  uv_read_start(reinterpret_cast<uv_stream_t*>(&inspector->tcp),
371  prepare_buffer,
372  websockets_data_cb);
373  if (err < 0) {
374  close_connection(inspector);
375  }
376  return err;
377 }
378 
380  uv_read_stop(reinterpret_cast<uv_stream_t*>(&inspector->tcp));
381  inspector->ws_state->alloc_cb = nullptr;
382  inspector->ws_state->read_cb = nullptr;
383 }
384 
385 static void generate_accept_string(const std::string& client_key,
386  char (*buffer)[ACCEPT_KEY_LENGTH]) {
387  // Magic string from websockets spec.
388  static const char ws_magic[] = "258EAFA5-E914-47DA-95CA-C5AB0DC85B11";
389  std::string input(client_key + ws_magic);
390  char hash[SHA_DIGEST_LENGTH];
391  SHA1(reinterpret_cast<const unsigned char*>(&input[0]), input.size(),
392  reinterpret_cast<unsigned char*>(hash));
393  node::base64_encode(hash, sizeof(hash), *buffer, sizeof(*buffer));
394 }
395 
396 static int header_value_cb(http_parser* parser, const char* at, size_t length) {
397  static const char SEC_WEBSOCKET_KEY_HEADER[] = "Sec-WebSocket-Key";
398  auto inspector = static_cast<InspectorSocket*>(parser->data);
399  auto state = inspector->http_parsing_state;
400  state->parsing_value = true;
401  if (state->current_header.size() == sizeof(SEC_WEBSOCKET_KEY_HEADER) - 1 &&
402  node::StringEqualNoCaseN(state->current_header.data(),
403  SEC_WEBSOCKET_KEY_HEADER,
404  sizeof(SEC_WEBSOCKET_KEY_HEADER) - 1)) {
405  state->ws_key.append(at, length);
406  }
407  return 0;
408 }
409 
410 static int header_field_cb(http_parser* parser, const char* at, size_t length) {
411  auto inspector = static_cast<InspectorSocket*>(parser->data);
412  auto state = inspector->http_parsing_state;
413  if (state->parsing_value) {
414  state->parsing_value = false;
415  state->current_header.clear();
416  }
417  state->current_header.append(at, length);
418  return 0;
419 }
420 
421 static int path_cb(http_parser* parser, const char* at, size_t length) {
422  auto inspector = static_cast<InspectorSocket*>(parser->data);
423  auto state = inspector->http_parsing_state;
424  state->path.append(at, length);
425  return 0;
426 }
427 
428 static void handshake_complete(InspectorSocket* inspector) {
429  uv_read_stop(reinterpret_cast<uv_stream_t*>(&inspector->tcp));
430  handshake_cb callback = inspector->http_parsing_state->callback;
431  inspector->ws_state = new ws_state_s();
432  inspector->ws_mode = true;
433  callback(inspector, kInspectorHandshakeUpgraded,
434  inspector->http_parsing_state->path);
435 }
436 
437 static void cleanup_http_parsing_state(InspectorSocket* inspector) {
438  delete inspector->http_parsing_state;
439  inspector->http_parsing_state = nullptr;
440 }
441 
442 static void report_handshake_failure_cb(uv_handle_t* handle) {
443  dispose_inspector(handle);
444  InspectorSocket* inspector = inspector_from_stream(handle);
445  handshake_cb cb = inspector->http_parsing_state->callback;
446  cleanup_http_parsing_state(inspector);
447  cb(inspector, kInspectorHandshakeFailed, std::string());
448 }
449 
450 static void close_and_report_handshake_failure(InspectorSocket* inspector) {
451  uv_handle_t* socket = reinterpret_cast<uv_handle_t*>(&inspector->tcp);
452  if (uv_is_closing(socket)) {
453  report_handshake_failure_cb(socket);
454  } else {
455  uv_read_stop(reinterpret_cast<uv_stream_t*>(socket));
456  uv_close(socket, report_handshake_failure_cb);
457  }
458 }
459 
460 static void then_close_and_report_failure(uv_write_t* req, int status) {
462  write_request_cleanup(req, status);
463  close_and_report_handshake_failure(inspector);
464 }
465 
466 static void handshake_failed(InspectorSocket* inspector) {
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  write_to_client(inspector, HANDSHAKE_FAILED_RESPONSE,
472  sizeof(HANDSHAKE_FAILED_RESPONSE) - 1,
473  then_close_and_report_failure);
474 }
475 
476 // init_handshake references message_complete_cb
477 static void init_handshake(InspectorSocket* socket);
478 
479 static int message_complete_cb(http_parser* parser) {
480  InspectorSocket* inspector = static_cast<InspectorSocket*>(parser->data);
481  struct http_parsing_state_s* state = inspector->http_parsing_state;
482  if (parser->method != HTTP_GET) {
483  handshake_failed(inspector);
484  } else if (!parser->upgrade) {
485  if (state->callback(inspector, kInspectorHandshakeHttpGet, state->path)) {
486  init_handshake(inspector);
487  } else {
488  handshake_failed(inspector);
489  }
490  } else if (state->ws_key.empty()) {
491  handshake_failed(inspector);
492  } else if (state->callback(inspector, kInspectorHandshakeUpgrading,
493  state->path)) {
494  char accept_string[ACCEPT_KEY_LENGTH];
495  generate_accept_string(state->ws_key, &accept_string);
496  const char accept_ws_prefix[] = "HTTP/1.1 101 Switching Protocols\r\n"
497  "Upgrade: websocket\r\n"
498  "Connection: Upgrade\r\n"
499  "Sec-WebSocket-Accept: ";
500  const char accept_ws_suffix[] = "\r\n\r\n";
501  std::string reply(accept_ws_prefix, sizeof(accept_ws_prefix) - 1);
502  reply.append(accept_string, sizeof(accept_string));
503  reply.append(accept_ws_suffix, sizeof(accept_ws_suffix) - 1);
504  if (write_to_client(inspector, &reply[0], reply.size()) >= 0) {
505  handshake_complete(inspector);
506  inspector->http_parsing_state->done = true;
507  } else {
508  close_and_report_handshake_failure(inspector);
509  }
510  } else {
511  handshake_failed(inspector);
512  }
513  return 0;
514 }
515 
516 static void data_received_cb(uv_stream_s* tcp, ssize_t nread,
517  const uv_buf_t* buf) {
518 #if DUMP_READS
519  if (nread >= 0) {
520  printf("%s (%ld bytes)\n", __FUNCTION__, nread);
521  dump_hex(buf->base, nread);
522  } else {
523  printf("[%s:%d] %s\n", __FUNCTION__, __LINE__, uv_err_name(nread));
524  }
525 #endif
526  InspectorSocket* inspector = inspector_from_stream(tcp);
527  reclaim_uv_buf(inspector, buf, nread);
528  if (nread < 0 || nread == UV_EOF) {
529  close_and_report_handshake_failure(inspector);
530  } else {
531  http_parsing_state_s* state = inspector->http_parsing_state;
532  http_parser* parser = &state->parser;
533  http_parser_execute(parser, &state->parser_settings,
534  inspector->buffer.data(), nread);
535  remove_from_beginning(&inspector->buffer, nread);
536  if (parser->http_errno != HPE_OK) {
537  handshake_failed(inspector);
538  }
539  if (inspector->http_parsing_state->done) {
540  cleanup_http_parsing_state(inspector);
541  }
542  }
543 }
544 
545 static void init_handshake(InspectorSocket* socket) {
546  http_parsing_state_s* state = socket->http_parsing_state;
547  CHECK_NE(state, nullptr);
548  state->current_header.clear();
549  state->ws_key.clear();
550  state->path.clear();
551  state->done = false;
552  http_parser_init(&state->parser, HTTP_REQUEST);
553  state->parser.data = socket;
554  http_parser_settings* settings = &state->parser_settings;
555  http_parser_settings_init(settings);
556  settings->on_header_field = header_field_cb;
557  settings->on_header_value = header_value_cb;
558  settings->on_message_complete = message_complete_cb;
559  settings->on_url = path_cb;
560 }
561 
562 int inspector_accept(uv_stream_t* server, InspectorSocket* socket,
563  handshake_cb callback) {
564  CHECK_NE(callback, nullptr);
565  CHECK_EQ(socket->http_parsing_state, nullptr);
566 
568  uv_stream_t* tcp = reinterpret_cast<uv_stream_t*>(&socket->tcp);
569  int err = uv_tcp_init(server->loop, &socket->tcp);
570 
571  if (err == 0) {
572  err = uv_accept(server, tcp);
573  }
574  if (err == 0) {
575  init_handshake(socket);
576  socket->http_parsing_state->callback = callback;
577  err = uv_read_start(tcp, prepare_buffer,
578  data_received_cb);
579  }
580  if (err != 0) {
581  uv_close(reinterpret_cast<uv_handle_t*>(tcp), NULL);
582  }
583  return err;
584 }
585 
586 void inspector_write(InspectorSocket* inspector, const char* data,
587  size_t len) {
588  if (inspector->ws_mode) {
589  std::vector<char> output = encode_frame_hybi17(data, len);
590  write_to_client(inspector, &output[0], output.size());
591  } else {
592  write_to_client(inspector, data, len);
593  }
594 }
595 
597  inspector_cb callback) {
598  // libuv throws assertions when closing stream that's already closed - we
599  // need to do the same.
600  CHECK(!uv_is_closing(reinterpret_cast<uv_handle_t*>(&inspector->tcp)));
601  CHECK(!inspector->shutting_down);
602  inspector->shutting_down = true;
603  inspector->ws_state->close_cb = callback;
604  if (inspector->connection_eof) {
605  close_connection(inspector);
606  } else {
607  inspector_read_stop(inspector);
608  write_to_client(inspector, CLOSE_FRAME, sizeof(CLOSE_FRAME),
609  on_close_frame_written);
610  inspector_read_start(inspector, nullptr, nullptr);
611  }
612 }
613 
614 bool inspector_is_active(const InspectorSocket* inspector) {
615  const uv_handle_t* tcp =
616  reinterpret_cast<const uv_handle_t*>(&inspector->tcp);
617  return !inspector->shutting_down && !uv_is_closing(tcp);
618 }
619 
621  http_parsing_state = nullptr;
622  ws_state = nullptr;
623  buffer.clear();
624  ws_mode = false;
625  shutting_down = false;
626  connection_eof = false;
627 }
628 
629 } // namespace inspector
630 } // namespace node
bool(* handshake_cb)(InspectorSocket *, enum inspector_handshake_event state, const std::string &path)
void inspector_close(InspectorSocket *inspector, inspector_cb callback)
const OpCode kOpCodePong
InspectorSocket *const inspector
void inspector_read_stop(InspectorSocket *inspector)
const unsigned char kOpCodeMask
unsigned char * buf
Definition: cares_wrap.cc:483
const unsigned char kReserved3Bit
void(* inspector_cb)(InspectorSocket *, int)
#define ACCEPT_KEY_LENGTH
static WriteRequest * from_write_req(uv_write_t *req)
int len
Definition: cares_wrap.cc:485
void inspector_write(InspectorSocket *inspector, const char *data, size_t len)
const OpCode kOpCodeClose
const unsigned char kPayloadLengthMask
const unsigned char kReserved1Bit
const OpCode kOpCodeText
const size_t kMaxSingleBytePayloadLength
int status
Definition: cares_wrap.cc:479
union node::cares_wrap::@8::CaresAsyncData::@0 data
const OpCode kOpCodeContinuation
const size_t kTwoBytePayloadLengthField
const unsigned char kFinalBit
InspectorSocket * inspector_from_stream(uv_tcp_t *stream)
WriteRequest(InspectorSocket *inspector, const char *data, size_t size)
int inspector_accept(uv_stream_t *server, InspectorSocket *socket, handshake_cb callback)
const unsigned char kMaskBit
struct http_parsing_state_s * http_parsing_state
bool inspector_is_active(const InspectorSocket *inspector)
const size_t kEightBytePayloadLengthField
const size_t kMaskingKeyWidthInBytes
const OpCode kOpCodeBinary
int inspector_read_start(InspectorSocket *inspector, uv_alloc_cb alloc_cb, uv_read_cb read_cb)
const unsigned char kReserved2Bit
const OpCode kOpCodePing