@honeybbq/teamspeak-client 0.1.0 → 0.2.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/README.md +14 -1
- package/dist/client.d.ts +6 -0
- package/dist/client.d.ts.map +1 -1
- package/dist/{crypt-init2-BIbQ7TN0.cjs → crypt-init2-C2oihZ7e.cjs} +2 -2
- package/dist/crypt-init2-C2oihZ7e.cjs.map +1 -0
- package/dist/{crypt-init2-C63eypta.js → crypt-init2-DWX7Tp-_.js} +36 -41
- package/dist/crypt-init2-DWX7Tp-_.js.map +1 -0
- package/dist/crypto/identity.d.ts.map +1 -1
- package/dist/crypto/index.cjs +1 -1
- package/dist/crypto/index.mjs +3 -3
- package/dist/crypto/primitives.d.ts +17 -2
- package/dist/crypto/primitives.d.ts.map +1 -1
- package/dist/{crypto-C3gBJkh2.cjs → crypto-2veVY1fC.cjs} +2 -2
- package/dist/{crypto-C3gBJkh2.cjs.map → crypto-2veVY1fC.cjs.map} +1 -1
- package/dist/{crypto-IGJlkTAl.js → crypto-VC7n6YJb.js} +12 -12
- package/dist/{crypto-IGJlkTAl.js.map → crypto-VC7n6YJb.js.map} +1 -1
- package/dist/{handler-C2vxlHYC.js → handler-C_JhqGTd.js} +2 -5
- package/dist/handler-C_JhqGTd.js.map +1 -0
- package/dist/{handler-DQteUMKT.cjs → handler-CqCD93f0.cjs} +2 -2
- package/dist/handler-CqCD93f0.cjs.map +1 -0
- package/dist/handshake/index.cjs +1 -1
- package/dist/handshake/index.mjs +1 -1
- package/dist/handshake.d.ts.map +1 -1
- package/dist/handshake.test.d.ts +2 -0
- package/dist/handshake.test.d.ts.map +1 -0
- package/dist/index.cjs +1 -1
- package/dist/index.cjs.map +1 -1
- package/dist/index.mjs +217 -199
- package/dist/index.mjs.map +1 -1
- package/dist/{primitives-CmIK1O7L.js → primitives-BIAYfJ2Y.js} +12 -6
- package/dist/primitives-BIAYfJ2Y.js.map +1 -0
- package/dist/primitives-bj-ml31v.cjs +2 -0
- package/dist/primitives-bj-ml31v.cjs.map +1 -0
- package/dist/transport/handler.d.ts.map +1 -1
- package/dist/transport/index.cjs +1 -1
- package/dist/transport/index.mjs +1 -1
- package/dist/types-CGKgXvpG.js.map +1 -1
- package/dist/types-DrnoCdSW.cjs.map +1 -1
- package/dist/types.d.ts +6 -0
- package/dist/types.d.ts.map +1 -1
- package/package.json +4 -4
- package/dist/crypt-init2-BIbQ7TN0.cjs.map +0 -1
- package/dist/crypt-init2-C63eypta.js.map +0 -1
- package/dist/handler-C2vxlHYC.js.map +0 -1
- package/dist/handler-DQteUMKT.cjs.map +0 -1
- package/dist/primitives-BxtDMP7x.cjs +0 -2
- package/dist/primitives-BxtDMP7x.cjs.map +0 -1
- package/dist/primitives-CmIK1O7L.js.map +0 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"crypto-IGJlkTAl.js","names":["#key","#cmac","#cachedKeys","#getSharedSecret"],"sources":["../src/crypto/eax.ts","../src/crypto/crypt.ts"],"sourcesContent":["import { createCipheriv, timingSafeEqual } from \"node:crypto\";\nimport { EAXTagMismatchError } from \"../errors.js\";\n\nconst EAX_TAG_SIZE = 8;\nconst EAX_BLOCK_SIZE = 16;\n\n/**\n * AES-EAX AEAD implementation for TS3 (64-bit tag, AES-128).\n * Uses AES-CMAC for authentication and AES-CTR for encryption.\n */\nexport class EAX {\n readonly #key: Uint8Array;\n\n constructor(key: Uint8Array) {\n if (key.length !== 16) throw new Error(\"EAX requires a 16-byte key\");\n this.#key = key;\n }\n\n encrypt(\n nonce: Uint8Array,\n header: Uint8Array,\n plaintext: Uint8Array,\n ): [ciphertext: Uint8Array, tag: Uint8Array] {\n const nStar = this.#cmac(0, nonce);\n const hStar = this.#cmac(1, header);\n\n const ciphertext = aesCtr(this.#key, nStar, plaintext);\n\n const cStar = this.#cmac(2, ciphertext);\n\n const tag = new Uint8Array(EAX_TAG_SIZE);\n for (let i = 0; i < EAX_TAG_SIZE; i++) {\n tag[i] = nStar[i]! ^ hStar[i]! ^ cStar[i]!;\n }\n\n return [ciphertext, tag];\n }\n\n decrypt(\n nonce: Uint8Array,\n header: Uint8Array,\n ciphertext: Uint8Array,\n tag: Uint8Array,\n ): Uint8Array {\n const nStar = this.#cmac(0, nonce);\n const hStar = this.#cmac(1, header);\n const cStar = this.#cmac(2, ciphertext);\n\n const expected = new Uint8Array(EAX_TAG_SIZE);\n for (let i = 0; i < EAX_TAG_SIZE; i++) {\n expected[i] = nStar[i]! ^ hStar[i]! ^ cStar[i]!;\n }\n\n if (!timingSafeEqual(Buffer.from(expected), Buffer.from(tag.slice(0, EAX_TAG_SIZE)))) {\n throw new EAXTagMismatchError();\n }\n\n return aesCtr(this.#key, nStar, ciphertext);\n }\n\n /**\n * AES-CMAC per RFC 4493:\n * input = [0…0 tag] ++ data (one block prefix)\n */\n #cmac(tagByte: number, data: Uint8Array): Uint8Array {\n const input = new Uint8Array(EAX_BLOCK_SIZE + data.length);\n // first block: zeros then tag byte at the last position\n input[EAX_BLOCK_SIZE - 1] = tagByte;\n input.set(data, EAX_BLOCK_SIZE);\n\n return aesCmac(this.#key, input);\n }\n}\n\n// ---- AES-CTR ----------------------------------------------------------------\n\nfunction aesCtr(key: Uint8Array, iv: Uint8Array, data: Uint8Array): Uint8Array {\n const cipher = createCipheriv(\"aes-128-ctr\", Buffer.from(key), Buffer.from(iv));\n return Buffer.concat([cipher.update(Buffer.from(data)), cipher.final()]);\n}\n\n// ---- AES-CMAC (RFC 4493) ----------------------------------------------------\n\nfunction aesEcb(key: Uint8Array, block: Uint8Array): Uint8Array {\n // Node.js does not expose ECB directly; simulate via CTR with zero IV and\n // a zero-input (CTR of 0-block XOR with input = ECB)\n const cipher = createCipheriv(\"aes-128-ecb\", Buffer.from(key), null);\n cipher.setAutoPadding(false);\n return Buffer.concat([cipher.update(Buffer.from(block)), cipher.final()]);\n}\n\nfunction xorBlock(a: Uint8Array, b: Uint8Array): Uint8Array {\n const out = new Uint8Array(EAX_BLOCK_SIZE);\n for (let i = 0; i < EAX_BLOCK_SIZE; i++) out[i] = a[i]! ^ b[i]!;\n return out;\n}\n\nfunction shiftLeft1(b: Uint8Array): Uint8Array {\n const out = new Uint8Array(EAX_BLOCK_SIZE);\n let carry = 0;\n for (let i = EAX_BLOCK_SIZE - 1; i >= 0; i--) {\n const shifted = ((b[i]! << 1) | carry) & 0xff;\n carry = b[i]! >> 7;\n out[i] = shifted;\n }\n return out;\n}\n\nconst RB = new Uint8Array(EAX_BLOCK_SIZE);\nRB[EAX_BLOCK_SIZE - 1] = 0x87;\n\nfunction generateSubkeys(key: Uint8Array): [Uint8Array, Uint8Array] {\n const zero = new Uint8Array(EAX_BLOCK_SIZE);\n const L = aesEcb(key, zero);\n\n let K1 = shiftLeft1(L);\n if ((L[0]! & 0x80) !== 0) K1 = xorBlock(K1, RB);\n\n let K2 = shiftLeft1(K1);\n if ((K1[0]! & 0x80) !== 0) K2 = xorBlock(K2, RB);\n\n return [K1, K2];\n}\n\nexport function aesCmac(key: Uint8Array, message: Uint8Array): Uint8Array {\n const [K1, K2] = generateSubkeys(key);\n\n const n = Math.max(1, Math.ceil(message.length / EAX_BLOCK_SIZE));\n const lastBlockComplete = message.length > 0 && message.length % EAX_BLOCK_SIZE === 0;\n\n let X: Uint8Array = new Uint8Array(EAX_BLOCK_SIZE);\n\n for (let i = 0; i < n - 1; i++) {\n const block = message.slice(i * EAX_BLOCK_SIZE, (i + 1) * EAX_BLOCK_SIZE);\n X = Uint8Array.from(aesEcb(key, xorBlock(X, block)));\n }\n\n const lastBlock = new Uint8Array(EAX_BLOCK_SIZE);\n const lastStart = (n - 1) * EAX_BLOCK_SIZE;\n const lastSlice = message.slice(lastStart);\n lastBlock.set(lastSlice);\n\n let Mn: Uint8Array;\n if (lastBlockComplete) {\n Mn = xorBlock(lastBlock, K1);\n } else {\n if (lastSlice.length < EAX_BLOCK_SIZE) lastBlock[lastSlice.length] = 0x80;\n Mn = xorBlock(lastBlock, K2);\n }\n\n return Uint8Array.from(aesEcb(key, xorBlock(X, Mn)));\n}\n","import { createHash, createECDH } from \"node:crypto\";\nimport { FakeSignatureMismatchError } from \"../errors.js\";\nimport type { Identity } from \"./identity.js\";\nimport { importPublicKey } from \"./identity.js\";\nimport { EAX } from \"./eax.js\";\n\nconst FAKE_SIGNATURE_SIZE = 8;\nconst IV_ALPHA_SIZE = 10;\nconst INIT1_PACKET_TYPE = 8;\nconst PACKET_TYPE_MASK = 0x0f;\n\nconst INIT1_MAC = Buffer.from(\"TS3INIT1\");\n\nexport interface KeyNonce {\n key: Uint8Array;\n nonce: Uint8Array;\n gen: number;\n}\n\n/** Precomputed dummy key/nonce matching the TS3 client pre-crypto placeholder. */\nconst DUMMY_KEY = Buffer.from(\"c:\\\\windows\\\\syste\");\nconst DUMMY_NONCE = Buffer.from(\"m\\\\firewall32.cpl\");\n\nexport class Crypt {\n readonly identity: Identity;\n\n ivStruct: Uint8Array = new Uint8Array(0);\n fakeSignature: Uint8Array = new Uint8Array(FAKE_SIGNATURE_SIZE);\n alphaTmp: Uint8Array = new Uint8Array(0);\n cryptoInitComplete = false;\n\n readonly #cachedKeys = new Map<bigint, KeyNonce>();\n\n constructor(identity: Identity) {\n this.identity = identity;\n }\n\n solveRsaChallenge(data: Uint8Array, offset: number, level: number): Uint8Array {\n if (level < 0 || level > 1_000_000) {\n throw new Error(\"RSA challenge level out of range\");\n }\n\n const xBytes = data.slice(offset, offset + 64);\n const nBytes = data.slice(offset + 64, offset + 128);\n\n let y = bytesToBigInt(xBytes);\n const n = bytesToBigInt(nBytes);\n\n for (let i = 0; i < level; i++) {\n y = (y * y) % n;\n }\n\n return bigIntToBytes(y, 64);\n }\n\n initCrypto(alpha: string, beta: string, omega: string): void {\n const alphaBytes = Buffer.from(alpha, \"base64\");\n const betaBytes = Buffer.from(beta, \"base64\");\n const omegaBytes = Buffer.from(omega, \"base64\");\n\n const serverPubKey = importPublicKey(omegaBytes);\n const sharedSecret = this.#getSharedSecret(serverPubKey);\n\n this.setSharedSecret(alphaBytes, betaBytes, sharedSecret);\n }\n\n setSharedSecret(alpha: Uint8Array, beta: Uint8Array, sharedKey: Uint8Array): void {\n this.ivStruct = new Uint8Array(IV_ALPHA_SIZE + beta.length);\n for (let i = 0; i < IV_ALPHA_SIZE; i++) {\n const a = sharedKey[i];\n const b = alpha[i];\n this.ivStruct[i] = ((a !== undefined ? a : 0) ^ (b !== undefined ? b : 0)) & 0xff;\n }\n for (let i = 0; i < beta.length; i++) {\n const a = sharedKey[IV_ALPHA_SIZE + i];\n const b = beta[i];\n this.ivStruct[IV_ALPHA_SIZE + i] =\n ((a !== undefined ? a : 0) ^ (b !== undefined ? b : 0)) & 0xff;\n }\n\n const digest = createHash(\"sha1\").update(this.ivStruct).digest();\n this.fakeSignature = new Uint8Array(digest.buffer, digest.byteOffset, FAKE_SIGNATURE_SIZE);\n this.cryptoInitComplete = true;\n }\n\n getKeyNonce(\n fromServer: boolean,\n packetID: number,\n generationID: number,\n packetType: number,\n dummy: boolean,\n ): [key: Uint8Array, nonce: Uint8Array] {\n if (dummy) {\n return [Uint8Array.from(DUMMY_KEY), Uint8Array.from(DUMMY_NONCE)];\n }\n\n const cacheKey = makeCacheKey(fromServer, packetType, generationID);\n let kn = this.#cachedKeys.get(cacheKey);\n\n if (kn === undefined) {\n const tmpToHash = new Uint8Array(6 + this.ivStruct.length);\n tmpToHash[0] = fromServer ? 0x30 : 0x31;\n tmpToHash[1] = packetType & PACKET_TYPE_MASK;\n new DataView(tmpToHash.buffer).setUint32(2, generationID, false);\n tmpToHash.set(this.ivStruct, 6);\n\n const hash = createHash(\"sha256\").update(tmpToHash).digest();\n kn = {\n key: Uint8Array.from(hash.slice(0, 16)),\n nonce: Uint8Array.from(hash.slice(16, 32)),\n gen: generationID,\n };\n this.#cachedKeys.set(cacheKey, kn);\n }\n\n const key = Uint8Array.from(kn.key);\n key[0] = (key[0] !== undefined ? key[0] : 0) ^ ((packetID >> 8) & 0xff);\n key[1] = (key[1] !== undefined ? key[1] : 0) ^ (packetID & 0xff);\n\n return [key, kn.nonce];\n }\n\n encrypt(\n packetType: number,\n packetID: number,\n generationID: number,\n header: Uint8Array,\n plaintext: Uint8Array,\n dummy: boolean,\n unencrypted: boolean,\n ): [ciphertext: Uint8Array, mac: Uint8Array] {\n if (packetType === INIT1_PACKET_TYPE) {\n return [plaintext, INIT1_MAC];\n }\n if (unencrypted) {\n return [plaintext, this.fakeSignature];\n }\n\n const [key, nonce] = this.getKeyNonce(false, packetID, generationID, packetType, dummy);\n const eax = new EAX(key);\n return eax.encrypt(nonce, header, plaintext);\n }\n\n decrypt(\n packetType: number,\n packetID: number,\n generationID: number,\n header: Uint8Array,\n ciphertext: Uint8Array,\n tag: Uint8Array,\n dummy: boolean,\n unencrypted: boolean,\n ): Uint8Array {\n if (packetType === INIT1_PACKET_TYPE) {\n return ciphertext;\n }\n if (unencrypted) {\n const fsSub = tag.slice(0, FAKE_SIGNATURE_SIZE);\n if (!Buffer.from(fsSub).equals(Buffer.from(this.fakeSignature))) {\n throw new FakeSignatureMismatchError();\n }\n return ciphertext;\n }\n\n const [key, nonce] = this.getKeyNonce(true, packetID, generationID, packetType, dummy);\n const eax = new EAX(key);\n return eax.decrypt(nonce, header, ciphertext, tag);\n }\n\n #getSharedSecret(serverPubKey: import(\"node:crypto\").KeyObject): Uint8Array {\n const privJwk = this.identity.privateKey.export({ format: \"jwk\" }) as {\n d: string;\n };\n const pubJwk = serverPubKey.export({ format: \"jwk\" }) as {\n x: string;\n y: string;\n };\n\n const ecdh = createECDH(\"prime256v1\");\n const dBytes = Buffer.from(privJwk.d, \"base64url\");\n ecdh.setPrivateKey(dBytes);\n\n const xBytes = base64UrlToBytes(pubJwk.x, 32);\n const yBytes = base64UrlToBytes(pubJwk.y, 32);\n const uncompressed = Buffer.alloc(65);\n uncompressed[0] = 0x04;\n xBytes.copy(uncompressed, 1);\n yBytes.copy(uncompressed, 33);\n\n const rawSecret = ecdh.computeSecret(uncompressed);\n return createHash(\"sha1\").update(rawSecret).digest();\n }\n}\n\n// ---- Helpers ----------------------------------------------------------------\n\nfunction makeCacheKey(fromServer: boolean, packetType: number, generationID: number): bigint {\n let key = 0n;\n if (fromServer) key |= 1n << 40n;\n key |= BigInt(packetType & PACKET_TYPE_MASK) << 32n;\n key |= BigInt(generationID);\n return key;\n}\n\nfunction bytesToBigInt(bytes: Uint8Array): bigint {\n let result = 0n;\n for (const b of bytes) result = (result << 8n) | BigInt(b);\n return result;\n}\n\nfunction bigIntToBytes(value: bigint, size: number): Uint8Array {\n const result = new Uint8Array(size);\n let v = value;\n for (let i = size - 1; i >= 0; i--) {\n result[i] = Number(v & 0xffn);\n v >>= 8n;\n }\n return result;\n}\n\nfunction base64UrlToBytes(b64url: string, size: number): Buffer {\n const buf = Buffer.from(b64url, \"base64url\");\n if (buf.length === size) return buf;\n const padded = Buffer.alloc(size);\n buf.copy(padded, size - buf.length);\n return padded;\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"crypto-VC7n6YJb.js","names":["#key","#cmac","#cachedKeys","#getSharedSecret"],"sources":["../src/crypto/eax.ts","../src/crypto/crypt.ts"],"sourcesContent":["import { createCipheriv, timingSafeEqual } from \"node:crypto\";\nimport { EAXTagMismatchError } from \"../errors.js\";\n\nconst EAX_TAG_SIZE = 8;\nconst EAX_BLOCK_SIZE = 16;\n\n/**\n * AES-EAX AEAD implementation for TS3 (64-bit tag, AES-128).\n * Uses AES-CMAC for authentication and AES-CTR for encryption.\n */\nexport class EAX {\n readonly #key: Uint8Array;\n\n constructor(key: Uint8Array) {\n if (key.length !== 16) throw new Error(\"EAX requires a 16-byte key\");\n this.#key = key;\n }\n\n encrypt(\n nonce: Uint8Array,\n header: Uint8Array,\n plaintext: Uint8Array,\n ): [ciphertext: Uint8Array, tag: Uint8Array] {\n const nStar = this.#cmac(0, nonce);\n const hStar = this.#cmac(1, header);\n\n const ciphertext = aesCtr(this.#key, nStar, plaintext);\n\n const cStar = this.#cmac(2, ciphertext);\n\n const tag = new Uint8Array(EAX_TAG_SIZE);\n for (let i = 0; i < EAX_TAG_SIZE; i++) {\n tag[i] = nStar[i]! ^ hStar[i]! ^ cStar[i]!;\n }\n\n return [ciphertext, tag];\n }\n\n decrypt(\n nonce: Uint8Array,\n header: Uint8Array,\n ciphertext: Uint8Array,\n tag: Uint8Array,\n ): Uint8Array {\n const nStar = this.#cmac(0, nonce);\n const hStar = this.#cmac(1, header);\n const cStar = this.#cmac(2, ciphertext);\n\n const expected = new Uint8Array(EAX_TAG_SIZE);\n for (let i = 0; i < EAX_TAG_SIZE; i++) {\n expected[i] = nStar[i]! ^ hStar[i]! ^ cStar[i]!;\n }\n\n if (!timingSafeEqual(Buffer.from(expected), Buffer.from(tag.slice(0, EAX_TAG_SIZE)))) {\n throw new EAXTagMismatchError();\n }\n\n return aesCtr(this.#key, nStar, ciphertext);\n }\n\n /**\n * AES-CMAC per RFC 4493:\n * input = [0…0 tag] ++ data (one block prefix)\n */\n #cmac(tagByte: number, data: Uint8Array): Uint8Array {\n const input = new Uint8Array(EAX_BLOCK_SIZE + data.length);\n // first block: zeros then tag byte at the last position\n input[EAX_BLOCK_SIZE - 1] = tagByte;\n input.set(data, EAX_BLOCK_SIZE);\n\n return aesCmac(this.#key, input);\n }\n}\n\n// ---- AES-CTR ----------------------------------------------------------------\n\nfunction aesCtr(key: Uint8Array, iv: Uint8Array, data: Uint8Array): Uint8Array {\n const cipher = createCipheriv(\"aes-128-ctr\", Buffer.from(key), Buffer.from(iv));\n return Buffer.concat([cipher.update(Buffer.from(data)), cipher.final()]);\n}\n\n// ---- AES-CMAC (RFC 4493) ----------------------------------------------------\n\nfunction aesEcb(key: Uint8Array, block: Uint8Array): Uint8Array {\n // Node.js does not expose ECB directly; simulate via CTR with zero IV and\n // a zero-input (CTR of 0-block XOR with input = ECB)\n const cipher = createCipheriv(\"aes-128-ecb\", Buffer.from(key), null);\n cipher.setAutoPadding(false);\n return Buffer.concat([cipher.update(Buffer.from(block)), cipher.final()]);\n}\n\nfunction xorBlock(a: Uint8Array, b: Uint8Array): Uint8Array {\n const out = new Uint8Array(EAX_BLOCK_SIZE);\n for (let i = 0; i < EAX_BLOCK_SIZE; i++) out[i] = a[i]! ^ b[i]!;\n return out;\n}\n\nfunction shiftLeft1(b: Uint8Array): Uint8Array {\n const out = new Uint8Array(EAX_BLOCK_SIZE);\n let carry = 0;\n for (let i = EAX_BLOCK_SIZE - 1; i >= 0; i--) {\n const shifted = ((b[i]! << 1) | carry) & 0xff;\n carry = b[i]! >> 7;\n out[i] = shifted;\n }\n return out;\n}\n\nconst RB = new Uint8Array(EAX_BLOCK_SIZE);\nRB[EAX_BLOCK_SIZE - 1] = 0x87;\n\nfunction generateSubkeys(key: Uint8Array): [Uint8Array, Uint8Array] {\n const zero = new Uint8Array(EAX_BLOCK_SIZE);\n const L = aesEcb(key, zero);\n\n let K1 = shiftLeft1(L);\n if ((L[0]! & 0x80) !== 0) K1 = xorBlock(K1, RB);\n\n let K2 = shiftLeft1(K1);\n if ((K1[0]! & 0x80) !== 0) K2 = xorBlock(K2, RB);\n\n return [K1, K2];\n}\n\nexport function aesCmac(key: Uint8Array, message: Uint8Array): Uint8Array {\n const [K1, K2] = generateSubkeys(key);\n\n const n = Math.max(1, Math.ceil(message.length / EAX_BLOCK_SIZE));\n const lastBlockComplete = message.length > 0 && message.length % EAX_BLOCK_SIZE === 0;\n\n let X: Uint8Array = new Uint8Array(EAX_BLOCK_SIZE);\n\n for (let i = 0; i < n - 1; i++) {\n const block = message.slice(i * EAX_BLOCK_SIZE, (i + 1) * EAX_BLOCK_SIZE);\n X = Uint8Array.from(aesEcb(key, xorBlock(X, block)));\n }\n\n const lastBlock = new Uint8Array(EAX_BLOCK_SIZE);\n const lastStart = (n - 1) * EAX_BLOCK_SIZE;\n const lastSlice = message.slice(lastStart);\n lastBlock.set(lastSlice);\n\n let Mn: Uint8Array;\n if (lastBlockComplete) {\n Mn = xorBlock(lastBlock, K1);\n } else {\n if (lastSlice.length < EAX_BLOCK_SIZE) lastBlock[lastSlice.length] = 0x80;\n Mn = xorBlock(lastBlock, K2);\n }\n\n return Uint8Array.from(aesEcb(key, xorBlock(X, Mn)));\n}\n","import { createHash, createECDH } from \"node:crypto\";\nimport { FakeSignatureMismatchError } from \"../errors.js\";\nimport type { Identity } from \"./identity.js\";\nimport { importPublicKey } from \"./identity.js\";\nimport { EAX } from \"./eax.js\";\n\nconst FAKE_SIGNATURE_SIZE = 8;\nconst IV_ALPHA_SIZE = 10;\nconst INIT1_PACKET_TYPE = 8;\nconst PACKET_TYPE_MASK = 0x0f;\n\nconst INIT1_MAC = Buffer.from(\"TS3INIT1\");\n\nexport interface KeyNonce {\n key: Uint8Array;\n nonce: Uint8Array;\n gen: number;\n}\n\n/** Precomputed dummy key/nonce matching the TS3 client pre-crypto placeholder. */\nconst DUMMY_KEY = Buffer.from(\"c:\\\\windows\\\\syste\");\nconst DUMMY_NONCE = Buffer.from(\"m\\\\firewall32.cpl\");\n\nexport class Crypt {\n readonly identity: Identity;\n\n ivStruct: Uint8Array = new Uint8Array(0);\n fakeSignature: Uint8Array = new Uint8Array(FAKE_SIGNATURE_SIZE);\n alphaTmp: Uint8Array = new Uint8Array(0);\n cryptoInitComplete = false;\n\n readonly #cachedKeys = new Map<bigint, KeyNonce>();\n\n constructor(identity: Identity) {\n this.identity = identity;\n }\n\n solveRsaChallenge(data: Uint8Array, offset: number, level: number): Uint8Array {\n if (level < 0 || level > 1_000_000) {\n throw new Error(\"RSA challenge level out of range\");\n }\n\n const xBytes = data.slice(offset, offset + 64);\n const nBytes = data.slice(offset + 64, offset + 128);\n\n let y = bytesToBigInt(xBytes);\n const n = bytesToBigInt(nBytes);\n\n for (let i = 0; i < level; i++) {\n y = (y * y) % n;\n }\n\n return bigIntToBytes(y, 64);\n }\n\n initCrypto(alpha: string, beta: string, omega: string): void {\n const alphaBytes = Buffer.from(alpha, \"base64\");\n const betaBytes = Buffer.from(beta, \"base64\");\n const omegaBytes = Buffer.from(omega, \"base64\");\n\n const serverPubKey = importPublicKey(omegaBytes);\n const sharedSecret = this.#getSharedSecret(serverPubKey);\n\n this.setSharedSecret(alphaBytes, betaBytes, sharedSecret);\n }\n\n setSharedSecret(alpha: Uint8Array, beta: Uint8Array, sharedKey: Uint8Array): void {\n this.ivStruct = new Uint8Array(IV_ALPHA_SIZE + beta.length);\n for (let i = 0; i < IV_ALPHA_SIZE; i++) {\n const a = sharedKey[i];\n const b = alpha[i];\n this.ivStruct[i] = ((a !== undefined ? a : 0) ^ (b !== undefined ? b : 0)) & 0xff;\n }\n for (let i = 0; i < beta.length; i++) {\n const a = sharedKey[IV_ALPHA_SIZE + i];\n const b = beta[i];\n this.ivStruct[IV_ALPHA_SIZE + i] =\n ((a !== undefined ? a : 0) ^ (b !== undefined ? b : 0)) & 0xff;\n }\n\n const digest = createHash(\"sha1\").update(this.ivStruct).digest();\n this.fakeSignature = new Uint8Array(digest.buffer, digest.byteOffset, FAKE_SIGNATURE_SIZE);\n this.cryptoInitComplete = true;\n }\n\n getKeyNonce(\n fromServer: boolean,\n packetID: number,\n generationID: number,\n packetType: number,\n dummy: boolean,\n ): [key: Uint8Array, nonce: Uint8Array] {\n if (dummy) {\n return [Uint8Array.from(DUMMY_KEY), Uint8Array.from(DUMMY_NONCE)];\n }\n\n const cacheKey = makeCacheKey(fromServer, packetType, generationID);\n let kn = this.#cachedKeys.get(cacheKey);\n\n if (kn === undefined) {\n const tmpToHash = new Uint8Array(6 + this.ivStruct.length);\n tmpToHash[0] = fromServer ? 0x30 : 0x31;\n tmpToHash[1] = packetType & PACKET_TYPE_MASK;\n new DataView(tmpToHash.buffer).setUint32(2, generationID, false);\n tmpToHash.set(this.ivStruct, 6);\n\n const hash = createHash(\"sha256\").update(tmpToHash).digest();\n kn = {\n key: Uint8Array.from(hash.slice(0, 16)),\n nonce: Uint8Array.from(hash.slice(16, 32)),\n gen: generationID,\n };\n this.#cachedKeys.set(cacheKey, kn);\n }\n\n const key = Uint8Array.from(kn.key);\n key[0] = (key[0] !== undefined ? key[0] : 0) ^ ((packetID >> 8) & 0xff);\n key[1] = (key[1] !== undefined ? key[1] : 0) ^ (packetID & 0xff);\n\n return [key, kn.nonce];\n }\n\n encrypt(\n packetType: number,\n packetID: number,\n generationID: number,\n header: Uint8Array,\n plaintext: Uint8Array,\n dummy: boolean,\n unencrypted: boolean,\n ): [ciphertext: Uint8Array, mac: Uint8Array] {\n if (packetType === INIT1_PACKET_TYPE) {\n return [plaintext, INIT1_MAC];\n }\n if (unencrypted) {\n return [plaintext, this.fakeSignature];\n }\n\n const [key, nonce] = this.getKeyNonce(false, packetID, generationID, packetType, dummy);\n const eax = new EAX(key);\n return eax.encrypt(nonce, header, plaintext);\n }\n\n decrypt(\n packetType: number,\n packetID: number,\n generationID: number,\n header: Uint8Array,\n ciphertext: Uint8Array,\n tag: Uint8Array,\n dummy: boolean,\n unencrypted: boolean,\n ): Uint8Array {\n if (packetType === INIT1_PACKET_TYPE) {\n return ciphertext;\n }\n if (unencrypted) {\n const fsSub = tag.slice(0, FAKE_SIGNATURE_SIZE);\n if (!Buffer.from(fsSub).equals(Buffer.from(this.fakeSignature))) {\n throw new FakeSignatureMismatchError();\n }\n return ciphertext;\n }\n\n const [key, nonce] = this.getKeyNonce(true, packetID, generationID, packetType, dummy);\n const eax = new EAX(key);\n return eax.decrypt(nonce, header, ciphertext, tag);\n }\n\n #getSharedSecret(serverPubKey: import(\"node:crypto\").KeyObject): Uint8Array {\n const privJwk = this.identity.privateKey.export({ format: \"jwk\" }) as {\n d: string;\n };\n const pubJwk = serverPubKey.export({ format: \"jwk\" }) as {\n x: string;\n y: string;\n };\n\n const ecdh = createECDH(\"prime256v1\");\n const dBytes = Buffer.from(privJwk.d, \"base64url\");\n ecdh.setPrivateKey(dBytes);\n\n const xBytes = base64UrlToBytes(pubJwk.x, 32);\n const yBytes = base64UrlToBytes(pubJwk.y, 32);\n const uncompressed = Buffer.alloc(65);\n uncompressed[0] = 0x04;\n xBytes.copy(uncompressed, 1);\n yBytes.copy(uncompressed, 33);\n\n const rawSecret = ecdh.computeSecret(uncompressed);\n return createHash(\"sha1\").update(rawSecret).digest();\n }\n}\n\n// ---- Helpers ----------------------------------------------------------------\n\nfunction makeCacheKey(fromServer: boolean, packetType: number, generationID: number): bigint {\n let key = 0n;\n if (fromServer) key |= 1n << 40n;\n key |= BigInt(packetType & PACKET_TYPE_MASK) << 32n;\n key |= BigInt(generationID);\n return key;\n}\n\nfunction bytesToBigInt(bytes: Uint8Array): bigint {\n let result = 0n;\n for (const b of bytes) result = (result << 8n) | BigInt(b);\n return result;\n}\n\nfunction bigIntToBytes(value: bigint, size: number): Uint8Array {\n const result = new Uint8Array(size);\n let v = value;\n for (let i = size - 1; i >= 0; i--) {\n result[i] = Number(v & 0xffn);\n v >>= 8n;\n }\n return result;\n}\n\nfunction base64UrlToBytes(b64url: string, size: number): Buffer {\n const buf = Buffer.from(b64url, \"base64url\");\n if (buf.length === size) return buf;\n const padded = Buffer.alloc(size);\n buf.copy(padded, size - buf.length);\n return padded;\n}\n"],"mappings":"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"}
|
|
@@ -317,10 +317,7 @@ var h = 500, g = 1024, _ = 5e3, v = 6e4, y = 1e3, b = 5, x = 8, S = 3, C = 500,
|
|
|
317
317
|
dummyUsed: !0
|
|
318
318
|
};
|
|
319
319
|
} catch {}
|
|
320
|
-
return
|
|
321
|
-
type: d,
|
|
322
|
-
id: e.id
|
|
323
|
-
}), null;
|
|
320
|
+
return null;
|
|
324
321
|
}
|
|
325
322
|
}
|
|
326
323
|
#w(e, t) {
|
|
@@ -455,4 +452,4 @@ function D(e, t) {
|
|
|
455
452
|
//#endregion
|
|
456
453
|
export { r as a, o as c, l as d, i, a as l, p as n, c as o, d as r, s, T as t, u };
|
|
457
454
|
|
|
458
|
-
//# sourceMappingURL=handler-
|
|
455
|
+
//# sourceMappingURL=handler-C_JhqGTd.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"handler-C_JhqGTd.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 const p: Packet = {\n typeFlagged: pType | flags,\n id: pID,\n clientID: this.#clientID,\n generationID: pGen,\n data,\n receivedAt: 0,\n };\n\n const unencrypted = (flags & PacketFlags.Unencrypted) !== 0;\n const header = buildC2SHeader(p);\n const [ciphertext, tag] = this.#crypt.encrypt(\n pType,\n pID,\n pGen,\n header,\n data,\n dummy,\n unencrypted,\n );\n\n const final = new Uint8Array(TAG_SIZE + HEADER_SIZE + ciphertext.length);\n final.set(tag.slice(0, TAG_SIZE), 0);\n final.set(header, TAG_SIZE);\n final.set(ciphertext, TAG_SIZE + HEADER_SIZE);\n this.#write(final);\n\n const rp: ResendPacket = {\n packet: p,\n firstSend: Date.now(),\n lastSend: Date.now(),\n retryCount: 0,\n nextInterval: RESEND_BASE_INTERVAL_MS,\n };\n this.#trackResend(pType, p, rp);\n }\n\n #write(data: Uint8Array): void {\n this.#conn?.send(Buffer.from(data), (err) => {\n if (err) this.#logger.warn(\"udp send error\", err);\n });\n }\n\n #handleRawPacket(raw: Uint8Array): void {\n if (raw.length < 11) return;\n\n const tag = raw.slice(0, TAG_SIZE);\n const header = raw.slice(TAG_SIZE, TAG_SIZE + 3);\n const ciphertext = raw.slice(TAG_SIZE + 3);\n\n const parsed = parseS2CHeader(header);\n const p: Packet = {\n ...parsed,\n clientID: 0,\n generationID: this.#resolveGeneration(parsed.id, parsed.typeFlagged & 0x0f),\n data: new Uint8Array(0),\n receivedAt: Date.now(),\n };\n\n const decrypted = this.#decryptPacketData(p, header, ciphertext, tag);\n if (decrypted === null) return;\n p.data = decrypted.plaintext;\n\n const pType = packetType(p);\n\n if (pType === PacketType.Ping) {\n this.#sendPong(p.id, decrypted.dummyUsed);\n return;\n }\n\n if (!this.#handleCommandWindowAndAck(p, decrypted.dummyUsed)) return;\n\n this.#handlePacketQueue(p);\n this.#updatePostReceiveState(p);\n }\n\n #resolveGeneration(id: number, pType: number): number {\n switch (pType as PacketType) {\n case PacketType.Command:\n return this.#recvWindowCommand.getGeneration(id);\n case PacketType.CommandLow:\n return this.#recvWindowCommandLow.getGeneration(id);\n case PacketType.Ack:\n return this.#sendWindowCommand.getGeneration(id);\n case PacketType.AckLow:\n return this.#sendWindowCommandLow.getGeneration(id);\n default:\n return 0;\n }\n }\n\n #decryptPacketData(\n p: Packet,\n header: Uint8Array,\n ciphertext: Uint8Array,\n tag: Uint8Array,\n ): { plaintext: Uint8Array; dummyUsed: boolean } | null {\n const unencrypted = (packetFlags(p) & PacketFlags.Unencrypted) !== 0;\n const dummy = !this.#crypt.cryptoInitComplete;\n let dummyUsed = dummy;\n const pType = packetType(p);\n const gen = p.generationID;\n\n try {\n const plaintext = this.#crypt.decrypt(\n pType,\n p.id,\n gen,\n header,\n ciphertext,\n tag,\n dummy,\n unencrypted,\n );\n return { plaintext, dummyUsed };\n } catch {\n // Try adjacent generations\n for (const offset of [-1, 1]) {\n const guessGen = gen + offset;\n if (guessGen < 0) continue;\n try {\n const plaintext = this.#crypt.decrypt(\n pType,\n p.id,\n guessGen,\n header,\n ciphertext,\n tag,\n false,\n false,\n );\n return { plaintext, dummyUsed: false };\n } catch {\n // continue\n }\n }\n\n // Try dummy fallback for command/ack types\n if (\n pType === PacketType.Command ||\n pType === PacketType.CommandLow ||\n pType === PacketType.Ack\n ) {\n try {\n const plaintext = this.#crypt.decrypt(\n pType,\n p.id,\n gen,\n header,\n ciphertext,\n tag,\n true,\n unencrypted,\n );\n return { plaintext, dummyUsed: true };\n } catch {\n // fall through\n }\n }\n\n return null;\n }\n }\n\n #handleCommandWindowAndAck(p: Packet, dummyUsed: boolean): boolean {\n const pType = packetType(p);\n if (pType !== PacketType.Command && pType !== PacketType.CommandLow) return true;\n\n const win = pType === PacketType.Command ? this.#recvWindowCommand : this.#recvWindowCommandLow;\n const ackType = pType === PacketType.Command ? PacketType.Ack : PacketType.AckLow;\n\n if (!win.isInWindow(p.id)) {\n if (win.isOldPacket(p.id)) {\n this.#sendAck(p.id, ackType, dummyUsed);\n }\n return false;\n }\n this.#sendAck(p.id, ackType, dummyUsed);\n return true;\n }\n\n #sendAck(packetID: number, ackType: PacketType, dummyUsed: boolean): void {\n const ackData = new Uint8Array(2);\n new DataView(ackData.buffer).setUint16(0, packetID, false);\n this.#sendPacketRaw(ackType, ackData, 0, dummyUsed);\n }\n\n #sendPong(pID: number, dummyUsed: boolean): void {\n const pongData = new Uint8Array(2);\n new DataView(pongData.buffer).setUint16(0, pID, false);\n this.#sendPacketRaw(PacketType.Pong, pongData, PacketFlags.Unencrypted, dummyUsed);\n }\n\n #handlePacketQueue(p: Packet): void {\n const pType = packetType(p);\n if (pType !== PacketType.Command && pType !== PacketType.CommandLow) {\n this.onPacket?.(p);\n return;\n }\n\n const isCommand = pType === PacketType.Command;\n const queue = isCommand ? this.#commandQueue : this.#commandLowQueue;\n const win = isCommand ? this.#recvWindowCommand : this.#recvWindowCommandLow;\n\n queue.set(p.id, p);\n\n if (isCommand) {\n this.#fastForwardMissingPackets(queue, win, true);\n } else {\n this.#fastForwardMissingPackets(queue, win, false);\n }\n\n while (true) {\n const current = isCommand ? this.#_nextCommandID : this.#_nextCommandLowID;\n const packet = queue.get(current);\n if (packet === undefined) break;\n\n const result = this.#tryReassemble(packet, queue, current, win);\n if (!result) break;\n\n const [reassembled, newNext] = result;\n if (isCommand) this.#_nextCommandID = newNext;\n else this.#_nextCommandLowID = newNext;\n\n this.#tryDecompress(reassembled);\n this.onPacket?.(reassembled);\n }\n }\n\n #_nextCommandID = 0;\n #_nextCommandLowID = 0;\n\n #fastForwardMissingPackets(\n queue: Map<number, Packet>,\n win: GenerationWindow,\n isCommand: boolean,\n ): void {\n let nextID = isCommand ? this.#_nextCommandID : this.#_nextCommandLowID;\n while (!queue.has(nextID) && hasOldNewerPacket(queue, nextID)) {\n nextID = (nextID + 1) & 0xffff;\n win.advance(1);\n }\n if (isCommand) this.#_nextCommandID = nextID;\n else this.#_nextCommandLowID = nextID;\n }\n\n #tryReassemble(\n startPacket: Packet,\n queue: Map<number, Packet>,\n nextID: number,\n win: GenerationWindow,\n ): [reassembled: Packet, newNextID: number] | null {\n if ((packetFlags(startPacket) & PacketFlags.Fragmented) === 0) {\n queue.delete(nextID);\n win.advance(1);\n return [startPacket, (nextID + 1) & 0xffff];\n }\n\n const fragments: Packet[] = [];\n let totalSize = 0;\n let currID = nextID;\n let startSeen = false;\n let complete = false;\n\n while (true) {\n const frag = queue.get(currID);\n if (!frag) return null;\n fragments.push(frag);\n totalSize += frag.data.length;\n\n const fragmented = (packetFlags(frag) & PacketFlags.Fragmented) !== 0;\n if (!startSeen) {\n startSeen = true;\n if (!fragmented) {\n complete = true;\n break;\n }\n } else if (fragmented) {\n complete = true;\n break;\n }\n currID = (currID + 1) & 0xffff;\n }\n\n if (!complete) return null;\n\n const combined = new Uint8Array(totalSize);\n let pos = 0;\n for (const frag of fragments) {\n combined.set(frag.data, pos);\n pos += frag.data.length;\n queue.delete(nextID);\n win.advance(1);\n nextID = (nextID + 1) & 0xffff;\n }\n\n startPacket.data = combined;\n startPacket.typeFlagged &= ~PacketFlags.Fragmented;\n return [startPacket, nextID];\n }\n\n #tryDecompress(packet: Packet): void {\n if ((packetFlags(packet) & PacketFlags.Compressed) === 0) return;\n try {\n const qlz = new Qlz();\n packet.data = qlz.decompress(packet.data);\n packet.typeFlagged &= ~PacketFlags.Compressed;\n } catch (err) {\n this.#logger.debug(\"decompression failed\", { id: packet.id, err });\n }\n }\n\n #updatePostReceiveState(p: Packet): void {\n const pType = packetType(p);\n\n if (pType === PacketType.Init1) {\n this.#initPacketCheck = null;\n return;\n }\n\n if ((pType === PacketType.Ack || pType === PacketType.AckLow) && p.data.length >= 2) {\n const ackID = new DataView(p.data.buffer, p.data.byteOffset).getUint16(0, false);\n const targetType = pType === PacketType.Ack ? PacketType.Command : PacketType.CommandLow;\n const key = (targetType << 16) | ackID;\n this.#ackManager.delete(key);\n }\n }\n\n #nextPacketIdentity(pType: PacketType): [id: number, gen: number] {\n const pID = this.#packetCounter[pType]!;\n const pGen = this.#generationCounter[pType]!;\n\n if (pType === PacketType.Init1) return [pID, pGen];\n\n this.#packetCounter[pType] = (pID + 1) & 0xffff;\n if (this.#packetCounter[pType] === 0) {\n this.#generationCounter[pType] = (pGen + 1) >>> 0;\n }\n\n if (pType === PacketType.Command) {\n this.#sendWindowCommand.advanceToExcluded(pID);\n } else if (pType === PacketType.CommandLow) {\n this.#sendWindowCommandLow.advanceToExcluded(pID);\n }\n\n return [pID, pGen];\n }\n\n #trackResend(pType: PacketType, p: Packet, rp: ResendPacket): void {\n if (pType === PacketType.Init1) {\n this.#initPacketCheck = rp;\n return;\n }\n if (pType === PacketType.Command || pType === PacketType.CommandLow) {\n const key = (pType << 16) | p.id;\n this.#ackManager.set(key, rp);\n }\n }\n\n #checkResends(): void {\n const now = Date.now();\n\n if (now - this.#lastMessageReceived > PACKET_TIMEOUT_MS) {\n this.#logger.warn(\"idle timeout\");\n this.#triggerClose(new Error(\"idle timeout\"));\n return;\n }\n\n if (this.#initPacketCheck) {\n this.#doResend(this.#initPacketCheck, now);\n }\n\n for (const [key, rp] of this.#ackManager) {\n if (now - rp.firstSend > PACKET_TIMEOUT_MS) {\n this.#ackManager.delete(key);\n this.#triggerClose(new Error(\"packet ack timeout\"));\n return;\n }\n this.#doResend(rp, now);\n }\n }\n\n #doResend(rp: ResendPacket, now: number): void {\n if (now - rp.lastSend < rp.nextInterval) return;\n\n rp.lastSend = now;\n rp.retryCount++;\n rp.nextInterval = Math.min(rp.nextInterval * 2, MAX_RETRY_INTERVAL_MS);\n\n const dummy = !this.#crypt.cryptoInitComplete;\n const unencrypted = (packetFlags(rp.packet) & PacketFlags.Unencrypted) !== 0;\n const header = buildC2SHeader(rp.packet);\n const pType = packetType(rp.packet);\n\n const [ciphertext, tag] = this.#crypt.encrypt(\n pType,\n rp.packet.id,\n rp.packet.generationID,\n header,\n rp.packet.data,\n dummy,\n unencrypted,\n );\n\n const final = new Uint8Array(TAG_SIZE + HEADER_SIZE + ciphertext.length);\n final.set(tag.slice(0, TAG_SIZE), 0);\n final.set(header, TAG_SIZE);\n final.set(ciphertext, TAG_SIZE + HEADER_SIZE);\n this.#write(final);\n }\n\n #triggerClose(err: Error | null): void {\n if (this.#closed) return;\n this.close();\n this.onClosed?.(err);\n }\n}\n\n// ---- Helpers ----------------------------------------------------------------\n\nfunction applyProtocolFlags(pType: PacketType, flags: number): number {\n if (pType === PacketType.Command || pType === PacketType.CommandLow) {\n return flags | PacketFlags.NewProtocol;\n }\n return flags;\n}\n\nfunction hasOldNewerPacket(queue: Map<number, Packet>, nextID: number): boolean {\n const now = Date.now();\n for (const [id, pkg] of queue) {\n const diff = (id - nextID + 0x10000) & 0xffff;\n if (diff < 0x8000 && now - pkg.receivedAt > 5_000) {\n return true;\n }\n }\n return false;\n}\n"],"mappings":"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"}
|
|
@@ -1,2 +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-
|
|
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 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-CqCD93f0.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"handler-CqCD93f0.cjs","names":["#mod","#receiveWindow","#generation","#mappedBaseOffset","#isNextGen","#hashtable","#ensureControl","#processReference","#processLiteral","#updateHashtable","#crypt","#logger","#clientID","#conn","#closed","#lastMessageReceived","#handleRawPacket","#triggerClose","#packetCounter","#sendPacketRaw","#stopPing","#checkResends","#stopResend","#initPacketCheck","#sendSplitPacket","#generationCounter","#write","#nextPacketIdentity","#trackResend","#resolveGeneration","#decryptPacketData","#sendPong","#handleCommandWindowAndAck","#handlePacketQueue","#updatePostReceiveState","#recvWindowCommand","#recvWindowCommandLow","#sendWindowCommand","#sendWindowCommandLow","#sendAck","#commandQueue","#commandLowQueue","#fastForwardMissingPackets","#_nextCommandID","#_nextCommandLowID","#tryReassemble","#tryDecompress","#ackManager","#doResend"],"sources":["../src/transport/packet.ts","../src/transport/generation-window.ts","../src/transport/quicklz.ts","../src/transport/handler.ts"],"sourcesContent":["export const enum PacketType {\n Voice = 0,\n VoiceWhisper = 1,\n Command = 2,\n CommandLow = 3,\n Ping = 4,\n Pong = 5,\n Ack = 6,\n AckLow = 7,\n Init1 = 8,\n}\n\nexport const enum PacketFlags {\n Fragmented = 0x10,\n NewProtocol = 0x20,\n Compressed = 0x40,\n Unencrypted = 0x80,\n}\n\nexport interface Packet {\n /** Type byte combined with flags (low nibble = type, high nibble = flags). */\n typeFlagged: number;\n id: number;\n clientID: number;\n generationID: number;\n data: Uint8Array;\n receivedAt: number; // Date.now()\n}\n\nexport function packetType(p: Packet): PacketType {\n return (p.typeFlagged & 0x0f) as PacketType;\n}\n\nexport function packetFlags(p: Packet): number {\n return p.typeFlagged & 0xf0;\n}\n\nexport function isUnencrypted(p: Packet): boolean {\n return (packetFlags(p) & PacketFlags.Unencrypted) !== 0;\n}\n\n/** Build the 5-byte client-to-server header: [packetID(2), clientID(2), typeFlagged(1)]. */\nexport function buildC2SHeader(p: Packet): Uint8Array {\n const header = new Uint8Array(5);\n const view = new DataView(header.buffer);\n view.setUint16(0, p.id, false);\n view.setUint16(2, p.clientID, false);\n header[4] = p.typeFlagged;\n return header;\n}\n\n/** Parse a 3-byte server-to-client header. */\nexport function parseS2CHeader(raw: Uint8Array): Pick<Packet, \"id\" | \"typeFlagged\"> {\n const view = new DataView(raw.buffer, raw.byteOffset, raw.byteLength);\n return {\n id: view.getUint16(0, false),\n typeFlagged: raw[2]!,\n };\n}\n\n/** Parse a 5-byte client-to-server header. */\nexport function parseC2SHeader(raw: Uint8Array): Pick<Packet, \"id\" | \"clientID\" | \"typeFlagged\"> {\n const view = new DataView(raw.buffer, raw.byteOffset, raw.byteLength);\n return {\n id: view.getUint16(0, false),\n clientID: view.getUint16(2, false),\n typeFlagged: raw[4]!,\n };\n}\n","export class GenerationWindow {\n #mappedBaseOffset = 0;\n #generation = 0;\n readonly #mod: number;\n readonly #receiveWindow: number;\n\n constructor(mod: number, windowSize: number) {\n this.#mod = mod;\n this.#receiveWindow = windowSize;\n }\n\n get generation(): number {\n return this.#generation;\n }\n\n advance(amount: number): void {\n if (amount <= 0) return;\n const newBaseOffset = this.#mappedBaseOffset + amount;\n const genStep = Math.floor(newBaseOffset / this.#mod);\n if (genStep > 0) {\n this.#generation = Math.min(this.#generation + genStep, 0xffff_ffff);\n }\n this.#mappedBaseOffset = newBaseOffset % this.#mod;\n }\n\n advanceToExcluded(mappedValue: number): void {\n let moveDist = mappedValue - this.#mappedBaseOffset;\n if (moveDist < 0) moveDist += this.#mod;\n this.advance(moveDist + 1);\n }\n\n syncTo(mappedValue: number): void {\n let moveDist = mappedValue - this.#mappedBaseOffset;\n if (moveDist < 0) moveDist += this.#mod;\n this.advance(moveDist);\n }\n\n isInWindow(mappedValue: number): boolean {\n const maxOffset = this.#mappedBaseOffset + this.#receiveWindow;\n if (maxOffset < this.#mod) {\n return mappedValue >= this.#mappedBaseOffset && mappedValue < maxOffset;\n }\n return mappedValue >= this.#mappedBaseOffset || mappedValue < maxOffset - this.#mod;\n }\n\n mappedToIndex(mappedValue: number): number {\n if (this.#isNextGen(mappedValue)) {\n return mappedValue + this.#mod - this.#mappedBaseOffset;\n }\n return mappedValue - this.#mappedBaseOffset;\n }\n\n isOldPacket(mappedValue: number): boolean {\n return this.mappedToIndex(mappedValue) < 0;\n }\n\n isFuturePacket(mappedValue: number): boolean {\n return this.mappedToIndex(mappedValue) >= this.#receiveWindow;\n }\n\n #isNextGen(mappedValue: number): boolean {\n return (\n this.#mappedBaseOffset > this.#mod - this.#receiveWindow &&\n mappedValue < this.#mappedBaseOffset + this.#receiveWindow - this.#mod\n );\n }\n\n getGeneration(mappedValue: number): number {\n if (this.#isNextGen(mappedValue)) return this.#generation + 1;\n return this.#generation;\n }\n\n reset(): void {\n this.#mappedBaseOffset = 0;\n this.#generation = 0;\n }\n}\n","const TABLE_SIZE = 4096;\n\ninterface QlzState {\n control: number;\n sourcePos: number;\n destPos: number;\n nextHashed: number;\n}\n\nexport class Qlz {\n #hashtable = new Int32Array(TABLE_SIZE);\n\n decompress(data: Uint8Array): Uint8Array {\n const { headerLen, decompressedSize, flags } = parseQlzHeader(data);\n\n const dest = new Uint8Array(decompressedSize);\n\n if ((flags & 0x01) === 0) {\n dest.set(data.slice(headerLen, headerLen + decompressedSize));\n return dest;\n }\n\n this.#hashtable.fill(0);\n\n const state: QlzState = {\n control: 1,\n sourcePos: headerLen,\n destPos: 0,\n nextHashed: 0,\n };\n\n while (this.#ensureControl(data, state)) {\n if ((state.control & 1) !== 0) {\n if (!this.#processReference(data, dest, state)) break;\n } else {\n if (this.#processLiteral(data, dest, decompressedSize, state)) break;\n }\n }\n\n return dest;\n }\n\n #ensureControl(data: Uint8Array, st: QlzState): boolean {\n if (st.control !== 1) return true;\n if (st.sourcePos + 4 > data.length) return false;\n st.control =\n (data[st.sourcePos]! |\n (data[st.sourcePos + 1]! << 8) |\n (data[st.sourcePos + 2]! << 16) |\n (data[st.sourcePos + 3]! << 24)) >>>\n 0;\n st.sourcePos += 4;\n return true;\n }\n\n #processReference(data: Uint8Array, dest: Uint8Array, st: QlzState): boolean {\n st.control = (st.control >>> 1) >>> 0;\n if (st.sourcePos + 2 > data.length) return false;\n\n const b1 = data[st.sourcePos]!;\n const b2 = data[st.sourcePos + 1]!;\n st.sourcePos += 2;\n\n const hash = (b1 >> 4) | (b2 << 4);\n let matchlen = b1 & 0x0f;\n if (matchlen !== 0) {\n matchlen += 2;\n } else {\n if (st.sourcePos >= data.length) return false;\n matchlen = data[st.sourcePos]!;\n st.sourcePos++;\n }\n\n const offset = this.#hashtable[hash]!;\n for (let i = 0; i < matchlen; i++) {\n if (st.destPos < dest.length && offset + i < st.destPos) {\n dest[st.destPos] = dest[offset + i]!;\n st.destPos++;\n }\n }\n\n const end = st.destPos + 1 - matchlen;\n this.#updateHashtable(dest, st, end);\n st.nextHashed = st.destPos;\n\n return true;\n }\n\n #processLiteral(\n data: Uint8Array,\n dest: Uint8Array,\n decompressedSize: number,\n st: QlzState,\n ): boolean {\n const threshold = Math.max(decompressedSize, 10) - 10;\n if (st.destPos >= threshold) {\n while (st.destPos < decompressedSize) {\n if (st.control === 1) {\n st.sourcePos += 4;\n if (st.sourcePos > data.length) break;\n st.control =\n (data[st.sourcePos - 4]! |\n (data[st.sourcePos - 3]! << 8) |\n (data[st.sourcePos - 2]! << 16) |\n (data[st.sourcePos - 1]! << 24)) >>>\n 0;\n }\n if (st.sourcePos >= data.length) break;\n dest[st.destPos++] = data[st.sourcePos++]!;\n st.control = (st.control >>> 1) >>> 0;\n }\n return true;\n }\n\n if (st.sourcePos >= data.length || st.destPos >= dest.length) return true;\n\n dest[st.destPos++] = data[st.sourcePos++]!;\n st.control = (st.control >>> 1) >>> 0;\n\n const end = Math.max(st.destPos - 2, 0);\n this.#updateHashtable(dest, st, end);\n if (st.nextHashed < end) st.nextHashed = end;\n\n return false;\n }\n\n #updateHashtable(dest: Uint8Array, st: QlzState, end: number): void {\n while (st.nextHashed < end) {\n if (st.nextHashed + 3 > dest.length) break;\n const v =\n (dest[st.nextHashed]! |\n (dest[st.nextHashed + 1]! << 8) |\n (dest[st.nextHashed + 2]! << 16)) >>>\n 0;\n const hash = ((v >> 12) ^ v) & 0xfff;\n this.#hashtable[hash] = st.nextHashed;\n st.nextHashed++;\n }\n }\n}\n\nfunction parseQlzHeader(data: Uint8Array): {\n headerLen: number;\n decompressedSize: number;\n flags: number;\n} {\n if (data.length < 3) throw new Error(\"QuickLZ: data too short\");\n\n const flags = data[0]!;\n const level = (flags >> 2) & 0x03;\n if (level !== 1) throw new Error(\"QuickLZ: only level 1 is supported\");\n\n const headerLen = (flags & 0x02) !== 0 ? 9 : 3;\n if (data.length < headerLen) throw new Error(\"QuickLZ: data too short for header\");\n\n let decompressedSize: number;\n if ((flags & 0x02) !== 0) {\n decompressedSize = (data[5]! | (data[6]! << 8) | (data[7]! << 16) | (data[8]! << 24)) >>> 0;\n } else {\n decompressedSize = data[2]!;\n }\n\n return { headerLen, decompressedSize, flags };\n}\n","import { createSocket, type Socket as UdpSocket } from \"node:dgram\";\nimport type { Crypt } from \"../crypto/crypt.js\";\nimport type { Logger } from \"../types.js\";\nimport { noopLogger } from \"../types.js\";\nimport {\n type Packet,\n PacketType,\n PacketFlags,\n packetType,\n packetFlags,\n buildC2SHeader,\n parseS2CHeader,\n} from \"./packet.js\";\nimport { GenerationWindow } from \"./generation-window.js\";\nimport { Qlz } from \"./quicklz.js\";\nimport { processInit1 } from \"../handshake/crypt-handshake.js\";\n\nconst MAX_OUT_PACKET_SIZE = 500;\nconst RECEIVE_PACKET_WINDOW_SIZE = 1024;\nconst PING_INTERVAL_MS = 5_000;\nconst PACKET_TIMEOUT_MS = 60_000;\nconst MAX_RETRY_INTERVAL_MS = 1_000;\nconst UDP_READ_BUFFER_SIZE = 4096;\nconst HEADER_SIZE = 5;\nconst TAG_SIZE = 8;\nconst VOICE_HEADER_SIZE = 3;\nconst RESEND_BASE_INTERVAL_MS = 500;\nconst RESEND_LOOP_INTERVAL_MS = 100;\n\ninterface ResendPacket {\n packet: Packet;\n firstSend: number;\n lastSend: number;\n retryCount: number;\n nextInterval: number;\n}\n\nexport class PacketHandler {\n onPacket: ((p: Packet) => void) | null = null;\n onClosed: ((err: Error | null) => void) | null = null;\n\n readonly #crypt: Crypt;\n readonly #logger: Logger;\n\n #conn: UdpSocket | null = null;\n #clientID = 0;\n #closed = false;\n #stopPing: (() => void) | null = null;\n #stopResend: (() => void) | null = null;\n #lastMessageReceived = Date.now();\n\n #packetCounter = new Uint16Array(9);\n #generationCounter = new Uint32Array(9);\n\n #recvWindowCommand = new GenerationWindow(1 << 16, RECEIVE_PACKET_WINDOW_SIZE);\n #recvWindowCommandLow = new GenerationWindow(1 << 16, RECEIVE_PACKET_WINDOW_SIZE);\n #sendWindowCommand = new GenerationWindow(1 << 16, RECEIVE_PACKET_WINDOW_SIZE);\n #sendWindowCommandLow = new GenerationWindow(1 << 16, RECEIVE_PACKET_WINDOW_SIZE);\n\n #commandQueue = new Map<number, Packet>();\n #commandLowQueue = new Map<number, Packet>();\n #ackManager = new Map<number, ResendPacket>();\n #initPacketCheck: ResendPacket | null = null;\n\n constructor(crypt: Crypt, logger: Logger = noopLogger) {\n this.#crypt = crypt;\n this.#logger = logger;\n }\n\n setClientID(id: number): void {\n this.#clientID = id;\n }\n\n connect(addr: string): Promise<void> {\n return new Promise((resolve, reject) => {\n const [host, portStr] =\n addr.lastIndexOf(\":\") > 0\n ? [addr.slice(0, addr.lastIndexOf(\":\")), addr.slice(addr.lastIndexOf(\":\") + 1)]\n : [addr, \"9987\"];\n const port = parseInt(portStr, 10);\n\n const socket = createSocket(\"udp4\");\n socket.once(\"error\", reject);\n socket.connect(port, host, () => {\n socket.off(\"error\", reject);\n this.start(socket);\n resolve();\n });\n });\n }\n\n start(conn: UdpSocket): void {\n this.#conn = conn;\n this.#closed = false;\n this.#lastMessageReceived = Date.now();\n\n conn.on(\"message\", (msg) => {\n this.#lastMessageReceived = Date.now();\n this.#handleRawPacket(new Uint8Array(msg.buffer, msg.byteOffset, msg.byteLength));\n });\n conn.on(\"error\", (err) => {\n this.#logger.error(\"udp error\", err);\n this.#triggerClose(err);\n });\n conn.on(\"close\", () => this.#triggerClose(null));\n\n this.#packetCounter[PacketType.Command] = 1;\n this.#packetCounter[PacketType.Init1] = 101;\n\n const init1Data = processInit1(this.#crypt, null);\n if (init1Data) this.#sendPacketRaw(PacketType.Init1, init1Data, 0);\n\n // Ping loop\n const pingTimer = setInterval(() => {\n if (this.#crypt.cryptoInitComplete) {\n this.sendPacket(PacketType.Ping, new Uint8Array(0), PacketFlags.Unencrypted);\n }\n }, PING_INTERVAL_MS);\n this.#stopPing = () => clearInterval(pingTimer);\n\n // Resend loop\n const resendTimer = setInterval(() => this.#checkResends(), RESEND_LOOP_INTERVAL_MS);\n this.#stopResend = () => clearInterval(resendTimer);\n }\n\n receivedFinalInitAck(): void {\n this.#initPacketCheck = null;\n }\n\n sendPacket(pType: PacketType, data: Uint8Array, flags: number): void {\n const dummy = !this.#crypt.cryptoInitComplete;\n if (data.length > 487 && pType !== PacketType.Voice && pType !== PacketType.VoiceWhisper) {\n this.#sendSplitPacket(pType, data, flags, dummy);\n return;\n }\n this.#sendPacketRaw(pType, data, flags, dummy);\n }\n\n sendVoicePacket(data: Uint8Array, codec: number): void {\n const pID = this.#packetCounter[PacketType.Voice]!;\n const pGen = this.#generationCounter[PacketType.Voice]!;\n this.#packetCounter[PacketType.Voice] = (pID + 1) & 0xffff;\n if (this.#packetCounter[PacketType.Voice] === 0) {\n this.#generationCounter[PacketType.Voice]!++;\n }\n\n const payloadLen = VOICE_HEADER_SIZE + data.length;\n const voicePayload = new Uint8Array(payloadLen);\n new DataView(voicePayload.buffer).setUint16(0, pID, false);\n voicePayload[2] = codec;\n voicePayload.set(data, VOICE_HEADER_SIZE);\n\n const p: Packet = {\n typeFlagged: PacketType.Voice | PacketFlags.Unencrypted,\n id: pID,\n clientID: this.#clientID,\n generationID: pGen,\n data: voicePayload,\n receivedAt: 0,\n };\n\n const header = buildC2SHeader(p);\n const final = new Uint8Array(TAG_SIZE + HEADER_SIZE + payloadLen);\n final.set(this.#crypt.fakeSignature, 0);\n final.set(header, TAG_SIZE);\n final.set(voicePayload, TAG_SIZE + HEADER_SIZE);\n this.#write(final);\n }\n\n close(): void {\n if (this.#closed) return;\n this.#closed = true;\n this.#stopPing?.();\n this.#stopResend?.();\n this.#conn?.close();\n }\n\n // ---- Private ---------------------------------------------------------------\n\n #sendSplitPacket(pType: PacketType, data: Uint8Array, flags: number, dummy: boolean): void {\n const maxSize = MAX_OUT_PACKET_SIZE - HEADER_SIZE - TAG_SIZE; // 487\n let pos = 0;\n let first = true;\n\n while (pos < data.length) {\n const blockSize = Math.min(data.length - pos, maxSize);\n const last = pos + blockSize === data.length;\n\n let pFlags = flags;\n if (first !== last) pFlags |= PacketFlags.Fragmented;\n\n this.#sendPacketRaw(pType, data.slice(pos, pos + blockSize), pFlags, dummy);\n pos += blockSize;\n first = false;\n }\n }\n\n #sendPacketRaw(\n pType: PacketType,\n data: Uint8Array,\n flags: number,\n dummy = !this.#crypt.cryptoInitComplete,\n ): void {\n flags = applyProtocolFlags(pType, flags);\n const [pID, pGen] = this.#nextPacketIdentity(pType);\n const p: Packet = {\n typeFlagged: pType | flags,\n id: pID,\n clientID: this.#clientID,\n generationID: pGen,\n data,\n receivedAt: 0,\n };\n\n const unencrypted = (flags & PacketFlags.Unencrypted) !== 0;\n const header = buildC2SHeader(p);\n const [ciphertext, tag] = this.#crypt.encrypt(\n pType,\n pID,\n pGen,\n header,\n data,\n dummy,\n unencrypted,\n );\n\n const final = new Uint8Array(TAG_SIZE + HEADER_SIZE + ciphertext.length);\n final.set(tag.slice(0, TAG_SIZE), 0);\n final.set(header, TAG_SIZE);\n final.set(ciphertext, TAG_SIZE + HEADER_SIZE);\n this.#write(final);\n\n const rp: ResendPacket = {\n packet: p,\n firstSend: Date.now(),\n lastSend: Date.now(),\n retryCount: 0,\n nextInterval: RESEND_BASE_INTERVAL_MS,\n };\n this.#trackResend(pType, p, rp);\n }\n\n #write(data: Uint8Array): void {\n this.#conn?.send(Buffer.from(data), (err) => {\n if (err) this.#logger.warn(\"udp send error\", err);\n });\n }\n\n #handleRawPacket(raw: Uint8Array): void {\n if (raw.length < 11) return;\n\n const tag = raw.slice(0, TAG_SIZE);\n const header = raw.slice(TAG_SIZE, TAG_SIZE + 3);\n const ciphertext = raw.slice(TAG_SIZE + 3);\n\n const parsed = parseS2CHeader(header);\n const p: Packet = {\n ...parsed,\n clientID: 0,\n generationID: this.#resolveGeneration(parsed.id, parsed.typeFlagged & 0x0f),\n data: new Uint8Array(0),\n receivedAt: Date.now(),\n };\n\n const decrypted = this.#decryptPacketData(p, header, ciphertext, tag);\n if (decrypted === null) return;\n p.data = decrypted.plaintext;\n\n const pType = packetType(p);\n\n if (pType === PacketType.Ping) {\n this.#sendPong(p.id, decrypted.dummyUsed);\n return;\n }\n\n if (!this.#handleCommandWindowAndAck(p, decrypted.dummyUsed)) return;\n\n this.#handlePacketQueue(p);\n this.#updatePostReceiveState(p);\n }\n\n #resolveGeneration(id: number, pType: number): number {\n switch (pType as PacketType) {\n case PacketType.Command:\n return this.#recvWindowCommand.getGeneration(id);\n case PacketType.CommandLow:\n return this.#recvWindowCommandLow.getGeneration(id);\n case PacketType.Ack:\n return this.#sendWindowCommand.getGeneration(id);\n case PacketType.AckLow:\n return this.#sendWindowCommandLow.getGeneration(id);\n default:\n return 0;\n }\n }\n\n #decryptPacketData(\n p: Packet,\n header: Uint8Array,\n ciphertext: Uint8Array,\n tag: Uint8Array,\n ): { plaintext: Uint8Array; dummyUsed: boolean } | null {\n const unencrypted = (packetFlags(p) & PacketFlags.Unencrypted) !== 0;\n const dummy = !this.#crypt.cryptoInitComplete;\n let dummyUsed = dummy;\n const pType = packetType(p);\n const gen = p.generationID;\n\n try {\n const plaintext = this.#crypt.decrypt(\n pType,\n p.id,\n gen,\n header,\n ciphertext,\n tag,\n dummy,\n unencrypted,\n );\n return { plaintext, dummyUsed };\n } catch {\n // Try adjacent generations\n for (const offset of [-1, 1]) {\n const guessGen = gen + offset;\n if (guessGen < 0) continue;\n try {\n const plaintext = this.#crypt.decrypt(\n pType,\n p.id,\n guessGen,\n header,\n ciphertext,\n tag,\n false,\n false,\n );\n return { plaintext, dummyUsed: false };\n } catch {\n // continue\n }\n }\n\n // Try dummy fallback for command/ack types\n if (\n pType === PacketType.Command ||\n pType === PacketType.CommandLow ||\n pType === PacketType.Ack\n ) {\n try {\n const plaintext = this.#crypt.decrypt(\n pType,\n p.id,\n gen,\n header,\n ciphertext,\n tag,\n true,\n unencrypted,\n );\n return { plaintext, dummyUsed: true };\n } catch {\n // fall through\n }\n }\n\n return null;\n }\n }\n\n #handleCommandWindowAndAck(p: Packet, dummyUsed: boolean): boolean {\n const pType = packetType(p);\n if (pType !== PacketType.Command && pType !== PacketType.CommandLow) return true;\n\n const win = pType === PacketType.Command ? this.#recvWindowCommand : this.#recvWindowCommandLow;\n const ackType = pType === PacketType.Command ? PacketType.Ack : PacketType.AckLow;\n\n if (!win.isInWindow(p.id)) {\n if (win.isOldPacket(p.id)) {\n this.#sendAck(p.id, ackType, dummyUsed);\n }\n return false;\n }\n this.#sendAck(p.id, ackType, dummyUsed);\n return true;\n }\n\n #sendAck(packetID: number, ackType: PacketType, dummyUsed: boolean): void {\n const ackData = new Uint8Array(2);\n new DataView(ackData.buffer).setUint16(0, packetID, false);\n this.#sendPacketRaw(ackType, ackData, 0, dummyUsed);\n }\n\n #sendPong(pID: number, dummyUsed: boolean): void {\n const pongData = new Uint8Array(2);\n new DataView(pongData.buffer).setUint16(0, pID, false);\n this.#sendPacketRaw(PacketType.Pong, pongData, PacketFlags.Unencrypted, dummyUsed);\n }\n\n #handlePacketQueue(p: Packet): void {\n const pType = packetType(p);\n if (pType !== PacketType.Command && pType !== PacketType.CommandLow) {\n this.onPacket?.(p);\n return;\n }\n\n const isCommand = pType === PacketType.Command;\n const queue = isCommand ? this.#commandQueue : this.#commandLowQueue;\n const win = isCommand ? this.#recvWindowCommand : this.#recvWindowCommandLow;\n\n queue.set(p.id, p);\n\n if (isCommand) {\n this.#fastForwardMissingPackets(queue, win, true);\n } else {\n this.#fastForwardMissingPackets(queue, win, false);\n }\n\n while (true) {\n const current = isCommand ? this.#_nextCommandID : this.#_nextCommandLowID;\n const packet = queue.get(current);\n if (packet === undefined) break;\n\n const result = this.#tryReassemble(packet, queue, current, win);\n if (!result) break;\n\n const [reassembled, newNext] = result;\n if (isCommand) this.#_nextCommandID = newNext;\n else this.#_nextCommandLowID = newNext;\n\n this.#tryDecompress(reassembled);\n this.onPacket?.(reassembled);\n }\n }\n\n #_nextCommandID = 0;\n #_nextCommandLowID = 0;\n\n #fastForwardMissingPackets(\n queue: Map<number, Packet>,\n win: GenerationWindow,\n isCommand: boolean,\n ): void {\n let nextID = isCommand ? this.#_nextCommandID : this.#_nextCommandLowID;\n while (!queue.has(nextID) && hasOldNewerPacket(queue, nextID)) {\n nextID = (nextID + 1) & 0xffff;\n win.advance(1);\n }\n if (isCommand) this.#_nextCommandID = nextID;\n else this.#_nextCommandLowID = nextID;\n }\n\n #tryReassemble(\n startPacket: Packet,\n queue: Map<number, Packet>,\n nextID: number,\n win: GenerationWindow,\n ): [reassembled: Packet, newNextID: number] | null {\n if ((packetFlags(startPacket) & PacketFlags.Fragmented) === 0) {\n queue.delete(nextID);\n win.advance(1);\n return [startPacket, (nextID + 1) & 0xffff];\n }\n\n const fragments: Packet[] = [];\n let totalSize = 0;\n let currID = nextID;\n let startSeen = false;\n let complete = false;\n\n while (true) {\n const frag = queue.get(currID);\n if (!frag) return null;\n fragments.push(frag);\n totalSize += frag.data.length;\n\n const fragmented = (packetFlags(frag) & PacketFlags.Fragmented) !== 0;\n if (!startSeen) {\n startSeen = true;\n if (!fragmented) {\n complete = true;\n break;\n }\n } else if (fragmented) {\n complete = true;\n break;\n }\n currID = (currID + 1) & 0xffff;\n }\n\n if (!complete) return null;\n\n const combined = new Uint8Array(totalSize);\n let pos = 0;\n for (const frag of fragments) {\n combined.set(frag.data, pos);\n pos += frag.data.length;\n queue.delete(nextID);\n win.advance(1);\n nextID = (nextID + 1) & 0xffff;\n }\n\n startPacket.data = combined;\n startPacket.typeFlagged &= ~PacketFlags.Fragmented;\n return [startPacket, nextID];\n }\n\n #tryDecompress(packet: Packet): void {\n if ((packetFlags(packet) & PacketFlags.Compressed) === 0) return;\n try {\n const qlz = new Qlz();\n packet.data = qlz.decompress(packet.data);\n packet.typeFlagged &= ~PacketFlags.Compressed;\n } catch (err) {\n this.#logger.debug(\"decompression failed\", { id: packet.id, err });\n }\n }\n\n #updatePostReceiveState(p: Packet): void {\n const pType = packetType(p);\n\n if (pType === PacketType.Init1) {\n this.#initPacketCheck = null;\n return;\n }\n\n if ((pType === PacketType.Ack || pType === PacketType.AckLow) && p.data.length >= 2) {\n const ackID = new DataView(p.data.buffer, p.data.byteOffset).getUint16(0, false);\n const targetType = pType === PacketType.Ack ? PacketType.Command : PacketType.CommandLow;\n const key = (targetType << 16) | ackID;\n this.#ackManager.delete(key);\n }\n }\n\n #nextPacketIdentity(pType: PacketType): [id: number, gen: number] {\n const pID = this.#packetCounter[pType]!;\n const pGen = this.#generationCounter[pType]!;\n\n if (pType === PacketType.Init1) return [pID, pGen];\n\n this.#packetCounter[pType] = (pID + 1) & 0xffff;\n if (this.#packetCounter[pType] === 0) {\n this.#generationCounter[pType] = (pGen + 1) >>> 0;\n }\n\n if (pType === PacketType.Command) {\n this.#sendWindowCommand.advanceToExcluded(pID);\n } else if (pType === PacketType.CommandLow) {\n this.#sendWindowCommandLow.advanceToExcluded(pID);\n }\n\n return [pID, pGen];\n }\n\n #trackResend(pType: PacketType, p: Packet, rp: ResendPacket): void {\n if (pType === PacketType.Init1) {\n this.#initPacketCheck = rp;\n return;\n }\n if (pType === PacketType.Command || pType === PacketType.CommandLow) {\n const key = (pType << 16) | p.id;\n this.#ackManager.set(key, rp);\n }\n }\n\n #checkResends(): void {\n const now = Date.now();\n\n if (now - this.#lastMessageReceived > PACKET_TIMEOUT_MS) {\n this.#logger.warn(\"idle timeout\");\n this.#triggerClose(new Error(\"idle timeout\"));\n return;\n }\n\n if (this.#initPacketCheck) {\n this.#doResend(this.#initPacketCheck, now);\n }\n\n for (const [key, rp] of this.#ackManager) {\n if (now - rp.firstSend > PACKET_TIMEOUT_MS) {\n this.#ackManager.delete(key);\n this.#triggerClose(new Error(\"packet ack timeout\"));\n return;\n }\n this.#doResend(rp, now);\n }\n }\n\n #doResend(rp: ResendPacket, now: number): void {\n if (now - rp.lastSend < rp.nextInterval) return;\n\n rp.lastSend = now;\n rp.retryCount++;\n rp.nextInterval = Math.min(rp.nextInterval * 2, MAX_RETRY_INTERVAL_MS);\n\n const dummy = !this.#crypt.cryptoInitComplete;\n const unencrypted = (packetFlags(rp.packet) & PacketFlags.Unencrypted) !== 0;\n const header = buildC2SHeader(rp.packet);\n const pType = packetType(rp.packet);\n\n const [ciphertext, tag] = this.#crypt.encrypt(\n pType,\n rp.packet.id,\n rp.packet.generationID,\n header,\n rp.packet.data,\n dummy,\n unencrypted,\n );\n\n const final = new Uint8Array(TAG_SIZE + HEADER_SIZE + ciphertext.length);\n final.set(tag.slice(0, TAG_SIZE), 0);\n final.set(header, TAG_SIZE);\n final.set(ciphertext, TAG_SIZE + HEADER_SIZE);\n this.#write(final);\n }\n\n #triggerClose(err: Error | null): void {\n if (this.#closed) return;\n this.close();\n this.onClosed?.(err);\n }\n}\n\n// ---- Helpers ----------------------------------------------------------------\n\nfunction applyProtocolFlags(pType: PacketType, flags: number): number {\n if (pType === PacketType.Command || pType === PacketType.CommandLow) {\n return flags | PacketFlags.NewProtocol;\n }\n return flags;\n}\n\nfunction hasOldNewerPacket(queue: Map<number, Packet>, nextID: number): boolean {\n const now = Date.now();\n for (const [id, pkg] of queue) {\n const diff = (id - nextID + 0x10000) & 0xffff;\n if (diff < 0x8000 && now - pkg.receivedAt > 5_000) {\n return true;\n }\n }\n return false;\n}\n"],"mappings":"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"}
|
package/dist/handshake/index.cjs
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
Object.defineProperty(exports,Symbol.toStringTag,{value:`Module`});const e=require(`../crypt-handshake-Dbj2cSBZ.cjs`),t=require(`../crypt-init2-
|
|
1
|
+
Object.defineProperty(exports,Symbol.toStringTag,{value:`Module`});const e=require(`../crypt-handshake-Dbj2cSBZ.cjs`),t=require(`../crypt-init2-C2oihZ7e.cjs`);exports.INIT_VERSION=e.t,exports.LicenseChain=t.n,exports.cryptoInit2=t.t,exports.parseLicenses=t.r,exports.processInit1=e.n;
|
package/dist/handshake/index.mjs
CHANGED
|
@@ -1,3 +1,3 @@
|
|
|
1
1
|
import { n as e, t } from "../crypt-handshake-CHmvZ2qs.js";
|
|
2
|
-
import { n, r, t as i } from "../crypt-init2-
|
|
2
|
+
import { n, r, t as i } from "../crypt-init2-DWX7Tp-_.js";
|
|
3
3
|
export { t as INIT_VERSION, n as LicenseChain, i as cryptoInit2, r as parseLicenses, e as processInit1 };
|
package/dist/handshake.d.ts.map
CHANGED
|
@@ -1 +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,
|
|
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,CAGnD"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"handshake.test.d.ts","sourceRoot":"","sources":["../src/handshake.test.ts"],"names":[],"mappings":""}
|
package/dist/index.cjs
CHANGED
|
@@ -1,2 +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;
|
|
1
|
+
Object.defineProperty(exports,Symbol.toStringTag,{value:`Module`});const e=require(`./types-DrnoCdSW.cjs`),t=require(`./primitives-bj-ml31v.cjs`),n=require(`./crypto-2veVY1fC.cjs`),r=require(`./resolver-Dey6omBe.cjs`),i=require(`./handler-CqCD93f0.cjs`),a=require(`./command-Cu2v-5-K.cjs`),o=require(`./crypt-handshake-Dbj2cSBZ.cjs`),s=require(`./crypt-init2-C2oihZ7e.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.C(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.b(`failed to send transfer key: ${e.message}`))):i(o)})});o.setTimeout(1e4),o.once(`error`,a),o.once(`timeout`,()=>{o.destroy(),a(new t.b(`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.r(),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.o(e.crypt.identity.privateKey,a);return Buffer.from(o).toString(`base64`)}function D(e){let t=O(e);e.handler.sendPacket(i.a.Command,Buffer.from(t),0)}function O(e){let t=e.crypt.identity.publicKeyBase64(),n=e.getClientInitOptions(),r=(0,l.createHash)(`sha1`).update(t).digest().toString(`base64`);return a.n(`clientinit`,[[`client_nickname`,e.nickname],[`client_version`,`3.?.? [Build: 5680278000]`],[`client_platform`,`Windows`],[`client_input_hardware`,`1`],[`client_output_hardware`,`1`],[`client_default_channel`,n.defaultChannel],[`client_default_channel_password`,n.defaultChannelPassword],[`client_server_password`,n.serverPassword],[`client_meta_data`,``],[`client_version_sign`,`DX5NIYLvfJEUjuIbCidnoeozxIDRRkpq3I9vVMBmE9L2qnekOoBzSenkzsg2lC9CMv8K5hkEzhr2TYUYSwUXCg==`],[`client_key_offset`,String(e.crypt.identity.offset)],[`client_nickname_phonetic`,``],[`client_default_token`,``],[`hwid`,r]])}function k(e){if(e===``||e===void 0)return 0n;try{return BigInt(e)}catch{return 0n}}function A(e){let t=parseInt(e,10);return isNaN(t)||t<0||t>65535?0:t}function j(e){let t=parseInt(e,10);return isNaN(t)?0:t}function M(e,t){if(t===e)return!0;if(!t.startsWith(e))return!1;let n=t.slice(e.length);return/^\d+$/.test(n)}function N(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 P(e,t,n,r){switch(e.name){case`notifycliententerview`:return F(e,n,r);case`notifyclientleftview`:return I(e,t,n);case`notifyclientmoved`:return L(e,n);case`notifytextmessage`:return R(e,n);case`notifyclientpoke`:return H(e);case`notifystartupload`:return{kind:`startUpload`,info:z(e)};case`notifystartdownload`:return{kind:`startDownload`,info:B(e)};case`notifystatusfiletransfer`:return{kind:`fileTransferStatus`,info:V(e)};default:return{kind:`unknown`}}}function F(e,t,n){let r=A(e.params.clid??``),i=k(e.params.cid??``),a=j(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 I(e,t,n){let r=A(e.params.clid??``),i=j(e.params.reasonid??``),a=r===t;return r!==0&&n.delete(r),{kind:`clientLeave`,event:{id:r,reasonID:i,reasonMsg:e.params.reasonmsg??``,targetID:A(e.params.targetid??``)},isSelf:a}}function L(e,t){let n=A(e.params.clid??``),r=k(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:j(e.params.reasonid??``),invokerID:A(e.params.invokerid??``),invokerName:e.params.invokername??``,invokerUID:e.params.invokeruid??``}}}function R(e,t){let n=A(e.params.invokerid??``),r=t.get(n);return{kind:`textMessage`,message:{targetMode:j(e.params.targetmode??``),targetID:k(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 z(e){return{clientFileTransferID:A(e.params.clientftfid??``),serverFileTransferID:A(e.params.serverftfid??``),fileTransferKey:e.params.ftkey??``,port:A(e.params.port??``),seekPosition:k(e.params.seekpos??``)}}function B(e){return{clientFileTransferID:A(e.params.clientftfid??``),serverFileTransferID:A(e.params.serverftfid??``),fileTransferKey:e.params.ftkey??``,port:A(e.params.port??``),size:k(e.params.size??``)}}function V(e){return{clientFileTransferID:A(e.params.clientftfid??``),status:j(e.params.status??``),message:e.params.msg??``}}function H(e){return{kind:`poked`,event:{invokerID:A(e.params.invokerid??``),invokerName:a.i(e.params.invokername??``),invokerUID:e.params.invokeruid??``,message:a.i(e.params.msg??``)}}}var U=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})})}}};function W(e){return{serverPassword:e.serverPassword??``,defaultChannel:e.defaultChannel??``,defaultChannelPassword:e.defaultChannelPassword??``}}var G=class{crypt;handler;logger;nickname;clid=0;#e;#t;#n;#r;#i=e.t.Disconnected;#a=new U;#o=new d;#s=new m;#c=new Map;#l=[];#u=[];#d=[];#f=[];#p=[];#m=[];#h=[];#g=[];#_=[];#v=[];#y=[];#b=[];#x;#S;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.#r=W(s),this.crypt=new n.t(t),this.handler=new i.t(this.crypt,this.logger),this.handler.onPacket=e=>this.#T(e),this.handler.onClosed=e=>this.#P(e),s.commandMiddleware&&this.#y.push(...s.commandMiddleware),s.eventMiddleware&&this.#b.push(...s.eventMiddleware),this.#x=this.#F(),this.#S=this.#I()}get status(){return this.#i}getClientInitOptions(){return this.#r}async connect(){if(this.#i!==e.t.Disconnected)throw new t.h;this.#C(),this.#i=e.t.Connecting;let n=await this.#w();this.logger.info(`connecting to server`,{address:n}),await this.handler.connect(n)}async disconnect(){if(this.#i===e.t.Disconnected)return;let t=this.#i===e.t.Connected;if(this.#i=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.#_.slice();for(let e of n)setImmediate(()=>e(void 0))}waitConnected(t){return this.#i===e.t.Connected?Promise.resolve():new Promise((e,n)=>{this.#l.push(e),t&&t.addEventListener(`abort`,()=>n(t.reason),{once:!0})})}async sendCommandNoWait(e){await this.#a.wait(),await this.#x(e)}async execCommand(e,t=1e4){await this.execCommandWithResponse(e,t)}async execCommandWithResponse(e,n=1e4){let[r,i]=this.#o.register(),a=p(e,r);try{await this.#a.wait(),await this.#x(a)}catch(e){throw this.#o.unregister(r),e}let o=await Promise.race([i,new Promise((r,i)=>setTimeout(()=>i(new t.g(e)),n))]);if(this.#o.unregister(r),o.err)throw o.err;return o.data}on(e,t){switch(e){case`textMessage`:this.#u.push(t);break;case`clientEnter`:this.#d.push(t);break;case`clientLeave`:this.#f.push(t);break;case`clientMoved`:this.#p.push(t);break;case`poked`:this.#m.push(t);break;case`voiceData`:this.#h.push(t);break;case`connected`:this.#g.push(t);break;case`disconnected`:this.#_.push(t);break;case`kicked`:this.#v.push(t);break}return this}useCommandMiddleware(...e){return this.#y.push(...e),this.#x=this.#F(),this}useEventMiddleware(...e){return this.#b.push(...e),this.#S=this.#I(),this}clientID(){return this.clid}channelID(){return this.#c.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.#s.register(),c=v(e,n,r,i,o,a);try{await this.execCommand(c,1e4)}catch(e){throw this.#s.unregister(o),e}let l=await Promise.race([s,new Promise((e,n)=>setTimeout(()=>n(new t.x),1e4))]);if(this.#s.unregister(o),`size`in l)throw new t.b(`unexpected download response`);if(`status`in l){let e=l;throw new t.b(`${e.message} (status=${e.status})`)}return l}async fileTransferInitDownload(e,n,r){let[i,a]=this.#s.register(),o=y(e,n,r,i);try{await this.execCommand(o,1e4)}catch(e){throw this.#s.unregister(i),e}let s=await Promise.race([a,new Promise((e,n)=>setTimeout(()=>n(new t.x),1e4))]);if(this.#s.unregister(i),`seekPosition`in s)throw new t.b(`unexpected upload response`);if(`status`in s){let e=s;throw new t.b(`${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.#i=e.t.Connected;for(let e of this.#l)e();this.#l=[];let t=this.#g.slice();for(let e of t)setImmediate(()=>e())}#C(){this.handler.close(),this.crypt=new n.t(this.#e),this.handler=new i.t(this.crypt,this.logger),this.handler.onPacket=e=>this.#T(e),this.handler.onClosed=e=>this.#P(e),this.#o.reset(),this.#s.reset(),this.#c.clear(),this.clid=0,this.#x=this.#F()}async#w(){let e=this.#t.includes(`:`)?this.#t:`${this.#t}:9987`;try{return(await this.#n.resolve(this.#t))[0]?.addr??e}catch{return e}}#T(e){this.#E(e)}#E(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.#D(e.data);return}(t===2||t===3)&&e.data.length>0&&this.#O(Buffer.from(e.data).toString(`utf8`))}#D(e){if(this.#h.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.#h)setImmediate(()=>e(n))}#O(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 N(t))this.#k(e)}}#k(e){let t=c.t(e);if(!(!t||!t.name)){if(t.name.startsWith(`notify`)){let e=P(t,this.clid,this.#c,this.nickname);this.#j(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.#A(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.#o.buffer(e);break}}}}#A(e){let{err:t,rc:n}=f(e);n===null?this.#o.discardBuffer():this.#o.resolve(n,t),(e.id??`0`)===`3329`&&setImmediate(()=>this.disconnect().catch(()=>{}))}#j(e,t){switch(e.kind){case`clientEnter`:{let t=e.info;t.id!==0&&M(this.nickname,t.nickname)&&(this.clid=t.id,this.handler.setClientID(t.id),this.#o.signalWelcomeComplete()),this.#M(`clientEnter`,t);break}case`clientLeave`:if(this.#M(`clientLeave`,e.event),e.isSelf&&(e.event.reasonID===4||e.event.reasonID===5)){let t=e.event.reasonMsg;for(let e of this.#v)setImmediate(()=>e(t))}break;case`clientMoved`:this.#M(`clientMoved`,e.event);break;case`textMessage`:this.#M(`textMessage`,e.message);break;case`poked`:this.#M(`poked`,e.event);break;case`startUpload`:this.#s.notify(e.info.clientFileTransferID,e.info);break;case`startDownload`:this.#s.notify(e.info.clientFileTransferID,e.info);break;case`fileTransferStatus`:this.#s.notify(e.info.clientFileTransferID,e.info);break}}#M(e,t){this.#S(t)}#N(e,t){switch(e){case`textMessage`:for(let e of this.#u)setImmediate(()=>e(t));break;case`clientEnter`:for(let e of this.#d)setImmediate(()=>e(t));break;case`clientLeave`:for(let e of this.#f)setImmediate(()=>e(t));break;case`clientMoved`:for(let e of this.#p)setImmediate(()=>e(t));break;case`poked`:for(let e of this.#m)setImmediate(()=>e(t));break}}#P(t){if(this.#i===e.t.Disconnected)return;this.#i=e.t.Disconnected;let n=this.#_.slice();for(let e of n)setImmediate(()=>e(t??void 0))}#F(){return b(this.#y,async e=>{this.handler.sendPacket(i.a.Command,Buffer.from(e),0)})}#I(){return x(this.#b,e=>{typeof e==`object`&&e&&`invokerName`in e&&`message`in e&&`targetMode`in e?this.#N(`textMessage`,e):typeof e==`object`&&e&&`invokerName`in e&&`message`in e&&!(`targetMode`in e)?this.#N(`poked`,e):typeof e==`object`&&e&&`id`in e&&`uid`in e?this.#N(`clientEnter`,e):typeof e==`object`&&e&&`id`in e&&`reasonID`in e&&`targetChannelID`in e?this.#N(`clientMoved`,e):typeof e==`object`&&e&&`id`in e&&`reasonID`in e&&this.#N(`clientLeave`,e)})}};async function K(e,t,n,r){let i=a.n(`sendtextmessage`,[[`targetmode`,String(t)],[`target`,String(n)],[`msg`,r]]);await e.sendCommandNoWait(i)}async function q(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 J(e,t,n){let r=a.n(`clientpoke`,[[`clid`,String(t)],[`msg`,n]]);await e.execCommand(r,1e4)}async function Y(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 X(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 Z(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 Q(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.h,exports.Client=G,exports.ClientStatus=e.t,exports.CommandTimeoutError=t.g,exports.CryptoInitError=t._,exports.EAXTagMismatchError=t.v,exports.FakeSignatureMismatchError=t.y,exports.FileTransferError=t.b,exports.FileTransferTimeoutError=t.x,exports.Identity=t.l,exports.InvalidIdentityError=t.S,exports.ServerError=t.C,exports.TeamspeakError=t.w,exports.clientMove=q,exports.consoleLogger=e.n,exports.dialFileTransfer=h,exports.downloadFileData=_,exports.fileTransferDeleteFile=Q,exports.generateIdentity=t.u,exports.getClientInfo=Y,exports.getUidFromPublicKey=t.d,exports.identityFromString=t.p,exports.listChannels=X,exports.listClients=Z,exports.noopLogger=e.r,exports.poke=J,exports.sendTextMessage=K,exports.uploadFileData=g;
|
|
2
2
|
//# sourceMappingURL=index.cjs.map
|