Browse Source

Reimplementing ban/unban/messages

pull/432/head
David Négrier 11 months ago
parent
commit
ea3aa3d128
  1. 12
      back/src/Model/GameRoom.ts
  2. 42
      back/src/RoomManager.ts
  3. 92
      back/src/Services/SocketManager.ts
  4. 24
      messages/protos/messages.proto
  5. 28
      pusher/src/Controller/IoSocketController.ts
  6. 4
      pusher/src/Services/ApiClientRepository.ts
  7. 34
      pusher/src/Services/SocketManager.ts

12
back/src/Model/GameRoom.ts

@ -17,7 +17,7 @@ export type ConnectCallback = (user: User, group: Group) => void;
export type DisconnectCallback = (user: User, group: Group) => void;
export enum GameRoomPolicyTypes {
ANONYMUS_POLICY = 1,
ANONYMOUS_POLICY = 1,
MEMBERS_ONLY_POLICY,
USE_TAGS_POLICY,
}
@ -28,6 +28,7 @@ export class GameRoom {
// Users, sorted by ID
private readonly users: Map<number, User>;
private readonly usersByUuid: Map<string, User>;
private readonly groups: Set<Group>;
private readonly admins: Set<Admin>;
@ -58,7 +59,7 @@ export class GameRoom {
this.roomId = roomId;
this.anonymous = isRoomAnonymous(roomId);
this.tags = [];
this.policyType = GameRoomPolicyTypes.ANONYMUS_POLICY;
this.policyType = GameRoomPolicyTypes.ANONYMOUS_POLICY;
if (this.anonymous) {
this.roomSlug = extractRoomSlugPublicRoomId(this.roomId);
@ -71,6 +72,7 @@ export class GameRoom {
this.users = new Map<number, User>();
this.usersByUuid = new Map<string, User>();
this.admins = new Set<Admin>();
this.groups = new Set<Group>();
this.connectCallback = connectCallback;
@ -89,6 +91,10 @@ export class GameRoom {
return this.users;
}
public getUserByUuid(uuid: string): User|undefined {
return this.usersByUuid.get(uuid);
}
public join(socket : UserSocket, joinRoomMessage: JoinRoomMessage): User {
const positionMessage = joinRoomMessage.getPositionmessage();
if (positionMessage === undefined) {
@ -99,6 +105,7 @@ export class GameRoom {
const user = new User(this.nextUserId, joinRoomMessage.getUseruuid(), position, false, this.positionNotifier, socket, joinRoomMessage.getTagList(), joinRoomMessage.getName(), ProtobufUtils.toCharacterLayerObjects(joinRoomMessage.getCharacterlayerList()));
this.nextUserId++;
this.users.set(user.id, user);
this.usersByUuid.set(user.uuid, user);
// Let's call update position to trigger the join / leave room
//this.updatePosition(socket, userPosition);
this.updateUserGroup(user);
@ -120,6 +127,7 @@ export class GameRoom {
this.leaveGroup(userObj);
}
this.users.delete(user.id);
this.usersByUuid.delete(user.uuid);
if (userObj !== undefined) {
this.positionNotifier.leave(userObj);

42
back/src/RoomManager.ts

@ -1,12 +1,25 @@
import {IRoomManagerServer} from "./Messages/generated/messages_grpc_pb";
import {
AdminPusherToBackMessage,
ClientToServerMessage, ItemEventMessage,
JoinRoomMessage, PlayGlobalMessage, PusherToBackMessage, QueryJitsiJwtMessage, ReportPlayerMessage,
RoomJoinedMessage, ServerToAdminClientMessage,
ServerToClientMessage, SilentMessage, UserMovesMessage, ViewportMessage, WebRtcSignalToServerMessage, ZoneMessage
AdminGlobalMessage,
AdminMessage,
AdminPusherToBackMessage, BanMessage,
ClientToServerMessage, EmptyMessage,
ItemEventMessage,
JoinRoomMessage,
PlayGlobalMessage,
PusherToBackMessage,
QueryJitsiJwtMessage,
ReportPlayerMessage,
RoomJoinedMessage,
ServerToAdminClientMessage,
ServerToClientMessage,
SilentMessage,
UserMovesMessage,
ViewportMessage,
WebRtcSignalToServerMessage,
ZoneMessage
} from "./Messages/generated/messages_pb";
import grpc, {ServerDuplexStream, ServerWritableStream} from "grpc";
import grpc, {sendUnaryData, ServerDuplexStream, ServerUnaryCall, ServerWritableStream} from "grpc";
import {Empty} from "google-protobuf/google/protobuf/empty_pb";
import {socketManager} from "./Services/SocketManager";
import {emitError} from "./Services/MessageHelpers";
@ -171,6 +184,23 @@ const roomManager: IRoomManagerServer = {
console.error('An error occurred in joinAdminRoom stream:', err);
});
},
sendAdminMessage(call: ServerUnaryCall<AdminMessage>, callback: sendUnaryData<EmptyMessage>): void {
socketManager.sendAdminMessage(call.request.getRoomid(), call.request.getRecipientuuid(), call.request.getMessage());
callback(null, new EmptyMessage());
},
sendGlobalAdminMessage(call: ServerUnaryCall<AdminGlobalMessage>, callback: sendUnaryData<EmptyMessage>): void {
throw new Error('Not implemented yet');
// TODO
callback(null, new EmptyMessage());
},
ban(call: ServerUnaryCall<BanMessage>, callback: sendUnaryData<EmptyMessage>): void {
socketManager.banUser(call.request.getRoomid(), call.request.getRecipientuuid());
callback(null, new EmptyMessage());
},
};
export {roomManager};

92
back/src/Services/SocketManager.ts

@ -31,7 +31,7 @@ import {
BatchMessage,
BatchToPusherMessage,
SubToPusherMessage,
UserJoinedZoneMessage, GroupUpdateZoneMessage, GroupLeftZoneMessage, UserLeftZoneMessage
UserJoinedZoneMessage, GroupUpdateZoneMessage, GroupLeftZoneMessage, UserLeftZoneMessage, AdminMessage, BanMessage
} from "../Messages/generated/messages_pb";
import {User, UserSocket} from "../Model/User";
import {ProtobufUtils} from "../Model/Websocket/ProtobufUtils";
@ -164,25 +164,6 @@ export class SocketManager {
console.log('SENDING MESSAGE roomJoinedMessage');
socket.write(serverToClientMessage);
//get data information and show messages
if (ADMIN_API_URL) {
adminApi.fetchMemberDataByUuid(user.uuid).then((res: FetchMemberDataByUuidResponse) => {
if (!res.messages) {
return;
}
res.messages.forEach((c: unknown) => {
const messageToSend = c as { type: string, message: string };
socketManager.emitSendUserMessage({
userUuid: user.uuid,
type: messageToSend.type,
message: messageToSend.message
})
});
}).catch((err) => {
console.error('fetchMemberDataByUuid => err', err);
});
}
return {
room,
user
@ -643,27 +624,6 @@ export class SocketManager {
user.socket.write(serverToClientMessage);
}
public emitSendUserMessage(messageToSend: {userUuid: string, message: string, type: string}): void {
// TODO: move this to room (findByUuid)
throw new Error("Not yet reimplemented");
/*const socket = this.searchClientByUuid(messageToSend.userUuid);
if(!socket){
throw 'socket was not found';
}
const sendUserMessage = new SendUserMessage();
sendUserMessage.setMessage(messageToSend.message);
sendUserMessage.setType(messageToSend.type);
const serverToClientMessage = new ServerToClientMessage();
serverToClientMessage.setSendusermessage(sendUserMessage);
if (!socket.disconnecting) {
socket.send(serverToClientMessage.serializeBinary().buffer, true);
}
return socket;*/
}
/**
* Merges the characterLayers received from the front (as an array of string) with the custom textures from the back.
*/
@ -762,6 +722,56 @@ export class SocketManager {
}
}
public sendAdminMessage(roomId: string, recipientUuid: string, message: string): void {
const room = this.rooms.get(roomId);
if (!room) {
console.error("In sendAdminMessage, could not find room with id '" + roomId + "'. Maybe the room was closed a few milliseconds ago and there was a race condition?");
return;
}
const recipient = room.getUserByUuid(recipientUuid);
if (recipient === undefined) {
console.error("In sendAdminMessage, could not find user with id '" + recipientUuid + "'. Maybe the user left the room a few milliseconds ago and there was a race condition?");
return;
}
const sendUserMessage = new SendUserMessage();
sendUserMessage.setMessage(message);
sendUserMessage.setType('ban');
const subToPusherMessage = new SubToPusherMessage();
subToPusherMessage.setSendusermessage(sendUserMessage);
recipient.socket.write(subToPusherMessage);
}
public banUser(roomId: string, recipientUuid: string): void {
const room = this.rooms.get(roomId);
if (!room) {
console.error("In banUser, could not find room with id '" + roomId + "'. Maybe the room was closed a few milliseconds ago and there was a race condition?");
return;
}
const recipient = room.getUserByUuid(recipientUuid);
if (recipient === undefined) {
console.error("In banUser, could not find user with id '" + recipientUuid + "'. Maybe the user left the room a few milliseconds ago and there was a race condition?");
return;
}
// Let's leave the room now.
room.leave(recipient);
const sendUserMessage = new SendUserMessage();
sendUserMessage.setType('banned');
const subToPusherMessage = new SubToPusherMessage();
subToPusherMessage.setSendusermessage(sendUserMessage);
recipient.socket.write(subToPusherMessage);
// Let's close the connection when the user is banned.
recipient.socket.end();
}
}
export const socketManager = new SocketManager();

24
messages/protos/messages.proto

@ -288,6 +288,7 @@ message SubToPusherMessage {
GroupLeftZoneMessage groupLeftZoneMessage = 4;
UserLeftZoneMessage userLeftZoneMessage = 5;
ItemEventMessage itemEventMessage = 6;
SendUserMessage sendUserMessage = 7;
}
}
@ -320,9 +321,32 @@ message AdminPusherToBackMessage {
}
}
// A message sent by an administrator to a recipient
message AdminMessage {
string message = 1;
string recipientUuid = 2;
string roomId = 3;
}
// A message sent by an administrator to absolutely everybody
message AdminGlobalMessage {
string message = 1;
}
message BanMessage {
string recipientUuid = 1;
string roomId = 2;
}
message EmptyMessage {
}
service RoomManager {
rpc joinRoom(stream PusherToBackMessage) returns (stream ServerToClientMessage);
rpc listenZone(ZoneMessage) returns (stream BatchToPusherMessage);
rpc adminRoom(stream AdminPusherToBackMessage) returns (stream ServerToAdminClientMessage);
rpc sendAdminMessage(AdminMessage) returns (EmptyMessage);
rpc sendGlobalAdminMessage(AdminGlobalMessage) returns (EmptyMessage);
rpc ban(BanMessage) returns (EmptyMessage);
}

28
pusher/src/Controller/IoSocketController.ts

@ -12,7 +12,7 @@ import {
WebRtcSignalToServerMessage,
PlayGlobalMessage,
ReportPlayerMessage,
QueryJitsiJwtMessage
QueryJitsiJwtMessage, SendUserMessage, ServerToClientMessage
} from "../Messages/generated/messages_pb";
import {UserMovesMessage} from "../Messages/generated/messages_pb";
import {TemplatedApp} from "uWebSockets.js"
@ -61,7 +61,6 @@ export class IoSocketController {
},
open: (ws) => {
console.log('Admin socket connect for room: '+ws.roomId);
const roomId = ws.roomId;
ws.disconnecting = false;
socketManager.handleAdminRoom(ws as ExAdminSocketInterface, ws.roomId as string);
@ -84,6 +83,8 @@ export class IoSocketController {
},
message: (ws, arrayBuffer, isBinary): void => {
try {
const roomId = ws.roomId as string;
//TODO refactor message type and data
const message: {event: string, message: {type: string, message: unknown, userUuid: string}} =
JSON.parse(new TextDecoder("utf-8").decode(new Uint8Array(arrayBuffer)));
@ -92,14 +93,11 @@ export class IoSocketController {
const messageToEmit = (message.message as { message: string, type: string, userUuid: string });
switch (message.message.type) {
case 'ban': {
socketManager.emitSendUserMessage(messageToEmit);
socketManager.emitSendUserMessage(messageToEmit.userUuid, messageToEmit.message, roomId);
break;
}
case 'banned': {
const socketUser = socketManager.emitSendUserMessage(messageToEmit);
setTimeout(() => {
socketUser.close();
}, 10000);
socketManager.emitBan(messageToEmit.userUuid, messageToEmit.message, roomId);
break;
}
default: {
@ -269,11 +267,17 @@ export class IoSocketController {
}
res.messages.forEach((c: unknown) => {
const messageToSend = c as { type: string, message: string };
socketManager.emitSendUserMessage({
userUuid: client.userUuid,
type: messageToSend.type,
message: messageToSend.message
})
const sendUserMessage = new SendUserMessage();
sendUserMessage.setType(messageToSend.type);
sendUserMessage.setMessage(messageToSend.message);
const serverToClientMessage = new ServerToClientMessage();
serverToClientMessage.setSendusermessage(sendUserMessage);
if (!client.disconnecting) {
client.send(serverToClientMessage.serializeBinary().buffer, true);
}
});
}).catch((err) => {
console.error('fetchMemberDataByUuid => err', err);

4
pusher/src/Services/ApiClientRepository.ts

@ -15,6 +15,10 @@ class ApiClientRepository {
}
return Promise.resolve(this.roomManagerClient);
}
public async getAllClients(): Promise<RoomManagerClient[]> {
return [await this.getClient('')];
}
}
const apiClientRepository = new ApiClientRepository();

34
pusher/src/Services/SocketManager.ts

@ -30,7 +30,7 @@ import {
CharacterLayerMessage,
PusherToBackMessage,
AdminPusherToBackMessage,
ServerToAdminClientMessage
ServerToAdminClientMessage, AdminMessage, BanMessage
} from "../Messages/generated/messages_pb";
import {PointInterface} from "../Model/Websocket/PointInterface";
import {ProtobufUtils} from "../Model/Websocket/ProtobufUtils";
@ -593,7 +593,21 @@ export class SocketManager implements ZoneEventListener {
client.send(serverToClientMessage.serializeBinary().buffer, true);
}
public emitSendUserMessage(messageToSend: {userUuid: string, message: string, type: string}): ExSocketInterface {
public async emitSendUserMessage(userUuid: string, message: string, roomId: string): Promise<void> {
const backConnection = await apiClientRepository.getClient(roomId);
const adminMessage = new AdminMessage();
adminMessage.setRecipientuuid(userUuid);
adminMessage.setMessage(message);
adminMessage.setRoomid(roomId);
backConnection.sendAdminMessage(adminMessage, (error) => {
if (error !== null) {
console.error('Error while sending admin message', error);
}
});
/*
const socket = this.searchClientByUuid(messageToSend.userUuid);
if(!socket){
throw 'socket was not found';
@ -609,7 +623,21 @@ export class SocketManager implements ZoneEventListener {
if (!socket.disconnecting) {
socket.send(serverToClientMessage.serializeBinary().buffer, true);
}
return socket;
return socket;*/
}
public async emitBan(userUuid: string, message: string, roomId: string): Promise<void> {
const backConnection = await apiClientRepository.getClient(roomId);
const banMessage = new BanMessage();
banMessage.setRecipientuuid(userUuid);
banMessage.setRoomid(roomId);
backConnection.ban(banMessage, (error) => {
if (error !== null) {
console.error('Error while sending ban message', error);
}
});
}
/**

Loading…
Cancel
Save