Use all available network addresses and name servers

This commit is contained in:
Juha Heinanen
2021-09-19 16:30:18 +03:00
parent 72ccb8a3b1
commit 9990ddca06
5 changed files with 183 additions and 159 deletions

View File

@ -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;

View File

@ -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()

View File

@ -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<LinkAddress>()
private var linkAddresses = mutableListOf<LinkAddress>()
@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<LinkAddress>()
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<InetAddress>()
// 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<LinkAddress>) {
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 {

View File

@ -147,7 +147,6 @@ object Config {
}
fun updateDnsServers(dnsServers: List<InetAddress>): Int {
Log.i(TAG, "Updating dnsServers with $dnsServers")
var servers = ""
for (dnsServer in dnsServers) {
var address = dnsServer.hostAddress.removePrefix("/")

View File

@ -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<LinkAddress>): String {
for (la in list)
fun hostAddresses(list: List<LinkAddress>?): 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<LinkAddress>): 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<InetAddress>): 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<String>, sep: String): String {