werift 0.24.4 → 0.25.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
|
@@ -1,13 +1,12 @@
|
|
|
1
1
|
import { Event } from "./imports/common";
|
|
2
|
-
import type {
|
|
2
|
+
import type { TransceiverManager } from "./media";
|
|
3
3
|
import type { RTCStats } from "./media/stats";
|
|
4
4
|
import type { PeerConfig } from "./peerConnection";
|
|
5
5
|
import type { SctpTransportManager } from "./sctpManager";
|
|
6
|
-
import type {
|
|
6
|
+
import type { SessionDescription } from "./sdp";
|
|
7
7
|
import { type DtlsKeys, RTCCertificate, RTCDtlsTransport } from "./transport/dtls";
|
|
8
8
|
import { IceCandidate, RTCIceTransport } from "./transport/ice";
|
|
9
9
|
import type { IceGathererState, RTCIceCandidate, RTCIceCandidateInit, RTCIceConnectionState } from "./transport/ice";
|
|
10
|
-
import type { RTCSctpTransport } from "./transport/sctp";
|
|
11
10
|
import type { ConnectionState } from "./types/domain";
|
|
12
11
|
export declare class SecureTransportManager {
|
|
13
12
|
connectionState: ConnectionState;
|
|
@@ -26,17 +25,40 @@ export declare class SecureTransportManager {
|
|
|
26
25
|
transceiverManager: TransceiverManager;
|
|
27
26
|
sctpManager: SctpTransportManager;
|
|
28
27
|
});
|
|
28
|
+
/**live な m-line (停止確定していない transceiver / SCTP) が使う transport */
|
|
29
29
|
get dtlsTransports(): RTCDtlsTransport[];
|
|
30
|
+
/**停止済み transceiver の transport も含めた全 transport */
|
|
31
|
+
private get allDtlsTransports();
|
|
30
32
|
get iceTransports(): RTCIceTransport[];
|
|
31
33
|
setupCertificate(keys: DtlsKeys): void;
|
|
32
|
-
|
|
33
|
-
|
|
34
|
+
/**
|
|
35
|
+
* Resolve STUN/TURN options from the current PeerConfig.
|
|
36
|
+
* Always returns every server-related field (including undefined) so
|
|
37
|
+
* Connection.setIceServers can fully replace residual TURN credentials.
|
|
38
|
+
*/
|
|
39
|
+
private resolveIceServerOptions;
|
|
40
|
+
/**
|
|
41
|
+
* Re-apply ICE servers from the current config to ICE transports that have
|
|
42
|
+
* not started gathering yet (`gatheringState === "new"`).
|
|
43
|
+
*
|
|
44
|
+
* JSEP (RFC 8829 §4.1.18) / ticket scope: server changes affect the next
|
|
45
|
+
* gathering phase. Once gathering has started or finished, leave the live
|
|
46
|
+
* Connection alone so existing candidates and TURN protocols are not
|
|
47
|
+
* disturbed. Used when TURN is learned after the gatherer was built
|
|
48
|
+
* (e.g. from a WHIP Link header) but before setLocalDescription gathers.
|
|
49
|
+
*/
|
|
50
|
+
updateIceServers(): void;
|
|
51
|
+
createTransport({ inheritCredentials }?: {
|
|
52
|
+
inheritCredentials?: boolean | undefined;
|
|
53
|
+
}): RTCDtlsTransport;
|
|
54
|
+
/**
|
|
55
|
+
* sdpMid / sdpMLineIndex は ICE transport を所有する受け入れ済み m-line
|
|
56
|
+
* (BUNDLE なら tag) を呼び出し側で解決して渡す。
|
|
57
|
+
*/
|
|
58
|
+
handleNewIceCandidate({ candidate, sdpMid, sdpMLineIndex, }: {
|
|
34
59
|
candidate: IceCandidate;
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
transceiver?: RTCRtpTransceiver;
|
|
38
|
-
sctpTransport?: RTCSctpTransport;
|
|
39
|
-
bundlePolicy?: BundlePolicy;
|
|
60
|
+
sdpMid?: string;
|
|
61
|
+
sdpMLineIndex?: number;
|
|
40
62
|
}): IceCandidate;
|
|
41
63
|
addIceCandidate(sdp: SessionDescription, candidateMessage: RTCIceCandidate | RTCIceCandidateInit | null): Promise<{
|
|
42
64
|
kind: "end-of-candidates";
|
|
@@ -48,16 +70,25 @@ export declare class SecureTransportManager {
|
|
|
48
70
|
mediaIndices: number[];
|
|
49
71
|
}>;
|
|
50
72
|
private resolveCandidateMediaIndices;
|
|
73
|
+
private isRejectedMedia;
|
|
51
74
|
private getTransportByMid;
|
|
52
75
|
private getTransportByMLineIndex;
|
|
53
76
|
restartIce(): void;
|
|
54
|
-
setLocalRole({ type, role, }: {
|
|
77
|
+
setLocalRole({ type, role, roleOfTransport, }: {
|
|
55
78
|
type: "offer" | "answer";
|
|
79
|
+
/**transport 個別の role がない場合に使う local description 先頭の role */
|
|
56
80
|
role: "auto" | "client" | "server" | undefined;
|
|
81
|
+
/**local description でその transport を使う m-line の role */
|
|
82
|
+
roleOfTransport?: Map<RTCDtlsTransport, "auto" | "client" | "server">;
|
|
57
83
|
}): void;
|
|
58
84
|
private updateIceGatheringState;
|
|
59
85
|
updateIceConnectionState(): void;
|
|
60
|
-
|
|
86
|
+
/**
|
|
87
|
+
* 未収集 (gatheringState=new) の ICE transport だけ候補を収集する。
|
|
88
|
+
* 収集済み transport は gather() が何もしないので、確立済み BUNDLE の transport は再収集されず、
|
|
89
|
+
* BUNDLE group 外に新設した独立 transport だけが候補を収集する。
|
|
90
|
+
*/
|
|
91
|
+
gatherCandidates(): Promise<void>;
|
|
61
92
|
setConnectionState(state: ConnectionState): void;
|
|
62
93
|
getStats(timestamp?: number): Promise<RTCStats[]>;
|
|
63
94
|
ensureCerts(): Promise<void>;
|
|
@@ -89,17 +89,22 @@ class SecureTransportManager {
|
|
|
89
89
|
}
|
|
90
90
|
}
|
|
91
91
|
}
|
|
92
|
+
/**live な m-line (停止確定していない transceiver / SCTP) が使う transport */
|
|
92
93
|
get dtlsTransports() {
|
|
93
|
-
|
|
94
|
+
return uniqueTransports([
|
|
95
|
+
...this.transceiverManager
|
|
96
|
+
.getTransceivers()
|
|
97
|
+
.filter((t) => !t.stopped)
|
|
98
|
+
.map((t) => t?.dtlsTransport),
|
|
99
|
+
this.sctpManager.sctpTransport?.dtlsTransport,
|
|
100
|
+
]);
|
|
101
|
+
}
|
|
102
|
+
/**停止済み transceiver の transport も含めた全 transport */
|
|
103
|
+
get allDtlsTransports() {
|
|
104
|
+
return uniqueTransports([
|
|
94
105
|
...this.transceiverManager.getTransceivers().map((t) => t?.dtlsTransport),
|
|
95
106
|
this.sctpManager.sctpTransport?.dtlsTransport,
|
|
96
|
-
]
|
|
97
|
-
return transports.reduce((acc, cur) => {
|
|
98
|
-
if (!acc.map((d) => d.id).includes(cur.id)) {
|
|
99
|
-
acc.push(cur);
|
|
100
|
-
}
|
|
101
|
-
return acc;
|
|
102
|
-
}, []);
|
|
107
|
+
]);
|
|
103
108
|
}
|
|
104
109
|
get iceTransports() {
|
|
105
110
|
return this.dtlsTransports.map((d) => d.iceTransport);
|
|
@@ -107,16 +112,58 @@ class SecureTransportManager {
|
|
|
107
112
|
setupCertificate(keys) {
|
|
108
113
|
this.certificate = new dtls_1.RTCCertificate(keys.keyPem, keys.certPem, keys.signatureHash);
|
|
109
114
|
}
|
|
110
|
-
|
|
111
|
-
|
|
115
|
+
/**
|
|
116
|
+
* Resolve STUN/TURN options from the current PeerConfig.
|
|
117
|
+
* Always returns every server-related field (including undefined) so
|
|
118
|
+
* Connection.setIceServers can fully replace residual TURN credentials.
|
|
119
|
+
*/
|
|
120
|
+
resolveIceServerOptions() {
|
|
112
121
|
const iceServerOptions = (0, utils_1.parseIceServers)(this.config.iceServers);
|
|
113
122
|
const turnTransport = (0, utils_1.resolveTurnTransport)({
|
|
114
123
|
parsedTurnTransport: iceServerOptions.turnTransport,
|
|
115
124
|
configuredTurnTransport: this.config.turnTransport,
|
|
116
125
|
forceTurnTCP: this.config.forceTurnTCP,
|
|
117
126
|
});
|
|
127
|
+
return {
|
|
128
|
+
stunServer: iceServerOptions.stunServer,
|
|
129
|
+
turnServer: iceServerOptions.turnServer,
|
|
130
|
+
turnUsername: iceServerOptions.turnUsername,
|
|
131
|
+
turnPassword: iceServerOptions.turnPassword,
|
|
132
|
+
turnTransport,
|
|
133
|
+
};
|
|
134
|
+
}
|
|
135
|
+
/**
|
|
136
|
+
* Re-apply ICE servers from the current config to ICE transports that have
|
|
137
|
+
* not started gathering yet (`gatheringState === "new"`).
|
|
138
|
+
*
|
|
139
|
+
* JSEP (RFC 8829 §4.1.18) / ticket scope: server changes affect the next
|
|
140
|
+
* gathering phase. Once gathering has started or finished, leave the live
|
|
141
|
+
* Connection alone so existing candidates and TURN protocols are not
|
|
142
|
+
* disturbed. Used when TURN is learned after the gatherer was built
|
|
143
|
+
* (e.g. from a WHIP Link header) but before setLocalDescription gathers.
|
|
144
|
+
*/
|
|
145
|
+
updateIceServers() {
|
|
146
|
+
const options = {
|
|
147
|
+
...this.resolveIceServerOptions(),
|
|
148
|
+
forceTurn: this.config.iceTransportPolicy === "relay",
|
|
149
|
+
useTcp: this.config.iceUseTcp,
|
|
150
|
+
turnUdpFamily: this.config.turnUdpFamily,
|
|
151
|
+
};
|
|
152
|
+
for (const iceTransport of this.iceTransports) {
|
|
153
|
+
// Only update gatherers that have never gathered in this generation.
|
|
154
|
+
// Applying after gathering would leave stale TURN protocols in
|
|
155
|
+
// Connection.protocols that get re-advertised on a later restart.
|
|
156
|
+
if (iceTransport.gatheringState === "new") {
|
|
157
|
+
iceTransport.setIceServers(options);
|
|
158
|
+
}
|
|
159
|
+
}
|
|
160
|
+
}
|
|
161
|
+
createTransport({ inheritCredentials = true } = {}) {
|
|
162
|
+
const existing = inheritCredentials
|
|
163
|
+
? this.iceTransports.find((transport) => transport.state !== "closed")
|
|
164
|
+
: undefined;
|
|
118
165
|
const iceGatherer = new ice_1.RTCIceGatherer({
|
|
119
|
-
...
|
|
166
|
+
...this.resolveIceServerOptions(),
|
|
120
167
|
iceLite: this.config.iceLite,
|
|
121
168
|
forceTurn: this.config.iceTransportPolicy === "relay",
|
|
122
169
|
portRange: this.config.icePortRange,
|
|
@@ -128,8 +175,11 @@ class SecureTransportManager {
|
|
|
128
175
|
useIpv4: this.config.iceUseIpv4,
|
|
129
176
|
useIpv6: this.config.iceUseIpv6,
|
|
130
177
|
useTcp: this.config.iceUseTcp,
|
|
131
|
-
|
|
178
|
+
tcpPassive: this.config.iceTcpPassive,
|
|
179
|
+
stunGatherTimeout: this.config.iceStunGatherTimeout,
|
|
180
|
+
turnConnectTimeout: this.config.iceTurnConnectTimeout,
|
|
132
181
|
turnTlsOptions: this.config.turnTlsOptions,
|
|
182
|
+
turnUdpFamily: this.config.turnUdpFamily,
|
|
133
183
|
useLinkLocalAddress: this.config.iceUseLinkLocalAddress,
|
|
134
184
|
});
|
|
135
185
|
if (existing) {
|
|
@@ -147,24 +197,13 @@ class SecureTransportManager {
|
|
|
147
197
|
const dtlsTransport = new dtls_1.RTCDtlsTransport(this.config, iceTransport, this.certificate, srtpProfiles);
|
|
148
198
|
return dtlsTransport;
|
|
149
199
|
}
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
}
|
|
158
|
-
else {
|
|
159
|
-
if (transceiver) {
|
|
160
|
-
candidate.sdpMLineIndex = transceiver.mLineIndex;
|
|
161
|
-
candidate.sdpMid = transceiver.mid ?? undefined;
|
|
162
|
-
}
|
|
163
|
-
if (sctpTransport) {
|
|
164
|
-
candidate.sdpMLineIndex = sctpTransport.mLineIndex;
|
|
165
|
-
candidate.sdpMid = sctpTransport.mid;
|
|
166
|
-
}
|
|
167
|
-
}
|
|
200
|
+
/**
|
|
201
|
+
* sdpMid / sdpMLineIndex は ICE transport を所有する受け入れ済み m-line
|
|
202
|
+
* (BUNDLE なら tag) を呼び出し側で解決して渡す。
|
|
203
|
+
*/
|
|
204
|
+
handleNewIceCandidate({ candidate, sdpMid, sdpMLineIndex, }) {
|
|
205
|
+
candidate.sdpMid = sdpMid;
|
|
206
|
+
candidate.sdpMLineIndex = sdpMLineIndex;
|
|
168
207
|
if (candidate.foundation &&
|
|
169
208
|
!candidate.foundation.startsWith("candidate:")) {
|
|
170
209
|
candidate.foundation = "candidate:" + candidate.foundation;
|
|
@@ -214,6 +253,14 @@ class SecureTransportManager {
|
|
|
214
253
|
candidate.sdpMLineIndex = targetMediaIndex;
|
|
215
254
|
const iceTransport = this.getTransportByMLineIndex(sdp, targetMediaIndex);
|
|
216
255
|
if (!iceTransport) {
|
|
256
|
+
if (this.isRejectedMedia(targetMedia)) {
|
|
257
|
+
// 拒否 / 停止した m-line の候補は MID / index を保ったまま記録だけする
|
|
258
|
+
return {
|
|
259
|
+
kind: "candidate",
|
|
260
|
+
candidate,
|
|
261
|
+
mediaIndices: [targetMediaIndex],
|
|
262
|
+
};
|
|
263
|
+
}
|
|
217
264
|
throw (0, errors_1.createWebRtcDomException)("OperationError", "ICE transport not found for candidate");
|
|
218
265
|
}
|
|
219
266
|
await iceTransport.addRemoteCandidate(candidate);
|
|
@@ -253,6 +300,21 @@ class SecureTransportManager {
|
|
|
253
300
|
}
|
|
254
301
|
return mediaIndices;
|
|
255
302
|
}
|
|
303
|
+
isRejectedMedia(media) {
|
|
304
|
+
if (media.port === 0) {
|
|
305
|
+
return true;
|
|
306
|
+
}
|
|
307
|
+
if (!["audio", "video"].includes(media.kind)) {
|
|
308
|
+
return false;
|
|
309
|
+
}
|
|
310
|
+
const transceiver = this.transceiverManager
|
|
311
|
+
.getTransceivers()
|
|
312
|
+
.find((t) => t.mid != undefined && t.mid === media.rtp.muxId);
|
|
313
|
+
return (!transceiver ||
|
|
314
|
+
transceiver.stopped ||
|
|
315
|
+
transceiver.stopping ||
|
|
316
|
+
transceiver.pendingRejection);
|
|
317
|
+
}
|
|
256
318
|
getTransportByMid(mid) {
|
|
257
319
|
if (!mid) {
|
|
258
320
|
return;
|
|
@@ -262,11 +324,14 @@ class SecureTransportManager {
|
|
|
262
324
|
.getTransceivers()
|
|
263
325
|
.find((t) => t.mid === mid);
|
|
264
326
|
if (transceiver) {
|
|
265
|
-
iceTransport = transceiver.dtlsTransport
|
|
327
|
+
iceTransport = transceiver.dtlsTransport?.iceTransport;
|
|
266
328
|
}
|
|
267
329
|
else if (!iceTransport && this.sctpManager.sctpTransport?.mid === mid) {
|
|
268
330
|
iceTransport = this.sctpManager.sctpTransport.dtlsTransport.iceTransport;
|
|
269
331
|
}
|
|
332
|
+
if (iceTransport?.state === "closed") {
|
|
333
|
+
return;
|
|
334
|
+
}
|
|
270
335
|
return iceTransport;
|
|
271
336
|
}
|
|
272
337
|
getTransportByMLineIndex(sdp, index) {
|
|
@@ -281,8 +346,11 @@ class SecureTransportManager {
|
|
|
281
346
|
for (const transport of this.iceTransports) {
|
|
282
347
|
transport.restart();
|
|
283
348
|
}
|
|
349
|
+
// restart() resets each gatherer to "new"; refresh the aggregate cache
|
|
350
|
+
// even if a gatherer failed to emit onGatheringStateChange.
|
|
351
|
+
this.updateIceGatheringState();
|
|
284
352
|
}
|
|
285
|
-
setLocalRole({ type, role, }) {
|
|
353
|
+
setLocalRole({ type, role, roleOfTransport, }) {
|
|
286
354
|
for (const dtlsTransport of this.dtlsTransports) {
|
|
287
355
|
const iceTransport = dtlsTransport.iceTransport;
|
|
288
356
|
if (iceTransport.connection.iceLite) {
|
|
@@ -300,8 +368,9 @@ class SecureTransportManager {
|
|
|
300
368
|
}
|
|
301
369
|
// # set DTLS role for mediasoup
|
|
302
370
|
if (type === "answer") {
|
|
303
|
-
|
|
304
|
-
|
|
371
|
+
const transportRole = roleOfTransport?.get(dtlsTransport) ?? role;
|
|
372
|
+
if (transportRole) {
|
|
373
|
+
dtlsTransport.role = transportRole;
|
|
305
374
|
}
|
|
306
375
|
}
|
|
307
376
|
}
|
|
@@ -383,18 +452,17 @@ class SecureTransportManager {
|
|
|
383
452
|
this.setConnectionState("disconnected");
|
|
384
453
|
}
|
|
385
454
|
}
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
}
|
|
455
|
+
/**
|
|
456
|
+
* 未収集 (gatheringState=new) の ICE transport だけ候補を収集する。
|
|
457
|
+
* 収集済み transport は gather() が何もしないので、確立済み BUNDLE の transport は再収集されず、
|
|
458
|
+
* BUNDLE group 外に新設した独立 transport だけが候補を収集する。
|
|
459
|
+
*/
|
|
460
|
+
async gatherCandidates() {
|
|
461
|
+
await Promise.allSettled(this.iceTransports
|
|
462
|
+
.filter((iceTransport) => iceTransport.state !== "closed")
|
|
463
|
+
.map((iceTransport) => iceTransport.gather())).catch((e) => {
|
|
464
|
+
log("gatherCandidates failed", e);
|
|
465
|
+
});
|
|
398
466
|
}
|
|
399
467
|
setConnectionState(state) {
|
|
400
468
|
if (this.connectionState === state) {
|
|
@@ -424,7 +492,7 @@ class SecureTransportManager {
|
|
|
424
492
|
}
|
|
425
493
|
async close() {
|
|
426
494
|
this.setConnectionState("closed");
|
|
427
|
-
await Promise.allSettled([...this.
|
|
495
|
+
await Promise.allSettled([...this.allDtlsTransports.map((t) => t.stop())]);
|
|
428
496
|
this.iceGatheringStateChange.allUnsubscribe();
|
|
429
497
|
this.iceConnectionStateChange.allUnsubscribe();
|
|
430
498
|
this.onIceCandidate.allUnsubscribe();
|
|
@@ -432,6 +500,14 @@ class SecureTransportManager {
|
|
|
432
500
|
}
|
|
433
501
|
}
|
|
434
502
|
exports.SecureTransportManager = SecureTransportManager;
|
|
503
|
+
function uniqueTransports(transports) {
|
|
504
|
+
return transports.reduce((acc, cur) => {
|
|
505
|
+
if (cur && !acc.map((d) => d.id).includes(cur.id)) {
|
|
506
|
+
acc.push(cur);
|
|
507
|
+
}
|
|
508
|
+
return acc;
|
|
509
|
+
}, []);
|
|
510
|
+
}
|
|
435
511
|
const srtpProfiles = [
|
|
436
512
|
const_1.SRTP_PROFILE.SRTP_AEAD_AES_128_GCM, // prefer
|
|
437
513
|
const_1.SRTP_PROFILE.SRTP_AES128_CM_HMAC_SHA1_80,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"secureTransportManager.js","sourceRoot":"","sources":["../../../src/secureTransportManager.ts"],"names":[],"mappings":"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","sourcesContent":["import { SRTP_PROFILE } from \"./const\";\nimport { createWebRtcDomException, createWebRtcTypeError } from \"./errors\";\nimport { Event, debug } from \"./imports/common\";\nimport type { RTCRtpTransceiver, TransceiverManager } from \"./media\";\nimport type { RTCStats } from \"./media/stats\";\nimport type { PeerConfig } from \"./peerConnection\";\nimport type { SctpTransportManager } from \"./sctpManager\";\nimport type { BundlePolicy, MediaDescription, SessionDescription } from \"./sdp\";\nimport {\n type DtlsKeys,\n RTCCertificate,\n RTCDtlsTransport,\n} from \"./transport/dtls\";\nimport { IceCandidate, RTCIceGatherer, RTCIceTransport } from \"./transport/ice\";\nimport type {\n IceGathererState,\n RTCIceCandidate,\n RTCIceCandidateInit,\n RTCIceConnectionState,\n} from \"./transport/ice\";\nimport type { RTCSctpTransport } from \"./transport/sctp\";\nimport type { ConnectionState } from \"./types/domain\";\nimport { parseIceServers, resolveTurnTransport } from \"./utils\";\n\nconst log = debug(\n \"werift:packages/webrtc/src/transport/secureTransportManager.ts\",\n);\nexport class SecureTransportManager {\n connectionState: ConnectionState = \"new\";\n iceConnectionState: RTCIceConnectionState = \"new\";\n iceGatheringState: IceGathererState = \"new\";\n certificate?: RTCCertificate;\n\n readonly iceGatheringStateChange = new Event<[IceGathererState]>();\n readonly iceConnectionStateChange = new Event<[RTCIceConnectionState]>();\n readonly onIceCandidate = new Event<[IceCandidate | undefined]>();\n readonly connectionStateChange = new Event<[ConnectionState]>();\n\n private config: PeerConfig;\n private transceiverManager: TransceiverManager;\n private sctpManager: SctpTransportManager;\n\n constructor({\n config,\n transceiverManager,\n sctpManager,\n }: {\n config: PeerConfig;\n transceiverManager: TransceiverManager;\n sctpManager: SctpTransportManager;\n }) {\n this.config = config;\n this.transceiverManager = transceiverManager;\n this.sctpManager = sctpManager;\n\n if (this.config.dtls) {\n const { keys } = this.config.dtls;\n\n if (this.config.certificates[0]) {\n this.certificate = this.config.certificates[0];\n } else if (keys) {\n this.setupCertificate(keys);\n }\n }\n }\n\n get dtlsTransports() {\n const transports = [\n ...this.transceiverManager.getTransceivers().map((t) => t?.dtlsTransport),\n this.sctpManager.sctpTransport?.dtlsTransport,\n ].filter((t) => t != undefined);\n\n return transports.reduce((acc: RTCDtlsTransport[], cur) => {\n if (!acc.map((d) => d.id).includes(cur.id)) {\n acc.push(cur);\n }\n return acc;\n }, []);\n }\n\n get iceTransports() {\n return this.dtlsTransports.map((d) => d.iceTransport);\n }\n\n setupCertificate(keys: DtlsKeys) {\n this.certificate = new RTCCertificate(\n keys.keyPem,\n keys.certPem,\n keys.signatureHash,\n );\n }\n\n createTransport() {\n const existing = this.iceTransports.find(\n (transport) => transport.state !== \"closed\",\n );\n const iceServerOptions = parseIceServers(this.config.iceServers);\n const turnTransport = resolveTurnTransport({\n parsedTurnTransport: iceServerOptions.turnTransport,\n configuredTurnTransport: this.config.turnTransport,\n forceTurnTCP: this.config.forceTurnTCP,\n });\n\n const iceGatherer = new RTCIceGatherer({\n ...iceServerOptions,\n iceLite: this.config.iceLite,\n forceTurn: this.config.iceTransportPolicy === \"relay\",\n portRange: this.config.icePortRange,\n interfaceAddresses: this.config.iceInterfaceAddresses,\n additionalHostAddresses: this.config.iceAdditionalHostAddresses,\n filterStunResponse: this.config.iceFilterStunResponse,\n filterCandidatePair: this.config.iceFilterCandidatePair,\n localPasswordPrefix: this.config.icePasswordPrefix,\n useIpv4: this.config.iceUseIpv4,\n useIpv6: this.config.iceUseIpv6,\n useTcp: this.config.iceUseTcp,\n turnTransport,\n turnTlsOptions: this.config.turnTlsOptions,\n useLinkLocalAddress: this.config.iceUseLinkLocalAddress,\n });\n\n if (existing) {\n iceGatherer.connection.localUsername = existing.connection.localUsername;\n iceGatherer.connection.localPassword = existing.connection.localPassword;\n }\n\n iceGatherer.onGatheringStateChange.subscribe(() => {\n this.updateIceGatheringState();\n });\n this.updateIceGatheringState();\n\n const iceTransport = new RTCIceTransport(iceGatherer);\n iceTransport.onStateChange.subscribe(() => {\n this.updateIceConnectionState();\n });\n\n const dtlsTransport = new RTCDtlsTransport(\n this.config,\n iceTransport,\n this.certificate,\n srtpProfiles,\n );\n\n return dtlsTransport;\n }\n\n handleNewIceCandidate({\n candidate,\n media,\n remoteIsBundled,\n transceiver,\n sctpTransport,\n bundlePolicy,\n }: {\n candidate: IceCandidate;\n media?: MediaDescription;\n remoteIsBundled: boolean;\n transceiver?: RTCRtpTransceiver;\n sctpTransport?: RTCSctpTransport;\n bundlePolicy?: BundlePolicy;\n }) {\n // Assign sdpMid and sdpMLineIndex\n if (bundlePolicy === \"max-bundle\" || remoteIsBundled) {\n candidate.sdpMLineIndex = 0;\n if (media) {\n candidate.sdpMid = media.rtp.muxId;\n }\n } else {\n if (transceiver) {\n candidate.sdpMLineIndex = transceiver.mLineIndex;\n candidate.sdpMid = transceiver.mid ?? undefined;\n }\n if (sctpTransport) {\n candidate.sdpMLineIndex = sctpTransport.mLineIndex;\n candidate.sdpMid = sctpTransport.mid;\n }\n }\n\n if (\n candidate.foundation &&\n !candidate.foundation.startsWith(\"candidate:\")\n ) {\n candidate.foundation = \"candidate:\" + candidate.foundation;\n }\n\n this.onIceCandidate.execute(candidate);\n\n return candidate;\n }\n\n async addIceCandidate(\n sdp: SessionDescription,\n candidateMessage: RTCIceCandidate | RTCIceCandidateInit | null,\n ) {\n const candidateText = candidateMessage?.candidate;\n const sdpMid = candidateMessage?.sdpMid;\n const sdpMLineIndex = candidateMessage?.sdpMLineIndex;\n const usernameFragment = candidateMessage?.usernameFragment;\n const isEndOfCandidates =\n candidateMessage == null || candidateText == null || candidateText === \"\";\n const mediaIndices = this.resolveCandidateMediaIndices({\n sdp,\n isEndOfCandidates,\n sdpMid,\n sdpMLineIndex,\n usernameFragment,\n });\n\n if (isEndOfCandidates) {\n const candidateTarget = mediaIndices\n .map((index) => this.getTransportByMLineIndex(sdp, index))\n .filter(\n (iceTransport): iceTransport is RTCIceTransport => !!iceTransport,\n )\n .reduce((acc: RTCIceTransport[], transport) => {\n if (!acc.find(({ id }) => id === transport.id)) {\n acc.push(transport);\n }\n return acc;\n }, []);\n\n await Promise.all(\n candidateTarget.map((iceTransport) =>\n iceTransport.addRemoteCandidate(undefined),\n ),\n );\n return {\n kind: \"end-of-candidates\" as const,\n mediaIndices,\n };\n }\n\n const candidate = IceCandidate.fromJSON(candidateMessage);\n if (!candidate) {\n throw createWebRtcDomException(\n \"OperationError\",\n \"Failed to parse ICE candidate\",\n );\n }\n\n const targetMediaIndex = mediaIndices[0];\n const targetMedia = sdp.media[targetMediaIndex];\n if (!targetMedia) {\n throw createWebRtcDomException(\n \"OperationError\",\n \"ICE media section not found\",\n );\n }\n candidate.sdpMid = targetMedia.rtp.muxId ?? undefined;\n candidate.sdpMLineIndex = targetMediaIndex;\n\n const iceTransport = this.getTransportByMLineIndex(sdp, targetMediaIndex);\n\n if (!iceTransport) {\n throw createWebRtcDomException(\n \"OperationError\",\n \"ICE transport not found for candidate\",\n );\n }\n\n await iceTransport.addRemoteCandidate(candidate);\n return {\n kind: \"candidate\" as const,\n candidate,\n mediaIndices: [targetMediaIndex],\n };\n }\n\n private resolveCandidateMediaIndices({\n sdp,\n isEndOfCandidates,\n sdpMid,\n sdpMLineIndex,\n usernameFragment,\n }: {\n sdp: SessionDescription;\n isEndOfCandidates: boolean;\n sdpMid?: string | null;\n sdpMLineIndex?: number | null;\n usernameFragment?: string | null;\n }) {\n let mediaIndices: number[];\n\n if (typeof sdpMid === \"string\") {\n const mediaIndex = sdp.media.findIndex(\n (media) => media.rtp.muxId === sdpMid,\n );\n if (mediaIndex < 0) {\n throw createWebRtcDomException(\n \"OperationError\",\n \"Media section for sdpMid was not found\",\n );\n }\n mediaIndices = [mediaIndex];\n } else if (typeof sdpMLineIndex === \"number\") {\n if (sdpMLineIndex < 0 || sdpMLineIndex >= sdp.media.length) {\n throw createWebRtcDomException(\n \"OperationError\",\n \"Media section for sdpMLineIndex was not found\",\n );\n }\n mediaIndices = [sdpMLineIndex];\n } else if (isEndOfCandidates) {\n mediaIndices = sdp.media.map((_, index) => index);\n } else {\n throw createWebRtcTypeError(\n \"sdpMid or sdpMLineIndex must be provided with a candidate\",\n );\n }\n\n if (typeof usernameFragment === \"string\") {\n const matchingIndices = mediaIndices.filter(\n (index) =>\n sdp.media[index]?.iceParams?.usernameFragment === usernameFragment,\n );\n if (matchingIndices.length === 0) {\n throw createWebRtcDomException(\n \"OperationError\",\n \"No media section matched the ICE usernameFragment\",\n );\n }\n mediaIndices = matchingIndices;\n }\n\n return mediaIndices;\n }\n\n private getTransportByMid(mid?: string) {\n if (!mid) {\n return;\n }\n let iceTransport: RTCIceTransport | undefined;\n\n const transceiver = this.transceiverManager\n .getTransceivers()\n .find((t) => t.mid === mid);\n if (transceiver) {\n iceTransport = transceiver.dtlsTransport.iceTransport;\n } else if (!iceTransport && this.sctpManager.sctpTransport?.mid === mid) {\n iceTransport = this.sctpManager.sctpTransport.dtlsTransport.iceTransport;\n }\n\n return iceTransport;\n }\n\n private getTransportByMLineIndex(sdp: SessionDescription, index: number) {\n const media = sdp.media[index];\n if (!media) {\n return;\n }\n const transport = this.getTransportByMid(media.rtp.muxId!);\n\n return transport;\n }\n\n restartIce() {\n for (const transport of this.iceTransports) {\n transport.restart();\n }\n }\n\n setLocalRole({\n type,\n role,\n }: {\n type: \"offer\" | \"answer\";\n role: \"auto\" | \"client\" | \"server\" | undefined;\n }) {\n for (const dtlsTransport of this.dtlsTransports) {\n const iceTransport = dtlsTransport.iceTransport;\n if (iceTransport.connection.iceLite) {\n iceTransport.connection.iceControlling = false;\n } else if (iceTransport.connection.remoteIsLite) {\n // RFC 8445 S6.1.1\n iceTransport.connection.iceControlling = true;\n } else if (type === \"offer\") {\n iceTransport.connection.iceControlling = true;\n } else {\n iceTransport.connection.iceControlling = false;\n }\n\n // # set DTLS role for mediasoup\n if (type === \"answer\") {\n if (role) {\n dtlsTransport.role = role;\n }\n }\n }\n }\n\n // https://w3c.github.io/webrtc-pc/#dom-rtcicegatheringstate\n private updateIceGatheringState() {\n const all = this.iceTransports;\n\n function allMatch(...state: IceGathererState[]) {\n return (\n all.filter((check) => state.includes(check.gatheringState)).length ===\n all.length\n );\n }\n\n let newState: IceGathererState;\n\n if (all.length && allMatch(\"complete\")) {\n newState = \"complete\";\n } else if (!all.length || allMatch(\"new\", \"complete\")) {\n newState = \"new\";\n } else if (all.map((check) => check.gatheringState).includes(\"gathering\")) {\n newState = \"gathering\";\n } else {\n newState = \"new\";\n }\n\n if (this.iceGatheringState === newState) {\n return;\n }\n\n this.iceGatheringState = newState;\n this.iceGatheringStateChange.execute(newState);\n }\n\n // https://w3c.github.io/webrtc-pc/#dom-rtciceconnectionstate\n updateIceConnectionState() {\n const all = this.iceTransports;\n let newState: RTCIceConnectionState;\n\n function allMatch(...state: RTCIceConnectionState[]) {\n return (\n all.filter((check) => state.includes(check.state)).length === all.length\n );\n }\n\n function anyMatch(...state: RTCIceConnectionState[]) {\n return all.some((check) => state.includes(check.state));\n }\n\n if (this.connectionState === \"closed\") {\n newState = \"closed\";\n } else if (anyMatch(\"failed\")) {\n newState = \"failed\";\n } else if (anyMatch(\"disconnected\")) {\n newState = \"disconnected\";\n } else if (allMatch(\"new\", \"closed\")) {\n newState = \"new\";\n } else if (anyMatch(\"new\", \"checking\")) {\n newState = \"checking\";\n } else if (allMatch(\"completed\", \"closed\")) {\n newState = \"completed\";\n } else if (allMatch(\"connected\", \"completed\", \"closed\")) {\n newState = \"connected\";\n } else {\n // unreachable?\n newState = \"new\";\n }\n\n if (this.iceConnectionState === newState) {\n return;\n }\n\n log(\"iceConnectionStateChange\", newState);\n this.iceConnectionState = newState;\n this.iceConnectionStateChange.execute(newState);\n\n // Runtime ICE failure (e.g. RFC 7675 consent expiry) must surface on\n // PeerConnection.connectionState without treating it as an explicit close().\n if (newState === \"failed\" && this.connectionState !== \"closed\") {\n this.setConnectionState(\"failed\");\n } else if (\n newState === \"disconnected\" &&\n this.connectionState === \"connected\"\n ) {\n this.setConnectionState(\"disconnected\");\n }\n }\n\n async gatherCandidates(remoteIsBundled: boolean) {\n const connected = this.iceTransports.find(\n (transport) =>\n transport.state === \"connected\" || transport.state === \"completed\",\n );\n if (remoteIsBundled && connected) {\n // no need to gather ice candidates on an existing bundled connection\n log(\"skipping ICE gathering for bundled connection\");\n } else {\n await Promise.allSettled(\n this.iceTransports.map((iceTransport) => iceTransport.gather()),\n ).catch((e) => {\n // エラーハンドリングを追加 (例: ログ出力)\n log(\"gatherCandidates failed\", e);\n });\n }\n }\n\n setConnectionState(state: ConnectionState) {\n if (this.connectionState === state) {\n return;\n }\n log(\"connectionStateChange\", state);\n this.connectionState = state;\n this.connectionStateChange.execute(state);\n }\n\n async getStats(timestamp?: number): Promise<RTCStats[]> {\n const stats: RTCStats[] = [];\n\n for (const dtlsTransport of this.dtlsTransports) {\n const transportStats = await dtlsTransport.getStats(timestamp);\n if (transportStats) {\n stats.push(...transportStats);\n }\n }\n\n return stats;\n }\n\n async ensureCerts() {\n if (!this.certificate) {\n this.certificate = await RTCDtlsTransport.SetupCertificate();\n }\n\n for (const dtlsTransport of this.dtlsTransports) {\n dtlsTransport.localCertificate = this.certificate;\n }\n }\n\n async close() {\n this.setConnectionState(\"closed\");\n\n await Promise.allSettled([...this.dtlsTransports.map((t) => t.stop())]);\n\n this.iceGatheringStateChange.allUnsubscribe();\n this.iceConnectionStateChange.allUnsubscribe();\n this.onIceCandidate.allUnsubscribe();\n this.connectionStateChange.allUnsubscribe();\n }\n}\n\nconst srtpProfiles = [\n SRTP_PROFILE.SRTP_AEAD_AES_128_GCM, // prefer\n SRTP_PROFILE.SRTP_AES128_CM_HMAC_SHA1_80,\n];\n"]}
|
|
1
|
+
{"version":3,"file":"secureTransportManager.js","sourceRoot":"","sources":["../../../src/secureTransportManager.ts"],"names":[],"mappings":"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","sourcesContent":["import { SRTP_PROFILE } from \"./const\";\nimport { createWebRtcDomException, createWebRtcTypeError } from \"./errors\";\nimport { Event, debug } from \"./imports/common\";\nimport type { RTCRtpTransceiver, TransceiverManager } from \"./media\";\nimport type { RTCStats } from \"./media/stats\";\nimport type { PeerConfig } from \"./peerConnection\";\nimport type { SctpTransportManager } from \"./sctpManager\";\nimport type { BundlePolicy, MediaDescription, SessionDescription } from \"./sdp\";\nimport {\n type DtlsKeys,\n RTCCertificate,\n RTCDtlsTransport,\n} from \"./transport/dtls\";\nimport { IceCandidate, RTCIceGatherer, RTCIceTransport } from \"./transport/ice\";\nimport type {\n IceGathererState,\n RTCIceCandidate,\n RTCIceCandidateInit,\n RTCIceConnectionState,\n} from \"./transport/ice\";\nimport type { RTCSctpTransport } from \"./transport/sctp\";\nimport type { ConnectionState } from \"./types/domain\";\nimport { parseIceServers, resolveTurnTransport } from \"./utils\";\n\nconst log = debug(\n \"werift:packages/webrtc/src/transport/secureTransportManager.ts\",\n);\nexport class SecureTransportManager {\n connectionState: ConnectionState = \"new\";\n iceConnectionState: RTCIceConnectionState = \"new\";\n iceGatheringState: IceGathererState = \"new\";\n certificate?: RTCCertificate;\n\n readonly iceGatheringStateChange = new Event<[IceGathererState]>();\n readonly iceConnectionStateChange = new Event<[RTCIceConnectionState]>();\n readonly onIceCandidate = new Event<[IceCandidate | undefined]>();\n readonly connectionStateChange = new Event<[ConnectionState]>();\n\n private config: PeerConfig;\n private transceiverManager: TransceiverManager;\n private sctpManager: SctpTransportManager;\n\n constructor({\n config,\n transceiverManager,\n sctpManager,\n }: {\n config: PeerConfig;\n transceiverManager: TransceiverManager;\n sctpManager: SctpTransportManager;\n }) {\n this.config = config;\n this.transceiverManager = transceiverManager;\n this.sctpManager = sctpManager;\n\n if (this.config.dtls) {\n const { keys } = this.config.dtls;\n\n if (this.config.certificates[0]) {\n this.certificate = this.config.certificates[0];\n } else if (keys) {\n this.setupCertificate(keys);\n }\n }\n }\n\n /**live な m-line (停止確定していない transceiver / SCTP) が使う transport */\n get dtlsTransports() {\n return uniqueTransports([\n ...this.transceiverManager\n .getTransceivers()\n .filter((t) => !t.stopped)\n .map((t) => t?.dtlsTransport),\n this.sctpManager.sctpTransport?.dtlsTransport,\n ]);\n }\n\n /**停止済み transceiver の transport も含めた全 transport */\n private get allDtlsTransports() {\n return uniqueTransports([\n ...this.transceiverManager.getTransceivers().map((t) => t?.dtlsTransport),\n this.sctpManager.sctpTransport?.dtlsTransport,\n ]);\n }\n\n get iceTransports() {\n return this.dtlsTransports.map((d) => d.iceTransport);\n }\n\n setupCertificate(keys: DtlsKeys) {\n this.certificate = new RTCCertificate(\n keys.keyPem,\n keys.certPem,\n keys.signatureHash,\n );\n }\n\n /**\n * Resolve STUN/TURN options from the current PeerConfig.\n * Always returns every server-related field (including undefined) so\n * Connection.setIceServers can fully replace residual TURN credentials.\n */\n private resolveIceServerOptions() {\n const iceServerOptions = parseIceServers(this.config.iceServers);\n const turnTransport = resolveTurnTransport({\n parsedTurnTransport: iceServerOptions.turnTransport,\n configuredTurnTransport: this.config.turnTransport,\n forceTurnTCP: this.config.forceTurnTCP,\n });\n return {\n stunServer: iceServerOptions.stunServer,\n turnServer: iceServerOptions.turnServer,\n turnUsername: iceServerOptions.turnUsername,\n turnPassword: iceServerOptions.turnPassword,\n turnTransport,\n };\n }\n\n /**\n * Re-apply ICE servers from the current config to ICE transports that have\n * not started gathering yet (`gatheringState === \"new\"`).\n *\n * JSEP (RFC 8829 §4.1.18) / ticket scope: server changes affect the next\n * gathering phase. Once gathering has started or finished, leave the live\n * Connection alone so existing candidates and TURN protocols are not\n * disturbed. Used when TURN is learned after the gatherer was built\n * (e.g. from a WHIP Link header) but before setLocalDescription gathers.\n */\n updateIceServers() {\n const options = {\n ...this.resolveIceServerOptions(),\n forceTurn: this.config.iceTransportPolicy === \"relay\",\n useTcp: this.config.iceUseTcp,\n turnUdpFamily: this.config.turnUdpFamily,\n };\n for (const iceTransport of this.iceTransports) {\n // Only update gatherers that have never gathered in this generation.\n // Applying after gathering would leave stale TURN protocols in\n // Connection.protocols that get re-advertised on a later restart.\n if (iceTransport.gatheringState === \"new\") {\n iceTransport.setIceServers(options);\n }\n }\n }\n\n createTransport({ inheritCredentials = true } = {}) {\n const existing = inheritCredentials\n ? this.iceTransports.find((transport) => transport.state !== \"closed\")\n : undefined;\n\n const iceGatherer = new RTCIceGatherer({\n ...this.resolveIceServerOptions(),\n iceLite: this.config.iceLite,\n forceTurn: this.config.iceTransportPolicy === \"relay\",\n portRange: this.config.icePortRange,\n interfaceAddresses: this.config.iceInterfaceAddresses,\n additionalHostAddresses: this.config.iceAdditionalHostAddresses,\n filterStunResponse: this.config.iceFilterStunResponse,\n filterCandidatePair: this.config.iceFilterCandidatePair,\n localPasswordPrefix: this.config.icePasswordPrefix,\n useIpv4: this.config.iceUseIpv4,\n useIpv6: this.config.iceUseIpv6,\n useTcp: this.config.iceUseTcp,\n tcpPassive: this.config.iceTcpPassive,\n stunGatherTimeout: this.config.iceStunGatherTimeout,\n turnConnectTimeout: this.config.iceTurnConnectTimeout,\n turnTlsOptions: this.config.turnTlsOptions,\n turnUdpFamily: this.config.turnUdpFamily,\n useLinkLocalAddress: this.config.iceUseLinkLocalAddress,\n });\n\n if (existing) {\n iceGatherer.connection.localUsername = existing.connection.localUsername;\n iceGatherer.connection.localPassword = existing.connection.localPassword;\n }\n\n iceGatherer.onGatheringStateChange.subscribe(() => {\n this.updateIceGatheringState();\n });\n this.updateIceGatheringState();\n\n const iceTransport = new RTCIceTransport(iceGatherer);\n iceTransport.onStateChange.subscribe(() => {\n this.updateIceConnectionState();\n });\n\n const dtlsTransport = new RTCDtlsTransport(\n this.config,\n iceTransport,\n this.certificate,\n srtpProfiles,\n );\n\n return dtlsTransport;\n }\n\n /**\n * sdpMid / sdpMLineIndex は ICE transport を所有する受け入れ済み m-line\n * (BUNDLE なら tag) を呼び出し側で解決して渡す。\n */\n handleNewIceCandidate({\n candidate,\n sdpMid,\n sdpMLineIndex,\n }: {\n candidate: IceCandidate;\n sdpMid?: string;\n sdpMLineIndex?: number;\n }) {\n candidate.sdpMid = sdpMid;\n candidate.sdpMLineIndex = sdpMLineIndex;\n\n if (\n candidate.foundation &&\n !candidate.foundation.startsWith(\"candidate:\")\n ) {\n candidate.foundation = \"candidate:\" + candidate.foundation;\n }\n\n this.onIceCandidate.execute(candidate);\n\n return candidate;\n }\n\n async addIceCandidate(\n sdp: SessionDescription,\n candidateMessage: RTCIceCandidate | RTCIceCandidateInit | null,\n ) {\n const candidateText = candidateMessage?.candidate;\n const sdpMid = candidateMessage?.sdpMid;\n const sdpMLineIndex = candidateMessage?.sdpMLineIndex;\n const usernameFragment = candidateMessage?.usernameFragment;\n const isEndOfCandidates =\n candidateMessage == null || candidateText == null || candidateText === \"\";\n const mediaIndices = this.resolveCandidateMediaIndices({\n sdp,\n isEndOfCandidates,\n sdpMid,\n sdpMLineIndex,\n usernameFragment,\n });\n\n if (isEndOfCandidates) {\n const candidateTarget = mediaIndices\n .map((index) => this.getTransportByMLineIndex(sdp, index))\n .filter(\n (iceTransport): iceTransport is RTCIceTransport => !!iceTransport,\n )\n .reduce((acc: RTCIceTransport[], transport) => {\n if (!acc.find(({ id }) => id === transport.id)) {\n acc.push(transport);\n }\n return acc;\n }, []);\n\n await Promise.all(\n candidateTarget.map((iceTransport) =>\n iceTransport.addRemoteCandidate(undefined),\n ),\n );\n return {\n kind: \"end-of-candidates\" as const,\n mediaIndices,\n };\n }\n\n const candidate = IceCandidate.fromJSON(candidateMessage);\n if (!candidate) {\n throw createWebRtcDomException(\n \"OperationError\",\n \"Failed to parse ICE candidate\",\n );\n }\n\n const targetMediaIndex = mediaIndices[0];\n const targetMedia = sdp.media[targetMediaIndex];\n if (!targetMedia) {\n throw createWebRtcDomException(\n \"OperationError\",\n \"ICE media section not found\",\n );\n }\n candidate.sdpMid = targetMedia.rtp.muxId ?? undefined;\n candidate.sdpMLineIndex = targetMediaIndex;\n\n const iceTransport = this.getTransportByMLineIndex(sdp, targetMediaIndex);\n\n if (!iceTransport) {\n if (this.isRejectedMedia(targetMedia)) {\n // 拒否 / 停止した m-line の候補は MID / index を保ったまま記録だけする\n return {\n kind: \"candidate\" as const,\n candidate,\n mediaIndices: [targetMediaIndex],\n };\n }\n throw createWebRtcDomException(\n \"OperationError\",\n \"ICE transport not found for candidate\",\n );\n }\n\n await iceTransport.addRemoteCandidate(candidate);\n return {\n kind: \"candidate\" as const,\n candidate,\n mediaIndices: [targetMediaIndex],\n };\n }\n\n private resolveCandidateMediaIndices({\n sdp,\n isEndOfCandidates,\n sdpMid,\n sdpMLineIndex,\n usernameFragment,\n }: {\n sdp: SessionDescription;\n isEndOfCandidates: boolean;\n sdpMid?: string | null;\n sdpMLineIndex?: number | null;\n usernameFragment?: string | null;\n }) {\n let mediaIndices: number[];\n\n if (typeof sdpMid === \"string\") {\n const mediaIndex = sdp.media.findIndex(\n (media) => media.rtp.muxId === sdpMid,\n );\n if (mediaIndex < 0) {\n throw createWebRtcDomException(\n \"OperationError\",\n \"Media section for sdpMid was not found\",\n );\n }\n mediaIndices = [mediaIndex];\n } else if (typeof sdpMLineIndex === \"number\") {\n if (sdpMLineIndex < 0 || sdpMLineIndex >= sdp.media.length) {\n throw createWebRtcDomException(\n \"OperationError\",\n \"Media section for sdpMLineIndex was not found\",\n );\n }\n mediaIndices = [sdpMLineIndex];\n } else if (isEndOfCandidates) {\n mediaIndices = sdp.media.map((_, index) => index);\n } else {\n throw createWebRtcTypeError(\n \"sdpMid or sdpMLineIndex must be provided with a candidate\",\n );\n }\n\n if (typeof usernameFragment === \"string\") {\n const matchingIndices = mediaIndices.filter(\n (index) =>\n sdp.media[index]?.iceParams?.usernameFragment === usernameFragment,\n );\n if (matchingIndices.length === 0) {\n throw createWebRtcDomException(\n \"OperationError\",\n \"No media section matched the ICE usernameFragment\",\n );\n }\n mediaIndices = matchingIndices;\n }\n\n return mediaIndices;\n }\n\n private isRejectedMedia(media: MediaDescription) {\n if (media.port === 0) {\n return true;\n }\n if (![\"audio\", \"video\"].includes(media.kind)) {\n return false;\n }\n const transceiver = this.transceiverManager\n .getTransceivers()\n .find((t) => t.mid != undefined && t.mid === media.rtp.muxId);\n return (\n !transceiver ||\n transceiver.stopped ||\n transceiver.stopping ||\n transceiver.pendingRejection\n );\n }\n\n private getTransportByMid(mid?: string) {\n if (!mid) {\n return;\n }\n let iceTransport: RTCIceTransport | undefined;\n\n const transceiver = this.transceiverManager\n .getTransceivers()\n .find((t) => t.mid === mid);\n if (transceiver) {\n iceTransport = transceiver.dtlsTransport?.iceTransport;\n } else if (!iceTransport && this.sctpManager.sctpTransport?.mid === mid) {\n iceTransport = this.sctpManager.sctpTransport.dtlsTransport.iceTransport;\n }\n\n if (iceTransport?.state === \"closed\") {\n return;\n }\n return iceTransport;\n }\n\n private getTransportByMLineIndex(sdp: SessionDescription, index: number) {\n const media = sdp.media[index];\n if (!media) {\n return;\n }\n const transport = this.getTransportByMid(media.rtp.muxId!);\n\n return transport;\n }\n\n restartIce() {\n for (const transport of this.iceTransports) {\n transport.restart();\n }\n // restart() resets each gatherer to \"new\"; refresh the aggregate cache\n // even if a gatherer failed to emit onGatheringStateChange.\n this.updateIceGatheringState();\n }\n\n setLocalRole({\n type,\n role,\n roleOfTransport,\n }: {\n type: \"offer\" | \"answer\";\n /**transport 個別の role がない場合に使う local description 先頭の role */\n role: \"auto\" | \"client\" | \"server\" | undefined;\n /**local description でその transport を使う m-line の role */\n roleOfTransport?: Map<RTCDtlsTransport, \"auto\" | \"client\" | \"server\">;\n }) {\n for (const dtlsTransport of this.dtlsTransports) {\n const iceTransport = dtlsTransport.iceTransport;\n if (iceTransport.connection.iceLite) {\n iceTransport.connection.iceControlling = false;\n } else if (iceTransport.connection.remoteIsLite) {\n // RFC 8445 S6.1.1\n iceTransport.connection.iceControlling = true;\n } else if (type === \"offer\") {\n iceTransport.connection.iceControlling = true;\n } else {\n iceTransport.connection.iceControlling = false;\n }\n\n // # set DTLS role for mediasoup\n if (type === \"answer\") {\n const transportRole = roleOfTransport?.get(dtlsTransport) ?? role;\n if (transportRole) {\n dtlsTransport.role = transportRole;\n }\n }\n }\n }\n\n // https://w3c.github.io/webrtc-pc/#dom-rtcicegatheringstate\n private updateIceGatheringState() {\n const all = this.iceTransports;\n\n function allMatch(...state: IceGathererState[]) {\n return (\n all.filter((check) => state.includes(check.gatheringState)).length ===\n all.length\n );\n }\n\n let newState: IceGathererState;\n\n if (all.length && allMatch(\"complete\")) {\n newState = \"complete\";\n } else if (!all.length || allMatch(\"new\", \"complete\")) {\n newState = \"new\";\n } else if (all.map((check) => check.gatheringState).includes(\"gathering\")) {\n newState = \"gathering\";\n } else {\n newState = \"new\";\n }\n\n if (this.iceGatheringState === newState) {\n return;\n }\n\n this.iceGatheringState = newState;\n this.iceGatheringStateChange.execute(newState);\n }\n\n // https://w3c.github.io/webrtc-pc/#dom-rtciceconnectionstate\n updateIceConnectionState() {\n const all = this.iceTransports;\n let newState: RTCIceConnectionState;\n\n function allMatch(...state: RTCIceConnectionState[]) {\n return (\n all.filter((check) => state.includes(check.state)).length === all.length\n );\n }\n\n function anyMatch(...state: RTCIceConnectionState[]) {\n return all.some((check) => state.includes(check.state));\n }\n\n if (this.connectionState === \"closed\") {\n newState = \"closed\";\n } else if (anyMatch(\"failed\")) {\n newState = \"failed\";\n } else if (anyMatch(\"disconnected\")) {\n newState = \"disconnected\";\n } else if (allMatch(\"new\", \"closed\")) {\n newState = \"new\";\n } else if (anyMatch(\"new\", \"checking\")) {\n newState = \"checking\";\n } else if (allMatch(\"completed\", \"closed\")) {\n newState = \"completed\";\n } else if (allMatch(\"connected\", \"completed\", \"closed\")) {\n newState = \"connected\";\n } else {\n // unreachable?\n newState = \"new\";\n }\n\n if (this.iceConnectionState === newState) {\n return;\n }\n\n log(\"iceConnectionStateChange\", newState);\n this.iceConnectionState = newState;\n this.iceConnectionStateChange.execute(newState);\n\n // Runtime ICE failure (e.g. RFC 7675 consent expiry) must surface on\n // PeerConnection.connectionState without treating it as an explicit close().\n if (newState === \"failed\" && this.connectionState !== \"closed\") {\n this.setConnectionState(\"failed\");\n } else if (\n newState === \"disconnected\" &&\n this.connectionState === \"connected\"\n ) {\n this.setConnectionState(\"disconnected\");\n }\n }\n\n /**\n * 未収集 (gatheringState=new) の ICE transport だけ候補を収集する。\n * 収集済み transport は gather() が何もしないので、確立済み BUNDLE の transport は再収集されず、\n * BUNDLE group 外に新設した独立 transport だけが候補を収集する。\n */\n async gatherCandidates() {\n await Promise.allSettled(\n this.iceTransports\n .filter((iceTransport) => iceTransport.state !== \"closed\")\n .map((iceTransport) => iceTransport.gather()),\n ).catch((e) => {\n log(\"gatherCandidates failed\", e);\n });\n }\n\n setConnectionState(state: ConnectionState) {\n if (this.connectionState === state) {\n return;\n }\n log(\"connectionStateChange\", state);\n this.connectionState = state;\n this.connectionStateChange.execute(state);\n }\n\n async getStats(timestamp?: number): Promise<RTCStats[]> {\n const stats: RTCStats[] = [];\n\n for (const dtlsTransport of this.dtlsTransports) {\n const transportStats = await dtlsTransport.getStats(timestamp);\n if (transportStats) {\n stats.push(...transportStats);\n }\n }\n\n return stats;\n }\n\n async ensureCerts() {\n if (!this.certificate) {\n this.certificate = await RTCDtlsTransport.SetupCertificate();\n }\n\n for (const dtlsTransport of this.dtlsTransports) {\n dtlsTransport.localCertificate = this.certificate;\n }\n }\n\n async close() {\n this.setConnectionState(\"closed\");\n\n await Promise.allSettled([...this.allDtlsTransports.map((t) => t.stop())]);\n\n this.iceGatheringStateChange.allUnsubscribe();\n this.iceConnectionStateChange.allUnsubscribe();\n this.onIceCandidate.allUnsubscribe();\n this.connectionStateChange.allUnsubscribe();\n }\n}\n\nfunction uniqueTransports(transports: (RTCDtlsTransport | undefined)[]) {\n return transports.reduce((acc: RTCDtlsTransport[], cur) => {\n if (cur && !acc.map((d) => d.id).includes(cur.id)) {\n acc.push(cur);\n }\n return acc;\n }, []);\n}\n\nconst srtpProfiles = [\n SRTP_PROFILE.SRTP_AEAD_AES_128_GCM, // prefer\n SRTP_PROFILE.SRTP_AES128_CM_HMAC_SHA1_80,\n];\n"]}
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import { Event } from "./imports/common";
|
|
2
|
-
import { MediaStream, type MediaStreamTrack, type RTCRtpParameters, type RTCRtpReceiveParameters, RTCRtpReceiver, RTCRtpSender, RTCRtpTransceiver, type RtpRouter, type TransceiverOptions } from "./media";
|
|
2
|
+
import { MediaStream, type MediaStreamTrack, type RTCRtpCodecParameters, type RTCRtpParameters, type RTCRtpReceiveParameters, RTCRtpReceiver, RTCRtpSender, RTCRtpTransceiver, type RtpRouter, type TransceiverOptions } from "./media";
|
|
3
3
|
import type { RTCStats } from "./media/stats";
|
|
4
|
-
import {
|
|
5
|
-
import { type MediaDescription } from "./sdp";
|
|
4
|
+
import type { PeerConfig } from "./peerConnection";
|
|
5
|
+
import { type MediaDescription, type SessionDescription } from "./sdp";
|
|
6
6
|
import type { RTCDtlsTransport } from "./transport/dtls";
|
|
7
7
|
import type { Kind } from "./types/domain";
|
|
8
8
|
export declare class TransceiverManager {
|
|
@@ -10,6 +10,8 @@ export declare class TransceiverManager {
|
|
|
10
10
|
private readonly config;
|
|
11
11
|
private readonly router;
|
|
12
12
|
private readonly transceivers;
|
|
13
|
+
private readonly watched;
|
|
14
|
+
private remoteOfferSnapshot?;
|
|
13
15
|
readonly onTransceiverAdded: Event<[RTCRtpTransceiver]>;
|
|
14
16
|
readonly onRemoteTransceiverAdded: Event<[RTCRtpTransceiver]>;
|
|
15
17
|
readonly onTrack: Event<[{
|
|
@@ -25,13 +27,96 @@ export declare class TransceiverManager {
|
|
|
25
27
|
getTransceiverByMLineIndex(index: number): RTCRtpTransceiver | undefined;
|
|
26
28
|
pushTransceiver(t: RTCRtpTransceiver): void;
|
|
27
29
|
replaceTransceiver(t: RTCRtpTransceiver, index: number): void;
|
|
28
|
-
|
|
30
|
+
/**m-line から外れた transceiver の購読を解除する */
|
|
31
|
+
private unwatchTransceiver;
|
|
32
|
+
private watchTransceiver;
|
|
33
|
+
/**
|
|
34
|
+
* 拒否 / 停止の交渉が確定した port 0 の位置のうち、同じ kind で
|
|
35
|
+
* まだ他の transceiver が予約していないものを返す。
|
|
36
|
+
* stopping (未交渉) の位置は先取りしない。
|
|
37
|
+
*/
|
|
38
|
+
private findReusableTransceiver;
|
|
39
|
+
/**旧 transceiver を m-line から外し、同じ位置に新しい transceiver を置く */
|
|
40
|
+
private takeOverMLine;
|
|
41
|
+
/**
|
|
42
|
+
* 既存の未関連付け transceiver を remote m-line の位置に関連付ける。
|
|
43
|
+
* 同じ位置に停止済みの旧 transceiver があれば m-line から外し、配列上でも置き換える。
|
|
44
|
+
* (旧 transceiver が位置を持ったままだと MID の割り当て先が重複する)
|
|
45
|
+
*/
|
|
46
|
+
associateMLine(transceiver: RTCRtpTransceiver, mLineIndex: number): void;
|
|
47
|
+
/**
|
|
48
|
+
* remote offer が定義した位置のうち、関連付けられなかった未交渉 transceiver の予約を解除する。
|
|
49
|
+
* (remote が予約位置を別 kind や別 transceiver で再利用した場合、次の offer で末尾に追加させる)
|
|
50
|
+
*/
|
|
51
|
+
releaseUnassociatedReservations(associated: Set<RTCRtpTransceiver>, mLineCount: number): void;
|
|
52
|
+
addTransceiver(trackOrKind: Kind | MediaStreamTrack, dtlsTransport?: RTCDtlsTransport, options?: Partial<TransceiverOptions>, { remoteMLineIndex, }?: {
|
|
53
|
+
/**remote offer 起因で作る場合の m-line index。確定済み停止位置の自動再利用は行わない */
|
|
54
|
+
remoteMLineIndex?: number;
|
|
55
|
+
}): RTCRtpTransceiver;
|
|
29
56
|
addTrack(track: MediaStreamTrack, streams?: MediaStream[]): RTCRtpTransceiver;
|
|
30
|
-
|
|
57
|
+
/**
|
|
58
|
+
* sender から track を外す。
|
|
59
|
+
* @returns 交渉が必要な変更をした場合 true (呼び出し側が negotiationneeded を要求する)
|
|
60
|
+
*/
|
|
61
|
+
removeTrack(sender: RTCRtpSender): boolean;
|
|
31
62
|
assignTransceiverCodecs(transceiver: RTCRtpTransceiver): void;
|
|
63
|
+
private filterCodecsByDirection;
|
|
64
|
+
private validateTrackForTransceiver;
|
|
32
65
|
getLocalRtpParams(transceiver: RTCRtpTransceiver): RTCRtpParameters;
|
|
33
66
|
getRemoteRtpParams(media: MediaDescription, transceiver: RTCRtpTransceiver): RTCRtpReceiveParameters;
|
|
34
|
-
|
|
67
|
+
/**
|
|
68
|
+
* remote offer と local (source constraint + preferences) から
|
|
69
|
+
* answer 用の codec を再解決し、sender/receiver の codec 状態も
|
|
70
|
+
* 新しい negotiated codec に同期する。
|
|
71
|
+
* setCodecPreferences() による無効化後に createAnswer() から呼ばれる。
|
|
72
|
+
* direction / headerExtensions / onTrack は setRemoteDescription() 時の
|
|
73
|
+
* まま変えない (track イベントの重複発火を避ける)。
|
|
74
|
+
*/
|
|
75
|
+
resyncAnswerCodecs(transceiver: RTCRtpTransceiver, remoteMedia: MediaDescription): void;
|
|
76
|
+
/**
|
|
77
|
+
* remote offer と local (source constraint + preferences) から
|
|
78
|
+
* answer 用の codec だけを再解決する (sender/receiver の同期なし)。
|
|
79
|
+
* setRemoteRTP() の交渉部分として使う。
|
|
80
|
+
*/
|
|
81
|
+
private resolveRemoteCodecSet;
|
|
82
|
+
refreshAnswerCodecs(transceiver: RTCRtpTransceiver, remoteMedia: MediaDescription): void;
|
|
83
|
+
/**
|
|
84
|
+
* remote SDP の全 audio/video m-line の codec を副作用なしで解決する。
|
|
85
|
+
* transceiver の対応付けは本適用と同じ resolver を使い、検証と適用の判定をずらさない。
|
|
86
|
+
* - port 0、停止済み / 停止中の m-line は codec 解決をしない (空)
|
|
87
|
+
* - local capability と MIME が 1 つも一致しない m-line は空とし、
|
|
88
|
+
* offer は setRemoteRTP() で拒否 (port 0 answer)、answer/pranswer は
|
|
89
|
+
* SDPManager が InvalidAccessError とする (Issue #705)
|
|
90
|
+
* - source constraint / preference / pending offer との不一致は NotSupportedError
|
|
91
|
+
*/
|
|
92
|
+
planRemoteRtpCodecs(remoteSdp: SessionDescription, findTransceiver: (remoteMedia: MediaDescription, index: number) => RTCRtpTransceiver | undefined): Map<number, RTCRtpCodecParameters[]>;
|
|
93
|
+
/**
|
|
94
|
+
* remote m-line を transceiver に適用する。
|
|
95
|
+
* codecs は planRemoteRtpCodecs() で検証済みの解決結果を渡す。
|
|
96
|
+
* codec が空、または remote port 0 の m-line は拒否として扱い、
|
|
97
|
+
* sender/receiver 準備・router 登録・onTrack・TWCC を行わない。
|
|
98
|
+
* @returns 受け入れた (RTP を流す) 場合 true
|
|
99
|
+
*/
|
|
100
|
+
setRemoteRTP(transceiver: RTCRtpTransceiver, remoteMedia: MediaDescription, type: "offer" | "answer" | "pranswer", mLineIndex: number, codecs: RTCRtpCodecParameters[]): boolean;
|
|
101
|
+
/**
|
|
102
|
+
* remote offer 適用前の transceiver 対応を保存する。
|
|
103
|
+
* 同じ offer/answer 交換中に複数回呼ばれても最初の状態を保持する。
|
|
104
|
+
*/
|
|
105
|
+
beginRemoteOffer(): void;
|
|
106
|
+
/**
|
|
107
|
+
* local answer の確定で、拒否予定の m-line を停止・解放する。
|
|
108
|
+
* remote SDP 起因の停止なので negotiationneeded は要求しない。
|
|
109
|
+
*/
|
|
110
|
+
commitRemoteOffer(): void;
|
|
111
|
+
/**remote offer の rollback で transceiver 対応を元に戻す */
|
|
112
|
+
rollbackRemoteOffer(): void;
|
|
113
|
+
/**
|
|
114
|
+
* answer 確定後に、stopping のまま交渉対象になり得ない transceiver の停止を確定する。
|
|
115
|
+
* (MID が確定済み local description の非ゼロ m-line にない = offer から外れる)
|
|
116
|
+
* @param negotiatedMids 確定済み local description の非ゼロ port の MID
|
|
117
|
+
* @returns 次の自分の offer で port 0 を交渉すべき transceiver があるか
|
|
118
|
+
*/
|
|
119
|
+
settleStoppingTransceivers(negotiatedMids: Set<string>): boolean;
|
|
35
120
|
collectStats(timestamp: number): RTCStats[];
|
|
36
121
|
getStatsRootIds(selector: MediaStreamTrack | null | undefined): string[];
|
|
37
122
|
/**
|