Skip to content

Commit f5d3996

Browse files
committed
feat: add protocol version checking
- Welcome message now includes protocolVersion field - Optional hello message: clients can send { type: "hello", protocolVersion } to verify compatibility — server rejects mismatched versions - Backwards compatible: clients that skip hello still work - Add BAD_PROTOCOL error code
1 parent d0d3b11 commit f5d3996

File tree

3 files changed

+23
-2
lines changed

3 files changed

+23
-2
lines changed

src/index.ts

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { decodeMessage, encodeMessage, ErrorCodes } from './protocol';
1+
import { decodeMessage, encodeMessage, ErrorCodes, PROTOCOL_VERSION } from './protocol';
22
import { Room } from './room';
33
import { RateLimiter } from './rate-limit';
44
import { getHealthResponse, getMetricsResponse } from './health';
@@ -123,6 +123,20 @@ const server = Bun.serve<WSData>({
123123
return;
124124
}
125125

126+
// Handle hello (optional protocol version check)
127+
if (decoded.type === 'hello') {
128+
const clientVersion = decoded.protocolVersion;
129+
if (typeof clientVersion === 'number' && clientVersion !== PROTOCOL_VERSION) {
130+
ws.sendBinary(encodeMessage({
131+
type: 'error',
132+
code: ErrorCodes.BAD_PROTOCOL,
133+
message: `Protocol mismatch. Server=${PROTOCOL_VERSION}, Client=${clientVersion}`,
134+
}));
135+
ws.close(1008, 'BAD_PROTOCOL');
136+
}
137+
return; // hello is consumed, not relayed
138+
}
139+
126140
// Handle ping
127141
if (decoded.type === 'ping' && typeof decoded.nonce === 'string') {
128142
ws.sendBinary(encodeMessage({

src/protocol.ts

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,14 @@
11
import { encode, decode } from '@msgpack/msgpack';
22

3+
// ─── Protocol Version ─────────────────────────────────────────────
4+
5+
export const PROTOCOL_VERSION = 1;
6+
37
// ─── Server → Client Messages ─────────────────────────────────────
48

59
export type WelcomeMessage = {
610
type: 'welcome';
11+
protocolVersion: number;
712
playerId: string;
813
peers: string[];
914
};
@@ -83,4 +88,5 @@ export const ErrorCodes = {
8388
RATE_LIMITED: 'RATE_LIMITED',
8489
ROOM_FULL: 'ROOM_FULL',
8590
INVALID_MESSAGE: 'INVALID_MESSAGE',
91+
BAD_PROTOCOL: 'BAD_PROTOCOL',
8692
} as const;

src/room.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import type { ServerWebSocket } from 'bun';
2-
import { encodeMessage, type ServerMessage, ErrorCodes } from './protocol';
2+
import { encodeMessage, PROTOCOL_VERSION, type ServerMessage, ErrorCodes } from './protocol';
33
import type { WSData } from './index';
44

55
export interface Peer {
@@ -67,6 +67,7 @@ export class Room {
6767
// Send welcome to the new peer with list of existing peers
6868
ws.sendBinary(encodeMessage({
6969
type: 'welcome',
70+
protocolVersion: PROTOCOL_VERSION,
7071
playerId: id,
7172
peers: existingPeerIds,
7273
}));

0 commit comments

Comments
 (0)