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: 876 1172 74.7 %
Date: 2020-09-06 22:14:11 Branches: 300 626 47.9 %

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::Isolate;
68
using v8::Local;
69
using v8::Null;
70
using v8::Object;
71
using v8::String;
72
using v8::Value;
73
74
namespace {
75
76
4473
Mutex ares_library_mutex;
77
78
56
inline uint16_t cares_get_16bit(const unsigned char* p) {
79
56
  return static_cast<uint32_t>(p[0] << 8U) | (static_cast<uint32_t>(p[1]));
80
}
81
82
20
inline uint32_t cares_get_32bit(const unsigned char* p) {
83
40
  return static_cast<uint32_t>(p[0] << 24U) |
84
40
         static_cast<uint32_t>(p[1] << 16U) |
85
20
         static_cast<uint32_t>(p[2] << 8U) |
86
20
         static_cast<uint32_t>(p[3]);
87
}
88
89
const int ns_t_cname_or_a = -1;
90
91
#define DNS_ESETSRVPENDING -1000
92
12
inline const char* ToErrorCodeString(int status) {
93






12
  switch (status) {
94
#define V(code) case ARES_##code: return #code;
95
    V(EADDRGETNETWORKPARAMS)
96
    V(EBADFAMILY)
97
    V(EBADFLAGS)
98
    V(EBADHINTS)
99
    V(EBADNAME)
100
    V(EBADQUERY)
101
2
    V(EBADRESP)
102
    V(EBADSTR)
103
3
    V(ECANCELLED)
104
    V(ECONNREFUSED)
105
    V(EDESTRUCTION)
106
    V(EFILE)
107
    V(EFORMERR)
108
    V(ELOADIPHLPAPI)
109
    V(ENODATA)
110
    V(ENOMEM)
111
    V(ENONAME)
112
1
    V(ENOTFOUND)
113
    V(ENOTIMP)
114
    V(ENOTINITIALIZED)
115
    V(EOF)
116
    V(EREFUSED)
117
    V(ESERVFAIL)
118
6
    V(ETIMEOUT)
119
#undef V
120
  }
121
122
  return "UNKNOWN_ARES_ERROR";
123
}
124
125
class ChannelWrap;
126
127
182
struct node_ares_task : public MemoryRetainer {
128
  ChannelWrap* channel;
129
  ares_socket_t sock;
130
  uv_poll_t poll_watcher;
131
132
  inline void MemoryInfo(MemoryTracker* tracker) const override;
133
  SET_MEMORY_INFO_NAME(node_ares_task)
134
  SET_SELF_SIZE(node_ares_task)
135
};
136
137
1058
struct TaskHash {
138
78
  size_t operator()(node_ares_task* a) const {
139
78
    return std::hash<ares_socket_t>()(a->sock);
140
  }
141
};
142
143
1058
struct TaskEqual {
144
26
  inline bool operator()(node_ares_task* a, node_ares_task* b) const {
145
26
    return a->sock == b->sock;
146
  }
147
};
148
149
using node_ares_task_list =
150
    std::unordered_set<node_ares_task*, TaskHash, TaskEqual>;
151
152
class ChannelWrap : public AsyncWrap {
153
 public:
154
  ChannelWrap(Environment* env, Local<Object> object, int timeout);
155
  ~ChannelWrap() override;
156
157
  static void New(const FunctionCallbackInfo<Value>& args);
158
159
  void Setup();
160
  void EnsureServers();
161
  void StartTimer();
162
  void CloseTimer();
163
164
  void ModifyActivityQueryCount(int count);
165
166
87
  inline uv_timer_t* timer_handle() { return timer_handle_; }
167
209
  inline ares_channel cares_channel() { return channel_; }
168
29
  inline void set_query_last_ok(bool ok) { query_last_ok_ = ok; }
169
23
  inline void set_is_servers_default(bool is_default) {
170
23
    is_servers_default_ = is_default;
171
23
  }
172
27
  inline int active_query_count() { return active_query_count_; }
173
253
  inline node_ares_task_list* task_list() { return &task_list_; }
174
175
4
  void MemoryInfo(MemoryTracker* tracker) const override {
176
4
    if (timer_handle_ != nullptr)
177
      tracker->TrackField("timer_handle", *timer_handle_);
178
4
    tracker->TrackField("task_list", task_list_, "node_ares_task_list");
179
4
  }
180
181
4
  SET_MEMORY_INFO_NAME(ChannelWrap)
182
4
  SET_SELF_SIZE(ChannelWrap)
183
184
  static void AresTimeout(uv_timer_t* handle);
185
186
 private:
187
  uv_timer_t* timer_handle_;
188
  ares_channel channel_;
189
  bool query_last_ok_;
190
  bool is_servers_default_;
191
  bool library_inited_;
192
  int timeout_;
193
  int active_query_count_;
194
  node_ares_task_list task_list_;
195
};
196
197
1058
ChannelWrap::ChannelWrap(Environment* env,
198
                         Local<Object> object,
199
1058
                         int timeout)
200
  : AsyncWrap(env, object, PROVIDER_DNSCHANNEL),
201
    timer_handle_(nullptr),
202
    channel_(nullptr),
203
    query_last_ok_(true),
204
    is_servers_default_(true),
205
    library_inited_(false),
206
    timeout_(timeout),
207
1058
    active_query_count_(0) {
208
1058
  MakeWeak();
209
210
1058
  Setup();
211
1058
}
212
213
1058
void ChannelWrap::New(const FunctionCallbackInfo<Value>& args) {
214
1058
  CHECK(args.IsConstructCall());
215
1058
  CHECK_EQ(args.Length(), 1);
216
2116
  CHECK(args[0]->IsInt32());
217
3174
  const int timeout = args[0].As<Int32>()->Value();
218
1058
  Environment* env = Environment::GetCurrent(args);
219
1058
  new ChannelWrap(env, args.This(), timeout);
220
1058
}
221
222
9478
class GetAddrInfoReqWrap : public ReqWrap<uv_getaddrinfo_t> {
223
 public:
224
  GetAddrInfoReqWrap(Environment* env,
225
                     Local<Object> req_wrap_obj,
226
                     bool verbatim);
227
228
1
  SET_NO_MEMORY_INFO()
229
1
  SET_MEMORY_INFO_NAME(GetAddrInfoReqWrap)
230
1
  SET_SELF_SIZE(GetAddrInfoReqWrap)
231
232
4739
  bool verbatim() const { return verbatim_; }
233
234
 private:
235
  const bool verbatim_;
236
};
237
238
4740
GetAddrInfoReqWrap::GetAddrInfoReqWrap(Environment* env,
239
                                       Local<Object> req_wrap_obj,
240
4740
                                       bool verbatim)
241
    : ReqWrap(env, req_wrap_obj, AsyncWrap::PROVIDER_GETADDRINFOREQWRAP)
242
4740
    , verbatim_(verbatim) {
243
4740
}
244
245
246
8
class GetNameInfoReqWrap : public ReqWrap<uv_getnameinfo_t> {
247
 public:
248
  GetNameInfoReqWrap(Environment* env, Local<Object> req_wrap_obj);
249
250
1
  SET_NO_MEMORY_INFO()
251
1
  SET_MEMORY_INFO_NAME(GetNameInfoReqWrap)
252
1
  SET_SELF_SIZE(GetNameInfoReqWrap)
253
};
254
255
4
GetNameInfoReqWrap::GetNameInfoReqWrap(Environment* env,
256
4
                                       Local<Object> req_wrap_obj)
257
4
    : ReqWrap(env, req_wrap_obj, AsyncWrap::PROVIDER_GETNAMEINFOREQWRAP) {
258
4
}
259
260
261
/* This is called once per second by loop->timer. It is used to constantly */
262
/* call back into c-ares for possibly processing timeouts. */
263
71
void ChannelWrap::AresTimeout(uv_timer_t* handle) {
264
71
  ChannelWrap* channel = static_cast<ChannelWrap*>(handle->data);
265
71
  CHECK_EQ(channel->timer_handle(), handle);
266
71
  CHECK_EQ(false, channel->task_list()->empty());
267
71
  ares_process_fd(channel->cares_channel(), ARES_SOCKET_BAD, ARES_SOCKET_BAD);
268
71
}
269
270
271
16
void ares_poll_cb(uv_poll_t* watcher, int status, int events) {
272
16
  node_ares_task* task = ContainerOf(&node_ares_task::poll_watcher, watcher);
273
16
  ChannelWrap* channel = task->channel;
274
275
  /* Reset the idle timer */
276
16
  uv_timer_again(channel->timer_handle());
277
278
16
  if (status < 0) {
279
    /* An error happened. Just pretend that the socket is both readable and */
280
    /* writable. */
281
    ares_process_fd(channel->cares_channel(), task->sock, task->sock);
282
    return;
283
  }
284
285
  /* Process DNS responses */
286

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

52
  if (read || write) {
334
26
    if (!task) {
335
      /* New socket */
336
26
      channel->StartTimer();
337
338
26
      task = ares_task_create(channel, sock);
339
26
      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
26
      channel->task_list()->insert(task);
347
    }
348
349
    /* This should never fail. If it fails anyway, the query will eventually */
350
    /* time out. */
351
26
    uv_poll_start(&task->poll_watcher,
352

26
                  (read ? UV_READABLE : 0) | (write ? UV_WRITABLE : 0),
353
26
                  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
26
    CHECK(task &&
360
          "When an ares socket is closed we should have a handle for it");
361
362
26
    channel->task_list()->erase(it);
363
26
    channel->env()->CloseHandle(&task->poll_watcher, ares_poll_close_cb);
364
365
26
    if (channel->task_list()->empty()) {
366
26
      channel->CloseTimer();
367
    }
368
  }
369
}
370
371
372
6
Local<Array> HostentToNames(Environment* env,
373
                            struct hostent* host,
374
                            Local<Array> append_to = Local<Array>()) {
375
6
  EscapableHandleScope scope(env->isolate());
376
6
  auto context = env->context();
377
6
  bool append = !append_to.IsEmpty();
378
6
  Local<Array> names = append ? append_to : Array::New(env->isolate());
379
6
  size_t offset = names->Length();
380
381
10
  for (uint32_t i = 0; host->h_aliases[i] != nullptr; ++i) {
382
4
    Local<String> address = OneByteString(env->isolate(), host->h_aliases[i]);
383
12
    names->Set(context, i + offset, address).Check();
384
  }
385
386
18
  return append ? names : scope.Escape(names);
387
}
388
389
2
void safe_free_hostent(struct hostent* host) {
390
  int idx;
391
392
2
  if (host->h_addr_list != nullptr) {
393
2
    idx = 0;
394
6
    while (host->h_addr_list[idx]) {
395
2
      free(host->h_addr_list[idx++]);
396
    }
397
2
    free(host->h_addr_list);
398
2
    host->h_addr_list = nullptr;
399
  }
400
401
2
  if (host->h_aliases != nullptr) {
402
2
    idx = 0;
403
2
    while (host->h_aliases[idx]) {
404
      free(host->h_aliases[idx++]);
405
    }
406
2
    free(host->h_aliases);
407
2
    host->h_aliases = nullptr;
408
  }
409
410
2
  free(host->h_name);
411
2
  free(host);
412
2
}
413
414
2
void cares_wrap_hostent_cpy(struct hostent* dest, const struct hostent* src) {
415
2
  dest->h_addr_list = nullptr;
416
2
  dest->h_addrtype = 0;
417
2
  dest->h_aliases = nullptr;
418
2
  dest->h_length = 0;
419
2
  dest->h_name = nullptr;
420
421
  /* copy `h_name` */
422
2
  size_t name_size = strlen(src->h_name) + 1;
423
2
  dest->h_name = node::Malloc<char>(name_size);
424
2
  memcpy(dest->h_name, src->h_name, name_size);
425
426
  /* copy `h_aliases` */
427
  size_t alias_count;
428
2
  for (alias_count = 0;
429
2
      src->h_aliases[alias_count] != nullptr;
430
      alias_count++) {
431
  }
432
433
2
  dest->h_aliases = node::Malloc<char*>(alias_count + 1);
434
2
  for (size_t i = 0; i < alias_count; i++) {
435
    const size_t cur_alias_size = strlen(src->h_aliases[i]) + 1;
436
    dest->h_aliases[i] = node::Malloc(cur_alias_size);
437
    memcpy(dest->h_aliases[i], src->h_aliases[i], cur_alias_size);
438
  }
439
2
  dest->h_aliases[alias_count] = nullptr;
440
441
  /* copy `h_addr_list` */
442
  size_t list_count;
443
4
  for (list_count = 0;
444
4
      src->h_addr_list[list_count] != nullptr;
445
      list_count++) {
446
  }
447
448
2
  dest->h_addr_list = node::Malloc<char*>(list_count + 1);
449
4
  for (size_t i = 0; i < list_count; i++) {
450
2
    dest->h_addr_list[i] = node::Malloc(src->h_length);
451
2
    memcpy(dest->h_addr_list[i], src->h_addr_list[i], src->h_length);
452
  }
453
2
  dest->h_addr_list[list_count] = nullptr;
454
455
  /* work after work */
456
2
  dest->h_length = src->h_length;
457
2
  dest->h_addrtype = src->h_addrtype;
458
2
}
459
460
class QueryWrap;
461
462
1058
void ChannelWrap::Setup() {
463
  struct ares_options options;
464
1058
  memset(&options, 0, sizeof(options));
465
1058
  options.flags = ARES_FLAG_NOCHECKRESP;
466
1058
  options.sock_state_cb = ares_sockstate_cb;
467
1058
  options.sock_state_cb_data = this;
468
1058
  options.timeout = timeout_;
469
470
  int r;
471
1058
  if (!library_inited_) {
472
2116
    Mutex::ScopedLock lock(ares_library_mutex);
473
    // Multiple calls to ares_library_init() increase a reference counter,
474
    // so this is a no-op except for the first call to it.
475
1058
    r = ares_library_init(ARES_LIB_INIT_ALL);
476
1058
    if (r != ARES_SUCCESS)
477
      return env()->ThrowError(ToErrorCodeString(r));
478
  }
479
480
  /* We do the call to ares_init_option for caller. */
481
  const int optmask =
482
1058
      ARES_OPT_FLAGS | ARES_OPT_TIMEOUTMS | ARES_OPT_SOCK_STATE_CB;
483
1058
  r = ares_init_options(&channel_, &options, optmask);
484
485
1058
  if (r != ARES_SUCCESS) {
486
    Mutex::ScopedLock lock(ares_library_mutex);
487
    ares_library_cleanup();
488
    return env()->ThrowError(ToErrorCodeString(r));
489
  }
490
491
1058
  library_inited_ = true;
492
}
493
494
26
void ChannelWrap::StartTimer() {
495
26
  if (timer_handle_ == nullptr) {
496
26
    timer_handle_ = new uv_timer_t();
497
26
    timer_handle_->data = static_cast<void*>(this);
498
26
    uv_timer_init(env()->event_loop(), timer_handle_);
499
  } else if (uv_is_active(reinterpret_cast<uv_handle_t*>(timer_handle_))) {
500
    return;
501
  }
502
26
  int timeout = timeout_;
503
26
  if (timeout == 0) timeout = 1;
504

26
  if (timeout < 0 || timeout > 1000) timeout = 1000;
505
26
  uv_timer_start(timer_handle_, AresTimeout, timeout, timeout);
506
}
507
508
1057
void ChannelWrap::CloseTimer() {
509
1057
  if (timer_handle_ == nullptr)
510
1031
    return;
511
512
52
  env()->CloseHandle(timer_handle_, [](uv_timer_t* handle) { delete handle; });
513
26
  timer_handle_ = nullptr;
514
}
515
516
3093
ChannelWrap::~ChannelWrap() {
517
1031
  ares_destroy(channel_);
518
519
1031
  if (library_inited_) {
520
2062
    Mutex::ScopedLock lock(ares_library_mutex);
521
    // This decreases the reference counter increased by ares_library_init().
522
1031
    ares_library_cleanup();
523
  }
524
525
1031
  CloseTimer();
526
2062
}
527
528
529
59
void ChannelWrap::ModifyActivityQueryCount(int count) {
530
59
  active_query_count_ += count;
531
59
  CHECK_GE(active_query_count_, 0);
532
59
}
533
534
535
/**
536
 * This function is to check whether current servers are fallback servers
537
 * when cares initialized.
538
 *
539
 * The fallback servers of cares is [ "127.0.0.1" ] with no user additional
540
 * setting.
541
 */
542
27
void ChannelWrap::EnsureServers() {
543
  /* if last query is OK or servers are set by user self, do not check */
544

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

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

34
    TRACE_EVENT_NESTABLE_ASYNC_END0(
719
        TRACING_CATEGORY_NODE2(dns, native), trace_name_, this);
720
721
17
    MakeCallback(env()->oncomplete_string(), argc, argv);
722
17
  }
723
724
12
  void ParseError(int status) {
725
12
    CHECK_NE(status, ARES_SUCCESS);
726
24
    HandleScope handle_scope(env()->isolate());
727
12
    Context::Scope context_scope(env()->context());
728
12
    const char* code = ToErrorCodeString(status);
729
12
    Local<Value> arg = OneByteString(env()->isolate(), code);
730

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

18
  for (size_t i = 0; i < naddrttls; i++)
764
18
    ttls[i] = Integer::NewFromUnsigned(isolate, addrttls[i].ttl);
765
766
18
  return Array::New(isolate, ttls.out(), naddrttls);
767
}
768
769
770
27
int ParseGeneralReply(Environment* env,
771
                      const unsigned char* buf,
772
                      int len,
773
                      int* type,
774
                      Local<Array> ret,
775
                      void* addrttls = nullptr,
776
                      int* naddrttls = nullptr) {
777
54
  HandleScope handle_scope(env->isolate());
778
27
  auto context = env->context();
779
  hostent* host;
780
781
  int status;
782

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


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

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

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

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

4
    if (status != ARES_SUCCESS && status != ARES_ENODATA) {
1284
      ParseError(status);
1285
      return;
1286
    }
1287
1288
    /* Parse NS records */
1289
4
    type = ns_t_ns;
1290
4
    old_count = ret->Length();
1291
4
    status = ParseGeneralReply(env(), buf, len, &type, ret);
1292

4
    if (status != ARES_SUCCESS && status != ARES_ENODATA) {
1293
      ParseError(status);
1294
      return;
1295
    }
1296
16
    for (uint32_t i = old_count; i < ret->Length(); i++) {
1297
4
      Local<Object> obj = Object::New(env()->isolate());
1298
8
      obj->Set(context,
1299
               env()->value_string(),
1300
16
               ret->Get(context, i).ToLocalChecked()).Check();
1301
8
      obj->Set(context,
1302
               env()->type_string(),
1303
16
               env()->dns_ns_string()).Check();
1304
8
      ret->Set(context, i, obj).Check();
1305
    }
1306
1307
    /* Parse TXT records */
1308
4
    status = ParseTxtReply(env(), buf, len, ret, true);
1309

4
    if (status != ARES_SUCCESS && status != ARES_ENODATA) {
1310
      ParseError(status);
1311
      return;
1312
    }
1313
1314
    /* Parse SRV records */
1315
4
    status = ParseSrvReply(env(), buf, len, ret, true);
1316

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

4
    if (status != ARES_SUCCESS && status != ARES_ENODATA) {
1338
      ParseError(status);
1339
      return;
1340
    }
1341
1342
    /* Parse SOA records */
1343
    Local<Object> soa_record = Local<Object>();
1344
4
    status = ParseSoaReply(env(), buf, len, &soa_record);
1345

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

6
    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
3
    ares_gethostbyaddr(channel_->cares_channel(),
1767
                       address_buffer,
1768
                       length,
1769
                       family,
1770
                       Callback,
1771
3
                       MakeCallbackPointer());
1772
3
    return 0;
1773
  }
1774
1775
  SET_NO_MEMORY_INFO()
1776
  SET_MEMORY_INFO_NAME(GetHostByAddrWrap)
1777
  SET_SELF_SIZE(GetHostByAddrWrap)
1778
1779
 protected:
1780
2
  void Parse(struct hostent* host) override {
1781
4
    HandleScope handle_scope(env()->isolate());
1782
2
    Context::Scope context_scope(env()->context());
1783
4
    this->CallOnComplete(HostentToNames(env(), host));
1784
2
  }
1785
};
1786
1787
1788
template <class Wrap>
1789
30
static void Query(const FunctionCallbackInfo<Value>& args) {
1790
30
  Environment* env = Environment::GetCurrent(args);
1791
  ChannelWrap* channel;
1792






30
  ASSIGN_OR_RETURN_UNWRAP(&channel, args.Holder());
1793
1794






30
  CHECK_EQ(false, args.IsConstructCall());
1795






60
  CHECK(args[0]->IsObject());
1796






90
  CHECK(args[1]->IsString());
1797
1798
60
  Local<Object> req_wrap_obj = args[0].As<Object>();
1799
60
  Local<String> string = args[1].As<String>();
1800
60
  auto wrap = std::make_unique<Wrap>(channel, req_wrap_obj);
1801
1802
60
  node::Utf8Value name(env->isolate(), string);
1803
30
  channel->ModifyActivityQueryCount(1);
1804
30
  int err = wrap->Send(*name);
1805






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

28914
        if (want_ipv4 && p->ai_family == AF_INET) {
1841
4895
          addr = reinterpret_cast<char*>(
1842
9790
              &(reinterpret_cast<struct sockaddr_in*>(p->ai_addr)->sin_addr));
1843

24019
        } else if (want_ipv6 && p->ai_family == AF_INET6) {
1844
9562
          addr = reinterpret_cast<char*>(
1845
19124
              &(reinterpret_cast<struct sockaddr_in6*>(p->ai_addr)->sin6_addr));
1846
        } else {
1847
28914
          continue;
1848
        }
1849
1850
        char ip[INET6_ADDRSTRLEN];
1851
14457
        if (uv_inet_ntop(p->ai_family, addr, ip, sizeof(ip)))
1852
          continue;
1853
1854
28914
        Local<String> s = OneByteString(env->isolate(), ip);
1855
57828
        results->Set(env->context(), n, s).Check();
1856
14457
        n++;
1857
      }
1858
14190
    };
1859
1860
4730
    add(true, verbatim);
1861
4730
    if (verbatim == false)
1862
4730
      add(false, true);
1863
1864
    // No responses were found to return
1865
4730
    if (n == 0) {
1866
      argv[0] = Integer::New(env->isolate(), UV_EAI_NODATA);
1867
    }
1868
1869
4730
    argv[1] = results;
1870
  }
1871
1872
4739
  uv_freeaddrinfo(res);
1873
1874

9478
  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
4739
  req_wrap->MakeCallback(env->oncomplete_string(), arraysize(argv), argv);
1880
4739
}
1881
1882
1883
4
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
8
      static_cast<GetNameInfoReqWrap*>(req->data)};
1889
4
  Environment* env = req_wrap->env();
1890
1891
8
  HandleScope handle_scope(env->isolate());
1892
4
  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
16
  };
1899
1900
4
  if (status == 0) {
1901
    // Success
1902
3
    Local<String> js_hostname = OneByteString(env->isolate(), hostname);
1903
3
    Local<String> js_service = OneByteString(env->isolate(), service);
1904
3
    argv[1] = js_hostname;
1905
3
    argv[2] = js_service;
1906
  }
1907
1908

8
  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
4
  req_wrap->MakeCallback(env->oncomplete_string(), arraysize(argv), argv);
1915
4
}
1916
1917
using ParseIPResult =
1918
    decltype(static_cast<ares_addr_port_node*>(nullptr)->addr);
1919
1920
24
int ParseIP(const char* ip, ParseIPResult* result = nullptr) {
1921
  ParseIPResult tmp;
1922
24
  if (result == nullptr) result = &tmp;
1923
24
  if (0 == uv_inet_pton(AF_INET, ip, result)) return 4;
1924
10
  if (0 == uv_inet_pton(AF_INET6, ip, result)) return 6;
1925
1
  return 0;
1926
}
1927
1928
24
void CanonicalizeIP(const FunctionCallbackInfo<Value>& args) {
1929
24
  Isolate* isolate = args.GetIsolate();
1930
47
  node::Utf8Value ip(isolate, args[0]);
1931
1932
  ParseIPResult result;
1933
24
  const int rc = ParseIP(*ip, &result);
1934
24
  if (rc == 0) return;
1935
1936
  char canonical_ip[INET6_ADDRSTRLEN];
1937
23
  const int af = (rc == 4 ? AF_INET : AF_INET6);
1938
23
  CHECK_EQ(0, uv_inet_ntop(af, &result, canonical_ip, sizeof(canonical_ip)));
1939
46
  Local<String> val = String::NewFromUtf8(isolate, canonical_ip)
1940
23
      .ToLocalChecked();
1941
46
  args.GetReturnValue().Set(val);
1942
}
1943
1944
4740
void GetAddrInfo(const FunctionCallbackInfo<Value>& args) {
1945
4740
  Environment* env = Environment::GetCurrent(args);
1946
1947
9480
  CHECK(args[0]->IsObject());
1948
14220
  CHECK(args[1]->IsString());
1949
9480
  CHECK(args[2]->IsInt32());
1950
9480
  CHECK(args[4]->IsBoolean());
1951
9480
  Local<Object> req_wrap_obj = args[0].As<Object>();
1952
9480
  node::Utf8Value hostname(env->isolate(), args[1]);
1953
1954
4740
  int32_t flags = 0;
1955
9480
  if (args[3]->IsInt32()) {
1956
14220
    flags = args[3].As<Int32>()->Value();
1957
  }
1958
1959
  int family;
1960
1961

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


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

4
  CHECK(uv_ip4_addr(*ip, port, reinterpret_cast<sockaddr_in*>(&addr)) == 0 ||
2016
        uv_ip6_addr(*ip, port, reinterpret_cast<sockaddr_in6*>(&addr)) == 0);
2017
2018
8
  auto req_wrap = std::make_unique<GetNameInfoReqWrap>(env, req_wrap_obj);
2019
2020

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

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

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