Showing
10 changed files
with
108 additions
and
5 deletions
1 | import { Socket } from "socket.io"; | 1 | import { Socket } from "socket.io"; |
2 | import { MessageHandlerRegistry } from "../message/MessageHandlerRegistry"; | 2 | import { MessageHandlerRegistry } from "../message/MessageHandlerRegistry"; |
3 | +import { Message } from "../message/types"; | ||
4 | +import { Room } from "../room/Room"; | ||
3 | import { User } from "../user/User"; | 5 | import { User } from "../user/User"; |
4 | 6 | ||
5 | export class Connection { | 7 | export class Connection { |
6 | public readonly socket: Socket; | 8 | public readonly socket: Socket; |
7 | 9 | ||
8 | public user?: User; | 10 | public user?: User; |
11 | + public room?: Room; | ||
9 | 12 | ||
10 | constructor(socket: Socket) { | 13 | constructor(socket: Socket) { |
11 | this.socket = socket; | 14 | this.socket = socket; |
... | @@ -16,4 +19,8 @@ export class Connection { | ... | @@ -16,4 +19,8 @@ export class Connection { |
16 | public get authenticated(): boolean { | 19 | public get authenticated(): boolean { |
17 | return this.user !== undefined; | 20 | return this.user !== undefined; |
18 | } | 21 | } |
22 | + | ||
23 | + public send(message: Message) { | ||
24 | + this.socket.emit(message.type, message); | ||
25 | + } | ||
19 | } | 26 | } | ... | ... |
... | @@ -2,6 +2,7 @@ import express from "express"; | ... | @@ -2,6 +2,7 @@ import express from "express"; |
2 | import socketIo from "socket.io"; | 2 | import socketIo from "socket.io"; |
3 | import { createServer } from "http"; | 3 | import { createServer } from "http"; |
4 | import { SocketHandler } from "./SocketHandler"; | 4 | import { SocketHandler } from "./SocketHandler"; |
5 | +import { RoomManager } from "./room/RoomManager"; | ||
5 | 6 | ||
6 | const PORT = 3000; | 7 | const PORT = 3000; |
7 | 8 | ||
... | @@ -10,6 +11,7 @@ const server = createServer(app); | ... | @@ -10,6 +11,7 @@ const server = createServer(app); |
10 | const io = new socketIo.Server(server); | 11 | const io = new socketIo.Server(server); |
11 | 12 | ||
12 | const handler = new SocketHandler(); | 13 | const handler = new SocketHandler(); |
14 | +const roomManager = new RoomManager(); | ||
13 | 15 | ||
14 | io.on("connection", (socket) => { | 16 | io.on("connection", (socket) => { |
15 | handler.connected(socket); | 17 | handler.connected(socket); | ... | ... |
1 | import { Connection } from "../connection/Connection"; | 1 | import { Connection } from "../connection/Connection"; |
2 | import { loginHandler } from "./handler/loginHandler"; | 2 | import { loginHandler } from "./handler/loginHandler"; |
3 | -import { MessageType } from "./types"; | 3 | +import { roomJoinHandler } from "./handler/roomJoinHandler"; |
4 | +import { roomLeaveHandler } from "./handler/roomLeaveHandler"; | ||
5 | +import { Message, MessageType } from "./types"; | ||
4 | 6 | ||
5 | export class MessageHandlerRegistry { | 7 | export class MessageHandlerRegistry { |
6 | static registerHandlers(connection: Connection) { | 8 | static registerHandlers(connection: Connection) { |
7 | this.registerHandler(connection, MessageType.LOGIN, loginHandler); | 9 | this.registerHandler(connection, MessageType.LOGIN, loginHandler); |
10 | + this.registerHandler(connection, MessageType.ROOM_JOIN, roomJoinHandler); | ||
11 | + this.registerHandler(connection, MessageType.ROOM_LEAVE, roomLeaveHandler); | ||
8 | } | 12 | } |
9 | 13 | ||
10 | - private static registerHandler<T>( | 14 | + private static registerHandler<T extends Message>( |
11 | connection: Connection, | 15 | connection: Connection, |
12 | typeName: string, | 16 | typeName: string, |
13 | handler: (connection: Connection, message: T) => void | 17 | handler: (connection: Connection, message: T) => void | ... | ... |
1 | import { Connection } from "../../connection/Connection"; | 1 | import { Connection } from "../../connection/Connection"; |
2 | +import { RoomManager } from "../../room/RoomManager"; | ||
2 | import { User } from "../../user/User"; | 3 | import { User } from "../../user/User"; |
3 | import { LoginMessage } from "../types"; | 4 | import { LoginMessage } from "../types"; |
4 | 5 | ||
... | @@ -8,4 +9,6 @@ export function loginHandler( | ... | @@ -8,4 +9,6 @@ export function loginHandler( |
8 | ): void { | 9 | ): void { |
9 | connection.user = new User(message.username); | 10 | connection.user = new User(message.username); |
10 | console.log(`User ${message.username} has logged in!`); | 11 | console.log(`User ${message.username} has logged in!`); |
12 | + | ||
13 | + RoomManager.instance().sendList(connection); | ||
11 | } | 14 | } | ... | ... |
server/message/handler/roomJoinHandler.ts
0 → 100644
1 | +import { Connection } from "../../connection/Connection"; | ||
2 | +import { RoomManager } from "../../room/RoomManager"; | ||
3 | +import { RoomJoinMessage } from "../types"; | ||
4 | + | ||
5 | +export function roomJoinHandler( | ||
6 | + connection: Connection, | ||
7 | + message: RoomJoinMessage | ||
8 | +): void { | ||
9 | + const room = RoomManager.instance().get(message.uuid); | ||
10 | + if (room !== undefined) { | ||
11 | + room.connect(connection); | ||
12 | + } | ||
13 | +} |
server/message/handler/roomLeaveHandler.ts
0 → 100644
1 | +import { Connection } from "../../connection/Connection"; | ||
2 | +import { RoomManager } from "../../room/RoomManager"; | ||
3 | +import { RoomLeaveMessage } from "../types"; | ||
4 | + | ||
5 | +export function roomLeaveHandler( | ||
6 | + connection: Connection, | ||
7 | + message: RoomLeaveMessage | ||
8 | +): void { | ||
9 | + if (connection.room !== undefined) { | ||
10 | + connection.room.disconnect(connection); | ||
11 | + } | ||
12 | +} |
1 | -export interface LoginMessage { | 1 | +import { RoomData } from "../room/types"; |
2 | - username: string; | 2 | + |
3 | +export interface Message { | ||
4 | + readonly type: string; | ||
5 | +} | ||
6 | + | ||
7 | +export class LoginMessage implements Message { | ||
8 | + readonly type = MessageType.LOGIN; | ||
9 | + constructor(public username: string) {} | ||
10 | +} | ||
11 | + | ||
12 | +export class RoomListMessage implements Message { | ||
13 | + readonly type = MessageType.ROOM_LIST; | ||
14 | + constructor(public rooms: RoomData[]) {} | ||
15 | +} | ||
16 | + | ||
17 | +export class RoomJoinMessage implements Message { | ||
18 | + readonly type = MessageType.ROOM_JOIN; | ||
19 | + constructor(public uuid: string) {} | ||
20 | +} | ||
21 | + | ||
22 | +export class RoomLeaveMessage implements Message { | ||
23 | + readonly type = MessageType.ROOM_LEAVE; | ||
24 | + constructor() {} | ||
3 | } | 25 | } |
4 | 26 | ||
5 | export class MessageType { | 27 | export class MessageType { |
6 | static readonly LOGIN = "login"; | 28 | static readonly LOGIN = "login"; |
29 | + static readonly ROOM_LIST = "room_list"; | ||
30 | + static readonly ROOM_JOIN = "room_join"; | ||
31 | + static readonly ROOM_LEAVE = "room_leave"; | ||
7 | } | 32 | } | ... | ... |
1 | import { Connection } from "../connection/Connection"; | 1 | import { Connection } from "../connection/Connection"; |
2 | import { v4 as uuidv4 } from "uuid"; | 2 | import { v4 as uuidv4 } from "uuid"; |
3 | +import { RoomData } from "./types"; | ||
3 | 4 | ||
4 | export class Room { | 5 | export class Room { |
5 | public readonly uuid: string; | 6 | public readonly uuid: string; |
... | @@ -26,18 +27,29 @@ export class Room { | ... | @@ -26,18 +27,29 @@ export class Room { |
26 | } | 27 | } |
27 | 28 | ||
28 | this.connections.push(connection); | 29 | this.connections.push(connection); |
30 | + connection.room = this; // TODO: 더 나은 관리 | ||
29 | } | 31 | } |
30 | 32 | ||
31 | public disconnect(connection: Connection): void { | 33 | public disconnect(connection: Connection): void { |
32 | const index = this.connections.indexOf(connection); | 34 | const index = this.connections.indexOf(connection); |
33 | if (index > -1) { | 35 | if (index > -1) { |
34 | this.connections.splice(index, 1); | 36 | this.connections.splice(index, 1); |
37 | + connection.room = undefined; | ||
35 | } | 38 | } |
36 | } | 39 | } |
37 | 40 | ||
41 | + public getData(): RoomData { | ||
42 | + return { | ||
43 | + uuid: this.uuid, | ||
44 | + name: this.name, | ||
45 | + currentConnections: this.connections.length, | ||
46 | + maxConnections: this.maxConnections, | ||
47 | + }; | ||
48 | + } | ||
49 | + | ||
38 | public close(): void { | 50 | public close(): void { |
39 | if (!this.closed) { | 51 | if (!this.closed) { |
40 | - // TODO | 52 | + this.connections.forEach((connection) => this.disconnect(connection)); |
41 | this.closed = true; | 53 | this.closed = true; |
42 | } | 54 | } |
43 | } | 55 | } | ... | ... |
1 | +import { Connection } from "../connection/Connection"; | ||
2 | +import { RoomListMessage } from "../message/types"; | ||
1 | import { Room } from "./Room"; | 3 | import { Room } from "./Room"; |
4 | +import { RoomData } from "./types"; | ||
2 | 5 | ||
3 | export class RoomManager { | 6 | export class RoomManager { |
7 | + private static _instance: RoomManager; | ||
8 | + | ||
4 | private rooms: Map<string, Room>; | 9 | private rooms: Map<string, Room>; |
5 | 10 | ||
6 | constructor() { | 11 | constructor() { |
12 | + RoomManager._instance = this; | ||
7 | this.rooms = new Map<string, Room>(); | 13 | this.rooms = new Map<string, Room>(); |
8 | } | 14 | } |
9 | 15 | ||
16 | + public static instance(): RoomManager { | ||
17 | + return RoomManager._instance; | ||
18 | + } | ||
19 | + | ||
10 | public create(name: string, maxConnections: number): Room { | 20 | public create(name: string, maxConnections: number): Room { |
11 | const room = new Room(name, maxConnections); | 21 | const room = new Room(name, maxConnections); |
12 | this.rooms.set(name, room); | 22 | this.rooms.set(name, room); |
... | @@ -24,4 +34,13 @@ export class RoomManager { | ... | @@ -24,4 +34,13 @@ export class RoomManager { |
24 | this.rooms.delete(uuid); | 34 | this.rooms.delete(uuid); |
25 | } | 35 | } |
26 | } | 36 | } |
37 | + | ||
38 | + public sendList(connection: Connection): void { | ||
39 | + var roomData: RoomData[] = []; | ||
40 | + this.rooms.forEach((room) => { | ||
41 | + roomData.push(room.getData()); | ||
42 | + }); | ||
43 | + | ||
44 | + connection.send(new RoomListMessage(roomData)); | ||
45 | + } | ||
27 | } | 46 | } | ... | ... |
-
Please register or login to post a comment