@honeybbq/teamspeak-client 0.0.0 → 0.1.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.
- package/LICENSE +21 -0
- package/README.md +208 -0
- package/dist/api.d.ts +17 -0
- package/dist/api.d.ts.map +1 -0
- package/dist/client.d.ts +39 -0
- package/dist/client.d.ts.map +1 -0
- package/dist/command/command.d.ts +12 -0
- package/dist/command/command.d.ts.map +1 -0
- package/dist/command/command.test.d.ts +2 -0
- package/dist/command/command.test.d.ts.map +1 -0
- package/dist/command/index.cjs +1 -0
- package/dist/command/index.d.ts +4 -0
- package/dist/command/index.d.ts.map +1 -0
- package/dist/command/index.mjs +3 -0
- package/dist/command/parser.d.ts +3 -0
- package/dist/command/parser.d.ts.map +1 -0
- package/dist/command-Cu2v-5-K.cjs +4 -0
- package/dist/command-Cu2v-5-K.cjs.map +1 -0
- package/dist/command-caXc4h0n.js +76 -0
- package/dist/command-caXc4h0n.js.map +1 -0
- package/dist/commands.d.ts +48 -0
- package/dist/commands.d.ts.map +1 -0
- package/dist/crypt-handshake-CHmvZ2qs.js +55 -0
- package/dist/crypt-handshake-CHmvZ2qs.js.map +1 -0
- package/dist/crypt-handshake-Dbj2cSBZ.cjs +2 -0
- package/dist/crypt-handshake-Dbj2cSBZ.cjs.map +1 -0
- package/dist/crypt-init2-BIbQ7TN0.cjs +2 -0
- package/dist/crypt-init2-BIbQ7TN0.cjs.map +1 -0
- package/dist/crypt-init2-C63eypta.js +165 -0
- package/dist/crypt-init2-C63eypta.js.map +1 -0
- package/dist/crypto/crypt-ops.d.ts +7 -0
- package/dist/crypto/crypt-ops.d.ts.map +1 -0
- package/dist/crypto/crypt.d.ts +22 -0
- package/dist/crypto/crypt.d.ts.map +1 -0
- package/dist/crypto/eax.d.ts +12 -0
- package/dist/crypto/eax.d.ts.map +1 -0
- package/dist/crypto/eax.test.d.ts +2 -0
- package/dist/crypto/eax.test.d.ts.map +1 -0
- package/dist/crypto/identity.d.ts +18 -0
- package/dist/crypto/identity.d.ts.map +1 -0
- package/dist/crypto/identity.test.d.ts +2 -0
- package/dist/crypto/identity.test.d.ts.map +1 -0
- package/dist/crypto/index.cjs +1 -0
- package/dist/crypto/index.d.ts +6 -0
- package/dist/crypto/index.d.ts.map +1 -0
- package/dist/crypto/index.mjs +3 -0
- package/dist/crypto/primitives.d.ts +28 -0
- package/dist/crypto/primitives.d.ts.map +1 -0
- package/dist/crypto-C3gBJkh2.cjs +2 -0
- package/dist/crypto-C3gBJkh2.cjs.map +1 -0
- package/dist/crypto-IGJlkTAl.js +165 -0
- package/dist/crypto-IGJlkTAl.js.map +1 -0
- package/dist/discovery/index.cjs +1 -0
- package/dist/discovery/index.d.ts +2 -0
- package/dist/discovery/index.d.ts.map +1 -0
- package/dist/discovery/index.mjs +2 -0
- package/dist/discovery/resolver.d.ts +8 -0
- package/dist/discovery/resolver.d.ts.map +1 -0
- package/dist/errors.d.ts +34 -0
- package/dist/errors.d.ts.map +1 -0
- package/dist/events.d.ts +10 -0
- package/dist/events.d.ts.map +1 -0
- package/dist/handler-C2vxlHYC.js +458 -0
- package/dist/handler-C2vxlHYC.js.map +1 -0
- package/dist/handler-DQteUMKT.cjs +2 -0
- package/dist/handler-DQteUMKT.cjs.map +1 -0
- package/dist/handshake/crypt-handshake.d.ts +8 -0
- package/dist/handshake/crypt-handshake.d.ts.map +1 -0
- package/dist/handshake/crypt-init2.d.ts +7 -0
- package/dist/handshake/crypt-init2.d.ts.map +1 -0
- package/dist/handshake/index.cjs +1 -0
- package/dist/handshake/index.d.ts +4 -0
- package/dist/handshake/index.d.ts.map +1 -0
- package/dist/handshake/index.mjs +3 -0
- package/dist/handshake/license.d.ts +28 -0
- package/dist/handshake/license.d.ts.map +1 -0
- package/dist/handshake.d.ts +9 -0
- package/dist/handshake.d.ts.map +1 -0
- package/dist/helpers.d.ts +14 -0
- package/dist/helpers.d.ts.map +1 -0
- package/dist/helpers.test.d.ts +2 -0
- package/dist/helpers.test.d.ts.map +1 -0
- package/dist/index.cjs +2 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.ts +9 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.mjs +761 -0
- package/dist/index.mjs.map +1 -0
- package/dist/integration.test.d.ts +12 -0
- package/dist/integration.test.d.ts.map +1 -0
- package/dist/notifications.d.ts +32 -0
- package/dist/notifications.d.ts.map +1 -0
- package/dist/notifications.test.d.ts +2 -0
- package/dist/notifications.test.d.ts.map +1 -0
- package/dist/parser-CJjP3LlO.js +33 -0
- package/dist/parser-CJjP3LlO.js.map +1 -0
- package/dist/parser-DhAWj-TI.cjs +2 -0
- package/dist/parser-DhAWj-TI.cjs.map +1 -0
- package/dist/primitives-BxtDMP7x.cjs +2 -0
- package/dist/primitives-BxtDMP7x.cjs.map +1 -0
- package/dist/primitives-CmIK1O7L.js +1836 -0
- package/dist/primitives-CmIK1O7L.js.map +1 -0
- package/dist/resolver-DDZWomrF.js +165 -0
- package/dist/resolver-DDZWomrF.js.map +1 -0
- package/dist/resolver-Dey6omBe.cjs +4 -0
- package/dist/resolver-Dey6omBe.cjs.map +1 -0
- package/dist/throttle.d.ts +11 -0
- package/dist/throttle.d.ts.map +1 -0
- package/dist/throttle.test.d.ts +2 -0
- package/dist/throttle.test.d.ts.map +1 -0
- package/dist/transfer.d.ts +34 -0
- package/dist/transfer.d.ts.map +1 -0
- package/dist/transport/generation-window.d.ts +15 -0
- package/dist/transport/generation-window.d.ts.map +1 -0
- package/dist/transport/generation-window.test.d.ts +2 -0
- package/dist/transport/generation-window.test.d.ts.map +1 -0
- package/dist/transport/handler.d.ts +18 -0
- package/dist/transport/handler.d.ts.map +1 -0
- package/dist/transport/index.cjs +1 -0
- package/dist/transport/index.d.ts +6 -0
- package/dist/transport/index.d.ts.map +1 -0
- package/dist/transport/index.mjs +2 -0
- package/dist/transport/packet.d.ts +36 -0
- package/dist/transport/packet.d.ts.map +1 -0
- package/dist/transport/packet.test.d.ts +2 -0
- package/dist/transport/packet.test.d.ts.map +1 -0
- package/dist/transport/quicklz.d.ts +5 -0
- package/dist/transport/quicklz.d.ts.map +1 -0
- package/dist/transport/quicklz.test.d.ts +2 -0
- package/dist/transport/quicklz.test.d.ts.map +1 -0
- package/dist/types-CGKgXvpG.js +18 -0
- package/dist/types-CGKgXvpG.js.map +1 -0
- package/dist/types-DrnoCdSW.cjs +2 -0
- package/dist/types-DrnoCdSW.cjs.map +1 -0
- package/dist/types.d.ts +114 -0
- package/dist/types.d.ts.map +1 -0
- package/package.json +87 -1
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"handler-C2vxlHYC.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 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\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 this.#logger.debug(\"packet decryption failed\", { type: pType, id: p.id });\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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"}
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
const e=require(`./types-DrnoCdSW.cjs`),t=require(`./crypt-handshake-Dbj2cSBZ.cjs`);let n=require(`node:dgram`);var r=function(e){return e[e.Voice=0]=`Voice`,e[e.VoiceWhisper=1]=`VoiceWhisper`,e[e.Command=2]=`Command`,e[e.CommandLow=3]=`CommandLow`,e[e.Ping=4]=`Ping`,e[e.Pong=5]=`Pong`,e[e.Ack=6]=`Ack`,e[e.AckLow=7]=`AckLow`,e[e.Init1=8]=`Init1`,e}({}),i=function(e){return e[e.Fragmented=16]=`Fragmented`,e[e.NewProtocol=32]=`NewProtocol`,e[e.Compressed=64]=`Compressed`,e[e.Unencrypted=128]=`Unencrypted`,e}({});function a(e){return e.typeFlagged&15}function o(e){return e.typeFlagged&240}function s(e){return(o(e)&i.Unencrypted)!==0}function c(e){let t=new Uint8Array(5),n=new DataView(t.buffer);return n.setUint16(0,e.id,!1),n.setUint16(2,e.clientID,!1),t[4]=e.typeFlagged,t}function l(e){return{id:new DataView(e.buffer,e.byteOffset,e.byteLength).getUint16(0,!1),typeFlagged:e[2]}}function u(e){let t=new DataView(e.buffer,e.byteOffset,e.byteLength);return{id:t.getUint16(0,!1),clientID:t.getUint16(2,!1),typeFlagged:e[4]}}var d=class{#e=0;#t=0;#n;#r;constructor(e,t){this.#n=e,this.#r=t}get generation(){return this.#t}advance(e){if(e<=0)return;let t=this.#e+e,n=Math.floor(t/this.#n);n>0&&(this.#t=Math.min(this.#t+n,4294967295)),this.#e=t%this.#n}advanceToExcluded(e){let t=e-this.#e;t<0&&(t+=this.#n),this.advance(t+1)}syncTo(e){let t=e-this.#e;t<0&&(t+=this.#n),this.advance(t)}isInWindow(e){let t=this.#e+this.#r;return t<this.#n?e>=this.#e&&e<t:e>=this.#e||e<t-this.#n}mappedToIndex(e){return this.#i(e)?e+this.#n-this.#e:e-this.#e}isOldPacket(e){return this.mappedToIndex(e)<0}isFuturePacket(e){return this.mappedToIndex(e)>=this.#r}#i(e){return this.#e>this.#n-this.#r&&e<this.#e+this.#r-this.#n}getGeneration(e){return this.#i(e)?this.#t+1:this.#t}reset(){this.#e=0,this.#t=0}},f=4096,p=class{#e=new Int32Array(f);decompress(e){let{headerLen:t,decompressedSize:n,flags:r}=m(e),i=new Uint8Array(n);if(!(r&1))return i.set(e.slice(t,t+n)),i;this.#e.fill(0);let a={control:1,sourcePos:t,destPos:0,nextHashed:0};for(;this.#t(e,a);)if(a.control&1){if(!this.#n(e,i,a))break}else if(this.#r(e,i,n,a))break;return i}#t(e,t){return t.control===1?t.sourcePos+4>e.length?!1:(t.control=(e[t.sourcePos]|e[t.sourcePos+1]<<8|e[t.sourcePos+2]<<16|e[t.sourcePos+3]<<24)>>>0,t.sourcePos+=4,!0):!0}#n(e,t,n){if(n.control=n.control>>>1>>>0,n.sourcePos+2>e.length)return!1;let r=e[n.sourcePos],i=e[n.sourcePos+1];n.sourcePos+=2;let a=r>>4|i<<4,o=r&15;if(o!==0)o+=2;else{if(n.sourcePos>=e.length)return!1;o=e[n.sourcePos],n.sourcePos++}let s=this.#e[a];for(let e=0;e<o;e++)n.destPos<t.length&&s+e<n.destPos&&(t[n.destPos]=t[s+e],n.destPos++);let c=n.destPos+1-o;return this.#i(t,n,c),n.nextHashed=n.destPos,!0}#r(e,t,n,r){let i=Math.max(n,10)-10;if(r.destPos>=i){for(;r.destPos<n;){if(r.control===1){if(r.sourcePos+=4,r.sourcePos>e.length)break;r.control=(e[r.sourcePos-4]|e[r.sourcePos-3]<<8|e[r.sourcePos-2]<<16|e[r.sourcePos-1]<<24)>>>0}if(r.sourcePos>=e.length)break;t[r.destPos++]=e[r.sourcePos++],r.control=r.control>>>1>>>0}return!0}if(r.sourcePos>=e.length||r.destPos>=t.length)return!0;t[r.destPos++]=e[r.sourcePos++],r.control=r.control>>>1>>>0;let a=Math.max(r.destPos-2,0);return this.#i(t,r,a),r.nextHashed<a&&(r.nextHashed=a),!1}#i(e,t,n){for(;t.nextHashed<n&&!(t.nextHashed+3>e.length);){let n=(e[t.nextHashed]|e[t.nextHashed+1]<<8|e[t.nextHashed+2]<<16)>>>0,r=(n>>12^n)&4095;this.#e[r]=t.nextHashed,t.nextHashed++}}};function m(e){if(e.length<3)throw Error(`QuickLZ: data too short`);let t=e[0];if((t>>2&3)!=1)throw Error(`QuickLZ: only level 1 is supported`);let n=t&2?9:3;if(e.length<n)throw Error(`QuickLZ: data too short for header`);let r;return r=t&2?(e[5]|e[6]<<8|e[7]<<16|e[8]<<24)>>>0:e[2],{headerLen:n,decompressedSize:r,flags:t}}var h=500,g=1024,_=5e3,v=6e4,y=1e3,b=5,x=8,S=3,C=500,w=100,T=class{onPacket=null;onClosed=null;#e;#t;#n=null;#r=0;#i=!1;#a=null;#o=null;#s=Date.now();#c=new Uint16Array(9);#l=new Uint32Array(9);#u=new d(65536,g);#d=new d(65536,g);#f=new d(65536,g);#p=new d(65536,g);#m=new Map;#h=new Map;#g=new Map;#_=null;constructor(t,n=e.r){this.#e=t,this.#t=n}setClientID(e){this.#r=e}connect(e){return new Promise((t,r)=>{let[i,a]=e.lastIndexOf(`:`)>0?[e.slice(0,e.lastIndexOf(`:`)),e.slice(e.lastIndexOf(`:`)+1)]:[e,`9987`],o=parseInt(a,10),s=(0,n.createSocket)(`udp4`);s.once(`error`,r),s.connect(o,i,()=>{s.off(`error`,r),this.start(s),t()})})}start(e){this.#n=e,this.#i=!1,this.#s=Date.now(),e.on(`message`,e=>{this.#s=Date.now(),this.#x(new Uint8Array(e.buffer,e.byteOffset,e.byteLength))}),e.on(`error`,e=>{this.#t.error(`udp error`,e),this.#R(e)}),e.on(`close`,()=>this.#R(null)),this.#c[r.Command]=1,this.#c[r.Init1]=101;let n=t.n(this.#e,null);n&&this.#y(r.Init1,n,0);let a=setInterval(()=>{this.#e.cryptoInitComplete&&this.sendPacket(r.Ping,new Uint8Array,i.Unencrypted)},_);this.#a=()=>clearInterval(a);let o=setInterval(()=>this.#I(),w);this.#o=()=>clearInterval(o)}receivedFinalInitAck(){this.#_=null}sendPacket(e,t,n){let i=!this.#e.cryptoInitComplete;if(t.length>487&&e!==r.Voice&&e!==r.VoiceWhisper){this.#v(e,t,n,i);return}this.#y(e,t,n,i)}sendVoicePacket(e,t){let n=this.#c[r.Voice],a=this.#l[r.Voice];this.#c[r.Voice]=n+1&65535,this.#c[r.Voice]===0&&this.#l[r.Voice]++;let o=S+e.length,s=new Uint8Array(o);new DataView(s.buffer).setUint16(0,n,!1),s[2]=t,s.set(e,S);let l=c({typeFlagged:r.Voice|i.Unencrypted,id:n,clientID:this.#r,generationID:a,data:s,receivedAt:0}),u=new Uint8Array(x+b+o);u.set(this.#e.fakeSignature,0),u.set(l,x),u.set(s,x+b),this.#b(u)}close(){this.#i||(this.#i=!0,this.#a?.(),this.#o?.(),this.#n?.close())}#v(e,t,n,r){let a=h-b-x,o=0,s=!0;for(;o<t.length;){let c=Math.min(t.length-o,a),l=o+c===t.length,u=n;s!==l&&(u|=i.Fragmented),this.#y(e,t.slice(o,o+c),u,r),o+=c,s=!1}}#y(e,t,n,r=!this.#e.cryptoInitComplete){n=E(e,n);let[a,o]=this.#P(e),s={typeFlagged:e|n,id:a,clientID:this.#r,generationID:o,data:t,receivedAt:0},l=(n&i.Unencrypted)!==0,u=c(s),[d,f]=this.#e.encrypt(e,a,o,u,t,r,l),p=new Uint8Array(x+b+d.length);p.set(f.slice(0,x),0),p.set(u,x),p.set(d,x+b),this.#b(p);let m={packet:s,firstSend:Date.now(),lastSend:Date.now(),retryCount:0,nextInterval:C};this.#F(e,s,m)}#b(e){this.#n?.send(Buffer.from(e),e=>{e&&this.#t.warn(`udp send error`,e)})}#x(e){if(e.length<11)return;let t=e.slice(0,x),n=e.slice(x,x+3),i=e.slice(x+3),o=l(n),s={...o,clientID:0,generationID:this.#S(o.id,o.typeFlagged&15),data:new Uint8Array,receivedAt:Date.now()},c=this.#C(s,n,i,t);if(c!==null){if(s.data=c.plaintext,a(s)===r.Ping){this.#E(s.id,c.dummyUsed);return}this.#w(s,c.dummyUsed)&&(this.#D(s),this.#N(s))}}#S(e,t){switch(t){case r.Command:return this.#u.getGeneration(e);case r.CommandLow:return this.#d.getGeneration(e);case r.Ack:return this.#f.getGeneration(e);case r.AckLow:return this.#p.getGeneration(e);default:return 0}}#C(e,t,n,s){let c=(o(e)&i.Unencrypted)!==0,l=!this.#e.cryptoInitComplete,u=l,d=a(e),f=e.generationID;try{return{plaintext:this.#e.decrypt(d,e.id,f,t,n,s,l,c),dummyUsed:u}}catch{for(let r of[-1,1]){let i=f+r;if(!(i<0))try{return{plaintext:this.#e.decrypt(d,e.id,i,t,n,s,!1,!1),dummyUsed:!1}}catch{}}if(d===r.Command||d===r.CommandLow||d===r.Ack)try{return{plaintext:this.#e.decrypt(d,e.id,f,t,n,s,!0,c),dummyUsed:!0}}catch{}return this.#t.debug(`packet decryption failed`,{type:d,id:e.id}),null}}#w(e,t){let n=a(e);if(n!==r.Command&&n!==r.CommandLow)return!0;let i=n===r.Command?this.#u:this.#d,o=n===r.Command?r.Ack:r.AckLow;return i.isInWindow(e.id)?(this.#T(e.id,o,t),!0):(i.isOldPacket(e.id)&&this.#T(e.id,o,t),!1)}#T(e,t,n){let r=new Uint8Array(2);new DataView(r.buffer).setUint16(0,e,!1),this.#y(t,r,0,n)}#E(e,t){let n=new Uint8Array(2);new DataView(n.buffer).setUint16(0,e,!1),this.#y(r.Pong,n,i.Unencrypted,t)}#D(e){let t=a(e);if(t!==r.Command&&t!==r.CommandLow){this.onPacket?.(e);return}let n=t===r.Command,i=n?this.#m:this.#h,o=n?this.#u:this.#d;for(i.set(e.id,e),n?this.#A(i,o,!0):this.#A(i,o,!1);;){let e=n?this.#O:this.#k,t=i.get(e);if(t===void 0)break;let r=this.#j(t,i,e,o);if(!r)break;let[a,s]=r;n?this.#O=s:this.#k=s,this.#M(a),this.onPacket?.(a)}}#O=0;#k=0;#A(e,t,n){let r=n?this.#O:this.#k;for(;!e.has(r)&&D(e,r);)r=r+1&65535,t.advance(1);n?this.#O=r:this.#k=r}#j(e,t,n,r){if((o(e)&i.Fragmented)===0)return t.delete(n),r.advance(1),[e,n+1&65535];let a=[],s=0,c=n,l=!1,u=!1;for(;;){let e=t.get(c);if(!e)return null;a.push(e),s+=e.data.length;let n=(o(e)&i.Fragmented)!==0;if(!l){if(l=!0,!n){u=!0;break}}else if(n){u=!0;break}c=c+1&65535}if(!u)return null;let d=new Uint8Array(s),f=0;for(let e of a)d.set(e.data,f),f+=e.data.length,t.delete(n),r.advance(1),n=n+1&65535;return e.data=d,e.typeFlagged&=~i.Fragmented,[e,n]}#M(e){if((o(e)&i.Compressed)!==0)try{e.data=new p().decompress(e.data),e.typeFlagged&=~i.Compressed}catch(t){this.#t.debug(`decompression failed`,{id:e.id,err:t})}}#N(e){let t=a(e);if(t===r.Init1){this.#_=null;return}if((t===r.Ack||t===r.AckLow)&&e.data.length>=2){let n=new DataView(e.data.buffer,e.data.byteOffset).getUint16(0,!1),i=(t===r.Ack?r.Command:r.CommandLow)<<16|n;this.#g.delete(i)}}#P(e){let t=this.#c[e],n=this.#l[e];return e===r.Init1?[t,n]:(this.#c[e]=t+1&65535,this.#c[e]===0&&(this.#l[e]=n+1>>>0),e===r.Command?this.#f.advanceToExcluded(t):e===r.CommandLow&&this.#p.advanceToExcluded(t),[t,n])}#F(e,t,n){if(e===r.Init1){this.#_=n;return}if(e===r.Command||e===r.CommandLow){let r=e<<16|t.id;this.#g.set(r,n)}}#I(){let e=Date.now();if(e-this.#s>v){this.#t.warn(`idle timeout`),this.#R(Error(`idle timeout`));return}this.#_&&this.#L(this.#_,e);for(let[t,n]of this.#g){if(e-n.firstSend>v){this.#g.delete(t),this.#R(Error(`packet ack timeout`));return}this.#L(n,e)}}#L(e,t){if(t-e.lastSend<e.nextInterval)return;e.lastSend=t,e.retryCount++,e.nextInterval=Math.min(e.nextInterval*2,y);let n=!this.#e.cryptoInitComplete,r=(o(e.packet)&i.Unencrypted)!==0,s=c(e.packet),l=a(e.packet),[u,d]=this.#e.encrypt(l,e.packet.id,e.packet.generationID,s,e.packet.data,n,r),f=new Uint8Array(x+b+u.length);f.set(d.slice(0,x),0),f.set(s,x),f.set(u,x+b),this.#b(f)}#R(e){this.#i||(this.close(),this.onClosed?.(e))}};function E(e,t){return e===r.Command||e===r.CommandLow?t|i.NewProtocol:t}function D(e,t){let n=Date.now();for(let[r,i]of e)if((r-t+65536&65535)<32768&&n-i.receivedAt>5e3)return!0;return!1}Object.defineProperty(exports,`a`,{enumerable:!0,get:function(){return r}}),Object.defineProperty(exports,`c`,{enumerable:!0,get:function(){return o}}),Object.defineProperty(exports,`d`,{enumerable:!0,get:function(){return l}}),Object.defineProperty(exports,`i`,{enumerable:!0,get:function(){return i}}),Object.defineProperty(exports,`l`,{enumerable:!0,get:function(){return a}}),Object.defineProperty(exports,`n`,{enumerable:!0,get:function(){return p}}),Object.defineProperty(exports,`o`,{enumerable:!0,get:function(){return c}}),Object.defineProperty(exports,`r`,{enumerable:!0,get:function(){return d}}),Object.defineProperty(exports,`s`,{enumerable:!0,get:function(){return s}}),Object.defineProperty(exports,`t`,{enumerable:!0,get:function(){return T}}),Object.defineProperty(exports,`u`,{enumerable:!0,get:function(){return u}});
|
|
2
|
+
//# sourceMappingURL=handler-DQteUMKT.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"handler-DQteUMKT.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\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 this.#logger.debug(\"packet decryption failed\", { type: pType, id: p.id });\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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"}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import type { Crypt } from "../crypto/crypt.js";
|
|
2
|
+
export declare const INIT_VERSION = 1566914096;
|
|
3
|
+
/**
|
|
4
|
+
* Handle the TS3INIT1 handshake steps.
|
|
5
|
+
* Returns the response bytes to send, or null if nothing should be sent.
|
|
6
|
+
*/
|
|
7
|
+
export declare function processInit1(crypt: Crypt, data: Uint8Array | null): Uint8Array | null;
|
|
8
|
+
//# sourceMappingURL=crypt-handshake.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"crypt-handshake.d.ts","sourceRoot":"","sources":["../../src/handshake/crypt-handshake.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,oBAAoB,CAAC;AAEhD,eAAO,MAAM,YAAY,aAAa,CAAC;AAMvC;;;GAGG;AACH,wBAAgB,YAAY,CAAC,KAAK,EAAE,KAAK,EAAE,IAAI,EAAE,UAAU,GAAG,IAAI,GAAG,UAAU,GAAG,IAAI,CAiBrF"}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import type { Crypt } from "../crypto/crypt.js";
|
|
2
|
+
/**
|
|
3
|
+
* CryptoInit2 performs the second stage of crypto initialization (Ed25519 ECDH).
|
|
4
|
+
* Mirrors Go's handshake.CryptoInit2.
|
|
5
|
+
*/
|
|
6
|
+
export declare function cryptoInit2(crypt: Crypt, license: string, omega: string, proof: string, beta: string, privateKey: Uint8Array): void;
|
|
7
|
+
//# sourceMappingURL=crypt-init2.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"crypt-init2.d.ts","sourceRoot":"","sources":["../../src/handshake/crypt-init2.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,oBAAoB,CAAC;AAKhD;;;GAGG;AACH,wBAAgB,WAAW,CACzB,KAAK,EAAE,KAAK,EACZ,OAAO,EAAE,MAAM,EACf,KAAK,EAAE,MAAM,EACb,KAAK,EAAE,MAAM,EACb,IAAI,EAAE,MAAM,EACZ,UAAU,EAAE,UAAU,GACrB,IAAI,CAqBN"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
Object.defineProperty(exports,Symbol.toStringTag,{value:`Module`});const e=require(`../crypt-handshake-Dbj2cSBZ.cjs`),t=require(`../crypt-init2-BIbQ7TN0.cjs`);exports.INIT_VERSION=e.t,exports.LicenseChain=t.n,exports.cryptoInit2=t.t,exports.parseLicenses=t.r,exports.processInit1=e.n;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/handshake/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,YAAY,EAAE,MAAM,sBAAsB,CAAC;AAClE,OAAO,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAC;AAC/C,OAAO,EAAE,YAAY,EAAE,aAAa,EAAE,MAAM,cAAc,CAAC"}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
declare const enum LicenseBlockType {
|
|
2
|
+
Intermediate = 0,
|
|
3
|
+
Server = 2,
|
|
4
|
+
Ts5Server = 8,
|
|
5
|
+
Ephemeral = 32
|
|
6
|
+
}
|
|
7
|
+
interface LicenseBlock {
|
|
8
|
+
readonly key: Uint8Array;
|
|
9
|
+
readonly hash: Uint8Array;
|
|
10
|
+
properties: Uint8Array[];
|
|
11
|
+
issuer: string;
|
|
12
|
+
notValidBefore: Date;
|
|
13
|
+
notValidAfter: Date;
|
|
14
|
+
blockType: LicenseBlockType;
|
|
15
|
+
serverType: number;
|
|
16
|
+
}
|
|
17
|
+
export declare class LicenseChain {
|
|
18
|
+
readonly blocks: LicenseBlock[];
|
|
19
|
+
constructor(blocks: LicenseBlock[]);
|
|
20
|
+
/**
|
|
21
|
+
* Derive the session key by chaining Ed25519 point arithmetic starting from
|
|
22
|
+
* the root key through each license block.
|
|
23
|
+
*/
|
|
24
|
+
deriveKey(): Uint8Array<ArrayBuffer>;
|
|
25
|
+
}
|
|
26
|
+
export declare function parseLicenses(data: Uint8Array): LicenseChain;
|
|
27
|
+
export {};
|
|
28
|
+
//# sourceMappingURL=license.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"license.d.ts","sourceRoot":"","sources":["../../src/handshake/license.ts"],"names":[],"mappings":"AAUA,mBAAW,gBAAgB;IACzB,YAAY,IAAI;IAChB,MAAM,IAAI;IACV,SAAS,IAAI;IACb,SAAS,KAAK;CACf;AAED,UAAU,YAAY;IACpB,QAAQ,CAAC,GAAG,EAAE,UAAU,CAAC;IACzB,QAAQ,CAAC,IAAI,EAAE,UAAU,CAAC;IAC1B,UAAU,EAAE,UAAU,EAAE,CAAC;IACzB,MAAM,EAAE,MAAM,CAAC;IACf,cAAc,EAAE,IAAI,CAAC;IACrB,aAAa,EAAE,IAAI,CAAC;IACpB,SAAS,EAAE,gBAAgB,CAAC;IAC5B,UAAU,EAAE,MAAM,CAAC;CACpB;AAED,qBAAa,YAAY;IACvB,QAAQ,CAAC,MAAM,EAAE,YAAY,EAAE,CAAC;gBAEpB,MAAM,EAAE,YAAY,EAAE;IAIlC;;;OAGG;IACH,SAAS,IAAI,UAAU,CAAC,WAAW,CAAC;CAOrC;AAED,wBAAgB,aAAa,CAAC,IAAI,EAAE,UAAU,GAAG,YAAY,CAc5D"}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import type { Client } from "./client.js";
|
|
2
|
+
/** Handle the `clientinitiv` message (P-256 based crypto path). */
|
|
3
|
+
export declare function handleHandshakeInitIV(client: Client, params: Record<string, string>): void;
|
|
4
|
+
/** Handle the `initivexpand2` message (Ed25519 / TS3 crypto path). */
|
|
5
|
+
export declare function handleHandshakeExpand2(client: Client, params: Record<string, string>): void;
|
|
6
|
+
/** Handle `initserver` — marks the client as connected. */
|
|
7
|
+
export declare function handleInitServer(client: Client, params: Record<string, string>): void;
|
|
8
|
+
export declare function sendClientInit(client: Client): void;
|
|
9
|
+
//# sourceMappingURL=handshake.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"handshake.d.ts","sourceRoot":"","sources":["../src/handshake.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,aAAa,CAAC;AAE1C,mEAAmE;AACnE,wBAAgB,qBAAqB,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,GAAG,IAAI,CAQ1F;AAED,sEAAsE;AACtE,wBAAgB,sBAAsB,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,GAAG,IAAI,CAY3F;AAED,2DAA2D;AAC3D,wBAAgB,gBAAgB,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,GAAG,IAAI,CAoBrF;AAwBD,wBAAgB,cAAc,CAAC,MAAM,EAAE,MAAM,GAAG,IAAI,CA0BnD"}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
export declare function parseUint64(s: string): bigint;
|
|
2
|
+
export declare function parseUint16(s: string): number;
|
|
3
|
+
export declare function parseInt10(s: string): number;
|
|
4
|
+
/**
|
|
5
|
+
* Reports whether `actual` equals `expected` or equals `expected` followed by
|
|
6
|
+
* only digits — the pattern TeamSpeak uses when a nickname is already taken.
|
|
7
|
+
*/
|
|
8
|
+
export declare function isAutoNicknameMatch(expected: string, actual: string): boolean;
|
|
9
|
+
/**
|
|
10
|
+
* Expand a pipe-separated multi-row TS3 command line into individual rows,
|
|
11
|
+
* each prefixed with the command name.
|
|
12
|
+
*/
|
|
13
|
+
export declare function splitCommandRows(line: string): string[];
|
|
14
|
+
//# sourceMappingURL=helpers.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"helpers.d.ts","sourceRoot":"","sources":["../src/helpers.ts"],"names":[],"mappings":"AAAA,wBAAgB,WAAW,CAAC,CAAC,EAAE,MAAM,GAAG,MAAM,CAO7C;AAED,wBAAgB,WAAW,CAAC,CAAC,EAAE,MAAM,GAAG,MAAM,CAI7C;AAED,wBAAgB,UAAU,CAAC,CAAC,EAAE,MAAM,GAAG,MAAM,CAG5C;AAED;;;GAGG;AACH,wBAAgB,mBAAmB,CAAC,QAAQ,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,OAAO,CAK7E;AAED;;;GAGG;AACH,wBAAgB,gBAAgB,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,EAAE,CAevD"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"helpers.test.d.ts","sourceRoot":"","sources":["../src/helpers.test.ts"],"names":[],"mappings":""}
|
package/dist/index.cjs
ADDED
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
Object.defineProperty(exports,Symbol.toStringTag,{value:`Module`});const e=require(`./types-DrnoCdSW.cjs`),t=require(`./primitives-BxtDMP7x.cjs`),n=require(`./crypto-C3gBJkh2.cjs`),r=require(`./resolver-Dey6omBe.cjs`),i=require(`./handler-DQteUMKT.cjs`),a=require(`./command-Cu2v-5-K.cjs`),o=require(`./crypt-handshake-Dbj2cSBZ.cjs`),s=require(`./crypt-init2-BIbQ7TN0.cjs`),c=require(`./parser-DhAWj-TI.cjs`);let l=require(`node:crypto`),u=require(`node:net`);var d=class{#e=new Map;#t=0;#n=[];#r=!1;register(){this.#t++;let e=this.#t;return[e,new Promise(t=>{this.#e.set(e,t)})]}unregister(e){this.#e.delete(e)}signalWelcomeComplete(){this.#r=!0,this.#n=[]}buffer(e){this.#r&&this.#e.size!==0&&this.#n.push(e)}resolve(e,t){let n=this.#e.get(e);if(!n){this.#n=[];return}let r=this.#n;this.#n=[],this.#e.delete(e),n({err:t,data:r})}discardBuffer(){this.#n=[]}reset(){this.#e.clear(),this.#n=[],this.#r=!1,this.#t=0}};function f(e){let n=e.id??`0`,r=e.msg??``,i=e.return_code,a=null;n!==`0`&&(a=new t.x(n,r));let o=null;if(i!==void 0&&i!==``){let e=parseInt(i,10);isNaN(e)||(o=e)}return{err:a,rc:o}}function p(e,t){return e.includes(`return_code=`)?e:`${e} return_code=${t}`}var m=class{#e=new Map;#t=0;register(){this.#t++,this.#t>65535&&(this.#t=1);let e=this.#t;return[e,new Promise(t=>{this.#e.set(e,t)})]}unregister(e){this.#e.delete(e)}notify(e,t){let n=this.#e.get(e);n&&n(t)}reset(){this.#e.clear(),this.#t=0}};function h(e,n,r){return new Promise((i,a)=>{let o=(0,u.createConnection)({host:e,port:n},()=>{o.write(r,e=>{e?(o.destroy(),a(new t.v(`failed to send transfer key: ${e.message}`))):i(o)})});o.setTimeout(1e4),o.once(`error`,a),o.once(`timeout`,()=>{o.destroy(),a(new t.v(`connection timeout`))})})}async function g(e,t,n){let r=await h(e,t.port,t.fileTransferKey);await new Promise((e,t)=>{n.pipe(r),r.on(`finish`,e),r.on(`error`,t)})}async function _(e,t,n){let r=await h(e,t.port,t.fileTransferKey);await new Promise((e,t)=>{r.pipe(n),n.on(`finish`,e),r.on(`error`,t),n.on(`error`,t)})}function v(e,t,n,r,i,o){let s=t.startsWith(`/`)?t:`/${t}`;return a.t(`ftinitupload`,{cid:String(e),name:s,cpw:n,size:String(r),clientftfid:String(i),overwrite:o?`1`:`0`,resume:`0`})}function y(e,t,n,r){let i=t.startsWith(`/`)?t:`/${t}`;return a.t(`ftinitdownload`,{cid:String(e),name:i,cpw:n,clientftfid:String(r),seekpos:`0`})}function b(e,t){let n=t;for(let t=e.length-1;t>=0;t--)n=e[t](n);return n}function x(e,t){let n=t;for(let t=e.length-1;t>=0;t--)n=e[t](n);return n}function S(e,t){let n=t.alpha??``,r=t.beta??``,i=t.omega??``;e.crypt.initCrypto(n,r,i),e.logger.info(`crypto initialized (P-256 path), sending clientinit`),D(e)}function C(e,t){e.logger.info(`received initivexpand2`),e.handler.receivedFinalInitAck();let n=t.l??``,r=t.omega??``,i=t.proof??``,a=t.beta??``,o=T(e,a);s.t(e.crypt,n,r,i,a,o),D(e)}function w(e,t){let n=t.aclid??t.clid??``,r=n?parseInt(n,10):0;r>0&&(e.clid=r,e.handler.setClientID(r)),e.logger.info(`connected to server`,{selfId:e.clid}),e._markConnected(),setImmediate(()=>{let t=a.t(`clientupdate`,{client_input_muted:`0`,client_output_muted:`0`});e.sendCommandNoWait(t).catch(()=>{})})}function T(e,n){let[r,o]=t.n(),s=Buffer.from(r).toString(`base64`),c=E(e,r,n),l=a.n(`clientek`,[[`ek`,s],[`proof`,c]]);return e.handler.sendPacket(i.a.Command,Buffer.from(l),0),o}function E(e,n,r){let i=Buffer.from(r,`base64`),a=new Uint8Array(86);a.set(n.slice(0,32)),a.set(i.slice(0,Math.min(54,i.length)),32);let o=t.i(e.crypt.identity.privateKey,a);return Buffer.from(o).toString(`base64`)}function D(e){let t=e.crypt.identity.publicKeyBase64(),n=(0,l.createHash)(`sha256`).update(t).digest().slice(0,16).toString(`base64`),r=a.n(`clientinit`,[[`client_nickname`,e.nickname],[`client_version`,`3.5.3 [Build: 1587971024]`],[`client_platform`,`Windows`],[`client_input_hardware`,`1`],[`client_output_hardware`,`1`],[`client_default_channel`,``],[`client_default_channel_password`,``],[`client_server_password`,``],[`client_meta_data`,``],[`client_version_sign`,`Kvmj7qX6wJCPI5GVT71samfmhz/bvs7M+OTXWB/JWxdQbxDe17xda7dzUWLX7pjvdJTqZmbse1HBmTxThPKvAg==`],[`client_key_offset`,String(e.crypt.identity.offset)],[`client_nickname_phonetic`,``],[`client_default_token`,``],[`hwid`,n]]);e.handler.sendPacket(i.a.Command,Buffer.from(r),0)}function O(e){if(e===``||e===void 0)return 0n;try{return BigInt(e)}catch{return 0n}}function k(e){let t=parseInt(e,10);return isNaN(t)||t<0||t>65535?0:t}function A(e){let t=parseInt(e,10);return isNaN(t)?0:t}function j(e,t){if(t===e)return!0;if(!t.startsWith(e))return!1;let n=t.slice(e.length);return/^\d+$/.test(n)}function M(e){let t=e.indexOf(` `);if(t<0)return[e];let n=e.slice(0,t),r=e.slice(t+1);if(!r.includes(`|`))return[e];let i=r.split(`|`),a=[];for(let e of i)e!==``&&a.push(`${n} ${e}`);return a.length===0?[e]:a}function N(e,t,n,r){switch(e.name){case`notifycliententerview`:return P(e,n,r);case`notifyclientleftview`:return F(e,t,n);case`notifyclientmoved`:return I(e,n);case`notifytextmessage`:return L(e,n);case`notifyclientpoke`:return V(e);case`notifystartupload`:return{kind:`startUpload`,info:R(e)};case`notifystartdownload`:return{kind:`startDownload`,info:z(e)};case`notifystatusfiletransfer`:return{kind:`fileTransferStatus`,info:B(e)};default:return{kind:`unknown`}}}function P(e,t,n){let r=k(e.params.clid??``),i=O(e.params.cid??``),a=A(e.params.client_type??``),o=e.params.client_servergroups??``,s={id:r,nickname:e.params.client_nickname??``,uid:e.params.client_unique_identifier??``,channelID:i,type:a,serverGroups:o?o.split(`,`):[]};return r!==0&&t.set(r,s),{kind:`clientEnter`,info:s}}function F(e,t,n){let r=k(e.params.clid??``),i=A(e.params.reasonid??``),a=r===t;return r!==0&&n.delete(r),{kind:`clientLeave`,event:{id:r,reasonID:i,reasonMsg:e.params.reasonmsg??``,targetID:k(e.params.targetid??``)},isSelf:a}}function I(e,t){let n=k(e.params.clid??``),r=O(e.params.ctid??``);if(n!==0){let e=t.get(n);e&&t.set(n,{...e,channelID:r})}return{kind:`clientMoved`,event:{id:n,targetChannelID:r,reasonID:A(e.params.reasonid??``),invokerID:k(e.params.invokerid??``),invokerName:e.params.invokername??``,invokerUID:e.params.invokeruid??``}}}function L(e,t){let n=k(e.params.invokerid??``),r=t.get(n);return{kind:`textMessage`,message:{targetMode:A(e.params.targetmode??``),targetID:O(e.params.target??``),invokerID:n,invokerName:e.params.invokername??``,invokerUID:e.params.invokeruid??r?.uid??``,message:a.i(e.params.msg??``),invokerGroups:r?.serverGroups??[]}}}function R(e){return{clientFileTransferID:k(e.params.clientftfid??``),serverFileTransferID:k(e.params.serverftfid??``),fileTransferKey:e.params.ftkey??``,port:k(e.params.port??``),seekPosition:O(e.params.seekpos??``)}}function z(e){return{clientFileTransferID:k(e.params.clientftfid??``),serverFileTransferID:k(e.params.serverftfid??``),fileTransferKey:e.params.ftkey??``,port:k(e.params.port??``),size:O(e.params.size??``)}}function B(e){return{clientFileTransferID:k(e.params.clientftfid??``),status:A(e.params.status??``),message:e.params.msg??``}}function V(e){return{kind:`poked`,event:{invokerID:k(e.params.invokerid??``),invokerName:a.i(e.params.invokername??``),invokerUID:e.params.invokeruid??``,message:a.i(e.params.msg??``)}}}var H=class e{static TOKEN_RATE=4;static TOKEN_MAX=8;#e=5;#t=Date.now();async wait(t){for(;;){if(t?.aborted)throw t.reason;let n=Date.now(),r=(n-this.#t)/1e3;if(this.#e=Math.min(this.#e+r*e.TOKEN_RATE,e.TOKEN_MAX),this.#t=n,this.#e>=1){--this.#e;return}let i=Math.ceil((1-this.#e)/e.TOKEN_RATE*1e3)+10;await new Promise((e,n)=>{let r=setTimeout(e,i);t&&t.addEventListener(`abort`,()=>{clearTimeout(r),n(t.reason)},{once:!0})})}}},U=class{crypt;handler;logger;nickname;clid=0;#e;#t;#n;#r=e.t.Disconnected;#i=new H;#a=new d;#o=new m;#s=new Map;#c=[];#l=[];#u=[];#d=[];#f=[];#p=[];#m=[];#h=[];#g=[];#_=[];#v=[];#y=[];#b;#x;constructor(t,a,o,s={}){this.#e=t,this.#t=a,this.nickname=o,this.logger=s.logger??e.n,this.#n=s.resolver??new r.t(this.logger),this.crypt=new n.t(t),this.handler=new i.t(this.crypt,this.logger),this.handler.onPacket=e=>this.#w(e),this.handler.onClosed=e=>this.#N(e),s.commandMiddleware&&this.#v.push(...s.commandMiddleware),s.eventMiddleware&&this.#y.push(...s.eventMiddleware),this.#b=this.#P(),this.#x=this.#F()}get status(){return this.#r}async connect(){if(this.#r!==e.t.Disconnected)throw new t.p;this.#S(),this.#r=e.t.Connecting;let n=await this.#C();this.logger.info(`connecting to server`,{address:n}),await this.handler.connect(n)}async disconnect(){if(this.#r===e.t.Disconnected)return;let t=this.#r===e.t.Connected;if(this.#r=e.t.Disconnected,this.logger.info(`disconnecting from server`),t)try{await this.execCommand(`clientdisconnect reasonmsg=Shutdown`,1e3)}catch{}this.handler.close();let n=this.#g.slice();for(let e of n)setImmediate(()=>e(void 0))}waitConnected(t){return this.#r===e.t.Connected?Promise.resolve():new Promise((e,n)=>{this.#c.push(e),t&&t.addEventListener(`abort`,()=>n(t.reason),{once:!0})})}async sendCommandNoWait(e){await this.#i.wait(),await this.#b(e)}async execCommand(e,t=1e4){await this.execCommandWithResponse(e,t)}async execCommandWithResponse(e,n=1e4){let[r,i]=this.#a.register(),a=p(e,r);try{await this.#i.wait(),await this.#b(a)}catch(e){throw this.#a.unregister(r),e}let o=await Promise.race([i,new Promise((r,i)=>setTimeout(()=>i(new t.m(e)),n))]);if(this.#a.unregister(r),o.err)throw o.err;return o.data}on(e,t){switch(e){case`textMessage`:this.#l.push(t);break;case`clientEnter`:this.#u.push(t);break;case`clientLeave`:this.#d.push(t);break;case`clientMoved`:this.#f.push(t);break;case`poked`:this.#p.push(t);break;case`voiceData`:this.#m.push(t);break;case`connected`:this.#h.push(t);break;case`disconnected`:this.#g.push(t);break;case`kicked`:this.#_.push(t);break}return this}useCommandMiddleware(...e){return this.#v.push(...e),this.#b=this.#P(),this}useEventMiddleware(...e){return this.#y.push(...e),this.#x=this.#F(),this}clientID(){return this.clid}channelID(){return this.#s.get(this.clid)?.channelID??0n}sendVoice(e,t){this.handler.sendVoicePacket(e,t)}async fileTransferInitUpload(e,n,r,i,a=!1){let[o,s]=this.#o.register(),c=v(e,n,r,i,o,a);try{await this.execCommand(c,1e4)}catch(e){throw this.#o.unregister(o),e}let l=await Promise.race([s,new Promise((e,n)=>setTimeout(()=>n(new t.y),1e4))]);if(this.#o.unregister(o),`size`in l)throw new t.v(`unexpected download response`);if(`status`in l){let e=l;throw new t.v(`${e.message} (status=${e.status})`)}return l}async fileTransferInitDownload(e,n,r){let[i,a]=this.#o.register(),o=y(e,n,r,i);try{await this.execCommand(o,1e4)}catch(e){throw this.#o.unregister(i),e}let s=await Promise.race([a,new Promise((e,n)=>setTimeout(()=>n(new t.y),1e4))]);if(this.#o.unregister(i),`seekPosition`in s)throw new t.v(`unexpected upload response`);if(`status`in s){let e=s;throw new t.v(`${e.message} (status=${e.status})`)}return s}uploadFileData(e,t,n){return g(e,t,n)}downloadFileData(e,t,n){return _(e,t,n)}_markConnected(){this.#r=e.t.Connected;for(let e of this.#c)e();this.#c=[];let t=this.#h.slice();for(let e of t)setImmediate(()=>e())}#S(){this.handler.close(),this.crypt=new n.t(this.#e),this.handler=new i.t(this.crypt,this.logger),this.handler.onPacket=e=>this.#w(e),this.handler.onClosed=e=>this.#N(e),this.#a.reset(),this.#o.reset(),this.#s.clear(),this.clid=0,this.#b=this.#P()}async#C(){let e=this.#t.includes(`:`)?this.#t:`${this.#t}:9987`;try{return(await this.#n.resolve(this.#t))[0]?.addr??e}catch{return e}}#w(e){this.#T(e)}#T(e){let t=e.typeFlagged&15;if(t===8){let t=o.n(this.crypt,e.data);t&&this.handler.sendPacket(i.a.Init1,t,0);return}if((t===0||t===1)&&e.data.length>5){this.#E(e.data);return}(t===2||t===3)&&e.data.length>0&&this.#D(Buffer.from(e.data).toString(`utf8`))}#E(e){if(this.#m.length===0)return;let t=new DataView(e.buffer,e.byteOffset,e.byteLength).getUint16(2,!1);if(t===this.clid)return;let n={clientId:t,codec:e[4],data:e.subarray(5)};for(let e of this.#m)setImmediate(()=>e(n))}#D(e){if(!e)return;let t=e.split(/[\n\0]/);for(let e of t){let t=e.replace(/\r$/,``);if(t)for(let e of M(t))this.#O(e)}}#O(e){let t=c.t(e);if(!(!t||!t.name)){if(t.name.startsWith(`notify`)){let e=N(t,this.clid,this.#s,this.nickname);this.#A(e,t.params);return}switch(t.name){case`clientinitiv`:S(this,t.params);break;case`initivexpand2`:C(this,t.params);break;case`initserver`:w(this,t.params);break;case`error`:this.#k(t.params);break;default:{let e=t.params;if(t.name.includes(`=`)){let n=t.name.indexOf(`=`),r=t.name.slice(0,n),i=t.name.slice(n+1);e={[r]:i,...t.params}}this.#a.buffer(e);break}}}}#k(e){let{err:t,rc:n}=f(e);n===null?this.#a.discardBuffer():this.#a.resolve(n,t),(e.id??`0`)===`3329`&&setImmediate(()=>this.disconnect().catch(()=>{}))}#A(e,t){switch(e.kind){case`clientEnter`:{let t=e.info;t.id!==0&&j(this.nickname,t.nickname)&&(this.clid=t.id,this.handler.setClientID(t.id),this.#a.signalWelcomeComplete()),this.#j(`clientEnter`,t);break}case`clientLeave`:if(this.#j(`clientLeave`,e.event),e.isSelf&&(e.event.reasonID===4||e.event.reasonID===5)){let t=e.event.reasonMsg;for(let e of this.#_)setImmediate(()=>e(t))}break;case`clientMoved`:this.#j(`clientMoved`,e.event);break;case`textMessage`:this.#j(`textMessage`,e.message);break;case`poked`:this.#j(`poked`,e.event);break;case`startUpload`:this.#o.notify(e.info.clientFileTransferID,e.info);break;case`startDownload`:this.#o.notify(e.info.clientFileTransferID,e.info);break;case`fileTransferStatus`:this.#o.notify(e.info.clientFileTransferID,e.info);break}}#j(e,t){this.#x(t)}#M(e,t){switch(e){case`textMessage`:for(let e of this.#l)setImmediate(()=>e(t));break;case`clientEnter`:for(let e of this.#u)setImmediate(()=>e(t));break;case`clientLeave`:for(let e of this.#d)setImmediate(()=>e(t));break;case`clientMoved`:for(let e of this.#f)setImmediate(()=>e(t));break;case`poked`:for(let e of this.#p)setImmediate(()=>e(t));break}}#N(t){if(this.#r===e.t.Disconnected)return;this.#r=e.t.Disconnected;let n=this.#g.slice();for(let e of n)setImmediate(()=>e(t??void 0))}#P(){return b(this.#v,async e=>{this.handler.sendPacket(i.a.Command,Buffer.from(e),0)})}#F(){return x(this.#y,e=>{typeof e==`object`&&e&&`invokerName`in e&&`message`in e&&`targetMode`in e?this.#M(`textMessage`,e):typeof e==`object`&&e&&`invokerName`in e&&`message`in e&&!(`targetMode`in e)?this.#M(`poked`,e):typeof e==`object`&&e&&`id`in e&&`uid`in e?this.#M(`clientEnter`,e):typeof e==`object`&&e&&`id`in e&&`reasonID`in e&&`targetChannelID`in e?this.#M(`clientMoved`,e):typeof e==`object`&&e&&`id`in e&&`reasonID`in e&&this.#M(`clientLeave`,e)})}};async function W(e,t,n,r){let i=a.n(`sendtextmessage`,[[`targetmode`,String(t)],[`target`,String(n)],[`msg`,r]]);await e.sendCommandNoWait(i)}async function G(e,t,n,r=``){let i=[[`clid`,String(t)],[`cid`,String(n)]];r&&i.push([`cpw`,r]);let o=a.n(`clientmove`,i);await e.execCommand(o,1e4)}async function K(e,t,n){let r=a.n(`clientpoke`,[[`clid`,String(t)],[`msg`,n]]);await e.execCommand(r,1e4)}async function q(e,t){let n=(await e.execCommandWithResponse(`clientinfo clid=${t}`,5e3))[0];if(!n)throw Error(`no data returned for client ${t}`);return n}async function J(e){return(await e.execCommandWithResponse(`channellist`,5e3)).map(e=>({id:BigInt(e.cid??`0`),parentID:BigInt(e.pid??`0`),name:a.i(e.channel_name??``),description:``}))}async function Y(e){return(await e.execCommandWithResponse(`clientlist -uid -away -voice -groups`,5e3)).map(e=>{let t=e.client_servergroups??``;return{id:parseInt(e.clid??`0`,10),nickname:a.i(e.client_nickname??``),uid:e.client_unique_identifier??``,channelID:BigInt(e.cid??`0`),type:parseInt(e.client_type??`0`,10),serverGroups:t?t.split(`,`):[]}})}async function X(e,t,n){if(n.length===0)return;let r=n.join(`|`),i=a.t(`ftdeletefile`,{cid:String(t),cpw:``,name:r});await e.execCommand(i,1e4)}exports.AlreadyConnectedError=t.p,exports.Client=U,exports.ClientStatus=e.t,exports.CommandTimeoutError=t.m,exports.CryptoInitError=t.h,exports.EAXTagMismatchError=t.g,exports.FakeSignatureMismatchError=t._,exports.FileTransferError=t.v,exports.FileTransferTimeoutError=t.y,exports.Identity=t.s,exports.InvalidIdentityError=t.b,exports.ServerError=t.x,exports.TeamspeakError=t.S,exports.clientMove=G,exports.consoleLogger=e.n,exports.dialFileTransfer=h,exports.downloadFileData=_,exports.fileTransferDeleteFile=X,exports.generateIdentity=t.c,exports.getClientInfo=q,exports.getUidFromPublicKey=t.l,exports.identityFromString=t.d,exports.listChannels=J,exports.listClients=Y,exports.noopLogger=e.r,exports.poke=K,exports.sendTextMessage=W,exports.uploadFileData=g;
|
|
2
|
+
//# sourceMappingURL=index.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.cjs","names":["#pending","#nextRC","#welcomeComplete","#buffer","#pending","#nextID","#lastUpdate","#tokens","#identity","#addr","#resolver","#handlePacket","#handleConnectionClosed","#cmdMiddlewares","#eventMiddlewares","#finalCmdHandler","#buildCmdHandler","#finalEvtHandler","#buildEvtHandler","#status","#resetForConnect","#resolveAddr","#disconnectedHandlers","#connectedResolvers","#throttle","#cmdTrack","#textMsgHandlers","#clientEnterHandlers","#clientLeaveHandlers","#clientMoveHandlers","#pokedHandlers","#voiceDataHandlers","#connectedHandlers","#kickedHandlers","#clients","#ftTrack","#handlePacketSync","#handleVoicePacket","#handleCommandLines","#handleCommandStr","#processNotificationResult","#handleError","#dispatchEvent","#dispatchEventDirect"],"sources":["../src/commands.ts","../src/transfer.ts","../src/events.ts","../src/handshake.ts","../src/helpers.ts","../src/notifications.ts","../src/throttle.ts","../src/client.ts","../src/api.ts"],"sourcesContent":["import { ServerError } from \"./errors.js\";\n\nexport interface CommandResult {\n err: Error | null;\n data: Record<string, string>[];\n}\n\n/**\n * Tracks in-flight commands by return_code.\n *\n * The TS3/TS5 server sends a \"welcome sequence\" of unsolicited data immediately\n * after the connection handshake (channellist, channelclientlist, etc.). This\n * data arrives on the event loop AFTER we may have registered our first pending\n * RC, which would contaminate our command responses.\n *\n * Solution: gate all row buffering on a `#welcomeComplete` flag. The flag is\n * set when `notifycliententerview` for our own clid arrives — the last event\n * the TS3/TS5 server sends in its welcome sequence. Any data arriving before\n * that is silently discarded.\n */\nexport class CommandTracker {\n readonly #pending = new Map<number, (result: CommandResult) => void>();\n #nextRC = 0;\n #buffer: Record<string, string>[] = [];\n\n /**\n * Set to true when we receive `notifycliententerview` for our own clid,\n * which marks the end of the server's welcome sequence.\n */\n #welcomeComplete = false;\n\n register(): [rc: number, promise: Promise<CommandResult>] {\n this.#nextRC++;\n const rc = this.#nextRC;\n const promise = new Promise<CommandResult>((resolve) => {\n this.#pending.set(rc, resolve);\n });\n return [rc, promise];\n }\n\n unregister(rc: number): void {\n this.#pending.delete(rc);\n }\n\n /**\n * Called when `notifycliententerview` for our own clid arrives.\n * Marks the welcome sequence as complete and discards any accumulated data.\n */\n signalWelcomeComplete(): void {\n this.#welcomeComplete = true;\n this.#buffer = [];\n }\n\n /**\n * Buffer a data row from the server. Rows arriving before the welcome\n * sequence is complete are silently discarded to prevent contamination.\n */\n buffer(params: Record<string, string>): void {\n if (!this.#welcomeComplete) return;\n if (this.#pending.size === 0) return;\n this.#buffer.push(params);\n }\n\n resolve(rc: number, err: Error | null): void {\n const resolve = this.#pending.get(rc);\n if (!resolve) {\n this.#buffer = [];\n return;\n }\n const data = this.#buffer;\n this.#buffer = [];\n this.#pending.delete(rc);\n resolve({ err, data });\n }\n\n discardBuffer(): void {\n this.#buffer = [];\n }\n\n reset(): void {\n this.#pending.clear();\n this.#buffer = [];\n this.#welcomeComplete = false;\n this.#nextRC = 0;\n }\n}\n\n/**\n * Parse and handle an `error` command from the server.\n * Returns the error (or null on success) and the resolved return_code.\n */\nexport function parseServerError(params: Record<string, string>): {\n err: Error | null;\n rc: number | null;\n} {\n const id = params[\"id\"] ?? \"0\";\n const msg = params[\"msg\"] ?? \"\";\n const rcStr = params[\"return_code\"];\n\n let err: Error | null = null;\n if (id !== \"0\") {\n err = new ServerError(id, msg);\n }\n\n let rc: number | null = null;\n if (rcStr !== undefined && rcStr !== \"\") {\n const parsed = parseInt(rcStr, 10);\n if (!isNaN(parsed)) rc = parsed;\n }\n\n return { err, rc };\n}\n\n/**\n * Append a return_code parameter to a command string if not already present.\n */\nexport function appendReturnCode(cmd: string, rc: number): string {\n if (cmd.includes(\"return_code=\")) return cmd;\n return `${cmd} return_code=${rc}`;\n}\n","import { createConnection } from \"node:net\";\nimport type { Readable, Writable } from \"node:stream\";\nimport type { FileUploadInfo, FileDownloadInfo } from \"./types.js\";\nimport { FileTransferError, FileTransferTimeoutError } from \"./errors.js\";\nimport { buildCommand } from \"./command/command.js\";\n\nexport interface FileTransferTracker {\n register(): [\n cftid: number,\n promise: Promise<\n FileUploadInfo | FileDownloadInfo | import(\"./types.js\").FileTransferStatusInfo\n >,\n ];\n unregister(cftid: number): void;\n notify(\n cftid: number,\n value: FileUploadInfo | FileDownloadInfo | import(\"./types.js\").FileTransferStatusInfo,\n ): void;\n reset(): void;\n}\n\ntype FtNotification =\n | FileUploadInfo\n | FileDownloadInfo\n | import(\"./types.js\").FileTransferStatusInfo;\n\nexport class FileTransferTracker {\n readonly #pending = new Map<number, (v: FtNotification) => void>();\n #nextID = 0;\n\n register(): [cftid: number, promise: Promise<FtNotification>] {\n this.#nextID++;\n if (this.#nextID > 65535) this.#nextID = 1;\n const cftid = this.#nextID;\n const promise = new Promise<FtNotification>((resolve) => {\n this.#pending.set(cftid, resolve);\n });\n return [cftid, promise];\n }\n\n unregister(cftid: number): void {\n this.#pending.delete(cftid);\n }\n\n notify(cftid: number, value: FtNotification): void {\n const resolve = this.#pending.get(cftid);\n if (resolve) resolve(value);\n }\n\n reset(): void {\n this.#pending.clear();\n this.#nextID = 0;\n }\n}\n\n/**\n * Open a TCP connection to the TS3 file transfer port and perform the\n * ftkey handshake. The caller is responsible for closing the socket.\n */\nexport function dialFileTransfer(\n host: string,\n port: number,\n key: string,\n): Promise<import(\"node:net\").Socket> {\n return new Promise((resolve, reject) => {\n const socket = createConnection({ host, port }, () => {\n socket.write(key, (err) => {\n if (err) {\n socket.destroy();\n reject(new FileTransferError(`failed to send transfer key: ${err.message}`));\n } else {\n resolve(socket);\n }\n });\n });\n socket.setTimeout(10_000);\n socket.once(\"error\", reject);\n socket.once(\"timeout\", () => {\n socket.destroy();\n reject(new FileTransferError(\"connection timeout\"));\n });\n });\n}\n\n/** Upload data via a TS3 file transfer connection. */\nexport async function uploadFileData(\n host: string,\n info: FileUploadInfo,\n data: Readable,\n): Promise<void> {\n const socket = await dialFileTransfer(host, info.port, info.fileTransferKey);\n await new Promise<void>((resolve, reject) => {\n data.pipe(socket);\n socket.on(\"finish\", resolve);\n socket.on(\"error\", reject);\n });\n}\n\n/** Download data via a TS3 file transfer connection. */\nexport async function downloadFileData(\n host: string,\n info: FileDownloadInfo,\n dest: Writable,\n): Promise<void> {\n const socket = await dialFileTransfer(host, info.port, info.fileTransferKey);\n await new Promise<void>((resolve, reject) => {\n socket.pipe(dest);\n dest.on(\"finish\", resolve);\n socket.on(\"error\", reject);\n dest.on(\"error\", reject);\n });\n}\n\n/**\n * Build a ftinitupload command string.\n */\nexport function buildFtInitUpload(\n channelID: bigint,\n path: string,\n password: string,\n size: bigint,\n cftid: number,\n overwrite: boolean,\n): string {\n const targetPath = path.startsWith(\"/\") ? path : `/${path}`;\n return buildCommand(\"ftinitupload\", {\n cid: String(channelID),\n name: targetPath,\n cpw: password,\n size: String(size),\n clientftfid: String(cftid),\n overwrite: overwrite ? \"1\" : \"0\",\n resume: \"0\",\n });\n}\n\n/**\n * Build a ftinitdownload command string.\n */\nexport function buildFtInitDownload(\n channelID: bigint,\n path: string,\n password: string,\n cftid: number,\n): string {\n const targetPath = path.startsWith(\"/\") ? path : `/${path}`;\n return buildCommand(\"ftinitdownload\", {\n cid: String(channelID),\n name: targetPath,\n cpw: password,\n clientftfid: String(cftid),\n seekpos: \"0\",\n });\n}\n\nexport { FileTransferError, FileTransferTimeoutError };\n","import type { EventMap, CommandMiddleware, EventMiddleware } from \"./types.js\";\n\ntype EventHandler<K extends keyof EventMap> = EventMap[K] extends void\n ? () => void\n : (payload: EventMap[K]) => void;\n\nexport type { EventHandler };\n\n/**\n * Compose a chain of middlewares around a base handler.\n * Rightmost middleware wraps the base first.\n */\nexport function buildCommandChain(\n middlewares: CommandMiddleware[],\n base: (cmd: string) => Promise<void>,\n): (cmd: string) => Promise<void> {\n let handler = base;\n for (let i = middlewares.length - 1; i >= 0; i--) {\n handler = middlewares[i]!(handler);\n }\n return handler;\n}\n\nexport function buildEventChain(\n middlewares: EventMiddleware[],\n base: (evt: EventMap[keyof EventMap]) => void,\n): (evt: EventMap[keyof EventMap]) => void {\n let handler = base;\n for (let i = middlewares.length - 1; i >= 0; i--) {\n handler = middlewares[i]!(handler);\n }\n return handler;\n}\n","import { createHash } from \"node:crypto\";\nimport { buildCommandOrdered, buildCommand } from \"./command/command.js\";\nimport { sign, generateTemporaryKey } from \"./crypto/primitives.js\";\nimport { cryptoInit2 } from \"./handshake/crypt-init2.js\";\nimport { PacketType } from \"./transport/packet.js\";\nimport type { Client } from \"./client.js\";\n\n/** Handle the `clientinitiv` message (P-256 based crypto path). */\nexport function handleHandshakeInitIV(client: Client, params: Record<string, string>): void {\n const alpha = params[\"alpha\"] ?? \"\";\n const beta = params[\"beta\"] ?? \"\";\n const omega = params[\"omega\"] ?? \"\";\n\n client.crypt.initCrypto(alpha, beta, omega);\n client.logger.info(\"crypto initialized (P-256 path), sending clientinit\");\n sendClientInit(client);\n}\n\n/** Handle the `initivexpand2` message (Ed25519 / TS3 crypto path). */\nexport function handleHandshakeExpand2(client: Client, params: Record<string, string>): void {\n client.logger.info(\"received initivexpand2\");\n client.handler.receivedFinalInitAck();\n\n const license = params[\"l\"] ?? \"\";\n const omega = params[\"omega\"] ?? \"\";\n const proof = params[\"proof\"] ?? \"\";\n const beta = params[\"beta\"] ?? \"\";\n\n const privateKey = sendClientEkPacket(client, beta);\n cryptoInit2(client.crypt, license, omega, proof, beta, privateKey);\n sendClientInit(client);\n}\n\n/** Handle `initserver` — marks the client as connected. */\nexport function handleInitServer(client: Client, params: Record<string, string>): void {\n const idStr = params[\"aclid\"] ?? params[\"clid\"] ?? \"\";\n const clid = idStr ? parseInt(idStr, 10) : 0;\n\n if (clid > 0) {\n client.clid = clid;\n client.handler.setClientID(clid);\n }\n\n client.logger.info(\"connected to server\", { selfId: client.clid });\n client._markConnected();\n\n // Inform the server about mute state\n setImmediate(() => {\n const updateCmd = buildCommand(\"clientupdate\", {\n client_input_muted: \"0\",\n client_output_muted: \"0\",\n });\n client.sendCommandNoWait(updateCmd).catch(() => {});\n });\n}\n\nfunction sendClientEkPacket(client: Client, beta: string): Uint8Array {\n const [publicKey, privateKey] = generateTemporaryKey();\n const ekBase64 = Buffer.from(publicKey).toString(\"base64\");\n const clientProof = buildClientEkProof(client, publicKey, beta);\n\n const clientEk = buildCommandOrdered(\"clientek\", [\n [\"ek\", ekBase64],\n [\"proof\", clientProof],\n ]);\n client.handler.sendPacket(PacketType.Command, Buffer.from(clientEk), 0);\n return privateKey;\n}\n\nfunction buildClientEkProof(client: Client, publicKey: Uint8Array, beta: string): string {\n const betaBytes = Buffer.from(beta, \"base64\");\n const toSign = new Uint8Array(86);\n toSign.set(publicKey.slice(0, 32));\n toSign.set(betaBytes.slice(0, Math.min(54, betaBytes.length)), 32);\n const sig = sign(client.crypt.identity.privateKey, toSign);\n return Buffer.from(sig).toString(\"base64\");\n}\n\nexport function sendClientInit(client: Client): void {\n const pubKeyBase64 = client.crypt.identity.publicKeyBase64();\n const hash = createHash(\"sha256\").update(pubKeyBase64).digest();\n const hwid = hash.slice(0, 16).toString(\"base64\");\n\n const cmd = buildCommandOrdered(\"clientinit\", [\n [\"client_nickname\", client.nickname],\n [\"client_version\", \"3.5.3 [Build: 1587971024]\"],\n [\"client_platform\", \"Windows\"],\n [\"client_input_hardware\", \"1\"],\n [\"client_output_hardware\", \"1\"],\n [\"client_default_channel\", \"\"],\n [\"client_default_channel_password\", \"\"],\n [\"client_server_password\", \"\"],\n [\"client_meta_data\", \"\"],\n [\n \"client_version_sign\",\n \"Kvmj7qX6wJCPI5GVT71samfmhz/bvs7M+OTXWB/JWxdQbxDe17xda7dzUWLX7pjvdJTqZmbse1HBmTxThPKvAg==\",\n ],\n [\"client_key_offset\", String(client.crypt.identity.offset)],\n [\"client_nickname_phonetic\", \"\"],\n [\"client_default_token\", \"\"],\n [\"hwid\", hwid],\n ]);\n\n client.handler.sendPacket(PacketType.Command, Buffer.from(cmd), 0);\n}\n","export function parseUint64(s: string): bigint {\n if (s === \"\" || s === undefined) return 0n;\n try {\n return BigInt(s);\n } catch {\n return 0n;\n }\n}\n\nexport function parseUint16(s: string): number {\n const v = parseInt(s, 10);\n if (isNaN(v) || v < 0 || v > 65535) return 0;\n return v;\n}\n\nexport function parseInt10(s: string): number {\n const v = parseInt(s, 10);\n return isNaN(v) ? 0 : v;\n}\n\n/**\n * Reports whether `actual` equals `expected` or equals `expected` followed by\n * only digits — the pattern TeamSpeak uses when a nickname is already taken.\n */\nexport function isAutoNicknameMatch(expected: string, actual: string): boolean {\n if (actual === expected) return true;\n if (!actual.startsWith(expected)) return false;\n const suffix = actual.slice(expected.length);\n return /^\\d+$/.test(suffix);\n}\n\n/**\n * Expand a pipe-separated multi-row TS3 command line into individual rows,\n * each prefixed with the command name.\n */\nexport function splitCommandRows(line: string): string[] {\n const spaceIdx = line.indexOf(\" \");\n if (spaceIdx < 0) return [line];\n\n const name = line.slice(0, spaceIdx);\n const rest = line.slice(spaceIdx + 1);\n\n if (!rest.includes(\"|\")) return [line];\n\n const parts = rest.split(\"|\");\n const rows: string[] = [];\n for (const part of parts) {\n if (part !== \"\") rows.push(`${name} ${part}`);\n }\n return rows.length === 0 ? [line] : rows;\n}\n","import type { Command } from \"./command/command.js\";\nimport { unescape } from \"./command/command.js\";\nimport type {\n ClientInfo,\n ClientLeftViewEvent,\n ClientMovedEvent,\n TextMessage,\n PokeEvent,\n FileUploadInfo,\n FileDownloadInfo,\n FileTransferStatusInfo,\n} from \"./types.js\";\nimport { parseUint64, parseUint16, parseInt10 } from \"./helpers.js\";\n\nexport type NotificationResult =\n | { kind: \"clientEnter\"; info: ClientInfo }\n | { kind: \"clientLeave\"; event: ClientLeftViewEvent; isSelf: boolean }\n | { kind: \"clientMoved\"; event: ClientMovedEvent }\n | { kind: \"textMessage\"; message: TextMessage }\n | { kind: \"poked\"; event: PokeEvent }\n | { kind: \"startUpload\"; info: FileUploadInfo }\n | { kind: \"startDownload\"; info: FileDownloadInfo }\n | { kind: \"fileTransferStatus\"; info: FileTransferStatusInfo }\n | { kind: \"unknown\" };\n\nexport function handleNotification(\n cmd: Command,\n selfCLID: number,\n clients: Map<number, ClientInfo>,\n nickname: string,\n): NotificationResult {\n switch (cmd.name) {\n case \"notifycliententerview\":\n return handleClientEnterView(cmd, clients, nickname);\n case \"notifyclientleftview\":\n return handleClientLeftView(cmd, selfCLID, clients);\n case \"notifyclientmoved\":\n return handleClientMoved(cmd, clients);\n case \"notifytextmessage\":\n return handleTextMessage(cmd, clients);\n case \"notifyclientpoke\":\n return handleClientPoked(cmd);\n case \"notifystartupload\":\n return { kind: \"startUpload\", info: handleStartUpload(cmd) };\n case \"notifystartdownload\":\n return { kind: \"startDownload\", info: handleStartDownload(cmd) };\n case \"notifystatusfiletransfer\":\n return { kind: \"fileTransferStatus\", info: handleFileTransferStatus(cmd) };\n default:\n return { kind: \"unknown\" };\n }\n}\n\nfunction handleClientEnterView(\n cmd: Command,\n clients: Map<number, ClientInfo>,\n nickname: string,\n): NotificationResult {\n const clid = parseUint16(cmd.params[\"clid\"] ?? \"\");\n const cid = parseUint64(cmd.params[\"cid\"] ?? \"\");\n const clientType = parseInt10(cmd.params[\"client_type\"] ?? \"\");\n const groupsStr = cmd.params[\"client_servergroups\"] ?? \"\";\n\n const info: ClientInfo = {\n id: clid,\n nickname: cmd.params[\"client_nickname\"] ?? \"\",\n uid: cmd.params[\"client_unique_identifier\"] ?? \"\",\n channelID: cid,\n type: clientType,\n serverGroups: groupsStr ? groupsStr.split(\",\") : [],\n };\n\n if (clid !== 0) {\n clients.set(clid, info);\n }\n\n return { kind: \"clientEnter\", info };\n}\n\nfunction handleClientLeftView(\n cmd: Command,\n selfCLID: number,\n clients: Map<number, ClientInfo>,\n): NotificationResult {\n const clid = parseUint16(cmd.params[\"clid\"] ?? \"\");\n const reasonID = parseInt10(cmd.params[\"reasonid\"] ?? \"\");\n\n const isSelf = clid === selfCLID;\n if (clid !== 0) clients.delete(clid);\n\n return {\n kind: \"clientLeave\",\n event: {\n id: clid,\n reasonID,\n reasonMsg: cmd.params[\"reasonmsg\"] ?? \"\",\n targetID: parseUint16(cmd.params[\"targetid\"] ?? \"\"),\n },\n isSelf,\n };\n}\n\nfunction handleClientMoved(cmd: Command, clients: Map<number, ClientInfo>): NotificationResult {\n const clid = parseUint16(cmd.params[\"clid\"] ?? \"\");\n const ctid = parseUint64(cmd.params[\"ctid\"] ?? \"\");\n\n if (clid !== 0) {\n const existing = clients.get(clid);\n if (existing) clients.set(clid, { ...existing, channelID: ctid });\n }\n\n return {\n kind: \"clientMoved\",\n event: {\n id: clid,\n targetChannelID: ctid,\n reasonID: parseInt10(cmd.params[\"reasonid\"] ?? \"\"),\n invokerID: parseUint16(cmd.params[\"invokerid\"] ?? \"\"),\n invokerName: cmd.params[\"invokername\"] ?? \"\",\n invokerUID: cmd.params[\"invokeruid\"] ?? \"\",\n },\n };\n}\n\nfunction handleTextMessage(cmd: Command, clients: Map<number, ClientInfo>): NotificationResult {\n const invokerID = parseUint16(cmd.params[\"invokerid\"] ?? \"\");\n const invokerInfo = clients.get(invokerID);\n\n const message: TextMessage = {\n targetMode: parseInt10(cmd.params[\"targetmode\"] ?? \"\"),\n targetID: parseUint64(cmd.params[\"target\"] ?? \"\"),\n invokerID,\n invokerName: cmd.params[\"invokername\"] ?? \"\",\n invokerUID: cmd.params[\"invokeruid\"] ?? invokerInfo?.uid ?? \"\",\n message: unescape(cmd.params[\"msg\"] ?? \"\"),\n invokerGroups: invokerInfo?.serverGroups ?? [],\n };\n\n return { kind: \"textMessage\", message };\n}\n\nfunction handleStartUpload(cmd: Command): FileUploadInfo {\n return {\n clientFileTransferID: parseUint16(cmd.params[\"clientftfid\"] ?? \"\"),\n serverFileTransferID: parseUint16(cmd.params[\"serverftfid\"] ?? \"\"),\n fileTransferKey: cmd.params[\"ftkey\"] ?? \"\",\n port: parseUint16(cmd.params[\"port\"] ?? \"\"),\n seekPosition: parseUint64(cmd.params[\"seekpos\"] ?? \"\"),\n };\n}\n\nfunction handleStartDownload(cmd: Command): FileDownloadInfo {\n return {\n clientFileTransferID: parseUint16(cmd.params[\"clientftfid\"] ?? \"\"),\n serverFileTransferID: parseUint16(cmd.params[\"serverftfid\"] ?? \"\"),\n fileTransferKey: cmd.params[\"ftkey\"] ?? \"\",\n port: parseUint16(cmd.params[\"port\"] ?? \"\"),\n size: parseUint64(cmd.params[\"size\"] ?? \"\"),\n };\n}\n\nfunction handleFileTransferStatus(cmd: Command): FileTransferStatusInfo {\n return {\n clientFileTransferID: parseUint16(cmd.params[\"clientftfid\"] ?? \"\"),\n status: parseInt10(cmd.params[\"status\"] ?? \"\"),\n message: cmd.params[\"msg\"] ?? \"\",\n };\n}\n\nfunction handleClientPoked(cmd: Command): NotificationResult {\n return {\n kind: \"poked\",\n event: {\n invokerID: parseUint16(cmd.params[\"invokerid\"] ?? \"\"),\n invokerName: unescape(cmd.params[\"invokername\"] ?? \"\"),\n invokerUID: cmd.params[\"invokeruid\"] ?? \"\",\n message: unescape(cmd.params[\"msg\"] ?? \"\"),\n },\n };\n}\n","/**\n * Token-bucket limiter for outbound TS3 commands.\n * Mirrors Go's commandThrottle.\n */\nexport class CommandThrottle {\n static readonly TOKEN_RATE = 4.0; // tokens per second\n static readonly TOKEN_MAX = 8.0; // bucket capacity\n\n #tokens = 5.0;\n #lastUpdate = Date.now();\n\n async wait(signal?: AbortSignal): Promise<void> {\n while (true) {\n if (signal?.aborted) throw signal.reason as Error;\n\n const now = Date.now();\n const elapsed = (now - this.#lastUpdate) / 1000;\n this.#tokens = Math.min(\n this.#tokens + elapsed * CommandThrottle.TOKEN_RATE,\n CommandThrottle.TOKEN_MAX,\n );\n this.#lastUpdate = now;\n\n if (this.#tokens >= 1.0) {\n this.#tokens -= 1.0;\n return;\n }\n\n const waitMs = Math.ceil(((1.0 - this.#tokens) / CommandThrottle.TOKEN_RATE) * 1000) + 10;\n\n await new Promise<void>((resolve, reject) => {\n const timer = setTimeout(resolve, waitMs);\n if (signal) {\n signal.addEventListener(\n \"abort\",\n () => {\n clearTimeout(timer);\n reject(signal.reason as Error);\n },\n { once: true },\n );\n }\n });\n }\n }\n}\n","import {\n type EventMap,\n type ClientOptions,\n type CommandMiddleware,\n type EventMiddleware,\n type Logger,\n type AddrResolver,\n type ClientInfo,\n ClientStatus,\n consoleLogger,\n} from \"./types.js\";\nimport { AlreadyConnectedError } from \"./errors.js\";\nimport { Identity, Crypt } from \"./crypto/index.js\";\nimport { Resolver } from \"./discovery/resolver.js\";\nimport { PacketHandler } from \"./transport/handler.js\";\nimport { PacketType } from \"./transport/packet.js\";\nimport type { Packet } from \"./transport/packet.js\";\nimport { CommandTracker, appendReturnCode, parseServerError } from \"./commands.js\";\nimport {\n FileTransferTracker,\n buildFtInitUpload,\n buildFtInitDownload,\n dialFileTransfer,\n uploadFileData,\n downloadFileData,\n} from \"./transfer.js\";\nimport { buildCommandChain, buildEventChain } from \"./events.js\";\nimport { processInit1 } from \"./handshake/crypt-handshake.js\";\nimport { handleHandshakeInitIV, handleHandshakeExpand2, handleInitServer } from \"./handshake.js\";\nimport { handleNotification } from \"./notifications.js\";\nimport { parseCommand } from \"./command/parser.js\";\nimport { CommandThrottle } from \"./throttle.js\";\nimport { splitCommandRows, isAutoNicknameMatch } from \"./helpers.js\";\nimport type { FileUploadInfo, FileDownloadInfo } from \"./types.js\";\nimport { CommandTimeoutError, FileTransferTimeoutError, FileTransferError } from \"./errors.js\";\nimport type { Readable, Writable } from \"node:stream\";\n\nexport { ClientStatus };\n\nexport interface ClientState {\n status: ClientStatus;\n clid: number;\n}\n\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\ntype AnyHandler = (arg: any) => void;\n\nexport class Client {\n // Internal — accessible from handshake.ts helpers\n /** @internal */ crypt: Crypt;\n /** @internal */ handler: PacketHandler;\n /** @internal */ logger: Logger;\n /** @internal */ nickname: string;\n /** @internal */ clid = 0;\n\n #identity: Identity;\n #addr: string;\n #resolver: AddrResolver;\n #status: ClientStatus = ClientStatus.Disconnected;\n #throttle = new CommandThrottle();\n #cmdTrack = new CommandTracker();\n #ftTrack = new FileTransferTracker();\n #clients = new Map<number, ClientInfo>();\n #connectedResolvers: Array<() => void> = [];\n\n // Event handler lists\n #textMsgHandlers: Array<(msg: import(\"./types.js\").TextMessage) => void> = [];\n #clientEnterHandlers: Array<(info: ClientInfo) => void> = [];\n #clientLeaveHandlers: Array<(evt: import(\"./types.js\").ClientLeftViewEvent) => void> = [];\n #clientMoveHandlers: Array<(evt: import(\"./types.js\").ClientMovedEvent) => void> = [];\n #pokedHandlers: Array<(evt: import(\"./types.js\").PokeEvent) => void> = [];\n #voiceDataHandlers: Array<(data: import(\"./types.js\").VoiceData) => void> = [];\n #connectedHandlers: Array<() => void> = [];\n #disconnectedHandlers: Array<(err: Error | undefined) => void> = [];\n #kickedHandlers: Array<(msg: string) => void> = [];\n\n // Middleware\n #cmdMiddlewares: CommandMiddleware[] = [];\n #eventMiddlewares: EventMiddleware[] = [];\n #finalCmdHandler: (cmd: string) => Promise<void>;\n #finalEvtHandler: (evt: EventMap[keyof EventMap]) => void;\n\n constructor(identity: Identity, addr: string, nickname: string, options: ClientOptions = {}) {\n this.#identity = identity;\n this.#addr = addr;\n this.nickname = nickname;\n this.logger = options.logger ?? consoleLogger;\n this.#resolver = options.resolver ?? new Resolver(this.logger);\n\n this.crypt = new Crypt(identity);\n this.handler = new PacketHandler(this.crypt, this.logger);\n this.handler.onPacket = (p) => this.#handlePacket(p);\n this.handler.onClosed = (err) => this.#handleConnectionClosed(err);\n\n if (options.commandMiddleware) {\n this.#cmdMiddlewares.push(...options.commandMiddleware);\n }\n if (options.eventMiddleware) {\n this.#eventMiddlewares.push(...options.eventMiddleware);\n }\n\n this.#finalCmdHandler = this.#buildCmdHandler();\n this.#finalEvtHandler = this.#buildEvtHandler();\n }\n\n get status(): ClientStatus {\n return this.#status;\n }\n\n // ---- Connection -----------------------------------------------------------\n\n async connect(): Promise<void> {\n if (this.#status !== ClientStatus.Disconnected) {\n throw new AlreadyConnectedError();\n }\n\n this.#resetForConnect();\n this.#status = ClientStatus.Connecting;\n\n const targetAddr = await this.#resolveAddr();\n this.logger.info(\"connecting to server\", { address: targetAddr });\n await this.handler.connect(targetAddr);\n }\n\n async disconnect(): Promise<void> {\n if (this.#status === ClientStatus.Disconnected) return;\n\n const wasConnected = this.#status === ClientStatus.Connected;\n this.#status = ClientStatus.Disconnected;\n\n this.logger.info(\"disconnecting from server\");\n\n if (wasConnected) {\n try {\n await this.execCommand(\"clientdisconnect reasonmsg=Shutdown\", 1000);\n } catch {\n // best-effort\n }\n }\n\n this.handler.close();\n const handlers = this.#disconnectedHandlers.slice();\n for (const h of handlers) setImmediate(() => h(undefined));\n }\n\n waitConnected(signal?: AbortSignal): Promise<void> {\n if (this.#status === ClientStatus.Connected) return Promise.resolve();\n return new Promise<void>((resolve, reject) => {\n this.#connectedResolvers.push(resolve);\n if (signal) {\n signal.addEventListener(\"abort\", () => reject(signal.reason as Error), { once: true });\n }\n });\n }\n\n // ---- Commands ------------------------------------------------------------\n\n async sendCommandNoWait(cmd: string): Promise<void> {\n await this.#throttle.wait();\n await this.#finalCmdHandler(cmd);\n }\n\n async execCommand(cmd: string, timeoutMs = 10_000): Promise<void> {\n await this.execCommandWithResponse(cmd, timeoutMs);\n }\n\n async execCommandWithResponse(\n cmd: string,\n timeoutMs = 10_000,\n ): Promise<Record<string, string>[]> {\n const [rc, promise] = this.#cmdTrack.register();\n const withRc = appendReturnCode(cmd, rc);\n\n try {\n await this.#throttle.wait();\n await this.#finalCmdHandler(withRc);\n } catch (err) {\n this.#cmdTrack.unregister(rc);\n throw err;\n }\n\n const result = await Promise.race([\n promise,\n new Promise<never>((_, reject) =>\n setTimeout(() => reject(new CommandTimeoutError(cmd)), timeoutMs),\n ),\n ]);\n\n this.#cmdTrack.unregister(rc);\n\n if (result.err) throw result.err;\n return result.data;\n }\n\n // ---- Events --------------------------------------------------------------\n\n on<K extends keyof EventMap>(\n event: K,\n handler: EventMap[K] extends void ? () => void : (payload: EventMap[K]) => void,\n ): this {\n switch (event) {\n case \"textMessage\":\n this.#textMsgHandlers.push(handler as AnyHandler);\n break;\n case \"clientEnter\":\n this.#clientEnterHandlers.push(handler as AnyHandler);\n break;\n case \"clientLeave\":\n this.#clientLeaveHandlers.push(handler as AnyHandler);\n break;\n case \"clientMoved\":\n this.#clientMoveHandlers.push(handler as AnyHandler);\n break;\n case \"poked\":\n this.#pokedHandlers.push(handler as AnyHandler);\n break;\n case \"voiceData\":\n this.#voiceDataHandlers.push(handler as AnyHandler);\n break;\n case \"connected\":\n this.#connectedHandlers.push(handler as () => void);\n break;\n case \"disconnected\":\n this.#disconnectedHandlers.push(handler as AnyHandler);\n break;\n case \"kicked\":\n this.#kickedHandlers.push(handler as AnyHandler);\n break;\n }\n return this;\n }\n\n useCommandMiddleware(...mw: CommandMiddleware[]): this {\n this.#cmdMiddlewares.push(...mw);\n this.#finalCmdHandler = this.#buildCmdHandler();\n return this;\n }\n\n useEventMiddleware(...mw: EventMiddleware[]): this {\n this.#eventMiddlewares.push(...mw);\n this.#finalEvtHandler = this.#buildEvtHandler();\n return this;\n }\n\n // ---- API shorthand -------------------------------------------------------\n\n clientID(): number {\n return this.clid;\n }\n\n channelID(): bigint {\n const info = this.#clients.get(this.clid);\n return info?.channelID ?? 0n;\n }\n\n sendVoice(data: Uint8Array, codec: number): void {\n this.handler.sendVoicePacket(data, codec);\n }\n\n // ---- File Transfer -------------------------------------------------------\n\n async fileTransferInitUpload(\n channelID: bigint,\n path: string,\n password: string,\n size: bigint,\n overwrite = false,\n ): Promise<FileUploadInfo> {\n const [cftid, ftPromise] = this.#ftTrack.register();\n const cmd = buildFtInitUpload(channelID, path, password, size, cftid, overwrite);\n\n try {\n await this.execCommand(cmd, 10_000);\n } catch (err) {\n this.#ftTrack.unregister(cftid);\n throw err;\n }\n\n const result = await Promise.race([\n ftPromise,\n new Promise<never>((_, reject) =>\n setTimeout(() => reject(new FileTransferTimeoutError()), 10_000),\n ),\n ]);\n this.#ftTrack.unregister(cftid);\n\n if (\"size\" in result) throw new FileTransferError(\"unexpected download response\");\n if (\"status\" in result) {\n const st = result as import(\"./types.js\").FileTransferStatusInfo;\n throw new FileTransferError(`${st.message} (status=${st.status})`);\n }\n return result as FileUploadInfo;\n }\n\n async fileTransferInitDownload(\n channelID: bigint,\n path: string,\n password: string,\n ): Promise<FileDownloadInfo> {\n const [cftid, ftPromise] = this.#ftTrack.register();\n const cmd = buildFtInitDownload(channelID, path, password, cftid);\n\n try {\n await this.execCommand(cmd, 10_000);\n } catch (err) {\n this.#ftTrack.unregister(cftid);\n throw err;\n }\n\n const result = await Promise.race([\n ftPromise,\n new Promise<never>((_, reject) =>\n setTimeout(() => reject(new FileTransferTimeoutError()), 10_000),\n ),\n ]);\n this.#ftTrack.unregister(cftid);\n\n if (\"seekPosition\" in result) throw new FileTransferError(\"unexpected upload response\");\n if (\"status\" in result) {\n const st = result as import(\"./types.js\").FileTransferStatusInfo;\n throw new FileTransferError(`${st.message} (status=${st.status})`);\n }\n return result as FileDownloadInfo;\n }\n\n uploadFileData(host: string, info: FileUploadInfo, data: Readable): Promise<void> {\n return uploadFileData(host, info, data);\n }\n\n downloadFileData(host: string, info: FileDownloadInfo, dest: Writable): Promise<void> {\n return downloadFileData(host, info, dest);\n }\n\n // ---- Internal (package-visible) ------------------------------------------\n\n /** @internal */\n _markConnected(): void {\n this.#status = ClientStatus.Connected;\n for (const resolve of this.#connectedResolvers) resolve();\n this.#connectedResolvers = [];\n const handlers = this.#connectedHandlers.slice();\n for (const h of handlers) setImmediate(() => h());\n }\n\n // ---- Private -------------------------------------------------------------\n\n #resetForConnect(): void {\n this.handler.close();\n this.crypt = new Crypt(this.#identity);\n this.handler = new PacketHandler(this.crypt, this.logger);\n this.handler.onPacket = (p) => this.#handlePacket(p);\n this.handler.onClosed = (err) => this.#handleConnectionClosed(err);\n this.#cmdTrack.reset();\n this.#ftTrack.reset();\n this.#clients.clear();\n this.clid = 0;\n this.#finalCmdHandler = this.#buildCmdHandler();\n }\n\n async #resolveAddr(): Promise<string> {\n const addrWithPort = this.#addr.includes(\":\") ? this.#addr : `${this.#addr}:9987`;\n try {\n const resolved = await this.#resolver.resolve(this.#addr);\n return resolved[0]?.addr ?? addrWithPort;\n } catch {\n return addrWithPort;\n }\n }\n\n #handlePacket(p: Packet): void {\n this.#handlePacketSync(p);\n }\n\n #handlePacketSync(p: Packet): void {\n const pType = p.typeFlagged & 0x0f;\n if (pType === 8 /* Init1 */) {\n const response = processInit1(this.crypt, p.data);\n if (response) {\n this.handler.sendPacket(PacketType.Init1, response, 0);\n }\n return;\n }\n\n if ((pType === 0 /* Voice */ || pType === 1) /* VoiceWhisper */ && p.data.length > 5) {\n this.#handleVoicePacket(p.data);\n return;\n }\n\n if ((pType === 2 /* Command */ || pType === 3) /* CommandLow */ && p.data.length > 0) {\n this.#handleCommandLines(Buffer.from(p.data).toString(\"utf8\"));\n }\n }\n\n /**\n * Parse an incoming S2C voice packet.\n * Format: [VId: u16] [CId: u16] [Codec: u8] [Data: var]\n */\n #handleVoicePacket(payload: Uint8Array): void {\n if (this.#voiceDataHandlers.length === 0) return;\n\n const view = new DataView(payload.buffer, payload.byteOffset, payload.byteLength);\n const clientId = view.getUint16(2, false);\n if (clientId === this.clid) return;\n\n const codec = payload[4]!;\n const data = payload.subarray(5);\n\n const voiceData: import(\"./types.js\").VoiceData = { clientId, codec, data };\n for (const h of this.#voiceDataHandlers) setImmediate(() => h(voiceData));\n }\n\n #handleCommandLines(s: string): void {\n if (!s) return;\n const lines = s.split(/[\\n\\0]/);\n for (const line of lines) {\n const trimmed = line.replace(/\\r$/, \"\");\n if (!trimmed) continue;\n for (const row of splitCommandRows(trimmed)) {\n this.#handleCommandStr(row);\n }\n }\n }\n\n #handleCommandStr(s: string): void {\n const cmd = parseCommand(s);\n if (!cmd || !cmd.name) return;\n\n if (cmd.name.startsWith(\"notify\")) {\n const result = handleNotification(cmd, this.clid, this.#clients, this.nickname);\n this.#processNotificationResult(result, cmd.params);\n return;\n }\n\n switch (cmd.name) {\n case \"clientinitiv\":\n handleHandshakeInitIV(this, cmd.params);\n break;\n case \"initivexpand2\":\n handleHandshakeExpand2(this, cmd.params);\n break;\n case \"initserver\":\n handleInitServer(this, cmd.params);\n break;\n case \"error\":\n this.#handleError(cmd.params);\n break;\n default: {\n // TS5/TS6 servers send data rows without a command-name prefix.\n // In that case our parser treats the first key=value pair as the\n // \"command name\" (e.g. name=\"clid=1827\"). Reconstruct full params.\n let params = cmd.params;\n if (cmd.name.includes(\"=\")) {\n const eqIdx = cmd.name.indexOf(\"=\");\n const k = cmd.name.slice(0, eqIdx);\n const v = cmd.name.slice(eqIdx + 1);\n params = { [k]: v, ...cmd.params };\n }\n this.#cmdTrack.buffer(params);\n break;\n }\n }\n }\n\n #handleError(params: Record<string, string>): void {\n const { err, rc } = parseServerError(params);\n if (rc !== null) {\n this.#cmdTrack.resolve(rc, err);\n } else {\n // No return_code: server is acknowledging an unsolicited command\n // (welcome-sequence channellist, no-RC commands like clientupdate, etc.).\n // Discard any rows buffered since the last resolved command.\n this.#cmdTrack.discardBuffer();\n }\n\n const id = params[\"id\"] ?? \"0\";\n if (id === \"3329\") {\n setImmediate(() => this.disconnect().catch(() => {}));\n }\n }\n\n #processNotificationResult(\n result: import(\"./notifications.js\").NotificationResult,\n _params: Record<string, string>,\n ): void {\n switch (result.kind) {\n case \"clientEnter\": {\n const info = result.info;\n if (info.id !== 0 && isAutoNicknameMatch(this.nickname, info.nickname)) {\n this.clid = info.id;\n this.handler.setClientID(info.id);\n // Our own notifycliententerview is the last event in the TS3/TS5\n // welcome sequence. Signal that it's safe to buffer command responses.\n this.#cmdTrack.signalWelcomeComplete();\n }\n this.#dispatchEvent(\"clientEnter\", info);\n break;\n }\n case \"clientLeave\": {\n this.#dispatchEvent(\"clientLeave\", result.event);\n if (result.isSelf && (result.event.reasonID === 4 || result.event.reasonID === 5)) {\n const msg = result.event.reasonMsg;\n for (const h of this.#kickedHandlers) setImmediate(() => h(msg));\n }\n break;\n }\n case \"clientMoved\":\n this.#dispatchEvent(\"clientMoved\", result.event);\n break;\n case \"textMessage\":\n this.#dispatchEvent(\"textMessage\", result.message);\n break;\n case \"poked\":\n this.#dispatchEvent(\"poked\", result.event);\n break;\n case \"startUpload\":\n this.#ftTrack.notify(result.info.clientFileTransferID, result.info);\n break;\n case \"startDownload\":\n this.#ftTrack.notify(result.info.clientFileTransferID, result.info);\n break;\n case \"fileTransferStatus\":\n this.#ftTrack.notify(result.info.clientFileTransferID, result.info);\n break;\n }\n }\n\n #dispatchEvent<K extends keyof EventMap>(event: K, payload: EventMap[K]): void {\n this.#finalEvtHandler(payload as EventMap[keyof EventMap]);\n }\n\n #dispatchEventDirect<K extends keyof EventMap>(event: K, payload: EventMap[K]): void {\n switch (event) {\n case \"textMessage\":\n for (const h of this.#textMsgHandlers)\n setImmediate(() => h(payload as import(\"./types.js\").TextMessage));\n break;\n case \"clientEnter\":\n for (const h of this.#clientEnterHandlers) setImmediate(() => h(payload as ClientInfo));\n break;\n case \"clientLeave\":\n for (const h of this.#clientLeaveHandlers)\n setImmediate(() => h(payload as import(\"./types.js\").ClientLeftViewEvent));\n break;\n case \"clientMoved\":\n for (const h of this.#clientMoveHandlers)\n setImmediate(() => h(payload as import(\"./types.js\").ClientMovedEvent));\n break;\n case \"poked\":\n for (const h of this.#pokedHandlers)\n setImmediate(() => h(payload as import(\"./types.js\").PokeEvent));\n break;\n }\n }\n\n #handleConnectionClosed(err: Error | null): void {\n if (this.#status === ClientStatus.Disconnected) return;\n this.#status = ClientStatus.Disconnected;\n const handlers = this.#disconnectedHandlers.slice();\n for (const h of handlers) setImmediate(() => h(err ?? undefined));\n }\n\n #buildCmdHandler(): (cmd: string) => Promise<void> {\n const base = async (cmd: string): Promise<void> => {\n this.handler.sendPacket(PacketType.Command, Buffer.from(cmd), 0);\n };\n return buildCommandChain(this.#cmdMiddlewares, base);\n }\n\n #buildEvtHandler(): (evt: EventMap[keyof EventMap]) => void {\n const base = (evt: EventMap[keyof EventMap]): void => {\n // Determine which event type this is by checking the shape\n if (\n evt !== null &&\n evt !== undefined &&\n typeof evt === \"object\" &&\n \"invokerName\" in evt &&\n \"message\" in evt &&\n \"targetMode\" in evt\n ) {\n this.#dispatchEventDirect(\"textMessage\", evt as EventMap[\"textMessage\"]);\n } else if (\n evt !== null &&\n evt !== undefined &&\n typeof evt === \"object\" &&\n \"invokerName\" in evt &&\n \"message\" in evt &&\n !(\"targetMode\" in evt)\n ) {\n this.#dispatchEventDirect(\"poked\", evt as EventMap[\"poked\"]);\n } else if (\n evt !== null &&\n evt !== undefined &&\n typeof evt === \"object\" &&\n \"id\" in evt &&\n \"uid\" in evt\n ) {\n this.#dispatchEventDirect(\"clientEnter\", evt as EventMap[\"clientEnter\"]);\n } else if (\n evt !== null &&\n evt !== undefined &&\n typeof evt === \"object\" &&\n \"id\" in evt &&\n \"reasonID\" in evt &&\n \"targetChannelID\" in evt\n ) {\n this.#dispatchEventDirect(\"clientMoved\", evt as EventMap[\"clientMoved\"]);\n } else if (\n evt !== null &&\n evt !== undefined &&\n typeof evt === \"object\" &&\n \"id\" in evt &&\n \"reasonID\" in evt\n ) {\n this.#dispatchEventDirect(\"clientLeave\", evt as EventMap[\"clientLeave\"]);\n }\n };\n return buildEventChain(this.#eventMiddlewares, base);\n }\n}\n","import { buildCommandOrdered, buildCommand, unescape } from \"./command/command.js\";\nimport type { ChannelInfo, ClientInfo } from \"./types.js\";\nimport type { Client } from \"./client.js\";\n\n/** Send a text message to a client (targetMode=1), channel (2), or server (3). */\nexport async function sendTextMessage(\n client: Client,\n targetMode: number,\n targetID: bigint,\n message: string,\n): Promise<void> {\n const cmd = buildCommandOrdered(\"sendtextmessage\", [\n [\"targetmode\", String(targetMode)],\n [\"target\", String(targetID)],\n [\"msg\", message],\n ]);\n await client.sendCommandNoWait(cmd);\n}\n\n/** Move a client to a different channel. */\nexport async function clientMove(\n client: Client,\n clid: number,\n channelID: bigint,\n password = \"\",\n): Promise<void> {\n const params: Array<readonly [string, string]> = [\n [\"clid\", String(clid)],\n [\"cid\", String(channelID)],\n ];\n if (password) params.push([\"cpw\", password]);\n const cmd = buildCommandOrdered(\"clientmove\", params);\n await client.execCommand(cmd, 10_000);\n}\n\n/** Send a poke message to a client. */\nexport async function poke(client: Client, clid: number, message: string): Promise<void> {\n const cmd = buildCommandOrdered(\"clientpoke\", [\n [\"clid\", String(clid)],\n [\"msg\", message],\n ]);\n await client.execCommand(cmd, 10_000);\n}\n\n/** Fetch raw clientinfo for a given clid. */\nexport async function getClientInfo(client: Client, clid: number): Promise<Record<string, string>> {\n const data = await client.execCommandWithResponse(`clientinfo clid=${clid}`, 5_000);\n const row = data[0];\n if (!row) throw new Error(`no data returned for client ${clid}`);\n return row;\n}\n\n/** List all channels on the server. */\nexport async function listChannels(client: Client): Promise<ChannelInfo[]> {\n const data = await client.execCommandWithResponse(\"channellist\", 5_000);\n return data.map((item) => ({\n id: BigInt(item[\"cid\"] ?? \"0\"),\n parentID: BigInt(item[\"pid\"] ?? \"0\"),\n name: unescape(item[\"channel_name\"] ?? \"\"),\n description: \"\",\n }));\n}\n\n/** List all clients currently connected to the server. */\nexport async function listClients(client: Client): Promise<ClientInfo[]> {\n const data = await client.execCommandWithResponse(\"clientlist -uid -away -voice -groups\", 5_000);\n return data.map((item) => {\n const groupsStr = item[\"client_servergroups\"] ?? \"\";\n return {\n id: parseInt(item[\"clid\"] ?? \"0\", 10),\n nickname: unescape(item[\"client_nickname\"] ?? \"\"),\n uid: item[\"client_unique_identifier\"] ?? \"\",\n channelID: BigInt(item[\"cid\"] ?? \"0\"),\n type: parseInt(item[\"client_type\"] ?? \"0\", 10),\n serverGroups: groupsStr ? groupsStr.split(\",\") : [],\n };\n });\n}\n\n/** Delete a file on the server. */\nexport async function fileTransferDeleteFile(\n client: Client,\n channelID: bigint,\n paths: string[],\n): Promise<void> {\n if (paths.length === 0) return;\n const pathStr = paths.join(\"|\");\n const cmd = buildCommand(\"ftdeletefile\", {\n cid: String(channelID),\n cpw: \"\",\n name: pathStr,\n });\n await client.execCommand(cmd, 10_000);\n}\n"],"mappings":"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"}
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
export { Client, ClientStatus } from "./client.js";
|
|
2
|
+
export type { ClientState } from "./client.js";
|
|
3
|
+
export type { TextMessage, ClientMovedEvent, ClientLeftViewEvent, ClientInfo, ChannelInfo, PokeEvent, VoiceData, FileUploadInfo, FileDownloadInfo, FileTransferStatusInfo, EventMap, CommandMiddleware, EventMiddleware, Logger, AddrResolver, ClientOptions, ResolvedAddr, EscapedString, } from "./types.js";
|
|
4
|
+
export { noopLogger, consoleLogger } from "./types.js";
|
|
5
|
+
export { TeamspeakError, ServerError, CommandTimeoutError, AlreadyConnectedError, EAXTagMismatchError, FakeSignatureMismatchError, FileTransferError, FileTransferTimeoutError, CryptoInitError, InvalidIdentityError, } from "./errors.js";
|
|
6
|
+
export { sendTextMessage, clientMove, poke, getClientInfo, listChannels, listClients, fileTransferDeleteFile, } from "./api.js";
|
|
7
|
+
export { dialFileTransfer, uploadFileData, downloadFileData } from "./transfer.js";
|
|
8
|
+
export { Identity, identityFromString, generateIdentity, getUidFromPublicKey, } from "./crypto/index.js";
|
|
9
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,MAAM,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AACnD,YAAY,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAG/C,YAAY,EACV,WAAW,EACX,gBAAgB,EAChB,mBAAmB,EACnB,UAAU,EACV,WAAW,EACX,SAAS,EACT,SAAS,EACT,cAAc,EACd,gBAAgB,EAChB,sBAAsB,EACtB,QAAQ,EACR,iBAAiB,EACjB,eAAe,EACf,MAAM,EACN,YAAY,EACZ,aAAa,EACb,YAAY,EACZ,aAAa,GACd,MAAM,YAAY,CAAC;AACpB,OAAO,EAAE,UAAU,EAAE,aAAa,EAAE,MAAM,YAAY,CAAC;AAGvD,OAAO,EACL,cAAc,EACd,WAAW,EACX,mBAAmB,EACnB,qBAAqB,EACrB,mBAAmB,EACnB,0BAA0B,EAC1B,iBAAiB,EACjB,wBAAwB,EACxB,eAAe,EACf,oBAAoB,GACrB,MAAM,aAAa,CAAC;AAGrB,OAAO,EACL,eAAe,EACf,UAAU,EACV,IAAI,EACJ,aAAa,EACb,YAAY,EACZ,WAAW,EACX,sBAAsB,GACvB,MAAM,UAAU,CAAC;AAGlB,OAAO,EAAE,gBAAgB,EAAE,cAAc,EAAE,gBAAgB,EAAE,MAAM,eAAe,CAAC;AAGnF,OAAO,EACL,QAAQ,EACR,kBAAkB,EAClB,gBAAgB,EAChB,mBAAmB,GACpB,MAAM,mBAAmB,CAAC"}
|