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