import Heartbeat from "./Heartbeat.js" import Timeout from "./Timeout.js" import InitNetworkTimeoutError from "./error/InitNetworkTimeoutError.js" import {reporter} from "./Reporter.js" import util from "./util.js" import InternalError from "./error/InternalError.js" import Logger from "./Logger.js" const logger = new Logger('ws') export default class Socket extends EventEmitter { constructor(e) { super(); E(this, "_ws"); E(this, "_openTimer"); E(this, "connected", !1); E(this, "_hasTimeout", !1); E(this, "heartbeat"); E(this, "latency", (e,t)=>this.send({ id: "checkLatency", data: JSON.stringify(e), packet_id: t })); E(this, "send", e=>{ if (this.wsNoReady()) { return; } const t = JSON.stringify(e); e.id !== "heartbeat" && logger.info("send ws frame", t); this._ws.send(t); console.log('发送socket数据:'+t) } ); E(this, "startGame", ()=>{ const {roomId: e, userId: t, avatarId: r, skinId: n, role: o, avatarComponents: a, versionId: s, rotationRenderType: l, isAllSync: u, nickname: c, avatarScale: h, appId: f, camera: d, player: _, firends: g, syncByEvent: m, areaName: v, attitude: y, pathName: b, person: T, roomTypeId: C="", syncToOthers: A, hasAvatar: S, prioritySync: P, extra: R={}, removeWhenDisconnected: M} = this.network.room.currentNetworkOptions; R.removeWhenDisconnected = M; const x = { id: "start", room_id: e, user_id: t, trace_id: util.uuid(), data: JSON.stringify({ avatar_components: JSON.stringify(a), avatar_id: r, skin_id: n, is_host: o ? o == "host" : !0, skin_data_version: n !== void 0 && s !== void 0 ? n + s : void 0, rotation_render_type: l, is_all_sync: u, nick_name: encodeURIComponent(c || ""), app_id: f, camera: d, player: _, person: T, firends: JSON.stringify(g), sync_by_event: m, area_name: v, path_name: b, attitude: y, room_type_id: C, syncToOthers: A, hasAvatar: S, avatarSize: h, prioritySync: P, extra: JSON.stringify(R) }) }; //this.send(x); // logger.warn("startGame", le(oe({}, x), { // data: JSON.parse(x.data) // })) } ); this.network = e; // this.heartbeat = new Heartbeat({ // ping: t=>{ // var r; // if (!this.connected) { // this.heartbeat.stop(), // (r = e.room.stats) == null || r.assign({ // rtt: 0 // }); // return // } // this.send({ // id: "heartbeat", // data: t // }) // } // , // pong(t) { // var r; // (r = e.room.stats) == null || r.assign({ // rtt: t // }) // } // }) } get connection() { return this._ws } start() { this._hasTimeout = !1; const e = this.getAddress(); logger.info(`connecting to ${e}`); const t = Date.now(); // this._ws = new WebSocket(e); // this._openTimer = new Timeout(()=>{ // const r = `Failed to open websocket in ${DEFAULT_OPEN_TIMEOUT_MS} ms`; // this._hasTimeout = !0, // this.emit("socketClosed", new InitNetworkTimeoutError(r)) // },DEFAULT_OPEN_TIMEOUT_MS), // this._ws.onopen = ()=>{ // var r; // (r = this._openTimer) == null || r.clear(), // this.connected = !0, // this.heartbeat.start(), // this.network.room.currentNetworkOptions.reconnect || (logger.infoAndReportMeasurement({ // metric: "wsOpenedAt", // group: "joinRoom", // startTime: this.network.room._startTime // }), // logger.infoAndReportMeasurement({ // metric: "wsOpenedCost", // group: "joinRoom", // startTime: t // })) // }, this.connected = !0; //this.handleWSEvent() } getAddress() { const {wsServerUrl: e, reconnect: t, sessionId: r, token: n, roomId: o, userId: a, pageSession: s} = this.network.room.currentNetworkOptions , l = this.network.room.skinId; let u = e; t && (u = u + `?reconnect=true&lastSessionID=${r}`); const c = `userId=${a}&roomId=${o}&pageSession=${s}` + (this.network.room.isHost ? `&skinId=${l}` : "") + (n ? `&token=${n}` : ""); return u = u.indexOf("?") > -1 ? u + "&" + c : u + "?" + c, u } handleWSEvent() { const e = this._ws; e.addEventListener("error", t=>{ this.connected = !1, logger.error("webscoket error", t), this.emit("socketClosed", new InternalError("connect to address error: " + this.network.room.currentNetworkOptions.wsServerUrl)) } ), e.addEventListener("close", t=>{ this.connected = !1, this._onClose(t) } ), e.addEventListener("message", t=>{ if (!t || this._hasTimeout || !this.connected) return; let r = null; try { r = JSON.parse(t.data) console.log('接收socket数据:'+t.data) } catch (o) { logger.error(o); return } if (!r) return; const n = r.id; if (!!n) { n !== "heartbeat" && logger.info(`receive ws frame: ${t.data}`); switch (n) { case "fail": break; case "init": // try { // const o = r.data.slice(-37, -1); // reporter.updateBody({ // serverSession: o // }) // } catch (o) { // console.error(o) // } // this.network.rtcp.start(); break; // case "heartbeat": // this.heartbeat.pong(r.data); // break; case "offer": //this.network.rtcp.setRemoteDescription(r.data, this.network.stream.el); break; case "ice_candidate": //this.network.rtcp.addCandidate(r.data); break; // case "start": // this.emit("gameRoomAvailable", r); // break; // case "error": // try { // const {Code: o, Msg: a} = JSON.parse(r.data); // if (o) { // if (o == 3003) // return this.emit("socketClosed", new TokenExpiredError); // if (authenticationErrorCodes.indexOf(o) > -1) // return this.emit("socketClosed", new AuthenticationError("\u9274\u6743\u9519\u8BEF:" + a)); // { // const s = util.getErrorByCode(o); // this.emit("socketClosed", new s(a)) // } // } // } catch (o) { // logger.error(o), // this.emit("socketClosed", new InternalError(r.data)) // } // break; // case "checkLatency": // { // const o = r.packet_id // , a = r.data.split(","); // this.onLatencyCheck({ // packetId: o, // addresses: a // }); // break // } // default: // logger.warn("unkown ws message type", n, r) } } } ) } onLatencyCheck(e) { const t = [...new Set(e.addresses || [])]; Promise.all(t.map(r=>({ [r]: 9999 }))).then(r=>{ const n = Object.assign({}, ...r); this.latency(n, e.packetId) } ) } wsNoReady() { return this._ws.readyState == WebSocket.CLOSED || this._ws.readyState == WebSocket.CLOSING || this._ws.readyState == WebSocket.CONNECTING } prepareReconnect() { this._close({ code: WS_CLOSE_RECONNECT, reason: "reconnect" }) } _onClose({code: e, reason: t}) { this._openTimer && this._openTimer.clear(), logger.warn(`ws closed: ${e} ` + t), [WS_CLOSE_RECONNECT, WS_CLOSE_NORMAL].includes(e) || this.emit("socketClosed", new InternalError("Websocket error")) } _close({code: e, reason: t}) { var r; (r = this._ws) == null || r.close(e, t) } quit() { this._close({ code: WS_CLOSE_NORMAL, reason: "quit" }) } }