Skip to content

Commit 81cd06b

Browse files
Nitzan Uzielytargos
Nitzan Uziely
authored andcommitted
dgram: support AbortSignal in createSocket
PR-URL: #37026 Backport-PR-URL: #38386 Reviewed-By: Benjamin Gruenbaum <benjamingr@gmail.com> Reviewed-By: Rich Trott <rtrott@gmail.com>
1 parent 1b74a08 commit 81cd06b

File tree

3 files changed

+67
-0
lines changed

3 files changed

+67
-0
lines changed

doc/api/dgram.md

+18
Original file line numberDiff line numberDiff line change
@@ -733,6 +733,9 @@ chained.
733733
<!-- YAML
734734
added: v0.11.13
735735
changes:
736+
- version: REPLACEME
737+
pr-url: https://github.com/nodejs/node/pull/37026
738+
description: AbortSignal support was added.
736739
- version: v11.4.0
737740
pr-url: https://github.com/nodejs/node/pull/23798
738741
description: The `ipv6Only` option is supported.
@@ -757,6 +760,7 @@ changes:
757760
* `recvBufferSize` {number} Sets the `SO_RCVBUF` socket value.
758761
* `sendBufferSize` {number} Sets the `SO_SNDBUF` socket value.
759762
* `lookup` {Function} Custom lookup function. **Default:** [`dns.lookup()`][].
763+
* `signal` {AbortSignal} An AbortSignal that may be used to close a socket.
760764
* `callback` {Function} Attached as a listener for `'message'` events. Optional.
761765
* Returns: {dgram.Socket}
762766

@@ -768,6 +772,20 @@ method will bind the socket to the "all interfaces" address on a random port
768772
and port can be retrieved using [`socket.address().address`][] and
769773
[`socket.address().port`][].
770774

775+
If the `signal` option is enabled, calling `.abort()` on the corresponding
776+
`AbortController` is similar to calling `.close()` on the socket:
777+
778+
```js
779+
const controller = new AbortController();
780+
const { signal } = controller;
781+
const server = dgram.createSocket({ type: 'udp4', signal });
782+
server.on('message', (msg, rinfo) => {
783+
console.log(`server got: ${msg} from ${rinfo.address}:${rinfo.port}`);
784+
});
785+
// Later, when you want to close the server.
786+
controller.abort();
787+
```
788+
771789
### `dgram.createSocket(type[, callback])`
772790
<!-- YAML
773791
added: v0.1.99

lib/dgram.js

+15
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,7 @@ const {
4848
} = errors.codes;
4949
const {
5050
isInt32,
51+
validateAbortSignal,
5152
validateString,
5253
validateNumber,
5354
validatePort,
@@ -121,6 +122,20 @@ function Socket(type, listener) {
121122
recvBufferSize,
122123
sendBufferSize
123124
};
125+
126+
if (options?.signal !== undefined) {
127+
const { signal } = options;
128+
validateAbortSignal(signal, 'options.signal');
129+
const onAborted = () => {
130+
this.close();
131+
};
132+
if (signal.aborted) {
133+
onAborted();
134+
} else {
135+
signal.addEventListener('abort', onAborted);
136+
this.once('close', () => signal.removeEventListener('abort', onAborted));
137+
}
138+
}
124139
}
125140
ObjectSetPrototypeOf(Socket.prototype, EventEmitter.prototype);
126141
ObjectSetPrototypeOf(Socket, EventEmitter);
+34
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
// Flags: --experimental-abortcontroller
2+
'use strict';
3+
4+
const common = require('../common');
5+
const assert = require('assert');
6+
const dgram = require('dgram');
7+
8+
{
9+
// Test bad signal.
10+
assert.throws(
11+
() => dgram.createSocket({ type: 'udp4', signal: {} }),
12+
{
13+
code: 'ERR_INVALID_ARG_TYPE',
14+
name: 'TypeError'
15+
});
16+
}
17+
18+
{
19+
// Test close.
20+
const controller = new AbortController();
21+
const { signal } = controller;
22+
const server = dgram.createSocket({ type: 'udp4', signal });
23+
server.on('close', common.mustCall());
24+
controller.abort();
25+
}
26+
27+
{
28+
// Test close with pre-aborted signal.
29+
const controller = new AbortController();
30+
controller.abort();
31+
const { signal } = controller;
32+
const server = dgram.createSocket({ type: 'udp4', signal });
33+
server.on('close', common.mustCall());
34+
}

0 commit comments

Comments
 (0)