From 3da057fef672da0d1f0173a2c8b4f64737917e19 Mon Sep 17 00:00:00 2001 From: Chris Dickinson Date: Thu, 5 Jun 2014 12:42:41 -0700 Subject: [PATCH] dgram: make send cb act as "error" event handler This allows users to provide a callback that handles potential errors resulting from a `socket.send` call. The original behavior of emitting the error event on the socket is preserved. Fixes: https://github.com/joyent/node/issues/4846 PR-URL: https://github.com/joyent/node/pull/7738 PR-URL: https://github.com/nodejs/io.js/pull/1796 Reviewed-By: Colin Ihrig Reviewed-By: Ben Noordhuis --- doc/api/dgram.markdown | 4 +- lib/dgram.js | 10 +++- .../test-dgram-send-cb-quelches-error.js | 54 +++++++++++++++++++ 3 files changed, 66 insertions(+), 2 deletions(-) create mode 100644 test/simple/test-dgram-send-cb-quelches-error.js diff --git a/doc/api/dgram.markdown b/doc/api/dgram.markdown index 7c13d1746f7036..896bf90d30077a 100644 --- a/doc/api/dgram.markdown +++ b/doc/api/dgram.markdown @@ -114,7 +114,9 @@ assigned a random port number and is bound to the "all interfaces" address An optional callback may be specified to detect DNS errors or for determining when it's safe to reuse the `buf` object. Note that DNS lookups delay the time to send for at least one tick. The only way to know for sure that the datagram -has been sent is by using a callback. +has been sent is by using a callback. If an error occurs and a callback is given, +the error will be the first argument to the callback. If a callback is not given, +the error is emitted as an `'error'` event on the `socket` object. With consideration for multi-byte characters, `offset` and `length` will be calculated with respect to diff --git a/lib/dgram.js b/lib/dgram.js index 22dc7a23192042..8cf5d307794f4d 100644 --- a/lib/dgram.js +++ b/lib/dgram.js @@ -300,7 +300,15 @@ Socket.prototype.send = function(buffer, self._handle.lookup(address, function(ex, ip) { if (ex) { - if (callback) callback(ex); + if (callback) { + callback(ex); + + if (self.listeners('error').length) + self.emit('error', ex); + + return; + } + self.emit('error', ex); } else if (self._handle) { var req = new SendWrap(); diff --git a/test/simple/test-dgram-send-cb-quelches-error.js b/test/simple/test-dgram-send-cb-quelches-error.js new file mode 100644 index 00000000000000..d5f29f9dafa39f --- /dev/null +++ b/test/simple/test-dgram-send-cb-quelches-error.js @@ -0,0 +1,54 @@ +// 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 dgram = require('dgram'); +var dns = require('dns'); + +var socket = dgram.createSocket('udp4'); +var buffer = new Buffer('gary busey'); +var times = 0; + +dns.setServers([]); + +// assert that: +// * callbacks act as "error" listeners if given. +// * callbacks and error events are emitted in a certain order. +socket.send(buffer, 0, buffer.length, 100, 'dne.example.com', callbackOnly); + +function callbackOnly(err) { + assert.ok(err); + socket.once('error', onEvent); + socket.send(buffer, 0, buffer.length, 100, 'dne.example.com', onCallback); +} + +function onEvent(err) { + assert.ok(err); + assert.equal(times, 0); + times++; +} + +function onCallback(err) { + assert.ok(err); + assert.equal(times, 1); + socket.close(); +}