Node.js  v8.x
Node.js is a JavaScript runtime built on Chrome's V8 JavaScript engine
cares_wrap.cc
Go to the documentation of this file.
1 // Copyright Joyent, Inc. and other Node contributors.
2 //
3 // Permission is hereby granted, free of charge, to any person obtaining a
4 // copy of this software and associated documentation files (the
5 // "Software"), to deal in the Software without restriction, including
6 // without limitation the rights to use, copy, modify, merge, publish,
7 // distribute, sublicense, and/or sell copies of the Software, and to permit
8 // persons to whom the Software is furnished to do so, subject to the
9 // following conditions:
10 //
11 // The above copyright notice and this permission notice shall be included
12 // in all copies or substantial portions of the Software.
13 //
14 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
15 // OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN
17 // NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
18 // DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
19 // OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
20 // USE OR OTHER DEALINGS IN THE SOFTWARE.
21 
22 #define CARES_STATICLIB
23 #include "ares.h"
24 #include "async-wrap.h"
25 #include "async-wrap-inl.h"
26 #include "env.h"
27 #include "env-inl.h"
28 #include "node.h"
29 #include "req-wrap.h"
30 #include "req-wrap-inl.h"
31 #include "util.h"
32 #include "util-inl.h"
33 #include "uv.h"
34 
35 #include <errno.h>
36 #include <stdlib.h>
37 #include <string.h>
38 #include <vector>
39 #include <unordered_set>
40 
41 #if defined(__ANDROID__) || \
42  defined(__MINGW32__) || \
43  defined(__OpenBSD__) || \
44  defined(_MSC_VER)
45 
46 # include <nameser.h>
47 #else
48 # include <arpa/nameser.h>
49 #endif
50 
51 #if defined(__OpenBSD__)
52 # define AI_V4MAPPED 0
53 #endif
54 
55 namespace node {
56 namespace cares_wrap {
57 
58 using v8::Array;
59 using v8::Context;
60 using v8::EscapableHandleScope;
61 using v8::FunctionCallbackInfo;
62 using v8::FunctionTemplate;
63 using v8::HandleScope;
64 using v8::Integer;
65 using v8::Local;
66 using v8::Null;
67 using v8::Object;
68 using v8::String;
69 using v8::Value;
70 
71 namespace {
72 
73 inline uint16_t cares_get_16bit(const unsigned char* p) {
74  return static_cast<uint32_t>(p[0] << 8U) | (static_cast<uint32_t>(p[1]));
75 }
76 
77 inline uint32_t cares_get_32bit(const unsigned char* p) {
78  return static_cast<uint32_t>(p[0] << 24U) |
79  static_cast<uint32_t>(p[1] << 16U) |
80  static_cast<uint32_t>(p[2] << 8U) |
81  static_cast<uint32_t>(p[3]);
82 }
83 
84 const int ns_t_cname_or_a = -1;
85 
86 inline const char* ToErrorCodeString(int status) {
87  switch (status) {
88 #define V(code) case ARES_##code: return #code;
89  V(EADDRGETNETWORKPARAMS)
90  V(EBADFAMILY)
91  V(EBADFLAGS)
92  V(EBADHINTS)
93  V(EBADNAME)
94  V(EBADQUERY)
95  V(EBADRESP)
96  V(EBADSTR)
97  V(ECANCELLED)
98  V(ECONNREFUSED)
99  V(EDESTRUCTION)
100  V(EFILE)
101  V(EFORMERR)
102  V(ELOADIPHLPAPI)
103  V(ENODATA)
104  V(ENOMEM)
105  V(ENONAME)
106  V(ENOTFOUND)
107  V(ENOTIMP)
108  V(ENOTINITIALIZED)
109  V(EOF)
110  V(EREFUSED)
111  V(ESERVFAIL)
112  V(ETIMEOUT)
113 #undef V
114  }
115 
116  return "UNKNOWN_ARES_ERROR";
117 }
118 
119 class ChannelWrap;
120 
121 struct node_ares_task {
122  ChannelWrap* channel;
123  ares_socket_t sock;
124  uv_poll_t poll_watcher;
125 };
126 
127 struct TaskHash {
128  size_t operator()(node_ares_task* a) const {
129  return std::hash<ares_socket_t>()(a->sock);
130  }
131 };
132 
133 struct TaskEqual {
134  inline bool operator()(node_ares_task* a, node_ares_task* b) const {
135  return a->sock == b->sock;
136  }
137 };
138 
139 using node_ares_task_list =
140  std::unordered_set<node_ares_task*, TaskHash, TaskEqual>;
141 
142 class ChannelWrap : public AsyncWrap {
143  public:
144  ChannelWrap(Environment* env, Local<Object> object);
145  ~ChannelWrap();
146 
147  static void New(const FunctionCallbackInfo<Value>& args);
148 
149  void Setup();
150  void EnsureServers();
151  void CleanupTimer();
152 
153  inline uv_timer_t* timer_handle() { return timer_handle_; }
154  inline ares_channel cares_channel() { return channel_; }
155  inline bool query_last_ok() const { return query_last_ok_; }
156  inline void set_query_last_ok(bool ok) { query_last_ok_ = ok; }
157  inline bool is_servers_default() const { return is_servers_default_; }
158  inline void set_is_servers_default(bool is_default) {
159  is_servers_default_ = is_default;
160  }
161  inline node_ares_task_list* task_list() { return &task_list_; }
162 
163  size_t self_size() const override { return sizeof(this); }
164 
165  static void AresTimeout(uv_timer_t* handle);
166 
167  private:
168  uv_timer_t* timer_handle_;
169  ares_channel channel_;
170  bool query_last_ok_;
171  bool is_servers_default_;
172  bool library_inited_;
173  node_ares_task_list task_list_;
174 };
175 
176 ChannelWrap::ChannelWrap(Environment* env,
177  Local<Object> object)
178  : AsyncWrap(env, object, PROVIDER_DNSCHANNEL),
179  timer_handle_(nullptr),
180  channel_(nullptr),
181  query_last_ok_(true),
182  is_servers_default_(true),
183  library_inited_(false) {
184  MakeWeak<ChannelWrap>(this);
185 
186  Setup();
187 }
188 
189 void ChannelWrap::New(const FunctionCallbackInfo<Value>& args) {
190  CHECK(args.IsConstructCall());
191  CHECK_EQ(args.Length(), 0);
192 
193  Environment* env = Environment::GetCurrent(args);
194  new ChannelWrap(env, args.This());
195 }
196 
197 class GetAddrInfoReqWrap : public ReqWrap<uv_getaddrinfo_t> {
198  public:
199  GetAddrInfoReqWrap(Environment* env,
200  Local<Object> req_wrap_obj,
201  bool verbatim);
202  ~GetAddrInfoReqWrap();
203 
204  size_t self_size() const override { return sizeof(*this); }
205  bool verbatim() const { return verbatim_; }
206 
207  private:
208  const bool verbatim_;
209 };
210 
211 GetAddrInfoReqWrap::GetAddrInfoReqWrap(Environment* env,
212  Local<Object> req_wrap_obj,
213  bool verbatim)
214  : ReqWrap(env, req_wrap_obj, AsyncWrap::PROVIDER_GETADDRINFOREQWRAP)
215  , verbatim_(verbatim) {
216  Wrap(req_wrap_obj, this);
217 }
218 
219 GetAddrInfoReqWrap::~GetAddrInfoReqWrap() {
220  ClearWrap(object());
221 }
222 
223 
224 class GetNameInfoReqWrap : public ReqWrap<uv_getnameinfo_t> {
225  public:
226  GetNameInfoReqWrap(Environment* env, Local<Object> req_wrap_obj);
227  ~GetNameInfoReqWrap();
228 
229  size_t self_size() const override { return sizeof(*this); }
230 };
231 
232 GetNameInfoReqWrap::GetNameInfoReqWrap(Environment* env,
233  Local<Object> req_wrap_obj)
234  : ReqWrap(env, req_wrap_obj, AsyncWrap::PROVIDER_GETNAMEINFOREQWRAP) {
235  Wrap(req_wrap_obj, this);
236 }
237 
238 GetNameInfoReqWrap::~GetNameInfoReqWrap() {
239  ClearWrap(object());
240 }
241 
242 
243 /* This is called once per second by loop->timer. It is used to constantly */
244 /* call back into c-ares for possibly processing timeouts. */
245 void ChannelWrap::AresTimeout(uv_timer_t* handle) {
246  ChannelWrap* channel = static_cast<ChannelWrap*>(handle->data);
247  CHECK_EQ(channel->timer_handle(), handle);
248  CHECK_EQ(false, channel->task_list()->empty());
249  ares_process_fd(channel->cares_channel(), ARES_SOCKET_BAD, ARES_SOCKET_BAD);
250 }
251 
252 
253 void ares_poll_cb(uv_poll_t* watcher, int status, int events) {
254  node_ares_task* task = ContainerOf(&node_ares_task::poll_watcher, watcher);
255  ChannelWrap* channel = task->channel;
256 
257  /* Reset the idle timer */
258  uv_timer_again(channel->timer_handle());
259 
260  if (status < 0) {
261  /* An error happened. Just pretend that the socket is both readable and */
262  /* writable. */
263  ares_process_fd(channel->cares_channel(), task->sock, task->sock);
264  return;
265  }
266 
267  /* Process DNS responses */
268  ares_process_fd(channel->cares_channel(),
269  events & UV_READABLE ? task->sock : ARES_SOCKET_BAD,
270  events & UV_WRITABLE ? task->sock : ARES_SOCKET_BAD);
271 }
272 
273 
274 void ares_poll_close_cb(uv_handle_t* watcher) {
275  node_ares_task* task = ContainerOf(&node_ares_task::poll_watcher,
276  reinterpret_cast<uv_poll_t*>(watcher));
277  free(task);
278 }
279 
280 
281 /* Allocates and returns a new node_ares_task */
282 node_ares_task* ares_task_create(ChannelWrap* channel, ares_socket_t sock) {
283  auto task = node::UncheckedMalloc<node_ares_task>(1);
284 
285  if (task == nullptr) {
286  /* Out of memory. */
287  return nullptr;
288  }
289 
290  task->channel = channel;
291  task->sock = sock;
292 
293  if (uv_poll_init_socket(channel->env()->event_loop(),
294  &task->poll_watcher, sock) < 0) {
295  /* This should never happen. */
296  free(task);
297  return nullptr;
298  }
299 
300  return task;
301 }
302 
303 
304 /* Callback from ares when socket operation is started */
305 void ares_sockstate_cb(void* data,
306  ares_socket_t sock,
307  int read,
308  int write) {
309  ChannelWrap* channel = static_cast<ChannelWrap*>(data);
310  node_ares_task* task;
311 
312  node_ares_task lookup_task;
313  lookup_task.sock = sock;
314  auto it = channel->task_list()->find(&lookup_task);
315 
316  task = (it == channel->task_list()->end()) ? nullptr : *it;
317 
318  if (read || write) {
319  if (!task) {
320  /* New socket */
321 
322  /* If this is the first socket then start the timer. */
323  uv_timer_t* timer_handle = channel->timer_handle();
324  if (!uv_is_active(reinterpret_cast<uv_handle_t*>(timer_handle))) {
325  CHECK(channel->task_list()->empty());
326  uv_timer_start(timer_handle, ChannelWrap::AresTimeout, 1000, 1000);
327  }
328 
329  task = ares_task_create(channel, sock);
330  if (task == nullptr) {
331  /* This should never happen unless we're out of memory or something */
332  /* is seriously wrong. The socket won't be polled, but the query will */
333  /* eventually time out. */
334  return;
335  }
336 
337  channel->task_list()->insert(task);
338  }
339 
340  /* This should never fail. If it fails anyway, the query will eventually */
341  /* time out. */
342  uv_poll_start(&task->poll_watcher,
343  (read ? UV_READABLE : 0) | (write ? UV_WRITABLE : 0),
344  ares_poll_cb);
345 
346  } else {
347  /* read == 0 and write == 0 this is c-ares's way of notifying us that */
348  /* the socket is now closed. We must free the data associated with */
349  /* socket. */
350  CHECK(task &&
351  "When an ares socket is closed we should have a handle for it");
352 
353  channel->task_list()->erase(it);
354  uv_close(reinterpret_cast<uv_handle_t*>(&task->poll_watcher),
355  ares_poll_close_cb);
356 
357  if (channel->task_list()->empty()) {
358  uv_timer_stop(channel->timer_handle());
359  }
360  }
361 }
362 
363 
364 Local<Array> HostentToAddresses(Environment* env,
365  struct hostent* host,
366  Local<Array> append_to = Local<Array>()) {
367  EscapableHandleScope scope(env->isolate());
368  auto context = env->context();
369  bool append = !append_to.IsEmpty();
370  Local<Array> addresses = append ? append_to : Array::New(env->isolate());
371  size_t offset = addresses->Length();
372 
373  char ip[INET6_ADDRSTRLEN];
374  for (uint32_t i = 0; host->h_addr_list[i] != nullptr; ++i) {
375  uv_inet_ntop(host->h_addrtype, host->h_addr_list[i], ip, sizeof(ip));
376  Local<String> address = OneByteString(env->isolate(), ip);
377  addresses->Set(context, i + offset, address).FromJust();
378  }
379 
380  return append ? addresses : scope.Escape(addresses);
381 }
382 
383 
384 Local<Array> HostentToNames(Environment* env,
385  struct hostent* host,
386  Local<Array> append_to = Local<Array>()) {
387  EscapableHandleScope scope(env->isolate());
388  auto context = env->context();
389  bool append = !append_to.IsEmpty();
390  Local<Array> names = append ? append_to : Array::New(env->isolate());
391  size_t offset = names->Length();
392 
393  for (uint32_t i = 0; host->h_aliases[i] != nullptr; ++i) {
394  Local<String> address = OneByteString(env->isolate(), host->h_aliases[i]);
395  names->Set(context, i + offset, address).FromJust();
396  }
397 
398  return append ? names : scope.Escape(names);
399 }
400 
401 void safe_free_hostent(struct hostent* host) {
402  int idx;
403 
404  if (host->h_addr_list != nullptr) {
405  idx = 0;
406  while (host->h_addr_list[idx]) {
407  free(host->h_addr_list[idx++]);
408  }
409  free(host->h_addr_list);
410  host->h_addr_list = 0;
411  }
412 
413  if (host->h_aliases != nullptr) {
414  idx = 0;
415  while (host->h_aliases[idx]) {
416  free(host->h_aliases[idx++]);
417  }
418  free(host->h_aliases);
419  host->h_aliases = 0;
420  }
421 
422  if (host->h_name != nullptr) {
423  free(host->h_name);
424  }
425 
426  host->h_addrtype = host->h_length = 0;
427 }
428 
429 void cares_wrap_hostent_cpy(struct hostent* dest, struct hostent* src) {
430  dest->h_addr_list = nullptr;
431  dest->h_addrtype = 0;
432  dest->h_aliases = nullptr;
433  dest->h_length = 0;
434  dest->h_name = nullptr;
435 
436  /* copy `h_name` */
437  size_t name_size = strlen(src->h_name) + 1;
438  dest->h_name = node::Malloc<char>(name_size);
439  memcpy(dest->h_name, src->h_name, name_size);
440 
441  /* copy `h_aliases` */
442  size_t alias_count;
443  size_t cur_alias_length;
444  for (alias_count = 0;
445  src->h_aliases[alias_count] != nullptr;
446  alias_count++) {
447  }
448 
449  dest->h_aliases = node::Malloc<char*>(alias_count + 1);
450  for (size_t i = 0; i < alias_count; i++) {
451  cur_alias_length = strlen(src->h_aliases[i]);
452  dest->h_aliases[i] = node::Malloc(cur_alias_length + 1);
453  memcpy(dest->h_aliases[i], src->h_aliases[i], cur_alias_length + 1);
454  }
455  dest->h_aliases[alias_count] = nullptr;
456 
457  /* copy `h_addr_list` */
458  size_t list_count;
459  for (list_count = 0;
460  src->h_addr_list[list_count] != nullptr;
461  list_count++) {
462  }
463 
464  dest->h_addr_list = node::Malloc<char*>(list_count + 1);
465  for (size_t i = 0; i < list_count; i++) {
466  dest->h_addr_list[i] = node::Malloc(src->h_length);
467  memcpy(dest->h_addr_list[i], src->h_addr_list[i], src->h_length);
468  }
469  dest->h_addr_list[list_count] = nullptr;
470 
471  /* work after work */
472  dest->h_length = src->h_length;
473  dest->h_addrtype = src->h_addrtype;
474 }
475 
476 class QueryWrap;
477 struct CaresAsyncData {
478  QueryWrap* wrap;
479  int status;
480  bool is_host;
481  union {
482  hostent* host;
483  unsigned char* buf;
484  } data;
485  int len;
486 
487  uv_async_t async_handle;
488 };
489 
490 void ChannelWrap::Setup() {
491  struct ares_options options;
492  memset(&options, 0, sizeof(options));
493  options.flags = ARES_FLAG_NOCHECKRESP;
494  options.sock_state_cb = ares_sockstate_cb;
495  options.sock_state_cb_data = this;
496 
497  int r;
498  if (!library_inited_) {
499  // Multiple calls to ares_library_init() increase a reference counter,
500  // so this is a no-op except for the first call to it.
501  r = ares_library_init(ARES_LIB_INIT_ALL);
502  if (r != ARES_SUCCESS)
503  return env()->ThrowError(ToErrorCodeString(r));
504  }
505 
506  /* We do the call to ares_init_option for caller. */
507  r = ares_init_options(&channel_,
508  &options,
509  ARES_OPT_FLAGS | ARES_OPT_SOCK_STATE_CB);
510 
511  if (r != ARES_SUCCESS) {
512  ares_library_cleanup();
513  return env()->ThrowError(ToErrorCodeString(r));
514  }
515 
516  library_inited_ = true;
517 
518  /* Initialize the timeout timer. The timer won't be started until the */
519  /* first socket is opened. */
520  CleanupTimer();
521  timer_handle_ = new uv_timer_t();
522  timer_handle_->data = static_cast<void*>(this);
523  uv_timer_init(env()->event_loop(), timer_handle_);
524 }
525 
526 
527 ChannelWrap::~ChannelWrap() {
528  if (library_inited_) {
529  // This decreases the reference counter increased by ares_library_init().
530  ares_library_cleanup();
531  }
532 
533  ares_destroy(channel_);
534  CleanupTimer();
535 }
536 
537 
538 void ChannelWrap::CleanupTimer() {
539  if (timer_handle_ == nullptr) return;
540 
541  uv_close(reinterpret_cast<uv_handle_t*>(timer_handle_),
542  [](uv_handle_t* handle) {
543  delete reinterpret_cast<uv_timer_t*>(handle);
544  });
545  timer_handle_ = nullptr;
546 }
547 
548 
556 void ChannelWrap::EnsureServers() {
557  /* if last query is OK or servers are set by user self, do not check */
558  if (query_last_ok_ || !is_servers_default_) {
559  return;
560  }
561 
562  ares_addr_port_node* servers = nullptr;
563 
564  ares_get_servers_ports(channel_, &servers);
565 
566  /* if no server or multi-servers, ignore */
567  if (servers == nullptr) return;
568  if (servers->next != nullptr) {
569  ares_free_data(servers);
570  is_servers_default_ = false;
571  return;
572  }
573 
574  /* if the only server is not 127.0.0.1, ignore */
575  if (servers[0].family != AF_INET ||
576  servers[0].addr.addr4.s_addr != htonl(INADDR_LOOPBACK) ||
577  servers[0].tcp_port != 0 ||
578  servers[0].udp_port != 0) {
579  ares_free_data(servers);
580  is_servers_default_ = false;
581  return;
582  }
583 
584  ares_free_data(servers);
585  servers = nullptr;
586 
587  /* destroy channel and reset channel */
588  ares_destroy(channel_);
589 
590  Setup();
591 }
592 
593 
594 class QueryWrap : public AsyncWrap {
595  public:
596  QueryWrap(ChannelWrap* channel, Local<Object> req_wrap_obj)
597  : AsyncWrap(channel->env(), req_wrap_obj, AsyncWrap::PROVIDER_QUERYWRAP),
598  channel_(channel) {
599  if (env()->in_domain()) {
600  req_wrap_obj->Set(env()->domain_string(),
601  env()->domain_array()->Get(env()->context(), 0)
602  .ToLocalChecked());
603  }
604 
605  Wrap(req_wrap_obj, this);
606 
607  // Make sure the channel object stays alive during the query lifetime.
608  req_wrap_obj->Set(env()->context(),
609  env()->channel_string(),
610  channel->object()).FromJust();
611  }
612 
613  ~QueryWrap() override {
614  CHECK_EQ(false, persistent().IsEmpty());
615  ClearWrap(object());
616  persistent().Reset();
617  }
618 
619  // Subclasses should implement the appropriate Send method.
620  virtual int Send(const char* name) {
621  UNREACHABLE();
622  return 0;
623  }
624 
625  virtual int Send(const char* name, int family) {
626  UNREACHABLE();
627  return 0;
628  }
629 
630  protected:
631  void AresQuery(const char* name,
632  int dnsclass,
633  int type) {
634  channel_->EnsureServers();
635  ares_query(channel_->cares_channel(), name, dnsclass, type, Callback,
636  static_cast<void*>(this));
637  }
638 
639  static void CaresAsyncClose(uv_handle_t* handle) {
640  uv_async_t* async = reinterpret_cast<uv_async_t*>(handle);
641  auto data = static_cast<struct CaresAsyncData*>(async->data);
642  delete data->wrap;
643  delete data;
644  }
645 
646  static void CaresAsyncCb(uv_async_t* handle) {
647  auto data = static_cast<struct CaresAsyncData*>(handle->data);
648 
649  QueryWrap* wrap = data->wrap;
650  int status = data->status;
651 
652  if (status != ARES_SUCCESS) {
653  wrap->ParseError(status);
654  } else if (!data->is_host) {
655  unsigned char* buf = data->data.buf;
656  wrap->Parse(buf, data->len);
657  free(buf);
658  } else {
659  hostent* host = data->data.host;
660  wrap->Parse(host);
661  safe_free_hostent(host);
662  free(host);
663  }
664 
665  uv_close(reinterpret_cast<uv_handle_t*>(handle), CaresAsyncClose);
666  }
667 
668  static void Callback(void *arg, int status, int timeouts,
669  unsigned char* answer_buf, int answer_len) {
670  QueryWrap* wrap = static_cast<QueryWrap*>(arg);
671 
672  unsigned char* buf_copy = nullptr;
673  if (status == ARES_SUCCESS) {
674  buf_copy = node::Malloc<unsigned char>(answer_len);
675  memcpy(buf_copy, answer_buf, answer_len);
676  }
677 
678  CaresAsyncData* data = new CaresAsyncData();
679  data->status = status;
680  data->wrap = wrap;
681  data->is_host = false;
682  data->data.buf = buf_copy;
683  data->len = answer_len;
684 
685  uv_async_t* async_handle = &data->async_handle;
686  CHECK_EQ(0, uv_async_init(wrap->env()->event_loop(),
687  async_handle,
688  CaresAsyncCb));
689 
690  wrap->channel_->set_query_last_ok(status != ARES_ECONNREFUSED);
691  async_handle->data = data;
692  uv_async_send(async_handle);
693  }
694 
695  static void Callback(void *arg, int status, int timeouts,
696  struct hostent* host) {
697  QueryWrap* wrap = static_cast<QueryWrap*>(arg);
698 
699  struct hostent* host_copy = nullptr;
700  if (status == ARES_SUCCESS) {
701  host_copy = node::Malloc<hostent>(1);
702  cares_wrap_hostent_cpy(host_copy, host);
703  }
704 
705  CaresAsyncData* data = new CaresAsyncData();
706  data->status = status;
707  data->data.host = host_copy;
708  data->wrap = wrap;
709  data->is_host = true;
710 
711  uv_async_t* async_handle = &data->async_handle;
712  CHECK_EQ(0, uv_async_init(wrap->env()->event_loop(),
713  async_handle,
714  CaresAsyncCb));
715 
716  wrap->channel_->set_query_last_ok(status != ARES_ECONNREFUSED);
717  async_handle->data = data;
718  uv_async_send(async_handle);
719  }
720 
721  void CallOnComplete(Local<Value> answer,
722  Local<Value> extra = Local<Value>()) {
723  HandleScope handle_scope(env()->isolate());
724  Context::Scope context_scope(env()->context());
725  Local<Value> argv[] = {
726  Integer::New(env()->isolate(), 0),
727  answer,
728  extra
729  };
730  const int argc = arraysize(argv) - extra.IsEmpty();
731  MakeCallback(env()->oncomplete_string(), argc, argv);
732  }
733 
734  void ParseError(int status) {
735  CHECK_NE(status, ARES_SUCCESS);
736  HandleScope handle_scope(env()->isolate());
737  Context::Scope context_scope(env()->context());
738  const char* code = ToErrorCodeString(status);
739  Local<Value> arg = OneByteString(env()->isolate(), code);
740  MakeCallback(env()->oncomplete_string(), 1, &arg);
741  }
742 
743  // Subclasses should implement the appropriate Parse method.
744  virtual void Parse(unsigned char* buf, int len) {
745  UNREACHABLE();
746  }
747 
748  virtual void Parse(struct hostent* host) {
749  UNREACHABLE();
750  }
751 
752  ChannelWrap* channel_;
753 };
754 
755 
756 template<typename T>
757 Local<Array> AddrTTLToArray(Environment* env,
758  const T* addrttls,
759  size_t naddrttls) {
760  auto isolate = env->isolate();
761  EscapableHandleScope escapable_handle_scope(isolate);
762  auto context = env->context();
763 
764  Local<Array> ttls = Array::New(isolate, naddrttls);
765  for (size_t i = 0; i < naddrttls; i++) {
766  auto value = Integer::New(isolate, addrttls[i].ttl);
767  ttls->Set(context, i, value).FromJust();
768  }
769 
770  return escapable_handle_scope.Escape(ttls);
771 }
772 
773 
774 int ParseGeneralReply(Environment* env,
775  const unsigned char* buf,
776  int len,
777  int* type,
778  Local<Array> ret,
779  void* addrttls = nullptr,
780  int* naddrttls = nullptr) {
781  HandleScope handle_scope(env->isolate());
782  auto context = env->context();
783  hostent* host;
784 
785  int status;
786  switch (*type) {
787  case ns_t_a:
788  case ns_t_cname:
789  case ns_t_cname_or_a:
790  status = ares_parse_a_reply(buf,
791  len,
792  &host,
793  static_cast<ares_addrttl*>(addrttls),
794  naddrttls);
795  break;
796  case ns_t_aaaa:
797  status = ares_parse_aaaa_reply(buf,
798  len,
799  &host,
800  static_cast<ares_addr6ttl*>(addrttls),
801  naddrttls);
802  break;
803  case ns_t_ns:
804  status = ares_parse_ns_reply(buf, len, &host);
805  break;
806  case ns_t_ptr:
807  status = ares_parse_ptr_reply(buf, len, NULL, 0, AF_INET, &host);
808  break;
809  default:
810  CHECK(0 && "Bad NS type");
811  break;
812  }
813 
814  if (status != ARES_SUCCESS)
815  return status;
816 
817  /* If it's `CNAME`, return the CNAME value;
818  * And if it's `CNAME_OR_A` and it has value in `h_name` and `h_aliases[0]`,
819  * we consider it's a CNAME record, otherwise we consider it's an A record. */
820  if ((*type == ns_t_cname_or_a && host->h_name && host->h_aliases[0]) ||
821  *type == ns_t_cname) {
822  // A cname lookup always returns a single record but we follow the
823  // common API here.
824  *type = ns_t_cname;
825  ret->Set(context,
826  ret->Length(),
827  OneByteString(env->isolate(), host->h_name)).FromJust();
828  ares_free_hostent(host);
829  return ARES_SUCCESS;
830  }
831 
832  if (*type == ns_t_cname_or_a)
833  *type = ns_t_a;
834 
835  if (*type == ns_t_ns) {
836  HostentToNames(env, host, ret);
837  } else if (*type == ns_t_ptr) {
838  uint32_t offset = ret->Length();
839  for (uint32_t i = 0; host->h_aliases[i] != NULL; i++) {
840  ret->Set(context,
841  i + offset,
842  OneByteString(env->isolate(), host->h_aliases[i])).FromJust();
843  }
844  } else {
845  HostentToAddresses(env, host, ret);
846  }
847 
848  ares_free_hostent(host);
849 
850  return ARES_SUCCESS;
851 }
852 
853 
854 int ParseMxReply(Environment* env,
855  const unsigned char* buf,
856  int len,
857  Local<Array> ret,
858  bool need_type = false) {
859  HandleScope handle_scope(env->isolate());
860  auto context = env->context();
861 
862  struct ares_mx_reply* mx_start;
863  int status = ares_parse_mx_reply(buf, len, &mx_start);
864  if (status != ARES_SUCCESS) {
865  return status;
866  }
867 
868  Local<String> exchange_symbol = env->exchange_string();
869  Local<String> priority_symbol = env->priority_string();
870  Local<String> type_symbol = env->type_string();
871  Local<String> mx_symbol = env->dns_mx_string();
872 
873  uint32_t offset = ret->Length();
874  ares_mx_reply* current = mx_start;
875  for (uint32_t i = 0; current != nullptr; ++i, current = current->next) {
876  Local<Object> mx_record = Object::New(env->isolate());
877  mx_record->Set(context,
878  exchange_symbol,
879  OneByteString(env->isolate(), current->host)).FromJust();
880  mx_record->Set(context,
881  priority_symbol,
882  Integer::New(env->isolate(), current->priority)).FromJust();
883  if (need_type)
884  mx_record->Set(context, type_symbol, mx_symbol).FromJust();
885 
886  ret->Set(context, i + offset, mx_record).FromJust();
887  }
888 
889  ares_free_data(mx_start);
890  return ARES_SUCCESS;
891 }
892 
893 int ParseTxtReply(Environment* env,
894  const unsigned char* buf,
895  int len,
896  Local<Array> ret,
897  bool need_type = false) {
898  HandleScope handle_scope(env->isolate());
899  auto context = env->context();
900 
901  struct ares_txt_ext* txt_out;
902 
903  int status = ares_parse_txt_reply_ext(buf, len, &txt_out);
904  if (status != ARES_SUCCESS) {
905  return status;
906  }
907 
908  Local<Array> txt_chunk;
909 
910  struct ares_txt_ext* current = txt_out;
911  uint32_t i = 0, j;
912  uint32_t offset = ret->Length();
913  for (j = 0; current != nullptr; current = current->next) {
914  Local<String> txt = OneByteString(env->isolate(), current->txt);
915 
916  // New record found - write out the current chunk
917  if (current->record_start) {
918  if (!txt_chunk.IsEmpty()) {
919  if (need_type) {
920  Local<Object> elem = Object::New(env->isolate());
921  elem->Set(context, env->entries_string(), txt_chunk).FromJust();
922  elem->Set(context,
923  env->type_string(),
924  env->dns_txt_string()).FromJust();
925  ret->Set(context, offset + i++, elem).FromJust();
926  } else {
927  ret->Set(context, offset + i++, txt_chunk).FromJust();
928  }
929  }
930 
931  txt_chunk = Array::New(env->isolate());
932  j = 0;
933  }
934 
935  txt_chunk->Set(context, j++, txt).FromJust();
936  }
937 
938  // Push last chunk if it isn't empty
939  if (!txt_chunk.IsEmpty()) {
940  if (need_type) {
941  Local<Object> elem = Object::New(env->isolate());
942  elem->Set(context, env->entries_string(), txt_chunk).FromJust();
943  elem->Set(context,
944  env->type_string(),
945  env->dns_txt_string()).FromJust();
946  ret->Set(context, offset + i, elem).FromJust();
947  } else {
948  ret->Set(context, offset + i, txt_chunk).FromJust();
949  }
950  }
951 
952  ares_free_data(txt_out);
953  return ARES_SUCCESS;
954 }
955 
956 
957 int ParseSrvReply(Environment* env,
958  const unsigned char* buf,
959  int len,
960  Local<Array> ret,
961  bool need_type = false) {
962  HandleScope handle_scope(env->isolate());
963  auto context = env->context();
964 
965  struct ares_srv_reply* srv_start;
966  int status = ares_parse_srv_reply(buf, len, &srv_start);
967  if (status != ARES_SUCCESS) {
968  return status;
969  }
970 
971  Local<String> name_symbol = env->name_string();
972  Local<String> port_symbol = env->port_string();
973  Local<String> priority_symbol = env->priority_string();
974  Local<String> weight_symbol = env->weight_string();
975  Local<String> type_symbol = env->type_string();
976  Local<String> srv_symbol = env->dns_srv_string();
977 
978  ares_srv_reply* current = srv_start;
979  int offset = ret->Length();
980  for (uint32_t i = 0; current != nullptr; ++i, current = current->next) {
981  Local<Object> srv_record = Object::New(env->isolate());
982  srv_record->Set(context,
983  name_symbol,
984  OneByteString(env->isolate(), current->host)).FromJust();
985  srv_record->Set(context,
986  port_symbol,
987  Integer::New(env->isolate(), current->port)).FromJust();
988  srv_record->Set(context,
989  priority_symbol,
990  Integer::New(env->isolate(), current->priority)).FromJust();
991  srv_record->Set(context,
992  weight_symbol,
993  Integer::New(env->isolate(), current->weight)).FromJust();
994  if (need_type)
995  srv_record->Set(context, type_symbol, srv_symbol).FromJust();
996 
997  ret->Set(context, i + offset, srv_record).FromJust();
998  }
999 
1000  ares_free_data(srv_start);
1001  return ARES_SUCCESS;
1002 }
1003 
1004 
1005 int ParseNaptrReply(Environment* env,
1006  const unsigned char* buf,
1007  int len,
1008  Local<Array> ret,
1009  bool need_type = false) {
1010  HandleScope handle_scope(env->isolate());
1011  auto context = env->context();
1012 
1013  ares_naptr_reply* naptr_start;
1014  int status = ares_parse_naptr_reply(buf, len, &naptr_start);
1015 
1016  if (status != ARES_SUCCESS) {
1017  return status;
1018  }
1019 
1020  Local<String> flags_symbol = env->flags_string();
1021  Local<String> service_symbol = env->service_string();
1022  Local<String> regexp_symbol = env->regexp_string();
1023  Local<String> replacement_symbol = env->replacement_string();
1024  Local<String> order_symbol = env->order_string();
1025  Local<String> preference_symbol = env->preference_string();
1026  Local<String> type_symbol = env->type_string();
1027  Local<String> naptr_symbol = env->dns_naptr_string();
1028 
1029  ares_naptr_reply* current = naptr_start;
1030  int offset = ret->Length();
1031  for (uint32_t i = 0; current != nullptr; ++i, current = current->next) {
1032  Local<Object> naptr_record = Object::New(env->isolate());
1033  naptr_record->Set(context,
1034  flags_symbol,
1035  OneByteString(env->isolate(), current->flags)).FromJust();
1036  naptr_record->Set(context,
1037  service_symbol,
1038  OneByteString(env->isolate(),
1039  current->service)).FromJust();
1040  naptr_record->Set(context,
1041  regexp_symbol,
1042  OneByteString(env->isolate(),
1043  current->regexp)).FromJust();
1044  naptr_record->Set(context,
1045  replacement_symbol,
1046  OneByteString(env->isolate(),
1047  current->replacement)).FromJust();
1048  naptr_record->Set(context,
1049  order_symbol,
1050  Integer::New(env->isolate(), current->order)).FromJust();
1051  naptr_record->Set(context,
1052  preference_symbol,
1053  Integer::New(env->isolate(),
1054  current->preference)).FromJust();
1055  if (need_type)
1056  naptr_record->Set(context, type_symbol, naptr_symbol).FromJust();
1057 
1058  ret->Set(context, i + offset, naptr_record).FromJust();
1059  }
1060 
1061  ares_free_data(naptr_start);
1062  return ARES_SUCCESS;
1063 }
1064 
1065 
1066 int ParseSoaReply(Environment* env,
1067  unsigned char* buf,
1068  int len,
1069  Local<Object>* ret) {
1070  EscapableHandleScope handle_scope(env->isolate());
1071  auto context = env->context();
1072 
1073  /* Can't use ares_parse_soa_reply() here which can only parse single record */
1074  unsigned int ancount = cares_get_16bit(buf + 6);
1075  unsigned char* ptr = buf + NS_HFIXEDSZ;
1076  int rr_type, rr_len;
1077  char* name;
1078  char* rr_name;
1079  long temp_len; // NOLINT(runtime/int)
1080  int status = ares_expand_name(ptr, buf, len, &name, &temp_len);
1081  if (status != ARES_SUCCESS) {
1082  /* returns EBADRESP in case of invalid input */
1083  return status == ARES_EBADNAME ? ARES_EBADRESP : status;
1084  }
1085 
1086  if (ptr + temp_len + NS_QFIXEDSZ > buf + len) {
1087  free(name);
1088  return ARES_EBADRESP;
1089  }
1090  ptr += temp_len + NS_QFIXEDSZ;
1091 
1092  for (unsigned int i = 0; i < ancount; i++) {
1093  status = ares_expand_name(ptr, buf, len, &rr_name, &temp_len);
1094 
1095  if (status != ARES_SUCCESS)
1096  break;
1097 
1098  ptr += temp_len;
1099  if (ptr + NS_RRFIXEDSZ > buf + len) {
1100  free(rr_name);
1101  status = ARES_EBADRESP;
1102  break;
1103  }
1104 
1105  rr_type = cares_get_16bit(ptr);
1106  rr_len = cares_get_16bit(ptr + 8);
1107  ptr += NS_RRFIXEDSZ;
1108 
1109  /* only need SOA */
1110  if (rr_type == ns_t_soa) {
1111  ares_soa_reply soa;
1112 
1113  status = ares_expand_name(ptr, buf, len, &soa.nsname, &temp_len);
1114  if (status != ARES_SUCCESS) {
1115  free(rr_name);
1116  break;
1117  }
1118  ptr += temp_len;
1119 
1120  status = ares_expand_name(ptr, buf, len, &soa.hostmaster, &temp_len);
1121  if (status != ARES_SUCCESS) {
1122  free(rr_name);
1123  free(soa.nsname);
1124  break;
1125  }
1126  ptr += temp_len;
1127 
1128  if (ptr + 5 * 4 > buf + len) {
1129  free(rr_name);
1130  free(soa.nsname);
1131  free(soa.hostmaster);
1132  status = ARES_EBADRESP;
1133  break;
1134  }
1135 
1136  soa.serial = cares_get_32bit(ptr + 0 * 4);
1137  soa.refresh = cares_get_32bit(ptr + 1 * 4);
1138  soa.retry = cares_get_32bit(ptr + 2 * 4);
1139  soa.expire = cares_get_32bit(ptr + 3 * 4);
1140  soa.minttl = cares_get_32bit(ptr + 4 * 4);
1141 
1142  Local<Object> soa_record = Object::New(env->isolate());
1143  soa_record->Set(context,
1144  env->nsname_string(),
1145  OneByteString(env->isolate(), soa.nsname)).FromJust();
1146  soa_record->Set(context,
1147  env->hostmaster_string(),
1148  OneByteString(env->isolate(),
1149  soa.hostmaster)).FromJust();
1150  soa_record->Set(context,
1151  env->serial_string(),
1152  Integer::New(env->isolate(), soa.serial)).FromJust();
1153  soa_record->Set(context,
1154  env->refresh_string(),
1155  Integer::New(env->isolate(), soa.refresh)).FromJust();
1156  soa_record->Set(context,
1157  env->retry_string(),
1158  Integer::New(env->isolate(), soa.retry)).FromJust();
1159  soa_record->Set(context,
1160  env->expire_string(),
1161  Integer::New(env->isolate(), soa.expire)).FromJust();
1162  soa_record->Set(context,
1163  env->minttl_string(),
1164  Integer::New(env->isolate(), soa.minttl)).FromJust();
1165  soa_record->Set(context,
1166  env->type_string(),
1167  env->dns_soa_string()).FromJust();
1168 
1169  free(soa.nsname);
1170  free(soa.hostmaster);
1171 
1172  *ret = handle_scope.Escape(soa_record);
1173  break;
1174  }
1175 
1176  free(rr_name);
1177  ptr += rr_len;
1178  }
1179 
1180  free(name);
1181 
1182  if (status != ARES_SUCCESS) {
1183  return status == ARES_EBADNAME ? ARES_EBADRESP : status;
1184  }
1185 
1186  return ARES_SUCCESS;
1187 }
1188 
1189 
1190 class QueryAnyWrap: public QueryWrap {
1191  public:
1192  QueryAnyWrap(ChannelWrap* channel, Local<Object> req_wrap_obj)
1193  : QueryWrap(channel, req_wrap_obj) {
1194  }
1195 
1196  int Send(const char* name) override {
1197  AresQuery(name, ns_c_in, ns_t_any);
1198  return 0;
1199  }
1200 
1201  size_t self_size() const override { return sizeof(*this); }
1202 
1203  protected:
1204  void Parse(unsigned char* buf, int len) override {
1205  HandleScope handle_scope(env()->isolate());
1206  auto context = env()->context();
1207  Context::Scope context_scope(context);
1208 
1209  Local<Array> ret = Array::New(env()->isolate());
1210  int type, status, old_count;
1211 
1212  /* Parse A records or CNAME records */
1213  ares_addrttl addrttls[256];
1214  int naddrttls = arraysize(addrttls);
1215 
1216  type = ns_t_cname_or_a;
1217  status = ParseGeneralReply(env(),
1218  buf,
1219  len,
1220  &type,
1221  ret,
1222  addrttls,
1223  &naddrttls);
1224  int a_count = ret->Length();
1225  if (status != ARES_SUCCESS && status != ARES_ENODATA) {
1226  ParseError(status);
1227  return;
1228  }
1229 
1230  if (type == ns_t_a) {
1231  CHECK_EQ(naddrttls, a_count);
1232  for (int i = 0; i < a_count; i++) {
1233  Local<Object> obj = Object::New(env()->isolate());
1234  obj->Set(context, env()->address_string(), ret->Get(i)).FromJust();
1235  obj->Set(context,
1236  env()->ttl_string(),
1237  Integer::New(env()->isolate(), addrttls[i].ttl)).FromJust();
1238  obj->Set(context,
1239  env()->type_string(),
1240  env()->dns_a_string()).FromJust();
1241  ret->Set(context, i, obj).FromJust();
1242  }
1243  } else {
1244  for (int i = 0; i < a_count; i++) {
1245  Local<Object> obj = Object::New(env()->isolate());
1246  obj->Set(context, env()->value_string(), ret->Get(i)).FromJust();
1247  obj->Set(context,
1248  env()->type_string(),
1249  env()->dns_cname_string()).FromJust();
1250  ret->Set(context, i, obj).FromJust();
1251  }
1252  }
1253 
1254  /* Parse AAAA records */
1255  ares_addr6ttl addr6ttls[256];
1256  int naddr6ttls = arraysize(addr6ttls);
1257 
1258  type = ns_t_aaaa;
1259  status = ParseGeneralReply(env(),
1260  buf,
1261  len,
1262  &type,
1263  ret,
1264  addr6ttls,
1265  &naddr6ttls);
1266  int aaaa_count = ret->Length() - a_count;
1267  if (status != ARES_SUCCESS && status != ARES_ENODATA) {
1268  ParseError(status);
1269  return;
1270  }
1271 
1272  CHECK_EQ(aaaa_count, naddr6ttls);
1273  for (uint32_t i = a_count; i < ret->Length(); i++) {
1274  Local<Object> obj = Object::New(env()->isolate());
1275  obj->Set(context, env()->address_string(), ret->Get(i)).FromJust();
1276  obj->Set(context,
1277  env()->ttl_string(),
1278  Integer::New(env()->isolate(), addr6ttls[i].ttl)).FromJust();
1279  obj->Set(context,
1280  env()->type_string(),
1281  env()->dns_aaaa_string()).FromJust();
1282  ret->Set(context, i, obj).FromJust();
1283  }
1284 
1285  /* Parse MX records */
1286  status = ParseMxReply(env(), buf, len, ret, true);
1287  if (status != ARES_SUCCESS && status != ARES_ENODATA) {
1288  ParseError(status);
1289  return;
1290  }
1291 
1292  /* Parse NS records */
1293  type = ns_t_ns;
1294  old_count = ret->Length();
1295  status = ParseGeneralReply(env(), buf, len, &type, ret);
1296  if (status != ARES_SUCCESS && status != ARES_ENODATA) {
1297  ParseError(status);
1298  return;
1299  }
1300  for (uint32_t i = old_count; i < ret->Length(); i++) {
1301  Local<Object> obj = Object::New(env()->isolate());
1302  obj->Set(context, env()->value_string(), ret->Get(i)).FromJust();
1303  obj->Set(context,
1304  env()->type_string(),
1305  env()->dns_ns_string()).FromJust();
1306  ret->Set(context, i, obj).FromJust();
1307  }
1308 
1309  /* Parse TXT records */
1310  status = ParseTxtReply(env(), buf, len, ret, true);
1311  if (status != ARES_SUCCESS && status != ARES_ENODATA) {
1312  ParseError(status);
1313  return;
1314  }
1315 
1316  /* Parse SRV records */
1317  status = ParseSrvReply(env(), buf, len, ret, true);
1318  if (status != ARES_SUCCESS && status != ARES_ENODATA) {
1319  return;
1320  }
1321 
1322  /* Parse PTR records */
1323  type = ns_t_ptr;
1324  old_count = ret->Length();
1325  status = ParseGeneralReply(env(), buf, len, &type, ret);
1326  for (uint32_t i = old_count; i < ret->Length(); i++) {
1327  Local<Object> obj = Object::New(env()->isolate());
1328  obj->Set(context, env()->value_string(), ret->Get(i)).FromJust();
1329  obj->Set(context,
1330  env()->type_string(),
1331  env()->dns_ptr_string()).FromJust();
1332  ret->Set(context, i, obj).FromJust();
1333  }
1334 
1335  /* Parse NAPTR records */
1336  status = ParseNaptrReply(env(), buf, len, ret, true);
1337  if (status != ARES_SUCCESS && status != ARES_ENODATA) {
1338  ParseError(status);
1339  return;
1340  }
1341 
1342  /* Parse SOA records */
1343  Local<Object> soa_record = Local<Object>();
1344  status = ParseSoaReply(env(), buf, len, &soa_record);
1345  if (status != ARES_SUCCESS && status != ARES_ENODATA) {
1346  ParseError(status);
1347  return;
1348  }
1349  if (!soa_record.IsEmpty())
1350  ret->Set(context, ret->Length(), soa_record).FromJust();
1351 
1352  CallOnComplete(ret);
1353  }
1354 };
1355 
1356 
1357 class QueryAWrap: public QueryWrap {
1358  public:
1359  QueryAWrap(ChannelWrap* channel, Local<Object> req_wrap_obj)
1360  : QueryWrap(channel, req_wrap_obj) {
1361  }
1362 
1363  int Send(const char* name) override {
1364  AresQuery(name, ns_c_in, ns_t_a);
1365  return 0;
1366  }
1367 
1368  size_t self_size() const override { return sizeof(*this); }
1369 
1370  protected:
1371  void Parse(unsigned char* buf, int len) override {
1372  HandleScope handle_scope(env()->isolate());
1373  Context::Scope context_scope(env()->context());
1374 
1375  ares_addrttl addrttls[256];
1376  int naddrttls = arraysize(addrttls), status;
1377  Local<Array> ret = Array::New(env()->isolate());
1378 
1379  int type = ns_t_a;
1380  status = ParseGeneralReply(env(),
1381  buf,
1382  len,
1383  &type,
1384  ret,
1385  addrttls,
1386  &naddrttls);
1387  if (status != ARES_SUCCESS) {
1388  ParseError(status);
1389  return;
1390  }
1391 
1392  Local<Array> ttls = AddrTTLToArray<ares_addrttl>(env(),
1393  addrttls,
1394  naddrttls);
1395 
1396  CallOnComplete(ret, ttls);
1397  }
1398 };
1399 
1400 
1401 class QueryAaaaWrap: public QueryWrap {
1402  public:
1403  QueryAaaaWrap(ChannelWrap* channel, Local<Object> req_wrap_obj)
1404  : QueryWrap(channel, req_wrap_obj) {
1405  }
1406 
1407  int Send(const char* name) override {
1408  AresQuery(name, ns_c_in, ns_t_aaaa);
1409  return 0;
1410  }
1411 
1412  size_t self_size() const override { return sizeof(*this); }
1413 
1414  protected:
1415  void Parse(unsigned char* buf, int len) override {
1416  HandleScope handle_scope(env()->isolate());
1417  Context::Scope context_scope(env()->context());
1418 
1419  ares_addr6ttl addrttls[256];
1420  int naddrttls = arraysize(addrttls), status;
1421  Local<Array> ret = Array::New(env()->isolate());
1422 
1423  int type = ns_t_aaaa;
1424  status = ParseGeneralReply(env(),
1425  buf,
1426  len,
1427  &type,
1428  ret,
1429  addrttls,
1430  &naddrttls);
1431  if (status != ARES_SUCCESS) {
1432  ParseError(status);
1433  return;
1434  }
1435 
1436  Local<Array> ttls = AddrTTLToArray<ares_addr6ttl>(env(),
1437  addrttls,
1438  naddrttls);
1439 
1440  CallOnComplete(ret, ttls);
1441  }
1442 };
1443 
1444 
1445 class QueryCnameWrap: public QueryWrap {
1446  public:
1447  QueryCnameWrap(ChannelWrap* channel, Local<Object> req_wrap_obj)
1448  : QueryWrap(channel, req_wrap_obj) {
1449  }
1450 
1451  int Send(const char* name) override {
1452  AresQuery(name, ns_c_in, ns_t_cname);
1453  return 0;
1454  }
1455 
1456  size_t self_size() const override { return sizeof(*this); }
1457 
1458  protected:
1459  void Parse(unsigned char* buf, int len) override {
1460  HandleScope handle_scope(env()->isolate());
1461  Context::Scope context_scope(env()->context());
1462 
1463  Local<Array> ret = Array::New(env()->isolate());
1464  int type = ns_t_cname;
1465  int status = ParseGeneralReply(env(), buf, len, &type, ret);
1466  if (status != ARES_SUCCESS) {
1467  ParseError(status);
1468  return;
1469  }
1470 
1471  this->CallOnComplete(ret);
1472  }
1473 };
1474 
1475 
1476 class QueryMxWrap: public QueryWrap {
1477  public:
1478  QueryMxWrap(ChannelWrap* channel, Local<Object> req_wrap_obj)
1479  : QueryWrap(channel, req_wrap_obj) {
1480  }
1481 
1482  int Send(const char* name) override {
1483  AresQuery(name, ns_c_in, ns_t_mx);
1484  return 0;
1485  }
1486 
1487  size_t self_size() const override { return sizeof(*this); }
1488 
1489  protected:
1490  void Parse(unsigned char* buf, int len) override {
1491  HandleScope handle_scope(env()->isolate());
1492  Context::Scope context_scope(env()->context());
1493 
1494  Local<Array> mx_records = Array::New(env()->isolate());
1495  int status = ParseMxReply(env(), buf, len, mx_records);
1496 
1497  if (status != ARES_SUCCESS) {
1498  ParseError(status);
1499  return;
1500  }
1501 
1502  this->CallOnComplete(mx_records);
1503  }
1504 };
1505 
1506 
1507 class QueryNsWrap: public QueryWrap {
1508  public:
1509  QueryNsWrap(ChannelWrap* channel, Local<Object> req_wrap_obj)
1510  : QueryWrap(channel, req_wrap_obj) {
1511  }
1512 
1513  int Send(const char* name) override {
1514  AresQuery(name, ns_c_in, ns_t_ns);
1515  return 0;
1516  }
1517 
1518  size_t self_size() const override { return sizeof(*this); }
1519 
1520  protected:
1521  void Parse(unsigned char* buf, int len) override {
1522  HandleScope handle_scope(env()->isolate());
1523  Context::Scope context_scope(env()->context());
1524 
1525  int type = ns_t_ns;
1526  Local<Array> names = Array::New(env()->isolate());
1527  int status = ParseGeneralReply(env(), buf, len, &type, names);
1528  if (status != ARES_SUCCESS) {
1529  ParseError(status);
1530  return;
1531  }
1532 
1533  this->CallOnComplete(names);
1534  }
1535 };
1536 
1537 
1538 class QueryTxtWrap: public QueryWrap {
1539  public:
1540  QueryTxtWrap(ChannelWrap* channel, Local<Object> req_wrap_obj)
1541  : QueryWrap(channel, req_wrap_obj) {
1542  }
1543 
1544  int Send(const char* name) override {
1545  AresQuery(name, ns_c_in, ns_t_txt);
1546  return 0;
1547  }
1548 
1549  size_t self_size() const override { return sizeof(*this); }
1550 
1551  protected:
1552  void Parse(unsigned char* buf, int len) override {
1553  HandleScope handle_scope(env()->isolate());
1554  Context::Scope context_scope(env()->context());
1555 
1556  Local<Array> txt_records = Array::New(env()->isolate());
1557  int status = ParseTxtReply(env(), buf, len, txt_records);
1558  if (status != ARES_SUCCESS) {
1559  ParseError(status);
1560  return;
1561  }
1562 
1563  this->CallOnComplete(txt_records);
1564  }
1565 };
1566 
1567 
1568 class QuerySrvWrap: public QueryWrap {
1569  public:
1570  explicit QuerySrvWrap(ChannelWrap* channel, Local<Object> req_wrap_obj)
1571  : QueryWrap(channel, req_wrap_obj) {
1572  }
1573 
1574  int Send(const char* name) override {
1575  AresQuery(name, ns_c_in, ns_t_srv);
1576  return 0;
1577  }
1578 
1579  size_t self_size() const override { return sizeof(*this); }
1580 
1581  protected:
1582  void Parse(unsigned char* buf, int len) override {
1583  HandleScope handle_scope(env()->isolate());
1584  Context::Scope context_scope(env()->context());
1585 
1586  Local<Array> srv_records = Array::New(env()->isolate());
1587  int status = ParseSrvReply(env(), buf, len, srv_records);
1588  if (status != ARES_SUCCESS) {
1589  ParseError(status);
1590  return;
1591  }
1592 
1593  this->CallOnComplete(srv_records);
1594  }
1595 };
1596 
1597 class QueryPtrWrap: public QueryWrap {
1598  public:
1599  explicit QueryPtrWrap(ChannelWrap* channel, Local<Object> req_wrap_obj)
1600  : QueryWrap(channel, req_wrap_obj) {
1601  }
1602 
1603  int Send(const char* name) override {
1604  AresQuery(name, ns_c_in, ns_t_ptr);
1605  return 0;
1606  }
1607 
1608  size_t self_size() const override { return sizeof(*this); }
1609 
1610  protected:
1611  void Parse(unsigned char* buf, int len) override {
1612  HandleScope handle_scope(env()->isolate());
1613  Context::Scope context_scope(env()->context());
1614 
1615  int type = ns_t_ptr;
1616  Local<Array> aliases = Array::New(env()->isolate());
1617 
1618  int status = ParseGeneralReply(env(), buf, len, &type, aliases);
1619  if (status != ARES_SUCCESS) {
1620  ParseError(status);
1621  return;
1622  }
1623 
1624  this->CallOnComplete(aliases);
1625  }
1626 };
1627 
1628 class QueryNaptrWrap: public QueryWrap {
1629  public:
1630  explicit QueryNaptrWrap(ChannelWrap* channel, Local<Object> req_wrap_obj)
1631  : QueryWrap(channel, req_wrap_obj) {
1632  }
1633 
1634  int Send(const char* name) override {
1635  AresQuery(name, ns_c_in, ns_t_naptr);
1636  return 0;
1637  }
1638 
1639  size_t self_size() const override { return sizeof(*this); }
1640 
1641  protected:
1642  void Parse(unsigned char* buf, int len) override {
1643  HandleScope handle_scope(env()->isolate());
1644  Context::Scope context_scope(env()->context());
1645 
1646  Local<Array> naptr_records = Array::New(env()->isolate());
1647  int status = ParseNaptrReply(env(), buf, len, naptr_records);
1648  if (status != ARES_SUCCESS) {
1649  ParseError(status);
1650  return;
1651  }
1652 
1653  this->CallOnComplete(naptr_records);
1654  }
1655 };
1656 
1657 
1658 class QuerySoaWrap: public QueryWrap {
1659  public:
1660  QuerySoaWrap(ChannelWrap* channel, Local<Object> req_wrap_obj)
1661  : QueryWrap(channel, req_wrap_obj) {
1662  }
1663 
1664  int Send(const char* name) override {
1665  AresQuery(name, ns_c_in, ns_t_soa);
1666  return 0;
1667  }
1668 
1669  size_t self_size() const override { return sizeof(*this); }
1670 
1671  protected:
1672  void Parse(unsigned char* buf, int len) override {
1673  HandleScope handle_scope(env()->isolate());
1674  auto context = env()->context();
1675  Context::Scope context_scope(context);
1676 
1677  ares_soa_reply* soa_out;
1678  int status = ares_parse_soa_reply(buf, len, &soa_out);
1679 
1680  if (status != ARES_SUCCESS) {
1681  ParseError(status);
1682  return;
1683  }
1684 
1685  Local<Object> soa_record = Object::New(env()->isolate());
1686 
1687  soa_record->Set(context,
1688  env()->nsname_string(),
1689  OneByteString(env()->isolate(),
1690  soa_out->nsname)).FromJust();
1691  soa_record->Set(context,
1692  env()->hostmaster_string(),
1693  OneByteString(env()->isolate(),
1694  soa_out->hostmaster)).FromJust();
1695  soa_record->Set(context,
1696  env()->serial_string(),
1697  Integer::New(env()->isolate(), soa_out->serial)).FromJust();
1698  soa_record->Set(context,
1699  env()->refresh_string(),
1700  Integer::New(env()->isolate(),
1701  soa_out->refresh)).FromJust();
1702  soa_record->Set(context,
1703  env()->retry_string(),
1704  Integer::New(env()->isolate(), soa_out->retry)).FromJust();
1705  soa_record->Set(context,
1706  env()->expire_string(),
1707  Integer::New(env()->isolate(), soa_out->expire)).FromJust();
1708  soa_record->Set(context,
1709  env()->minttl_string(),
1710  Integer::New(env()->isolate(), soa_out->minttl)).FromJust();
1711 
1712  ares_free_data(soa_out);
1713 
1714  this->CallOnComplete(soa_record);
1715  }
1716 };
1717 
1718 
1719 class GetHostByAddrWrap: public QueryWrap {
1720  public:
1721  explicit GetHostByAddrWrap(ChannelWrap* channel, Local<Object> req_wrap_obj)
1722  : QueryWrap(channel, req_wrap_obj) {
1723  }
1724 
1725  int Send(const char* name) override {
1726  int length, family;
1727  char address_buffer[sizeof(struct in6_addr)];
1728 
1729  if (uv_inet_pton(AF_INET, name, &address_buffer) == 0) {
1730  length = sizeof(struct in_addr);
1731  family = AF_INET;
1732  } else if (uv_inet_pton(AF_INET6, name, &address_buffer) == 0) {
1733  length = sizeof(struct in6_addr);
1734  family = AF_INET6;
1735  } else {
1736  return UV_EINVAL; // So errnoException() reports a proper error.
1737  }
1738 
1739  ares_gethostbyaddr(channel_->cares_channel(),
1740  address_buffer,
1741  length,
1742  family,
1743  Callback,
1744  static_cast<void*>(static_cast<QueryWrap*>(this)));
1745  return 0;
1746  }
1747 
1748  size_t self_size() const override { return sizeof(*this); }
1749 
1750  protected:
1751  void Parse(struct hostent* host) override {
1752  HandleScope handle_scope(env()->isolate());
1753  Context::Scope context_scope(env()->context());
1754  this->CallOnComplete(HostentToNames(env(), host));
1755  }
1756 };
1757 
1758 
1759 class GetHostByNameWrap: public QueryWrap {
1760  public:
1761  explicit GetHostByNameWrap(ChannelWrap* channel, Local<Object> req_wrap_obj)
1762  : QueryWrap(channel, req_wrap_obj) {
1763  }
1764 
1765  int Send(const char* name, int family) override {
1766  ares_gethostbyname(channel_->cares_channel(),
1767  name,
1768  family,
1769  Callback,
1770  static_cast<void*>(static_cast<QueryWrap*>(this)));
1771  return 0;
1772  }
1773 
1774  protected:
1775  void Parse(struct hostent* host) override {
1776  HandleScope scope(env()->isolate());
1777 
1778  Local<Array> addresses = HostentToAddresses(env(), host);
1779  Local<Integer> family = Integer::New(env()->isolate(), host->h_addrtype);
1780 
1781  this->CallOnComplete(addresses, family);
1782  }
1783 };
1784 
1785 
1786 template <class Wrap>
1787 static void Query(const FunctionCallbackInfo<Value>& args) {
1788  Environment* env = Environment::GetCurrent(args);
1789  ChannelWrap* channel;
1790  ASSIGN_OR_RETURN_UNWRAP(&channel, args.Holder());
1791 
1792  CHECK_EQ(false, args.IsConstructCall());
1793  CHECK(args[0]->IsObject());
1794  CHECK(args[1]->IsString());
1795 
1796  Local<Object> req_wrap_obj = args[0].As<Object>();
1797  Local<String> string = args[1].As<String>();
1798  Wrap* wrap = new Wrap(channel, req_wrap_obj);
1799 
1800  node::Utf8Value name(env->isolate(), string);
1801  int err = wrap->Send(*name);
1802  if (err)
1803  delete wrap;
1804 
1805  args.GetReturnValue().Set(err);
1806 }
1807 
1808 
1809 void AfterGetAddrInfo(uv_getaddrinfo_t* req, int status, struct addrinfo* res) {
1810  GetAddrInfoReqWrap* req_wrap = static_cast<GetAddrInfoReqWrap*>(req->data);
1811  Environment* env = req_wrap->env();
1812 
1813  HandleScope handle_scope(env->isolate());
1814  Context::Scope context_scope(env->context());
1815 
1816  Local<Value> argv[] = {
1817  Integer::New(env->isolate(), status),
1818  Null(env->isolate())
1819  };
1820 
1821  if (status == 0) {
1822  int n = 0;
1823  Local<Array> results = Array::New(env->isolate());
1824 
1825  auto add = [&] (bool want_ipv4, bool want_ipv6) {
1826  for (auto p = res; p != nullptr; p = p->ai_next) {
1827  CHECK_EQ(p->ai_socktype, SOCK_STREAM);
1828 
1829  const char* addr;
1830  if (want_ipv4 && p->ai_family == AF_INET) {
1831  addr = reinterpret_cast<char*>(
1832  &(reinterpret_cast<struct sockaddr_in*>(p->ai_addr)->sin_addr));
1833  } else if (want_ipv6 && p->ai_family == AF_INET6) {
1834  addr = reinterpret_cast<char*>(
1835  &(reinterpret_cast<struct sockaddr_in6*>(p->ai_addr)->sin6_addr));
1836  } else {
1837  continue;
1838  }
1839 
1840  char ip[INET6_ADDRSTRLEN];
1841  if (uv_inet_ntop(p->ai_family, addr, ip, sizeof(ip)))
1842  continue;
1843 
1844  Local<String> s = OneByteString(env->isolate(), ip);
1845  results->Set(n, s);
1846  n++;
1847  }
1848  };
1849 
1850  const bool verbatim = req_wrap->verbatim();
1851  add(true, verbatim);
1852  if (verbatim == false)
1853  add(false, true);
1854 
1855  // No responses were found to return
1856  if (n == 0) {
1857  argv[0] = Integer::New(env->isolate(), UV_EAI_NODATA);
1858  }
1859 
1860  argv[1] = results;
1861  }
1862 
1863  uv_freeaddrinfo(res);
1864 
1865  // Make the callback into JavaScript
1866  req_wrap->MakeCallback(env->oncomplete_string(), arraysize(argv), argv);
1867 
1868  delete req_wrap;
1869 }
1870 
1871 
1872 void AfterGetNameInfo(uv_getnameinfo_t* req,
1873  int status,
1874  const char* hostname,
1875  const char* service) {
1876  GetNameInfoReqWrap* req_wrap = static_cast<GetNameInfoReqWrap*>(req->data);
1877  Environment* env = req_wrap->env();
1878 
1879  HandleScope handle_scope(env->isolate());
1880  Context::Scope context_scope(env->context());
1881 
1882  Local<Value> argv[] = {
1883  Integer::New(env->isolate(), status),
1884  Null(env->isolate()),
1885  Null(env->isolate())
1886  };
1887 
1888  if (status == 0) {
1889  // Success
1890  Local<String> js_hostname = OneByteString(env->isolate(), hostname);
1891  Local<String> js_service = OneByteString(env->isolate(), service);
1892  argv[1] = js_hostname;
1893  argv[2] = js_service;
1894  }
1895 
1896  // Make the callback into JavaScript
1897  req_wrap->MakeCallback(env->oncomplete_string(), arraysize(argv), argv);
1898 
1899  delete req_wrap;
1900 }
1901 
1902 
1903 void IsIP(const FunctionCallbackInfo<Value>& args) {
1904  node::Utf8Value ip(args.GetIsolate(), args[0]);
1905  char address_buffer[sizeof(struct in6_addr)];
1906 
1907  int rc = 0;
1908  if (uv_inet_pton(AF_INET, *ip, &address_buffer) == 0)
1909  rc = 4;
1910  else if (uv_inet_pton(AF_INET6, *ip, &address_buffer) == 0)
1911  rc = 6;
1912 
1913  args.GetReturnValue().Set(rc);
1914 }
1915 
1916 void IsIPv4(const FunctionCallbackInfo<Value>& args) {
1917  node::Utf8Value ip(args.GetIsolate(), args[0]);
1918  char address_buffer[sizeof(struct in_addr)];
1919 
1920  if (uv_inet_pton(AF_INET, *ip, &address_buffer) == 0) {
1921  args.GetReturnValue().Set(true);
1922  } else {
1923  args.GetReturnValue().Set(false);
1924  }
1925 }
1926 
1927 void IsIPv6(const FunctionCallbackInfo<Value>& args) {
1928  node::Utf8Value ip(args.GetIsolate(), args[0]);
1929  char address_buffer[sizeof(struct in6_addr)];
1930 
1931  if (uv_inet_pton(AF_INET6, *ip, &address_buffer) == 0) {
1932  args.GetReturnValue().Set(true);
1933  } else {
1934  args.GetReturnValue().Set(false);
1935  }
1936 }
1937 
1938 void GetAddrInfo(const FunctionCallbackInfo<Value>& args) {
1939  Environment* env = Environment::GetCurrent(args);
1940 
1941  CHECK(args[0]->IsObject());
1942  CHECK(args[1]->IsString());
1943  CHECK(args[2]->IsInt32());
1944  CHECK(args[4]->IsBoolean());
1945  Local<Object> req_wrap_obj = args[0].As<Object>();
1946  node::Utf8Value hostname(env->isolate(), args[1]);
1947 
1948  int32_t flags = (args[3]->IsInt32()) ? args[3]->Int32Value() : 0;
1949  int family;
1950 
1951  switch (args[2]->Int32Value()) {
1952  case 0:
1953  family = AF_UNSPEC;
1954  break;
1955  case 4:
1956  family = AF_INET;
1957  break;
1958  case 6:
1959  family = AF_INET6;
1960  break;
1961  default:
1962  CHECK(0 && "bad address family");
1963  }
1964 
1965  auto req_wrap = new GetAddrInfoReqWrap(env, req_wrap_obj, args[4]->IsTrue());
1966 
1967  struct addrinfo hints;
1968  memset(&hints, 0, sizeof(struct addrinfo));
1969  hints.ai_family = family;
1970  hints.ai_socktype = SOCK_STREAM;
1971  hints.ai_flags = flags;
1972 
1973  int err = uv_getaddrinfo(env->event_loop(),
1974  req_wrap->req(),
1975  AfterGetAddrInfo,
1976  *hostname,
1977  nullptr,
1978  &hints);
1979  req_wrap->Dispatched();
1980  if (err)
1981  delete req_wrap;
1982 
1983  args.GetReturnValue().Set(err);
1984 }
1985 
1986 
1987 void GetNameInfo(const FunctionCallbackInfo<Value>& args) {
1988  Environment* env = Environment::GetCurrent(args);
1989 
1990  CHECK(args[0]->IsObject());
1991  CHECK(args[1]->IsString());
1992  CHECK(args[2]->IsUint32());
1993  Local<Object> req_wrap_obj = args[0].As<Object>();
1994  node::Utf8Value ip(env->isolate(), args[1]);
1995  const unsigned port = args[2]->Uint32Value();
1996  struct sockaddr_storage addr;
1997 
1998  CHECK(uv_ip4_addr(*ip, port, reinterpret_cast<sockaddr_in*>(&addr)) == 0 ||
1999  uv_ip6_addr(*ip, port, reinterpret_cast<sockaddr_in6*>(&addr)) == 0);
2000 
2001  GetNameInfoReqWrap* req_wrap = new GetNameInfoReqWrap(env, req_wrap_obj);
2002 
2003  int err = uv_getnameinfo(env->event_loop(),
2004  req_wrap->req(),
2005  AfterGetNameInfo,
2006  (struct sockaddr*)&addr,
2007  NI_NAMEREQD);
2008  req_wrap->Dispatched();
2009  if (err)
2010  delete req_wrap;
2011 
2012  args.GetReturnValue().Set(err);
2013 }
2014 
2015 
2016 void GetServers(const FunctionCallbackInfo<Value>& args) {
2017  Environment* env = Environment::GetCurrent(args);
2018  ChannelWrap* channel;
2019  ASSIGN_OR_RETURN_UNWRAP(&channel, args.Holder());
2020 
2021  Local<Array> server_array = Array::New(env->isolate());
2022 
2023  ares_addr_port_node* servers;
2024 
2025  int r = ares_get_servers_ports(channel->cares_channel(), &servers);
2026  CHECK_EQ(r, ARES_SUCCESS);
2027 
2028  ares_addr_port_node* cur = servers;
2029 
2030  for (uint32_t i = 0; cur != nullptr; ++i, cur = cur->next) {
2031  char ip[INET6_ADDRSTRLEN];
2032 
2033  const void* caddr = static_cast<const void*>(&cur->addr);
2034  int err = uv_inet_ntop(cur->family, caddr, ip, sizeof(ip));
2035  CHECK_EQ(err, 0);
2036 
2037  Local<Array> ret = Array::New(env->isolate(), 2);
2038  ret->Set(0, OneByteString(env->isolate(), ip));
2039  ret->Set(1, Integer::New(env->isolate(), cur->udp_port));
2040 
2041  server_array->Set(i, ret);
2042  }
2043 
2044  ares_free_data(servers);
2045 
2046  args.GetReturnValue().Set(server_array);
2047 }
2048 
2049 
2050 void SetServers(const FunctionCallbackInfo<Value>& args) {
2051  Environment* env = Environment::GetCurrent(args);
2052  ChannelWrap* channel;
2053  ASSIGN_OR_RETURN_UNWRAP(&channel, args.Holder());
2054 
2055  CHECK(args[0]->IsArray());
2056 
2057  Local<Array> arr = Local<Array>::Cast(args[0]);
2058 
2059  uint32_t len = arr->Length();
2060 
2061  if (len == 0) {
2062  int rv = ares_set_servers(channel->cares_channel(), nullptr);
2063  return args.GetReturnValue().Set(rv);
2064  }
2065 
2066  std::vector<ares_addr_port_node> servers(len);
2067  ares_addr_port_node* last = nullptr;
2068 
2069  int err;
2070 
2071  for (uint32_t i = 0; i < len; i++) {
2072  CHECK(arr->Get(i)->IsArray());
2073 
2074  Local<Array> elm = Local<Array>::Cast(arr->Get(i));
2075 
2076  CHECK(elm->Get(0)->Int32Value());
2077  CHECK(elm->Get(1)->IsString());
2078  CHECK(elm->Get(2)->Int32Value());
2079 
2080  int fam = elm->Get(0)->Int32Value();
2081  node::Utf8Value ip(env->isolate(), elm->Get(1));
2082  int port = elm->Get(2)->Int32Value();
2083 
2084  ares_addr_port_node* cur = &servers[i];
2085 
2086  cur->tcp_port = cur->udp_port = port;
2087  switch (fam) {
2088  case 4:
2089  cur->family = AF_INET;
2090  err = uv_inet_pton(AF_INET, *ip, &cur->addr);
2091  break;
2092  case 6:
2093  cur->family = AF_INET6;
2094  err = uv_inet_pton(AF_INET6, *ip, &cur->addr);
2095  break;
2096  default:
2097  CHECK(0 && "Bad address family.");
2098  }
2099 
2100  if (err)
2101  break;
2102 
2103  cur->next = nullptr;
2104 
2105  if (last != nullptr)
2106  last->next = cur;
2107 
2108  last = cur;
2109  }
2110 
2111  if (err == 0)
2112  err = ares_set_servers_ports(channel->cares_channel(), &servers[0]);
2113  else
2114  err = ARES_EBADSTR;
2115 
2116  if (err == ARES_SUCCESS)
2117  channel->set_is_servers_default(false);
2118 
2119  args.GetReturnValue().Set(err);
2120 }
2121 
2122 void Cancel(const FunctionCallbackInfo<Value>& args) {
2123  ChannelWrap* channel;
2124  ASSIGN_OR_RETURN_UNWRAP(&channel, args.Holder());
2125 
2126  ares_cancel(channel->cares_channel());
2127 }
2128 
2129 
2130 void StrError(const FunctionCallbackInfo<Value>& args) {
2131  Environment* env = Environment::GetCurrent(args);
2132  const char* errmsg = ares_strerror(args[0]->Int32Value());
2133  args.GetReturnValue().Set(OneByteString(env->isolate(), errmsg));
2134 }
2135 
2136 
2137 void Initialize(Local<Object> target,
2138  Local<Value> unused,
2139  Local<Context> context) {
2140  Environment* env = Environment::GetCurrent(context);
2141 
2142  env->SetMethod(target, "getaddrinfo", GetAddrInfo);
2143  env->SetMethod(target, "getnameinfo", GetNameInfo);
2144  env->SetMethod(target, "isIP", IsIP);
2145  env->SetMethod(target, "isIPv4", IsIPv4);
2146  env->SetMethod(target, "isIPv6", IsIPv6);
2147 
2148  env->SetMethod(target, "strerror", StrError);
2149 
2150  target->Set(FIXED_ONE_BYTE_STRING(env->isolate(), "AF_INET"),
2151  Integer::New(env->isolate(), AF_INET));
2152  target->Set(FIXED_ONE_BYTE_STRING(env->isolate(), "AF_INET6"),
2153  Integer::New(env->isolate(), AF_INET6));
2154  target->Set(FIXED_ONE_BYTE_STRING(env->isolate(), "AF_UNSPEC"),
2155  Integer::New(env->isolate(), AF_UNSPEC));
2156  target->Set(FIXED_ONE_BYTE_STRING(env->isolate(), "AI_ADDRCONFIG"),
2157  Integer::New(env->isolate(), AI_ADDRCONFIG));
2158  target->Set(FIXED_ONE_BYTE_STRING(env->isolate(), "AI_V4MAPPED"),
2159  Integer::New(env->isolate(), AI_V4MAPPED));
2160 
2161  auto is_construct_call_callback =
2162  [](const FunctionCallbackInfo<Value>& args) {
2163  CHECK(args.IsConstructCall());
2164  ClearWrap(args.This());
2165  };
2166  Local<FunctionTemplate> aiw =
2167  FunctionTemplate::New(env->isolate(), is_construct_call_callback);
2168  aiw->InstanceTemplate()->SetInternalFieldCount(1);
2169  AsyncWrap::AddWrapMethods(env, aiw);
2170  Local<String> addrInfoWrapString =
2171  FIXED_ONE_BYTE_STRING(env->isolate(), "GetAddrInfoReqWrap");
2172  aiw->SetClassName(addrInfoWrapString);
2173  target->Set(addrInfoWrapString, aiw->GetFunction());
2174 
2175  Local<FunctionTemplate> niw =
2176  FunctionTemplate::New(env->isolate(), is_construct_call_callback);
2177  niw->InstanceTemplate()->SetInternalFieldCount(1);
2178  AsyncWrap::AddWrapMethods(env, niw);
2179  Local<String> nameInfoWrapString =
2180  FIXED_ONE_BYTE_STRING(env->isolate(), "GetNameInfoReqWrap");
2181  niw->SetClassName(nameInfoWrapString);
2182  target->Set(nameInfoWrapString, niw->GetFunction());
2183 
2184  Local<FunctionTemplate> qrw =
2185  FunctionTemplate::New(env->isolate(), is_construct_call_callback);
2186  qrw->InstanceTemplate()->SetInternalFieldCount(1);
2187  AsyncWrap::AddWrapMethods(env, qrw);
2188  Local<String> queryWrapString =
2189  FIXED_ONE_BYTE_STRING(env->isolate(), "QueryReqWrap");
2190  qrw->SetClassName(queryWrapString);
2191  target->Set(queryWrapString, qrw->GetFunction());
2192 
2193  Local<FunctionTemplate> channel_wrap =
2194  env->NewFunctionTemplate(ChannelWrap::New);
2195  channel_wrap->InstanceTemplate()->SetInternalFieldCount(1);
2196  AsyncWrap::AddWrapMethods(env, channel_wrap);
2197 
2198  env->SetProtoMethod(channel_wrap, "queryAny", Query<QueryAnyWrap>);
2199  env->SetProtoMethod(channel_wrap, "queryA", Query<QueryAWrap>);
2200  env->SetProtoMethod(channel_wrap, "queryAaaa", Query<QueryAaaaWrap>);
2201  env->SetProtoMethod(channel_wrap, "queryCname", Query<QueryCnameWrap>);
2202  env->SetProtoMethod(channel_wrap, "queryMx", Query<QueryMxWrap>);
2203  env->SetProtoMethod(channel_wrap, "queryNs", Query<QueryNsWrap>);
2204  env->SetProtoMethod(channel_wrap, "queryTxt", Query<QueryTxtWrap>);
2205  env->SetProtoMethod(channel_wrap, "querySrv", Query<QuerySrvWrap>);
2206  env->SetProtoMethod(channel_wrap, "queryPtr", Query<QueryPtrWrap>);
2207  env->SetProtoMethod(channel_wrap, "queryNaptr", Query<QueryNaptrWrap>);
2208  env->SetProtoMethod(channel_wrap, "querySoa", Query<QuerySoaWrap>);
2209  env->SetProtoMethod(channel_wrap, "getHostByAddr", Query<GetHostByAddrWrap>);
2210 
2211  env->SetProtoMethod(channel_wrap, "getServers", GetServers);
2212  env->SetProtoMethod(channel_wrap, "setServers", SetServers);
2213  env->SetProtoMethod(channel_wrap, "cancel", Cancel);
2214 
2215  Local<String> channelWrapString =
2216  FIXED_ONE_BYTE_STRING(env->isolate(), "ChannelWrap");
2217  channel_wrap->SetClassName(channelWrapString);
2218  target->Set(channelWrapString, channel_wrap->GetFunction());
2219 }
2220 
2221 } // anonymous namespace
2222 } // namespace cares_wrap
2223 } // namespace node
2224 
uv_poll_t poll_watcher
Definition: cares_wrap.cc:124
unsigned char * buf
Definition: cares_wrap.cc:483
NODE_MODULE_CONTEXT_AWARE_BUILTIN(inspector, node::inspector::Agent::InitInspector)
int len
Definition: cares_wrap.cc:485
QueryWrap * wrap
Definition: cares_wrap.cc:478
int status
Definition: cares_wrap.cc:479
union node::cares_wrap::@8::CaresAsyncData::@0 data
hostent * host
Definition: cares_wrap.cc:482
#define V(code)
bool is_host
Definition: cares_wrap.cc:480
dtrace a
Definition: v8ustack.d:531
void Initialize(Local< Object > target, Local< Value > unused, Local< Context > context, void *priv)
Definition: node_http2.cc:1172
dtrace p
Definition: v8ustack.d:615
dtrace s
Definition: v8ustack.d:615
ChannelWrap * channel
Definition: cares_wrap.cc:122
uv_fs_t req
Definition: node_file.cc:374
uv_async_t async_handle
Definition: cares_wrap.cc:487
ares_socket_t sock
Definition: cares_wrap.cc:123
MaybeLocal< Object > New(Isolate *isolate, Local< String > string, enum encoding enc)
Definition: node_buffer.cc:241
MaybeLocal< Value > MakeCallback(Isolate *isolate, Local< Object > recv, Local< Function > callback, int argc, Local< Value > *argv, async_id asyncId, async_id triggerAsyncId)
Definition: async-wrap.cc:802
dtrace n
Definition: v8ustack.d:531