werift 0.24.3 → 0.25.0-alpha.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +116 -113
- package/lib/common/src/event.js +2 -1
- package/lib/common/src/event.js.map +1 -1
- package/lib/common/src/transport.d.ts +22 -2
- package/lib/common/src/transport.js +84 -26
- package/lib/common/src/transport.js.map +1 -1
- package/lib/ice/src/exceptions.d.ts +9 -0
- package/lib/ice/src/exceptions.js +23 -1
- package/lib/ice/src/exceptions.js.map +1 -1
- package/lib/ice/src/ice.d.ts +40 -0
- package/lib/ice/src/ice.js +194 -28
- package/lib/ice/src/ice.js.map +1 -1
- package/lib/ice/src/iceBase.d.ts +26 -0
- package/lib/ice/src/iceBase.js.map +1 -1
- package/lib/ice/src/stun/const.d.ts +7 -0
- package/lib/ice/src/stun/const.js +8 -0
- package/lib/ice/src/stun/const.js.map +1 -1
- package/lib/ice/src/stun/protocol.js +1 -4
- package/lib/ice/src/stun/protocol.js.map +1 -1
- package/lib/ice/src/stun/tcpProtocol.d.ts +7 -1
- package/lib/ice/src/stun/tcpProtocol.js +65 -14
- package/lib/ice/src/stun/tcpProtocol.js.map +1 -1
- package/lib/ice/src/stun/transaction.d.ts +12 -1
- package/lib/ice/src/stun/transaction.js +37 -4
- package/lib/ice/src/stun/transaction.js.map +1 -1
- package/lib/ice/src/turn/protocol.d.ts +79 -22
- package/lib/ice/src/turn/protocol.js +282 -78
- package/lib/ice/src/turn/protocol.js.map +1 -1
- package/lib/ice/src/types/model.d.ts +8 -0
- package/lib/ice/src/types/model.js.map +1 -1
- package/lib/index.mjs +5646 -3451
- package/lib/nonstandard/index.mjs +287 -1004
- package/lib/polyfill/dom.mjs +23794 -0
- package/lib/polyfill/index.mjs +23794 -0
- package/lib/rtp/src/extra/container/mp4/container.js +12 -4
- package/lib/rtp/src/extra/container/mp4/container.js.map +1 -1
- package/lib/rtp/src/extra/processor/mp4.js +8 -3
- package/lib/rtp/src/extra/processor/mp4.js.map +1 -1
- package/lib/rtp/src/extra/processor/mp4Callback.js +3 -1
- package/lib/rtp/src/extra/processor/mp4Callback.js.map +1 -1
- package/lib/sctp/src/chunk.d.ts +5 -0
- package/lib/sctp/src/chunk.js +16 -11
- package/lib/sctp/src/chunk.js.map +1 -1
- package/lib/sctp/src/index.d.ts +3 -1
- package/lib/sctp/src/index.js +10 -1
- package/lib/sctp/src/index.js.map +1 -1
- package/lib/sctp/src/sctp.d.ts +12 -3
- package/lib/sctp/src/sctp.js +51 -18
- package/lib/sctp/src/sctp.js.map +1 -1
- package/lib/webrtc/src/const.js +2 -0
- package/lib/webrtc/src/const.js.map +1 -1
- package/lib/webrtc/src/errors.d.ts +9 -1
- package/lib/webrtc/src/errors.js +19 -0
- package/lib/webrtc/src/errors.js.map +1 -1
- package/lib/webrtc/src/media/codec.d.ts +5 -0
- package/lib/webrtc/src/media/codec.js +21 -0
- package/lib/webrtc/src/media/codec.js.map +1 -1
- package/lib/webrtc/src/media/codecCompatibility.d.ts +23 -0
- package/lib/webrtc/src/media/codecCompatibility.js +138 -0
- package/lib/webrtc/src/media/codecCompatibility.js.map +1 -0
- package/lib/webrtc/src/media/index.d.ts +1 -0
- package/lib/webrtc/src/media/index.js +1 -0
- package/lib/webrtc/src/media/index.js.map +1 -1
- package/lib/webrtc/src/media/router.d.ts +2 -0
- package/lib/webrtc/src/media/router.js +23 -3
- package/lib/webrtc/src/media/router.js.map +1 -1
- package/lib/webrtc/src/media/rtpReceiver.d.ts +12 -0
- package/lib/webrtc/src/media/rtpReceiver.js +35 -0
- package/lib/webrtc/src/media/rtpReceiver.js.map +1 -1
- package/lib/webrtc/src/media/rtpSender.d.ts +65 -4
- package/lib/webrtc/src/media/rtpSender.js +264 -35
- package/lib/webrtc/src/media/rtpSender.js.map +1 -1
- package/lib/webrtc/src/media/rtpTransceiver.d.ts +42 -0
- package/lib/webrtc/src/media/rtpTransceiver.js +157 -4
- package/lib/webrtc/src/media/rtpTransceiver.js.map +1 -1
- package/lib/webrtc/src/media/track.d.ts +29 -1
- package/lib/webrtc/src/media/track.js +164 -5
- package/lib/webrtc/src/media/track.js.map +1 -1
- package/lib/webrtc/src/nonstandard/index.d.ts +0 -1
- package/lib/webrtc/src/nonstandard/index.js +0 -1
- package/lib/webrtc/src/nonstandard/index.js.map +1 -1
- package/lib/webrtc/src/nonstandard/recorder/writer/webm.js +2 -1
- package/lib/webrtc/src/nonstandard/recorder/writer/webm.js.map +1 -1
- package/lib/webrtc/src/nonstandard/userMedia.d.ts +1 -2
- package/lib/webrtc/src/nonstandard/userMedia.js +30 -14
- package/lib/webrtc/src/nonstandard/userMedia.js.map +1 -1
- package/lib/webrtc/src/peerConnection.d.ts +127 -5
- package/lib/webrtc/src/peerConnection.js +629 -143
- package/lib/webrtc/src/peerConnection.js.map +1 -1
- package/lib/webrtc/src/polyfill/api.d.ts +14 -0
- package/lib/webrtc/src/polyfill/api.js +23 -0
- package/lib/webrtc/src/polyfill/api.js.map +1 -0
- package/lib/webrtc/src/polyfill/browserIdentity.d.ts +11 -0
- package/lib/webrtc/src/polyfill/browserIdentity.js +59 -0
- package/lib/webrtc/src/polyfill/browserIdentity.js.map +1 -0
- package/lib/webrtc/src/polyfill/dom.d.ts +11 -0
- package/lib/webrtc/src/polyfill/dom.js +18 -0
- package/lib/webrtc/src/polyfill/dom.js.map +1 -0
- package/lib/webrtc/src/polyfill/existingMediaDevices.d.ts +2 -0
- package/lib/webrtc/src/polyfill/existingMediaDevices.js +22 -0
- package/lib/webrtc/src/polyfill/existingMediaDevices.js.map +1 -0
- package/lib/webrtc/src/polyfill/globals.d.ts +28 -0
- package/lib/webrtc/src/polyfill/globals.js +3 -0
- package/lib/webrtc/src/polyfill/globals.js.map +1 -0
- package/lib/webrtc/src/polyfill/index.d.ts +2 -0
- package/lib/webrtc/src/polyfill/index.js +19 -0
- package/lib/webrtc/src/polyfill/index.js.map +1 -0
- package/lib/webrtc/src/polyfill/install.d.ts +13 -0
- package/lib/webrtc/src/polyfill/install.js +266 -0
- package/lib/webrtc/src/polyfill/install.js.map +1 -0
- package/lib/webrtc/src/polyfill/mediaDevices.d.ts +38 -0
- package/lib/webrtc/src/polyfill/mediaDevices.js +228 -0
- package/lib/webrtc/src/polyfill/mediaDevices.js.map +1 -0
- package/lib/webrtc/src/polyfill/mediaRegister.d.ts +51 -0
- package/lib/webrtc/src/polyfill/mediaRegister.js +14 -0
- package/lib/webrtc/src/polyfill/mediaRegister.js.map +1 -0
- package/lib/webrtc/src/polyfill/peerConnectionConfig.d.ts +3 -0
- package/lib/webrtc/src/polyfill/peerConnectionConfig.js +52 -0
- package/lib/webrtc/src/polyfill/peerConnectionConfig.js.map +1 -0
- package/lib/webrtc/src/polyfill/registers/callback.d.ts +16 -0
- package/lib/webrtc/src/polyfill/registers/callback.js +57 -0
- package/lib/webrtc/src/polyfill/registers/callback.js.map +1 -0
- package/lib/webrtc/src/polyfill/registers/empty.d.ts +2 -0
- package/lib/webrtc/src/polyfill/registers/empty.js +28 -0
- package/lib/webrtc/src/polyfill/registers/empty.js.map +1 -0
- package/lib/webrtc/src/polyfill/registers/mp4Webm.d.ts +36 -0
- package/lib/webrtc/src/polyfill/registers/mp4Webm.js +242 -0
- package/lib/webrtc/src/polyfill/registers/mp4Webm.js.map +1 -0
- package/lib/webrtc/src/polyfill/registers/rtpRtcp.d.ts +17 -0
- package/lib/webrtc/src/polyfill/registers/rtpRtcp.js +143 -0
- package/lib/webrtc/src/polyfill/registers/rtpRtcp.js.map +1 -0
- package/lib/webrtc/src/polyfill/rtcSessionDescription.d.ts +18 -0
- package/lib/webrtc/src/polyfill/rtcSessionDescription.js +36 -0
- package/lib/webrtc/src/polyfill/rtcSessionDescription.js.map +1 -0
- package/lib/webrtc/src/polyfill/rtpCodec.d.ts +17 -0
- package/lib/webrtc/src/polyfill/rtpCodec.js +93 -0
- package/lib/webrtc/src/polyfill/rtpCodec.js.map +1 -0
- package/lib/webrtc/src/polyfill/selectSettings.d.ts +31 -0
- package/lib/webrtc/src/polyfill/selectSettings.js +156 -0
- package/lib/webrtc/src/polyfill/selectSettings.js.map +1 -0
- package/lib/webrtc/src/polyfill/sourceIo.d.ts +21 -0
- package/lib/webrtc/src/polyfill/sourceIo.js +298 -0
- package/lib/webrtc/src/polyfill/sourceIo.js.map +1 -0
- package/lib/webrtc/src/polyfill/trackStop.d.ts +4 -0
- package/lib/webrtc/src/polyfill/trackStop.js +16 -0
- package/lib/webrtc/src/polyfill/trackStop.js.map +1 -0
- package/lib/webrtc/src/sctpManager.d.ts +2 -1
- package/lib/webrtc/src/sctpManager.js +5 -2
- package/lib/webrtc/src/sctpManager.js.map +1 -1
- package/lib/webrtc/src/sdp.d.ts +1 -1
- package/lib/webrtc/src/sdp.js +5 -6
- package/lib/webrtc/src/sdp.js.map +1 -1
- package/lib/webrtc/src/sdpManager.d.ts +38 -1
- package/lib/webrtc/src/sdpManager.js +236 -30
- package/lib/webrtc/src/sdpManager.js.map +1 -1
- package/lib/webrtc/src/secureTransportManager.d.ts +43 -12
- package/lib/webrtc/src/secureTransportManager.js +123 -47
- package/lib/webrtc/src/secureTransportManager.js.map +1 -1
- package/lib/webrtc/src/transceiverManager.d.ts +91 -6
- package/lib/webrtc/src/transceiverManager.js +477 -62
- package/lib/webrtc/src/transceiverManager.js.map +1 -1
- package/lib/webrtc/src/transport/ice.d.ts +8 -0
- package/lib/webrtc/src/transport/ice.js +17 -1
- package/lib/webrtc/src/transport/ice.js.map +1 -1
- package/lib/webrtc/src/transport/sctp.d.ts +3 -2
- package/lib/webrtc/src/transport/sctp.js +8 -2
- package/lib/webrtc/src/transport/sctp.js.map +1 -1
- package/package.json +14 -3
|
@@ -14,5 +14,13 @@ var __exportStar = (this && this.__exportStar) || function(m, exports) {
|
|
|
14
14
|
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
|
|
15
15
|
};
|
|
16
16
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
17
|
+
exports.TCP_CHECK_RESPONSE_TIMEOUT_MS = void 0;
|
|
17
18
|
__exportStar(require("../../../ice-server/src/stun/const"), exports);
|
|
19
|
+
/**
|
|
20
|
+
* Response deadline for ICE connectivity checks over TCP (RFC 6544).
|
|
21
|
+
* Reliable transports send each STUN request once (RFC 5389 §7.2.2), so this
|
|
22
|
+
* single wait has to cover the TCP connect of an active candidate as well as
|
|
23
|
+
* the request/response round trip on a loaded host.
|
|
24
|
+
*/
|
|
25
|
+
exports.TCP_CHECK_RESPONSE_TIMEOUT_MS = 3000;
|
|
18
26
|
//# sourceMappingURL=const.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"const.js","sourceRoot":"","sources":["../../../../../ice/src/stun/const.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"const.js","sourceRoot":"","sources":["../../../../../ice/src/stun/const.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;AAAA,qEAAmD;AAEnD;;;;;GAKG;AACU,QAAA,6BAA6B,GAAG,IAAI,CAAC","sourcesContent":["export * from \"../../../ice-server/src/stun/const\";\n\n/**\n * Response deadline for ICE connectivity checks over TCP (RFC 6544).\n * Reliable transports send each STUN request once (RFC 5389 §7.2.2), so this\n * single wait has to cover the TCP connect of an active candidate as well as\n * the request/response round trip on a loaded host.\n */\nexport const TCP_CHECK_RESPONSE_TIMEOUT_MS = 3000;\n"]}
|
|
@@ -144,10 +144,7 @@ class StunProtocol {
|
|
|
144
144
|
request.addFingerprint();
|
|
145
145
|
}
|
|
146
146
|
// Match DNS family to the bound socket so STUN hostname targets resolve correctly.
|
|
147
|
-
const
|
|
148
|
-
.socketType;
|
|
149
|
-
const family = socketType === "udp6" ? 6 : 4;
|
|
150
|
-
const resolvedAddr = await (0, transaction_1.resolveRequestAddress)(addr, family);
|
|
147
|
+
const resolvedAddr = await (0, transaction_1.resolveRequestAddress)(addr, this.transport.addressFamily);
|
|
151
148
|
const options = (0, transaction_1.buildTransactionOptions)(integrityKey, retransmissionsOrOptions, onRequestSent);
|
|
152
149
|
const transaction = new transaction_1.Transaction(request, resolvedAddr, this, options);
|
|
153
150
|
this.transactions[request.transactionIdHex] = transaction;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"protocol.js","sourceRoot":"","sources":["../../../../../ice/src/stun/protocol.ts"],"names":[],"mappings":"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
|
|
1
|
+
{"version":3,"file":"protocol.js","sourceRoot":"","sources":["../../../../../ice/src/stun/protocol.ts"],"names":[],"mappings":"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","sourcesContent":["import { Event, UdpTransport, debug } from \"../imports/common\";\n\nimport type { Address, InterfaceAddresses } from \"../../../common/src/network\";\nimport type { Candidate } from \"../candidate\";\n\nimport type { Protocol, TransactionRequestOptions } from \"../types/model\";\nimport { classes } from \"./const\";\nimport { type Message, parseMessage } from \"./message\";\nimport {\n Transaction,\n buildTransactionOptions,\n resolveRequestAddress,\n} from \"./transaction\";\n\nconst log = debug(\"werift-ice : packages/ice/src/stun/protocol.ts\");\n\nexport class StunProtocol implements Protocol {\n static readonly type = \"stun\";\n readonly type = StunProtocol.type;\n transport!: UdpTransport;\n transactions: { [key: string]: Transaction } = {};\n get transactionsKeys() {\n return Object.keys(this.transactions);\n }\n localCandidate?: Candidate;\n sentMessage?: Message;\n localIp?: string;\n\n readonly onRequestReceived = new Event<[Message, Address, Buffer]>();\n readonly onDataReceived = new Event<[Buffer]>();\n\n constructor() {}\n\n connectionMade = async (\n useIpv4: boolean,\n portRange?: [number, number],\n interfaceAddresses?: InterfaceAddresses,\n ) => {\n if (useIpv4) {\n this.transport = await UdpTransport.init(\"udp4\", {\n portRange,\n interfaceAddresses,\n });\n } else {\n this.transport = await UdpTransport.init(\"udp6\", {\n portRange,\n interfaceAddresses,\n });\n }\n\n this.transport.onData = (data, addr) => {\n this.datagramReceived(data, addr);\n };\n };\n\n private datagramReceived(data: Buffer, addr: Address) {\n try {\n const message = parseMessage(data);\n if (!message) {\n if (this.localCandidate) {\n this.onDataReceived.execute(data);\n }\n return;\n }\n // log(\"parseMessage\", addr, message.toJSON());\n if (\n (message.messageClass === classes.RESPONSE ||\n message.messageClass === classes.ERROR) &&\n this.transactionsKeys.includes(message.transactionIdHex)\n ) {\n const transaction = this.transactions[message.transactionIdHex];\n // Re-parse with integrity key so unauthenticated responses are dropped.\n const verified = transaction.integrityKey\n ? parseMessage(data, transaction.integrityKey)\n : message;\n if (!verified) {\n log(\"STUN response failed MESSAGE-INTEGRITY check\");\n return;\n }\n transaction.responseReceived(verified, addr);\n } else if (message.messageClass === classes.REQUEST) {\n this.onRequestReceived.execute(message, addr, data);\n }\n } catch (error) {\n log(\"datagramReceived error\", error);\n }\n }\n\n getExtraInfo(): Address {\n const { address: host, port } = this.transport.address;\n return [host, port];\n }\n\n async sendStun(message: Message, addr: Address) {\n if (this.transport.closed) {\n return;\n }\n\n const data = message.bytes;\n await this.transport.send(data, addr).catch(() => {\n log(\"sendStun failed\", addr, message);\n });\n }\n\n async sendData(data: Buffer, addr: Address) {\n if (this.transport.closed) {\n return;\n }\n\n await this.transport.send(data, addr);\n }\n\n async request(\n request: Message,\n addr: Address,\n integrityKey?: Buffer,\n retransmissionsOrOptions?: number | TransactionRequestOptions,\n onRequestSent?: (attempt: number) => void,\n ) {\n // \"\"\"\n // Execute a STUN transaction and return the response.\n // \"\"\"\n if (this.transactionsKeys.includes(request.transactionIdHex))\n throw new Error(\"already request ed\");\n\n if (integrityKey) {\n request.addMessageIntegrity(integrityKey);\n request.addFingerprint();\n }\n\n // Match DNS family to the bound socket so STUN hostname targets resolve correctly.\n const resolvedAddr = await resolveRequestAddress(\n addr,\n this.transport.addressFamily,\n );\n\n const options = buildTransactionOptions(\n integrityKey,\n retransmissionsOrOptions,\n onRequestSent,\n );\n const transaction: Transaction = new Transaction(\n request,\n resolvedAddr,\n this,\n options,\n );\n this.transactions[request.transactionIdHex] = transaction;\n\n try {\n return await transaction.run();\n } catch (e) {\n throw e;\n } finally {\n delete this.transactions[request.transactionIdHex];\n }\n }\n\n async close() {\n Object.values(this.transactions).forEach((transaction) => {\n transaction.cancel();\n });\n await this.transport.close();\n this.onRequestReceived.complete();\n this.onDataReceived.complete();\n }\n}\n"]}
|
|
@@ -20,11 +20,17 @@ declare abstract class BaseTcpProtocol implements Protocol {
|
|
|
20
20
|
localIp?: string;
|
|
21
21
|
readonly onRequestReceived: Event<[Message, readonly [string, number], Buffer<ArrayBufferLike>]>;
|
|
22
22
|
readonly onDataReceived: Event<[Buffer<ArrayBufferLike>]>;
|
|
23
|
+
/** The connection to this remote address was closed (by either side). */
|
|
24
|
+
readonly onConnectionClosed: Event<[readonly [string, number]]>;
|
|
23
25
|
protected readonly sockets: Map<string, SocketEntry>;
|
|
24
26
|
abstract connectionMade(...args: any[]): Promise<void>;
|
|
25
27
|
protected abstract getSocket(addr: Address): Promise<SocketEntry>;
|
|
26
28
|
protected rememberSocket(entry: SocketEntry): void;
|
|
27
|
-
|
|
29
|
+
/** Drop `entry` only if it is still the socket registered for its address. */
|
|
30
|
+
protected forgetSocket(entry: SocketEntry): boolean;
|
|
31
|
+
/** Registered socket for `addr`, discarding it if it is already closed. */
|
|
32
|
+
protected getOpenSocket(addr: Address): SocketEntry | undefined;
|
|
33
|
+
private dropSocket;
|
|
28
34
|
protected registerSocket(socket: Socket, remoteAddr?: Address): SocketEntry;
|
|
29
35
|
private handleFrame;
|
|
30
36
|
private sendFrame;
|
|
@@ -11,6 +11,9 @@ const log = (0, common_1.debug)("werift-ice:packages/ice/src/stun/tcpProtocol.ts
|
|
|
11
11
|
function socketKey(addr) {
|
|
12
12
|
return `${addr[0]}:${addr[1]}`;
|
|
13
13
|
}
|
|
14
|
+
function isSocketClosed(socket) {
|
|
15
|
+
return socket.destroyed || socket.writableEnded;
|
|
16
|
+
}
|
|
14
17
|
function addressFromSocket(socket) {
|
|
15
18
|
if (!socket.remoteAddress || !socket.remotePort) {
|
|
16
19
|
return;
|
|
@@ -80,6 +83,13 @@ class BaseTcpProtocol {
|
|
|
80
83
|
writable: true,
|
|
81
84
|
value: new common_1.Event()
|
|
82
85
|
});
|
|
86
|
+
/** The connection to this remote address was closed (by either side). */
|
|
87
|
+
Object.defineProperty(this, "onConnectionClosed", {
|
|
88
|
+
enumerable: true,
|
|
89
|
+
configurable: true,
|
|
90
|
+
writable: true,
|
|
91
|
+
value: new common_1.Event()
|
|
92
|
+
});
|
|
83
93
|
Object.defineProperty(this, "sockets", {
|
|
84
94
|
enumerable: true,
|
|
85
95
|
configurable: true,
|
|
@@ -94,11 +104,36 @@ class BaseTcpProtocol {
|
|
|
94
104
|
}
|
|
95
105
|
this.sockets.set(socketKey(remoteAddr), entry);
|
|
96
106
|
}
|
|
97
|
-
|
|
107
|
+
/** Drop `entry` only if it is still the socket registered for its address. */
|
|
108
|
+
forgetSocket(entry) {
|
|
109
|
+
const remoteAddr = entry.remoteAddr;
|
|
98
110
|
if (!remoteAddr) {
|
|
111
|
+
return false;
|
|
112
|
+
}
|
|
113
|
+
const key = socketKey(remoteAddr);
|
|
114
|
+
if (this.sockets.get(key) !== entry) {
|
|
115
|
+
return false;
|
|
116
|
+
}
|
|
117
|
+
this.sockets.delete(key);
|
|
118
|
+
return true;
|
|
119
|
+
}
|
|
120
|
+
/** Registered socket for `addr`, discarding it if it is already closed. */
|
|
121
|
+
getOpenSocket(addr) {
|
|
122
|
+
const entry = this.sockets.get(socketKey(addr));
|
|
123
|
+
if (!entry) {
|
|
124
|
+
return;
|
|
125
|
+
}
|
|
126
|
+
if (isSocketClosed(entry.socket)) {
|
|
127
|
+
this.dropSocket(entry);
|
|
99
128
|
return;
|
|
100
129
|
}
|
|
101
|
-
|
|
130
|
+
return entry;
|
|
131
|
+
}
|
|
132
|
+
dropSocket(entry) {
|
|
133
|
+
entry.socket.destroy();
|
|
134
|
+
if (this.forgetSocket(entry) && entry.remoteAddr) {
|
|
135
|
+
this.onConnectionClosed.execute(entry.remoteAddr);
|
|
136
|
+
}
|
|
102
137
|
}
|
|
103
138
|
registerSocket(socket, remoteAddr) {
|
|
104
139
|
const entry = {
|
|
@@ -129,7 +164,9 @@ class BaseTcpProtocol {
|
|
|
129
164
|
}
|
|
130
165
|
});
|
|
131
166
|
socket.on("close", () => {
|
|
132
|
-
this.forgetSocket(entry.remoteAddr)
|
|
167
|
+
if (this.forgetSocket(entry) && entry.remoteAddr) {
|
|
168
|
+
this.onConnectionClosed.execute(entry.remoteAddr);
|
|
169
|
+
}
|
|
133
170
|
});
|
|
134
171
|
socket.on("error", (error) => {
|
|
135
172
|
log("tcp socket error", error);
|
|
@@ -166,15 +203,24 @@ class BaseTcpProtocol {
|
|
|
166
203
|
}
|
|
167
204
|
async sendFrame(data, addr) {
|
|
168
205
|
const entry = await this.getSocket(addr);
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
206
|
+
try {
|
|
207
|
+
await new Promise((resolve, reject) => {
|
|
208
|
+
entry.socket.write((0, tcpFrame_1.encodeTcpFrame)(data), (error) => {
|
|
209
|
+
if (error) {
|
|
210
|
+
reject(error);
|
|
211
|
+
return;
|
|
212
|
+
}
|
|
213
|
+
resolve();
|
|
214
|
+
});
|
|
176
215
|
});
|
|
177
|
-
}
|
|
216
|
+
}
|
|
217
|
+
catch (error) {
|
|
218
|
+
// EPIPE / ECONNRESET / ERR_STREAM_DESTROYED: this connection is gone.
|
|
219
|
+
// Forget it so the next send does not reuse it, and report the failure.
|
|
220
|
+
log("tcp write failed", addr, error);
|
|
221
|
+
this.dropSocket(entry);
|
|
222
|
+
throw error;
|
|
223
|
+
}
|
|
178
224
|
}
|
|
179
225
|
async sendStun(message, addr) {
|
|
180
226
|
await this.sendFrame(message.bytes, addr);
|
|
@@ -191,7 +237,11 @@ class BaseTcpProtocol {
|
|
|
191
237
|
request.addFingerprint();
|
|
192
238
|
}
|
|
193
239
|
const resolvedAddr = await (0, transaction_1.resolveRequestAddress)(addr);
|
|
194
|
-
const options =
|
|
240
|
+
const options = {
|
|
241
|
+
// A failed connect/write will not be fixed by waiting for a response.
|
|
242
|
+
failOnSendError: true,
|
|
243
|
+
...(0, transaction_1.buildTransactionOptions)(integrityKey, retransmissionsOrOptions, onRequestSent),
|
|
244
|
+
};
|
|
195
245
|
const transaction = new transaction_1.Transaction(request, resolvedAddr, this, options);
|
|
196
246
|
this.transactions[request.transactionIdHex] = transaction;
|
|
197
247
|
try {
|
|
@@ -223,6 +273,7 @@ class BaseTcpProtocol {
|
|
|
223
273
|
await this.pruneForSelection();
|
|
224
274
|
this.onRequestReceived.complete();
|
|
225
275
|
this.onDataReceived.complete();
|
|
276
|
+
this.onConnectionClosed.complete();
|
|
226
277
|
}
|
|
227
278
|
}
|
|
228
279
|
Object.defineProperty(BaseTcpProtocol, "type", {
|
|
@@ -246,7 +297,7 @@ class TcpActiveProtocol extends BaseTcpProtocol {
|
|
|
246
297
|
}
|
|
247
298
|
async getSocket(addr) {
|
|
248
299
|
const key = socketKey(addr);
|
|
249
|
-
const existing = this.
|
|
300
|
+
const existing = this.getOpenSocket(addr);
|
|
250
301
|
if (existing) {
|
|
251
302
|
return existing;
|
|
252
303
|
}
|
|
@@ -312,7 +363,7 @@ class TcpPassiveProtocol extends BaseTcpProtocol {
|
|
|
312
363
|
await waitForListening(this.server, localIp);
|
|
313
364
|
}
|
|
314
365
|
async getSocket(addr) {
|
|
315
|
-
const entry = this.
|
|
366
|
+
const entry = this.getOpenSocket(addr);
|
|
316
367
|
if (!entry) {
|
|
317
368
|
throw new Error("tcp passive connection not established");
|
|
318
369
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"tcpProtocol.js","sourceRoot":"","sources":["../../../../../ice/src/stun/tcpProtocol.ts"],"names":[],"mappings":";;;AAAA,uCAAgF;AAGhF,8CAA+D;AAE/D,mCAAkC;AAClC,uCAAuD;AACvD,yCAA4D;AAC5D,+CAIuB;AAEvB,MAAM,GAAG,GAAG,IAAA,cAAK,EAAC,iDAAiD,CAAC,CAAC;AAQrE,SAAS,SAAS,CAAC,IAAa;IAC9B,OAAO,GAAG,IAAI,CAAC,CAAC,CAAC,IAAI,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC;AACjC,CAAC;AAED,SAAS,iBAAiB,CAAC,MAAc;IACvC,IAAI,CAAC,MAAM,CAAC,aAAa,IAAI,CAAC,MAAM,CAAC,UAAU,EAAE,CAAC;QAChD,OAAO;IACT,CAAC;IACD,OAAO,CAAC,MAAM,CAAC,aAAa,EAAE,MAAM,CAAC,UAAU,CAAY,CAAC;AAC9D,CAAC;AAED,KAAK,UAAU,gBAAgB,CAC7B,MAAuC,EACvC,IAAY,EACZ,IAAa;IAEb,OAAO,MAAM,IAAI,OAAO,CAAO,CAAC,OAAO,EAAE,MAAM,EAAE,EAAE;QACjD,MAAM,OAAO,GAAG,CAAC,KAAY,EAAE,EAAE;YAC/B,MAAM,CAAC,GAAG,CAAC,WAAW,EAAE,WAAW,CAAC,CAAC;YACrC,MAAM,CAAC,KAAK,CAAC,CAAC;QAChB,CAAC,CAAC;QACF,MAAM,WAAW,GAAG,GAAG,EAAE;YACvB,MAAM,CAAC,GAAG,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC;YAC7B,OAAO,EAAE,CAAC;QACZ,CAAC,CAAC;QAEF,MAAM,CAAC,IAAI,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC;QAC9B,MAAM,CAAC,IAAI,CAAC,WAAW,EAAE,WAAW,CAAC,CAAC;QACtC,MAAM,CAAC,MAAM,CAAC;YACZ,IAAI;YACJ,IAAI,EAAE,IAAI,IAAI,CAAC;YACf,SAAS,EAAE,IAAI;SAChB,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;AACL,CAAC;AAED,MAAe,eAAe;IAA9B;QAEW;;;;mBAAO,eAAe,CAAC,IAAI;WAAC;QACrC;;;;mBAA+C,EAAE;WAAC;QAClD;;;;;WAA2B;QAC3B;;;;;WAAsB;QACtB;;;;;WAAiB;QAER;;;;mBAAoB,IAAI,cAAK,EAA8B;WAAC;QAC5D;;;;mBAAiB,IAAI,cAAK,EAAY;WAAC;QAE7B;;;;mBAAU,IAAI,GAAG,EAAuB;WAAC;IA6K9D,CAAC;IAxKW,cAAc,CAAC,KAAkB;QACzC,MAAM,UAAU,GAAG,KAAK,CAAC,UAAU,CAAC;QACpC,IAAI,CAAC,UAAU,EAAE,CAAC;YAChB,OAAO;QACT,CAAC;QAED,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,SAAS,CAAC,UAAU,CAAC,EAAE,KAAK,CAAC,CAAC;IACjD,CAAC;IAES,YAAY,CAAC,UAAoB;QACzC,IAAI,CAAC,UAAU,EAAE,CAAC;YAChB,OAAO;QACT,CAAC;QACD,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC,SAAS,CAAC,UAAU,CAAC,CAAC,CAAC;IAC7C,CAAC;IAES,cAAc,CAAC,MAAc,EAAE,UAAoB;QAC3D,MAAM,KAAK,GAAgB;YACzB,MAAM;YACN,MAAM,EAAE,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC;YACvB,UAAU;SACX,CAAC;QAEF,IAAI,UAAU,EAAE,CAAC;YACf,IAAI,CAAC,cAAc,CAAC,KAAK,CAAC,CAAC;QAC7B,CAAC;QAED,MAAM,CAAC,EAAE,CAAC,MAAM,EAAE,CAAC,IAAI,EAAE,EAAE;YACzB,KAAK,CAAC,MAAM,GAAG,MAAM,CAAC,MAAM,CAAC,CAAC,KAAK,CAAC,MAAM,EAAE,IAAI,CAAC,CAAC,CAAC;YACnD,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE,GAAG,IAAA,yBAAc,EAAC,KAAK,CAAC,MAAM,CAAC,CAAC;YACtD,KAAK,CAAC,MAAM,GAAG,IAAI,CAAC;YAEpB,MAAM,UAAU,GAAG,KAAK,CAAC,UAAU,IAAI,iBAAiB,CAAC,MAAM,CAAC,CAAC;YACjE,IAAI,CAAC,KAAK,CAAC,UAAU,IAAI,UAAU,EAAE,CAAC;gBACpC,KAAK,CAAC,UAAU,GAAG,UAAU,CAAC;gBAC9B,IAAI,CAAC,cAAc,CAAC,KAAK,CAAC,CAAC;YAC7B,CAAC;YACD,IAAI,CAAC,UAAU,EAAE,CAAC;gBAChB,OAAO;YACT,CAAC;YAED,KAAK,MAAM,KAAK,IAAI,MAAM,EAAE,CAAC;gBAC3B,IAAI,KAAK,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;oBACvB,SAAS;gBACX,CAAC;gBACD,IAAI,CAAC,WAAW,CAAC,KAAK,EAAE,UAAU,CAAC,CAAC;YACtC,CAAC;QACH,CAAC,CAAC,CAAC;QACH,MAAM,CAAC,EAAE,CAAC,OAAO,EAAE,GAAG,EAAE;YACtB,IAAI,CAAC,YAAY,CAAC,KAAK,CAAC,UAAU,CAAC,CAAC;QACtC,CAAC,CAAC,CAAC;QACH,MAAM,CAAC,EAAE,CAAC,OAAO,EAAE,CAAC,KAAK,EAAE,EAAE;YAC3B,GAAG,CAAC,kBAAkB,EAAE,KAAK,CAAC,CAAC;QACjC,CAAC,CAAC,CAAC;QAEH,OAAO,KAAK,CAAC;IACf,CAAC;IAEO,WAAW,CAAC,IAAY,EAAE,IAAa;QAC7C,IAAI,CAAC;YACH,MAAM,OAAO,GAAG,IAAA,sBAAY,EAAC,IAAI,CAAC,CAAC;YACnC,IAAI,CAAC,OAAO,EAAE,CAAC;gBACb,IAAI,CAAC,cAAc,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC;gBAClC,OAAO;YACT,CAAC;YAED,IACE,CAAC,OAAO,CAAC,YAAY,KAAK,eAAO,CAAC,QAAQ;gBACxC,OAAO,CAAC,YAAY,KAAK,eAAO,CAAC,KAAK,CAAC;gBACzC,IAAI,CAAC,YAAY,CAAC,OAAO,CAAC,gBAAgB,CAAC,EAC3C,CAAC;gBACD,MAAM,WAAW,GAAG,IAAI,CAAC,YAAY,CAAC,OAAO,CAAC,gBAAgB,CAAC,CAAC;gBAChE,MAAM,QAAQ,GAAG,WAAW,CAAC,YAAY;oBACvC,CAAC,CAAC,IAAA,sBAAY,EAAC,IAAI,EAAE,WAAW,CAAC,YAAY,CAAC;oBAC9C,CAAC,CAAC,OAAO,CAAC;gBACZ,IAAI,CAAC,QAAQ,EAAE,CAAC;oBACd,GAAG,CAAC,8CAA8C,CAAC,CAAC;oBACpD,OAAO;gBACT,CAAC;gBACD,WAAW,CAAC,gBAAgB,CAAC,QAAQ,EAAE,IAAI,CAAC,CAAC;YAC/C,CAAC;iBAAM,IAAI,OAAO,CAAC,YAAY,KAAK,eAAO,CAAC,OAAO,EAAE,CAAC;gBACpD,IAAI,CAAC,iBAAiB,CAAC,OAAO,CAAC,OAAO,EAAE,IAAI,EAAE,IAAI,CAAC,CAAC;YACtD,CAAC;QACH,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,GAAG,CAAC,uBAAuB,EAAE,KAAK,CAAC,CAAC;QACtC,CAAC;IACH,CAAC;IAEO,KAAK,CAAC,SAAS,CAAC,IAAY,EAAE,IAAa;QACjD,MAAM,KAAK,GAAG,MAAM,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,CAAC;QACzC,MAAM,IAAI,OAAO,CAAO,CAAC,OAAO,EAAE,MAAM,EAAE,EAAE;YAC1C,KAAK,CAAC,MAAM,CAAC,KAAK,CAAC,IAAA,yBAAc,EAAC,IAAI,CAAC,EAAE,CAAC,KAAK,EAAE,EAAE;gBACjD,IAAI,KAAK,EAAE,CAAC;oBACV,MAAM,CAAC,KAAK,CAAC,CAAC;oBACd,OAAO;gBACT,CAAC;gBACD,OAAO,EAAE,CAAC;YACZ,CAAC,CAAC,CAAC;QACL,CAAC,CAAC,CAAC;IACL,CAAC;IAED,KAAK,CAAC,QAAQ,CAAC,OAAgB,EAAE,IAAa;QAC5C,MAAM,IAAI,CAAC,SAAS,CAAC,OAAO,CAAC,KAAK,EAAE,IAAI,CAAC,CAAC;IAC5C,CAAC;IAED,KAAK,CAAC,QAAQ,CAAC,IAAY,EAAE,IAAa;QACxC,MAAM,IAAI,CAAC,SAAS,CAAC,IAAI,EAAE,IAAI,CAAC,CAAC;IACnC,CAAC;IAED,KAAK,CAAC,OAAO,CACX,OAAgB,EAChB,IAAa,EACb,YAAqB,EACrB,wBAA6D,EAC7D,aAAyC;QAEzC,IAAI,IAAI,CAAC,YAAY,CAAC,OAAO,CAAC,gBAAgB,CAAC,EAAE,CAAC;YAChD,MAAM,IAAI,KAAK,CAAC,mBAAmB,CAAC,CAAC;QACvC,CAAC;QAED,IAAI,YAAY,EAAE,CAAC;YACjB,OAAO,CAAC,mBAAmB,CAAC,YAAY,CAAC,CAAC;YAC1C,OAAO,CAAC,cAAc,EAAE,CAAC;QAC3B,CAAC;QAED,MAAM,YAAY,GAAG,MAAM,IAAA,mCAAqB,EAAC,IAAI,CAAC,CAAC;QACvD,MAAM,OAAO,GAAG,IAAA,qCAAuB,EACrC,YAAY,EACZ,wBAAwB,EACxB,aAAa,CACd,CAAC;QACF,MAAM,WAAW,GAAG,IAAI,yBAAW,CAAC,OAAO,EAAE,YAAY,EAAE,IAAI,EAAE,OAAO,CAAC,CAAC;QAC1E,IAAI,CAAC,YAAY,CAAC,OAAO,CAAC,gBAAgB,CAAC,GAAG,WAAW,CAAC;QAE1D,IAAI,CAAC;YACH,OAAO,MAAM,WAAW,CAAC,GAAG,EAAE,CAAC;QACjC,CAAC;gBAAS,CAAC;YACT,OAAO,IAAI,CAAC,YAAY,CAAC,OAAO,CAAC,gBAAgB,CAAC,CAAC;QACrD,CAAC;IACH,CAAC;IAED,KAAK,CAAC,iBAAiB,CAAC,UAAoB;QAC1C,KAAK,MAAM,CAAC,GAAG,EAAE,KAAK,CAAC,IAAI,IAAI,CAAC,OAAO,CAAC,OAAO,EAAE,EAAE,CAAC;YAClD,IAAI,UAAU,IAAI,GAAG,KAAK,SAAS,CAAC,UAAU,CAAC,EAAE,CAAC;gBAChD,SAAS;YACX,CAAC;YACD,KAAK,CAAC,MAAM,CAAC,OAAO,EAAE,CAAC;YACvB,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;QAC3B,CAAC;IACH,CAAC;IAED,IAAI,iBAAiB;QACnB,OAAO,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC;IAC3B,CAAC;IAED,IAAI,OAAO;QACT,OAAO,EAAiB,CAAC;IAC3B,CAAC;IAED,KAAK,CAAC,KAAK;QACT,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC,YAAY,CAAC,CAAC,OAAO,CAAC,CAAC,WAAW,EAAE,EAAE;YACvD,WAAW,CAAC,MAAM,EAAE,CAAC;QACvB,CAAC,CAAC,CAAC;QAEH,MAAM,IAAI,CAAC,iBAAiB,EAAE,CAAC;QAC/B,IAAI,CAAC,iBAAiB,CAAC,QAAQ,EAAE,CAAC;QAClC,IAAI,CAAC,cAAc,CAAC,QAAQ,EAAE,CAAC;IACjC,CAAC;;AAtLe;;;;WAAO,KAAK;EAAR,CAAS;AAyL/B,MAAa,iBAAkB,SAAQ,eAAe;IAAtD;;QACmB;;;;mBAAiB,IAAI,GAAG,EAAgC;WAAC;IA+C5E,CAAC;IA7CC,KAAK,CAAC,cAAc,CAAC,OAAe;QAClC,IAAI,CAAC,OAAO,GAAG,OAAO,CAAC;IACzB,CAAC;IAES,KAAK,CAAC,SAAS,CAAC,IAAa;QACrC,MAAM,GAAG,GAAG,SAAS,CAAC,IAAI,CAAC,CAAC;QAC5B,MAAM,QAAQ,GAAG,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;QACvC,IAAI,QAAQ,EAAE,CAAC;YACb,OAAO,QAAQ,CAAC;QAClB,CAAC;QAED,MAAM,OAAO,GAAG,IAAI,CAAC,cAAc,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;QAC7C,IAAI,OAAO,EAAE,CAAC;YACZ,OAAO,MAAM,OAAO,CAAC;QACvB,CAAC;QAED,MAAM,UAAU,GAAG,IAAI,OAAO,CAAc,CAAC,OAAO,EAAE,MAAM,EAAE,EAAE;YAC9D,MAAM,MAAM,GAAG,IAAA,kBAAO,EAAC;gBACrB,IAAI,EAAE,IAAI,CAAC,CAAC,CAAC;gBACb,IAAI,EAAE,IAAI,CAAC,CAAC,CAAC;gBACb,YAAY,EAAE,IAAI,CAAC,OAAO;aAC3B,CAAC,CAAC;YACH,MAAM,KAAK,GAAG,IAAI,CAAC,cAAc,CAAC,MAAM,EAAE,IAAI,CAAC,CAAC;YAEhD,MAAM,OAAO,GAAG,CAAC,KAAY,EAAE,EAAE;gBAC/B,MAAM,CAAC,GAAG,CAAC,SAAS,EAAE,SAAS,CAAC,CAAC;gBACjC,MAAM,CAAC,KAAK,CAAC,CAAC;YAChB,CAAC,CAAC;YACF,MAAM,SAAS,GAAG,GAAG,EAAE;gBACrB,MAAM,CAAC,GAAG,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC;gBAC7B,OAAO,CAAC,KAAK,CAAC,CAAC;YACjB,CAAC,CAAC;YAEF,MAAM,CAAC,IAAI,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC;YAC9B,MAAM,CAAC,IAAI,CAAC,SAAS,EAAE,SAAS,CAAC,CAAC;QACpC,CAAC,CAAC,CAAC;QAEH,IAAI,CAAC,cAAc,CAAC,GAAG,CAAC,GAAG,EAAE,UAAU,CAAC,CAAC;QAEzC,IAAI,CAAC;YACH,OAAO,MAAM,UAAU,CAAC;QAC1B,CAAC;gBAAS,CAAC;YACT,IAAI,CAAC,cAAc,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;QAClC,CAAC;IACH,CAAC;CACF;AAhDD,8CAgDC;AAED,MAAa,kBAAmB,SAAQ,eAAe;IAAvD;;QACU;;;;mBAAS,IAAA,uBAAY,EAAC,CAAC,MAAM,EAAE,EAAE;gBACvC,IAAI,CAAC,cAAc,CAAC,MAAM,EAAE,iBAAiB,CAAC,MAAM,CAAC,CAAC,CAAC;YACzD,CAAC,CAAC;WAAC;IA2CL,CAAC;IAzCC,KAAK,CAAC,cAAc,CAAC,OAAe,EAAE,SAA4B;QAChE,IAAI,CAAC,OAAO,GAAG,OAAO,CAAC;QAEvB,IAAI,SAAS,EAAE,CAAC;YACd,IAAI,SAA4B,CAAC;YACjC,KAAK,IAAI,IAAI,GAAG,SAAS,CAAC,CAAC,CAAC,EAAE,IAAI,IAAI,SAAS,CAAC,CAAC,CAAC,EAAE,IAAI,EAAE,EAAE,CAAC;gBAC3D,IAAI,CAAC;oBACH,MAAM,gBAAgB,CAAC,IAAI,CAAC,MAAM,EAAE,OAAO,EAAE,IAAI,CAAC,CAAC;oBACnD,OAAO;gBACT,CAAC;gBAAC,OAAO,KAAK,EAAE,CAAC;oBACf,SAAS,GAAG,KAAc,CAAC;gBAC7B,CAAC;YACH,CAAC;YACD,MAAM,SAAS,IAAI,IAAI,KAAK,CAAC,oBAAoB,CAAC,CAAC;QACrD,CAAC;QAED,MAAM,gBAAgB,CAAC,IAAI,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAC/C,CAAC;IAES,KAAK,CAAC,SAAS,CAAC,IAAa;QACrC,MAAM,KAAK,GAAG,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,SAAS,CAAC,IAAI,CAAC,CAAC,CAAC;QAChD,IAAI,CAAC,KAAK,EAAE,CAAC;YACX,MAAM,IAAI,KAAK,CAAC,wCAAwC,CAAC,CAAC;QAC5D,CAAC;QACD,OAAO,KAAK,CAAC;IACf,CAAC;IAED,IAAI,aAAa;QACf,MAAM,OAAO,GAAG,IAAI,CAAC,MAAM,CAAC,OAAO,EAAE,CAAC;QACtC,IAAI,CAAC,OAAO,IAAI,OAAO,OAAO,KAAK,QAAQ,EAAE,CAAC;YAC5C,MAAM,IAAI,KAAK,CAAC,uCAAuC,CAAC,CAAC;QAC3D,CAAC;QACD,OAAO,OAAO,CAAC,IAAI,CAAC;IACtB,CAAC;IAEQ,KAAK,CAAC,KAAK;QAClB,MAAM,KAAK,CAAC,KAAK,EAAE,CAAC;QACpB,MAAM,IAAI,OAAO,CAAO,CAAC,OAAO,EAAE,EAAE;YAClC,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC,OAAO,EAAE,CAAC,CAAC;QACrC,CAAC,CAAC,CAAC;IACL,CAAC;CACF;AA9CD,gDA8CC","sourcesContent":["import { type AddressInfo, type Socket, connect, createServer } from \"node:net\";\n\nimport type { Candidate } from \"../candidate\";\nimport { type Address, Event, debug } from \"../imports/common\";\nimport type { Protocol, TransactionRequestOptions } from \"../types/model\";\nimport { classes } from \"./const\";\nimport { type Message, parseMessage } from \"./message\";\nimport { encodeTcpFrame, splitTcpFrames } from \"./tcpFrame\";\nimport {\n Transaction,\n buildTransactionOptions,\n resolveRequestAddress,\n} from \"./transaction\";\n\nconst log = debug(\"werift-ice:packages/ice/src/stun/tcpProtocol.ts\");\n\ntype SocketEntry = {\n socket: Socket;\n buffer: Buffer;\n remoteAddr?: Address;\n};\n\nfunction socketKey(addr: Address) {\n return `${addr[0]}:${addr[1]}`;\n}\n\nfunction addressFromSocket(socket: Socket) {\n if (!socket.remoteAddress || !socket.remotePort) {\n return;\n }\n return [socket.remoteAddress, socket.remotePort] as Address;\n}\n\nasync function waitForListening(\n server: ReturnType<typeof createServer>,\n host: string,\n port?: number,\n) {\n return await new Promise<void>((resolve, reject) => {\n const onError = (error: Error) => {\n server.off(\"listening\", onListening);\n reject(error);\n };\n const onListening = () => {\n server.off(\"error\", onError);\n resolve();\n };\n\n server.once(\"error\", onError);\n server.once(\"listening\", onListening);\n server.listen({\n host,\n port: port ?? 0,\n exclusive: true,\n });\n });\n}\n\nabstract class BaseTcpProtocol implements Protocol {\n static readonly type = \"tcp\";\n readonly type = BaseTcpProtocol.type;\n transactions: { [key: string]: Transaction } = {};\n localCandidate?: Candidate;\n sentMessage?: Message;\n localIp?: string;\n\n readonly onRequestReceived = new Event<[Message, Address, Buffer]>();\n readonly onDataReceived = new Event<[Buffer]>();\n\n protected readonly sockets = new Map<string, SocketEntry>();\n\n abstract connectionMade(...args: any[]): Promise<void>;\n protected abstract getSocket(addr: Address): Promise<SocketEntry>;\n\n protected rememberSocket(entry: SocketEntry) {\n const remoteAddr = entry.remoteAddr;\n if (!remoteAddr) {\n return;\n }\n\n this.sockets.set(socketKey(remoteAddr), entry);\n }\n\n protected forgetSocket(remoteAddr?: Address) {\n if (!remoteAddr) {\n return;\n }\n this.sockets.delete(socketKey(remoteAddr));\n }\n\n protected registerSocket(socket: Socket, remoteAddr?: Address) {\n const entry: SocketEntry = {\n socket,\n buffer: Buffer.alloc(0),\n remoteAddr,\n };\n\n if (remoteAddr) {\n this.rememberSocket(entry);\n }\n\n socket.on(\"data\", (data) => {\n entry.buffer = Buffer.concat([entry.buffer, data]);\n const { frames, rest } = splitTcpFrames(entry.buffer);\n entry.buffer = rest;\n\n const socketAddr = entry.remoteAddr ?? addressFromSocket(socket);\n if (!entry.remoteAddr && socketAddr) {\n entry.remoteAddr = socketAddr;\n this.rememberSocket(entry);\n }\n if (!socketAddr) {\n return;\n }\n\n for (const frame of frames) {\n if (frame.length === 0) {\n continue;\n }\n this.handleFrame(frame, socketAddr);\n }\n });\n socket.on(\"close\", () => {\n this.forgetSocket(entry.remoteAddr);\n });\n socket.on(\"error\", (error) => {\n log(\"tcp socket error\", error);\n });\n\n return entry;\n }\n\n private handleFrame(data: Buffer, addr: Address) {\n try {\n const message = parseMessage(data);\n if (!message) {\n this.onDataReceived.execute(data);\n return;\n }\n\n if (\n (message.messageClass === classes.RESPONSE ||\n message.messageClass === classes.ERROR) &&\n this.transactions[message.transactionIdHex]\n ) {\n const transaction = this.transactions[message.transactionIdHex];\n const verified = transaction.integrityKey\n ? parseMessage(data, transaction.integrityKey)\n : message;\n if (!verified) {\n log(\"STUN response failed MESSAGE-INTEGRITY check\");\n return;\n }\n transaction.responseReceived(verified, addr);\n } else if (message.messageClass === classes.REQUEST) {\n this.onRequestReceived.execute(message, addr, data);\n }\n } catch (error) {\n log(\"tcp frame parse error\", error);\n }\n }\n\n private async sendFrame(data: Buffer, addr: Address) {\n const entry = await this.getSocket(addr);\n await new Promise<void>((resolve, reject) => {\n entry.socket.write(encodeTcpFrame(data), (error) => {\n if (error) {\n reject(error);\n return;\n }\n resolve();\n });\n });\n }\n\n async sendStun(message: Message, addr: Address) {\n await this.sendFrame(message.bytes, addr);\n }\n\n async sendData(data: Buffer, addr: Address) {\n await this.sendFrame(data, addr);\n }\n\n async request(\n request: Message,\n addr: Address,\n integrityKey?: Buffer,\n retransmissionsOrOptions?: number | TransactionRequestOptions,\n onRequestSent?: (attempt: number) => void,\n ) {\n if (this.transactions[request.transactionIdHex]) {\n throw new Error(\"already requested\");\n }\n\n if (integrityKey) {\n request.addMessageIntegrity(integrityKey);\n request.addFingerprint();\n }\n\n const resolvedAddr = await resolveRequestAddress(addr);\n const options = buildTransactionOptions(\n integrityKey,\n retransmissionsOrOptions,\n onRequestSent,\n );\n const transaction = new Transaction(request, resolvedAddr, this, options);\n this.transactions[request.transactionIdHex] = transaction;\n\n try {\n return await transaction.run();\n } finally {\n delete this.transactions[request.transactionIdHex];\n }\n }\n\n async pruneForSelection(remoteAddr?: Address) {\n for (const [key, entry] of this.sockets.entries()) {\n if (remoteAddr && key === socketKey(remoteAddr)) {\n continue;\n }\n entry.socket.destroy();\n this.sockets.delete(key);\n }\n }\n\n get activeSocketCount() {\n return this.sockets.size;\n }\n\n get address() {\n return {} as AddressInfo;\n }\n\n async close() {\n Object.values(this.transactions).forEach((transaction) => {\n transaction.cancel();\n });\n\n await this.pruneForSelection();\n this.onRequestReceived.complete();\n this.onDataReceived.complete();\n }\n}\n\nexport class TcpActiveProtocol extends BaseTcpProtocol {\n private readonly pendingSockets = new Map<string, Promise<SocketEntry>>();\n\n async connectionMade(localIp: string) {\n this.localIp = localIp;\n }\n\n protected async getSocket(addr: Address) {\n const key = socketKey(addr);\n const existing = this.sockets.get(key);\n if (existing) {\n return existing;\n }\n\n const pending = this.pendingSockets.get(key);\n if (pending) {\n return await pending;\n }\n\n const connecting = new Promise<SocketEntry>((resolve, reject) => {\n const socket = connect({\n host: addr[0],\n port: addr[1],\n localAddress: this.localIp,\n });\n const entry = this.registerSocket(socket, addr);\n\n const onError = (error: Error) => {\n socket.off(\"connect\", onConnect);\n reject(error);\n };\n const onConnect = () => {\n socket.off(\"error\", onError);\n resolve(entry);\n };\n\n socket.once(\"error\", onError);\n socket.once(\"connect\", onConnect);\n });\n\n this.pendingSockets.set(key, connecting);\n\n try {\n return await connecting;\n } finally {\n this.pendingSockets.delete(key);\n }\n }\n}\n\nexport class TcpPassiveProtocol extends BaseTcpProtocol {\n private server = createServer((socket) => {\n this.registerSocket(socket, addressFromSocket(socket));\n });\n\n async connectionMade(localIp: string, portRange?: [number, number]) {\n this.localIp = localIp;\n\n if (portRange) {\n let lastError: Error | undefined;\n for (let port = portRange[0]; port <= portRange[1]; port++) {\n try {\n await waitForListening(this.server, localIp, port);\n return;\n } catch (error) {\n lastError = error as Error;\n }\n }\n throw lastError ?? new Error(\"tcp port not found\");\n }\n\n await waitForListening(this.server, localIp);\n }\n\n protected async getSocket(addr: Address) {\n const entry = this.sockets.get(socketKey(addr));\n if (!entry) {\n throw new Error(\"tcp passive connection not established\");\n }\n return entry;\n }\n\n get listeningPort() {\n const address = this.server.address();\n if (!address || typeof address === \"string\") {\n throw new Error(\"tcp passive protocol is not listening\");\n }\n return address.port;\n }\n\n override async close() {\n await super.close();\n await new Promise<void>((resolve) => {\n this.server.close(() => resolve());\n });\n }\n}\n"]}
|
|
1
|
+
{"version":3,"file":"tcpProtocol.js","sourceRoot":"","sources":["../../../../../ice/src/stun/tcpProtocol.ts"],"names":[],"mappings":"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","sourcesContent":["import { type AddressInfo, type Socket, connect, createServer } from \"node:net\";\n\nimport type { Candidate } from \"../candidate\";\nimport { type Address, Event, debug } from \"../imports/common\";\nimport type { Protocol, TransactionRequestOptions } from \"../types/model\";\nimport { classes } from \"./const\";\nimport { type Message, parseMessage } from \"./message\";\nimport { encodeTcpFrame, splitTcpFrames } from \"./tcpFrame\";\nimport {\n Transaction,\n buildTransactionOptions,\n resolveRequestAddress,\n} from \"./transaction\";\n\nconst log = debug(\"werift-ice:packages/ice/src/stun/tcpProtocol.ts\");\n\ntype SocketEntry = {\n socket: Socket;\n buffer: Buffer;\n remoteAddr?: Address;\n};\n\nfunction socketKey(addr: Address) {\n return `${addr[0]}:${addr[1]}`;\n}\n\nfunction isSocketClosed(socket: Socket) {\n return socket.destroyed || socket.writableEnded;\n}\n\nfunction addressFromSocket(socket: Socket) {\n if (!socket.remoteAddress || !socket.remotePort) {\n return;\n }\n return [socket.remoteAddress, socket.remotePort] as Address;\n}\n\nasync function waitForListening(\n server: ReturnType<typeof createServer>,\n host: string,\n port?: number,\n) {\n return await new Promise<void>((resolve, reject) => {\n const onError = (error: Error) => {\n server.off(\"listening\", onListening);\n reject(error);\n };\n const onListening = () => {\n server.off(\"error\", onError);\n resolve();\n };\n\n server.once(\"error\", onError);\n server.once(\"listening\", onListening);\n server.listen({\n host,\n port: port ?? 0,\n exclusive: true,\n });\n });\n}\n\nabstract class BaseTcpProtocol implements Protocol {\n static readonly type = \"tcp\";\n readonly type = BaseTcpProtocol.type;\n transactions: { [key: string]: Transaction } = {};\n localCandidate?: Candidate;\n sentMessage?: Message;\n localIp?: string;\n\n readonly onRequestReceived = new Event<[Message, Address, Buffer]>();\n readonly onDataReceived = new Event<[Buffer]>();\n /** The connection to this remote address was closed (by either side). */\n readonly onConnectionClosed = new Event<[Address]>();\n\n protected readonly sockets = new Map<string, SocketEntry>();\n\n abstract connectionMade(...args: any[]): Promise<void>;\n protected abstract getSocket(addr: Address): Promise<SocketEntry>;\n\n protected rememberSocket(entry: SocketEntry) {\n const remoteAddr = entry.remoteAddr;\n if (!remoteAddr) {\n return;\n }\n\n this.sockets.set(socketKey(remoteAddr), entry);\n }\n\n /** Drop `entry` only if it is still the socket registered for its address. */\n protected forgetSocket(entry: SocketEntry) {\n const remoteAddr = entry.remoteAddr;\n if (!remoteAddr) {\n return false;\n }\n const key = socketKey(remoteAddr);\n if (this.sockets.get(key) !== entry) {\n return false;\n }\n this.sockets.delete(key);\n return true;\n }\n\n /** Registered socket for `addr`, discarding it if it is already closed. */\n protected getOpenSocket(addr: Address) {\n const entry = this.sockets.get(socketKey(addr));\n if (!entry) {\n return;\n }\n if (isSocketClosed(entry.socket)) {\n this.dropSocket(entry);\n return;\n }\n return entry;\n }\n\n private dropSocket(entry: SocketEntry) {\n entry.socket.destroy();\n if (this.forgetSocket(entry) && entry.remoteAddr) {\n this.onConnectionClosed.execute(entry.remoteAddr);\n }\n }\n\n protected registerSocket(socket: Socket, remoteAddr?: Address) {\n const entry: SocketEntry = {\n socket,\n buffer: Buffer.alloc(0),\n remoteAddr,\n };\n\n if (remoteAddr) {\n this.rememberSocket(entry);\n }\n\n socket.on(\"data\", (data) => {\n entry.buffer = Buffer.concat([entry.buffer, data]);\n const { frames, rest } = splitTcpFrames(entry.buffer);\n entry.buffer = rest;\n\n const socketAddr = entry.remoteAddr ?? addressFromSocket(socket);\n if (!entry.remoteAddr && socketAddr) {\n entry.remoteAddr = socketAddr;\n this.rememberSocket(entry);\n }\n if (!socketAddr) {\n return;\n }\n\n for (const frame of frames) {\n if (frame.length === 0) {\n continue;\n }\n this.handleFrame(frame, socketAddr);\n }\n });\n socket.on(\"close\", () => {\n if (this.forgetSocket(entry) && entry.remoteAddr) {\n this.onConnectionClosed.execute(entry.remoteAddr);\n }\n });\n socket.on(\"error\", (error) => {\n log(\"tcp socket error\", error);\n });\n\n return entry;\n }\n\n private handleFrame(data: Buffer, addr: Address) {\n try {\n const message = parseMessage(data);\n if (!message) {\n this.onDataReceived.execute(data);\n return;\n }\n\n if (\n (message.messageClass === classes.RESPONSE ||\n message.messageClass === classes.ERROR) &&\n this.transactions[message.transactionIdHex]\n ) {\n const transaction = this.transactions[message.transactionIdHex];\n const verified = transaction.integrityKey\n ? parseMessage(data, transaction.integrityKey)\n : message;\n if (!verified) {\n log(\"STUN response failed MESSAGE-INTEGRITY check\");\n return;\n }\n transaction.responseReceived(verified, addr);\n } else if (message.messageClass === classes.REQUEST) {\n this.onRequestReceived.execute(message, addr, data);\n }\n } catch (error) {\n log(\"tcp frame parse error\", error);\n }\n }\n\n private async sendFrame(data: Buffer, addr: Address) {\n const entry = await this.getSocket(addr);\n try {\n await new Promise<void>((resolve, reject) => {\n entry.socket.write(encodeTcpFrame(data), (error) => {\n if (error) {\n reject(error);\n return;\n }\n resolve();\n });\n });\n } catch (error) {\n // EPIPE / ECONNRESET / ERR_STREAM_DESTROYED: this connection is gone.\n // Forget it so the next send does not reuse it, and report the failure.\n log(\"tcp write failed\", addr, error);\n this.dropSocket(entry);\n throw error;\n }\n }\n\n async sendStun(message: Message, addr: Address) {\n await this.sendFrame(message.bytes, addr);\n }\n\n async sendData(data: Buffer, addr: Address) {\n await this.sendFrame(data, addr);\n }\n\n async request(\n request: Message,\n addr: Address,\n integrityKey?: Buffer,\n retransmissionsOrOptions?: number | TransactionRequestOptions,\n onRequestSent?: (attempt: number) => void,\n ) {\n if (this.transactions[request.transactionIdHex]) {\n throw new Error(\"already requested\");\n }\n\n if (integrityKey) {\n request.addMessageIntegrity(integrityKey);\n request.addFingerprint();\n }\n\n const resolvedAddr = await resolveRequestAddress(addr);\n const options: TransactionRequestOptions = {\n // A failed connect/write will not be fixed by waiting for a response.\n failOnSendError: true,\n ...buildTransactionOptions(\n integrityKey,\n retransmissionsOrOptions,\n onRequestSent,\n ),\n };\n const transaction = new Transaction(request, resolvedAddr, this, options);\n this.transactions[request.transactionIdHex] = transaction;\n\n try {\n return await transaction.run();\n } finally {\n delete this.transactions[request.transactionIdHex];\n }\n }\n\n async pruneForSelection(remoteAddr?: Address) {\n for (const [key, entry] of this.sockets.entries()) {\n if (remoteAddr && key === socketKey(remoteAddr)) {\n continue;\n }\n entry.socket.destroy();\n this.sockets.delete(key);\n }\n }\n\n get activeSocketCount() {\n return this.sockets.size;\n }\n\n get address() {\n return {} as AddressInfo;\n }\n\n async close() {\n Object.values(this.transactions).forEach((transaction) => {\n transaction.cancel();\n });\n\n await this.pruneForSelection();\n this.onRequestReceived.complete();\n this.onDataReceived.complete();\n this.onConnectionClosed.complete();\n }\n}\n\nexport class TcpActiveProtocol extends BaseTcpProtocol {\n private readonly pendingSockets = new Map<string, Promise<SocketEntry>>();\n\n async connectionMade(localIp: string) {\n this.localIp = localIp;\n }\n\n protected async getSocket(addr: Address) {\n const key = socketKey(addr);\n const existing = this.getOpenSocket(addr);\n if (existing) {\n return existing;\n }\n\n const pending = this.pendingSockets.get(key);\n if (pending) {\n return await pending;\n }\n\n const connecting = new Promise<SocketEntry>((resolve, reject) => {\n const socket = connect({\n host: addr[0],\n port: addr[1],\n localAddress: this.localIp,\n });\n const entry = this.registerSocket(socket, addr);\n\n const onError = (error: Error) => {\n socket.off(\"connect\", onConnect);\n reject(error);\n };\n const onConnect = () => {\n socket.off(\"error\", onError);\n resolve(entry);\n };\n\n socket.once(\"error\", onError);\n socket.once(\"connect\", onConnect);\n });\n\n this.pendingSockets.set(key, connecting);\n\n try {\n return await connecting;\n } finally {\n this.pendingSockets.delete(key);\n }\n }\n}\n\nexport class TcpPassiveProtocol extends BaseTcpProtocol {\n private server = createServer((socket) => {\n this.registerSocket(socket, addressFromSocket(socket));\n });\n\n async connectionMade(localIp: string, portRange?: [number, number]) {\n this.localIp = localIp;\n\n if (portRange) {\n let lastError: Error | undefined;\n for (let port = portRange[0]; port <= portRange[1]; port++) {\n try {\n await waitForListening(this.server, localIp, port);\n return;\n } catch (error) {\n lastError = error as Error;\n }\n }\n throw lastError ?? new Error(\"tcp port not found\");\n }\n\n await waitForListening(this.server, localIp);\n }\n\n protected async getSocket(addr: Address) {\n const entry = this.getOpenSocket(addr);\n if (!entry) {\n throw new Error(\"tcp passive connection not established\");\n }\n return entry;\n }\n\n get listeningPort() {\n const address = this.server.address();\n if (!address || typeof address === \"string\") {\n throw new Error(\"tcp passive protocol is not listening\");\n }\n return address.port;\n }\n\n override async close() {\n await super.close();\n await new Promise<void>((resolve) => {\n this.server.close(() => resolve());\n });\n }\n}\n"]}
|
|
@@ -4,6 +4,11 @@ import type { Message } from "./message";
|
|
|
4
4
|
/**
|
|
5
5
|
* Resolve a request target to a concrete IP before creating a Transaction so
|
|
6
6
|
* response source-address checks match the UDP peer address (hostname ≠ IP).
|
|
7
|
+
*
|
|
8
|
+
* `family` is the family of the socket that will carry the request: a
|
|
9
|
+
* hostname resolves only in that family, and an IP literal of the other
|
|
10
|
+
* family throws AddressFamilyMismatch instead of retransmitting into a send
|
|
11
|
+
* that cannot succeed. Family 0 means unknown: no preference, no check.
|
|
7
12
|
*/
|
|
8
13
|
export declare function resolveRequestAddress(addr: Address, family?: 0 | 4 | 6): Promise<Address>;
|
|
9
14
|
/**
|
|
@@ -11,7 +16,11 @@ export declare function resolveRequestAddress(addr: Address, family?: 0 | 4 | 6)
|
|
|
11
16
|
* Existing callers pass `(retransmissions?, onRequestSent?)`.
|
|
12
17
|
*/
|
|
13
18
|
export declare function normalizeTransactionOptions(retransmissionsOrOptions?: number | TransactionRequestOptions, onRequestSent?: (attempt: number) => void): TransactionRequestOptions;
|
|
14
|
-
/**
|
|
19
|
+
/**
|
|
20
|
+
* Compare ICE transport addresses (host, port).
|
|
21
|
+
* IPv6 literals are compared in canonical form because the socket reports
|
|
22
|
+
* `::1` even when the peer was configured as `0:0:0:0:0:0:0:1`.
|
|
23
|
+
*/
|
|
15
24
|
export declare function addressEquals(a: Address, b: Address): boolean;
|
|
16
25
|
export declare class Transaction {
|
|
17
26
|
private request;
|
|
@@ -24,6 +33,7 @@ export declare class Transaction {
|
|
|
24
33
|
private readonly onResponse;
|
|
25
34
|
private readonly onRequestSent?;
|
|
26
35
|
private readonly signal?;
|
|
36
|
+
private readonly failOnSendError;
|
|
27
37
|
/** Remote address this transaction was sent to; responses must match. */
|
|
28
38
|
readonly expectedAddr: Address;
|
|
29
39
|
/**
|
|
@@ -45,6 +55,7 @@ export declare class Transaction {
|
|
|
45
55
|
run: () => Promise<[Message, readonly [string, number]]>;
|
|
46
56
|
private attachAbortListener;
|
|
47
57
|
private failWithTimeout;
|
|
58
|
+
private fail;
|
|
48
59
|
private clearWait;
|
|
49
60
|
private wait;
|
|
50
61
|
private retry;
|
|
@@ -14,9 +14,18 @@ const log = (0, common_1.debug)("werift-ice:packages/ice/src/stun/transaction.ts
|
|
|
14
14
|
/**
|
|
15
15
|
* Resolve a request target to a concrete IP before creating a Transaction so
|
|
16
16
|
* response source-address checks match the UDP peer address (hostname ≠ IP).
|
|
17
|
+
*
|
|
18
|
+
* `family` is the family of the socket that will carry the request: a
|
|
19
|
+
* hostname resolves only in that family, and an IP literal of the other
|
|
20
|
+
* family throws AddressFamilyMismatch instead of retransmitting into a send
|
|
21
|
+
* that cannot succeed. Family 0 means unknown: no preference, no check.
|
|
17
22
|
*/
|
|
18
23
|
async function resolveRequestAddress(addr, family = 0) {
|
|
19
|
-
|
|
24
|
+
const literalFamily = (0, node_net_1.isIP)(addr[0]);
|
|
25
|
+
if (literalFamily) {
|
|
26
|
+
if (family !== 0 && literalFamily !== family) {
|
|
27
|
+
throw new exceptions_1.AddressFamilyMismatch(addr, family);
|
|
28
|
+
}
|
|
20
29
|
return addr;
|
|
21
30
|
}
|
|
22
31
|
const looked = await node_dns_1.promises.lookup(addr[0], { family });
|
|
@@ -40,9 +49,20 @@ function normalizeTransactionOptions(retransmissionsOrOptions, onRequestSent) {
|
|
|
40
49
|
onRequestSent,
|
|
41
50
|
};
|
|
42
51
|
}
|
|
43
|
-
/**
|
|
52
|
+
/**
|
|
53
|
+
* Compare ICE transport addresses (host, port).
|
|
54
|
+
* IPv6 literals are compared in canonical form because the socket reports
|
|
55
|
+
* `::1` even when the peer was configured as `0:0:0:0:0:0:0:1`.
|
|
56
|
+
*/
|
|
44
57
|
function addressEquals(a, b) {
|
|
45
|
-
return a[
|
|
58
|
+
return a[1] === b[1] && canonicalHost(a[0]) === canonicalHost(b[0]);
|
|
59
|
+
}
|
|
60
|
+
// Only used for comparison; never for the address a packet is sent to,
|
|
61
|
+
// since SocketAddress drops the zone id (`fe80::1%eth0`).
|
|
62
|
+
function canonicalHost(host) {
|
|
63
|
+
return (0, node_net_1.isIP)(host) === 6
|
|
64
|
+
? new node_net_1.SocketAddress({ address: host, family: "ipv6" }).address
|
|
65
|
+
: host;
|
|
46
66
|
}
|
|
47
67
|
class Transaction {
|
|
48
68
|
constructor(request, addr, protocol, retransmissionsOrOptions, onRequestSent) {
|
|
@@ -106,6 +126,12 @@ class Transaction {
|
|
|
106
126
|
writable: true,
|
|
107
127
|
value: void 0
|
|
108
128
|
});
|
|
129
|
+
Object.defineProperty(this, "failOnSendError", {
|
|
130
|
+
enumerable: true,
|
|
131
|
+
configurable: true,
|
|
132
|
+
writable: true,
|
|
133
|
+
value: void 0
|
|
134
|
+
});
|
|
109
135
|
/** Remote address this transaction was sent to; responses must match. */
|
|
110
136
|
Object.defineProperty(this, "expectedAddr", {
|
|
111
137
|
enumerable: true,
|
|
@@ -215,6 +241,9 @@ class Transaction {
|
|
|
215
241
|
this.onRequestSent?.(this.tries);
|
|
216
242
|
this.protocol.sendStun(this.request, this.addr).catch((e) => {
|
|
217
243
|
log("send stun failed", e);
|
|
244
|
+
if (this.failOnSendError) {
|
|
245
|
+
this.fail(e);
|
|
246
|
+
}
|
|
218
247
|
});
|
|
219
248
|
await this.wait(this.timeoutDelay);
|
|
220
249
|
if (this.ended) {
|
|
@@ -236,6 +265,7 @@ class Transaction {
|
|
|
236
265
|
this.timeoutDelay = options.responseTimeout ?? const_1.RETRY_RTO;
|
|
237
266
|
this.onRequestSent = options.onRequestSent;
|
|
238
267
|
this.signal = options.signal;
|
|
268
|
+
this.failOnSendError = options.failOnSendError ?? false;
|
|
239
269
|
this.expectedAddr = addr;
|
|
240
270
|
this.integrityKey = options.integrityKey;
|
|
241
271
|
}
|
|
@@ -249,13 +279,16 @@ class Transaction {
|
|
|
249
279
|
this.signal.addEventListener("abort", this.onAbort, { once: true });
|
|
250
280
|
}
|
|
251
281
|
failWithTimeout() {
|
|
282
|
+
this.fail(new exceptions_1.TransactionTimeout());
|
|
283
|
+
}
|
|
284
|
+
fail(error) {
|
|
252
285
|
if (this.ended) {
|
|
253
286
|
return;
|
|
254
287
|
}
|
|
255
288
|
this.ended = true;
|
|
256
289
|
this.clearWait();
|
|
257
290
|
if (this.onResponse.length > 0) {
|
|
258
|
-
this.onResponse.error(
|
|
291
|
+
this.onResponse.error(error);
|
|
259
292
|
}
|
|
260
293
|
}
|
|
261
294
|
clearWait() {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"transaction.js","sourceRoot":"","sources":["../../../../../ice/src/stun/transaction.ts"],"names":[],"mappings":"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","sourcesContent":["import { promises as dns } from \"node:dns\";\nimport { isIP } from \"node:net\";\n\nimport { type Address, Event, debug } from \"../imports/common\";\n\nimport { TransactionFailed, TransactionTimeout } from \"../exceptions\";\nimport type { Protocol, TransactionRequestOptions } from \"../types/model\";\nimport { RETRY_MAX, RETRY_RTO, classes } from \"./const\";\nimport type { Message } from \"./message\";\n\nconst log = debug(\"werift-ice:packages/ice/src/stun/transaction.ts\");\n\n/**\n * Resolve a request target to a concrete IP before creating a Transaction so\n * response source-address checks match the UDP peer address (hostname ≠ IP).\n */\nexport async function resolveRequestAddress(\n addr: Address,\n family: 0 | 4 | 6 = 0,\n): Promise<Address> {\n if (isIP(addr[0])) {\n return addr;\n }\n const looked = await dns.lookup(addr[0], { family });\n return [looked.address, addr[1]];\n}\n\n/**\n * Normalize legacy positional args and the options-object form into one shape.\n * Existing callers pass `(retransmissions?, onRequestSent?)`.\n */\nexport function normalizeTransactionOptions(\n retransmissionsOrOptions?: number | TransactionRequestOptions,\n onRequestSent?: (attempt: number) => void,\n): TransactionRequestOptions {\n if (\n retransmissionsOrOptions !== null &&\n typeof retransmissionsOrOptions === \"object\"\n ) {\n return retransmissionsOrOptions;\n }\n // After the object branch, only number | undefined remains (legacy positional API).\n const retransmissions =\n typeof retransmissionsOrOptions === \"number\"\n ? retransmissionsOrOptions\n : undefined;\n return {\n retransmissions,\n onRequestSent,\n };\n}\n\n/** Compare ICE transport addresses (host, port). */\nexport function addressEquals(a: Address, b: Address): boolean {\n return a[0] === b[0] && a[1] === b[1];\n}\n\nexport class Transaction {\n private timeoutDelay: number;\n ended = false;\n private tries = 0;\n private readonly triesMax: number;\n private readonly onResponse = new Event<[Message, Address]>();\n private readonly onRequestSent?: (attempt: number) => void;\n private readonly signal?: AbortSignal;\n /** Remote address this transaction was sent to; responses must match. */\n readonly expectedAddr: Address;\n /**\n * When set, protocol layers re-parse the wire response with this key so\n * MESSAGE-INTEGRITY failures are rejected before responseReceived.\n */\n readonly integrityKey?: Buffer;\n private waitTimer?: ReturnType<typeof setTimeout>;\n private waitResolve?: () => void;\n private onAbort?: () => void;\n\n constructor(\n private request: Message,\n private addr: Address,\n private protocol: Protocol,\n retransmissionsOrOptions?: number | TransactionRequestOptions,\n onRequestSent?: (attempt: number) => void,\n ) {\n const options = normalizeTransactionOptions(\n retransmissionsOrOptions,\n onRequestSent,\n );\n // triesMax = initial send + retransmissions\n this.triesMax = 1 + (options.retransmissions ?? RETRY_MAX);\n // responseTimeout is independent of retransmission count (RFC 7675 / 8445)\n this.timeoutDelay = options.responseTimeout ?? RETRY_RTO;\n this.onRequestSent = options.onRequestSent;\n this.signal = options.signal;\n this.expectedAddr = addr;\n this.integrityKey = options.integrityKey;\n }\n\n /**\n * Accept a matching authenticated non-error response from the expected\n * remote address. Wrong address, missing MESSAGE-INTEGRITY (when required),\n * or non-success class is rejected without completing the transaction\n * (wrong address / unauthenticated responses are ignored so we keep waiting).\n */\n responseReceived = (message: Message, addr: Address) => {\n if (this.ended || this.onResponse.length === 0) {\n return;\n }\n\n // RFC 7675 / ICE: only responses from the request's transport address.\n if (!addressEquals(this.expectedAddr, addr)) {\n log(\n \"ignore STUN response from unexpected address\",\n addr,\n \"expected\",\n this.expectedAddr,\n );\n return;\n }\n\n // RFC 7675 authenticated consent: integrityKey requires MESSAGE-INTEGRITY.\n // Wire HMAC is verified by protocol layers via parseMessage(data, key);\n // this presence check is defense-in-depth if responseReceived is called\n // with a constructed Message that skipped the wire re-parse path.\n if (this.integrityKey) {\n const hasIntegrity =\n message.attributesKeys.includes(\"MESSAGE-INTEGRITY\") ||\n message.attributesKeys.includes(\"MESSAGE-INTEGRITY-SHA256\");\n if (!hasIntegrity) {\n log(\n \"ignore unauthenticated STUN response (MESSAGE-INTEGRITY required)\",\n );\n return;\n }\n }\n\n if (message.messageClass === classes.RESPONSE) {\n this.onResponse.execute(message, addr);\n this.onResponse.complete();\n } else {\n // ERROR class or other non-success\n this.onResponse.error(new TransactionFailed(message, addr));\n }\n };\n\n run = async () => {\n try {\n if (this.signal?.aborted) {\n throw new TransactionTimeout();\n }\n this.attachAbortListener();\n this.retry().catch((e) => {\n log(\"retry failed\", e);\n });\n const res = await this.onResponse.asPromise();\n return res;\n } catch (error) {\n throw error;\n } finally {\n this.cancel();\n }\n };\n\n private attachAbortListener() {\n if (!this.signal) {\n return;\n }\n this.onAbort = () => {\n this.failWithTimeout();\n };\n this.signal.addEventListener(\"abort\", this.onAbort, { once: true });\n }\n\n private failWithTimeout() {\n if (this.ended) {\n return;\n }\n this.ended = true;\n this.clearWait();\n if (this.onResponse.length > 0) {\n this.onResponse.error(new TransactionTimeout());\n }\n }\n\n private clearWait() {\n if (this.waitTimer !== undefined) {\n clearTimeout(this.waitTimer);\n this.waitTimer = undefined;\n }\n const resolve = this.waitResolve;\n this.waitResolve = undefined;\n resolve?.();\n }\n\n private wait(ms: number): Promise<void> {\n return new Promise((resolve) => {\n if (this.ended || this.signal?.aborted) {\n resolve();\n return;\n }\n this.waitResolve = resolve;\n this.waitTimer = setTimeout(() => {\n this.waitTimer = undefined;\n this.waitResolve = undefined;\n resolve();\n }, ms);\n });\n }\n\n private retry = async () => {\n while (this.tries < this.triesMax && !this.ended) {\n this.onRequestSent?.(this.tries);\n this.protocol.sendStun(this.request, this.addr).catch((e) => {\n log(\"send stun failed\", e);\n });\n await this.wait(this.timeoutDelay);\n if (this.ended) {\n break;\n }\n this.timeoutDelay *= 2;\n this.tries++;\n }\n if (this.tries >= this.triesMax && !this.ended) {\n log(`retry failed times:${this.tries} maxLimit:${this.triesMax}`);\n this.failWithTimeout();\n }\n };\n\n cancel() {\n this.ended = true;\n this.clearWait();\n if (this.signal && this.onAbort) {\n this.signal.removeEventListener(\"abort\", this.onAbort);\n this.onAbort = undefined;\n }\n }\n}\n\n/**\n * Build Transaction options for Protocol.request, folding integrityKey into\n * options so response path can re-verify MESSAGE-INTEGRITY.\n */\nexport function buildTransactionOptions(\n integrityKey: Buffer | undefined,\n retransmissionsOrOptions?: number | TransactionRequestOptions,\n onRequestSent?: (attempt: number) => void,\n): TransactionRequestOptions {\n const options = normalizeTransactionOptions(\n retransmissionsOrOptions,\n onRequestSent,\n );\n if (integrityKey && !options.integrityKey) {\n options.integrityKey = integrityKey;\n }\n return options;\n}\n"]}
|
|
1
|
+
{"version":3,"file":"transaction.js","sourceRoot":"","sources":["../../../../../ice/src/stun/transaction.ts"],"names":[],"mappings":"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","sourcesContent":["import { promises as dns } from \"node:dns\";\nimport { SocketAddress, isIP } from \"node:net\";\n\nimport { type Address, Event, debug } from \"../imports/common\";\n\nimport {\n AddressFamilyMismatch,\n TransactionFailed,\n TransactionTimeout,\n} from \"../exceptions\";\nimport type { Protocol, TransactionRequestOptions } from \"../types/model\";\nimport { RETRY_MAX, RETRY_RTO, classes } from \"./const\";\nimport type { Message } from \"./message\";\n\nconst log = debug(\"werift-ice:packages/ice/src/stun/transaction.ts\");\n\n/**\n * Resolve a request target to a concrete IP before creating a Transaction so\n * response source-address checks match the UDP peer address (hostname ≠ IP).\n *\n * `family` is the family of the socket that will carry the request: a\n * hostname resolves only in that family, and an IP literal of the other\n * family throws AddressFamilyMismatch instead of retransmitting into a send\n * that cannot succeed. Family 0 means unknown: no preference, no check.\n */\nexport async function resolveRequestAddress(\n addr: Address,\n family: 0 | 4 | 6 = 0,\n): Promise<Address> {\n const literalFamily = isIP(addr[0]);\n if (literalFamily) {\n if (family !== 0 && literalFamily !== family) {\n throw new AddressFamilyMismatch(addr, family);\n }\n return addr;\n }\n const looked = await dns.lookup(addr[0], { family });\n return [looked.address, addr[1]];\n}\n\n/**\n * Normalize legacy positional args and the options-object form into one shape.\n * Existing callers pass `(retransmissions?, onRequestSent?)`.\n */\nexport function normalizeTransactionOptions(\n retransmissionsOrOptions?: number | TransactionRequestOptions,\n onRequestSent?: (attempt: number) => void,\n): TransactionRequestOptions {\n if (\n retransmissionsOrOptions !== null &&\n typeof retransmissionsOrOptions === \"object\"\n ) {\n return retransmissionsOrOptions;\n }\n // After the object branch, only number | undefined remains (legacy positional API).\n const retransmissions =\n typeof retransmissionsOrOptions === \"number\"\n ? retransmissionsOrOptions\n : undefined;\n return {\n retransmissions,\n onRequestSent,\n };\n}\n\n/**\n * Compare ICE transport addresses (host, port).\n * IPv6 literals are compared in canonical form because the socket reports\n * `::1` even when the peer was configured as `0:0:0:0:0:0:0:1`.\n */\nexport function addressEquals(a: Address, b: Address): boolean {\n return a[1] === b[1] && canonicalHost(a[0]) === canonicalHost(b[0]);\n}\n\n// Only used for comparison; never for the address a packet is sent to,\n// since SocketAddress drops the zone id (`fe80::1%eth0`).\nfunction canonicalHost(host: string): string {\n return isIP(host) === 6\n ? new SocketAddress({ address: host, family: \"ipv6\" }).address\n : host;\n}\n\nexport class Transaction {\n private timeoutDelay: number;\n ended = false;\n private tries = 0;\n private readonly triesMax: number;\n private readonly onResponse = new Event<[Message, Address]>();\n private readonly onRequestSent?: (attempt: number) => void;\n private readonly signal?: AbortSignal;\n private readonly failOnSendError: boolean;\n /** Remote address this transaction was sent to; responses must match. */\n readonly expectedAddr: Address;\n /**\n * When set, protocol layers re-parse the wire response with this key so\n * MESSAGE-INTEGRITY failures are rejected before responseReceived.\n */\n readonly integrityKey?: Buffer;\n private waitTimer?: ReturnType<typeof setTimeout>;\n private waitResolve?: () => void;\n private onAbort?: () => void;\n\n constructor(\n private request: Message,\n private addr: Address,\n private protocol: Protocol,\n retransmissionsOrOptions?: number | TransactionRequestOptions,\n onRequestSent?: (attempt: number) => void,\n ) {\n const options = normalizeTransactionOptions(\n retransmissionsOrOptions,\n onRequestSent,\n );\n // triesMax = initial send + retransmissions\n this.triesMax = 1 + (options.retransmissions ?? RETRY_MAX);\n // responseTimeout is independent of retransmission count (RFC 7675 / 8445)\n this.timeoutDelay = options.responseTimeout ?? RETRY_RTO;\n this.onRequestSent = options.onRequestSent;\n this.signal = options.signal;\n this.failOnSendError = options.failOnSendError ?? false;\n this.expectedAddr = addr;\n this.integrityKey = options.integrityKey;\n }\n\n /**\n * Accept a matching authenticated non-error response from the expected\n * remote address. Wrong address, missing MESSAGE-INTEGRITY (when required),\n * or non-success class is rejected without completing the transaction\n * (wrong address / unauthenticated responses are ignored so we keep waiting).\n */\n responseReceived = (message: Message, addr: Address) => {\n if (this.ended || this.onResponse.length === 0) {\n return;\n }\n\n // RFC 7675 / ICE: only responses from the request's transport address.\n if (!addressEquals(this.expectedAddr, addr)) {\n log(\n \"ignore STUN response from unexpected address\",\n addr,\n \"expected\",\n this.expectedAddr,\n );\n return;\n }\n\n // RFC 7675 authenticated consent: integrityKey requires MESSAGE-INTEGRITY.\n // Wire HMAC is verified by protocol layers via parseMessage(data, key);\n // this presence check is defense-in-depth if responseReceived is called\n // with a constructed Message that skipped the wire re-parse path.\n if (this.integrityKey) {\n const hasIntegrity =\n message.attributesKeys.includes(\"MESSAGE-INTEGRITY\") ||\n message.attributesKeys.includes(\"MESSAGE-INTEGRITY-SHA256\");\n if (!hasIntegrity) {\n log(\n \"ignore unauthenticated STUN response (MESSAGE-INTEGRITY required)\",\n );\n return;\n }\n }\n\n if (message.messageClass === classes.RESPONSE) {\n this.onResponse.execute(message, addr);\n this.onResponse.complete();\n } else {\n // ERROR class or other non-success\n this.onResponse.error(new TransactionFailed(message, addr));\n }\n };\n\n run = async () => {\n try {\n if (this.signal?.aborted) {\n throw new TransactionTimeout();\n }\n this.attachAbortListener();\n this.retry().catch((e) => {\n log(\"retry failed\", e);\n });\n const res = await this.onResponse.asPromise();\n return res;\n } catch (error) {\n throw error;\n } finally {\n this.cancel();\n }\n };\n\n private attachAbortListener() {\n if (!this.signal) {\n return;\n }\n this.onAbort = () => {\n this.failWithTimeout();\n };\n this.signal.addEventListener(\"abort\", this.onAbort, { once: true });\n }\n\n private failWithTimeout() {\n this.fail(new TransactionTimeout());\n }\n\n private fail(error: Error) {\n if (this.ended) {\n return;\n }\n this.ended = true;\n this.clearWait();\n if (this.onResponse.length > 0) {\n this.onResponse.error(error);\n }\n }\n\n private clearWait() {\n if (this.waitTimer !== undefined) {\n clearTimeout(this.waitTimer);\n this.waitTimer = undefined;\n }\n const resolve = this.waitResolve;\n this.waitResolve = undefined;\n resolve?.();\n }\n\n private wait(ms: number): Promise<void> {\n return new Promise((resolve) => {\n if (this.ended || this.signal?.aborted) {\n resolve();\n return;\n }\n this.waitResolve = resolve;\n this.waitTimer = setTimeout(() => {\n this.waitTimer = undefined;\n this.waitResolve = undefined;\n resolve();\n }, ms);\n });\n }\n\n private retry = async () => {\n while (this.tries < this.triesMax && !this.ended) {\n this.onRequestSent?.(this.tries);\n this.protocol.sendStun(this.request, this.addr).catch((e) => {\n log(\"send stun failed\", e);\n if (this.failOnSendError) {\n this.fail(e);\n }\n });\n await this.wait(this.timeoutDelay);\n if (this.ended) {\n break;\n }\n this.timeoutDelay *= 2;\n this.tries++;\n }\n if (this.tries >= this.triesMax && !this.ended) {\n log(`retry failed times:${this.tries} maxLimit:${this.triesMax}`);\n this.failWithTimeout();\n }\n };\n\n cancel() {\n this.ended = true;\n this.clearWait();\n if (this.signal && this.onAbort) {\n this.signal.removeEventListener(\"abort\", this.onAbort);\n this.onAbort = undefined;\n }\n }\n}\n\n/**\n * Build Transaction options for Protocol.request, folding integrityKey into\n * options so response path can re-verify MESSAGE-INTEGRITY.\n */\nexport function buildTransactionOptions(\n integrityKey: Buffer | undefined,\n retransmissionsOrOptions?: number | TransactionRequestOptions,\n onRequestSent?: (attempt: number) => void,\n): TransactionRequestOptions {\n const options = normalizeTransactionOptions(\n retransmissionsOrOptions,\n onRequestSent,\n );\n if (integrityKey && !options.integrityKey) {\n options.integrityKey = integrityKey;\n }\n return options;\n}\n"]}
|