@jshookmcp/jshook 0.3.1 → 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 (226) hide show
  1. package/LICENSE +661 -661
  2. package/README.md +11 -3
  3. package/README.zh.md +11 -3
  4. package/dist/{AntiCheatDetector-CGVGNfy5.mjs → AntiCheatDetector-B6d4Qe9D.mjs} +1 -1
  5. package/dist/BrowserSessionCoordinator-BJ-HOxo0.mjs +1 -0
  6. package/dist/{CodeInjector-BlgyqTOk.mjs → CodeInjector-Cll_7bLJ.mjs} +1 -1
  7. package/dist/ConsoleMonitor-CxDJV15E.mjs +306 -0
  8. package/dist/DOMInspector-C19J4zeq.mjs +95 -0
  9. package/dist/DetailedDataManager-DmQ1LT-W.mjs +1 -0
  10. package/dist/ExtensionManager-BD724zkO.mjs +1 -0
  11. package/dist/ExtensionManager.tools-oVMJgPcN.mjs +1 -0
  12. package/dist/{HardwareBreakpoint-OcJqNFVc.mjs → HardwareBreakpoint-BUfPdp0f.mjs} +1 -1
  13. package/dist/{HeapAnalyzer-CqAxZzeS.mjs → HeapAnalyzer-B_aqY8oj.mjs} +1 -1
  14. package/dist/MCPServer.search.handlers.domain-BbS-6LnX.mjs +1 -0
  15. package/dist/MemoryController-X1XNSn1n.mjs +2 -0
  16. package/dist/{MemoryScanSession-CaxAjZJf.mjs → MemoryScanSession-DG_F-PjE.mjs} +1 -1
  17. package/dist/{MemoryScanner-BLYnMJy6.mjs → MemoryScanner-g1_L1ub5.mjs} +1 -1
  18. package/dist/{NativeMemoryManager.impl-CI554XbY.mjs → NativeMemoryManager.impl-DniBe2wf.mjs} +1 -1
  19. package/dist/{NativeMemoryManager.utils-DM4NC3FE.mjs → NativeMemoryManager.utils-BHy1P_jM.mjs} +1 -1
  20. package/dist/NetworkMonitor-B_-au6aV.mjs +185 -0
  21. package/dist/{PEAnalyzer-DJyaJTQJ.mjs → PEAnalyzer-yWQaGrcx.mjs} +1 -1
  22. package/dist/PageController-Dfsm1_o7.mjs +1 -0
  23. package/dist/{PointerChainEngine-5nF9eNlu.mjs → PointerChainEngine-BhCUkmxY.mjs} +1 -1
  24. package/dist/ProcessRegistry-C-bN48oR.mjs +1 -0
  25. package/dist/{ResponseBuilder-B2lu4KEl.mjs → ResponseBuilder-BfWP-uaT.mjs} +1 -1
  26. package/dist/RingBuffer-Dm54ELKT.mjs +1 -0
  27. package/dist/{ScriptManager-fgqiALgj.mjs → ScriptManager-LWGPTdvD.mjs} +1 -1
  28. package/dist/ServerRuntimeState-D2bWHqEE.mjs +1 -0
  29. package/dist/{Speedhack-l6s8L2Qw.mjs → Speedhack-yseDPSZ9.mjs} +1 -1
  30. package/dist/{StructureAnalyzer-A-WamfYE.mjs → StructureAnalyzer-C5lpuZkg.mjs} +1 -1
  31. package/dist/ToolCatalog-CYdD9F5f.mjs +1 -0
  32. package/dist/ToolProbe-C7ZU2x7M.mjs +1 -0
  33. package/dist/ToolRegistry-C5oB8KP8.mjs +1 -0
  34. package/dist/{ToolRouter.policy-CFHoN_Lw.mjs → ToolRouter.policy-CfhJczkt.mjs} +2 -2
  35. package/dist/{TraceRecorder-Dd8jLXpi.mjs → TraceRecorder-BiJWBXHX.mjs} +1 -1
  36. package/dist/{Win32Debug-CQteFL4F.mjs → Win32Debug-CYrIQBvr.mjs} +1 -1
  37. package/dist/{WorkflowEngine-CxEp2WXH.mjs → WorkflowEngine-D876meOO.mjs} +1 -1
  38. package/dist/analysis-D4swdMvq.mjs +6 -0
  39. package/dist/{antidebug-BOTZH6-0.mjs → antidebug-7L3ygj_9.mjs} +4 -4
  40. package/dist/apk-packer-BqXcInnX.mjs +1 -0
  41. package/dist/{artifactRetention-NBdncOEW.mjs → artifactRetention-BCPQASm7.mjs} +1 -1
  42. package/dist/{artifacts-B5xQuEa_.mjs → artifacts-CkodUM4j.mjs} +1 -1
  43. package/dist/betterSqlite3-Brtq-SIQ.mjs +1 -0
  44. package/dist/{binary-instrument-Cf9qqLlM.mjs → binary-instrument-DU7V6TUM.mjs} +1 -1
  45. package/dist/binary-secrets-PdMVoyt0.mjs +1 -0
  46. package/dist/{boringssl-inspector-BST5vtKx.mjs → boringssl-inspector-BBaJwwkU.mjs} +1 -1
  47. package/dist/browser-Qqco2rOT.mjs +11 -0
  48. package/dist/collector-Bpl6qy2L.mjs +1 -0
  49. package/dist/constants-BYj8Xek8.mjs +1 -0
  50. package/dist/{coordination-BbijHEHH.mjs → coordination-CWXW1o8K.mjs} +1 -1
  51. package/dist/dart-inspector-7AkPeZ_Q.mjs +0 -0
  52. package/dist/{debugger-CRJq_krh.mjs → debugger-DyALjYMk.mjs} +1 -1
  53. package/dist/{definitions-DZ8uKusP.mjs → definitions-BWxBke3r.mjs} +1 -1
  54. package/dist/{definitions-CYFbewnd.mjs → definitions-BYwATKc-.mjs} +1 -1
  55. package/dist/{definitions-DJklW2sS.mjs → definitions-B_83XfNQ.mjs} +1 -1
  56. package/dist/definitions-Bf3H1EwV.mjs +1 -0
  57. package/dist/{definitions-BGobEDQa.mjs → definitions-BftdXgXI.mjs} +1 -1
  58. package/dist/definitions-Bio5XJYy.mjs +1 -0
  59. package/dist/definitions-C3qNgSn1.mjs +1 -0
  60. package/dist/{definitions-NoVp_9Pm.mjs → definitions-CB6vmOer.mjs} +1 -1
  61. package/dist/{definitions-CoQFbggH.mjs → definitions-CMZRSy3k.mjs} +1 -1
  62. package/dist/{definitions-DI9YXsJk.mjs → definitions-CQd7yCQH.mjs} +1 -1
  63. package/dist/{definitions-CIO9O-Sw.mjs → definitions-CT8ln6GQ.mjs} +1 -1
  64. package/dist/{definitions-BGwNSkVm.mjs → definitions-Cenu6mxo.mjs} +1 -1
  65. package/dist/definitions-D4g-MS10.mjs +1 -0
  66. package/dist/{definitions-CuJRsJ6N.mjs → definitions-D5wl_8HN.mjs} +1 -1
  67. package/dist/{definitions-jXPaVy4P.mjs → definitions-DAQm1Xar.mjs} +1 -1
  68. package/dist/definitions-DP1vgxEY.mjs +1 -0
  69. package/dist/{definitions-Dds_zrWx.mjs → definitions-DxFNRQNK2.mjs} +1 -1
  70. package/dist/{definitions-DtE0XLrT.mjs → definitions-Ibci7e_L.mjs} +1 -1
  71. package/dist/{definitions-CCP9gphV.mjs → definitions-OeLvmlQy.mjs} +1 -1
  72. package/dist/{definitions-BbxOUiP-.mjs → definitions-RZYGD_Ey.mjs} +1 -1
  73. package/dist/definitions-Tls8c0A0.mjs +1 -0
  74. package/dist/{definitions-LaYTuwQd.mjs → definitions-bybDvnG0.mjs} +1 -1
  75. package/dist/{definitions-Dgrg7f3D.mjs → definitions-l7TjdE6V.mjs} +1 -1
  76. package/dist/{encoding-DGcr6Aj_.mjs → encoding-ycOaz8Vr.mjs} +1 -1
  77. package/dist/{ensure-browser-core-Buls24LQ.mjs → ensure-browser-core-DxWC-NTp.mjs} +1 -1
  78. package/dist/{factory-Cx_1LorX.mjs → factory-CKr4fAE1.mjs} +1 -1
  79. package/dist/{graphql-HLf3MS8H.mjs → graphql-B2TiPEow.mjs} +4 -4
  80. package/dist/{handlers-D49r1-1P.mjs → handlers-8zN_vBIz.mjs} +1 -1
  81. package/dist/handlers-B62K4FTc.mjs +1 -0
  82. package/dist/{handlers-BZoPla6E.mjs → handlers-BpDlVVVU.mjs} +1 -1
  83. package/dist/{handlers-DmQzIc44.mjs → handlers-CMJK7m1c.mjs} +1 -1
  84. package/dist/{handlers-BLMa4X7l.mjs → handlers-D2ZOul9p.mjs} +2 -2
  85. package/dist/{handlers-DW5AbYs5.mjs → handlers-D5E40ssn.mjs} +3 -3
  86. package/dist/{handlers-BP12ZsWc.mjs → handlers-DGbdQAgD.mjs} +2 -2
  87. package/dist/handlers-DHO3rjsW.mjs +1 -0
  88. package/dist/{handlers-DCE45Ww8.mjs → handlers-FJ80VzUI.mjs} +1 -1
  89. package/dist/handlers-VHWrxbM_.mjs +1 -0
  90. package/dist/{handlers-BggKiVx9.mjs → handlers-l8QIKqBj.mjs} +1 -1
  91. package/dist/{handlers-DnJRGp7t.mjs → handlers-mPFiNPe8.mjs} +1 -1
  92. package/dist/{handlers-pVNpaw4A.mjs → handlers-yo_xYzT8.mjs} +1 -1
  93. package/dist/handlers.impl-D9Hh8Bgl.mjs +1 -0
  94. package/dist/{hooks-DDKppogd.mjs → hooks-D4XLfgtV.mjs} +1 -1
  95. package/dist/index.mjs +11 -15
  96. package/dist/jadx-search-B_Yse0Zh.mjs +5 -0
  97. package/dist/maintenance-BUpIukhg.mjs +1 -0
  98. package/dist/{manifest-yu2xiQqe.mjs → manifest-0Jpt_AQa.mjs} +1 -1
  99. package/dist/{manifest-DMJlcsTR.mjs → manifest-B3fZbSWR.mjs} +1 -1
  100. package/dist/{manifest-De-6Wf2R.mjs → manifest-B7NB2rh2.mjs} +1 -1
  101. package/dist/manifest-BDi4nbH1.mjs +1 -0
  102. package/dist/{manifest-ais9Afrw.mjs → manifest-BLDfkE7n.mjs} +1 -1
  103. package/dist/manifest-BcXbB4gf.mjs +1 -0
  104. package/dist/{manifest-DsVh7Y4U.mjs → manifest-Bdnc_vrc.mjs} +1 -1
  105. package/dist/manifest-BuYKgCnp.mjs +1 -0
  106. package/dist/{manifest-Cx2IVMUY.mjs → manifest-CBfNnGPV.mjs} +1 -1
  107. package/dist/{manifest-DC-SMF6b.mjs → manifest-CPS1Xv69.mjs} +1 -1
  108. package/dist/{manifest-CGq4NpqH2.mjs → manifest-CQH9FhwI.mjs} +1 -1
  109. package/dist/{manifest-CRIJq4Hs.mjs → manifest-CRryuZF4.mjs} +1 -1
  110. package/dist/manifest-CctIumog.mjs +1 -0
  111. package/dist/manifest-CvTe5ZGV2.mjs +1 -0
  112. package/dist/{manifest-H-EpAyZQ.mjs → manifest-D-5GH0DV.mjs} +1 -1
  113. package/dist/{manifest-CtPmHAdn.mjs → manifest-D3Ssf3IC.mjs} +1 -1
  114. package/dist/{manifest-BeP_zJGb2.mjs → manifest-D5ck3NvC.mjs} +1 -1
  115. package/dist/{manifest-CeQmtQOY.mjs → manifest-D9jUUJAu.mjs} +1 -1
  116. package/dist/{manifest-C7qV1z7F.mjs → manifest-DCx6w2XV.mjs} +1 -1
  117. package/dist/{manifest-CFn0359q2.mjs → manifest-DG19q-Ld.mjs} +1 -1
  118. package/dist/{manifest-CJMGt7Qy.mjs → manifest-DLMlD0Zc.mjs} +1 -1
  119. package/dist/{manifest-CDeUZGUZ.mjs → manifest-DYpn8w_h.mjs} +1 -1
  120. package/dist/manifest-DYzWI8Xs.mjs +1 -0
  121. package/dist/{manifest-DKUorv5M.mjs → manifest-D_obs5F4.mjs} +1 -1
  122. package/dist/{manifest-D610kxZr.mjs → manifest-DujQqEQR.mjs} +2 -2
  123. package/dist/manifest-DwL2ik8P.mjs +1 -0
  124. package/dist/manifest-ItF5P8A12.mjs +1 -0
  125. package/dist/{manifest-tmb54wmA.mjs → manifest-KZphqIyX.mjs} +1 -1
  126. package/dist/{manifest-BPuE6oH2.mjs → manifest-LG42zPLY2.mjs} +1 -1
  127. package/dist/{manifest-D44TaRJU.mjs → manifest-LLdI5m4T.mjs} +1 -1
  128. package/dist/{manifest-Dgh0uDW-.mjs → manifest-QYbQXJn0.mjs} +1 -1
  129. package/dist/{manifest-BFGxlDRh.mjs → manifest-RcpX_MyZ.mjs} +2 -2
  130. package/dist/{manifest-CDiCtaQT.mjs → manifest-YgVd8Sgz.mjs} +1 -1
  131. package/dist/{manifest-D16xPXro.mjs → manifest-Zy7Odg5J.mjs} +1 -1
  132. package/dist/manifest-ff1H7Pdp.mjs +1 -0
  133. package/dist/{manifest-C_hEIjSx.mjs → manifest-iuhF6pTL2.mjs} +1 -1
  134. package/dist/{manifest-DWUUWBz0.mjs → manifest-nXHmtMSp2.mjs} +1 -1
  135. package/dist/{manifest-C1nZkTkO.mjs → manifest-xWfu6iLo.mjs} +1 -1
  136. package/dist/{manifest-C0g67k6U.mjs → manifest-yC16OhL2.mjs} +1 -1
  137. package/dist/manifest-ztWJoXy4.mjs +1 -0
  138. package/dist/modules-BPBcSaM-.mjs +333 -0
  139. package/dist/{mojo-ipc-VGlv3Qyp.mjs → mojo-ipc-BhwsdVUW.mjs} +1 -1
  140. package/dist/native/scripts/linux/enum-windows.sh +12 -12
  141. package/dist/native/scripts/macos/enum-windows.applescript +22 -22
  142. package/dist/native-j8l473zn.mjs +961 -0
  143. package/dist/network-T0VRwNPd.mjs +7 -0
  144. package/dist/{outputPaths-BonGThuc.mjs → outputPaths-B4Ic4RZh.mjs} +2 -2
  145. package/dist/platform-CzaQtISh.mjs +93 -0
  146. package/dist/process-CWhsCWrf.mjs +2 -0
  147. package/dist/proxy-DZFlDsG3.mjs +2 -0
  148. package/dist/{registry-DUHIPE-v.mjs → registry-DH4sc1dt.mjs} +1 -1
  149. package/dist/renderer-pid-9tJnZ_9N.mjs +1 -0
  150. package/dist/{search-defaults-D2bY-rzH.mjs → search-defaults-lYBVn_3L.mjs} +1 -1
  151. package/dist/server/plugin-api.d.mts +19 -36
  152. package/dist/server/plugin-api.mjs +1 -1
  153. package/dist/{shared-state-board-Cyg-xh_k.mjs → shared-state-board-BSjXLUV1.mjs} +1 -1
  154. package/dist/{sourcemap-D6Q1UuAp.mjs → sourcemap-Dh3Ai_ur.mjs} +1 -1
  155. package/dist/streaming-BcJ0B6ao.mjs +1 -0
  156. package/dist/transform-DOxzeWPB.mjs +103 -0
  157. package/dist/wasm-CZ_HTfKR.mjs +174 -0
  158. package/dist/{webcrack-CsLLJIs9.mjs → webcrack-C1iYG_EX.mjs} +3 -3
  159. package/dist/{workflow-CYIXtrWD.mjs → workflow-BdwQmARn.mjs} +4 -4
  160. package/package.json +16 -15
  161. package/src/native/scripts/linux/enum-windows.sh +12 -12
  162. package/src/native/scripts/macos/enum-windows.applescript +22 -22
  163. package/dist/ConsoleMonitor-Dkqc0HNi.mjs +0 -490
  164. package/dist/DOMInspector-BYY_EJ0C.mjs +0 -95
  165. package/dist/DetailedDataManager-BniBJlVv.mjs +0 -1
  166. package/dist/ExtensionManager-erMpqcLk.mjs +0 -1
  167. package/dist/MCPServer.search.handlers.domain-DVbWL1bT.mjs +0 -1
  168. package/dist/MemoryController-BaqstM5w.mjs +0 -2
  169. package/dist/PageController-D9jVkH0i.mjs +0 -1
  170. package/dist/ProcessRegistry-Hf12LlR9.mjs +0 -1
  171. package/dist/ToolCatalog-D_IKl1Hu.mjs +0 -1
  172. package/dist/ToolProbe-xsfALmN3.mjs +0 -1
  173. package/dist/ToolRegistry-B0Zs-phN.mjs +0 -1
  174. package/dist/analysis-BuR-NgX8.mjs +0 -5
  175. package/dist/betterSqlite3-CGaxz4AX.mjs +0 -1
  176. package/dist/browser-C4Le3xqA.mjs +0 -11
  177. package/dist/collector-CKO8RPK8.mjs +0 -1
  178. package/dist/constants-Cp6hBrrx.mjs +0 -1
  179. package/dist/definitions-CdWEuIkI.mjs +0 -1
  180. package/dist/definitions-OvGsfxdt.mjs +0 -1
  181. package/dist/handlers-D3iev8g1.mjs +0 -1
  182. package/dist/handlers-De5u62Ga2.mjs +0 -1
  183. package/dist/handlers-S9Ws0IGy.mjs +0 -2
  184. package/dist/handlers.impl-CD2_kOcC.mjs +0 -1
  185. package/dist/maintenance-CutEO84j.mjs +0 -1
  186. package/dist/manifest-BXry5N09.mjs +0 -1
  187. package/dist/manifest-Cq0j7GZt.mjs +0 -1
  188. package/dist/manifest-DD3rtxvV.mjs +0 -1
  189. package/dist/manifest-Dm0o3i2U.mjs +0 -1
  190. package/dist/manifest-DtEFSRaq.mjs +0 -1
  191. package/dist/manifest-zrbrpKCC.mjs +0 -1
  192. package/dist/modules-p-PUNv9r.mjs +0 -332
  193. package/dist/network-BjZ1Y-GB.mjs +0 -7
  194. package/dist/platform-C446Lf97.mjs +0 -93
  195. package/dist/process-C9f2A5zk.mjs +0 -962
  196. package/dist/proxy-CvRepxgV.mjs +0 -1
  197. package/dist/streaming-CTX58tbb.mjs +0 -1
  198. package/dist/transform-Cv9P2vVD.mjs +0 -103
  199. package/dist/wasm-DaJa8J0V.mjs +0 -174
  200. /package/dist/{CacheAdapters-CdAxBmVW.mjs → CacheAdapters-CsNtQIR8.mjs} +0 -0
  201. /package/dist/{DarwinAPI-DC4HGGLl.mjs → DarwinAPI-ZfQdpLNI.mjs} +0 -0
  202. /package/dist/{EventBus-DgciURGg.mjs → EventBus-DL8iLA09.mjs} +0 -0
  203. /package/dist/{EvidenceGraphBridge-BIfgB7HP.mjs → EvidenceGraphBridge-BtbwXsLC.mjs} +0 -0
  204. /package/dist/{FingerprintManager-N7BZqjxP.mjs → FingerprintManager-DT0EAUEo.mjs} +0 -0
  205. /package/dist/{HookGeneratorBuilders.core.generators.storage-Bf1fbrNK.mjs → HookGeneratorBuilders.core.generators.storage-DzD6dIJd.mjs} +0 -0
  206. /package/dist/{InstrumentationSession-DxXs0sCp.mjs → InstrumentationSession-D_G1ZPyd.mjs} +0 -0
  207. /package/dist/{PrerequisiteError-Bl3dK8XA.mjs → PrerequisiteError-BjCQA-gK.mjs} +0 -0
  208. /package/dist/{ReverseEvidenceGraph-B931HeoW.mjs → ReverseEvidenceGraph-BhSYYdiI.mjs} +0 -0
  209. /package/dist/{StealthVerifier-Dhbj4B4P.mjs → StealthVerifier-BmcxfwSF.mjs} +0 -0
  210. /package/dist/{VersionDetector-DMoUWyNm.mjs → VersionDetector-CHT36Az0.mjs} +0 -0
  211. /package/dist/{Win32API-Bhi5xFBe.mjs → Win32API-eUCF57l_.mjs} +0 -0
  212. /package/dist/{authorization-schema-B40obG1A.mjs → authorization-schema-BOFwSXUN.mjs} +0 -0
  213. /package/dist/{bind-helpers-BlAOQrFQ.mjs → bind-helpers-m2U8glkF.mjs} +0 -0
  214. /package/dist/{capabilities-DbYCv-HF.mjs → capabilities-CyXuKUl1.mjs} +0 -0
  215. /package/dist/{concurrency-CcK46d0h.mjs → concurrency-DCr8WQ2M.mjs} +0 -0
  216. /package/dist/{evidence-graph-bridge-B0yhGPcs.mjs → evidence-graph-bridge-CV_UdYqj.mjs} +0 -0
  217. /package/dist/{flat-target-session-CO5g78k3.mjs → flat-target-session-DvcQX7J5.mjs} +0 -0
  218. /package/dist/{formatAddress-C7j2fDlM.mjs → formatAddress-vLA_hOJt.mjs} +0 -0
  219. /package/dist/{handlers-Dv_runVv.mjs → handlers-0yKLRIfo.mjs} +0 -0
  220. /package/dist/{matchesWildcardPattern-BGqLSmEs.mjs → matchesWildcardPattern-BAG6LvX5.mjs} +0 -0
  221. /package/dist/{parse-args-Cuk7-xUt.mjs → parse-args-Bw413PlW.mjs} +0 -0
  222. /package/dist/{playwright-cdp-fallback-BwVR-_T3.mjs → playwright-cdp-fallback-DqFdx9-s.mjs} +0 -0
  223. /package/dist/{ssrf-policy-T96MR3r6.mjs → ssrf-policy-CsIJGkpd.mjs} +0 -0
  224. /package/dist/{tool-builder-CI9914Tf.mjs → tool-builder-qif8M9-K.mjs} +0 -0
  225. /package/dist/{types-DtThH00r.mjs → types-D9EiE5o9.mjs} +0 -0
  226. /package/dist/{types-CuyefmGT.mjs → types-Fz69RzbZ.mjs} +0 -0
@@ -1,5 +1,5 @@
1
- import{n as e}from"./response-C7rKQst4.mjs";import{a as t,c as n,i as r,l as i,n as a,o,r as s,s as c}from"./boringssl-inspector-BST5vtKx.mjs";import{a as l,n as u,o as d,r as f,t as p}from"./parse-args-Cuk7-xUt.mjs";import{a as m,s as h}from"./ssrf-policy-T96MR3r6.mjs";import{X509Certificate as g,createHash as _,randomBytes as v,randomUUID as y}from"node:crypto";import{readFile as b}from"node:fs/promises";import{Socket as x,createServer as S,isIP as C}from"node:net";import{createSocket as w}from"node:dgram";import{checkServerIdentity as T,connect as E}from"node:tls";const D=new Set([`TLSv1`,`TLSv1.1`,`TLSv1.2`,`TLSv1.3`]);function O(e){return e instanceof Error?e.message:String(e)}function k(e){return e.replace(/\s+/g,``).toUpperCase()}function A(e){return e.length>0&&e.length%2==0&&/^[0-9A-F]+$/i.test(e)}function j(e){return h(e)&&!m(e)?{ok:!1,error:`Blocked: target host "${e}" resolves to a private/internal address. SSRF protection applies.`}:null}function M(e){return typeof e==`string`&&e.length>0?e:null}function N(e){return typeof e==`string`&&e.length>0?e:null}function P(e,t){let n={...e};return Reflect.set(n,`rejectUnauthorized`,!t),n}async function F(e){let t=l(e,`caPem`)??null,n=l(e,`caPath`)??null;if(t&&n)return{ok:!1,error:`caPem and caPath are mutually exclusive`};if(t)return{ok:!0,ca:t,source:`inline`,path:null,bytes:Buffer.byteLength(t)};if(n)try{let e=await b(n,`utf8`);return{ok:!0,ca:e,source:`path`,path:n,bytes:Buffer.byteLength(e)}}catch(e){return{ok:!1,error:`Failed to read caPath "${n}": ${O(e)}`}}return{ok:!0,ca:void 0,source:null,path:null,bytes:null}}function I(e){return typeof e==`object`&&!!e&&Object.keys(e).length>0}function L(e){return I(e)}function R(e,t){let n=Buffer.isBuffer(e.raw)?e.raw:null,r=n?new g(n):null,i=r?.subject??null,a=r?.issuer??null;return{depth:t,subject:i,issuer:a,subjectAltName:r?.subjectAltName??e.subjectaltname??null,serialNumber:r?.serialNumber??e.serialNumber??null,validFrom:r?.validFrom??e.valid_from??null,validTo:r?.validTo??e.valid_to??null,fingerprint256:r?.fingerprint256??e.fingerprint256??null,fingerprint512:r?.fingerprint512??e.fingerprint512??null,rawLength:n?.length??null,isCA:r?.ca??e.ca??null,selfIssued:i&&a?i===a:null}}function z(e){if(!e)return[];let t=[],n=new Set,r=e,i=0;for(;r&&L(r);){let e=R(r,i),a=e.fingerprint256??`${e.subject??`unknown-subject`}:${e.serialNumber??`unknown-serial`}:${i}`;if(n.has(a)||(n.add(a),t.push(e),!(`issuerCertificate`in r)))break;let o=r.issuerCertificate;if(!o||o===r||!L(o))break;r=o,i+=1}return t}function B(e){let t=_(`sha256`).update(e).digest(`hex`).toUpperCase();try{let n=new g(e);return{subject:n.subject||void 0,issuer:n.issuer||void 0,serialNumber:n.serialNumber||void 0,validFrom:n.validFrom||void 0,validTo:n.validTo||void 0,sha256:t,length:e.length}}catch{return{sha256:t,length:e.length}}}function V(e){let t=Buffer.from(k(e),`hex`),n=[],r=0;for(;r<t.length-4;)if(t[r]===48){let e=B(t.subarray(r));n.push({sha256:e.sha256,length:e.length}),r+=e.length}else r+=1;return n.length===0&&t.length>0&&n.push({sha256:_(`sha256`).update(t).digest(`hex`).toUpperCase(),length:t.length}),n}function H(e){return`${e}_${y()}`}function U(e){return{localAddress:e.localAddress??null,localPort:e.localPort??null,remoteAddress:e.remoteAddress??null,remotePort:e.remotePort??null}}function W(e){return{bufferedBytes:e.buffer.length,remoteEnded:e.ended,socketClosed:e.closed,error:e.error}}function G(e){for(let t of e.waiters)t();e.waiters.clear()}function K(e){e.socket.on(`data`,t=>{e.buffer=Buffer.concat([e.buffer,t]),G(e)}),e.socket.on(`end`,()=>{e.ended=!0,G(e)}),e.socket.on(`close`,()=>{e.closed=!0,G(e)}),e.socket.on(`error`,t=>{e.error=t.message,G(e)})}function ee(e,t){return new Promise(n=>{let r=()=>{clearTimeout(i),e.waiters.delete(r),n(!0)},i=setTimeout(()=>{e.waiters.delete(r),n(!1)},t);e.waiters.add(r)})}function te(e,t,n,r){let i=t?t.toString(`hex`).toUpperCase():null;if(t){let r=e.buffer.indexOf(t);if(r>=0){let a=r+t.length,o=n?e.buffer.subarray(0,a):e.buffer.subarray(0,r);return e.buffer=e.buffer.subarray(a),{data:o,matchedDelimiter:!0,stopReason:`delimiter`,delimiterHex:i}}}if(typeof r==`number`&&e.buffer.length>=r){let t=e.buffer.subarray(0,r);return e.buffer=e.buffer.subarray(r),{data:t,matchedDelimiter:!1,stopReason:`maxBytes`,delimiterHex:i}}if((e.error||e.ended||e.closed)&&e.buffer.length>0){let t=e.buffer;return e.buffer=Buffer.alloc(0),{data:t,matchedDelimiter:!1,stopReason:e.error?`error`:`closed`,delimiterHex:i}}return null}function q(e){return{bufferedBytes:e.parserBuffer.length,queuedFrames:e.frames.length,remoteEnded:e.ended,socketClosed:e.closed,closeSent:e.closeSent,closeReceived:e.closeReceived,error:e.error}}function J(e){return!e||e.trim().length===0?`/`:e.startsWith(`/`)?e:`/${e}`}function ne(e){return{1:`text`,2:`binary`,8:`close`,9:`ping`,10:`pong`}[e]??null}function re(e){return _(`sha1`).update(`${e}258EAFA5-E914-47DA-95CA-C5AB0DC85B11`,`utf8`).digest(`base64`)}function Y(e,t,n,r){let i={text:1,binary:2,close:8,ping:9,pong:10},a=t;if(e===`close`)if(n!=null){let e=r?Buffer.from(r,`utf8`):Buffer.alloc(0);a=Buffer.alloc(2+e.length),a.writeUInt16BE(n,0),e.copy(a,2)}else r&&(a=Buffer.from(r,`utf8`));let o=v(4),s=a.length,c;s<126?(c=Buffer.alloc(2),c[1]=128|s):s<=65535?(c=Buffer.alloc(4),c[1]=254,c.writeUInt16BE(s,2)):(c=Buffer.alloc(10),c[1]=255,c.writeBigUInt64BE(BigInt(s),2)),c[0]=128|i[e];let l=Buffer.alloc(s);for(let e=0;e<s;e+=1)l[e]=a[e]^o[e%4];return Buffer.concat([c,o,l])}function ie(e){if(e.length<2)return null;let t=e[0],n=e[1],r=(t&128)!=0,i=t&15,a=(n&128)!=0,o=n&127,s=2;if(o===126){if(e.length<s+2)return null;o=e.readUInt16BE(s),s+=2}else if(o===127){if(e.length<s+8)return null;let t=e.readBigUInt64BE(s);if(t>BigInt(2**53-1))throw Error(`WebSocket frame payload length exceeds supported limits`);o=Number(t),s+=8}let c=a?e.subarray(s,s+4):null;if(a){if(e.length<s+4)return null;s+=4}if(e.length<s+o)return null;let l=e.subarray(s,s+o),u=Buffer.alloc(l.length);if(a&&c)for(let e=0;e<l.length;e+=1)u[e]=l[e]^c[e%4];else l.copy(u);let d=ne(i);if(!d)throw Error(`Unsupported WebSocket opcode 0x${i.toString(16)}`);let f=null,p=null;return d===`close`&&u.length>=2&&(f=u.readUInt16BE(0),p=u.subarray(2).toString(`utf8`)),{frame:{type:d,fin:r,opcode:i,masked:a,data:u,closeCode:f,closeReason:p,receivedAt:Date.now()},bytesConsumed:s+o}}function X(e){for(let t of e.waiters)t();e.waiters.clear()}function ae(e,t){return new Promise(n=>{let r=()=>{clearTimeout(i),e.waiters.delete(r),n(!0)},i=setTimeout(()=>{e.waiters.delete(r),n(!1)},t);e.waiters.add(r)})}const oe={"3:1":`TLS 1.0`,"3:2":`TLS 1.1`,"3:3":`TLS 1.2`,"3:4":`TLS 1.3`},se={20:`change_cipher_spec`,21:`alert`,22:`handshake`,23:`application_data`,24:`heartbeat`},ce={156:`TLS_RSA_WITH_AES_128_GCM_SHA256`,157:`TLS_RSA_WITH_AES_256_GCM_SHA384`,52392:`TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256`,52393:`TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384`,4865:`TLS_AES_128_GCM_SHA256`,4866:`TLS_AES_256_GCM_SHA384`,4867:`TLS_CHACHA20_POLY1305_SHA256`,4868:`TLS_AES_128_CCM_SHA256`,4869:`TLS_AES_128_CCM_8_SHA256`,49195:`TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256`,49196:`TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384`,49199:`TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256`,49200:`TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384`},le={0:`server_name`,1:`max_fragment_length`,5:`status_request`,10:`supported_groups`,13:`signature_algorithms`,16:`application_layer_protocol_negotiation`,18:`signed_certificate_timestamp`,23:`record_size_limit`,27:`compress_certificate`,35:`session_ticket`,43:`supported_versions`,44:`cookie`,45:`psk_key_exchange_modes`,49:`post_handshake_auth`,51:`key_share`};function Z(e,t){return oe[`${e}:${t}`]??`0x${e.toString(16).padStart(2,`0`)}${t.toString(16).padStart(2,`0`)}`}function Q(e){return se[e]??`unknown`}function ue(e){let t={cipherSuites:[],extensions:[]},n=e[0]!==void 0&&e[0]<25?4:0;if(e.length<n+38)return t;let r=n+34,i=e[r]??0,a=r+1+i;if(a+2>e.length)return t;let o=e.readUInt16BE(a);a+=2;let s=a+o;for(;a+2<=s;){let n=e.readUInt16BE(a);t.cipherSuites.push(ce[n]??`0x${n.toString(16).padStart(4,`0`)}`),a+=2}if(a=s+1,a<e.length){let t=e[a];t!==void 0&&(a+=1+t)}if(a+2<=e.length){let n=e.readUInt16BE(a);a+=2;let r=a+n;for(;a+4<=r;){let n=e.readUInt16BE(a),i=e.readUInt16BE(a+2);a+=4;let o=le[n]??`unknown(0x${n.toString(16)})`;if(t.extensions.push({type:n,name:o,length:i}),n===0&&a+2<=r){let n=a+2;if(n+3<=r&&e[n]===0){let i=e.readUInt16BE(n+1),a=n+3;a+i<=r&&(t.serverName=e.subarray(a,a+i).toString(`utf8`))}}a+=i}}return t}var de=class{keyLogExtractor;extensionInvoke;eventBus;tcpSessions=new Map;tlsSessions=new Map;websocketSessions=new Map;constructor(e=new a){this.keyLogExtractor=e}setExtensionInvoke(e){this.extensionInvoke=e}setEventBus(e){this.eventBus=e}getTcpSession(e){return this.tcpSessions.get(e)??null}getTlsSession(e){return this.tlsSessions.get(e)??null}getWebSocketSession(e){return this.websocketSessions.get(e)??null}parseWritePayload(e){let t=l(e,`dataHex`),n=l(e,`dataText`);if(!t&&!n)return{ok:!1,error:`dataHex or dataText is required`};if(t&&n)return{ok:!1,error:`dataHex and dataText are mutually exclusive`};if(t){let e=k(t);return A(e)?{ok:!0,data:Buffer.from(e,`hex`),inputEncoding:`hex`}:{ok:!1,error:`dataHex must be valid even-length hexadecimal data`}}return{ok:!0,data:Buffer.from(n??``,`utf8`),inputEncoding:`utf8`}}async writeBufferedSession(e,t){if(e.socket.destroyed||e.closed)return{ok:!1,error:`Session "${e.id}" is already closed`,sessionId:e.id,kind:e.kind,state:W(e)};let n=this.parseWritePayload(t);if(!n.ok)return{ok:!1,error:n.error,sessionId:e.id,kind:e.kind};let r=f(t,`timeoutMs`)??5e3;return!Number.isFinite(r)||r<=0?{ok:!1,error:`timeoutMs must be a positive number`}:new Promise(t=>{let i=!1,a=n=>{i||(i=!0,clearTimeout(o),e.socket.off(`error`,s),t(n))},o=setTimeout(()=>{a({ok:!1,error:`write timed out`,sessionId:e.id,kind:e.kind,state:W(e)})},r),s=t=>{a({ok:!1,error:t.message,sessionId:e.id,kind:e.kind,state:W(e)})};e.socket.once(`error`,s),e.socket.write(n.data,()=>{e.kind===`tcp`?this.eventBus?.emit(`tcp:session_written`,{sessionId:e.id,byteLength:n.data.length,timestamp:new Date().toISOString()}):this.eventBus?.emit(`tls:session_written`,{sessionId:e.id,byteLength:n.data.length,timestamp:new Date().toISOString()}),a({ok:!0,sessionId:e.id,kind:e.kind,inputEncoding:n.inputEncoding,bytesWritten:n.data.length,transport:U(e.socket),state:W(e)})})})}async readBufferedSessionUntil(e,t){let n=l(t,`delimiterHex`),r=l(t,`delimiterText`);if(n&&r)return{ok:!1,error:`delimiterHex and delimiterText are mutually exclusive`};let i=null;if(n){let e=k(n);if(!A(e))return{ok:!1,error:`delimiterHex must be valid even-length hexadecimal data`};i=Buffer.from(e,`hex`)}else r!==void 0&&(i=Buffer.from(r,`utf8`));if(i&&i.length===0)return{ok:!1,error:`delimiter must not be empty`};let a=p(t,`includeDelimiter`)??!0,o=f(t,`maxBytes`),s=o===void 0?void 0:Math.trunc(o);if(s!==void 0&&(!Number.isFinite(s)||s<=0))return{ok:!1,error:`maxBytes must be a positive integer when provided`};if(!i&&s===void 0)return{ok:!1,error:`delimiterHex, delimiterText, or maxBytes is required`};let c=f(t,`timeoutMs`)??5e3;if(!Number.isFinite(c)||c<=0)return{ok:!1,error:`timeoutMs must be a positive number`};if(e.activeRead)return{ok:!1,error:`Session "${e.id}" already has a pending read`,sessionId:e.id,kind:e.kind,state:W(e)};e.activeRead=!0;let u=Date.now();try{for(;;){let t=te(e,i,a,s);if(t)return e.kind===`tcp`?this.eventBus?.emit(`tcp:session_read`,{sessionId:e.id,byteLength:t.data.length,matched:t.matchedDelimiter,timestamp:new Date().toISOString()}):this.eventBus?.emit(`tls:session_read`,{sessionId:e.id,byteLength:t.data.length,matched:t.matchedDelimiter,timestamp:new Date().toISOString()}),{ok:!0,sessionId:e.id,kind:e.kind,bytesRead:t.data.length,matchedDelimiter:t.matchedDelimiter,stopReason:t.stopReason,delimiterHex:t.delimiterHex,dataHex:t.data.toString(`hex`).toUpperCase(),dataText:t.data.toString(`utf8`),elapsedMs:Date.now()-u,state:W(e)};if(e.error)return{ok:!1,error:e.error,sessionId:e.id,kind:e.kind,state:W(e)};if(e.ended||e.closed)return{ok:!1,error:`socket closed before the requested read condition was satisfied`,sessionId:e.id,kind:e.kind,state:W(e)};let n=c-(Date.now()-u);if(n<=0||!await ee(e,n))return{ok:!1,error:`read timed out`,sessionId:e.id,kind:e.kind,state:W(e)}}}finally{e.activeRead=!1}}async closeBufferedSession(e,t,n,r){let i=t.get(e);if(!i)return{ok:!1,error:`Unknown ${n} sessionId "${e}"`};let a=p(r,`force`)??!1,o=f(r,`timeoutMs`)??1e3;if(!Number.isFinite(o)||o<=0)return{ok:!1,error:`timeoutMs must be a positive number`};let s=i.buffer.length;return i.closed||i.socket.destroyed?(t.delete(e),{ok:!0,sessionId:e,kind:n,force:a,closed:!0,bufferedBytesDiscarded:s,state:W(i)}):new Promise(r=>{let c=!1,l=o=>{c||(c=!0,clearTimeout(f),i.socket.off(`close`,u),i.socket.off(`error`,d),t.delete(e),n===`tcp`?this.eventBus?.emit(`tcp:session_closed`,{sessionId:e,reason:i.error,timestamp:new Date().toISOString()}):this.eventBus?.emit(`tls:session_closed`,{sessionId:e,reason:i.error,timestamp:new Date().toISOString()}),r({ok:!0,sessionId:e,kind:n,force:a,closed:o,bufferedBytesDiscarded:s,state:W(i)}))},u=()=>l(!0),d=()=>l(i.socket.destroyed||i.closed),f=setTimeout(()=>{i.socket.destroy(),l(i.socket.destroyed||i.closed)},o);if(i.socket.once(`close`,u),i.socket.once(`error`,d),a){i.socket.destroy();return}i.socket.end()})}},fe=class extends de{async handleTlsKeylogEnable(e){return{enabled:!0,keyLogPath:await this.keyLogExtractor.enableKeyLog(),environmentVariable:`SSLKEYLOGFILE`}}async handleTlsKeylogDisable(e){let t=l(e,`path`)??null;return t?await this.keyLogExtractor.disableKeyLog():r(),{disabled:!0,previousPath:t??o()}}async handleTlsKeylogParse(e){let t=l(e,`path`)??null,n=this.keyLogExtractor.parseKeyLog(t??void 0),r=this.keyLogExtractor.summarizeKeyLog(t??void 0);return{path:t??this.keyLogExtractor.getKeyLogFilePath(),entries:n,summary:r}}async handleTlsDecryptPayload(e){let t=l(e,`encryptedHex`)??null,n=l(e,`keyHex`)??null,r=l(e,`nonceHex`)??null,i=l(e,`algorithm`)??`aes-256-gcm`,a=l(e,`authTagHex`)??null;if(!t||!n||!r)return{ok:!1,error:`encryptedHex, keyHex, and nonceHex are required`};let o=s(t,n,r,i,a??void 0);return{ok:!0,algorithm:i,decrypted:o,isFailed:o.startsWith(`DECRYPTION_FAILED:`)}}async handleTlsKeylogSummarize(e){let t=l(e,`content`)??null;return t?i(n(t)):(this.keyLogExtractor.parseKeyLog(),this.keyLogExtractor.summarizeKeyLog())}async handleTlsKeylogLookupSecret(e){let t=l(e,`clientRandom`)??null,n=l(e,`label`)??void 0;if(!t)return{ok:!1,error:`clientRandom is required`};let r=this.keyLogExtractor.lookupSecret(t);if(r)return{ok:!0,clientRandom:k(t),secret:r};let i=c(this.keyLogExtractor.parseKeyLog(),t,n);return{ok:i!==null,clientRandom:k(t),secret:i??null}}async handleTlsCertPinBypass(e){let t=l(e,`target`)??null;return t!==`android`&&t!==`ios`&&t!==`desktop`?{error:`target must be one of android, ios, or desktop`}:{bypassStrategy:{android:`hook-trust-manager`,ios:`replace-sec-trust-evaluation`,desktop:`patch-custom-verifier`}[t],affectedDomains:[`*`],instructions:{android:[`Inject a Frida script that overrides X509TrustManager checks.`,`Re-run the target flow after SSLKEYLOGFILE capture is enabled.`],ios:[`Hook SecTrustEvaluateWithError and return success for the target session.`,`Collect TLS keys after the app resumes the failing request.`],desktop:[`Patch the custom verifier callback or disable pin comparison in the client.`,`Capture a fresh handshake after the patched build starts.`]}[t]}}async handleParseHandshake(t){let n=l(t,`rawHex`)??null,r=t.decrypt===!0;if(!n)return e({success:!1,error:`rawHex is required`});let i=k(n);if(!/^(?:[0-9a-f]{2})+$/i.test(i))return e({success:!1,error:`Invalid hex payload`});let a=Buffer.from(i,`hex`);if(a.length<5)return e({success:!1,error:`TLS record is too short`});let o=a[0],s=a[1],c=a[2],u=a.readUInt16BE(3),d=a.subarray(5),f=o===22&&d.length>0&&d[0]===1?ue(d):void 0,p=r?(()=>{let e=this.keyLogExtractor.decryptPayload(i,this.keyLogExtractor.parseKeyLog());return e?e.subarray(0,16).toString(`hex`).toUpperCase():null})():void 0;return e({success:!0,record:{contentType:o,contentTypeName:Q(o),version:Z(s,c),declaredLength:u,actualLength:d.length},handshake:{version:Z(s,c),contentType:Q(o),...f?{type:`client_hello`,serverName:f.serverName,cipherSuites:f.cipherSuites,extensions:f.extensions}:{cipherSuite:[],extensions:[]}},sni:f?.serverName?{serverName:f.serverName}:void 0,...p===void 0?{}:{decryptedPreviewHex:p}})}async handleKeyLogEnable(n){let r=l(n,`filePath`)??`/tmp/sslkeylog.log`;return t(r),this.eventBus?.emit(`tls:keylog_started`,{filePath:r,timestamp:new Date().toISOString()}),e({success:!0,filePath:r,currentFilePath:o()})}async handleCipherSuites(t){let n=l(t,`filter`)??null,r=[`TLS_AES_128_GCM_SHA256`,`TLS_AES_256_GCM_SHA384`,`TLS_CHACHA20_POLY1305_SHA256`,`TLS_AES_128_CCM_SHA256`,`TLS_AES_128_CCM_8_SHA256`,`TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256`,`TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384`,`TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256`,`TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384`,`TLS_RSA_WITH_AES_128_GCM_SHA256`,`TLS_RSA_WITH_AES_256_GCM_SHA384`],i=n?r.filter(e=>e.includes(n)):r;return e({success:!0,filter:n,total:i.length,suites:i})}async handleParseCertificate(t){let n=l(t,`rawHex`)??null;if(!n)return e({success:!1,error:`rawHex is required`});let r=V(n);return e({success:!0,certificateCount:r.length,fingerprints:r.map(e=>({sha256:e.sha256,length:e.length}))})}};const $=[`TLSv1`,`TLSv1.1`,`TLSv1.2`,`TLSv1.3`];var pe=class extends fe{async handleTlsProbeEndpoint(e){let t=l(e,`host`)?.trim()??null;if(!t)return{ok:!1,error:`host is required`};let n=f(e,`port`)??443;if(!Number.isInteger(n)||n<1||n>65535)return{ok:!1,error:`port must be an integer between 1 and 65535`};let r=f(e,`timeoutMs`)??5e3;if(!Number.isFinite(r)||r<=0)return{ok:!1,error:`timeoutMs must be a positive number`};let i=p(e,`allowInvalidCertificates`)??!1,a=p(e,`skipHostnameCheck`)??!1,o=l(e,`servername`)?.trim()??null,s=[...new Set(d(e,`alpnProtocols`).map(e=>e.trim()))].filter(e=>e.length>0),c,m;try{c=u(e,`minVersion`,D),m=u(e,`maxVersion`,D)}catch(e){return{ok:!1,error:O(e)}}if(c&&m&&$.indexOf(c)>$.indexOf(m))return{ok:!1,error:`minVersion must not be greater than maxVersion`};let h=j(t);if(h)return h;let g=await F(e);if(!g.ok)return{ok:!1,error:g.error};let _=o??t,v=o??(C(t)===0?t:void 0),y=Date.now();return new Promise(e=>{let o=!1,l=E(P({host:t,port:n,servername:v,...c?{minVersion:c}:{},...m?{maxVersion:m}:{},...s.length>0?{ALPNProtocols:s}:{},...g.ca?{ca:g.ca}:{}},i)),u=t=>{o||(o=!0,clearTimeout(d),l.removeAllListeners(),l.destroy(),e(t))},d=setTimeout(()=>{this.eventBus?.emit(`tls:probe_completed`,{host:t,port:n,success:!1,timestamp:new Date().toISOString()}),u({ok:!1,error:`TLS probe timed out`,target:{host:t,port:n,requestedServername:v??null,validationTarget:_},policy:{allowInvalidCertificates:i,skipHostnameCheck:a,timeoutMs:r,minVersion:c??null,maxVersion:m??null,alpnProtocols:s,customCa:{source:g.source,path:g.path,bytes:g.bytes}}})},r);l.once(`error`,e=>{this.eventBus?.emit(`tls:probe_completed`,{host:t,port:n,success:!1,timestamp:new Date().toISOString()}),u({ok:!1,error:e.message,errorCode:e.code??null,target:{host:t,port:n,requestedServername:v??null,validationTarget:_},policy:{allowInvalidCertificates:i,skipHostnameCheck:a,timeoutMs:r,minVersion:c??null,maxVersion:m??null,alpnProtocols:s,customCa:{source:g.source,path:g.path,bytes:g.bytes}}})}),l.once(`secureConnect`,()=>{let e=Date.now()-y,o=l.getPeerCertificate(!0),d=L(o),f=d?z(o):[],p=f[0]??null,h=a||!d?void 0:T(_,o),b={checked:!a,target:a?null:_,matched:a?null:h===void 0,error:!a&&!d?`Peer certificate was not presented by the server`:h?.message??null},x=[l.authorized?`Certificate chain validated against the active trust store.`:`Certificate chain validation failed: ${l.authorizationError??`unknown_authority`}`,a?`Hostname validation was skipped by request.`:b.matched?`Hostname validation passed.`:`Hostname validation failed: ${b.error??`unknown_error`}`,!l.authorized&&i?`Policy allowed the probe to continue despite certificate trust failure.`:null].filter(e=>!!e),S=l.getCipher();this.eventBus?.emit(`tls:probe_completed`,{host:t,port:n,success:!0,timestamp:new Date().toISOString()}),u({ok:!0,target:{host:t,port:n,requestedServername:v??null,validationTarget:_},policy:{allowInvalidCertificates:i,skipHostnameCheck:a,timeoutMs:r,minVersion:c??null,maxVersion:m??null,alpnProtocols:s,customCa:{source:g.source,path:g.path,bytes:g.bytes}},transport:{protocol:l.getProtocol()??null,alpnProtocol:N(l.alpnProtocol),cipher:{name:S.name,standardName:S.standardName,version:S.version},localAddress:l.localAddress??null,localPort:l.localPort??null,remoteAddress:l.remoteAddress??null,remotePort:l.remotePort??null,servernameSent:M(l.servername),sessionReused:l.isSessionReused()},authorization:{socketAuthorized:l.authorized,authorizationError:typeof l.authorizationError==`string`?l.authorizationError:l.authorizationError?.message??null,hostnameValidation:b,policyAllowed:(l.authorized||i)&&(a||b.matched===!0),reasons:x},certificates:{leaf:p,chain:f},timing:{handshakeMs:e}})})})}};const me=[`TLSv1`,`TLSv1.1`,`TLSv1.2`,`TLSv1.3`];var he=class extends pe{async handleTcpOpen(e){let t=l(e,`host`)??`127.0.0.1`,n=f(e,`port`);if(n===void 0||!Number.isInteger(n)||n<1||n>65535)return{ok:!1,error:`port must be an integer between 1 and 65535`};let r=f(e,`timeoutMs`)??5e3;if(!Number.isFinite(r)||r<=0)return{ok:!1,error:`timeoutMs must be a positive number`};let i=p(e,`noDelay`)??!0;return j(t)||new Promise(e=>{let a=!1,o=new x,s=t=>{a||(a=!0,clearTimeout(c),o.off(`connect`,u),o.off(`error`,l),e(t))},c=setTimeout(()=>{o.destroy(),s({ok:!1,error:`TCP connect timed out`,target:{host:t,port:n}})},r),l=e=>{s({ok:!1,error:e.message,target:{host:t,port:n}})},u=()=>{o.setNoDelay(i);let e=H(`tcp`),r={id:e,kind:`tcp`,socket:o,host:t,port:n,createdAt:Date.now(),buffer:Buffer.alloc(0),ended:!1,closed:!1,error:null,waiters:new Set,activeRead:!1};K(r),this.tcpSessions.set(e,r),this.eventBus?.emit(`tcp:session_opened`,{sessionId:e,host:t,port:n,timestamp:new Date().toISOString()}),s({ok:!0,sessionId:e,kind:`tcp`,target:{host:t,port:n},createdAt:new Date(r.createdAt).toISOString(),transport:U(o),state:W(r)})};o.once(`connect`,u),o.once(`error`,l),o.connect(n,t)})}async handleTcpWrite(e){let t=l(e,`sessionId`)?.trim()??null;if(!t)return{ok:!1,error:`sessionId is required`};let n=this.getTcpSession(t);return n?this.writeBufferedSession(n,e):{ok:!1,error:`Unknown tcp sessionId "${t}"`}}async handleTcpReadUntil(e){let t=l(e,`sessionId`)?.trim()??null;if(!t)return{ok:!1,error:`sessionId is required`};let n=this.getTcpSession(t);return n?this.readBufferedSessionUntil(n,e):{ok:!1,error:`Unknown tcp sessionId "${t}"`}}async handleTcpClose(e){let t=l(e,`sessionId`)?.trim()??null;return t?this.closeBufferedSession(t,this.tcpSessions,`tcp`,e):{ok:!1,error:`sessionId is required`}}async handleTlsOpen(e){let t=l(e,`host`)?.trim()??null;if(!t)return{ok:!1,error:`host is required`};let n=f(e,`port`)??443;if(!Number.isInteger(n)||n<1||n>65535)return{ok:!1,error:`port must be an integer between 1 and 65535`};let r=f(e,`timeoutMs`)??5e3;if(!Number.isFinite(r)||r<=0)return{ok:!1,error:`timeoutMs must be a positive number`};let i=p(e,`allowInvalidCertificates`)??!1,a=p(e,`skipHostnameCheck`)??!1,o=l(e,`servername`)?.trim()??null,s=[...new Set(d(e,`alpnProtocols`).map(e=>e.trim()))].filter(e=>e.length>0),c,m;try{c=u(e,`minVersion`,D),m=u(e,`maxVersion`,D)}catch(e){return{ok:!1,error:O(e)}}if(c&&m&&me.indexOf(c)>me.indexOf(m))return{ok:!1,error:`minVersion must not be greater than maxVersion`};let h=j(t);if(h)return h;let g=await F(e);if(!g.ok)return{ok:!1,error:g.error};let _={host:t,port:n,requestedServername:o??(C(t)===0?t:void 0)??null,validationTarget:o??t},v={allowInvalidCertificates:i,skipHostnameCheck:a,timeoutMs:r,minVersion:c??null,maxVersion:m??null,alpnProtocols:s,customCa:{source:g.source,path:g.path,bytes:g.bytes}},y=Date.now();return new Promise(e=>{let o=!1,l=E(P({host:t,port:n,servername:_.requestedServername??void 0,...c?{minVersion:c}:{},...m?{maxVersion:m}:{},...s.length>0?{ALPNProtocols:s}:{},...g.ca?{ca:g.ca}:{}},i)),u=t=>{o||(o=!0,clearTimeout(d),l.off(`error`,f),l.off(`secureConnect`,p),e(t))},d=setTimeout(()=>{l.destroy(),this.eventBus?.emit(`tls:probe_completed`,{host:t,port:n,success:!1,timestamp:new Date().toISOString()}),u({ok:!1,error:`TLS open timed out`,target:_,policy:v})},r),f=e=>{this.eventBus?.emit(`tls:probe_completed`,{host:t,port:n,success:!1,timestamp:new Date().toISOString()}),u({ok:!1,error:e.message,errorCode:e.code??null,target:_,policy:v})},p=()=>{let e=Date.now()-y,r=l.getPeerCertificate(!0),o=L(r),s=o?z(r):[],c=s[0]??null,d=a||!o?void 0:T(_.validationTarget,r),f={checked:!a,target:a?null:_.validationTarget,matched:a?null:d===void 0,error:!a&&!o?`Peer certificate was not presented by the server`:d?.message??null},p=[l.authorized?`Certificate chain validated against the active trust store.`:`Certificate chain validation failed: ${l.authorizationError??`unknown_authority`}`,a?`Hostname validation was skipped by request.`:f.matched?`Hostname validation passed.`:`Hostname validation failed: ${f.error??`unknown_error`}`,!l.authorized&&i?`Policy allowed the session to continue despite certificate trust failure.`:null].filter(e=>!!e),m=l.getCipher(),h={target:_,policy:v,transport:{protocol:l.getProtocol()??null,alpnProtocol:N(l.alpnProtocol),cipher:{name:m.name,standardName:m.standardName,version:m.version},localAddress:l.localAddress??null,localPort:l.localPort??null,remoteAddress:l.remoteAddress??null,remotePort:l.remotePort??null,servernameSent:M(l.servername),sessionReused:l.isSessionReused()},authorization:{socketAuthorized:l.authorized,authorizationError:typeof l.authorizationError==`string`?l.authorizationError:l.authorizationError?.message??null,hostnameValidation:f,policyAllowed:(l.authorized||i)&&(a||f.matched===!0),reasons:p},certificates:{leaf:c,chain:s}};if(!h.authorization.policyAllowed){l.destroy(),this.eventBus?.emit(`tls:probe_completed`,{host:t,port:n,success:!1,timestamp:new Date().toISOString()}),u({ok:!1,error:`TLS session authorization failed`,...h,timing:{handshakeMs:e}});return}let g=H(`tls`),b={id:g,kind:`tls`,socket:l,host:t,port:n,createdAt:Date.now(),buffer:Buffer.alloc(0),ended:!1,closed:!1,error:null,waiters:new Set,activeRead:!1,metadata:h};K(b),this.tlsSessions.set(g,b),this.eventBus?.emit(`tls:session_opened`,{sessionId:g,host:t,port:n,timestamp:new Date().toISOString()}),this.eventBus?.emit(`tls:probe_completed`,{host:t,port:n,success:!0,timestamp:new Date().toISOString()}),u({ok:!0,sessionId:g,kind:`tls`,...h,timing:{handshakeMs:e},state:W(b)})};l.once(`error`,f),l.once(`secureConnect`,p)})}async handleTlsWrite(e){let t=l(e,`sessionId`)?.trim()??null;if(!t)return{ok:!1,error:`sessionId is required`};let n=this.getTlsSession(t);return n?this.writeBufferedSession(n,e):{ok:!1,error:`Unknown tls sessionId "${t}"`}}async handleTlsReadUntil(e){let t=l(e,`sessionId`)?.trim()??null;if(!t)return{ok:!1,error:`sessionId is required`};let n=this.getTlsSession(t);return n?this.readBufferedSessionUntil(n,e):{ok:!1,error:`Unknown tls sessionId "${t}"`}}async handleTlsClose(e){let t=l(e,`sessionId`)?.trim()??null;return t?this.closeBufferedSession(t,this.tlsSessions,`tls`,e):{ok:!1,error:`sessionId is required`}}},ge=class extends he{emitWebSocketEvent(e,t){this.eventBus?.emit(e,t)}attachWebSocketSession(e){let t=()=>{for(;e.parserBuffer.length>0;){let t;try{t=ie(e.parserBuffer)}catch(t){e.error=O(t),e.socket.destroy();break}if(!t)break;e.parserBuffer=e.parserBuffer.subarray(t.bytesConsumed);let n=t.frame;if(e.frames.push(n),n.type===`ping`&&!e.closeSent&&!e.socket.destroyed){let t=Y(`pong`,n.data);e.socket.write(t),this.emitWebSocketEvent(`websocket:session_written`,{sessionId:e.id,frameType:`pong`,byteLength:n.data.length,automatic:!0,timestamp:new Date().toISOString()})}n.type===`close`&&(e.closeReceived=!0,!e.closeSent&&!e.socket.destroyed&&(e.closeSent=!0,e.socket.write(Y(`close`,n.data,n.closeCode,n.closeReason)),this.emitWebSocketEvent(`websocket:session_written`,{sessionId:e.id,frameType:`close`,byteLength:n.data.length,automatic:!0,timestamp:new Date().toISOString()})))}X(e)};e.socket.on(`data`,n=>{e.parserBuffer=Buffer.concat([e.parserBuffer,n]),t()}),e.socket.on(`end`,()=>{e.ended=!0,X(e)}),e.socket.on(`close`,()=>{e.closed=!0,X(e)}),e.socket.on(`error`,t=>{e.error=t.message,X(e)}),t()}async readWebSocketFrame(e,t){let n=f(t,`timeoutMs`)??5e3;if(!Number.isFinite(n)||n<=0)return{ok:!1,error:`timeoutMs must be a positive number`};if(e.activeRead)return{ok:!1,error:`Session "${e.id}" already has a pending read`,sessionId:e.id,kind:e.kind,state:q(e)};e.activeRead=!0;let r=Date.now();try{for(;;){let t=e.frames.shift();if(t)return this.emitWebSocketEvent(`websocket:frame_read`,{sessionId:e.id,frameType:t.type,byteLength:t.data.length,timestamp:new Date().toISOString()}),{ok:!0,sessionId:e.id,kind:e.kind,scheme:e.scheme,frameType:t.type,fin:t.fin,opcode:t.opcode,masked:t.masked,byteLength:t.data.length,dataHex:t.data.toString(`hex`).toUpperCase(),dataText:t.type===`binary`?null:t.data.toString(`utf8`),closeCode:t.closeCode,closeReason:t.closeReason,elapsedMs:Date.now()-r,state:q(e)};if(e.error)return{ok:!1,error:e.error,sessionId:e.id,kind:e.kind,state:q(e)};if(e.closed||e.ended)return{ok:!1,error:`socket closed before a WebSocket frame was available`,sessionId:e.id,kind:e.kind,state:q(e)};let i=n-(Date.now()-r);if(i<=0||!await ae(e,i))return{ok:!1,error:`read timed out`,sessionId:e.id,kind:e.kind,state:q(e)}}}finally{e.activeRead=!1}}async sendWebSocketFrame(e,t){if(e.closed||e.socket.destroyed)return{ok:!1,error:`Session "${e.id}" is already closed`,sessionId:e.id,kind:e.kind,state:q(e)};let n=u(t,`frameType`,new Set([`text`,`binary`,`ping`,`pong`,`close`]));if(!n)return{ok:!1,error:`frameType is required`};let r=l(t,`dataHex`),i=l(t,`dataText`);if(r&&i)return{ok:!1,error:`dataHex and dataText are mutually exclusive`};let a=f(t,`timeoutMs`)??5e3;if(!Number.isFinite(a)||a<=0)return{ok:!1,error:`timeoutMs must be a positive number`};let o=Buffer.alloc(0);if(r){let e=k(r);if(!A(e))return{ok:!1,error:`dataHex must be valid even-length hexadecimal data`};o=Buffer.from(e,`hex`)}else i!==void 0&&(o=Buffer.from(i,`utf8`));let s=null,c=null;if(n===`close`){let n=f(t,`closeCode`);if(n!==void 0){if(!Number.isInteger(n)||n<1e3||n>4999)return{ok:!1,error:`closeCode must be an integer between 1000 and 4999`};s=n}if(c=l(t,`closeReason`)??null,r||i)return{ok:!1,error:`close frames use closeCode/closeReason instead of dataHex/dataText`};e.closeSent=!0}if(n===`text`&&r)return{ok:!1,error:`text frames require UTF-8 dataText instead of dataHex`};let d=Y(n,o,s,c);return new Promise(t=>{let r=!1,i=n=>{r||(r=!0,clearTimeout(l),e.socket.off(`error`,u),t(n))},l=setTimeout(()=>{i({ok:!1,error:`write timed out`,sessionId:e.id,kind:e.kind,state:q(e)})},a),u=t=>{i({ok:!1,error:t.message,sessionId:e.id,kind:e.kind,state:q(e)})};e.socket.once(`error`,u),e.socket.write(d,()=>{this.emitWebSocketEvent(`websocket:session_written`,{sessionId:e.id,frameType:n,byteLength:n===`close`?c?Buffer.byteLength(c)+2:s?2:0:o.length,automatic:!1,timestamp:new Date().toISOString()}),i({ok:!0,sessionId:e.id,kind:e.kind,scheme:e.scheme,frameType:n,bytesWritten:d.length,payloadBytes:n===`close`?c?Buffer.byteLength(c)+2:s?2:0:o.length,state:q(e)})})})}async closeWebSocketSession(e,t){let n=this.websocketSessions.get(e);if(!n)return{ok:!1,error:`Unknown websocket sessionId "${e}"`};let r=p(t,`force`)??!1,i=f(t,`timeoutMs`)??1e3;if(!Number.isFinite(i)||i<=0)return{ok:!1,error:`timeoutMs must be a positive number`};let a=n.frames.length;if(n.closed||n.socket.destroyed)return this.websocketSessions.delete(e),{ok:!0,sessionId:e,kind:n.kind,force:r,closed:!0,queuedFramesDiscarded:a,state:q(n)};let o=null,s=f(t,`closeCode`);if(s!==void 0){if(!Number.isInteger(s)||s<1e3||s>4999)return{ok:!1,error:`closeCode must be an integer between 1000 and 4999`};o=s}let c=l(t,`closeReason`)??null;return new Promise(t=>{let s=!1,l=i=>{s||(s=!0,clearTimeout(f),n.socket.off(`close`,u),n.socket.off(`error`,d),this.websocketSessions.delete(e),this.emitWebSocketEvent(`websocket:session_closed`,{sessionId:e,reason:n.error,timestamp:new Date().toISOString()}),t({ok:!0,sessionId:e,kind:n.kind,force:r,closed:i,queuedFramesDiscarded:a,state:q(n)}))},u=()=>l(!0),d=()=>l(n.socket.destroyed||n.closed),f=setTimeout(()=>{n.socket.destroy(),l(n.socket.destroyed||n.closed)},i);if(n.socket.once(`close`,u),n.socket.once(`error`,d),r){n.socket.destroy();return}n.closeSent||(n.closeSent=!0,n.socket.write(Y(`close`,Buffer.alloc(0),o,c)),this.emitWebSocketEvent(`websocket:session_written`,{sessionId:e,frameType:`close`,byteLength:c?Buffer.byteLength(c)+2:o?2:0,automatic:!1,timestamp:new Date().toISOString()}))})}async handleWebSocketSendFrame(e){let t=l(e,`sessionId`)?.trim()??null;if(!t)return{ok:!1,error:`sessionId is required`};let n=this.getWebSocketSession(t);return n?this.sendWebSocketFrame(n,e):{ok:!1,error:`Unknown websocket sessionId "${t}"`}}async handleWebSocketReadFrame(e){let t=l(e,`sessionId`)?.trim()??null;if(!t)return{ok:!1,error:`sessionId is required`};let n=this.getWebSocketSession(t);return n?this.readWebSocketFrame(n,e):{ok:!1,error:`Unknown websocket sessionId "${t}"`}}async handleWebSocketClose(e){let t=l(e,`sessionId`)?.trim()??null;return t?this.closeWebSocketSession(t,e):{ok:!1,error:`sessionId is required`}}};const _e=[`TLSv1`,`TLSv1.1`,`TLSv1.2`,`TLSv1.3`];var ve=class extends ge{async handleWebSocketOpen(e){let t=l(e,`url`)?.trim()??null,n=l(e,`host`)?.trim()??null,r=l(e,`path`)?.trim()??null,i=f(e,`port`),a=l(e,`scheme`)?.trim()??null;if(t&&(n||r||i!==void 0||a))return{ok:!1,error:`url is mutually exclusive with explicit scheme/host/port/path inputs`};let o=`ws`,s=n,c=i??void 0,m=J(r),h;if(t){let e;try{e=new URL(t)}catch(e){return{ok:!1,error:`Invalid url: ${O(e)}`}}if(e.protocol!==`ws:`&&e.protocol!==`wss:`)return{ok:!1,error:`url must use ws:// or wss:// protocol`};o=e.protocol===`wss:`?`wss`:`ws`,s=e.hostname,c=e.port.length>0?Number(e.port):o===`wss`?443:80,m=J(`${e.pathname}${e.search}`),h=`${o}://${e.host}${m}`}else{if(!s)return{ok:!1,error:`host or url is required`};if(a){if(a!==`ws`&&a!==`wss`)return{ok:!1,error:`scheme must be ws or wss`};o=a}c??=o===`wss`?443:80;let e=c===(o===`wss`?443:80)?s:`${s}:${String(c)}`;h=`${o}://${e}${m}`}if(!s||!c||!Number.isInteger(c)||c<1||c>65535)return{ok:!1,error:`port must be an integer between 1 and 65535`};let g=f(e,`timeoutMs`)??5e3;if(!Number.isFinite(g)||g<=0)return{ok:!1,error:`timeoutMs must be a positive number`};let _=[...new Set(d(e,`subprotocols`).map(e=>e.trim()))].filter(e=>e.length>0),y=j(s);if(y)return y;let b=p(e,`allowInvalidCertificates`)??!1,S=p(e,`skipHostnameCheck`)??!1,w=l(e,`servername`)?.trim()??null,k=[...new Set(d(e,`alpnProtocols`).map(e=>e.trim()))].filter(e=>e.length>0),A,I;try{A=u(e,`minVersion`,D),I=u(e,`maxVersion`,D)}catch(e){return{ok:!1,error:O(e)}}if(A&&I&&_e.indexOf(A)>_e.indexOf(I))return{ok:!1,error:`minVersion must not be greater than maxVersion`};let R=o===`wss`?await F(e):{ok:!0,ca:void 0,source:null,path:null,bytes:null};if(!R.ok)return{ok:!1,error:R.error};let B={scheme:o,url:h,host:s,port:c,path:m,requestedServername:o===`wss`?w??(C(s)===0?s:void 0)??null:null,validationTarget:o===`wss`?w??s:null},V=v(16).toString(`base64`),W=re(V),G=Date.now();return new Promise(e=>{let t=!1,n=Buffer.alloc(0),r=null,i=null,a=null,l=o===`wss`?E(P({host:s,port:c,servername:B.requestedServername??void 0,...A?{minVersion:A}:{},...I?{maxVersion:I}:{},...k.length>0?{ALPNProtocols:k}:{},...R.ca?{ca:R.ca}:{}},b)):new x,u=n=>{t||(t=!0,clearTimeout(f),l.off(`error`,p),l.off(`connect`,v),l.off(`secureConnect`,y),l.off(`data`,C),e(n))},d=()=>{let e=c===(o===`wss`?443:80)?s:`${s}:${String(c)}`,t=[`GET ${m} HTTP/1.1`,`Host: ${e}`,`Upgrade: websocket`,`Connection: Upgrade`,`Sec-WebSocket-Key: ${V}`,`Sec-WebSocket-Version: 13`];return _.length>0&&t.push(`Sec-WebSocket-Protocol: ${_.join(`, `)}`),t.push(``,``),Buffer.from(t.join(`\r
2
- `),`utf8`)},f=setTimeout(()=>{l.destroy(),u({ok:!1,error:`WebSocket open timed out`,target:B})},g),p=e=>{u({ok:!1,error:e.message,errorCode:e.code??null,target:B})},h=()=>{l.write(d())},v=()=>{l instanceof x&&l.setNoDelay(!0),r={...U(l),protocol:null,alpnProtocol:null,servernameSent:null,sessionReused:null},h()},y=()=>{let e=l,t=e.getPeerCertificate(!0),n=L(t),o=n?z(t):[],s=o[0]??null,c=S||!n||!B.validationTarget?void 0:T(B.validationTarget,t),d={checked:!S,target:S?null:B.validationTarget,matched:S?null:c===void 0,error:!S&&!n?`Peer certificate was not presented by the server`:c?.message??null},f=[e.authorized?`Certificate chain validated against the active trust store.`:`Certificate chain validation failed: ${e.authorizationError??`unknown_authority`}`,S?`Hostname validation was skipped by request.`:d.matched?`Hostname validation passed.`:`Hostname validation failed: ${d.error??`unknown_error`}`,!e.authorized&&b?`Policy allowed the session to continue despite certificate trust failure.`:null].filter(e=>!!e);if(i={socketAuthorized:e.authorized,authorizationError:typeof e.authorizationError==`string`?e.authorizationError:e.authorizationError?.message??null,hostnameValidation:d,policyAllowed:(e.authorized||b)&&(S||d.matched===!0),reasons:f},a={leaf:s,chain:o},r={...U(e),protocol:e.getProtocol()??null,alpnProtocol:N(e.alpnProtocol),servernameSent:M(e.servername),sessionReused:e.isSessionReused()},!i.policyAllowed){e.destroy(),u({ok:!1,error:`WebSocket TLS authorization failed`,target:B,authorization:i,certificates:a});return}h()},C=e=>{n=Buffer.concat([n,e]);let t=n.indexOf(`\r
1
+ import{n as e}from"./response-C7rKQst4.mjs";import{a as t,c as n,i as r,l as i,n as a,o,r as s,s as c}from"./boringssl-inspector-BBaJwwkU.mjs";import{a as l,n as u,o as d,r as f,t as p}from"./parse-args-Bw413PlW.mjs";import{a as m,s as h}from"./ssrf-policy-CsIJGkpd.mjs";import{X509Certificate as g,createHash as _,randomBytes as v,randomUUID as y}from"node:crypto";import{readFile as b}from"node:fs/promises";import{createSocket as x}from"node:dgram";import{Socket as S,createServer as C,isIP as w}from"node:net";import{checkServerIdentity as T,connect as E}from"node:tls";const D=new Set([`TLSv1`,`TLSv1.1`,`TLSv1.2`,`TLSv1.3`]);function O(e){return e instanceof Error?e.message:String(e)}function k(e){return e.replace(/\s+/g,``).toUpperCase()}function A(e){return e.length>0&&e.length%2==0&&/^[0-9A-F]+$/i.test(e)}function j(e){return h(e)&&!m(e)?{ok:!1,error:`Blocked: target host "${e}" resolves to a private/internal address. SSRF protection applies.`}:null}function M(e){return typeof e==`string`&&e.length>0?e:null}function N(e){return typeof e==`string`&&e.length>0?e:null}function P(e,t){let n={...e};return Reflect.set(n,`rejectUnauthorized`,!t),n}async function F(e){let t=l(e,`caPem`)??null,n=l(e,`caPath`)??null;if(t&&n)return{ok:!1,error:`caPem and caPath are mutually exclusive`};if(t)return{ok:!0,ca:t,source:`inline`,path:null,bytes:Buffer.byteLength(t)};if(n)try{let e=await b(n,`utf8`);return{ok:!0,ca:e,source:`path`,path:n,bytes:Buffer.byteLength(e)}}catch(e){return{ok:!1,error:`Failed to read caPath "${n}": ${O(e)}`}}return{ok:!0,ca:void 0,source:null,path:null,bytes:null}}function I(e){return typeof e==`object`&&!!e&&Object.keys(e).length>0}function L(e){return I(e)}function R(e,t){let n=Buffer.isBuffer(e.raw)?e.raw:null,r=n?new g(n):null,i=r?.subject??null,a=r?.issuer??null;return{depth:t,subject:i,issuer:a,subjectAltName:r?.subjectAltName??e.subjectaltname??null,serialNumber:r?.serialNumber??e.serialNumber??null,validFrom:r?.validFrom??e.valid_from??null,validTo:r?.validTo??e.valid_to??null,fingerprint256:r?.fingerprint256??e.fingerprint256??null,fingerprint512:r?.fingerprint512??e.fingerprint512??null,rawLength:n?.length??null,isCA:r?.ca??e.ca??null,selfIssued:i&&a?i===a:null}}function z(e){if(!e)return[];let t=[],n=new Set,r=e,i=0;for(;r&&L(r);){let e=R(r,i),a=e.fingerprint256??`${e.subject??`unknown-subject`}:${e.serialNumber??`unknown-serial`}:${i}`;if(n.has(a)||(n.add(a),t.push(e),!(`issuerCertificate`in r)))break;let o=r.issuerCertificate;if(!o||o===r||!L(o))break;r=o,i+=1}return t}function B(e){let t=_(`sha256`).update(e).digest(`hex`).toUpperCase();try{let n=new g(e);return{subject:n.subject||void 0,issuer:n.issuer||void 0,serialNumber:n.serialNumber||void 0,validFrom:n.validFrom||void 0,validTo:n.validTo||void 0,sha256:t,length:e.length}}catch{return{sha256:t,length:e.length}}}function V(e){let t=Buffer.from(k(e),`hex`),n=[],r=0;for(;r<t.length-4;)if(t[r]===48){let e=B(t.subarray(r));n.push({sha256:e.sha256,length:e.length}),r+=e.length}else r+=1;return n.length===0&&t.length>0&&n.push({sha256:_(`sha256`).update(t).digest(`hex`).toUpperCase(),length:t.length}),n}function H(e){return`${e}_${y()}`}function U(e){return{localAddress:e.localAddress??null,localPort:e.localPort??null,remoteAddress:e.remoteAddress??null,remotePort:e.remotePort??null}}function W(e){return{bufferedBytes:e.buffer.length,remoteEnded:e.ended,socketClosed:e.closed,error:e.error}}function G(e){for(let t of e.waiters)t();e.waiters.clear()}function K(e){e.socket.on(`data`,t=>{e.buffer=Buffer.concat([e.buffer,t]),G(e)}),e.socket.on(`end`,()=>{e.ended=!0,G(e)}),e.socket.on(`close`,()=>{e.closed=!0,G(e)}),e.socket.on(`error`,t=>{e.error=t.message,G(e)})}function ee(e,t){return new Promise(n=>{let r=()=>{clearTimeout(i),e.waiters.delete(r),n(!0)},i=setTimeout(()=>{e.waiters.delete(r),n(!1)},t);e.waiters.add(r)})}function te(e,t,n,r){let i=t?t.toString(`hex`).toUpperCase():null;if(t){let r=e.buffer.indexOf(t);if(r>=0){let a=r+t.length,o=n?e.buffer.subarray(0,a):e.buffer.subarray(0,r);return e.buffer=e.buffer.subarray(a),{data:o,matchedDelimiter:!0,stopReason:`delimiter`,delimiterHex:i}}}if(typeof r==`number`&&e.buffer.length>=r){let t=e.buffer.subarray(0,r);return e.buffer=e.buffer.subarray(r),{data:t,matchedDelimiter:!1,stopReason:`maxBytes`,delimiterHex:i}}if((e.error||e.ended||e.closed)&&e.buffer.length>0){let t=e.buffer;return e.buffer=Buffer.alloc(0),{data:t,matchedDelimiter:!1,stopReason:e.error?`error`:`closed`,delimiterHex:i}}return null}function q(e){return{bufferedBytes:e.parserBuffer.length,queuedFrames:e.frames.length,remoteEnded:e.ended,socketClosed:e.closed,closeSent:e.closeSent,closeReceived:e.closeReceived,error:e.error}}function J(e){return!e||e.trim().length===0?`/`:e.startsWith(`/`)?e:`/${e}`}function ne(e){return{1:`text`,2:`binary`,8:`close`,9:`ping`,10:`pong`}[e]??null}function re(e){return _(`sha1`).update(`${e}258EAFA5-E914-47DA-95CA-C5AB0DC85B11`,`utf8`).digest(`base64`)}function Y(e,t,n,r){let i={text:1,binary:2,close:8,ping:9,pong:10},a=t;if(e===`close`)if(n!=null){let e=r?Buffer.from(r,`utf8`):Buffer.alloc(0);a=Buffer.alloc(2+e.length),a.writeUInt16BE(n,0),e.copy(a,2)}else r&&(a=Buffer.from(r,`utf8`));let o=v(4),s=a.length,c;s<126?(c=Buffer.alloc(2),c[1]=128|s):s<=65535?(c=Buffer.alloc(4),c[1]=254,c.writeUInt16BE(s,2)):(c=Buffer.alloc(10),c[1]=255,c.writeBigUInt64BE(BigInt(s),2)),c[0]=128|i[e];let l=Buffer.alloc(s);for(let e=0;e<s;e+=1)l[e]=a[e]^o[e%4];return Buffer.concat([c,o,l])}function ie(e){if(e.length<2)return null;let t=e[0],n=e[1],r=(t&128)!=0,i=t&15,a=(n&128)!=0,o=n&127,s=2;if(o===126){if(e.length<s+2)return null;o=e.readUInt16BE(s),s+=2}else if(o===127){if(e.length<s+8)return null;let t=e.readBigUInt64BE(s);if(t>BigInt(2**53-1))throw Error(`WebSocket frame payload length exceeds supported limits`);o=Number(t),s+=8}let c=a?e.subarray(s,s+4):null;if(a){if(e.length<s+4)return null;s+=4}if(e.length<s+o)return null;let l=e.subarray(s,s+o),u=Buffer.alloc(l.length);if(a&&c)for(let e=0;e<l.length;e+=1)u[e]=l[e]^c[e%4];else l.copy(u);let d=ne(i);if(!d)throw Error(`Unsupported WebSocket opcode 0x${i.toString(16)}`);let f=null,p=null;return d===`close`&&u.length>=2&&(f=u.readUInt16BE(0),p=u.subarray(2).toString(`utf8`)),{frame:{type:d,fin:r,opcode:i,masked:a,data:u,closeCode:f,closeReason:p,receivedAt:Date.now()},bytesConsumed:s+o}}function X(e){for(let t of e.waiters)t();e.waiters.clear()}function ae(e,t){return new Promise(n=>{let r=()=>{clearTimeout(i),e.waiters.delete(r),n(!0)},i=setTimeout(()=>{e.waiters.delete(r),n(!1)},t);e.waiters.add(r)})}const oe={"3:1":`TLS 1.0`,"3:2":`TLS 1.1`,"3:3":`TLS 1.2`,"3:4":`TLS 1.3`},se={20:`change_cipher_spec`,21:`alert`,22:`handshake`,23:`application_data`,24:`heartbeat`},ce={156:`TLS_RSA_WITH_AES_128_GCM_SHA256`,157:`TLS_RSA_WITH_AES_256_GCM_SHA384`,52392:`TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256`,52393:`TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384`,4865:`TLS_AES_128_GCM_SHA256`,4866:`TLS_AES_256_GCM_SHA384`,4867:`TLS_CHACHA20_POLY1305_SHA256`,4868:`TLS_AES_128_CCM_SHA256`,4869:`TLS_AES_128_CCM_8_SHA256`,49195:`TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256`,49196:`TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384`,49199:`TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256`,49200:`TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384`},le={0:`server_name`,1:`max_fragment_length`,5:`status_request`,10:`supported_groups`,13:`signature_algorithms`,16:`application_layer_protocol_negotiation`,18:`signed_certificate_timestamp`,23:`record_size_limit`,27:`compress_certificate`,35:`session_ticket`,43:`supported_versions`,44:`cookie`,45:`psk_key_exchange_modes`,49:`post_handshake_auth`,51:`key_share`};function Z(e,t){return oe[`${e}:${t}`]??`0x${e.toString(16).padStart(2,`0`)}${t.toString(16).padStart(2,`0`)}`}function Q(e){return se[e]??`unknown`}function ue(e){let t={cipherSuites:[],extensions:[]},n=e[0]!==void 0&&e[0]<25?4:0;if(e.length<n+38)return t;let r=n+34,i=e[r]??0,a=r+1+i;if(a+2>e.length)return t;let o=e.readUInt16BE(a);a+=2;let s=a+o;for(;a+2<=s;){let n=e.readUInt16BE(a);t.cipherSuites.push(ce[n]??`0x${n.toString(16).padStart(4,`0`)}`),a+=2}if(a=s+1,a<e.length){let t=e[a];t!==void 0&&(a+=1+t)}if(a+2<=e.length){let n=e.readUInt16BE(a);a+=2;let r=a+n;for(;a+4<=r;){let n=e.readUInt16BE(a),i=e.readUInt16BE(a+2);a+=4;let o=le[n]??`unknown(0x${n.toString(16)})`;if(t.extensions.push({type:n,name:o,length:i}),n===0&&a+2<=r){let n=a+2;if(n+3<=r&&e[n]===0){let i=e.readUInt16BE(n+1),a=n+3;a+i<=r&&(t.serverName=e.subarray(a,a+i).toString(`utf8`))}}a+=i}}return t}var de=class{keyLogExtractor;extensionInvoke;eventBus;tcpSessions=new Map;tlsSessions=new Map;websocketSessions=new Map;constructor(e=new a){this.keyLogExtractor=e}setExtensionInvoke(e){this.extensionInvoke=e}setEventBus(e){this.eventBus=e}getTcpSession(e){return this.tcpSessions.get(e)??null}getTlsSession(e){return this.tlsSessions.get(e)??null}getWebSocketSession(e){return this.websocketSessions.get(e)??null}parseWritePayload(e){let t=l(e,`dataHex`),n=l(e,`dataText`);if(!t&&!n)return{ok:!1,error:`dataHex or dataText is required`};if(t&&n)return{ok:!1,error:`dataHex and dataText are mutually exclusive`};if(t){let e=k(t);return A(e)?{ok:!0,data:Buffer.from(e,`hex`),inputEncoding:`hex`}:{ok:!1,error:`dataHex must be valid even-length hexadecimal data`}}return{ok:!0,data:Buffer.from(n??``,`utf8`),inputEncoding:`utf8`}}async writeBufferedSession(e,t){if(e.socket.destroyed||e.closed)return{ok:!1,error:`Session "${e.id}" is already closed`,sessionId:e.id,kind:e.kind,state:W(e)};let n=this.parseWritePayload(t);if(!n.ok)return{ok:!1,error:n.error,sessionId:e.id,kind:e.kind};let r=f(t,`timeoutMs`)??5e3;return!Number.isFinite(r)||r<=0?{ok:!1,error:`timeoutMs must be a positive number`}:new Promise(t=>{let i=!1,a=n=>{i||(i=!0,clearTimeout(o),e.socket.off(`error`,s),t(n))},o=setTimeout(()=>{a({ok:!1,error:`write timed out`,sessionId:e.id,kind:e.kind,state:W(e)})},r),s=t=>{a({ok:!1,error:t.message,sessionId:e.id,kind:e.kind,state:W(e)})};e.socket.once(`error`,s),e.socket.write(n.data,()=>{e.kind===`tcp`?this.eventBus?.emit(`tcp:session_written`,{sessionId:e.id,byteLength:n.data.length,timestamp:new Date().toISOString()}):this.eventBus?.emit(`tls:session_written`,{sessionId:e.id,byteLength:n.data.length,timestamp:new Date().toISOString()}),a({ok:!0,sessionId:e.id,kind:e.kind,inputEncoding:n.inputEncoding,bytesWritten:n.data.length,transport:U(e.socket),state:W(e)})})})}async readBufferedSessionUntil(e,t){let n=l(t,`delimiterHex`),r=l(t,`delimiterText`);if(n&&r)return{ok:!1,error:`delimiterHex and delimiterText are mutually exclusive`};let i=null;if(n){let e=k(n);if(!A(e))return{ok:!1,error:`delimiterHex must be valid even-length hexadecimal data`};i=Buffer.from(e,`hex`)}else r!==void 0&&(i=Buffer.from(r,`utf8`));if(i&&i.length===0)return{ok:!1,error:`delimiter must not be empty`};let a=p(t,`includeDelimiter`)??!0,o=f(t,`maxBytes`),s=o===void 0?void 0:Math.trunc(o);if(s!==void 0&&(!Number.isFinite(s)||s<=0))return{ok:!1,error:`maxBytes must be a positive integer when provided`};if(!i&&s===void 0)return{ok:!1,error:`delimiterHex, delimiterText, or maxBytes is required`};let c=f(t,`timeoutMs`)??5e3;if(!Number.isFinite(c)||c<=0)return{ok:!1,error:`timeoutMs must be a positive number`};if(e.activeRead)return{ok:!1,error:`Session "${e.id}" already has a pending read`,sessionId:e.id,kind:e.kind,state:W(e)};e.activeRead=!0;let u=Date.now();try{for(;;){let t=te(e,i,a,s);if(t)return e.kind===`tcp`?this.eventBus?.emit(`tcp:session_read`,{sessionId:e.id,byteLength:t.data.length,matched:t.matchedDelimiter,timestamp:new Date().toISOString()}):this.eventBus?.emit(`tls:session_read`,{sessionId:e.id,byteLength:t.data.length,matched:t.matchedDelimiter,timestamp:new Date().toISOString()}),{ok:!0,sessionId:e.id,kind:e.kind,bytesRead:t.data.length,matchedDelimiter:t.matchedDelimiter,stopReason:t.stopReason,delimiterHex:t.delimiterHex,dataHex:t.data.toString(`hex`).toUpperCase(),dataText:t.data.toString(`utf8`),elapsedMs:Date.now()-u,state:W(e)};if(e.error)return{ok:!1,error:e.error,sessionId:e.id,kind:e.kind,state:W(e)};if(e.ended||e.closed)return{ok:!1,error:`socket closed before the requested read condition was satisfied`,sessionId:e.id,kind:e.kind,state:W(e)};let n=c-(Date.now()-u);if(n<=0||!await ee(e,n))return{ok:!1,error:`read timed out`,sessionId:e.id,kind:e.kind,state:W(e)}}}finally{e.activeRead=!1}}async closeBufferedSession(e,t,n,r){let i=t.get(e);if(!i)return{ok:!1,error:`Unknown ${n} sessionId "${e}"`};let a=p(r,`force`)??!1,o=f(r,`timeoutMs`)??1e3;if(!Number.isFinite(o)||o<=0)return{ok:!1,error:`timeoutMs must be a positive number`};let s=i.buffer.length;return i.closed||i.socket.destroyed?(t.delete(e),{ok:!0,sessionId:e,kind:n,force:a,closed:!0,bufferedBytesDiscarded:s,state:W(i)}):new Promise(r=>{let c=!1,l=o=>{c||(c=!0,clearTimeout(f),i.socket.off(`close`,u),i.socket.off(`error`,d),t.delete(e),n===`tcp`?this.eventBus?.emit(`tcp:session_closed`,{sessionId:e,reason:i.error,timestamp:new Date().toISOString()}):this.eventBus?.emit(`tls:session_closed`,{sessionId:e,reason:i.error,timestamp:new Date().toISOString()}),r({ok:!0,sessionId:e,kind:n,force:a,closed:o,bufferedBytesDiscarded:s,state:W(i)}))},u=()=>l(!0),d=()=>l(i.socket.destroyed||i.closed),f=setTimeout(()=>{i.socket.destroy(),l(i.socket.destroyed||i.closed)},o);if(i.socket.once(`close`,u),i.socket.once(`error`,d),a){i.socket.destroy();return}i.socket.end()})}},fe=class extends de{async handleTlsKeylogEnable(e){return{enabled:!0,keyLogPath:await this.keyLogExtractor.enableKeyLog(),environmentVariable:`SSLKEYLOGFILE`}}async handleTlsKeylogDisable(e){let t=l(e,`path`)??null;return t?await this.keyLogExtractor.disableKeyLog():r(),{disabled:!0,previousPath:t??o()}}async handleTlsKeylogParse(e){let t=l(e,`path`)??null,n=this.keyLogExtractor.parseKeyLog(t??void 0),r=this.keyLogExtractor.summarizeKeyLog(t??void 0);return{path:t??this.keyLogExtractor.getKeyLogFilePath(),entries:n,summary:r}}async handleTlsDecryptPayload(e){let t=l(e,`encryptedHex`)??null,n=l(e,`keyHex`)??null,r=l(e,`nonceHex`)??null,i=l(e,`algorithm`)??`aes-256-gcm`,a=l(e,`authTagHex`)??null;if(!t||!n||!r)return{ok:!1,error:`encryptedHex, keyHex, and nonceHex are required`};let o=s(t,n,r,i,a??void 0);return{ok:!0,algorithm:i,decrypted:o,isFailed:o.startsWith(`DECRYPTION_FAILED:`)}}async handleTlsKeylogSummarize(e){let t=l(e,`content`)??null;return t?i(n(t)):(this.keyLogExtractor.parseKeyLog(),this.keyLogExtractor.summarizeKeyLog())}async handleTlsKeylogLookupSecret(e){let t=l(e,`clientRandom`)??null,n=l(e,`label`)??void 0;if(!t)return{ok:!1,error:`clientRandom is required`};let r=this.keyLogExtractor.lookupSecret(t);if(r)return{ok:!0,clientRandom:k(t),secret:r};let i=c(this.keyLogExtractor.parseKeyLog(),t,n);return{ok:i!==null,clientRandom:k(t),secret:i??null}}async handleTlsCertPinBypass(e){let t=l(e,`target`)??null;return t!==`android`&&t!==`ios`&&t!==`desktop`?{error:`target must be one of android, ios, or desktop`}:{bypassStrategy:{android:`hook-trust-manager`,ios:`replace-sec-trust-evaluation`,desktop:`patch-custom-verifier`}[t],affectedDomains:[`*`],instructions:{android:[`Inject a Frida script that overrides X509TrustManager checks.`,`Re-run the target flow after SSLKEYLOGFILE capture is enabled.`],ios:[`Hook SecTrustEvaluateWithError and return success for the target session.`,`Collect TLS keys after the app resumes the failing request.`],desktop:[`Patch the custom verifier callback or disable pin comparison in the client.`,`Capture a fresh handshake after the patched build starts.`]}[t]}}async handleParseHandshake(t){let n=l(t,`rawHex`)??null,r=t.decrypt===!0;if(!n)return e({success:!1,error:`rawHex is required`});let i=k(n);if(!/^(?:[0-9a-f]{2})+$/i.test(i))return e({success:!1,error:`Invalid hex payload`});let a=Buffer.from(i,`hex`);if(a.length<5)return e({success:!1,error:`TLS record is too short`});let o=a[0],s=a[1],c=a[2],u=a.readUInt16BE(3),d=a.subarray(5),f=o===22&&d.length>0&&d[0]===1?ue(d):void 0,p=r?(()=>{let e=this.keyLogExtractor.decryptPayload(i,this.keyLogExtractor.parseKeyLog());return e?e.subarray(0,16).toString(`hex`).toUpperCase():null})():void 0;return e({success:!0,record:{contentType:o,contentTypeName:Q(o),version:Z(s,c),declaredLength:u,actualLength:d.length},handshake:{version:Z(s,c),contentType:Q(o),...f?{type:`client_hello`,serverName:f.serverName,cipherSuites:f.cipherSuites,extensions:f.extensions}:{cipherSuite:[],extensions:[]}},sni:f?.serverName?{serverName:f.serverName}:void 0,...p===void 0?{}:{decryptedPreviewHex:p}})}async handleKeyLogEnable(n){let r=l(n,`filePath`)??`/tmp/sslkeylog.log`;return t(r),this.eventBus?.emit(`tls:keylog_started`,{filePath:r,timestamp:new Date().toISOString()}),e({success:!0,filePath:r,currentFilePath:o()})}async handleCipherSuites(t){let n=l(t,`filter`)??null,r=[`TLS_AES_128_GCM_SHA256`,`TLS_AES_256_GCM_SHA384`,`TLS_CHACHA20_POLY1305_SHA256`,`TLS_AES_128_CCM_SHA256`,`TLS_AES_128_CCM_8_SHA256`,`TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256`,`TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384`,`TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256`,`TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384`,`TLS_RSA_WITH_AES_128_GCM_SHA256`,`TLS_RSA_WITH_AES_256_GCM_SHA384`],i=n?r.filter(e=>e.includes(n)):r;return e({success:!0,filter:n,total:i.length,suites:i})}async handleParseCertificate(t){let n=l(t,`rawHex`)??null;if(!n)return e({success:!1,error:`rawHex is required`});let r=V(n);return e({success:!0,certificateCount:r.length,fingerprints:r.map(e=>({sha256:e.sha256,length:e.length}))})}};const $=[`TLSv1`,`TLSv1.1`,`TLSv1.2`,`TLSv1.3`];var pe=class extends fe{async handleTlsProbeEndpoint(e){let t=l(e,`host`)?.trim()??null;if(!t)return{ok:!1,error:`host is required`};let n=f(e,`port`)??443;if(!Number.isInteger(n)||n<1||n>65535)return{ok:!1,error:`port must be an integer between 1 and 65535`};let r=f(e,`timeoutMs`)??5e3;if(!Number.isFinite(r)||r<=0)return{ok:!1,error:`timeoutMs must be a positive number`};let i=p(e,`allowInvalidCertificates`)??!1,a=p(e,`skipHostnameCheck`)??!1,o=l(e,`servername`)?.trim()??null,s=[...new Set(d(e,`alpnProtocols`).map(e=>e.trim()))].filter(e=>e.length>0),c,m;try{c=u(e,`minVersion`,D),m=u(e,`maxVersion`,D)}catch(e){return{ok:!1,error:O(e)}}if(c&&m&&$.indexOf(c)>$.indexOf(m))return{ok:!1,error:`minVersion must not be greater than maxVersion`};let h=j(t);if(h)return h;let g=await F(e);if(!g.ok)return{ok:!1,error:g.error};let _=o??t,v=o??(w(t)===0?t:void 0),y=Date.now();return new Promise(e=>{let o=!1,l=E(P({host:t,port:n,servername:v,...c?{minVersion:c}:{},...m?{maxVersion:m}:{},...s.length>0?{ALPNProtocols:s}:{},...g.ca?{ca:g.ca}:{}},i)),u=t=>{o||(o=!0,clearTimeout(d),l.removeAllListeners(),l.destroy(),e(t))},d=setTimeout(()=>{this.eventBus?.emit(`tls:probe_completed`,{host:t,port:n,success:!1,timestamp:new Date().toISOString()}),u({ok:!1,error:`TLS probe timed out`,target:{host:t,port:n,requestedServername:v??null,validationTarget:_},policy:{allowInvalidCertificates:i,skipHostnameCheck:a,timeoutMs:r,minVersion:c??null,maxVersion:m??null,alpnProtocols:s,customCa:{source:g.source,path:g.path,bytes:g.bytes}}})},r);l.once(`error`,e=>{this.eventBus?.emit(`tls:probe_completed`,{host:t,port:n,success:!1,timestamp:new Date().toISOString()}),u({ok:!1,error:e.message,errorCode:e.code??null,target:{host:t,port:n,requestedServername:v??null,validationTarget:_},policy:{allowInvalidCertificates:i,skipHostnameCheck:a,timeoutMs:r,minVersion:c??null,maxVersion:m??null,alpnProtocols:s,customCa:{source:g.source,path:g.path,bytes:g.bytes}}})}),l.once(`secureConnect`,()=>{let e=Date.now()-y,o=l.getPeerCertificate(!0),d=L(o),f=d?z(o):[],p=f[0]??null,h=a||!d?void 0:T(_,o),b={checked:!a,target:a?null:_,matched:a?null:h===void 0,error:!a&&!d?`Peer certificate was not presented by the server`:h?.message??null},x=[l.authorized?`Certificate chain validated against the active trust store.`:`Certificate chain validation failed: ${l.authorizationError??`unknown_authority`}`,a?`Hostname validation was skipped by request.`:b.matched?`Hostname validation passed.`:`Hostname validation failed: ${b.error??`unknown_error`}`,!l.authorized&&i?`Policy allowed the probe to continue despite certificate trust failure.`:null].filter(e=>!!e),S=l.getCipher();this.eventBus?.emit(`tls:probe_completed`,{host:t,port:n,success:!0,timestamp:new Date().toISOString()}),u({ok:!0,target:{host:t,port:n,requestedServername:v??null,validationTarget:_},policy:{allowInvalidCertificates:i,skipHostnameCheck:a,timeoutMs:r,minVersion:c??null,maxVersion:m??null,alpnProtocols:s,customCa:{source:g.source,path:g.path,bytes:g.bytes}},transport:{protocol:l.getProtocol()??null,alpnProtocol:N(l.alpnProtocol),cipher:{name:S.name,standardName:S.standardName,version:S.version},localAddress:l.localAddress??null,localPort:l.localPort??null,remoteAddress:l.remoteAddress??null,remotePort:l.remotePort??null,servernameSent:M(l.servername),sessionReused:l.isSessionReused()},authorization:{socketAuthorized:l.authorized,authorizationError:typeof l.authorizationError==`string`?l.authorizationError:l.authorizationError?.message??null,hostnameValidation:b,policyAllowed:(l.authorized||i)&&(a||b.matched===!0),reasons:x},certificates:{leaf:p,chain:f},timing:{handshakeMs:e}})})})}};const me=[`TLSv1`,`TLSv1.1`,`TLSv1.2`,`TLSv1.3`];var he=class extends pe{async handleTcpOpen(e){let t=l(e,`host`)??`127.0.0.1`,n=f(e,`port`);if(n===void 0||!Number.isInteger(n)||n<1||n>65535)return{ok:!1,error:`port must be an integer between 1 and 65535`};let r=f(e,`timeoutMs`)??5e3;if(!Number.isFinite(r)||r<=0)return{ok:!1,error:`timeoutMs must be a positive number`};let i=p(e,`noDelay`)??!0;return j(t)||new Promise(e=>{let a=!1,o=new S,s=t=>{a||(a=!0,clearTimeout(c),o.off(`connect`,u),o.off(`error`,l),e(t))},c=setTimeout(()=>{o.destroy(),s({ok:!1,error:`TCP connect timed out`,target:{host:t,port:n}})},r),l=e=>{s({ok:!1,error:e.message,target:{host:t,port:n}})},u=()=>{o.setNoDelay(i);let e=H(`tcp`),r={id:e,kind:`tcp`,socket:o,host:t,port:n,createdAt:Date.now(),buffer:Buffer.alloc(0),ended:!1,closed:!1,error:null,waiters:new Set,activeRead:!1};K(r),this.tcpSessions.set(e,r),this.eventBus?.emit(`tcp:session_opened`,{sessionId:e,host:t,port:n,timestamp:new Date().toISOString()}),s({ok:!0,sessionId:e,kind:`tcp`,target:{host:t,port:n},createdAt:new Date(r.createdAt).toISOString(),transport:U(o),state:W(r)})};o.once(`connect`,u),o.once(`error`,l),o.connect(n,t)})}async handleTcpWrite(e){let t=l(e,`sessionId`)?.trim()??null;if(!t)return{ok:!1,error:`sessionId is required`};let n=this.getTcpSession(t);return n?this.writeBufferedSession(n,e):{ok:!1,error:`Unknown tcp sessionId "${t}"`}}async handleTcpReadUntil(e){let t=l(e,`sessionId`)?.trim()??null;if(!t)return{ok:!1,error:`sessionId is required`};let n=this.getTcpSession(t);return n?this.readBufferedSessionUntil(n,e):{ok:!1,error:`Unknown tcp sessionId "${t}"`}}async handleTcpClose(e){let t=l(e,`sessionId`)?.trim()??null;return t?this.closeBufferedSession(t,this.tcpSessions,`tcp`,e):{ok:!1,error:`sessionId is required`}}async handleTlsOpen(e){let t=l(e,`host`)?.trim()??null;if(!t)return{ok:!1,error:`host is required`};let n=f(e,`port`)??443;if(!Number.isInteger(n)||n<1||n>65535)return{ok:!1,error:`port must be an integer between 1 and 65535`};let r=f(e,`timeoutMs`)??5e3;if(!Number.isFinite(r)||r<=0)return{ok:!1,error:`timeoutMs must be a positive number`};let i=p(e,`allowInvalidCertificates`)??!1,a=p(e,`skipHostnameCheck`)??!1,o=l(e,`servername`)?.trim()??null,s=[...new Set(d(e,`alpnProtocols`).map(e=>e.trim()))].filter(e=>e.length>0),c,m;try{c=u(e,`minVersion`,D),m=u(e,`maxVersion`,D)}catch(e){return{ok:!1,error:O(e)}}if(c&&m&&me.indexOf(c)>me.indexOf(m))return{ok:!1,error:`minVersion must not be greater than maxVersion`};let h=j(t);if(h)return h;let g=await F(e);if(!g.ok)return{ok:!1,error:g.error};let _={host:t,port:n,requestedServername:o??(w(t)===0?t:void 0)??null,validationTarget:o??t},v={allowInvalidCertificates:i,skipHostnameCheck:a,timeoutMs:r,minVersion:c??null,maxVersion:m??null,alpnProtocols:s,customCa:{source:g.source,path:g.path,bytes:g.bytes}},y=Date.now();return new Promise(e=>{let o=!1,l=E(P({host:t,port:n,servername:_.requestedServername??void 0,...c?{minVersion:c}:{},...m?{maxVersion:m}:{},...s.length>0?{ALPNProtocols:s}:{},...g.ca?{ca:g.ca}:{}},i)),u=t=>{o||(o=!0,clearTimeout(d),l.off(`error`,f),l.off(`secureConnect`,p),e(t))},d=setTimeout(()=>{l.destroy(),this.eventBus?.emit(`tls:probe_completed`,{host:t,port:n,success:!1,timestamp:new Date().toISOString()}),u({ok:!1,error:`TLS open timed out`,target:_,policy:v})},r),f=e=>{this.eventBus?.emit(`tls:probe_completed`,{host:t,port:n,success:!1,timestamp:new Date().toISOString()}),u({ok:!1,error:e.message,errorCode:e.code??null,target:_,policy:v})},p=()=>{let e=Date.now()-y,r=l.getPeerCertificate(!0),o=L(r),s=o?z(r):[],c=s[0]??null,d=a||!o?void 0:T(_.validationTarget,r),f={checked:!a,target:a?null:_.validationTarget,matched:a?null:d===void 0,error:!a&&!o?`Peer certificate was not presented by the server`:d?.message??null},p=[l.authorized?`Certificate chain validated against the active trust store.`:`Certificate chain validation failed: ${l.authorizationError??`unknown_authority`}`,a?`Hostname validation was skipped by request.`:f.matched?`Hostname validation passed.`:`Hostname validation failed: ${f.error??`unknown_error`}`,!l.authorized&&i?`Policy allowed the session to continue despite certificate trust failure.`:null].filter(e=>!!e),m=l.getCipher(),h={target:_,policy:v,transport:{protocol:l.getProtocol()??null,alpnProtocol:N(l.alpnProtocol),cipher:{name:m.name,standardName:m.standardName,version:m.version},localAddress:l.localAddress??null,localPort:l.localPort??null,remoteAddress:l.remoteAddress??null,remotePort:l.remotePort??null,servernameSent:M(l.servername),sessionReused:l.isSessionReused()},authorization:{socketAuthorized:l.authorized,authorizationError:typeof l.authorizationError==`string`?l.authorizationError:l.authorizationError?.message??null,hostnameValidation:f,policyAllowed:(l.authorized||i)&&(a||f.matched===!0),reasons:p},certificates:{leaf:c,chain:s}};if(!h.authorization.policyAllowed){l.destroy(),this.eventBus?.emit(`tls:probe_completed`,{host:t,port:n,success:!1,timestamp:new Date().toISOString()}),u({ok:!1,error:`TLS session authorization failed`,...h,timing:{handshakeMs:e}});return}let g=H(`tls`),b={id:g,kind:`tls`,socket:l,host:t,port:n,createdAt:Date.now(),buffer:Buffer.alloc(0),ended:!1,closed:!1,error:null,waiters:new Set,activeRead:!1,metadata:h};K(b),this.tlsSessions.set(g,b),this.eventBus?.emit(`tls:session_opened`,{sessionId:g,host:t,port:n,timestamp:new Date().toISOString()}),this.eventBus?.emit(`tls:probe_completed`,{host:t,port:n,success:!0,timestamp:new Date().toISOString()}),u({ok:!0,sessionId:g,kind:`tls`,...h,timing:{handshakeMs:e},state:W(b)})};l.once(`error`,f),l.once(`secureConnect`,p)})}async handleTlsWrite(e){let t=l(e,`sessionId`)?.trim()??null;if(!t)return{ok:!1,error:`sessionId is required`};let n=this.getTlsSession(t);return n?this.writeBufferedSession(n,e):{ok:!1,error:`Unknown tls sessionId "${t}"`}}async handleTlsReadUntil(e){let t=l(e,`sessionId`)?.trim()??null;if(!t)return{ok:!1,error:`sessionId is required`};let n=this.getTlsSession(t);return n?this.readBufferedSessionUntil(n,e):{ok:!1,error:`Unknown tls sessionId "${t}"`}}async handleTlsClose(e){let t=l(e,`sessionId`)?.trim()??null;return t?this.closeBufferedSession(t,this.tlsSessions,`tls`,e):{ok:!1,error:`sessionId is required`}}},ge=class extends he{emitWebSocketEvent(e,t){this.eventBus?.emit(e,t)}attachWebSocketSession(e){let t=()=>{for(;e.parserBuffer.length>0;){let t;try{t=ie(e.parserBuffer)}catch(t){e.error=O(t),e.socket.destroy();break}if(!t)break;e.parserBuffer=e.parserBuffer.subarray(t.bytesConsumed);let n=t.frame;if(e.frames.push(n),n.type===`ping`&&!e.closeSent&&!e.socket.destroyed){let t=Y(`pong`,n.data);e.socket.write(t),this.emitWebSocketEvent(`websocket:session_written`,{sessionId:e.id,frameType:`pong`,byteLength:n.data.length,automatic:!0,timestamp:new Date().toISOString()})}n.type===`close`&&(e.closeReceived=!0,!e.closeSent&&!e.socket.destroyed&&(e.closeSent=!0,e.socket.write(Y(`close`,n.data,n.closeCode,n.closeReason)),this.emitWebSocketEvent(`websocket:session_written`,{sessionId:e.id,frameType:`close`,byteLength:n.data.length,automatic:!0,timestamp:new Date().toISOString()})))}X(e)};e.socket.on(`data`,n=>{e.parserBuffer=Buffer.concat([e.parserBuffer,n]),t()}),e.socket.on(`end`,()=>{e.ended=!0,X(e)}),e.socket.on(`close`,()=>{e.closed=!0,X(e)}),e.socket.on(`error`,t=>{e.error=t.message,X(e)}),t()}async readWebSocketFrame(e,t){let n=f(t,`timeoutMs`)??5e3;if(!Number.isFinite(n)||n<=0)return{ok:!1,error:`timeoutMs must be a positive number`};if(e.activeRead)return{ok:!1,error:`Session "${e.id}" already has a pending read`,sessionId:e.id,kind:e.kind,state:q(e)};e.activeRead=!0;let r=Date.now();try{for(;;){let t=e.frames.shift();if(t)return this.emitWebSocketEvent(`websocket:frame_read`,{sessionId:e.id,frameType:t.type,byteLength:t.data.length,timestamp:new Date().toISOString()}),{ok:!0,sessionId:e.id,kind:e.kind,scheme:e.scheme,frameType:t.type,fin:t.fin,opcode:t.opcode,masked:t.masked,byteLength:t.data.length,dataHex:t.data.toString(`hex`).toUpperCase(),dataText:t.type===`binary`?null:t.data.toString(`utf8`),closeCode:t.closeCode,closeReason:t.closeReason,elapsedMs:Date.now()-r,state:q(e)};if(e.error)return{ok:!1,error:e.error,sessionId:e.id,kind:e.kind,state:q(e)};if(e.closed||e.ended)return{ok:!1,error:`socket closed before a WebSocket frame was available`,sessionId:e.id,kind:e.kind,state:q(e)};let i=n-(Date.now()-r);if(i<=0||!await ae(e,i))return{ok:!1,error:`read timed out`,sessionId:e.id,kind:e.kind,state:q(e)}}}finally{e.activeRead=!1}}async sendWebSocketFrame(e,t){if(e.closed||e.socket.destroyed)return{ok:!1,error:`Session "${e.id}" is already closed`,sessionId:e.id,kind:e.kind,state:q(e)};let n=u(t,`frameType`,new Set([`text`,`binary`,`ping`,`pong`,`close`]));if(!n)return{ok:!1,error:`frameType is required`};let r=l(t,`dataHex`),i=l(t,`dataText`);if(r&&i)return{ok:!1,error:`dataHex and dataText are mutually exclusive`};let a=f(t,`timeoutMs`)??5e3;if(!Number.isFinite(a)||a<=0)return{ok:!1,error:`timeoutMs must be a positive number`};let o=Buffer.alloc(0);if(r){let e=k(r);if(!A(e))return{ok:!1,error:`dataHex must be valid even-length hexadecimal data`};o=Buffer.from(e,`hex`)}else i!==void 0&&(o=Buffer.from(i,`utf8`));let s=null,c=null;if(n===`close`){let n=f(t,`closeCode`);if(n!==void 0){if(!Number.isInteger(n)||n<1e3||n>4999)return{ok:!1,error:`closeCode must be an integer between 1000 and 4999`};s=n}if(c=l(t,`closeReason`)??null,r||i)return{ok:!1,error:`close frames use closeCode/closeReason instead of dataHex/dataText`};e.closeSent=!0}if(n===`text`&&r)return{ok:!1,error:`text frames require UTF-8 dataText instead of dataHex`};let d=Y(n,o,s,c);return new Promise(t=>{let r=!1,i=n=>{r||(r=!0,clearTimeout(l),e.socket.off(`error`,u),t(n))},l=setTimeout(()=>{i({ok:!1,error:`write timed out`,sessionId:e.id,kind:e.kind,state:q(e)})},a),u=t=>{i({ok:!1,error:t.message,sessionId:e.id,kind:e.kind,state:q(e)})};e.socket.once(`error`,u),e.socket.write(d,()=>{this.emitWebSocketEvent(`websocket:session_written`,{sessionId:e.id,frameType:n,byteLength:n===`close`?c?Buffer.byteLength(c)+2:s?2:0:o.length,automatic:!1,timestamp:new Date().toISOString()}),i({ok:!0,sessionId:e.id,kind:e.kind,scheme:e.scheme,frameType:n,bytesWritten:d.length,payloadBytes:n===`close`?c?Buffer.byteLength(c)+2:s?2:0:o.length,state:q(e)})})})}async closeWebSocketSession(e,t){let n=this.websocketSessions.get(e);if(!n)return{ok:!1,error:`Unknown websocket sessionId "${e}"`};let r=p(t,`force`)??!1,i=f(t,`timeoutMs`)??1e3;if(!Number.isFinite(i)||i<=0)return{ok:!1,error:`timeoutMs must be a positive number`};let a=n.frames.length;if(n.closed||n.socket.destroyed)return this.websocketSessions.delete(e),{ok:!0,sessionId:e,kind:n.kind,force:r,closed:!0,queuedFramesDiscarded:a,state:q(n)};let o=null,s=f(t,`closeCode`);if(s!==void 0){if(!Number.isInteger(s)||s<1e3||s>4999)return{ok:!1,error:`closeCode must be an integer between 1000 and 4999`};o=s}let c=l(t,`closeReason`)??null;return new Promise(t=>{let s=!1,l=i=>{s||(s=!0,clearTimeout(f),n.socket.off(`close`,u),n.socket.off(`error`,d),this.websocketSessions.delete(e),this.emitWebSocketEvent(`websocket:session_closed`,{sessionId:e,reason:n.error,timestamp:new Date().toISOString()}),t({ok:!0,sessionId:e,kind:n.kind,force:r,closed:i,queuedFramesDiscarded:a,state:q(n)}))},u=()=>l(!0),d=()=>l(n.socket.destroyed||n.closed),f=setTimeout(()=>{n.socket.destroy(),l(n.socket.destroyed||n.closed)},i);if(n.socket.once(`close`,u),n.socket.once(`error`,d),r){n.socket.destroy();return}n.closeSent||(n.closeSent=!0,n.socket.write(Y(`close`,Buffer.alloc(0),o,c)),this.emitWebSocketEvent(`websocket:session_written`,{sessionId:e,frameType:`close`,byteLength:c?Buffer.byteLength(c)+2:o?2:0,automatic:!1,timestamp:new Date().toISOString()}))})}async handleWebSocketSendFrame(e){let t=l(e,`sessionId`)?.trim()??null;if(!t)return{ok:!1,error:`sessionId is required`};let n=this.getWebSocketSession(t);return n?this.sendWebSocketFrame(n,e):{ok:!1,error:`Unknown websocket sessionId "${t}"`}}async handleWebSocketReadFrame(e){let t=l(e,`sessionId`)?.trim()??null;if(!t)return{ok:!1,error:`sessionId is required`};let n=this.getWebSocketSession(t);return n?this.readWebSocketFrame(n,e):{ok:!1,error:`Unknown websocket sessionId "${t}"`}}async handleWebSocketClose(e){let t=l(e,`sessionId`)?.trim()??null;return t?this.closeWebSocketSession(t,e):{ok:!1,error:`sessionId is required`}}};const _e=[`TLSv1`,`TLSv1.1`,`TLSv1.2`,`TLSv1.3`];var ve=class extends ge{async handleWebSocketOpen(e){let t=l(e,`url`)?.trim()??null,n=l(e,`host`)?.trim()??null,r=l(e,`path`)?.trim()??null,i=f(e,`port`),a=l(e,`scheme`)?.trim()??null;if(t&&(n||r||i!==void 0||a))return{ok:!1,error:`url is mutually exclusive with explicit scheme/host/port/path inputs`};let o=`ws`,s=n,c=i??void 0,m=J(r),h;if(t){let e;try{e=new URL(t)}catch(e){return{ok:!1,error:`Invalid url: ${O(e)}`}}if(e.protocol!==`ws:`&&e.protocol!==`wss:`)return{ok:!1,error:`url must use ws:// or wss:// protocol`};o=e.protocol===`wss:`?`wss`:`ws`,s=e.hostname,c=e.port.length>0?Number(e.port):o===`wss`?443:80,m=J(`${e.pathname}${e.search}`),h=`${o}://${e.host}${m}`}else{if(!s)return{ok:!1,error:`host or url is required`};if(a){if(a!==`ws`&&a!==`wss`)return{ok:!1,error:`scheme must be ws or wss`};o=a}c??=o===`wss`?443:80;let e=c===(o===`wss`?443:80)?s:`${s}:${String(c)}`;h=`${o}://${e}${m}`}if(!s||!c||!Number.isInteger(c)||c<1||c>65535)return{ok:!1,error:`port must be an integer between 1 and 65535`};let g=f(e,`timeoutMs`)??5e3;if(!Number.isFinite(g)||g<=0)return{ok:!1,error:`timeoutMs must be a positive number`};let _=[...new Set(d(e,`subprotocols`).map(e=>e.trim()))].filter(e=>e.length>0),y=j(s);if(y)return y;let b=p(e,`allowInvalidCertificates`)??!1,x=p(e,`skipHostnameCheck`)??!1,C=l(e,`servername`)?.trim()??null,k=[...new Set(d(e,`alpnProtocols`).map(e=>e.trim()))].filter(e=>e.length>0),A,I;try{A=u(e,`minVersion`,D),I=u(e,`maxVersion`,D)}catch(e){return{ok:!1,error:O(e)}}if(A&&I&&_e.indexOf(A)>_e.indexOf(I))return{ok:!1,error:`minVersion must not be greater than maxVersion`};let R=o===`wss`?await F(e):{ok:!0,ca:void 0,source:null,path:null,bytes:null};if(!R.ok)return{ok:!1,error:R.error};let B={scheme:o,url:h,host:s,port:c,path:m,requestedServername:o===`wss`?C??(w(s)===0?s:void 0)??null:null,validationTarget:o===`wss`?C??s:null},V=v(16).toString(`base64`),W=re(V),G=Date.now();return new Promise(e=>{let t=!1,n=Buffer.alloc(0),r=null,i=null,a=null,l=o===`wss`?E(P({host:s,port:c,servername:B.requestedServername??void 0,...A?{minVersion:A}:{},...I?{maxVersion:I}:{},...k.length>0?{ALPNProtocols:k}:{},...R.ca?{ca:R.ca}:{}},b)):new S,u=n=>{t||(t=!0,clearTimeout(f),l.off(`error`,p),l.off(`connect`,v),l.off(`secureConnect`,y),l.off(`data`,C),e(n))},d=()=>{let e=c===(o===`wss`?443:80)?s:`${s}:${String(c)}`,t=[`GET ${m} HTTP/1.1`,`Host: ${e}`,`Upgrade: websocket`,`Connection: Upgrade`,`Sec-WebSocket-Key: ${V}`,`Sec-WebSocket-Version: 13`];return _.length>0&&t.push(`Sec-WebSocket-Protocol: ${_.join(`, `)}`),t.push(``,``),Buffer.from(t.join(`\r
2
+ `),`utf8`)},f=setTimeout(()=>{l.destroy(),u({ok:!1,error:`WebSocket open timed out`,target:B})},g),p=e=>{u({ok:!1,error:e.message,errorCode:e.code??null,target:B})},h=()=>{l.write(d())},v=()=>{l instanceof S&&l.setNoDelay(!0),r={...U(l),protocol:null,alpnProtocol:null,servernameSent:null,sessionReused:null},h()},y=()=>{let e=l,t=e.getPeerCertificate(!0),n=L(t),o=n?z(t):[],s=o[0]??null,c=x||!n||!B.validationTarget?void 0:T(B.validationTarget,t),d={checked:!x,target:x?null:B.validationTarget,matched:x?null:c===void 0,error:!x&&!n?`Peer certificate was not presented by the server`:c?.message??null},f=[e.authorized?`Certificate chain validated against the active trust store.`:`Certificate chain validation failed: ${e.authorizationError??`unknown_authority`}`,x?`Hostname validation was skipped by request.`:d.matched?`Hostname validation passed.`:`Hostname validation failed: ${d.error??`unknown_error`}`,!e.authorized&&b?`Policy allowed the session to continue despite certificate trust failure.`:null].filter(e=>!!e);if(i={socketAuthorized:e.authorized,authorizationError:typeof e.authorizationError==`string`?e.authorizationError:e.authorizationError?.message??null,hostnameValidation:d,policyAllowed:(e.authorized||b)&&(x||d.matched===!0),reasons:f},a={leaf:s,chain:o},r={...U(e),protocol:e.getProtocol()??null,alpnProtocol:N(e.alpnProtocol),servernameSent:M(e.servername),sessionReused:e.isSessionReused()},!i.policyAllowed){e.destroy(),u({ok:!1,error:`WebSocket TLS authorization failed`,target:B,authorization:i,certificates:a});return}h()},C=e=>{n=Buffer.concat([n,e]);let t=n.indexOf(`\r
3
3
  \r
4
4
  `);if(t<0)return;let d=n.subarray(0,t).toString(`utf8`).split(`\r
5
- `),f=d.shift()??``;if(!/^HTTP\/1\.1 101\b/.test(f)){l.destroy(),u({ok:!1,error:`Unexpected WebSocket upgrade response: ${f}`,target:B});return}let p=new Map;for(let e of d){let t=e.indexOf(`:`);if(t<=0)continue;let n=e.slice(0,t).trim().toLowerCase(),r=e.slice(t+1).trim();p.set(n,r)}let h=p.get(`upgrade`)?.toLowerCase()??``,g=p.get(`connection`)?.toLowerCase()??``,v=p.get(`sec-websocket-accept`)??null;if(h!==`websocket`){l.destroy(),u({ok:!1,error:`Upgrade header did not confirm websocket`,target:B});return}if(!g.split(`,`).map(e=>e.trim()).includes(`upgrade`)){l.destroy(),u({ok:!1,error:`Connection header did not confirm upgrade`,target:B});return}if(v!==W){l.destroy(),u({ok:!1,error:`sec-websocket-accept did not match the client key`,target:B});return}let y=p.get(`sec-websocket-protocol`)??null;if(y&&!_.includes(y)){l.destroy(),u({ok:!1,error:`Server selected unexpected subprotocol "${y}"`,target:B});return}let b=H(`websocket`),x={id:b,kind:`websocket`,scheme:o,socket:l,host:s,port:c,path:m,createdAt:Date.now(),parserBuffer:n.subarray(t+4),frames:[],ended:!1,closed:!1,error:null,waiters:new Set,activeRead:!1,closeSent:!1,closeReceived:!1,metadata:{target:B,handshake:{requestKey:V,acceptKey:W,responseAcceptKey:v,subprotocol:y},transport:r??{...U(l),protocol:null,alpnProtocol:null,servernameSent:null,sessionReused:null},authorization:i,certificates:a}};this.attachWebSocketSession(x),this.websocketSessions.set(b,x),this.emitWebSocketEvent(`websocket:session_opened`,{sessionId:b,scheme:o,host:s,port:c,path:m,timestamp:new Date().toISOString()}),u({ok:!0,sessionId:b,kind:x.kind,scheme:o,target:B,handshake:x.metadata.handshake,transport:x.metadata.transport,authorization:x.metadata.authorization,certificates:x.metadata.certificates,timing:{handshakeMs:Date.now()-G},state:q(x)})};l.once(`error`,p),l.on(`data`,C),o===`wss`?l.once(`secureConnect`,y):(l.once(`connect`,v),l.connect(c,s))})}async handleBypassCertPinning(t){if(this.extensionInvoke)try{let n=await this.extensionInvoke(t);if(n)return e({success:!0,strategy:`frida-injection`,result:n})}catch{}return e({success:!0,strategy:`manual-bypass`,instructions:{android:[`Use Frida to hook X509TrustManager.checkServerTrusted and return without throwing.`,`Alternatively, use OkHttp CertificatePinner.Builder().add() with the target cert.`],ios:[`Hook SecTrustEvaluateWithError to always return true.`,`Or use SSLSetSessionOption to disable certificate validation.`],desktop:[`Set NODE_TLS_REJECT_UNAUTHORIZED=0 for Node.js targets.`,`Or patch the certificate comparison function in the HTTP client.`]},args:t})}},ye=class extends ve{async handleRawTcpSend(e){let t=l(e,`host`)??`127.0.0.1`,n=f(e,`port`);if(n===void 0||n<1||n>65535)return{ok:!1,error:`port must be a number between 1 and 65535`};let r=j(t);if(r)return r;let i=l(e,`dataHex`),a=l(e,`dataText`);if(!i&&!a)return{ok:!1,error:`dataHex or dataText is required`};let o=i?Buffer.from(k(i),`hex`):Buffer.from(a??``,`utf8`),s=f(e,`timeout`)??5e3;return new Promise(e=>{let r=new x,i=setTimeout(()=>{r.destroy(),e({ok:!1,error:`Connection timed out`})},s);r.on(`connect`,()=>{r.write(o,()=>{r.end()})}),r.on(`data`,a=>{clearTimeout(i),e({ok:!0,host:t,port:n,sentBytes:o.length,responseHex:a.toString(`hex`).toUpperCase(),responseText:a.toString(`utf8`)}),r.destroy()}),r.on(`error`,t=>{clearTimeout(i),e({ok:!1,error:t.message})}),r.connect(n,t)})}async handleRawTcpListen(e){let t=f(e,`port`);if(t===void 0||t<1||t>65535)return{ok:!1,error:`port must be a number between 1 and 65535`};let n=f(e,`timeout`)??1e4;return new Promise(e=>{let r=S(),i=setTimeout(()=>{r.close(),e({ok:!1,error:`Listen timed out - no connection received`})},n);r.on(`connection`,n=>{clearTimeout(i);let a=[];n.on(`data`,e=>{a.push(e)}),n.on(`end`,()=>{let n=Buffer.concat(a);r.close(),e({ok:!0,port:t,receivedBytes:n.length,dataHex:n.toString(`hex`).toUpperCase(),dataText:n.toString(`utf8`)})}),n.on(`error`,t=>{clearTimeout(i),r.close(),e({ok:!1,error:t.message})})}),r.on(`error`,t=>{clearTimeout(i),e({ok:!1,error:t.message})}),r.listen(t,`127.0.0.1`)})}async handleRawUdpSend(e){let t=l(e,`host`)??`127.0.0.1`,n=f(e,`port`);if(n===void 0||n<1||n>65535)return{ok:!1,error:`port must be a number between 1 and 65535`};let r=j(t);if(r)return r;let i=l(e,`dataHex`),a=l(e,`dataText`);if(!i&&!a)return{ok:!1,error:`dataHex or dataText is required`};let o=i?Buffer.from(k(i),`hex`):Buffer.from(a??``,`utf8`),s=f(e,`timeout`)??5e3;return new Promise(e=>{let r=w(`udp4`),i=setTimeout(()=>{r.close(),e({ok:!1,error:`UDP response timed out`})},s);r.on(`message`,a=>{clearTimeout(i),r.close(),e({ok:!0,host:t,port:n,sentBytes:o.length,responseHex:a.toString(`hex`).toUpperCase(),responseText:a.toString(`utf8`)})}),r.on(`error`,t=>{clearTimeout(i),r.close(),e({ok:!1,error:t.message})}),r.send(o,0,o.length,n,t)})}async handleRawUdpListen(e){let t=f(e,`port`);if(t===void 0||t<1||t>65535)return{ok:!1,error:`port must be a number between 1 and 65535`};let n=f(e,`timeout`)??1e4;return new Promise(e=>{let r=w(`udp4`),i=setTimeout(()=>{r.close(),e({ok:!1,error:`UDP listen timed out`})},n);r.on(`message`,(n,a)=>{clearTimeout(i),r.close(),e({ok:!0,localPort:t,receivedBytes:n.length,from:a,dataHex:n.toString(`hex`).toUpperCase(),dataText:n.toString(`utf8`)})}),r.on(`error`,t=>{clearTimeout(i),r.close(),e({ok:!1,error:t.message})}),r.bind(t,`127.0.0.1`)})}},be=class extends ye{};export{be as BoringsslInspectorHandlers};
5
+ `),f=d.shift()??``;if(!/^HTTP\/1\.1 101\b/.test(f)){l.destroy(),u({ok:!1,error:`Unexpected WebSocket upgrade response: ${f}`,target:B});return}let p=new Map;for(let e of d){let t=e.indexOf(`:`);if(t<=0)continue;let n=e.slice(0,t).trim().toLowerCase(),r=e.slice(t+1).trim();p.set(n,r)}let h=p.get(`upgrade`)?.toLowerCase()??``,g=p.get(`connection`)?.toLowerCase()??``,v=p.get(`sec-websocket-accept`)??null;if(h!==`websocket`){l.destroy(),u({ok:!1,error:`Upgrade header did not confirm websocket`,target:B});return}if(!g.split(`,`).map(e=>e.trim()).includes(`upgrade`)){l.destroy(),u({ok:!1,error:`Connection header did not confirm upgrade`,target:B});return}if(v!==W){l.destroy(),u({ok:!1,error:`sec-websocket-accept did not match the client key`,target:B});return}let y=p.get(`sec-websocket-protocol`)??null;if(y&&!_.includes(y)){l.destroy(),u({ok:!1,error:`Server selected unexpected subprotocol "${y}"`,target:B});return}let b=H(`websocket`),x={id:b,kind:`websocket`,scheme:o,socket:l,host:s,port:c,path:m,createdAt:Date.now(),parserBuffer:n.subarray(t+4),frames:[],ended:!1,closed:!1,error:null,waiters:new Set,activeRead:!1,closeSent:!1,closeReceived:!1,metadata:{target:B,handshake:{requestKey:V,acceptKey:W,responseAcceptKey:v,subprotocol:y},transport:r??{...U(l),protocol:null,alpnProtocol:null,servernameSent:null,sessionReused:null},authorization:i,certificates:a}};this.attachWebSocketSession(x),this.websocketSessions.set(b,x),this.emitWebSocketEvent(`websocket:session_opened`,{sessionId:b,scheme:o,host:s,port:c,path:m,timestamp:new Date().toISOString()}),u({ok:!0,sessionId:b,kind:x.kind,scheme:o,target:B,handshake:x.metadata.handshake,transport:x.metadata.transport,authorization:x.metadata.authorization,certificates:x.metadata.certificates,timing:{handshakeMs:Date.now()-G},state:q(x)})};l.once(`error`,p),l.on(`data`,C),o===`wss`?l.once(`secureConnect`,y):(l.once(`connect`,v),l.connect(c,s))})}async handleBypassCertPinning(t){if(this.extensionInvoke)try{let n=await this.extensionInvoke(t);if(n)return e({success:!0,strategy:`frida-injection`,result:n})}catch{}return e({success:!0,strategy:`manual-bypass`,instructions:{android:[`Use Frida to hook X509TrustManager.checkServerTrusted and return without throwing.`,`Alternatively, use OkHttp CertificatePinner.Builder().add() with the target cert.`],ios:[`Hook SecTrustEvaluateWithError to always return true.`,`Or use SSLSetSessionOption to disable certificate validation.`],desktop:[`Set NODE_TLS_REJECT_UNAUTHORIZED=0 for Node.js targets.`,`Or patch the certificate comparison function in the HTTP client.`]},args:t})}},ye=class extends ve{async handleRawTcpSend(e){let t=l(e,`host`)??`127.0.0.1`,n=f(e,`port`);if(n===void 0||n<1||n>65535)return{ok:!1,error:`port must be a number between 1 and 65535`};let r=j(t);if(r)return r;let i=l(e,`dataHex`),a=l(e,`dataText`);if(!i&&!a)return{ok:!1,error:`dataHex or dataText is required`};let o=i?Buffer.from(k(i),`hex`):Buffer.from(a??``,`utf8`),s=f(e,`timeout`)??5e3;return new Promise(e=>{let r=new S,i=setTimeout(()=>{r.destroy(),e({ok:!1,error:`Connection timed out`})},s);r.on(`connect`,()=>{r.write(o,()=>{r.end()})}),r.on(`data`,a=>{clearTimeout(i),e({ok:!0,host:t,port:n,sentBytes:o.length,responseHex:a.toString(`hex`).toUpperCase(),responseText:a.toString(`utf8`)}),r.destroy()}),r.on(`error`,t=>{clearTimeout(i),e({ok:!1,error:t.message})}),r.connect(n,t)})}async handleRawTcpListen(e){let t=f(e,`port`);if(t===void 0||t<1||t>65535)return{ok:!1,error:`port must be a number between 1 and 65535`};let n=f(e,`timeout`)??1e4;return new Promise(e=>{let r=C(),i=setTimeout(()=>{r.close(),e({ok:!1,error:`Listen timed out - no connection received`})},n);r.on(`connection`,n=>{clearTimeout(i);let a=[];n.on(`data`,e=>{a.push(e)}),n.on(`end`,()=>{let n=Buffer.concat(a);r.close(),e({ok:!0,port:t,receivedBytes:n.length,dataHex:n.toString(`hex`).toUpperCase(),dataText:n.toString(`utf8`)})}),n.on(`error`,t=>{clearTimeout(i),r.close(),e({ok:!1,error:t.message})})}),r.on(`error`,t=>{clearTimeout(i),e({ok:!1,error:t.message})}),r.listen(t,`127.0.0.1`)})}async handleRawUdpSend(e){let t=l(e,`host`)??`127.0.0.1`,n=f(e,`port`);if(n===void 0||n<1||n>65535)return{ok:!1,error:`port must be a number between 1 and 65535`};let r=j(t);if(r)return r;let i=l(e,`dataHex`),a=l(e,`dataText`);if(!i&&!a)return{ok:!1,error:`dataHex or dataText is required`};let o=i?Buffer.from(k(i),`hex`):Buffer.from(a??``,`utf8`),s=f(e,`timeout`)??5e3;return new Promise(e=>{let r=x(`udp4`),i=setTimeout(()=>{r.close(),e({ok:!1,error:`UDP response timed out`})},s);r.on(`message`,a=>{clearTimeout(i),r.close(),e({ok:!0,host:t,port:n,sentBytes:o.length,responseHex:a.toString(`hex`).toUpperCase(),responseText:a.toString(`utf8`)})}),r.on(`error`,t=>{clearTimeout(i),r.close(),e({ok:!1,error:t.message})}),r.send(o,0,o.length,n,t)})}async handleRawUdpListen(e){let t=f(e,`port`);if(t===void 0||t<1||t>65535)return{ok:!1,error:`port must be a number between 1 and 65535`};let n=f(e,`timeout`)??1e4;return new Promise(e=>{let r=x(`udp4`),i=setTimeout(()=>{r.close(),e({ok:!1,error:`UDP listen timed out`})},n);r.on(`message`,(n,a)=>{clearTimeout(i),r.close(),e({ok:!0,localPort:t,receivedBytes:n.length,from:a,dataHex:n.toString(`hex`).toUpperCase(),dataText:n.toString(`utf8`)})}),r.on(`error`,t=>{clearTimeout(i),r.close(),e({ok:!1,error:t.message})}),r.bind(t,`127.0.0.1`)})}},be=class extends ye{};export{be as BoringsslInspectorHandlers};
@@ -1,4 +1,4 @@
1
- import{an as e,cn as t,ln as n,on as r,sn as i}from"./constants-Cp6hBrrx.mjs";import{n as a}from"./response-C7rKQst4.mjs";import{i as o,o as s,s as c}from"./parse-args-Cuk7-xUt.mjs";import{readFile as l,writeFile as u}from"node:fs/promises";import{isIP as d}from"node:net";const f={20:`ChangeCipherSpec`,21:`Alert`,22:`Handshake`,23:`ApplicationData`},p={"0300":`SSL 3.0`,"0301":`TLS 1.0`,"0302":`TLS 1.1`,"0303":`TLS 1.2`,"0304":`TLS 1.3`},ee={1301:`TLS_AES_128_GCM_SHA256`,1302:`TLS_AES_256_GCM_SHA384`,1303:`TLS_CHACHA20_POLY1305_SHA256`,c02b:`TLS_ECDHE_ECDSA_AES_128_GCM_SHA256`,c02f:`TLS_ECDHE_RSA_AES_128_GCM_SHA256`,c02c:`TLS_ECDHE_ECDSA_AES_256_GCM_SHA384`,c030:`TLS_ECDHE_RSA_AES_256_GCM_SHA384`,cca9:`TLS_ECDHE_ECDSA_CHACHA20_POLY1305`,cca8:`TLS_ECDHE_RSA_CHACHA20_POLY1305`,"009c":`TLS_RSA_AES_128_GCM_SHA256`,"009d":`TLS_RSA_AES_256_GCM_SHA384`,"002f":`TLS_RSA_AES_128_CBC_SHA`,"0035":`TLS_RSA_AES_256_CBC_SHA`,c013:`TLS_ECDHE_RSA_AES_128_CBC_SHA`,c014:`TLS_ECDHE_RSA_AES_256_CBC_SHA`,"00ff":`TLS_EMPTY_RENEGOTIATION_INFO_SCSV`,5600:`TLS_FALLBACK_SCSV`},m={0:`NOERROR`,1:`FORMERR`,2:`SERVFAIL`,3:`NXDOMAIN`,4:`NOTIMP`,5:`REFUSED`},h={0:`QUERY`,1:`IQUERY`,2:`STATUS`,3:`UNASSIGNED`,4:`NOTIFY`,5:`UPDATE`},g={474554:`GET`,"504f5354":`POST`,505554:`PUT`,"44454c45":`DELETE`,48454144:`HEAD`,50415443:`PATCH`,"4f505449":`OPTIONS`,"434f4e4e":`CONNECT`},_={"0000":`server_name`,"000a":`supported_groups`,"000b":`ec_point_formats`,"000d":`signature_algorithms`,"0010":`application_layer_protocol_negotiation`,"0015":`padding`,"0017":`extended_master_secret`,"001b":`compress_certificate`,"0023":`session_ticket`,"0029":`pre_shared_key`,"002b":`supported_versions`,"002d":`psk_key_exchange_modes`,"0033":`key_share`,"0039":`quic_transport_parameters`,4469:`next_protocol_negotiation`,fe0d:`encrypted_client_hello`,ff01:`renegotiation_info`},te={0:`continuation`,1:`text`,2:`binary`,8:`close`,9:`ping`,10:`pong`};function v(e,t){return Number.parseInt(e.substring(t*2,t*2+2),16)}function y(e,t){return Number.parseInt(e.substring(t*2,t*2+4),16)}function b(e,t,n){return e.substring(t*2,(t+n)*2)}function x(e){return e.length>=24&&/^0{24}$/i.test(e.slice(0,24))}function ne(e){if(e.length<44)return null;let t=v(e,0);if(t!==22)return null;let n=b(e,1,2),r=y(e,3);if(e.length/2<5+r||v(e,5)!==1)return null;let i={recordType:f[t]??`0x${t.toString(16)}`,recordVersion:p[n]??n,recordLength:r,handshakeType:`ClientHello`},a=9;if(a+2>e.length/2)return i;let o=b(e,a,2);if(i.clientVersion=p[o]??o,a+=34,a>=e.length/2)return i;let s=v(e,a);if(a+=1+s,a+2>e.length/2)return i;let c=y(e,a);a+=2;let l=[];for(let t=0;t<c/2&&a+2<=e.length/2;t++){let t=b(e,a,2).toLowerCase();l.push({hex:t,name:ee[t]??`Unknown(0x${t})`}),a+=2}if(i.cipherSuites=l,i.cipherSuiteCount=l.length,a>=e.length/2)return i;let u=v(e,a);if(a+=1+u,a+2>e.length/2)return i;let d=y(e,a);a+=2;let m=a+d,h=[];for(;a+4<=m&&a+4<=e.length/2;){let t=b(e,a,2).toLowerCase(),n=y(e,a+2);h.push({type:t,length:n,name:_[t]}),a+=4+n}return i.extensions=h,i.extensionCount=h.length,i}function re(e){if(e.length<24)return null;let t=y(e,0),n=v(e,2),r=v(e,3),i=n>>7&1,a=n>>3&15,o=n>>2&1,s=n>>1&1,c=n&1,l=r>>7&1,u=r>>4&7,d=r&15;return{transactionId:`0x${t.toString(16).padStart(4,`0`)}`,flags:{qr:i===1?`Response`:`Query`,opcode:h[a]??a,authoritativeAnswer:!!o,truncation:!!s,recursionDesired:!!c,recursionAvailable:!!l,reserved:u,responseCode:m[d]??d},questionCount:y(e,4),answerCount:y(e,6),authorityCount:y(e,8),additionalCount:y(e,10)}}function ie(e){if(e.length<24||x(e))return!1;let t=v(e,2),n=v(e,3),r=t>>7&1,i=t>>3&15,a=n&15,o=y(e,4),s=y(e,6);return!(i>2||o+s===0||r===0&&a!==0||r===1&&a>5)}function S(e){return typeof e==`object`&&!!e&&!Array.isArray(e)}function ae(e,t){if(!S(e))throw Error(`fields[${t}] must be an object`);let n=e.name,r=e.offset,i=e.length,a=e.type;if(typeof n!=`string`||n.trim().length===0)throw Error(`fields[${t}].name must be a non-empty string`);if(typeof r!=`number`||!Number.isInteger(r)||r<0)throw Error(`fields[${t}].offset must be a non-negative integer`);if(typeof i!=`number`||!Number.isInteger(i)||i<=0)throw Error(`fields[${t}].length must be a positive integer`);if(a!==`int`&&a!==`string`&&a!==`bytes`&&a!==`bool`&&a!==`float`)throw Error(`fields[${t}].type is invalid`);return{name:n,offset:r,length:i,type:a}}function oe(e,t){if(!S(e))throw Error(`fields[${t}] must be an object`);let n=e.name,r=e.offset,i=e.length,a=e.type,o=e.description;if(typeof n!=`string`||n.trim().length===0)throw Error(`fields[${t}].name must be a non-empty string`);if(typeof r!=`number`||!Number.isInteger(r)||r<0)throw Error(`fields[${t}].offset must be a non-negative integer`);if(typeof i!=`number`||!Number.isInteger(i)||i<=0)throw Error(`fields[${t}].length must be a positive integer`);if(a!==`uint8`&&a!==`uint16`&&a!==`uint32`&&a!==`int64`&&a!==`float`&&a!==`string`&&a!==`bytes`)throw Error(`fields[${t}].type is invalid`);return{name:n,offset:r,length:i,type:a,...typeof o==`string`?{description:o}:{}}}function se(e,t){let n=t.fields;if(!Array.isArray(n))throw Error(`spec.fields must be an array`);let r=typeof t.fieldDelimiter==`string`&&t.fieldDelimiter.length>0?t.fieldDelimiter:void 0,i=t.byteOrder,a=i===`le`||i===`be`?i:void 0;return{name:e,...r?{fieldDelimiter:r}:{},...a?{byteOrder:a}:{},fields:n.map((e,t)=>ae(e,t))}}function ce(e){if(!S(e))return;let t=e.type;if(t!==`aes`&&t!==`xor`&&t!==`rc4`&&t!==`custom`)return;let n=typeof e.key==`string`?e.key:void 0,r=typeof e.iv==`string`?e.iv:void 0,i=typeof e.notes==`string`?e.notes:void 0;return{type:t,...n?{key:n}:{},...r?{iv:r}:{},...i?{notes:i}:{}}}function le(e,t){if(!S(e))throw Error(`messages[${t}] must be an object`);let n=e.direction,r=e.timestamp,i=e.fields,a=e.raw;if(n!==`req`&&n!==`res`)throw Error(`messages[${t}].direction must be "req" or "res"`);if(typeof r!=`number`||!Number.isFinite(r))throw Error(`messages[${t}].timestamp must be a number`);if(!S(i))throw Error(`messages[${t}].fields must be an object`);if(typeof a!=`string`)throw Error(`messages[${t}].raw must be a string`);return{direction:n,timestamp:r,fields:i,raw:a}}const ue=[`utf8`,`ascii`],C=[`utf8`,`ascii`,`hex`,`base64`],de=[`u8`,`u16`,`u32`,`i8`,`i16`,`i32`,`string`,`bytes`],fe=[`set_byte`,`flip_bit`,`overwrite_bytes`,`append_bytes`,`truncate`,`increment_integer`];function w(e,t=`big`){return e===`little`?`little`:t}function T(e,t){if(typeof e!=`number`||!Number.isInteger(e)||e<0)throw Error(`${t} must be a non-negative integer`);return e}function E(e,t){if(typeof e!=`number`||!Number.isInteger(e)||e<=0)throw Error(`${t} must be a positive integer`);return e}function D(e,t){if(typeof e!=`number`||!Number.isInteger(e))throw Error(`${t} must be an integer`);return e}function O(e,t){let n=D(e,t);if(n<0||n>255)throw Error(`${t} must be between 0 and 255`);return n}function pe(e,t){return e===void 0?void 0:E(e,t)}function k(e,t,n,r){if(e===void 0)return n;if(typeof e!=`string`||!t.includes(e))throw Error(`${r} is invalid`);return e}function A(e,t){if(typeof e!=`string`)throw Error(`${t} must be a string`);return e}function j(e,t){let n=e.replace(/^0x/i,``).replace(/\s+/g,``);if(n.length===0)return n;if(n.length%2!=0||/[^0-9a-f]/i.test(n))throw Error(`${t} must be a valid even-length hex string`);return n.toLowerCase()}function M(e,t,n){switch(t){case`utf8`:case`ascii`:return Buffer.from(e,t);case`hex`:return Buffer.from(j(e,n),`hex`);case`base64`:return Buffer.from(e,`base64`)}}function me(e,t){let n=e*8;return t?{min:-(2**(n-1)),max:2**(n-1)-1}:{min:0,max:2**n-1}}function N(e){switch(e){case`u8`:return{width:1,signed:!1};case`u16`:return{width:2,signed:!1};case`u32`:return{width:4,signed:!1};case`i8`:return{width:1,signed:!0};case`i16`:return{width:2,signed:!0};case`i32`:return{width:4,signed:!0};default:return null}}function P(e,t,n,r,i){if(r)switch(n){case 1:e.writeInt8(t,0);return;case 2:i===`little`?e.writeInt16LE(t,0):e.writeInt16BE(t,0);return;case 4:i===`little`?e.writeInt32LE(t,0):e.writeInt32BE(t,0);return}switch(n){case 1:e.writeUInt8(t,0);return;case 2:i===`little`?e.writeUInt16LE(t,0):e.writeUInt16BE(t,0);return;case 4:i===`little`?e.writeUInt32LE(t,0):e.writeUInt32BE(t,0);return}}function he(e,t,n,r,i){if(r)switch(n){case 1:return e.readInt8(t);case 2:return i===`little`?e.readInt16LE(t):e.readInt16BE(t);case 4:return i===`little`?e.readInt32LE(t):e.readInt32BE(t)}switch(n){case 1:return e.readUInt8(t);case 2:return i===`little`?e.readUInt16LE(t):e.readUInt16BE(t);case 4:return i===`little`?e.readUInt32LE(t):e.readUInt32BE(t)}}function F(e,t,n){return t===void 0||e.length===t?e:e.length>t?e.subarray(0,t):Buffer.concat([e,Buffer.alloc(t-e.length,n)])}function ge(e,t){if(!S(e))throw Error(`fields[${t}] must be an object`);let n=e.name,r=e.type,i=e.value;if(typeof n!=`string`||n.trim().length===0)throw Error(`fields[${t}].name must be a non-empty string`);if(typeof r!=`string`||!de.includes(r))throw Error(`fields[${t}].type is invalid`);let a=r,o=N(a);if(o){let s=D(i,`fields[${t}].value`),c=me(o.width,o.signed);if(s<c.min||s>c.max)throw Error(`fields[${t}].value is out of range for ${r} (${c.min}..${c.max})`);if(e.length!==void 0||e.padByte!==void 0||e.encoding!==void 0)throw Error(`fields[${t}] does not support length, padByte, or encoding`);return{name:n,type:a,value:s}}let s=A(i,`fields[${t}].value`),c=pe(e.length,`fields[${t}].length`),l=e.padByte===void 0?0:O(e.padByte,`fields[${t}].padByte`);return r===`string`?{name:n,type:`string`,value:s,encoding:k(e.encoding,ue,`utf8`,`fields[${t}].encoding`),...c===void 0?{}:{length:c},padByte:l}:{name:n,type:`bytes`,value:s,encoding:k(e.encoding,C,`hex`,`fields[${t}].encoding`),...c===void 0?{}:{length:c},padByte:l}}function _e(e,t){switch(e.type){case`u8`:case`u16`:case`u32`:case`i8`:case`i16`:case`i32`:{let n=N(e.type);if(!n)throw Error(`Unsupported numeric field type: ${e.type}`);let r=Buffer.alloc(n.width);return P(r,e.value,n.width,n.signed,t),r}case`string`:return F(Buffer.from(e.value,e.encoding),e.length,e.padByte);case`bytes`:return F(M(e.value,e.encoding,`field ${e.name}`),e.length,e.padByte)}}function ve(e,t){let n=[],r=[],i=0;for(let a of e){let e=_e(a,t);n.push(e),r.push({name:a.name,offset:i,length:e.length,hex:e.toString(`hex`)}),i+=e.length}return{payload:Buffer.concat(n),segments:r}}function ye(e,t){if(!S(e))throw Error(`mutations[${t}] must be an object`);let n=e.strategy;if(typeof n!=`string`||!fe.includes(n))throw Error(`mutations[${t}].strategy is invalid`);switch(n){case`set_byte`:return{strategy:`set_byte`,offset:T(e.offset,`mutations[${t}].offset`),value:O(e.value,`mutations[${t}].value`)};case`flip_bit`:return{strategy:`flip_bit`,offset:T(e.offset,`mutations[${t}].offset`),bit:(()=>{let n=D(e.bit,`mutations[${t}].bit`);if(n<0||n>7)throw Error(`mutations[${t}].bit must be between 0 and 7`);return n})()};case`overwrite_bytes`:return{strategy:`overwrite_bytes`,offset:T(e.offset,`mutations[${t}].offset`),data:M(A(e.data,`mutations[${t}].data`),k(e.encoding,C,`hex`,`mutations[${t}].encoding`),`mutations[${t}].data`)};case`append_bytes`:return{strategy:`append_bytes`,data:M(A(e.data,`mutations[${t}].data`),k(e.encoding,C,`hex`,`mutations[${t}].encoding`),`mutations[${t}].data`)};case`truncate`:return{strategy:`truncate`,length:T(e.length,`mutations[${t}].length`)};case`increment_integer`:{let n=e.width;if(n!==1&&n!==2&&n!==4)throw Error(`mutations[${t}].width must be 1, 2, or 4`);return{strategy:`increment_integer`,offset:T(e.offset,`mutations[${t}].offset`),width:n,delta:D(e.delta,`mutations[${t}].delta`),endian:w(e.endian),signed:e.signed===!0}}}}function be(e,t,n){let r=Buffer.from(e);switch(t.strategy){case`set_byte`:if(t.offset>=r.length)throw Error(`mutations[${n}] offset is outside the payload`);return r[t.offset]=t.value,{payload:r,summary:{index:n,strategy:t.strategy,detail:`set payload[${t.offset}] to ${t.value}`}};case`flip_bit`:if(t.offset>=r.length)throw Error(`mutations[${n}] offset is outside the payload`);{let e=r[t.offset];r[t.offset]=e^1<<t.bit}return{payload:r,summary:{index:n,strategy:t.strategy,detail:`flipped bit ${t.bit} at offset ${t.offset}`}};case`overwrite_bytes`:if(t.offset+t.data.length>r.length)throw Error(`mutations[${n}] overwrite exceeds payload length`);return t.data.copy(r,t.offset),{payload:r,summary:{index:n,strategy:t.strategy,detail:`overwrote ${t.data.length} bytes at offset ${t.offset}`}};case`append_bytes`:return{payload:Buffer.concat([r,t.data]),summary:{index:n,strategy:t.strategy,detail:`appended ${t.data.length} bytes`}};case`truncate`:if(t.length>r.length)throw Error(`mutations[${n}] length exceeds payload size`);return{payload:r.subarray(0,t.length),summary:{index:n,strategy:t.strategy,detail:`truncated payload to ${t.length} bytes`}};case`increment_integer`:{if(t.offset+t.width>r.length)throw Error(`mutations[${n}] integer range exceeds payload length`);let e=he(r,t.offset,t.width,t.signed,t.endian)+t.delta,i=me(t.width,t.signed);if(e<i.min||e>i.max)throw Error(`mutations[${n}] integer overflow (${i.min}..${i.max})`);return P(r.subarray(t.offset,t.offset+t.width),e,t.width,t.signed,t.endian),{payload:r,summary:{index:n,strategy:t.strategy,detail:`incremented ${t.signed?`signed`:`unsigned`} ${t.width}-byte integer at offset ${t.offset} by ${t.delta}`}}}}}const xe=Object.freeze({arp:2054,ipv4:2048,ipv6:34525,vlan:33024}),Se=Object.freeze({icmp:1,igmp:2,tcp:6,udp:17,gre:47,esp:50,ah:51,icmpv6:58,ospf:89}),Ce=Object.freeze({loopback:0,ethernet:1,raw:101});function I(e,t,n,r){if(typeof e==`number`){if(!Number.isInteger(e)||e<0||e>r)throw Error(`${t} must be an integer between 0 and ${r}`);return e}if(typeof e!=`string`||e.trim().length===0)throw Error(`${t} must be a non-empty string or integer`);let i=e.trim().toLowerCase(),a=n[i];if(a!==void 0)return a;if(/^\d+$/.test(i)){let e=Number.parseInt(i,10);if(e>r)throw Error(`${t} must be less than or equal to ${r}`);return e}let o=j(i,t),s=Number.parseInt(o,16);if(s>r)throw Error(`${t} must be less than or equal to ${r}`);return s}function L(e,t){if(typeof e!=`string`||e.trim().length===0)throw Error(`${t} must be a non-empty MAC address string`);let n=e.trim().toLowerCase().replace(/^0x/,``).replace(/[:\-.\s]/g,``);if(!/^[0-9a-f]{12}$/i.test(n))throw Error(`${t} must be a valid 6-byte MAC address`);let r=n.match(/.{2}/g)?.join(`:`);if(!r)throw Error(`${t} must be a valid 6-byte MAC address`);return{canonical:r,bytes:Buffer.from(n,`hex`)}}function R(e,t){if(typeof e!=`string`||d(e.trim())!==4)throw Error(`${t} must be a valid IPv4 address`);let n=e.trim().split(`.`).map(e=>Number.parseInt(e,10));return Buffer.from(n)}function z(e,t){return e.length===0?[]:e.split(`:`).flatMap(e=>{if(e.length===0)return[];if(e.includes(`.`)){let n=R(e,t);return[n.readUInt16BE(0).toString(16),n.readUInt16BE(2).toString(16)]}if(!/^[0-9a-f]{1,4}$/i.test(e))throw Error(`${t} contains an invalid IPv6 group`);return[e]})}function we(e,t){if(typeof e!=`string`)throw Error(`${t} must be a valid IPv6 address`);let n=e.trim().toLowerCase().split(`%`)[0]??``;if(d(n)!==6)throw Error(`${t} must be a valid IPv6 address`);let r=n.split(`::`);if(r.length>2)throw Error(`${t} must be a valid IPv6 address`);let i=z(r[0]??``,t),a=z(r[1]??``,t),o=r.length===2?[...i,...Array.from({length:8-i.length-a.length},()=>`0`),...a]:i;if(o.length!==8)throw Error(`${t} must expand to exactly 8 IPv6 groups`);let s=Buffer.alloc(16);for(let[e,t]of o.entries())s.writeUInt16BE(Number.parseInt(t,16),e*2);return s}function B(e,t,n){return t===`ipv4`?R(e,n):we(e,n)}function V(e,t){return I(e,t,xe,65535)}function Te(e,t){return I(e,t,Se,255)}function Ee(e,t){return I(e,t,Ce,4294967295)}function De(e){return e===`little`?`little`:`big`}function Oe(e){return e===`big`?`big`:`little`}function ke(e){return e===`nano`?`nano`:`micro`}function H(e,t){if(typeof e!=`string`)throw Error(`${t} must be a hex string`);return Buffer.from(j(e,t),`hex`)}function U(e){let t=0;for(let n=0;n<e.length;n+=2){let r=e[n]??0,i=e[n+1]??0;for(t+=r<<8|i;t>65535;)t=(t&65535)+(t>>>16)}return~t&65535}function Ae(e,t,n,r){let i=Buffer.alloc(14);return e.bytes.copy(i,0),t.bytes.copy(i,6),i.writeUInt16BE(n,12),Buffer.concat([i,r])}function je(e){if(e.hardwareSize!==e.senderMac.bytes.length||e.hardwareSize!==e.targetMac.bytes.length)throw Error(`hardwareSize must match the provided MAC address lengths`);if(e.protocolSize!==e.senderIp.length||e.protocolSize!==e.targetIp.length)throw Error(`protocolSize must match the provided IP address lengths`);let t=Buffer.alloc(8+e.hardwareSize*2+e.protocolSize*2),n=0;return t.writeUInt16BE(e.hardwareType,n),n+=2,t.writeUInt16BE(e.protocolType,n),n+=2,t.writeUInt8(e.hardwareSize,n++),t.writeUInt8(e.protocolSize,n++),t.writeUInt16BE(e.operation===`reply`?2:1,n),n+=2,e.senderMac.bytes.copy(t,n),n+=e.hardwareSize,e.senderIp.copy(t,n),n+=e.protocolSize,e.targetMac.bytes.copy(t,n),n+=e.hardwareSize,e.targetIp.copy(t,n),t}function Me(e){let t=Buffer.alloc(20);t[0]=69,t[1]=(e.dscp&63)<<2|e.ecn&3,t.writeUInt16BE(t.length+e.payload.length,2),t.writeUInt16BE(e.identification,4);let n=!!e.dontFragment<<1|!!e.moreFragments;t.writeUInt16BE((n&7)<<13|e.fragmentOffset&8191,6),t[8]=e.ttl,t[9]=e.protocol,t.writeUInt16BE(0,10),e.sourceIp.copy(t,12),e.destinationIp.copy(t,16);let r=U(t);return t.writeUInt16BE(r,10),{packet:Buffer.concat([t,e.payload]),checksum:r}}function Ne(e){let t=Buffer.alloc(40),n=6<<28|(((e.dscp&63)<<2|e.ecn&3)&255)<<20|e.flowLabel&1048575;return t.writeUInt32BE(n>>>0,0),t.writeUInt16BE(e.payload.length,4),t.writeUInt8(e.protocol,6),t.writeUInt8(e.hopLimit,7),e.sourceIp.copy(t,8),e.destinationIp.copy(t,24),Buffer.concat([t,e.payload])}function Pe(e){let t=Buffer.alloc(8+e.payload.length);t[0]=e.operation===`reply`?0:8,t[1]=0,t.writeUInt16BE(0,2),t.writeUInt16BE(e.identifier,4),t.writeUInt16BE(e.sequenceNumber,6),e.payload.copy(t,8);let n=U(t);return t.writeUInt16BE(n,2),{packet:t,checksum:n}}function W(e,t,n,r){r===`little`?e.writeUInt32LE(n,t):e.writeUInt32BE(n,t)}function G(e,t,n,r){r===`little`?e.writeUInt16LE(n,t):e.writeUInt16BE(n,t)}function K(e,t,n){return n===`little`?e.readUInt32LE(t):e.readUInt32BE(t)}function q(e,t,n){return n===`little`?e.readUInt16LE(t):e.readUInt16BE(t)}function Fe(e,t){let n=e===`little`?t===`nano`?`4d3cb2a1`:`d4c3b2a1`:t===`nano`?`a1b23c4d`:`a1b2c3d4`;return Buffer.from(n,`hex`)}function Ie(e){if(e.length<24)throw Error(`PCAP file is too small to contain a global header`);let t=e.subarray(0,4).toString(`hex`),n,r;switch(t){case`d4c3b2a1`:n=`little`,r=`micro`;break;case`4d3cb2a1`:n=`little`,r=`nano`;break;case`a1b2c3d4`:n=`big`,r=`micro`;break;case`a1b23c4d`:n=`big`,r=`nano`;break;default:throw Error(`Unsupported capture format: only classic PCAP files are supported`)}return{endianness:n,timestampPrecision:r,versionMajor:q(e,4,n),versionMinor:q(e,6,n),snapLength:K(e,16,n),linkType:K(e,20,n)}}function Le(e,t){if(!S(e))throw Error(`packets[${t}] must be an object`);let n=H(e.dataHex,`packets[${t}].dataHex`),r=e.timestampSeconds===void 0?0:T(e.timestampSeconds,`packets[${t}].timestampSeconds`),i=e.timestampFraction===void 0?0:T(e.timestampFraction,`packets[${t}].timestampFraction`),a=e.originalLength===void 0?n.length:E(e.originalLength,`packets[${t}].originalLength`);if(a<n.length)throw Error(`packets[${t}].originalLength must be >= included packet length`);return{data:n,timestampSeconds:r,timestampFraction:i,originalLength:a}}function Re(e){let t=Buffer.alloc(24);Fe(e.endianness,e.timestampPrecision).copy(t,0),G(t,4,2,e.endianness),G(t,6,4,e.endianness),W(t,8,0,e.endianness),W(t,12,0,e.endianness),W(t,16,e.snapLength,e.endianness),W(t,20,e.linkType,e.endianness);let n=e.packets.map(t=>{let n=Buffer.alloc(16);return W(n,0,t.timestampSeconds,e.endianness),W(n,4,t.timestampFraction,e.endianness),W(n,8,t.data.length,e.endianness),W(n,12,t.originalLength,e.endianness),Buffer.concat([n,t.data])});return Buffer.concat([t,...n])}function ze(e,t,n){let r=Ie(e),i=[],a=24;for(;a<e.length&&!(t!==void 0&&i.length>=t);){if(a+16>e.length)throw Error(`PCAP file ends with an incomplete packet header`);let t=K(e,a,r.endianness),o=K(e,a+4,r.endianness),s=K(e,a+8,r.endianness),c=K(e,a+12,r.endianness);if(a+=16,a+s>e.length)throw Error(`PCAP file ends with an incomplete packet payload`);let l=e.subarray(a,a+s);a+=s;let u=n===void 0?l.length:n,d=Math.min(u,l.length);i.push({index:i.length,timestampSeconds:t,timestampFraction:o,includedLength:s,originalLength:c,dataHex:l.subarray(0,d).toString(`hex`),truncated:d<l.length})}return{header:r,packets:i}}const Be=[Buffer.from([44]),Buffer.from([124]),Buffer.from([58]),Buffer.from([59]),Buffer.from([9]),Buffer.from([0]),Buffer.from([13,10])];function J(e){return e.replace(/^0x/i,``).replace(/\s+/g,``).toLowerCase()}function Y(e){let t=J(e);return t.length===0||t.length%2!=0?!1:/^[0-9a-f]+$/i.test(t)}function X(e){return Y(e)?Buffer.from(J(e),`hex`):null}function Z(e){return e>=32&&e<=126}function Q(e){if(e.length===0)return 0;let t=0;for(let n of e.values())Z(n)&&(t+=1);return t/e.length}function Ve(e){return e.length===0?0:e.reduce((e,t)=>e+Q(t),0)/e.length}function He(e,t){if(t.length===0)return[e];let n=[],r=0,i=e.indexOf(t,r);for(;i>=0;)n.push(e.subarray(r,i)),r=i+t.length,i=e.indexOf(t,r);return n.push(e.subarray(r)),n}function Ue(e){return Q(e)===1?e.toString(`utf8`):e.toString(`hex`)}function We(e){let t=[];for(let n of e){let e=X(n);e&&t.push(e)}return t}function Ge(e,t){if(e.length===0)return null;if(e.length===1)return e.readUInt8(0);if(e.length===2)return t===`le`?e.readUInt16LE(0):e.readUInt16BE(0);if(e.length===4)return t===`le`?e.readUInt32LE(0):e.readUInt32BE(0);if(e.length===8){let n=Number(t===`le`?e.readBigUInt64LE(0):e.readBigUInt64BE(0));return Number.isFinite(n)?n:null}let n=0,r=t===`le`?[...e.values()].toReversed():[...e.values()];for(let e of r)n=n*256+e;return Number.isFinite(n)?n:null}function Ke(e,t){if(e.length===4){let n=t===`le`?e.readFloatLE(0):e.readFloatBE(0);return Number.isFinite(n)?n:null}if(e.length===8){let n=t===`le`?e.readDoubleLE(0):e.readDoubleBE(0);return Number.isFinite(n)?n:null}return null}function qe(e,t){if(t.length===0)return 0;let n=0,r=0,i=e.indexOf(t,r);for(;i>=0;)n+=1,r=i+t.length,i=e.indexOf(t,r);return n}function Je(e){return e.length===0?`bytes`:e.every(e=>e.length===1)&&e.every(e=>e[0]===0||e[0]===1)?`bool`:Ve(e)>=.7?`string`:e.every(e=>e.length===4)&&Ye(e)?`float`:e.every(e=>e.length<=4)?`int`:`bytes`}function Ye(e){let t=[];for(let n of e){let e=Ke(n,`be`);if(e===null)return!1;t.push(e)}return t.some(e=>Math.abs(e)>.001&&Math.abs(e)<1e6)}function Xe(e,t){let n=0,r=0;for(let i of e){let e=i[t];e!==void 0&&(n+=1,Z(e)&&(r+=1))}return n>0&&r/n>=.8}function Ze(e,t){let n=0;for(let r of e){let e=r[t];if(e!==void 0&&(n+=1,e!==0&&e!==1))return!1}return n>0}function Qe(e,t){if(t.length===0)return[];let n=e.map(e=>He(e,t)),r=n[0];if(!r||r.length<2)return[];let i=r.length;if(!n.every(e=>e.length===i))return[];let a=[],o=0;for(let e=0;e<i;e+=1){let i=r[e];if(!i)continue;let s=n.map(t=>t[e]).filter(e=>Buffer.isBuffer(e));a.push({name:`field_${e+1}`,offset:o,length:i.length,type:Je(s)}),o+=i.length+t.length}return a}function $e(e){let t=Math.min(...e.map(e=>e.length)),n=[],r=0;for(;r<t&&n.length<24;){if(Xe(e,r)){let i=r+1;for(;i<t&&Xe(e,i);)i+=1;n.push({name:`field_${n.length+1}`,offset:r,length:i-r,type:`string`}),r=i;continue}if(Ze(e,r)){n.push({name:`field_${n.length+1}`,offset:r,length:1,type:`bool`}),r+=1;continue}let i=t-r;if(i>=4&&Ye(e.map(e=>e.subarray(r,r+4)))){n.push({name:`field_${n.length+1}`,offset:r,length:4,type:`float`}),r+=4;continue}let a=i>=4?4:Math.min(i,2),o=e.map(e=>e.subarray(r,r+a));n.push({name:`field_${n.length+1}`,offset:r,length:a,type:Je(o)}),r+=a}return n}function et(e){for(let t of Be){let n=e.map(e=>qe(e,t)),r=n[0];if(typeof r==`number`&&r>=2&&n.every(e=>e===r))return Ue(t)}}function tt(e){let t=Math.min(...e.map(e=>e.length));if(t<2)return`be`;let n=0,r=0,i=Math.min(t-1,8);for(let t=0;t<i;t+=2){let i=0,a=0;for(let n of e){let e=n.readUInt16LE(t),r=n.readUInt16BE(t);e<4096&&(i+=1),r<4096&&(a+=1)}i>a?n+=1:a>i&&(r+=1)}return n>r?`le`:`be`}function nt(e,t){if(e.length===0||t.length<2)return e;let n=Math.min(...t.map(e=>e.length)),r=0;for(let e=0;e<n;e+=1){let n=t[0][e];if(t.every(t=>t[e]===n))r=e+1;else break}if(r===0)return e;let i=!1;return e.map(e=>!i&&e.offset===0&&r>=2?(i=!0,{...e,name:`magic`}):i&&e.type===`int`&&e.length<=2&&e.offset<=r?{...e,name:`version`}:e)}var rt=class{patterns=new Map;legacyPatterns=new Map;definePattern(e,t,n){let r=Array.isArray(t)?this.createLegacyPattern(e,t,n):this.createLegacyPatternFromSpec(e,t),i=this.createSpecFromLegacyPattern(r);if(this.patterns.set(e,i),this.legacyPatterns.set(e,r),Array.isArray(t))return r}detectPattern(e){let t=X(e);if(!t)return null;let n=null;for(let e of this.patterns.values()){let r=e.fields.length+ +!!e.fieldDelimiter;if(r===0)continue;let i=0;e.fieldDelimiter&&this.payloadContainsDelimiter(t,e.fieldDelimiter)&&(i+=1);for(let n of e.fields)this.matchesField(t,n,e.byteOrder??`be`)&&(i+=1);let a=Number((i/r).toFixed(2));if(a<=0)continue;let o={pattern:e,confidence:a,matches:i,total:r};(!n||o.confidence>n.confidence||o.confidence===n.confidence&&o.matches>n.matches)&&(n=o)}return n}autoDetect(e){let t=We(e);if(t.length===0)return null;let n=et(t),r=this.inferFields(e);return{name:`auto-detected-pattern`,fieldDelimiter:n,byteOrder:tt(t),fields:r}}inferFields(e){let t=We(e);if(t.length===0)return[];let n=et(t);if(n){let e=Qe(t,this.parseDelimiter(n));if(e.length>0)return nt(e,t)}return nt($e(t),t)}autoDetectPattern(e,t){let n=e.map(e=>e.toString(`hex`)),r=this.autoDetect(n),i=t?.name??r?.name??`auto_detected`;if(!r){let e=this.createLegacyPattern(i,[]);return this.patterns.set(i,this.createSpecFromLegacyPattern(e)),this.legacyPatterns.set(i,e),e}let a={...r,name:i};return this.definePattern(i,a),this.getPattern(i)??this.createLegacyPatternFromSpec(i,a)}getPattern(e){return this.legacyPatterns.get(e)}listPatterns(){return[...this.patterns.keys()]}exportProto(e){let t=this.isLegacyPattern(e)?e:this.createLegacyPatternFromSpec(e.name,e),n=[`// Protocol: ${t.name}`,`// Byte order: ${t.byteOrder}`,``];t.encryption&&(n.push(`// Encryption: ${t.encryption.type}`),t.encryption.notes&&n.push(`// Notes: ${t.encryption.notes}`),n.push(``)),n.push(`message ${this.toPascalCase(t.name)} {`);for(let e=0;e<t.fields.length;e+=1){let r=t.fields[e];if(!r)continue;let i=r.description?` // ${r.description}`:``;n.push(` ${this.toProtoType(r.type)} ${r.name} = ${e+1};${i}`)}return n.push(`}`),n.push(``),n.join(`
1
+ import{An as e,Dn as t,En as n,On as r,kn as i}from"./constants-BYj8Xek8.mjs";import{n as a}from"./response-C7rKQst4.mjs";import{i as o,o as s,s as c}from"./parse-args-Bw413PlW.mjs";import{readFile as l,writeFile as u}from"node:fs/promises";import{isIP as d}from"node:net";const f={20:`ChangeCipherSpec`,21:`Alert`,22:`Handshake`,23:`ApplicationData`},p={"0300":`SSL 3.0`,"0301":`TLS 1.0`,"0302":`TLS 1.1`,"0303":`TLS 1.2`,"0304":`TLS 1.3`},ee={1301:`TLS_AES_128_GCM_SHA256`,1302:`TLS_AES_256_GCM_SHA384`,1303:`TLS_CHACHA20_POLY1305_SHA256`,c02b:`TLS_ECDHE_ECDSA_AES_128_GCM_SHA256`,c02f:`TLS_ECDHE_RSA_AES_128_GCM_SHA256`,c02c:`TLS_ECDHE_ECDSA_AES_256_GCM_SHA384`,c030:`TLS_ECDHE_RSA_AES_256_GCM_SHA384`,cca9:`TLS_ECDHE_ECDSA_CHACHA20_POLY1305`,cca8:`TLS_ECDHE_RSA_CHACHA20_POLY1305`,"009c":`TLS_RSA_AES_128_GCM_SHA256`,"009d":`TLS_RSA_AES_256_GCM_SHA384`,"002f":`TLS_RSA_AES_128_CBC_SHA`,"0035":`TLS_RSA_AES_256_CBC_SHA`,c013:`TLS_ECDHE_RSA_AES_128_CBC_SHA`,c014:`TLS_ECDHE_RSA_AES_256_CBC_SHA`,"00ff":`TLS_EMPTY_RENEGOTIATION_INFO_SCSV`,5600:`TLS_FALLBACK_SCSV`},m={0:`NOERROR`,1:`FORMERR`,2:`SERVFAIL`,3:`NXDOMAIN`,4:`NOTIMP`,5:`REFUSED`},h={0:`QUERY`,1:`IQUERY`,2:`STATUS`,3:`UNASSIGNED`,4:`NOTIFY`,5:`UPDATE`},g={474554:`GET`,"504f5354":`POST`,505554:`PUT`,"44454c45":`DELETE`,48454144:`HEAD`,50415443:`PATCH`,"4f505449":`OPTIONS`,"434f4e4e":`CONNECT`},_={"0000":`server_name`,"000a":`supported_groups`,"000b":`ec_point_formats`,"000d":`signature_algorithms`,"0010":`application_layer_protocol_negotiation`,"0015":`padding`,"0017":`extended_master_secret`,"001b":`compress_certificate`,"0023":`session_ticket`,"0029":`pre_shared_key`,"002b":`supported_versions`,"002d":`psk_key_exchange_modes`,"0033":`key_share`,"0039":`quic_transport_parameters`,4469:`next_protocol_negotiation`,fe0d:`encrypted_client_hello`,ff01:`renegotiation_info`},te={0:`continuation`,1:`text`,2:`binary`,8:`close`,9:`ping`,10:`pong`};function v(e,t){return Number.parseInt(e.substring(t*2,t*2+2),16)}function y(e,t){return Number.parseInt(e.substring(t*2,t*2+4),16)}function b(e,t,n){return e.substring(t*2,(t+n)*2)}function x(e){return e.length>=24&&/^0{24}$/i.test(e.slice(0,24))}function ne(e){if(e.length<44)return null;let t=v(e,0);if(t!==22)return null;let n=b(e,1,2),r=y(e,3);if(e.length/2<5+r||v(e,5)!==1)return null;let i={recordType:f[t]??`0x${t.toString(16)}`,recordVersion:p[n]??n,recordLength:r,handshakeType:`ClientHello`},a=9;if(a+2>e.length/2)return i;let o=b(e,a,2);if(i.clientVersion=p[o]??o,a+=34,a>=e.length/2)return i;let s=v(e,a);if(a+=1+s,a+2>e.length/2)return i;let c=y(e,a);a+=2;let l=[];for(let t=0;t<c/2&&a+2<=e.length/2;t++){let t=b(e,a,2).toLowerCase();l.push({hex:t,name:ee[t]??`Unknown(0x${t})`}),a+=2}if(i.cipherSuites=l,i.cipherSuiteCount=l.length,a>=e.length/2)return i;let u=v(e,a);if(a+=1+u,a+2>e.length/2)return i;let d=y(e,a);a+=2;let m=a+d,h=[];for(;a+4<=m&&a+4<=e.length/2;){let t=b(e,a,2).toLowerCase(),n=y(e,a+2);h.push({type:t,length:n,name:_[t]}),a+=4+n}return i.extensions=h,i.extensionCount=h.length,i}function re(e){if(e.length<24)return null;let t=y(e,0),n=v(e,2),r=v(e,3),i=n>>7&1,a=n>>3&15,o=n>>2&1,s=n>>1&1,c=n&1,l=r>>7&1,u=r>>4&7,d=r&15;return{transactionId:`0x${t.toString(16).padStart(4,`0`)}`,flags:{qr:i===1?`Response`:`Query`,opcode:h[a]??a,authoritativeAnswer:!!o,truncation:!!s,recursionDesired:!!c,recursionAvailable:!!l,reserved:u,responseCode:m[d]??d},questionCount:y(e,4),answerCount:y(e,6),authorityCount:y(e,8),additionalCount:y(e,10)}}function ie(e){if(e.length<24||x(e))return!1;let t=v(e,2),n=v(e,3),r=t>>7&1,i=t>>3&15,a=n&15,o=y(e,4),s=y(e,6);return!(i>2||o+s===0||r===0&&a!==0||r===1&&a>5)}function S(e){return typeof e==`object`&&!!e&&!Array.isArray(e)}function ae(e,t){if(!S(e))throw Error(`fields[${t}] must be an object`);let n=e.name,r=e.offset,i=e.length,a=e.type;if(typeof n!=`string`||n.trim().length===0)throw Error(`fields[${t}].name must be a non-empty string`);if(typeof r!=`number`||!Number.isInteger(r)||r<0)throw Error(`fields[${t}].offset must be a non-negative integer`);if(typeof i!=`number`||!Number.isInteger(i)||i<=0)throw Error(`fields[${t}].length must be a positive integer`);if(a!==`int`&&a!==`string`&&a!==`bytes`&&a!==`bool`&&a!==`float`)throw Error(`fields[${t}].type is invalid`);return{name:n,offset:r,length:i,type:a}}function oe(e,t){if(!S(e))throw Error(`fields[${t}] must be an object`);let n=e.name,r=e.offset,i=e.length,a=e.type,o=e.description;if(typeof n!=`string`||n.trim().length===0)throw Error(`fields[${t}].name must be a non-empty string`);if(typeof r!=`number`||!Number.isInteger(r)||r<0)throw Error(`fields[${t}].offset must be a non-negative integer`);if(typeof i!=`number`||!Number.isInteger(i)||i<=0)throw Error(`fields[${t}].length must be a positive integer`);if(a!==`uint8`&&a!==`uint16`&&a!==`uint32`&&a!==`int64`&&a!==`float`&&a!==`string`&&a!==`bytes`)throw Error(`fields[${t}].type is invalid`);return{name:n,offset:r,length:i,type:a,...typeof o==`string`?{description:o}:{}}}function se(e,t){let n=t.fields;if(!Array.isArray(n))throw Error(`spec.fields must be an array`);let r=typeof t.fieldDelimiter==`string`&&t.fieldDelimiter.length>0?t.fieldDelimiter:void 0,i=t.byteOrder,a=i===`le`||i===`be`?i:void 0;return{name:e,...r?{fieldDelimiter:r}:{},...a?{byteOrder:a}:{},fields:n.map((e,t)=>ae(e,t))}}function ce(e){if(!S(e))return;let t=e.type;if(t!==`aes`&&t!==`xor`&&t!==`rc4`&&t!==`custom`)return;let n=typeof e.key==`string`?e.key:void 0,r=typeof e.iv==`string`?e.iv:void 0,i=typeof e.notes==`string`?e.notes:void 0;return{type:t,...n?{key:n}:{},...r?{iv:r}:{},...i?{notes:i}:{}}}function le(e,t){if(!S(e))throw Error(`messages[${t}] must be an object`);let n=e.direction,r=e.timestamp,i=e.fields,a=e.raw;if(n!==`req`&&n!==`res`)throw Error(`messages[${t}].direction must be "req" or "res"`);if(typeof r!=`number`||!Number.isFinite(r))throw Error(`messages[${t}].timestamp must be a number`);if(!S(i))throw Error(`messages[${t}].fields must be an object`);if(typeof a!=`string`)throw Error(`messages[${t}].raw must be a string`);return{direction:n,timestamp:r,fields:i,raw:a}}const ue=[`utf8`,`ascii`],C=[`utf8`,`ascii`,`hex`,`base64`],de=[`u8`,`u16`,`u32`,`i8`,`i16`,`i32`,`string`,`bytes`],fe=[`set_byte`,`flip_bit`,`overwrite_bytes`,`append_bytes`,`truncate`,`increment_integer`];function w(e,t=`big`){return e===`little`?`little`:t}function T(e,t){if(typeof e!=`number`||!Number.isInteger(e)||e<0)throw Error(`${t} must be a non-negative integer`);return e}function E(e,t){if(typeof e!=`number`||!Number.isInteger(e)||e<=0)throw Error(`${t} must be a positive integer`);return e}function D(e,t){if(typeof e!=`number`||!Number.isInteger(e))throw Error(`${t} must be an integer`);return e}function O(e,t){let n=D(e,t);if(n<0||n>255)throw Error(`${t} must be between 0 and 255`);return n}function pe(e,t){return e===void 0?void 0:E(e,t)}function k(e,t,n,r){if(e===void 0)return n;if(typeof e!=`string`||!t.includes(e))throw Error(`${r} is invalid`);return e}function A(e,t){if(typeof e!=`string`)throw Error(`${t} must be a string`);return e}function j(e,t){let n=e.replace(/^0x/i,``).replace(/\s+/g,``);if(n.length===0)return n;if(n.length%2!=0||/[^0-9a-f]/i.test(n))throw Error(`${t} must be a valid even-length hex string`);return n.toLowerCase()}function M(e,t,n){switch(t){case`utf8`:case`ascii`:return Buffer.from(e,t);case`hex`:return Buffer.from(j(e,n),`hex`);case`base64`:return Buffer.from(e,`base64`)}}function me(e,t){let n=e*8;return t?{min:-(2**(n-1)),max:2**(n-1)-1}:{min:0,max:2**n-1}}function N(e){switch(e){case`u8`:return{width:1,signed:!1};case`u16`:return{width:2,signed:!1};case`u32`:return{width:4,signed:!1};case`i8`:return{width:1,signed:!0};case`i16`:return{width:2,signed:!0};case`i32`:return{width:4,signed:!0};default:return null}}function P(e,t,n,r,i){if(r)switch(n){case 1:e.writeInt8(t,0);return;case 2:i===`little`?e.writeInt16LE(t,0):e.writeInt16BE(t,0);return;case 4:i===`little`?e.writeInt32LE(t,0):e.writeInt32BE(t,0);return}switch(n){case 1:e.writeUInt8(t,0);return;case 2:i===`little`?e.writeUInt16LE(t,0):e.writeUInt16BE(t,0);return;case 4:i===`little`?e.writeUInt32LE(t,0):e.writeUInt32BE(t,0);return}}function he(e,t,n,r,i){if(r)switch(n){case 1:return e.readInt8(t);case 2:return i===`little`?e.readInt16LE(t):e.readInt16BE(t);case 4:return i===`little`?e.readInt32LE(t):e.readInt32BE(t)}switch(n){case 1:return e.readUInt8(t);case 2:return i===`little`?e.readUInt16LE(t):e.readUInt16BE(t);case 4:return i===`little`?e.readUInt32LE(t):e.readUInt32BE(t)}}function F(e,t,n){return t===void 0||e.length===t?e:e.length>t?e.subarray(0,t):Buffer.concat([e,Buffer.alloc(t-e.length,n)])}function ge(e,t){if(!S(e))throw Error(`fields[${t}] must be an object`);let n=e.name,r=e.type,i=e.value;if(typeof n!=`string`||n.trim().length===0)throw Error(`fields[${t}].name must be a non-empty string`);if(typeof r!=`string`||!de.includes(r))throw Error(`fields[${t}].type is invalid`);let a=r,o=N(a);if(o){let s=D(i,`fields[${t}].value`),c=me(o.width,o.signed);if(s<c.min||s>c.max)throw Error(`fields[${t}].value is out of range for ${r} (${c.min}..${c.max})`);if(e.length!==void 0||e.padByte!==void 0||e.encoding!==void 0)throw Error(`fields[${t}] does not support length, padByte, or encoding`);return{name:n,type:a,value:s}}let s=A(i,`fields[${t}].value`),c=pe(e.length,`fields[${t}].length`),l=e.padByte===void 0?0:O(e.padByte,`fields[${t}].padByte`);return r===`string`?{name:n,type:`string`,value:s,encoding:k(e.encoding,ue,`utf8`,`fields[${t}].encoding`),...c===void 0?{}:{length:c},padByte:l}:{name:n,type:`bytes`,value:s,encoding:k(e.encoding,C,`hex`,`fields[${t}].encoding`),...c===void 0?{}:{length:c},padByte:l}}function _e(e,t){switch(e.type){case`u8`:case`u16`:case`u32`:case`i8`:case`i16`:case`i32`:{let n=N(e.type);if(!n)throw Error(`Unsupported numeric field type: ${e.type}`);let r=Buffer.alloc(n.width);return P(r,e.value,n.width,n.signed,t),r}case`string`:return F(Buffer.from(e.value,e.encoding),e.length,e.padByte);case`bytes`:return F(M(e.value,e.encoding,`field ${e.name}`),e.length,e.padByte)}}function ve(e,t){let n=[],r=[],i=0;for(let a of e){let e=_e(a,t);n.push(e),r.push({name:a.name,offset:i,length:e.length,hex:e.toString(`hex`)}),i+=e.length}return{payload:Buffer.concat(n),segments:r}}function ye(e,t){if(!S(e))throw Error(`mutations[${t}] must be an object`);let n=e.strategy;if(typeof n!=`string`||!fe.includes(n))throw Error(`mutations[${t}].strategy is invalid`);switch(n){case`set_byte`:return{strategy:`set_byte`,offset:T(e.offset,`mutations[${t}].offset`),value:O(e.value,`mutations[${t}].value`)};case`flip_bit`:return{strategy:`flip_bit`,offset:T(e.offset,`mutations[${t}].offset`),bit:(()=>{let n=D(e.bit,`mutations[${t}].bit`);if(n<0||n>7)throw Error(`mutations[${t}].bit must be between 0 and 7`);return n})()};case`overwrite_bytes`:return{strategy:`overwrite_bytes`,offset:T(e.offset,`mutations[${t}].offset`),data:M(A(e.data,`mutations[${t}].data`),k(e.encoding,C,`hex`,`mutations[${t}].encoding`),`mutations[${t}].data`)};case`append_bytes`:return{strategy:`append_bytes`,data:M(A(e.data,`mutations[${t}].data`),k(e.encoding,C,`hex`,`mutations[${t}].encoding`),`mutations[${t}].data`)};case`truncate`:return{strategy:`truncate`,length:T(e.length,`mutations[${t}].length`)};case`increment_integer`:{let n=e.width;if(n!==1&&n!==2&&n!==4)throw Error(`mutations[${t}].width must be 1, 2, or 4`);return{strategy:`increment_integer`,offset:T(e.offset,`mutations[${t}].offset`),width:n,delta:D(e.delta,`mutations[${t}].delta`),endian:w(e.endian),signed:e.signed===!0}}}}function be(e,t,n){let r=Buffer.from(e);switch(t.strategy){case`set_byte`:if(t.offset>=r.length)throw Error(`mutations[${n}] offset is outside the payload`);return r[t.offset]=t.value,{payload:r,summary:{index:n,strategy:t.strategy,detail:`set payload[${t.offset}] to ${t.value}`}};case`flip_bit`:if(t.offset>=r.length)throw Error(`mutations[${n}] offset is outside the payload`);{let e=r[t.offset];r[t.offset]=e^1<<t.bit}return{payload:r,summary:{index:n,strategy:t.strategy,detail:`flipped bit ${t.bit} at offset ${t.offset}`}};case`overwrite_bytes`:if(t.offset+t.data.length>r.length)throw Error(`mutations[${n}] overwrite exceeds payload length`);return t.data.copy(r,t.offset),{payload:r,summary:{index:n,strategy:t.strategy,detail:`overwrote ${t.data.length} bytes at offset ${t.offset}`}};case`append_bytes`:return{payload:Buffer.concat([r,t.data]),summary:{index:n,strategy:t.strategy,detail:`appended ${t.data.length} bytes`}};case`truncate`:if(t.length>r.length)throw Error(`mutations[${n}] length exceeds payload size`);return{payload:r.subarray(0,t.length),summary:{index:n,strategy:t.strategy,detail:`truncated payload to ${t.length} bytes`}};case`increment_integer`:{if(t.offset+t.width>r.length)throw Error(`mutations[${n}] integer range exceeds payload length`);let e=he(r,t.offset,t.width,t.signed,t.endian)+t.delta,i=me(t.width,t.signed);if(e<i.min||e>i.max)throw Error(`mutations[${n}] integer overflow (${i.min}..${i.max})`);return P(r.subarray(t.offset,t.offset+t.width),e,t.width,t.signed,t.endian),{payload:r,summary:{index:n,strategy:t.strategy,detail:`incremented ${t.signed?`signed`:`unsigned`} ${t.width}-byte integer at offset ${t.offset} by ${t.delta}`}}}}}const xe=Object.freeze({arp:2054,ipv4:2048,ipv6:34525,vlan:33024}),Se=Object.freeze({icmp:1,igmp:2,tcp:6,udp:17,gre:47,esp:50,ah:51,icmpv6:58,ospf:89}),Ce=Object.freeze({loopback:0,ethernet:1,raw:101});function I(e,t,n,r){if(typeof e==`number`){if(!Number.isInteger(e)||e<0||e>r)throw Error(`${t} must be an integer between 0 and ${r}`);return e}if(typeof e!=`string`||e.trim().length===0)throw Error(`${t} must be a non-empty string or integer`);let i=e.trim().toLowerCase(),a=n[i];if(a!==void 0)return a;if(/^\d+$/.test(i)){let e=Number.parseInt(i,10);if(e>r)throw Error(`${t} must be less than or equal to ${r}`);return e}let o=j(i,t),s=Number.parseInt(o,16);if(s>r)throw Error(`${t} must be less than or equal to ${r}`);return s}function L(e,t){if(typeof e!=`string`||e.trim().length===0)throw Error(`${t} must be a non-empty MAC address string`);let n=e.trim().toLowerCase().replace(/^0x/,``).replace(/[:\-.\s]/g,``);if(!/^[0-9a-f]{12}$/i.test(n))throw Error(`${t} must be a valid 6-byte MAC address`);let r=n.match(/.{2}/g)?.join(`:`);if(!r)throw Error(`${t} must be a valid 6-byte MAC address`);return{canonical:r,bytes:Buffer.from(n,`hex`)}}function R(e,t){if(typeof e!=`string`||d(e.trim())!==4)throw Error(`${t} must be a valid IPv4 address`);let n=e.trim().split(`.`).map(e=>Number.parseInt(e,10));return Buffer.from(n)}function z(e,t){return e.length===0?[]:e.split(`:`).flatMap(e=>{if(e.length===0)return[];if(e.includes(`.`)){let n=R(e,t);return[n.readUInt16BE(0).toString(16),n.readUInt16BE(2).toString(16)]}if(!/^[0-9a-f]{1,4}$/i.test(e))throw Error(`${t} contains an invalid IPv6 group`);return[e]})}function we(e,t){if(typeof e!=`string`)throw Error(`${t} must be a valid IPv6 address`);let n=e.trim().toLowerCase().split(`%`)[0]??``;if(d(n)!==6)throw Error(`${t} must be a valid IPv6 address`);let r=n.split(`::`);if(r.length>2)throw Error(`${t} must be a valid IPv6 address`);let i=z(r[0]??``,t),a=z(r[1]??``,t),o=r.length===2?[...i,...Array.from({length:8-i.length-a.length},()=>`0`),...a]:i;if(o.length!==8)throw Error(`${t} must expand to exactly 8 IPv6 groups`);let s=Buffer.alloc(16);for(let[e,t]of o.entries())s.writeUInt16BE(Number.parseInt(t,16),e*2);return s}function B(e,t,n){return t===`ipv4`?R(e,n):we(e,n)}function V(e,t){return I(e,t,xe,65535)}function Te(e,t){return I(e,t,Se,255)}function Ee(e,t){return I(e,t,Ce,4294967295)}function De(e){return e===`little`?`little`:`big`}function Oe(e){return e===`big`?`big`:`little`}function ke(e){return e===`nano`?`nano`:`micro`}function H(e,t){if(typeof e!=`string`)throw Error(`${t} must be a hex string`);return Buffer.from(j(e,t),`hex`)}function U(e){let t=0;for(let n=0;n<e.length;n+=2){let r=e[n]??0,i=e[n+1]??0;for(t+=r<<8|i;t>65535;)t=(t&65535)+(t>>>16)}return~t&65535}function Ae(e,t,n,r){let i=Buffer.alloc(14);return e.bytes.copy(i,0),t.bytes.copy(i,6),i.writeUInt16BE(n,12),Buffer.concat([i,r])}function je(e){if(e.hardwareSize!==e.senderMac.bytes.length||e.hardwareSize!==e.targetMac.bytes.length)throw Error(`hardwareSize must match the provided MAC address lengths`);if(e.protocolSize!==e.senderIp.length||e.protocolSize!==e.targetIp.length)throw Error(`protocolSize must match the provided IP address lengths`);let t=Buffer.alloc(8+e.hardwareSize*2+e.protocolSize*2),n=0;return t.writeUInt16BE(e.hardwareType,n),n+=2,t.writeUInt16BE(e.protocolType,n),n+=2,t.writeUInt8(e.hardwareSize,n++),t.writeUInt8(e.protocolSize,n++),t.writeUInt16BE(e.operation===`reply`?2:1,n),n+=2,e.senderMac.bytes.copy(t,n),n+=e.hardwareSize,e.senderIp.copy(t,n),n+=e.protocolSize,e.targetMac.bytes.copy(t,n),n+=e.hardwareSize,e.targetIp.copy(t,n),t}function Me(e){let t=Buffer.alloc(20);t[0]=69,t[1]=(e.dscp&63)<<2|e.ecn&3,t.writeUInt16BE(t.length+e.payload.length,2),t.writeUInt16BE(e.identification,4);let n=!!e.dontFragment<<1|!!e.moreFragments;t.writeUInt16BE((n&7)<<13|e.fragmentOffset&8191,6),t[8]=e.ttl,t[9]=e.protocol,t.writeUInt16BE(0,10),e.sourceIp.copy(t,12),e.destinationIp.copy(t,16);let r=U(t);return t.writeUInt16BE(r,10),{packet:Buffer.concat([t,e.payload]),checksum:r}}function Ne(e){let t=Buffer.alloc(40),n=6<<28|(((e.dscp&63)<<2|e.ecn&3)&255)<<20|e.flowLabel&1048575;return t.writeUInt32BE(n>>>0,0),t.writeUInt16BE(e.payload.length,4),t.writeUInt8(e.protocol,6),t.writeUInt8(e.hopLimit,7),e.sourceIp.copy(t,8),e.destinationIp.copy(t,24),Buffer.concat([t,e.payload])}function Pe(e){let t=Buffer.alloc(8+e.payload.length);t[0]=e.operation===`reply`?0:8,t[1]=0,t.writeUInt16BE(0,2),t.writeUInt16BE(e.identifier,4),t.writeUInt16BE(e.sequenceNumber,6),e.payload.copy(t,8);let n=U(t);return t.writeUInt16BE(n,2),{packet:t,checksum:n}}function W(e,t,n,r){r===`little`?e.writeUInt32LE(n,t):e.writeUInt32BE(n,t)}function G(e,t,n,r){r===`little`?e.writeUInt16LE(n,t):e.writeUInt16BE(n,t)}function K(e,t,n){return n===`little`?e.readUInt32LE(t):e.readUInt32BE(t)}function q(e,t,n){return n===`little`?e.readUInt16LE(t):e.readUInt16BE(t)}function Fe(e,t){let n=e===`little`?t===`nano`?`4d3cb2a1`:`d4c3b2a1`:t===`nano`?`a1b23c4d`:`a1b2c3d4`;return Buffer.from(n,`hex`)}function Ie(e){if(e.length<24)throw Error(`PCAP file is too small to contain a global header`);let t=e.subarray(0,4).toString(`hex`),n,r;switch(t){case`d4c3b2a1`:n=`little`,r=`micro`;break;case`4d3cb2a1`:n=`little`,r=`nano`;break;case`a1b2c3d4`:n=`big`,r=`micro`;break;case`a1b23c4d`:n=`big`,r=`nano`;break;default:throw Error(`Unsupported capture format: only classic PCAP files are supported`)}return{endianness:n,timestampPrecision:r,versionMajor:q(e,4,n),versionMinor:q(e,6,n),snapLength:K(e,16,n),linkType:K(e,20,n)}}function Le(e,t){if(!S(e))throw Error(`packets[${t}] must be an object`);let n=H(e.dataHex,`packets[${t}].dataHex`),r=e.timestampSeconds===void 0?0:T(e.timestampSeconds,`packets[${t}].timestampSeconds`),i=e.timestampFraction===void 0?0:T(e.timestampFraction,`packets[${t}].timestampFraction`),a=e.originalLength===void 0?n.length:E(e.originalLength,`packets[${t}].originalLength`);if(a<n.length)throw Error(`packets[${t}].originalLength must be >= included packet length`);return{data:n,timestampSeconds:r,timestampFraction:i,originalLength:a}}function Re(e){let t=Buffer.alloc(24);Fe(e.endianness,e.timestampPrecision).copy(t,0),G(t,4,2,e.endianness),G(t,6,4,e.endianness),W(t,8,0,e.endianness),W(t,12,0,e.endianness),W(t,16,e.snapLength,e.endianness),W(t,20,e.linkType,e.endianness);let n=e.packets.map(t=>{let n=Buffer.alloc(16);return W(n,0,t.timestampSeconds,e.endianness),W(n,4,t.timestampFraction,e.endianness),W(n,8,t.data.length,e.endianness),W(n,12,t.originalLength,e.endianness),Buffer.concat([n,t.data])});return Buffer.concat([t,...n])}function ze(e,t,n){let r=Ie(e),i=[],a=24;for(;a<e.length&&!(t!==void 0&&i.length>=t);){if(a+16>e.length)throw Error(`PCAP file ends with an incomplete packet header`);let t=K(e,a,r.endianness),o=K(e,a+4,r.endianness),s=K(e,a+8,r.endianness),c=K(e,a+12,r.endianness);if(a+=16,a+s>e.length)throw Error(`PCAP file ends with an incomplete packet payload`);let l=e.subarray(a,a+s);a+=s;let u=n===void 0?l.length:n,d=Math.min(u,l.length);i.push({index:i.length,timestampSeconds:t,timestampFraction:o,includedLength:s,originalLength:c,dataHex:l.subarray(0,d).toString(`hex`),truncated:d<l.length})}return{header:r,packets:i}}const Be=[Buffer.from([44]),Buffer.from([124]),Buffer.from([58]),Buffer.from([59]),Buffer.from([9]),Buffer.from([0]),Buffer.from([13,10])];function J(e){return e.replace(/^0x/i,``).replace(/\s+/g,``).toLowerCase()}function Y(e){let t=J(e);return t.length===0||t.length%2!=0?!1:/^[0-9a-f]+$/i.test(t)}function X(e){return Y(e)?Buffer.from(J(e),`hex`):null}function Z(e){return e>=32&&e<=126}function Q(e){if(e.length===0)return 0;let t=0;for(let n of e.values())Z(n)&&(t+=1);return t/e.length}function Ve(e){return e.length===0?0:e.reduce((e,t)=>e+Q(t),0)/e.length}function He(e,t){if(t.length===0)return[e];let n=[],r=0,i=e.indexOf(t,r);for(;i>=0;)n.push(e.subarray(r,i)),r=i+t.length,i=e.indexOf(t,r);return n.push(e.subarray(r)),n}function Ue(e){return Q(e)===1?e.toString(`utf8`):e.toString(`hex`)}function We(e){let t=[];for(let n of e){let e=X(n);e&&t.push(e)}return t}function Ge(e,t){if(e.length===0)return null;if(e.length===1)return e.readUInt8(0);if(e.length===2)return t===`le`?e.readUInt16LE(0):e.readUInt16BE(0);if(e.length===4)return t===`le`?e.readUInt32LE(0):e.readUInt32BE(0);if(e.length===8){let n=Number(t===`le`?e.readBigUInt64LE(0):e.readBigUInt64BE(0));return Number.isFinite(n)?n:null}let n=0,r=t===`le`?[...e.values()].toReversed():[...e.values()];for(let e of r)n=n*256+e;return Number.isFinite(n)?n:null}function Ke(e,t){if(e.length===4){let n=t===`le`?e.readFloatLE(0):e.readFloatBE(0);return Number.isFinite(n)?n:null}if(e.length===8){let n=t===`le`?e.readDoubleLE(0):e.readDoubleBE(0);return Number.isFinite(n)?n:null}return null}function qe(e,t){if(t.length===0)return 0;let n=0,r=0,i=e.indexOf(t,r);for(;i>=0;)n+=1,r=i+t.length,i=e.indexOf(t,r);return n}function Je(e){return e.length===0?`bytes`:e.every(e=>e.length===1)&&e.every(e=>e[0]===0||e[0]===1)?`bool`:Ve(e)>=.7?`string`:e.every(e=>e.length===4)&&Ye(e)?`float`:e.every(e=>e.length<=4)?`int`:`bytes`}function Ye(e){let t=[];for(let n of e){let e=Ke(n,`be`);if(e===null)return!1;t.push(e)}return t.some(e=>Math.abs(e)>.001&&Math.abs(e)<1e6)}function Xe(e,t){let n=0,r=0;for(let i of e){let e=i[t];e!==void 0&&(n+=1,Z(e)&&(r+=1))}return n>0&&r/n>=.8}function Ze(e,t){let n=0;for(let r of e){let e=r[t];if(e!==void 0&&(n+=1,e!==0&&e!==1))return!1}return n>0}function Qe(e,t){if(t.length===0)return[];let n=e.map(e=>He(e,t)),r=n[0];if(!r||r.length<2)return[];let i=r.length;if(!n.every(e=>e.length===i))return[];let a=[],o=0;for(let e=0;e<i;e+=1){let i=r[e];if(!i)continue;let s=n.map(t=>t[e]).filter(e=>Buffer.isBuffer(e));a.push({name:`field_${e+1}`,offset:o,length:i.length,type:Je(s)}),o+=i.length+t.length}return a}function $e(e){let t=Math.min(...e.map(e=>e.length)),n=[],r=0;for(;r<t&&n.length<24;){if(Xe(e,r)){let i=r+1;for(;i<t&&Xe(e,i);)i+=1;n.push({name:`field_${n.length+1}`,offset:r,length:i-r,type:`string`}),r=i;continue}if(Ze(e,r)){n.push({name:`field_${n.length+1}`,offset:r,length:1,type:`bool`}),r+=1;continue}let i=t-r;if(i>=4&&Ye(e.map(e=>e.subarray(r,r+4)))){n.push({name:`field_${n.length+1}`,offset:r,length:4,type:`float`}),r+=4;continue}let a=i>=4?4:Math.min(i,2),o=e.map(e=>e.subarray(r,r+a));n.push({name:`field_${n.length+1}`,offset:r,length:a,type:Je(o)}),r+=a}return n}function et(e){for(let t of Be){let n=e.map(e=>qe(e,t)),r=n[0];if(typeof r==`number`&&r>=2&&n.every(e=>e===r))return Ue(t)}}function tt(e){let t=Math.min(...e.map(e=>e.length));if(t<2)return`be`;let n=0,r=0,i=Math.min(t-1,8);for(let t=0;t<i;t+=2){let i=0,a=0;for(let n of e){let e=n.readUInt16LE(t),r=n.readUInt16BE(t);e<4096&&(i+=1),r<4096&&(a+=1)}i>a?n+=1:a>i&&(r+=1)}return n>r?`le`:`be`}function nt(e,t){if(e.length===0||t.length<2)return e;let n=Math.min(...t.map(e=>e.length)),r=0;for(let e=0;e<n;e+=1){let n=t[0][e];if(t.every(t=>t[e]===n))r=e+1;else break}if(r===0)return e;let i=!1;return e.map(e=>!i&&e.offset===0&&r>=2?(i=!0,{...e,name:`magic`}):i&&e.type===`int`&&e.length<=2&&e.offset<=r?{...e,name:`version`}:e)}var rt=class{patterns=new Map;legacyPatterns=new Map;definePattern(e,t,n){let r=Array.isArray(t)?this.createLegacyPattern(e,t,n):this.createLegacyPatternFromSpec(e,t),i=this.createSpecFromLegacyPattern(r);if(this.patterns.set(e,i),this.legacyPatterns.set(e,r),Array.isArray(t))return r}detectPattern(e){let t=X(e);if(!t)return null;let n=null;for(let e of this.patterns.values()){let r=e.fields.length+ +!!e.fieldDelimiter;if(r===0)continue;let i=0;e.fieldDelimiter&&this.payloadContainsDelimiter(t,e.fieldDelimiter)&&(i+=1);for(let n of e.fields)this.matchesField(t,n,e.byteOrder??`be`)&&(i+=1);let a=Number((i/r).toFixed(2));if(a<=0)continue;let o={pattern:e,confidence:a,matches:i,total:r};(!n||o.confidence>n.confidence||o.confidence===n.confidence&&o.matches>n.matches)&&(n=o)}return n}autoDetect(e){let t=We(e);if(t.length===0)return null;let n=et(t),r=this.inferFields(e);return{name:`auto-detected-pattern`,fieldDelimiter:n,byteOrder:tt(t),fields:r}}inferFields(e){let t=We(e);if(t.length===0)return[];let n=et(t);if(n){let e=Qe(t,this.parseDelimiter(n));if(e.length>0)return nt(e,t)}return nt($e(t),t)}autoDetectPattern(e,t){let n=e.map(e=>e.toString(`hex`)),r=this.autoDetect(n),i=t?.name??r?.name??`auto_detected`;if(!r){let e=this.createLegacyPattern(i,[]);return this.patterns.set(i,this.createSpecFromLegacyPattern(e)),this.legacyPatterns.set(i,e),e}let a={...r,name:i};return this.definePattern(i,a),this.getPattern(i)??this.createLegacyPatternFromSpec(i,a)}getPattern(e){return this.legacyPatterns.get(e)}listPatterns(){return[...this.patterns.keys()]}exportProto(e){let t=this.isLegacyPattern(e)?e:this.createLegacyPatternFromSpec(e.name,e),n=[`// Protocol: ${t.name}`,`// Byte order: ${t.byteOrder}`,``];t.encryption&&(n.push(`// Encryption: ${t.encryption.type}`),t.encryption.notes&&n.push(`// Notes: ${t.encryption.notes}`),n.push(``)),n.push(`message ${this.toPascalCase(t.name)} {`);for(let e=0;e<t.fields.length;e+=1){let r=t.fields[e];if(!r)continue;let i=r.description?` // ${r.description}`:``;n.push(` ${this.toProtoType(r.type)} ${r.name} = ${e+1};${i}`)}return n.push(`}`),n.push(``),n.join(`
2
2
  `)}payloadContainsDelimiter(e,t){let n=this.parseDelimiter(t);return n.length===0?!1:e.includes(n)}matchesField(e,t,n){if(t.offset<0||t.length<=0||e.length<t.offset+t.length)return!1;let r=e.subarray(t.offset,t.offset+t.length);switch(t.type){case`bytes`:return r.length===t.length;case`bool`:return r.length===1&&(r[0]===0||r[0]===1);case`string`:return Q(r)>=.6;case`int`:return Ge(r,n)!==null;case`float`:return Ke(r,n)!==null;default:return!1}}createLegacyPattern(e,t,n){return{name:e,fields:t.map(e=>({name:e.name,offset:e.offset,length:e.length,type:e.type,...e.description?{description:e.description}:{}})).toSorted((e,t)=>e.offset-t.offset),byteOrder:n?.byteOrder??`big`,...n?.encryption?{encryption:n.encryption}:{}}}createLegacyPatternFromSpec(e,t){return{name:e,fieldDelimiter:t.fieldDelimiter,byteOrder:t.byteOrder===`le`?`little`:`big`,fields:t.fields.map(e=>({name:e.name,offset:e.offset,length:e.length,type:this.toLegacyFieldType(e),...e.description?{description:e.description}:{}}))}}createSpecFromLegacyPattern(e){return{name:e.name,fieldDelimiter:e.fieldDelimiter,byteOrder:e.byteOrder===`little`?`le`:`be`,fields:e.fields.map(e=>({name:e.name,offset:e.offset,length:e.length,type:this.toSpecFieldType(e.type),...e.description?{description:e.description}:{}}))}}isLegacyPattern(e){return e.byteOrder===`big`||e.byteOrder===`little`}toLegacyFieldType(e){return e.type===`float`?`float`:e.type===`string`?`string`:e.type===`bytes`?`bytes`:e.length===1?`uint8`:e.length===2?`uint16`:e.length===4?`uint32`:`int64`}toSpecFieldType(e){return e===`float`?`float`:e===`string`?`string`:e===`bytes`?`bytes`:`int`}parseDelimiter(e){if(Y(e)){let t=X(e);if(t)return t}return Buffer.from(e,`utf8`)}toProtoType(e){return{uint8:`uint32`,uint16:`uint32`,uint32:`uint32`,int64:`int64`,float:`float`,string:`string`,bytes:`bytes`}[e]}toPascalCase(e){return e.replace(/[^a-zA-Z0-9_]/g,`_`).split(`_`).filter(Boolean).map(e=>e.charAt(0).toUpperCase()+e.slice(1)).join(``)||`Message`}};function it(e){return typeof e==`object`&&!!e&&!Array.isArray(e)}function $(e){return e.trim().toLowerCase()}function at(e){if(e.length===0)return 0;let t=new Map;for(let n of e)t.set(n,(t.get(n)??0)+1);let n=0;for(let r of t.values()){let t=r/e.length;t>0&&(n-=t*Math.log2(t))}return n}function ot(e){if(e.length===0)return 0;let t=0;for(let n=0;n<e.length;n+=1){let r=e.charCodeAt(n);r>=32&&r<=126&&(t+=1)}return t/e.length}var st=class{infer(e){if(e.length===0)return{states:[],transitions:[],initial:``,initialState:``,finalStates:[]};let t=new Map,n=new Map,r=``;for(let i=0;i<e.length;i+=1){let a=e[i];if(!a)continue;let o=this.buildSignature(a),s=t.get(o);if(s?s.type=this.mergeStateTypes(s.type,this.inferStateType(a,i===e.length-1)):(s={id:`state_${t.size+1}`,name:this.buildStateName(a,t.size+1),type:this.inferStateType(a,i===e.length-1)},t.set(o,s)),r&&a.timestamp!==void 0){let t=e[0];t&&t.timestamp!==void 0&&(s.timeout=a.timestamp-t.timestamp)}if(r){let e=this.buildEventName(a),t=this.buildCondition(a.fields),i=this.buildAction(a),o=`${r}:${s.id}:${e}`;n.has(o)||n.set(o,{from:r,to:s.id,event:e,confidence:this.computeTransitionConfidence(a),...t?{condition:t}:{},...i?{action:i}:{}})}r=s.id}let i=e[0],a=i?t.get(this.buildSignature(i))?.id??``:``;return{states:[...t.values()],transitions:[...n.values()],initial:a,initialState:a,finalStates:this.collectTerminalStates([...t.values()])}}visualize(e){if(e.states.length===0)return["```mermaid",`stateDiagram-v2`,` [*] --> empty`,"```"].join(`
3
3
  `);let t=["```mermaid",`stateDiagram-v2`],n=e.initialState??e.initial;n&&t.push(` [*] --> ${n}`);for(let n of e.states){let e=n.type??`normal`,r=e===`normal`?n.name:`${n.name} (${e})`;t.push(` state "${r}" as ${n.id}`)}for(let n of e.transitions){let e=[n.event??n.trigger??`transition`];typeof n.confidence==`number`&&e.push(`(${n.confidence.toFixed(2)})`),n.condition&&e.push(`[${n.condition}]`),n.action&&e.push(`/ ${n.action}`),t.push(` ${n.from} --> ${n.to} : ${e.join(` `)}`)}let r=new Set(e.finalStates??[]);for(let n of e.states){let e=n.type??`normal`;(e===`accept`||e===`reject`||r.has(n.id))&&t.push(` ${n.id} --> [*]`)}return t.push("```"),t.join(`
4
- `)}inferStateMachine(e){let t=e.map(e=>({direction:e.direction===`out`?`req`:`res`,timestamp:e.timestamp??0,fields:{},raw:e.payload.length>0?e.payload.toString(`utf8`):e.payload.toString(`hex`),rawBuffer:e.payload}));return this.infer(t)}generateMermaid(e){return this.visualize(e)}simplify(e){if(e.states.length<2)return{...e,initialState:e.initialState??e.initial,finalStates:e.finalStates??this.collectTerminalStates(e.states)};let t=new Map,n=new Map;for(let r of e.states){let e=this.getPayloadPrefix(r);if(!e)continue;let i=[...n.entries()].find(([t])=>t===e);i?t.set(r.id,i[0]):(n.set(e,r.id),t.set(r.id,e))}let r=new Map,i=new Map;for(let[e,t]of n)i.set(e,t);for(let t of e.states){let e=this.getPayloadPrefix(t);if(!e)continue;let n=i.get(e);n&&n!==t.id&&r.set(t.id,n)}if(r.size===0)return{...e,initialState:e.initialState??e.initial,finalStates:e.finalStates??this.collectTerminalStates(e.states)};let a=e.states.filter(e=>!r.has(e.id)),o=e.transitions.map(e=>({...e,from:r.get(e.from)??e.from,to:r.get(e.to)??e.to})).filter(e=>e.from!==e.to),s=e.initialState??e.initial??``,c=r.get(s)??s;return{states:a,transitions:o,initial:c,initialState:c,finalStates:e.finalStates.map(e=>r.get(e)??e).filter((e,t,n)=>n.indexOf(e)===t)}}getPayloadPrefix(e){let t=e.expectedPayload;return!t||t.length<8?null:t.slice(0,8).toLowerCase()}buildSignature(e){let t=Object.keys(e.fields).toSorted().join(`,`),n=$(e.rawBuffer?e.rawBuffer.toString(`hex`):e.raw).slice(0,24);return`${e.direction}|${t}|${n}`}buildStateName(e,t){let n=e.direction===`req`?`send`:`recv`,r=this.findPrimaryFieldName(e.fields),i=e.raw;if(i.length===0)return`${n}_empty`;let a=e.rawBuffer,o=Buffer.isBuffer(a)?a.toString(`hex`):i;if(o.startsWith(`16`)||o.startsWith(`15`)||o.startsWith(`17`))return`${n}_tls_handshake`;let s=i.trimStart();if(s.startsWith(`{`)||s.startsWith(`[`))return`${n}_json_${r||`step_${t}`}`;if(ot(i)>=.7){let e=$(i);return e.includes(`close`)||e.includes(`fin`)||e.includes(`bye`)?`${n}_close`:e.startsWith(`get `)||e.startsWith(`post `)||e.startsWith(`http`)?`${n}_text_http`:`${n}_text_${r||`step_${t}`}`}return Buffer.isBuffer(a)&&a.length>=32&&at(a)>6?`${n}_encrypted`:Buffer.isBuffer(a)&&a.length<=4?`${n}_control`:`${n}_${r||`step_${t}`}`}findPrimaryFieldName(e){return Object.keys(e).toSorted()[0]||``}inferStateType(e,t){let n=$(e.raw),r=this.findStatusValue(e.fields);return this.containsRejectSignal(n)||this.containsRejectSignal(r)?`reject`:this.containsAcceptSignal(n)||this.containsAcceptSignal(r)||t&&e.direction===`res`?`accept`:`normal`}mergeStateTypes(e,t){return e===`reject`||t===`reject`?`reject`:e===`accept`||t===`accept`?`accept`:`normal`}findStatusValue(e){for(let t of[`status`,`result`,`code`,`reason`,`message`]){let n=e[t];if(typeof n==`string`||typeof n==`number`||typeof n==`boolean`)return String(n)}return``}containsRejectSignal(e){return[`error`,`fail`,`denied`,`reject`,`timeout`,`invalid`].some(t=>$(e).includes(t))}containsAcceptSignal(e){return[`ok`,`success`,`accept`,`ready`,`done`,`complete`].some(t=>$(e).includes(t))}buildEventName(e){let t=this.findStatusValue(e.fields);if(t)return`${e.direction}_${$(t).replace(/[^a-z0-9]+/g,`_`)}`;let n=this.findPrimaryFieldName(e.fields);return n?`${e.direction}_${n}`:`${e.direction}_message`}buildCondition(e){let t=this.findStatusValue(e);if(t)return`status=${t}`;let n=Object.keys(e).toSorted().slice(0,2);if(n.length===0)return;let r=[];for(let t of n){let n=e[t];(typeof n==`string`||typeof n==`number`||typeof n==`boolean`)&&r.push(`${t}=${n}`)}return r.length>0?r.join(`, `):void 0}buildAction(e){let t=this.findStatusValue(e.fields);if(this.containsRejectSignal(t)||this.containsRejectSignal(e.raw))return`reject`;if(this.containsAcceptSignal(t)||this.containsAcceptSignal(e.raw))return`complete`;let n=$(e.raw);if(n.includes(`ack`))return`acknowledge`;if(n.includes(`retry`))return`retry`;if(Object.keys(e.fields).length>0&&it(e.fields))return e.direction===`req`?`send`:`receive`}collectTerminalStates(e){let t=e.filter(e=>{let t=e.type??`normal`;return t===`accept`||t===`reject`}).map(e=>e.id);for(let n of e){let e=$(n.name);(e.includes(`close`)||e.includes(`fin`)||e.includes(`bye`))&&(t.includes(n.id)||t.push(n.id))}return t}computeTransitionConfidence(e){let t=.3;return Object.keys(e.fields).length>0&&(t+=.3),this.findStatusValue(e.fields)&&(t+=.2),e.raw.length>0&&(t+=.2),Math.min(t,1)}};const ct={states:[],transitions:[],initial:``,initialState:``,finalStates:[]};var lt=class{engine;inferrer;eventBus;constructor(e,t,n){this.engine=e,this.inferrer=t,this.eventBus=n}emitEvent(e,t){this.eventBus?.emit(e,{...t,timestamp:new Date().toISOString()})}getEngine(){return this.engine||=new rt,this.engine}getInferrer(){return this.inferrer||=new st,this.inferrer}errorMessage(e){return e instanceof Error?e.message:String(e)}},ut=class extends lt{async handleDefinePattern(e){try{let t=typeof e.name==`string`&&e.name.trim().length>0?e.name:`unnamed_pattern`,n=o(e,`spec`);if(n){let e=se(t,n);return this.getEngine().definePattern(t,e),{patternId:t,pattern:this.getEngine().getPattern(t)??{name:t,fields:[],byteOrder:`big`},success:!0}}let r=(Array.isArray(e.fields)?e.fields:[]).map((e,t)=>oe(e,t)),i=e.byteOrder===`little`||e.byteOrder===`big`?e.byteOrder:void 0,a=ce(e.encryption);return{patternId:t,pattern:this.getEngine().definePattern(t,r,{...i?{byteOrder:i}:{},...a?{encryption:a}:{}}),success:!0}}catch(e){return{patternId:`error`,pattern:{name:`error`,fields:[],byteOrder:`big`},success:!1,error:this.errorMessage(e)}}}async handleAutoDetect(e){try{let t=(()=>{let t=s(e,`hexPayloads`);return t.length>0?t:s(e,`payloads`)})(),n=this.getEngine().autoDetect(t),r=typeof e.name==`string`&&e.name.trim().length>0?e.name:void 0;if(!n)return{patterns:[this.getEngine().autoDetectPattern([],r?{name:r}:{})],success:!0};let i={...n,name:r??n.name};this.getEngine().definePattern(i.name,i);let a=this.getEngine().getPattern(i.name)??{name:i.name,fields:[],byteOrder:`big`};return this.emitEvent(`protocol:pattern_detected`,{patternName:i.name,confidence:0}),{patterns:[a],success:!0}}catch(e){return{patterns:[],success:!1,error:this.errorMessage(e)}}}async handleInferFields(e){try{let t=s(e,`hexPayloads`);return{success:!0,fields:this.getEngine().inferFields(t)}}catch(e){return{fields:[],success:!1,error:this.errorMessage(e)}}}async handleExportSchema(e){try{let t=c(e,`patternId`),n=this.getEngine().getPattern(t);return n?{schema:this.getEngine().exportProto(n)}:{schema:`// Error: pattern '${t}' not found`}}catch(e){return{schema:`// Error: ${this.errorMessage(e)}`}}}async handleInferStateMachine(e){try{let t=e.messages;if(!Array.isArray(t))throw Error(`messages must be an array`);let n=t.some(e=>S(e)&&(e.direction===`in`||e.direction===`out`)),r;if(n){let e=t.map((e,t)=>{if(!S(e))throw Error(`messages[${t}] must be an object`);let n=e.direction,r=typeof e.payloadHex==`string`?e.payloadHex:``,i=typeof e.timestamp==`number`?e.timestamp:void 0,a=Buffer.from(r.replace(/\s+/g,``),`hex`);if(n!==`in`&&n!==`out`)throw Error(`messages[${t}].direction must be "in" or "out"`);return{direction:n,payload:a,...i===void 0?{}:{timestamp:i}}});r=this.getInferrer().inferStateMachine(e)}else{let e=t.map((e,t)=>le(e,t));r=this.getInferrer().infer(e)}return e.simplify===!0&&(r=this.getInferrer().simplify(r)),{stateMachine:r,mermaid:this.getInferrer().generateMermaid(r),success:!0}}catch(e){return{stateMachine:{...ct},success:!1,error:this.errorMessage(e)}}}async handleVisualizeState(e){try{let t=e.stateMachine;if(!S(t))return{mermaidDiagram:this.getInferrer().generateMermaid(ct)};let n=Array.isArray(t.states)?t.states:[],r=Array.isArray(t.transitions)?t.transitions:[],i=typeof t.initialState==`string`?t.initialState:``,a=Array.isArray(t.finalStates)?t.finalStates.filter(e=>typeof e==`string`):[];return{mermaidDiagram:this.getInferrer().generateMermaid({states:n.filter(e=>S(e)),transitions:r.filter(e=>S(e)),initial:i,initialState:i,finalStates:a})}}catch(e){return{mermaidDiagram:`stateDiagram-v2\n note right of empty: ${this.errorMessage(e)}`}}}},dt=class extends ut{async handlePayloadTemplateBuild(e){try{let t=e.fields;if(!Array.isArray(t))throw Error(`fields must be an array`);let{payload:n,segments:r}=ve(t.map((e,t)=>ge(e,t)),w(e.endian));return this.emitEvent(`protocol:payload_built`,{byteLength:n.length,fieldCount:r.length}),{hexPayload:n.toString(`hex`),byteLength:n.length,fields:r,success:!0}}catch(e){return{hexPayload:``,byteLength:0,fields:[],success:!1,error:this.errorMessage(e)}}}async handlePayloadMutate(e){let t=``;try{if(typeof e.hexPayload!=`string`)throw Error(`hexPayload must be a string`);t=j(e.hexPayload,`hexPayload`);let n=e.mutations;if(!Array.isArray(n))throw Error(`mutations must be an array`);let r=Buffer.from(t,`hex`),i=[];for(let[e,t]of n.entries()){let n=ye(t,e),a=be(r,n,e);r=a.payload,i.push(a.summary)}return this.emitEvent(`protocol:payload_mutated`,{byteLength:r.length,mutationCount:i.length}),{originalHex:t,mutatedHex:r.toString(`hex`),byteLength:r.length,appliedMutations:i,success:!0}}catch(e){return{originalHex:t,mutatedHex:``,byteLength:0,appliedMutations:[],success:!1,error:this.errorMessage(e)}}}},ft=class extends dt{async handleEthernetFrameBuild(e){try{let t=L(e.destinationMac,`destinationMac`),n=L(e.sourceMac,`sourceMac`),r=V(e.etherType,`etherType`),i=Ae(t,n,r,H(e.payloadHex,`payloadHex`));return this.emitEvent(`protocol:ethernet_frame_built`,{byteLength:i.length,etherType:`0x${r.toString(16).padStart(4,`0`)}`}),{destinationMac:t.canonical,sourceMac:n.canonical,etherType:r,etherTypeHex:`0x${r.toString(16).padStart(4,`0`)}`,byteLength:i.length,headerHex:i.subarray(0,14).toString(`hex`),frameHex:i.toString(`hex`),success:!0}}catch(e){return{destinationMac:``,sourceMac:``,etherType:0,etherTypeHex:`0x0000`,byteLength:0,headerHex:``,frameHex:``,success:!1,error:this.errorMessage(e)}}}async handleArpBuild(e){try{let t=e.operation===`reply`?`reply`:`request`,n=L(e.senderMac,`senderMac`),r=L(e.targetMac??`00:00:00:00:00:00`,`targetMac`),i=R(e.senderIp,`senderIp`),a=R(e.targetIp,`targetIp`),o=je({operation:t,hardwareType:e.hardwareType===void 0?1:T(e.hardwareType,`hardwareType`),protocolType:V(e.protocolType??`ipv4`,`protocolType`),hardwareSize:e.hardwareSize===void 0?6:E(e.hardwareSize,`hardwareSize`),protocolSize:e.protocolSize===void 0?4:E(e.protocolSize,`protocolSize`),senderMac:n,senderIp:i,targetMac:r,targetIp:a});return this.emitEvent(`protocol:arp_built`,{operation:t,byteLength:o.length}),{operation:t,byteLength:o.length,payloadHex:o.toString(`hex`),senderMac:n.canonical,senderIp:e.senderIp,targetMac:r.canonical,targetIp:e.targetIp,success:!0}}catch(e){return{operation:null,byteLength:0,payloadHex:``,senderMac:``,senderIp:``,targetMac:``,targetIp:``,success:!1,error:this.errorMessage(e)}}}},pt=class extends ft{async handleRawIpPacketBuild(e){try{let t=e.version===`ipv6`?`ipv6`:`ipv4`,n=H(e.payloadHex??``,`payloadHex`),r=Te(e.protocol,`protocol`),i=e.dscp===void 0?0:T(e.dscp,`dscp`),a=e.ecn===void 0?0:T(e.ecn,`ecn`);if(i>63)throw Error(`dscp must be between 0 and 63`);if(a>3)throw Error(`ecn must be between 0 and 3`);if(t===`ipv4`){let o=e.ttl===void 0?64:O(e.ttl,`ttl`),s=e.identification===void 0?0:T(e.identification,`identification`),c=e.fragmentOffset===void 0?0:T(e.fragmentOffset,`fragmentOffset`);if(s>65535)throw Error(`identification must be between 0 and 65535`);if(c>8191)throw Error(`fragmentOffset must be between 0 and 8191`);let{packet:l,checksum:u}=Me({sourceIp:B(e.sourceIp,`ipv4`,`sourceIp`),destinationIp:B(e.destinationIp,`ipv4`,`destinationIp`),protocol:r,payload:n,ttl:o,identification:s,dontFragment:e.dontFragment===!0,moreFragments:e.moreFragments===!0,fragmentOffset:c,dscp:i,ecn:a});return this.emitEvent(`protocol:ip_packet_built`,{version:t,protocol:r,byteLength:l.length}),{version:t,protocol:r,byteLength:l.length,headerLength:20,packetHex:l.toString(`hex`),headerHex:l.subarray(0,20).toString(`hex`),payloadHex:n.toString(`hex`),checksumHex:u.toString(16).padStart(4,`0`),success:!0}}let o=e.hopLimit===void 0?e.ttl===void 0?64:O(e.ttl,`ttl`):O(e.hopLimit,`hopLimit`),s=e.flowLabel===void 0?0:T(e.flowLabel,`flowLabel`);if(s>1048575)throw Error(`flowLabel must be between 0 and 1048575`);let c=Ne({sourceIp:B(e.sourceIp,`ipv6`,`sourceIp`),destinationIp:B(e.destinationIp,`ipv6`,`destinationIp`),protocol:r,payload:n,hopLimit:o,dscp:i,ecn:a,flowLabel:s});return this.emitEvent(`protocol:ip_packet_built`,{version:t,protocol:r,byteLength:c.length}),{version:t,protocol:r,byteLength:c.length,headerLength:40,packetHex:c.toString(`hex`),headerHex:c.subarray(0,40).toString(`hex`),payloadHex:n.toString(`hex`),checksumHex:null,success:!0}}catch(e){return{version:null,protocol:null,byteLength:0,headerLength:0,packetHex:``,headerHex:``,payloadHex:``,checksumHex:null,success:!1,error:this.errorMessage(e)}}}async handleIcmpEchoBuild(e){try{let t=e.operation===`reply`?`reply`:`request`,n=e.identifier===void 0?0:T(e.identifier,`identifier`),r=e.sequenceNumber===void 0?0:T(e.sequenceNumber,`sequenceNumber`);if(n>65535)throw Error(`identifier must be between 0 and 65535`);if(r>65535)throw Error(`sequenceNumber must be between 0 and 65535`);let i=H(e.payloadHex??``,`payloadHex`),{packet:a,checksum:o}=Pe({operation:t,identifier:n,sequenceNumber:r,payload:i}),s=o.toString(16).padStart(4,`0`);return this.emitEvent(`protocol:icmp_echo_built`,{operation:t,byteLength:a.length,checksumHex:s}),{operation:t,identifier:n,sequenceNumber:r,checksum:o,checksumHex:s,byteLength:a.length,packetHex:a.toString(`hex`),payloadHex:i.toString(`hex`),success:!0}}catch(e){return{operation:null,identifier:null,sequenceNumber:null,checksum:null,checksumHex:``,byteLength:0,packetHex:``,payloadHex:``,success:!1,error:this.errorMessage(e)}}}},mt=class extends pt{async handleChecksumApply(e){try{let t=H(e.hexPayload,`hexPayload`),n=e.startOffset===void 0?0:T(e.startOffset,`startOffset`),r=e.endOffset===void 0?t.length:T(e.endOffset,`endOffset`);if(n>r||r>t.length)throw Error(`checksum range must stay within the payload`);let i=e.zeroOffset===void 0?void 0:T(e.zeroOffset,`zeroOffset`),a=e.zeroLength===void 0?2:E(e.zeroLength,`zeroLength`),o=e.writeOffset===void 0?i:T(e.writeOffset,`writeOffset`),s=De(e.endian),c=Buffer.from(t);if(i!==void 0){if(i+a>c.length)throw Error(`zeroOffset and zeroLength must stay within the payload`);c.fill(0,i,i+a)}let l=U(c.subarray(n,r));if(o!==void 0){if(o+2>c.length)throw Error(`writeOffset must leave room for a 16-bit checksum field`);s===`little`?c.writeUInt16LE(l,o):c.writeUInt16BE(l,o)}let u=l.toString(16).padStart(4,`0`);return this.emitEvent(`protocol:checksum_applied`,{checksumHex:u,byteLength:c.length}),{checksumHex:u,checksum:l,mutatedHex:c.toString(`hex`),byteLength:c.length,rangeStart:n,rangeEnd:r,success:!0}}catch(e){return{checksumHex:``,checksum:0,mutatedHex:``,byteLength:0,rangeStart:0,rangeEnd:0,success:!1,error:this.errorMessage(e)}}}},ht=class extends mt{},gt=class extends ht{async handlePcapWrite(e){try{let t=this.parseRequiredPath(e);if(!Array.isArray(e.packets))throw Error(`packets must be an array`);let n=e.packets.map((e,t)=>Le(e,t)),r=Oe(e.endianness),i=ke(e.timestampPrecision),a=e.snapLength===void 0?65535:E(e.snapLength,`snapLength`),o=Ee(e.linkType??`ethernet`,`linkType`),s=Re({packets:n,endianness:r,timestampPrecision:i,snapLength:a,linkType:o});return await u(t,s),this.emitEvent(`protocol:pcap_written`,{path:t,packetCount:n.length,byteLength:s.length}),{path:t,packetCount:n.length,byteLength:s.length,endianness:r,timestampPrecision:i,linkType:o,success:!0}}catch(t){return{path:typeof e.path==`string`?e.path:``,packetCount:0,byteLength:0,endianness:null,timestampPrecision:null,linkType:null,success:!1,error:this.errorMessage(t)}}}async handlePcapRead(e){try{let t=this.parseRequiredPath(e),n=e.maxPackets===void 0?void 0:E(e.maxPackets,`maxPackets`),r=e.maxBytesPerPacket===void 0?void 0:E(e.maxBytesPerPacket,`maxBytesPerPacket`),{header:i,packets:a}=ze(await l(t),n,r);return this.emitEvent(`protocol:pcap_read`,{path:t,packetCount:a.length}),{path:t,header:i,packets:a,success:!0}}catch(t){return{path:typeof e.path==`string`?e.path:``,header:null,packets:[],success:!1,error:this.errorMessage(t)}}}parseRequiredPath(e){if(typeof e.path!=`string`||e.path.trim().length===0)throw Error(`path must be a non-empty string`);return e.path}},_t=class extends gt{},vt=class extends _t{async handleProtoFingerprint(o){let c=s(o,`hexPayloads`),l=o.includeKnownProtocols!==!1,u=o.includeFieldHints!==!1;return c.length===0?a({success:!1,error:`hexPayloads is required`}):a({success:!0,fingerprints:c.map((a,o)=>{let s=a.replace(/\s/g,``),c=[],d=s.length/2,f=d>=5?y(s,3):-1,p=Number.isFinite(f)&&f>=0&&d>=5+f,ee=p&&f>=t&&v(s,0)===22&&v(s,5)===1,m=ie(s),h=Object.keys(g).some(e=>s.toUpperCase().startsWith(e)),_=s.toUpperCase().startsWith(`5353482D`),b=s.length>=4&&(()=>{let e=v(s,0),t=v(s,1),n=e&15;if(n===0)return!1;let r=n<=10&&!(n>=3&&n<=7),i=(t>>7&1)==1,a=s.length/2,o=t&127,c=2;if(o===126){if(a<4)return!1;o=y(s,2),c=4}else if(o===127){if(a<10)return!1;let e=y(s,2)<<16|y(s,4),t=y(s,6)<<16|y(s,8);o=e>0?4294967295:t,c=10}return r&&a>=c+(i?4:0)+o})(),x=null;if(ee)c.push({protocol:`TLS ClientHello`,layer:`L6-TLS`,confidence:i}),u&&(x=ne(s));else if(h)c.push({protocol:`HTTP/1.x`,layer:`L7-HTTP`,confidence:e}),u&&(x={method:Object.entries(g).find(([e])=>s.toUpperCase().startsWith(e))?.[1]??`UNKNOWN`,httpVersion:s.indexOf(`2048545450`)>0?`1.x`:`unknown`});else if(_)c.push({protocol:`SSH`,layer:`L7-SSH`,confidence:r}),u&&s.length>=20&&(x={banner:Buffer.from(s.substring(0,Math.min(s.length,80)),`hex`).toString(`ascii`)});else if(b){if(c.push({protocol:`WebSocket`,layer:`L7-WS`,confidence:n}),u&&s.length>=4){let e=v(s,0),t=v(s,1),n=e&15,r=t>>7&1,i=t&127,a=2;if(i===126)i=s.length>=4?y(s,2):0,a=4;else if(i===127){if(s.length>=20){let e=y(s,2)<<16|y(s,4),t=y(s,6)<<16|y(s,8);i=e>0?4294967295:t}else i=0;a=10}r&&(a+=4),x={fin:e>>7&1,rsv1:e>>6&1,opcode:n,opcodeName:te[n]??`reserved(${n})`,masked:!!r,payloadLength:i,headerSize:a}}}else m&&(c.push({protocol:`DNS`,layer:`L7-DNS`,confidence:.85}),u&&(x=re(s)));l&&c.length===0&&(p&&/^160301|^160302|^160303/i.test(s.substring(0,8))&&c.push({protocol:`TLS Record`,layer:`L6-TLS`,confidence:.9}),s.substring(0,8).startsWith(`50524920`)&&c.push({protocol:`HTTP/2 PRI`,layer:`L7-HTTP2`,confidence:.9}));let S=[];if(u&&!x&&s.length>=8){let e=y(s,0);e>0&&e<s.length/2&&S.push({offset:0,hint:`possible length field (${e} bytes)`})}return{index:o,size:d,protocolMatches:c.length>0?c:[{protocol:`unknown`,layer:`unknown`,confidence:0}],...x?{parsedFields:x}:{},...S.length>0?{fieldHints:S}:{}}})})}},yt=class extends vt{};export{yt as ProtocolAnalysisHandlers};
4
+ `)}inferStateMachine(e){let t=e.map(e=>({direction:e.direction===`out`?`req`:`res`,timestamp:e.timestamp??0,fields:{},raw:e.payload.length>0?e.payload.toString(`utf8`):e.payload.toString(`hex`),rawBuffer:e.payload}));return this.infer(t)}generateMermaid(e){return this.visualize(e)}simplify(e){if(e.states.length<2)return{...e,initialState:e.initialState??e.initial,finalStates:e.finalStates??this.collectTerminalStates(e.states)};let t=new Map,n=new Map;for(let r of e.states){let e=this.getPayloadPrefix(r);if(!e)continue;let i=[...n.entries()].find(([t])=>t===e);i?t.set(r.id,i[0]):(n.set(e,r.id),t.set(r.id,e))}let r=new Map,i=new Map;for(let[e,t]of n)i.set(e,t);for(let t of e.states){let e=this.getPayloadPrefix(t);if(!e)continue;let n=i.get(e);n&&n!==t.id&&r.set(t.id,n)}if(r.size===0)return{...e,initialState:e.initialState??e.initial,finalStates:e.finalStates??this.collectTerminalStates(e.states)};let a=e.states.filter(e=>!r.has(e.id)),o=e.transitions.map(e=>({...e,from:r.get(e.from)??e.from,to:r.get(e.to)??e.to})).filter(e=>e.from!==e.to),s=e.initialState??e.initial??``,c=r.get(s)??s;return{states:a,transitions:o,initial:c,initialState:c,finalStates:e.finalStates.map(e=>r.get(e)??e).filter((e,t,n)=>n.indexOf(e)===t)}}getPayloadPrefix(e){let t=e.expectedPayload;return!t||t.length<8?null:t.slice(0,8).toLowerCase()}buildSignature(e){let t=Object.keys(e.fields).toSorted().join(`,`),n=$(e.rawBuffer?e.rawBuffer.toString(`hex`):e.raw).slice(0,24);return`${e.direction}|${t}|${n}`}buildStateName(e,t){let n=e.direction===`req`?`send`:`recv`,r=this.findPrimaryFieldName(e.fields),i=e.raw;if(i.length===0)return`${n}_empty`;let a=e.rawBuffer,o=Buffer.isBuffer(a)?a.toString(`hex`):i;if(o.startsWith(`16`)||o.startsWith(`15`)||o.startsWith(`17`))return`${n}_tls_handshake`;let s=i.trimStart();if(s.startsWith(`{`)||s.startsWith(`[`))return`${n}_json_${r||`step_${t}`}`;if(ot(i)>=.7){let e=$(i);return e.includes(`close`)||e.includes(`fin`)||e.includes(`bye`)?`${n}_close`:e.startsWith(`get `)||e.startsWith(`post `)||e.startsWith(`http`)?`${n}_text_http`:`${n}_text_${r||`step_${t}`}`}return Buffer.isBuffer(a)&&a.length>=32&&at(a)>6?`${n}_encrypted`:Buffer.isBuffer(a)&&a.length<=4?`${n}_control`:`${n}_${r||`step_${t}`}`}findPrimaryFieldName(e){return Object.keys(e).toSorted()[0]||``}inferStateType(e,t){let n=$(e.raw),r=this.findStatusValue(e.fields);return this.containsRejectSignal(n)||this.containsRejectSignal(r)?`reject`:this.containsAcceptSignal(n)||this.containsAcceptSignal(r)||t&&e.direction===`res`?`accept`:`normal`}mergeStateTypes(e,t){return e===`reject`||t===`reject`?`reject`:e===`accept`||t===`accept`?`accept`:`normal`}findStatusValue(e){for(let t of[`status`,`result`,`code`,`reason`,`message`]){let n=e[t];if(typeof n==`string`||typeof n==`number`||typeof n==`boolean`)return String(n)}return``}containsRejectSignal(e){return[`error`,`fail`,`denied`,`reject`,`timeout`,`invalid`].some(t=>$(e).includes(t))}containsAcceptSignal(e){return[`ok`,`success`,`accept`,`ready`,`done`,`complete`].some(t=>$(e).includes(t))}buildEventName(e){let t=this.findStatusValue(e.fields);if(t)return`${e.direction}_${$(t).replace(/[^a-z0-9]+/g,`_`)}`;let n=this.findPrimaryFieldName(e.fields);return n?`${e.direction}_${n}`:`${e.direction}_message`}buildCondition(e){let t=this.findStatusValue(e);if(t)return`status=${t}`;let n=Object.keys(e).toSorted().slice(0,2);if(n.length===0)return;let r=[];for(let t of n){let n=e[t];(typeof n==`string`||typeof n==`number`||typeof n==`boolean`)&&r.push(`${t}=${n}`)}return r.length>0?r.join(`, `):void 0}buildAction(e){let t=this.findStatusValue(e.fields);if(this.containsRejectSignal(t)||this.containsRejectSignal(e.raw))return`reject`;if(this.containsAcceptSignal(t)||this.containsAcceptSignal(e.raw))return`complete`;let n=$(e.raw);if(n.includes(`ack`))return`acknowledge`;if(n.includes(`retry`))return`retry`;if(Object.keys(e.fields).length>0&&it(e.fields))return e.direction===`req`?`send`:`receive`}collectTerminalStates(e){let t=e.filter(e=>{let t=e.type??`normal`;return t===`accept`||t===`reject`}).map(e=>e.id);for(let n of e){let e=$(n.name);(e.includes(`close`)||e.includes(`fin`)||e.includes(`bye`))&&(t.includes(n.id)||t.push(n.id))}return t}computeTransitionConfidence(e){let t=.3;return Object.keys(e.fields).length>0&&(t+=.3),this.findStatusValue(e.fields)&&(t+=.2),e.raw.length>0&&(t+=.2),Math.min(t,1)}};const ct={states:[],transitions:[],initial:``,initialState:``,finalStates:[]};var lt=class{engine;inferrer;eventBus;constructor(e,t,n){this.engine=e,this.inferrer=t,this.eventBus=n}emitEvent(e,t){this.eventBus?.emit(e,{...t,timestamp:new Date().toISOString()})}getEngine(){return this.engine||=new rt,this.engine}getInferrer(){return this.inferrer||=new st,this.inferrer}errorMessage(e){return e instanceof Error?e.message:String(e)}},ut=class extends lt{async handleDefinePattern(e){try{let t=typeof e.name==`string`&&e.name.trim().length>0?e.name:`unnamed_pattern`,n=o(e,`spec`);if(n){let e=se(t,n);return this.getEngine().definePattern(t,e),{patternId:t,pattern:this.getEngine().getPattern(t)??{name:t,fields:[],byteOrder:`big`},success:!0}}let r=(Array.isArray(e.fields)?e.fields:[]).map((e,t)=>oe(e,t)),i=e.byteOrder===`little`||e.byteOrder===`big`?e.byteOrder:void 0,a=ce(e.encryption);return{patternId:t,pattern:this.getEngine().definePattern(t,r,{...i?{byteOrder:i}:{},...a?{encryption:a}:{}}),success:!0}}catch(e){return{patternId:`error`,pattern:{name:`error`,fields:[],byteOrder:`big`},success:!1,error:this.errorMessage(e)}}}async handleAutoDetect(e){try{let t=(()=>{let t=s(e,`hexPayloads`);return t.length>0?t:s(e,`payloads`)})(),n=this.getEngine().autoDetect(t),r=typeof e.name==`string`&&e.name.trim().length>0?e.name:void 0;if(!n)return{patterns:[this.getEngine().autoDetectPattern([],r?{name:r}:{})],success:!0};let i={...n,name:r??n.name};this.getEngine().definePattern(i.name,i);let a=this.getEngine().getPattern(i.name)??{name:i.name,fields:[],byteOrder:`big`};return this.emitEvent(`protocol:pattern_detected`,{patternName:i.name,confidence:0}),{patterns:[a],success:!0}}catch(e){return{patterns:[],success:!1,error:this.errorMessage(e)}}}async handleInferFields(e){try{let t=s(e,`hexPayloads`);return{success:!0,fields:this.getEngine().inferFields(t)}}catch(e){return{fields:[],success:!1,error:this.errorMessage(e)}}}async handleExportSchema(e){try{let t=c(e,`patternId`),n=this.getEngine().getPattern(t);return n?{schema:this.getEngine().exportProto(n)}:{schema:`// Error: pattern '${t}' not found`}}catch(e){return{schema:`// Error: ${this.errorMessage(e)}`}}}async handleInferStateMachine(e){try{let t=e.messages;if(!Array.isArray(t))throw Error(`messages must be an array`);let n=t.some(e=>S(e)&&(e.direction===`in`||e.direction===`out`)),r;if(n){let e=t.map((e,t)=>{if(!S(e))throw Error(`messages[${t}] must be an object`);let n=e.direction,r=typeof e.payloadHex==`string`?e.payloadHex:``,i=typeof e.timestamp==`number`?e.timestamp:void 0,a=Buffer.from(r.replace(/\s+/g,``),`hex`);if(n!==`in`&&n!==`out`)throw Error(`messages[${t}].direction must be "in" or "out"`);return{direction:n,payload:a,...i===void 0?{}:{timestamp:i}}});r=this.getInferrer().inferStateMachine(e)}else{let e=t.map((e,t)=>le(e,t));r=this.getInferrer().infer(e)}return e.simplify===!0&&(r=this.getInferrer().simplify(r)),{stateMachine:r,mermaid:this.getInferrer().generateMermaid(r),success:!0}}catch(e){return{stateMachine:{...ct},success:!1,error:this.errorMessage(e)}}}async handleVisualizeState(e){try{let t=e.stateMachine;if(!S(t))return{mermaidDiagram:this.getInferrer().generateMermaid(ct)};let n=Array.isArray(t.states)?t.states:[],r=Array.isArray(t.transitions)?t.transitions:[],i=typeof t.initialState==`string`?t.initialState:``,a=Array.isArray(t.finalStates)?t.finalStates.filter(e=>typeof e==`string`):[];return{mermaidDiagram:this.getInferrer().generateMermaid({states:n.filter(e=>S(e)),transitions:r.filter(e=>S(e)),initial:i,initialState:i,finalStates:a})}}catch(e){return{mermaidDiagram:`stateDiagram-v2\n note right of empty: ${this.errorMessage(e)}`}}}},dt=class extends ut{async handlePayloadTemplateBuild(e){try{let t=e.fields;if(!Array.isArray(t))throw Error(`fields must be an array`);let{payload:n,segments:r}=ve(t.map((e,t)=>ge(e,t)),w(e.endian));return this.emitEvent(`protocol:payload_built`,{byteLength:n.length,fieldCount:r.length}),{hexPayload:n.toString(`hex`),byteLength:n.length,fields:r,success:!0}}catch(e){return{hexPayload:``,byteLength:0,fields:[],success:!1,error:this.errorMessage(e)}}}async handlePayloadMutate(e){let t=``;try{if(typeof e.hexPayload!=`string`)throw Error(`hexPayload must be a string`);t=j(e.hexPayload,`hexPayload`);let n=e.mutations;if(!Array.isArray(n))throw Error(`mutations must be an array`);let r=Buffer.from(t,`hex`),i=[];for(let[e,t]of n.entries()){let n=ye(t,e),a=be(r,n,e);r=a.payload,i.push(a.summary)}return this.emitEvent(`protocol:payload_mutated`,{byteLength:r.length,mutationCount:i.length}),{originalHex:t,mutatedHex:r.toString(`hex`),byteLength:r.length,appliedMutations:i,success:!0}}catch(e){return{originalHex:t,mutatedHex:``,byteLength:0,appliedMutations:[],success:!1,error:this.errorMessage(e)}}}},ft=class extends dt{async handleEthernetFrameBuild(e){try{let t=L(e.destinationMac,`destinationMac`),n=L(e.sourceMac,`sourceMac`),r=V(e.etherType,`etherType`),i=Ae(t,n,r,H(e.payloadHex,`payloadHex`));return this.emitEvent(`protocol:ethernet_frame_built`,{byteLength:i.length,etherType:`0x${r.toString(16).padStart(4,`0`)}`}),{destinationMac:t.canonical,sourceMac:n.canonical,etherType:r,etherTypeHex:`0x${r.toString(16).padStart(4,`0`)}`,byteLength:i.length,headerHex:i.subarray(0,14).toString(`hex`),frameHex:i.toString(`hex`),success:!0}}catch(e){return{destinationMac:``,sourceMac:``,etherType:0,etherTypeHex:`0x0000`,byteLength:0,headerHex:``,frameHex:``,success:!1,error:this.errorMessage(e)}}}async handleArpBuild(e){try{let t=e.operation===`reply`?`reply`:`request`,n=L(e.senderMac,`senderMac`),r=L(e.targetMac??`00:00:00:00:00:00`,`targetMac`),i=R(e.senderIp,`senderIp`),a=R(e.targetIp,`targetIp`),o=je({operation:t,hardwareType:e.hardwareType===void 0?1:T(e.hardwareType,`hardwareType`),protocolType:V(e.protocolType??`ipv4`,`protocolType`),hardwareSize:e.hardwareSize===void 0?6:E(e.hardwareSize,`hardwareSize`),protocolSize:e.protocolSize===void 0?4:E(e.protocolSize,`protocolSize`),senderMac:n,senderIp:i,targetMac:r,targetIp:a});return this.emitEvent(`protocol:arp_built`,{operation:t,byteLength:o.length}),{operation:t,byteLength:o.length,payloadHex:o.toString(`hex`),senderMac:n.canonical,senderIp:e.senderIp,targetMac:r.canonical,targetIp:e.targetIp,success:!0}}catch(e){return{operation:null,byteLength:0,payloadHex:``,senderMac:``,senderIp:``,targetMac:``,targetIp:``,success:!1,error:this.errorMessage(e)}}}},pt=class extends ft{async handleRawIpPacketBuild(e){try{let t=e.version===`ipv6`?`ipv6`:`ipv4`,n=H(e.payloadHex??``,`payloadHex`),r=Te(e.protocol,`protocol`),i=e.dscp===void 0?0:T(e.dscp,`dscp`),a=e.ecn===void 0?0:T(e.ecn,`ecn`);if(i>63)throw Error(`dscp must be between 0 and 63`);if(a>3)throw Error(`ecn must be between 0 and 3`);if(t===`ipv4`){let o=e.ttl===void 0?64:O(e.ttl,`ttl`),s=e.identification===void 0?0:T(e.identification,`identification`),c=e.fragmentOffset===void 0?0:T(e.fragmentOffset,`fragmentOffset`);if(s>65535)throw Error(`identification must be between 0 and 65535`);if(c>8191)throw Error(`fragmentOffset must be between 0 and 8191`);let{packet:l,checksum:u}=Me({sourceIp:B(e.sourceIp,`ipv4`,`sourceIp`),destinationIp:B(e.destinationIp,`ipv4`,`destinationIp`),protocol:r,payload:n,ttl:o,identification:s,dontFragment:e.dontFragment===!0,moreFragments:e.moreFragments===!0,fragmentOffset:c,dscp:i,ecn:a});return this.emitEvent(`protocol:ip_packet_built`,{version:t,protocol:r,byteLength:l.length}),{version:t,protocol:r,byteLength:l.length,headerLength:20,packetHex:l.toString(`hex`),headerHex:l.subarray(0,20).toString(`hex`),payloadHex:n.toString(`hex`),checksumHex:u.toString(16).padStart(4,`0`),success:!0}}let o=e.hopLimit===void 0?e.ttl===void 0?64:O(e.ttl,`ttl`):O(e.hopLimit,`hopLimit`),s=e.flowLabel===void 0?0:T(e.flowLabel,`flowLabel`);if(s>1048575)throw Error(`flowLabel must be between 0 and 1048575`);let c=Ne({sourceIp:B(e.sourceIp,`ipv6`,`sourceIp`),destinationIp:B(e.destinationIp,`ipv6`,`destinationIp`),protocol:r,payload:n,hopLimit:o,dscp:i,ecn:a,flowLabel:s});return this.emitEvent(`protocol:ip_packet_built`,{version:t,protocol:r,byteLength:c.length}),{version:t,protocol:r,byteLength:c.length,headerLength:40,packetHex:c.toString(`hex`),headerHex:c.subarray(0,40).toString(`hex`),payloadHex:n.toString(`hex`),checksumHex:null,success:!0}}catch(e){return{version:null,protocol:null,byteLength:0,headerLength:0,packetHex:``,headerHex:``,payloadHex:``,checksumHex:null,success:!1,error:this.errorMessage(e)}}}async handleIcmpEchoBuild(e){try{let t=e.operation===`reply`?`reply`:`request`,n=e.identifier===void 0?0:T(e.identifier,`identifier`),r=e.sequenceNumber===void 0?0:T(e.sequenceNumber,`sequenceNumber`);if(n>65535)throw Error(`identifier must be between 0 and 65535`);if(r>65535)throw Error(`sequenceNumber must be between 0 and 65535`);let i=H(e.payloadHex??``,`payloadHex`),{packet:a,checksum:o}=Pe({operation:t,identifier:n,sequenceNumber:r,payload:i}),s=o.toString(16).padStart(4,`0`);return this.emitEvent(`protocol:icmp_echo_built`,{operation:t,byteLength:a.length,checksumHex:s}),{operation:t,identifier:n,sequenceNumber:r,checksum:o,checksumHex:s,byteLength:a.length,packetHex:a.toString(`hex`),payloadHex:i.toString(`hex`),success:!0}}catch(e){return{operation:null,identifier:null,sequenceNumber:null,checksum:null,checksumHex:``,byteLength:0,packetHex:``,payloadHex:``,success:!1,error:this.errorMessage(e)}}}},mt=class extends pt{async handleChecksumApply(e){try{let t=H(e.hexPayload,`hexPayload`),n=e.startOffset===void 0?0:T(e.startOffset,`startOffset`),r=e.endOffset===void 0?t.length:T(e.endOffset,`endOffset`);if(n>r||r>t.length)throw Error(`checksum range must stay within the payload`);let i=e.zeroOffset===void 0?void 0:T(e.zeroOffset,`zeroOffset`),a=e.zeroLength===void 0?2:E(e.zeroLength,`zeroLength`),o=e.writeOffset===void 0?i:T(e.writeOffset,`writeOffset`),s=De(e.endian),c=Buffer.from(t);if(i!==void 0){if(i+a>c.length)throw Error(`zeroOffset and zeroLength must stay within the payload`);c.fill(0,i,i+a)}let l=U(c.subarray(n,r));if(o!==void 0){if(o+2>c.length)throw Error(`writeOffset must leave room for a 16-bit checksum field`);s===`little`?c.writeUInt16LE(l,o):c.writeUInt16BE(l,o)}let u=l.toString(16).padStart(4,`0`);return this.emitEvent(`protocol:checksum_applied`,{checksumHex:u,byteLength:c.length}),{checksumHex:u,checksum:l,mutatedHex:c.toString(`hex`),byteLength:c.length,rangeStart:n,rangeEnd:r,success:!0}}catch(e){return{checksumHex:``,checksum:0,mutatedHex:``,byteLength:0,rangeStart:0,rangeEnd:0,success:!1,error:this.errorMessage(e)}}}},ht=class extends mt{},gt=class extends ht{async handlePcapWrite(e){try{let t=this.parseRequiredPath(e);if(!Array.isArray(e.packets))throw Error(`packets must be an array`);let n=e.packets.map((e,t)=>Le(e,t)),r=Oe(e.endianness),i=ke(e.timestampPrecision),a=e.snapLength===void 0?65535:E(e.snapLength,`snapLength`),o=Ee(e.linkType??`ethernet`,`linkType`),s=Re({packets:n,endianness:r,timestampPrecision:i,snapLength:a,linkType:o});return await u(t,s),this.emitEvent(`protocol:pcap_written`,{path:t,packetCount:n.length,byteLength:s.length}),{path:t,packetCount:n.length,byteLength:s.length,endianness:r,timestampPrecision:i,linkType:o,success:!0}}catch(t){return{path:typeof e.path==`string`?e.path:``,packetCount:0,byteLength:0,endianness:null,timestampPrecision:null,linkType:null,success:!1,error:this.errorMessage(t)}}}async handlePcapRead(e){try{let t=this.parseRequiredPath(e),n=e.maxPackets===void 0?void 0:E(e.maxPackets,`maxPackets`),r=e.maxBytesPerPacket===void 0?void 0:E(e.maxBytesPerPacket,`maxBytesPerPacket`),{header:i,packets:a}=ze(await l(t),n,r);return this.emitEvent(`protocol:pcap_read`,{path:t,packetCount:a.length}),{path:t,header:i,packets:a,success:!0}}catch(t){return{path:typeof e.path==`string`?e.path:``,header:null,packets:[],success:!1,error:this.errorMessage(t)}}}parseRequiredPath(e){if(typeof e.path!=`string`||e.path.trim().length===0)throw Error(`path must be a non-empty string`);return e.path}},_t=class extends gt{},vt=class extends _t{async handleProtoFingerprint(o){let c=s(o,`hexPayloads`),l=o.includeKnownProtocols!==!1,u=o.includeFieldHints!==!1;return c.length===0?a({success:!1,error:`hexPayloads is required`}):a({success:!0,fingerprints:c.map((a,o)=>{let s=a.replace(/\s/g,``),c=[],d=s.length/2,f=d>=5?y(s,3):-1,p=Number.isFinite(f)&&f>=0&&d>=5+f,ee=p&&f>=i&&v(s,0)===22&&v(s,5)===1,m=ie(s),h=Object.keys(g).some(e=>s.toUpperCase().startsWith(e)),_=s.toUpperCase().startsWith(`5353482D`),b=s.length>=4&&(()=>{let e=v(s,0),t=v(s,1),n=e&15;if(n===0)return!1;let r=n<=10&&!(n>=3&&n<=7),i=(t>>7&1)==1,a=s.length/2,o=t&127,c=2;if(o===126){if(a<4)return!1;o=y(s,2),c=4}else if(o===127){if(a<10)return!1;let e=y(s,2)<<16|y(s,4),t=y(s,6)<<16|y(s,8);o=e>0?4294967295:t,c=10}return r&&a>=c+(i?4:0)+o})(),x=null;if(ee)c.push({protocol:`TLS ClientHello`,layer:`L6-TLS`,confidence:r}),u&&(x=ne(s));else if(h)c.push({protocol:`HTTP/1.x`,layer:`L7-HTTP`,confidence:n}),u&&(x={method:Object.entries(g).find(([e])=>s.toUpperCase().startsWith(e))?.[1]??`UNKNOWN`,httpVersion:s.indexOf(`2048545450`)>0?`1.x`:`unknown`});else if(_)c.push({protocol:`SSH`,layer:`L7-SSH`,confidence:t}),u&&s.length>=20&&(x={banner:Buffer.from(s.substring(0,Math.min(s.length,80)),`hex`).toString(`ascii`)});else if(b){if(c.push({protocol:`WebSocket`,layer:`L7-WS`,confidence:e}),u&&s.length>=4){let e=v(s,0),t=v(s,1),n=e&15,r=t>>7&1,i=t&127,a=2;if(i===126)i=s.length>=4?y(s,2):0,a=4;else if(i===127){if(s.length>=20){let e=y(s,2)<<16|y(s,4),t=y(s,6)<<16|y(s,8);i=e>0?4294967295:t}else i=0;a=10}r&&(a+=4),x={fin:e>>7&1,rsv1:e>>6&1,opcode:n,opcodeName:te[n]??`reserved(${n})`,masked:!!r,payloadLength:i,headerSize:a}}}else m&&(c.push({protocol:`DNS`,layer:`L7-DNS`,confidence:.85}),u&&(x=re(s)));l&&c.length===0&&(p&&/^160301|^160302|^160303/i.test(s.substring(0,8))&&c.push({protocol:`TLS Record`,layer:`L6-TLS`,confidence:.9}),s.substring(0,8).startsWith(`50524920`)&&c.push({protocol:`HTTP/2 PRI`,layer:`L7-HTTP2`,confidence:.9}));let S=[];if(u&&!x&&s.length>=8){let e=y(s,0);e>0&&e<s.length/2&&S.push({offset:0,hint:`possible length field (${e} bytes)`})}return{index:o,size:d,protocolMatches:c.length>0?c:[{protocol:`unknown`,layer:`unknown`,confidence:0}],...x?{parsedFields:x}:{},...S.length>0?{fieldHints:S}:{}}})})}},yt=class extends vt{};export{yt as ProtocolAnalysisHandlers};
@@ -0,0 +1 @@
1
+ import{n as e}from"./response-C7rKQst4.mjs";import{t}from"./ToolError-DWU_z7gp.mjs";import{t as n}from"./ToolProbe-C7ZU2x7M.mjs";import{a as r,r as i,s as a,t as o}from"./parse-args-Bw413PlW.mjs";import{join as s}from"node:path";import{mkdir as c}from"node:fs/promises";import{execFile as l}from"node:child_process";function u(e){return e instanceof Error?e.message:String(e)}function d(e){return e?[`-s`,e]:[]}async function f(e,t){return new Promise((n,r)=>{l(e,t,{encoding:`utf8`,windowsHide:!0},(e,t,i)=>{e?r(e):n({stdout:t??``,stderr:i??``})})})}async function p(e,t){let{stdout:n}=await f(e,[...d(t),`shell`,`cat /proc/net/unix`]),r=[];for(let e of n.split(/\r?\n/)){let t=e.trim();if(t.includes(`@webview_devtools_remote`)){let e=t.match(/@webview_devtools_remote\S+/);e&&r.push(e[0])}}return r}function m(e){return e.trim().replace(/\/+$/,``)}function h(e,t,n){let r=new Set;for(let i of[/nativeLibraryDir=([^\s]+)/g,/legacyNativeLibraryDir=([^\s]+)/g,/secondaryNativeLibraryDir=([^\s]+)/g]){let a;for(;(a=i.exec(e))!==null;){let e=m(a[1]??``);e&&(!n&&!e.includes(t)||r.add(e))}}return[...r]}var g=class{cachedAdb;async resolveAdb(){if(this.cachedAdb)return this.cachedAdb;let e=await n(`adb`);if(!e.available)throw new t(`PREREQUISITE`,e.reason??`adb not found in PATH. Install Android Platform Tools.`,{toolName:`adb-bridge`});return this.cachedAdb=e.path??`adb`,this.cachedAdb}async run(n,r){try{return e(await r())}catch(e){throw e instanceof t?e:new t(`RUNTIME`,u(e),{toolName:n})}}async handleDeviceList(e){return this.run(`adb_device_list`,async()=>{let{stdout:e}=await f(await this.resolveAdb(),[`devices`,`-l`]),t=[];for(let n of e.split(/\r?\n/)){let e=n.trim();if(!e||e.startsWith(`List of devices`))continue;let r=e.split(/\s+/),i=r[0];if(!i)continue;let a={};for(let e=2;e<r.length;e++){let t=r[e];if(!t)continue;let n=t.indexOf(`:`);if(n>0){let e=t.slice(0,n),r=t.slice(n+1);e&&r&&(a[e]=r)}}t.push({serial:i,state:r[1]??``,model:a.model??``,product:a.product??``})}return{success:!0,count:t.length,devices:t}})}async handleShell(e){return this.run(`adb_shell`,async()=>{let t=a(e,`serial`),n=a(e,`command`),{stdout:r,stderr:i}=await f(await this.resolveAdb(),[...d(t),`shell`,n]);return{success:!0,serial:t,command:n,stdout:r,stderr:i||``}})}async handleApkPull(e){return this.run(`adb_apk_pull`,async()=>{let t=a(e,`serial`),n=r(e,`packageName`),i=r(e,`outputPath`)??`.`;if(!n)return{success:!1,error:`packageName is required`};let o=await this.resolveAdb(),{stdout:c}=await f(o,[...d(t),`shell`,`pm path ${n}`]),l=c.match(/package:([\w./]+)/)?.[1];if(!l)return{success:!1,error:`APK not found for ${n}`,raw:c};let u=s(i,`${n}.apk`).replace(/\\/g,`/`);return await f(o,[...d(t),`pull`,l,u]),{success:!0,serial:t,packageName:n,remotePath:l,localPath:u}})}async handleAnalyzeApk(e){return this.run(`adb_apk_analyze`,async()=>{let t=a(e,`serial`),n=a(e,`packageName`),{stdout:r}=await f(await this.resolveAdb(),[...d(t),`shell`,`dumpsys package ${n}`]),i={packageName:n},o=r.match(/versionName=([^\s]+)/);o?.[1]&&(i.versionName=o[1]);let s=r.match(/versionCode=(\d+)/);s?.[1]&&(i.versionCode=s[1]);let c=r.match(/minSdk=(\d+)/);c?.[1]&&(i.minSdk=c[1]);let l=r.match(/targetSdk=(\d+)/);l?.[1]&&(i.targetSdk=l[1]);let u=[],p=[],m=[],h=[],g=``;for(let e of r.split(/\r?\n/)){if(e.includes(`requested permissions:`)||e.includes(`install permissions:`)){g=`permissions`;continue}if(e.includes(`Activity Resolver Table`)||e.includes(`activities:`)){g=`activities`;continue}if(e.includes(`Service Resolver Table`)||e.includes(`services:`)){g=`services`;continue}if(e.includes(`Receiver Resolver Table`)||e.includes(`receivers:`)){g=`receivers`;continue}let t=e.trim(),r=t.split(` `)[0];g===`permissions`?r&&t.startsWith(`android.permission.`)&&u.push(r):g===`activities`&&t.includes(n)?r&&p.push(r):g===`services`&&t.includes(n)?r&&m.push(r):g===`receivers`&&t.includes(n)&&r&&h.push(r)}return i.permissions=[...new Set(u)],i.activities=[...new Set(p)],i.services=[...new Set(m)],i.receivers=[...new Set(h)],{success:!0,serial:t,...i}})}async handlePullNativeLibs(e){return this.run(`adb_pull_native_libs`,async()=>{let t=a(e,`serial`),n=a(e,`packageName`),i=r(e,`outputPath`)??`.`,l=o(e,`includeSystemLibs`)??!1,u=await this.resolveAdb(),{stdout:p}=await f(u,[...d(t),`shell`,`dumpsys package ${n}`]),m=h(p,n,l);if(m.length===0)return{success:!1,serial:t,packageName:n,error:`No native library directories found for ${n}`};let g=s(i,`${n}-native-libs`).replace(/\\/g,`/`);await c(g,{recursive:!0});let _=[];for(let e of m){let n=s(g,e.split(`/`).filter(Boolean).pop()??`lib`).replace(/\\/g,`/`);await c(n,{recursive:!0}),await f(u,[...d(t),`pull`,e,n]),_.push({remoteDir:e,localPath:n})}return{success:!0,serial:t,packageName:n,includeSystemLibs:l,count:_.length,outputPath:g,libraries:_}})}async handleWebViewList(e){return this.run(`adb_webview_list`,async()=>{let t=a(e,`serial`),n=i(e,`hostPort`)??9222,r=await this.resolveAdb(),o=await p(r,t);if(o.length===0)return{success:!0,serial:t,hostPort:n,webviews:[],count:0};let s=o[0];await f(r,[...d(t),`forward`,`tcp:${n}`,`localabstract:${s}`]);let c=await import(`node:http`),l=await new Promise(e=>{c.get(`http://localhost:${n}/json/list`,t=>{let n=``;t.on(`data`,e=>{n+=e}),t.on(`end`,()=>{try{e(JSON.parse(n))}catch{e([])}})}).on(`error`,()=>e([]))});return{success:!0,serial:t,hostPort:n,webviews:l.map(e=>({id:e.id,url:e.url,title:e.title,webSocketDebuggerUrl:e.webSocketDebuggerUrl})),count:l.length}})}async handleWebViewAttach(e){return this.run(`adb_webview_attach`,async()=>{let t=a(e,`serial`),n=a(e,`targetId`),r=i(e,`hostPort`)??9222,o=await this.resolveAdb(),s=await p(o,t);if(s.length===0)return{success:!1,error:`No WebView devtools sockets found on device`};let c=s[0];await f(o,[...d(t),`forward`,`tcp:${r}`,`localabstract:${c}`]);let l=await import(`node:http`),u=await new Promise(e=>{l.get(`http://localhost:${r}/json`,t=>{let r=``;t.on(`data`,e=>{r+=e}),t.on(`end`,()=>{try{e(JSON.parse(r).find(e=>e.id===n)?.webSocketDebuggerUrl)}catch{e(void 0)}})}).on(`error`,()=>e(void 0))});return u?{success:!0,serial:t,targetId:n,hostPort:r,webSocketDebuggerUrl:u,attached:!0}:{success:!1,error:`Target ${n} not found`}})}};export{g as ADBBridgeHandlers};
@@ -1,2 +1,2 @@
1
- import{t as e}from"./logger-sBC6IdRT.mjs";import{vt as t,yt as n}from"./constants-Cp6hBrrx.mjs";import{i as r}from"./outputPaths-BonGThuc.mjs";import{n as i}from"./WorkflowEngine-CxEp2WXH.mjs";import{extname as a,resolve as o}from"node:path";import{readFile as s,readdir as c}from"node:fs/promises";function l(e){return`kind`in e?e:e.build()}function u(e,t){return t?.(e),e}function d(e,t){let n={},r,i,a,o;return n.input=e=>(r=e,n),n.inputFrom=e=>(i=e,n),n.retry=e=>(a=e,n),n.timeout=e=>(o=e,n),n.build=()=>({kind:`tool`,id:e,toolName:t,input:r,inputFrom:i,retry:a,timeoutMs:o}),n}function f(e,t){return t?typeof t==`function`?(t(e),e):(t.input&&e.input(t.input),t.inputFrom&&e.inputFrom(t.inputFrom),t.retry&&e.retry(t.retry),t.timeoutMs!==void 0&&e.timeout(t.timeoutMs),e):e}function p(e,t){return e.step=n=>(t.push(n),e),e.tool=(n,r,i)=>(t.push(f(d(n,r),i)),e),e.sequence=(n,r)=>(t.push(u(m(n),r)),e),e.parallel=(n,r)=>(t.push(u(h(n),r)),e),e.branch=(n,r,i)=>(t.push(u(g(n,r),i)),e),e.fallback=(n,r)=>(t.push(u(_(n),r)),e),e}function m(e){let t=[],n=p({},t);return n.build=()=>({kind:`sequence`,id:e,steps:t.map(l)}),n}function h(e){let t=[],n=p({},t),r=4,i=!1;return n.maxConcurrency=e=>(r=e,n),n.failFast=e=>(i=e,n),n.build=()=>({kind:`parallel`,id:e,steps:t.map(l),maxConcurrency:r,failFast:i}),n}function g(e,t){let n={},r,i,a;return n.predicateFn=e=>(r=e,n),n.whenTrue=e=>(i=e,n),n.whenFalse=e=>(a=e,n),n.build=()=>{if(!i)throw Error(`BranchNode '${e}' requires a whenTrue step`);return{kind:`branch`,id:e,predicateId:t,predicateFn:r,whenTrue:l(i),whenFalse:a?l(a):void 0}},n}function _(e){let t={},n,r;return t.primary=e=>(n=e,t),t.fallback=e=>(r=e,t),t.build=()=>{if(!n)throw Error(`FallbackNode '${e}' requires a primary step`);if(!r)throw Error(`FallbackNode '${e}' requires a fallback step`);return{kind:`fallback`,id:e,primary:l(n),fallback:l(r)}},t}function v(e,t){let n={},r,i,a,o,s,c,l,u,d;return n.description=e=>(r=e,n),n.tags=e=>(i=e,n),n.timeoutMs=e=>(a=e,n),n.defaultMaxConcurrency=e=>(o=e,n),n.route=e=>(s=e,n),n.buildGraph=e=>(c=e,n),n.onStart=e=>(l=e,n),n.onFinish=e=>(u=e,n),n.onError=e=>(d=e,n),n.build=()=>{if(!c)throw Error(`Workflow '${e}' needs a buildGraph() function.`);return{kind:`workflow-contract`,version:1,id:e,displayName:t,description:r,tags:i,timeoutMs:a,defaultMaxConcurrency:o,route:s,build:c,onStart:l,onFinish:u,onError:d}},n}function y(e,t,n){let r=v(e,t);return n(r),r.build()}function b(e,t,n){return f(d(e,t),n).build()}function x(e,t){return u(m(e),t).build()}var S=class{ctx;constructor(e){this.ctx=e}buildWorkflowFromDefinition(e){return y(e.id,e.displayName,t=>t.description(e.description).tags(e.tags).timeoutMs(e.timeoutMs??n).buildGraph(()=>x(`${e.id}-root`,t=>{for(let n of e.steps)t.step(b(n.id,n.toolName,e=>{e.input(n.input??{}).timeout(n.timeoutMs??0),n.inputFrom&&e.inputFrom(n.inputFrom)}))})).onStart(t=>{t.emitSpan(`macro.start`,{macroId:e.id,totalSteps:e.steps.length})}).onError((t,n)=>{t.emitSpan(`macro.error`,{macroId:e.id,error:n.message})}))}async execute(e,t){let n=this.buildWorkflowFromDefinition(e),r=Date.now();try{let r=await i(this.ctx,n,{nodeInputOverrides:t}),a=this.buildProgress(e,r.spans,r.stepResults);return{macroId:e.id,displayName:e.displayName,ok:!0,durationMs:r.durationMs,stepsCompleted:e.steps.length,totalSteps:e.steps.length,stepResults:r.stepResults,progress:a}}catch(t){let n=Date.now()-r,i=t instanceof Error?t.message:String(t),a=this.buildPartialProgress(e,i);return{macroId:e.id,displayName:e.displayName,ok:!1,durationMs:n,stepsCompleted:a.filter(e=>e.status===`complete`).length,totalSteps:e.steps.length,stepResults:{},progress:a,error:i}}}formatProgressReport(e){let t=[];t.push(`**Macro:** ${e.displayName} (\`${e.macroId}\`)`),t.push(``);for(let n of e.progress){let e=n.durationMs===void 0?``:` (${n.durationMs}ms)`,r=n.error?`: ${n.error}`:``,i=n.status===`complete`?`✓`:n.status===`failed`?`✗`:`○`;t.push(`[stage ${n.step}/${n.totalSteps}] ${i} ${n.stepName} — ${n.status}${e}${r}`)}return t.push(``),e.ok?t.push(`✓ Macro complete (${e.stepsCompleted}/${e.totalSteps} steps, ${e.durationMs}ms)`):t.push(`✗ Macro failed at step ${e.stepsCompleted+1}/${e.totalSteps}: ${e.error??`unknown error`}`),t.join(`
1
+ import{t as e}from"./logger-sBC6IdRT.mjs";import{It as t,Lt as n}from"./constants-BYj8Xek8.mjs";import{i as r}from"./outputPaths-B4Ic4RZh.mjs";import{n as i}from"./WorkflowEngine-D876meOO.mjs";import{extname as a,resolve as o}from"node:path";import{readFile as s,readdir as c}from"node:fs/promises";function l(e){return`kind`in e?e:e.build()}function u(e,t){return t?.(e),e}function d(e,t){let n={},r,i,a,o;return n.input=e=>(r=e,n),n.inputFrom=e=>(i=e,n),n.retry=e=>(a=e,n),n.timeout=e=>(o=e,n),n.build=()=>({kind:`tool`,id:e,toolName:t,input:r,inputFrom:i,retry:a,timeoutMs:o}),n}function f(e,t){return t?typeof t==`function`?(t(e),e):(t.input&&e.input(t.input),t.inputFrom&&e.inputFrom(t.inputFrom),t.retry&&e.retry(t.retry),t.timeoutMs!==void 0&&e.timeout(t.timeoutMs),e):e}function p(e,t){return e.step=n=>(t.push(n),e),e.tool=(n,r,i)=>(t.push(f(d(n,r),i)),e),e.sequence=(n,r)=>(t.push(u(m(n),r)),e),e.parallel=(n,r)=>(t.push(u(h(n),r)),e),e.branch=(n,r,i)=>(t.push(u(g(n,r),i)),e),e.fallback=(n,r)=>(t.push(u(_(n),r)),e),e}function m(e){let t=[],n=p({},t);return n.build=()=>({kind:`sequence`,id:e,steps:t.map(l)}),n}function h(e){let t=[],n=p({},t),r=4,i=!1;return n.maxConcurrency=e=>(r=e,n),n.failFast=e=>(i=e,n),n.build=()=>({kind:`parallel`,id:e,steps:t.map(l),maxConcurrency:r,failFast:i}),n}function g(e,t){let n={},r,i,a;return n.predicateFn=e=>(r=e,n),n.whenTrue=e=>(i=e,n),n.whenFalse=e=>(a=e,n),n.build=()=>{if(!i)throw Error(`BranchNode '${e}' requires a whenTrue step`);return{kind:`branch`,id:e,predicateId:t,predicateFn:r,whenTrue:l(i),whenFalse:a?l(a):void 0}},n}function _(e){let t={},n,r;return t.primary=e=>(n=e,t),t.fallback=e=>(r=e,t),t.build=()=>{if(!n)throw Error(`FallbackNode '${e}' requires a primary step`);if(!r)throw Error(`FallbackNode '${e}' requires a fallback step`);return{kind:`fallback`,id:e,primary:l(n),fallback:l(r)}},t}function v(e,t){let n={},r,i,a,o,s,c,l,u,d;return n.description=e=>(r=e,n),n.tags=e=>(i=e,n),n.timeoutMs=e=>(a=e,n),n.defaultMaxConcurrency=e=>(o=e,n),n.route=e=>(s=e,n),n.buildGraph=e=>(c=e,n),n.onStart=e=>(l=e,n),n.onFinish=e=>(u=e,n),n.onError=e=>(d=e,n),n.build=()=>{if(!c)throw Error(`Workflow '${e}' needs a buildGraph() function.`);return{kind:`workflow-contract`,version:1,id:e,displayName:t,description:r,tags:i,timeoutMs:a,defaultMaxConcurrency:o,route:s,build:c,onStart:l,onFinish:u,onError:d}},n}function y(e,t,n){let r=v(e,t);return n(r),r.build()}function b(e,t,n){return f(d(e,t),n).build()}function x(e,t){return u(m(e),t).build()}var S=class{ctx;constructor(e){this.ctx=e}buildWorkflowFromDefinition(e){return y(e.id,e.displayName,t=>t.description(e.description).tags(e.tags).timeoutMs(e.timeoutMs??n).buildGraph(()=>x(`${e.id}-root`,t=>{for(let n of e.steps)t.step(b(n.id,n.toolName,e=>{e.input(n.input??{}).timeout(n.timeoutMs??0),n.inputFrom&&e.inputFrom(n.inputFrom)}))})).onStart(t=>{t.emitSpan(`macro.start`,{macroId:e.id,totalSteps:e.steps.length})}).onError((t,n)=>{t.emitSpan(`macro.error`,{macroId:e.id,error:n.message})}))}async execute(e,t){let n=this.buildWorkflowFromDefinition(e),r=Date.now();try{let r=await i(this.ctx,n,{nodeInputOverrides:t}),a=this.buildProgress(e,r.spans,r.stepResults);return{macroId:e.id,displayName:e.displayName,ok:!0,durationMs:r.durationMs,stepsCompleted:e.steps.length,totalSteps:e.steps.length,stepResults:r.stepResults,progress:a}}catch(t){let n=Date.now()-r,i=t instanceof Error?t.message:String(t),a=this.buildPartialProgress(e,i);return{macroId:e.id,displayName:e.displayName,ok:!1,durationMs:n,stepsCompleted:a.filter(e=>e.status===`complete`).length,totalSteps:e.steps.length,stepResults:{},progress:a,error:i}}}formatProgressReport(e){let t=[];t.push(`**Macro:** ${e.displayName} (\`${e.macroId}\`)`),t.push(``);for(let n of e.progress){let e=n.durationMs===void 0?``:` (${n.durationMs}ms)`,r=n.error?`: ${n.error}`:``,i=n.status===`complete`?`✓`:n.status===`failed`?`✗`:`○`;t.push(`[stage ${n.step}/${n.totalSteps}] ${i} ${n.stepName} — ${n.status}${e}${r}`)}return t.push(``),e.ok?t.push(`✓ Macro complete (${e.stepsCompleted}/${e.totalSteps} steps, ${e.durationMs}ms)`):t.push(`✗ Macro failed at step ${e.stepsCompleted+1}/${e.totalSteps}: ${e.error??`unknown error`}`),t.join(`
2
2
  `)}buildProgress(e,t,n){return e.steps.map((r,i)=>{let a=t.find(e=>e.name===`workflow.node.start`&&e.attrs?.nodeId===r.id),o=t.find(e=>e.name===`workflow.node.finish`&&e.attrs?.nodeId===r.id),s;a&&o&&(s=new Date(o.at).getTime()-new Date(a.at).getTime());let c=r.id in n;return{step:i+1,totalSteps:e.steps.length,stepName:r.id,status:c?`complete`:`skipped`,durationMs:s}})}buildPartialProgress(e,t){return e.steps.map((n,r)=>({step:r+1,totalSteps:e.steps.length,stepName:n.id,status:`failed`,error:r===0?t:void 0}))}};async function C(t){let n;try{n=await c(t)}catch{return[]}let r=n.filter(e=>a(e)===`.json`),i=[];for(let n of r){let r=o(t,n);try{let t=JSON.parse(await s(r,`utf-8`));w(t)?(i.push(T(t)),e.info(`[macros] Loaded user macro "${t.id}" from ${n}`)):e.warn(`[macros] Skipping ${n}: invalid macro schema`)}catch(t){e.warn(`[macros] Skipping ${n}: ${t instanceof Error?t.message:String(t)}`)}}return i}function w(e){if(!e||typeof e!=`object`)return!1;let t=e;if(typeof t.id!=`string`||!t.id||typeof t.displayName!=`string`||!t.displayName||!Array.isArray(t.steps)||t.steps.length===0)return!1;for(let e of t.steps){if(!e||typeof e!=`object`)return!1;let t=e;if(typeof t.id!=`string`||!t.id||typeof t.toolName!=`string`||!t.toolName)return!1}return!0}function T(e){return{id:e.id,displayName:e.displayName,description:e.description??``,tags:e.tags??[],timeoutMs:e.timeoutMs,steps:e.steps.map(e=>({id:e.id,toolName:e.toolName,input:e.input,inputFrom:e.inputFrom,timeoutMs:e.timeoutMs,optional:e.optional}))}}const E={loadFromDirectory:C,validate:w},D=[{id:`deobfuscate_ast_flow`,displayName:`Deobfuscate AST Flow`,description:`Chain: deobfuscate → optional webcrack unpack → semantic analysis`,tags:[`analysis`,`deobfuscation`,`ast`],timeoutMs:t,steps:[{id:`deobfuscate`,toolName:`deobfuscate`,input:{}},{id:`advanced_deobfuscate`,toolName:`webcrack_unpack`,input:{unpack:!0,unminify:!0},inputFrom:{code:`deobfuscate.code`},optional:!0},{id:`analyze_deobfuscated`,toolName:`understand_code`,inputFrom:{code:`deobfuscate.code`}}]},{id:`unpacker_flow`,displayName:`Unpacker Flow`,description:`Detect packer type → extract inner code → optional deep unpack → normalize output`,tags:[`analysis`,`unpacking`,`deobfuscation`],timeoutMs:9e4,steps:[{id:`detect_and_unpack`,toolName:`deobfuscate`,input:{unpack:!0}},{id:`deep_deobfuscate`,toolName:`webcrack_unpack`,input:{unpack:!0,unminify:!0},inputFrom:{code:`detect_and_unpack.code`},optional:!0},{id:`normalize_output`,toolName:`ast_transform_apply`,input:{transforms:[`dead_code_remove`,`rename_vars`]},inputFrom:{code:`detect_and_unpack.code`}}]}];var O=class{runner;macros=null;constructor(e){this.runner=new S(e)}async ensureMacrosLoaded(){if(this.macros)return this.macros;this.macros=new Map;for(let e of D)this.macros.set(e.id,e);try{let e=await E.loadFromDirectory(o(r(),`macros`));for(let t of e)this.macros.set(t.id,t)}catch{}return this.macros}async handleRunMacro(e){let t=e.macroId,n=e.inputOverrides;if(!t||typeof t!=`string`)return{content:[{type:`text`,text:JSON.stringify({ok:!1,error:`macroId parameter is required`})}]};let r=await this.ensureMacrosLoaded(),i=r.get(t);if(!i)return{content:[{type:`text`,text:JSON.stringify({ok:!1,error:`Macro "${t}" not found`,available:Array.from(r.keys())})}]};let a=await this.runner.execute(i,n);return{content:[{type:`text`,text:this.runner.formatProgressReport(a)}]}}async handleListMacros(){let e=await this.ensureMacrosLoaded(),t=Array.from(e.values()).map(e=>({id:e.id,displayName:e.displayName,description:e.description,tags:e.tags,stepCount:e.steps.length}));return{content:[{type:`text`,text:JSON.stringify({macros:t,count:t.length})}]}}};export{O as MacroToolHandlers};
@@ -0,0 +1 @@
1
+ import{ni as e}from"./constants-BYj8Xek8.mjs";import{t}from"./ToolProbe-C7ZU2x7M.mjs";import{a as n,c as r,i,n as a,o,r as s,s as c}from"./binary-instrument-DU7V6TUM.mjs";import{n as l,t as u}from"./capabilities-CyXuKUl1.mjs";import{tmpdir as d}from"node:os";import{join as f,relative as p}from"node:path";import{access as m,mkdir as h,mkdtemp as g,readFile as _,readdir as v,rm as y}from"node:fs/promises";import{execFile as b}from"node:child_process";import{open as x}from"yauzl";const S={plugin_frida_bridge:`Install @jshookmcpextension/plugin-frida-bridge and reload extensions.`,plugin_ghidra_bridge:`Install @jshookmcpextension/plugin-ghidra-bridge and reload extensions.`,plugin_ida_bridge:`Install @jshookmcpextension/plugin-ida-bridge and reload extensions.`,plugin_jadx_bridge:`Install @jshookmcpextension/plugin-jadx-bridge and reload extensions.`};function C(e){return{content:[{type:`text`,text:e}]}}function w(e){return C(JSON.stringify(e))}function T(e,t){let n=e[t];if(typeof n!=`string`||n.trim().length===0)throw Error(`${t} is required`);return n.trim()}function E(e,t){let n=e[t];return typeof n==`string`&&n.trim().length>0?n.trim():void 0}function D(e,t){let n=e[t];return typeof n==`number`&&Number.isFinite(n)?n:void 0}function O(e,t){let n=e[t];return typeof n==`boolean`?n:void 0}function k(e,t){let n=e[t];return Array.isArray(n)?n.filter(e=>typeof e==`string`&&e.length>0):[]}function A(e){return typeof e==`object`&&!!e}function j(e){return A(e)&&e.extensionPluginsById instanceof Map&&e.extensionPluginRuntimeById instanceof Map}function M(e,t){if(!e)return;let n=e.extensionPluginsById;if(n instanceof Map)return n.has(t)}function N(e){return S[e]}function P(e,t){let n=M(e,t);return n===!0?{status:`available`,fix:N(t)}:n===!1?{status:`unavailable`,reason:`Plugin ${t.replaceAll(`_`,`-`)} is not installed`,fix:N(t)}:{status:`unknown`,reason:`Extension plugin registry is not available in the current server context`,fix:`Run inside the full MCP server with extension support enabled.`}}async function F(e,t,r,i){let a=P(e,t);if(!e||a.status!==`available`)return w({...u(r,t,a.reason??`Plugin ${t.replaceAll(`_`,`-`)} is not available`,a.fix),status:a.status});let o=await n(e,{pluginId:t,toolName:r,args:i});return o.success?w(o):w({...u(r,t,o.error??`Plugin invocation failed`,a.fix)})}function I(e,t){let n=e[t];if(!A(n))return;let r={},i=n.includeArgs,a=n.includeRetAddr;return typeof i==`boolean`&&(r.includeArgs=i),typeof a==`boolean`&&(r.includeRetAddr=a),r}function L(e){if(!/^\d+$/.test(e))return null;let t=Number.parseInt(e,10);return Number.isNaN(t)?null:t}function R(e){return e.toLowerCase().replace(/[^a-z0-9]+/g,`-`).replace(/^-+|-+$/g,``).slice(0,24)}async function z(){let e=process.env.UNIDBG_JAR??``;if(e.length===0)return{available:!1,reason:`UNIDBG_JAR is not configured`,command:`java`,jarPath:``};try{await m(e)}catch{return{available:!1,reason:`UNIDBG_JAR not found: ${e}`,command:`java`,jarPath:e}}return{available:!0,reason:``,command:`java`,jarPath:e}}function B(e,t,n){return new Promise((r,i)=>{b(e,t,{timeout:n,windowsHide:!0,maxBuffer:8388608,encoding:`utf8`},(e,t,n)=>{if(e){i(e);return}r({stdout:typeof t==`string`?t:``,stderr:typeof n==`string`?n:``})})})}function V(e){return A(e)&&Array.isArray(e.functions)&&Array.isArray(e.imports)}function H(e){let t=[];for(let n of e){if(!A(n))continue;let e=U(n,`functionName`),r=U(n,`hookCode`),i=U(n,`description`),a=W(n.parameters);!e||!r||!i||t.push({functionName:e,hookCode:r,description:i,parameters:a})}return t}function U(e,t){let n=e[t];return typeof n==`string`?n:void 0}function W(e){if(!Array.isArray(e))return[];let t=[];for(let n of e){if(!A(n))continue;let e=U(n,`name`),r=U(n,`type`),i=U(n,`description`);e&&r&&i&&t.push({name:e,type:r,description:i})}return t}var G=class{state;constructor(e){this.state=e}async handleFridaAttach(e){let t=E(e,`pid`);if(!E(e,`target`)&&t)return F(this.state.context,`plugin_frida_bridge`,`frida_attach`,e);let n=T(e,`target`),r=this.getFridaSession(),i=await r.getAvailability();if(!i.available){let e=`mock-frida-${R(n)}`;return w({success:!1,available:!1,capability:`frida_cli`,fix:`Install frida-tools and ensure the frida CLI is on PATH.`,target:n,sessionId:e,reason:i.reason??`Frida CLI is not available`,sessions:[{id:e,target:n,pid:L(n),status:`unavailable`}]})}let a;try{a=await r.attach(n)}catch(e){return w({success:!1,available:!0,capability:`frida_attach`,fix:`Run the server elevated or choose a target process that allows Frida injection.`,target:n,reason:e instanceof Error?e.message:String(e),sessions:r.listSessions()})}return this.state.context?.eventBus.emit(`frida:attached`,{target:n,sessionId:a,timestamp:new Date().toISOString()}),w({success:!0,available:!0,target:n,sessionId:a,sessions:r.listSessions()})}async handleFridaEnumerateModules(e){let t=T(e,`sessionId`),n=this.getFridaSession(),r=await n.getAvailability();if(!r.available)return w({available:!1,capability:`frida_cli`,fix:`Install frida-tools and ensure the frida CLI is on PATH.`,sessionId:t,reason:r.reason??`Frida CLI is not available`,modules:[{name:`mock-module`,base:`0x0`,size:0,path:`<unavailable>`}]});if(!n.useSession(t))return w({available:!1,capability:`frida_session`,fix:`Call frida_attach first and reuse the returned sessionId.`,sessionId:t,reason:`Unknown Frida session: ${t}`,modules:[]});let i=await n.enumerateModules(),a=n.getSessionDiagnostics(t);return a?.status===`error`&&a.lastError?w({success:!1,available:!0,sessionId:t,reason:a.lastError,modules:i}):w({success:!0,available:!0,sessionId:t,modules:i})}async handleFridaRunScript(e){let t=E(e,`sessionId`);if(!t)return C(`Missing required string argument: sessionId`);let n=T(e,`script`),r=this.getFridaSession(),i=await r.getAvailability();if(!i.available)return{available:!1,capability:`frida_cli`,fix:`Install frida-tools and ensure the frida CLI is on PATH.`,sessionId:t,reason:i.reason??`Frida CLI is not available`,execution:{output:``,error:`Frida unavailable`}};if(!r.useSession(t))return{available:!1,capability:`frida_session`,fix:`Call frida_attach first and reuse the returned sessionId.`,sessionId:t,reason:`Unknown Frida session: ${t}`,execution:{output:``,error:`Unknown session`}};let a=await r.executeScript(n);return a.error?w({success:!1,available:!0,sessionId:t,reason:a.error,execution:a}):w({success:!0,available:!0,sessionId:t,execution:a})}async handleFridaDetach(e){let t=E(e,`sessionId`);if(!t)return C(`Missing required string argument: sessionId`);let n=this.getFridaSession();return(await n.getAvailability()).available&&n.hasSession(t)?(n.useSession(t),await n.detach(),w({success:!0,sessionId:t,detached:!0})):F(this.state.context,`plugin_frida_bridge`,`frida_detach`,e)}async handleFridaListSessions(e){let t=this.getFridaSession(),n=await t.getAvailability(),r=t.listSessions();if(n.available)return w({success:!0,available:!0,sessions:r,count:r.length});let i=P(this.state.context,`plugin_frida_bridge`);return r.length>0||i.status===`unavailable`?w({success:!0,available:!1,capability:`frida_cli`,reason:n.reason??`Frida CLI is not available`,fix:`Install frida-tools and ensure the frida CLI is on PATH.`,sessions:r,count:r.length}):F(this.state.context,`plugin_frida_bridge`,`frida_list_sessions`,e)}async handleFridaGenerateScript(e){let t=E(e,`target`)??`unknown`,n=E(e,`template`)??`trace`,r=E(e,`functionName`)??`target_function`,i=[{functionName:r,hookCode:`console.log('[${n}] ${r} called');`,description:`${n} hook for ${r}`,parameters:[]}];return w({success:!0,target:t,template:n,functionName:r,script:this.state.hookCodeGenerator.exportScript(i,`frida`)})}async handleFridaEnumerateFunctions(e){let t=T(e,`sessionId`),n=T(e,`moduleName`),r=this.getFridaSession(),i=await r.getAvailability();if(!i.available)return{available:!1,capability:`frida_cli`,fix:`Install frida-tools and ensure the frida CLI is on PATH.`,sessionId:t,moduleName:n,reason:i.reason??`Frida CLI is not available`,functions:[]};if(!r.useSession(t))return{available:!1,capability:`frida_session`,fix:`Call frida_attach first and reuse the returned sessionId.`,sessionId:t,reason:`Unknown Frida session: ${t}`,functions:[]};let a=await r.enumerateFunctions(n),o=r.getSessionDiagnostics(t);return o?.status===`error`&&o.lastError?w({success:!1,available:!0,sessionId:t,moduleName:n,reason:o.lastError,functions:a,count:a.length}):w({success:!0,available:!0,sessionId:t,moduleName:n,functions:a,count:a.length})}async handleFridaFindSymbols(e){let t=T(e,`sessionId`),n=T(e,`pattern`),r=this.getFridaSession(),i=await r.getAvailability();if(!i.available)return{available:!1,capability:`frida_cli`,fix:`Install frida-tools and ensure the frida CLI is on PATH.`,sessionId:t,pattern:n,reason:i.reason??`Frida CLI is not available`,symbols:[]};if(!r.useSession(t))return{available:!1,capability:`frida_session`,fix:`Call frida_attach first and reuse the returned sessionId.`,sessionId:t,reason:`Unknown Frida session: ${t}`,symbols:[]};let a=await r.findSymbols(n),o=r.getSessionDiagnostics(t);return o?.status===`error`&&o.lastError?w({success:!1,available:!0,sessionId:t,pattern:n,reason:o.lastError,symbols:a,count:a.length}):w({success:!0,available:!0,sessionId:t,pattern:n,symbols:a,count:a.length})}getFridaSession(){return this.state.fridaSession||(this.state.fridaSession=new r),this.state.fridaSession}},K=class{state;constructor(e){this.state=e}async handleGhidraAnalyze(e){let t=T(e,`binaryPath`),n=D(e,`timeout`),r=this.getGhidraAnalyzer(),i=await r.getAvailability(),a=await r.analyze(t,n===void 0?void 0:{timeout:n});return i.available?{available:!0,binaryPath:t,analysis:a}:{available:!1,capability:`ghidra_headless`,fix:`Install Ghidra and ensure analyzeHeadless is on PATH.`,binaryPath:t,reason:i.reason??`Ghidra analyzeHeadless is not available`,analysis:a}}async handleGhidraDecompile(e){return F(this.state.context,`plugin_ghidra_bridge`,`ghidra_decompile`,e)}async handleIdaDecompile(e){return F(this.state.context,`plugin_ida_bridge`,`ida_decompile`,e)}async handleJadxDecompile(e){let n=T(e,`apkPath`),r=T(e,`className`),i=E(e,`methodName`),a=await t(`jadx`,[`--version`]);return a.available?this.jadxNativeDecompile(a.path??`jadx`,n,r,i):F(this.state.context,`plugin_jadx_bridge`,`jadx_decompile`,e)}async handleApktoolDecode(e){let n=T(e,`apkPath`),r=E(e,`outputDir`),i=O(e,`force`)??!1,a=await t(`apktool`,[`--version`]);if(!a.available)return w({available:!1,capability:`apktool_cli`,fix:`Install apktool and ensure it is on PATH.`,apkPath:n,reason:a.reason??`apktool is not available`});let o=r??f(d(),`jshook-apktool-${Date.now()}`);r&&await h(o,{recursive:!0});try{let e=[`decode`,`--output`,o];i&&e.push(`--force`),e.push(n);let t=await B(a.path??`apktool`,e,12e4);return w({available:!0,apkPath:n,outputDir:o,force:i,stdout:t.stdout.trim(),stderr:t.stderr.trim()})}catch(e){return w({available:!0,apkPath:n,outputDir:o,force:i,error:e instanceof Error?e.message:String(e)})}}async handleApkManifestDump(e){let n=T(e,`apkPath`),r=await this.readZipEntryBuffer(n,`AndroidManifest.xml`);if(!r.success)return w({available:!1,apkPath:n,entry:`AndroidManifest.xml`,error:r.error});let i=this.decodeTextEntry(r.buffer);if(i!==null)return w({available:!0,apkPath:n,entry:`AndroidManifest.xml`,format:`xml`,decodedBy:`zip-entry`,manifest:i});let a=await t(`jadx`,[`--version`]);if(a.available){let e=await this.decodeManifestWithJadx(a.path??`jadx`,n);if(e.success)return w({available:!0,apkPath:n,entry:`AndroidManifest.xml`,format:`xml`,decodedBy:`jadx_cli`,manifest:e.manifest})}return w({available:!0,apkPath:n,entry:`AndroidManifest.xml`,format:`binary-axml`,decodedBy:`zip-entry`,size:r.buffer.length,manifestBase64:r.buffer.toString(`base64`)})}async handleApkNativeLibsList(e){let t=T(e,`apkPath`),n=await this.listZipEntries(t);if(!n.success)return w({available:!1,apkPath:t,error:n.error});let r=n.entries.filter(e=>/^lib\/.+\/[^/]+\.so$/i.test(e)).map(e=>{let t=e.split(`/`);return{path:e,abi:t[1]??``,name:t[t.length-1]??``}});return w({available:!0,apkPath:t,count:r.length,libraries:r})}async handleGenerateHooks(e){let t=E(e,`ghidraOutput`);if(t)return this.handleLegacyGenerateHooks(t);let n=e.ghidraOutput;if(A(n))return this.handleLegacyGenerateHooks(JSON.stringify(n));let r=k(e,`symbols`);if(r.length===0)return C(`symbols or ghidraOutput is required`);let i=I(e,`options`),a=this.getHookGenerator().generateFridaHookScript(r,i);return w({available:!0,symbolCount:r.length,script:a})}async handleExportHookScript(e){let t=E(e,`hookTemplates`);if(!t){let e=this.state.hookCodeGenerator.exportScript([],`frida`);return w({format:`frida`,hookCount:0,script:e.includes(`Java.perform`)?e:`Java.perform(function() {\n${e}\n});`})}try{let e=JSON.parse(t);if(!Array.isArray(e))return C(`Invalid JSON`);let n=H(e),r=this.state.hookCodeGenerator.exportScript(n,`frida`);return w({format:`frida`,hookCount:n.length,script:r})}catch{return C(`Invalid JSON`)}}async handleUnidbgEmulate(t){let n=T(t,`binaryPath`),r=T(t,`functionName`),i=k(t,`args`),a=await z();if(!a.available)return{available:!1,capability:`unidbg_jar`,fix:`Set UNIDBG_JAR to a reachable Unidbg JAR path.`,binaryPath:n,functionName:r,args:i,reason:a.reason,result:{returnValue:`0x0`,stdout:``,stderr:``,trace:[`mock-unidbg-unavailable`]}};let o=await B(a.command,[`-jar`,a.jarPath,n,r,...i],e);return{available:!0,binaryPath:n,functionName:r,args:i,result:{returnValue:`0x0`,stdout:o.stdout.trim(),stderr:o.stderr.trim(),trace:[]}}}async handleUnidbgLaunch(e){let t=E(e,`soPath`);if(!t)return C(`Missing required string argument: soPath`);let n=E(e,`arch`)??`arm`;try{let e=await this.state.unidbgRunner.launch(t,n);return{available:!0,sessionId:e.sessionId,soPath:e.soPath,arch:e.arch,sessions:this.state.unidbgRunner.listSessions()}}catch(e){return{available:!1,capability:`unidbg_jar`,fix:`Set UNIDBG_JAR to a reachable Unidbg JAR path and retry.`,soPath:t,arch:n,reason:e instanceof Error?e.message:String(e),sessions:this.state.unidbgRunner.listSessions()}}}async handleUnidbgCall(e){let t=E(e,`sessionId`);if(!t)return C(`Missing required string argument: sessionId`);let n=E(e,`functionName`);if(!n)return C(`Missing required string argument: functionName`);let r=A(e.args)?e.args:{};try{return w(await this.state.unidbgRunner.callFunction(t,n,r))}catch(e){let t=e instanceof Error?e.message:String(e);return C(t.startsWith(`No unidbg session found`)?`${t} (not found)`:t)}}async handleUnidbgTrace(e){let t=E(e,`sessionId`);if(!t)return C(`Missing required string argument: sessionId`);try{return w(await this.state.unidbgRunner.trace(t))}catch(e){let t=e instanceof Error?e.message:String(e);return C(t.startsWith(`No unidbg session found`)?`${t} (not found)`:t)}}async handleGetAvailablePlugins(e){let t=this.state.context?i(this.state.context):[];return w({plugins:t,count:t.length})}getGhidraAnalyzer(){return this.state.ghidra||(this.state.ghidra=new c),this.state.ghidra}getHookGenerator(){return this.state.hookGen||(this.state.hookGen=new s),this.state.hookGen}handleLegacyGenerateHooks(e){let t;try{t=JSON.parse(e)}catch{return C(`Invalid JSON`)}if(!V(t))return C(`ghidraOutput is required`);let n=this.state.hookCodeGenerator.generateHooks(t);return w({count:n.length,hooks:n})}async listZipEntries(e){try{let t=await this.openZipFile(e);return{success:!0,entries:await new Promise((e,n)=>{let r=[],i=!1,a=e=>{r.push(e.fileName),t.readEntry()},o=()=>c(()=>e(r)),s=e=>c(()=>n(e)),c=e=>{i||(i=!0,t.removeListener(`entry`,a),t.removeListener(`end`,o),t.removeListener(`error`,s),e())};t.on(`entry`,a),t.on(`end`,o),t.on(`error`,s),t.readEntry()})}}catch(e){return{success:!1,error:e instanceof Error?e.message:String(e)}}}async readZipEntryBuffer(e,t){try{let n=await this.openZipFile(e);return{success:!0,buffer:await new Promise((e,r)=>{let i=!1,a=()=>{try{n.close()}catch{}},o=i=>{if(i.fileName!==t){n.readEntry();return}n.openReadStream(i,(n,i)=>{if(n||!i){l(()=>r(n??Error(`Unable to read ZIP entry: ${t}`))),a();return}this.readStreamToBuffer(i).then(t=>{l(()=>e(t)),a()}).catch(e=>{l(()=>r(e)),a()})})},s=()=>l(()=>r(Error(`ZIP entry not found: ${t}`))),c=e=>l(()=>r(e)),l=e=>{i||(i=!0,n.removeListener(`entry`,o),n.removeListener(`end`,s),n.removeListener(`error`,c),e())};n.on(`entry`,o),n.on(`end`,s),n.on(`error`,c),n.readEntry()})}}catch(e){return{success:!1,error:e instanceof Error?e.message:String(e)}}}async jadxNativeDecompile(e,t,n,r){let i=await g(f(d(),`jshook-jadx-`));try{let a=[`--no-res`,`--no-debug-info`,`-d`,i,t];await this.runJadx(e,a);let o=f(i,`sources`),s=await this.resolveDecompiledClassFile(o,n);if(!s.success)return w({available:!0,apkPath:t,className:n,error:`Class file not found after decompilation: ${n}`,suggestions:s.suggestions});let c;try{c=await _(s.classFile,`utf8`)}catch{return w({available:!0,apkPath:t,className:n,...s.resolvedClassName===n?{}:{resolvedClassName:s.resolvedClassName},error:`Class file not found after decompilation: ${n}`})}if(r){let e=this.extractMethodSource(c,r);return w(e?{available:!0,apkPath:t,className:n,...s.resolvedClassName===n?{}:{resolvedClassName:s.resolvedClassName},methodName:r,source:e}:{available:!0,apkPath:t,className:n,...s.resolvedClassName===n?{}:{resolvedClassName:s.resolvedClassName},methodName:r,source:``,error:`Method ${r} not found in ${n}`})}return w({available:!0,apkPath:t,className:n,...s.resolvedClassName===n?{}:{resolvedClassName:s.resolvedClassName},source:c})}catch(e){return w({available:!0,apkPath:t,className:n,error:e instanceof Error?e.message:String(e)})}finally{await y(i,{recursive:!0,force:!0})}}openZipFile(e){return new Promise((t,n)=>{x(e,{autoClose:!0,lazyEntries:!0,decodeStrings:!0,validateEntrySizes:!0,strictFileNames:!1},(r,i)=>{if(r||!i){n(r??Error(`Unable to open ZIP archive: ${e}`));return}t(i)})})}readStreamToBuffer(e){return new Promise((t,n)=>{let r=[];e.on(`data`,e=>{r.push(Buffer.isBuffer(e)?e:Buffer.from(e))}),e.on(`end`,()=>t(Buffer.concat(r))),e.on(`error`,n)})}decodeTextEntry(e){if(e.length===0)return``;let t=e.subarray(0,Math.min(e.length,1024)),n=0;for(let e of t){if(e===0)return null;(e<9||e>13&&e<32)&&(n+=1)}if(n>t.length*.1)return null;let r=e.toString(`utf8`);return r.trimStart().startsWith(`<`)?r:null}async decodeManifestWithJadx(e,t){let n=await g(f(d(),`jshook-jadx-manifest-`));try{await this.runJadx(e,[`--no-src`,`-d`,n,t]);let r=await _(f(n,`resources`,`AndroidManifest.xml`),`utf8`);return r.trimStart().startsWith(`<`)?{success:!0,manifest:r}:{success:!1,error:`Decoded manifest is not XML`}}catch(e){return{success:!1,error:e instanceof Error?e.message:String(e)}}finally{await y(n,{recursive:!0,force:!0})}}async runJadx(e,t){await new Promise((n,r)=>{b(e,t,{encoding:`utf8`,windowsHide:!0,timeout:12e4},e=>{if(e&&e.code!==1){r(e);return}n()})})}async resolveDecompiledClassFile(e,t){let n=this.buildExpectedClassFile(e,t);try{return await _(n,`utf8`),{success:!0,classFile:n,resolvedClassName:t}}catch{}let r=await this.findClassCandidates(e,t);if(r.length===0)return{success:!1,suggestions:[]};if(r.length===1){let e=r[0];return e?{success:!0,classFile:e.classFile,resolvedClassName:e.className}:{success:!1,suggestions:[]}}let i=r[0],a=r[1];return!i||!a?{success:!1,suggestions:r.slice(0,10).map(e=>e.className)}:i.score>a.score?{success:!0,classFile:i.classFile,resolvedClassName:i.className}:{success:!1,suggestions:r.slice(0,10).map(e=>e.className)}}buildExpectedClassFile(e,t){let n=t.split(`.`),r=(n[n.length-1]??``).split(`$`)[0]??``;return f(e,...n.slice(0,-1),`${r}.java`)}async findClassCandidates(e,t){let n=t.split(`.`),r=(n[n.length-1]??``).split(`$`)[0]??``,i=n.slice(0,-1),a=`${r}.java`,o=[],s=async t=>{let n=await v(t,{withFileTypes:!0});for(let r of n){let n=f(t,r.name);if(r.isDirectory()){await s(n);continue}if(!r.isFile()||r.name!==a)continue;let c=p(e,n).replace(/\\/g,`/`).replace(/\.java$/i,``).split(`/`).join(`.`),l=c.split(`.`).slice(0,-1);o.push({className:c,classFile:n,score:this.scoreClassCandidate(i,l)})}};return await s(e),o.toSorted((e,t)=>t.score-e.score||e.className.localeCompare(t.className))}scoreClassCandidate(e,t){let n=0,r=Math.min(e.length,t.length);for(;n<r&&e[n]===t[n];)n+=1;let i=0,a=Math.min(e.length,t.length);for(;i<a&&e[e.length-1-i]===t[t.length-1-i];)i+=1;return n*10+i}extractMethodSource(e,t){let n=RegExp(`(?:public|private|protected|static|final|abstract|synchronized|native)\\s+[\\w<>\\[\\]]+\\s+${t.replace(/[.*+?^${}()|[\]\\]/g,`\\$&`)}\\s*\\([^)]*\\)\\s*(?:throws[^{]*)?\\{`),r=e.search(n);if(r===-1)return null;let i=0,a=e.indexOf(`{`,r);for(;a<e.length;a++)if(e[a]===`{`)i+=1;else if(e[a]===`}`&&(--i,i===0))break;return e.slice(r,a+1)}},q=class{state;constructor(e){this.state=e}async handleBinaryInstrumentCapabilities(){let[e,n,r,i,a]=await Promise.all([this.getFridaSession().getAvailability(),this.getGhidraAnalyzer().getAvailability(),t(`jadx`,[`--version`]),t(`apktool`,[`--version`]),z()]);return w(l(`binary_instrument_capabilities`,[{capability:`frida_cli`,status:e.available?`available`:`unavailable`,reason:e.reason,fix:e.available?void 0:`Install frida-tools and ensure the frida CLI is on PATH.`,details:{tools:[`frida_attach`,`frida_enumerate_modules`,`frida_run_script`,`frida_enumerate_functions`,`frida_find_symbols`],...e.path?{path:e.path}:{},...e.version?{version:e.version}:{}}},{capability:`plugin_frida_bridge`,...P(this.state.context,`plugin_frida_bridge`),details:{tools:[`frida_attach`,`frida_detach`,`frida_list_sessions`]}},{capability:`ghidra_headless`,status:n.available?`available`:`unavailable`,reason:n.reason,fix:n.available?void 0:`Install Ghidra and ensure analyzeHeadless is on PATH.`,details:{tools:[`ghidra_analyze`],...n.path?{path:n.path}:{},...n.version?{version:n.version}:{}}},{capability:`plugin_ghidra_bridge`,...P(this.state.context,`plugin_ghidra_bridge`),details:{tools:[`ghidra_decompile`]}},{capability:`plugin_ida_bridge`,...P(this.state.context,`plugin_ida_bridge`),details:{tools:[`ida_decompile`]}},{capability:`jadx_cli`,status:r.available?`available`:`unavailable`,reason:r.reason,fix:r.available?void 0:`Install JADX and ensure the jadx CLI is on PATH.`,details:{tools:[`jadx_decompile`],...r.path?{path:r.path}:{},...r.version?{version:r.version}:{}}},{capability:`plugin_jadx_bridge`,...P(this.state.context,`plugin_jadx_bridge`),details:{tools:[`jadx_decompile`]}},{capability:`apktool_cli`,status:i.available?`available`:`unavailable`,reason:i.reason,fix:i.available?void 0:`Install apktool and ensure it is on PATH.`,details:{tools:[`apktool_decode`],...i.path?{path:i.path}:{},...i.version?{version:i.version}:{}}},{capability:`unidbg_jar`,status:a.available?`available`:`unavailable`,reason:a.reason||void 0,fix:a.available?void 0:`Set UNIDBG_JAR to a reachable Unidbg JAR path.`,details:{tools:[`unidbg_emulate`,`unidbg_launch`,`unidbg_call`,`unidbg_trace`],command:a.command,jarPath:a.jarPath}}]))}getFridaSession(){return this.state.fridaSession||(this.state.fridaSession=new r),this.state.fridaSession}getGhidraAnalyzer(){return this.state.ghidra||(this.state.ghidra=new c),this.state.ghidra}},J=class{state;frida;analysis;capabilities;constructor(e,t,n){this.state={hookCodeGenerator:new o,unidbgRunner:new a},e instanceof r?this.state.fridaSession=e:j(e)&&(this.state.context=e),t&&(this.state.ghidra=t),n&&(this.state.hookGen=n),this.frida=new G(this.state),this.analysis=new K(this.state),this.capabilities=new q(this.state)}handleBinaryInstrumentCapabilities(){return this.capabilities.handleBinaryInstrumentCapabilities()}handleFridaAttach(e){return this.frida.handleFridaAttach(e)}handleFridaEnumerateModules(e){return this.frida.handleFridaEnumerateModules(e)}handleFridaRunScript(e){return this.frida.handleFridaRunScript(e)}handleFridaDetach(e){return this.frida.handleFridaDetach(e)}handleFridaListSessions(e){return this.frida.handleFridaListSessions(e)}handleFridaGenerateScript(e){return this.frida.handleFridaGenerateScript(e)}handleFridaEnumerateFunctions(e){return this.frida.handleFridaEnumerateFunctions(e)}handleFridaFindSymbols(e){return this.frida.handleFridaFindSymbols(e)}handleGhidraAnalyze(e){return this.analysis.handleGhidraAnalyze(e)}handleGhidraDecompile(e){return this.analysis.handleGhidraDecompile(e)}handleIdaDecompile(e){return this.analysis.handleIdaDecompile(e)}handleJadxDecompile(e){return this.analysis.handleJadxDecompile(e)}handleApktoolDecode(e){return this.analysis.handleApktoolDecode(e)}handleApkManifestDump(e){return this.analysis.handleApkManifestDump(e)}handleApkNativeLibsList(e){return this.analysis.handleApkNativeLibsList(e)}handleGenerateHooks(e){return this.analysis.handleGenerateHooks(e)}handleExportHookScript(e){return this.analysis.handleExportHookScript(e)}handleUnidbgEmulate(e){return this.analysis.handleUnidbgEmulate(e)}handleUnidbgLaunch(e){return this.analysis.handleUnidbgLaunch(e)}handleUnidbgCall(e){return this.analysis.handleUnidbgCall(e)}handleUnidbgTrace(e){return this.analysis.handleUnidbgTrace(e)}handleGetAvailablePlugins(e){return this.analysis.handleGetAvailablePlugins(e)}};export{J as BinaryInstrumentHandlers};