Add binding to uv_getaddrinfo

pull/22966/head
Ryan Dahl 2011-10-20 15:06:53 -07:00
parent 95d530f2b4
commit be2320d408
2 changed files with 130 additions and 8 deletions

View File

@ -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));

View File

@ -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);
});