diff --git a/server/src/presentation/socket/VideoSocketManager.ts b/server/src/presentation/socket/VideoSocketManager.ts index 161a87e1..46c3fccd 100644 --- a/server/src/presentation/socket/VideoSocketManager.ts +++ b/server/src/presentation/socket/VideoSocketManager.ts @@ -3,6 +3,7 @@ import logger from "../../utils/logger"; export default class VideoSocketManager { private io: Namespace; + constructor(io: Server) { this.io = io.of("/video"); this.initializeVideoNamespace(); @@ -11,32 +12,78 @@ export default class VideoSocketManager { private initializeVideoNamespace() { this.io.on("connection", (socket: Socket) => { - logger.info(`User connected to Video namespace: ${socket.id}`); - // Join a video room - socket.on("join-room", (roomId) => { - socket.join(roomId); - logger.info(`User ${socket.id} joined video room ${roomId}`); + socket.on("join-room", (roomId: string) => { + if (roomId) { + socket.join(roomId); + logger.info(`Socket ${socket.id} joined room ${roomId}`); + } else { + logger.warn(`Socket ${socket.id} attempted to join a room without a roomId`); + } }); - // Handle WebRTC offer signaling - socket.on("offer", (offer, roomId) => { - this.io.to(roomId).emit("offer", offer); + socket.on("offer", (offer: RTCSessionDescriptionInit, roomId: string) => { + try { + if (offer && roomId) { + this.io.to(roomId).emit("offer", offer); + } else { + logger.warn(`Invalid offer or roomId received from socket ${socket.id}`); + } + } catch (error:any) { + logger.error(`Error handling offer from socket ${socket.id}: ${error.message}`); + } }); // Handle WebRTC answer signaling - socket.on("answer", (answer, roomId) => { - this.io.to(roomId).emit("answer", answer); + socket.on("answer", (answer: RTCSessionDescriptionInit, roomId: string) => { + try { + if (answer && roomId) { + this.io.to(roomId).emit("answer", answer); + logger.info(`Answer sent to room ${roomId} by socket ${socket.id}`); + } else { + logger.warn(`Invalid answer or roomId received from socket ${socket.id}`); + } + } catch (error:any) { + logger.error(`Error handling answer from socket ${socket.id}: ${error.message}`); + } }); - // Handle ICE candidate signaling - socket.on("ice-candidate", (candidate, roomId) => { - this.io.to(roomId).emit("ice-candidate", candidate); + socket.on("ice-candidate", (candidate: RTCIceCandidate, roomId: string) => { + try { + if (candidate && roomId) { + this.io.to(roomId).emit("ice-candidate", candidate); + } else { + logger.warn(`Invalid ICE candidate or roomId received from socket ${socket.id}`); + } + } catch (error:any) { + logger.error(`Error handling ICE candidate from socket ${socket.id}: ${error.message}`); + } }); - // Handle video disconnection socket.on("disconnect", () => { - logger.warn(`User disconnected from Video namespace: ${socket.id}`); + this.handleUserDisconnection(socket); + }); + + socket.on("leave-room", (roomId: string) => { + if (roomId) { + socket.leave(roomId); + this.notifyRoomAboutLeaving(roomId, socket.id); + } else { + logger.warn(`Socket ${socket.id} attempted to leave a room without a roomId`); + } }); }); } + + private notifyRoomAboutLeaving(roomId: string, socketId: string) { + this.io.to(roomId).emit("user-left", { userId: socketId }); + } + + // Handle user disconnection and cleanup + private handleUserDisconnection(socket: Socket) { + const rooms = Array.from(socket.rooms).filter(room => room !== socket.id); + rooms.forEach((roomId) => { + socket.leave(roomId); + this.notifyRoomAboutLeaving(roomId, socket.id); + }); + } }