[dgram] only look up hostname for the requested address family

- [lib/dns.js] dns.lookup takes a new optional argument "family" which
  should be the integer 4, 6, dns.AF_INET or dns.AF_INET6. Passing a
  non-false "family" argument makes c-ares explicitly look up addresses for
  the specified family.

- [test/simple/test-c-ares.js] test explicit address family lookups
This commit is contained in:
Rasmus Andersson 2010-08-09 02:53:55 +02:00 коммит произвёл Ryan Dahl
Родитель 9395786d11
Коммит fd3cd755d1
3 изменённых файлов: 107 добавлений и 47 удалений

Просмотреть файл

@ -2515,6 +2515,17 @@ resolves the IP addresses which are returned.
});
});
### dns.lookup(domain, family=null, callback)
Resolves a domain (e.g. `'google.com'`) into the first found A (IPv4) or
AAAA (IPv6) record.
The callback has arguments `(err, address, family)`. The `address` argument
is a string representation of a IP v4 or v6 address. The `family` argument
is either the integer 4 or 6 and denotes the family of `address` (not
neccessarily the value initially passed to `lookup`).
### dns.resolve(domain, rrtype='A', callback)
Resolves a domain (e.g. `'google.com'`) into an array of the record types

Просмотреть файл

@ -28,6 +28,16 @@ function getPool() {
return pool;
}
function dnsLookup(type, hostname, callback) {
var family = (type ? ((type === "udp6") ? 6 : 4) : null);
dns.lookup(hostname, family, function (err, ip, addressFamily) {
if (!err && family && addressFamily !== family) {
err = new Error('no address found in family '+type+' for '+hostname);
}
callback(err, ip, addressFamily);
});
}
function Socket (type, listener) {
events.EventEmitter.call(this);
var self = this;
@ -103,22 +113,15 @@ Socket.prototype.bind = function () {
} else {
// the first argument is the port, the second an address
this.port = arguments[0];
if (dns.isIP(arguments[1])) {
this.address = arguments[1];
binding.bind(self.fd, port, arguments[1]);
this.emit("listening");
} else {
dns.lookup(arguments[1], function (err, ip, addressType) {
// TODO - only look up proper record for address family
if (err) {
self.emit('error', err);
} else {
self.ip = ip;
binding.bind(self.fd, self.port, ip);
self.emit("listening");
}
});
}
dnsLookup(this.type, arguments[1], function (err, ip, addressFamily) {
if (err) {
self.emit('error', err);
} else {
self.ip = ip;
binding.bind(self.fd, self.port, ip);
self.emit("listening");
}
});
}
}
};
@ -153,7 +156,7 @@ Socket.prototype.setTTL = function(arg) {
}
};
// translate arguments from JS API into C++ API, after optional DNS lookup
// translate arguments from JS API into C++ API, possibly after DNS lookup
Socket.prototype.send = function(buffer, offset, length) {
var self = this;
@ -173,13 +176,12 @@ Socket.prototype.send = function(buffer, offset, length) {
}
if (dns.isIP(arguments[4])) {
self.sendto(arguments[0], arguments[1], arguments[2], arguments[3], arguments[4], arguments[5]);
self.sendto(arguments[0], arguments[1], arguments[2], arguments[3],
arguments[4], arguments[5]);
} else {
var port = arguments[3],
callback = arguments[5];
// TODO - only look up proper record for address family
dns.lookup(arguments[4], function (err, ip, addressType) {
dnsLookup(this.type, arguments[4], function (err, ip, addressFamily) {
if (err) { // DNS error
if (callback) {
callback(err);

Просмотреть файл

@ -100,46 +100,93 @@ exports.getHostByName = function (domain, callback) {
var net;
// Easy DNS A/AAAA look up
exports.lookup = function (domain, callback) {
var addressType = dns.isIP(domain);
if (addressType) {
process.nextTick(function () {
callback(null, domain, addressType);
});
// lookup(domain, [family,] callback)
exports.lookup = function (domain, family, callback) {
if (arguments.length === 2) {
callback = family;
family = undefined;
} else if (family && family !== 4 && family !== 6) {
family = parseInt(family);
if (family === dns.AF_INET) {
family = 4;
} else if (family === dns.AF_INET6) {
family = 6;
} else if (family !== 4 && family !== 6) {
throw new Error('invalid argument: "family" must be 4 or 6');
}
}
if (!domain) {
callback(null, null, family === 6 ? 6 : 4);
return;
}
var matchedFamily = dns.isIP(domain);
if (matchedFamily) {
callback(null, domain, matchedFamily);
} else {
if (/\w\.local\.?$/.test(domain) ) {
if (/\w\.local\.?$/.test(domain)) {
// ANNOYING: In the case of mDNS domains use NSS in the thread pool.
// I wish c-ares had better support.
process.binding('net').getaddrinfo(domain, 4, function (err, domains4) {
callback(err, domains4[0], 4);
});
} else {
channel.getHostByName(domain, dns.AF_INET, function (err, domains4) {
if (domains4 && domains4.length) {
callback(null, domains4[0], 4);
} else {
channel.getHostByName(domain, dns.AF_INET6, function (err, domains6) {
if (domains6 && domains6.length) {
callback(null, domains6[0], 6);
if (family) {
// resolve names for explicit address family
var af = (family === 4) ? dns.AF_INET : dns.AF_INET6;
channel.getHostByName(domain, af, function (err, domains) {
if (!err && domains && domains.length) {
if (family !== dns.isIP(domains[0])) {
callback(new Error('not found'), []);
} else {
callback(err, []);
callback(null, domains[0], family);
}
});
}
});
} else {
callback(err, []);
}
});
} else {
// first resolve names for v4 and if that fails, try v6
channel.getHostByName(domain, dns.AF_INET, function (err, domains4) {
if (domains4 && domains4.length) {
callback(null, domains4[0], 4);
} else {
channel.getHostByName(domain, dns.AF_INET6,
function (err, domains6) {
if (domains6 && domains6.length) {
callback(null, domains6[0], 6);
} else {
callback(err, []);
}
});
}
});
}
}
}
};
exports.resolve4 = function(domain, callback) { channel.query(domain, dns.A, callback) };
exports.resolve6 = function(domain, callback) { channel.query(domain, dns.AAAA, callback) };
exports.resolveMx = function(domain, callback) { channel.query(domain, dns.MX, callback) };
exports.resolveTxt = function(domain, callback) { channel.query(domain, dns.TXT, callback) };
exports.resolveSrv = function(domain, callback) { channel.query(domain, dns.SRV, callback) };
exports.reverse = function(domain, callback) { channel.query(domain, dns.PTR, callback) };
exports.resolveNs = function(domain, callback) { channel.query(domain, dns.NS, callback) };
exports.resolve4 = function(domain, callback) {
channel.query(domain, dns.A, callback);
};
exports.resolve6 = function(domain, callback) {
channel.query(domain, dns.AAAA, callback);
};
exports.resolveMx = function(domain, callback) {
channel.query(domain, dns.MX, callback);
};
exports.resolveTxt = function(domain, callback) {
channel.query(domain, dns.TXT, callback);
};
exports.resolveSrv = function(domain, callback) {
channel.query(domain, dns.SRV, callback);
};
exports.reverse = function(domain, callback) {
channel.query(domain, dns.PTR, callback);
};
exports.resolveNs = function(domain, callback) {
channel.query(domain, dns.NS, callback);
};
var resolveMap = {
'A' : exports.resolve4,