Skip to content

Commit

Permalink
dgram: support AbortSignal in createSocket
Browse files Browse the repository at this point in the history
PR-URL: #37026
Backport-PR-URL: #38386
Reviewed-By: Benjamin Gruenbaum <benjamingr@gmail.com>
Reviewed-By: Rich Trott <rtrott@gmail.com>
  • Loading branch information
Nitzan Uziely authored and targos committed Apr 30, 2021
1 parent 1b74a08 commit 81cd06b
Show file tree
Hide file tree
Showing 3 changed files with 67 additions and 0 deletions.
18 changes: 18 additions & 0 deletions doc/api/dgram.md
Original file line number Diff line number Diff line change
Expand Up @@ -733,6 +733,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.
Expand All @@ -757,6 +760,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}

Expand All @@ -768,6 +772,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
Expand Down
15 changes: 15 additions & 0 deletions lib/dgram.js
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@ const {
} = errors.codes;
const {
isInt32,
validateAbortSignal,
validateString,
validateNumber,
validatePort,
Expand Down Expand Up @@ -121,6 +122,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);
Expand Down
34 changes: 34 additions & 0 deletions test/parallel/test-dgram-close-signal.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
// Flags: --experimental-abortcontroller
'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());
}

0 comments on commit 81cd06b

Please sign in to comment.