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.
Files changed (166) hide show
  1. package/README.md +116 -113
  2. package/lib/common/src/transport.d.ts +22 -2
  3. package/lib/common/src/transport.js +84 -26
  4. package/lib/common/src/transport.js.map +1 -1
  5. package/lib/ice/src/exceptions.d.ts +9 -0
  6. package/lib/ice/src/exceptions.js +23 -1
  7. package/lib/ice/src/exceptions.js.map +1 -1
  8. package/lib/ice/src/ice.d.ts +40 -0
  9. package/lib/ice/src/ice.js +194 -28
  10. package/lib/ice/src/ice.js.map +1 -1
  11. package/lib/ice/src/iceBase.d.ts +26 -0
  12. package/lib/ice/src/iceBase.js.map +1 -1
  13. package/lib/ice/src/stun/const.d.ts +7 -0
  14. package/lib/ice/src/stun/const.js +8 -0
  15. package/lib/ice/src/stun/const.js.map +1 -1
  16. package/lib/ice/src/stun/protocol.js +1 -4
  17. package/lib/ice/src/stun/protocol.js.map +1 -1
  18. package/lib/ice/src/stun/tcpProtocol.d.ts +7 -1
  19. package/lib/ice/src/stun/tcpProtocol.js +65 -14
  20. package/lib/ice/src/stun/tcpProtocol.js.map +1 -1
  21. package/lib/ice/src/stun/transaction.d.ts +12 -1
  22. package/lib/ice/src/stun/transaction.js +37 -4
  23. package/lib/ice/src/stun/transaction.js.map +1 -1
  24. package/lib/ice/src/turn/protocol.d.ts +40 -15
  25. package/lib/ice/src/turn/protocol.js +141 -32
  26. package/lib/ice/src/turn/protocol.js.map +1 -1
  27. package/lib/ice/src/types/model.d.ts +8 -0
  28. package/lib/ice/src/types/model.js.map +1 -1
  29. package/lib/index.mjs +6175 -4073
  30. package/lib/nonstandard/index.mjs +286 -1003
  31. package/lib/polyfill/dom.mjs +23794 -0
  32. package/lib/polyfill/index.mjs +23794 -0
  33. package/lib/rtp/src/extra/container/mp4/container.js +12 -4
  34. package/lib/rtp/src/extra/container/mp4/container.js.map +1 -1
  35. package/lib/rtp/src/extra/processor/mp4.js +8 -3
  36. package/lib/rtp/src/extra/processor/mp4.js.map +1 -1
  37. package/lib/rtp/src/extra/processor/mp4Callback.js +3 -1
  38. package/lib/rtp/src/extra/processor/mp4Callback.js.map +1 -1
  39. package/lib/sctp/src/chunk.d.ts +5 -0
  40. package/lib/sctp/src/chunk.js +16 -11
  41. package/lib/sctp/src/chunk.js.map +1 -1
  42. package/lib/sctp/src/index.d.ts +3 -1
  43. package/lib/sctp/src/index.js +10 -1
  44. package/lib/sctp/src/index.js.map +1 -1
  45. package/lib/sctp/src/sctp.d.ts +12 -3
  46. package/lib/sctp/src/sctp.js +51 -18
  47. package/lib/sctp/src/sctp.js.map +1 -1
  48. package/lib/webrtc/src/const.js +2 -0
  49. package/lib/webrtc/src/const.js.map +1 -1
  50. package/lib/webrtc/src/errors.d.ts +9 -1
  51. package/lib/webrtc/src/errors.js +19 -0
  52. package/lib/webrtc/src/errors.js.map +1 -1
  53. package/lib/webrtc/src/media/codec.d.ts +5 -0
  54. package/lib/webrtc/src/media/codec.js +21 -0
  55. package/lib/webrtc/src/media/codec.js.map +1 -1
  56. package/lib/webrtc/src/media/codecCompatibility.d.ts +23 -0
  57. package/lib/webrtc/src/media/codecCompatibility.js +138 -0
  58. package/lib/webrtc/src/media/codecCompatibility.js.map +1 -0
  59. package/lib/webrtc/src/media/index.d.ts +1 -0
  60. package/lib/webrtc/src/media/index.js +1 -0
  61. package/lib/webrtc/src/media/index.js.map +1 -1
  62. package/lib/webrtc/src/media/router.d.ts +2 -0
  63. package/lib/webrtc/src/media/router.js +23 -3
  64. package/lib/webrtc/src/media/router.js.map +1 -1
  65. package/lib/webrtc/src/media/rtpReceiver.d.ts +12 -0
  66. package/lib/webrtc/src/media/rtpReceiver.js +35 -0
  67. package/lib/webrtc/src/media/rtpReceiver.js.map +1 -1
  68. package/lib/webrtc/src/media/rtpSender.d.ts +65 -4
  69. package/lib/webrtc/src/media/rtpSender.js +264 -35
  70. package/lib/webrtc/src/media/rtpSender.js.map +1 -1
  71. package/lib/webrtc/src/media/rtpTransceiver.d.ts +42 -0
  72. package/lib/webrtc/src/media/rtpTransceiver.js +157 -4
  73. package/lib/webrtc/src/media/rtpTransceiver.js.map +1 -1
  74. package/lib/webrtc/src/media/track.d.ts +29 -1
  75. package/lib/webrtc/src/media/track.js +164 -5
  76. package/lib/webrtc/src/media/track.js.map +1 -1
  77. package/lib/webrtc/src/nonstandard/index.d.ts +0 -1
  78. package/lib/webrtc/src/nonstandard/index.js +0 -1
  79. package/lib/webrtc/src/nonstandard/index.js.map +1 -1
  80. package/lib/webrtc/src/nonstandard/recorder/writer/webm.js +2 -1
  81. package/lib/webrtc/src/nonstandard/recorder/writer/webm.js.map +1 -1
  82. package/lib/webrtc/src/nonstandard/userMedia.d.ts +1 -2
  83. package/lib/webrtc/src/nonstandard/userMedia.js +30 -14
  84. package/lib/webrtc/src/nonstandard/userMedia.js.map +1 -1
  85. package/lib/webrtc/src/peerConnection.d.ts +126 -5
  86. package/lib/webrtc/src/peerConnection.js +609 -136
  87. package/lib/webrtc/src/peerConnection.js.map +1 -1
  88. package/lib/webrtc/src/polyfill/api.d.ts +14 -0
  89. package/lib/webrtc/src/polyfill/api.js +23 -0
  90. package/lib/webrtc/src/polyfill/api.js.map +1 -0
  91. package/lib/webrtc/src/polyfill/browserIdentity.d.ts +11 -0
  92. package/lib/webrtc/src/polyfill/browserIdentity.js +59 -0
  93. package/lib/webrtc/src/polyfill/browserIdentity.js.map +1 -0
  94. package/lib/webrtc/src/polyfill/dom.d.ts +11 -0
  95. package/lib/webrtc/src/polyfill/dom.js +18 -0
  96. package/lib/webrtc/src/polyfill/dom.js.map +1 -0
  97. package/lib/webrtc/src/polyfill/existingMediaDevices.d.ts +2 -0
  98. package/lib/webrtc/src/polyfill/existingMediaDevices.js +22 -0
  99. package/lib/webrtc/src/polyfill/existingMediaDevices.js.map +1 -0
  100. package/lib/webrtc/src/polyfill/globals.d.ts +28 -0
  101. package/lib/webrtc/src/polyfill/globals.js +3 -0
  102. package/lib/webrtc/src/polyfill/globals.js.map +1 -0
  103. package/lib/webrtc/src/polyfill/index.d.ts +2 -0
  104. package/lib/webrtc/src/polyfill/index.js +19 -0
  105. package/lib/webrtc/src/polyfill/index.js.map +1 -0
  106. package/lib/webrtc/src/polyfill/install.d.ts +13 -0
  107. package/lib/webrtc/src/polyfill/install.js +266 -0
  108. package/lib/webrtc/src/polyfill/install.js.map +1 -0
  109. package/lib/webrtc/src/polyfill/mediaDevices.d.ts +38 -0
  110. package/lib/webrtc/src/polyfill/mediaDevices.js +228 -0
  111. package/lib/webrtc/src/polyfill/mediaDevices.js.map +1 -0
  112. package/lib/webrtc/src/polyfill/mediaRegister.d.ts +51 -0
  113. package/lib/webrtc/src/polyfill/mediaRegister.js +14 -0
  114. package/lib/webrtc/src/polyfill/mediaRegister.js.map +1 -0
  115. package/lib/webrtc/src/polyfill/peerConnectionConfig.d.ts +3 -0
  116. package/lib/webrtc/src/polyfill/peerConnectionConfig.js +52 -0
  117. package/lib/webrtc/src/polyfill/peerConnectionConfig.js.map +1 -0
  118. package/lib/webrtc/src/polyfill/registers/callback.d.ts +16 -0
  119. package/lib/webrtc/src/polyfill/registers/callback.js +57 -0
  120. package/lib/webrtc/src/polyfill/registers/callback.js.map +1 -0
  121. package/lib/webrtc/src/polyfill/registers/empty.d.ts +2 -0
  122. package/lib/webrtc/src/polyfill/registers/empty.js +28 -0
  123. package/lib/webrtc/src/polyfill/registers/empty.js.map +1 -0
  124. package/lib/webrtc/src/polyfill/registers/mp4Webm.d.ts +36 -0
  125. package/lib/webrtc/src/polyfill/registers/mp4Webm.js +242 -0
  126. package/lib/webrtc/src/polyfill/registers/mp4Webm.js.map +1 -0
  127. package/lib/webrtc/src/polyfill/registers/rtpRtcp.d.ts +17 -0
  128. package/lib/webrtc/src/polyfill/registers/rtpRtcp.js +143 -0
  129. package/lib/webrtc/src/polyfill/registers/rtpRtcp.js.map +1 -0
  130. package/lib/webrtc/src/polyfill/rtcSessionDescription.d.ts +18 -0
  131. package/lib/webrtc/src/polyfill/rtcSessionDescription.js +36 -0
  132. package/lib/webrtc/src/polyfill/rtcSessionDescription.js.map +1 -0
  133. package/lib/webrtc/src/polyfill/rtpCodec.d.ts +17 -0
  134. package/lib/webrtc/src/polyfill/rtpCodec.js +93 -0
  135. package/lib/webrtc/src/polyfill/rtpCodec.js.map +1 -0
  136. package/lib/webrtc/src/polyfill/selectSettings.d.ts +31 -0
  137. package/lib/webrtc/src/polyfill/selectSettings.js +156 -0
  138. package/lib/webrtc/src/polyfill/selectSettings.js.map +1 -0
  139. package/lib/webrtc/src/polyfill/sourceIo.d.ts +21 -0
  140. package/lib/webrtc/src/polyfill/sourceIo.js +298 -0
  141. package/lib/webrtc/src/polyfill/sourceIo.js.map +1 -0
  142. package/lib/webrtc/src/polyfill/trackStop.d.ts +4 -0
  143. package/lib/webrtc/src/polyfill/trackStop.js +16 -0
  144. package/lib/webrtc/src/polyfill/trackStop.js.map +1 -0
  145. package/lib/webrtc/src/sctpManager.d.ts +2 -1
  146. package/lib/webrtc/src/sctpManager.js +5 -2
  147. package/lib/webrtc/src/sctpManager.js.map +1 -1
  148. package/lib/webrtc/src/sdp.d.ts +1 -1
  149. package/lib/webrtc/src/sdp.js +5 -6
  150. package/lib/webrtc/src/sdp.js.map +1 -1
  151. package/lib/webrtc/src/sdpManager.d.ts +38 -1
  152. package/lib/webrtc/src/sdpManager.js +236 -30
  153. package/lib/webrtc/src/sdpManager.js.map +1 -1
  154. package/lib/webrtc/src/secureTransportManager.d.ts +43 -12
  155. package/lib/webrtc/src/secureTransportManager.js +123 -47
  156. package/lib/webrtc/src/secureTransportManager.js.map +1 -1
  157. package/lib/webrtc/src/transceiverManager.d.ts +91 -6
  158. package/lib/webrtc/src/transceiverManager.js +477 -62
  159. package/lib/webrtc/src/transceiverManager.js.map +1 -1
  160. package/lib/webrtc/src/transport/ice.d.ts +8 -0
  161. package/lib/webrtc/src/transport/ice.js +17 -1
  162. package/lib/webrtc/src/transport/ice.js.map +1 -1
  163. package/lib/webrtc/src/transport/sctp.d.ts +3 -2
  164. package/lib/webrtc/src/transport/sctp.js +8 -2
  165. package/lib/webrtc/src/transport/sctp.js.map +1 -1
  166. package/package.json +13 -3
@@ -1,13 +1,12 @@
1
1
  import { Event } from "./imports/common";
2
- import type { RTCRtpTransceiver, TransceiverManager } from "./media";
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 { BundlePolicy, MediaDescription, SessionDescription } from "./sdp";
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
- createTransport(): RTCDtlsTransport;
33
- handleNewIceCandidate({ candidate, media, remoteIsBundled, transceiver, sctpTransport, bundlePolicy, }: {
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
- media?: MediaDescription;
36
- remoteIsBundled: boolean;
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
- gatherCandidates(remoteIsBundled: boolean): Promise<void>;
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
- const transports = [
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
- ].filter((t) => t != undefined);
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
- createTransport() {
111
- const existing = this.iceTransports.find((transport) => transport.state !== "closed");
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
- ...iceServerOptions,
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
- turnTransport,
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
- handleNewIceCandidate({ candidate, media, remoteIsBundled, transceiver, sctpTransport, bundlePolicy, }) {
151
- // Assign sdpMid and sdpMLineIndex
152
- if (bundlePolicy === "max-bundle" || remoteIsBundled) {
153
- candidate.sdpMLineIndex = 0;
154
- if (media) {
155
- candidate.sdpMid = media.rtp.muxId;
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.iceTransport;
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
- if (role) {
304
- dtlsTransport.role = role;
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
- async gatherCandidates(remoteIsBundled) {
387
- const connected = this.iceTransports.find((transport) => transport.state === "connected" || transport.state === "completed");
388
- if (remoteIsBundled && connected) {
389
- // no need to gather ice candidates on an existing bundled connection
390
- log("skipping ICE gathering for bundled connection");
391
- }
392
- else {
393
- await Promise.allSettled(this.iceTransports.map((iceTransport) => iceTransport.gather())).catch((e) => {
394
- // エラーハンドリングを追加 (例: ログ出力)
395
- log("gatherCandidates failed", e);
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.dtlsTransports.map((t) => t.stop())]);
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 { type PeerConfig } from "./peerConnection";
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
- addTransceiver(trackOrKind: Kind | MediaStreamTrack, dtlsTransport?: RTCDtlsTransport, options?: Partial<TransceiverOptions>): RTCRtpTransceiver;
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
- removeTrack(sender: RTCRtpSender): void;
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
- setRemoteRTP(transceiver: RTCRtpTransceiver, remoteMedia: MediaDescription, type: "offer" | "answer" | "pranswer", mLineIndex: number): void;
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
  /**