dgram: support AbortSignal in createSocket

PR-URL: https://github.com/nodejs/node/pull/37026
Reviewed-By: Benjamin Gruenbaum <benjamingr@gmail.com>
Reviewed-By: Rich Trott <rtrott@gmail.com>
This commit is contained in:
Nitzan Uziely 2021-01-22 23:01:43 +02:00 committed by Michaël Zasso
parent c79688ffe3
commit 2c7ad38c75
No known key found for this signature in database
GPG Key ID: 770F7A9A5AE15600
3 changed files with 66 additions and 0 deletions

View File

@ -735,6 +735,9 @@ chained.
<!-- YAML
added: v0.11.13
changes:
- version: REPLACEME
pr-url: https://github.com/nodejs/node/pull/37026
description: AbortSignal support was added.
- version: v11.4.0
pr-url: https://github.com/nodejs/node/pull/23798
description: The `ipv6Only` option is supported.
@ -759,6 +762,7 @@ changes:
* `recvBufferSize` {number} Sets the `SO_RCVBUF` socket value.
* `sendBufferSize` {number} Sets the `SO_SNDBUF` socket value.
* `lookup` {Function} Custom lookup function. **Default:** [`dns.lookup()`][].
* `signal` {AbortSignal} An AbortSignal that may be used to close a socket.
* `callback` {Function} Attached as a listener for `'message'` events. Optional.
* Returns: {dgram.Socket}
@ -770,6 +774,20 @@ method will bind the socket to the "all interfaces" address on a random port
and port can be retrieved using [`socket.address().address`][] and
[`socket.address().port`][].
If the `signal` option is enabled, calling `.abort()` on the corresponding
`AbortController` is similar to calling `.close()` on the socket:
```js
const controller = new AbortController();
const { signal } = controller;
const server = dgram.createSocket({ type: 'udp4', signal });
server.on('message', (msg, rinfo) => {
console.log(`server got: ${msg} from ${rinfo.address}:${rinfo.port}`);
});
// Later, when you want to close the server.
controller.abort();
```
### `dgram.createSocket(type[, callback])`
<!-- YAML
added: v0.1.99

View File

@ -52,6 +52,7 @@ const {
} = errors.codes;
const {
isInt32,
validateAbortSignal,
validateString,
validateNumber,
validatePort,
@ -125,6 +126,20 @@ function Socket(type, listener) {
recvBufferSize,
sendBufferSize
};
if (options?.signal !== undefined) {
const { signal } = options;
validateAbortSignal(signal, 'options.signal');
const onAborted = () => {
this.close();
};
if (signal.aborted) {
onAborted();
} else {
signal.addEventListener('abort', onAborted);
this.once('close', () => signal.removeEventListener('abort', onAborted));
}
}
}
ObjectSetPrototypeOf(Socket.prototype, EventEmitter.prototype);
ObjectSetPrototypeOf(Socket, EventEmitter);

View File

@ -0,0 +1,33 @@
'use strict';
const common = require('../common');
const assert = require('assert');
const dgram = require('dgram');
{
// Test bad signal.
assert.throws(
() => dgram.createSocket({ type: 'udp4', signal: {} }),
{
code: 'ERR_INVALID_ARG_TYPE',
name: 'TypeError'
});
}
{
// Test close.
const controller = new AbortController();
const { signal } = controller;
const server = dgram.createSocket({ type: 'udp4', signal });
server.on('close', common.mustCall());
controller.abort();
}
{
// Test close with pre-aborted signal.
const controller = new AbortController();
controller.abort();
const { signal } = controller;
const server = dgram.createSocket({ type: 'udp4', signal });
server.on('close', common.mustCall());
}