mirror of
https://github.com/MHSanaei/3x-ui.git
synced 2026-07-12 15:46:06 +00:00
dab0add191
* feat(finalmask): support salamander packetSize (Gecko) and realm tlsConfig Hysteria v2.9.1/v2.9.2 added two finalmask features that the pinned Xray-core (26.6.1, 94ffd50) already supports but the panel UI did not expose: Salamander's packetSize range (Gecko, XTLS/Xray-core#6198) and the Realm UDP hole-punching mask's optional tlsConfig (XTLS/Xray-core#6137). Add typed schemas and form fields for both, keeping UdpMaskSchema.settings permissive per the existing finalmask design note. packetSize reuses the existing dash-range preprocess (like udpHop.ports) so it round-trips under the fm= share-link param with no new URI key; realm tlsConfig emits xray's flat TLSConfig shape (serverName/alpn/fingerprint/allowInsecure). Verified against the bundled Xray 26.6.1: configs with packetSize and realm tlsConfig validate (Configuration OK.), plain salamander stays backward-compatible, and a malformed packetSize is correctly rejected by the salamander mask builder. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * test(finalmask): add snapshots for salamander-gecko and realm-tls fixtures vitest run does not auto-create missing snapshots in CI mode, so the two new fixtures need committed snapshot entries. Verified under node:22 that finalmask.test.ts passes (6/6) with these snapshots. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * feat(finalmask): polished Gecko UX with core-grounded validation Fold PR #5281's Gecko work into the Realm tlsConfig base: - Replace the plain packetSize input with a Salamander/Gecko mode selector and validated Min/Max number inputs. - parseGeckoPacketSize enforces xray-core's real bound (1 <= min <= max <= 2048, the gecko buffer size) so the panel rejects configs core would reject at runtime. - Accurate Gecko description; add parser unit tests. - Drop the unused Salamander/Realm settings schemas; settings stay permissive and are validated at the form level. --------- Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com> Co-authored-by: Sanaei <ho3ein.sanaei@gmail.com>
47 lines
1.8 KiB
TypeScript
47 lines
1.8 KiB
TypeScript
/// <reference types="vite/client" />
|
|
import { describe, expect, it } from 'vitest';
|
|
|
|
import { parseGeckoPacketSize } from '@/lib/xray/forms/transport/FinalMaskForm';
|
|
import { FinalMaskStreamSettingsSchema } from '@/schemas/protocols/stream';
|
|
|
|
const fixtures = import.meta.glob<unknown>(
|
|
'./golden/fixtures/finalmask/*.json',
|
|
{ eager: true, import: 'default' },
|
|
);
|
|
|
|
function fixtureName(path: string): string {
|
|
const file = path.split('/').pop() ?? path;
|
|
return file.replace(/\.json$/, '');
|
|
}
|
|
|
|
describe('FinalMaskStreamSettingsSchema fixtures', () => {
|
|
const entries = Object.entries(fixtures).sort(([a], [b]) => a.localeCompare(b));
|
|
expect(entries.length, 'expected at least one fixture under golden/fixtures/finalmask').toBeGreaterThan(0);
|
|
|
|
for (const [path, raw] of entries) {
|
|
it(`parses ${fixtureName(path)} byte-stably`, () => {
|
|
const parsed = FinalMaskStreamSettingsSchema.parse(raw);
|
|
expect(parsed).toMatchSnapshot();
|
|
});
|
|
}
|
|
});
|
|
|
|
describe('parseGeckoPacketSize', () => {
|
|
it('accepts positive ordered packet size ranges', () => {
|
|
expect(parseGeckoPacketSize('512-1200')).toEqual({ min: 512, max: 1200 });
|
|
expect(parseGeckoPacketSize('1200-1200')).toEqual({ min: 1200, max: 1200 });
|
|
expect(parseGeckoPacketSize('1-2048')).toEqual({ min: 1, max: 2048 });
|
|
});
|
|
|
|
it('rejects invalid packet size ranges', () => {
|
|
expect(parseGeckoPacketSize('')).toBeNull();
|
|
expect(parseGeckoPacketSize('0-1200')).toBeNull();
|
|
expect(parseGeckoPacketSize('1200-512')).toBeNull();
|
|
expect(parseGeckoPacketSize('512')).toBeNull();
|
|
expect(parseGeckoPacketSize('512-abc')).toBeNull();
|
|
// exceeds xray-core's gecko buffer (max 2048)
|
|
expect(parseGeckoPacketSize('512-2049')).toBeNull();
|
|
expect(parseGeckoPacketSize('512-9999')).toBeNull();
|
|
});
|
|
});
|