Add network state listening and reconnection

Vpn reconnects when the default network is changed
This commit is contained in:
albexk 2023-12-11 15:16:50 +03:00
parent 8cc5846808
commit 1576aed1ea
15 changed files with 240 additions and 223 deletions

View file

@ -67,7 +67,7 @@ open class OpenVpn : Protocol() {
configBuilder = configBuilder,
state = state,
getLocalNetworks = { ipv6 -> getLocalNetworks(context, ipv6) },
establish = makeEstablish(configBuilder, vpnBuilder),
establish = makeEstablish(vpnBuilder),
protect = protect,
onError = onError
)
@ -109,22 +109,28 @@ open class OpenVpn : Protocol() {
openVpnClient = null
}
override fun reconnectVpn(vpnBuilder: Builder) {
openVpnClient?.let {
it.establish = makeEstablish(vpnBuilder)
it.reconnect(0)
}
}
protected open fun parseConfig(config: JSONObject): ClientAPI_Config {
val openVpnConfig = ClientAPI_Config()
openVpnConfig.content = config.getJSONObject("openvpn_config_data").getString("config")
return openVpnConfig
}
private fun makeEstablish(configBuilder: OpenVpnConfig.Builder, vpnBuilder: Builder): () -> Int =
{
val openVpnConfig = configBuilder.build()
buildVpnInterface(openVpnConfig, vpnBuilder)
private fun makeEstablish(vpnBuilder: Builder): (OpenVpnConfig.Builder) -> Int = { configBuilder ->
val openVpnConfig = configBuilder.build()
buildVpnInterface(openVpnConfig, vpnBuilder)
vpnBuilder.establish().use { tunFd ->
if (tunFd == null) {
throw VpnStartException("Create VPN interface: permission not granted or revoked")
}
return@use tunFd.detachFd()
vpnBuilder.establish().use { tunFd ->
if (tunFd == null) {
throw VpnStartException("Create VPN interface: permission not granted or revoked")
}
return@use tunFd.detachFd()
}
}
}

View file

@ -3,6 +3,7 @@ package org.amnezia.vpn.protocol.openvpn
import android.net.ProxyInfo
import android.os.Build
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.getAndUpdate
import net.openvpn.ovpn3.ClientAPI_Config
import net.openvpn.ovpn3.ClientAPI_EvalConfig
import net.openvpn.ovpn3.ClientAPI_Event
@ -14,6 +15,7 @@ import net.openvpn.ovpn3.ClientAPI_TransportStats
import org.amnezia.vpn.protocol.ProtocolState
import org.amnezia.vpn.protocol.ProtocolState.CONNECTED
import org.amnezia.vpn.protocol.ProtocolState.DISCONNECTED
import org.amnezia.vpn.protocol.ProtocolState.RECONNECTING
import org.amnezia.vpn.util.Log
import org.amnezia.vpn.util.net.InetNetwork
import org.amnezia.vpn.util.net.parseInetAddress
@ -25,7 +27,7 @@ class OpenVpnClient(
private val configBuilder: OpenVpnConfig.Builder,
private val state: MutableStateFlow<ProtocolState>,
private val getLocalNetworks: (Boolean) -> List<InetNetwork>,
private val establish: () -> Int,
internal var establish: (OpenVpnConfig.Builder) -> Int,
private val protect: (Int) -> Boolean,
private val onError: (String) -> Unit
) : ClientAPI_OpenVPNClient() {
@ -51,6 +53,7 @@ class OpenVpnClient(
// Should be called first.
override fun tun_builder_new(): Boolean {
Log.v(TAG, "tun_builder_new")
configBuilder.clearAddresses()
return true
}
@ -147,7 +150,7 @@ class OpenVpnClient(
// Always called last after tun_builder session has been configured.
override fun tun_builder_establish(): Int {
Log.v(TAG, "tun_builder_establish")
return establish()
return establish(configBuilder)
}
// Callback to reroute default gateway to VPN interface.
@ -368,6 +371,12 @@ class OpenVpnClient(
"COMPRESSION_ENABLED", "WARN" -> Log.w(TAG, "$name: $info")
"CONNECTED" -> state.value = CONNECTED
"DISCONNECTED" -> state.value = DISCONNECTED
"RECONNECTING" -> {
state.getAndUpdate { state ->
if (state == DISCONNECTED || state == CONNECTED) RECONNECTING
else state
}
}
}
if (event.error || event.fatal) {
state.value = DISCONNECTED