|
|
@ -43,11 +43,6 @@ function isIP(address) { |
|
|
|
|
|
|
|
|
|
|
|
function lookup(address, family, callback) { |
|
|
|
// implicit 'bind before send' needs to run on the same tick
|
|
|
|
var matchedFamily = isIP(address); |
|
|
|
if (matchedFamily) |
|
|
|
return callback(null, address, matchedFamily); |
|
|
|
|
|
|
|
if (!dns) |
|
|
|
dns = require('dns'); |
|
|
|
|
|
|
@ -111,31 +106,36 @@ exports.createSocket = function(type, listener) { |
|
|
|
}; |
|
|
|
|
|
|
|
|
|
|
|
Socket.prototype.bind = function(port, address) { |
|
|
|
Socket.prototype.bind = function(port, address, callback) { |
|
|
|
var self = this; |
|
|
|
|
|
|
|
self._healthCheck(); |
|
|
|
|
|
|
|
if (typeof callback === 'function') |
|
|
|
self.once('listening', callback); |
|
|
|
|
|
|
|
// resolve address first
|
|
|
|
self._handle.lookup(address, function(err, ip) { |
|
|
|
if (!err) { |
|
|
|
if (self._handle.bind(ip, port || 0, /*flags=*/0)) { |
|
|
|
err = errnoException(errno, 'bind'); |
|
|
|
} |
|
|
|
else { |
|
|
|
self._bound = true; |
|
|
|
self._startReceiving(); |
|
|
|
self.emit('listening'); |
|
|
|
} |
|
|
|
} |
|
|
|
if (!self._handle) |
|
|
|
return; // handle has been closed in the mean time
|
|
|
|
|
|
|
|
if (err) { |
|
|
|
// caller may not have had a chance yet to register its
|
|
|
|
// error event listener so defer the error to the next tick
|
|
|
|
process.nextTick(function() { |
|
|
|
self.emit('error', err); |
|
|
|
}); |
|
|
|
return; |
|
|
|
} |
|
|
|
|
|
|
|
if (self._handle.bind(ip, port || 0, /*flags=*/ 0)) { |
|
|
|
self.emit('error', errnoException(errno, 'bind')); |
|
|
|
return; |
|
|
|
} |
|
|
|
|
|
|
|
self._handle.onmessage = onMessage; |
|
|
|
self._handle.recvStart(); |
|
|
|
self._receiving = true; |
|
|
|
self._bound = true; |
|
|
|
self.fd = -42; // compatibility hack
|
|
|
|
|
|
|
|
self.emit('listening'); |
|
|
|
}); |
|
|
|
}; |
|
|
|
|
|
|
@ -174,7 +174,14 @@ Socket.prototype.send = function(buffer, |
|
|
|
callback = callback || noop; |
|
|
|
|
|
|
|
self._healthCheck(); |
|
|
|
self._startReceiving(); |
|
|
|
|
|
|
|
if (!self._bound) { |
|
|
|
self.bind(0, null); |
|
|
|
self.once('listening', function() { |
|
|
|
self.send(buffer, offset, length, port, address, callback); |
|
|
|
}); |
|
|
|
return; |
|
|
|
} |
|
|
|
|
|
|
|
self._handle.lookup(address, function(err, ip) { |
|
|
|
if (err) { |
|
|
@ -309,25 +316,6 @@ Socket.prototype._healthCheck = function() { |
|
|
|
}; |
|
|
|
|
|
|
|
|
|
|
|
Socket.prototype._startReceiving = function() { |
|
|
|
if (this._receiving) |
|
|
|
return; |
|
|
|
|
|
|
|
if (!this._bound) { |
|
|
|
this.bind(); // bind to random port
|
|
|
|
|
|
|
|
// sanity check
|
|
|
|
if (!this._bound) |
|
|
|
throw new Error('implicit bind failed'); |
|
|
|
} |
|
|
|
|
|
|
|
this._handle.onmessage = onMessage; |
|
|
|
this._handle.recvStart(); |
|
|
|
this._receiving = true; |
|
|
|
this.fd = -42; // compatibility hack
|
|
|
|
}; |
|
|
|
|
|
|
|
|
|
|
|
Socket.prototype._stopReceiving = function() { |
|
|
|
if (!this._receiving) |
|
|
|
return; |
|
|
|