diff --git a/.circleci/config.yml b/.circleci/config.yml
index 1c9c25dba1..2465703dd9 100644
--- a/.circleci/config.yml
+++ b/.circleci/config.yml
@@ -3,7 +3,7 @@ jobs:
build:
working_directory: ~/code
docker:
- - image: circleci/android:api-29-ndk
+ - image: shadowsocks/android-ndk-go:v1.0
environment:
GRADLE_OPTS: -Dorg.gradle.workers.max=1 -Dorg.gradle.daemon=false -Dkotlin.compiler.execution.strategy="in-process"
steps:
@@ -13,7 +13,7 @@ jobs:
key: jars-{{ checksum "build.gradle" }}
- run:
name: Run Build and Tests
- command: ./gradlew assembleDebug check
+ command: ./gradlew assembleDebug check -PCARGO_PROFILE=debug
- save_cache:
paths:
- ~/.gradle
diff --git a/.gitmodules b/.gitmodules
index b9e2447a19..954b512529 100644
--- a/.gitmodules
+++ b/.gitmodules
@@ -1,6 +1,3 @@
-[submodule "core/src/main/jni/shadowsocks-libev"]
- path = core/src/main/jni/shadowsocks-libev
- url = https://github.com/shadowsocks/shadowsocks-libev
[submodule "core/src/main/jni/badvpn"]
path = core/src/main/jni/badvpn
url = https://github.com/shadowsocks/badvpn.git
@@ -17,19 +14,6 @@
path = core/src/main/jni/redsocks
url = https://github.com/shadowsocks/redsocks.git
branch = shadowsocks-android
-[submodule "core/src/main/jni/mbedtls"]
- path = core/src/main/jni/mbedtls
- url = https://github.com/ARMmbed/mbedtls
-[submodule "core/src/main/jni/pcre"]
- path = core/src/main/jni/pcre
- url = https://android.googlesource.com/platform/external/pcre
-[submodule "core/src/main/jni/libsodium"]
- path = core/src/main/jni/libsodium
- url = https://github.com/jedisct1/libsodium.git
- branch = stable
-[submodule "core/src/main/jni/libev"]
- path = core/src/main/jni/libev
- url = https://git.lighttpd.net/libev.git
-[submodule "core/src/main/jni/re2"]
- path = core/src/main/jni/re2
- url = https://github.com/google/re2.git
+[submodule "core/src/main/rust/shadowsocks-rust"]
+ path = core/src/main/rust/shadowsocks-rust
+ url = https://github.com/madeye/shadowsocks-rust
diff --git a/README.md b/README.md
index 314e956a1c..28de976b1c 100644
--- a/README.md
+++ b/README.md
@@ -45,14 +45,11 @@ If you are interested in contributing or getting involved with this project, ple
diff --git a/build.gradle b/build.gradle
index 79f97f2647..b21f490fb8 100644
--- a/build.gradle
+++ b/build.gradle
@@ -5,12 +5,12 @@ apply plugin: 'com.github.ben-manes.versions'
buildscript {
ext {
javaVersion = JavaVersion.VERSION_1_8
- kotlinVersion = '1.3.61'
+ kotlinVersion = '1.3.72'
minSdkVersion = 21
sdkVersion = 29
compileSdkVersion = 29
lifecycleVersion = '2.2.0'
- desugarLibsVersion = '1.0.4'
+ desugarLibsVersion = '1.0.5'
junitVersion = '4.13'
androidTestVersion = '1.2.0'
androidEspressoVersion = '3.2.0'
@@ -25,14 +25,18 @@ buildscript {
maven {
url 'https://maven.fabric.io/public'
}
+ maven {
+ url "https://plugins.gradle.org/m2/"
+ }
}
dependencies {
- classpath 'com.android.tools.build:gradle:4.0.0-alpha09'
- classpath 'com.github.ben-manes:gradle-versions-plugin:0.27.0'
- classpath 'com.google.android.gms:oss-licenses-plugin:0.9.5'
+ classpath 'com.android.tools.build:gradle:4.0.0-beta04'
+ classpath 'com.github.ben-manes:gradle-versions-plugin:0.28.0'
+ classpath 'com.google.android.gms:oss-licenses-plugin:0.10.2'
classpath 'com.google.gms:google-services:4.3.3'
- classpath 'com.vanniktech:gradle-maven-publish-plugin:0.9.0'
+ classpath 'com.vanniktech:gradle-maven-publish-plugin:0.11.1'
+ classpath 'gradle.plugin.org.mozilla.rust-android-gradle:plugin:0.8.3'
classpath 'io.fabric.tools:gradle:1.31.2'
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlinVersion"
}
diff --git a/core/build.gradle b/core/build.gradle
index b15f0542dd..72a927314d 100644
--- a/core/build.gradle
+++ b/core/build.gradle
@@ -2,6 +2,7 @@ apply plugin: 'com.android.library'
apply plugin: 'kotlin-android'
apply plugin: 'kotlin-android-extensions'
apply plugin: 'kotlin-kapt'
+apply plugin: 'org.mozilla.rust-android-gradle.rust-android'
android {
compileSdkVersion rootProject.compileSdkVersion
@@ -50,27 +51,43 @@ androidExtensions {
experimental = true
}
-def coroutinesVersion = '1.3.3'
-def roomVersion = '2.2.3'
-def workVersion = '2.3.1'
+cargo {
+ module = 'src/main/rust/shadowsocks-rust'
+ libname = 'sslocal'
+ targets = ['arm', 'arm64', 'x86', 'x86_64']
+ profile = findProperty('CARGO_PROFILE') ?: 'release'
+ targetIncludes = ["lib${libname}.so"]
+ extraCargoBuildArguments = ['--bin', 'sslocal']
+ features {
+ noDefaultBut "sodium", "rc4", "aes-cfb", "aes-ctr", "camellia-cfb", "openssl-vendored", "local-flow-stat", "local-dns-relay"
+ }
+ exec { spec, toolchain ->
+ spec.environment("RUSTFLAGS", "-C lto=no -C link-arg=-o -C link-arg=target/${toolchain.target}/$profile/lib${libname}.so")
+ }
+}
+
+preBuild.dependsOn "cargoBuild"
+
+def coroutinesVersion = '1.3.5'
+def roomVersion = '2.2.5'
+def workVersion = '2.3.4'
dependencies {
api project(':plugin')
- api 'androidx.fragment:fragment-ktx:1.2.1'
+ api 'androidx.fragment:fragment-ktx:1.2.4'
api "androidx.lifecycle:lifecycle-common-java8:$lifecycleVersion"
api "androidx.lifecycle:lifecycle-livedata-core-ktx:$lifecycleVersion"
- api 'androidx.preference:preference:1.1.0'
+ api 'androidx.preference:preference:1.1.1'
api "androidx.room:room-runtime:$roomVersion"
api "androidx.work:work-runtime-ktx:$workVersion"
api "androidx.work:work-gcm:$workVersion"
api 'com.crashlytics.sdk.android:crashlytics:2.10.1'
api 'com.google.android.gms:play-services-oss-licenses:17.0.0'
api 'com.google.code.gson:gson:2.8.6'
- api 'com.google.firebase:firebase-analytics:17.2.2'
- api 'com.google.firebase:firebase-config:19.1.1'
- api 'dnsjava:dnsjava:2.1.9'
+ api 'com.google.firebase:firebase-analytics:17.3.0'
+ api 'com.google.firebase:firebase-config:19.1.3'
+ api 'dnsjava:dnsjava:3.0.2'
api "org.jetbrains.kotlinx:kotlinx-coroutines-android:$coroutinesVersion"
api "org.jetbrains.kotlinx:kotlinx-coroutines-play-services:$coroutinesVersion"
- api 'org.connectbot.jsocks:jsocks:1.0.0'
coreLibraryDesugaring "com.android.tools:desugar_jdk_libs:$desugarLibsVersion"
kapt "androidx.room:room-compiler:$roomVersion"
testImplementation "junit:junit:$junitVersion"
diff --git a/core/proguard-rules.pro b/core/proguard-rules.pro
index f2c7cde94e..97f6f95aaa 100644
--- a/core/proguard-rules.pro
+++ b/core/proguard-rules.pro
@@ -20,8 +20,3 @@
# If you keep the line number information, uncomment this to
# hide the original source file name.
#-renamesourcefileattribute SourceFile
-
-# https://issuetracker.google.com/issues/147972078#comment4
--keepclasseswithmembers class * extends androidx.lifecycle.ViewModel {
- ();
-}
diff --git a/core/src/androidTest/java/com/github/shadowsocks/acl/AclMatcherTest.kt b/core/src/androidTest/java/com/github/shadowsocks/acl/AclMatcherTest.kt
deleted file mode 100644
index 003c38c47d..0000000000
--- a/core/src/androidTest/java/com/github/shadowsocks/acl/AclMatcherTest.kt
+++ /dev/null
@@ -1,85 +0,0 @@
-/*******************************************************************************
- * *
- * Copyright (C) 2020 by Max Lv *
- * Copyright (C) 2020 by Mygod Studio *
- * *
- * 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 com.github.shadowsocks.acl
-
-import androidx.test.core.app.ApplicationProvider
-import com.github.shadowsocks.Core
-import com.github.shadowsocks.utils.parseNumericAddress
-import kotlinx.coroutines.runBlocking
-import org.junit.Assert
-import org.junit.BeforeClass
-import org.junit.Test
-
-class AclMatcherTest {
- companion object {
- @BeforeClass
- @JvmStatic
- fun setup() {
- Core.app = ApplicationProvider.getApplicationContext()
- }
- }
-
- @Test
- fun emptyFile() {
- runBlocking {
- AclMatcher().apply {
- init(AclTest.BYPASS_BASE.reader())
- Assert.assertTrue(shouldBypassIpv4(ByteArray(4)))
- Assert.assertTrue(shouldBypassIpv6(ByteArray(16)))
- Assert.assertNull(shouldBypass("www.google.com"))
- }
- }
- }
-
- @Test
- fun basic() {
- runBlocking {
- AclMatcher().apply {
- init(AclTest.INPUT1.reader())
- Assert.assertTrue(shouldBypassIpv4("0.1.2.3".parseNumericAddress()!!.address))
- Assert.assertFalse(shouldBypassIpv4("1.0.1.2".parseNumericAddress()!!.address))
- Assert.assertTrue(shouldBypassIpv4("1.0.3.2".parseNumericAddress()!!.address))
- Assert.assertTrue(shouldBypassIpv6("::".parseNumericAddress()!!.address))
- Assert.assertFalse(shouldBypassIpv6("2020::2020".parseNumericAddress()!!.address))
- Assert.assertTrue(shouldBypassIpv6("fe80::2020".parseNumericAddress()!!.address))
- Assert.assertTrue(shouldBypass("4tern.com") == false)
- Assert.assertTrue(shouldBypass("www.4tern.com") == false)
- Assert.assertNull(shouldBypass("www.google.com"))
- }
- }
- }
-
- @Test
- fun bypassList() {
- runBlocking {
- AclMatcher().apply {
- init(AclTest.INPUT2.reader())
- Assert.assertFalse(shouldBypassIpv4("0.1.2.3".parseNumericAddress()!!.address))
- Assert.assertTrue(shouldBypassIpv4("10.0.1.2".parseNumericAddress()!!.address))
- Assert.assertTrue(shouldBypassIpv4("10.10.1.2".parseNumericAddress()!!.address))
- Assert.assertFalse(shouldBypassIpv4("11.0.1.2".parseNumericAddress()!!.address))
- Assert.assertTrue(shouldBypass("chrome.com") == true)
- Assert.assertTrue(shouldBypass("about.google") == false)
- Assert.assertNull(shouldBypass("www.google.com"))
- }
- }
- }
-}
diff --git a/core/src/main/AndroidManifest.xml b/core/src/main/AndroidManifest.xml
index 6a1cdc3006..a1d1bddea0 100644
--- a/core/src/main/AndroidManifest.xml
+++ b/core/src/main/AndroidManifest.xml
@@ -103,7 +103,6 @@
*
- * Copyright (C) 2019 by Mygod Studio *
- * *
- * 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 com.github.shadowsocks.acl
-
-import com.github.shadowsocks.Core
-import com.github.shadowsocks.net.Subnet
-import java.io.Reader
-import java.net.Inet4Address
-import java.net.Inet6Address
-
-class AclMatcher : AutoCloseable {
- companion object {
- init {
- System.loadLibrary("jni-helper")
- }
-
- @JvmStatic private external fun init(): Long
- @JvmStatic private external fun close(handle: Long)
-
- @JvmStatic private external fun addBypassDomain(handle: Long, regex: String): Boolean
- @JvmStatic private external fun addProxyDomain(handle: Long, regex: String): Boolean
- @JvmStatic private external fun build(handle: Long, memoryLimit: Long): String?
- @JvmStatic private external fun matchHost(handle: Long, host: String): Int
- }
-
- class Re2Exception(message: String) : IllegalArgumentException(message)
-
- private var handle = 0L
- override fun close() {
- if (handle != 0L) {
- close(handle)
- handle = 0L
- }
- }
-
- private var subnetsIpv4 = emptyList()
- private var subnetsIpv6 = emptyList()
- private var bypass = false
-
- suspend fun init(id: String) = init(Acl.getFile(id).bufferedReader())
- suspend fun init(reader: Reader) {
- fun Sequence.dedup() = sequence {
- val iterator = map { it.toImmutable() }.sortedWith(Subnet.Immutable).iterator()
- var current: Subnet.Immutable? = null
- while (iterator.hasNext()) {
- val next = iterator.next()
- if (current?.matches(next) == true) continue
- yield(next)
- current = next
- }
- }.toList()
- check(handle == 0L)
- handle = init()
- try {
- val (bypass, subnets) = Acl.parse(reader, {
- check(addBypassDomain(handle, it))
- }, {
- check(addProxyDomain(handle, it))
- })
- build(handle, if (Core.activity.isLowRamDevice) 8 shl 20 else 64 shl 20)?.also { throw Re2Exception(it) }
- subnetsIpv4 = subnets.asSequence().filter { it.address is Inet4Address }.dedup()
- subnetsIpv6 = subnets.asSequence().filter { it.address is Inet6Address }.dedup()
- this.bypass = bypass
- } catch (e: Exception) {
- close()
- throw e
- }
- }
-
- private fun quickMatches(subnets: List, ip: ByteArray): Boolean {
- val i = subnets.binarySearch(Subnet.Immutable(ip), Subnet.Immutable)
- return i >= 0 || i < -1 && subnets[-i - 2].matches(ip)
- }
-
- fun shouldBypassIpv4(ip: ByteArray) = bypass xor quickMatches(subnetsIpv4, ip)
- fun shouldBypassIpv6(ip: ByteArray) = bypass xor quickMatches(subnetsIpv6, ip)
- fun shouldBypass(host: String) = when (val e = matchHost(handle, host)) {
- 0 -> null
- 1 -> true
- 2 -> false
- else -> error("matchHost -> $e")
- }
-}
diff --git a/core/src/main/java/com/github/shadowsocks/bg/BaseService.kt b/core/src/main/java/com/github/shadowsocks/bg/BaseService.kt
index e46b56b217..d590386d4f 100644
--- a/core/src/main/java/com/github/shadowsocks/bg/BaseService.kt
+++ b/core/src/main/java/com/github/shadowsocks/bg/BaseService.kt
@@ -37,6 +37,7 @@ import com.github.shadowsocks.aidl.IShadowsocksService
import com.github.shadowsocks.aidl.IShadowsocksServiceCallback
import com.github.shadowsocks.aidl.TrafficStats
import com.github.shadowsocks.core.R
+import com.github.shadowsocks.net.DnsResolverCompat
import com.github.shadowsocks.net.HostsFile
import com.github.shadowsocks.preference.DataStore
import com.github.shadowsocks.utils.*
@@ -46,7 +47,6 @@ import java.io.File
import java.io.IOException
import java.net.URL
import java.net.UnknownHostException
-import java.util.*
/**
* This object uses WeakMap to simulate the effects of multi-inheritance.
@@ -74,6 +74,7 @@ object BaseService {
var processes: GuardedProcessPool? = null
var proxy: ProxyInstance? = null
var udpFallback: ProxyInstance? = null
+ var localDns: LocalDnsWorker? = null
var notification: ServiceNotification? = null
val closeReceiver = broadcastReceiver { _, intent ->
@@ -232,7 +233,7 @@ object BaseService {
}
}
- fun buildAdditionalArguments(cmd: ArrayList): ArrayList = cmd
+ val isVpnService get() = false
suspend fun startProcesses(hosts: HostsFile) {
val configRoot = (if (Build.VERSION.SDK_INT < 24 || app.getSystemService()
@@ -241,12 +242,13 @@ object BaseService {
data.proxy!!.start(this,
File(Core.deviceStorage.noBackupFilesDir, "stat_main"),
File(configRoot, CONFIG_FILE),
- if (udpFallback == null) "-u" else null)
+ if (udpFallback == null) "-U" else null)
check(udpFallback?.plugin == null) { "UDP fallback cannot have plugins" }
udpFallback?.start(this,
File(Core.deviceStorage.noBackupFilesDir, "stat_udp"),
File(configRoot, CONFIG_FILE_UDP),
- "-U")
+ "-u", false)
+ data.localDns = LocalDnsWorker(this::rawResolver).apply { start() }
}
fun startRunner() {
@@ -260,6 +262,8 @@ object BaseService {
close(scope)
data.processes = null
}
+ data.localDns?.shutdown(scope)
+ data.localDns = null
}
fun stopRunner(restart: Boolean = false, msg: String? = null) {
@@ -309,6 +313,7 @@ object BaseService {
suspend fun preInit() { }
suspend fun getActiveNetwork() = if (Build.VERSION.SDK_INT >= 23) Core.connectivity.activeNetwork else null
suspend fun resolver(host: String) = DnsResolverCompat.resolveOnActiveNetwork(host)
+ suspend fun rawResolver(query: ByteArray) = DnsResolverCompat.resolveRawOnActiveNetwork(query)
suspend fun openConnection(url: URL) = url.openConnection()
fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int {
diff --git a/core/src/main/java/com/github/shadowsocks/bg/Executable.kt b/core/src/main/java/com/github/shadowsocks/bg/Executable.kt
index 01c97419b4..0e6136d6c2 100644
--- a/core/src/main/java/com/github/shadowsocks/bg/Executable.kt
+++ b/core/src/main/java/com/github/shadowsocks/bg/Executable.kt
@@ -31,7 +31,7 @@ import java.io.IOException
object Executable {
const val REDSOCKS = "libredsocks.so"
- const val SS_LOCAL = "libss-local.so"
+ const val SS_LOCAL = "libsslocal.so"
const val TUN2SOCKS = "libtun2socks.so"
private val EXECUTABLES = setOf(SS_LOCAL, REDSOCKS, TUN2SOCKS)
diff --git a/core/src/main/java/com/github/shadowsocks/bg/LocalDnsService.kt b/core/src/main/java/com/github/shadowsocks/bg/LocalDnsService.kt
deleted file mode 100644
index f5979c5e71..0000000000
--- a/core/src/main/java/com/github/shadowsocks/bg/LocalDnsService.kt
+++ /dev/null
@@ -1,64 +0,0 @@
-/*******************************************************************************
- * *
- * Copyright (C) 2017 by Max Lv *
- * Copyright (C) 2017 by Mygod Studio *
- * *
- * 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 com.github.shadowsocks.bg
-
-import com.github.shadowsocks.acl.Acl
-import com.github.shadowsocks.acl.AclMatcher
-import com.github.shadowsocks.net.HostsFile
-import com.github.shadowsocks.net.LocalDnsServer
-import com.github.shadowsocks.net.Socks5Endpoint
-import com.github.shadowsocks.preference.DataStore
-import kotlinx.coroutines.CoroutineScope
-import java.net.InetSocketAddress
-import java.net.URI
-import java.net.URISyntaxException
-import java.util.*
-
-object LocalDnsService {
- private val servers = WeakHashMap()
-
- interface Interface : BaseService.Interface {
- override suspend fun startProcesses(hosts: HostsFile) {
- super.startProcesses(hosts)
- val profile = data.proxy!!.profile
- val dns = try {
- URI("dns://${profile.remoteDns}")
- } catch (e: URISyntaxException) {
- throw BaseService.ExpectedExceptionWrapper(e)
- }
- LocalDnsServer(this::resolver,
- Socks5Endpoint(dns.host, if (dns.port < 0) 53 else dns.port),
- DataStore.proxyAddress,
- hosts,
- !profile.udpdns,
- if (profile.route == Acl.ALL) null else object {
- suspend fun createAcl() = AclMatcher().apply { init(profile.route) }
- }::createAcl).also {
- servers[this] = it
- }.start(InetSocketAddress(DataStore.listenAddress, DataStore.portLocalDns))
- }
-
- override fun killProcesses(scope: CoroutineScope) {
- servers.remove(this)?.shutdown(scope)
- super.killProcesses(scope)
- }
- }
-}
diff --git a/core/src/main/java/com/github/shadowsocks/bg/LocalDnsWorker.kt b/core/src/main/java/com/github/shadowsocks/bg/LocalDnsWorker.kt
new file mode 100644
index 0000000000..3c7cd82cbe
--- /dev/null
+++ b/core/src/main/java/com/github/shadowsocks/bg/LocalDnsWorker.kt
@@ -0,0 +1,56 @@
+package com.github.shadowsocks.bg
+
+import android.net.LocalSocket
+import android.util.Log
+import com.crashlytics.android.Crashlytics
+import com.github.shadowsocks.Core
+import com.github.shadowsocks.net.ConcurrentLocalSocketListener
+import com.github.shadowsocks.net.DnsResolverCompat
+import com.github.shadowsocks.utils.printLog
+import kotlinx.coroutines.CancellationException
+import kotlinx.coroutines.CoroutineScope
+import kotlinx.coroutines.TimeoutCancellationException
+import kotlinx.coroutines.launch
+import org.xbill.DNS.Message
+import org.xbill.DNS.Rcode
+import java.io.DataInputStream
+import java.io.DataOutputStream
+import java.io.File
+import java.io.IOException
+
+class LocalDnsWorker(private val resolver: suspend (ByteArray) -> ByteArray) : ConcurrentLocalSocketListener(
+ "LocalDnsThread", File(Core.deviceStorage.noBackupFilesDir, "local_dns_path")), CoroutineScope {
+ override fun acceptInternal(socket: LocalSocket) = error("big no no")
+ override fun accept(socket: LocalSocket) {
+ launch {
+ socket.use {
+ val input = DataInputStream(socket.inputStream)
+ val query = ByteArray(input.readUnsignedShort())
+ input.read(query)
+ try {
+ resolver(query)
+ } catch (e: Exception) {
+ when (e) {
+ is TimeoutCancellationException -> Crashlytics.log(Log.WARN, name, "Resolving timed out")
+ is CancellationException -> { } // ignore
+ is IOException -> Crashlytics.log(Log.WARN, name, e.message)
+ else -> printLog(e)
+ }
+ try {
+ DnsResolverCompat.prepareDnsResponse(Message(query)).apply {
+ header.rcode = Rcode.SERVFAIL
+ }.toWire()
+ } catch (_: IOException) {
+ byteArrayOf() // return empty if cannot parse packet
+ }
+ }?.let { response ->
+ try {
+ val output = DataOutputStream(socket.outputStream)
+ output.writeShort(response.size)
+ output.write(response)
+ } catch (_: IOException) { } // connection early close possibly due to resolving timeout
+ }
+ }
+ }
+ }
+}
diff --git a/core/src/main/java/com/github/shadowsocks/bg/ProxyInstance.kt b/core/src/main/java/com/github/shadowsocks/bg/ProxyInstance.kt
index 488bc8ace4..6d17ad09bb 100644
--- a/core/src/main/java/com/github/shadowsocks/bg/ProxyInstance.kt
+++ b/core/src/main/java/com/github/shadowsocks/bg/ProxyInstance.kt
@@ -26,6 +26,7 @@ import com.github.shadowsocks.Core
import com.github.shadowsocks.acl.Acl
import com.github.shadowsocks.acl.AclSyncer
import com.github.shadowsocks.database.Profile
+import com.github.shadowsocks.net.DnsResolverCompat
import com.github.shadowsocks.net.HostsFile
import com.github.shadowsocks.plugin.PluginConfiguration
import com.github.shadowsocks.plugin.PluginManager
@@ -109,32 +110,40 @@ class ProxyInstance(val profile: Profile, private val route: String = profile.ro
* Sensitive shadowsocks configuration file requires extra protection. It may be stored in encrypted storage or
* device storage, depending on which is currently available.
*/
- fun start(service: BaseService.Interface, stat: File, configFile: File, extraFlag: String? = null) {
+ fun start(service: BaseService.Interface, stat: File, configFile: File, extraFlag: String? = null,
+ dnsRelay: Boolean = true) {
trafficMonitor = TrafficMonitor(stat)
this.configFile = configFile
val config = profile.toJson()
- plugin?.let { (path, opts) -> config.put("plugin", path).put("plugin_opts", opts.toString()) }
+ val vpnFlags = if (service.isVpnService) ";V" else ""
+ plugin?.let { (path, opts) -> config.put("plugin", path).put("plugin_opts", opts.toString() + vpnFlags) }
+ config.put("local_address", DataStore.listenAddress)
+ config.put("local_port", DataStore.portProxy)
configFile.writeText(config.toString())
- val cmd = service.buildAdditionalArguments(arrayListOf(
+ val dns = try {
+ URI("dns://${profile.remoteDns}")
+ } catch (e: URISyntaxException) {
+ throw BaseService.ExpectedExceptionWrapper(e)
+ }
+
+ val cmd = arrayListOf(
File((service as Context).applicationInfo.nativeLibraryDir, Executable.SS_LOCAL).absolutePath,
- "-b", DataStore.listenAddress,
- "-l", DataStore.portProxy.toString(),
- "-t", "600",
- "-S", stat.absolutePath,
- "-c", configFile.absolutePath))
+ "--stat-path", stat.absolutePath,
+ "-c", configFile.absolutePath)
+ if (service.isVpnService) cmd += arrayListOf("--vpn")
if (extraFlag != null) cmd.add(extraFlag)
+ if (dnsRelay) cmd += arrayListOf(
+ "--dns-relay", "${DataStore.listenAddress}:${DataStore.portLocalDns}",
+ "--remote-dns", "${dns.host}:${if (dns.port < 0) 53 else dns.port}")
if (route != Acl.ALL) {
cmd += "--acl"
cmd += Acl.getFile(route).absolutePath
}
- // for UDP profile, it's only going to operate in UDP relay mode-only so this flag has no effect
- if (profile.route == Acl.ALL) cmd += "-D"
-
- if (DataStore.tcpFastOpen) cmd += "--fast-open"
+ // if (DataStore.tcpFastOpen) cmd += "--fast-open"
service.data.processes!!.start(cmd)
}
diff --git a/core/src/main/java/com/github/shadowsocks/bg/TransproxyService.kt b/core/src/main/java/com/github/shadowsocks/bg/TransproxyService.kt
index d3b6ff4325..ff30cf5329 100644
--- a/core/src/main/java/com/github/shadowsocks/bg/TransproxyService.kt
+++ b/core/src/main/java/com/github/shadowsocks/bg/TransproxyService.kt
@@ -27,7 +27,7 @@ import com.github.shadowsocks.net.HostsFile
import com.github.shadowsocks.preference.DataStore
import java.io.File
-class TransproxyService : Service(), LocalDnsService.Interface {
+class TransproxyService : Service(), BaseService.Interface {
override val data = BaseService.Data(this)
override val tag: String get() = "ShadowsocksTransproxyService"
override fun createNotification(profileName: String): ServiceNotification =
@@ -35,7 +35,7 @@ class TransproxyService : Service(), LocalDnsService.Interface {
override fun onBind(intent: Intent) = super.onBind(intent)
override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int =
- super.onStartCommand(intent, flags, startId)
+ super.onStartCommand(intent, flags, startId)
private fun startRedsocksDaemon() {
File(Core.deviceStorage.noBackupFilesDir, "redsocks.conf").writeText("""base {
diff --git a/core/src/main/java/com/github/shadowsocks/bg/VpnService.kt b/core/src/main/java/com/github/shadowsocks/bg/VpnService.kt
index 1b238241f4..b529492668 100644
--- a/core/src/main/java/com/github/shadowsocks/bg/VpnService.kt
+++ b/core/src/main/java/com/github/shadowsocks/bg/VpnService.kt
@@ -34,26 +34,18 @@ import com.github.shadowsocks.Core
import com.github.shadowsocks.VpnRequestActivity
import com.github.shadowsocks.acl.Acl
import com.github.shadowsocks.core.R
-import com.github.shadowsocks.net.ConcurrentLocalSocketListener
-import com.github.shadowsocks.net.DefaultNetworkListener
-import com.github.shadowsocks.net.HostsFile
-import com.github.shadowsocks.net.Subnet
+import com.github.shadowsocks.net.*
import com.github.shadowsocks.preference.DataStore
import com.github.shadowsocks.utils.Key
import com.github.shadowsocks.utils.closeQuietly
import com.github.shadowsocks.utils.int
import com.github.shadowsocks.utils.printLog
-import kotlinx.coroutines.CoroutineScope
-import kotlinx.coroutines.delay
-import kotlinx.coroutines.launch
-import java.io.File
-import java.io.FileDescriptor
-import java.io.IOException
+import kotlinx.coroutines.*
+import java.io.*
import java.net.URL
-import java.util.*
import android.net.VpnService as BaseVpnService
-class VpnService : BaseVpnService(), LocalDnsService.Interface {
+class VpnService : BaseVpnService(), BaseService.Interface {
companion object {
private const val VPN_MTU = 1500
private const val PRIVATE_VLAN4_CLIENT = "172.19.0.1"
@@ -115,7 +107,7 @@ class VpnService : BaseVpnService(), LocalDnsService.Interface {
override fun onBind(intent: Intent) = when (intent.action) {
SERVICE_INTERFACE -> super.onBind(intent)
- else -> super.onBind(intent)
+ else -> super.onBind(intent)
}
override fun onRevoke() = stopRunner()
@@ -134,7 +126,7 @@ class VpnService : BaseVpnService(), LocalDnsService.Interface {
if (DataStore.serviceMode == Key.modeVpn) {
if (prepare(this) != null) {
startActivity(Intent(this, VpnRequestActivity::class.java).addFlags(Intent.FLAG_ACTIVITY_NEW_TASK))
- } else return super.onStartCommand(intent, flags, startId)
+ } else return super.onStartCommand(intent, flags, startId)
}
stopRunner()
return Service.START_NOT_STICKY
@@ -143,6 +135,10 @@ class VpnService : BaseVpnService(), LocalDnsService.Interface {
override suspend fun preInit() = DefaultNetworkListener.start(this) { underlyingNetwork = it }
override suspend fun getActiveNetwork() = DefaultNetworkListener.get()
override suspend fun resolver(host: String) = DnsResolverCompat.resolve(DefaultNetworkListener.get(), host)
+ override suspend fun rawResolver(query: ByteArray) =
+ // no need to listen for network here as this is only used for forwarding local DNS queries.
+ // retries should be attempted by client.
+ DnsResolverCompat.resolveRaw(underlyingNetwork ?: throw IOException("no network"), query)
override suspend fun openConnection(url: URL) = DefaultNetworkListener.get().openConnection(url)
override suspend fun startProcesses(hosts: HostsFile) {
@@ -151,10 +147,7 @@ class VpnService : BaseVpnService(), LocalDnsService.Interface {
sendFd(startVpn())
}
- override fun buildAdditionalArguments(cmd: ArrayList): ArrayList {
- cmd += "-V"
- return cmd
- }
+ override val isVpnService get() = true
private suspend fun startVpn(): FileDescriptor {
val profile = data.proxy!!.profile
diff --git a/core/src/main/java/com/github/shadowsocks/net/ChannelMonitor.kt b/core/src/main/java/com/github/shadowsocks/net/ChannelMonitor.kt
deleted file mode 100644
index fa8d7a989c..0000000000
--- a/core/src/main/java/com/github/shadowsocks/net/ChannelMonitor.kt
+++ /dev/null
@@ -1,127 +0,0 @@
-/*******************************************************************************
- * *
- * Copyright (C) 2019 by Max Lv *
- * Copyright (C) 2019 by Mygod Studio *
- * *
- * 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 com.github.shadowsocks.net
-
-import android.os.Build
-import com.github.shadowsocks.utils.printLog
-import kotlinx.coroutines.*
-import kotlinx.coroutines.channels.Channel
-import kotlinx.coroutines.channels.sendBlocking
-import java.io.IOException
-import java.nio.ByteBuffer
-import java.nio.channels.*
-
-class ChannelMonitor : Thread("ChannelMonitor") {
- private data class Registration(val channel: SelectableChannel,
- val ops: Int,
- val listener: (SelectionKey) -> Unit) {
- val result = CompletableDeferred()
- }
-
- private val selector = Selector.open()
- private val registrationPipe = Pipe.open()
- private val pendingRegistrations = Channel(Channel.UNLIMITED)
- private val closeChannel = Channel(1)
- @Volatile
- private var running = true
-
- private fun registerInternal(channel: SelectableChannel, ops: Int, block: (SelectionKey) -> Unit) =
- channel.register(selector, ops, block)
-
- init {
- registrationPipe.source().apply {
- configureBlocking(false)
- registerInternal(this, SelectionKey.OP_READ) {
- val junk = ByteBuffer.allocateDirect(1)
- while (read(junk) > 0) {
- pendingRegistrations.poll()!!.apply {
- try {
- result.complete(registerInternal(channel, ops, listener))
- } catch (e: Exception) {
- result.completeExceptionally(e)
- }
- }
- junk.clear()
- }
- }
- }
- start()
- }
-
- /**
- * Prevent NetworkOnMainThreadException because people enable strict mode for no reasons.
- */
- private suspend fun WritableByteChannel.writeCompat(src: ByteBuffer) =
- if (Build.VERSION.SDK_INT <= 23) withContext(Dispatchers.Default) { write(src) } else write(src)
-
- suspend fun register(channel: SelectableChannel, ops: Int, block: (SelectionKey) -> Unit): SelectionKey {
- val registration = Registration(channel, ops, block)
- pendingRegistrations.send(registration)
- ByteBuffer.allocateDirect(1).also { junk ->
- loop@ while (running) when (registrationPipe.sink().writeCompat(junk)) {
- 0 -> kotlinx.coroutines.yield()
- 1 -> break@loop
- else -> throw IOException("Failed to register in the channel")
- }
- }
- if (!running) throw CancellationException()
- return registration.result.await()
- }
-
- suspend fun wait(channel: SelectableChannel, ops: Int) = CompletableDeferred().run {
- register(channel, ops) {
- if (it.isValid) try {
- it.interestOps(0) // stop listening
- } catch (_: CancelledKeyException) { }
- complete(it)
- }
- await()
- }
-
- override fun run() {
- while (running) {
- val num = try {
- selector.select()
- } catch (e: Exception) {
- printLog(e)
- continue
- }
- if (num <= 0) continue
- val iterator = selector.selectedKeys().iterator()
- while (iterator.hasNext()) {
- val key = iterator.next()
- iterator.remove()
- (key.attachment() as (SelectionKey) -> Unit)(key)
- }
- }
- closeChannel.sendBlocking(Unit)
- }
-
- fun close(scope: CoroutineScope) {
- running = false
- selector.wakeup()
- scope.launch {
- closeChannel.receive()
- selector.keys().forEach { it.channel().close() }
- selector.close()
- }
- }
-}
diff --git a/core/src/main/java/com/github/shadowsocks/bg/DnsResolverCompat.kt b/core/src/main/java/com/github/shadowsocks/net/DnsResolverCompat.kt
similarity index 68%
rename from core/src/main/java/com/github/shadowsocks/bg/DnsResolverCompat.kt
rename to core/src/main/java/com/github/shadowsocks/net/DnsResolverCompat.kt
index c4790ad4dc..25568313b6 100644
--- a/core/src/main/java/com/github/shadowsocks/bg/DnsResolverCompat.kt
+++ b/core/src/main/java/com/github/shadowsocks/net/DnsResolverCompat.kt
@@ -18,7 +18,7 @@
* *
*******************************************************************************/
-package com.github.shadowsocks.bg
+package com.github.shadowsocks.net
import android.annotation.SuppressLint
import android.annotation.TargetApi
@@ -36,8 +36,11 @@ import com.github.shadowsocks.utils.int
import com.github.shadowsocks.utils.parseNumericAddress
import com.github.shadowsocks.utils.printLog
import kotlinx.coroutines.*
+import org.xbill.DNS.*
import java.io.FileDescriptor
import java.io.IOException
+import java.net.Inet4Address
+import java.net.Inet6Address
import java.net.InetAddress
import java.util.concurrent.Executor
import java.util.concurrent.Executors
@@ -94,6 +97,22 @@ sealed class DnsResolverCompat {
override fun bindSocket(network: Network, socket: FileDescriptor) = instance.bindSocket(network, socket)
override suspend fun resolve(network: Network, host: String) = instance.resolve(network, host)
override suspend fun resolveOnActiveNetwork(host: String) = instance.resolveOnActiveNetwork(host)
+ override suspend fun resolveRaw(network: Network, query: ByteArray) = instance.resolveRaw(network, query)
+ override suspend fun resolveRawOnActiveNetwork(query: ByteArray) = instance.resolveRawOnActiveNetwork(query)
+
+ // additional platform-independent DNS helpers
+
+ /**
+ * TTL returned from localResolver is set to 120. Android API does not provide TTL,
+ * so we suppose Android apps should not care about TTL either.
+ */
+ private const val TTL = 120L
+
+ fun prepareDnsResponse(request: Message) = Message(request.header.id).apply {
+ header.setFlag(Flags.QR.toInt()) // this is a response
+ if (request.header.getFlag(Flags.RD.toInt())) header.setFlag(Flags.RD.toInt())
+ request.question?.also { addRecord(it, Section.QUESTION) }
+ }
}
@Throws(IOException::class)
@@ -102,6 +121,8 @@ sealed class DnsResolverCompat {
Os.connect(fd, address, port)
abstract suspend fun resolve(network: Network, host: String): Array
abstract suspend fun resolveOnActiveNetwork(host: String): Array
+ abstract suspend fun resolveRaw(network: Network, query: ByteArray): ByteArray
+ abstract suspend fun resolveRawOnActiveNetwork(query: ByteArray): ByteArray
@SuppressLint("PrivateApi")
private open class DnsResolverCompat21 : DnsResolverCompat() {
@@ -138,6 +159,40 @@ sealed class DnsResolverCompat {
GlobalScope.async(unboundedIO) { network.getAllByName(host) }.await()
override suspend fun resolveOnActiveNetwork(host: String) =
GlobalScope.async(unboundedIO) { InetAddress.getAllByName(host) }.await()
+
+ private suspend fun resolveRaw(query: ByteArray,
+ hostResolver: suspend (String) -> Array): ByteArray {
+ val request = try {
+ Message(query)
+ } catch (e: IOException) {
+ throw UnsupportedOperationException(e) // unrecognized packet
+ }
+ when (val opcode = request.header.opcode) {
+ Opcode.QUERY -> { }
+ else -> throw UnsupportedOperationException("Unsupported opcode $opcode")
+ }
+ val question = request.question
+ val isIpv6 = when (val type = question?.type) {
+ Type.A -> false
+ Type.AAAA -> true
+ else -> throw UnsupportedOperationException("Unsupported query type $type")
+ }
+ val host = question.name.canonicalize().toString(true)
+ return prepareDnsResponse(request).apply {
+ header.setFlag(Flags.RA.toInt()) // recursion available
+ for (address in hostResolver(host).asIterable().run {
+ if (isIpv6) filterIsInstance() else filterIsInstance()
+ }) addRecord(when (address) {
+ is Inet4Address -> ARecord(question.name, DClass.IN, TTL, address)
+ is Inet6Address -> AAAARecord(question.name, DClass.IN, TTL, address)
+ else -> error("Unsupported address $address")
+ }, Section.ANSWER)
+ }.toWire()
+ }
+ override suspend fun resolveRaw(network: Network, query: ByteArray) =
+ resolveRaw(query) { resolve(network, it) }
+ override suspend fun resolveRawOnActiveNetwork(query: ByteArray) =
+ resolveRaw(query, this::resolveOnActiveNetwork)
}
@TargetApi(23)
@@ -154,6 +209,8 @@ sealed class DnsResolverCompat {
override fun bindSocket(network: Network, socket: FileDescriptor) = network.bindSocket(socket)
+ private val activeNetwork get() = Core.connectivity.activeNetwork ?: throw IOException("no network")
+
override suspend fun resolve(network: Network, host: String): Array {
return suspendCancellableCoroutine { cont ->
val signal = CancellationSignal()
@@ -167,9 +224,19 @@ sealed class DnsResolverCompat {
})
}
}
+ override suspend fun resolveOnActiveNetwork(host: String) = resolve(activeNetwork, host)
- override suspend fun resolveOnActiveNetwork(host: String): Array {
- return resolve(Core.connectivity.activeNetwork ?: return emptyArray(), host)
+ override suspend fun resolveRaw(network: Network, query: ByteArray): ByteArray {
+ return suspendCancellableCoroutine { cont ->
+ val signal = CancellationSignal()
+ cont.invokeOnCancellation { signal.cancel() }
+ DnsResolver.getInstance().rawQuery(network, query, DnsResolver.FLAG_NO_RETRY, this,
+ signal, object : DnsResolver.Callback {
+ override fun onAnswer(answer: ByteArray, rcode: Int) = cont.resume(answer)
+ override fun onError(error: DnsResolver.DnsException) = cont.resumeWithException(IOException(error))
+ })
+ }
}
+ override suspend fun resolveRawOnActiveNetwork(query: ByteArray) = resolveRaw(activeNetwork, query)
}
}
diff --git a/core/src/main/java/com/github/shadowsocks/net/LocalDnsServer.kt b/core/src/main/java/com/github/shadowsocks/net/LocalDnsServer.kt
deleted file mode 100644
index 9bfc5aa2d2..0000000000
--- a/core/src/main/java/com/github/shadowsocks/net/LocalDnsServer.kt
+++ /dev/null
@@ -1,213 +0,0 @@
-/*******************************************************************************
- * *
- * Copyright (C) 2019 by Max Lv *
- * Copyright (C) 2019 by Mygod Studio *
- * *
- * 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 com.github.shadowsocks.net
-
-import android.util.Log
-import com.crashlytics.android.Crashlytics
-import com.github.shadowsocks.acl.AclMatcher
-import com.github.shadowsocks.bg.BaseService
-import com.github.shadowsocks.utils.printLog
-import kotlinx.coroutines.*
-import org.xbill.DNS.*
-import java.io.IOException
-import java.net.*
-import java.nio.ByteBuffer
-import java.nio.channels.DatagramChannel
-import java.nio.channels.SelectionKey
-import java.nio.channels.SocketChannel
-
-/**
- * A simple DNS conditional forwarder.
- *
- * No cache is provided as localResolver may change from time to time. We expect DNS clients to do cache themselves.
- *
- * Based on:
- * https://github.com/bitcoinj/httpseed/blob/809dd7ad9280f4bc98a356c1ffb3d627bf6c7ec5/src/main/kotlin/dns.kt
- * https://github.com/shadowsocks/overture/tree/874f22613c334a3b78e40155a55479b7b69fee04
- */
-class LocalDnsServer(private val localResolver: suspend (String) -> Array,
- private val remoteDns: Socks5Endpoint,
- private val proxy: SocketAddress,
- private val hosts: HostsFile,
- /**
- * Forward UDP queries to TCP.
- */
- private val tcp: Boolean = false,
- aclSpawn: (suspend () -> AclMatcher)? = null) : CoroutineScope {
- companion object {
- private const val TAG = "LocalDnsServer"
- private const val TIMEOUT = 10_000L
- /**
- * TTL returned from localResolver is set to 120. Android API does not provide TTL,
- * so we suppose Android apps should not care about TTL either.
- */
- private const val TTL = 120L
- private const val UDP_PACKET_SIZE = 512
-
- private fun prepareDnsResponse(request: Message) = Message(request.header.id).apply {
- header.setFlag(Flags.QR.toInt()) // this is a response
- if (request.header.getFlag(Flags.RD.toInt())) header.setFlag(Flags.RD.toInt())
- request.question?.also { addRecord(it, Section.QUESTION) }
- }
-
- private fun cookDnsResponse(request: Message, results: Iterable) =
- ByteBuffer.wrap(prepareDnsResponse(request).apply {
- header.setFlag(Flags.RA.toInt()) // recursion available
- for (address in results) addRecord(when (address) {
- is Inet4Address -> ARecord(question.name, DClass.IN, TTL, address)
- is Inet6Address -> AAAARecord(question.name, DClass.IN, TTL, address)
- else -> error("Unsupported address $address")
- }, Section.ANSWER)
- }.toWire())
- }
-
- private val monitor = ChannelMonitor()
-
- override val coroutineContext = SupervisorJob() + CoroutineExceptionHandler { _, t ->
- if (t is IOException) Crashlytics.log(Log.WARN, TAG, t.message) else printLog(t)
- }
- private val acl = aclSpawn?.let { async { it() } }
-
- suspend fun start(listen: SocketAddress) = DatagramChannel.open().run {
- configureBlocking(false)
- try {
- socket().bind(listen)
- } catch (e: BindException) {
- throw BaseService.ExpectedExceptionWrapper(e)
- }
- monitor.register(this, SelectionKey.OP_READ) { handlePacket(this) }
- }
-
- private fun handlePacket(channel: DatagramChannel) {
- val buffer = ByteBuffer.allocateDirect(UDP_PACKET_SIZE)
- val source = channel.receive(buffer)!!
- buffer.flip()
- launch {
- val reply = resolve(buffer)
- while (channel.send(reply, source) <= 0) monitor.wait(channel, SelectionKey.OP_WRITE)
- }
- }
-
- private suspend fun resolve(packet: ByteBuffer): ByteBuffer {
- val request = try {
- Message(packet)
- } catch (e: IOException) { // we cannot parse the message, do not attempt to handle it at all
- Crashlytics.log(Log.WARN, TAG, e.message)
- return forward(packet)
- }
- return supervisorScope {
- val remote = async { withTimeout(TIMEOUT) { forward(packet) } }
- try {
- if (request.header.opcode != Opcode.QUERY) return@supervisorScope remote.await()
- val question = request.question
- val isIpv6 = when (question?.type) {
- Type.A -> false
- Type.AAAA -> true
- else -> return@supervisorScope remote.await()
- }
- val host = question.name.canonicalize().toString(true)
- val hostsResults = hosts.resolve(host)
- if (hostsResults.isNotEmpty()) {
- remote.cancel()
- return@supervisorScope cookDnsResponse(request, hostsResults.run {
- if (isIpv6) filterIsInstance() else filterIsInstance()
- })
- }
- val acl = acl?.await() ?: return@supervisorScope remote.await()
- val useLocal = when (acl.shouldBypass(host)) {
- true -> true.also { remote.cancel() }
- false -> return@supervisorScope remote.await()
- null -> false
- }
- val localResults = try {
- withTimeout(TIMEOUT) { localResolver(host) }
- } catch (_: TimeoutCancellationException) {
- Crashlytics.log(Log.WARN, TAG, "Local resolving timed out, falling back to remote resolving")
- return@supervisorScope remote.await()
- } catch (_: UnknownHostException) {
- return@supervisorScope remote.await()
- }
- if (isIpv6) {
- val filtered = localResults.filterIsInstance()
- if (useLocal) return@supervisorScope cookDnsResponse(request, filtered)
- if (filtered.any { acl.shouldBypassIpv6(it.address) }) {
- remote.cancel()
- cookDnsResponse(request, filtered)
- } else remote.await()
- } else {
- val filtered = localResults.filterIsInstance()
- if (useLocal) return@supervisorScope cookDnsResponse(request, filtered)
- if (filtered.any { acl.shouldBypassIpv4(it.address) }) {
- remote.cancel()
- cookDnsResponse(request, filtered)
- } else remote.await()
- }
- } catch (e: Exception) {
- remote.cancel()
- when (e) {
- is TimeoutCancellationException -> Crashlytics.log(Log.WARN, TAG, "Remote resolving timed out")
- is CancellationException -> { } // ignore
- is IOException -> Crashlytics.log(Log.WARN, TAG, e.message)
- else -> printLog(e)
- }
- ByteBuffer.wrap(prepareDnsResponse(request).apply {
- header.rcode = Rcode.SERVFAIL
- }.toWire())
- }
- }
- }
-
- private suspend fun forward(packet: ByteBuffer): ByteBuffer {
- packet.position(0) // the packet might have been parsed, reset to beginning
- return if (tcp) SocketChannel.open().use { channel ->
- channel.configureBlocking(false)
- channel.connect(proxy)
- val wrapped = remoteDns.tcpWrap(packet)
- while (!channel.finishConnect()) monitor.wait(channel, SelectionKey.OP_CONNECT)
- while (channel.write(wrapped) >= 0 && wrapped.hasRemaining()) monitor.wait(channel, SelectionKey.OP_WRITE)
- val result = remoteDns.tcpReceiveBuffer(UDP_PACKET_SIZE)
- remoteDns.tcpUnwrap(result, channel::read) { monitor.wait(channel, SelectionKey.OP_READ) }
- result
- } else DatagramChannel.open().use { channel ->
- channel.configureBlocking(false)
- monitor.wait(channel, SelectionKey.OP_WRITE)
- check(channel.send(remoteDns.udpWrap(packet), proxy) > 0)
- val result = remoteDns.udpReceiveBuffer(UDP_PACKET_SIZE)
- while (isActive) {
- monitor.wait(channel, SelectionKey.OP_READ)
- if (channel.receive(result) == proxy) break
- result.clear()
- }
- result.flip()
- remoteDns.udpUnwrap(result)
- result
- }
- }
-
- fun shutdown(scope: CoroutineScope) {
- cancel()
- monitor.close(scope)
- scope.launch {
- this@LocalDnsServer.coroutineContext[Job]!!.join()
- acl?.also { it.await().close() }
- }
- }
-}
diff --git a/core/src/main/java/com/github/shadowsocks/net/Socks5Endpoint.kt b/core/src/main/java/com/github/shadowsocks/net/Socks5Endpoint.kt
deleted file mode 100644
index f30b98a4d9..0000000000
--- a/core/src/main/java/com/github/shadowsocks/net/Socks5Endpoint.kt
+++ /dev/null
@@ -1,128 +0,0 @@
-/*******************************************************************************
- * *
- * Copyright (C) 2019 by Max Lv *
- * Copyright (C) 2019 by Mygod Studio *
- * *
- * 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 com.github.shadowsocks.net
-
-import com.github.shadowsocks.utils.parseNumericAddress
-import net.sourceforge.jsocks.Socks4Message
-import net.sourceforge.jsocks.Socks5Message
-import java.io.EOFException
-import java.io.IOException
-import java.net.Inet4Address
-import java.net.Inet6Address
-import java.nio.ByteBuffer
-import kotlin.math.max
-
-class Socks5Endpoint(host: String, port: Int) {
- private val dest = host.parseNumericAddress().let { numeric ->
- val bytes = numeric?.address ?: host.toByteArray().apply { check(size < 256) { "Hostname too long" } }
- val type = when (numeric) {
- null -> Socks5Message.SOCKS_ATYP_DOMAINNAME
- is Inet4Address -> Socks5Message.SOCKS_ATYP_IPV4
- is Inet6Address -> Socks5Message.SOCKS_ATYP_IPV6
- else -> error("Unsupported address type $numeric")
- }
- ByteBuffer.allocate(bytes.size + (if (numeric == null) 1 else 0) + 3).apply {
- put(type.toByte())
- if (numeric == null) put(bytes.size.toByte())
- put(bytes)
- putShort(port.toShort())
- }
- }.array()
- private val headerReserved = max(3 + 3 + 16, 3 + dest.size)
-
- fun tcpWrap(message: ByteBuffer): ByteBuffer {
- check(message.remaining() < 65536) { "TCP message too large" }
- return ByteBuffer.allocateDirect(8 + dest.size + message.remaining()).apply {
- put(Socks5Message.SOCKS_VERSION.toByte())
- put(1) // nmethods
- put(0) // no authentication required
- // header
- put(Socks5Message.SOCKS_VERSION.toByte())
- put(Socks4Message.REQUEST_CONNECT.toByte())
- put(0) // reserved
- put(dest)
- // data
- putShort(message.remaining().toShort())
- put(message)
- flip()
- }
- }
- fun tcpReceiveBuffer(size: Int) = ByteBuffer.allocateDirect(headerReserved + 4 + size)
- suspend fun tcpUnwrap(buffer: ByteBuffer, reader: (ByteBuffer) -> Int, wait: suspend () -> Unit) {
- suspend fun readBytes(till: Int) {
- if (buffer.position() >= till) return
- while (reader(buffer) >= 0 && buffer.position() < till) wait()
- if (buffer.position() < till) throw EOFException("${buffer.position()} < $till")
- }
- suspend fun read(index: Int): Byte {
- readBytes(index + 1)
- return buffer[index]
- }
- if (read(0) != Socks5Message.SOCKS_VERSION.toByte()) throw IOException("Unsupported SOCKS version ${buffer[0]}")
- if (read(1) != 0.toByte()) throw IOException("Unsupported authentication ${buffer[1]}")
- if (read(2) != Socks5Message.SOCKS_VERSION.toByte()) throw IOException("Unsupported SOCKS version ${buffer[2]}")
- if (read(3) != 0.toByte()) throw IOException("SOCKS5 server returned error ${buffer[3]}")
- val dataOffset = when (val type = read(5)) {
- Socks5Message.SOCKS_ATYP_IPV4.toByte() -> 4
- Socks5Message.SOCKS_ATYP_DOMAINNAME.toByte() -> 1 + read(6)
- Socks5Message.SOCKS_ATYP_IPV6.toByte() -> 16
- else -> throw IOException("Unsupported address type $type")
- } + 8
- readBytes(dataOffset + 2)
- buffer.limit(buffer.position()) // store old position to update mark
- buffer.position(dataOffset)
- val dataLength = buffer.short.toUShort().toInt()
- val end = buffer.position() + dataLength
- if (end > buffer.capacity()) throw IOException(
- "Buffer too small to contain the message: $dataLength > ${buffer.capacity() - buffer.position()}")
- buffer.mark()
- buffer.position(buffer.limit()) // restore old position
- buffer.limit(end)
- readBytes(buffer.limit())
- buffer.reset()
- }
-
- private fun ByteBuffer.tryPosition(newPosition: Int) {
- if (limit() < newPosition) throw EOFException("${limit()} < $newPosition")
- position(newPosition)
- }
-
- fun udpWrap(packet: ByteBuffer) = ByteBuffer.allocateDirect(3 + dest.size + packet.remaining()).apply {
- // header
- putShort(0) // reserved
- put(0) // fragment number
- put(dest)
- // data
- put(packet)
- flip()
- }
- fun udpReceiveBuffer(size: Int) = ByteBuffer.allocateDirect(headerReserved + size)
- fun udpUnwrap(packet: ByteBuffer) {
- packet.tryPosition(3)
- packet.tryPosition(6 + when (val type = packet.get()) {
- Socks5Message.SOCKS_ATYP_IPV4.toByte() -> 4
- Socks5Message.SOCKS_ATYP_DOMAINNAME.toByte() -> 1 + packet.get()
- Socks5Message.SOCKS_ATYP_IPV6.toByte() -> 16
- else -> throw IOException("Unsupported address type $type")
- })
- packet.mark()
- }
-}
diff --git a/core/src/main/java/com/github/shadowsocks/subscription/SubscriptionService.kt b/core/src/main/java/com/github/shadowsocks/subscription/SubscriptionService.kt
index 5778a376b2..5b39b0b75a 100644
--- a/core/src/main/java/com/github/shadowsocks/subscription/SubscriptionService.kt
+++ b/core/src/main/java/com/github/shadowsocks/subscription/SubscriptionService.kt
@@ -24,8 +24,6 @@ import android.app.NotificationChannel
import android.app.NotificationManager
import android.app.PendingIntent
import android.app.Service
-import android.content.BroadcastReceiver
-import android.content.Context
import android.content.Intent
import android.content.IntentFilter
import android.os.IBinder
@@ -35,7 +33,6 @@ import androidx.annotation.RequiresApi
import androidx.core.app.NotificationCompat
import androidx.core.content.ContextCompat
import androidx.lifecycle.MutableLiveData
-import com.crashlytics.android.Crashlytics
import com.github.shadowsocks.Core
import com.github.shadowsocks.Core.app
import com.github.shadowsocks.core.R
diff --git a/core/src/main/java/com/github/shadowsocks/utils/Utils.kt b/core/src/main/java/com/github/shadowsocks/utils/Utils.kt
index d0582dc49d..69c3b45a8d 100644
--- a/core/src/main/java/com/github/shadowsocks/utils/Utils.kt
+++ b/core/src/main/java/com/github/shadowsocks/utils/Utils.kt
@@ -70,7 +70,7 @@ fun FileDescriptor.closeQuietly() = try {
Os.close(this)
} catch (_: ErrnoException) { }
-private val parseNumericAddress by lazy @SuppressLint("DiscouragedPrivateApi") {
+private val parseNumericAddress by lazy @SuppressLint("SoonBlockedPrivateApi") {
InetAddress::class.java.getDeclaredMethod("parseNumericAddress", String::class.java).apply {
isAccessible = true
}
diff --git a/core/src/main/jni/Android.mk b/core/src/main/jni/Android.mk
index f8549e58c6..9fb93e07f6 100755
--- a/core/src/main/jni/Android.mk
+++ b/core/src/main/jni/Android.mk
@@ -18,93 +18,6 @@ ROOT_PATH := $(LOCAL_PATH)
BUILD_SHARED_EXECUTABLE := $(LOCAL_PATH)/build-shared-executable.mk
-########################################################
-## libsodium
-########################################################
-
-include $(CLEAR_VARS)
-
-SODIUM_SOURCE := \
- crypto_aead/aes256gcm/aesni/aead_aes256gcm_aesni.c \
- crypto_aead/chacha20poly1305/sodium/aead_chacha20poly1305.c \
- crypto_aead/xchacha20poly1305/sodium/aead_xchacha20poly1305.c \
- crypto_core/ed25519/ref10/ed25519_ref10.c \
- crypto_core/hchacha20/core_hchacha20.c \
- crypto_core/salsa/ref/core_salsa_ref.c \
- crypto_generichash/blake2b/ref/blake2b-compress-ref.c \
- crypto_generichash/blake2b/ref/blake2b-ref.c \
- crypto_generichash/blake2b/ref/generichash_blake2b.c \
- crypto_onetimeauth/poly1305/onetimeauth_poly1305.c \
- crypto_onetimeauth/poly1305/donna/poly1305_donna.c \
- crypto_pwhash/crypto_pwhash.c \
- crypto_pwhash/argon2/argon2-core.c \
- crypto_pwhash/argon2/argon2.c \
- crypto_pwhash/argon2/argon2-encoding.c \
- crypto_pwhash/argon2/argon2-fill-block-ref.c \
- crypto_pwhash/argon2/blake2b-long.c \
- crypto_pwhash/argon2/pwhash_argon2i.c \
- crypto_scalarmult/curve25519/scalarmult_curve25519.c \
- crypto_scalarmult/curve25519/ref10/x25519_ref10.c \
- crypto_stream/chacha20/stream_chacha20.c \
- crypto_stream/chacha20/ref/chacha20_ref.c \
- crypto_stream/salsa20/stream_salsa20.c \
- crypto_stream/salsa20/ref/salsa20_ref.c \
- crypto_verify/sodium/verify.c \
- randombytes/randombytes.c \
- randombytes/sysrandom/randombytes_sysrandom.c \
- sodium/core.c \
- sodium/runtime.c \
- sodium/utils.c \
- sodium/version.c
-
-LOCAL_MODULE := sodium
-LOCAL_CFLAGS += -I$(LOCAL_PATH)/libsodium/src/libsodium/include \
- -I$(LOCAL_PATH)/include \
- -I$(LOCAL_PATH)/include/sodium \
- -I$(LOCAL_PATH)/libsodium/src/libsodium/include/sodium \
- -DPACKAGE_NAME=\"libsodium\" -DPACKAGE_TARNAME=\"libsodium\" \
- -DPACKAGE_VERSION=\"1.0.15\" -DPACKAGE_STRING=\"libsodium-1.0.15\" \
- -DPACKAGE_BUGREPORT=\"https://github.com/jedisct1/libsodium/issues\" \
- -DPACKAGE_URL=\"https://github.com/jedisct1/libsodium\" \
- -DPACKAGE=\"libsodium\" -DVERSION=\"1.0.15\" \
- -DHAVE_PTHREAD=1 \
- -DSTDC_HEADERS=1 \
- -DHAVE_SYS_TYPES_H=1 \
- -DHAVE_SYS_STAT_H=1 \
- -DHAVE_STDLIB_H=1 \
- -DHAVE_STRING_H=1 \
- -DHAVE_MEMORY_H=1 \
- -DHAVE_STRINGS_H=1 \
- -DHAVE_INTTYPES_H=1 \
- -DHAVE_STDINT_H=1 \
- -DHAVE_UNISTD_H=1 \
- -D__EXTENSIONS__=1 \
- -D_ALL_SOURCE=1 \
- -D_GNU_SOURCE=1 \
- -D_POSIX_PTHREAD_SEMANTICS=1 \
- -D_TANDEM_SOURCE=1 \
- -DHAVE_DLFCN_H=1 \
- -DLT_OBJDIR=\".libs/\" \
- -DHAVE_SYS_MMAN_H=1 \
- -DNATIVE_LITTLE_ENDIAN=1 \
- -DASM_HIDE_SYMBOL=.hidden \
- -DHAVE_WEAK_SYMBOLS=1 \
- -DHAVE_ATOMIC_OPS=1 \
- -DHAVE_ARC4RANDOM=1 \
- -DHAVE_ARC4RANDOM_BUF=1 \
- -DHAVE_MMAP=1 \
- -DHAVE_MLOCK=1 \
- -DHAVE_MADVISE=1 \
- -DHAVE_MPROTECT=1 \
- -DHAVE_NANOSLEEP=1 \
- -DHAVE_POSIX_MEMALIGN=1 \
- -DHAVE_GETPID=1 \
- -DCONFIGURED=1
-
-LOCAL_SRC_FILES := $(addprefix libsodium/src/libsodium/,$(SODIUM_SOURCE))
-
-include $(BUILD_STATIC_LIBRARY)
-
########################################################
## libevent
########################################################
@@ -138,87 +51,6 @@ LOCAL_SRC_FILES := $(addprefix libancillary/, $(ANCILLARY_SOURCE))
include $(BUILD_STATIC_LIBRARY)
-########################################################
-## libbloom
-########################################################
-
-include $(CLEAR_VARS)
-
-BLOOM_SOURCE := bloom.c murmur2/MurmurHash2.c
-
-LOCAL_MODULE := libbloom
-LOCAL_CFLAGS += -I$(LOCAL_PATH)/shadowsocks-libev/libbloom \
- -I$(LOCAL_PATH)/shadowsocks-libev/libbloom/murmur2
-
-LOCAL_SRC_FILES := $(addprefix shadowsocks-libev/libbloom/, $(BLOOM_SOURCE))
-
-include $(BUILD_STATIC_LIBRARY)
-
-########################################################
-## libipset
-########################################################
-
-include $(CLEAR_VARS)
-
-bdd_src = bdd/assignments.c bdd/basics.c bdd/bdd-iterator.c bdd/expanded.c \
- bdd/reachable.c bdd/read.c bdd/write.c
-map_src = map/allocation.c map/inspection.c map/ipv4_map.c map/ipv6_map.c \
- map/storage.c
-set_src = set/allocation.c set/inspection.c set/ipv4_set.c set/ipv6_set.c \
- set/iterator.c set/storage.c
-
-IPSET_SOURCE := general.c $(bdd_src) $(map_src) $(set_src)
-
-LOCAL_MODULE := libipset
-LOCAL_CFLAGS += -I$(LOCAL_PATH)/shadowsocks-libev/libipset/include \
- -I$(LOCAL_PATH)/shadowsocks-libev/libcork/include
-
-LOCAL_SRC_FILES := $(addprefix shadowsocks-libev/libipset/src/libipset/,$(IPSET_SOURCE))
-
-include $(BUILD_STATIC_LIBRARY)
-
-########################################################
-## libcork
-########################################################
-
-include $(CLEAR_VARS)
-
-cli_src := cli/commands.c
-core_src := core/allocator.c core/error.c core/gc.c \
- core/hash.c core/ip-address.c core/mempool.c \
- core/timestamp.c core/u128.c
-ds_src := ds/array.c ds/bitset.c ds/buffer.c ds/dllist.c \
- ds/file-stream.c ds/hash-table.c ds/managed-buffer.c \
- ds/ring-buffer.c ds/slice.c
-posix_src := posix/directory-walker.c posix/env.c posix/exec.c \
- posix/files.c posix/process.c posix/subprocess.c
-pthreads_src := pthreads/thread.c
-
-CORK_SOURCE := $(cli_src) $(core_src) $(ds_src) $(posix_src) $(pthreads_src)
-
-LOCAL_MODULE := libcork
-LOCAL_CFLAGS += -I$(LOCAL_PATH)/shadowsocks-libev/libcork/include \
- -DCORK_API=CORK_LOCAL
-
-LOCAL_SRC_FILES := $(addprefix shadowsocks-libev/libcork/src/libcork/,$(CORK_SOURCE))
-
-include $(BUILD_STATIC_LIBRARY)
-
-########################################################
-## libev
-########################################################
-
-include $(CLEAR_VARS)
-
-LOCAL_MODULE := libev
-LOCAL_CFLAGS += -DNDEBUG -DHAVE_CONFIG_H \
- -I$(LOCAL_PATH)/include/libev
-LOCAL_SRC_FILES := \
- libev/ev.c \
- libev/event.c
-
-include $(BUILD_STATIC_LIBRARY)
-
########################################################
## redsocks
########################################################
@@ -233,7 +65,7 @@ REDSOCKS_SOURCES := base.c http-connect.c \
LOCAL_STATIC_LIBRARIES := libevent
LOCAL_MODULE := redsocks
-LOCAL_SRC_FILES := $(addprefix redsocks/, $(REDSOCKS_SOURCES))
+LOCAL_SRC_FILES := $(addprefix redsocks/, $(REDSOCKS_SOURCES))
LOCAL_CFLAGS := -std=gnu99 -DUSE_IPTABLES \
-I$(LOCAL_PATH)/redsocks \
-I$(LOCAL_PATH)/libevent/include \
@@ -241,76 +73,6 @@ LOCAL_CFLAGS := -std=gnu99 -DUSE_IPTABLES \
include $(BUILD_SHARED_EXECUTABLE)
-########################################################
-## shadowsocks-libev local
-########################################################
-
-include $(CLEAR_VARS)
-
-SHADOWSOCKS_SOURCES := local.c \
- cache.c udprelay.c utils.c netutils.c json.c jconf.c \
- acl.c http.c tls.c rule.c \
- crypto.c aead.c stream.c base64.c \
- plugin.c ppbloom.c \
- android.c
-
-LOCAL_MODULE := ss-local
-LOCAL_SRC_FILES := $(addprefix shadowsocks-libev/src/, $(SHADOWSOCKS_SOURCES))
-LOCAL_CFLAGS := -Wall -fno-strict-aliasing -DMODULE_LOCAL \
- -DUSE_CRYPTO_MBEDTLS -DHAVE_CONFIG_H \
- -DCONNECT_IN_PROGRESS=EINPROGRESS \
- -I$(LOCAL_PATH)/include/shadowsocks-libev \
- -I$(LOCAL_PATH)/include \
- -I$(LOCAL_PATH)/libancillary \
- -I$(LOCAL_PATH)/mbedtls/include \
- -I$(LOCAL_PATH)/pcre \
- -I$(LOCAL_PATH)/libsodium/src/libsodium/include \
- -I$(LOCAL_PATH)/libsodium/src/libsodium/include/sodium \
- -I$(LOCAL_PATH)/shadowsocks-libev/libcork/include \
- -I$(LOCAL_PATH)/shadowsocks-libev/libipset/include \
- -I$(LOCAL_PATH)/shadowsocks-libev/libbloom \
- -I$(LOCAL_PATH)/libev
-
-LOCAL_STATIC_LIBRARIES := libev libmbedtls libipset libcork libbloom \
- libsodium libancillary libpcre
-
-LOCAL_LDLIBS := -llog
-
-include $(BUILD_SHARED_EXECUTABLE)
-
-########################################################
-## jni-helper
-########################################################
-
-include $(CLEAR_VARS)
-
-LOCAL_MODULE:= jni-helper
-
-LOCAL_C_INCLUDES := $(LOCAL_PATH)/re2
-
-LOCAL_CFLAGS := -std=c++17
-
-LOCAL_SRC_FILES := jni-helper.cpp \
- $(LOCAL_PATH)/re2/re2/bitstate.cc \
- $(LOCAL_PATH)/re2/re2/compile.cc \
- $(LOCAL_PATH)/re2/re2/dfa.cc \
- $(LOCAL_PATH)/re2/re2/nfa.cc \
- $(LOCAL_PATH)/re2/re2/onepass.cc \
- $(LOCAL_PATH)/re2/re2/parse.cc \
- $(LOCAL_PATH)/re2/re2/perl_groups.cc \
- $(LOCAL_PATH)/re2/re2/prog.cc \
- $(LOCAL_PATH)/re2/re2/re2.cc \
- $(LOCAL_PATH)/re2/re2/regexp.cc \
- $(LOCAL_PATH)/re2/re2/simplify.cc \
- $(LOCAL_PATH)/re2/re2/stringpiece.cc \
- $(LOCAL_PATH)/re2/re2/tostring.cc \
- $(LOCAL_PATH)/re2/re2/unicode_casefold.cc \
- $(LOCAL_PATH)/re2/re2/unicode_groups.cc \
- $(LOCAL_PATH)/re2/util/rune.cc \
- $(LOCAL_PATH)/re2/util/strutil.cc
-
-include $(BUILD_SHARED_LIBRARY)
-
########################################################
## tun2socks
########################################################
@@ -404,57 +166,3 @@ LOCAL_LDLIBS := -ldl -llog
LOCAL_SRC_FILES := $(addprefix badvpn/, $(TUN2SOCKS_SOURCES))
include $(BUILD_SHARED_EXECUTABLE)
-
-########################################################
-## mbed TLS
-########################################################
-
-include $(CLEAR_VARS)
-
-LOCAL_MODULE := mbedtls
-
-LOCAL_C_INCLUDES := $(LOCAL_PATH)/mbedtls/include
-
-MBEDTLS_SOURCES := $(wildcard $(LOCAL_PATH)/mbedtls/library/*.c)
-
-LOCAL_SRC_FILES := $(MBEDTLS_SOURCES:$(LOCAL_PATH)/%=%)
-
-include $(BUILD_STATIC_LIBRARY)
-
-########################################################
-## pcre
-########################################################
-
-include $(CLEAR_VARS)
-
-LOCAL_MODULE := pcre
-
-LOCAL_CFLAGS += -DHAVE_CONFIG_H
-
-LOCAL_C_INCLUDES := $(LOCAL_PATH)/pcre/dist $(LOCAL_PATH)/pcre
-
-libpcre_src_files := \
- dist/pcre_byte_order.c \
- dist/pcre_compile.c \
- dist/pcre_config.c \
- dist/pcre_dfa_exec.c \
- dist/pcre_exec.c \
- dist/pcre_fullinfo.c \
- dist/pcre_get.c \
- dist/pcre_globals.c \
- dist/pcre_jit_compile.c \
- dist/pcre_maketables.c \
- dist/pcre_newline.c \
- dist/pcre_ord2utf8.c \
- dist/pcre_refcount.c \
- dist/pcre_string_utils.c \
- dist/pcre_study.c \
- dist/pcre_tables.c \
- dist/pcre_ucd.c \
- dist/pcre_valid_utf8.c \
- dist/pcre_version.c \
- dist/pcre_xclass.c
-
-LOCAL_SRC_FILES := $(addprefix pcre/, $(libpcre_src_files)) $(LOCAL_PATH)/patch/pcre/pcre_chartables.c
-
-include $(BUILD_STATIC_LIBRARY)
diff --git a/core/src/main/jni/include/libev/config.h b/core/src/main/jni/include/libev/config.h
deleted file mode 100644
index 5c46ab0fa1..0000000000
--- a/core/src/main/jni/include/libev/config.h
+++ /dev/null
@@ -1,126 +0,0 @@
-/* config.h. Generated from config.h.in by configure. */
-/* config.h.in. Generated from configure.ac by autoheader. */
-
-/* Define to 1 if you have the `clock_gettime' function. */
-/* #undef HAVE_CLOCK_GETTIME */
-
-/* Define to 1 to use the syscall interface for clock_gettime */
-#define HAVE_CLOCK_SYSCALL 1
-
-/* Define to 1 if you have the header file. */
-#define HAVE_DLFCN_H 1
-
-/* Define to 1 if you have the `epoll_ctl' function. */
-#define HAVE_EPOLL_CTL 1
-
-/* Define to 1 if you have the `eventfd' function. */
-#define HAVE_EVENTFD 1
-
-/* Define to 1 if the floor function is available */
-#define HAVE_FLOOR 1
-
-/* Define to 1 if you have the `inotify_init' function. */
-#define HAVE_INOTIFY_INIT 1
-
-/* Define to 1 if you have the header file. */
-#define HAVE_INTTYPES_H 1
-
-/* Define to 1 if you have the `kqueue' function. */
-/* #undef HAVE_KQUEUE */
-
-/* Define to 1 if you have the `rt' library (-lrt). */
-/* #undef HAVE_LIBRT */
-
-/* Define to 1 if you have the header file. */
-#define HAVE_MEMORY_H 1
-
-/* Define to 1 if you have the `nanosleep' function. */
-#define HAVE_NANOSLEEP 1
-
-/* Define to 1 if you have the `poll' function. */
-#define HAVE_POLL 1
-
-/* Define to 1 if you have the header file. */
-#define HAVE_POLL_H 1
-
-/* Define to 1 if you have the `port_create' function. */
-/* #undef HAVE_PORT_CREATE */
-
-/* Define to 1 if you have the header file. */
-/* #undef HAVE_PORT_H */
-
-/* Define to 1 if you have the `select' function. */
-#define HAVE_SELECT 1
-
-/* Define to 1 if you have the `signalfd' function. */
-#define HAVE_SIGNALFD 0
-
-/* Define to 1 if you have the header file. */
-#define HAVE_STDINT_H 1
-
-/* Define to 1 if you have the header file. */
-#define HAVE_STDLIB_H 1
-
-/* Define to 1 if you have the header file. */
-#define HAVE_STRINGS_H 1
-
-/* Define to 1 if you have the header file. */
-#define HAVE_STRING_H 1
-
-/* Define to 1 if you have the header file. */
-#define HAVE_SYS_EPOLL_H 1
-
-/* Define to 1 if you have the header file. */
-#define HAVE_SYS_EVENTFD_H 1
-
-/* Define to 1 if you have the header file. */
-/* #undef HAVE_SYS_EVENT_H */
-
-/* Define to 1 if you have the header file. */
-#define HAVE_SYS_INOTIFY_H 1
-
-/* Define to 1 if you have the header file. */
-#define HAVE_SYS_SELECT_H 1
-
-/* Define to 1 if you have the header file. */
-#define HAVE_SYS_SIGNALFD_H 1
-
-/* Define to 1 if you have the header file. */
-#define HAVE_SYS_STAT_H 1
-
-/* Define to 1 if you have the header file. */
-#define HAVE_SYS_TYPES_H 1
-
-/* Define to 1 if you have the header file. */
-#define HAVE_UNISTD_H 1
-
-/* Define to the sub-directory in which libtool stores uninstalled libraries.
- */
-#define LT_OBJDIR ".libs/"
-
-/* Name of package */
-#define PACKAGE "libev"
-
-/* Define to the address where bug reports for this package should be sent. */
-#define PACKAGE_BUGREPORT ""
-
-/* Define to the full name of this package. */
-#define PACKAGE_NAME ""
-
-/* Define to the full name and version of this package. */
-#define PACKAGE_STRING ""
-
-/* Define to the one symbol short name of this package. */
-#define PACKAGE_TARNAME ""
-
-/* Define to the home page for this package. */
-#define PACKAGE_URL ""
-
-/* Define to the version of this package. */
-#define PACKAGE_VERSION ""
-
-/* Define to 1 if you have the ANSI C header files. */
-#define STDC_HEADERS 1
-
-/* Version number of package */
-#define VERSION "4.11"
diff --git a/core/src/main/jni/include/pdnsd/config.h b/core/src/main/jni/include/pdnsd/config.h
deleted file mode 100644
index 3740beae73..0000000000
--- a/core/src/main/jni/include/pdnsd/config.h
+++ /dev/null
@@ -1,437 +0,0 @@
-/* config.h. Generated from config.h.in by configure. */
-/* config.h.in. Generated from configure.in by autoheader. */
-#ifndef _CONFIG_H_
-#define _CONFIG_H_
-
-/* ONLY EDIT acconfig.h, NEVER config.h or config.h.in!
- * config.h MAY BE OVERWRITTEN BY make, config.h.in by autoheader! */
-
-/* Define your Target here. Currently defined are TARGET_LINUX (any
- * architecture), TARGET_BSD (experimental; tested on FreeBSD, hopefully
- * works for other BSD variants) and TARGET_CYGWIN. */
-#define TARGET TARGET_LINUX
-
-/* change the #undef to #define if you do not want to compile with special
- * ISDN support for Linux. Note that the ISDN support will not compile ok on
- * unpatched kernerls earlier than 2.2.12 (if you did apply newer isdn patches,
- * it may work fine). This is not on by default because it will cause compile
- * problems on some systems */
-/* #undef ISDN_SUPPORT */
-
-/* The following regulates the IP Protocol support. Supported types are IPv4
- * and IPv6 (aka IPng). You may enable either or both of these protocols.
- * Enabling in this context means that support for the respective protocol
- * will be in the binary. When running the binary, one of the protocols may
- * be activated via command line switches. Note that activating both IPv4 and
- * IPv6 is pointless (and will not work because two UDP and two TCP threads
- * will be started that concur for ports). Because of that, it is not allowed.
- * When pdnsd runs with IPv6 activated it should be able to service queries
- * from IPv6 as well as from IPv4 hosts, provided that you host is configured
- * properly.
- * For each of the protocols there are two options: ENABLE_IPV4 and ENABLE_IPV6
- * control whether support for the respective protocol is available in the
- * binary. DEFAULT_IPV4 selects which protocol is enabled on pdnsd
- * startup by default. 1 means IPv4, while 0 means IPv6. If support for
- * a protocol was included in the executable, you can specify command line
- * parameters to activate or deactivate that protocol (the options are -4 and
- * -6), but it makes more sense to use the run_ipv4=on/off option in the
- * configuration file.
- * Make your choice. Note that IPv6 support is experimental in pdnsd.
- * In normal operation, you will currently only need IPv4. */
-#define ENABLE_IPV4 1
-#define DEFAULT_IPV4 1
-#undef ENABLE_IPV6
-
-/* In all pdnsd versions before 1.0.6, DNS queries were always done over
- * TCP. Now, you have the choice. You can control that behaviour using
- * the -m command line switch, and you can give a preset here. There
- * are 3 different modes:
- * UDP_ONLY: This is undoubtedly the fastest query method, because
- * no TCP negotiation needs to be done.
- * TCP_ONLY: This is slower than uo, but generally more secure
- * against DNS spoofing. Note that some name servers on the
- * internet do not support TCP queries, notably dnscache.
- * TCP_UDP: TCP, then UDP. If the TCP query fails with a "connection refused"-
- * error or times out, the query is retried using UDP.
- * UDP_TCP: UDP, then TCP. If the UDP reply is truncated (i.e. the tc flag is set),
- * the query is retried using TCP. */
-#define M_PRESET TCP_ONLY
-
-/* In addition to choosing the presets, you may also completely disable
- * one of the protocols (TCP for preset UDP_ONLY and UDP for preset TCP_ONLY).
- * This saves some executable space. */
-/* #undef NO_UDP_QUERIES */
-/* #undef NO_TCP_QUERIES */
-
-/* With the following option, you can disable the TCP server functionality
- * of pdnsd. Nearly no program does TCP queries, so you probably can do
- * this safely and save some executable space and one thread.
- * You also can turn off the TCP server at runtime with the --notcp option. */
-/* #undef NO_TCP_SERVER */
-
-/* By undefining the following, you can disable the UDP source address
- * discovery code. This is not recommended, but you may need it when
- * running into compilation problems. */
-#define SRC_ADDR_DISC 1
-
-/* NO_POLL specifies not to use poll(2), but select(2) instead. If you are
- * unsure about what this means, just leave this as it is.*/
-/* #undef NO_POLL */
-
-/* Define this for "hard" RFC 2181 compliance: this RFC states that
- * implementations should discard answers whose RR sets have multiple
- * different time stamps. While correct answers are generated, incorrect
- * ones are normally tolerated and corrected. Full RFC compliance is
- * however only achieved by deactivating this behaviour and thus being
- * intolerant. */
-/* #undef RFC2181_ME_HARDER */
-
-/* Define this to the device you want to use for getting random numbers.
- * Leave this undefined if you wand to use the standard C library random
- * function, which basically should be sufficient.
- * Linux and FreeBSD have two random number devices: /dev/random and
- * /dev/urandom. /dev/urandom might be less secure in some cases, but
- * should still be more than sufficient. The use of /dev/random is
- * discouraged, as reading from this device blocks when new random bits
- * need to be gathered. */
-/* #undef RANDOM_DEVICE */
-#define R_DEFAULT 1
-/* #undef R_RANDOM */
-/* #undef R_ARC4RANDOM */
-/*#define RANDOM_DEVICE "/dev/urandom"*/
-
-/* Designate which database manager to use for cacheing.
- * default: native; others: gdbm */
-#define CACHE_DBM DBM_NATIVE
-
-#define CONFDIR "/data/data/com.github.shadowsocks"
-
-#define CACHEDIR "/data/data/com.github.shadowsocks"
-
-#define TEMPDIR "/data/data/com.github.shadowsocks/cache";
-
-/* This is for various debugging facilities that produce debug output and
- * double-check some values. You can enable debug messages with the -g option.
- * Normally, you can switch this off safely by setting the number after DEBUG
- * to 0. This will increase speed (although only marginally), save space
- * in the executable (only about 12kB) and some stack space per thread
- * (which may be significant if you have many threads running simultaneously).
- * However, it may be an aid when debugging config files.
- * The only defined debug levels by now are in the range 0 - 9.
- * Define this to 9 if you want hex dumps of all the queries and replies pdnsd
- * receives (you must also call pdnsd with -v9 to actually see the hex dumps).
- * When in doubt, leave it defined to 1. */
-#define DEBUG 1
-
-/* This defines the default verbosity of informational messages you will get.
- This has nothing to to with the debug option (-g), but may be set with -v
- option. 0 is for normal operation, up to 3 for debugging.
- Unlike the debug messages, these messages will also be written to the syslog.*/
-#define VERBOSITY 0
-
-/* Redefine this if you want another hash size.
- * The number of hash buckets is computed as power of two (1< and it should be used (not on Ultrix).
- */
-#define HAVE_ALLOCA_H 1
-
-/* Define to 1 if you have the `asprintf' function. */
-#define HAVE_ASPRINTF 1
-
-/* Define to 1 if you don't have `vprintf' but do have `_doprnt.' */
-/* #undef HAVE_DOPRNT */
-
-/* Define to 1 if you have the header file. */
-#define HAVE_FCNTL_H 1
-
-/* Define to 1 if you have the `getline' function. */
-#if defined(__aarch64__) || defined(__x86_64__)
-#define HAVE_GETLINE 1
-#endif
-
-/* Define to 1 if you have the `getpwnam_r' function. */
-//#define HAVE_GETPWNAM_R 1
-
-/* Define to 1 if you have the `gettimeofday' function. */
-#define HAVE_GETTIMEOFDAY 1
-
-/* Define to 1 if you have the `inet_ntop' function. */
-#define HAVE_INET_NTOP 1
-
-/* Define to 1 if you have the `inet_pton' function. */
-#define HAVE_INET_PTON 1
-
-/* Define to 1 if you have the header file. */
-#define HAVE_INTTYPES_H 1
-
-/* Define to 1 if you have the `pthread' library (-lpthread). */
-#define HAVE_LIBPTHREAD 1
-
-/* Define to 1 if you have the header file. */
-#define HAVE_MALLOC_H 1
-
-/* Define to 1 if you have the header file. */
-#define HAVE_MEMORY_H 1
-
-/* Define to 1 if you have the `mempcpy' function. */
-//#define HAVE_MEMPCPY 1
-
-/* Define to 1 if you have the `mkfifo' function. */
-#define HAVE_MKFIFO 1
-
-/* Define to 1 if you have the `nanosleep' function. */
-#define HAVE_NANOSLEEP 1
-
-/* Define to 1 if you have the header file. */
-#define HAVE_NETINET_IN_H 1
-
-/* Define to 1 if you have the header file. */
-#define HAVE_NET_IF_H 1
-
-/* Define to 1 if you have the `poll' function. */
-#define HAVE_POLL 1
-
-/* Define to 1 if you have the `select' function. */
-#define HAVE_SELECT 1
-
-/* Define to 1 if you have the `snprintf' function. */
-#define HAVE_SNPRINTF 1
-
-/* Define to 1 if you have the `socket' function. */
-#define HAVE_SOCKET 1
-
-/* Define to 1 if the system has the type `socklen_t'. */
-#define HAVE_SOCKLEN_T 1
-
-/* Define to 1 if you have the header file. */
-#define HAVE_STDINT_H 1
-
-/* Define to 1 if you have the header file. */
-#define HAVE_STDLIB_H 1
-
-/* Define to 1 if you have the `stpcpy' function. */
-#if defined(__aarch64__) || defined(__x86_64__)
-#define HAVE_STPCPY 1
-#endif
-
-/* Define to 1 if you have the `stpncpy' function. */
-//#define HAVE_STPNCPY 1
-
-/* Define to 1 if you have the `strdup' function. */
-#define HAVE_STRDUP 1
-
-/* Define to 1 if you have the `strerror' function. */
-#define HAVE_STRERROR 1
-
-/* Define to 1 if you have the header file. */
-#define HAVE_STRINGS_H 1
-
-/* Define to 1 if you have the header file. */
-#define HAVE_STRING_H 1
-
-/* Define to 1 if you have the `strlcpy' function. */
-/* #undef HAVE_STRLCPY */
-
-/* Define to 1 if you have the `strndup' function. */
-#define HAVE_STRNDUP 1
-
-/* Define to 1 if the system has the type `struct ifreq'. */
-#define HAVE_STRUCT_IFREQ 1
-
-/* Define to 1 if the system has the type `struct in6_addr'. */
-#define HAVE_STRUCT_IN6_ADDR 1
-
-/* Define to 1 if the system has the type `struct in_pktinfo'. */
-#define HAVE_STRUCT_IN_PKTINFO 1
-
-/* Define to 1 if you have the header file. */
-#define HAVE_SYSLOG_H 1
-
-/* Define to 1 if you have the header file. */
-#define HAVE_SYS_IOCTL_H 1
-
-/* Define to 1 if you have the header file. */
-#define HAVE_SYS_POLL_H 1
-
-/* Define to 1 if you have the header file. */
-#define HAVE_SYS_SOCKET_H 1
-
-/* Define to 1 if you have the header file. */
-#define HAVE_SYS_STAT_H 1
-
-/* Define to 1 if you have the header file. */
-#define HAVE_SYS_TIME_H 1
-
-/* Define to 1 if you have the header file. */
-#define HAVE_SYS_TYPES_H 1
-
-/* Define to 1 if you have that is POSIX.1 compatible. */
-#define HAVE_SYS_WAIT_H 1
-
-/* Define to 1 if you have the `uname' function. */
-#define HAVE_UNAME 1
-
-/* Define to 1 if you have the header file. */
-#define HAVE_UNISTD_H 1
-
-/* Define to 1 if you have the `vasprintf' function. */
-#define HAVE_VASPRINTF 1
-
-/* Define to 1 if you have the `vprintf' function. */
-#define HAVE_VPRINTF 1
-
-/* Define to 1 if you have the `vsnprintf' function. */
-#define HAVE_VSNPRINTF 1
-
-/* Define to 1 if your C compiler doesn't accept -c and -o together. */
-/* #undef NO_MINUS_C_MINUS_O */
-
-/* Define to the address where bug reports for this package should be sent. */
-#define PACKAGE_BUGREPORT ""
-
-/* Define to the full name of this package. */
-#define PACKAGE_NAME ""
-
-/* Define to the full name and version of this package. */
-#define PACKAGE_STRING ""
-
-/* Define to the one symbol short name of this package. */
-#define PACKAGE_TARNAME ""
-
-/* Define to the version of this package. */
-#define PACKAGE_VERSION ""
-
-/* Define as the return type of signal handlers (`int' or `void'). */
-#define RETSIGTYPE void
-
-/* If using the C implementation of alloca, define if you know the
- direction of stack growth for your system; otherwise it will be
- automatically deduced at runtime.
- STACK_DIRECTION > 0 => grows toward higher addresses
- STACK_DIRECTION < 0 => grows toward lower addresses
- STACK_DIRECTION = 0 => direction of growth unknown */
-/* #undef STACK_DIRECTION */
-
-/* Define to 1 if you have the ANSI C header files. */
-#define STDC_HEADERS 1
-
-/* Define to 1 if you can safely include both and . */
-#define TIME_WITH_SYS_TIME 1
-
-/* Define to 1 if your declares `struct tm'. */
-/* #undef TM_IN_SYS_TIME */
-
-/* Enable extensions on AIX 3, Interix. */
-#ifndef _ALL_SOURCE
-# define _ALL_SOURCE 1
-#endif
-/* Enable GNU extensions on systems that have them. */
-#ifndef _GNU_SOURCE
-# define _GNU_SOURCE 1
-#endif
-/* Enable threading extensions on Solaris. */
-#ifndef _POSIX_PTHREAD_SEMANTICS
-# define _POSIX_PTHREAD_SEMANTICS 1
-#endif
-/* Enable extensions on HP NonStop. */
-#ifndef _TANDEM_SOURCE
-# define _TANDEM_SOURCE 1
-#endif
-/* Enable general extensions on Solaris. */
-#ifndef __EXTENSIONS__
-# define __EXTENSIONS__ 1
-#endif
-
-
-/* Define to 1 if on MINIX. */
-/* #undef _MINIX */
-
-/* Define to 2 if the system does not provide POSIX.1 features except with
- this defined. */
-/* #undef _POSIX_1_SOURCE */
-
-/* Define to 1 if you need to in order for `stat' and other things to work. */
-/* #undef _POSIX_SOURCE */
-
-/* Define to empty if `const' does not conform to ANSI C. */
-/* #undef const */
-
-/* Define to `int' if does not define. */
-/* #undef pid_t */
-
-/* Define to `unsigned int' if does not define. */
-/* #undef size_t */
diff --git a/core/src/main/jni/include/shadowsocks-libev/config.h b/core/src/main/jni/include/shadowsocks-libev/config.h
deleted file mode 100644
index 8594fa0dbe..0000000000
--- a/core/src/main/jni/include/shadowsocks-libev/config.h
+++ /dev/null
@@ -1,428 +0,0 @@
-/* config.h. Generated from config.h.in by configure. */
-/* config.h.in. Generated from configure.ac by autoheader. */
-
-/* Define if building universal (internal helper macro) */
-/* #undef AC_APPLE_UNIVERSAL_BUILD */
-
-/* errno for incomplete non-blocking connect(2) */
-#define CONNECT_IN_PROGRESS EINPROGRESS
-
-/* Override libev default fd conversion macro. */
-/* #undef EV_FD_TO_WIN32_HANDLE */
-
-/* Override libev default fd close macro. */
-/* #undef EV_WIN32_CLOSE_FD */
-
-/* Override libev default handle conversion macro. */
-/* #undef EV_WIN32_HANDLE_TO_FD */
-
-/* Reset max file descriptor size. */
-/* #undef FD_SETSIZE */
-
-/* Define to 1 if you have the header file. */
-#define HAVE_ARPA_INET_H 1
-
-/* Define to 1 if you have the `CCCryptorCreateWithMode' function. */
-/* #undef HAVE_CCCRYPTORCREATEWITHMODE */
-
-/* Define to 1 if you have the `clock_gettime' function. */
-/* #undef HAVE_CLOCK_GETTIME */
-
-/* Define to 1 to use the syscall interface for clock_gettime */
-/* #undef HAVE_CLOCK_SYSCALL */
-
-/* Define to 1 if you have the header file. */
-/* #undef HAVE_COMMONCRYPTO_COMMONCRYPTO_H */
-
-/* Define to 1 if you have the declaration of `inet_ntop', and to 0 if you
- don't. */
-#define HAVE_DECL_INET_NTOP 1
-
-/* Define to 1 if you have the header file. */
-#define HAVE_DLFCN_H 1
-
-/* Define to 1 if you have the header file. */
-#define HAVE_LINUX_TCP_H 1
-
-/* Define to 1 if you have the `epoll_ctl' function. */
-/* #undef HAVE_EPOLL_CTL */
-
-/* Define to 1 if you have the `eventfd' function. */
-/* #undef HAVE_EVENTFD */
-
-/* Define to 1 if you have the `EVP_EncryptInit_ex' function. */
-/* #undef HAVE_EVP_ENCRYPTINIT_EX */
-
-/* Define to 1 if you have the header file. */
-#define HAVE_FCNTL_H 1
-
-/* Define to 1 if the floor function is available */
-#define HAVE_FLOOR 1
-
-/* Define to 1 if you have the `fork' function. */
-#define HAVE_FORK 1
-
-/* Define to 1 if you have the `getpwnam_r' function. */
-#define HAVE_GETPWNAM_R 1
-
-/* Define to 1 if you have the `inet_ntop' function. */
-/* #undef HAVE_INET_NTOP */
-
-/* Define to 1 if you have the `inotify_init' function. */
-/* #undef HAVE_INOTIFY_INIT */
-
-/* Define to 1 if you have the header file. */
-#define HAVE_INTTYPES_H 1
-
-/* Enable IPv6 support in libudns */
-#define HAVE_IPv6 1
-
-/* Define to 1 if you have the `kqueue' function. */
-#define HAVE_KQUEUE 1
-
-/* Define to 1 if you have the header file. */
-#define HAVE_LANGINFO_H 1
-
-/* Define to 1 if you have the `rt' library (-lrt). */
-/* #undef HAVE_LIBRT */
-
-/* Define to 1 if you have the `socket' library (-lsocket). */
-/* #undef HAVE_LIBSOCKET */
-
-/* Define to 1 if you have the header file. */
-#define HAVE_LIMITS_H 1
-
-/* Define to 1 if you have the header file. */
-/* #undef HAVE_LINUX_IF_H */
-
-/* Define to 1 if you have the header file. */
-/* #undef HAVE_LINUX_NETFILTER_IPV4_H */
-
-/* Define to 1 if you have the header
- file. */
-/* #undef HAVE_LINUX_NETFILTER_IPV6_IP6_TABLES_H */
-
-/* Define to 1 if you have the header file. */
-#define HAVE_LOCALE_H 1
-
-/* Define to 1 if you have the `malloc' function. */
-#define HAVE_MALLOC 1
-
-/* Define to 1 if you have the header file. */
-#define HAVE_MEMORY_H 1
-
-/* Define to 1 if you have the `memset' function. */
-#define HAVE_MEMSET 1
-
-/* Define to 1 if you have the `nanosleep' function. */
-#define HAVE_NANOSLEEP 1
-
-/* Define to 1 if you have the header file. */
-#define HAVE_NETDB_H 1
-
-/* Define to 1 if you have the header file. */
-#define HAVE_NETINET_IN_H 1
-
-/* Define to 1 if you have the header file. */
-#define HAVE_NET_IF_H 1
-
-/* Define to 1 if you have the header file. */
-/* #undef HAVE_OPENSSL_ENGINE_H */
-
-/* Define to 1 if you have the header file. */
-/* #undef HAVE_OPENSSL_ERR_H */
-
-/* Define to 1 if you have the header file. */
-/* #undef HAVE_OPENSSL_EVP_H */
-
-/* Define to 1 if you have the header file. */
-/* #undef HAVE_OPENSSL_PEM_H */
-
-/* Define to 1 if you have the header file. */
-/* #undef HAVE_OPENSSL_RAND_H */
-
-/* Define to 1 if you have the header file. */
-/* #undef HAVE_OPENSSL_RSA_H */
-
-/* Define to 1 if you have the header file. */
-/* #undef HAVE_OPENSSL_SHA_H */
-
-/* Define to 1 if you have the `poll' function. */
-#define HAVE_POLL 1
-
-/* Define to 1 if you have the header file. */
-#define HAVE_POLL_H 1
-
-/* Define to 1 if you have the `port_create' function. */
-/* #undef HAVE_PORT_CREATE */
-
-/* Define to 1 if you have the header file. */
-/* #undef HAVE_PORT_H */
-
-/* Have PTHREAD_PRIO_INHERIT. */
-#define HAVE_PTHREAD_PRIO_INHERIT 1
-
-/* Define to 1 if you have the `RAND_pseudo_bytes' function. */
-/* #undef HAVE_RAND_PSEUDO_BYTES */
-
-/* Define to 1 if you have the 'select' function. */
-#define HAVE_SELECT 1
-
-/* Define to 1 if you have the `setresuid' function. */
-/* #undef HAVE_SETRESUID */
-
-/* Define to 1 if you have the `setreuid' function. */
-#define HAVE_SETREUID 1
-
-/* Define to 1 if you have the `setrlimit' function. */
-#define HAVE_SETRLIMIT 1
-
-/* Define to 1 if you have the `signalfd' function. */
-/* #undef HAVE_SIGNALFD */
-
-/* Define to 1 if you have the `socket' function. */
-#define HAVE_SOCKET 1
-
-/* Define to 1 if you have the header file. */
-#define HAVE_STDINT_H 1
-
-/* Define to 1 if you have the header file. */
-#define HAVE_STDLIB_H 1
-
-/* Define to 1 if you have the `strerror' function. */
-#define HAVE_STRERROR 1
-
-/* Define to 1 if you have the header file. */
-#define HAVE_STRINGS_H 1
-
-/* Define to 1 if you have the header file. */
-#define HAVE_STRING_H 1
-
-/* Define to 1 if you have the header file. */
-/* #undef HAVE_SYS_EPOLL_H */
-
-/* Define to 1 if you have the header file. */
-/* #undef HAVE_SYS_EVENTFD_H */
-
-/* Define to 1 if you have the header file. */
-#define HAVE_SYS_EVENT_H 1
-
-/* Define to 1 if you have the header file. */
-/* #undef HAVE_SYS_INOTIFY_H */
-
-/* Define to 1 if you have the header file. */
-#define HAVE_SYS_IOCTL_H 1
-
-/* Define to 1 if you have the header file. */
-#define HAVE_SYS_SELECT_H 1
-
-/* Define to 1 if you have the header file. */
-/* #undef HAVE_SYS_SIGNALFD_H */
-
-/* Define to 1 if you have the header file. */
-#define HAVE_SYS_SOCKET_H 1
-
-/* Define to 1 if you have the header file. */
-#define HAVE_SYS_STAT_H 1
-
-/* Define to 1 if you have the header file. */
-#define HAVE_SYS_TYPES_H 1
-
-/* Define to 1 if you have that is POSIX.1 compatible. */
-#define HAVE_SYS_WAIT_H 1
-
-/* Define to 1 if you have the header file. */
-#define HAVE_UNISTD_H 1
-
-/* Define to 1 if you have the `vfork' function. */
-#define HAVE_VFORK 1
-
-/* Define to 1 if you have the header file. */
-/* #undef HAVE_VFORK_H */
-
-/* Define to 1 if you have the header file. */
-/* #undef HAVE_WINDOWS_H */
-
-/* Define to 1 if you have the header file. */
-/* #undef HAVE_WINSOCK2_H */
-
-/* Define to 1 if `fork' works. */
-#define HAVE_WORKING_FORK 1
-
-/* Define to 1 if `vfork' works. */
-#define HAVE_WORKING_VFORK 1
-
-/* Define to 1 if you have the header file. */
-/* #undef HAVE_WS2TCPIP_H */
-
-/* have zlib compression support */
-/* #undef HAVE_ZLIB */
-
-/* Define to 1 if you have the header file. */
-/* #undef HAVE_ZLIB_H */
-
-/* Define to the sub-directory in which libtool stores uninstalled libraries.
- */
-#define LT_OBJDIR ".libs/"
-
-/* Define to 1 if assertions should be disabled. */
-/* #undef NDEBUG */
-
-/* Name of package */
-#define PACKAGE "shadowsocks-libev"
-
-/* Define to the address where bug reports for this package should be sent. */
-#define PACKAGE_BUGREPORT "max.c.lv@gmail.com"
-
-/* Define to the full name of this package. */
-#define PACKAGE_NAME "shadowsocks-libev"
-
-/* Define to the full name and version of this package. */
-#define PACKAGE_STRING "shadowsocks-libev 2.4.8"
-
-/* Define to the one symbol short name of this package. */
-#define PACKAGE_TARNAME "shadowsocks-libev"
-
-/* Define to the home page for this package. */
-#define PACKAGE_URL ""
-
-/* Define to the version of this package. */
-#define PACKAGE_VERSION "2.4.8"
-
-/* Define to necessary symbol if this constant uses a non-standard name on
- your system. */
-/* #undef PTHREAD_CREATE_JOINABLE */
-
-/* Define as the return type of signal handlers (`int' or `void'). */
-#define RETSIGTYPE void
-
-/* Define to the type of arg 1 for `select'. */
-#define SELECT_TYPE_ARG1 int
-
-/* Define to the type of args 2, 3 and 4 for `select'. */
-#define SELECT_TYPE_ARG234 (fd_set *)
-
-/* Define to the type of arg 5 for `select'. */
-#define SELECT_TYPE_ARG5 (struct timeval *)
-
-/* Define to 1 if you have the ANSI C header files. */
-#define STDC_HEADERS 1
-
-/* Define to 1 if you can safely include both and . */
-#define TIME_WITH_SYS_TIME 1
-
-/* If the compiler supports a TLS storage class define it to that here */
-#define TLS __thread
-
-/* Use Apple CommonCrypto library */
-/* #undef USE_CRYPTO_APPLECC */
-
-/* Use mbed TLS library */
-#define USE_CRYPTO_MBEDTLS 1
-
-/* Use OpenSSL library */
-/* #undef USE_CRYPTO_OPENSSL */
-
-/* Use PolarSSL library */
-/* #undef USE_CRYPTO_POLARSSL */
-
-/* Enable extensions on AIX 3, Interix. */
-#ifndef _ALL_SOURCE
-# define _ALL_SOURCE 1
-#endif
-/* Enable GNU extensions on systems that have them. */
-#ifndef _GNU_SOURCE
-# define _GNU_SOURCE 1
-#endif
-/* Enable threading extensions on Solaris. */
-#ifndef _POSIX_PTHREAD_SEMANTICS
-# define _POSIX_PTHREAD_SEMANTICS 1
-#endif
-/* Enable extensions on HP NonStop. */
-#ifndef _TANDEM_SOURCE
-# define _TANDEM_SOURCE 1
-#endif
-/* Enable general extensions on Solaris. */
-#ifndef __EXTENSIONS__
-# define __EXTENSIONS__ 1
-#endif
-
-
-/* Version number of package */
-#define VERSION "2.4.8"
-
-/* Define WORDS_BIGENDIAN to 1 if your processor stores words with the most
- significant byte first (like Motorola and SPARC, unlike Intel). */
-#if defined AC_APPLE_UNIVERSAL_BUILD
-# if defined __BIG_ENDIAN__
-# define WORDS_BIGENDIAN 1
-# endif
-#else
-# ifndef WORDS_BIGENDIAN
-/* # undef WORDS_BIGENDIAN */
-# endif
-#endif
-
-/* Define to 1 if on MINIX. */
-/* #undef _MINIX */
-
-/* Define to 2 if the system does not provide POSIX.1 features except with
- this defined. */
-/* #undef _POSIX_1_SOURCE */
-
-/* Define to 1 if you need to in order for `stat' and other things to work. */
-/* #undef _POSIX_SOURCE */
-
-/* Define for Solaris 2.5.1 so the uint8_t typedef from ,
- , or is not used. If the typedef were allowed, the
- #define below would cause a syntax error. */
-/* #undef _UINT8_T */
-
-/* Define to empty if `const' does not conform to ANSI C. */
-/* #undef const */
-
-/* Define to `__inline__' or `__inline' if that's what the C compiler
- calls it, or to nothing if 'inline' is not supported under any name. */
-#ifndef __cplusplus
-/* #undef inline */
-#endif
-
-/* Define to `int' if does not define. */
-/* #undef pid_t */
-
-/* Define to the equivalent of the C99 'restrict' keyword, or to
- nothing if this is not supported. Do not define if restrict is
- supported directly. */
-#define restrict __restrict
-/* Work around a bug in Sun C++: it does not support _Restrict or
- __restrict__, even though the corresponding Sun C compiler ends up with
- "#define restrict _Restrict" or "#define restrict __restrict__" in the
- previous line. Perhaps some future version of Sun C++ will work with
- restrict; if so, hopefully it defines __RESTRICT like Sun C does. */
-#if defined __SUNPRO_CC && !defined __RESTRICT
-# define _Restrict
-# define __restrict__
-#endif
-
-/* Define to `unsigned int' if does not define. */
-/* #undef size_t */
-
-/* Define to `int' if does not define. */
-/* #undef ssize_t */
-
-/* Define to the type of an unsigned integer type of width exactly 16 bits if
- such a type exists and the standard includes do not define it. */
-/* #undef uint16_t */
-
-/* Define to the type of an unsigned integer type of width exactly 8 bits if
- such a type exists and the standard includes do not define it. */
-/* #undef uint8_t */
-
-/* Define as `fork' if `vfork' does not work. */
-/* #undef vfork */
-
-/* Define to 1 if you have the header file. */
-#define HAVE_PCRE_H 1
-
-/* Define to 1 if you have the header file. */
-/* #undef HAVE_PCRE_PCRE_H */
diff --git a/core/src/main/jni/include/sodium/version.h b/core/src/main/jni/include/sodium/version.h
deleted file mode 100644
index b95c40b523..0000000000
--- a/core/src/main/jni/include/sodium/version.h
+++ /dev/null
@@ -1,29 +0,0 @@
-
-#ifndef sodium_version_H
-#define sodium_version_H
-
-#include "export.h"
-
-#define SODIUM_VERSION_STRING "1.0.7"
-
-#define SODIUM_LIBRARY_VERSION_MAJOR 9
-#define SODIUM_LIBRARY_VERSION_MINOR 0
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-SODIUM_EXPORT
-const char *sodium_version_string(void);
-
-SODIUM_EXPORT
-int sodium_library_version_major(void);
-
-SODIUM_EXPORT
-int sodium_library_version_minor(void);
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif
diff --git a/core/src/main/jni/jni-helper.cpp b/core/src/main/jni/jni-helper.cpp
deleted file mode 100644
index 60936bbb04..0000000000
--- a/core/src/main/jni/jni-helper.cpp
+++ /dev/null
@@ -1,112 +0,0 @@
-/*******************************************************************************
- * *
- * Copyright (C) 2019 by Max Lv *
- * Copyright (C) 2019 by Mygod Studio *
- * *
- * 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 . *
- * *
- *******************************************************************************/
-
-#include
-
-#include "jni.h"
-#include "re2/re2.h"
-
-using namespace std;
-
-struct AclMatcher {
- stringstream bypassDomainsBuilder, proxyDomainsBuilder;
- RE2 *bypassDomains, *proxyDomains;
-
- ~AclMatcher() {
- if (bypassDomains) delete bypassDomains;
- if (proxyDomains) delete proxyDomains;
- }
-};
-
-bool addDomain(JNIEnv *env, stringstream &domains, jstring regex) {
- const char *regexChars = env->GetStringUTFChars(regex, nullptr);
- if (regexChars == nullptr) return false;
- if (domains.rdbuf()->in_avail()) domains << '|';
- domains << regexChars;
- env->ReleaseStringUTFChars(regex, regexChars);
- return true;
-}
-
-const char *buildRE2(stringstream &domains, RE2 *&out, const RE2::Options &options) {
- if (domains.rdbuf()->in_avail()) {
- out = new RE2(domains.str(), options);
- domains.clear();
- if (!out->ok()) return out->error().c_str();
- } else {
- delete out;
- out = nullptr;
- }
- return nullptr;
-}
-
-#pragma clang diagnostic push
-#pragma clang diagnostic ignored "-Wunused-parameter"
-extern "C" {
-JNIEXPORT jlong JNICALL Java_com_github_shadowsocks_acl_AclMatcher_init(JNIEnv *env, jclass clazz) {
- return reinterpret_cast(new AclMatcher());
-}
-
-JNIEXPORT void JNICALL
-Java_com_github_shadowsocks_acl_AclMatcher_close(JNIEnv *env, jclass clazz, jlong handle) {
- delete reinterpret_cast(handle);
-}
-
-JNIEXPORT jboolean JNICALL
-Java_com_github_shadowsocks_acl_AclMatcher_addBypassDomain(JNIEnv *env, jclass clazz, jlong handle,
- jstring regex) {
- return static_cast(handle &&
- ::addDomain(env, reinterpret_cast(handle)->bypassDomainsBuilder, regex));
-}
-
-JNIEXPORT jboolean JNICALL
-Java_com_github_shadowsocks_acl_AclMatcher_addProxyDomain(JNIEnv *env, jclass clazz, jlong handle,
- jstring regex) {
- return static_cast(handle &&
- ::addDomain(env, reinterpret_cast(handle)->proxyDomainsBuilder, regex));
-}
-
-JNIEXPORT jstring JNICALL
-Java_com_github_shadowsocks_acl_AclMatcher_build(JNIEnv *env, jclass clazz, jlong handle,
- jlong memory_limit) {
- if (!handle) return env->NewStringUTF("AclMatcher closed");
- auto matcher = reinterpret_cast(handle);
- RE2::Options options;
- options.set_max_mem(memory_limit);
- options.set_never_capture(true);
- const char *e = ::buildRE2(matcher->bypassDomainsBuilder, matcher->bypassDomains, options);
- if (e) return env->NewStringUTF(e);
- e = ::buildRE2(matcher->proxyDomainsBuilder, matcher->proxyDomains, options);
- if (e) return env->NewStringUTF(e);
- return nullptr;
-}
-
-JNIEXPORT jint JNICALL
-Java_com_github_shadowsocks_acl_AclMatcher_matchHost(JNIEnv *env, jclass clazz, jlong handle,
- jstring host) {
- if (!handle) return -1;
- auto matcher = reinterpret_cast(handle);
- const char *hostChars = env->GetStringUTFChars(host, nullptr);
- jint result = 0;
- if (matcher->bypassDomains && RE2::PartialMatch(hostChars, *matcher->bypassDomains)) result = 1;
- else if (matcher->proxyDomains && RE2::PartialMatch(hostChars, *matcher->proxyDomains)) result = 2;
- env->ReleaseStringUTFChars(host, hostChars);
- return result;
-}
-}
diff --git a/core/src/main/jni/libev b/core/src/main/jni/libev
deleted file mode 160000
index 31ca40b7a1..0000000000
--- a/core/src/main/jni/libev
+++ /dev/null
@@ -1 +0,0 @@
-Subproject commit 31ca40b7a18ed424213a4ecba0d57706ed3e56a0
diff --git a/core/src/main/jni/libsodium b/core/src/main/jni/libsodium
deleted file mode 160000
index b732443c44..0000000000
--- a/core/src/main/jni/libsodium
+++ /dev/null
@@ -1 +0,0 @@
-Subproject commit b732443c442239c2e0184820e9b23cca0de0828c
diff --git a/core/src/main/jni/mbedtls b/core/src/main/jni/mbedtls
deleted file mode 160000
index 9f4f8eec93..0000000000
--- a/core/src/main/jni/mbedtls
+++ /dev/null
@@ -1 +0,0 @@
-Subproject commit 9f4f8eec93dd1f32d78e0bcceddbef0ca570e66f
diff --git a/core/src/main/jni/patch/pcre/pcre_chartables.c b/core/src/main/jni/patch/pcre/pcre_chartables.c
deleted file mode 100644
index 1e20ec29d0..0000000000
--- a/core/src/main/jni/patch/pcre/pcre_chartables.c
+++ /dev/null
@@ -1,198 +0,0 @@
-/*************************************************
-* Perl-Compatible Regular Expressions *
-*************************************************/
-
-/* This file contains character tables that are used when no external tables
-are passed to PCRE by the application that calls it. The tables are used only
-for characters whose code values are less than 256.
-
-This is a default version of the tables that assumes ASCII encoding. A program
-called dftables (which is distributed with PCRE) can be used to build
-alternative versions of this file. This is necessary if you are running in an
-EBCDIC environment, or if you want to default to a different encoding, for
-example ISO-8859-1. When dftables is run, it creates these tables in the
-current locale. If PCRE is configured with --enable-rebuild-chartables, this
-happens automatically.
-
-The following #includes are present because without them gcc 4.x may remove the
-array definition from the final binary if PCRE is built into a static library
-and dead code stripping is activated. This leads to link errors. Pulling in the
-header ensures that the array gets flagged as "someone outside this compilation
-unit might reference this" and so it will always be supplied to the linker. */
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include "pcre_internal.h"
-
-const pcre_uint8 PRIV(default_tables)[] = {
-
-/* This table is a lower casing table. */
-
- 0, 1, 2, 3, 4, 5, 6, 7,
- 8, 9, 10, 11, 12, 13, 14, 15,
- 16, 17, 18, 19, 20, 21, 22, 23,
- 24, 25, 26, 27, 28, 29, 30, 31,
- 32, 33, 34, 35, 36, 37, 38, 39,
- 40, 41, 42, 43, 44, 45, 46, 47,
- 48, 49, 50, 51, 52, 53, 54, 55,
- 56, 57, 58, 59, 60, 61, 62, 63,
- 64, 97, 98, 99,100,101,102,103,
- 104,105,106,107,108,109,110,111,
- 112,113,114,115,116,117,118,119,
- 120,121,122, 91, 92, 93, 94, 95,
- 96, 97, 98, 99,100,101,102,103,
- 104,105,106,107,108,109,110,111,
- 112,113,114,115,116,117,118,119,
- 120,121,122,123,124,125,126,127,
- 128,129,130,131,132,133,134,135,
- 136,137,138,139,140,141,142,143,
- 144,145,146,147,148,149,150,151,
- 152,153,154,155,156,157,158,159,
- 160,161,162,163,164,165,166,167,
- 168,169,170,171,172,173,174,175,
- 176,177,178,179,180,181,182,183,
- 184,185,186,187,188,189,190,191,
- 192,193,194,195,196,197,198,199,
- 200,201,202,203,204,205,206,207,
- 208,209,210,211,212,213,214,215,
- 216,217,218,219,220,221,222,223,
- 224,225,226,227,228,229,230,231,
- 232,233,234,235,236,237,238,239,
- 240,241,242,243,244,245,246,247,
- 248,249,250,251,252,253,254,255,
-
-/* This table is a case flipping table. */
-
- 0, 1, 2, 3, 4, 5, 6, 7,
- 8, 9, 10, 11, 12, 13, 14, 15,
- 16, 17, 18, 19, 20, 21, 22, 23,
- 24, 25, 26, 27, 28, 29, 30, 31,
- 32, 33, 34, 35, 36, 37, 38, 39,
- 40, 41, 42, 43, 44, 45, 46, 47,
- 48, 49, 50, 51, 52, 53, 54, 55,
- 56, 57, 58, 59, 60, 61, 62, 63,
- 64, 97, 98, 99,100,101,102,103,
- 104,105,106,107,108,109,110,111,
- 112,113,114,115,116,117,118,119,
- 120,121,122, 91, 92, 93, 94, 95,
- 96, 65, 66, 67, 68, 69, 70, 71,
- 72, 73, 74, 75, 76, 77, 78, 79,
- 80, 81, 82, 83, 84, 85, 86, 87,
- 88, 89, 90,123,124,125,126,127,
- 128,129,130,131,132,133,134,135,
- 136,137,138,139,140,141,142,143,
- 144,145,146,147,148,149,150,151,
- 152,153,154,155,156,157,158,159,
- 160,161,162,163,164,165,166,167,
- 168,169,170,171,172,173,174,175,
- 176,177,178,179,180,181,182,183,
- 184,185,186,187,188,189,190,191,
- 192,193,194,195,196,197,198,199,
- 200,201,202,203,204,205,206,207,
- 208,209,210,211,212,213,214,215,
- 216,217,218,219,220,221,222,223,
- 224,225,226,227,228,229,230,231,
- 232,233,234,235,236,237,238,239,
- 240,241,242,243,244,245,246,247,
- 248,249,250,251,252,253,254,255,
-
-/* This table contains bit maps for various character classes. Each map is 32
-bytes long and the bits run from the least significant end of each byte. The
-classes that have their own maps are: space, xdigit, digit, upper, lower, word,
-graph, print, punct, and cntrl. Other classes are built from combinations. */
-
- 0x00,0x3e,0x00,0x00,0x01,0x00,0x00,0x00,
- 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
- 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
- 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
-
- 0x00,0x00,0x00,0x00,0x00,0x00,0xff,0x03,
- 0x7e,0x00,0x00,0x00,0x7e,0x00,0x00,0x00,
- 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
- 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
-
- 0x00,0x00,0x00,0x00,0x00,0x00,0xff,0x03,
- 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
- 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
- 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
-
- 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
- 0xfe,0xff,0xff,0x07,0x00,0x00,0x00,0x00,
- 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
- 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
-
- 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
- 0x00,0x00,0x00,0x00,0xfe,0xff,0xff,0x07,
- 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
- 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
-
- 0x00,0x00,0x00,0x00,0x00,0x00,0xff,0x03,
- 0xfe,0xff,0xff,0x87,0xfe,0xff,0xff,0x07,
- 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
- 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
-
- 0x00,0x00,0x00,0x00,0xfe,0xff,0xff,0xff,
- 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x7f,
- 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
- 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
-
- 0x00,0x00,0x00,0x00,0xff,0xff,0xff,0xff,
- 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x7f,
- 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
- 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
-
- 0x00,0x00,0x00,0x00,0xfe,0xff,0x00,0xfc,
- 0x01,0x00,0x00,0xf8,0x01,0x00,0x00,0x78,
- 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
- 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
-
- 0xff,0xff,0xff,0xff,0x00,0x00,0x00,0x00,
- 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x80,
- 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
- 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
-
-/* This table identifies various classes of character by individual bits:
- 0x01 white space character
- 0x02 letter
- 0x04 decimal digit
- 0x08 hexadecimal digit
- 0x10 alphanumeric or '_'
- 0x80 regular expression metacharacter or binary zero
-*/
-
- 0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 0- 7 */
- 0x00,0x01,0x01,0x01,0x01,0x01,0x00,0x00, /* 8- 15 */
- 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 16- 23 */
- 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 24- 31 */
- 0x01,0x00,0x00,0x00,0x80,0x00,0x00,0x00, /* - ' */
- 0x80,0x80,0x80,0x80,0x00,0x00,0x80,0x00, /* ( - / */
- 0x1c,0x1c,0x1c,0x1c,0x1c,0x1c,0x1c,0x1c, /* 0 - 7 */
- 0x1c,0x1c,0x00,0x00,0x00,0x00,0x00,0x80, /* 8 - ? */
- 0x00,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x12, /* @ - G */
- 0x12,0x12,0x12,0x12,0x12,0x12,0x12,0x12, /* H - O */
- 0x12,0x12,0x12,0x12,0x12,0x12,0x12,0x12, /* P - W */
- 0x12,0x12,0x12,0x80,0x80,0x00,0x80,0x10, /* X - _ */
- 0x00,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x12, /* ` - g */
- 0x12,0x12,0x12,0x12,0x12,0x12,0x12,0x12, /* h - o */
- 0x12,0x12,0x12,0x12,0x12,0x12,0x12,0x12, /* p - w */
- 0x12,0x12,0x12,0x80,0x80,0x00,0x00,0x00, /* x -127 */
- 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 128-135 */
- 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 136-143 */
- 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 144-151 */
- 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 152-159 */
- 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 160-167 */
- 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 168-175 */
- 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 176-183 */
- 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 184-191 */
- 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 192-199 */
- 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 200-207 */
- 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 208-215 */
- 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 216-223 */
- 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 224-231 */
- 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 232-239 */
- 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 240-247 */
- 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};/* 248-255 */
-
-/* End of pcre_chartables.c */
diff --git a/core/src/main/jni/pcre b/core/src/main/jni/pcre
deleted file mode 160000
index 222bbf4b3f..0000000000
--- a/core/src/main/jni/pcre
+++ /dev/null
@@ -1 +0,0 @@
-Subproject commit 222bbf4b3fb8e13c21686803e47e31aa3e4ad130
diff --git a/core/src/main/jni/re2 b/core/src/main/jni/re2
deleted file mode 160000
index bb8e777557..0000000000
--- a/core/src/main/jni/re2
+++ /dev/null
@@ -1 +0,0 @@
-Subproject commit bb8e777557ddbdeabdedea4f23613c5021ffd7b1
diff --git a/core/src/main/jni/shadowsocks-libev b/core/src/main/jni/shadowsocks-libev
deleted file mode 160000
index 6b5025bf74..0000000000
--- a/core/src/main/jni/shadowsocks-libev
+++ /dev/null
@@ -1 +0,0 @@
-Subproject commit 6b5025bf741cff93212ba048353eb3d2c02b5c46
diff --git a/core/src/main/res/values/arrays.xml b/core/src/main/res/values/arrays.xml
index 62398ca903..37d0095104 100644
--- a/core/src/main/res/values/arrays.xml
+++ b/core/src/main/res/values/arrays.xml
@@ -1,6 +1,7 @@
+ - PLAIN
- RC4-MD5
- AES-128-CFB
- AES-192-CFB
@@ -23,6 +24,7 @@
+ - plain
- rc4-md5
- aes-128-cfb
- aes-192-cfb
@@ -212,4 +214,4 @@
- vpn
- transproxy
-
\ No newline at end of file
+
diff --git a/core/src/main/rust/shadowsocks-rust b/core/src/main/rust/shadowsocks-rust
new file mode 160000
index 0000000000..246b6c48bc
--- /dev/null
+++ b/core/src/main/rust/shadowsocks-rust
@@ -0,0 +1 @@
+Subproject commit 246b6c48bce6d4a83af046bd3feb4843f772b9d2
diff --git a/detekt.yml b/detekt.yml
index 235590d0ca..4874946f52 100644
--- a/detekt.yml
+++ b/detekt.yml
@@ -1,4 +1,4 @@
-# https://github.com/arturbosch/detekt/blob/1.5.0/detekt-cli/src/main/resources/default-detekt-config.yml
+# https://github.com/arturbosch/detekt/blob/1.7.1/detekt-cli/src/main/resources/default-detekt-config.yml
comments:
active: false
@@ -12,6 +12,7 @@ complexity:
active: true
threshold: 10
includeStaticDeclarations: false
+ includePrivateDeclarations: false
ComplexMethod:
active: true
threshold: 15
@@ -21,7 +22,7 @@ complexity:
nestingFunctions: run,let,apply,with,also,use,forEach,isNotNull,ifNull
LabeledExpression:
active: false
- ignoredLabels: ""
+ ignoredLabels: ''
LargeClass:
active: true
threshold: 600
@@ -30,8 +31,10 @@ complexity:
threshold: 60
LongParameterList:
active: true
- threshold: 6
+ functionThreshold: 6
+ constructorThreshold: 7
ignoreDefaultParameters: true
+ ignoreDataClasses: true
MethodOverloading:
active: false
NestedBlockDepth:
@@ -39,14 +42,14 @@ complexity:
threshold: 4
StringLiteralDuplication:
active: true
- excludes: "**/test/**,**/androidTest/**,**/*.Test.kt,**/*.Spec.kt,**/*.Spek.kt"
+ excludes: '**/test/**,**/androidTest/**,**/*.Test.kt,**/*.Spec.kt,**/*.Spek.kt'
threshold: 3
ignoreAnnotation: true
excludeStringsWithLessThan5Characters: true
ignoreStringsRegex: '$^'
TooManyFunctions:
active: true
- excludes: "**/test/**,**/androidTest/**,**/*.Test.kt,**/*.Spec.kt,**/*.Spek.kt"
+ excludes: '**/test/**,**/androidTest/**,**/*.Test.kt,**/*.Spec.kt,**/*.Spek.kt'
thresholdInFiles: 11
thresholdInClasses: 11
thresholdInInterfaces: 11
@@ -67,7 +70,7 @@ empty-blocks:
active: true
EmptyCatchBlock:
active: true
- allowedExceptionNameRegex: "^(_|(ignore|expected).*)"
+ allowedExceptionNameRegex: '^(_|(ignore|expected).*)'
EmptyClassBlock:
active: true
EmptyDefaultConstructor:
@@ -91,6 +94,8 @@ empty-blocks:
active: true
EmptySecondaryConstructor:
active: true
+ EmptyTryBlock:
+ active: true
EmptyWhenBlock:
active: true
EmptyWhileBlock:
@@ -115,7 +120,7 @@ exceptions:
SwallowedException:
active: true
ignoredExceptionTypes: 'InterruptedException,NumberFormatException,ParseException,MalformedURLException'
- allowedExceptionNameRegex: "^(_|(ignore|expected).*)"
+ allowedExceptionNameRegex: '^(_|(ignore|expected).*)'
ThrowingExceptionFromFinally:
active: false
ThrowingExceptionInMain:
@@ -127,7 +132,7 @@ exceptions:
active: true
TooGenericExceptionCaught:
active: true
- excludes: "**/test/**,**/androidTest/**,**/*.Test.kt,**/*.Spec.kt,**/*.Spek.kt"
+ excludes: '**/test/**,**/androidTest/**,**/*.Test.kt,**/*.Spec.kt,**/*.Spek.kt'
exceptionNames:
- ArrayIndexOutOfBoundsException
- Error
@@ -137,7 +142,7 @@ exceptions:
- IndexOutOfBoundsException
- RuntimeException
- Throwable
- allowedExceptionNameRegex: "^(_|(ignore|expected).*)"
+ allowedExceptionNameRegex: '^(_|(ignore|expected).*)'
TooGenericExceptionThrown:
active: true
exceptionNames:
@@ -166,6 +171,7 @@ formatting:
FinalNewline:
active: true
autoCorrect: true
+ insertFinalNewLine: true
ImportOrdering:
active: false
Indentation:
@@ -253,37 +259,37 @@ naming:
ClassNaming:
active: true
classPattern: '[A-Z$][a-zA-Z0-9$]*'
- excludes: "**/test/**,**/androidTest/**,**/*.Test.kt,**/*.Spec.kt,**/*.Spek.kt"
+ excludes: '**/test/**,**/androidTest/**,**/*.Test.kt,**/*.Spec.kt,**/*.Spek.kt'
ConstructorParameterNaming:
active: true
- excludes: "**/test/**,**/androidTest/**,**/*.Test.kt,**/*.Spec.kt,**/*.Spek.kt"
+ excludes: '**/test/**,**/androidTest/**,**/*.Test.kt,**/*.Spec.kt,**/*.Spek.kt'
parameterPattern: '[a-z][A-Za-z0-9]*'
privateParameterPattern: '[a-z][A-Za-z0-9]*'
excludeClassPattern: '$^'
ignoreOverridden: true
EnumNaming:
active: true
- excludes: "**/test/**,**/androidTest/**,**/*.Test.kt,**/*.Spec.kt,**/*.Spek.kt"
+ excludes: '**/test/**,**/androidTest/**,**/*.Test.kt,**/*.Spec.kt,**/*.Spek.kt'
enumEntryPattern: '^[A-Z][_a-zA-Z0-9]*'
ForbiddenClassName:
active: true
- excludes: "**/test/**,**/androidTest/**,**/*.Test.kt,**/*.Spec.kt,**/*.Spek.kt"
+ excludes: '**/test/**,**/androidTest/**,**/*.Test.kt,**/*.Spec.kt,**/*.Spek.kt'
forbiddenName: ''
FunctionMaxLength:
active: true
- excludes: "**/test/**,**/androidTest/**,**/*.Test.kt,**/*.Spec.kt,**/*.Spek.kt"
+ excludes: '**/test/**,**/androidTest/**,**/*.Test.kt,**/*.Spec.kt,**/*.Spek.kt'
maximumFunctionNameLength: 30
FunctionMinLength:
active: false
FunctionNaming:
active: true
- excludes: "**/test/**,**/androidTest/**,**/*.Test.kt,**/*.Spec.kt,**/*.Spek.kt"
+ excludes: '**/test/**,**/androidTest/**,**/*.Test.kt,**/*.Spec.kt,**/*.Spek.kt'
functionPattern: '^([a-z$][a-zA-Z$0-9]*)|(`.*`)$'
excludeClassPattern: '$^'
ignoreOverridden: true
FunctionParameterNaming:
active: true
- excludes: "**/test/**,**/androidTest/**,**/*.Test.kt,**/*.Spec.kt,**/*.Spek.kt"
+ excludes: '**/test/**,**/androidTest/**,**/*.Test.kt,**/*.Spec.kt,**/*.Spek.kt'
parameterPattern: '[a-z][A-Za-z0-9]*'
excludeClassPattern: '$^'
ignoreOverridden: true
@@ -292,33 +298,34 @@ naming:
rootPackage: ''
MatchingDeclarationName:
active: true
+ mustBeFirst: true
MemberNameEqualsClassName:
active: false
ObjectPropertyNaming:
active: true
- excludes: "**/test/**,**/androidTest/**,**/*.Test.kt,**/*.Spec.kt,**/*.Spek.kt"
+ excludes: '**/test/**,**/androidTest/**,**/*.Test.kt,**/*.Spec.kt,**/*.Spek.kt'
constantPattern: '[A-Za-z][_A-Za-z0-9]*'
propertyPattern: '[A-Za-z][_A-Za-z0-9]*'
privatePropertyPattern: '(_)?[A-Za-z][_A-Za-z0-9]*'
PackageNaming:
active: true
- excludes: "**/test/**,**/androidTest/**,**/*.Test.kt,**/*.Spec.kt,**/*.Spek.kt"
+ excludes: '**/test/**,**/androidTest/**,**/*.Test.kt,**/*.Spec.kt,**/*.Spek.kt'
packagePattern: '^[a-z]+(\.[a-z][A-Za-z0-9]*)*$'
TopLevelPropertyNaming:
active: true
- excludes: "**/test/**,**/androidTest/**,**/*.Test.kt,**/*.Spec.kt,**/*.Spek.kt"
+ excludes: '**/test/**,**/androidTest/**,**/*.Test.kt,**/*.Spec.kt,**/*.Spek.kt'
constantPattern: '[A-Z][_A-Z0-9]*'
propertyPattern: '[A-Za-z][_A-Za-z0-9]*'
privatePropertyPattern: '_?[A-Za-z][_A-Za-z0-9]*'
VariableMaxLength:
active: true
- excludes: "**/test/**,**/androidTest/**,**/*.Test.kt,**/*.Spec.kt,**/*.Spek.kt"
+ excludes: '**/test/**,**/androidTest/**,**/*.Test.kt,**/*.Spec.kt,**/*.Spek.kt'
maximumVariableNameLength: 64
VariableMinLength:
active: false
VariableNaming:
active: true
- excludes: "**/test/**,**/androidTest/**,**/*.Test.kt,**/*.Spec.kt,**/*.Spek.kt"
+ excludes: '**/test/**,**/androidTest/**,**/*.Test.kt,**/*.Spec.kt,**/*.Spek.kt'
variablePattern: '[a-z][A-Za-z0-9]*'
privateVariablePattern: '(_)?[a-z][A-Za-z0-9]*'
excludeClassPattern: '$^'
@@ -330,10 +337,10 @@ performance:
active: true
ForEachOnRange:
active: true
- excludes: "**/test/**,**/androidTest/**,**/*.Test.kt,**/*.Spec.kt,**/*.Spek.kt"
+ excludes: '**/test/**,**/androidTest/**,**/*.Test.kt,**/*.Spec.kt,**/*.Spek.kt'
SpreadOperator:
active: true
- excludes: "**/test/**,**/androidTest/**,**/*.Test.kt,**/*.Spec.kt,**/*.Spek.kt"
+ excludes: '**/test/**,**/androidTest/**,**/*.Test.kt,**/*.Spec.kt,**/*.Spek.kt'
UnnecessaryTemporaryInstantiation:
active: true
@@ -402,11 +409,11 @@ style:
ForbiddenComment:
active: true
values: 'TODO:,FIXME:,STOPSHIP:'
- allowedPatterns: ""
+ allowedPatterns: ''
ForbiddenImport:
active: true
- imports: ''
- forbiddenPatterns: ""
+ imports: []
+ forbiddenPatterns: ''
ForbiddenMethodCall:
active: true
methods: ''
@@ -421,7 +428,7 @@ style:
active: true
ignoreOverridableFunction: true
excludedFunctions: 'describeContents'
- excludeAnnotatedFunction: "dagger.Provides"
+ excludeAnnotatedFunction: 'dagger.Provides'
LibraryCodeMustSpecifyReturnType:
active: true
LoopWithTooManyJumpStatements:
@@ -477,8 +484,7 @@ style:
UnderscoresInNumericLiterals:
active: false
UnnecessaryAbstractClass:
- active: true
- excludeAnnotatedClasses: "dagger.Module"
+ active: false
UnnecessaryAnnotationUseSiteTarget:
active: true
UnnecessaryApply:
@@ -497,7 +503,7 @@ style:
active: true
UnusedPrivateMember:
active: true
- allowedNames: "(_|ignored|expected|serialVersionUID)"
+ allowedNames: '(_|ignored|expected|serialVersionUID)'
UseArrayLiteralsInAnnotations:
active: true
UseCheckOrError:
diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties
index 4e1cc9db6b..6623300beb 100644
--- a/gradle/wrapper/gradle-wrapper.properties
+++ b/gradle/wrapper/gradle-wrapper.properties
@@ -1,5 +1,5 @@
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
-distributionUrl=https\://services.gradle.org/distributions/gradle-6.1.1-all.zip
+distributionUrl=https\://services.gradle.org/distributions/gradle-6.3-all.zip
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists
diff --git a/gradlew.bat b/gradlew.bat
index 24467a141f..9109989e3c 100644
--- a/gradlew.bat
+++ b/gradlew.bat
@@ -29,6 +29,9 @@ if "%DIRNAME%" == "" set DIRNAME=.
set APP_BASE_NAME=%~n0
set APP_HOME=%DIRNAME%
+@rem Resolve any "." and ".." in APP_HOME to make it shorter.
+for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi
+
@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m"
diff --git a/mobile/build.gradle b/mobile/build.gradle
index 2a33042c93..890d5064ab 100644
--- a/mobile/build.gradle
+++ b/mobile/build.gradle
@@ -66,12 +66,12 @@ dependencies {
implementation 'androidx.browser:browser:1.2.0'
implementation 'androidx.constraintlayout:constraintlayout:2.0.0-beta4'
implementation "androidx.lifecycle:lifecycle-runtime-ktx:$lifecycleVersion"
- implementation 'com.google.android.gms:play-services-vision:19.0.0'
- implementation 'com.google.firebase:firebase-ads:18.3.0'
+ implementation 'com.google.android.gms:play-services-vision:20.0.0'
+ implementation 'com.google.firebase:firebase-ads:19.1.0'
implementation 'com.google.zxing:core:3.4.0'
implementation 'com.takisoft.preferencex:preferencex-simplemenu:1.1.0'
implementation 'com.twofortyfouram:android-plugin-api-for-locale:1.0.4'
- implementation 'me.zhanghai.android.fastscroll:library:1.1.0'
+ implementation 'me.zhanghai.android.fastscroll:library:1.1.2'
implementation 'xyz.belvi.mobilevision:barcodescanner:2.0.3'
testImplementation "junit:junit:$junitVersion"
androidTestImplementation "androidx.test:runner:$androidTestVersion"
diff --git a/mobile/src/main/java/com/github/shadowsocks/AdsManager.kt b/mobile/src/main/java/com/github/shadowsocks/AdsManager.kt
new file mode 100644
index 0000000000..4ebb8fa8b8
--- /dev/null
+++ b/mobile/src/main/java/com/github/shadowsocks/AdsManager.kt
@@ -0,0 +1,41 @@
+/*******************************************************************************
+ * *
+ * Copyright (C) 2020 by Max Lv *
+ * Copyright (C) 2020 by Mygod Studio *
+ * *
+ * 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 com.github.shadowsocks
+
+import android.content.Context
+import com.google.android.gms.ads.AdLoader
+import com.google.android.gms.ads.AdRequest
+import com.google.android.gms.ads.MobileAds
+import com.google.android.gms.ads.RequestConfiguration
+
+internal object AdsManager {
+ init {
+ MobileAds.setRequestConfiguration(RequestConfiguration.Builder().apply {
+ setTestDeviceIds(listOf(
+ "B08FC1764A7B250E91EA9D0D5EBEB208", "7509D18EB8AF82F915874FEF53877A64",
+ "F58907F28184A828DD0DB6F8E38189C6", "FE983F496D7C5C1878AA163D9420CA97"))
+ }.build())
+ }
+
+ fun load(context: Context?, setup: AdLoader.Builder.() -> Unit) =
+ AdLoader.Builder(context, "ca-app-pub-3283768469187309/8632513739").apply(setup).build()
+ .loadAd(AdRequest.Builder().build())
+}
diff --git a/mobile/src/main/java/com/github/shadowsocks/GlobalSettingsPreferenceFragment.kt b/mobile/src/main/java/com/github/shadowsocks/GlobalSettingsPreferenceFragment.kt
index 76a9e2e64b..7e8efe9487 100644
--- a/mobile/src/main/java/com/github/shadowsocks/GlobalSettingsPreferenceFragment.kt
+++ b/mobile/src/main/java/com/github/shadowsocks/GlobalSettingsPreferenceFragment.kt
@@ -91,25 +91,17 @@ class GlobalSettingsPreferenceFragment : PreferenceFragmentCompat() {
val portTransproxy = findPreference(Key.portTransproxy)!!
portTransproxy.setOnBindEditTextListener(EditTextPreferenceModifiers.Port)
val onServiceModeChange = Preference.OnPreferenceChangeListener { _, newValue ->
- val (enabledLocalDns, enabledTransproxy) = when (newValue as String?) {
- Key.modeProxy -> Pair(false, false)
- Key.modeVpn -> Pair(true, false)
- Key.modeTransproxy -> Pair(true, true)
- else -> throw IllegalArgumentException("newValue: $newValue")
- }
- hosts.isEnabled = enabledLocalDns
- portLocalDns.isEnabled = enabledLocalDns
- portTransproxy.isEnabled = enabledTransproxy
+ portTransproxy.isEnabled = newValue as String? == Key.modeTransproxy
true
}
val listener: (BaseService.State) -> Unit = {
val stopped = it == BaseService.State.Stopped
tfo.isEnabled = stopped
+ hosts.isEnabled = stopped
serviceMode.isEnabled = stopped
portProxy.isEnabled = stopped
+ portLocalDns.isEnabled = stopped
if (stopped) onServiceModeChange.onPreferenceChange(null, DataStore.serviceMode) else {
- hosts.isEnabled = false
- portLocalDns.isEnabled = false
portTransproxy.isEnabled = false
}
}
diff --git a/mobile/src/main/java/com/github/shadowsocks/ProfileConfigFragment.kt b/mobile/src/main/java/com/github/shadowsocks/ProfileConfigFragment.kt
index 8071e97e77..838e932568 100644
--- a/mobile/src/main/java/com/github/shadowsocks/ProfileConfigFragment.kt
+++ b/mobile/src/main/java/com/github/shadowsocks/ProfileConfigFragment.kt
@@ -177,7 +177,7 @@ class ProfileConfigFragment : PreferenceFragmentCompat(),
DataStore.dirty = true
true
} catch (exc: RuntimeException) {
- Snackbar.make(view!!, exc.readableMessage, Snackbar.LENGTH_LONG).show()
+ Snackbar.make(requireView(), exc.readableMessage, Snackbar.LENGTH_LONG).show()
false
}
@@ -217,7 +217,9 @@ class ProfileConfigFragment : PreferenceFragmentCompat(),
plugin.value = pluginConfiguration.selected
pluginConfigure.isEnabled = selected !is NoPlugin
pluginConfigure.text = pluginConfiguration.getOptions().toString()
- if (!selected.trusted) Snackbar.make(view!!, R.string.plugin_untrusted, Snackbar.LENGTH_LONG).show()
+ if (!selected.trusted) {
+ Snackbar.make(requireView(), R.string.plugin_untrusted, Snackbar.LENGTH_LONG).show()
+ }
}
REQUEST_CODE_PLUGIN_CONFIGURE -> when (resultCode) {
Activity.RESULT_OK -> {
diff --git a/mobile/src/main/java/com/github/shadowsocks/ProfilesFragment.kt b/mobile/src/main/java/com/github/shadowsocks/ProfilesFragment.kt
index 26af06fc24..d6a2c00dd9 100644
--- a/mobile/src/main/java/com/github/shadowsocks/ProfilesFragment.kt
+++ b/mobile/src/main/java/com/github/shadowsocks/ProfilesFragment.kt
@@ -59,8 +59,6 @@ import com.github.shadowsocks.utils.readableMessage
import com.github.shadowsocks.widget.ListHolderListener
import com.github.shadowsocks.widget.MainListListener
import com.github.shadowsocks.widget.UndoSnackbarManager
-import com.google.android.gms.ads.AdLoader
-import com.google.android.gms.ads.AdRequest
import com.google.android.gms.ads.VideoOptions
import com.google.android.gms.ads.formats.NativeAdOptions
import com.google.android.gms.ads.formats.UnifiedNativeAd
@@ -249,7 +247,7 @@ class ProfilesFragment : ToolbarFragment(), Toolbar.OnMenuItemClickListener {
if (adHost != null || !item.isSponsored) return
if (nativeAdView == null) {
nativeAdView = layoutInflater.inflate(R.layout.ad_unified, adContainer, false) as UnifiedNativeAdView
- AdLoader.Builder(context, "ca-app-pub-3283768469187309/8632513739").apply {
+ AdsManager.load(context) {
forUnifiedNativeAd { unifiedNativeAd ->
// You must call destroy on old ads when you are done with them,
// otherwise you will have a memory leak.
@@ -262,12 +260,7 @@ class ProfilesFragment : ToolbarFragment(), Toolbar.OnMenuItemClickListener {
setStartMuted(true)
}.build())
}.build())
- }.build().loadAd(AdRequest.Builder().apply {
- addTestDevice("B08FC1764A7B250E91EA9D0D5EBEB208")
- addTestDevice("7509D18EB8AF82F915874FEF53877A64")
- addTestDevice("F58907F28184A828DD0DB6F8E38189C6")
- addTestDevice("FE983F496D7C5C1878AA163D9420CA97")
- }.build())
+ }
} else if (nativeAd != null) populateUnifiedNativeAdView(nativeAd!!, nativeAdView!!)
}
diff --git a/mobile/src/main/java/com/github/shadowsocks/subscription/SubscriptionFragment.kt b/mobile/src/main/java/com/github/shadowsocks/subscription/SubscriptionFragment.kt
index 786ed0585a..72171b241b 100644
--- a/mobile/src/main/java/com/github/shadowsocks/subscription/SubscriptionFragment.kt
+++ b/mobile/src/main/java/com/github/shadowsocks/subscription/SubscriptionFragment.kt
@@ -220,7 +220,7 @@ class SubscriptionFragment : ToolbarFragment(), Toolbar.OnMenuItemClickListener
toolbar.setTitle(R.string.subscriptions)
toolbar.inflateMenu(R.menu.subscription_menu)
toolbar.setOnMenuItemClickListener(this)
- SubscriptionService.idle.observe(this) {
+ SubscriptionService.idle.observe(viewLifecycleOwner) {
toolbar.menu.findItem(R.id.action_update_subscription).isEnabled = it
}
val activity = activity as MainActivity
diff --git a/mobile/src/main/res/raw/about.html b/mobile/src/main/res/raw/about.html
index f67992340e..2bd462d24b 100644
--- a/mobile/src/main/res/raw/about.html
+++ b/mobile/src/main/res/raw/about.html
@@ -20,14 +20,11 @@
Open Source Licenses