Merge pull request #2269 from vitorpamplona/claude/fix-relay-connectivity-pJ29t
Improve Tor bootstrap resilience and WebSocket connection handling
This commit is contained in:
+6
@@ -46,10 +46,16 @@ class OkHttpClientFactory(
|
||||
.addNetworkInterceptor(keyDecryptor)
|
||||
.build()
|
||||
|
||||
private var lastProxy: Proxy? = null
|
||||
|
||||
fun buildHttpClient(
|
||||
proxy: Proxy?,
|
||||
timeoutSeconds: Int,
|
||||
): OkHttpClient {
|
||||
if (proxy != lastProxy) {
|
||||
rootClient.connectionPool.evictAll()
|
||||
lastProxy = proxy
|
||||
}
|
||||
val seconds = if (proxy != null) timeoutSeconds * 3 else timeoutSeconds
|
||||
return rootClient
|
||||
.newBuilder()
|
||||
|
||||
+8
@@ -37,6 +37,7 @@ class OkHttpClientFactoryForRelays(
|
||||
const val DEFAULT_IS_MOBILE: Boolean = false
|
||||
const val DEFAULT_TIMEOUT_ON_WIFI_SECS: Int = 10
|
||||
const val DEFAULT_TIMEOUT_ON_MOBILE_SECS: Int = 30
|
||||
const val WEBSOCKET_PING_INTERVAL_SECS: Long = 120
|
||||
|
||||
private fun isEmulator(): Boolean =
|
||||
Build.FINGERPRINT.startsWith("generic") ||
|
||||
@@ -76,10 +77,16 @@ class OkHttpClientFactoryForRelays(
|
||||
.addInterceptor(DefaultContentTypeInterceptor(userAgent))
|
||||
.build()
|
||||
|
||||
private var lastProxy: Proxy? = null
|
||||
|
||||
fun buildHttpClient(
|
||||
proxy: Proxy?,
|
||||
timeoutSeconds: Int,
|
||||
): OkHttpClient {
|
||||
if (proxy != lastProxy) {
|
||||
rootClient.connectionPool.evictAll()
|
||||
lastProxy = proxy
|
||||
}
|
||||
val seconds = if (proxy != null) timeoutSeconds * 3 else timeoutSeconds
|
||||
return rootClient
|
||||
.newBuilder()
|
||||
@@ -87,6 +94,7 @@ class OkHttpClientFactoryForRelays(
|
||||
.connectTimeout(Duration.ofSeconds(seconds.toLong()))
|
||||
.readTimeout(Duration.ofSeconds(seconds.toLong() * 3))
|
||||
.writeTimeout(Duration.ofSeconds(seconds.toLong() * 3))
|
||||
.pingInterval(Duration.ofSeconds(WEBSOCKET_PING_INTERVAL_SECS))
|
||||
.build()
|
||||
}
|
||||
|
||||
|
||||
@@ -54,6 +54,34 @@ class TorService(
|
||||
private val _status = MutableStateFlow<TorServiceStatus>(TorServiceStatus.Off)
|
||||
val status: StateFlow<TorServiceStatus> = _status.asStateFlow()
|
||||
|
||||
private fun artiDataDir() = File(context.filesDir, "arti")
|
||||
|
||||
/**
|
||||
* Clears the Arti cache directory (consensus, relay descriptors) while
|
||||
* preserving the state directory (guard selection). This forces a fresh
|
||||
* consensus download on the next bootstrap, preventing stale cached data
|
||||
* from causing circuit failures.
|
||||
*/
|
||||
private fun clearArtiCache() {
|
||||
val cacheDir = File(artiDataDir(), "cache")
|
||||
if (cacheDir.exists()) {
|
||||
cacheDir.deleteRecursively()
|
||||
Log.d("TorService") { "Cleared Arti cache directory" }
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Clears all Arti persistent data (state + cache). Used as a last resort
|
||||
* when initialization fails, to recover from corrupted state.
|
||||
*/
|
||||
private fun clearAllArtiData() {
|
||||
val dataDir = artiDataDir()
|
||||
if (dataDir.exists()) {
|
||||
dataDir.deleteRecursively()
|
||||
Log.d("TorService") { "Cleared all Arti data" }
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialize the TorClient (once) and start the SOCKS proxy.
|
||||
* Must be called from a coroutine on [Dispatchers.IO].
|
||||
@@ -90,12 +118,21 @@ class TorService(
|
||||
}
|
||||
}
|
||||
|
||||
val dataDir = File(context.filesDir, "arti").absolutePath
|
||||
// Clear cached consensus/descriptors so Arti bootstraps with
|
||||
// fresh network data, preventing stale guards/circuits.
|
||||
clearArtiCache()
|
||||
|
||||
val dataDir = artiDataDir().absolutePath
|
||||
Log.d("TorService") { "Initializing Arti with data dir: $dataDir" }
|
||||
|
||||
val initResult = ArtiNative.initialize(dataDir)
|
||||
var initResult = ArtiNative.initialize(dataDir)
|
||||
if (initResult != 0) {
|
||||
Log.e("TorService") { "Failed to initialize Arti: error $initResult" }
|
||||
Log.e("TorService") { "Failed to initialize Arti: error $initResult, clearing data and retrying" }
|
||||
clearAllArtiData()
|
||||
initResult = ArtiNative.initialize(dataDir)
|
||||
}
|
||||
if (initResult != 0) {
|
||||
Log.e("TorService") { "Failed to initialize Arti on retry: error $initResult" }
|
||||
initialized.set(false)
|
||||
_status.value = TorServiceStatus.Off
|
||||
return@withContext
|
||||
|
||||
+1
-1
@@ -228,7 +228,7 @@ open class BasicRelayClient(
|
||||
}
|
||||
|
||||
fun dontTryAgainForALongTime() {
|
||||
delayToConnectInSeconds = TimeUtils.ONE_DAY
|
||||
delayToConnectInSeconds = TimeUtils.FIVE_MINUTES
|
||||
}
|
||||
|
||||
override fun sendOrConnectAndSync(cmd: Command) {
|
||||
|
||||
Reference in New Issue
Block a user