diff --git a/amethyst/src/main/java/com/vitorpamplona/amethyst/ServiceManager.kt b/amethyst/src/main/java/com/vitorpamplona/amethyst/ServiceManager.kt index 6dbdc7564..7e2ae9bd2 100644 --- a/amethyst/src/main/java/com/vitorpamplona/amethyst/ServiceManager.kt +++ b/amethyst/src/main/java/com/vitorpamplona/amethyst/ServiceManager.kt @@ -121,7 +121,7 @@ class ServiceManager( HttpClientManager.setProxyNotReady() } } - else -> HttpClientManager.setDefaultProxy(null) + else -> HttpClientManager.setProxyNotReady() } OtsResolver.ots = @@ -136,7 +136,7 @@ class ServiceManager( OkHttpCalendarBuilder { false }, ) - HttpClientManager.setDefaultProxy(null) + HttpClientManager.setProxyNotReady() } // Convert this into a flow diff --git a/amethyst/src/main/java/com/vitorpamplona/amethyst/service/notifications/RegisterAccounts.kt b/amethyst/src/main/java/com/vitorpamplona/amethyst/service/notifications/RegisterAccounts.kt index 7b684007b..7c145f359 100644 --- a/amethyst/src/main/java/com/vitorpamplona/amethyst/service/notifications/RegisterAccounts.kt +++ b/amethyst/src/main/java/com/vitorpamplona/amethyst/service/notifications/RegisterAccounts.kt @@ -29,6 +29,7 @@ import com.vitorpamplona.amethyst.launchAndWaitAll import com.vitorpamplona.amethyst.model.AccountSettings import com.vitorpamplona.amethyst.service.okhttp.HttpClientManager import com.vitorpamplona.amethyst.tryAndWait +import com.vitorpamplona.amethyst.ui.tor.TorManager import com.vitorpamplona.quartz.nip42RelayAuth.RelayAuthEvent import com.vitorpamplona.quartz.nip55AndroidSigner.NostrSignerExternal import kotlinx.coroutines.CancellationException @@ -151,8 +152,8 @@ class RegisterAccounts( .post(body) .build() - // Always try via Tor for Amethyst. - val client = HttpClientManager.getHttpClient(true) + // Always try via Tor if active. + val client = HttpClientManager.getHttpClient(TorManager.isSocksReady()) val isSucess = client.newCall(request).execute().use { it.isSuccessful } Log.i(tag, "Server registration $isSucess") diff --git a/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/AccountScreen.kt b/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/AccountScreen.kt index a69208190..083580a78 100644 --- a/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/AccountScreen.kt +++ b/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/AccountScreen.kt @@ -62,6 +62,7 @@ import com.vitorpamplona.amethyst.ui.screen.loggedIn.AccountViewModel import com.vitorpamplona.amethyst.ui.screen.loggedOff.LoginOrSignupScreen import com.vitorpamplona.amethyst.ui.stringRes import com.vitorpamplona.amethyst.ui.tor.TorManager +import com.vitorpamplona.amethyst.ui.tor.TorStatus import com.vitorpamplona.amethyst.ui.tor.TorType import com.vitorpamplona.quartz.nip55AndroidSigner.NostrSignerExternal import kotlinx.coroutines.CancellationException @@ -160,6 +161,7 @@ fun ManageTorInstance(accountViewModel: AccountViewModel) { val torSettings by accountViewModel.account.settings.torSettings.torType .collectAsStateWithLifecycle() if (torSettings == TorType.INTERNAL) { + WatchConnection(accountViewModel) ManageTorInstanceInner(accountViewModel) } } @@ -204,6 +206,17 @@ fun ManageTorInstanceInner(accountViewModel: AccountViewModel) { } } +@Composable +fun WatchConnection(accountViewModel: AccountViewModel) { + val status by TorManager.status.collectAsStateWithLifecycle() + + LaunchedEffect(key1 = status, key2 = accountViewModel) { + if (status is TorStatus.Active) { + accountViewModel.changeProxyPort((status as TorStatus.Active).port) + } + } +} + @Composable private fun ListenToExternalSignerIfNeeded(accountViewModel: AccountViewModel) { if (accountViewModel.account.signer is NostrSignerExternal) { diff --git a/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/AccountViewModel.kt b/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/AccountViewModel.kt index 54e8e71b8..4f44fdca8 100644 --- a/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/AccountViewModel.kt +++ b/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/AccountViewModel.kt @@ -1265,6 +1265,12 @@ class AccountViewModel( } } + fun changeProxyPort(port: Int) { + viewModelScope.launch(Dispatchers.IO) { + Amethyst.instance.serviceManager.forceRestart() + } + } + class Factory( val accountSettings: AccountSettings, val settings: SettingsState, diff --git a/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/tor/TorManager.kt b/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/tor/TorManager.kt index a25fc1340..6e293478e 100644 --- a/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/tor/TorManager.kt +++ b/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/tor/TorManager.kt @@ -27,20 +27,33 @@ import android.content.ServiceConnection import android.os.IBinder import android.util.Log import androidx.appcompat.app.AppCompatActivity.BIND_AUTO_CREATE -import com.vitorpamplona.amethyst.service.okhttp.HttpClientManager +import kotlinx.coroutines.flow.MutableStateFlow import org.torproject.jni.TorService import org.torproject.jni.TorService.LocalBinder import java.util.concurrent.atomic.AtomicBoolean +sealed class TorStatus { + data class Active( + val port: Int, + ) : TorStatus() + + object Off : TorStatus() + + object Connecting : TorStatus() +} + object TorManager { var runningIntent: Intent? = null var torService: TorService? = null + val status = MutableStateFlow(TorStatus.Off) + // To make sure we don't start two services. var isConnectingMutex = AtomicBoolean(false) fun startTorIfNotAlreadyOn(ctx: Context) { if (runningIntent == null && isConnectingMutex.compareAndSet(false, true)) { + status.tryEmit(TorStatus.Connecting) try { startTor(ctx) } finally { @@ -54,6 +67,7 @@ object TorManager { runningIntent?.let { ctx.stopService(runningIntent) } + status.tryEmit(TorStatus.Off) runningIntent = null torService = null } @@ -80,14 +94,14 @@ object TorManager { } } - HttpClientManager.setDefaultProxyOnPort(socksPort()) - + status.tryEmit(TorStatus.Active(socksPort())) Log.d("TorManager", "Tor Service Connected ${socksPort()}") } override fun onServiceDisconnected(name: ComponentName) { runningIntent = null torService = null + status.tryEmit(TorStatus.Off) Log.d("TorManager", "Tor Service Disconected") } }, @@ -95,10 +109,7 @@ object TorManager { ) } - fun isSocksReady() = - torService?.let { - it.socksPort > 0 - } ?: false + fun isSocksReady() = torService?.let { it.socksPort > 0 } == true fun socksPort(): Int = torService?.socksPort ?: 9050 diff --git a/quartz/src/main/java/com/vitorpamplona/quartz/nip01Core/relay/SimpleClientRelay.kt b/quartz/src/main/java/com/vitorpamplona/quartz/nip01Core/relay/SimpleClientRelay.kt index 9a373862a..02978d479 100644 --- a/quartz/src/main/java/com/vitorpamplona/quartz/nip01Core/relay/SimpleClientRelay.kt +++ b/quartz/src/main/java/com/vitorpamplona/quartz/nip01Core/relay/SimpleClientRelay.kt @@ -35,6 +35,7 @@ import com.vitorpamplona.quartz.nip01Core.relay.commands.toRelay.AuthCmd import com.vitorpamplona.quartz.nip01Core.relay.commands.toRelay.CloseCmd import com.vitorpamplona.quartz.nip01Core.relay.commands.toRelay.CountCmd import com.vitorpamplona.quartz.nip01Core.relay.commands.toRelay.EventCmd +import com.vitorpamplona.quartz.nip01Core.relay.commands.toRelay.ReqCmd import com.vitorpamplona.quartz.nip01Core.relay.filters.Filter import com.vitorpamplona.quartz.nip01Core.relay.sockets.WebSocket import com.vitorpamplona.quartz.nip01Core.relay.sockets.WebSocketListener @@ -312,10 +313,7 @@ class SimpleClientRelay( if (isConnectionStarted()) { if (isReady) { if (filters.isNotEmpty()) { - writeToSocket( - com.vitorpamplona.quartz.nip01Core.relay.commands.toRelay.ReqCmd - .toJson(requestId, filters), - ) + writeToSocket(ReqCmd.toJson(requestId, filters)) afterEOSEPerSubscription[requestId] = false } }