From 2394f3fba12185a3f59e2667ce8e493c3c7dffb2 Mon Sep 17 00:00:00 2001 From: Juha Heinanen Date: Sun, 2 Jul 2023 15:20:06 +0300 Subject: [PATCH] Added Redirect Mode account setting that tells if call redirect requests (3xx responses) can be followed automatically or if confirmation needs to be asked --- app/src/main/cpp/baresip.c | 15 ++++++++ .../main/kotlin/com/tutpro/baresip/Account.kt | 4 ++ .../com/tutpro/baresip/AccountActivity.kt | 38 +++++++++++++++++++ app/src/main/kotlin/com/tutpro/baresip/Api.kt | 2 + .../com/tutpro/baresip/BaresipService.kt | 11 ++++-- .../kotlin/com/tutpro/baresip/MainActivity.kt | 31 +++++++++++++++ app/src/main/res/layout/activity_account.xml | 15 ++++++++ app/src/main/res/values-fi/strings.xml | 6 +++ app/src/main/res/values/strings.xml | 6 +++ 9 files changed, 125 insertions(+), 3 deletions(-) diff --git a/app/src/main/cpp/baresip.c b/app/src/main/cpp/baresip.c index ec545634..31702c9d 100644 --- a/app/src/main/cpp/baresip.c +++ b/app/src/main/cpp/baresip.c @@ -184,6 +184,9 @@ static void ua_event_handler( case UA_EVENT_CALL_ANSWERED: len = re_snprintf(event_buf, sizeof event_buf, "call answered"); break; + case UA_EVENT_CALL_REDIRECT: + len = re_snprintf(event_buf, sizeof event_buf, "call redirect,%s", prm + 4); + break; case UA_EVENT_CALL_LOCAL_SDP: if (strcmp(prm, "offer") == 0) return; @@ -958,6 +961,18 @@ JNIEXPORT jint JNICALL Java_com_tutpro_baresip_Api_account_1set_1answermode( return account_set_answermode((struct account *)acc, mode); } +JNIEXPORT jboolean JNICALL Java_com_tutpro_baresip_Api_account_1sip_1autoredirect( + JNIEnv *env, jobject thiz, jlong acc) +{ + return account_sip_autoredirect((struct account *)acc); +} + +JNIEXPORT void JNICALL Java_com_tutpro_baresip_Api_account_1set_1sip_1autoredirect( + JNIEnv *env, jobject thiz, jlong acc, jboolean allow) +{ + return account_set_sip_autoredirect((struct account *)acc, allow); +} + JNIEXPORT jboolean JNICALL Java_com_tutpro_baresip_Api_account_1rtcp_1mux( JNIEnv *env, jobject thiz, jlong acc) { diff --git a/app/src/main/kotlin/com/tutpro/baresip/Account.kt b/app/src/main/kotlin/com/tutpro/baresip/Account.kt index ee8c08b0..ba1fee5c 100644 --- a/app/src/main/kotlin/com/tutpro/baresip/Account.kt +++ b/app/src/main/kotlin/com/tutpro/baresip/Account.kt @@ -27,6 +27,7 @@ class Account(val accp: Long) { var rtcpMux = Api.account_rtcp_mux(accp) var dtmfMode = Api.account_dtmfmode(accp) var answerMode = Api.account_answermode(accp) + var autoRedirect = Api.account_sip_autoredirect(accp) var vmUri = Api.account_vm_uri(accp) var vmNew = 0 var vmOld = 0 @@ -132,6 +133,9 @@ class Account(val accp: Long) { if (answerMode == Api.ANSWERMODE_AUTO) res += ";answermode=auto" + if (autoRedirect) + res += ";sip_autoredirect=yes" + res += ";ptime=20;regint=${regint};regq=0.5;pubint=0;call_transfer=yes;100rel=no" var extra = "" diff --git a/app/src/main/kotlin/com/tutpro/baresip/AccountActivity.kt b/app/src/main/kotlin/com/tutpro/baresip/AccountActivity.kt index c3db50e2..df00af78 100644 --- a/app/src/main/kotlin/com/tutpro/baresip/AccountActivity.kt +++ b/app/src/main/kotlin/com/tutpro/baresip/AccountActivity.kt @@ -49,6 +49,8 @@ class AccountActivity : AppCompatActivity() { private lateinit var dtmfModeSpinner: Spinner private var answerMode = Api.ANSWERMODE_MANUAL private lateinit var answerModeSpinner: Spinner + private var autoRedirect = false + private lateinit var redirectModeSpinner: Spinner private lateinit var vmUri: EditText private lateinit var countryCode: EditText private lateinit var telProvider: EditText @@ -95,6 +97,7 @@ class AccountActivity : AppCompatActivity() { rtcpCheck = binding.RtcpMux dtmfModeSpinner = binding.dtmfModeSpinner answerModeSpinner = binding.answerModeSpinner + redirectModeSpinner = binding.redirectModeSpinner vmUri = binding.voicemailUri countryCode = binding.countryCode telProvider = binding.telephonyProvider @@ -203,6 +206,8 @@ class AccountActivity : AppCompatActivity() { else Api.ANSWERMODE_AUTO } + "redirect-mode" -> + acc.autoRedirect = text == "yes" "voicemail-uri" -> if (text.isNotEmpty()) acc.vmUri = text @@ -344,6 +349,27 @@ class AccountActivity : AppCompatActivity() { } } + autoRedirect = acc.autoRedirect + val redirectModeKeys = arrayListOf(false, true) + val redirectModeVals = arrayListOf(getString(R.string.manual), getString(R.string.auto)) + keyIx = redirectModeKeys.indexOf(acc.autoRedirect) + keyVal = redirectModeVals.elementAt(keyIx) + redirectModeKeys.removeAt(keyIx) + redirectModeVals.removeAt(keyIx) + redirectModeKeys.add(0, acc.autoRedirect) + redirectModeVals.add(0, keyVal) + val redirectModeAdapter = ArrayAdapter(this,android.R.layout.simple_spinner_item, + redirectModeVals) + redirectModeAdapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item) + redirectModeSpinner.adapter = redirectModeAdapter + redirectModeSpinner.onItemSelectedListener = object : AdapterView.OnItemSelectedListener { + override fun onItemSelected(parent: AdapterView<*>, view: View, position: Int, id: Long) { + autoRedirect = redirectModeKeys[redirectModeVals.indexOf(parent.selectedItem.toString())] + } + override fun onNothingSelected(parent: AdapterView<*>) { + } + } + if (acc.countryCode != "") countryCode.setText(acc.countryCode) @@ -612,6 +638,12 @@ class AccountActivity : AppCompatActivity() { } } + if (autoRedirect != acc.autoRedirect) { + Api.account_set_sip_autoredirect(acc.accp, autoRedirect) + acc.autoRedirect = autoRedirect + Log.d(TAG, "New autoRedirect is ${acc.autoRedirect}") + } + var tVmUri = vmUri.text.toString().trim() if (tVmUri != acc.vmUri) { if (tVmUri != "") { @@ -785,6 +817,12 @@ class AccountActivity : AppCompatActivity() { getString(R.string.answer_mode_help) ) } + binding.RedirectModeTitle.setOnClickListener { + Utils.alertView( + this, getString(R.string.redirect_mode), + getString(R.string.redirect_mode_help) + ) + } binding.VoicemailUriTitle.setOnClickListener { Utils.alertView( this, getString(R.string.voicemail_uri), diff --git a/app/src/main/kotlin/com/tutpro/baresip/Api.kt b/app/src/main/kotlin/com/tutpro/baresip/Api.kt index 837e92c8..fec2944f 100644 --- a/app/src/main/kotlin/com/tutpro/baresip/Api.kt +++ b/app/src/main/kotlin/com/tutpro/baresip/Api.kt @@ -46,6 +46,8 @@ object Api { external fun account_vm_uri(acc: Long): String external fun account_answermode(acc: Long): Int external fun account_set_answermode(acc: Long, mode: Int): Int + external fun account_sip_autoredirect(acc: Long): Boolean + external fun account_set_sip_autoredirect(acc: Long, allow: Boolean) external fun account_rtcp_mux(acc: Long): Boolean external fun account_set_rtcp_mux(acc: Long, value: Boolean): Int external fun account_dtmfmode(acc: Long): Int diff --git a/app/src/main/kotlin/com/tutpro/baresip/BaresipService.kt b/app/src/main/kotlin/com/tutpro/baresip/BaresipService.kt index 85e9fd55..a87ae62c 100644 --- a/app/src/main/kotlin/com/tutpro/baresip/BaresipService.kt +++ b/app/src/main/kotlin/com/tutpro/baresip/BaresipService.kt @@ -777,6 +777,9 @@ class BaresipService: Service() { else return } + "call redirect" -> { + stopMediaPlayer() + } "call established" -> { nm.cancel(CALL_NOTIFICATION_ID) Log.d(TAG, "AoR $aor call $callp established in mode ${am.mode}") @@ -951,10 +954,12 @@ class BaresipService: Service() { } val reason = ev[1].trim() if ((reason != "") && (ua.calls().isEmpty())) { - if (reason[0].isDigit()) - toast("${getString(R.string.call_failed)}: $reason") - else + if (reason[0].isDigit()) { + if (reason[0] != '3') + toast("${getString(R.string.call_failed)}: $reason") + } else { toast("${getString(R.string.call_closed)}: ${Api.call_peer_uri(callp)}: $reason") + } } } } diff --git a/app/src/main/kotlin/com/tutpro/baresip/MainActivity.kt b/app/src/main/kotlin/com/tutpro/baresip/MainActivity.kt index 1707bdd8..883f930c 100644 --- a/app/src/main/kotlin/com/tutpro/baresip/MainActivity.kt +++ b/app/src/main/kotlin/com/tutpro/baresip/MainActivity.kt @@ -1086,6 +1086,37 @@ class MainActivity : AppCompatActivity() { "call answered" -> { showCall(ua) } + "call redirect" -> { + val redirectUri = ev[1] + val target = Utils.friendlyUri(this, redirectUri, acc) + if (acc.autoRedirect) { + if (ua.account.aor != aorSpinner.tag) + spinToAor(ua.account.aor) + callUri.setText(redirectUri) + callButton.performClick() + Toast.makeText(applicationContext, + String.format(getString(R.string.redirect_notice), target), + Toast.LENGTH_SHORT + ).show() + } else { + with(MaterialAlertDialogBuilder(this, R.style.AlertDialogTheme)) { + setTitle(R.string.redirect_request) + setMessage(String.format(getString(R.string.redirect_request_query), target)) + setPositiveButton(getString(R.string.yes)) { dialog, _ -> + if (ua.account.aor != aorSpinner.tag) + spinToAor(ua.account.aor) + callUri.setText(redirectUri) + callButton.performClick() + dialog.dismiss() + } + setNeutralButton(getString(R.string.no)) { dialog, _ -> + dialog.dismiss() + } + show() + } + } + showCall(ua) + } "call established" -> { if (aor == aorSpinner.tag) { dtmf.setText("") diff --git a/app/src/main/res/layout/activity_account.xml b/app/src/main/res/layout/activity_account.xml index ca2bc3ff..73715109 100644 --- a/app/src/main/res/layout/activity_account.xml +++ b/app/src/main/res/layout/activity_account.xml @@ -368,6 +368,21 @@ android:paddingTop="8dp" > + + + + + Valitsee tulevien puheluiden vastaustavan. Manuaalinen Automaattinen + Uudelleenohjaustapa + Valitsee toteutetaanko puhelun uudelleenohjauspyyntö + automaattisesti vai kysytäänkö vahvistusta. Puhepostin URI SIP URI, jota käytetään puhepostiviestien kuunteluun. Jos URI:a ei ole annettu, tietoa @@ -521,6 +524,9 @@ Todennatko SAS:n <%1$s>\? Siirtopyyntö Hyväksytkö tämän puhelun siirron kohteeseen \'%1$s\'\? + Automaattinen uudelleenohjaus kohteeseen \'%1$s\'\ + Uudelleenohjauspyyntö + Hyväksytkö puhelun uudelleenohjauksen kohteeseen \'%1$s\'\? Puhelu epäonnistui Puhelu on päättynyt Tämä puhelu EI ole turvallinen! diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 46a7b47d..915970b5 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -176,6 +176,9 @@ SIP INFO Requests Answer Mode Selects how incoming calls are answered. + Redirect Mode + Selects if call redirect request is followed automatically or + if confirmation is requested. Manual Automatic Voicemail URI @@ -494,6 +497,9 @@ Do you want to verify SAS <%1$s>\? Transfer Request Do you accept to transfer this call to \'%1$s\'\? + Automatic redirection to \'%1$s\'\ + Redirect Request + Do you accept to call redirection to \'%1$s\'\? Call failed Call is closed This call is NOT secure!