mirror of https://github.com/nodejs/node.git
Add binding to uv_getaddrinfo
parent
95d530f2b4
commit
be2320d408
|
@ -21,8 +21,11 @@
|
|||
|
||||
#include <assert.h>
|
||||
#include <node.h>
|
||||
#include <req_wrap.h>
|
||||
#include <uv.h>
|
||||
|
||||
#include <string.h>
|
||||
|
||||
#if defined(__OpenBSD__) || defined(__MINGW32__) || defined(_MSC_VER)
|
||||
# include <nameser.h>
|
||||
#else
|
||||
|
@ -63,6 +66,9 @@ using v8::Persistent;
|
|||
using v8::String;
|
||||
using v8::Value;
|
||||
|
||||
|
||||
typedef class ReqWrap<uv_getaddrinfo_t> GetAddrInfoReqWrap;
|
||||
|
||||
static Persistent<String> oncomplete_sym;
|
||||
|
||||
static ares_channel ares_channel;
|
||||
|
@ -592,6 +598,104 @@ static Handle<Value> QueryWithFamily(const Arguments& args) {
|
|||
}
|
||||
|
||||
|
||||
void AfterGetAddrInfo(uv_getaddrinfo_t* req, int status, struct addrinfo* res) {
|
||||
HandleScope scope;
|
||||
|
||||
GetAddrInfoReqWrap* req_wrap = (GetAddrInfoReqWrap*) req->data;
|
||||
|
||||
Local<Value> argv[1];
|
||||
|
||||
if (status) {
|
||||
// Error
|
||||
SetErrno(uv_last_error(uv_default_loop()));
|
||||
argv[0] = Local<Value>::New(Null());
|
||||
} else {
|
||||
// Success
|
||||
struct addrinfo *address;
|
||||
int n = 0;
|
||||
|
||||
// Count the number of responses.
|
||||
for (address = res; address; address = address->ai_next) {
|
||||
n++;
|
||||
}
|
||||
|
||||
// Create the response array.
|
||||
Local<Array> results = Array::New(n);
|
||||
|
||||
char ip[INET6_ADDRSTRLEN];
|
||||
const char *addr;
|
||||
|
||||
n = 0;
|
||||
|
||||
// Iterate over the responses again this time creating javascript
|
||||
// strings for each IP and filling the results array.
|
||||
address = res;
|
||||
while (address) {
|
||||
assert(address->ai_socktype == SOCK_STREAM);
|
||||
assert(address->ai_family == AF_INET || address->ai_family == AF_INET6);
|
||||
|
||||
// Juggle pointers
|
||||
addr = (address->ai_family == AF_INET ?
|
||||
(char*) &((struct sockaddr_in*) address->ai_addr)->sin_addr :
|
||||
(char*) &((struct sockaddr_in6*) address->ai_addr)->sin6_addr);
|
||||
const char* c = inet_ntop(address->ai_family, addr, ip, INET6_ADDRSTRLEN);
|
||||
|
||||
// Create JavaScript string
|
||||
Local<String> s = String::New(c);
|
||||
results->Set(n, s);
|
||||
|
||||
// Increment
|
||||
n++;
|
||||
address = address->ai_next;
|
||||
}
|
||||
|
||||
argv[0] = results;
|
||||
}
|
||||
|
||||
uv_freeaddrinfo(res);
|
||||
|
||||
// Make the callback into JavaScript
|
||||
MakeCallback(req_wrap->object_, "oncomplete", 1, argv);
|
||||
|
||||
delete req_wrap;
|
||||
}
|
||||
|
||||
|
||||
static Handle<Value> GetAddrInfo(const Arguments& args) {
|
||||
HandleScope scope;
|
||||
|
||||
String::Utf8Value hostname(args[0]->ToString());
|
||||
|
||||
int fam = AF_INET;
|
||||
if (args[1]->IsInt32() && args[1]->Int32Value() == 6) {
|
||||
fam = AF_INET6;
|
||||
}
|
||||
|
||||
GetAddrInfoReqWrap* req_wrap = new GetAddrInfoReqWrap();
|
||||
|
||||
struct addrinfo hints;
|
||||
memset(&hints, 0, sizeof(struct addrinfo));
|
||||
hints.ai_family = fam;
|
||||
hints.ai_socktype = SOCK_STREAM;
|
||||
|
||||
int r = uv_getaddrinfo(uv_default_loop(),
|
||||
&req_wrap->req_,
|
||||
AfterGetAddrInfo,
|
||||
*hostname,
|
||||
NULL,
|
||||
&hints);
|
||||
req_wrap->Dispatched();
|
||||
|
||||
if (r) {
|
||||
SetErrno(uv_last_error(uv_default_loop()));
|
||||
delete req_wrap;
|
||||
return scope.Close(v8::Null());
|
||||
} else {
|
||||
return scope.Close(req_wrap->object_);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void Initialize(Handle<Object> target) {
|
||||
HandleScope scope;
|
||||
int r;
|
||||
|
@ -613,6 +717,8 @@ static void Initialize(Handle<Object> target) {
|
|||
NODE_SET_METHOD(target, "getHostByAddr", Query<GetHostByAddrWrap>);
|
||||
NODE_SET_METHOD(target, "getHostByName", QueryWithFamily<GetHostByNameWrap>);
|
||||
|
||||
NODE_SET_METHOD(target, "getaddrinfo", GetAddrInfo);
|
||||
|
||||
target->Set(String::NewSymbol("AF_INET"), Integer::New(AF_INET));
|
||||
target->Set(String::NewSymbol("AF_INET6"), Integer::New(AF_INET6));
|
||||
target->Set(String::NewSymbol("AF_UNSPEC"), Integer::New(AF_UNSPEC));
|
||||
|
|
|
@ -21,7 +21,7 @@
|
|||
|
||||
var assert = require('assert'),
|
||||
dns = require('dns'),
|
||||
net = require('net_uv'),
|
||||
net = require('net'),
|
||||
isIP = net.isIP,
|
||||
isIPv4 = net.isIPv4,
|
||||
isIPv6 = net.isIPv6;
|
||||
|
@ -57,13 +57,6 @@ function TEST(f) {
|
|||
}
|
||||
|
||||
|
||||
process.on('exit', function() {
|
||||
console.log(completed + ' tests completed');
|
||||
assert.equal(running, false);
|
||||
assert.strictEqual(expected, completed);
|
||||
});
|
||||
|
||||
|
||||
function checkWrap(req) {
|
||||
assert.ok(typeof req === 'object');
|
||||
}
|
||||
|
@ -386,3 +379,26 @@ TEST(function test_lookup_localhost_ipv4(done) {
|
|||
|
||||
checkWrap(req);
|
||||
}); */
|
||||
|
||||
|
||||
var getaddrinfoCallbackCalled = false;
|
||||
|
||||
console.log("looking up nodejs.org...");
|
||||
var req = process.binding('cares_wrap').getaddrinfo('nodejs.org');
|
||||
|
||||
req.oncomplete = function(domains) {
|
||||
console.log("nodejs.org = ", domains);
|
||||
assert.ok(Array.isArray(domains));
|
||||
assert.ok(domains.length >= 1);
|
||||
assert.ok(typeof domains[0] == 'string');
|
||||
getaddrinfoCallbackCalled = true;
|
||||
};
|
||||
|
||||
|
||||
|
||||
process.on('exit', function() {
|
||||
console.log(completed + ' tests completed');
|
||||
assert.equal(running, false);
|
||||
assert.strictEqual(expected, completed);
|
||||
assert.ok(getaddrinfoCallbackCalled);
|
||||
});
|
||||
|
|
Loading…
Reference in New Issue