diff --git a/app/src/main/java/org/linphone/ui/main/settings/viewmodel/AccountSettingsViewModel.kt b/app/src/main/java/org/linphone/ui/main/settings/viewmodel/AccountSettingsViewModel.kt index 0d1a9a163..1d4668bda 100644 --- a/app/src/main/java/org/linphone/ui/main/settings/viewmodel/AccountSettingsViewModel.kt +++ b/app/src/main/java/org/linphone/ui/main/settings/viewmodel/AccountSettingsViewModel.kt @@ -26,6 +26,8 @@ import java.util.Locale import org.linphone.LinphoneApplication.Companion.coreContext import org.linphone.core.AVPFMode import org.linphone.core.Account +import org.linphone.core.AuthInfo +import org.linphone.core.Factory import org.linphone.core.NatPolicy import org.linphone.core.TransportType import org.linphone.core.tools.Log @@ -39,6 +41,8 @@ class AccountSettingsViewModel @UiThread constructor() : GenericViewModel() { val expandAdvancedSettings = MutableLiveData() + val expandNatPolicySettings = MutableLiveData() + val pushNotificationsAvailable = MutableLiveData() val pushNotificationsEnabled = MutableLiveData() @@ -59,6 +63,14 @@ class AccountSettingsViewModel @UiThread constructor() : GenericViewModel() { val iceEnabled = MutableLiveData() + val turnEnabled = MutableLiveData() + + val turnUsername = MutableLiveData() + + val turnPassword = MutableLiveData() + + val showTurnPassword = MutableLiveData() + val avpfEnabled = MutableLiveData() val expire = MutableLiveData() @@ -82,9 +94,12 @@ class AccountSettingsViewModel @UiThread constructor() : GenericViewModel() { private lateinit var account: Account private lateinit var natPolicy: NatPolicy + private lateinit var natPolicyAuthInfo: AuthInfo init { expandAdvancedSettings.value = false + expandNatPolicySettings.value = false + showTurnPassword.value = false availableTransports.add(TransportType.Udp.name.uppercase(Locale.getDefault())) availableTransports.add(TransportType.Tcp.name.uppercase(Locale.getDefault())) @@ -126,6 +141,19 @@ class AccountSettingsViewModel @UiThread constructor() : GenericViewModel() { natPolicy = params.natPolicy ?: core.createNatPolicy() stunServer.postValue(natPolicy.stunServer) iceEnabled.postValue(natPolicy.isIceEnabled) + turnEnabled.postValue(natPolicy.isTurnEnabled) + + val turnStunUsername = natPolicy.stunServerUsername.orEmpty() + turnUsername.postValue(turnStunUsername) + if (turnStunUsername.isNotEmpty()) { + val authInfo = core.findAuthInfo(null, turnStunUsername, null) + if (authInfo == null) { + Log.w("$TAG TURN username not empty but unable to find matching auth info!") + } else { + natPolicyAuthInfo = authInfo + turnPassword.postValue(authInfo.password.orEmpty()) + } + } avpfEnabled.postValue(account.isAvpfEnabled) @@ -182,7 +210,34 @@ class AccountSettingsViewModel @UiThread constructor() : GenericViewModel() { natPolicy.stunServer = stunServer.value natPolicy.isStunEnabled = stunServer.value.orEmpty().isNotEmpty() natPolicy.isIceEnabled = iceEnabled.value == true + natPolicy.isTurnEnabled = turnEnabled.value == true + val stunTurnUsername = turnUsername.value.orEmpty() + natPolicy.stunServerUsername = stunTurnUsername newParams.natPolicy = natPolicy + + if (::natPolicyAuthInfo.isInitialized) { + if (stunTurnUsername.isEmpty()) { + Log.i( + "$TAG NAT policy TURN username is now empty, removing existing auth info" + ) + core.removeAuthInfo(natPolicyAuthInfo) + } else { + Log.i("$TAG Found NAT policy auth info, updating it") + natPolicyAuthInfo.username = stunTurnUsername + natPolicyAuthInfo.password = turnPassword.value.orEmpty() + } + } else if (stunTurnUsername.isNotEmpty()) { + Log.i("$TAG No NAT policy auth info found, creating it with") + val authInfo = Factory.instance().createAuthInfo( + stunTurnUsername, + null, + turnPassword.value.orEmpty(), + null, + null, + null + ) + core.addAuthInfo(authInfo) + } } newParams.avpfMode = if (avpfEnabled.value == true) AVPFMode.Enabled else AVPFMode.Disabled @@ -253,6 +308,11 @@ class AccountSettingsViewModel @UiThread constructor() : GenericViewModel() { return limeServerUrl.value.orEmpty().isNotEmpty() && conferenceFactoryUri.value.orEmpty().isNotEmpty() } + @UiThread + fun toggleNatPolicySettingsExpand() { + expandNatPolicySettings.value = expandNatPolicySettings.value == false + } + @UiThread fun toggleAdvancedSettingsExpand() { expandAdvancedSettings.value = expandAdvancedSettings.value == false @@ -278,4 +338,9 @@ class AccountSettingsViewModel @UiThread constructor() : GenericViewModel() { } } } + + @UiThread + fun toggleShowTurnPassword() { + showTurnPassword.value = showTurnPassword.value == false + } } diff --git a/app/src/main/res/layout/account_advanced_settings.xml b/app/src/main/res/layout/account_advanced_settings.xml index bac5954a7..0f9f8d9f4 100644 --- a/app/src/main/res/layout/account_advanced_settings.xml +++ b/app/src/main/res/layout/account_advanced_settings.xml @@ -116,64 +116,6 @@ app:layout_constraintStart_toStartOf="parent" app:layout_constraintEnd_toStartOf="@id/outbound_proxy_switch"/> - - - - - - - - + app:layout_constraintTop_toBottomOf="@id/outbound_proxy_title" /> + app:layout_constraintTop_toTopOf="@id/cpim_basic_chat_room_switch"/> diff --git a/app/src/main/res/layout/account_nat_policy_settings.xml b/app/src/main/res/layout/account_nat_policy_settings.xml new file mode 100644 index 000000000..c8a7d09f6 --- /dev/null +++ b/app/src/main/res/layout/account_nat_policy_settings.xml @@ -0,0 +1,186 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/account_settings_fragment.xml b/app/src/main/res/layout/account_settings_fragment.xml index 8c38150d9..0da02f3f6 100644 --- a/app/src/main/res/layout/account_settings_fragment.xml +++ b/app/src/main/res/layout/account_settings_fragment.xml @@ -198,6 +198,32 @@ + + + + @@ -216,7 +243,6 @@ android:id="@+id/account_advanced_settings" android:layout_width="match_parent" android:layout_height="wrap_content" - android:layout_marginTop="8dp" android:layout_marginStart="16dp" android:layout_marginEnd="16dp" android:layout_marginBottom="@dimen/screen_bottom_margin" diff --git a/app/src/main/res/values-fr/strings.xml b/app/src/main/res/values-fr/strings.xml index 69c3c23c3..11403c8da 100644 --- a/app/src/main/res/values-fr/strings.xml +++ b/app/src/main/res/values-fr/strings.xml @@ -297,8 +297,12 @@ Chiffrement obligatoire des conversations URL du serveur mandataire Serveur mandataire sortant - URL du serveur STUN + Paramètres de politique NAT + URL du serveur STUN/TURN Activer ICE + Activer TURN + Utilisateur TURN + Mot de passe TURN AVPF Expiration (en secondes) URI de l\'usine à conversations diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 6af695c5f..7d95be00f 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -334,8 +334,12 @@ IM encryption mandatory SIP proxy server URL Outbound proxy - STUN server URL + NAT policy settings + STUN/TURN server URL Enable ICE + Enable TURN + TURN username + TURN password AVPF Expire (in seconds) Conference factory URI