From 998d31233e25684ab50974ee0d15721c0de2dfe1 Mon Sep 17 00:00:00 2001 From: Evan Lucas Date: Mon, 10 Mar 2014 15:42:58 -0500 Subject: [PATCH] net: give better error messages Add address and/or port to errors where applicable for better reporting. See #7005 --- lib/net.js | 52 ++++++++++++++++--- ...t-net-better-error-messages-listen-path.js | 39 ++++++++++++++ .../test-net-better-error-messages-listen.js | 41 +++++++++++++++ .../test-net-better-error-messages-path.js | 45 ++++++++++++++++ ...net-better-error-messages-port-hostname.js | 46 ++++++++++++++++ .../test-net-better-error-messages-port.js | 46 ++++++++++++++++ 6 files changed, 262 insertions(+), 7 deletions(-) create mode 100644 test/simple/test-net-better-error-messages-listen-path.js create mode 100644 test/simple/test-net-better-error-messages-listen.js create mode 100644 test/simple/test-net-better-error-messages-path.js create mode 100644 test/simple/test-net-better-error-messages-port-hostname.js create mode 100644 test/simple/test-net-better-error-messages-port.js diff --git a/lib/net.js b/lib/net.js index 751b04b05e15..0948bc4c931e 100644 --- a/lib/net.js +++ b/lib/net.js @@ -769,7 +769,11 @@ function afterWrite(status, handle, req, err) { } if (status < 0) { + err = (err || '') + req.address; + if (req.port) err += ':' + req.port; var ex = errnoException(status, 'write', err); + if (req.port) ex.port = req.port; + if (req.address) ex.address = req.address; debug('write failure', ex); self._destroy(ex, req.cb); return; @@ -831,7 +835,12 @@ function connect(self, address, port, addressType, localAddress, localPort) { err = bind(localAddress, localPort); if (err) { - self._destroy(errnoException(err, 'bind')); + var details = address; + if (port) details += ':' + port; + var ex = errnoException(err, 'bind', details); + ex.address = address; + if (port) ex.port = port; + self._destroy(ex); return; } } @@ -842,17 +851,25 @@ function connect(self, address, port, addressType, localAddress, localPort) { 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); } if (err) { - self._destroy(errnoException(err, 'connect')); + var details = address; + if (port) details += ':' + port; + var ex = errnoException(err, 'connect', details); + ex.address = address; + if (port) ex.port = port; + self._destroy(ex); } } @@ -925,6 +942,7 @@ 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() { + if (options.port) err.port = options.port; self.emit('error', err); self._destroy(); }); @@ -992,7 +1010,12 @@ function afterConnect(status, handle, req, readable, writable) { } else { self._connecting = false; - self._destroy(errnoException(status, 'connect')); + var details = req.address ? req.address : ''; + if (req.port) details += ':' + req.port; + var ex = errnoException(status, 'connect', details); + ex.address = req.address; + if (req.port) ex.port = req.port; + self._destroy(ex); } } @@ -1123,7 +1146,11 @@ 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 = address; + if (port > 0) details += ':' + port; + var error = errnoException(rval, 'listen', details); + error.address = address; + if (port > 0) error.port = port; process.nextTick(function() { self.emit('error', error); }); @@ -1143,7 +1170,11 @@ Server.prototype._listen2 = function(address, port, addressType, backlog, fd) { err = _listen(self._handle, backlog); if (err) { - var ex = errnoException(err, 'listen'); + var details = address; + if (port > 0) details += ':' + port; + var ex = errnoException(err, 'listen', details); + ex.address = address; + if (port > 0) ex.port = port; self._handle.close(); self._handle = null; process.nextTick(function() { @@ -1187,8 +1218,15 @@ 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 = address; + if (port > 0) details += ':' + port; + var ex = errnoException(err, 'bind', details); + ex.address = address; + if (port > 0) ex.port = port; + return self.emit('error', ex); + } + self._handle = handle; self._listen2(address, port, addressType, backlog, fd); 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 000000000000..32f949621a3e --- /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 000000000000..268ea6efc300 --- /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 000000000000..45993fd6125d --- /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 000000000000..75f23767c1c7 --- /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 000000000000..dabe01e93757 --- /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); +});