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: 464 1050 44.2 %
Date: 2017-06-14 Branches: 149 771 19.3 %

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.h"
25
#include "async-wrap-inl.h"
26
#include "env.h"
27
#include "env-inl.h"
28
#include "node.h"
29
#include "req-wrap.h"
30
#include "req-wrap-inl.h"
31
#include "tree.h"
32
#include "util.h"
33
#include "util-inl.h"
34
#include "uv.h"
35
36
#include <errno.h>
37
#include <stdlib.h>
38
#include <string.h>
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::Integer;
64
using v8::Local;
65
using v8::Null;
66
using v8::Object;
67
using v8::String;
68
using v8::Value;
69
70
namespace {
71
72
inline uint16_t cares_get_16bit(const unsigned char* p) {
73
  return static_cast<uint32_t>(p[0] << 8U) | (static_cast<uint32_t>(p[1]));
74
}
75
76
inline uint32_t cares_get_32bit(const unsigned char* p) {
77
  return static_cast<uint32_t>(p[0] << 24U) |
78
         static_cast<uint32_t>(p[1] << 16U) |
79
         static_cast<uint32_t>(p[2] << 8U) |
80
         static_cast<uint32_t>(p[3]);
81
}
82
83
const int ns_t_cname_or_a = -1;
84
85
2
inline const char* ToErrorCodeString(int status) {
86






2
  switch (status) {
87
#define V(code) case ARES_##code: return #code;
88
    V(EADDRGETNETWORKPARAMS)
89
    V(EBADFAMILY)
90
    V(EBADFLAGS)
91
    V(EBADHINTS)
92
    V(EBADNAME)
93
    V(EBADQUERY)
94
    V(EBADRESP)
95
    V(EBADSTR)
96
    V(ECANCELLED)
97
    V(ECONNREFUSED)
98
    V(EDESTRUCTION)
99
    V(EFILE)
100
    V(EFORMERR)
101
    V(ELOADIPHLPAPI)
102
    V(ENODATA)
103
    V(ENOMEM)
104
    V(ENONAME)
105
2
    V(ENOTFOUND)
106
    V(ENOTIMP)
107
    V(ENOTINITIALIZED)
108
    V(EOF)
109
    V(EREFUSED)
110
    V(ESERVFAIL)
111
    V(ETIMEOUT)
112
#undef V
113
  }
114
115
  return "UNKNOWN_ARES_ERROR";
116
}
117
118
class GetAddrInfoReqWrap : public ReqWrap<uv_getaddrinfo_t> {
119
 public:
120
  GetAddrInfoReqWrap(Environment* env, Local<Object> req_wrap_obj);
121
  ~GetAddrInfoReqWrap();
122
123
  size_t self_size() const override { return sizeof(*this); }
124
};
125
126
1968
GetAddrInfoReqWrap::GetAddrInfoReqWrap(Environment* env,
127
                                       Local<Object> req_wrap_obj)
128
1968
    : ReqWrap(env, req_wrap_obj, AsyncWrap::PROVIDER_GETADDRINFOREQWRAP) {
129
1968
  Wrap(req_wrap_obj, this);
130
1968
}
131
132
5901
GetAddrInfoReqWrap::~GetAddrInfoReqWrap() {
133
1967
  ClearWrap(object());
134
3934
}
135
136
137
class GetNameInfoReqWrap : public ReqWrap<uv_getnameinfo_t> {
138
 public:
139
  GetNameInfoReqWrap(Environment* env, Local<Object> req_wrap_obj);
140
  ~GetNameInfoReqWrap();
141
142
  size_t self_size() const override { return sizeof(*this); }
143
};
144
145
2
GetNameInfoReqWrap::GetNameInfoReqWrap(Environment* env,
146
                                       Local<Object> req_wrap_obj)
147
2
    : ReqWrap(env, req_wrap_obj, AsyncWrap::PROVIDER_GETNAMEINFOREQWRAP) {
148
2
  Wrap(req_wrap_obj, this);
149
2
}
150
151
6
GetNameInfoReqWrap::~GetNameInfoReqWrap() {
152
2
  ClearWrap(object());
153
4
}
154
155
156
2
int cmp_ares_tasks(const node_ares_task* a, const node_ares_task* b) {
157
2
  if (a->sock < b->sock)
158
    return -1;
159
2
  if (a->sock > b->sock)
160
    return 1;
161
2
  return 0;
162
}
163
164
165




















































12
RB_GENERATE_STATIC(node_ares_task_list, node_ares_task, node, cmp_ares_tasks)
166
167
168
169
/* This is called once per second by loop->timer. It is used to constantly */
170
/* call back into c-ares for possibly processing timeouts. */
171
void ares_timeout(uv_timer_t* handle) {
172
  Environment* env = Environment::from_cares_timer_handle(handle);
173
  CHECK_EQ(false, RB_EMPTY(env->cares_task_list()));
174
  ares_process_fd(env->cares_channel(), ARES_SOCKET_BAD, ARES_SOCKET_BAD);
175
}
176
177
178
2
void ares_poll_cb(uv_poll_t* watcher, int status, int events) {
179
2
  node_ares_task* task = ContainerOf(&node_ares_task::poll_watcher, watcher);
180
2
  Environment* env = task->env;
181
182
  /* Reset the idle timer */
183
2
  uv_timer_again(env->cares_timer_handle());
184
185
2
  if (status < 0) {
186
    /* An error happened. Just pretend that the socket is both readable and */
187
    /* writable. */
188
    ares_process_fd(env->cares_channel(), task->sock, task->sock);
189
2
    return;
190
  }
191
192
  /* Process DNS responses */
193
  ares_process_fd(env->cares_channel(),
194
2
                  events & UV_READABLE ? task->sock : ARES_SOCKET_BAD,
195

4
                  events & UV_WRITABLE ? task->sock : ARES_SOCKET_BAD);
196
}
197
198
199
2
void ares_poll_close_cb(uv_handle_t* watcher) {
200
  node_ares_task* task = ContainerOf(&node_ares_task::poll_watcher,
201
2
                                  reinterpret_cast<uv_poll_t*>(watcher));
202
2
  free(task);
203
2
}
204
205
206
/* Allocates and returns a new node_ares_task */
207
2
node_ares_task* ares_task_create(Environment* env, ares_socket_t sock) {
208
2
  auto task = node::UncheckedMalloc<node_ares_task>(1);
209
210
2
  if (task == nullptr) {
211
    /* Out of memory. */
212
    return nullptr;
213
  }
214
215
2
  task->env = env;
216
2
  task->sock = sock;
217
218
2
  if (uv_poll_init_socket(env->event_loop(), &task->poll_watcher, sock) < 0) {
219
    /* This should never happen. */
220
    free(task);
221
    return nullptr;
222
  }
223
224
2
  return task;
225
}
226
227
228
/* Callback from ares when socket operation is started */
229
4
void ares_sockstate_cb(void* data,
230
                       ares_socket_t sock,
231
                       int read,
232
                       int write) {
233
4
  Environment* env = static_cast<Environment*>(data);
234
  node_ares_task* task;
235
236
  node_ares_task lookup_task;
237
4
  lookup_task.sock = sock;
238
4
  task = RB_FIND(node_ares_task_list, env->cares_task_list(), &lookup_task);
239
240

4
  if (read || write) {
241
2
    if (!task) {
242
      /* New socket */
243
244
      /* If this is the first socket then start the timer. */
245
2
      uv_timer_t* timer_handle = env->cares_timer_handle();
246
2
      if (!uv_is_active(reinterpret_cast<uv_handle_t*>(timer_handle))) {
247
2
        CHECK(RB_EMPTY(env->cares_task_list()));
248
2
        uv_timer_start(timer_handle, ares_timeout, 1000, 1000);
249
      }
250
251
2
      task = ares_task_create(env, sock);
252
2
      if (task == nullptr) {
253
        /* This should never happen unless we're out of memory or something */
254
        /* is seriously wrong. The socket won't be polled, but the query will */
255
        /* eventually time out. */
256
        return;
257
      }
258
259
2
      RB_INSERT(node_ares_task_list, env->cares_task_list(), task);
260
    }
261
262
    /* This should never fail. If it fails anyway, the query will eventually */
263
    /* time out. */
264
    uv_poll_start(&task->poll_watcher,
265
                  (read ? UV_READABLE : 0) | (write ? UV_WRITABLE : 0),
266

2
                  ares_poll_cb);
267
268
  } else {
269
    /* read == 0 and write == 0 this is c-ares's way of notifying us that */
270
    /* the socket is now closed. We must free the data associated with */
271
    /* socket. */
272
2
    CHECK(task &&
273
          "When an ares socket is closed we should have a handle for it");
274
275
2
    RB_REMOVE(node_ares_task_list, env->cares_task_list(), task);
276
    uv_close(reinterpret_cast<uv_handle_t*>(&task->poll_watcher),
277
2
             ares_poll_close_cb);
278
279
2
    if (RB_EMPTY(env->cares_task_list())) {
280
2
      uv_timer_stop(env->cares_timer_handle());
281
    }
282
  }
283
}
284
285
286
Local<Array> HostentToAddresses(Environment* env,
287
                                struct hostent* host,
288
                                Local<Array> append_to = Local<Array>()) {
289
  EscapableHandleScope scope(env->isolate());
290
  auto context = env->context();
291
  bool append = !append_to.IsEmpty();
292
  Local<Array> addresses = append ? append_to : Array::New(env->isolate());
293
  size_t offset = addresses->Length();
294
295
  char ip[INET6_ADDRSTRLEN];
296
  for (uint32_t i = 0; host->h_addr_list[i] != nullptr; ++i) {
297
    uv_inet_ntop(host->h_addrtype, host->h_addr_list[i], ip, sizeof(ip));
298
    Local<String> address = OneByteString(env->isolate(), ip);
299
    addresses->Set(context, i + offset, address).FromJust();
300
  }
301
302
  return append ? addresses : scope.Escape(addresses);
303
}
304
305
306
1
Local<Array> HostentToNames(Environment* env,
307
                            struct hostent* host,
308
                            Local<Array> append_to = Local<Array>()) {
309
1
  EscapableHandleScope scope(env->isolate());
310
1
  auto context = env->context();
311
1
  bool append = !append_to.IsEmpty();
312
1
  Local<Array> names = append ? append_to : Array::New(env->isolate());
313
1
  size_t offset = names->Length();
314
315
1
  for (uint32_t i = 0; host->h_aliases[i] != nullptr; ++i) {
316
    Local<String> address = OneByteString(env->isolate(), host->h_aliases[i]);
317
    names->Set(context, i + offset, address).FromJust();
318
  }
319
320
3
  return append ? names : scope.Escape(names);
321
}
322
323
1
void safe_free_hostent(struct hostent* host) {
324
  int idx;
325
326
1
  if (host->h_addr_list != nullptr) {
327
1
    idx = 0;
328
3
    while (host->h_addr_list[idx]) {
329
1
      free(host->h_addr_list[idx++]);
330
    }
331
1
    free(host->h_addr_list);
332
1
    host->h_addr_list = 0;
333
  }
334
335
1
  if (host->h_aliases != nullptr) {
336
1
    idx = 0;
337
2
    while (host->h_aliases[idx]) {
338
      free(host->h_aliases[idx++]);
339
    }
340
1
    free(host->h_aliases);
341
1
    host->h_aliases = 0;
342
  }
343
344
1
  if (host->h_name != nullptr) {
345
1
    free(host->h_name);
346
  }
347
348
1
  host->h_addrtype = host->h_length = 0;
349
1
}
350
351
1
void cares_wrap_hostent_cpy(struct hostent* dest, struct hostent* src) {
352
1
  dest->h_addr_list = nullptr;
353
1
  dest->h_addrtype = 0;
354
1
  dest->h_aliases = nullptr;
355
1
  dest->h_length = 0;
356
1
  dest->h_name = nullptr;
357
358
  /* copy `h_name` */
359
1
  size_t name_size = strlen(src->h_name) + 1;
360
1
  dest->h_name = node::Malloc<char>(name_size);
361
1
  memcpy(dest->h_name, src->h_name, name_size);
362
363
  /* copy `h_aliases` */
364
  size_t alias_count;
365
  size_t cur_alias_length;
366
2
  for (alias_count = 0;
367
1
      src->h_aliases[alias_count] != nullptr;
368
      alias_count++) {
369
  }
370
371
1
  dest->h_aliases = node::Malloc<char*>(alias_count + 1);
372
1
  for (size_t i = 0; i < alias_count; i++) {
373
    cur_alias_length = strlen(src->h_aliases[i]);
374
    dest->h_aliases[i] = node::Malloc(cur_alias_length + 1);
375
    memcpy(dest->h_aliases[i], src->h_aliases[i], cur_alias_length + 1);
376
  }
377
1
  dest->h_aliases[alias_count] = nullptr;
378
379
  /* copy `h_addr_list` */
380
  size_t list_count;
381
3
  for (list_count = 0;
382
2
      src->h_addr_list[list_count] != nullptr;
383
      list_count++) {
384
  }
385
386
1
  dest->h_addr_list = node::Malloc<char*>(list_count + 1);
387
2
  for (size_t i = 0; i < list_count; i++) {
388
1
    dest->h_addr_list[i] = node::Malloc(src->h_length);
389
1
    memcpy(dest->h_addr_list[i], src->h_addr_list[i], src->h_length);
390
  }
391
1
  dest->h_addr_list[list_count] = nullptr;
392
393
  /* work after work */
394
1
  dest->h_length = src->h_length;
395
1
  dest->h_addrtype = src->h_addrtype;
396
1
}
397
398
class QueryWrap;
399
struct CaresAsyncData {
400
  QueryWrap* wrap;
401
  int status;
402
  bool is_host;
403
  union {
404
    hostent* host;
405
    unsigned char* buf;
406
  } data;
407
  int len;
408
409
  uv_async_t async_handle;
410
};
411
412
2319
void SetupCaresChannel(Environment* env) {
413
  struct ares_options options;
414
2319
  memset(&options, 0, sizeof(options));
415
2319
  options.flags = ARES_FLAG_NOCHECKRESP;
416
2319
  options.sock_state_cb = ares_sockstate_cb;
417
2319
  options.sock_state_cb_data = env;
418
419
  /* We do the call to ares_init_option for caller. */
420
  int r = ares_init_options(env->cares_channel_ptr(),
421
                            &options,
422
2319
                            ARES_OPT_FLAGS | ARES_OPT_SOCK_STATE_CB);
423
424
2319
  if (r != ARES_SUCCESS) {
425
    ares_library_cleanup();
426
    return env->ThrowError(ToErrorCodeString(r));
427
  }
428
}
429
430
431
/**
432
 * This function is to check whether current servers are fallback servers
433
 * when cares initialized.
434
 *
435
 * The fallback servers of cares is [ "127.0.0.1" ] with no user additional
436
 * setting.
437
 */
438
2
void AresEnsureServers(Environment* env) {
439
  /* if last query is OK or servers are set by user self, do not check */
440

2
  if (env->cares_query_last_ok() || !env->cares_is_servers_default()) {
441
4
    return;
442
  }
443
444
  ares_channel channel = env->cares_channel();
445
  ares_addr_node* servers = nullptr;
446
447
  ares_get_servers(channel, &servers);
448
449
  /* if no server or multi-servers, ignore */
450
  if (servers == nullptr) return;
451
  if (servers->next != nullptr) {
452
    ares_free_data(servers);
453
    env->set_cares_is_servers_default(false);
454
    return;
455
  }
456
457
  /* if the only server is not 127.0.0.1, ignore */
458
  if (servers[0].family != AF_INET ||
459
      servers[0].addr.addr4.s_addr != htonl(INADDR_LOOPBACK)) {
460
    ares_free_data(servers);
461
    env->set_cares_is_servers_default(false);
462
    return;
463
  }
464
465
  ares_free_data(servers);
466
  servers = nullptr;
467
468
  /* destroy channel and reset channel */
469
  ares_destroy(channel);
470
471
  SetupCaresChannel(env);
472
}
473
474
475
class QueryWrap : public AsyncWrap {
476
 public:
477
3
  QueryWrap(Environment* env, Local<Object> req_wrap_obj)
478
3
      : AsyncWrap(env, req_wrap_obj, AsyncWrap::PROVIDER_QUERYWRAP) {
479
3
    if (env->in_domain())
480
      req_wrap_obj->Set(env->domain_string(), env->domain_array()->Get(0));
481
3
    Wrap(req_wrap_obj, this);
482
3
  }
483
484
6
  ~QueryWrap() override {
485
6
    CHECK_EQ(false, persistent().IsEmpty());
486
3
    ClearWrap(object());
487
3
    persistent().Reset();
488
3
  }
489
490
  // Subclasses should implement the appropriate Send method.
491
  virtual int Send(const char* name) {
492
    UNREACHABLE();
493
    return 0;
494
  }
495
496
  virtual int Send(const char* name, int family) {
497
    UNREACHABLE();
498
    return 0;
499
  }
500
501
 protected:
502
3
  void* GetQueryArg() {
503
3
    return static_cast<void*>(this);
504
  }
505
506
2
  static void AresQuery(Environment* env, const char* name,
507
                        int dnsclass, int type, ares_callback callback,
508
                        void* arg) {
509
2
    AresEnsureServers(env);
510
2
    ares_query(env->cares_channel(), name, dnsclass, type, callback, arg);
511
2
  }
512
513
3
  static void CaresAsyncClose(uv_handle_t* handle) {
514
3
    uv_async_t* async = reinterpret_cast<uv_async_t*>(handle);
515
3
    auto data = static_cast<struct CaresAsyncData*>(async->data);
516
3
    delete data->wrap;
517
3
    delete data;
518
3
  }
519
520
3
  static void CaresAsyncCb(uv_async_t* handle) {
521
3
    auto data = static_cast<struct CaresAsyncData*>(handle->data);
522
523
3
    QueryWrap* wrap = data->wrap;
524
3
    int status = data->status;
525
526
3
    if (status != ARES_SUCCESS) {
527
2
      wrap->ParseError(status);
528
1
    } else if (!data->is_host) {
529
      unsigned char* buf = data->data.buf;
530
      wrap->Parse(buf, data->len);
531
      free(buf);
532
    } else {
533
1
      hostent* host = data->data.host;
534
1
      wrap->Parse(host);
535
1
      safe_free_hostent(host);
536
1
      free(host);
537
    }
538
539
3
    uv_close(reinterpret_cast<uv_handle_t*>(handle), CaresAsyncClose);
540
3
  }
541
542
2
  static void Callback(void *arg, int status, int timeouts,
543
                       unsigned char* answer_buf, int answer_len) {
544
2
    QueryWrap* wrap = static_cast<QueryWrap*>(arg);
545
546
2
    unsigned char* buf_copy = nullptr;
547
2
    if (status == ARES_SUCCESS) {
548
      buf_copy = node::Malloc<unsigned char>(answer_len);
549
      memcpy(buf_copy, answer_buf, answer_len);
550
    }
551
552
2
    CaresAsyncData* data = new CaresAsyncData();
553
2
    data->status = status;
554
2
    data->wrap = wrap;
555
2
    data->is_host = false;
556
2
    data->data.buf = buf_copy;
557
2
    data->len = answer_len;
558
559
2
    uv_async_t* async_handle = &data->async_handle;
560
2
    CHECK_EQ(0, uv_async_init(wrap->env()->event_loop(),
561
                              async_handle,
562
                              CaresAsyncCb));
563
564
2
    wrap->env()->set_cares_query_last_ok(status != ARES_ECONNREFUSED);
565
2
    async_handle->data = data;
566
2
    uv_async_send(async_handle);
567
2
  }
568
569
1
  static void Callback(void *arg, int status, int timeouts,
570
                       struct hostent* host) {
571
1
    QueryWrap* wrap = static_cast<QueryWrap*>(arg);
572
573
1
    struct hostent* host_copy = nullptr;
574
1
    if (status == ARES_SUCCESS) {
575
1
      host_copy = node::Malloc<hostent>(1);
576
1
      cares_wrap_hostent_cpy(host_copy, host);
577
    }
578
579
1
    CaresAsyncData* data = new CaresAsyncData();
580
1
    data->status = status;
581
1
    data->data.host = host_copy;
582
1
    data->wrap = wrap;
583
1
    data->is_host = true;
584
585
1
    uv_async_t* async_handle = &data->async_handle;
586
1
    CHECK_EQ(0, uv_async_init(wrap->env()->event_loop(),
587
                              async_handle,
588
                              CaresAsyncCb));
589
590
1
    wrap->env()->set_cares_query_last_ok(status != ARES_ECONNREFUSED);
591
1
    async_handle->data = data;
592
1
    uv_async_send(async_handle);
593
1
  }
594
595
1
  void CallOnComplete(Local<Value> answer,
596
                      Local<Value> extra = Local<Value>()) {
597
1
    HandleScope handle_scope(env()->isolate());
598
1
    Context::Scope context_scope(env()->context());
599
    Local<Value> argv[] = {
600
      Integer::New(env()->isolate(), 0),
601
      answer,
602
      extra
603
2
    };
604
2
    const int argc = arraysize(argv) - extra.IsEmpty();
605
2
    MakeCallback(env()->oncomplete_string(), argc, argv);
606
1
  }
607
608
2
  void ParseError(int status) {
609
2
    CHECK_NE(status, ARES_SUCCESS);
610
2
    HandleScope handle_scope(env()->isolate());
611
2
    Context::Scope context_scope(env()->context());
612
2
    const char* code = ToErrorCodeString(status);
613
2
    Local<Value> arg = OneByteString(env()->isolate(), code);
614
4
    MakeCallback(env()->oncomplete_string(), 1, &arg);
615
2
  }
616
617
  // Subclasses should implement the appropriate Parse method.
618
  virtual void Parse(unsigned char* buf, int len) {
619
    UNREACHABLE();
620
  }
621
622
  virtual void Parse(struct hostent* host) {
623
    UNREACHABLE();
624
  }
625
};
626
627
628
template<typename T>
629
Local<Array> AddrTTLToArray(Environment* env,
630
                            const T* addrttls,
631
                            size_t naddrttls) {
632
  auto isolate = env->isolate();
633
  EscapableHandleScope escapable_handle_scope(isolate);
634
  auto context = env->context();
635
636
  Local<Array> ttls = Array::New(isolate, naddrttls);
637
  for (size_t i = 0; i < naddrttls; i++) {
638
    auto value = Integer::New(isolate, addrttls[i].ttl);
639
    ttls->Set(context, i, value).FromJust();
640
  }
641
642
  return escapable_handle_scope.Escape(ttls);
643
}
644
645
646
int ParseGeneralReply(Environment* env,
647
                      const unsigned char* buf,
648
                      int len,
649
                      int* type,
650
                      Local<Array> ret,
651
                      void* addrttls = nullptr,
652
                      int* naddrttls = nullptr) {
653
  HandleScope handle_scope(env->isolate());
654
  auto context = env->context();
655
  hostent* host;
656
657
  int status;
658
  switch (*type) {
659
    case ns_t_a:
660
    case ns_t_cname:
661
    case ns_t_cname_or_a:
662
      status = ares_parse_a_reply(buf,
663
                                  len,
664
                                  &host,
665
                                  static_cast<ares_addrttl*>(addrttls),
666
                                  naddrttls);
667
      break;
668
    case ns_t_aaaa:
669
      status = ares_parse_aaaa_reply(buf,
670
                                     len,
671
                                     &host,
672
                                     static_cast<ares_addr6ttl*>(addrttls),
673
                                     naddrttls);
674
      break;
675
    case ns_t_ns:
676
      status = ares_parse_ns_reply(buf, len, &host);
677
      break;
678
    case ns_t_ptr:
679
      status = ares_parse_ptr_reply(buf, len, NULL, 0, AF_INET, &host);
680
      break;
681
    default:
682
      CHECK(0 && "Bad NS type");
683
      break;
684
  }
685
686
  if (status != ARES_SUCCESS)
687
    return status;
688
689
  /* If it's `CNAME`, return the CNAME value;
690
   * And if it's `CNAME_OR_A` and it has value in `h_name` and `h_aliases[0]`,
691
   * we consider it's a CNAME record, otherwise we consider it's an A record. */
692
  if ((*type == ns_t_cname_or_a && host->h_name && host->h_aliases[0]) ||
693
      *type == ns_t_cname) {
694
    // A cname lookup always returns a single record but we follow the
695
    // common API here.
696
    *type = ns_t_cname;
697
    ret->Set(context,
698
             ret->Length(),
699
             OneByteString(env->isolate(), host->h_name)).FromJust();
700
    ares_free_hostent(host);
701
    return ARES_SUCCESS;
702
  }
703
704
  if (*type == ns_t_cname_or_a)
705
    *type = ns_t_a;
706
707
  if (*type == ns_t_ns) {
708
    HostentToNames(env, host, ret);
709
  } else if (*type == ns_t_ptr) {
710
    uint32_t offset = ret->Length();
711
    for (uint32_t i = 0; host->h_aliases[i] != NULL; i++) {
712
      ret->Set(context,
713
               i + offset,
714
               OneByteString(env->isolate(), host->h_aliases[i])).FromJust();
715
    }
716
  } else {
717
    HostentToAddresses(env, host, ret);
718
  }
719
720
  ares_free_hostent(host);
721
722
  return ARES_SUCCESS;
723
}
724
725
726
int ParseMxReply(Environment* env,
727
                 const unsigned char* buf,
728
                 int len,
729
                 Local<Array> ret,
730
                 bool need_type = false) {
731
  HandleScope handle_scope(env->isolate());
732
  auto context = env->context();
733
734
  struct ares_mx_reply* mx_start;
735
  int status = ares_parse_mx_reply(buf, len, &mx_start);
736
  if (status != ARES_SUCCESS) {
737
    return status;
738
  }
739
740
  Local<String> exchange_symbol = env->exchange_string();
741
  Local<String> priority_symbol = env->priority_string();
742
  Local<String> type_symbol = env->type_string();
743
  Local<String> mx_symbol = env->dns_mx_string();
744
745
  uint32_t offset = ret->Length();
746
  ares_mx_reply* current = mx_start;
747
  for (uint32_t i = 0; current != nullptr; ++i, current = current->next) {
748
    Local<Object> mx_record = Object::New(env->isolate());
749
    mx_record->Set(context,
750
                   exchange_symbol,
751
                   OneByteString(env->isolate(), current->host)).FromJust();
752
    mx_record->Set(context,
753
                   priority_symbol,
754
                   Integer::New(env->isolate(), current->priority)).FromJust();
755
    if (need_type)
756
      mx_record->Set(context, type_symbol, mx_symbol).FromJust();
757
758
    ret->Set(context, i + offset, mx_record).FromJust();
759
  }
760
761
  ares_free_data(mx_start);
762
  return ARES_SUCCESS;
763
}
764
765
int ParseTxtReply(Environment* env,
766
                  const unsigned char* buf,
767
                  int len,
768
                  Local<Array> ret,
769
                  bool need_type = false) {
770
  HandleScope handle_scope(env->isolate());
771
  auto context = env->context();
772
773
  struct ares_txt_ext* txt_out;
774
775
  int status = ares_parse_txt_reply_ext(buf, len, &txt_out);
776
  if (status != ARES_SUCCESS) {
777
    return status;
778
  }
779
780
  Local<Array> txt_chunk;
781
782
  struct ares_txt_ext* current = txt_out;
783
  uint32_t i = 0, j;
784
  uint32_t offset = ret->Length();
785
  for (j = 0; current != nullptr; current = current->next) {
786
    Local<String> txt = OneByteString(env->isolate(), current->txt);
787
788
    // New record found - write out the current chunk
789
    if (current->record_start) {
790
      if (!txt_chunk.IsEmpty()) {
791
        if (need_type) {
792
          Local<Object> elem = Object::New(env->isolate());
793
          elem->Set(context, env->entries_string(), txt_chunk).FromJust();
794
          elem->Set(context,
795
                    env->type_string(),
796
                    env->dns_txt_string()).FromJust();
797
          ret->Set(context, offset + i++, elem).FromJust();
798
        } else {
799
          ret->Set(context, offset + i++, txt_chunk).FromJust();
800
        }
801
      }
802
803
      txt_chunk = Array::New(env->isolate());
804
      j = 0;
805
    }
806
807
    txt_chunk->Set(context, j++, txt).FromJust();
808
  }
809
810
  // Push last chunk if it isn't empty
811
  if (!txt_chunk.IsEmpty()) {
812
    if (need_type) {
813
      Local<Object> elem = Object::New(env->isolate());
814
      elem->Set(context, env->entries_string(), txt_chunk).FromJust();
815
      elem->Set(context,
816
                env->type_string(),
817
                env->dns_txt_string()).FromJust();
818
      ret->Set(context, offset + i, elem).FromJust();
819
    } else {
820
      ret->Set(context, offset + i, txt_chunk).FromJust();
821
    }
822
  }
823
824
  ares_free_data(txt_out);
825
  return ARES_SUCCESS;
826
}
827
828
829
int ParseSrvReply(Environment* env,
830
                  const unsigned char* buf,
831
                  int len,
832
                  Local<Array> ret,
833
                  bool need_type = false) {
834
  HandleScope handle_scope(env->isolate());
835
  auto context = env->context();
836
837
  struct ares_srv_reply* srv_start;
838
  int status = ares_parse_srv_reply(buf, len, &srv_start);
839
  if (status != ARES_SUCCESS) {
840
    return status;
841
  }
842
843
  Local<String> name_symbol = env->name_string();
844
  Local<String> port_symbol = env->port_string();
845
  Local<String> priority_symbol = env->priority_string();
846
  Local<String> weight_symbol = env->weight_string();
847
  Local<String> type_symbol = env->type_string();
848
  Local<String> srv_symbol = env->dns_srv_string();
849
850
  ares_srv_reply* current = srv_start;
851
  int offset = ret->Length();
852
  for (uint32_t i = 0; current != nullptr; ++i, current = current->next) {
853
    Local<Object> srv_record = Object::New(env->isolate());
854
    srv_record->Set(context,
855
                    name_symbol,
856
                    OneByteString(env->isolate(), current->host)).FromJust();
857
    srv_record->Set(context,
858
                    port_symbol,
859
                    Integer::New(env->isolate(), current->port)).FromJust();
860
    srv_record->Set(context,
861
                    priority_symbol,
862
                    Integer::New(env->isolate(), current->priority)).FromJust();
863
    srv_record->Set(context,
864
                    weight_symbol,
865
                    Integer::New(env->isolate(), current->weight)).FromJust();
866
    if (need_type)
867
      srv_record->Set(context, type_symbol, srv_symbol).FromJust();
868
869
    ret->Set(context, i + offset, srv_record).FromJust();
870
  }
871
872
  ares_free_data(srv_start);
873
  return ARES_SUCCESS;
874
}
875
876
877
int ParseNaptrReply(Environment* env,
878
                    const unsigned char* buf,
879
                    int len,
880
                    Local<Array> ret,
881
                    bool need_type = false) {
882
  HandleScope handle_scope(env->isolate());
883
  auto context = env->context();
884
885
  ares_naptr_reply* naptr_start;
886
  int status = ares_parse_naptr_reply(buf, len, &naptr_start);
887
888
  if (status != ARES_SUCCESS) {
889
    return status;
890
  }
891
892
  Local<String> flags_symbol = env->flags_string();
893
  Local<String> service_symbol = env->service_string();
894
  Local<String> regexp_symbol = env->regexp_string();
895
  Local<String> replacement_symbol = env->replacement_string();
896
  Local<String> order_symbol = env->order_string();
897
  Local<String> preference_symbol = env->preference_string();
898
  Local<String> type_symbol = env->type_string();
899
  Local<String> naptr_symbol = env->dns_naptr_string();
900
901
  ares_naptr_reply* current = naptr_start;
902
  int offset = ret->Length();
903
  for (uint32_t i = 0; current != nullptr; ++i, current = current->next) {
904
    Local<Object> naptr_record = Object::New(env->isolate());
905
    naptr_record->Set(context,
906
                      flags_symbol,
907
                      OneByteString(env->isolate(), current->flags)).FromJust();
908
    naptr_record->Set(context,
909
                      service_symbol,
910
                      OneByteString(env->isolate(),
911
                                    current->service)).FromJust();
912
    naptr_record->Set(context,
913
                      regexp_symbol,
914
                      OneByteString(env->isolate(),
915
                                    current->regexp)).FromJust();
916
    naptr_record->Set(context,
917
                      replacement_symbol,
918
                      OneByteString(env->isolate(),
919
                                    current->replacement)).FromJust();
920
    naptr_record->Set(context,
921
                      order_symbol,
922
                      Integer::New(env->isolate(), current->order)).FromJust();
923
    naptr_record->Set(context,
924
                      preference_symbol,
925
                      Integer::New(env->isolate(),
926
                                   current->preference)).FromJust();
927
    if (need_type)
928
      naptr_record->Set(context, type_symbol, naptr_symbol).FromJust();
929
930
    ret->Set(context, i + offset, naptr_record).FromJust();
931
  }
932
933
  ares_free_data(naptr_start);
934
  return ARES_SUCCESS;
935
}
936
937
938
int ParseSoaReply(Environment* env,
939
                  unsigned char* buf,
940
                  int len,
941
                  Local<Object>* ret) {
942
  EscapableHandleScope handle_scope(env->isolate());
943
  auto context = env->context();
944
945
  /* Can't use ares_parse_soa_reply() here which can only parse single record */
946
  unsigned int ancount = cares_get_16bit(buf + 6);
947
  unsigned char* ptr = buf + NS_HFIXEDSZ;
948
  int rr_type, rr_len;
949
  char* name;
950
  char* rr_name;
951
  long temp_len;  // NOLINT(runtime/int)
952
  int status = ares_expand_name(ptr, buf, len, &name, &temp_len);
953
  if (status != ARES_SUCCESS) {
954
    /* returns EBADRESP in case of invalid input */
955
    return status == ARES_EBADNAME ? ARES_EBADRESP : status;
956
  }
957
958
  if (ptr + temp_len + NS_QFIXEDSZ > buf + len) {
959
    free(name);
960
    return ARES_EBADRESP;
961
  }
962
  ptr += temp_len + NS_QFIXEDSZ;
963
964
  for (unsigned int i = 0; i < ancount; i++) {
965
    status = ares_expand_name(ptr, buf, len, &rr_name, &temp_len);
966
967
    if (status != ARES_SUCCESS)
968
      break;
969
970
    ptr += temp_len;
971
    if (ptr + NS_RRFIXEDSZ > buf + len) {
972
      free(rr_name);
973
      status = ARES_EBADRESP;
974
      break;
975
    }
976
977
    rr_type = cares_get_16bit(ptr);
978
    rr_len = cares_get_16bit(ptr + 8);
979
    ptr += NS_RRFIXEDSZ;
980
981
    /* only need SOA */
982
    if (rr_type == ns_t_soa) {
983
      ares_soa_reply soa;
984
985
      status = ares_expand_name(ptr, buf, len, &soa.nsname, &temp_len);
986
      if (status != ARES_SUCCESS) {
987
        free(rr_name);
988
        break;
989
      }
990
      ptr += temp_len;
991
992
      status = ares_expand_name(ptr, buf, len, &soa.hostmaster, &temp_len);
993
      if (status != ARES_SUCCESS) {
994
        free(rr_name);
995
        free(soa.nsname);
996
        break;
997
      }
998
      ptr += temp_len;
999
1000
      if (ptr + 5 * 4 > buf + len) {
1001
        free(rr_name);
1002
        free(soa.nsname);
1003
        free(soa.hostmaster);
1004
        status = ARES_EBADRESP;
1005
        break;
1006
      }
1007
1008
      soa.serial = cares_get_32bit(ptr + 0 * 4);
1009
      soa.refresh = cares_get_32bit(ptr + 1 * 4);
1010
      soa.retry = cares_get_32bit(ptr + 2 * 4);
1011
      soa.expire = cares_get_32bit(ptr + 3 * 4);
1012
      soa.minttl = cares_get_32bit(ptr + 4 * 4);
1013
1014
      Local<Object> soa_record = Object::New(env->isolate());
1015
      soa_record->Set(context,
1016
                      env->nsname_string(),
1017
                      OneByteString(env->isolate(), soa.nsname)).FromJust();
1018
      soa_record->Set(context,
1019
                      env->hostmaster_string(),
1020
                      OneByteString(env->isolate(),
1021
                                    soa.hostmaster)).FromJust();
1022
      soa_record->Set(context,
1023
                      env->serial_string(),
1024
                      Integer::New(env->isolate(), soa.serial)).FromJust();
1025
      soa_record->Set(context,
1026
                      env->refresh_string(),
1027
                      Integer::New(env->isolate(), soa.refresh)).FromJust();
1028
      soa_record->Set(context,
1029
                      env->retry_string(),
1030
                      Integer::New(env->isolate(), soa.retry)).FromJust();
1031
      soa_record->Set(context,
1032
                      env->expire_string(),
1033
                      Integer::New(env->isolate(), soa.expire)).FromJust();
1034
      soa_record->Set(context,
1035
                      env->minttl_string(),
1036
                      Integer::New(env->isolate(), soa.minttl)).FromJust();
1037
      soa_record->Set(context,
1038
                      env->type_string(),
1039
                      env->dns_soa_string()).FromJust();
1040
1041
      free(soa.nsname);
1042
      free(soa.hostmaster);
1043
1044
      *ret = handle_scope.Escape(soa_record);
1045
      break;
1046
    }
1047
1048
    free(rr_name);
1049
    ptr += rr_len;
1050
  }
1051
1052
  free(name);
1053
1054
  if (status != ARES_SUCCESS) {
1055
    return status == ARES_EBADNAME ? ARES_EBADRESP : status;
1056
  }
1057
1058
  return ARES_SUCCESS;
1059
}
1060
1061
1062
class QueryAnyWrap: public QueryWrap {
1063
 public:
1064
  QueryAnyWrap(Environment* env, Local<Object> req_wrap_obj)
1065
    : QueryWrap(env, req_wrap_obj) {
1066
  }
1067
1068
  int Send(const char* name) override {
1069
    ares_query(env()->cares_channel(),
1070
               name,
1071
               ns_c_in,
1072
               ns_t_any,
1073
               Callback,
1074
               GetQueryArg());
1075
    return 0;
1076
  }
1077
1078
  size_t self_size() const override { return sizeof(*this); }
1079
1080
 protected:
1081
  void Parse(unsigned char* buf, int len) override {
1082
    HandleScope handle_scope(env()->isolate());
1083
    auto context = env()->context();
1084
    Context::Scope context_scope(context);
1085
1086
    Local<Array> ret = Array::New(env()->isolate());
1087
    int type, status, old_count;
1088
1089
    /* Parse A records or CNAME records */
1090
    ares_addrttl addrttls[256];
1091
    int naddrttls = arraysize(addrttls);
1092
1093
    type = ns_t_cname_or_a;
1094
    status = ParseGeneralReply(env(),
1095
                               buf,
1096
                               len,
1097
                               &type,
1098
                               ret,
1099
                               addrttls,
1100
                               &naddrttls);
1101
    int a_count = ret->Length();
1102
    if (status != ARES_SUCCESS && status != ARES_ENODATA) {
1103
      ParseError(status);
1104
      return;
1105
    }
1106
1107
    if (type == ns_t_a) {
1108
      CHECK_EQ(naddrttls, a_count);
1109
      for (int i = 0; i < a_count; i++) {
1110
        Local<Object> obj = Object::New(env()->isolate());
1111
        obj->Set(context, env()->address_string(), ret->Get(i)).FromJust();
1112
        obj->Set(context,
1113
                 env()->ttl_string(),
1114
                 Integer::New(env()->isolate(), addrttls[i].ttl)).FromJust();
1115
        obj->Set(context,
1116
                 env()->type_string(),
1117
                 env()->dns_a_string()).FromJust();
1118
        ret->Set(context, i, obj).FromJust();
1119
      }
1120
    } else {
1121
      for (int i = 0; i < a_count; i++) {
1122
        Local<Object> obj = Object::New(env()->isolate());
1123
        obj->Set(context, env()->value_string(), ret->Get(i)).FromJust();
1124
        obj->Set(context,
1125
                 env()->type_string(),
1126
                 env()->dns_cname_string()).FromJust();
1127
        ret->Set(context, i, obj).FromJust();
1128
      }
1129
    }
1130
1131
    /* Parse AAAA records */
1132
    ares_addr6ttl addr6ttls[256];
1133
    int naddr6ttls = arraysize(addr6ttls);
1134
1135
    type = ns_t_aaaa;
1136
    status = ParseGeneralReply(env(),
1137
                               buf,
1138
                               len,
1139
                               &type,
1140
                               ret,
1141
                               addr6ttls,
1142
                               &naddr6ttls);
1143
    int aaaa_count = ret->Length() - a_count;
1144
    if (status != ARES_SUCCESS && status != ARES_ENODATA) {
1145
      ParseError(status);
1146
      return;
1147
    }
1148
1149
    CHECK_EQ(aaaa_count, naddr6ttls);
1150
    for (uint32_t i = a_count; i < ret->Length(); i++) {
1151
      Local<Object> obj = Object::New(env()->isolate());
1152
      obj->Set(context, env()->address_string(), ret->Get(i)).FromJust();
1153
      obj->Set(context,
1154
               env()->ttl_string(),
1155
               Integer::New(env()->isolate(), addr6ttls[i].ttl)).FromJust();
1156
      obj->Set(context,
1157
               env()->type_string(),
1158
               env()->dns_aaaa_string()).FromJust();
1159
      ret->Set(context, i, obj).FromJust();
1160
    }
1161
1162
    /* Parse MX records */
1163
    status = ParseMxReply(env(), buf, len, ret, true);
1164
    if (status != ARES_SUCCESS && status != ARES_ENODATA) {
1165
      ParseError(status);
1166
      return;
1167
    }
1168
1169
    /* Parse NS records */
1170
    type = ns_t_ns;
1171
    old_count = ret->Length();
1172
    status = ParseGeneralReply(env(), buf, len, &type, ret);
1173
    if (status != ARES_SUCCESS && status != ARES_ENODATA) {
1174
      ParseError(status);
1175
      return;
1176
    }
1177
    for (uint32_t i = old_count; i < ret->Length(); i++) {
1178
      Local<Object> obj = Object::New(env()->isolate());
1179
      obj->Set(context, env()->value_string(), ret->Get(i)).FromJust();
1180
      obj->Set(context,
1181
               env()->type_string(),
1182
               env()->dns_ns_string()).FromJust();
1183
      ret->Set(context, i, obj).FromJust();
1184
    }
1185
1186
    /* Parse TXT records */
1187
    status = ParseTxtReply(env(), buf, len, ret, true);
1188
    if (status != ARES_SUCCESS && status != ARES_ENODATA) {
1189
      ParseError(status);
1190
      return;
1191
    }
1192
1193
    /* Parse SRV records */
1194
    status = ParseSrvReply(env(), buf, len, ret, true);
1195
    if (status != ARES_SUCCESS && status != ARES_ENODATA) {
1196
      return;
1197
    }
1198
1199
    /* Parse PTR records */
1200
    type = ns_t_ptr;
1201
    old_count = ret->Length();
1202
    status = ParseGeneralReply(env(), buf, len, &type, ret);
1203
    for (uint32_t i = old_count; i < ret->Length(); i++) {
1204
      Local<Object> obj = Object::New(env()->isolate());
1205
      obj->Set(context, env()->value_string(), ret->Get(i)).FromJust();
1206
      obj->Set(context,
1207
               env()->type_string(),
1208
               env()->dns_ptr_string()).FromJust();
1209
      ret->Set(context, i, obj).FromJust();
1210
    }
1211
1212
    /* Parse NAPTR records */
1213
    status = ParseNaptrReply(env(), buf, len, ret, true);
1214
    if (status != ARES_SUCCESS && status != ARES_ENODATA) {
1215
      ParseError(status);
1216
      return;
1217
    }
1218
1219
    /* Parse SOA records */
1220
    Local<Object> soa_record = Local<Object>();
1221
    status = ParseSoaReply(env(), buf, len, &soa_record);
1222
    if (status != ARES_SUCCESS && status != ARES_ENODATA) {
1223
      ParseError(status);
1224
      return;
1225
    }
1226
    if (!soa_record.IsEmpty())
1227
      ret->Set(context, ret->Length(), soa_record).FromJust();
1228
1229
    CallOnComplete(ret);
1230
  }
1231
};
1232
1233
1234
2
class QueryAWrap: public QueryWrap {
1235
 public:
1236
1
  QueryAWrap(Environment* env, Local<Object> req_wrap_obj)
1237
1
      : QueryWrap(env, req_wrap_obj) {
1238
1
  }
1239
1240
1
  int Send(const char* name) override {
1241
1
    AresQuery(env(), name, ns_c_in, ns_t_a, Callback, GetQueryArg());
1242
1
    return 0;
1243
  }
1244
1245
  size_t self_size() const override { return sizeof(*this); }
1246
1247
 protected:
1248
  void Parse(unsigned char* buf, int len) override {
1249
    HandleScope handle_scope(env()->isolate());
1250
    Context::Scope context_scope(env()->context());
1251
1252
    ares_addrttl addrttls[256];
1253
    int naddrttls = arraysize(addrttls), status;
1254
    Local<Array> ret = Array::New(env()->isolate());
1255
1256
    int type = ns_t_a;
1257
    status = ParseGeneralReply(env(),
1258
                               buf,
1259
                               len,
1260
                               &type,
1261
                               ret,
1262
                               addrttls,
1263
                               &naddrttls);
1264
    if (status != ARES_SUCCESS) {
1265
      ParseError(status);
1266
      return;
1267
    }
1268
1269
    Local<Array> ttls = AddrTTLToArray<ares_addrttl>(env(),
1270
                                                     addrttls,
1271
                                                     naddrttls);
1272
1273
    CallOnComplete(ret, ttls);
1274
  }
1275
};
1276
1277
1278
2
class QueryAaaaWrap: public QueryWrap {
1279
 public:
1280
1
  QueryAaaaWrap(Environment* env, Local<Object> req_wrap_obj)
1281
1
      : QueryWrap(env, req_wrap_obj) {
1282
1
  }
1283
1284
1
  int Send(const char* name) override {
1285
1
    AresQuery(env(),  name, ns_c_in, ns_t_aaaa, Callback, GetQueryArg());
1286
1
    return 0;
1287
  }
1288
1289
  size_t self_size() const override { return sizeof(*this); }
1290
1291
 protected:
1292
  void Parse(unsigned char* buf, int len) override {
1293
    HandleScope handle_scope(env()->isolate());
1294
    Context::Scope context_scope(env()->context());
1295
1296
    ares_addr6ttl addrttls[256];
1297
    int naddrttls = arraysize(addrttls), status;
1298
    Local<Array> ret = Array::New(env()->isolate());
1299
1300
    int type = ns_t_aaaa;
1301
    status = ParseGeneralReply(env(),
1302
                               buf,
1303
                               len,
1304
                               &type,
1305
                               ret,
1306
                               addrttls,
1307
                               &naddrttls);
1308
    if (status != ARES_SUCCESS) {
1309
      ParseError(status);
1310
      return;
1311
    }
1312
1313
    Local<Array> ttls = AddrTTLToArray<ares_addr6ttl>(env(),
1314
                                                      addrttls,
1315
                                                      naddrttls);
1316
1317
    CallOnComplete(ret, ttls);
1318
  }
1319
};
1320
1321
1322
class QueryCnameWrap: public QueryWrap {
1323
 public:
1324
  QueryCnameWrap(Environment* env, Local<Object> req_wrap_obj)
1325
      : QueryWrap(env, req_wrap_obj) {
1326
  }
1327
1328
  int Send(const char* name) override {
1329
    AresQuery(env(), name, ns_c_in, ns_t_cname, Callback, GetQueryArg());
1330
    return 0;
1331
  }
1332
1333
  size_t self_size() const override { return sizeof(*this); }
1334
1335
 protected:
1336
  void Parse(unsigned char* buf, int len) override {
1337
    HandleScope handle_scope(env()->isolate());
1338
    Context::Scope context_scope(env()->context());
1339
1340
    Local<Array> ret = Array::New(env()->isolate());
1341
    int type = ns_t_cname;
1342
    int status = ParseGeneralReply(env(), buf, len, &type, ret);
1343
    if (status != ARES_SUCCESS) {
1344
      ParseError(status);
1345
      return;
1346
    }
1347
1348
    this->CallOnComplete(ret);
1349
  }
1350
};
1351
1352
1353
class QueryMxWrap: public QueryWrap {
1354
 public:
1355
  QueryMxWrap(Environment* env, Local<Object> req_wrap_obj)
1356
      : QueryWrap(env, req_wrap_obj) {
1357
  }
1358
1359
  int Send(const char* name) override {
1360
    AresQuery(env(), name, ns_c_in, ns_t_mx, Callback, GetQueryArg());
1361
    return 0;
1362
  }
1363
1364
  size_t self_size() const override { return sizeof(*this); }
1365
1366
 protected:
1367
  void Parse(unsigned char* buf, int len) override {
1368
    HandleScope handle_scope(env()->isolate());
1369
    Context::Scope context_scope(env()->context());
1370
1371
    Local<Array> mx_records = Array::New(env()->isolate());
1372
    int status = ParseMxReply(env(), buf, len, mx_records);
1373
1374
    if (status != ARES_SUCCESS) {
1375
      ParseError(status);
1376
      return;
1377
    }
1378
1379
    this->CallOnComplete(mx_records);
1380
  }
1381
};
1382
1383
1384
class QueryNsWrap: public QueryWrap {
1385
 public:
1386
  QueryNsWrap(Environment* env, Local<Object> req_wrap_obj)
1387
      : QueryWrap(env, req_wrap_obj) {
1388
  }
1389
1390
  int Send(const char* name) override {
1391
    AresQuery(env(), name, ns_c_in, ns_t_ns, Callback, GetQueryArg());
1392
    return 0;
1393
  }
1394
1395
  size_t self_size() const override { return sizeof(*this); }
1396
1397
 protected:
1398
  void Parse(unsigned char* buf, int len) override {
1399
    HandleScope handle_scope(env()->isolate());
1400
    Context::Scope context_scope(env()->context());
1401
1402
    int type = ns_t_ns;
1403
    Local<Array> names = Array::New(env()->isolate());
1404
    int status = ParseGeneralReply(env(), buf, len, &type, names);
1405
    if (status != ARES_SUCCESS) {
1406
      ParseError(status);
1407
      return;
1408
    }
1409
1410
    this->CallOnComplete(names);
1411
  }
1412
};
1413
1414
1415
class QueryTxtWrap: public QueryWrap {
1416
 public:
1417
  QueryTxtWrap(Environment* env, Local<Object> req_wrap_obj)
1418
      : QueryWrap(env, req_wrap_obj) {
1419
  }
1420
1421
  int Send(const char* name) override {
1422
    AresQuery(env(), name, ns_c_in, ns_t_txt, Callback, GetQueryArg());
1423
    return 0;
1424
  }
1425
1426
  size_t self_size() const override { return sizeof(*this); }
1427
1428
 protected:
1429
  void Parse(unsigned char* buf, int len) override {
1430
    HandleScope handle_scope(env()->isolate());
1431
    Context::Scope context_scope(env()->context());
1432
1433
    Local<Array> txt_records = Array::New(env()->isolate());
1434
    int status = ParseTxtReply(env(), buf, len, txt_records);
1435
    if (status != ARES_SUCCESS) {
1436
      ParseError(status);
1437
      return;
1438
    }
1439
1440
    this->CallOnComplete(txt_records);
1441
  }
1442
};
1443
1444
1445
class QuerySrvWrap: public QueryWrap {
1446
 public:
1447
  explicit QuerySrvWrap(Environment* env, Local<Object> req_wrap_obj)
1448
      : QueryWrap(env, req_wrap_obj) {
1449
  }
1450
1451
  int Send(const char* name) override {
1452
    AresQuery(env(), name, ns_c_in, ns_t_srv, Callback, GetQueryArg());
1453
    return 0;
1454
  }
1455
1456
  size_t self_size() const override { return sizeof(*this); }
1457
1458
 protected:
1459
  void Parse(unsigned char* buf, int len) override {
1460
    HandleScope handle_scope(env()->isolate());
1461
    Context::Scope context_scope(env()->context());
1462
1463
    Local<Array> srv_records = Array::New(env()->isolate());
1464
    int status = ParseSrvReply(env(), buf, len, srv_records);
1465
    if (status != ARES_SUCCESS) {
1466
      ParseError(status);
1467
      return;
1468
    }
1469
1470
    this->CallOnComplete(srv_records);
1471
  }
1472
};
1473
1474
class QueryPtrWrap: public QueryWrap {
1475
 public:
1476
  explicit QueryPtrWrap(Environment* env, Local<Object> req_wrap_obj)
1477
      : QueryWrap(env, req_wrap_obj) {
1478
  }
1479
1480
  int Send(const char* name) override {
1481
    AresQuery(env(), name, ns_c_in, ns_t_ptr, Callback, GetQueryArg());
1482
    return 0;
1483
  }
1484
1485
  size_t self_size() const override { return sizeof(*this); }
1486
1487
 protected:
1488
  void Parse(unsigned char* buf, int len) override {
1489
    HandleScope handle_scope(env()->isolate());
1490
    Context::Scope context_scope(env()->context());
1491
1492
    int type = ns_t_ptr;
1493
    Local<Array> aliases = Array::New(env()->isolate());
1494
1495
    int status = ParseGeneralReply(env(), buf, len, &type, aliases);
1496
    if (status != ARES_SUCCESS) {
1497
      ParseError(status);
1498
      return;
1499
    }
1500
1501
    this->CallOnComplete(aliases);
1502
  }
1503
};
1504
1505
class QueryNaptrWrap: public QueryWrap {
1506
 public:
1507
  explicit QueryNaptrWrap(Environment* env, Local<Object> req_wrap_obj)
1508
      : QueryWrap(env, req_wrap_obj) {
1509
  }
1510
1511
  int Send(const char* name) override {
1512
    AresQuery(env(), name, ns_c_in, ns_t_naptr, Callback, GetQueryArg());
1513
    return 0;
1514
  }
1515
1516
  size_t self_size() const override { return sizeof(*this); }
1517
1518
 protected:
1519
  void Parse(unsigned char* buf, int len) override {
1520
    HandleScope handle_scope(env()->isolate());
1521
    Context::Scope context_scope(env()->context());
1522
1523
    Local<Array> naptr_records = Array::New(env()->isolate());
1524
    int status = ParseNaptrReply(env(), buf, len, naptr_records);
1525
    if (status != ARES_SUCCESS) {
1526
      ParseError(status);
1527
      return;
1528
    }
1529
1530
    this->CallOnComplete(naptr_records);
1531
  }
1532
};
1533
1534
1535
class QuerySoaWrap: public QueryWrap {
1536
 public:
1537
  QuerySoaWrap(Environment* env, Local<Object> req_wrap_obj)
1538
      : QueryWrap(env, req_wrap_obj) {
1539
  }
1540
1541
  int Send(const char* name) override {
1542
    AresQuery(env(), name, ns_c_in, ns_t_soa, Callback, GetQueryArg());
1543
    return 0;
1544
  }
1545
1546
  size_t self_size() const override { return sizeof(*this); }
1547
1548
 protected:
1549
  void Parse(unsigned char* buf, int len) override {
1550
    HandleScope handle_scope(env()->isolate());
1551
    auto context = env()->context();
1552
    Context::Scope context_scope(context);
1553
1554
    ares_soa_reply* soa_out;
1555
    int status = ares_parse_soa_reply(buf, len, &soa_out);
1556
1557
    if (status != ARES_SUCCESS) {
1558
      ParseError(status);
1559
      return;
1560
    }
1561
1562
    Local<Object> soa_record = Object::New(env()->isolate());
1563
1564
    soa_record->Set(context,
1565
                    env()->nsname_string(),
1566
                    OneByteString(env()->isolate(),
1567
                                  soa_out->nsname)).FromJust();
1568
    soa_record->Set(context,
1569
                    env()->hostmaster_string(),
1570
                    OneByteString(env()->isolate(),
1571
                                  soa_out->hostmaster)).FromJust();
1572
    soa_record->Set(context,
1573
                    env()->serial_string(),
1574
                    Integer::New(env()->isolate(), soa_out->serial)).FromJust();
1575
    soa_record->Set(context,
1576
                    env()->refresh_string(),
1577
                    Integer::New(env()->isolate(),
1578
                                 soa_out->refresh)).FromJust();
1579
    soa_record->Set(context,
1580
                    env()->retry_string(),
1581
                    Integer::New(env()->isolate(), soa_out->retry)).FromJust();
1582
    soa_record->Set(context,
1583
                    env()->expire_string(),
1584
                    Integer::New(env()->isolate(), soa_out->expire)).FromJust();
1585
    soa_record->Set(context,
1586
                    env()->minttl_string(),
1587
                    Integer::New(env()->isolate(), soa_out->minttl)).FromJust();
1588
1589
    ares_free_data(soa_out);
1590
1591
    this->CallOnComplete(soa_record);
1592
  }
1593
};
1594
1595
1596
2
class GetHostByAddrWrap: public QueryWrap {
1597
 public:
1598
1
  explicit GetHostByAddrWrap(Environment* env, Local<Object> req_wrap_obj)
1599
1
      : QueryWrap(env, req_wrap_obj) {
1600
1
  }
1601
1602
1
  int Send(const char* name) override {
1603
    int length, family;
1604
    char address_buffer[sizeof(struct in6_addr)];
1605
1606
1
    if (uv_inet_pton(AF_INET, name, &address_buffer) == 0) {
1607
1
      length = sizeof(struct in_addr);
1608
1
      family = AF_INET;
1609
    } else if (uv_inet_pton(AF_INET6, name, &address_buffer) == 0) {
1610
      length = sizeof(struct in6_addr);
1611
      family = AF_INET6;
1612
    } else {
1613
      return UV_EINVAL;  // So errnoException() reports a proper error.
1614
    }
1615
1616
    ares_gethostbyaddr(env()->cares_channel(),
1617
                       address_buffer,
1618
                       length,
1619
                       family,
1620
                       Callback,
1621
1
                       GetQueryArg());
1622
1
    return 0;
1623
  }
1624
1625
  size_t self_size() const override { return sizeof(*this); }
1626
1627
 protected:
1628
1
  void Parse(struct hostent* host) override {
1629
1
    HandleScope handle_scope(env()->isolate());
1630
1
    Context::Scope context_scope(env()->context());
1631
3
    this->CallOnComplete(HostentToNames(env(), host));
1632
1
  }
1633
};
1634
1635
1636
class GetHostByNameWrap: public QueryWrap {
1637
 public:
1638
  explicit GetHostByNameWrap(Environment* env, Local<Object> req_wrap_obj)
1639
      : QueryWrap(env, req_wrap_obj) {
1640
  }
1641
1642
  int Send(const char* name, int family) override {
1643
    ares_gethostbyname(env()->cares_channel(),
1644
                       name,
1645
                       family,
1646
                       Callback,
1647
                       GetQueryArg());
1648
    return 0;
1649
  }
1650
1651
 protected:
1652
  void Parse(struct hostent* host) override {
1653
    HandleScope scope(env()->isolate());
1654
1655
    Local<Array> addresses = HostentToAddresses(env(), host);
1656
    Local<Integer> family = Integer::New(env()->isolate(), host->h_addrtype);
1657
1658
    this->CallOnComplete(addresses, family);
1659
  }
1660
};
1661
1662
1663
template <class Wrap>
1664
3
static void Query(const FunctionCallbackInfo<Value>& args) {
1665
3
  Environment* env = Environment::GetCurrent(args);
1666
1667






3
  CHECK_EQ(false, args.IsConstructCall());
1668






6
  CHECK(args[0]->IsObject());
1669






9
  CHECK(args[1]->IsString());
1670
1671
6
  Local<Object> req_wrap_obj = args[0].As<Object>();
1672
6
  Local<String> string = args[1].As<String>();
1673
3
  Wrap* wrap = new Wrap(env, req_wrap_obj);
1674
1675
3
  node::Utf8Value name(env->isolate(), string);
1676
3
  int err = wrap->Send(*name);
1677






3
  if (err)
1678
    delete wrap;
1679
1680
6
  args.GetReturnValue().Set(err);
1681
3
}
1682
1683
1684
1967
void AfterGetAddrInfo(uv_getaddrinfo_t* req, int status, struct addrinfo* res) {
1685
1967
  GetAddrInfoReqWrap* req_wrap = static_cast<GetAddrInfoReqWrap*>(req->data);
1686
1967
  Environment* env = req_wrap->env();
1687
1688
1967
  HandleScope handle_scope(env->isolate());
1689
1967
  Context::Scope context_scope(env->context());
1690
1691
  Local<Value> argv[] = {
1692
    Integer::New(env->isolate(), status),
1693
    Null(env->isolate())
1694
5901
  };
1695
1696
1967
  if (status == 0) {
1697
    // Success
1698
    struct addrinfo *address;
1699
1960
    int n = 0;
1700
1701
    // Create the response array.
1702
1960
    Local<Array> results = Array::New(env->isolate());
1703
1704
    char ip[INET6_ADDRSTRLEN];
1705
    const char *addr;
1706
1707
    // Iterate over the IPv4 responses again this time creating javascript
1708
    // strings for each IP and filling the results array.
1709
1960
    address = res;
1710
7834
    while (address) {
1711
3914
      CHECK_EQ(address->ai_socktype, SOCK_STREAM);
1712
1713
      // Ignore random ai_family types.
1714
3914
      if (address->ai_family == AF_INET) {
1715
        // Juggle pointers
1716
        addr = reinterpret_cast<char*>(&(reinterpret_cast<struct sockaddr_in*>(
1717
1965
            address->ai_addr)->sin_addr));
1718
        int err = uv_inet_ntop(address->ai_family,
1719
                               addr,
1720
                               ip,
1721
1965
                               INET6_ADDRSTRLEN);
1722
1965
        if (err)
1723
          continue;
1724
1725
        // Create JavaScript string
1726
1965
        Local<String> s = OneByteString(env->isolate(), ip);
1727
3930
        results->Set(n, s);
1728
1965
        n++;
1729
      }
1730
1731
      // Increment
1732
3914
      address = address->ai_next;
1733
    }
1734
1735
    // Iterate over the IPv6 responses putting them in the array.
1736
1960
    address = res;
1737
7834
    while (address) {
1738
3914
      CHECK_EQ(address->ai_socktype, SOCK_STREAM);
1739
1740
      // Ignore random ai_family types.
1741
3914
      if (address->ai_family == AF_INET6) {
1742
        // Juggle pointers
1743
        addr = reinterpret_cast<char*>(&(reinterpret_cast<struct sockaddr_in6*>(
1744
1949
            address->ai_addr)->sin6_addr));
1745
        int err = uv_inet_ntop(address->ai_family,
1746
                               addr,
1747
                               ip,
1748
1949
                               INET6_ADDRSTRLEN);
1749
1949
        if (err)
1750
          continue;
1751
1752
        // Create JavaScript string
1753
1949
        Local<String> s = OneByteString(env->isolate(), ip);
1754
3898
        results->Set(n, s);
1755
1949
        n++;
1756
      }
1757
1758
      // Increment
1759
3914
      address = address->ai_next;
1760
    }
1761
1762
    // No responses were found to return
1763
1960
    if (n == 0) {
1764
      argv[0] = Integer::New(env->isolate(), UV_EAI_NODATA);
1765
    }
1766
1767
1960
    argv[1] = results;
1768
  }
1769
1770
1967
  uv_freeaddrinfo(res);
1771
1772
  // Make the callback into JavaScript
1773
1967
  req_wrap->MakeCallback(env->oncomplete_string(), arraysize(argv), argv);
1774
1775
3934
  delete req_wrap;
1776
1967
}
1777
1778
1779
2
void AfterGetNameInfo(uv_getnameinfo_t* req,
1780
                      int status,
1781
                      const char* hostname,
1782
                      const char* service) {
1783
2
  GetNameInfoReqWrap* req_wrap = static_cast<GetNameInfoReqWrap*>(req->data);
1784
2
  Environment* env = req_wrap->env();
1785
1786
2
  HandleScope handle_scope(env->isolate());
1787
2
  Context::Scope context_scope(env->context());
1788
1789
  Local<Value> argv[] = {
1790
    Integer::New(env->isolate(), status),
1791
    Null(env->isolate()),
1792
    Null(env->isolate())
1793
8
  };
1794
1795
2
  if (status == 0) {
1796
    // Success
1797
2
    Local<String> js_hostname = OneByteString(env->isolate(), hostname);
1798
2
    Local<String> js_service = OneByteString(env->isolate(), service);
1799
2
    argv[1] = js_hostname;
1800
2
    argv[2] = js_service;
1801
  }
1802
1803
  // Make the callback into JavaScript
1804
2
  req_wrap->MakeCallback(env->oncomplete_string(), arraysize(argv), argv);
1805
1806
4
  delete req_wrap;
1807
2
}
1808
1809
1810
4729
void IsIP(const FunctionCallbackInfo<Value>& args) {
1811
4729
  node::Utf8Value ip(args.GetIsolate(), args[0]);
1812
  char address_buffer[sizeof(struct in6_addr)];
1813
1814
4729
  int rc = 0;
1815
4729
  if (uv_inet_pton(AF_INET, *ip, &address_buffer) == 0)
1816
656
    rc = 4;
1817
4073
  else if (uv_inet_pton(AF_INET6, *ip, &address_buffer) == 0)
1818
41
    rc = 6;
1819
1820
9458
  args.GetReturnValue().Set(rc);
1821
4729
}
1822
1823
12
void IsIPv4(const FunctionCallbackInfo<Value>& args) {
1824
12
  node::Utf8Value ip(args.GetIsolate(), args[0]);
1825
  char address_buffer[sizeof(struct in_addr)];
1826
1827
12
  if (uv_inet_pton(AF_INET, *ip, &address_buffer) == 0) {
1828
4
    args.GetReturnValue().Set(true);
1829
  } else {
1830
20
    args.GetReturnValue().Set(false);
1831
12
  }
1832
12
}
1833
1834
12
void IsIPv6(const FunctionCallbackInfo<Value>& args) {
1835
12
  node::Utf8Value ip(args.GetIsolate(), args[0]);
1836
  char address_buffer[sizeof(struct in6_addr)];
1837
1838
12
  if (uv_inet_pton(AF_INET6, *ip, &address_buffer) == 0) {
1839
4
    args.GetReturnValue().Set(true);
1840
  } else {
1841
20
    args.GetReturnValue().Set(false);
1842
12
  }
1843
12
}
1844
1845
1968
void GetAddrInfo(const FunctionCallbackInfo<Value>& args) {
1846
1968
  Environment* env = Environment::GetCurrent(args);
1847
1848
3936
  CHECK(args[0]->IsObject());
1849
5904
  CHECK(args[1]->IsString());
1850
3936
  CHECK(args[2]->IsInt32());
1851
3936
  Local<Object> req_wrap_obj = args[0].As<Object>();
1852
1968
  node::Utf8Value hostname(env->isolate(), args[1]);
1853
1854

7872
  int32_t flags = (args[3]->IsInt32()) ? args[3]->Int32Value() : 0;
1855
  int family;
1856
1857

3936
  switch (args[2]->Int32Value()) {
1858
  case 0:
1859
1952
    family = AF_UNSPEC;
1860
1952
    break;
1861
  case 4:
1862
11
    family = AF_INET;
1863
11
    break;
1864
  case 6:
1865
5
    family = AF_INET6;
1866
5
    break;
1867
  default:
1868
    CHECK(0 && "bad address family");
1869
  }
1870
1871
1968
  GetAddrInfoReqWrap* req_wrap = new GetAddrInfoReqWrap(env, req_wrap_obj);
1872
1873
  struct addrinfo hints;
1874
1968
  memset(&hints, 0, sizeof(struct addrinfo));
1875
1968
  hints.ai_family = family;
1876
1968
  hints.ai_socktype = SOCK_STREAM;
1877
1968
  hints.ai_flags = flags;
1878
1879
  int err = uv_getaddrinfo(env->event_loop(),
1880
                           req_wrap->req(),
1881
                           AfterGetAddrInfo,
1882
1968
                           *hostname,
1883
                           nullptr,
1884
1968
                           &hints);
1885
1968
  req_wrap->Dispatched();
1886
1968
  if (err)
1887
    delete req_wrap;
1888
1889
3936
  args.GetReturnValue().Set(err);
1890
1968
}
1891
1892
1893
2
void GetNameInfo(const FunctionCallbackInfo<Value>& args) {
1894
2
  Environment* env = Environment::GetCurrent(args);
1895
1896
4
  CHECK(args[0]->IsObject());
1897
6
  CHECK(args[1]->IsString());
1898
4
  CHECK(args[2]->IsUint32());
1899
4
  Local<Object> req_wrap_obj = args[0].As<Object>();
1900
2
  node::Utf8Value ip(env->isolate(), args[1]);
1901
4
  const unsigned port = args[2]->Uint32Value();
1902
  struct sockaddr_storage addr;
1903
1904

2
  CHECK(uv_ip4_addr(*ip, port, reinterpret_cast<sockaddr_in*>(&addr)) == 0 ||
1905
        uv_ip6_addr(*ip, port, reinterpret_cast<sockaddr_in6*>(&addr)) == 0);
1906
1907
2
  GetNameInfoReqWrap* req_wrap = new GetNameInfoReqWrap(env, req_wrap_obj);
1908
1909
  int err = uv_getnameinfo(env->event_loop(),
1910
                           req_wrap->req(),
1911
                           AfterGetNameInfo,
1912
                           (struct sockaddr*)&addr,
1913
2
                           NI_NAMEREQD);
1914
2
  req_wrap->Dispatched();
1915
2
  if (err)
1916
    delete req_wrap;
1917
1918
4
  args.GetReturnValue().Set(err);
1919
2
}
1920
1921
1922
15
void GetServers(const FunctionCallbackInfo<Value>& args) {
1923
15
  Environment* env = Environment::GetCurrent(args);
1924
1925
15
  Local<Array> server_array = Array::New(env->isolate());
1926
1927
  ares_addr_node* servers;
1928
1929
15
  int r = ares_get_servers(env->cares_channel(), &servers);
1930
15
  CHECK_EQ(r, ARES_SUCCESS);
1931
1932
15
  ares_addr_node* cur = servers;
1933
1934
46
  for (uint32_t i = 0; cur != nullptr; ++i, cur = cur->next) {
1935
    char ip[INET6_ADDRSTRLEN];
1936
1937
31
    const void* caddr = static_cast<const void*>(&cur->addr);
1938
31
    int err = uv_inet_ntop(cur->family, caddr, ip, sizeof(ip));
1939
31
    CHECK_EQ(err, 0);
1940
1941
31
    Local<String> addr = OneByteString(env->isolate(), ip);
1942
31
    server_array->Set(i, addr);
1943
  }
1944
1945
15
  ares_free_data(servers);
1946
1947
30
  args.GetReturnValue().Set(server_array);
1948
15
}
1949
1950
1951
7
void SetServers(const FunctionCallbackInfo<Value>& args) {
1952
7
  Environment* env = Environment::GetCurrent(args);
1953
1954
14
  CHECK(args[0]->IsArray());
1955
1956
7
  Local<Array> arr = Local<Array>::Cast(args[0]);
1957
1958
7
  uint32_t len = arr->Length();
1959
1960
7
  if (len == 0) {
1961
1
    int rv = ares_set_servers(env->cares_channel(), nullptr);
1962
9
    return args.GetReturnValue().Set(rv);
1963
  }
1964
1965
6
  ares_addr_node* servers = new ares_addr_node[len];
1966
6
  ares_addr_node* last = nullptr;
1967
1968
  int err;
1969
1970
20
  for (uint32_t i = 0; i < len; i++) {
1971
28
    CHECK(arr->Get(i)->IsArray());
1972
1973
28
    Local<Array> elm = Local<Array>::Cast(arr->Get(i));
1974
1975
28
    CHECK(elm->Get(0)->Int32Value());
1976
42
    CHECK(elm->Get(1)->IsString());
1977
1978
28
    int fam = elm->Get(0)->Int32Value();
1979
14
    node::Utf8Value ip(env->isolate(), elm->Get(1));
1980
1981
14
    ares_addr_node* cur = &servers[i];
1982
1983
14
    switch (fam) {
1984
      case 4:
1985
9
        cur->family = AF_INET;
1986
9
        err = uv_inet_pton(AF_INET, *ip, &cur->addr);
1987
9
        break;
1988
      case 6:
1989
5
        cur->family = AF_INET6;
1990
5
        err = uv_inet_pton(AF_INET6, *ip, &cur->addr);
1991
5
        break;
1992
      default:
1993
        CHECK(0 && "Bad address family.");
1994
    }
1995
1996
14
    if (err)
1997
      break;
1998
1999
14
    cur->next = nullptr;
2000
2001
14
    if (last != nullptr)
2002
8
      last->next = cur;
2003
2004
14
    last = cur;
2005
14
  }
2006
2007
6
  if (err == 0)
2008
6
    err = ares_set_servers(env->cares_channel(), &servers[0]);
2009
  else
2010
    err = ARES_EBADSTR;
2011
2012
6
  delete[] servers;
2013
2014
6
  if (err == ARES_SUCCESS)
2015
6
    env->set_cares_is_servers_default(false);
2016
2017
12
  args.GetReturnValue().Set(err);
2018
}
2019
2020
2021
void StrError(const FunctionCallbackInfo<Value>& args) {
2022
  Environment* env = Environment::GetCurrent(args);
2023
  const char* errmsg = ares_strerror(args[0]->Int32Value());
2024
  args.GetReturnValue().Set(OneByteString(env->isolate(), errmsg));
2025
}
2026
2027
2028
void CaresTimerCloseCb(uv_handle_t* handle) {
2029
  Environment* env = Environment::from_cares_timer_handle(
2030
      reinterpret_cast<uv_timer_t*>(handle));
2031
  env->FinishHandleCleanup(handle);
2032
}
2033
2034
2035
void CaresTimerClose(Environment* env,
2036
                     uv_handle_t* handle,
2037
                     void* arg) {
2038
  uv_close(handle, CaresTimerCloseCb);
2039
}
2040
2041
2042
2319
void Initialize(Local<Object> target,
2043
                Local<Value> unused,
2044
                Local<Context> context) {
2045
2319
  Environment* env = Environment::GetCurrent(context);
2046
2047
2319
  int r = ares_library_init(ARES_LIB_INIT_ALL);
2048
2319
  if (r != ARES_SUCCESS)
2049
2319
    return env->ThrowError(ToErrorCodeString(r));
2050
2051
2319
  SetupCaresChannel(env);
2052
2053
  /* Initialize the timeout timer. The timer won't be started until the */
2054
  /* first socket is opened. */
2055
2319
  uv_timer_init(env->event_loop(), env->cares_timer_handle());
2056
  env->RegisterHandleCleanup(
2057
2319
      reinterpret_cast<uv_handle_t*>(env->cares_timer_handle()),
2058
      CaresTimerClose,
2059
2319
      nullptr);
2060
2061
2319
  env->SetMethod(target, "queryAny", Query<QueryAnyWrap>);
2062
2319
  env->SetMethod(target, "queryA", Query<QueryAWrap>);
2063
2319
  env->SetMethod(target, "queryAaaa", Query<QueryAaaaWrap>);
2064
2319
  env->SetMethod(target, "queryCname", Query<QueryCnameWrap>);
2065
2319
  env->SetMethod(target, "queryMx", Query<QueryMxWrap>);
2066
2319
  env->SetMethod(target, "queryNs", Query<QueryNsWrap>);
2067
2319
  env->SetMethod(target, "queryTxt", Query<QueryTxtWrap>);
2068
2319
  env->SetMethod(target, "querySrv", Query<QuerySrvWrap>);
2069
2319
  env->SetMethod(target, "queryPtr", Query<QueryPtrWrap>);
2070
2319
  env->SetMethod(target, "queryNaptr", Query<QueryNaptrWrap>);
2071
2319
  env->SetMethod(target, "querySoa", Query<QuerySoaWrap>);
2072
2319
  env->SetMethod(target, "getHostByAddr", Query<GetHostByAddrWrap>);
2073
2074
2319
  env->SetMethod(target, "getaddrinfo", GetAddrInfo);
2075
2319
  env->SetMethod(target, "getnameinfo", GetNameInfo);
2076
2319
  env->SetMethod(target, "isIP", IsIP);
2077
2319
  env->SetMethod(target, "isIPv4", IsIPv4);
2078
2319
  env->SetMethod(target, "isIPv6", IsIPv6);
2079
2080
2319
  env->SetMethod(target, "strerror", StrError);
2081
2319
  env->SetMethod(target, "getServers", GetServers);
2082
2319
  env->SetMethod(target, "setServers", SetServers);
2083
2084
  target->Set(FIXED_ONE_BYTE_STRING(env->isolate(), "AF_INET"),
2085
6957
              Integer::New(env->isolate(), AF_INET));
2086
  target->Set(FIXED_ONE_BYTE_STRING(env->isolate(), "AF_INET6"),
2087
6957
              Integer::New(env->isolate(), AF_INET6));
2088
  target->Set(FIXED_ONE_BYTE_STRING(env->isolate(), "AF_UNSPEC"),
2089
6957
              Integer::New(env->isolate(), AF_UNSPEC));
2090
  target->Set(FIXED_ONE_BYTE_STRING(env->isolate(), "AI_ADDRCONFIG"),
2091
6957
              Integer::New(env->isolate(), AI_ADDRCONFIG));
2092
  target->Set(FIXED_ONE_BYTE_STRING(env->isolate(), "AI_V4MAPPED"),
2093
6957
              Integer::New(env->isolate(), AI_V4MAPPED));
2094
2095
  auto is_construct_call_callback =
2096
10911
      [](const FunctionCallbackInfo<Value>& args) {
2097
1977
    CHECK(args.IsConstructCall());
2098
1977
    ClearWrap(args.This());
2099
10911
  };
2100
  Local<FunctionTemplate> aiw =
2101
2319
      FunctionTemplate::New(env->isolate(), is_construct_call_callback);
2102
4638
  aiw->InstanceTemplate()->SetInternalFieldCount(1);
2103
2319
  env->SetProtoMethod(aiw, "getAsyncId", AsyncWrap::GetAsyncId);
2104
  aiw->SetClassName(
2105
4638
      FIXED_ONE_BYTE_STRING(env->isolate(), "GetAddrInfoReqWrap"));
2106
  target->Set(FIXED_ONE_BYTE_STRING(env->isolate(), "GetAddrInfoReqWrap"),
2107
6957
              aiw->GetFunction());
2108
2109
  Local<FunctionTemplate> niw =
2110
2319
      FunctionTemplate::New(env->isolate(), is_construct_call_callback);
2111
4638
  niw->InstanceTemplate()->SetInternalFieldCount(1);
2112
2319
  env->SetProtoMethod(niw, "getAsyncId", AsyncWrap::GetAsyncId);
2113
  niw->SetClassName(
2114
4638
      FIXED_ONE_BYTE_STRING(env->isolate(), "GetNameInfoReqWrap"));
2115
  target->Set(FIXED_ONE_BYTE_STRING(env->isolate(), "GetNameInfoReqWrap"),
2116
6957
              niw->GetFunction());
2117
2118
  Local<FunctionTemplate> qrw =
2119
2319
      FunctionTemplate::New(env->isolate(), is_construct_call_callback);
2120
4638
  qrw->InstanceTemplate()->SetInternalFieldCount(1);
2121
2319
  env->SetProtoMethod(qrw, "getAsyncId", AsyncWrap::GetAsyncId);
2122
  qrw->SetClassName(
2123
4638
      FIXED_ONE_BYTE_STRING(env->isolate(), "QueryReqWrap"));
2124
  target->Set(FIXED_ONE_BYTE_STRING(env->isolate(), "QueryReqWrap"),
2125
6957
              qrw->GetFunction());
2126
}
2127
2128
}  // anonymous namespace
2129
}  // namespace cares_wrap
2130
}  // namespace node
2131
2132
2441
NODE_MODULE_CONTEXT_AWARE_BUILTIN(cares_wrap, node::cares_wrap::Initialize)