Commit 74e2935f authored by Mygod's avatar Mygod

Actually use underlying network

parent 0af45000
...@@ -20,7 +20,6 @@ ...@@ -20,7 +20,6 @@
package com.github.shadowsocks.bg package com.github.shadowsocks.bg
import android.annotation.TargetApi
import android.app.Service import android.app.Service
import android.content.Context import android.content.Context
import android.content.Intent import android.content.Intent
...@@ -29,7 +28,6 @@ import android.net.* ...@@ -29,7 +28,6 @@ import android.net.*
import android.os.Build import android.os.Build
import android.os.IBinder import android.os.IBinder
import android.os.ParcelFileDescriptor import android.os.ParcelFileDescriptor
import android.support.v4.os.BuildCompat
import android.util.Log import android.util.Log
import com.github.shadowsocks.App.Companion.app import com.github.shadowsocks.App.Companion.app
import com.github.shadowsocks.JniHelper import com.github.shadowsocks.JniHelper
...@@ -56,7 +54,8 @@ class VpnService : BaseVpnService(), LocalDnsService.Interface { ...@@ -56,7 +54,8 @@ class VpnService : BaseVpnService(), LocalDnsService.Interface {
private val getInt: Method = FileDescriptor::class.java.getDeclaredMethod("getInt$") private val getInt: Method = FileDescriptor::class.java.getDeclaredMethod("getInt$")
/** /**
* Unfortunately registerDefaultNetworkCallback is going to return our VPN interface: https://android.googlesource.com/platform/frameworks/base/+/dda156ab0c5d66ad82bdcf76cda07cbc0a9c8a2e * Unfortunately registerDefaultNetworkCallback is going to return VPN interface since Android P DP1:
* https://android.googlesource.com/platform/frameworks/base/+/dda156ab0c5d66ad82bdcf76cda07cbc0a9c8a2e
* *
* This makes doing a requestNetwork with REQUEST necessary so that we don't get ALL possible networks that * This makes doing a requestNetwork with REQUEST necessary so that we don't get ALL possible networks that
* satisfies default network capabilities but only THE default network. Unfortunately we need to have * satisfies default network capabilities but only THE default network. Unfortunately we need to have
...@@ -77,13 +76,22 @@ class VpnService : BaseVpnService(), LocalDnsService.Interface { ...@@ -77,13 +76,22 @@ class VpnService : BaseVpnService(), LocalDnsService.Interface {
var success = false var success = false
try { try {
socket.inputStream.read() socket.inputStream.read()
val fds = socket.ancillaryFileDescriptors val fd = socket.ancillaryFileDescriptors!!.single()!!
if (fds.isEmpty()) return val fdInt = getInt.invoke(fd) as Int
val fd = getInt.invoke(fds.first()) as Int try {
success = protect(fd) val network = underlyingNetwork
JniHelper.close(fd) // Trick to close file decriptor success = if (network != null && Build.VERSION.SDK_INT >= 23) {
network.bindSocket(fd)
true
} else protect(fdInt)
} catch (e: Exception) {
Log.e(tag, "Error when protect socket", e)
app.track(e)
} finally {
JniHelper.close(fdInt) // Trick to close file decriptor
}
} catch (e: Exception) { } catch (e: Exception) {
Log.e(tag, "Error when protect socket", e) Log.e(tag, "Error when receiving ancillary fd", e)
app.track(e) app.track(e)
} }
try { try {
...@@ -107,19 +115,23 @@ class VpnService : BaseVpnService(), LocalDnsService.Interface { ...@@ -107,19 +115,23 @@ class VpnService : BaseVpnService(), LocalDnsService.Interface {
private var conn: ParcelFileDescriptor? = null private var conn: ParcelFileDescriptor? = null
private var worker: ProtectWorker? = null private var worker: ProtectWorker? = null
private var tun2socksProcess: GuardedProcess? = null private var tun2socksProcess: GuardedProcess? = null
private var underlyingNetwork: Network? = null
set(value) {
if (Build.VERSION.SDK_INT >= 22) setUnderlyingNetworks(if (value == null) null else arrayOf(value))
field = value
}
private val connectivity by lazy { getSystemService(Context.CONNECTIVITY_SERVICE) as ConnectivityManager } private val connectivity by lazy { getSystemService(Context.CONNECTIVITY_SERVICE) as ConnectivityManager }
@TargetApi(Build.VERSION_CODES.P)
private val defaultNetworkCallback = object : ConnectivityManager.NetworkCallback() { private val defaultNetworkCallback = object : ConnectivityManager.NetworkCallback() {
override fun onAvailable(network: Network) { override fun onAvailable(network: Network) {
setUnderlyingNetworks(arrayOf(network)) underlyingNetwork = network
} }
override fun onCapabilitiesChanged(network: Network, networkCapabilities: NetworkCapabilities?) { override fun onCapabilitiesChanged(network: Network, networkCapabilities: NetworkCapabilities?) {
// it's a good idea to refresh capabilities // it's a good idea to refresh capabilities
setUnderlyingNetworks(arrayOf(network)) underlyingNetwork = network
} }
override fun onLost(network: Network) { override fun onLost(network: Network) {
setUnderlyingNetworks(null) underlyingNetwork = null
} }
} }
private var listeningForDefaultNetwork = false private var listeningForDefaultNetwork = false
...@@ -132,7 +144,7 @@ class VpnService : BaseVpnService(), LocalDnsService.Interface { ...@@ -132,7 +144,7 @@ class VpnService : BaseVpnService(), LocalDnsService.Interface {
override fun onRevoke() = stopRunner(true) override fun onRevoke() = stopRunner(true)
override fun killProcesses() { override fun killProcesses() {
if (BuildCompat.isAtLeastP() && listeningForDefaultNetwork) { if (listeningForDefaultNetwork) {
connectivity.unregisterNetworkCallback(defaultNetworkCallback) connectivity.unregisterNetworkCallback(defaultNetworkCallback)
listeningForDefaultNetwork = false listeningForDefaultNetwork = false
} }
...@@ -217,12 +229,9 @@ class VpnService : BaseVpnService(), LocalDnsService.Interface { ...@@ -217,12 +229,9 @@ class VpnService : BaseVpnService(), LocalDnsService.Interface {
this.conn = conn this.conn = conn
val fd = conn.fd val fd = conn.fd
// We only need to update since Android P: https://android.googlesource.com/platform/frameworks/base/+/72f9c42b9e59761a28d6b32c42f65de57c98daed // we want REQUEST here instead of LISTEN
if (BuildCompat.isAtLeastP()) { connectivity.requestNetwork(defaultNetworkRequest, defaultNetworkCallback)
// we want REQUEST here instead of LISTEN listeningForDefaultNetwork = true
connectivity.requestNetwork(defaultNetworkRequest, defaultNetworkCallback)
listeningForDefaultNetwork = true
}
val cmd = arrayListOf(File(applicationInfo.nativeLibraryDir, Executable.TUN2SOCKS).absolutePath, val cmd = arrayListOf(File(applicationInfo.nativeLibraryDir, Executable.TUN2SOCKS).absolutePath,
"--netif-ipaddr", PRIVATE_VLAN.format(Locale.ENGLISH, "2"), "--netif-ipaddr", PRIVATE_VLAN.format(Locale.ENGLISH, "2"),
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment