aboutsummaryrefslogtreecommitdiffstatshomepage
diff options
context:
space:
mode:
authorRoger Chuang <lchuang@mozilla.com>2019-11-26 19:19:52 +0800
committerRoger Chuang <lchuang@mozilla.com>2019-11-27 10:12:13 +0800
commitbbc8c442cfb16d2900f623fbcd69af5fa86b1b41 (patch)
treea3adf755d1eb932a478762a76fe56f092c01755d
parentAdd statistic interface to TunnelManager.kt (diff)
downloadwireguard-android-bbc8c442cfb16d2900f623fbcd69af5fa86b1b41.tar.xz
wireguard-android-bbc8c442cfb16d2900f623fbcd69af5fa86b1b41.zip
Use Channel instead of LiveData to deliver VpnService instance
Signed-off-by: Roger Chuang <lchuang@mozilla.com>
-rw-r--r--libwg/build.gradle1
-rw-r--r--libwg/src/main/java/com/wireguard/android/backend/TunnelManager.kt103
2 files changed, 52 insertions, 52 deletions
diff --git a/libwg/build.gradle b/libwg/build.gradle
index 9c187499..34b66a64 100644
--- a/libwg/build.gradle
+++ b/libwg/build.gradle
@@ -37,6 +37,7 @@ dependencies {
implementation "android.arch.lifecycle:extensions:1.1.1"
implementation "androidx.annotation:annotation:$annotationsVersion"
implementation "androidx.appcompat:appcompat:$appcompatVersion"
+ implementation "org.jetbrains.kotlinx:kotlinx-coroutines-core:1.3.2"
implementation "net.sourceforge.streamsupport:android-retrofuture:$streamsupportVersion"
}
diff --git a/libwg/src/main/java/com/wireguard/android/backend/TunnelManager.kt b/libwg/src/main/java/com/wireguard/android/backend/TunnelManager.kt
index 3bc20e9e..35f8140a 100644
--- a/libwg/src/main/java/com/wireguard/android/backend/TunnelManager.kt
+++ b/libwg/src/main/java/com/wireguard/android/backend/TunnelManager.kt
@@ -11,72 +11,60 @@ import android.net.VpnService
import android.net.VpnService.prepare
import android.os.SystemClock
import android.util.Pair
-import androidx.lifecycle.MutableLiveData
-import androidx.lifecycle.Observer
-import androidx.lifecycle.ProcessLifecycleOwner
import com.wireguard.config.Config
import com.wireguard.crypto.Key
import com.wireguard.crypto.KeyFormatException
-import java.util.HashMap
-
-class TunnelManager {
+import kotlinx.coroutines.*
+import kotlinx.coroutines.channels.Channel
+import java.util.*
+
+class TunnelManager(
+ context: Context,
+ private val builderProvider: VpnBuilderProvider
+) {
+
+ private val appContext = context.applicationContext
+ private val backend: VpnServiceBackend = VpnServiceBackend(object: VpnServiceBackend.VpnServiceDelegate{
+ override fun protect(socket: Int): Boolean {
+ return currentService?.protect(socket) ?: false
+ }
+ })
- val backend: VpnServiceBackend
- val builderProvider: VpnBuilderProvider
- val context: Context
var currentTunnel: Tunnel? = null
-
- companion object {
- private val vpnService = MutableLiveData<VpnService>()
- }
+ var currentService: VpnService? = null
interface VpnBuilderProvider {
fun patchBuilder(builder: android.net.VpnService.Builder): android.net.VpnService.Builder
}
- init {
-
- }
-
- constructor(context: Context, builderProvider: VpnBuilderProvider) {
- this.backend = VpnServiceBackend(object: VpnServiceBackend.VpnServiceDelegate{
- override fun protect(socket: Int): Boolean {
- return vpnService.value?.protect(socket) ?: false
- }
- })
- this.context = context.applicationContext
- this.builderProvider = builderProvider
- }
-
fun tunnelDown() {
- vpnService.value = null
+ currentTunnel?.let { backend.tunnelDown(it) }
+ currentService = null
}
fun tunnelUp(tunnel: Tunnel) {
currentTunnel = tunnel
val config = tunnel.config
- vpnService.observe(ProcessLifecycleOwner.get(), object: Observer<VpnService>{
- override fun onChanged(service: VpnService?) {
- if(service == null){
- vpnService.removeObserver(this)
- currentTunnel?.apply { backend.tunnelDown(this) }
- return
+ GlobalScope.launch(Dispatchers.Main) {
+ currentService = serviceChannel.receive()
+ currentService?.Builder()?.apply {
+ builderProvider.patchBuilder(this)
+ applyConfig(config)
+ establish()?.let { fd ->
+ backend.tunnelUp(tunnel, fd, config.toWgUserspaceString())
}
+ }
- val builder = service.Builder()
- builderProvider.patchBuilder(builder)
- builder.applyConfig(config)
- val tun = builder.establish() ?: return
+ }
- backend.tunnelUp(tunnel, tun, config.toWgUserspaceString())
- }
+ appContext.startService(Intent(appContext, VpnService::class.java).apply {
+ putExtra(VpnService.EXTRA_COMMAND, VpnService.COMMAND_TURN_ON)
})
- context.startService(Intent(context, VpnService::class.java))
}
fun isGranted(): Boolean {
- return prepare(context) == null
+ return prepare(appContext) == null
}
fun isConnected(): Boolean {
@@ -131,26 +119,37 @@ class TunnelManager {
return stats
}
- public class VpnService : android.net.VpnService() {
- val builder: Builder
- get() {
- return Builder()
+ class VpnService : android.net.VpnService() {
+ private val serviceJob = Job()
+ private val serviceScope = CoroutineScope(Dispatchers.Main + serviceJob)
+
+ override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int {
+
+ when (intent?.getStringExtra(EXTRA_COMMAND) ?: "") {
+ COMMAND_TURN_ON -> turnOn()
}
- override fun onCreate() {
- super.onCreate()
- vpnService.value = this
+ return super.onStartCommand(intent, flags, startId)
}
override fun onDestroy() {
- vpnService.value = null
+ serviceJob.cancel()
super.onDestroy()
}
- override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int {
- return super.onStartCommand(intent, flags, startId)
+ private fun turnOn() = serviceScope.launch(Dispatchers.Main) {
+ serviceChannel.send(this@VpnService)
+ }
+
+ companion object {
+ const val EXTRA_COMMAND = "command"
+ const val COMMAND_TURN_ON = "turn_on"
}
}
+
+ companion object {
+ private val serviceChannel = Channel<VpnService>()
+ }
}
fun VpnService.Builder.applyConfig(config: Config){