Skip to content

Commit c3c6ea4

Browse files
[SES-3717] - Add support for multi-part config and tidy up JNI usages (#6)
1 parent 741a071 commit c3c6ea4

23 files changed

+482
-528
lines changed

.drone.yml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ steps:
1616
environment:
1717
ANDROID_HOME: /usr/lib/android-sdk
1818
commands:
19-
- apt-get -y install ninja-build
19+
- apt-get -y update && apt-get -y install ninja-build
2020
- update-java-alternatives -s java-1.17.0-openjdk-amd64
2121
- env VERSION=`git describe --tags --dirty` ./gradlew publish
2222

@@ -26,5 +26,5 @@ steps:
2626
SSH_KEY:
2727
from_secret: SSH_KEY
2828
commands:
29-
- apt-get -y install python3
29+
- apt-get -y update && apt-get -y install python3
3030
- ./scripts/upload-maven-artifacts.py

library/src/main/cpp/config_base.cpp

Lines changed: 24 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -29,24 +29,17 @@ Java_network_loki_messenger_libsession_1util_ConfigBase_push(JNIEnv *env, jobjec
2929
return jni_utils::run_catching_cxx_exception_or_throws<jobject>(env, [=] {
3030
std::lock_guard lock{util::util_mutex_};
3131
auto config = ptrToConfigBase(env, thiz);
32-
auto push_tuple = config->push();
33-
auto to_push_str = std::get<1>(push_tuple);
34-
auto to_delete = std::get<2>(push_tuple);
32+
auto [seq_no, to_push, to_delete] = config->push();
33+
34+
jobject messages = jni_utils::jlist_from_collection(env, to_push, [](JNIEnv *env, const std::vector<unsigned char> &data) {
35+
return jni_utils::session_bytes_from_range(env, data);
36+
});
37+
38+
jobject obsoleteHashes = jni_utils::jstring_list_from_collection(env, to_delete);
3539

36-
jbyteArray returnByteArray = util::bytes_from_vector(env, to_push_str);
37-
jlong seqNo = std::get<0>(push_tuple);
3840
jclass returnObjectClass = env->FindClass("network/loki/messenger/libsession_util/util/ConfigPush");
39-
jclass stackClass = env->FindClass("java/util/Stack");
40-
jmethodID methodId = env->GetMethodID(returnObjectClass, "<init>", "([BJLjava/util/List;)V");
41-
jmethodID stack_init = env->GetMethodID(stackClass, "<init>", "()V");
42-
jobject our_stack = env->NewObject(stackClass, stack_init);
43-
jmethodID push_stack = env->GetMethodID(stackClass, "push", "(Ljava/lang/Object;)Ljava/lang/Object;");
44-
for (auto entry : to_delete) {
45-
auto entry_jstring = env->NewStringUTF(entry.data());
46-
env->CallObjectMethod(our_stack, push_stack, entry_jstring);
47-
}
48-
jobject returnObject = env->NewObject(returnObjectClass, methodId, returnByteArray, seqNo, our_stack);
49-
return returnObject;
41+
jmethodID methodId = env->GetMethodID(returnObjectClass, "<init>", "(Ljava/util/List;JLjava/util/List;)V");
42+
return env->NewObject(returnObjectClass, methodId, messages, static_cast<jlong>(seq_no), obsoleteHashes);
5043
});
5144
}
5245

@@ -75,12 +68,20 @@ Java_network_loki_messenger_libsession_1util_ConfigBase_encryptionDomain(JNIEnv
7568
JNIEXPORT void JNICALL
7669
Java_network_loki_messenger_libsession_1util_ConfigBase_confirmPushed(JNIEnv *env, jobject thiz,
7770
jlong seq_no,
78-
jstring new_hash_jstring) {
71+
jobjectArray hash_list) {
7972
std::lock_guard lock{util::util_mutex_};
8073
auto conf = ptrToConfigBase(env, thiz);
81-
auto new_hash = env->GetStringUTFChars(new_hash_jstring, nullptr);
82-
conf->confirm_pushed(seq_no, new_hash);
83-
env->ReleaseStringUTFChars(new_hash_jstring, new_hash);
74+
auto hash_list_size = env->GetArrayLength(hash_list);
75+
std::unordered_set<std::string> hashes(hash_list_size);
76+
77+
for (int i = 0; i < hash_list_size; i++) {
78+
auto hash_jstring = jni_utils::JavaLocalRef(env, (jstring) env->GetObjectArrayElement(hash_list, i));
79+
auto hash = env->GetStringUTFChars(hash_jstring.get(), nullptr);
80+
hashes.insert(hash);
81+
env->ReleaseStringUTFChars(hash_jstring.get(), hash);
82+
}
83+
84+
conf->confirm_pushed(seq_no, hashes);
8485
}
8586

8687
#pragma clang diagnostic push
@@ -98,9 +99,7 @@ Java_network_loki_messenger_libsession_1util_ConfigBase_merge___3Lkotlin_Pair_2(
9899
auto pair = extractHashAndData(env, jElement);
99100
configs.push_back(pair);
100101
}
101-
auto returned = conf->merge(configs);
102-
auto string_stack = util::build_string_stack(env, returned);
103-
return string_stack;
102+
return jni_utils::jstring_list_from_collection(env, conf->merge(configs));
104103
});
105104
}
106105

@@ -137,16 +136,8 @@ Java_network_loki_messenger_libsession_1util_ConfigBase_00024Companion_kindFor(J
137136

138137
extern "C"
139138
JNIEXPORT jobject JNICALL
140-
Java_network_loki_messenger_libsession_1util_ConfigBase_currentHashes(JNIEnv *env, jobject thiz) {
139+
Java_network_loki_messenger_libsession_1util_ConfigBase_activeHashes(JNIEnv *env, jobject thiz) {
141140
std::lock_guard lock{util::util_mutex_};
142141
auto conf = ptrToConfigBase(env, thiz);
143-
jclass stack = env->FindClass("java/util/Stack");
144-
jmethodID init = env->GetMethodID(stack, "<init>", "()V");
145-
jobject our_stack = env->NewObject(stack, init);
146-
jmethodID push = env->GetMethodID(stack, "push", "(Ljava/lang/Object;)Ljava/lang/Object;");
147-
auto vec = conf->current_hashes();
148-
for (std::string element: vec) {
149-
env->CallObjectMethod(our_stack, push, env->NewStringUTF(element.data()));
150-
}
151-
return our_stack;
142+
return jni_utils::jstring_list_from_collection(env, conf->active_hashes());
152143
}

library/src/main/cpp/config_base.h

Lines changed: 13 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -3,31 +3,32 @@
33

44
#include "session/config/base.hpp"
55
#include "util.h"
6+
#include "jni_utils.h"
67
#include <jni.h>
78
#include <string>
89

910
inline session::config::ConfigBase* ptrToConfigBase(JNIEnv *env, jobject obj) {
10-
jclass baseClass = env->FindClass("network/loki/messenger/libsession_util/ConfigBase");
11-
jfieldID pointerField = env->GetFieldID(baseClass, "pointer", "J");
11+
auto baseClass = jni_utils::JavaLocalRef(env, env->FindClass("network/loki/messenger/libsession_util/ConfigBase"));
12+
jfieldID pointerField = env->GetFieldID(baseClass.get(), "pointer", "J");
1213
return (session::config::ConfigBase*) env->GetLongField(obj, pointerField);
1314
}
1415

1516
inline std::pair<std::string, std::vector<unsigned char>> extractHashAndData(JNIEnv *env, jobject kotlin_pair) {
16-
jclass pair = env->FindClass("kotlin/Pair");
17-
jfieldID first = env->GetFieldID(pair, "first", "Ljava/lang/Object;");
18-
jfieldID second = env->GetFieldID(pair, "second", "Ljava/lang/Object;");
19-
jstring hash_as_jstring = static_cast<jstring>(env->GetObjectField(kotlin_pair, first));
20-
jbyteArray data_as_jbytes = static_cast<jbyteArray>(env->GetObjectField(kotlin_pair, second));
21-
auto hash_as_string = env->GetStringUTFChars(hash_as_jstring, nullptr);
22-
auto data_as_vector = util::vector_from_bytes(env, data_as_jbytes);
17+
auto pair = jni_utils::JavaLocalRef(env, env->FindClass("kotlin/Pair"));
18+
jfieldID first = env->GetFieldID(pair.get(), "first", "Ljava/lang/Object;");
19+
jfieldID second = env->GetFieldID(pair.get(), "second", "Ljava/lang/Object;");
20+
auto hash_as_jstring = jni_utils::JavaLocalRef(env, static_cast<jstring>(env->GetObjectField(kotlin_pair, first)));
21+
auto data_as_jbytes = jni_utils::JavaLocalRef(env, static_cast<jbyteArray>(env->GetObjectField(kotlin_pair, second)));
22+
auto hash_as_string = env->GetStringUTFChars(hash_as_jstring.get(), nullptr);
23+
auto data_as_vector = util::vector_from_bytes(env, data_as_jbytes.get());
2324
auto ret_pair = std::pair<std::string, std::vector<unsigned char>>{hash_as_string, data_as_vector};
24-
env->ReleaseStringUTFChars(hash_as_jstring, hash_as_string);
25+
env->ReleaseStringUTFChars(hash_as_jstring.get(), hash_as_string);
2526
return ret_pair;
2627
}
2728

2829
inline session::config::ConfigSig* ptrToConfigSig(JNIEnv* env, jobject obj) {
29-
jclass sigClass = env->FindClass("network/loki/messenger/libsession_util/ConfigSig");
30-
jfieldID pointerField = env->GetFieldID(sigClass, "pointer", "J");
30+
auto sigClass = jni_utils::JavaLocalRef(env, env->FindClass("network/loki/messenger/libsession_util/ConfigSig"));
31+
jfieldID pointerField = env->GetFieldID(sigClass.get(), "pointer", "J");
3132
return (session::config::ConfigSig*) env->GetLongField(obj, pointerField);
3233
}
3334

library/src/main/cpp/contacts.cpp

Lines changed: 1 addition & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -69,14 +69,6 @@ Java_network_loki_messenger_libsession_1util_Contacts_all(JNIEnv *env, jobject t
6969
return jni_utils::run_catching_cxx_exception_or_throws<jobject>(env, [=] {
7070
std::lock_guard lock{util::util_mutex_};
7171
auto contacts = ptrToContacts(env, thiz);
72-
jclass stack = env->FindClass("java/util/Stack");
73-
jmethodID init = env->GetMethodID(stack, "<init>", "()V");
74-
jobject our_stack = env->NewObject(stack, init);
75-
jmethodID push = env->GetMethodID(stack, "push", "(Ljava/lang/Object;)Ljava/lang/Object;");
76-
for (const auto &contact: *contacts) {
77-
auto contact_obj = serialize_contact(env, contact);
78-
env->CallObjectMethod(our_stack, push, contact_obj);
79-
}
80-
return our_stack;
72+
return jni_utils::jlist_from_collection(env, *ptrToContacts(env, thiz), serialize_contact);
8173
});
8274
}

library/src/main/cpp/contacts.h

Lines changed: 25 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -5,27 +5,28 @@
55
#include <vector>
66
#include "session/config/contacts.hpp"
77
#include "util.h"
8+
#include "jni_utils.h"
89

910
inline session::config::Contacts *ptrToContacts(JNIEnv *env, jobject obj) {
10-
jclass contactsClass = env->FindClass("network/loki/messenger/libsession_util/Contacts");
11-
jfieldID pointerField = env->GetFieldID(contactsClass, "pointer", "J");
11+
auto contactsClass = jni_utils::JavaLocalRef(env, env->FindClass("network/loki/messenger/libsession_util/Contacts"));
12+
jfieldID pointerField = env->GetFieldID(contactsClass.get(), "pointer", "J");
1213
return (session::config::Contacts *) env->GetLongField(obj, pointerField);
1314
}
1415

1516
inline jobject serialize_contact(JNIEnv *env, session::config::contact_info info) {
16-
jclass contactClass = env->FindClass("network/loki/messenger/libsession_util/util/Contact");
17-
jmethodID constructor = env->GetMethodID(contactClass, "<init>", "(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;ZZZLnetwork/loki/messenger/libsession_util/util/UserPic;JLnetwork/loki/messenger/libsession_util/util/ExpiryMode;)V");
18-
jstring id = env->NewStringUTF(info.session_id.data());
19-
jstring name = env->NewStringUTF(info.name.data());
20-
jstring nickname = env->NewStringUTF(info.nickname.data());
17+
auto contactClass = jni_utils::JavaLocalRef(env, env->FindClass("network/loki/messenger/libsession_util/util/Contact"));
18+
jmethodID constructor = env->GetMethodID(contactClass.get(), "<init>", "(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;ZZZLnetwork/loki/messenger/libsession_util/util/UserPic;JLnetwork/loki/messenger/libsession_util/util/ExpiryMode;)V");
19+
auto id = jni_utils::JavaLocalRef(env, env->NewStringUTF(info.session_id.data()));
20+
auto name = jni_utils::JavaLocalRef(env, env->NewStringUTF(info.name.data()));
21+
auto nickname = jni_utils::JavaLocalRef(env, env->NewStringUTF(info.nickname.data()));
2122
jboolean approved, approvedMe, blocked;
2223
approved = info.approved;
2324
approvedMe = info.approved_me;
2425
blocked = info.blocked;
2526
auto created = info.created;
26-
jobject profilePic = util::serialize_user_pic(env, info.profile_picture);
27-
jobject returnObj = env->NewObject(contactClass, constructor, id, name, nickname, approved,
28-
approvedMe, blocked, profilePic, (jlong)info.priority,
27+
auto profilePic = jni_utils::JavaLocalRef(env, util::serialize_user_pic(env, info.profile_picture));
28+
jobject returnObj = env->NewObject(contactClass.get(), constructor, id.get(), name.get(), nickname.get(), approved,
29+
approvedMe, blocked, profilePic.get(), (jlong)info.priority,
2930
util::serialize_expiry(env, info.exp_mode, info.exp_timer));
3031
return returnObj;
3132
}
@@ -44,35 +45,34 @@ inline session::config::contact_info deserialize_contact(JNIEnv *env, jobject in
4445
"Lnetwork/loki/messenger/libsession_util/util/UserPic;");
4546
getPriority = env->GetFieldID(contactClass, "priority", "J");
4647
getExpiry = env->GetFieldID(contactClass, "expiryMode", "Lnetwork/loki/messenger/libsession_util/util/ExpiryMode;");
47-
jstring name, nickname, account_id;
48-
account_id = static_cast<jstring>(env->GetObjectField(info, getId));
49-
name = static_cast<jstring>(env->GetObjectField(info, getName));
50-
nickname = static_cast<jstring>(env->GetObjectField(info, getNick));
48+
auto account_id = jni_utils::JavaLocalRef(env, static_cast<jstring>(env->GetObjectField(info, getId)));
49+
auto name = jni_utils::JavaLocalRef(env, static_cast<jstring>(env->GetObjectField(info, getName)));
50+
auto nickname = jni_utils::JavaLocalRef(env, static_cast<jstring>(env->GetObjectField(info, getNick)));
5151
bool approved, approvedMe, blocked, hidden;
5252
int priority = env->GetLongField(info, getPriority);
5353
approved = env->GetBooleanField(info, getApproved);
5454
approvedMe = env->GetBooleanField(info, getApprovedMe);
5555
blocked = env->GetBooleanField(info, getBlocked);
56-
jobject user_pic = env->GetObjectField(info, getUserPic);
57-
jobject expiry_mode = env->GetObjectField(info, getExpiry);
56+
auto user_pic = jni_utils::JavaLocalRef(env, env->GetObjectField(info, getUserPic));
57+
auto expiry_mode = jni_utils::JavaLocalRef(env, env->GetObjectField(info, getExpiry));
5858

59-
auto expiry_pair = util::deserialize_expiry(env, expiry_mode);
59+
auto expiry_pair = util::deserialize_expiry(env, expiry_mode.get());
6060

6161
std::string url;
6262
std::vector<unsigned char> key;
6363

64-
if (user_pic != nullptr) {
65-
auto deserialized_pic = util::deserialize_user_pic(env, user_pic);
64+
if (user_pic.get() != nullptr) {
65+
auto deserialized_pic = util::deserialize_user_pic(env, user_pic.get());
6666
auto url_jstring = deserialized_pic.first;
6767
auto url_bytes = env->GetStringUTFChars(url_jstring, nullptr);
6868
url = std::string(url_bytes);
6969
env->ReleaseStringUTFChars(url_jstring, url_bytes);
7070
key = util::vector_from_bytes(env, deserialized_pic.second);
7171
}
7272

73-
auto account_id_bytes = env->GetStringUTFChars(account_id, nullptr);
74-
auto name_bytes = name ? env->GetStringUTFChars(name, nullptr) : nullptr;
75-
auto nickname_bytes = nickname ? env->GetStringUTFChars(nickname, nullptr) : nullptr;
73+
auto account_id_bytes = env->GetStringUTFChars(account_id.get(), nullptr);
74+
auto name_bytes = name.get() ? env->GetStringUTFChars(name.get(), nullptr) : nullptr;
75+
auto nickname_bytes = nickname.get() ? env->GetStringUTFChars(nickname.get(), nullptr) : nullptr;
7676

7777
auto contact_info = conf->get_or_construct(account_id_bytes);
7878
if (name_bytes) {
@@ -90,12 +90,12 @@ inline session::config::contact_info deserialize_contact(JNIEnv *env, jobject in
9090
contact_info.profile_picture = session::config::profile_pic();
9191
}
9292

93-
env->ReleaseStringUTFChars(account_id, account_id_bytes);
93+
env->ReleaseStringUTFChars(account_id.get(), account_id_bytes);
9494
if (name_bytes) {
95-
env->ReleaseStringUTFChars(name, name_bytes);
95+
env->ReleaseStringUTFChars(name.get(), name_bytes);
9696
}
9797
if (nickname_bytes) {
98-
env->ReleaseStringUTFChars(nickname, nickname_bytes);
98+
env->ReleaseStringUTFChars(nickname.get(), nickname_bytes);
9999
}
100100

101101
contact_info.priority = priority;

library/src/main/cpp/conversation.cpp

Lines changed: 11 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
#include <jni.h>
22
#include "conversation.h"
3+
#include "jni_utils.h"
34

45

56
extern "C"
@@ -266,57 +267,35 @@ Java_network_loki_messenger_libsession_1util_ConversationVolatileConfig_all(JNIE
266267
jobject thiz) {
267268
std::lock_guard lock{util::util_mutex_};
268269
auto convos = ptrToConvoInfo(env, thiz);
269-
jclass stack = env->FindClass("java/util/Stack");
270-
jmethodID init = env->GetMethodID(stack, "<init>", "()V");
271-
jobject our_stack = env->NewObject(stack, init);
272-
jmethodID push = env->GetMethodID(stack, "push", "(Ljava/lang/Object;)Ljava/lang/Object;");
273-
for (const auto& convo : *convos) {
274-
auto contact_obj = serialize_any(env, convo);
275-
env->CallObjectMethod(our_stack, push, contact_obj);
276-
}
277-
return our_stack;
270+
271+
return jni_utils::jlist_from_collection(env, *convos, serialize_any);
278272
}
279273
extern "C"
280274
JNIEXPORT jobject JNICALL
281275
Java_network_loki_messenger_libsession_1util_ConversationVolatileConfig_allOneToOnes(JNIEnv *env,
282276
jobject thiz) {
283277
std::lock_guard lock{util::util_mutex_};
284278
auto convos = ptrToConvoInfo(env, thiz);
285-
jclass stack = env->FindClass("java/util/Stack");
286-
jmethodID init = env->GetMethodID(stack, "<init>", "()V");
287-
jobject our_stack = env->NewObject(stack, init);
288-
jmethodID push = env->GetMethodID(stack, "push", "(Ljava/lang/Object;)Ljava/lang/Object;");
289-
for (auto contact = convos->begin_1to1(); contact != convos->end(); ++contact)
290-
env->CallObjectMethod(our_stack, push, serialize_one_to_one(env, *contact));
291-
return our_stack;
279+
return jni_utils::jlist_from_iterator(env, convos->begin_1to1(), convos->end(),
280+
serialize_one_to_one);
292281
}
293282
extern "C"
294283
JNIEXPORT jobject JNICALL
295284
Java_network_loki_messenger_libsession_1util_ConversationVolatileConfig_allCommunities(JNIEnv *env,
296285
jobject thiz) {
297286
std::lock_guard lock{util::util_mutex_};
298287
auto convos = ptrToConvoInfo(env, thiz);
299-
jclass stack = env->FindClass("java/util/Stack");
300-
jmethodID init = env->GetMethodID(stack, "<init>", "()V");
301-
jobject our_stack = env->NewObject(stack, init);
302-
jmethodID push = env->GetMethodID(stack, "push", "(Ljava/lang/Object;)Ljava/lang/Object;");
303-
for (auto contact = convos->begin_communities(); contact != convos->end(); ++contact)
304-
env->CallObjectMethod(our_stack, push, serialize_open_group(env, *contact));
305-
return our_stack;
288+
return jni_utils::jlist_from_iterator(env, convos->begin_communities(), convos->end(),
289+
serialize_open_group);
306290
}
307291
extern "C"
308292
JNIEXPORT jobject JNICALL
309293
Java_network_loki_messenger_libsession_1util_ConversationVolatileConfig_allLegacyClosedGroups(
310294
JNIEnv *env, jobject thiz) {
311295
std::lock_guard lock{util::util_mutex_};
312296
auto convos = ptrToConvoInfo(env, thiz);
313-
jclass stack = env->FindClass("java/util/Stack");
314-
jmethodID init = env->GetMethodID(stack, "<init>", "()V");
315-
jobject our_stack = env->NewObject(stack, init);
316-
jmethodID push = env->GetMethodID(stack, "push", "(Ljava/lang/Object;)Ljava/lang/Object;");
317-
for (auto contact = convos->begin_legacy_groups(); contact != convos->end(); ++contact)
318-
env->CallObjectMethod(our_stack, push, serialize_legacy_group(env, *contact));
319-
return our_stack;
297+
return jni_utils::jlist_from_iterator(env, convos->begin_legacy_groups(), convos->end(),
298+
serialize_legacy_group);
320299
}
321300

322301
extern "C"
@@ -325,13 +304,8 @@ Java_network_loki_messenger_libsession_1util_ConversationVolatileConfig_allClose
325304
jobject thiz) {
326305
std::lock_guard lock{util::util_mutex_};
327306
auto convos = ptrToConvoInfo(env, thiz);
328-
jclass stack = env->FindClass("java/util/Stack");
329-
jmethodID init = env->GetMethodID(stack, "<init>", "()V");
330-
jobject our_stack = env->NewObject(stack, init);
331-
jmethodID push = env->GetMethodID(stack, "push", "(Ljava/lang/Object;)Ljava/lang/Object;");
332-
for (auto contact = convos->begin_groups(); contact != convos->end(); ++contact)
333-
env->CallObjectMethod(our_stack, push, serialize_closed_group(env, *contact));
334-
return our_stack;
307+
return jni_utils::jlist_from_iterator(env, convos->begin_groups(), convos->end(),
308+
serialize_closed_group);
335309
}
336310

337311
extern "C"

0 commit comments

Comments
 (0)