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






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

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

52
  if (read || write) {
335
26
    if (!task) {
336
      /* New socket */
337
26
      channel->StartTimer();
338
339
26
      task = ares_task_create(channel, sock);
340
26
      if (task == nullptr) {
341
        /* This should never happen unless we're out of memory or something */
342
        /* is seriously wrong. The socket won't be polled, but the query will */
343
        /* eventually time out. */
344
        return;
345
      }
346
347
26
      channel->task_list()->insert(task);
348
    }
349
350
    /* This should never fail. If it fails anyway, the query will eventually */
351
    /* time out. */
352
26
    uv_poll_start(&task->poll_watcher,
353

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

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

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

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

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

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

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

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


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

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

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

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

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

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

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

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

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

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

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






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






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






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






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






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

29118
        if (want_ipv4 && p->ai_family == AF_INET) {
1842
4953
          addr = reinterpret_cast<char*>(
1843
9906
              &(reinterpret_cast<struct sockaddr_in*>(p->ai_addr)->sin_addr));
1844

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

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

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

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


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

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

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

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

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