Added TURN NAT policy settings

This commit is contained in:
Sylvain Berfini 2024-11-26 10:32:34 +01:00
parent 0b0d7ce85a
commit d864b5efa5
6 changed files with 290 additions and 66 deletions

View file

@ -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<Boolean>()
val expandNatPolicySettings = MutableLiveData<Boolean>()
val pushNotificationsAvailable = MutableLiveData<Boolean>()
val pushNotificationsEnabled = MutableLiveData<Boolean>()
@ -59,6 +63,14 @@ class AccountSettingsViewModel @UiThread constructor() : GenericViewModel() {
val iceEnabled = MutableLiveData<Boolean>()
val turnEnabled = MutableLiveData<Boolean>()
val turnUsername = MutableLiveData<String>()
val turnPassword = MutableLiveData<String>()
val showTurnPassword = MutableLiveData<Boolean>()
val avpfEnabled = MutableLiveData<Boolean>()
val expire = MutableLiveData<String>()
@ -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
}
}

View file

@ -116,64 +116,6 @@
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toStartOf="@id/outbound_proxy_switch"/>
<androidx.appcompat.widget.AppCompatTextView
style="@style/settings_title_style"
android:id="@+id/stun_server_title"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginTop="20dp"
android:layout_marginStart="16dp"
android:layout_marginEnd="16dp"
android:text="@string/account_settings_stun_server_url_title"
android:maxLines="2"
android:ellipsize="end"
app:layout_constraintTop_toBottomOf="@id/outbound_proxy_switch"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toEndOf="parent"/>
<androidx.appcompat.widget.AppCompatEditText
style="@style/default_text_style"
android:id="@+id/stun_server"
android:layout_width="0dp"
android:layout_height="50dp"
android:layout_marginEnd="16dp"
android:layout_marginStart="16dp"
android:background="@drawable/edit_text_background"
android:paddingStart="20dp"
android:paddingEnd="20dp"
android:text="@={viewModel.stunServer}"
android:inputType="text|textUri"
android:hint="@string/account_settings_stun_server_url_title"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toBottomOf="@id/stun_server_title"/>
<com.google.android.material.materialswitch.MaterialSwitch
style="@style/material_switch_style"
android:id="@+id/ice_switch"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="20dp"
android:layout_marginEnd="16dp"
android:checked="@={viewModel.iceEnabled}"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toBottomOf="@id/stun_server" />
<androidx.appcompat.widget.AppCompatTextView
style="@style/settings_title_style"
android:id="@+id/ice_title"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginStart="16dp"
android:layout_marginEnd="10dp"
android:text="@string/account_settings_enable_ice_title"
android:maxLines="2"
android:ellipsize="end"
app:layout_constraintTop_toTopOf="@id/ice_switch"
app:layout_constraintBottom_toBottomOf="@id/ice_switch"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toStartOf="@id/ice_switch"/>
<com.google.android.material.materialswitch.MaterialSwitch
style="@style/material_switch_style"
android:id="@+id/avpf_switch"
@ -183,7 +125,7 @@
android:layout_marginEnd="16dp"
android:checked="@={viewModel.avpfEnabled}"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toBottomOf="@id/ice_switch" />
app:layout_constraintTop_toBottomOf="@id/outbound_proxy_title" />
<androidx.appcompat.widget.AppCompatTextView
style="@style/settings_title_style"
@ -251,10 +193,8 @@
android:visibility="@{viewModel.imEncryptionMandatory ? View.GONE : View.VISIBLE}"
app:layout_constraintBottom_toBottomOf="@id/cpim_basic_chat_room_switch"
app:layout_constraintEnd_toStartOf="@id/cpim_basic_chat_room_switch"
app:layout_constraintHorizontal_bias="0.0"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="@id/cpim_basic_chat_room_switch"
app:layout_constraintVertical_bias="1.0" />
app:layout_constraintTop_toTopOf="@id/cpim_basic_chat_room_switch"/>
<androidx.appcompat.widget.AppCompatTextView
style="@style/settings_title_style"
@ -284,7 +224,6 @@
android:text="@={viewModel.expire}"
android:inputType="number"
android:hint="@string/account_settings_expire_title"
app:layout_constraintVertical_bias="0"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toBottomOf="@id/expire_title"/>

View file

@ -0,0 +1,186 @@
<?xml version="1.0" encoding="utf-8"?>
<layout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto">
<data>
<import type="android.view.View" />
<import type="android.text.InputType" />
<variable
name="viewModel"
type="org.linphone.ui.main.settings.viewmodel.AccountSettingsViewModel" />
</data>
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="@drawable/shape_squircle_white_background">
<androidx.appcompat.widget.AppCompatTextView
style="@style/settings_title_style"
android:id="@+id/stun_server_title"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginTop="20dp"
android:layout_marginStart="16dp"
android:layout_marginEnd="16dp"
android:text="@string/account_settings_stun_server_url_title"
android:maxLines="2"
android:ellipsize="end"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toEndOf="parent"/>
<androidx.appcompat.widget.AppCompatEditText
style="@style/default_text_style"
android:id="@+id/stun_server"
android:layout_width="0dp"
android:layout_height="50dp"
android:layout_marginEnd="16dp"
android:layout_marginStart="16dp"
android:background="@drawable/edit_text_background"
android:paddingStart="20dp"
android:paddingEnd="20dp"
android:text="@={viewModel.stunServer}"
android:inputType="text|textUri"
android:hint="@string/account_settings_stun_server_url_title"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toBottomOf="@id/stun_server_title"/>
<com.google.android.material.materialswitch.MaterialSwitch
style="@style/material_switch_style"
android:id="@+id/ice_switch"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="20dp"
android:layout_marginEnd="16dp"
android:checked="@={viewModel.iceEnabled}"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toBottomOf="@id/stun_server" />
<androidx.appcompat.widget.AppCompatTextView
style="@style/settings_title_style"
android:id="@+id/ice_title"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginStart="16dp"
android:layout_marginEnd="10dp"
android:text="@string/account_settings_enable_ice_title"
android:maxLines="2"
android:ellipsize="end"
app:layout_constraintTop_toTopOf="@id/ice_switch"
app:layout_constraintBottom_toBottomOf="@id/ice_switch"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toStartOf="@id/ice_switch"/>
<com.google.android.material.materialswitch.MaterialSwitch
style="@style/material_switch_style"
android:id="@+id/turn_switch"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="20dp"
android:layout_marginEnd="16dp"
android:checked="@={viewModel.turnEnabled}"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toBottomOf="@id/ice_switch" />
<androidx.appcompat.widget.AppCompatTextView
style="@style/settings_title_style"
android:id="@+id/turn_title"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginStart="16dp"
android:layout_marginEnd="10dp"
android:text="@string/account_settings_enable_turn_title"
android:maxLines="2"
android:ellipsize="end"
app:layout_constraintTop_toTopOf="@id/turn_switch"
app:layout_constraintBottom_toBottomOf="@id/turn_switch"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toStartOf="@id/turn_switch"/>
<androidx.appcompat.widget.AppCompatTextView
style="@style/settings_title_style"
android:id="@+id/turn_username_title"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginTop="20dp"
android:layout_marginStart="16dp"
android:layout_marginEnd="16dp"
android:text="@string/account_settings_turn_username_title"
android:maxLines="2"
android:ellipsize="end"
app:layout_constraintTop_toBottomOf="@id/turn_title"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toEndOf="parent"/>
<androidx.appcompat.widget.AppCompatEditText
style="@style/default_text_style"
android:id="@+id/turn_username"
android:layout_width="0dp"
android:layout_height="50dp"
android:layout_marginEnd="16dp"
android:layout_marginStart="16dp"
android:layout_marginBottom="20dp"
android:background="@drawable/edit_text_background"
android:paddingStart="20dp"
android:paddingEnd="20dp"
android:text="@={viewModel.turnUsername}"
android:inputType="text|textPersonName"
android:hint="@string/account_settings_turn_username_title"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toBottomOf="@id/turn_username_title" />
<androidx.appcompat.widget.AppCompatTextView
style="@style/settings_title_style"
android:id="@+id/turn_password_title"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginTop="20dp"
android:layout_marginStart="16dp"
android:layout_marginEnd="16dp"
android:text="@string/account_settings_turn_password_title"
android:maxLines="2"
android:ellipsize="end"
app:layout_constraintTop_toBottomOf="@id/turn_username"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toEndOf="parent"/>
<androidx.appcompat.widget.AppCompatEditText
style="@style/default_text_style"
android:id="@+id/turn_password"
android:layout_width="0dp"
android:layout_height="50dp"
android:layout_marginEnd="16dp"
android:layout_marginStart="16dp"
android:layout_marginBottom="20dp"
android:background="@drawable/edit_text_background"
android:paddingStart="20dp"
android:paddingEnd="20dp"
android:text="@={viewModel.turnPassword}"
android:hint="@string/account_settings_turn_password_title"
android:inputType="@{viewModel.showTurnPassword ? InputType.TYPE_CLASS_TEXT | InputType.TYPE_TEXT_VARIATION_VISIBLE_PASSWORD : InputType.TYPE_CLASS_TEXT | InputType.TYPE_TEXT_VARIATION_PASSWORD, default=textPassword}"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toBottomOf="@id/turn_password_title"
app:layout_constraintBottom_toBottomOf="parent"/>
<ImageView
android:onClick="@{() -> viewModel.toggleShowTurnPassword()}"
android:id="@+id/eye"
android:layout_width="@dimen/icon_size"
android:layout_height="0dp"
android:padding="4dp"
android:layout_marginEnd="20dp"
android:contentDescription="@string/content_description_toggle_password_visibility"
android:src="@{viewModel.showTurnPassword ? @drawable/eye_slash : @drawable/eye, default=@drawable/eye}"
app:tint="?attr/color_main2_500"
app:layout_constraintEnd_toEndOf="@id/turn_password"
app:layout_constraintTop_toTopOf="@id/turn_password"
app:layout_constraintBottom_toBottomOf="@id/turn_password" />
</androidx.constraintlayout.widget.ConstraintLayout>
</layout>

View file

@ -198,6 +198,32 @@
</androidx.constraintlayout.widget.ConstraintLayout>
<androidx.appcompat.widget.AppCompatTextView
style="@style/section_header_style"
android:id="@+id/nat_policy_settings_header"
android:onClick="@{() -> viewModel.toggleNatPolicySettingsExpand()}"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:padding="5dp"
android:layout_marginStart="26dp"
android:layout_marginEnd="26dp"
android:layout_marginTop="16dp"
android:layout_marginBottom="10dp"
android:text="@string/account_settings_nat_policy_title"
android:drawableEnd="@{viewModel.expandNatPolicySettings ? @drawable/caret_up : @drawable/caret_down, default=@drawable/caret_up}"
android:drawableTint="?attr/color_main2_600"/>
<include
android:id="@+id/nat_policy_settings"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginStart="16dp"
android:layout_marginEnd="16dp"
android:layout_marginBottom="@dimen/screen_bottom_margin"
android:visibility="@{viewModel.expandNatPolicySettings ? View.VISIBLE : View.GONE}"
layout="@layout/account_nat_policy_settings"
bind:viewModel="@{viewModel}"/>
<androidx.appcompat.widget.AppCompatTextView
style="@style/section_header_style"
android:id="@+id/advanced_settings_header"
@ -208,6 +234,7 @@
android:layout_marginStart="26dp"
android:layout_marginEnd="26dp"
android:layout_marginTop="16dp"
android:layout_marginBottom="10dp"
android:text="@string/settings_advanced_title"
android:drawableEnd="@{viewModel.expandAdvancedSettings ? @drawable/caret_up : @drawable/caret_down, default=@drawable/caret_up}"
android:drawableTint="?attr/color_main2_600"/>
@ -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"

View file

@ -297,8 +297,12 @@
<string name="account_settings_im_encryption_mandatory_title">Chiffrement obligatoire des conversations</string>
<string name="account_settings_sip_proxy_url_title">URL du serveur mandataire</string>
<string name="account_settings_outbound_proxy_title">Serveur mandataire sortant</string>
<string name="account_settings_stun_server_url_title">URL du serveur STUN</string>
<string name="account_settings_nat_policy_title">Paramètres de politique NAT</string>
<string name="account_settings_stun_server_url_title">URL du serveur STUN/TURN</string>
<string name="account_settings_enable_ice_title">Activer ICE</string>
<string name="account_settings_enable_turn_title">Activer TURN</string>
<string name="account_settings_turn_username_title">Utilisateur TURN</string>
<string name="account_settings_turn_password_title">Mot de passe TURN</string>
<string name="account_settings_avpf_title">AVPF</string>
<string name="account_settings_expire_title">Expiration (en secondes)</string>
<string name="account_settings_conference_factory_uri_title">URI de l\'usine à conversations</string>

View file

@ -334,8 +334,12 @@
<string name="account_settings_im_encryption_mandatory_title">IM encryption mandatory</string>
<string name="account_settings_sip_proxy_url_title">SIP proxy server URL</string>
<string name="account_settings_outbound_proxy_title">Outbound proxy</string>
<string name="account_settings_stun_server_url_title">STUN server URL</string>
<string name="account_settings_nat_policy_title">NAT policy settings</string>
<string name="account_settings_stun_server_url_title">STUN/TURN server URL</string>
<string name="account_settings_enable_ice_title">Enable ICE</string>
<string name="account_settings_enable_turn_title">Enable TURN</string>
<string name="account_settings_turn_username_title">TURN username</string>
<string name="account_settings_turn_password_title">TURN password</string>
<string name="account_settings_avpf_title">AVPF</string>
<string name="account_settings_expire_title">Expire (in seconds)</string>
<string name="account_settings_conference_factory_uri_title">Conference factory URI</string>