mirror of
https://github.com/MHSanaei/3x-ui.git
synced 2026-07-24 21:46:07 +00:00
fix(ui): make the Happy Eyeballs toggle produce a config xray actually enables
Toggling Happy Eyeballs on filled the object with schema defaults, and tryDelayMs defaulted to 0. That broke the feature twice over: xray-core treats tryDelayMs=0 as happy-eyeballs-off, and the wire normalizer strips every field that equals its default, leaving an empty object it then deletes - so the switch silently flipped back off on reopen (the "disabled when Prefer IPv6 is off" symptom; prioritizeIPv6=true was the one non-default that let the object survive). Default tryDelayMs to the recommended 250ms so an enabled config survives serialization and is functional in the core. Closes #5780
This commit is contained in:
@@ -33,7 +33,7 @@ export const AddressPortStrategySchema = z.enum([
|
|||||||
export type AddressPortStrategy = z.infer<typeof AddressPortStrategySchema>;
|
export type AddressPortStrategy = z.infer<typeof AddressPortStrategySchema>;
|
||||||
|
|
||||||
export const HappyEyeballsSchema = z.object({
|
export const HappyEyeballsSchema = z.object({
|
||||||
tryDelayMs: z.number().int().min(0).default(0),
|
tryDelayMs: z.number().int().min(0).default(250),
|
||||||
prioritizeIPv6: z.boolean().default(false),
|
prioritizeIPv6: z.boolean().default(false),
|
||||||
interleave: z.number().int().min(1).default(1),
|
interleave: z.number().int().min(1).default(1),
|
||||||
maxConcurrentTry: z.number().int().min(0).default(4),
|
maxConcurrentTry: z.number().int().min(0).default(4),
|
||||||
|
|||||||
@@ -10,6 +10,7 @@ import {
|
|||||||
validateRealityTarget,
|
validateRealityTarget,
|
||||||
} from '@/lib/xray/stream-wire-normalize';
|
} from '@/lib/xray/stream-wire-normalize';
|
||||||
import { InboundFormSchema } from '@/schemas/forms/inbound-form';
|
import { InboundFormSchema } from '@/schemas/forms/inbound-form';
|
||||||
|
import { HappyEyeballsSchema } from '@/schemas/protocols/stream/sockopt';
|
||||||
import type { InboundFormValues } from '@/schemas/forms/inbound-form';
|
import type { InboundFormValues } from '@/schemas/forms/inbound-form';
|
||||||
import { XHttpXmuxSchema } from '@/schemas/protocols/stream/xhttp';
|
import { XHttpXmuxSchema } from '@/schemas/protocols/stream/xhttp';
|
||||||
|
|
||||||
@@ -204,6 +205,14 @@ describe('normalizeSockoptForWire', () => {
|
|||||||
});
|
});
|
||||||
expect(out?.domainStrategy).toBe('UseIP');
|
expect(out?.domainStrategy).toBe('UseIP');
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('keeps a freshly toggled happyEyeballs (schema defaults) across the wire round trip', () => {
|
||||||
|
const out = normalizeSockoptForWire({
|
||||||
|
happyEyeballs: HappyEyeballsSchema.parse({}),
|
||||||
|
});
|
||||||
|
|
||||||
|
expect(out?.happyEyeballs).toEqual({ tryDelayMs: 250 });
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('normalizeStreamSettingsForWire reality', () => {
|
describe('normalizeStreamSettingsForWire reality', () => {
|
||||||
|
|||||||
Reference in New Issue
Block a user