| FazBrowse GitHub Viewer | Trending | | Home |
| Tools: [Download Repo ZIP] [Original HTTPS Page] |
1 parent 5020955 commit 3017a54
5 files changed
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -733,6 +733,9 @@ it to interact with the client. | |||
| 733 | 733 | <!-- YAML | |
| 734 | 734 | added: v0.3.4 | |
| 735 | 735 | changes: | |
| 736 | + - version: REPLACEME | ||
| 737 | + pr-url: https://github.com/nodejs/node/pull/61503 | ||
| 738 | + description: Added `typeOfService` option. | ||
| 736 | 739 | - version: v15.14.0 | |
| 737 | 740 | pr-url: https://github.com/nodejs/node/pull/37735 | |
| 738 | 741 | description: AbortSignal support was added. | |
@@ -774,6 +777,7 @@ changes: | |||
| 774 | 777 | otherwise ignored. **Default:** `false`. | |
| 775 | 778 | * `signal` {AbortSignal} An Abort signal that may be used to destroy the | |
| 776 | 779 | socket. | |
| 780 | + * `typeOfService` {number} The initial Type of Service (TOS) value. | ||
| 777 | 781 | * `writable` {boolean} Allow writes on the socket when an `fd` is passed, | |
| 778 | 782 | otherwise ignored. **Default:** `false`. | |
| 779 | 783 | * Returns: {net.Socket} | |
@@ -1447,6 +1451,45 @@ If `timeout` is 0, then the existing idle timeout is disabled. | |||
| 1447 | 1451 | The optional `callback` parameter will be added as a one-time listener for the | |
| 1448 | 1452 | [`'timeout'`][] event. | |
| 1449 | 1453 | ||
| 1454 | + ### `socket.getTypeOfService()` | ||
| 1455 | + | ||
| 1456 | + <!-- YAML | ||
| 1457 | + added: REPLACEME | ||
| 1458 | + --> | ||
| 1459 | + | ||
| 1460 | + * Returns: {integer} The current TOS value. | ||
| 1461 | + | ||
| 1462 | + Returns the current Type of Service (TOS) field for IPv4 packets or Traffic | ||
| 1463 | + Class for IPv6 packets for this socket. | ||
| 1464 | + | ||
| 1465 | + `setTypeOfService()` may be called before the socket is connected; the value | ||
| 1466 | + will be cached and applied when the socket establishes a connection. | ||
| 1467 | + `getTypeOfService()` will return the currently set value even before connection. | ||
| 1468 | + | ||
| 1469 | + On some platforms (e.g., Linux), certain TOS/ECN bits may be masked or ignored, | ||
| 1470 | + and behavior can differ between IPv4 and IPv6 or dual-stack sockets. Callers | ||
| 1471 | + should verify platform-specific semantics. | ||
| 1472 | + | ||
| 1473 | + ### `socket.setTypeOfService(tos)` | ||
| 1474 | + | ||
| 1475 | + <!-- YAML | ||
| 1476 | + added: REPLACEME | ||
| 1477 | + --> | ||
| 1478 | + | ||
| 1479 | + * `tos` {integer} The TOS value to set (0-255). | ||
| 1480 | + * Returns: {net.Socket} The socket itself. | ||
| 1481 | + | ||
| 1482 | + Sets the Type of Service (TOS) field for IPv4 packets or Traffic Class for IPv6 | ||
| 1483 | + Packets sent from this socket. This can be used to prioritize network traffic. | ||
| 1484 | + | ||
| 1485 | + `setTypeOfService()` may be called before the socket is connected; the value | ||
| 1486 | + will be cached and applied when the socket establishes a connection. | ||
| 1487 | + `getTypeOfService()` will return the currently set value even before connection. | ||
| 1488 | + | ||
| 1489 | + On some platforms (e.g., Linux), certain TOS/ECN bits may be masked or ignored, | ||
| 1490 | + and behavior can differ between IPv4 and IPv6 or dual-stack sockets. Callers | ||
| 1491 | + should verify platform-specific semantics. | ||
| 1492 | + | ||
| 1450 | 1493 | ### `socket.timeout` | |
| 1451 | 1494 | ||
| 1452 | 1495 | <!-- YAML | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -55,6 +55,7 @@ const { | |||
| 55 | 55 | const assert = require('internal/assert'); | |
| 56 | 56 | const { | |
| 57 | 57 | UV_EADDRINUSE, | |
| 58 | + UV_EBADF, | ||
| 58 | 59 | UV_EINVAL, | |
| 59 | 60 | UV_ENOTCONN, | |
| 60 | 61 | UV_ECANCELED, | |
@@ -359,6 +360,7 @@ const kBytesWritten = Symbol('kBytesWritten'); | |||
| 359 | 360 | const kSetNoDelay = Symbol('kSetNoDelay'); | |
| 360 | 361 | const kSetKeepAlive = Symbol('kSetKeepAlive'); | |
| 361 | 362 | const kSetKeepAliveInitialDelay = Symbol('kSetKeepAliveInitialDelay'); | |
| 363 | + const kSetTOS = Symbol('kSetTOS'); | ||
| 362 | 364 | ||
| 363 | 365 | function Socket(options) { | |
| 364 | 366 | if (!(this instanceof Socket)) return new Socket(options); | |
@@ -474,6 +476,10 @@ function Socket(options) { | |||
| 474 | 476 | this[kSetNoDelay] = Boolean(options.noDelay); | |
| 475 | 477 | this[kSetKeepAlive] = Boolean(options.keepAlive); | |
| 476 | 478 | this[kSetKeepAliveInitialDelay] = ~~(options.keepAliveInitialDelay / 1000); | |
| 479 | + if (options.typeOfService !== undefined) { | ||
| 480 | + validateInt32(options.typeOfService, 'options.typeOfService', 0, 255); | ||
| 481 | + } | ||
| 482 | + this[kSetTOS] = options.typeOfService; | ||
| 477 | 483 | ||
| 478 | 484 | // Shut down the socket when we're finished with it. | |
| 479 | 485 | this.on('end', onReadableStreamEnd); | |
@@ -653,6 +659,59 @@ Socket.prototype.setKeepAlive = function(enable, initialDelayMsecs) { | |||
| 653 | 659 | }; | |
| 654 | 660 | ||
| 655 | 661 | ||
| 662 | + Socket.prototype.setTypeOfService = function(tos) { | ||
| 663 | + if (NumberIsNaN(tos)) { | ||
| 664 | + throw new ERR_INVALID_ARG_TYPE('tos', 'number', tos); | ||
| 665 | + } | ||
| 666 | + validateInt32(tos, 'tos', 0, 255); | ||
| 667 | + | ||
| 668 | + if (!this._handle) { | ||
| 669 | + this[kSetTOS] = tos; | ||
| 670 | + return this; | ||
| 671 | + } | ||
| 672 | + | ||
| 673 | + if (!this._handle.setTypeOfService) { | ||
| 674 | + this[kSetTOS] = tos; | ||
| 675 | + return this; | ||
| 676 | + } | ||
| 677 | + | ||
| 678 | + if (tos !== this[kSetTOS]) { | ||
| 679 | + this[kSetTOS] = tos; | ||
| 680 | + const err = this._handle.setTypeOfService(tos); | ||
| 681 | + // On Windows, setting TOS is often restricted or returns error codes even if partially applied. | ||
| 682 | + // We treat this as a "best effort" operation and do not throw on Windows. | ||
| 683 | + if (err && !isWindows) { | ||
| 684 | + throw new ErrnoException(err, 'setTypeOfService'); | ||
| 685 | + } | ||
| 686 | + } | ||
| 687 | + | ||
| 688 | + return this; | ||
| 689 | + }; | ||
| 690 | + | ||
| 691 | + | ||
| 692 | + Socket.prototype.getTypeOfService = function() { | ||
| 693 | + if (!this._handle) { | ||
| 694 | + // Return cached value if set, otherwise default to 0 | ||
| 695 | + return this[kSetTOS] !== undefined ? this[kSetTOS] : 0; | ||
| 696 | + } | ||
| 697 | + | ||
| 698 | + if (!this._handle.getTypeOfService) { | ||
| 699 | + return this[kSetTOS] !== undefined ? this[kSetTOS] : 0; | ||
| 700 | + } | ||
| 701 | + | ||
| 702 | + const res = this._handle.getTypeOfService(); | ||
| 703 | + if (typeof res === 'number' && res < 0) { | ||
| 704 | + // On Windows, getsockopt(IP_TOS) often fails. In that case, fall back | ||
| 705 | + // to the cached value we attempted to set, or 0. | ||
| 706 | + if (isWindows) { | ||
| 707 | + return this[kSetTOS] !== undefined ? this[kSetTOS] : 0; | ||
| 708 | + } | ||
| 709 | + throw new ErrnoException(res, 'getTypeOfService'); | ||
| 710 | + } | ||
| 711 | + return res; | ||
| 712 | + }; | ||
| 713 | + | ||
| 714 | + | ||
| 656 | 715 | Socket.prototype.address = function() { | |
| 657 | 716 | return this._getsockname(); | |
| 658 | 717 | }; | |
@@ -1628,6 +1687,15 @@ function afterConnect(status, handle, req, readable, writable) { | |||
| 1628 | 1687 | self._handle.setKeepAlive(true, self[kSetKeepAliveInitialDelay]); | |
| 1629 | 1688 | } | |
| 1630 | 1689 | ||
| 1690 | + if (self[kSetTOS] !== undefined && self._handle.setTypeOfService) { | ||
| 1691 | + const err = self._handle.setTypeOfService(self[kSetTOS]); | ||
| 1692 | + // On Windows, setting TOS is best-effort. If it fails, we shouldn't destroy | ||
| 1693 | + // the connection or emit an error, as the socket is otherwise healthy. | ||
| 1694 | + if (err && err !== UV_EBADF && !isWindows) { | ||
| 1695 | + self.emit('error', new ErrnoException(err, 'setTypeOfService')); | ||
| 1696 | + } | ||
| 1697 | + } | ||
| 1698 | + | ||
| 1631 | 1699 | self.emit('connect'); | |
| 1632 | 1700 | self.emit('ready'); | |
| 1633 | 1701 | ||
| Back | FazBrowse Home | New Git URL |
0 commit comments