123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323 |
- 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);
- const mt = JSON.parse(x.data);
- delete mt.token;
- logger.infoAndReportMeasurement({
- type: "startGame",
- extraData: mt
- });
- });
- (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({
- type: "wsOpenedAt",
- group: "joinRoom"
- }),
- logger.infoAndReportMeasurement({
- type: "wsOpenedCost",
- group: "joinRoom"
- }));
- }),
- 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 == "heartbeat") console.log("Socket心跳请求时间(ms):", Date.now() - parseInt(r.data))
- if (!!n)
- switch (
- (n !== "heartbeat" && logger.info(`receive ws frame: ${t.data}`), 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":
- console.log("server start", JSON.stringify(r));
- 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 (d) {
- const _ = new InternalError(
- "JSON.parse websocket data error: " + r.data
- );
- logger.error(d, _);
- this.emit("socketClosed", _);
- }
- 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",
- });
- }
- }
|