owenclave / app/src/main/java/io/nekohasekai/sagernet/fmt/v2ray/V2RayConfig.java

github - dev - back to tree - upstream
/****************************************************************************** * * * Copyright (C) 2021 by nekohasekai * * * * This program is free software: you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation, either version 3 of the License, or * * (at your option) any later version. * * * * This program is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * * along with this program. If not, see . * * * ******************************************************************************/ package io.nekohasekai.sagernet.fmt.v2ray; import androidx.annotation.Nullable; import com.google.gson.annotations.SerializedName; import com.google.gson.stream.JsonToken; import java.util.List; import java.util.Locale; import java.util.Map; import java.util.Set; import io.nekohasekai.sagernet.fmt.gson.JsonLazyInterface; import io.nekohasekai.sagernet.fmt.gson.JsonOr; @SuppressWarnings({"SpellCheckingInspection", "unused", "RedundantSuppression"}) public class V2RayConfig { public LogObject log; public static class LogObject { public String access; public String error; public String loglevel; } public ApiObject api; public static class ApiObject { public String tag; public List services; public String listen; } public DnsObject dns; public static class DnsObject { public static class StringOrListObject extends JsonOr> { public StringOrListObject() { super(JsonToken.STRING, JsonToken.BEGIN_ARRAY); } } public Map hosts; public List servers; public List fakedns; public static class StringOrFakeDnsObject extends JsonOr { public StringOrFakeDnsObject() { super(JsonToken.STRING, JsonToken.BEGIN_OBJECT); } } public static class ServerObject { public String address; public Integer port; public String clientIp; public Boolean skipFallback; // deprecated public List domains; public List expectIPs; public String tag; public String queryStrategy; public String cacheStrategy; public String fallbackStrategy; public String domainMatcher; public List fakedns; public static class StringOrFakeDnsObject extends JsonOr { public StringOrFakeDnsObject() { super(JsonToken.STRING, JsonToken.BEGIN_OBJECT); } } } public static class StringOrServerObject extends JsonOr { public StringOrServerObject() { super(JsonToken.STRING, JsonToken.BEGIN_OBJECT); } } public String clientIp; public Boolean disableCache; // deprecated public String tag; public List domains; public List expectIPs; public String queryStrategy; public String cacheStrategy; public String fallbackStrategy; public String domainMatcher; public Boolean disableFallback; // deprecated public Boolean disableFallbackIfMatch; // deprecated } public RoutingObject routing; public static class RoutingObject { public String domainStrategy; public String domainMatcher; public List rules; public static class RuleObject { public String type; public List domain; public List domains; public List ip; public String port; public String sourcePort; public String network; public List source; public List user; public List inboundTag; public List protocol; public String attrs; public String outboundTag; public String balancerTag; // SagerNet private public List uid; public List ssid; public List networkType; public Boolean skipDomain; } public List balancers; public static class BalancerObject { public String tag; public List selector; public StrategyObject strategy; public String fallbackTag; public static class StrategyObject { public String type; public strategyConfig settings; public static class strategyConfig { public String observerTag; // random, leastPing, leastLoad, fallback public Boolean aliveOnly; // random public Boolean stickyChoice; // leastPing public Float tolerance; // leastLoad public String maxRTT; // leastLoad public Integer expected; // leastLoad public List baselines; // leastLoad public List costs; // leastLoad public static class CostObject { public Boolean regexp; public String match; public Float value; } } } } } public PolicyObject policy; public static class PolicyObject { public Map levels; public static class LevelPolicyObject { public Integer handshake; public Integer connIdle; public Integer uplinkOnly; public Integer downlinkOnly; public Boolean statsUserUplink; public Boolean statsUserDownlink; public Integer bufferSize; } public SystemPolicyObject system; public static class SystemPolicyObject { public Boolean statsInboundUplink; public Boolean statsInboundDownlink; public Boolean statsOutboundUplink; public Boolean statsOutboundDownlink; public Boolean overrideAccessLogDest; } } public List inbounds; public static class InboundObject { public String listen; public Integer port; public String protocol; public LazyInboundConfigurationObject settings; public StreamSettingsObject streamSettings; public String tag; public SniffingObject sniffing; public AllocateObject allocate; public Boolean dumpUID; public void init() { if (settings != null) { settings.init(this); } } public static class SniffingObject { public Boolean enabled; public List destOverride; public Boolean metadataOnly; public Boolean routeOnly; } public static class AllocateObject { public String strategy; public Integer refresh; public Integer concurrency; } } public static class LazyInboundConfigurationObject extends JsonLazyInterface { public LazyInboundConfigurationObject() { } public LazyInboundConfigurationObject(InboundObject ctx, InboundConfigurationObject value) { super(value); init(ctx); } public InboundObject ctx; public void init(InboundObject ctx) { this.ctx = ctx; } @Nullable @Override protected Class getType() { switch (ctx.protocol.toLowerCase(Locale.ROOT)) { case "ipc": return IPCInboundConfigurationObject.class; case "dokodemo-door": return DokodemoDoorInboundConfigurationObject.class; case "http": return HTTPInboundConfigurationObject.class; case "socks": return SocksInboundConfigurationObject.class; case "vmess": return VMessInboundConfigurationObject.class; case "vless": return VLESSInboundConfigurationObject.class; case "shadowsocks": return ShadowsocksInboundConfigurationObject.class; case "trojan": return TrojanInboundConfigurationObject.class; case "mixed": return MixedInboundConfigurationObject.class; case "wireguard": return WireGuardInboundConfigurationObject.class; case "shadowsocks-2022": return Shadowsocks2022InboundConfigurationObject.class; case "shadowsocks-2022-multi": return Shadowsocks2022MultiInboundConfigurationObject.class; case "shadowsocks-2022-relay": return Shadowsocks2022RelayInboundConfigurationObject.class; case "hysteria2": return Hysteria2InboundConfigurationObject.class; case "anytls": return AnyTLSInboundConfigurationObject.class; } return null; } } public interface InboundConfigurationObject { } public static class IPCInboundConfigurationObject implements InboundConfigurationObject { public Integer level; } public static class DokodemoDoorInboundConfigurationObject implements InboundConfigurationObject { public String address; public Integer port; public String network; public Boolean followRedirect; public Integer userLevel; } public static class HTTPInboundConfigurationObject implements InboundConfigurationObject { public List accounts; public Boolean allowTransparent; public Integer userLevel; public static class AccountObject { public String user; public String pass; public Map headers; } } public static class SocksInboundConfigurationObject implements InboundConfigurationObject { public String auth; public List accounts; public Boolean udp; public String ip; public Integer userLevel; public Boolean deferLastReply; public static class AccountObject { public String user; public String pass; } } public static class VMessInboundConfigurationObject implements InboundConfigurationObject { public List clients; @SerializedName("default") public DefaultObject defaultObject; public DetourObject detour; public Boolean disableInsecureEncryption; public static class ClientObject { public String id; public Integer level; public Integer alterId; public String email; public String experiments; } public static class DefaultObject { public Integer level; public Integer alterId; } public static class DetourObject { public String to; } } public static class VLESSInboundConfigurationObject implements InboundConfigurationObject { public List clients; public String decryption; public List fallbacks; public static class ClientObject { public String id; public Integer level; public String email; } public static class FallbackObject { public String alpn; public String path; public String dest; // fxxk public Long xver; public String name; public String type; } } public static class ShadowsocksInboundConfigurationObject implements InboundConfigurationObject { public String email; public String method; public String password; public Integer level; public String network; public Boolean ivCheck; public String plugin; public String pluginOpts; public List pluginArgs; public String pluginWorkingDir; public List clients; public List users; public static class UserObject { public String password; public Integer level; public String email; public String address; public Integer port; public String method; } } public static class TrojanInboundConfigurationObject implements InboundConfigurationObject { public List clients; public List fallbacks; public static class ClientObject { public String password; public String email; public Integer level; } public static class FallbackObject { public String name; public String alpn; public String path; public String type; public String dest; // fxxk public Long xver; } } public static class MixedInboundConfigurationObject implements InboundConfigurationObject { public String auth; public List accounts; public Boolean udp; public String ip; public Integer userLevel; public Boolean allowTransparent; public Boolean deferLastReply; public static class AccountObject { public String user; public String pass; } } public static class WireGuardInboundConfigurationObject implements InboundConfigurationObject { public List address; public String secretKey; public Integer mtu; public Integer workers; public List peers; } public static class Shadowsocks2022InboundConfigurationObject implements InboundConfigurationObject { public String method; public String key; public Integer level; public String email; public String network; public String plugin; public String pluginOpts; public List pluginArgs; public String pluginWorkingDir; } public static class Shadowsocks2022MultiInboundConfigurationObject implements InboundConfigurationObject { public String method; public String key; public String network; public String plugin; public String pluginOpts; public List pluginArgs; public String pluginWorkingDir; public List users; public static class UserObject { public String key; public Integer level; public String email; } } public static class Shadowsocks2022RelayInboundConfigurationObject implements InboundConfigurationObject { public String method; public String key; public String network; public String plugin; public String pluginOpts; public List pluginArgs; public String pluginWorkingDir; public List destinations; public static class DestinationObject { public String key; public String address; public Integer port; public Integer level; public String email; } } public static class Hysteria2InboundConfigurationObject implements InboundConfigurationObject { } public static class AnyTLSInboundConfigurationObject implements InboundConfigurationObject { public UserObject users; public List paddingScheme; public static class UserObject { public String password; public String email; public Integer level; } } public List outbounds; public static class OutboundObject { public String sendThrough; public String protocol; public LazyOutboundConfigurationObject settings; public String tag; public StreamSettingsObject streamSettings; public ProxySettingsObject proxySettings; public MuxObject mux; public SmuxObject smux; public String domainStrategy; public String dialDomainStrategy; public void init() { if (settings != null) { settings.init(this); } } public static class ProxySettingsObject { public String tag; public Boolean transportLayer; } public static class MuxObject { public Boolean enabled; public Integer concurrency; public String packetEncoding; } public static class SmuxObject { public Boolean enabled; public String protocol; public Integer maxConnections; public Integer minStreams; public Integer maxStreams; public Boolean padding; } } public static class LazyOutboundConfigurationObject extends JsonLazyInterface { public LazyOutboundConfigurationObject() { } public LazyOutboundConfigurationObject(OutboundObject ctx, OutboundConfigurationObject value) { super(value); init(ctx); } private OutboundObject ctx; public void init(OutboundObject ctx) { this.ctx = ctx; } @Nullable @Override protected Class getType() { switch (ctx.protocol.toLowerCase(Locale.ROOT)) { case "blackhole": return BlackholeOutboundConfigurationObject.class; case "dns": return DNSOutboundConfigurationObject.class; case "freedom": return FreedomOutboundConfigurationObject.class; case "http": return HTTPOutboundConfigurationObject.class; case "socks": return SocksOutboundConfigurationObject.class; case "vmess": return VMessOutboundConfigurationObject.class; case "vless": return VLESSOutboundConfigurationObject.class; case "shadowsocks": return ShadowsocksOutboundConfigurationObject.class; case "trojan": return TrojanOutboundConfigurationObject.class; case "loopback": return LoopbackOutboundConfigurationObject.class; case "wireguard": return WireGuardOutboundConfigurationObject.class; case "ssh": return SSHOutboundConfigurationObject.class; case "shadowsocks-2022": return Shadowsocks2022OutboundConfigurationObject.class; case "hysteria2": return Hysteria2OutboundConfigurationObject.class; case "tuic": return TUICOutboundConfigurationObject.class; case "http3": return HTTP3OutboundConfigurationObject.class; case "anytls": return AnyTLSOutboundConfigurationObject.class; case "juicity": return JuicityOutboundConfigurationObject.class; case "mieru": return MieruOutboundConfigurationObject.class; case "trusttunnel": return TrustTunnelOutboundConfigurationObject.class; case "snell": return SnellOutboundConfigurationObject.class; } return null; } } public interface OutboundConfigurationObject { } public static class BlackholeOutboundConfigurationObject implements OutboundConfigurationObject { public ResponseObject response; public static class ResponseObject { public String type; } } public static class DNSOutboundConfigurationObject implements OutboundConfigurationObject { public String network; public String address; public Integer port; public Integer userLevel; public Boolean overrideResponseTTL; public Integer responseTTL; public String nonIPQuery; public Boolean lookupAsExchange; } public static class FreedomOutboundConfigurationObject implements OutboundConfigurationObject { public String domainStrategy; public String redirect; public Integer userLevel; // SagerNet private public Boolean interruptConnections; } public static class HTTPOutboundConfigurationObject implements OutboundConfigurationObject { public List servers; public Boolean h1SkipWaitForReply; public static class ServerObject { public String address; public Integer port; public List users; } } public static class HTTP3OutboundConfigurationObject implements OutboundConfigurationObject { public String address; public Integer port; public Integer level; public String username; public String password; public Map headers; } public static class SocksOutboundConfigurationObject implements OutboundConfigurationObject { public List servers; public String version; public Boolean uot; public static class ServerObject { public String address; public Integer port; public List users; public static class UserObject { public String user; public String pass; public Integer level; } } } public static class VMessOutboundConfigurationObject implements OutboundConfigurationObject { public List vnext; public String packetEncoding; public static class ServerObject { public String address; public Integer port; public List users; public static class UserObject { public String id; public Integer alterId; public String security; public Integer level; public String experiments; } } } public static class ShadowsocksOutboundConfigurationObject implements OutboundConfigurationObject { public List servers; public static class ServerObject { public String address; public Integer port; public String method; public String password; public Integer level; public String email; public Boolean ivCheck; public Boolean experimentReducedIvHeadEntropy; } public String plugin; public String pluginOpts; public List pluginArgs; public String pluginWorkingDir; public Boolean uot; } public static class Shadowsocks2022OutboundConfigurationObject implements OutboundConfigurationObject { public String address; public Integer port; public String method; public String key; public String plugin; public String pluginOpts; public List pluginArgs; public String pluginWorkingDir; public Boolean uot; } public static class VLESSOutboundConfigurationObject implements OutboundConfigurationObject { public List vnext; public String packetEncoding; public static class ServerObject { public String address; public Integer port; public List users; public static class UserObject { public String id; public String encryption; public Integer level; public String flow; } } } public static class TrojanOutboundConfigurationObject implements OutboundConfigurationObject { public List servers; public static class ServerObject { public String address; public Integer port; public String password; public String email; public Integer level; } } public static class LoopbackOutboundConfigurationObject implements OutboundConfigurationObject { public String inboundTag; } public static class WireGuardOutboundConfigurationObject implements OutboundConfigurationObject { public List address; public String secretKey; public Integer mtu; public Integer workers; public List peers; public List reserved; public String domainStrategy; public static class WireGuardPeerObject { public String publicKey; public String preSharedKey; public String endpoint; public Integer keepAlive; public List allowedIPs; } } public static class SSHOutboundConfigurationObject implements OutboundConfigurationObject { public String address; public Integer port; public String user; public String password; public String privateKey; public String privateKeyPassphrase; public String publicKey; public Integer userLevel; public String clientVersion; public List hostKeyAlgorithms; public Integer keepaliveInterval; } public static class Hysteria2OutboundConfigurationObject implements OutboundConfigurationObject { public List servers; public static class ServerObject { public String address; public Integer port; public String email; public Integer level; } } public static class TUICOutboundConfigurationObject implements OutboundConfigurationObject { public String address; public Integer port; public String uuid; public String password; public String congestionControl; public String udpRelayMode; public Integer heartbeat; public Boolean zeroRTTHandshake; public Boolean udpOverStream; } public static class AnyTLSOutboundConfigurationObject implements OutboundConfigurationObject { public String address; public Integer port; public String password; public Integer idleSessionCheckInterval; public Integer idleSessionTimeout; public Integer minIdleSession; public Boolean disableReuse; } public static class JuicityOutboundConfigurationObject implements OutboundConfigurationObject { public String address; public Integer port; public String uuid; public String password; } public static class SnellOutboundConfigurationObject implements OutboundConfigurationObject { public String address; public Integer port; public String psk; public String userKey; public String obfsMode; public String obfsHost; public Integer version; public Boolean reuse; public String mode; public String domainStrategy; } public static class MieruOutboundConfigurationObject implements OutboundConfigurationObject { public String address; public Integer port; public List portRange; public String username; public String password; public String protocol; public String multiplexing; public String handshakeMode; public String trafficPattern; } public static class TrustTunnelOutboundConfigurationObject implements OutboundConfigurationObject { public String address; public Integer port; public Integer level; public String username; public String password; public Boolean http3; public String domainStrategy; } public static class StreamSettingsObject { public String network; public String security; public TLSObject tlsSettings; public UTLSObject utlsSettings; public RealityObject realitySettings; public TcpObject tcpSettings; public KcpObject kcpSettings; public WebSocketObject wsSettings; public HttpObject httpSettings; public QuicObject quicSettings; public DomainSocketObject dsSettings; public GrpcObject grpcSettings; public GrpcObject gunSettings; public MeekObject meekSettings; public HTTPUpgradeObject httpupgradeSettings; public Hysteria2Object hy2Settings; public SplitHTTPObject splithttpSettings; public SplitHTTPObject xhttpSettings; public MekyaObject mekyaSettings; public TLSMirrorObject tlsmirrorSettings; public SockoptObject sockopt; public static class SockoptObject { public Integer mark; public Boolean tcpFastOpen; public Boolean acceptProxyProtocol; public String tproxy; public Integer tcpKeepAliveInterval; public Integer tcpKeepAliveIdle; public Integer tcpFastOpenQueueLength; public String bindToDevice; public Long rxBufSize; public Long txBufSize; public Boolean forceBufSize; public TLSFragmentationObject tlsFragmentation; public static class TLSFragmentationObject { public Boolean tlsRecordFragmentation; public Boolean tcpSegmentation; } } } public static class TLSObject { public String serverName; public Boolean allowInsecure; public List alpn; public List certificates; public Boolean disableSystemRoot; public List pinnedPeerCertificateChainSha256; public List pinnedPeerCertificatePublicKeySha256; public List pinnedPeerCertificateSha256; public Boolean verifyClientCertificate; public String fingerprint; public String minVersion; public String maxVersion; public Boolean allowInsecureIfPinnedPeerCertificate; public ECHObject ech; public List serverNameToVerify; public static class CertificateObject { public String usage; public String certificateFile; public String keyFile; public List certificate; public List key; } public static class ECHObject { public Boolean enabled; public String config; public String queryDomain; public String key; } } public static class UTLSObject { public TLSObject tlsConfig; public String imitate; public Boolean noSNI; public String forceALPN; } public static class RealityObject { public String dest; // String or Integer public String target; // String or Integer, alias of dest public String type; public Long xver; public List serverNames; public String password; // alias of privateKey public String privateKey; public List shortIds; public String serverName; public String publicKey; public String shortId; public String mldsa65Verify; public String fingerprint; public String version; public Boolean disableX25519MLKEM768; } public static class TcpObject { public Boolean acceptProxyProtocol; public HeaderObject header; public static class HeaderObject { public String type; public HTTPRequestObject request; public HTTPResponseObject response; public static class HTTPRequestObject { public String version; public String method; public List path; public Map headers; } public static class HTTPResponseObject { public String version; public String status; public String reason; public Map headers; } public static class StringOrListObject extends JsonOr> { public StringOrListObject() { super(JsonToken.STRING, JsonToken.BEGIN_ARRAY); } } } } public static class KcpObject { public Integer mtu; public Integer tti; public Integer uplinkCapacity; public Integer downlinkCapacity; public Boolean congestion; public Integer readBufferSize; public Integer writeBufferSize; public HeaderObject header; public String seed; public static class HeaderObject { public String type; } } public static class WebSocketObject { public Boolean acceptProxyProtocol; public String path; public Map headers; public Integer maxEarlyData; public String earlyDataHeaderName; public Boolean useBrowserForwarding; public Boolean parseXForwardedFor; } public static class HttpObject { public List host; public String path; public String method; public Map> headers; public Boolean parseXForwardedFor; } public static class QuicObject { public String security; public String key; public HeaderObject header; public static class HeaderObject { public String type; } } public static class DomainSocketObject { public String path; @SerializedName("abstract") public Boolean isAbstract; public Boolean padding; } public static class GrpcObject { public String serviceName; public Integer idle_timeout; public Integer health_check_timeout; public Boolean permit_without_stream; public Integer initial_windows_size; public Boolean parseXForwardedFor; public Boolean multiMode; public Boolean serviceNameCompat; } public static class MeekObject { public String url; } public static class HTTPUpgradeObject { public String host; public String path; public Integer maxEarlyData; public String earlyDataHeaderName; public List header; public Boolean parseXForwardedFor; public static class HTTPUpgradeHeaderObject { public String key; public String value; } } public static class Hysteria2Object { public String password; public CongestionObject congestion; public Boolean ignore_client_bandwidth; public Boolean use_udp_extension; public OBFSObject obfs; public List passwords; public String hopPorts; public Long hopInterval; public Long hopIntervalMin; public Long hopIntervalMax; public Boolean omitMaxDatagramFrameSize; public static class CongestionObject { public String type; public Long up_mbps; public Long down_mbps; public String bbrProfile; } public static class OBFSObject { public String type; public String password; public Integer minPacketSize; public Integer maxPacketSize; } } public static class SplitHTTPObject { public String host; public String path; public Map headers; public String mode; public String scMaxConcurrentPosts; public String scMaxEachPostBytes; public String scMinPostsIntervalMs; public String xPaddingBytes; public Boolean xPaddingObfsMode; public String xPaddingKey; public String xPaddingHeader; public String xPaddingPlacement; public String xPaddingMethod; public String uplinkHTTPMethod; public String sessionIDPlacement; public String sessionIDKey; public String sessionIDTable; public String sessionIDLength; public String seqPlacement; public String seqKey; public String uplinkDataPlacement; public String uplinkDataKey; public String uplinkChunkSize; public Boolean noGRPCHeader; public XmuxObject xmux; public DownloadSettingsObject downloadSettings; public Boolean useBrowserForwarding; public static class XmuxObject { public String maxConcurrency; public String maxConnections; public String cMaxReuseTimes; public String hMaxRequestTimes; public String hMaxReusableSecs; } public static class DownloadSettingsObject { public String address; public Integer port; public String network; public String security; public TLSObject tlsSettings; public UTLSObject utlsSettings; public RealityObject realitySettings; public SplitHTTPObject splithttpSettings; public SplitHTTPObject xhttpSettings; } } public static class MekyaObject { public KcpObject kcp; public Integer maxWriteDelay; public Integer maxRequestSize; public Integer pollingIntervalInitial; public Integer maxWriteSize; public Integer maxWriteDurationMs; public Integer maxSimultaneousWriteConnection; public Integer packetWritingBuffer; public String url; public Integer h2PoolSize; } public static class TLSMirrorObject { public String forwardAddress; public Integer forwardPort; public String forwardTag; public String carrierConnectionTag; public EmbeddedTrafficGeneratorObject embeddedTrafficGenerator; public String primaryKey; public List explicitNonceCiphersuites; public TimeSpecObject deferInstanceDerivedWriteTime; public TransportPaddingObject transportLayerPadding; public ConnectionEnrolmentObject connectionEnrolment; public Boolean sequenceWatermarkingEnabled; public static class EmbeddedTrafficGeneratorObject { public List steps; public TLSObject tlsSettings; public UTLSObject utlsSettings; } public static class EmbeddedTrafficGeneratorStepObject { public String name; public String host; public String path; public String method; public List nextStep; public Boolean connectionReady; public List headers; public Boolean connectionRecallExit; public EmbeddedTrafficGeneratorTimeSpecObject waitTime; public Boolean h2DoNotWaitForDownloadFinish; } public static class EmbeddedTrafficGeneratorTimeSpecObject { public Long baseNanoseconds; public Long uniformRandomMultiplierNanoseconds; } public static class EmbeddedTrafficGeneratorTransferCandidateObject { public Integer weight; public Long gotoLocation; } public static class EmbeddedTrafficGeneratorHeaderObject { public String name; public String value; public List values; } public static class ConnectionEnrolmentObject { public String primaryIngressOutbound; public String primaryEgressOutbound; public String bootstrapEgressOutbound; } public static class TimeSpecObject { public Long baseNanoseconds; public Long uniformRandomMultiplierNanoseconds; } public static class TransportPaddingObject { public Boolean enabled; } } public Map stats; public List fakedns; // deprecated public static class FakeDnsObject { public String ipPool; public Integer poolSize; } public BrowserForwarderObject browserForwarder; public static class BrowserForwarderObject { public String listenAddr; public Integer listenPort; } public BrowserDialerObject browserDialer; public static class BrowserDialerObject { public String listenAddr; public Integer listenPort; } public ObservatoryObject observatory; public static class ObservatoryObject { public Set subjectSelector; public String probeURL; public String probeInterval; public Boolean persistentProbeResult; public Boolean enableConcurrency; // SagerNet private } public MultiObservatoryObject multiObservatory; public static class MultiObservatoryObject { public List observers; public static class MultiObservatoryItem { public String type; public String tag; public Map settings; // ObservatoryObject or BurstObservatoryObject, WTF } } public BurstObservatoryObject burstObservatory; public static class BurstObservatoryObject { public Set subjectSelector; public PingConfigObject pingConfig; public static class PingConfigObject { public String destination; public String connectivity; public String interval; public Integer sampling; public String timeout; } } public FileSystemStorageObject fileSystemStorage; public static class FileSystemStorageObject { public String stateStorageRoot; public String instanceName; public String protoJSON; } public void init() { if (inbounds != null) { for (InboundObject inbound : inbounds) inbound.init(); } if (outbounds != null) { for (OutboundObject outbound : outbounds) outbound.init(); } } }