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: 969 1108 87.5 %
Date: 2019-03-02 22:23:06 Branches: 398 650 61.2 %

Line Branch Exec Source
1
// Copyright Joyent, Inc. and other Node contributors.
2
//
3
// Permission is hereby granted, free of charge, to any person obtaining a
4
// copy of this software and associated documentation files (the
5
// "Software"), to deal in the Software without restriction, including
6
// without limitation the rights to use, copy, modify, merge, publish,
7
// distribute, sublicense, and/or sell copies of the Software, and to permit
8
// persons to whom the Software is furnished to do so, subject to the
9
// following conditions:
10
//
11
// The above copyright notice and this permission notice shall be included
12
// in all copies or substantial portions of the Software.
13
//
14
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
15
// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN
17
// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
18
// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
19
// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
20
// USE OR OTHER DEALINGS IN THE SOFTWARE.
21
22
#define CARES_STATICLIB
23
#include "ares.h"
24
#include "async_wrap-inl.h"
25
#include "env-inl.h"
26
#include "node.h"
27
#include "req_wrap-inl.h"
28
#include "util-inl.h"
29
#include "uv.h"
30
31
#include <cerrno>
32
#include <cstring>
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
4292
Mutex ares_library_mutex;
74
75
141
inline uint16_t cares_get_16bit(const unsigned char* p) {
76
141
  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
411
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
177
  size_t operator()(node_ares_task* a) const {
136
177
    return std::hash<ares_socket_t>()(a->sock);
137
  }
138
};
139
140
struct TaskEqual {
141
63
  inline bool operator()(node_ares_task* a, node_ares_task* b) const {
142
63
    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() override;
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
101
  inline uv_timer_t* timer_handle() { return timer_handle_; }
164
279
  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
17
  inline void set_is_servers_default(bool is_default) {
169
17
    is_servers_default_ = is_default;
170
17
  }
171
21
  inline int active_query_count() { return active_query_count_; }
172
422
  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
988
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
988
    active_query_count_(0) {
204
988
  MakeWeak();
205
206
988
  Setup();
207
988
}
208
209
988
void ChannelWrap::New(const FunctionCallbackInfo<Value>& args) {
210
988
  CHECK(args.IsConstructCall());
211
988
  CHECK_EQ(args.Length(), 0);
212
213
988
  Environment* env = Environment::GetCurrent(args);
214
988
  new ChannelWrap(env, args.This());
215
988
}
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
4912
GetAddrInfoReqWrap::GetAddrInfoReqWrap(Environment* env,
234
                                       Local<Object> req_wrap_obj,
235
                                       bool verbatim)
236
    : ReqWrap(env, req_wrap_obj, AsyncWrap::PROVIDER_GETADDRINFOREQWRAP)
237
4912
    , verbatim_(verbatim) {
238
4912
}
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
11
void ChannelWrap::AresTimeout(uv_timer_t* handle) {
259
11
  ChannelWrap* channel = static_cast<ChannelWrap*>(handle->data);
260
11
  CHECK_EQ(channel->timer_handle(), handle);
261
11
  CHECK_EQ(false, channel->task_list()->empty());
262
11
  ares_process_fd(channel->cares_channel(), ARES_SOCKET_BAD, ARES_SOCKET_BAD);
263
11
}
264
265
266
90
void ares_poll_cb(uv_poll_t* watcher, int status, int events) {
267
90
  node_ares_task* task = ContainerOf(&node_ares_task::poll_watcher, watcher);
268
90
  ChannelWrap* channel = task->channel;
269
270
  /* Reset the idle timer */
271
90
  uv_timer_again(channel->timer_handle());
272
273
90
  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
90
    return;
278
  }
279
280
  /* Process DNS responses */
281
  ares_process_fd(channel->cares_channel(),
282
90
                  events & UV_READABLE ? task->sock : ARES_SOCKET_BAD,
283

180
                  events & UV_WRITABLE ? task->sock : ARES_SOCKET_BAD);
284
}
285
286
287
57
void ares_poll_close_cb(uv_poll_t* watcher) {
288
57
  node_ares_task* task = ContainerOf(&node_ares_task::poll_watcher, watcher);
289
57
  delete task;
290
57
}
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
57
node_ares_task* ares_task_create(ChannelWrap* channel, ares_socket_t sock) {
298
57
  auto task = new node_ares_task();
299
300
57
  if (task == nullptr) {
301
    /* Out of memory. */
302
    return nullptr;
303
  }
304
305
57
  task->channel = channel;
306
57
  task->sock = sock;
307
308
57
  if (uv_poll_init_socket(channel->env()->event_loop(),
309
57
                          &task->poll_watcher, sock) < 0) {
310
    /* This should never happen. */
311
    free(task);
312
    return nullptr;
313
  }
314
315
57
  return task;
316
}
317
318
319
/* Callback from ares when socket operation is started */
320
120
void ares_sockstate_cb(void* data,
321
                       ares_socket_t sock,
322
                       int read,
323
                       int write) {
324
120
  ChannelWrap* channel = static_cast<ChannelWrap*>(data);
325
  node_ares_task* task;
326
327
120
  node_ares_task lookup_task;
328
120
  lookup_task.sock = sock;
329
120
  auto it = channel->task_list()->find(&lookup_task);
330
331
120
  task = (it == channel->task_list()->end()) ? nullptr : *it;
332
333

120
  if (read || write) {
334
63
    if (!task) {
335
      /* New socket */
336
57
      channel->StartTimer();
337
338
57
      task = ares_task_create(channel, sock);
339
57
      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
120
        return;
344
      }
345
346
57
      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

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

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

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

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

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

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

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


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

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

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

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

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

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

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

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

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

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

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






208
  ASSIGN_OR_RETURN_UNWRAP(&channel, args.Holder());
1791
1792






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






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






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






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

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

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

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

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

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


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

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

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

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

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