@colyseus/sdk 0.17.41 → 0.17.43
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.
- package/build/3rd_party/discord.cjs +1 -1
- package/build/3rd_party/discord.mjs +1 -1
- package/build/Auth.cjs +1 -1
- package/build/Auth.mjs +1 -1
- package/build/Client.cjs +39 -10
- package/build/Client.cjs.map +1 -1
- package/build/Client.d.ts +11 -2
- package/build/Client.mjs +38 -10
- package/build/Client.mjs.map +1 -1
- package/build/Connection.cjs +1 -1
- package/build/Connection.mjs +1 -1
- package/build/HTTP.cjs +1 -1
- package/build/HTTP.mjs +1 -1
- package/build/Room.cjs +1 -1
- package/build/Room.mjs +1 -1
- package/build/Storage.cjs +1 -1
- package/build/Storage.mjs +1 -1
- package/build/core/nanoevents.cjs +1 -1
- package/build/core/nanoevents.mjs +1 -1
- package/build/core/signal.cjs +1 -1
- package/build/core/signal.mjs +1 -1
- package/build/core/utils.cjs +1 -1
- package/build/core/utils.mjs +1 -1
- package/build/debug.cjs +1 -1
- package/build/debug.mjs +1 -1
- package/build/errors/Errors.cjs +1 -1
- package/build/errors/Errors.mjs +1 -1
- package/build/fetchXHR.cjs +1 -1
- package/build/fetchXHR.mjs +1 -1
- package/build/index.cjs +1 -1
- package/build/index.mjs +1 -1
- package/build/legacy.cjs +1 -1
- package/build/legacy.mjs +1 -1
- package/build/serializer/NoneSerializer.cjs +1 -1
- package/build/serializer/NoneSerializer.mjs +1 -1
- package/build/serializer/SchemaSerializer.cjs +1 -1
- package/build/serializer/SchemaSerializer.mjs +1 -1
- package/build/serializer/Serializer.cjs +1 -1
- package/build/serializer/Serializer.mjs +1 -1
- package/build/transport/H3Transport.cjs +70 -21
- package/build/transport/H3Transport.cjs.map +1 -1
- package/build/transport/H3Transport.d.ts +16 -0
- package/build/transport/H3Transport.mjs +69 -23
- package/build/transport/H3Transport.mjs.map +1 -1
- package/build/transport/WebSocketTransport.cjs +1 -1
- package/build/transport/WebSocketTransport.mjs +1 -1
- package/dist/colyseus.js +107 -30
- package/dist/colyseus.js.map +1 -1
- package/dist/debug.js +1 -1
- package/package.json +2 -2
- package/src/Client.ts +41 -8
- package/src/transport/H3Transport.ts +74 -24
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"H3Transport.mjs","sources":["../../src/transport/H3Transport.ts"],"sourcesContent":["import { encode, decode, type Iterator } from '@colyseus/schema';\nimport type { ITransport, ITransportEventMap } from \"./ITransport.ts\";\n\nexport class H3TransportTransport implements ITransport {\n wt: WebTransport;\n isOpen: boolean = false;\n events: ITransportEventMap;\n\n reader: ReadableStreamDefaultReader;\n writer: WritableStreamDefaultWriter;\n\n unreliableReader: ReadableStreamDefaultReader<Uint8Array>;\n unreliableWriter: WritableStreamDefaultWriter<Uint8Array>;\n\n private lengthPrefixBuffer = new Uint8Array(9); // 9 bytes is the maximum length of a length prefix\n\n constructor(events: ITransportEventMap) {\n this.events = events;\n }\n\n public connect(url: string, options: any = {}) {\n const wtOpts: WebTransportOptions = options.fingerprint && ({\n // requireUnreliable: true,\n // congestionControl: \"default\", // \"low-latency\" || \"throughput\"\n\n serverCertificateHashes: [{\n algorithm: 'sha-256',\n value: new Uint8Array(options.fingerprint).buffer\n }]\n }) || undefined;\n\n this.wt = new WebTransport(url, wtOpts);\n\n this.wt.ready.then((e) => {\n console.log(\"WebTransport ready!\", e)\n this.isOpen = true;\n\n this.unreliableReader = this.wt.datagrams.readable.getReader();\n this.unreliableWriter = this.wt.datagrams.writable.getWriter();\n\n const incomingBidi = this.wt.incomingBidirectionalStreams.getReader();\n incomingBidi.read().then((stream) => {\n this.reader = stream.value.readable.getReader();\n this.writer = stream.value.writable.getWriter();\n\n // immediately write room/sessionId for establishing the room connection\n this.sendSeatReservation(options.roomId, options.sessionId, options.reconnectionToken, options.skipHandshake);\n\n // start reading incoming data\n this.readIncomingData();\n this.readIncomingUnreliableData();\n\n }).catch((e) => {\n console.error(\"failed to read incoming stream\", e);\n console.error(\"TODO: close the connection\");\n });\n\n // this.events.onopen(e);\n }).catch((e: WebTransportCloseInfo) => {\n // this.events.onerror(e);\n // this.events.onclose({ code: e.closeCode, reason: e.reason });\n console.log(\"WebTransport not ready!\", e)\n this._close();\n });\n\n this.wt.closed.then((e: WebTransportCloseInfo) => {\n console.log(\"WebTransport closed w/ success\", e)\n this.events.onclose({ code: e.closeCode, reason: e.reason });\n\n }).catch((e: WebTransportCloseInfo) => {\n console.log(\"WebTransport closed w/ error\", e)\n this.events.onerror(e);\n this.events.onclose({ code: e.closeCode, reason: e.reason });\n }).finally(() => {\n this._close();\n });\n }\n\n public send(data: Buffer | Uint8Array): void {\n const prefixLength = encode.number(this.lengthPrefixBuffer as any, data.length, { offset: 0 });\n const dataWithPrefixedLength = new Uint8Array(prefixLength + data.length);\n dataWithPrefixedLength.set(this.lengthPrefixBuffer.subarray(0, prefixLength), 0);\n dataWithPrefixedLength.set(data, prefixLength);\n this.writer.write(dataWithPrefixedLength);\n }\n\n public sendUnreliable(data: Buffer | Uint8Array): void {\n const prefixLength = encode.number(this.lengthPrefixBuffer as any, data.length, { offset: 0 });\n const dataWithPrefixedLength = new Uint8Array(prefixLength + data.length);\n dataWithPrefixedLength.set(this.lengthPrefixBuffer.subarray(0, prefixLength), 0);\n dataWithPrefixedLength.set(data, prefixLength);\n this.unreliableWriter.write(dataWithPrefixedLength);\n }\n\n public close(code?: number, reason?: string) {\n try {\n this.wt.close({ closeCode: code, reason: reason });\n } catch (e) {\n console.error(e);\n }\n }\n\n protected async readIncomingData() {\n let result: ReadableStreamReadResult<Uint8Array>;\n\n while (this.isOpen) {\n try {\n result = await this.reader.read();\n\n //\n // a single read may contain multiple messages\n // each message is prefixed with its length\n //\n\n const messages = result.value;\n const it: Iterator = { offset: 0 };\n do {\n //\n // QUESTION: should we buffer the message in case it's not fully read?\n //\n\n const length = decode.number(messages as any, it);\n this.events.onmessage({ data: messages.subarray(it.offset, it.offset + length) });\n it.offset += length;\n } while (it.offset < messages.length);\n\n } catch (e) {\n if (e.message.indexOf(\"session is closed\") === -1) {\n console.error(\"H3Transport: failed to read incoming data\", e);\n }\n break;\n }\n\n if (result.done) {\n break;\n }\n }\n }\n\n protected async readIncomingUnreliableData() {\n let result: ReadableStreamReadResult<Uint8Array>;\n\n while (this.isOpen) {\n try {\n result = await this.unreliableReader.read();\n\n //\n // a single read may contain multiple messages\n // each message is prefixed with its length\n //\n\n const messages = result.value;\n const it: Iterator = { offset: 0 };\n do {\n //\n // QUESTION: should we buffer the message in case it's not fully read?\n //\n\n const length = decode.number(messages as any, it);\n this.events.onmessage({ data: messages.subarray(it.offset, it.offset + length) });\n it.offset += length;\n } while (it.offset < messages.length);\n\n } catch (e) {\n if (e.message.indexOf(\"session is closed\") === -1) {\n console.error(\"H3Transport: failed to read incoming data\", e);\n }\n break;\n }\n\n if (result.done) {\n break;\n }\n }\n }\n\n protected sendSeatReservation (roomId: string, sessionId: string, reconnectionToken?: string, skipHandshake?: boolean) {\n const it: Iterator = { offset: 0 };\n const bytes: number[] = [];\n\n encode.string(bytes, roomId, it);\n encode.string(bytes, sessionId, it);\n\n if (reconnectionToken) {\n encode.string(bytes, reconnectionToken, it);\n }\n\n if (skipHandshake) {\n encode.boolean(bytes, 1, it);\n }\n\n this.writer.write(new Uint8Array(bytes).buffer);\n }\n\n protected _close() {\n this.isOpen = false;\n }\n\n}\n"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"H3Transport.mjs","sources":["../../src/transport/H3Transport.ts"],"sourcesContent":["import { encode, decode, type Iterator } from '@colyseus/schema';\nimport type { ITransport, ITransportEventMap } from \"./ITransport.ts\";\n\n// 9 bytes is the maximum length of a variable-length integer prefix\nconst MAX_LENGTH_PREFIX_BYTES = 9;\n\n/**\n * Reassembles length-prefixed frames from arbitrary byte chunks.\n *\n * A single WebTransport `reader.read()` may:\n * - deliver multiple whole frames in one chunk\n * - split a frame (or its length prefix) across multiple chunks\n *\n * This reassembler buffers partial data across reads so each dispatched\n * frame is exactly one complete message.\n */\nexport class FrameReassembler {\n private pending: Uint8Array = new Uint8Array(0);\n\n push(chunk: Uint8Array | undefined): Uint8Array[] {\n if (!chunk || chunk.byteLength === 0) { return []; }\n\n const bytes = (this.pending.byteLength === 0)\n ? chunk\n : concatBytes(this.pending, chunk);\n\n const frames: Uint8Array[] = [];\n let offset = 0;\n\n while (offset < bytes.byteLength) {\n const it: Iterator = { offset };\n let length: number;\n\n try {\n length = decode.number(bytes as any, it);\n } catch (e) {\n // length prefix is incomplete — wait for more bytes\n if (bytes.byteLength - offset <= MAX_LENGTH_PREFIX_BYTES) { break; }\n throw e;\n }\n\n const frameEnd = it.offset + length;\n if (frameEnd > bytes.byteLength) {\n // payload is incomplete — wait for more bytes\n break;\n }\n\n frames.push(bytes.subarray(it.offset, frameEnd));\n offset = frameEnd;\n }\n\n this.pending = (offset < bytes.byteLength)\n ? bytes.slice(offset)\n : new Uint8Array(0);\n\n return frames;\n }\n}\n\nfunction concatBytes(a: Uint8Array, b: Uint8Array): Uint8Array {\n const out = new Uint8Array(a.byteLength + b.byteLength);\n out.set(a, 0);\n out.set(b, a.byteLength);\n return out;\n}\n\nexport class H3TransportTransport implements ITransport {\n wt: WebTransport;\n isOpen: boolean = false;\n events: ITransportEventMap;\n\n reader: ReadableStreamDefaultReader;\n writer: WritableStreamDefaultWriter;\n\n unreliableReader: ReadableStreamDefaultReader<Uint8Array>;\n unreliableWriter: WritableStreamDefaultWriter<Uint8Array>;\n\n private lengthPrefixBuffer = new Uint8Array(9); // 9 bytes is the maximum length of a length prefix\n\n private reliableReassembler = new FrameReassembler();\n private unreliableReassembler = new FrameReassembler();\n\n constructor(events: ITransportEventMap) {\n this.events = events;\n }\n\n public connect(url: string, options: any = {}) {\n const wtOpts: WebTransportOptions = options.fingerprint && ({\n // requireUnreliable: true,\n // congestionControl: \"default\", // \"low-latency\" || \"throughput\"\n\n serverCertificateHashes: [{\n algorithm: 'sha-256',\n value: new Uint8Array(options.fingerprint).buffer\n }]\n }) || undefined;\n\n this.wt = new WebTransport(url, wtOpts);\n\n this.wt.ready.then((e) => {\n console.log(\"WebTransport ready!\", e)\n this.isOpen = true;\n\n this.unreliableReader = this.wt.datagrams.readable.getReader();\n this.unreliableWriter = this.wt.datagrams.writable.getWriter();\n\n const incomingBidi = this.wt.incomingBidirectionalStreams.getReader();\n incomingBidi.read().then((stream) => {\n this.reader = stream.value.readable.getReader();\n this.writer = stream.value.writable.getWriter();\n\n // immediately write room/sessionId for establishing the room connection\n this.sendSeatReservation(options.roomId, options.sessionId, options.reconnectionToken, options.skipHandshake);\n\n // start reading incoming data\n this.readIncomingData();\n this.readIncomingUnreliableData();\n\n }).catch((e) => {\n console.error(\"failed to read incoming stream\", e);\n console.error(\"TODO: close the connection\");\n });\n\n // this.events.onopen(e);\n }).catch((e: WebTransportCloseInfo) => {\n // this.events.onerror(e);\n // this.events.onclose({ code: e.closeCode, reason: e.reason });\n console.log(\"WebTransport not ready!\", e)\n this._close();\n });\n\n this.wt.closed.then((e: WebTransportCloseInfo) => {\n console.log(\"WebTransport closed w/ success\", e)\n this.events.onclose({ code: e.closeCode, reason: e.reason });\n\n }).catch((e: WebTransportCloseInfo) => {\n console.log(\"WebTransport closed w/ error\", e)\n this.events.onerror(e);\n this.events.onclose({ code: e.closeCode, reason: e.reason });\n }).finally(() => {\n this._close();\n });\n }\n\n public send(data: Buffer | Uint8Array): void {\n const prefixLength = encode.number(this.lengthPrefixBuffer as any, data.length, { offset: 0 });\n const dataWithPrefixedLength = new Uint8Array(prefixLength + data.length);\n dataWithPrefixedLength.set(this.lengthPrefixBuffer.subarray(0, prefixLength), 0);\n dataWithPrefixedLength.set(data, prefixLength);\n this.writer.write(dataWithPrefixedLength);\n }\n\n public sendUnreliable(data: Buffer | Uint8Array): void {\n const prefixLength = encode.number(this.lengthPrefixBuffer as any, data.length, { offset: 0 });\n const dataWithPrefixedLength = new Uint8Array(prefixLength + data.length);\n dataWithPrefixedLength.set(this.lengthPrefixBuffer.subarray(0, prefixLength), 0);\n dataWithPrefixedLength.set(data, prefixLength);\n this.unreliableWriter.write(dataWithPrefixedLength);\n }\n\n public close(code?: number, reason?: string) {\n try {\n this.wt.close({ closeCode: code, reason: reason });\n } catch (e) {\n console.error(e);\n }\n }\n\n protected async readIncomingData() {\n let result: ReadableStreamReadResult<Uint8Array>;\n\n while (this.isOpen) {\n try {\n result = await this.reader.read();\n\n //\n // a single read may contain multiple messages\n // each message is prefixed with its length\n // a read may also deliver a partial frame; buffer across reads\n //\n for (const frame of this.reliableReassembler.push(result.value)) {\n this.events.onmessage({ data: frame });\n }\n\n } catch (e) {\n if (e.message.indexOf(\"session is closed\") === -1) {\n console.error(\"H3Transport: failed to read incoming data\", e);\n }\n break;\n }\n\n if (result.done) {\n break;\n }\n }\n }\n\n protected async readIncomingUnreliableData() {\n let result: ReadableStreamReadResult<Uint8Array>;\n\n while (this.isOpen) {\n try {\n result = await this.unreliableReader.read();\n\n //\n // a single read may contain multiple messages\n // each message is prefixed with its length\n // a read may also deliver a partial frame; buffer across reads\n //\n for (const frame of this.unreliableReassembler.push(result.value)) {\n this.events.onmessage({ data: frame });\n }\n\n } catch (e) {\n if (e.message.indexOf(\"session is closed\") === -1) {\n console.error(\"H3Transport: failed to read incoming data\", e);\n }\n break;\n }\n\n if (result.done) {\n break;\n }\n }\n }\n\n protected sendSeatReservation (roomId: string, sessionId: string, reconnectionToken?: string, skipHandshake?: boolean) {\n const it: Iterator = { offset: 0 };\n const bytes: number[] = [];\n\n encode.string(bytes, roomId, it);\n encode.string(bytes, sessionId, it);\n\n if (reconnectionToken) {\n encode.string(bytes, reconnectionToken, it);\n }\n\n if (skipHandshake) {\n encode.boolean(bytes, 1, it);\n }\n\n this.writer.write(new Uint8Array(bytes).buffer);\n }\n\n protected _close() {\n this.isOpen = false;\n }\n\n}\n"],"names":[],"mappings":"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"}
|
package/dist/colyseus.js
CHANGED
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
// This software is released under the MIT License.
|
|
4
4
|
// https://opensource.org/license/MIT
|
|
5
5
|
//
|
|
6
|
-
// colyseus.js@0.17.
|
|
6
|
+
// colyseus.js@0.17.43 - @colyseus/schema 4.0.13
|
|
7
7
|
(function (global, factory) {
|
|
8
8
|
typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports) :
|
|
9
9
|
typeof define === 'function' && define.amd ? define('@colyseus/sdk', ['exports'], factory) :
|
|
@@ -8154,10 +8154,70 @@
|
|
|
8154
8154
|
const RESET_BUFFER_MODE = 1024;
|
|
8155
8155
|
const RESERVE_START_SPACE = 2048;
|
|
8156
8156
|
|
|
8157
|
+
// 9 bytes is the maximum length of a variable-length integer prefix
|
|
8158
|
+
const MAX_LENGTH_PREFIX_BYTES = 9;
|
|
8159
|
+
/**
|
|
8160
|
+
* Reassembles length-prefixed frames from arbitrary byte chunks.
|
|
8161
|
+
*
|
|
8162
|
+
* A single WebTransport `reader.read()` may:
|
|
8163
|
+
* - deliver multiple whole frames in one chunk
|
|
8164
|
+
* - split a frame (or its length prefix) across multiple chunks
|
|
8165
|
+
*
|
|
8166
|
+
* This reassembler buffers partial data across reads so each dispatched
|
|
8167
|
+
* frame is exactly one complete message.
|
|
8168
|
+
*/
|
|
8169
|
+
class FrameReassembler {
|
|
8170
|
+
constructor() {
|
|
8171
|
+
this.pending = new Uint8Array(0);
|
|
8172
|
+
}
|
|
8173
|
+
push(chunk) {
|
|
8174
|
+
if (!chunk || chunk.byteLength === 0) {
|
|
8175
|
+
return [];
|
|
8176
|
+
}
|
|
8177
|
+
const bytes = (this.pending.byteLength === 0)
|
|
8178
|
+
? chunk
|
|
8179
|
+
: concatBytes(this.pending, chunk);
|
|
8180
|
+
const frames = [];
|
|
8181
|
+
let offset = 0;
|
|
8182
|
+
while (offset < bytes.byteLength) {
|
|
8183
|
+
const it = { offset };
|
|
8184
|
+
let length;
|
|
8185
|
+
try {
|
|
8186
|
+
length = buildExports.decode.number(bytes, it);
|
|
8187
|
+
}
|
|
8188
|
+
catch (e) {
|
|
8189
|
+
// length prefix is incomplete — wait for more bytes
|
|
8190
|
+
if (bytes.byteLength - offset <= MAX_LENGTH_PREFIX_BYTES) {
|
|
8191
|
+
break;
|
|
8192
|
+
}
|
|
8193
|
+
throw e;
|
|
8194
|
+
}
|
|
8195
|
+
const frameEnd = it.offset + length;
|
|
8196
|
+
if (frameEnd > bytes.byteLength) {
|
|
8197
|
+
// payload is incomplete — wait for more bytes
|
|
8198
|
+
break;
|
|
8199
|
+
}
|
|
8200
|
+
frames.push(bytes.subarray(it.offset, frameEnd));
|
|
8201
|
+
offset = frameEnd;
|
|
8202
|
+
}
|
|
8203
|
+
this.pending = (offset < bytes.byteLength)
|
|
8204
|
+
? bytes.slice(offset)
|
|
8205
|
+
: new Uint8Array(0);
|
|
8206
|
+
return frames;
|
|
8207
|
+
}
|
|
8208
|
+
}
|
|
8209
|
+
function concatBytes(a, b) {
|
|
8210
|
+
const out = new Uint8Array(a.byteLength + b.byteLength);
|
|
8211
|
+
out.set(a, 0);
|
|
8212
|
+
out.set(b, a.byteLength);
|
|
8213
|
+
return out;
|
|
8214
|
+
}
|
|
8157
8215
|
class H3TransportTransport {
|
|
8158
8216
|
constructor(events) {
|
|
8159
8217
|
this.isOpen = false;
|
|
8160
8218
|
this.lengthPrefixBuffer = new Uint8Array(9); // 9 bytes is the maximum length of a length prefix
|
|
8219
|
+
this.reliableReassembler = new FrameReassembler();
|
|
8220
|
+
this.unreliableReassembler = new FrameReassembler();
|
|
8161
8221
|
this.events = events;
|
|
8162
8222
|
}
|
|
8163
8223
|
connect(url, options = {}) {
|
|
@@ -8237,17 +8297,11 @@
|
|
|
8237
8297
|
//
|
|
8238
8298
|
// a single read may contain multiple messages
|
|
8239
8299
|
// each message is prefixed with its length
|
|
8300
|
+
// a read may also deliver a partial frame; buffer across reads
|
|
8240
8301
|
//
|
|
8241
|
-
const
|
|
8242
|
-
|
|
8243
|
-
|
|
8244
|
-
//
|
|
8245
|
-
// QUESTION: should we buffer the message in case it's not fully read?
|
|
8246
|
-
//
|
|
8247
|
-
const length = buildExports.decode.number(messages, it);
|
|
8248
|
-
this.events.onmessage({ data: messages.subarray(it.offset, it.offset + length) });
|
|
8249
|
-
it.offset += length;
|
|
8250
|
-
} while (it.offset < messages.length);
|
|
8302
|
+
for (const frame of this.reliableReassembler.push(result.value)) {
|
|
8303
|
+
this.events.onmessage({ data: frame });
|
|
8304
|
+
}
|
|
8251
8305
|
}
|
|
8252
8306
|
catch (e) {
|
|
8253
8307
|
if (e.message.indexOf("session is closed") === -1) {
|
|
@@ -8270,17 +8324,11 @@
|
|
|
8270
8324
|
//
|
|
8271
8325
|
// a single read may contain multiple messages
|
|
8272
8326
|
// each message is prefixed with its length
|
|
8327
|
+
// a read may also deliver a partial frame; buffer across reads
|
|
8273
8328
|
//
|
|
8274
|
-
const
|
|
8275
|
-
|
|
8276
|
-
|
|
8277
|
-
//
|
|
8278
|
-
// QUESTION: should we buffer the message in case it's not fully read?
|
|
8279
|
-
//
|
|
8280
|
-
const length = buildExports.decode.number(messages, it);
|
|
8281
|
-
this.events.onmessage({ data: messages.subarray(it.offset, it.offset + length) });
|
|
8282
|
-
it.offset += length;
|
|
8283
|
-
} while (it.offset < messages.length);
|
|
8329
|
+
for (const frame of this.unreliableReassembler.push(result.value)) {
|
|
8330
|
+
this.events.onmessage({ data: frame });
|
|
8331
|
+
}
|
|
8284
8332
|
}
|
|
8285
8333
|
catch (e) {
|
|
8286
8334
|
if (e.message.indexOf("session is closed") === -1) {
|
|
@@ -9534,7 +9582,7 @@
|
|
|
9534
9582
|
* Select the endpoint with the lowest latency.
|
|
9535
9583
|
* @param endpoints Array of endpoints to select from.
|
|
9536
9584
|
* @param options Client options.
|
|
9537
|
-
* @param latencyOptions Latency measurement options (protocol, pingCount).
|
|
9585
|
+
* @param latencyOptions Latency measurement options (protocol, pingCount, timeout) — forwarded to each {@link getLatency} call.
|
|
9538
9586
|
* @returns The client with the lowest latency.
|
|
9539
9587
|
*/
|
|
9540
9588
|
static selectByLatency(endpoints_1, options_1) {
|
|
@@ -9613,16 +9661,41 @@
|
|
|
9613
9661
|
}
|
|
9614
9662
|
/**
|
|
9615
9663
|
* Create a new connection with the server, and measure the latency.
|
|
9616
|
-
*
|
|
9664
|
+
*
|
|
9665
|
+
* Always settles: resolves with the (average) round-trip time, or rejects on
|
|
9666
|
+
* connection error, server-side close before all pongs arrive, or timeout.
|
|
9667
|
+
*
|
|
9668
|
+
* @param options Latency measurement options (protocol, pingCount, timeout).
|
|
9617
9669
|
*/
|
|
9618
9670
|
getLatency(options = {}) {
|
|
9619
|
-
var _a, _b;
|
|
9671
|
+
var _a, _b, _c;
|
|
9620
9672
|
const protocol = (_a = options.protocol) !== null && _a !== void 0 ? _a : "ws";
|
|
9621
9673
|
const pingCount = (_b = options.pingCount) !== null && _b !== void 0 ? _b : 1;
|
|
9674
|
+
const timeout = (_c = options.timeout) !== null && _c !== void 0 ? _c : 1500;
|
|
9622
9675
|
return new Promise((resolve, reject) => {
|
|
9676
|
+
var _a;
|
|
9623
9677
|
const conn = new Connection(protocol);
|
|
9624
9678
|
const latencies = [];
|
|
9625
9679
|
let pingStart = 0;
|
|
9680
|
+
let settled = false;
|
|
9681
|
+
let timeoutId;
|
|
9682
|
+
// run exactly once — guards against late events after resolve/reject
|
|
9683
|
+
// (e.g. our own conn.close() firing onclose, or a stray onclose/onerror pair)
|
|
9684
|
+
const settle = (run) => {
|
|
9685
|
+
if (settled) {
|
|
9686
|
+
return;
|
|
9687
|
+
}
|
|
9688
|
+
settled = true;
|
|
9689
|
+
clearTimeout(timeoutId);
|
|
9690
|
+
try {
|
|
9691
|
+
conn.close();
|
|
9692
|
+
}
|
|
9693
|
+
catch (e) { /* socket may never have opened */ }
|
|
9694
|
+
run();
|
|
9695
|
+
};
|
|
9696
|
+
const fail = (message) => settle(() => reject(new ServerError(CloseCode.ABNORMAL_CLOSURE, `Failed to get latency: ${message}`)));
|
|
9697
|
+
// bound blackholed/filtered hosts that never fire onopen/onerror within the OS TCP timeout
|
|
9698
|
+
timeoutId = setTimeout(() => fail(`timed out after ${timeout}ms`), timeout);
|
|
9626
9699
|
conn.events.onopen = () => {
|
|
9627
9700
|
pingStart = Date.now();
|
|
9628
9701
|
conn.send(new Uint8Array([Protocol.PING]));
|
|
@@ -9636,15 +9709,19 @@
|
|
|
9636
9709
|
}
|
|
9637
9710
|
else {
|
|
9638
9711
|
// Done, calculate average and close
|
|
9639
|
-
conn.close();
|
|
9640
9712
|
const average = latencies.reduce((sum, l) => sum + l, 0) / latencies.length;
|
|
9641
|
-
resolve(average);
|
|
9713
|
+
settle(() => resolve(average));
|
|
9642
9714
|
}
|
|
9643
9715
|
};
|
|
9644
|
-
|
|
9645
|
-
|
|
9646
|
-
|
|
9647
|
-
|
|
9716
|
+
// server closed the socket before all pongs arrived — fires without onerror on a clean close
|
|
9717
|
+
conn.events.onclose = (event) => fail(`connection closed${(event === null || event === void 0 ? void 0 : event.code) ? ` (${event.code})` : ""}${(event === null || event === void 0 ? void 0 : event.reason) ? `: ${event.reason}` : ""}`);
|
|
9718
|
+
conn.events.onerror = (event) => fail(event.message);
|
|
9719
|
+
try {
|
|
9720
|
+
conn.connect(this.getHttpEndpoint());
|
|
9721
|
+
}
|
|
9722
|
+
catch (e) {
|
|
9723
|
+
fail((_a = e === null || e === void 0 ? void 0 : e.message) !== null && _a !== void 0 ? _a : "failed to connect");
|
|
9724
|
+
}
|
|
9648
9725
|
});
|
|
9649
9726
|
}
|
|
9650
9727
|
createMatchMakeRequest(method_1, roomName_1) {
|