From 91717628f9ecf398a5cca2196a179146655f45c3 Mon Sep 17 00:00:00 2001 From: Juha Heinanen Date: Sun, 3 Nov 2019 11:46:17 +0200 Subject: [PATCH] - Use net_set_address API function to set IPv6 address. --- app/src/main/assets/config | 2 +- app/src/main/cpp/baresip.c | 32 ++++++++- app/src/main/kotlin/com/tutpro/baresip/Api.kt | 1 + .../com/tutpro/baresip/BaresipService.kt | 65 ++++++++++--------- .../main/kotlin/com/tutpro/baresip/Config.kt | 50 +++++++------- .../main/kotlin/com/tutpro/baresip/Utils.kt | 17 +++++ 6 files changed, 109 insertions(+), 58 deletions(-) diff --git a/app/src/main/assets/config b/app/src/main/assets/config index 26b659fb..116d24a3 100644 --- a/app/src/main/assets/config +++ b/app/src/main/assets/config @@ -19,7 +19,7 @@ rtcp_mux no jitter_buffer_delay 5-10 rtp_stats no dyn_dns yes -net_prefer_ipv6 no +prefer_ipv6 no module opus.so module amr.so module ilbc.so diff --git a/app/src/main/cpp/baresip.c b/app/src/main/cpp/baresip.c index 45d92484..59c994e4 100644 --- a/app/src/main/cpp/baresip.c +++ b/app/src/main/cpp/baresip.c @@ -374,10 +374,13 @@ JNIEXPORT jint JNICALL JNI_OnLoad(JavaVM* vm, void* reserved) { } JNIEXPORT void JNICALL -Java_com_tutpro_baresip_BaresipService_baresipStart(JNIEnv *env, jobject instance, jstring javaPath) { +Java_com_tutpro_baresip_BaresipService_baresipStart(JNIEnv *env, jobject instance, + jstring javaPath, jstring javaIpV6Addr, jboolean javaPreferIpV6) { LOGD("starting baresip\n"); + struct sa temp_sa; + const char *ipv6_addr = (*env)->GetStringUTFChars(env, javaIpV6Addr, 0); char start_error[64] = ""; JavaVM *javaVM = g_ctx.javaVM; @@ -419,6 +422,12 @@ Java_com_tutpro_baresip_BaresipService_baresipStart(JNIEnv *env, jobject instanc goto out; } + if (strlen(ipv6_addr) > 0) { + LOGW("setting ipv6 net address (%s)\n", ipv6_addr); + sa_set_str(&temp_sa, ipv6_addr, 0); + net_set_address(baresip_network(), &temp_sa, (bool)(javaPreferIpV6 == JNI_TRUE)); + } + play_set_path(baresip_player(), path); err = ua_init("baresip v" BARESIP_VERSION " (" ARCH "/" OS ")", @@ -483,6 +492,8 @@ Java_com_tutpro_baresip_BaresipService_baresipStart(JNIEnv *env, jobject instanc out: + (*env)->ReleaseStringUTFChars(env, javaIpV6Addr, ipv6_addr); + if (err) { LOGE("stopping UAs due to error: (%d)\n", err); ua_stop_all(true); @@ -1366,7 +1377,7 @@ Java_com_tutpro_baresip_Api_net_1use_1nameserver(JNIEnv *env, jobject thiz, jstr str_ncpy(servers, native_servers, 256); (*env)->ReleaseStringUTFChars(env, javaServers, native_servers); server = &(servers[0]); - while((count < NET_MAX_NS) && ((comma = strchr(server, ',')) != NULL)) { + while ((count < NET_MAX_NS) && ((comma = strchr(server, ',')) != NULL)) { *comma = '\0'; err = sa_decode(&(nsv[count]), server, str_len(server)); if (err) { @@ -1387,6 +1398,23 @@ Java_com_tutpro_baresip_Api_net_1use_1nameserver(JNIEnv *env, jobject thiz, jstr return net_use_nameserver(baresip_network(), nsv, count); } +JNIEXPORT jint JNICALL +Java_com_tutpro_baresip_Api_net_1set_1address(JNIEnv *env, jobject thiz, + jstring javaIp, jboolean javaPrefer) { + const char *native_ip = (*env)->GetStringUTFChars(env, javaIp, 0); + int res = 0; + struct sa temp_sa; + LOGD("using address '%s'\n", native_ip); + if (0 == sa_set_str(&temp_sa, native_ip, 0)) { + net_set_address(baresip_network(), &temp_sa, (bool)(javaPrefer == JNI_TRUE)); + } else { + LOGE("invalid ip address %s\n", native_ip); + res = EAFNOSUPPORT; + } + (*env)->ReleaseStringUTFChars(env, javaIp, native_ip); + return res; +} + JNIEXPORT void JNICALL Java_com_tutpro_baresip_Api_net_1debug(JNIEnv *env, jobject thiz) { net_debug_log(); diff --git a/app/src/main/kotlin/com/tutpro/baresip/Api.kt b/app/src/main/kotlin/com/tutpro/baresip/Api.kt index c8ed1177..00a3eb9c 100644 --- a/app/src/main/kotlin/com/tutpro/baresip/Api.kt +++ b/app/src/main/kotlin/com/tutpro/baresip/Api.kt @@ -32,6 +32,7 @@ object Api { external fun contacts_remove() external fun log_level_set(level: Int) external fun net_use_nameserver(servers: String): Int + external fun net_set_address(ip_addr: String, preferIpV6: Boolean): Int external fun net_debug() external fun net_dns_debug() external fun module_load(module: String): Int diff --git a/app/src/main/kotlin/com/tutpro/baresip/BaresipService.kt b/app/src/main/kotlin/com/tutpro/baresip/BaresipService.kt index 2461efd5..9fc7f182 100644 --- a/app/src/main/kotlin/com/tutpro/baresip/BaresipService.kt +++ b/app/src/main/kotlin/com/tutpro/baresip/BaresipService.kt @@ -50,6 +50,8 @@ class BaresipService: Service() { internal var audioFocused = false internal var origCallVolume = -1 internal val btAdapter = BluetoothAdapter.getDefaultAdapter() + internal var dnsServers = listOf() + internal var linkAddresses = listOf() override fun onCreate() { @@ -76,18 +78,12 @@ class BaresipService: Service() { cm.registerNetworkCallback( builder.build(), object : ConnectivityManager.NetworkCallback() { + override fun onAvailable(network: Network) { super.onAvailable(network) - Log.d(LOG_TAG, "Network '$network' is available") - if (dynDns) { - val linkProperties = cm.getLinkProperties(network) - val dnsServers = linkProperties.dnsServers - if (Config.updateDnsServers(dnsServers) == 0) - Api.net_dns_debug() - else - Log.w(LOG_TAG, "Failed to update DNS servers '$dnsServers'") - } - UserAgent.register() + Log.i(LOG_TAG, "Network '${cm.getLinkProperties(network)}' is available") + dnsServers = cm.getLinkProperties(network).dnsServers + linkAddresses = cm.getLinkProperties(network).linkAddresses } override fun onLost(network: Network) { @@ -97,14 +93,26 @@ class BaresipService: Service() { override fun onLinkPropertiesChanged(network: Network, linkProperties: LinkProperties) { super.onLinkPropertiesChanged(network, linkProperties) - Log.d(LOG_TAG, "Network $network link properties changed") + Log.d(LOG_TAG, "Network link properties changed: $linkProperties") if (dynDns) { val dnsServers = linkProperties.dnsServers - if (Config.updateDnsServers(dnsServers) == 0) - Api.net_dns_debug() - else + if (Config.updateDnsServers(dnsServers) != 0) Log.w(LOG_TAG, "Failed to update DNS servers '$dnsServers'") } + if (preferIpV6) { + val ipV6Addr = Utils.findIpV6Address(linkProperties.linkAddresses) + if (ipV6Addr != "") { + if (Config.updateNetAddress(ipV6Addr, preferIpV6) != 0) + Log.w(LOG_TAG, "Failed to update net address '$ipV6Addr'") + + } else { + val ipV4Addr = Utils.findIpV4Address(linkProperties.linkAddresses) + if (ipV4Addr != "") + if (Config.updateNetAddress(ipV4Addr, !preferIpV6) != 0) + Log.w(LOG_TAG, "Failed to update net address '$ipV4Addr'") + } + } + Api.net_debug() UserAgent.register() } } @@ -239,19 +247,8 @@ class BaresipService: Service() { } else { Log.d(LOG_TAG, "Asset '$a' already copied") } - if (a == "config") { - var dnsServers = listOf() - if (Build.VERSION.SDK_INT >= 23) { - val activeNetwork = cm.activeNetwork - if (activeNetwork != null) { - dnsServers = cm.getLinkProperties(activeNetwork).dnsServers - Log.d(LOG_TAG, "DNS Servers = $dnsServers") - } else { - Log.d(LOG_TAG, "No active network!") - } - } + if (a == "config") Config.initialize(dnsServers) - } } if (File(filesDir, "history").exists()) @@ -261,12 +258,18 @@ class BaresipService: Service() { CallHistory.restore() Message.restore() - Thread(Runnable { baresipStart(filesPath) }).start() + Thread(Runnable { baresipStart(filesPath, + Utils.findIpV6Address(linkAddresses), + preferIpV6) }).start() + isServiceRunning = true + showStatusNotification() - if (Config.variable("dyn_dns")[0] == "yes") - Config.removeVariable("dns_server") + if (bindAddress != "") { + Config.removeVariable("net_interface") + Config.save() + } if (AccountsActivity.noAccounts()) { val newIntent = Intent(this, MainActivity::class.java) @@ -1010,7 +1013,7 @@ class BaresipService: Service() { isServiceClean = true } - external fun baresipStart(path: String) + external fun baresipStart(path: String, ipV6Addr: String, preferIpV6: Boolean) external fun baresipStop(force: Boolean) companion object { @@ -1041,6 +1044,8 @@ class BaresipService: Service() { var speakerPhone = false var callVolume = 0 var dynDns = false + var preferIpV6 = false + var bindAddress = "" var filesPath = "" var downloadsPath = "" diff --git a/app/src/main/kotlin/com/tutpro/baresip/Config.kt b/app/src/main/kotlin/com/tutpro/baresip/Config.kt index 81ee9be8..26f4e797 100644 --- a/app/src/main/kotlin/com/tutpro/baresip/Config.kt +++ b/app/src/main/kotlin/com/tutpro/baresip/Config.kt @@ -11,84 +11,78 @@ object Config { private var config = String(Utils.getFileContents(configPath)!!, StandardCharsets.ISO_8859_1) fun initialize(dnsServers: List) { + Log.d("Baresip", "Config is '$config'") - var write = false + if (!config.contains("zrtp_hash")) { config = "${config}zrtp_hash yes\n" - write = true } + if (!config.contains(Regex("ausrc_format s16"))) { config = "${config}ausrc_format s16\nauplay_format s16\nauenc_format s16\naudec_format s16\nmodule webrtc_aec.so\n" - write = true } + if (config.contains(Regex("#module_app[ ]+mwi.so"))) { config = config.replace(Regex("#module_app[ ]+mwi.so"), "module_app mwi.so") - write = true } + if (!config.contains("opus_application")) { config = "${config}opus_application voip\n" - write = true } + if (!config.contains("opus_samplerate")) { config = "${config}opus_samplerate 16000\n" val accountsPath = BaresipService.filesPath + "/accounts" var accounts = String(Utils.getFileContents(accountsPath)!!, StandardCharsets.ISO_8859_1) accounts = accounts.replace("opus/48000/1", "opus/16000/1") Utils.putFileContents(accountsPath, accounts.toByteArray()) - write = true } + if (!config.contains("opus_stereo")) { config = "${config}opus_stereo no\n" - write = true } + if (!config.contains("opus_sprop_stereo")) { config = "${config}opus_sprop_stereo no\n" - write = true } + if (!config.contains("log_level")) { config = "${config}log_level 2\n" Api.log_level_set(2) Log.logLevel = Log.LogLevel.WARN - write = true } else { val ll = variable("log_level")[0].toInt() Api.log_level_set(ll) Log.logLevelSet(ll) } - val preferIpv6 = variable("prefer_ipv6") - if (preferIpv6.size > 0) { - removeVariable("prefer_ipv6") - config = "net_prefer_ipv6 ${preferIpv6[0]}\n${config}" - write = true + + val preferIpV6 = variable("prefer_ipv6") + if (preferIpV6.size == 0) { + BaresipService.preferIpV6 = false } else { - if (!config.contains("net_prefer_ipv6")) { - config = "net_prefer_ipv6 no\n${config}" - write = true - } + BaresipService.preferIpV6 = preferIpV6[0] == "yes" } + if (!config.contains("call_volume")) { config = "${config}call_volume 0\n" - write = true } else { BaresipService.callVolume = variable("call_volume")[0].toInt() } + if (!config.contains("dyn_dns")) { config = "${config}dyn_dns no\n" - write = true } else { if (config.contains(Regex("dyn_dns[ ]+yes"))) { for (dnsServer in dnsServers) config = "${config}dns_server ${dnsServer.hostAddress}:53\n" BaresipService.dynDns = true - write = true } } - if (write) { - Log.e("Baresip", "Writing config '$config'") - Utils.putFileContents(configPath, config.toByteArray()) - } + Log.e("Baresip", "Initialized config to '$config'") + Utils.putFileContents(configPath, config.toByteArray()) + } fun variable(name: String): ArrayList { @@ -148,4 +142,10 @@ object Config { } return Api.net_use_nameserver(servers) } + + + fun updateNetAddress(ipAddress: String, prefer: Boolean): Int { + return Api.net_set_address(ipAddress, prefer) + } + } diff --git a/app/src/main/kotlin/com/tutpro/baresip/Utils.kt b/app/src/main/kotlin/com/tutpro/baresip/Utils.kt index 1e593f1a..56ed412d 100644 --- a/app/src/main/kotlin/com/tutpro/baresip/Utils.kt +++ b/app/src/main/kotlin/com/tutpro/baresip/Utils.kt @@ -6,6 +6,7 @@ import android.content.Context import android.support.v7.app.AlertDialog import android.content.Intent import android.content.pm.PackageManager +import android.net.LinkAddress import android.os.Bundle import android.support.v4.app.ActivityCompat import android.support.v4.content.ContextCompat @@ -227,6 +228,22 @@ object Utils { return true } + fun findIpV6Address(list: List): String { + 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 implode(list: List, sep: String): String { var res = "" for (s in list) {