import Workers from "./Workers.js" import Heartbeat from "./Heartbeat.js" import Logger from "./Logger.js" const logger = new Logger('rtcp') export default class Rtcp extends EventEmitter { constructor(e) { super(); E(this, "connection", null); E(this, "inputChannel", null); E(this, "mediaStream"); E(this, "socket"); E(this, "connected", !1); E(this, "candidates", []); E(this, "isAnswered", !1); E(this, "isFlushing", !1); E(this, "inputReady", !1); E(this, "workers"); E(this, "actived", !0); E(this, "heartbeat"); E(this, "onIcecandidate", e=>{ if (e.candidate != null) { const t = JSON.stringify(e.candidate); logger.debug(`Got ice candidate: ${t}`), this.network.socket.send({ id: "ice_candidate", data: btoa(t) }) } } ); E(this, "onIcecandidateerror", e=>{ logger.error("onicecandidateerror", e.errorCode, e.errorText, e) } ); E(this, "onIceStateChange", e=>{ switch (e.target.iceGatheringState) { case "gathering": logger.info("ice gathering"); break; case "complete": logger.info("Ice gathering completed") } } ); E(this, "onIceConnectionStateChange", ()=>{ if (!!this.connection) switch (logger.info(`iceConnectionState: ${this.connection.iceConnectionState}`), this.connection.iceConnectionState) { case "connected": { this.connected = !0; break } case "disconnected": { this.connected = !1, this.emit("rtcDisconnected"); break } case "failed": { this.emit("rtcDisconnected"), this.connected = !1; break } } } ); E(this, "setRemoteDescription", async(e,t)=>{ var a, s, l; if (!this.connection) return; const r = JSON.parse(atob(e)) , n = new RTCSessionDescription(r); await this.connection.setRemoteDescription(n); const o = await this.connection.createAnswer(); if (o.sdp = (a = o.sdp) == null ? void 0 : a.replace(/(a=fmtp:111 .*)/g, "$1;stereo=1;sprop-stereo=1"), ((l = (s = o.sdp) == null ? void 0 : s.match(/a=mid:1/g)) == null ? void 0 : l.length) == 2) { const u = o.sdp.lastIndexOf("a=mid:1"); o.sdp = o.sdp.slice(0, u) + "a=mid:2" + o.sdp.slice(u + 7) } try { await this.connection.setLocalDescription(o) } catch (u) { logger.error("error", u) } this.isAnswered = !0, this.network.rtcp.flushCandidate(), this.network.socket.send({ id: "answer", data: btoa(JSON.stringify(o)) }), t.srcObject = this.mediaStream } ); E(this, "flushCandidate", ()=>{ this.isFlushing || !this.isAnswered || (this.isFlushing = !0, this.candidates.forEach(e=>{ const t = atob(e) , r = JSON.parse(t); if (/172\./.test(r.candidate)) return; const n = new RTCIceCandidate(r); this.connection && this.connection.addIceCandidate(n).then(()=>{} , o=>{ logger.info("add candidate failed", o) } ) } ), this.isFlushing = !1) } ); E(this, "input", e=>{ // var t = this.inputChannel // if(!this.actived || !this.inputChannel || this.inputChannel.readyState === "open"){ // if(t!=null){ // //发送webrtc数据 // console.log('发送webrtc数据:'+e) // t.send(e) // } // } //!this.actived || !this.inputChannel || this.inputChannel.readyState === "open" && (t == null || t.send(e)) } ); this.network = e, this.workers = new Workers(this,logger), this.workers.registerLogger(logger), this.workers.registerFunction("data", t=>{ this.emit("data", t) } ), this.heartbeat = new Heartbeat({ ping: t=>{ e.room.actionsHandler.echo(t) } , pong(t, r) { var n; r && t > 500 && logger.warn(`high hb value ${t}, traceId:` + r), (n = e.room.stats) == null || n.assign({ hb: t }) } }) } start() { this.connection = new RTCPeerConnection; const e = Date.now(); this.connection.ondatachannel = t=>{ logger.info(`ondatachannel: ${t.channel.label}`); this.inputChannel = t.channel; this.inputChannel.onopen = ()=>{ // var r; // logger.info("The input channel has opened, id:", (r = this.inputChannel) == null ? void 0 : r.id), // this.inputReady = !0; // this.emit("rtcConnected"); // this.network.room.currentNetworkOptions.reconnect || (logger.infoAndReportMeasurement({ // metric: "datachannelOpenedAt", // startTime: this.network.room._startTime, // group: "joinRoom" // }), // logger.infoAndReportMeasurement({ // metric: "datachannelOpenedCost", // startTime: e, // group: "joinRoom" // })) // console.log('this.inputChannel',this.inputChannel) } , this.inputChannel.onclose = ()=>{ // var r; // return logger.info("The input channel has closed, id:", (r = this.inputChannel) == null ? void 0 : r.id) }, this.inputChannel.onmessage = r=>{ // console.log('this.workers',this.workers) // console.log('inputChannel',r.data) this.workers.dataHandle(r.data) } } , this.connection.oniceconnectionstatechange = this.onIceConnectionStateChange, this.connection.onicegatheringstatechange = this.onIceStateChange, this.connection.onicecandidate = this.onIcecandidate, this.connection.onicecandidateerror = this.onIcecandidateerror; this.network.socket.send({ id: "init_webrtc", data: JSON.stringify({ is_mobile: !0 }) }) } addCandidate(e) { e === "" ? this.network.rtcp.flushCandidate() : this.candidates.push(e) } disconnect() { var e, t, r; this.heartbeat.stop(), logger.info("ready to close datachannel, id", (e = this.inputChannel) == null ? void 0 : e.id), (t = this.inputChannel) == null || t.close(), (r = this.connection) == null || r.close(), this.connection = null, this.inputChannel = null } sendStringData(e) { console.log('e',e) this.input(e) } sendData(e) { let t = ""; try { t = JSON.stringify(e) } catch (r) { logger.error(r); return } this.input(t) } }