diff --git a/app/src/main/java/com/bitchat/android/net/OkHttpProvider.kt b/app/src/main/java/com/bitchat/android/net/OkHttpProvider.kt index 7f4d7c29..f9ad16e2 100644 --- a/app/src/main/java/com/bitchat/android/net/OkHttpProvider.kt +++ b/app/src/main/java/com/bitchat/android/net/OkHttpProvider.kt @@ -22,10 +22,13 @@ object OkHttpProvider { private val httpClientRef = AtomicReference(null) private val wsClientRef = AtomicReference(null) + private val clientLock = Any() fun reset() { - httpClientRef.set(null) - wsClientRef.set(null) + synchronized(clientLock) { + httpClientRef.set(null) + wsClientRef.set(null) + } } fun httpClient(): OkHttpClient = routedHttpClient().client @@ -38,26 +41,29 @@ object OkHttpProvider { */ fun routedHttpClient(): RoutedClient { httpClientRef.get()?.let { return it } - val (builder, route) = baseBuilderForCurrentProxy() - val client = builder - .callTimeout(15, TimeUnit.SECONDS) - .connectTimeout(10, TimeUnit.SECONDS) - .readTimeout(15, TimeUnit.SECONDS) - .build() - val routedClient = RoutedClient(client, route) - httpClientRef.set(routedClient) - return routedClient + return synchronized(clientLock) { + httpClientRef.get() ?: run { + val (builder, route) = baseBuilderForCurrentProxy() + val client = builder + .callTimeout(15, TimeUnit.SECONDS) + .connectTimeout(10, TimeUnit.SECONDS) + .readTimeout(15, TimeUnit.SECONDS) + .build() + RoutedClient(client, route).also(httpClientRef::set) + } + } } fun webSocketClient(): OkHttpClient { wsClientRef.get()?.let { return it } - val client = baseBuilderForCurrentProxy().first - .connectTimeout(10, TimeUnit.SECONDS) - .readTimeout(0, TimeUnit.SECONDS) - .writeTimeout(10, TimeUnit.SECONDS) - .build() - wsClientRef.set(client) - return client + return synchronized(clientLock) { + wsClientRef.get() ?: baseBuilderForCurrentProxy().first + .connectTimeout(10, TimeUnit.SECONDS) + .readTimeout(0, TimeUnit.SECONDS) + .writeTimeout(10, TimeUnit.SECONDS) + .build() + .also(wsClientRef::set) + } } private fun baseBuilderForCurrentProxy(): Pair { diff --git a/app/src/test/kotlin/com/bitchat/android/net/OkHttpProviderTest.kt b/app/src/test/kotlin/com/bitchat/android/net/OkHttpProviderTest.kt new file mode 100644 index 00000000..95117435 --- /dev/null +++ b/app/src/test/kotlin/com/bitchat/android/net/OkHttpProviderTest.kt @@ -0,0 +1,26 @@ +package com.bitchat.android.net + +import org.junit.Assert.assertEquals +import org.junit.Assert.assertNotSame +import org.junit.Test +import org.junit.runner.RunWith +import org.robolectric.RobolectricTestRunner + +@RunWith(RobolectricTestRunner::class) +class OkHttpProviderTest { + + @Test + fun `reset clears cached clients without changing the route`() { + OkHttpProvider.reset() + val cachedHttp = OkHttpProvider.routedHttpClient() + val cachedWebSocket = OkHttpProvider.webSocketClient() + + OkHttpProvider.reset() + + val rebuiltHttp = OkHttpProvider.routedHttpClient() + val rebuiltWebSocket = OkHttpProvider.webSocketClient() + assertEquals(cachedHttp.route, rebuiltHttp.route) + assertNotSame(cachedHttp.client, rebuiltHttp.client) + assertNotSame(cachedWebSocket, rebuiltWebSocket) + } +}