GCC Code Coverage Report
Directory: ../ Exec Total Coverage
File: /home/iojs/build/workspace/node-test-commit-linux-coverage-daily/nodes/benchmark/out/../src/cares_wrap.cc Lines: 50 1067 4.7 %
Date: 2019-02-01 22:03:38 Branches: 2 644 0.3 %

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

656
NODE_MODULE_CONTEXT_AWARE_INTERNAL(cares_wrap, node::cares_wrap::Initialize)