FinalMaskForm.vue 24 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510
  1. <script setup>
  2. import { computed } from 'vue';
  3. import { DeleteOutlined, PlusOutlined, ReloadOutlined } from '@ant-design/icons-vue';
  4. import { RandomUtil } from '@/utils';
  5. import { Protocols } from '@/models/inbound.js';
  6. // Mirrors web/html/form/stream/stream_finalmask.html. Used by both the
  7. // inbound and outbound modals — they share the same StreamSettings
  8. // shape (`stream.finalmask`, `stream.addTcpMask()`, etc.) so a single
  9. // component handles both. The host modal passes its protocol through
  10. // so we know whether to show only the Hysteria-specific UDP types.
  11. const props = defineProps({
  12. stream: { type: Object, required: true },
  13. protocol: { type: String, default: '' },
  14. });
  15. const isHysteria = computed(() => props.protocol === Protocols.HYSTERIA);
  16. const network = computed(() => props.stream?.network || '');
  17. const showTcp = computed(() => ['raw', 'tcp', 'httpupgrade', 'ws', 'grpc', 'xhttp'].includes(network.value));
  18. const showUdp = computed(() => isHysteria.value || network.value === 'kcp');
  19. const showQuic = computed(() => isHysteria.value || network.value === 'xhttp');
  20. // Reset the per-row settings shape when the user picks a different
  21. // type — mirrors the legacy `mask._getDefaultSettings(type, {})` call.
  22. function changeMaskType(mask, type) {
  23. mask.type = type;
  24. mask.settings = mask._getDefaultSettings(type, {});
  25. }
  26. // Special case from the legacy form: switching a UDP mask to xdns
  27. // shrinks the kcp MTU; everything else needs the default 1350.
  28. function changeUdpMaskType(mask, type) {
  29. changeMaskType(mask, type);
  30. if (network.value === 'kcp' && props.stream.kcp) {
  31. props.stream.kcp.mtu = type === 'xdns' ? 900 : 1350;
  32. }
  33. }
  34. // header-custom and noise rows share the same per-item shape — the
  35. // type select rewires the packet field. Pulled out so the click
  36. // handlers in the template stay readable.
  37. function changeItemType(item, type) {
  38. item.type = type;
  39. if (type === 'base64') item.packet = RandomUtil.randomBase64();
  40. else if (type === 'array') { item.rand = 0; item.packet = []; }
  41. else item.packet = '';
  42. }
  43. function addUdpMaskWithDefault() {
  44. const def = isHysteria.value ? 'salamander' : 'mkcp-aes128gcm';
  45. props.stream.addUdpMask(def);
  46. }
  47. function newClientServerItem() {
  48. return { delay: 0, rand: 0, randRange: '0-255', type: 'array', packet: [] };
  49. }
  50. function newUdpClientServerItem() {
  51. return { rand: 0, randRange: '0-255', type: 'array', packet: [] };
  52. }
  53. function newNoiseItem() {
  54. return { rand: '1-8192', randRange: '0-255', type: 'array', packet: [], delay: '10-20' };
  55. }
  56. </script>
  57. <template>
  58. <a-form v-if="showTcp || showUdp || showQuic" :colon="false" :label-col="{ md: { span: 8 } }"
  59. :wrapper-col="{ md: { span: 14 } }">
  60. <!-- ============================== TCP MASKS ============================== -->
  61. <template v-if="showTcp">
  62. <a-form-item label="TCP Masks">
  63. <a-button type="primary" size="small" @click="stream.addTcpMask('fragment')">
  64. <template #icon>
  65. <PlusOutlined />
  66. </template>
  67. </a-button>
  68. </a-form-item>
  69. <template v-for="(mask, mIdx) in (stream.finalmask.tcp || [])" :key="`tcp-${mIdx}`">
  70. <a-divider :style="{ margin: '0' }">
  71. TCP Mask {{ mIdx + 1 }}
  72. <DeleteOutlined :style="{ color: 'rgb(255, 77, 79)', cursor: 'pointer', marginLeft: '8px' }"
  73. @click="stream.delTcpMask(mIdx)" />
  74. </a-divider>
  75. <a-form-item label="Type">
  76. <a-select :value="mask.type" @change="(t) => changeMaskType(mask, t)">
  77. <a-select-option value="fragment">Fragment</a-select-option>
  78. <a-select-option value="header-custom">Header Custom</a-select-option>
  79. <a-select-option value="sudoku">Sudoku</a-select-option>
  80. </a-select>
  81. </a-form-item>
  82. <!-- Fragment -->
  83. <template v-if="mask.type === 'fragment'">
  84. <a-form-item label="Packets">
  85. <a-select v-model:value="mask.settings.packets">
  86. <a-select-option value="tlshello">tlshello</a-select-option>
  87. <a-select-option value="1-3">1-3</a-select-option>
  88. <a-select-option value="1-5">1-5</a-select-option>
  89. </a-select>
  90. </a-form-item>
  91. <a-form-item label="Length">
  92. <a-input v-model:value="mask.settings.length" placeholder="e.g. 100-200" />
  93. </a-form-item>
  94. <a-form-item label="Delay">
  95. <a-input v-model:value="mask.settings.delay" placeholder="e.g. 10-20" />
  96. </a-form-item>
  97. <a-form-item label="Max Split">
  98. <a-input v-model:value="mask.settings.maxSplit" placeholder="e.g. 3-6" />
  99. </a-form-item>
  100. </template>
  101. <!-- Sudoku -->
  102. <template v-if="mask.type === 'sudoku'">
  103. <a-form-item label="Password">
  104. <a-input v-model:value="mask.settings.password" placeholder="Obfuscation password" />
  105. </a-form-item>
  106. <a-form-item label="ASCII">
  107. <a-input v-model:value="mask.settings.ascii" placeholder="ASCII" />
  108. </a-form-item>
  109. <a-form-item label="Custom Table">
  110. <a-input v-model:value="mask.settings.customTable" placeholder="Custom Table" />
  111. </a-form-item>
  112. <a-form-item label="Custom Tables">
  113. <a-input v-model:value="mask.settings.customTables" placeholder="Custom Tables" />
  114. </a-form-item>
  115. <a-form-item label="Padding Min">
  116. <a-input-number v-model:value="mask.settings.paddingMin" :min="0" />
  117. </a-form-item>
  118. <a-form-item label="Padding Max">
  119. <a-input-number v-model:value="mask.settings.paddingMax" :min="0" />
  120. </a-form-item>
  121. </template>
  122. <!-- Header Custom — clients/servers as 2D groups -->
  123. <template v-if="mask.type === 'header-custom'">
  124. <!-- Clients -->
  125. <a-form-item label="Clients">
  126. <a-button type="primary" size="small" @click="mask.settings.clients.push([newClientServerItem()])">
  127. <template #icon>
  128. <PlusOutlined />
  129. </template>
  130. </a-button>
  131. </a-form-item>
  132. <template v-for="(group, gi) in mask.settings.clients" :key="`tcp-cg-${mIdx}-${gi}`">
  133. <a-divider :style="{ margin: '0' }">
  134. Clients Group {{ gi + 1 }}
  135. <DeleteOutlined :style="{ color: 'rgb(255, 77, 79)', cursor: 'pointer', marginLeft: '8px' }"
  136. @click="mask.settings.clients.splice(gi, 1)" />
  137. </a-divider>
  138. <template v-for="(item, ii) in group" :key="`tcp-ci-${mIdx}-${gi}-${ii}`">
  139. <a-form-item label="Type">
  140. <a-select :value="item.type" @change="(t) => changeItemType(item, t)">
  141. <a-select-option value="array">Array</a-select-option>
  142. <a-select-option value="str">String</a-select-option>
  143. <a-select-option value="hex">Hex</a-select-option>
  144. <a-select-option value="base64">Base64</a-select-option>
  145. </a-select>
  146. </a-form-item>
  147. <a-form-item label="Delay (ms)">
  148. <a-input-number v-model:value="item.delay" :min="0" />
  149. </a-form-item>
  150. <template v-if="item.type === 'array'">
  151. <a-form-item label="Rand">
  152. <a-input-number v-model:value="item.rand" :min="0" />
  153. </a-form-item>
  154. <a-form-item label="Rand Range">
  155. <a-input v-model:value="item.randRange" placeholder="0-255" />
  156. </a-form-item>
  157. </template>
  158. <a-form-item v-else label="Packet">
  159. <a-input-group v-if="item.type === 'base64'" compact>
  160. <a-input v-model:value="item.packet" placeholder="binary data"
  161. :style="{ width: 'calc(100% - 32px)' }" />
  162. <a-button @click="item.packet = RandomUtil.randomBase64()">
  163. <template #icon>
  164. <ReloadOutlined />
  165. </template>
  166. </a-button>
  167. </a-input-group>
  168. <a-input v-else v-model:value="item.packet" placeholder="binary data" />
  169. </a-form-item>
  170. </template>
  171. </template>
  172. <!-- Servers -->
  173. <a-form-item label="Servers">
  174. <a-button type="primary" size="small" @click="mask.settings.servers.push([newClientServerItem()])">
  175. <template #icon>
  176. <PlusOutlined />
  177. </template>
  178. </a-button>
  179. </a-form-item>
  180. <template v-for="(group, gi) in mask.settings.servers" :key="`tcp-sg-${mIdx}-${gi}`">
  181. <a-divider :style="{ margin: '0' }">
  182. Servers Group {{ gi + 1 }}
  183. <DeleteOutlined :style="{ color: 'rgb(255, 77, 79)', cursor: 'pointer', marginLeft: '8px' }"
  184. @click="mask.settings.servers.splice(gi, 1)" />
  185. </a-divider>
  186. <template v-for="(item, ii) in group" :key="`tcp-si-${mIdx}-${gi}-${ii}`">
  187. <a-form-item label="Type">
  188. <a-select :value="item.type" @change="(t) => changeItemType(item, t)">
  189. <a-select-option value="array">Array</a-select-option>
  190. <a-select-option value="str">String</a-select-option>
  191. <a-select-option value="hex">Hex</a-select-option>
  192. <a-select-option value="base64">Base64</a-select-option>
  193. </a-select>
  194. </a-form-item>
  195. <a-form-item label="Delay (ms)">
  196. <a-input-number v-model:value="item.delay" :min="0" />
  197. </a-form-item>
  198. <template v-if="item.type === 'array'">
  199. <a-form-item label="Rand">
  200. <a-input-number v-model:value="item.rand" :min="0" />
  201. </a-form-item>
  202. <a-form-item label="Rand Range">
  203. <a-input v-model:value="item.randRange" placeholder="0-255" />
  204. </a-form-item>
  205. </template>
  206. <a-form-item v-else label="Packet">
  207. <a-input-group v-if="item.type === 'base64'" compact>
  208. <a-input v-model:value="item.packet" placeholder="binary data"
  209. :style="{ width: 'calc(100% - 32px)' }" />
  210. <a-button @click="item.packet = RandomUtil.randomBase64()">
  211. <template #icon>
  212. <ReloadOutlined />
  213. </template>
  214. </a-button>
  215. </a-input-group>
  216. <a-input v-else v-model:value="item.packet" placeholder="binary data" />
  217. </a-form-item>
  218. </template>
  219. </template>
  220. </template>
  221. </template>
  222. </template>
  223. <!-- ============================== UDP MASKS ============================== -->
  224. <template v-if="showUdp">
  225. <a-form-item label="UDP Masks">
  226. <a-button type="primary" size="small" @click="addUdpMaskWithDefault">
  227. <template #icon>
  228. <PlusOutlined />
  229. </template>
  230. </a-button>
  231. </a-form-item>
  232. <template v-for="(mask, mIdx) in (stream.finalmask.udp || [])" :key="`udp-${mIdx}`">
  233. <a-divider :style="{ margin: '0' }">
  234. UDP Mask {{ mIdx + 1 }}
  235. <DeleteOutlined :style="{ color: 'rgb(255, 77, 79)', cursor: 'pointer', marginLeft: '8px' }"
  236. @click="stream.delUdpMask(mIdx)" />
  237. </a-divider>
  238. <a-form-item label="Type">
  239. <a-select :value="mask.type" @change="(t) => changeUdpMaskType(mask, t)">
  240. <template v-if="isHysteria">
  241. <a-select-option value="salamander">Salamander (Hysteria2)</a-select-option>
  242. </template>
  243. <template v-else>
  244. <a-select-option value="mkcp-aes128gcm">mKCP AES-128-GCM</a-select-option>
  245. <a-select-option value="header-dns">Header DNS</a-select-option>
  246. <a-select-option value="header-dtls">Header DTLS 1.2</a-select-option>
  247. <a-select-option value="header-srtp">Header SRTP</a-select-option>
  248. <a-select-option value="header-utp">Header uTP</a-select-option>
  249. <a-select-option value="header-wechat">Header WeChat Video</a-select-option>
  250. <a-select-option value="header-wireguard">Header WireGuard</a-select-option>
  251. <a-select-option value="mkcp-original">mKCP Original</a-select-option>
  252. <a-select-option value="xdns">xDNS</a-select-option>
  253. <a-select-option value="xicmp">xICMP</a-select-option>
  254. <a-select-option value="header-custom">Header Custom</a-select-option>
  255. <a-select-option value="noise">Noise</a-select-option>
  256. </template>
  257. </a-select>
  258. </a-form-item>
  259. <a-form-item v-if="['mkcp-aes128gcm', 'salamander'].includes(mask.type)" label="Password">
  260. <a-input v-model:value="mask.settings.password" placeholder="Obfuscation password" />
  261. </a-form-item>
  262. <a-form-item v-if="mask.type === 'header-dns'" label="Domain">
  263. <a-input v-model:value="mask.settings.domain" placeholder="e.g., www.example.com" />
  264. </a-form-item>
  265. <a-form-item v-if="mask.type === 'xdns'" label="Domains">
  266. <a-select v-model:value="mask.settings.domains" mode="tags" :style="{ width: '100%' }"
  267. :token-separators="[',']" placeholder="e.g., www.example.com" />
  268. </a-form-item>
  269. <!-- Noise -->
  270. <template v-if="mask.type === 'noise'">
  271. <a-form-item label="Reset">
  272. <a-input-number v-model:value="mask.settings.reset" :min="0" />
  273. </a-form-item>
  274. <a-form-item label="Noise">
  275. <a-button type="primary" size="small" @click="mask.settings.noise.push(newNoiseItem())">
  276. <template #icon>
  277. <PlusOutlined />
  278. </template>
  279. </a-button>
  280. </a-form-item>
  281. <template v-for="(n, ni) in mask.settings.noise" :key="`udp-noise-${mIdx}-${ni}`">
  282. <a-divider :style="{ margin: '0' }">
  283. Noise {{ ni + 1 }}
  284. <DeleteOutlined :style="{ color: 'rgb(255, 77, 79)', cursor: 'pointer', marginLeft: '8px' }"
  285. @click="mask.settings.noise.splice(ni, 1)" />
  286. </a-divider>
  287. <a-form-item label="Type">
  288. <a-select :value="n.type" @change="(t) => changeItemType(n, t)">
  289. <a-select-option value="array">Array</a-select-option>
  290. <a-select-option value="str">String</a-select-option>
  291. <a-select-option value="hex">Hex</a-select-option>
  292. <a-select-option value="base64">Base64</a-select-option>
  293. </a-select>
  294. </a-form-item>
  295. <template v-if="n.type === 'array'">
  296. <a-form-item label="Rand">
  297. <a-input v-model:value="n.rand" placeholder="0 or 1-8192" />
  298. </a-form-item>
  299. <a-form-item label="Rand Range">
  300. <a-input v-model:value="n.randRange" placeholder="0-255" />
  301. </a-form-item>
  302. </template>
  303. <a-form-item v-else label="Packet">
  304. <a-input-group v-if="n.type === 'base64'" compact>
  305. <a-input v-model:value="n.packet" placeholder="binary data" :style="{ width: 'calc(100% - 32px)' }" />
  306. <a-button @click="n.packet = RandomUtil.randomBase64()">
  307. <template #icon>
  308. <ReloadOutlined />
  309. </template>
  310. </a-button>
  311. </a-input-group>
  312. <a-input v-else v-model:value="n.packet" placeholder="binary data" />
  313. </a-form-item>
  314. <a-form-item label="Delay">
  315. <a-input v-model:value="n.delay" placeholder="10-20" />
  316. </a-form-item>
  317. </template>
  318. </template>
  319. <!-- Header Custom (UDP) — flat client/server lists -->
  320. <template v-if="mask.type === 'header-custom'">
  321. <a-form-item label="Client">
  322. <a-button type="primary" size="small" @click="mask.settings.client.push(newUdpClientServerItem())">
  323. <template #icon>
  324. <PlusOutlined />
  325. </template>
  326. </a-button>
  327. </a-form-item>
  328. <template v-for="(c, ci) in mask.settings.client" :key="`udp-c-${mIdx}-${ci}`">
  329. <a-divider :style="{ margin: '0' }">
  330. Client {{ ci + 1 }}
  331. <DeleteOutlined :style="{ color: 'rgb(255, 77, 79)', cursor: 'pointer', marginLeft: '8px' }"
  332. @click="mask.settings.client.splice(ci, 1)" />
  333. </a-divider>
  334. <a-form-item label="Type">
  335. <a-select :value="c.type" @change="(t) => changeItemType(c, t)">
  336. <a-select-option value="array">Array</a-select-option>
  337. <a-select-option value="str">String</a-select-option>
  338. <a-select-option value="hex">Hex</a-select-option>
  339. <a-select-option value="base64">Base64</a-select-option>
  340. </a-select>
  341. </a-form-item>
  342. <template v-if="c.type === 'array'">
  343. <a-form-item label="Rand">
  344. <a-input-number v-model:value="c.rand" />
  345. </a-form-item>
  346. <a-form-item label="Rand Range">
  347. <a-input v-model:value="c.randRange" placeholder="0-255" />
  348. </a-form-item>
  349. </template>
  350. <a-form-item v-else label="Packet">
  351. <a-input-group v-if="c.type === 'base64'" compact>
  352. <a-input v-model:value="c.packet" placeholder="binary data" :style="{ width: 'calc(100% - 32px)' }" />
  353. <a-button @click="c.packet = RandomUtil.randomBase64()">
  354. <template #icon>
  355. <ReloadOutlined />
  356. </template>
  357. </a-button>
  358. </a-input-group>
  359. <a-input v-else v-model:value="c.packet" placeholder="binary data" />
  360. </a-form-item>
  361. </template>
  362. <a-divider :style="{ margin: '0' }" />
  363. <a-form-item label="Server">
  364. <a-button type="primary" size="small" @click="mask.settings.server.push(newUdpClientServerItem())">
  365. <template #icon>
  366. <PlusOutlined />
  367. </template>
  368. </a-button>
  369. </a-form-item>
  370. <template v-for="(s, si) in mask.settings.server" :key="`udp-s-${mIdx}-${si}`">
  371. <a-divider :style="{ margin: '0' }">
  372. Server {{ si + 1 }}
  373. <DeleteOutlined :style="{ color: 'rgb(255, 77, 79)', cursor: 'pointer', marginLeft: '8px' }"
  374. @click="mask.settings.server.splice(si, 1)" />
  375. </a-divider>
  376. <a-form-item label="Type">
  377. <a-select :value="s.type" @change="(t) => changeItemType(s, t)">
  378. <a-select-option value="array">Array</a-select-option>
  379. <a-select-option value="str">String</a-select-option>
  380. <a-select-option value="hex">Hex</a-select-option>
  381. <a-select-option value="base64">Base64</a-select-option>
  382. </a-select>
  383. </a-form-item>
  384. <template v-if="s.type === 'array'">
  385. <a-form-item label="Rand">
  386. <a-input-number v-model:value="s.rand" />
  387. </a-form-item>
  388. <a-form-item label="Rand Range">
  389. <a-input v-model:value="s.randRange" placeholder="0-255" />
  390. </a-form-item>
  391. </template>
  392. <a-form-item v-else label="Packet">
  393. <a-input-group v-if="s.type === 'base64'" compact>
  394. <a-input v-model:value="s.packet" placeholder="binary data" :style="{ width: 'calc(100% - 32px)' }" />
  395. <a-button @click="s.packet = RandomUtil.randomBase64()">
  396. <template #icon>
  397. <ReloadOutlined />
  398. </template>
  399. </a-button>
  400. </a-input-group>
  401. <a-input v-else v-model:value="s.packet" placeholder="binary data" />
  402. </a-form-item>
  403. </template>
  404. </template>
  405. <!-- xICMP -->
  406. <template v-if="mask.type === 'xicmp'">
  407. <a-form-item label="IP">
  408. <a-input v-model:value="mask.settings.ip" placeholder="0.0.0.0" />
  409. </a-form-item>
  410. <a-form-item label="ID">
  411. <a-input-number v-model:value="mask.settings.id" :min="0" />
  412. </a-form-item>
  413. </template>
  414. </template>
  415. </template>
  416. <!-- ============================== QUIC PARAMS ============================== -->
  417. <template v-if="showQuic">
  418. <a-form-item label="QUIC Params">
  419. <a-switch v-model:checked="stream.finalmask.enableQuicParams" />
  420. </a-form-item>
  421. <template v-if="stream.finalmask.enableQuicParams && stream.finalmask.quicParams">
  422. <a-form-item label="Congestion">
  423. <a-select v-model:value="stream.finalmask.quicParams.congestion">
  424. <a-select-option value="reno">Reno</a-select-option>
  425. <a-select-option value="bbr">BBR</a-select-option>
  426. <a-select-option value="brutal">Brutal</a-select-option>
  427. <a-select-option value="force-brutal">Force Brutal</a-select-option>
  428. </a-select>
  429. </a-form-item>
  430. <a-form-item label="Debug">
  431. <a-switch v-model:checked="stream.finalmask.quicParams.debug" />
  432. </a-form-item>
  433. <template v-if="['brutal', 'force-brutal'].includes(stream.finalmask.quicParams.congestion)">
  434. <a-form-item label="Brutal Up">
  435. <a-input v-model:value="stream.finalmask.quicParams.brutalUp" placeholder="65537" />
  436. </a-form-item>
  437. <a-form-item label="Brutal Down">
  438. <a-input v-model:value="stream.finalmask.quicParams.brutalDown" placeholder="65537" />
  439. </a-form-item>
  440. </template>
  441. <a-form-item label="UDP Hop">
  442. <a-switch v-model:checked="stream.finalmask.quicParams.hasUdpHop" />
  443. </a-form-item>
  444. <template v-if="stream.finalmask.quicParams.hasUdpHop && stream.finalmask.quicParams.udpHop">
  445. <a-form-item label="Hop Ports">
  446. <a-input v-model:value="stream.finalmask.quicParams.udpHop.ports" placeholder="e.g. 20000-50000" />
  447. </a-form-item>
  448. <a-form-item label="Hop Interval (s)">
  449. <a-input-number v-model:value="stream.finalmask.quicParams.udpHop.interval" :min="5" />
  450. </a-form-item>
  451. </template>
  452. <a-form-item label="Max Idle Timeout (s)">
  453. <a-input-number v-model:value="stream.finalmask.quicParams.maxIdleTimeout" :min="4" :max="120" />
  454. </a-form-item>
  455. <a-form-item label="Keep Alive Period (s)">
  456. <a-input-number v-model:value="stream.finalmask.quicParams.keepAlivePeriod" :min="2" :max="60" />
  457. </a-form-item>
  458. <a-form-item label="Disable Path MTU Dis">
  459. <a-switch v-model:checked="stream.finalmask.quicParams.disablePathMTUDiscovery" />
  460. </a-form-item>
  461. <a-form-item label="Max Incoming Streams">
  462. <a-input-number v-model:value="stream.finalmask.quicParams.maxIncomingStreams" :min="8"
  463. placeholder="1024 = default" />
  464. </a-form-item>
  465. <a-form-item label="Init Stream Window">
  466. <a-input-number v-model:value="stream.finalmask.quicParams.initStreamReceiveWindow" :min="16384"
  467. placeholder="8388608 = default" />
  468. </a-form-item>
  469. <a-form-item label="Max Stream Window">
  470. <a-input-number v-model:value="stream.finalmask.quicParams.maxStreamReceiveWindow" :min="16384"
  471. placeholder="8388608 = default" />
  472. </a-form-item>
  473. <a-form-item label="Init Conn Window">
  474. <a-input-number v-model:value="stream.finalmask.quicParams.initConnectionReceiveWindow" :min="16384"
  475. placeholder="20971520 = default" />
  476. </a-form-item>
  477. <a-form-item label="Max Conn Window">
  478. <a-input-number v-model:value="stream.finalmask.quicParams.maxConnectionReceiveWindow" :min="16384"
  479. placeholder="20971520 = default" />
  480. </a-form-item>
  481. </template>
  482. </template>
  483. </a-form>
  484. </template>