From 332fea5ac1816e498030109c4211bca24a7fa667 Mon Sep 17 00:00:00 2001 From: Ben Noordhuis Date: Mon, 9 Jul 2012 17:53:48 +0200 Subject: [PATCH] dgram: make .bind() always asynchronous --- lib/dgram.js | 70 ++++++++++++++++++++++------------------------------ 1 file changed, 29 insertions(+), 41 deletions(-) diff --git a/lib/dgram.js b/lib/dgram.js index d05790ccefc8f7..6c70e175de272d 100644 --- a/lib/dgram.js +++ b/lib/dgram.js @@ -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); - }); + 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;