Skip to content

Commit 5a664a1

Browse files
committed
fix: add lobby verification lock and sockets gateway disconnect handler
Wrap matchmaking verify+setLobbyDetails+addLobbyToQueue in a Redis lock to prevent a banned player from bypassing verification between the check and queue addition. Add handleDisconnect lifecycle hook to SocketsGateway and make handleConnection public for proper NestJS gateway lifecycle support.
1 parent c4ee3d7 commit 5a664a1

3 files changed

Lines changed: 26 additions & 9 deletions

File tree

src/matchmaking/matchmaking.gateway.ts

Lines changed: 19 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import { e_match_types_enum } from "generated";
44
import { MatchmakeService } from "./matchmake.service";
55
import { MatchmakingLobbyService } from "./matchmaking-lobby.service";
66
import { RedisManagerService } from "../redis/redis-manager/redis-manager.service";
7+
import { CacheService } from "src/cache/cache.service";
78
import { FiveStackWebSocketClient } from "src/sockets/types/FiveStackWebSocketClient";
89
import {
910
ConnectedSocket,
@@ -12,6 +13,7 @@ import {
1213
WebSocketGateway,
1314
} from "@nestjs/websockets";
1415
import { JoinQueueError } from "./utilities/joinQueueError";
16+
import { PlayerLobby } from "./types/PlayerLobby";
1517
import { HasuraService } from "src/hasura/hasura.service";
1618
import { isRoleAbove } from "src/utilities/isRoleAbove";
1719
import { e_player_roles_enum } from "generated";
@@ -29,6 +31,7 @@ export class MatchmakingGateway {
2931
public readonly redisManager: RedisManagerService,
3032
public readonly matchmakeService: MatchmakeService,
3133
public readonly matchmakingLobbyService: MatchmakingLobbyService,
34+
private readonly cache: CacheService,
3235
) {
3336
this.redis = this.redisManager.getConnection();
3437
}
@@ -122,7 +125,7 @@ export class MatchmakingGateway {
122125
throw new JoinQueueError("You do not have permission to join this queue");
123126
}
124127

125-
let lobby;
128+
let lobby: PlayerLobby | undefined;
126129
const user = client.user;
127130

128131
if (!user) {
@@ -220,16 +223,24 @@ export class MatchmakingGateway {
220223
throw new JoinQueueError("Unable to find Player Lobby");
221224
}
222225

223-
await this.matchmakingLobbyService.verifyLobby(lobby, user, type);
224-
225226
try {
226-
await this.matchmakingLobbyService.setLobbyDetails(
227-
regions,
228-
type,
229-
lobby,
227+
await this.cache.lock(
228+
`matchmaking:verify:${lobby.id}`,
229+
async () => {
230+
await this.matchmakingLobbyService.verifyLobby(lobby, user, type);
231+
await this.matchmakingLobbyService.setLobbyDetails(
232+
regions,
233+
type,
234+
lobby,
235+
);
236+
await this.matchmakeService.addLobbyToQueue(lobby.id);
237+
return true;
238+
},
230239
);
231-
await this.matchmakeService.addLobbyToQueue(lobby.id);
232240
} catch (error) {
241+
if (error instanceof JoinQueueError) {
242+
throw error;
243+
}
233244
this.logger.error(`unable to add lobby to queue`, error);
234245
await this.matchmakingLobbyService.removeLobbyFromQueue(lobby.id);
235246
await this.matchmakingLobbyService.removeLobbyDetails(lobby.id);

src/matchmaking/matchmaking.module.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ import { loggerFactory } from "../utilities/LoggerFactory";
33
import { MatchmakingGateway } from "./matchmaking.gateway";
44
import { HasuraModule } from "src/hasura/hasura.module";
55
import { RedisModule } from "src/redis/redis.module";
6+
import { CacheModule } from "src/cache/cache.module";
67
import { MatchesModule } from "src/matches/matches.module";
78
import { MatchmakeService } from "./matchmake.service";
89
import { MatchmakingLobbyService } from "./matchmaking-lobby.service";
@@ -19,6 +20,7 @@ import { MarkPlayerOffline } from "./jobs/MarkPlayerOffline";
1920
imports: [
2021
RedisModule,
2122
HasuraModule,
23+
CacheModule,
2224
forwardRef(() => MatchesModule),
2325
BullModule.registerQueue({
2426
name: MatchmakingQueues.Matchmaking,

src/sockets/sockets.gateway.ts

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,10 +22,14 @@ export class SocketsGateway {
2222
await this.sockets.updateClient(client.user.steam_id, client.id);
2323
}
2424

25-
private async handleConnection(
25+
public async handleConnection(
2626
@ConnectedSocket() client: FiveStackWebSocketClient,
2727
request: Request,
2828
) {
2929
await this.sockets.setupSocket(client, request);
3030
}
31+
32+
public handleDisconnect(client: FiveStackWebSocketClient) {
33+
// Cleanup is handled by client.on("close") in SocketsService.setupSocket
34+
}
3135
}

0 commit comments

Comments
 (0)