Merge pull request #338 from thecodingmachine/ioSocketRefractor

Creating a websocket for the admin plateform
This commit is contained in:
David Négrier 2020-10-19 14:28:00 +02:00 committed by GitHub
commit 88a1e899a3
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
8 changed files with 124 additions and 28 deletions

View File

@ -23,6 +23,8 @@ import {adminApi} from "../Services/AdminApi";
import {socketManager} from "../Services/SocketManager"; import {socketManager} from "../Services/SocketManager";
import {emitInBatch, resetPing} from "../Services/IoSocketHelpers"; import {emitInBatch, resetPing} from "../Services/IoSocketHelpers";
import Jwt from "jsonwebtoken"; import Jwt from "jsonwebtoken";
import {clientEventsEmitter} from "../Services/ClientEventsEmitter";
import {ADMIN_API_TOKEN} from "../Enum/EnvironmentVariable";
export class IoSocketController { export class IoSocketController {
private nextUserId: number = 1; private nextUserId: number = 1;
@ -33,18 +35,51 @@ export class IoSocketController {
} }
adminRoomSocket() { adminRoomSocket() {
/*this.app.ws('/admin/rooms', { this.app.ws('/admin/rooms', {
upgrade: (res, req, context) => {
const query = parse(req.getQuery());
const websocketKey = req.getHeader('sec-websocket-key');
const websocketProtocol = req.getHeader('sec-websocket-protocol');
const websocketExtensions = req.getHeader('sec-websocket-extensions');
const token = query.token;
if (token !== ADMIN_API_TOKEN) {
console.log('Admin access refused for token: '+token)
res.writeStatus("401 Unauthorized").end('Incorrect token');
}
const roomId = query.roomId as string;
res.upgrade(
{roomId},
websocketKey, websocketProtocol, websocketExtensions, context,
);
},
open: (ws) => { open: (ws) => {
console.log('o', ws) console.log('Admin socket connect for room: '+ws.roomId);
ws.send('Hello'); ws.send('Data:'+JSON.stringify(socketManager.getAdminSocketDataFor(ws.roomId as string)));
ws.clientJoinCallback = (clientUUid: string, roomId: string) => {
const wsroomId = ws.roomId as string;
if(wsroomId === roomId) {
ws.send('MemberJoin:'+clientUUid+';'+roomId);
}
};
ws.clientLeaveCallback = (clientUUid: string, roomId: string) => {
const wsroomId = ws.roomId as string;
if(wsroomId === roomId) {
ws.send('MemberLeave:'+clientUUid+';'+roomId);
}
};
clientEventsEmitter.registerToClientJoin(ws.clientJoinCallback);
clientEventsEmitter.registerToClientLeave(ws.clientLeaveCallback);
}, },
message: (ws, arrayBuffer, isBinary): void => { message: (ws, arrayBuffer, isBinary): void => {
console.log('m', ws) console.log('m', ws); //todo: add admin actions such as ban here
}, },
close: (ws, code, message) => { close: (ws, code, message) => {
console.log('close'); //todo make sure this code unregister the right listeners
clientEventsEmitter.unregisterFromClientJoin(ws.clientJoinCallback);
clientEventsEmitter.unregisterFromClientLeave(ws.clientLeaveCallback);
} }
})*/ })
} }
ioConnection() { ioConnection() {

View File

@ -58,7 +58,7 @@ export class MapController extends BaseController{
this.addCorsHeaders(res); this.addCorsHeaders(res);
res.end(JSON.stringify(mapDetails)); res.end(JSON.stringify(mapDetails));
} catch (e) { } catch (e) {
console.error(e); console.error(e.message || e);
res.writeStatus("500 Internal Server Error") res.writeStatus("500 Internal Server Error")
this.addCorsHeaders(res); this.addCorsHeaders(res);
res.end("An error occurred"); res.end("An error occurred");

View File

@ -85,7 +85,7 @@ export class GameRoom {
} }
public join(socket : ExSocketInterface, userPosition: PointInterface): void { public join(socket : ExSocketInterface, userPosition: PointInterface): void {
const user = new User(socket.userId, userPosition, false, this.positionNotifier, socket); const user = new User(socket.userId, socket.userUuid, userPosition, false, this.positionNotifier, socket);
this.users.set(socket.userId, user); this.users.set(socket.userId, user);
// Let's call update position to trigger the join / leave room // Let's call update position to trigger the join / leave room
//this.updatePosition(socket, userPosition); //this.updatePosition(socket, userPosition);

View File

@ -12,6 +12,7 @@ export class User implements Movable {
public constructor( public constructor(
public id: number, public id: number,
public uuid: string,
private position: PointInterface, private position: PointInterface,
public silent: boolean, public silent: boolean,
private positionNotifier: PositionNotifier, private positionNotifier: PositionNotifier,

View File

@ -0,0 +1,32 @@
const EventEmitter = require('events');
const clientJoinEvent = 'clientJoin';
const clientLeaveEvent = 'clientLeave';
class ClientEventsEmitter extends EventEmitter {
emitClientJoin(clientUUid: string, roomId: string): void {
this.emit(clientJoinEvent, clientUUid, roomId);
}
emitClientLeave(clientUUid: string, roomId: string): void {
this.emit(clientLeaveEvent, clientUUid, roomId);
}
registerToClientJoin(callback: (clientUUid: string, roomId: string) => void): void {
this.on(clientJoinEvent, callback);
}
registerToClientLeave(callback: (clientUUid: string, roomId: string) => void): void {
this.on(clientLeaveEvent, callback);
}
unregisterFromClientJoin(callback: (clientUUid: string, roomId: string) => void): void {
this.removeListener(clientJoinEvent, callback);
}
unregisterFromClientLeave(callback: (clientUUid: string, roomId: string) => void): void {
this.removeListener(clientLeaveEvent, callback);
}
}
export const clientEventsEmitter = new ClientEventsEmitter();

View File

@ -36,6 +36,19 @@ import {Gauge} from "prom-client";
import {emitError, emitInBatch} from "./IoSocketHelpers"; import {emitError, emitInBatch} from "./IoSocketHelpers";
import Jwt from "jsonwebtoken"; import Jwt from "jsonwebtoken";
import {JITSI_URL} from "../Enum/EnvironmentVariable"; import {JITSI_URL} from "../Enum/EnvironmentVariable";
import {clientEventsEmitter} from "./ClientEventsEmitter";
interface AdminSocketRoomsList {
[index: string]: number;
}
interface AdminSocketUsersList {
[index: string]: boolean;
}
export interface AdminSocketData {
rooms: AdminSocketRoomsList,
users: AdminSocketUsersList,
}
class SocketManager { class SocketManager {
private Worlds: Map<string, GameRoom> = new Map<string, GameRoom>(); private Worlds: Map<string, GameRoom> = new Map<string, GameRoom>();
@ -54,6 +67,34 @@ class SocketManager {
help: 'Number of clients per room', help: 'Number of clients per room',
labelNames: [ 'room' ] labelNames: [ 'room' ]
}); });
clientEventsEmitter.registerToClientJoin((clientUUid, roomId) => {
this.nbClientsGauge.inc();
// Let's log server load when a user joins
console.log(new Date().toISOString() + ' A user joined (', this.sockets.size, ' connected users)');
});
clientEventsEmitter.registerToClientLeave((clientUUid, roomId) => {
this.nbClientsGauge.dec();
// Let's log server load when a user leaves
console.log('A user left (', this.sockets.size, ' connected users)');
});
}
getAdminSocketDataFor(roomId:string): AdminSocketData {
const data:AdminSocketData = {
rooms: {},
users: {},
}
const room = this.Worlds.get(roomId);
if (room === undefined) {
return data;
}
const users = room.getUsers();
data.rooms[roomId] = users.size;
users.forEach(user => {
data.users[user.uuid] = true
})
return data;
} }
handleJoinRoom(client: ExSocketInterface): void { handleJoinRoom(client: ExSocketInterface): void {
@ -61,10 +102,7 @@ class SocketManager {
const viewport = client.viewport; const viewport = client.viewport;
try { try {
this.sockets.set(client.userId, client); //todo: should this be at the end of the function? this.sockets.set(client.userId, client); //todo: should this be at the end of the function?
this.nbClientsGauge.inc(); clientEventsEmitter.emitClientJoin(client.userUuid, client.roomId);
// Let's log server load when a user joins
console.log(new Date().toISOString() + ' A user joined (', socketManager.sockets.size, ' connected users)');
//join new previous room //join new previous room
const gameRoom = this.joinRoom(client, position); const gameRoom = this.joinRoom(client, position);
@ -332,12 +370,10 @@ class SocketManager {
//user leave previous room //user leave previous room
//Client.leave(Client.roomId); //Client.leave(Client.roomId);
} finally { } finally {
this.nbClientsPerRoomGauge.dec({ room: Client.roomId });
//delete Client.roomId; //delete Client.roomId;
this.sockets.delete(Client.userId); this.sockets.delete(Client.userId);
// Let's log server load when a user leaves this.nbClientsPerRoomGauge.dec({ room: Client.roomId });
this.nbClientsGauge.dec(); clientEventsEmitter.emitClientLeave(Client.userUuid, Client.roomId);
console.log('A user left (', this.sockets.size, ' connected users)');
} }
} }
} }

View File

@ -25,14 +25,14 @@ describe("PositionNotifier", () => {
leaveTriggered = true; leaveTriggered = true;
}); });
const user1 = new User(1, { const user1 = new User(1, 'test', {
x: 500, x: 500,
y: 500, y: 500,
moving: false, moving: false,
direction: 'down' direction: 'down'
}, false, positionNotifier, {} as ExSocketInterface); }, false, positionNotifier, {} as ExSocketInterface);
const user2 = new User(2, { const user2 = new User(2, 'test', {
x: -9999, x: -9999,
y: -9999, y: -9999,
moving: false, moving: false,
@ -103,14 +103,14 @@ describe("PositionNotifier", () => {
leaveTriggered = true; leaveTriggered = true;
}); });
const user1 = new User(1, { const user1 = new User(1, 'test', {
x: 500, x: 500,
y: 500, y: 500,
moving: false, moving: false,
direction: 'down' direction: 'down'
}, false, positionNotifier, {} as ExSocketInterface); }, false, positionNotifier, {} as ExSocketInterface);
const user2 = new User(2, { const user2 = new User(2, 'test', {
x: 0, x: 0,
y: 0, y: 0,
moving: false, moving: false,

View File

@ -64,13 +64,5 @@ export class FourOFourScene extends Phaser.Scene {
this.cat = this.physics.add.sprite(this.game.renderer.width / 2, this.game.renderer.height / 2 - 32, 'cat', 6); this.cat = this.physics.add.sprite(this.game.renderer.width / 2, this.game.renderer.height / 2 - 32, 'cat', 6);
this.cat.flipY=true; this.cat.flipY=true;
/*this.anims.create({
key: 'right',
frames: this.anims.generateFrameNumbers('cat', { start: 6, end: 8 }),
frameRate: 10,
repeat: -1
});
cat.play('right');*/
} }
} }