From c7bb59d991295986022e238a6f0f01b84b4db4a2 Mon Sep 17 00:00:00 2001 From: Sylvain Berfini Date: Wed, 2 Aug 2023 09:55:54 +0200 Subject: [PATCH] Prevent some issues related to ZRTP SAS confirmation dialog --- .../voip/fragments/SingleCallFragment.kt | 2 +- .../voip/fragments/StatusFragment.kt | 31 +++++++++++++++---- .../voip/viewmodels/StatusViewModel.kt | 31 ++++++++++++++----- 3 files changed, 49 insertions(+), 15 deletions(-) diff --git a/app/src/main/java/org/linphone/activities/voip/fragments/SingleCallFragment.kt b/app/src/main/java/org/linphone/activities/voip/fragments/SingleCallFragment.kt index 1477dcf92..2f90854af 100644 --- a/app/src/main/java/org/linphone/activities/voip/fragments/SingleCallFragment.kt +++ b/app/src/main/java/org/linphone/activities/voip/fragments/SingleCallFragment.kt @@ -87,7 +87,7 @@ class SingleCallFragment : GenericVideoPreviewFragment { + Call.State.OutgoingRinging, Call.State.OutgoingEarlyMedia -> { Log.i( "[Single Call] New current call is in [$callState] state, switching to OutgoingCall fragment" ) diff --git a/app/src/main/java/org/linphone/activities/voip/fragments/StatusFragment.kt b/app/src/main/java/org/linphone/activities/voip/fragments/StatusFragment.kt index 690b2972a..0536d1da6 100644 --- a/app/src/main/java/org/linphone/activities/voip/fragments/StatusFragment.kt +++ b/app/src/main/java/org/linphone/activities/voip/fragments/StatusFragment.kt @@ -84,8 +84,11 @@ class StatusFragment : GenericFragment() { private fun showZrtpDialog(call: Call) { if (zrtpDialog != null && zrtpDialog?.isShowing == true) { - Log.e("[Status Fragment] ZRTP dialog already visible") - return + Log.w( + "[Status Fragment] ZRTP dialog already visible, closing it and creating a new one" + ) + zrtpDialog?.dismiss() + zrtpDialog = null } val token = call.authenticationToken @@ -125,8 +128,19 @@ class StatusFragment : GenericFragment() { viewModel.showCancelButton( { - call.authenticationTokenVerified = false - this@StatusFragment.viewModel.updateEncryptionInfo(call) + if (call.state != Call.State.End && call.state != Call.State.Released) { + if (call.authenticationTokenVerified) { + Log.w( + "[Status Fragment] Removing trust from previously verified ZRTP SAS auth token" + ) + this@StatusFragment.viewModel.previouslyDeclineToken = true + call.authenticationTokenVerified = false + } + } else { + Log.e( + "[Status Fragment] Can't decline the ZRTP SAS token, call is in state [${call.state}]" + ) + } dialog.dismiss() zrtpDialog = null }, @@ -135,8 +149,13 @@ class StatusFragment : GenericFragment() { viewModel.showOkButton( { - call.authenticationTokenVerified = true - this@StatusFragment.viewModel.updateEncryptionInfo(call) + if (call.state != Call.State.End && call.state != Call.State.Released) { + call.authenticationTokenVerified = true + } else { + Log.e( + "[Status Fragment] Can't verify the ZRTP SAS token, call is in state [${call.state}]" + ) + } dialog.dismiss() zrtpDialog = null }, diff --git a/app/src/main/java/org/linphone/activities/voip/viewmodels/StatusViewModel.kt b/app/src/main/java/org/linphone/activities/voip/viewmodels/StatusViewModel.kt index ab8d3b597..ec2d25fbd 100644 --- a/app/src/main/java/org/linphone/activities/voip/viewmodels/StatusViewModel.kt +++ b/app/src/main/java/org/linphone/activities/voip/viewmodels/StatusViewModel.kt @@ -42,6 +42,8 @@ class StatusViewModel : StatusViewModel() { MutableLiveData>() } + var previouslyDeclineToken = false + private val listener = object : CoreListenerStub() { override fun onCallStatsUpdated(core: Core, call: Call, stats: CallStats) { updateCallQualityIcon() @@ -54,8 +56,11 @@ class StatusViewModel : StatusViewModel() { authenticationToken: String? ) { updateEncryptionInfo(call) - if (call.currentParams.mediaEncryption == MediaEncryption.ZRTP && !call.authenticationTokenVerified && call.authenticationToken != null) { - showZrtpDialogEvent.value = Event(call) + // Check if we just declined a previously validated token + // In that case, don't show the ZRTP dialog again + if (!previouslyDeclineToken) { + previouslyDeclineToken = false + showZrtpDialog(call) } } @@ -79,10 +84,7 @@ class StatusViewModel : StatusViewModel() { val currentCall = coreContext.core.currentCall if (currentCall != null) { updateEncryptionInfo(currentCall) - - if (currentCall.currentParams.mediaEncryption == MediaEncryption.ZRTP && !currentCall.authenticationTokenVerified && currentCall.authenticationToken != null) { - showZrtpDialogEvent.value = Event(currentCall) - } + showZrtpDialog(currentCall) } } @@ -94,8 +96,8 @@ class StatusViewModel : StatusViewModel() { fun showZrtpDialog() { val currentCall = coreContext.core.currentCall - if (currentCall?.authenticationToken != null && currentCall.currentParams.mediaEncryption == MediaEncryption.ZRTP) { - showZrtpDialogEvent.value = Event(currentCall) + if (currentCall != null) { + showZrtpDialog(currentCall, force = true) } } @@ -112,6 +114,9 @@ class StatusViewModel : StatusViewModel() { encryptionContentDescription.value = R.string.content_description_call_secured return } + if (call.state == Call.State.End || call.state == Call.State.Released) { + return + } when (call.currentParams.mediaEncryption ?: MediaEncryption.None) { MediaEncryption.SRTP, MediaEncryption.DTLS -> { @@ -139,6 +144,16 @@ class StatusViewModel : StatusViewModel() { } } + private fun showZrtpDialog(call: Call, force: Boolean = false) { + if ( + call.currentParams.mediaEncryption == MediaEncryption.ZRTP && + call.authenticationToken != null && + (!call.authenticationTokenVerified || force) + ) { + showZrtpDialogEvent.value = Event(call) + } + } + private fun updateCallQualityIcon() { val call = coreContext.core.currentCall ?: coreContext.core.calls.firstOrNull() val quality = call?.currentQuality ?: 0f