mirror of
https://github.com/2dust/v2rayNG.git
synced 2026-10-29 14:39:25 +00:00
Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
aa4b05503a | ||
|
|
7179f0838f | ||
|
|
0d1c57000f | ||
|
|
40b8706ccd | ||
|
|
0f961c54c8 | ||
|
|
1b78a510f2 |
No files matched your search
@@ -13,8 +13,8 @@ android {
|
||||
applicationId = "com.v2ray.ang"
|
||||
minSdk = 24
|
||||
targetSdk = 37
|
||||
versionCode = 753
|
||||
versionName = "2.3.13"
|
||||
versionCode = 754
|
||||
versionName = "2.3.14"
|
||||
|
||||
val abiFilterList = (properties["ABI_FILTERS"] as? String)?.split(';')
|
||||
splits {
|
||||
|
||||
@@ -23,7 +23,7 @@ object Hysteria2Fmt : FmtBase() {
|
||||
val uri = URI(Utils.fixIllegalUrl(str))
|
||||
config.remarks = Utils.decodeURIComponent(uri.fragment.orEmpty()).let { it.ifEmpty { "none" } }
|
||||
config.server = uri.idnHost
|
||||
config.serverPort = uri.port.toString()
|
||||
config.serverPort = (if (uri.port == -1) AppConfig.DEFAULT_PORT else uri.port).toString()
|
||||
config.password = uri.userInfo
|
||||
config.security = AppConfig.TLS
|
||||
config.network = NetworkType.HYSTERIA.type
|
||||
|
||||
@@ -126,7 +126,7 @@ object RootProxyManager {
|
||||
val lanShare = forceLanShare || MmkvManager.decodeSettingsBool(AppConfig.PREF_ROOT_LAN_SHARING)
|
||||
val corePid = Process.myPid()
|
||||
|
||||
val config = buildHevConfig(socksUsername, socksPassword, port, ipv6)
|
||||
val config = buildHevConfig(socksUsername, socksPassword, port, ipv6, SettingsManager.getVpnMtu(), lanShare)
|
||||
if (!writeHevConfig(cfgFile, config)) {
|
||||
return null
|
||||
}
|
||||
@@ -209,14 +209,28 @@ object RootProxyManager {
|
||||
* tun address when IPv6 is enabled; whether v6 actually flows in is decided separately by
|
||||
* the v6 route into [TABLE].
|
||||
*/
|
||||
private fun buildHevConfig(socksUsername: String?, socksPassword: String?, socksPort: Int, ipv6: Boolean): String {
|
||||
internal fun buildHevConfig(
|
||||
socksUsername: String?,
|
||||
socksPassword: String?,
|
||||
socksPort: Int,
|
||||
ipv6: Boolean,
|
||||
mtu: Int,
|
||||
lanSharing: Boolean,
|
||||
): String {
|
||||
val v4 = AppConfig.ROOT_TUN_ADDR_V4.substringBefore("/")
|
||||
val v6 = AppConfig.ROOT_TUN_ADDR_V6.substringBefore("/")
|
||||
return buildString {
|
||||
appendLine("tunnel:")
|
||||
appendLine(" name: '$TUN'")
|
||||
appendLine(" mtu: ${SettingsManager.getVpnMtu()}")
|
||||
appendLine(" mtu: $mtu")
|
||||
appendLine(" multi-queue: true")
|
||||
if (lanSharing) {
|
||||
// VNET setup or TCP-GSO EINVAL on Android can leave IPv6 packets above the LAN MTU.
|
||||
// Remove when both fallback forwarding tests pass with jumbo and TSO enabled.
|
||||
appendLine(" offload:")
|
||||
appendLine(" jumbo: false")
|
||||
if (ipv6) appendLine(" tso: false")
|
||||
}
|
||||
appendLine(" ipv4: '$v4'")
|
||||
if (ipv6) appendLine(" ipv6: '$v6'")
|
||||
appendLine("socks5:")
|
||||
|
||||
@@ -561,7 +561,8 @@
|
||||
<string name="connection_test_empty_message">ətraflı məlumat yoxdur</string>
|
||||
<string name="value_unknown">naməlum</string>
|
||||
<string name="sub_info_open_support">Dəstək linkini aç</string>
|
||||
<string name="sub_info_open_page">Abunəlik məlumat səhifəsini aç</string>
|
||||
<string name="sub_info_open_page">Abunəlik səhifəsini aç</string>
|
||||
<string name="sub_info_traffic" translatable="false">%1$s / %2$s</string>
|
||||
<string name="sub_info_unlimited">Limitsiz</string>
|
||||
|
||||
</resources>
|
||||
@@ -0,0 +1,89 @@
|
||||
package com.v2ray.ang.fmt
|
||||
|
||||
import com.v2ray.ang.AppConfig
|
||||
import org.junit.jupiter.api.Assertions.assertEquals
|
||||
import org.junit.jupiter.api.Test
|
||||
import java.net.URI
|
||||
|
||||
class Hysteria2FmtTest {
|
||||
|
||||
@Test
|
||||
fun hysteria2WithoutPortUses443() {
|
||||
val profile = Hysteria2Fmt.parse("hysteria2://test@example.com/")
|
||||
|
||||
assertEquals("example.com", profile.server)
|
||||
assertEquals("443", profile.serverPort)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun hy2WithoutPortUses443() {
|
||||
val profile = Hysteria2Fmt.parse("hy2://test@example.com/")
|
||||
|
||||
assertEquals("example.com", profile.server)
|
||||
assertEquals("443", profile.serverPort)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun uriWithoutCredentialsUses443() {
|
||||
val profile = Hysteria2Fmt.parse("hysteria2://example.com/")
|
||||
|
||||
assertEquals("example.com", profile.server)
|
||||
assertEquals("443", profile.serverPort)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun omittedPortPreservesTlsParameters() {
|
||||
val profile = Hysteria2Fmt.parse(
|
||||
"hy2://test@example.com/?sni=example.org&insecure=0&pinSHA256=test-pin#example"
|
||||
)
|
||||
|
||||
assertEquals("test", profile.password)
|
||||
assertEquals("example", profile.remarks)
|
||||
assertEquals(AppConfig.TLS, profile.security)
|
||||
assertEquals("example.org", profile.sni)
|
||||
assertEquals(false, profile.insecure)
|
||||
assertEquals("test-pin", profile.pinnedCA256)
|
||||
assertEquals("443", profile.serverPort)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun ipv6WithoutPortUses443() {
|
||||
val profile = Hysteria2Fmt.parse("hysteria2://test@[2001:db8::1]/")
|
||||
|
||||
assertEquals("2001:db8::1", profile.server)
|
||||
assertEquals("443", profile.serverPort)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun explicitPortsArePreserved() {
|
||||
for (scheme in listOf("hysteria2", "hy2")) {
|
||||
// Port range validation is separate from choosing a missing-port default.
|
||||
for (port in listOf(0, 443, 8443, 65535, 65536)) {
|
||||
val profile = Hysteria2Fmt.parse("$scheme://test@example.com:$port/")
|
||||
|
||||
assertEquals("example.com", profile.server)
|
||||
assertEquals(port.toString(), profile.serverPort)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
fun nonnumericPortDoesNotAcquireAHost() {
|
||||
val profile = Hysteria2Fmt.parse("hysteria2://test@example.com:invalid/")
|
||||
|
||||
assertEquals("", profile.server)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun defaultPortSurvivesUriRoundTrip() {
|
||||
val profile = Hysteria2Fmt.parse("hy2://test@example.com/?sni=example.org")
|
||||
val exported = "hysteria2://${Hysteria2Fmt.toUri(profile)}"
|
||||
val reparsed = Hysteria2Fmt.parse(exported)
|
||||
|
||||
assertEquals(443, URI(exported).port)
|
||||
assertEquals("443", reparsed.serverPort)
|
||||
assertEquals(profile.server, reparsed.server)
|
||||
assertEquals(profile.password, reparsed.password)
|
||||
assertEquals(profile.sni, reparsed.sni)
|
||||
}
|
||||
}
|
||||
@@ -1,10 +1,43 @@
|
||||
package com.v2ray.ang.root
|
||||
|
||||
import org.junit.jupiter.api.Assertions.assertEquals
|
||||
import org.junit.jupiter.api.Assertions.assertFalse
|
||||
import org.junit.jupiter.api.Assertions.assertTrue
|
||||
import org.junit.jupiter.api.Test
|
||||
|
||||
class RootProxyManagerTest {
|
||||
|
||||
@Test
|
||||
fun `IPv6 LAN forwarding disables jumbo and TSO`() {
|
||||
val config = RootProxyManager.buildHevConfig(null, null, 10808, true, 1500, true)
|
||||
|
||||
assertTrue(config.contains(" offload:\n jumbo: false\n"))
|
||||
assertTrue(config.contains(" multi-queue: true\n"))
|
||||
assertTrue(config.contains(" tso: false\n"))
|
||||
assertFalse(config.contains("uso:"))
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `local root keeps default offloads and configured MTU`() {
|
||||
val config = RootProxyManager.buildHevConfig(null, null, 10808, true, 8500, false)
|
||||
|
||||
assertFalse(config.contains("offload:"))
|
||||
assertTrue(config.contains(" mtu: 8500\n"))
|
||||
assertTrue(config.contains(" ipv6:"))
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `LAN offload guard preserves IPv4 only and quoted authentication`() {
|
||||
val config = RootProxyManager.buildHevConfig("user'name", "pa'ss", 10809, false, 1500, true)
|
||||
|
||||
assertTrue(config.contains(" offload:\n jumbo: false\n"))
|
||||
assertFalse(config.contains("tso:"))
|
||||
assertFalse(config.contains(" ipv6:"))
|
||||
assertTrue(config.contains(" port: 10809\n"))
|
||||
assertTrue(config.contains(" username: 'user''name'\n"))
|
||||
assertTrue(config.contains(" password: 'pa''ss'\n"))
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `single quotes are escaped in YAML scalars`() {
|
||||
assertEquals("'user''name'", "user'name".toSingleQuotedYamlScalar())
|
||||
|
||||
@@ -11,7 +11,7 @@ activity = "1.13.0"
|
||||
appcompat = "1.8.0"
|
||||
mmkvStatic = "1.3.17"
|
||||
gson = "2.14.0"
|
||||
okhttp = "5.5.0"
|
||||
okhttp = "5.5.1"
|
||||
kotlinxCoroutines = "1.11.0"
|
||||
core = "3.5.4"
|
||||
workRuntimeKtx = "2.12.0"
|
||||
|
||||
+1
-1
Submodule hev-socks5-tunnel updated: 107a5083cb...c5584feca8.
Reference in new issue
Block a user