Skip to content

Commit

Permalink
dgram: report send errors to cb, don't pass bytes
Browse files Browse the repository at this point in the history
Passing the number of sent bytes to the callback is superfluous;
datagram sockets operate in atomic mode: either the sendmsg() system
call succeeds or it fails but it never does partial writes.

Instead, report send errors to the callback. UDP error reporting is
fairly haphazard on most platforms. You should not expect reliable
delivery of anything besides EMSGSIZE and (possibly) ENETDOWN and
ENETUNREACH.

Fixes nodejs#2608.
  • Loading branch information
bnoordhuis committed Jul 29, 2013
1 parent 34b0a36 commit 6bd922f
Show file tree
Hide file tree
Showing 5 changed files with 49 additions and 19 deletions.
11 changes: 8 additions & 3 deletions doc/api/dgram.markdown
Original file line number Diff line number Diff line change
Expand Up @@ -48,8 +48,13 @@ should be created via `dgram.createSocket(type, [callback])`.
* `msg` Buffer object. The message
* `rinfo` Object. Remote address information

Emitted when a new datagram is available on a socket. `msg` is a `Buffer` and `rinfo` is
an object with the sender's address information and the number of bytes in the datagram.
Emitted when a new datagram is available on a socket. `msg` is a `Buffer` and
`rinfo` is an object with the sender's address information:

socket.on('message', function(msg, rinfo) {
console.log('Received %d bytes from %s:%d\n',
msg.length, rinfo.address, rinfo.port);
});

### Event: 'listening'

Expand Down Expand Up @@ -93,7 +98,7 @@ Example of sending a UDP packet to a random port on `localhost`;
var dgram = require('dgram');
var message = new Buffer("Some bytes");
var client = dgram.createSocket("udp4");
client.send(message, 0, message.length, 41234, "localhost", function(err, bytes) {
client.send(message, 0, message.length, 41234, "localhost", function(err) {
client.close();
});

Expand Down
8 changes: 3 additions & 5 deletions lib/dgram.js
Original file line number Diff line number Diff line change
Expand Up @@ -302,11 +302,9 @@ Socket.prototype.send = function(buffer,
};


function afterSend(status, handle, req, buffer) {
var self = handle.owner;

if (req.cb)
req.cb(null, buffer.length); // compatibility with dgram_legacy.js
function afterSend(err) {
if (this.cb)
this.cb(err ? errnoException(err, 'send') : null);
}


Expand Down
10 changes: 2 additions & 8 deletions src/udp_wrap.cc
Original file line number Diff line number Diff line change
Expand Up @@ -341,14 +341,8 @@ void UDPWrap::OnSend(uv_udp_send_t* req, int status) {
assert(wrap->persistent().IsEmpty() == false);

Local<Object> req_wrap_obj = req_wrap->object();
Local<Value> argv[] = {
Integer::New(status, node_isolate),
wrap->object(),
req_wrap_obj,
req_wrap_obj->GetHiddenValue(buffer_sym),
};

MakeCallback(req_wrap_obj, oncomplete_sym, ARRAY_SIZE(argv), argv);
Local<Value> arg = Integer::New(status, node_isolate);
MakeCallback(req_wrap_obj, oncomplete_sym, 1, &arg);
delete req_wrap;
}

Expand Down
35 changes: 35 additions & 0 deletions test/simple/test-dgram-msgsize.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
// 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');

// Send a too big datagram. The destination doesn't matter because it's
// not supposed to get sent out anyway.
var buf = Buffer(256 * 1024);
var sock = dgram.createSocket('udp4');
sock.send(buf, 0, buf.length, 12345, '127.0.0.1', common.mustCall(cb));
function cb(err) {
assert(err instanceof Error);
assert.equal(err.code, 'EMSGSIZE');
sock.close();
}
4 changes: 1 addition & 3 deletions test/simple/test-dgram-udp4.js
Original file line number Diff line number Diff line change
Expand Up @@ -54,13 +54,11 @@ server.on('listening', function() {
server.close();
});
client.send(message_to_send, 0, message_to_send.length,
server_port, 'localhost', function(err, bytes) {
server_port, 'localhost', function(err) {
if (err) {
console.log('Caught error in client send.');
throw err;
}
console.log('client wrote ' + bytes + ' bytes.');
assert.strictEqual(bytes, message_to_send.length);
});
client.on('close',
function() {
Expand Down

0 comments on commit 6bd922f

Please sign in to comment.