Rtcp.js 7.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217
  1. import {logger} from "./Logger.js"
  2. import Workers from "./Workers.js"
  3. import Heartbeat from "./Heartbeat.js"
  4. export default class Rtcp extends EventEmitter {
  5. constructor(e) {
  6. super();
  7. E(this, "connection", null);
  8. E(this, "inputChannel", null);
  9. E(this, "mediaStream");
  10. E(this, "socket");
  11. E(this, "connected", !1);
  12. E(this, "candidates", []);
  13. E(this, "isAnswered", !1);
  14. E(this, "isFlushing", !1);
  15. E(this, "inputReady", !1);
  16. E(this, "workers");
  17. E(this, "actived", !0);
  18. E(this, "heartbeat");
  19. E(this, "onIcecandidate", e=>{
  20. if (e.candidate != null) {
  21. const t = JSON.stringify(e.candidate);
  22. logger.debug(`Got ice candidate: ${t}`),
  23. this.network.socket.send({
  24. id: "ice_candidate",
  25. data: btoa(t)
  26. })
  27. }
  28. }
  29. );
  30. E(this, "onIcecandidateerror", e=>{
  31. logger.error("onicecandidateerror", e.errorCode, e.errorText, e)
  32. }
  33. );
  34. E(this, "onIceStateChange", e=>{
  35. switch (e.target.iceGatheringState) {
  36. case "gathering":
  37. logger.info("ice gathering");
  38. break;
  39. case "complete":
  40. logger.info("Ice gathering completed")
  41. }
  42. }
  43. );
  44. E(this, "onIceConnectionStateChange", ()=>{
  45. if (!!this.connection)
  46. switch (logger.info(`iceConnectionState: ${this.connection.iceConnectionState}`),
  47. this.connection.iceConnectionState) {
  48. case "connected":
  49. {
  50. this.connected = !0;
  51. break
  52. }
  53. case "disconnected":
  54. {
  55. this.connected = !1,
  56. this.emit("rtcDisconnected");
  57. break
  58. }
  59. case "failed":
  60. {
  61. this.emit("rtcDisconnected"),
  62. this.connected = !1;
  63. break
  64. }
  65. }
  66. }
  67. );
  68. E(this, "setRemoteDescription", async(e,t)=>{
  69. var a, s, l;
  70. if (!this.connection)
  71. return;
  72. const r = JSON.parse(atob(e))
  73. , n = new RTCSessionDescription(r);
  74. await this.connection.setRemoteDescription(n);
  75. const o = await this.connection.createAnswer();
  76. if (o.sdp = (a = o.sdp) == null ? void 0 : a.replace(/(a=fmtp:111 .*)/g, "$1;stereo=1;sprop-stereo=1"),
  77. ((l = (s = o.sdp) == null ? void 0 : s.match(/a=mid:1/g)) == null ? void 0 : l.length) == 2) {
  78. const u = o.sdp.lastIndexOf("a=mid:1");
  79. o.sdp = o.sdp.slice(0, u) + "a=mid:2" + o.sdp.slice(u + 7)
  80. }
  81. try {
  82. await this.connection.setLocalDescription(o)
  83. } catch (u) {
  84. logger.error("error", u)
  85. }
  86. this.isAnswered = !0,
  87. this.network.rtcp.flushCandidate(),
  88. this.network.socket.send({
  89. id: "answer",
  90. data: btoa(JSON.stringify(o))
  91. }),
  92. t.srcObject = this.mediaStream
  93. }
  94. );
  95. E(this, "flushCandidate", ()=>{
  96. this.isFlushing || !this.isAnswered || (this.isFlushing = !0,
  97. this.candidates.forEach(e=>{
  98. const t = atob(e)
  99. , r = JSON.parse(t);
  100. if (/172\./.test(r.candidate))
  101. return;
  102. const n = new RTCIceCandidate(r);
  103. this.connection && this.connection.addIceCandidate(n).then(()=>{}
  104. , o=>{
  105. logger.info("add candidate failed", o)
  106. }
  107. )
  108. }
  109. ),
  110. this.isFlushing = !1)
  111. }
  112. );
  113. E(this, "input", e=>{
  114. var t;
  115. !this.actived || !this.inputChannel || this.inputChannel.readyState === "open" && ((t = this.inputChannel) == null || t.send(e))
  116. }
  117. );
  118. this.network = e,
  119. this.workers = new Workers(this,logger),
  120. this.workers.registerLogger(logger),
  121. this.workers.registerFunction("data", t=>{
  122. this.emit("data", t)
  123. }
  124. ),
  125. this.heartbeat = new Heartbeat({
  126. ping: t=>{
  127. e.room.actionsHandler.echo(t)
  128. }
  129. ,
  130. pong(t, r) {
  131. var n;
  132. r && t > 500 && logger.warn(`high hb value ${t}, traceId:` + r),
  133. (n = e.room.stats) == null || n.assign({
  134. hb: t
  135. })
  136. }
  137. })
  138. }
  139. start() {
  140. this.connection = new RTCPeerConnection;
  141. const e = Date.now();
  142. this.connection.ondatachannel = t=>{
  143. logger.info(`ondatachannel: ${t.channel.label}`);
  144. this.inputChannel = t.channel;
  145. this.inputChannel.onopen = ()=>{
  146. var r;
  147. logger.info("The input channel has opened, id:", (r = this.inputChannel) == null ? void 0 : r.id),
  148. this.inputReady = !0,
  149. this.emit("rtcConnected"),
  150. this.network.room.currentNetworkOptions.reconnect || (logger.infoAndReportMeasurement({
  151. metric: "datachannelOpenedAt",
  152. startTime: this.network.room._startTime,
  153. group: "joinRoom"
  154. }),
  155. logger.infoAndReportMeasurement({
  156. metric: "datachannelOpenedCost",
  157. startTime: e,
  158. group: "joinRoom"
  159. }))
  160. console.log('this.inputChannel',this.inputChannel)
  161. }
  162. ,
  163. this.inputChannel.onclose = ()=>{
  164. var r;
  165. return logger.info("The input channel has closed, id:", (r = this.inputChannel) == null ? void 0 : r.id)
  166. },
  167. this.inputChannel.onmessage = r=>{
  168. // console.log('this.workers',this.workers)
  169. console.log('inputChannel',r.data)
  170. this.workers.dataHandle(r.data)
  171. }
  172. }
  173. ,
  174. this.connection.oniceconnectionstatechange = this.onIceConnectionStateChange,
  175. this.connection.onicegatheringstatechange = this.onIceStateChange,
  176. this.connection.onicecandidate = this.onIcecandidate,
  177. this.connection.onicecandidateerror = this.onIcecandidateerror,
  178. this.network.socket.send({
  179. id: "init_webrtc",
  180. data: JSON.stringify({
  181. is_mobile: !0
  182. })
  183. })
  184. }
  185. addCandidate(e) {
  186. e === "" ? this.network.rtcp.flushCandidate() : this.candidates.push(e)
  187. }
  188. disconnect() {
  189. var e, t, r;
  190. this.heartbeat.stop(),
  191. logger.info("ready to close datachannel, id", (e = this.inputChannel) == null ? void 0 : e.id),
  192. (t = this.inputChannel) == null || t.close(),
  193. (r = this.connection) == null || r.close(),
  194. this.connection = null,
  195. this.inputChannel = null
  196. }
  197. sendStringData(e) {
  198. console.log('e',e)
  199. this.input(e)
  200. }
  201. sendData(e) {
  202. let t = "";
  203. try {
  204. t = JSON.stringify(e)
  205. } catch (r) {
  206. logger.error(r);
  207. return
  208. }
  209. this.input(t)
  210. }
  211. }