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: 863 1165 74.1 %
Date: 2020-05-27 22:15:15 Branches: 291 618 47.1 %

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
4326
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
6
inline const char* ToErrorCodeString(int status) {
94






6
  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
    V(ETIMEOUT)
120
#undef V
121
  }
122
123
  return "UNKNOWN_ARES_ERROR";
124
}
125
126
class ChannelWrap;
127
128
140
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
1025
struct TaskHash {
139
60
  size_t operator()(node_ares_task* a) const {
140
60
    return std::hash<ares_socket_t>()(a->sock);
141
  }
142
};
143
144
1025
struct TaskEqual {
145
20
  inline bool operator()(node_ares_task* a, node_ares_task* b) const {
146
20
    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);
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
16
  inline uv_timer_t* timer_handle() { return timer_handle_; }
168
120
  inline ares_channel cares_channel() { return channel_; }
169
23
  inline void set_query_last_ok(bool ok) { query_last_ok_ = ok; }
170
17
  inline void set_is_servers_default(bool is_default) {
171
17
    is_servers_default_ = is_default;
172
17
  }
173
21
  inline int active_query_count() { return active_query_count_; }
174
140
  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 active_query_count_;
194
  node_ares_task_list task_list_;
195
};
196
197
1025
ChannelWrap::ChannelWrap(Environment* env,
198
1025
                         Local<Object> object)
199
  : AsyncWrap(env, object, PROVIDER_DNSCHANNEL),
200
    timer_handle_(nullptr),
201
    channel_(nullptr),
202
    query_last_ok_(true),
203
    is_servers_default_(true),
204
    library_inited_(false),
205
1025
    active_query_count_(0) {
206
1025
  MakeWeak();
207
208
1025
  Setup();
209
1025
}
210
211
1025
void ChannelWrap::New(const FunctionCallbackInfo<Value>& args) {
212
1025
  CHECK(args.IsConstructCall());
213
1025
  CHECK_EQ(args.Length(), 0);
214
215
1025
  Environment* env = Environment::GetCurrent(args);
216
1025
  new ChannelWrap(env, args.This());
217
1025
}
218
219
9444
class GetAddrInfoReqWrap : public ReqWrap<uv_getaddrinfo_t> {
220
 public:
221
  GetAddrInfoReqWrap(Environment* env,
222
                     Local<Object> req_wrap_obj,
223
                     bool verbatim);
224
225
1
  SET_NO_MEMORY_INFO()
226
1
  SET_MEMORY_INFO_NAME(GetAddrInfoReqWrap)
227
1
  SET_SELF_SIZE(GetAddrInfoReqWrap)
228
229
4722
  bool verbatim() const { return verbatim_; }
230
231
 private:
232
  const bool verbatim_;
233
};
234
235
4723
GetAddrInfoReqWrap::GetAddrInfoReqWrap(Environment* env,
236
                                       Local<Object> req_wrap_obj,
237
4723
                                       bool verbatim)
238
    : ReqWrap(env, req_wrap_obj, AsyncWrap::PROVIDER_GETADDRINFOREQWRAP)
239
4723
    , verbatim_(verbatim) {
240
4723
}
241
242
243
8
class GetNameInfoReqWrap : public ReqWrap<uv_getnameinfo_t> {
244
 public:
245
  GetNameInfoReqWrap(Environment* env, Local<Object> req_wrap_obj);
246
247
1
  SET_NO_MEMORY_INFO()
248
1
  SET_MEMORY_INFO_NAME(GetNameInfoReqWrap)
249
1
  SET_SELF_SIZE(GetNameInfoReqWrap)
250
};
251
252
4
GetNameInfoReqWrap::GetNameInfoReqWrap(Environment* env,
253
4
                                       Local<Object> req_wrap_obj)
254
4
    : ReqWrap(env, req_wrap_obj, AsyncWrap::PROVIDER_GETNAMEINFOREQWRAP) {
255
4
}
256
257
258
/* This is called once per second by loop->timer. It is used to constantly */
259
/* call back into c-ares for possibly processing timeouts. */
260
void ChannelWrap::AresTimeout(uv_timer_t* handle) {
261
  ChannelWrap* channel = static_cast<ChannelWrap*>(handle->data);
262
  CHECK_EQ(channel->timer_handle(), handle);
263
  CHECK_EQ(false, channel->task_list()->empty());
264
  ares_process_fd(channel->cares_channel(), ARES_SOCKET_BAD, ARES_SOCKET_BAD);
265
}
266
267
268
16
void ares_poll_cb(uv_poll_t* watcher, int status, int events) {
269
16
  node_ares_task* task = ContainerOf(&node_ares_task::poll_watcher, watcher);
270
16
  ChannelWrap* channel = task->channel;
271
272
  /* Reset the idle timer */
273
16
  uv_timer_again(channel->timer_handle());
274
275
16
  if (status < 0) {
276
    /* An error happened. Just pretend that the socket is both readable and */
277
    /* writable. */
278
    ares_process_fd(channel->cares_channel(), task->sock, task->sock);
279
    return;
280
  }
281
282
  /* Process DNS responses */
283

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

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

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

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

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

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

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

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

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


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

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

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

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

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

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

4
    if (status != ARES_SUCCESS && status != ARES_ENODATA) {
1303
      ParseError(status);
1304
      return;
1305
    }
1306
1307
    /* Parse SRV records */
1308
4
    status = ParseSrvReply(env(), buf, len, ret, true);
1309

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

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

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

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






24
  ASSIGN_OR_RETURN_UNWRAP(&channel, args.Holder());
1786
1787






24
  CHECK_EQ(false, args.IsConstructCall());
1788






48
  CHECK(args[0]->IsObject());
1789






72
  CHECK(args[1]->IsString());
1790
1791
48
  Local<Object> req_wrap_obj = args[0].As<Object>();
1792
48
  Local<String> string = args[1].As<String>();
1793
48
  auto wrap = std::make_unique<Wrap>(channel, req_wrap_obj);
1794
1795
48
  node::Utf8Value name(env->isolate(), string);
1796
24
  channel->ModifyActivityQueryCount(1);
1797
24
  int err = wrap->Send(*name);
1798






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

28896
        if (want_ipv4 && p->ai_family == AF_INET) {
1834
4900
          addr = reinterpret_cast<char*>(
1835
9800
              &(reinterpret_cast<struct sockaddr_in*>(p->ai_addr)->sin_addr));
1836

23996
        } else if (want_ipv6 && p->ai_family == AF_INET6) {
1837
9548
          addr = reinterpret_cast<char*>(
1838
19096
              &(reinterpret_cast<struct sockaddr_in6*>(p->ai_addr)->sin6_addr));
1839
        } else {
1840
28896
          continue;
1841
        }
1842
1843
        char ip[INET6_ADDRSTRLEN];
1844
14448
        if (uv_inet_ntop(p->ai_family, addr, ip, sizeof(ip)))
1845
          continue;
1846
1847
28896
        Local<String> s = OneByteString(env->isolate(), ip);
1848
57792
        results->Set(env->context(), n, s).Check();
1849
14448
        n++;
1850
      }
1851
14139
    };
1852
1853
4713
    add(true, verbatim);
1854
4713
    if (verbatim == false)
1855
4713
      add(false, true);
1856
1857
    // No responses were found to return
1858
4713
    if (n == 0) {
1859
      argv[0] = Integer::New(env->isolate(), UV_EAI_NODATA);
1860
    }
1861
1862
4713
    argv[1] = results;
1863
  }
1864
1865
4722
  uv_freeaddrinfo(res);
1866
1867

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

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

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


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

4
  CHECK(uv_ip4_addr(*ip, port, reinterpret_cast<sockaddr_in*>(&addr)) == 0 ||
2009
        uv_ip6_addr(*ip, port, reinterpret_cast<sockaddr_in6*>(&addr)) == 0);
2010
2011
8
  auto req_wrap = std::make_unique<GetNameInfoReqWrap>(env, req_wrap_obj);
2012
2013

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

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

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