werift 0.22.1 → 0.22.2

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 (176) hide show
  1. package/lib/common/src/binary.d.ts +6 -6
  2. package/lib/common/src/event.d.ts +1 -0
  3. package/lib/common/src/event.js +5 -0
  4. package/lib/common/src/event.js.map +1 -1
  5. package/lib/common/src/log.d.ts +1 -2
  6. package/lib/common/src/transport.d.ts +2 -1
  7. package/lib/common/src/transport.js +28 -14
  8. package/lib/common/src/transport.js.map +1 -1
  9. package/lib/dtls/src/cipher/prf.d.ts +12 -12
  10. package/lib/dtls/src/cipher/suites/aead.d.ts +3 -2
  11. package/lib/dtls/src/cipher/suites/aead.js +31 -38
  12. package/lib/dtls/src/cipher/suites/aead.js.map +1 -1
  13. package/lib/dtls/src/context/cipher.d.ts +4 -4
  14. package/lib/dtls/src/context/cipher.js +21 -10
  15. package/lib/dtls/src/context/cipher.js.map +1 -1
  16. package/lib/dtls/src/context/srtp.d.ts +3 -3
  17. package/lib/dtls/src/context/srtp.js.map +1 -1
  18. package/lib/dtls/src/flight/client/flight5.js.map +1 -1
  19. package/lib/dtls/src/flight/server/flight2.js.map +1 -1
  20. package/lib/dtls/src/handshake/extensions/ellipticCurves.d.ts +1 -1
  21. package/lib/dtls/src/handshake/extensions/renegotiationIndication.d.ts +2 -2
  22. package/lib/dtls/src/handshake/extensions/signature.d.ts +2 -2
  23. package/lib/dtls/src/handshake/extensions/useSrtp.d.ts +1 -1
  24. package/lib/dtls/src/handshake/message/alert.d.ts +1 -1
  25. package/lib/dtls/src/handshake/message/certificate.d.ts +1 -1
  26. package/lib/dtls/src/handshake/message/changeCipherSpec.d.ts +1 -1
  27. package/lib/dtls/src/handshake/message/client/certificateVerify.d.ts +1 -1
  28. package/lib/dtls/src/handshake/message/client/hello.d.ts +1 -1
  29. package/lib/dtls/src/handshake/message/client/keyExchange.d.ts +1 -1
  30. package/lib/dtls/src/handshake/message/finished.d.ts +1 -1
  31. package/lib/dtls/src/handshake/message/server/certificateRequest.d.ts +1 -1
  32. package/lib/dtls/src/handshake/message/server/hello.d.ts +1 -1
  33. package/lib/dtls/src/handshake/message/server/helloDone.d.ts +1 -1
  34. package/lib/dtls/src/handshake/message/server/helloVerifyRequest.d.ts +1 -1
  35. package/lib/dtls/src/handshake/message/server/keyExchange.d.ts +1 -1
  36. package/lib/dtls/src/handshake/random.d.ts +3 -3
  37. package/lib/dtls/src/record/message/fragment.d.ts +1 -1
  38. package/lib/dtls/src/record/message/header.d.ts +2 -19
  39. package/lib/dtls/src/record/message/header.js +1 -60
  40. package/lib/dtls/src/record/message/header.js.map +1 -1
  41. package/lib/dtls/src/record/message/plaintext.d.ts +6 -27
  42. package/lib/dtls/src/record/message/plaintext.js +34 -16
  43. package/lib/dtls/src/record/message/plaintext.js.map +1 -1
  44. package/lib/dtls/src/socket.d.ts +4 -4
  45. package/lib/dtls/src/socket.js.map +1 -1
  46. package/lib/dtls/src/util/binary.d.ts +1 -1
  47. package/lib/ice/src/helper.d.ts +1 -1
  48. package/lib/ice/src/ice.d.ts +4 -3
  49. package/lib/ice/src/ice.js +89 -68
  50. package/lib/ice/src/ice.js.map +1 -1
  51. package/lib/ice/src/iceBase.d.ts +20 -1
  52. package/lib/ice/src/iceBase.js +46 -0
  53. package/lib/ice/src/iceBase.js.map +1 -1
  54. package/lib/ice/src/stun/attributes.d.ts +2 -2
  55. package/lib/ice/src/stun/attributes.js +47 -27
  56. package/lib/ice/src/stun/attributes.js.map +1 -1
  57. package/lib/ice/src/stun/message.d.ts +2 -2
  58. package/lib/ice/src/stun/message.js +21 -23
  59. package/lib/ice/src/stun/message.js.map +1 -1
  60. package/lib/ice/src/stun/protocol.d.ts +2 -2
  61. package/lib/ice/src/turn/protocol.d.ts +2 -2
  62. package/lib/index.mjs +2252 -1474
  63. package/lib/nonstandard/index.mjs +308 -351
  64. package/lib/rtp/src/codec/av1.d.ts +2 -2
  65. package/lib/rtp/src/codec/opus.d.ts +1 -1
  66. package/lib/rtp/src/extra/container/mp4/container.js +18 -8
  67. package/lib/rtp/src/extra/container/mp4/container.js.map +1 -1
  68. package/lib/rtp/src/extra/container/mp4/h264.d.ts +2 -2
  69. package/lib/rtp/src/extra/container/mp4/sps-parser.d.ts +1 -1
  70. package/lib/rtp/src/extra/container/ogg/parser.d.ts +1 -1
  71. package/lib/rtp/src/extra/container/webm/container.d.ts +7 -7
  72. package/lib/rtp/src/extra/container/webm/container.js +17 -7
  73. package/lib/rtp/src/extra/container/webm/container.js.map +1 -1
  74. package/lib/rtp/src/extra/container/webm/ebml/ebml.d.ts +1 -1
  75. package/lib/rtp/src/extra/container/webm/ebml/id.d.ts +222 -222
  76. package/lib/rtp/src/extra/processor/depacketizerCallback.d.ts +1 -1
  77. package/lib/rtp/src/extra/processor/depacketizerTransformer.d.ts +6 -1
  78. package/lib/rtp/src/extra/processor/dtxCallback.d.ts +1 -1
  79. package/lib/rtp/src/extra/processor/interface.d.ts +1 -1
  80. package/lib/rtp/src/extra/processor/jitterBufferCallback.d.ts +1 -1
  81. package/lib/rtp/src/extra/processor/mp4.js +3 -0
  82. package/lib/rtp/src/extra/processor/mp4.js.map +1 -1
  83. package/lib/rtp/src/extra/processor/nackHandlerCallback.d.ts +1 -1
  84. package/lib/rtp/src/extra/processor/ntpTimeCallback.d.ts +1 -1
  85. package/lib/rtp/src/extra/processor/rtpTimeCallback.d.ts +1 -1
  86. package/lib/rtp/src/extra/processor/webm.d.ts +1 -1
  87. package/lib/rtp/src/helper.d.ts +1 -1
  88. package/lib/rtp/src/rtcp/header.d.ts +1 -1
  89. package/lib/rtp/src/rtcp/psfb/fullIntraRequest.d.ts +1 -1
  90. package/lib/rtp/src/rtcp/psfb/index.d.ts +1 -1
  91. package/lib/rtp/src/rtcp/psfb/pictureLossIndication.d.ts +1 -1
  92. package/lib/rtp/src/rtcp/psfb/remb.d.ts +1 -1
  93. package/lib/rtp/src/rtcp/rr.d.ts +2 -2
  94. package/lib/rtp/src/rtcp/rtcp.d.ts +1 -1
  95. package/lib/rtp/src/rtcp/rtpfb/index.d.ts +1 -1
  96. package/lib/rtp/src/rtcp/rtpfb/nack.d.ts +1 -1
  97. package/lib/rtp/src/rtcp/rtpfb/twcc.d.ts +4 -4
  98. package/lib/rtp/src/rtcp/sdes.d.ts +3 -3
  99. package/lib/rtp/src/rtcp/sr.d.ts +2 -2
  100. package/lib/rtp/src/rtp/headerExtension.d.ts +6 -6
  101. package/lib/rtp/src/rtp/red/packet.d.ts +2 -2
  102. package/lib/rtp/src/rtp/rtp.d.ts +2 -2
  103. package/lib/rtp/src/srtp/cipher/ctr.d.ts +4 -4
  104. package/lib/rtp/src/srtp/cipher/gcm.d.ts +4 -4
  105. package/lib/rtp/src/srtp/const.d.ts +3 -3
  106. package/lib/rtp/src/srtp/const.js.map +1 -1
  107. package/lib/rtp/src/srtp/context/context.d.ts +7 -7
  108. package/lib/rtp/src/srtp/context/context.js +10 -4
  109. package/lib/rtp/src/srtp/context/context.js.map +1 -1
  110. package/lib/rtp/src/srtp/context/srtcp.d.ts +3 -3
  111. package/lib/rtp/src/srtp/context/srtcp.js.map +1 -1
  112. package/lib/rtp/src/srtp/context/srtp.d.ts +3 -3
  113. package/lib/rtp/src/srtp/context/srtp.js.map +1 -1
  114. package/lib/rtp/src/srtp/srtcp.d.ts +2 -2
  115. package/lib/rtp/src/srtp/srtp.d.ts +2 -2
  116. package/lib/sctp/src/chunk.d.ts +12 -12
  117. package/lib/sctp/src/chunk.js +87 -66
  118. package/lib/sctp/src/chunk.js.map +1 -1
  119. package/lib/sctp/src/param.d.ts +3 -3
  120. package/lib/sctp/src/sctp.d.ts +3 -1
  121. package/lib/sctp/src/sctp.js +36 -1
  122. package/lib/sctp/src/sctp.js.map +1 -1
  123. package/lib/webrtc/src/dataChannel.d.ts +15 -4
  124. package/lib/webrtc/src/dataChannel.js +42 -7
  125. package/lib/webrtc/src/dataChannel.js.map +1 -1
  126. package/lib/webrtc/src/index.d.ts +1 -0
  127. package/lib/webrtc/src/index.js +1 -0
  128. package/lib/webrtc/src/index.js.map +1 -1
  129. package/lib/webrtc/src/media/index.d.ts +1 -0
  130. package/lib/webrtc/src/media/index.js +1 -0
  131. package/lib/webrtc/src/media/index.js.map +1 -1
  132. package/lib/webrtc/src/media/parameters.d.ts +2 -2
  133. package/lib/webrtc/src/media/parameters.js.map +1 -1
  134. package/lib/webrtc/src/media/router.js +2 -1
  135. package/lib/webrtc/src/media/router.js.map +1 -1
  136. package/lib/webrtc/src/media/rtpReceiver.d.ts +3 -3
  137. package/lib/webrtc/src/media/rtpReceiver.js +51 -2
  138. package/lib/webrtc/src/media/rtpReceiver.js.map +1 -1
  139. package/lib/webrtc/src/media/rtpSender.d.ts +6 -0
  140. package/lib/webrtc/src/media/rtpSender.js +78 -7
  141. package/lib/webrtc/src/media/rtpSender.js.map +1 -1
  142. package/lib/webrtc/src/media/rtpTransceiver.d.ts +12 -9
  143. package/lib/webrtc/src/media/rtpTransceiver.js +45 -8
  144. package/lib/webrtc/src/media/rtpTransceiver.js.map +1 -1
  145. package/lib/webrtc/src/media/stats.d.ts +279 -0
  146. package/lib/webrtc/src/media/stats.js +35 -1
  147. package/lib/webrtc/src/media/stats.js.map +1 -1
  148. package/lib/webrtc/src/peerConnection.d.ts +34 -64
  149. package/lib/webrtc/src/peerConnection.js +319 -986
  150. package/lib/webrtc/src/peerConnection.js.map +1 -1
  151. package/lib/webrtc/src/sctpManager.d.ts +27 -0
  152. package/lib/webrtc/src/sctpManager.js +147 -0
  153. package/lib/webrtc/src/sctpManager.js.map +1 -0
  154. package/lib/webrtc/src/sdp.d.ts +3 -2
  155. package/lib/webrtc/src/sdp.js +17 -7
  156. package/lib/webrtc/src/sdp.js.map +1 -1
  157. package/lib/webrtc/src/sdpManager.d.ts +78 -0
  158. package/lib/webrtc/src/sdpManager.js +391 -0
  159. package/lib/webrtc/src/sdpManager.js.map +1 -0
  160. package/lib/webrtc/src/secureTransportManager.d.ts +56 -0
  161. package/lib/webrtc/src/secureTransportManager.js +345 -0
  162. package/lib/webrtc/src/secureTransportManager.js.map +1 -0
  163. package/lib/webrtc/src/transceiverManager.d.ts +40 -0
  164. package/lib/webrtc/src/transceiverManager.js +355 -0
  165. package/lib/webrtc/src/transceiverManager.js.map +1 -0
  166. package/lib/webrtc/src/transport/dtls.d.ts +18 -6
  167. package/lib/webrtc/src/transport/dtls.js +119 -11
  168. package/lib/webrtc/src/transport/dtls.js.map +1 -1
  169. package/lib/webrtc/src/transport/ice.d.ts +24 -0
  170. package/lib/webrtc/src/transport/ice.js +86 -0
  171. package/lib/webrtc/src/transport/ice.js.map +1 -1
  172. package/lib/webrtc/src/transport/sctp.js +22 -7
  173. package/lib/webrtc/src/transport/sctp.js.map +1 -1
  174. package/lib/webrtc/src/utils.d.ts +3 -3
  175. package/lib/webrtc/src/utils.js.map +1 -1
  176. package/package.json +15 -21
@@ -15,64 +15,41 @@ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (
15
15
  }) : function(o, v) {
16
16
  o["default"] = v;
17
17
  });
18
- var __importStar = (this && this.__importStar) || function (mod) {
19
- if (mod && mod.__esModule) return mod;
20
- var result = {};
21
- if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
22
- __setModuleDefault(result, mod);
23
- return result;
24
- };
18
+ var __importStar = (this && this.__importStar) || (function () {
19
+ var ownKeys = function(o) {
20
+ ownKeys = Object.getOwnPropertyNames || function (o) {
21
+ var ar = [];
22
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
23
+ return ar;
24
+ };
25
+ return ownKeys(o);
26
+ };
27
+ return function (mod) {
28
+ if (mod && mod.__esModule) return mod;
29
+ var result = {};
30
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
31
+ __setModuleDefault(result, mod);
32
+ return result;
33
+ };
34
+ })();
25
35
  var __importDefault = (this && this.__importDefault) || function (mod) {
26
36
  return (mod && mod.__esModule) ? mod : { "default": mod };
27
37
  };
28
38
  Object.defineProperty(exports, "__esModule", { value: true });
29
39
  exports.defaultPeerConfig = exports.findCodecByMimeType = exports.RTCPeerConnection = void 0;
30
- exports.createMediaDescriptionForTransceiver = createMediaDescriptionForTransceiver;
31
- exports.createMediaDescriptionForSctp = createMediaDescriptionForSctp;
32
- exports.addTransportDescription = addTransportDescription;
33
- exports.allocateMid = allocateMid;
34
40
  const cloneDeep_js_1 = __importDefault(require("lodash/cloneDeep.js"));
35
- const isEqual_js_1 = __importDefault(require("lodash/isEqual.js"));
36
41
  const uuid = __importStar(require("uuid"));
37
- const const_1 = require("./const");
38
- const dataChannel_1 = require("./dataChannel");
39
42
  const helper_1 = require("./helper");
40
43
  const common_1 = require("./imports/common");
41
44
  const media_1 = require("./media");
45
+ const stats_1 = require("./media/stats");
46
+ const sctpManager_1 = require("./sctpManager");
42
47
  const sdp_1 = require("./sdp");
43
- const dtls_1 = require("./transport/dtls");
44
- const ice_1 = require("./transport/ice");
45
- const sctp_1 = require("./transport/sctp");
48
+ const sdpManager_1 = require("./sdpManager");
49
+ const secureTransportManager_1 = require("./secureTransportManager");
46
50
  const utils_1 = require("./utils");
47
51
  const log = (0, common_1.debug)("werift:packages/webrtc/src/peerConnection.ts");
48
52
  class RTCPeerConnection extends helper_1.EventTarget {
49
- pushTransceiver(t) {
50
- this.transceivers.push(t);
51
- }
52
- replaceTransceiver(t, index) {
53
- this.transceivers[index] = t;
54
- }
55
- get dtlsTransports() {
56
- const transports = this.transceivers.map((t) => t.dtlsTransport);
57
- if (this.sctpTransport) {
58
- transports.push(this.sctpTransport.dtlsTransport);
59
- }
60
- return transports.reduce((acc, cur) => {
61
- if (!acc.map((d) => d.id).includes(cur.id)) {
62
- acc.push(cur);
63
- }
64
- return acc;
65
- }, []);
66
- }
67
- get iceTransports() {
68
- return this.dtlsTransports.map((d) => d.iceTransport);
69
- }
70
- get extIdUriMap() {
71
- return this.router.extIdUriMap;
72
- }
73
- get iceGeneration() {
74
- return this.iceTransports[0].connection.generation;
75
- }
76
53
  constructor(config = {}) {
77
54
  super();
78
55
  Object.defineProperty(this, "cname", {
@@ -81,55 +58,67 @@ class RTCPeerConnection extends helper_1.EventTarget {
81
58
  writable: true,
82
59
  value: uuid.v4()
83
60
  });
84
- Object.defineProperty(this, "sctpTransport", {
61
+ Object.defineProperty(this, "config", {
85
62
  enumerable: true,
86
63
  configurable: true,
87
64
  writable: true,
88
- value: void 0
65
+ value: (0, cloneDeep_js_1.default)(exports.defaultPeerConfig)
89
66
  });
90
- Object.defineProperty(this, "config", {
67
+ Object.defineProperty(this, "signalingState", {
91
68
  enumerable: true,
92
69
  configurable: true,
93
70
  writable: true,
94
- value: (0, cloneDeep_js_1.default)(exports.defaultPeerConfig)
71
+ value: "stable"
95
72
  });
96
- Object.defineProperty(this, "connectionState", {
73
+ Object.defineProperty(this, "negotiationneeded", {
97
74
  enumerable: true,
98
75
  configurable: true,
99
76
  writable: true,
100
- value: "new"
77
+ value: false
101
78
  });
102
- Object.defineProperty(this, "iceConnectionState", {
79
+ Object.defineProperty(this, "needRestart", {
103
80
  enumerable: true,
104
81
  configurable: true,
105
82
  writable: true,
106
- value: "new"
83
+ value: false
107
84
  });
108
- Object.defineProperty(this, "iceGatheringState", {
85
+ Object.defineProperty(this, "router", {
109
86
  enumerable: true,
110
87
  configurable: true,
111
88
  writable: true,
112
- value: "new"
89
+ value: new media_1.RtpRouter()
113
90
  });
114
- Object.defineProperty(this, "signalingState", {
91
+ Object.defineProperty(this, "sdpManager", {
115
92
  enumerable: true,
116
93
  configurable: true,
117
94
  writable: true,
118
- value: "stable"
95
+ value: void 0
119
96
  });
120
- Object.defineProperty(this, "negotiationneeded", {
97
+ Object.defineProperty(this, "transceiverManager", {
121
98
  enumerable: true,
122
99
  configurable: true,
123
100
  writable: true,
124
- value: false
101
+ value: void 0
125
102
  });
126
- Object.defineProperty(this, "transceivers", {
103
+ Object.defineProperty(this, "sctpManager", {
127
104
  enumerable: true,
128
105
  configurable: true,
129
106
  writable: true,
130
- value: []
107
+ value: void 0
131
108
  });
132
- Object.defineProperty(this, "needRestart", {
109
+ Object.defineProperty(this, "secureManager", {
110
+ enumerable: true,
111
+ configurable: true,
112
+ writable: true,
113
+ value: void 0
114
+ });
115
+ Object.defineProperty(this, "isClosed", {
116
+ enumerable: true,
117
+ configurable: true,
118
+ writable: true,
119
+ value: false
120
+ });
121
+ Object.defineProperty(this, "shouldNegotiationneeded", {
133
122
  enumerable: true,
134
123
  configurable: true,
135
124
  writable: true,
@@ -207,96 +196,48 @@ class RTCPeerConnection extends helper_1.EventTarget {
207
196
  writable: true,
208
197
  value: void 0
209
198
  });
210
- Object.defineProperty(this, "onnegotiationneeded", {
211
- enumerable: true,
212
- configurable: true,
213
- writable: true,
214
- value: void 0
215
- });
216
- Object.defineProperty(this, "onsignalingstatechange", {
217
- enumerable: true,
218
- configurable: true,
219
- writable: true,
220
- value: void 0
221
- });
222
- Object.defineProperty(this, "ontrack", {
199
+ Object.defineProperty(this, "onicecandidateerror", {
223
200
  enumerable: true,
224
201
  configurable: true,
225
202
  writable: true,
226
203
  value: void 0
227
204
  });
228
- Object.defineProperty(this, "onconnectionstatechange", {
205
+ Object.defineProperty(this, "onicegatheringstatechange", {
229
206
  enumerable: true,
230
207
  configurable: true,
231
208
  writable: true,
232
209
  value: void 0
233
210
  });
234
- Object.defineProperty(this, "oniceconnectionstatechange", {
235
- enumerable: true,
236
- configurable: true,
237
- writable: true,
238
- value: void 0
239
- });
240
- Object.defineProperty(this, "router", {
241
- enumerable: true,
242
- configurable: true,
243
- writable: true,
244
- value: new media_1.RtpRouter()
245
- });
246
- Object.defineProperty(this, "certificate", {
247
- enumerable: true,
248
- configurable: true,
249
- writable: true,
250
- value: void 0
251
- });
252
- Object.defineProperty(this, "sctpRemotePort", {
211
+ Object.defineProperty(this, "onnegotiationneeded", {
253
212
  enumerable: true,
254
213
  configurable: true,
255
214
  writable: true,
256
215
  value: void 0
257
216
  });
258
- Object.defineProperty(this, "seenMid", {
259
- enumerable: true,
260
- configurable: true,
261
- writable: true,
262
- value: new Set()
263
- });
264
- Object.defineProperty(this, "currentLocalDescription", {
217
+ Object.defineProperty(this, "onsignalingstatechange", {
265
218
  enumerable: true,
266
219
  configurable: true,
267
220
  writable: true,
268
221
  value: void 0
269
222
  });
270
- Object.defineProperty(this, "currentRemoteDescription", {
223
+ Object.defineProperty(this, "ontrack", {
271
224
  enumerable: true,
272
225
  configurable: true,
273
226
  writable: true,
274
227
  value: void 0
275
228
  });
276
- Object.defineProperty(this, "pendingLocalDescription", {
229
+ Object.defineProperty(this, "onconnectionstatechange", {
277
230
  enumerable: true,
278
231
  configurable: true,
279
232
  writable: true,
280
233
  value: void 0
281
234
  });
282
- Object.defineProperty(this, "pendingRemoteDescription", {
235
+ Object.defineProperty(this, "oniceconnectionstatechange", {
283
236
  enumerable: true,
284
237
  configurable: true,
285
238
  writable: true,
286
239
  value: void 0
287
240
  });
288
- Object.defineProperty(this, "isClosed", {
289
- enumerable: true,
290
- configurable: true,
291
- writable: true,
292
- value: false
293
- });
294
- Object.defineProperty(this, "shouldNegotiationneeded", {
295
- enumerable: true,
296
- configurable: true,
297
- writable: true,
298
- value: false
299
- });
300
241
  Object.defineProperty(this, "needNegotiation", {
301
242
  enumerable: true,
302
243
  configurable: true,
@@ -316,17 +257,111 @@ class RTCPeerConnection extends helper_1.EventTarget {
316
257
  }
317
258
  });
318
259
  this.setConfiguration(config);
319
- this.iceConnectionStateChange.subscribe((state) => {
320
- switch (state) {
321
- case "disconnected":
322
- this.setConnectionState("disconnected");
323
- break;
324
- case "closed":
325
- this.close();
326
- break;
260
+ this.sdpManager = new sdpManager_1.SDPManager({
261
+ cname: this.cname,
262
+ bundlePolicy: this.config.bundlePolicy,
263
+ });
264
+ this.transceiverManager = new media_1.TransceiverManager(this.cname, this.config, this.router);
265
+ this.transceiverManager.onTransceiverAdded.pipe(this.onTransceiverAdded);
266
+ this.transceiverManager.onRemoteTransceiverAdded.pipe(this.onRemoteTransceiverAdded);
267
+ this.transceiverManager.onTrack.subscribe(({ track, stream, transceiver }) => {
268
+ const event = {
269
+ track,
270
+ streams: [stream],
271
+ transceiver,
272
+ receiver: transceiver.receiver,
273
+ };
274
+ this.onTrack.execute(track);
275
+ this.emit("track", event);
276
+ if (this.ontrack) {
277
+ this.ontrack(event);
278
+ }
279
+ });
280
+ this.transceiverManager.onNegotiationNeeded.subscribe(() => this.needNegotiation());
281
+ this.sctpManager = new sctpManager_1.SctpTransportManager();
282
+ this.sctpManager.onDataChannel.subscribe((channel) => {
283
+ this.onDataChannel.execute(channel);
284
+ const event = { channel };
285
+ this.ondatachannel?.(event);
286
+ this.emit("datachannel", event);
287
+ });
288
+ this.secureManager = new secureTransportManager_1.SecureTransportManager({
289
+ config: this.config,
290
+ sctpManager: this.sctpManager,
291
+ transceiverManager: this.transceiverManager,
292
+ });
293
+ this.secureManager.iceGatheringStateChange.pipe(this.iceGatheringStateChange);
294
+ this.secureManager.iceConnectionStateChange.subscribe((state) => {
295
+ if (state === "closed") {
296
+ this.close();
327
297
  }
298
+ this.iceConnectionStateChange.execute(state);
299
+ });
300
+ this.secureManager.connectionStateChange.subscribe((state) => {
301
+ this.connectionStateChange.execute(state);
302
+ this.onconnectionstatechange?.();
303
+ this.emit("connectionstatechange");
304
+ });
305
+ this.secureManager.onIceCandidate.subscribe((candidate) => {
306
+ const iceCandidate = candidate ? candidate.toJSON() : undefined;
307
+ this.onIceCandidate.execute(iceCandidate);
308
+ this.onicecandidate?.({ candidate: iceCandidate });
309
+ this.emit("icecandidate", { candidate: iceCandidate });
328
310
  });
329
311
  }
312
+ get connectionState() {
313
+ return this.secureManager.connectionState;
314
+ }
315
+ get iceConnectionState() {
316
+ return this.secureManager.iceConnectionState;
317
+ }
318
+ get iceGathererState() {
319
+ return this.secureManager.iceGatheringState;
320
+ }
321
+ get iceGatheringState() {
322
+ return this.secureManager.iceGatheringState;
323
+ }
324
+ get dtlsTransports() {
325
+ return this.secureManager.dtlsTransports;
326
+ }
327
+ get sctpTransport() {
328
+ return this.sctpManager.sctpTransport;
329
+ }
330
+ get sctpRemotePort() {
331
+ return this.sctpManager.sctpRemotePort;
332
+ }
333
+ get iceTransports() {
334
+ return this.secureManager.iceTransports;
335
+ }
336
+ get extIdUriMap() {
337
+ return this.router.extIdUriMap;
338
+ }
339
+ get iceGeneration() {
340
+ return this.iceTransports[0].connection.generation;
341
+ }
342
+ get localDescription() {
343
+ return this.sdpManager.localDescription;
344
+ }
345
+ get remoteDescription() {
346
+ return this.sdpManager.remoteDescription;
347
+ }
348
+ /**@private */
349
+ get _localDescription() {
350
+ return this.sdpManager._localDescription;
351
+ }
352
+ /**@private */
353
+ get _remoteDescription() {
354
+ return this.sdpManager._remoteDescription;
355
+ }
356
+ getTransceivers() {
357
+ return this.transceiverManager.getTransceivers();
358
+ }
359
+ getSenders() {
360
+ return this.transceiverManager.getSenders();
361
+ }
362
+ getReceivers() {
363
+ return this.transceiverManager.getReceivers();
364
+ }
330
365
  setConfiguration(config) {
331
366
  (0, utils_1.deepMerge)(this.config, config);
332
367
  if (this.config.icePortRange) {
@@ -367,38 +402,6 @@ class RTCPeerConnection extends helper_1.EventTarget {
367
402
  ].forEach((v, i) => {
368
403
  v.id = 1 + i;
369
404
  });
370
- if (this.config.dtls) {
371
- const { keys } = this.config.dtls;
372
- if (keys) {
373
- this.certificate = new dtls_1.RTCCertificate(keys.keyPem, keys.certPem, keys.signatureHash);
374
- }
375
- }
376
- }
377
- get localDescription() {
378
- if (!this._localDescription) {
379
- return undefined;
380
- }
381
- return this._localDescription.toJSON();
382
- }
383
- get remoteDescription() {
384
- if (!this._remoteDescription) {
385
- return undefined;
386
- }
387
- return this._remoteDescription.toJSON();
388
- }
389
- /**@private */
390
- get _localDescription() {
391
- return this.pendingLocalDescription || this.currentLocalDescription;
392
- }
393
- /**@private */
394
- get _remoteDescription() {
395
- return this.pendingRemoteDescription || this.currentRemoteDescription;
396
- }
397
- getTransceiverByMid(mid) {
398
- return this.transceivers.find((transceiver) => transceiver.mid === mid);
399
- }
400
- getTransceiverByMLineIndex(index) {
401
- return this.transceivers.find((transceiver) => transceiver.mLineIndex === index);
402
405
  }
403
406
  getConfiguration() {
404
407
  return this.config;
@@ -406,207 +409,63 @@ class RTCPeerConnection extends helper_1.EventTarget {
406
409
  async createOffer({ iceRestart } = {}) {
407
410
  if (iceRestart || this.needRestart) {
408
411
  this.needRestart = false;
409
- for (const t of this.iceTransports) {
410
- t.restart();
411
- }
412
+ this.secureManager.restartIce();
412
413
  }
413
- await this.ensureCerts();
414
- const description = this.buildOfferSdp();
415
- return description.toJSON();
416
- }
417
- assignTransceiverCodecs(transceiver) {
418
- const codecs = this.config.codecs[transceiver.kind].filter((codecCandidate) => {
419
- switch (codecCandidate.direction) {
420
- case "recvonly": {
421
- if (const_1.ReceiverDirection.includes(transceiver.direction))
422
- return true;
423
- return false;
424
- }
425
- case "sendonly": {
426
- if (const_1.SenderDirections.includes(transceiver.direction))
427
- return true;
428
- return false;
429
- }
430
- case "sendrecv": {
431
- if ([media_1.Sendrecv, media_1.Recvonly, media_1.Sendonly].includes(transceiver.direction))
432
- return true;
433
- return false;
434
- }
435
- case "all": {
436
- return true;
437
- }
438
- default:
439
- return false;
440
- }
441
- });
442
- transceiver.codecs = codecs;
443
- }
444
- buildOfferSdp() {
445
- this.transceivers.forEach((transceiver) => {
414
+ await this.secureManager.ensureCerts();
415
+ for (const transceiver of this.transceiverManager.getTransceivers()) {
446
416
  if (transceiver.codecs.length === 0) {
447
- this.assignTransceiverCodecs(transceiver);
417
+ this.transceiverManager.assignTransceiverCodecs(transceiver);
448
418
  }
449
419
  if (transceiver.headerExtensions.length === 0) {
450
420
  transceiver.headerExtensions =
451
421
  this.config.headerExtensions[transceiver.kind] ?? [];
452
422
  }
453
- });
454
- const description = new sdp_1.SessionDescription();
455
- (0, sdp_1.addSDPHeader)("offer", description);
456
- // # handle existing transceivers / sctp
457
- const currentMedia = this._localDescription
458
- ? this._localDescription.media
459
- : [];
460
- currentMedia.forEach((m, i) => {
461
- const mid = m.rtp.muxId;
462
- if (!mid) {
463
- log("mid missing", m);
464
- return;
465
- }
466
- if (m.kind === "application") {
467
- if (!this.sctpTransport) {
468
- throw new Error("sctpTransport not found");
469
- }
470
- this.sctpTransport.mLineIndex = i;
471
- description.media.push(createMediaDescriptionForSctp(this.sctpTransport));
472
- }
473
- else {
474
- const transceiver = this.getTransceiverByMid(mid);
475
- if (!transceiver) {
476
- if (m.direction === "inactive") {
477
- description.media.push(m);
478
- return;
479
- }
480
- throw new Error("transceiver not found");
481
- }
482
- transceiver.mLineIndex = i;
483
- description.media.push(createMediaDescriptionForTransceiver(transceiver, this.cname, transceiver.direction));
484
- }
485
- });
486
- // # handle new transceivers / sctp
487
- this.transceivers
488
- .filter((t) => !description.media.find((m) => m.rtp.muxId === t.mid))
489
- .forEach((transceiver) => {
490
- if (transceiver.mid == undefined) {
491
- transceiver.mid = allocateMid(this.seenMid, this.config.midSuffix ? "av" : "");
492
- }
493
- const mediaDescription = createMediaDescriptionForTransceiver(transceiver, this.cname, transceiver.direction);
494
- if (transceiver.mLineIndex === undefined) {
495
- transceiver.mLineIndex = description.media.length;
496
- description.media.push(mediaDescription);
497
- }
498
- else {
499
- description.media[transceiver.mLineIndex] = mediaDescription;
500
- }
501
- });
502
- if (this.sctpTransport &&
503
- !description.media.find((m) => m.kind === "application")) {
504
- this.sctpTransport.mLineIndex = description.media.length;
505
- if (this.sctpTransport.mid == undefined) {
506
- this.sctpTransport.mid = allocateMid(this.seenMid, this.config.midSuffix ? "dc" : "");
507
- }
508
- description.media.push(createMediaDescriptionForSctp(this.sctpTransport));
509
423
  }
510
- if (this.config.bundlePolicy !== "disable") {
511
- const mids = description.media
512
- .map((m) => (m.direction !== "inactive" ? m.rtp.muxId : undefined))
513
- .filter((v) => v);
514
- if (mids.length) {
515
- const bundle = new sdp_1.GroupDescription("BUNDLE", mids);
516
- description.group.push(bundle);
517
- }
518
- }
519
- return description;
424
+ const description = this.sdpManager.buildOfferSdp(this.transceiverManager.getTransceivers(), this.sctpTransport);
425
+ return description.toJSON();
426
+ }
427
+ createSctpTransport() {
428
+ const sctp = this.sctpManager.createSctpTransport();
429
+ const dtlsTransport = this.findOrCreateTransport();
430
+ sctp.setDtlsTransport(dtlsTransport);
431
+ return sctp;
520
432
  }
521
433
  createDataChannel(label, options = {}) {
522
- const base = {
523
- protocol: "",
524
- ordered: true,
525
- negotiated: false,
526
- };
527
- const settings = { ...base, ...options };
528
- if (settings.maxPacketLifeTime && settings.maxRetransmits) {
529
- throw new Error("can not select both");
530
- }
531
434
  if (!this.sctpTransport) {
532
- this.sctpTransport = this.createSctpTransport();
435
+ this.createSctpTransport();
533
436
  this.needNegotiation();
534
437
  }
535
- const parameters = new dataChannel_1.RTCDataChannelParameters({
536
- id: settings.id,
537
- label,
538
- maxPacketLifeTime: settings.maxPacketLifeTime,
539
- maxRetransmits: settings.maxRetransmits,
540
- negotiated: settings.negotiated,
541
- ordered: settings.ordered,
542
- protocol: settings.protocol,
543
- });
544
- const channel = new dataChannel_1.RTCDataChannel(this.sctpTransport, parameters);
438
+ const channel = this.sctpManager.createDataChannel(label, options);
439
+ if (!channel.sctp.dtlsTransport) {
440
+ const dtlsTransport = this.findOrCreateTransport();
441
+ channel.sctp.setDtlsTransport(dtlsTransport);
442
+ }
545
443
  return channel;
546
444
  }
547
445
  removeTrack(sender) {
548
- if (this.isClosed)
446
+ if (this.isClosed) {
549
447
  throw new Error("peer closed");
550
- if (!this.getSenders().find(({ ssrc }) => sender.ssrc === ssrc)) {
551
- throw new Error("unExist");
552
- }
553
- const transceiver = this.transceivers.find(({ sender: { ssrc } }) => sender.ssrc === ssrc);
554
- if (!transceiver)
555
- throw new Error("unExist");
556
- sender.stop();
557
- if (transceiver.currentDirection === "recvonly") {
558
- this.needNegotiation();
559
- return;
560
- }
561
- if (transceiver.stopping || transceiver.stopped) {
562
- transceiver.setDirection("inactive");
563
- }
564
- else {
565
- if (transceiver.direction === "sendrecv") {
566
- transceiver.setDirection("recvonly");
567
- }
568
- else if (transceiver.direction === "sendonly" ||
569
- transceiver.direction === "recvonly") {
570
- transceiver.setDirection("inactive");
571
- }
572
448
  }
449
+ this.transceiverManager.removeTrack(sender);
573
450
  this.needNegotiation();
574
451
  }
575
- createTransport(srtpProfiles = []) {
452
+ findOrCreateTransport() {
576
453
  const [existing] = this.iceTransports;
577
454
  // Gather ICE candidates for only one track. If the remote endpoint is not bundle-aware, negotiate only one media track.
578
455
  // https://w3c.github.io/webrtc-pc/#rtcbundlepolicy-enum
579
- if (this.config.bundlePolicy === "max-bundle") {
456
+ if (this.sdpManager.bundlePolicy === "max-bundle") {
580
457
  if (existing) {
581
458
  return this.dtlsTransports[0];
582
459
  }
583
460
  }
584
- const iceGatherer = new ice_1.RTCIceGatherer({
585
- ...(0, utils_1.parseIceServers)(this.config.iceServers),
586
- forceTurn: this.config.iceTransportPolicy === "relay",
587
- portRange: this.config.icePortRange,
588
- interfaceAddresses: this.config.iceInterfaceAddresses,
589
- additionalHostAddresses: this.config.iceAdditionalHostAddresses,
590
- filterStunResponse: this.config.iceFilterStunResponse,
591
- filterCandidatePair: this.config.iceFilterCandidatePair,
592
- localPasswordPrefix: this.config.icePasswordPrefix,
593
- useIpv4: this.config.iceUseIpv4,
594
- useIpv6: this.config.iceUseIpv6,
595
- turnTransport: this.config.forceTurnTCP === true ? "tcp" : "udp",
596
- useLinkLocalAddress: this.config.iceUseLinkLocalAddress,
461
+ const dtlsTransport = this.secureManager.createTransport();
462
+ dtlsTransport.onRtp.subscribe((rtp) => {
463
+ this.router.routeRtp(rtp);
597
464
  });
598
- if (existing) {
599
- iceGatherer.connection.localUsername = existing.connection.localUsername;
600
- iceGatherer.connection.localPassword = existing.connection.localPassword;
601
- }
602
- iceGatherer.onGatheringStateChange.subscribe(() => {
603
- this.updateIceGatheringState();
604
- });
605
- this.updateIceGatheringState();
606
- const iceTransport = new ice_1.RTCIceTransport(iceGatherer);
607
- iceTransport.onStateChange.subscribe(() => {
608
- this.updateIceConnectionState();
465
+ dtlsTransport.onRtcp.subscribe((rtcp) => {
466
+ this.router.routeRtcp(rtcp);
609
467
  });
468
+ const iceTransport = dtlsTransport.iceTransport;
610
469
  iceTransport.onNegotiationNeeded.subscribe(() => {
611
470
  this.needNegotiation();
612
471
  });
@@ -616,7 +475,7 @@ class RTCPeerConnection extends helper_1.EventTarget {
616
475
  return;
617
476
  }
618
477
  if (!candidate) {
619
- this.setLocal(this._localDescription);
478
+ this.sdpManager.setLocal(this._localDescription, this.transceiverManager.getTransceivers(), this.sctpTransport);
620
479
  this.onIceCandidate.execute(undefined);
621
480
  if (this.onicecandidate) {
622
481
  this.onicecandidate({ candidate: undefined });
@@ -624,58 +483,44 @@ class RTCPeerConnection extends helper_1.EventTarget {
624
483
  this.emit("icecandidate", { candidate: undefined });
625
484
  return;
626
485
  }
627
- if (this.config.bundlePolicy === "max-bundle" || this.remoteIsBundled) {
628
- candidate.sdpMLineIndex = 0;
629
- const media = this._localDescription?.media[0];
630
- if (media) {
631
- candidate.sdpMid = media.rtp.muxId;
632
- }
633
- }
634
- else {
635
- const transceiver = this.transceivers.find((t) => t.dtlsTransport.iceTransport.id === iceTransport.id);
636
- if (transceiver) {
637
- candidate.sdpMLineIndex = transceiver.mLineIndex;
638
- candidate.sdpMid = transceiver.mid;
639
- }
640
- if (this.sctpTransport?.dtlsTransport.iceTransport.id === iceTransport.id) {
641
- candidate.sdpMLineIndex = this.sctpTransport.mLineIndex;
642
- candidate.sdpMid = this.sctpTransport.mid;
643
- }
644
- }
645
- candidate.foundation = "candidate:" + candidate.foundation;
646
- this.onIceCandidate.execute(candidate.toJSON());
647
- if (this.onicecandidate) {
648
- this.onicecandidate({ candidate: candidate.toJSON() });
486
+ if (!this._localDescription) {
487
+ log("localDescription not found when ice candidate was gathered");
488
+ return;
649
489
  }
650
- this.emit("icecandidate", { candidate });
490
+ this.secureManager.handleNewIceCandidate({
491
+ candidate,
492
+ bundlePolicy: this.sdpManager.bundlePolicy,
493
+ remoteIsBundled: !!this.sdpManager.remoteIsBundled,
494
+ media: this._localDescription.media[0],
495
+ transceiver: this.transceiverManager
496
+ .getTransceivers()
497
+ .find((t) => t.dtlsTransport.iceTransport.id === iceTransport.id),
498
+ sctpTransport: this.sctpTransport?.dtlsTransport.iceTransport.id === iceTransport.id
499
+ ? this.sctpTransport
500
+ : undefined,
501
+ });
651
502
  });
652
- const dtlsTransport = new dtls_1.RTCDtlsTransport(this.config, iceTransport, this.router, this.certificate, srtpProfiles);
653
503
  return dtlsTransport;
654
504
  }
655
- createSctpTransport() {
656
- const dtlsTransport = this.createTransport([
657
- const_1.SRTP_PROFILE.SRTP_AEAD_AES_128_GCM, // prefer
658
- const_1.SRTP_PROFILE.SRTP_AES128_CM_HMAC_SHA1_80,
659
- ]);
660
- const sctp = new sctp_1.RTCSctpTransport();
661
- sctp.setDtlsTransport(dtlsTransport);
662
- sctp.mid = undefined;
663
- sctp.onDataChannel.subscribe((channel) => {
664
- this.onDataChannel.execute(channel);
665
- const event = { channel };
666
- if (this.ondatachannel)
667
- this.ondatachannel(event);
668
- this.emit("datachannel", event);
669
- });
670
- this.sctpTransport = sctp;
671
- this.updateIceConnectionState();
672
- return sctp;
673
- }
674
505
  async setLocalDescription(sessionDescription) {
506
+ // https://developer.mozilla.org/en-US/docs/Web/API/RTCPeerConnection/setLocalDescription#type
507
+ const implicitOfferState = [
508
+ "stable",
509
+ "have-local-offer",
510
+ "have-remote-pranswer",
511
+ ];
512
+ sessionDescription =
513
+ sessionDescription ??
514
+ (implicitOfferState.includes(this.signalingState)
515
+ ? await this.createOffer()
516
+ : await this.createAnswer());
675
517
  // # parse and validate description
676
- const description = sdp_1.SessionDescription.parse(sessionDescription.sdp);
677
- description.type = sessionDescription.type;
678
- this.validateDescription(description, true);
518
+ const description = this.sdpManager.parseSdp({
519
+ sdp: sessionDescription.sdp,
520
+ isLocal: true,
521
+ signalingState: this.signalingState,
522
+ type: sessionDescription.type,
523
+ });
679
524
  // # update signaling state
680
525
  if (description.type === "offer") {
681
526
  this.setSignalingState("have-local-offer");
@@ -686,9 +531,9 @@ class RTCPeerConnection extends helper_1.EventTarget {
686
531
  // # assign MID
687
532
  for (const [i, media] of (0, helper_1.enumerate)(description.media)) {
688
533
  const mid = media.rtp.muxId;
689
- this.seenMid.add(mid);
534
+ this.sdpManager.registerMid(mid);
690
535
  if (["audio", "video"].includes(media.kind)) {
691
- const transceiver = this.getTransceiverByMLineIndex(i);
536
+ const transceiver = this.transceiverManager.getTransceiverByMLineIndex(i);
692
537
  if (transceiver) {
693
538
  transceiver.mid = mid;
694
539
  }
@@ -698,38 +543,21 @@ class RTCPeerConnection extends helper_1.EventTarget {
698
543
  }
699
544
  }
700
545
  // setup ice,dtls role
701
- for (const dtlsTransport of this.dtlsTransports) {
702
- const iceTransport = dtlsTransport.iceTransport;
703
- // # set ICE role
704
- if (description.type === "offer") {
705
- iceTransport.connection.iceControlling = true;
706
- }
707
- else {
708
- iceTransport.connection.iceControlling = false;
709
- }
710
- // One agent full, one lite: The full agent MUST take the controlling role, and the lite agent MUST take the controlled role
711
- // RFC 8445 S6.1.1
712
- if (iceTransport.connection.remoteIsLite) {
713
- iceTransport.connection.iceControlling = true;
714
- }
715
- // # set DTLS role for mediasoup
716
- if (description.type === "answer") {
717
- const role = description.media.find((media) => media.dtlsParams)
718
- ?.dtlsParams?.role;
719
- if (role) {
720
- dtlsTransport.role = role;
721
- }
722
- }
723
- }
546
+ const role = description.media.find((media) => media.dtlsParams)?.dtlsParams
547
+ ?.role;
548
+ this.secureManager.setLocalRole({
549
+ type: description.type,
550
+ role,
551
+ });
724
552
  // # configure direction
725
553
  if (["answer", "pranswer"].includes(description.type)) {
726
- for (const t of this.transceivers) {
554
+ for (const t of this.transceiverManager.getTransceivers()) {
727
555
  const direction = (0, utils_1.andDirection)(t.direction, t.offerDirection);
728
556
  t.setCurrentDirection(direction);
729
557
  }
730
558
  }
731
559
  // for trickle ice
732
- this.setLocal(description);
560
+ this.sdpManager.setLocal(description, this.transceiverManager.getTransceivers(), this.sctpTransport);
733
561
  await this.gatherCandidates().catch((e) => {
734
562
  log("gatherCandidates failed", e);
735
563
  });
@@ -737,84 +565,21 @@ class RTCPeerConnection extends helper_1.EventTarget {
737
565
  if (description.type === "answer") {
738
566
  this.connect().catch((err) => {
739
567
  log("connect failed", err);
740
- this.setConnectionState("failed");
568
+ this.secureManager.setConnectionState("failed");
741
569
  });
742
570
  }
743
- this.setLocal(description);
571
+ this.sdpManager.setLocal(description, this.transceiverManager.getTransceivers(), this.sctpTransport);
744
572
  if (this.shouldNegotiationneeded) {
745
573
  this.needNegotiation();
746
574
  }
747
575
  return description;
748
576
  }
749
577
  async gatherCandidates() {
750
- // # gather candidates
751
- const connected = this.iceTransports.find((transport) => transport.state === "connected");
752
- if (this.remoteIsBundled && connected) {
753
- // no need to gather ice candidates on an existing bundled connection
754
- }
755
- else {
756
- await Promise.allSettled(this.iceTransports.map((iceTransport) => iceTransport.gather()));
757
- }
758
- }
759
- setLocal(description) {
760
- description.media
761
- .filter((m) => ["audio", "video"].includes(m.kind))
762
- .forEach((m, i) => {
763
- addTransportDescription(m, this.transceivers[i].dtlsTransport);
764
- });
765
- const sctpMedia = description.media.find((m) => m.kind === "application");
766
- if (this.sctpTransport && sctpMedia) {
767
- addTransportDescription(sctpMedia, this.sctpTransport.dtlsTransport);
768
- }
769
- if (description.type === "answer") {
770
- this.currentLocalDescription = description;
771
- this.pendingLocalDescription = undefined;
772
- }
773
- else {
774
- this.pendingLocalDescription = description;
775
- }
776
- }
777
- getTransportByMid(mid) {
778
- let iceTransport;
779
- const transceiver = this.transceivers.find((t) => t.mid === mid);
780
- if (transceiver) {
781
- iceTransport = transceiver.dtlsTransport.iceTransport;
782
- }
783
- else if (!iceTransport && this.sctpTransport?.mid === mid) {
784
- iceTransport = this.sctpTransport?.dtlsTransport.iceTransport;
785
- }
786
- return iceTransport;
787
- }
788
- getTransportByMLineIndex(index) {
789
- const sdp = this.buildOfferSdp();
790
- const media = sdp.media[index];
791
- if (!media) {
792
- return;
793
- }
794
- const transport = this.getTransportByMid(media.rtp.muxId);
795
- return transport;
578
+ await this.secureManager.gatherCandidates(!!this.sdpManager.remoteIsBundled);
796
579
  }
797
580
  async addIceCandidate(candidateMessage) {
798
- const candidate = ice_1.IceCandidate.fromJSON(candidateMessage);
799
- if (!candidate) {
800
- return;
801
- }
802
- let iceTransport;
803
- if (typeof candidate.sdpMid === "number") {
804
- iceTransport = this.getTransportByMid(candidate.sdpMid);
805
- }
806
- if (!iceTransport && typeof candidate.sdpMLineIndex === "number") {
807
- iceTransport = this.getTransportByMLineIndex(candidate.sdpMLineIndex);
808
- }
809
- if (!iceTransport) {
810
- iceTransport = this.iceTransports[0];
811
- }
812
- if (iceTransport) {
813
- await iceTransport.addRemoteCandidate(candidate);
814
- }
815
- else {
816
- log("iceTransport not found", candidate);
817
- }
581
+ const sdp = this.sdpManager.buildOfferSdp(this.transceiverManager.getTransceivers(), this.sctpTransport);
582
+ await this.secureManager.addIceCandidate(sdp, candidateMessage);
818
583
  }
819
584
  async connect() {
820
585
  log("start connect");
@@ -823,12 +588,16 @@ class RTCPeerConnection extends helper_1.EventTarget {
823
588
  if (iceTransport.state === "connected") {
824
589
  return;
825
590
  }
826
- this.setConnectionState("connecting");
591
+ const checkDtlsConnected = () => dtlsTransport.state === "connected";
592
+ if (checkDtlsConnected()) {
593
+ return;
594
+ }
595
+ this.secureManager.setConnectionState("connecting");
827
596
  await iceTransport.start().catch((err) => {
828
597
  log("iceTransport.start failed", err);
829
598
  throw err;
830
599
  });
831
- if (dtlsTransport.state === "connected") {
600
+ if (checkDtlsConnected()) {
832
601
  return;
833
602
  }
834
603
  await dtlsTransport.start().catch((err) => {
@@ -836,85 +605,27 @@ class RTCPeerConnection extends helper_1.EventTarget {
836
605
  throw err;
837
606
  });
838
607
  if (this.sctpTransport &&
839
- this.sctpRemotePort &&
840
608
  this.sctpTransport.dtlsTransport.id === dtlsTransport.id) {
841
- await this.sctpTransport.start(this.sctpRemotePort);
842
- await this.sctpTransport.sctp.stateChanged.connected.asPromise();
843
- log("sctp connected");
609
+ await this.sctpManager.connectSctp();
844
610
  }
845
611
  }));
846
612
  if (res.find((r) => r.status === "rejected")) {
847
- this.setConnectionState("failed");
613
+ this.secureManager.setConnectionState("failed");
848
614
  }
849
615
  else {
850
- this.setConnectionState("connected");
851
- }
852
- }
853
- getLocalRtpParams(transceiver) {
854
- if (transceiver.mid == undefined)
855
- throw new Error("mid not assigned");
856
- const rtp = {
857
- codecs: transceiver.codecs,
858
- muxId: transceiver.mid,
859
- headerExtensions: transceiver.headerExtensions,
860
- rtcp: { cname: this.cname, ssrc: transceiver.sender.ssrc, mux: true },
861
- };
862
- return rtp;
863
- }
864
- getRemoteRtpParams(media, transceiver) {
865
- const receiveParameters = {
866
- muxId: media.rtp.muxId,
867
- rtcp: media.rtp.rtcp,
868
- codecs: transceiver.codecs,
869
- headerExtensions: transceiver.headerExtensions,
870
- encodings: Object.values(transceiver.codecs.reduce((acc, codec) => {
871
- if (codec.name.toLowerCase() === "rtx") {
872
- const params = (0, sdp_1.codecParametersFromString)(codec.parameters ?? "");
873
- const apt = acc[params["apt"]];
874
- if (apt && media.ssrc.length === 2) {
875
- apt.rtx = new media_1.RTCRtpRtxParameters({ ssrc: media.ssrc[1].ssrc });
876
- }
877
- return acc;
878
- }
879
- acc[codec.payloadType] = new media_1.RTCRtpCodingParameters({
880
- ssrc: media.ssrc[0]?.ssrc,
881
- payloadType: codec.payloadType,
882
- });
883
- return acc;
884
- }, {})),
885
- };
886
- return receiveParameters;
887
- }
888
- get remoteIsBundled() {
889
- const remoteSdp = this._remoteDescription;
890
- if (!remoteSdp) {
891
- return undefined;
616
+ this.secureManager.setConnectionState("connected");
892
617
  }
893
- const bundle = remoteSdp.group.find((g) => g.semantic === "BUNDLE" && this.config.bundlePolicy !== "disable");
894
- return bundle;
895
618
  }
896
619
  restartIce() {
897
620
  this.needRestart = true;
898
621
  this.needNegotiation();
899
622
  }
900
623
  async setRemoteDescription(sessionDescription) {
901
- if (!sessionDescription.sdp ||
902
- !sessionDescription.type ||
903
- sessionDescription.type === "rollback" ||
904
- sessionDescription.type === "pranswer") {
905
- throw new Error("invalid sessionDescription");
624
+ if (sessionDescription instanceof sdp_1.SessionDescription) {
625
+ sessionDescription = sessionDescription.toSdp();
906
626
  }
907
627
  // # parse and validate description
908
- const remoteSdp = sdp_1.SessionDescription.parse(sessionDescription.sdp);
909
- remoteSdp.type = sessionDescription.type;
910
- this.validateDescription(remoteSdp, false);
911
- if (remoteSdp.type === "answer") {
912
- this.currentRemoteDescription = remoteSdp;
913
- this.pendingRemoteDescription = undefined;
914
- }
915
- else {
916
- this.pendingRemoteDescription = remoteSdp;
917
- }
628
+ const remoteSdp = this.sdpManager.setRemoteDescription(sessionDescription, this.signalingState);
918
629
  let bundleTransport;
919
630
  // # apply description
920
631
  const matchTransceiverWithMedia = (transceiver, media) => transceiver.kind === media.kind &&
@@ -922,10 +633,12 @@ class RTCPeerConnection extends helper_1.EventTarget {
922
633
  let transports = remoteSdp.media.map((remoteMedia, i) => {
923
634
  let dtlsTransport;
924
635
  if (["audio", "video"].includes(remoteMedia.kind)) {
925
- let transceiver = this.transceivers.find((t) => matchTransceiverWithMedia(t, remoteMedia));
636
+ let transceiver = this.transceiverManager
637
+ .getTransceivers()
638
+ .find((t) => matchTransceiverWithMedia(t, remoteMedia));
926
639
  if (!transceiver) {
927
640
  // create remote transceiver
928
- transceiver = this._addTransceiver(remoteMedia.kind, {
641
+ transceiver = this.addTransceiver(remoteMedia.kind, {
929
642
  direction: "recvonly",
930
643
  });
931
644
  transceiver.mid = remoteMedia.rtp.muxId;
@@ -940,7 +653,7 @@ class RTCPeerConnection extends helper_1.EventTarget {
940
653
  return;
941
654
  }
942
655
  }
943
- if (this.remoteIsBundled) {
656
+ if (this.sdpManager.remoteIsBundled) {
944
657
  if (!bundleTransport) {
945
658
  bundleTransport = transceiver.dtlsTransport;
946
659
  }
@@ -949,30 +662,31 @@ class RTCPeerConnection extends helper_1.EventTarget {
949
662
  }
950
663
  }
951
664
  dtlsTransport = transceiver.dtlsTransport;
952
- this.setRemoteRTP(transceiver, remoteMedia, remoteSdp.type, i);
665
+ this.transceiverManager.setRemoteRTP(transceiver, remoteMedia, remoteSdp.type, i);
953
666
  }
954
667
  else if (remoteMedia.kind === "application") {
955
- if (!this.sctpTransport) {
956
- this.sctpTransport = this.createSctpTransport();
957
- this.sctpTransport.mid = remoteMedia.rtp.muxId;
668
+ let sctpTransport = this.sctpTransport;
669
+ if (!sctpTransport) {
670
+ sctpTransport = this.createSctpTransport();
671
+ sctpTransport.mid = remoteMedia.rtp.muxId;
958
672
  }
959
- if (this.remoteIsBundled) {
673
+ if (this.sdpManager.remoteIsBundled) {
960
674
  if (!bundleTransport) {
961
- bundleTransport = this.sctpTransport.dtlsTransport;
675
+ bundleTransport = sctpTransport.dtlsTransport;
962
676
  }
963
677
  else {
964
- this.sctpTransport.setDtlsTransport(bundleTransport);
678
+ sctpTransport.setDtlsTransport(bundleTransport);
965
679
  }
966
680
  }
967
- dtlsTransport = this.sctpTransport.dtlsTransport;
968
- this.setRemoteSCTP(remoteMedia, this.sctpTransport, i);
681
+ dtlsTransport = sctpTransport.dtlsTransport;
682
+ this.sctpManager.setRemoteSCTP(remoteMedia, i);
969
683
  }
970
684
  else {
971
685
  throw new Error("invalid media kind");
972
686
  }
973
687
  const iceTransport = dtlsTransport.iceTransport;
974
688
  if (remoteMedia.iceParams) {
975
- const renomination = !!remoteSdp.media.find((m) => m.direction === "inactive");
689
+ const renomination = !!this.sdpManager.inactiveRemoteMedia;
976
690
  iceTransport.setRemoteParams(remoteMedia.iceParams, renomination);
977
691
  // One agent full, one lite: The full agent MUST take the controlling role, and the lite agent MUST take the controlled role
978
692
  // RFC 8445 S6.1.1
@@ -997,7 +711,9 @@ class RTCPeerConnection extends helper_1.EventTarget {
997
711
  });
998
712
  // filter out inactive transports
999
713
  transports = transports.filter((iceTransport) => !!iceTransport);
1000
- const removedTransceivers = this.transceivers.filter((t) => remoteSdp.media.find((m) => matchTransceiverWithMedia(t, m)) ==
714
+ const removedTransceivers = this.transceiverManager
715
+ .getTransceivers()
716
+ .filter((t) => remoteSdp.media.find((m) => matchTransceiverWithMedia(t, m)) ==
1001
717
  undefined);
1002
718
  if (sessionDescription.type === "answer") {
1003
719
  for (const transceiver of removedTransceivers) {
@@ -1018,7 +734,7 @@ class RTCPeerConnection extends helper_1.EventTarget {
1018
734
  log("caller start connect");
1019
735
  this.connect().catch((err) => {
1020
736
  log("connect failed", err);
1021
- this.setConnectionState("failed");
737
+ this.secureManager.setConnectionState("failed");
1022
738
  });
1023
739
  }
1024
740
  this.negotiationneeded = false;
@@ -1026,177 +742,12 @@ class RTCPeerConnection extends helper_1.EventTarget {
1026
742
  this.needNegotiation();
1027
743
  }
1028
744
  }
1029
- setRemoteRTP(transceiver, remoteMedia, type, mLineIndex) {
1030
- if (!transceiver.mid) {
1031
- transceiver.mid = remoteMedia.rtp.muxId;
1032
- }
1033
- transceiver.mLineIndex = mLineIndex;
1034
- // # negotiate codecs
1035
- transceiver.codecs = remoteMedia.rtp.codecs.filter((remoteCodec) => {
1036
- const localCodecs = this.config.codecs[remoteMedia.kind] || [];
1037
- const existCodec = (0, exports.findCodecByMimeType)(localCodecs, remoteCodec);
1038
- if (!existCodec) {
1039
- return false;
1040
- }
1041
- if (existCodec?.name.toLowerCase() === "rtx") {
1042
- const params = (0, sdp_1.codecParametersFromString)(existCodec.parameters ?? "");
1043
- const pt = params["apt"];
1044
- const origin = remoteMedia.rtp.codecs.find((c) => c.payloadType === pt);
1045
- if (!origin) {
1046
- return false;
1047
- }
1048
- return !!(0, exports.findCodecByMimeType)(localCodecs, origin);
1049
- }
1050
- return true;
1051
- });
1052
- log("negotiated codecs", transceiver.codecs);
1053
- if (transceiver.codecs.length === 0) {
1054
- throw new Error("negotiate codecs failed.");
1055
- }
1056
- transceiver.headerExtensions = remoteMedia.rtp.headerExtensions.filter((extension) => (this.config.headerExtensions[remoteMedia.kind] || []).find((v) => v.uri === extension.uri));
1057
- // # configure direction
1058
- const mediaDirection = remoteMedia.direction ?? "inactive";
1059
- const direction = (0, utils_1.reverseDirection)(mediaDirection);
1060
- if (["answer", "pranswer"].includes(type)) {
1061
- transceiver.setCurrentDirection(direction);
1062
- }
1063
- else {
1064
- transceiver.offerDirection = direction;
1065
- }
1066
- const localParams = this.getLocalRtpParams(transceiver);
1067
- transceiver.sender.prepareSend(localParams);
1068
- if (["recvonly", "sendrecv"].includes(transceiver.direction)) {
1069
- const remotePrams = this.getRemoteRtpParams(remoteMedia, transceiver);
1070
- // register simulcast receiver
1071
- remoteMedia.simulcastParameters.forEach((param) => {
1072
- this.router.registerRtpReceiverByRid(transceiver, param, remotePrams);
1073
- });
1074
- transceiver.receiver.prepareReceive(remotePrams);
1075
- // register ssrc receiver
1076
- this.router.registerRtpReceiverBySsrc(transceiver, remotePrams);
1077
- }
1078
- if (["sendonly", "sendrecv"].includes(mediaDirection)) {
1079
- if (remoteMedia.msid) {
1080
- const [streamId, trackId] = remoteMedia.msid.split(" ");
1081
- transceiver.receiver.remoteStreamId = streamId;
1082
- transceiver.receiver.remoteTrackId = trackId;
1083
- }
1084
- this.fireOnTrack(transceiver.receiver.track, transceiver, new media_1.MediaStream({
1085
- id: transceiver.receiver.remoteStreamId,
1086
- tracks: [transceiver.receiver.track],
1087
- }));
1088
- }
1089
- if (remoteMedia.ssrc[0]?.ssrc) {
1090
- transceiver.receiver.setupTWCC(remoteMedia.ssrc[0].ssrc);
1091
- }
1092
- }
1093
- setRemoteSCTP(remoteMedia, sctpTransport, mLineIndex) {
1094
- // # configure sctp
1095
- this.sctpRemotePort = remoteMedia.sctpPort;
1096
- if (!this.sctpRemotePort) {
1097
- throw new Error("sctpRemotePort not exist");
1098
- }
1099
- sctpTransport.setRemotePort(this.sctpRemotePort);
1100
- sctpTransport.mLineIndex = mLineIndex;
1101
- if (!sctpTransport.mid) {
1102
- sctpTransport.mid = remoteMedia.rtp.muxId;
1103
- }
1104
- }
1105
- validateDescription(description, isLocal) {
1106
- if (isLocal) {
1107
- if (description.type === "offer") {
1108
- if (!["stable", "have-local-offer"].includes(this.signalingState))
1109
- throw new Error("Cannot handle offer in signaling state");
1110
- }
1111
- else if (description.type === "answer") {
1112
- if (!["have-remote-offer", "have-local-pranswer"].includes(this.signalingState)) {
1113
- throw new Error("Cannot handle answer in signaling state");
1114
- }
1115
- }
1116
- }
1117
- else {
1118
- if (description.type === "offer") {
1119
- if (!["stable", "have-remote-offer"].includes(this.signalingState)) {
1120
- throw new Error("Cannot handle offer in signaling state");
1121
- }
1122
- }
1123
- else if (description.type === "answer") {
1124
- if (!["have-local-offer", "have-remote-pranswer"].includes(this.signalingState)) {
1125
- throw new Error("Cannot handle answer in signaling state");
1126
- }
1127
- }
1128
- }
1129
- description.media.forEach((media) => {
1130
- if (media.direction === "inactive")
1131
- return;
1132
- if (!media.iceParams ||
1133
- !media.iceParams.usernameFragment ||
1134
- !media.iceParams.password)
1135
- throw new Error("ICE username fragment or password is missing");
1136
- });
1137
- if (["answer", "pranswer"].includes(description.type || "")) {
1138
- const offer = isLocal ? this._remoteDescription : this._localDescription;
1139
- if (!offer)
1140
- throw new Error();
1141
- const answerMedia = description.media.map((v, i) => [v.kind, i]);
1142
- const offerMedia = offer.media.map((v, i) => [v.kind, i]);
1143
- if (!(0, isEqual_js_1.default)(offerMedia, answerMedia)) {
1144
- throw new Error("Media sections in answer do not match offer");
1145
- }
1146
- }
1147
- }
1148
- fireOnTrack(track, transceiver, stream) {
1149
- const event = {
1150
- track,
1151
- streams: [stream],
1152
- transceiver,
1153
- receiver: transceiver.receiver,
1154
- };
1155
- this.onTrack.execute(track);
1156
- this.emit("track", event);
1157
- if (this.ontrack) {
1158
- this.ontrack(event);
1159
- }
1160
- }
1161
745
  addTransceiver(trackOrKind, options = {}) {
1162
- return this._addTransceiver(trackOrKind, options);
1163
- }
1164
- _addTransceiver(trackOrKind, options = {}) {
1165
- const kind = typeof trackOrKind === "string" ? trackOrKind : trackOrKind.kind;
1166
- const direction = options.direction || "sendrecv";
1167
- const dtlsTransport = this.createTransport([
1168
- const_1.SRTP_PROFILE.SRTP_AEAD_AES_128_GCM, // prefer
1169
- const_1.SRTP_PROFILE.SRTP_AES128_CM_HMAC_SHA1_80,
1170
- ]);
1171
- const sender = new media_1.RTCRtpSender(trackOrKind);
1172
- const receiver = new media_1.RTCRtpReceiver(this.config, kind, sender.ssrc);
1173
- const newTransceiver = new media_1.RTCRtpTransceiver(kind, dtlsTransport, receiver, sender, direction);
1174
- newTransceiver.options = options;
1175
- this.router.registerRtpSender(newTransceiver.sender);
1176
- // reuse inactive
1177
- const inactiveTransceiverIndex = this.transceivers.findIndex((t) => t.currentDirection === "inactive");
1178
- const inactiveTransceiver = this.transceivers.find((t) => t.currentDirection === "inactive");
1179
- if (inactiveTransceiverIndex > -1 && inactiveTransceiver) {
1180
- this.replaceTransceiver(newTransceiver, inactiveTransceiverIndex);
1181
- newTransceiver.mLineIndex = inactiveTransceiver.mLineIndex;
1182
- inactiveTransceiver.setCurrentDirection(undefined);
1183
- }
1184
- else {
1185
- this.pushTransceiver(newTransceiver);
1186
- }
1187
- this.onTransceiverAdded.execute(newTransceiver);
1188
- this.updateIceConnectionState();
746
+ const dtlsTransport = this.findOrCreateTransport();
747
+ const transceiver = this.transceiverManager.addTransceiver(trackOrKind, dtlsTransport, options);
748
+ this.secureManager.updateIceConnectionState();
1189
749
  this.needNegotiation();
1190
- return newTransceiver;
1191
- }
1192
- getTransceivers() {
1193
- return this.transceivers;
1194
- }
1195
- getSenders() {
1196
- return this.getTransceivers().map((t) => t.sender);
1197
- }
1198
- getReceivers() {
1199
- return this.getTransceivers().map((t) => t.receiver);
750
+ return transceiver;
1200
751
  }
1201
752
  // todo fix
1202
753
  addTrack(track,
@@ -1205,207 +756,29 @@ class RTCPeerConnection extends helper_1.EventTarget {
1205
756
  if (this.isClosed) {
1206
757
  throw new Error("is closed");
1207
758
  }
1208
- if (this.getSenders().find((sender) => sender.track?.uuid === track.uuid)) {
1209
- throw new Error("track exist");
1210
- }
1211
- const emptyTrackSender = this.transceivers.find((t) => t.sender.track == undefined &&
1212
- t.kind === track.kind &&
1213
- const_1.SenderDirections.includes(t.direction) === true);
1214
- if (emptyTrackSender) {
1215
- const sender = emptyTrackSender.sender;
1216
- sender.registerTrack(track);
1217
- this.needNegotiation();
1218
- return sender;
1219
- }
1220
- const notSendTransceiver = this.transceivers.find((t) => t.sender.track == undefined &&
1221
- t.kind === track.kind &&
1222
- const_1.SenderDirections.includes(t.direction) === false &&
1223
- !t.usedForSender);
1224
- if (notSendTransceiver) {
1225
- const sender = notSendTransceiver.sender;
1226
- sender.registerTrack(track);
1227
- switch (notSendTransceiver.direction) {
1228
- case "recvonly":
1229
- notSendTransceiver.setDirection("sendrecv");
1230
- break;
1231
- case "inactive":
1232
- notSendTransceiver.setDirection("sendonly");
1233
- break;
1234
- }
1235
- this.needNegotiation();
1236
- return sender;
1237
- }
1238
- else {
1239
- const transceiver = this._addTransceiver(track, {
1240
- direction: "sendrecv",
1241
- });
1242
- this.needNegotiation();
1243
- return transceiver.sender;
1244
- }
1245
- }
1246
- async ensureCerts() {
1247
- if (!this.certificate) {
1248
- this.certificate = await dtls_1.RTCDtlsTransport.SetupCertificate();
1249
- }
1250
- for (const dtlsTransport of this.dtlsTransports) {
1251
- dtlsTransport.localCertificate = this.certificate;
759
+ const transceiver = this.transceiverManager.addTrack(track, ms);
760
+ if (!transceiver.dtlsTransport) {
761
+ const dtlsTransport = this.findOrCreateTransport();
762
+ transceiver.setDtlsTransport(dtlsTransport);
1252
763
  }
764
+ this.needNegotiation();
765
+ return transceiver.sender;
1253
766
  }
1254
767
  async createAnswer() {
1255
- await this.ensureCerts();
1256
- const description = this.buildAnswer();
1257
- return description.toJSON();
1258
- }
1259
- buildAnswer() {
1260
768
  this.assertNotClosed();
1261
- if (!["have-remote-offer", "have-local-pranswer"].includes(this.signalingState)) {
1262
- throw new Error("createAnswer failed");
1263
- }
1264
- if (!this._remoteDescription) {
1265
- throw new Error("wrong state");
1266
- }
1267
- const description = new sdp_1.SessionDescription();
1268
- (0, sdp_1.addSDPHeader)("answer", description);
1269
- this._remoteDescription.media.forEach((remoteMedia) => {
1270
- let dtlsTransport;
1271
- let media;
1272
- if (["audio", "video"].includes(remoteMedia.kind)) {
1273
- const transceiver = this.getTransceiverByMid(remoteMedia.rtp.muxId);
1274
- media = createMediaDescriptionForTransceiver(transceiver, this.cname, (0, utils_1.andDirection)(transceiver.direction, transceiver.offerDirection));
1275
- dtlsTransport = transceiver.dtlsTransport;
1276
- }
1277
- else if (remoteMedia.kind === "application") {
1278
- if (!this.sctpTransport || !this.sctpTransport.mid) {
1279
- throw new Error("sctpTransport not found");
1280
- }
1281
- media = createMediaDescriptionForSctp(this.sctpTransport);
1282
- dtlsTransport = this.sctpTransport.dtlsTransport;
1283
- }
1284
- else {
1285
- throw new Error("invalid kind");
1286
- }
1287
- // # determine DTLS role, or preserve the currently configured role
1288
- if (media.dtlsParams) {
1289
- if (dtlsTransport.role === "auto") {
1290
- media.dtlsParams.role = "client";
1291
- }
1292
- else {
1293
- media.dtlsParams.role = dtlsTransport.role;
1294
- }
1295
- }
1296
- media.simulcastParameters = remoteMedia.simulcastParameters.map((v) => ({
1297
- ...v,
1298
- direction: (0, utils_1.reverseSimulcastDirection)(v.direction),
1299
- }));
1300
- description.media.push(media);
769
+ await this.secureManager.ensureCerts();
770
+ const description = this.sdpManager.buildAnswerSdp({
771
+ transceivers: this.transceiverManager.getTransceivers(),
772
+ sctpTransport: this.sctpTransport,
773
+ signalingState: this.signalingState,
1301
774
  });
1302
- if (this.config.bundlePolicy !== "disable") {
1303
- const bundle = new sdp_1.GroupDescription("BUNDLE", []);
1304
- for (const media of description.media) {
1305
- if (media.direction !== "inactive") {
1306
- bundle.items.push(media.rtp.muxId);
1307
- }
1308
- }
1309
- description.group.push(bundle);
1310
- }
1311
- return description;
1312
- }
1313
- async close() {
1314
- if (this.isClosed)
1315
- return;
1316
- this.isClosed = true;
1317
- this.setSignalingState("closed");
1318
- this.setConnectionState("closed");
1319
- this.transceivers.forEach((transceiver) => {
1320
- transceiver.receiver.stop();
1321
- transceiver.sender.stop();
1322
- });
1323
- if (this.sctpTransport) {
1324
- await this.sctpTransport.stop();
1325
- }
1326
- for (const dtlsTransport of this.dtlsTransports) {
1327
- await dtlsTransport.stop();
1328
- await dtlsTransport.iceTransport.stop();
1329
- }
1330
- this.dispose();
1331
- log("peerConnection closed");
775
+ return description.toJSON();
1332
776
  }
1333
777
  assertNotClosed() {
1334
778
  if (this.isClosed) {
1335
779
  throw new Error("RTCPeerConnection is closed");
1336
780
  }
1337
781
  }
1338
- // https://w3c.github.io/webrtc-pc/#dom-rtcicegatheringstate
1339
- updateIceGatheringState() {
1340
- const all = this.iceTransports;
1341
- function allMatch(...state) {
1342
- return (all.filter((check) => state.includes(check.gatheringState)).length ===
1343
- all.length);
1344
- }
1345
- let newState;
1346
- if (all.length && allMatch("complete")) {
1347
- newState = "complete";
1348
- }
1349
- else if (!all.length || allMatch("new", "complete")) {
1350
- newState = "new";
1351
- }
1352
- else if (all.map((check) => check.gatheringState).includes("gathering")) {
1353
- newState = "gathering";
1354
- }
1355
- else {
1356
- newState = "new";
1357
- }
1358
- if (this.iceGatheringState === newState) {
1359
- return;
1360
- }
1361
- log("iceGatheringStateChange", newState);
1362
- this.iceGatheringState = newState;
1363
- this.iceGatheringStateChange.execute(newState);
1364
- this.emit("icegatheringstatechange", newState);
1365
- }
1366
- // https://w3c.github.io/webrtc-pc/#dom-rtciceconnectionstate
1367
- updateIceConnectionState() {
1368
- const all = this.iceTransports;
1369
- let newState;
1370
- function allMatch(...state) {
1371
- return (all.filter((check) => state.includes(check.state)).length === all.length);
1372
- }
1373
- if (this.connectionState === "closed") {
1374
- newState = "closed";
1375
- }
1376
- else if (allMatch("failed")) {
1377
- newState = "failed";
1378
- }
1379
- else if (allMatch("disconnected")) {
1380
- newState = "disconnected";
1381
- }
1382
- else if (allMatch("new", "closed")) {
1383
- newState = "new";
1384
- }
1385
- else if (allMatch("new", "checking")) {
1386
- newState = "checking";
1387
- }
1388
- else if (allMatch("completed", "closed")) {
1389
- newState = "completed";
1390
- }
1391
- else if (allMatch("connected", "completed", "closed")) {
1392
- newState = "connected";
1393
- }
1394
- else {
1395
- // unreachable?
1396
- newState = "new";
1397
- }
1398
- if (this.iceConnectionState === newState) {
1399
- return;
1400
- }
1401
- log("iceConnectionStateChange", newState);
1402
- this.iceConnectionState = newState;
1403
- this.iceConnectionStateChange.execute(newState);
1404
- this.emit("iceconnectionstatechange", newState);
1405
- if (this.oniceconnectionstatechange) {
1406
- this.oniceconnectionstatechange();
1407
- }
1408
- }
1409
782
  setSignalingState(state) {
1410
783
  log("signalingStateChange", state);
1411
784
  this.signalingState = state;
@@ -1414,16 +787,43 @@ class RTCPeerConnection extends helper_1.EventTarget {
1414
787
  this.onsignalingstatechange({});
1415
788
  }
1416
789
  }
1417
- setConnectionState(state) {
1418
- log("connectionStateChange", state);
1419
- this.connectionState = state;
1420
- this.connectionStateChange.execute(state);
1421
- if (this.onconnectionstatechange) {
1422
- this.onconnectionstatechange();
790
+ createPeerConnectionStats() {
791
+ const timestamp = (0, stats_1.getStatsTimestamp)();
792
+ return {
793
+ type: "peer-connection",
794
+ id: (0, stats_1.generateStatsId)("peer-connection"),
795
+ timestamp,
796
+ dataChannelsOpened: this.sctpManager.dataChannelsOpened,
797
+ dataChannelsClosed: this.sctpManager.dataChannelsClosed,
798
+ };
799
+ }
800
+ async getStats(selector) {
801
+ const stats = [];
802
+ // Peer connection stats - always included regardless of selector
803
+ stats.push(this.createPeerConnectionStats());
804
+ // Get stats from transceivers
805
+ const transceiverStats = await this.transceiverManager.getStats(selector);
806
+ stats.push(...transceiverStats);
807
+ // Get transport stats - always included regardless of selector
808
+ const transportStats = await this.secureManager.getStats();
809
+ stats.push(...transportStats);
810
+ // Get data channel stats - always included regardless of selector
811
+ if (this.sctpTransport) {
812
+ const dataChannelStats = await this.sctpManager.getStats();
813
+ if (dataChannelStats) {
814
+ stats.push(...dataChannelStats);
815
+ }
1423
816
  }
1424
- this.emit("connectionstatechange");
817
+ return new stats_1.RTCStatsReport(stats);
1425
818
  }
1426
- dispose() {
819
+ async close() {
820
+ if (this.isClosed)
821
+ return;
822
+ this.isClosed = true;
823
+ this.setSignalingState("closed");
824
+ await this.secureManager.close();
825
+ await this.sctpManager.close();
826
+ this.transceiverManager.close();
1427
827
  this.onDataChannel.allUnsubscribe();
1428
828
  this.iceGatheringStateChange.allUnsubscribe();
1429
829
  this.iceConnectionStateChange.allUnsubscribe();
@@ -1431,77 +831,10 @@ class RTCPeerConnection extends helper_1.EventTarget {
1431
831
  this.onTransceiverAdded.allUnsubscribe();
1432
832
  this.onRemoteTransceiverAdded.allUnsubscribe();
1433
833
  this.onIceCandidate.allUnsubscribe();
834
+ log("peerConnection closed");
1434
835
  }
1435
836
  }
1436
837
  exports.RTCPeerConnection = RTCPeerConnection;
1437
- function createMediaDescriptionForTransceiver(transceiver, cname, direction) {
1438
- const media = new sdp_1.MediaDescription(transceiver.kind, 9, "UDP/TLS/RTP/SAVPF", transceiver.codecs.map((c) => c.payloadType));
1439
- media.direction = direction;
1440
- media.msid = transceiver.msid;
1441
- media.rtp = {
1442
- codecs: transceiver.codecs,
1443
- headerExtensions: transceiver.headerExtensions,
1444
- muxId: transceiver.mid,
1445
- };
1446
- media.rtcpHost = "0.0.0.0";
1447
- media.rtcpPort = 9;
1448
- media.rtcpMux = true;
1449
- media.ssrc = [new sdp_1.SsrcDescription({ ssrc: transceiver.sender.ssrc, cname })];
1450
- if (transceiver.options.simulcast) {
1451
- media.simulcastParameters = transceiver.options.simulcast.map((o) => new media_1.RTCRtpSimulcastParameters(o));
1452
- }
1453
- if (media.rtp.codecs.find((c) => c.name.toLowerCase() === "rtx")) {
1454
- media.ssrc.push(new sdp_1.SsrcDescription({ ssrc: transceiver.sender.rtxSsrc, cname }));
1455
- media.ssrcGroup = [
1456
- new sdp_1.GroupDescription("FID", [
1457
- transceiver.sender.ssrc.toString(),
1458
- transceiver.sender.rtxSsrc.toString(),
1459
- ]),
1460
- ];
1461
- }
1462
- addTransportDescription(media, transceiver.dtlsTransport);
1463
- return media;
1464
- }
1465
- function createMediaDescriptionForSctp(sctp) {
1466
- const media = new sdp_1.MediaDescription("application", const_1.DISCARD_PORT, "UDP/DTLS/SCTP", ["webrtc-datachannel"]);
1467
- media.sctpPort = sctp.port;
1468
- media.rtp.muxId = sctp.mid;
1469
- media.sctpCapabilities = sctp_1.RTCSctpTransport.getCapabilities();
1470
- addTransportDescription(media, sctp.dtlsTransport);
1471
- return media;
1472
- }
1473
- function addTransportDescription(media, dtlsTransport) {
1474
- const iceTransport = dtlsTransport.iceTransport;
1475
- media.iceCandidates = iceTransport.localCandidates;
1476
- media.iceCandidatesComplete = iceTransport.gatheringState === "complete";
1477
- media.iceParams = iceTransport.localParameters;
1478
- media.iceOptions = "trickle";
1479
- media.host = const_1.DISCARD_HOST;
1480
- media.port = const_1.DISCARD_PORT;
1481
- if (media.direction === "inactive") {
1482
- media.port = 0;
1483
- media.msid = undefined;
1484
- }
1485
- if (!media.dtlsParams) {
1486
- media.dtlsParams = dtlsTransport.localParameters;
1487
- if (!media.dtlsParams.fingerprints) {
1488
- media.dtlsParams.fingerprints =
1489
- dtlsTransport.localParameters.fingerprints;
1490
- }
1491
- }
1492
- }
1493
- function allocateMid(mids, type) {
1494
- let mid = "";
1495
- for (let i = 0;;) {
1496
- // rfc9143.html#name-security-considerations
1497
- // SHOULD be 3 bytes or fewer to allow them to efficiently fit into the MID RTP header extension
1498
- mid = (i++).toString() + type;
1499
- if (!mids.has(mid))
1500
- break;
1501
- }
1502
- mids.add(mid);
1503
- return mid;
1504
- }
1505
838
  const findCodecByMimeType = (codecs, target) => codecs.find((localCodec) => localCodec.mimeType.toLowerCase() === target.mimeType.toLowerCase())
1506
839
  ? target
1507
840
  : undefined;