Kaynağa Gözat

fix(frontend): QUIC udpHop.interval is a range string, not a number (B19)

User report: "streamSettings.finalmask.quicParams.udpHop.interval:
Invalid input: expected string, received number".

Three-part fix:
- FinalMaskForm: Hop Interval input changed from InputNumber to
  Input with "e.g. 5-10" placeholder. xray-core spec says interval
  is a range string like '5-10' (seconds between min-max hops),
  not a single number.
- FinalMaskForm: defaultQuicParams() seeds interval: '5-10' instead
  of the broken `interval: 5`.
- QuicUdpHopSchema: preprocess coerces number → string for legacy
  DB rows that were written by the now-fixed buggy UI. Stops the
  load-time validation crash on existing inbounds.

Tests still 296/296.
MHSanaei 1 gün önce
ebeveyn
işleme
ce2fd2f0dd

+ 2 - 2
frontend/src/components/FinalMaskForm.tsx

@@ -91,7 +91,7 @@ function defaultQuicParams(): Record<string, unknown> {
     brutalUp: 0,
     brutalDown: 0,
     hasUdpHop: false,
-    udpHop: { ports: '20000-50000', interval: 5 },
+    udpHop: { ports: '20000-50000', interval: '5-10' },
     maxIdleTimeout: 30,
     keepAlivePeriod: 10,
     disablePathMTUDiscovery: false,
@@ -707,7 +707,7 @@ function QuicParamsForm({ base, form }: { base: (string | number)[]; form: FormI
             <Input placeholder="e.g. 20000-50000" />
           </Form.Item>
           <Form.Item label="Hop Interval (s)" name={[...base, 'udpHop', 'interval']}>
-            <InputNumber min={5} />
+            <Input placeholder="e.g. 5-10" />
           </Form.Item>
         </>
       )}

+ 9 - 3
frontend/src/schemas/protocols/stream/finalmask.ts

@@ -47,10 +47,16 @@ export type QuicCongestion = z.infer<typeof QuicCongestionSchema>;
 
 // udpHop randomizes the QUIC port between a range every `interval` seconds
 // to dodge port-based blocking. Both fields are dash-range strings on the
-// wire (e.g. '20000-50000', '5-10').
+// wire (e.g. '20000-50000', '5-10'). preprocess coerces legacy DB rows
+// where interval was stored as a number (UI bug — see B19 in commit history).
+const StringRangeSchema = z.preprocess(
+  (v) => (typeof v === 'number' ? String(v) : v),
+  z.string(),
+);
+
 export const QuicUdpHopSchema = z.object({
-  ports: z.string().default('20000-50000'),
-  interval: z.string().default('5-10'),
+  ports: StringRangeSchema.default('20000-50000'),
+  interval: StringRangeSchema.default('5-10'),
 });
 export type QuicUdpHop = z.infer<typeof QuicUdpHopSchema>;