mirror of
https://github.com/oxen-io/session-android.git
synced 2025-12-30 15:46:30 +00:00
feat: start on closed group polling for new signatures
This commit is contained in:
@@ -34,10 +34,9 @@ import androidx.lifecycle.ProcessLifecycleOwner;
|
||||
import org.conscrypt.Conscrypt;
|
||||
import org.session.libsession.avatars.AvatarHelper;
|
||||
import org.session.libsession.database.MessageDataProvider;
|
||||
import org.session.libsession.database.StorageProtocol;
|
||||
import org.session.libsession.messaging.MessagingModuleConfiguration;
|
||||
import org.session.libsession.messaging.sending_receiving.notifications.MessageNotifier;
|
||||
import org.session.libsession.messaging.sending_receiving.pollers.ClosedGroupPollerV2;
|
||||
import org.session.libsession.messaging.sending_receiving.pollers.LegacyClosedGroupPollerV2;
|
||||
import org.session.libsession.messaging.sending_receiving.pollers.Poller;
|
||||
import org.session.libsession.snode.SnodeModule;
|
||||
import org.session.libsession.utilities.Address;
|
||||
@@ -283,7 +282,7 @@ public class ApplicationContext extends Application implements DefaultLifecycleO
|
||||
if (poller != null) {
|
||||
poller.stopIfNeeded();
|
||||
}
|
||||
ClosedGroupPollerV2.getShared().stopAll();
|
||||
LegacyClosedGroupPollerV2.getShared().stopAll();
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -446,7 +445,7 @@ public class ApplicationContext extends Application implements DefaultLifecycleO
|
||||
if (poller != null) {
|
||||
poller.startIfNeeded();
|
||||
}
|
||||
ClosedGroupPollerV2.getShared().start();
|
||||
LegacyClosedGroupPollerV2.getShared().start();
|
||||
}
|
||||
|
||||
private void resubmitProfilePictureIfNeeded() {
|
||||
|
||||
@@ -56,7 +56,7 @@ import org.session.libsession.messaging.sending_receiving.attachments.DatabaseAt
|
||||
import org.session.libsession.messaging.sending_receiving.data_extraction.DataExtractionNotificationInfoMessage
|
||||
import org.session.libsession.messaging.sending_receiving.link_preview.LinkPreview
|
||||
import org.session.libsession.messaging.sending_receiving.notifications.PushRegistryV1
|
||||
import org.session.libsession.messaging.sending_receiving.pollers.ClosedGroupPollerV2
|
||||
import org.session.libsession.messaging.sending_receiving.pollers.LegacyClosedGroupPollerV2
|
||||
import org.session.libsession.messaging.sending_receiving.quotes.QuoteModel
|
||||
import org.session.libsession.messaging.utilities.SodiumUtilities
|
||||
import org.session.libsession.messaging.utilities.UpdateMessageData
|
||||
@@ -124,8 +124,11 @@ open class Storage(context: Context, helper: SQLCipherOpenHelper, private val co
|
||||
}
|
||||
address.isClosedGroup -> {
|
||||
val sessionId = address.serialize()
|
||||
val closedGroup = groups.getClosedGroup(sessionId)
|
||||
TODO("Set the closed group's convo volatile info")
|
||||
groups.getClosedGroup(sessionId) ?: return Log.d("Closed group doesn't exist locally", NullPointerException())
|
||||
val conversation = Conversation.ClosedGroup(
|
||||
sessionId, 0, false
|
||||
)
|
||||
volatile.set(conversation)
|
||||
}
|
||||
address.isOpenGroup -> {
|
||||
// these should be added on the group join / group info fetch
|
||||
@@ -465,7 +468,7 @@ open class Storage(context: Context, helper: SQLCipherOpenHelper, private val co
|
||||
is ConversationVolatileConfig -> updateConvoVolatile(forConfigObject)
|
||||
is UserGroupsConfig -> updateUserGroups(forConfigObject)
|
||||
is GroupInfoConfig -> updateGroupInfo(forConfigObject)
|
||||
is GroupKeysConfig -> updateGroupKeys(forConfigObject)
|
||||
// is GroupKeysConfig -> updateGroupKeys(forConfigObject)
|
||||
is GroupMembersConfig -> updateGroupMembers(forConfigObject)
|
||||
}
|
||||
}
|
||||
@@ -545,7 +548,7 @@ open class Storage(context: Context, helper: SQLCipherOpenHelper, private val co
|
||||
is Conversation.OneToOne -> getThreadIdFor(conversation.sessionId, null, null, createThread = false)
|
||||
is Conversation.LegacyGroup -> getThreadIdFor("", conversation.groupId,null, createThread = false)
|
||||
is Conversation.Community -> getThreadIdFor("",null, "${conversation.baseCommunityInfo.baseUrl.removeSuffix("/")}.${conversation.baseCommunityInfo.room}", createThread = false)
|
||||
is Conversation.ClosedGroup -> getThreadIdFor(conversation.sessionId, null, null, createThread = false)
|
||||
is Conversation.ClosedGroup -> getThreadIdFor(conversation.sessionId, null, null, createThread = false) // New groups will be managed bia libsession
|
||||
}
|
||||
if (threadId != null) {
|
||||
if (conversation.lastRead > getLastSeen(threadId)) {
|
||||
@@ -607,6 +610,15 @@ open class Storage(context: Context, helper: SQLCipherOpenHelper, private val co
|
||||
}
|
||||
}
|
||||
|
||||
val newClosedGroups = userGroups.allClosedGroupInfo()
|
||||
for (closedGroup in newClosedGroups) {
|
||||
val recipient = Recipient.from(context, Address.fromSerialized(closedGroup.groupSessionId.hexString()), false)
|
||||
setRecipientApprovedMe(recipient, true)
|
||||
setRecipientApproved(recipient, true)
|
||||
val threadId = getOrCreateThreadIdFor(recipient.address)
|
||||
setPinned(threadId, closedGroup.priority == PRIORITY_PINNED)
|
||||
}
|
||||
|
||||
for (group in lgc) {
|
||||
val existingGroup = existingClosedGroups.firstOrNull { GroupUtil.doubleDecodeGroupId(it.encodedId) == group.sessionId.hexString() }
|
||||
val existingThread = existingGroup?.let { getThreadId(existingGroup.encodedId) }
|
||||
@@ -643,7 +655,7 @@ open class Storage(context: Context, helper: SQLCipherOpenHelper, private val co
|
||||
insertOutgoingInfoMessage(context, groupId, SignalServiceGroup.Type.CREATION, title, members.map { it.serialize() }, admins.map { it.serialize() }, threadID, formationTimestamp)
|
||||
// Don't create config group here, it's from a config update
|
||||
// Start polling
|
||||
ClosedGroupPollerV2.shared.startPolling(group.sessionId.hexString())
|
||||
LegacyClosedGroupPollerV2.shared.startPolling(group.sessionId.hexString())
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -883,8 +895,9 @@ open class Storage(context: Context, helper: SQLCipherOpenHelper, private val co
|
||||
DatabaseComponent.get(context).groupDatabase().create(groupId, title, members, avatar, relay, admins, formationTimestamp)
|
||||
}
|
||||
|
||||
override fun createNewGroup(groupName: String, groupDescription: String, members: Set<SessionId>): Optional<Boolean> {
|
||||
override fun createNewGroup(groupName: String, groupDescription: String, members: Set<SessionId>): Optional<Recipient> {
|
||||
val userGroups = configFactory.userGroups ?: return Optional.absent()
|
||||
val convoVolatile = configFactory.convoVolatile ?: return Optional.absent()
|
||||
val ourSessionId = getUserPublicKey() ?: return Optional.absent()
|
||||
val userKp = MessagingModuleConfiguration.shared.getUserED25519KeyPair() ?: return Optional.absent()
|
||||
|
||||
@@ -916,7 +929,9 @@ open class Storage(context: Context, helper: SQLCipherOpenHelper, private val co
|
||||
val newGroupRecipient = group.groupSessionId.hexString()
|
||||
val configTtl = 1 * 24 * 60 * 60 * 1000L // TODO: just testing here, 1 day so we don't fill large space on network
|
||||
// Test the sending
|
||||
val keyPush = groupKeys.pendingPush() ?: return Optional.absent()
|
||||
val keyPush = groupKeys.pendingConfig() ?: return Optional.absent()
|
||||
val pendingKey = groupKeys.pendingKey() ?: return Optional.absent()
|
||||
|
||||
val keysSnodeMessage = SnodeMessage(
|
||||
newGroupRecipient,
|
||||
Base64.encodeBytes(keyPush),
|
||||
@@ -932,7 +947,7 @@ open class Storage(context: Context, helper: SQLCipherOpenHelper, private val co
|
||||
val (infoPush, infoSeqNo) = groupInfo.push()
|
||||
val infoSnodeMessage = SnodeMessage(
|
||||
newGroupRecipient,
|
||||
Base64.encodeBytes(keyPush),
|
||||
Base64.encodeBytes(infoPush),
|
||||
configTtl,
|
||||
groupCreationTimestamp
|
||||
)
|
||||
@@ -968,13 +983,28 @@ open class Storage(context: Context, helper: SQLCipherOpenHelper, private val co
|
||||
val responseList = (response["results"] as List<RawResponse>)
|
||||
|
||||
val keyResponse = responseList[0]
|
||||
val keyHash = (keyResponse["body"] as Map<String,Any>)["hash"] as String
|
||||
val keyTimestamp = (keyResponse["body"] as Map<String,Any>)["t"] as Long
|
||||
val infoResponse = responseList[1]
|
||||
val infoHash = (infoResponse["body"] as Map<String,Any>)["hash"] as String
|
||||
val memberResponse = responseList[2]
|
||||
val memberHash = (memberResponse["body"] as Map<String,Any>)["hash"] as String
|
||||
// TODO: check response success
|
||||
groupKeys.loadKey(keyPush, keyHash, keyTimestamp, groupInfo, groupMembers)
|
||||
groupInfo.confirmPushed(infoSeqNo, infoHash)
|
||||
groupMembers.confirmPushed(memberSeqNo, memberHash)
|
||||
|
||||
configFactory.saveGroupConfigs(groupKeys, groupInfo, groupMembers) // now check poller to be all
|
||||
convoVolatile.set(Conversation.ClosedGroup(newGroupRecipient, groupCreationTimestamp, false))
|
||||
ConfigurationMessageUtilities.forceSyncConfigurationNowIfNeeded(context)
|
||||
Log.d("Group Config", "Saved group config for $newGroupRecipient")
|
||||
return Optional.of(true)
|
||||
groupKeys.free()
|
||||
groupInfo.free()
|
||||
groupMembers.free()
|
||||
val groupRecipient = Recipient.from(context, Address.fromSerialized(newGroupRecipient), false)
|
||||
setRecipientApprovedMe(groupRecipient, true)
|
||||
setRecipientApproved(groupRecipient, true)
|
||||
return Optional.of(groupRecipient)
|
||||
} catch (e: Exception) {
|
||||
Log.e("Group Config", e)
|
||||
Log.e("Group Config", "Deleting group from our group")
|
||||
@@ -1648,7 +1678,7 @@ open class Storage(context: Context, helper: SQLCipherOpenHelper, private val co
|
||||
}
|
||||
|
||||
override fun getRecipientApproved(address: Address): Boolean {
|
||||
return DatabaseComponent.get(context).recipientDatabase().getApproved(address)
|
||||
return address.isClosedGroup || DatabaseComponent.get(context).recipientDatabase().getApproved(address)
|
||||
}
|
||||
|
||||
override fun setRecipientApproved(recipient: Recipient, approved: Boolean) {
|
||||
|
||||
@@ -503,7 +503,8 @@ public class ThreadDatabase extends Database {
|
||||
}
|
||||
|
||||
public Cursor getApprovedConversationList() {
|
||||
String where = "((" + HAS_SENT + " = 1 OR " + RecipientDatabase.APPROVED + " = 1 OR "+ GroupDatabase.TABLE_NAME +"."+GROUP_ID+" LIKE '"+ LEGACY_CLOSED_GROUP_PREFIX +"%') OR " + GroupDatabase.TABLE_NAME + "." + GROUP_ID + " LIKE '" + OPEN_GROUP_PREFIX + "%') " +
|
||||
String where = "((" + HAS_SENT + " = 1 OR " + RecipientDatabase.APPROVED + " = 1 OR "+ GroupDatabase.TABLE_NAME +"."+GROUP_ID+" LIKE '"+ LEGACY_CLOSED_GROUP_PREFIX +"%' OR "+RecipientDatabase.TABLE_NAME+"."+RecipientDatabase.ADDRESS+" LIKE '"+ IdPrefix.GROUP.getValue() +"%') " +
|
||||
"OR " + GroupDatabase.TABLE_NAME + "." + GROUP_ID + " LIKE '" + OPEN_GROUP_PREFIX + "%') " +
|
||||
"AND " + ARCHIVED + " = 0 ";
|
||||
return getConversationList(where);
|
||||
}
|
||||
@@ -830,9 +831,7 @@ public class ThreadDatabase extends Database {
|
||||
}
|
||||
|
||||
private boolean deleteThreadOnEmpty(long threadId) {
|
||||
return false; // TODO: test the deletion / clearing logic here to make sure this is the desired functionality
|
||||
// Recipient threadRecipient = getRecipientForThreadId(threadId);
|
||||
// return threadRecipient != null && !threadRecipient.isOpenGroupRecipient();
|
||||
return false;
|
||||
}
|
||||
|
||||
private @NonNull String getFormattedBodyFor(@NonNull MessageRecord messageRecord) {
|
||||
|
||||
@@ -350,6 +350,6 @@ class ConfigFactory(
|
||||
) {
|
||||
val pubKey = groupInfo.id().hexString()
|
||||
val timestamp = SnodeAPI.nowWithOffset
|
||||
configDatabase.storeGroupConfigs(pubKey, groupKeys.dump(), groupInfo.dump(), groupMembers.dump(), timestamp)
|
||||
configDatabase.storeGroupConfigs(pubKey, groupKeys.keyDump(), groupInfo.dump(), groupMembers.dump(), timestamp)
|
||||
}
|
||||
}
|
||||
@@ -4,7 +4,7 @@ import android.content.Context
|
||||
import network.loki.messenger.libsession_util.ConfigBase
|
||||
import org.session.libsession.messaging.MessagingModuleConfiguration
|
||||
import org.session.libsession.messaging.sending_receiving.notifications.PushRegistryV1
|
||||
import org.session.libsession.messaging.sending_receiving.pollers.ClosedGroupPollerV2
|
||||
import org.session.libsession.messaging.sending_receiving.pollers.LegacyClosedGroupPollerV2
|
||||
import org.session.libsession.utilities.Address
|
||||
import org.session.libsession.utilities.GroupRecord
|
||||
import org.session.libsession.utilities.GroupUtil
|
||||
@@ -26,7 +26,7 @@ object ClosedGroupManager {
|
||||
// Notify the PN server
|
||||
PushRegistryV1.unsubscribeGroup(closedGroupPublicKey = groupPublicKey, publicKey = userPublicKey)
|
||||
// Stop polling
|
||||
ClosedGroupPollerV2.shared.stopPolling(groupPublicKey)
|
||||
LegacyClosedGroupPollerV2.shared.stopPolling(groupPublicKey)
|
||||
storage.cancelPendingMessageSendJobs(threadId)
|
||||
ApplicationContext.getInstance(context).messageNotifier.updateNotification(context)
|
||||
if (delete) {
|
||||
|
||||
@@ -77,9 +77,8 @@ class CreateGroupFragment : Fragment() {
|
||||
}
|
||||
}
|
||||
|
||||
private fun openConversationActivity(context: Context, threadId: Long, recipient: Recipient) {
|
||||
private fun openConversationActivity(context: Context, recipient: Recipient) {
|
||||
val intent = Intent(context, ConversationActivityV2::class.java)
|
||||
intent.putExtra(ConversationActivityV2.THREAD_ID, threadId)
|
||||
intent.putExtra(ConversationActivityV2.ADDRESS, recipient.address)
|
||||
context.startActivity(intent)
|
||||
}
|
||||
@@ -94,7 +93,10 @@ class CreateGroupFragment : Fragment() {
|
||||
createGroupState,
|
||||
onCreate = { newGroup ->
|
||||
// launch something to create here
|
||||
viewModel.tryCreateGroup(newGroup)
|
||||
val groupRecipient = viewModel.tryCreateGroup(newGroup)
|
||||
groupRecipient?.let { recipient ->
|
||||
openConversationActivity(requireContext(), recipient)
|
||||
}
|
||||
},
|
||||
onClose = {
|
||||
delegate.onDialogClosePressed()
|
||||
|
||||
@@ -40,7 +40,7 @@ class CreateGroupViewModel @Inject constructor(
|
||||
}
|
||||
}
|
||||
|
||||
fun tryCreateGroup(createGroupState: CreateGroupState) {
|
||||
fun tryCreateGroup(createGroupState: CreateGroupState): Recipient? {
|
||||
_viewState.postValue(CreateGroupFragment.ViewState(true, null, null))
|
||||
|
||||
val name = createGroupState.groupName
|
||||
@@ -49,14 +49,16 @@ class CreateGroupViewModel @Inject constructor(
|
||||
|
||||
// do some validations
|
||||
if (name.isEmpty()) {
|
||||
return _viewState.postValue(
|
||||
_viewState.postValue(
|
||||
CreateGroupFragment.ViewState(false, R.string.error, null)
|
||||
)
|
||||
return null
|
||||
}
|
||||
// TODO: add future validation for empty group ? we'll add ourselves anyway ig
|
||||
|
||||
// make a group
|
||||
storage.createNewGroup(name, description, members)
|
||||
val newGroup = storage.createNewGroup(name, description, members) // TODO: handle optional
|
||||
return newGroup.orNull()
|
||||
}
|
||||
|
||||
fun filter(query: String): List<Recipient> {
|
||||
|
||||
@@ -7,8 +7,8 @@ import androidx.work.Constraints
|
||||
import androidx.work.Data
|
||||
import androidx.work.ExistingPeriodicWorkPolicy
|
||||
import androidx.work.NetworkType
|
||||
import androidx.work.PeriodicWorkRequestBuilder
|
||||
import androidx.work.OneTimeWorkRequestBuilder
|
||||
import androidx.work.PeriodicWorkRequestBuilder
|
||||
import androidx.work.WorkManager
|
||||
import androidx.work.Worker
|
||||
import androidx.work.WorkerParameters
|
||||
@@ -18,7 +18,7 @@ import nl.komponents.kovenant.functional.bind
|
||||
import org.session.libsession.messaging.MessagingModuleConfiguration
|
||||
import org.session.libsession.messaging.jobs.BatchMessageReceiveJob
|
||||
import org.session.libsession.messaging.jobs.MessageReceiveParameters
|
||||
import org.session.libsession.messaging.sending_receiving.pollers.ClosedGroupPollerV2
|
||||
import org.session.libsession.messaging.sending_receiving.pollers.LegacyClosedGroupPollerV2
|
||||
import org.session.libsession.messaging.sending_receiving.pollers.OpenGroupPoller
|
||||
import org.session.libsession.snode.SnodeAPI
|
||||
import org.session.libsession.utilities.TextSecurePreferences
|
||||
@@ -121,7 +121,7 @@ class BackgroundPollWorker(val context: Context, params: WorkerParameters) : Wor
|
||||
|
||||
// Closed groups
|
||||
if (requestTargets.contains(Targets.CLOSED_GROUPS)) {
|
||||
val closedGroupPoller = ClosedGroupPollerV2() // Intentionally don't use shared
|
||||
val closedGroupPoller = LegacyClosedGroupPollerV2() // Intentionally don't use shared
|
||||
val storage = MessagingModuleConfiguration.shared.storage
|
||||
val allGroupPublicKeys = storage.getAllClosedGroupPublicKeys()
|
||||
allGroupPublicKeys.iterator().forEach { closedGroupPoller.poll(it) }
|
||||
|
||||
@@ -13,7 +13,7 @@ inline session::config::Contacts *ptrToContacts(JNIEnv *env, jobject obj) {
|
||||
|
||||
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");
|
||||
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");
|
||||
jstring id = env->NewStringUTF(info.session_id.data());
|
||||
jstring name = env->NewStringUTF(info.name.data());
|
||||
jstring nickname = env->NewStringUTF(info.nickname.data());
|
||||
@@ -24,7 +24,7 @@ inline jobject serialize_contact(JNIEnv *env, session::config::contact_info info
|
||||
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,
|
||||
approvedMe, blocked, profilePic, (jlong)info.priority,
|
||||
util::serialize_expiry(env, info.exp_mode, info.exp_timer));
|
||||
return returnObj;
|
||||
}
|
||||
@@ -42,14 +42,14 @@ deserialize_contact(JNIEnv *env, jobject info, session::config::Contacts *conf)
|
||||
getBlocked = env->GetFieldID(contactClass, "blocked", "Z");
|
||||
getUserPic = env->GetFieldID(contactClass, "profilePicture",
|
||||
"Lnetwork/loki/messenger/libsession_util/util/UserPic;");
|
||||
getPriority = env->GetFieldID(contactClass, "priority", "I");
|
||||
getPriority = env->GetFieldID(contactClass, "priority", "J");
|
||||
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);
|
||||
int priority = env->GetLongField(info, getPriority);
|
||||
approved = env->GetBooleanField(info, getApproved);
|
||||
approvedMe = env->GetBooleanField(info, getApprovedMe);
|
||||
blocked = env->GetBooleanField(info, getBlocked);
|
||||
|
||||
@@ -72,20 +72,19 @@ Java_network_loki_messenger_libsession_1util_GroupKeysConfig_groupKeys(JNIEnv *e
|
||||
extern "C"
|
||||
JNIEXPORT void JNICALL
|
||||
Java_network_loki_messenger_libsession_1util_GroupKeysConfig_loadKey(JNIEnv *env, jobject thiz,
|
||||
jbyteArray message,
|
||||
jstring hash,
|
||||
jbyteArray data,
|
||||
jbyteArray msg_id,
|
||||
jlong timestamp_ms,
|
||||
jobject info_jobject,
|
||||
jobject members_jobject) {
|
||||
std::lock_guard lock{util::util_mutex_};
|
||||
auto keys = ptrToKeys(env, thiz);
|
||||
auto message_bytes = util::ustring_from_bytes(env, message);
|
||||
auto hash_bytes = env->GetStringUTFChars(hash, nullptr);
|
||||
auto data_bytes = util::ustring_from_bytes(env, data);
|
||||
auto msg_bytes = util::ustring_from_bytes(env, msg_id);
|
||||
auto info = ptrToInfo(env, info_jobject);
|
||||
auto members = ptrToMembers(env, members_jobject);
|
||||
keys->load_key_message(hash_bytes, data_bytes, timestamp_ms, *info, *members);
|
||||
keys->load_key_message(hash_bytes, message_bytes, timestamp_ms, *info, *members);
|
||||
|
||||
env->ReleaseStringUTFChars(hash, hash_bytes);
|
||||
}
|
||||
|
||||
@@ -112,8 +111,8 @@ Java_network_loki_messenger_libsession_1util_GroupKeysConfig_pendingKey(JNIEnv *
|
||||
|
||||
extern "C"
|
||||
JNIEXPORT jbyteArray JNICALL
|
||||
Java_network_loki_messenger_libsession_1util_GroupKeysConfig_pendingPush(JNIEnv *env,
|
||||
jobject thiz) {
|
||||
Java_network_loki_messenger_libsession_1util_GroupKeysConfig_pendingConfig(JNIEnv *env,
|
||||
jobject thiz) {
|
||||
std::lock_guard lock{util::util_mutex_};
|
||||
auto keys = ptrToKeys(env, thiz);
|
||||
auto pending = keys->pending_config();
|
||||
@@ -135,4 +134,20 @@ Java_network_loki_messenger_libsession_1util_GroupKeysConfig_rekey(JNIEnv *env,
|
||||
auto rekey = keys->rekey(*info, *members);
|
||||
auto rekey_bytes = util::bytes_from_ustring(env, rekey.data());
|
||||
return rekey_bytes;
|
||||
}
|
||||
}
|
||||
|
||||
extern "C"
|
||||
JNIEXPORT jbyteArray JNICALL
|
||||
Java_network_loki_messenger_libsession_1util_GroupKeysConfig_keyDump(JNIEnv *env, jobject thiz) {
|
||||
auto keys = ptrToKeys(env, thiz);
|
||||
auto dump = keys->dump();
|
||||
auto byte_array = util::bytes_from_ustring(env, dump);
|
||||
return byte_array;
|
||||
}
|
||||
|
||||
extern "C"
|
||||
JNIEXPORT void JNICALL
|
||||
Java_network_loki_messenger_libsession_1util_GroupKeysConfig_free(JNIEnv *env, jobject thiz) {
|
||||
auto ptr = ptrToKeys(env, thiz);
|
||||
delete ptr;
|
||||
}
|
||||
|
||||
@@ -28,7 +28,6 @@ sealed class ConfigBase(protected val /* yucky */ pointer: Long) {
|
||||
is ConversationVolatileConfig -> Kind.CONVO_INFO_VOLATILE
|
||||
is UserGroupsConfig -> Kind.GROUPS
|
||||
is GroupInfoConfig -> Kind.CLOSED_GROUP_INFO
|
||||
is GroupKeysConfig -> Kind.ENCRYPTION_KEYS
|
||||
is GroupMembersConfig -> Kind.CLOSED_GROUP_MEMBERS
|
||||
}
|
||||
|
||||
@@ -275,7 +274,7 @@ class GroupMembersConfig(pointer: Long): ConfigBase(pointer), Closeable {
|
||||
}
|
||||
}
|
||||
|
||||
class GroupKeysConfig(pointer: Long): ConfigBase(pointer), Closeable {
|
||||
class GroupKeysConfig(private val pointer: Long): Closeable {
|
||||
companion object {
|
||||
init {
|
||||
System.loadLibrary("session_util")
|
||||
@@ -292,16 +291,16 @@ class GroupKeysConfig(pointer: Long): ConfigBase(pointer), Closeable {
|
||||
}
|
||||
external fun groupKeys(): Stack<ByteArray>
|
||||
external fun keyDump(): ByteArray
|
||||
external fun loadKey(hash: String,
|
||||
data: ByteArray,
|
||||
msgId: ByteArray,
|
||||
external fun loadKey(message: ByteArray,
|
||||
hash: String,
|
||||
timestampMs: Long,
|
||||
info: GroupInfoConfig,
|
||||
members: GroupMembersConfig)
|
||||
external fun needsRekey(): Boolean
|
||||
external fun pendingKey(): ByteArray?
|
||||
external fun pendingPush(): ByteArray?
|
||||
external fun pendingConfig(): ByteArray?
|
||||
external fun rekey(info: GroupInfoConfig, members: GroupMembersConfig): ByteArray
|
||||
external fun free()
|
||||
override fun close() {
|
||||
free()
|
||||
}
|
||||
|
||||
@@ -156,7 +156,7 @@ interface StorageProtocol {
|
||||
fun setExpirationTimer(address: String, duration: Int)
|
||||
|
||||
// Closed Groups
|
||||
fun createNewGroup(groupName: String, groupDescription: String, members: Set<SessionId>): Optional<Boolean>
|
||||
fun createNewGroup(groupName: String, groupDescription: String, members: Set<SessionId>): Optional<Recipient>
|
||||
fun getMembers(groupPublicKey: String): List<network.loki.messenger.libsession_util.util.GroupMember>
|
||||
|
||||
// Groups
|
||||
|
||||
@@ -9,7 +9,7 @@ import org.session.libsession.messaging.MessagingModuleConfiguration
|
||||
import org.session.libsession.messaging.messages.control.ClosedGroupControlMessage
|
||||
import org.session.libsession.messaging.sending_receiving.MessageSender.Error
|
||||
import org.session.libsession.messaging.sending_receiving.notifications.PushRegistryV1
|
||||
import org.session.libsession.messaging.sending_receiving.pollers.ClosedGroupPollerV2
|
||||
import org.session.libsession.messaging.sending_receiving.pollers.LegacyClosedGroupPollerV2
|
||||
import org.session.libsession.snode.SnodeAPI
|
||||
import org.session.libsession.utilities.Address
|
||||
import org.session.libsession.utilities.Address.Companion.fromSerialized
|
||||
@@ -96,7 +96,7 @@ fun MessageSender.create(
|
||||
// Notify the PN server
|
||||
PushRegistryV1.register(device = device, publicKey = userPublicKey)
|
||||
// Start polling
|
||||
ClosedGroupPollerV2.shared.startPolling(groupPublicKey)
|
||||
LegacyClosedGroupPollerV2.shared.startPolling(groupPublicKey)
|
||||
// Fulfill the promise
|
||||
deferred.resolve(groupID)
|
||||
}
|
||||
|
||||
@@ -25,7 +25,7 @@ import org.session.libsession.messaging.sending_receiving.attachments.PointerAtt
|
||||
import org.session.libsession.messaging.sending_receiving.data_extraction.DataExtractionNotificationInfoMessage
|
||||
import org.session.libsession.messaging.sending_receiving.link_preview.LinkPreview
|
||||
import org.session.libsession.messaging.sending_receiving.notifications.PushRegistryV1
|
||||
import org.session.libsession.messaging.sending_receiving.pollers.ClosedGroupPollerV2
|
||||
import org.session.libsession.messaging.sending_receiving.pollers.LegacyClosedGroupPollerV2
|
||||
import org.session.libsession.messaging.sending_receiving.quotes.QuoteModel
|
||||
import org.session.libsession.messaging.utilities.SodiumUtilities
|
||||
import org.session.libsession.messaging.utilities.WebRtcUtils
|
||||
@@ -580,7 +580,7 @@ private fun handleNewClosedGroup(sender: String, sentTimestamp: Long, groupPubli
|
||||
storage.insertIncomingInfoMessage(context, sender, groupID, SignalServiceGroup.Type.CREATION, name, members, admins, sentTimestamp)
|
||||
}
|
||||
// Start polling
|
||||
ClosedGroupPollerV2.shared.startPolling(groupPublicKey)
|
||||
LegacyClosedGroupPollerV2.shared.startPolling(groupPublicKey)
|
||||
}
|
||||
|
||||
private fun MessageReceiver.handleClosedGroupEncryptionKeyPair(message: ClosedGroupControlMessage) {
|
||||
@@ -886,7 +886,7 @@ fun MessageReceiver.disableLocalGroupAndUnsubscribe(groupPublicKey: String, grou
|
||||
// Notify the PN server
|
||||
PushRegistryV1.unsubscribeGroup(groupPublicKey, publicKey = userPublicKey)
|
||||
// Stop polling
|
||||
ClosedGroupPollerV2.shared.stopPolling(groupPublicKey)
|
||||
LegacyClosedGroupPollerV2.shared.stopPolling(groupPublicKey)
|
||||
|
||||
if (delete) {
|
||||
val threadId = storage.getOrCreateThreadIdFor(Address.fromSerialized(groupID))
|
||||
|
||||
@@ -0,0 +1,48 @@
|
||||
package org.session.libsession.messaging.sending_receiving.pollers
|
||||
|
||||
import kotlinx.coroutines.CoroutineScope
|
||||
import kotlinx.coroutines.Job
|
||||
import kotlinx.coroutines.delay
|
||||
import kotlinx.coroutines.launch
|
||||
import org.session.libsession.snode.SnodeAPI
|
||||
import org.session.libsession.utilities.ConfigFactoryProtocol
|
||||
import org.session.libsignal.utilities.Log
|
||||
import org.session.libsignal.utilities.SessionId
|
||||
|
||||
class ClosedGroupPoller(private val executor: CoroutineScope,
|
||||
private val closedGroupSessionId: SessionId,
|
||||
private val configFactoryProtocol: ConfigFactoryProtocol) {
|
||||
|
||||
companion object {
|
||||
const val POLL_INTERVAL = 3_000L
|
||||
}
|
||||
|
||||
private var isRunning: Boolean = false
|
||||
private var job: Job? = null
|
||||
|
||||
fun start() {
|
||||
job?.cancel()
|
||||
job = executor.launch {
|
||||
val nextPoll = poll()
|
||||
delay(nextPoll)
|
||||
}
|
||||
}
|
||||
|
||||
fun stop() {
|
||||
job?.cancel()
|
||||
}
|
||||
|
||||
fun poll(): Long {
|
||||
try {
|
||||
val snode = SnodeAPI.getSingleTargetSnode(closedGroupSessionId.hexString()).get()
|
||||
val info = configFactoryProtocol.getOrConstructGroupInfoConfig(closedGroupSessionId)
|
||||
val members = configFactoryProtocol.getOrConstructGroupMemberConfig(closedGroupSessionId)
|
||||
val keys = configFactoryProtocol.getGroupKeysConfig(closedGroupSessionId)
|
||||
|
||||
} catch (e: Exception) {
|
||||
Log.e("GroupPoller", "Polling failed for group", e)
|
||||
}
|
||||
return POLL_INTERVAL // this might change in future
|
||||
}
|
||||
|
||||
}
|
||||
@@ -22,7 +22,7 @@ import java.util.concurrent.ScheduledFuture
|
||||
import java.util.concurrent.TimeUnit
|
||||
import kotlin.math.min
|
||||
|
||||
class ClosedGroupPollerV2 {
|
||||
class LegacyClosedGroupPollerV2 {
|
||||
private val executorService = Executors.newScheduledThreadPool(1)
|
||||
private var isPolling = mutableMapOf<String, Boolean>()
|
||||
private var futures = mutableMapOf<String, ScheduledFuture<*>>()
|
||||
@@ -36,7 +36,7 @@ class ClosedGroupPollerV2 {
|
||||
private val maxPollInterval = 4 * 60 * 1000
|
||||
|
||||
@JvmStatic
|
||||
val shared = ClosedGroupPollerV2()
|
||||
val shared = LegacyClosedGroupPollerV2()
|
||||
}
|
||||
|
||||
class InsufficientSnodesException() : Exception("No snodes left to poll.")
|
||||
@@ -210,7 +210,6 @@ class Poller(private val configFactory: ConfigFactoryProtocol, debounceTimer: Ti
|
||||
val responseList = (rawResponses["results"] as List<RawResponse>)
|
||||
// in case we had null configs, the array won't be fully populated
|
||||
// index of the sparse array key iterator should be the request index, with the key being the namespace
|
||||
// TODO: add in specific ordering of config namespaces for processing
|
||||
listOfNotNull(
|
||||
configFactory.user?.configNamespace(),
|
||||
configFactory.contacts?.configNamespace(),
|
||||
|
||||
Reference in New Issue
Block a user