@honeybbq/teamspeak-client 0.2.3 → 0.3.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 (89) hide show
  1. package/README.md +1 -0
  2. package/dist/address-BR-5unVo.cjs +2 -0
  3. package/dist/address-BR-5unVo.cjs.map +1 -0
  4. package/dist/address-BfmovVpp.js +65 -0
  5. package/dist/address-BfmovVpp.js.map +1 -0
  6. package/dist/address.d.ts +9 -0
  7. package/dist/address.d.ts.map +1 -0
  8. package/dist/address.test.d.ts +2 -0
  9. package/dist/address.test.d.ts.map +1 -0
  10. package/dist/api.d.ts.map +1 -1
  11. package/dist/api.test.d.ts +2 -0
  12. package/dist/api.test.d.ts.map +1 -0
  13. package/dist/client.d.ts +2 -0
  14. package/dist/client.d.ts.map +1 -1
  15. package/dist/command/index.cjs +1 -1
  16. package/dist/command/index.mjs +2 -2
  17. package/dist/{command-CTDmBXd_.js → command-BLe-C2L2.js} +2 -4
  18. package/dist/{command-CTDmBXd_.js.map → command-BLe-C2L2.js.map} +1 -1
  19. package/dist/command-DAK4pUBP.cjs +4 -0
  20. package/dist/{command-CUPNiKRl.cjs.map → command-DAK4pUBP.cjs.map} +1 -1
  21. package/dist/{crypt-handshake-D2Rsi2e3.cjs → crypt-handshake-CQkQreLx.cjs} +2 -2
  22. package/dist/{crypt-handshake-D2Rsi2e3.cjs.map → crypt-handshake-CQkQreLx.cjs.map} +1 -1
  23. package/dist/{crypt-handshake-DIj51kno.js → crypt-handshake-DziOY4Lq.js} +2 -2
  24. package/dist/{crypt-handshake-DIj51kno.js.map → crypt-handshake-DziOY4Lq.js.map} +1 -1
  25. package/dist/{crypt-init2-C2X9oK4i.js → crypt-init2-D70ha4LB.js} +6 -6
  26. package/dist/{crypt-init2-C2X9oK4i.js.map → crypt-init2-D70ha4LB.js.map} +1 -1
  27. package/dist/{crypt-init2-CazdFwqF.cjs → crypt-init2-DparLekm.cjs} +2 -2
  28. package/dist/{crypt-init2-CazdFwqF.cjs.map → crypt-init2-DparLekm.cjs.map} +1 -1
  29. package/dist/crypto/identity.d.ts.map +1 -1
  30. package/dist/crypto/index.cjs +1 -1
  31. package/dist/crypto/index.mjs +2 -2
  32. package/dist/{crypto-CwIMggQG.js → crypto-Bg02m4ZE.js} +7 -7
  33. package/dist/crypto-Bg02m4ZE.js.map +1 -0
  34. package/dist/crypto-CDlweUL3.cjs +2 -0
  35. package/dist/crypto-CDlweUL3.cjs.map +1 -0
  36. package/dist/discovery/index.cjs +1 -1
  37. package/dist/discovery/index.mjs +1 -1
  38. package/dist/discovery/resolver.d.ts.map +1 -1
  39. package/dist/{handler-BP38rMNl.js → handler-DI_abe9c.js} +153 -125
  40. package/dist/handler-DI_abe9c.js.map +1 -0
  41. package/dist/handler-DuwoO5RC.cjs +2 -0
  42. package/dist/handler-DuwoO5RC.cjs.map +1 -0
  43. package/dist/handshake/index.cjs +1 -1
  44. package/dist/handshake/index.mjs +2 -2
  45. package/dist/helpers.d.ts.map +1 -1
  46. package/dist/index.cjs +2 -2
  47. package/dist/index.cjs.map +1 -1
  48. package/dist/index.mjs +154 -140
  49. package/dist/index.mjs.map +1 -1
  50. package/dist/{parser-B6cGUByG.cjs → parser-CL33R9tr.cjs} +2 -2
  51. package/dist/{parser-B6cGUByG.cjs.map → parser-CL33R9tr.cjs.map} +1 -1
  52. package/dist/{parser-BPzO8py_.js → parser-DZMv3Jm-.js} +2 -2
  53. package/dist/{parser-BPzO8py_.js.map → parser-DZMv3Jm-.js.map} +1 -1
  54. package/dist/primitives-cNNAeFCo.cjs +2 -0
  55. package/dist/primitives-cNNAeFCo.cjs.map +1 -0
  56. package/dist/primitives-xIr6Tjk4.js +1457 -0
  57. package/dist/primitives-xIr6Tjk4.js.map +1 -0
  58. package/dist/resolver-6B8dI9gr.js +141 -0
  59. package/dist/resolver-6B8dI9gr.js.map +1 -0
  60. package/dist/resolver-DCcmyWSK.cjs +4 -0
  61. package/dist/resolver-DCcmyWSK.cjs.map +1 -0
  62. package/dist/transport/handler.d.ts +2 -0
  63. package/dist/transport/handler.d.ts.map +1 -1
  64. package/dist/transport/index.cjs +1 -1
  65. package/dist/transport/index.mjs +1 -1
  66. package/dist/transport/whisper.test.d.ts +2 -0
  67. package/dist/transport/whisper.test.d.ts.map +1 -0
  68. package/dist/types.d.ts +2 -0
  69. package/dist/types.d.ts.map +1 -1
  70. package/package.json +4 -4
  71. package/dist/command-CUPNiKRl.cjs +0 -4
  72. package/dist/crypto-CwIMggQG.js.map +0 -1
  73. package/dist/crypto-IbzNNTgO.cjs +0 -2
  74. package/dist/crypto-IbzNNTgO.cjs.map +0 -1
  75. package/dist/handler-BJdwhtkp.cjs +0 -2
  76. package/dist/handler-BJdwhtkp.cjs.map +0 -1
  77. package/dist/handler-BP38rMNl.js.map +0 -1
  78. package/dist/primitives-Bt-L4BZa.js +0 -1483
  79. package/dist/primitives-Bt-L4BZa.js.map +0 -1
  80. package/dist/primitives-ClIhDdNZ.cjs +0 -2
  81. package/dist/primitives-ClIhDdNZ.cjs.map +0 -1
  82. package/dist/resolver-B7jho9CP.cjs +0 -4
  83. package/dist/resolver-B7jho9CP.cjs.map +0 -1
  84. package/dist/resolver-BDCF2KbM.js +0 -162
  85. package/dist/resolver-BDCF2KbM.js.map +0 -1
  86. package/dist/types-ANvuLFWH.cjs +0 -2
  87. package/dist/types-ANvuLFWH.cjs.map +0 -1
  88. package/dist/types-Xm1vrW4s.js +0 -18
  89. package/dist/types-Xm1vrW4s.js.map +0 -1
@@ -1 +0,0 @@
1
- {"version":3,"file":"handler-BP38rMNl.js","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 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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"}