mirror of
https://github.com/vitorpamplona/amethyst.git
synced 2025-09-26 05:56:17 +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
|
||||
val locationManager = LocationState(this, applicationIOScope)
|
||||
val torManager = TorManager(this, applicationIOScope)
|
||||
val connManager = ConnectivityManager(this, applicationIOScope)
|
||||
|
||||
val torManager = TorManager(this, applicationIOScope)
|
||||
|
||||
// Service that will run at all times to receive events from Pokey
|
||||
val pokeyReceiver = PokeyReceiver()
|
||||
|
||||
@@ -109,7 +110,7 @@ class Amethyst : Application() {
|
||||
val client: NostrClient = NostrClient(websocketBuilder, applicationIOScope)
|
||||
|
||||
// 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
|
||||
val cacheClientConnector = CacheClientConnector(client, cache)
|
||||
|
@@ -63,6 +63,12 @@ class ConnectivityFlow(
|
||||
Log.d("ConnectivityFlow", "onCapabilitiesChanged ${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)
|
||||
|
@@ -21,14 +21,20 @@
|
||||
package com.vitorpamplona.amethyst.service.relayClient
|
||||
|
||||
import android.util.Log
|
||||
import com.vitorpamplona.amethyst.model.torState.TorRelayEvaluation
|
||||
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.ProxySettingsAnchor
|
||||
import com.vitorpamplona.amethyst.ui.tor.TorManager
|
||||
import com.vitorpamplona.amethyst.ui.tor.TorServiceStatus
|
||||
import com.vitorpamplona.quartz.nip01Core.relay.client.NostrClient
|
||||
import kotlinx.coroutines.CoroutineScope
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.FlowPreview
|
||||
import kotlinx.coroutines.NonCancellable.isActive
|
||||
import kotlinx.coroutines.flow.SharingStarted
|
||||
import kotlinx.coroutines.flow.StateFlow
|
||||
import kotlinx.coroutines.flow.combine
|
||||
import kotlinx.coroutines.flow.debounce
|
||||
import kotlinx.coroutines.flow.flowOn
|
||||
@@ -36,14 +42,24 @@ import kotlinx.coroutines.flow.onCompletion
|
||||
import kotlinx.coroutines.flow.onEach
|
||||
import kotlinx.coroutines.flow.onStart
|
||||
import kotlinx.coroutines.flow.stateIn
|
||||
import net.freehaven.tor.control.TorControlCommands
|
||||
import okhttp3.OkHttpClient
|
||||
|
||||
class RelayProxyClientConnector(
|
||||
val torProxySettingsAnchor: ProxySettingsAnchor,
|
||||
val okHttpClients: DualHttpClientManager,
|
||||
val connManager: ConnectivityManager,
|
||||
val client: NostrClient,
|
||||
val torManager: TorManager,
|
||||
val scope: CoroutineScope,
|
||||
) {
|
||||
data class RelayServiceInfra(
|
||||
val torSettings: StateFlow<TorRelayEvaluation>,
|
||||
val torConnection: OkHttpClient,
|
||||
val clearConnection: OkHttpClient,
|
||||
val connectivity: ConnectivityStatus,
|
||||
)
|
||||
|
||||
@OptIn(FlowPreview::class)
|
||||
val relayServices =
|
||||
combine(
|
||||
@@ -52,11 +68,35 @@ class RelayProxyClientConnector(
|
||||
okHttpClients.defaultHttpClientWithoutProxy,
|
||||
connManager.status,
|
||||
) { torSettings, torConnection, clearConnection, connectivity ->
|
||||
torSettings.hashCode() + torConnection.hashCode() + clearConnection.hashCode() + connectivity.hashCode()
|
||||
RelayServiceInfra(torSettings, torConnection, clearConnection, connectivity)
|
||||
}.debounce(100)
|
||||
.onEach {
|
||||
Log.d("ManageRelayServices", "Relay Services have changed")
|
||||
client.reconnect(true)
|
||||
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)
|
||||
}
|
||||
}.onStart {
|
||||
Log.d("ManageRelayServices", "Resuming Relay Services")
|
||||
client.connect()
|
||||
|
@@ -138,7 +138,6 @@ fun ObserveImageLoadingTor(accountViewModel: AccountViewModel) {
|
||||
fun ManageRelayServices(accountViewModel: AccountViewModel) {
|
||||
val relayServices by Amethyst.instance.relayProxyClientConnector.relayServices
|
||||
.collectAsStateWithLifecycle()
|
||||
Log.d("ManageRelayServices", "Relay Services changed $relayServices")
|
||||
}
|
||||
|
||||
@Composable
|
||||
|
@@ -62,7 +62,7 @@ class TorService(
|
||||
delay(100)
|
||||
}
|
||||
|
||||
trySend(TorServiceStatus.Active(torService.socksPort))
|
||||
trySend(TorServiceStatus.Active(torService.socksPort, torService.torControlConnection))
|
||||
Log.d("TorService", "Tor Service Connected ${torService.socksPort}")
|
||||
}
|
||||
}
|
||||
|
@@ -20,9 +20,12 @@
|
||||
*/
|
||||
package com.vitorpamplona.amethyst.ui.tor
|
||||
|
||||
import net.freehaven.tor.control.TorControlConnection
|
||||
|
||||
sealed class TorServiceStatus {
|
||||
data class Active(
|
||||
val port: Int,
|
||||
val torControlConnection: TorControlConnection,
|
||||
) : TorServiceStatus()
|
||||
|
||||
object Off : TorServiceStatus()
|
||||
|
@@ -133,6 +133,8 @@ class NostrClient(
|
||||
relayPool.disconnect()
|
||||
}
|
||||
|
||||
fun isActive() = isActive
|
||||
|
||||
@Synchronized
|
||||
fun reconnect(onlyIfChanged: Boolean = false) {
|
||||
if (onlyIfChanged) {
|
||||
|
@@ -75,23 +75,27 @@ class RelayPool(
|
||||
|
||||
fun reconnectIfNeedsToORIfItIsTime() {
|
||||
if (lastReconnectCall < TimeUtils.oneMinuteAgo()) {
|
||||
relays.forEach { url, relay ->
|
||||
if (relay.isConnected()) {
|
||||
if (relay.needsToReconnect()) {
|
||||
// network has changed, force reconnect
|
||||
relay.disconnect()
|
||||
relay.connect()
|
||||
}
|
||||
} else {
|
||||
// relay is not connected. Connect if it is time
|
||||
relay.connectAndSyncFiltersIfDisconnected()
|
||||
}
|
||||
}
|
||||
reconnectIfNeedsTo()
|
||||
|
||||
lastReconnectCall = TimeUtils.now()
|
||||
}
|
||||
}
|
||||
|
||||
fun reconnectIfNeedsTo() {
|
||||
relays.forEach { url, relay ->
|
||||
if (relay.isConnected()) {
|
||||
if (relay.needsToReconnect()) {
|
||||
// network has changed, force reconnect
|
||||
relay.disconnect()
|
||||
relay.connect()
|
||||
}
|
||||
} else {
|
||||
// relay is not connected. Connect if it is time
|
||||
relay.connectAndSyncFiltersIfDisconnected()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun connect() =
|
||||
relays.forEach { url, relay ->
|
||||
relay.connect()
|
||||
|
Reference in New Issue
Block a user