From d1da522700ecaa4650bf3b522f63992b2f426a6d Mon Sep 17 00:00:00 2001 From: arm64v8a <48624112+arm64v8a@users.noreply.github.com> Date: Tue, 8 Aug 2023 16:57:39 +0900 Subject: [PATCH] use internal hysteria & tuic --- .../sagernet/database/DataStore.kt | 1 + .../sagernet/database/ProxyEntity.kt | 2 +- .../nekohasekai/sagernet/fmt/ConfigBuilder.kt | 9 +- .../sagernet/fmt/hysteria/HysteriaBean.java | 26 +- .../sagernet/fmt/hysteria/HysteriaFmt.kt | 46 ++-- .../nekohasekai/sagernet/fmt/tuic/TuicFmt.kt | 27 +++ .../sagernet/fmt/v2ray/StandardV2RayBean.java | 1 + .../nekohasekai/sagernet/group/RawUpdater.kt | 7 +- .../ui/profile/HysteriaSettingsActivity.kt | 8 +- .../ui/profile/TuicSettingsActivity.kt | 12 - .../java/moe/matsuri/nb4a/SingBoxOptions.java | 228 ++++++++++++++++++ app/src/main/res/xml/hysteria_preferences.xml | 2 +- app/src/main/res/xml/tuic_preferences.xml | 5 - 13 files changed, 318 insertions(+), 56 deletions(-) diff --git a/app/src/main/java/io/nekohasekai/sagernet/database/DataStore.kt b/app/src/main/java/io/nekohasekai/sagernet/database/DataStore.kt index 7a188b8..eaad164 100644 --- a/app/src/main/java/io/nekohasekai/sagernet/database/DataStore.kt +++ b/app/src/main/java/io/nekohasekai/sagernet/database/DataStore.kt @@ -176,6 +176,7 @@ object DataStore : OnPreferenceDataStoreChangeListener { var profileName by profileCacheStore.string(Key.PROFILE_NAME) var serverAddress by profileCacheStore.string(Key.SERVER_ADDRESS) var serverPort by profileCacheStore.stringToInt(Key.SERVER_PORT) + var serverPorts by profileCacheStore.string("serverPorts") var serverUsername by profileCacheStore.string(Key.SERVER_USERNAME) var serverPassword by profileCacheStore.string(Key.SERVER_PASSWORD) var serverPassword1 by profileCacheStore.string(Key.SERVER_PASSWORD1) diff --git a/app/src/main/java/io/nekohasekai/sagernet/database/ProxyEntity.kt b/app/src/main/java/io/nekohasekai/sagernet/database/ProxyEntity.kt index f79a5af..9aa1a2f 100644 --- a/app/src/main/java/io/nekohasekai/sagernet/database/ProxyEntity.kt +++ b/app/src/main/java/io/nekohasekai/sagernet/database/ProxyEntity.kt @@ -296,7 +296,7 @@ data class ProxyEntity( TYPE_TROJAN_GO -> true TYPE_NAIVE -> true TYPE_HYSTERIA -> !hysteriaBean!!.canUseSingBox() - TYPE_TUIC -> true + TYPE_TUIC -> tuicBean!!.protocolVersion == 4 TYPE_NEKO -> true else -> false } diff --git a/app/src/main/java/io/nekohasekai/sagernet/fmt/ConfigBuilder.kt b/app/src/main/java/io/nekohasekai/sagernet/fmt/ConfigBuilder.kt index ba76625..23896ff 100644 --- a/app/src/main/java/io/nekohasekai/sagernet/fmt/ConfigBuilder.kt +++ b/app/src/main/java/io/nekohasekai/sagernet/fmt/ConfigBuilder.kt @@ -13,7 +13,6 @@ import io.nekohasekai.sagernet.database.SagerDatabase import io.nekohasekai.sagernet.fmt.ConfigBuildResult.IndexEntity import io.nekohasekai.sagernet.fmt.hysteria.HysteriaBean import io.nekohasekai.sagernet.fmt.hysteria.buildSingBoxOutboundHysteriaBean -import io.nekohasekai.sagernet.fmt.hysteria.isMultiPort import io.nekohasekai.sagernet.fmt.internal.ChainBean import io.nekohasekai.sagernet.fmt.shadowsocks.ShadowsocksBean import io.nekohasekai.sagernet.fmt.shadowsocks.buildSingBoxOutboundShadowsocksBean @@ -22,6 +21,7 @@ import io.nekohasekai.sagernet.fmt.socks.buildSingBoxOutboundSocksBean import io.nekohasekai.sagernet.fmt.ssh.SSHBean import io.nekohasekai.sagernet.fmt.ssh.buildSingBoxOutboundSSHBean import io.nekohasekai.sagernet.fmt.tuic.TuicBean +import io.nekohasekai.sagernet.fmt.tuic.buildSingBoxOutboundTuicBean import io.nekohasekai.sagernet.fmt.tuic.pluginId import io.nekohasekai.sagernet.fmt.v2ray.StandardV2RayBean import io.nekohasekai.sagernet.fmt.v2ray.buildSingBoxOutboundStandardV2RayBean @@ -382,6 +382,9 @@ fun buildConfig( is HysteriaBean -> buildSingBoxOutboundHysteriaBean(bean).asMap() + is TuicBean -> + buildSingBoxOutboundTuicBean(bean).asMap() + is SOCKSBean -> buildSingBoxOutboundSocksBean(bean).asMap() @@ -664,9 +667,7 @@ fun buildConfig( // Bypass Lookup for the first profile bypassDNSBeans.forEach { var serverAddr = it.serverAddress - if (it is HysteriaBean && it.isMultiPort()) { - serverAddr = it.serverAddress.substringBeforeLast(":") - } + if (it is ConfigBean) { var config = mutableMapOf() config = gson.fromJson(it.config, config.javaClass) diff --git a/app/src/main/java/io/nekohasekai/sagernet/fmt/hysteria/HysteriaBean.java b/app/src/main/java/io/nekohasekai/sagernet/fmt/hysteria/HysteriaBean.java index 239c9d4..56a8a45 100644 --- a/app/src/main/java/io/nekohasekai/sagernet/fmt/hysteria/HysteriaBean.java +++ b/app/src/main/java/io/nekohasekai/sagernet/fmt/hysteria/HysteriaBean.java @@ -9,6 +9,8 @@ import org.jetbrains.annotations.NotNull; import io.nekohasekai.sagernet.fmt.AbstractBean; import io.nekohasekai.sagernet.fmt.KryoConverters; +import io.nekohasekai.sagernet.ktx.NetsKt; +import kotlin.text.StringsKt; public class HysteriaBean extends AbstractBean { @@ -38,6 +40,8 @@ public class HysteriaBean extends AbstractBean { public Boolean disableMtuDiscovery; public Integer hopInterval; + public String serverPorts; + @Override public boolean canMapping() { return protocol != PROTOCOL_FAKETCP; @@ -62,11 +66,12 @@ public class HysteriaBean extends AbstractBean { if (connectionReceiveWindow == null) connectionReceiveWindow = 0; if (disableMtuDiscovery == null) disableMtuDiscovery = false; if (hopInterval == null) hopInterval = 10; + if (serverPorts == null) serverPorts = "443"; } @Override public void serialize(ByteBufferOutput output) { - output.writeInt(5); + output.writeInt(6); super.serialize(output); output.writeInt(authPayloadType); output.writeString(authPayload); @@ -84,6 +89,7 @@ public class HysteriaBean extends AbstractBean { output.writeInt(connectionReceiveWindow); output.writeBoolean(disableMtuDiscovery); output.writeInt(hopInterval); + output.writeString(serverPorts); } @@ -113,6 +119,17 @@ public class HysteriaBean extends AbstractBean { if (version >= 5) { hopInterval = input.readInt(); } + if (version >= 6) { + serverPorts = input.readString(); + } else { + // old update to new + if (HysteriaFmtKt.isMultiPort(serverAddress)) { + serverPorts = StringsKt.substringAfterLast(serverAddress, ":", serverAddress); + serverAddress = StringsKt.substringBeforeLast(serverAddress, ":", serverAddress); + } else { + serverPorts = serverPort.toString(); + } + } } @Override @@ -128,10 +145,7 @@ public class HysteriaBean extends AbstractBean { @Override public String displayAddress() { - if (HysteriaFmtKt.isMultiPort(this)) { - return serverAddress; - } - return super.displayAddress(); + return NetsKt.wrapIPV6Host(serverAddress) + ":" + serverPorts; } @Override @@ -157,4 +171,4 @@ public class HysteriaBean extends AbstractBean { return new HysteriaBean[size]; } }; -} +} diff --git a/app/src/main/java/io/nekohasekai/sagernet/fmt/hysteria/HysteriaFmt.kt b/app/src/main/java/io/nekohasekai/sagernet/fmt/hysteria/HysteriaFmt.kt index 8a91622..d1d5aeb 100644 --- a/app/src/main/java/io/nekohasekai/sagernet/fmt/hysteria/HysteriaFmt.kt +++ b/app/src/main/java/io/nekohasekai/sagernet/fmt/hysteria/HysteriaFmt.kt @@ -18,11 +18,11 @@ fun parseHysteria(url: String): HysteriaBean { ) return HysteriaBean().apply { serverAddress = link.host - serverPort = link.port + serverPorts = link.port.toString() name = link.fragment link.queryParameter("mport")?.also { - serverAddress = serverAddress.wrapIPV6Host() + ":" + it + serverPorts = it } link.queryParameter("peer")?.also { sni = it @@ -51,6 +51,7 @@ fun parseHysteria(url: String): HysteriaBean { "faketcp" -> { protocol = HysteriaBean.PROTOCOL_FAKETCP } + "wechat-video" -> { protocol = HysteriaBean.PROTOCOL_WECHAT_VIDEO } @@ -60,9 +61,11 @@ fun parseHysteria(url: String): HysteriaBean { } fun HysteriaBean.toUri(): String { - val builder = linkBuilder().host(serverAddress.substringBeforeLast(":")).port(serverPort) - if (isMultiPort()) { - builder.addQueryParameter("mport", serverAddress.substringAfterLast(":")) + val builder = linkBuilder() + .host(serverAddress) + .port(getFirstPort(serverPorts)) + if (isMultiPort(displayAddress())) { + builder.addQueryParameter("mport", serverPorts) } if (allowInsecure) { builder.addQueryParameter("insecure", "1") @@ -86,6 +89,7 @@ fun HysteriaBean.toUri(): String { HysteriaBean.PROTOCOL_FAKETCP -> { builder.addQueryParameter("protocol", "faketcp") } + HysteriaBean.PROTOCOL_WECHAT_VIDEO -> { builder.addQueryParameter("protocol", "wechat-video") } @@ -101,11 +105,8 @@ fun HysteriaBean.toUri(): String { fun JSONObject.parseHysteria(): HysteriaBean { return HysteriaBean().apply { - serverAddress = optString("server") - if (!isMultiPort()) { - serverAddress = optString("server").substringBeforeLast(":") - serverPort = optString("server").substringAfterLast(":").toIntOrNull() ?: 443 - } + serverAddress = optString("server").substringBeforeLast(":") + serverPorts = optString("server").substringAfterLast(":") uploadMbps = getIntNya("up_mbps") downloadMbps = getIntNya("down_mbps") obfuscation = getStr("obfs") @@ -122,6 +123,7 @@ fun JSONObject.parseHysteria(): HysteriaBean { "faketcp" -> { protocol = HysteriaBean.PROTOCOL_FAKETCP } + "wechat-video" -> { protocol = HysteriaBean.PROTOCOL_WECHAT_VIDEO } @@ -139,11 +141,12 @@ fun JSONObject.parseHysteria(): HysteriaBean { fun HysteriaBean.buildHysteriaConfig(port: Int, cacheFile: (() -> File)?): String { return JSONObject().apply { - put("server", if (isMultiPort()) serverAddress else wrapUri()) + put("server", displayAddress()) when (protocol) { HysteriaBean.PROTOCOL_FAKETCP -> { put("protocol", "faketcp") } + HysteriaBean.PROTOCOL_WECHAT_VIDEO -> { put("protocol", "wechat-video") } @@ -190,24 +193,33 @@ fun HysteriaBean.buildHysteriaConfig(port: Int, cacheFile: (() -> File)?): Strin }.toStringPretty() } -fun HysteriaBean.isMultiPort(): Boolean { - if (!serverAddress.contains(":")) return false - val p = serverAddress.substringAfterLast(":") +fun isMultiPort(hyAddr: String): Boolean { + if (!hyAddr.contains(":")) return false + val p = hyAddr.substringAfterLast(":") if (p.contains("-") || p.contains(",")) return true return false } +fun getFirstPort(portStr: String): Int { + return portStr.substringBefore(":").substringBefore(",").toIntOrNull() ?: 443 +} + fun HysteriaBean.canUseSingBox(): Boolean { - if (isMultiPort() || protocol != HysteriaBean.PROTOCOL_UDP) return false + if (protocol != HysteriaBean.PROTOCOL_UDP) return false return true } fun buildSingBoxOutboundHysteriaBean(bean: HysteriaBean): SingBoxOptions.Outbound_HysteriaOptions { - // No multi-port return SingBoxOptions.Outbound_HysteriaOptions().apply { type = "hysteria" server = bean.serverAddress - server_port = bean.serverPort + val port = bean.serverPorts.toIntOrNull() + if (port != null) { + server_port = port + } else { + hop_ports = bean.serverPorts + } + hop_interval = bean.hopInterval up_mbps = bean.uploadMbps down_mbps = bean.downloadMbps obfs = bean.obfuscation diff --git a/app/src/main/java/io/nekohasekai/sagernet/fmt/tuic/TuicFmt.kt b/app/src/main/java/io/nekohasekai/sagernet/fmt/tuic/TuicFmt.kt index e5e3f09..fc16469 100644 --- a/app/src/main/java/io/nekohasekai/sagernet/fmt/tuic/TuicFmt.kt +++ b/app/src/main/java/io/nekohasekai/sagernet/fmt/tuic/TuicFmt.kt @@ -2,6 +2,7 @@ package io.nekohasekai.sagernet.fmt.tuic import io.nekohasekai.sagernet.fmt.LOCALHOST import io.nekohasekai.sagernet.ktx.isIpAddress +import moe.matsuri.nb4a.SingBoxOptions import moe.matsuri.nb4a.utils.JavaUtil import moe.matsuri.nb4a.utils.Util import moe.matsuri.nb4a.utils.listByLineOrComma @@ -9,6 +10,32 @@ import org.json.JSONArray import org.json.JSONObject import java.io.File +fun buildSingBoxOutboundTuicBean(bean: TuicBean): SingBoxOptions.Outbound_TUICOptions { + return SingBoxOptions.Outbound_TUICOptions().apply { + type = "tuic" + server = bean.serverAddress + server_port = bean.serverPort + uuid = bean.uuid + password = bean.token + congestion_control = bean.congestionController + udp_relay_mode = bean.udpRelayMode + zero_rtt_handshake = bean.reduceRTT + tls = SingBoxOptions.OutboundTLSOptions().apply { + if (bean.sni.isNotBlank()) { + server_name = bean.sni + } + if (bean.alpn.isNotBlank()) { + alpn = bean.alpn.listByLineOrComma() + } + if (bean.caText.isNotBlank()) { + certificate = bean.caText + } + insecure = bean.allowInsecure + enabled = true + } + } +} + fun TuicBean.pluginId(): String { return when (protocolVersion) { 5 -> "tuic-v5-plugin" diff --git a/app/src/main/java/io/nekohasekai/sagernet/fmt/v2ray/StandardV2RayBean.java b/app/src/main/java/io/nekohasekai/sagernet/fmt/v2ray/StandardV2RayBean.java index add8fd1..bdf7d60 100644 --- a/app/src/main/java/io/nekohasekai/sagernet/fmt/v2ray/StandardV2RayBean.java +++ b/app/src/main/java/io/nekohasekai/sagernet/fmt/v2ray/StandardV2RayBean.java @@ -187,6 +187,7 @@ public abstract class StandardV2RayBean extends AbstractBean { StandardV2RayBean bean = ((StandardV2RayBean) other); bean.allowInsecure = allowInsecure; bean.utlsFingerprint = utlsFingerprint; + bean.packetEncoding = packetEncoding; } public boolean isVLESS() { diff --git a/app/src/main/java/io/nekohasekai/sagernet/group/RawUpdater.kt b/app/src/main/java/io/nekohasekai/sagernet/group/RawUpdater.kt index 8b653b8..ee432be 100644 --- a/app/src/main/java/io/nekohasekai/sagernet/group/RawUpdater.kt +++ b/app/src/main/java/io/nekohasekai/sagernet/group/RawUpdater.kt @@ -311,8 +311,8 @@ object RawUpdater : GroupUpdater() { } "xudp" -> if (opt.value.toString() == "true") { - bean.packetEncoding = 2 - } + bean.packetEncoding = 2 + } "network" -> { bean.type = opt.value as String @@ -511,8 +511,7 @@ object RawUpdater : GroupUpdater() { } } if (hopPorts.isNotBlank()) { - bean.serverAddress = - bean.serverAddress.wrapIPV6Host() + ":" + hopPorts + bean.serverPorts = hopPorts } proxies.add(bean) } diff --git a/app/src/main/java/io/nekohasekai/sagernet/ui/profile/HysteriaSettingsActivity.kt b/app/src/main/java/io/nekohasekai/sagernet/ui/profile/HysteriaSettingsActivity.kt index 02534b5..78d2257 100644 --- a/app/src/main/java/io/nekohasekai/sagernet/ui/profile/HysteriaSettingsActivity.kt +++ b/app/src/main/java/io/nekohasekai/sagernet/ui/profile/HysteriaSettingsActivity.kt @@ -18,7 +18,7 @@ class HysteriaSettingsActivity : ProfileSettingsActivity() { override fun HysteriaBean.init() { DataStore.profileName = name DataStore.serverAddress = serverAddress - DataStore.serverPort = serverPort + DataStore.serverPorts = serverPorts DataStore.serverObfs = obfuscation DataStore.serverAuthType = authPayloadType DataStore.serverProtocolVersion = protocol @@ -38,7 +38,7 @@ class HysteriaSettingsActivity : ProfileSettingsActivity() { override fun HysteriaBean.serialize() { name = DataStore.profileName serverAddress = DataStore.serverAddress - serverPort = DataStore.serverPort + serverPorts = DataStore.serverPorts obfuscation = DataStore.serverObfs authPayloadType = DataStore.serverAuthType authPayload = DataStore.serverPassword @@ -82,10 +82,6 @@ class HysteriaSettingsActivity : ProfileSettingsActivity() { setOnBindEditTextListener(EditTextPreferenceModifiers.Number) } - findPreference(Key.SERVER_PORT)!!.apply { - setOnBindEditTextListener(EditTextPreferenceModifiers.Port) - } - findPreference(Key.SERVER_PASSWORD)!!.apply { summaryProvider = PasswordSummaryProvider } diff --git a/app/src/main/java/io/nekohasekai/sagernet/ui/profile/TuicSettingsActivity.kt b/app/src/main/java/io/nekohasekai/sagernet/ui/profile/TuicSettingsActivity.kt index c94a4a6..461a043 100644 --- a/app/src/main/java/io/nekohasekai/sagernet/ui/profile/TuicSettingsActivity.kt +++ b/app/src/main/java/io/nekohasekai/sagernet/ui/profile/TuicSettingsActivity.kt @@ -60,16 +60,12 @@ class TuicSettingsActivity : ProfileSettingsActivity() { uuid = DataStore.serverUsername } - private lateinit var editConfigPreference: EditConfigPreference - override fun PreferenceFragmentCompat.createPreferences( savedInstanceState: Bundle?, rootKey: String?, ) { addPreferencesFromResource(R.xml.tuic_preferences) - editConfigPreference = findPreference(Key.SERVER_CONFIG)!! - val uuid = findPreference(Key.SERVER_USERNAME)!! val mtu = findPreference(Key.SERVER_MTU)!! val fastConnect = findPreference(Key.SERVER_FAST_CONNECT)!! @@ -103,12 +99,4 @@ class TuicSettingsActivity : ProfileSettingsActivity() { } } - override fun onResume() { - super.onResume() - - if (::editConfigPreference.isInitialized) { - editConfigPreference.notifyChanged() - } - } - } \ No newline at end of file diff --git a/app/src/main/java/moe/matsuri/nb4a/SingBoxOptions.java b/app/src/main/java/moe/matsuri/nb4a/SingBoxOptions.java index f9912eb..f626d8d 100644 --- a/app/src/main/java/moe/matsuri/nb4a/SingBoxOptions.java +++ b/app/src/main/java/moe/matsuri/nb4a/SingBoxOptions.java @@ -432,6 +432,10 @@ public class SingBoxOptions { public OutboundTLSOptions tls; + public String hop_ports; + + public Integer hop_interval; + } @@ -469,6 +473,8 @@ public class SingBoxOptions { // Generate note: option type: public VLESSInboundOptions VLESSOptions; + // Generate note: option type: public TUICInboundOptions TUICOptions; + } public static class InboundOptions extends SingBoxOption { @@ -637,6 +643,8 @@ public class SingBoxOptions { // Generate note: option type: public VLESSOutboundOptions VLESSOptions; + // Generate note: option type: public TUICOutboundOptions TUICOptions; + // Generate note: option type: public SelectorOutboundOptions SelectorOptions; // Generate note: option type: public URLTestOutboundOptions URLTestOptions; @@ -1936,6 +1944,120 @@ public class SingBoxOptions { } + public static class TUICInboundOptions extends SingBoxOption { + + // Generate note: nested type ListenOptions + public String listen; + + public Integer listen_port; + + public Boolean tcp_fast_open; + + public Boolean udp_fragment; + + // Generate note: option type: public Boolean UDPFragmentDefault; + + public Long udp_timeout; + + public Boolean proxy_protocol; + + public Boolean proxy_protocol_accept_no_header; + + public String detour; + + // Generate note: nested type InboundOptions + public Boolean sniff; + + public Boolean sniff_override_destination; + + public Long sniff_timeout; + + public String domain_strategy; + + // End of public InboundOptions ; + + // End of public ListenOptions ; + + public List users; + + public String congestion_control; + + public Long auth_timeout; + + public Boolean zero_rtt_handshake; + + public Long heartbeat; + + public InboundTLSOptions tls; + + } + + public static class TUICUser extends SingBoxOption { + + public String name; + + public String uuid; + + public String password; + + } + + public static class TUICOutboundOptions extends SingBoxOption { + + // Generate note: nested type DialerOptions + public String detour; + + public String bind_interface; + + public String inet4_bind_address; + + public String inet6_bind_address; + + public String protect_path; + + public Integer routing_mark; + + public Boolean reuse_addr; + + public Long connect_timeout; + + public Boolean tcp_fast_open; + + public Boolean udp_fragment; + + // Generate note: option type: public Boolean UDPFragmentDefault; + + public String domain_strategy; + + public Long fallback_delay; + + // End of public DialerOptions ; + + // Generate note: nested type ServerOptions + public String server; + + public Integer server_port; + + // End of public ServerOptions ; + + public String uuid; + + public String password; + + public String congestion_control; + + public String udp_relay_mode; + + public Boolean zero_rtt_handshake; + + public Long heartbeat; + + public String network; + + public OutboundTLSOptions tls; + + } + public static class TunInboundOptions extends SingBoxOption { public String interface_name; @@ -3023,6 +3145,53 @@ public class SingBoxOptions { } + public static class Inbound_TUICOptions extends Inbound { + + // Generate note: nested type ListenOptions + public String listen; + + public Integer listen_port; + + public Boolean tcp_fast_open; + + public Boolean udp_fragment; + + + public Long udp_timeout; + + public Boolean proxy_protocol; + + public Boolean proxy_protocol_accept_no_header; + + public String detour; + + // Generate note: nested type InboundOptions + public Boolean sniff; + + public Boolean sniff_override_destination; + + public Long sniff_timeout; + + public String domain_strategy; + + // End of public InboundOptions ; + + // End of public ListenOptions ; + + public List users; + + public String congestion_control; + + public Long auth_timeout; + + public Boolean zero_rtt_handshake; + + public Long heartbeat; + + public InboundTLSOptions tls; + + } + public static class Outbound_DirectOptions extends Outbound { // Generate note: nested type DialerOptions @@ -3445,6 +3614,10 @@ public class SingBoxOptions { public OutboundTLSOptions tls; + public String hop_ports; + + public Integer hop_interval; + } public static class Outbound_TorOptions extends Outbound { @@ -3695,6 +3868,61 @@ public class SingBoxOptions { } + public static class Outbound_TUICOptions extends Outbound { + + // Generate note: nested type DialerOptions + public String detour; + + public String bind_interface; + + public String inet4_bind_address; + + public String inet6_bind_address; + + public String protect_path; + + public Integer routing_mark; + + public Boolean reuse_addr; + + public Long connect_timeout; + + public Boolean tcp_fast_open; + + public Boolean udp_fragment; + + + public String domain_strategy; + + public Long fallback_delay; + + // End of public DialerOptions ; + + // Generate note: nested type ServerOptions + public String server; + + public Integer server_port; + + // End of public ServerOptions ; + + public String uuid; + + public String password; + + public String congestion_control; + + public String udp_relay_mode; + + public Boolean zero_rtt_handshake; + + public Long heartbeat; + + public String network; + + public OutboundTLSOptions tls; + + } + public static class Outbound_SelectorOptions extends Outbound { public List outbounds; diff --git a/app/src/main/res/xml/hysteria_preferences.xml b/app/src/main/res/xml/hysteria_preferences.xml index a968a9c..9b5e338 100644 --- a/app/src/main/res/xml/hysteria_preferences.xml +++ b/app/src/main/res/xml/hysteria_preferences.xml @@ -15,7 +15,7 @@ app:useSimpleSummaryProvider="true" /> - \ No newline at end of file