Skip to content

Commit 2c7ad38

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

File tree

3 files changed

+66
-0
lines changed

3 files changed

+66
-0
lines changed

doc/api/dgram.md

+18
Original file line numberDiff line numberDiff line change
@@ -735,6 +735,9 @@ chained.
735735
<!-- YAML
736736
added: v0.11.13
737737
changes:
738+
- version: REPLACEME
739+
pr-url: https://github.com/nodejs/node/pull/37026
740+
description: AbortSignal support was added.
738741
- version: v11.4.0
739742
pr-url: https://github.com/nodejs/node/pull/23798
740743
description: The `ipv6Only` option is supported.
@@ -759,6 +762,7 @@ changes:
759762
* `recvBufferSize` {number} Sets the `SO_RCVBUF` socket value.
760763
* `sendBufferSize` {number} Sets the `SO_SNDBUF` socket value.
761764
* `lookup` {Function} Custom lookup function. **Default:** [`dns.lookup()`][].
765+
* `signal` {AbortSignal} An AbortSignal that may be used to close a socket.
762766
* `callback` {Function} Attached as a listener for `'message'` events. Optional.
763767
* Returns: {dgram.Socket}
764768

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

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

lib/dgram.js

+15
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,7 @@ const {
5252
} = errors.codes;
5353
const {
5454
isInt32,
55+
validateAbortSignal,
5556
validateString,
5657
validateNumber,
5758
validatePort,
@@ -125,6 +126,20 @@ function Socket(type, listener) {
125126
recvBufferSize,
126127
sendBufferSize
127128
};
129+
130+
if (options?.signal !== undefined) {
131+
const { signal } = options;
132+
validateAbortSignal(signal, 'options.signal');
133+
const onAborted = () => {
134+
this.close();
135+
};
136+
if (signal.aborted) {
137+
onAborted();
138+
} else {
139+
signal.addEventListener('abort', onAborted);
140+
this.once('close', () => signal.removeEventListener('abort', onAborted));
141+
}
142+
}
128143
}
129144
ObjectSetPrototypeOf(Socket.prototype, EventEmitter.prototype);
130145
ObjectSetPrototypeOf(Socket, EventEmitter);
+33
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
'use strict';
2+
3+
const common = require('../common');
4+
const assert = require('assert');
5+
const dgram = require('dgram');
6+
7+
{
8+
// Test bad signal.
9+
assert.throws(
10+
() => dgram.createSocket({ type: 'udp4', signal: {} }),
11+
{
12+
code: 'ERR_INVALID_ARG_TYPE',
13+
name: 'TypeError'
14+
});
15+
}
16+
17+
{
18+
// Test close.
19+
const controller = new AbortController();
20+
const { signal } = controller;
21+
const server = dgram.createSocket({ type: 'udp4', signal });
22+
server.on('close', common.mustCall());
23+
controller.abort();
24+
}
25+
26+
{
27+
// Test close with pre-aborted signal.
28+
const controller = new AbortController();
29+
controller.abort();
30+
const { signal } = controller;
31+
const server = dgram.createSocket({ type: 'udp4', signal });
32+
server.on('close', common.mustCall());
33+
}

0 commit comments

Comments
 (0)