mirror of
https://github.com/vitorpamplona/amethyst.git
synced 2025-10-04 20:32:30 +02:00
Correctly manages airplane mode changes: reconnects Tor and Relays
This commit is contained in:
@@ -75,9 +75,10 @@ class Amethyst : Application() {
|
|||||||
|
|
||||||
// App services that should be run as soon as there are subscribers to their flows
|
// App services that should be run as soon as there are subscribers to their flows
|
||||||
val locationManager = LocationState(this, applicationIOScope)
|
val locationManager = LocationState(this, applicationIOScope)
|
||||||
val torManager = TorManager(this, applicationIOScope)
|
|
||||||
val connManager = ConnectivityManager(this, applicationIOScope)
|
val connManager = ConnectivityManager(this, applicationIOScope)
|
||||||
|
|
||||||
|
val torManager = TorManager(this, applicationIOScope)
|
||||||
|
|
||||||
// Service that will run at all times to receive events from Pokey
|
// Service that will run at all times to receive events from Pokey
|
||||||
val pokeyReceiver = PokeyReceiver()
|
val pokeyReceiver = PokeyReceiver()
|
||||||
|
|
||||||
@@ -109,7 +110,7 @@ class Amethyst : Application() {
|
|||||||
val client: NostrClient = NostrClient(websocketBuilder, applicationIOScope)
|
val client: NostrClient = NostrClient(websocketBuilder, applicationIOScope)
|
||||||
|
|
||||||
// Watches for changes on Tor and Relay List Settings
|
// Watches for changes on Tor and Relay List Settings
|
||||||
val relayProxyClientConnector = RelayProxyClientConnector(torProxySettingsAnchor, okHttpClients, connManager, client, applicationIOScope)
|
val relayProxyClientConnector = RelayProxyClientConnector(torProxySettingsAnchor, okHttpClients, connManager, client, torManager, applicationIOScope)
|
||||||
|
|
||||||
// Verifies and inserts in the cache from all relays, all subscriptions
|
// Verifies and inserts in the cache from all relays, all subscriptions
|
||||||
val cacheClientConnector = CacheClientConnector(client, cache)
|
val cacheClientConnector = CacheClientConnector(client, cache)
|
||||||
|
@@ -63,6 +63,12 @@ class ConnectivityFlow(
|
|||||||
Log.d("ConnectivityFlow", "onCapabilitiesChanged ${network.networkHandle} $isMobile")
|
Log.d("ConnectivityFlow", "onCapabilitiesChanged ${network.networkHandle} $isMobile")
|
||||||
trySend(ConnectivityStatus.Active(network.networkHandle, isMobile))
|
trySend(ConnectivityStatus.Active(network.networkHandle, isMobile))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override fun onLost(network: Network) {
|
||||||
|
super.onLost(network)
|
||||||
|
Log.d("ConnectivityFlow", "onLost ${network.networkHandle} ")
|
||||||
|
trySend(ConnectivityStatus.Off)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
connectivityManager.registerDefaultNetworkCallback(networkCallback)
|
connectivityManager.registerDefaultNetworkCallback(networkCallback)
|
||||||
|
@@ -21,14 +21,20 @@
|
|||||||
package com.vitorpamplona.amethyst.service.relayClient
|
package com.vitorpamplona.amethyst.service.relayClient
|
||||||
|
|
||||||
import android.util.Log
|
import android.util.Log
|
||||||
|
import com.vitorpamplona.amethyst.model.torState.TorRelayEvaluation
|
||||||
import com.vitorpamplona.amethyst.service.connectivity.ConnectivityManager
|
import com.vitorpamplona.amethyst.service.connectivity.ConnectivityManager
|
||||||
|
import com.vitorpamplona.amethyst.service.connectivity.ConnectivityStatus
|
||||||
import com.vitorpamplona.amethyst.service.okhttp.DualHttpClientManager
|
import com.vitorpamplona.amethyst.service.okhttp.DualHttpClientManager
|
||||||
import com.vitorpamplona.amethyst.service.okhttp.ProxySettingsAnchor
|
import com.vitorpamplona.amethyst.service.okhttp.ProxySettingsAnchor
|
||||||
|
import com.vitorpamplona.amethyst.ui.tor.TorManager
|
||||||
|
import com.vitorpamplona.amethyst.ui.tor.TorServiceStatus
|
||||||
import com.vitorpamplona.quartz.nip01Core.relay.client.NostrClient
|
import com.vitorpamplona.quartz.nip01Core.relay.client.NostrClient
|
||||||
import kotlinx.coroutines.CoroutineScope
|
import kotlinx.coroutines.CoroutineScope
|
||||||
import kotlinx.coroutines.Dispatchers
|
import kotlinx.coroutines.Dispatchers
|
||||||
import kotlinx.coroutines.FlowPreview
|
import kotlinx.coroutines.FlowPreview
|
||||||
|
import kotlinx.coroutines.NonCancellable.isActive
|
||||||
import kotlinx.coroutines.flow.SharingStarted
|
import kotlinx.coroutines.flow.SharingStarted
|
||||||
|
import kotlinx.coroutines.flow.StateFlow
|
||||||
import kotlinx.coroutines.flow.combine
|
import kotlinx.coroutines.flow.combine
|
||||||
import kotlinx.coroutines.flow.debounce
|
import kotlinx.coroutines.flow.debounce
|
||||||
import kotlinx.coroutines.flow.flowOn
|
import kotlinx.coroutines.flow.flowOn
|
||||||
@@ -36,14 +42,24 @@ import kotlinx.coroutines.flow.onCompletion
|
|||||||
import kotlinx.coroutines.flow.onEach
|
import kotlinx.coroutines.flow.onEach
|
||||||
import kotlinx.coroutines.flow.onStart
|
import kotlinx.coroutines.flow.onStart
|
||||||
import kotlinx.coroutines.flow.stateIn
|
import kotlinx.coroutines.flow.stateIn
|
||||||
|
import net.freehaven.tor.control.TorControlCommands
|
||||||
|
import okhttp3.OkHttpClient
|
||||||
|
|
||||||
class RelayProxyClientConnector(
|
class RelayProxyClientConnector(
|
||||||
val torProxySettingsAnchor: ProxySettingsAnchor,
|
val torProxySettingsAnchor: ProxySettingsAnchor,
|
||||||
val okHttpClients: DualHttpClientManager,
|
val okHttpClients: DualHttpClientManager,
|
||||||
val connManager: ConnectivityManager,
|
val connManager: ConnectivityManager,
|
||||||
val client: NostrClient,
|
val client: NostrClient,
|
||||||
|
val torManager: TorManager,
|
||||||
val scope: CoroutineScope,
|
val scope: CoroutineScope,
|
||||||
) {
|
) {
|
||||||
|
data class RelayServiceInfra(
|
||||||
|
val torSettings: StateFlow<TorRelayEvaluation>,
|
||||||
|
val torConnection: OkHttpClient,
|
||||||
|
val clearConnection: OkHttpClient,
|
||||||
|
val connectivity: ConnectivityStatus,
|
||||||
|
)
|
||||||
|
|
||||||
@OptIn(FlowPreview::class)
|
@OptIn(FlowPreview::class)
|
||||||
val relayServices =
|
val relayServices =
|
||||||
combine(
|
combine(
|
||||||
@@ -52,11 +68,35 @@ class RelayProxyClientConnector(
|
|||||||
okHttpClients.defaultHttpClientWithoutProxy,
|
okHttpClients.defaultHttpClientWithoutProxy,
|
||||||
connManager.status,
|
connManager.status,
|
||||||
) { torSettings, torConnection, clearConnection, connectivity ->
|
) { torSettings, torConnection, clearConnection, connectivity ->
|
||||||
torSettings.hashCode() + torConnection.hashCode() + clearConnection.hashCode() + connectivity.hashCode()
|
RelayServiceInfra(torSettings, torConnection, clearConnection, connectivity)
|
||||||
}.debounce(100)
|
}.debounce(100)
|
||||||
.onEach {
|
.onEach {
|
||||||
Log.d("ManageRelayServices", "Relay Services have changed")
|
if (it.connectivity is ConnectivityStatus.Off) {
|
||||||
|
Log.d("ManageRelayServices", "Pausing Relay Services ${it.connectivity}")
|
||||||
|
if (client.isActive()) {
|
||||||
|
client.disconnect()
|
||||||
|
}
|
||||||
|
val torStatus = torManager.status.value
|
||||||
|
if (torStatus is TorServiceStatus.Active) {
|
||||||
|
torStatus.torControlConnection.signal(TorControlCommands.SIGNAL_DORMANT)
|
||||||
|
Log.d("ManageRelayServices", "Pausing Tor Activity")
|
||||||
|
}
|
||||||
|
} else if (it.connectivity is ConnectivityStatus.Active && !client.isActive()) {
|
||||||
|
Log.d("ManageRelayServices", "Resuming Relay Services")
|
||||||
|
|
||||||
|
val torStatus = torManager.status.value
|
||||||
|
if (torStatus is TorServiceStatus.Active) {
|
||||||
|
torStatus.torControlConnection.signal(TorControlCommands.SIGNAL_ACTIVE)
|
||||||
|
torStatus.torControlConnection.signal(TorControlCommands.SIGNAL_NEWNYM)
|
||||||
|
Log.d("ManageRelayServices", "Resuming Tor Activity with new nym")
|
||||||
|
}
|
||||||
|
|
||||||
|
// only calls this if the client is not active. Otherwise goes to the else below
|
||||||
|
client.connect()
|
||||||
|
} else {
|
||||||
|
Log.d("ManageRelayServices", "Relay Services have changed, reconnecting relays that need to")
|
||||||
client.reconnect(true)
|
client.reconnect(true)
|
||||||
|
}
|
||||||
}.onStart {
|
}.onStart {
|
||||||
Log.d("ManageRelayServices", "Resuming Relay Services")
|
Log.d("ManageRelayServices", "Resuming Relay Services")
|
||||||
client.connect()
|
client.connect()
|
||||||
|
@@ -138,7 +138,6 @@ fun ObserveImageLoadingTor(accountViewModel: AccountViewModel) {
|
|||||||
fun ManageRelayServices(accountViewModel: AccountViewModel) {
|
fun ManageRelayServices(accountViewModel: AccountViewModel) {
|
||||||
val relayServices by Amethyst.instance.relayProxyClientConnector.relayServices
|
val relayServices by Amethyst.instance.relayProxyClientConnector.relayServices
|
||||||
.collectAsStateWithLifecycle()
|
.collectAsStateWithLifecycle()
|
||||||
Log.d("ManageRelayServices", "Relay Services changed $relayServices")
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
|
@@ -62,7 +62,7 @@ class TorService(
|
|||||||
delay(100)
|
delay(100)
|
||||||
}
|
}
|
||||||
|
|
||||||
trySend(TorServiceStatus.Active(torService.socksPort))
|
trySend(TorServiceStatus.Active(torService.socksPort, torService.torControlConnection))
|
||||||
Log.d("TorService", "Tor Service Connected ${torService.socksPort}")
|
Log.d("TorService", "Tor Service Connected ${torService.socksPort}")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -20,9 +20,12 @@
|
|||||||
*/
|
*/
|
||||||
package com.vitorpamplona.amethyst.ui.tor
|
package com.vitorpamplona.amethyst.ui.tor
|
||||||
|
|
||||||
|
import net.freehaven.tor.control.TorControlConnection
|
||||||
|
|
||||||
sealed class TorServiceStatus {
|
sealed class TorServiceStatus {
|
||||||
data class Active(
|
data class Active(
|
||||||
val port: Int,
|
val port: Int,
|
||||||
|
val torControlConnection: TorControlConnection,
|
||||||
) : TorServiceStatus()
|
) : TorServiceStatus()
|
||||||
|
|
||||||
object Off : TorServiceStatus()
|
object Off : TorServiceStatus()
|
||||||
|
@@ -133,6 +133,8 @@ class NostrClient(
|
|||||||
relayPool.disconnect()
|
relayPool.disconnect()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun isActive() = isActive
|
||||||
|
|
||||||
@Synchronized
|
@Synchronized
|
||||||
fun reconnect(onlyIfChanged: Boolean = false) {
|
fun reconnect(onlyIfChanged: Boolean = false) {
|
||||||
if (onlyIfChanged) {
|
if (onlyIfChanged) {
|
||||||
|
@@ -75,6 +75,13 @@ class RelayPool(
|
|||||||
|
|
||||||
fun reconnectIfNeedsToORIfItIsTime() {
|
fun reconnectIfNeedsToORIfItIsTime() {
|
||||||
if (lastReconnectCall < TimeUtils.oneMinuteAgo()) {
|
if (lastReconnectCall < TimeUtils.oneMinuteAgo()) {
|
||||||
|
reconnectIfNeedsTo()
|
||||||
|
|
||||||
|
lastReconnectCall = TimeUtils.now()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun reconnectIfNeedsTo() {
|
||||||
relays.forEach { url, relay ->
|
relays.forEach { url, relay ->
|
||||||
if (relay.isConnected()) {
|
if (relay.isConnected()) {
|
||||||
if (relay.needsToReconnect()) {
|
if (relay.needsToReconnect()) {
|
||||||
@@ -87,9 +94,6 @@ class RelayPool(
|
|||||||
relay.connectAndSyncFiltersIfDisconnected()
|
relay.connectAndSyncFiltersIfDisconnected()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
lastReconnectCall = TimeUtils.now()
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fun connect() =
|
fun connect() =
|
||||||
|
Reference in New Issue
Block a user