Skip to content

Commit 7b7a922

Browse files
authored
Merge pull request #1226 from amnezia-vpn/fix/android-awg-connection
Fix connection check for AWG/WG
2 parents 09bd958 + 1533270 commit 7b7a922

File tree

1 file changed

+49
-36
lines changed
  • client/android/wireguard/src/main/kotlin/org/amnezia/vpn/protocol/wireguard

1 file changed

+49
-36
lines changed

client/android/wireguard/src/main/kotlin/org/amnezia/vpn/protocol/wireguard/Wireguard.kt

+49-36
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,12 @@
11
package org.amnezia.vpn.protocol.wireguard
22

33
import android.net.VpnService.Builder
4-
import java.io.IOException
5-
import java.util.Locale
4+
import kotlinx.coroutines.CoroutineScope
65
import kotlinx.coroutines.Dispatchers
6+
import kotlinx.coroutines.Job
7+
import kotlinx.coroutines.cancel
78
import kotlinx.coroutines.delay
8-
import kotlinx.coroutines.withContext
9+
import kotlinx.coroutines.launch
910
import org.amnezia.awg.GoBackend
1011
import org.amnezia.vpn.protocol.Protocol
1112
import org.amnezia.vpn.protocol.ProtocolState.CONNECTED
@@ -27,6 +28,8 @@ open class Wireguard : Protocol() {
2728

2829
private var tunnelHandle: Int = -1
2930
protected open val ifName: String = "amn0"
31+
private lateinit var scope: CoroutineScope
32+
private var statusJob: Job? = null
3033

3134
override val statistics: Statistics
3235
get() {
@@ -49,46 +52,17 @@ open class Wireguard : Protocol() {
4952

5053
override fun internalInit() {
5154
if (!isInitialized) loadSharedLibrary(context, "wg-go")
55+
if (this::scope.isInitialized) {
56+
scope.cancel()
57+
}
58+
scope = CoroutineScope(Dispatchers.IO)
5259
}
5360

5461
override suspend fun startVpn(config: JSONObject, vpnBuilder: Builder, protect: (Int) -> Boolean) {
5562
val wireguardConfig = parseConfig(config)
56-
val startTime = System.currentTimeMillis()
5763
start(wireguardConfig, vpnBuilder, protect)
58-
waitForConnection(startTime)
59-
state.value = CONNECTED
6064
}
6165

62-
private suspend fun waitForConnection(startTime: Long) {
63-
Log.d(TAG, "Waiting for connection")
64-
withContext(Dispatchers.IO) {
65-
val time = String.format(Locale.ROOT,"%.3f", startTime / 1000.0)
66-
try {
67-
delay(1000)
68-
var log = getLogcat(time)
69-
Log.v(TAG, "First waiting log: $log")
70-
// check that there is a connection log,
71-
// to avoid infinite connection
72-
if (!log.contains("Attaching to interface")) {
73-
Log.w(TAG, "Logs do not contain a connection log")
74-
return@withContext
75-
}
76-
while (!log.contains("Received handshake response")) {
77-
delay(1000)
78-
log = getLogcat(time)
79-
}
80-
} catch (e: IOException) {
81-
Log.e(TAG, "Failed to get logcat: $e")
82-
}
83-
}
84-
}
85-
86-
private fun getLogcat(time: String): String =
87-
ProcessBuilder("logcat", "--buffer=main", "--format=raw", "*:S AmneziaWG/awg0", "-t", time)
88-
.redirectErrorStream(true)
89-
.start()
90-
.inputStream.reader().readText()
91-
9266
protected open fun parseConfig(config: JSONObject): WireguardConfig {
9367
val configData = config.getJSONObject("wireguard_config_data")
9468
return WireguardConfig.build {
@@ -178,13 +152,52 @@ open class Wireguard : Protocol() {
178152
tunnelHandle = -1
179153
throw VpnStartException("Protect VPN interface: permission not granted or revoked")
180154
}
155+
launchStatusJob()
156+
}
157+
158+
private fun launchStatusJob() {
159+
Log.d(TAG, "Launch status job")
160+
statusJob = scope.launch {
161+
while (true) {
162+
val lastHandshake = getLastHandshake()
163+
Log.v(TAG, "lastHandshake=$lastHandshake")
164+
if (lastHandshake == 0L) {
165+
delay(1000)
166+
continue
167+
}
168+
if (lastHandshake == -2L || lastHandshake > 0L) state.value = CONNECTED
169+
else if (lastHandshake == -1L) state.value = DISCONNECTED
170+
statusJob = null
171+
break
172+
}
173+
}
174+
}
175+
176+
private fun getLastHandshake(): Long {
177+
if (tunnelHandle == -1) {
178+
Log.e(TAG, "Trying to get config of a non-existent tunnel")
179+
return -1
180+
}
181+
val config = GoBackend.awgGetConfig(tunnelHandle)
182+
if (config == null) {
183+
Log.e(TAG, "Failed to get tunnel config")
184+
return -2
185+
}
186+
val lastHandshake = config.lines().find { it.startsWith("last_handshake_time_sec=") }?.substring(24)?.toLong()
187+
if (lastHandshake == null) {
188+
Log.e(TAG, "Failed to get last_handshake_time_sec")
189+
return -2
190+
}
191+
return lastHandshake
181192
}
182193

183194
override fun stopVpn() {
184195
if (tunnelHandle == -1) {
185196
Log.w(TAG, "Tunnel already down")
186197
return
187198
}
199+
statusJob?.cancel()
200+
statusJob = null
188201
val handleToClose = tunnelHandle
189202
tunnelHandle = -1
190203
GoBackend.awgTurnOff(handleToClose)

0 commit comments

Comments
 (0)