diff --git a/app/src/main/cpp/baresip.c b/app/src/main/cpp/baresip.c index 6d3fb7d4..414b504e 100644 --- a/app/src/main/cpp/baresip.c +++ b/app/src/main/cpp/baresip.c @@ -437,21 +437,22 @@ JNIEXPORT jint JNICALL JNI_OnLoad(JavaVM* vm, void* reserved) { } JNIEXPORT jint JNICALL -Java_com_tutpro_baresip_Api_net_1set_1address(JNIEnv *env, jobject thiz, jstring javaIp); +Java_com_tutpro_baresip_Api_net_1add_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 jPath, jstring jIpV4Addr, jstring jIpV6Addr, jstring jNetInterface, - jstring jDnsServers, jint jNetAf, jint javaLogLevel) { + jstring jPath, jstring jIpAddrs, jstring jNetInterface, jint jNetAf, jint jLogLevel) { - LOGD("starting baresip\n"); + LOGI("starting baresip\n"); const char *net_interface = (*env)->GetStringUTFChars(env, jNetInterface, 0); const int net_af = jNetAf; + const char *ip_addrs = (*env)->GetStringUTFChars(env, jIpAddrs, 0); + char start_error[64] = ""; JavaVM *javaVM = g_ctx.javaVM; @@ -477,7 +478,7 @@ Java_com_tutpro_baresip_BaresipService_baresipStart(JNIEnv *env, jobject instanc conf_path_set(path); - log_level_set((enum log_level)javaLogLevel); + log_level_set((enum log_level)jLogLevel); err = conf_configure(); if (err) { @@ -502,9 +503,26 @@ Java_com_tutpro_baresip_BaresipService_baresipStart(JNIEnv *env, jobject instanc goto out; } - 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); + if (strlen(ip_addrs) > 0) { + char* addr_list = (char*)malloc(strlen(ip_addrs)); + struct sa temp_sa; + char buf[256]; + net_flush_addresses(baresip_network()); + strcpy(addr_list, ip_addrs); + char *ptr = strtok(addr_list, ";"); + while (ptr != NULL) { + LOGI("adding address '%s'", ptr); + if (0 == sa_set_str(&temp_sa, ptr, 0)) { + sa_ntop(&temp_sa, buf, 256); + net_add_address(baresip_network(), &temp_sa); + } else { + LOGE("invalid ip address %s\n", ptr); + res = EAFNOSUPPORT; + } + ptr = strtok(NULL, ";"); + } + free(addr_list); + } net_debug_log(); @@ -1677,6 +1695,50 @@ Java_com_tutpro_baresip_Api_net_1set_1address(JNIEnv *env, jobject thiz, jstring return res; } +JNIEXPORT jint JNICALL +Java_com_tutpro_baresip_Api_net_1add_1address(JNIEnv *env, jobject thiz, jstring javaIp) { + const char *native_ip = (*env)->GetStringUTFChars(env, javaIp, 0); + int res = 0; + struct sa temp_sa; + char buf[256]; + LOGI("adding 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_add_address(baresip_network(), &temp_sa); + } else { + LOGE("invalid ip address %s\n", native_ip); + res = EAFNOSUPPORT; + } + (*env)->ReleaseStringUTFChars(env, javaIp, native_ip); + return res; +} + +JNIEXPORT jint JNICALL +Java_com_tutpro_baresip_Api_net_1rm_1address(JNIEnv *env, jobject thiz, jstring jIp) { + const char *native_ip = (*env)->GetStringUTFChars(env, jIp, 0); + int res = 0; + struct sa temp_sa; + char buf[256]; + LOGD("removing address '%s'\n", native_ip); + if (str_len(native_ip) == 0) { + (*env)->ReleaseStringUTFChars(env, jIp, native_ip); + return 0; + } + if (0 == sa_set_str(&temp_sa, native_ip, 0)) { + sa_ntop(&temp_sa, buf, 256); + net_rm_address(baresip_network(), &temp_sa); + } else { + LOGE("invalid ip address %s\n", native_ip); + res = EAFNOSUPPORT; + } + (*env)->ReleaseStringUTFChars(env, jIp, native_ip); + return res; +} + JNIEXPORT void JNICALL Java_com_tutpro_baresip_Api_net_1unset_1address(JNIEnv *env, jobject thiz, jint javaAf) { struct sa temp_sa; diff --git a/app/src/main/kotlin/com/tutpro/baresip/Api.kt b/app/src/main/kotlin/com/tutpro/baresip/Api.kt index a7df7cbe..08fd49dc 100644 --- a/app/src/main/kotlin/com/tutpro/baresip/Api.kt +++ b/app/src/main/kotlin/com/tutpro/baresip/Api.kt @@ -3,7 +3,7 @@ package com.tutpro.baresip object Api { const val AF_UNSPEC = 0 - const val AF_INET = 2 + // const val AF_INET = 2 const val AF_INET6 = 10 const val VIDMODE_OFF = 0 // const val VIDMODE_ON = 1 @@ -76,6 +76,8 @@ object Api { external fun net_use_nameserver(servers: String): Int external fun net_set_address(ip_addr: String): Int + external fun net_add_address(ip_addr: String): Int + external fun net_rm_address(ip_addr: String): Int external fun net_unset_address(af: Int) external fun net_debug() external fun net_dns_debug() diff --git a/app/src/main/kotlin/com/tutpro/baresip/BaresipService.kt b/app/src/main/kotlin/com/tutpro/baresip/BaresipService.kt index a5ff9ce5..8b2586fe 100644 --- a/app/src/main/kotlin/com/tutpro/baresip/BaresipService.kt +++ b/app/src/main/kotlin/com/tutpro/baresip/BaresipService.kt @@ -29,6 +29,7 @@ import java.io.File import java.net.InetAddress import java.nio.charset.StandardCharsets import java.util.* +import kotlin.collections.ArrayList import kotlin.concurrent.schedule import kotlin.math.roundToInt @@ -55,7 +56,7 @@ class BaresipService: Service() { private var origVolume = -1 private val btAdapter = BluetoothAdapter.getDefaultAdapter() private var activeNetwork: Network? = null - private var linkAddresses = listOf() + private var linkAddresses = mutableListOf() @SuppressLint("WakelockTimeout") override fun onCreate() { @@ -119,15 +120,9 @@ class BaresipService: Service() { updateNetwork() } - override fun onCapabilitiesChanged(network: Network, caps: NetworkCapabilities) { - super.onCapabilitiesChanged(network, caps) - Log.i(TAG, "Network $network capabilities changed: $caps") - } } ) - - wm = applicationContext.getSystemService(Context.WIFI_SERVICE) as WifiManager tm = getSystemService(Context.TELEPHONY_SERVICE) as TelephonyManager @@ -234,6 +229,25 @@ class BaresipService: Service() { when (action) { "Start" -> { + + var ipAddrs = "" + for (n in cm.allNetworks) { + val props = cm.getLinkProperties(n) + if (props != null) { + for (a in props.linkAddresses) + linkAddresses.add(a) + val addrs = Utils.hostAddresses(props.linkAddresses) + if (addrs != "") { + if (ipAddrs == "") + ipAddrs = addrs + else + ipAddrs += ";$addrs" + } + } + } + + updateDnsServers() + val assets = arrayOf("accounts", "config", "contacts", "busy.wav", "callwaiting.wav", "error.wav", "ringback.wav") var file = File(filesPath) @@ -264,15 +278,12 @@ class BaresipService: Service() { CallHistory.restore() Message.restore() - val ipV4Addr = Utils.findIpV4Address(linkAddresses) - val ipV6Addr = Utils.findIpV6Address(linkAddresses) - val dnsServers = Utils.findDnsServers(BaresipService.dnsServers) - if ((ipV4Addr == "") && (ipV6Addr == "")) + if (ipAddrs == "") Log.w(TAG, "Starting baresip without IP addresses") Thread { baresipStart( - filesPath, ipV4Addr, ipV6Addr, "", dnsServers, Api.AF_UNSPEC, logLevel + filesPath, ipAddrs, "", Api.AF_UNSPEC, logLevel ) }.start() @@ -425,35 +436,11 @@ class BaresipService: Service() { "registering failed" -> { status[account_index] = R.drawable.dot_red updateStatusNotification() - if ((ev.size > 1) && (ev[1] == "Invalid argument")) { - // Most likely this error is due to DNS lookup failure + if (ev.size > 1 && ev[1] == "Invalid argument") + // Likely due to DNS lookup failure newEvent = "registering failed,DNS lookup failed" - Api.net_dns_debug() - if (dynDns) - if (VERSION.SDK_INT >= 23) { - val activeNetwork = cm.activeNetwork - if (activeNetwork != null) { - val props = cm.getLinkProperties(activeNetwork) - if (props != null) { - val dnsServers = props.dnsServers - Log.d(TAG, "Updating DNS Servers = $dnsServers") - if (Config.updateDnsServers(dnsServers) != 0) { - Log.w(TAG, "Failed to update DNS servers '$dnsServers'") - } else { - Api.net_dns_debug() - if (!ua.registrationFailed) { - ua.registrationFailed = true - Api.ua_register(uap) - } - } - } - } else { - Log.d(TAG, "No active network!") - } - } - } - if ((ev.size > 1) && (ev[1] == "Software caused connection abort")) { - // Perhaps due to VPN connect/disconnect + if (!ua.registrationFailed) { + ua.registrationFailed = true updateNetwork() } if (!Utils.isVisible()) @@ -1102,94 +1089,92 @@ class BaresipService: Service() { } private fun updateNetwork() { - - var selectedNetwork: Network? = null - var caps: NetworkCapabilities? = null - var props: LinkProperties? = null - - // Use VPN network if available - for (n in cm.allNetworks) { - caps = cm.getNetworkCapabilities(n) ?: continue - if (isNetworkActive(n) && caps.hasTransport(NetworkCapabilities.TRANSPORT_VPN)) { - props = cm.getLinkProperties(n) ?: continue - Log.i(TAG, "Active VPN network $n is available with caps: $caps, props: $props") - selectedNetwork = n - break + /* for (n in cm.allNetworks) + Log.i(TAG, "NETWORK $n with caps ${cm.getNetworkCapabilities(n)} and props " + + "${cm.getLinkProperties(n)} is active ${isNetworkActive(n)}") */ + activeNetwork = activeNetwork() + if (activeNetwork != null) { + val linkCaps = cm.getNetworkCapabilities(activeNetwork) + val linkProps = cm.getLinkProperties(activeNetwork) + Log.d(TAG, "Using active network $activeNetwork with caps: $linkCaps, props: $linkProps") + val lnAddrs = mutableListOf() + for (n in cm.allNetworks) { + val props = cm.getLinkProperties(n) + if (props != null) + for (a in props.linkAddresses) + lnAddrs.add(a) } - } - - // Otherwise, use currently active default data network - for (n in cm.allNetworks) { - if (isNetworkActive(n)) { - caps = cm.getNetworkCapabilities(n) ?: continue - props = cm.getLinkProperties(n) ?: continue - Log.i(TAG, "Active network $n is available with caps: $caps, props: $props") - selectedNetwork = n - break - } - } - - if (selectedNetwork != null) { - activeNetwork = selectedNetwork - if (isServiceRunning) { - updateLinkProperties(props!!) + var addrUpdate = false + for (a in lnAddrs) + if (!linkAddresses.contains(a)) { + Api.net_add_address(a.address.hostAddress) + addrUpdate = true + } + for (a in linkAddresses) + if (!lnAddrs.contains(a)) { + Api.net_rm_address(a.address.hostAddress) + addrUpdate = true + } + val dnsUpdate = updateDnsServers() + if (addrUpdate) { + linkAddresses = lnAddrs + Api.uag_reset_transp(register = true, reinvite = true) } else { - dnsServers = props!!.dnsServers - linkAddresses = props.linkAddresses + if (dnsUpdate) + UserAgent.register() } - if (caps!!.hasTransport(NetworkCapabilities.TRANSPORT_WIFI)) { + if (linkCaps != null && linkCaps.hasTransport(NetworkCapabilities.TRANSPORT_WIFI)) { Log.d(TAG, "Acquiring WiFi Lock") wifiLock.acquire() } else { Log.d(TAG, "Releasing WiFi Lock") wifiLock.release() } - } + } else + Log.w(TAG, "No active network") } - private fun updateLinkProperties(props: LinkProperties) { - if (dynDns && (dnsServers != props.dnsServers)) { - if (isServiceRunning) - if (Config.updateDnsServers(props.dnsServers) != 0) - Log.w(TAG, "Failed to update DNS servers '${props.dnsServers}'") - else - dnsServers = props.dnsServers - else - dnsServers = props.dnsServers + private fun updateDnsServers(): Boolean { + if (isServiceRunning && !dynDns) + return false + val servers = mutableListOf() + // Use DNS servers first from active network (if given) + for (n in cm.allNetworks) + if (isNetworkActive(n)) { + val linkProps = cm.getLinkProperties(n) + if (linkProps != null) { + servers.addAll(linkProps.dnsServers) + break + } + } + // Then add DNS servers from the other networks + for (n in cm.allNetworks) { + if (isNetworkActive(n)) continue + val linkProps = cm.getLinkProperties(n) + if (linkProps != null) + for (server in linkProps.dnsServers) + if (!servers.contains(server)) servers.add(server) } - updateLinkAddresses(props.linkAddresses) + // Update if change + if (servers != dnsServers) { + if (isServiceRunning && Config.updateDnsServers(servers) != 0) { + Log.w(TAG, "Failed to update DNS servers '${servers}'") + } else { + // Log.d(TAG, "Updated DNS servers: '${servers}'") + dnsServers = servers + return true + } + } + return false } - private fun updateLinkAddresses(linkAddrs: List) { - var updated = false - val ipV6Addr = Utils.findIpV6Address(linkAddrs) - if (ipV6Addr != Utils.findIpV6Address(linkAddresses)) { - Log.d(TAG, "Updating IPv6 address to '$ipV6Addr'") - if (ipV6Addr != "") { - if (Api.net_set_address(ipV6Addr) != 0) - Log.w(TAG, "Failed to update net address '$ipV6Addr") - } else { - Api.net_unset_address(Api.AF_INET6) - } - updated = true - } - val ipV4Addr = Utils.findIpV4Address(linkAddrs) - if (ipV4Addr != Utils.findIpV4Address(linkAddresses)) { - Log.d(TAG, "Updating IPv4 address to '$ipV4Addr'") - if (ipV4Addr != "") { - if (Api.net_set_address(ipV4Addr) != 0) - Log.w(TAG, "Failed to update net address '$ipV4Addr'") - } else { - Api.net_unset_address(Api.AF_INET) - } - updated = true - } - if (updated) { - linkAddresses = linkAddrs - Api.uag_reset_transp(register = true, reinvite = true) - Api.net_debug() - } else { - UserAgent.register() + private fun activeNetwork(): Network? { + return if (VERSION.SDK_INT >= 23) + cm.activeNetwork + else { + for (n in cm.allNetworks) + if (isNetworkActive(n)) return n + return null } } @@ -1220,9 +1205,8 @@ class BaresipService: Service() { isServiceClean = true } - private external fun baresipStart(path: String, ipV4Addr: String, ipV6Addr: String, - netInterface: String, dnsServers: String, netAf: Int, - logLevel: Int) + private external fun baresipStart(path: String, ipAddrs: String, netInterface: String, + netAf: Int, logLevel: Int) private external fun baresipStop(force: Boolean) companion object { diff --git a/app/src/main/kotlin/com/tutpro/baresip/Config.kt b/app/src/main/kotlin/com/tutpro/baresip/Config.kt index 0a375eac..9099a69c 100644 --- a/app/src/main/kotlin/com/tutpro/baresip/Config.kt +++ b/app/src/main/kotlin/com/tutpro/baresip/Config.kt @@ -147,7 +147,6 @@ object Config { } fun updateDnsServers(dnsServers: List): Int { - Log.i(TAG, "Updating dnsServers with $dnsServers") var servers = "" for (dnsServer in dnsServers) { var address = dnsServer.hostAddress.removePrefix("/") diff --git a/app/src/main/kotlin/com/tutpro/baresip/Utils.kt b/app/src/main/kotlin/com/tutpro/baresip/Utils.kt index 39e2e5f4..fd12a540 100644 --- a/app/src/main/kotlin/com/tutpro/baresip/Utils.kt +++ b/app/src/main/kotlin/com/tutpro/baresip/Utils.kt @@ -9,8 +9,7 @@ import android.content.res.Configuration import android.graphics.Bitmap import android.graphics.Bitmap.createScaledBitmap import android.graphics.Color -import android.net.LinkAddress -import android.net.Uri +import android.net.* import android.os.Bundle import android.os.Environment import android.provider.DocumentsContract @@ -27,7 +26,6 @@ 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 @@ -279,36 +277,15 @@ object Utils { return true } - fun findIpV6Address(list: List): String { - for (la in list) + fun hostAddresses(list: List?): String { + var result = "" + if (list != null) for (la in list) if (la.scope == android.system.OsConstants.RT_SCOPE_UNIVERSE) - if (checkIpV6(la.address.hostAddress)) - return la.address.hostAddress - return "" - } - - fun findIpV4Address(list: List): String { - for (la in list) - if (la.scope == android.system.OsConstants.RT_SCOPE_UNIVERSE) - if (checkIpV4(la.address.hostAddress)) - return la.address.hostAddress - return "" - } - - fun findDnsServers(list: List): String { - var servers = "" - for (dnsServer in list) { - var address = dnsServer.hostAddress.removePrefix("/") - address = if (checkIpV4(address)) - "${address}:53" - else - "[${address}]:53" - servers = if (servers == "") - address - else - "${servers},${address}" - } - return servers + if (result == "") + result = la.address.hostAddress + else + result += ";" + la.address.hostAddress + return result } fun implode(list: List, sep: String): String {