Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Newer
Older
100644 787 lines (613 sloc) 19.741 kb
858f230 @piscisaureus Bindings for libuv-integrated c-ares
piscisaureus authored
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 #include <assert.h>
ff4a9d3 @bnoordhuis core: use proper #include directives
bnoordhuis authored
23 #include "node.h"
24 #include "req_wrap.h"
25 #include "uv.h"
858f230 @piscisaureus Bindings for libuv-integrated c-ares
piscisaureus authored
26
be2320d @ry Add binding to uv_getaddrinfo
ry authored
27 #include <string.h>
28
13d6a1f @DrPizza Basic VC++ compatibility work.
DrPizza authored
29 #if defined(__OpenBSD__) || defined(__MINGW32__) || defined(_MSC_VER)
858f230 @piscisaureus Bindings for libuv-integrated c-ares
piscisaureus authored
30 # include <nameser.h>
31 #else
32 # include <arpa/nameser.h>
33 #endif
34
35 // Temporary hack: libuv should provide uv_inet_pton and uv_inet_ntop.
13d6a1f @DrPizza Basic VC++ compatibility work.
DrPizza authored
36 #if defined(__MINGW32__) || defined(_MSC_VER)
858f230 @piscisaureus Bindings for libuv-integrated c-ares
piscisaureus authored
37 extern "C" {
38 # include <inet_net_pton.h>
39 # include <inet_ntop.h>
40 }
41 # define uv_inet_pton ares_inet_pton
42 # define uv_inet_ntop ares_inet_ntop
43
44 #else // __POSIX__
45 # include <arpa/inet.h>
46 # define uv_inet_pton inet_pton
47 # define uv_inet_ntop inet_ntop
48 #endif
49
15f0e0a @tjfontaine src: replace usage of String::Utf8Value
tjfontaine authored
50 #include "util.h"
858f230 @piscisaureus Bindings for libuv-integrated c-ares
piscisaureus authored
51
52 namespace node {
53
54 namespace cares_wrap {
55
56 using v8::Arguments;
57 using v8::Array;
58 using v8::Context;
59 using v8::Function;
60 using v8::Handle;
61 using v8::HandleScope;
62 using v8::Integer;
63 using v8::Local;
64 using v8::Null;
65 using v8::Object;
66 using v8::Persistent;
67 using v8::String;
68 using v8::Value;
69
be2320d @ry Add binding to uv_getaddrinfo
ry authored
70
71 typedef class ReqWrap<uv_getaddrinfo_t> GetAddrInfoReqWrap;
72
74a8215 @bnoordhuis Revert support for isolates.
bnoordhuis authored
73 static Persistent<String> oncomplete_sym;
74
75 static ares_channel ares_channel;
76
77
858f230 @piscisaureus Bindings for libuv-integrated c-ares
piscisaureus authored
78 static Local<Array> HostentToAddresses(struct hostent* host) {
79 HandleScope scope;
80 Local<Array> addresses = Array::New();
81
82 char ip[INET6_ADDRSTRLEN];
83 for (int i = 0; host->h_addr_list[i]; ++i) {
84 uv_inet_ntop(host->h_addrtype, host->h_addr_list[i], ip, sizeof(ip));
85
86 Local<String> address = String::New(ip);
87 addresses->Set(Integer::New(i), address);
88 }
89
90 return scope.Close(addresses);
91 }
92
93
94 static Local<Array> HostentToNames(struct hostent* host) {
95 HandleScope scope;
96 Local<Array> names = Array::New();
97
98 for (int i = 0; host->h_aliases[i]; ++i) {
99 Local<String> address = String::New(host->h_aliases[i]);
100 names->Set(Integer::New(i), address);
101 }
102
103 return scope.Close(names);
104 }
105
106
107 static const char* AresErrnoString(int errorno) {
108 switch (errorno) {
109 #define ERRNO_CASE(e) case ARES_##e: return #e;
110 ERRNO_CASE(SUCCESS)
111 ERRNO_CASE(ENODATA)
112 ERRNO_CASE(EFORMERR)
113 ERRNO_CASE(ESERVFAIL)
114 ERRNO_CASE(ENOTFOUND)
115 ERRNO_CASE(ENOTIMP)
116 ERRNO_CASE(EREFUSED)
117 ERRNO_CASE(EBADQUERY)
118 ERRNO_CASE(EBADNAME)
119 ERRNO_CASE(EBADFAMILY)
120 ERRNO_CASE(EBADRESP)
121 ERRNO_CASE(ECONNREFUSED)
122 ERRNO_CASE(ETIMEOUT)
123 ERRNO_CASE(EOF)
124 ERRNO_CASE(EFILE)
125 ERRNO_CASE(ENOMEM)
126 ERRNO_CASE(EDESTRUCTION)
127 ERRNO_CASE(EBADSTR)
128 ERRNO_CASE(EBADFLAGS)
129 ERRNO_CASE(ENONAME)
130 ERRNO_CASE(EBADHINTS)
131 ERRNO_CASE(ENOTINITIALIZED)
132 ERRNO_CASE(ELOADIPHLPAPI)
133 ERRNO_CASE(EADDRGETNETWORKPARAMS)
134 ERRNO_CASE(ECANCELLED)
135 #undef ERRNO_CASE
136 default:
137 assert(0 && "Unhandled c-ares error");
138 return "(UNKNOWN)";
139 }
140 }
141
142
143 static void SetAresErrno(int errorno) {
144 HandleScope scope;
145 Handle<Value> key = String::NewSymbol("errno");
146 Handle<Value> value = String::NewSymbol(AresErrnoString(errorno));
147 Context::GetCurrent()->Global()->Set(key, value);
148 }
149
150
151 class QueryWrap {
152 public:
153 QueryWrap() {
154 HandleScope scope;
155
156 object_ = Persistent<Object>::New(Object::New());
157 }
158
f1d3ae7 @bnoordhuis cares_wrap: make destructor virtual
bnoordhuis authored
159 virtual ~QueryWrap() {
858f230 @piscisaureus Bindings for libuv-integrated c-ares
piscisaureus authored
160 assert(!object_.IsEmpty());
161
12798c6 @ry dns callbacks should go through MakeCallback
ry authored
162 object_->Delete(oncomplete_sym);
858f230 @piscisaureus Bindings for libuv-integrated c-ares
piscisaureus authored
163
164 object_.Dispose();
165 object_.Clear();
166 }
167
168 Handle<Object> GetObject() {
169 return object_;
170 }
171
12798c6 @ry dns callbacks should go through MakeCallback
ry authored
172 void SetOnComplete(Handle<Value> oncomplete) {
173 assert(oncomplete->IsFunction());
174 object_->Set(oncomplete_sym, oncomplete);
858f230 @piscisaureus Bindings for libuv-integrated c-ares
piscisaureus authored
175 }
176
177 // Subclasses should implement the appropriate Send method.
178 virtual int Send(const char* name) {
179 assert(0);
13d6a1f @DrPizza Basic VC++ compatibility work.
DrPizza authored
180 return 0;
858f230 @piscisaureus Bindings for libuv-integrated c-ares
piscisaureus authored
181 }
182
183 virtual int Send(const char* name, int family) {
184 assert(0);
13d6a1f @DrPizza Basic VC++ compatibility work.
DrPizza authored
185 return 0;
858f230 @piscisaureus Bindings for libuv-integrated c-ares
piscisaureus authored
186 }
187
188 protected:
189 void* GetQueryArg() {
190 return static_cast<void*>(this);
191 }
192
193 static void Callback(void *arg, int status, int timeouts,
194 unsigned char* answer_buf, int answer_len) {
195 QueryWrap* wrap = reinterpret_cast<QueryWrap*>(arg);
196
197 if (status != ARES_SUCCESS) {
198 wrap->ParseError(status);
199 } else {
200 wrap->Parse(answer_buf, answer_len);
201 }
202
203 delete wrap;
204 }
205
206 static void Callback(void *arg, int status, int timeouts,
207 struct hostent* host) {
208 QueryWrap* wrap = reinterpret_cast<QueryWrap*>(arg);
209
210 if (status != ARES_SUCCESS) {
211 wrap->ParseError(status);
212 } else {
213 wrap->Parse(host);
214 }
215
216 delete wrap;
217 }
218
12798c6 @ry dns callbacks should go through MakeCallback
ry authored
219 void CallOnComplete(Local<Value> answer) {
858f230 @piscisaureus Bindings for libuv-integrated c-ares
piscisaureus authored
220 HandleScope scope;
221 Local<Value> argv[2] = { Integer::New(0), answer };
a26bee8 @isaacs MakeCallback: Consistent symbol usage
isaacs authored
222 MakeCallback(object_, oncomplete_sym, ARRAY_SIZE(argv), argv);
858f230 @piscisaureus Bindings for libuv-integrated c-ares
piscisaureus authored
223 }
224
12798c6 @ry dns callbacks should go through MakeCallback
ry authored
225 void CallOnComplete(Local<Value> answer, Local<Value> family) {
858f230 @piscisaureus Bindings for libuv-integrated c-ares
piscisaureus authored
226 HandleScope scope;
227 Local<Value> argv[3] = { Integer::New(0), answer, family };
a26bee8 @isaacs MakeCallback: Consistent symbol usage
isaacs authored
228 MakeCallback(object_, oncomplete_sym, ARRAY_SIZE(argv), argv);
858f230 @piscisaureus Bindings for libuv-integrated c-ares
piscisaureus authored
229 }
230
231 void ParseError(int status) {
232 assert(status != ARES_SUCCESS);
233 SetAresErrno(status);
234
235 HandleScope scope;
236 Local<Value> argv[1] = { Integer::New(-1) };
a26bee8 @isaacs MakeCallback: Consistent symbol usage
isaacs authored
237 MakeCallback(object_, oncomplete_sym, ARRAY_SIZE(argv), argv);
858f230 @piscisaureus Bindings for libuv-integrated c-ares
piscisaureus authored
238 }
239
240 // Subclasses should implement the appropriate Parse method.
241 virtual void Parse(unsigned char* buf, int len) {
242 assert(0);
243 };
244
245 virtual void Parse(struct hostent* host) {
246 assert(0);
247 };
248
249 private:
250 Persistent<Object> object_;
251 };
252
253
254 class QueryAWrap: public QueryWrap {
255 public:
256 int Send(const char* name) {
257 ares_query(ares_channel, name, ns_c_in, ns_t_a, Callback, GetQueryArg());
258 return 0;
259 }
260
261 protected:
262 void Parse(unsigned char* buf, int len) {
263 HandleScope scope;
264
265 struct hostent* host;
266
267 int status = ares_parse_a_reply(buf, len, &host, NULL, NULL);
268 if (status != ARES_SUCCESS) {
269 this->ParseError(status);
270 return;
271 }
272
273 Local<Array> addresses = HostentToAddresses(host);
274 ares_free_hostent(host);
275
12798c6 @ry dns callbacks should go through MakeCallback
ry authored
276 this->CallOnComplete(addresses);
858f230 @piscisaureus Bindings for libuv-integrated c-ares
piscisaureus authored
277 }
278 };
279
280
281 class QueryAaaaWrap: public QueryWrap {
282 public:
283 int Send(const char* name) {
284 ares_query(ares_channel,
285 name,
286 ns_c_in,
287 ns_t_aaaa,
288 Callback,
289 GetQueryArg());
290 return 0;
291 }
292
293 protected:
294 void Parse(unsigned char* buf, int len) {
295 HandleScope scope;
296
297 struct hostent* host;
298
299 int status = ares_parse_aaaa_reply(buf, len, &host, NULL, NULL);
300 if (status != ARES_SUCCESS) {
301 this->ParseError(status);
302 return;
303 }
304
305 Local<Array> addresses = HostentToAddresses(host);
306 ares_free_hostent(host);
307
12798c6 @ry dns callbacks should go through MakeCallback
ry authored
308 this->CallOnComplete(addresses);
858f230 @piscisaureus Bindings for libuv-integrated c-ares
piscisaureus authored
309 }
310 };
311
312
313 class QueryCnameWrap: public QueryWrap {
314 public:
315 int Send(const char* name) {
316 ares_query(ares_channel,
317 name,
318 ns_c_in,
319 ns_t_cname,
320 Callback,
321 GetQueryArg());
322 return 0;
323 }
324
325 protected:
326 void Parse(unsigned char* buf, int len) {
327 HandleScope scope;
328
329 struct hostent* host;
330
331 int status = ares_parse_a_reply(buf, len, &host, NULL, NULL);
332 if (status != ARES_SUCCESS) {
333 this->ParseError(status);
334 return;
335 }
336
337 // A cname lookup always returns a single record but we follow the
338 // common API here.
339 Local<Array> result = Array::New(1);
340 result->Set(0, String::New(host->h_name));
341 ares_free_hostent(host);
342
12798c6 @ry dns callbacks should go through MakeCallback
ry authored
343 this->CallOnComplete(result);
858f230 @piscisaureus Bindings for libuv-integrated c-ares
piscisaureus authored
344 }
345 };
346
347
348 class QueryMxWrap: public QueryWrap {
349 public:
350 int Send(const char* name) {
351 ares_query(ares_channel, name, ns_c_in, ns_t_mx, Callback, GetQueryArg());
352 return 0;
353 }
354
355 protected:
356 void Parse(unsigned char* buf, int len) {
357 HandleScope scope;
358
359 struct ares_mx_reply* mx_start;
360 int status = ares_parse_mx_reply(buf, len, &mx_start);
361 if (status != ARES_SUCCESS) {
362 this->ParseError(status);
363 return;
364 }
365
366 Local<Array> mx_records = Array::New();
367 Local<String> exchange_symbol = String::NewSymbol("exchange");
368 Local<String> priority_symbol = String::NewSymbol("priority");
369 int i = 0;
370 for (struct ares_mx_reply* mx_current = mx_start;
371 mx_current;
372 mx_current = mx_current->next) {
373 Local<Object> mx_record = Object::New();
374 mx_record->Set(exchange_symbol, String::New(mx_current->host));
375 mx_record->Set(priority_symbol, Integer::New(mx_current->priority));
376 mx_records->Set(Integer::New(i++), mx_record);
377 }
378
379 ares_free_data(mx_start);
380
12798c6 @ry dns callbacks should go through MakeCallback
ry authored
381 this->CallOnComplete(mx_records);
858f230 @piscisaureus Bindings for libuv-integrated c-ares
piscisaureus authored
382 }
383 };
384
385
386 class QueryNsWrap: public QueryWrap {
387 public:
388 int Send(const char* name) {
389 ares_query(ares_channel, name, ns_c_in, ns_t_ns, Callback, GetQueryArg());
390 return 0;
391 }
392
393 protected:
394 void Parse(unsigned char* buf, int len) {
395 struct hostent* host;
396
397 int status = ares_parse_ns_reply(buf, len, &host);
398 if (status != ARES_SUCCESS) {
399 this->ParseError(status);
400 return;
401 }
402
403 Local<Array> names = HostentToNames(host);
404 ares_free_hostent(host);
405
12798c6 @ry dns callbacks should go through MakeCallback
ry authored
406 this->CallOnComplete(names);
858f230 @piscisaureus Bindings for libuv-integrated c-ares
piscisaureus authored
407 }
408 };
409
410
d9c67ae @tellnes dns: implement resolveTxt()
tellnes authored
411 class QueryTxtWrap: public QueryWrap {
412 public:
413 int Send(const char* name) {
414 ares_query(ares_channel, name, ns_c_in, ns_t_txt, Callback, GetQueryArg());
415 return 0;
416 }
417
418 protected:
419 void Parse(unsigned char* buf, int len) {
420 struct ares_txt_reply* txt_out;
421
422 int status = ares_parse_txt_reply(buf, len, &txt_out);
423 if (status != ARES_SUCCESS) {
424 this->ParseError(status);
425 return;
426 }
427
428 Local<Array> txt_records = Array::New();
429
430 struct ares_txt_reply *current = txt_out;
431 for (int i = 0; current; ++i, current = current->next) {
432 Local<String> txt = String::New(reinterpret_cast<char*>(current->txt));
433 txt_records->Set(Integer::New(i), txt);
434 }
435
436 ares_free_data(txt_out);
437
438 this->CallOnComplete(txt_records);
439 }
440 };
441
442
858f230 @piscisaureus Bindings for libuv-integrated c-ares
piscisaureus authored
443 class QuerySrvWrap: public QueryWrap {
444 public:
445 int Send(const char* name) {
446 ares_query(ares_channel,
447 name,
448 ns_c_in,
449 ns_t_srv,
450 Callback,
451 GetQueryArg());
452 return 0;
453 }
454
455 protected:
456 void Parse(unsigned char* buf, int len) {
457 HandleScope scope;
458
459 struct ares_srv_reply* srv_start;
460 int status = ares_parse_srv_reply(buf, len, &srv_start);
461 if (status != ARES_SUCCESS) {
462 this->ParseError(status);
463 return;
464 }
465
466 Local<Array> srv_records = Array::New();
72e18d7 dns_uv: match the old api better, fix tests
Bert Belder authored
467 Local<String> name_symbol = String::NewSymbol("name");
858f230 @piscisaureus Bindings for libuv-integrated c-ares
piscisaureus authored
468 Local<String> port_symbol = String::NewSymbol("port");
469 Local<String> priority_symbol = String::NewSymbol("priority");
470 Local<String> weight_symbol = String::NewSymbol("weight");
471 int i = 0;
472 for (struct ares_srv_reply* srv_current = srv_start;
473 srv_current;
474 srv_current = srv_current->next) {
475 Local<Object> srv_record = Object::New();
72e18d7 dns_uv: match the old api better, fix tests
Bert Belder authored
476 srv_record->Set(name_symbol, String::New(srv_current->host));
858f230 @piscisaureus Bindings for libuv-integrated c-ares
piscisaureus authored
477 srv_record->Set(port_symbol, Integer::New(srv_current->port));
478 srv_record->Set(priority_symbol, Integer::New(srv_current->priority));
479 srv_record->Set(weight_symbol, Integer::New(srv_current->weight));
480 srv_records->Set(Integer::New(i++), srv_record);
481 }
482
483 ares_free_data(srv_start);
484
12798c6 @ry dns callbacks should go through MakeCallback
ry authored
485 this->CallOnComplete(srv_records);
858f230 @piscisaureus Bindings for libuv-integrated c-ares
piscisaureus authored
486 }
487 };
488
489
490 class GetHostByAddrWrap: public QueryWrap {
491 public:
492 int Send(const char* name) {
493 int length, family;
494 char address_buffer[sizeof(struct in6_addr)];
495
496 if (uv_inet_pton(AF_INET, name, &address_buffer) == 1) {
497 length = sizeof(struct in_addr);
498 family = AF_INET;
499 } else if (uv_inet_pton(AF_INET6, name, &address_buffer) == 1) {
500 length = sizeof(struct in6_addr);
501 family = AF_INET6;
502 } else {
503 return ARES_ENOTIMP;
504 }
505
506 ares_gethostbyaddr(ares_channel,
507 address_buffer,
508 length,
509 family,
510 Callback,
511 GetQueryArg());
512 return 0;
513 }
514
515 protected:
516 void Parse(struct hostent* host) {
517 HandleScope scope;
518
12798c6 @ry dns callbacks should go through MakeCallback
ry authored
519 this->CallOnComplete(HostentToNames(host));
858f230 @piscisaureus Bindings for libuv-integrated c-ares
piscisaureus authored
520 }
521 };
522
523
524 class GetHostByNameWrap: public QueryWrap {
525 public:
526 int Send(const char* name, int family) {
527 ares_gethostbyname(ares_channel, name, family, Callback, GetQueryArg());
528 return 0;
529 }
530
531 protected:
532 void Parse(struct hostent* host) {
533 HandleScope scope;
534
535 Local<Array> addresses = HostentToAddresses(host);
536 Local<Integer> family = Integer::New(host->h_addrtype);
537
12798c6 @ry dns callbacks should go through MakeCallback
ry authored
538 this->CallOnComplete(addresses, family);
858f230 @piscisaureus Bindings for libuv-integrated c-ares
piscisaureus authored
539 }
540 };
541
542
543 template <class Wrap>
544 static Handle<Value> Query(const Arguments& args) {
545 HandleScope scope;
546
547 assert(!args.IsConstructCall());
548 assert(args.Length() >= 2);
549 assert(args[1]->IsFunction());
550
551 Wrap* wrap = new Wrap();
12798c6 @ry dns callbacks should go through MakeCallback
ry authored
552 wrap->SetOnComplete(args[1]);
858f230 @piscisaureus Bindings for libuv-integrated c-ares
piscisaureus authored
553
554 // We must cache the wrap's js object here, because cares might make the
555 // callback from the wrap->Send stack. This will destroy the wrap's internal
556 // object reference, causing wrap->GetObject() to return undefined.
557 Local<Object> object = Local<Object>::New(wrap->GetObject());
558
15f0e0a @tjfontaine src: replace usage of String::Utf8Value
tjfontaine authored
559 node::Utf8Value name(args[0]);
858f230 @piscisaureus Bindings for libuv-integrated c-ares
piscisaureus authored
560
561 int r = wrap->Send(*name);
562 if (r) {
563 SetAresErrno(r);
564 delete wrap;
565 return scope.Close(v8::Null());
566 } else {
567 return scope.Close(object);
568 }
569 }
570
571
572 template <class Wrap>
573 static Handle<Value> QueryWithFamily(const Arguments& args) {
574 HandleScope scope;
575
576 assert(!args.IsConstructCall());
577 assert(args.Length() >= 3);
578 assert(args[2]->IsFunction());
579
580 Wrap* wrap = new Wrap();
12798c6 @ry dns callbacks should go through MakeCallback
ry authored
581 wrap->SetOnComplete(args[2]);
858f230 @piscisaureus Bindings for libuv-integrated c-ares
piscisaureus authored
582
583 // We must cache the wrap's js object here, because cares might make the
584 // callback from the wrap->Send stack. This will destroy the wrap's internal
585 // object reference, causing wrap->GetObject() to return undefined.
586 Local<Object> object = Local<Object>::New(wrap->GetObject());
587
15f0e0a @tjfontaine src: replace usage of String::Utf8Value
tjfontaine authored
588 node::Utf8Value name(args[0]);
858f230 @piscisaureus Bindings for libuv-integrated c-ares
piscisaureus authored
589 int family = args[1]->Int32Value();
590
591 int r = wrap->Send(*name, family);
592 if (r) {
593 SetAresErrno(r);
594 delete wrap;
595 return scope.Close(v8::Null());
596 } else {
597 return scope.Close(object);
598 }
599 }
600
601
be2320d @ry Add binding to uv_getaddrinfo
ry authored
602 void AfterGetAddrInfo(uv_getaddrinfo_t* req, int status, struct addrinfo* res) {
603 HandleScope scope;
604
605 GetAddrInfoReqWrap* req_wrap = (GetAddrInfoReqWrap*) req->data;
606
607 Local<Value> argv[1];
608
609 if (status) {
610 // Error
74a8215 @bnoordhuis Revert support for isolates.
bnoordhuis authored
611 SetErrno(uv_last_error(uv_default_loop()));
be2320d @ry Add binding to uv_getaddrinfo
ry authored
612 argv[0] = Local<Value>::New(Null());
613 } else {
614 // Success
615 struct addrinfo *address;
616 int n = 0;
617
618 // Count the number of responses.
619 for (address = res; address; address = address->ai_next) {
620 n++;
621 }
622
623 // Create the response array.
624 Local<Array> results = Array::New(n);
625
626 char ip[INET6_ADDRSTRLEN];
627 const char *addr;
628
629 n = 0;
630
194511f @ry Return IPv4 addresses before IPv6 addresses from getaddrinfo
ry authored
631 // Iterate over the IPv4 responses again this time creating javascript
be2320d @ry Add binding to uv_getaddrinfo
ry authored
632 // strings for each IP and filling the results array.
633 address = res;
634 while (address) {
635 assert(address->ai_socktype == SOCK_STREAM);
636
c83dda8 @ry dns.lookup uses cares_wrap::GetAddrInfo
ry authored
637 // Ignore random ai_family types.
194511f @ry Return IPv4 addresses before IPv6 addresses from getaddrinfo
ry authored
638 if (address->ai_family == AF_INET) {
c83dda8 @ry dns.lookup uses cares_wrap::GetAddrInfo
ry authored
639 // Juggle pointers
194511f @ry Return IPv4 addresses before IPv6 addresses from getaddrinfo
ry authored
640 addr = (char*) &((struct sockaddr_in*) address->ai_addr)->sin_addr;
c83dda8 @ry dns.lookup uses cares_wrap::GetAddrInfo
ry authored
641 const char* c = uv_inet_ntop(address->ai_family, addr, ip,
642 INET6_ADDRSTRLEN);
be2320d @ry Add binding to uv_getaddrinfo
ry authored
643
c83dda8 @ry dns.lookup uses cares_wrap::GetAddrInfo
ry authored
644 // Create JavaScript string
645 Local<String> s = String::New(c);
646 results->Set(n, s);
194511f @ry Return IPv4 addresses before IPv6 addresses from getaddrinfo
ry authored
647 n++;
648 }
649
650 // Increment
651 address = address->ai_next;
652 }
653
654 // Iterate over the IPv6 responses putting them in the array.
655 address = res;
656 while (address) {
657 assert(address->ai_socktype == SOCK_STREAM);
658
659 // Ignore random ai_family types.
660 if (address->ai_family == AF_INET6) {
661 // Juggle pointers
662 addr = (char*) &((struct sockaddr_in6*) address->ai_addr)->sin6_addr;
663 const char* c = uv_inet_ntop(address->ai_family, addr, ip,
664 INET6_ADDRSTRLEN);
665
666 // Create JavaScript string
667 Local<String> s = String::New(c);
668 results->Set(n, s);
669 n++;
c83dda8 @ry dns.lookup uses cares_wrap::GetAddrInfo
ry authored
670 }
be2320d @ry Add binding to uv_getaddrinfo
ry authored
671
672 // Increment
673 address = address->ai_next;
674 }
675
194511f @ry Return IPv4 addresses before IPv6 addresses from getaddrinfo
ry authored
676
be2320d @ry Add binding to uv_getaddrinfo
ry authored
677 argv[0] = results;
678 }
679
680 uv_freeaddrinfo(res);
681
682 // Make the callback into JavaScript
a26bee8 @isaacs MakeCallback: Consistent symbol usage
isaacs authored
683 MakeCallback(req_wrap->object_, oncomplete_sym, ARRAY_SIZE(argv), argv);
be2320d @ry Add binding to uv_getaddrinfo
ry authored
684
685 delete req_wrap;
686 }
687
688
c9f2531 @snoj net: More accurate IP address validation and IPv6 dotted notation.
snoj authored
689 static Handle<Value> IsIP(const Arguments& args) {
690 HandleScope scope;
691
692 String::AsciiValue ip(args[0]);
693 char address_buffer[sizeof(struct in6_addr)];
694
695 if (uv_inet_pton(AF_INET, *ip, &address_buffer) == 1) {
696 return scope.Close(v8::Integer::New(4));
697 }
698
699 if (uv_inet_pton(AF_INET6, *ip, &address_buffer) == 1) {
700 return scope.Close(v8::Integer::New(6));
701 }
702
703 return scope.Close(v8::Integer::New(0));
704 }
705
706
be2320d @ry Add binding to uv_getaddrinfo
ry authored
707 static Handle<Value> GetAddrInfo(const Arguments& args) {
708 HandleScope scope;
709
15f0e0a @tjfontaine src: replace usage of String::Utf8Value
tjfontaine authored
710 node::Utf8Value hostname(args[0]);
be2320d @ry Add binding to uv_getaddrinfo
ry authored
711
c83dda8 @ry dns.lookup uses cares_wrap::GetAddrInfo
ry authored
712 int fam = AF_UNSPEC;
713 if (args[1]->IsInt32()) {
714 switch (args[1]->Int32Value()) {
715 case 6:
716 fam = AF_INET6;
717 break;
718
719 case 4:
720 fam = AF_INET;
721 break;
722 }
be2320d @ry Add binding to uv_getaddrinfo
ry authored
723 }
724
725 GetAddrInfoReqWrap* req_wrap = new GetAddrInfoReqWrap();
726
727 struct addrinfo hints;
728 memset(&hints, 0, sizeof(struct addrinfo));
729 hints.ai_family = fam;
730 hints.ai_socktype = SOCK_STREAM;
731
74a8215 @bnoordhuis Revert support for isolates.
bnoordhuis authored
732 int r = uv_getaddrinfo(uv_default_loop(),
be2320d @ry Add binding to uv_getaddrinfo
ry authored
733 &req_wrap->req_,
734 AfterGetAddrInfo,
735 *hostname,
736 NULL,
737 &hints);
738 req_wrap->Dispatched();
739
740 if (r) {
74a8215 @bnoordhuis Revert support for isolates.
bnoordhuis authored
741 SetErrno(uv_last_error(uv_default_loop()));
be2320d @ry Add binding to uv_getaddrinfo
ry authored
742 delete req_wrap;
743 return scope.Close(v8::Null());
744 } else {
745 return scope.Close(req_wrap->object_);
746 }
747 }
748
749
858f230 @piscisaureus Bindings for libuv-integrated c-ares
piscisaureus authored
750 static void Initialize(Handle<Object> target) {
751 HandleScope scope;
752 int r;
753
754 r = ares_library_init(ARES_LIB_INIT_ALL);
755 assert(r == ARES_SUCCESS);
756
757 struct ares_options options;
74a8215 @bnoordhuis Revert support for isolates.
bnoordhuis authored
758 uv_ares_init_options(uv_default_loop(), &ares_channel, &options, 0);
858f230 @piscisaureus Bindings for libuv-integrated c-ares
piscisaureus authored
759 assert(r == 0);
760
761 NODE_SET_METHOD(target, "queryA", Query<QueryAWrap>);
762 NODE_SET_METHOD(target, "queryAaaa", Query<QueryAaaaWrap>);
763 NODE_SET_METHOD(target, "queryCname", Query<QueryCnameWrap>);
764 NODE_SET_METHOD(target, "queryMx", Query<QueryMxWrap>);
765 NODE_SET_METHOD(target, "queryNs", Query<QueryNsWrap>);
d9c67ae @tellnes dns: implement resolveTxt()
tellnes authored
766 NODE_SET_METHOD(target, "queryTxt", Query<QueryTxtWrap>);
858f230 @piscisaureus Bindings for libuv-integrated c-ares
piscisaureus authored
767 NODE_SET_METHOD(target, "querySrv", Query<QuerySrvWrap>);
768 NODE_SET_METHOD(target, "getHostByAddr", Query<GetHostByAddrWrap>);
769 NODE_SET_METHOD(target, "getHostByName", QueryWithFamily<GetHostByNameWrap>);
770
be2320d @ry Add binding to uv_getaddrinfo
ry authored
771 NODE_SET_METHOD(target, "getaddrinfo", GetAddrInfo);
c9f2531 @snoj net: More accurate IP address validation and IPv6 dotted notation.
snoj authored
772 NODE_SET_METHOD(target, "isIP", IsIP);
be2320d @ry Add binding to uv_getaddrinfo
ry authored
773
858f230 @piscisaureus Bindings for libuv-integrated c-ares
piscisaureus authored
774 target->Set(String::NewSymbol("AF_INET"), Integer::New(AF_INET));
775 target->Set(String::NewSymbol("AF_INET6"), Integer::New(AF_INET6));
776 target->Set(String::NewSymbol("AF_UNSPEC"), Integer::New(AF_UNSPEC));
777
a26bee8 @isaacs MakeCallback: Consistent symbol usage
isaacs authored
778 oncomplete_sym = NODE_PSYMBOL("oncomplete");
858f230 @piscisaureus Bindings for libuv-integrated c-ares
piscisaureus authored
779 }
780
781
782 } // namespace cares_wrap
783
784 } // namespace node
785
cdcb111 @bnoordhuis Remove stray NODE_MODULE() semi-colons.
bnoordhuis authored
786 NODE_MODULE(node_cares_wrap, node::cares_wrap::Initialize)
Something went wrong with that request. Please try again.