Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Appearance settings

Commit 4cf94fa

Browse filesBrowse files
amyssnippetaduh95
authored andcommitted
net: add setTOS and getTOS to Socket
PR-URL: #61503 Fixes: #61489 Reviewed-By: Matteo Collina <matteo.collina@gmail.com> Reviewed-By: Robert Nagy <ronagy@icloud.com> Reviewed-By: Anna Henningsen <anna@addaleax.net>
1 parent 3ad4d9b commit 4cf94fa
Copy full SHA for 4cf94fa

5 files changed

+428-86Lines changed: 428 additions & 86 deletions

File tree

Expand file treeCollapse file tree
Open diff view settings
Filter options
Expand file treeCollapse file tree
Open diff view settings
Collapse file

‎doc/api/net.md‎

Copy file name to clipboardExpand all lines: doc/api/net.md
+43Lines changed: 43 additions & 0 deletions
  • Display the source diff
  • Display the rich diff
Original file line numberDiff line numberDiff line change
@@ -747,6 +747,9 @@ it to interact with the client.
747747
<!-- YAML
748748
added: v0.3.4
749749
changes:
750+
- version: REPLACEME
751+
pr-url: https://github.com/nodejs/node/pull/61503
752+
description: Added `typeOfService` option.
750753
- version: v15.14.0
751754
pr-url: https://github.com/nodejs/node/pull/37735
752755
description: AbortSignal support was added.
@@ -788,6 +791,7 @@ changes:
788791
otherwise ignored. **Default:** `false`.
789792
* `signal` {AbortSignal} An Abort signal that may be used to destroy the
790793
socket.
794+
* `typeOfService` {number} The initial Type of Service (TOS) value.
791795
* `writable` {boolean} Allow writes on the socket when an `fd` is passed,
792796
otherwise ignored. **Default:** `false`.
793797
* Returns: {net.Socket}
@@ -1461,6 +1465,45 @@ If `timeout` is 0, then the existing idle timeout is disabled.
14611465
The optional `callback` parameter will be added as a one-time listener for the
14621466
[`'timeout'`][] event.
14631467

1468+
### `socket.getTypeOfService()`
1469+
1470+
<!-- YAML
1471+
added: REPLACEME
1472+
-->
1473+
1474+
* Returns: {integer} The current TOS value.
1475+
1476+
Returns the current Type of Service (TOS) field for IPv4 packets or Traffic
1477+
Class for IPv6 packets for this socket.
1478+
1479+
`setTypeOfService()` may be called before the socket is connected; the value
1480+
will be cached and applied when the socket establishes a connection.
1481+
`getTypeOfService()` will return the currently set value even before connection.
1482+
1483+
On some platforms (e.g., Linux), certain TOS/ECN bits may be masked or ignored,
1484+
and behavior can differ between IPv4 and IPv6 or dual-stack sockets. Callers
1485+
should verify platform-specific semantics.
1486+
1487+
### `socket.setTypeOfService(tos)`
1488+
1489+
<!-- YAML
1490+
added: REPLACEME
1491+
-->
1492+
1493+
* `tos` {integer} The TOS value to set (0-255).
1494+
* Returns: {net.Socket} The socket itself.
1495+
1496+
Sets the Type of Service (TOS) field for IPv4 packets or Traffic Class for IPv6
1497+
Packets sent from this socket. This can be used to prioritize network traffic.
1498+
1499+
`setTypeOfService()` may be called before the socket is connected; the value
1500+
will be cached and applied when the socket establishes a connection.
1501+
`getTypeOfService()` will return the currently set value even before connection.
1502+
1503+
On some platforms (e.g., Linux), certain TOS/ECN bits may be masked or ignored,
1504+
and behavior can differ between IPv4 and IPv6 or dual-stack sockets. Callers
1505+
should verify platform-specific semantics.
1506+
14641507
### `socket.timeout`
14651508

14661509
<!-- YAML
Collapse file

‎lib/net.js‎

Copy file name to clipboardExpand all lines: lib/net.js
+68Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,7 @@ const {
5757
const assert = require('internal/assert');
5858
const {
5959
UV_EADDRINUSE,
60+
UV_EBADF,
6061
UV_EINVAL,
6162
UV_ENOTCONN,
6263
UV_ECANCELED,
@@ -358,6 +359,7 @@ const kBytesWritten = Symbol('kBytesWritten');
358359
const kSetNoDelay = Symbol('kSetNoDelay');
359360
const kSetKeepAlive = Symbol('kSetKeepAlive');
360361
const kSetKeepAliveInitialDelay = Symbol('kSetKeepAliveInitialDelay');
362+
const kSetTOS = Symbol('kSetTOS');
361363

362364
function Socket(options) {
363365
if (!(this instanceof Socket)) return new Socket(options);
@@ -473,6 +475,10 @@ function Socket(options) {
473475
this[kSetNoDelay] = Boolean(options.noDelay);
474476
this[kSetKeepAlive] = Boolean(options.keepAlive);
475477
this[kSetKeepAliveInitialDelay] = ~~(options.keepAliveInitialDelay / 1000);
478+
if (options.typeOfService !== undefined) {
479+
validateInt32(options.typeOfService, 'options.typeOfService', 0, 255);
480+
}
481+
this[kSetTOS] = options.typeOfService;
476482

477483
// Shut down the socket when we're finished with it.
478484
this.on('end', onReadableStreamEnd);
@@ -652,6 +658,59 @@ Socket.prototype.setKeepAlive = function(enable, initialDelayMsecs) {
652658
};
653659

654660

661+
Socket.prototype.setTypeOfService = function(tos) {
662+
if (NumberIsNaN(tos)) {
663+
throw new ERR_INVALID_ARG_TYPE('tos', 'number', tos);
664+
}
665+
validateInt32(tos, 'tos', 0, 255);
666+
667+
if (!this._handle) {
668+
this[kSetTOS] = tos;
669+
return this;
670+
}
671+
672+
if (!this._handle.setTypeOfService) {
673+
this[kSetTOS] = tos;
674+
return this;
675+
}
676+
677+
if (tos !== this[kSetTOS]) {
678+
this[kSetTOS] = tos;
679+
const err = this._handle.setTypeOfService(tos);
680+
// On Windows, setting TOS is often restricted or returns error codes even if partially applied.
681+
// We treat this as a "best effort" operation and do not throw on Windows.
682+
if (err && !isWindows) {
683+
throw new ErrnoException(err, 'setTypeOfService');
684+
}
685+
}
686+
687+
return this;
688+
};
689+
690+
691+
Socket.prototype.getTypeOfService = function() {
692+
if (!this._handle) {
693+
// Return cached value if set, otherwise default to 0
694+
return this[kSetTOS] !== undefined ? this[kSetTOS] : 0;
695+
}
696+
697+
if (!this._handle.getTypeOfService) {
698+
return this[kSetTOS] !== undefined ? this[kSetTOS] : 0;
699+
}
700+
701+
const res = this._handle.getTypeOfService();
702+
if (typeof res === 'number' && res < 0) {
703+
// On Windows, getsockopt(IP_TOS) often fails. In that case, fall back
704+
// to the cached value we attempted to set, or 0.
705+
if (isWindows) {
706+
return this[kSetTOS] !== undefined ? this[kSetTOS] : 0;
707+
}
708+
throw new ErrnoException(res, 'getTypeOfService');
709+
}
710+
return res;
711+
};
712+
713+
655714
Socket.prototype.address = function() {
656715
return this._getsockname();
657716
};
@@ -1619,6 +1678,15 @@ function afterConnect(status, handle, req, readable, writable) {
16191678
self._handle.setKeepAlive(true, self[kSetKeepAliveInitialDelay]);
16201679
}
16211680

1681+
if (self[kSetTOS] !== undefined && self._handle.setTypeOfService) {
1682+
const err = self._handle.setTypeOfService(self[kSetTOS]);
1683+
// On Windows, setting TOS is best-effort. If it fails, we shouldn't destroy
1684+
// the connection or emit an error, as the socket is otherwise healthy.
1685+
if (err && err !== UV_EBADF && !isWindows) {
1686+
self.emit('error', new ErrnoException(err, 'setTypeOfService'));
1687+
}
1688+
}
1689+
16221690
self.emit('connect');
16231691
self.emit('ready');
16241692

0 commit comments

Comments
0 (0)
Morty Proxy This is a proxified and sanitized view of the page, visit original site.