From ab32021fc0d7754605ab9bac4b6788e5277388aa Mon Sep 17 00:00:00 2001 From: Gregoire Parant Date: Sat, 23 May 2020 14:00:36 +0200 Subject: [PATCH 1/4] Fix mediam stream manage and server back down --- back/src/Controller/AuthenticateController.ts | 10 ++++---- back/src/Controller/IoSocketController.ts | 23 +++++++++++++++--- front/src/Connexion.ts | 13 ++++------ front/src/Phaser/Game/GameScene.ts | 11 ++++++++- front/src/WebRtc/SimplePeer.ts | 24 +++++++++++++++++-- 5 files changed, 61 insertions(+), 20 deletions(-) diff --git a/back/src/Controller/AuthenticateController.ts b/back/src/Controller/AuthenticateController.ts index db5fb1ce..4e617509 100644 --- a/back/src/Controller/AuthenticateController.ts +++ b/back/src/Controller/AuthenticateController.ts @@ -15,21 +15,21 @@ export class AuthenticateController { //permit to login on application. Return token to connect on Websocket IO. login(){ // For now, let's completely forget the /login route. - /*this.App.post("/login", (req: Request, res: Response) => { + this.App.post("/login", (req: Request, res: Response) => { let param = req.body; - if(!param.email){ + /*if(!param.name){ return res.status(BAD_REQUEST).send({ message: "email parameter is empty" }); - } + }*/ //TODO check user email for The Coding Machine game let userId = uuid(); - let token = Jwt.sign({email: param.email, userId: userId}, SECRET_KEY, {expiresIn: '24h'}); + let token = Jwt.sign({name: param.name, userId: userId}, SECRET_KEY, {expiresIn: '24h'}); return res.status(OK).send({ token: token, mapUrlStart: URL_ROOM_STARTED, userId: userId, }); - });*/ + }); } } diff --git a/back/src/Controller/IoSocketController.ts b/back/src/Controller/IoSocketController.ts index 8332d782..a93f7738 100644 --- a/back/src/Controller/IoSocketController.ts +++ b/back/src/Controller/IoSocketController.ts @@ -39,25 +39,42 @@ export class IoSocketController { // Authentication with token. it will be decoded and stored in the socket. // Completely commented for now, as we do not use the "/login" route at all. - /*this.Io.use((socket: Socket, next) => { + this.Io.use((socket: Socket, next) => { if (!socket.handshake.query || !socket.handshake.query.token) { return next(new Error('Authentication error')); } if(this.searchClientByToken(socket.handshake.query.token)){ return next(new Error('Authentication error')); } - Jwt.verify(socket.handshake.query.token, SECRET_KEY, (err: JsonWebTokenError, tokenDecoded: object) => { + Jwt.verify(socket.handshake.query.token, SECRET_KEY, (err: JsonWebTokenError, tokenDecoded: any) => { if (err) { return next(new Error('Authentication error')); } (socket as ExSocketInterface).token = tokenDecoded; + (socket as ExSocketInterface).id = tokenDecoded.userId; next(); }); - });*/ + }); this.ioConnection(); } + /** + * + * @param token + */ + searchClientByToken(token: string): ExSocketInterface | null { + let clients: Array = Object.values(this.Io.sockets.sockets); + for (let i = 0; i < clients.length; i++) { + let client: ExSocketInterface = clients[i]; + if (client.token !== token) { + continue + } + return client; + } + return null; + } + private sendUpdateGroupEvent(group: Group): void { // Let's get the room of the group. To do this, let's get anyone in the group and find its room. // Note: this is suboptimal diff --git a/front/src/Connexion.ts b/front/src/Connexion.ts index 1b963129..e5a73aaf 100644 --- a/front/src/Connexion.ts +++ b/front/src/Connexion.ts @@ -165,25 +165,20 @@ export class Connexion implements ConnexionInterface { createConnexion(name: string, characterSelected: string): Promise { this.name = name; this.character = characterSelected; - /*return Axios.post(`${API_URL}/login`, {email: this.email}) + return Axios.post(`${API_URL}/login`, {name: name}) .then((res) => { this.token = res.data.token; - this.userId = res.data.userId;*/ - this.socket = SocketIo(`${API_URL}`, { - /*query: { + query: { token: this.token - }*/ + } }); - return this.connectSocketServer(); - - /* return res.data; }) .catch((err) => { console.error(err); throw err; - });*/ + }); } /** diff --git a/front/src/Phaser/Game/GameScene.ts b/front/src/Phaser/Game/GameScene.ts index 4a003b33..c79fb740 100644 --- a/front/src/Phaser/Game/GameScene.ts +++ b/front/src/Phaser/Game/GameScene.ts @@ -3,7 +3,7 @@ import { GroupCreatedUpdatedMessageInterface, MessageUserJoined, MessageUserMovedInterface, - MessageUserPositionInterface + MessageUserPositionInterface, PointInterface } from "../../Connexion"; import {CurrentGamerInterface, GamerInterface, hasMovedEventName, Player} from "../Player/Player"; import { DEBUG_MODE, RESOLUTION, ROOM, ZOOM_LEVEL} from "../../Enum/EnvironmentVariable"; @@ -14,6 +14,7 @@ import Sprite = Phaser.GameObjects.Sprite; import CanvasTexture = Phaser.Textures.CanvasTexture; import {AddPlayerInterface} from "./AddPlayerInterface"; import {PlayerAnimationNames} from "../Player/Animation"; +import {MessageUserMoved} from "../../../../back/src/Model/Websocket/MessageUserMoved"; export enum Textures { Player = "male1" @@ -410,6 +411,14 @@ export class GameScene extends Phaser.Scene { * Create new player */ public addPlayer(addPlayerData : AddPlayerInterface) : void{ + //check if exist player, if exist, move position + if(this.MapPlayersByKey.has(addPlayerData.userId)){ + this.updatePlayerPosition({ + userId: addPlayerData.userId, + position: addPlayerData.position + }); + return; + } //initialise player let player = new Player( addPlayerData.userId, diff --git a/front/src/WebRtc/SimplePeer.ts b/front/src/WebRtc/SimplePeer.ts index 595e83b2..b301876e 100644 --- a/front/src/WebRtc/SimplePeer.ts +++ b/front/src/WebRtc/SimplePeer.ts @@ -141,9 +141,9 @@ export class SimplePeer implements SimplePeerInterface{ this.stream(user.userId, stream); }); - this.PeerConnexionArray.get(user.userId).on('track', (track: MediaStreamTrack, stream: MediaStream) => { + /*this.PeerConnexionArray.get(user.userId).on('track', (track: MediaStreamTrack, stream: MediaStream) => { this.stream(user.userId, stream); - }); + });*/ this.PeerConnexionArray.get(user.userId).on('close', () => { this.closeConnexion(user.userId); @@ -157,6 +157,13 @@ export class SimplePeer implements SimplePeerInterface{ console.info(`connect => ${user.userId}`); }); + this.PeerConnexionArray.get(user.userId).on('data', (chunk: Buffer) => { + let data = JSON.parse(chunk.toString('utf8')); + if(data.type === "stream"){ + this.stream(user.userId, data.stream); + } + }); + this.addMedia(user.userId); } @@ -205,6 +212,11 @@ export class SimplePeer implements SimplePeerInterface{ * @param stream */ private stream(userId : any, stream: MediaStream) { + if(!stream){ + this.MediaManager.disabledVideoByUserId(userId); + this.MediaManager.disabledMicrophoneByUserId(userId); + return; + } this.MediaManager.addStreamRemoteVideo(userId, stream); } @@ -216,6 +228,14 @@ export class SimplePeer implements SimplePeerInterface{ try { let transceiver : any = null; if(!this.MediaManager.localStream){ + //send fake signal + if(!this.PeerConnexionArray.has(userId)){ + return; + } + this.PeerConnexionArray.get(userId).write(new Buffer(JSON.stringify({ + type: "stream", + stream: null + }))); return; } this.MediaManager.localStream.getTracks().forEach( From 0c9cbca7658ef05f9cfaaa3b1faf2932728b0616 Mon Sep 17 00:00:00 2001 From: Gregoire Parant Date: Sat, 23 May 2020 15:04:25 +0200 Subject: [PATCH 2/4] Use `userId` generated by back end in all message --- back/src/Controller/IoSocketController.ts | 22 +++++++++---------- back/src/Model/Websocket/ExSocketInterface.ts | 2 +- back/src/Model/Websocket/Identificable.ts | 2 +- back/src/Model/World.ts | 12 +++++----- 4 files changed, 19 insertions(+), 19 deletions(-) diff --git a/back/src/Controller/IoSocketController.ts b/back/src/Controller/IoSocketController.ts index a93f7738..f6f9f41f 100644 --- a/back/src/Controller/IoSocketController.ts +++ b/back/src/Controller/IoSocketController.ts @@ -51,7 +51,7 @@ export class IoSocketController { return next(new Error('Authentication error')); } (socket as ExSocketInterface).token = tokenDecoded; - (socket as ExSocketInterface).id = tokenDecoded.userId; + (socket as ExSocketInterface).userId = tokenDecoded.userId; next(); }); }); @@ -97,7 +97,8 @@ export class IoSocketController { ioConnection() { this.Io.on(SockerIoEvent.CONNECTION, (socket: Socket) => { - this.sockets.set(socket.id, socket as ExSocketInterface); + let client : ExSocketInterface = socket as ExSocketInterface; + this.sockets.set(client.userId, client); /*join-rom event permit to join one room. message : userId : user identification @@ -135,7 +136,7 @@ export class IoSocketController { //add function to refresh position user in real time. //this.refreshUserPosition(Client); - let messageUserJoined = new MessageUserJoined(Client.id, Client.name, Client.character, Client.position); + let messageUserJoined = new MessageUserJoined(Client.userId, Client.name, Client.character, Client.position); socket.to(roomId).emit(SockerIoEvent.JOIN_ROOM, messageUserJoined); @@ -172,7 +173,7 @@ export class IoSocketController { } world.updatePosition(Client, position); - socket.to(Client.roomId).emit(SockerIoEvent.USER_MOVED, new MessageUserMoved(Client.id, Client.position)); + socket.to(Client.roomId).emit(SockerIoEvent.USER_MOVED, new MessageUserMoved(Client.userId, Client.position)); } catch (e) { console.error('An error occurred on "user_position" event'); console.error(e); @@ -200,9 +201,8 @@ export class IoSocketController { }); socket.on(SockerIoEvent.DISCONNECT, () => { + let Client = (socket as ExSocketInterface); try { - let Client = (socket as ExSocketInterface); - //leave room this.leaveRoom(Client); @@ -218,7 +218,7 @@ export class IoSocketController { console.error('An error occurred on "disconnect"'); console.error(e); } - this.sockets.delete(socket.id); + this.sockets.delete(Client.userId); }); // Let's send the user id to the user @@ -226,7 +226,7 @@ export class IoSocketController { let Client = (socket as ExSocketInterface); Client.name = playerDetails.name; Client.character = playerDetails.character; - answerFn(socket.id); + answerFn(Client.userId); }); }); } @@ -242,7 +242,7 @@ export class IoSocketController { leaveRoom(Client : ExSocketInterface){ // leave previous room and world if(Client.roomId){ - Client.to(Client.roomId).emit(SockerIoEvent.USER_LEFT, Client.id); + Client.to(Client.roomId).emit(SockerIoEvent.USER_LEFT, Client.userId); //user leave previous world let world : World|undefined = this.Worlds.get(Client.roomId); @@ -310,11 +310,11 @@ export class IoSocketController { clients.forEach((client: ExSocketInterface, index: number) => { let clientsId = clients.reduce((tabs: Array, clientId: ExSocketInterface, indexClientId: number) => { - if (!clientId.id || clientId.id === client.id) { + if (!clientId.userId || clientId.userId === client.userId) { return tabs; } tabs.push({ - userId: clientId.id, + userId: clientId.userId, name: clientId.name, initiator: index <= indexClientId }); diff --git a/back/src/Model/Websocket/ExSocketInterface.ts b/back/src/Model/Websocket/ExSocketInterface.ts index c55a9759..df72321f 100644 --- a/back/src/Model/Websocket/ExSocketInterface.ts +++ b/back/src/Model/Websocket/ExSocketInterface.ts @@ -6,7 +6,7 @@ export interface ExSocketInterface extends Socket, Identificable { token: any; roomId: string; webRtcRoomId: string; - //userId: string; + userId: string; name: string; character: string; position: PointInterface; diff --git a/back/src/Model/Websocket/Identificable.ts b/back/src/Model/Websocket/Identificable.ts index 8c344259..4e3228ae 100644 --- a/back/src/Model/Websocket/Identificable.ts +++ b/back/src/Model/Websocket/Identificable.ts @@ -1,3 +1,3 @@ export interface Identificable { - id: string; + userId: string; } diff --git a/back/src/Model/World.ts b/back/src/Model/World.ts index 0529edc3..5f70a32f 100644 --- a/back/src/Model/World.ts +++ b/back/src/Model/World.ts @@ -53,8 +53,8 @@ export class World { } public join(socket : Identificable, userPosition: PointInterface): void { - this.users.set(socket.id, { - id: socket.id, + this.users.set(socket.userId, { + id: socket.userId, position: userPosition }); // Let's call update position to trigger the join / leave room @@ -62,18 +62,18 @@ export class World { } public leave(user : Identificable){ - let userObj = this.users.get(user.id); + let userObj = this.users.get(user.userId); if (userObj === undefined) { - console.warn('User ', user.id, 'does not belong to world! It should!'); + console.warn('User ', user.userId, 'does not belong to world! It should!'); } if (userObj !== undefined && typeof userObj.group !== 'undefined') { this.leaveGroup(userObj); } - this.users.delete(user.id); + this.users.delete(user.userId); } public updatePosition(socket : Identificable, userPosition: PointInterface): void { - let user = this.users.get(socket.id); + let user = this.users.get(socket.userId); if(typeof user === 'undefined') { return; } From 57e8c0261c94ed9cc7b335e4fac074cc54a5956e Mon Sep 17 00:00:00 2001 From: Gregoire Parant Date: Sat, 23 May 2020 16:32:14 +0200 Subject: [PATCH 3/4] Fix test socket --- back/tests/WorldTest.ts | 26 +++++++++++++------------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/back/tests/WorldTest.ts b/back/tests/WorldTest.ts index aed9b838..88c87430 100644 --- a/back/tests/WorldTest.ts +++ b/back/tests/WorldTest.ts @@ -15,19 +15,19 @@ describe("World", () => { let world = new World(connect, disconnect, 160, 160, () => {}, () => {}); - world.join({ id: "foo" }, new Point(100, 100)); + world.join({ userId: "foo" }, new Point(100, 100)); - world.join({ id: "bar" }, new Point(500, 100)); + world.join({ userId: "bar" }, new Point(500, 100)); - world.updatePosition({ id: "bar" }, new Point(261, 100)); + world.updatePosition({ userId: "bar" }, new Point(261, 100)); expect(connectCalledNumber).toBe(0); - world.updatePosition({ id: "bar" }, new Point(101, 100)); + world.updatePosition({ userId: "bar" }, new Point(101, 100)); expect(connectCalledNumber).toBe(2); - world.updatePosition({ id: "bar" }, new Point(102, 100)); + world.updatePosition({ userId: "bar" }, new Point(102, 100)); expect(connectCalledNumber).toBe(2); }); @@ -42,19 +42,19 @@ describe("World", () => { let world = new World(connect, disconnect, 160, 160, () => {}, () => {}); - world.join({ id: "foo" }, new Point(100, 100)); + world.join({ userId: "foo" }, new Point(100, 100)); - world.join({ id: "bar" }, new Point(200, 100)); + world.join({ userId: "bar" }, new Point(200, 100)); expect(connectCalled).toBe(true); connectCalled = false; // baz joins at the outer limit of the group - world.join({ id: "baz" }, new Point(311, 100)); + world.join({ userId: "baz" }, new Point(311, 100)); expect(connectCalled).toBe(false); - world.updatePosition({ id: "baz" }, new Point(309, 100)); + world.updatePosition({ userId: "baz" }, new Point(309, 100)); expect(connectCalled).toBe(true); }); @@ -71,18 +71,18 @@ describe("World", () => { let world = new World(connect, disconnect, 160, 160, () => {}, () => {}); - world.join({ id: "foo" }, new Point(100, 100)); + world.join({ userId: "foo" }, new Point(100, 100)); - world.join({ id: "bar" }, new Point(259, 100)); + world.join({ userId: "bar" }, new Point(259, 100)); expect(connectCalled).toBe(true); expect(disconnectCallNumber).toBe(0); - world.updatePosition({ id: "bar" }, new Point(100+160+160+1, 100)); + world.updatePosition({ userId: "bar" }, new Point(100+160+160+1, 100)); expect(disconnectCallNumber).toBe(2); - world.updatePosition({ id: "bar" }, new Point(262, 100)); + world.updatePosition({ userId: "bar" }, new Point(262, 100)); expect(disconnectCallNumber).toBe(2); }); From f4ed2e52bfeb305c95a6b7a5a3fd7f97622ec737 Mon Sep 17 00:00:00 2001 From: Gregoire Parant Date: Sat, 23 May 2020 16:50:17 +0200 Subject: [PATCH 4/4] Fix CI --- front/src/Phaser/Game/GameScene.ts | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/front/src/Phaser/Game/GameScene.ts b/front/src/Phaser/Game/GameScene.ts index c79fb740..cce0e939 100644 --- a/front/src/Phaser/Game/GameScene.ts +++ b/front/src/Phaser/Game/GameScene.ts @@ -1,12 +1,11 @@ -import {GameManager, gameManager, HasMovedEvent, MapObject, StatusGameManagerEnum} from "./GameManager"; +import {GameManager, gameManager, HasMovedEvent} from "./GameManager"; import { GroupCreatedUpdatedMessageInterface, - MessageUserJoined, MessageUserMovedInterface, - MessageUserPositionInterface, PointInterface + MessageUserPositionInterface } from "../../Connexion"; import {CurrentGamerInterface, GamerInterface, hasMovedEventName, Player} from "../Player/Player"; -import { DEBUG_MODE, RESOLUTION, ROOM, ZOOM_LEVEL} from "../../Enum/EnvironmentVariable"; +import { DEBUG_MODE, ZOOM_LEVEL} from "../../Enum/EnvironmentVariable"; import {ITiledMap, ITiledMapLayer, ITiledTileSet} from "../Map/ITiledMap"; import {PLAYER_RESOURCES} from "../Entity/PlayableCaracter"; import Texture = Phaser.Textures.Texture; @@ -14,7 +13,6 @@ import Sprite = Phaser.GameObjects.Sprite; import CanvasTexture = Phaser.Textures.CanvasTexture; import {AddPlayerInterface} from "./AddPlayerInterface"; import {PlayerAnimationNames} from "../Player/Animation"; -import {MessageUserMoved} from "../../../../back/src/Model/Websocket/MessageUserMoved"; export enum Textures { Player = "male1"