-
Notifications
You must be signed in to change notification settings - Fork 30.7k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
net: cleanup connect logic and add ability to specify custom lookup function #1505
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -881,64 +881,81 @@ Socket.prototype.connect = function(options, cb) { | |
connect(self, options.path); | ||
|
||
} else { | ||
const dns = require('dns'); | ||
var host = options.host || 'localhost'; | ||
var port = 0; | ||
var localAddress = options.localAddress; | ||
var localPort = options.localPort; | ||
var dnsopts = { | ||
family: options.family, | ||
hints: 0 | ||
}; | ||
|
||
if (localAddress && !exports.isIP(localAddress)) | ||
throw new TypeError('localAddress must be a valid IP: ' + localAddress); | ||
|
||
if (localPort && typeof localPort !== 'number') | ||
throw new TypeError('localPort should be a number: ' + localPort); | ||
|
||
port = options.port; | ||
if (typeof port !== 'undefined') { | ||
if (typeof port !== 'number' && typeof port !== 'string') | ||
throw new TypeError('port should be a number or string: ' + port); | ||
if (!isLegalPort(port)) | ||
throw new RangeError('port should be >= 0 and < 65536: ' + port); | ||
} | ||
port |= 0; | ||
lookupAndConnect(self, options); | ||
} | ||
return self; | ||
}; | ||
|
||
if (dnsopts.family !== 4 && dnsopts.family !== 6) | ||
dnsopts.hints = dns.ADDRCONFIG | dns.V4MAPPED; | ||
|
||
debug('connect: find host ' + host); | ||
debug('connect: dns options ' + dnsopts); | ||
self._host = host; | ||
dns.lookup(host, dnsopts, function(err, ip, addressType) { | ||
self.emit('lookup', err, ip, addressType); | ||
function lookupAndConnect(self, options) { | ||
const dns = require('dns'); | ||
var host = options.host || 'localhost'; | ||
var port = options.port; | ||
var localAddress = options.localAddress; | ||
var localPort = options.localPort; | ||
|
||
// It's possible we were destroyed while looking this up. | ||
// XXX it would be great if we could cancel the promise returned by | ||
// the look up. | ||
if (!self._connecting) return; | ||
if (localAddress && !exports.isIP(localAddress)) | ||
throw new TypeError('localAddress must be a valid IP: ' + localAddress); | ||
|
||
if (err) { | ||
// net.createConnection() creates a net.Socket object and | ||
// immediately calls net.Socket.connect() on it (that's us). | ||
// There are no event listeners registered yet so defer the | ||
// error event to the next tick. | ||
process.nextTick(connectErrorNT, self, err, options); | ||
} else { | ||
self._unrefTimer(); | ||
connect(self, | ||
ip, | ||
port, | ||
addressType, | ||
localAddress, | ||
localPort); | ||
} | ||
}); | ||
if (localPort && typeof localPort !== 'number') | ||
throw new TypeError('localPort should be a number: ' + localPort); | ||
|
||
if (typeof port !== 'undefined') { | ||
if (typeof port !== 'number' && typeof port !== 'string') | ||
throw new TypeError('port should be a number or string: ' + port); | ||
if (!isLegalPort(port)) | ||
throw new RangeError('port should be >= 0 and < 65536: ' + port); | ||
} | ||
return self; | ||
}; | ||
port |= 0; | ||
|
||
// If host is an IP, skip performing a lookup | ||
// TODO(evanlucas) should we hot path this for localhost? | ||
var addressType = exports.isIP(host); | ||
if (addressType) { | ||
connect(self, host, port, addressType, localAddress, localPort); | ||
return; | ||
} | ||
|
||
if (options.lookup && typeof options.lookup !== 'function') | ||
throw new TypeError('options.lookup should be a function.'); | ||
|
||
var dnsopts = { | ||
family: options.family, | ||
hints: 0 | ||
}; | ||
|
||
if (dnsopts.family !== 4 && dnsopts.family !== 6) | ||
dnsopts.hints = dns.ADDRCONFIG | dns.V4MAPPED; | ||
|
||
debug('connect: find host ' + host); | ||
debug('connect: dns options ' + dnsopts); | ||
self._host = host; | ||
var lookup = options.lookup || dns.lookup; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Add type check like if (typeof lookup !== 'function') {
throw new TypeError('lookup should be a function.');
} There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Good call. Added. |
||
lookup(host, dnsopts, function(err, ip, addressType) { | ||
self.emit('lookup', err, ip, addressType); | ||
|
||
// It's possible we were destroyed while looking this up. | ||
// XXX it would be great if we could cancel the promise returned by | ||
// the look up. | ||
if (!self._connecting) return; | ||
|
||
if (err) { | ||
// net.createConnection() creates a net.Socket object and | ||
// immediately calls net.Socket.connect() on it (that's us). | ||
// There are no event listeners registered yet so defer the | ||
// error event to the next tick. | ||
process.nextTick(connectErrorNT, self, err, options); | ||
} else { | ||
self._unrefTimer(); | ||
connect(self, | ||
ip, | ||
port, | ||
addressType, | ||
localAddress, | ||
localPort); | ||
} | ||
}); | ||
} | ||
|
||
|
||
function connectErrorNT(self, err, options) { | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,40 @@ | ||
var common = require('../common'); | ||
var assert = require('assert'); | ||
var net = require('net'); | ||
var dns = require('dns'); | ||
var ok = false; | ||
|
||
function check(addressType, cb) { | ||
var server = net.createServer(function(client) { | ||
client.end(); | ||
server.close(); | ||
cb && cb(); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. In this test, |
||
}); | ||
|
||
var address = addressType === 4 ? '127.0.0.1' : '::1'; | ||
server.listen(common.PORT, address, function() { | ||
net.connect({ | ||
port: common.PORT, | ||
host: 'localhost', | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Could this use Edit: ah, thats unnecessary since we don't check the host. I think. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This was actually something I am not sure of. Since we don't call lookup in the event that the host is an IP address, this test could fail of |
||
lookup: lookup | ||
}).on('lookup', function(err, ip, type) { | ||
assert.equal(err, null); | ||
assert.equal(ip, address); | ||
assert.equal(type, addressType); | ||
ok = true; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. oops, check was missing. Added |
||
}); | ||
}); | ||
|
||
function lookup(host, dnsopts, cb) { | ||
dnsopts.family = addressType; | ||
dns.lookup(host, dnsopts, cb); | ||
} | ||
} | ||
|
||
check(4, function() { | ||
common.hasIPv6 && check(6); | ||
}); | ||
|
||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. style fix: we don't put lines at the end of file. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Fixed |
||
process.on('exit', function() { | ||
assert.ok(ok); | ||
}); |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,18 @@ | ||
var common = require('../common'); | ||
var assert = require('assert'); | ||
var net = require('net'); | ||
|
||
function check(addressType) { | ||
var server = net.createServer(function(client) { | ||
client.end(); | ||
server.close(); | ||
}); | ||
|
||
var address = addressType === 4 ? '127.0.0.1' : '::1'; | ||
server.listen(common.PORT, address, function() { | ||
net.connect(common.PORT, address).on('lookup', assert.fail); | ||
}); | ||
} | ||
|
||
check(4); | ||
common.hasIPv6 && check(6); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Any chance this can be cached while you're at it? Unless you want to just move the code.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I could cache it if that is what we want. I'm assuming it was not included until now for lazy loading though. Either way works for me