feat: implement reconnection in AWG by turning the VPN off and on (#2046)

This commit is contained in:
albexk
2025-12-11 13:51:19 +03:00
committed by GitHub
parent 3e6f0c0342
commit 5103bc640e
5 changed files with 29 additions and 13 deletions

View File

@@ -93,7 +93,7 @@ open class OpenVpn : Protocol() {
openVpnClient = null
}
override fun reconnectVpn(vpnBuilder: Builder) {
override fun reconnectVpn(vpnBuilder: Builder, protect: (Int) -> Boolean) {
openVpnClient?.let {
it.establish = makeEstablish(vpnBuilder)
it.reconnect(0)

View File

@@ -42,7 +42,7 @@ abstract class Protocol {
abstract fun stopVpn()
abstract fun reconnectVpn(vpnBuilder: Builder)
abstract fun reconnectVpn(vpnBuilder: Builder, protect: (Int) -> Boolean)
protected fun ProtocolConfig.Builder.configSplitTunneling(config: JSONObject) {
if (!allowSplitTunneling) {

View File

@@ -565,7 +565,7 @@ open class AmneziaVpnService : VpnService() {
protocolState.value = RECONNECTING
connectionJob = connectionScope.launch {
vpnProto?.protocol?.reconnectVpn(Builder())
vpnProto?.protocol?.reconnectVpn(Builder(), ::protect)
}
}

View File

@@ -12,6 +12,7 @@ import org.amnezia.vpn.protocol.Protocol
import org.amnezia.vpn.protocol.ProtocolState.CONNECTED
import org.amnezia.vpn.protocol.ProtocolState.DISCONNECTED
import org.amnezia.vpn.protocol.Statistics
import org.amnezia.vpn.protocol.VpnException
import org.amnezia.vpn.protocol.VpnStartException
import org.amnezia.vpn.util.LibraryLoader.loadSharedLibrary
import org.amnezia.vpn.util.Log
@@ -27,6 +28,7 @@ private const val TAG = "Wireguard"
open class Wireguard : Protocol() {
private var tunnelHandle: Int = -1
private var config: WireguardConfig? = null // save config for reconnect
protected open val ifName: String = "amn0"
private lateinit var scope: CoroutineScope
private var statusJob: Job? = null
@@ -61,6 +63,7 @@ open class Wireguard : Protocol() {
override suspend fun startVpn(config: JSONObject, vpnBuilder: Builder, protect: (Int) -> Boolean) {
val wireguardConfig = parseConfig(config)
start(wireguardConfig, vpnBuilder, protect)
this.config = wireguardConfig
}
protected open fun parseConfig(config: JSONObject): WireguardConfig {
@@ -133,8 +136,13 @@ open class Wireguard : Protocol() {
configData.optStringOrNull("I5")?.let { setI5(it) }
}
private fun start(config: WireguardConfig, vpnBuilder: Builder, protect: (Int) -> Boolean) {
if (tunnelHandle != -1) {
private fun start(
config: WireguardConfig,
vpnBuilder: Builder,
protect: (Int) -> Boolean,
stopExistingVpn: Boolean = false
) {
if (!stopExistingVpn && tunnelHandle != -1) {
Log.w(TAG, "Tunnel already up")
return
}
@@ -142,6 +150,9 @@ open class Wireguard : Protocol() {
buildVpnInterface(config, vpnBuilder)
vpnBuilder.establish().use { tunFd ->
if (stopExistingVpn && tunnelHandle != -1) {
turnOffVpn()
}
if (tunFd == null) {
throw VpnStartException("Create VPN interface: permission not granted or revoked")
}
@@ -198,20 +209,25 @@ open class Wireguard : Protocol() {
return lastHandshake
}
override fun stopVpn() {
if (tunnelHandle == -1) {
Log.w(TAG, "Tunnel already down")
return
}
private fun turnOffVpn() {
statusJob?.cancel()
statusJob = null
val handleToClose = tunnelHandle
tunnelHandle = -1
GoBackend.awgTurnOff(handleToClose)
}
override fun stopVpn() {
if (tunnelHandle == -1) {
Log.w(TAG, "Tunnel already down")
return
}
turnOffVpn()
state.value = DISCONNECTED
}
override fun reconnectVpn(vpnBuilder: Builder) {
state.value = CONNECTED
override fun reconnectVpn(vpnBuilder: Builder, protect: (Int) -> Boolean) {
val config = this.config ?: throw VpnException("Reconnect config is empty")
start(config, vpnBuilder, protect, true)
}
}

View File

@@ -157,7 +157,7 @@ class Xray : Protocol() {
state.value = DISCONNECTED
}
override fun reconnectVpn(vpnBuilder: Builder) {
override fun reconnectVpn(vpnBuilder: Builder, protect: (Int) -> Boolean) {
state.value = CONNECTED
}