GCC Code Coverage Report
Directory: ../src/ Exec Total Coverage
File: /home/node-core-coverage/node-core-coverage/workdir/node/src/cares_wrap.cc Lines: 379 690 54.9 %
Date: 2016-07-23 Branches: 122 512 23.8 %

Line Exec Source
1
#define CARES_STATICLIB
2
#include "ares.h"
3
#include "async-wrap.h"
4
#include "async-wrap-inl.h"
5
#include "env.h"
6
#include "env-inl.h"
7
#include "node.h"
8
#include "req-wrap.h"
9
#include "req-wrap-inl.h"
10
#include "tree.h"
11
#include "util.h"
12
#include "util-inl.h"
13
#include "uv.h"
14
15
#include <errno.h>
16
#include <stdlib.h>
17
#include <string.h>
18
19
#if defined(__ANDROID__) || \
20
    defined(__MINGW32__) || \
21
    defined(__OpenBSD__) || \
22
    defined(_MSC_VER)
23
24
# include <nameser.h>
25
#else
26
# include <arpa/nameser.h>
27
#endif
28
29
#if defined(__OpenBSD__)
30
# define AI_V4MAPPED 0
31
#endif
32
33
namespace node {
34
namespace cares_wrap {
35
36
using v8::Array;
37
using v8::Context;
38
using v8::EscapableHandleScope;
39
using v8::Function;
40
using v8::FunctionCallbackInfo;
41
using v8::FunctionTemplate;
42
using v8::HandleScope;
43
using v8::Integer;
44
using v8::Local;
45
using v8::Null;
46
using v8::Object;
47
using v8::String;
48
using v8::Value;
49
50
51
1917
class GetAddrInfoReqWrap : public ReqWrap<uv_getaddrinfo_t> {
52
 public:
53
  GetAddrInfoReqWrap(Environment* env, Local<Object> req_wrap_obj);
54
55
  size_t self_size() const override { return sizeof(*this); }
56
};
57
58
1918
GetAddrInfoReqWrap::GetAddrInfoReqWrap(Environment* env,
59
                                       Local<Object> req_wrap_obj)
60
1918
    : ReqWrap(env, req_wrap_obj, AsyncWrap::PROVIDER_GETADDRINFOREQWRAP) {
61
1918
  Wrap(req_wrap_obj, this);
62
1918
}
63
64
65
1919
static void NewGetAddrInfoReqWrap(const FunctionCallbackInfo<Value>& args) {
66
1919
  CHECK(args.IsConstructCall());
67
1919
}
68
69
70
3
class GetNameInfoReqWrap : public ReqWrap<uv_getnameinfo_t> {
71
 public:
72
  GetNameInfoReqWrap(Environment* env, Local<Object> req_wrap_obj);
73
74
  size_t self_size() const override { return sizeof(*this); }
75
};
76
77
3
GetNameInfoReqWrap::GetNameInfoReqWrap(Environment* env,
78
                                       Local<Object> req_wrap_obj)
79
3
    : ReqWrap(env, req_wrap_obj, AsyncWrap::PROVIDER_GETNAMEINFOREQWRAP) {
80
3
  Wrap(req_wrap_obj, this);
81
3
}
82
83
84
3
static void NewGetNameInfoReqWrap(const FunctionCallbackInfo<Value>& args) {
85
3
  CHECK(args.IsConstructCall());
86
3
}
87
88
89
3
static void NewQueryReqWrap(const FunctionCallbackInfo<Value>& args) {
90
3
  CHECK(args.IsConstructCall());
91
3
}
92
93
94
static int cmp_ares_tasks(const node_ares_task* a, const node_ares_task* b) {
95
2
  if (a->sock < b->sock)
96
    return -1;
97
2
  if (a->sock > b->sock)
98
    return 1;
99
  return 0;
100
}
101
102
103
14
RB_GENERATE_STATIC(node_ares_task_list, node_ares_task, node, cmp_ares_tasks)
104
105
106
107
/* This is called once per second by loop->timer. It is used to constantly */
108
/* call back into c-ares for possibly processing timeouts. */
109
static void ares_timeout(uv_timer_t* handle) {
110
  Environment* env = Environment::from_cares_timer_handle(handle);
111
  CHECK_EQ(false, RB_EMPTY(env->cares_task_list()));
112
  ares_process_fd(env->cares_channel(), ARES_SOCKET_BAD, ARES_SOCKET_BAD);
113
}
114
115
116
2
static void ares_poll_cb(uv_poll_t* watcher, int status, int events) {
117
2
  node_ares_task* task = ContainerOf(&node_ares_task::poll_watcher, watcher);
118
2
  Environment* env = task->env;
119
120
  /* Reset the idle timer */
121
2
  uv_timer_again(env->cares_timer_handle());
122
123
2
  if (status < 0) {
124
    /* An error happened. Just pretend that the socket is both readable and */
125
    /* writable. */
126
    ares_process_fd(env->cares_channel(), task->sock, task->sock);
127
    return;
128
  }
129
130
  /* Process DNS responses */
131
4
  ares_process_fd(env->cares_channel(),
132
2
                  events & UV_READABLE ? task->sock : ARES_SOCKET_BAD,
133
4
                  events & UV_WRITABLE ? task->sock : ARES_SOCKET_BAD);
134
}
135
136
137
2
static void ares_poll_close_cb(uv_handle_t* watcher) {
138
2
  node_ares_task* task = ContainerOf(&node_ares_task::poll_watcher,
139
2
                                  reinterpret_cast<uv_poll_t*>(watcher));
140
2
  free(task);
141
2
}
142
143
144
/* Allocates and returns a new node_ares_task */
145
2
static node_ares_task* ares_task_create(Environment* env, ares_socket_t sock) {
146
2
  node_ares_task* task = static_cast<node_ares_task*>(malloc(sizeof(*task)));
147
148
2
  if (task == nullptr) {
149
    /* Out of memory. */
150
    return nullptr;
151
  }
152
153
2
  task->env = env;
154
2
  task->sock = sock;
155
156
4
  if (uv_poll_init_socket(env->event_loop(), &task->poll_watcher, sock) < 0) {
157
    /* This should never happen. */
158
    free(task);
159
    return nullptr;
160
  }
161
162
  return task;
163
}
164
165
166
/* Callback from ares when socket operation is started */
167
4
static void ares_sockstate_cb(void* data,
168
                              ares_socket_t sock,
169
                              int read,
170
                              int write) {
171
4
  Environment* env = static_cast<Environment*>(data);
172
  node_ares_task* task;
173
174
  node_ares_task lookup_task;
175
4
  lookup_task.sock = sock;
176
8
  task = RB_FIND(node_ares_task_list, env->cares_task_list(), &lookup_task);
177
178
4
  if (read || write) {
179
2
    if (!task) {
180
      /* New socket */
181
182
      /* If this is the first socket then start the timer. */
183
2
      uv_timer_t* timer_handle = env->cares_timer_handle();
184
2
      if (!uv_is_active(reinterpret_cast<uv_handle_t*>(timer_handle))) {
185
2
        CHECK(RB_EMPTY(env->cares_task_list()));
186
2
        uv_timer_start(timer_handle, ares_timeout, 1000, 1000);
187
      }
188
189
2
      task = ares_task_create(env, sock);
190
2
      if (task == nullptr) {
191
        /* This should never happen unless we're out of memory or something */
192
        /* is seriously wrong. The socket won't be polled, but the the query */
193
        /* will eventually time out. */
194
        return;
195
      }
196
197
2
      RB_INSERT(node_ares_task_list, env->cares_task_list(), task);
198
    }
199
200
    /* This should never fail. If it fails anyway, the query will eventually */
201
    /* time out. */
202
2
    uv_poll_start(&task->poll_watcher,
203
                  (read ? UV_READABLE : 0) | (write ? UV_WRITABLE : 0),
204
2
                  ares_poll_cb);
205
206
  } else {
207
    /* read == 0 and write == 0 this is c-ares's way of notifying us that */
208
    /* the socket is now closed. We must free the data associated with */
209
    /* socket. */
210
2
    CHECK(task &&
211
          "When an ares socket is closed we should have a handle for it");
212
213
2
    RB_REMOVE(node_ares_task_list, env->cares_task_list(), task);
214
2
    uv_close(reinterpret_cast<uv_handle_t*>(&task->poll_watcher),
215
2
             ares_poll_close_cb);
216
217
2
    if (RB_EMPTY(env->cares_task_list())) {
218
2
      uv_timer_stop(env->cares_timer_handle());
219
    }
220
  }
221
}
222
223
224
1
static Local<Array> HostentToAddresses(Environment* env, struct hostent* host) {
225
2
  EscapableHandleScope scope(env->isolate());
226
1
  Local<Array> addresses = Array::New(env->isolate());
227
228
  char ip[INET6_ADDRSTRLEN];
229
2
  for (uint32_t i = 0; host->h_addr_list[i] != nullptr; ++i) {
230
1
    uv_inet_ntop(host->h_addrtype, host->h_addr_list[i], ip, sizeof(ip));
231
1
    Local<String> address = OneByteString(env->isolate(), ip);
232
2
    addresses->Set(i, address);
233
  }
234
235
2
  return scope.Escape(addresses);
236
}
237
238
239
1
static Local<Array> HostentToNames(Environment* env, struct hostent* host) {
240
2
  EscapableHandleScope scope(env->isolate());
241
1
  Local<Array> names = Array::New(env->isolate());
242
243
2
  for (uint32_t i = 0; host->h_aliases[i] != nullptr; ++i) {
244
1
    Local<String> address = OneByteString(env->isolate(), host->h_aliases[i]);
245
2
    names->Set(i, address);
246
  }
247
248
2
  return scope.Escape(names);
249
}
250
251
252
class QueryWrap : public AsyncWrap {
253
 public:
254
3
  QueryWrap(Environment* env, Local<Object> req_wrap_obj)
255
3
      : AsyncWrap(env, req_wrap_obj, AsyncWrap::PROVIDER_QUERYWRAP) {
256
3
    if (env->in_domain())
257
      req_wrap_obj->Set(env->domain_string(), env->domain_array()->Get(0));
258
3
  }
259
260
6
  ~QueryWrap() override {
261
6
    CHECK_EQ(false, persistent().IsEmpty());
262
6
    ClearWrap(object());
263
6
    persistent().Reset();
264
3
  }
265
266
  // Subclasses should implement the appropriate Send method.
267
  virtual int Send(const char* name) {
268
    UNREACHABLE();
269
    return 0;
270
  }
271
272
  virtual int Send(const char* name, int family) {
273
    UNREACHABLE();
274
    return 0;
275
  }
276
277
 protected:
278
  void* GetQueryArg() {
279
    return static_cast<void*>(this);
280
  }
281
282
2
  static void Callback(void *arg, int status, int timeouts,
283
      unsigned char* answer_buf, int answer_len) {
284
2
    QueryWrap* wrap = static_cast<QueryWrap*>(arg);
285
286
2
    if (status != ARES_SUCCESS) {
287
1
      wrap->ParseError(status);
288
    } else {
289
1
      wrap->Parse(answer_buf, answer_len);
290
    }
291
292
2
    delete wrap;
293
2
  }
294
295
1
  static void Callback(void *arg, int status, int timeouts,
296
      struct hostent* host) {
297
1
    QueryWrap* wrap = static_cast<QueryWrap*>(arg);
298
299
1
    if (status != ARES_SUCCESS) {
300
      wrap->ParseError(status);
301
    } else {
302
1
      wrap->Parse(host);
303
    }
304
305
1
    delete wrap;
306
1
  }
307
308
2
  void CallOnComplete(Local<Value> answer) {
309
4
    HandleScope handle_scope(env()->isolate());
310
8
    Context::Scope context_scope(env()->context());
311
    Local<Value> argv[] = {
312
      Integer::New(env()->isolate(), 0),
313
      answer
314
4
    };
315
4
    MakeCallback(env()->oncomplete_string(), arraysize(argv), argv);
316
2
  }
317
318
  void CallOnComplete(Local<Value> answer, Local<Value> family) {
319
    HandleScope handle_scope(env()->isolate());
320
    Context::Scope context_scope(env()->context());
321
    Local<Value> argv[] = {
322
      Integer::New(env()->isolate(), 0),
323
      answer,
324
      family
325
    };
326
    MakeCallback(env()->oncomplete_string(), arraysize(argv), argv);
327
  }
328
329
1
  void ParseError(int status) {
330
1
    CHECK_NE(status, ARES_SUCCESS);
331
2
    HandleScope handle_scope(env()->isolate());
332
4
    Context::Scope context_scope(env()->context());
333
1
    Local<Value> arg;
334
1
    switch (status) {
335
#define V(code)                                                               \
336
      case ARES_ ## code:                                                     \
337
        arg = FIXED_ONE_BYTE_STRING(env()->isolate(), #code);                 \
338
        break;
339
      V(ENODATA)
340
      V(EFORMERR)
341
      V(ESERVFAIL)
342
2
      V(ENOTFOUND)
343
      V(ENOTIMP)
344
      V(EREFUSED)
345
      V(EBADQUERY)
346
      V(EBADNAME)
347
      V(EBADFAMILY)
348
      V(EBADRESP)
349
      V(ECONNREFUSED)
350
      V(ETIMEOUT)
351
      V(EOF)
352
      V(EFILE)
353
      V(ENOMEM)
354
      V(EDESTRUCTION)
355
      V(EBADSTR)
356
      V(EBADFLAGS)
357
      V(ENONAME)
358
      V(EBADHINTS)
359
      V(ENOTINITIALIZED)
360
      V(ELOADIPHLPAPI)
361
      V(EADDRGETNETWORKPARAMS)
362
      V(ECANCELLED)
363
#undef V
364
      default:
365
        arg = FIXED_ONE_BYTE_STRING(env()->isolate(), "UNKNOWN_ARES_ERROR");
366
        break;
367
    }
368
2
    MakeCallback(env()->oncomplete_string(), 1, &arg);
369
1
  }
370
371
  // Subclasses should implement the appropriate Parse method.
372
  virtual void Parse(unsigned char* buf, int len) {
373
    UNREACHABLE();
374
  }
375
376
  virtual void Parse(struct hostent* host) {
377
    UNREACHABLE();
378
  }
379
};
380
381
382
2
class QueryAWrap: public QueryWrap {
383
 public:
384
  QueryAWrap(Environment* env, Local<Object> req_wrap_obj)
385
2
      : QueryWrap(env, req_wrap_obj) {
386
  }
387
388
2
  int Send(const char* name) override {
389
2
    ares_query(env()->cares_channel(),
390
               name,
391
               ns_c_in,
392
               ns_t_a,
393
               Callback,
394
2
               GetQueryArg());
395
2
    return 0;
396
  }
397
398
  size_t self_size() const override { return sizeof(*this); }
399
400
 protected:
401
1
  void Parse(unsigned char* buf, int len) override {
402
2
    HandleScope handle_scope(env()->isolate());
403
4
    Context::Scope context_scope(env()->context());
404
405
    struct hostent* host;
406
407
1
    int status = ares_parse_a_reply(buf, len, &host, nullptr, nullptr);
408
1
    if (status != ARES_SUCCESS) {
409
      ParseError(status);
410
      return;
411
    }
412
413
1
    Local<Array> addresses = HostentToAddresses(env(), host);
414
1
    ares_free_hostent(host);
415
416
1
    this->CallOnComplete(addresses);
417
  }
418
};
419
420
421
class QueryAaaaWrap: public QueryWrap {
422
 public:
423
  QueryAaaaWrap(Environment* env, Local<Object> req_wrap_obj)
424
      : QueryWrap(env, req_wrap_obj) {
425
  }
426
427
  int Send(const char* name) override {
428
    ares_query(env()->cares_channel(),
429
               name,
430
               ns_c_in,
431
               ns_t_aaaa,
432
               Callback,
433
               GetQueryArg());
434
    return 0;
435
  }
436
437
  size_t self_size() const override { return sizeof(*this); }
438
439
 protected:
440
  void Parse(unsigned char* buf, int len) override {
441
    HandleScope handle_scope(env()->isolate());
442
    Context::Scope context_scope(env()->context());
443
444
    struct hostent* host;
445
446
    int status = ares_parse_aaaa_reply(buf, len, &host, nullptr, nullptr);
447
    if (status != ARES_SUCCESS) {
448
      ParseError(status);
449
      return;
450
    }
451
452
    Local<Array> addresses = HostentToAddresses(env(), host);
453
    ares_free_hostent(host);
454
455
    this->CallOnComplete(addresses);
456
  }
457
};
458
459
460
class QueryCnameWrap: public QueryWrap {
461
 public:
462
  QueryCnameWrap(Environment* env, Local<Object> req_wrap_obj)
463
      : QueryWrap(env, req_wrap_obj) {
464
  }
465
466
  int Send(const char* name) override {
467
    ares_query(env()->cares_channel(),
468
               name,
469
               ns_c_in,
470
               ns_t_cname,
471
               Callback,
472
               GetQueryArg());
473
    return 0;
474
  }
475
476
  size_t self_size() const override { return sizeof(*this); }
477
478
 protected:
479
  void Parse(unsigned char* buf, int len) override {
480
    HandleScope handle_scope(env()->isolate());
481
    Context::Scope context_scope(env()->context());
482
    struct hostent* host;
483
484
    int status = ares_parse_a_reply(buf, len, &host, nullptr, nullptr);
485
    if (status != ARES_SUCCESS) {
486
      ParseError(status);
487
      return;
488
    }
489
490
    // A cname lookup always returns a single record but we follow the
491
    // common API here.
492
    Local<Array> result = Array::New(env()->isolate(), 1);
493
    result->Set(0, OneByteString(env()->isolate(), host->h_name));
494
    ares_free_hostent(host);
495
496
    this->CallOnComplete(result);
497
  }
498
};
499
500
501
class QueryMxWrap: public QueryWrap {
502
 public:
503
  QueryMxWrap(Environment* env, Local<Object> req_wrap_obj)
504
      : QueryWrap(env, req_wrap_obj) {
505
  }
506
507
  int Send(const char* name) override {
508
    ares_query(env()->cares_channel(),
509
               name,
510
               ns_c_in,
511
               ns_t_mx,
512
               Callback,
513
               GetQueryArg());
514
    return 0;
515
  }
516
517
  size_t self_size() const override { return sizeof(*this); }
518
519
 protected:
520
  void Parse(unsigned char* buf, int len) override {
521
    HandleScope handle_scope(env()->isolate());
522
    Context::Scope context_scope(env()->context());
523
524
    struct ares_mx_reply* mx_start;
525
    int status = ares_parse_mx_reply(buf, len, &mx_start);
526
    if (status != ARES_SUCCESS) {
527
      ParseError(status);
528
      return;
529
    }
530
531
    Local<Array> mx_records = Array::New(env()->isolate());
532
    Local<String> exchange_symbol = env()->exchange_string();
533
    Local<String> priority_symbol = env()->priority_string();
534
535
    ares_mx_reply* current = mx_start;
536
    for (uint32_t i = 0; current != nullptr; ++i, current = current->next) {
537
      Local<Object> mx_record = Object::New(env()->isolate());
538
      mx_record->Set(exchange_symbol,
539
                     OneByteString(env()->isolate(), current->host));
540
      mx_record->Set(priority_symbol,
541
                     Integer::New(env()->isolate(), current->priority));
542
      mx_records->Set(i, mx_record);
543
    }
544
545
    ares_free_data(mx_start);
546
547
    this->CallOnComplete(mx_records);
548
  }
549
};
550
551
552
class QueryNsWrap: public QueryWrap {
553
 public:
554
  QueryNsWrap(Environment* env, Local<Object> req_wrap_obj)
555
      : QueryWrap(env, req_wrap_obj) {
556
  }
557
558
  int Send(const char* name) override {
559
    ares_query(env()->cares_channel(),
560
               name,
561
               ns_c_in,
562
               ns_t_ns,
563
               Callback,
564
               GetQueryArg());
565
    return 0;
566
  }
567
568
  size_t self_size() const override { return sizeof(*this); }
569
570
 protected:
571
  void Parse(unsigned char* buf, int len) override {
572
    HandleScope handle_scope(env()->isolate());
573
    Context::Scope context_scope(env()->context());
574
    struct hostent* host;
575
576
    int status = ares_parse_ns_reply(buf, len, &host);
577
    if (status != ARES_SUCCESS) {
578
      ParseError(status);
579
      return;
580
    }
581
582
    Local<Array> names = HostentToNames(env(), host);
583
    ares_free_hostent(host);
584
585
    this->CallOnComplete(names);
586
  }
587
};
588
589
590
class QueryTxtWrap: public QueryWrap {
591
 public:
592
  QueryTxtWrap(Environment* env, Local<Object> req_wrap_obj)
593
      : QueryWrap(env, req_wrap_obj) {
594
  }
595
596
  int Send(const char* name) override {
597
    ares_query(env()->cares_channel(),
598
               name,
599
               ns_c_in,
600
               ns_t_txt,
601
               Callback,
602
               GetQueryArg());
603
    return 0;
604
  }
605
606
  size_t self_size() const override { return sizeof(*this); }
607
608
 protected:
609
  void Parse(unsigned char* buf, int len) override {
610
    HandleScope handle_scope(env()->isolate());
611
    Context::Scope context_scope(env()->context());
612
    struct ares_txt_ext* txt_out;
613
614
    int status = ares_parse_txt_reply_ext(buf, len, &txt_out);
615
    if (status != ARES_SUCCESS) {
616
      ParseError(status);
617
      return;
618
    }
619
620
    Local<Array> txt_records = Array::New(env()->isolate());
621
    Local<Array> txt_chunk;
622
623
    struct ares_txt_ext* current = txt_out;
624
    uint32_t i = 0;
625
    for (uint32_t j = 0; current != nullptr; current = current->next) {
626
      Local<String> txt = OneByteString(env()->isolate(), current->txt);
627
      // New record found - write out the current chunk
628
      if (current->record_start) {
629
        if (!txt_chunk.IsEmpty())
630
          txt_records->Set(i++, txt_chunk);
631
        txt_chunk = Array::New(env()->isolate());
632
        j = 0;
633
      }
634
      txt_chunk->Set(j++, txt);
635
    }
636
    // Push last chunk if it isn't empty
637
    if (!txt_chunk.IsEmpty())
638
      txt_records->Set(i, txt_chunk);
639
640
    ares_free_data(txt_out);
641
642
    this->CallOnComplete(txt_records);
643
  }
644
};
645
646
647
class QuerySrvWrap: public QueryWrap {
648
 public:
649
  explicit QuerySrvWrap(Environment* env, Local<Object> req_wrap_obj)
650
      : QueryWrap(env, req_wrap_obj) {
651
  }
652
653
  int Send(const char* name) override {
654
    ares_query(env()->cares_channel(),
655
               name,
656
               ns_c_in,
657
               ns_t_srv,
658
               Callback,
659
               GetQueryArg());
660
    return 0;
661
  }
662
663
  size_t self_size() const override { return sizeof(*this); }
664
665
 protected:
666
  void Parse(unsigned char* buf, int len) override {
667
    HandleScope handle_scope(env()->isolate());
668
    Context::Scope context_scope(env()->context());
669
670
    struct ares_srv_reply* srv_start;
671
    int status = ares_parse_srv_reply(buf, len, &srv_start);
672
    if (status != ARES_SUCCESS) {
673
      ParseError(status);
674
      return;
675
    }
676
677
    Local<Array> srv_records = Array::New(env()->isolate());
678
    Local<String> name_symbol = env()->name_string();
679
    Local<String> port_symbol = env()->port_string();
680
    Local<String> priority_symbol = env()->priority_string();
681
    Local<String> weight_symbol = env()->weight_string();
682
683
    ares_srv_reply* current = srv_start;
684
    for (uint32_t i = 0; current != nullptr; ++i, current = current->next) {
685
      Local<Object> srv_record = Object::New(env()->isolate());
686
      srv_record->Set(name_symbol,
687
                      OneByteString(env()->isolate(), current->host));
688
      srv_record->Set(port_symbol,
689
                      Integer::New(env()->isolate(), current->port));
690
      srv_record->Set(priority_symbol,
691
                      Integer::New(env()->isolate(), current->priority));
692
      srv_record->Set(weight_symbol,
693
                      Integer::New(env()->isolate(), current->weight));
694
      srv_records->Set(i, srv_record);
695
    }
696
697
    ares_free_data(srv_start);
698
699
    this->CallOnComplete(srv_records);
700
  }
701
};
702
703
class QueryPtrWrap: public QueryWrap {
704
 public:
705
  explicit QueryPtrWrap(Environment* env, Local<Object> req_wrap_obj)
706
      : QueryWrap(env, req_wrap_obj) {
707
  }
708
709
  int Send(const char* name) override {
710
    ares_query(env()->cares_channel(),
711
               name,
712
               ns_c_in,
713
               ns_t_ptr,
714
               Callback,
715
               GetQueryArg());
716
    return 0;
717
  }
718
719
  size_t self_size() const override { return sizeof(*this); }
720
721
 protected:
722
  void Parse(unsigned char* buf, int len) override {
723
    HandleScope handle_scope(env()->isolate());
724
    Context::Scope context_scope(env()->context());
725
726
    struct hostent* host;
727
728
    int status = ares_parse_ptr_reply(buf, len, NULL, 0, AF_INET, &host);
729
    if (status != ARES_SUCCESS) {
730
      ParseError(status);
731
      return;
732
    }
733
734
    Local<Array> aliases = Array::New(env()->isolate());
735
736
    for (uint32_t i = 0; host->h_aliases[i] != NULL; i++) {
737
      aliases->Set(i, OneByteString(env()->isolate(), host->h_aliases[i]));
738
    }
739
740
    ares_free_hostent(host);
741
742
    this->CallOnComplete(aliases);
743
  }
744
};
745
746
class QueryNaptrWrap: public QueryWrap {
747
 public:
748
  explicit QueryNaptrWrap(Environment* env, Local<Object> req_wrap_obj)
749
      : QueryWrap(env, req_wrap_obj) {
750
  }
751
752
  int Send(const char* name) override {
753
    ares_query(env()->cares_channel(),
754
               name,
755
               ns_c_in,
756
               ns_t_naptr,
757
               Callback,
758
               GetQueryArg());
759
    return 0;
760
  }
761
762
  size_t self_size() const override { return sizeof(*this); }
763
764
 protected:
765
  void Parse(unsigned char* buf, int len) override {
766
    HandleScope handle_scope(env()->isolate());
767
    Context::Scope context_scope(env()->context());
768
769
    ares_naptr_reply* naptr_start;
770
    int status = ares_parse_naptr_reply(buf, len, &naptr_start);
771
772
    if (status != ARES_SUCCESS) {
773
      ParseError(status);
774
      return;
775
    }
776
777
    Local<Array> naptr_records = Array::New(env()->isolate());
778
    Local<String> flags_symbol = env()->flags_string();
779
    Local<String> service_symbol = env()->service_string();
780
    Local<String> regexp_symbol = env()->regexp_string();
781
    Local<String> replacement_symbol = env()->replacement_string();
782
    Local<String> order_symbol = env()->order_string();
783
    Local<String> preference_symbol = env()->preference_string();
784
785
    ares_naptr_reply* current = naptr_start;
786
    for (uint32_t i = 0; current != nullptr; ++i, current = current->next) {
787
      Local<Object> naptr_record = Object::New(env()->isolate());
788
      naptr_record->Set(flags_symbol,
789
                        OneByteString(env()->isolate(), current->flags));
790
      naptr_record->Set(service_symbol,
791
                        OneByteString(env()->isolate(), current->service));
792
      naptr_record->Set(regexp_symbol,
793
                        OneByteString(env()->isolate(), current->regexp));
794
      naptr_record->Set(replacement_symbol,
795
                        OneByteString(env()->isolate(), current->replacement));
796
      naptr_record->Set(order_symbol,
797
                        Integer::New(env()->isolate(), current->order));
798
      naptr_record->Set(preference_symbol,
799
                        Integer::New(env()->isolate(), current->preference));
800
      naptr_records->Set(i, naptr_record);
801
    }
802
803
    ares_free_data(naptr_start);
804
805
    this->CallOnComplete(naptr_records);
806
  }
807
};
808
809
810
class QuerySoaWrap: public QueryWrap {
811
 public:
812
  QuerySoaWrap(Environment* env, Local<Object> req_wrap_obj)
813
      : QueryWrap(env, req_wrap_obj) {
814
  }
815
816
  int Send(const char* name) override {
817
    ares_query(env()->cares_channel(),
818
               name,
819
               ns_c_in,
820
               ns_t_soa,
821
               Callback,
822
               GetQueryArg());
823
    return 0;
824
  }
825
826
  size_t self_size() const override { return sizeof(*this); }
827
828
 protected:
829
  void Parse(unsigned char* buf, int len) override {
830
    HandleScope handle_scope(env()->isolate());
831
    Context::Scope context_scope(env()->context());
832
833
    ares_soa_reply* soa_out;
834
    int status = ares_parse_soa_reply(buf, len, &soa_out);
835
836
    if (status != ARES_SUCCESS) {
837
      ParseError(status);
838
      return;
839
    }
840
841
    Local<Object> soa_record = Object::New(env()->isolate());
842
843
    soa_record->Set(env()->nsname_string(),
844
                    OneByteString(env()->isolate(), soa_out->nsname));
845
    soa_record->Set(env()->hostmaster_string(),
846
                    OneByteString(env()->isolate(), soa_out->hostmaster));
847
    soa_record->Set(env()->serial_string(),
848
                    Integer::New(env()->isolate(), soa_out->serial));
849
    soa_record->Set(env()->refresh_string(),
850
                    Integer::New(env()->isolate(), soa_out->refresh));
851
    soa_record->Set(env()->retry_string(),
852
                    Integer::New(env()->isolate(), soa_out->retry));
853
    soa_record->Set(env()->expire_string(),
854
                    Integer::New(env()->isolate(), soa_out->expire));
855
    soa_record->Set(env()->minttl_string(),
856
                    Integer::New(env()->isolate(), soa_out->minttl));
857
858
    ares_free_data(soa_out);
859
860
    this->CallOnComplete(soa_record);
861
  }
862
};
863
864
865
1
class GetHostByAddrWrap: public QueryWrap {
866
 public:
867
  explicit GetHostByAddrWrap(Environment* env, Local<Object> req_wrap_obj)
868
1
      : QueryWrap(env, req_wrap_obj) {
869
  }
870
871
1
  int Send(const char* name) override {
872
    int length, family;
873
    char address_buffer[sizeof(struct in6_addr)];
874
875
1
    if (uv_inet_pton(AF_INET, name, &address_buffer) == 0) {
876
      length = sizeof(struct in_addr);
877
      family = AF_INET;
878
    } else if (uv_inet_pton(AF_INET6, name, &address_buffer) == 0) {
879
      length = sizeof(struct in6_addr);
880
      family = AF_INET6;
881
    } else {
882
      return UV_EINVAL;  // So errnoException() reports a proper error.
883
    }
884
885
1
    ares_gethostbyaddr(env()->cares_channel(),
886
                       address_buffer,
887
                       length,
888
                       family,
889
                       Callback,
890
1
                       GetQueryArg());
891
1
    return 0;
892
  }
893
894
  size_t self_size() const override { return sizeof(*this); }
895
896
 protected:
897
1
  void Parse(struct hostent* host) override {
898
2
    HandleScope handle_scope(env()->isolate());
899
4
    Context::Scope context_scope(env()->context());
900
2
    this->CallOnComplete(HostentToNames(env(), host));
901
1
  }
902
};
903
904
905
class GetHostByNameWrap: public QueryWrap {
906
 public:
907
  explicit GetHostByNameWrap(Environment* env, Local<Object> req_wrap_obj)
908
      : QueryWrap(env, req_wrap_obj) {
909
  }
910
911
  int Send(const char* name, int family) override {
912
    ares_gethostbyname(env()->cares_channel(),
913
                       name,
914
                       family,
915
                       Callback,
916
                       GetQueryArg());
917
    return 0;
918
  }
919
920
 protected:
921
  void Parse(struct hostent* host) override {
922
    HandleScope scope(env()->isolate());
923
924
    Local<Array> addresses = HostentToAddresses(env(), host);
925
    Local<Integer> family = Integer::New(env()->isolate(), host->h_addrtype);
926
927
    this->CallOnComplete(addresses, family);
928
  }
929
};
930
931
932
template <class Wrap>
933
3
static void Query(const FunctionCallbackInfo<Value>& args) {
934
3
  Environment* env = Environment::GetCurrent(args);
935
936
3
  CHECK_EQ(false, args.IsConstructCall());
937
3
  CHECK(args[0]->IsObject());
938
6
  CHECK(args[1]->IsString());
939
940
6
  Local<Object> req_wrap_obj = args[0].As<Object>();
941
6
  Local<String> string = args[1].As<String>();
942
6
  Wrap* wrap = new Wrap(env, req_wrap_obj);
943
944
6
  node::Utf8Value name(env->isolate(), string);
945
3
  int err = wrap->Send(*name);
946
3
  if (err)
947
    delete wrap;
948
949
6
  args.GetReturnValue().Set(err);
950
3
}
951
952
953
1917
void AfterGetAddrInfo(uv_getaddrinfo_t* req, int status, struct addrinfo* res) {
954
1917
  GetAddrInfoReqWrap* req_wrap = static_cast<GetAddrInfoReqWrap*>(req->data);
955
1917
  Environment* env = req_wrap->env();
956
957
3834
  HandleScope handle_scope(env->isolate());
958
5751
  Context::Scope context_scope(env->context());
959
960
  Local<Value> argv[] = {
961
    Integer::New(env->isolate(), status),
962
    Null(env->isolate())
963
7668
  };
964
965
1917
  if (status == 0) {
966
    // Success
967
    struct addrinfo *address;
968
1910
    int n = 0;
969
970
    // Create the response array.
971
1910
    Local<Array> results = Array::New(env->isolate());
972
973
    char ip[INET6_ADDRSTRLEN];
974
    const char *addr;
975
976
    // Iterate over the IPv4 responses again this time creating javascript
977
    // strings for each IP and filling the results array.
978
1910
    address = res;
979
3827
    while (address) {
980
1917
      CHECK_EQ(address->ai_socktype, SOCK_STREAM);
981
982
      // Ignore random ai_family types.
983
1917
      if (address->ai_family == AF_INET) {
984
        // Juggle pointers
985
        addr = reinterpret_cast<char*>(&(reinterpret_cast<struct sockaddr_in*>(
986
1909
            address->ai_addr)->sin_addr));
987
        int err = uv_inet_ntop(address->ai_family,
988
                               addr,
989
                               ip,
990
1909
                               INET6_ADDRSTRLEN);
991
1909
        if (err)
992
          continue;
993
994
        // Create JavaScript string
995
1909
        Local<String> s = OneByteString(env->isolate(), ip);
996
1909
        results->Set(n, s);
997
1909
        n++;
998
      }
999
1000
      // Increment
1001
1917
      address = address->ai_next;
1002
    }
1003
1004
    // Iterate over the IPv6 responses putting them in the array.
1005
    address = res;
1006
3827
    while (address) {
1007
1917
      CHECK_EQ(address->ai_socktype, SOCK_STREAM);
1008
1009
      // Ignore random ai_family types.
1010
1917
      if (address->ai_family == AF_INET6) {
1011
        // Juggle pointers
1012
        addr = reinterpret_cast<char*>(&(reinterpret_cast<struct sockaddr_in6*>(
1013
8
            address->ai_addr)->sin6_addr));
1014
        int err = uv_inet_ntop(address->ai_family,
1015
                               addr,
1016
                               ip,
1017
8
                               INET6_ADDRSTRLEN);
1018
8
        if (err)
1019
          continue;
1020
1021
        // Create JavaScript string
1022
8
        Local<String> s = OneByteString(env->isolate(), ip);
1023
8
        results->Set(n, s);
1024
8
        n++;
1025
      }
1026
1027
      // Increment
1028
1917
      address = address->ai_next;
1029
    }
1030
1031
    // No responses were found to return
1032
1910
    if (n == 0) {
1033
      argv[0] = Integer::New(env->isolate(), UV_EAI_NODATA);
1034
    }
1035
1036
1910
    argv[1] = results;
1037
  }
1038
1039
1917
  uv_freeaddrinfo(res);
1040
1041
  // Make the callback into JavaScript
1042
3834
  req_wrap->MakeCallback(env->oncomplete_string(), arraysize(argv), argv);
1043
1044
1917
  delete req_wrap;
1045
1917
}
1046
1047
1048
3
void AfterGetNameInfo(uv_getnameinfo_t* req,
1049
                      int status,
1050
                      const char* hostname,
1051
                      const char* service) {
1052
3
  GetNameInfoReqWrap* req_wrap = static_cast<GetNameInfoReqWrap*>(req->data);
1053
3
  Environment* env = req_wrap->env();
1054
1055
6
  HandleScope handle_scope(env->isolate());
1056
9
  Context::Scope context_scope(env->context());
1057
1058
  Local<Value> argv[] = {
1059
    Integer::New(env->isolate(), status),
1060
    Null(env->isolate()),
1061
    Null(env->isolate())
1062
18
  };
1063
1064
3
  if (status == 0) {
1065
    // Success
1066
    Local<String> js_hostname = OneByteString(env->isolate(), hostname);
1067
    Local<String> js_service = OneByteString(env->isolate(), service);
1068
    argv[1] = js_hostname;
1069
    argv[2] = js_service;
1070
  }
1071
1072
  // Make the callback into JavaScript
1073
6
  req_wrap->MakeCallback(env->oncomplete_string(), arraysize(argv), argv);
1074
1075
3
  delete req_wrap;
1076
3
}
1077
1078
1079
4815
static void IsIP(const FunctionCallbackInfo<Value>& args) {
1080
14445
  node::Utf8Value ip(args.GetIsolate(), args[0]);
1081
  char address_buffer[sizeof(struct in6_addr)];
1082
1083
4815
  int rc = 0;
1084
4815
  if (uv_inet_pton(AF_INET, *ip, &address_buffer) == 0)
1085
    rc = 4;
1086
3952
  else if (uv_inet_pton(AF_INET6, *ip, &address_buffer) == 0)
1087
47
    rc = 6;
1088
1089
9630
  args.GetReturnValue().Set(rc);
1090
4815
}
1091
1092
12
static void IsIPv4(const FunctionCallbackInfo<Value>& args) {
1093
36
  node::Utf8Value ip(args.GetIsolate(), args[0]);
1094
  char address_buffer[sizeof(struct in_addr)];
1095
1096
12
  if (uv_inet_pton(AF_INET, *ip, &address_buffer) == 0) {
1097
4
    args.GetReturnValue().Set(true);
1098
  } else {
1099
20
    args.GetReturnValue().Set(false);
1100
  }
1101
12
}
1102
1103
18
static void IsIPv6(const FunctionCallbackInfo<Value>& args) {
1104
54
  node::Utf8Value ip(args.GetIsolate(), args[0]);
1105
  char address_buffer[sizeof(struct in6_addr)];
1106
1107
18
  if (uv_inet_pton(AF_INET6, *ip, &address_buffer) == 0) {
1108
16
    args.GetReturnValue().Set(true);
1109
  } else {
1110
20
    args.GetReturnValue().Set(false);
1111
  }
1112
18
}
1113
1114
1918
static void GetAddrInfo(const FunctionCallbackInfo<Value>& args) {
1115
1918
  Environment* env = Environment::GetCurrent(args);
1116
1117
1918
  CHECK(args[0]->IsObject());
1118
3836
  CHECK(args[1]->IsString());
1119
1918
  CHECK(args[2]->IsInt32());
1120
3836
  Local<Object> req_wrap_obj = args[0].As<Object>();
1121
3836
  node::Utf8Value hostname(env->isolate(), args[1]);
1122
1123
3836
  int32_t flags = (args[3]->IsInt32()) ? args[3]->Int32Value() : 0;
1124
  int family;
1125
1126
1918
  switch (args[2]->Int32Value()) {
1127
  case 0:
1128
    family = AF_UNSPEC;
1129
    break;
1130
  case 4:
1131
8
    family = AF_INET;
1132
8
    break;
1133
  case 6:
1134
6
    family = AF_INET6;
1135
6
    break;
1136
  default:
1137
    CHECK(0 && "bad address family");
1138
    ABORT();
1139
  }
1140
1141
1918
  GetAddrInfoReqWrap* req_wrap = new GetAddrInfoReqWrap(env, req_wrap_obj);
1142
1143
  struct addrinfo hints;
1144
1918
  memset(&hints, 0, sizeof(struct addrinfo));
1145
1918
  hints.ai_family = family;
1146
1918
  hints.ai_socktype = SOCK_STREAM;
1147
1918
  hints.ai_flags = flags;
1148
1149
3836
  int err = uv_getaddrinfo(env->event_loop(),
1150
                           &req_wrap->req_,
1151
                           AfterGetAddrInfo,
1152
1918
                           *hostname,
1153
                           nullptr,
1154
1918
                           &hints);
1155
3836
  req_wrap->Dispatched();
1156
1918
  if (err)
1157
    delete req_wrap;
1158
1159
3836
  args.GetReturnValue().Set(err);
1160
1918
}
1161
1162
1163
3
static void GetNameInfo(const FunctionCallbackInfo<Value>& args) {
1164
3
  Environment* env = Environment::GetCurrent(args);
1165
1166
3
  CHECK(args[0]->IsObject());
1167
6
  CHECK(args[1]->IsString());
1168
3
  CHECK(args[2]->IsUint32());
1169
6
  Local<Object> req_wrap_obj = args[0].As<Object>();
1170
6
  node::Utf8Value ip(env->isolate(), args[1]);
1171
3
  const unsigned port = args[2]->Uint32Value();
1172
  struct sockaddr_storage addr;
1173
1174
3
  CHECK(uv_ip4_addr(*ip, port, reinterpret_cast<sockaddr_in*>(&addr)) == 0 ||
1175
        uv_ip6_addr(*ip, port, reinterpret_cast<sockaddr_in6*>(&addr)) == 0);
1176
1177
3
  GetNameInfoReqWrap* req_wrap = new GetNameInfoReqWrap(env, req_wrap_obj);
1178
1179
6
  int err = uv_getnameinfo(env->event_loop(),
1180
                           &req_wrap->req_,
1181
                           AfterGetNameInfo,
1182
                           (struct sockaddr*)&addr,
1183
3
                           NI_NAMEREQD);
1184
6
  req_wrap->Dispatched();
1185
3
  if (err)
1186
    delete req_wrap;
1187
1188
6
  args.GetReturnValue().Set(err);
1189
3
}
1190
1191
1192
13
static void GetServers(const FunctionCallbackInfo<Value>& args) {
1193
13
  Environment* env = Environment::GetCurrent(args);
1194
1195
13
  Local<Array> server_array = Array::New(env->isolate());
1196
1197
  ares_addr_node* servers;
1198
1199
13
  int r = ares_get_servers(env->cares_channel(), &servers);
1200
13
  CHECK_EQ(r, ARES_SUCCESS);
1201
1202
13
  ares_addr_node* cur = servers;
1203
1204
39
  for (uint32_t i = 0; cur != nullptr; ++i, cur = cur->next) {
1205
    char ip[INET6_ADDRSTRLEN];
1206
1207
26
    const void* caddr = static_cast<const void*>(&cur->addr);
1208
26
    int err = uv_inet_ntop(cur->family, caddr, ip, sizeof(ip));
1209
26
    CHECK_EQ(err, 0);
1210
1211
26
    Local<String> addr = OneByteString(env->isolate(), ip);
1212
52
    server_array->Set(i, addr);
1213
  }
1214
1215
13
  ares_free_data(servers);
1216
1217
26
  args.GetReturnValue().Set(server_array);
1218
13
}
1219
1220
1221
5
static void SetServers(const FunctionCallbackInfo<Value>& args) {
1222
5
  Environment* env = Environment::GetCurrent(args);
1223
1224
5
  CHECK(args[0]->IsArray());
1225
1226
10
  Local<Array> arr = Local<Array>::Cast(args[0]);
1227
1228
5
  uint32_t len = arr->Length();
1229
1230
5
  if (len == 0) {
1231
1
    int rv = ares_set_servers(env->cares_channel(), nullptr);
1232
2
    return args.GetReturnValue().Set(rv);
1233
  }
1234
1235
4
  ares_addr_node* servers = new ares_addr_node[len];
1236
4
  ares_addr_node* last = nullptr;
1237
1238
  int err;
1239
1240
13
  for (uint32_t i = 0; i < len; i++) {
1241
18
    CHECK(arr->Get(i)->IsArray());
1242
1243
18
    Local<Array> elm = Local<Array>::Cast(arr->Get(i));
1244
1245
18
    CHECK(elm->Get(0)->Int32Value());
1246
27
    CHECK(elm->Get(1)->IsString());
1247
1248
18
    int fam = elm->Get(0)->Int32Value();
1249
18
    node::Utf8Value ip(env->isolate(), elm->Get(1));
1250
1251
9
    ares_addr_node* cur = &servers[i];
1252
1253
9
    switch (fam) {
1254
      case 4:
1255
4
        cur->family = AF_INET;
1256
4
        err = uv_inet_pton(AF_INET, *ip, &cur->addr);
1257
4
        break;
1258
      case 6:
1259
5
        cur->family = AF_INET6;
1260
5
        err = uv_inet_pton(AF_INET6, *ip, &cur->addr);
1261
5
        break;
1262
      default:
1263
        CHECK(0 && "Bad address family.");
1264
        ABORT();
1265
    }
1266
1267
9
    if (err)
1268
      break;
1269
1270
9
    cur->next = nullptr;
1271
1272
9
    if (last != nullptr)
1273
5
      last->next = cur;
1274
1275
9
    last = cur;
1276
  }
1277
1278
4
  if (err == 0)
1279
4
    err = ares_set_servers(env->cares_channel(), &servers[0]);
1280
  else
1281
    err = ARES_EBADSTR;
1282
1283
4
  delete[] servers;
1284
1285
8
  args.GetReturnValue().Set(err);
1286
}
1287
1288
1289
static void StrError(const FunctionCallbackInfo<Value>& args) {
1290
  Environment* env = Environment::GetCurrent(args);
1291
  const char* errmsg = ares_strerror(args[0]->Int32Value());
1292
  args.GetReturnValue().Set(OneByteString(env->isolate(), errmsg));
1293
}
1294
1295
1296
1353
static void CaresTimerCloseCb(uv_handle_t* handle) {
1297
  Environment* env = Environment::from_cares_timer_handle(
1298
1353
      reinterpret_cast<uv_timer_t*>(handle));
1299
1353
  env->FinishHandleCleanup(handle);
1300
1353
}
1301
1302
1303
1353
static void CaresTimerClose(Environment* env,
1304
                            uv_handle_t* handle,
1305
                            void* arg) {
1306
1353
  uv_close(handle, CaresTimerCloseCb);
1307
1353
}
1308
1309
1310
1512
static void Initialize(Local<Object> target,
1311
                       Local<Value> unused,
1312
                       Local<Context> context) {
1313
1512
  Environment* env = Environment::GetCurrent(context);
1314
1315
1512
  int r = ares_library_init(ARES_LIB_INIT_ALL);
1316
1512
  CHECK_EQ(r, ARES_SUCCESS);
1317
1318
  struct ares_options options;
1319
1512
  memset(&options, 0, sizeof(options));
1320
1512
  options.flags = ARES_FLAG_NOCHECKRESP;
1321
1512
  options.sock_state_cb = ares_sockstate_cb;
1322
1512
  options.sock_state_cb_data = env;
1323
1324
  /* We do the call to ares_init_option for caller. */
1325
1512
  r = ares_init_options(env->cares_channel_ptr(),
1326
                        &options,
1327
1512
                        ARES_OPT_FLAGS | ARES_OPT_SOCK_STATE_CB);
1328
1512
  CHECK_EQ(r, ARES_SUCCESS);
1329
1330
  /* Initialize the timeout timer. The timer won't be started until the */
1331
  /* first socket is opened. */
1332
3024
  uv_timer_init(env->event_loop(), env->cares_timer_handle());
1333
  env->RegisterHandleCleanup(
1334
1512
      reinterpret_cast<uv_handle_t*>(env->cares_timer_handle()),
1335
      CaresTimerClose,
1336
1512
      nullptr);
1337
1338
1512
  env->SetMethod(target, "queryA", Query<QueryAWrap>);
1339
1512
  env->SetMethod(target, "queryAaaa", Query<QueryAaaaWrap>);
1340
1512
  env->SetMethod(target, "queryCname", Query<QueryCnameWrap>);
1341
1512
  env->SetMethod(target, "queryMx", Query<QueryMxWrap>);
1342
1512
  env->SetMethod(target, "queryNs", Query<QueryNsWrap>);
1343
1512
  env->SetMethod(target, "queryTxt", Query<QueryTxtWrap>);
1344
1512
  env->SetMethod(target, "querySrv", Query<QuerySrvWrap>);
1345
1512
  env->SetMethod(target, "queryPtr", Query<QueryPtrWrap>);
1346
1512
  env->SetMethod(target, "queryNaptr", Query<QueryNaptrWrap>);
1347
1512
  env->SetMethod(target, "querySoa", Query<QuerySoaWrap>);
1348
1512
  env->SetMethod(target, "getHostByAddr", Query<GetHostByAddrWrap>);
1349
1350
1512
  env->SetMethod(target, "getaddrinfo", GetAddrInfo);
1351
1512
  env->SetMethod(target, "getnameinfo", GetNameInfo);
1352
1512
  env->SetMethod(target, "isIP", IsIP);
1353
1512
  env->SetMethod(target, "isIPv4", IsIPv4);
1354
1512
  env->SetMethod(target, "isIPv6", IsIPv6);
1355
1356
1512
  env->SetMethod(target, "strerror", StrError);
1357
1512
  env->SetMethod(target, "getServers", GetServers);
1358
1512
  env->SetMethod(target, "setServers", SetServers);
1359
1360
6048
  target->Set(FIXED_ONE_BYTE_STRING(env->isolate(), "AF_INET"),
1361
1512
              Integer::New(env->isolate(), AF_INET));
1362
6048
  target->Set(FIXED_ONE_BYTE_STRING(env->isolate(), "AF_INET6"),
1363
1512
              Integer::New(env->isolate(), AF_INET6));
1364
6048
  target->Set(FIXED_ONE_BYTE_STRING(env->isolate(), "AF_UNSPEC"),
1365
1512
              Integer::New(env->isolate(), AF_UNSPEC));
1366
6048
  target->Set(FIXED_ONE_BYTE_STRING(env->isolate(), "AI_ADDRCONFIG"),
1367
1512
              Integer::New(env->isolate(), AI_ADDRCONFIG));
1368
6048
  target->Set(FIXED_ONE_BYTE_STRING(env->isolate(), "AI_V4MAPPED"),
1369
1512
              Integer::New(env->isolate(), AI_V4MAPPED));
1370
1371
  Local<FunctionTemplate> aiw =
1372
3024
      FunctionTemplate::New(env->isolate(), NewGetAddrInfoReqWrap);
1373
3024
  aiw->InstanceTemplate()->SetInternalFieldCount(1);
1374
1512
  aiw->SetClassName(
1375
1512
      FIXED_ONE_BYTE_STRING(env->isolate(), "GetAddrInfoReqWrap"));
1376
6048
  target->Set(FIXED_ONE_BYTE_STRING(env->isolate(), "GetAddrInfoReqWrap"),
1377
1512
              aiw->GetFunction());
1378
1379
  Local<FunctionTemplate> niw =
1380
3024
      FunctionTemplate::New(env->isolate(), NewGetNameInfoReqWrap);
1381
3024
  niw->InstanceTemplate()->SetInternalFieldCount(1);
1382
1512
  niw->SetClassName(
1383
1512
      FIXED_ONE_BYTE_STRING(env->isolate(), "GetNameInfoReqWrap"));
1384
6048
  target->Set(FIXED_ONE_BYTE_STRING(env->isolate(), "GetNameInfoReqWrap"),
1385
1512
              niw->GetFunction());
1386
1387
  Local<FunctionTemplate> qrw =
1388
3024
      FunctionTemplate::New(env->isolate(), NewQueryReqWrap);
1389
3024
  qrw->InstanceTemplate()->SetInternalFieldCount(1);
1390
1512
  qrw->SetClassName(
1391
1512
      FIXED_ONE_BYTE_STRING(env->isolate(), "QueryReqWrap"));
1392
6048
  target->Set(FIXED_ONE_BYTE_STRING(env->isolate(), "QueryReqWrap"),
1393
1512
              qrw->GetFunction());
1394
1512
}
1395
1396
}  // namespace cares_wrap
1397
}  // namespace node
1398
1399
1568
NODE_MODULE_CONTEXT_AWARE_BUILTIN(cares_wrap, node::cares_wrap::Initialize)