feat(xray): add loopback sniffing and per-segment fragment masks

- Loopback outbound: add sniffing support (xray-core #6320)

- FinalMask fragment: support per-segment lengths/delays arrays with legacy length/delay migration (xray-core #6334)

- Consolidate sniffing into a shared SniffingFields component and the canonical SniffingSchema across inbound, VLESS reverse, and loopback
This commit is contained in:
MHSanaei
2026-06-23 13:24:16 +02:00
parent 42cd351e4e
commit 852b53db79
18 changed files with 343 additions and 255 deletions
@@ -359,6 +359,39 @@ describe('outbound-form-adapter: round-trip', () => {
expect(back.settings).toEqual({ inboundTag: 'tagged-inbound' });
});
it('loopback omits sniffing when disabled', () => {
const form = rawOutboundToFormValues({
protocol: 'loopback',
settings: { inboundTag: 'tagged-inbound' },
});
if (form.protocol === 'loopback') {
expect(form.settings.sniffing.enabled).toBe(false);
}
const back = formValuesToWirePayload(form);
expect(back.settings).not.toHaveProperty('sniffing');
});
it('loopback round-trips sniffing when enabled', () => {
const wire = {
protocol: 'loopback',
settings: {
inboundTag: 'tagged-inbound',
sniffing: { enabled: true, destOverride: ['tls', 'http'], routeOnly: true },
},
};
const form = rawOutboundToFormValues(wire);
if (form.protocol === 'loopback') {
expect(form.settings.sniffing.enabled).toBe(true);
expect(form.settings.sniffing.destOverride).toEqual(['tls', 'http']);
expect(form.settings.sniffing.routeOnly).toBe(true);
}
const back = formValuesToWirePayload(form);
const sniffing = (back.settings as Record<string, unknown>).sniffing as Record<string, unknown>;
expect(sniffing.enabled).toBe(true);
expect(sniffing.destOverride).toEqual(['tls', 'http']);
expect(sniffing.routeOnly).toBe(true);
});
it('unknown protocol falls back to vless without throwing', () => {
const form = rawOutboundToFormValues({ protocol: 'mysterious', settings: {} });
expect(form.protocol).toBe('vless');