From f809e8ac296c82a46b71736eb2e6a9861378dc20 Mon Sep 17 00:00:00 2001 From: Juha Heinanen Date: Sun, 15 Nov 2020 16:54:13 +0200 Subject: [PATCH] Added support for VPNs --- app/src/main/cpp/baresip.c | 38 ++-- .../com/tutpro/baresip/BaresipService.kt | 176 ++++++++++-------- .../main/kotlin/com/tutpro/baresip/Config.kt | 6 +- .../main/kotlin/com/tutpro/baresip/Utils.kt | 34 +++- 4 files changed, 148 insertions(+), 106 deletions(-) diff --git a/app/src/main/cpp/baresip.c b/app/src/main/cpp/baresip.c index 7edba2b0..f24bdb5c 100644 --- a/app/src/main/cpp/baresip.c +++ b/app/src/main/cpp/baresip.c @@ -436,18 +436,22 @@ JNIEXPORT jint JNICALL JNI_OnLoad(JavaVM* vm, void* reserved) { return JNI_VERSION_1_6; } +JNIEXPORT jint JNICALL +Java_com_tutpro_baresip_Api_net_1set_1address(JNIEnv *env, jobject thiz, jstring javaIp); + +JNIEXPORT jint JNICALL +Java_com_tutpro_baresip_Api_net_1use_1nameserver(JNIEnv *env, jobject thiz, jstring javaServers); + JNIEXPORT void JNICALL Java_com_tutpro_baresip_BaresipService_baresipStart(JNIEnv *env, jobject instance, - jstring javaPath, jstring javaIpV4Addr, jstring javaIpV6Addr, - jstring javaNetInterface, jint javaNetAf, jint javaLogLevel) { + jstring jPath, jstring jIpV4Addr, jstring jIpV6Addr, jstring jNetInterface, + jstring jDnsServers, jint jNetAf, jint javaLogLevel) { LOGD("starting baresip\n"); struct sa temp_sa; - const char *ipv4_addr = (*env)->GetStringUTFChars(env, javaIpV4Addr, 0); - const char *ipv6_addr = (*env)->GetStringUTFChars(env, javaIpV6Addr, 0); - const char *net_interface = (*env)->GetStringUTFChars(env, javaNetInterface, 0); - const int net_af = javaNetAf; + const char *net_interface = (*env)->GetStringUTFChars(env, jNetInterface, 0); + const int net_af = jNetAf; char start_error[64] = ""; @@ -463,7 +467,7 @@ Java_com_tutpro_baresip_BaresipService_baresipStart(JNIEnv *env, jobject instanc g_ctx.env = env; int err; - const char *path = (*env)->GetStringUTFChars(env, javaPath, 0); + const char *path = (*env)->GetStringUTFChars(env, jPath, 0); struct le *le; runLoggingThread(); @@ -499,17 +503,9 @@ Java_com_tutpro_baresip_BaresipService_baresipStart(JNIEnv *env, jobject instanc goto out; } - if (strlen(ipv4_addr) > 0) { - sa_set_str(&temp_sa, ipv4_addr, 0); - LOGD("setting IPv4 address %s\n", ipv4_addr); - net_set_address(baresip_network(), &temp_sa); - } - - if (strlen(ipv6_addr) > 0) { - sa_set_str(&temp_sa, ipv6_addr, 0); - LOGD("setting IPv6 address %s\n", ipv6_addr); - net_set_address(baresip_network(), &temp_sa); - } + Java_com_tutpro_baresip_Api_net_1set_1address(env, instance, jIpV4Addr); + Java_com_tutpro_baresip_Api_net_1set_1address(env, instance, jIpV6Addr); + Java_com_tutpro_baresip_Api_net_1use_1nameserver(env, instance, jDnsServers); net_debug_log(); @@ -574,8 +570,6 @@ Java_com_tutpro_baresip_BaresipService_baresipStart(JNIEnv *env, jobject instanc err = re_main(signal_handler); out: - (*env)->ReleaseStringUTFChars(env, javaIpV4Addr, ipv4_addr); - (*env)->ReleaseStringUTFChars(env, javaIpV6Addr, ipv6_addr); if (err) { LOGE("stopping UAs due to error: (%d)\n", err); @@ -1633,6 +1627,10 @@ Java_com_tutpro_baresip_Api_net_1set_1address(JNIEnv *env, jobject thiz, jstring struct sa temp_sa; char buf[256]; LOGD("setting address '%s'\n", native_ip); + if (str_len(native_ip) == 0) { + (*env)->ReleaseStringUTFChars(env, javaIp, native_ip); + return 0; + } if (0 == sa_set_str(&temp_sa, native_ip, 0)) { sa_ntop(&temp_sa, buf, 256); net_set_address(baresip_network(), &temp_sa); diff --git a/app/src/main/kotlin/com/tutpro/baresip/BaresipService.kt b/app/src/main/kotlin/com/tutpro/baresip/BaresipService.kt index e05b8ba2..b7b3af74 100644 --- a/app/src/main/kotlin/com/tutpro/baresip/BaresipService.kt +++ b/app/src/main/kotlin/com/tutpro/baresip/BaresipService.kt @@ -84,83 +84,27 @@ class BaresipService: Service() { override fun onAvailable(network: Network) { super.onAvailable(network) - val linkProps = cm.getLinkProperties(network) - if (linkProps != null) { - val interfaceName = linkProps.interfaceName!! - if (((Build.VERSION.SDK_INT >= 23) && (network == cm.activeNetwork)) || - ((Build.VERSION.SDK_INT < 23) && - (cm.activeNetworkInfo.toString() == - cm.getNetworkInfo(network).toString()))) { - Log.i(LOG_TAG, "Active network $network@$interfaceName " + - " is available: $linkProps") - activeNetwork = "$network" - if (isServiceRunning) { - Utils.updateLinkProperties(linkProps) - } else { - dnsServers = linkProps.dnsServers - linkAddresses = linkProps.linkAddresses - } - } else { - Log.i(LOG_TAG, "Non-active network $network@$interfaceName " + - " is available: $linkProps") - } - } + Log.i(LOG_TAG, "Network $network is available") + updateNetwork() } override fun onLost(network: Network) { super.onLost(network) - if (activeNetwork == "$network") { - Log.d(LOG_TAG, "Currently active network $network is lost") - var newNetwork: Network? = null - for (net in cm.allNetworks) - if (net != network) { - if (((Build.VERSION.SDK_INT >= 23) && (net == cm.activeNetwork)) || - ((Build.VERSION.SDK_INT < 23) && - cm.activeNetworkInfo.toString() == - cm.getNetworkInfo(net).toString())) { - Log.d(LOG_TAG, "New active network $net is available") - newNetwork = net - break - } - } - if (newNetwork != null) { - val linkProps = cm.getLinkProperties(newNetwork) - if (linkProps != null) { - val interfaceName = linkProps.interfaceName - Log.d(LOG_TAG, "Updating new active network " + - "$newNetwork@$interfaceName link properties: $linkProps") - activeNetwork = "$newNetwork" - Utils.updateLinkProperties(linkProps) - } - } - } else { - Log.d(LOG_TAG, "Network '$network' is lost") - } + Log.i(LOG_TAG, "Network $network is lost") + if (activeNetwork == "$network") + updateNetwork() } - override fun onLinkPropertiesChanged(network: Network, linkProperties: LinkProperties) { - super.onLinkPropertiesChanged(network, linkProperties) - val linkProps = cm.getLinkProperties(network) - if (linkProps != null) { - val interfaceName = linkProps.interfaceName - if (((Build.VERSION.SDK_INT >= 23) && (network == cm.activeNetwork)) || - ((Build.VERSION.SDK_INT < 23) && - (cm.activeNetworkInfo.toString() == - cm.getNetworkInfo(network).toString()))) { - Log.d(LOG_TAG, "Active network $network@$interfaceName " + - " link properties changed: $linkProperties") - activeNetwork = "$network" - if (isServiceRunning) { - Utils.updateLinkProperties(linkProperties) - } else { - dnsServers = linkProperties.dnsServers - linkAddresses = linkProperties.linkAddresses - } - } else { - Log.d(LOG_TAG, "Network $network@$interfaceName " + - " link properties changed: $linkProperties") - } - } + override fun onLinkPropertiesChanged(network: Network, props: LinkProperties) { + super.onLinkPropertiesChanged(network, props) + Log.i(LOG_TAG, "Network $network link properties changed") + if (activeNetwork == "$network") + updateNetwork() + } + + override fun onCapabilitiesChanged(network: Network, caps: NetworkCapabilities) { + super.onCapabilitiesChanged(network, caps) + Log.i(LOG_TAG, "Network $network capabilities changed: $caps") } } ) @@ -307,10 +251,11 @@ class BaresipService: Service() { val ipV4Addr = Utils.findIpV4Address(linkAddresses) val ipV6Addr = Utils.findIpV6Address(linkAddresses) + val dnsServers = Utils.findDnsServers(BaresipService.dnsServers) if ((ipV4Addr == "") && (ipV6Addr == "")) Log.w(LOG_TAG, "Starting baresip without IP addresses") Thread(Runnable { baresipStart(filesPath, ipV4Addr, ipV6Addr, "", - Api.AF_UNSPEC, logLevel) + dnsServers, Api.AF_UNSPEC, logLevel) }).start() isServiceRunning = true @@ -517,9 +462,9 @@ class BaresipService: Service() { if (Build.VERSION.SDK_INT >= 23) { val activeNetwork = cm.activeNetwork if (activeNetwork != null) { - val linkProps = cm.getLinkProperties(activeNetwork) - if (linkProps != null) { - val dnsServers = linkProps.dnsServers + val props = cm.getLinkProperties(activeNetwork) + if (props != null) { + val dnsServers = props.dnsServers Log.d(LOG_TAG, "Updating DNS Servers = $dnsServers") if (Config.updateDnsServers(dnsServers) != 0) { Log.w(LOG_TAG, "Failed to update DNS servers '$dnsServers'") @@ -536,6 +481,10 @@ class BaresipService: Service() { } } } + if ((ev.size > 1) && (ev[1] == "Software caused connection abort")) { + // Perhaps due to VPN connect/disconnect + updateNetwork() + } if (!Utils.isVisible()) return } @@ -1079,6 +1028,80 @@ class BaresipService: Service() { } } + private fun updateNetwork() { + if (Build.VERSION.SDK_INT >= 23) { + for (n in cm.allNetworks) { + val caps = cm.getNetworkCapabilities(n) ?: continue + val props = cm.getLinkProperties(n) ?: continue + Log.i(LOG_TAG, "Network $n ${n == cm.activeNetwork}" + + " is available with caps: $caps, props: $props") + } + // Use VPN network if available + for (n in cm.allNetworks) { + val caps = cm.getNetworkCapabilities(n) ?: continue + val props = cm.getLinkProperties(n) ?: continue + if (n == cm.activeNetwork) + Log.i("Baresip", "Network $n is active") + else + Log.i("Baresip", "Network $n is NOT active") + if (caps.hasTransport(NetworkCapabilities.TRANSPORT_VPN) && + (n == cm.activeNetwork)) { + Log.i(LOG_TAG, "Active VPN network $n is available with caps: " + + "$caps, props: $props") + activeNetwork = "$n" + if (!isConfigInitialized) + Log.i("Baresip", "Config is NOT initialized") + else + Log.i("Baresip", "Config is initialized") + if (isConfigInitialized) { + Utils.updateLinkProperties(props) + } else { + for (s in props.dnsServers) + Log.i(LOG_TAG, "DNS Server ${s.hostAddress}") + dnsServers = props.dnsServers + linkAddresses = props.linkAddresses + } + return + } + } + // Otherwise, use active network with Internet access + for (n in cm.allNetworks) { + val caps = cm.getNetworkCapabilities(n) ?: continue + val props = cm.getLinkProperties(n) ?: continue + if ((n == cm.activeNetwork) && + caps.hasCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET)) { + Log.i(LOG_TAG, "Active Internet network $n is available with caps: " + + "$caps, props: $props") + activeNetwork = "$n" + if (isServiceRunning) { + Utils.updateLinkProperties(props) + } else { + dnsServers = props.dnsServers + linkAddresses = props.linkAddresses + } + return + } + } + // Otherwise, use an active network + for (n in cm.allNetworks) { + val caps = cm.getNetworkCapabilities(n) ?: continue + val props = cm.getLinkProperties(n) ?: continue + if (n == cm.activeNetwork) { + Log.i(LOG_TAG, "Active network $n is available with caps: " + + "$caps, props: $props") + activeNetwork = "$n" + if (isServiceRunning) { + Utils.updateLinkProperties(props) + } else { + dnsServers = props.dnsServers + linkAddresses = props.linkAddresses + } + return + } + } + } + } + private fun cleanService() { abandonAudioFocus() uas.clear() @@ -1097,7 +1120,7 @@ class BaresipService: Service() { } external fun baresipStart(path: String, ipV4Addr: String, ipV6Addr: String, netInterface: String, - netAf: Int, logLevel: Int) + dnsServers: String, netAf: Int, logLevel: Int) external fun baresipStop(force: Boolean) companion object { @@ -1123,6 +1146,7 @@ class BaresipService: Service() { val HIGH_CHANNEL_ID = "com.tutpro.baresip.high" var isServiceRunning = false + var isConfigInitialized = false var libraryLoaded = false var isServiceClean = false var speakerPhone = false diff --git a/app/src/main/kotlin/com/tutpro/baresip/Config.kt b/app/src/main/kotlin/com/tutpro/baresip/Config.kt index e8085759..fff075d7 100644 --- a/app/src/main/kotlin/com/tutpro/baresip/Config.kt +++ b/app/src/main/kotlin/com/tutpro/baresip/Config.kt @@ -86,8 +86,9 @@ object Config { } } - Log.e("Baresip", "Initialized config to '$config'") Utils.putFileContents(configPath, config.toByteArray()) + BaresipService.isConfigInitialized = true + Log.i("Baresip", "Initialized config to '$config'") } @@ -139,9 +140,10 @@ object Config { } fun updateDnsServers(dnsServers: List): Int { + Log.i("Baresip", "Updating dnsServers with $dnsServers") var servers = "" for (dnsServer in dnsServers) { - var address = dnsServer.hostAddress + var address = dnsServer.hostAddress.removePrefix("/") if (Utils.checkIpV4(address)) address = "${address}:53" else diff --git a/app/src/main/kotlin/com/tutpro/baresip/Utils.kt b/app/src/main/kotlin/com/tutpro/baresip/Utils.kt index e5cf466d..c7ca6d86 100644 --- a/app/src/main/kotlin/com/tutpro/baresip/Utils.kt +++ b/app/src/main/kotlin/com/tutpro/baresip/Utils.kt @@ -1,6 +1,5 @@ package com.tutpro.baresip -import android.annotation.SuppressLint import android.app.Activity import android.app.ActivityManager import android.content.Context @@ -14,7 +13,6 @@ import android.net.LinkProperties import android.os.Bundle import android.text.Editable import android.text.TextWatcher -import android.view.LayoutInflater import android.view.View import android.widget.TextView import androidx.appcompat.app.AlertDialog @@ -22,6 +20,7 @@ import androidx.core.app.ActivityCompat import androidx.core.content.ContextCompat import java.io.* +import java.net.InetAddress import java.security.SecureRandom import java.util.* import java.util.zip.ZipEntry @@ -269,6 +268,22 @@ object Utils { return "" } + fun findDnsServers(list: List): String { + var servers = "" + for (dnsServer in list) { + var address = dnsServer.hostAddress.removePrefix("/") + if (Utils.checkIpV4(address)) + address = "${address}:53" + else + address = "[${address}]:53" + if (servers == "") + servers = address + else + servers = "${servers},${address}" + } + return servers + } + private fun updateLinkAddresses(linkAddresses: List) { var updated = false val ipV6Addr = findIpV6Address(linkAddresses) @@ -302,14 +317,17 @@ object Utils { } } - fun updateLinkProperties(linkProperties: LinkProperties) { - if (BaresipService.dynDns && (BaresipService.dnsServers != linkProperties.dnsServers)) { - if (Config.updateDnsServers(linkProperties.dnsServers) != 0) - Log.w("Baresip", "Failed to update DNS servers '${BaresipService.dnsServers}'") + fun updateLinkProperties(props: LinkProperties) { + if (BaresipService.dynDns && (BaresipService.dnsServers != props.dnsServers)) { + if (BaresipService.isServiceRunning) + if (Config.updateDnsServers(props.dnsServers) != 0) + Log.w("Baresip", "Failed to update DNS servers '${props.dnsServers}'") + else + BaresipService.dnsServers = props.dnsServers else - BaresipService.dnsServers = linkProperties.dnsServers + BaresipService.dnsServers = props.dnsServers } - updateLinkAddresses(linkProperties.linkAddresses) + updateLinkAddresses(props.linkAddresses) } fun implode(list: List, sep: String): String {