GCC Code Coverage Report
Directory: ../ Exec Total Coverage
File: /home/iojs/build/workspace/node-test-commit-linux-coverage/nodes/benchmark/out/../src/cares_wrap.cc Lines: 795 1109 71.7 %
Date: 2017-11-19 Branches: 242 611 39.6 %

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






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

12
                  events & UV_WRITABLE ? task->sock : ARES_SOCKET_BAD);
271
}
272
273
274
9
void ares_poll_close_cb(uv_handle_t* watcher) {
275
  node_ares_task* task = ContainerOf(&node_ares_task::poll_watcher,
276
9
                                  reinterpret_cast<uv_poll_t*>(watcher));
277
9
  free(task);
278
9
}
279
280
281
/* Allocates and returns a new node_ares_task */
282
9
node_ares_task* ares_task_create(ChannelWrap* channel, ares_socket_t sock) {
283
9
  auto task = node::UncheckedMalloc<node_ares_task>(1);
284
285
9
  if (task == nullptr) {
286
    /* Out of memory. */
287
    return nullptr;
288
  }
289
290
9
  task->channel = channel;
291
9
  task->sock = sock;
292
293
9
  if (uv_poll_init_socket(channel->env()->event_loop(),
294
9
                          &task->poll_watcher, sock) < 0) {
295
    /* This should never happen. */
296
    free(task);
297
    return nullptr;
298
  }
299
300
9
  return task;
301
}
302
303
304
/* Callback from ares when socket operation is started */
305
18
void ares_sockstate_cb(void* data,
306
                       ares_socket_t sock,
307
                       int read,
308
                       int write) {
309
18
  ChannelWrap* channel = static_cast<ChannelWrap*>(data);
310
  node_ares_task* task;
311
312
  node_ares_task lookup_task;
313
18
  lookup_task.sock = sock;
314
18
  auto it = channel->task_list()->find(&lookup_task);
315
316
18
  task = (it == channel->task_list()->end()) ? nullptr : *it;
317
318

18
  if (read || write) {
319
9
    if (!task) {
320
      /* New socket */
321
322
      /* If this is the first socket then start the timer. */
323
9
      uv_timer_t* timer_handle = channel->timer_handle();
324
9
      if (!uv_is_active(reinterpret_cast<uv_handle_t*>(timer_handle))) {
325
9
        CHECK(channel->task_list()->empty());
326
9
        uv_timer_start(timer_handle, ChannelWrap::AresTimeout, 1000, 1000);
327
      }
328
329
9
      task = ares_task_create(channel, sock);
330
9
      if (task == nullptr) {
331
        /* This should never happen unless we're out of memory or something */
332
        /* is seriously wrong. The socket won't be polled, but the query will */
333
        /* eventually time out. */
334
        return;
335
      }
336
337
9
      channel->task_list()->insert(task);
338
    }
339
340
    /* This should never fail. If it fails anyway, the query will eventually */
341
    /* time out. */
342
    uv_poll_start(&task->poll_watcher,
343
                  (read ? UV_READABLE : 0) | (write ? UV_WRITABLE : 0),
344

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

8
  if (query_last_ok_ || !is_servers_default_) {
559
16
    return;
560
  }
561
562
  ares_addr_port_node* servers = nullptr;
563
564
  ares_get_servers_ports(channel_, &servers);
565
566
  /* if no server or multi-servers, ignore */
567
  if (servers == nullptr) return;
568
  if (servers->next != nullptr) {
569
    ares_free_data(servers);
570
    is_servers_default_ = false;
571
    return;
572
  }
573
574
  /* if the only server is not 127.0.0.1, ignore */
575
  if (servers[0].family != AF_INET ||
576
      servers[0].addr.addr4.s_addr != htonl(INADDR_LOOPBACK) ||
577
      servers[0].tcp_port != 0 ||
578
      servers[0].udp_port != 0) {
579
    ares_free_data(servers);
580
    is_servers_default_ = false;
581
    return;
582
  }
583
584
  ares_free_data(servers);
585
  servers = nullptr;
586
587
  /* destroy channel and reset channel */
588
  ares_destroy(channel_);
589
590
  Setup();
591
}
592
593
594
class QueryWrap : public AsyncWrap {
595
 public:
596
10
  QueryWrap(ChannelWrap* channel, Local<Object> req_wrap_obj)
597
      : AsyncWrap(channel->env(), req_wrap_obj, AsyncWrap::PROVIDER_QUERYWRAP),
598
10
        channel_(channel) {
599
10
    Wrap(req_wrap_obj, this);
600
601
    // Make sure the channel object stays alive during the query lifetime.
602
    req_wrap_obj->Set(env()->context(),
603
                      env()->channel_string(),
604
50
                      channel->object()).FromJust();
605
10
  }
606
607
20
  ~QueryWrap() override {
608
20
    CHECK_EQ(false, persistent().IsEmpty());
609
10
    ClearWrap(object());
610
10
    persistent().Reset();
611
10
  }
612
613
  // Subclasses should implement the appropriate Send method.
614
  virtual int Send(const char* name) {
615
    UNREACHABLE();
616
    return 0;
617
  }
618
619
  virtual int Send(const char* name, int family) {
620
    UNREACHABLE();
621
    return 0;
622
  }
623
624
 protected:
625
8
  void AresQuery(const char* name,
626
                 int dnsclass,
627
                 int type) {
628
8
    channel_->EnsureServers();
629
    ares_query(channel_->cares_channel(), name, dnsclass, type, Callback,
630
8
               static_cast<void*>(this));
631
8
  }
632
633
10
  static void CaresAsyncClose(uv_handle_t* handle) {
634
10
    uv_async_t* async = reinterpret_cast<uv_async_t*>(handle);
635
10
    auto data = static_cast<struct CaresAsyncData*>(async->data);
636
10
    delete data->wrap;
637
10
    delete data;
638
10
  }
639
640
10
  static void CaresAsyncCb(uv_async_t* handle) {
641
10
    auto data = static_cast<struct CaresAsyncData*>(handle->data);
642
643
10
    QueryWrap* wrap = data->wrap;
644
10
    int status = data->status;
645
646
10
    if (status != ARES_SUCCESS) {
647
5
      wrap->ParseError(status);
648
5
    } else if (!data->is_host) {
649
4
      unsigned char* buf = data->data.buf;
650
4
      wrap->Parse(buf, data->len);
651
4
      free(buf);
652
    } else {
653
1
      hostent* host = data->data.host;
654
1
      wrap->Parse(host);
655
1
      safe_free_hostent(host);
656
1
      free(host);
657
    }
658
659
10
    uv_close(reinterpret_cast<uv_handle_t*>(handle), CaresAsyncClose);
660
10
  }
661
662
8
  static void Callback(void *arg, int status, int timeouts,
663
                       unsigned char* answer_buf, int answer_len) {
664
8
    QueryWrap* wrap = static_cast<QueryWrap*>(arg);
665
666
8
    unsigned char* buf_copy = nullptr;
667
8
    if (status == ARES_SUCCESS) {
668
4
      buf_copy = node::Malloc<unsigned char>(answer_len);
669
4
      memcpy(buf_copy, answer_buf, answer_len);
670
    }
671
672
8
    CaresAsyncData* data = new CaresAsyncData();
673
8
    data->status = status;
674
8
    data->wrap = wrap;
675
8
    data->is_host = false;
676
8
    data->data.buf = buf_copy;
677
8
    data->len = answer_len;
678
679
8
    uv_async_t* async_handle = &data->async_handle;
680
8
    CHECK_EQ(0, uv_async_init(wrap->env()->event_loop(),
681
                              async_handle,
682
                              CaresAsyncCb));
683
684
8
    wrap->channel_->set_query_last_ok(status != ARES_ECONNREFUSED);
685
8
    async_handle->data = data;
686
8
    uv_async_send(async_handle);
687
8
  }
688
689
2
  static void Callback(void *arg, int status, int timeouts,
690
                       struct hostent* host) {
691
2
    QueryWrap* wrap = static_cast<QueryWrap*>(arg);
692
693
2
    struct hostent* host_copy = nullptr;
694
2
    if (status == ARES_SUCCESS) {
695
1
      host_copy = node::Malloc<hostent>(1);
696
1
      cares_wrap_hostent_cpy(host_copy, host);
697
    }
698
699
2
    CaresAsyncData* data = new CaresAsyncData();
700
2
    data->status = status;
701
2
    data->data.host = host_copy;
702
2
    data->wrap = wrap;
703
2
    data->is_host = true;
704
705
2
    uv_async_t* async_handle = &data->async_handle;
706
2
    CHECK_EQ(0, uv_async_init(wrap->env()->event_loop(),
707
                              async_handle,
708
                              CaresAsyncCb));
709
710
2
    wrap->channel_->set_query_last_ok(status != ARES_ECONNREFUSED);
711
2
    async_handle->data = data;
712
2
    uv_async_send(async_handle);
713
2
  }
714
715
4
  void CallOnComplete(Local<Value> answer,
716
                      Local<Value> extra = Local<Value>()) {
717
4
    HandleScope handle_scope(env()->isolate());
718
4
    Context::Scope context_scope(env()->context());
719
    Local<Value> argv[] = {
720
      Integer::New(env()->isolate(), 0),
721
      answer,
722
      extra
723
8
    };
724
8
    const int argc = arraysize(argv) - extra.IsEmpty();
725
8
    MakeCallback(env()->oncomplete_string(), argc, argv);
726
4
  }
727
728
6
  void ParseError(int status) {
729
6
    CHECK_NE(status, ARES_SUCCESS);
730
6
    HandleScope handle_scope(env()->isolate());
731
6
    Context::Scope context_scope(env()->context());
732
6
    const char* code = ToErrorCodeString(status);
733
6
    Local<Value> arg = OneByteString(env()->isolate(), code);
734
12
    MakeCallback(env()->oncomplete_string(), 1, &arg);
735
6
  }
736
737
  // Subclasses should implement the appropriate Parse method.
738
  virtual void Parse(unsigned char* buf, int len) {
739
    UNREACHABLE();
740
  }
741
742
  virtual void Parse(struct hostent* host) {
743
    UNREACHABLE();
744
  }
745
746
  ChannelWrap* channel_;
747
};
748
749
750
template<typename T>
751
2
Local<Array> AddrTTLToArray(Environment* env,
752
                            const T* addrttls,
753
                            size_t naddrttls) {
754
2
  auto isolate = env->isolate();
755
2
  EscapableHandleScope escapable_handle_scope(isolate);
756
2
  auto context = env->context();
757
758
2
  Local<Array> ttls = Array::New(isolate, naddrttls);
759

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

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


12
  if ((*type == ns_t_cname_or_a && host->h_name && host->h_aliases[0]) ||
815
6
      *type == ns_t_cname) {
816
    // A cname lookup always returns a single record but we follow the
817
    // common API here.
818
    *type = ns_t_cname;
819
    ret->Set(context,
820
             ret->Length(),
821
             OneByteString(env->isolate(), host->h_name)).FromJust();
822
    ares_free_hostent(host);
823
    return ARES_SUCCESS;
824
  }
825
826
6
  if (*type == ns_t_cname_or_a)
827
1
    *type = ns_t_a;
828
829
6
  if (*type == ns_t_ns) {
830
1
    HostentToNames(env, host, ret);
831
5
  } else if (*type == ns_t_ptr) {
832
1
    uint32_t offset = ret->Length();
833
2
    for (uint32_t i = 0; host->h_aliases[i] != NULL; i++) {
834
1
      ret->Set(context,
835
               i + offset,
836
4
               OneByteString(env->isolate(), host->h_aliases[i])).FromJust();
837
    }
838
  } else {
839
4
    HostentToAddresses(env, host, ret);
840
  }
841
842
6
  ares_free_hostent(host);
843
844
6
  return ARES_SUCCESS;
845
}
846
847
848
1
int ParseMxReply(Environment* env,
849
                 const unsigned char* buf,
850
                 int len,
851
                 Local<Array> ret,
852
                 bool need_type = false) {
853
1
  HandleScope handle_scope(env->isolate());
854
1
  auto context = env->context();
855
856
  struct ares_mx_reply* mx_start;
857
1
  int status = ares_parse_mx_reply(buf, len, &mx_start);
858
1
  if (status != ARES_SUCCESS) {
859
    return status;
860
  }
861
862
1
  Local<String> exchange_symbol = env->exchange_string();
863
1
  Local<String> priority_symbol = env->priority_string();
864
1
  Local<String> type_symbol = env->type_string();
865
1
  Local<String> mx_symbol = env->dns_mx_string();
866
867
1
  uint32_t offset = ret->Length();
868
1
  ares_mx_reply* current = mx_start;
869
2
  for (uint32_t i = 0; current != nullptr; ++i, current = current->next) {
870
1
    Local<Object> mx_record = Object::New(env->isolate());
871
    mx_record->Set(context,
872
                   exchange_symbol,
873
3
                   OneByteString(env->isolate(), current->host)).FromJust();
874
    mx_record->Set(context,
875
                   priority_symbol,
876
3
                   Integer::New(env->isolate(), current->priority)).FromJust();
877
1
    if (need_type)
878
2
      mx_record->Set(context, type_symbol, mx_symbol).FromJust();
879
880
3
    ret->Set(context, i + offset, mx_record).FromJust();
881
  }
882
883
1
  ares_free_data(mx_start);
884
1
  return ARES_SUCCESS;
885
}
886
887
1
int ParseTxtReply(Environment* env,
888
                  const unsigned char* buf,
889
                  int len,
890
                  Local<Array> ret,
891
                  bool need_type = false) {
892
1
  HandleScope handle_scope(env->isolate());
893
1
  auto context = env->context();
894
895
  struct ares_txt_ext* txt_out;
896
897
1
  int status = ares_parse_txt_reply_ext(buf, len, &txt_out);
898
1
  if (status != ARES_SUCCESS) {
899
    return status;
900
  }
901
902
  Local<Array> txt_chunk;
903
904
1
  struct ares_txt_ext* current = txt_out;
905
1
  uint32_t i = 0, j;
906
1
  uint32_t offset = ret->Length();
907
3
  for (j = 0; current != nullptr; current = current->next) {
908
2
    Local<String> txt = OneByteString(env->isolate(), current->txt);
909
910
    // New record found - write out the current chunk
911
2
    if (current->record_start) {
912
1
      if (!txt_chunk.IsEmpty()) {
913
        if (need_type) {
914
          Local<Object> elem = Object::New(env->isolate());
915
          elem->Set(context, env->entries_string(), txt_chunk).FromJust();
916
          elem->Set(context,
917
                    env->type_string(),
918
                    env->dns_txt_string()).FromJust();
919
          ret->Set(context, offset + i++, elem).FromJust();
920
        } else {
921
          ret->Set(context, offset + i++, txt_chunk).FromJust();
922
        }
923
      }
924
925
1
      txt_chunk = Array::New(env->isolate());
926
1
      j = 0;
927
    }
928
929
6
    txt_chunk->Set(context, j++, txt).FromJust();
930
  }
931
932
  // Push last chunk if it isn't empty
933
1
  if (!txt_chunk.IsEmpty()) {
934
1
    if (need_type) {
935
1
      Local<Object> elem = Object::New(env->isolate());
936
3
      elem->Set(context, env->entries_string(), txt_chunk).FromJust();
937
      elem->Set(context,
938
                env->type_string(),
939
4
                env->dns_txt_string()).FromJust();
940
3
      ret->Set(context, offset + i, elem).FromJust();
941
    } else {
942
      ret->Set(context, offset + i, txt_chunk).FromJust();
943
    }
944
  }
945
946
1
  ares_free_data(txt_out);
947
1
  return ARES_SUCCESS;
948
}
949
950
951
1
int ParseSrvReply(Environment* env,
952
                  const unsigned char* buf,
953
                  int len,
954
                  Local<Array> ret,
955
                  bool need_type = false) {
956
1
  HandleScope handle_scope(env->isolate());
957
1
  auto context = env->context();
958
959
  struct ares_srv_reply* srv_start;
960
1
  int status = ares_parse_srv_reply(buf, len, &srv_start);
961
1
  if (status != ARES_SUCCESS) {
962
    return status;
963
  }
964
965
1
  Local<String> name_symbol = env->name_string();
966
1
  Local<String> port_symbol = env->port_string();
967
1
  Local<String> priority_symbol = env->priority_string();
968
1
  Local<String> weight_symbol = env->weight_string();
969
1
  Local<String> type_symbol = env->type_string();
970
1
  Local<String> srv_symbol = env->dns_srv_string();
971
972
1
  ares_srv_reply* current = srv_start;
973
1
  int offset = ret->Length();
974
1
  for (uint32_t i = 0; current != nullptr; ++i, current = current->next) {
975
    Local<Object> srv_record = Object::New(env->isolate());
976
    srv_record->Set(context,
977
                    name_symbol,
978
                    OneByteString(env->isolate(), current->host)).FromJust();
979
    srv_record->Set(context,
980
                    port_symbol,
981
                    Integer::New(env->isolate(), current->port)).FromJust();
982
    srv_record->Set(context,
983
                    priority_symbol,
984
                    Integer::New(env->isolate(), current->priority)).FromJust();
985
    srv_record->Set(context,
986
                    weight_symbol,
987
                    Integer::New(env->isolate(), current->weight)).FromJust();
988
    if (need_type)
989
      srv_record->Set(context, type_symbol, srv_symbol).FromJust();
990
991
    ret->Set(context, i + offset, srv_record).FromJust();
992
  }
993
994
1
  ares_free_data(srv_start);
995
1
  return ARES_SUCCESS;
996
}
997
998
999
1
int ParseNaptrReply(Environment* env,
1000
                    const unsigned char* buf,
1001
                    int len,
1002
                    Local<Array> ret,
1003
                    bool need_type = false) {
1004
1
  HandleScope handle_scope(env->isolate());
1005
1
  auto context = env->context();
1006
1007
  ares_naptr_reply* naptr_start;
1008
1
  int status = ares_parse_naptr_reply(buf, len, &naptr_start);
1009
1010
1
  if (status != ARES_SUCCESS) {
1011
    return status;
1012
  }
1013
1014
1
  Local<String> flags_symbol = env->flags_string();
1015
1
  Local<String> service_symbol = env->service_string();
1016
1
  Local<String> regexp_symbol = env->regexp_string();
1017
1
  Local<String> replacement_symbol = env->replacement_string();
1018
1
  Local<String> order_symbol = env->order_string();
1019
1
  Local<String> preference_symbol = env->preference_string();
1020
1
  Local<String> type_symbol = env->type_string();
1021
1
  Local<String> naptr_symbol = env->dns_naptr_string();
1022
1023
1
  ares_naptr_reply* current = naptr_start;
1024
1
  int offset = ret->Length();
1025
1
  for (uint32_t i = 0; current != nullptr; ++i, current = current->next) {
1026
    Local<Object> naptr_record = Object::New(env->isolate());
1027
    naptr_record->Set(context,
1028
                      flags_symbol,
1029
                      OneByteString(env->isolate(), current->flags)).FromJust();
1030
    naptr_record->Set(context,
1031
                      service_symbol,
1032
                      OneByteString(env->isolate(),
1033
                                    current->service)).FromJust();
1034
    naptr_record->Set(context,
1035
                      regexp_symbol,
1036
                      OneByteString(env->isolate(),
1037
                                    current->regexp)).FromJust();
1038
    naptr_record->Set(context,
1039
                      replacement_symbol,
1040
                      OneByteString(env->isolate(),
1041
                                    current->replacement)).FromJust();
1042
    naptr_record->Set(context,
1043
                      order_symbol,
1044
                      Integer::New(env->isolate(), current->order)).FromJust();
1045
    naptr_record->Set(context,
1046
                      preference_symbol,
1047
                      Integer::New(env->isolate(),
1048
                                   current->preference)).FromJust();
1049
    if (need_type)
1050
      naptr_record->Set(context, type_symbol, naptr_symbol).FromJust();
1051
1052
    ret->Set(context, i + offset, naptr_record).FromJust();
1053
  }
1054
1055
1
  ares_free_data(naptr_start);
1056
1
  return ARES_SUCCESS;
1057
}
1058
1059
1060
1
int ParseSoaReply(Environment* env,
1061
                  unsigned char* buf,
1062
                  int len,
1063
                  Local<Object>* ret) {
1064
1
  EscapableHandleScope handle_scope(env->isolate());
1065
1
  auto context = env->context();
1066
1067
  /* Can't use ares_parse_soa_reply() here which can only parse single record */
1068
1
  unsigned int ancount = cares_get_16bit(buf + 6);
1069
1
  unsigned char* ptr = buf + NS_HFIXEDSZ;
1070
  int rr_type, rr_len;
1071
  char* name;
1072
  char* rr_name;
1073
  long temp_len;  // NOLINT(runtime/int)
1074
1
  int status = ares_expand_name(ptr, buf, len, &name, &temp_len);
1075
1
  if (status != ARES_SUCCESS) {
1076
    /* returns EBADRESP in case of invalid input */
1077
    return status == ARES_EBADNAME ? ARES_EBADRESP : status;
1078
  }
1079
1080
1
  if (ptr + temp_len + NS_QFIXEDSZ > buf + len) {
1081
    free(name);
1082
    return ARES_EBADRESP;
1083
  }
1084
1
  ptr += temp_len + NS_QFIXEDSZ;
1085
1086
7
  for (unsigned int i = 0; i < ancount; i++) {
1087
7
    status = ares_expand_name(ptr, buf, len, &rr_name, &temp_len);
1088
1089
7
    if (status != ARES_SUCCESS)
1090
      break;
1091
1092
7
    ptr += temp_len;
1093
7
    if (ptr + NS_RRFIXEDSZ > buf + len) {
1094
      free(rr_name);
1095
      status = ARES_EBADRESP;
1096
      break;
1097
    }
1098
1099
7
    rr_type = cares_get_16bit(ptr);
1100
7
    rr_len = cares_get_16bit(ptr + 8);
1101
7
    ptr += NS_RRFIXEDSZ;
1102
1103
    /* only need SOA */
1104
7
    if (rr_type == ns_t_soa) {
1105
      ares_soa_reply soa;
1106
1107
1
      status = ares_expand_name(ptr, buf, len, &soa.nsname, &temp_len);
1108
1
      if (status != ARES_SUCCESS) {
1109
        free(rr_name);
1110
        break;
1111
      }
1112
1
      ptr += temp_len;
1113
1114
1
      status = ares_expand_name(ptr, buf, len, &soa.hostmaster, &temp_len);
1115
1
      if (status != ARES_SUCCESS) {
1116
        free(rr_name);
1117
        free(soa.nsname);
1118
        break;
1119
      }
1120
1
      ptr += temp_len;
1121
1122
1
      if (ptr + 5 * 4 > buf + len) {
1123
        free(rr_name);
1124
        free(soa.nsname);
1125
        free(soa.hostmaster);
1126
        status = ARES_EBADRESP;
1127
        break;
1128
      }
1129
1130
1
      soa.serial = cares_get_32bit(ptr + 0 * 4);
1131
1
      soa.refresh = cares_get_32bit(ptr + 1 * 4);
1132
1
      soa.retry = cares_get_32bit(ptr + 2 * 4);
1133
1
      soa.expire = cares_get_32bit(ptr + 3 * 4);
1134
1
      soa.minttl = cares_get_32bit(ptr + 4 * 4);
1135
1136
1
      Local<Object> soa_record = Object::New(env->isolate());
1137
      soa_record->Set(context,
1138
                      env->nsname_string(),
1139
4
                      OneByteString(env->isolate(), soa.nsname)).FromJust();
1140
      soa_record->Set(context,
1141
                      env->hostmaster_string(),
1142
                      OneByteString(env->isolate(),
1143
4
                                    soa.hostmaster)).FromJust();
1144
      soa_record->Set(context,
1145
                      env->serial_string(),
1146
4
                      Integer::New(env->isolate(), soa.serial)).FromJust();
1147
      soa_record->Set(context,
1148
                      env->refresh_string(),
1149
4
                      Integer::New(env->isolate(), soa.refresh)).FromJust();
1150
      soa_record->Set(context,
1151
                      env->retry_string(),
1152
4
                      Integer::New(env->isolate(), soa.retry)).FromJust();
1153
      soa_record->Set(context,
1154
                      env->expire_string(),
1155
4
                      Integer::New(env->isolate(), soa.expire)).FromJust();
1156
      soa_record->Set(context,
1157
                      env->minttl_string(),
1158
4
                      Integer::New(env->isolate(), soa.minttl)).FromJust();
1159
      soa_record->Set(context,
1160
                      env->type_string(),
1161
4
                      env->dns_soa_string()).FromJust();
1162
1163
1
      free(soa.nsname);
1164
1
      free(soa.hostmaster);
1165
1166
1
      *ret = handle_scope.Escape(soa_record);
1167
1
      break;
1168
    }
1169
1170
6
    free(rr_name);
1171
6
    ptr += rr_len;
1172
  }
1173
1174
1
  free(name);
1175
1176
1
  if (status != ARES_SUCCESS) {
1177
    return status == ARES_EBADNAME ? ARES_EBADRESP : status;
1178
  }
1179
1180
1
  return ARES_SUCCESS;
1181
}
1182
1183
1184
4
class QueryAnyWrap: public QueryWrap {
1185
 public:
1186
2
  QueryAnyWrap(ChannelWrap* channel, Local<Object> req_wrap_obj)
1187
2
    : QueryWrap(channel, req_wrap_obj) {
1188
2
  }
1189
1190
2
  int Send(const char* name) override {
1191
2
    AresQuery(name, ns_c_in, ns_t_any);
1192
2
    return 0;
1193
  }
1194
1195
  size_t self_size() const override { return sizeof(*this); }
1196
1197
 protected:
1198
2
  void Parse(unsigned char* buf, int len) override {
1199
2
    HandleScope handle_scope(env()->isolate());
1200
2
    auto context = env()->context();
1201
1
    Context::Scope context_scope(context);
1202
1203
2
    Local<Array> ret = Array::New(env()->isolate());
1204
    int type, status, old_count;
1205
1206
    /* Parse A records or CNAME records */
1207
    ares_addrttl addrttls[256];
1208
2
    int naddrttls = arraysize(addrttls);
1209
1210
2
    type = ns_t_cname_or_a;
1211
    status = ParseGeneralReply(env(),
1212
                               buf,
1213
                               len,
1214
                               &type,
1215
                               ret,
1216
                               addrttls,
1217
2
                               &naddrttls);
1218
2
    int a_count = ret->Length();
1219

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

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

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

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

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

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

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

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






20
  ASSIGN_OR_RETURN_UNWRAP(&channel, args.Holder());
1795
1796






10
  CHECK_EQ(false, args.IsConstructCall());
1797






20
  CHECK(args[0]->IsObject());
1798






30
  CHECK(args[1]->IsString());
1799
1800
20
  Local<Object> req_wrap_obj = args[0].As<Object>();
1801
20
  Local<String> string = args[1].As<String>();
1802
10
  Wrap* wrap = new Wrap(channel, req_wrap_obj);
1803
1804
10
  node::Utf8Value name(env->isolate(), string);
1805
10
  int err = wrap->Send(*name);
1806






10
  if (err)
1807
    delete wrap;
1808
1809
20
  args.GetReturnValue().Set(err);
1810
}
1811
1812
1813
2238
void AfterGetAddrInfo(uv_getaddrinfo_t* req, int status, struct addrinfo* res) {
1814
2238
  GetAddrInfoReqWrap* req_wrap = static_cast<GetAddrInfoReqWrap*>(req->data);
1815
2238
  Environment* env = req_wrap->env();
1816
1817
2238
  HandleScope handle_scope(env->isolate());
1818
2238
  Context::Scope context_scope(env->context());
1819
1820
  Local<Value> argv[] = {
1821
    Integer::New(env->isolate(), status),
1822
    Null(env->isolate())
1823
6714
  };
1824
1825
2238
  if (status == 0) {
1826
2230
    int n = 0;
1827
2230
    Local<Array> results = Array::New(env->isolate());
1828
1829
4460
    auto add = [&] (bool want_ipv4, bool want_ipv6) {
1830
13350
      for (auto p = res; p != nullptr; p = p->ai_next) {
1831
8890
        CHECK_EQ(p->ai_socktype, SOCK_STREAM);
1832
1833
        const char* addr;
1834

8890
        if (want_ipv4 && p->ai_family == AF_INET) {
1835
          addr = reinterpret_cast<char*>(
1836
2235
              &(reinterpret_cast<struct sockaddr_in*>(p->ai_addr)->sin_addr));
1837

6655
        } else if (want_ipv6 && p->ai_family == AF_INET6) {
1838
          addr = reinterpret_cast<char*>(
1839
2210
              &(reinterpret_cast<struct sockaddr_in6*>(p->ai_addr)->sin6_addr));
1840
        } else {
1841
8890
          continue;
1842
        }
1843
1844
        char ip[INET6_ADDRSTRLEN];
1845
4445
        if (uv_inet_ntop(p->ai_family, addr, ip, sizeof(ip)))
1846
          continue;
1847
1848
4445
        Local<String> s = OneByteString(env->isolate(), ip);
1849
8890
        results->Set(n, s);
1850
4445
        n++;
1851
      }
1852
6690
    };
1853
1854
2230
    const bool verbatim = req_wrap->verbatim();
1855
2230
    add(true, verbatim);
1856
2230
    if (verbatim == false)
1857
2230
      add(false, true);
1858
1859
    // No responses were found to return
1860
2230
    if (n == 0) {
1861
      argv[0] = Integer::New(env->isolate(), UV_EAI_NODATA);
1862
    }
1863
1864
2230
    argv[1] = results;
1865
  }
1866
1867
2238
  uv_freeaddrinfo(res);
1868
1869
  // Make the callback into JavaScript
1870
2238
  req_wrap->MakeCallback(env->oncomplete_string(), arraysize(argv), argv);
1871
1872
4476
  delete req_wrap;
1873
2238
}
1874
1875
1876
3
void AfterGetNameInfo(uv_getnameinfo_t* req,
1877
                      int status,
1878
                      const char* hostname,
1879
                      const char* service) {
1880
3
  GetNameInfoReqWrap* req_wrap = static_cast<GetNameInfoReqWrap*>(req->data);
1881
3
  Environment* env = req_wrap->env();
1882
1883
3
  HandleScope handle_scope(env->isolate());
1884
3
  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
12
  };
1891
1892
3
  if (status == 0) {
1893
    // Success
1894
3
    Local<String> js_hostname = OneByteString(env->isolate(), hostname);
1895
3
    Local<String> js_service = OneByteString(env->isolate(), service);
1896
3
    argv[1] = js_hostname;
1897
3
    argv[2] = js_service;
1898
  }
1899
1900
  // Make the callback into JavaScript
1901
3
  req_wrap->MakeCallback(env->oncomplete_string(), arraysize(argv), argv);
1902
1903
6
  delete req_wrap;
1904
3
}
1905
1906
1907
5680
void IsIP(const FunctionCallbackInfo<Value>& args) {
1908
5680
  node::Utf8Value ip(args.GetIsolate(), args[0]);
1909
  char address_buffer[sizeof(struct in6_addr)];
1910
1911
5680
  int rc = 0;
1912
5680
  if (uv_inet_pton(AF_INET, *ip, &address_buffer) == 0)
1913
1040
    rc = 4;
1914
4640
  else if (uv_inet_pton(AF_INET6, *ip, &address_buffer) == 0)
1915
48
    rc = 6;
1916
1917
11360
  args.GetReturnValue().Set(rc);
1918
5680
}
1919
1920
12
void IsIPv4(const FunctionCallbackInfo<Value>& args) {
1921
12
  node::Utf8Value ip(args.GetIsolate(), args[0]);
1922
  char address_buffer[sizeof(struct in_addr)];
1923
1924
12
  if (uv_inet_pton(AF_INET, *ip, &address_buffer) == 0) {
1925
4
    args.GetReturnValue().Set(true);
1926
  } else {
1927
20
    args.GetReturnValue().Set(false);
1928
12
  }
1929
12
}
1930
1931
12
void IsIPv6(const FunctionCallbackInfo<Value>& args) {
1932
12
  node::Utf8Value ip(args.GetIsolate(), args[0]);
1933
  char address_buffer[sizeof(struct in6_addr)];
1934
1935
12
  if (uv_inet_pton(AF_INET6, *ip, &address_buffer) == 0) {
1936
4
    args.GetReturnValue().Set(true);
1937
  } else {
1938
20
    args.GetReturnValue().Set(false);
1939
12
  }
1940
12
}
1941
1942
17
void CanonicalizeIP(const FunctionCallbackInfo<Value>& args) {
1943
17
  v8::Isolate* isolate = args.GetIsolate();
1944
17
  node::Utf8Value ip(isolate, args[0]);
1945
  char address_buffer[sizeof(struct in6_addr)];
1946
  char canonical_ip[INET6_ADDRSTRLEN];
1947
1948
  int af;
1949
17
  if (uv_inet_pton(AF_INET, *ip, &address_buffer) == 0)
1950
8
    af = AF_INET;
1951
9
  else if (uv_inet_pton(AF_INET6, *ip, &address_buffer) == 0)
1952
9
    af = AF_INET6;
1953
  else
1954
17
    return;
1955
1956
  int err = uv_inet_ntop(af, address_buffer, canonical_ip,
1957
17
                         sizeof(canonical_ip));
1958
17
  CHECK_EQ(err, 0);
1959
1960
51
  args.GetReturnValue().Set(String::NewFromUtf8(isolate, canonical_ip));
1961
}
1962
1963
2239
void GetAddrInfo(const FunctionCallbackInfo<Value>& args) {
1964
2239
  Environment* env = Environment::GetCurrent(args);
1965
1966
4478
  CHECK(args[0]->IsObject());
1967
6717
  CHECK(args[1]->IsString());
1968
4478
  CHECK(args[2]->IsInt32());
1969
4478
  CHECK(args[4]->IsBoolean());
1970
4478
  Local<Object> req_wrap_obj = args[0].As<Object>();
1971
2239
  node::Utf8Value hostname(env->isolate(), args[1]);
1972
1973
2239
  int32_t flags = 0;
1974
4478
  if (args[3]->IsInt32()) {
1975
8956
    flags = args[3]->Int32Value(env->context()).FromJust();
1976
  }
1977
1978
  int family;
1979
1980

8956
  switch (args[2]->Int32Value(env->context()).FromJust()) {
1981
  case 0:
1982
2222
    family = AF_UNSPEC;
1983
2222
    break;
1984
  case 4:
1985
12
    family = AF_INET;
1986
12
    break;
1987
  case 6:
1988
5
    family = AF_INET6;
1989
5
    break;
1990
  default:
1991
    CHECK(0 && "bad address family");
1992
  }
1993
1994
6717
  auto req_wrap = new GetAddrInfoReqWrap(env, req_wrap_obj, args[4]->IsTrue());
1995
1996
  struct addrinfo hints;
1997
2239
  memset(&hints, 0, sizeof(struct addrinfo));
1998
2239
  hints.ai_family = family;
1999
2239
  hints.ai_socktype = SOCK_STREAM;
2000
2239
  hints.ai_flags = flags;
2001
2002
  int err = uv_getaddrinfo(env->event_loop(),
2003
                           req_wrap->req(),
2004
                           AfterGetAddrInfo,
2005
2239
                           *hostname,
2006
                           nullptr,
2007
2239
                           &hints);
2008
2239
  req_wrap->Dispatched();
2009
2239
  if (err)
2010
    delete req_wrap;
2011
2012
4478
  args.GetReturnValue().Set(err);
2013
2239
}
2014
2015
2016
3
void GetNameInfo(const FunctionCallbackInfo<Value>& args) {
2017
3
  Environment* env = Environment::GetCurrent(args);
2018
2019
6
  CHECK(args[0]->IsObject());
2020
9
  CHECK(args[1]->IsString());
2021
6
  CHECK(args[2]->IsUint32());
2022
6
  Local<Object> req_wrap_obj = args[0].As<Object>();
2023
3
  node::Utf8Value ip(env->isolate(), args[1]);
2024
12
  const unsigned port = args[2]->Uint32Value(env->context()).FromJust();
2025
  struct sockaddr_storage addr;
2026
2027

3
  CHECK(uv_ip4_addr(*ip, port, reinterpret_cast<sockaddr_in*>(&addr)) == 0 ||
2028
        uv_ip6_addr(*ip, port, reinterpret_cast<sockaddr_in6*>(&addr)) == 0);
2029
2030
3
  GetNameInfoReqWrap* req_wrap = new GetNameInfoReqWrap(env, req_wrap_obj);
2031
2032
  int err = uv_getnameinfo(env->event_loop(),
2033
                           req_wrap->req(),
2034
                           AfterGetNameInfo,
2035
                           (struct sockaddr*)&addr,
2036
3
                           NI_NAMEREQD);
2037
3
  req_wrap->Dispatched();
2038
3
  if (err)
2039
    delete req_wrap;
2040
2041
6
  args.GetReturnValue().Set(err);
2042
3
}
2043
2044
2045
25
void GetServers(const FunctionCallbackInfo<Value>& args) {
2046
25
  Environment* env = Environment::GetCurrent(args);
2047
  ChannelWrap* channel;
2048
50
  ASSIGN_OR_RETURN_UNWRAP(&channel, args.Holder());
2049
2050
25
  Local<Array> server_array = Array::New(env->isolate());
2051
2052
  ares_addr_port_node* servers;
2053
2054
25
  int r = ares_get_servers_ports(channel->cares_channel(), &servers);
2055
25
  CHECK_EQ(r, ARES_SUCCESS);
2056
2057
25
  ares_addr_port_node* cur = servers;
2058
2059
81
  for (uint32_t i = 0; cur != nullptr; ++i, cur = cur->next) {
2060
    char ip[INET6_ADDRSTRLEN];
2061
2062
56
    const void* caddr = static_cast<const void*>(&cur->addr);
2063
56
    int err = uv_inet_ntop(cur->family, caddr, ip, sizeof(ip));
2064
56
    CHECK_EQ(err, 0);
2065
2066
56
    Local<Array> ret = Array::New(env->isolate(), 2);
2067
112
    ret->Set(0, OneByteString(env->isolate(), ip));
2068
112
    ret->Set(1, Integer::New(env->isolate(), cur->udp_port));
2069
2070
56
    server_array->Set(i, ret);
2071
  }
2072
2073
25
  ares_free_data(servers);
2074
2075
50
  args.GetReturnValue().Set(server_array);
2076
}
2077
2078
2079
14
void SetServers(const FunctionCallbackInfo<Value>& args) {
2080
14
  Environment* env = Environment::GetCurrent(args);
2081
  ChannelWrap* channel;
2082
15
  ASSIGN_OR_RETURN_UNWRAP(&channel, args.Holder());
2083
2084
28
  CHECK(args[0]->IsArray());
2085
2086
14
  Local<Array> arr = Local<Array>::Cast(args[0]);
2087
2088
14
  uint32_t len = arr->Length();
2089
2090
14
  if (len == 0) {
2091
1
    int rv = ares_set_servers(channel->cares_channel(), nullptr);
2092
2
    return args.GetReturnValue().Set(rv);
2093
  }
2094
2095
13
  std::vector<ares_addr_port_node> servers(len);
2096
13
  ares_addr_port_node* last = nullptr;
2097
2098
  int err;
2099
2100
36
  for (uint32_t i = 0; i < len; i++) {
2101
92
    CHECK(arr->Get(env->context(), i).ToLocalChecked()->IsArray());
2102
2103
    Local<Array> elm =
2104
69
        Local<Array>::Cast(arr->Get(env->context(), i).ToLocalChecked());
2105
2106
115
    CHECK(elm->Get(env->context(),
2107
                   0).ToLocalChecked()->Int32Value(env->context()).FromJust());
2108
115
    CHECK(elm->Get(env->context(), 1).ToLocalChecked()->IsString());
2109
115
    CHECK(elm->Get(env->context(),
2110
                   2).ToLocalChecked()->Int32Value(env->context()).FromJust());
2111
2112
46
    int fam = elm->Get(env->context(), 0)
2113
115
        .ToLocalChecked()->Int32Value(env->context()).FromJust();
2114
    node::Utf8Value ip(env->isolate(),
2115
69
                       elm->Get(env->context(), 1).ToLocalChecked());
2116
46
    int port = elm->Get(env->context(), 2)
2117
115
        .ToLocalChecked()->Int32Value(env->context()).FromJust();
2118
2119
23
    ares_addr_port_node* cur = &servers[i];
2120
2121
23
    cur->tcp_port = cur->udp_port = port;
2122
23
    switch (fam) {
2123
      case 4:
2124
17
        cur->family = AF_INET;
2125
17
        err = uv_inet_pton(AF_INET, *ip, &cur->addr);
2126
17
        break;
2127
      case 6:
2128
6
        cur->family = AF_INET6;
2129
6
        err = uv_inet_pton(AF_INET6, *ip, &cur->addr);
2130
6
        break;
2131
      default:
2132
        CHECK(0 && "Bad address family.");
2133
    }
2134
2135
23
    if (err)
2136
      break;
2137
2138
23
    cur->next = nullptr;
2139
2140
23
    if (last != nullptr)
2141
10
      last->next = cur;
2142
2143
23
    last = cur;
2144
23
  }
2145
2146
13
  if (err == 0)
2147
13
    err = ares_set_servers_ports(channel->cares_channel(), &servers[0]);
2148
  else
2149
    err = ARES_EBADSTR;
2150
2151
13
  if (err == ARES_SUCCESS)
2152
13
    channel->set_is_servers_default(false);
2153
2154
26
  args.GetReturnValue().Set(err);
2155
}
2156
2157
3
void Cancel(const FunctionCallbackInfo<Value>& args) {
2158
  ChannelWrap* channel;
2159
6
  ASSIGN_OR_RETURN_UNWRAP(&channel, args.Holder());
2160
2161
3
  ares_cancel(channel->cares_channel());
2162
}
2163
2164
2165
void StrError(const FunctionCallbackInfo<Value>& args) {
2166
  Environment* env = Environment::GetCurrent(args);
2167
  const char* errmsg = ares_strerror(args[0]->Int32Value(env->context())
2168
                                     .FromJust());
2169
  args.GetReturnValue().Set(OneByteString(env->isolate(), errmsg));
2170
}
2171
2172
2173
3256
void Initialize(Local<Object> target,
2174
                Local<Value> unused,
2175
                Local<Context> context) {
2176
3256
  Environment* env = Environment::GetCurrent(context);
2177
2178
3256
  env->SetMethod(target, "getaddrinfo", GetAddrInfo);
2179
3256
  env->SetMethod(target, "getnameinfo", GetNameInfo);
2180
3256
  env->SetMethod(target, "isIP", IsIP);
2181
3256
  env->SetMethod(target, "isIPv4", IsIPv4);
2182
3256
  env->SetMethod(target, "isIPv6", IsIPv6);
2183
3256
  env->SetMethod(target, "canonicalizeIP", CanonicalizeIP);
2184
2185
3256
  env->SetMethod(target, "strerror", StrError);
2186
2187
  target->Set(FIXED_ONE_BYTE_STRING(env->isolate(), "AF_INET"),
2188
9768
              Integer::New(env->isolate(), AF_INET));
2189
  target->Set(FIXED_ONE_BYTE_STRING(env->isolate(), "AF_INET6"),
2190
9768
              Integer::New(env->isolate(), AF_INET6));
2191
  target->Set(FIXED_ONE_BYTE_STRING(env->isolate(), "AF_UNSPEC"),
2192
9768
              Integer::New(env->isolate(), AF_UNSPEC));
2193
  target->Set(FIXED_ONE_BYTE_STRING(env->isolate(), "AI_ADDRCONFIG"),
2194
9768
              Integer::New(env->isolate(), AI_ADDRCONFIG));
2195
  target->Set(FIXED_ONE_BYTE_STRING(env->isolate(), "AI_V4MAPPED"),
2196
9768
              Integer::New(env->isolate(), AI_V4MAPPED));
2197
2198
  auto is_construct_call_callback =
2199
14280
      [](const FunctionCallbackInfo<Value>& args) {
2200
2256
    CHECK(args.IsConstructCall());
2201
2256
    ClearWrap(args.This());
2202
14280
  };
2203
  Local<FunctionTemplate> aiw =
2204
3256
      FunctionTemplate::New(env->isolate(), is_construct_call_callback);
2205
6512
  aiw->InstanceTemplate()->SetInternalFieldCount(1);
2206
3256
  AsyncWrap::AddWrapMethods(env, aiw);
2207
  Local<String> addrInfoWrapString =
2208
3256
      FIXED_ONE_BYTE_STRING(env->isolate(), "GetAddrInfoReqWrap");
2209
3256
  aiw->SetClassName(addrInfoWrapString);
2210
6512
  target->Set(addrInfoWrapString, aiw->GetFunction());
2211
2212
  Local<FunctionTemplate> niw =
2213
3256
      FunctionTemplate::New(env->isolate(), is_construct_call_callback);
2214
6512
  niw->InstanceTemplate()->SetInternalFieldCount(1);
2215
3256
  AsyncWrap::AddWrapMethods(env, niw);
2216
  Local<String> nameInfoWrapString =
2217
3256
      FIXED_ONE_BYTE_STRING(env->isolate(), "GetNameInfoReqWrap");
2218
3256
  niw->SetClassName(nameInfoWrapString);
2219
6512
  target->Set(nameInfoWrapString, niw->GetFunction());
2220
2221
  Local<FunctionTemplate> qrw =
2222
3256
      FunctionTemplate::New(env->isolate(), is_construct_call_callback);
2223
6512
  qrw->InstanceTemplate()->SetInternalFieldCount(1);
2224
3256
  AsyncWrap::AddWrapMethods(env, qrw);
2225
  Local<String> queryWrapString =
2226
3256
      FIXED_ONE_BYTE_STRING(env->isolate(), "QueryReqWrap");
2227
3256
  qrw->SetClassName(queryWrapString);
2228
6512
  target->Set(queryWrapString, qrw->GetFunction());
2229
2230
  Local<FunctionTemplate> channel_wrap =
2231
3256
      env->NewFunctionTemplate(ChannelWrap::New);
2232
6512
  channel_wrap->InstanceTemplate()->SetInternalFieldCount(1);
2233
3256
  AsyncWrap::AddWrapMethods(env, channel_wrap);
2234
2235
3256
  env->SetProtoMethod(channel_wrap, "queryAny", Query<QueryAnyWrap>);
2236
3256
  env->SetProtoMethod(channel_wrap, "queryA", Query<QueryAWrap>);
2237
3256
  env->SetProtoMethod(channel_wrap, "queryAaaa", Query<QueryAaaaWrap>);
2238
3256
  env->SetProtoMethod(channel_wrap, "queryCname", Query<QueryCnameWrap>);
2239
3256
  env->SetProtoMethod(channel_wrap, "queryMx", Query<QueryMxWrap>);
2240
3256
  env->SetProtoMethod(channel_wrap, "queryNs", Query<QueryNsWrap>);
2241
3256
  env->SetProtoMethod(channel_wrap, "queryTxt", Query<QueryTxtWrap>);
2242
3256
  env->SetProtoMethod(channel_wrap, "querySrv", Query<QuerySrvWrap>);
2243
3256
  env->SetProtoMethod(channel_wrap, "queryPtr", Query<QueryPtrWrap>);
2244
3256
  env->SetProtoMethod(channel_wrap, "queryNaptr", Query<QueryNaptrWrap>);
2245
3256
  env->SetProtoMethod(channel_wrap, "querySoa", Query<QuerySoaWrap>);
2246
3256
  env->SetProtoMethod(channel_wrap, "getHostByAddr", Query<GetHostByAddrWrap>);
2247
2248
3256
  env->SetProtoMethod(channel_wrap, "getServers", GetServers);
2249
3256
  env->SetProtoMethod(channel_wrap, "setServers", SetServers);
2250
3256
  env->SetProtoMethod(channel_wrap, "cancel", Cancel);
2251
2252
  Local<String> channelWrapString =
2253
3256
      FIXED_ONE_BYTE_STRING(env->isolate(), "ChannelWrap");
2254
3256
  channel_wrap->SetClassName(channelWrapString);
2255
6512
  target->Set(channelWrapString, channel_wrap->GetFunction());
2256
3256
}
2257
2258
}  // anonymous namespace
2259
}  // namespace cares_wrap
2260
}  // namespace node
2261
2262
3332
NODE_BUILTIN_MODULE_CONTEXT_AWARE(cares_wrap, node::cares_wrap::Initialize)