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: 974 1105 88.1 %
Date: 2019-09-12 22:30:12 Branches: 400 650 61.5 %

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 "memory_tracker-inl.h"
27
#include "node.h"
28
#include "req_wrap-inl.h"
29
#include "util-inl.h"
30
#include "uv.h"
31
32
#include <cerrno>
33
#include <cstring>
34
#include <memory>
35
#include <vector>
36
#include <unordered_set>
37
38
#ifdef __POSIX__
39
# include <netdb.h>
40
#endif  // __POSIX__
41
42
#if defined(__ANDROID__) || \
43
    defined(__MINGW32__) || \
44
    defined(__OpenBSD__) || \
45
    defined(_MSC_VER)
46
47
# include <nameser.h>
48
#else
49
# include <arpa/nameser.h>
50
#endif
51
52
#if defined(__OpenBSD__)
53
# define AI_V4MAPPED 0
54
#endif
55
56
namespace node {
57
namespace cares_wrap {
58
59
using v8::Array;
60
using v8::Context;
61
using v8::EscapableHandleScope;
62
using v8::FunctionCallbackInfo;
63
using v8::FunctionTemplate;
64
using v8::HandleScope;
65
using v8::Int32;
66
using v8::Integer;
67
using v8::Local;
68
using v8::Null;
69
using v8::Object;
70
using v8::String;
71
using v8::Value;
72
73
namespace {
74
75
4956
Mutex ares_library_mutex;
76
77
155
inline uint16_t cares_get_16bit(const unsigned char* p) {
78
155
  return static_cast<uint32_t>(p[0] << 8U) | (static_cast<uint32_t>(p[1]));
79
}
80
81
40
inline uint32_t cares_get_32bit(const unsigned char* p) {
82
80
  return static_cast<uint32_t>(p[0] << 24U) |
83
80
         static_cast<uint32_t>(p[1] << 16U) |
84
80
         static_cast<uint32_t>(p[2] << 8U) |
85
80
         static_cast<uint32_t>(p[3]);
86
}
87
88
const int ns_t_cname_or_a = -1;
89
90
#define DNS_ESETSRVPENDING -1000
91
34
inline const char* ToErrorCodeString(int status) {
92






34
  switch (status) {
93
#define V(code) case ARES_##code: return #code;
94
    V(EADDRGETNETWORKPARAMS)
95
    V(EBADFAMILY)
96
    V(EBADFLAGS)
97
    V(EBADHINTS)
98
    V(EBADNAME)
99
    V(EBADQUERY)
100
2
    V(EBADRESP)
101
    V(EBADSTR)
102
3
    V(ECANCELLED)
103
    V(ECONNREFUSED)
104
    V(EDESTRUCTION)
105
    V(EFILE)
106
    V(EFORMERR)
107
    V(ELOADIPHLPAPI)
108
8
    V(ENODATA)
109
    V(ENOMEM)
110
    V(ENONAME)
111
21
    V(ENOTFOUND)
112
    V(ENOTIMP)
113
    V(ENOTINITIALIZED)
114
    V(EOF)
115
    V(EREFUSED)
116
    V(ESERVFAIL)
117
    V(ETIMEOUT)
118
#undef V
119
  }
120
121
  return "UNKNOWN_ARES_ERROR";
122
}
123
124
class ChannelWrap;
125
126
460
struct node_ares_task : public MemoryRetainer {
127
  ChannelWrap* channel;
128
  ares_socket_t sock;
129
  uv_poll_t poll_watcher;
130
131
  inline void MemoryInfo(MemoryTracker* tracker) const override;
132
2
  SET_MEMORY_INFO_NAME(node_ares_task)
133
2
  SET_SELF_SIZE(node_ares_task)
134
};
135
136
struct TaskHash {
137
198
  size_t operator()(node_ares_task* a) const {
138
198
    return std::hash<ares_socket_t>()(a->sock);
139
  }
140
};
141
142
struct TaskEqual {
143
70
  inline bool operator()(node_ares_task* a, node_ares_task* b) const {
144
70
    return a->sock == b->sock;
145
  }
146
};
147
148
using node_ares_task_list =
149
    std::unordered_set<node_ares_task*, TaskHash, TaskEqual>;
150
151
class ChannelWrap : public AsyncWrap {
152
 public:
153
  ChannelWrap(Environment* env, Local<Object> object);
154
  ~ChannelWrap() override;
155
156
  static void New(const FunctionCallbackInfo<Value>& args);
157
158
  void Setup();
159
  void EnsureServers();
160
  void StartTimer();
161
  void CloseTimer();
162
163
  void ModifyActivityQueryCount(int count);
164
165
124
  inline uv_timer_t* timer_handle() { return timer_handle_; }
166
314
  inline ares_channel cares_channel() { return channel_; }
167
109
  inline void set_query_last_ok(bool ok) { query_last_ok_ = ok; }
168
19
  inline void set_is_servers_default(bool is_default) {
169
19
    is_servers_default_ = is_default;
170
19
  }
171
23
  inline int active_query_count() { return active_query_count_; }
172
481
  inline node_ares_task_list* task_list() { return &task_list_; }
173
174
12
  void MemoryInfo(MemoryTracker* tracker) const override {
175
12
    if (timer_handle_ != nullptr)
176
2
      tracker->TrackField("timer_handle", *timer_handle_);
177
12
    tracker->TrackField("task_list", task_list_, "node_ares_task_list");
178
12
  }
179
180
12
  SET_MEMORY_INFO_NAME(ChannelWrap)
181
12
  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
1103
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
1103
    active_query_count_(0) {
204
1103
  MakeWeak();
205
206
1103
  Setup();
207
1103
}
208
209
1103
void ChannelWrap::New(const FunctionCallbackInfo<Value>& args) {
210
1103
  CHECK(args.IsConstructCall());
211
1103
  CHECK_EQ(args.Length(), 0);
212
213
1103
  Environment* env = Environment::GetCurrent(args);
214
1103
  new ChannelWrap(env, args.This());
215
1103
}
216
217
10224
class GetAddrInfoReqWrap : public ReqWrap<uv_getaddrinfo_t> {
218
 public:
219
  GetAddrInfoReqWrap(Environment* env,
220
                     Local<Object> req_wrap_obj,
221
                     bool verbatim);
222
223
3
  SET_NO_MEMORY_INFO()
224
3
  SET_MEMORY_INFO_NAME(GetAddrInfoReqWrap)
225
3
  SET_SELF_SIZE(GetAddrInfoReqWrap)
226
227
5113
  bool verbatim() const { return verbatim_; }
228
229
 private:
230
  const bool verbatim_;
231
};
232
233
5156
GetAddrInfoReqWrap::GetAddrInfoReqWrap(Environment* env,
234
                                       Local<Object> req_wrap_obj,
235
                                       bool verbatim)
236
    : ReqWrap(env, req_wrap_obj, AsyncWrap::PROVIDER_GETADDRINFOREQWRAP)
237
5156
    , verbatim_(verbatim) {
238
5156
}
239
240
241
22
class GetNameInfoReqWrap : public ReqWrap<uv_getnameinfo_t> {
242
 public:
243
  GetNameInfoReqWrap(Environment* env, Local<Object> req_wrap_obj);
244
245
1
  SET_NO_MEMORY_INFO()
246
1
  SET_MEMORY_INFO_NAME(GetNameInfoReqWrap)
247
1
  SET_SELF_SIZE(GetNameInfoReqWrap)
248
};
249
250
11
GetNameInfoReqWrap::GetNameInfoReqWrap(Environment* env,
251
                                       Local<Object> req_wrap_obj)
252
11
    : ReqWrap(env, req_wrap_obj, AsyncWrap::PROVIDER_GETNAMEINFOREQWRAP) {
253
11
}
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
21
void ChannelWrap::AresTimeout(uv_timer_t* handle) {
259
21
  ChannelWrap* channel = static_cast<ChannelWrap*>(handle->data);
260
21
  CHECK_EQ(channel->timer_handle(), handle);
261
21
  CHECK_EQ(false, channel->task_list()->empty());
262
21
  ares_process_fd(channel->cares_channel(), ARES_SOCKET_BAD, ARES_SOCKET_BAD);
263
21
}
264
265
266
103
void ares_poll_cb(uv_poll_t* watcher, int status, int events) {
267
103
  node_ares_task* task = ContainerOf(&node_ares_task::poll_watcher, watcher);
268
103
  ChannelWrap* channel = task->channel;
269
270
  /* Reset the idle timer */
271
103
  uv_timer_again(channel->timer_handle());
272
273
103
  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
103
    return;
278
  }
279
280
  /* Process DNS responses */
281
  ares_process_fd(channel->cares_channel(),
282
103
                  events & UV_READABLE ? task->sock : ARES_SOCKET_BAD,
283

206
                  events & UV_WRITABLE ? task->sock : ARES_SOCKET_BAD);
284
}
285
286
287
64
void ares_poll_close_cb(uv_poll_t* watcher) {
288
64
  node_ares_task* task = ContainerOf(&node_ares_task::poll_watcher, watcher);
289
64
  delete task;
290
64
}
291
292
2
void node_ares_task::MemoryInfo(MemoryTracker* tracker) const {
293
2
  tracker->TrackField("channel", channel);
294
2
}
295
296
/* Allocates and returns a new node_ares_task */
297
64
node_ares_task* ares_task_create(ChannelWrap* channel, ares_socket_t sock) {
298
64
  auto task = new node_ares_task();
299
300
64
  task->channel = channel;
301
64
  task->sock = sock;
302
303
64
  if (uv_poll_init_socket(channel->env()->event_loop(),
304
64
                          &task->poll_watcher, sock) < 0) {
305
    /* This should never happen. */
306
    delete task;
307
    return nullptr;
308
  }
309
310
64
  return task;
311
}
312
313
314
/* Callback from ares when socket operation is started */
315
134
void ares_sockstate_cb(void* data,
316
                       ares_socket_t sock,
317
                       int read,
318
                       int write) {
319
134
  ChannelWrap* channel = static_cast<ChannelWrap*>(data);
320
  node_ares_task* task;
321
322
134
  node_ares_task lookup_task;
323
134
  lookup_task.sock = sock;
324
134
  auto it = channel->task_list()->find(&lookup_task);
325
326
134
  task = (it == channel->task_list()->end()) ? nullptr : *it;
327
328

134
  if (read || write) {
329
70
    if (!task) {
330
      /* New socket */
331
64
      channel->StartTimer();
332
333
64
      task = ares_task_create(channel, sock);
334
64
      if (task == nullptr) {
335
        /* This should never happen unless we're out of memory or something */
336
        /* is seriously wrong. The socket won't be polled, but the query will */
337
        /* eventually time out. */
338
134
        return;
339
      }
340
341
64
      channel->task_list()->insert(task);
342
    }
343
344
    /* This should never fail. If it fails anyway, the query will eventually */
345
    /* time out. */
346
    uv_poll_start(&task->poll_watcher,
347
                  (read ? UV_READABLE : 0) | (write ? UV_WRITABLE : 0),
348

70
                  ares_poll_cb);
349
350
  } else {
351
    /* read == 0 and write == 0 this is c-ares's way of notifying us that */
352
    /* the socket is now closed. We must free the data associated with */
353
    /* socket. */
354
64
    CHECK(task &&
355
          "When an ares socket is closed we should have a handle for it");
356
357
64
    channel->task_list()->erase(it);
358
64
    channel->env()->CloseHandle(&task->poll_watcher, ares_poll_close_cb);
359
360
64
    if (channel->task_list()->empty()) {
361
59
      channel->CloseTimer();
362
    }
363
134
  }
364
}
365
366
367
20
Local<Array> HostentToNames(Environment* env,
368
                            struct hostent* host,
369
                            Local<Array> append_to = Local<Array>()) {
370
20
  EscapableHandleScope scope(env->isolate());
371
20
  auto context = env->context();
372
20
  bool append = !append_to.IsEmpty();
373
20
  Local<Array> names = append ? append_to : Array::New(env->isolate());
374
20
  size_t offset = names->Length();
375
376
53
  for (uint32_t i = 0; host->h_aliases[i] != nullptr; ++i) {
377
33
    Local<String> address = OneByteString(env->isolate(), host->h_aliases[i]);
378
99
    names->Set(context, i + offset, address).Check();
379
  }
380
381
60
  return append ? names : scope.Escape(names);
382
}
383
384
7
void safe_free_hostent(struct hostent* host) {
385
  int idx;
386
387
7
  if (host->h_addr_list != nullptr) {
388
7
    idx = 0;
389
21
    while (host->h_addr_list[idx]) {
390
7
      free(host->h_addr_list[idx++]);
391
    }
392
7
    free(host->h_addr_list);
393
7
    host->h_addr_list = nullptr;
394
  }
395
396
7
  if (host->h_aliases != nullptr) {
397
7
    idx = 0;
398
19
    while (host->h_aliases[idx]) {
399
5
      free(host->h_aliases[idx++]);
400
    }
401
7
    free(host->h_aliases);
402
7
    host->h_aliases = nullptr;
403
  }
404
405
7
  free(host->h_name);
406
7
  free(host);
407
7
}
408
409
7
void cares_wrap_hostent_cpy(struct hostent* dest, const struct hostent* src) {
410
7
  dest->h_addr_list = nullptr;
411
7
  dest->h_addrtype = 0;
412
7
  dest->h_aliases = nullptr;
413
7
  dest->h_length = 0;
414
7
  dest->h_name = nullptr;
415
416
  /* copy `h_name` */
417
7
  size_t name_size = strlen(src->h_name) + 1;
418
7
  dest->h_name = node::Malloc<char>(name_size);
419
7
  memcpy(dest->h_name, src->h_name, name_size);
420
421
  /* copy `h_aliases` */
422
  size_t alias_count;
423
19
  for (alias_count = 0;
424
12
      src->h_aliases[alias_count] != nullptr;
425
      alias_count++) {
426
  }
427
428
7
  dest->h_aliases = node::Malloc<char*>(alias_count + 1);
429
12
  for (size_t i = 0; i < alias_count; i++) {
430
5
    const size_t cur_alias_size = strlen(src->h_aliases[i]) + 1;
431
5
    dest->h_aliases[i] = node::Malloc(cur_alias_size);
432
5
    memcpy(dest->h_aliases[i], src->h_aliases[i], cur_alias_size);
433
  }
434
7
  dest->h_aliases[alias_count] = nullptr;
435
436
  /* copy `h_addr_list` */
437
  size_t list_count;
438
21
  for (list_count = 0;
439
14
      src->h_addr_list[list_count] != nullptr;
440
      list_count++) {
441
  }
442
443
7
  dest->h_addr_list = node::Malloc<char*>(list_count + 1);
444
14
  for (size_t i = 0; i < list_count; i++) {
445
7
    dest->h_addr_list[i] = node::Malloc(src->h_length);
446
7
    memcpy(dest->h_addr_list[i], src->h_addr_list[i], src->h_length);
447
  }
448
7
  dest->h_addr_list[list_count] = nullptr;
449
450
  /* work after work */
451
7
  dest->h_length = src->h_length;
452
7
  dest->h_addrtype = src->h_addrtype;
453
7
}
454
455
class QueryWrap;
456
457
1103
void ChannelWrap::Setup() {
458
  struct ares_options options;
459
1103
  memset(&options, 0, sizeof(options));
460
1103
  options.flags = ARES_FLAG_NOCHECKRESP;
461
1103
  options.sock_state_cb = ares_sockstate_cb;
462
1103
  options.sock_state_cb_data = this;
463
464
  int r;
465
1103
  if (!library_inited_) {
466
1103
    Mutex::ScopedLock lock(ares_library_mutex);
467
    // Multiple calls to ares_library_init() increase a reference counter,
468
    // so this is a no-op except for the first call to it.
469
1103
    r = ares_library_init(ARES_LIB_INIT_ALL);
470
1103
    if (r != ARES_SUCCESS)
471
      return env()->ThrowError(ToErrorCodeString(r));
472
  }
473
474
  /* We do the call to ares_init_option for caller. */
475
  r = ares_init_options(&channel_,
476
                        &options,
477
1103
                        ARES_OPT_FLAGS | ARES_OPT_SOCK_STATE_CB);
478
479
1103
  if (r != ARES_SUCCESS) {
480
    Mutex::ScopedLock lock(ares_library_mutex);
481
    ares_library_cleanup();
482
    return env()->ThrowError(ToErrorCodeString(r));
483
  }
484
485
1103
  library_inited_ = true;
486
}
487
488
64
void ChannelWrap::StartTimer() {
489
64
  if (timer_handle_ == nullptr) {
490
59
    timer_handle_ = new uv_timer_t();
491
59
    timer_handle_->data = static_cast<void*>(this);
492
59
    uv_timer_init(env()->event_loop(), timer_handle_);
493
5
  } else if (uv_is_active(reinterpret_cast<uv_handle_t*>(timer_handle_))) {
494
69
    return;
495
  }
496
59
  uv_timer_start(timer_handle_, AresTimeout, 1000, 1000);
497
}
498
499
1114
void ChannelWrap::CloseTimer() {
500
1114
  if (timer_handle_ == nullptr)
501
2169
    return;
502
503
118
  env()->CloseHandle(timer_handle_, [](uv_timer_t* handle) { delete handle; });
504
59
  timer_handle_ = nullptr;
505
}
506
507
3165
ChannelWrap::~ChannelWrap() {
508
1055
  ares_destroy(channel_);
509
510
1055
  if (library_inited_) {
511
1055
    Mutex::ScopedLock lock(ares_library_mutex);
512
    // This decreases the reference counter increased by ares_library_init().
513
1055
    ares_library_cleanup();
514
  }
515
516
1055
  CloseTimer();
517
2110
}
518
519
520
223
void ChannelWrap::ModifyActivityQueryCount(int count) {
521
223
  active_query_count_ += count;
522
223
  CHECK_GE(active_query_count_, 0);
523
223
}
524
525
526
/**
527
 * This function is to check whether current servers are fallback servers
528
 * when cares initialized.
529
 *
530
 * The fallback servers of cares is [ "127.0.0.1" ] with no user additional
531
 * setting.
532
 */
533
100
void ChannelWrap::EnsureServers() {
534
  /* if last query is OK or servers are set by user self, do not check */
535

100
  if (query_last_ok_ || !is_servers_default_) {
536
200
    return;
537
  }
538
539
  ares_addr_port_node* servers = nullptr;
540
541
  ares_get_servers_ports(channel_, &servers);
542
543
  /* if no server or multi-servers, ignore */
544
  if (servers == nullptr) return;
545
  if (servers->next != nullptr) {
546
    ares_free_data(servers);
547
    is_servers_default_ = false;
548
    return;
549
  }
550
551
  /* if the only server is not 127.0.0.1, ignore */
552
  if (servers[0].family != AF_INET ||
553
      servers[0].addr.addr4.s_addr != htonl(INADDR_LOOPBACK) ||
554
      servers[0].tcp_port != 0 ||
555
      servers[0].udp_port != 0) {
556
    ares_free_data(servers);
557
    is_servers_default_ = false;
558
    return;
559
  }
560
561
  ares_free_data(servers);
562
  servers = nullptr;
563
564
  /* destroy channel and reset channel */
565
  ares_destroy(channel_);
566
567
  CloseTimer();
568
  Setup();
569
}
570
571
572
class QueryWrap : public AsyncWrap {
573
 public:
574
112
  QueryWrap(ChannelWrap* channel, Local<Object> req_wrap_obj, const char* name)
575
      : AsyncWrap(channel->env(), req_wrap_obj, AsyncWrap::PROVIDER_QUERYWRAP),
576
        channel_(channel),
577
112
        trace_name_(name) {
578
    // Make sure the channel object stays alive during the query lifetime.
579
    req_wrap_obj->Set(env()->context(),
580
                      env()->channel_string(),
581
560
                      channel->object()).Check();
582
112
  }
583
584
224
  ~QueryWrap() override {
585
224
    CHECK_EQ(false, persistent().IsEmpty());
586
587
    // Let Callback() know that this object no longer exists.
588
112
    if (callback_ptr_ != nullptr)
589
1
      *callback_ptr_ = nullptr;
590
112
  }
591
592
  // Subclasses should implement the appropriate Send method.
593
  virtual int Send(const char* name) {
594
    UNREACHABLE();
595
    return 0;
596
  }
597
598
  virtual int Send(const char* name, int family) {
599
    UNREACHABLE();
600
    return 0;
601
  }
602
603
 protected:
604
100
  void AresQuery(const char* name,
605
                 int dnsclass,
606
                 int type) {
607
100
    channel_->EnsureServers();
608

200
    TRACE_EVENT_NESTABLE_ASYNC_BEGIN1(
609
      TRACING_CATEGORY_NODE2(dns, native), trace_name_, this,
610
      "name", TRACE_STR_COPY(name));
611
    ares_query(channel_->cares_channel(), name, dnsclass, type, Callback,
612
100
               MakeCallbackPointer());
613
100
  }
614
615
218
  struct ResponseData {
616
    int status;
617
    bool is_host;
618
    DeleteFnPtr<hostent, safe_free_hostent> host;
619
    MallocedBuffer<unsigned char> buf;
620
  };
621
622
109
  void AfterResponse() {
623
109
    CHECK(response_data_);
624
625
109
    const int status = response_data_->status;
626
627
109
    if (status != ARES_SUCCESS) {
628
32
      ParseError(status);
629
77
    } else if (!response_data_->is_host) {
630
70
      Parse(response_data_->buf.data, response_data_->buf.size);
631
    } else {
632
7
      Parse(response_data_->host.get());
633
    }
634
635
109
    delete this;
636
109
  }
637
638
110
  void* MakeCallbackPointer() {
639
110
    CHECK_NULL(callback_ptr_);
640
110
    callback_ptr_ = new QueryWrap*(this);
641
110
    return callback_ptr_;
642
  }
643
644
110
  static QueryWrap* FromCallbackPointer(void* arg) {
645
110
    std::unique_ptr<QueryWrap*> wrap_ptr { static_cast<QueryWrap**>(arg) };
646
110
    QueryWrap* wrap = *wrap_ptr.get();
647
110
    if (wrap == nullptr) return nullptr;
648
109
    wrap->callback_ptr_ = nullptr;
649
109
    return wrap;
650
  }
651
652
100
  static void Callback(void* arg, int status, int timeouts,
653
                       unsigned char* answer_buf, int answer_len) {
654
100
    QueryWrap* wrap = FromCallbackPointer(arg);
655
200
    if (wrap == nullptr) return;
656
657
99
    unsigned char* buf_copy = nullptr;
658
99
    if (status == ARES_SUCCESS) {
659
70
      buf_copy = node::Malloc<unsigned char>(answer_len);
660
70
      memcpy(buf_copy, answer_buf, answer_len);
661
    }
662
663
99
    wrap->response_data_ = std::make_unique<ResponseData>();
664
99
    ResponseData* data = wrap->response_data_.get();
665
99
    data->status = status;
666
99
    data->is_host = false;
667
99
    data->buf = MallocedBuffer<unsigned char>(buf_copy, answer_len);
668
669
99
    wrap->QueueResponseCallback(status);
670
  }
671
672
10
  static void Callback(void* arg, int status, int timeouts,
673
                       struct hostent* host) {
674
10
    QueryWrap* wrap = FromCallbackPointer(arg);
675
20
    if (wrap == nullptr) return;
676
677
10
    struct hostent* host_copy = nullptr;
678
10
    if (status == ARES_SUCCESS) {
679
7
      host_copy = node::Malloc<hostent>(1);
680
7
      cares_wrap_hostent_cpy(host_copy, host);
681
    }
682
683
10
    wrap->response_data_ = std::make_unique<ResponseData>();
684
10
    ResponseData* data = wrap->response_data_.get();
685
10
    data->status = status;
686
10
    data->host.reset(host_copy);
687
10
    data->is_host = true;
688
689
10
    wrap->QueueResponseCallback(status);
690
  }
691
692
109
  void QueueResponseCallback(int status) {
693
109
    env()->SetImmediate([this](Environment*) {
694
109
      AfterResponse();
695
218
    }, object());
696
697
109
    channel_->set_query_last_ok(status != ARES_ECONNREFUSED);
698
109
    channel_->ModifyActivityQueryCount(-1);
699
109
  }
700
701
75
  void CallOnComplete(Local<Value> answer,
702
                      Local<Value> extra = Local<Value>()) {
703
75
    HandleScope handle_scope(env()->isolate());
704
75
    Context::Scope context_scope(env()->context());
705
    Local<Value> argv[] = {
706
      Integer::New(env()->isolate(), 0),
707
      answer,
708
      extra
709
150
    };
710
150
    const int argc = arraysize(argv) - extra.IsEmpty();
711

150
    TRACE_EVENT_NESTABLE_ASYNC_END0(
712
        TRACING_CATEGORY_NODE2(dns, native), trace_name_, this);
713
714
150
    MakeCallback(env()->oncomplete_string(), argc, argv);
715
75
  }
716
717
34
  void ParseError(int status) {
718
34
    CHECK_NE(status, ARES_SUCCESS);
719
34
    HandleScope handle_scope(env()->isolate());
720
34
    Context::Scope context_scope(env()->context());
721
34
    const char* code = ToErrorCodeString(status);
722
34
    Local<Value> arg = OneByteString(env()->isolate(), code);
723

68
    TRACE_EVENT_NESTABLE_ASYNC_END1(
724
        TRACING_CATEGORY_NODE2(dns, native), trace_name_, this,
725
        "error", status);
726
68
    MakeCallback(env()->oncomplete_string(), 1, &arg);
727
34
  }
728
729
  // Subclasses should implement the appropriate Parse method.
730
  virtual void Parse(unsigned char* buf, int len) {
731
    UNREACHABLE();
732
  }
733
734
  virtual void Parse(struct hostent* host) {
735
    UNREACHABLE();
736
  }
737
738
  ChannelWrap* channel_;
739
740
 private:
741
  std::unique_ptr<ResponseData> response_data_;
742
  const char* trace_name_;
743
  // Pointer to pointer to 'this' that can be reset from the destructor,
744
  // in order to let Callback() know that 'this' no longer exists.
745
  QueryWrap** callback_ptr_ = nullptr;
746
};
747
748
749
template <typename T>
750
27
Local<Array> AddrTTLToArray(Environment* env,
751
                            const T* addrttls,
752
                            size_t naddrttls) {
753
27
  auto isolate = env->isolate();
754
27
  EscapableHandleScope escapable_handle_scope(isolate);
755
27
  auto context = env->context();
756
757
27
  Local<Array> ttls = Array::New(isolate, naddrttls);
758

66
  for (size_t i = 0; i < naddrttls; i++) {
759
39
    auto value = Integer::NewFromUnsigned(isolate, addrttls[i].ttl);
760
117
    ttls->Set(context, i, value).Check();
761
  }
762
763
27
  return escapable_handle_scope.Escape(ttls);
764
}
765
766
767
89
int ParseGeneralReply(Environment* env,
768
                      const unsigned char* buf,
769
                      int len,
770
                      int* type,
771
                      Local<Array> ret,
772
                      void* addrttls = nullptr,
773
                      int* naddrttls = nullptr) {
774
89
  HandleScope handle_scope(env->isolate());
775
89
  auto context = env->context();
776
  hostent* host;
777
778
  int status;
779

89
  switch (*type) {
780
    case ns_t_a:
781
    case ns_t_cname:
782
    case ns_t_cname_or_a:
783
      status = ares_parse_a_reply(buf,
784
                                  len,
785
                                  &host,
786
                                  static_cast<ares_addrttl*>(addrttls),
787
36
                                  naddrttls);
788
36
      break;
789
    case ns_t_aaaa:
790
      status = ares_parse_aaaa_reply(buf,
791
                                     len,
792
                                     &host,
793
                                     static_cast<ares_addr6ttl*>(addrttls),
794
21
                                     naddrttls);
795
21
      break;
796
    case ns_t_ns:
797
17
      status = ares_parse_ns_reply(buf, len, &host);
798
17
      break;
799
    case ns_t_ptr:
800
15
      status = ares_parse_ptr_reply(buf, len, nullptr, 0, AF_INET, &host);
801
15
      break;
802
    default:
803
      CHECK(0 && "Bad NS type");
804
      break;
805
  }
806
807
89
  if (status != ARES_SUCCESS)
808
23
    return status;
809
810
  /* If it's `CNAME`, return the CNAME value;
811
   * And if it's `CNAME_OR_A` and it has value in `h_name` and `h_aliases[0]`,
812
   * we consider it's a CNAME record, otherwise we consider it's an A record. */
813


132
  if ((*type == ns_t_cname_or_a && host->h_name && host->h_aliases[0]) ||
814
66
      *type == ns_t_cname) {
815
    // A cname lookup always returns a single record but we follow the
816
    // common API here.
817
2
    *type = ns_t_cname;
818
2
    ret->Set(context,
819
             ret->Length(),
820
8
             OneByteString(env->isolate(), host->h_name)).Check();
821
2
    ares_free_hostent(host);
822
2
    return ARES_SUCCESS;
823
  }
824
825
64
  if (*type == ns_t_cname_or_a)
826
9
    *type = ns_t_a;
827
828
64
  if (*type == ns_t_ns) {
829
13
    HostentToNames(env, host, ret);
830
51
  } else if (*type == ns_t_ptr) {
831
8
    uint32_t offset = ret->Length();
832
16
    for (uint32_t i = 0; host->h_aliases[i] != nullptr; i++) {
833
8
      auto alias = OneByteString(env->isolate(), host->h_aliases[i]);
834
24
      ret->Set(context, i + offset, alias).Check();
835
    }
836
  } else {
837
43
    uint32_t offset = ret->Length();
838
    char ip[INET6_ADDRSTRLEN];
839
100
    for (uint32_t i = 0; host->h_addr_list[i] != nullptr; ++i) {
840
57
      uv_inet_ntop(host->h_addrtype, host->h_addr_list[i], ip, sizeof(ip));
841
57
      auto address = OneByteString(env->isolate(), ip);
842
171
      ret->Set(context, i + offset, address).Check();
843
    }
844
  }
845
846
64
  ares_free_hostent(host);
847
848
64
  return ARES_SUCCESS;
849
}
850
851
852
17
int ParseMxReply(Environment* env,
853
                 const unsigned char* buf,
854
                 int len,
855
                 Local<Array> ret,
856
                 bool need_type = false) {
857
17
  HandleScope handle_scope(env->isolate());
858
17
  auto context = env->context();
859
860
  struct ares_mx_reply* mx_start;
861
17
  int status = ares_parse_mx_reply(buf, len, &mx_start);
862
17
  if (status != ARES_SUCCESS) {
863
    return status;
864
  }
865
866
17
  uint32_t offset = ret->Length();
867
17
  ares_mx_reply* current = mx_start;
868
48
  for (uint32_t i = 0; current != nullptr; ++i, current = current->next) {
869
31
    Local<Object> mx_record = Object::New(env->isolate());
870
    mx_record->Set(context,
871
                   env->exchange_string(),
872
124
                   OneByteString(env->isolate(), current->host)).Check();
873
    mx_record->Set(context,
874
                   env->priority_string(),
875
124
                   Integer::New(env->isolate(), current->priority)).Check();
876
31
    if (need_type)
877
      mx_record->Set(context,
878
                     env->type_string(),
879
60
                     env->dns_mx_string()).Check();
880
881
93
    ret->Set(context, i + offset, mx_record).Check();
882
  }
883
884
17
  ares_free_data(mx_start);
885
17
  return ARES_SUCCESS;
886
}
887
888
19
int ParseTxtReply(Environment* env,
889
                  const unsigned char* buf,
890
                  int len,
891
                  Local<Array> ret,
892
                  bool need_type = false) {
893
19
  HandleScope handle_scope(env->isolate());
894
19
  auto context = env->context();
895
896
  struct ares_txt_ext* txt_out;
897
898
19
  int status = ares_parse_txt_reply_ext(buf, len, &txt_out);
899
19
  if (status != ARES_SUCCESS) {
900
    return status;
901
  }
902
903
  Local<Array> txt_chunk;
904
905
19
  struct ares_txt_ext* current = txt_out;
906
19
  uint32_t i = 0, j;
907
19
  uint32_t offset = ret->Length();
908
37
  for (j = 0; current != nullptr; current = current->next) {
909
18
    Local<String> txt = OneByteString(env->isolate(), current->txt);
910
911
    // New record found - write out the current chunk
912
18
    if (current->record_start) {
913
16
      if (!txt_chunk.IsEmpty()) {
914
8
        if (need_type) {
915
8
          Local<Object> elem = Object::New(env->isolate());
916
24
          elem->Set(context, env->entries_string(), txt_chunk).Check();
917
          elem->Set(context,
918
                    env->type_string(),
919
32
                    env->dns_txt_string()).Check();
920
24
          ret->Set(context, offset + i++, elem).Check();
921
        } else {
922
          ret->Set(context, offset + i++, txt_chunk).Check();
923
        }
924
      }
925
926
16
      txt_chunk = Array::New(env->isolate());
927
16
      j = 0;
928
    }
929
930
54
    txt_chunk->Set(context, j++, txt).Check();
931
  }
932
933
  // Push last chunk if it isn't empty
934
19
  if (!txt_chunk.IsEmpty()) {
935
8
    if (need_type) {
936
4
      Local<Object> elem = Object::New(env->isolate());
937
12
      elem->Set(context, env->entries_string(), txt_chunk).Check();
938
      elem->Set(context,
939
                env->type_string(),
940
16
                env->dns_txt_string()).Check();
941
12
      ret->Set(context, offset + i, elem).Check();
942
    } else {
943
12
      ret->Set(context, offset + i, txt_chunk).Check();
944
    }
945
  }
946
947
19
  ares_free_data(txt_out);
948
19
  return ARES_SUCCESS;
949
}
950
951
952
15
int ParseSrvReply(Environment* env,
953
                  const unsigned char* buf,
954
                  int len,
955
                  Local<Array> ret,
956
                  bool need_type = false) {
957
15
  HandleScope handle_scope(env->isolate());
958
15
  auto context = env->context();
959
960
  struct ares_srv_reply* srv_start;
961
15
  int status = ares_parse_srv_reply(buf, len, &srv_start);
962
15
  if (status != ARES_SUCCESS) {
963
    return status;
964
  }
965
966
15
  ares_srv_reply* current = srv_start;
967
15
  int offset = ret->Length();
968
35
  for (uint32_t i = 0; current != nullptr; ++i, current = current->next) {
969
20
    Local<Object> srv_record = Object::New(env->isolate());
970
    srv_record->Set(context,
971
                    env->name_string(),
972
80
                    OneByteString(env->isolate(), current->host)).Check();
973
    srv_record->Set(context,
974
                    env->port_string(),
975
80
                    Integer::New(env->isolate(), current->port)).Check();
976
    srv_record->Set(context,
977
                    env->priority_string(),
978
80
                    Integer::New(env->isolate(), current->priority)).Check();
979
    srv_record->Set(context,
980
                    env->weight_string(),
981
80
                    Integer::New(env->isolate(), current->weight)).Check();
982
20
    if (need_type)
983
      srv_record->Set(context,
984
                      env->type_string(),
985
40
                      env->dns_srv_string()).Check();
986
987
60
    ret->Set(context, i + offset, srv_record).Check();
988
  }
989
990
15
  ares_free_data(srv_start);
991
15
  return ARES_SUCCESS;
992
}
993
994
995
15
int ParseNaptrReply(Environment* env,
996
                    const unsigned char* buf,
997
                    int len,
998
                    Local<Array> ret,
999
                    bool need_type = false) {
1000
15
  HandleScope handle_scope(env->isolate());
1001
15
  auto context = env->context();
1002
1003
  ares_naptr_reply* naptr_start;
1004
15
  int status = ares_parse_naptr_reply(buf, len, &naptr_start);
1005
1006
15
  if (status != ARES_SUCCESS) {
1007
    return status;
1008
  }
1009
1010
15
  ares_naptr_reply* current = naptr_start;
1011
15
  int offset = ret->Length();
1012
27
  for (uint32_t i = 0; current != nullptr; ++i, current = current->next) {
1013
12
    Local<Object> naptr_record = Object::New(env->isolate());
1014
    naptr_record->Set(context,
1015
                      env->flags_string(),
1016
48
                      OneByteString(env->isolate(), current->flags)).Check();
1017
    naptr_record->Set(context,
1018
                      env->service_string(),
1019
                      OneByteString(env->isolate(),
1020
48
                                    current->service)).Check();
1021
    naptr_record->Set(context,
1022
                      env->regexp_string(),
1023
                      OneByteString(env->isolate(),
1024
48
                                    current->regexp)).Check();
1025
    naptr_record->Set(context,
1026
                      env->replacement_string(),
1027
                      OneByteString(env->isolate(),
1028
48
                                    current->replacement)).Check();
1029
    naptr_record->Set(context,
1030
                      env->order_string(),
1031
48
                      Integer::New(env->isolate(), current->order)).Check();
1032
    naptr_record->Set(context,
1033
                      env->preference_string(),
1034
                      Integer::New(env->isolate(),
1035
48
                                   current->preference)).Check();
1036
12
    if (need_type)
1037
      naptr_record->Set(context,
1038
                        env->type_string(),
1039
24
                        env->dns_naptr_string()).Check();
1040
1041
36
    ret->Set(context, i + offset, naptr_record).Check();
1042
  }
1043
1044
15
  ares_free_data(naptr_start);
1045
15
  return ARES_SUCCESS;
1046
}
1047
1048
1049
13
int ParseSoaReply(Environment* env,
1050
                  unsigned char* buf,
1051
                  int len,
1052
                  Local<Object>* ret) {
1053
13
  EscapableHandleScope handle_scope(env->isolate());
1054
13
  auto context = env->context();
1055
1056
  // Manage memory using standardard smart pointer std::unique_tr
1057
  struct AresDeleter {
1058
100
    void operator()(char* ptr) const noexcept { ares_free_string(ptr); }
1059
  };
1060
  using ares_unique_ptr = std::unique_ptr<char[], AresDeleter>;
1061
1062
  // Can't use ares_parse_soa_reply() here which can only parse single record
1063
13
  const unsigned int ancount = cares_get_16bit(buf + 6);
1064
13
  unsigned char* ptr = buf + NS_HFIXEDSZ;
1065
  char* name_temp;
1066
  long temp_len;  // NOLINT(runtime/int)
1067
13
  int status = ares_expand_name(ptr, buf, len, &name_temp, &temp_len);
1068
26
  const ares_unique_ptr name(name_temp);
1069
13
  if (status != ARES_SUCCESS) {
1070
    // returns EBADRESP in case of invalid input
1071
    return status == ARES_EBADNAME ? ARES_EBADRESP : status;
1072
  }
1073
1074
13
  if (ptr + temp_len + NS_QFIXEDSZ > buf + len) {
1075
    return ARES_EBADRESP;
1076
  }
1077
13
  ptr += temp_len + NS_QFIXEDSZ;
1078
1079
76
  for (unsigned int i = 0; i < ancount; i++) {
1080
    char* rr_name_temp;
1081
    long rr_temp_len;  // NOLINT(runtime/int)
1082
71
    int status2 = ares_expand_name(ptr, buf, len, &rr_name_temp, &rr_temp_len);
1083
71
    const ares_unique_ptr rr_name(rr_name_temp);
1084
1085
71
    if (status2 != ARES_SUCCESS)
1086
      return status2 == ARES_EBADNAME ? ARES_EBADRESP : status2;
1087
1088
71
    ptr += rr_temp_len;
1089
71
    if (ptr + NS_RRFIXEDSZ > buf + len) {
1090
      return ARES_EBADRESP;
1091
    }
1092
1093
71
    const int rr_type = cares_get_16bit(ptr);
1094
71
    const int rr_len = cares_get_16bit(ptr + 8);
1095
71
    ptr += NS_RRFIXEDSZ;
1096
1097
    // only need SOA
1098
71
    if (rr_type == ns_t_soa) {
1099
      char* nsname_temp;
1100
      long nsname_temp_len;  // NOLINT(runtime/int)
1101
1102
      int status3 = ares_expand_name(ptr, buf, len,
1103
                                     &nsname_temp,
1104
8
                                     &nsname_temp_len);
1105
8
      const ares_unique_ptr nsname(nsname_temp);
1106
8
      if (status3 != ARES_SUCCESS) {
1107
        return status3 == ARES_EBADNAME ? ARES_EBADRESP : status3;
1108
      }
1109
8
      ptr += nsname_temp_len;
1110
1111
      char* hostmaster_temp;
1112
      long hostmaster_temp_len;  // NOLINT(runtime/int)
1113
      int status4 = ares_expand_name(ptr, buf, len,
1114
                                     &hostmaster_temp,
1115
8
                                     &hostmaster_temp_len);
1116
8
      const ares_unique_ptr hostmaster(hostmaster_temp);
1117
8
      if (status4 != ARES_SUCCESS) {
1118
        return status4 == ARES_EBADNAME ? ARES_EBADRESP : status4;
1119
      }
1120
8
      ptr += hostmaster_temp_len;
1121
1122
8
      if (ptr + 5 * 4 > buf + len) {
1123
        return ARES_EBADRESP;
1124
      }
1125
1126
8
      const unsigned int serial = cares_get_32bit(ptr + 0 * 4);
1127
8
      const unsigned int refresh = cares_get_32bit(ptr + 1 * 4);
1128
8
      const unsigned int retry = cares_get_32bit(ptr + 2 * 4);
1129
8
      const unsigned int expire = cares_get_32bit(ptr + 3 * 4);
1130
8
      const unsigned int minttl = cares_get_32bit(ptr + 4 * 4);
1131
1132
8
      Local<Object> soa_record = Object::New(env->isolate());
1133
      soa_record->Set(context,
1134
                      env->nsname_string(),
1135
32
                      OneByteString(env->isolate(), nsname.get())).Check();
1136
      soa_record->Set(context,
1137
                      env->hostmaster_string(),
1138
                      OneByteString(env->isolate(),
1139
32
                                    hostmaster.get())).Check();
1140
      soa_record->Set(context,
1141
                      env->serial_string(),
1142
32
                      Integer::NewFromUnsigned(env->isolate(), serial)).Check();
1143
      soa_record->Set(context,
1144
                      env->refresh_string(),
1145
32
                      Integer::New(env->isolate(), refresh)).Check();
1146
      soa_record->Set(context,
1147
                      env->retry_string(),
1148
32
                      Integer::New(env->isolate(), retry)).Check();
1149
      soa_record->Set(context,
1150
                      env->expire_string(),
1151
32
                      Integer::New(env->isolate(), expire)).Check();
1152
      soa_record->Set(context,
1153
                      env->minttl_string(),
1154
32
                      Integer::NewFromUnsigned(env->isolate(), minttl)).Check();
1155
      soa_record->Set(context,
1156
                      env->type_string(),
1157
32
                      env->dns_soa_string()).Check();
1158
1159
1160
8
      *ret = handle_scope.Escape(soa_record);
1161

8
      break;
1162
    }
1163
1164
63
    ptr += rr_len;
1165
63
  }
1166
1167
13
  return ARES_SUCCESS;
1168
}
1169
1170
1171
30
class QueryAnyWrap: public QueryWrap {
1172
 public:
1173
15
  QueryAnyWrap(ChannelWrap* channel, Local<Object> req_wrap_obj)
1174
15
    : QueryWrap(channel, req_wrap_obj, "resolveAny") {
1175
15
  }
1176
1177
15
  int Send(const char* name) override {
1178
15
    AresQuery(name, ns_c_in, ns_t_any);
1179
15
    return 0;
1180
  }
1181
1182
  SET_NO_MEMORY_INFO()
1183
  SET_MEMORY_INFO_NAME(QueryAnyWrap)
1184
  SET_SELF_SIZE(QueryAnyWrap)
1185
1186
 protected:
1187
15
  void Parse(unsigned char* buf, int len) override {
1188
15
    HandleScope handle_scope(env()->isolate());
1189
15
    auto context = env()->context();
1190
13
    Context::Scope context_scope(context);
1191
1192
15
    Local<Array> ret = Array::New(env()->isolate());
1193
    int type, status, old_count;
1194
1195
    /* Parse A records or CNAME records */
1196
    ares_addrttl addrttls[256];
1197
15
    int naddrttls = arraysize(addrttls);
1198
1199
15
    type = ns_t_cname_or_a;
1200
    status = ParseGeneralReply(env(),
1201
                               buf,
1202
                               len,
1203
                               &type,
1204
                               ret,
1205
                               addrttls,
1206
15
                               &naddrttls);
1207
15
    uint32_t a_count = ret->Length();
1208

15
    if (status != ARES_SUCCESS && status != ARES_ENODATA) {
1209
2
      ParseError(status);
1210
2
      return;
1211
    }
1212
1213
13
    if (type == ns_t_a) {
1214
9
      CHECK_EQ(static_cast<uint32_t>(naddrttls), a_count);
1215
20
      for (uint32_t i = 0; i < a_count; i++) {
1216
11
        Local<Object> obj = Object::New(env()->isolate());
1217
        obj->Set(context,
1218
                 env()->address_string(),
1219
44
                 ret->Get(context, i).ToLocalChecked()).Check();
1220
        obj->Set(context,
1221
                 env()->ttl_string(),
1222
                 Integer::NewFromUnsigned(
1223
44
                   env()->isolate(), addrttls[i].ttl)).Check();
1224
        obj->Set(context,
1225
                 env()->type_string(),
1226
44
                 env()->dns_a_string()).Check();
1227
22
        ret->Set(context, i, obj).Check();
1228
      }
1229
    } else {
1230
4
      for (uint32_t i = 0; i < a_count; i++) {
1231
        Local<Object> obj = Object::New(env()->isolate());
1232
        obj->Set(context,
1233
                 env()->value_string(),
1234
                 ret->Get(context, i).ToLocalChecked()).Check();
1235
        obj->Set(context,
1236
                 env()->type_string(),
1237
                 env()->dns_cname_string()).Check();
1238
        ret->Set(context, i, obj).Check();
1239
      }
1240
    }
1241
1242
    /* Parse AAAA records */
1243
    ares_addr6ttl addr6ttls[256];
1244
13
    int naddr6ttls = arraysize(addr6ttls);
1245
1246
13
    type = ns_t_aaaa;
1247
    status = ParseGeneralReply(env(),
1248
                               buf,
1249
                               len,
1250
                               &type,
1251
                               ret,
1252
                               addr6ttls,
1253
13
                               &naddr6ttls);
1254
13
    uint32_t aaaa_count = ret->Length() - a_count;
1255

13
    if (status != ARES_SUCCESS && status != ARES_ENODATA) {
1256
      ParseError(status);
1257
      return;
1258
    }
1259
1260
13
    CHECK_EQ(aaaa_count, static_cast<uint32_t>(naddr6ttls));
1261
13
    CHECK_EQ(ret->Length(), a_count + aaaa_count);
1262
40
    for (uint32_t i = a_count; i < ret->Length(); i++) {
1263
7
      Local<Object> obj = Object::New(env()->isolate());
1264
      obj->Set(context,
1265
               env()->address_string(),
1266
28
               ret->Get(context, i).ToLocalChecked()).Check();
1267
      obj->Set(context,
1268
               env()->ttl_string(),
1269
               Integer::NewFromUnsigned(
1270
28
                 env()->isolate(), addr6ttls[i - a_count].ttl)).Check();
1271
      obj->Set(context,
1272
               env()->type_string(),
1273
28
               env()->dns_aaaa_string()).Check();
1274
14
      ret->Set(context, i, obj).Check();
1275
    }
1276
1277
    /* Parse MX records */
1278
13
    status = ParseMxReply(env(), buf, len, ret, true);
1279

13
    if (status != ARES_SUCCESS && status != ARES_ENODATA) {
1280
      ParseError(status);
1281
      return;
1282
    }
1283
1284
    /* Parse NS records */
1285
13
    type = ns_t_ns;
1286
13
    old_count = ret->Length();
1287
13
    status = ParseGeneralReply(env(), buf, len, &type, ret);
1288

13
    if (status != ARES_SUCCESS && status != ARES_ENODATA) {
1289
      ParseError(status);
1290
      return;
1291
    }
1292
66
    for (uint32_t i = old_count; i < ret->Length(); i++) {
1293
20
      Local<Object> obj = Object::New(env()->isolate());
1294
      obj->Set(context,
1295
               env()->value_string(),
1296
80
               ret->Get(context, i).ToLocalChecked()).Check();
1297
      obj->Set(context,
1298
               env()->type_string(),
1299
80
               env()->dns_ns_string()).Check();
1300
40
      ret->Set(context, i, obj).Check();
1301
    }
1302
1303
    /* Parse TXT records */
1304
13
    status = ParseTxtReply(env(), buf, len, ret, true);
1305

13
    if (status != ARES_SUCCESS && status != ARES_ENODATA) {
1306
      ParseError(status);
1307
      return;
1308
    }
1309
1310
    /* Parse SRV records */
1311
13
    status = ParseSrvReply(env(), buf, len, ret, true);
1312

13
    if (status != ARES_SUCCESS && status != ARES_ENODATA) {
1313
      return;
1314
    }
1315
1316
    /* Parse PTR records */
1317
13
    type = ns_t_ptr;
1318
13
    old_count = ret->Length();
1319
13
    status = ParseGeneralReply(env(), buf, len, &type, ret);
1320
38
    for (uint32_t i = old_count; i < ret->Length(); i++) {
1321
6
      Local<Object> obj = Object::New(env()->isolate());
1322
      obj->Set(context,
1323
               env()->value_string(),
1324
24
               ret->Get(context, i).ToLocalChecked()).Check();
1325
      obj->Set(context,
1326
               env()->type_string(),
1327
24
               env()->dns_ptr_string()).Check();
1328
12
      ret->Set(context, i, obj).Check();
1329
    }
1330
1331
    /* Parse NAPTR records */
1332
13
    status = ParseNaptrReply(env(), buf, len, ret, true);
1333

13
    if (status != ARES_SUCCESS && status != ARES_ENODATA) {
1334
      ParseError(status);
1335
      return;
1336
    }
1337
1338
    /* Parse SOA records */
1339
    Local<Object> soa_record = Local<Object>();
1340
13
    status = ParseSoaReply(env(), buf, len, &soa_record);
1341

13
    if (status != ARES_SUCCESS && status != ARES_ENODATA) {
1342
      ParseError(status);
1343
      return;
1344
    }
1345
13
    if (!soa_record.IsEmpty())
1346
24
      ret->Set(context, ret->Length(), soa_record).Check();
1347
1348
26
    CallOnComplete(ret);
1349
  }
1350
};
1351
1352
1353
46
class QueryAWrap: public QueryWrap {
1354
 public:
1355
23
  QueryAWrap(ChannelWrap* channel, Local<Object> req_wrap_obj)
1356
23
      : QueryWrap(channel, req_wrap_obj, "resolve4") {
1357
23
  }
1358
1359
23
  int Send(const char* name) override {
1360
23
    AresQuery(name, ns_c_in, ns_t_a);
1361
23
    return 0;
1362
  }
1363
1364
2
  SET_NO_MEMORY_INFO()
1365
2
  SET_MEMORY_INFO_NAME(QueryAWrap)
1366
2
  SET_SELF_SIZE(QueryAWrap)
1367
1368
 protected:
1369
19
  void Parse(unsigned char* buf, int len) override {
1370
19
    HandleScope handle_scope(env()->isolate());
1371
38
    Context::Scope context_scope(env()->context());
1372
1373
    ares_addrttl addrttls[256];
1374
19
    int naddrttls = arraysize(addrttls), status;
1375
19
    Local<Array> ret = Array::New(env()->isolate());
1376
1377
19
    int type = ns_t_a;
1378
    status = ParseGeneralReply(env(),
1379
                               buf,
1380
                               len,
1381
                               &type,
1382
                               ret,
1383
                               addrttls,
1384
19
                               &naddrttls);
1385
19
    if (status != ARES_SUCCESS) {
1386
      ParseError(status);
1387
19
      return;
1388
    }
1389
1390
    Local<Array> ttls = AddrTTLToArray<ares_addrttl>(env(),
1391
                                                     addrttls,
1392
19
                                                     naddrttls);
1393
1394
38
    CallOnComplete(ret, ttls);
1395
  }
1396
};
1397
1398
1399
18
class QueryAaaaWrap: public QueryWrap {
1400
 public:
1401
9
  QueryAaaaWrap(ChannelWrap* channel, Local<Object> req_wrap_obj)
1402
9
      : QueryWrap(channel, req_wrap_obj, "resolve6") {
1403
9
  }
1404
1405
9
  int Send(const char* name) override {
1406
9
    AresQuery(name, ns_c_in, ns_t_aaaa);
1407
9
    return 0;
1408
  }
1409
1410
1
  SET_NO_MEMORY_INFO()
1411
1
  SET_MEMORY_INFO_NAME(QueryAaaaWrap)
1412
1
  SET_SELF_SIZE(QueryAaaaWrap)
1413
1414
 protected:
1415
8
  void Parse(unsigned char* buf, int len) override {
1416
8
    HandleScope handle_scope(env()->isolate());
1417
16
    Context::Scope context_scope(env()->context());
1418
1419
    ares_addr6ttl addrttls[256];
1420
8
    int naddrttls = arraysize(addrttls), status;
1421
8
    Local<Array> ret = Array::New(env()->isolate());
1422
1423
8
    int type = ns_t_aaaa;
1424
    status = ParseGeneralReply(env(),
1425
                               buf,
1426
                               len,
1427
                               &type,
1428
                               ret,
1429
                               addrttls,
1430
8
                               &naddrttls);
1431
8
    if (status != ARES_SUCCESS) {
1432
      ParseError(status);
1433
8
      return;
1434
    }
1435
1436
    Local<Array> ttls = AddrTTLToArray<ares_addr6ttl>(env(),
1437
                                                      addrttls,
1438
8
                                                      naddrttls);
1439
1440
16
    CallOnComplete(ret, ttls);
1441
  }
1442
};
1443
1444
1445
12
class QueryCnameWrap: public QueryWrap {
1446
 public:
1447
6
  QueryCnameWrap(ChannelWrap* channel, Local<Object> req_wrap_obj)
1448
6
      : QueryWrap(channel, req_wrap_obj, "resolveCname") {
1449
6
  }
1450
1451
6
  int Send(const char* name) override {
1452
6
    AresQuery(name, ns_c_in, ns_t_cname);
1453
6
    return 0;
1454
  }
1455
1456
  SET_NO_MEMORY_INFO()
1457
  SET_MEMORY_INFO_NAME(QueryCnameWrap)
1458
  SET_SELF_SIZE(QueryCnameWrap)
1459
1460
 protected:
1461
2
  void Parse(unsigned char* buf, int len) override {
1462
2
    HandleScope handle_scope(env()->isolate());
1463
4
    Context::Scope context_scope(env()->context());
1464
1465
2
    Local<Array> ret = Array::New(env()->isolate());
1466
2
    int type = ns_t_cname;
1467
2
    int status = ParseGeneralReply(env(), buf, len, &type, ret);
1468
2
    if (status != ARES_SUCCESS) {
1469
      ParseError(status);
1470
2
      return;
1471
    }
1472
1473
4
    this->CallOnComplete(ret);
1474
  }
1475
};
1476
1477
1478
14
class QueryMxWrap: public QueryWrap {
1479
 public:
1480
7
  QueryMxWrap(ChannelWrap* channel, Local<Object> req_wrap_obj)
1481
7
      : QueryWrap(channel, req_wrap_obj, "resolveMx") {
1482
7
  }
1483
1484
7
  int Send(const char* name) override {
1485
7
    AresQuery(name, ns_c_in, ns_t_mx);
1486
7
    return 0;
1487
  }
1488
1489
  SET_NO_MEMORY_INFO()
1490
  SET_MEMORY_INFO_NAME(QueryMxWrap)
1491
  SET_SELF_SIZE(QueryMxWrap)
1492
1493
 protected:
1494
4
  void Parse(unsigned char* buf, int len) override {
1495
4
    HandleScope handle_scope(env()->isolate());
1496
8
    Context::Scope context_scope(env()->context());
1497
1498
4
    Local<Array> mx_records = Array::New(env()->isolate());
1499
4
    int status = ParseMxReply(env(), buf, len, mx_records);
1500
1501
4
    if (status != ARES_SUCCESS) {
1502
      ParseError(status);
1503
4
      return;
1504
    }
1505
1506
8
    this->CallOnComplete(mx_records);
1507
  }
1508
};
1509
1510
1511
12
class QueryNsWrap: public QueryWrap {
1512
 public:
1513
6
  QueryNsWrap(ChannelWrap* channel, Local<Object> req_wrap_obj)
1514
6
      : QueryWrap(channel, req_wrap_obj, "resolveNs") {
1515
6
  }
1516
1517
6
  int Send(const char* name) override {
1518
6
    AresQuery(name, ns_c_in, ns_t_ns);
1519
6
    return 0;
1520
  }
1521
1522
  SET_NO_MEMORY_INFO()
1523
  SET_MEMORY_INFO_NAME(QueryNsWrap)
1524
  SET_SELF_SIZE(QueryNsWrap)
1525
1526
 protected:
1527
4
  void Parse(unsigned char* buf, int len) override {
1528
4
    HandleScope handle_scope(env()->isolate());
1529
8
    Context::Scope context_scope(env()->context());
1530
1531
4
    int type = ns_t_ns;
1532
4
    Local<Array> names = Array::New(env()->isolate());
1533
4
    int status = ParseGeneralReply(env(), buf, len, &type, names);
1534
4
    if (status != ARES_SUCCESS) {
1535
      ParseError(status);
1536
4
      return;
1537
    }
1538
1539
8
    this->CallOnComplete(names);
1540
  }
1541
};
1542
1543
1544
16
class QueryTxtWrap: public QueryWrap {
1545
 public:
1546
8
  QueryTxtWrap(ChannelWrap* channel, Local<Object> req_wrap_obj)
1547
8
      : QueryWrap(channel, req_wrap_obj, "resolveTxt") {
1548
8
  }
1549
1550
8
  int Send(const char* name) override {
1551
8
    AresQuery(name, ns_c_in, ns_t_txt);
1552
8
    return 0;
1553
  }
1554
1555
  SET_NO_MEMORY_INFO()
1556
  SET_MEMORY_INFO_NAME(QueryTxtWrap)
1557
  SET_SELF_SIZE(QueryTxtWrap)
1558
1559
 protected:
1560
6
  void Parse(unsigned char* buf, int len) override {
1561
6
    HandleScope handle_scope(env()->isolate());
1562
12
    Context::Scope context_scope(env()->context());
1563
1564
6
    Local<Array> txt_records = Array::New(env()->isolate());
1565
6
    int status = ParseTxtReply(env(), buf, len, txt_records);
1566
6
    if (status != ARES_SUCCESS) {
1567
      ParseError(status);
1568
6
      return;
1569
    }
1570
1571
12
    this->CallOnComplete(txt_records);
1572
  }
1573
};
1574
1575
1576
12
class QuerySrvWrap: public QueryWrap {
1577
 public:
1578
6
  explicit QuerySrvWrap(ChannelWrap* channel, Local<Object> req_wrap_obj)
1579
6
      : QueryWrap(channel, req_wrap_obj, "resolveSrv") {
1580
6
  }
1581
1582
6
  int Send(const char* name) override {
1583
6
    AresQuery(name, ns_c_in, ns_t_srv);
1584
6
    return 0;
1585
  }
1586
1587
  SET_NO_MEMORY_INFO()
1588
  SET_MEMORY_INFO_NAME(QuerySrvWrap)
1589
  SET_SELF_SIZE(QuerySrvWrap)
1590
1591
 protected:
1592
2
  void Parse(unsigned char* buf, int len) override {
1593
2
    HandleScope handle_scope(env()->isolate());
1594
4
    Context::Scope context_scope(env()->context());
1595
1596
2
    Local<Array> srv_records = Array::New(env()->isolate());
1597
2
    int status = ParseSrvReply(env(), buf, len, srv_records);
1598
2
    if (status != ARES_SUCCESS) {
1599
      ParseError(status);
1600
2
      return;
1601
    }
1602
1603
4
    this->CallOnComplete(srv_records);
1604
  }
1605
};
1606
1607
12
class QueryPtrWrap: public QueryWrap {
1608
 public:
1609
6
  explicit QueryPtrWrap(ChannelWrap* channel, Local<Object> req_wrap_obj)
1610
6
      : QueryWrap(channel, req_wrap_obj, "resolvePtr") {
1611
6
  }
1612
1613
6
  int Send(const char* name) override {
1614
6
    AresQuery(name, ns_c_in, ns_t_ptr);
1615
6
    return 0;
1616
  }
1617
1618
  SET_NO_MEMORY_INFO()
1619
  SET_MEMORY_INFO_NAME(QueryPtrWrap)
1620
  SET_SELF_SIZE(QueryPtrWrap)
1621
1622
 protected:
1623
2
  void Parse(unsigned char* buf, int len) override {
1624
2
    HandleScope handle_scope(env()->isolate());
1625
4
    Context::Scope context_scope(env()->context());
1626
1627
2
    int type = ns_t_ptr;
1628
2
    Local<Array> aliases = Array::New(env()->isolate());
1629
1630
2
    int status = ParseGeneralReply(env(), buf, len, &type, aliases);
1631
2
    if (status != ARES_SUCCESS) {
1632
      ParseError(status);
1633
2
      return;
1634
    }
1635
1636
4
    this->CallOnComplete(aliases);
1637
  }
1638
};
1639
1640
12
class QueryNaptrWrap: public QueryWrap {
1641
 public:
1642
6
  explicit QueryNaptrWrap(ChannelWrap* channel, Local<Object> req_wrap_obj)
1643
6
      : QueryWrap(channel, req_wrap_obj, "resolveNaptr") {
1644
6
  }
1645
1646
6
  int Send(const char* name) override {
1647
6
    AresQuery(name, ns_c_in, ns_t_naptr);
1648
6
    return 0;
1649
  }
1650
1651
  SET_NO_MEMORY_INFO()
1652
  SET_MEMORY_INFO_NAME(QueryNaptrWrap)
1653
  SET_SELF_SIZE(QueryNaptrWrap)
1654
1655
 protected:
1656
2
  void Parse(unsigned char* buf, int len) override {
1657
2
    HandleScope handle_scope(env()->isolate());
1658
4
    Context::Scope context_scope(env()->context());
1659
1660
2
    Local<Array> naptr_records = Array::New(env()->isolate());
1661
2
    int status = ParseNaptrReply(env(), buf, len, naptr_records);
1662
2
    if (status != ARES_SUCCESS) {
1663
      ParseError(status);
1664
2
      return;
1665
    }
1666
1667
4
    this->CallOnComplete(naptr_records);
1668
  }
1669
};
1670
1671
1672
16
class QuerySoaWrap: public QueryWrap {
1673
 public:
1674
8
  QuerySoaWrap(ChannelWrap* channel, Local<Object> req_wrap_obj)
1675
8
      : QueryWrap(channel, req_wrap_obj, "resolveSoa") {
1676
8
  }
1677
1678
8
  int Send(const char* name) override {
1679
8
    AresQuery(name, ns_c_in, ns_t_soa);
1680
8
    return 0;
1681
  }
1682
1683
  SET_NO_MEMORY_INFO()
1684
  SET_MEMORY_INFO_NAME(QuerySoaWrap)
1685
  SET_SELF_SIZE(QuerySoaWrap)
1686
1687
 protected:
1688
6
  void Parse(unsigned char* buf, int len) override {
1689
6
    HandleScope handle_scope(env()->isolate());
1690
6
    auto context = env()->context();
1691
6
    Context::Scope context_scope(context);
1692
1693
    ares_soa_reply* soa_out;
1694
6
    int status = ares_parse_soa_reply(buf, len, &soa_out);
1695
1696
6
    if (status != ARES_SUCCESS) {
1697
      ParseError(status);
1698
6
      return;
1699
    }
1700
1701
6
    Local<Object> soa_record = Object::New(env()->isolate());
1702
1703
    soa_record->Set(context,
1704
                    env()->nsname_string(),
1705
                    OneByteString(env()->isolate(),
1706
24
                                  soa_out->nsname)).Check();
1707
    soa_record->Set(context,
1708
                    env()->hostmaster_string(),
1709
                    OneByteString(env()->isolate(),
1710
24
                                  soa_out->hostmaster)).Check();
1711
    soa_record->Set(context,
1712
                    env()->serial_string(),
1713
                    Integer::NewFromUnsigned(
1714
24
                      env()->isolate(), soa_out->serial)).Check();
1715
    soa_record->Set(context,
1716
                    env()->refresh_string(),
1717
                    Integer::New(env()->isolate(),
1718
24
                                 soa_out->refresh)).Check();
1719
    soa_record->Set(context,
1720
                    env()->retry_string(),
1721
24
                    Integer::New(env()->isolate(), soa_out->retry)).Check();
1722
    soa_record->Set(context,
1723
                    env()->expire_string(),
1724
24
                    Integer::New(env()->isolate(), soa_out->expire)).Check();
1725
    soa_record->Set(context,
1726
                    env()->minttl_string(),
1727
                    Integer::NewFromUnsigned(
1728
24
                      env()->isolate(), soa_out->minttl)).Check();
1729
1730
6
    ares_free_data(soa_out);
1731
1732
12
    this->CallOnComplete(soa_record);
1733
  }
1734
};
1735
1736
1737
24
class GetHostByAddrWrap: public QueryWrap {
1738
 public:
1739
12
  explicit GetHostByAddrWrap(ChannelWrap* channel, Local<Object> req_wrap_obj)
1740
12
      : QueryWrap(channel, req_wrap_obj, "reverse") {
1741
12
  }
1742
1743
12
  int Send(const char* name) override {
1744
    int length, family;
1745
    char address_buffer[sizeof(struct in6_addr)];
1746
1747
12
    if (uv_inet_pton(AF_INET, name, &address_buffer) == 0) {
1748
8
      length = sizeof(struct in_addr);
1749
8
      family = AF_INET;
1750
4
    } else if (uv_inet_pton(AF_INET6, name, &address_buffer) == 0) {
1751
2
      length = sizeof(struct in6_addr);
1752
2
      family = AF_INET6;
1753
    } else {
1754
2
      return UV_EINVAL;  // So errnoException() reports a proper error.
1755
    }
1756
1757

20
    TRACE_EVENT_NESTABLE_ASYNC_BEGIN2(
1758
        TRACING_CATEGORY_NODE2(dns, native), "reverse", this,
1759
        "name", TRACE_STR_COPY(name),
1760
        "family", family == AF_INET ? "ipv4" : "ipv6");
1761
1762
    ares_gethostbyaddr(channel_->cares_channel(),
1763
                       address_buffer,
1764
                       length,
1765
                       family,
1766
                       Callback,
1767
10
                       MakeCallbackPointer());
1768
10
    return 0;
1769
  }
1770
1771
  SET_NO_MEMORY_INFO()
1772
  SET_MEMORY_INFO_NAME(GetHostByAddrWrap)
1773
  SET_SELF_SIZE(GetHostByAddrWrap)
1774
1775
 protected:
1776
7
  void Parse(struct hostent* host) override {
1777
7
    HandleScope handle_scope(env()->isolate());
1778
7
    Context::Scope context_scope(env()->context());
1779
21
    this->CallOnComplete(HostentToNames(env(), host));
1780
7
  }
1781
};
1782
1783
1784
template <class Wrap>
1785
112
static void Query(const FunctionCallbackInfo<Value>& args) {
1786
112
  Environment* env = Environment::GetCurrent(args);
1787
  ChannelWrap* channel;
1788






224
  ASSIGN_OR_RETURN_UNWRAP(&channel, args.Holder());
1789
1790






112
  CHECK_EQ(false, args.IsConstructCall());
1791






224
  CHECK(args[0]->IsObject());
1792






336
  CHECK(args[1]->IsString());
1793
1794
224
  Local<Object> req_wrap_obj = args[0].As<Object>();
1795
224
  Local<String> string = args[1].As<String>();
1796
112
  auto wrap = std::make_unique<Wrap>(channel, req_wrap_obj);
1797
1798
224
  node::Utf8Value name(env->isolate(), string);
1799
112
  channel->ModifyActivityQueryCount(1);
1800
112
  int err = wrap->Send(*name);
1801






112
  if (err) {
1802
2
    channel->ModifyActivityQueryCount(-1);
1803
  } else {
1804
    // Release ownership of the pointer allowing the ownership to be transferred
1805
110
    USE(wrap.release());
1806
  }
1807
1808
336
  args.GetReturnValue().Set(err);
1809
}
1810
1811
1812
5113
void AfterGetAddrInfo(uv_getaddrinfo_t* req, int status, struct addrinfo* res) {
1813
  std::unique_ptr<GetAddrInfoReqWrap> req_wrap {
1814
5113
      static_cast<GetAddrInfoReqWrap*>(req->data)};
1815
5113
  Environment* env = req_wrap->env();
1816
1817
10225
  HandleScope handle_scope(env->isolate());
1818
5113
  Context::Scope context_scope(env->context());
1819
1820
  Local<Value> argv[] = {
1821
    Integer::New(env->isolate(), status),
1822
    Null(env->isolate())
1823
15339
  };
1824
1825
5113
  uint64_t n = 0;
1826
5113
  const bool verbatim = req_wrap->verbatim();
1827
1828
5113
  if (status == 0) {
1829
4993
    Local<Array> results = Array::New(env->isolate());
1830
1831
9985
    auto add = [&] (bool want_ipv4, bool want_ipv6) {
1832
40119
      for (auto p = res; p != nullptr; p = p->ai_next) {
1833
30134
        CHECK_EQ(p->ai_socktype, SOCK_STREAM);
1834
1835
        const char* addr;
1836

30134
        if (want_ipv4 && p->ai_family == AF_INET) {
1837
          addr = reinterpret_cast<char*>(
1838
5143
              &(reinterpret_cast<struct sockaddr_in*>(p->ai_addr)->sin_addr));
1839

24991
        } else if (want_ipv6 && p->ai_family == AF_INET6) {
1840
          addr = reinterpret_cast<char*>(
1841
9925
              &(reinterpret_cast<struct sockaddr_in6*>(p->ai_addr)->sin6_addr));
1842
        } else {
1843
30132
          continue;
1844
        }
1845
1846
        char ip[INET6_ADDRSTRLEN];
1847
15068
        if (uv_inet_ntop(p->ai_family, addr, ip, sizeof(ip)))
1848
          continue;
1849
1850
15068
        Local<String> s = OneByteString(env->isolate(), ip);
1851
45204
        results->Set(env->context(), n, s).Check();
1852
15068
        n++;
1853
      }
1854
14978
    };
1855
1856
4993
    add(true, verbatim);
1857
4993
    if (verbatim == false)
1858
4992
      add(false, true);
1859
1860
    // No responses were found to return
1861
4993
    if (n == 0) {
1862
      argv[0] = Integer::New(env->isolate(), UV_EAI_NODATA);
1863
    }
1864
1865
4993
    argv[1] = results;
1866
  }
1867
1868
5113
  uv_freeaddrinfo(res);
1869
1870

10226
  TRACE_EVENT_NESTABLE_ASYNC_END2(
1871
      TRACING_CATEGORY_NODE2(dns, native), "lookup", req_wrap.get(),
1872
      "count", n, "verbatim", verbatim);
1873
1874
  // Make the callback into JavaScript
1875
10225
  req_wrap->MakeCallback(env->oncomplete_string(), arraysize(argv), argv);
1876
5112
}
1877
1878
1879
11
void AfterGetNameInfo(uv_getnameinfo_t* req,
1880
                      int status,
1881
                      const char* hostname,
1882
                      const char* service) {
1883
  std::unique_ptr<GetNameInfoReqWrap> req_wrap {
1884
11
      static_cast<GetNameInfoReqWrap*>(req->data)};
1885
11
  Environment* env = req_wrap->env();
1886
1887
22
  HandleScope handle_scope(env->isolate());
1888
11
  Context::Scope context_scope(env->context());
1889
1890
  Local<Value> argv[] = {
1891
    Integer::New(env->isolate(), status),
1892
    Null(env->isolate()),
1893
    Null(env->isolate())
1894
44
  };
1895
1896
11
  if (status == 0) {
1897
    // Success
1898
7
    Local<String> js_hostname = OneByteString(env->isolate(), hostname);
1899
7
    Local<String> js_service = OneByteString(env->isolate(), service);
1900
7
    argv[1] = js_hostname;
1901
7
    argv[2] = js_service;
1902
  }
1903
1904

22
  TRACE_EVENT_NESTABLE_ASYNC_END2(
1905
      TRACING_CATEGORY_NODE2(dns, native), "lookupService", req_wrap.get(),
1906
      "hostname", TRACE_STR_COPY(hostname),
1907
      "service", TRACE_STR_COPY(service));
1908
1909
  // Make the callback into JavaScript
1910
22
  req_wrap->MakeCallback(env->oncomplete_string(), arraysize(argv), argv);
1911
11
}
1912
1913
using ParseIPResult =
1914
    decltype(static_cast<ares_addr_port_node*>(nullptr)->addr);
1915
1916
24
int ParseIP(const char* ip, ParseIPResult* result = nullptr) {
1917
  ParseIPResult tmp;
1918
24
  if (result == nullptr) result = &tmp;
1919
24
  if (0 == uv_inet_pton(AF_INET, ip, result)) return 4;
1920
10
  if (0 == uv_inet_pton(AF_INET6, ip, result)) return 6;
1921
1
  return 0;
1922
}
1923
1924
24
void CanonicalizeIP(const FunctionCallbackInfo<Value>& args) {
1925
24
  v8::Isolate* isolate = args.GetIsolate();
1926
24
  node::Utf8Value ip(isolate, args[0]);
1927
1928
  ParseIPResult result;
1929
24
  const int rc = ParseIP(*ip, &result);
1930
48
  if (rc == 0) return;
1931
1932
  char canonical_ip[INET6_ADDRSTRLEN];
1933
23
  const int af = (rc == 4 ? AF_INET : AF_INET6);
1934
23
  CHECK_EQ(0, uv_inet_ntop(af, &result, canonical_ip, sizeof(canonical_ip)));
1935
  v8::Local<String> val = String::NewFromUtf8(isolate, canonical_ip,
1936
46
      v8::NewStringType::kNormal).ToLocalChecked();
1937
46
  args.GetReturnValue().Set(val);
1938
}
1939
1940
5156
void GetAddrInfo(const FunctionCallbackInfo<Value>& args) {
1941
5156
  Environment* env = Environment::GetCurrent(args);
1942
1943
10312
  CHECK(args[0]->IsObject());
1944
15468
  CHECK(args[1]->IsString());
1945
10312
  CHECK(args[2]->IsInt32());
1946
10312
  CHECK(args[4]->IsBoolean());
1947
10312
  Local<Object> req_wrap_obj = args[0].As<Object>();
1948
5156
  node::Utf8Value hostname(env->isolate(), args[1]);
1949
1950
5156
  int32_t flags = 0;
1951
10312
  if (args[3]->IsInt32()) {
1952
15468
    flags = args[3].As<Int32>()->Value();
1953
  }
1954
1955
  int family;
1956
1957

15468
  switch (args[2].As<Int32>()->Value()) {
1958
    case 0:
1959
5117
      family = AF_UNSPEC;
1960
5117
      break;
1961
    case 4:
1962
28
      family = AF_INET;
1963
28
      break;
1964
    case 6:
1965
11
      family = AF_INET6;
1966
11
      break;
1967
    default:
1968
      CHECK(0 && "bad address family");
1969
  }
1970
1971
  auto req_wrap = std::make_unique<GetAddrInfoReqWrap>(env,
1972
                                                       req_wrap_obj,
1973
15468
                                                       args[4]->IsTrue());
1974
1975
  struct addrinfo hints;
1976
5156
  memset(&hints, 0, sizeof(hints));
1977
5156
  hints.ai_family = family;
1978
5156
  hints.ai_socktype = SOCK_STREAM;
1979
5156
  hints.ai_flags = flags;
1980
1981


10312
  TRACE_EVENT_NESTABLE_ASYNC_BEGIN2(
1982
      TRACING_CATEGORY_NODE2(dns, native), "lookup", req_wrap.get(),
1983
      "hostname", TRACE_STR_COPY(*hostname),
1984
      "family",
1985
      family == AF_INET ? "ipv4" : family == AF_INET6 ? "ipv6" : "unspec");
1986
1987
5156
  int err = req_wrap->Dispatch(uv_getaddrinfo,
1988
                               AfterGetAddrInfo,
1989
                               *hostname,
1990
                               nullptr,
1991
10312
                               &hints);
1992
5156
  if (err == 0)
1993
    // Release ownership of the pointer allowing the ownership to be transferred
1994
5156
    USE(req_wrap.release());
1995
1996
15468
  args.GetReturnValue().Set(err);
1997
5156
}
1998
1999
2000
11
void GetNameInfo(const FunctionCallbackInfo<Value>& args) {
2001
11
  Environment* env = Environment::GetCurrent(args);
2002
2003
22
  CHECK(args[0]->IsObject());
2004
33
  CHECK(args[1]->IsString());
2005
22
  CHECK(args[2]->IsUint32());
2006
22
  Local<Object> req_wrap_obj = args[0].As<Object>();
2007
11
  node::Utf8Value ip(env->isolate(), args[1]);
2008
44
  const unsigned port = args[2]->Uint32Value(env->context()).FromJust();
2009
  struct sockaddr_storage addr;
2010
2011

11
  CHECK(uv_ip4_addr(*ip, port, reinterpret_cast<sockaddr_in*>(&addr)) == 0 ||
2012
        uv_ip6_addr(*ip, port, reinterpret_cast<sockaddr_in6*>(&addr)) == 0);
2013
2014
22
  auto req_wrap = std::make_unique<GetNameInfoReqWrap>(env, req_wrap_obj);
2015
2016

22
  TRACE_EVENT_NESTABLE_ASYNC_BEGIN2(
2017
      TRACING_CATEGORY_NODE2(dns, native), "lookupService", req_wrap.get(),
2018
      "ip", TRACE_STR_COPY(*ip), "port", port);
2019
2020
11
  int err = req_wrap->Dispatch(uv_getnameinfo,
2021
                               AfterGetNameInfo,
2022
                               reinterpret_cast<struct sockaddr*>(&addr),
2023
11
                               NI_NAMEREQD);
2024
11
  if (err == 0)
2025
    // Release ownership of the pointer allowing the ownership to be transferred
2026
11
    USE(req_wrap.release());
2027
2028
33
  args.GetReturnValue().Set(err);
2029
11
}
2030
2031
2032
56
void GetServers(const FunctionCallbackInfo<Value>& args) {
2033
56
  Environment* env = Environment::GetCurrent(args);
2034
  ChannelWrap* channel;
2035
112
  ASSIGN_OR_RETURN_UNWRAP(&channel, args.Holder());
2036
2037
56
  Local<Array> server_array = Array::New(env->isolate());
2038
2039
  ares_addr_port_node* servers;
2040
2041
56
  int r = ares_get_servers_ports(channel->cares_channel(), &servers);
2042
56
  CHECK_EQ(r, ARES_SUCCESS);
2043
2044
56
  ares_addr_port_node* cur = servers;
2045
2046
171
  for (uint32_t i = 0; cur != nullptr; ++i, cur = cur->next) {
2047
    char ip[INET6_ADDRSTRLEN];
2048
2049
115
    const void* caddr = static_cast<const void*>(&cur->addr);
2050
115
    int err = uv_inet_ntop(cur->family, caddr, ip, sizeof(ip));
2051
115
    CHECK_EQ(err, 0);
2052
2053
115
    Local<Array> ret = Array::New(env->isolate(), 2);
2054
460
    ret->Set(env->context(), 0, OneByteString(env->isolate(), ip)).Check();
2055
115
    ret->Set(env->context(),
2056
             1,
2057
460
             Integer::New(env->isolate(), cur->udp_port)).Check();
2058
2059
345
    server_array->Set(env->context(), i, ret).Check();
2060
  }
2061
2062
56
  ares_free_data(servers);
2063
2064
112
  args.GetReturnValue().Set(server_array);
2065
}
2066
2067
2068
23
void SetServers(const FunctionCallbackInfo<Value>& args) {
2069
23
  Environment* env = Environment::GetCurrent(args);
2070
  ChannelWrap* channel;
2071
27
  ASSIGN_OR_RETURN_UNWRAP(&channel, args.Holder());
2072
2073
23
  if (channel->active_query_count()) {
2074
4
    return args.GetReturnValue().Set(DNS_ESETSRVPENDING);
2075
  }
2076
2077
42
  CHECK(args[0]->IsArray());
2078
2079
21
  Local<Array> arr = Local<Array>::Cast(args[0]);
2080
2081
21
  uint32_t len = arr->Length();
2082
2083
21
  if (len == 0) {
2084
2
    int rv = ares_set_servers(channel->cares_channel(), nullptr);
2085
4
    return args.GetReturnValue().Set(rv);
2086
  }
2087
2088
19
  std::vector<ares_addr_port_node> servers(len);
2089
19
  ares_addr_port_node* last = nullptr;
2090
2091
  int err;
2092
2093
50
  for (uint32_t i = 0; i < len; i++) {
2094
124
    CHECK(arr->Get(env->context(), i).ToLocalChecked()->IsArray());
2095
2096
    Local<Array> elm =
2097
93
        Local<Array>::Cast(arr->Get(env->context(), i).ToLocalChecked());
2098
2099
155
    CHECK(elm->Get(env->context(),
2100
                   0).ToLocalChecked()->Int32Value(env->context()).FromJust());
2101
155
    CHECK(elm->Get(env->context(), 1).ToLocalChecked()->IsString());
2102
155
    CHECK(elm->Get(env->context(),
2103
                   2).ToLocalChecked()->Int32Value(env->context()).FromJust());
2104
2105
62
    int fam = elm->Get(env->context(), 0)
2106
155
        .ToLocalChecked()->Int32Value(env->context()).FromJust();
2107
    node::Utf8Value ip(env->isolate(),
2108
93
                       elm->Get(env->context(), 1).ToLocalChecked());
2109
62
    int port = elm->Get(env->context(), 2)
2110
155
        .ToLocalChecked()->Int32Value(env->context()).FromJust();
2111
2112
31
    ares_addr_port_node* cur = &servers[i];
2113
2114
31
    cur->tcp_port = cur->udp_port = port;
2115
31
    switch (fam) {
2116
      case 4:
2117
24
        cur->family = AF_INET;
2118
24
        err = uv_inet_pton(AF_INET, *ip, &cur->addr);
2119
24
        break;
2120
      case 6:
2121
7
        cur->family = AF_INET6;
2122
7
        err = uv_inet_pton(AF_INET6, *ip, &cur->addr);
2123
7
        break;
2124
      default:
2125
        CHECK(0 && "Bad address family.");
2126
    }
2127
2128
31
    if (err)
2129
      break;
2130
2131
31
    cur->next = nullptr;
2132
2133
31
    if (last != nullptr)
2134
12
      last->next = cur;
2135
2136
31
    last = cur;
2137
31
  }
2138
2139
19
  if (err == 0)
2140
19
    err = ares_set_servers_ports(channel->cares_channel(), &servers[0]);
2141
  else
2142
    err = ARES_EBADSTR;
2143
2144
19
  if (err == ARES_SUCCESS)
2145
19
    channel->set_is_servers_default(false);
2146
2147
38
  args.GetReturnValue().Set(err);
2148
}
2149
2150
3
void Cancel(const FunctionCallbackInfo<Value>& args) {
2151
  ChannelWrap* channel;
2152
6
  ASSIGN_OR_RETURN_UNWRAP(&channel, args.Holder());
2153
2154

6
  TRACE_EVENT_INSTANT0(TRACING_CATEGORY_NODE2(dns, native),
2155
      "cancel", TRACE_EVENT_SCOPE_THREAD);
2156
2157
3
  ares_cancel(channel->cares_channel());
2158
}
2159
2160
const char EMSG_ESETSRVPENDING[] = "There are pending queries.";
2161
1
void StrError(const FunctionCallbackInfo<Value>& args) {
2162
1
  Environment* env = Environment::GetCurrent(args);
2163
4
  int code = args[0]->Int32Value(env->context()).FromJust();
2164
  const char* errmsg = (code == DNS_ESETSRVPENDING) ?
2165
    EMSG_ESETSRVPENDING :
2166
1
    ares_strerror(code);
2167
3
  args.GetReturnValue().Set(OneByteString(env->isolate(), errmsg));
2168
1
}
2169
2170
2171
1163
void Initialize(Local<Object> target,
2172
                Local<Value> unused,
2173
                Local<Context> context,
2174
                void* priv) {
2175
1163
  Environment* env = Environment::GetCurrent(context);
2176
2177
1163
  env->SetMethod(target, "getaddrinfo", GetAddrInfo);
2178
1163
  env->SetMethod(target, "getnameinfo", GetNameInfo);
2179
1163
  env->SetMethodNoSideEffect(target, "canonicalizeIP", CanonicalizeIP);
2180
2181
1163
  env->SetMethod(target, "strerror", StrError);
2182
2183
  target->Set(env->context(), FIXED_ONE_BYTE_STRING(env->isolate(), "AF_INET"),
2184
5815
              Integer::New(env->isolate(), AF_INET)).Check();
2185
  target->Set(env->context(), FIXED_ONE_BYTE_STRING(env->isolate(), "AF_INET6"),
2186
5815
              Integer::New(env->isolate(), AF_INET6)).Check();
2187
  target->Set(env->context(), FIXED_ONE_BYTE_STRING(env->isolate(),
2188
                                                    "AF_UNSPEC"),
2189
5815
              Integer::New(env->isolate(), AF_UNSPEC)).Check();
2190
  target->Set(env->context(), FIXED_ONE_BYTE_STRING(env->isolate(),
2191
                                                    "AI_ADDRCONFIG"),
2192
5815
              Integer::New(env->isolate(), AI_ADDRCONFIG)).Check();
2193
  target->Set(env->context(), FIXED_ONE_BYTE_STRING(env->isolate(),
2194
                                                    "AI_V4MAPPED"),
2195
5815
              Integer::New(env->isolate(), AI_V4MAPPED)).Check();
2196
2197
  Local<FunctionTemplate> aiw =
2198
1163
      BaseObject::MakeLazilyInitializedJSTemplate(env);
2199
2326
  aiw->Inherit(AsyncWrap::GetConstructorTemplate(env));
2200
  Local<String> addrInfoWrapString =
2201
1163
      FIXED_ONE_BYTE_STRING(env->isolate(), "GetAddrInfoReqWrap");
2202
1163
  aiw->SetClassName(addrInfoWrapString);
2203
  target->Set(env->context(),
2204
              addrInfoWrapString,
2205
4652
              aiw->GetFunction(context).ToLocalChecked()).Check();
2206
2207
  Local<FunctionTemplate> niw =
2208
1163
      BaseObject::MakeLazilyInitializedJSTemplate(env);
2209
2326
  niw->Inherit(AsyncWrap::GetConstructorTemplate(env));
2210
  Local<String> nameInfoWrapString =
2211
1163
      FIXED_ONE_BYTE_STRING(env->isolate(), "GetNameInfoReqWrap");
2212
1163
  niw->SetClassName(nameInfoWrapString);
2213
  target->Set(env->context(),
2214
              nameInfoWrapString,
2215
4652
              niw->GetFunction(context).ToLocalChecked()).Check();
2216
2217
  Local<FunctionTemplate> qrw =
2218
1163
      BaseObject::MakeLazilyInitializedJSTemplate(env);
2219
2326
  qrw->Inherit(AsyncWrap::GetConstructorTemplate(env));
2220
  Local<String> queryWrapString =
2221
1163
      FIXED_ONE_BYTE_STRING(env->isolate(), "QueryReqWrap");
2222
1163
  qrw->SetClassName(queryWrapString);
2223
  target->Set(env->context(),
2224
              queryWrapString,
2225
4652
              qrw->GetFunction(context).ToLocalChecked()).Check();
2226
2227
  Local<FunctionTemplate> channel_wrap =
2228
1163
      env->NewFunctionTemplate(ChannelWrap::New);
2229
2326
  channel_wrap->InstanceTemplate()->SetInternalFieldCount(1);
2230
2326
  channel_wrap->Inherit(AsyncWrap::GetConstructorTemplate(env));
2231
2232
1163
  env->SetProtoMethod(channel_wrap, "queryAny", Query<QueryAnyWrap>);
2233
1163
  env->SetProtoMethod(channel_wrap, "queryA", Query<QueryAWrap>);
2234
1163
  env->SetProtoMethod(channel_wrap, "queryAaaa", Query<QueryAaaaWrap>);
2235
1163
  env->SetProtoMethod(channel_wrap, "queryCname", Query<QueryCnameWrap>);
2236
1163
  env->SetProtoMethod(channel_wrap, "queryMx", Query<QueryMxWrap>);
2237
1163
  env->SetProtoMethod(channel_wrap, "queryNs", Query<QueryNsWrap>);
2238
1163
  env->SetProtoMethod(channel_wrap, "queryTxt", Query<QueryTxtWrap>);
2239
1163
  env->SetProtoMethod(channel_wrap, "querySrv", Query<QuerySrvWrap>);
2240
1163
  env->SetProtoMethod(channel_wrap, "queryPtr", Query<QueryPtrWrap>);
2241
1163
  env->SetProtoMethod(channel_wrap, "queryNaptr", Query<QueryNaptrWrap>);
2242
1163
  env->SetProtoMethod(channel_wrap, "querySoa", Query<QuerySoaWrap>);
2243
1163
  env->SetProtoMethod(channel_wrap, "getHostByAddr", Query<GetHostByAddrWrap>);
2244
2245
1163
  env->SetProtoMethodNoSideEffect(channel_wrap, "getServers", GetServers);
2246
1163
  env->SetProtoMethod(channel_wrap, "setServers", SetServers);
2247
1163
  env->SetProtoMethod(channel_wrap, "cancel", Cancel);
2248
2249
  Local<String> channelWrapString =
2250
1163
      FIXED_ONE_BYTE_STRING(env->isolate(), "ChannelWrap");
2251
1163
  channel_wrap->SetClassName(channelWrapString);
2252
  target->Set(env->context(), channelWrapString,
2253
4652
              channel_wrap->GetFunction(context).ToLocalChecked()).Check();
2254
1163
}
2255
2256
}  // anonymous namespace
2257
}  // namespace cares_wrap
2258
}  // namespace node
2259
2260

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