@honeybbq/teamspeak-client 0.3.0 → 0.3.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (106) hide show
  1. package/dist/address-BR-5unVo.cjs.map +1 -1
  2. package/dist/address-BfmovVpp.js.map +1 -1
  3. package/dist/api.d.ts.map +1 -1
  4. package/dist/client.d.ts +16 -1
  5. package/dist/client.d.ts.map +1 -1
  6. package/dist/command/index.cjs +1 -1
  7. package/dist/command/index.mjs +1 -1
  8. package/dist/command/parser.d.ts.map +1 -1
  9. package/dist/command-BLe-C2L2.js.map +1 -1
  10. package/dist/command-DAK4pUBP.cjs.map +1 -1
  11. package/dist/commands.d.ts.map +1 -1
  12. package/dist/crypt-handshake-CQkQreLx.cjs.map +1 -1
  13. package/dist/crypt-handshake-DziOY4Lq.js.map +1 -1
  14. package/dist/{crypt-init2-D70ha4LB.js → crypt-init2-BcGT--df.js} +2 -2
  15. package/dist/crypt-init2-BcGT--df.js.map +1 -0
  16. package/dist/{crypt-init2-DparLekm.cjs → crypt-init2-Bkee1YxV.cjs} +2 -2
  17. package/dist/crypt-init2-Bkee1YxV.cjs.map +1 -0
  18. package/dist/crypto/crypt.d.ts.map +1 -1
  19. package/dist/crypto/eax.d.ts.map +1 -1
  20. package/dist/crypto/identity.d.ts +13 -1
  21. package/dist/crypto/identity.d.ts.map +1 -1
  22. package/dist/crypto/index.cjs +1 -1
  23. package/dist/crypto/index.d.ts +2 -1
  24. package/dist/crypto/index.d.ts.map +1 -1
  25. package/dist/crypto/index.mjs +3 -3
  26. package/dist/{crypto-CDlweUL3.cjs → crypto-BfDd9DP6.cjs} +2 -2
  27. package/dist/crypto-BfDd9DP6.cjs.map +1 -0
  28. package/dist/{crypto-Bg02m4ZE.js → crypto-DLV3oH5F.js} +12 -12
  29. package/dist/crypto-DLV3oH5F.js.map +1 -0
  30. package/dist/discovery/resolver.d.ts.map +1 -1
  31. package/dist/errors.d.ts.map +1 -1
  32. package/dist/{handler-DI_abe9c.js → handler-BpdZFsKo.js} +104 -102
  33. package/dist/handler-BpdZFsKo.js.map +1 -0
  34. package/dist/handler-aywHvv7I.cjs +2 -0
  35. package/dist/handler-aywHvv7I.cjs.map +1 -0
  36. package/dist/handshake/index.cjs +1 -1
  37. package/dist/handshake/index.mjs +1 -1
  38. package/dist/handshake/license.d.ts.map +1 -1
  39. package/dist/handshake.d.ts +9 -0
  40. package/dist/handshake.d.ts.map +1 -1
  41. package/dist/index.cjs +2 -2
  42. package/dist/index.cjs.map +1 -1
  43. package/dist/index.mjs +314 -279
  44. package/dist/index.mjs.map +1 -1
  45. package/dist/{parser-DZMv3Jm-.js → parser-BX8NEiBe.js} +4 -4
  46. package/dist/parser-BX8NEiBe.js.map +1 -0
  47. package/dist/parser-BfwYH2fT.cjs +2 -0
  48. package/dist/parser-BfwYH2fT.cjs.map +1 -0
  49. package/dist/{primitives-xIr6Tjk4.js → primitives-CdX74Rgu.js} +194 -190
  50. package/dist/primitives-CdX74Rgu.js.map +1 -0
  51. package/dist/primitives-DkwW7wcP.cjs +2 -0
  52. package/dist/primitives-DkwW7wcP.cjs.map +1 -0
  53. package/dist/resolver-6B8dI9gr.js.map +1 -1
  54. package/dist/resolver-DCcmyWSK.cjs.map +1 -1
  55. package/dist/throttle.d.ts.map +1 -1
  56. package/dist/transfer.d.ts.map +1 -1
  57. package/dist/transport/generation-window.d.ts.map +1 -1
  58. package/dist/transport/handler.d.ts +9 -1
  59. package/dist/transport/handler.d.ts.map +1 -1
  60. package/dist/transport/index.cjs +1 -1
  61. package/dist/transport/index.mjs +1 -1
  62. package/dist/transport/quicklz.d.ts.map +1 -1
  63. package/dist/types.d.ts +11 -0
  64. package/dist/types.d.ts.map +1 -1
  65. package/package.json +8 -6
  66. package/dist/address.test.d.ts +0 -2
  67. package/dist/address.test.d.ts.map +0 -1
  68. package/dist/api.test.d.ts +0 -2
  69. package/dist/api.test.d.ts.map +0 -1
  70. package/dist/command/command.test.d.ts +0 -2
  71. package/dist/command/command.test.d.ts.map +0 -1
  72. package/dist/crypt-init2-D70ha4LB.js.map +0 -1
  73. package/dist/crypt-init2-DparLekm.cjs.map +0 -1
  74. package/dist/crypto/eax.test.d.ts +0 -2
  75. package/dist/crypto/eax.test.d.ts.map +0 -1
  76. package/dist/crypto/identity.test.d.ts +0 -2
  77. package/dist/crypto/identity.test.d.ts.map +0 -1
  78. package/dist/crypto-Bg02m4ZE.js.map +0 -1
  79. package/dist/crypto-CDlweUL3.cjs.map +0 -1
  80. package/dist/handler-DI_abe9c.js.map +0 -1
  81. package/dist/handler-DuwoO5RC.cjs +0 -2
  82. package/dist/handler-DuwoO5RC.cjs.map +0 -1
  83. package/dist/handshake.test.d.ts +0 -2
  84. package/dist/handshake.test.d.ts.map +0 -1
  85. package/dist/helpers.test.d.ts +0 -2
  86. package/dist/helpers.test.d.ts.map +0 -1
  87. package/dist/integration.test.d.ts +0 -12
  88. package/dist/integration.test.d.ts.map +0 -1
  89. package/dist/notifications.test.d.ts +0 -2
  90. package/dist/notifications.test.d.ts.map +0 -1
  91. package/dist/parser-CL33R9tr.cjs +0 -2
  92. package/dist/parser-CL33R9tr.cjs.map +0 -1
  93. package/dist/parser-DZMv3Jm-.js.map +0 -1
  94. package/dist/primitives-cNNAeFCo.cjs +0 -2
  95. package/dist/primitives-cNNAeFCo.cjs.map +0 -1
  96. package/dist/primitives-xIr6Tjk4.js.map +0 -1
  97. package/dist/throttle.test.d.ts +0 -2
  98. package/dist/throttle.test.d.ts.map +0 -1
  99. package/dist/transport/generation-window.test.d.ts +0 -2
  100. package/dist/transport/generation-window.test.d.ts.map +0 -1
  101. package/dist/transport/packet.test.d.ts +0 -2
  102. package/dist/transport/packet.test.d.ts.map +0 -1
  103. package/dist/transport/quicklz.test.d.ts +0 -2
  104. package/dist/transport/quicklz.test.d.ts.map +0 -1
  105. package/dist/transport/whisper.test.d.ts +0 -2
  106. package/dist/transport/whisper.test.d.ts.map +0 -1
@@ -1,4 +1,4 @@
1
- import { m as e, v as t, y as n } from "./primitives-xIr6Tjk4.js";
1
+ import { b as e, m as t, y as n } from "./primitives-CdX74Rgu.js";
2
2
  import { createCipheriv as r, createECDH as i, createHash as a, timingSafeEqual as o } from "node:crypto";
3
3
  //#region src/crypto/eax.ts
4
4
  var s = 8, c = 16, l = class {
@@ -12,10 +12,10 @@ var s = 8, c = 16, l = class {
12
12
  for (let e = 0; e < s; e++) c[e] = r[e] ^ i[e] ^ o[e];
13
13
  return [a, c];
14
14
  }
15
- decrypt(e, n, r, i) {
16
- let a = this.#t(0, e), c = this.#t(1, n), l = this.#t(2, r), d = new Uint8Array(s);
15
+ decrypt(e, t, r, i) {
16
+ let a = this.#t(0, e), c = this.#t(1, t), l = this.#t(2, r), d = new Uint8Array(s);
17
17
  for (let e = 0; e < s; e++) d[e] = a[e] ^ c[e] ^ l[e];
18
- if (!o(Buffer.from(d), Buffer.from(i.slice(0, s)))) throw new t();
18
+ if (!o(Buffer.from(d), Buffer.from(i.slice(0, s)))) throw new n();
19
19
  return u(this.#e, a, r);
20
20
  }
21
21
  #t(e, t) {
@@ -81,8 +81,8 @@ var _ = 8, v = 10, y = 8, b = 15, x = Buffer.from("TS3INIT1"), S = Buffer.from("
81
81
  for (let e = 0; e < n; e++) a = a * a % o;
82
82
  return D(a, 64);
83
83
  }
84
- initCrypto(t, n, r) {
85
- let i = Buffer.from(t, "base64"), a = Buffer.from(n, "base64"), o = Buffer.from(r, "base64"), s = e(o), c = this.#t(s);
84
+ initCrypto(e, n, r) {
85
+ let i = Buffer.from(e, "base64"), a = Buffer.from(n, "base64"), o = Buffer.from(r, "base64"), s = t(o), c = this.#t(s);
86
86
  this.setSharedSecret(i, a, c);
87
87
  }
88
88
  setSharedSecret(e, t, n) {
@@ -120,14 +120,14 @@ var _ = 8, v = 10, y = 8, b = 15, x = Buffer.from("TS3INIT1"), S = Buffer.from("
120
120
  let [s, c] = this.getKeyNonce(!1, t, n, e, a);
121
121
  return new l(s).encrypt(c, r, i);
122
122
  }
123
- decrypt(e, t, r, i, a, o, s, c) {
124
- if (e === y) return a;
123
+ decrypt(t, n, r, i, a, o, s, c) {
124
+ if (t === y) return a;
125
125
  if (c) {
126
- let e = o.slice(0, _);
127
- if (!Buffer.from(e).equals(Buffer.from(this.fakeSignature))) throw new n();
126
+ let t = o.slice(0, _);
127
+ if (!Buffer.from(t).equals(Buffer.from(this.fakeSignature))) throw new e();
128
128
  return a;
129
129
  }
130
- let [u, d] = this.getKeyNonce(!0, t, r, e, s);
130
+ let [u, d] = this.getKeyNonce(!0, n, r, t, s);
131
131
  return new l(u).decrypt(d, i, a, o);
132
132
  }
133
133
  #t(e) {
@@ -162,4 +162,4 @@ function O(e, t) {
162
162
  //#endregion
163
163
  export { l as n, g as r, w as t };
164
164
 
165
- //# sourceMappingURL=crypto-Bg02m4ZE.js.map
165
+ //# sourceMappingURL=crypto-DLV3oH5F.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"crypto-DLV3oH5F.js","names":["FakeSignatureMismatchError","importPublicKey","EAXTagMismatchError","EAX_TAG_SIZE","EAX_BLOCK_SIZE","EAX","key","#key","nStar","#cmac","nonce","hStar","header","ciphertext","aesCtr","plaintext","cStar","tag","i","expected","timingSafeEqual","input","data","tagByte","aesCmac","cipher","createCipheriv","iv","aesEcb","block","xorBlock","out","a","b","shiftLeft1","carry","shifted","RB","generateSubkeys","L","K1","K2","n","message","lastBlockComplete","X","lastBlock","lastStart","lastSlice","Mn","FAKE_SIGNATURE_SIZE","IV_ALPHA_SIZE","INIT1_PACKET_TYPE","PACKET_TYPE_MASK","INIT1_MAC","DUMMY_KEY","DUMMY_NONCE","Crypt","identity","level","xBytes","offset","nBytes","y","bytesToBigInt","bigIntToBytes","alphaBytes","alpha","betaBytes","beta","omegaBytes","omega","serverPubKey","sharedSecret","#getSharedSecret","sharedKey","digest","createHash","dummy","cacheKey","makeCacheKey","fromServer","packetType","generationID","kn","#cachedKeys","tmpToHash","hash","packetID","unencrypted","fsSub","privJwk","pubJwk","ecdh","createECDH","dBytes","base64UrlToBytes","yBytes","uncompressed","rawSecret","result","bytes","size","v","value","buf","b64url","padded"],"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 +1 @@
1
- {"version":3,"file":"resolver.d.ts","sourceRoot":"","sources":["../../src/discovery/resolver.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,aAAa,CAAC;AAC1C,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAQhD,qBAAa,QAAQ;;gBAGP,IAAI,GAAE,MAAmB;IAE/B,OAAO,CAAC,SAAS,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,WAAW,GAAG,OAAO,CAAC,YAAY,EAAE,CAAC;CA+GhF"}
1
+ {"version":3,"file":"resolver.d.ts","sourceRoot":"","sources":["../../src/discovery/resolver.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,aAAa,CAAC;AAC1C,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAQhD,qBAAa,QAAQ;;IAGnB,YAAY,IAAI,GAAE,MAAmB,EAAI;IAEnC,OAAO,CAAC,SAAS,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,WAAW,GAAG,OAAO,CAAC,YAAY,EAAE,CAAC,CA+C9E;CAgEF"}
@@ -1 +1 @@
1
- {"version":3,"file":"errors.d.ts","sourceRoot":"","sources":["../src/errors.ts"],"names":[],"mappings":"AAAA,qBAAa,cAAe,SAAQ,KAAK;gBAC3B,OAAO,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,YAAY;CAIpD;AAED,qBAAa,WAAY,SAAQ,cAAc;IAC7C,QAAQ,CAAC,EAAE,EAAE,MAAM,CAAC;IACpB,QAAQ,CAAC,aAAa,EAAE,MAAM,CAAC;gBAEnB,EAAE,EAAE,MAAM,EAAE,aAAa,EAAE,MAAM;CAM9C;AAED,qBAAa,mBAAoB,SAAQ,cAAc;IACrD,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;gBAEb,OAAO,EAAE,MAAM;CAK5B;AAED,qBAAa,qBAAsB,SAAQ,cAAc;;CAKxD;AAED,qBAAa,mBAAoB,SAAQ,cAAc;;CAKtD;AAED,qBAAa,0BAA2B,SAAQ,cAAc;;CAK7D;AAED,qBAAa,iBAAkB,SAAQ,cAAc;gBACvC,OAAO,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,YAAY;CAIpD;AAED,qBAAa,wBAAyB,SAAQ,cAAc;;CAK3D;AAED,qBAAa,eAAgB,SAAQ,cAAc;gBACrC,OAAO,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,YAAY;CAIpD;AAED,qBAAa,oBAAqB,SAAQ,cAAc;gBAC1C,OAAO,SAA4B;CAIhD"}
1
+ {"version":3,"file":"errors.d.ts","sourceRoot":"","sources":["../src/errors.ts"],"names":[],"mappings":"AAAA,qBAAa,cAAe,SAAQ,KAAK;IACvC,YAAY,OAAO,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,YAAY,EAGlD;CACF;AAED,qBAAa,WAAY,SAAQ,cAAc;IAC7C,QAAQ,CAAC,EAAE,EAAE,MAAM,CAAC;IACpB,QAAQ,CAAC,aAAa,EAAE,MAAM,CAAC;IAE/B,YAAY,EAAE,EAAE,MAAM,EAAE,aAAa,EAAE,MAAM,EAK5C;CACF;AAED,qBAAa,mBAAoB,SAAQ,cAAc;IACrD,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IAEzB,YAAY,OAAO,EAAE,MAAM,EAI1B;CACF;AAED,qBAAa,qBAAsB,SAAQ,cAAc;IACvD,cAGC;CACF;AAED,qBAAa,mBAAoB,SAAQ,cAAc;IACrD,cAGC;CACF;AAED,qBAAa,0BAA2B,SAAQ,cAAc;IAC5D,cAGC;CACF;AAED,qBAAa,iBAAkB,SAAQ,cAAc;IACnD,YAAY,OAAO,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,YAAY,EAGlD;CACF;AAED,qBAAa,wBAAyB,SAAQ,cAAc;IAC1D,cAGC;CACF;AAED,qBAAa,eAAgB,SAAQ,cAAc;IACjD,YAAY,OAAO,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,YAAY,EAGlD;CACF;AAED,qBAAa,oBAAqB,SAAQ,cAAc;IACtD,YAAY,OAAO,SAA4B,EAG9C;CACF"}
@@ -1,6 +1,6 @@
1
1
  import { o as e, r as t } from "./address-BfmovVpp.js";
2
2
  import { n } from "./crypt-handshake-DziOY4Lq.js";
3
- import { isIP as r } from "node:net";
3
+ import { lookup as r } from "node:dns/promises";
4
4
  import { createSocket as i } from "node:dgram";
5
5
  //#region src/transport/packet.ts
6
6
  var a = /* @__PURE__ */ function(e) {
@@ -163,85 +163,87 @@ var _ = 1024, v = 5e3, y = 6e4, b = 1e3, x = 8, S = 3, C = 5, w = 500, T = 100,
163
163
  onClosed = null;
164
164
  #e;
165
165
  #t;
166
- #n = null;
167
- #r = 0;
168
- #i = !1;
169
- #a = null;
166
+ #n;
167
+ #r = null;
168
+ #i = 0;
169
+ #a = !1;
170
170
  #o = null;
171
- #s = Date.now();
172
- #c = /* @__PURE__ */ new Uint16Array(9);
173
- #l = /* @__PURE__ */ new Uint32Array(9);
174
- #u = new p(65536, _);
171
+ #s = null;
172
+ #c = Date.now();
173
+ #l = /* @__PURE__ */ new Uint16Array(9);
174
+ #u = /* @__PURE__ */ new Uint32Array(9);
175
175
  #d = new p(65536, _);
176
176
  #f = new p(65536, _);
177
177
  #p = new p(65536, _);
178
- #m = /* @__PURE__ */ new Map();
178
+ #m = new p(65536, _);
179
179
  #h = /* @__PURE__ */ new Map();
180
180
  #g = /* @__PURE__ */ new Map();
181
- #_ = null;
182
- constructor(t, n = e) {
183
- this.#e = t, this.#t = n;
181
+ #_ = /* @__PURE__ */ new Map();
182
+ #v = null;
183
+ constructor(t, n = e, r) {
184
+ this.#e = t, this.#t = n, this.#n = r;
184
185
  }
185
186
  setClientID(e) {
186
- this.#r = e;
187
+ this.#i = e;
187
188
  }
188
- connect(e) {
189
- return new Promise((n, a) => {
190
- let { host: o, port: s } = t(e), c = i(r(o) === 6 ? "udp6" : "udp4"), l = (e) => {
191
- c.close(), a(e);
189
+ async connect(e) {
190
+ let { host: n, port: a } = t(e), o = parseInt(a, 10), { address: s, family: c } = await r(n), l = c === 6, u = this.#n ? this.#n(l ? 6 : 4) : i(l ? "udp6" : "udp4");
191
+ await new Promise((e, t) => {
192
+ let n = (e) => {
193
+ u.close(), t(e);
192
194
  };
193
- c.once("error", l), c.connect(parseInt(s, 10), o, () => {
194
- c.off("error", l), this.start(c), n();
195
+ u.once("error", n), u.connect(o, s, () => {
196
+ u.off("error", n), this.start(u), e();
195
197
  });
196
198
  });
197
199
  }
198
200
  start(e) {
199
- this.#n = e, this.#i = !1, this.#s = Date.now(), e.on("message", (e) => {
200
- this.#s = Date.now(), this.#x(new Uint8Array(e.buffer, e.byteOffset, e.byteLength));
201
+ this.#r = e, this.#a = !1, this.#c = Date.now(), e.on("message", (e) => {
202
+ this.#c = Date.now(), this.#S(new Uint8Array(e.buffer, e.byteOffset, e.byteLength));
201
203
  }), e.on("error", (e) => {
202
- this.#t.error("udp error", e), this.#R(e);
203
- }), e.on("close", () => this.#R(null)), this.#c[a.Command] = 1, this.#c[a.Init1] = 101;
204
+ this.#t.error("udp error", e), this.#z(e);
205
+ }), e.on("close", () => this.#z(null)), this.#l[a.Command] = 1, this.#l[a.Init1] = 101;
204
206
  let t = n(this.#e, null);
205
- t && this.#y(a.Init1, t, 0);
207
+ t && this.#b(a.Init1, t, 0);
206
208
  let r = setInterval(() => {
207
209
  this.#e.cryptoInitComplete && this.sendPacket(a.Ping, /* @__PURE__ */ new Uint8Array(), o.Unencrypted);
208
210
  }, v);
209
- this.#a = () => clearInterval(r);
210
- let i = setInterval(() => this.#I(), T);
211
- this.#o = () => clearInterval(i);
211
+ this.#o = () => clearInterval(r);
212
+ let i = setInterval(() => this.#L(), T);
213
+ this.#s = () => clearInterval(i);
212
214
  }
213
215
  receivedFinalInitAck() {
214
- this.#_ = null;
216
+ this.#v = null;
215
217
  }
216
218
  sendPacket(e, t, n) {
217
219
  let r = !this.#e.cryptoInitComplete;
218
220
  if (t.length > 487 && e !== a.Voice && e !== a.VoiceWhisper) {
219
- this.#v(e, t, n, r);
221
+ this.#y(e, t, n, r);
220
222
  return;
221
223
  }
222
- this.#y(e, t, n, r);
224
+ this.#b(e, t, n, r);
223
225
  }
224
226
  sendVoicePacket(e, t) {
225
- let n = this.#c[a.Voice], r = this.#l[a.Voice];
226
- this.#c[a.Voice] = n + 1 & 65535, this.#c[a.Voice] === 0 && this.#l[a.Voice]++;
227
+ let n = this.#l[a.Voice], r = this.#u[a.Voice];
228
+ this.#l[a.Voice] = n + 1 & 65535, this.#l[a.Voice] === 0 && this.#u[a.Voice]++;
227
229
  let i = S + e.length, s = new Uint8Array(i);
228
230
  new DataView(s.buffer).setUint16(0, n, !1), s[2] = t, s.set(e, S);
229
231
  let c = u({
230
232
  typeFlagged: a.Voice | o.Unencrypted,
231
233
  id: n,
232
- clientID: this.#r,
234
+ clientID: this.#i,
233
235
  generationID: r,
234
236
  data: s,
235
237
  receivedAt: 0
236
238
  }), l = new Uint8Array(13 + i);
237
- l.set(this.#e.fakeSignature, 0), l.set(c, x), l.set(s, 13), this.#b(l);
239
+ l.set(this.#e.fakeSignature, 0), l.set(c, x), l.set(s, 13), this.#x(l);
238
240
  }
239
241
  sendWhisperPacket(e, t, n) {
240
242
  if (t.length === 0) throw Error("whisper requires at least one target");
241
243
  if (t.length > 32) throw Error("too many whisper targets");
242
244
  if (t.some((e) => !Number.isInteger(e) || e < 0 || e > 65535)) throw RangeError("invalid whisper target");
243
- let r = this.#c[a.VoiceWhisper], i = this.#l[a.VoiceWhisper];
244
- this.#c[a.VoiceWhisper] = r + 1 & 65535, this.#c[a.VoiceWhisper] === 0 && (this.#l[a.VoiceWhisper] = i + 1 >>> 0);
245
+ let r = this.#l[a.VoiceWhisper], i = this.#u[a.VoiceWhisper];
246
+ this.#l[a.VoiceWhisper] = r + 1 & 65535, this.#l[a.VoiceWhisper] === 0 && (this.#u[a.VoiceWhisper] = i + 1 >>> 0);
245
247
  let s = C + t.length * 2 + e.length, c = new Uint8Array(s), l = new DataView(c.buffer);
246
248
  l.setUint16(0, r, !1), c[2] = n, c[3] = 0, c[4] = t.length;
247
249
  for (let e = 0; e < t.length; e++) l.setUint16(C + e * 2, t[e], !1);
@@ -249,34 +251,34 @@ var _ = 1024, v = 5e3, y = 6e4, b = 1e3, x = 8, S = 3, C = 5, w = 500, T = 100,
249
251
  let d = u({
250
252
  typeFlagged: a.VoiceWhisper | o.Unencrypted,
251
253
  id: r,
252
- clientID: this.#r,
254
+ clientID: this.#i,
253
255
  generationID: i,
254
256
  data: c,
255
257
  receivedAt: 0
256
258
  }), f = new Uint8Array(13 + s);
257
- f.set(this.#e.fakeSignature, 0), f.set(d, x), f.set(c, 13), this.#b(f);
259
+ f.set(this.#e.fakeSignature, 0), f.set(d, x), f.set(c, 13), this.#x(f);
258
260
  }
259
261
  close() {
260
- this.#i || (this.#i = !0, this.#a?.(), this.#o?.(), this.#n?.close());
262
+ this.#a || (this.#a = !0, this.#o?.(), this.#s?.(), this.#r?.close());
261
263
  }
262
- #v(e, t, n, r) {
264
+ #y(e, t, n, r) {
263
265
  let i = 0, a = !0;
264
266
  for (; i < t.length;) {
265
267
  let s = Math.min(t.length - i, 487), c = i + s === t.length, l = n;
266
- a !== c && (l |= o.Fragmented), this.#y(e, t.slice(i, i + s), l, r), i += s, a = !1;
268
+ a !== c && (l |= o.Fragmented), this.#b(e, t.slice(i, i + s), l, r), i += s, a = !1;
267
269
  }
268
270
  }
269
- #y(e, t, n, r = !this.#e.cryptoInitComplete) {
271
+ #b(e, t, n, r = !this.#e.cryptoInitComplete) {
270
272
  n = D(e, n);
271
- let [i, a] = this.#P(e), s = {
273
+ let [i, a] = this.#F(e), s = {
272
274
  typeFlagged: e | n,
273
275
  id: i,
274
- clientID: this.#r,
276
+ clientID: this.#i,
275
277
  generationID: a,
276
278
  data: t,
277
279
  receivedAt: 0
278
280
  }, c = (n & o.Unencrypted) !== 0, l = u(s), [d, f] = this.#e.encrypt(e, i, a, l, t, r, c), p = new Uint8Array(13 + d.length);
279
- p.set(f.slice(0, x), 0), p.set(l, x), p.set(d, 13), this.#b(p);
281
+ p.set(f.slice(0, x), 0), p.set(l, x), p.set(d, 13), this.#x(p);
280
282
  let m = {
281
283
  packet: s,
282
284
  firstSend: Date.now(),
@@ -284,45 +286,45 @@ var _ = 1024, v = 5e3, y = 6e4, b = 1e3, x = 8, S = 3, C = 5, w = 500, T = 100,
284
286
  retryCount: 0,
285
287
  nextInterval: w
286
288
  };
287
- this.#F(e, s, m);
289
+ this.#I(e, s, m);
288
290
  }
289
- #b(e) {
290
- if (this.#n) try {
291
- this.#n.send(Buffer.from(e), (e) => {
291
+ #x(e) {
292
+ if (this.#r) try {
293
+ this.#r.send(Buffer.from(e), (e) => {
292
294
  e && this.#t.warn("udp send error", e);
293
295
  });
294
296
  } catch (e) {
295
297
  let t = e instanceof Error ? e : Error(String(e));
296
- this.#t.error("udp send failed", t), this.#R(t);
298
+ this.#t.error("udp send failed", t), this.#z(t);
297
299
  }
298
300
  }
299
- #x(e) {
301
+ #S(e) {
300
302
  if (e.length < 11) return;
301
303
  let t = e.slice(0, x), n = e.slice(x, 11), r = e.slice(11), i = d(n), o = {
302
304
  ...i,
303
305
  clientID: 0,
304
- generationID: this.#S(i.id, i.typeFlagged & 15),
306
+ generationID: this.#C(i.id, i.typeFlagged & 15),
305
307
  data: /* @__PURE__ */ new Uint8Array(),
306
308
  receivedAt: Date.now()
307
- }, c = this.#C(o, n, r, t);
309
+ }, c = this.#w(o, n, r, t);
308
310
  if (c !== null) {
309
311
  if (o.data = c.plaintext, s(o) === a.Ping) {
310
- this.#E(o.id, c.dummyUsed);
312
+ this.#D(o.id, c.dummyUsed);
311
313
  return;
312
314
  }
313
- this.#w(o, c.dummyUsed) && (this.#D(o), this.#N(o));
315
+ this.#T(o, c.dummyUsed) && (this.#O(o), this.#P(o));
314
316
  }
315
317
  }
316
- #S(e, t) {
318
+ #C(e, t) {
317
319
  switch (t) {
318
- case a.Command: return this.#u.getGeneration(e);
319
- case a.CommandLow: return this.#d.getGeneration(e);
320
- case a.Ack: return this.#f.getGeneration(e);
321
- case a.AckLow: return this.#p.getGeneration(e);
320
+ case a.Command: return this.#d.getGeneration(e);
321
+ case a.CommandLow: return this.#f.getGeneration(e);
322
+ case a.Ack: return this.#p.getGeneration(e);
323
+ case a.AckLow: return this.#m.getGeneration(e);
322
324
  default: return 0;
323
325
  }
324
326
  }
325
- #C(e, t, n, r) {
327
+ #w(e, t, n, r) {
326
328
  let i = (c(e) & o.Unencrypted) !== 0, l = !this.#e.cryptoInitComplete, u = l, d = s(e), f = e.generationID;
327
329
  try {
328
330
  return {
@@ -348,44 +350,44 @@ var _ = 1024, v = 5e3, y = 6e4, b = 1e3, x = 8, S = 3, C = 5, w = 500, T = 100,
348
350
  return null;
349
351
  }
350
352
  }
351
- #w(e, t) {
353
+ #T(e, t) {
352
354
  let n = s(e);
353
355
  if (n !== a.Command && n !== a.CommandLow) return !0;
354
- let r = n === a.Command ? this.#u : this.#d, i = n === a.Command ? a.Ack : a.AckLow;
355
- return r.isInWindow(e.id) ? (this.#T(e.id, i, t), !0) : (r.isOldPacket(e.id) && this.#T(e.id, i, t), !1);
356
+ let r = n === a.Command ? this.#d : this.#f, i = n === a.Command ? a.Ack : a.AckLow;
357
+ return r.isInWindow(e.id) ? (this.#E(e.id, i, t), !0) : (r.isOldPacket(e.id) && this.#E(e.id, i, t), !1);
356
358
  }
357
- #T(e, t, n) {
359
+ #E(e, t, n) {
358
360
  let r = /* @__PURE__ */ new Uint8Array(2);
359
- new DataView(r.buffer).setUint16(0, e, !1), this.#y(t, r, 0, n);
361
+ new DataView(r.buffer).setUint16(0, e, !1), this.#b(t, r, 0, n);
360
362
  }
361
- #E(e, t) {
363
+ #D(e, t) {
362
364
  let n = /* @__PURE__ */ new Uint8Array(2);
363
- new DataView(n.buffer).setUint16(0, e, !1), this.#y(a.Pong, n, o.Unencrypted, t);
365
+ new DataView(n.buffer).setUint16(0, e, !1), this.#b(a.Pong, n, o.Unencrypted, t);
364
366
  }
365
- #D(e) {
367
+ #O(e) {
366
368
  let t = s(e);
367
369
  if (t !== a.Command && t !== a.CommandLow) {
368
370
  this.onPacket?.(e);
369
371
  return;
370
372
  }
371
- let n = t === a.Command, r = n ? this.#m : this.#h, i = n ? this.#u : this.#d;
372
- for (r.set(e.id, e), n ? this.#A(r, i, !0) : this.#A(r, i, !1);;) {
373
- let e = n ? this.#O : this.#k, t = r.get(e);
373
+ let n = t === a.Command, r = n ? this.#h : this.#g, i = n ? this.#d : this.#f;
374
+ for (r.set(e.id, e), n ? this.#j(r, i, !0) : this.#j(r, i, !1);;) {
375
+ let e = n ? this.#k : this.#A, t = r.get(e);
374
376
  if (t === void 0) break;
375
- let a = this.#j(t, r, e, i);
377
+ let a = this.#M(t, r, e, i);
376
378
  if (!a) break;
377
379
  let [o, s] = a;
378
- n ? this.#O = s : this.#k = s, this.#M(o), this.onPacket?.(o);
380
+ n ? this.#k = s : this.#A = s, this.#N(o), this.onPacket?.(o);
379
381
  }
380
382
  }
381
- #O = 0;
382
383
  #k = 0;
383
- #A(e, t, n) {
384
- let r = n ? this.#O : this.#k;
384
+ #A = 0;
385
+ #j(e, t, n) {
386
+ let r = n ? this.#k : this.#A;
385
387
  for (; !e.has(r) && O(e, r);) r = r + 1 & 65535, t.advance(1);
386
- n ? this.#O = r : this.#k = r;
388
+ n ? this.#k = r : this.#A = r;
387
389
  }
388
- #j(e, t, n, r) {
390
+ #M(e, t, n, r) {
389
391
  if ((c(e) & o.Fragmented) === 0) return t.delete(n), r.advance(1), [e, n + 1 & 65535];
390
392
  let i = [], a = 0, s = n, l = !1, u = !1;
391
393
  for (;;) {
@@ -409,7 +411,7 @@ var _ = 1024, v = 5e3, y = 6e4, b = 1e3, x = 8, S = 3, C = 5, w = 500, T = 100,
409
411
  for (let e of i) d.set(e.data, f), f += e.data.length, t.delete(n), r.advance(1), n = n + 1 & 65535;
410
412
  return e.data = d, e.typeFlagged &= ~o.Fragmented, [e, n];
411
413
  }
412
- #M(e) {
414
+ #N(e) {
413
415
  if ((c(e) & o.Compressed) !== 0) try {
414
416
  e.data = new h().decompress(e.data), e.typeFlagged &= ~o.Compressed;
415
417
  } catch (t) {
@@ -419,54 +421,54 @@ var _ = 1024, v = 5e3, y = 6e4, b = 1e3, x = 8, S = 3, C = 5, w = 500, T = 100,
419
421
  });
420
422
  }
421
423
  }
422
- #N(e) {
424
+ #P(e) {
423
425
  let t = s(e);
424
426
  if (t === a.Init1) {
425
- this.#_ = null;
427
+ this.#v = null;
426
428
  return;
427
429
  }
428
430
  if ((t === a.Ack || t === a.AckLow) && e.data.length >= 2) {
429
431
  let n = new DataView(e.data.buffer, e.data.byteOffset).getUint16(0, !1), r = (t === a.Ack ? a.Command : a.CommandLow) << 16 | n;
430
- this.#g.delete(r);
432
+ this.#_.delete(r);
431
433
  }
432
434
  }
433
- #P(e) {
434
- let t = this.#c[e], n = this.#l[e];
435
- return e === a.Init1 ? [t, n] : (this.#c[e] = t + 1 & 65535, this.#c[e] === 0 && (this.#l[e] = n + 1 >>> 0), e === a.Command ? this.#f.advanceToExcluded(t) : e === a.CommandLow && this.#p.advanceToExcluded(t), [t, n]);
435
+ #F(e) {
436
+ let t = this.#l[e], n = this.#u[e];
437
+ return e === a.Init1 ? [t, n] : (this.#l[e] = t + 1 & 65535, this.#l[e] === 0 && (this.#u[e] = n + 1 >>> 0), e === a.Command ? this.#p.advanceToExcluded(t) : e === a.CommandLow && this.#m.advanceToExcluded(t), [t, n]);
436
438
  }
437
- #F(e, t, n) {
439
+ #I(e, t, n) {
438
440
  if (e === a.Init1) {
439
- this.#_ = n;
441
+ this.#v = n;
440
442
  return;
441
443
  }
442
444
  if (e === a.Command || e === a.CommandLow) {
443
445
  let r = e << 16 | t.id;
444
- this.#g.set(r, n);
446
+ this.#_.set(r, n);
445
447
  }
446
448
  }
447
- #I() {
449
+ #L() {
448
450
  let e = Date.now();
449
- if (e - this.#s > y) {
450
- this.#t.warn("idle timeout"), this.#R(/* @__PURE__ */ Error("idle timeout"));
451
+ if (e - this.#c > y) {
452
+ this.#t.warn("idle timeout"), this.#z(/* @__PURE__ */ Error("idle timeout"));
451
453
  return;
452
454
  }
453
- this.#_ && this.#L(this.#_, e);
454
- for (let [t, n] of this.#g) {
455
+ this.#v && this.#R(this.#v, e);
456
+ for (let [t, n] of this.#_) {
455
457
  if (e - n.firstSend > y) {
456
- this.#g.delete(t), this.#R(/* @__PURE__ */ Error("packet ack timeout"));
458
+ this.#_.delete(t), this.#z(/* @__PURE__ */ Error("packet ack timeout"));
457
459
  return;
458
460
  }
459
- this.#L(n, e);
461
+ this.#R(n, e);
460
462
  }
461
463
  }
462
- #L(e, t) {
464
+ #R(e, t) {
463
465
  if (t - e.lastSend < e.nextInterval) return;
464
466
  e.lastSend = t, e.retryCount++, e.nextInterval = Math.min(e.nextInterval * 2, b);
465
467
  let n = !this.#e.cryptoInitComplete, r = (c(e.packet) & o.Unencrypted) !== 0, i = u(e.packet), a = s(e.packet), [l, d] = this.#e.encrypt(a, e.packet.id, e.packet.generationID, i, e.packet.data, n, r), f = new Uint8Array(13 + l.length);
466
- f.set(d.slice(0, x), 0), f.set(i, x), f.set(l, 13), this.#b(f);
468
+ f.set(d.slice(0, x), 0), f.set(i, x), f.set(l, 13), this.#x(f);
467
469
  }
468
- #R(e) {
469
- this.#i || (this.close(), this.onClosed?.(e));
470
+ #z(e) {
471
+ this.#a || (this.close(), this.onClosed?.(e));
470
472
  }
471
473
  };
472
474
  function D(e, t) {
@@ -480,4 +482,4 @@ function O(e, t) {
480
482
  //#endregion
481
483
  export { a, c, d, o as i, s as l, h as n, u as o, p as r, l as s, E as t, f as u };
482
484
 
483
- //# sourceMappingURL=handler-DI_abe9c.js.map
485
+ //# sourceMappingURL=handler-BpdZFsKo.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"handler-BpdZFsKo.js","names":["noopLogger","splitHostPort","PacketType","\"Voice\"","\"VoiceWhisper\"","\"Command\"","\"CommandLow\"","\"Ping\"","\"Pong\"","\"Ack\"","\"AckLow\"","\"Init1\"","PacketFlags","\"Fragmented\"","\"NewProtocol\"","\"Compressed\"","\"Unencrypted\"","packetType","p","packetFlags","isUnencrypted","buildC2SHeader","header","view","parseS2CHeader","raw","parseC2SHeader","GenerationWindow","#mod","mod","#receiveWindow","windowSize","#generation","amount","newBaseOffset","#mappedBaseOffset","genStep","moveDist","mappedValue","maxOffset","#isNextGen","TABLE_SIZE","Qlz","parseQlzHeader","data","dest","decompressedSize","flags","headerLen","#hashtable","state","#ensureControl","#processReference","#processLiteral","st","b1","b2","hash","matchlen","offset","i","end","#updateHashtable","threshold","v","RECEIVE_PACKET_WINDOW_SIZE","PING_INTERVAL_MS","PACKET_TIMEOUT_MS","MAX_RETRY_INTERVAL_MS","TAG_SIZE","VOICE_HEADER_SIZE","WHISPER_HEADER_SIZE","RESEND_BASE_INTERVAL_MS","RESEND_LOOP_INTERVAL_MS","PacketHandler","#crypt","crypt","#logger","logger","#socketFactory","socketFactory","#clientID","id","addr","portNumber","port","lookup","host","family6","family","socket","createSocket","onError","reject","error","address","resolve","#conn","conn","#closed","#lastMessageReceived","#handleRawPacket","msg","err","#triggerClose","#packetCounter","init1Data","processInit1","#sendPacketRaw","pingTimer","#stopPing","resendTimer","#checkResends","#stopResend","#initPacketCheck","dummy","pType","#sendSplitPacket","pID","pGen","#generationCounter","payloadLen","voicePayload","codec","final","#write","targetClientIds","whisperPayload","index","pos","first","blockSize","last","pFlags","applyProtocolFlags","#nextPacketIdentity","unencrypted","ciphertext","tag","rp","#trackResend","normalized","parsed","#resolveGeneration","decrypted","#decryptPacketData","#sendPong","#handleCommandWindowAndAck","#handlePacketQueue","#updatePostReceiveState","#recvWindowCommand","#recvWindowCommandLow","#sendWindowCommand","#sendWindowCommandLow","dummyUsed","gen","guessGen","win","ackType","#sendAck","ackData","packetID","pongData","isCommand","queue","#commandQueue","#commandLowQueue","#fastForwardMissingPackets","current","#_nextCommandID","#_nextCommandLowID","packet","result","#tryReassemble","reassembled","newNext","#tryDecompress","nextID","hasOldNewerPacket","startPacket","fragments","totalSize","currID","startSeen","complete","frag","fragmented","combined","ackID","key","#ackManager","now","#doResend","pkg"],"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 { lookup } from \"node:dns/promises\";\nimport { splitHostPort } from \"../address.js\";\nimport type { Crypt } from \"../crypto/crypt.js\";\nimport type { Logger } from \"../types.js\";\nimport { noopLogger } from \"../types.js\";\nimport {\n type Packet,\n PacketType,\n PacketFlags,\n packetType,\n packetFlags,\n buildC2SHeader,\n parseS2CHeader,\n} from \"./packet.js\";\nimport { GenerationWindow } from \"./generation-window.js\";\nimport { Qlz } from \"./quicklz.js\";\nimport { processInit1 } from \"../handshake/crypt-handshake.js\";\n\nconst MAX_OUT_PACKET_SIZE = 500;\nconst RECEIVE_PACKET_WINDOW_SIZE = 1024;\nconst PING_INTERVAL_MS = 5_000;\nconst PACKET_TIMEOUT_MS = 60_000;\nconst MAX_RETRY_INTERVAL_MS = 1_000;\nconst HEADER_SIZE = 5;\nconst TAG_SIZE = 8;\nconst VOICE_HEADER_SIZE = 3;\nconst WHISPER_HEADER_SIZE = 5;\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\n/**\n * Creates the UDP socket the client talks through.\n *\n * Receives the resolved address family (4 or 6) and returns a socket of that\n * family. Supplying one lets an application route through a proxy or tunnel,\n * or drive the client from something other than a real socket.\n */\nexport type SocketFactory = (family: 4 | 6) => UdpSocket;\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 readonly #socketFactory: SocketFactory | undefined;\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, socketFactory?: SocketFactory) {\n this.#crypt = crypt;\n this.#logger = logger;\n this.#socketFactory = socketFactory;\n }\n\n setClientID(id: number): void {\n this.#clientID = id;\n }\n\n async connect(addr: string): Promise<void> {\n const { host, port } = splitHostPort(addr);\n const portNumber = parseInt(port, 10);\n\n // Resolve before choosing a socket family. `isIP()` only recognises literal\n // addresses and returns 0 for every hostname, so picking the family from it\n // sent every hostname to a udp4 socket — and a udp4 socket handed a name\n // that resolves to IPv6 drops the datagrams with no error at all. On a\n // stock macOS/Linux box `localhost` resolves to ::1 first, so that path\n // silently never connected. Let DNS decide, then match the family.\n const { address, family } = await lookup(host);\n\n const family6 = family === 6;\n const socket = this.#socketFactory\n ? this.#socketFactory(family6 ? 6 : 4)\n : createSocket(family6 ? \"udp6\" : \"udp4\");\n\n await new Promise<void>((resolve, reject) => {\n const onError = (error: Error) => {\n socket.close();\n reject(error);\n };\n socket.once(\"error\", onError);\n // Connect to the resolved address, not the original host, so the socket\n // cannot end up talking to a different family than it was created for.\n socket.connect(portNumber, address, () => {\n socket.off(\"error\", onError);\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 /** Send an unencrypted TeamSpeak voice whisper packet to up to 32 clients. */\n sendWhisperPacket(data: Uint8Array, targetClientIds: number[], codec: number): void {\n if (targetClientIds.length === 0) throw new Error(\"whisper requires at least one target\");\n if (targetClientIds.length > 32) throw new Error(\"too many whisper targets\");\n if (targetClientIds.some((id) => !Number.isInteger(id) || id < 0 || id > 0xffff)) {\n throw new RangeError(\"invalid whisper target\");\n }\n\n const pID = this.#packetCounter[PacketType.VoiceWhisper]!;\n const pGen = this.#generationCounter[PacketType.VoiceWhisper]!;\n this.#packetCounter[PacketType.VoiceWhisper] = (pID + 1) & 0xffff;\n if (this.#packetCounter[PacketType.VoiceWhisper] === 0) {\n this.#generationCounter[PacketType.VoiceWhisper] = (pGen + 1) >>> 0;\n }\n\n const payloadLen = WHISPER_HEADER_SIZE + targetClientIds.length * 2 + data.length;\n const whisperPayload = new Uint8Array(payloadLen);\n const view = new DataView(whisperPayload.buffer);\n view.setUint16(0, pID, false);\n whisperPayload[2] = codec;\n whisperPayload[3] = 0;\n whisperPayload[4] = targetClientIds.length;\n for (let index = 0; index < targetClientIds.length; index++) {\n view.setUint16(WHISPER_HEADER_SIZE + index * 2, targetClientIds[index]!, false);\n }\n whisperPayload.set(data, WHISPER_HEADER_SIZE + targetClientIds.length * 2);\n\n const packet: Packet = {\n typeFlagged: PacketType.VoiceWhisper | PacketFlags.Unencrypted,\n id: pID,\n clientID: this.#clientID,\n generationID: pGen,\n data: whisperPayload,\n receivedAt: 0,\n };\n const header = buildC2SHeader(packet);\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(whisperPayload, 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 if (!this.#conn) return;\n try {\n this.#conn.send(Buffer.from(data), (err) => {\n if (err) this.#logger.warn(\"udp send error\", err);\n });\n } catch (error: unknown) {\n const normalized = error instanceof Error ? error : new Error(String(error));\n // dgram can throw synchronously for an invalid family/address pair. A\n // malformed remote target must close this session, never escape from an\n // async socket callback and terminate the gateway process.\n this.#logger.error(\"udp send failed\", normalized);\n this.#triggerClose(normalized);\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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"}