werift 0.22.1 → 0.22.3

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 (244) hide show
  1. package/lib/common/src/binary.d.ts +8 -7
  2. package/lib/common/src/binary.js +5 -2
  3. package/lib/common/src/binary.js.map +1 -1
  4. package/lib/common/src/event.d.ts +1 -0
  5. package/lib/common/src/event.js +5 -0
  6. package/lib/common/src/event.js.map +1 -1
  7. package/lib/common/src/log.d.ts +1 -2
  8. package/lib/common/src/transport.d.ts +4 -1
  9. package/lib/common/src/transport.js +35 -14
  10. package/lib/common/src/transport.js.map +1 -1
  11. package/lib/dtls/src/cipher/create.d.ts +2 -1
  12. package/lib/dtls/src/cipher/create.js.map +1 -1
  13. package/lib/dtls/src/cipher/prf.d.ts +12 -12
  14. package/lib/dtls/src/cipher/suites/abstract.d.ts +2 -1
  15. package/lib/dtls/src/cipher/suites/abstract.js.map +1 -1
  16. package/lib/dtls/src/cipher/suites/aead.d.ts +3 -2
  17. package/lib/dtls/src/cipher/suites/aead.js +34 -41
  18. package/lib/dtls/src/cipher/suites/aead.js.map +1 -1
  19. package/lib/dtls/src/context/cipher.d.ts +4 -4
  20. package/lib/dtls/src/context/cipher.js +25 -15
  21. package/lib/dtls/src/context/cipher.js.map +1 -1
  22. package/lib/dtls/src/context/srtp.d.ts +3 -3
  23. package/lib/dtls/src/context/srtp.js.map +1 -1
  24. package/lib/dtls/src/flight/client/flight5.js.map +1 -1
  25. package/lib/dtls/src/flight/server/flight2.js.map +1 -1
  26. package/lib/dtls/src/handshake/extensions/ellipticCurves.d.ts +1 -1
  27. package/lib/dtls/src/handshake/extensions/renegotiationIndication.d.ts +2 -2
  28. package/lib/dtls/src/handshake/extensions/signature.d.ts +2 -2
  29. package/lib/dtls/src/handshake/extensions/useSrtp.d.ts +1 -1
  30. package/lib/dtls/src/handshake/extensions/useSrtp.js +4 -7
  31. package/lib/dtls/src/handshake/extensions/useSrtp.js.map +1 -1
  32. package/lib/dtls/src/handshake/message/alert.d.ts +1 -1
  33. package/lib/dtls/src/handshake/message/certificate.d.ts +1 -1
  34. package/lib/dtls/src/handshake/message/changeCipherSpec.d.ts +1 -1
  35. package/lib/dtls/src/handshake/message/client/certificateVerify.d.ts +1 -1
  36. package/lib/dtls/src/handshake/message/client/hello.d.ts +1 -1
  37. package/lib/dtls/src/handshake/message/client/keyExchange.d.ts +1 -1
  38. package/lib/dtls/src/handshake/message/finished.d.ts +1 -1
  39. package/lib/dtls/src/handshake/message/server/certificateRequest.d.ts +1 -1
  40. package/lib/dtls/src/handshake/message/server/hello.d.ts +1 -1
  41. package/lib/dtls/src/handshake/message/server/helloDone.d.ts +1 -1
  42. package/lib/dtls/src/handshake/message/server/helloVerifyRequest.d.ts +1 -1
  43. package/lib/dtls/src/handshake/message/server/keyExchange.d.ts +1 -1
  44. package/lib/dtls/src/handshake/random.d.ts +3 -3
  45. package/lib/dtls/src/record/message/fragment.d.ts +1 -1
  46. package/lib/dtls/src/record/message/header.d.ts +2 -19
  47. package/lib/dtls/src/record/message/header.js +1 -60
  48. package/lib/dtls/src/record/message/header.js.map +1 -1
  49. package/lib/dtls/src/record/message/plaintext.d.ts +6 -27
  50. package/lib/dtls/src/record/message/plaintext.js +34 -16
  51. package/lib/dtls/src/record/message/plaintext.js.map +1 -1
  52. package/lib/dtls/src/socket.d.ts +4 -4
  53. package/lib/dtls/src/socket.js.map +1 -1
  54. package/lib/dtls/src/util/binary.d.ts +1 -1
  55. package/lib/ice/src/candidate.js +1 -5
  56. package/lib/ice/src/candidate.js.map +1 -1
  57. package/lib/ice/src/helper.d.ts +1 -1
  58. package/lib/ice/src/ice.d.ts +4 -3
  59. package/lib/ice/src/ice.js +93 -72
  60. package/lib/ice/src/ice.js.map +1 -1
  61. package/lib/ice/src/iceBase.d.ts +21 -2
  62. package/lib/ice/src/iceBase.js +47 -1
  63. package/lib/ice/src/iceBase.js.map +1 -1
  64. package/lib/ice/src/stun/attributes.d.ts +2 -2
  65. package/lib/ice/src/stun/attributes.js +48 -29
  66. package/lib/ice/src/stun/attributes.js.map +1 -1
  67. package/lib/ice/src/stun/message.d.ts +2 -2
  68. package/lib/ice/src/stun/message.js +22 -23
  69. package/lib/ice/src/stun/message.js.map +1 -1
  70. package/lib/ice/src/stun/protocol.d.ts +2 -2
  71. package/lib/ice/src/stun/protocol.js +6 -0
  72. package/lib/ice/src/stun/protocol.js.map +1 -1
  73. package/lib/ice/src/turn/protocol.d.ts +2 -2
  74. package/lib/ice/src/turn/protocol.js +3 -0
  75. package/lib/ice/src/turn/protocol.js.map +1 -1
  76. package/lib/index.mjs +2707 -1883
  77. package/lib/nonstandard/index.mjs +737 -698
  78. package/lib/rtp/src/codec/av1.d.ts +2 -2
  79. package/lib/rtp/src/codec/opus.d.ts +1 -1
  80. package/lib/rtp/src/extra/container/mp4/container.js +18 -8
  81. package/lib/rtp/src/extra/container/mp4/container.js.map +1 -1
  82. package/lib/rtp/src/extra/container/mp4/h264.d.ts +2 -2
  83. package/lib/rtp/src/extra/container/mp4/sps-parser.d.ts +1 -1
  84. package/lib/rtp/src/extra/container/ogg/parser.d.ts +1 -1
  85. package/lib/rtp/src/extra/container/webm/container.d.ts +9 -9
  86. package/lib/rtp/src/extra/container/webm/container.js +24 -12
  87. package/lib/rtp/src/extra/container/webm/container.js.map +1 -1
  88. package/lib/rtp/src/extra/container/webm/ebml/ebml.d.ts +35 -1
  89. package/lib/rtp/src/extra/container/webm/ebml/ebml.js +75 -1
  90. package/lib/rtp/src/extra/container/webm/ebml/ebml.js.map +1 -1
  91. package/lib/rtp/src/extra/container/webm/ebml/id.d.ts +222 -222
  92. package/lib/rtp/src/extra/container/webm/index.d.ts +1 -0
  93. package/lib/rtp/src/extra/container/webm/index.js +1 -0
  94. package/lib/rtp/src/extra/container/webm/index.js.map +1 -1
  95. package/lib/rtp/src/extra/container/webm/util.d.ts +8 -0
  96. package/lib/rtp/src/extra/container/webm/util.js +100 -0
  97. package/lib/rtp/src/extra/container/webm/util.js.map +1 -0
  98. package/lib/rtp/src/extra/processor/depacketizerCallback.d.ts +1 -1
  99. package/lib/rtp/src/extra/processor/depacketizerTransformer.d.ts +6 -1
  100. package/lib/rtp/src/extra/processor/dtx.d.ts +1 -1
  101. package/lib/rtp/src/extra/processor/dtx.js +1 -1
  102. package/lib/rtp/src/extra/processor/dtx.js.map +1 -1
  103. package/lib/rtp/src/extra/processor/dtxCallback.d.ts +1 -1
  104. package/lib/rtp/src/extra/processor/interface.d.ts +1 -1
  105. package/lib/rtp/src/extra/processor/jitterBufferCallback.d.ts +1 -1
  106. package/lib/rtp/src/extra/processor/lipsync.js +1 -1
  107. package/lib/rtp/src/extra/processor/lipsync.js.map +1 -1
  108. package/lib/rtp/src/extra/processor/mp4.js +3 -0
  109. package/lib/rtp/src/extra/processor/mp4.js.map +1 -1
  110. package/lib/rtp/src/extra/processor/mute.d.ts +1 -1
  111. package/lib/rtp/src/extra/processor/mute.js +1 -1
  112. package/lib/rtp/src/extra/processor/mute.js.map +1 -1
  113. package/lib/rtp/src/extra/processor/nackHandlerCallback.d.ts +1 -1
  114. package/lib/rtp/src/extra/processor/ntpTime.d.ts +1 -1
  115. package/lib/rtp/src/extra/processor/ntpTime.js +1 -1
  116. package/lib/rtp/src/extra/processor/ntpTime.js.map +1 -1
  117. package/lib/rtp/src/extra/processor/ntpTimeCallback.d.ts +1 -1
  118. package/lib/rtp/src/extra/processor/rtpTimeCallback.d.ts +1 -1
  119. package/lib/rtp/src/extra/processor/webm.d.ts +3 -3
  120. package/lib/rtp/src/extra/processor/webm.js.map +1 -1
  121. package/lib/rtp/src/extra/processor/webmStream.d.ts +2 -2
  122. package/lib/rtp/src/extra/processor/webmStream.js.map +1 -1
  123. package/lib/rtp/src/helper.d.ts +1 -1
  124. package/lib/rtp/src/rtcp/header.d.ts +2 -1
  125. package/lib/rtp/src/rtcp/header.js +10 -0
  126. package/lib/rtp/src/rtcp/header.js.map +1 -1
  127. package/lib/rtp/src/rtcp/psfb/fullIntraRequest.d.ts +1 -1
  128. package/lib/rtp/src/rtcp/psfb/index.d.ts +2 -2
  129. package/lib/rtp/src/rtcp/psfb/index.js +2 -2
  130. package/lib/rtp/src/rtcp/psfb/index.js.map +1 -1
  131. package/lib/rtp/src/rtcp/psfb/pictureLossIndication.d.ts +1 -1
  132. package/lib/rtp/src/rtcp/psfb/remb.d.ts +1 -1
  133. package/lib/rtp/src/rtcp/rr.d.ts +2 -2
  134. package/lib/rtp/src/rtcp/rr.js +2 -2
  135. package/lib/rtp/src/rtcp/rr.js.map +1 -1
  136. package/lib/rtp/src/rtcp/rtcp.d.ts +0 -1
  137. package/lib/rtp/src/rtcp/rtcp.js +0 -10
  138. package/lib/rtp/src/rtcp/rtcp.js.map +1 -1
  139. package/lib/rtp/src/rtcp/rtpfb/const.d.ts +1 -0
  140. package/lib/rtp/src/rtcp/rtpfb/const.js +5 -0
  141. package/lib/rtp/src/rtcp/rtpfb/const.js.map +1 -0
  142. package/lib/rtp/src/rtcp/rtpfb/index.d.ts +1 -1
  143. package/lib/rtp/src/rtcp/rtpfb/index.js +2 -1
  144. package/lib/rtp/src/rtcp/rtpfb/index.js.map +1 -1
  145. package/lib/rtp/src/rtcp/rtpfb/nack.d.ts +1 -1
  146. package/lib/rtp/src/rtcp/rtpfb/nack.js +2 -2
  147. package/lib/rtp/src/rtcp/rtpfb/nack.js.map +1 -1
  148. package/lib/rtp/src/rtcp/rtpfb/twcc.d.ts +4 -4
  149. package/lib/rtp/src/rtcp/sdes.d.ts +4 -4
  150. package/lib/rtp/src/rtcp/sdes.js +2 -2
  151. package/lib/rtp/src/rtcp/sdes.js.map +1 -1
  152. package/lib/rtp/src/rtcp/sr.d.ts +2 -2
  153. package/lib/rtp/src/rtcp/sr.js +2 -2
  154. package/lib/rtp/src/rtcp/sr.js.map +1 -1
  155. package/lib/rtp/src/rtp/headerExtension.d.ts +6 -6
  156. package/lib/rtp/src/rtp/red/packet.d.ts +2 -2
  157. package/lib/rtp/src/rtp/rtp.d.ts +2 -2
  158. package/lib/rtp/src/srtp/cipher/ctr.d.ts +4 -4
  159. package/lib/rtp/src/srtp/cipher/gcm.d.ts +4 -4
  160. package/lib/rtp/src/srtp/const.d.ts +3 -3
  161. package/lib/rtp/src/srtp/const.js.map +1 -1
  162. package/lib/rtp/src/srtp/context/context.d.ts +10 -10
  163. package/lib/rtp/src/srtp/context/context.js +10 -4
  164. package/lib/rtp/src/srtp/context/context.js.map +1 -1
  165. package/lib/rtp/src/srtp/context/srtcp.d.ts +3 -3
  166. package/lib/rtp/src/srtp/context/srtcp.js.map +1 -1
  167. package/lib/rtp/src/srtp/context/srtp.d.ts +3 -3
  168. package/lib/rtp/src/srtp/context/srtp.js.map +1 -1
  169. package/lib/rtp/src/srtp/srtcp.d.ts +2 -2
  170. package/lib/rtp/src/srtp/srtp.d.ts +2 -2
  171. package/lib/sctp/src/chunk.d.ts +12 -12
  172. package/lib/sctp/src/chunk.js +87 -66
  173. package/lib/sctp/src/chunk.js.map +1 -1
  174. package/lib/sctp/src/param.d.ts +3 -3
  175. package/lib/sctp/src/param.js +4 -5
  176. package/lib/sctp/src/param.js.map +1 -1
  177. package/lib/sctp/src/sctp.d.ts +3 -1
  178. package/lib/sctp/src/sctp.js +58 -15
  179. package/lib/sctp/src/sctp.js.map +1 -1
  180. package/lib/webrtc/src/dataChannel.d.ts +15 -4
  181. package/lib/webrtc/src/dataChannel.js +42 -7
  182. package/lib/webrtc/src/dataChannel.js.map +1 -1
  183. package/lib/webrtc/src/index.d.ts +1 -0
  184. package/lib/webrtc/src/index.js +1 -0
  185. package/lib/webrtc/src/index.js.map +1 -1
  186. package/lib/webrtc/src/media/index.d.ts +2 -0
  187. package/lib/webrtc/src/media/index.js +2 -0
  188. package/lib/webrtc/src/media/index.js.map +1 -1
  189. package/lib/webrtc/src/media/parameters.d.ts +2 -2
  190. package/lib/webrtc/src/media/parameters.js.map +1 -1
  191. package/lib/webrtc/src/media/receiver/nack.js +3 -7
  192. package/lib/webrtc/src/media/receiver/nack.js.map +1 -1
  193. package/lib/webrtc/src/media/receiver/receiverTwcc.d.ts +2 -2
  194. package/lib/webrtc/src/media/receiver/receiverTwcc.js +1 -1
  195. package/lib/webrtc/src/media/receiver/receiverTwcc.js.map +1 -1
  196. package/lib/webrtc/src/media/router.js +2 -1
  197. package/lib/webrtc/src/media/router.js.map +1 -1
  198. package/lib/webrtc/src/media/rtpReceiver.d.ts +3 -3
  199. package/lib/webrtc/src/media/rtpReceiver.js +53 -4
  200. package/lib/webrtc/src/media/rtpReceiver.js.map +1 -1
  201. package/lib/webrtc/src/media/rtpSender.d.ts +6 -0
  202. package/lib/webrtc/src/media/rtpSender.js +64 -26
  203. package/lib/webrtc/src/media/rtpSender.js.map +1 -1
  204. package/lib/webrtc/src/media/rtpTransceiver.d.ts +12 -9
  205. package/lib/webrtc/src/media/rtpTransceiver.js +30 -26
  206. package/lib/webrtc/src/media/rtpTransceiver.js.map +1 -1
  207. package/lib/webrtc/src/media/stats.d.ts +279 -0
  208. package/lib/webrtc/src/media/stats.js +35 -1
  209. package/lib/webrtc/src/media/stats.js.map +1 -1
  210. package/lib/webrtc/src/media/track.js +3 -3
  211. package/lib/webrtc/src/media/track.js.map +1 -1
  212. package/lib/webrtc/src/nonstandard/recorder/writer/webm.js.map +1 -1
  213. package/lib/webrtc/src/nonstandard/userMedia.js +2 -2
  214. package/lib/webrtc/src/nonstandard/userMedia.js.map +1 -1
  215. package/lib/webrtc/src/peerConnection.d.ts +35 -64
  216. package/lib/webrtc/src/peerConnection.js +337 -1034
  217. package/lib/webrtc/src/peerConnection.js.map +1 -1
  218. package/lib/webrtc/src/sctpManager.d.ts +27 -0
  219. package/lib/webrtc/src/sctpManager.js +147 -0
  220. package/lib/webrtc/src/sctpManager.js.map +1 -0
  221. package/lib/webrtc/src/sdp.d.ts +3 -2
  222. package/lib/webrtc/src/sdp.js +17 -7
  223. package/lib/webrtc/src/sdp.js.map +1 -1
  224. package/lib/webrtc/src/sdpManager.d.ts +78 -0
  225. package/lib/webrtc/src/sdpManager.js +391 -0
  226. package/lib/webrtc/src/sdpManager.js.map +1 -0
  227. package/lib/webrtc/src/secureTransportManager.d.ts +56 -0
  228. package/lib/webrtc/src/secureTransportManager.js +349 -0
  229. package/lib/webrtc/src/secureTransportManager.js.map +1 -0
  230. package/lib/webrtc/src/transceiverManager.d.ts +40 -0
  231. package/lib/webrtc/src/transceiverManager.js +355 -0
  232. package/lib/webrtc/src/transceiverManager.js.map +1 -0
  233. package/lib/webrtc/src/transport/dtls.d.ts +18 -6
  234. package/lib/webrtc/src/transport/dtls.js +128 -13
  235. package/lib/webrtc/src/transport/dtls.js.map +1 -1
  236. package/lib/webrtc/src/transport/ice.d.ts +24 -0
  237. package/lib/webrtc/src/transport/ice.js +88 -2
  238. package/lib/webrtc/src/transport/ice.js.map +1 -1
  239. package/lib/webrtc/src/transport/sctp.js +13 -26
  240. package/lib/webrtc/src/transport/sctp.js.map +1 -1
  241. package/lib/webrtc/src/utils.d.ts +9 -4
  242. package/lib/webrtc/src/utils.js +34 -13
  243. package/lib/webrtc/src/utils.js.map +1 -1
  244. package/package.json +12 -26
@@ -1,135 +1,87 @@
1
1
  "use strict";
2
- var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
- if (k2 === undefined) k2 = k;
4
- var desc = Object.getOwnPropertyDescriptor(m, k);
5
- if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
- desc = { enumerable: true, get: function() { return m[k]; } };
7
- }
8
- Object.defineProperty(o, k2, desc);
9
- }) : (function(o, m, k, k2) {
10
- if (k2 === undefined) k2 = k;
11
- o[k2] = m[k];
12
- }));
13
- var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
- Object.defineProperty(o, "default", { enumerable: true, value: v });
15
- }) : function(o, v) {
16
- o["default"] = v;
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
- };
25
- var __importDefault = (this && this.__importDefault) || function (mod) {
26
- return (mod && mod.__esModule) ? mod : { "default": mod };
27
- };
28
2
  Object.defineProperty(exports, "__esModule", { value: true });
29
3
  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
- const cloneDeep_js_1 = __importDefault(require("lodash/cloneDeep.js"));
35
- const isEqual_js_1 = __importDefault(require("lodash/isEqual.js"));
36
- const uuid = __importStar(require("uuid"));
37
- const const_1 = require("./const");
38
- const dataChannel_1 = require("./dataChannel");
4
+ const crypto_1 = require("crypto");
39
5
  const helper_1 = require("./helper");
40
6
  const common_1 = require("./imports/common");
41
7
  const media_1 = require("./media");
8
+ const stats_1 = require("./media/stats");
9
+ const sctpManager_1 = require("./sctpManager");
42
10
  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");
11
+ const sdpManager_1 = require("./sdpManager");
12
+ const secureTransportManager_1 = require("./secureTransportManager");
46
13
  const utils_1 = require("./utils");
47
14
  const log = (0, common_1.debug)("werift:packages/webrtc/src/peerConnection.ts");
48
15
  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
16
  constructor(config = {}) {
77
17
  super();
78
18
  Object.defineProperty(this, "cname", {
79
19
  enumerable: true,
80
20
  configurable: true,
81
21
  writable: true,
82
- value: uuid.v4()
22
+ value: (0, crypto_1.randomUUID)().toString()
83
23
  });
84
- Object.defineProperty(this, "sctpTransport", {
24
+ Object.defineProperty(this, "config", {
85
25
  enumerable: true,
86
26
  configurable: true,
87
27
  writable: true,
88
- value: void 0
28
+ value: generateDefaultPeerConfig()
89
29
  });
90
- Object.defineProperty(this, "config", {
30
+ Object.defineProperty(this, "signalingState", {
91
31
  enumerable: true,
92
32
  configurable: true,
93
33
  writable: true,
94
- value: (0, cloneDeep_js_1.default)(exports.defaultPeerConfig)
34
+ value: "stable"
95
35
  });
96
- Object.defineProperty(this, "connectionState", {
36
+ Object.defineProperty(this, "negotiationneeded", {
97
37
  enumerable: true,
98
38
  configurable: true,
99
39
  writable: true,
100
- value: "new"
40
+ value: false
101
41
  });
102
- Object.defineProperty(this, "iceConnectionState", {
42
+ Object.defineProperty(this, "needRestart", {
103
43
  enumerable: true,
104
44
  configurable: true,
105
45
  writable: true,
106
- value: "new"
46
+ value: false
107
47
  });
108
- Object.defineProperty(this, "iceGatheringState", {
48
+ Object.defineProperty(this, "router", {
109
49
  enumerable: true,
110
50
  configurable: true,
111
51
  writable: true,
112
- value: "new"
52
+ value: new media_1.RtpRouter()
113
53
  });
114
- Object.defineProperty(this, "signalingState", {
54
+ Object.defineProperty(this, "sdpManager", {
115
55
  enumerable: true,
116
56
  configurable: true,
117
57
  writable: true,
118
- value: "stable"
58
+ value: void 0
119
59
  });
120
- Object.defineProperty(this, "negotiationneeded", {
60
+ Object.defineProperty(this, "transceiverManager", {
121
61
  enumerable: true,
122
62
  configurable: true,
123
63
  writable: true,
124
- value: false
64
+ value: void 0
125
65
  });
126
- Object.defineProperty(this, "transceivers", {
66
+ Object.defineProperty(this, "sctpManager", {
127
67
  enumerable: true,
128
68
  configurable: true,
129
69
  writable: true,
130
- value: []
70
+ value: void 0
131
71
  });
132
- Object.defineProperty(this, "needRestart", {
72
+ Object.defineProperty(this, "secureManager", {
73
+ enumerable: true,
74
+ configurable: true,
75
+ writable: true,
76
+ value: void 0
77
+ });
78
+ Object.defineProperty(this, "isClosed", {
79
+ enumerable: true,
80
+ configurable: true,
81
+ writable: true,
82
+ value: false
83
+ });
84
+ Object.defineProperty(this, "shouldNegotiationneeded", {
133
85
  enumerable: true,
134
86
  configurable: true,
135
87
  writable: true,
@@ -207,96 +159,48 @@ class RTCPeerConnection extends helper_1.EventTarget {
207
159
  writable: true,
208
160
  value: void 0
209
161
  });
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", {
162
+ Object.defineProperty(this, "onicecandidateerror", {
223
163
  enumerable: true,
224
164
  configurable: true,
225
165
  writable: true,
226
166
  value: void 0
227
167
  });
228
- Object.defineProperty(this, "onconnectionstatechange", {
229
- enumerable: true,
230
- configurable: true,
231
- writable: true,
232
- value: void 0
233
- });
234
- Object.defineProperty(this, "oniceconnectionstatechange", {
168
+ Object.defineProperty(this, "onicegatheringstatechange", {
235
169
  enumerable: true,
236
170
  configurable: true,
237
171
  writable: true,
238
172
  value: void 0
239
173
  });
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", {
174
+ Object.defineProperty(this, "onnegotiationneeded", {
253
175
  enumerable: true,
254
176
  configurable: true,
255
177
  writable: true,
256
178
  value: void 0
257
179
  });
258
- Object.defineProperty(this, "seenMid", {
259
- enumerable: true,
260
- configurable: true,
261
- writable: true,
262
- value: new Set()
263
- });
264
- Object.defineProperty(this, "currentLocalDescription", {
180
+ Object.defineProperty(this, "onsignalingstatechange", {
265
181
  enumerable: true,
266
182
  configurable: true,
267
183
  writable: true,
268
184
  value: void 0
269
185
  });
270
- Object.defineProperty(this, "currentRemoteDescription", {
186
+ Object.defineProperty(this, "ontrack", {
271
187
  enumerable: true,
272
188
  configurable: true,
273
189
  writable: true,
274
190
  value: void 0
275
191
  });
276
- Object.defineProperty(this, "pendingLocalDescription", {
192
+ Object.defineProperty(this, "onconnectionstatechange", {
277
193
  enumerable: true,
278
194
  configurable: true,
279
195
  writable: true,
280
196
  value: void 0
281
197
  });
282
- Object.defineProperty(this, "pendingRemoteDescription", {
198
+ Object.defineProperty(this, "oniceconnectionstatechange", {
283
199
  enumerable: true,
284
200
  configurable: true,
285
201
  writable: true,
286
202
  value: void 0
287
203
  });
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
204
  Object.defineProperty(this, "needNegotiation", {
301
205
  enumerable: true,
302
206
  configurable: true,
@@ -316,16 +220,113 @@ class RTCPeerConnection extends helper_1.EventTarget {
316
220
  }
317
221
  });
318
222
  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;
223
+ this.sdpManager = new sdpManager_1.SDPManager({
224
+ cname: this.cname,
225
+ bundlePolicy: this.config.bundlePolicy,
226
+ });
227
+ this.transceiverManager = new media_1.TransceiverManager(this.cname, this.config, this.router);
228
+ this.transceiverManager.onTransceiverAdded.pipe(this.onTransceiverAdded);
229
+ this.transceiverManager.onRemoteTransceiverAdded.pipe(this.onRemoteTransceiverAdded);
230
+ this.transceiverManager.onTrack.subscribe(({ track, stream, transceiver }) => {
231
+ const event = {
232
+ track,
233
+ streams: [stream],
234
+ transceiver,
235
+ receiver: transceiver.receiver,
236
+ };
237
+ this.onTrack.execute(track);
238
+ this.emit("track", event);
239
+ if (this.ontrack) {
240
+ this.ontrack(event);
241
+ }
242
+ });
243
+ this.transceiverManager.onNegotiationNeeded.subscribe(() => this.needNegotiation());
244
+ this.sctpManager = new sctpManager_1.SctpTransportManager();
245
+ this.sctpManager.onDataChannel.subscribe((channel) => {
246
+ this.onDataChannel.execute(channel);
247
+ const event = { channel };
248
+ this.ondatachannel?.(event);
249
+ this.emit("datachannel", event);
250
+ });
251
+ this.secureManager = new secureTransportManager_1.SecureTransportManager({
252
+ config: this.config,
253
+ sctpManager: this.sctpManager,
254
+ transceiverManager: this.transceiverManager,
255
+ });
256
+ this.secureManager.iceGatheringStateChange.pipe(this.iceGatheringStateChange);
257
+ this.secureManager.iceConnectionStateChange.subscribe((state) => {
258
+ if (state === "closed") {
259
+ this.close();
327
260
  }
261
+ this.iceConnectionStateChange.execute(state);
328
262
  });
263
+ this.secureManager.connectionStateChange.subscribe((state) => {
264
+ this.connectionStateChange.execute(state);
265
+ this.onconnectionstatechange?.();
266
+ this.emit("connectionstatechange");
267
+ });
268
+ this.secureManager.onIceCandidate.subscribe((candidate) => {
269
+ const iceCandidate = candidate ? candidate.toJSON() : undefined;
270
+ this.onIceCandidate.execute(iceCandidate);
271
+ this.onicecandidate?.({ candidate: iceCandidate });
272
+ this.emit("icecandidate", { candidate: iceCandidate });
273
+ });
274
+ }
275
+ get connectionState() {
276
+ return this.secureManager.connectionState;
277
+ }
278
+ get iceConnectionState() {
279
+ return this.secureManager.iceConnectionState;
280
+ }
281
+ get iceGathererState() {
282
+ return this.secureManager.iceGatheringState;
283
+ }
284
+ get iceGatheringState() {
285
+ return this.secureManager.iceGatheringState;
286
+ }
287
+ get dtlsTransports() {
288
+ return this.secureManager.dtlsTransports;
289
+ }
290
+ get sctpTransport() {
291
+ return this.sctpManager.sctpTransport;
292
+ }
293
+ get sctpRemotePort() {
294
+ return this.sctpManager.sctpRemotePort;
295
+ }
296
+ get iceTransports() {
297
+ return this.secureManager.iceTransports;
298
+ }
299
+ get extIdUriMap() {
300
+ return this.router.extIdUriMap;
301
+ }
302
+ get iceGeneration() {
303
+ return this.iceTransports[0].connection.generation;
304
+ }
305
+ get localDescription() {
306
+ return this.sdpManager.localDescription;
307
+ }
308
+ get remoteDescription() {
309
+ return this.sdpManager.remoteDescription;
310
+ }
311
+ get remoteIsBundled() {
312
+ return this.sdpManager.remoteIsBundled;
313
+ }
314
+ /**@private */
315
+ get _localDescription() {
316
+ return this.sdpManager._localDescription;
317
+ }
318
+ /**@private */
319
+ get _remoteDescription() {
320
+ return this.sdpManager._remoteDescription;
321
+ }
322
+ getTransceivers() {
323
+ return this.transceiverManager.getTransceivers();
324
+ }
325
+ getSenders() {
326
+ return this.transceiverManager.getSenders();
327
+ }
328
+ getReceivers() {
329
+ return this.transceiverManager.getReceivers();
329
330
  }
330
331
  setConfiguration(config) {
331
332
  (0, utils_1.deepMerge)(this.config, config);
@@ -367,38 +368,6 @@ class RTCPeerConnection extends helper_1.EventTarget {
367
368
  ].forEach((v, i) => {
368
369
  v.id = 1 + i;
369
370
  });
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
371
  }
403
372
  getConfiguration() {
404
373
  return this.config;
@@ -406,207 +375,64 @@ class RTCPeerConnection extends helper_1.EventTarget {
406
375
  async createOffer({ iceRestart } = {}) {
407
376
  if (iceRestart || this.needRestart) {
408
377
  this.needRestart = false;
409
- for (const t of this.iceTransports) {
410
- t.restart();
411
- }
378
+ this.secureManager.restartIce();
412
379
  }
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) => {
380
+ await this.secureManager.ensureCerts();
381
+ for (const transceiver of this.transceiverManager.getTransceivers()) {
446
382
  if (transceiver.codecs.length === 0) {
447
- this.assignTransceiverCodecs(transceiver);
383
+ this.transceiverManager.assignTransceiverCodecs(transceiver);
448
384
  }
449
385
  if (transceiver.headerExtensions.length === 0) {
450
386
  transceiver.headerExtensions =
451
387
  this.config.headerExtensions[transceiver.kind] ?? [];
452
388
  }
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
- }
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
389
  }
519
- return description;
390
+ const description = this.sdpManager.buildOfferSdp(this.transceiverManager.getTransceivers(), this.sctpTransport);
391
+ return description.toJSON();
392
+ }
393
+ createSctpTransport() {
394
+ const sctp = this.sctpManager.createSctpTransport();
395
+ const dtlsTransport = this.findOrCreateTransport();
396
+ sctp.setDtlsTransport(dtlsTransport);
397
+ return sctp;
520
398
  }
521
399
  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
400
  if (!this.sctpTransport) {
532
- this.sctpTransport = this.createSctpTransport();
401
+ this.createSctpTransport();
533
402
  this.needNegotiation();
534
403
  }
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);
404
+ const channel = this.sctpManager.createDataChannel(label, options);
405
+ if (!channel.sctp.dtlsTransport) {
406
+ const dtlsTransport = this.findOrCreateTransport();
407
+ channel.sctp.setDtlsTransport(dtlsTransport);
408
+ }
545
409
  return channel;
546
410
  }
547
411
  removeTrack(sender) {
548
- if (this.isClosed)
412
+ if (this.isClosed) {
549
413
  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
414
  }
415
+ this.transceiverManager.removeTrack(sender);
573
416
  this.needNegotiation();
574
417
  }
575
- createTransport(srtpProfiles = []) {
418
+ findOrCreateTransport() {
576
419
  const [existing] = this.iceTransports;
577
420
  // Gather ICE candidates for only one track. If the remote endpoint is not bundle-aware, negotiate only one media track.
578
421
  // https://w3c.github.io/webrtc-pc/#rtcbundlepolicy-enum
579
- if (this.config.bundlePolicy === "max-bundle") {
422
+ if (this.sdpManager.bundlePolicy === "max-bundle" ||
423
+ (this.sdpManager.bundlePolicy !== "disable" && this.remoteIsBundled)) {
580
424
  if (existing) {
581
425
  return this.dtlsTransports[0];
582
426
  }
583
427
  }
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,
428
+ const dtlsTransport = this.secureManager.createTransport();
429
+ dtlsTransport.onRtp.subscribe((rtp) => {
430
+ this.router.routeRtp(rtp);
597
431
  });
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();
432
+ dtlsTransport.onRtcp.subscribe((rtcp) => {
433
+ this.router.routeRtcp(rtcp);
609
434
  });
435
+ const iceTransport = dtlsTransport.iceTransport;
610
436
  iceTransport.onNegotiationNeeded.subscribe(() => {
611
437
  this.needNegotiation();
612
438
  });
@@ -616,7 +442,7 @@ class RTCPeerConnection extends helper_1.EventTarget {
616
442
  return;
617
443
  }
618
444
  if (!candidate) {
619
- this.setLocal(this._localDescription);
445
+ this.sdpManager.setLocal(this._localDescription, this.transceiverManager.getTransceivers(), this.sctpTransport);
620
446
  this.onIceCandidate.execute(undefined);
621
447
  if (this.onicecandidate) {
622
448
  this.onicecandidate({ candidate: undefined });
@@ -624,58 +450,44 @@ class RTCPeerConnection extends helper_1.EventTarget {
624
450
  this.emit("icecandidate", { candidate: undefined });
625
451
  return;
626
452
  }
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() });
453
+ if (!this._localDescription) {
454
+ log("localDescription not found when ice candidate was gathered");
455
+ return;
649
456
  }
650
- this.emit("icecandidate", { candidate });
457
+ this.secureManager.handleNewIceCandidate({
458
+ candidate,
459
+ bundlePolicy: this.sdpManager.bundlePolicy,
460
+ remoteIsBundled: !!this.sdpManager.remoteIsBundled,
461
+ media: this._localDescription.media[0],
462
+ transceiver: this.transceiverManager
463
+ .getTransceivers()
464
+ .find((t) => t.dtlsTransport.iceTransport.id === iceTransport.id),
465
+ sctpTransport: this.sctpTransport?.dtlsTransport.iceTransport.id === iceTransport.id
466
+ ? this.sctpTransport
467
+ : undefined,
468
+ });
651
469
  });
652
- const dtlsTransport = new dtls_1.RTCDtlsTransport(this.config, iceTransport, this.router, this.certificate, srtpProfiles);
653
470
  return dtlsTransport;
654
471
  }
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
472
  async setLocalDescription(sessionDescription) {
473
+ // https://developer.mozilla.org/en-US/docs/Web/API/RTCPeerConnection/setLocalDescription#type
474
+ const implicitOfferState = [
475
+ "stable",
476
+ "have-local-offer",
477
+ "have-remote-pranswer",
478
+ ];
479
+ sessionDescription =
480
+ sessionDescription ??
481
+ (implicitOfferState.includes(this.signalingState)
482
+ ? await this.createOffer()
483
+ : await this.createAnswer());
675
484
  // # parse and validate description
676
- const description = sdp_1.SessionDescription.parse(sessionDescription.sdp);
677
- description.type = sessionDescription.type;
678
- this.validateDescription(description, true);
485
+ const description = this.sdpManager.parseSdp({
486
+ sdp: sessionDescription.sdp,
487
+ isLocal: true,
488
+ signalingState: this.signalingState,
489
+ type: sessionDescription.type,
490
+ });
679
491
  // # update signaling state
680
492
  if (description.type === "offer") {
681
493
  this.setSignalingState("have-local-offer");
@@ -686,9 +498,9 @@ class RTCPeerConnection extends helper_1.EventTarget {
686
498
  // # assign MID
687
499
  for (const [i, media] of (0, helper_1.enumerate)(description.media)) {
688
500
  const mid = media.rtp.muxId;
689
- this.seenMid.add(mid);
501
+ this.sdpManager.registerMid(mid);
690
502
  if (["audio", "video"].includes(media.kind)) {
691
- const transceiver = this.getTransceiverByMLineIndex(i);
503
+ const transceiver = this.transceiverManager.getTransceiverByMLineIndex(i);
692
504
  if (transceiver) {
693
505
  transceiver.mid = mid;
694
506
  }
@@ -698,38 +510,21 @@ class RTCPeerConnection extends helper_1.EventTarget {
698
510
  }
699
511
  }
700
512
  // 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
- }
513
+ const role = description.media.find((media) => media.dtlsParams)?.dtlsParams
514
+ ?.role;
515
+ this.secureManager.setLocalRole({
516
+ type: description.type,
517
+ role,
518
+ });
724
519
  // # configure direction
725
520
  if (["answer", "pranswer"].includes(description.type)) {
726
- for (const t of this.transceivers) {
521
+ for (const t of this.transceiverManager.getTransceivers()) {
727
522
  const direction = (0, utils_1.andDirection)(t.direction, t.offerDirection);
728
523
  t.setCurrentDirection(direction);
729
524
  }
730
525
  }
731
526
  // for trickle ice
732
- this.setLocal(description);
527
+ this.sdpManager.setLocal(description, this.transceiverManager.getTransceivers(), this.sctpTransport);
733
528
  await this.gatherCandidates().catch((e) => {
734
529
  log("gatherCandidates failed", e);
735
530
  });
@@ -737,84 +532,21 @@ class RTCPeerConnection extends helper_1.EventTarget {
737
532
  if (description.type === "answer") {
738
533
  this.connect().catch((err) => {
739
534
  log("connect failed", err);
740
- this.setConnectionState("failed");
535
+ this.secureManager.setConnectionState("failed");
741
536
  });
742
537
  }
743
- this.setLocal(description);
538
+ this.sdpManager.setLocal(description, this.transceiverManager.getTransceivers(), this.sctpTransport);
744
539
  if (this.shouldNegotiationneeded) {
745
540
  this.needNegotiation();
746
541
  }
747
542
  return description;
748
543
  }
749
544
  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;
545
+ await this.secureManager.gatherCandidates(!!this.sdpManager.remoteIsBundled);
796
546
  }
797
547
  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
- }
548
+ const sdp = this.sdpManager.buildOfferSdp(this.transceiverManager.getTransceivers(), this.sctpTransport);
549
+ await this.secureManager.addIceCandidate(sdp, candidateMessage);
818
550
  }
819
551
  async connect() {
820
552
  log("start connect");
@@ -823,12 +555,16 @@ class RTCPeerConnection extends helper_1.EventTarget {
823
555
  if (iceTransport.state === "connected") {
824
556
  return;
825
557
  }
826
- this.setConnectionState("connecting");
558
+ const checkDtlsConnected = () => dtlsTransport.state === "connected";
559
+ if (checkDtlsConnected()) {
560
+ return;
561
+ }
562
+ this.secureManager.setConnectionState("connecting");
827
563
  await iceTransport.start().catch((err) => {
828
564
  log("iceTransport.start failed", err);
829
565
  throw err;
830
566
  });
831
- if (dtlsTransport.state === "connected") {
567
+ if (checkDtlsConnected()) {
832
568
  return;
833
569
  }
834
570
  await dtlsTransport.start().catch((err) => {
@@ -836,85 +572,27 @@ class RTCPeerConnection extends helper_1.EventTarget {
836
572
  throw err;
837
573
  });
838
574
  if (this.sctpTransport &&
839
- this.sctpRemotePort &&
840
575
  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");
576
+ await this.sctpManager.connectSctp();
844
577
  }
845
578
  }));
846
579
  if (res.find((r) => r.status === "rejected")) {
847
- this.setConnectionState("failed");
580
+ this.secureManager.setConnectionState("failed");
848
581
  }
849
582
  else {
850
- this.setConnectionState("connected");
583
+ this.secureManager.setConnectionState("connected");
851
584
  }
852
585
  }
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;
892
- }
893
- const bundle = remoteSdp.group.find((g) => g.semantic === "BUNDLE" && this.config.bundlePolicy !== "disable");
894
- return bundle;
895
- }
896
586
  restartIce() {
897
587
  this.needRestart = true;
898
588
  this.needNegotiation();
899
589
  }
900
590
  async setRemoteDescription(sessionDescription) {
901
- if (!sessionDescription.sdp ||
902
- !sessionDescription.type ||
903
- sessionDescription.type === "rollback" ||
904
- sessionDescription.type === "pranswer") {
905
- throw new Error("invalid sessionDescription");
591
+ if (sessionDescription instanceof sdp_1.SessionDescription) {
592
+ sessionDescription = sessionDescription.toSdp();
906
593
  }
907
594
  // # 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
- }
595
+ const remoteSdp = this.sdpManager.setRemoteDescription(sessionDescription, this.signalingState);
918
596
  let bundleTransport;
919
597
  // # apply description
920
598
  const matchTransceiverWithMedia = (transceiver, media) => transceiver.kind === media.kind &&
@@ -922,10 +600,12 @@ class RTCPeerConnection extends helper_1.EventTarget {
922
600
  let transports = remoteSdp.media.map((remoteMedia, i) => {
923
601
  let dtlsTransport;
924
602
  if (["audio", "video"].includes(remoteMedia.kind)) {
925
- let transceiver = this.transceivers.find((t) => matchTransceiverWithMedia(t, remoteMedia));
603
+ let transceiver = this.transceiverManager
604
+ .getTransceivers()
605
+ .find((t) => matchTransceiverWithMedia(t, remoteMedia));
926
606
  if (!transceiver) {
927
607
  // create remote transceiver
928
- transceiver = this._addTransceiver(remoteMedia.kind, {
608
+ transceiver = this.addTransceiver(remoteMedia.kind, {
929
609
  direction: "recvonly",
930
610
  });
931
611
  transceiver.mid = remoteMedia.rtp.muxId;
@@ -940,7 +620,7 @@ class RTCPeerConnection extends helper_1.EventTarget {
940
620
  return;
941
621
  }
942
622
  }
943
- if (this.remoteIsBundled) {
623
+ if (this.sdpManager.remoteIsBundled) {
944
624
  if (!bundleTransport) {
945
625
  bundleTransport = transceiver.dtlsTransport;
946
626
  }
@@ -949,30 +629,31 @@ class RTCPeerConnection extends helper_1.EventTarget {
949
629
  }
950
630
  }
951
631
  dtlsTransport = transceiver.dtlsTransport;
952
- this.setRemoteRTP(transceiver, remoteMedia, remoteSdp.type, i);
632
+ this.transceiverManager.setRemoteRTP(transceiver, remoteMedia, remoteSdp.type, i);
953
633
  }
954
634
  else if (remoteMedia.kind === "application") {
955
- if (!this.sctpTransport) {
956
- this.sctpTransport = this.createSctpTransport();
957
- this.sctpTransport.mid = remoteMedia.rtp.muxId;
635
+ let sctpTransport = this.sctpTransport;
636
+ if (!sctpTransport) {
637
+ sctpTransport = this.createSctpTransport();
638
+ sctpTransport.mid = remoteMedia.rtp.muxId;
958
639
  }
959
- if (this.remoteIsBundled) {
640
+ if (this.sdpManager.remoteIsBundled) {
960
641
  if (!bundleTransport) {
961
- bundleTransport = this.sctpTransport.dtlsTransport;
642
+ bundleTransport = sctpTransport.dtlsTransport;
962
643
  }
963
644
  else {
964
- this.sctpTransport.setDtlsTransport(bundleTransport);
645
+ sctpTransport.setDtlsTransport(bundleTransport);
965
646
  }
966
647
  }
967
- dtlsTransport = this.sctpTransport.dtlsTransport;
968
- this.setRemoteSCTP(remoteMedia, this.sctpTransport, i);
648
+ dtlsTransport = sctpTransport.dtlsTransport;
649
+ this.sctpManager.setRemoteSCTP(remoteMedia, i);
969
650
  }
970
651
  else {
971
652
  throw new Error("invalid media kind");
972
653
  }
973
654
  const iceTransport = dtlsTransport.iceTransport;
974
655
  if (remoteMedia.iceParams) {
975
- const renomination = !!remoteSdp.media.find((m) => m.direction === "inactive");
656
+ const renomination = !!this.sdpManager.inactiveRemoteMedia;
976
657
  iceTransport.setRemoteParams(remoteMedia.iceParams, renomination);
977
658
  // One agent full, one lite: The full agent MUST take the controlling role, and the lite agent MUST take the controlled role
978
659
  // RFC 8445 S6.1.1
@@ -997,7 +678,9 @@ class RTCPeerConnection extends helper_1.EventTarget {
997
678
  });
998
679
  // filter out inactive transports
999
680
  transports = transports.filter((iceTransport) => !!iceTransport);
1000
- const removedTransceivers = this.transceivers.filter((t) => remoteSdp.media.find((m) => matchTransceiverWithMedia(t, m)) ==
681
+ const removedTransceivers = this.transceiverManager
682
+ .getTransceivers()
683
+ .filter((t) => remoteSdp.media.find((m) => matchTransceiverWithMedia(t, m)) ==
1001
684
  undefined);
1002
685
  if (sessionDescription.type === "answer") {
1003
686
  for (const transceiver of removedTransceivers) {
@@ -1018,7 +701,7 @@ class RTCPeerConnection extends helper_1.EventTarget {
1018
701
  log("caller start connect");
1019
702
  this.connect().catch((err) => {
1020
703
  log("connect failed", err);
1021
- this.setConnectionState("failed");
704
+ this.secureManager.setConnectionState("failed");
1022
705
  });
1023
706
  }
1024
707
  this.negotiationneeded = false;
@@ -1026,177 +709,12 @@ class RTCPeerConnection extends helper_1.EventTarget {
1026
709
  this.needNegotiation();
1027
710
  }
1028
711
  }
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
712
  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();
713
+ const dtlsTransport = this.findOrCreateTransport();
714
+ const transceiver = this.transceiverManager.addTransceiver(trackOrKind, dtlsTransport, options);
715
+ this.secureManager.updateIceConnectionState();
1189
716
  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);
717
+ return transceiver;
1200
718
  }
1201
719
  // todo fix
1202
720
  addTrack(track,
@@ -1205,207 +723,29 @@ class RTCPeerConnection extends helper_1.EventTarget {
1205
723
  if (this.isClosed) {
1206
724
  throw new Error("is closed");
1207
725
  }
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;
726
+ const transceiver = this.transceiverManager.addTrack(track, ms);
727
+ if (!transceiver.dtlsTransport) {
728
+ const dtlsTransport = this.findOrCreateTransport();
729
+ transceiver.setDtlsTransport(dtlsTransport);
1252
730
  }
731
+ this.needNegotiation();
732
+ return transceiver.sender;
1253
733
  }
1254
734
  async createAnswer() {
1255
- await this.ensureCerts();
1256
- const description = this.buildAnswer();
1257
- return description.toJSON();
1258
- }
1259
- buildAnswer() {
1260
735
  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);
1301
- });
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();
736
+ await this.secureManager.ensureCerts();
737
+ const description = this.sdpManager.buildAnswerSdp({
738
+ transceivers: this.transceiverManager.getTransceivers(),
739
+ sctpTransport: this.sctpTransport,
740
+ signalingState: this.signalingState,
1322
741
  });
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");
742
+ return description.toJSON();
1332
743
  }
1333
744
  assertNotClosed() {
1334
745
  if (this.isClosed) {
1335
746
  throw new Error("RTCPeerConnection is closed");
1336
747
  }
1337
748
  }
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
749
  setSignalingState(state) {
1410
750
  log("signalingStateChange", state);
1411
751
  this.signalingState = state;
@@ -1414,16 +754,43 @@ class RTCPeerConnection extends helper_1.EventTarget {
1414
754
  this.onsignalingstatechange({});
1415
755
  }
1416
756
  }
1417
- setConnectionState(state) {
1418
- log("connectionStateChange", state);
1419
- this.connectionState = state;
1420
- this.connectionStateChange.execute(state);
1421
- if (this.onconnectionstatechange) {
1422
- this.onconnectionstatechange();
757
+ createPeerConnectionStats() {
758
+ const timestamp = (0, stats_1.getStatsTimestamp)();
759
+ return {
760
+ type: "peer-connection",
761
+ id: (0, stats_1.generateStatsId)("peer-connection"),
762
+ timestamp,
763
+ dataChannelsOpened: this.sctpManager.dataChannelsOpened,
764
+ dataChannelsClosed: this.sctpManager.dataChannelsClosed,
765
+ };
766
+ }
767
+ async getStats(selector) {
768
+ 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();
776
+ stats.push(...transportStats);
777
+ // Get data channel stats - always included regardless of selector
778
+ if (this.sctpTransport) {
779
+ const dataChannelStats = await this.sctpManager.getStats();
780
+ if (dataChannelStats) {
781
+ stats.push(...dataChannelStats);
782
+ }
1423
783
  }
1424
- this.emit("connectionstatechange");
784
+ return new stats_1.RTCStatsReport(stats);
1425
785
  }
1426
- dispose() {
786
+ async close() {
787
+ if (this.isClosed)
788
+ return;
789
+ this.isClosed = true;
790
+ this.setSignalingState("closed");
791
+ this.transceiverManager.close();
792
+ await this.secureManager.close();
793
+ await this.sctpManager.close();
1427
794
  this.onDataChannel.allUnsubscribe();
1428
795
  this.iceGatheringStateChange.allUnsubscribe();
1429
796
  this.iceConnectionStateChange.allUnsubscribe();
@@ -1431,105 +798,41 @@ class RTCPeerConnection extends helper_1.EventTarget {
1431
798
  this.onTransceiverAdded.allUnsubscribe();
1432
799
  this.onRemoteTransceiverAdded.allUnsubscribe();
1433
800
  this.onIceCandidate.allUnsubscribe();
801
+ log("peerConnection closed");
1434
802
  }
1435
803
  }
1436
804
  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
805
  const findCodecByMimeType = (codecs, target) => codecs.find((localCodec) => localCodec.mimeType.toLowerCase() === target.mimeType.toLowerCase())
1506
806
  ? target
1507
807
  : undefined;
1508
808
  exports.findCodecByMimeType = findCodecByMimeType;
1509
- exports.defaultPeerConfig = {
1510
- codecs: {
1511
- audio: [(0, media_1.useOPUS)(), (0, media_1.usePCMU)()],
1512
- video: [(0, media_1.useVP8)()],
1513
- },
1514
- headerExtensions: {
1515
- audio: [],
1516
- video: [],
1517
- },
1518
- iceTransportPolicy: "all",
1519
- iceServers: [{ urls: "stun:stun.l.google.com:19302" }],
1520
- icePortRange: undefined,
1521
- iceInterfaceAddresses: undefined,
1522
- iceAdditionalHostAddresses: undefined,
1523
- iceUseIpv4: true,
1524
- iceUseIpv6: true,
1525
- iceFilterStunResponse: undefined,
1526
- iceFilterCandidatePair: undefined,
1527
- icePasswordPrefix: undefined,
1528
- iceUseLinkLocalAddress: undefined,
1529
- dtls: {},
1530
- bundlePolicy: "max-compat",
1531
- debug: {},
1532
- midSuffix: false,
1533
- forceTurnTCP: false,
1534
- };
809
+ function generateDefaultPeerConfig() {
810
+ return {
811
+ codecs: {
812
+ audio: [(0, media_1.useOPUS)(), (0, media_1.usePCMU)()],
813
+ video: [(0, media_1.useVP8)()],
814
+ },
815
+ headerExtensions: {
816
+ audio: [],
817
+ video: [],
818
+ },
819
+ iceTransportPolicy: "all",
820
+ iceServers: [{ urls: "stun:stun.l.google.com:19302" }],
821
+ icePortRange: undefined,
822
+ iceInterfaceAddresses: undefined,
823
+ iceAdditionalHostAddresses: undefined,
824
+ iceUseIpv4: true,
825
+ iceUseIpv6: true,
826
+ iceFilterStunResponse: undefined,
827
+ iceFilterCandidatePair: undefined,
828
+ icePasswordPrefix: undefined,
829
+ iceUseLinkLocalAddress: undefined,
830
+ dtls: {},
831
+ bundlePolicy: "max-compat",
832
+ debug: {},
833
+ midSuffix: false,
834
+ forceTurnTCP: false,
835
+ };
836
+ }
837
+ exports.defaultPeerConfig = generateDefaultPeerConfig();
1535
838
  //# sourceMappingURL=peerConnection.js.map