diff --git a/CHANGELOG.md b/CHANGELOG.md index 10785db07..e32be5ac5 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,10 +4,10 @@ ### Changes -- Added GuestHole support, that can be used by the clients to overcome potential blocked api. Mainly -this is supported now from VPN client. +- Added Server Connection error support, that can be used by the clients to overcome potential blocked api. +Mainly and initially this is supported now from VPN client for their guest hole feature. - Clients should provide a new dependency for `GuestHoleFallbackListener` or use the default one that -Core provides `DefaultGustHoleFallbackListener` which does not do anything. +Core provides `ServerConnectionListener` which does not do anything. ## Auth [1.18.4], Network [1.15.8], Util Kotlin [1.15.3] ## Auth [1.18.5], Network [1.15.9], Util Kotlin [1.15.4] diff --git a/coreexample/src/main/kotlin/me/proton/android/core/coreexample/di/NetworkModule.kt b/coreexample/src/main/kotlin/me/proton/android/core/coreexample/di/NetworkModule.kt index 1e09731fd..1c9c604da 100644 --- a/coreexample/src/main/kotlin/me/proton/android/core/coreexample/di/NetworkModule.kt +++ b/coreexample/src/main/kotlin/me/proton/android/core/coreexample/di/NetworkModule.kt @@ -142,13 +142,13 @@ class NetworkModule { @Provides @Singleton fun provideGuestHoleFallbackListener(): ServerConnectionListener = object: ServerConnectionListener { - override suspend fun fallbackCall( + override suspend fun onPotentiallyBlocked( path: String?, query: String?, - blockToRetry: suspend () -> ApiResult + backendCall: suspend () -> ApiResult ): ApiResult? { delay(1000) - return blockToRetry() + return backendCall() } } } diff --git a/network/data/src/main/kotlin/me/proton/core/network/data/ApiManagerFactory.kt b/network/data/src/main/kotlin/me/proton/core/network/data/ApiManagerFactory.kt index 460e0fee7..a96e311d9 100644 --- a/network/data/src/main/kotlin/me/proton/core/network/data/ApiManagerFactory.kt +++ b/network/data/src/main/kotlin/me/proton/core/network/data/ApiManagerFactory.kt @@ -137,15 +137,15 @@ class ApiManagerFactory( ): List> { val refreshTokenHandler = RefreshTokenHandler(sessionId, sessionProvider, sessionListener, monoClockMs) val forceUpdateHandler = ProtonForceUpdateHandler(apiClient) - val guestHoleHandler = ServerConnectionHandler(serverConnectionListener) + val serverConnectionHandler = ServerConnectionHandler(serverConnectionListener) val humanVerificationNeededHandler = HumanVerificationNeededHandler(sessionId, clientIdProvider, humanVerificationListener, monoClockMs) val humanVerificationInvalidHandler = HumanVerificationInvalidHandler(sessionId, clientIdProvider, humanVerificationListener) return listOf( + serverConnectionHandler, refreshTokenHandler, forceUpdateHandler, - guestHoleHandler, humanVerificationInvalidHandler, humanVerificationNeededHandler ) diff --git a/network/data/src/main/kotlin/me/proton/core/network/data/ApiResultUtils.kt b/network/data/src/main/kotlin/me/proton/core/network/data/ApiResultUtils.kt index 58c92efed..6e661b01b 100644 --- a/network/data/src/main/kotlin/me/proton/core/network/data/ApiResultUtils.kt +++ b/network/data/src/main/kotlin/me/proton/core/network/data/ApiResultUtils.kt @@ -47,7 +47,7 @@ internal suspend fun safeApiCall( } catch (e: CertificateException) { ApiResult.Error.Certificate(e) } catch (e: ServerConnectionException) { - e.parse(networkManager) + e.toApiResult(networkManager) } if (result is ApiResult.Error) { result.cause?.let { CoreLogger.e(LogTag.DEFAULT, it) } @@ -55,7 +55,7 @@ internal suspend fun safeApiCall( return result } -private fun ServerConnectionException.parse(networkManager: NetworkManager): ApiResult.Error.Connection { +private fun ServerConnectionException.toApiResult(networkManager: NetworkManager): ApiResult.Error.Connection { // handle the exceptions that might indicate that the API is potentially blocked return when (originalException) { is SSLHandshakeException -> ApiResult.Error.Certificate(this) diff --git a/network/domain/src/main/kotlin/me/proton/core/network/domain/handlers/ServerConnectionHandler.kt b/network/domain/src/main/kotlin/me/proton/core/network/domain/handlers/ServerConnectionHandler.kt index 4f933d1c1..9d9127a2a 100644 --- a/network/domain/src/main/kotlin/me/proton/core/network/domain/handlers/ServerConnectionHandler.kt +++ b/network/domain/src/main/kotlin/me/proton/core/network/domain/handlers/ServerConnectionHandler.kt @@ -36,12 +36,12 @@ class ServerConnectionHandler( ): ApiResult { if (!error.isPotentialBlocking) return error if (error !is ApiResult.Error.Connection) return error - // it should suspend and ask the client to establish guest hole - val result = + + return serverConnectionListener?.let { listener -> globalMutex.withLock { - serverConnectionListener?.fallbackCall(error.path, error.query) { backend(call) } + listener.onPotentiallyBlocked(error.path, error.query) { backend(call) } } - return result ?: error + } ?: error } companion object { diff --git a/network/domain/src/main/kotlin/me/proton/core/network/domain/serverconnection/ServerConnectionListener.kt b/network/domain/src/main/kotlin/me/proton/core/network/domain/serverconnection/ServerConnectionListener.kt index e3c42bd97..22465edd3 100644 --- a/network/domain/src/main/kotlin/me/proton/core/network/domain/serverconnection/ServerConnectionListener.kt +++ b/network/domain/src/main/kotlin/me/proton/core/network/domain/serverconnection/ServerConnectionListener.kt @@ -22,9 +22,9 @@ import me.proton.core.network.domain.ApiResult interface ServerConnectionListener { - suspend fun fallbackCall( + suspend fun onPotentiallyBlocked( path: String?, query: String?, - blockToRetry: suspend () -> ApiResult + backendCall: suspend () -> ApiResult ): ApiResult? }