- Replaced global setting "Prefer IPv6" with account specific

"Prefer IPv6 Media" setting.
- Improved acting on changes in network connectivity.
This commit is contained in:
Juha Heinanen
2020-02-07 01:19:41 +02:00
parent 85b8520fe9
commit 86b60fa0f8
13 changed files with 185 additions and 149 deletions

View File

@ -19,7 +19,6 @@ rtcp_mux no
jitter_buffer_delay 5-10
rtp_stats no
dyn_dns yes
prefer_ipv6 no
module opus.so
module amr.so
module ilbc.so

View File

@ -58,6 +58,16 @@ static void net_dns_debug_log() {
}
}
static void ua_debug_log(struct ua *ua) {
char debug_buf[2048];
int l;
l = re_snprintf(&(debug_buf[0]), 2047, "%H", ua_debug, ua);
if (l != -1) {
debug_buf[l] = '\0';
LOGD("%s\n", debug_buf);
}
}
static void ua_print_status_log(struct ua *ua) {
char debug_buf[2048];
int l;
@ -375,13 +385,17 @@ JNIEXPORT jint JNICALL JNI_OnLoad(JavaVM* vm, void* reserved) {
JNIEXPORT void JNICALL
Java_com_tutpro_baresip_BaresipService_baresipStart(JNIEnv *env, jobject instance,
jstring javaPath, jstring javaIpV4Addr, jstring javaIpV6Addr, jboolean javaPreferIpV6) {
jstring javaPath, jstring javaIpV4Addr, jstring javaIpV6Addr,
jstring javaNetInterface, jint javaNetAf) {
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;
char start_error[64] = "";
JavaVM *javaVM = g_ctx.javaVM;
@ -416,6 +430,15 @@ Java_com_tutpro_baresip_BaresipService_baresipStart(JNIEnv *env, jobject instanc
goto out;
}
if (strlen(net_interface) > 0) {
struct config *theconf = conf_config();
str_ncpy(theconf->net.ifname, net_interface,
sizeof(theconf->net.ifname));
}
if (net_af != AF_UNSPEC)
conf_config()->net.af = net_af;
err = baresip_init(conf_config());
if (err) {
LOGW("baresip_init() failed (%d)\n", err);
@ -425,13 +448,14 @@ Java_com_tutpro_baresip_BaresipService_baresipStart(JNIEnv *env, jobject instanc
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);
net_set_af(baresip_network(), javaPreferIpV6 == JNI_TRUE ? AF_INET6 : AF_INET);
}
net_debug_log();
@ -1157,6 +1181,23 @@ Java_com_tutpro_baresip_Api_ua_1answer(JNIEnv *env, jobject thiz, jstring javaUA
(*env)->ReleaseStringUTFChars(env, javaCall, native_call);
}
JNIEXPORT void JNICALL
Java_com_tutpro_baresip_Api_ua_1set_1media_1af(JNIEnv *env, jobject thiz, jstring javaUA,
jint javaAf) {
const char *native_ua = (*env)->GetStringUTFChars(env, javaUA, 0);
struct ua *ua = (struct ua *)strtoul(native_ua, NULL, 10);
LOGD("setting ua media af to '%d'\n", javaAf);
ua_set_media_af(ua, javaAf);
}
JNIEXPORT void JNICALL
Java_com_tutpro_baresip_Api_ua_1debug(JNIEnv *env, jobject thiz, jstring javaUA) {
const char *native_ua = (*env)->GetStringUTFChars(env, javaUA, 0);
struct ua *ua = (struct ua *)strtoul(native_ua, NULL, 10);
ua_debug_log(ua);
}
JNIEXPORT jint JNICALL
Java_com_tutpro_baresip_Api_call_1connect(JNIEnv *env, jobject thiz, jstring javaCall,
jstring javaPeer) {
@ -1440,33 +1481,18 @@ Java_com_tutpro_baresip_Api_net_1set_1address(JNIEnv *env, jobject thiz, jstring
}
JNIEXPORT void JNICALL
Java_com_tutpro_baresip_Api_net_1unset_1address(JNIEnv *env, jobject thiz, jboolean javaIpV6) {
int res = 0;
Java_com_tutpro_baresip_Api_net_1unset_1address(JNIEnv *env, jobject thiz, jint javaAf) {
struct sa temp_sa;
LOGD("unsetting %s address\n", javaIpV6 == JNI_TRUE ? "IPv6" : "IpV4");
if (javaIpV6 == JNI_TRUE)
sa_init(&temp_sa, AF_INET6);
else
sa_init(&temp_sa, AF_INET);
LOGD("unsetting AF '%d' address\n", javaAf);
sa_init(&temp_sa, javaAf);
net_set_address(baresip_network(), &temp_sa);
}
JNIEXPORT jboolean JNICALL
Java_com_tutpro_baresip_Api_net_1set_1af(JNIEnv *env, jobject thiz, jboolean javaIpV6) {
int af = javaIpV6 == JNI_TRUE ? AF_INET6 : AF_INET;
int res = 0;
LOGD("setting af '%d'\n", af);
if (net_af(baresip_network()) != af) {
net_set_af(baresip_network(), af);
return true;
}
return false;
}
JNIEXPORT void JNICALL
Java_com_tutpro_baresip_Api_net_1force_1change(JNIEnv *env, jobject thiz) {
LOGD("forcing net change\n");
net_force_change(baresip_network());
Java_com_tutpro_baresip_Api_uag_1reset_1transp(JNIEnv *env, jobject thiz, jboolean reg,
jboolean reinvite) {
LOGD("reseting transports (%d, %d)\n", reg, reinvite);
(void)uag_reset_transp(reg, reinvite);
}
JNIEXPORT void JNICALL

View File

@ -17,6 +17,7 @@ class Account(val accp: String) {
var audioCodec = ArrayList<String>()
var regint = account_regint(accp)
var mediaEnc = account_mediaenc(accp)
var preferIPv6Media = false
var answerMode = ""
var vmUri = account_vm_uri(accp)
var vmNew = 0
@ -59,6 +60,7 @@ class Account(val accp: String) {
}
val extra = account_extra(accp)
preferIPv6Media = Utils.paramValue(extra,"prefer_ipv6_media") == "yes"
answerMode = Utils.paramValue(extra,"answer_mode")
if (answerMode == "") answerMode = "manual"
callHistory = Utils.paramValue(extra,"call_history") == ""
@ -112,14 +114,18 @@ class Account(val accp: String) {
res += ";ptime=20;regint=${regint};regq=0.5;pubint=0;call_transfer=yes"
var extra = ""
if (!callHistory) extra = "call_history=no"
if (answerMode == "auto") {
if (extra == "")
extra = "answer_mode=auto"
else
if (!callHistory)
extra += ";call_history=no"
if (answerMode == "auto")
extra += ";answer_mode=auto"
}
res += ";extra=\"$extra\""
if (preferIPv6Media)
extra += ";prefer_ipv6_media=yes"
if (extra != "")
res += ";extra=\"" + extra.substringAfter(";") + "\""
return res
}

View File

@ -27,6 +27,7 @@ class AccountActivity : AppCompatActivity() {
internal lateinit var stunServer: EditText
internal lateinit var regCheck: CheckBox
internal lateinit var mediaEnc: String
internal lateinit var ipV6MediaCheck: CheckBox
internal lateinit var answerMode: String
internal lateinit var vmUri: EditText
internal lateinit var defaultCheck: CheckBox
@ -156,6 +157,9 @@ class AccountActivity : AppCompatActivity() {
}
}
ipV6MediaCheck = findViewById(R.id.PreferIPv6Media) as CheckBox
ipV6MediaCheck.isChecked = acc.preferIPv6Media
answerMode = acc.answerMode
val answerModeSpinner = findViewById(R.id.answerModeSpinner) as Spinner
val answerModeKeys = arrayListOf("manual", "auto")
@ -377,6 +381,16 @@ class AccountActivity : AppCompatActivity() {
}
}
if (ipV6MediaCheck.isChecked != acc.preferIPv6Media) {
acc.preferIPv6Media = ipV6MediaCheck.isChecked
Log.d("Baresip", "New preferIPv6Media is ${acc.preferIPv6Media}")
if (acc.preferIPv6Media)
Api.ua_set_media_af(ua.uap, Api.AF_INET6)
else
Api.ua_set_media_af(ua.uap, Api.AF_UNSPEC)
save = true
}
if (answerMode != acc.answerMode) {
acc.answerMode = answerMode
Log.d("Baresip", "New answermode is ${acc.answerMode}")
@ -415,6 +429,8 @@ class AccountActivity : AppCompatActivity() {
AccountsActivity.saveAccounts()
if (Api.ua_update_account(ua.uap) != 0)
Log.e("Baresip", "Failed to update UA ${ua.uap} with AoR $aor")
//else
//Api.ua_debug(ua.uap)
}
if (regCheck.isChecked) Api.ua_register(ua.uap)
@ -485,6 +501,10 @@ class AccountActivity : AppCompatActivity() {
Utils.alertView(this, getString(R.string.media_encryption),
getString(R.string.media_encryption_help))
}
findViewById(R.id.PreferIPv6MediaTitle) as TextView -> {
Utils.alertView(this, getString(R.string.prefer_ipv6_media),
getString(R.string.prefer_ipv6_media_help))
}
findViewById(R.id.AnswerModeTitle) as TextView -> {
Utils.alertView(this, getString(R.string.answer_mode),
getString(R.string.answer_mode_help))

View File

@ -2,8 +2,13 @@ package com.tutpro.baresip
object Api {
val AF_UNSPEC = 0
val AF_INET = 2
val AF_INET6 = 10
external fun audio_codecs(): String
external fun uag_current_set(uap: String)
external fun uag_reset_transp(reg: Boolean, reinvite: Boolean)
external fun ua_account(ua: String): String
external fun ua_alloc(uri: String): String
external fun ua_update_account(ua: String): Int
@ -15,6 +20,8 @@ object Api {
external fun ua_hangup(uap: String, callp: String, code: Int, reason: String)
external fun ua_call_alloc(uap: String, xcallp: String): String
external fun ua_answer(uap: String, callp: String)
external fun ua_set_media_af(uap: String, af: Int)
external fun ua_debug(uap: String)
external fun call_hold(callp: String): Int
external fun call_unhold(callp: String): Int
external fun call_connect(callp: String, peer_uri: String): Int
@ -33,9 +40,7 @@ object Api {
external fun log_level_set(level: Int)
external fun net_use_nameserver(servers: String): Int
external fun net_set_address(ip_addr: String): Int
external fun net_unset_address(ipv6: Boolean)
external fun net_set_af(ipv6: Boolean): Boolean
external fun net_force_change()
external fun net_unset_address(af: Int)
external fun net_debug()
external fun net_dns_debug()
external fun module_load(module: String): Int

View File

@ -87,9 +87,10 @@ class BaresipService: Service() {
super.onAvailable(network)
val linkProperties = cm.getLinkProperties(network)
Log.i(LOG_TAG, "Network $network is available: '$linkProperties'")
if (activeNetwork == null) {
Log.i(LOG_TAG, "Updating dnsServers and linkAddresses")
activeNetwork = network
activeNetwork = network
if (isServiceRunning) {
Utils.updateLinkProperties(linkProperties)
} else {
dnsServers = linkProperties.dnsServers
linkAddresses = linkProperties.linkAddresses
}
@ -107,15 +108,7 @@ class BaresipService: Service() {
break
}
if (activeNetwork != null) {
val linkProperties = cm.getLinkProperties(activeNetwork)
if (dynDns) {
dnsServers = linkProperties.dnsServers
if (Config.updateDnsServers(dnsServers) != 0)
Log.w(LOG_TAG, "Failed to update DNS servers '$dnsServers'")
}
linkAddresses = linkProperties.linkAddresses
Utils.updateLinkAddresses()
UserAgent.register()
Utils.updateLinkProperties(cm.getLinkProperties(activeNetwork))
}
} else {
Log.d(LOG_TAG, "Network '$network' is lost")
@ -127,16 +120,14 @@ class BaresipService: Service() {
if (!isServiceRunning)
return
if (network == activeNetwork) {
Log.e(LOG_TAG, "Active network $network link properties changed: " +
Log.d(LOG_TAG, "Active network $network link properties changed: " +
"$linkProperties")
if (dynDns) {
if (isServiceRunning) {
Utils.updateLinkProperties(linkProperties)
} else {
dnsServers = linkProperties.dnsServers
if (Config.updateDnsServers(dnsServers) != 0)
Log.w(LOG_TAG, "Failed to update DNS servers '$dnsServers'")
linkAddresses = linkProperties.linkAddresses
}
linkAddresses = linkProperties.linkAddresses
Utils.updateLinkAddresses()
// UserAgent.register()
} else {
Log.e(LOG_TAG, "Network $network link properties changed: " +
"$linkProperties")
@ -288,7 +279,8 @@ class BaresipService: Service() {
Thread(Runnable { baresipStart(filesPath,
Utils.findIpV4Address(linkAddresses),
Utils.findIpV6Address(linkAddresses),
preferIpV6) }).start()
"", Api.AF_UNSPEC)
}).start()
isServiceRunning = true
@ -437,9 +429,11 @@ class BaresipService: Service() {
@Keep
fun uaAdd(uap: String) {
Log.d(LOG_TAG, "uaAdd at BaresipService")
val ua = UserAgent(uap)
Log.d(LOG_TAG, "uaAdd ${ua.account.aor} at BaresipService")
uas.add(ua)
if (ua.account.preferIPv6Media)
Api.ua_set_media_af(ua.uap, Api.AF_INET6)
if (Api.ua_isregistered(uap)) {
Log.d(LOG_TAG, "Ua ${ua.account.aor} is registered")
status.add(R.drawable.dot_green)
@ -456,13 +450,14 @@ class BaresipService: Service() {
@Keep
fun uaEvent(event: String, uap: String, callp: String) {
Log.d(LOG_TAG, "uaEvent got event $event/$uap/$callp")
if (!isServiceRunning) return
val ua = UserAgent.find(uap)
if (ua == null) {
Log.w(LOG_TAG, "uaEvent did not find ua $uap")
return
}
Log.d(LOG_TAG, "got uaEvent $event/${ua.account.aor}/$callp")
val aor = ua.account.aor
var newEvent: String? = null
val ev = event.split(",")
@ -829,6 +824,7 @@ class BaresipService: Service() {
isServiceRunning = false
if (error == "ua_init") {
Config.removeVariable("sip_listen")
Config.removeVariable("net_interface")
Config.removeVariable("sip_certificate")
Config.removeVariable("sip_cafile")
}
@ -1042,7 +1038,8 @@ class BaresipService: Service() {
isServiceClean = true
}
external fun baresipStart(path: String, ipV4Addr: String, ipV6Addr: String, preferIpV6: Boolean)
external fun baresipStart(path: String, ipV4Addr: String, ipV6Addr: String, netInterface: String,
netAf: Int)
external fun baresipStop(force: Boolean)
companion object {
@ -1073,7 +1070,7 @@ class BaresipService: Service() {
var speakerPhone = false
var callVolume = 0
var dynDns = false
var preferIpV6 = false
var netInterface = ""
var filesPath = ""
var downloadsPath = ""
@ -1085,8 +1082,8 @@ class BaresipService: Service() {
val contacts = ArrayList<Contact>()
val chatTexts: MutableMap<String, String> = mutableMapOf<String, String>()
val activities = mutableListOf<String>()
var dnsServers = listOf<InetAddress>()
var linkAddresses = listOf<LinkAddress>()
var dnsServers = listOf<InetAddress>()
}

View File

@ -57,14 +57,8 @@ object Config {
Log.logLevelSet(ll)
}
removeVariable("net_interface")
removeVariable("net_prefer_ipv6")
val preferIpV6 = variable("prefer_ipv6")
if (preferIpV6.size == 0) {
BaresipService.preferIpV6 = false
} else {
BaresipService.preferIpV6 = preferIpV6[0] == "yes"
if (config.contains("net_interface")) {
BaresipService.netInterface = variable("net_interface")[0]
}
if (!config.contains("call_volume")) {

View File

@ -19,7 +19,6 @@ class ConfigActivity : AppCompatActivity() {
internal lateinit var autoStart: CheckBox
internal lateinit var listenAddr: EditText
internal lateinit var preferIPv6: CheckBox
internal lateinit var dnsServers: EditText
internal lateinit var certificateFile: CheckBox
internal lateinit var caFile: CheckBox
@ -32,7 +31,6 @@ class ConfigActivity : AppCompatActivity() {
private var oldAutoStart = ""
private var oldListenAddr = ""
private var oldPreferIPv6 = ""
private var oldDnsServers = ""
private var oldCertificateFile = false
private var oldCAFile = false
@ -68,11 +66,6 @@ class ConfigActivity : AppCompatActivity() {
oldListenAddr = if (laCv.size == 0) "" else laCv[0]
listenAddr.setText(oldListenAddr)
preferIPv6 = findViewById(R.id.PreferIPv6) as CheckBox
val piCv = Config.variable("prefer_ipv6")
oldPreferIPv6 = if (piCv.size == 0) "no" else piCv[0]
preferIPv6.isChecked = oldPreferIPv6 == "yes"
dnsServers = findViewById(R.id.DnsServers) as EditText
val ddCv = Config.variable("dyn_dns")
if (ddCv[0] == "yes") {
@ -220,15 +213,6 @@ class ConfigActivity : AppCompatActivity() {
restart = true
}
var preferIPv6String = "no"
if (preferIPv6.isChecked) preferIPv6String = "yes"
if (oldPreferIPv6 != preferIPv6String) {
Config.replaceVariable("prefer_ipv6", preferIPv6String)
BaresipService.preferIpV6 = preferIPv6String == "yes"
Utils.updateLinkAddresses()
save = true
}
val dnsServers = addMissingPorts(dnsServers.text.toString().trim().toLowerCase())
if (dnsServers != oldDnsServers) {
if (!checkDnsServers(dnsServers)) {
@ -461,10 +445,6 @@ class ConfigActivity : AppCompatActivity() {
Utils.alertView(this, getString(R.string.listen_address),
getString(R.string.listen_address_help))
}
findViewById(R.id.PreferIPv6Title) as TextView-> {
Utils.alertView(this, getString(R.string.prefer_ipv6),
getString(R.string.prefer_ipv6_help))
}
findViewById(R.id.DnsServersTitle) as TextView -> {
Utils.alertView(this, getString(R.string.dns_servers),
getString(R.string.dns_servers_help))

View File

@ -10,6 +10,7 @@ import android.graphics.Bitmap
import android.graphics.Bitmap.createScaledBitmap
import android.graphics.Color
import android.net.LinkAddress
import android.net.LinkProperties
import android.os.Bundle
import android.support.v4.app.ActivityCompat
import android.support.v4.content.ContextCompat
@ -254,34 +255,46 @@ object Utils {
return ""
}
fun updateLinkAddresses() {
val ipV6Addr = findIpV6Address(BaresipService.linkAddresses)
if (ipV6Addr != "") {
Log.d("Baresip", "Found IPv6 address '$ipV6Addr'")
if (Api.net_set_address(ipV6Addr) != 0) {
Log.w("Baresip", "Failed to update net address '$ipV6Addr'")
private fun updateLinkAddresses(linkAddresses: List<LinkAddress>) {
var updated = false
val ipV6Addr = findIpV6Address(linkAddresses)
if (ipV6Addr != findIpV6Address(BaresipService.linkAddresses)) {
Log.d("Baresip", "Updating IPv6 address to '$ipV6Addr'")
if (ipV6Addr != "") {
if (Api.net_set_address(ipV6Addr) != 0)
Log.w("Baresip", "Failed to update net address '$ipV6Addr")
} else {
Api.net_set_af(BaresipService.preferIpV6)
Api.net_unset_address(Api.AF_INET6)
}
} else {
Api.net_unset_address(true)
Api.net_set_af(false)
updated = true
}
val ipV4Addr = findIpV4Address(BaresipService.linkAddresses)
if (ipV4Addr != "") {
Log.w("Baresip", "Found IPv4 address '$ipV4Addr'")
if (Api.net_set_address(ipV4Addr) != 0) {
Log.w("Baresip", "Failed to update net address '$ipV4Addr'")
val ipV4Addr = findIpV4Address(linkAddresses)
if (ipV4Addr != findIpV4Address(BaresipService.linkAddresses)) {
Log.d("Baresip", "Updating IPv4 address to '$ipV4Addr'")
if (ipV4Addr != "") {
if (Api.net_set_address(ipV4Addr) != 0)
Log.w("Baresip", "Failed to update net address '$ipV4Addr'")
} else {
if (!BaresipService.preferIpV6 || (ipV6Addr == ""))
Api.net_set_af(false)
Api.net_unset_address(Api.AF_INET)
}
} else {
Api.net_unset_address(false)
Api.net_set_af(false)
updated = true
}
Api.net_force_change()
Api.net_debug()
if (updated) {
BaresipService.linkAddresses = linkAddresses
Api.uag_reset_transp(true,true)
Api.net_debug()
}
}
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}'")
else
BaresipService.dnsServers = linkProperties.dnsServers
}
updateLinkAddresses(linkProperties.linkAddresses)
}
fun implode(list: List<String>, sep: String): String {

View File

@ -221,6 +221,32 @@
android:paddingTop="8dp" >
</Spinner>
<RelativeLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="horizontal" >
<TextView
android:id="@+id/PreferIPv6MediaTitle"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentStart="true"
android:layout_toStartOf="@id/PreferIPv6Media"
android:paddingTop="10dp"
android:textSize="18sp"
android:textColor="@android:color/black"
android:onClick="onClick"
android:text="@string/prefer_ipv6_media" >
</TextView>
<CheckBox
android:id="@+id/PreferIPv6Media"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentEnd="true"
android:layout_gravity="end"
android:checked="false" >
</CheckBox>
</RelativeLayout>
<TextView
android:id="@+id/AnswerModeTitle"
android:layout_width="wrap_content"

View File

@ -64,34 +64,6 @@
android:importantForAutofill="no" >
</EditText>
<RelativeLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginBottom="12dp"
android:orientation="horizontal" >
<TextView
android:id="@+id/PreferIPv6Title"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentStart="true"
android:layout_centerVertical="true"
android:layout_toStartOf="@id/PreferIPv6"
android:textSize="18sp"
android:textColor="@android:color/black"
android:onClick="onClick"
android:text="@string/prefer_ipv6" >
</TextView>
<CheckBox
android:id="@+id/PreferIPv6"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentEnd="true"
android:layout_centerVertical="true"
android:layout_gravity="end"
android:checked="false" >
</CheckBox>
</RelativeLayout>
<TextView
android:id="@+id/DnsServersTitle"
android:layout_width="wrap_content"

View File

@ -89,6 +89,11 @@
lähteviin puheluihin ja että RTP/SAVP- tai RTP/SAVPF-protokollaa
käytetään, jos sellaista tarjotaan tulevissa puheluissa.
</string>
<string name="prefer_ipv6_media">Suosi IPv6-mediaprotokollaa</string>
<string name="prefer_ipv6_media_help">Jos merkitty, tarjoa IPv6-mediaprotokollaa (mikäli
se on käytettävissä), jos puhelun molempien osapuolten tukemaa mediaprotokollaa
ei saada automaattisesti selvitettyä.
</string>
<string name="answer_mode">Vastaustapa</string>
<string name="answer_mode_help">Valitsee tulevien puheluiden vastaustavan.</string>
<string name="manual">Manuaalinen</string>
@ -181,12 +186,6 @@
osoitteilla.
</string>
<string name="invalid_listen_address">Virheellinen kuunteluosoite</string>
<string name="prefer_ipv6">Suosi IPv6-protokollaa</string>
<string name="prefer_ipv6_help">Jos merkitty, baresip käyttää
IPv6-protokollaa, mikäli sekä IPv4 että IPv6 ovat käytettävissä. Jos
ei merkitty ja molemmat ovat käytettävissä, baresip käyttää
IPv4-protokollaa.
</string>
<string name="dns_servers">DNS-palvelimet</string>
<string name="dns_servers_help">Pilkulla toisistaan erotettu luettelo DNS-palvelijoiden
osoitteita. Jos jätetään antamatta (oletus), osoitteet hankitaan dynaamisesti järjestelmästä.

View File

@ -84,6 +84,10 @@
\n • SRTP means that RTP/AVP is offered in outgoing call and that RTP/SAVP or RTP/SAVPF is used
if offered in incoming call.
</string>
<string name="prefer_ipv6_media">Prefer IPv6 Media</string>
<string name="prefer_ipv6_media_help">If checked, offer to use IPv6 media protocol (if available)
when media protocol of peer cannot be automatically determined.
</string>
<string name="answer_mode">Answer Mode</string>
<string name="answer_mode_help">Selects how incoming calls are answered.</string>
<string name="manual">Manual</string>
@ -172,11 +176,6 @@
</string>
<string name="invalid_listen_address">Invalid Listen Address</string>
<string name="_0_0_0_0_5060" translatable="false">0.0.0.0:5060</string>
<string name="prefer_ipv6">Prefer IPv6</string>
<string name="prefer_ipv6_help">If checked, baresip uses IPv6
protocol if both IPv4 and IPv6 are available. If not checked and
both are available, baresip uses IPv4.
</string>
<string name="dns_servers">DNS Servers</string>
<string name="dns_servers_help">Comma separated list of addresses of DNS servers. If not given,
DNS server addresses are obtained dynamically from the system. Each DNS address is of form