From 8bec0004ccd9666d77b174266fb668a236132221 Mon Sep 17 00:00:00 2001 From: Evgeny Poberezkin <2769109+epoberezkin@users.noreply.github.com> Date: Sat, 21 Jan 2023 16:05:09 +0000 Subject: [PATCH] mobile: UI to choose transport isolation mode (#1813) * mobile: UI to choose transport isolation mode * typo Co-authored-by: JRoberts <8711996+jr-simplex@users.noreply.github.com> * ios: update alerts Co-authored-by: JRoberts <8711996+jr-simplex@users.noreply.github.com> --- .../java/chat/simplex/app/model/SimpleXAPI.kt | 43 ++++++++-- .../usersettings/AdvancedNetworkSettings.kt | 3 + .../views/usersettings/NetworkAndServers.kt | 83 +++++++++++++++++-- .../app/src/main/res/values/strings.xml | 6 ++ .../UserSettings/NetworkAndServers.swift | 66 +++++++++++---- apps/ios/SimpleXChat/APITypes.swift | 17 +++- apps/ios/SimpleXChat/AppGroup.swift | 11 +++ 7 files changed, 200 insertions(+), 29 deletions(-) diff --git a/apps/android/app/src/main/java/chat/simplex/app/model/SimpleXAPI.kt b/apps/android/app/src/main/java/chat/simplex/app/model/SimpleXAPI.kt index a802c70a6a..4384c4257b 100644 --- a/apps/android/app/src/main/java/chat/simplex/app/model/SimpleXAPI.kt +++ b/apps/android/app/src/main/java/chat/simplex/app/model/SimpleXAPI.kt @@ -109,6 +109,18 @@ class AppPreferences(val context: Context) { val chatLastStart = mkDatePreference(SHARED_PREFS_CHAT_LAST_START, null) val developerTools = mkBoolPreference(SHARED_PREFS_DEVELOPER_TOOLS, false) val networkUseSocksProxy = mkBoolPreference(SHARED_PREFS_NETWORK_USE_SOCKS_PROXY, false) + private val _networkSessionMode = mkStrPreference(SHARED_PREFS_NETWORK_SESSION_MODE, TransportSessionMode.default.name) + val networkSessionMode: SharedPreference = SharedPreference( + get = fun(): TransportSessionMode { + val value = _networkSessionMode.get() ?: return TransportSessionMode.default + return try { + TransportSessionMode.valueOf(value) + } catch (e: Error) { + TransportSessionMode.default + } + }, + set = fun(mode: TransportSessionMode) { _networkSessionMode.set(mode.name) } + ) val networkHostMode = mkStrPreference(SHARED_PREFS_NETWORK_HOST_MODE, HostMode.OnionViaSocks.name) val networkRequiredHostMode = mkBoolPreference(SHARED_PREFS_NETWORK_REQUIRED_HOST_MODE, false) val networkTCPConnectTimeout = mkTimeoutPreference(SHARED_PREFS_NETWORK_TCP_CONNECT_TIMEOUT, NetCfg.defaults.tcpConnectTimeout, NetCfg.proxyDefaults.tcpConnectTimeout) @@ -206,6 +218,7 @@ class AppPreferences(val context: Context) { private const val SHARED_PREFS_CHAT_LAST_START = "ChatLastStart" private const val SHARED_PREFS_DEVELOPER_TOOLS = "DeveloperTools" private const val SHARED_PREFS_NETWORK_USE_SOCKS_PROXY = "NetworkUseSocksProxy" + private const val SHARED_PREFS_NETWORK_SESSION_MODE = "NetworkSessionMode" private const val SHARED_PREFS_NETWORK_HOST_MODE = "NetworkHostMode" private const val SHARED_PREFS_NETWORK_REQUIRED_HOST_MODE = "NetworkRequiredHostMode" private const val SHARED_PREFS_NETWORK_TCP_CONNECT_TIMEOUT = "NetworkTCPConnectTimeout" @@ -254,6 +267,8 @@ open class ChatController(var ctrl: ChatCtrl?, val ntfManager: NtfManager, val a apiSetNetworkConfig(getNetCfg()) val justStarted = apiStartChat() if (justStarted) { + chatModel.currentUser.value = user + chatModel.userCreated.value = true apiSetFilesFolder(getAppFilesDirectory(appContext)) apiSetIncognito(chatModel.incognito.value) chatModel.userAddress.value = apiGetUserAddress() @@ -263,8 +278,6 @@ open class ChatController(var ctrl: ChatCtrl?, val ntfManager: NtfManager, val a chatModel.chatItemTTL.value = getChatItemTTL() val chats = apiGetChats() chatModel.updateChats(chats) - chatModel.currentUser.value = user - chatModel.userCreated.value = true chatModel.onboardingStage.value = OnboardingStage.OnboardingComplete chatModel.controller.appPrefs.chatLastStart.set(Clock.System.now()) chatModel.chatRunning.value = true @@ -1533,6 +1546,7 @@ open class ChatController(var ctrl: ChatCtrl?, val ntfManager: NtfManager, val a val socksProxy = if (useSocksProxy) ":9050" else null val hostMode = HostMode.valueOf(appPrefs.networkHostMode.get()!!) val requiredHostMode = appPrefs.networkRequiredHostMode.get() + val sessionMode = appPrefs.networkSessionMode.get() val tcpConnectTimeout = appPrefs.networkTCPConnectTimeout.get() val tcpTimeout = appPrefs.networkTCPTimeout.get() val smpPingInterval = appPrefs.networkSMPPingInterval.get() @@ -1550,6 +1564,7 @@ open class ChatController(var ctrl: ChatCtrl?, val ntfManager: NtfManager, val a socksProxy = socksProxy, hostMode = hostMode, requiredHostMode = requiredHostMode, + sessionMode = sessionMode, tcpConnectTimeout = tcpConnectTimeout, tcpTimeout = tcpTimeout, tcpKeepAlive = tcpKeepAlive, @@ -1562,6 +1577,7 @@ open class ChatController(var ctrl: ChatCtrl?, val ntfManager: NtfManager, val a appPrefs.networkUseSocksProxy.set(cfg.useSocksProxy) appPrefs.networkHostMode.set(cfg.hostMode.name) appPrefs.networkRequiredHostMode.set(cfg.requiredHostMode) + appPrefs.networkSessionMode.set(cfg.sessionMode) appPrefs.networkTCPConnectTimeout.set(cfg.tcpConnectTimeout) appPrefs.networkTCPTimeout.set(cfg.tcpTimeout) appPrefs.networkSMPPingInterval.set(cfg.smpPingInterval) @@ -2000,9 +2016,10 @@ data class ParsedServerAddress ( @Serializable data class NetCfg( - val socksProxy: String? = null, - val hostMode: HostMode = HostMode.OnionViaSocks, - val requiredHostMode: Boolean = false, + val socksProxy: String?, + val hostMode: HostMode, + val requiredHostMode: Boolean, + val sessionMode: TransportSessionMode, val tcpConnectTimeout: Long, // microseconds val tcpTimeout: Long, // microseconds val tcpKeepAlive: KeepAliveOpts?, @@ -2017,6 +2034,9 @@ data class NetCfg( val defaults: NetCfg = NetCfg( socksProxy = null, + hostMode = HostMode.OnionViaSocks, + requiredHostMode = false, + sessionMode = TransportSessionMode.User, tcpConnectTimeout = 10_000_000, tcpTimeout = 7_000_000, tcpKeepAlive = KeepAliveOpts.defaults, @@ -2027,6 +2047,9 @@ data class NetCfg( val proxyDefaults: NetCfg = NetCfg( socksProxy = ":9050", + hostMode = HostMode.OnionViaSocks, + requiredHostMode = false, + sessionMode = TransportSessionMode.User, tcpConnectTimeout = 20_000_000, tcpTimeout = 15_000_000, tcpKeepAlive = KeepAliveOpts.defaults, @@ -2063,6 +2086,16 @@ enum class HostMode { @SerialName("public") Public; } +@Serializable +enum class TransportSessionMode { + @SerialName("user") User, + @SerialName("entity") Entity; + + companion object { + val default = User + } +} + @Serializable data class KeepAliveOpts( val keepIdle: Int, // seconds diff --git a/apps/android/app/src/main/java/chat/simplex/app/views/usersettings/AdvancedNetworkSettings.kt b/apps/android/app/src/main/java/chat/simplex/app/views/usersettings/AdvancedNetworkSettings.kt index 8f3618e4e3..45b8d3c650 100644 --- a/apps/android/app/src/main/java/chat/simplex/app/views/usersettings/AdvancedNetworkSettings.kt +++ b/apps/android/app/src/main/java/chat/simplex/app/views/usersettings/AdvancedNetworkSettings.kt @@ -60,6 +60,9 @@ fun AdvancedNetworkSettingsView(chatModel: ChatModel) { } return NetCfg( socksProxy = currentCfg.value.socksProxy, + hostMode = currentCfg.value.hostMode, + requiredHostMode = currentCfg.value.requiredHostMode, + sessionMode = currentCfg.value.sessionMode, tcpConnectTimeout = networkTCPConnectTimeout.value, tcpTimeout = networkTCPTimeout.value, tcpKeepAlive = tcpKeepAlive, diff --git a/apps/android/app/src/main/java/chat/simplex/app/views/usersettings/NetworkAndServers.kt b/apps/android/app/src/main/java/chat/simplex/app/views/usersettings/NetworkAndServers.kt index cc0a6de7f2..7ab7a9419d 100644 --- a/apps/android/app/src/main/java/chat/simplex/app/views/usersettings/NetworkAndServers.kt +++ b/apps/android/app/src/main/java/chat/simplex/app/views/usersettings/NetworkAndServers.kt @@ -31,6 +31,7 @@ fun NetworkAndServersView( val networkUseSocksProxy: MutableState = remember { mutableStateOf(netCfg.useSocksProxy) } val developerTools = chatModel.controller.appPrefs.developerTools.get() val onionHosts = remember { mutableStateOf(netCfg.onionHosts) } + val sessionMode = remember { mutableStateOf(netCfg.sessionMode) } LaunchedEffect(Unit) { chatModel.userSMPServersUnsaved.value = null @@ -40,6 +41,7 @@ fun NetworkAndServersView( developerTools = developerTools, networkUseSocksProxy = networkUseSocksProxy, onionHosts = onionHosts, + sessionMode = sessionMode, showModal = showModal, showSettingsModal = showSettingsModal, toggleSocksProxy = { enable -> @@ -82,9 +84,13 @@ fun NetworkAndServersView( OnionHosts.PREFER -> generalGetString(R.string.network_use_onion_hosts_prefer_desc_in_alert) OnionHosts.REQUIRED -> generalGetString(R.string.network_use_onion_hosts_required_desc_in_alert) } - updateOnionHostsDialog(startsWith, onDismiss = { - onionHosts.value = prevValue - }) { + updateNetworkSettingsDialog( + title = generalGetString(R.string.update_onion_hosts_settings_question), + startsWith, + onDismiss = { + onionHosts.value = prevValue + } + ) { withApi { val newCfg = chatModel.controller.getNetCfg().withOnionHosts(it) val res = chatModel.controller.apiSetNetworkConfig(newCfg) @@ -96,6 +102,31 @@ fun NetworkAndServersView( } } } + }, + updateSessionMode = { + if (sessionMode.value == it) return@NetworkAndServersLayout + val prevValue = sessionMode.value + sessionMode.value = it + val startsWith = when (it) { + TransportSessionMode.User -> generalGetString(R.string.network_session_mode_user_description) + TransportSessionMode.Entity -> generalGetString(R.string.network_session_mode_entity_description) + } + updateNetworkSettingsDialog( + title = generalGetString(R.string.update_network_session_mode_question), + startsWith, + onDismiss = { sessionMode.value = prevValue } + ) { + withApi { + val newCfg = chatModel.controller.getNetCfg().copy(sessionMode = it) + val res = chatModel.controller.apiSetNetworkConfig(newCfg) + if (res) { + chatModel.controller.setNetCfg(newCfg) + sessionMode.value = it + } else { + sessionMode.value = prevValue + } + } + } } ) } @@ -104,10 +135,12 @@ fun NetworkAndServersView( developerTools: Boolean, networkUseSocksProxy: MutableState, onionHosts: MutableState, + sessionMode: MutableState, showModal: (@Composable (ChatModel) -> Unit) -> (() -> Unit), showSettingsModal: (@Composable (ChatModel) -> Unit) -> (() -> Unit), toggleSocksProxy: (Boolean) -> Unit, useOnion: (OnionHosts) -> Unit, + updateSessionMode: (TransportSessionMode) -> Unit, ) { Column( Modifier.fillMaxWidth(), @@ -124,6 +157,10 @@ fun NetworkAndServersView( SectionDivider() UseOnionHosts(onionHosts, networkUseSocksProxy, showSettingsModal, useOnion) SectionDivider() + if (developerTools) { + SessionModePicker(sessionMode, showSettingsModal, updateSessionMode) + SectionDivider() + } SettingsActionItem(Icons.Outlined.Cable, stringResource(R.string.network_settings), showSettingsModal { AdvancedNetworkSettingsView(it) }) } Spacer(Modifier.height(8.dp)) @@ -183,7 +220,6 @@ private fun UseOnionHosts( } } val onSelected = showModal { - Column( Modifier.fillMaxWidth(), horizontalAlignment = Alignment.Start, @@ -203,14 +239,47 @@ private fun UseOnionHosts( ) } -private fun updateOnionHostsDialog( +@Composable +private fun SessionModePicker( + sessionMode: MutableState, + showModal: (@Composable (ChatModel) -> Unit) -> (() -> Unit), + updateSessionMode: (TransportSessionMode) -> Unit, +) { + val values = remember { + TransportSessionMode.values().map { + when (it) { + TransportSessionMode.User -> ValueTitleDesc(TransportSessionMode.User, generalGetString(R.string.network_session_mode_user), generalGetString(R.string.network_session_mode_user_description)) + TransportSessionMode.Entity -> ValueTitleDesc(TransportSessionMode.Entity, generalGetString(R.string.network_session_mode_entity), generalGetString(R.string.network_session_mode_entity_description)) + } + } + } + + SectionItemWithValue( + generalGetString(R.string.network_session_mode_transport_isolation), + sessionMode, + values, + icon = Icons.Outlined.SafetyDivider, + onSelected = showModal { + Column( + Modifier.fillMaxWidth(), + horizontalAlignment = Alignment.Start, + ) { + AppBarTitle(stringResource(R.string.network_session_mode_transport_isolation)) + SectionViewSelectable(null, sessionMode, values, updateSessionMode) + } + } + ) +} + +private fun updateNetworkSettingsDialog( + title: String, startsWith: String = "", message: String = generalGetString(R.string.updating_settings_will_reconnect_client_to_all_servers), onDismiss: () -> Unit, onConfirm: () -> Unit ) { AlertManager.shared.showAlertDialog( - title = generalGetString(R.string.update_onion_hosts_settings_question), + title = title, text = startsWith + "\n\n" + message, confirmText = generalGetString(R.string.update_network_settings_confirmation), onDismiss = onDismiss, @@ -230,7 +299,9 @@ fun PreviewNetworkAndServersLayout() { showSettingsModal = { {} }, toggleSocksProxy = {}, onionHosts = remember { mutableStateOf(OnionHosts.PREFER) }, + sessionMode = remember { mutableStateOf(TransportSessionMode.User) }, useOnion = {}, + updateSessionMode = {}, ) } } diff --git a/apps/android/app/src/main/res/values/strings.xml b/apps/android/app/src/main/res/values/strings.xml index cc79c17e71..46384c14ab 100644 --- a/apps/android/app/src/main/res/values/strings.xml +++ b/apps/android/app/src/main/res/values/strings.xml @@ -478,6 +478,12 @@ Onion hosts will be used when available. Onion hosts will not be used. Onion hosts will be required for connection. + Transport isolation + Chat profile + Connection + A separate TCP connection (and SOCKS credential) will be used for each chat profile you have in the app. + A separate TCP connection (and SOCKS credential) will be used for each contact and group member.\nPlease note: if you have many connections, your battery and traffic consumption can be substantially higher and some connections may fail. + Update transport isolation mode? Appearance diff --git a/apps/ios/Shared/Views/UserSettings/NetworkAndServers.swift b/apps/ios/Shared/Views/UserSettings/NetworkAndServers.swift index b88a18e170..598255a0bd 100644 --- a/apps/ios/Shared/Views/UserSettings/NetworkAndServers.swift +++ b/apps/ios/Shared/Views/UserSettings/NetworkAndServers.swift @@ -9,13 +9,15 @@ import SwiftUI import SimpleXChat -enum OnionHostsAlert: Identifiable { - case update(hosts: OnionHosts) +private enum NetworkAlert: Identifiable { + case updateOnionHosts(hosts: OnionHosts) + case updateSessionMode(mode: TransportSessionMode) case error(err: String) var id: String { switch self { - case let .update(hosts): return "update \(hosts)" + case let .updateOnionHosts(hosts): return "updateOnionHosts \(hosts)" + case let .updateSessionMode(mode): return "updateSessionMode \(mode)" case let .error(err): return "error \(err)" } } @@ -27,7 +29,8 @@ struct NetworkAndServers: View { @State private var currentNetCfg = NetCfg.defaults @State private var netCfg = NetCfg.defaults @State private var onionHosts: OnionHosts = .no - @State private var showOnionHostsAlert: OnionHostsAlert? + @State private var sessionMode: TransportSessionMode = .user + @State private var alert: NetworkAlert? var body: some View { VStack { @@ -45,6 +48,12 @@ struct NetworkAndServers: View { } .frame(height: 36) + if developerTools { + Picker("Transport isolation", selection: $sessionMode) { + ForEach(TransportSessionMode.values, id: \.self) { Text($0.text) } + } + } + NavigationLink { AdvancedNetworkSettings() .navigationTitle("Network settings") @@ -75,17 +84,37 @@ struct NetworkAndServers: View { } .onChange(of: onionHosts) { _ in if onionHosts != OnionHosts(netCfg: currentNetCfg) { - showOnionHostsAlert = .update(hosts: onionHosts) + alert = .updateOnionHosts(hosts: onionHosts) } } - .alert(item: $showOnionHostsAlert) { a in + .onChange(of: sessionMode) { _ in + if sessionMode != netCfg.sessionMode { + alert = .updateSessionMode(mode: sessionMode) + } + } + .alert(item: $alert) { a in switch a { - case let .update(hosts): + case let .updateOnionHosts(hosts): return Alert( title: Text("Update .onion hosts setting?"), - message: Text(onionHostsInfo()) + Text("\n") + Text("Updating this setting will re-connect the client to all servers."), + message: Text(onionHostsInfo(hosts)) + Text("\n") + Text("Updating this setting will re-connect the client to all servers."), primaryButton: .default(Text("Ok")) { - saveNetCfg(hosts) + let (hostMode, requiredHostMode) = hosts.hostMode + netCfg.hostMode = hostMode + netCfg.requiredHostMode = requiredHostMode + saveNetCfg() + }, + secondaryButton: .cancel() { + resetNetCfgView() + } + ) + case let .updateSessionMode(mode): + return Alert( + title: Text("Update transport isolation mode?"), + message: Text(sessionModeInfo(mode)) + Text("\n") + Text("Updating this setting will re-connect the client to all servers."), + primaryButton: .default(Text("Ok")) { + netCfg.sessionMode = mode + saveNetCfg() }, secondaryButton: .cancel() { resetNetCfgView() @@ -100,11 +129,8 @@ struct NetworkAndServers: View { } } - private func saveNetCfg(_ hosts: OnionHosts) { + private func saveNetCfg() { do { - let (hostMode, requiredHostMode) = hosts.hostMode - netCfg.hostMode = hostMode - netCfg.requiredHostMode = requiredHostMode let def = netCfg.hostMode == .onionHost ? NetCfg.proxyDefaults : NetCfg.defaults netCfg.tcpConnectTimeout = def.tcpConnectTimeout netCfg.tcpTimeout = def.tcpTimeout @@ -114,7 +140,7 @@ struct NetworkAndServers: View { } catch let error { let err = responseError(error) resetNetCfgView() - showOnionHostsAlert = .error(err: err) + alert = .error(err: err) logger.error("\(err)") } } @@ -122,15 +148,23 @@ struct NetworkAndServers: View { private func resetNetCfgView() { netCfg = currentNetCfg onionHosts = OnionHosts(netCfg: netCfg) + sessionMode = netCfg.sessionMode } - private func onionHostsInfo() -> LocalizedStringKey { - switch onionHosts { + private func onionHostsInfo(_ hosts: OnionHosts) -> LocalizedStringKey { + switch hosts { case .no: return "Onion hosts will not be used." case .prefer: return "Onion hosts will be used when available. Requires enabling VPN." case .require: return "Onion hosts will be required for connection. Requires enabling VPN." } } + + private func sessionModeInfo(_ mode: TransportSessionMode) -> LocalizedStringKey { + switch mode { + case .user: return "A separate TCP connection will be used **for each chat profile you have in the app**." + case .entity: return "A separate TCP connection will be used **for each contact and group member**.\n**Please note**: if you have many connections, your battery and traffic consumption can be substantially higher and some connections may fail." + } + } } struct NetworkServersView_Previews: PreviewProvider { diff --git a/apps/ios/SimpleXChat/APITypes.swift b/apps/ios/SimpleXChat/APITypes.swift index de42584b72..f652c1229b 100644 --- a/apps/ios/SimpleXChat/APITypes.swift +++ b/apps/ios/SimpleXChat/APITypes.swift @@ -824,7 +824,7 @@ public struct NetCfg: Codable, Equatable { public var socksProxy: String? = nil public var hostMode: HostMode = .publicHost public var requiredHostMode = true - public var sessionMode = TransportSessionMode.user + public var sessionMode: TransportSessionMode public var tcpConnectTimeout: Int // microseconds public var tcpTimeout: Int // microseconds public var tcpKeepAlive: KeepAliveOpts? @@ -834,6 +834,7 @@ public struct NetCfg: Codable, Equatable { public static let defaults: NetCfg = NetCfg( socksProxy: nil, + sessionMode: TransportSessionMode.user, tcpConnectTimeout: 10_000_000, tcpTimeout: 7_000_000, tcpKeepAlive: KeepAliveOpts.defaults, @@ -844,6 +845,7 @@ public struct NetCfg: Codable, Equatable { public static let proxyDefaults: NetCfg = NetCfg( socksProxy: nil, + sessionMode: TransportSessionMode.user, tcpConnectTimeout: 20_000_000, tcpTimeout: 15_000_000, tcpKeepAlive: KeepAliveOpts.defaults, @@ -895,9 +897,20 @@ public enum OnionHosts: String, Identifiable { public static let values: [OnionHosts] = [.no, .prefer, .require] } -public enum TransportSessionMode: String, Codable { +public enum TransportSessionMode: String, Codable, Identifiable { case user case entity + + public var text: LocalizedStringKey { + switch self { + case .user: return "User profile" + case .entity: return "Connection" + } + } + + public var id: TransportSessionMode { self } + + public static let values: [TransportSessionMode] = [.user, .entity] } public struct KeepAliveOpts: Codable, Equatable { diff --git a/apps/ios/SimpleXChat/AppGroup.swift b/apps/ios/SimpleXChat/AppGroup.swift index 0dd43a2fca..d9135a3128 100644 --- a/apps/ios/SimpleXChat/AppGroup.swift +++ b/apps/ios/SimpleXChat/AppGroup.swift @@ -17,6 +17,7 @@ let GROUP_DEFAULT_PRIVACY_ACCEPT_IMAGES = "privacyAcceptImages" public let GROUP_DEFAULT_PRIVACY_TRANSFER_IMAGES_INLINE = "privacyTransferImagesInline" let GROUP_DEFAULT_NTF_BADGE_COUNT = "ntgBadgeCount" let GROUP_DEFAULT_NETWORK_USE_ONION_HOSTS = "networkUseOnionHosts" +let GROUP_DEFAULT_NETWORK_SESSION_MODE = "networkSessionMode" let GROUP_DEFAULT_NETWORK_TCP_CONNECT_TIMEOUT = "networkTCPConnectTimeout" let GROUP_DEFAULT_NETWORK_TCP_TIMEOUT = "networkTCPTimeout" let GROUP_DEFAULT_NETWORK_SMP_PING_INTERVAL = "networkSMPPingInterval" @@ -36,6 +37,7 @@ public let groupDefaults = UserDefaults(suiteName: APP_GROUP_NAME)! public func registerGroupDefaults() { groupDefaults.register(defaults: [ GROUP_DEFAULT_NETWORK_USE_ONION_HOSTS: OnionHosts.no.rawValue, + GROUP_DEFAULT_NETWORK_SESSION_MODE: TransportSessionMode.user.rawValue, GROUP_DEFAULT_NETWORK_TCP_CONNECT_TIMEOUT: NetCfg.defaults.tcpConnectTimeout, GROUP_DEFAULT_NETWORK_TCP_TIMEOUT: NetCfg.defaults.tcpTimeout, GROUP_DEFAULT_NETWORK_SMP_PING_INTERVAL: NetCfg.defaults.smpPingInterval, @@ -107,6 +109,12 @@ public let networkUseOnionHostsGroupDefault = EnumDefault( withDefault: .no ) +public let networkSessionModeGroupDefault = EnumDefault( + defaults: groupDefaults, + forKey: GROUP_DEFAULT_NETWORK_SESSION_MODE, + withDefault: .user +) + public let storeDBPassphraseGroupDefault = BoolDefault(defaults: groupDefaults, forKey: GROUP_DEFAULT_STORE_DB_PASSPHRASE) public let initialRandomDBPassphraseGroupDefault = BoolDefault(defaults: groupDefaults, forKey: GROUP_DEFAULT_INITIAL_RANDOM_DB_PASSPHRASE) @@ -186,6 +194,7 @@ public class Default { public func getNetCfg() -> NetCfg { let onionHosts = networkUseOnionHostsGroupDefault.get() let (hostMode, requiredHostMode) = onionHosts.hostMode + let sessionMode = networkSessionModeGroupDefault.get() let tcpConnectTimeout = groupDefaults.integer(forKey: GROUP_DEFAULT_NETWORK_TCP_CONNECT_TIMEOUT) let tcpTimeout = groupDefaults.integer(forKey: GROUP_DEFAULT_NETWORK_TCP_TIMEOUT) let smpPingInterval = groupDefaults.integer(forKey: GROUP_DEFAULT_NETWORK_SMP_PING_INTERVAL) @@ -203,6 +212,7 @@ public func getNetCfg() -> NetCfg { return NetCfg( hostMode: hostMode, requiredHostMode: requiredHostMode, + sessionMode: sessionMode, tcpConnectTimeout: tcpConnectTimeout, tcpTimeout: tcpTimeout, tcpKeepAlive: tcpKeepAlive, @@ -214,6 +224,7 @@ public func getNetCfg() -> NetCfg { public func setNetCfg(_ cfg: NetCfg) { networkUseOnionHostsGroupDefault.set(OnionHosts(netCfg: cfg)) + networkSessionModeGroupDefault.set(cfg.sessionMode) groupDefaults.set(cfg.tcpConnectTimeout, forKey: GROUP_DEFAULT_NETWORK_TCP_CONNECT_TIMEOUT) groupDefaults.set(cfg.tcpTimeout, forKey: GROUP_DEFAULT_NETWORK_TCP_TIMEOUT) groupDefaults.set(cfg.smpPingInterval, forKey: GROUP_DEFAULT_NETWORK_SMP_PING_INTERVAL)