From dba0ca910e40631019f33f434794aa2581c746aa Mon Sep 17 00:00:00 2001 From: ThomasSession Date: Mon, 29 Jul 2024 17:20:44 +1000 Subject: [PATCH 1/9] JNI bridging for the new version blinded key api --- libsession-util/src/main/cpp/CMakeLists.txt | 1 + libsession-util/src/main/cpp/blinded_key.cpp | 34 +++++++++++++++++++ .../libsession_util/util/BlindKeyAPI.kt | 10 ++++++ 3 files changed, 45 insertions(+) create mode 100644 libsession-util/src/main/cpp/blinded_key.cpp create mode 100644 libsession-util/src/main/java/network/loki/messenger/libsession_util/util/BlindKeyAPI.kt diff --git a/libsession-util/src/main/cpp/CMakeLists.txt b/libsession-util/src/main/cpp/CMakeLists.txt index 47fee4803c..f65667bcb5 100644 --- a/libsession-util/src/main/cpp/CMakeLists.txt +++ b/libsession-util/src/main/cpp/CMakeLists.txt @@ -30,6 +30,7 @@ set(SOURCES config_base.cpp contacts.cpp conversation.cpp + blinded_key.cpp util.cpp) add_library( # Sets the name of the library. diff --git a/libsession-util/src/main/cpp/blinded_key.cpp b/libsession-util/src/main/cpp/blinded_key.cpp new file mode 100644 index 0000000000..1ed1cfd554 --- /dev/null +++ b/libsession-util/src/main/cpp/blinded_key.cpp @@ -0,0 +1,34 @@ +#include +#include + +#include "util.h" +#include "jni_utils.h" + +// +// Created by Thomas Ruffie on 29/7/2024. +// + +extern "C" +JNIEXPORT jobject JNICALL +Java_network_loki_messenger_libsession_1util_util_BlindKeyAPI_blindVersionKeyPair(JNIEnv *env, + jobject thiz, + jbyteArray ed25519_secret_key) { + return jni_utils::run_catching_cxx_exception_or_throws(env, [=] { + const auto [pk, sk] = session::blind_version_key_pair(util::ustring_from_bytes(env, ed25519_secret_key)); + + jclass kp_class = env->FindClass("network/loki/messenger/libsession_util/util/KeyPair"); + jmethodID kp_constructor = env->GetMethodID(kp_class, "", "([B[B)V"); + return env->NewObject(kp_class, kp_constructor, util::bytes_from_ustring(env, {pk.data(), pk.size()}), util::bytes_from_ustring(env, {sk.data(), sk.size()})); + }); +} +extern "C" +JNIEXPORT jbyteArray JNICALL +Java_network_loki_messenger_libsession_1util_util_BlindKeyAPI_blindVersionSign(JNIEnv *env, + jobject thiz, + jbyteArray ed25519_secret_key, + jlong timestamp) { + return jni_utils::run_catching_cxx_exception_or_throws(env, [=] { + auto bytes = session::blind_version_sign(util::ustring_from_bytes(env, ed25519_secret_key), session::Platform::android, timestamp); + return util::bytes_from_ustring(env, bytes); + }); +} \ No newline at end of file diff --git a/libsession-util/src/main/java/network/loki/messenger/libsession_util/util/BlindKeyAPI.kt b/libsession-util/src/main/java/network/loki/messenger/libsession_util/util/BlindKeyAPI.kt new file mode 100644 index 0000000000..8f57caf071 --- /dev/null +++ b/libsession-util/src/main/java/network/loki/messenger/libsession_util/util/BlindKeyAPI.kt @@ -0,0 +1,10 @@ +package network.loki.messenger.libsession_util.util + +object BlindKeyAPI { + init { + System.loadLibrary("session_util") + } + + external fun blindVersionKeyPair(ed25519SecretKey: ByteArray): KeyPair + external fun blindVersionSign(ed25519SecretKey: ByteArray, timestamp: Long): ByteArray +} \ No newline at end of file From d23d8f3b07811c4dcbd6d0451abc63d775654028 Mon Sep 17 00:00:00 2001 From: Fanchao Liu <273191+simophin@users.noreply.github.com> Date: Mon, 29 Jul 2024 17:42:26 +1000 Subject: [PATCH 2/9] Fix double closing on memory file (#1579) Co-authored-by: fanchao --- .../java/org/thoughtcrime/securesms/util/MemoryFileUtil.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/src/main/java/org/thoughtcrime/securesms/util/MemoryFileUtil.java b/app/src/main/java/org/thoughtcrime/securesms/util/MemoryFileUtil.java index 4ee43e1e9c..f193827efd 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/util/MemoryFileUtil.java +++ b/app/src/main/java/org/thoughtcrime/securesms/util/MemoryFileUtil.java @@ -22,7 +22,7 @@ public class MemoryFileUtil { int fd = field.getInt(fileDescriptor); - return ParcelFileDescriptor.adoptFd(fd); + return ParcelFileDescriptor.fromFd(fd); } catch (IllegalAccessException e) { throw new IOException(e); } catch (InvocationTargetException e) { From 35a9f9fbbe0d0a358d66d5bad313f68ac1a0473d Mon Sep 17 00:00:00 2001 From: ThomasSession Date: Tue, 30 Jul 2024 12:02:56 +1000 Subject: [PATCH 3/9] Version fetching API added --- .../securesms/util/VersionUtil.kt | 44 ++++++++++++++ .../messaging/file_server/FileServerApi.kt | 57 ++++++++++++++++++- .../messaging/file_server/VersionData.kt | 7 +++ .../libsession/snode/utilities/PromiseUtil.kt | 13 +++++ .../utilities/TextSecurePreferences.kt | 13 +++++ 5 files changed, 132 insertions(+), 2 deletions(-) create mode 100644 app/src/main/java/org/thoughtcrime/securesms/util/VersionUtil.kt create mode 100644 libsession/src/main/java/org/session/libsession/messaging/file_server/VersionData.kt create mode 100644 libsession/src/main/java/org/session/libsession/snode/utilities/PromiseUtil.kt diff --git a/app/src/main/java/org/thoughtcrime/securesms/util/VersionUtil.kt b/app/src/main/java/org/thoughtcrime/securesms/util/VersionUtil.kt new file mode 100644 index 0000000000..f5cde8d445 --- /dev/null +++ b/app/src/main/java/org/thoughtcrime/securesms/util/VersionUtil.kt @@ -0,0 +1,44 @@ +package org.thoughtcrime.securesms.util + +import android.content.Context +import android.os.Handler +import android.os.Looper +import org.session.libsession.utilities.TextSecurePreferences + +class VersionUtil( + private val context: Context, + private val prefs: TextSecurePreferences +) { + + private val handler = Handler(Looper.getMainLooper()) + private val runnable: Runnable + + init { + runnable = Runnable { + // Task to be executed every 4 hours + fetchVersionData() + } + + // Re-schedule the task + handler.postDelayed(runnable, FOUR_HOURS) + } + + fun startTimedVersionCheck() { + handler.post(runnable) + } + + fun stopTimedVersionCheck() { + handler.removeCallbacks(runnable) + } + + private fun fetchVersionData() { + // only perform this if at least 4h has elapsed since th last successful check + if(prefs.getLastVersionCheck() < FOUR_HOURS) return + + + } + + companion object { + private const val FOUR_HOURS = 4 * 60 * 60 * 1000L // 4 hours in milliseconds + } +} \ No newline at end of file diff --git a/libsession/src/main/java/org/session/libsession/messaging/file_server/FileServerApi.kt b/libsession/src/main/java/org/session/libsession/messaging/file_server/FileServerApi.kt index 5bffed57ee..2543983cd9 100644 --- a/libsession/src/main/java/org/session/libsession/messaging/file_server/FileServerApi.kt +++ b/libsession/src/main/java/org/session/libsession/messaging/file_server/FileServerApi.kt @@ -1,18 +1,22 @@ package org.session.libsession.messaging.file_server +import android.util.Base64 +import network.loki.messenger.libsession_util.util.BlindKeyAPI import nl.komponents.kovenant.Promise import nl.komponents.kovenant.functional.map -import okhttp3.Headers import okhttp3.Headers.Companion.toHeaders import okhttp3.HttpUrl import okhttp3.HttpUrl.Companion.toHttpUrlOrNull -import okhttp3.MediaType import okhttp3.MediaType.Companion.toMediaType import okhttp3.RequestBody +import org.session.libsession.messaging.MessagingModuleConfiguration import org.session.libsession.snode.OnionRequestAPI +import org.session.libsession.snode.utilities.await import org.session.libsignal.utilities.HTTP import org.session.libsignal.utilities.JsonUtil import org.session.libsignal.utilities.Log +import org.session.libsignal.utilities.toHexString +import java.util.concurrent.TimeUnit object FileServerApi { @@ -23,6 +27,7 @@ object FileServerApi { sealed class Error(message: String) : Exception(message) { object ParsingFailed : Error("Invalid response.") object InvalidURL : Error("Invalid URL.") + object NoEd25519KeyPair : Error("Couldn't find ed25519 key pair.") } data class Request( @@ -105,4 +110,52 @@ object FileServerApi { val request = Request(verb = HTTP.Verb.GET, endpoint = "file/$file") return send(request) } + + /** + * Returns the current version of session + * This is effectively proxying (and caching) the response from the github release + * page. + * + * Note that the value is cached and can be up to 30 minutes out of date normally, and up to 24 + * hours out of date if we cannot reach the Github API for some reason. + * + * https://github.com/oxen-io/session-file-server/blob/dev/doc/api.yaml#L119 + */ + suspend fun getClientVersion(): VersionData { + // Generate the auth signature + val secretKey = MessagingModuleConfiguration.shared.getUserED25519KeyPair()?.secretKey?.asBytes + ?: throw (Error.NoEd25519KeyPair) + + val blindedKeys = BlindKeyAPI.blindVersionKeyPair(secretKey) + val timestamp = TimeUnit.MILLISECONDS.toSeconds(System.currentTimeMillis()) // The current timestamp in seconds + val signature = BlindKeyAPI.blindVersionSign(secretKey, timestamp) + + // The hex encoded version-blinded public key with a 07 prefix + val blindedPkHex = buildString { + append("07") + append(blindedKeys.pubKey.toHexString()) + } + + val request = Request( + verb = HTTP.Verb.GET, + endpoint = "session_version", + queryParameters = mapOf("platform" to "android"), + headers = mapOf( + "X-FS-Pubkey" to blindedPkHex, + "X-FS-Timestamp" to timestamp.toString(), + "X-FS-Signature" to Base64.encodeToString(signature, Base64.NO_WRAP) + ) + ) + + // transform the promise into a coroutine + val result = send(request).await() + + // map out the result + val json = JsonUtil.fromJson(result, Map::class.java) + val statusCode = json.getOrDefault("status_code", 0) as Int + val version = json.getOrDefault("result", "") as String + val updated = json.getOrDefault("updated", 0.0) as Double + + return VersionData(statusCode, version, updated) + } } \ No newline at end of file diff --git a/libsession/src/main/java/org/session/libsession/messaging/file_server/VersionData.kt b/libsession/src/main/java/org/session/libsession/messaging/file_server/VersionData.kt new file mode 100644 index 0000000000..b7c28020e7 --- /dev/null +++ b/libsession/src/main/java/org/session/libsession/messaging/file_server/VersionData.kt @@ -0,0 +1,7 @@ +package org.session.libsession.messaging.file_server + +data class VersionData( + val statusCode: Int, // The value 200. Included for backwards compatibility, and may be removed someday. + val version: String, // The Session version. + val updated: Double // The unix timestamp when this version was retrieved from Github; this can be up to 24 hours ago in case of consistent fetch errors, though normally will be within the last 30 minutes. +) \ No newline at end of file diff --git a/libsession/src/main/java/org/session/libsession/snode/utilities/PromiseUtil.kt b/libsession/src/main/java/org/session/libsession/snode/utilities/PromiseUtil.kt new file mode 100644 index 0000000000..9a4cd0dd5a --- /dev/null +++ b/libsession/src/main/java/org/session/libsession/snode/utilities/PromiseUtil.kt @@ -0,0 +1,13 @@ +package org.session.libsession.snode.utilities + +import nl.komponents.kovenant.Promise +import kotlin.coroutines.resume +import kotlin.coroutines.resumeWithException +import kotlin.coroutines.suspendCoroutine + +suspend fun Promise.await(): T { + return suspendCoroutine { cont -> + success { cont.resume(it) } + fail { cont.resumeWithException(it) } + } +} \ No newline at end of file diff --git a/libsession/src/main/java/org/session/libsession/utilities/TextSecurePreferences.kt b/libsession/src/main/java/org/session/libsession/utilities/TextSecurePreferences.kt index 12fdd4ceaf..5bf109843d 100644 --- a/libsession/src/main/java/org/session/libsession/utilities/TextSecurePreferences.kt +++ b/libsession/src/main/java/org/session/libsession/utilities/TextSecurePreferences.kt @@ -13,6 +13,7 @@ import kotlinx.coroutines.channels.BufferOverflow import kotlinx.coroutines.flow.MutableSharedFlow import kotlinx.coroutines.flow.asSharedFlow import org.session.libsession.R +import org.session.libsession.utilities.TextSecurePreferences.Companion import org.session.libsession.utilities.TextSecurePreferences.Companion.AUTOPLAY_AUDIO_MESSAGES import org.session.libsession.utilities.TextSecurePreferences.Companion.CALL_NOTIFICATIONS_ENABLED import org.session.libsession.utilities.TextSecurePreferences.Companion.CLASSIC_DARK @@ -20,6 +21,7 @@ import org.session.libsession.utilities.TextSecurePreferences.Companion.CLASSIC_ import org.session.libsession.utilities.TextSecurePreferences.Companion.FOLLOW_SYSTEM_SETTINGS import org.session.libsession.utilities.TextSecurePreferences.Companion.HIDE_PASSWORD import org.session.libsession.utilities.TextSecurePreferences.Companion.LAST_VACUUM_TIME +import org.session.libsession.utilities.TextSecurePreferences.Companion.LAST_VERSION_CHECK import org.session.libsession.utilities.TextSecurePreferences.Companion.LEGACY_PREF_KEY_SELECTED_UI_MODE import org.session.libsession.utilities.TextSecurePreferences.Companion.OCEAN_DARK import org.session.libsession.utilities.TextSecurePreferences.Companion.OCEAN_LIGHT @@ -186,6 +188,8 @@ interface TextSecurePreferences { fun clearAll() fun getHidePassword(): Boolean fun setHidePassword(value: Boolean) + fun getLastVersionCheck(): Long + fun setLastVersionCheck() companion object { val TAG = TextSecurePreferences::class.simpleName @@ -272,6 +276,7 @@ interface TextSecurePreferences { const val AUTOPLAY_AUDIO_MESSAGES = "pref_autoplay_audio" const val FINGERPRINT_KEY_GENERATED = "fingerprint_key_generated" const val SELECTED_ACCENT_COLOR = "selected_accent_color" + const val LAST_VERSION_CHECK = "pref_last_version_check" const val HAS_RECEIVED_LEGACY_CONFIG = "has_received_legacy_config" const val HAS_FORCED_NEW_CONFIG = "has_forced_new_config" @@ -1541,6 +1546,14 @@ class AppTextSecurePreferences @Inject constructor( setLongPreference(LAST_VACUUM_TIME, System.currentTimeMillis()) } + override fun getLastVersionCheck(): Long { + return getLongPreference(LAST_VERSION_CHECK, 0) + } + + override fun setLastVersionCheck() { + setLongPreference(LAST_VERSION_CHECK, System.currentTimeMillis()) + } + override fun setShownCallNotification(): Boolean { val previousValue = getBooleanPreference(SHOWN_CALL_NOTIFICATION, false) if (previousValue) return false From d3990572a046a219d82975f1bb41ff3f8e48977e Mon Sep 17 00:00:00 2001 From: ThomasSession Date: Tue, 30 Jul 2024 12:46:13 +1000 Subject: [PATCH 4/9] Linking Version util to the app --- .../securesms/ApplicationContext.java | 9 ++++++ .../securesms/util/VersionUtil.kt | 30 +++++++++++++++++-- 2 files changed, 37 insertions(+), 2 deletions(-) diff --git a/app/src/main/java/org/thoughtcrime/securesms/ApplicationContext.java b/app/src/main/java/org/thoughtcrime/securesms/ApplicationContext.java index 023ec6b660..498060f59e 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/ApplicationContext.java +++ b/app/src/main/java/org/thoughtcrime/securesms/ApplicationContext.java @@ -86,6 +86,7 @@ import org.thoughtcrime.securesms.sskenvironment.ProfileManager; import org.thoughtcrime.securesms.sskenvironment.ReadReceiptManager; import org.thoughtcrime.securesms.sskenvironment.TypingStatusRepository; import org.thoughtcrime.securesms.util.Broadcaster; +import org.thoughtcrime.securesms.util.VersionUtil; import org.thoughtcrime.securesms.util.dynamiclanguage.LocaleParseHelper; import org.thoughtcrime.securesms.webrtc.CallMessageProcessor; import org.webrtc.PeerConnectionFactory; @@ -142,6 +143,7 @@ public class ApplicationContext extends Application implements DefaultLifecycleO private HandlerThread conversationListHandlerThread; private Handler conversationListHandler; private PersistentLogger persistentLogger; + private VersionUtil versionUtil; @Inject LokiAPIDatabase lokiAPIDatabase; @Inject public Storage storage; @@ -248,6 +250,7 @@ public class ApplicationContext extends Application implements DefaultLifecycleO resubmitProfilePictureIfNeeded(); loadEmojiSearchIndexIfNeeded(); EmojiSource.refresh(); + versionUtil = new VersionUtil(this, textSecurePreferences); NetworkConstraint networkConstraint = new NetworkConstraint.Factory(this).create(); HTTP.INSTANCE.setConnectedToNetwork(networkConstraint::isMet); @@ -274,6 +277,10 @@ public class ApplicationContext extends Application implements DefaultLifecycleO OpenGroupManager.INSTANCE.startPolling(); }); + + // try to fetch last version now and start the version polling + versionUtil.fetchVersionData(); + versionUtil.startTimedVersionCheck(); } @Override @@ -286,12 +293,14 @@ public class ApplicationContext extends Application implements DefaultLifecycleO poller.stopIfNeeded(); } ClosedGroupPollerV2.getShared().stopAll(); + versionUtil.stopTimedVersionCheck(); } @Override public void onTerminate() { stopKovenant(); // Loki OpenGroupManager.INSTANCE.stopPolling(); + versionUtil.clear(); super.onTerminate(); } diff --git a/app/src/main/java/org/thoughtcrime/securesms/util/VersionUtil.kt b/app/src/main/java/org/thoughtcrime/securesms/util/VersionUtil.kt index f5cde8d445..68da185baf 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/util/VersionUtil.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/util/VersionUtil.kt @@ -3,6 +3,12 @@ package org.thoughtcrime.securesms.util import android.content.Context import android.os.Handler import android.os.Looper +import android.util.Log +import kotlinx.coroutines.CoroutineScope +import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.Job +import kotlinx.coroutines.launch +import org.session.libsession.messaging.file_server.FileServerApi import org.session.libsession.utilities.TextSecurePreferences class VersionUtil( @@ -13,6 +19,9 @@ class VersionUtil( private val handler = Handler(Looper.getMainLooper()) private val runnable: Runnable + private val scope = CoroutineScope(Dispatchers.Default) + private var job: Job? = null + init { runnable = Runnable { // Task to be executed every 4 hours @@ -31,11 +40,28 @@ class VersionUtil( handler.removeCallbacks(runnable) } - private fun fetchVersionData() { + fun clear() { + job?.cancel() + stopTimedVersionCheck() + } + + fun fetchVersionData() { + Log.d("", "***** Trying to fetch version. Last check: ${prefs.getLastVersionCheck()}") // only perform this if at least 4h has elapsed since th last successful check if(prefs.getLastVersionCheck() < FOUR_HOURS) return - + job = scope.launch { + try { + // perform the version check + Log.d("", "***** Fetching last version") + val clientVersion = FileServerApi.getClientVersion() + Log.d("", "***** Got version: $clientVersion") + prefs.setLastVersionCheck() + } catch (e: Exception) { + // we can silently ignore the error + Log.e("", "***** Error fetching version", e) + } + } } companion object { From 42733c910d3510248698634860481326a859b7ee Mon Sep 17 00:00:00 2001 From: ThomasSession Date: Tue, 30 Jul 2024 13:30:58 +1000 Subject: [PATCH 5/9] Clean up logic Fixed randomly found timeunit error --- .../securesms/ApplicationContext.java | 5 ++-- .../org/thoughtcrime/securesms/MuteDialog.kt | 2 +- .../securesms/util/VersionUtil.kt | 30 ++++++++----------- 3 files changed, 15 insertions(+), 22 deletions(-) diff --git a/app/src/main/java/org/thoughtcrime/securesms/ApplicationContext.java b/app/src/main/java/org/thoughtcrime/securesms/ApplicationContext.java index 498060f59e..cfdc16e06c 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/ApplicationContext.java +++ b/app/src/main/java/org/thoughtcrime/securesms/ApplicationContext.java @@ -250,7 +250,7 @@ public class ApplicationContext extends Application implements DefaultLifecycleO resubmitProfilePictureIfNeeded(); loadEmojiSearchIndexIfNeeded(); EmojiSource.refresh(); - versionUtil = new VersionUtil(this, textSecurePreferences); + versionUtil = new VersionUtil(textSecurePreferences); NetworkConstraint networkConstraint = new NetworkConstraint.Factory(this).create(); HTTP.INSTANCE.setConnectedToNetwork(networkConstraint::isMet); @@ -278,8 +278,7 @@ public class ApplicationContext extends Application implements DefaultLifecycleO OpenGroupManager.INSTANCE.startPolling(); }); - // try to fetch last version now and start the version polling - versionUtil.fetchVersionData(); + // fetch last version data versionUtil.startTimedVersionCheck(); } diff --git a/app/src/main/java/org/thoughtcrime/securesms/MuteDialog.kt b/app/src/main/java/org/thoughtcrime/securesms/MuteDialog.kt index f294e387ff..071da43311 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/MuteDialog.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/MuteDialog.kt @@ -18,7 +18,7 @@ fun showMuteDialog( private enum class Option(@StringRes val stringRes: Int, val getTime: () -> Long) { ONE_HOUR(R.string.arrays__mute_for_one_hour, duration = TimeUnit.HOURS.toMillis(1)), - TWO_HOURS(R.string.arrays__mute_for_two_hours, duration = TimeUnit.DAYS.toMillis(2)), + TWO_HOURS(R.string.arrays__mute_for_two_hours, duration = TimeUnit.HOURS.toMillis(2)), ONE_DAY(R.string.arrays__mute_for_one_day, duration = TimeUnit.DAYS.toMillis(1)), SEVEN_DAYS(R.string.arrays__mute_for_seven_days, duration = TimeUnit.DAYS.toMillis(7)), FOREVER(R.string.arrays__mute_forever, getTime = { Long.MAX_VALUE }); diff --git a/app/src/main/java/org/thoughtcrime/securesms/util/VersionUtil.kt b/app/src/main/java/org/thoughtcrime/securesms/util/VersionUtil.kt index 68da185baf..9781c1105a 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/util/VersionUtil.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/util/VersionUtil.kt @@ -1,20 +1,19 @@ package org.thoughtcrime.securesms.util -import android.content.Context import android.os.Handler import android.os.Looper -import android.util.Log import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.Job import kotlinx.coroutines.launch import org.session.libsession.messaging.file_server.FileServerApi import org.session.libsession.utilities.TextSecurePreferences +import java.util.concurrent.TimeUnit class VersionUtil( - private val context: Context, private val prefs: TextSecurePreferences ) { + private val FOUR_HOURS: Long = TimeUnit.HOURS.toMillis(4) private val handler = Handler(Looper.getMainLooper()) private val runnable: Runnable @@ -24,12 +23,8 @@ class VersionUtil( init { runnable = Runnable { - // Task to be executed every 4 hours - fetchVersionData() + fetchAndScheduleNextVersionCheck() } - - // Re-schedule the task - handler.postDelayed(runnable, FOUR_HOURS) } fun startTimedVersionCheck() { @@ -45,26 +40,25 @@ class VersionUtil( stopTimedVersionCheck() } - fun fetchVersionData() { - Log.d("", "***** Trying to fetch version. Last check: ${prefs.getLastVersionCheck()}") + private fun fetchAndScheduleNextVersionCheck() { + fetchVersionData() + handler.postDelayed(runnable, FOUR_HOURS) + } + + private fun fetchVersionData() { // only perform this if at least 4h has elapsed since th last successful check - if(prefs.getLastVersionCheck() < FOUR_HOURS) return + val lastCheck = System.currentTimeMillis() - prefs.getLastVersionCheck() + if(lastCheck < FOUR_HOURS) return + job?.cancel() job = scope.launch { try { // perform the version check - Log.d("", "***** Fetching last version") val clientVersion = FileServerApi.getClientVersion() - Log.d("", "***** Got version: $clientVersion") prefs.setLastVersionCheck() } catch (e: Exception) { // we can silently ignore the error - Log.e("", "***** Error fetching version", e) } } } - - companion object { - private const val FOUR_HOURS = 4 * 60 * 60 * 1000L // 4 hours in milliseconds - } } \ No newline at end of file From 4b87e926c4845d61e7d91c0f118c575a1012ef49 Mon Sep 17 00:00:00 2001 From: ThomasSession Date: Tue, 30 Jul 2024 13:58:35 +1000 Subject: [PATCH 6/9] Added a log so we can see when the version data is returned --- .../main/java/org/thoughtcrime/securesms/util/VersionUtil.kt | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/app/src/main/java/org/thoughtcrime/securesms/util/VersionUtil.kt b/app/src/main/java/org/thoughtcrime/securesms/util/VersionUtil.kt index 9781c1105a..68a5982da5 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/util/VersionUtil.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/util/VersionUtil.kt @@ -8,11 +8,13 @@ import kotlinx.coroutines.Job import kotlinx.coroutines.launch import org.session.libsession.messaging.file_server.FileServerApi import org.session.libsession.utilities.TextSecurePreferences +import org.session.libsignal.utilities.Log import java.util.concurrent.TimeUnit class VersionUtil( private val prefs: TextSecurePreferences ) { + private val TAG: String = VersionUtil::class.java.simpleName private val FOUR_HOURS: Long = TimeUnit.HOURS.toMillis(4) private val handler = Handler(Looper.getMainLooper()) @@ -55,9 +57,11 @@ class VersionUtil( try { // perform the version check val clientVersion = FileServerApi.getClientVersion() + Log.i(TAG, "Fetched version data: $clientVersion") prefs.setLastVersionCheck() } catch (e: Exception) { // we can silently ignore the error + Log.e(TAG, "Error fetching version data: $e") } } } From 83ea71de246ce3d68319632ac80fa75886ef5106 Mon Sep 17 00:00:00 2001 From: ThomasSession Date: Tue, 30 Jul 2024 14:49:45 +1000 Subject: [PATCH 7/9] Update app/src/main/java/org/thoughtcrime/securesms/util/VersionUtil.kt Co-authored-by: Andrew --- .../main/java/org/thoughtcrime/securesms/util/VersionUtil.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/src/main/java/org/thoughtcrime/securesms/util/VersionUtil.kt b/app/src/main/java/org/thoughtcrime/securesms/util/VersionUtil.kt index 68a5982da5..76075b4ac1 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/util/VersionUtil.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/util/VersionUtil.kt @@ -50,7 +50,7 @@ class VersionUtil( private fun fetchVersionData() { // only perform this if at least 4h has elapsed since th last successful check val lastCheck = System.currentTimeMillis() - prefs.getLastVersionCheck() - if(lastCheck < FOUR_HOURS) return + if (lastCheck < FOUR_HOURS) return job?.cancel() job = scope.launch { From 7a8e1309fb461bc867ea944ff9e656d0c474d9ac Mon Sep 17 00:00:00 2001 From: ThomasSession Date: Tue, 30 Jul 2024 15:04:41 +1000 Subject: [PATCH 8/9] PR feedback --- .../messenger/libsession_util/util/BlindKeyAPI.kt | 7 ++++++- .../messaging/file_server/FileServerApi.kt | 13 +++++++------ 2 files changed, 13 insertions(+), 7 deletions(-) diff --git a/libsession-util/src/main/java/network/loki/messenger/libsession_util/util/BlindKeyAPI.kt b/libsession-util/src/main/java/network/loki/messenger/libsession_util/util/BlindKeyAPI.kt index 8f57caf071..cd3dac3af2 100644 --- a/libsession-util/src/main/java/network/loki/messenger/libsession_util/util/BlindKeyAPI.kt +++ b/libsession-util/src/main/java/network/loki/messenger/libsession_util/util/BlindKeyAPI.kt @@ -1,10 +1,15 @@ package network.loki.messenger.libsession_util.util object BlindKeyAPI { - init { + private val loadLibrary by lazy { System.loadLibrary("session_util") } + init { + // Ensure the library is loaded at initialization + loadLibrary + } + external fun blindVersionKeyPair(ed25519SecretKey: ByteArray): KeyPair external fun blindVersionSign(ed25519SecretKey: ByteArray, timestamp: Long): ByteArray } \ No newline at end of file diff --git a/libsession/src/main/java/org/session/libsession/messaging/file_server/FileServerApi.kt b/libsession/src/main/java/org/session/libsession/messaging/file_server/FileServerApi.kt index 2543983cd9..fb9c014a15 100644 --- a/libsession/src/main/java/org/session/libsession/messaging/file_server/FileServerApi.kt +++ b/libsession/src/main/java/org/session/libsession/messaging/file_server/FileServerApi.kt @@ -151,11 +151,12 @@ object FileServerApi { val result = send(request).await() // map out the result - val json = JsonUtil.fromJson(result, Map::class.java) - val statusCode = json.getOrDefault("status_code", 0) as Int - val version = json.getOrDefault("result", "") as String - val updated = json.getOrDefault("updated", 0.0) as Double - - return VersionData(statusCode, version, updated) + return JsonUtil.fromJson(result, Map::class.java).let { + VersionData( + statusCode = it["status_code"] as? Int ?: 0, + version = it["result"] as? String ?: "", + updated = it["updated"] as? Double ?: 0.0 + ) + } } } \ No newline at end of file From a594952832ea94db4323a7c0b52327ae9ec0d8ff Mon Sep 17 00:00:00 2001 From: ThomasSession Date: Tue, 30 Jul 2024 15:14:09 +1000 Subject: [PATCH 9/9] Update libsession/src/main/java/org/session/libsession/snode/utilities/PromiseUtil.kt Co-authored-by: Andrew --- .../org/session/libsession/snode/utilities/PromiseUtil.kt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/libsession/src/main/java/org/session/libsession/snode/utilities/PromiseUtil.kt b/libsession/src/main/java/org/session/libsession/snode/utilities/PromiseUtil.kt index 9a4cd0dd5a..9c55a2282a 100644 --- a/libsession/src/main/java/org/session/libsession/snode/utilities/PromiseUtil.kt +++ b/libsession/src/main/java/org/session/libsession/snode/utilities/PromiseUtil.kt @@ -7,7 +7,7 @@ import kotlin.coroutines.suspendCoroutine suspend fun Promise.await(): T { return suspendCoroutine { cont -> - success { cont.resume(it) } - fail { cont.resumeWithException(it) } + success(cont::resume) + fail(cont::resumeWithException) } } \ No newline at end of file