326 lines
10 KiB
Kotlin
326 lines
10 KiB
Kotlin
package com.tutpro.baresip
|
|
|
|
import android.content.Context
|
|
import java.net.URLDecoder
|
|
import java.net.URLEncoder
|
|
import java.util.Locale
|
|
|
|
class Account(val accp: Long, virtualAor: String? = null) {
|
|
|
|
var isMobile = false
|
|
var nickName = ""
|
|
var displayName = if (accp != 0L) Api.account_display_name(accp) else ""
|
|
val aor = if (accp != 0L) Api.account_aor(accp) else (virtualAor ?: "")
|
|
val luri = if (accp != 0L) Api.account_luri(accp) else (virtualAor ?: "")
|
|
var authUser = if (accp != 0L) Api.account_auth_user(accp) else ""
|
|
var authPass = if (accp != 0L) Api.account_auth_pass(accp) else ""
|
|
var outbound = ArrayList<String>()
|
|
var mediaNat = if (accp != 0L) Api.account_medianat(accp) else ""
|
|
var stunServer = if (accp != 0L) Api.account_stun_uri(accp) else ""
|
|
var stunUser = if (accp != 0L) Api.account_stun_user(accp) else ""
|
|
var stunPass = if (accp != 0L) Api.account_stun_pass(accp) else ""
|
|
var audioCodec = ArrayList<String>()
|
|
var videoCodec = ArrayList<String>()
|
|
var regint = if (accp != 0L) Api.account_regint(accp) else 0
|
|
var checkOrigin = if (accp != 0L) Api.account_check_origin(accp) else true
|
|
var configuredRegInt = REGISTRATION_INTERVAL
|
|
var mediaEnc = if (accp != 0L) Api.account_mediaenc(accp) else ""
|
|
var rtcpMux = if (accp != 0L) Api.account_rtcp_mux(accp) else false
|
|
var rel100Mode = if (accp != 0L) Api.account_rel100_mode(accp) else Api.REL100_DISABLED
|
|
var dtmfMode = if (accp != 0L) Api.account_dtmfmode(accp) else Api.DTMFMODE_AUTO
|
|
var answerMode = if (accp != 0L) Api.account_answermode(accp) else Api.ANSWERMODE_MANUAL
|
|
var autoRedirect = if (accp != 0L) Api.account_sip_autoredirect(accp) else false
|
|
var blockUnknown = false
|
|
var vmUri = if (accp != 0L) Api.account_vm_uri(accp) else ""
|
|
var vmNew = 0
|
|
var vmOld = 0
|
|
var missedCalls = false
|
|
var unreadMessages = false
|
|
var callHistory = true
|
|
var countryCode = ""
|
|
var telProvider = if (accp != 0L) Utils.aorDomain(aor) else ""
|
|
var resumeUri = ""
|
|
var numericKeypad = false
|
|
var customParams = ""
|
|
|
|
init {
|
|
if (accp != 0L) {
|
|
if (authPass == "")
|
|
authPass = NO_AUTH_PASS
|
|
|
|
var i = 0
|
|
while (true) {
|
|
val ob = Api.account_outbound(accp, i)
|
|
if (ob != "") {
|
|
outbound.add(ob)
|
|
i++
|
|
} else {
|
|
break
|
|
}
|
|
}
|
|
|
|
i = 0
|
|
while (true) {
|
|
val ac = Api.account_audio_codec(accp, i)
|
|
if (ac != "") {
|
|
audioCodec.add(ac)
|
|
i++
|
|
} else {
|
|
break
|
|
}
|
|
}
|
|
}
|
|
|
|
val extra = Api.account_extra(accp)
|
|
if (Utils.paramExists(extra, "nickname"))
|
|
nickName = Utils.paramValue(extra, "nickname")
|
|
isMobile = Utils.paramExists(extra, "is_mobile")
|
|
if (Utils.paramExists(extra, "regint"))
|
|
configuredRegInt = Utils.paramValue(extra, "regint").toInt()
|
|
callHistory = Utils.paramValue(extra, "call_history") == ""
|
|
blockUnknown = Utils.paramExists(extra, "block_unknown")
|
|
if (Utils.paramExists(extra, "country_code"))
|
|
countryCode = Utils.paramValue(extra, "country_code")
|
|
if (Utils.paramExists(extra, "tel_provider"))
|
|
telProvider = URLDecoder.decode(Utils.paramValue(extra, "tel_provider"), "UTF-8")
|
|
numericKeypad = Utils.paramExists(extra, "numeric_keypad")
|
|
customParams = extra.substringAfter("last=empty").substringAfter(";")
|
|
}
|
|
|
|
fun print() : String {
|
|
|
|
var res = if (isMobile) {
|
|
"<${aor};transport=udp>"
|
|
} else {
|
|
if (displayName != "")
|
|
"\"${displayName}\" "
|
|
else
|
|
""
|
|
}
|
|
|
|
if (!isMobile) {
|
|
res = "$res<$luri>"
|
|
if (authUser != "") res += ";auth_user=\"${authUser}\""
|
|
}
|
|
|
|
if ((authPass != "") && !BaresipService.aorPasswords.containsKey(aor))
|
|
res += ";auth_pass=\"${authPass}\""
|
|
|
|
if (outbound.isNotEmpty()) {
|
|
res += ";outbound=\"${outbound[0]}\""
|
|
if (outbound.size > 1) res += ";outbound2=\"${outbound[1]}\""
|
|
res = "$res;sipnat=outbound"
|
|
}
|
|
|
|
if (!checkOrigin) res += ";check_origin=no"
|
|
|
|
if (mediaNat != "") res += ";medianat=${mediaNat}"
|
|
|
|
if (stunServer != "")
|
|
res += ";stunserver=\"${stunServer}\""
|
|
|
|
if (stunUser != "")
|
|
res += ";stunuser=\"${stunUser}\""
|
|
|
|
if (stunPass != "")
|
|
res += ";stunpass=\"${stunPass}\""
|
|
|
|
if (audioCodec.isNotEmpty()) {
|
|
var first = true
|
|
res = "$res;audio_codecs="
|
|
for (c in audioCodec)
|
|
if (first) {
|
|
res += c
|
|
first = false
|
|
} else {
|
|
res = "$res,$c"
|
|
}
|
|
}
|
|
|
|
if (mediaEnc != "") res += ";mediaenc=${mediaEnc}"
|
|
|
|
if (rtcpMux)
|
|
res += ";rtcp_mux=yes"
|
|
|
|
res += if (rel100Mode == Api.REL100_ENABLED)
|
|
";100rel=yes"
|
|
else
|
|
";100rel=no"
|
|
|
|
if (dtmfMode == Api.DTMFMODE_SIP_INFO)
|
|
res += ";dtmfmode=info"
|
|
else if (dtmfMode == Api.DTMFMODE_AUTO)
|
|
res += ";dtmfmode=auto"
|
|
|
|
res = if (vmUri == "")
|
|
"$res;mwi=no"
|
|
else
|
|
"$res;mwi=yes;vm_uri=\"$vmUri\""
|
|
|
|
if (answerMode == Api.ANSWERMODE_AUTO)
|
|
res += ";answermode=auto"
|
|
|
|
if (autoRedirect)
|
|
res += ";sip_autoredirect=yes"
|
|
|
|
res += ";ptime=20;regint=${regint};regq=0.5;pubint=0;inreq_allowed=yes"
|
|
|
|
if (isMobile)
|
|
res += ";call_transfer=no"
|
|
|
|
var extra = ""
|
|
|
|
if (nickName != "")
|
|
extra += ";nickname=${nickName}"
|
|
|
|
if (isMobile)
|
|
extra += ";is_mobile=yes"
|
|
|
|
if (!callHistory)
|
|
extra += ";call_history=no"
|
|
|
|
if (blockUnknown)
|
|
extra += ";block_unknown=yes"
|
|
|
|
if (telProvider != "")
|
|
extra += ";tel_provider=${URLEncoder.encode(telProvider, "UTF-8")}"
|
|
|
|
if (countryCode != "")
|
|
extra += ";country_code=$countryCode"
|
|
|
|
if (configuredRegInt != REGISTRATION_INTERVAL)
|
|
extra += ";regint=$configuredRegInt"
|
|
|
|
if (numericKeypad)
|
|
extra += ";numeric_keypad=yes"
|
|
|
|
extra += ";last=empty"
|
|
|
|
if (customParams != "")
|
|
extra += ";$customParams"
|
|
|
|
res += ";extra=\"" + extra.substringAfter(";") + "\""
|
|
|
|
if (customParams != "")
|
|
res += ";$customParams"
|
|
|
|
return res
|
|
}
|
|
|
|
fun vmMessages(cxt: Context) : String {
|
|
|
|
val new = if (vmNew > 0) {
|
|
if (vmNew == 1)
|
|
cxt.getString(R.string.one_new_message)
|
|
else
|
|
"$vmNew ${cxt.getString(R.string.new_messages)}"
|
|
} else
|
|
""
|
|
|
|
val old = if (vmOld > 0) {
|
|
if (vmOld == 1)
|
|
cxt.getString(R.string.one_old_message)
|
|
else
|
|
"$vmOld ${cxt.getString(R.string.old_messages)}"
|
|
} else
|
|
""
|
|
|
|
var msg = cxt.getString(R.string.you_have)
|
|
if (new != "") {
|
|
msg = "$msg $new"
|
|
if (old != "") msg = "$msg ${cxt.getString(R.string.and)} $old"
|
|
} else {
|
|
msg = if (old != "")
|
|
"$msg $old"
|
|
else
|
|
cxt.getString(R.string.no_messages)
|
|
}
|
|
|
|
return "$msg."
|
|
}
|
|
|
|
fun host() : String {
|
|
return aor.split("@")[1]
|
|
}
|
|
|
|
fun text(): String {
|
|
return if (nickName != "")
|
|
nickName
|
|
else
|
|
aor.split(":")[1].substringBefore(";")
|
|
}
|
|
|
|
private fun removeAudioCodecsStartingWith(prefix: String) {
|
|
val newCodecs = ArrayList<String>()
|
|
for (acSpec in audioCodec)
|
|
if (!acSpec.lowercase(Locale.ROOT).startsWith(prefix)) newCodecs.add(acSpec)
|
|
audioCodec = newCodecs
|
|
}
|
|
|
|
fun removeAudioCodecs(codecModule: String) {
|
|
when (codecModule) {
|
|
"g711" ->
|
|
removeAudioCodecsStartingWith("pcm")
|
|
"g722" ->
|
|
removeAudioCodecsStartingWith("g722/")
|
|
else ->
|
|
removeAudioCodecsStartingWith(codecModule)
|
|
}
|
|
}
|
|
|
|
companion object {
|
|
|
|
fun accounts(): ArrayList<Account> {
|
|
val res = ArrayList<Account>()
|
|
for (ua in BaresipService.uas.value) {
|
|
res.add(ua.account)
|
|
}
|
|
return res
|
|
}
|
|
|
|
fun saveAccounts() {
|
|
var accounts = ""
|
|
for (a in accounts()) accounts = accounts + a.print() + "\n"
|
|
Utils.putFileContents(
|
|
BaresipService.filesPath + "/accounts",
|
|
accounts.toByteArray(Charsets.UTF_8)
|
|
)
|
|
// Log.d(TAG, "Saved accounts '${accounts}' to '${BaresipService.filesPath}/accounts'")
|
|
}
|
|
|
|
fun ofAor(aor: String): Account? {
|
|
for (ua in BaresipService.uas.value)
|
|
if (ua.account.aor == aor) return ua.account
|
|
return null
|
|
}
|
|
|
|
fun checkDisplayName(dn: String): Boolean {
|
|
if (dn == "") return true
|
|
val dnRegex = Regex("^([* .!%_`'~]|[+]|[-a-zA-Z0-9]){1,64}$")
|
|
return dnRegex.matches(dn)
|
|
}
|
|
|
|
fun checkAuthUser(au: String): Boolean {
|
|
if (au == "") return true
|
|
val ud = au.split("@")
|
|
return when (ud.size) {
|
|
1 -> Utils.checkUriUser(au)
|
|
2 -> Utils.checkUriUser(ud[0]) && Utils.checkDomain(ud[1])
|
|
else -> false
|
|
}
|
|
}
|
|
|
|
fun checkAuthPass(ap: String): Boolean {
|
|
return (ap.isNotEmpty()) && (ap.length <= 64) &&
|
|
Regex("^[ -~]*$").matches(ap) && !ap.contains('"')
|
|
}
|
|
|
|
fun uniqueNickName(nickName: String): Boolean {
|
|
for (ua in BaresipService.uas.value)
|
|
if (ua.account.nickName == nickName)
|
|
return false
|
|
return true
|
|
}
|
|
}
|
|
}
|