From 886daebfeac360781bdd7efe96e23f360c70435c Mon Sep 17 00:00:00 2001 From: kharhamel Date: Fri, 26 Mar 2021 14:12:22 +0100 Subject: [PATCH 1/4] improved the unloading process to not create a useless socket --- back/src/Services/SocketManager.ts | 4 ++-- docker-compose.yaml | 4 +--- front/src/Connexion/ConnectionManager.ts | 17 +++++++++++++---- front/src/Connexion/RoomConnection.ts | 12 +++++------- front/src/Phaser/Game/GameScene.ts | 5 ++--- pusher/src/Controller/BaseController.ts | 6 +++--- 6 files changed, 26 insertions(+), 22 deletions(-) diff --git a/back/src/Services/SocketManager.ts b/back/src/Services/SocketManager.ts index 40023833..75e683d3 100644 --- a/back/src/Services/SocketManager.ts +++ b/back/src/Services/SocketManager.ts @@ -77,10 +77,10 @@ export class SocketManager { } public async handleJoinRoom(socket: UserSocket, joinRoomMessage: JoinRoomMessage): Promise<{ room: GameRoom; user: User }> { - + //join new previous room const {room, user} = await this.joinRoom(socket, joinRoomMessage); - + const roomJoinedMessage = new RoomJoinedMessage(); roomJoinedMessage.setTagList(joinRoomMessage.getTagList()); diff --git a/docker-compose.yaml b/docker-compose.yaml index 98071437..fdb74d6a 100644 --- a/docker-compose.yaml +++ b/docker-compose.yaml @@ -53,10 +53,8 @@ services: pusher: image: thecodingmachine/nodejs:12 command: yarn dev - #command: yarn run prod - #command: yarn run profile environment: - DEBUG: "*" + DEBUG: "socket:*" STARTUP_COMMAND_1: yarn install SECRET_JITSI_KEY: "$SECRET_JITSI_KEY" SECRET_KEY: yourSecretKey diff --git a/front/src/Connexion/ConnectionManager.ts b/front/src/Connexion/ConnectionManager.ts index 522407e3..b2f1247c 100644 --- a/front/src/Connexion/ConnectionManager.ts +++ b/front/src/Connexion/ConnectionManager.ts @@ -6,16 +6,25 @@ import {GameConnexionTypes, urlManager} from "../Url/UrlManager"; import {localUserStore} from "./LocalUserStore"; import {LocalUser} from "./LocalUser"; import {Room} from "./Room"; -import {Subject} from "rxjs"; -import {ServerToClientMessage} from "../Messages/generated/messages_pb"; class ConnectionManager { private localUser!:LocalUser; private connexionType?: GameConnexionTypes + private reconnectingTimeout: NodeJS.Timeout|null = null; + private _unloading:boolean = false; - public _serverToClientMessageStream:Subject = new Subject(); + get unloading () { + return this._unloading; + } + + constructor() { + window.addEventListener('beforeunload', () => { + this._unloading = true; + if (this.reconnectingTimeout) clearTimeout(this.reconnectingTimeout) + }) + } /** * Tries to login to the node server and return the starting map url to be loaded */ @@ -99,7 +108,7 @@ class ConnectionManager { }).catch((err) => { // Let's retry in 4-6 seconds return new Promise((resolve, reject) => { - setTimeout(() => { + this.reconnectingTimeout = setTimeout(() => { //todo: allow a way to break recursion? //todo: find a way to avoid recursive function. Otherwise, the call stack will grow indefinitely. this.connectToRoomSocket(roomId, name, characterLayers, position, viewport).then((connection) => resolve(connection)); diff --git a/front/src/Connexion/RoomConnection.ts b/front/src/Connexion/RoomConnection.ts index debb99f4..584dae06 100644 --- a/front/src/Connexion/RoomConnection.ts +++ b/front/src/Connexion/RoomConnection.ts @@ -45,6 +45,7 @@ import {BodyResourceDescriptionInterface} from "../Phaser/Entity/PlayerTextures" import {adminMessagesService} from "./AdminMessagesService"; import {worldFullMessageStream} from "./WorldFullMessageStream"; import {worldFullWarningStream} from "./WorldFullWarningStream"; +import {connectionManager} from "./ConnectionManager"; const manualPingDelay = 20000; @@ -380,10 +381,7 @@ export class RoomConnection implements RoomConnection { public onConnectError(callback: (error: Event) => void): void { this.socket.addEventListener('error', callback) } - - /*public onConnect(callback: (e: Event) => void): void { - this.socket.addEventListener('open', callback) - }*/ + public onConnect(callback: (roomConnection: OnConnectInterface) => void): void { //this.socket.addEventListener('open', callback) this.onMessage(EventMessage.CONNECT, callback); @@ -452,9 +450,9 @@ export class RoomConnection implements RoomConnection { }); } - public onServerDisconnected(callback: (event: CloseEvent) => void): void { + public onServerDisconnected(callback: () => void): void { this.socket.addEventListener('close', (event) => { - if (this.closed === true) { + if (this.closed === true || connectionManager.unloading) { return; } console.log('Socket closed with code '+event.code+". Reason: "+event.reason); @@ -462,7 +460,7 @@ export class RoomConnection implements RoomConnection { // Normal closure case return; } - callback(event); + callback(); }); } diff --git a/front/src/Phaser/Game/GameScene.ts b/front/src/Phaser/Game/GameScene.ts index 15872658..6b50109b 100644 --- a/front/src/Phaser/Game/GameScene.ts +++ b/front/src/Phaser/Game/GameScene.ts @@ -471,9 +471,7 @@ export class GameScene extends ResizableScene implements CenterListener { this.connection.onServerDisconnected(() => { console.log('Player disconnected from server. Reloading scene.'); - - this.simplePeer.closeAllConnections(); - this.simplePeer.unregister(); + this.cleanupClosingScene(); const gameSceneKey = 'somekey' + Math.round(Math.random() * 10000); const game: Phaser.Scene = new GameScene(this.room, this.MapUrlFile, gameSceneKey); @@ -708,6 +706,7 @@ export class GameScene extends ResizableScene implements CenterListener { audioManager.unloadAudio(); // We are completely destroying the current scene to avoid using a half-backed instance when coming back to the same map. this.connection?.closeConnection(); + this.simplePeer.closeAllConnections(); this.simplePeer?.unregister(); this.messageSubscription?.unsubscribe(); } diff --git a/pusher/src/Controller/BaseController.ts b/pusher/src/Controller/BaseController.ts index 673ffd3c..bb500b57 100644 --- a/pusher/src/Controller/BaseController.ts +++ b/pusher/src/Controller/BaseController.ts @@ -1,5 +1,4 @@ -import {HttpRequest, HttpResponse} from "uWebSockets.js"; -import {ADMIN_API_TOKEN} from "../Enum/EnvironmentVariable"; +import {HttpResponse} from "uWebSockets.js"; export class BaseController { @@ -14,7 +13,8 @@ export class BaseController { */ // eslint-disable-next-line @typescript-eslint/no-explicit-any protected errorToResponse(e: any, res: HttpResponse): void { - console.error("An error happened", e); + console.error(e.message || "An error happened.", e?.config.url); + console.error(e.stack || 'no stack defined.'); if (e.response) { res.writeStatus(e.response.status+" "+e.response.statusText); this.addCorsHeaders(res); From d269596702ffb03be2db8c86bb94330aa47cd883 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20N=C3=A9grier?= Date: Fri, 26 Mar 2021 14:33:55 +0100 Subject: [PATCH 2/4] Fixing Discord invite link --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index cf640d9c..c6facad3 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,4 @@ -![](https://github.com/thecodingmachine/workadventure/workflows/Continuous%20Integration/badge.svg) [![Discord](https://img.shields.io/discord/821338762134290432?label=Discord)](https://discord.gg/JVVhXzcE) +![](https://github.com/thecodingmachine/workadventure/workflows/Continuous%20Integration/badge.svg) [![Discord](https://img.shields.io/discord/821338762134290432?label=Discord)](https://discord.gg/YGtngdh9gt) ![WorkAdventure landscape image](README-INTRO.jpg) From 3b6fe8da8d591974a81bb9dd362c45cca30209f0 Mon Sep 17 00:00:00 2001 From: kharhamel Date: Fri, 26 Mar 2021 15:13:08 +0100 Subject: [PATCH 3/4] improved the back to better handle ghost connexions --- back/src/RoomManager.ts | 9 +++++++-- back/src/Services/SocketManager.ts | 14 +++++++------- 2 files changed, 14 insertions(+), 9 deletions(-) diff --git a/back/src/RoomManager.ts b/back/src/RoomManager.ts index 0a8e4a01..60e90d82 100644 --- a/back/src/RoomManager.ts +++ b/back/src/RoomManager.ts @@ -43,8 +43,13 @@ const roomManager: IRoomManagerServer = { if (room === null || user === null) { if (message.hasJoinroommessage()) { socketManager.handleJoinRoom(call, message.getJoinroommessage() as JoinRoomMessage).then(({room: gameRoom, user: myUser}) => { - room = gameRoom; - user = myUser; + if (call.writable) { + room = gameRoom; + user = myUser; + } else { + //Connexion may have been closed before the init was finished, so we have to manually disconnect the user. + socketManager.leaveRoom(gameRoom, myUser); + } }); } else { throw new Error('The first message sent MUST be of type JoinRoomMessage'); diff --git a/back/src/Services/SocketManager.ts b/back/src/Services/SocketManager.ts index 75e683d3..c03f4773 100644 --- a/back/src/Services/SocketManager.ts +++ b/back/src/Services/SocketManager.ts @@ -81,6 +81,13 @@ export class SocketManager { //join new previous room const {room, user} = await this.joinRoom(socket, joinRoomMessage); + if (!socket.writable) { + console.warn('Socket was aborted'); + return { + room, + user + }; + } const roomJoinedMessage = new RoomJoinedMessage(); roomJoinedMessage.setTagList(joinRoomMessage.getTagList()); @@ -96,7 +103,6 @@ export class SocketManager { const serverToClientMessage = new ServerToClientMessage(); serverToClientMessage.setRoomjoinedmessage(roomJoinedMessage); - console.log('SENDING MESSAGE roomJoinedMessage'); socket.write(serverToClientMessage); return { @@ -264,8 +270,6 @@ export class SocketManager { debug('Room is empty. Deleting room "%s"', room.roomId); } } finally { - //delete Client.roomId; - //this.sockets.delete(Client.userId); clientEventsEmitter.emitClientLeave(user.uuid, room.roomId); console.log('A user left'); } @@ -415,10 +419,6 @@ export class SocketManager { } private joinWebRtcRoom(user: User, group: Group) { - /*const roomId: string = "webrtcroom"+group.getId(); - if (user.socket.webRtcRoomId === roomId) { - return; - }*/ for (const otherUser of group.getUsers()) { if (user === otherUser) { From 5375528d7c7a4f860d04ffff0107bb2d50c9c1d8 Mon Sep 17 00:00:00 2001 From: Johannes Berthel Date: Sat, 27 Mar 2021 13:57:50 +0100 Subject: [PATCH 4/4] use map tilewidth instead of hardcoded values --- front/src/Phaser/Game/GameScene.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/front/src/Phaser/Game/GameScene.ts b/front/src/Phaser/Game/GameScene.ts index 6b50109b..6faaf4fa 100644 --- a/front/src/Phaser/Game/GameScene.ts +++ b/front/src/Phaser/Game/GameScene.ts @@ -817,7 +817,7 @@ export class GameScene extends ResizableScene implements CenterListener { const y = Math.floor(key / layer.width); const x = key % layer.width; - possibleStartPositions.push({x: x*32, y: y*32}); + possibleStartPositions.push({x: x * this.mapFile.tilewidth, y: y * this.mapFile.tilewidth}); }); // Get a value at random amongst allowed values if (possibleStartPositions.length === 0) {