Skip to content

Commit eef3dbc

Browse files
committed
feat: enhance GeoIP DB update process and improve error handling
1 parent 188221a commit eef3dbc

File tree

6 files changed

+70
-28
lines changed

6 files changed

+70
-28
lines changed

composeApp/src/androidMain/kotlin/org/ooni/probe/net/Http.android.kt

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,13 @@ import java.net.URL
1111

1212
actual suspend fun httpGetBytes(url: String): Result<ByteArray, GetBytesException> =
1313
withContext(Dispatchers.IO) {
14-
val connection = (URL(url).openConnection() as HttpURLConnection)
14+
val connection: HttpURLConnection
15+
try {
16+
connection = URL(url).openConnection() as HttpURLConnection
17+
} catch (e: Throwable) {
18+
return@withContext Failure(GetBytesException(e))
19+
}
20+
1521
connection.requestMethod = "GET"
1622
connection.instanceFollowRedirects = true
1723
connection.connectTimeout = 15000

composeApp/src/commonMain/kotlin/org/ooni/engine/Engine.kt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -197,7 +197,7 @@ class Engine(
197197
MAX_RUNTIME_DISABLED
198198
}
199199

200-
private suspend fun buildSessionConfig(
200+
private fun buildSessionConfig(
201201
taskOrigin: TaskOrigin,
202202
preferences: EnginePreferences,
203203
) = OonimkallBridge.SessionConfig(

composeApp/src/commonMain/kotlin/org/ooni/engine/TaskEventMapper.kt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -101,7 +101,7 @@ class TaskEventMapper(
101101
)
102102

103103
"status.resolver_lookup" -> value?.geoIpdb?.let {
104-
println(it)
104+
Logger.d("GeoIP DB info in resolver lookup: $it")
105105
null
106106
}
107107

composeApp/src/commonMain/kotlin/org/ooni/probe/di/Dependencies.kt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -210,7 +210,7 @@ class Dependencies(
210210
private val downloader by lazy {
211211
DownloadFile(
212212
fileSystem = FileSystem.SYSTEM,
213-
fetchBytes = { url -> httpGetBytes(url) },
213+
fetchBytes = ::httpGetBytes,
214214
)
215215
}
216216

composeApp/src/commonMain/kotlin/org/ooni/probe/domain/FetchGeoIpDbUpdates.kt

Lines changed: 32 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,17 @@
11
package org.ooni.probe.domain
22

3+
import co.touchlab.kermit.Logger
34
import kotlinx.coroutines.flow.first
45
import kotlinx.serialization.SerialName
56
import kotlinx.serialization.Serializable
7+
import kotlinx.serialization.SerializationException
68
import kotlinx.serialization.json.Json
79
import okio.Path
810
import ooniprobe.composeapp.generated.resources.Res
911
import ooniprobe.composeapp.generated.resources.engine_mmdb_version
1012
import org.jetbrains.compose.resources.getString
1113
import org.ooni.engine.Engine
14+
import org.ooni.engine.Engine.MkException
1215
import org.ooni.engine.models.Failure
1316
import org.ooni.engine.models.Result
1417
import org.ooni.engine.models.Success
@@ -38,8 +41,14 @@ class FetchGeoIpDbUpdates(
3841

3942
downloadFile(url, target)
4043
.onSuccess { downloadedPath ->
41-
preferencesRepository.setValueByKey(SettingsKey.MMDB_VERSION, versionName)
42-
preferencesRepository.setValueByKey(SettingsKey.MMDB_LAST_CHECK, Clock.System.now().toEpochMilliseconds())
44+
preferencesRepository.setValueByKey(
45+
SettingsKey.MMDB_VERSION,
46+
versionName,
47+
)
48+
preferencesRepository.setValueByKey(
49+
SettingsKey.MMDB_LAST_CHECK,
50+
Clock.System.now().toEpochMilliseconds(),
51+
)
4352
return Success(downloadedPath)
4453
}.onFailure { downloadError ->
4554
return Failure(Engine.MkException(downloadError))
@@ -56,17 +65,33 @@ class FetchGeoIpDbUpdates(
5665
*/
5766
private suspend fun isGeoIpDbLatest(latestVersion: String): Triple<Boolean, String, String> {
5867
val currentGeoIpDbVersion: String =
59-
(preferencesRepository.getValueByKey(SettingsKey.MMDB_VERSION).first() ?: getString(Res.string.engine_mmdb_version)) as String
68+
(
69+
preferencesRepository.getValueByKey(SettingsKey.MMDB_VERSION).first()
70+
?: getString(Res.string.engine_mmdb_version)
71+
) as String
6072

61-
return Triple(normalize(currentGeoIpDbVersion) >= normalize(latestVersion), currentGeoIpDbVersion, latestVersion)
73+
return Triple(
74+
normalize(currentGeoIpDbVersion) >= normalize(latestVersion),
75+
currentGeoIpDbVersion,
76+
latestVersion,
77+
)
6278
}
6379

64-
private suspend fun getLatestEngineVersion(): Result<String, Engine.MkException> {
80+
private suspend fun getLatestEngineVersion(): Result<String, MkException> {
6581
val url = "https://api.github.com/repos/aanorbel/oomplt-mmdb/releases/latest"
6682

6783
return engineHttpDo("GET", url, TaskOrigin.OoniRun).map { payload ->
68-
val jsonStr = payload ?: throw Engine.MkException(Throwable("Empty body"))
69-
json.decodeFromString(GhRelease.serializer(), jsonStr).tag
84+
payload?.let {
85+
try {
86+
json.decodeFromString(GhRelease.serializer(), payload).tag
87+
} catch (e: SerializationException) {
88+
Logger.e(e) { "Failed to decode release info" }
89+
null
90+
} catch (e: IllegalArgumentException) {
91+
Logger.e(e) { "Failed to decode release info" }
92+
null
93+
}
94+
} ?: throw MkException(Throwable("Failed to fetch latest version"))
7095
}
7196
}
7297

composeApp/src/iosMain/kotlin/org/ooni/probe/net/Http.ios.kt

Lines changed: 28 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -16,31 +16,42 @@ import kotlin.coroutines.resume
1616

1717
actual suspend fun httpGetBytes(url: String): Result<ByteArray, GetBytesException> =
1818
suspendCancellableCoroutine { cont ->
19-
val nsurl = NSURL.URLWithString(url)!!
19+
val nsurl = NSURL.URLWithString(url) ?: run {
20+
cont.resume(Failure(GetBytesException(RuntimeException("Invalid URL: $url"))))
21+
return@suspendCancellableCoroutine
22+
}
2023
val task = NSURLSession.sharedSession.dataTaskWithURL(nsurl) { data, response, error ->
21-
when {
22-
error != null -> cont.resume(Failure(GetBytesException(RuntimeException(error.localizedDescription))))
23-
data != null -> {
24-
// If we have an HTTP response, check status code
25-
val http = response as? platform.Foundation.NSHTTPURLResponse
26-
val status = http?.statusCode?.toInt() ?: 200
27-
if (status in 200..299) {
28-
cont.resume(Success((data as NSData).toByteArray()))
24+
if (error != null) {
25+
cont.resume(Failure(GetBytesException(RuntimeException(error.toString()))))
26+
return@dataTaskWithURL
27+
}
28+
29+
when (val r = response) {
30+
is platform.Foundation.NSHTTPURLResponse -> {
31+
val statusCode = r.statusCode
32+
if (statusCode in 200..299) {
33+
cont.resume(Success(data?.toByteArray() ?: ByteArray(0)))
2934
} else {
30-
cont.resume(Failure(GetBytesException(RuntimeException("HTTP $status while GET $url"))))
35+
cont.resume(Failure(GetBytesException(RuntimeException("HTTP $statusCode while GET $url"))))
36+
}
37+
}
38+
else -> {
39+
// This could be for non-HTTP responses (e.g. file://) or an invalid state
40+
if (data != null) {
41+
cont.resume(Success(data.toByteArray()))
42+
} else {
43+
cont.resume(Failure(GetBytesException(RuntimeException("Request to $url returned no data and no error"))))
3144
}
3245
}
33-
else -> cont.resume(Success(ByteArray(0)))
3446
}
3547
}
3648
cont.invokeOnCancellation { task.cancel() }
3749
task.resume()
3850
}
3951

40-
private fun NSData.toByteArray(): ByteArray {
41-
val result = ByteArray(length.toInt())
42-
result.usePinned {
43-
memcpy(it.addressOf(0), this.bytes, this.length)
52+
private fun NSData.toByteArray(): ByteArray =
53+
ByteArray(length.toInt()).apply {
54+
usePinned {
55+
memcpy(it.addressOf(0), bytes, length)
56+
}
4457
}
45-
return result
46-
}

0 commit comments

Comments
 (0)