diff --git a/lib/net.js b/lib/net.js index c653c814b75..5635910daf0 100644 --- a/lib/net.js +++ b/lib/net.js @@ -742,7 +742,8 @@ function afterWrite(status, handle, req, err) { } if (status < 0) { - var ex = errnoException(status, 'write', err); + err = util.format('%s %s:%s', err || '', req.address, req.port); + var ex = errnoException(status, 'write', err, req); debug('write failure', ex); self._destroy(ex, req.cb); return; @@ -804,28 +805,56 @@ function connect(self, address, port, addressType, localAddress, localPort) { err = bind(localAddress, localPort); if (err) { - self._destroy(errnoException(err, 'bind')); + var additions = { + address: address + }; + var details; + if (port) { + details = util.format('%s:%s', address, port); + additions.port = port; + } else { + details = address; + } + var ex = errnoException(err, 'bind', details, additions); + self._destroy(ex); return; } } - var req = { oncomplete: afterConnect }; + var req = { + oncomplete: afterConnect, + port: undefined, + address: undefined, + localAddress: undefined, + localPort: undefined + }; if (addressType === 6 || addressType === 4) { port = port | 0; if (port <= 0 || port > 65535) throw new RangeError('Port should be > 0 and < 65536'); + req.port = port; + req.address = address; if (addressType === 6) { err = self._handle.connect6(req, address, port); } else if (addressType === 4) { err = self._handle.connect(req, address, port); } } else { + req.address = address; err = self._handle.connect(req, address, afterConnect); } + self._getsockname(); + if (self._sockname) { + req.localAddress = self._sockname.address; + req.localPort = self._sockname.port; + } if (err) { - self._destroy(errnoException(err, 'connect')); + var details = port ? + util.format('%s:%s', address, port) : + address; + self._destroy(errnoException(err, 'connect', details, req)); } } @@ -908,7 +937,15 @@ Socket.prototype.connect = function(options, cb) { // There are no event listeners registered yet so defer the // error event to the next tick. process.nextTick(function() { - self.emit('error', err); + // The errno may not be recognized by libuv + var ex = util._extend(err, options); + var message = util.format('%s %s %s:%s', + err.syscall, + err.errno, + options.host, + options.port); + ex.message = message; + self.emit('error', ex); self._destroy(); }); } else { @@ -975,7 +1012,17 @@ function afterConnect(status, handle, req, readable, writable) { } else { self._connecting = false; - self._destroy(errnoException(status, 'connect')); + var details = req.port ? + util.format('%s:%s', req.address, req.port) : + req.address; + + if (req.localAddress && req.localPort) { + details = util.format('%s - Local (%s:%s)', + details, + req.localAddress, + req.localPort); + } + self._destroy(errnoException(status, 'connect', details, req)); } } @@ -1103,7 +1150,21 @@ Server.prototype._listen2 = function(address, port, addressType, backlog, fd) { debug('_listen2: create a handle'); var rval = createServerHandle(address, port, addressType, fd); if (util.isNumber(rval)) { - var error = errnoException(rval, 'listen'); + var details, additions; + if (port > 0) { + details = util.format('%s:%s', address, port); + additions = { + address: address, + port: port + }; + } else { + details = address; + additions = { + address: address + }; + } + + var error = errnoException(rval, 'listen', details, additions); process.nextTick(function() { self.emit('error', error); }); @@ -1120,7 +1181,20 @@ Server.prototype._listen2 = function(address, port, addressType, backlog, fd) { var err = _listen(self._handle, backlog); if (err) { - var ex = errnoException(err, 'listen'); + var details, additions; + if (port > 0) { + details = util.format('%s:%s', address, port); + additions = { + address: address, + port: port + }; + } else { + details = address; + additions = { + address: address + }; + } + var ex = errnoException(err, 'listen', details, additions); self._handle.close(); self._handle = null; process.nextTick(function() { @@ -1166,8 +1240,23 @@ function listen(self, address, port, addressType, backlog, fd) { err = uv.UV_EADDRINUSE; } - if (err) - return self.emit('error', errnoException(err, 'bind')); + if (err) { + var details, additions; + if (port > 0) { + details = util.format('%s:%s', address, port); + additions = { + address: address, + port: port + }; + } else { + details = address; + additions = { + address: address + }; + } + var ex = errnoException(err, 'bind', details, additions); + return self.emit('error', ex); + } self._handle = handle; self._listen2(address, port, addressType, backlog, fd); diff --git a/lib/util.js b/lib/util.js index 2de944586fe..e1a23237c6b 100644 --- a/lib/util.js +++ b/lib/util.js @@ -733,7 +733,7 @@ exports.pump = exports.deprecate(function(readStream, writeStream, callback) { var uv; -exports._errnoException = function(err, syscall, original) { +exports._errnoException = function(err, syscall, original, additions) { if (isUndefined(uv)) uv = process.binding('uv'); var errname = uv.errname(err); var message = syscall + ' ' + errname; @@ -743,5 +743,15 @@ exports._errnoException = function(err, syscall, original) { e.code = errname; e.errno = errname; e.syscall = syscall; + if (additions && isObject(additions)) { + var keys = Object.keys(additions); + var len = keys.length; + for (var i = 0; i < len; i++) { + if (!isNullOrUndefined(additions[keys[i]]) && + isPrimitive(additions[keys[i]])) { + e[keys[i]] = additions[keys[i]]; + } + } + } return e; }; diff --git a/test/simple/test-net-better-error-messages-listen-path.js b/test/simple/test-net-better-error-messages-listen-path.js new file mode 100644 index 00000000000..32f949621a3 --- /dev/null +++ b/test/simple/test-net-better-error-messages-listen-path.js @@ -0,0 +1,39 @@ +// Copyright Joyent, Inc. and other Node contributors. +// +// Permission is hereby granted, free of charge, to any person obtaining a +// copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to permit +// persons to whom the Software is furnished to do so, subject to the +// following conditions: +// +// The above copyright notice and this permission notice shall be included +// in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN +// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, +// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR +// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE +// USE OR OTHER DEALINGS IN THE SOFTWARE. + +var common = require('../common'); +var assert = require('assert'); +var net = require('net'); +var gotError = false; +var fp = '/blah/fadfa'; +var server = net.createServer(function(socket) { +}); +server.listen(fp, function() { + assert(false); +}); +server.on('error', function(e) { + console.error('error', e); + gotError = true; +}); + +process.on('exit', function() { + assert(gotError); +}); diff --git a/test/simple/test-net-better-error-messages-listen.js b/test/simple/test-net-better-error-messages-listen.js new file mode 100644 index 00000000000..268ea6efc30 --- /dev/null +++ b/test/simple/test-net-better-error-messages-listen.js @@ -0,0 +1,41 @@ +// Copyright Joyent, Inc. and other Node contributors. +// +// Permission is hereby granted, free of charge, to any person obtaining a +// copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to permit +// persons to whom the Software is furnished to do so, subject to the +// following conditions: +// +// The above copyright notice and this permission notice shall be included +// in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN +// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, +// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR +// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE +// USE OR OTHER DEALINGS IN THE SOFTWARE. + +var common = require('../common'); +var assert = require('assert'); +var net = require('net'); +var gotError = false; + +var server = net.createServer(function(socket) { +}); +server.listen(1, '1.1.1.1', function() { // EACCESS or EADDRNOTAVAIL + assert(false); +}); +server.on('error', function(e) { + console.error('error', e); + gotError = true; + assert.equal('1.1.1.1', e.address); + assert.equal(1, e.port); +}); + +process.on('exit', function() { + assert(gotError); +}); diff --git a/test/simple/test-net-better-error-messages-path.js b/test/simple/test-net-better-error-messages-path.js new file mode 100644 index 00000000000..45993fd6125 --- /dev/null +++ b/test/simple/test-net-better-error-messages-path.js @@ -0,0 +1,45 @@ +// Copyright Joyent, Inc. and other Node contributors. +// +// Permission is hereby granted, free of charge, to any person obtaining a +// copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to permit +// persons to whom the Software is furnished to do so, subject to the +// following conditions: +// +// The above copyright notice and this permission notice shall be included +// in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN +// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, +// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR +// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE +// USE OR OTHER DEALINGS IN THE SOFTWARE. + + + +var common = require('../common'); +var net = require('net'); +var assert = require('assert'); +var fp = '/tmp/fadagagsdfgsdf'; +var c = net.connect(fp); + +c.on('connect', function() { + console.error('connected?!'); + assert.ok(false); +}); + +var gotError = false; +c.on('error', function(e) { + console.error('couldn\'t connect.', e); + gotError = true; + assert.equal('ENOENT', e.code); + assert.equal(fp, e.address); +}); + +process.on('exit', function() { + assert.ok(gotError); +}); diff --git a/test/simple/test-net-better-error-messages-port-hostname.js b/test/simple/test-net-better-error-messages-port-hostname.js new file mode 100644 index 00000000000..75f23767c1c --- /dev/null +++ b/test/simple/test-net-better-error-messages-port-hostname.js @@ -0,0 +1,46 @@ +// Copyright Joyent, Inc. and other Node contributors. +// +// Permission is hereby granted, free of charge, to any person obtaining a +// copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to permit +// persons to whom the Software is furnished to do so, subject to the +// following conditions: +// +// The above copyright notice and this permission notice shall be included +// in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN +// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, +// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR +// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE +// USE OR OTHER DEALINGS IN THE SOFTWARE. + + + +var common = require('../common'); +var net = require('net'); +var assert = require('assert'); + +var c = net.createConnection(common.PORT, 'blah'); + +c.on('connect', function() { + console.error('connected?!'); + assert.ok(false); +}); + +var gotError = false; +c.on('error', function(e) { + console.error('couldn\'t connect.', e); + gotError = true; + assert.equal('ENOTFOUND', e.code); + assert.equal(common.PORT, e.port); + assert.equal('blah', e.hostname); +}); + +process.on('exit', function() { + assert.ok(gotError); +}); diff --git a/test/simple/test-net-better-error-messages-port.js b/test/simple/test-net-better-error-messages-port.js new file mode 100644 index 00000000000..dabe01e9375 --- /dev/null +++ b/test/simple/test-net-better-error-messages-port.js @@ -0,0 +1,46 @@ +// Copyright Joyent, Inc. and other Node contributors. +// +// Permission is hereby granted, free of charge, to any person obtaining a +// copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to permit +// persons to whom the Software is furnished to do so, subject to the +// following conditions: +// +// The above copyright notice and this permission notice shall be included +// in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN +// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, +// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR +// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE +// USE OR OTHER DEALINGS IN THE SOFTWARE. + + + +var common = require('../common'); +var net = require('net'); +var assert = require('assert'); + +var c = net.createConnection(common.PORT); + +c.on('connect', function() { + console.error('connected?!'); + assert.ok(false); +}); + +var gotError = false; +c.on('error', function(e) { + console.error('couldn\'t connect.', e); + gotError = true; + assert.equal('ECONNREFUSED', e.code); + assert.equal(common.PORT, e.port); + assert.equal('127.0.0.1', e.address); +}); + +process.on('exit', function() { + assert.ok(gotError); +});