DataStore.kt 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331
  1. /******************************************************************************
  2. * *
  3. * Copyright (C) 2021 by nekohasekai <[email protected]> *
  4. * Copyright (C) 2021 by Max Lv <[email protected]> *
  5. * Copyright (C) 2021 by Mygod Studio <[email protected]> *
  6. * *
  7. * This program is free software: you can redistribute it and/or modify *
  8. * it under the terms of the GNU General Public License as published by *
  9. * the Free Software Foundation, either version 3 of the License, or *
  10. * (at your option) any later version. *
  11. * *
  12. * This program is distributed in the hope that it will be useful, *
  13. * but WITHOUT ANY WARRANTY; without even the implied warranty of *
  14. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
  15. * GNU General Public License for more details. *
  16. * *
  17. * You should have received a copy of the GNU General Public License *
  18. * along with this program. If not, see <http://www.gnu.org/licenses/>. *
  19. * *
  20. ******************************************************************************/
  21. package io.nekohasekai.sagernet.database
  22. import android.os.Binder
  23. import android.os.Build
  24. import androidx.preference.PreferenceDataStore
  25. import io.nekohasekai.sagernet.*
  26. import io.nekohasekai.sagernet.bg.VpnService
  27. import io.nekohasekai.sagernet.database.preference.InMemoryDatabase
  28. import io.nekohasekai.sagernet.database.preference.OnPreferenceDataStoreChangeListener
  29. import io.nekohasekai.sagernet.database.preference.PublicDatabase
  30. import io.nekohasekai.sagernet.database.preference.RoomPreferenceDataStore
  31. import io.nekohasekai.sagernet.ktx.*
  32. import io.nekohasekai.sagernet.utils.DirectBoot
  33. object DataStore : OnPreferenceDataStoreChangeListener {
  34. val configurationStore = RoomPreferenceDataStore(PublicDatabase.kvPairDao)
  35. val profileCacheStore = RoomPreferenceDataStore(InMemoryDatabase.kvPairDao)
  36. fun init() {
  37. /*if (Build.VERSION.SDK_INT >= 24) {
  38. SagerNet.deviceStorage.moveDatabaseFrom(SagerNet.application, Key.DB_PUBLIC)
  39. }
  40. if (Build.VERSION.SDK_INT >= 24 && directBootAware && SagerNet.user.isUserUnlocked) {
  41. DirectBoot.flushTrafficStats()
  42. }*/
  43. }
  44. var selectedProxy by configurationStore.long(Key.PROFILE_ID)
  45. var currentProfile by configurationStore.long(Key.PROFILE_CURRENT)
  46. var startedProfile by configurationStore.long(Key.PROFILE_STARTED)
  47. var selectedGroup by configurationStore.long(Key.PROFILE_GROUP) {
  48. SagerNet.currentProfile?.groupId ?: 0L
  49. }
  50. fun currentGroupId(): Long {
  51. val currentSelected = selectedGroup
  52. if (currentSelected > 0L) return currentSelected
  53. val groups = SagerDatabase.groupDao.allGroups()
  54. if (groups.isNotEmpty()) {
  55. val groupId = groups[0].id
  56. selectedGroup = groupId
  57. return groupId
  58. }
  59. val groupId = SagerDatabase.groupDao.createGroup(ProxyGroup(ungrouped = true))
  60. selectedGroup = groupId
  61. return groupId
  62. }
  63. fun currentGroup(): ProxyGroup {
  64. var group: ProxyGroup? = null
  65. val currentSelected = selectedGroup
  66. if (currentSelected > 0L) {
  67. group = SagerDatabase.groupDao.getById(currentSelected)
  68. }
  69. if (group != null) return group
  70. val groups = SagerDatabase.groupDao.allGroups()
  71. if (groups.isEmpty()) {
  72. group = ProxyGroup(ungrouped = true).apply {
  73. id = SagerDatabase.groupDao.createGroup(this)
  74. }
  75. } else {
  76. group = groups[0]
  77. }
  78. selectedGroup = group.id
  79. return group
  80. }
  81. fun selectedGroupForImport(): Long {
  82. val current = currentGroup()
  83. if (current.type == GroupType.BASIC) return current.id
  84. val groups = SagerDatabase.groupDao.allGroups()
  85. return groups.find { it.type == GroupType.BASIC }!!.id
  86. }
  87. var appTheme by configurationStore.int(Key.APP_THEME)
  88. var nightTheme by configurationStore.stringToInt(Key.NIGHT_THEME)
  89. var serviceMode by configurationStore.string(Key.SERVICE_MODE) { Key.MODE_VPN }
  90. var domainStrategy by configurationStore.string(Key.DOMAIN_STRATEGY) { "AsIs" }
  91. var trafficSniffing by configurationStore.boolean(Key.TRAFFIC_SNIFFING) { true }
  92. var destinationOverride by configurationStore.boolean(Key.DESTINATION_OVERRIDE)
  93. var resolveDestination by configurationStore.boolean(Key.RESOLVE_DESTINATION)
  94. var tcpKeepAliveInterval by configurationStore.stringToInt(Key.TCP_KEEP_ALIVE_INTERVAL) { 15 }
  95. var bypassLan by configurationStore.boolean(Key.BYPASS_LAN)
  96. var bypassLanInCoreOnly by configurationStore.boolean(Key.BYPASS_LAN_IN_CORE_ONLY)
  97. var allowAccess by configurationStore.boolean(Key.ALLOW_ACCESS)
  98. var speedInterval by configurationStore.stringToInt(Key.SPEED_INTERVAL)
  99. // https://github.com/SagerNet/SagerNet/issues/180
  100. var remoteDns by configurationStore.stringNotBlack(Key.REMOTE_DNS) { "tls://dns.google" }
  101. var directDns by configurationStore.stringNotBlack(Key.DIRECT_DNS) { "tls+local://dot.pub" }
  102. var useLocalDnsAsDirectDns by configurationStore.boolean(Key.USE_LOCAL_DNS_AS_DIRECT_DNS) { true }
  103. var hosts by configurationStore.string(Key.DNS_HOSTS)
  104. var enableDnsRouting by configurationStore.boolean(Key.ENABLE_DNS_ROUTING) { true }
  105. var disableDnsExpire by configurationStore.boolean(Key.DISABLE_DNS_EXPIRE)
  106. var securityAdvisory by configurationStore.boolean(Key.SECURITY_ADVISORY) { true }
  107. var rulesProvider by configurationStore.stringToInt(Key.RULES_PROVIDER)
  108. var enableLog by configurationStore.boolean(Key.ENABLE_LOG) { BuildConfig.DEBUG }
  109. var enablePcap by configurationStore.boolean(Key.ENABLE_PCAP)
  110. var acquireWakeLock by configurationStore.boolean(Key.ACQUIRE_WAKE_LOCK)
  111. // hopefully hashCode = mHandle doesn't change, currently this is true from KitKat to Nougat
  112. private val userIndex by lazy { Binder.getCallingUserHandle().hashCode() }
  113. var socksPort: Int
  114. get() = getLocalPort(Key.SOCKS_PORT, 2080)
  115. set(value) = saveLocalPort(Key.SOCKS_PORT, value)
  116. var localDNSPort: Int
  117. get() = getLocalPort(Key.LOCAL_DNS_PORT, 6450)
  118. set(value) {
  119. saveLocalPort(Key.LOCAL_DNS_PORT, value)
  120. }
  121. var httpPort: Int
  122. get() = getLocalPort(Key.HTTP_PORT, 9080)
  123. set(value) = saveLocalPort(Key.HTTP_PORT, value)
  124. var transproxyPort: Int
  125. get() = getLocalPort(Key.TRANSPROXY_PORT, 9200)
  126. set(value) = saveLocalPort(Key.TRANSPROXY_PORT, value)
  127. fun initGlobal() {
  128. if (configurationStore.getString(Key.SOCKS_PORT) == null) {
  129. socksPort = socksPort
  130. }
  131. if (configurationStore.getString(Key.LOCAL_DNS_PORT) == null) {
  132. localDNSPort = localDNSPort
  133. }
  134. if (configurationStore.getString(Key.HTTP_PORT) == null) {
  135. httpPort = httpPort
  136. }
  137. if (configurationStore.getString(Key.TRANSPROXY_PORT) == null) {
  138. transproxyPort = transproxyPort
  139. }
  140. if (configurationStore.getString(Key.DNS_HOSTS) == null) {
  141. hosts = hosts
  142. }
  143. if (configurationStore.getString(Key.REMOTE_DNS).isNullOrBlank()) {
  144. remoteDns = remoteDns
  145. }
  146. if (configurationStore.getString(Key.DIRECT_DNS).isNullOrBlank()) {
  147. directDns = directDns
  148. }
  149. if (configurationStore.getString(Key.MTU).isNullOrBlank()) {
  150. mtu = mtu
  151. }
  152. }
  153. private fun getLocalPort(key: String, default: Int): Int {
  154. return parsePort(configurationStore.getString(key), default + userIndex)
  155. }
  156. private fun saveLocalPort(key: String, value: Int) {
  157. configurationStore.putString(key, "$value")
  158. }
  159. var ipv6Mode by configurationStore.stringToInt(Key.IPV6_MODE) { IPv6Mode.ENABLE }
  160. var meteredNetwork by configurationStore.boolean(Key.METERED_NETWORK)
  161. var proxyApps by configurationStore.boolean(Key.PROXY_APPS)
  162. var bypass by configurationStore.boolean(Key.BYPASS_MODE) { true }
  163. var individual by configurationStore.string(Key.INDIVIDUAL)
  164. var enableMux by configurationStore.boolean(Key.ENABLE_MUX)
  165. var enableMuxForAll by configurationStore.boolean(Key.ENABLE_MUX_FOR_ALL)
  166. var muxConcurrency by configurationStore.stringToInt(Key.MUX_CONCURRENCY) { 8 }
  167. var showDirectSpeed by configurationStore.boolean(Key.SHOW_DIRECT_SPEED)
  168. val persistAcrossReboot by configurationStore.boolean(Key.PERSIST_ACROSS_REBOOT) { true }
  169. val canToggleLocked: Boolean get() = false//configurationStore.getBoolean(Key.DIRECT_BOOT_AWARE) == true
  170. val directBootAware: Boolean get() = SagerNet.directBootSupported && canToggleLocked
  171. var requireHttp by configurationStore.boolean(Key.REQUIRE_HTTP) { false }
  172. var appendHttpProxy by configurationStore.boolean(Key.APPEND_HTTP_PROXY) { true }
  173. var requireTransproxy by configurationStore.boolean(Key.REQUIRE_TRANSPROXY)
  174. var transproxyMode by configurationStore.stringToInt(Key.TRANSPROXY_MODE)
  175. var connectionTestURL by configurationStore.string(Key.CONNECTION_TEST_URL) { CONNECTION_TEST_URL }
  176. var alwaysShowAddress by configurationStore.boolean(Key.ALWAYS_SHOW_ADDRESS)
  177. var tunImplementation by configurationStore.stringToInt(Key.TUN_IMPLEMENTATION) { TunImplementation.SYSTEM }
  178. var useUpstreamInterfaceMTU by configurationStore.boolean(Key.USE_UPSTREAM_INTERFACE_MTU) { true }
  179. var mtu by configurationStore.stringToInt(Key.MTU) { VpnService.DEFAULT_MTU }
  180. var appTrafficStatistics by configurationStore.boolean(Key.APP_TRAFFIC_STATISTICS)
  181. var profileTrafficStatistics by configurationStore.boolean(Key.PROFILE_TRAFFIC_STATISTICS) { true }
  182. // protocol
  183. var providerTrojan by configurationStore.stringToInt(Key.PROVIDER_TROJAN)
  184. var providerRootCA by configurationStore.stringToInt(Key.PROVIDER_ROOT_CA)
  185. var providerInstaller by configurationStore.stringToInt(Key.PROVIDER_INSTALLER)
  186. // cache
  187. var dirty by profileCacheStore.boolean(Key.PROFILE_DIRTY)
  188. var editingId by profileCacheStore.long(Key.PROFILE_ID)
  189. var editingGroup by profileCacheStore.long(Key.PROFILE_GROUP)
  190. var profileName by profileCacheStore.string(Key.PROFILE_NAME)
  191. var serverAddress by profileCacheStore.string(Key.SERVER_ADDRESS)
  192. var serverPort by profileCacheStore.stringToInt(Key.SERVER_PORT)
  193. var serverUsername by profileCacheStore.string(Key.SERVER_USERNAME)
  194. var serverPassword by profileCacheStore.string(Key.SERVER_PASSWORD)
  195. var serverPassword1 by profileCacheStore.string(Key.SERVER_PASSWORD1)
  196. var serverMethod by profileCacheStore.string(Key.SERVER_METHOD)
  197. var serverPlugin by profileCacheStore.string(Key.SERVER_PLUGIN)
  198. var serverProtocol by profileCacheStore.string(Key.SERVER_PROTOCOL)
  199. var serverProtocolParam by profileCacheStore.string(Key.SERVER_PROTOCOL_PARAM)
  200. var serverObfs by profileCacheStore.string(Key.SERVER_OBFS)
  201. var serverObfsParam by profileCacheStore.string(Key.SERVER_OBFS_PARAM)
  202. var serverUserId by profileCacheStore.string(Key.SERVER_USER_ID)
  203. var serverSecurity by profileCacheStore.string(Key.SERVER_SECURITY)
  204. var serverNetwork by profileCacheStore.string(Key.SERVER_NETWORK)
  205. var serverHeader by profileCacheStore.string(Key.SERVER_HEADER)
  206. var serverHost by profileCacheStore.string(Key.SERVER_HOST)
  207. var serverPath by profileCacheStore.string(Key.SERVER_PATH)
  208. var serverSNI by profileCacheStore.string(Key.SERVER_SNI)
  209. var serverTLS by profileCacheStore.boolean(Key.SERVER_TLS)
  210. var serverEncryption by profileCacheStore.string(Key.SERVER_ENCRYPTION)
  211. var serverALPN by profileCacheStore.string(Key.SERVER_ALPN)
  212. var serverCertificates by profileCacheStore.string(Key.SERVER_CERTIFICATES)
  213. var serverPinnedCertificateChain by profileCacheStore.string(Key.SERVER_PINNED_CERTIFICATE_CHAIN)
  214. var serverFlow by profileCacheStore.string(Key.SERVER_FLOW)
  215. var serverQuicSecurity by profileCacheStore.string(Key.SERVER_QUIC_SECURITY)
  216. var serverWsMaxEarlyData by profileCacheStore.stringToInt(Key.SERVER_WS_MAX_EARLY_DATA)
  217. var serverWsBrowserForwarding by profileCacheStore.boolean(Key.SERVER_WS_BROWSER_FORWARDING)
  218. var serverEarlyDataHeaderName by profileCacheStore.string(Key.SERVER_EARLY_DATA_HEADER_NAME)
  219. var serverHeaders by profileCacheStore.string(Key.SERVER_HEADERS)
  220. var serverAllowInsecure by profileCacheStore.boolean(Key.SERVER_ALLOW_INSECURE)
  221. var serverPacketEncoding by profileCacheStore.stringToInt(Key.SERVER_PACKET_ENCODING)
  222. var serverVMessExperimentalAuthenticatedLength by profileCacheStore.boolean(Key.SERVER_VMESS_EXPERIMENTAL_AUTHENTICATED_LENGTH)
  223. var serverVMessExperimentalNoTerminationSignal by profileCacheStore.boolean(Key.SERVER_VMESS_EXPERIMENTAL_NO_TERMINATION_SIGNAL)
  224. var serverAuthType by profileCacheStore.stringToInt(Key.SERVER_AUTH_TYPE)
  225. var serverUploadSpeed by profileCacheStore.stringToInt(Key.SERVER_UPLOAD_SPEED)
  226. var serverDownloadSpeed by profileCacheStore.stringToInt(Key.SERVER_DOWNLOAD_SPEED)
  227. var serverStreamReceiveWindow by profileCacheStore.stringToIntIfExists(Key.SERVER_STREAM_RECEIVE_WINDOW)
  228. var serverConnectionReceiveWindow by profileCacheStore.stringToIntIfExists(Key.SERVER_CONNECTION_RECEIVE_WINDOW)
  229. var serverDisableMtuDiscovery by profileCacheStore.boolean(Key.SERVER_DISABLE_MTU_DISCOVERY)
  230. var serverProtocolVersion by profileCacheStore.stringToInt(Key.SERVER_PROTOCOL)
  231. var serverPrivateKey by profileCacheStore.string(Key.SERVER_PRIVATE_KEY)
  232. var serverLocalAddress by profileCacheStore.string(Key.SERVER_LOCAL_ADDRESS)
  233. var serverInsecureConcurrency by profileCacheStore.stringToInt(Key.SERVER_INSECURE_CONCURRENCY)
  234. var serverMTU by profileCacheStore.stringToInt(Key.SERVER_MTU)
  235. var serverReducedIvHeadEntropy by profileCacheStore.boolean(Key.SERVER_REDUCED_IV_HEAD_ENTROPY)
  236. var serverUoT by profileCacheStore.boolean(Key.SERVER_UDP_OVER_TCP)
  237. var serverWithoutBrookProtocol by profileCacheStore.boolean(Key.SERVER_WITHOUT_BROOK_PROTOCOL)
  238. var serverGrpcMode by profileCacheStore.string(Key.SERVER_GRPC_MODE)
  239. var serverEncryptedProtocolExtension by profileCacheStore.boolean(Key.SERVER_ENCRYPTED_PROTOCOL_EXTENSION)
  240. var balancerType by profileCacheStore.stringToInt(Key.BALANCER_TYPE)
  241. var balancerGroup by profileCacheStore.stringToLong(Key.BALANCER_GROUP)
  242. var balancerStrategy by profileCacheStore.string(Key.BALANCER_STRATEGY)
  243. var balancerProbeUrl by profileCacheStore.string(Key.PROBE_URL)
  244. var balancerProbeInterval by profileCacheStore.stringToInt(Key.PROBE_INTERVAL) { 300 }
  245. var routeName by profileCacheStore.string(Key.ROUTE_NAME)
  246. var routeDomain by profileCacheStore.string(Key.ROUTE_DOMAIN)
  247. var routeIP by profileCacheStore.string(Key.ROUTE_IP)
  248. var routePort by profileCacheStore.string(Key.ROUTE_PORT)
  249. var routeSourcePort by profileCacheStore.string(Key.ROUTE_SOURCE_PORT)
  250. var routeNetwork by profileCacheStore.string(Key.ROUTE_NETWORK)
  251. var routeSource by profileCacheStore.string(Key.ROUTE_SOURCE)
  252. var routeProtocol by profileCacheStore.string(Key.ROUTE_PROTOCOL)
  253. var routeAttrs by profileCacheStore.string(Key.ROUTE_ATTRS)
  254. var routeOutbound by profileCacheStore.stringToInt(Key.ROUTE_OUTBOUND)
  255. var routeOutboundRule by profileCacheStore.long(Key.ROUTE_OUTBOUND_RULE)
  256. var routeReverse by profileCacheStore.boolean(Key.ROUTE_REVERSE)
  257. var routeRedirect by profileCacheStore.string(Key.ROUTE_REDIRECT)
  258. var routePackages by profileCacheStore.string(Key.ROUTE_PACKAGES)
  259. var routeNetworkType by profileCacheStore.string(Key.ROUTE_NETWORK_TYPE)
  260. var routeSSID by profileCacheStore.string(Key.ROUTE_SSID)
  261. var serverConfig by profileCacheStore.string(Key.SERVER_CONFIG)
  262. var groupName by profileCacheStore.string(Key.GROUP_NAME)
  263. var groupType by profileCacheStore.stringToInt(Key.GROUP_TYPE)
  264. var groupOrder by profileCacheStore.stringToInt(Key.GROUP_ORDER)
  265. var subscriptionType by profileCacheStore.stringToInt(Key.SUBSCRIPTION_TYPE)
  266. var subscriptionLink by profileCacheStore.string(Key.SUBSCRIPTION_LINK)
  267. var subscriptionToken by profileCacheStore.string(Key.SUBSCRIPTION_TOKEN)
  268. var subscriptionForceResolve by profileCacheStore.boolean(Key.SUBSCRIPTION_FORCE_RESOLVE)
  269. var subscriptionDeduplication by profileCacheStore.boolean(Key.SUBSCRIPTION_DEDUPLICATION)
  270. var subscriptionUpdateWhenConnectedOnly by profileCacheStore.boolean(Key.SUBSCRIPTION_UPDATE_WHEN_CONNECTED_ONLY)
  271. var subscriptionUserAgent by profileCacheStore.string(Key.SUBSCRIPTION_USER_AGENT)
  272. var subscriptionAutoUpdate by profileCacheStore.boolean(Key.SUBSCRIPTION_AUTO_UPDATE)
  273. var subscriptionAutoUpdateDelay by profileCacheStore.stringToInt(Key.SUBSCRIPTION_AUTO_UPDATE_DELAY) { 360 }
  274. var taskerAction by profileCacheStore.stringToInt(Key.TASKER_ACTION)
  275. var taskerProfile by profileCacheStore.stringToInt(Key.TASKER_PROFILE)
  276. var taskerProfileId by profileCacheStore.long(Key.TASKER_PROFILE_ID) { -1L }
  277. var rulesFirstCreate by profileCacheStore.boolean("rulesFirstCreate")
  278. override fun onPreferenceDataStoreChanged(store: PreferenceDataStore, key: String) {
  279. when (key) {
  280. Key.PROFILE_ID -> if (directBootAware) DirectBoot.update()
  281. }
  282. }
  283. }