- Added Listen Address config variable.

- Improved config handling with aid of new Config object.
This commit is contained in:
Juha Heinanen
2019-05-04 17:16:03 +03:00
parent afe762b3c7
commit 3f861b575f
9 changed files with 230 additions and 119 deletions

View File

@ -354,6 +354,8 @@ Java_com_tutpro_baresip_BaresipService_baresipStart(JNIEnv *env, jobject instanc
LOGD("Starting baresip\n"); LOGD("Starting baresip\n");
char start_error[64] = "";
BaresipContext *pctx = (BaresipContext *)(&g_ctx); BaresipContext *pctx = (BaresipContext *)(&g_ctx);
JavaVM *javaVM = pctx->javaVM; JavaVM *javaVM = pctx->javaVM;
jint res = (*javaVM)->GetEnv(javaVM, (void **) &env, JNI_VERSION_1_6); jint res = (*javaVM)->GetEnv(javaVM, (void **) &env, JNI_VERSION_1_6);
@ -382,12 +384,14 @@ Java_com_tutpro_baresip_BaresipService_baresipStart(JNIEnv *env, jobject instanc
err = conf_configure(); err = conf_configure();
if (err) { if (err) {
LOGW("conf_configure() failed: (%d)\n", err); LOGW("conf_configure() failed: (%d)\n", err);
strcpy(start_error, "conf_configure");
goto out; goto out;
} }
err = baresip_init(conf_config()); err = baresip_init(conf_config());
if (err) { if (err) {
LOGW("baresip_init() failed (%d)\n", err); LOGW("baresip_init() failed (%d)\n", err);
strcpy(start_error, "baresip_init");
goto out; goto out;
} }
@ -397,6 +401,7 @@ Java_com_tutpro_baresip_BaresipService_baresipStart(JNIEnv *env, jobject instanc
true, true, true); true, true, true);
if (err) { if (err) {
LOGE("ua_init() failed (%d)\n", err); LOGE("ua_init() failed (%d)\n", err);
strcpy(start_error, "ua_init");
goto out; goto out;
} }
@ -405,18 +410,21 @@ Java_com_tutpro_baresip_BaresipService_baresipStart(JNIEnv *env, jobject instanc
err = uag_event_register(ua_event_handler, NULL); err = uag_event_register(ua_event_handler, NULL);
if (err) { if (err) {
LOGE("uag_event_register() failed (%d)\n", err); LOGE("uag_event_register() failed (%d)\n", err);
strcpy(start_error, "uag_event_register");
goto out; goto out;
} }
err = message_listen(baresip_message(), message_handler, NULL); err = message_listen(baresip_message(), message_handler, NULL);
if (err) { if (err) {
LOGE("message_listen() failed (%d)\n", err); LOGE("message_listen() failed (%d)\n", err);
strcpy(start_error, "message_listen");
goto out; goto out;
} }
err = conf_modules(); err = conf_modules();
if (err) { if (err) {
LOGW("conf_modules() failed (%d)\n", err); LOGW("conf_modules() failed (%d)\n", err);
strcpy(start_error, "conf_modules");
goto out; goto out;
} }
@ -436,12 +444,20 @@ Java_com_tutpro_baresip_BaresipService_baresipStart(JNIEnv *env, jobject instanc
LOGI("allocating mqeue\n"); LOGI("allocating mqeue\n");
err = mqueue_alloc(&mq, mqueue_handler, NULL); err = mqueue_alloc(&mq, mqueue_handler, NULL);
if (err) if (err) {
LOGW("mqueue_alloc failed (%d)\n", err);
strcpy(start_error, "mqueue_alloc");
goto out; goto out;
}
/* char debug_buf[2048]; /* char debug_buf[2048];
int l; int l;
l = re_snprintf(&(debug_buf[0]), 2047, "%H", net_debug, baresip_network()); l = re_snprintf(&(debug_buf[0]), 2047, "%H", net_debug, baresip_network());
if (l != -1) {
debug_buf[l] = '\0';
LOGD("%s\n", debug_buf);
}
l = re_snprintf(&(debug_buf[0]), 2047, "%H", ua_print_sip_status);
if (l != -1) { if (l != -1) {
debug_buf[l] = '\0'; debug_buf[l] = '\0';
LOGD("%s\n", debug_buf); LOGD("%s\n", debug_buf);
@ -481,8 +497,11 @@ Java_com_tutpro_baresip_BaresipService_baresipStart(JNIEnv *env, jobject instanc
stopped: stopped:
LOGD("tell main that baresip has stopped"); LOGD("tell main that baresip has stopped");
jmethodID stoppedId = (*env)->GetMethodID(env, pctx->mainActivityClz, "stopped", "()V"); jstring javaError = (*env)->NewStringUTF(env, start_error);
(*env)->CallVoidMethod(env, pctx->mainActivityObj, stoppedId); jmethodID stoppedId = (*env)->GetMethodID(env, pctx->mainActivityClz, "stopped",
"(Ljava/lang/String;)V");
(*env)->CallVoidMethod(env, pctx->mainActivityObj, stoppedId, javaError);
(*env)->DeleteLocalRef(env, javaError);
return; return;
} }
@ -960,7 +979,7 @@ Java_com_tutpro_baresip_Api_ua_1destroy(JNIEnv *env, jobject thiz, jstring javaU
struct ua *ua = (struct ua *)strtoul(native_ua, NULL, 10); struct ua *ua = (struct ua *)strtoul(native_ua, NULL, 10);
LOGD("destroying ua %s\n", native_ua); LOGD("destroying ua %s\n", native_ua);
(*env)->ReleaseStringUTFChars(env, javaUA, native_ua); (*env)->ReleaseStringUTFChars(env, javaUA, native_ua);
ua_destroy(ua); (void)ua_destroy(ua);
} }
JNIEXPORT jstring JNICALL JNIEXPORT jstring JNICALL

View File

@ -127,6 +127,7 @@ class Account(val accp: String) {
fun host() : String { fun host() : String {
return aor.split("@")[1] return aor.split("@")[1]
} }
companion object { companion object {
fun accounts(): ArrayList<Account> { fun accounts(): ArrayList<Account> {

View File

@ -23,13 +23,13 @@ import android.provider.Settings
import java.io.File import java.io.File
import java.nio.charset.StandardCharsets import java.nio.charset.StandardCharsets
import java.io.InputStream
import java.util.* import java.util.*
import kotlin.math.roundToInt import kotlin.math.roundToInt
class BaresipService: Service() { class BaresipService: Service() {
private val LOG_TAG = "Baresip Service" private val LOG_TAG = "Baresip Service"
internal lateinit var intent: Intent internal lateinit var intent: Intent
internal lateinit var am: AudioManager internal lateinit var am: AudioManager
internal lateinit var rt: Ringtone internal lateinit var rt: Ringtone
@ -39,7 +39,6 @@ class BaresipService: Service() {
internal lateinit var fl: WifiManager.WifiLock internal lateinit var fl: WifiManager.WifiLock
internal var rtTimer: Timer? = null internal var rtTimer: Timer? = null
internal var filesPath = ""
internal var audioFocusRequest: AudioFocusRequest? = null internal var audioFocusRequest: AudioFocusRequest? = null
internal var audioFocused = false internal var audioFocused = false
internal var origCallVolume = 0 internal var origCallVolume = 0
@ -51,7 +50,8 @@ class BaresipService: Service() {
intent = Intent("com.tutpro.baresip.EVENT") intent = Intent("com.tutpro.baresip.EVENT")
intent.setPackage("com.tutpro.baresip") intent.setPackage("com.tutpro.baresip")
filesPath = applicationContext.filesDir.absolutePath filesPath = filesDir.absolutePath
context = applicationContext
am = getSystemService(Context.AUDIO_SERVICE) as AudioManager am = getSystemService(Context.AUDIO_SERVICE) as AudioManager
val rtUri = RingtoneManager.getActualDefaultRingtoneUri(applicationContext, val rtUri = RingtoneManager.getActualDefaultRingtoneUri(applicationContext,
@ -129,49 +129,7 @@ class BaresipService: Service() {
Utils.copyAssetToFile(applicationContext, a, "$filesPath/$a") Utils.copyAssetToFile(applicationContext, a, "$filesPath/$a")
} else { } else {
Log.d(LOG_TAG, "Asset $a already copied") Log.d(LOG_TAG, "Asset $a already copied")
if (a == "config") { if (a == "config") Config.initialize()
val inputStream: InputStream = file.inputStream()
var contents = inputStream.bufferedReader().use { it.readText() }
inputStream.close()
var write = false
if (!contents.contains("zrtp_hash")) {
contents = "${contents}zrtp_hash yes\n"
write = true
}
if (contents.contains(Regex("#module_app[ ]+mwi.so"))) {
contents = contents.replace(Regex("#module_app[ ]+mwi.so"),
"module_app mwi.so")
write = true
}
if (!contents.contains("opus_application")) {
contents = "${contents}opus_application voip\n"
write = true
}
if (!contents.contains("log_level")) {
contents = "${contents}log_level 2\n"
Api.log_level_set(2)
Log.logLevel = Log.LogLevel.WARN
write = true
} else {
val ll = Utils.getNameValue(contents, "log_level")[0].toInt()
Api.log_level_set(ll)
Log.logLevelSet(ll)
}
if (!contents.contains("prefer_ipv6")) {
contents = "prefer_ipv6 no\n${contents}"
write = true
}
if (!contents.contains("call_volume")) {
contents = "${contents}call_volume 0\n"
write = true
} else {
callVolume = Utils.getNameValue(contents, "call_volume")[0].toInt()
}
if (write) {
Log.d(LOG_TAG, "Writing '$contents'")
Utils.putFileContents(file, contents)
}
}
} }
} }
ContactsActivity.restoreContacts(applicationContext.filesDir) ContactsActivity.restoreContacts(applicationContext.filesDir)
@ -632,12 +590,13 @@ class BaresipService: Service() {
} }
@Keep @Keep
fun stopped() { fun stopped(error: String) {
Log.d(LOG_TAG, "'stopped' from baresip") Log.d(LOG_TAG, "'stopped' from baresip with error $error")
isServiceRunning = false isServiceRunning = false
if (error == "ua_init") Config.remove("sip_listen")
val intent = Intent("service event") val intent = Intent("service event")
intent.putExtra("event", "stopped") intent.putExtra("event", "stopped")
intent.putExtra("params", arrayListOf<String>()) intent.putExtra("params", arrayListOf(error))
LocalBroadcastManager.getInstance(this).sendBroadcast(intent) LocalBroadcastManager.getInstance(this).sendBroadcast(intent)
stopForeground(true) stopForeground(true)
stopSelf() stopSelf()
@ -807,6 +766,8 @@ class BaresipService: Service() {
var speakerPhone = false var speakerPhone = false
var callVolume = 0 var callVolume = 0
var filesPath = ""
var context: Context? = null
var uas = ArrayList<UserAgent>() var uas = ArrayList<UserAgent>()
var status = ArrayList<Int>() var status = ArrayList<Int>()
var calls = ArrayList<Call>() var calls = ArrayList<Call>()

View File

@ -0,0 +1,87 @@
package com.tutpro.baresip
import java.io.File
object Config {
private val path = BaresipService.filesPath + "/config"
private val file = File(path)
private val context = BaresipService.context
private var config = Utils.getFileContents(file)
fun initialize() {
var write = false
if (!config.contains("zrtp_hash")) {
config = "${config}zrtp_hash yes\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("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)
}
if (!config.contains("prefer_ipv6")) {
config = "prefer_ipv6 no\n${config}"
write = true
}
if (!config.contains("call_volume")) {
config = "${config}call_volume 0\n"
write = true
} else {
BaresipService.callVolume = variable("call_volume")[0].toInt()
}
if (write) {
Log.e("Baresip", "Writing '$config'")
Utils.putFileContents(file, config)
}
}
fun variable(name: String): ArrayList<String> {
val lines = config.split("\n")
val result = ArrayList<String>()
for (line in lines) {
if (line.startsWith(name))
result.add((line.substring(name.length).trim()).split("# \t")[0])
}
return result
}
fun add(variable: String, value: String) {
config += "\n$variable $value\n"
}
fun remove(variable: String) {
config = Utils.removeLinesStartingWithName(config, variable)
Utils.putFileContents(file, config)
}
fun replace(variable: String, value: String) {
remove(variable)
add(variable, value)
}
fun reset() {
Utils.copyAssetToFile(context!!, "config", path)
}
fun save() {
Utils.putFileContents(file, config)
Log.d("Baresip", "New config '$config'")
// Api.reload_config()
}
}

View File

@ -9,12 +9,10 @@ import android.view.MenuItem
import android.view.View import android.view.View
import android.widget.* import android.widget.*
import java.io.File
class ConfigActivity : AppCompatActivity() { class ConfigActivity : AppCompatActivity() {
internal lateinit var configFile: File
internal lateinit var autoStart: CheckBox internal lateinit var autoStart: CheckBox
internal lateinit var listenAddr: EditText
internal lateinit var preferIPv6: CheckBox internal lateinit var preferIPv6: CheckBox
internal lateinit var dnsServers: EditText internal lateinit var dnsServers: EditText
internal lateinit var opusBitRate: EditText internal lateinit var opusBitRate: EditText
@ -23,6 +21,7 @@ class ConfigActivity : AppCompatActivity() {
internal lateinit var reset: CheckBox internal lateinit var reset: CheckBox
private var oldAutoStart = "" private var oldAutoStart = ""
private var oldListenAddr = ""
private var oldPreferIPv6 = "" private var oldPreferIPv6 = ""
private var oldDnsServers = "" private var oldDnsServers = ""
private var oldOpusBitrate = "" private var oldOpusBitrate = ""
@ -38,38 +37,35 @@ class ConfigActivity : AppCompatActivity() {
super.onCreate(savedInstanceState) super.onCreate(savedInstanceState)
setContentView(R.layout.activity_config) setContentView(R.layout.activity_config)
configFile = File(applicationContext.filesDir.absolutePath + "/config")
config = Utils.getFileContents(configFile)
if (config.length <= 100) {
Utils.alertView(this, "Internal Error", "Failed to read config file")
finish()
return
}
autoStart = findViewById(R.id.AutoStart) as CheckBox autoStart = findViewById(R.id.AutoStart) as CheckBox
val asCv = Utils.getNameValue(config, "auto_start") val asCv = Config.variable("auto_start")
oldAutoStart = if (asCv.size == 0) "no" else asCv[0] oldAutoStart = if (asCv.size == 0) "no" else asCv[0]
autoStart.isChecked = oldAutoStart == "yes" autoStart.isChecked = oldAutoStart == "yes"
listenAddr = findViewById(R.id.ListenAddress) as EditText
val laCv = Config.variable("sip_listen")
oldListenAddr = if (laCv.size == 0) "" else laCv[0]
listenAddr.setText(oldListenAddr)
preferIPv6 = findViewById(R.id.PreferIPv6) as CheckBox preferIPv6 = findViewById(R.id.PreferIPv6) as CheckBox
val piCv = Utils.getNameValue(config, "prefer_ipv6") val piCv = Config.variable("prefer_ipv6")
oldPreferIPv6 = if (piCv.size == 0) "no" else piCv[0] oldPreferIPv6 = if (piCv.size == 0) "no" else piCv[0]
preferIPv6.isChecked = oldPreferIPv6 == "yes" preferIPv6.isChecked = oldPreferIPv6 == "yes"
dnsServers = findViewById(R.id.DnsServers) as EditText dnsServers = findViewById(R.id.DnsServers) as EditText
val dsCv = Utils.getNameValue(config, "dns_server") val dsCv = Config.variable("dns_server")
var dsTv = "" var dsTv = ""
for (ds in dsCv) dsTv += ", $ds" for (ds in dsCv) dsTv += ", $ds"
oldDnsServers = dsTv.trimStart(',').trimStart(' ') oldDnsServers = dsTv.trimStart(',').trimStart(' ')
dnsServers.setText(oldDnsServers) dnsServers.setText(oldDnsServers)
opusBitRate = findViewById(R.id.OpusBitRate) as EditText opusBitRate = findViewById(R.id.OpusBitRate) as EditText
val obCv = Utils.getNameValue(config, "opus_bitrate") val obCv = Config.variable("opus_bitrate")
oldOpusBitrate = if (obCv.size == 0) "28000" else obCv[0] oldOpusBitrate = if (obCv.size == 0) "28000" else obCv[0]
opusBitRate.setText(oldOpusBitrate) opusBitRate.setText(oldOpusBitrate)
iceLite = findViewById(R.id.IceLite) as CheckBox iceLite = findViewById(R.id.IceLite) as CheckBox
val imCv = Utils.getNameValue(config, "ice_mode") val imCv = Config.variable("ice_mode")
oldIceMode = if (imCv.size == 0) "full" else imCv[0] oldIceMode = if (imCv.size == 0) "full" else imCv[0]
iceLite.isChecked = oldIceMode == "lite" iceLite.isChecked = oldIceMode == "lite"
@ -95,7 +91,7 @@ class ConfigActivity : AppCompatActivity() {
} }
debug = findViewById(R.id.Debug) as CheckBox debug = findViewById(R.id.Debug) as CheckBox
val dbCv = Utils.getNameValue(config, "log_level") val dbCv = Config.variable("log_level")
if (dbCv.size == 0) if (dbCv.size == 0)
oldLogLevel = "2" oldLogLevel = "2"
else else
@ -123,17 +119,28 @@ class ConfigActivity : AppCompatActivity() {
var autoStartString = "no" var autoStartString = "no"
if (autoStart.isChecked) autoStartString = "yes" if (autoStart.isChecked) autoStartString = "yes"
if (oldAutoStart != autoStartString) { if (oldAutoStart != autoStartString) {
config = Utils.removeLinesStartingWithName(config, "auto_start") Config.replace("auto_start", autoStartString)
config += "\nauto_start $autoStartString\n"
save = true save = true
restart = false restart = false
} }
val listenAddr = listenAddr.text.toString().trim()
if (listenAddr != oldListenAddr) {
if ((listenAddr != "") && !Utils.checkIpPort(listenAddr)) {
Utils.alertView(this, "Notice",
"Invalid Listen Address '$listenAddr'")
return false
}
Config.remove("sip_listen")
if (listenAddr != "") Config.add("sip_listen", listenAddr)
save = true
restart = true
}
var preferIPv6String = "no" var preferIPv6String = "no"
if (preferIPv6.isChecked) preferIPv6String = "yes" if (preferIPv6.isChecked) preferIPv6String = "yes"
if (oldPreferIPv6 != preferIPv6String) { if (oldPreferIPv6 != preferIPv6String) {
config = Utils.removeLinesStartingWithName(config, "prefer_ipv6") Config.replace("prefer_ipv6", preferIPv6String)
config = "prefer_ipv6 $preferIPv6String\n$config"
save = true save = true
restart = true restart = true
} }
@ -144,9 +151,9 @@ class ConfigActivity : AppCompatActivity() {
Utils.alertView(this, "Notice", "Invalid DNS Servers: $dnsServers") Utils.alertView(this, "Notice", "Invalid DNS Servers: $dnsServers")
return false return false
} }
config = Utils.removeLinesStartingWithName(config, "dns_server") Config.remove("dns_server")
for (server in dnsServers.split(",")) for (server in dnsServers.split(","))
config += "\ndns_server ${server.trim()}\n" Config.add("dns_server", server)
save = true save = true
restart = true restart = true
} }
@ -157,8 +164,7 @@ class ConfigActivity : AppCompatActivity() {
Utils.alertView(this, "Notice", "Invalid Opus Bit Rate: $opusBitRate") Utils.alertView(this, "Notice", "Invalid Opus Bit Rate: $opusBitRate")
return false return false
} }
config = Utils.removeLinesStartingWithName(config, "opus_bitrate") Config.replace("opus_bitrate", opusBitRate)
config += "\nopus_bitrate $opusBitRate\n"
save = true save = true
restart = true restart = true
} }
@ -166,48 +172,33 @@ class ConfigActivity : AppCompatActivity() {
var iceModeString = "full" var iceModeString = "full"
if (iceLite.isChecked) iceModeString = "lite" if (iceLite.isChecked) iceModeString = "lite"
if (oldIceMode != iceModeString) { if (oldIceMode != iceModeString) {
config = Utils.removeLinesStartingWithName(config, "ice_mode") Config.replace("ice_mode", iceModeString)
config += "\nice_mode $iceModeString\n"
save = true save = true
restart = true restart = true
} }
if (BaresipService.callVolume != callVolume) { if (BaresipService.callVolume != callVolume) {
BaresipService.callVolume = callVolume BaresipService.callVolume = callVolume
config = Utils.removeLinesStartingWithName(config, "call_volume") Config.replace("call_volume", callVolume.toString())
config += "\ncall_volume $callVolume\n"
save = true save = true
} }
var logLevelString = "2" var logLevelString = "2"
if (debug.isChecked) logLevelString = "0" if (debug.isChecked) logLevelString = "0"
if (oldLogLevel != logLevelString) { if (oldLogLevel != logLevelString) {
config = Utils.removeLinesStartingWithName(config, "log_level") Config.replace("log_level", logLevelString)
config += "\nlog_level $logLevelString\n"
Api.log_level_set(logLevelString.toInt()) Api.log_level_set(logLevelString.toInt())
Log.logLevelSet(logLevelString.toInt()) Log.logLevelSet(logLevelString.toInt())
save = true save = true
} }
if (reset.isChecked) { if (reset.isChecked) {
Utils.copyAssetToFile(applicationContext, "config", Config.reset()
applicationContext.filesDir.absolutePath + "/config")
save = false save = false
restart = true restart = true
} }
if (save) { if (save) Config.save()
var newConfig = ""
for (line in config.split("\n")) {
val trimmedLine = line.trim()
if (trimmedLine.startsWith("#") || (trimmedLine.length == 0)) continue
// Log.d("Baresip", "Config line $trimmedLine")
newConfig += trimmedLine.split("#")[0] + "\n"
}
Log.d("Baresip", "New config '$newConfig'")
Utils.putFileContents(configFile, newConfig)
// Api.reload_config()
}
intent.putExtra("restart", restart ) intent.putExtra("restart", restart )
setResult(RESULT_OK, intent) setResult(RESULT_OK, intent)
@ -229,6 +220,9 @@ class ConfigActivity : AppCompatActivity() {
findViewById(R.id.AutoStartTitle) as TextView-> { findViewById(R.id.AutoStartTitle) as TextView-> {
Utils.alertView(this, "Start Automatically", getString(R.string.autoStart)) Utils.alertView(this, "Start Automatically", getString(R.string.autoStart))
} }
findViewById(R.id.ListenAddressTitle) as TextView-> {
Utils.alertView(this, "Listen Address", getString(R.string.listenAddress))
}
findViewById(R.id.PreferIPv6Title) as TextView-> { findViewById(R.id.PreferIPv6Title) as TextView-> {
Utils.alertView(this, "Prefer IPv6", getString(R.string.preferIPv6)) Utils.alertView(this, "Prefer IPv6", getString(R.string.preferIPv6))
} }

View File

@ -558,11 +558,25 @@ class MainActivity : AppCompatActivity() {
return return
} }
if (event == "stopped") { if (event == "stopped") {
Log.d("Baresip", "Handling service event 'stopped'") Log.d("Baresip", "Handling service event 'stopped' with param ${params[0]}")
quitTimer.cancel() if (params[0] != "") {
finishAndRemoveTask() val alertDialog = AlertDialog.Builder(this).create()
System.exit(0) alertDialog.setTitle("Notice")
return alertDialog.setMessage("Baresip failed to start! Listen Address was reset. Restart baresip.")
alertDialog.setButton(AlertDialog.BUTTON_NEUTRAL, "OK"
) { dialog, _ ->
dialog.dismiss()
quitTimer.cancel()
finishAndRemoveTask()
System.exit(0)
}
alertDialog.show()
} else {
quitTimer.cancel()
finishAndRemoveTask()
System.exit(0)
return
}
} }
val uap = params[0] val uap = params[0]
val ua = UserAgent.find(uap) val ua = UserAgent.find(uap)

View File

@ -153,14 +153,18 @@ object Utils {
return Regex("^[+]?[0-9]{1,16}\$").matches(no) return Regex("^[+]?[0-9]{1,16}\$").matches(no)
} }
fun checkIP(ip: String): Boolean { fun checkIpV4(ip: String): Boolean {
return Regex("^(([0-1]?[0-9]{1,2}\\.)|(2[0-4][0-9]\\.)|(25[0-5]\\.)){3}(([0-1]?[0-9]{1,2})|(2[0-4][0-9])|(25[0-5]))$").matches(ip) return Regex("^(([0-1]?[0-9]{1,2}\\.)|(2[0-4][0-9]\\.)|(25[0-5]\\.)){3}(([0-1]?[0-9]{1,2})|(2[0-4][0-9])|(25[0-5]))$").matches(ip)
} }
fun checkIPv6(ip: String): Boolean { fun checkIpV6(ip: String): Boolean {
return Regex("^(([0-9a-fA-F]{0,4}:){1,7}[0-9a-fA-F]{0,4})$").matches(ip) return Regex("^(([0-9a-fA-F]{0,4}:){1,7}[0-9a-fA-F]{0,4})$").matches(ip)
} }
fun checkIp(ip: String): Boolean {
return checkIpV4(ip) || checkIpV6(ip)
}
fun checkUriUser(user: String): Boolean { fun checkUriUser(user: String): Boolean {
for (c in user) for (c in user)
if (!(c.isLetterOrDigit() || c in "-_.!~*'()&=+$,;?/")) return false if (!(c.isLetterOrDigit() || c in "-_.!~*'()&=+$,;?/")) return false
@ -183,23 +187,27 @@ object Utils {
return (number > 0) && (number < 65536) return (number > 0) && (number < 65536)
} }
fun checkHostPort(hp: String, portMandatory: Boolean) : Boolean { fun checkHost(host: String): Boolean {
if (hp.startsWith("[")) { return checkIp(host) || checkDomain(host)
val parts = hp.split("]") }
if (parts.size != 2) return false
Log.d("Baresip", "Checking IPv6 '${parts[0].substring(1)}'") fun checkHostPort(hostPort: String, portMandatory: Boolean): Boolean {
if (!checkIPv6(parts[0].substring(1))) return false if (portMandatory) {
if (portMandatory && !parts[1].startsWith(":")) return false return checkHost(hostPort.substringBeforeLast(":")) &&
Log.d("Baresip", "Checking port '${parts[1].substring(1)}'") checkPort(hostPort.substringAfterLast(":"))
return checkPort(parts[1].substring(1))
} else { } else {
val parts = hp.split(":") if (hostPort.substringAfterLast(":").contains(Regex("^[0-9]+\$")))
if (portMandatory && (parts.size != 2)) return false return checkHostPort(hostPort, true)
if (parts.size == 1) return checkIP(parts[0]) || checkDomain(parts[0]) else
return checkPort(parts[1]) && (checkIP(parts[0]) || checkDomain(parts[0])) return checkHost(hostPort)
} }
} }
fun checkIpPort(ipPort: String): Boolean {
return checkIp(ipPort.substringBeforeLast(":")) &&
checkPort(ipPort.substringAfterLast(":"))
}
fun checkParams(params: String): Boolean { fun checkParams(params: String): Boolean {
for (param in params.split(";")) for (param in params.split(";"))
if (!checkParam(param)) return false if (!checkParam(param)) return false
@ -241,7 +249,7 @@ object Utils {
val userDomain = uri.replace("sip:", "").split("@") val userDomain = uri.replace("sip:", "").split("@")
if (userDomain.size != 2) return false if (userDomain.size != 2) return false
if (!checkUriUser(userDomain[0])) return false if (!checkUriUser(userDomain[0])) return false
return checkDomain(userDomain[1]) || checkIP(userDomain[1]) return checkDomain(userDomain[1]) || checkIp(userDomain[1])
} }
fun checkPrintAscii(s: String): Boolean { fun checkPrintAscii(s: String): Boolean {

View File

@ -42,6 +42,27 @@
</CheckBox> </CheckBox>
</RelativeLayout> </RelativeLayout>
<TextView
android:id="@+id/ListenAddressTitle"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerVertical="true"
android:onClick="onClick"
android:text="Listen Address"
android:textColor="@android:color/black"
android:textSize="18sp" >
</TextView>
<EditText
android:id="@+id/ListenAddress"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_centerVertical="true"
android:layout_marginBottom="12dp"
android:textSize="18sp"
android:hint="0.0.0.0:5060" >
</EditText>
<RelativeLayout <RelativeLayout
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"

View File

@ -54,6 +54,12 @@
<string name="defaultAccount">If checked, this account is selected when baresip is started. <string name="defaultAccount">If checked, this account is selected when baresip is started.
</string>> </string>>
<string name="autoStart">If checked, baresip starts automatically after device (re)start.</string> <string name="autoStart">If checked, baresip starts automatically after device (re)start.</string>
<string name="listenAddress">IP address and port of form \'address:port\' at which baresip listens
for incoming SIP requests. If IP address is an IPv6 address, it must be written inside
brackets []. IPv4 address 0.0.0.0 or IPv6 address [::] makes baresip listen at all
available addresses. If left empty (factory default), baresip listens at port 5060 of
all available addresses.
</string>
<string name="preferIPv6">Prefer IPv6 if both IPv4 and IPv6 are available.</string> <string name="preferIPv6">Prefer IPv6 if both IPv4 and IPv6 are available.</string>
<string name="dnsServers">Comma separated list of DNS servers. Each DNS server is of form <string name="dnsServers">Comma separated list of DNS servers. Each DNS server is of form
\'server:port\'. If server is an IPv6 address, the address must be written inside brackets []. \'server:port\'. If server is an IPv6 address, the address must be written inside brackets [].