werift 0.24.4 → 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/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 +40 -15
- package/lib/ice/src/turn/protocol.js +141 -32
- 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 +6175 -4073
- package/lib/nonstandard/index.mjs +286 -1003
- 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 +126 -5
- package/lib/webrtc/src/peerConnection.js +609 -136
- 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 +13 -3
|
@@ -4,6 +4,7 @@ exports.TurnProtocol = exports.StunOverTurnProtocol = void 0;
|
|
|
4
4
|
exports.createTurnClient = createTurnClient;
|
|
5
5
|
exports.createStunOverTurnClient = createStunOverTurnClient;
|
|
6
6
|
exports.makeIntegrityKey = makeIntegrityKey;
|
|
7
|
+
const node_net_1 = require("node:net");
|
|
7
8
|
const promises_1 = require("timers/promises");
|
|
8
9
|
const auth_1 = require("../../../ice-server/src/turn/auth");
|
|
9
10
|
const exceptions_1 = require("../exceptions");
|
|
@@ -152,7 +153,9 @@ Object.defineProperty(StunOverTurnProtocol, "type", {
|
|
|
152
153
|
value: "turn"
|
|
153
154
|
});
|
|
154
155
|
class TurnProtocol {
|
|
155
|
-
constructor(
|
|
156
|
+
constructor(
|
|
157
|
+
/** TURN server as configured; the host may be a hostname. */
|
|
158
|
+
server, username, password, lifetime, transport, options = {}) {
|
|
156
159
|
Object.defineProperty(this, "server", {
|
|
157
160
|
enumerable: true,
|
|
158
161
|
configurable: true,
|
|
@@ -334,29 +337,56 @@ class TurnProtocol {
|
|
|
334
337
|
writable: true,
|
|
335
338
|
value: new Map()
|
|
336
339
|
});
|
|
340
|
+
/** Concrete TURN server address the allocation lives on, once selected. */
|
|
341
|
+
Object.defineProperty(this, "pinnedServerEndpoint", {
|
|
342
|
+
enumerable: true,
|
|
343
|
+
configurable: true,
|
|
344
|
+
writable: true,
|
|
345
|
+
value: void 0
|
|
346
|
+
});
|
|
347
|
+
Object.defineProperty(this, "serverEndpointSelection", {
|
|
348
|
+
enumerable: true,
|
|
349
|
+
configurable: true,
|
|
350
|
+
writable: true,
|
|
351
|
+
value: void 0
|
|
352
|
+
});
|
|
337
353
|
Object.defineProperty(this, "refresh", {
|
|
338
354
|
enumerable: true,
|
|
339
355
|
configurable: true,
|
|
340
356
|
writable: true,
|
|
341
357
|
value: (exp) => {
|
|
342
358
|
this.refreshHandle = (0, helper_1.cancelable)(async (_, __, onCancel) => {
|
|
343
|
-
|
|
359
|
+
const abort = new AbortController();
|
|
344
360
|
onCancel.once(() => {
|
|
345
|
-
|
|
361
|
+
abort.abort();
|
|
346
362
|
});
|
|
347
|
-
while (
|
|
363
|
+
while (!abort.signal.aborted) {
|
|
348
364
|
// refresh before expire
|
|
349
365
|
const delay = (5 / 6) * exp * 1000;
|
|
350
366
|
log("refresh delay", delay, { exp });
|
|
351
|
-
|
|
367
|
+
try {
|
|
368
|
+
await (0, promises_1.setTimeout)(delay, undefined, { signal: abort.signal });
|
|
369
|
+
}
|
|
370
|
+
catch (error) {
|
|
371
|
+
if (abort.signal.aborted) {
|
|
372
|
+
return;
|
|
373
|
+
}
|
|
374
|
+
throw error;
|
|
375
|
+
}
|
|
376
|
+
if (abort.signal.aborted) {
|
|
377
|
+
return;
|
|
378
|
+
}
|
|
352
379
|
const request = new message_1.Message(const_1.methods.REFRESH, const_1.classes.REQUEST);
|
|
353
380
|
request.setAttribute("LIFETIME", exp);
|
|
354
381
|
try {
|
|
355
|
-
const [message] = await this.requestWithRetry(request, this.server);
|
|
382
|
+
const [message] = await this.requestWithRetry(request, this.server, abort.signal);
|
|
356
383
|
exp = message.getAttributeValue("LIFETIME");
|
|
357
384
|
log("refresh", { exp });
|
|
358
385
|
}
|
|
359
386
|
catch (error) {
|
|
387
|
+
if (abort.signal.aborted) {
|
|
388
|
+
return;
|
|
389
|
+
}
|
|
360
390
|
log("refresh error", error);
|
|
361
391
|
}
|
|
362
392
|
}
|
|
@@ -476,7 +506,7 @@ class TurnProtocol {
|
|
|
476
506
|
// TURN server allocation/refresh uses default STUN retry policy unless
|
|
477
507
|
// callers pass explicit options. Peer consent goes through StunOverTurnProtocol.
|
|
478
508
|
// Prefer the TURN session integrity key for response verification.
|
|
479
|
-
const resolvedAddr = await
|
|
509
|
+
const resolvedAddr = await this.resolveRequestTarget(addr);
|
|
480
510
|
const options = (0, transaction_1.buildTransactionOptions)(this.integrityKey, retransmissionsOrOptions, onRequestSent);
|
|
481
511
|
const transaction = new transaction_1.Transaction(request, resolvedAddr, this, options);
|
|
482
512
|
this.transactions[request.transactionIdHex] = transaction;
|
|
@@ -490,18 +520,74 @@ class TurnProtocol {
|
|
|
490
520
|
delete this.transactions[request.transactionIdHex];
|
|
491
521
|
}
|
|
492
522
|
}
|
|
493
|
-
|
|
523
|
+
/**
|
|
524
|
+
* The concrete TURN server address, selected on the first request and
|
|
525
|
+
* pinned for the rest of the allocation, so a later DNS answer can never
|
|
526
|
+
* move REFRESH, CREATE_PERMISSION, CHANNEL_BIND or data to another server.
|
|
527
|
+
*/
|
|
528
|
+
get serverEndpoint() {
|
|
529
|
+
return this.pinnedServerEndpoint;
|
|
530
|
+
}
|
|
531
|
+
/**
|
|
532
|
+
* Address a request to `addr` is sent to, and the address its response
|
|
533
|
+
* must come from. A stream carries every request to the peer it is
|
|
534
|
+
* connected to, so it always uses the server endpoint.
|
|
535
|
+
*/
|
|
536
|
+
async resolveRequestTarget(addr) {
|
|
537
|
+
if (isStreamTransport(this.transport) || (0, transaction_1.addressEquals)(addr, this.server)) {
|
|
538
|
+
return this.selectServerEndpoint();
|
|
539
|
+
}
|
|
540
|
+
return (0, transaction_1.resolveRequestAddress)(addr, this.transport.addressFamily ?? 0);
|
|
541
|
+
}
|
|
542
|
+
async serverDestination() {
|
|
543
|
+
return this.pinnedServerEndpoint ?? this.selectServerEndpoint();
|
|
544
|
+
}
|
|
545
|
+
selectServerEndpoint() {
|
|
546
|
+
this.serverEndpointSelection ?? (this.serverEndpointSelection = this.resolveServerEndpoint().then((endpoint) => {
|
|
547
|
+
this.pinnedServerEndpoint = endpoint;
|
|
548
|
+
return endpoint;
|
|
549
|
+
}, (error) => {
|
|
550
|
+
// Let a later request try again, e.g. after a transient DNS failure.
|
|
551
|
+
this.serverEndpointSelection = undefined;
|
|
552
|
+
throw error;
|
|
553
|
+
}));
|
|
554
|
+
return this.serverEndpointSelection;
|
|
555
|
+
}
|
|
556
|
+
/**
|
|
557
|
+
* UDP: resolve the configured server in the bound socket's family; a udp4
|
|
558
|
+
* socket cannot send to an IPv6 answer. TCP/TLS: use the peer the socket
|
|
559
|
+
* actually connected to. Looking the hostname up again could return a
|
|
560
|
+
* different A/AAAA record, and responses from the real peer would then be
|
|
561
|
+
* dropped as coming from an unexpected address.
|
|
562
|
+
*/
|
|
563
|
+
async resolveServerEndpoint() {
|
|
564
|
+
const transport = this.transport;
|
|
565
|
+
if (!isStreamTransport(transport)) {
|
|
566
|
+
return (0, transaction_1.resolveRequestAddress)(this.server, transport.addressFamily ?? 0);
|
|
567
|
+
}
|
|
568
|
+
if (transport.remoteAddress) {
|
|
569
|
+
return transport.remoteAddress;
|
|
570
|
+
}
|
|
571
|
+
if (transport instanceof common_1.TcpTransport ||
|
|
572
|
+
transport instanceof common_1.TlsTransport) {
|
|
573
|
+
throw new Error(`${transport.type} transport has no remote address`);
|
|
574
|
+
}
|
|
575
|
+
// A custom stream transport that does not report its peer: fall back to
|
|
576
|
+
// a lookup with no family preference.
|
|
577
|
+
return (0, transaction_1.resolveRequestAddress)(this.server);
|
|
578
|
+
}
|
|
579
|
+
async requestWithRetry(request, addr, signal) {
|
|
494
580
|
let message, address;
|
|
495
581
|
try {
|
|
496
|
-
[message, address] = await this.request(request, addr
|
|
582
|
+
[message, address] = await this.request(request, addr, undefined, {
|
|
583
|
+
signal,
|
|
584
|
+
});
|
|
497
585
|
}
|
|
498
586
|
catch (error) {
|
|
499
587
|
if (error instanceof exceptions_1.TransactionFailed == false) {
|
|
500
588
|
log("requestWithRetry error", error);
|
|
501
589
|
throw error;
|
|
502
590
|
}
|
|
503
|
-
// resolve dns address
|
|
504
|
-
this.server = error.addr;
|
|
505
591
|
const [errorCode] = error.response.getAttributeValue("ERROR-CODE");
|
|
506
592
|
const nonce = error.response.getAttributeValue("NONCE");
|
|
507
593
|
const realm = error.response.getAttributeValue("REALM");
|
|
@@ -514,7 +600,7 @@ class TurnProtocol {
|
|
|
514
600
|
}
|
|
515
601
|
this.integrityKey = makeIntegrityKey(this.username, this.realm, this.password);
|
|
516
602
|
request.transactionId = (0, helper_1.randomTransactionId)();
|
|
517
|
-
[message, address] = await this.request(request, this.server);
|
|
603
|
+
[message, address] = await this.request(request, this.server, undefined, { signal });
|
|
518
604
|
}
|
|
519
605
|
else {
|
|
520
606
|
throw error;
|
|
@@ -536,10 +622,10 @@ class TurnProtocol {
|
|
|
536
622
|
const indicate = new message_1.Message(const_1.methods.SEND, const_1.classes.INDICATION)
|
|
537
623
|
.setAttribute("DATA", data)
|
|
538
624
|
.setAttribute("XOR-PEER-ADDRESS", addr);
|
|
539
|
-
await this.sendStun(indicate, this.
|
|
625
|
+
await this.sendStun(indicate, await this.serverDestination());
|
|
540
626
|
return;
|
|
541
627
|
}
|
|
542
|
-
await this.send((0, frame_1.encodeChannelData)(channel.number, data), this.
|
|
628
|
+
await this.send((0, frame_1.encodeChannelData)(channel.number, data), await this.serverDestination());
|
|
543
629
|
}
|
|
544
630
|
/**
|
|
545
631
|
* Ensure a CreatePermission exists for the peer IP.
|
|
@@ -677,31 +763,54 @@ Object.defineProperty(TurnProtocol, "type", {
|
|
|
677
763
|
writable: true,
|
|
678
764
|
value: "turn"
|
|
679
765
|
});
|
|
680
|
-
|
|
766
|
+
/**
|
|
767
|
+
* Select the UDP socket type for a TURN server.
|
|
768
|
+
* Precedence: IP literal family > udpFamily > 4.
|
|
769
|
+
* An IP literal fixes the destination family, so a conflicting udpFamily is
|
|
770
|
+
* ignored (and logged) rather than making the server unreachable.
|
|
771
|
+
*/
|
|
772
|
+
function selectTurnUdpSocketType(address, udpFamily) {
|
|
773
|
+
const literalFamily = (0, node_net_1.isIP)(address[0]);
|
|
774
|
+
if (literalFamily === 4 || literalFamily === 6) {
|
|
775
|
+
if (udpFamily && udpFamily !== literalFamily) {
|
|
776
|
+
log("udpFamily ignored for IP literal TURN server", {
|
|
777
|
+
address,
|
|
778
|
+
udpFamily,
|
|
779
|
+
literalFamily,
|
|
780
|
+
});
|
|
781
|
+
}
|
|
782
|
+
return literalFamily === 6 ? "udp6" : "udp4";
|
|
783
|
+
}
|
|
784
|
+
return (udpFamily ?? 4) === 6 ? "udp6" : "udp4";
|
|
785
|
+
}
|
|
786
|
+
async function createTurnClient({ address, username, password }, { lifetime, portRange, interfaceAddresses, ssl, tlsOptions, transport: transportType, connectTimeoutMs, udpFamily, } = {}) {
|
|
681
787
|
lifetime ?? (lifetime = DEFAULT_ALLOCATION_LIFETIME);
|
|
682
788
|
transportType ?? (transportType = ssl ? "tls" : "udp");
|
|
683
789
|
const transport = transportType === "udp"
|
|
684
|
-
? await common_1.UdpTransport.init(
|
|
790
|
+
? await common_1.UdpTransport.init(selectTurnUdpSocketType(address, udpFamily), {
|
|
791
|
+
portRange,
|
|
792
|
+
interfaceAddresses,
|
|
793
|
+
})
|
|
685
794
|
: transportType === "tcp"
|
|
686
|
-
? await common_1.TcpTransport.init(address)
|
|
687
|
-
: await common_1.TlsTransport.init(address, tlsOptions);
|
|
795
|
+
? await common_1.TcpTransport.init(address, { connectTimeoutMs })
|
|
796
|
+
: await common_1.TlsTransport.init(address, tlsOptions, { connectTimeoutMs });
|
|
688
797
|
const turn = new TurnProtocol(address, username, password, lifetime, transport);
|
|
689
|
-
|
|
798
|
+
try {
|
|
799
|
+
await turn.connectionMade();
|
|
800
|
+
}
|
|
801
|
+
catch (error) {
|
|
802
|
+
try {
|
|
803
|
+
await turn.close();
|
|
804
|
+
}
|
|
805
|
+
catch (closeError) {
|
|
806
|
+
log("failed to close TURN client after allocation failure", closeError);
|
|
807
|
+
}
|
|
808
|
+
throw error;
|
|
809
|
+
}
|
|
690
810
|
return turn;
|
|
691
811
|
}
|
|
692
|
-
async function createStunOverTurnClient(
|
|
693
|
-
const turn = await createTurnClient(
|
|
694
|
-
address,
|
|
695
|
-
username,
|
|
696
|
-
password,
|
|
697
|
-
}, {
|
|
698
|
-
lifetime,
|
|
699
|
-
portRange,
|
|
700
|
-
interfaceAddresses,
|
|
701
|
-
ssl,
|
|
702
|
-
tlsOptions,
|
|
703
|
-
transport: transportType,
|
|
704
|
-
});
|
|
812
|
+
async function createStunOverTurnClient(config, options = {}) {
|
|
813
|
+
const turn = await createTurnClient(config, options);
|
|
705
814
|
const turnTransport = new StunOverTurnProtocol(turn);
|
|
706
815
|
return turnTransport;
|
|
707
816
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"protocol.js","sourceRoot":"","sources":["../../../../../ice/src/turn/protocol.ts"],"names":[],"mappings":"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","sourcesContent":["import { setTimeout } from \"timers/promises\";\n\nimport { makeTurnIntegrityKey } from \"../../../ice-server/src/turn/auth\";\nimport type { Candidate } from \"../candidate\";\nimport { TransactionFailed } from \"../exceptions\";\nimport { type Cancelable, cancelable, randomTransactionId } from \"../helper\";\nimport {\n type Address,\n Event,\n EventDisposer,\n type InterfaceAddresses,\n TcpTransport,\n type TlsConnectionOptions,\n TlsTransport,\n type Transport,\n UdpTransport,\n bufferReader,\n debug,\n int,\n} from \"../imports/common\";\nimport { classes, methods } from \"../stun/const\";\nimport { Message, paddingLength, parseMessage } from \"../stun/message\";\nimport {\n Transaction,\n buildTransactionOptions,\n resolveRequestAddress,\n} from \"../stun/transaction\";\nimport type { Protocol, TransactionRequestOptions } from \"../types/model\";\nimport {\n decodeChannelData,\n encodeChannelData,\n isChannelData,\n padTurnFrame,\n splitTurnTcpFrames,\n} from \"./frame\";\n\nconst log = debug(\"werift-ice:packages/ice/src/turn/protocol.ts\");\n\nconst DEFAULT_CHANNEL_REFRESH_TIME = 500;\nconst DEFAULT_ALLOCATION_LIFETIME = 600;\nconst UDP_TRANSPORT = 0x11000000;\n\n/** Channel binding state for a single peer transport address. */\nexport interface TurnChannel {\n number: number;\n address: Address;\n /** Unix seconds when this channel should be refreshed. */\n refreshAt: number;\n}\n\nfunction isStreamTransport(transport: Transport) {\n return transport.type === \"tcp\" || transport.type === \"tls\";\n}\n\n/** Permission is peer-IP scoped (RFC 8656). */\nfunction permissionKey(addr: Address): string {\n return addr[0];\n}\n\n/** ChannelBind is peer transport-address scoped (IP + port). */\nfunction channelKey(addr: Address): string {\n return JSON.stringify(addr);\n}\n\nexport class StunOverTurnProtocol implements Protocol {\n static type = \"turn\";\n readonly type = StunOverTurnProtocol.type;\n localCandidate!: Candidate;\n private disposer = new EventDisposer();\n onRequestReceived: Event<[Message, Address, Buffer]> = new Event();\n onDataReceived: Event<[Buffer]> = new Event();\n\n constructor(public turn: TurnProtocol) {\n turn.onData\n .subscribe((data, addr) => {\n this.handleStunMessage(data, addr);\n })\n .disposer(this.disposer);\n }\n\n private handleStunMessage = (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 ) {\n const transaction = this.turn.transactions[message.transactionIdHex];\n if (transaction) {\n const verified = transaction.integrityKey\n ? parseMessage(data, transaction.integrityKey)\n : message;\n if (!verified) {\n log(\"STUN over TURN response failed MESSAGE-INTEGRITY check\");\n return;\n }\n transaction.responseReceived(verified, addr);\n }\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 async request(\n request: Message,\n addr: Address,\n integrityKey?: Buffer,\n retransmissionsOrOptions?: number | TransactionRequestOptions,\n onRequestSent?: (attempt: number) => void,\n ) {\n if (this.turn.transactions[request.transactionIdHex]) {\n throw new Error(\"exist\");\n }\n\n if (integrityKey) {\n request.addMessageIntegrity(integrityKey);\n request.addFingerprint();\n }\n\n // Peer-facing STUN over TURN must honor retransmissions/responseTimeout\n // (consent uses retransmissions: 0). Do not confuse with TURN server\n // allocation/refresh policy on TurnProtocol.\n // Peer addresses are already IPs from candidates; resolve for safety.\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.turn.transactions[request.transactionIdHex] = transaction;\n\n try {\n return await transaction.run();\n } catch (e) {\n throw e;\n } finally {\n delete this.turn.transactions[request.transactionIdHex];\n }\n }\n async connectionMade() {}\n async sendData(data: Buffer, addr: Address) {\n await this.turn.sendData(data, addr);\n }\n async sendStun(message: Message, addr: Address) {\n await this.turn.sendData(message.bytes, addr);\n }\n async close() {\n this.disposer.dispose();\n return this.turn.close();\n }\n}\n\nexport class TurnProtocol implements Protocol {\n static type = \"turn\";\n readonly type = TurnProtocol.type;\n readonly onData = new Event<[Buffer, Address]>();\n onRequestReceived: Event<[Message, Address, Buffer]> = new Event();\n onDataReceived: Event<[Buffer]> = new Event();\n integrityKey?: Buffer;\n nonce?: Buffer;\n realm?: string;\n relayedAddress!: Address;\n mappedAddress!: Address;\n localCandidate!: Candidate;\n transactions: { [hexId: string]: Transaction } = {};\n private refreshHandle?: Cancelable<void>;\n private channelNumber = 0x4000;\n private channelByAddr: { [key: string]: TurnChannel } = {};\n private addrByChannel: { [channel: number]: Address } = {};\n /**sec */\n private channelRefreshTime: number;\n /**\n * Serializes ChannelBind requests so allocation-wide auth state\n * (nonce/realm/integrityKey) is not updated concurrently. Rejections\n * must not poison this tail — see channelBindQueue assignment sites.\n */\n private channelBindQueue: Promise<void> = Promise.resolve();\n /** In-flight ChannelBind per peer transport address (dedupe concurrent). */\n private channelBindingByAddr = new Map<string, Promise<TurnChannel>>();\n private tcpBuffer: Buffer = Buffer.alloc(0);\n /** Permission cache keyed by peer IP only (RFC 8656). */\n private permissionByAddr: { [peerIp: string]: boolean } = {};\n /**\n * Serializes CreatePermission requests (auth state race avoidance).\n * Rejections must not poison this tail.\n */\n private permissionQueue: Promise<void> = Promise.resolve();\n /** In-flight CreatePermission per peer IP (dedupe concurrent). */\n private creatingPermissionByAddr = new Map<string, Promise<void>>();\n\n constructor(\n public server: Address,\n public username: string,\n public password: string,\n public lifetime: number,\n public transport: Transport,\n public options: {\n /**sec */\n channelRefreshTime?: number;\n } = {},\n ) {\n this.channelRefreshTime =\n this.options.channelRefreshTime ?? DEFAULT_CHANNEL_REFRESH_TIME;\n }\n\n async connectionMade() {\n this.transport.onData = (data, addr) => {\n this.dataReceived(data, addr);\n };\n\n const request = new Message(methods.ALLOCATE, classes.REQUEST);\n request\n .setAttribute(\"LIFETIME\", this.lifetime)\n .setAttribute(\"REQUESTED-TRANSPORT\", UDP_TRANSPORT);\n\n const [response] = await this.requestWithRetry(request, this.server).catch(\n (e) => {\n log(\"connect error\", e);\n throw e;\n },\n );\n this.relayedAddress = response.getAttributeValue(\"XOR-RELAYED-ADDRESS\");\n this.mappedAddress = response.getAttributeValue(\"XOR-MAPPED-ADDRESS\");\n const exp = response.getAttributeValue(\"LIFETIME\");\n log(\"connect\", this.relayedAddress, this.mappedAddress, { exp });\n\n this.refresh(exp);\n }\n\n private handleChannelData(data: Buffer) {\n const decoded = decodeChannelData(data);\n const addr = decoded && this.addrByChannel[decoded.channelNumber];\n\n if (addr && decoded) {\n this.onData.execute(decoded.data, addr);\n }\n }\n\n private handleSTUNMessage(data: Buffer, addr: Address) {\n try {\n const message = parseMessage(data);\n if (!message) {\n throw new Error(\"not stun message\");\n }\n\n if (\n message.messageClass === classes.RESPONSE ||\n message.messageClass === classes.ERROR\n ) {\n const transaction = this.transactions[message.transactionIdHex];\n if (transaction) {\n const verified = transaction.integrityKey\n ? parseMessage(data, transaction.integrityKey)\n : message;\n if (!verified) {\n log(\"TURN STUN response failed MESSAGE-INTEGRITY check\");\n return;\n }\n transaction.responseReceived(verified, addr);\n }\n } else if (message.messageClass === classes.REQUEST) {\n this.onData.execute(data, addr);\n }\n\n if (message.getAttributeValue(\"DATA\")) {\n const buf: Buffer = message.getAttributeValue(\"DATA\");\n const peerAddress =\n message.getAttributeValue(\"XOR-PEER-ADDRESS\") ?? addr;\n this.onData.execute(buf, peerAddress);\n }\n } catch (error) {\n log(\"parse error\", data.toString());\n }\n }\n\n private dataReceived(data: Buffer, addr: Address) {\n const datagramReceived = (data: Buffer, addr: Address) => {\n if (data.length >= 4 && isChannelData(data)) {\n this.handleChannelData(data);\n } else {\n this.handleSTUNMessage(data, addr);\n }\n };\n\n if (isStreamTransport(this.transport)) {\n this.tcpBuffer = Buffer.concat([this.tcpBuffer, data]);\n const { frames, rest } = splitTurnTcpFrames(this.tcpBuffer);\n this.tcpBuffer = rest;\n for (const frame of frames) {\n datagramReceived(frame, addr);\n }\n } else {\n datagramReceived(data, addr);\n }\n }\n\n private async send(data: Buffer, addr: Address) {\n if (this.transport.closed) {\n return;\n }\n\n await this.transport.send(\n isStreamTransport(this.transport) ? padTurnFrame(data) : data,\n addr,\n );\n }\n\n private async createPermission(peerAddress: Address) {\n const request = new Message(methods.CREATE_PERMISSION, classes.REQUEST);\n request\n .setAttribute(\"XOR-PEER-ADDRESS\", peerAddress)\n .setAttribute(\"USERNAME\", this.username)\n .setAttribute(\"REALM\", this.realm)\n .setAttribute(\"NONCE\", this.nonce);\n // Use requestWithRetry for stale-nonce (438) consistency with ChannelBind.\n await this.requestWithRetry(request, this.server);\n }\n\n private refresh = (exp: number) => {\n this.refreshHandle = cancelable<void>(async (_, __, onCancel) => {\n let run = true;\n onCancel.once(() => {\n run = false;\n });\n\n while (run) {\n // refresh before expire\n const delay = (5 / 6) * exp * 1000;\n log(\"refresh delay\", delay, { exp });\n await setTimeout(delay);\n\n const request = new Message(methods.REFRESH, classes.REQUEST);\n request.setAttribute(\"LIFETIME\", exp);\n\n try {\n const [message] = await this.requestWithRetry(request, this.server);\n exp = message.getAttributeValue(\"LIFETIME\");\n log(\"refresh\", { exp });\n } catch (error) {\n log(\"refresh error\", error);\n }\n }\n });\n };\n\n async request(\n request: Message,\n addr: Address,\n _integrityKey?: Buffer,\n retransmissionsOrOptions?: number | TransactionRequestOptions,\n onRequestSent?: (attempt: number) => void,\n ): Promise<[Message, Address]> {\n if (this.transactions[request.transactionIdHex]) {\n throw new Error(\"exist\");\n }\n if (this.integrityKey) {\n request\n .setAttribute(\"USERNAME\", this.username)\n .setAttribute(\"REALM\", this.realm)\n .setAttribute(\"NONCE\", this.nonce)\n .addMessageIntegrity(this.integrityKey)\n .addFingerprint();\n }\n\n // TURN server allocation/refresh uses default STUN retry policy unless\n // callers pass explicit options. Peer consent goes through StunOverTurnProtocol.\n // Prefer the TURN session integrity key for response verification.\n const resolvedAddr = await resolveRequestAddress(addr);\n const options = buildTransactionOptions(\n this.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 } catch (e) {\n throw e;\n } finally {\n delete this.transactions[request.transactionIdHex];\n }\n }\n\n async requestWithRetry(\n request: Message,\n addr: Address,\n ): Promise<[Message, Address]> {\n let message: Message, address: Address;\n try {\n [message, address] = await this.request(request, addr);\n } catch (error) {\n if (error instanceof TransactionFailed == false) {\n log(\"requestWithRetry error\", error);\n throw error;\n }\n\n // resolve dns address\n this.server = error.addr;\n\n const [errorCode] = error.response.getAttributeValue(\"ERROR-CODE\");\n const nonce = error.response.getAttributeValue(\"NONCE\");\n const realm = error.response.getAttributeValue(\"REALM\");\n\n if (\n ((errorCode === 401 && realm) || (errorCode === 438 && this.realm)) &&\n nonce\n ) {\n log(\"retry with nonce\", errorCode);\n\n this.nonce = nonce;\n if (errorCode === 401) {\n this.realm = realm;\n }\n this.integrityKey = makeIntegrityKey(\n this.username,\n this.realm!,\n this.password,\n );\n\n request.transactionId = randomTransactionId();\n [message, address] = await this.request(request, this.server);\n } else {\n throw error;\n }\n }\n return [message!, address!];\n }\n\n async sendData(data: Buffer, addr: Address) {\n let channel: TurnChannel | undefined;\n try {\n channel = await this.getChannel(addr);\n } catch (e) {\n // Keep original ChannelBind error for diagnostics (403/438/timeout).\n log(\"channelBind error; falling back to Send Indication\", e);\n }\n\n if (!channel) {\n await this.getPermission(addr);\n const indicate = new Message(methods.SEND, classes.INDICATION)\n .setAttribute(\"DATA\", data)\n .setAttribute(\"XOR-PEER-ADDRESS\", addr);\n\n await this.sendStun(indicate, this.server);\n return;\n }\n\n await this.send(encodeChannelData(channel.number, data), this.server);\n }\n\n /**\n * Ensure a CreatePermission exists for the peer IP.\n * Peer failures are isolated: a rejection for peer A does not poison peer B.\n */\n async getPermission(addr: Address) {\n const key = permissionKey(addr);\n\n if (this.permissionByAddr[key]) {\n return;\n }\n\n const existing = this.creatingPermissionByAddr.get(key);\n if (existing) {\n return existing;\n }\n\n const operation = this.permissionQueue.then(async () => {\n // Another caller may have succeeded while we waited on the queue.\n if (this.permissionByAddr[key]) {\n return;\n }\n\n await this.createPermission(addr);\n // Cache only after successful CreatePermission.\n this.permissionByAddr[key] = true;\n });\n\n // Do not let rejection poison subsequent peers on the shared queue.\n this.permissionQueue = operation.then(\n () => undefined,\n () => undefined,\n );\n\n this.creatingPermissionByAddr.set(key, operation);\n\n try {\n await operation;\n } catch (error) {\n log(\"createPermission error\", error);\n throw error;\n } finally {\n if (this.creatingPermissionByAddr.get(key) === operation) {\n this.creatingPermissionByAddr.delete(key);\n }\n }\n }\n\n /**\n * Ensure a ChannelBind exists for the peer transport address.\n * Peer failures are isolated; concurrent same-peer calls share one Promise.\n */\n async getChannel(addr: Address): Promise<TurnChannel> {\n const key = channelKey(addr);\n\n const existing = this.channelBindingByAddr.get(key);\n if (existing) {\n return existing;\n }\n\n // Fast path: bound and not due for refresh.\n const cached = this.channelByAddr[key];\n const now = int(Date.now() / 1000);\n if (cached && cached.refreshAt > now) {\n return cached;\n }\n\n const operation = this.channelBindQueue.then(() =>\n this.ensureChannel(addr),\n );\n\n // Do not let rejection poison subsequent peers on the shared queue.\n this.channelBindQueue = operation.then(\n () => undefined,\n () => undefined,\n );\n\n this.channelBindingByAddr.set(key, operation);\n\n try {\n return await operation;\n } catch (error) {\n log(\"channelBind error\", error);\n throw error;\n } finally {\n if (this.channelBindingByAddr.get(key) === operation) {\n this.channelBindingByAddr.delete(key);\n }\n }\n }\n\n /**\n * Create or refresh a channel for addr. Provisional mapping is installed\n * before the request so early ChannelData can be decoded; only a failed\n * *initial* bind rolls the mapping back. Failed channel numbers are never\n * reused.\n */\n private async ensureChannel(addr: Address): Promise<TurnChannel> {\n const key = channelKey(addr);\n const now = int(Date.now() / 1000);\n\n let channel = this.channelByAddr[key];\n if (channel && channel.refreshAt > now) {\n return channel;\n }\n\n const isNew = !channel;\n\n if (!channel) {\n channel = {\n number: this.channelNumber++,\n address: addr,\n refreshAt: 0,\n };\n // Provisional mapping for ChannelData that may arrive before success.\n this.channelByAddr[key] = channel;\n this.addrByChannel[channel.number] = addr;\n }\n\n try {\n await this.channelBind(channel.number, addr);\n channel.refreshAt = int(Date.now() / 1000) + this.channelRefreshTime;\n log(isNew ? \"channelBind\" : \"channelBind refresh\", channel);\n return channel;\n } catch (error) {\n if (isNew) {\n // Roll back provisional mapping only for a failed initial bind.\n delete this.channelByAddr[key];\n delete this.addrByChannel[channel.number];\n // Do not reuse the channel number (no channelNumber--).\n }\n throw error;\n }\n }\n\n private async channelBind(channelNumber: number, addr: Address) {\n const request = new Message(methods.CHANNEL_BIND, classes.REQUEST);\n request\n .setAttribute(\"CHANNEL-NUMBER\", channelNumber)\n .setAttribute(\"XOR-PEER-ADDRESS\", addr);\n const [response] = await this.requestWithRetry(request, this.server);\n if (response.messageMethod !== methods.CHANNEL_BIND) {\n throw new Error(\"should be CHANNEL_BIND\");\n }\n }\n\n async sendStun(message: Message, addr: Address) {\n await this.send(message.bytes, addr);\n }\n\n async close() {\n this.refreshHandle?.resolve?.();\n await this.transport.close();\n }\n}\n\nexport interface TurnClientConfig {\n address: Address;\n username: string;\n password: string;\n}\nexport interface TurnClientOptions {\n lifetime?: number;\n ssl?: boolean;\n transport?: \"udp\" | \"tcp\" | \"tls\";\n tlsOptions?: TlsConnectionOptions;\n portRange?: [number, number];\n interfaceAddresses?: InterfaceAddresses;\n}\n\nexport async function createTurnClient(\n { address, username, password }: TurnClientConfig,\n {\n lifetime,\n portRange,\n interfaceAddresses,\n ssl,\n tlsOptions,\n transport: transportType,\n }: TurnClientOptions = {},\n) {\n lifetime ??= DEFAULT_ALLOCATION_LIFETIME;\n transportType ??= ssl ? \"tls\" : \"udp\";\n\n const transport =\n transportType === \"udp\"\n ? await UdpTransport.init(\"udp4\", { portRange, interfaceAddresses })\n : transportType === \"tcp\"\n ? await TcpTransport.init(address)\n : await TlsTransport.init(address, tlsOptions);\n\n const turn = new TurnProtocol(\n address,\n username,\n password,\n lifetime,\n transport,\n );\n\n await turn.connectionMade();\n return turn;\n}\n\nexport async function createStunOverTurnClient(\n {\n address,\n username,\n password,\n }: {\n address: Address;\n username: string;\n password: string;\n },\n {\n lifetime,\n portRange,\n interfaceAddresses,\n ssl,\n tlsOptions,\n transport: transportType,\n }: {\n lifetime?: number;\n ssl?: boolean;\n transport?: \"udp\" | \"tcp\" | \"tls\";\n tlsOptions?: TlsConnectionOptions;\n portRange?: [number, number];\n interfaceAddresses?: InterfaceAddresses;\n } = {},\n) {\n const turn = await createTurnClient(\n {\n address,\n username,\n password,\n },\n {\n lifetime,\n portRange,\n interfaceAddresses,\n ssl,\n tlsOptions,\n transport: transportType,\n },\n );\n const turnTransport = new StunOverTurnProtocol(turn);\n return turnTransport;\n}\n\nexport function makeIntegrityKey(\n username: string,\n realm: string,\n password: string,\n) {\n return makeTurnIntegrityKey(username, realm, password);\n}\n"]}
|
|
1
|
+
{"version":3,"file":"protocol.js","sourceRoot":"","sources":["../../../../../ice/src/turn/protocol.ts"],"names":[],"mappings":"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","sourcesContent":["import { isIP } from \"node:net\";\nimport { setTimeout } from \"timers/promises\";\n\nimport { makeTurnIntegrityKey } from \"../../../ice-server/src/turn/auth\";\nimport type { Candidate } from \"../candidate\";\nimport { TransactionFailed } from \"../exceptions\";\nimport { type Cancelable, cancelable, randomTransactionId } from \"../helper\";\nimport {\n type Address,\n Event,\n EventDisposer,\n type InterfaceAddresses,\n TcpTransport,\n type TlsConnectionOptions,\n TlsTransport,\n type Transport,\n UdpTransport,\n bufferReader,\n debug,\n int,\n} from \"../imports/common\";\nimport { classes, methods } from \"../stun/const\";\nimport { Message, paddingLength, parseMessage } from \"../stun/message\";\nimport {\n Transaction,\n addressEquals,\n buildTransactionOptions,\n resolveRequestAddress,\n} from \"../stun/transaction\";\nimport type { Protocol, TransactionRequestOptions } from \"../types/model\";\nimport {\n decodeChannelData,\n encodeChannelData,\n isChannelData,\n padTurnFrame,\n splitTurnTcpFrames,\n} from \"./frame\";\n\nconst log = debug(\"werift-ice:packages/ice/src/turn/protocol.ts\");\n\nconst DEFAULT_CHANNEL_REFRESH_TIME = 500;\nconst DEFAULT_ALLOCATION_LIFETIME = 600;\nconst UDP_TRANSPORT = 0x11000000;\n\n/** Channel binding state for a single peer transport address. */\nexport interface TurnChannel {\n number: number;\n address: Address;\n /** Unix seconds when this channel should be refreshed. */\n refreshAt: number;\n}\n\nfunction isStreamTransport(transport: Transport) {\n return transport.type === \"tcp\" || transport.type === \"tls\";\n}\n\n/** Permission is peer-IP scoped (RFC 8656). */\nfunction permissionKey(addr: Address): string {\n return addr[0];\n}\n\n/** ChannelBind is peer transport-address scoped (IP + port). */\nfunction channelKey(addr: Address): string {\n return JSON.stringify(addr);\n}\n\nexport class StunOverTurnProtocol implements Protocol {\n static type = \"turn\";\n readonly type = StunOverTurnProtocol.type;\n localCandidate!: Candidate;\n private disposer = new EventDisposer();\n onRequestReceived: Event<[Message, Address, Buffer]> = new Event();\n onDataReceived: Event<[Buffer]> = new Event();\n\n constructor(public turn: TurnProtocol) {\n turn.onData\n .subscribe((data, addr) => {\n this.handleStunMessage(data, addr);\n })\n .disposer(this.disposer);\n }\n\n private handleStunMessage = (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 ) {\n const transaction = this.turn.transactions[message.transactionIdHex];\n if (transaction) {\n const verified = transaction.integrityKey\n ? parseMessage(data, transaction.integrityKey)\n : message;\n if (!verified) {\n log(\"STUN over TURN response failed MESSAGE-INTEGRITY check\");\n return;\n }\n transaction.responseReceived(verified, addr);\n }\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 async request(\n request: Message,\n addr: Address,\n integrityKey?: Buffer,\n retransmissionsOrOptions?: number | TransactionRequestOptions,\n onRequestSent?: (attempt: number) => void,\n ) {\n if (this.turn.transactions[request.transactionIdHex]) {\n throw new Error(\"exist\");\n }\n\n if (integrityKey) {\n request.addMessageIntegrity(integrityKey);\n request.addFingerprint();\n }\n\n // Peer-facing STUN over TURN must honor retransmissions/responseTimeout\n // (consent uses retransmissions: 0). Do not confuse with TURN server\n // allocation/refresh policy on TurnProtocol.\n // Peer addresses are already IPs from candidates; resolve for safety.\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.turn.transactions[request.transactionIdHex] = transaction;\n\n try {\n return await transaction.run();\n } catch (e) {\n throw e;\n } finally {\n delete this.turn.transactions[request.transactionIdHex];\n }\n }\n async connectionMade() {}\n async sendData(data: Buffer, addr: Address) {\n await this.turn.sendData(data, addr);\n }\n async sendStun(message: Message, addr: Address) {\n await this.turn.sendData(message.bytes, addr);\n }\n async close() {\n this.disposer.dispose();\n return this.turn.close();\n }\n}\n\nexport class TurnProtocol implements Protocol {\n static type = \"turn\";\n readonly type = TurnProtocol.type;\n readonly onData = new Event<[Buffer, Address]>();\n onRequestReceived: Event<[Message, Address, Buffer]> = new Event();\n onDataReceived: Event<[Buffer]> = new Event();\n integrityKey?: Buffer;\n nonce?: Buffer;\n realm?: string;\n relayedAddress!: Address;\n mappedAddress!: Address;\n localCandidate!: Candidate;\n transactions: { [hexId: string]: Transaction } = {};\n private refreshHandle?: Cancelable<void>;\n private channelNumber = 0x4000;\n private channelByAddr: { [key: string]: TurnChannel } = {};\n private addrByChannel: { [channel: number]: Address } = {};\n /**sec */\n private channelRefreshTime: number;\n /**\n * Serializes ChannelBind requests so allocation-wide auth state\n * (nonce/realm/integrityKey) is not updated concurrently. Rejections\n * must not poison this tail — see channelBindQueue assignment sites.\n */\n private channelBindQueue: Promise<void> = Promise.resolve();\n /** In-flight ChannelBind per peer transport address (dedupe concurrent). */\n private channelBindingByAddr = new Map<string, Promise<TurnChannel>>();\n private tcpBuffer: Buffer = Buffer.alloc(0);\n /** Permission cache keyed by peer IP only (RFC 8656). */\n private permissionByAddr: { [peerIp: string]: boolean } = {};\n /**\n * Serializes CreatePermission requests (auth state race avoidance).\n * Rejections must not poison this tail.\n */\n private permissionQueue: Promise<void> = Promise.resolve();\n /** In-flight CreatePermission per peer IP (dedupe concurrent). */\n private creatingPermissionByAddr = new Map<string, Promise<void>>();\n /** Concrete TURN server address the allocation lives on, once selected. */\n private pinnedServerEndpoint?: Address;\n private serverEndpointSelection?: Promise<Address>;\n\n constructor(\n /** TURN server as configured; the host may be a hostname. */\n public server: Address,\n public username: string,\n public password: string,\n public lifetime: number,\n public transport: Transport,\n public options: {\n /**sec */\n channelRefreshTime?: number;\n } = {},\n ) {\n this.channelRefreshTime =\n this.options.channelRefreshTime ?? DEFAULT_CHANNEL_REFRESH_TIME;\n }\n\n async connectionMade() {\n this.transport.onData = (data, addr) => {\n this.dataReceived(data, addr);\n };\n\n const request = new Message(methods.ALLOCATE, classes.REQUEST);\n request\n .setAttribute(\"LIFETIME\", this.lifetime)\n .setAttribute(\"REQUESTED-TRANSPORT\", UDP_TRANSPORT);\n\n const [response] = await this.requestWithRetry(request, this.server).catch(\n (e) => {\n log(\"connect error\", e);\n throw e;\n },\n );\n this.relayedAddress = response.getAttributeValue(\"XOR-RELAYED-ADDRESS\");\n this.mappedAddress = response.getAttributeValue(\"XOR-MAPPED-ADDRESS\");\n const exp = response.getAttributeValue(\"LIFETIME\");\n log(\"connect\", this.relayedAddress, this.mappedAddress, { exp });\n\n this.refresh(exp);\n }\n\n private handleChannelData(data: Buffer) {\n const decoded = decodeChannelData(data);\n const addr = decoded && this.addrByChannel[decoded.channelNumber];\n\n if (addr && decoded) {\n this.onData.execute(decoded.data, addr);\n }\n }\n\n private handleSTUNMessage(data: Buffer, addr: Address) {\n try {\n const message = parseMessage(data);\n if (!message) {\n throw new Error(\"not stun message\");\n }\n\n if (\n message.messageClass === classes.RESPONSE ||\n message.messageClass === classes.ERROR\n ) {\n const transaction = this.transactions[message.transactionIdHex];\n if (transaction) {\n const verified = transaction.integrityKey\n ? parseMessage(data, transaction.integrityKey)\n : message;\n if (!verified) {\n log(\"TURN STUN response failed MESSAGE-INTEGRITY check\");\n return;\n }\n transaction.responseReceived(verified, addr);\n }\n } else if (message.messageClass === classes.REQUEST) {\n this.onData.execute(data, addr);\n }\n\n if (message.getAttributeValue(\"DATA\")) {\n const buf: Buffer = message.getAttributeValue(\"DATA\");\n const peerAddress =\n message.getAttributeValue(\"XOR-PEER-ADDRESS\") ?? addr;\n this.onData.execute(buf, peerAddress);\n }\n } catch (error) {\n log(\"parse error\", data.toString());\n }\n }\n\n private dataReceived(data: Buffer, addr: Address) {\n const datagramReceived = (data: Buffer, addr: Address) => {\n if (data.length >= 4 && isChannelData(data)) {\n this.handleChannelData(data);\n } else {\n this.handleSTUNMessage(data, addr);\n }\n };\n\n if (isStreamTransport(this.transport)) {\n this.tcpBuffer = Buffer.concat([this.tcpBuffer, data]);\n const { frames, rest } = splitTurnTcpFrames(this.tcpBuffer);\n this.tcpBuffer = rest;\n for (const frame of frames) {\n datagramReceived(frame, addr);\n }\n } else {\n datagramReceived(data, addr);\n }\n }\n\n private async send(data: Buffer, addr: Address) {\n if (this.transport.closed) {\n return;\n }\n\n await this.transport.send(\n isStreamTransport(this.transport) ? padTurnFrame(data) : data,\n addr,\n );\n }\n\n private async createPermission(peerAddress: Address) {\n const request = new Message(methods.CREATE_PERMISSION, classes.REQUEST);\n request\n .setAttribute(\"XOR-PEER-ADDRESS\", peerAddress)\n .setAttribute(\"USERNAME\", this.username)\n .setAttribute(\"REALM\", this.realm)\n .setAttribute(\"NONCE\", this.nonce);\n // Use requestWithRetry for stale-nonce (438) consistency with ChannelBind.\n await this.requestWithRetry(request, this.server);\n }\n\n private refresh = (exp: number) => {\n this.refreshHandle = cancelable<void>(async (_, __, onCancel) => {\n const abort = new AbortController();\n onCancel.once(() => {\n abort.abort();\n });\n\n while (!abort.signal.aborted) {\n // refresh before expire\n const delay = (5 / 6) * exp * 1000;\n log(\"refresh delay\", delay, { exp });\n try {\n await setTimeout(delay, undefined, { signal: abort.signal });\n } catch (error) {\n if (abort.signal.aborted) {\n return;\n }\n throw error;\n }\n\n if (abort.signal.aborted) {\n return;\n }\n\n const request = new Message(methods.REFRESH, classes.REQUEST);\n request.setAttribute(\"LIFETIME\", exp);\n\n try {\n const [message] = await this.requestWithRetry(\n request,\n this.server,\n abort.signal,\n );\n exp = message.getAttributeValue(\"LIFETIME\");\n log(\"refresh\", { exp });\n } catch (error) {\n if (abort.signal.aborted) {\n return;\n }\n log(\"refresh error\", error);\n }\n }\n });\n };\n\n async request(\n request: Message,\n addr: Address,\n _integrityKey?: Buffer,\n retransmissionsOrOptions?: number | TransactionRequestOptions,\n onRequestSent?: (attempt: number) => void,\n ): Promise<[Message, Address]> {\n if (this.transactions[request.transactionIdHex]) {\n throw new Error(\"exist\");\n }\n if (this.integrityKey) {\n request\n .setAttribute(\"USERNAME\", this.username)\n .setAttribute(\"REALM\", this.realm)\n .setAttribute(\"NONCE\", this.nonce)\n .addMessageIntegrity(this.integrityKey)\n .addFingerprint();\n }\n\n // TURN server allocation/refresh uses default STUN retry policy unless\n // callers pass explicit options. Peer consent goes through StunOverTurnProtocol.\n // Prefer the TURN session integrity key for response verification.\n const resolvedAddr = await this.resolveRequestTarget(addr);\n const options = buildTransactionOptions(\n this.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 } catch (e) {\n throw e;\n } finally {\n delete this.transactions[request.transactionIdHex];\n }\n }\n\n /**\n * The concrete TURN server address, selected on the first request and\n * pinned for the rest of the allocation, so a later DNS answer can never\n * move REFRESH, CREATE_PERMISSION, CHANNEL_BIND or data to another server.\n */\n get serverEndpoint(): Address | undefined {\n return this.pinnedServerEndpoint;\n }\n\n /**\n * Address a request to `addr` is sent to, and the address its response\n * must come from. A stream carries every request to the peer it is\n * connected to, so it always uses the server endpoint.\n */\n private async resolveRequestTarget(addr: Address): Promise<Address> {\n if (isStreamTransport(this.transport) || addressEquals(addr, this.server)) {\n return this.selectServerEndpoint();\n }\n return resolveRequestAddress(addr, this.transport.addressFamily ?? 0);\n }\n\n private async serverDestination(): Promise<Address> {\n return this.pinnedServerEndpoint ?? this.selectServerEndpoint();\n }\n\n private selectServerEndpoint(): Promise<Address> {\n this.serverEndpointSelection ??= this.resolveServerEndpoint().then(\n (endpoint) => {\n this.pinnedServerEndpoint = endpoint;\n return endpoint;\n },\n (error) => {\n // Let a later request try again, e.g. after a transient DNS failure.\n this.serverEndpointSelection = undefined;\n throw error;\n },\n );\n return this.serverEndpointSelection;\n }\n\n /**\n * UDP: resolve the configured server in the bound socket's family; a udp4\n * socket cannot send to an IPv6 answer. TCP/TLS: use the peer the socket\n * actually connected to. Looking the hostname up again could return a\n * different A/AAAA record, and responses from the real peer would then be\n * dropped as coming from an unexpected address.\n */\n private async resolveServerEndpoint(): Promise<Address> {\n const transport = this.transport;\n if (!isStreamTransport(transport)) {\n return resolveRequestAddress(this.server, transport.addressFamily ?? 0);\n }\n if (transport.remoteAddress) {\n return transport.remoteAddress;\n }\n if (\n transport instanceof TcpTransport ||\n transport instanceof TlsTransport\n ) {\n throw new Error(`${transport.type} transport has no remote address`);\n }\n // A custom stream transport that does not report its peer: fall back to\n // a lookup with no family preference.\n return resolveRequestAddress(this.server);\n }\n\n async requestWithRetry(\n request: Message,\n addr: Address,\n signal?: AbortSignal,\n ): Promise<[Message, Address]> {\n let message: Message, address: Address;\n try {\n [message, address] = await this.request(request, addr, undefined, {\n signal,\n });\n } catch (error) {\n if (error instanceof TransactionFailed == false) {\n log(\"requestWithRetry error\", error);\n throw error;\n }\n\n const [errorCode] = error.response.getAttributeValue(\"ERROR-CODE\");\n const nonce = error.response.getAttributeValue(\"NONCE\");\n const realm = error.response.getAttributeValue(\"REALM\");\n\n if (\n ((errorCode === 401 && realm) || (errorCode === 438 && this.realm)) &&\n nonce\n ) {\n log(\"retry with nonce\", errorCode);\n\n this.nonce = nonce;\n if (errorCode === 401) {\n this.realm = realm;\n }\n this.integrityKey = makeIntegrityKey(\n this.username,\n this.realm!,\n this.password,\n );\n\n request.transactionId = randomTransactionId();\n [message, address] = await this.request(\n request,\n this.server,\n undefined,\n { signal },\n );\n } else {\n throw error;\n }\n }\n return [message!, address!];\n }\n\n async sendData(data: Buffer, addr: Address) {\n let channel: TurnChannel | undefined;\n try {\n channel = await this.getChannel(addr);\n } catch (e) {\n // Keep original ChannelBind error for diagnostics (403/438/timeout).\n log(\"channelBind error; falling back to Send Indication\", e);\n }\n\n if (!channel) {\n await this.getPermission(addr);\n const indicate = new Message(methods.SEND, classes.INDICATION)\n .setAttribute(\"DATA\", data)\n .setAttribute(\"XOR-PEER-ADDRESS\", addr);\n\n await this.sendStun(indicate, await this.serverDestination());\n return;\n }\n\n await this.send(\n encodeChannelData(channel.number, data),\n await this.serverDestination(),\n );\n }\n\n /**\n * Ensure a CreatePermission exists for the peer IP.\n * Peer failures are isolated: a rejection for peer A does not poison peer B.\n */\n async getPermission(addr: Address) {\n const key = permissionKey(addr);\n\n if (this.permissionByAddr[key]) {\n return;\n }\n\n const existing = this.creatingPermissionByAddr.get(key);\n if (existing) {\n return existing;\n }\n\n const operation = this.permissionQueue.then(async () => {\n // Another caller may have succeeded while we waited on the queue.\n if (this.permissionByAddr[key]) {\n return;\n }\n\n await this.createPermission(addr);\n // Cache only after successful CreatePermission.\n this.permissionByAddr[key] = true;\n });\n\n // Do not let rejection poison subsequent peers on the shared queue.\n this.permissionQueue = operation.then(\n () => undefined,\n () => undefined,\n );\n\n this.creatingPermissionByAddr.set(key, operation);\n\n try {\n await operation;\n } catch (error) {\n log(\"createPermission error\", error);\n throw error;\n } finally {\n if (this.creatingPermissionByAddr.get(key) === operation) {\n this.creatingPermissionByAddr.delete(key);\n }\n }\n }\n\n /**\n * Ensure a ChannelBind exists for the peer transport address.\n * Peer failures are isolated; concurrent same-peer calls share one Promise.\n */\n async getChannel(addr: Address): Promise<TurnChannel> {\n const key = channelKey(addr);\n\n const existing = this.channelBindingByAddr.get(key);\n if (existing) {\n return existing;\n }\n\n // Fast path: bound and not due for refresh.\n const cached = this.channelByAddr[key];\n const now = int(Date.now() / 1000);\n if (cached && cached.refreshAt > now) {\n return cached;\n }\n\n const operation = this.channelBindQueue.then(() =>\n this.ensureChannel(addr),\n );\n\n // Do not let rejection poison subsequent peers on the shared queue.\n this.channelBindQueue = operation.then(\n () => undefined,\n () => undefined,\n );\n\n this.channelBindingByAddr.set(key, operation);\n\n try {\n return await operation;\n } catch (error) {\n log(\"channelBind error\", error);\n throw error;\n } finally {\n if (this.channelBindingByAddr.get(key) === operation) {\n this.channelBindingByAddr.delete(key);\n }\n }\n }\n\n /**\n * Create or refresh a channel for addr. Provisional mapping is installed\n * before the request so early ChannelData can be decoded; only a failed\n * *initial* bind rolls the mapping back. Failed channel numbers are never\n * reused.\n */\n private async ensureChannel(addr: Address): Promise<TurnChannel> {\n const key = channelKey(addr);\n const now = int(Date.now() / 1000);\n\n let channel = this.channelByAddr[key];\n if (channel && channel.refreshAt > now) {\n return channel;\n }\n\n const isNew = !channel;\n\n if (!channel) {\n channel = {\n number: this.channelNumber++,\n address: addr,\n refreshAt: 0,\n };\n // Provisional mapping for ChannelData that may arrive before success.\n this.channelByAddr[key] = channel;\n this.addrByChannel[channel.number] = addr;\n }\n\n try {\n await this.channelBind(channel.number, addr);\n channel.refreshAt = int(Date.now() / 1000) + this.channelRefreshTime;\n log(isNew ? \"channelBind\" : \"channelBind refresh\", channel);\n return channel;\n } catch (error) {\n if (isNew) {\n // Roll back provisional mapping only for a failed initial bind.\n delete this.channelByAddr[key];\n delete this.addrByChannel[channel.number];\n // Do not reuse the channel number (no channelNumber--).\n }\n throw error;\n }\n }\n\n private async channelBind(channelNumber: number, addr: Address) {\n const request = new Message(methods.CHANNEL_BIND, classes.REQUEST);\n request\n .setAttribute(\"CHANNEL-NUMBER\", channelNumber)\n .setAttribute(\"XOR-PEER-ADDRESS\", addr);\n const [response] = await this.requestWithRetry(request, this.server);\n if (response.messageMethod !== methods.CHANNEL_BIND) {\n throw new Error(\"should be CHANNEL_BIND\");\n }\n }\n\n async sendStun(message: Message, addr: Address) {\n await this.send(message.bytes, addr);\n }\n\n async close() {\n this.refreshHandle?.resolve?.();\n await this.transport.close();\n }\n}\n\nexport interface TurnClientConfig {\n address: Address;\n username: string;\n password: string;\n}\nexport interface TurnClientOptions {\n lifetime?: number;\n ssl?: boolean;\n transport?: \"udp\" | \"tcp\" | \"tls\";\n tlsOptions?: TlsConnectionOptions;\n portRange?: [number, number];\n interfaceAddresses?: InterfaceAddresses;\n /** Maximum time to wait for TCP/TLS connection establishment, in milliseconds. */\n connectTimeoutMs?: number;\n /**\n * Preferred IP family of the UDP socket, applied only when the server\n * address is a hostname. Ignored for an IP literal server address, whose\n * own family always selects the socket. Defaults to 4.\n */\n udpFamily?: 4 | 6;\n}\n\n/**\n * Select the UDP socket type for a TURN server.\n * Precedence: IP literal family > udpFamily > 4.\n * An IP literal fixes the destination family, so a conflicting udpFamily is\n * ignored (and logged) rather than making the server unreachable.\n */\nfunction selectTurnUdpSocketType(\n address: Address,\n udpFamily: 4 | 6 | undefined,\n): \"udp4\" | \"udp6\" {\n const literalFamily = isIP(address[0]);\n if (literalFamily === 4 || literalFamily === 6) {\n if (udpFamily && udpFamily !== literalFamily) {\n log(\"udpFamily ignored for IP literal TURN server\", {\n address,\n udpFamily,\n literalFamily,\n });\n }\n return literalFamily === 6 ? \"udp6\" : \"udp4\";\n }\n return (udpFamily ?? 4) === 6 ? \"udp6\" : \"udp4\";\n}\n\nexport async function createTurnClient(\n { address, username, password }: TurnClientConfig,\n {\n lifetime,\n portRange,\n interfaceAddresses,\n ssl,\n tlsOptions,\n transport: transportType,\n connectTimeoutMs,\n udpFamily,\n }: TurnClientOptions = {},\n) {\n lifetime ??= DEFAULT_ALLOCATION_LIFETIME;\n transportType ??= ssl ? \"tls\" : \"udp\";\n const transport =\n transportType === \"udp\"\n ? await UdpTransport.init(selectTurnUdpSocketType(address, udpFamily), {\n portRange,\n interfaceAddresses,\n })\n : transportType === \"tcp\"\n ? await TcpTransport.init(address, { connectTimeoutMs })\n : await TlsTransport.init(address, tlsOptions, { connectTimeoutMs });\n\n const turn = new TurnProtocol(\n address,\n username,\n password,\n lifetime,\n transport,\n );\n\n try {\n await turn.connectionMade();\n } catch (error) {\n try {\n await turn.close();\n } catch (closeError) {\n log(\"failed to close TURN client after allocation failure\", closeError);\n }\n throw error;\n }\n return turn;\n}\n\nexport async function createStunOverTurnClient(\n config: TurnClientConfig,\n options: TurnClientOptions = {},\n) {\n const turn = await createTurnClient(config, options);\n const turnTransport = new StunOverTurnProtocol(turn);\n return turnTransport;\n}\n\nexport function makeIntegrityKey(\n username: string,\n realm: string,\n password: string,\n) {\n return makeTurnIntegrityKey(username, realm, password);\n}\n"]}
|
|
@@ -19,6 +19,12 @@ export interface TransactionRequestOptions {
|
|
|
19
19
|
onRequestSent?: (attempt: number) => void;
|
|
20
20
|
/** Abort the outstanding transaction (e.g. consent lifecycle teardown). */
|
|
21
21
|
signal?: AbortSignal;
|
|
22
|
+
/**
|
|
23
|
+
* Fail the transaction as soon as the request cannot be sent instead of
|
|
24
|
+
* waiting for the response timeout. Used on reliable transports (TCP),
|
|
25
|
+
* where a send error means the connection itself is unusable.
|
|
26
|
+
*/
|
|
27
|
+
failOnSendError?: boolean;
|
|
22
28
|
/**
|
|
23
29
|
* When set, responses must include MESSAGE-INTEGRITY and pass HMAC
|
|
24
30
|
* verification (protocol re-parses the wire bytes with this key; the
|
|
@@ -31,6 +37,8 @@ export interface Protocol {
|
|
|
31
37
|
type: string;
|
|
32
38
|
onRequestReceived: Event<[Message, Address, Buffer]>;
|
|
33
39
|
onDataReceived: Event<[Buffer]>;
|
|
40
|
+
/** Connection-oriented protocols: the connection to this remote address is gone. */
|
|
41
|
+
onConnectionClosed?: Event<[Address]>;
|
|
34
42
|
request: (message: Message, addr: Address, integrityKey?: Buffer, retransmissionsOrOptions?: number | TransactionRequestOptions, onRequestSent?: (attempt: number) => void) => Promise<[Message, Address]>;
|
|
35
43
|
close: () => Promise<void>;
|
|
36
44
|
connectionMade: (...args: any) => Promise<void>;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"model.js","sourceRoot":"","sources":["../../../../../ice/src/types/model.ts"],"names":[],"mappings":"","sourcesContent":["import type { Candidate } from \"../candidate\";\nimport type { Address, Event } from \"../imports/common\";\nimport type { Message } from \"../stun/message\";\n\n/**\n * Options for a STUN transaction / Protocol.request.\n * Retransmission count and response wait deadline are independent\n * so consent freshness (retransmissions: 0, longer timeout) can be expressed.\n */\nexport interface TransactionRequestOptions {\n /** Number of retransmissions after the initial send. 0 = send once. */\n retransmissions?: number;\n /**\n * Initial response wait deadline in milliseconds.\n * Doubled after each retransmission when retransmissions > 0.\n * Defaults to RETRY_RTO when omitted.\n */\n responseTimeout?: number;\n /** Called for each wire send (attempt 0 is the initial transmission). */\n onRequestSent?: (attempt: number) => void;\n /** Abort the outstanding transaction (e.g. consent lifecycle teardown). */\n signal?: AbortSignal;\n /**\n * When set, responses must include MESSAGE-INTEGRITY and pass HMAC\n * verification (protocol re-parses the wire bytes with this key; the\n * transaction also rejects unsigned Messages as defense-in-depth).\n * Unsigned or forged responses must not complete the transaction.\n */\n integrityKey?: Buffer;\n}\n\nexport interface Protocol {\n type: string;\n onRequestReceived: Event<[Message, Address, Buffer]>;\n onDataReceived: Event<[Buffer]>;\n request: (\n message: Message,\n addr: Address,\n integrityKey?: Buffer,\n retransmissionsOrOptions?: number | TransactionRequestOptions,\n onRequestSent?: (attempt: number) => void,\n ) => Promise<[Message, Address]>;\n close: () => Promise<void>;\n connectionMade: (...args: any) => Promise<void>;\n sendStun: (message: Message, addr: Address) => Promise<void>;\n sendData: (data: Buffer, addr: Address) => Promise<void>;\n localCandidate?: Candidate;\n sentMessage?: Message;\n responseAddr?: Address;\n responseMessage?: string;\n localIp?: string;\n}\n"]}
|
|
1
|
+
{"version":3,"file":"model.js","sourceRoot":"","sources":["../../../../../ice/src/types/model.ts"],"names":[],"mappings":"","sourcesContent":["import type { Candidate } from \"../candidate\";\nimport type { Address, Event } from \"../imports/common\";\nimport type { Message } from \"../stun/message\";\n\n/**\n * Options for a STUN transaction / Protocol.request.\n * Retransmission count and response wait deadline are independent\n * so consent freshness (retransmissions: 0, longer timeout) can be expressed.\n */\nexport interface TransactionRequestOptions {\n /** Number of retransmissions after the initial send. 0 = send once. */\n retransmissions?: number;\n /**\n * Initial response wait deadline in milliseconds.\n * Doubled after each retransmission when retransmissions > 0.\n * Defaults to RETRY_RTO when omitted.\n */\n responseTimeout?: number;\n /** Called for each wire send (attempt 0 is the initial transmission). */\n onRequestSent?: (attempt: number) => void;\n /** Abort the outstanding transaction (e.g. consent lifecycle teardown). */\n signal?: AbortSignal;\n /**\n * Fail the transaction as soon as the request cannot be sent instead of\n * waiting for the response timeout. Used on reliable transports (TCP),\n * where a send error means the connection itself is unusable.\n */\n failOnSendError?: boolean;\n /**\n * When set, responses must include MESSAGE-INTEGRITY and pass HMAC\n * verification (protocol re-parses the wire bytes with this key; the\n * transaction also rejects unsigned Messages as defense-in-depth).\n * Unsigned or forged responses must not complete the transaction.\n */\n integrityKey?: Buffer;\n}\n\nexport interface Protocol {\n type: string;\n onRequestReceived: Event<[Message, Address, Buffer]>;\n onDataReceived: Event<[Buffer]>;\n /** Connection-oriented protocols: the connection to this remote address is gone. */\n onConnectionClosed?: Event<[Address]>;\n request: (\n message: Message,\n addr: Address,\n integrityKey?: Buffer,\n retransmissionsOrOptions?: number | TransactionRequestOptions,\n onRequestSent?: (attempt: number) => void,\n ) => Promise<[Message, Address]>;\n close: () => Promise<void>;\n connectionMade: (...args: any) => Promise<void>;\n sendStun: (message: Message, addr: Address) => Promise<void>;\n sendData: (data: Buffer, addr: Address) => Promise<void>;\n localCandidate?: Candidate;\n sentMessage?: Message;\n responseAddr?: Address;\n responseMessage?: string;\n localIp?: string;\n}\n"]}
|