@honeybbq/teamspeak-client 0.2.1 → 0.2.3
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/dist/client.d.ts.map +1 -1
- package/dist/command/index.cjs +1 -1
- package/dist/command/index.mjs +2 -2
- package/dist/{command-caXc4h0n.js → command-CTDmBXd_.js} +1 -1
- package/dist/{command-caXc4h0n.js.map → command-CTDmBXd_.js.map} +1 -1
- package/dist/{command-Cu2v-5-K.cjs → command-CUPNiKRl.cjs} +2 -2
- package/dist/{command-Cu2v-5-K.cjs.map → command-CUPNiKRl.cjs.map} +1 -1
- package/dist/crypt-handshake-D2Rsi2e3.cjs +2 -0
- package/dist/{crypt-handshake-Dbj2cSBZ.cjs.map → crypt-handshake-D2Rsi2e3.cjs.map} +1 -1
- package/dist/crypt-handshake-DIj51kno.js +55 -0
- package/dist/{crypt-handshake-CHmvZ2qs.js.map → crypt-handshake-DIj51kno.js.map} +1 -1
- package/dist/{crypt-init2-DWX7Tp-_.js → crypt-init2-C2X9oK4i.js} +24 -26
- package/dist/{crypt-init2-DWX7Tp-_.js.map → crypt-init2-C2X9oK4i.js.map} +1 -1
- package/dist/crypt-init2-CazdFwqF.cjs +2 -0
- package/dist/{crypt-init2-C2oihZ7e.cjs.map → crypt-init2-CazdFwqF.cjs.map} +1 -1
- package/dist/crypto/identity.d.ts.map +1 -1
- package/dist/crypto/index.cjs +1 -1
- package/dist/crypto/index.mjs +2 -2
- package/dist/{crypto-VC7n6YJb.js → crypto-CwIMggQG.js} +4 -4
- package/dist/{crypto-VC7n6YJb.js.map → crypto-CwIMggQG.js.map} +1 -1
- package/dist/{crypto-2veVY1fC.cjs → crypto-IbzNNTgO.cjs} +2 -2
- package/dist/{crypto-2veVY1fC.cjs.map → crypto-IbzNNTgO.cjs.map} +1 -1
- package/dist/discovery/index.cjs +1 -1
- package/dist/discovery/index.mjs +1 -1
- package/dist/discovery/resolver.d.ts +1 -1
- package/dist/discovery/resolver.d.ts.map +1 -1
- package/dist/handler-BJdwhtkp.cjs +2 -0
- package/dist/handler-BJdwhtkp.cjs.map +1 -0
- package/dist/{handler-C_JhqGTd.js → handler-BP38rMNl.js} +18 -18
- package/dist/handler-BP38rMNl.js.map +1 -0
- package/dist/handshake/index.cjs +1 -1
- package/dist/handshake/index.mjs +2 -2
- package/dist/index.cjs +3 -1
- package/dist/index.cjs.map +1 -1
- package/dist/index.mjs +12 -12
- package/dist/index.mjs.map +1 -1
- package/dist/{parser-DhAWj-TI.cjs → parser-B6cGUByG.cjs} +2 -2
- package/dist/{parser-DhAWj-TI.cjs.map → parser-B6cGUByG.cjs.map} +1 -1
- package/dist/{parser-CJjP3LlO.js → parser-BPzO8py_.js} +2 -2
- package/dist/{parser-CJjP3LlO.js.map → parser-BPzO8py_.js.map} +1 -1
- package/dist/primitives-Bt-L4BZa.js +1483 -0
- package/dist/primitives-Bt-L4BZa.js.map +1 -0
- package/dist/primitives-ClIhDdNZ.cjs +2 -0
- package/dist/primitives-ClIhDdNZ.cjs.map +1 -0
- package/dist/resolver-B7jho9CP.cjs +4 -0
- package/dist/resolver-B7jho9CP.cjs.map +1 -0
- package/dist/{resolver-DDZWomrF.js → resolver-BDCF2KbM.js} +19 -22
- package/dist/resolver-BDCF2KbM.js.map +1 -0
- package/dist/transfer.d.ts +5 -9
- package/dist/transfer.d.ts.map +1 -1
- package/dist/transport/handler.d.ts.map +1 -1
- package/dist/transport/index.cjs +1 -1
- package/dist/transport/index.mjs +1 -1
- package/dist/{types-DrnoCdSW.cjs → types-ANvuLFWH.cjs} +2 -2
- package/dist/{types-DrnoCdSW.cjs.map → types-ANvuLFWH.cjs.map} +1 -1
- package/dist/{types-CGKgXvpG.js → types-Xm1vrW4s.js} +1 -1
- package/dist/{types-CGKgXvpG.js.map → types-Xm1vrW4s.js.map} +1 -1
- package/package.json +7 -7
- package/dist/crypt-handshake-CHmvZ2qs.js +0 -55
- package/dist/crypt-handshake-Dbj2cSBZ.cjs +0 -2
- package/dist/crypt-init2-C2oihZ7e.cjs +0 -2
- package/dist/handler-C_JhqGTd.js.map +0 -1
- package/dist/handler-CqCD93f0.cjs +0 -2
- package/dist/handler-CqCD93f0.cjs.map +0 -1
- package/dist/primitives-BIAYfJ2Y.js +0 -1842
- package/dist/primitives-BIAYfJ2Y.js.map +0 -1
- package/dist/primitives-bj-ml31v.cjs +0 -2
- package/dist/primitives-bj-ml31v.cjs.map +0 -1
- package/dist/resolver-DDZWomrF.js.map +0 -1
- package/dist/resolver-Dey6omBe.cjs +0 -4
- package/dist/resolver-Dey6omBe.cjs.map +0 -1
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"handler-CqCD93f0.cjs","names":["#mod","#receiveWindow","#generation","#mappedBaseOffset","#isNextGen","#hashtable","#ensureControl","#processReference","#processLiteral","#updateHashtable","#crypt","#logger","#clientID","#conn","#closed","#lastMessageReceived","#handleRawPacket","#triggerClose","#packetCounter","#sendPacketRaw","#stopPing","#checkResends","#stopResend","#initPacketCheck","#sendSplitPacket","#generationCounter","#write","#nextPacketIdentity","#trackResend","#resolveGeneration","#decryptPacketData","#sendPong","#handleCommandWindowAndAck","#handlePacketQueue","#updatePostReceiveState","#recvWindowCommand","#recvWindowCommandLow","#sendWindowCommand","#sendWindowCommandLow","#sendAck","#commandQueue","#commandLowQueue","#fastForwardMissingPackets","#_nextCommandID","#_nextCommandLowID","#tryReassemble","#tryDecompress","#ackManager","#doResend"],"sources":["../src/transport/packet.ts","../src/transport/generation-window.ts","../src/transport/quicklz.ts","../src/transport/handler.ts"],"sourcesContent":["export const enum PacketType {\n Voice = 0,\n VoiceWhisper = 1,\n Command = 2,\n CommandLow = 3,\n Ping = 4,\n Pong = 5,\n Ack = 6,\n AckLow = 7,\n Init1 = 8,\n}\n\nexport const enum PacketFlags {\n Fragmented = 0x10,\n NewProtocol = 0x20,\n Compressed = 0x40,\n Unencrypted = 0x80,\n}\n\nexport interface Packet {\n /** Type byte combined with flags (low nibble = type, high nibble = flags). */\n typeFlagged: number;\n id: number;\n clientID: number;\n generationID: number;\n data: Uint8Array;\n receivedAt: number; // Date.now()\n}\n\nexport function packetType(p: Packet): PacketType {\n return (p.typeFlagged & 0x0f) as PacketType;\n}\n\nexport function packetFlags(p: Packet): number {\n return p.typeFlagged & 0xf0;\n}\n\nexport function isUnencrypted(p: Packet): boolean {\n return (packetFlags(p) & PacketFlags.Unencrypted) !== 0;\n}\n\n/** Build the 5-byte client-to-server header: [packetID(2), clientID(2), typeFlagged(1)]. */\nexport function buildC2SHeader(p: Packet): Uint8Array {\n const header = new Uint8Array(5);\n const view = new DataView(header.buffer);\n view.setUint16(0, p.id, false);\n view.setUint16(2, p.clientID, false);\n header[4] = p.typeFlagged;\n return header;\n}\n\n/** Parse a 3-byte server-to-client header. */\nexport function parseS2CHeader(raw: Uint8Array): Pick<Packet, \"id\" | \"typeFlagged\"> {\n const view = new DataView(raw.buffer, raw.byteOffset, raw.byteLength);\n return {\n id: view.getUint16(0, false),\n typeFlagged: raw[2]!,\n };\n}\n\n/** Parse a 5-byte client-to-server header. */\nexport function parseC2SHeader(raw: Uint8Array): Pick<Packet, \"id\" | \"clientID\" | \"typeFlagged\"> {\n const view = new DataView(raw.buffer, raw.byteOffset, raw.byteLength);\n return {\n id: view.getUint16(0, false),\n clientID: view.getUint16(2, false),\n typeFlagged: raw[4]!,\n };\n}\n","export class GenerationWindow {\n #mappedBaseOffset = 0;\n #generation = 0;\n readonly #mod: number;\n readonly #receiveWindow: number;\n\n constructor(mod: number, windowSize: number) {\n this.#mod = mod;\n this.#receiveWindow = windowSize;\n }\n\n get generation(): number {\n return this.#generation;\n }\n\n advance(amount: number): void {\n if (amount <= 0) return;\n const newBaseOffset = this.#mappedBaseOffset + amount;\n const genStep = Math.floor(newBaseOffset / this.#mod);\n if (genStep > 0) {\n this.#generation = Math.min(this.#generation + genStep, 0xffff_ffff);\n }\n this.#mappedBaseOffset = newBaseOffset % this.#mod;\n }\n\n advanceToExcluded(mappedValue: number): void {\n let moveDist = mappedValue - this.#mappedBaseOffset;\n if (moveDist < 0) moveDist += this.#mod;\n this.advance(moveDist + 1);\n }\n\n syncTo(mappedValue: number): void {\n let moveDist = mappedValue - this.#mappedBaseOffset;\n if (moveDist < 0) moveDist += this.#mod;\n this.advance(moveDist);\n }\n\n isInWindow(mappedValue: number): boolean {\n const maxOffset = this.#mappedBaseOffset + this.#receiveWindow;\n if (maxOffset < this.#mod) {\n return mappedValue >= this.#mappedBaseOffset && mappedValue < maxOffset;\n }\n return mappedValue >= this.#mappedBaseOffset || mappedValue < maxOffset - this.#mod;\n }\n\n mappedToIndex(mappedValue: number): number {\n if (this.#isNextGen(mappedValue)) {\n return mappedValue + this.#mod - this.#mappedBaseOffset;\n }\n return mappedValue - this.#mappedBaseOffset;\n }\n\n isOldPacket(mappedValue: number): boolean {\n return this.mappedToIndex(mappedValue) < 0;\n }\n\n isFuturePacket(mappedValue: number): boolean {\n return this.mappedToIndex(mappedValue) >= this.#receiveWindow;\n }\n\n #isNextGen(mappedValue: number): boolean {\n return (\n this.#mappedBaseOffset > this.#mod - this.#receiveWindow &&\n mappedValue < this.#mappedBaseOffset + this.#receiveWindow - this.#mod\n );\n }\n\n getGeneration(mappedValue: number): number {\n if (this.#isNextGen(mappedValue)) return this.#generation + 1;\n return this.#generation;\n }\n\n reset(): void {\n this.#mappedBaseOffset = 0;\n this.#generation = 0;\n }\n}\n","const TABLE_SIZE = 4096;\n\ninterface QlzState {\n control: number;\n sourcePos: number;\n destPos: number;\n nextHashed: number;\n}\n\nexport class Qlz {\n #hashtable = new Int32Array(TABLE_SIZE);\n\n decompress(data: Uint8Array): Uint8Array {\n const { headerLen, decompressedSize, flags } = parseQlzHeader(data);\n\n const dest = new Uint8Array(decompressedSize);\n\n if ((flags & 0x01) === 0) {\n dest.set(data.slice(headerLen, headerLen + decompressedSize));\n return dest;\n }\n\n this.#hashtable.fill(0);\n\n const state: QlzState = {\n control: 1,\n sourcePos: headerLen,\n destPos: 0,\n nextHashed: 0,\n };\n\n while (this.#ensureControl(data, state)) {\n if ((state.control & 1) !== 0) {\n if (!this.#processReference(data, dest, state)) break;\n } else {\n if (this.#processLiteral(data, dest, decompressedSize, state)) break;\n }\n }\n\n return dest;\n }\n\n #ensureControl(data: Uint8Array, st: QlzState): boolean {\n if (st.control !== 1) return true;\n if (st.sourcePos + 4 > data.length) return false;\n st.control =\n (data[st.sourcePos]! |\n (data[st.sourcePos + 1]! << 8) |\n (data[st.sourcePos + 2]! << 16) |\n (data[st.sourcePos + 3]! << 24)) >>>\n 0;\n st.sourcePos += 4;\n return true;\n }\n\n #processReference(data: Uint8Array, dest: Uint8Array, st: QlzState): boolean {\n st.control = (st.control >>> 1) >>> 0;\n if (st.sourcePos + 2 > data.length) return false;\n\n const b1 = data[st.sourcePos]!;\n const b2 = data[st.sourcePos + 1]!;\n st.sourcePos += 2;\n\n const hash = (b1 >> 4) | (b2 << 4);\n let matchlen = b1 & 0x0f;\n if (matchlen !== 0) {\n matchlen += 2;\n } else {\n if (st.sourcePos >= data.length) return false;\n matchlen = data[st.sourcePos]!;\n st.sourcePos++;\n }\n\n const offset = this.#hashtable[hash]!;\n for (let i = 0; i < matchlen; i++) {\n if (st.destPos < dest.length && offset + i < st.destPos) {\n dest[st.destPos] = dest[offset + i]!;\n st.destPos++;\n }\n }\n\n const end = st.destPos + 1 - matchlen;\n this.#updateHashtable(dest, st, end);\n st.nextHashed = st.destPos;\n\n return true;\n }\n\n #processLiteral(\n data: Uint8Array,\n dest: Uint8Array,\n decompressedSize: number,\n st: QlzState,\n ): boolean {\n const threshold = Math.max(decompressedSize, 10) - 10;\n if (st.destPos >= threshold) {\n while (st.destPos < decompressedSize) {\n if (st.control === 1) {\n st.sourcePos += 4;\n if (st.sourcePos > data.length) break;\n st.control =\n (data[st.sourcePos - 4]! |\n (data[st.sourcePos - 3]! << 8) |\n (data[st.sourcePos - 2]! << 16) |\n (data[st.sourcePos - 1]! << 24)) >>>\n 0;\n }\n if (st.sourcePos >= data.length) break;\n dest[st.destPos++] = data[st.sourcePos++]!;\n st.control = (st.control >>> 1) >>> 0;\n }\n return true;\n }\n\n if (st.sourcePos >= data.length || st.destPos >= dest.length) return true;\n\n dest[st.destPos++] = data[st.sourcePos++]!;\n st.control = (st.control >>> 1) >>> 0;\n\n const end = Math.max(st.destPos - 2, 0);\n this.#updateHashtable(dest, st, end);\n if (st.nextHashed < end) st.nextHashed = end;\n\n return false;\n }\n\n #updateHashtable(dest: Uint8Array, st: QlzState, end: number): void {\n while (st.nextHashed < end) {\n if (st.nextHashed + 3 > dest.length) break;\n const v =\n (dest[st.nextHashed]! |\n (dest[st.nextHashed + 1]! << 8) |\n (dest[st.nextHashed + 2]! << 16)) >>>\n 0;\n const hash = ((v >> 12) ^ v) & 0xfff;\n this.#hashtable[hash] = st.nextHashed;\n st.nextHashed++;\n }\n }\n}\n\nfunction parseQlzHeader(data: Uint8Array): {\n headerLen: number;\n decompressedSize: number;\n flags: number;\n} {\n if (data.length < 3) throw new Error(\"QuickLZ: data too short\");\n\n const flags = data[0]!;\n const level = (flags >> 2) & 0x03;\n if (level !== 1) throw new Error(\"QuickLZ: only level 1 is supported\");\n\n const headerLen = (flags & 0x02) !== 0 ? 9 : 3;\n if (data.length < headerLen) throw new Error(\"QuickLZ: data too short for header\");\n\n let decompressedSize: number;\n if ((flags & 0x02) !== 0) {\n decompressedSize = (data[5]! | (data[6]! << 8) | (data[7]! << 16) | (data[8]! << 24)) >>> 0;\n } else {\n decompressedSize = data[2]!;\n }\n\n return { headerLen, decompressedSize, flags };\n}\n","import { createSocket, type Socket as UdpSocket } from \"node:dgram\";\nimport type { Crypt } from \"../crypto/crypt.js\";\nimport type { Logger } from \"../types.js\";\nimport { noopLogger } from \"../types.js\";\nimport {\n type Packet,\n PacketType,\n PacketFlags,\n packetType,\n packetFlags,\n buildC2SHeader,\n parseS2CHeader,\n} from \"./packet.js\";\nimport { GenerationWindow } from \"./generation-window.js\";\nimport { Qlz } from \"./quicklz.js\";\nimport { processInit1 } from \"../handshake/crypt-handshake.js\";\n\nconst MAX_OUT_PACKET_SIZE = 500;\nconst RECEIVE_PACKET_WINDOW_SIZE = 1024;\nconst PING_INTERVAL_MS = 5_000;\nconst PACKET_TIMEOUT_MS = 60_000;\nconst MAX_RETRY_INTERVAL_MS = 1_000;\nconst UDP_READ_BUFFER_SIZE = 4096;\nconst HEADER_SIZE = 5;\nconst TAG_SIZE = 8;\nconst VOICE_HEADER_SIZE = 3;\nconst RESEND_BASE_INTERVAL_MS = 500;\nconst RESEND_LOOP_INTERVAL_MS = 100;\n\ninterface ResendPacket {\n packet: Packet;\n firstSend: number;\n lastSend: number;\n retryCount: number;\n nextInterval: number;\n}\n\nexport class PacketHandler {\n onPacket: ((p: Packet) => void) | null = null;\n onClosed: ((err: Error | null) => void) | null = null;\n\n readonly #crypt: Crypt;\n readonly #logger: Logger;\n\n #conn: UdpSocket | null = null;\n #clientID = 0;\n #closed = false;\n #stopPing: (() => void) | null = null;\n #stopResend: (() => void) | null = null;\n #lastMessageReceived = Date.now();\n\n #packetCounter = new Uint16Array(9);\n #generationCounter = new Uint32Array(9);\n\n #recvWindowCommand = new GenerationWindow(1 << 16, RECEIVE_PACKET_WINDOW_SIZE);\n #recvWindowCommandLow = new GenerationWindow(1 << 16, RECEIVE_PACKET_WINDOW_SIZE);\n #sendWindowCommand = new GenerationWindow(1 << 16, RECEIVE_PACKET_WINDOW_SIZE);\n #sendWindowCommandLow = new GenerationWindow(1 << 16, RECEIVE_PACKET_WINDOW_SIZE);\n\n #commandQueue = new Map<number, Packet>();\n #commandLowQueue = new Map<number, Packet>();\n #ackManager = new Map<number, ResendPacket>();\n #initPacketCheck: ResendPacket | null = null;\n\n constructor(crypt: Crypt, logger: Logger = noopLogger) {\n this.#crypt = crypt;\n this.#logger = logger;\n }\n\n setClientID(id: number): void {\n this.#clientID = id;\n }\n\n connect(addr: string): Promise<void> {\n return new Promise((resolve, reject) => {\n const [host, portStr] =\n addr.lastIndexOf(\":\") > 0\n ? [addr.slice(0, addr.lastIndexOf(\":\")), addr.slice(addr.lastIndexOf(\":\") + 1)]\n : [addr, \"9987\"];\n const port = parseInt(portStr, 10);\n\n const socket = createSocket(\"udp4\");\n socket.once(\"error\", reject);\n socket.connect(port, host, () => {\n socket.off(\"error\", reject);\n this.start(socket);\n resolve();\n });\n });\n }\n\n start(conn: UdpSocket): void {\n this.#conn = conn;\n this.#closed = false;\n this.#lastMessageReceived = Date.now();\n\n conn.on(\"message\", (msg) => {\n this.#lastMessageReceived = Date.now();\n this.#handleRawPacket(new Uint8Array(msg.buffer, msg.byteOffset, msg.byteLength));\n });\n conn.on(\"error\", (err) => {\n this.#logger.error(\"udp error\", err);\n this.#triggerClose(err);\n });\n conn.on(\"close\", () => this.#triggerClose(null));\n\n this.#packetCounter[PacketType.Command] = 1;\n this.#packetCounter[PacketType.Init1] = 101;\n\n const init1Data = processInit1(this.#crypt, null);\n if (init1Data) this.#sendPacketRaw(PacketType.Init1, init1Data, 0);\n\n // Ping loop\n const pingTimer = setInterval(() => {\n if (this.#crypt.cryptoInitComplete) {\n this.sendPacket(PacketType.Ping, new Uint8Array(0), PacketFlags.Unencrypted);\n }\n }, PING_INTERVAL_MS);\n this.#stopPing = () => clearInterval(pingTimer);\n\n // Resend loop\n const resendTimer = setInterval(() => this.#checkResends(), RESEND_LOOP_INTERVAL_MS);\n this.#stopResend = () => clearInterval(resendTimer);\n }\n\n receivedFinalInitAck(): void {\n this.#initPacketCheck = null;\n }\n\n sendPacket(pType: PacketType, data: Uint8Array, flags: number): void {\n const dummy = !this.#crypt.cryptoInitComplete;\n if (data.length > 487 && pType !== PacketType.Voice && pType !== PacketType.VoiceWhisper) {\n this.#sendSplitPacket(pType, data, flags, dummy);\n return;\n }\n this.#sendPacketRaw(pType, data, flags, dummy);\n }\n\n sendVoicePacket(data: Uint8Array, codec: number): void {\n const pID = this.#packetCounter[PacketType.Voice]!;\n const pGen = this.#generationCounter[PacketType.Voice]!;\n this.#packetCounter[PacketType.Voice] = (pID + 1) & 0xffff;\n if (this.#packetCounter[PacketType.Voice] === 0) {\n this.#generationCounter[PacketType.Voice]!++;\n }\n\n const payloadLen = VOICE_HEADER_SIZE + data.length;\n const voicePayload = new Uint8Array(payloadLen);\n new DataView(voicePayload.buffer).setUint16(0, pID, false);\n voicePayload[2] = codec;\n voicePayload.set(data, VOICE_HEADER_SIZE);\n\n const p: Packet = {\n typeFlagged: PacketType.Voice | PacketFlags.Unencrypted,\n id: pID,\n clientID: this.#clientID,\n generationID: pGen,\n data: voicePayload,\n receivedAt: 0,\n };\n\n const header = buildC2SHeader(p);\n const final = new Uint8Array(TAG_SIZE + HEADER_SIZE + payloadLen);\n final.set(this.#crypt.fakeSignature, 0);\n final.set(header, TAG_SIZE);\n final.set(voicePayload, TAG_SIZE + HEADER_SIZE);\n this.#write(final);\n }\n\n close(): void {\n if (this.#closed) return;\n this.#closed = true;\n this.#stopPing?.();\n this.#stopResend?.();\n this.#conn?.close();\n }\n\n // ---- Private ---------------------------------------------------------------\n\n #sendSplitPacket(pType: PacketType, data: Uint8Array, flags: number, dummy: boolean): void {\n const maxSize = MAX_OUT_PACKET_SIZE - HEADER_SIZE - TAG_SIZE; // 487\n let pos = 0;\n let first = true;\n\n while (pos < data.length) {\n const blockSize = Math.min(data.length - pos, maxSize);\n const last = pos + blockSize === data.length;\n\n let pFlags = flags;\n if (first !== last) pFlags |= PacketFlags.Fragmented;\n\n this.#sendPacketRaw(pType, data.slice(pos, pos + blockSize), pFlags, dummy);\n pos += blockSize;\n first = false;\n }\n }\n\n #sendPacketRaw(\n pType: PacketType,\n data: Uint8Array,\n flags: number,\n dummy = !this.#crypt.cryptoInitComplete,\n ): void {\n flags = applyProtocolFlags(pType, flags);\n const [pID, pGen] = this.#nextPacketIdentity(pType);\n const p: Packet = {\n typeFlagged: pType | flags,\n id: pID,\n clientID: this.#clientID,\n generationID: pGen,\n data,\n receivedAt: 0,\n };\n\n const unencrypted = (flags & PacketFlags.Unencrypted) !== 0;\n const header = buildC2SHeader(p);\n const [ciphertext, tag] = this.#crypt.encrypt(\n pType,\n pID,\n pGen,\n header,\n data,\n dummy,\n unencrypted,\n );\n\n const final = new Uint8Array(TAG_SIZE + HEADER_SIZE + ciphertext.length);\n final.set(tag.slice(0, TAG_SIZE), 0);\n final.set(header, TAG_SIZE);\n final.set(ciphertext, TAG_SIZE + HEADER_SIZE);\n this.#write(final);\n\n const rp: ResendPacket = {\n packet: p,\n firstSend: Date.now(),\n lastSend: Date.now(),\n retryCount: 0,\n nextInterval: RESEND_BASE_INTERVAL_MS,\n };\n this.#trackResend(pType, p, rp);\n }\n\n #write(data: Uint8Array): void {\n this.#conn?.send(Buffer.from(data), (err) => {\n if (err) this.#logger.warn(\"udp send error\", err);\n });\n }\n\n #handleRawPacket(raw: Uint8Array): void {\n if (raw.length < 11) return;\n\n const tag = raw.slice(0, TAG_SIZE);\n const header = raw.slice(TAG_SIZE, TAG_SIZE + 3);\n const ciphertext = raw.slice(TAG_SIZE + 3);\n\n const parsed = parseS2CHeader(header);\n const p: Packet = {\n ...parsed,\n clientID: 0,\n generationID: this.#resolveGeneration(parsed.id, parsed.typeFlagged & 0x0f),\n data: new Uint8Array(0),\n receivedAt: Date.now(),\n };\n\n const decrypted = this.#decryptPacketData(p, header, ciphertext, tag);\n if (decrypted === null) return;\n p.data = decrypted.plaintext;\n\n const pType = packetType(p);\n\n if (pType === PacketType.Ping) {\n this.#sendPong(p.id, decrypted.dummyUsed);\n return;\n }\n\n if (!this.#handleCommandWindowAndAck(p, decrypted.dummyUsed)) return;\n\n this.#handlePacketQueue(p);\n this.#updatePostReceiveState(p);\n }\n\n #resolveGeneration(id: number, pType: number): number {\n switch (pType as PacketType) {\n case PacketType.Command:\n return this.#recvWindowCommand.getGeneration(id);\n case PacketType.CommandLow:\n return this.#recvWindowCommandLow.getGeneration(id);\n case PacketType.Ack:\n return this.#sendWindowCommand.getGeneration(id);\n case PacketType.AckLow:\n return this.#sendWindowCommandLow.getGeneration(id);\n default:\n return 0;\n }\n }\n\n #decryptPacketData(\n p: Packet,\n header: Uint8Array,\n ciphertext: Uint8Array,\n tag: Uint8Array,\n ): { plaintext: Uint8Array; dummyUsed: boolean } | null {\n const unencrypted = (packetFlags(p) & PacketFlags.Unencrypted) !== 0;\n const dummy = !this.#crypt.cryptoInitComplete;\n let dummyUsed = dummy;\n const pType = packetType(p);\n const gen = p.generationID;\n\n try {\n const plaintext = this.#crypt.decrypt(\n pType,\n p.id,\n gen,\n header,\n ciphertext,\n tag,\n dummy,\n unencrypted,\n );\n return { plaintext, dummyUsed };\n } catch {\n // Try adjacent generations\n for (const offset of [-1, 1]) {\n const guessGen = gen + offset;\n if (guessGen < 0) continue;\n try {\n const plaintext = this.#crypt.decrypt(\n pType,\n p.id,\n guessGen,\n header,\n ciphertext,\n tag,\n false,\n false,\n );\n return { plaintext, dummyUsed: false };\n } catch {\n // continue\n }\n }\n\n // Try dummy fallback for command/ack types\n if (\n pType === PacketType.Command ||\n pType === PacketType.CommandLow ||\n pType === PacketType.Ack\n ) {\n try {\n const plaintext = this.#crypt.decrypt(\n pType,\n p.id,\n gen,\n header,\n ciphertext,\n tag,\n true,\n unencrypted,\n );\n return { plaintext, dummyUsed: true };\n } catch {\n // fall through\n }\n }\n\n return null;\n }\n }\n\n #handleCommandWindowAndAck(p: Packet, dummyUsed: boolean): boolean {\n const pType = packetType(p);\n if (pType !== PacketType.Command && pType !== PacketType.CommandLow) return true;\n\n const win = pType === PacketType.Command ? this.#recvWindowCommand : this.#recvWindowCommandLow;\n const ackType = pType === PacketType.Command ? PacketType.Ack : PacketType.AckLow;\n\n if (!win.isInWindow(p.id)) {\n if (win.isOldPacket(p.id)) {\n this.#sendAck(p.id, ackType, dummyUsed);\n }\n return false;\n }\n this.#sendAck(p.id, ackType, dummyUsed);\n return true;\n }\n\n #sendAck(packetID: number, ackType: PacketType, dummyUsed: boolean): void {\n const ackData = new Uint8Array(2);\n new DataView(ackData.buffer).setUint16(0, packetID, false);\n this.#sendPacketRaw(ackType, ackData, 0, dummyUsed);\n }\n\n #sendPong(pID: number, dummyUsed: boolean): void {\n const pongData = new Uint8Array(2);\n new DataView(pongData.buffer).setUint16(0, pID, false);\n this.#sendPacketRaw(PacketType.Pong, pongData, PacketFlags.Unencrypted, dummyUsed);\n }\n\n #handlePacketQueue(p: Packet): void {\n const pType = packetType(p);\n if (pType !== PacketType.Command && pType !== PacketType.CommandLow) {\n this.onPacket?.(p);\n return;\n }\n\n const isCommand = pType === PacketType.Command;\n const queue = isCommand ? this.#commandQueue : this.#commandLowQueue;\n const win = isCommand ? this.#recvWindowCommand : this.#recvWindowCommandLow;\n\n queue.set(p.id, p);\n\n if (isCommand) {\n this.#fastForwardMissingPackets(queue, win, true);\n } else {\n this.#fastForwardMissingPackets(queue, win, false);\n }\n\n while (true) {\n const current = isCommand ? this.#_nextCommandID : this.#_nextCommandLowID;\n const packet = queue.get(current);\n if (packet === undefined) break;\n\n const result = this.#tryReassemble(packet, queue, current, win);\n if (!result) break;\n\n const [reassembled, newNext] = result;\n if (isCommand) this.#_nextCommandID = newNext;\n else this.#_nextCommandLowID = newNext;\n\n this.#tryDecompress(reassembled);\n this.onPacket?.(reassembled);\n }\n }\n\n #_nextCommandID = 0;\n #_nextCommandLowID = 0;\n\n #fastForwardMissingPackets(\n queue: Map<number, Packet>,\n win: GenerationWindow,\n isCommand: boolean,\n ): void {\n let nextID = isCommand ? this.#_nextCommandID : this.#_nextCommandLowID;\n while (!queue.has(nextID) && hasOldNewerPacket(queue, nextID)) {\n nextID = (nextID + 1) & 0xffff;\n win.advance(1);\n }\n if (isCommand) this.#_nextCommandID = nextID;\n else this.#_nextCommandLowID = nextID;\n }\n\n #tryReassemble(\n startPacket: Packet,\n queue: Map<number, Packet>,\n nextID: number,\n win: GenerationWindow,\n ): [reassembled: Packet, newNextID: number] | null {\n if ((packetFlags(startPacket) & PacketFlags.Fragmented) === 0) {\n queue.delete(nextID);\n win.advance(1);\n return [startPacket, (nextID + 1) & 0xffff];\n }\n\n const fragments: Packet[] = [];\n let totalSize = 0;\n let currID = nextID;\n let startSeen = false;\n let complete = false;\n\n while (true) {\n const frag = queue.get(currID);\n if (!frag) return null;\n fragments.push(frag);\n totalSize += frag.data.length;\n\n const fragmented = (packetFlags(frag) & PacketFlags.Fragmented) !== 0;\n if (!startSeen) {\n startSeen = true;\n if (!fragmented) {\n complete = true;\n break;\n }\n } else if (fragmented) {\n complete = true;\n break;\n }\n currID = (currID + 1) & 0xffff;\n }\n\n if (!complete) return null;\n\n const combined = new Uint8Array(totalSize);\n let pos = 0;\n for (const frag of fragments) {\n combined.set(frag.data, pos);\n pos += frag.data.length;\n queue.delete(nextID);\n win.advance(1);\n nextID = (nextID + 1) & 0xffff;\n }\n\n startPacket.data = combined;\n startPacket.typeFlagged &= ~PacketFlags.Fragmented;\n return [startPacket, nextID];\n }\n\n #tryDecompress(packet: Packet): void {\n if ((packetFlags(packet) & PacketFlags.Compressed) === 0) return;\n try {\n const qlz = new Qlz();\n packet.data = qlz.decompress(packet.data);\n packet.typeFlagged &= ~PacketFlags.Compressed;\n } catch (err) {\n this.#logger.debug(\"decompression failed\", { id: packet.id, err });\n }\n }\n\n #updatePostReceiveState(p: Packet): void {\n const pType = packetType(p);\n\n if (pType === PacketType.Init1) {\n this.#initPacketCheck = null;\n return;\n }\n\n if ((pType === PacketType.Ack || pType === PacketType.AckLow) && p.data.length >= 2) {\n const ackID = new DataView(p.data.buffer, p.data.byteOffset).getUint16(0, false);\n const targetType = pType === PacketType.Ack ? PacketType.Command : PacketType.CommandLow;\n const key = (targetType << 16) | ackID;\n this.#ackManager.delete(key);\n }\n }\n\n #nextPacketIdentity(pType: PacketType): [id: number, gen: number] {\n const pID = this.#packetCounter[pType]!;\n const pGen = this.#generationCounter[pType]!;\n\n if (pType === PacketType.Init1) return [pID, pGen];\n\n this.#packetCounter[pType] = (pID + 1) & 0xffff;\n if (this.#packetCounter[pType] === 0) {\n this.#generationCounter[pType] = (pGen + 1) >>> 0;\n }\n\n if (pType === PacketType.Command) {\n this.#sendWindowCommand.advanceToExcluded(pID);\n } else if (pType === PacketType.CommandLow) {\n this.#sendWindowCommandLow.advanceToExcluded(pID);\n }\n\n return [pID, pGen];\n }\n\n #trackResend(pType: PacketType, p: Packet, rp: ResendPacket): void {\n if (pType === PacketType.Init1) {\n this.#initPacketCheck = rp;\n return;\n }\n if (pType === PacketType.Command || pType === PacketType.CommandLow) {\n const key = (pType << 16) | p.id;\n this.#ackManager.set(key, rp);\n }\n }\n\n #checkResends(): void {\n const now = Date.now();\n\n if (now - this.#lastMessageReceived > PACKET_TIMEOUT_MS) {\n this.#logger.warn(\"idle timeout\");\n this.#triggerClose(new Error(\"idle timeout\"));\n return;\n }\n\n if (this.#initPacketCheck) {\n this.#doResend(this.#initPacketCheck, now);\n }\n\n for (const [key, rp] of this.#ackManager) {\n if (now - rp.firstSend > PACKET_TIMEOUT_MS) {\n this.#ackManager.delete(key);\n this.#triggerClose(new Error(\"packet ack timeout\"));\n return;\n }\n this.#doResend(rp, now);\n }\n }\n\n #doResend(rp: ResendPacket, now: number): void {\n if (now - rp.lastSend < rp.nextInterval) return;\n\n rp.lastSend = now;\n rp.retryCount++;\n rp.nextInterval = Math.min(rp.nextInterval * 2, MAX_RETRY_INTERVAL_MS);\n\n const dummy = !this.#crypt.cryptoInitComplete;\n const unencrypted = (packetFlags(rp.packet) & PacketFlags.Unencrypted) !== 0;\n const header = buildC2SHeader(rp.packet);\n const pType = packetType(rp.packet);\n\n const [ciphertext, tag] = this.#crypt.encrypt(\n pType,\n rp.packet.id,\n rp.packet.generationID,\n header,\n rp.packet.data,\n dummy,\n unencrypted,\n );\n\n const final = new Uint8Array(TAG_SIZE + HEADER_SIZE + ciphertext.length);\n final.set(tag.slice(0, TAG_SIZE), 0);\n final.set(header, TAG_SIZE);\n final.set(ciphertext, TAG_SIZE + HEADER_SIZE);\n this.#write(final);\n }\n\n #triggerClose(err: Error | null): void {\n if (this.#closed) return;\n this.close();\n this.onClosed?.(err);\n }\n}\n\n// ---- Helpers ----------------------------------------------------------------\n\nfunction applyProtocolFlags(pType: PacketType, flags: number): number {\n if (pType === PacketType.Command || pType === PacketType.CommandLow) {\n return flags | PacketFlags.NewProtocol;\n }\n return flags;\n}\n\nfunction hasOldNewerPacket(queue: Map<number, Packet>, nextID: number): boolean {\n const now = Date.now();\n for (const [id, pkg] of queue) {\n const diff = (id - nextID + 0x10000) & 0xffff;\n if (diff < 0x8000 && now - pkg.receivedAt > 5_000) {\n return true;\n }\n }\n return false;\n}\n"],"mappings":"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"}
|