[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:
Родитель
9395786d11
Коммит
fd3cd755d1
|
@ -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
|
||||
|
|
44
lib/dgram.js
44
lib/dgram.js
|
@ -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);
|
||||
|
|
99
lib/dns.js
99
lib/dns.js
|
@ -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,
|
||||
|
|
Загрузка…
Ссылка в новой задаче