Refactoring searchClientById
searchClientById was scanning through all open sockets to find the right one (which is inefficient if we have many). Instead, I created a new Map that directly maps ids to sockets. Furthermore, this solves a long-standing issue (when a socket is disconnected, we cannot find it anymore in the sockets list but it is still available in the disconnect callback from the map) As a result, we should not have any remaining circles any more.
This commit is contained in:
parent
2628373b56
commit
e934015d87
@ -30,6 +30,7 @@ enum SockerIoEvent {
|
|||||||
export class IoSocketController {
|
export class IoSocketController {
|
||||||
Io: socketIO.Server;
|
Io: socketIO.Server;
|
||||||
Worlds: Map<string, World> = new Map<string, World>();
|
Worlds: Map<string, World> = new Map<string, World>();
|
||||||
|
sockets: Map<string, ExSocketInterface> = new Map<string, ExSocketInterface>();
|
||||||
|
|
||||||
constructor(server: http.Server) {
|
constructor(server: http.Server) {
|
||||||
this.Io = socketIO(server);
|
this.Io = socketIO(server);
|
||||||
@ -60,10 +61,7 @@ export class IoSocketController {
|
|||||||
// Let's get the room of the group. To do this, let's get anyone in the group and find its room.
|
// 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
|
// Note: this is suboptimal
|
||||||
let userId = group.getUsers()[0].id;
|
let userId = group.getUsers()[0].id;
|
||||||
let client: ExSocketInterface|null = this.searchClientById(userId);
|
let client: ExSocketInterface = this.searchClientByIdOrFail(userId);
|
||||||
if (client === null) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
let roomId = client.roomId;
|
let roomId = client.roomId;
|
||||||
this.Io.in(roomId).emit(SockerIoEvent.GROUP_CREATE_UPDATE, {
|
this.Io.in(roomId).emit(SockerIoEvent.GROUP_CREATE_UPDATE, {
|
||||||
position: group.getPosition(),
|
position: group.getPosition(),
|
||||||
@ -73,19 +71,15 @@ export class IoSocketController {
|
|||||||
|
|
||||||
private sendDeleteGroupEvent(uuid: string, lastUser: UserInterface): void {
|
private sendDeleteGroupEvent(uuid: string, lastUser: UserInterface): void {
|
||||||
// Let's get the room of the group. To do this, let's get anyone in the group and find its room.
|
// 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
|
|
||||||
let userId = lastUser.id;
|
let userId = lastUser.id;
|
||||||
let client: ExSocketInterface|null = this.searchClientById(userId);
|
let client: ExSocketInterface = this.searchClientByIdOrFail(userId);
|
||||||
if (client === null) {
|
|
||||||
console.warn('Could not find client ', userId, ' in group')
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
let roomId = client.roomId;
|
let roomId = client.roomId;
|
||||||
this.Io.in(roomId).emit(SockerIoEvent.GROUP_DELETE, uuid);
|
this.Io.in(roomId).emit(SockerIoEvent.GROUP_DELETE, uuid);
|
||||||
}
|
}
|
||||||
|
|
||||||
ioConnection() {
|
ioConnection() {
|
||||||
this.Io.on(SockerIoEvent.CONNECTION, (socket: Socket) => {
|
this.Io.on(SockerIoEvent.CONNECTION, (socket: Socket) => {
|
||||||
|
this.sockets.set(socket.id, socket as ExSocketInterface);
|
||||||
/*join-rom event permit to join one room.
|
/*join-rom event permit to join one room.
|
||||||
message :
|
message :
|
||||||
userId : user identification
|
userId : user identification
|
||||||
@ -148,20 +142,19 @@ export class IoSocketController {
|
|||||||
|
|
||||||
socket.on(SockerIoEvent.WEBRTC_SIGNAL, (data: any) => {
|
socket.on(SockerIoEvent.WEBRTC_SIGNAL, (data: any) => {
|
||||||
//send only at user
|
//send only at user
|
||||||
let client = this.searchClientById(data.receiverId);
|
let client = this.sockets.get(data.receiverId);
|
||||||
if (!client) {
|
if (client === undefined) {
|
||||||
console.error("While exchanging a WebRTC signal: client doesn't exist for ", data.receiverId);
|
console.warn("While exchanging a WebRTC signal: client with id ", data.receiverId, " does not exist. This might be a race condition.");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
return client.emit(SockerIoEvent.WEBRTC_SIGNAL, data);
|
return client.emit(SockerIoEvent.WEBRTC_SIGNAL, data);
|
||||||
});
|
});
|
||||||
|
|
||||||
socket.on(SockerIoEvent.WEBRTC_OFFER, (data: any) => {
|
socket.on(SockerIoEvent.WEBRTC_OFFER, (data: any) => {
|
||||||
|
|
||||||
//send only at user
|
//send only at user
|
||||||
let client = this.searchClientById(data.receiverId);
|
let client = this.sockets.get(data.receiverId);
|
||||||
if (!client) {
|
if (client === undefined) {
|
||||||
console.error("client doesn't exist for ", data.receiverId);
|
console.warn("While exchanging a WebRTC offer: client with id ", data.receiverId, " does not exist. This might be a race condition.");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
client.emit(SockerIoEvent.WEBRTC_OFFER, data);
|
client.emit(SockerIoEvent.WEBRTC_OFFER, data);
|
||||||
@ -170,16 +163,16 @@ export class IoSocketController {
|
|||||||
socket.on(SockerIoEvent.DISCONNECT, () => {
|
socket.on(SockerIoEvent.DISCONNECT, () => {
|
||||||
try {
|
try {
|
||||||
let Client = (socket as ExSocketInterface);
|
let Client = (socket as ExSocketInterface);
|
||||||
this.sendDisconnectedEvent(Client);
|
//this.sendDisconnectedEvent(Client);
|
||||||
|
|
||||||
//refresh position of all user in all rooms in real time
|
//refresh position of all user in all rooms in real time (to remove the disconnected user)
|
||||||
this.refreshUserPosition(Client);
|
this.refreshUserPosition(Client);
|
||||||
|
|
||||||
//leave room
|
//leave room
|
||||||
this.leaveRoom(Client);
|
this.leaveRoom(Client);
|
||||||
|
|
||||||
//leave webrtc room
|
//leave webrtc room
|
||||||
socket.leave(Client.webRtcRoomId);
|
//socket.leave(Client.webRtcRoomId);
|
||||||
|
|
||||||
//delete all socket information
|
//delete all socket information
|
||||||
delete Client.webRtcRoomId;
|
delete Client.webRtcRoomId;
|
||||||
@ -190,6 +183,7 @@ export class IoSocketController {
|
|||||||
console.error('An error occurred on "disconnect"');
|
console.error('An error occurred on "disconnect"');
|
||||||
console.error(e);
|
console.error(e);
|
||||||
}
|
}
|
||||||
|
this.sockets.delete(socket.id);
|
||||||
});
|
});
|
||||||
|
|
||||||
// Let's send the user id to the user
|
// Let's send the user id to the user
|
||||||
@ -202,55 +196,13 @@ export class IoSocketController {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
searchClientByIdOrFail(userId: string): ExSocketInterface {
|
||||||
* TODO: each call to this method is suboptimal. It means that instead of passing an ID, we should pass a client object.
|
let client: ExSocketInterface|undefined = this.sockets.get(userId);
|
||||||
* @param userId
|
if (client === undefined) {
|
||||||
*/
|
throw new Error("Could not find user with id " + userId);
|
||||||
searchClientById(userId: string): ExSocketInterface | null {
|
|
||||||
let clients: Array<any> = Object.values(this.Io.sockets.sockets);
|
|
||||||
for (let i = 0; i < clients.length; i++) {
|
|
||||||
let client: ExSocketInterface = clients[i];
|
|
||||||
if (client.id !== userId) {
|
|
||||||
continue;
|
|
||||||
}
|
}
|
||||||
return client;
|
return client;
|
||||||
}
|
}
|
||||||
console.log("Could not find user with id ", userId);
|
|
||||||
//throw new Error("Could not find user with id " + userId);
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param userId
|
|
||||||
*/
|
|
||||||
searchClientByToken(userId: string): ExSocketInterface | null {
|
|
||||||
let clients: Array<any> = Object.values(this.Io.sockets.sockets);
|
|
||||||
for (let i = 0; i < clients.length; i++) {
|
|
||||||
let client: ExSocketInterface = clients[i];
|
|
||||||
if (client.id !== userId) {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
return client;
|
|
||||||
}
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
*
|
|
||||||
* @param Client: ExSocketInterface
|
|
||||||
*/
|
|
||||||
sendDisconnectedEvent(Client: ExSocketInterface) {
|
|
||||||
Client.broadcast.emit(SockerIoEvent.WEBRTC_DISCONNECT, {
|
|
||||||
userId: Client.id
|
|
||||||
});
|
|
||||||
|
|
||||||
//disconnect webrtc room
|
|
||||||
if(!Client.webRtcRoomId){
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
Client.leave(Client.webRtcRoomId);
|
|
||||||
delete Client.webRtcRoomId;
|
|
||||||
}
|
|
||||||
|
|
||||||
leaveRoom(Client : ExSocketInterface){
|
leaveRoom(Client : ExSocketInterface){
|
||||||
//lease previous room and world
|
//lease previous room and world
|
||||||
@ -349,12 +301,11 @@ export class IoSocketController {
|
|||||||
rooms.refreshUserPosition(rooms, this.Io);
|
rooms.refreshUserPosition(rooms, this.Io);
|
||||||
|
|
||||||
// update position in the world
|
// update position in the world
|
||||||
let messageUserPosition = new MessageUserPosition(Client.id, Client.name, Client.character, Client.position);
|
|
||||||
let world = this.Worlds.get(Client.roomId);
|
let world = this.Worlds.get(Client.roomId);
|
||||||
if (!world) {
|
if (!world) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
world.updatePosition(Client, messageUserPosition.position);
|
world.updatePosition(Client, Client.position);
|
||||||
this.Worlds.set(Client.roomId, world);
|
this.Worlds.set(Client.roomId, world);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -412,19 +363,26 @@ export class IoSocketController {
|
|||||||
|
|
||||||
//connected user
|
//connected user
|
||||||
connectedUser(userId: string, group: Group) {
|
connectedUser(userId: string, group: Group) {
|
||||||
let Client = this.searchClientById(userId);
|
/*let Client = this.sockets.get(userId);
|
||||||
if (!Client) {
|
if (Client === undefined) {
|
||||||
return;
|
return;
|
||||||
}
|
}*/
|
||||||
|
let Client = this.searchClientByIdOrFail(userId);
|
||||||
this.joinWebRtcRoom(Client, group.getId());
|
this.joinWebRtcRoom(Client, group.getId());
|
||||||
}
|
}
|
||||||
|
|
||||||
//disconnect user
|
//disconnect user
|
||||||
disConnectedUser(userId: string, group: Group) {
|
disConnectedUser(userId: string, group: Group) {
|
||||||
let Client = this.searchClientById(userId);
|
let Client = this.searchClientByIdOrFail(userId);
|
||||||
if (!Client) {
|
Client.to(group.getId()).emit(SockerIoEvent.WEBRTC_DISCONNECT, {
|
||||||
|
userId: userId
|
||||||
|
});
|
||||||
|
|
||||||
|
//disconnect webrtc room
|
||||||
|
if(!Client.webRtcRoomId){
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
this.sendDisconnectedEvent(Client)
|
Client.leave(Client.webRtcRoomId);
|
||||||
|
delete Client.webRtcRoomId;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -60,7 +60,6 @@ export class World {
|
|||||||
public leave(user : Identificable){
|
public leave(user : Identificable){
|
||||||
let userObj = this.users.get(user.id);
|
let userObj = this.users.get(user.id);
|
||||||
if (userObj === undefined) {
|
if (userObj === undefined) {
|
||||||
// FIXME: this seems always wrong. I guess user.id is different from userPosition.userId
|
|
||||||
console.warn('User ', user.id, 'does not belong to world! It should!');
|
console.warn('User ', user.id, 'does not belong to world! It should!');
|
||||||
}
|
}
|
||||||
if (userObj !== undefined && typeof userObj.group !== 'undefined') {
|
if (userObj !== undefined && typeof userObj.group !== 'undefined') {
|
||||||
|
Loading…
Reference in New Issue
Block a user