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: 974 1106 88.1 %
Date: 2019-05-05 22:32:45 Branches: 397 650 61.1 %

Line Branch Exec Source
1
// Copyright Joyent, Inc. and other Node contributors.
2
//
3
// Permission is hereby granted, free of charge, to any person obtaining a
4
// copy of this software and associated documentation files (the
5
// "Software"), to deal in the Software without restriction, including
6
// without limitation the rights to use, copy, modify, merge, publish,
7
// distribute, sublicense, and/or sell copies of the Software, and to permit
8
// persons to whom the Software is furnished to do so, subject to the
9
// following conditions:
10
//
11
// The above copyright notice and this permission notice shall be included
12
// in all copies or substantial portions of the Software.
13
//
14
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
15
// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN
17
// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
18
// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
19
// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
20
// USE OR OTHER DEALINGS IN THE SOFTWARE.
21
22
#define CARES_STATICLIB
23
#include "ares.h"
24
#include "async_wrap-inl.h"
25
#include "env-inl.h"
26
#include "node.h"
27
#include "req_wrap-inl.h"
28
#include "util-inl.h"
29
#include "uv.h"
30
31
#include <cerrno>
32
#include <cstring>
33
#include <memory>
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
4524
Mutex ares_library_mutex;
75
76
149
inline uint16_t cares_get_16bit(const unsigned char* p) {
77
149
  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
35
inline const char* ToErrorCodeString(int status) {
91






35
  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
21
    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
397
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
171
  size_t operator()(node_ares_task* a) const {
137
171
    return std::hash<ares_socket_t>()(a->sock);
138
  }
139
};
140
141
struct TaskEqual {
142
61
  inline bool operator()(node_ares_task* a, node_ares_task* b) const {
143
61
    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() override;
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
119
  inline uv_timer_t* timer_handle() { return timer_handle_; }
165
299
  inline ares_channel cares_channel() { return channel_; }
166
101
  inline void set_query_last_ok(bool ok) { query_last_ok_ = ok; }
167
18
  inline void set_is_servers_default(bool is_default) {
168
18
    is_servers_default_ = is_default;
169
18
  }
170
22
  inline int active_query_count() { return active_query_count_; }
171
423
  inline node_ares_task_list* task_list() { return &task_list_; }
172
173
10
  void MemoryInfo(MemoryTracker* tracker) const override {
174
10
    if (timer_handle_ != nullptr)
175
2
      tracker->TrackField("timer_handle", *timer_handle_);
176
10
    tracker->TrackField("task_list", task_list_, "node_ares_task_list");
177
10
  }
178
179
10
  SET_MEMORY_INFO_NAME(ChannelWrap)
180
10
  SET_SELF_SIZE(ChannelWrap)
181
182
  static void AresTimeout(uv_timer_t* handle);
183
184
 private:
185
  uv_timer_t* timer_handle_;
186
  ares_channel channel_;
187
  bool query_last_ok_;
188
  bool is_servers_default_;
189
  bool library_inited_;
190
  int active_query_count_;
191
  node_ares_task_list task_list_;
192
};
193
194
1018
ChannelWrap::ChannelWrap(Environment* env,
195
                         Local<Object> object)
196
  : AsyncWrap(env, object, PROVIDER_DNSCHANNEL),
197
    timer_handle_(nullptr),
198
    channel_(nullptr),
199
    query_last_ok_(true),
200
    is_servers_default_(true),
201
    library_inited_(false),
202
1018
    active_query_count_(0) {
203
1018
  MakeWeak();
204
205
1018
  Setup();
206
1018
}
207
208
1018
void ChannelWrap::New(const FunctionCallbackInfo<Value>& args) {
209
1018
  CHECK(args.IsConstructCall());
210
1018
  CHECK_EQ(args.Length(), 0);
211
212
1018
  Environment* env = Environment::GetCurrent(args);
213
1018
  new ChannelWrap(env, args.This());
214
1018
}
215
216
10348
class GetAddrInfoReqWrap : public ReqWrap<uv_getaddrinfo_t> {
217
 public:
218
  GetAddrInfoReqWrap(Environment* env,
219
                     Local<Object> req_wrap_obj,
220
                     bool verbatim);
221
222
3
  SET_NO_MEMORY_INFO()
223
3
  SET_MEMORY_INFO_NAME(GetAddrInfoReqWrap)
224
3
  SET_SELF_SIZE(GetAddrInfoReqWrap)
225
226
5174
  bool verbatim() const { return verbatim_; }
227
228
 private:
229
  const bool verbatim_;
230
};
231
232
5176
GetAddrInfoReqWrap::GetAddrInfoReqWrap(Environment* env,
233
                                       Local<Object> req_wrap_obj,
234
                                       bool verbatim)
235
    : ReqWrap(env, req_wrap_obj, AsyncWrap::PROVIDER_GETADDRINFOREQWRAP)
236
5176
    , verbatim_(verbatim) {
237
5176
}
238
239
240
22
class GetNameInfoReqWrap : public ReqWrap<uv_getnameinfo_t> {
241
 public:
242
  GetNameInfoReqWrap(Environment* env, Local<Object> req_wrap_obj);
243
244
1
  SET_NO_MEMORY_INFO()
245
1
  SET_MEMORY_INFO_NAME(GetNameInfoReqWrap)
246
1
  SET_SELF_SIZE(GetNameInfoReqWrap)
247
};
248
249
11
GetNameInfoReqWrap::GetNameInfoReqWrap(Environment* env,
250
                                       Local<Object> req_wrap_obj)
251
11
    : ReqWrap(env, req_wrap_obj, AsyncWrap::PROVIDER_GETNAMEINFOREQWRAP) {
252
11
}
253
254
255
/* This is called once per second by loop->timer. It is used to constantly */
256
/* call back into c-ares for possibly processing timeouts. */
257
26
void ChannelWrap::AresTimeout(uv_timer_t* handle) {
258
26
  ChannelWrap* channel = static_cast<ChannelWrap*>(handle->data);
259
26
  CHECK_EQ(channel->timer_handle(), handle);
260
26
  CHECK_EQ(false, channel->task_list()->empty());
261
26
  ares_process_fd(channel->cares_channel(), ARES_SOCKET_BAD, ARES_SOCKET_BAD);
262
26
}
263
264
265
93
void ares_poll_cb(uv_poll_t* watcher, int status, int events) {
266
93
  node_ares_task* task = ContainerOf(&node_ares_task::poll_watcher, watcher);
267
93
  ChannelWrap* channel = task->channel;
268
269
  /* Reset the idle timer */
270
93
  uv_timer_again(channel->timer_handle());
271
272
93
  if (status < 0) {
273
    /* An error happened. Just pretend that the socket is both readable and */
274
    /* writable. */
275
    ares_process_fd(channel->cares_channel(), task->sock, task->sock);
276
93
    return;
277
  }
278
279
  /* Process DNS responses */
280
  ares_process_fd(channel->cares_channel(),
281
93
                  events & UV_READABLE ? task->sock : ARES_SOCKET_BAD,
282

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

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

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

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

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

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

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

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

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


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

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

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

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

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

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

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

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

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

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

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






208
  ASSIGN_OR_RETURN_UNWRAP(&channel, args.Holder());
1785
1786






104
  CHECK_EQ(false, args.IsConstructCall());
1787






208
  CHECK(args[0]->IsObject());
1788






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






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

30842
        if (want_ipv4 && p->ai_family == AF_INET) {
1833
          addr = reinterpret_cast<char*>(
1834
5237
              &(reinterpret_cast<struct sockaddr_in*>(p->ai_addr)->sin_addr));
1835

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

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

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

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


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

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

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

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

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