Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 4 additions & 8 deletions core/src/main/java/com/github/shadowsocks/bg/BaseService.kt
Original file line number Diff line number Diff line change
Expand Up @@ -35,10 +35,8 @@ 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.Action
import com.github.shadowsocks.utils.Key
import com.github.shadowsocks.utils.broadcastReceiver
import com.github.shadowsocks.utils.readableMessage
import com.google.firebase.analytics.FirebaseAnalytics
Expand Down Expand Up @@ -239,7 +237,7 @@ object BaseService {

val isVpnService get() = false

suspend fun startProcesses(hosts: HostsFile) {
suspend fun startProcesses() {
val configRoot = (if (Build.VERSION.SDK_INT < 24 || app.getSystemService<UserManager>()
?.isUserUnlocked != false) app else Core.deviceStorage).noBackupFilesDir
val udpFallback = data.udpFallback
Expand Down Expand Up @@ -315,7 +313,6 @@ object BaseService {
listOfNotNull(data.proxy, data.udpFallback).forEach { it.trafficMonitor?.persistStats(it.profile.id) }

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()
Expand Down Expand Up @@ -355,9 +352,8 @@ object BaseService {
try {
Executable.killAll() // clean up old processes
preInit()
val hosts = HostsFile(DataStore.publicStore.getString(Key.hosts) ?: "")
proxy.init(this@Interface, hosts)
data.udpFallback?.init(this@Interface, hosts)
proxy.init(this@Interface)
data.udpFallback?.init(this@Interface)
if (profile.route == Acl.CUSTOM_RULES) try {
withContext(Dispatchers.IO) {
Acl.customRules.flatten(10, this@Interface::openConnection).also {
Expand All @@ -372,7 +368,7 @@ object BaseService {
Timber.w(it)
stopRunner(false, it.readableMessage)
}
startProcesses(hosts)
startProcesses()

proxy.scheduleUpdate()
data.udpFallback?.scheduleUpdate()
Expand Down
25 changes: 5 additions & 20 deletions core/src/main/java/com/github/shadowsocks/bg/ProxyInstance.kt
Original file line number Diff line number Diff line change
Expand Up @@ -26,8 +26,6 @@ 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
import com.github.shadowsocks.preference.DataStore
Expand All @@ -52,7 +50,7 @@ class ProxyInstance(val profile: Profile, private val route: String = profile.ro
val plugin by lazy { PluginManager.init(PluginConfiguration(profile.plugin ?: "")) }
private var scheduleConfigUpdate = false

suspend fun init(service: BaseService.Interface, hosts: HostsFile) {
suspend fun init(service: BaseService.Interface) {
if (profile.isSponsored) {
scheduleConfigUpdate = true
val mdg = MessageDigest.getInstance("SHA-1")
Expand Down Expand Up @@ -86,23 +84,10 @@ class ProxyInstance(val profile: Profile, private val route: String = profile.ro

// it's hard to resolve DNS on a specific interface so we'll do it here
if (profile.host.parseNumericAddress() == null) {
profile.host = hosts.resolve(profile.host).run {
if (isEmpty()) try {
service.resolver(profile.host).firstOrNull()
} catch (_: IOException) {
null
} else {
val network = service.getActiveNetwork() ?: throw UnknownHostException()
val hasIpv4 = DnsResolverCompat.haveIpv4(network)
val hasIpv6 = DnsResolverCompat.haveIpv6(network)
firstOrNull {
when (it) {
is Inet4Address -> hasIpv4
is Inet6Address -> hasIpv6
else -> error(it)
}
}
}
profile.host = try {
service.resolver(profile.host).firstOrNull()
} catch (_: IOException) {
null
}?.hostAddress ?: throw UnknownHostException()
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,6 @@ package com.github.shadowsocks.bg
import android.app.Service
import android.content.Intent
import com.github.shadowsocks.Core
import com.github.shadowsocks.net.HostsFile
import com.github.shadowsocks.preference.DataStore
import java.io.File

Expand Down Expand Up @@ -57,9 +56,9 @@ redsocks {
File(applicationInfo.nativeLibraryDir, Executable.REDSOCKS).absolutePath, "-c", "redsocks.conf"))
}

override suspend fun startProcesses(hosts: HostsFile) {
override suspend fun startProcesses() {
startRedsocksDaemon()
super.startProcesses(hosts)
super.startProcesses()
}

override fun onDestroy() {
Expand Down
10 changes: 6 additions & 4 deletions core/src/main/java/com/github/shadowsocks/bg/VpnService.kt
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,10 @@ 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.*
import com.github.shadowsocks.net.ConcurrentLocalSocketListener
import com.github.shadowsocks.net.DefaultNetworkListener
import com.github.shadowsocks.net.DnsResolverCompat
import com.github.shadowsocks.net.Subnet
import com.github.shadowsocks.preference.DataStore
import com.github.shadowsocks.utils.Key
import com.github.shadowsocks.utils.closeQuietly
Expand Down Expand Up @@ -137,17 +140,16 @@ class VpnService : BaseVpnService(), BaseService.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) {
override suspend fun startProcesses() {
worker = ProtectWorker().apply { start() }
super.startProcesses(hosts)
super.startProcesses()
sendFd(startVpn())
}

Expand Down
40 changes: 0 additions & 40 deletions core/src/main/java/com/github/shadowsocks/net/DnsResolverCompat.kt
Original file line number Diff line number Diff line change
Expand Up @@ -29,14 +29,10 @@ import android.os.CancellationSignal
import android.os.Looper
import android.system.ErrnoException
import android.system.Os
import android.system.OsConstants
import com.github.shadowsocks.Core
import com.github.shadowsocks.utils.closeQuietly
import com.github.shadowsocks.utils.int
import com.github.shadowsocks.utils.parseNumericAddress
import kotlinx.coroutines.*
import org.xbill.DNS.*
import timber.log.Timber
import java.io.FileDescriptor
import java.io.IOException
import java.net.Inet4Address
Expand All @@ -58,42 +54,6 @@ sealed class DnsResolverCompat {
}
}

/**
* Based on: https://android.googlesource.com/platform/frameworks/base/+/9f97f97/core/java/android/net/util/DnsUtils.java#341
*/
private val address4 = "8.8.8.8".parseNumericAddress()!!
private val address6 = "2000::".parseNumericAddress()!!
suspend fun haveIpv4(network: Network) = checkConnectivity(network, OsConstants.AF_INET, address4)
suspend fun haveIpv6(network: Network) = checkConnectivity(network, OsConstants.AF_INET6, address6)
private suspend fun checkConnectivity(network: Network, domain: Int, addr: InetAddress) = try {
val socket = Os.socket(domain, OsConstants.SOCK_DGRAM, OsConstants.IPPROTO_UDP)
try {
instance.bindSocket(network, socket)
instance.connectUdp(socket, addr)
} finally {
socket.closeQuietly()
}
true
} catch (e: IOException) {
if ((e.cause as? ErrnoException)?.errno == OsConstants.EPERM) checkConnectivity(network, addr) else false
} catch (_: ErrnoException) {
false
} catch (e: ReflectiveOperationException) {
check(Build.VERSION.SDK_INT < 23)
Timber.w(e)
checkConnectivity(network, addr)
}
private fun checkConnectivity(network: Network, addr: InetAddress): Boolean {
return Core.connectivity.getLinkProperties(network)?.routes?.any {
try {
it.matches(addr)
} catch (e: RuntimeException) {
Timber.w(e)
false
}
} == true
}

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)
Expand Down
38 changes: 0 additions & 38 deletions core/src/main/java/com/github/shadowsocks/net/HostsFile.kt

This file was deleted.

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,6 @@ object Key {

const val dirty = "profileDirty"

const val hosts = "hosts"
const val assetUpdateTime = "assetUpdateTime"

// TV specific values
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,8 +20,6 @@

package com.github.shadowsocks

import android.app.Activity
import android.content.Intent
import android.os.Build
import android.os.Bundle
import android.view.View
Expand All @@ -30,24 +28,14 @@ import androidx.preference.Preference
import androidx.preference.PreferenceFragmentCompat
import androidx.preference.SwitchPreference
import com.github.shadowsocks.bg.BaseService
import com.github.shadowsocks.plugin.showAllowingStateLoss
import com.github.shadowsocks.preference.BrowsableEditTextPreferenceDialogFragment
import com.github.shadowsocks.preference.DataStore
import com.github.shadowsocks.preference.EditTextPreferenceModifiers
import com.github.shadowsocks.preference.HostsSummaryProvider
import com.github.shadowsocks.utils.DirectBoot
import com.github.shadowsocks.utils.Key
import com.github.shadowsocks.utils.readableMessage
import com.github.shadowsocks.utils.remove
import com.github.shadowsocks.widget.MainListListener

class GlobalSettingsPreferenceFragment : PreferenceFragmentCompat() {
companion object {
private const val REQUEST_BROWSE = 1
}

private val hosts by lazy { findPreference<EditTextPreference>(Key.hosts)!! }

override fun onCreatePreferences(savedInstanceState: Bundle?, rootKey: String?) {
preferenceManager.preferenceDataStore = DataStore.publicStore
DataStore.initGlobal()
Expand All @@ -63,8 +51,6 @@ class GlobalSettingsPreferenceFragment : PreferenceFragmentCompat() {
true
} else canToggleLocked.remove()

hosts.setOnBindEditTextListener(EditTextPreferenceModifiers.Monospace)
hosts.summaryProvider = HostsSummaryProvider
val serviceMode = findPreference<Preference>(Key.serviceMode)!!
val portProxy = findPreference<EditTextPreference>(Key.portProxy)!!
portProxy.setOnBindEditTextListener(EditTextPreferenceModifiers.Port)
Expand All @@ -78,7 +64,6 @@ class GlobalSettingsPreferenceFragment : PreferenceFragmentCompat() {
}
val listener: (BaseService.State) -> Unit = {
val stopped = it == BaseService.State.Stopped
hosts.isEnabled = stopped
serviceMode.isEnabled = stopped
portProxy.isEnabled = stopped
portLocalDns.isEnabled = stopped
Expand All @@ -96,29 +81,6 @@ class GlobalSettingsPreferenceFragment : PreferenceFragmentCompat() {
listView.setOnApplyWindowInsetsListener(MainListListener)
}

override fun onDisplayPreferenceDialog(preference: Preference?) {
if (preference == hosts) BrowsableEditTextPreferenceDialogFragment().apply {
setKey(hosts.key)
setTargetFragment(this@GlobalSettingsPreferenceFragment, REQUEST_BROWSE)
}.showAllowingStateLoss(parentFragmentManager, hosts.key) else super.onDisplayPreferenceDialog(preference)
}

override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
when (requestCode) {
REQUEST_BROWSE -> {
if (resultCode != Activity.RESULT_OK) return
val activity = activity as MainActivity
try {
// we read and persist all its content here to avoid content URL permission issues
hosts.text = activity.contentResolver.openInputStream(data!!.data!!)!!.bufferedReader().readText()
} catch (e: Exception) {
activity.snackbar(e.readableMessage).show()
}
}
else -> super.onActivityResult(requestCode, resultCode, data)
}
}

override fun onDestroy() {
MainActivity.stateListener = null
super.onDestroy()
Expand Down
Loading