werift 0.22.9 → 0.24.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 (173) hide show
  1. package/README.md +46 -0
  2. package/lib/common/src/transport.d.ts +22 -9
  3. package/lib/common/src/transport.js +152 -25
  4. package/lib/common/src/transport.js.map +1 -1
  5. package/lib/dtls/src/flight/server/flight6.js +12 -2
  6. package/lib/dtls/src/flight/server/flight6.js.map +1 -1
  7. package/lib/dtls/src/server.js +6 -1
  8. package/lib/dtls/src/server.js.map +1 -1
  9. package/lib/dtls/src/socket.d.ts +1 -0
  10. package/lib/dtls/src/socket.js +3 -0
  11. package/lib/dtls/src/socket.js.map +1 -1
  12. package/lib/ice/src/candidate.d.ts +16 -1
  13. package/lib/ice/src/candidate.js +99 -15
  14. package/lib/ice/src/candidate.js.map +1 -1
  15. package/lib/ice/src/ice.d.ts +2 -0
  16. package/lib/ice/src/ice.js +171 -41
  17. package/lib/ice/src/ice.js.map +1 -1
  18. package/lib/ice/src/iceBase.d.ts +23 -2
  19. package/lib/ice/src/iceBase.js +63 -1
  20. package/lib/ice/src/iceBase.js.map +1 -1
  21. package/lib/ice/src/index.d.ts +2 -0
  22. package/lib/ice/src/index.js +2 -0
  23. package/lib/ice/src/index.js.map +1 -1
  24. package/lib/ice/src/stun/const.d.ts +1 -26
  25. package/lib/ice/src/stun/const.js +15 -54
  26. package/lib/ice/src/stun/const.js.map +1 -1
  27. package/lib/ice/src/stun/message.d.ts +1 -25
  28. package/lib/ice/src/stun/message.js +15 -149
  29. package/lib/ice/src/stun/message.js.map +1 -1
  30. package/lib/ice/src/stun/protocol.d.ts +1 -1
  31. package/lib/ice/src/stun/protocol.js +2 -2
  32. package/lib/ice/src/stun/protocol.js.map +1 -1
  33. package/lib/ice/src/stun/tcpFrame.d.ts +5 -0
  34. package/lib/ice/src/stun/tcpFrame.js +26 -0
  35. package/lib/ice/src/stun/tcpFrame.js.map +1 -0
  36. package/lib/ice/src/stun/tcpProtocol.d.ts +51 -0
  37. package/lib/ice/src/stun/tcpProtocol.js +326 -0
  38. package/lib/ice/src/stun/tcpProtocol.js.map +1 -0
  39. package/lib/ice/src/stun/transaction.d.ts +2 -1
  40. package/lib/ice/src/stun/transaction.js +9 -3
  41. package/lib/ice/src/stun/transaction.js.map +1 -1
  42. package/lib/ice/src/turn/frame.d.ts +1 -0
  43. package/lib/ice/src/turn/frame.js +18 -0
  44. package/lib/ice/src/turn/frame.js.map +1 -0
  45. package/lib/ice/src/turn/protocol.d.ts +9 -7
  46. package/lib/ice/src/turn/protocol.js +32 -44
  47. package/lib/ice/src/turn/protocol.js.map +1 -1
  48. package/lib/ice/src/types/model.d.ts +1 -1
  49. package/lib/ice/src/types/model.js.map +1 -1
  50. package/lib/{ice → ice-server}/src/stun/attributes.d.ts +12 -5
  51. package/lib/{ice → ice-server}/src/stun/attributes.js +60 -19
  52. package/lib/ice-server/src/stun/attributes.js.map +1 -0
  53. package/lib/ice-server/src/stun/const.d.ts +28 -0
  54. package/lib/ice-server/src/stun/const.js +88 -0
  55. package/lib/ice-server/src/stun/const.js.map +1 -0
  56. package/lib/ice-server/src/stun/message.d.ts +37 -0
  57. package/lib/ice-server/src/stun/message.js +190 -0
  58. package/lib/ice-server/src/stun/message.js.map +1 -0
  59. package/lib/ice-server/src/turn/auth.d.ts +1 -0
  60. package/lib/ice-server/src/turn/auth.js +10 -0
  61. package/lib/ice-server/src/turn/auth.js.map +1 -0
  62. package/lib/ice-server/src/turn/frame.d.ts +13 -0
  63. package/lib/ice-server/src/turn/frame.js +69 -0
  64. package/lib/ice-server/src/turn/frame.js.map +1 -0
  65. package/lib/index.mjs +3075 -883
  66. package/lib/nonstandard/index.mjs +1964 -447
  67. package/lib/rtp/src/extra/container/mp4/container.d.ts +9 -6
  68. package/lib/rtp/src/extra/container/mp4/container.js +258 -173
  69. package/lib/rtp/src/extra/container/mp4/container.js.map +1 -1
  70. package/lib/rtp/src/extra/container/mp4/h264.d.ts +1 -0
  71. package/lib/rtp/src/extra/container/mp4/h264.js +13 -0
  72. package/lib/rtp/src/extra/container/mp4/h264.js.map +1 -1
  73. package/lib/rtp/src/extra/processor/mp4.d.ts +11 -7
  74. package/lib/rtp/src/extra/processor/mp4.js +115 -60
  75. package/lib/rtp/src/extra/processor/mp4.js.map +1 -1
  76. package/lib/rtp/src/extra/processor/mp4Callback.d.ts +2 -3
  77. package/lib/rtp/src/extra/processor/mp4Callback.js +5 -3
  78. package/lib/rtp/src/extra/processor/mp4Callback.js.map +1 -1
  79. package/lib/rtp/src/index.d.ts +1 -0
  80. package/lib/rtp/src/index.js +1 -0
  81. package/lib/rtp/src/index.js.map +1 -1
  82. package/lib/rtp/src/srtp/cipher/ctr.d.ts +3 -3
  83. package/lib/rtp/src/srtp/cipher/ctr.js +25 -14
  84. package/lib/rtp/src/srtp/cipher/ctr.js.map +1 -1
  85. package/lib/rtp/src/srtp/cipher/gcm.d.ts +3 -3
  86. package/lib/rtp/src/srtp/cipher/gcm.js +57 -20
  87. package/lib/rtp/src/srtp/cipher/gcm.js.map +1 -1
  88. package/lib/rtp/src/srtp/cipher/index.d.ts +1 -1
  89. package/lib/rtp/src/srtp/cipher/index.js +1 -1
  90. package/lib/rtp/src/srtp/cipher/index.js.map +1 -1
  91. package/lib/rtp/src/srtp/context/srtp.d.ts +2 -1
  92. package/lib/rtp/src/srtp/context/srtp.js +22 -5
  93. package/lib/rtp/src/srtp/context/srtp.js.map +1 -1
  94. package/lib/rtp/src/srtp/error.d.ts +3 -0
  95. package/lib/rtp/src/srtp/error.js +11 -0
  96. package/lib/rtp/src/srtp/error.js.map +1 -0
  97. package/lib/rtp/src/srtp/packet.d.ts +5 -0
  98. package/lib/rtp/src/srtp/packet.js +48 -0
  99. package/lib/rtp/src/srtp/packet.js.map +1 -0
  100. package/lib/webrtc/src/dataChannel.d.ts +4 -2
  101. package/lib/webrtc/src/dataChannel.js +14 -4
  102. package/lib/webrtc/src/dataChannel.js.map +1 -1
  103. package/lib/webrtc/src/errors.d.ts +3 -0
  104. package/lib/webrtc/src/errors.js +11 -0
  105. package/lib/webrtc/src/errors.js.map +1 -0
  106. package/lib/webrtc/src/helper.d.ts +5 -1
  107. package/lib/webrtc/src/helper.js +33 -1
  108. package/lib/webrtc/src/helper.js.map +1 -1
  109. package/lib/webrtc/src/media/receiver/statistics.d.ts +4 -1
  110. package/lib/webrtc/src/media/receiver/statistics.js +22 -0
  111. package/lib/webrtc/src/media/receiver/statistics.js.map +1 -1
  112. package/lib/webrtc/src/media/rtpReceiver.d.ts +15 -2
  113. package/lib/webrtc/src/media/rtpReceiver.js +135 -20
  114. package/lib/webrtc/src/media/rtpReceiver.js.map +1 -1
  115. package/lib/webrtc/src/media/rtpSender.d.ts +32 -7
  116. package/lib/webrtc/src/media/rtpSender.js +177 -28
  117. package/lib/webrtc/src/media/rtpSender.js.map +1 -1
  118. package/lib/webrtc/src/media/rtpTransceiver.d.ts +13 -4
  119. package/lib/webrtc/src/media/rtpTransceiver.js +26 -5
  120. package/lib/webrtc/src/media/rtpTransceiver.js.map +1 -1
  121. package/lib/webrtc/src/media/stats.d.ts +15 -1
  122. package/lib/webrtc/src/media/stats.js +55 -1
  123. package/lib/webrtc/src/media/stats.js.map +1 -1
  124. package/lib/webrtc/src/media/track.d.ts +2 -1
  125. package/lib/webrtc/src/media/track.js +7 -1
  126. package/lib/webrtc/src/media/track.js.map +1 -1
  127. package/lib/webrtc/src/nonstandard/dummyMedia.d.ts +19 -0
  128. package/lib/webrtc/src/nonstandard/dummyMedia.js +157 -0
  129. package/lib/webrtc/src/nonstandard/dummyMedia.js.map +1 -0
  130. package/lib/webrtc/src/nonstandard/navigator.d.ts +18 -8
  131. package/lib/webrtc/src/nonstandard/navigator.js +96 -32
  132. package/lib/webrtc/src/nonstandard/navigator.js.map +1 -1
  133. package/lib/webrtc/src/nonstandard/userMedia/packetizer.d.ts +16 -0
  134. package/lib/webrtc/src/nonstandard/userMedia/packetizer.js +360 -0
  135. package/lib/webrtc/src/nonstandard/userMedia/packetizer.js.map +1 -0
  136. package/lib/webrtc/src/nonstandard/userMedia.d.ts +71 -31
  137. package/lib/webrtc/src/nonstandard/userMedia.js +454 -108
  138. package/lib/webrtc/src/nonstandard/userMedia.js.map +1 -1
  139. package/lib/webrtc/src/peerConnection.d.ts +185 -49
  140. package/lib/webrtc/src/peerConnection.js +477 -107
  141. package/lib/webrtc/src/peerConnection.js.map +1 -1
  142. package/lib/webrtc/src/sctpManager.d.ts +2 -2
  143. package/lib/webrtc/src/sctpManager.js +30 -9
  144. package/lib/webrtc/src/sctpManager.js.map +1 -1
  145. package/lib/webrtc/src/sdp.d.ts +10 -7
  146. package/lib/webrtc/src/sdp.js +39 -9
  147. package/lib/webrtc/src/sdp.js.map +1 -1
  148. package/lib/webrtc/src/sdpManager.d.ts +5 -4
  149. package/lib/webrtc/src/sdpManager.js +53 -31
  150. package/lib/webrtc/src/sdpManager.js.map +1 -1
  151. package/lib/webrtc/src/secureTransportManager.d.ts +13 -4
  152. package/lib/webrtc/src/secureTransportManager.js +101 -23
  153. package/lib/webrtc/src/secureTransportManager.js.map +1 -1
  154. package/lib/webrtc/src/transceiverManager.d.ts +5 -4
  155. package/lib/webrtc/src/transceiverManager.js +64 -64
  156. package/lib/webrtc/src/transceiverManager.js.map +1 -1
  157. package/lib/webrtc/src/transport/dtls.d.ts +16 -4
  158. package/lib/webrtc/src/transport/dtls.js +208 -35
  159. package/lib/webrtc/src/transport/dtls.js.map +1 -1
  160. package/lib/webrtc/src/transport/ice.d.ts +21 -3
  161. package/lib/webrtc/src/transport/ice.js +159 -30
  162. package/lib/webrtc/src/transport/ice.js.map +1 -1
  163. package/lib/webrtc/src/transport/sctp.d.ts +10 -3
  164. package/lib/webrtc/src/transport/sctp.js +44 -13
  165. package/lib/webrtc/src/transport/sctp.js.map +1 -1
  166. package/lib/webrtc/src/utils.d.ts +14 -4
  167. package/lib/webrtc/src/utils.js +138 -16
  168. package/lib/webrtc/src/utils.js.map +1 -1
  169. package/package.json +7 -4
  170. package/lib/ice/src/stun/attributes.js.map +0 -1
  171. package/lib/rtp/src/extra/container/mp4/mp4box.d.ts +0 -5
  172. package/lib/rtp/src/extra/container/mp4/mp4box.js +0 -32
  173. package/lib/rtp/src/extra/container/mp4/mp4box.js.map +0 -1
@@ -1,7 +1,8 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.defaultPeerConfig = exports.findCodecByMimeType = exports.RTCPeerConnection = void 0;
3
+ exports.RTCTrackEvent = exports.defaultPeerConfig = exports.findCodecByMimeType = exports.RTCPeerConnection = void 0;
4
4
  const crypto_1 = require("crypto");
5
+ const errors_1 = require("./errors");
5
6
  const helper_1 = require("./helper");
6
7
  const common_1 = require("./imports/common");
7
8
  const media_1 = require("./media");
@@ -10,11 +11,95 @@ const sctpManager_1 = require("./sctpManager");
10
11
  const sdp_1 = require("./sdp");
11
12
  const sdpManager_1 = require("./sdpManager");
12
13
  const secureTransportManager_1 = require("./secureTransportManager");
14
+ const sctp_1 = require("./transport/sctp");
13
15
  const utils_1 = require("./utils");
14
16
  const log = (0, common_1.debug)("werift:packages/webrtc/src/peerConnection.ts");
17
+ /**
18
+ * W3C compatibility notes kept near the public RTCPeerConnection surface so the
19
+ * reviewable diff does not depend on external PR text.
20
+ *
21
+ * - `current/pending*Description`, `canTrickleIceCandidates`, `sctp`,
22
+ * `addIceCandidate(null)`, and `RTCConfiguration` round-trip behavior are
23
+ * implemented here and covered by `tests/wpt/peerConnectionApiCompatibility.test.ts`.
24
+ * - `addIceCandidate()` also validates `sdpMid` / `sdpMLineIndex` /
25
+ * `usernameFragment` against the applied remote description and appends
26
+ * candidates or end-of-candidates markers to the corresponding m-section.
27
+ * The public API keeps werift's historical pre-SRD buffering behavior, while
28
+ * the WPT runner wraps the class to exercise strict spec rejection.
29
+ * - `bundlePolicy: "balanced"` is accepted for input compatibility but is
30
+ * normalized to werift's `"max-compat"` behavior, so `getConfiguration()`
31
+ * returns the normalized value.
32
+ * - `setLocalDescription()` keeps the historical `SessionDescription` return
33
+ * value for non-rollback calls, while `{ type: "rollback" }` resolves `void`
34
+ * to match the actual behavior without pretending to return a description.
35
+ * - API reference markdown is regenerated with `cd packages/webrtc && npm run doc`.
36
+ * The generated output lives under `packages/webrtc/doc/`; compatibility
37
+ * notes remain here and in the package README so review context is visible
38
+ * even when generated docs are not committed in the same change.
39
+ */
15
40
  class RTCPeerConnection extends helper_1.EventTarget {
41
+ get ondatachannel() {
42
+ return this.eventHandlers.ondatachannel ?? null;
43
+ }
44
+ set ondatachannel(value) {
45
+ this.eventHandlers.ondatachannel = value ?? undefined;
46
+ }
47
+ get onicecandidate() {
48
+ return this.eventHandlers.onicecandidate ?? null;
49
+ }
50
+ set onicecandidate(value) {
51
+ this.eventHandlers.onicecandidate = value ?? undefined;
52
+ }
53
+ get onicecandidateerror() {
54
+ return this.eventHandlers.onicecandidateerror ?? null;
55
+ }
56
+ set onicecandidateerror(value) {
57
+ this.eventHandlers.onicecandidateerror = value ?? undefined;
58
+ }
59
+ get onicegatheringstatechange() {
60
+ return this.eventHandlers.onicegatheringstatechange ?? null;
61
+ }
62
+ set onicegatheringstatechange(value) {
63
+ this.eventHandlers.onicegatheringstatechange = value ?? undefined;
64
+ }
65
+ get onnegotiationneeded() {
66
+ return this.eventHandlers.onnegotiationneeded ?? null;
67
+ }
68
+ set onnegotiationneeded(value) {
69
+ this.eventHandlers.onnegotiationneeded = value ?? undefined;
70
+ }
71
+ get onsignalingstatechange() {
72
+ return this.eventHandlers.onsignalingstatechange ?? null;
73
+ }
74
+ set onsignalingstatechange(value) {
75
+ this.eventHandlers.onsignalingstatechange = value ?? undefined;
76
+ }
77
+ get ontrack() {
78
+ return this.eventHandlers.ontrack ?? null;
79
+ }
80
+ set ontrack(value) {
81
+ this.eventHandlers.ontrack = value ?? undefined;
82
+ }
83
+ get onconnectionstatechange() {
84
+ return this.eventHandlers.onconnectionstatechange ?? null;
85
+ }
86
+ set onconnectionstatechange(value) {
87
+ this.eventHandlers.onconnectionstatechange = value ?? undefined;
88
+ }
89
+ get oniceconnectionstatechange() {
90
+ return this.eventHandlers.oniceconnectionstatechange ?? null;
91
+ }
92
+ set oniceconnectionstatechange(value) {
93
+ this.eventHandlers.oniceconnectionstatechange = value ?? undefined;
94
+ }
16
95
  constructor(config = {}) {
17
96
  super();
97
+ Object.defineProperty(this, "id", {
98
+ enumerable: true,
99
+ configurable: true,
100
+ writable: true,
101
+ value: (0, crypto_1.randomUUID)().toString()
102
+ });
18
103
  Object.defineProperty(this, "cname", {
19
104
  enumerable: true,
20
105
  configurable: true,
@@ -87,6 +172,24 @@ class RTCPeerConnection extends helper_1.EventTarget {
87
172
  writable: true,
88
173
  value: false
89
174
  });
175
+ Object.defineProperty(this, "lastCreatedAnswer", {
176
+ enumerable: true,
177
+ configurable: true,
178
+ writable: true,
179
+ value: void 0
180
+ });
181
+ Object.defineProperty(this, "lastCreatedOffer", {
182
+ enumerable: true,
183
+ configurable: true,
184
+ writable: true,
185
+ value: void 0
186
+ });
187
+ Object.defineProperty(this, "pendingRemoteCandidates", {
188
+ enumerable: true,
189
+ configurable: true,
190
+ writable: true,
191
+ value: []
192
+ });
90
193
  Object.defineProperty(this, "iceGatheringStateChange", {
91
194
  enumerable: true,
92
195
  configurable: true,
@@ -147,65 +250,18 @@ class RTCPeerConnection extends helper_1.EventTarget {
147
250
  writable: true,
148
251
  value: new common_1.Event()
149
252
  });
150
- Object.defineProperty(this, "ondatachannel", {
151
- enumerable: true,
152
- configurable: true,
153
- writable: true,
154
- value: void 0
155
- });
156
- Object.defineProperty(this, "onicecandidate", {
157
- enumerable: true,
158
- configurable: true,
159
- writable: true,
160
- value: void 0
161
- });
162
- Object.defineProperty(this, "onicecandidateerror", {
253
+ Object.defineProperty(this, "eventHandlers", {
163
254
  enumerable: true,
164
255
  configurable: true,
165
256
  writable: true,
166
- value: void 0
167
- });
168
- Object.defineProperty(this, "onicegatheringstatechange", {
169
- enumerable: true,
170
- configurable: true,
171
- writable: true,
172
- value: void 0
173
- });
174
- Object.defineProperty(this, "onnegotiationneeded", {
175
- enumerable: true,
176
- configurable: true,
177
- writable: true,
178
- value: void 0
179
- });
180
- Object.defineProperty(this, "onsignalingstatechange", {
181
- enumerable: true,
182
- configurable: true,
183
- writable: true,
184
- value: void 0
185
- });
186
- Object.defineProperty(this, "ontrack", {
187
- enumerable: true,
188
- configurable: true,
189
- writable: true,
190
- value: void 0
191
- });
192
- Object.defineProperty(this, "onconnectionstatechange", {
193
- enumerable: true,
194
- configurable: true,
195
- writable: true,
196
- value: void 0
197
- });
198
- Object.defineProperty(this, "oniceconnectionstatechange", {
199
- enumerable: true,
200
- configurable: true,
201
- writable: true,
202
- value: void 0
257
+ value: {}
203
258
  });
204
259
  Object.defineProperty(this, "needNegotiation", {
205
260
  enumerable: true,
206
261
  configurable: true,
207
262
  writable: true,
208
263
  value: async () => {
264
+ this.invalidateLastCreatedDescriptions();
209
265
  this.shouldNegotiationneeded = true;
210
266
  if (this.negotiationneeded || this.signalingState !== "stable") {
211
267
  return;
@@ -214,8 +270,10 @@ class RTCPeerConnection extends helper_1.EventTarget {
214
270
  setImmediate(() => {
215
271
  this.negotiationneeded = true;
216
272
  this.onNegotiationneeded.execute();
217
- if (this.onnegotiationneeded)
218
- this.onnegotiationneeded({});
273
+ if (this.onnegotiationneeded) {
274
+ this.onnegotiationneeded(new globalThis.Event("negotiationneeded"));
275
+ }
276
+ this.emit("negotiationneeded");
219
277
  });
220
278
  }
221
279
  });
@@ -227,13 +285,13 @@ class RTCPeerConnection extends helper_1.EventTarget {
227
285
  this.transceiverManager = new media_1.TransceiverManager(this.cname, this.config, this.router);
228
286
  this.transceiverManager.onTransceiverAdded.pipe(this.onTransceiverAdded);
229
287
  this.transceiverManager.onRemoteTransceiverAdded.pipe(this.onRemoteTransceiverAdded);
230
- this.transceiverManager.onTrack.subscribe(({ track, stream, transceiver }) => {
231
- const event = {
288
+ this.transceiverManager.onTrack.subscribe(({ track, streams, transceiver }) => {
289
+ const event = new RTCTrackEvent({
232
290
  track,
233
- streams: [stream],
291
+ streams,
234
292
  transceiver,
235
293
  receiver: transceiver.receiver,
236
- };
294
+ });
237
295
  this.onTrack.execute(track);
238
296
  this.emit("track", event);
239
297
  if (this.ontrack) {
@@ -244,7 +302,7 @@ class RTCPeerConnection extends helper_1.EventTarget {
244
302
  this.sctpManager = new sctpManager_1.SctpTransportManager();
245
303
  this.sctpManager.onDataChannel.subscribe((channel) => {
246
304
  this.onDataChannel.execute(channel);
247
- const event = { channel };
305
+ const event = { type: "datachannel", channel };
248
306
  this.ondatachannel?.(event);
249
307
  this.emit("datachannel", event);
250
308
  });
@@ -253,12 +311,18 @@ class RTCPeerConnection extends helper_1.EventTarget {
253
311
  sctpManager: this.sctpManager,
254
312
  transceiverManager: this.transceiverManager,
255
313
  });
256
- this.secureManager.iceGatheringStateChange.pipe(this.iceGatheringStateChange);
314
+ this.secureManager.iceGatheringStateChange.subscribe((state) => {
315
+ this.iceGatheringStateChange.execute(state);
316
+ this.onicegatheringstatechange?.(new globalThis.Event("icegatheringstatechange"));
317
+ this.emit("icegatheringstatechange");
318
+ });
257
319
  this.secureManager.iceConnectionStateChange.subscribe((state) => {
258
320
  if (state === "closed") {
259
321
  this.close();
260
322
  }
261
323
  this.iceConnectionStateChange.execute(state);
324
+ this.oniceconnectionstatechange?.();
325
+ this.emit("iceconnectionstatechange");
262
326
  });
263
327
  this.secureManager.connectionStateChange.subscribe((state) => {
264
328
  this.connectionStateChange.execute(state);
@@ -268,8 +332,12 @@ class RTCPeerConnection extends helper_1.EventTarget {
268
332
  this.secureManager.onIceCandidate.subscribe((candidate) => {
269
333
  const iceCandidate = candidate ? candidate.toJSON() : undefined;
270
334
  this.onIceCandidate.execute(iceCandidate);
271
- this.onicecandidate?.({ candidate: iceCandidate });
272
- this.emit("icecandidate", { candidate: iceCandidate });
335
+ const event = {
336
+ type: "icecandidate",
337
+ candidate: iceCandidate,
338
+ };
339
+ this.onicecandidate?.(event);
340
+ this.emit("icecandidate", event);
273
341
  });
274
342
  }
275
343
  get connectionState() {
@@ -290,6 +358,9 @@ class RTCPeerConnection extends helper_1.EventTarget {
290
358
  get sctpTransport() {
291
359
  return this.sctpManager.sctpTransport;
292
360
  }
361
+ get sctp() {
362
+ return this.sctpTransport ?? null;
363
+ }
293
364
  get sctpRemotePort() {
294
365
  return this.sctpManager.sctpRemotePort;
295
366
  }
@@ -303,10 +374,35 @@ class RTCPeerConnection extends helper_1.EventTarget {
303
374
  return this.iceTransports[0].connection.generation;
304
375
  }
305
376
  get localDescription() {
306
- return this.sdpManager.localDescription;
377
+ return this.sdpManager.localDescription ?? null;
378
+ }
379
+ get currentLocalDescription() {
380
+ return this.sdpManager.currentLocalDescription?.toJSON() ?? null;
381
+ }
382
+ get pendingLocalDescription() {
383
+ return this.sdpManager.pendingLocalDescription?.toJSON() ?? null;
307
384
  }
308
385
  get remoteDescription() {
309
- return this.sdpManager.remoteDescription;
386
+ return this.sdpManager.remoteDescription ?? null;
387
+ }
388
+ get currentRemoteDescription() {
389
+ return this.sdpManager.currentRemoteDescription?.toJSON() ?? null;
390
+ }
391
+ get pendingRemoteDescription() {
392
+ return this.sdpManager.pendingRemoteDescription?.toJSON() ?? null;
393
+ }
394
+ get canTrickleIceCandidates() {
395
+ const remoteDescription = this.sdpManager._remoteDescription;
396
+ if (!remoteDescription) {
397
+ return null;
398
+ }
399
+ const iceOptions = [
400
+ remoteDescription.iceOptions,
401
+ ...remoteDescription.media.map((media) => media.iceOptions),
402
+ ]
403
+ .filter((value) => !!value)
404
+ .join(" ");
405
+ return iceOptions.split(/\s+/).includes("trickle");
310
406
  }
311
407
  get remoteIsBundled() {
312
408
  return this.sdpManager.remoteIsBundled;
@@ -329,7 +425,42 @@ class RTCPeerConnection extends helper_1.EventTarget {
329
425
  return this.transceiverManager.getReceivers();
330
426
  }
331
427
  setConfiguration(config) {
332
- (0, utils_1.deepMerge)(this.config, config);
428
+ const normalizedConfig = normalizePeerConfiguration(config);
429
+ const isReconfiguration = !!this.sdpManager;
430
+ if (normalizedConfig.rtcpMuxPolicy &&
431
+ normalizedConfig.rtcpMuxPolicy !== "require") {
432
+ throw new Error("rtcpMuxPolicy must be require");
433
+ }
434
+ if (normalizedConfig.iceCandidatePoolSize !== undefined &&
435
+ (!Number.isInteger(normalizedConfig.iceCandidatePoolSize) ||
436
+ normalizedConfig.iceCandidatePoolSize < 0)) {
437
+ throw new Error("iceCandidatePoolSize must be a non-negative integer");
438
+ }
439
+ if (isReconfiguration &&
440
+ normalizedConfig.bundlePolicy !== undefined &&
441
+ normalizedConfig.bundlePolicy !== this.config.bundlePolicy) {
442
+ throw new Error("bundlePolicy cannot be changed");
443
+ }
444
+ if (isReconfiguration &&
445
+ normalizedConfig.rtcpMuxPolicy !== undefined &&
446
+ normalizedConfig.rtcpMuxPolicy !== this.config.rtcpMuxPolicy) {
447
+ throw new Error("rtcpMuxPolicy cannot be changed");
448
+ }
449
+ if (isReconfiguration &&
450
+ normalizedConfig.certificates !== undefined &&
451
+ !hasSameCertificates(normalizedConfig.certificates, this.config.certificates)) {
452
+ throw new Error("certificates cannot be changed");
453
+ }
454
+ if (isReconfiguration &&
455
+ normalizedConfig.iceCandidatePoolSize !== undefined &&
456
+ this.localDescription &&
457
+ normalizedConfig.iceCandidatePoolSize !== this.config.iceCandidatePoolSize) {
458
+ throw new Error("iceCandidatePoolSize cannot be changed after setLocalDescription");
459
+ }
460
+ if ((normalizedConfig.iceCandidatePoolSize ?? 0) > 0) {
461
+ throw new Error("iceCandidatePoolSize > 0 is not supported");
462
+ }
463
+ (0, utils_1.deepMerge)(this.config, normalizedConfig);
333
464
  if (this.config.icePortRange) {
334
465
  const [min, max] = this.config.icePortRange;
335
466
  if (min === max)
@@ -337,6 +468,14 @@ class RTCPeerConnection extends helper_1.EventTarget {
337
468
  if (min >= max)
338
469
  throw new Error("The min must be less than max");
339
470
  }
471
+ if (!Number.isInteger(this.config.maxMessageSize) ||
472
+ this.config.maxMessageSize < 0) {
473
+ throw new Error("maxMessageSize must be a non-negative integer");
474
+ }
475
+ if (this.sctpManager?.sctpTransport) {
476
+ this.sctpManager.sctpTransport.maxMessageSize =
477
+ this.config.maxMessageSize;
478
+ }
340
479
  for (const [i, codecParams] of (0, helper_1.enumerate)([
341
480
  ...(this.config.codecs.audio || []),
342
481
  ...(this.config.codecs.video || []),
@@ -370,7 +509,7 @@ class RTCPeerConnection extends helper_1.EventTarget {
370
509
  });
371
510
  }
372
511
  getConfiguration() {
373
- return this.config;
512
+ return clonePeerConfiguration(this.config);
374
513
  }
375
514
  async createOffer({ iceRestart } = {}) {
376
515
  if (iceRestart || this.needRestart) {
@@ -388,10 +527,12 @@ class RTCPeerConnection extends helper_1.EventTarget {
388
527
  }
389
528
  }
390
529
  const description = this.sdpManager.buildOfferSdp(this.transceiverManager.getTransceivers(), this.sctpTransport);
391
- return description.toJSON();
530
+ const createdOffer = description.toJSON();
531
+ this.lastCreatedOffer = createdOffer;
532
+ return createdOffer;
392
533
  }
393
534
  createSctpTransport() {
394
- const sctp = this.sctpManager.createSctpTransport();
535
+ const sctp = this.sctpManager.createSctpTransport(this.config.maxMessageSize);
395
536
  const dtlsTransport = this.findOrCreateTransport();
396
537
  sctp.setDtlsTransport(dtlsTransport);
397
538
  return sctp;
@@ -410,19 +551,31 @@ class RTCPeerConnection extends helper_1.EventTarget {
410
551
  }
411
552
  removeTrack(sender) {
412
553
  if (this.isClosed) {
413
- throw new Error("peer closed");
554
+ throw (0, errors_1.createWebRtcDomException)("InvalidStateError", "peer closed");
414
555
  }
415
556
  this.transceiverManager.removeTrack(sender);
416
557
  this.needNegotiation();
417
558
  }
559
+ invalidateLastCreatedDescriptions() {
560
+ this.lastCreatedAnswer = undefined;
561
+ this.lastCreatedOffer = undefined;
562
+ }
563
+ async waitForPendingDescriptionTask() {
564
+ this.assertNotClosed();
565
+ await Promise.resolve();
566
+ if (this.isClosed) {
567
+ await new Promise(() => undefined);
568
+ }
569
+ }
418
570
  findOrCreateTransport() {
419
- const [existing] = this.iceTransports;
571
+ const existingDtlsTransport = this.dtlsTransports.find((transport) => transport.state !== "closed");
572
+ const existing = existingDtlsTransport?.iceTransport;
420
573
  // Gather ICE candidates for only one track. If the remote endpoint is not bundle-aware, negotiate only one media track.
421
574
  // https://w3c.github.io/webrtc-pc/#rtcbundlepolicy-enum
422
575
  if (this.sdpManager.bundlePolicy === "max-bundle" ||
423
576
  (this.sdpManager.bundlePolicy !== "disable" && this.remoteIsBundled)) {
424
- if (existing) {
425
- return this.dtlsTransports[0];
577
+ if (existingDtlsTransport) {
578
+ return existingDtlsTransport;
426
579
  }
427
580
  }
428
581
  const dtlsTransport = this.secureManager.createTransport();
@@ -476,17 +629,48 @@ class RTCPeerConnection extends helper_1.EventTarget {
476
629
  "have-local-offer",
477
630
  "have-remote-pranswer",
478
631
  ];
479
- sessionDescription =
480
- sessionDescription ??
481
- (implicitOfferState.includes(this.signalingState)
482
- ? await this.createOffer()
483
- : await this.createAnswer());
632
+ await this.waitForPendingDescriptionTask();
633
+ if (sessionDescription?.type === "rollback") {
634
+ this.sdpManager.rollbackLocalDescription(this.signalingState);
635
+ this.setSignalingState("stable");
636
+ if (this.shouldNegotiationneeded) {
637
+ this.needNegotiation();
638
+ }
639
+ this.invalidateLastCreatedDescriptions();
640
+ return;
641
+ }
642
+ const needsGeneratedDescription = !sessionDescription?.type ||
643
+ !sessionDescription.sdp ||
644
+ sessionDescription.sdp.length === 0;
645
+ const generatedDescription = needsGeneratedDescription
646
+ ? sessionDescription?.type === "offer"
647
+ ? (this.lastCreatedOffer ?? (await this.createOffer()))
648
+ : sessionDescription?.type === "answer" ||
649
+ sessionDescription?.type === "pranswer"
650
+ ? (this.lastCreatedAnswer ?? (await this.createAnswer()))
651
+ : implicitOfferState.includes(this.signalingState)
652
+ ? (this.lastCreatedOffer ?? (await this.createOffer()))
653
+ : (this.lastCreatedAnswer ?? (await this.createAnswer()))
654
+ : undefined;
655
+ sessionDescription = {
656
+ type: sessionDescription?.type ?? generatedDescription.type,
657
+ sdp: sessionDescription?.sdp && sessionDescription.sdp.length > 0
658
+ ? sessionDescription.sdp
659
+ : generatedDescription.sdp,
660
+ };
661
+ if (sessionDescription.type === "offer" &&
662
+ this.lastCreatedOffer &&
663
+ sessionDescription.sdp !== this.lastCreatedOffer.sdp) {
664
+ throw (0, errors_1.createWebRtcDomException)("InvalidModificationError", "setLocalDescription must use the latest created offer");
665
+ }
484
666
  // # parse and validate description
667
+ const descriptionType = sessionDescription.type;
668
+ const descriptionSdp = sessionDescription.sdp;
485
669
  const description = this.sdpManager.parseSdp({
486
- sdp: sessionDescription.sdp,
670
+ sdp: descriptionSdp,
487
671
  isLocal: true,
488
672
  signalingState: this.signalingState,
489
- type: sessionDescription.type,
673
+ type: descriptionType,
490
674
  });
491
675
  // # update signaling state
492
676
  if (description.type === "offer") {
@@ -495,6 +679,9 @@ class RTCPeerConnection extends helper_1.EventTarget {
495
679
  else if (description.type === "answer") {
496
680
  this.setSignalingState("stable");
497
681
  }
682
+ else if (description.type === "pranswer") {
683
+ this.setSignalingState("have-local-pranswer");
684
+ }
498
685
  // # assign MID
499
686
  for (const [i, media] of (0, helper_1.enumerate)(description.media)) {
500
687
  const mid = media.rtp.muxId;
@@ -513,7 +700,7 @@ class RTCPeerConnection extends helper_1.EventTarget {
513
700
  const role = description.media.find((media) => media.dtlsParams)?.dtlsParams
514
701
  ?.role;
515
702
  this.secureManager.setLocalRole({
516
- type: description.type,
703
+ type: description.type === "offer" ? "offer" : "answer",
517
704
  role,
518
705
  });
519
706
  // # configure direction
@@ -539,14 +726,56 @@ class RTCPeerConnection extends helper_1.EventTarget {
539
726
  if (this.shouldNegotiationneeded) {
540
727
  this.needNegotiation();
541
728
  }
729
+ this.invalidateLastCreatedDescriptions();
542
730
  return description;
543
731
  }
544
732
  async gatherCandidates() {
545
733
  await this.secureManager.gatherCandidates(!!this.sdpManager.remoteIsBundled);
546
734
  }
547
- async addIceCandidate(candidateMessage) {
548
- const sdp = this.sdpManager.buildOfferSdp(this.transceiverManager.getTransceivers(), this.sctpTransport);
549
- await this.secureManager.addIceCandidate(sdp, candidateMessage);
735
+ async addIceCandidate(candidateMessage = {}) {
736
+ if (this.isClosed) {
737
+ throw (0, errors_1.createWebRtcDomException)("InvalidStateError", "is closed");
738
+ }
739
+ if (!this.remoteDescription || !this.sdpManager._remoteDescription) {
740
+ this.pendingRemoteCandidates.push(candidateMessage);
741
+ return;
742
+ }
743
+ await this.applyRemoteIceCandidate(candidateMessage);
744
+ }
745
+ async applyRemoteIceCandidate(candidateMessage) {
746
+ const sdp = this.sdpManager._remoteDescription;
747
+ if (!sdp) {
748
+ return;
749
+ }
750
+ const appliedCandidate = await this.secureManager.addIceCandidate(sdp, candidateMessage);
751
+ const remoteDescription = this.sdpManager._remoteDescription;
752
+ if (!remoteDescription || !appliedCandidate) {
753
+ return;
754
+ }
755
+ if (appliedCandidate.kind === "end-of-candidates") {
756
+ for (const mediaIndex of appliedCandidate.mediaIndices) {
757
+ const media = remoteDescription.media[mediaIndex];
758
+ if (media) {
759
+ media.iceCandidatesComplete = true;
760
+ }
761
+ }
762
+ return;
763
+ }
764
+ for (const mediaIndex of appliedCandidate.mediaIndices) {
765
+ const media = remoteDescription.media[mediaIndex];
766
+ if (!media) {
767
+ continue;
768
+ }
769
+ media.iceCandidates.push(appliedCandidate.candidate);
770
+ }
771
+ }
772
+ async flushPendingRemoteCandidates() {
773
+ while (this.pendingRemoteCandidates.length > 0 &&
774
+ this.remoteDescription &&
775
+ this.sdpManager._remoteDescription) {
776
+ const candidate = this.pendingRemoteCandidates.shift();
777
+ await this.applyRemoteIceCandidate(candidate ?? null);
778
+ }
550
779
  }
551
780
  async connect() {
552
781
  log("start connect");
@@ -591,12 +820,29 @@ class RTCPeerConnection extends helper_1.EventTarget {
591
820
  if (sessionDescription instanceof sdp_1.SessionDescription) {
592
821
  sessionDescription = sessionDescription.toSdp();
593
822
  }
823
+ await this.waitForPendingDescriptionTask();
824
+ const needsImplicitLocalRollback = sessionDescription.type === "offer" &&
825
+ ["have-local-offer", "have-local-pranswer"].includes(this.signalingState);
826
+ if (needsImplicitLocalRollback) {
827
+ this.sdpManager.rollbackLocalDescription(this.signalingState);
828
+ this.shouldNegotiationneeded = true;
829
+ this.setSignalingState("stable");
830
+ await Promise.resolve();
831
+ }
594
832
  // # parse and validate description
595
833
  const remoteSdp = this.sdpManager.setRemoteDescription(sessionDescription, this.signalingState);
834
+ if (!remoteSdp) {
835
+ this.setSignalingState("stable");
836
+ if (this.shouldNegotiationneeded) {
837
+ this.needNegotiation();
838
+ }
839
+ this.invalidateLastCreatedDescriptions();
840
+ return;
841
+ }
596
842
  let bundleTransport;
597
843
  // # apply description
598
844
  const matchTransceiverWithMedia = (transceiver, media) => transceiver.kind === media.kind &&
599
- [undefined, media.rtp.muxId].includes(transceiver.mid);
845
+ [null, media.rtp.muxId].includes(transceiver.mid);
600
846
  let transports = remoteSdp.media.map((remoteMedia, i) => {
601
847
  let dtlsTransport;
602
848
  if (["audio", "video"].includes(remoteMedia.kind)) {
@@ -608,7 +854,7 @@ class RTCPeerConnection extends helper_1.EventTarget {
608
854
  transceiver = this.addTransceiver(remoteMedia.kind, {
609
855
  direction: "recvonly",
610
856
  });
611
- transceiver.mid = remoteMedia.rtp.muxId;
857
+ transceiver.mid = remoteMedia.rtp.muxId ?? null;
612
858
  this.onRemoteTransceiverAdded.execute(transceiver);
613
859
  }
614
860
  else {
@@ -657,7 +903,7 @@ class RTCPeerConnection extends helper_1.EventTarget {
657
903
  iceTransport.setRemoteParams(remoteMedia.iceParams, renomination);
658
904
  // One agent full, one lite: The full agent MUST take the controlling role, and the lite agent MUST take the controlled role
659
905
  // RFC 8445 S6.1.1
660
- if (remoteMedia.iceParams?.iceLite) {
906
+ if (remoteMedia.iceParams.iceLite && !iceTransport.connection.iceLite) {
661
907
  iceTransport.connection.iceControlling = true;
662
908
  }
663
909
  }
@@ -696,6 +942,10 @@ class RTCPeerConnection extends helper_1.EventTarget {
696
942
  else if (remoteSdp.type === "answer") {
697
943
  this.setSignalingState("stable");
698
944
  }
945
+ else if (remoteSdp.type === "pranswer") {
946
+ this.setSignalingState("have-remote-pranswer");
947
+ }
948
+ await this.flushPendingRemoteCandidates();
699
949
  // connect transports
700
950
  if (remoteSdp.type === "answer") {
701
951
  log("caller start connect");
@@ -708,6 +958,7 @@ class RTCPeerConnection extends helper_1.EventTarget {
708
958
  if (this.shouldNegotiationneeded) {
709
959
  this.needNegotiation();
710
960
  }
961
+ this.invalidateLastCreatedDescriptions();
711
962
  }
712
963
  addTransceiver(trackOrKind, options = {}) {
713
964
  const dtlsTransport = this.findOrCreateTransport();
@@ -717,13 +968,11 @@ class RTCPeerConnection extends helper_1.EventTarget {
717
968
  return transceiver;
718
969
  }
719
970
  // todo fix
720
- addTrack(track,
721
- /**todo impl */
722
- ms) {
971
+ addTrack(track, ...streams) {
723
972
  if (this.isClosed) {
724
- throw new Error("is closed");
973
+ throw (0, errors_1.createWebRtcDomException)("InvalidStateError", "is closed");
725
974
  }
726
- const transceiver = this.transceiverManager.addTrack(track, ms);
975
+ const transceiver = this.transceiverManager.addTrack(track, streams);
727
976
  if (!transceiver.dtlsTransport) {
728
977
  const dtlsTransport = this.findOrCreateTransport();
729
978
  transceiver.setDtlsTransport(dtlsTransport);
@@ -739,54 +988,61 @@ class RTCPeerConnection extends helper_1.EventTarget {
739
988
  sctpTransport: this.sctpTransport,
740
989
  signalingState: this.signalingState,
741
990
  });
742
- return description.toJSON();
991
+ const createdAnswer = description.toJSON();
992
+ this.lastCreatedAnswer = createdAnswer;
993
+ return createdAnswer;
743
994
  }
744
995
  assertNotClosed() {
745
996
  if (this.isClosed) {
746
- throw new Error("RTCPeerConnection is closed");
997
+ throw (0, errors_1.createWebRtcDomException)("InvalidStateError", "RTCPeerConnection is closed");
747
998
  }
748
999
  }
749
1000
  setSignalingState(state) {
1001
+ if (this.signalingState === state) {
1002
+ return;
1003
+ }
750
1004
  log("signalingStateChange", state);
751
1005
  this.signalingState = state;
752
1006
  this.signalingStateChange.execute(state);
753
1007
  if (this.onsignalingstatechange) {
754
- this.onsignalingstatechange({});
1008
+ this.onsignalingstatechange(new globalThis.Event("signalingstatechange"));
755
1009
  }
1010
+ this.emit("signalingstatechange");
756
1011
  }
757
- createPeerConnectionStats() {
758
- const timestamp = (0, stats_1.getStatsTimestamp)();
1012
+ createPeerConnectionStats(timestamp) {
759
1013
  return {
760
1014
  type: "peer-connection",
761
- id: (0, stats_1.generateStatsId)("peer-connection"),
1015
+ id: (0, stats_1.generateStatsId)("peer-connection", this.id),
762
1016
  timestamp,
763
1017
  dataChannelsOpened: this.sctpManager.dataChannelsOpened,
764
1018
  dataChannelsClosed: this.sctpManager.dataChannelsClosed,
765
1019
  };
766
1020
  }
767
1021
  async getStats(selector) {
1022
+ const timestamp = (0, stats_1.getStatsTimestamp)();
768
1023
  const stats = [];
769
- // Peer connection stats - always included regardless of selector
770
- stats.push(this.createPeerConnectionStats());
771
- // Get stats from transceivers
772
- const transceiverStats = await this.transceiverManager.getStats(selector);
773
- stats.push(...transceiverStats);
774
- // Get transport stats - always included regardless of selector
775
- const transportStats = await this.secureManager.getStats();
1024
+ if (!selector) {
1025
+ stats.push(this.createPeerConnectionStats(timestamp));
1026
+ }
1027
+ stats.push(...this.transceiverManager.collectStats(timestamp));
1028
+ const transportStats = await this.secureManager.getStats(timestamp);
776
1029
  stats.push(...transportStats);
777
- // Get data channel stats - always included regardless of selector
778
- if (this.sctpTransport) {
779
- const dataChannelStats = await this.sctpManager.getStats();
1030
+ if (!selector && this.sctpTransport) {
1031
+ const dataChannelStats = await this.sctpManager.getStats(timestamp);
780
1032
  if (dataChannelStats) {
781
1033
  stats.push(...dataChannelStats);
782
1034
  }
783
1035
  }
784
- return new stats_1.RTCStatsReport(stats);
1036
+ if (!selector) {
1037
+ return (0, stats_1.buildStatsReport)(stats);
1038
+ }
1039
+ return (0, stats_1.buildStatsReport)(stats, this.transceiverManager.getStatsRootIds(selector));
785
1040
  }
786
1041
  async close() {
787
1042
  if (this.isClosed)
788
1043
  return;
789
1044
  this.isClosed = true;
1045
+ this.pendingRemoteCandidates.length = 0;
790
1046
  this.setSignalingState("closed");
791
1047
  this.transceiverManager.close();
792
1048
  await this.secureManager.close();
@@ -817,22 +1073,136 @@ function generateDefaultPeerConfig() {
817
1073
  video: [],
818
1074
  },
819
1075
  iceTransportPolicy: "all",
1076
+ iceLite: false,
820
1077
  iceServers: [{ urls: "stun:stun.l.google.com:19302" }],
821
1078
  icePortRange: undefined,
822
1079
  iceInterfaceAddresses: undefined,
823
1080
  iceAdditionalHostAddresses: undefined,
824
1081
  iceUseIpv4: true,
825
1082
  iceUseIpv6: true,
1083
+ iceUseTcp: false,
1084
+ turnTransport: undefined,
1085
+ turnTlsOptions: undefined,
826
1086
  iceFilterStunResponse: undefined,
827
1087
  iceFilterCandidatePair: undefined,
828
1088
  icePasswordPrefix: undefined,
829
1089
  iceUseLinkLocalAddress: undefined,
830
1090
  dtls: {},
831
1091
  bundlePolicy: "max-compat",
1092
+ rtcpMuxPolicy: "require",
1093
+ iceCandidatePoolSize: 0,
1094
+ certificates: [],
832
1095
  debug: {},
833
1096
  midSuffix: false,
834
1097
  forceTurnTCP: false,
1098
+ maxMessageSize: sctp_1.DEFAULT_MAX_MESSAGE_SIZE,
835
1099
  };
836
1100
  }
837
1101
  exports.defaultPeerConfig = generateDefaultPeerConfig();
1102
+ function normalizePeerConfiguration(config) {
1103
+ const input = Object(config ?? {});
1104
+ const normalizedConfig = { ...input };
1105
+ if (input.bundlePolicy === "balanced") {
1106
+ normalizedConfig.bundlePolicy = "max-compat";
1107
+ }
1108
+ if ("certificates" in input) {
1109
+ if (input.certificates === undefined) {
1110
+ normalizedConfig.certificates = undefined;
1111
+ }
1112
+ else if (!Array.isArray(input.certificates) ||
1113
+ input.certificates.some((certificate) => certificate == null)) {
1114
+ throw (0, errors_1.createWebRtcTypeError)("certificates must be an array of RTCCertificate");
1115
+ }
1116
+ else {
1117
+ normalizedConfig.certificates = [...input.certificates];
1118
+ }
1119
+ }
1120
+ if ("iceCandidatePoolSize" in input) {
1121
+ normalizedConfig.iceCandidatePoolSize = coerceUnsignedShort(input.iceCandidatePoolSize, "iceCandidatePoolSize");
1122
+ }
1123
+ return normalizedConfig;
1124
+ }
1125
+ function coerceUnsignedShort(value, name) {
1126
+ const coerced = Number(value);
1127
+ if (!Number.isFinite(coerced) ||
1128
+ !Number.isInteger(coerced) ||
1129
+ coerced < 0 ||
1130
+ coerced > 65535) {
1131
+ throw (0, errors_1.createWebRtcTypeError)(`${name} must be an unsigned short`);
1132
+ }
1133
+ return coerced;
1134
+ }
1135
+ function hasSameCertificates(left, right) {
1136
+ return (left.length === right.length &&
1137
+ left.every((certificate, index) => certificate === right[index]));
1138
+ }
1139
+ function clonePeerConfiguration(config) {
1140
+ return {
1141
+ ...config,
1142
+ codecs: {
1143
+ audio: config.codecs.audio ? [...config.codecs.audio] : undefined,
1144
+ video: config.codecs.video ? [...config.codecs.video] : undefined,
1145
+ },
1146
+ headerExtensions: {
1147
+ audio: config.headerExtensions.audio
1148
+ ? [...config.headerExtensions.audio]
1149
+ : undefined,
1150
+ video: config.headerExtensions.video
1151
+ ? [...config.headerExtensions.video]
1152
+ : undefined,
1153
+ },
1154
+ iceServers: config.iceServers.map((server) => ({
1155
+ ...server,
1156
+ urls: Array.isArray(server.urls) ? [...server.urls] : server.urls,
1157
+ })),
1158
+ icePortRange: config.icePortRange
1159
+ ? [...config.icePortRange]
1160
+ : undefined,
1161
+ iceAdditionalHostAddresses: config.iceAdditionalHostAddresses
1162
+ ? [...config.iceAdditionalHostAddresses]
1163
+ : undefined,
1164
+ dtls: { ...config.dtls },
1165
+ certificates: [...config.certificates],
1166
+ debug: { ...config.debug },
1167
+ };
1168
+ }
1169
+ class RTCTrackEvent {
1170
+ constructor(init) {
1171
+ Object.defineProperty(this, "type", {
1172
+ enumerable: true,
1173
+ configurable: true,
1174
+ writable: true,
1175
+ value: "track"
1176
+ });
1177
+ Object.defineProperty(this, "track", {
1178
+ enumerable: true,
1179
+ configurable: true,
1180
+ writable: true,
1181
+ value: void 0
1182
+ });
1183
+ Object.defineProperty(this, "streams", {
1184
+ enumerable: true,
1185
+ configurable: true,
1186
+ writable: true,
1187
+ value: void 0
1188
+ });
1189
+ Object.defineProperty(this, "transceiver", {
1190
+ enumerable: true,
1191
+ configurable: true,
1192
+ writable: true,
1193
+ value: void 0
1194
+ });
1195
+ Object.defineProperty(this, "receiver", {
1196
+ enumerable: true,
1197
+ configurable: true,
1198
+ writable: true,
1199
+ value: void 0
1200
+ });
1201
+ this.track = init.track;
1202
+ this.streams = [...init.streams];
1203
+ this.transceiver = init.transceiver;
1204
+ this.receiver = init.receiver;
1205
+ }
1206
+ }
1207
+ exports.RTCTrackEvent = RTCTrackEvent;
838
1208
  //# sourceMappingURL=peerConnection.js.map