Rtcp.js 7.8 KB

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