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: 971 1110 87.5 %
Date: 2019-02-13 22:28:58 Branches: 392 644 60.9 %

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






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

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

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

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

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

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

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

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

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

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


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

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

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

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

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

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

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

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

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

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

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






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






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






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






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






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

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

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

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

11
  TRACE_EVENT_NESTABLE_ASYNC_END2(
1909
      TRACING_CATEGORY_NODE2(dns, native), "lookupService", req_wrap.get(),
1910
      "hostname", TRACE_STR_COPY(hostname),
1911
      "service", TRACE_STR_COPY(service));
1912
1913
  // Make the callback into JavaScript
1914
22
  req_wrap->MakeCallback(env->oncomplete_string(), arraysize(argv), argv);
1915
11
}
1916
1917
using ParseIPResult =
1918
    decltype(static_cast<ares_addr_port_node*>(nullptr)->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
4911
void GetAddrInfo(const FunctionCallbackInfo<Value>& args) {
1945
4911
  Environment* env = Environment::GetCurrent(args);
1946
1947
9822
  CHECK(args[0]->IsObject());
1948
14733
  CHECK(args[1]->IsString());
1949
9822
  CHECK(args[2]->IsInt32());
1950
9822
  CHECK(args[4]->IsBoolean());
1951
9822
  Local<Object> req_wrap_obj = args[0].As<Object>();
1952
4911
  node::Utf8Value hostname(env->isolate(), args[1]);
1953
1954
4911
  int32_t flags = 0;
1955
9822
  if (args[3]->IsInt32()) {
1956
14733
    flags = args[3].As<Int32>()->Value();
1957
  }
1958
1959
  int family;
1960
1961

14733
  switch (args[2].As<Int32>()->Value()) {
1962
    case 0:
1963
4875
      family = AF_UNSPEC;
1964
4875
      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
14733
                                                       args[4]->IsTrue());
1978
1979
  struct addrinfo hints;
1980
4911
  memset(&hints, 0, sizeof(struct addrinfo));
1981
4911
  hints.ai_family = family;
1982
4911
  hints.ai_socktype = SOCK_STREAM;
1983
4911
  hints.ai_flags = flags;
1984
1985


4911
  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
4911
  int err = req_wrap->Dispatch(uv_getaddrinfo,
1992
                               AfterGetAddrInfo,
1993
                               *hostname,
1994
                               nullptr,
1995
9822
                               &hints);
1996
4911
  if (err == 0)
1997
    // Release ownership of the pointer allowing the ownership to be transferred
1998
4911
    USE(req_wrap.release());
1999
2000
14733
  args.GetReturnValue().Set(err);
2001
4911
}
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
43
  for (uint32_t i = 0; i < len; i++) {
2098
108
    CHECK(arr->Get(env->context(), i).ToLocalChecked()->IsArray());
2099
2100
    Local<Array> elm =
2101
81
        Local<Array>::Cast(arr->Get(env->context(), i).ToLocalChecked());
2102
2103
135
    CHECK(elm->Get(env->context(),
2104
                   0).ToLocalChecked()->Int32Value(env->context()).FromJust());
2105
135
    CHECK(elm->Get(env->context(), 1).ToLocalChecked()->IsString());
2106
135
    CHECK(elm->Get(env->context(),
2107
                   2).ToLocalChecked()->Int32Value(env->context()).FromJust());
2108
2109
54
    int fam = elm->Get(env->context(), 0)
2110
135
        .ToLocalChecked()->Int32Value(env->context()).FromJust();
2111
    node::Utf8Value ip(env->isolate(),
2112
81
                       elm->Get(env->context(), 1).ToLocalChecked());
2113
54
    int port = elm->Get(env->context(), 2)
2114
135
        .ToLocalChecked()->Int32Value(env->context()).FromJust();
2115
2116
27
    ares_addr_port_node* cur = &servers[i];
2117
2118
27
    cur->tcp_port = cur->udp_port = port;
2119
27
    switch (fam) {
2120
      case 4:
2121
21
        cur->family = AF_INET;
2122
21
        err = uv_inet_pton(AF_INET, *ip, &cur->addr);
2123
21
        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
27
    if (err)
2133
      break;
2134
2135
27
    cur->next = nullptr;
2136
2137
27
    if (last != nullptr)
2138
11
      last->next = cur;
2139
2140
27
    last = cur;
2141
27
  }
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
1031
void Initialize(Local<Object> target,
2176
                Local<Value> unused,
2177
                Local<Context> context,
2178
                void* priv) {
2179
1031
  Environment* env = Environment::GetCurrent(context);
2180
2181
1031
  env->SetMethod(target, "getaddrinfo", GetAddrInfo);
2182
1031
  env->SetMethod(target, "getnameinfo", GetNameInfo);
2183
1031
  env->SetMethodNoSideEffect(target, "canonicalizeIP", CanonicalizeIP);
2184
2185
1031
  env->SetMethod(target, "strerror", StrError);
2186
2187
  target->Set(env->context(), FIXED_ONE_BYTE_STRING(env->isolate(), "AF_INET"),
2188
5155
              Integer::New(env->isolate(), AF_INET)).FromJust();
2189
  target->Set(env->context(), FIXED_ONE_BYTE_STRING(env->isolate(), "AF_INET6"),
2190
5155
              Integer::New(env->isolate(), AF_INET6)).FromJust();
2191
  target->Set(env->context(), FIXED_ONE_BYTE_STRING(env->isolate(),
2192
                                                    "AF_UNSPEC"),
2193
5155
              Integer::New(env->isolate(), AF_UNSPEC)).FromJust();
2194
  target->Set(env->context(), FIXED_ONE_BYTE_STRING(env->isolate(),
2195
                                                    "AI_ADDRCONFIG"),
2196
5155
              Integer::New(env->isolate(), AI_ADDRCONFIG)).FromJust();
2197
  target->Set(env->context(), FIXED_ONE_BYTE_STRING(env->isolate(),
2198
                                                    "AI_V4MAPPED"),
2199
5155
              Integer::New(env->isolate(), AI_V4MAPPED)).FromJust();
2200
2201
  Local<FunctionTemplate> aiw =
2202
1031
      BaseObject::MakeLazilyInitializedJSTemplate(env);
2203
2062
  aiw->Inherit(AsyncWrap::GetConstructorTemplate(env));
2204
  Local<String> addrInfoWrapString =
2205
1031
      FIXED_ONE_BYTE_STRING(env->isolate(), "GetAddrInfoReqWrap");
2206
1031
  aiw->SetClassName(addrInfoWrapString);
2207
  target->Set(env->context(),
2208
              addrInfoWrapString,
2209
4124
              aiw->GetFunction(context).ToLocalChecked()).FromJust();
2210
2211
  Local<FunctionTemplate> niw =
2212
1031
      BaseObject::MakeLazilyInitializedJSTemplate(env);
2213
2062
  niw->Inherit(AsyncWrap::GetConstructorTemplate(env));
2214
  Local<String> nameInfoWrapString =
2215
1031
      FIXED_ONE_BYTE_STRING(env->isolate(), "GetNameInfoReqWrap");
2216
1031
  niw->SetClassName(nameInfoWrapString);
2217
  target->Set(env->context(),
2218
              nameInfoWrapString,
2219
4124
              niw->GetFunction(context).ToLocalChecked()).FromJust();
2220
2221
  Local<FunctionTemplate> qrw =
2222
1031
      BaseObject::MakeLazilyInitializedJSTemplate(env);
2223
2062
  qrw->Inherit(AsyncWrap::GetConstructorTemplate(env));
2224
  Local<String> queryWrapString =
2225
1031
      FIXED_ONE_BYTE_STRING(env->isolate(), "QueryReqWrap");
2226
1031
  qrw->SetClassName(queryWrapString);
2227
  target->Set(env->context(),
2228
              queryWrapString,
2229
4124
              qrw->GetFunction(context).ToLocalChecked()).FromJust();
2230
2231
  Local<FunctionTemplate> channel_wrap =
2232
1031
      env->NewFunctionTemplate(ChannelWrap::New);
2233
2062
  channel_wrap->InstanceTemplate()->SetInternalFieldCount(1);
2234
2062
  channel_wrap->Inherit(AsyncWrap::GetConstructorTemplate(env));
2235
2236
1031
  env->SetProtoMethod(channel_wrap, "queryAny", Query<QueryAnyWrap>);
2237
1031
  env->SetProtoMethod(channel_wrap, "queryA", Query<QueryAWrap>);
2238
1031
  env->SetProtoMethod(channel_wrap, "queryAaaa", Query<QueryAaaaWrap>);
2239
1031
  env->SetProtoMethod(channel_wrap, "queryCname", Query<QueryCnameWrap>);
2240
1031
  env->SetProtoMethod(channel_wrap, "queryMx", Query<QueryMxWrap>);
2241
1031
  env->SetProtoMethod(channel_wrap, "queryNs", Query<QueryNsWrap>);
2242
1031
  env->SetProtoMethod(channel_wrap, "queryTxt", Query<QueryTxtWrap>);
2243
1031
  env->SetProtoMethod(channel_wrap, "querySrv", Query<QuerySrvWrap>);
2244
1031
  env->SetProtoMethod(channel_wrap, "queryPtr", Query<QueryPtrWrap>);
2245
1031
  env->SetProtoMethod(channel_wrap, "queryNaptr", Query<QueryNaptrWrap>);
2246
1031
  env->SetProtoMethod(channel_wrap, "querySoa", Query<QuerySoaWrap>);
2247
1031
  env->SetProtoMethod(channel_wrap, "getHostByAddr", Query<GetHostByAddrWrap>);
2248
2249
1031
  env->SetProtoMethodNoSideEffect(channel_wrap, "getServers", GetServers);
2250
1031
  env->SetProtoMethod(channel_wrap, "setServers", SetServers);
2251
1031
  env->SetProtoMethod(channel_wrap, "cancel", Cancel);
2252
2253
  Local<String> channelWrapString =
2254
1031
      FIXED_ONE_BYTE_STRING(env->isolate(), "ChannelWrap");
2255
1031
  channel_wrap->SetClassName(channelWrapString);
2256
  target->Set(env->context(), channelWrapString,
2257
4124
              channel_wrap->GetFunction(context).ToLocalChecked()).FromJust();
2258
1031
}
2259
2260
}  // anonymous namespace
2261
}  // namespace cares_wrap
2262
}  // namespace node
2263
2264

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