Skip to content
This repository
Newer
Older
100644 785 lines (612 sloc) 19.729 kb
858f2309 » piscisaureus
2011-07-05 Bindings for libuv-integrated c-ares
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>
ff4a9d38 » bnoordhuis
2012-03-10 core: use proper #include directives
23 #include "node.h"
24 #include "req_wrap.h"
25 #include "uv.h"
858f2309 » piscisaureus
2011-07-05 Bindings for libuv-integrated c-ares
26
be2320d4 » ry
2011-10-20 Add binding to uv_getaddrinfo
27 #include <string.h>
28
13d6a1f6 » DrPizza
2011-08-06 Basic VC++ compatibility work.
29 #if defined(__OpenBSD__) || defined(__MINGW32__) || defined(_MSC_VER)
858f2309 » piscisaureus
2011-07-05 Bindings for libuv-integrated c-ares
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.
13d6a1f6 » DrPizza
2011-08-06 Basic VC++ compatibility work.
36 #if defined(__MINGW32__) || defined(_MSC_VER)
858f2309 » piscisaureus
2011-07-05 Bindings for libuv-integrated c-ares
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
be2320d4 » ry
2011-10-20 Add binding to uv_getaddrinfo
69
70 typedef class ReqWrap<uv_getaddrinfo_t> GetAddrInfoReqWrap;
71
74a8215a » bnoordhuis
2012-02-03 Revert support for isolates.
72 static Persistent<String> oncomplete_sym;
73
74 static ares_channel ares_channel;
75
76
858f2309 » piscisaureus
2011-07-05 Bindings for libuv-integrated c-ares
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
f1d3ae77 » bnoordhuis
2011-10-14 cares_wrap: make destructor virtual
158 virtual ~QueryWrap() {
858f2309 » piscisaureus
2011-07-05 Bindings for libuv-integrated c-ares
159 assert(!object_.IsEmpty());
160
12798c62 » ry
2011-09-18 dns callbacks should go through MakeCallback
161 object_->Delete(oncomplete_sym);
858f2309 » piscisaureus
2011-07-05 Bindings for libuv-integrated c-ares
162
163 object_.Dispose();
164 object_.Clear();
165 }
166
167 Handle<Object> GetObject() {
168 return object_;
169 }
170
12798c62 » ry
2011-09-18 dns callbacks should go through MakeCallback
171 void SetOnComplete(Handle<Value> oncomplete) {
172 assert(oncomplete->IsFunction());
173 object_->Set(oncomplete_sym, oncomplete);
858f2309 » piscisaureus
2011-07-05 Bindings for libuv-integrated c-ares
174 }
175
176 // Subclasses should implement the appropriate Send method.
177 virtual int Send(const char* name) {
178 assert(0);
13d6a1f6 » DrPizza
2011-08-06 Basic VC++ compatibility work.
179 return 0;
858f2309 » piscisaureus
2011-07-05 Bindings for libuv-integrated c-ares
180 }
181
182 virtual int Send(const char* name, int family) {
183 assert(0);
13d6a1f6 » DrPizza
2011-08-06 Basic VC++ compatibility work.
184 return 0;
858f2309 » piscisaureus
2011-07-05 Bindings for libuv-integrated c-ares
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
12798c62 » ry
2011-09-18 dns callbacks should go through MakeCallback
218 void CallOnComplete(Local<Value> answer) {
858f2309 » piscisaureus
2011-07-05 Bindings for libuv-integrated c-ares
219 HandleScope scope;
220 Local<Value> argv[2] = { Integer::New(0), answer };
a26bee8f » isaacs
2012-04-12 MakeCallback: Consistent symbol usage
221 MakeCallback(object_, oncomplete_sym, ARRAY_SIZE(argv), argv);
858f2309 » piscisaureus
2011-07-05 Bindings for libuv-integrated c-ares
222 }
223
12798c62 » ry
2011-09-18 dns callbacks should go through MakeCallback
224 void CallOnComplete(Local<Value> answer, Local<Value> family) {
858f2309 » piscisaureus
2011-07-05 Bindings for libuv-integrated c-ares
225 HandleScope scope;
226 Local<Value> argv[3] = { Integer::New(0), answer, family };
a26bee8f » isaacs
2012-04-12 MakeCallback: Consistent symbol usage
227 MakeCallback(object_, oncomplete_sym, ARRAY_SIZE(argv), argv);
858f2309 » piscisaureus
2011-07-05 Bindings for libuv-integrated c-ares
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) };
a26bee8f » isaacs
2012-04-12 MakeCallback: Consistent symbol usage
236 MakeCallback(object_, oncomplete_sym, ARRAY_SIZE(argv), argv);
858f2309 » piscisaureus
2011-07-05 Bindings for libuv-integrated c-ares
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
12798c62 » ry
2011-09-18 dns callbacks should go through MakeCallback
275 this->CallOnComplete(addresses);
858f2309 » piscisaureus
2011-07-05 Bindings for libuv-integrated c-ares
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
12798c62 » ry
2011-09-18 dns callbacks should go through MakeCallback
307 this->CallOnComplete(addresses);
858f2309 » piscisaureus
2011-07-05 Bindings for libuv-integrated c-ares
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
12798c62 » ry
2011-09-18 dns callbacks should go through MakeCallback
342 this->CallOnComplete(result);
858f2309 » piscisaureus
2011-07-05 Bindings for libuv-integrated c-ares
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
12798c62 » ry
2011-09-18 dns callbacks should go through MakeCallback
380 this->CallOnComplete(mx_records);
858f2309 » piscisaureus
2011-07-05 Bindings for libuv-integrated c-ares
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
12798c62 » ry
2011-09-18 dns callbacks should go through MakeCallback
405 this->CallOnComplete(names);
858f2309 » piscisaureus
2011-07-05 Bindings for libuv-integrated c-ares
406 }
407 };
408
409
d9c67aeb » tellnes
2011-10-03 dns: implement resolveTxt()
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
858f2309 » piscisaureus
2011-07-05 Bindings for libuv-integrated c-ares
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();
72e18d7f » Bert Belder
2011-07-05 dns_uv: match the old api better, fix tests
466 Local<String> name_symbol = String::NewSymbol("name");
858f2309 » piscisaureus
2011-07-05 Bindings for libuv-integrated c-ares
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();
72e18d7f » Bert Belder
2011-07-05 dns_uv: match the old api better, fix tests
475 srv_record->Set(name_symbol, String::New(srv_current->host));
858f2309 » piscisaureus
2011-07-05 Bindings for libuv-integrated c-ares
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
12798c62 » ry
2011-09-18 dns callbacks should go through MakeCallback
484 this->CallOnComplete(srv_records);
858f2309 » piscisaureus
2011-07-05 Bindings for libuv-integrated c-ares
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
12798c62 » ry
2011-09-18 dns callbacks should go through MakeCallback
518 this->CallOnComplete(HostentToNames(host));
858f2309 » piscisaureus
2011-07-05 Bindings for libuv-integrated c-ares
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
12798c62 » ry
2011-09-18 dns callbacks should go through MakeCallback
537 this->CallOnComplete(addresses, family);
858f2309 » piscisaureus
2011-07-05 Bindings for libuv-integrated c-ares
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();
12798c62 » ry
2011-09-18 dns callbacks should go through MakeCallback
551 wrap->SetOnComplete(args[1]);
858f2309 » piscisaureus
2011-07-05 Bindings for libuv-integrated c-ares
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
249c3c16 » ssuda
2012-03-21 Avoiding unnecessary ToString() calls
558 String::Utf8Value name(args[0]);
858f2309 » piscisaureus
2011-07-05 Bindings for libuv-integrated c-ares
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();
12798c62 » ry
2011-09-18 dns callbacks should go through MakeCallback
580 wrap->SetOnComplete(args[2]);
858f2309 » piscisaureus
2011-07-05 Bindings for libuv-integrated c-ares
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
249c3c16 » ssuda
2012-03-21 Avoiding unnecessary ToString() calls
587 String::Utf8Value name(args[0]);
858f2309 » piscisaureus
2011-07-05 Bindings for libuv-integrated c-ares
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
be2320d4 » ry
2011-10-20 Add binding to uv_getaddrinfo
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
74a8215a » bnoordhuis
2012-02-03 Revert support for isolates.
610 SetErrno(uv_last_error(uv_default_loop()));
be2320d4 » ry
2011-10-20 Add binding to uv_getaddrinfo
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
194511ff » ry
2011-10-26 Return IPv4 addresses before IPv6 addresses from getaddrinfo
630 // Iterate over the IPv4 responses again this time creating javascript
be2320d4 » ry
2011-10-20 Add binding to uv_getaddrinfo
631 // strings for each IP and filling the results array.
632 address = res;
633 while (address) {
634 assert(address->ai_socktype == SOCK_STREAM);
635
c83dda89 » ry
2011-10-20 dns.lookup uses cares_wrap::GetAddrInfo
636 // Ignore random ai_family types.
194511ff » ry
2011-10-26 Return IPv4 addresses before IPv6 addresses from getaddrinfo
637 if (address->ai_family == AF_INET) {
c83dda89 » ry
2011-10-20 dns.lookup uses cares_wrap::GetAddrInfo
638 // Juggle pointers
194511ff » ry
2011-10-26 Return IPv4 addresses before IPv6 addresses from getaddrinfo
639 addr = (char*) &((struct sockaddr_in*) address->ai_addr)->sin_addr;
c83dda89 » ry
2011-10-20 dns.lookup uses cares_wrap::GetAddrInfo
640 const char* c = uv_inet_ntop(address->ai_family, addr, ip,
641 INET6_ADDRSTRLEN);
be2320d4 » ry
2011-10-20 Add binding to uv_getaddrinfo
642
c83dda89 » ry
2011-10-20 dns.lookup uses cares_wrap::GetAddrInfo
643 // Create JavaScript string
644 Local<String> s = String::New(c);
645 results->Set(n, s);
194511ff » ry
2011-10-26 Return IPv4 addresses before IPv6 addresses from getaddrinfo
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++;
c83dda89 » ry
2011-10-20 dns.lookup uses cares_wrap::GetAddrInfo
669 }
be2320d4 » ry
2011-10-20 Add binding to uv_getaddrinfo
670
671 // Increment
672 address = address->ai_next;
673 }
674
194511ff » ry
2011-10-26 Return IPv4 addresses before IPv6 addresses from getaddrinfo
675
be2320d4 » ry
2011-10-20 Add binding to uv_getaddrinfo
676 argv[0] = results;
677 }
678
679 uv_freeaddrinfo(res);
680
681 // Make the callback into JavaScript
a26bee8f » isaacs
2012-04-12 MakeCallback: Consistent symbol usage
682 MakeCallback(req_wrap->object_, oncomplete_sym, ARRAY_SIZE(argv), argv);
be2320d4 » ry
2011-10-20 Add binding to uv_getaddrinfo
683
684 delete req_wrap;
685 }
686
687
c9f2531a » snoj
2012-10-08 net: More accurate IP address validation and IPv6 dotted notation.
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
be2320d4 » ry
2011-10-20 Add binding to uv_getaddrinfo
706 static Handle<Value> GetAddrInfo(const Arguments& args) {
707 HandleScope scope;
708
249c3c16 » ssuda
2012-03-21 Avoiding unnecessary ToString() calls
709 String::Utf8Value hostname(args[0]);
be2320d4 » ry
2011-10-20 Add binding to uv_getaddrinfo
710
c83dda89 » ry
2011-10-20 dns.lookup uses cares_wrap::GetAddrInfo
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 }
be2320d4 » ry
2011-10-20 Add binding to uv_getaddrinfo
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
74a8215a » bnoordhuis
2012-02-03 Revert support for isolates.
731 int r = uv_getaddrinfo(uv_default_loop(),
be2320d4 » ry
2011-10-20 Add binding to uv_getaddrinfo
732 &req_wrap->req_,
733 AfterGetAddrInfo,
734 *hostname,
735 NULL,
736 &hints);
737 req_wrap->Dispatched();
738
739 if (r) {
74a8215a » bnoordhuis
2012-02-03 Revert support for isolates.
740 SetErrno(uv_last_error(uv_default_loop()));
be2320d4 » ry
2011-10-20 Add binding to uv_getaddrinfo
741 delete req_wrap;
742 return scope.Close(v8::Null());
743 } else {
744 return scope.Close(req_wrap->object_);
745 }
746 }
747
748
858f2309 » piscisaureus
2011-07-05 Bindings for libuv-integrated c-ares
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;
74a8215a » bnoordhuis
2012-02-03 Revert support for isolates.
757 uv_ares_init_options(uv_default_loop(), &ares_channel, &options, 0);
858f2309 » piscisaureus
2011-07-05 Bindings for libuv-integrated c-ares
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>);
d9c67aeb » tellnes
2011-10-03 dns: implement resolveTxt()
765 NODE_SET_METHOD(target, "queryTxt", Query<QueryTxtWrap>);
858f2309 » piscisaureus
2011-07-05 Bindings for libuv-integrated c-ares
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
be2320d4 » ry
2011-10-20 Add binding to uv_getaddrinfo
770 NODE_SET_METHOD(target, "getaddrinfo", GetAddrInfo);
c9f2531a » snoj
2012-10-08 net: More accurate IP address validation and IPv6 dotted notation.
771 NODE_SET_METHOD(target, "isIP", IsIP);
be2320d4 » ry
2011-10-20 Add binding to uv_getaddrinfo
772
858f2309 » piscisaureus
2011-07-05 Bindings for libuv-integrated c-ares
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
a26bee8f » isaacs
2012-04-12 MakeCallback: Consistent symbol usage
777 oncomplete_sym = NODE_PSYMBOL("oncomplete");
858f2309 » piscisaureus
2011-07-05 Bindings for libuv-integrated c-ares
778 }
779
780
781 } // namespace cares_wrap
782
783 } // namespace node
784
cdcb1118 » bnoordhuis
2011-11-09 Remove stray NODE_MODULE() semi-colons.
785 NODE_MODULE(node_cares_wrap, node::cares_wrap::Initialize)
Something went wrong with that request. Please try again.