[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:
parent
9395786d11
commit
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)
|
### dns.resolve(domain, rrtype='A', callback)
|
||||||
|
|
||||||
Resolves a domain (e.g. `'google.com'`) into an array of the record types
|
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;
|
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) {
|
function Socket (type, listener) {
|
||||||
events.EventEmitter.call(this);
|
events.EventEmitter.call(this);
|
||||||
var self = this;
|
var self = this;
|
||||||
@ -103,22 +113,15 @@ Socket.prototype.bind = function () {
|
|||||||
} else {
|
} else {
|
||||||
// the first argument is the port, the second an address
|
// the first argument is the port, the second an address
|
||||||
this.port = arguments[0];
|
this.port = arguments[0];
|
||||||
if (dns.isIP(arguments[1])) {
|
dnsLookup(this.type, arguments[1], function (err, ip, addressFamily) {
|
||||||
this.address = arguments[1];
|
if (err) {
|
||||||
binding.bind(self.fd, port, arguments[1]);
|
self.emit('error', err);
|
||||||
this.emit("listening");
|
} else {
|
||||||
} else {
|
self.ip = ip;
|
||||||
dns.lookup(arguments[1], function (err, ip, addressType) {
|
binding.bind(self.fd, self.port, ip);
|
||||||
// TODO - only look up proper record for address family
|
self.emit("listening");
|
||||||
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) {
|
Socket.prototype.send = function(buffer, offset, length) {
|
||||||
var self = this;
|
var self = this;
|
||||||
|
|
||||||
@ -173,13 +176,12 @@ Socket.prototype.send = function(buffer, offset, length) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (dns.isIP(arguments[4])) {
|
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 {
|
} else {
|
||||||
var port = arguments[3],
|
var port = arguments[3],
|
||||||
callback = arguments[5];
|
callback = arguments[5];
|
||||||
|
dnsLookup(this.type, arguments[4], function (err, ip, addressFamily) {
|
||||||
// TODO - only look up proper record for address family
|
|
||||||
dns.lookup(arguments[4], function (err, ip, addressType) {
|
|
||||||
if (err) { // DNS error
|
if (err) { // DNS error
|
||||||
if (callback) {
|
if (callback) {
|
||||||
callback(err);
|
callback(err);
|
||||||
|
99
lib/dns.js
99
lib/dns.js
@ -100,46 +100,93 @@ exports.getHostByName = function (domain, callback) {
|
|||||||
var net;
|
var net;
|
||||||
|
|
||||||
// Easy DNS A/AAAA look up
|
// Easy DNS A/AAAA look up
|
||||||
exports.lookup = function (domain, callback) {
|
// lookup(domain, [family,] callback)
|
||||||
var addressType = dns.isIP(domain);
|
exports.lookup = function (domain, family, callback) {
|
||||||
if (addressType) {
|
if (arguments.length === 2) {
|
||||||
process.nextTick(function () {
|
callback = family;
|
||||||
callback(null, domain, addressType);
|
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 {
|
} else {
|
||||||
if (/\w\.local\.?$/.test(domain) ) {
|
if (/\w\.local\.?$/.test(domain)) {
|
||||||
// ANNOYING: In the case of mDNS domains use NSS in the thread pool.
|
// ANNOYING: In the case of mDNS domains use NSS in the thread pool.
|
||||||
// I wish c-ares had better support.
|
// I wish c-ares had better support.
|
||||||
process.binding('net').getaddrinfo(domain, 4, function (err, domains4) {
|
process.binding('net').getaddrinfo(domain, 4, function (err, domains4) {
|
||||||
callback(err, domains4[0], 4);
|
callback(err, domains4[0], 4);
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
channel.getHostByName(domain, dns.AF_INET, function (err, domains4) {
|
if (family) {
|
||||||
if (domains4 && domains4.length) {
|
// resolve names for explicit address family
|
||||||
callback(null, domains4[0], 4);
|
var af = (family === 4) ? dns.AF_INET : dns.AF_INET6;
|
||||||
} else {
|
channel.getHostByName(domain, af, function (err, domains) {
|
||||||
channel.getHostByName(domain, dns.AF_INET6, function (err, domains6) {
|
if (!err && domains && domains.length) {
|
||||||
if (domains6 && domains6.length) {
|
if (family !== dns.isIP(domains[0])) {
|
||||||
callback(null, domains6[0], 6);
|
callback(new Error('not found'), []);
|
||||||
} else {
|
} 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.resolve4 = function(domain, callback) {
|
||||||
exports.resolve6 = function(domain, callback) { channel.query(domain, dns.AAAA, callback) };
|
channel.query(domain, dns.A, callback);
|
||||||
exports.resolveMx = function(domain, callback) { channel.query(domain, dns.MX, callback) };
|
};
|
||||||
exports.resolveTxt = function(domain, callback) { channel.query(domain, dns.TXT, callback) };
|
exports.resolve6 = function(domain, callback) {
|
||||||
exports.resolveSrv = function(domain, callback) { channel.query(domain, dns.SRV, callback) };
|
channel.query(domain, dns.AAAA, callback);
|
||||||
exports.reverse = function(domain, callback) { channel.query(domain, dns.PTR, callback) };
|
};
|
||||||
exports.resolveNs = function(domain, callback) { channel.query(domain, dns.NS, 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 = {
|
var resolveMap = {
|
||||||
'A' : exports.resolve4,
|
'A' : exports.resolve4,
|
||||||
|
Loading…
x
Reference in New Issue
Block a user