twinwire 0.0.0-stage → 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (95) hide show
  1. package/CHANGELOG.md +29 -0
  2. package/LICENSE +21 -0
  3. package/README.md +128 -2
  4. package/dist/browser/twinwire.js +2075 -0
  5. package/dist/browser/twinwire.js.map +7 -0
  6. package/dist/browser/twinwire.min.js +1 -0
  7. package/dist/browser/twinwire.mjs +2052 -0
  8. package/dist/browser/twinwire.mjs.map +7 -0
  9. package/dist/browser.d.ts +5 -0
  10. package/dist/browser.js +6 -0
  11. package/dist/browser.js.map +1 -0
  12. package/dist/client/client.d.ts +128 -0
  13. package/dist/client/client.js +470 -0
  14. package/dist/client/client.js.map +1 -0
  15. package/dist/client/index.d.ts +3 -0
  16. package/dist/client/index.js +4 -0
  17. package/dist/client/index.js.map +1 -0
  18. package/dist/client/lobby.d.ts +40 -0
  19. package/dist/client/lobby.js +122 -0
  20. package/dist/client/lobby.js.map +1 -0
  21. package/dist/client/rtc.d.ts +17 -0
  22. package/dist/client/rtc.js +102 -0
  23. package/dist/client/rtc.js.map +1 -0
  24. package/dist/core/budget.d.ts +27 -0
  25. package/dist/core/budget.js +39 -0
  26. package/dist/core/budget.js.map +1 -0
  27. package/dist/core/endpoint.d.ts +144 -0
  28. package/dist/core/endpoint.js +501 -0
  29. package/dist/core/endpoint.js.map +1 -0
  30. package/dist/core/lobby.d.ts +59 -0
  31. package/dist/core/lobby.js +53 -0
  32. package/dist/core/lobby.js.map +1 -0
  33. package/dist/core/protocol.d.ts +52 -0
  34. package/dist/core/protocol.js +100 -0
  35. package/dist/core/protocol.js.map +1 -0
  36. package/dist/core/reliable.d.ts +52 -0
  37. package/dist/core/reliable.js +116 -0
  38. package/dist/core/reliable.js.map +1 -0
  39. package/dist/core/rtc.d.ts +28 -0
  40. package/dist/core/rtc.js +21 -0
  41. package/dist/core/rtc.js.map +1 -0
  42. package/dist/index.d.ts +6 -0
  43. package/dist/index.js +7 -0
  44. package/dist/index.js.map +1 -0
  45. package/dist/netcode/clock.d.ts +15 -0
  46. package/dist/netcode/clock.js +37 -0
  47. package/dist/netcode/clock.js.map +1 -0
  48. package/dist/netcode/codec.d.ts +10 -0
  49. package/dist/netcode/codec.js +95 -0
  50. package/dist/netcode/codec.js.map +1 -0
  51. package/dist/netcode/index.d.ts +9 -0
  52. package/dist/netcode/index.js +10 -0
  53. package/dist/netcode/index.js.map +1 -0
  54. package/dist/netcode/inputs.d.ts +7 -0
  55. package/dist/netcode/inputs.js +43 -0
  56. package/dist/netcode/inputs.js.map +1 -0
  57. package/dist/netcode/interpolation.d.ts +44 -0
  58. package/dist/netcode/interpolation.js +101 -0
  59. package/dist/netcode/interpolation.js.map +1 -0
  60. package/dist/netcode/prediction.d.ts +40 -0
  61. package/dist/netcode/prediction.js +97 -0
  62. package/dist/netcode/prediction.js.map +1 -0
  63. package/dist/netcode/replication.d.ts +36 -0
  64. package/dist/netcode/replication.js +90 -0
  65. package/dist/netcode/replication.js.map +1 -0
  66. package/dist/netcode/snapshots.d.ts +29 -0
  67. package/dist/netcode/snapshots.js +78 -0
  68. package/dist/netcode/snapshots.js.map +1 -0
  69. package/dist/netcode/spatial.d.ts +16 -0
  70. package/dist/netcode/spatial.js +63 -0
  71. package/dist/netcode/spatial.js.map +1 -0
  72. package/dist/netcode/timing.d.ts +37 -0
  73. package/dist/netcode/timing.js +41 -0
  74. package/dist/netcode/timing.js.map +1 -0
  75. package/dist/server/index.d.ts +4 -0
  76. package/dist/server/index.js +5 -0
  77. package/dist/server/index.js.map +1 -0
  78. package/dist/server/lobby.d.ts +134 -0
  79. package/dist/server/lobby.js +462 -0
  80. package/dist/server/lobby.js.map +1 -0
  81. package/dist/server/rtc.d.ts +38 -0
  82. package/dist/server/rtc.js +102 -0
  83. package/dist/server/rtc.js.map +1 -0
  84. package/dist/server/server.d.ts +145 -0
  85. package/dist/server/server.js +457 -0
  86. package/dist/server/server.js.map +1 -0
  87. package/dist/server/turn.d.ts +22 -0
  88. package/dist/server/turn.js +52 -0
  89. package/dist/server/turn.js.map +1 -0
  90. package/docs/ADOPTING.md +64 -0
  91. package/docs/API.md +181 -0
  92. package/docs/ARCHITECTURE.md +101 -0
  93. package/docs/OPERATIONS.md +93 -0
  94. package/docs/RELEASE-CHECKLIST.md +25 -0
  95. package/package.json +100 -4
@@ -0,0 +1,145 @@
1
+ import { type IncomingMessage, type Server as HttpServer, type ServerResponse } from 'node:http';
2
+ import { Endpoint, type EndpointOptions, type StateMessage, type StateOptions } from '../core/endpoint.js';
3
+ import { type Json } from '../core/protocol.js';
4
+ import { type IceServer } from '../core/rtc.js';
5
+ import type { RtcFactory } from './rtc.js';
6
+ interface Ws {
7
+ readyState: number;
8
+ bufferedAmount: number;
9
+ send(data: string | Uint8Array): void;
10
+ close(code?: number, reason?: string): void;
11
+ terminate(): void;
12
+ on(type: 'message', cb: (data: Buffer, binary: boolean) => void): void;
13
+ on(type: 'close' | 'error', cb: () => void): void;
14
+ }
15
+ interface WsServer {
16
+ on(type: 'connection', cb: (ws: Ws, req: IncomingMessage) => void): void;
17
+ close(): void;
18
+ }
19
+ interface WsModule {
20
+ WebSocketServer: new (o: Record<string, unknown>) => WsServer;
21
+ }
22
+ export interface GameServerOptions {
23
+ port?: number;
24
+ host?: string;
25
+ path?: string;
26
+ /** Exact page origins, or a predicate (for example, any origin for a game without cookies or accounts). */
27
+ origins: string[] | ((origin: string) => boolean);
28
+ allowMissingOrigin?: boolean;
29
+ maxSessions?: number;
30
+ maxConnections?: number;
31
+ maxPerIp?: number;
32
+ resumeGraceMs?: number;
33
+ heartbeatTimeoutMs?: number;
34
+ handshakeTimeoutMs?: number;
35
+ endpoint?: EndpointOptions;
36
+ rtc?: RtcFactory;
37
+ /** STUN/TURN servers handed to each client in its welcome (a function can mint per-session TURN credentials). */
38
+ iceServers?: IceServer[] | ((session: GameSession) => IceServer[] | Promise<IceServer[]>);
39
+ /** Behind one reverse proxy (Caddy, nginx) on this machine: take the client address from X-Forwarded-For. */
40
+ trustProxy?: boolean;
41
+ /** Development only: honour a client's request to impair this server's sends to it. */
42
+ allowImpairment?: boolean;
43
+ /** Messages per second and bytes per second each connection may send (defaults 300 and 256 KiB). */
44
+ rateLimit?: {
45
+ messages?: number;
46
+ bytes?: number;
47
+ };
48
+ /** A stable account subject, or null to reject. Omit for anonymous rooms. Revalidated on resume. */
49
+ authenticate?: (request: {
50
+ room: string;
51
+ auth: Json;
52
+ resuming: boolean;
53
+ ip: string;
54
+ }) => string | null | Promise<string | null>;
55
+ onSession?: (session: GameSession, resumed: boolean) => void;
56
+ onDisconnect?: (session: GameSession) => void;
57
+ onExpire?: (session: GameSession) => void;
58
+ onError?: (error: Error) => void;
59
+ http?: (req: IncomingMessage, res: ServerResponse) => void;
60
+ }
61
+ export declare class GameSession {
62
+ readonly id: string;
63
+ readonly room: string;
64
+ readonly subject: string | null;
65
+ readonly endpoint: Endpoint;
66
+ connected: boolean;
67
+ disconnectedAt: number;
68
+ epoch: number;
69
+ /** Address of the current (or last) connection. */
70
+ ip: string;
71
+ /** The application JSON the client sent as `auth` with its latest hello (names, build ids). Validate before use. */
72
+ hello: Json;
73
+ /** Free for the application (player record, room membership). */
74
+ data: unknown;
75
+ constructor(id: string, room: string, subject: string | null, options?: EndpointOptions);
76
+ sendEvent(data: Json): number;
77
+ sendState(stream: number, data: Uint8Array, options?: StateOptions): number;
78
+ set onState(cb: (state: StateMessage) => void);
79
+ set onEvent(cb: (data: Json, seq: number) => void);
80
+ set onStateAck(cb: (stream: number, seq: number) => void);
81
+ get transport(): 'rtc' | 'ws' | 'none';
82
+ }
83
+ type Hook = 'session' | 'disconnect' | 'expire';
84
+ type HookFn<H extends Hook> = H extends 'session' ? (s: GameSession, resumed: boolean) => void : (s: GameSession) => void;
85
+ export declare class GameServer {
86
+ readonly options: GameServerOptions;
87
+ readonly sessions: Map<string, GameSession>;
88
+ readonly stats: {
89
+ connectionsAccepted: number;
90
+ protocolErrors: number;
91
+ rateLimited: number;
92
+ sessionResumes: number;
93
+ expiredSessions: number;
94
+ };
95
+ private tokens;
96
+ private connections;
97
+ private epoch;
98
+ private timer?;
99
+ private shuttingDown;
100
+ private wsServer;
101
+ readonly httpServer: HttpServer;
102
+ private pumpCursor;
103
+ private hooks;
104
+ private maxFrame;
105
+ constructor(options: GameServerOptions, ws: WsModule);
106
+ /** Add a listener next to the options' callbacks (used by Lobby). */
107
+ on<H extends Hook>(hook: H, fn: HookFn<H>): () => void;
108
+ private emit;
109
+ listen(): Promise<number>;
110
+ private report;
111
+ /** The client address, honouring one trusted local proxy when configured. */
112
+ addressOf(req: IncomingMessage): string;
113
+ private connect;
114
+ private hello;
115
+ private message;
116
+ private stopRtc;
117
+ private disconnect;
118
+ private expire;
119
+ /** End a session now (kick). The client reports session loss and does not reconnect into it. */
120
+ endSession(session: GameSession, reason?: string): void;
121
+ private pump;
122
+ /** Broadcast reliable events to every session that joined with this hello room. For snapshots, filter per session. */
123
+ broadcast(room: string, data: Json): {
124
+ queued: number;
125
+ rejected: string[];
126
+ };
127
+ /** Totals for a health endpoint: sessions, connections, transports and traffic. */
128
+ metrics(): {
129
+ connectionsAccepted: number;
130
+ protocolErrors: number;
131
+ rateLimited: number;
132
+ sessionResumes: number;
133
+ expiredSessions: number;
134
+ sessions: number;
135
+ connections: number;
136
+ rtc: number;
137
+ ws: number;
138
+ bytesSent: number;
139
+ bytesReceived: number;
140
+ pendingEvents: number;
141
+ };
142
+ close(): Promise<void>;
143
+ }
144
+ export declare function createGameServer(options: GameServerOptions): Promise<GameServer>;
145
+ export {};
@@ -0,0 +1,457 @@
1
+ import { createServer } from 'node:http';
2
+ import { randomBytes, randomUUID } from 'node:crypto';
3
+ import { Endpoint } from '../core/endpoint.js';
4
+ import { TokenBucket } from '../core/budget.js';
5
+ import { readControl, record as isRecord, stringify, VERSION, MAX_CONTROL_BYTES, isUint } from '../core/protocol.js';
6
+ import { validIceServers, validSignal } from '../core/rtc.js';
7
+ export class GameSession {
8
+ id;
9
+ room;
10
+ subject;
11
+ endpoint;
12
+ connected = false;
13
+ disconnectedAt = 0;
14
+ epoch = 0;
15
+ /** Address of the current (or last) connection. */
16
+ ip = '';
17
+ /** The application JSON the client sent as `auth` with its latest hello (names, build ids). Validate before use. */
18
+ hello = null;
19
+ /** Free for the application (player record, room membership). */
20
+ data = undefined;
21
+ constructor(id, room, subject, options = {}) {
22
+ this.id = id;
23
+ this.room = room;
24
+ this.subject = subject;
25
+ this.endpoint = new Endpoint(options);
26
+ }
27
+ sendEvent(data) { return this.endpoint.sendEvent(data); }
28
+ sendState(stream, data, options) {
29
+ return this.endpoint.sendState(stream, data, performance.now(), options);
30
+ }
31
+ set onState(cb) { this.endpoint.onState = cb; }
32
+ set onEvent(cb) { this.endpoint.onEvent = cb; }
33
+ set onStateAck(cb) { this.endpoint.onStateAck = cb; }
34
+ get transport() { return !this.connected ? 'none' : this.endpoint.fastActive ? 'rtc' : 'ws'; }
35
+ }
36
+ export class GameServer {
37
+ options;
38
+ sessions = new Map();
39
+ stats = { connectionsAccepted: 0, protocolErrors: 0, rateLimited: 0, sessionResumes: 0, expiredSessions: 0 };
40
+ tokens = new Map();
41
+ connections = new Set();
42
+ epoch = randomBytes(4).readUInt32LE(0) || 1;
43
+ timer;
44
+ shuttingDown = false;
45
+ wsServer;
46
+ httpServer;
47
+ pumpCursor = 0;
48
+ hooks = { session: [], disconnect: [], expire: [] };
49
+ maxFrame;
50
+ constructor(options, ws) {
51
+ this.options = options;
52
+ if (typeof options.origins !== 'function' && (!Array.isArray(options.origins) || options.origins.some(s => typeof s !== 'string' || s === '*')))
53
+ throw new Error('Supply exact permitted origins, not a wildcard');
54
+ this.maxFrame = new Endpoint(options.endpoint).maxFrameBytes;
55
+ this.httpServer = createServer((req, res) => {
56
+ if (options.http)
57
+ options.http(req, res);
58
+ else {
59
+ res.writeHead(404);
60
+ res.end();
61
+ }
62
+ });
63
+ this.wsServer = new ws.WebSocketServer({ server: this.httpServer, path: options.path ?? '/connect',
64
+ maxPayload: Math.max(MAX_CONTROL_BYTES, this.maxFrame), perMessageDeflate: false });
65
+ this.wsServer.on('connection', (socket, req) => this.connect(socket, req));
66
+ }
67
+ /** Add a listener next to the options' callbacks (used by Lobby). */
68
+ on(hook, fn) {
69
+ const list = this.hooks[hook];
70
+ list.push(fn);
71
+ return () => { const i = list.indexOf(fn); if (i >= 0)
72
+ list.splice(i, 1); };
73
+ }
74
+ emit(hook, s, resumed = false) {
75
+ const own = hook === 'session' ? this.options.onSession : hook === 'disconnect' ? this.options.onDisconnect : this.options.onExpire;
76
+ for (const fn of [...this.hooks[hook], ...(own ? [own] : [])]) {
77
+ try {
78
+ fn(s, resumed);
79
+ }
80
+ catch (e) {
81
+ this.report(e);
82
+ }
83
+ }
84
+ }
85
+ async listen() {
86
+ if (this.timer)
87
+ throw new Error('Already listening');
88
+ await new Promise((resolve, reject) => {
89
+ const error = (e) => reject(e);
90
+ this.httpServer.once('error', error);
91
+ this.httpServer.listen(this.options.port ?? 0, this.options.host ?? '127.0.0.1', () => { this.httpServer.off('error', error); resolve(); });
92
+ });
93
+ this.timer = setInterval(() => this.pump(), 1000 / 60);
94
+ return this.httpServer.address().port;
95
+ }
96
+ report(error) {
97
+ try {
98
+ this.options.onError?.(error instanceof Error ? error : new Error(String(error)));
99
+ }
100
+ catch { /* A diagnostics callback must not stop the room pump. */ }
101
+ }
102
+ /** The client address, honouring one trusted local proxy when configured. */
103
+ addressOf(req) {
104
+ const peer = req.socket.remoteAddress ?? 'unknown';
105
+ if (this.options.trustProxy && /^(127\.|::1$|::ffff:127\.)/.test(peer)) {
106
+ const f = req.headers['x-forwarded-for'], list = (Array.isArray(f) ? f.join(',') : f ?? '').split(',').map(s => s.trim()).filter(Boolean);
107
+ if (list.length)
108
+ return list[list.length - 1].slice(0, 64);
109
+ }
110
+ return peer;
111
+ }
112
+ connect(ws, req) {
113
+ const origin = req.headers.origin, ip = this.addressOf(req);
114
+ const allowed = (o) => typeof this.options.origins === 'function' ? this.options.origins(o) : this.options.origins.includes(o);
115
+ if (this.shuttingDown || (origin ? !allowed(origin) : !this.options.allowMissingOrigin)) {
116
+ ws.close(1008, 'origin');
117
+ return;
118
+ }
119
+ let fromIp = 0;
120
+ for (const c of this.connections)
121
+ if (c.ip === ip)
122
+ fromIp++;
123
+ if (this.connections.size >= (this.options.maxConnections ?? 512) || fromIp >= (this.options.maxPerIp ?? 32)) {
124
+ ws.close(1013, 'capacity');
125
+ return;
126
+ }
127
+ const now = performance.now(), rate = this.options.rateLimit ?? {};
128
+ const msgs = rate.messages ?? 300, bytes = rate.bytes ?? 256 * 1024;
129
+ const c = { ws, ip, started: now, lastSeen: now, authenticating: false, epoch: 0, attempt: 0, rtcStarted: 0,
130
+ messages: new TokenBucket(msgs, msgs * 2, now), bytes: new TokenBucket(bytes, Math.max(bytes * 2, this.maxFrame * 2), now) };
131
+ this.connections.add(c);
132
+ this.stats.connectionsAccepted++;
133
+ ws.on('error', () => { });
134
+ ws.on('close', () => this.disconnect(c));
135
+ ws.on('message', (raw, binary) => {
136
+ if (!this.connections.has(c) || c.record && c.record.connection !== c)
137
+ return;
138
+ const now = performance.now();
139
+ c.lastSeen = now;
140
+ if (!c.messages.take(1, now) || !c.bytes.take(raw.byteLength, now)) {
141
+ this.stats.rateLimited++;
142
+ ws.close(1008, 'rate');
143
+ return;
144
+ }
145
+ try {
146
+ if (binary) {
147
+ if (!c.record || raw.length > this.maxFrame)
148
+ throw new Error('Unexpected binary frame');
149
+ c.record.session.endpoint.receiveBinary(new Uint8Array(raw), 'ws');
150
+ }
151
+ else {
152
+ if (c.record)
153
+ c.record.session.endpoint.stats.bytesReceived += raw.byteLength;
154
+ const m = readControl(raw.toString('utf8'));
155
+ if (!m)
156
+ throw new Error('Invalid control');
157
+ if (m.t === 'hello') {
158
+ void this.hello(c, m).catch(e => { this.report(e); ws.close(1008, 'join'); });
159
+ }
160
+ else
161
+ this.message(c, m);
162
+ }
163
+ }
164
+ catch (error) {
165
+ this.stats.protocolErrors++;
166
+ this.report(error);
167
+ ws.close(1002, 'protocol');
168
+ }
169
+ });
170
+ }
171
+ async hello(c, m) {
172
+ if (c.record || c.authenticating || m.v !== VERSION || typeof m.room !== 'string' ||
173
+ !/^[\w:.-]{1,64}$/.test(m.room) || !(m.token === null || typeof m.token === 'string' && /^[\w-]{20,128}$/.test(m.token)))
174
+ throw new Error('Invalid hello');
175
+ c.authenticating = true;
176
+ const auth = (m.auth ?? null);
177
+ const subject = this.options.authenticate ? await this.options.authenticate({ room: m.room, auth, resuming: !!m.token, ip: c.ip }) : null;
178
+ if (!this.connections.has(c) || c.ws.readyState !== 1 || this.shuttingDown)
179
+ return;
180
+ if (this.options.authenticate && (typeof subject !== 'string' || !subject))
181
+ throw new Error('Authentication rejected');
182
+ let record;
183
+ const resumed = typeof m.token === 'string';
184
+ if (resumed) {
185
+ record = this.tokens.get(m.token);
186
+ if (!record || record.session.room !== m.room || record.session.subject !== subject ||
187
+ !record.session.connected && performance.now() - record.session.disconnectedAt > (this.options.resumeGraceMs ?? 90000)) {
188
+ c.ws.send(JSON.stringify({ t: 'reset', reason: 'session unavailable' }));
189
+ c.ws.close(4001, 'session unavailable');
190
+ return;
191
+ }
192
+ this.stats.sessionResumes++;
193
+ }
194
+ else {
195
+ if (this.sessions.size >= (this.options.maxSessions ?? 256)) {
196
+ c.ws.close(1013, 'room capacity');
197
+ return;
198
+ }
199
+ const session = new GameSession(randomUUID(), m.room, subject, this.options.endpoint);
200
+ record = { session, token: randomBytes(32).toString('base64url') };
201
+ this.sessions.set(session.id, session);
202
+ this.tokens.set(record.token, record);
203
+ }
204
+ const s = record.session;
205
+ let ice = [];
206
+ try {
207
+ const v = typeof this.options.iceServers === 'function' ? await this.options.iceServers(s) : this.options.iceServers ?? [];
208
+ if (validIceServers(v))
209
+ ice = v;
210
+ else
211
+ this.report(new Error('Invalid iceServers ignored'));
212
+ }
213
+ catch (e) {
214
+ this.report(e);
215
+ }
216
+ if (!this.connections.has(c) || c.ws.readyState !== 1 || this.shuttingDown)
217
+ return;
218
+ const old = record.connection;
219
+ if (old && old !== c) {
220
+ this.stopRtc(old, false);
221
+ old.record = undefined;
222
+ old.ws.close(4002, 'session resumed elsewhere');
223
+ }
224
+ record.connection = c;
225
+ c.record = record;
226
+ c.authenticating = false;
227
+ c.epoch = this.epoch = (this.epoch + 1) >>> 0 || 1;
228
+ s.epoch = c.epoch;
229
+ s.connected = true;
230
+ s.ip = c.ip;
231
+ s.hello = auth;
232
+ try {
233
+ s.endpoint.setImpairment(this.options.allowImpairment && isRecord(m.impair) ? m.impair : null);
234
+ }
235
+ catch (e) {
236
+ this.report(e);
237
+ s.endpoint.setImpairment(null);
238
+ }
239
+ const socket = c.ws;
240
+ s.endpoint.attach(c.epoch, {
241
+ get open() { return socket.readyState === 1; }, get bufferedAmount() { return socket.bufferedAmount; },
242
+ send(data) { if (socket.readyState !== 1)
243
+ return false; socket.send(data); return true; }, close() { socket.close(); },
244
+ });
245
+ s.endpoint.onFastDown = () => this.stopRtc(c, true);
246
+ s.endpoint.sendControl({ t: 'welcome', v: VERSION, e: c.epoch, id: s.id, token: record.token, resumed, rtc: !!this.options.rtc, ice: ice });
247
+ this.emit('session', s, resumed);
248
+ s.endpoint.flush();
249
+ }
250
+ message(c, m) {
251
+ const r = c.record;
252
+ if (!r || r.connection !== c || m.e !== c.epoch)
253
+ return;
254
+ const endpoint = r.session.endpoint;
255
+ if (endpoint.receiveControl(m))
256
+ return;
257
+ if (m.t === 'ping' && isUint(m.n)) {
258
+ endpoint.sendControl({ t: 'pong', e: c.epoch, n: m.n, s: performance.now() });
259
+ return;
260
+ }
261
+ if (m.t === 'leave') {
262
+ this.expire(r);
263
+ return;
264
+ }
265
+ if (m.t === 'rtc-reset' && m.a === c.attempt) {
266
+ this.stopRtc(c, false);
267
+ return;
268
+ }
269
+ if (m.t === 'signal' && isUint(m.a) && m.a > 0 && validSignal(m.d)) {
270
+ if (!this.options.rtc) {
271
+ endpoint.sendControl({ t: 'rtc-reset', e: c.epoch, a: m.a });
272
+ return;
273
+ }
274
+ if (m.d.kind === 'offer') {
275
+ if (m.a <= c.attempt || performance.now() - c.rtcStarted < 1000 && c.attempt > 0)
276
+ return;
277
+ this.stopRtc(c, false);
278
+ c.attempt = m.a;
279
+ c.rtcStarted = performance.now();
280
+ const a = c.attempt, epoch = c.epoch;
281
+ const current = () => r.connection === c && c.attempt === a && c.epoch === epoch && this.connections.has(c);
282
+ c.rtc = this.options.rtc({
283
+ signal: d => { if (current())
284
+ endpoint.sendControl({ t: 'signal', e: epoch, a, d }); },
285
+ open: link => { if (current())
286
+ endpoint.attachDatagram(link);
287
+ else
288
+ link.close(); },
289
+ data: data => {
290
+ if (!current())
291
+ return;
292
+ const now = performance.now();
293
+ if (!c.messages.take(1, now) || !c.bytes.take(data.length, now)) {
294
+ this.stats.rateLimited++;
295
+ c.ws.close(1008, 'rate');
296
+ return;
297
+ }
298
+ try {
299
+ endpoint.receiveBinary(data, 'rtc');
300
+ }
301
+ catch (error) {
302
+ this.report(error);
303
+ c.ws.close(1002, 'protocol');
304
+ }
305
+ },
306
+ closed: () => { if (current())
307
+ this.stopRtc(c, true); },
308
+ error: e => { if (current()) {
309
+ this.report(e);
310
+ this.stopRtc(c, true);
311
+ } },
312
+ });
313
+ }
314
+ if (m.a === c.attempt) {
315
+ try {
316
+ const pending = c.rtc?.signal(m.d);
317
+ if (pending)
318
+ void pending.catch(error => { this.report(error); this.stopRtc(c, true); });
319
+ }
320
+ catch (error) {
321
+ this.report(error);
322
+ this.stopRtc(c, true);
323
+ }
324
+ }
325
+ }
326
+ }
327
+ stopRtc(c, notify) {
328
+ const rtc = c.rtc;
329
+ c.rtc = undefined;
330
+ if (notify && rtc)
331
+ c.record?.session.endpoint.sendControl({ t: 'rtc-reset', e: c.epoch, a: c.attempt });
332
+ if (c.record?.connection === c)
333
+ c.record.session.endpoint.dropDatagram(false);
334
+ rtc?.close();
335
+ }
336
+ disconnect(c) {
337
+ this.connections.delete(c);
338
+ this.stopRtc(c, false);
339
+ const r = c.record;
340
+ if (!r || r.connection !== c)
341
+ return;
342
+ r.connection = undefined;
343
+ r.session.connected = false;
344
+ r.session.disconnectedAt = performance.now();
345
+ r.session.endpoint.detach();
346
+ this.emit('disconnect', r.session);
347
+ }
348
+ expire(r) {
349
+ if (!this.tokens.has(r.token))
350
+ return;
351
+ this.tokens.delete(r.token);
352
+ this.sessions.delete(r.session.id);
353
+ this.stats.expiredSessions++;
354
+ const c = r.connection;
355
+ if (c) {
356
+ this.stopRtc(c, false);
357
+ c.record = undefined;
358
+ c.ws.close(1000, 'left');
359
+ }
360
+ r.connection = undefined;
361
+ r.session.connected = false;
362
+ r.session.endpoint.detach();
363
+ this.emit('expire', r.session);
364
+ }
365
+ /** End a session now (kick). The client reports session loss and does not reconnect into it. */
366
+ endSession(session, reason = 'removed') {
367
+ for (const r of this.tokens.values())
368
+ if (r.session === session) {
369
+ const c = r.connection;
370
+ if (c?.ws.readyState === 1)
371
+ try {
372
+ c.ws.send(stringify({ t: 'reset', reason: reason.slice(0, 100) }));
373
+ }
374
+ catch { /* closing anyway */ }
375
+ this.expire(r);
376
+ return;
377
+ }
378
+ }
379
+ pump() {
380
+ const now = performance.now();
381
+ for (const c of this.connections) {
382
+ if (!c.record && now - c.started > (this.options.handshakeTimeoutMs ?? 5000) ||
383
+ c.record && now - c.lastSeen > (this.options.heartbeatTimeoutMs ?? 15000)) {
384
+ c.ws.terminate();
385
+ continue;
386
+ }
387
+ if (c.rtc && now - c.rtcStarted > 10000 && !c.record?.session.endpoint.fastActive)
388
+ this.stopRtc(c, true);
389
+ }
390
+ const sessions = [...this.sessions.values()];
391
+ const start = this.pumpCursor++ % Math.max(1, sessions.length);
392
+ for (let i = 0; i < sessions.length; i++) {
393
+ const s = sessions[(start + i) % sessions.length];
394
+ try {
395
+ if (s.connected)
396
+ s.endpoint.pump();
397
+ }
398
+ catch (e) {
399
+ this.report(e);
400
+ }
401
+ }
402
+ for (const r of [...this.tokens.values()])
403
+ if (!r.session.connected && now - r.session.disconnectedAt > (this.options.resumeGraceMs ?? 90000))
404
+ this.expire(r);
405
+ }
406
+ /** Broadcast reliable events to every session that joined with this hello room. For snapshots, filter per session. */
407
+ broadcast(room, data) {
408
+ const result = { queued: 0, rejected: [] };
409
+ for (const s of this.sessions.values())
410
+ if (s.room === room) {
411
+ try {
412
+ s.sendEvent(data);
413
+ result.queued++;
414
+ }
415
+ catch (error) {
416
+ result.rejected.push(s.id);
417
+ this.report(error);
418
+ }
419
+ }
420
+ return result;
421
+ }
422
+ /** Totals for a health endpoint: sessions, connections, transports and traffic. */
423
+ metrics() {
424
+ let rtc = 0, ws = 0, bytesSent = 0, bytesReceived = 0, pendingEvents = 0;
425
+ for (const s of this.sessions.values()) {
426
+ const t = s.transport;
427
+ if (t === 'rtc')
428
+ rtc++;
429
+ else if (t === 'ws')
430
+ ws++;
431
+ bytesSent += s.endpoint.stats.bytesSent;
432
+ bytesReceived += s.endpoint.stats.bytesReceived;
433
+ pendingEvents += s.endpoint.events.size;
434
+ }
435
+ return { sessions: this.sessions.size, connections: this.connections.size, rtc, ws, bytesSent, bytesReceived, pendingEvents, ...this.stats };
436
+ }
437
+ async close() {
438
+ this.shuttingDown = true;
439
+ clearInterval(this.timer);
440
+ this.timer = undefined;
441
+ for (const c of this.connections) {
442
+ this.stopRtc(c, false);
443
+ c.ws.terminate();
444
+ }
445
+ this.wsServer.close();
446
+ await new Promise(resolve => this.httpServer.close(() => resolve()));
447
+ this.connections.clear();
448
+ this.tokens.clear();
449
+ this.sessions.clear();
450
+ }
451
+ }
452
+ export async function createGameServer(options) {
453
+ const name = 'ws';
454
+ const module = await import(name);
455
+ return new GameServer(options, module);
456
+ }
457
+ //# sourceMappingURL=server.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"server.js","sourceRoot":"","sources":["../../src/server/server.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,22 @@
1
+ import { type IceServer } from '../core/rtc.js';
2
+ /**
3
+ * Short-lived TURN credentials for coturn's `use-auth-secret` (the "TURN REST API" scheme): the username is
4
+ * `<expiry unix seconds>:<user>` and the password is base64(HMAC-SHA1(secret, username)). Never ship the secret.
5
+ */
6
+ export declare function turnCredentials(o: {
7
+ secret: string;
8
+ urls: string | string[];
9
+ user?: string;
10
+ ttlSeconds?: number;
11
+ now?: number;
12
+ }): IceServer;
13
+ /**
14
+ * ICE servers from Cloudflare Realtime TURN (a managed relay with anycast TURN over UDP, TCP and TLS:443).
15
+ * Credentials are fetched with your key and cached until shortly before they expire.
16
+ */
17
+ export declare function cloudflareTurn(o: {
18
+ keyId: string;
19
+ apiToken: string;
20
+ ttlSeconds?: number;
21
+ fetch?: typeof fetch;
22
+ }): () => Promise<IceServer[]>;