mirror of
https://github.com/oxen-io/session-android.git
synced 2025-08-11 17:27:42 +00:00
Integrate shared libsession-util library (#1096)
* feat: add some config db basics and DI for it, make the user profile optional, start looking at integrate building from initial dump * update: get latest util library submodule update * refactor: fix compile for refactored API * refactor: naming consistent with library * feat: add in config storage and injection to common places, managing lifecycle of native instances * refactor: config database changes, new protos, adding in support for config base namespace queries * refactor: config query and store use the same format as other platforms * feat: add batch snode calls and try to poll from all the config namespaces * fix: add optional namespace in signature and params * feat: add raw requests for modifying expiry and getting expiries * feat: add some base config migration logic, start implementing wrappers for conversation and expiry types * chore: update libsession base * feat: start integrating conversation wrapper functions * feat: add basic conversation info volatile types and implementations, start working on tests * feat: more common library wrapper implementation and test * fix: tests and compile issues * fix: fix tests, don't use iterables * feat: add all iterators and tests * feat: add in more config factory for volatile * feat: update request responses and their appropriate processing * feat: add storage with hashes and some basic profile update logic in config factory probably move that somewhere else * feat: adding config sync functionality, refactoring jobs to execute in suspend context to do some nice coroutine execution * refactor: moving some properties around so we have access in libsession * feat: expand on the config sync job, finish basic implementation to test against * feat: add forced config sync * feat: syncs the user profile stuff for now, and errors back to placeholder instead of unknown recipient * feat: add basic message read logic for synchronizing last reads, need to modify the query to use the last seen instead of the unread count in a subquery possibly for thread display record * feat: add broken unreads everywhere * fix: unreads work now for incoming messages, need to sync conv volatile properly still * feat: batching poll responses properly and handling groups properly * fix: replace the mark read receiver (from notifications) to use the new set last seen mark read logic * feat: update to the group list branch * fix: compile errors from updating library to use latest branch, now requires cmake 3.22.1 * fix: fix the contact tests * fix: getters weren't getters properly in the config factory, fixed new onboarding from configs * feat: add the last seen * feat: start adding user groups wrapper objects * refactor: add more else branches for unimplemented types * feat: buffer the last read when in conversation * feat: add basic contact logic for setting local contact state. Need to implement handling properly * refactor: trying to just include blocked status for now in updating contacts * fix: add some more contact syncing: nicknames, approved statuses, blocked statuses * feat: start implementing hashes in shared lib and refactoring * feat: start to implement group list info classes and wrappers and refactor to use library based hashes * feat: incorporate hashes from library, more wrapper for user groups and serialization from c++ * feat: adding more serialization changes for community base info and user groups LGC * feat: adding more serialize deserialize to legacy closed groups * feat: finish serial/deserial helper * feat: just implement deserialize community info * refactor: refactor tests and wrappers to use less pointers, finish implementing user groups API * feat: finish latest wrappers fix tests and continue building default generation functions. refactor defaults to be used if no stored data blob in DB * feat: more usergroup functionality, storage functionality for checking pinned status, adding pinned status for NTS/contacts, move community info parse full url to base community, add StorageProtocol logic for group info * feat: adding user groups to the list of user configs, refactorign some of the config factory to fetch the user configs easier. Add handling for polling user group namespace * feat: implement the default user config list * feat: add user group config handling * chore: extra missed existing group * refactor: use existing lookup for objects in wrappers so they don't overwrite missing values * feat: add contacts expiry serialization/deserialization, more LGC, timestamps to add closed group encryption info (for latest tracking) * refactor: change how expiration timer works for contacts, set the expiration timer for those conversations in handling contact configs * feat: add expiration updates via config for contacts as well * feat: add almost all group editing cases, need to hook into the thread deletion for groups in the user groups * feat: open group joining should work now * feat: add groups to configs for push * fix: handling user group updates bug fix for closed groups instead of all groups * fix: open group sync persistence * feat: add in activity finish if recipient no longer exists (deleted thread) from sync * feat: support avatar removal from shared library * feat: support thread deletion and refactoring a lot of getOrCreateThread references to go via storage or assume they are correctly set to hook into the contact and volatile creation during thread creation * fix: database update not deleting in certain circumstances, storage persisting and removing the volatile convo info for thread deletion / creation, NTS hidden getter values in shared library * refactor: make update listener visibility package * refactor: update kotlin * feat: update dependencies and support outdated config messages, refactor config factory to return null configs if new configs not supported * feat: update shared library to use priority only, fix compile errors, fix group member sync problem * fix: compile error * fix: profile avatar fixes for local user now that we aren't setting local user profile key * Revert "fix: profile avatar fixes for local user now that we aren't setting local user profile key" This reverts commit3f569e3403
. * refactor: let the local number update recipient details in profile manager * fix: don't recreate thread after leaving * fix: fix up the duplicate thread creation in the message receive handler * fix: fix the placeholder rendering on new messages, add in extra context logging for adding contacts and preventing new thread creation on new messages of various types * feat: add test theme for xml layout previews * feat: add shortened hex for session IDs throughout, replace nullable getName with null in underlying contacts for individual contacts, build shared lib with release mode, remove todo, fix broken unit test * feat: setup android unit tests for verifying storage behaviours and state of shared configs * feat: adding dependencies to try and get android tests working, fixing bug with initial config not syncing properly * fix: remove hilt testing, add spy on app context storage field instead, update libsession-util to fixed sodium cmake branch * refactor: use PR version of libsession-util to test cmake build * fix: new build on normal repo * feat: new libsession util commit * refactor: remove the old custom build libsodium stuff from cmake * feat: update libsession module * fix: add legacy config subscription to the home activity to enable showing banner at any time * fix: pinned status for communities and groups, group last read time being set to snodeapi.now on finish joining * fix: some open group volatile convo fix for last read timer being set. Need to investigate further * fix: prevent blocking local number * fix: adding in more checks for open group inbox recipients before being saved to the shared configs. Prevent sending typing indicator for blocked users * fix: add blocked check for read receipt and updating expiring messages * fix: another contact recipient config library call removed for non-standard IDs * fix: another ID check * fix: don't process thread creation for user is sender && recipient (sync message) for message request responses * refactor: mark as read on open and use less buffer time * fix: finally fix the darn unread count issue by * fix: removing debug logs, adding failure error handling logs for expiry message updater, properly using the message thread ID created for the expiring messages. Process the non-thread messages properly with await in BatchMessageReceiveJob * fix: checking the last read open to message and make sure that scroll behaviour matches expected, fix the config sync job not deleting ALL old hashes only latest * refactor: try to add a retry logic to config sync job in case of snode failure * build: update submodule * fix: remove user notifications for leaving group to prevent synced device issues, don't create thread in messages for new closed groups, includei nactive groups in the deletion queries for merging group configs * feat: use blinded message count for banner also * refactor: remove some logging, don't use blinded conversations in the list * fix: don't set the read flag in update notifications, some roundabout logic for first loads and scrolling to last known positions * refactor: merge changes, re-add the group check in unapproved messages * fix: re-poll on fail in case that was breaking anything * fix: pinning groups and notifying list listeners in threadDb.setPinned * feat: add in TTL extension subrequest and builder, enable extending TTLs for all latest config messages in poll as subrequest * feat: add block to the delete all message requests, only if they're not open group inbox contacts * refactor: disable edit text for non contacts * refactor: let the user display name return "You" for local user * fix: prevent NTS self create thread on user view bind * refactor: remove populate public key cache if needed call which seems unnecessary at that point, maybe UserView refs have changed since 2020 * refactor: use just first visible instead of completely visible, merge message sender changes * fix: prevent block of users in delete all * fix: self sync sync message failures for default values * feat: update libsession-util, adjust docs, update mms and sms to use message sent timestamp instead of -1 for last read in the thread * fix: some compile issues in tests and some TODOs for things to do before merge * fix: handle recyclerview scrolled on scroll to first unread if it's the first load * fix: added more migration code for deleting unnecessary threads and groups, fixed a post-migration last seen issue on last item (current read is now), comment out actual network sync while testing migrations * feat: adding a force new configs flag and logic for timestamp handling / forced configs, fix issue with handling legacy messages * refactor: re-add the sending of configs * fix: don't add contacts if they don't exist in the profile manager * [wip] fix: trying to consolidate prof pic and key properly * feat: add logs and fix compile issue with a themes.xml entry, add removing profile picture into logic for profile manager * fix: force has sent for local user, only prevent setting last seen for open group recipients, allow empty user pics to trigger config sync in settings * fix: nts threads * fix: open group avatar loop for open groups we have left * feat: add a wrapper hash to track home diff util changes for wrapper contact recipient info, add test for dirty state in double set * feat: add a dump in there as well * refactor: more test code refactor * fix: update last seen if later than current * fix: open group threads and avatar downloads * fix: add max size and maybe fix the non-200 sub requests for batches (for 421s in particular) * fix: open group comparison issues potentially, have to update some more outgoing message open group flags for visibility of details etc * Updated to the latest libSession-util * Updated logic to delete legacy groups when kicked/left * Added the legacy group 'joined_at' value * Replaced incorrect character in JNI * Fixed an issue where the group keyPair was getting encoded incorrectly * Updated the code to ignore outdated legacy group control message changes * Updated the code to ignore messages invalidated by the config * [Review] Updated the poller to process config messages before standard * Cleaned up the outdated message logic * Fixed inverted config dropping flags * Fixed an issue where the joining a community would read all messages Stopped using a reversed RecyclerView in all cases (caused the unread issue) Updated the logic to jump to the newly sent message when sending a message (to be consistent with other platforms) Updated the logic to refresh the DB unread count when the cursor receives an update * Updated the conversation to highlight the first unread message on open * Fixed a couple of bugs with the highlighting * Fixed a bug where the user profile picture wasn't downloading correctly * feat: add all namespaces to delete all messages request and signature verification data * fix: merge namespace hashes for signature returned and * fix: import correct scroll to bottom * build: update version code and name * fix: initial contact generation fix for existing blinded contacts * fix: initial convo generation fix for existing blinded convos (?) * fix: conversation unread not doing a check for standard ID prefix * fix: thread ID not being created for legacy config messages * fix: don't treat 404 as bad snode * fix: don't add retrieve profile job if we have one for that address * build: update build code * fix: reduce attempts for downloading image, invert unreachable type check * fix: attempting to fix preventing message processing if group thread is not active for closed groups and initial contact dump only allows conversations with thread, may need further optimisations though * feat: Added an unread marker and search result focus highlighting * fix: empty set in appropriate places for current closed groups * build: update build version code * fix: fix the notifications and request at appropriate time * refactor: remove debug logging for thread create and delete * build: update build number * fix: new community doesn't break persisting config if the .add request fails * build: trying to track down broken retrieve avatar job * feat: update to latest libsession dev * fix: maybe fix avatar download for new messages * fix: 404s causing snode errors and trying to retrieve avatars that have already 404'd a lot * fix: closed group creation sets thread date to formation timestamp * build: update version code * build: update version code * build: remove debuggable release build * fix: use new permissions for external attachments * build: update version code * chore: remove debug logs * fix: tests and main thread blocking db fetch for path status view * wip: trying to track down failure to mark conversation as read in delayed group add * wip: add more logs for initial last Read sync of communities * wip: maybe the volatile is being updated with 0 on batch message receive? * fix: maybe syncing read statuses are working now * chore: remove debug logs * build: update build number * fix: trying to improve performance * fix: add close to banner * refactor: hide seed reminder in preview * build: update build number * fix: maybe requires update thread no matter what * fix: message request banner shows again * fix: android tests work again and permissions * fix: blocked contacts click handler being overridden by something * Revert "fix: blocked contacts click handler being overridden by something" This reverts commit608572fc42
. * build: update build number * refactor: remove unused dependencies and update minor for sqlcipher * fix: actually do insert contact, because otherwise name doesn't get set properly * fix: maybe fix scroll to bottom issue * build: update build number * fix: the message time and jump to message queries are more optimized * fix: maybe fix the last seen issues * build: update build number * fix: pfp broken closed groups why * fix: add admins and members as member list instead of just members * fix: exclude lgc without membership > 1 and inactive explicitly * fix: submodule update * fix: compiles with removal of iterator erase * fix: unread indicator updates properly in ConversationActivityV2 * fix: unread notifications clear and altered if any notifications exist (prevents clearing read notifications in conversation or on home screen) * refactor: profile pictures kinda broken * build: update build number * refactor: remove full hash from log * fix: isPinned threadDB call * refactor: use mutex in all libsession native calls, change timestamp * refactor: add basic support for blinded v2 prefixes --------- Co-authored-by: Morgan Pretty <morgan.t.pretty@gmail.com>
This commit is contained in:
5
libsession-util/src/main/AndroidManifest.xml
Normal file
5
libsession-util/src/main/AndroidManifest.xml
Normal file
@@ -0,0 +1,5 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
package="network.loki.messenger.libsession_util">
|
||||
|
||||
</manifest>
|
66
libsession-util/src/main/cpp/CMakeLists.txt
Normal file
66
libsession-util/src/main/cpp/CMakeLists.txt
Normal file
@@ -0,0 +1,66 @@
|
||||
# For more information about using CMake with Android Studio, read the
|
||||
# documentation: https://d.android.com/studio/projects/add-native-code.html
|
||||
|
||||
# Sets the minimum version of CMake required to build the native library.
|
||||
|
||||
cmake_minimum_required(VERSION 3.18.1)
|
||||
|
||||
# Declares and names the project.
|
||||
|
||||
project("session_util")
|
||||
|
||||
# Compiles in C++17 mode
|
||||
set(CMAKE_CXX_STANDARD 17)
|
||||
set(CMAKE_CXX_STANDARD_REQUIRED ON)
|
||||
set(CMAKE_CXX_EXTENSIONS OFF)
|
||||
|
||||
set(CMAKE_BUILD_TYPE Release)
|
||||
|
||||
# Creates and names a library, sets it as either STATIC
|
||||
# or SHARED, and provides the relative paths to its source code.
|
||||
# You can define multiple libraries, and CMake builds them for you.
|
||||
# Gradle automatically packages shared libraries with your APK.
|
||||
|
||||
set(STATIC_BUNDLE ON)
|
||||
add_subdirectory(../../../libsession-util libsession)
|
||||
|
||||
set(SOURCES
|
||||
user_profile.cpp
|
||||
user_groups.cpp
|
||||
config_base.cpp
|
||||
contacts.cpp
|
||||
conversation.cpp
|
||||
util.cpp)
|
||||
|
||||
add_library( # Sets the name of the library.
|
||||
session_util
|
||||
# Sets the library as a shared library.
|
||||
SHARED
|
||||
# Provides a relative path to your source file(s).
|
||||
${SOURCES})
|
||||
|
||||
# Searches for a specified prebuilt library and stores the path as a
|
||||
# variable. Because CMake includes system libraries in the search path by
|
||||
# default, you only need to specify the name of the public NDK library
|
||||
# you want to add. CMake verifies that the library exists before
|
||||
# completing its build.
|
||||
|
||||
find_library( # Sets the name of the path variable.
|
||||
log-lib
|
||||
|
||||
# Specifies the name of the NDK library that
|
||||
# you want CMake to locate.
|
||||
log)
|
||||
|
||||
# Specifies libraries CMake should link to your target library. You
|
||||
# can link multiple libraries, such as libraries you define in this
|
||||
# build script, prebuilt third-party libraries, or system libraries.
|
||||
|
||||
target_link_libraries( # Specifies the target library.
|
||||
session_util
|
||||
PUBLIC
|
||||
libsession::config
|
||||
libsession::crypto
|
||||
# Links the target library to the log library
|
||||
# included in the NDK.
|
||||
${log-lib})
|
154
libsession-util/src/main/cpp/config_base.cpp
Normal file
154
libsession-util/src/main/cpp/config_base.cpp
Normal file
@@ -0,0 +1,154 @@
|
||||
#include "config_base.h"
|
||||
#include "util.h"
|
||||
|
||||
extern "C" {
|
||||
JNIEXPORT jboolean JNICALL
|
||||
Java_network_loki_messenger_libsession_1util_ConfigBase_dirty(JNIEnv *env, jobject thiz) {
|
||||
std::lock_guard lock{util::util_mutex_};
|
||||
auto* configBase = ptrToConfigBase(env, thiz);
|
||||
return configBase->is_dirty();
|
||||
}
|
||||
|
||||
JNIEXPORT jboolean JNICALL
|
||||
Java_network_loki_messenger_libsession_1util_ConfigBase_needsPush(JNIEnv *env, jobject thiz) {
|
||||
std::lock_guard lock{util::util_mutex_};
|
||||
auto config = ptrToConfigBase(env, thiz);
|
||||
return config->needs_push();
|
||||
}
|
||||
|
||||
JNIEXPORT jboolean JNICALL
|
||||
Java_network_loki_messenger_libsession_1util_ConfigBase_needsDump(JNIEnv *env, jobject thiz) {
|
||||
std::lock_guard lock{util::util_mutex_};
|
||||
auto config = ptrToConfigBase(env, thiz);
|
||||
return config->needs_dump();
|
||||
}
|
||||
|
||||
JNIEXPORT jobject JNICALL
|
||||
Java_network_loki_messenger_libsession_1util_ConfigBase_push(JNIEnv *env, jobject thiz) {
|
||||
std::lock_guard lock{util::util_mutex_};
|
||||
auto config = ptrToConfigBase(env, thiz);
|
||||
auto push_tuple = config->push();
|
||||
auto to_push_str = std::get<1>(push_tuple);
|
||||
auto to_delete = std::get<2>(push_tuple);
|
||||
|
||||
jbyteArray returnByteArray = util::bytes_from_ustring(env, to_push_str);
|
||||
jlong seqNo = std::get<0>(push_tuple);
|
||||
jclass returnObjectClass = env->FindClass("network/loki/messenger/libsession_util/util/ConfigPush");
|
||||
jclass stackClass = env->FindClass("java/util/Stack");
|
||||
jmethodID methodId = env->GetMethodID(returnObjectClass, "<init>", "([BJLjava/util/List;)V");
|
||||
jmethodID stack_init = env->GetMethodID(stackClass, "<init>", "()V");
|
||||
jobject our_stack = env->NewObject(stackClass, stack_init);
|
||||
jmethodID push_stack = env->GetMethodID(stackClass, "push", "(Ljava/lang/Object;)Ljava/lang/Object;");
|
||||
for (auto entry : to_delete) {
|
||||
auto entry_jstring = env->NewStringUTF(entry.data());
|
||||
env->CallObjectMethod(our_stack, push_stack, entry_jstring);
|
||||
}
|
||||
jobject returnObject = env->NewObject(returnObjectClass, methodId, returnByteArray, seqNo, our_stack);
|
||||
return returnObject;
|
||||
}
|
||||
|
||||
JNIEXPORT void JNICALL
|
||||
Java_network_loki_messenger_libsession_1util_ConfigBase_free(JNIEnv *env, jobject thiz) {
|
||||
auto config = ptrToConfigBase(env, thiz);
|
||||
delete config;
|
||||
}
|
||||
|
||||
JNIEXPORT jbyteArray JNICALL
|
||||
Java_network_loki_messenger_libsession_1util_ConfigBase_dump(JNIEnv *env, jobject thiz) {
|
||||
std::lock_guard lock{util::util_mutex_};
|
||||
auto config = ptrToConfigBase(env, thiz);
|
||||
auto dumped = config->dump();
|
||||
jbyteArray bytes = util::bytes_from_ustring(env, dumped);
|
||||
return bytes;
|
||||
}
|
||||
|
||||
JNIEXPORT jstring JNICALL
|
||||
Java_network_loki_messenger_libsession_1util_ConfigBase_encryptionDomain(JNIEnv *env,
|
||||
jobject thiz) {
|
||||
auto conf = ptrToConfigBase(env, thiz);
|
||||
return env->NewStringUTF(conf->encryption_domain());
|
||||
}
|
||||
|
||||
JNIEXPORT void JNICALL
|
||||
Java_network_loki_messenger_libsession_1util_ConfigBase_confirmPushed(JNIEnv *env, jobject thiz,
|
||||
jlong seq_no,
|
||||
jstring new_hash_jstring) {
|
||||
std::lock_guard lock{util::util_mutex_};
|
||||
auto conf = ptrToConfigBase(env, thiz);
|
||||
auto new_hash = env->GetStringUTFChars(new_hash_jstring, nullptr);
|
||||
conf->confirm_pushed(seq_no, new_hash);
|
||||
env->ReleaseStringUTFChars(new_hash_jstring, new_hash);
|
||||
}
|
||||
|
||||
#pragma clang diagnostic push
|
||||
#pragma ide diagnostic ignored "bugprone-reserved-identifier"
|
||||
JNIEXPORT jint JNICALL
|
||||
Java_network_loki_messenger_libsession_1util_ConfigBase_merge___3Lkotlin_Pair_2(JNIEnv *env, jobject thiz,
|
||||
jobjectArray to_merge) {
|
||||
std::lock_guard lock{util::util_mutex_};
|
||||
auto conf = ptrToConfigBase(env, thiz);
|
||||
size_t number = env->GetArrayLength(to_merge);
|
||||
std::vector<std::pair<std::string,session::ustring>> configs = {};
|
||||
for (int i = 0; i < number; i++) {
|
||||
auto jElement = (jobject) env->GetObjectArrayElement(to_merge, i);
|
||||
auto pair = extractHashAndData(env, jElement);
|
||||
configs.push_back(pair);
|
||||
}
|
||||
return conf->merge(configs);
|
||||
}
|
||||
|
||||
JNIEXPORT jint JNICALL
|
||||
Java_network_loki_messenger_libsession_1util_ConfigBase_merge__Lkotlin_Pair_2(JNIEnv *env, jobject thiz,
|
||||
jobject to_merge) {
|
||||
std::lock_guard lock{util::util_mutex_};
|
||||
auto conf = ptrToConfigBase(env, thiz);
|
||||
std::vector<std::pair<std::string, session::ustring>> configs = {extractHashAndData(env, to_merge)};
|
||||
return conf->merge(configs);
|
||||
}
|
||||
|
||||
#pragma clang diagnostic pop
|
||||
}
|
||||
extern "C"
|
||||
JNIEXPORT jint JNICALL
|
||||
Java_network_loki_messenger_libsession_1util_ConfigBase_configNamespace(JNIEnv *env, jobject thiz) {
|
||||
auto conf = ptrToConfigBase(env, thiz);
|
||||
return (std::int16_t) conf->storage_namespace();
|
||||
}
|
||||
extern "C"
|
||||
JNIEXPORT jclass JNICALL
|
||||
Java_network_loki_messenger_libsession_1util_ConfigBase_00024Companion_kindFor(JNIEnv *env,
|
||||
jobject thiz,
|
||||
jint config_namespace) {
|
||||
auto user_class = env->FindClass("network/loki/messenger/libsession_util/UserProfile");
|
||||
auto contact_class = env->FindClass("network/loki/messenger/libsession_util/Contacts");
|
||||
auto convo_volatile_class = env->FindClass("network/loki/messenger/libsession_util/ConversationVolatileConfig");
|
||||
auto group_list_class = env->FindClass("network/loki/messenger/libsession_util/UserGroupsConfig");
|
||||
switch (config_namespace) {
|
||||
case (int)session::config::Namespace::UserProfile:
|
||||
return user_class;
|
||||
case (int)session::config::Namespace::Contacts:
|
||||
return contact_class;
|
||||
case (int)session::config::Namespace::ConvoInfoVolatile:
|
||||
return convo_volatile_class;
|
||||
case (int)session::config::Namespace::UserGroups:
|
||||
return group_list_class;
|
||||
default:
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
extern "C"
|
||||
JNIEXPORT jobject JNICALL
|
||||
Java_network_loki_messenger_libsession_1util_ConfigBase_currentHashes(JNIEnv *env, jobject thiz) {
|
||||
std::lock_guard lock{util::util_mutex_};
|
||||
auto conf = ptrToConfigBase(env, thiz);
|
||||
jclass stack = env->FindClass("java/util/Stack");
|
||||
jmethodID init = env->GetMethodID(stack, "<init>", "()V");
|
||||
jobject our_stack = env->NewObject(stack, init);
|
||||
jmethodID push = env->GetMethodID(stack, "push", "(Ljava/lang/Object;)Ljava/lang/Object;");
|
||||
auto vec = conf->current_hashes();
|
||||
for (std::string element: vec) {
|
||||
env->CallObjectMethod(our_stack, push, env->NewStringUTF(element.data()));
|
||||
}
|
||||
return our_stack;
|
||||
}
|
28
libsession-util/src/main/cpp/config_base.h
Normal file
28
libsession-util/src/main/cpp/config_base.h
Normal file
@@ -0,0 +1,28 @@
|
||||
#ifndef SESSION_ANDROID_CONFIG_BASE_H
|
||||
#define SESSION_ANDROID_CONFIG_BASE_H
|
||||
|
||||
#include "session/config/base.hpp"
|
||||
#include "util.h"
|
||||
#include <jni.h>
|
||||
#include <string>
|
||||
|
||||
inline session::config::ConfigBase* ptrToConfigBase(JNIEnv *env, jobject obj) {
|
||||
jclass baseClass = env->FindClass("network/loki/messenger/libsession_util/ConfigBase");
|
||||
jfieldID pointerField = env->GetFieldID(baseClass, "pointer", "J");
|
||||
return (session::config::ConfigBase*) env->GetLongField(obj, pointerField);
|
||||
}
|
||||
|
||||
inline std::pair<std::string, session::ustring> extractHashAndData(JNIEnv *env, jobject kotlin_pair) {
|
||||
jclass pair = env->FindClass("kotlin/Pair");
|
||||
jfieldID first = env->GetFieldID(pair, "first", "Ljava/lang/Object;");
|
||||
jfieldID second = env->GetFieldID(pair, "second", "Ljava/lang/Object;");
|
||||
jstring hash_as_jstring = static_cast<jstring>(env->GetObjectField(kotlin_pair, first));
|
||||
jbyteArray data_as_jbytes = static_cast<jbyteArray>(env->GetObjectField(kotlin_pair, second));
|
||||
auto hash_as_string = env->GetStringUTFChars(hash_as_jstring, nullptr);
|
||||
auto data_as_ustring = util::ustring_from_bytes(env, data_as_jbytes);
|
||||
auto ret_pair = std::pair<std::string, session::ustring>{hash_as_string, data_as_ustring};
|
||||
env->ReleaseStringUTFChars(hash_as_jstring, hash_as_string);
|
||||
return ret_pair;
|
||||
}
|
||||
|
||||
#endif
|
100
libsession-util/src/main/cpp/contacts.cpp
Normal file
100
libsession-util/src/main/cpp/contacts.cpp
Normal file
@@ -0,0 +1,100 @@
|
||||
#include "contacts.h"
|
||||
#include "util.h"
|
||||
|
||||
extern "C"
|
||||
JNIEXPORT jobject JNICALL
|
||||
Java_network_loki_messenger_libsession_1util_Contacts_get(JNIEnv *env, jobject thiz,
|
||||
jstring session_id) {
|
||||
std::lock_guard lock{util::util_mutex_};
|
||||
auto contacts = ptrToContacts(env, thiz);
|
||||
auto session_id_chars = env->GetStringUTFChars(session_id, nullptr);
|
||||
auto contact = contacts->get(session_id_chars);
|
||||
env->ReleaseStringUTFChars(session_id, session_id_chars);
|
||||
if (!contact) return nullptr;
|
||||
jobject j_contact = serialize_contact(env, contact.value());
|
||||
return j_contact;
|
||||
}
|
||||
|
||||
extern "C"
|
||||
JNIEXPORT jobject JNICALL
|
||||
Java_network_loki_messenger_libsession_1util_Contacts_getOrConstruct(JNIEnv *env, jobject thiz,
|
||||
jstring session_id) {
|
||||
std::lock_guard lock{util::util_mutex_};
|
||||
auto contacts = ptrToContacts(env, thiz);
|
||||
auto session_id_chars = env->GetStringUTFChars(session_id, nullptr);
|
||||
auto contact = contacts->get_or_construct(session_id_chars);
|
||||
env->ReleaseStringUTFChars(session_id, session_id_chars);
|
||||
return serialize_contact(env, contact);
|
||||
}
|
||||
|
||||
extern "C"
|
||||
JNIEXPORT void JNICALL
|
||||
Java_network_loki_messenger_libsession_1util_Contacts_set(JNIEnv *env, jobject thiz,
|
||||
jobject contact) {
|
||||
std::lock_guard lock{util::util_mutex_};
|
||||
auto contacts = ptrToContacts(env, thiz);
|
||||
auto contact_info = deserialize_contact(env, contact, contacts);
|
||||
contacts->set(contact_info);
|
||||
}
|
||||
|
||||
extern "C"
|
||||
JNIEXPORT jboolean JNICALL
|
||||
Java_network_loki_messenger_libsession_1util_Contacts_erase(JNIEnv *env, jobject thiz,
|
||||
jstring session_id) {
|
||||
std::lock_guard lock{util::util_mutex_};
|
||||
auto contacts = ptrToContacts(env, thiz);
|
||||
auto session_id_chars = env->GetStringUTFChars(session_id, nullptr);
|
||||
|
||||
bool result = contacts->erase(session_id_chars);
|
||||
env->ReleaseStringUTFChars(session_id, session_id_chars);
|
||||
return result;
|
||||
}
|
||||
extern "C"
|
||||
#pragma clang diagnostic push
|
||||
#pragma ide diagnostic ignored "bugprone-reserved-identifier"
|
||||
JNIEXPORT jobject JNICALL
|
||||
Java_network_loki_messenger_libsession_1util_Contacts_00024Companion_newInstance___3B(JNIEnv *env,
|
||||
jobject thiz,
|
||||
jbyteArray ed25519_secret_key) {
|
||||
std::lock_guard lock{util::util_mutex_};
|
||||
auto secret_key = util::ustring_from_bytes(env, ed25519_secret_key);
|
||||
auto* contacts = new session::config::Contacts(secret_key, std::nullopt);
|
||||
|
||||
jclass contactsClass = env->FindClass("network/loki/messenger/libsession_util/Contacts");
|
||||
jmethodID constructor = env->GetMethodID(contactsClass, "<init>", "(J)V");
|
||||
jobject newConfig = env->NewObject(contactsClass, constructor, reinterpret_cast<jlong>(contacts));
|
||||
|
||||
return newConfig;
|
||||
}
|
||||
extern "C"
|
||||
JNIEXPORT jobject JNICALL
|
||||
Java_network_loki_messenger_libsession_1util_Contacts_00024Companion_newInstance___3B_3B(
|
||||
JNIEnv *env, jobject thiz, jbyteArray ed25519_secret_key, jbyteArray initial_dump) {
|
||||
std::lock_guard lock{util::util_mutex_};
|
||||
auto secret_key = util::ustring_from_bytes(env, ed25519_secret_key);
|
||||
auto initial = util::ustring_from_bytes(env, initial_dump);
|
||||
|
||||
auto* contacts = new session::config::Contacts(secret_key, initial);
|
||||
|
||||
jclass contactsClass = env->FindClass("network/loki/messenger/libsession_util/Contacts");
|
||||
jmethodID constructor = env->GetMethodID(contactsClass, "<init>", "(J)V");
|
||||
jobject newConfig = env->NewObject(contactsClass, constructor, reinterpret_cast<jlong>(contacts));
|
||||
|
||||
return newConfig;
|
||||
}
|
||||
#pragma clang diagnostic pop
|
||||
extern "C"
|
||||
JNIEXPORT jobject JNICALL
|
||||
Java_network_loki_messenger_libsession_1util_Contacts_all(JNIEnv *env, jobject thiz) {
|
||||
std::lock_guard lock{util::util_mutex_};
|
||||
auto contacts = ptrToContacts(env, thiz);
|
||||
jclass stack = env->FindClass("java/util/Stack");
|
||||
jmethodID init = env->GetMethodID(stack, "<init>", "()V");
|
||||
jobject our_stack = env->NewObject(stack, init);
|
||||
jmethodID push = env->GetMethodID(stack, "push", "(Ljava/lang/Object;)Ljava/lang/Object;");
|
||||
for (const auto& contact : *contacts) {
|
||||
auto contact_obj = serialize_contact(env, contact);
|
||||
env->CallObjectMethod(our_stack, push, contact_obj);
|
||||
}
|
||||
return our_stack;
|
||||
}
|
109
libsession-util/src/main/cpp/contacts.h
Normal file
109
libsession-util/src/main/cpp/contacts.h
Normal file
@@ -0,0 +1,109 @@
|
||||
#ifndef SESSION_ANDROID_CONTACTS_H
|
||||
#define SESSION_ANDROID_CONTACTS_H
|
||||
|
||||
#include <jni.h>
|
||||
#include "session/config/contacts.hpp"
|
||||
#include "util.h"
|
||||
|
||||
inline session::config::Contacts *ptrToContacts(JNIEnv *env, jobject obj) {
|
||||
jclass contactsClass = env->FindClass("network/loki/messenger/libsession_util/Contacts");
|
||||
jfieldID pointerField = env->GetFieldID(contactsClass, "pointer", "J");
|
||||
return (session::config::Contacts *) env->GetLongField(obj, pointerField);
|
||||
}
|
||||
|
||||
inline jobject serialize_contact(JNIEnv *env, session::config::contact_info info) {
|
||||
jclass contactClass = env->FindClass("network/loki/messenger/libsession_util/util/Contact");
|
||||
jmethodID constructor = env->GetMethodID(contactClass, "<init>", "(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;ZZZLnetwork/loki/messenger/libsession_util/util/UserPic;ILnetwork/loki/messenger/libsession_util/util/ExpiryMode;)V");
|
||||
jstring id = env->NewStringUTF(info.session_id.data());
|
||||
jstring name = env->NewStringUTF(info.name.data());
|
||||
jstring nickname = env->NewStringUTF(info.nickname.data());
|
||||
jboolean approved, approvedMe, blocked;
|
||||
approved = info.approved;
|
||||
approvedMe = info.approved_me;
|
||||
blocked = info.blocked;
|
||||
auto created = info.created;
|
||||
jobject profilePic = util::serialize_user_pic(env, info.profile_picture);
|
||||
jobject returnObj = env->NewObject(contactClass, constructor, id, name, nickname, approved,
|
||||
approvedMe, blocked, profilePic, info.priority,
|
||||
util::serialize_expiry(env, info.exp_mode, info.exp_timer));
|
||||
return returnObj;
|
||||
}
|
||||
|
||||
inline session::config::contact_info
|
||||
deserialize_contact(JNIEnv *env, jobject info, session::config::Contacts *conf) {
|
||||
jclass contactClass = env->FindClass("network/loki/messenger/libsession_util/util/Contact");
|
||||
|
||||
jfieldID getId, getName, getNick, getApproved, getApprovedMe, getBlocked, getUserPic, getPriority, getExpiry, getHidden;
|
||||
getId = env->GetFieldID(contactClass, "id", "Ljava/lang/String;");
|
||||
getName = env->GetFieldID(contactClass, "name", "Ljava/lang/String;");
|
||||
getNick = env->GetFieldID(contactClass, "nickname", "Ljava/lang/String;");
|
||||
getApproved = env->GetFieldID(contactClass, "approved", "Z");
|
||||
getApprovedMe = env->GetFieldID(contactClass, "approvedMe", "Z");
|
||||
getBlocked = env->GetFieldID(contactClass, "blocked", "Z");
|
||||
getUserPic = env->GetFieldID(contactClass, "profilePicture",
|
||||
"Lnetwork/loki/messenger/libsession_util/util/UserPic;");
|
||||
getPriority = env->GetFieldID(contactClass, "priority", "I");
|
||||
getExpiry = env->GetFieldID(contactClass, "expiryMode", "Lnetwork/loki/messenger/libsession_util/util/ExpiryMode;");
|
||||
jstring name, nickname, session_id;
|
||||
session_id = static_cast<jstring>(env->GetObjectField(info, getId));
|
||||
name = static_cast<jstring>(env->GetObjectField(info, getName));
|
||||
nickname = static_cast<jstring>(env->GetObjectField(info, getNick));
|
||||
bool approved, approvedMe, blocked, hidden;
|
||||
int priority = env->GetIntField(info, getPriority);
|
||||
approved = env->GetBooleanField(info, getApproved);
|
||||
approvedMe = env->GetBooleanField(info, getApprovedMe);
|
||||
blocked = env->GetBooleanField(info, getBlocked);
|
||||
jobject user_pic = env->GetObjectField(info, getUserPic);
|
||||
jobject expiry_mode = env->GetObjectField(info, getExpiry);
|
||||
|
||||
auto expiry_pair = util::deserialize_expiry(env, expiry_mode);
|
||||
|
||||
std::string url;
|
||||
session::ustring key;
|
||||
|
||||
if (user_pic != nullptr) {
|
||||
auto deserialized_pic = util::deserialize_user_pic(env, user_pic);
|
||||
auto url_jstring = deserialized_pic.first;
|
||||
auto url_bytes = env->GetStringUTFChars(url_jstring, nullptr);
|
||||
url = std::string(url_bytes);
|
||||
env->ReleaseStringUTFChars(url_jstring, url_bytes);
|
||||
key = util::ustring_from_bytes(env, deserialized_pic.second);
|
||||
}
|
||||
|
||||
auto session_id_bytes = env->GetStringUTFChars(session_id, nullptr);
|
||||
auto name_bytes = name ? env->GetStringUTFChars(name, nullptr) : nullptr;
|
||||
auto nickname_bytes = nickname ? env->GetStringUTFChars(nickname, nullptr) : nullptr;
|
||||
|
||||
auto contact_info = conf->get_or_construct(session_id_bytes);
|
||||
if (name_bytes) {
|
||||
contact_info.name = name_bytes;
|
||||
}
|
||||
if (nickname_bytes) {
|
||||
contact_info.nickname = nickname_bytes;
|
||||
}
|
||||
contact_info.approved = approved;
|
||||
contact_info.approved_me = approvedMe;
|
||||
contact_info.blocked = blocked;
|
||||
if (!url.empty() && !key.empty()) {
|
||||
contact_info.profile_picture = session::config::profile_pic(url, key);
|
||||
} else {
|
||||
contact_info.profile_picture = session::config::profile_pic();
|
||||
}
|
||||
|
||||
env->ReleaseStringUTFChars(session_id, session_id_bytes);
|
||||
if (name_bytes) {
|
||||
env->ReleaseStringUTFChars(name, name_bytes);
|
||||
}
|
||||
if (nickname_bytes) {
|
||||
env->ReleaseStringUTFChars(nickname, nickname_bytes);
|
||||
}
|
||||
|
||||
contact_info.priority = priority;
|
||||
contact_info.exp_mode = expiry_pair.first;
|
||||
contact_info.exp_timer = std::chrono::seconds(expiry_pair.second);
|
||||
|
||||
return contact_info;
|
||||
}
|
||||
|
||||
|
||||
#endif //SESSION_ANDROID_CONTACTS_H
|
352
libsession-util/src/main/cpp/conversation.cpp
Normal file
352
libsession-util/src/main/cpp/conversation.cpp
Normal file
@@ -0,0 +1,352 @@
|
||||
#include <jni.h>
|
||||
#include "conversation.h"
|
||||
|
||||
#pragma clang diagnostic push
|
||||
|
||||
extern "C"
|
||||
#pragma ide diagnostic ignored "bugprone-reserved-identifier"
|
||||
JNIEXPORT jobject JNICALL
|
||||
Java_network_loki_messenger_libsession_1util_ConversationVolatileConfig_00024Companion_newInstance___3B(
|
||||
JNIEnv *env, jobject thiz, jbyteArray ed25519_secret_key) {
|
||||
std::lock_guard lock{util::util_mutex_};
|
||||
auto secret_key = util::ustring_from_bytes(env, ed25519_secret_key);
|
||||
auto* convo_info_volatile = new session::config::ConvoInfoVolatile(secret_key, std::nullopt);
|
||||
|
||||
jclass convoClass = env->FindClass("network/loki/messenger/libsession_util/ConversationVolatileConfig");
|
||||
jmethodID constructor = env->GetMethodID(convoClass, "<init>", "(J)V");
|
||||
jobject newConfig = env->NewObject(convoClass, constructor, reinterpret_cast<jlong>(convo_info_volatile));
|
||||
|
||||
return newConfig;
|
||||
}
|
||||
extern "C"
|
||||
#pragma ide diagnostic ignored "bugprone-reserved-identifier"
|
||||
JNIEXPORT jobject JNICALL
|
||||
Java_network_loki_messenger_libsession_1util_ConversationVolatileConfig_00024Companion_newInstance___3B_3B(
|
||||
JNIEnv *env, jobject thiz, jbyteArray ed25519_secret_key, jbyteArray initial_dump) {
|
||||
std::lock_guard lock{util::util_mutex_};
|
||||
auto secret_key = util::ustring_from_bytes(env, ed25519_secret_key);
|
||||
auto initial = util::ustring_from_bytes(env, initial_dump);
|
||||
auto* convo_info_volatile = new session::config::ConvoInfoVolatile(secret_key, initial);
|
||||
|
||||
jclass convoClass = env->FindClass("network/loki/messenger/libsession_util/ConversationVolatileConfig");
|
||||
jmethodID constructor = env->GetMethodID(convoClass, "<init>", "(J)V");
|
||||
jobject newConfig = env->NewObject(convoClass, constructor, reinterpret_cast<jlong>(convo_info_volatile));
|
||||
|
||||
return newConfig;
|
||||
}
|
||||
|
||||
|
||||
|
||||
extern "C"
|
||||
JNIEXPORT jint JNICALL
|
||||
Java_network_loki_messenger_libsession_1util_ConversationVolatileConfig_sizeOneToOnes(JNIEnv *env,
|
||||
jobject thiz) {
|
||||
std::lock_guard lock{util::util_mutex_};
|
||||
auto conversations = ptrToConvoInfo(env, thiz);
|
||||
return conversations->size_1to1();
|
||||
}
|
||||
|
||||
#pragma clang diagnostic pop
|
||||
extern "C"
|
||||
JNIEXPORT jint JNICALL
|
||||
Java_network_loki_messenger_libsession_1util_ConversationVolatileConfig_eraseAll(JNIEnv *env,
|
||||
jobject thiz,
|
||||
jobject predicate) {
|
||||
std::lock_guard lock{util::util_mutex_};
|
||||
auto conversations = ptrToConvoInfo(env, thiz);
|
||||
|
||||
jclass predicate_class = env->FindClass("kotlin/jvm/functions/Function1");
|
||||
jmethodID predicate_call = env->GetMethodID(predicate_class, "invoke", "(Ljava/lang/Object;)Ljava/lang/Object;");
|
||||
|
||||
jclass bool_class = env->FindClass("java/lang/Boolean");
|
||||
jmethodID bool_get = env->GetMethodID(bool_class, "booleanValue", "()Z");
|
||||
|
||||
int removed = 0;
|
||||
auto to_erase = std::vector<session::config::convo::any>();
|
||||
|
||||
for (auto it = conversations->begin(); it != conversations->end(); ++it) {
|
||||
auto result = env->CallObjectMethod(predicate, predicate_call, serialize_any(env, *it));
|
||||
bool bool_result = env->CallBooleanMethod(result, bool_get);
|
||||
if (bool_result) {
|
||||
to_erase.push_back(*it);
|
||||
}
|
||||
}
|
||||
|
||||
for (auto & entry : to_erase) {
|
||||
if (conversations->erase(entry)) {
|
||||
removed++;
|
||||
}
|
||||
}
|
||||
|
||||
return removed;
|
||||
}
|
||||
|
||||
extern "C"
|
||||
JNIEXPORT jint JNICALL
|
||||
Java_network_loki_messenger_libsession_1util_ConversationVolatileConfig_size(JNIEnv *env,
|
||||
jobject thiz) {
|
||||
std::lock_guard lock{util::util_mutex_};
|
||||
auto config = ptrToConvoInfo(env, thiz);
|
||||
return (jint)config->size();
|
||||
}
|
||||
extern "C"
|
||||
JNIEXPORT jboolean JNICALL
|
||||
Java_network_loki_messenger_libsession_1util_ConversationVolatileConfig_empty(JNIEnv *env,
|
||||
jobject thiz) {
|
||||
std::lock_guard lock{util::util_mutex_};
|
||||
auto config = ptrToConvoInfo(env, thiz);
|
||||
return config->empty();
|
||||
}
|
||||
extern "C"
|
||||
JNIEXPORT void JNICALL
|
||||
Java_network_loki_messenger_libsession_1util_ConversationVolatileConfig_set(JNIEnv *env,
|
||||
jobject thiz,
|
||||
jobject to_store) {
|
||||
std::lock_guard lock{util::util_mutex_};
|
||||
|
||||
auto convos = ptrToConvoInfo(env, thiz);
|
||||
|
||||
jclass one_to_one = env->FindClass("network/loki/messenger/libsession_util/util/Conversation$OneToOne");
|
||||
jclass open_group = env->FindClass("network/loki/messenger/libsession_util/util/Conversation$Community");
|
||||
jclass legacy_closed_group = env->FindClass("network/loki/messenger/libsession_util/util/Conversation$LegacyGroup");
|
||||
|
||||
jclass to_store_class = env->GetObjectClass(to_store);
|
||||
if (env->IsSameObject(to_store_class, one_to_one)) {
|
||||
// store as 1to1
|
||||
convos->set(deserialize_one_to_one(env, to_store, convos));
|
||||
} else if (env->IsSameObject(to_store_class,open_group)) {
|
||||
// store as open_group
|
||||
convos->set(deserialize_community(env, to_store, convos));
|
||||
} else if (env->IsSameObject(to_store_class,legacy_closed_group)) {
|
||||
// store as legacy_closed_group
|
||||
convos->set(deserialize_legacy_closed_group(env, to_store, convos));
|
||||
}
|
||||
}
|
||||
extern "C"
|
||||
JNIEXPORT jobject JNICALL
|
||||
Java_network_loki_messenger_libsession_1util_ConversationVolatileConfig_getOneToOne(JNIEnv *env,
|
||||
jobject thiz,
|
||||
jstring pub_key_hex) {
|
||||
std::lock_guard lock{util::util_mutex_};
|
||||
auto convos = ptrToConvoInfo(env, thiz);
|
||||
auto param = env->GetStringUTFChars(pub_key_hex, nullptr);
|
||||
auto internal = convos->get_1to1(param);
|
||||
env->ReleaseStringUTFChars(pub_key_hex, param);
|
||||
if (internal) {
|
||||
return serialize_one_to_one(env, *internal);
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
extern "C"
|
||||
JNIEXPORT jobject JNICALL
|
||||
Java_network_loki_messenger_libsession_1util_ConversationVolatileConfig_getOrConstructOneToOne(
|
||||
JNIEnv *env, jobject thiz, jstring pub_key_hex) {
|
||||
std::lock_guard lock{util::util_mutex_};
|
||||
auto convos = ptrToConvoInfo(env, thiz);
|
||||
auto param = env->GetStringUTFChars(pub_key_hex, nullptr);
|
||||
auto internal = convos->get_or_construct_1to1(param);
|
||||
env->ReleaseStringUTFChars(pub_key_hex, param);
|
||||
return serialize_one_to_one(env, internal);
|
||||
}
|
||||
extern "C"
|
||||
JNIEXPORT jboolean JNICALL
|
||||
Java_network_loki_messenger_libsession_1util_ConversationVolatileConfig_eraseOneToOne(JNIEnv *env,
|
||||
jobject thiz,
|
||||
jstring pub_key_hex) {
|
||||
std::lock_guard lock{util::util_mutex_};
|
||||
auto convos = ptrToConvoInfo(env, thiz);
|
||||
auto param = env->GetStringUTFChars(pub_key_hex, nullptr);
|
||||
auto result = convos->erase_1to1(param);
|
||||
env->ReleaseStringUTFChars(pub_key_hex, param);
|
||||
return result;
|
||||
}
|
||||
|
||||
extern "C"
|
||||
JNIEXPORT jobject JNICALL
|
||||
Java_network_loki_messenger_libsession_1util_ConversationVolatileConfig_getCommunity__Ljava_lang_String_2Ljava_lang_String_2(
|
||||
JNIEnv *env, jobject thiz, jstring base_url, jstring room) {
|
||||
std::lock_guard lock{util::util_mutex_};
|
||||
auto convos = ptrToConvoInfo(env, thiz);
|
||||
auto base_url_chars = env->GetStringUTFChars(base_url, nullptr);
|
||||
auto room_chars = env->GetStringUTFChars(room, nullptr);
|
||||
auto open = convos->get_community(base_url_chars, room_chars);
|
||||
if (open) {
|
||||
auto serialized = serialize_open_group(env, *open);
|
||||
return serialized;
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
extern "C"
|
||||
JNIEXPORT jobject JNICALL
|
||||
Java_network_loki_messenger_libsession_1util_ConversationVolatileConfig_getOrConstructCommunity__Ljava_lang_String_2Ljava_lang_String_2_3B(
|
||||
JNIEnv *env, jobject thiz, jstring base_url, jstring room, jbyteArray pub_key) {
|
||||
std::lock_guard lock{util::util_mutex_};
|
||||
auto convos = ptrToConvoInfo(env, thiz);
|
||||
auto base_url_chars = env->GetStringUTFChars(base_url, nullptr);
|
||||
auto room_chars = env->GetStringUTFChars(room, nullptr);
|
||||
auto pub_key_ustring = util::ustring_from_bytes(env, pub_key);
|
||||
auto open = convos->get_or_construct_community(base_url_chars, room_chars, pub_key_ustring);
|
||||
auto serialized = serialize_open_group(env, open);
|
||||
return serialized;
|
||||
}
|
||||
extern "C"
|
||||
JNIEXPORT jobject JNICALL
|
||||
Java_network_loki_messenger_libsession_1util_ConversationVolatileConfig_getOrConstructCommunity__Ljava_lang_String_2Ljava_lang_String_2Ljava_lang_String_2(
|
||||
JNIEnv *env, jobject thiz, jstring base_url, jstring room, jstring pub_key_hex) {
|
||||
std::lock_guard lock{util::util_mutex_};
|
||||
auto convos = ptrToConvoInfo(env, thiz);
|
||||
auto base_url_chars = env->GetStringUTFChars(base_url, nullptr);
|
||||
auto room_chars = env->GetStringUTFChars(room, nullptr);
|
||||
auto hex_chars = env->GetStringUTFChars(pub_key_hex, nullptr);
|
||||
auto open = convos->get_or_construct_community(base_url_chars, room_chars, hex_chars);
|
||||
env->ReleaseStringUTFChars(base_url, base_url_chars);
|
||||
env->ReleaseStringUTFChars(room, room_chars);
|
||||
env->ReleaseStringUTFChars(pub_key_hex, hex_chars);
|
||||
auto serialized = serialize_open_group(env, open);
|
||||
return serialized;
|
||||
}
|
||||
extern "C"
|
||||
JNIEXPORT jboolean JNICALL
|
||||
Java_network_loki_messenger_libsession_1util_ConversationVolatileConfig_eraseCommunity__Lnetwork_loki_messenger_libsession_1util_util_Conversation_Community_2(JNIEnv *env,
|
||||
jobject thiz,
|
||||
jobject open_group) {
|
||||
std::lock_guard lock{util::util_mutex_};
|
||||
auto convos = ptrToConvoInfo(env, thiz);
|
||||
auto deserialized = deserialize_community(env, open_group, convos);
|
||||
return convos->erase(deserialized);
|
||||
}
|
||||
extern "C"
|
||||
JNIEXPORT jboolean JNICALL
|
||||
Java_network_loki_messenger_libsession_1util_ConversationVolatileConfig_eraseCommunity__Ljava_lang_String_2Ljava_lang_String_2(
|
||||
JNIEnv *env, jobject thiz, jstring base_url, jstring room) {
|
||||
std::lock_guard lock{util::util_mutex_};
|
||||
auto convos = ptrToConvoInfo(env, thiz);
|
||||
auto base_url_chars = env->GetStringUTFChars(base_url, nullptr);
|
||||
auto room_chars = env->GetStringUTFChars(room, nullptr);
|
||||
auto result = convos->erase_community(base_url_chars, room_chars);
|
||||
env->ReleaseStringUTFChars(base_url, base_url_chars);
|
||||
env->ReleaseStringUTFChars(room, room_chars);
|
||||
return result;
|
||||
}
|
||||
extern "C"
|
||||
JNIEXPORT jobject JNICALL
|
||||
Java_network_loki_messenger_libsession_1util_ConversationVolatileConfig_getLegacyClosedGroup(
|
||||
JNIEnv *env, jobject thiz, jstring group_id) {
|
||||
std::lock_guard lock{util::util_mutex_};
|
||||
auto convos = ptrToConvoInfo(env, thiz);
|
||||
auto id_chars = env->GetStringUTFChars(group_id, nullptr);
|
||||
auto lgc = convos->get_legacy_group(id_chars);
|
||||
env->ReleaseStringUTFChars(group_id, id_chars);
|
||||
if (lgc) {
|
||||
auto serialized = serialize_legacy_group(env, *lgc);
|
||||
return serialized;
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
extern "C"
|
||||
JNIEXPORT jobject JNICALL
|
||||
Java_network_loki_messenger_libsession_1util_ConversationVolatileConfig_getOrConstructLegacyGroup(
|
||||
JNIEnv *env, jobject thiz, jstring group_id) {
|
||||
std::lock_guard lock{util::util_mutex_};
|
||||
auto convos = ptrToConvoInfo(env, thiz);
|
||||
auto id_chars = env->GetStringUTFChars(group_id, nullptr);
|
||||
auto lgc = convos->get_or_construct_legacy_group(id_chars);
|
||||
env->ReleaseStringUTFChars(group_id, id_chars);
|
||||
return serialize_legacy_group(env, lgc);
|
||||
}
|
||||
extern "C"
|
||||
JNIEXPORT jboolean JNICALL
|
||||
Java_network_loki_messenger_libsession_1util_ConversationVolatileConfig_eraseLegacyClosedGroup(
|
||||
JNIEnv *env, jobject thiz, jstring group_id) {
|
||||
std::lock_guard lock{util::util_mutex_};
|
||||
auto convos = ptrToConvoInfo(env, thiz);
|
||||
auto id_chars = env->GetStringUTFChars(group_id, nullptr);
|
||||
auto result = convos->erase_legacy_group(id_chars);
|
||||
env->ReleaseStringUTFChars(group_id, id_chars);
|
||||
return result;
|
||||
}
|
||||
extern "C"
|
||||
JNIEXPORT jboolean JNICALL
|
||||
Java_network_loki_messenger_libsession_1util_ConversationVolatileConfig_erase(JNIEnv *env,
|
||||
jobject thiz,
|
||||
jobject conversation) {
|
||||
std::lock_guard lock{util::util_mutex_};
|
||||
auto convos = ptrToConvoInfo(env, thiz);
|
||||
auto deserialized = deserialize_any(env, conversation, convos);
|
||||
if (!deserialized.has_value()) return false;
|
||||
return convos->erase(*deserialized);
|
||||
}
|
||||
extern "C"
|
||||
JNIEXPORT jint JNICALL
|
||||
Java_network_loki_messenger_libsession_1util_ConversationVolatileConfig_sizeCommunities(JNIEnv *env,
|
||||
jobject thiz) {
|
||||
std::lock_guard lock{util::util_mutex_};
|
||||
auto convos = ptrToConvoInfo(env, thiz);
|
||||
return convos->size_communities();
|
||||
}
|
||||
extern "C"
|
||||
JNIEXPORT jint JNICALL
|
||||
Java_network_loki_messenger_libsession_1util_ConversationVolatileConfig_sizeLegacyClosedGroups(
|
||||
JNIEnv *env, jobject thiz) {
|
||||
std::lock_guard lock{util::util_mutex_};
|
||||
auto convos = ptrToConvoInfo(env, thiz);
|
||||
return convos->size_legacy_groups();
|
||||
}
|
||||
extern "C"
|
||||
JNIEXPORT jobject JNICALL
|
||||
Java_network_loki_messenger_libsession_1util_ConversationVolatileConfig_all(JNIEnv *env,
|
||||
jobject thiz) {
|
||||
std::lock_guard lock{util::util_mutex_};
|
||||
auto convos = ptrToConvoInfo(env, thiz);
|
||||
jclass stack = env->FindClass("java/util/Stack");
|
||||
jmethodID init = env->GetMethodID(stack, "<init>", "()V");
|
||||
jobject our_stack = env->NewObject(stack, init);
|
||||
jmethodID push = env->GetMethodID(stack, "push", "(Ljava/lang/Object;)Ljava/lang/Object;");
|
||||
for (const auto& convo : *convos) {
|
||||
auto contact_obj = serialize_any(env, convo);
|
||||
env->CallObjectMethod(our_stack, push, contact_obj);
|
||||
}
|
||||
return our_stack;
|
||||
}
|
||||
extern "C"
|
||||
JNIEXPORT jobject JNICALL
|
||||
Java_network_loki_messenger_libsession_1util_ConversationVolatileConfig_allOneToOnes(JNIEnv *env,
|
||||
jobject thiz) {
|
||||
std::lock_guard lock{util::util_mutex_};
|
||||
auto convos = ptrToConvoInfo(env, thiz);
|
||||
jclass stack = env->FindClass("java/util/Stack");
|
||||
jmethodID init = env->GetMethodID(stack, "<init>", "()V");
|
||||
jobject our_stack = env->NewObject(stack, init);
|
||||
jmethodID push = env->GetMethodID(stack, "push", "(Ljava/lang/Object;)Ljava/lang/Object;");
|
||||
for (auto contact = convos->begin_1to1(); contact != convos->end(); ++contact)
|
||||
env->CallObjectMethod(our_stack, push, serialize_one_to_one(env, *contact));
|
||||
return our_stack;
|
||||
}
|
||||
extern "C"
|
||||
JNIEXPORT jobject JNICALL
|
||||
Java_network_loki_messenger_libsession_1util_ConversationVolatileConfig_allCommunities(JNIEnv *env,
|
||||
jobject thiz) {
|
||||
std::lock_guard lock{util::util_mutex_};
|
||||
auto convos = ptrToConvoInfo(env, thiz);
|
||||
jclass stack = env->FindClass("java/util/Stack");
|
||||
jmethodID init = env->GetMethodID(stack, "<init>", "()V");
|
||||
jobject our_stack = env->NewObject(stack, init);
|
||||
jmethodID push = env->GetMethodID(stack, "push", "(Ljava/lang/Object;)Ljava/lang/Object;");
|
||||
for (auto contact = convos->begin_communities(); contact != convos->end(); ++contact)
|
||||
env->CallObjectMethod(our_stack, push, serialize_open_group(env, *contact));
|
||||
return our_stack;
|
||||
}
|
||||
extern "C"
|
||||
JNIEXPORT jobject JNICALL
|
||||
Java_network_loki_messenger_libsession_1util_ConversationVolatileConfig_allLegacyClosedGroups(
|
||||
JNIEnv *env, jobject thiz) {
|
||||
std::lock_guard lock{util::util_mutex_};
|
||||
auto convos = ptrToConvoInfo(env, thiz);
|
||||
jclass stack = env->FindClass("java/util/Stack");
|
||||
jmethodID init = env->GetMethodID(stack, "<init>", "()V");
|
||||
jobject our_stack = env->NewObject(stack, init);
|
||||
jmethodID push = env->GetMethodID(stack, "push", "(Ljava/lang/Object;)Ljava/lang/Object;");
|
||||
for (auto contact = convos->begin_legacy_groups(); contact != convos->end(); ++contact)
|
||||
env->CallObjectMethod(our_stack, push, serialize_legacy_group(env, *contact));
|
||||
return our_stack;
|
||||
}
|
122
libsession-util/src/main/cpp/conversation.h
Normal file
122
libsession-util/src/main/cpp/conversation.h
Normal file
@@ -0,0 +1,122 @@
|
||||
#ifndef SESSION_ANDROID_CONVERSATION_H
|
||||
#define SESSION_ANDROID_CONVERSATION_H
|
||||
|
||||
#include <jni.h>
|
||||
#include "util.h"
|
||||
#include "session/config/convo_info_volatile.hpp"
|
||||
|
||||
inline session::config::ConvoInfoVolatile *ptrToConvoInfo(JNIEnv *env, jobject obj) {
|
||||
jclass contactsClass = env->FindClass("network/loki/messenger/libsession_util/ConversationVolatileConfig");
|
||||
jfieldID pointerField = env->GetFieldID(contactsClass, "pointer", "J");
|
||||
return (session::config::ConvoInfoVolatile *) env->GetLongField(obj, pointerField);
|
||||
}
|
||||
|
||||
inline jobject serialize_one_to_one(JNIEnv *env, session::config::convo::one_to_one one_to_one) {
|
||||
jclass clazz = env->FindClass("network/loki/messenger/libsession_util/util/Conversation$OneToOne");
|
||||
jmethodID constructor = env->GetMethodID(clazz, "<init>", "(Ljava/lang/String;JZ)V");
|
||||
auto session_id = env->NewStringUTF(one_to_one.session_id.data());
|
||||
auto last_read = one_to_one.last_read;
|
||||
auto unread = one_to_one.unread;
|
||||
jobject serialized = env->NewObject(clazz, constructor, session_id, last_read, unread);
|
||||
return serialized;
|
||||
}
|
||||
|
||||
inline jobject serialize_open_group(JNIEnv *env, session::config::convo::community community) {
|
||||
jclass clazz = env->FindClass("network/loki/messenger/libsession_util/util/Conversation$Community");
|
||||
auto base_community = util::serialize_base_community(env, community);
|
||||
jmethodID constructor = env->GetMethodID(clazz, "<init>",
|
||||
"(Lnetwork/loki/messenger/libsession_util/util/BaseCommunityInfo;JZ)V");
|
||||
auto last_read = community.last_read;
|
||||
auto unread = community.unread;
|
||||
jobject serialized = env->NewObject(clazz, constructor, base_community, last_read, unread);
|
||||
return serialized;
|
||||
}
|
||||
|
||||
inline jobject serialize_legacy_group(JNIEnv *env, session::config::convo::legacy_group group) {
|
||||
jclass clazz = env->FindClass("network/loki/messenger/libsession_util/util/Conversation$LegacyGroup");
|
||||
jmethodID constructor = env->GetMethodID(clazz, "<init>", "(Ljava/lang/String;JZ)V");
|
||||
auto group_id = env->NewStringUTF(group.id.data());
|
||||
auto last_read = group.last_read;
|
||||
auto unread = group.unread;
|
||||
jobject serialized = env->NewObject(clazz, constructor, group_id, last_read, unread);
|
||||
return serialized;
|
||||
}
|
||||
|
||||
inline jobject serialize_any(JNIEnv *env, session::config::convo::any any) {
|
||||
if (auto* dm = std::get_if<session::config::convo::one_to_one>(&any)) {
|
||||
return serialize_one_to_one(env, *dm);
|
||||
} else if (auto* og = std::get_if<session::config::convo::community>(&any)) {
|
||||
return serialize_open_group(env, *og);
|
||||
} else if (auto* lgc = std::get_if<session::config::convo::legacy_group>(&any)) {
|
||||
return serialize_legacy_group(env, *lgc);
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
inline session::config::convo::one_to_one deserialize_one_to_one(JNIEnv *env, jobject info, session::config::ConvoInfoVolatile *conf) {
|
||||
auto clazz = env->FindClass("network/loki/messenger/libsession_util/util/Conversation$OneToOne");
|
||||
auto id_getter = env->GetFieldID(clazz, "sessionId", "Ljava/lang/String;");
|
||||
auto last_read_getter = env->GetFieldID(clazz, "lastRead", "J");
|
||||
auto unread_getter = env->GetFieldID(clazz, "unread", "Z");
|
||||
jstring id = static_cast<jstring>(env->GetObjectField(info, id_getter));
|
||||
auto id_chars = env->GetStringUTFChars(id, nullptr);
|
||||
std::string id_string = std::string{id_chars};
|
||||
auto deserialized = conf->get_or_construct_1to1(id_string);
|
||||
deserialized.last_read = env->GetLongField(info, last_read_getter);
|
||||
deserialized.unread = env->GetBooleanField(info, unread_getter);
|
||||
env->ReleaseStringUTFChars(id, id_chars);
|
||||
return deserialized;
|
||||
}
|
||||
|
||||
inline session::config::convo::community deserialize_community(JNIEnv *env, jobject info, session::config::ConvoInfoVolatile *conf) {
|
||||
auto clazz = env->FindClass("network/loki/messenger/libsession_util/util/Conversation$Community");
|
||||
auto base_community_getter = env->GetFieldID(clazz, "baseCommunityInfo", "Lnetwork/loki/messenger/libsession_util/util/BaseCommunityInfo;");
|
||||
auto last_read_getter = env->GetFieldID(clazz, "lastRead", "J");
|
||||
auto unread_getter = env->GetFieldID(clazz, "unread", "Z");
|
||||
|
||||
auto base_community_info = env->GetObjectField(info, base_community_getter);
|
||||
|
||||
auto base_community_deserialized = util::deserialize_base_community(env, base_community_info);
|
||||
auto deserialized = conf->get_or_construct_community(
|
||||
base_community_deserialized.base_url(),
|
||||
base_community_deserialized.room(),
|
||||
base_community_deserialized.pubkey()
|
||||
);
|
||||
|
||||
deserialized.last_read = env->GetLongField(info, last_read_getter);
|
||||
deserialized.unread = env->GetBooleanField(info, unread_getter);
|
||||
|
||||
return deserialized;
|
||||
}
|
||||
|
||||
inline session::config::convo::legacy_group deserialize_legacy_closed_group(JNIEnv *env, jobject info, session::config::ConvoInfoVolatile *conf) {
|
||||
auto clazz = env->FindClass("network/loki/messenger/libsession_util/util/Conversation$LegacyGroup");
|
||||
auto group_id_getter = env->GetFieldID(clazz, "groupId", "Ljava/lang/String;");
|
||||
auto last_read_getter = env->GetFieldID(clazz, "lastRead", "J");
|
||||
auto unread_getter = env->GetFieldID(clazz, "unread", "Z");
|
||||
auto group_id = static_cast<jstring>(env->GetObjectField(info, group_id_getter));
|
||||
auto group_id_bytes = env->GetStringUTFChars(group_id, nullptr);
|
||||
auto group_id_string = std::string{group_id_bytes};
|
||||
auto deserialized = conf->get_or_construct_legacy_group(group_id_string);
|
||||
deserialized.last_read = env->GetLongField(info, last_read_getter);
|
||||
deserialized.unread = env->GetBooleanField(info, unread_getter);
|
||||
env->ReleaseStringUTFChars(group_id, group_id_bytes);
|
||||
return deserialized;
|
||||
}
|
||||
|
||||
inline std::optional<session::config::convo::any> deserialize_any(JNIEnv *env, jobject convo, session::config::ConvoInfoVolatile *conf) {
|
||||
auto oto_class = env->FindClass("network/loki/messenger/libsession_util/util/Conversation$OneToOne");
|
||||
auto og_class = env->FindClass("network/loki/messenger/libsession_util/util/Conversation$Community");
|
||||
auto lgc_class = env->FindClass("network/loki/messenger/libsession_util/util/Conversation$LegacyGroup");
|
||||
auto object_class = env->GetObjectClass(convo);
|
||||
if (env->IsSameObject(object_class, oto_class)) {
|
||||
return session::config::convo::any{deserialize_one_to_one(env, convo, conf)};
|
||||
} else if (env->IsSameObject(object_class, og_class)) {
|
||||
return session::config::convo::any{deserialize_community(env, convo, conf)};
|
||||
} else if (env->IsSameObject(object_class, lgc_class)) {
|
||||
return session::config::convo::any{deserialize_legacy_closed_group(env, convo, conf)};
|
||||
}
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
#endif //SESSION_ANDROID_CONVERSATION_H
|
273
libsession-util/src/main/cpp/user_groups.cpp
Normal file
273
libsession-util/src/main/cpp/user_groups.cpp
Normal file
@@ -0,0 +1,273 @@
|
||||
#pragma clang diagnostic push
|
||||
#pragma ide diagnostic ignored "bugprone-reserved-identifier"
|
||||
#include "user_groups.h"
|
||||
|
||||
|
||||
#pragma clang diagnostic push
|
||||
#pragma ide diagnostic ignored "bugprone-reserved-identifier"
|
||||
extern "C"
|
||||
JNIEXPORT jobject JNICALL
|
||||
Java_network_loki_messenger_libsession_1util_UserGroupsConfig_00024Companion_newInstance___3B(
|
||||
JNIEnv *env, jobject thiz, jbyteArray ed25519_secret_key) {
|
||||
std::lock_guard lock{util::util_mutex_};
|
||||
auto secret_key = util::ustring_from_bytes(env, ed25519_secret_key);
|
||||
|
||||
auto* user_groups = new session::config::UserGroups(secret_key, std::nullopt);
|
||||
|
||||
jclass contactsClass = env->FindClass("network/loki/messenger/libsession_util/UserGroupsConfig");
|
||||
jmethodID constructor = env->GetMethodID(contactsClass, "<init>", "(J)V");
|
||||
jobject newConfig = env->NewObject(contactsClass, constructor, reinterpret_cast<jlong>(user_groups));
|
||||
|
||||
return newConfig;
|
||||
}
|
||||
|
||||
extern "C"
|
||||
JNIEXPORT jobject JNICALL
|
||||
Java_network_loki_messenger_libsession_1util_UserGroupsConfig_00024Companion_newInstance___3B_3B(
|
||||
JNIEnv *env, jobject thiz, jbyteArray ed25519_secret_key, jbyteArray initial_dump) {
|
||||
std::lock_guard lock{util::util_mutex_};
|
||||
auto secret_key = util::ustring_from_bytes(env, ed25519_secret_key);
|
||||
auto initial = util::ustring_from_bytes(env, initial_dump);
|
||||
|
||||
auto* user_groups = new session::config::UserGroups(secret_key, initial);
|
||||
|
||||
jclass contactsClass = env->FindClass("network/loki/messenger/libsession_util/UserGroupsConfig");
|
||||
jmethodID constructor = env->GetMethodID(contactsClass, "<init>", "(J)V");
|
||||
jobject newConfig = env->NewObject(contactsClass, constructor, reinterpret_cast<jlong>(user_groups));
|
||||
|
||||
return newConfig;
|
||||
}
|
||||
#pragma clang diagnostic pop
|
||||
|
||||
extern "C"
|
||||
JNIEXPORT jint JNICALL
|
||||
Java_network_loki_messenger_libsession_1util_util_GroupInfo_00024LegacyGroupInfo_00024Companion_NAME_1MAX_1LENGTH(
|
||||
JNIEnv *env, jobject thiz) {
|
||||
std::lock_guard lock{util::util_mutex_};
|
||||
return session::config::legacy_group_info::NAME_MAX_LENGTH;
|
||||
}
|
||||
|
||||
extern "C"
|
||||
JNIEXPORT jobject JNICALL
|
||||
Java_network_loki_messenger_libsession_1util_UserGroupsConfig_getCommunityInfo(JNIEnv *env,
|
||||
jobject thiz,
|
||||
jstring base_url,
|
||||
jstring room) {
|
||||
std::lock_guard lock{util::util_mutex_};
|
||||
auto conf = ptrToUserGroups(env, thiz);
|
||||
auto base_url_bytes = env->GetStringUTFChars(base_url, nullptr);
|
||||
auto room_bytes = env->GetStringUTFChars(room, nullptr);
|
||||
|
||||
auto community = conf->get_community(base_url_bytes, room_bytes);
|
||||
|
||||
jobject community_info = nullptr;
|
||||
|
||||
if (community) {
|
||||
community_info = serialize_community_info(env, *community);
|
||||
}
|
||||
env->ReleaseStringUTFChars(base_url, base_url_bytes);
|
||||
env->ReleaseStringUTFChars(room, room_bytes);
|
||||
return community_info;
|
||||
}
|
||||
|
||||
extern "C"
|
||||
JNIEXPORT jobject JNICALL
|
||||
Java_network_loki_messenger_libsession_1util_UserGroupsConfig_getLegacyGroupInfo(JNIEnv *env,
|
||||
jobject thiz,
|
||||
jstring session_id) {
|
||||
std::lock_guard lock{util::util_mutex_};
|
||||
auto conf = ptrToUserGroups(env, thiz);
|
||||
auto id_bytes = env->GetStringUTFChars(session_id, nullptr);
|
||||
auto legacy_group = conf->get_legacy_group(id_bytes);
|
||||
jobject return_group = nullptr;
|
||||
if (legacy_group) {
|
||||
return_group = serialize_legacy_group_info(env, *legacy_group);
|
||||
}
|
||||
env->ReleaseStringUTFChars(session_id, id_bytes);
|
||||
return return_group;
|
||||
}
|
||||
|
||||
extern "C"
|
||||
JNIEXPORT jobject JNICALL
|
||||
Java_network_loki_messenger_libsession_1util_UserGroupsConfig_getOrConstructCommunityInfo(
|
||||
JNIEnv *env, jobject thiz, jstring base_url, jstring room, jstring pub_key_hex) {
|
||||
std::lock_guard lock{util::util_mutex_};
|
||||
auto conf = ptrToUserGroups(env, thiz);
|
||||
auto base_url_bytes = env->GetStringUTFChars(base_url, nullptr);
|
||||
auto room_bytes = env->GetStringUTFChars(room, nullptr);
|
||||
auto pub_hex_bytes = env->GetStringUTFChars(pub_key_hex, nullptr);
|
||||
|
||||
auto group = conf->get_or_construct_community(base_url_bytes, room_bytes, pub_hex_bytes);
|
||||
|
||||
env->ReleaseStringUTFChars(base_url, base_url_bytes);
|
||||
env->ReleaseStringUTFChars(room, room_bytes);
|
||||
env->ReleaseStringUTFChars(pub_key_hex, pub_hex_bytes);
|
||||
return serialize_community_info(env, group);
|
||||
}
|
||||
|
||||
extern "C"
|
||||
JNIEXPORT jobject JNICALL
|
||||
Java_network_loki_messenger_libsession_1util_UserGroupsConfig_getOrConstructLegacyGroupInfo(
|
||||
JNIEnv *env, jobject thiz, jstring session_id) {
|
||||
std::lock_guard lock{util::util_mutex_};
|
||||
auto conf = ptrToUserGroups(env, thiz);
|
||||
auto id_bytes = env->GetStringUTFChars(session_id, nullptr);
|
||||
auto group = conf->get_or_construct_legacy_group(id_bytes);
|
||||
env->ReleaseStringUTFChars(session_id, id_bytes);
|
||||
return serialize_legacy_group_info(env, group);
|
||||
}
|
||||
|
||||
extern "C"
|
||||
JNIEXPORT void JNICALL
|
||||
Java_network_loki_messenger_libsession_1util_UserGroupsConfig_set__Lnetwork_loki_messenger_libsession_1util_util_GroupInfo_2(
|
||||
JNIEnv *env, jobject thiz, jobject group_info) {
|
||||
std::lock_guard lock{util::util_mutex_};
|
||||
auto conf = ptrToUserGroups(env, thiz);
|
||||
auto community_info = env->FindClass("network/loki/messenger/libsession_util/util/GroupInfo$CommunityGroupInfo");
|
||||
auto legacy_info = env->FindClass("network/loki/messenger/libsession_util/util/GroupInfo$LegacyGroupInfo");
|
||||
auto object_class = env->GetObjectClass(group_info);
|
||||
if (env->IsSameObject(community_info, object_class)) {
|
||||
auto deserialized = deserialize_community_info(env, group_info, conf);
|
||||
conf->set(deserialized);
|
||||
} else if (env->IsSameObject(legacy_info, object_class)) {
|
||||
auto deserialized = deserialize_legacy_group_info(env, group_info, conf);
|
||||
conf->set(deserialized);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
extern "C"
|
||||
JNIEXPORT void JNICALL
|
||||
Java_network_loki_messenger_libsession_1util_UserGroupsConfig_erase__Lnetwork_loki_messenger_libsession_1util_util_GroupInfo_2(
|
||||
JNIEnv *env, jobject thiz, jobject group_info) {
|
||||
std::lock_guard lock{util::util_mutex_};
|
||||
auto conf = ptrToUserGroups(env, thiz);
|
||||
auto communityInfo = env->FindClass("network/loki/messenger/libsession_util/util/GroupInfo$CommunityGroupInfo");
|
||||
auto legacyInfo = env->FindClass("network/loki/messenger/libsession_util/util/GroupInfo$LegacyGroupInfo");
|
||||
if (env->GetObjectClass(group_info) == communityInfo) {
|
||||
auto deserialized = deserialize_community_info(env, group_info, conf);
|
||||
conf->erase(deserialized);
|
||||
} else if (env->GetObjectClass(group_info) == legacyInfo) {
|
||||
auto deserialized = deserialize_legacy_group_info(env, group_info, conf);
|
||||
conf->erase(deserialized);
|
||||
}
|
||||
}
|
||||
|
||||
extern "C"
|
||||
JNIEXPORT jint JNICALL
|
||||
Java_network_loki_messenger_libsession_1util_UserGroupsConfig_sizeCommunityInfo(JNIEnv *env,
|
||||
jobject thiz) {
|
||||
std::lock_guard lock{util::util_mutex_};
|
||||
auto conf = ptrToUserGroups(env, thiz);
|
||||
return conf->size_communities();
|
||||
}
|
||||
|
||||
extern "C"
|
||||
JNIEXPORT jint JNICALL
|
||||
Java_network_loki_messenger_libsession_1util_UserGroupsConfig_sizeLegacyGroupInfo(JNIEnv *env,
|
||||
jobject thiz) {
|
||||
std::lock_guard lock{util::util_mutex_};
|
||||
auto conf = ptrToUserGroups(env, thiz);
|
||||
return conf->size_legacy_groups();
|
||||
}
|
||||
|
||||
extern "C"
|
||||
JNIEXPORT jint JNICALL
|
||||
Java_network_loki_messenger_libsession_1util_UserGroupsConfig_size(JNIEnv *env, jobject thiz) {
|
||||
std::lock_guard lock{util::util_mutex_};
|
||||
auto conf = ptrToConvoInfo(env, thiz);
|
||||
return conf->size();
|
||||
}
|
||||
|
||||
inline jobject iterator_as_java_stack(JNIEnv *env, const session::config::UserGroups::iterator& begin, const session::config::UserGroups::iterator& end) {
|
||||
jclass stack = env->FindClass("java/util/Stack");
|
||||
jmethodID init = env->GetMethodID(stack, "<init>", "()V");
|
||||
jobject our_stack = env->NewObject(stack, init);
|
||||
jmethodID push = env->GetMethodID(stack, "push", "(Ljava/lang/Object;)Ljava/lang/Object;");
|
||||
for (auto it = begin; it != end;) {
|
||||
// do something with it
|
||||
auto item = *it;
|
||||
jobject serialized = nullptr;
|
||||
if (auto* lgc = std::get_if<session::config::legacy_group_info>(&item)) {
|
||||
serialized = serialize_legacy_group_info(env, *lgc);
|
||||
} else if (auto* community = std::get_if<session::config::community_info>(&item)) {
|
||||
serialized = serialize_community_info(env, *community);
|
||||
}
|
||||
if (serialized != nullptr) {
|
||||
env->CallObjectMethod(our_stack, push, serialized);
|
||||
}
|
||||
it++;
|
||||
}
|
||||
return our_stack;
|
||||
}
|
||||
|
||||
extern "C"
|
||||
JNIEXPORT jobject JNICALL
|
||||
Java_network_loki_messenger_libsession_1util_UserGroupsConfig_all(JNIEnv *env, jobject thiz) {
|
||||
std::lock_guard lock{util::util_mutex_};
|
||||
auto conf = ptrToUserGroups(env, thiz);
|
||||
jobject all_stack = iterator_as_java_stack(env, conf->begin(), conf->end());
|
||||
return all_stack;
|
||||
}
|
||||
|
||||
extern "C"
|
||||
JNIEXPORT jobject JNICALL
|
||||
Java_network_loki_messenger_libsession_1util_UserGroupsConfig_allCommunityInfo(JNIEnv *env,
|
||||
jobject thiz) {
|
||||
std::lock_guard lock{util::util_mutex_};
|
||||
auto conf = ptrToUserGroups(env, thiz);
|
||||
jobject community_stack = iterator_as_java_stack(env, conf->begin_communities(), conf->end());
|
||||
return community_stack;
|
||||
}
|
||||
|
||||
extern "C"
|
||||
JNIEXPORT jobject JNICALL
|
||||
Java_network_loki_messenger_libsession_1util_UserGroupsConfig_allLegacyGroupInfo(JNIEnv *env,
|
||||
jobject thiz) {
|
||||
std::lock_guard lock{util::util_mutex_};
|
||||
auto conf = ptrToUserGroups(env, thiz);
|
||||
jobject legacy_stack = iterator_as_java_stack(env, conf->begin_legacy_groups(), conf->end());
|
||||
return legacy_stack;
|
||||
}
|
||||
|
||||
extern "C"
|
||||
JNIEXPORT jboolean JNICALL
|
||||
Java_network_loki_messenger_libsession_1util_UserGroupsConfig_eraseCommunity__Lnetwork_loki_messenger_libsession_1util_util_BaseCommunityInfo_2(JNIEnv *env,
|
||||
jobject thiz,
|
||||
jobject base_community_info) {
|
||||
std::lock_guard lock{util::util_mutex_};
|
||||
auto conf = ptrToUserGroups(env, thiz);
|
||||
auto base_community = util::deserialize_base_community(env, base_community_info);
|
||||
return conf->erase_community(base_community.base_url(),base_community.room());
|
||||
}
|
||||
|
||||
extern "C"
|
||||
JNIEXPORT jboolean JNICALL
|
||||
Java_network_loki_messenger_libsession_1util_UserGroupsConfig_eraseCommunity__Ljava_lang_String_2Ljava_lang_String_2(
|
||||
JNIEnv *env, jobject thiz, jstring server, jstring room) {
|
||||
std::lock_guard lock{util::util_mutex_};
|
||||
auto conf = ptrToUserGroups(env, thiz);
|
||||
auto server_bytes = env->GetStringUTFChars(server, nullptr);
|
||||
auto room_bytes = env->GetStringUTFChars(room, nullptr);
|
||||
auto community = conf->get_community(server_bytes, room_bytes);
|
||||
bool deleted = false;
|
||||
if (community) {
|
||||
deleted = conf->erase(*community);
|
||||
}
|
||||
env->ReleaseStringUTFChars(server, server_bytes);
|
||||
env->ReleaseStringUTFChars(room, room_bytes);
|
||||
return deleted;
|
||||
}
|
||||
|
||||
extern "C"
|
||||
JNIEXPORT jboolean JNICALL
|
||||
Java_network_loki_messenger_libsession_1util_UserGroupsConfig_eraseLegacyGroup(JNIEnv *env,
|
||||
jobject thiz,
|
||||
jstring session_id) {
|
||||
std::lock_guard lock{util::util_mutex_};
|
||||
auto conf = ptrToUserGroups(env, thiz);
|
||||
auto session_id_bytes = env->GetStringUTFChars(session_id, nullptr);
|
||||
bool return_bool = conf->erase_legacy_group(session_id_bytes);
|
||||
env->ReleaseStringUTFChars(session_id, session_id_bytes);
|
||||
return return_bool;
|
||||
}
|
139
libsession-util/src/main/cpp/user_groups.h
Normal file
139
libsession-util/src/main/cpp/user_groups.h
Normal file
@@ -0,0 +1,139 @@
|
||||
|
||||
#ifndef SESSION_ANDROID_USER_GROUPS_H
|
||||
#define SESSION_ANDROID_USER_GROUPS_H
|
||||
|
||||
#include "jni.h"
|
||||
#include "util.h"
|
||||
#include "conversation.h"
|
||||
#include "session/config/user_groups.hpp"
|
||||
|
||||
inline session::config::UserGroups* ptrToUserGroups(JNIEnv *env, jobject obj) {
|
||||
jclass configClass = env->FindClass("network/loki/messenger/libsession_util/UserGroupsConfig");
|
||||
jfieldID pointerField = env->GetFieldID(configClass, "pointer", "J");
|
||||
return (session::config::UserGroups*) env->GetLongField(obj, pointerField);
|
||||
}
|
||||
|
||||
inline void deserialize_members_into(JNIEnv *env, jobject members_map, session::config::legacy_group_info& to_append_group) {
|
||||
jclass map_class = env->FindClass("java/util/Map");
|
||||
jclass map_entry_class = env->FindClass("java/util/Map$Entry");
|
||||
jclass set_class = env->FindClass("java/util/Set");
|
||||
jclass iterator_class = env->FindClass("java/util/Iterator");
|
||||
jclass boxed_bool = env->FindClass("java/lang/Boolean");
|
||||
|
||||
jmethodID get_entry_set = env->GetMethodID(map_class, "entrySet", "()Ljava/util/Set;");
|
||||
jmethodID get_at = env->GetMethodID(set_class, "iterator", "()Ljava/util/Iterator;");
|
||||
jmethodID has_next = env->GetMethodID(iterator_class, "hasNext", "()Z");
|
||||
jmethodID next = env->GetMethodID(iterator_class, "next", "()Ljava/lang/Object;");
|
||||
jmethodID get_key = env->GetMethodID(map_entry_class, "getKey", "()Ljava/lang/Object;");
|
||||
jmethodID get_value = env->GetMethodID(map_entry_class, "getValue", "()Ljava/lang/Object;");
|
||||
jmethodID get_bool_value = env->GetMethodID(boxed_bool, "booleanValue", "()Z");
|
||||
|
||||
jobject entry_set = env->CallObjectMethod(members_map, get_entry_set);
|
||||
jobject iterator = env->CallObjectMethod(entry_set, get_at);
|
||||
|
||||
while (env->CallBooleanMethod(iterator, has_next)) {
|
||||
jobject entry = env->CallObjectMethod(iterator, next);
|
||||
jstring key = static_cast<jstring>(env->CallObjectMethod(entry, get_key));
|
||||
jobject boxed = env->CallObjectMethod(entry, get_value);
|
||||
bool is_admin = env->CallBooleanMethod(boxed, get_bool_value);
|
||||
auto member_string = env->GetStringUTFChars(key, nullptr);
|
||||
to_append_group.insert(member_string, is_admin);
|
||||
env->ReleaseStringUTFChars(key, member_string);
|
||||
}
|
||||
}
|
||||
|
||||
inline session::config::legacy_group_info deserialize_legacy_group_info(JNIEnv *env, jobject info, session::config::UserGroups* conf) {
|
||||
auto clazz = env->FindClass("network/loki/messenger/libsession_util/util/GroupInfo$LegacyGroupInfo");
|
||||
auto id_field = env->GetFieldID(clazz, "sessionId", "Ljava/lang/String;");
|
||||
auto name_field = env->GetFieldID(clazz, "name", "Ljava/lang/String;");
|
||||
auto members_field = env->GetFieldID(clazz, "members", "Ljava/util/Map;");
|
||||
auto enc_pub_key_field = env->GetFieldID(clazz, "encPubKey", "[B");
|
||||
auto enc_sec_key_field = env->GetFieldID(clazz, "encSecKey", "[B");
|
||||
auto priority_field = env->GetFieldID(clazz, "priority", "I");
|
||||
auto disappearing_timer_field = env->GetFieldID(clazz, "disappearingTimer", "J");
|
||||
auto joined_at_field = env->GetFieldID(clazz, "joinedAt", "J");
|
||||
jstring id = static_cast<jstring>(env->GetObjectField(info, id_field));
|
||||
jstring name = static_cast<jstring>(env->GetObjectField(info, name_field));
|
||||
jobject members_map = env->GetObjectField(info, members_field);
|
||||
jbyteArray enc_pub_key = static_cast<jbyteArray>(env->GetObjectField(info, enc_pub_key_field));
|
||||
jbyteArray enc_sec_key = static_cast<jbyteArray>(env->GetObjectField(info, enc_sec_key_field));
|
||||
int priority = env->GetIntField(info, priority_field);
|
||||
long joined_at = env->GetLongField(info, joined_at_field);
|
||||
|
||||
auto id_bytes = env->GetStringUTFChars(id, nullptr);
|
||||
auto name_bytes = env->GetStringUTFChars(name, nullptr);
|
||||
auto enc_pub_key_bytes = util::ustring_from_bytes(env, enc_pub_key);
|
||||
auto enc_sec_key_bytes = util::ustring_from_bytes(env, enc_sec_key);
|
||||
|
||||
auto info_deserialized = conf->get_or_construct_legacy_group(id_bytes);
|
||||
|
||||
auto current_members = info_deserialized.members();
|
||||
for (auto member = current_members.begin(); member != current_members.end(); ++member) {
|
||||
info_deserialized.erase(member->first);
|
||||
}
|
||||
deserialize_members_into(env, members_map, info_deserialized);
|
||||
info_deserialized.name = name_bytes;
|
||||
info_deserialized.enc_pubkey = enc_pub_key_bytes;
|
||||
info_deserialized.enc_seckey = enc_sec_key_bytes;
|
||||
info_deserialized.priority = priority;
|
||||
info_deserialized.disappearing_timer = std::chrono::seconds(env->GetLongField(info, disappearing_timer_field));
|
||||
info_deserialized.joined_at = joined_at;
|
||||
env->ReleaseStringUTFChars(id, id_bytes);
|
||||
env->ReleaseStringUTFChars(name, name_bytes);
|
||||
return info_deserialized;
|
||||
}
|
||||
|
||||
inline session::config::community_info deserialize_community_info(JNIEnv *env, jobject info, session::config::UserGroups* conf) {
|
||||
auto clazz = env->FindClass("network/loki/messenger/libsession_util/util/GroupInfo$CommunityGroupInfo");
|
||||
auto base_info = env->GetFieldID(clazz, "community", "Lnetwork/loki/messenger/libsession_util/util/BaseCommunityInfo;");
|
||||
auto priority = env->GetFieldID(clazz, "priority", "I");
|
||||
jobject base_community_info = env->GetObjectField(info, base_info);
|
||||
auto deserialized_base_info = util::deserialize_base_community(env, base_community_info);
|
||||
int deserialized_priority = env->GetIntField(info, priority);
|
||||
auto community_info = conf->get_or_construct_community(deserialized_base_info.base_url(), deserialized_base_info.room(), deserialized_base_info.pubkey_hex());
|
||||
community_info.priority = deserialized_priority;
|
||||
return community_info;
|
||||
}
|
||||
|
||||
inline jobject serialize_members(JNIEnv *env, std::map<std::string, bool> members_map) {
|
||||
jclass map_class = env->FindClass("java/util/HashMap");
|
||||
jclass boxed_bool = env->FindClass("java/lang/Boolean");
|
||||
jmethodID map_constructor = env->GetMethodID(map_class, "<init>", "()V");
|
||||
jmethodID insert = env->GetMethodID(map_class, "put", "(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;");
|
||||
jmethodID new_bool = env->GetMethodID(boxed_bool, "<init>", "(Z)V");
|
||||
|
||||
jobject new_map = env->NewObject(map_class, map_constructor);
|
||||
for (auto it = members_map.begin(); it != members_map.end(); it++) {
|
||||
auto session_id = env->NewStringUTF(it->first.data());
|
||||
bool is_admin = it->second;
|
||||
auto jbool = env->NewObject(boxed_bool, new_bool, is_admin);
|
||||
env->CallObjectMethod(new_map, insert, session_id, jbool);
|
||||
}
|
||||
return new_map;
|
||||
}
|
||||
|
||||
inline jobject serialize_legacy_group_info(JNIEnv *env, session::config::legacy_group_info info) {
|
||||
jstring session_id = env->NewStringUTF(info.session_id.data());
|
||||
jstring name = env->NewStringUTF(info.name.data());
|
||||
jobject members = serialize_members(env, info.members());
|
||||
jbyteArray enc_pubkey = util::bytes_from_ustring(env, info.enc_pubkey);
|
||||
jbyteArray enc_seckey = util::bytes_from_ustring(env, info.enc_seckey);
|
||||
int priority = info.priority;
|
||||
long joined_at = info.joined_at;
|
||||
|
||||
jclass legacy_group_class = env->FindClass("network/loki/messenger/libsession_util/util/GroupInfo$LegacyGroupInfo");
|
||||
jmethodID constructor = env->GetMethodID(legacy_group_class, "<init>", "(Ljava/lang/String;Ljava/lang/String;Ljava/util/Map;[B[BIJJ)V");
|
||||
jobject serialized = env->NewObject(legacy_group_class, constructor, session_id, name, members, enc_pubkey, enc_seckey, priority, (jlong) info.disappearing_timer.count(), joined_at);
|
||||
return serialized;
|
||||
}
|
||||
|
||||
inline jobject serialize_community_info(JNIEnv *env, session::config::community_info info) {
|
||||
auto priority = info.priority;
|
||||
auto serialized_info = util::serialize_base_community(env, info);
|
||||
auto clazz = env->FindClass("network/loki/messenger/libsession_util/util/GroupInfo$CommunityGroupInfo");
|
||||
jmethodID constructor = env->GetMethodID(clazz, "<init>", "(Lnetwork/loki/messenger/libsession_util/util/BaseCommunityInfo;I)V");
|
||||
jobject serialized = env->NewObject(clazz, constructor, serialized_info, priority);
|
||||
return serialized;
|
||||
}
|
||||
|
||||
#endif //SESSION_ANDROID_USER_GROUPS_H
|
98
libsession-util/src/main/cpp/user_profile.cpp
Normal file
98
libsession-util/src/main/cpp/user_profile.cpp
Normal file
@@ -0,0 +1,98 @@
|
||||
#include "user_profile.h"
|
||||
#include "util.h"
|
||||
|
||||
extern "C" {
|
||||
#pragma clang diagnostic push
|
||||
#pragma ide diagnostic ignored "bugprone-reserved-identifier"
|
||||
JNIEXPORT jobject JNICALL
|
||||
Java_network_loki_messenger_libsession_1util_UserProfile_00024Companion_newInstance___3B_3B(
|
||||
JNIEnv *env, jobject thiz, jbyteArray ed25519_secret_key, jbyteArray initial_dump) {
|
||||
std::lock_guard lock{util::util_mutex_};
|
||||
auto secret_key = util::ustring_from_bytes(env, ed25519_secret_key);
|
||||
auto initial = util::ustring_from_bytes(env, initial_dump);
|
||||
auto* profile = new session::config::UserProfile(secret_key, std::optional(initial));
|
||||
|
||||
jclass userClass = env->FindClass("network/loki/messenger/libsession_util/UserProfile");
|
||||
jmethodID constructor = env->GetMethodID(userClass, "<init>", "(J)V");
|
||||
jobject newConfig = env->NewObject(userClass, constructor, reinterpret_cast<jlong>(profile));
|
||||
|
||||
return newConfig;
|
||||
}
|
||||
|
||||
JNIEXPORT jobject JNICALL
|
||||
Java_network_loki_messenger_libsession_1util_UserProfile_00024Companion_newInstance___3B(
|
||||
JNIEnv* env,
|
||||
jobject,
|
||||
jbyteArray secretKey) {
|
||||
std::lock_guard lock{util::util_mutex_};
|
||||
auto* profile = new session::config::UserProfile(util::ustring_from_bytes(env, secretKey), std::nullopt);
|
||||
|
||||
jclass userClass = env->FindClass("network/loki/messenger/libsession_util/UserProfile");
|
||||
jmethodID constructor = env->GetMethodID(userClass, "<init>", "(J)V");
|
||||
jobject newConfig = env->NewObject(userClass, constructor, reinterpret_cast<jlong>(profile));
|
||||
|
||||
return newConfig;
|
||||
}
|
||||
#pragma clang diagnostic pop
|
||||
|
||||
JNIEXPORT void JNICALL
|
||||
Java_network_loki_messenger_libsession_1util_UserProfile_setName(
|
||||
JNIEnv* env,
|
||||
jobject thiz,
|
||||
jstring newName) {
|
||||
std::lock_guard lock{util::util_mutex_};
|
||||
auto profile = ptrToProfile(env, thiz);
|
||||
auto name_chars = env->GetStringUTFChars(newName, nullptr);
|
||||
profile->set_name(name_chars);
|
||||
env->ReleaseStringUTFChars(newName, name_chars);
|
||||
}
|
||||
|
||||
JNIEXPORT jstring JNICALL
|
||||
Java_network_loki_messenger_libsession_1util_UserProfile_getName(JNIEnv *env, jobject thiz) {
|
||||
std::lock_guard lock{util::util_mutex_};
|
||||
auto profile = ptrToProfile(env, thiz);
|
||||
auto name = profile->get_name();
|
||||
if (name == std::nullopt) return nullptr;
|
||||
jstring returnString = env->NewStringUTF(name->data());
|
||||
return returnString;
|
||||
}
|
||||
|
||||
JNIEXPORT jobject JNICALL
|
||||
Java_network_loki_messenger_libsession_1util_UserProfile_getPic(JNIEnv *env, jobject thiz) {
|
||||
std::lock_guard lock{util::util_mutex_};
|
||||
auto profile = ptrToProfile(env, thiz);
|
||||
auto pic = profile->get_profile_pic();
|
||||
|
||||
jobject returnObject = util::serialize_user_pic(env, pic);
|
||||
|
||||
return returnObject;
|
||||
}
|
||||
|
||||
JNIEXPORT void JNICALL
|
||||
Java_network_loki_messenger_libsession_1util_UserProfile_setPic(JNIEnv *env, jobject thiz,
|
||||
jobject user_pic) {
|
||||
std::lock_guard lock{util::util_mutex_};
|
||||
auto profile = ptrToProfile(env, thiz);
|
||||
auto pic = util::deserialize_user_pic(env, user_pic);
|
||||
auto url = env->GetStringUTFChars(pic.first, nullptr);
|
||||
auto key = util::ustring_from_bytes(env, pic.second);
|
||||
profile->set_profile_pic(url, key);
|
||||
env->ReleaseStringUTFChars(pic.first, url);
|
||||
}
|
||||
|
||||
}
|
||||
extern "C"
|
||||
JNIEXPORT void JNICALL
|
||||
Java_network_loki_messenger_libsession_1util_UserProfile_setNtsPriority(JNIEnv *env, jobject thiz,
|
||||
jint priority) {
|
||||
std::lock_guard lock{util::util_mutex_};
|
||||
auto profile = ptrToProfile(env, thiz);
|
||||
profile->set_nts_priority(priority);
|
||||
}
|
||||
extern "C"
|
||||
JNIEXPORT jint JNICALL
|
||||
Java_network_loki_messenger_libsession_1util_UserProfile_getNtsPriority(JNIEnv *env, jobject thiz) {
|
||||
std::lock_guard lock{util::util_mutex_};
|
||||
auto profile = ptrToProfile(env, thiz);
|
||||
return profile->get_nts_priority();
|
||||
}
|
14
libsession-util/src/main/cpp/user_profile.h
Normal file
14
libsession-util/src/main/cpp/user_profile.h
Normal file
@@ -0,0 +1,14 @@
|
||||
#ifndef SESSION_ANDROID_USER_PROFILE_H
|
||||
#define SESSION_ANDROID_USER_PROFILE_H
|
||||
|
||||
#include "session/config/user_profile.hpp"
|
||||
#include <jni.h>
|
||||
#include <string>
|
||||
|
||||
inline session::config::UserProfile* ptrToProfile(JNIEnv* env, jobject obj) {
|
||||
jclass configClass = env->FindClass("network/loki/messenger/libsession_util/UserProfile");
|
||||
jfieldID pointerField = env->GetFieldID(configClass, "pointer", "J");
|
||||
return (session::config::UserProfile*) env->GetLongField(obj, pointerField);
|
||||
}
|
||||
|
||||
#endif
|
167
libsession-util/src/main/cpp/util.cpp
Normal file
167
libsession-util/src/main/cpp/util.cpp
Normal file
@@ -0,0 +1,167 @@
|
||||
#include "util.h"
|
||||
#include <string>
|
||||
#include <sodium/crypto_sign.h>
|
||||
|
||||
namespace util {
|
||||
|
||||
std::mutex util_mutex_ = std::mutex();
|
||||
|
||||
jbyteArray bytes_from_ustring(JNIEnv* env, session::ustring_view from_str) {
|
||||
size_t length = from_str.length();
|
||||
auto jlength = (jsize)length;
|
||||
jbyteArray new_array = env->NewByteArray(jlength);
|
||||
env->SetByteArrayRegion(new_array, 0, jlength, (jbyte*)from_str.data());
|
||||
return new_array;
|
||||
}
|
||||
|
||||
session::ustring ustring_from_bytes(JNIEnv* env, jbyteArray byteArray) {
|
||||
size_t len = env->GetArrayLength(byteArray);
|
||||
auto bytes = env->GetByteArrayElements(byteArray, nullptr);
|
||||
|
||||
session::ustring st{reinterpret_cast<const unsigned char *>(bytes), len};
|
||||
env->ReleaseByteArrayElements(byteArray, bytes, 0);
|
||||
return st;
|
||||
}
|
||||
|
||||
jobject serialize_user_pic(JNIEnv *env, session::config::profile_pic pic) {
|
||||
jclass returnObjectClass = env->FindClass("network/loki/messenger/libsession_util/util/UserPic");
|
||||
jmethodID constructor = env->GetMethodID(returnObjectClass, "<init>", "(Ljava/lang/String;[B)V");
|
||||
jstring url = env->NewStringUTF(pic.url.data());
|
||||
jbyteArray byteArray = util::bytes_from_ustring(env, pic.key);
|
||||
return env->NewObject(returnObjectClass, constructor, url, byteArray);
|
||||
}
|
||||
|
||||
std::pair<jstring, jbyteArray> deserialize_user_pic(JNIEnv *env, jobject user_pic) {
|
||||
jclass userPicClass = env->FindClass("network/loki/messenger/libsession_util/util/UserPic");
|
||||
jfieldID picField = env->GetFieldID(userPicClass, "url", "Ljava/lang/String;");
|
||||
jfieldID keyField = env->GetFieldID(userPicClass, "key", "[B");
|
||||
auto pic = (jstring)env->GetObjectField(user_pic, picField);
|
||||
auto key = (jbyteArray)env->GetObjectField(user_pic, keyField);
|
||||
return {pic, key};
|
||||
}
|
||||
|
||||
jobject serialize_base_community(JNIEnv *env, const session::config::community& community) {
|
||||
jclass base_community_clazz = env->FindClass("network/loki/messenger/libsession_util/util/BaseCommunityInfo");
|
||||
jmethodID base_community_constructor = env->GetMethodID(base_community_clazz, "<init>", "(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)V");
|
||||
auto base_url = env->NewStringUTF(community.base_url().data());
|
||||
auto room = env->NewStringUTF(community.room().data());
|
||||
auto pubkey_jstring = env->NewStringUTF(community.pubkey_hex().data());
|
||||
jobject ret = env->NewObject(base_community_clazz, base_community_constructor, base_url, room, pubkey_jstring);
|
||||
return ret;
|
||||
}
|
||||
|
||||
session::config::community deserialize_base_community(JNIEnv *env, jobject base_community) {
|
||||
jclass base_community_clazz = env->FindClass("network/loki/messenger/libsession_util/util/BaseCommunityInfo");
|
||||
jfieldID base_url_field = env->GetFieldID(base_community_clazz, "baseUrl", "Ljava/lang/String;");
|
||||
jfieldID room_field = env->GetFieldID(base_community_clazz, "room", "Ljava/lang/String;");
|
||||
jfieldID pubkey_hex_field = env->GetFieldID(base_community_clazz, "pubKeyHex", "Ljava/lang/String;");
|
||||
auto base_url = (jstring)env->GetObjectField(base_community,base_url_field);
|
||||
auto room = (jstring)env->GetObjectField(base_community, room_field);
|
||||
auto pub_key_hex = (jstring)env->GetObjectField(base_community, pubkey_hex_field);
|
||||
auto base_url_chars = env->GetStringUTFChars(base_url, nullptr);
|
||||
auto room_chars = env->GetStringUTFChars(room, nullptr);
|
||||
auto pub_key_hex_chars = env->GetStringUTFChars(pub_key_hex, nullptr);
|
||||
|
||||
auto community = session::config::community(base_url_chars, room_chars, pub_key_hex_chars);
|
||||
|
||||
env->ReleaseStringUTFChars(base_url, base_url_chars);
|
||||
env->ReleaseStringUTFChars(room, room_chars);
|
||||
env->ReleaseStringUTFChars(pub_key_hex, pub_key_hex_chars);
|
||||
return community;
|
||||
}
|
||||
|
||||
jobject serialize_expiry(JNIEnv *env, const session::config::expiration_mode& mode, const std::chrono::seconds& time_seconds) {
|
||||
jclass none = env->FindClass("network/loki/messenger/libsession_util/util/ExpiryMode$NONE");
|
||||
jfieldID none_instance = env->GetStaticFieldID(none, "INSTANCE", "Lnetwork/loki/messenger/libsession_util/util/ExpiryMode$NONE;");
|
||||
jclass after_send = env->FindClass("network/loki/messenger/libsession_util/util/ExpiryMode$AfterSend");
|
||||
jmethodID send_init = env->GetMethodID(after_send, "<init>", "(J)V");
|
||||
jclass after_read = env->FindClass("network/loki/messenger/libsession_util/util/ExpiryMode$AfterRead");
|
||||
jmethodID read_init = env->GetMethodID(after_read, "<init>", "(J)V");
|
||||
|
||||
if (mode == session::config::expiration_mode::none) {
|
||||
return env->GetStaticObjectField(none, none_instance);
|
||||
} else if (mode == session::config::expiration_mode::after_send) {
|
||||
return env->NewObject(after_send, send_init, time_seconds.count());
|
||||
} else if (mode == session::config::expiration_mode::after_read) {
|
||||
return env->NewObject(after_read, read_init, time_seconds.count());
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
std::pair<session::config::expiration_mode, long> deserialize_expiry(JNIEnv *env, jobject expiry_mode) {
|
||||
jclass parent = env->FindClass("network/loki/messenger/libsession_util/util/ExpiryMode");
|
||||
jclass after_read = env->FindClass("network/loki/messenger/libsession_util/util/ExpiryMode$AfterRead");
|
||||
jclass after_send = env->FindClass("network/loki/messenger/libsession_util/util/ExpiryMode$AfterSend");
|
||||
jfieldID duration_seconds = env->GetFieldID(parent, "expirySeconds", "J");
|
||||
|
||||
jclass object_class = env->GetObjectClass(expiry_mode);
|
||||
|
||||
if (object_class == after_read) {
|
||||
return std::pair(session::config::expiration_mode::after_read, env->GetLongField(expiry_mode, duration_seconds));
|
||||
} else if (object_class == after_send) {
|
||||
return std::pair(session::config::expiration_mode::after_send, env->GetLongField(expiry_mode, duration_seconds));
|
||||
}
|
||||
return std::pair(session::config::expiration_mode::none, 0);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
extern "C"
|
||||
JNIEXPORT jobject JNICALL
|
||||
Java_network_loki_messenger_libsession_1util_util_Sodium_ed25519KeyPair(JNIEnv *env, jobject thiz, jbyteArray seed) {
|
||||
std::array<unsigned char, 32> ed_pk; // NOLINT(cppcoreguidelines-pro-type-member-init)
|
||||
std::array<unsigned char, 64> ed_sk; // NOLINT(cppcoreguidelines-pro-type-member-init)
|
||||
auto seed_bytes = util::ustring_from_bytes(env, seed);
|
||||
crypto_sign_ed25519_seed_keypair(ed_pk.data(), ed_sk.data(), seed_bytes.data());
|
||||
|
||||
jclass kp_class = env->FindClass("network/loki/messenger/libsession_util/util/KeyPair");
|
||||
jmethodID kp_constructor = env->GetMethodID(kp_class, "<init>", "([B[B)V");
|
||||
|
||||
jbyteArray pk_jarray = util::bytes_from_ustring(env, session::ustring_view {ed_pk.data(), ed_pk.size()});
|
||||
jbyteArray sk_jarray = util::bytes_from_ustring(env, session::ustring_view {ed_sk.data(), ed_sk.size()});
|
||||
|
||||
jobject return_obj = env->NewObject(kp_class, kp_constructor, pk_jarray, sk_jarray);
|
||||
return return_obj;
|
||||
}
|
||||
extern "C"
|
||||
JNIEXPORT jbyteArray JNICALL
|
||||
Java_network_loki_messenger_libsession_1util_util_Sodium_ed25519PkToCurve25519(JNIEnv *env,
|
||||
jobject thiz,
|
||||
jbyteArray pk) {
|
||||
auto ed_pk = util::ustring_from_bytes(env, pk);
|
||||
std::array<unsigned char, 32> curve_pk; // NOLINT(cppcoreguidelines-pro-type-member-init)
|
||||
int success = crypto_sign_ed25519_pk_to_curve25519(curve_pk.data(), ed_pk.data());
|
||||
if (success != 0) {
|
||||
jclass exception = env->FindClass("java/lang/Exception");
|
||||
env->ThrowNew(exception, "Invalid crypto_sign_ed25519_pk_to_curve25519 operation");
|
||||
return nullptr;
|
||||
}
|
||||
jbyteArray curve_pk_jarray = util::bytes_from_ustring(env, session::ustring_view {curve_pk.data(), curve_pk.size()});
|
||||
return curve_pk_jarray;
|
||||
}
|
||||
extern "C"
|
||||
JNIEXPORT jobject JNICALL
|
||||
Java_network_loki_messenger_libsession_1util_util_BaseCommunityInfo_00024Companion_parseFullUrl(
|
||||
JNIEnv *env, jobject thiz, jstring full_url) {
|
||||
auto bytes = env->GetStringUTFChars(full_url, nullptr);
|
||||
auto [base, room, pk] = session::config::community::parse_full_url(bytes);
|
||||
env->ReleaseStringUTFChars(full_url, bytes);
|
||||
|
||||
jclass clazz = env->FindClass("kotlin/Triple");
|
||||
jmethodID constructor = env->GetMethodID(clazz, "<init>", "(Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;)V");
|
||||
|
||||
auto base_j = env->NewStringUTF(base.data());
|
||||
auto room_j = env->NewStringUTF(room.data());
|
||||
auto pk_jbytes = util::bytes_from_ustring(env, pk);
|
||||
|
||||
jobject triple = env->NewObject(clazz, constructor, base_j, room_j, pk_jbytes);
|
||||
return triple;
|
||||
}
|
||||
extern "C"
|
||||
JNIEXPORT jstring JNICALL
|
||||
Java_network_loki_messenger_libsession_1util_util_BaseCommunityInfo_fullUrl(JNIEnv *env,
|
||||
jobject thiz) {
|
||||
auto deserialized = util::deserialize_base_community(env, thiz);
|
||||
auto full_url = deserialized.full_url();
|
||||
return env->NewStringUTF(full_url.data());
|
||||
}
|
24
libsession-util/src/main/cpp/util.h
Normal file
24
libsession-util/src/main/cpp/util.h
Normal file
@@ -0,0 +1,24 @@
|
||||
#ifndef SESSION_ANDROID_UTIL_H
|
||||
#define SESSION_ANDROID_UTIL_H
|
||||
|
||||
#include <jni.h>
|
||||
#include <array>
|
||||
#include <optional>
|
||||
#include "session/types.hpp"
|
||||
#include "session/config/profile_pic.hpp"
|
||||
#include "session/config/user_groups.hpp"
|
||||
#include "session/config/expiring.hpp"
|
||||
|
||||
namespace util {
|
||||
extern std::mutex util_mutex_;
|
||||
jbyteArray bytes_from_ustring(JNIEnv* env, session::ustring_view from_str);
|
||||
session::ustring ustring_from_bytes(JNIEnv* env, jbyteArray byteArray);
|
||||
jobject serialize_user_pic(JNIEnv *env, session::config::profile_pic pic);
|
||||
std::pair<jstring, jbyteArray> deserialize_user_pic(JNIEnv *env, jobject user_pic);
|
||||
jobject serialize_base_community(JNIEnv *env, const session::config::community& base_community);
|
||||
session::config::community deserialize_base_community(JNIEnv *env, jobject base_community);
|
||||
jobject serialize_expiry(JNIEnv *env, const session::config::expiration_mode& mode, const std::chrono::seconds& time_seconds);
|
||||
std::pair<session::config::expiration_mode, long> deserialize_expiry(JNIEnv *env, jobject expiry_mode);
|
||||
}
|
||||
|
||||
#endif
|
@@ -0,0 +1,200 @@
|
||||
package network.loki.messenger.libsession_util
|
||||
|
||||
import network.loki.messenger.libsession_util.util.BaseCommunityInfo
|
||||
import network.loki.messenger.libsession_util.util.ConfigPush
|
||||
import network.loki.messenger.libsession_util.util.Contact
|
||||
import network.loki.messenger.libsession_util.util.Conversation
|
||||
import network.loki.messenger.libsession_util.util.GroupInfo
|
||||
import network.loki.messenger.libsession_util.util.UserPic
|
||||
import org.session.libsignal.protos.SignalServiceProtos.SharedConfigMessage.Kind
|
||||
import org.session.libsignal.utilities.IdPrefix
|
||||
import org.session.libsignal.utilities.Log
|
||||
|
||||
|
||||
sealed class ConfigBase(protected val /* yucky */ pointer: Long) {
|
||||
companion object {
|
||||
init {
|
||||
System.loadLibrary("session_util")
|
||||
}
|
||||
external fun kindFor(configNamespace: Int): Class<ConfigBase>
|
||||
|
||||
fun ConfigBase.protoKindFor(): Kind = when (this) {
|
||||
is UserProfile -> Kind.USER_PROFILE
|
||||
is Contacts -> Kind.CONTACTS
|
||||
is ConversationVolatileConfig -> Kind.CONVO_INFO_VOLATILE
|
||||
is UserGroupsConfig -> Kind.GROUPS
|
||||
}
|
||||
|
||||
// TODO: time in future to activate (hardcoded to 1st jan 2024 for testing, change before release)
|
||||
private const val ACTIVATE_TIME = 1690761600000
|
||||
|
||||
fun isNewConfigEnabled(forced: Boolean, currentTime: Long) =
|
||||
forced || currentTime >= ACTIVATE_TIME
|
||||
|
||||
const val PRIORITY_HIDDEN = -1
|
||||
const val PRIORITY_VISIBLE = 0
|
||||
const val PRIORITY_PINNED = 1
|
||||
|
||||
}
|
||||
|
||||
external fun dirty(): Boolean
|
||||
external fun needsPush(): Boolean
|
||||
external fun needsDump(): Boolean
|
||||
external fun push(): ConfigPush
|
||||
external fun dump(): ByteArray
|
||||
external fun encryptionDomain(): String
|
||||
external fun confirmPushed(seqNo: Long, newHash: String)
|
||||
external fun merge(toMerge: Array<Pair<String,ByteArray>>): Int
|
||||
external fun currentHashes(): List<String>
|
||||
|
||||
external fun configNamespace(): Int
|
||||
|
||||
// Singular merge
|
||||
external fun merge(toMerge: Pair<String,ByteArray>): Int
|
||||
|
||||
external fun free()
|
||||
|
||||
}
|
||||
|
||||
class Contacts(pointer: Long) : ConfigBase(pointer) {
|
||||
companion object {
|
||||
init {
|
||||
System.loadLibrary("session_util")
|
||||
}
|
||||
external fun newInstance(ed25519SecretKey: ByteArray): Contacts
|
||||
external fun newInstance(ed25519SecretKey: ByteArray, initialDump: ByteArray): Contacts
|
||||
}
|
||||
|
||||
external fun get(sessionId: String): Contact?
|
||||
external fun getOrConstruct(sessionId: String): Contact
|
||||
external fun all(): List<Contact>
|
||||
external fun set(contact: Contact)
|
||||
external fun erase(sessionId: String): Boolean
|
||||
|
||||
/**
|
||||
* Similar to [updateIfExists], but will create the underlying contact if it doesn't exist before passing to [updateFunction]
|
||||
*/
|
||||
fun upsertContact(sessionId: String, updateFunction: Contact.()->Unit = {}) {
|
||||
if (sessionId.startsWith(IdPrefix.BLINDED.value)) {
|
||||
Log.w("Loki", "Trying to create a contact with a blinded ID prefix")
|
||||
return
|
||||
} else if (sessionId.startsWith(IdPrefix.UN_BLINDED.value)) {
|
||||
Log.w("Loki", "Trying to create a contact with an un-blinded ID prefix")
|
||||
return
|
||||
} else if (sessionId.startsWith(IdPrefix.BLINDEDV2.value)) {
|
||||
Log.w("Loki", "Trying to create a contact with a blindedv2 ID prefix")
|
||||
return
|
||||
}
|
||||
val contact = getOrConstruct(sessionId)
|
||||
updateFunction(contact)
|
||||
set(contact)
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates the contact by sessionId with a given [updateFunction], and applies to the underlying config.
|
||||
* the [updateFunction] doesn't run if there is no contact
|
||||
*/
|
||||
fun updateIfExists(sessionId: String, updateFunction: Contact.()->Unit) {
|
||||
if (sessionId.startsWith(IdPrefix.BLINDED.value)) {
|
||||
Log.w("Loki", "Trying to create a contact with a blinded ID prefix")
|
||||
return
|
||||
} else if (sessionId.startsWith(IdPrefix.UN_BLINDED.value)) {
|
||||
Log.w("Loki", "Trying to create a contact with an un-blinded ID prefix")
|
||||
return
|
||||
} else if (sessionId.startsWith(IdPrefix.BLINDEDV2.value)) {
|
||||
Log.w("Loki", "Trying to create a contact with a blindedv2 ID prefix")
|
||||
return
|
||||
}
|
||||
val contact = get(sessionId) ?: return
|
||||
updateFunction(contact)
|
||||
set(contact)
|
||||
}
|
||||
}
|
||||
|
||||
class UserProfile(pointer: Long) : ConfigBase(pointer) {
|
||||
companion object {
|
||||
init {
|
||||
System.loadLibrary("session_util")
|
||||
}
|
||||
external fun newInstance(ed25519SecretKey: ByteArray): UserProfile
|
||||
external fun newInstance(ed25519SecretKey: ByteArray, initialDump: ByteArray): UserProfile
|
||||
}
|
||||
|
||||
external fun setName(newName: String)
|
||||
external fun getName(): String?
|
||||
external fun getPic(): UserPic
|
||||
external fun setPic(userPic: UserPic)
|
||||
external fun setNtsPriority(priority: Int)
|
||||
external fun getNtsPriority(): Int
|
||||
}
|
||||
|
||||
class ConversationVolatileConfig(pointer: Long): ConfigBase(pointer) {
|
||||
companion object {
|
||||
init {
|
||||
System.loadLibrary("session_util")
|
||||
}
|
||||
external fun newInstance(ed25519SecretKey: ByteArray): ConversationVolatileConfig
|
||||
external fun newInstance(ed25519SecretKey: ByteArray, initialDump: ByteArray): ConversationVolatileConfig
|
||||
}
|
||||
|
||||
external fun getOneToOne(pubKeyHex: String): Conversation.OneToOne?
|
||||
external fun getOrConstructOneToOne(pubKeyHex: String): Conversation.OneToOne
|
||||
external fun eraseOneToOne(pubKeyHex: String): Boolean
|
||||
|
||||
external fun getCommunity(baseUrl: String, room: String): Conversation.Community?
|
||||
external fun getOrConstructCommunity(baseUrl: String, room: String, pubKeyHex: String): Conversation.Community
|
||||
external fun getOrConstructCommunity(baseUrl: String, room: String, pubKey: ByteArray): Conversation.Community
|
||||
external fun eraseCommunity(community: Conversation.Community): Boolean
|
||||
external fun eraseCommunity(baseUrl: String, room: String): Boolean
|
||||
|
||||
external fun getLegacyClosedGroup(groupId: String): Conversation.LegacyGroup?
|
||||
external fun getOrConstructLegacyGroup(groupId: String): Conversation.LegacyGroup
|
||||
external fun eraseLegacyClosedGroup(groupId: String): Boolean
|
||||
external fun erase(conversation: Conversation): Boolean
|
||||
|
||||
external fun set(toStore: Conversation)
|
||||
|
||||
/**
|
||||
* Erase all conversations that do not satisfy the `predicate`, similar to [MutableList.removeAll]
|
||||
*/
|
||||
external fun eraseAll(predicate: (Conversation) -> Boolean): Int
|
||||
|
||||
external fun sizeOneToOnes(): Int
|
||||
external fun sizeCommunities(): Int
|
||||
external fun sizeLegacyClosedGroups(): Int
|
||||
external fun size(): Int
|
||||
|
||||
external fun empty(): Boolean
|
||||
|
||||
external fun allOneToOnes(): List<Conversation.OneToOne>
|
||||
external fun allCommunities(): List<Conversation.Community>
|
||||
external fun allLegacyClosedGroups(): List<Conversation.LegacyGroup>
|
||||
external fun all(): List<Conversation>
|
||||
|
||||
}
|
||||
|
||||
class UserGroupsConfig(pointer: Long): ConfigBase(pointer) {
|
||||
companion object {
|
||||
init {
|
||||
System.loadLibrary("session_util")
|
||||
}
|
||||
external fun newInstance(ed25519SecretKey: ByteArray): UserGroupsConfig
|
||||
external fun newInstance(ed25519SecretKey: ByteArray, initialDump: ByteArray): UserGroupsConfig
|
||||
}
|
||||
|
||||
external fun getCommunityInfo(baseUrl: String, room: String): GroupInfo.CommunityGroupInfo?
|
||||
external fun getLegacyGroupInfo(sessionId: String): GroupInfo.LegacyGroupInfo?
|
||||
external fun getOrConstructCommunityInfo(baseUrl: String, room: String, pubKeyHex: String): GroupInfo.CommunityGroupInfo
|
||||
external fun getOrConstructLegacyGroupInfo(sessionId: String): GroupInfo.LegacyGroupInfo
|
||||
external fun set(groupInfo: GroupInfo)
|
||||
external fun erase(communityInfo: GroupInfo)
|
||||
external fun eraseCommunity(baseCommunityInfo: BaseCommunityInfo): Boolean
|
||||
external fun eraseCommunity(server: String, room: String): Boolean
|
||||
external fun eraseLegacyGroup(sessionId: String): Boolean
|
||||
external fun sizeCommunityInfo(): Int
|
||||
external fun sizeLegacyGroupInfo(): Int
|
||||
external fun size(): Int
|
||||
external fun all(): List<GroupInfo>
|
||||
external fun allCommunityInfo(): List<GroupInfo.CommunityGroupInfo>
|
||||
external fun allLegacyGroupInfo(): List<GroupInfo.LegacyGroupInfo>
|
||||
}
|
@@ -0,0 +1,11 @@
|
||||
package network.loki.messenger.libsession_util.util
|
||||
|
||||
data class BaseCommunityInfo(val baseUrl: String, val room: String, val pubKeyHex: String) {
|
||||
companion object {
|
||||
init {
|
||||
System.loadLibrary("session_util")
|
||||
}
|
||||
external fun parseFullUrl(fullUrl: String): Triple<String, String, ByteArray>?
|
||||
}
|
||||
external fun fullUrl(): String
|
||||
}
|
@@ -0,0 +1,13 @@
|
||||
package network.loki.messenger.libsession_util.util
|
||||
|
||||
data class Contact(
|
||||
val id: String,
|
||||
var name: String = "",
|
||||
var nickname: String = "",
|
||||
var approved: Boolean = false,
|
||||
var approvedMe: Boolean = false,
|
||||
var blocked: Boolean = false,
|
||||
var profilePicture: UserPic = UserPic.DEFAULT,
|
||||
var priority: Int = 0,
|
||||
var expiryMode: ExpiryMode,
|
||||
)
|
@@ -0,0 +1,25 @@
|
||||
package network.loki.messenger.libsession_util.util
|
||||
|
||||
sealed class Conversation {
|
||||
|
||||
abstract var lastRead: Long
|
||||
abstract var unread: Boolean
|
||||
|
||||
data class OneToOne(
|
||||
val sessionId: String,
|
||||
override var lastRead: Long,
|
||||
override var unread: Boolean
|
||||
): Conversation()
|
||||
|
||||
data class Community(
|
||||
val baseCommunityInfo: BaseCommunityInfo,
|
||||
override var lastRead: Long,
|
||||
override var unread: Boolean
|
||||
) : Conversation()
|
||||
|
||||
data class LegacyGroup(
|
||||
val groupId: String,
|
||||
override var lastRead: Long,
|
||||
override var unread: Boolean
|
||||
): Conversation()
|
||||
}
|
@@ -0,0 +1,7 @@
|
||||
package network.loki.messenger.libsession_util.util
|
||||
|
||||
sealed class ExpiryMode(val expirySeconds: Long) {
|
||||
object NONE: ExpiryMode(0)
|
||||
class AfterSend(seconds: Long): ExpiryMode(seconds)
|
||||
class AfterRead(seconds: Long): ExpiryMode(seconds)
|
||||
}
|
@@ -0,0 +1,53 @@
|
||||
package network.loki.messenger.libsession_util.util
|
||||
|
||||
sealed class GroupInfo {
|
||||
|
||||
data class CommunityGroupInfo(val community: BaseCommunityInfo, val priority: Int) : GroupInfo()
|
||||
|
||||
data class LegacyGroupInfo(
|
||||
val sessionId: String,
|
||||
val name: String,
|
||||
val members: Map<String, Boolean>,
|
||||
val encPubKey: ByteArray,
|
||||
val encSecKey: ByteArray,
|
||||
val priority: Int,
|
||||
val disappearingTimer: Long,
|
||||
val joinedAt: Long
|
||||
): GroupInfo() {
|
||||
companion object {
|
||||
@Suppress("FunctionName")
|
||||
external fun NAME_MAX_LENGTH(): Int
|
||||
}
|
||||
|
||||
override fun equals(other: Any?): Boolean {
|
||||
if (this === other) return true
|
||||
if (javaClass != other?.javaClass) return false
|
||||
|
||||
other as LegacyGroupInfo
|
||||
|
||||
if (sessionId != other.sessionId) return false
|
||||
if (name != other.name) return false
|
||||
if (members != other.members) return false
|
||||
if (!encPubKey.contentEquals(other.encPubKey)) return false
|
||||
if (!encSecKey.contentEquals(other.encSecKey)) return false
|
||||
if (priority != other.priority) return false
|
||||
if (disappearingTimer != other.disappearingTimer) return false
|
||||
if (joinedAt != other.joinedAt) return false
|
||||
|
||||
return true
|
||||
}
|
||||
|
||||
override fun hashCode(): Int {
|
||||
var result = sessionId.hashCode()
|
||||
result = 31 * result + name.hashCode()
|
||||
result = 31 * result + members.hashCode()
|
||||
result = 31 * result + encPubKey.contentHashCode()
|
||||
result = 31 * result + encSecKey.contentHashCode()
|
||||
result = 31 * result + priority
|
||||
result = 31 * result + disappearingTimer.hashCode()
|
||||
result = 31 * result + joinedAt.hashCode()
|
||||
return result
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@@ -0,0 +1,9 @@
|
||||
package network.loki.messenger.libsession_util.util
|
||||
|
||||
object Sodium {
|
||||
init {
|
||||
System.loadLibrary("session_util")
|
||||
}
|
||||
external fun ed25519KeyPair(seed: ByteArray): KeyPair
|
||||
external fun ed25519PkToCurve25519(pk: ByteArray): ByteArray
|
||||
}
|
@@ -0,0 +1,67 @@
|
||||
package network.loki.messenger.libsession_util.util
|
||||
|
||||
data class ConfigPush(val config: ByteArray, val seqNo: Long, val obsoleteHashes: List<String>) {
|
||||
override fun equals(other: Any?): Boolean {
|
||||
if (this === other) return true
|
||||
if (javaClass != other?.javaClass) return false
|
||||
|
||||
other as ConfigPush
|
||||
|
||||
if (!config.contentEquals(other.config)) return false
|
||||
if (seqNo != other.seqNo) return false
|
||||
if (obsoleteHashes != other.obsoleteHashes) return false
|
||||
|
||||
return true
|
||||
}
|
||||
|
||||
override fun hashCode(): Int {
|
||||
var result = config.contentHashCode()
|
||||
result = 31 * result + seqNo.hashCode()
|
||||
result = 31 * result + obsoleteHashes.hashCode()
|
||||
return result
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
data class UserPic(val url: String, val key: ByteArray) {
|
||||
companion object {
|
||||
val DEFAULT = UserPic("", byteArrayOf())
|
||||
}
|
||||
override fun equals(other: Any?): Boolean {
|
||||
if (this === other) return true
|
||||
if (javaClass != other?.javaClass) return false
|
||||
|
||||
other as UserPic
|
||||
|
||||
if (url != other.url) return false
|
||||
if (!key.contentEquals(other.key)) return false
|
||||
|
||||
return true
|
||||
}
|
||||
|
||||
override fun hashCode(): Int {
|
||||
var result = url.hashCode()
|
||||
result = 31 * result + key.contentHashCode()
|
||||
return result
|
||||
}
|
||||
}
|
||||
|
||||
data class KeyPair(val pubKey: ByteArray, val secretKey: ByteArray) {
|
||||
override fun equals(other: Any?): Boolean {
|
||||
if (this === other) return true
|
||||
if (javaClass != other?.javaClass) return false
|
||||
|
||||
other as KeyPair
|
||||
|
||||
if (!pubKey.contentEquals(other.pubKey)) return false
|
||||
if (!secretKey.contentEquals(other.secretKey)) return false
|
||||
|
||||
return true
|
||||
}
|
||||
|
||||
override fun hashCode(): Int {
|
||||
var result = pubKey.contentHashCode()
|
||||
result = 31 * result + secretKey.contentHashCode()
|
||||
return result
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user