Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

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