Adapting admin connection to pusher.

Done: onUserLeave / onUserEnter
To be done: ban / unban
This commit is contained in:
David Négrier 2020-12-10 17:46:15 +01:00
parent bf797085e6
commit 24cb85cc7c
10 changed files with 306 additions and 522 deletions

37
back/src/Model/Admin.ts Normal file
View file

@ -0,0 +1,37 @@
import { Group } from "./Group";
import { PointInterface } from "./Websocket/PointInterface";
import {Zone} from "_Model/Zone";
import {Movable} from "_Model/Movable";
import {PositionNotifier} from "_Model/PositionNotifier";
import {ServerDuplexStream} from "grpc";
import {
BatchMessage,
PusherToBackMessage,
ServerToAdminClientMessage,
ServerToClientMessage,
SubMessage
} from "../Messages/generated/messages_pb";
import {CharacterLayer} from "_Model/Websocket/CharacterLayer";
import {AdminSocket} from "../RoomManager";
export class Admin {
public constructor(
private readonly socket: AdminSocket
) {
}
public sendUserJoin(uuid: string): void {
const serverToAdminClientMessage = new ServerToAdminClientMessage();
serverToAdminClientMessage.setUseruuidjoinedroom(uuid);
this.socket.write(serverToAdminClientMessage);
}
public sendUserLeft(uuid: string): void {
const serverToAdminClientMessage = new ServerToAdminClientMessage();
serverToAdminClientMessage.setUseruuidleftroom(uuid);
this.socket.write(serverToAdminClientMessage);
}
}

View file

@ -10,7 +10,8 @@ import {arrayIntersect} from "../Services/ArrayHelper";
import {MAX_USERS_PER_ROOM} from "../Enum/EnvironmentVariable";
import {JoinRoomMessage} from "../Messages/generated/messages_pb";
import {ProtobufUtils} from "../Model/Websocket/ProtobufUtils";
import { ZoneSocket } from "src/RoomManager";
import {ZoneSocket} from "src/RoomManager";
import {Admin} from "../Model/Admin";
export type ConnectCallback = (user: User, group: Group) => void;
export type DisconnectCallback = (user: User, group: Group) => void;
@ -28,6 +29,7 @@ export class GameRoom {
// Users, sorted by ID
private readonly users: Map<number, User>;
private readonly groups: Set<Group>;
private readonly admins: Set<Admin>;
private readonly connectCallback: ConnectCallback;
private readonly disconnectCallback: DisconnectCallback;
@ -69,6 +71,7 @@ export class GameRoom {
this.users = new Map<number, User>();
this.admins = new Set<Admin>();
this.groups = new Set<Group>();
this.connectCallback = connectCallback;
this.disconnectCallback = disconnectCallback;
@ -99,6 +102,12 @@ export class GameRoom {
// Let's call update position to trigger the join / leave room
//this.updatePosition(socket, userPosition);
this.updateUserGroup(user);
// Notify admins
for (const admin of this.admins) {
admin.sendUserJoin(user.uuid);
}
return user;
}
@ -115,6 +124,11 @@ export class GameRoom {
if (userObj !== undefined) {
this.positionNotifier.leave(userObj);
}
// Notify admins
for (const admin of this.admins) {
admin.sendUserLeft(user.uuid);
}
}
get isFull(): boolean {
@ -122,7 +136,7 @@ export class GameRoom {
}
public isEmpty(): boolean {
return this.users.size === 0;
return this.users.size === 0 && this.admins.size === 0;
}
public updatePosition(user : User, userPosition: PointInterface): void {
@ -290,4 +304,17 @@ export class GameRoom {
public removeZoneListener(call: ZoneSocket, x: number, y: number): void {
return this.positionNotifier.removeZoneListener(call, x, y);
}
public adminJoin(admin: Admin): void {
this.admins.add(admin);
// Let's send all connected users
for (const user of this.users.values()) {
admin.sendUserJoin(user.uuid);
}
}
public adminLeave(admin: Admin): void {
this.admins.delete(admin);
}
}

View file

@ -1,20 +1,23 @@
import {IRoomManagerServer} from "./Messages/generated/messages_grpc_pb";
import {
AdminPusherToBackMessage,
ClientToServerMessage, ItemEventMessage,
JoinRoomMessage, PlayGlobalMessage, PusherToBackMessage, QueryJitsiJwtMessage, ReportPlayerMessage,
RoomJoinedMessage,
RoomJoinedMessage, ServerToAdminClientMessage,
ServerToClientMessage, SilentMessage, UserMovesMessage, ViewportMessage, WebRtcSignalToServerMessage, ZoneMessage
} from "./Messages/generated/messages_pb";
import grpc, {ServerWritableStream} from "grpc";
import grpc, {ServerDuplexStream, ServerWritableStream} from "grpc";
import {Empty} from "google-protobuf/google/protobuf/empty_pb";
import {socketManager} from "./Services/SocketManager";
import {emitError} from "./Services/MessageHelpers";
import {User, UserSocket} from "./Model/User";
import {GameRoom} from "./Model/GameRoom";
import Debug from "debug";
import {Admin} from "./Model/Admin";
const debug = Debug('roommanager');
export type AdminSocket = ServerDuplexStream<AdminPusherToBackMessage, ServerToAdminClientMessage>;
export type ZoneSocket = ServerWritableStream<ZoneMessage, ServerToClientMessage>;
const roomManager: IRoomManagerServer = {
@ -109,6 +112,65 @@ const roomManager: IRoomManagerServer = {
call.end();
});
},
adminRoom(call: AdminSocket): void {
console.log('adminRoom called');
const admin = new Admin(call);
let room: GameRoom|null = null;
call.on('data', (message: AdminPusherToBackMessage) => {
try {
if (room === null) {
if (message.hasSubscribetoroom()) {
const roomId = message.getSubscribetoroom();
socketManager.handleJoinAdminRoom(admin, roomId).then((gameRoom: GameRoom) => {
room = gameRoom;
});
} else {
throw new Error('The first message sent MUST be of type JoinRoomMessage');
}
} else {
/*if (message.hasJoinroommessage()) {
throw new Error('Cannot call JoinRoomMessage twice!');
} else if (message.hasUsermovesmessage()) {
socketManager.handleUserMovesMessage(room, user, message.getUsermovesmessage() as UserMovesMessage);
} else if (message.hasSilentmessage()) {
socketManager.handleSilentMessage(room, user, message.getSilentmessage() as SilentMessage);
} else if (message.hasItemeventmessage()) {
socketManager.handleItemEvent(room, user, message.getItemeventmessage() as ItemEventMessage);
} else if (message.hasWebrtcsignaltoservermessage()) {
socketManager.emitVideo(room, user, message.getWebrtcsignaltoservermessage() as WebRtcSignalToServerMessage);
} else if (message.hasWebrtcscreensharingsignaltoservermessage()) {
socketManager.emitScreenSharing(room, user, message.getWebrtcscreensharingsignaltoservermessage() as WebRtcSignalToServerMessage);
} else if (message.hasPlayglobalmessage()) {
socketManager.emitPlayGlobalMessage(room, message.getPlayglobalmessage() as PlayGlobalMessage);
} else if (message.hasQueryjitsijwtmessage()){
socketManager.handleQueryJitsiJwtMessage(user, message.getQueryjitsijwtmessage() as QueryJitsiJwtMessage);
} else {
throw new Error('Unhandled message type');
}*/
}
} catch (e) {
emitError(call, e);
call.end();
}
});
call.on('end', () => {
debug('joinRoom ended');
if (room !== null) {
socketManager.leaveAdminRoom(room, admin);
}
call.end();
room = null;
});
call.on('error', (err: Error) => {
console.error('An error occurred in joinAdminRoom stream:', err);
});
},
};
export {roomManager};

View file

@ -11,7 +11,7 @@ class ClientEventsEmitter extends EventEmitter {
emitClientLeave(clientUUid: string, roomId: string): void {
this.emit(clientLeaveEvent, clientUUid, roomId);
}
registerToClientJoin(callback: (clientUUid: string, roomId: string) => void): void {
this.on(clientJoinEvent, callback);
}
@ -29,4 +29,4 @@ class ClientEventsEmitter extends EventEmitter {
}
}
export const clientEventsEmitter = new ClientEventsEmitter();
export const clientEventsEmitter = new ClientEventsEmitter();

View file

@ -45,9 +45,10 @@ import Jwt from "jsonwebtoken";
import {JITSI_URL} from "../Enum/EnvironmentVariable";
import {clientEventsEmitter} from "./ClientEventsEmitter";
import {gaugeManager} from "./GaugeManager";
import {ZoneSocket} from "../RoomManager";
import {AdminSocket, ZoneSocket} from "../RoomManager";
import {Zone} from "_Model/Zone";
import Debug from "debug";
import {Admin} from "_Model/Admin";
const debug = Debug('sockermanager');
@ -83,7 +84,7 @@ export class SocketManager {
});
}
getAdminSocketDataFor(roomId:string): AdminSocketData {
/*getAdminSocketDataFor(roomId:string): AdminSocketData {
const data:AdminSocketData = {
rooms: {},
users: {},
@ -98,7 +99,7 @@ export class SocketManager {
data.users[user.uuid] = true
})
return data;
}
}*/
public async handleJoinRoom(socket: UserSocket, joinRoomMessage: JoinRoomMessage): Promise<{ room: GameRoom; user: User }> {
/*const positionMessage = joinRoomMessage.getPositionmessage();
@ -385,6 +386,7 @@ export class SocketManager {
//join world
const user = world.join(socket, joinRoomMessage);
clientEventsEmitter.emitClientJoin(user.uuid, roomId);
//console.log(new Date().toISOString() + ' A user joined (', this.sockets.size, ' connected users)');
console.log(new Date().toISOString() + ' A user joined');
@ -738,6 +740,28 @@ export class SocketManager {
room.removeZoneListener(call, x, y);
}
public async handleJoinAdminRoom(admin: Admin, roomId: string): Promise<GameRoom> {
const room = await socketManager.getOrCreateRoom(roomId);
// Dispatch groups position to newly connected user
/*world.getGroups().forEach((group: Group) => {
this.emitCreateUpdateGroupEvent(socket, group);
});*/
room.adminJoin(admin);
return room;
}
public leaveAdminRoom(room: GameRoom, admin: Admin){
room.adminLeave(admin);
if (room.isEmpty()) {
this.rooms.delete(room.roomId);
debug('Room is empty. Deleting room "%s"', room.roomId);
}
}
}
export const socketManager = new SocketManager();