mirror of
https://github.com/simplex-chat/simplex-chat.git
synced 2025-06-28 12:19:54 +00:00
core, ui: option to use web port by default for preset servers only (#5847)
* core: option to use web port by default for preset servers only * ui * refactor * simplexmq
This commit is contained in:
parent
d53c13f8be
commit
7b11d8514a
14 changed files with 156 additions and 94 deletions
|
@ -209,11 +209,16 @@ struct AdvancedNetworkSettings: View {
|
||||||
}
|
}
|
||||||
|
|
||||||
Section {
|
Section {
|
||||||
Toggle("Use web port", isOn: $netCfg.smpWebPort)
|
Picker("Use web port", selection: $netCfg.smpWebPortServers) {
|
||||||
|
ForEach(SMPWebPortServers.allCases, id: \.self) { Text($0.text) }
|
||||||
|
}
|
||||||
|
.frame(height: 36)
|
||||||
} header: {
|
} header: {
|
||||||
Text("TCP port for messaging")
|
Text("TCP port for messaging")
|
||||||
} footer: {
|
} footer: {
|
||||||
Text("Use TCP port \(netCfg.smpWebPort ? "443" : "5223") when no port is specified.")
|
netCfg.smpWebPortServers == .preset
|
||||||
|
? Text("Use TCP port 443 for preset servers only.")
|
||||||
|
: Text("Use TCP port \(netCfg.smpWebPortServers == .all ? "443" : "5223") when no port is specified.")
|
||||||
}
|
}
|
||||||
|
|
||||||
Section("TCP connection") {
|
Section("TCP connection") {
|
||||||
|
|
|
@ -1796,7 +1796,7 @@ public struct NetCfg: Codable, Equatable {
|
||||||
public var sessionMode = TransportSessionMode.user
|
public var sessionMode = TransportSessionMode.user
|
||||||
public var smpProxyMode: SMPProxyMode = .always
|
public var smpProxyMode: SMPProxyMode = .always
|
||||||
public var smpProxyFallback: SMPProxyFallback = .allowProtected
|
public var smpProxyFallback: SMPProxyFallback = .allowProtected
|
||||||
public var smpWebPort = false
|
public var smpWebPortServers: SMPWebPortServers = .preset
|
||||||
public var tcpConnectTimeout: Int // microseconds
|
public var tcpConnectTimeout: Int // microseconds
|
||||||
public var tcpTimeout: Int // microseconds
|
public var tcpTimeout: Int // microseconds
|
||||||
public var tcpTimeoutPerKb: Int // microseconds
|
public var tcpTimeoutPerKb: Int // microseconds
|
||||||
|
@ -1892,6 +1892,20 @@ public enum SMPProxyFallback: String, Codable, SelectableItem {
|
||||||
public static let values: [SMPProxyFallback] = [.allow, .allowProtected, .prohibit]
|
public static let values: [SMPProxyFallback] = [.allow, .allowProtected, .prohibit]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public enum SMPWebPortServers: String, Codable, CaseIterable {
|
||||||
|
case all = "all"
|
||||||
|
case preset = "preset"
|
||||||
|
case off = "off"
|
||||||
|
|
||||||
|
public var text: LocalizedStringKey {
|
||||||
|
switch self {
|
||||||
|
case .all: "All servers"
|
||||||
|
case .preset: "Preset servers"
|
||||||
|
case .off: "Off"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public enum OnionHosts: String, Identifiable {
|
public enum OnionHosts: String, Identifiable {
|
||||||
case no
|
case no
|
||||||
case prefer
|
case prefer
|
||||||
|
|
|
@ -40,7 +40,7 @@ let GROUP_DEFAULT_NETWORK_USE_ONION_HOSTS = "networkUseOnionHosts"
|
||||||
let GROUP_DEFAULT_NETWORK_SESSION_MODE = "networkSessionMode"
|
let GROUP_DEFAULT_NETWORK_SESSION_MODE = "networkSessionMode"
|
||||||
let GROUP_DEFAULT_NETWORK_SMP_PROXY_MODE = "networkSMPProxyMode"
|
let GROUP_DEFAULT_NETWORK_SMP_PROXY_MODE = "networkSMPProxyMode"
|
||||||
let GROUP_DEFAULT_NETWORK_SMP_PROXY_FALLBACK = "networkSMPProxyFallback"
|
let GROUP_DEFAULT_NETWORK_SMP_PROXY_FALLBACK = "networkSMPProxyFallback"
|
||||||
let GROUP_DEFAULT_NETWORK_SMP_WEB_PORT = "networkSMPWebPort"
|
let GROUP_DEFAULT_NETWORK_SMP_WEB_PORT_SERVERS = "networkSMPWebPortServers"
|
||||||
let GROUP_DEFAULT_NETWORK_TCP_CONNECT_TIMEOUT = "networkTCPConnectTimeout"
|
let GROUP_DEFAULT_NETWORK_TCP_CONNECT_TIMEOUT = "networkTCPConnectTimeout"
|
||||||
let GROUP_DEFAULT_NETWORK_TCP_TIMEOUT = "networkTCPTimeout"
|
let GROUP_DEFAULT_NETWORK_TCP_TIMEOUT = "networkTCPTimeout"
|
||||||
let GROUP_DEFAULT_NETWORK_TCP_TIMEOUT_PER_KB = "networkTCPTimeoutPerKb"
|
let GROUP_DEFAULT_NETWORK_TCP_TIMEOUT_PER_KB = "networkTCPTimeoutPerKb"
|
||||||
|
@ -72,7 +72,7 @@ public func registerGroupDefaults() {
|
||||||
GROUP_DEFAULT_NETWORK_SESSION_MODE: TransportSessionMode.session.rawValue,
|
GROUP_DEFAULT_NETWORK_SESSION_MODE: TransportSessionMode.session.rawValue,
|
||||||
GROUP_DEFAULT_NETWORK_SMP_PROXY_MODE: SMPProxyMode.unknown.rawValue,
|
GROUP_DEFAULT_NETWORK_SMP_PROXY_MODE: SMPProxyMode.unknown.rawValue,
|
||||||
GROUP_DEFAULT_NETWORK_SMP_PROXY_FALLBACK: SMPProxyFallback.allowProtected.rawValue,
|
GROUP_DEFAULT_NETWORK_SMP_PROXY_FALLBACK: SMPProxyFallback.allowProtected.rawValue,
|
||||||
GROUP_DEFAULT_NETWORK_SMP_WEB_PORT: false,
|
GROUP_DEFAULT_NETWORK_SMP_WEB_PORT_SERVERS: SMPWebPortServers.preset.rawValue,
|
||||||
GROUP_DEFAULT_NETWORK_TCP_CONNECT_TIMEOUT: NetCfg.defaults.tcpConnectTimeout,
|
GROUP_DEFAULT_NETWORK_TCP_CONNECT_TIMEOUT: NetCfg.defaults.tcpConnectTimeout,
|
||||||
GROUP_DEFAULT_NETWORK_TCP_TIMEOUT: NetCfg.defaults.tcpTimeout,
|
GROUP_DEFAULT_NETWORK_TCP_TIMEOUT: NetCfg.defaults.tcpTimeout,
|
||||||
GROUP_DEFAULT_NETWORK_TCP_TIMEOUT_PER_KB: NetCfg.defaults.tcpTimeoutPerKb,
|
GROUP_DEFAULT_NETWORK_TCP_TIMEOUT_PER_KB: NetCfg.defaults.tcpTimeoutPerKb,
|
||||||
|
@ -251,6 +251,12 @@ public let networkSMPProxyFallbackGroupDefault = EnumDefault<SMPProxyFallback>(
|
||||||
withDefault: .allowProtected
|
withDefault: .allowProtected
|
||||||
)
|
)
|
||||||
|
|
||||||
|
public let networkSMPWebPortServersDefault = EnumDefault<SMPWebPortServers>(
|
||||||
|
defaults: groupDefaults,
|
||||||
|
forKey: GROUP_DEFAULT_NETWORK_SMP_WEB_PORT_SERVERS,
|
||||||
|
withDefault: .preset
|
||||||
|
)
|
||||||
|
|
||||||
public let storeDBPassphraseGroupDefault = BoolDefault(defaults: groupDefaults, forKey: GROUP_DEFAULT_STORE_DB_PASSPHRASE)
|
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)
|
public let initialRandomDBPassphraseGroupDefault = BoolDefault(defaults: groupDefaults, forKey: GROUP_DEFAULT_INITIAL_RANDOM_DB_PASSPHRASE)
|
||||||
|
@ -338,7 +344,7 @@ public func getNetCfg() -> NetCfg {
|
||||||
let sessionMode = networkSessionModeGroupDefault.get()
|
let sessionMode = networkSessionModeGroupDefault.get()
|
||||||
let smpProxyMode = networkSMPProxyModeGroupDefault.get()
|
let smpProxyMode = networkSMPProxyModeGroupDefault.get()
|
||||||
let smpProxyFallback = networkSMPProxyFallbackGroupDefault.get()
|
let smpProxyFallback = networkSMPProxyFallbackGroupDefault.get()
|
||||||
let smpWebPort = groupDefaults.bool(forKey: GROUP_DEFAULT_NETWORK_SMP_WEB_PORT)
|
let smpWebPortServers = networkSMPWebPortServersDefault.get()
|
||||||
let tcpConnectTimeout = groupDefaults.integer(forKey: GROUP_DEFAULT_NETWORK_TCP_CONNECT_TIMEOUT)
|
let tcpConnectTimeout = groupDefaults.integer(forKey: GROUP_DEFAULT_NETWORK_TCP_CONNECT_TIMEOUT)
|
||||||
let tcpTimeout = groupDefaults.integer(forKey: GROUP_DEFAULT_NETWORK_TCP_TIMEOUT)
|
let tcpTimeout = groupDefaults.integer(forKey: GROUP_DEFAULT_NETWORK_TCP_TIMEOUT)
|
||||||
let tcpTimeoutPerKb = groupDefaults.integer(forKey: GROUP_DEFAULT_NETWORK_TCP_TIMEOUT_PER_KB)
|
let tcpTimeoutPerKb = groupDefaults.integer(forKey: GROUP_DEFAULT_NETWORK_TCP_TIMEOUT_PER_KB)
|
||||||
|
@ -362,7 +368,7 @@ public func getNetCfg() -> NetCfg {
|
||||||
sessionMode: sessionMode,
|
sessionMode: sessionMode,
|
||||||
smpProxyMode: smpProxyMode,
|
smpProxyMode: smpProxyMode,
|
||||||
smpProxyFallback: smpProxyFallback,
|
smpProxyFallback: smpProxyFallback,
|
||||||
smpWebPort: smpWebPort,
|
smpWebPortServers: smpWebPortServers,
|
||||||
tcpConnectTimeout: tcpConnectTimeout,
|
tcpConnectTimeout: tcpConnectTimeout,
|
||||||
tcpTimeout: tcpTimeout,
|
tcpTimeout: tcpTimeout,
|
||||||
tcpTimeoutPerKb: tcpTimeoutPerKb,
|
tcpTimeoutPerKb: tcpTimeoutPerKb,
|
||||||
|
@ -381,7 +387,7 @@ public func setNetCfg(_ cfg: NetCfg, networkProxy: NetworkProxy?) {
|
||||||
networkSMPProxyFallbackGroupDefault.set(cfg.smpProxyFallback)
|
networkSMPProxyFallbackGroupDefault.set(cfg.smpProxyFallback)
|
||||||
let socksProxy = networkProxy?.toProxyString()
|
let socksProxy = networkProxy?.toProxyString()
|
||||||
groupDefaults.set(socksProxy, forKey: GROUP_DEFAULT_NETWORK_SOCKS_PROXY)
|
groupDefaults.set(socksProxy, forKey: GROUP_DEFAULT_NETWORK_SOCKS_PROXY)
|
||||||
groupDefaults.set(cfg.smpWebPort, forKey: GROUP_DEFAULT_NETWORK_SMP_WEB_PORT)
|
networkSMPWebPortServersDefault.set(cfg.smpWebPortServers)
|
||||||
groupDefaults.set(cfg.tcpConnectTimeout, forKey: GROUP_DEFAULT_NETWORK_TCP_CONNECT_TIMEOUT)
|
groupDefaults.set(cfg.tcpConnectTimeout, forKey: GROUP_DEFAULT_NETWORK_TCP_CONNECT_TIMEOUT)
|
||||||
groupDefaults.set(cfg.tcpTimeout, forKey: GROUP_DEFAULT_NETWORK_TCP_TIMEOUT)
|
groupDefaults.set(cfg.tcpTimeout, forKey: GROUP_DEFAULT_NETWORK_TCP_TIMEOUT)
|
||||||
groupDefaults.set(cfg.tcpTimeoutPerKb, forKey: GROUP_DEFAULT_NETWORK_TCP_TIMEOUT_PER_KB)
|
groupDefaults.set(cfg.tcpTimeoutPerKb, forKey: GROUP_DEFAULT_NETWORK_TCP_TIMEOUT_PER_KB)
|
||||||
|
|
|
@ -20,6 +20,8 @@ import chat.simplex.common.model.ChatController.getNetCfg
|
||||||
import chat.simplex.common.model.ChatController.setNetCfg
|
import chat.simplex.common.model.ChatController.setNetCfg
|
||||||
import chat.simplex.common.model.ChatModel.changingActiveUserMutex
|
import chat.simplex.common.model.ChatModel.changingActiveUserMutex
|
||||||
import chat.simplex.common.model.MsgContent.MCUnknown
|
import chat.simplex.common.model.MsgContent.MCUnknown
|
||||||
|
import chat.simplex.common.model.SMPProxyFallback.AllowProtected
|
||||||
|
import chat.simplex.common.model.SMPProxyMode.Always
|
||||||
import dev.icerock.moko.resources.compose.painterResource
|
import dev.icerock.moko.resources.compose.painterResource
|
||||||
import chat.simplex.common.platform.*
|
import chat.simplex.common.platform.*
|
||||||
import chat.simplex.common.ui.theme.*
|
import chat.simplex.common.ui.theme.*
|
||||||
|
@ -86,18 +88,7 @@ class AppPreferences {
|
||||||
val backgroundServiceBatteryNoticeShown = mkBoolPreference(SHARED_PREFS_SERVICE_BATTERY_NOTICE_SHOWN, false)
|
val backgroundServiceBatteryNoticeShown = mkBoolPreference(SHARED_PREFS_SERVICE_BATTERY_NOTICE_SHOWN, false)
|
||||||
val autoRestartWorkerVersion = mkIntPreference(SHARED_PREFS_AUTO_RESTART_WORKER_VERSION, 0)
|
val autoRestartWorkerVersion = mkIntPreference(SHARED_PREFS_AUTO_RESTART_WORKER_VERSION, 0)
|
||||||
val webrtcPolicyRelay = mkBoolPreference(SHARED_PREFS_WEBRTC_POLICY_RELAY, true)
|
val webrtcPolicyRelay = mkBoolPreference(SHARED_PREFS_WEBRTC_POLICY_RELAY, true)
|
||||||
private val _callOnLockScreen = mkStrPreference(SHARED_PREFS_WEBRTC_CALLS_ON_LOCK_SCREEN, CallOnLockScreen.default.name)
|
val callOnLockScreen: SharedPreference<CallOnLockScreen> = mkSafeEnumPreference(SHARED_PREFS_WEBRTC_CALLS_ON_LOCK_SCREEN, CallOnLockScreen.default)
|
||||||
val callOnLockScreen: SharedPreference<CallOnLockScreen> = SharedPreference(
|
|
||||||
get = fun(): CallOnLockScreen {
|
|
||||||
val value = _callOnLockScreen.get() ?: return CallOnLockScreen.default
|
|
||||||
return try {
|
|
||||||
CallOnLockScreen.valueOf(value)
|
|
||||||
} catch (e: Throwable) {
|
|
||||||
CallOnLockScreen.default
|
|
||||||
}
|
|
||||||
},
|
|
||||||
set = fun(action: CallOnLockScreen) { _callOnLockScreen.set(action.name) }
|
|
||||||
)
|
|
||||||
val performLA = mkBoolPreference(SHARED_PREFS_PERFORM_LA, false)
|
val performLA = mkBoolPreference(SHARED_PREFS_PERFORM_LA, false)
|
||||||
val laMode = mkEnumPreference(SHARED_PREFS_LA_MODE, LAMode.default) { LAMode.values().firstOrNull { it.name == this } }
|
val laMode = mkEnumPreference(SHARED_PREFS_LA_MODE, LAMode.default) { LAMode.values().firstOrNull { it.name == this } }
|
||||||
val laLockDelay = mkIntPreference(SHARED_PREFS_LA_LOCK_DELAY, 30)
|
val laLockDelay = mkIntPreference(SHARED_PREFS_LA_LOCK_DELAY, 30)
|
||||||
|
@ -107,18 +98,7 @@ class AppPreferences {
|
||||||
val privacyAcceptImages = mkBoolPreference(SHARED_PREFS_PRIVACY_ACCEPT_IMAGES, true)
|
val privacyAcceptImages = mkBoolPreference(SHARED_PREFS_PRIVACY_ACCEPT_IMAGES, true)
|
||||||
val privacyLinkPreviews = mkBoolPreference(SHARED_PREFS_PRIVACY_LINK_PREVIEWS, true)
|
val privacyLinkPreviews = mkBoolPreference(SHARED_PREFS_PRIVACY_LINK_PREVIEWS, true)
|
||||||
val privacyChatListOpenLinks = mkEnumPreference(SHARED_PREFS_PRIVACY_CHAT_LIST_OPEN_LINKS, PrivacyChatListOpenLinksMode.ASK) { PrivacyChatListOpenLinksMode.values().firstOrNull { it.name == this } }
|
val privacyChatListOpenLinks = mkEnumPreference(SHARED_PREFS_PRIVACY_CHAT_LIST_OPEN_LINKS, PrivacyChatListOpenLinksMode.ASK) { PrivacyChatListOpenLinksMode.values().firstOrNull { it.name == this } }
|
||||||
private val _simplexLinkMode = mkStrPreference(SHARED_PREFS_PRIVACY_SIMPLEX_LINK_MODE, SimplexLinkMode.default.name)
|
val simplexLinkMode: SharedPreference<SimplexLinkMode> = mkSafeEnumPreference(SHARED_PREFS_PRIVACY_SIMPLEX_LINK_MODE, SimplexLinkMode.default)
|
||||||
val simplexLinkMode: SharedPreference<SimplexLinkMode> = SharedPreference(
|
|
||||||
get = fun(): SimplexLinkMode {
|
|
||||||
val value = _simplexLinkMode.get() ?: return SimplexLinkMode.default
|
|
||||||
return try {
|
|
||||||
SimplexLinkMode.valueOf(value)
|
|
||||||
} catch (e: Throwable) {
|
|
||||||
SimplexLinkMode.default
|
|
||||||
}
|
|
||||||
},
|
|
||||||
set = fun(mode: SimplexLinkMode) { _simplexLinkMode.set(mode.name) }
|
|
||||||
)
|
|
||||||
val privacyShowChatPreviews = mkBoolPreference(SHARED_PREFS_PRIVACY_SHOW_CHAT_PREVIEWS, true)
|
val privacyShowChatPreviews = mkBoolPreference(SHARED_PREFS_PRIVACY_SHOW_CHAT_PREVIEWS, true)
|
||||||
val privacySaveLastDraft = mkBoolPreference(SHARED_PREFS_PRIVACY_SAVE_LAST_DRAFT, true)
|
val privacySaveLastDraft = mkBoolPreference(SHARED_PREFS_PRIVACY_SAVE_LAST_DRAFT, true)
|
||||||
val privacyShortLinks = mkBoolPreference(SHARED_PREFS_PRIVACY_SHORT_LINKS, false)
|
val privacyShortLinks = mkBoolPreference(SHARED_PREFS_PRIVACY_SHORT_LINKS, false)
|
||||||
|
@ -158,23 +138,12 @@ class AppPreferences {
|
||||||
},
|
},
|
||||||
set = fun(proxy: NetworkProxy) { _networkProxy.set(json.encodeToString(proxy)) }
|
set = fun(proxy: NetworkProxy) { _networkProxy.set(json.encodeToString(proxy)) }
|
||||||
)
|
)
|
||||||
private val _networkSessionMode = mkStrPreference(SHARED_PREFS_NETWORK_SESSION_MODE, TransportSessionMode.default.name)
|
val networkSessionMode: SharedPreference<TransportSessionMode> = mkSafeEnumPreference(SHARED_PREFS_NETWORK_SESSION_MODE, TransportSessionMode.default)
|
||||||
val networkSessionMode: SharedPreference<TransportSessionMode> = SharedPreference(
|
val networkSMPProxyMode: SharedPreference<SMPProxyMode> = mkSafeEnumPreference(SHARED_PREFS_NETWORK_SMP_PROXY_MODE, SMPProxyMode.default)
|
||||||
get = fun(): TransportSessionMode {
|
val networkSMPProxyFallback: SharedPreference<SMPProxyFallback> = mkSafeEnumPreference(SHARED_PREFS_NETWORK_SMP_PROXY_FALLBACK, SMPProxyFallback.default)
|
||||||
val value = _networkSessionMode.get() ?: return TransportSessionMode.default
|
val networkHostMode: SharedPreference<HostMode> = mkSafeEnumPreference(SHARED_PREFS_NETWORK_HOST_MODE, HostMode.default)
|
||||||
return try {
|
|
||||||
TransportSessionMode.valueOf(value)
|
|
||||||
} catch (e: Throwable) {
|
|
||||||
TransportSessionMode.default
|
|
||||||
}
|
|
||||||
},
|
|
||||||
set = fun(mode: TransportSessionMode) { _networkSessionMode.set(mode.name) }
|
|
||||||
)
|
|
||||||
val networkSMPProxyMode = mkStrPreference(SHARED_PREFS_NETWORK_SMP_PROXY_MODE, NetCfg.defaults.smpProxyMode.name)
|
|
||||||
val networkSMPProxyFallback = mkStrPreference(SHARED_PREFS_NETWORK_SMP_PROXY_FALLBACK, NetCfg.defaults.smpProxyFallback.name)
|
|
||||||
val networkHostMode = mkStrPreference(SHARED_PREFS_NETWORK_HOST_MODE, HostMode.OnionViaSocks.name)
|
|
||||||
val networkRequiredHostMode = mkBoolPreference(SHARED_PREFS_NETWORK_REQUIRED_HOST_MODE, false)
|
val networkRequiredHostMode = mkBoolPreference(SHARED_PREFS_NETWORK_REQUIRED_HOST_MODE, false)
|
||||||
val networkSMPWebPort = mkBoolPreference(SHARED_PREFS_NETWORK_SMP_WEB_PORT, false)
|
val networkSMPWebPortServers: SharedPreference<SMPWebPortServers> = mkSafeEnumPreference(SHARED_PREFS_NETWORK_SMP_WEB_PORT_SERVERS, SMPWebPortServers.default)
|
||||||
val networkTCPConnectTimeout = mkTimeoutPreference(SHARED_PREFS_NETWORK_TCP_CONNECT_TIMEOUT, NetCfg.defaults.tcpConnectTimeout, NetCfg.proxyDefaults.tcpConnectTimeout)
|
val networkTCPConnectTimeout = mkTimeoutPreference(SHARED_PREFS_NETWORK_TCP_CONNECT_TIMEOUT, NetCfg.defaults.tcpConnectTimeout, NetCfg.proxyDefaults.tcpConnectTimeout)
|
||||||
val networkTCPTimeout = mkTimeoutPreference(SHARED_PREFS_NETWORK_TCP_TIMEOUT, NetCfg.defaults.tcpTimeout, NetCfg.proxyDefaults.tcpTimeout)
|
val networkTCPTimeout = mkTimeoutPreference(SHARED_PREFS_NETWORK_TCP_TIMEOUT, NetCfg.defaults.tcpTimeout, NetCfg.proxyDefaults.tcpTimeout)
|
||||||
val networkTCPTimeoutPerKb = mkTimeoutPreference(SHARED_PREFS_NETWORK_TCP_TIMEOUT_PER_KB, NetCfg.defaults.tcpTimeoutPerKb, NetCfg.proxyDefaults.tcpTimeoutPerKb)
|
val networkTCPTimeoutPerKb = mkTimeoutPreference(SHARED_PREFS_NETWORK_TCP_TIMEOUT_PER_KB, NetCfg.defaults.tcpTimeoutPerKb, NetCfg.proxyDefaults.tcpTimeoutPerKb)
|
||||||
|
@ -329,7 +298,19 @@ class AppPreferences {
|
||||||
set = fun(value) = settings.putString(prefName, value.toString())
|
set = fun(value) = settings.putString(prefName, value.toString())
|
||||||
)
|
)
|
||||||
|
|
||||||
// LALAL
|
private inline fun <reified T : Enum<T>> mkSafeEnumPreference(key: String, default: T): SharedPreference<T> = SharedPreference(
|
||||||
|
get = {
|
||||||
|
val value = settings.getString(key, "")
|
||||||
|
if (value == "") return@SharedPreference default
|
||||||
|
try {
|
||||||
|
enumValueOf<T>(value)
|
||||||
|
} catch (e: IllegalArgumentException) {
|
||||||
|
default
|
||||||
|
}
|
||||||
|
},
|
||||||
|
set = { value -> settings.putString(key, value.name) }
|
||||||
|
)
|
||||||
|
|
||||||
private fun mkDatePreference(prefName: String, default: Instant?): SharedPreference<Instant?> =
|
private fun mkDatePreference(prefName: String, default: Instant?): SharedPreference<Instant?> =
|
||||||
SharedPreference(
|
SharedPreference(
|
||||||
get = {
|
get = {
|
||||||
|
@ -414,7 +395,7 @@ class AppPreferences {
|
||||||
private const val SHARED_PREFS_NETWORK_SMP_PROXY_FALLBACK = "NetworkSMPProxyFallback"
|
private const val SHARED_PREFS_NETWORK_SMP_PROXY_FALLBACK = "NetworkSMPProxyFallback"
|
||||||
private const val SHARED_PREFS_NETWORK_HOST_MODE = "NetworkHostMode"
|
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_REQUIRED_HOST_MODE = "NetworkRequiredHostMode"
|
||||||
private const val SHARED_PREFS_NETWORK_SMP_WEB_PORT = "NetworkSMPWebPort"
|
private const val SHARED_PREFS_NETWORK_SMP_WEB_PORT_SERVERS = "NetworkSMPWebPortServers"
|
||||||
private const val SHARED_PREFS_NETWORK_TCP_CONNECT_TIMEOUT = "NetworkTCPConnectTimeout"
|
private const val SHARED_PREFS_NETWORK_TCP_CONNECT_TIMEOUT = "NetworkTCPConnectTimeout"
|
||||||
private const val SHARED_PREFS_NETWORK_TCP_TIMEOUT = "NetworkTCPTimeout"
|
private const val SHARED_PREFS_NETWORK_TCP_TIMEOUT = "NetworkTCPTimeout"
|
||||||
private const val SHARED_PREFS_NETWORK_TCP_TIMEOUT_PER_KB = "networkTCPTimeoutPerKb"
|
private const val SHARED_PREFS_NETWORK_TCP_TIMEOUT_PER_KB = "networkTCPTimeoutPerKb"
|
||||||
|
@ -3309,12 +3290,12 @@ object ChatController {
|
||||||
} else {
|
} else {
|
||||||
null
|
null
|
||||||
}
|
}
|
||||||
val hostMode = HostMode.valueOf(appPrefs.networkHostMode.get()!!)
|
val hostMode = appPrefs.networkHostMode.get()
|
||||||
val requiredHostMode = appPrefs.networkRequiredHostMode.get()
|
val requiredHostMode = appPrefs.networkRequiredHostMode.get()
|
||||||
val sessionMode = appPrefs.networkSessionMode.get()
|
val sessionMode = appPrefs.networkSessionMode.get()
|
||||||
val smpProxyMode = SMPProxyMode.valueOf(appPrefs.networkSMPProxyMode.get()!!)
|
val smpProxyMode = appPrefs.networkSMPProxyMode.get()
|
||||||
val smpProxyFallback = SMPProxyFallback.valueOf(appPrefs.networkSMPProxyFallback.get()!!)
|
val smpProxyFallback = appPrefs.networkSMPProxyFallback.get()
|
||||||
val smpWebPort = appPrefs.networkSMPWebPort.get()
|
val smpWebPortServers = appPrefs.networkSMPWebPortServers.get()
|
||||||
val tcpConnectTimeout = appPrefs.networkTCPConnectTimeout.get()
|
val tcpConnectTimeout = appPrefs.networkTCPConnectTimeout.get()
|
||||||
val tcpTimeout = appPrefs.networkTCPTimeout.get()
|
val tcpTimeout = appPrefs.networkTCPTimeout.get()
|
||||||
val tcpTimeoutPerKb = appPrefs.networkTCPTimeoutPerKb.get()
|
val tcpTimeoutPerKb = appPrefs.networkTCPTimeoutPerKb.get()
|
||||||
|
@ -3337,7 +3318,7 @@ object ChatController {
|
||||||
sessionMode = sessionMode,
|
sessionMode = sessionMode,
|
||||||
smpProxyMode = smpProxyMode,
|
smpProxyMode = smpProxyMode,
|
||||||
smpProxyFallback = smpProxyFallback,
|
smpProxyFallback = smpProxyFallback,
|
||||||
smpWebPort = smpWebPort,
|
smpWebPortServers = smpWebPortServers,
|
||||||
tcpConnectTimeout = tcpConnectTimeout,
|
tcpConnectTimeout = tcpConnectTimeout,
|
||||||
tcpTimeout = tcpTimeout,
|
tcpTimeout = tcpTimeout,
|
||||||
tcpTimeoutPerKb = tcpTimeoutPerKb,
|
tcpTimeoutPerKb = tcpTimeoutPerKb,
|
||||||
|
@ -3353,12 +3334,12 @@ object ChatController {
|
||||||
* */
|
* */
|
||||||
fun setNetCfg(cfg: NetCfg) {
|
fun setNetCfg(cfg: NetCfg) {
|
||||||
appPrefs.networkUseSocksProxy.set(cfg.useSocksProxy)
|
appPrefs.networkUseSocksProxy.set(cfg.useSocksProxy)
|
||||||
appPrefs.networkHostMode.set(cfg.hostMode.name)
|
appPrefs.networkHostMode.set(cfg.hostMode)
|
||||||
appPrefs.networkRequiredHostMode.set(cfg.requiredHostMode)
|
appPrefs.networkRequiredHostMode.set(cfg.requiredHostMode)
|
||||||
appPrefs.networkSessionMode.set(cfg.sessionMode)
|
appPrefs.networkSessionMode.set(cfg.sessionMode)
|
||||||
appPrefs.networkSMPProxyMode.set(cfg.smpProxyMode.name)
|
appPrefs.networkSMPProxyMode.set(cfg.smpProxyMode)
|
||||||
appPrefs.networkSMPProxyFallback.set(cfg.smpProxyFallback.name)
|
appPrefs.networkSMPProxyFallback.set(cfg.smpProxyFallback)
|
||||||
appPrefs.networkSMPWebPort.set(cfg.smpWebPort)
|
appPrefs.networkSMPWebPortServers.set(cfg.smpWebPortServers)
|
||||||
appPrefs.networkTCPConnectTimeout.set(cfg.tcpConnectTimeout)
|
appPrefs.networkTCPConnectTimeout.set(cfg.tcpConnectTimeout)
|
||||||
appPrefs.networkTCPTimeout.set(cfg.tcpTimeout)
|
appPrefs.networkTCPTimeout.set(cfg.tcpTimeout)
|
||||||
appPrefs.networkTCPTimeoutPerKb.set(cfg.tcpTimeoutPerKb)
|
appPrefs.networkTCPTimeoutPerKb.set(cfg.tcpTimeoutPerKb)
|
||||||
|
@ -4460,13 +4441,13 @@ data class ParsedServerAddress (
|
||||||
@Serializable
|
@Serializable
|
||||||
data class NetCfg(
|
data class NetCfg(
|
||||||
val socksProxy: String?,
|
val socksProxy: String?,
|
||||||
val socksMode: SocksMode = SocksMode.Always,
|
val socksMode: SocksMode = SocksMode.default,
|
||||||
val hostMode: HostMode = HostMode.OnionViaSocks,
|
val hostMode: HostMode = HostMode.default,
|
||||||
val requiredHostMode: Boolean = false,
|
val requiredHostMode: Boolean = false,
|
||||||
val sessionMode: TransportSessionMode = TransportSessionMode.default,
|
val sessionMode: TransportSessionMode = TransportSessionMode.default,
|
||||||
val smpProxyMode: SMPProxyMode = SMPProxyMode.Always,
|
val smpProxyMode: SMPProxyMode = SMPProxyMode.default,
|
||||||
val smpProxyFallback: SMPProxyFallback = SMPProxyFallback.AllowProtected,
|
val smpProxyFallback: SMPProxyFallback = SMPProxyFallback.default,
|
||||||
val smpWebPort: Boolean = false,
|
val smpWebPortServers: SMPWebPortServers = SMPWebPortServers.default,
|
||||||
val tcpConnectTimeout: Long, // microseconds
|
val tcpConnectTimeout: Long, // microseconds
|
||||||
val tcpTimeout: Long, // microseconds
|
val tcpTimeout: Long, // microseconds
|
||||||
val tcpTimeoutPerKb: Long, // microseconds
|
val tcpTimeoutPerKb: Long, // microseconds
|
||||||
|
@ -4564,12 +4545,20 @@ enum class HostMode {
|
||||||
@SerialName("onionViaSocks") OnionViaSocks,
|
@SerialName("onionViaSocks") OnionViaSocks,
|
||||||
@SerialName("onion") Onion,
|
@SerialName("onion") Onion,
|
||||||
@SerialName("public") Public;
|
@SerialName("public") Public;
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
val default = OnionViaSocks
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Serializable
|
@Serializable
|
||||||
enum class SocksMode {
|
enum class SocksMode {
|
||||||
@SerialName("always") Always,
|
@SerialName("always") Always,
|
||||||
@SerialName("onion") Onion;
|
@SerialName("onion") Onion;
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
val default = Always
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Serializable
|
@Serializable
|
||||||
|
@ -4578,6 +4567,10 @@ enum class SMPProxyMode {
|
||||||
@SerialName("unknown") Unknown,
|
@SerialName("unknown") Unknown,
|
||||||
@SerialName("unprotected") Unprotected,
|
@SerialName("unprotected") Unprotected,
|
||||||
@SerialName("never") Never;
|
@SerialName("never") Never;
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
val default = Always
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Serializable
|
@Serializable
|
||||||
|
@ -4585,6 +4578,27 @@ enum class SMPProxyFallback {
|
||||||
@SerialName("allow") Allow,
|
@SerialName("allow") Allow,
|
||||||
@SerialName("allowProtected") AllowProtected,
|
@SerialName("allowProtected") AllowProtected,
|
||||||
@SerialName("prohibit") Prohibit;
|
@SerialName("prohibit") Prohibit;
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
val default = AllowProtected
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Serializable
|
||||||
|
enum class SMPWebPortServers {
|
||||||
|
@SerialName("all") All,
|
||||||
|
@SerialName("preset") Preset,
|
||||||
|
@SerialName("off") Off;
|
||||||
|
|
||||||
|
val text get(): StringResource = when (this) {
|
||||||
|
All -> MR.strings.network_smp_web_port_all
|
||||||
|
Preset -> MR.strings.network_smp_web_port_preset
|
||||||
|
Off -> MR.strings.network_smp_web_port_off
|
||||||
|
}
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
val default = Preset
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Serializable
|
@Serializable
|
||||||
|
|
|
@ -19,6 +19,7 @@ import dev.icerock.moko.resources.compose.painterResource
|
||||||
import dev.icerock.moko.resources.compose.stringResource
|
import dev.icerock.moko.resources.compose.stringResource
|
||||||
import androidx.compose.ui.text.style.TextOverflow
|
import androidx.compose.ui.text.style.TextOverflow
|
||||||
import androidx.compose.ui.unit.dp
|
import androidx.compose.ui.unit.dp
|
||||||
|
import androidx.compose.ui.unit.sp
|
||||||
import chat.simplex.common.model.*
|
import chat.simplex.common.model.*
|
||||||
import chat.simplex.common.model.ChatController.appPrefs
|
import chat.simplex.common.model.ChatController.appPrefs
|
||||||
import chat.simplex.common.ui.theme.*
|
import chat.simplex.common.ui.theme.*
|
||||||
|
@ -45,7 +46,7 @@ fun ModalData.AdvancedNetworkSettingsView(showModal: (ModalData.() -> Unit) -> U
|
||||||
val sessionMode = remember { mutableStateOf(currentCfgVal.sessionMode) }
|
val sessionMode = remember { mutableStateOf(currentCfgVal.sessionMode) }
|
||||||
val smpProxyMode = remember { mutableStateOf(currentCfgVal.smpProxyMode) }
|
val smpProxyMode = remember { mutableStateOf(currentCfgVal.smpProxyMode) }
|
||||||
val smpProxyFallback = remember { mutableStateOf(currentCfgVal.smpProxyFallback) }
|
val smpProxyFallback = remember { mutableStateOf(currentCfgVal.smpProxyFallback) }
|
||||||
val smpWebPort = remember { mutableStateOf(currentCfgVal.smpWebPort) }
|
val smpWebPortServers = remember { mutableStateOf(currentCfgVal.smpWebPortServers) }
|
||||||
|
|
||||||
val networkTCPConnectTimeout = remember { mutableStateOf(currentCfgVal.tcpConnectTimeout) }
|
val networkTCPConnectTimeout = remember { mutableStateOf(currentCfgVal.tcpConnectTimeout) }
|
||||||
val networkTCPTimeout = remember { mutableStateOf(currentCfgVal.tcpTimeout) }
|
val networkTCPTimeout = remember { mutableStateOf(currentCfgVal.tcpTimeout) }
|
||||||
|
@ -84,7 +85,7 @@ fun ModalData.AdvancedNetworkSettingsView(showModal: (ModalData.() -> Unit) -> U
|
||||||
sessionMode = sessionMode.value,
|
sessionMode = sessionMode.value,
|
||||||
smpProxyMode = smpProxyMode.value,
|
smpProxyMode = smpProxyMode.value,
|
||||||
smpProxyFallback = smpProxyFallback.value,
|
smpProxyFallback = smpProxyFallback.value,
|
||||||
smpWebPort = smpWebPort.value,
|
smpWebPortServers = smpWebPortServers.value,
|
||||||
tcpConnectTimeout = networkTCPConnectTimeout.value,
|
tcpConnectTimeout = networkTCPConnectTimeout.value,
|
||||||
tcpTimeout = networkTCPTimeout.value,
|
tcpTimeout = networkTCPTimeout.value,
|
||||||
tcpTimeoutPerKb = networkTCPTimeoutPerKb.value,
|
tcpTimeoutPerKb = networkTCPTimeoutPerKb.value,
|
||||||
|
@ -99,7 +100,7 @@ fun ModalData.AdvancedNetworkSettingsView(showModal: (ModalData.() -> Unit) -> U
|
||||||
sessionMode.value = cfg.sessionMode
|
sessionMode.value = cfg.sessionMode
|
||||||
smpProxyMode.value = cfg.smpProxyMode
|
smpProxyMode.value = cfg.smpProxyMode
|
||||||
smpProxyFallback.value = cfg.smpProxyFallback
|
smpProxyFallback.value = cfg.smpProxyFallback
|
||||||
smpWebPort.value = cfg.smpWebPort
|
smpWebPortServers.value = cfg.smpWebPortServers
|
||||||
networkTCPConnectTimeout.value = cfg.tcpConnectTimeout
|
networkTCPConnectTimeout.value = cfg.tcpConnectTimeout
|
||||||
networkTCPTimeout.value = cfg.tcpTimeout
|
networkTCPTimeout.value = cfg.tcpTimeout
|
||||||
networkTCPTimeoutPerKb.value = cfg.tcpTimeoutPerKb
|
networkTCPTimeoutPerKb.value = cfg.tcpTimeoutPerKb
|
||||||
|
@ -154,7 +155,7 @@ fun ModalData.AdvancedNetworkSettingsView(showModal: (ModalData.() -> Unit) -> U
|
||||||
sessionMode = sessionMode,
|
sessionMode = sessionMode,
|
||||||
smpProxyMode = smpProxyMode,
|
smpProxyMode = smpProxyMode,
|
||||||
smpProxyFallback = smpProxyFallback,
|
smpProxyFallback = smpProxyFallback,
|
||||||
smpWebPort,
|
smpWebPortServers,
|
||||||
networkTCPConnectTimeout,
|
networkTCPConnectTimeout,
|
||||||
networkTCPTimeout,
|
networkTCPTimeout,
|
||||||
networkTCPTimeoutPerKb,
|
networkTCPTimeoutPerKb,
|
||||||
|
@ -187,7 +188,7 @@ fun ModalData.AdvancedNetworkSettingsView(showModal: (ModalData.() -> Unit) -> U
|
||||||
sessionMode: MutableState<TransportSessionMode>,
|
sessionMode: MutableState<TransportSessionMode>,
|
||||||
smpProxyMode: MutableState<SMPProxyMode>,
|
smpProxyMode: MutableState<SMPProxyMode>,
|
||||||
smpProxyFallback: MutableState<SMPProxyFallback>,
|
smpProxyFallback: MutableState<SMPProxyFallback>,
|
||||||
smpWebPort: MutableState<Boolean>,
|
smpWebPortServers: MutableState<SMPWebPortServers>,
|
||||||
networkTCPConnectTimeout: MutableState<Long>,
|
networkTCPConnectTimeout: MutableState<Long>,
|
||||||
networkTCPTimeout: MutableState<Long>,
|
networkTCPTimeout: MutableState<Long>,
|
||||||
networkTCPTimeoutPerKb: MutableState<Long>,
|
networkTCPTimeoutPerKb: MutableState<Long>,
|
||||||
|
@ -226,11 +227,16 @@ fun ModalData.AdvancedNetworkSettingsView(showModal: (ModalData.() -> Unit) -> U
|
||||||
}
|
}
|
||||||
SectionDividerSpaced()
|
SectionDividerSpaced()
|
||||||
SectionView(stringResource(MR.strings.network_smp_web_port_section_title).uppercase()) {
|
SectionView(stringResource(MR.strings.network_smp_web_port_section_title).uppercase()) {
|
||||||
PreferenceToggle(stringResource(MR.strings.network_smp_web_port_toggle), checked = smpWebPort.value) {
|
ExposedDropDownSettingRow(
|
||||||
smpWebPort.value = it
|
stringResource(MR.strings.network_smp_web_port_toggle),
|
||||||
}
|
SMPWebPortServers.entries.map { it to stringResource(it.text) },
|
||||||
|
smpWebPortServers
|
||||||
|
) { smpWebPortServers.value = it }
|
||||||
}
|
}
|
||||||
SectionTextFooter(String.format(stringResource(MR.strings.network_smp_web_port_footer), if (smpWebPort.value) "443" else "5223"))
|
SectionTextFooter(
|
||||||
|
if (smpWebPortServers.value == SMPWebPortServers.Preset) stringResource(MR.strings.network_smp_web_port_preset_footer)
|
||||||
|
else String.format(stringResource(MR.strings.network_smp_web_port_footer), if (smpWebPortServers.value == SMPWebPortServers.All) "443" else "5223")
|
||||||
|
)
|
||||||
SectionDividerSpaced(maxTopPadding = true)
|
SectionDividerSpaced(maxTopPadding = true)
|
||||||
|
|
||||||
SectionView(stringResource(MR.strings.network_option_tcp_connection).uppercase()) {
|
SectionView(stringResource(MR.strings.network_option_tcp_connection).uppercase()) {
|
||||||
|
@ -320,7 +326,7 @@ private fun SMPProxyModePicker(
|
||||||
) {
|
) {
|
||||||
val density = LocalDensity.current
|
val density = LocalDensity.current
|
||||||
val values = remember {
|
val values = remember {
|
||||||
SMPProxyMode.values().map {
|
SMPProxyMode.entries.map {
|
||||||
when (it) {
|
when (it) {
|
||||||
SMPProxyMode.Always -> ValueTitleDesc(SMPProxyMode.Always, generalGetString(MR.strings.network_smp_proxy_mode_always), escapedHtmlToAnnotatedString(generalGetString(MR.strings.network_smp_proxy_mode_always_description), density))
|
SMPProxyMode.Always -> ValueTitleDesc(SMPProxyMode.Always, generalGetString(MR.strings.network_smp_proxy_mode_always), escapedHtmlToAnnotatedString(generalGetString(MR.strings.network_smp_proxy_mode_always_description), density))
|
||||||
SMPProxyMode.Unknown -> ValueTitleDesc(SMPProxyMode.Unknown, generalGetString(MR.strings.network_smp_proxy_mode_unknown), escapedHtmlToAnnotatedString(generalGetString(MR.strings.network_smp_proxy_mode_unknown_description), density))
|
SMPProxyMode.Unknown -> ValueTitleDesc(SMPProxyMode.Unknown, generalGetString(MR.strings.network_smp_proxy_mode_unknown), escapedHtmlToAnnotatedString(generalGetString(MR.strings.network_smp_proxy_mode_unknown_description), density))
|
||||||
|
@ -355,7 +361,7 @@ private fun SMPProxyFallbackPicker(
|
||||||
) {
|
) {
|
||||||
val density = LocalDensity.current
|
val density = LocalDensity.current
|
||||||
val values = remember {
|
val values = remember {
|
||||||
SMPProxyFallback.values().map {
|
SMPProxyFallback.entries.map {
|
||||||
when (it) {
|
when (it) {
|
||||||
SMPProxyFallback.Allow -> ValueTitleDesc(SMPProxyFallback.Allow, generalGetString(MR.strings.network_smp_proxy_fallback_allow), escapedHtmlToAnnotatedString(generalGetString(MR.strings.network_smp_proxy_fallback_allow_description), density))
|
SMPProxyFallback.Allow -> ValueTitleDesc(SMPProxyFallback.Allow, generalGetString(MR.strings.network_smp_proxy_fallback_allow), escapedHtmlToAnnotatedString(generalGetString(MR.strings.network_smp_proxy_fallback_allow_description), density))
|
||||||
SMPProxyFallback.AllowProtected -> ValueTitleDesc(SMPProxyFallback.AllowProtected, generalGetString(MR.strings.network_smp_proxy_fallback_allow_protected), escapedHtmlToAnnotatedString(generalGetString(MR.strings.network_smp_proxy_fallback_allow_protected_description), density))
|
SMPProxyFallback.AllowProtected -> ValueTitleDesc(SMPProxyFallback.AllowProtected, generalGetString(MR.strings.network_smp_proxy_fallback_allow_protected), escapedHtmlToAnnotatedString(generalGetString(MR.strings.network_smp_proxy_fallback_allow_protected_description), density))
|
||||||
|
@ -548,7 +554,7 @@ fun PreviewAdvancedNetworkSettingsLayout() {
|
||||||
sessionMode = remember { mutableStateOf(TransportSessionMode.User) },
|
sessionMode = remember { mutableStateOf(TransportSessionMode.User) },
|
||||||
smpProxyMode = remember { mutableStateOf(SMPProxyMode.Never) },
|
smpProxyMode = remember { mutableStateOf(SMPProxyMode.Never) },
|
||||||
smpProxyFallback = remember { mutableStateOf(SMPProxyFallback.Allow) },
|
smpProxyFallback = remember { mutableStateOf(SMPProxyFallback.Allow) },
|
||||||
smpWebPort = remember { mutableStateOf(false) },
|
smpWebPortServers = remember { mutableStateOf(SMPWebPortServers.Preset) },
|
||||||
networkTCPConnectTimeout = remember { mutableStateOf(10_000000) },
|
networkTCPConnectTimeout = remember { mutableStateOf(10_000000) },
|
||||||
networkTCPTimeout = remember { mutableStateOf(10_000000) },
|
networkTCPTimeout = remember { mutableStateOf(10_000000) },
|
||||||
networkTCPTimeoutPerKb = remember { mutableStateOf(10_000) },
|
networkTCPTimeoutPerKb = remember { mutableStateOf(10_000) },
|
||||||
|
|
|
@ -964,6 +964,10 @@
|
||||||
<string name="network_smp_web_port_section_title">TCP port for messaging</string>
|
<string name="network_smp_web_port_section_title">TCP port for messaging</string>
|
||||||
<string name="network_smp_web_port_toggle">Use web port</string>
|
<string name="network_smp_web_port_toggle">Use web port</string>
|
||||||
<string name="network_smp_web_port_footer">Use TCP port %1$s when no port is specified.</string>
|
<string name="network_smp_web_port_footer">Use TCP port %1$s when no port is specified.</string>
|
||||||
|
<string name="network_smp_web_port_preset_footer">Use TCP port 443 for preset servers only.</string>
|
||||||
|
<string name="network_smp_web_port_all">All servers</string>
|
||||||
|
<string name="network_smp_web_port_preset">Preset servers</string>
|
||||||
|
<string name="network_smp_web_port_off">Off</string>
|
||||||
<string name="appearance_settings">Appearance</string>
|
<string name="appearance_settings">Appearance</string>
|
||||||
<string name="customize_theme_title">Customize theme</string>
|
<string name="customize_theme_title">Customize theme</string>
|
||||||
<string name="theme_colors_section_title">INTERFACE COLORS</string>
|
<string name="theme_colors_section_title">INTERFACE COLORS</string>
|
||||||
|
|
|
@ -2440,6 +2440,10 @@
|
||||||
<string name="report_compose_reason_header_other">Пожаловаться: увидят только модераторы группы.</string>
|
<string name="report_compose_reason_header_other">Пожаловаться: увидят только модераторы группы.</string>
|
||||||
<string name="mute_all_chat">Выключить уведомления для всех</string>
|
<string name="mute_all_chat">Выключить уведомления для всех</string>
|
||||||
<string name="network_smp_web_port_footer">Использовать TCP-порт %1$s, когда порт не указан.</string>
|
<string name="network_smp_web_port_footer">Использовать TCP-порт %1$s, когда порт не указан.</string>
|
||||||
|
<string name="network_smp_web_port_preset_footer">Использовать TCP-порт 443 только для серверов по умолчанию.</string>
|
||||||
|
<string name="network_smp_web_port_all">Все серверы</string>
|
||||||
|
<string name="network_smp_web_port_preset">Серверы по умолчанию</string>
|
||||||
|
<string name="network_smp_web_port_off">Нет</string>
|
||||||
<string name="network_smp_web_port_toggle">Использовать веб-порт</string>
|
<string name="network_smp_web_port_toggle">Использовать веб-порт</string>
|
||||||
<string name="privacy_chat_list_open_links_no">Нет</string>
|
<string name="privacy_chat_list_open_links_no">Нет</string>
|
||||||
<string name="report_compose_reason_header_illegal">Пожаловаться на сообщение: увидят только модераторы группы.</string>
|
<string name="report_compose_reason_header_illegal">Пожаловаться на сообщение: увидят только модераторы группы.</string>
|
||||||
|
|
|
@ -12,7 +12,7 @@ constraints: zip +disable-bzip2 +disable-zstd
|
||||||
source-repository-package
|
source-repository-package
|
||||||
type: git
|
type: git
|
||||||
location: https://github.com/simplex-chat/simplexmq.git
|
location: https://github.com/simplex-chat/simplexmq.git
|
||||||
tag: ec5a60430d6e2b1b4f33fa1790effbb6060bf7b8
|
tag: 08b84deba458407ae97d55debd98b872cb6c4d79
|
||||||
|
|
||||||
source-repository-package
|
source-repository-package
|
||||||
type: git
|
type: git
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
{
|
{
|
||||||
"https://github.com/simplex-chat/simplexmq.git"."ec5a60430d6e2b1b4f33fa1790effbb6060bf7b8" = "0q238j7w976f9nx7r3gd61yhj557zwcxvrbci5lq7fib0v4ja7aw";
|
"https://github.com/simplex-chat/simplexmq.git"."08b84deba458407ae97d55debd98b872cb6c4d79" = "0b4n7d81spl1r7zppr0lc40ls9m1i93g4l3hzg2996pi3bxmafrr";
|
||||||
"https://github.com/simplex-chat/hs-socks.git"."a30cc7a79a08d8108316094f8f2f82a0c5e1ac51" = "0yasvnr7g91k76mjkamvzab2kvlb1g5pspjyjn2fr6v83swjhj38";
|
"https://github.com/simplex-chat/hs-socks.git"."a30cc7a79a08d8108316094f8f2f82a0c5e1ac51" = "0yasvnr7g91k76mjkamvzab2kvlb1g5pspjyjn2fr6v83swjhj38";
|
||||||
"https://github.com/simplex-chat/direct-sqlcipher.git"."f814ee68b16a9447fbb467ccc8f29bdd3546bfd9" = "1ql13f4kfwkbaq7nygkxgw84213i0zm7c1a8hwvramayxl38dq5d";
|
"https://github.com/simplex-chat/direct-sqlcipher.git"."f814ee68b16a9447fbb467ccc8f29bdd3546bfd9" = "1ql13f4kfwkbaq7nygkxgw84213i0zm7c1a8hwvramayxl38dq5d";
|
||||||
"https://github.com/simplex-chat/sqlcipher-simple.git"."a46bd361a19376c5211f1058908fc0ae6bf42446" = "1z0r78d8f0812kxbgsm735qf6xx8lvaz27k1a0b4a2m0sshpd5gl";
|
"https://github.com/simplex-chat/sqlcipher-simple.git"."a46bd361a19376c5211f1058908fc0ae6bf42446" = "1z0r78d8f0812kxbgsm735qf6xx8lvaz27k1a0b4a2m0sshpd5gl";
|
||||||
|
|
|
@ -89,6 +89,7 @@ defaultChatConfig =
|
||||||
-- to have a different set of servers on the receiving end and on the sending end.
|
-- to have a different set of servers on the receiving end and on the sending end.
|
||||||
-- To preserve backward compatibility receiving end should update before the sending.
|
-- To preserve backward compatibility receiving end should update before the sending.
|
||||||
shortLinkPresetServers = allPresetServers,
|
shortLinkPresetServers = allPresetServers,
|
||||||
|
presetDomains = [".simplex.im", ".simplexonflux.com"],
|
||||||
tbqSize = 1024,
|
tbqSize = 1024,
|
||||||
fileChunkSize = 15780, -- do not change
|
fileChunkSize = 15780, -- do not change
|
||||||
xftpDescrPartSize = 14000,
|
xftpDescrPartSize = 14000,
|
||||||
|
@ -240,12 +241,12 @@ newChatController
|
||||||
randomServerCfgs name p opDomains rndSrvs =
|
randomServerCfgs name p opDomains rndSrvs =
|
||||||
toJustOrError name $ L.nonEmpty $ agentServerCfgs p opDomains $ concatMap (pServers p) rndSrvs
|
toJustOrError name $ L.nonEmpty $ agentServerCfgs p opDomains $ concatMap (pServers p) rndSrvs
|
||||||
agentServers :: DB.Connection -> ChatConfig -> NonEmpty PresetOperator -> RandomAgentServers -> IO InitialAgentServers
|
agentServers :: DB.Connection -> ChatConfig -> NonEmpty PresetOperator -> RandomAgentServers -> IO InitialAgentServers
|
||||||
agentServers db ChatConfig {presetServers = PresetServers {ntf, netCfg}} presetOps as = do
|
agentServers db ChatConfig {presetServers = PresetServers {ntf, netCfg}, presetDomains} presetOps as = do
|
||||||
users <- getUsers db
|
users <- getUsers db
|
||||||
ops <- getUpdateServerOperators db presetOps (null users)
|
ops <- getUpdateServerOperators db presetOps (null users)
|
||||||
let opDomains = operatorDomains $ mapMaybe snd ops
|
let opDomains = operatorDomains $ mapMaybe snd ops
|
||||||
(smp', xftp') <- unzip <$> mapM (getServers ops opDomains) users
|
(smp', xftp') <- unzip <$> mapM (getServers ops opDomains) users
|
||||||
pure InitialAgentServers {smp = M.fromList (optServers smp' smpServers), xftp = M.fromList (optServers xftp' xftpServers), ntf, netCfg}
|
pure InitialAgentServers {smp = M.fromList (optServers smp' smpServers), xftp = M.fromList (optServers xftp' xftpServers), ntf, netCfg, presetDomains}
|
||||||
where
|
where
|
||||||
optServers :: [(UserId, NonEmpty (ServerCfg p))] -> [ProtoServerWithAuth p] -> [(UserId, NonEmpty (ServerCfg p))]
|
optServers :: [(UserId, NonEmpty (ServerCfg p))] -> [ProtoServerWithAuth p] -> [(UserId, NonEmpty (ServerCfg p))]
|
||||||
optServers srvs overrides_ = case L.nonEmpty overrides_ of
|
optServers srvs overrides_ = case L.nonEmpty overrides_ of
|
||||||
|
|
|
@ -50,6 +50,7 @@ import Data.Time.Clock.System (SystemTime (..), systemToUTCTime)
|
||||||
import Data.Version (showVersion)
|
import Data.Version (showVersion)
|
||||||
import Data.Word (Word16)
|
import Data.Word (Word16)
|
||||||
import Language.Haskell.TH (Exp, Q, runIO)
|
import Language.Haskell.TH (Exp, Q, runIO)
|
||||||
|
import Network.Socket (HostName)
|
||||||
import Numeric.Natural
|
import Numeric.Natural
|
||||||
import qualified Paths_simplex_chat as SC
|
import qualified Paths_simplex_chat as SC
|
||||||
import Simplex.Chat.AppSettings
|
import Simplex.Chat.AppSettings
|
||||||
|
@ -77,7 +78,7 @@ import Simplex.Messaging.Agent.Protocol
|
||||||
import Simplex.Messaging.Agent.Store.Common (DBStore, withTransaction, withTransactionPriority)
|
import Simplex.Messaging.Agent.Store.Common (DBStore, withTransaction, withTransactionPriority)
|
||||||
import Simplex.Messaging.Agent.Store.Shared (MigrationConfirmation, UpMigration)
|
import Simplex.Messaging.Agent.Store.Shared (MigrationConfirmation, UpMigration)
|
||||||
import qualified Simplex.Messaging.Agent.Store.DB as DB
|
import qualified Simplex.Messaging.Agent.Store.DB as DB
|
||||||
import Simplex.Messaging.Client (HostMode (..), SMPProxyFallback (..), SMPProxyMode (..), SocksMode (..))
|
import Simplex.Messaging.Client (HostMode (..), SMPProxyFallback (..), SMPProxyMode (..), SMPWebPortServers (..), SocksMode (..))
|
||||||
import qualified Simplex.Messaging.Crypto as C
|
import qualified Simplex.Messaging.Crypto as C
|
||||||
import Simplex.Messaging.Crypto.File (CryptoFile (..))
|
import Simplex.Messaging.Crypto.File (CryptoFile (..))
|
||||||
import qualified Simplex.Messaging.Crypto.File as CF
|
import qualified Simplex.Messaging.Crypto.File as CF
|
||||||
|
@ -139,6 +140,7 @@ data ChatConfig = ChatConfig
|
||||||
confirmMigrations :: MigrationConfirmation,
|
confirmMigrations :: MigrationConfirmation,
|
||||||
presetServers :: PresetServers,
|
presetServers :: PresetServers,
|
||||||
shortLinkPresetServers :: NonEmpty SMPServer,
|
shortLinkPresetServers :: NonEmpty SMPServer,
|
||||||
|
presetDomains :: [HostName],
|
||||||
tbqSize :: Natural,
|
tbqSize :: Natural,
|
||||||
fileChunkSize :: Integer,
|
fileChunkSize :: Integer,
|
||||||
xftpDescrPartSize :: Int,
|
xftpDescrPartSize :: Int,
|
||||||
|
@ -1053,7 +1055,7 @@ data SimpleNetCfg = SimpleNetCfg
|
||||||
requiredHostMode :: Bool,
|
requiredHostMode :: Bool,
|
||||||
smpProxyMode_ :: Maybe SMPProxyMode,
|
smpProxyMode_ :: Maybe SMPProxyMode,
|
||||||
smpProxyFallback_ :: Maybe SMPProxyFallback,
|
smpProxyFallback_ :: Maybe SMPProxyFallback,
|
||||||
smpWebPort :: Bool,
|
smpWebPortServers :: SMPWebPortServers,
|
||||||
tcpTimeout_ :: Maybe Int,
|
tcpTimeout_ :: Maybe Int,
|
||||||
logTLSErrors :: Bool
|
logTLSErrors :: Bool
|
||||||
}
|
}
|
||||||
|
@ -1068,7 +1070,7 @@ defaultSimpleNetCfg =
|
||||||
requiredHostMode = False,
|
requiredHostMode = False,
|
||||||
smpProxyMode_ = Nothing,
|
smpProxyMode_ = Nothing,
|
||||||
smpProxyFallback_ = Nothing,
|
smpProxyFallback_ = Nothing,
|
||||||
smpWebPort = False,
|
smpWebPortServers = SWPPreset,
|
||||||
tcpTimeout_ = Nothing,
|
tcpTimeout_ = Nothing,
|
||||||
logTLSErrors = False
|
logTLSErrors = False
|
||||||
}
|
}
|
||||||
|
|
|
@ -91,7 +91,7 @@ import Simplex.Messaging.Agent.Store.Interface (execSQL)
|
||||||
import Simplex.Messaging.Agent.Store.Shared (upMigration)
|
import Simplex.Messaging.Agent.Store.Shared (upMigration)
|
||||||
import qualified Simplex.Messaging.Agent.Store.DB as DB
|
import qualified Simplex.Messaging.Agent.Store.DB as DB
|
||||||
import Simplex.Messaging.Agent.Store.Interface (getCurrentMigrations)
|
import Simplex.Messaging.Agent.Store.Interface (getCurrentMigrations)
|
||||||
import Simplex.Messaging.Client (NetworkConfig (..), SocksMode (SMAlways), textToHostMode)
|
import Simplex.Messaging.Client (NetworkConfig (..), SMPWebPortServers (..), SocksMode (SMAlways), textToHostMode)
|
||||||
import qualified Simplex.Messaging.Crypto as C
|
import qualified Simplex.Messaging.Crypto as C
|
||||||
import Simplex.Messaging.Crypto.File (CryptoFile (..), CryptoFileArgs (..))
|
import Simplex.Messaging.Crypto.File (CryptoFile (..), CryptoFileArgs (..))
|
||||||
import qualified Simplex.Messaging.Crypto.File as CF
|
import qualified Simplex.Messaging.Crypto.File as CF
|
||||||
|
@ -255,11 +255,11 @@ stopChatController ChatController {smpAgent, agentAsync = s, sndFiles, rcvFiles,
|
||||||
atomically $ writeTVar files M.empty
|
atomically $ writeTVar files M.empty
|
||||||
|
|
||||||
updateNetworkConfig :: NetworkConfig -> SimpleNetCfg -> NetworkConfig
|
updateNetworkConfig :: NetworkConfig -> SimpleNetCfg -> NetworkConfig
|
||||||
updateNetworkConfig cfg SimpleNetCfg {socksProxy, socksMode, hostMode, requiredHostMode, smpProxyMode_, smpProxyFallback_, smpWebPort, tcpTimeout_, logTLSErrors} =
|
updateNetworkConfig cfg SimpleNetCfg {socksProxy, socksMode, hostMode, requiredHostMode, smpProxyMode_, smpProxyFallback_, smpWebPortServers, tcpTimeout_, logTLSErrors} =
|
||||||
let cfg1 = maybe cfg (\smpProxyMode -> cfg {smpProxyMode}) smpProxyMode_
|
let cfg1 = maybe cfg (\smpProxyMode -> cfg {smpProxyMode}) smpProxyMode_
|
||||||
cfg2 = maybe cfg1 (\smpProxyFallback -> cfg1 {smpProxyFallback}) smpProxyFallback_
|
cfg2 = maybe cfg1 (\smpProxyFallback -> cfg1 {smpProxyFallback}) smpProxyFallback_
|
||||||
cfg3 = maybe cfg2 (\tcpTimeout -> cfg2 {tcpTimeout, tcpConnectTimeout = (tcpTimeout * 3) `div` 2}) tcpTimeout_
|
cfg3 = maybe cfg2 (\tcpTimeout -> cfg2 {tcpTimeout, tcpConnectTimeout = (tcpTimeout * 3) `div` 2}) tcpTimeout_
|
||||||
in cfg3 {socksProxy, socksMode, hostMode, requiredHostMode, smpWebPort, logTLSErrors}
|
in cfg3 {socksProxy, socksMode, hostMode, requiredHostMode, smpWebPortServers, logTLSErrors}
|
||||||
|
|
||||||
useServers :: Foldable f => RandomAgentServers -> [(Text, ServerOperator)] -> f UserOperatorServers -> (NonEmpty (ServerCfg 'PSMP), NonEmpty (ServerCfg 'PXFTP))
|
useServers :: Foldable f => RandomAgentServers -> [(Text, ServerOperator)] -> f UserOperatorServers -> (NonEmpty (ServerCfg 'PSMP), NonEmpty (ServerCfg 'PXFTP))
|
||||||
useServers as opDomains uss =
|
useServers as opDomains uss =
|
||||||
|
@ -4383,11 +4383,11 @@ chatCommandP =
|
||||||
requiredHostMode <- (" required-host-mode" $> True) <|> pure False
|
requiredHostMode <- (" required-host-mode" $> True) <|> pure False
|
||||||
smpProxyMode_ <- optional $ " smp-proxy=" *> strP
|
smpProxyMode_ <- optional $ " smp-proxy=" *> strP
|
||||||
smpProxyFallback_ <- optional $ " smp-proxy-fallback=" *> strP
|
smpProxyFallback_ <- optional $ " smp-proxy-fallback=" *> strP
|
||||||
smpWebPort <- (" smp-web-port" $> True) <|> pure False
|
smpWebPortServers <- (" smp-web-port-servers=" *> strP) <|> (" smp-web-port" $> SWPAll) <|> pure SWPPreset
|
||||||
t_ <- optional $ " timeout=" *> A.decimal
|
t_ <- optional $ " timeout=" *> A.decimal
|
||||||
logTLSErrors <- " log=" *> onOffP <|> pure False
|
logTLSErrors <- " log=" *> onOffP <|> pure False
|
||||||
let tcpTimeout_ = (1000000 *) <$> t_
|
let tcpTimeout_ = (1000000 *) <$> t_
|
||||||
pure $ SimpleNetCfg {socksProxy, socksMode, hostMode, requiredHostMode, smpProxyMode_, smpProxyFallback_, smpWebPort, tcpTimeout_, logTLSErrors}
|
pure $ SimpleNetCfg {socksProxy, socksMode, hostMode, requiredHostMode, smpProxyMode_, smpProxyFallback_, smpWebPortServers, tcpTimeout_, logTLSErrors}
|
||||||
#if !defined(dbPostgres)
|
#if !defined(dbPostgres)
|
||||||
dbKeyP = nonEmptyKey <$?> strP
|
dbKeyP = nonEmptyKey <$?> strP
|
||||||
nonEmptyKey k@(DBEncryptionKey s) = if BA.null s then Left "empty key" else Right k
|
nonEmptyKey k@(DBEncryptionKey s) = if BA.null s then Left "empty key" else Right k
|
||||||
|
|
|
@ -46,7 +46,7 @@ operatorFlux =
|
||||||
-- so that option used for restoring links is updated earlier, for backward/forward compatibility.
|
-- so that option used for restoring links is updated earlier, for backward/forward compatibility.
|
||||||
allPresetServers :: NonEmpty SMPServer
|
allPresetServers :: NonEmpty SMPServer
|
||||||
allPresetServers = enabledSimplexChatSMPServers <> disabledSimplexChatSMPServers <> fluxSMPServers_
|
allPresetServers = enabledSimplexChatSMPServers <> disabledSimplexChatSMPServers <> fluxSMPServers_
|
||||||
-- TODO [short links] remove, added for testing
|
-- added for testing, not preset in the clients
|
||||||
<> ["smp://8Af90NX2TTkKEJAF1RCg69P_Odg2Z-6_J6DOKUqK3rQ=@smp7.simplex.im,dbxqutskmmbkbrs7ofi7pmopeyhgi5cxbjbh4ummgmep4r6bz4cbrcid.onion"]
|
<> ["smp://8Af90NX2TTkKEJAF1RCg69P_Odg2Z-6_J6DOKUqK3rQ=@smp7.simplex.im,dbxqutskmmbkbrs7ofi7pmopeyhgi5cxbjbh4ummgmep4r6bz4cbrcid.onion"]
|
||||||
|
|
||||||
simplexChatSMPServers :: [NewUserServer 'PSMP]
|
simplexChatSMPServers :: [NewUserServer 'PSMP]
|
||||||
|
@ -87,7 +87,7 @@ disabledSimplexChatSMPServers =
|
||||||
]
|
]
|
||||||
|
|
||||||
fluxSMPServers :: [NewUserServer 'PSMP]
|
fluxSMPServers :: [NewUserServer 'PSMP]
|
||||||
fluxSMPServers = map (presetServer' True) $ L.toList fluxSMPServers_
|
fluxSMPServers = map (presetServer' True) (L.toList fluxSMPServers_)
|
||||||
|
|
||||||
-- Please note: if any servers are removed from this list, they MUST be added to allPresetServers.
|
-- Please note: if any servers are removed from this list, they MUST be added to allPresetServers.
|
||||||
-- Otherwise previously created short links won't work.
|
-- Otherwise previously created short links won't work.
|
||||||
|
|
|
@ -29,7 +29,7 @@ import Numeric.Natural (Natural)
|
||||||
import Options.Applicative
|
import Options.Applicative
|
||||||
import Simplex.Chat.Controller (ChatLogLevel (..), SimpleNetCfg (..), updateStr, versionNumber, versionString)
|
import Simplex.Chat.Controller (ChatLogLevel (..), SimpleNetCfg (..), updateStr, versionNumber, versionString)
|
||||||
import Simplex.FileTransfer.Description (mb)
|
import Simplex.FileTransfer.Description (mb)
|
||||||
import Simplex.Messaging.Client (HostMode (..), SocksMode (..), textToHostMode)
|
import Simplex.Messaging.Client (HostMode (..), SMPWebPortServers (..), SocksMode (..), textToHostMode)
|
||||||
import Simplex.Messaging.Encoding.String
|
import Simplex.Messaging.Encoding.String
|
||||||
import Simplex.Messaging.Parsers (parseAll)
|
import Simplex.Messaging.Parsers (parseAll)
|
||||||
import Simplex.Messaging.Protocol (ProtoServerWithAuth, ProtocolTypeI, SMPServerWithAuth, XFTPServerWithAuth)
|
import Simplex.Messaging.Protocol (ProtoServerWithAuth, ProtocolTypeI, SMPServerWithAuth, XFTPServerWithAuth)
|
||||||
|
@ -153,11 +153,17 @@ coreChatOptsP appDir defaultDbName = do
|
||||||
<> metavar "SMP_PROXY_FALLBACK_MODE"
|
<> metavar "SMP_PROXY_FALLBACK_MODE"
|
||||||
<> help "Allow downgrade and connect directly: no, [when IP address is] protected (default), yes"
|
<> help "Allow downgrade and connect directly: no, [when IP address is] protected (default), yes"
|
||||||
)
|
)
|
||||||
smpWebPort <-
|
smpWebPortServers <-
|
||||||
switch
|
flag' SWPAll
|
||||||
( long "smp-web-port"
|
( long "smp-web-port"
|
||||||
<> help "Use port 443 with SMP servers when not specified"
|
<> help "Use port 443 with SMP servers when not specified"
|
||||||
)
|
)
|
||||||
|
<|> option
|
||||||
|
strParse
|
||||||
|
( long "smp-web-port-servers"
|
||||||
|
<> help "Use port 443 with SMP servers when not specified: all, preset (default), off"
|
||||||
|
<> value SWPPreset
|
||||||
|
)
|
||||||
t <-
|
t <-
|
||||||
option
|
option
|
||||||
auto
|
auto
|
||||||
|
@ -243,7 +249,7 @@ coreChatOptsP appDir defaultDbName = do
|
||||||
requiredHostMode,
|
requiredHostMode,
|
||||||
smpProxyMode_,
|
smpProxyMode_,
|
||||||
smpProxyFallback_,
|
smpProxyFallback_,
|
||||||
smpWebPort,
|
smpWebPortServers,
|
||||||
tcpTimeout_ = Just $ useTcpTimeout socksProxy t,
|
tcpTimeout_ = Just $ useTcpTimeout socksProxy t,
|
||||||
logTLSErrors
|
logTLSErrors
|
||||||
},
|
},
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue