Skip to content

Commit 592be01

Browse files
committed
dgram: introduce reuseAddr option
Introduce new signature for both `dgram.createSocket` method and `dgram.Socket` constructor: dgram.createSocket(options, [listener]) Options should contain `type` property and may contain `reuseAddr` property. When `reuseAddr` is `true` - SO_REUSEADDR will be issued on socket on bind. fix nodejs#7415 Signed-off-by: Fedor Indutny <fedor@indutny.com>
1 parent c20b209 commit 592be01

File tree

4 files changed

+33
-4
lines changed

4 files changed

+33
-4
lines changed

doc/api/dgram.markdown

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,8 +22,13 @@ You have to change it to this:
2222

2323

2424
## dgram.createSocket(type, [callback])
25+
## dgram.createSocket(options, [callback])
2526

2627
* `type` String. Either 'udp4' or 'udp6'
28+
* `options` Object. Should contain a `type` property and could contain
29+
`reuseAddr` property. `false` by default.
30+
When `reuseAddr` is `true` - `socket.bind()` will reuse address, even if the
31+
other process has already bound a socket on it.
2732
* `callback` Function. Attached as a listener to `message` events.
2833
Optional
2934
* Returns: Socket object
@@ -41,7 +46,7 @@ with `socket.address().address` and `socket.address().port`.
4146
## Class: dgram.Socket
4247

4348
The dgram Socket class encapsulates the datagram functionality. It
44-
should be created via `dgram.createSocket(type, [callback])`.
49+
should be created via `dgram.createSocket(...)`
4550

4651
### Event: 'message'
4752

lib/dgram.js

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@
2222
var assert = require('assert');
2323
var util = require('util');
2424
var events = require('events');
25+
var constants = require('constants');
2526

2627
var UDP = process.binding('udp_wrap').UDP;
2728

@@ -96,6 +97,11 @@ exports._createSocketHandle = function(address, port, addressType, fd) {
9697
function Socket(type, listener) {
9798
events.EventEmitter.call(this);
9899

100+
if (typeof type === 'object') {
101+
var options = type;
102+
type = options.type;
103+
}
104+
99105
var handle = newHandle(type);
100106
handle.owner = this;
101107

@@ -105,6 +111,9 @@ function Socket(type, listener) {
105111
this.type = type;
106112
this.fd = null; // compatibility hack
107113

114+
// If true - UV_UDP_REUSEADDR flag will be set
115+
this._reuseAddr = options && options.reuseAddr;
116+
108117
if (util.isFunction(listener))
109118
this.on('message', listener);
110119
}
@@ -196,7 +205,11 @@ Socket.prototype.bind = function(/*port, address, callback*/) {
196205
if (!self._handle)
197206
return; // handle has been closed in the mean time
198207

199-
var err = self._handle.bind(ip, port || 0, /*flags=*/ 0);
208+
var flags = 0;
209+
if (self._reuseAddr)
210+
flags |= constants.UV_UDP_REUSEADDR;
211+
212+
var err = self._handle.bind(ip, port || 0, flags);
200213
if (err) {
201214
self.emit('error', errnoException(err, 'bind'));
202215
self._bindState = BIND_STATE_UNBOUND;

src/node_constants.cc

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1071,12 +1071,17 @@ void DefineSystemConstants(Handle<Object> target) {
10711071
#endif
10721072
}
10731073

1074+
void DefineUVConstants(Handle<Object> target) {
1075+
NODE_DEFINE_CONSTANT(target, UV_UDP_REUSEADDR);
1076+
}
1077+
10741078
void DefineConstants(Handle<Object> target) {
10751079
DefineErrnoConstants(target);
10761080
DefineWindowsErrorConstants(target);
10771081
DefineSignalConstants(target);
10781082
DefineOpenSSLConstants(target);
10791083
DefineSystemConstants(target);
1084+
DefineUVConstants(target);
10801085
}
10811086

10821087
} // namespace node

test/simple/test-dgram-broadcast-multi-process.js

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -157,7 +157,10 @@ if (process.argv[2] !== 'child') {
157157
})(x);
158158
}
159159

160-
var sendSocket = dgram.createSocket('udp4');
160+
var sendSocket = dgram.createSocket({
161+
type: 'udp4',
162+
reuseAddr: true
163+
});
161164

162165
// bind the address explicitly for sending
163166
// INADDR_BROADCAST to only one interface
@@ -201,7 +204,10 @@ if (process.argv[2] !== 'child') {
201204

202205
if (process.argv[2] === 'child') {
203206
var receivedMessages = [];
204-
var listenSocket = dgram.createSocket('udp4');
207+
var listenSocket = dgram.createSocket({
208+
type: 'udp4',
209+
reuseAddr: true
210+
});
205211

206212
listenSocket.on('message', function(buf, rinfo) {
207213
// receive udp messages only sent from parent

0 commit comments

Comments
 (0)