GCC Code Coverage Report
Directory: ../ Exec Total Coverage
File: /home/iojs/build/workspace/node-test-commit-linux-coverage/nodes/benchmark/out/../src/cares_wrap.cc Lines: 971 1110 87.5 %
Date: 2019-01-07 12:15:22 Branches: 388 644 60.2 %

Line Branch Exec Source
1
// Copyright Joyent, Inc. and other Node contributors.
2
//
3
// Permission is hereby granted, free of charge, to any person obtaining a
4
// copy of this software and associated documentation files (the
5
// "Software"), to deal in the Software without restriction, including
6
// without limitation the rights to use, copy, modify, merge, publish,
7
// distribute, sublicense, and/or sell copies of the Software, and to permit
8
// persons to whom the Software is furnished to do so, subject to the
9
// following conditions:
10
//
11
// The above copyright notice and this permission notice shall be included
12
// in all copies or substantial portions of the Software.
13
//
14
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
15
// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN
17
// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
18
// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
19
// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
20
// USE OR OTHER DEALINGS IN THE SOFTWARE.
21
22
#define CARES_STATICLIB
23
#include "ares.h"
24
#include "async_wrap-inl.h"
25
#include "env-inl.h"
26
#include "node.h"
27
#include "node_internals.h"
28
#include "req_wrap-inl.h"
29
#include "util-inl.h"
30
#include "uv.h"
31
32
#include <errno.h>
33
#include <string.h>
34
#include <vector>
35
#include <unordered_set>
36
37
#ifdef __POSIX__
38
# include <netdb.h>
39
#endif  // __POSIX__
40
41
#if defined(__ANDROID__) || \
42
    defined(__MINGW32__) || \
43
    defined(__OpenBSD__) || \
44
    defined(_MSC_VER)
45
46
# include <nameser.h>
47
#else
48
# include <arpa/nameser.h>
49
#endif
50
51
#if defined(__OpenBSD__)
52
# define AI_V4MAPPED 0
53
#endif
54
55
namespace node {
56
namespace cares_wrap {
57
58
using v8::Array;
59
using v8::Context;
60
using v8::EscapableHandleScope;
61
using v8::FunctionCallbackInfo;
62
using v8::FunctionTemplate;
63
using v8::HandleScope;
64
using v8::Int32;
65
using v8::Integer;
66
using v8::Local;
67
using v8::Null;
68
using v8::Object;
69
using v8::String;
70
using v8::Value;
71
72
namespace {
73
74
3597
Mutex ares_library_mutex;
75
76
129
inline uint16_t cares_get_16bit(const unsigned char* p) {
77
129
  return static_cast<uint32_t>(p[0] << 8U) | (static_cast<uint32_t>(p[1]));
78
}
79
80
30
inline uint32_t cares_get_32bit(const unsigned char* p) {
81
60
  return static_cast<uint32_t>(p[0] << 24U) |
82
60
         static_cast<uint32_t>(p[1] << 16U) |
83
60
         static_cast<uint32_t>(p[2] << 8U) |
84
60
         static_cast<uint32_t>(p[3]);
85
}
86
87
const int ns_t_cname_or_a = -1;
88
89
#define DNS_ESETSRVPENDING -1000
90
34
inline const char* ToErrorCodeString(int status) {
91






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

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

102
  if (read || write) {
335
51
    if (!task) {
336
      /* New socket */
337
51
      channel->StartTimer();
338
339
51
      task = ares_task_create(channel, sock);
340
51
      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
102
        return;
345
      }
346
347
51
      channel->task_list()->insert(task);
348
    }
349
350
    /* This should never fail. If it fails anyway, the query will eventually */
351
    /* time out. */
352
    uv_poll_start(&task->poll_watcher,
353
                  (read ? UV_READABLE : 0) | (write ? UV_WRITABLE : 0),
354

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

88
  if (query_last_ok_ || !is_servers_default_) {
556
176
    return;
557
  }
558
559
  ares_addr_port_node* servers = nullptr;
560
561
  ares_get_servers_ports(channel_, &servers);
562
563
  /* if no server or multi-servers, ignore */
564
  if (servers == nullptr) return;
565
  if (servers->next != nullptr) {
566
    ares_free_data(servers);
567
    is_servers_default_ = false;
568
    return;
569
  }
570
571
  /* if the only server is not 127.0.0.1, ignore */
572
  if (servers[0].family != AF_INET ||
573
      servers[0].addr.addr4.s_addr != htonl(INADDR_LOOPBACK) ||
574
      servers[0].tcp_port != 0 ||
575
      servers[0].udp_port != 0) {
576
    ares_free_data(servers);
577
    is_servers_default_ = false;
578
    return;
579
  }
580
581
  ares_free_data(servers);
582
  servers = nullptr;
583
584
  /* destroy channel and reset channel */
585
  ares_destroy(channel_);
586
587
  CloseTimer();
588
  Setup();
589
}
590
591
592
class QueryWrap : public AsyncWrap {
593
 public:
594
100
  QueryWrap(ChannelWrap* channel, Local<Object> req_wrap_obj, const char* name)
595
      : AsyncWrap(channel->env(), req_wrap_obj, AsyncWrap::PROVIDER_QUERYWRAP),
596
        channel_(channel),
597
100
        trace_name_(name) {
598
    // Make sure the channel object stays alive during the query lifetime.
599
    req_wrap_obj->Set(env()->context(),
600
                      env()->channel_string(),
601
500
                      channel->object()).FromJust();
602
100
  }
603
604
200
  ~QueryWrap() override {
605
200
    CHECK_EQ(false, persistent().IsEmpty());
606
100
  }
607
608
  // Subclasses should implement the appropriate Send method.
609
  virtual int Send(const char* name) {
610
    UNREACHABLE();
611
    return 0;
612
  }
613
614
  virtual int Send(const char* name, int family) {
615
    UNREACHABLE();
616
    return 0;
617
  }
618
619
 protected:
620
88
  void AresQuery(const char* name,
621
                 int dnsclass,
622
                 int type) {
623
88
    channel_->EnsureServers();
624

88
    TRACE_EVENT_NESTABLE_ASYNC_BEGIN1(
625
      TRACING_CATEGORY_NODE2(dns, native), trace_name_, this,
626
      "name", TRACE_STR_COPY(name));
627
    ares_query(channel_->cares_channel(), name, dnsclass, type, Callback,
628
88
               static_cast<void*>(this));
629
88
  }
630
631
98
  static void CaresAsyncClose(uv_async_t* async) {
632
98
    auto data = static_cast<struct CaresAsyncData*>(async->data);
633
98
    delete data->wrap;
634
98
    delete data;
635
98
  }
636
637
98
  static void CaresAsyncCb(uv_async_t* handle) {
638
98
    auto data = static_cast<struct CaresAsyncData*>(handle->data);
639
640
98
    QueryWrap* wrap = data->wrap;
641
98
    int status = data->status;
642
643
98
    if (status != ARES_SUCCESS) {
644
32
      wrap->ParseError(status);
645
66
    } else if (!data->is_host) {
646
59
      unsigned char* buf = data->data.buf;
647
59
      wrap->Parse(buf, data->len);
648
59
      free(buf);
649
    } else {
650
7
      hostent* host = data->data.host;
651
7
      wrap->Parse(host);
652
7
      safe_free_hostent(host);
653
7
      free(host);
654
    }
655
656
98
    wrap->env()->CloseHandle(handle, CaresAsyncClose);
657
98
  }
658
659
88
  static void Callback(void* arg, int status, int timeouts,
660
                       unsigned char* answer_buf, int answer_len) {
661
88
    QueryWrap* wrap = static_cast<QueryWrap*>(arg);
662
663
88
    unsigned char* buf_copy = nullptr;
664
88
    if (status == ARES_SUCCESS) {
665
59
      buf_copy = node::Malloc<unsigned char>(answer_len);
666
59
      memcpy(buf_copy, answer_buf, answer_len);
667
    }
668
669
88
    CaresAsyncData* data = new CaresAsyncData();
670
88
    data->status = status;
671
88
    data->wrap = wrap;
672
88
    data->is_host = false;
673
88
    data->data.buf = buf_copy;
674
88
    data->len = answer_len;
675
676
88
    uv_async_t* async_handle = &data->async_handle;
677
88
    CHECK_EQ(0, uv_async_init(wrap->env()->event_loop(),
678
                              async_handle,
679
                              CaresAsyncCb));
680
681
88
    wrap->channel_->set_query_last_ok(status != ARES_ECONNREFUSED);
682
88
    wrap->channel_->ModifyActivityQueryCount(-1);
683
88
    async_handle->data = data;
684
88
    uv_async_send(async_handle);
685
88
  }
686
687
10
  static void Callback(void* arg, int status, int timeouts,
688
                       struct hostent* host) {
689
10
    QueryWrap* wrap = static_cast<QueryWrap*>(arg);
690
691
10
    struct hostent* host_copy = nullptr;
692
10
    if (status == ARES_SUCCESS) {
693
7
      host_copy = node::Malloc<hostent>(1);
694
7
      cares_wrap_hostent_cpy(host_copy, host);
695
    }
696
697
10
    CaresAsyncData* data = new CaresAsyncData();
698
10
    data->status = status;
699
10
    data->data.host = host_copy;
700
10
    data->wrap = wrap;
701
10
    data->is_host = true;
702
703
10
    uv_async_t* async_handle = &data->async_handle;
704
10
    CHECK_EQ(0, uv_async_init(wrap->env()->event_loop(),
705
                              async_handle,
706
                              CaresAsyncCb));
707
708
10
    wrap->channel_->set_query_last_ok(status != ARES_ECONNREFUSED);
709
10
    async_handle->data = data;
710
10
    uv_async_send(async_handle);
711
10
  }
712
713
64
  void CallOnComplete(Local<Value> answer,
714
                      Local<Value> extra = Local<Value>()) {
715
64
    HandleScope handle_scope(env()->isolate());
716
64
    Context::Scope context_scope(env()->context());
717
    Local<Value> argv[] = {
718
      Integer::New(env()->isolate(), 0),
719
      answer,
720
      extra
721
128
    };
722
128
    const int argc = arraysize(argv) - extra.IsEmpty();
723

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

34
    TRACE_EVENT_NESTABLE_ASYNC_END1(
736
        TRACING_CATEGORY_NODE2(dns, native), trace_name_, this,
737
        "error", status);
738
68
    MakeCallback(env()->oncomplete_string(), 1, &arg);
739
34
  }
740
741
  // Subclasses should implement the appropriate Parse method.
742
  virtual void Parse(unsigned char* buf, int len) {
743
    UNREACHABLE();
744
  }
745
746
  virtual void Parse(struct hostent* host) {
747
    UNREACHABLE();
748
  }
749
750
  ChannelWrap* channel_;
751
752
 private:
753
  const char* trace_name_;
754
};
755
756
757
template <typename T>
758
21
Local<Array> AddrTTLToArray(Environment* env,
759
                            const T* addrttls,
760
                            size_t naddrttls) {
761
21
  auto isolate = env->isolate();
762
21
  EscapableHandleScope escapable_handle_scope(isolate);
763
21
  auto context = env->context();
764
765
21
  Local<Array> ttls = Array::New(isolate, naddrttls);
766

54
  for (size_t i = 0; i < naddrttls; i++) {
767
33
    auto value = Integer::New(isolate, addrttls[i].ttl);
768
99
    ttls->Set(context, i, value).FromJust();
769
  }
770
771
21
  return escapable_handle_scope.Escape(ttls);
772
}
773
774
775
75
int ParseGeneralReply(Environment* env,
776
                      const unsigned char* buf,
777
                      int len,
778
                      int* type,
779
                      Local<Array> ret,
780
                      void* addrttls = nullptr,
781
                      int* naddrttls = nullptr) {
782
75
  HandleScope handle_scope(env->isolate());
783
75
  auto context = env->context();
784
  hostent* host;
785
786
  int status;
787

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


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

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

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

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

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

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

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

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

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

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

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






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






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






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






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






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

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

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

4396
  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
8792
  req_wrap->MakeCallback(env->oncomplete_string(), arraysize(argv), argv);
1881
4396
}
1882
1883
1884
11
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
11
      static_cast<GetNameInfoReqWrap*>(req->data)};
1890
11
  Environment* env = req_wrap->env();
1891
1892
22
  HandleScope handle_scope(env->isolate());
1893
11
  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
44
  };
1900
1901
11
  if (status == 0) {
1902
    // Success
1903
7
    Local<String> js_hostname = OneByteString(env->isolate(), hostname);
1904
7
    Local<String> js_service = OneByteString(env->isolate(), service);
1905
7
    argv[1] = js_hostname;
1906
7
    argv[2] = js_service;
1907
  }
1908
1909

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

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


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

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

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

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

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