- Delete the xray settings page (routes/menu/title), geodata UI/service, XraySettingController/Service and routing-sync write paths; the stored xrayTemplateConfig row loses its last readers (GetXrayConfigTemplate now returns the embedded factory template; B1 already deleted the row). - Settings GeneralTab gains the four trafficStatsSwitches switches (settings.trafficStatsSwitches, B1) with the dual warning copy; entity AllSetting carries the key end to end (TestTrafficStatsSwitchesPlumbing). - Tag-directory consumers (panelOutbound, mtproto egress, node/host outbound pickers) move from POST /xray/ to GET /server/outboundDirectory. - Shared Mux/Sockopt forms and balancer helpers relocated to lib/xray; converter preserves sniffing ips/domains exclusions into the panel sidecar instead of dropping them (B2 gap closed by retention). - Freedom final-rules DB fix seeders retired; getDefaultJsonConfig endpoint removed (no in-repo consumer); locales pruned to referenced keys (pages.xray 331 -> 68) plus the five new settings keys.
54 lines
2.2 KiB
TypeScript
54 lines
2.2 KiB
TypeScript
import { SockoptForm } from '@/lib/xray/forms/outbound/transport';
|
|
import { useOutboundTagGroups } from '@/api/queries/useOutboundTags';
|
|
|
|
import OutboundSubtreeJsonForm from './OutboundSubtreeJsonForm';
|
|
import { serializeOverride } from './helpers';
|
|
|
|
/*
|
|
* Sockopt override editor — reuses the outbound SockoptForm (which carries its
|
|
* own enable Switch and writes streamSettings.sockopt). Serialized to the host's
|
|
* sockoptParams JSON string.
|
|
*
|
|
* A host is the client/dialer side, so the inbound-only sockopt keys are dropped
|
|
* from the output. Verified against xray-core transport/internet/sockopt_*.go:
|
|
* only V6Only and the handler-level acceptProxyProtocol / trustedXForwardedFor
|
|
* are inbound-only — tproxy (IP_TRANSPARENT) and keepalive/interface ARE applied
|
|
* on the outbound/dialer socket, so they stay. The outbound form no longer shows
|
|
* the inbound-only keys, but its default object still seeds them, so strip here.
|
|
*/
|
|
const INBOUND_ONLY_SOCKOPT = ['acceptProxyProtocol', 'V6Only', 'trustedXForwardedFor'];
|
|
|
|
function serializeClientSockopt(sockopt: unknown): string {
|
|
if (!sockopt || typeof sockopt !== 'object') return serializeOverride(sockopt);
|
|
const copy = { ...(sockopt as Record<string, unknown>) };
|
|
for (const key of INBOUND_ONLY_SOCKOPT) delete copy[key];
|
|
return serializeOverride(copy);
|
|
}
|
|
|
|
export default function HostSockoptForm({
|
|
value,
|
|
onChange,
|
|
}: {
|
|
value?: string;
|
|
onChange?: (next: string) => void;
|
|
}) {
|
|
/*
|
|
* Populate the dialerProxy dropdown with the panel's outbound tags (a host can
|
|
* chain through one of the subscription's outbounds by tag). dialerProxy chains
|
|
* through a single outbound, so balancers (routing targets) are excluded — only
|
|
* the outbound group is used; blackhole is dropped too (chaining to it just
|
|
* drops the traffic).
|
|
*/
|
|
const { data: tagGroups } = useOutboundTagGroups({ excludeBlackhole: true });
|
|
const outboundTags = tagGroups?.outbounds ?? [];
|
|
return (
|
|
<OutboundSubtreeJsonForm
|
|
value={value}
|
|
onChange={onChange}
|
|
path={['streamSettings', 'sockopt']}
|
|
serialize={serializeClientSockopt}
|
|
render={() => <SockoptForm outboundTags={outboundTags} />}
|
|
/>
|
|
);
|
|
}
|