mirror of
https://github.com/oxen-io/session-android.git
synced 2024-12-24 00:37:47 +00:00
WIP: clean up signal protocols
This commit is contained in:
parent
13c2995746
commit
958ec690f1
@ -76,7 +76,6 @@ import org.thoughtcrime.securesms.loki.database.LokiAPIDatabase;
|
||||
import org.thoughtcrime.securesms.loki.database.LokiThreadDatabase;
|
||||
import org.thoughtcrime.securesms.loki.database.LokiUserDatabase;
|
||||
import org.thoughtcrime.securesms.loki.protocol.MultiDeviceProtocol;
|
||||
import org.thoughtcrime.securesms.loki.protocol.SessionResetImplementation;
|
||||
import org.thoughtcrime.securesms.loki.utilities.Broadcaster;
|
||||
import org.thoughtcrime.securesms.loki.utilities.UiModeUtilities;
|
||||
import org.thoughtcrime.securesms.notifications.DefaultMessageNotifier;
|
||||
@ -84,7 +83,6 @@ import org.thoughtcrime.securesms.notifications.NotificationChannels;
|
||||
import org.thoughtcrime.securesms.notifications.OptimizedMessageNotifier;
|
||||
import org.thoughtcrime.securesms.providers.BlobProvider;
|
||||
import org.thoughtcrime.securesms.push.SignalServiceNetworkAccess;
|
||||
import org.session.libsession.messaging.threads.recipients.Recipient;
|
||||
import org.thoughtcrime.securesms.service.ExpiringMessageManager;
|
||||
import org.thoughtcrime.securesms.service.IncomingMessageObserver;
|
||||
import org.thoughtcrime.securesms.service.KeyCachingService;
|
||||
@ -107,8 +105,7 @@ import org.session.libsignal.service.loki.api.opengroups.PublicChatAPI;
|
||||
import org.session.libsignal.service.loki.api.shelved.p2p.LokiP2PAPI;
|
||||
import org.session.libsignal.service.loki.api.shelved.p2p.LokiP2PAPIDelegate;
|
||||
import org.session.libsignal.service.loki.database.LokiAPIDatabaseProtocol;
|
||||
import org.session.libsignal.service.loki.protocol.mentions.MentionsManager;
|
||||
import org.session.libsignal.service.loki.protocol.meta.SessionMetaProtocol;
|
||||
import org.session.libsignal.service.loki.utilities.mentions.MentionsManager;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileInputStream;
|
||||
@ -136,7 +133,6 @@ import static nl.komponents.kovenant.android.KovenantAndroid.stopKovenant;
|
||||
public class ApplicationContext extends MultiDexApplication implements DependencyInjector, DefaultLifecycleObserver, LokiP2PAPIDelegate {
|
||||
|
||||
private static final String TAG = ApplicationContext.class.getSimpleName();
|
||||
private final static int OK_HTTP_CACHE_SIZE = 10 * 1024 * 1024; // 10 MB
|
||||
|
||||
private ExpiringMessageManager expiringMessageManager;
|
||||
private TypingStatusRepository typingStatusRepository;
|
||||
@ -144,7 +140,6 @@ public class ApplicationContext extends MultiDexApplication implements Dependenc
|
||||
private JobManager jobManager;
|
||||
private ReadReceiptManager readReceiptManager;
|
||||
private ProfileManager profileManager;
|
||||
private IncomingMessageObserver incomingMessageObserver;
|
||||
private ObjectGraph objectGraph;
|
||||
private PersistentLogger persistentLogger;
|
||||
|
||||
@ -182,7 +177,6 @@ public class ApplicationContext extends MultiDexApplication implements Dependenc
|
||||
LokiThreadDatabase threadDB = DatabaseFactory.getLokiThreadDatabase(this);
|
||||
LokiUserDatabase userDB = DatabaseFactory.getLokiUserDatabase(this);
|
||||
String userPublicKey = TextSecurePreferences.getLocalNumber(this);
|
||||
SessionResetImplementation sessionResetImpl = new SessionResetImplementation(this);
|
||||
MessagingConfiguration.Companion.configure(this,
|
||||
DatabaseFactory.getStorage(this),
|
||||
DatabaseFactory.getAttachmentProvider(this),
|
||||
@ -191,7 +185,6 @@ public class ApplicationContext extends MultiDexApplication implements Dependenc
|
||||
SwarmAPI.Companion.configureIfNeeded(apiDB);
|
||||
SnodeAPI.Companion.configureIfNeeded(userPublicKey, apiDB, broadcaster);
|
||||
MentionsManager.Companion.configureIfNeeded(userPublicKey, threadDB, userDB);
|
||||
SessionMetaProtocol.Companion.configureIfNeeded(apiDB, userPublicKey);
|
||||
}
|
||||
setUpP2PAPIIfNeeded();
|
||||
PushNotificationAPI.Companion.configureIfNeeded(BuildConfig.DEBUG);
|
||||
@ -206,7 +199,6 @@ public class ApplicationContext extends MultiDexApplication implements Dependenc
|
||||
UiModeUtilities.setupUiModeToUserSelected(this);
|
||||
// ========
|
||||
initializeJobManager();
|
||||
initializeMessageRetrieval();
|
||||
initializeExpiringMessageManager();
|
||||
initializeTypingStatusRepository();
|
||||
initializeTypingStatusSender();
|
||||
@ -347,10 +339,6 @@ public class ApplicationContext extends MultiDexApplication implements Dependenc
|
||||
.build());
|
||||
}
|
||||
|
||||
public void initializeMessageRetrieval() {
|
||||
this.incomingMessageObserver = new IncomingMessageObserver(this);
|
||||
}
|
||||
|
||||
private void initializeDependencyInjection() {
|
||||
communicationModule = new SignalCommunicationModule(this, new SignalServiceNetworkAccess(this));
|
||||
this.objectGraph = ObjectGraph.create(communicationModule);
|
||||
|
@ -90,9 +90,8 @@ import org.session.libsession.utilities.MediaTypes;
|
||||
import org.session.libsignal.libsignal.InvalidMessageException;
|
||||
import org.session.libsignal.libsignal.util.guava.Optional;
|
||||
import org.session.libsignal.service.loki.api.opengroups.PublicChat;
|
||||
import org.session.libsignal.service.loki.protocol.mentions.Mention;
|
||||
import org.session.libsignal.service.loki.protocol.mentions.MentionsManager;
|
||||
import org.session.libsignal.service.loki.protocol.meta.SessionMetaProtocol;
|
||||
import org.session.libsignal.service.loki.utilities.mentions.Mention;
|
||||
import org.session.libsignal.service.loki.utilities.mentions.MentionsManager;
|
||||
import org.session.libsignal.service.loki.utilities.HexEncodingKt;
|
||||
import org.session.libsignal.service.loki.utilities.PublicKeyValidation;
|
||||
import org.thoughtcrime.securesms.ApplicationContext;
|
||||
@ -144,7 +143,6 @@ import org.thoughtcrime.securesms.loki.database.LokiThreadDatabase;
|
||||
import org.thoughtcrime.securesms.loki.database.LokiThreadDatabaseDelegate;
|
||||
import org.thoughtcrime.securesms.loki.database.LokiUserDatabase;
|
||||
import org.thoughtcrime.securesms.loki.protocol.ClosedGroupsProtocolV2;
|
||||
import org.thoughtcrime.securesms.loki.protocol.SessionManagementProtocol;
|
||||
import org.thoughtcrime.securesms.loki.utilities.GeneralUtilitiesKt;
|
||||
import org.thoughtcrime.securesms.loki.utilities.MentionManagerUtilities;
|
||||
import org.thoughtcrime.securesms.loki.utilities.OpenGroupUtilities;
|
||||
@ -404,7 +402,6 @@ public class ConversationActivity extends PassphraseRequiredActionBarActivity
|
||||
});
|
||||
|
||||
sessionRestoreBannerView.setOnRestore(() -> {
|
||||
SessionManagementProtocol.startSessionReset(this, recipient.getAddress().serialize());
|
||||
updateSessionRestoreBanner();
|
||||
return Unit.INSTANCE;
|
||||
});
|
||||
@ -2003,7 +2000,7 @@ public class ConversationActivity extends PassphraseRequiredActionBarActivity
|
||||
Log.w(TAG, ex);
|
||||
}
|
||||
|
||||
if (messageStatus == null && !isGroupConversation() && !SessionMetaProtocol.shared.isNoteToSelf(recipient.getAddress().serialize())) {
|
||||
if (messageStatus == null && !isGroupConversation() && !(TextSecurePreferences.getLocalNumber(this).equals(recipient.getAddress().serialize()))) {
|
||||
messageStatus = "calculatingPoW";
|
||||
updateSubtitleTextView();
|
||||
updateMessageStatusProgressBar();
|
||||
@ -2680,7 +2677,7 @@ public class ConversationActivity extends PassphraseRequiredActionBarActivity
|
||||
}
|
||||
|
||||
private void handleMessageStatusChanged(String newMessageStatus, long timestamp) {
|
||||
if (timestamp == 0 || SessionMetaProtocol.shared.isNoteToSelf(recipient.getAddress().serialize()) ) { return; }
|
||||
if (timestamp == 0 || (TextSecurePreferences.getLocalNumber(this).equals(recipient.getAddress().serialize())) ) { return; }
|
||||
updateForNewMessageStatusIfNeeded(newMessageStatus, timestamp);
|
||||
if (newMessageStatus.equals("messageFailed") || newMessageStatus.equals("messageSent")) {
|
||||
new Handler().postDelayed(() -> clearMessageStatusIfNeeded(timestamp), 1000);
|
||||
|
@ -49,11 +49,11 @@ public class PushDatabase extends Database {
|
||||
values.put(TYPE, envelope.getType());
|
||||
values.put(SOURCE, envelope.getSource());
|
||||
values.put(DEVICE_ID, envelope.getSourceDevice());
|
||||
values.put(LEGACY_MSG, envelope.hasLegacyMessage() ? Base64.encodeBytes(envelope.getLegacyMessage()) : "");
|
||||
values.put(LEGACY_MSG, "");
|
||||
values.put(CONTENT, envelope.hasContent() ? Base64.encodeBytes(envelope.getContent()) : "");
|
||||
values.put(TIMESTAMP, envelope.getTimestamp());
|
||||
values.put(SERVER_TIMESTAMP, envelope.getServerTimestamp());
|
||||
values.put(SERVER_GUID, envelope.getUuid());
|
||||
values.put(SERVER_GUID, "");
|
||||
|
||||
return databaseHelper.getWritableDatabase().insert(TABLE_NAME, null, values);
|
||||
}
|
||||
@ -68,17 +68,14 @@ public class PushDatabase extends Database {
|
||||
null, null, null);
|
||||
|
||||
if (cursor != null && cursor.moveToNext()) {
|
||||
String legacyMessage = cursor.getString(cursor.getColumnIndexOrThrow(LEGACY_MSG));
|
||||
String content = cursor.getString(cursor.getColumnIndexOrThrow(CONTENT));
|
||||
|
||||
return new SignalServiceEnvelope(cursor.getInt(cursor.getColumnIndexOrThrow(TYPE)),
|
||||
cursor.getString(cursor.getColumnIndexOrThrow(SOURCE)),
|
||||
cursor.getInt(cursor.getColumnIndexOrThrow(DEVICE_ID)),
|
||||
cursor.getLong(cursor.getColumnIndexOrThrow(TIMESTAMP)),
|
||||
Util.isEmpty(legacyMessage) ? null : Base64.decode(legacyMessage),
|
||||
Util.isEmpty(content) ? null : Base64.decode(content),
|
||||
cursor.getLong(cursor.getColumnIndexOrThrow(SERVER_TIMESTAMP)),
|
||||
cursor.getString(cursor.getColumnIndexOrThrow(SERVER_GUID)));
|
||||
cursor.getLong(cursor.getColumnIndexOrThrow(SERVER_TIMESTAMP)));
|
||||
}
|
||||
} catch (IOException e) {
|
||||
Log.w(TAG, e);
|
||||
@ -114,7 +111,7 @@ public class PushDatabase extends Database {
|
||||
new String[] {String.valueOf(envelope.getType()),
|
||||
envelope.getSource(),
|
||||
String.valueOf(envelope.getSourceDevice()),
|
||||
envelope.hasLegacyMessage() ? Base64.encodeBytes(envelope.getLegacyMessage()) : "",
|
||||
"",
|
||||
envelope.hasContent() ? Base64.encodeBytes(envelope.getContent()) : "",
|
||||
String.valueOf(envelope.getTimestamp())},
|
||||
null, null, null);
|
||||
@ -144,16 +141,13 @@ public class PushDatabase extends Database {
|
||||
int type = cursor.getInt(cursor.getColumnIndexOrThrow(TYPE));
|
||||
String source = cursor.getString(cursor.getColumnIndexOrThrow(SOURCE));
|
||||
int deviceId = cursor.getInt(cursor.getColumnIndexOrThrow(DEVICE_ID));
|
||||
String legacyMessage = cursor.getString(cursor.getColumnIndexOrThrow(LEGACY_MSG));
|
||||
String content = cursor.getString(cursor.getColumnIndexOrThrow(CONTENT));
|
||||
long timestamp = cursor.getLong(cursor.getColumnIndexOrThrow(TIMESTAMP));
|
||||
long serverTimestamp = cursor.getLong(cursor.getColumnIndexOrThrow(SERVER_TIMESTAMP));
|
||||
String serverGuid = cursor.getString(cursor.getColumnIndexOrThrow(SERVER_GUID));
|
||||
|
||||
return new SignalServiceEnvelope(type, source, deviceId, timestamp,
|
||||
legacyMessage != null ? Base64.decode(legacyMessage) : null,
|
||||
content != null ? Base64.decode(content) : null,
|
||||
serverTimestamp, serverGuid);
|
||||
serverTimestamp);
|
||||
} catch (IOException e) {
|
||||
throw new AssertionError(e);
|
||||
}
|
||||
|
@ -250,7 +250,9 @@ public class SQLCipherOpenHelper extends SQLiteOpenHelper {
|
||||
}
|
||||
|
||||
if (oldVersion < lokiV21) {
|
||||
deleteJobRecords(db, "ClosedGroupUpdateMessageSendJob");
|
||||
deleteJobRecords(db,
|
||||
"ClosedGroupUpdateMessageSendJob",
|
||||
"NullMessageSendJob");
|
||||
}
|
||||
|
||||
db.setTransactionSuccessful();
|
||||
|
@ -32,7 +32,6 @@ import org.thoughtcrime.securesms.jobs.TypingSendJob;
|
||||
import org.thoughtcrime.securesms.linkpreview.LinkPreviewRepository;
|
||||
import org.session.libsignal.utilities.logging.Log;
|
||||
import org.thoughtcrime.securesms.loki.api.SessionProtocolImpl;
|
||||
import org.thoughtcrime.securesms.loki.protocol.SessionResetImplementation;
|
||||
import org.thoughtcrime.securesms.preferences.AppProtectionPreferenceFragment;
|
||||
import org.thoughtcrime.securesms.push.MessageSenderEventListener;
|
||||
import org.thoughtcrime.securesms.push.SignalServiceNetworkAccess;
|
||||
@ -88,20 +87,15 @@ public class SignalCommunicationModule {
|
||||
@Provides
|
||||
public synchronized SignalServiceMessageSender provideSignalMessageSender() {
|
||||
if (this.messageSender == null) {
|
||||
this.messageSender = new SignalServiceMessageSender(networkAccess.getConfiguration(context),
|
||||
new DynamicCredentialsProvider(context),
|
||||
this.messageSender = new SignalServiceMessageSender(new DynamicCredentialsProvider(context),
|
||||
new SignalProtocolStoreImpl(context),
|
||||
BuildConfig.USER_AGENT,
|
||||
Optional.fromNullable(IncomingMessageObserver.getPipe()),
|
||||
Optional.fromNullable(IncomingMessageObserver.getUnidentifiedPipe()),
|
||||
Optional.of(new MessageSenderEventListener(context)),
|
||||
TextSecurePreferences.getLocalNumber(context),
|
||||
DatabaseFactory.getLokiAPIDatabase(context),
|
||||
DatabaseFactory.getLokiThreadDatabase(context),
|
||||
DatabaseFactory.getLokiMessageDatabase(context),
|
||||
null, // DatabaseFactory.getLokiPreKeyBundleDatabase(context)
|
||||
new SessionProtocolImpl(context),
|
||||
new SessionResetImplementation(context),
|
||||
DatabaseFactory.getLokiUserDatabase(context),
|
||||
DatabaseFactory.getGroupDatabase(context),
|
||||
((ApplicationContext)context.getApplicationContext()).broadcaster);
|
||||
|
@ -17,7 +17,6 @@ import org.thoughtcrime.securesms.jobmanager.impl.SqlCipherMigrationConstraintOb
|
||||
import org.thoughtcrime.securesms.loki.api.PrepareAttachmentAudioExtrasJob;
|
||||
import org.thoughtcrime.securesms.loki.api.ResetThreadSessionJob;
|
||||
import org.thoughtcrime.securesms.loki.protocol.ClosedGroupUpdateMessageSendJobV2;
|
||||
import org.thoughtcrime.securesms.loki.protocol.NullMessageSendJob;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
@ -41,7 +40,6 @@ public final class JobManagerFactories {
|
||||
put(MmsDownloadJob.KEY, new MmsDownloadJob.Factory());
|
||||
put(MmsReceiveJob.KEY, new MmsReceiveJob.Factory());
|
||||
put(MmsSendJob.KEY, new MmsSendJob.Factory());
|
||||
put(NullMessageSendJob.KEY, new NullMessageSendJob.Factory());
|
||||
put(PushContentReceiveJob.KEY, new PushContentReceiveJob.Factory());
|
||||
put(PushDecryptJob.KEY, new PushDecryptJob.Factory());
|
||||
put(PushGroupSendJob.KEY, new PushGroupSendJob.Factory());
|
||||
|
@ -17,19 +17,8 @@ import com.annimon.stream.Stream;
|
||||
import org.session.libsession.messaging.jobs.Data;
|
||||
import org.session.libsession.utilities.MediaTypes;
|
||||
import org.session.libsignal.metadata.InvalidMetadataMessageException;
|
||||
import org.session.libsignal.metadata.InvalidMetadataVersionException;
|
||||
import org.session.libsignal.metadata.ProtocolDuplicateMessageException;
|
||||
import org.session.libsignal.metadata.ProtocolInvalidKeyException;
|
||||
import org.session.libsignal.metadata.ProtocolInvalidKeyIdException;
|
||||
import org.session.libsignal.metadata.ProtocolInvalidMessageException;
|
||||
import org.session.libsignal.metadata.ProtocolInvalidVersionException;
|
||||
import org.session.libsignal.metadata.ProtocolLegacyMessageException;
|
||||
import org.session.libsignal.metadata.ProtocolNoSessionException;
|
||||
import org.session.libsignal.metadata.ProtocolUntrustedIdentityException;
|
||||
import org.session.libsignal.metadata.SelfSendException;
|
||||
import org.session.libsignal.service.api.crypto.SignalServiceCipher;
|
||||
import org.session.libsignal.service.loki.api.crypto.SessionProtocol;
|
||||
import org.session.libsignal.utilities.PromiseUtilities;
|
||||
import org.thoughtcrime.securesms.ApplicationContext;
|
||||
|
||||
import org.session.libsession.messaging.sending_receiving.linkpreview.LinkPreview;
|
||||
@ -48,13 +37,10 @@ import org.session.libsession.utilities.TextSecurePreferences;
|
||||
|
||||
import org.thoughtcrime.securesms.contactshare.ContactModelMapper;
|
||||
import org.thoughtcrime.securesms.crypto.IdentityKeyUtil;
|
||||
import org.thoughtcrime.securesms.crypto.UnidentifiedAccessUtil;
|
||||
import org.thoughtcrime.securesms.crypto.storage.SignalProtocolStoreImpl;
|
||||
import org.thoughtcrime.securesms.database.AttachmentDatabase;
|
||||
import org.thoughtcrime.securesms.database.DatabaseFactory;
|
||||
import org.thoughtcrime.securesms.database.GroupDatabase;
|
||||
import org.thoughtcrime.securesms.database.GroupReceiptDatabase;
|
||||
import org.thoughtcrime.securesms.database.MessagingDatabase;
|
||||
import org.thoughtcrime.securesms.database.MessagingDatabase.InsertResult;
|
||||
import org.thoughtcrime.securesms.database.MessagingDatabase.SyncMessageId;
|
||||
import org.thoughtcrime.securesms.database.MmsDatabase;
|
||||
@ -79,26 +65,19 @@ import org.thoughtcrime.securesms.loki.database.LokiMessageDatabase;
|
||||
import org.thoughtcrime.securesms.loki.database.LokiThreadDatabase;
|
||||
import org.thoughtcrime.securesms.loki.protocol.ClosedGroupsProtocolV2;
|
||||
import org.thoughtcrime.securesms.loki.protocol.MultiDeviceProtocol;
|
||||
import org.thoughtcrime.securesms.loki.protocol.SessionManagementProtocol;
|
||||
import org.thoughtcrime.securesms.loki.protocol.SessionMetaProtocol;
|
||||
import org.thoughtcrime.securesms.loki.protocol.SessionResetImplementation;
|
||||
import org.thoughtcrime.securesms.loki.utilities.MentionManagerUtilities;
|
||||
import org.thoughtcrime.securesms.mms.IncomingMediaMessage;
|
||||
import org.thoughtcrime.securesms.mms.MmsException;
|
||||
import org.thoughtcrime.securesms.mms.OutgoingExpirationUpdateMessage;
|
||||
import org.thoughtcrime.securesms.mms.OutgoingMediaMessage;
|
||||
import org.thoughtcrime.securesms.mms.OutgoingSecureMediaMessage;
|
||||
import org.thoughtcrime.securesms.mms.SlideDeck;
|
||||
import org.thoughtcrime.securesms.mms.StickerSlide;
|
||||
import org.thoughtcrime.securesms.notifications.NotificationChannels;
|
||||
import org.thoughtcrime.securesms.sms.IncomingEncryptedMessage;
|
||||
import org.thoughtcrime.securesms.sms.IncomingEndSessionMessage;
|
||||
import org.thoughtcrime.securesms.sms.IncomingTextMessage;
|
||||
import org.thoughtcrime.securesms.sms.OutgoingEncryptedMessage;
|
||||
import org.thoughtcrime.securesms.sms.OutgoingTextMessage;
|
||||
import org.session.libsignal.utilities.Hex;
|
||||
import org.session.libsignal.libsignal.InvalidMessageException;
|
||||
import org.session.libsignal.libsignal.loki.SessionResetProtocol;
|
||||
import org.session.libsignal.libsignal.state.SignalProtocolStore;
|
||||
import org.session.libsignal.libsignal.util.guava.Optional;
|
||||
import org.session.libsignal.service.api.SignalServiceMessageSender;
|
||||
@ -111,16 +90,14 @@ import org.session.libsignal.service.api.messages.SignalServiceReceiptMessage;
|
||||
import org.session.libsignal.service.api.messages.SignalServiceTypingMessage;
|
||||
import org.session.libsignal.service.api.messages.shared.SharedContact;
|
||||
import org.session.libsignal.service.api.push.SignalServiceAddress;
|
||||
import org.session.libsignal.service.loki.protocol.mentions.MentionsManager;
|
||||
import org.session.libsignal.service.loki.utilities.mentions.MentionsManager;
|
||||
import org.session.libsignal.service.loki.utilities.PublicKeyValidation;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.security.SecureRandom;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
import javax.inject.Inject;
|
||||
|
||||
@ -242,10 +219,9 @@ public class PushDecryptJob extends BaseJob implements InjectableType {
|
||||
try {
|
||||
GroupDatabase groupDatabase = DatabaseFactory.getGroupDatabase(context);
|
||||
SignalProtocolStore axolotlStore = new SignalProtocolStoreImpl(context);
|
||||
SessionResetProtocol sessionResetProtocol = new SessionResetImplementation(context);
|
||||
SignalServiceAddress localAddress = new SignalServiceAddress(TextSecurePreferences.getLocalNumber(context));
|
||||
LokiAPIDatabase apiDB = DatabaseFactory.getLokiAPIDatabase(context);
|
||||
SignalServiceCipher cipher = new SignalServiceCipher(localAddress, axolotlStore, sessionResetProtocol, new SessionProtocolImpl(context), apiDB);
|
||||
SignalServiceCipher cipher = new SignalServiceCipher(localAddress, axolotlStore, new SessionProtocolImpl(context), apiDB);
|
||||
|
||||
SignalServiceContent content = cipher.decrypt(envelope);
|
||||
|
||||
@ -254,8 +230,6 @@ public class PushDecryptJob extends BaseJob implements InjectableType {
|
||||
return;
|
||||
}
|
||||
|
||||
SessionManagementProtocol.handlePreKeyBundleMessageIfNeeded(context, content);
|
||||
|
||||
SessionMetaProtocol.handleProfileUpdateIfNeeded(context, content);
|
||||
|
||||
if (content.configurationMessageProto.isPresent()) {
|
||||
@ -341,7 +315,6 @@ public class PushDecryptJob extends BaseJob implements InjectableType {
|
||||
}
|
||||
|
||||
if (threadId != null) {
|
||||
SessionManagementProtocol.handleEndSessionMessageIfNeeded(context, content);
|
||||
messageNotifier.updateNotification(context, threadId);
|
||||
}
|
||||
}
|
||||
@ -706,82 +679,6 @@ public class PushDecryptJob extends BaseJob implements InjectableType {
|
||||
smsDatabase.markAsDecryptFailed(smsMessageId.get());
|
||||
}
|
||||
}
|
||||
|
||||
if (canRecoverAutomatically(e)) {
|
||||
Recipient recipient = Recipient.from(context, Address.fromSerialized(sender), false);
|
||||
LokiThreadDatabase threadDB = DatabaseFactory.getLokiThreadDatabase(context);
|
||||
long threadID = DatabaseFactory.getThreadDatabase(context).getOrCreateThreadIdFor(recipient);
|
||||
threadDB.addSessionRestoreDevice(threadID, sender);
|
||||
SessionManagementProtocol.startSessionReset(context, sender);
|
||||
} else {
|
||||
SessionManagementProtocol.triggerSessionRestorationUI(context, sender, timestamp);
|
||||
}
|
||||
}
|
||||
|
||||
private boolean canRecoverAutomatically(Throwable e) {
|
||||
// Corrupt message exception
|
||||
if (e.getCause() != null) {
|
||||
Throwable e2 = e.getCause();
|
||||
if (e2.getCause() != null) {
|
||||
Throwable e3 = e2.getCause();
|
||||
if (e3 instanceof InvalidMessageException) {
|
||||
String message = e3.getMessage();
|
||||
return (message != null && message.startsWith("Bad Mac!"));
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private void handleNoSessionMessage(@NonNull String sender, int senderDevice, long timestamp,
|
||||
@NonNull Optional<Long> smsMessageId)
|
||||
{
|
||||
SmsDatabase smsDatabase = DatabaseFactory.getSmsDatabase(context);
|
||||
if (!SessionMetaProtocol.shouldIgnoreDecryptionException(context, timestamp)) {
|
||||
if (!smsMessageId.isPresent()) {
|
||||
Optional<InsertResult> insertResult = insertPlaceholder(sender, senderDevice, timestamp);
|
||||
|
||||
if (insertResult.isPresent()) {
|
||||
smsDatabase.markAsNoSession(insertResult.get().getMessageId());
|
||||
messageNotifier.updateNotification(context, insertResult.get().getThreadId());
|
||||
}
|
||||
} else {
|
||||
smsDatabase.markAsNoSession(smsMessageId.get());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void handleLegacyMessage(@NonNull String sender, int senderDevice, long timestamp,
|
||||
@NonNull Optional<Long> smsMessageId)
|
||||
{
|
||||
SmsDatabase smsDatabase = DatabaseFactory.getSmsDatabase(context);
|
||||
|
||||
if (!smsMessageId.isPresent()) {
|
||||
Optional<InsertResult> insertResult = insertPlaceholder(sender, senderDevice, timestamp);
|
||||
|
||||
if (insertResult.isPresent()) {
|
||||
smsDatabase.markAsLegacyVersion(insertResult.get().getMessageId());
|
||||
messageNotifier.updateNotification(context, insertResult.get().getThreadId());
|
||||
}
|
||||
} else {
|
||||
smsDatabase.markAsLegacyVersion(smsMessageId.get());
|
||||
}
|
||||
}
|
||||
|
||||
@SuppressWarnings("unused")
|
||||
private void handleDuplicateMessage(@NonNull String sender, int senderDeviceId, long timestamp,
|
||||
@NonNull Optional<Long> smsMessageId)
|
||||
{
|
||||
// Let's start ignoring these now
|
||||
// SmsDatabase smsDatabase = DatabaseFactory.getEncryptingSmsDatabase(context);
|
||||
//
|
||||
// if (smsMessageId <= 0) {
|
||||
// Pair<Long, Long> messageAndThreadId = insertPlaceholder(masterSecret, envelope);
|
||||
// smsDatabase.markAsDecryptDuplicate(messageAndThreadId.first);
|
||||
// MessageNotifier.updateNotification(context, masterSecret, messageAndThreadId.second);
|
||||
// } else {
|
||||
// smsDatabase.markAsDecryptDuplicate(smsMessageId);
|
||||
// }
|
||||
}
|
||||
|
||||
private void handleNeedsDeliveryReceipt(@NonNull SignalServiceContent content,
|
||||
@ -905,42 +802,6 @@ public class PushDecryptJob extends BaseJob implements InjectableType {
|
||||
PointerAttachment.forPointersOfDataMessage(quote.get().getAttachments())));
|
||||
}
|
||||
|
||||
private Optional<Attachment> getStickerAttachment(Optional<SignalServiceDataMessage.Sticker> sticker) {
|
||||
if (!sticker.isPresent()) {
|
||||
return Optional.absent();
|
||||
}
|
||||
|
||||
if (sticker.get().getPackId() == null || sticker.get().getPackKey() == null || sticker.get().getAttachment() == null) {
|
||||
Log.w(TAG, "Malformed sticker!");
|
||||
return Optional.absent();
|
||||
}
|
||||
|
||||
String packId = Hex.toStringCondensed(sticker.get().getPackId());
|
||||
String packKey = Hex.toStringCondensed(sticker.get().getPackKey());
|
||||
int stickerId = sticker.get().getStickerId();
|
||||
StickerLocator stickerLocator = new StickerLocator(packId, packKey, stickerId);
|
||||
StickerDatabase stickerDatabase = DatabaseFactory.getStickerDatabase(context);
|
||||
StickerRecord stickerRecord = stickerDatabase.getSticker(stickerLocator.getPackId(), stickerLocator.getStickerId(), false);
|
||||
|
||||
if (stickerRecord != null) {
|
||||
return Optional.of(new UriAttachment(stickerRecord.getUri(),
|
||||
stickerRecord.getUri(),
|
||||
MediaTypes.IMAGE_WEBP,
|
||||
AttachmentDatabase.TRANSFER_PROGRESS_DONE,
|
||||
stickerRecord.getSize(),
|
||||
StickerSlide.WIDTH,
|
||||
StickerSlide.HEIGHT,
|
||||
null,
|
||||
String.valueOf(new SecureRandom().nextLong()),
|
||||
false,
|
||||
false,
|
||||
null,
|
||||
stickerLocator));
|
||||
} else {
|
||||
return Optional.of(PointerAttachment.forPointer(Optional.of(sticker.get().getAttachment()), stickerLocator).get());
|
||||
}
|
||||
}
|
||||
|
||||
private Optional<List<Contact>> getContacts(Optional<List<SharedContact>> sharedContacts) {
|
||||
if (!sharedContacts.isPresent()) return Optional.absent();
|
||||
|
||||
@ -1069,10 +930,6 @@ public class PushDecryptJob extends BaseJob implements InjectableType {
|
||||
return false;
|
||||
}
|
||||
|
||||
private boolean isGroupChatMessage(SignalServiceContent content) {
|
||||
return content.getDataMessage().isPresent() && content.getDataMessage().get().isGroupMessage();
|
||||
}
|
||||
|
||||
private void resetRecipientToPush(@NonNull Recipient recipient) {
|
||||
if (recipient.isForceSmsSelection()) {
|
||||
DatabaseFactory.getRecipientDatabase(context).setForceSmsSelection(recipient, false);
|
||||
|
@ -39,12 +39,10 @@ import org.session.libsignal.service.api.messages.SendMessageResult;
|
||||
import org.session.libsignal.service.api.messages.SignalServiceAttachment;
|
||||
import org.session.libsignal.service.api.messages.SignalServiceDataMessage;
|
||||
import org.session.libsignal.service.api.messages.SignalServiceDataMessage.Preview;
|
||||
import org.session.libsignal.service.api.messages.multidevice.SignalServiceSyncMessage;
|
||||
import org.session.libsignal.service.api.messages.shared.SharedContact;
|
||||
import org.session.libsignal.service.api.push.SignalServiceAddress;
|
||||
import org.session.libsignal.service.api.push.exceptions.UnregisteredUserException;
|
||||
import org.session.libsignal.service.loki.api.SnodeAPI;
|
||||
import org.session.libsignal.service.loki.protocol.meta.SessionMetaProtocol;
|
||||
|
||||
import java.io.FileNotFoundException;
|
||||
import java.io.IOException;
|
||||
@ -285,7 +283,7 @@ public class PushMediaSendJob extends PushSendJob implements InjectableType {
|
||||
.asExpirationUpdate(message.isExpirationUpdate())
|
||||
.build();
|
||||
|
||||
if (SessionMetaProtocol.shared.isNoteToSelf(address.getNumber())) {
|
||||
if (userPublicKey == address.getNumber()) {
|
||||
// Loki - Device link messages don't go through here
|
||||
SendMessageResult result = messageSender.sendMessage(messageId, address, unidentifiedAccessPair, mediaMessage);
|
||||
if (result.getLokiAPIError() != null) {
|
||||
|
@ -33,10 +33,7 @@ public abstract class PushReceivedJob extends BaseJob {
|
||||
}
|
||||
}
|
||||
|
||||
if (envelope.isReceipt()) {
|
||||
handleReceipt(envelope);
|
||||
} else if (envelope.isPreKeySignalMessage() || envelope.isSignalMessage()
|
||||
|| envelope.isUnidentifiedSender() || envelope.isFallbackMessage() || envelope.isClosedGroupCiphertext()) {
|
||||
if (envelope.isUnidentifiedSender() || envelope.isClosedGroupCiphertext()) {
|
||||
handleMessage(envelope, isPushNotification);
|
||||
} else {
|
||||
Log.w(TAG, "Received envelope of unknown type: " + envelope.getType());
|
||||
@ -51,13 +48,6 @@ public abstract class PushReceivedJob extends BaseJob {
|
||||
new PushDecryptJob(context).processMessage(envelope, isPushNotification);
|
||||
}
|
||||
|
||||
@SuppressLint("DefaultLocale")
|
||||
private void handleReceipt(SignalServiceEnvelope envelope) {
|
||||
Log.i(TAG, String.format("Received receipt: (XXXXX, %d)", envelope.getTimestamp()));
|
||||
DatabaseFactory.getMmsSmsDatabase(context).incrementDeliveryReceiptCount(new SyncMessageId(Address.fromExternal(context, envelope.getSource()),
|
||||
envelope.getTimestamp()), System.currentTimeMillis());
|
||||
}
|
||||
|
||||
private boolean isActiveNumber(@NonNull Recipient recipient) {
|
||||
return recipient.resolve().getRegistered() == Recipient.RegisteredState.REGISTERED;
|
||||
}
|
||||
|
@ -12,7 +12,6 @@ import org.session.libsession.messaging.sending_receiving.attachments.Attachment
|
||||
import org.session.libsession.messaging.sending_receiving.sharecontacts.Contact;
|
||||
import org.session.libsession.utilities.MediaTypes;
|
||||
import org.session.libsignal.utilities.Base64;
|
||||
import org.session.libsession.utilities.TextSecurePreferences;
|
||||
import org.session.libsession.utilities.Util;
|
||||
|
||||
import org.greenrobot.eventbus.EventBus;
|
||||
@ -34,13 +33,10 @@ import org.thoughtcrime.securesms.util.BitmapUtil;
|
||||
import org.session.libsignal.utilities.Hex;
|
||||
import org.thoughtcrime.securesms.util.MediaUtil;
|
||||
import org.session.libsignal.libsignal.util.guava.Optional;
|
||||
import org.session.libsignal.service.api.crypto.UnidentifiedAccessPair;
|
||||
import org.session.libsignal.service.api.messages.SignalServiceAttachment;
|
||||
import org.session.libsignal.service.api.messages.SignalServiceAttachmentPointer;
|
||||
import org.session.libsignal.service.api.messages.SignalServiceDataMessage;
|
||||
import org.session.libsignal.service.api.messages.SignalServiceDataMessage.Preview;
|
||||
import org.session.libsignal.service.api.messages.multidevice.SentTranscriptMessage;
|
||||
import org.session.libsignal.service.api.messages.multidevice.SignalServiceSyncMessage;
|
||||
import org.session.libsignal.service.api.messages.shared.SharedContact;
|
||||
import org.session.libsignal.service.api.push.SignalServiceAddress;
|
||||
|
||||
@ -55,7 +51,6 @@ import java.util.concurrent.TimeUnit;
|
||||
public abstract class PushSendJob extends SendJob {
|
||||
|
||||
private static final String TAG = PushSendJob.class.getSimpleName();
|
||||
private static final long CERTIFICATE_EXPIRATION_BUFFER = TimeUnit.DAYS.toMillis(1);
|
||||
|
||||
protected PushSendJob(Job.Parameters parameters) {
|
||||
super(parameters);
|
||||
@ -72,14 +67,6 @@ public abstract class PushSendJob extends SendJob {
|
||||
|
||||
@Override
|
||||
protected final void onSend() throws Exception {
|
||||
// if (TextSecurePreferences.getSignedPreKeyFailureCount(context) > 5) {
|
||||
// ApplicationContext.getInstance(context)
|
||||
// .getJobManager()
|
||||
// .add(new RotateSignedPreKeyJob());
|
||||
//
|
||||
// throw new TextSecureExpiredException("Too many signed prekey rotation failures");
|
||||
// }
|
||||
|
||||
onPushSend();
|
||||
}
|
||||
|
||||
|
@ -30,11 +30,9 @@ import org.session.libsignal.service.api.crypto.UnidentifiedAccessPair;
|
||||
import org.session.libsignal.service.api.crypto.UntrustedIdentityException;
|
||||
import org.session.libsignal.service.api.messages.SendMessageResult;
|
||||
import org.session.libsignal.service.api.messages.SignalServiceDataMessage;
|
||||
import org.session.libsignal.service.api.messages.multidevice.SignalServiceSyncMessage;
|
||||
import org.session.libsignal.service.api.push.SignalServiceAddress;
|
||||
import org.session.libsignal.service.api.push.exceptions.UnregisteredUserException;
|
||||
import org.session.libsignal.service.loki.api.SnodeAPI;
|
||||
import org.session.libsignal.service.loki.protocol.meta.SessionMetaProtocol;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
@ -224,7 +222,7 @@ public class PushTextSendJob extends PushSendJob implements InjectableType {
|
||||
.asEndSessionMessage(message.isEndSession())
|
||||
.build();
|
||||
|
||||
if (SessionMetaProtocol.shared.isNoteToSelf(address.getNumber())) {
|
||||
if (userPublicKey.equals(address.getNumber())) {
|
||||
// Loki - Device link messages don't go through here
|
||||
SendMessageResult result = messageSender.sendMessage(messageId, address, unidentifiedAccess, textSecureMessage);
|
||||
if (result.getLokiAPIError() != null) {
|
||||
|
@ -87,16 +87,14 @@ public class TypingSendJob extends BaseJob implements InjectableType {
|
||||
}
|
||||
|
||||
List<Recipient> recipients = Collections.singletonList(recipient);
|
||||
Optional<byte[]> groupId = Optional.absent();
|
||||
|
||||
if (recipient.isGroupRecipient()) {
|
||||
recipients = DatabaseFactory.getGroupDatabase(context).getGroupMembers(recipient.getAddress().toGroupString(), false);
|
||||
groupId = Optional.of(GroupUtil.getDecodedGroupIDAsData(recipient.getAddress().toGroupString()));
|
||||
}
|
||||
|
||||
List<SignalServiceAddress> addresses = Stream.of(recipients).map(r -> new SignalServiceAddress(r.getAddress().serialize())).toList();
|
||||
List<Optional<UnidentifiedAccessPair>> unidentifiedAccess = Stream.of(recipients).map(r -> UnidentifiedAccessUtil.getAccessFor(context, r)).toList();
|
||||
SignalServiceTypingMessage typingMessage = new SignalServiceTypingMessage(typing ? Action.STARTED : Action.STOPPED, System.currentTimeMillis(), groupId);
|
||||
SignalServiceTypingMessage typingMessage = new SignalServiceTypingMessage(typing ? Action.STARTED : Action.STOPPED, System.currentTimeMillis());
|
||||
|
||||
messageSender.sendTyping(addresses, unidentifiedAccess, typingMessage);
|
||||
}
|
||||
|
@ -193,8 +193,6 @@ class BackupRestoreViewModel(application: Application): AndroidViewModel(applica
|
||||
application.setUpStorageAPIIfNeeded()
|
||||
application.setUpP2PAPIIfNeeded()
|
||||
|
||||
HomeActivity.requestResetAllSessionsOnStartup(context)
|
||||
|
||||
BackupRestoreResult.SUCCESS
|
||||
} catch (e: DatabaseDowngradeException) {
|
||||
Log.w(TAG, "Failed due to the backup being from a newer version of Signal.", e)
|
||||
|
@ -33,7 +33,6 @@ import org.session.libsession.utilities.GroupUtil
|
||||
import org.thoughtcrime.securesms.database.DatabaseFactory
|
||||
import org.thoughtcrime.securesms.database.model.ThreadRecord
|
||||
import org.thoughtcrime.securesms.loki.api.ResetThreadSessionJob
|
||||
import org.thoughtcrime.securesms.loki.protocol.SessionResetImplementation
|
||||
import org.thoughtcrime.securesms.loki.utilities.*
|
||||
import org.thoughtcrime.securesms.loki.views.ConversationView
|
||||
import org.thoughtcrime.securesms.loki.views.NewConversationButtonSetViewDelegate
|
||||
@ -44,8 +43,7 @@ import org.session.libsession.utilities.TextSecurePreferences
|
||||
import org.session.libsession.utilities.TextSecurePreferences.getBooleanPreference
|
||||
import org.session.libsession.utilities.TextSecurePreferences.setBooleanPreference
|
||||
import org.session.libsession.utilities.Util
|
||||
import org.session.libsignal.service.loki.protocol.mentions.MentionsManager
|
||||
import org.session.libsignal.service.loki.protocol.meta.SessionMetaProtocol
|
||||
import org.session.libsignal.service.loki.utilities.mentions.MentionsManager
|
||||
import org.session.libsignal.utilities.ThreadUtils
|
||||
import org.session.libsignal.service.loki.utilities.toHexString
|
||||
import org.thoughtcrime.securesms.loki.dialogs.*
|
||||
@ -54,31 +52,6 @@ import java.io.IOException
|
||||
|
||||
class HomeActivity : PassphraseRequiredActionBarActivity, ConversationClickListener, SeedReminderViewDelegate, NewConversationButtonSetViewDelegate {
|
||||
|
||||
companion object {
|
||||
private const val PREF_RESET_ALL_SESSIONS_ON_START_UP = "pref_reset_all_sessions_on_start_up"
|
||||
|
||||
@JvmStatic
|
||||
fun requestResetAllSessionsOnStartup(context: Context) {
|
||||
setBooleanPreference(context, PREF_RESET_ALL_SESSIONS_ON_START_UP, true)
|
||||
}
|
||||
|
||||
@JvmStatic
|
||||
fun scheduleResetAllSessionsIfRequested(context: Context) {
|
||||
if (!getBooleanPreference(context, PREF_RESET_ALL_SESSIONS_ON_START_UP, false)) return
|
||||
setBooleanPreference(context, PREF_RESET_ALL_SESSIONS_ON_START_UP, false)
|
||||
|
||||
val jobManager = ApplicationContext.getInstance(context).jobManager
|
||||
|
||||
DatabaseFactory.getThreadDatabase(context).conversationListQuick.forEach { tuple ->
|
||||
val threadId: Long = tuple.first
|
||||
val recipientAddress: String = tuple.second
|
||||
jobManager.add(ResetThreadSessionJob(
|
||||
Address.fromSerialized(recipientAddress),
|
||||
threadId))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private lateinit var glide: GlideRequests
|
||||
private var broadcastReceiver: BroadcastReceiver? = null
|
||||
|
||||
@ -165,10 +138,8 @@ class HomeActivity : PassphraseRequiredActionBarActivity, ConversationClickListe
|
||||
val threadDB = DatabaseFactory.getLokiThreadDatabase(this)
|
||||
val userDB = DatabaseFactory.getLokiUserDatabase(this)
|
||||
val userPublicKey = TextSecurePreferences.getLocalNumber(this)
|
||||
val sessionResetImpl = SessionResetImplementation(this)
|
||||
if (userPublicKey != null) {
|
||||
MentionsManager.configureIfNeeded(userPublicKey, threadDB, userDB)
|
||||
SessionMetaProtocol.configureIfNeeded(apiDB, userPublicKey)
|
||||
application.publicChatManager.startPollersIfNeeded()
|
||||
}
|
||||
IP2Country.configureIfNeeded(this)
|
||||
|
@ -153,67 +153,11 @@ class PublicChatPoller(private val context: Context, private val group: PublicCh
|
||||
signalLinkPreviews.add(SignalServiceDataMessage.Preview(linkPreview.linkPreviewURL!!, linkPreview.linkPreviewTitle!!, Optional.of(attachment)))
|
||||
}
|
||||
val body = if (message.body == message.timestamp.toString()) "" else message.body // Workaround for the fact that the back-end doesn't accept messages without a body
|
||||
return SignalServiceDataMessage(message.timestamp, serviceGroup, attachments, body, 0, false, null, quote, null, signalLinkPreviews)
|
||||
val syncTarget = if (message.senderPublicKey == userHexEncodedPublicKey) group.id else null
|
||||
return SignalServiceDataMessage(message.timestamp, serviceGroup, attachments, body, 0, false, null, quote, null, signalLinkPreviews, null, syncTarget)
|
||||
}
|
||||
|
||||
fun pollForNewMessages(): Promise<Unit, Exception> {
|
||||
fun processIncomingMessage(message: PublicChatMessage) {
|
||||
// If the sender of the current message is not a slave device, set the display name in the database
|
||||
val senderDisplayName = "${message.displayName} (...${message.senderPublicKey.takeLast(8)})"
|
||||
DatabaseFactory.getLokiUserDatabase(context).setServerDisplayName(group.id, message.senderPublicKey, senderDisplayName)
|
||||
val senderHexEncodedPublicKey = message.senderPublicKey
|
||||
val serviceDataMessage = getDataMessage(message)
|
||||
val serviceContent = SignalServiceContent(serviceDataMessage, senderHexEncodedPublicKey, SignalServiceAddress.DEFAULT_DEVICE_ID, message.serverTimestamp, false)
|
||||
if (serviceDataMessage.quote.isPresent || (serviceDataMessage.attachments.isPresent && serviceDataMessage.attachments.get().size > 0) || serviceDataMessage.previews.isPresent) {
|
||||
PushDecryptJob(context).handleMediaMessage(serviceContent, serviceDataMessage, Optional.absent(), Optional.of(message.serverID))
|
||||
} else {
|
||||
PushDecryptJob(context).handleTextMessage(serviceContent, serviceDataMessage, Optional.absent(), Optional.of(message.serverID))
|
||||
}
|
||||
// Update profile picture if needed
|
||||
val senderAsRecipient = Recipient.from(context, Address.fromSerialized(senderHexEncodedPublicKey), false)
|
||||
if (message.profilePicture != null && message.profilePicture!!.url.isNotEmpty()) {
|
||||
val profileKey = message.profilePicture!!.profileKey
|
||||
val url = message.profilePicture!!.url
|
||||
if (senderAsRecipient.profileKey == null || !MessageDigest.isEqual(senderAsRecipient.profileKey, profileKey)) {
|
||||
val database = DatabaseFactory.getRecipientDatabase(context)
|
||||
database.setProfileKey(senderAsRecipient, profileKey)
|
||||
ApplicationContext.getInstance(context).jobManager.add(RetrieveProfileAvatarJob(senderAsRecipient, url))
|
||||
}
|
||||
}
|
||||
}
|
||||
fun processOutgoingMessage(message: PublicChatMessage) {
|
||||
val messageServerID = message.serverID ?: return
|
||||
val messageID = DatabaseFactory.getLokiMessageDatabase(context).getMessageID(messageServerID)
|
||||
var isDuplicate = false
|
||||
if (messageID != null) {
|
||||
isDuplicate = DatabaseFactory.getMmsDatabase(context).getThreadIdForMessage(messageID) >= 0
|
||||
|| DatabaseFactory.getSmsDatabase(context).getThreadIdForMessage(messageID) >= 0
|
||||
}
|
||||
if (isDuplicate) { return }
|
||||
if (message.body.isEmpty() && message.attachments.isEmpty() && message.quote == null) { return }
|
||||
val userHexEncodedPublicKey = TextSecurePreferences.getLocalNumber(context)
|
||||
val dataMessage = getDataMessage(message)
|
||||
SessionMetaProtocol.dropFromTimestampCacheIfNeeded(message.serverTimestamp)
|
||||
val transcript = SentTranscriptMessage(userHexEncodedPublicKey, message.serverTimestamp, dataMessage, dataMessage.expiresInSeconds.toLong(), Collections.singletonMap(userHexEncodedPublicKey, false))
|
||||
transcript.messageServerID = messageServerID
|
||||
if (dataMessage.quote.isPresent || (dataMessage.attachments.isPresent && dataMessage.attachments.get().size > 0) || dataMessage.previews.isPresent) {
|
||||
PushDecryptJob(context).handleSynchronizeSentMediaMessage(transcript)
|
||||
} else {
|
||||
PushDecryptJob(context).handleSynchronizeSentTextMessage(transcript)
|
||||
}
|
||||
// If we got a message from our master device then make sure our mapping stays in sync
|
||||
val recipient = Recipient.from(context, Address.fromSerialized(message.senderPublicKey), false)
|
||||
if (message.profilePicture != null) {
|
||||
val profileKey = message.profilePicture!!.profileKey
|
||||
val url = message.profilePicture!!.url
|
||||
if (recipient.profileKey == null || !MessageDigest.isEqual(recipient.profileKey, profileKey)) {
|
||||
val database = DatabaseFactory.getRecipientDatabase(context)
|
||||
database.setProfileKey(recipient, profileKey)
|
||||
database.setProfileAvatar(recipient, url)
|
||||
ApplicationContext.getInstance(context).updateOpenGroupProfilePicturesIfNeeded()
|
||||
}
|
||||
}
|
||||
}
|
||||
if (isPollOngoing) { return Promise.of(Unit) }
|
||||
isPollOngoing = true
|
||||
val userPrivateKey = IdentityKeyUtil.getIdentityKeyPair(context).privateKey.serialize()
|
||||
@ -226,10 +170,27 @@ class PublicChatPoller(private val context: Context, private val group: PublicCh
|
||||
promise.successBackground { messages ->
|
||||
// Process messages in the background
|
||||
messages.forEach { message ->
|
||||
if (message.senderPublicKey == userHexEncodedPublicKey) {
|
||||
processOutgoingMessage(message)
|
||||
// If the sender of the current message is not a slave device, set the display name in the database
|
||||
val senderDisplayName = "${message.displayName} (...${message.senderPublicKey.takeLast(8)})"
|
||||
DatabaseFactory.getLokiUserDatabase(context).setServerDisplayName(group.id, message.senderPublicKey, senderDisplayName)
|
||||
val senderHexEncodedPublicKey = message.senderPublicKey
|
||||
val serviceDataMessage = getDataMessage(message)
|
||||
val serviceContent = SignalServiceContent(serviceDataMessage, senderHexEncodedPublicKey, SignalServiceAddress.DEFAULT_DEVICE_ID, message.serverTimestamp, false)
|
||||
if (serviceDataMessage.quote.isPresent || (serviceDataMessage.attachments.isPresent && serviceDataMessage.attachments.get().size > 0) || serviceDataMessage.previews.isPresent) {
|
||||
PushDecryptJob(context).handleMediaMessage(serviceContent, serviceDataMessage, Optional.absent(), Optional.of(message.serverID))
|
||||
} else {
|
||||
processIncomingMessage(message)
|
||||
PushDecryptJob(context).handleTextMessage(serviceContent, serviceDataMessage, Optional.absent(), Optional.of(message.serverID))
|
||||
}
|
||||
// Update profile picture if needed
|
||||
val senderAsRecipient = Recipient.from(context, Address.fromSerialized(senderHexEncodedPublicKey), false)
|
||||
if (message.profilePicture != null && message.profilePicture!!.url.isNotEmpty()) {
|
||||
val profileKey = message.profilePicture!!.profileKey
|
||||
val url = message.profilePicture!!.url
|
||||
if (senderAsRecipient.profileKey == null || !MessageDigest.isEqual(senderAsRecipient.profileKey, profileKey)) {
|
||||
val database = DatabaseFactory.getRecipientDatabase(context)
|
||||
database.setProfileKey(senderAsRecipient, profileKey)
|
||||
ApplicationContext.getInstance(context).jobManager.add(RetrieveProfileAvatarJob(senderAsRecipient, url))
|
||||
}
|
||||
}
|
||||
}
|
||||
isCaughtUp = true
|
||||
|
@ -14,7 +14,6 @@ import org.session.libsession.messaging.threads.recipients.Recipient
|
||||
import org.session.libsession.utilities.TextSecurePreferences
|
||||
import org.session.libsignal.service.loki.api.opengroups.PublicChat
|
||||
|
||||
import org.session.libsignal.libsignal.loki.SessionResetStatus
|
||||
import org.session.libsignal.utilities.JsonUtil
|
||||
import org.session.libsignal.service.loki.database.LokiThreadDatabaseProtocol
|
||||
import org.session.libsignal.service.loki.utilities.PublicKeyValidation
|
||||
@ -39,34 +38,6 @@ class LokiThreadDatabase(context: Context, helper: SQLCipherOpenHelper) : Databa
|
||||
return DatabaseFactory.getThreadDatabase(context).getOrCreateThreadIdFor(recipient)
|
||||
}
|
||||
|
||||
fun getThreadID(messageID: Long): Long {
|
||||
return DatabaseFactory.getSmsDatabase(context).getThreadIdForMessage(messageID)
|
||||
}
|
||||
|
||||
fun getSessionResetStatus(hexEncodedPublicKey: String): SessionResetStatus {
|
||||
val threadID = getThreadID(hexEncodedPublicKey)
|
||||
val database = databaseHelper.readableDatabase
|
||||
val result = database.get(sessionResetTable, "${Companion.threadID} = ?", arrayOf( threadID.toString() )) { cursor ->
|
||||
cursor.getInt(sessionResetStatus)
|
||||
}
|
||||
return if (result != null) {
|
||||
SessionResetStatus.values().first { it.rawValue == result }
|
||||
} else {
|
||||
SessionResetStatus.NONE
|
||||
}
|
||||
}
|
||||
|
||||
fun setSessionResetStatus(hexEncodedPublicKey: String, sessionResetStatus: SessionResetStatus) {
|
||||
val threadID = getThreadID(hexEncodedPublicKey)
|
||||
val database = databaseHelper.writableDatabase
|
||||
val contentValues = ContentValues(2)
|
||||
contentValues.put(Companion.threadID, threadID)
|
||||
contentValues.put(Companion.sessionResetStatus, sessionResetStatus.rawValue)
|
||||
database.insertOrUpdate(sessionResetTable, contentValues, "${Companion.threadID} = ?", arrayOf( threadID.toString() ))
|
||||
notifyConversationListListeners()
|
||||
notifyConversationListeners(threadID)
|
||||
}
|
||||
|
||||
fun getAllPublicChats(): Map<Long, PublicChat> {
|
||||
val database = databaseHelper.readableDatabase
|
||||
var cursor: Cursor? = null
|
||||
|
@ -13,7 +13,7 @@ import org.session.libsignal.libsignal.util.guava.Optional
|
||||
import org.session.libsignal.service.api.push.SignalServiceAddress
|
||||
import org.session.libsignal.service.internal.push.SignalServiceProtos
|
||||
import org.session.libsignal.service.internal.push.SignalServiceProtos.DataMessage
|
||||
import org.session.libsignal.service.loki.protocol.meta.TTLUtilities
|
||||
import org.session.libsignal.service.loki.utilities.TTLUtilities
|
||||
import org.session.libsignal.service.loki.utilities.removing05PrefixIfNeeded
|
||||
import org.session.libsignal.service.loki.utilities.toHexString
|
||||
import org.thoughtcrime.securesms.ApplicationContext
|
||||
@ -25,7 +25,6 @@ import org.session.libsignal.utilities.logging.Log
|
||||
import org.thoughtcrime.securesms.loki.utilities.recipient
|
||||
import org.session.libsignal.utilities.Hex
|
||||
|
||||
import java.util.*
|
||||
import java.util.concurrent.TimeUnit
|
||||
|
||||
class ClosedGroupUpdateMessageSendJobV2 private constructor(parameters: Parameters, private val destination: String, private val kind: Kind, private val sentTime: Long) : BaseJob(parameters) {
|
||||
|
@ -8,6 +8,7 @@ import org.session.libsession.utilities.TextSecurePreferences
|
||||
import org.session.libsignal.libsignal.util.guava.Optional
|
||||
import org.session.libsignal.service.api.push.SignalServiceAddress
|
||||
import org.session.libsignal.service.internal.push.SignalServiceProtos
|
||||
import org.session.libsignal.service.internal.push.SignalServiceProtos.DataMessage
|
||||
import org.session.libsignal.service.loki.utilities.removing05PrefixIfNeeded
|
||||
import org.session.libsignal.utilities.Hex
|
||||
import org.session.libsignal.utilities.logging.Log
|
||||
@ -72,8 +73,8 @@ object MultiDeviceProtocol {
|
||||
for (closedGroup in configurationMessage.closedGroups) {
|
||||
if (allClosedGroupPublicKeys.contains(closedGroup.publicKey)) continue
|
||||
|
||||
val closedGroupUpdate = SignalServiceProtos.ClosedGroupUpdateV2.newBuilder()
|
||||
closedGroupUpdate.type = SignalServiceProtos.ClosedGroupUpdateV2.Type.NEW
|
||||
val closedGroupUpdate = DataMessage.ClosedGroupControlMessage.newBuilder()
|
||||
closedGroupUpdate.type = DataMessage.ClosedGroupControlMessage.Type.NEW
|
||||
closedGroupUpdate.publicKey = ByteString.copyFrom(Hex.fromStringCondensed(closedGroup.publicKey))
|
||||
closedGroupUpdate.name = closedGroup.name
|
||||
val encryptionKeyPair = SignalServiceProtos.KeyPair.newBuilder()
|
||||
|
@ -1,85 +0,0 @@
|
||||
package org.thoughtcrime.securesms.loki.protocol
|
||||
|
||||
import com.google.protobuf.ByteString
|
||||
import org.session.libsession.messaging.jobs.Data
|
||||
import org.thoughtcrime.securesms.ApplicationContext
|
||||
import org.thoughtcrime.securesms.crypto.UnidentifiedAccessUtil
|
||||
import org.session.libsession.messaging.threads.Address
|
||||
import org.thoughtcrime.securesms.jobmanager.Job
|
||||
import org.thoughtcrime.securesms.jobmanager.impl.NetworkConstraint
|
||||
import org.thoughtcrime.securesms.jobs.BaseJob
|
||||
import org.session.libsignal.utilities.logging.Log
|
||||
import org.session.libsession.messaging.threads.recipients.Recipient
|
||||
import org.session.libsignal.libsignal.util.guava.Optional
|
||||
import org.session.libsignal.service.api.push.SignalServiceAddress
|
||||
import org.session.libsignal.service.internal.push.SignalServiceProtos
|
||||
import org.session.libsignal.service.loki.protocol.meta.TTLUtilities
|
||||
import java.io.IOException
|
||||
import java.security.SecureRandom
|
||||
import java.util.*
|
||||
import java.util.concurrent.TimeUnit
|
||||
|
||||
class NullMessageSendJob private constructor(parameters: Parameters, private val publicKey: String) : BaseJob(parameters) {
|
||||
|
||||
companion object {
|
||||
const val KEY = "NullMessageSendJob"
|
||||
}
|
||||
|
||||
constructor(publicKey: String) : this(Parameters.Builder()
|
||||
.addConstraint(NetworkConstraint.KEY)
|
||||
.setQueue(KEY)
|
||||
.setLifespan(TimeUnit.DAYS.toMillis(1))
|
||||
.setMaxAttempts(1)
|
||||
.build(),
|
||||
publicKey)
|
||||
|
||||
override fun serialize(): Data {
|
||||
return Data.Builder().putString("publicKey", publicKey).build()
|
||||
}
|
||||
|
||||
override fun getFactoryKey(): String { return KEY }
|
||||
|
||||
public override fun onRun() {
|
||||
val contentMessage = SignalServiceProtos.Content.newBuilder()
|
||||
val nullMessage = SignalServiceProtos.NullMessage.newBuilder()
|
||||
val sr = SecureRandom()
|
||||
val paddingSize = sr.nextInt(512)
|
||||
val padding = ByteArray(paddingSize)
|
||||
sr.nextBytes(padding)
|
||||
nullMessage.padding = ByteString.copyFrom(padding)
|
||||
contentMessage.nullMessage = nullMessage.build()
|
||||
val serializedContentMessage = contentMessage.build().toByteArray()
|
||||
val messageSender = ApplicationContext.getInstance(context).communicationModule.provideSignalMessageSender()
|
||||
val address = SignalServiceAddress(publicKey)
|
||||
val recipient = Recipient.from(context, Address.fromSerialized(publicKey), false)
|
||||
val udAccess = UnidentifiedAccessUtil.getAccessFor(context, recipient)
|
||||
val ttl = TTLUtilities.getTTL(TTLUtilities.MessageType.Ephemeral)
|
||||
try {
|
||||
messageSender.sendMessage(0, address, udAccess.get().targetUnidentifiedAccess,
|
||||
Date().time, serializedContentMessage, false, ttl,
|
||||
false, false, false, Optional.absent())
|
||||
} catch (e: Exception) {
|
||||
Log.d("Loki", "Failed to send null message to: $publicKey due to error: $e.")
|
||||
throw e
|
||||
}
|
||||
}
|
||||
|
||||
public override fun onShouldRetry(e: Exception): Boolean {
|
||||
// Disable since we have our own retrying
|
||||
return false
|
||||
}
|
||||
|
||||
override fun onCanceled() { }
|
||||
|
||||
class Factory : Job.Factory<NullMessageSendJob> {
|
||||
|
||||
override fun create(parameters: Parameters, data: Data): NullMessageSendJob {
|
||||
try {
|
||||
val publicKey = data.getString("publicKey")
|
||||
return NullMessageSendJob(parameters, publicKey)
|
||||
} catch (e: IOException) {
|
||||
throw AssertionError(e)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -1,102 +0,0 @@
|
||||
package org.thoughtcrime.securesms.loki.protocol
|
||||
|
||||
import android.content.Context
|
||||
import org.session.libsignal.utilities.logging.Log
|
||||
import org.thoughtcrime.securesms.ApplicationContext
|
||||
import org.thoughtcrime.securesms.crypto.SecurityEvent
|
||||
import org.thoughtcrime.securesms.crypto.storage.TextSecureSessionStore
|
||||
import org.thoughtcrime.securesms.database.DatabaseFactory
|
||||
import org.thoughtcrime.securesms.loki.utilities.recipient
|
||||
import org.thoughtcrime.securesms.sms.MessageSender
|
||||
import org.thoughtcrime.securesms.sms.OutgoingEndSessionMessage
|
||||
import org.thoughtcrime.securesms.sms.OutgoingTextMessage
|
||||
import org.session.libsession.utilities.TextSecurePreferences
|
||||
import org.session.libsignal.libsignal.loki.SessionResetStatus
|
||||
import org.session.libsignal.service.api.messages.SignalServiceContent
|
||||
import java.util.*
|
||||
|
||||
object SessionManagementProtocol {
|
||||
|
||||
@JvmStatic
|
||||
fun startSessionReset(context: Context, publicKey: String) {
|
||||
val recipient = recipient(context, publicKey)
|
||||
if (recipient.isGroupRecipient) { return }
|
||||
val lokiThreadDB = DatabaseFactory.getLokiThreadDatabase(context)
|
||||
val threadID = DatabaseFactory.getThreadDatabase(context).getOrCreateThreadIdFor(recipient)
|
||||
val devices = lokiThreadDB.getSessionRestoreDevices(threadID)
|
||||
for (device in devices) {
|
||||
val endSessionMessage = OutgoingEndSessionMessage(OutgoingTextMessage(recipient, "TERMINATE", 0, -1))
|
||||
MessageSender.send(context, endSessionMessage, threadID, false, null)
|
||||
}
|
||||
val smsDB = DatabaseFactory.getSmsDatabase(context)
|
||||
val infoMessage = OutgoingTextMessage(recipient, "", 0, 0)
|
||||
val infoMessageID = smsDB.insertMessageOutbox(threadID, infoMessage, false, System.currentTimeMillis(), null)
|
||||
if (infoMessageID > -1) {
|
||||
smsDB.markAsSentLokiSessionRestorationRequest(infoMessageID)
|
||||
}
|
||||
lokiThreadDB.removeAllSessionRestoreDevices(threadID)
|
||||
}
|
||||
|
||||
// @JvmStatic
|
||||
// fun refreshSignedPreKey(context: Context) {
|
||||
// if (TextSecurePreferences.isSignedPreKeyRegistered(context)) {
|
||||
// Log.d("Loki", "Skipping signed pre key refresh; using existing signed pre key.")
|
||||
// } else {
|
||||
// Log.d("Loki", "Signed pre key refreshed successfully.")
|
||||
// val identityKeyPair = IdentityKeyUtil.getIdentityKeyPair(context)
|
||||
// PreKeyUtil.generateSignedPreKey(context, identityKeyPair, true)
|
||||
// TextSecurePreferences.setSignedPreKeyRegistered(context, true)
|
||||
// ApplicationContext.getInstance(context).jobManager.add(CleanPreKeysJob())
|
||||
// }
|
||||
// }
|
||||
|
||||
@JvmStatic
|
||||
fun shouldProcessSessionRequest(context: Context, publicKey: String, timestamp: Long): Boolean {
|
||||
val apiDB = DatabaseFactory.getLokiAPIDatabase(context)
|
||||
val sentTimestamp = apiDB.getSessionRequestSentTimestamp(publicKey) ?: 0
|
||||
val processedTimestamp = apiDB.getSessionRequestProcessedTimestamp(publicKey) ?: 0
|
||||
val restorationTimestamp = TextSecurePreferences.getRestorationTime(context)
|
||||
return timestamp > sentTimestamp && timestamp > processedTimestamp && timestamp > restorationTimestamp
|
||||
}
|
||||
|
||||
@JvmStatic
|
||||
fun handlePreKeyBundleMessageIfNeeded(context: Context, content: SignalServiceContent) {
|
||||
val preKeyBundleMessage = content.preKeyBundleMessage.orNull() ?: return
|
||||
val publicKey = content.sender
|
||||
if (recipient(context, publicKey).isGroupRecipient) { return } // Should never occur
|
||||
Log.d("Loki", "Received a pre key bundle from: $publicKey.")
|
||||
if (!shouldProcessSessionRequest(context, publicKey, content.timestamp)) {
|
||||
Log.d("Loki", "Ignoring session request from: $publicKey.")
|
||||
return
|
||||
}
|
||||
val registrationID = TextSecurePreferences.getLocalRegistrationId(context)
|
||||
// val lokiPreKeyBundleDatabase = DatabaseFactory.getLokiPreKeyBundleDatabase(context)
|
||||
val preKeyBundle = preKeyBundleMessage.getPreKeyBundle(registrationID)
|
||||
// lokiPreKeyBundleDatabase.setPreKeyBundle(publicKey, preKeyBundle)
|
||||
DatabaseFactory.getLokiAPIDatabase(context).setSessionRequestProcessedTimestamp(publicKey, Date().time)
|
||||
val job = NullMessageSendJob(publicKey)
|
||||
ApplicationContext.getInstance(context).jobManager.add(job)
|
||||
}
|
||||
|
||||
@JvmStatic
|
||||
fun handleEndSessionMessageIfNeeded(context: Context, content: SignalServiceContent) {
|
||||
if (!content.dataMessage.isPresent || !content.dataMessage.get().isEndSession) { return }
|
||||
val sessionStore = TextSecureSessionStore(context)
|
||||
val lokiThreadDB = DatabaseFactory.getLokiThreadDatabase(context)
|
||||
Log.d("Loki", "Received a session reset request from: ${content.sender}; archiving the session.")
|
||||
sessionStore.archiveAllSessions(content.sender)
|
||||
lokiThreadDB.setSessionResetStatus(content.sender, SessionResetStatus.REQUEST_RECEIVED)
|
||||
Log.d("Loki", "Sending an ephemeral message back to: ${content.sender}.")
|
||||
val job = NullMessageSendJob(content.sender)
|
||||
ApplicationContext.getInstance(context).jobManager.add(job)
|
||||
SecurityEvent.broadcastSecurityUpdateEvent(context)
|
||||
}
|
||||
|
||||
@JvmStatic
|
||||
fun triggerSessionRestorationUI(context: Context, publicKey: String, errorTimestamp: Long) {
|
||||
val recipient = recipient(context, publicKey)
|
||||
if (recipient.isGroupRecipient) { return }
|
||||
val threadID = DatabaseFactory.getThreadDatabase(context).getOrCreateThreadIdFor(recipient)
|
||||
DatabaseFactory.getLokiThreadDatabase(context).addSessionRestoreDevice(threadID, publicKey)
|
||||
}
|
||||
}
|
@ -1,43 +0,0 @@
|
||||
package org.thoughtcrime.securesms.loki.protocol
|
||||
|
||||
import android.content.Context
|
||||
import org.thoughtcrime.securesms.ApplicationContext
|
||||
import org.session.libsession.messaging.threads.Address
|
||||
import org.thoughtcrime.securesms.database.DatabaseFactory
|
||||
import org.session.libsession.messaging.threads.recipients.Recipient
|
||||
import org.thoughtcrime.securesms.sms.OutgoingTextMessage
|
||||
import org.session.libsignal.libsignal.loki.SessionResetProtocol
|
||||
import org.session.libsignal.libsignal.loki.SessionResetStatus
|
||||
import org.session.libsignal.libsignal.protocol.PreKeySignalMessage
|
||||
|
||||
class SessionResetImplementation(private val context: Context) : SessionResetProtocol {
|
||||
|
||||
override fun getSessionResetStatus(publicKey: String): SessionResetStatus {
|
||||
return DatabaseFactory.getLokiThreadDatabase(context).getSessionResetStatus(publicKey)
|
||||
}
|
||||
|
||||
override fun setSessionResetStatus(publicKey: String, sessionResetStatus: SessionResetStatus) {
|
||||
return DatabaseFactory.getLokiThreadDatabase(context).setSessionResetStatus(publicKey, sessionResetStatus)
|
||||
}
|
||||
|
||||
override fun onNewSessionAdopted(publicKey: String, oldSessionResetStatus: SessionResetStatus) {
|
||||
if (oldSessionResetStatus == SessionResetStatus.IN_PROGRESS) {
|
||||
val job = NullMessageSendJob(publicKey)
|
||||
ApplicationContext.getInstance(context).jobManager.add(job)
|
||||
}
|
||||
val smsDB = DatabaseFactory.getSmsDatabase(context)
|
||||
val recipient = Recipient.from(context, Address.fromSerialized(publicKey), false)
|
||||
val threadID = DatabaseFactory.getThreadDatabase(context).getOrCreateThreadIdFor(recipient)
|
||||
val infoMessage = OutgoingTextMessage(recipient, "", 0, 0)
|
||||
val infoMessageID = smsDB.insertMessageOutbox(threadID, infoMessage, false, System.currentTimeMillis(), null)
|
||||
if (infoMessageID > -1) {
|
||||
smsDB.markAsLokiSessionRestorationDone(infoMessageID)
|
||||
}
|
||||
}
|
||||
|
||||
override fun validatePreKeySignalMessage(publicKey: String, message: PreKeySignalMessage) {
|
||||
// val preKeyRecord = DatabaseFactory.getLokiPreKeyRecordDatabase(context).getPreKeyRecord(publicKey) ?: return
|
||||
// // TODO: Checking that the pre key record isn't null is causing issues when it shouldn't
|
||||
// check(preKeyRecord.id == (message.preKeyId ?: -1)) { "Received a background message from an unknown source." }
|
||||
}
|
||||
}
|
@ -4,7 +4,7 @@ import android.content.Context
|
||||
import org.thoughtcrime.securesms.database.DatabaseFactory
|
||||
import org.thoughtcrime.securesms.database.model.MessageRecord
|
||||
import org.session.libsession.utilities.TextSecurePreferences
|
||||
import org.session.libsignal.service.loki.protocol.mentions.MentionsManager
|
||||
import org.session.libsignal.service.loki.utilities.mentions.MentionsManager
|
||||
|
||||
object MentionManagerUtilities {
|
||||
|
||||
|
@ -15,8 +15,6 @@ import org.thoughtcrime.securesms.loki.utilities.MentionManagerUtilities.populat
|
||||
import org.thoughtcrime.securesms.loki.utilities.MentionUtilities.highlightMentions
|
||||
import org.thoughtcrime.securesms.mms.GlideRequests
|
||||
import org.thoughtcrime.securesms.util.DateUtils
|
||||
import org.session.libsession.utilities.TextSecurePreferences
|
||||
import org.session.libsignal.service.loki.protocol.mentions.MentionsManager
|
||||
import java.util.*
|
||||
|
||||
class ConversationView : LinearLayout {
|
||||
|
@ -10,7 +10,7 @@ import android.widget.ListView
|
||||
import org.thoughtcrime.securesms.database.DatabaseFactory
|
||||
import org.thoughtcrime.securesms.loki.utilities.toPx
|
||||
import org.thoughtcrime.securesms.mms.GlideRequests
|
||||
import org.session.libsignal.service.loki.protocol.mentions.Mention
|
||||
import org.session.libsignal.service.loki.utilities.mentions.Mention
|
||||
|
||||
class MentionCandidateSelectionView(context: Context, attrs: AttributeSet?, defStyleAttr: Int) : ListView(context, attrs, defStyleAttr) {
|
||||
private var mentionCandidates = listOf<Mention>()
|
||||
|
@ -10,7 +10,7 @@ import kotlinx.android.synthetic.main.view_mention_candidate.view.*
|
||||
import network.loki.messenger.R
|
||||
import org.thoughtcrime.securesms.mms.GlideRequests
|
||||
import org.session.libsignal.service.loki.api.opengroups.PublicChatAPI
|
||||
import org.session.libsignal.service.loki.protocol.mentions.Mention
|
||||
import org.session.libsignal.service.loki.utilities.mentions.Mention
|
||||
|
||||
class MentionCandidateView(context: Context, attrs: AttributeSet?, defStyleAttr: Int) : LinearLayout(context, attrs, defStyleAttr) {
|
||||
var mentionCandidate = Mention("", "")
|
||||
|
@ -17,7 +17,7 @@ import org.thoughtcrime.securesms.loki.utilities.AvatarPlaceholderGenerator
|
||||
import org.thoughtcrime.securesms.mms.GlideRequests
|
||||
import org.session.libsession.messaging.threads.recipients.Recipient
|
||||
import org.session.libsession.utilities.TextSecurePreferences
|
||||
import org.session.libsignal.service.loki.protocol.mentions.MentionsManager
|
||||
import org.session.libsignal.service.loki.utilities.mentions.MentionsManager
|
||||
|
||||
// TODO: Look into a better way of handling different sizes. Maybe an enum (with associated values) encapsulating the different modes?
|
||||
|
||||
|
@ -83,7 +83,6 @@ public class ExpiringMessageManager implements SSKEnvironment.MessageExpirationM
|
||||
Optional.absent(),
|
||||
Optional.absent(),
|
||||
Optional.absent(),
|
||||
Optional.absent(),
|
||||
Optional.absent());
|
||||
|
||||
database.insertSecureDecryptedMessageInbox(mediaMessage, -1);
|
||||
|
@ -278,6 +278,12 @@ message GroupContext {
|
||||
repeated string members = 4;
|
||||
optional AttachmentPointer avatar = 5;
|
||||
repeated string admins = 6;
|
||||
|
||||
// Loki - These fields are only used internally for the Android code base.
|
||||
// This is so that we can differentiate adding/kicking.
|
||||
// DO NOT USE WHEN SENDING MESSAGES.
|
||||
repeated string newMembers = 998;
|
||||
repeated string removedMembers = 999;
|
||||
}
|
||||
|
||||
message ContactDetails {
|
||||
|
@ -1,78 +0,0 @@
|
||||
package org.session.libsignal.libsignal.loki
|
||||
|
||||
import org.session.libsignal.libsignal.DecryptionCallback
|
||||
import org.session.libsignal.libsignal.SessionCipher
|
||||
import org.session.libsignal.libsignal.SignalProtocolAddress
|
||||
import org.session.libsignal.libsignal.protocol.PreKeySignalMessage
|
||||
import org.session.libsignal.libsignal.protocol.SignalMessage
|
||||
import org.session.libsignal.libsignal.state.SessionState
|
||||
import org.session.libsignal.libsignal.state.SignalProtocolStore
|
||||
|
||||
/**
|
||||
* A wrapper class for `SessionCipher`.
|
||||
* This applies session reset logic on decryption.
|
||||
*/
|
||||
class LokiSessionCipher(private val protocolStore: SignalProtocolStore, private var sessionResetProtocol: SessionResetProtocol, val address: SignalProtocolAddress) : SessionCipher(protocolStore, address) {
|
||||
|
||||
override fun decrypt(ciphertext: PreKeySignalMessage?, callback: DecryptionCallback?): ByteArray {
|
||||
// Record the current session state as it may change during decryption
|
||||
val activeSession = getCurrentSessionState()
|
||||
if (activeSession == null && ciphertext != null) {
|
||||
sessionResetProtocol.validatePreKeySignalMessage(address.name, ciphertext)
|
||||
}
|
||||
val plainText = super.decrypt(ciphertext, callback)
|
||||
handleSessionResetRequestIfNeeded(activeSession)
|
||||
return plainText
|
||||
}
|
||||
|
||||
override fun decrypt(ciphertext: SignalMessage?, callback: DecryptionCallback?): ByteArray {
|
||||
// Record the current session state as it may change during decryption
|
||||
val activeSession = getCurrentSessionState()
|
||||
val plainText = super.decrypt(ciphertext, callback)
|
||||
handleSessionResetRequestIfNeeded(activeSession)
|
||||
return plainText
|
||||
}
|
||||
|
||||
private fun getCurrentSessionState(): SessionState? {
|
||||
val sessionRecord = protocolStore.loadSession(address)
|
||||
return sessionRecord.sessionState
|
||||
}
|
||||
|
||||
private fun handleSessionResetRequestIfNeeded(oldSession: SessionState?) {
|
||||
if (oldSession == null) { return }
|
||||
val publicKey = address.name
|
||||
val currentSessionResetStatus = sessionResetProtocol.getSessionResetStatus(publicKey)
|
||||
if (currentSessionResetStatus == SessionResetStatus.NONE) return
|
||||
val currentSession = getCurrentSessionState()
|
||||
if (currentSession == null || currentSession.aliceBaseKey?.contentEquals(oldSession.aliceBaseKey) != true) {
|
||||
if (currentSessionResetStatus == SessionResetStatus.REQUEST_RECEIVED) {
|
||||
// The other user used an old session to contact us; wait for them to switch to a new one.
|
||||
restoreSession(oldSession)
|
||||
} else {
|
||||
// Our session reset was successful; we initiated one and got a new session back from the other user.
|
||||
deleteAllSessionsExcept(currentSession)
|
||||
sessionResetProtocol.setSessionResetStatus(publicKey, SessionResetStatus.NONE)
|
||||
sessionResetProtocol.onNewSessionAdopted(publicKey, currentSessionResetStatus)
|
||||
}
|
||||
} else if (currentSessionResetStatus == SessionResetStatus.REQUEST_RECEIVED) {
|
||||
// Our session reset was successful; we received a message with the same session from the other user.
|
||||
deleteAllSessionsExcept(oldSession)
|
||||
sessionResetProtocol.setSessionResetStatus(publicKey, SessionResetStatus.NONE)
|
||||
sessionResetProtocol.onNewSessionAdopted(publicKey, currentSessionResetStatus)
|
||||
}
|
||||
}
|
||||
|
||||
private fun restoreSession(state: SessionState) {
|
||||
val session = protocolStore.loadSession(address)
|
||||
session.previousSessionStates.removeAll { it.aliceBaseKey?.contentEquals(state.aliceBaseKey) ?: false }
|
||||
session.promoteState(state)
|
||||
protocolStore.storeSession(address, session)
|
||||
}
|
||||
|
||||
private fun deleteAllSessionsExcept(state: SessionState?) {
|
||||
val sessionRecord = protocolStore.loadSession(address)
|
||||
sessionRecord.removePreviousSessionStates()
|
||||
sessionRecord.setState(state ?: SessionState())
|
||||
protocolStore.storeSession(address, sessionRecord)
|
||||
}
|
||||
}
|
@ -1,11 +0,0 @@
|
||||
package org.session.libsignal.libsignal.loki
|
||||
|
||||
import org.session.libsignal.libsignal.protocol.PreKeySignalMessage
|
||||
|
||||
interface SessionResetProtocol {
|
||||
|
||||
fun getSessionResetStatus(publicKey: String): SessionResetStatus
|
||||
fun setSessionResetStatus(publicKey: String, sessionResetStatus: SessionResetStatus)
|
||||
fun validatePreKeySignalMessage(publicKey: String, message: PreKeySignalMessage)
|
||||
fun onNewSessionAdopted(publicKey: String, oldSessionResetStatus: SessionResetStatus)
|
||||
}
|
@ -1,7 +0,0 @@
|
||||
package org.session.libsignal.libsignal.loki
|
||||
|
||||
enum class SessionResetStatus(val rawValue: Int) {
|
||||
NONE(0),
|
||||
IN_PROGRESS(1),
|
||||
REQUEST_RECEIVED(2)
|
||||
}
|
@ -24,8 +24,6 @@ import org.session.libsignal.libsignal.ecc.ECPrivateKey;
|
||||
import org.session.libsignal.libsignal.ecc.ECPublicKey;
|
||||
import org.session.libsignal.libsignal.kdf.HKDFv3;
|
||||
import org.session.libsignal.libsignal.loki.FallbackSessionCipher;
|
||||
import org.session.libsignal.libsignal.loki.LokiSessionCipher;
|
||||
import org.session.libsignal.libsignal.loki.SessionResetProtocol;
|
||||
import org.session.libsignal.libsignal.protocol.CiphertextMessage;
|
||||
import org.session.libsignal.libsignal.protocol.PreKeySignalMessage;
|
||||
import org.session.libsignal.libsignal.protocol.SignalMessage;
|
||||
@ -51,15 +49,11 @@ import javax.crypto.spec.SecretKeySpec;
|
||||
public class SealedSessionCipher {
|
||||
|
||||
private final SignalProtocolStore signalProtocolStore;
|
||||
private final SessionResetProtocol sessionResetProtocol;
|
||||
private final SignalProtocolAddress localAddress;
|
||||
|
||||
public SealedSessionCipher(SignalProtocolStore signalProtocolStore,
|
||||
SessionResetProtocol sessionResetProtocol,
|
||||
SignalProtocolAddress localAddress)
|
||||
public SealedSessionCipher(SignalProtocolStore signalProtocolStore, SignalProtocolAddress localAddress)
|
||||
{
|
||||
this.signalProtocolStore = signalProtocolStore;
|
||||
this.sessionResetProtocol = sessionResetProtocol;
|
||||
this.localAddress = localAddress;
|
||||
}
|
||||
|
||||
@ -201,8 +195,8 @@ public class SealedSessionCipher {
|
||||
SignalProtocolAddress sender = new SignalProtocolAddress(message.getSenderCertificate().getSender(), message.getSenderCertificate().getSenderDeviceId());
|
||||
|
||||
switch (message.getType()) {
|
||||
case CiphertextMessage.WHISPER_TYPE: return new LokiSessionCipher(signalProtocolStore, sessionResetProtocol, sender).decrypt(new SignalMessage(message.getContent()));
|
||||
case CiphertextMessage.PREKEY_TYPE: return new LokiSessionCipher(signalProtocolStore, sessionResetProtocol, sender).decrypt(new PreKeySignalMessage(message.getContent()));
|
||||
case CiphertextMessage.WHISPER_TYPE: return new SessionCipher(signalProtocolStore, sender).decrypt(new SignalMessage(message.getContent()));
|
||||
case CiphertextMessage.PREKEY_TYPE: return new SessionCipher(signalProtocolStore, sender).decrypt(new PreKeySignalMessage(message.getContent()));
|
||||
case CiphertextMessage.FALLBACK_MESSAGE_TYPE: {
|
||||
try {
|
||||
byte[] privateKey = signalProtocolStore.getIdentityKeyPair().getPrivateKey().serialize();
|
||||
|
@ -6,12 +6,10 @@
|
||||
package org.session.libsignal.service.api;
|
||||
|
||||
import com.google.protobuf.ByteString;
|
||||
import com.google.protobuf.InvalidProtocolBufferException;
|
||||
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.session.libsignal.libsignal.ecc.ECKeyPair;
|
||||
import org.session.libsignal.utilities.logging.Log;
|
||||
import org.session.libsignal.libsignal.loki.SessionResetProtocol;
|
||||
import org.session.libsignal.libsignal.state.SignalProtocolStore;
|
||||
import org.session.libsignal.libsignal.util.guava.Optional;
|
||||
import org.session.libsignal.service.api.crypto.AttachmentCipherOutputStream;
|
||||
@ -67,24 +65,20 @@ import org.session.libsignal.service.loki.database.LokiOpenGroupDatabaseProtocol
|
||||
import org.session.libsignal.service.loki.database.LokiPreKeyBundleDatabaseProtocol;
|
||||
import org.session.libsignal.service.loki.database.LokiThreadDatabaseProtocol;
|
||||
import org.session.libsignal.service.loki.database.LokiUserDatabaseProtocol;
|
||||
import org.session.libsignal.service.loki.protocol.meta.TTLUtilities;
|
||||
import org.session.libsignal.service.loki.protocol.sessionmanagement.SessionManagementProtocol;
|
||||
import org.session.libsignal.service.loki.utilities.TTLUtilities;
|
||||
import org.session.libsignal.service.loki.utilities.Broadcaster;
|
||||
import org.session.libsignal.service.loki.utilities.HexEncodingKt;
|
||||
import org.session.libsignal.service.loki.utilities.PlaintextOutputStreamFactory;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.security.SecureRandom;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.Iterator;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.concurrent.atomic.AtomicBoolean;
|
||||
import java.util.concurrent.atomic.AtomicReference;
|
||||
|
||||
import kotlin.Unit;
|
||||
@ -100,10 +94,8 @@ public class SignalServiceMessageSender {
|
||||
|
||||
private static final String TAG = SignalServiceMessageSender.class.getSimpleName();
|
||||
|
||||
private final PushServiceSocket socket;
|
||||
private final SignalProtocolStore store;
|
||||
private final SignalServiceAddress localAddress;
|
||||
private final Optional<EventListener> eventListener;
|
||||
|
||||
private final AtomicReference<Optional<SignalServiceMessagePipe>> pipe;
|
||||
private final AtomicReference<Optional<SignalServiceMessagePipe>> unidentifiedPipe;
|
||||
@ -113,9 +105,7 @@ public class SignalServiceMessageSender {
|
||||
private final LokiAPIDatabaseProtocol apiDatabase;
|
||||
private final LokiThreadDatabaseProtocol threadDatabase;
|
||||
private final LokiMessageDatabaseProtocol messageDatabase;
|
||||
private final LokiPreKeyBundleDatabaseProtocol preKeyBundleDatabase;
|
||||
private final SessionProtocol sessionProtocolImpl;
|
||||
private final SessionResetProtocol sessionResetImpl;
|
||||
private final LokiUserDatabaseProtocol userDatabase;
|
||||
private final LokiOpenGroupDatabaseProtocol openGroupDatabase;
|
||||
private final Broadcaster broadcaster;
|
||||
@ -123,65 +113,48 @@ public class SignalServiceMessageSender {
|
||||
/**
|
||||
* Construct a SignalServiceMessageSender.
|
||||
*
|
||||
* @param urls The URL of the Signal Service.
|
||||
* @param user The Signal Service username (eg phone number).
|
||||
* @param password The Signal Service user password.
|
||||
* @param store The SignalProtocolStore.
|
||||
* @param eventListener An optional event listener, which fires whenever sessions are
|
||||
* setup or torn down for a recipient.
|
||||
*/
|
||||
public SignalServiceMessageSender(SignalServiceConfiguration urls,
|
||||
String user, String password,
|
||||
public SignalServiceMessageSender(String user, String password,
|
||||
SignalProtocolStore store,
|
||||
String userAgent,
|
||||
Optional<SignalServiceMessagePipe> pipe,
|
||||
Optional<SignalServiceMessagePipe> unidentifiedPipe,
|
||||
Optional<EventListener> eventListener,
|
||||
String userPublicKey,
|
||||
LokiAPIDatabaseProtocol apiDatabase,
|
||||
LokiThreadDatabaseProtocol threadDatabase,
|
||||
LokiMessageDatabaseProtocol messageDatabase,
|
||||
LokiPreKeyBundleDatabaseProtocol preKeyBundleDatabase,
|
||||
SessionProtocol sessionProtocolImpl,
|
||||
SessionResetProtocol sessionResetImpl,
|
||||
LokiUserDatabaseProtocol userDatabase,
|
||||
LokiOpenGroupDatabaseProtocol openGroupDatabase,
|
||||
Broadcaster broadcaster)
|
||||
{
|
||||
this(urls, new StaticCredentialsProvider(user, password, null), store, userAgent, pipe, unidentifiedPipe, eventListener, userPublicKey, apiDatabase, threadDatabase, messageDatabase, preKeyBundleDatabase, sessionProtocolImpl, sessionResetImpl, userDatabase, openGroupDatabase, broadcaster);
|
||||
this(new StaticCredentialsProvider(user, password, null), store, pipe, unidentifiedPipe, userPublicKey, apiDatabase, threadDatabase, messageDatabase, sessionProtocolImpl, userDatabase, openGroupDatabase, broadcaster);
|
||||
}
|
||||
|
||||
public SignalServiceMessageSender(SignalServiceConfiguration urls,
|
||||
CredentialsProvider credentialsProvider,
|
||||
public SignalServiceMessageSender(CredentialsProvider credentialsProvider,
|
||||
SignalProtocolStore store,
|
||||
String userAgent,
|
||||
Optional<SignalServiceMessagePipe> pipe,
|
||||
Optional<SignalServiceMessagePipe> unidentifiedPipe,
|
||||
Optional<EventListener> eventListener,
|
||||
String userPublicKey,
|
||||
LokiAPIDatabaseProtocol apiDatabase,
|
||||
LokiThreadDatabaseProtocol threadDatabase,
|
||||
LokiMessageDatabaseProtocol messageDatabase,
|
||||
LokiPreKeyBundleDatabaseProtocol preKeyBundleDatabase,
|
||||
SessionProtocol sessionProtocolImpl,
|
||||
SessionResetProtocol sessionResetImpl,
|
||||
LokiUserDatabaseProtocol userDatabase,
|
||||
LokiOpenGroupDatabaseProtocol openGroupDatabase,
|
||||
Broadcaster broadcaster)
|
||||
{
|
||||
this.socket = new PushServiceSocket(urls, credentialsProvider, userAgent);
|
||||
this.store = store;
|
||||
this.localAddress = new SignalServiceAddress(credentialsProvider.getUser());
|
||||
this.pipe = new AtomicReference<>(pipe);
|
||||
this.unidentifiedPipe = new AtomicReference<>(unidentifiedPipe);
|
||||
this.eventListener = eventListener;
|
||||
this.userPublicKey = userPublicKey;
|
||||
this.apiDatabase = apiDatabase;
|
||||
this.threadDatabase = threadDatabase;
|
||||
this.messageDatabase = messageDatabase;
|
||||
this.preKeyBundleDatabase = preKeyBundleDatabase;
|
||||
this.sessionProtocolImpl = sessionProtocolImpl;
|
||||
this.sessionResetImpl = sessionResetImpl;
|
||||
this.userDatabase = userDatabase;
|
||||
this.openGroupDatabase = openGroupDatabase;
|
||||
this.broadcaster = broadcaster;
|
||||
|
@ -10,31 +10,11 @@ import com.google.protobuf.InvalidProtocolBufferException;
|
||||
|
||||
import org.session.libsignal.libsignal.ecc.ECKeyPair;
|
||||
import org.session.libsignal.metadata.InvalidMetadataMessageException;
|
||||
import org.session.libsignal.metadata.InvalidMetadataVersionException;
|
||||
import org.session.libsignal.metadata.ProtocolDuplicateMessageException;
|
||||
import org.session.libsignal.metadata.ProtocolInvalidKeyException;
|
||||
import org.session.libsignal.metadata.ProtocolInvalidKeyIdException;
|
||||
import org.session.libsignal.metadata.ProtocolInvalidMessageException;
|
||||
import org.session.libsignal.metadata.ProtocolInvalidVersionException;
|
||||
import org.session.libsignal.metadata.ProtocolLegacyMessageException;
|
||||
import org.session.libsignal.metadata.ProtocolNoSessionException;
|
||||
import org.session.libsignal.metadata.ProtocolUntrustedIdentityException;
|
||||
import org.session.libsignal.metadata.SealedSessionCipher;
|
||||
import org.session.libsignal.metadata.SelfSendException;
|
||||
import org.session.libsignal.libsignal.DuplicateMessageException;
|
||||
import org.session.libsignal.libsignal.InvalidKeyException;
|
||||
import org.session.libsignal.libsignal.InvalidKeyIdException;
|
||||
import org.session.libsignal.libsignal.InvalidMessageException;
|
||||
import org.session.libsignal.libsignal.InvalidVersionException;
|
||||
import org.session.libsignal.libsignal.LegacyMessageException;
|
||||
import org.session.libsignal.libsignal.NoSessionException;
|
||||
import org.session.libsignal.libsignal.SessionCipher;
|
||||
import org.session.libsignal.libsignal.SignalProtocolAddress;
|
||||
import org.session.libsignal.libsignal.UntrustedIdentityException;
|
||||
import org.session.libsignal.libsignal.loki.LokiSessionCipher;
|
||||
import org.session.libsignal.libsignal.loki.SessionResetProtocol;
|
||||
import org.session.libsignal.libsignal.protocol.PreKeySignalMessage;
|
||||
import org.session.libsignal.libsignal.protocol.SignalMessage;
|
||||
import org.session.libsignal.libsignal.state.SignalProtocolStore;
|
||||
import org.session.libsignal.libsignal.util.guava.Optional;
|
||||
import org.session.libsignal.service.api.messages.SignalServiceAttachment;
|
||||
@ -60,7 +40,6 @@ import org.session.libsignal.service.loki.api.crypto.SessionProtocol;
|
||||
import org.session.libsignal.service.loki.api.crypto.SessionProtocolUtilities;
|
||||
import org.session.libsignal.service.loki.database.LokiAPIDatabaseProtocol;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
|
||||
@ -77,19 +56,16 @@ public class SignalServiceCipher {
|
||||
private static final String TAG = SignalServiceCipher.class.getSimpleName();
|
||||
|
||||
private final SignalProtocolStore signalProtocolStore;
|
||||
private final SessionResetProtocol sessionResetProtocol;
|
||||
private final SignalServiceAddress localAddress;
|
||||
private final SessionProtocol sessionProtocolImpl;
|
||||
private final LokiAPIDatabaseProtocol apiDB;
|
||||
|
||||
public SignalServiceCipher(SignalServiceAddress localAddress,
|
||||
SignalProtocolStore signalProtocolStore,
|
||||
SessionResetProtocol sessionResetProtocol,
|
||||
SessionProtocol sessionProtocolImpl,
|
||||
LokiAPIDatabaseProtocol apiDB)
|
||||
{
|
||||
this.signalProtocolStore = signalProtocolStore;
|
||||
this.sessionResetProtocol = sessionResetProtocol;
|
||||
this.localAddress = localAddress;
|
||||
this.sessionProtocolImpl = sessionProtocolImpl;
|
||||
this.apiDB = apiDB;
|
||||
@ -160,8 +136,8 @@ public class SignalServiceCipher {
|
||||
protected Plaintext decrypt(SignalServiceEnvelope envelope, byte[] ciphertext) throws InvalidMetadataMessageException
|
||||
{
|
||||
SignalProtocolAddress sourceAddress = new SignalProtocolAddress(envelope.getSource(), envelope.getSourceDevice());
|
||||
SessionCipher sessionCipher = new LokiSessionCipher(signalProtocolStore, sessionResetProtocol, sourceAddress);
|
||||
SealedSessionCipher sealedSessionCipher = new SealedSessionCipher(signalProtocolStore, sessionResetProtocol, new SignalProtocolAddress(localAddress.getNumber(), 1));
|
||||
SessionCipher sessionCipher = new SessionCipher(signalProtocolStore, sourceAddress);
|
||||
SealedSessionCipher sealedSessionCipher = new SealedSessionCipher(signalProtocolStore, new SignalProtocolAddress(localAddress.getNumber(), 1));
|
||||
|
||||
byte[] paddedMessage;
|
||||
Metadata metadata;
|
||||
|
@ -7,9 +7,7 @@
|
||||
package org.session.libsignal.service.api.messages;
|
||||
|
||||
import org.session.libsignal.libsignal.util.guava.Optional;
|
||||
import org.session.libsignal.service.api.messages.calls.SignalServiceCallMessage;
|
||||
import org.session.libsignal.service.internal.push.SignalServiceProtos;
|
||||
import org.session.libsignal.service.loki.protocol.sessionmanagement.PreKeyBundleMessage;
|
||||
|
||||
public class SignalServiceContent {
|
||||
private final String sender;
|
||||
@ -24,7 +22,6 @@ public class SignalServiceContent {
|
||||
|
||||
// Loki
|
||||
public Optional<SignalServiceProtos.Content> configurationMessageProto = Optional.absent();
|
||||
public Optional<PreKeyBundleMessage> preKeyBundleMessage = Optional.absent();
|
||||
public Optional<String> senderDisplayName = Optional.absent();
|
||||
public Optional<String> senderProfilePictureURL = Optional.absent();
|
||||
|
||||
|
@ -11,7 +11,7 @@ import org.session.libsignal.libsignal.util.guava.Optional;
|
||||
import org.session.libsignal.service.api.messages.shared.SharedContact;
|
||||
import org.session.libsignal.service.api.push.SignalServiceAddress;
|
||||
import org.session.libsignal.service.internal.push.SignalServiceProtos.DataMessage.ClosedGroupControlMessage;
|
||||
import org.session.libsignal.service.loki.protocol.meta.TTLUtilities;
|
||||
import org.session.libsignal.service.loki.utilities.TTLUtilities;
|
||||
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
|
@ -1,6 +1,6 @@
|
||||
package org.session.libsignal.service.api.messages;
|
||||
|
||||
import org.session.libsignal.service.loki.protocol.meta.TTLUtilities;
|
||||
import org.session.libsignal.service.loki.utilities.TTLUtilities;
|
||||
|
||||
public class SignalServiceNullMessage {
|
||||
|
||||
|
@ -1,7 +1,7 @@
|
||||
package org.session.libsignal.service.api.messages;
|
||||
|
||||
|
||||
import org.session.libsignal.service.loki.protocol.meta.TTLUtilities;
|
||||
import org.session.libsignal.service.loki.utilities.TTLUtilities;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
|
@ -1,7 +1,6 @@
|
||||
package org.session.libsignal.service.api.messages;
|
||||
|
||||
import org.session.libsignal.libsignal.util.guava.Optional;
|
||||
import org.session.libsignal.service.loki.protocol.meta.TTLUtilities;
|
||||
import org.session.libsignal.service.loki.utilities.TTLUtilities;
|
||||
|
||||
public class SignalServiceTypingMessage {
|
||||
|
||||
|
@ -1,7 +1,7 @@
|
||||
package org.session.libsignal.service.api.messages.calls;
|
||||
|
||||
import org.session.libsignal.libsignal.util.guava.Optional;
|
||||
import org.session.libsignal.service.loki.protocol.meta.TTLUtilities;
|
||||
import org.session.libsignal.service.loki.utilities.TTLUtilities;
|
||||
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
|
@ -24483,6 +24483,70 @@ public final class SignalServiceProtos {
|
||||
*/
|
||||
com.google.protobuf.ByteString
|
||||
getAdminsBytes(int index);
|
||||
|
||||
// repeated string newMembers = 998;
|
||||
/**
|
||||
* <code>repeated string newMembers = 998;</code>
|
||||
*
|
||||
* <pre>
|
||||
* Loki - These fields are only used internally for the Android code base.
|
||||
* This is so that we can differentiate adding/kicking.
|
||||
* DO NOT USE WHEN SENDING MESSAGES.
|
||||
* </pre>
|
||||
*/
|
||||
java.util.List<java.lang.String>
|
||||
getNewMembersList();
|
||||
/**
|
||||
* <code>repeated string newMembers = 998;</code>
|
||||
*
|
||||
* <pre>
|
||||
* Loki - These fields are only used internally for the Android code base.
|
||||
* This is so that we can differentiate adding/kicking.
|
||||
* DO NOT USE WHEN SENDING MESSAGES.
|
||||
* </pre>
|
||||
*/
|
||||
int getNewMembersCount();
|
||||
/**
|
||||
* <code>repeated string newMembers = 998;</code>
|
||||
*
|
||||
* <pre>
|
||||
* Loki - These fields are only used internally for the Android code base.
|
||||
* This is so that we can differentiate adding/kicking.
|
||||
* DO NOT USE WHEN SENDING MESSAGES.
|
||||
* </pre>
|
||||
*/
|
||||
java.lang.String getNewMembers(int index);
|
||||
/**
|
||||
* <code>repeated string newMembers = 998;</code>
|
||||
*
|
||||
* <pre>
|
||||
* Loki - These fields are only used internally for the Android code base.
|
||||
* This is so that we can differentiate adding/kicking.
|
||||
* DO NOT USE WHEN SENDING MESSAGES.
|
||||
* </pre>
|
||||
*/
|
||||
com.google.protobuf.ByteString
|
||||
getNewMembersBytes(int index);
|
||||
|
||||
// repeated string removedMembers = 999;
|
||||
/**
|
||||
* <code>repeated string removedMembers = 999;</code>
|
||||
*/
|
||||
java.util.List<java.lang.String>
|
||||
getRemovedMembersList();
|
||||
/**
|
||||
* <code>repeated string removedMembers = 999;</code>
|
||||
*/
|
||||
int getRemovedMembersCount();
|
||||
/**
|
||||
* <code>repeated string removedMembers = 999;</code>
|
||||
*/
|
||||
java.lang.String getRemovedMembers(int index);
|
||||
/**
|
||||
* <code>repeated string removedMembers = 999;</code>
|
||||
*/
|
||||
com.google.protobuf.ByteString
|
||||
getRemovedMembersBytes(int index);
|
||||
}
|
||||
/**
|
||||
* Protobuf type {@code signalservice.GroupContext}
|
||||
@ -24585,6 +24649,22 @@ public final class SignalServiceProtos {
|
||||
admins_.add(input.readBytes());
|
||||
break;
|
||||
}
|
||||
case 7986: {
|
||||
if (!((mutable_bitField0_ & 0x00000040) == 0x00000040)) {
|
||||
newMembers_ = new com.google.protobuf.LazyStringArrayList();
|
||||
mutable_bitField0_ |= 0x00000040;
|
||||
}
|
||||
newMembers_.add(input.readBytes());
|
||||
break;
|
||||
}
|
||||
case 7994: {
|
||||
if (!((mutable_bitField0_ & 0x00000080) == 0x00000080)) {
|
||||
removedMembers_ = new com.google.protobuf.LazyStringArrayList();
|
||||
mutable_bitField0_ |= 0x00000080;
|
||||
}
|
||||
removedMembers_.add(input.readBytes());
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch (com.google.protobuf.InvalidProtocolBufferException e) {
|
||||
@ -24599,6 +24679,12 @@ public final class SignalServiceProtos {
|
||||
if (((mutable_bitField0_ & 0x00000020) == 0x00000020)) {
|
||||
admins_ = new com.google.protobuf.UnmodifiableLazyStringList(admins_);
|
||||
}
|
||||
if (((mutable_bitField0_ & 0x00000040) == 0x00000040)) {
|
||||
newMembers_ = new com.google.protobuf.UnmodifiableLazyStringList(newMembers_);
|
||||
}
|
||||
if (((mutable_bitField0_ & 0x00000080) == 0x00000080)) {
|
||||
removedMembers_ = new com.google.protobuf.UnmodifiableLazyStringList(removedMembers_);
|
||||
}
|
||||
this.unknownFields = unknownFields.build();
|
||||
makeExtensionsImmutable();
|
||||
}
|
||||
@ -24913,6 +24999,90 @@ public final class SignalServiceProtos {
|
||||
return admins_.getByteString(index);
|
||||
}
|
||||
|
||||
// repeated string newMembers = 998;
|
||||
public static final int NEWMEMBERS_FIELD_NUMBER = 998;
|
||||
private com.google.protobuf.LazyStringList newMembers_;
|
||||
/**
|
||||
* <code>repeated string newMembers = 998;</code>
|
||||
*
|
||||
* <pre>
|
||||
* Loki - These fields are only used internally for the Android code base.
|
||||
* This is so that we can differentiate adding/kicking.
|
||||
* DO NOT USE WHEN SENDING MESSAGES.
|
||||
* </pre>
|
||||
*/
|
||||
public java.util.List<java.lang.String>
|
||||
getNewMembersList() {
|
||||
return newMembers_;
|
||||
}
|
||||
/**
|
||||
* <code>repeated string newMembers = 998;</code>
|
||||
*
|
||||
* <pre>
|
||||
* Loki - These fields are only used internally for the Android code base.
|
||||
* This is so that we can differentiate adding/kicking.
|
||||
* DO NOT USE WHEN SENDING MESSAGES.
|
||||
* </pre>
|
||||
*/
|
||||
public int getNewMembersCount() {
|
||||
return newMembers_.size();
|
||||
}
|
||||
/**
|
||||
* <code>repeated string newMembers = 998;</code>
|
||||
*
|
||||
* <pre>
|
||||
* Loki - These fields are only used internally for the Android code base.
|
||||
* This is so that we can differentiate adding/kicking.
|
||||
* DO NOT USE WHEN SENDING MESSAGES.
|
||||
* </pre>
|
||||
*/
|
||||
public java.lang.String getNewMembers(int index) {
|
||||
return newMembers_.get(index);
|
||||
}
|
||||
/**
|
||||
* <code>repeated string newMembers = 998;</code>
|
||||
*
|
||||
* <pre>
|
||||
* Loki - These fields are only used internally for the Android code base.
|
||||
* This is so that we can differentiate adding/kicking.
|
||||
* DO NOT USE WHEN SENDING MESSAGES.
|
||||
* </pre>
|
||||
*/
|
||||
public com.google.protobuf.ByteString
|
||||
getNewMembersBytes(int index) {
|
||||
return newMembers_.getByteString(index);
|
||||
}
|
||||
|
||||
// repeated string removedMembers = 999;
|
||||
public static final int REMOVEDMEMBERS_FIELD_NUMBER = 999;
|
||||
private com.google.protobuf.LazyStringList removedMembers_;
|
||||
/**
|
||||
* <code>repeated string removedMembers = 999;</code>
|
||||
*/
|
||||
public java.util.List<java.lang.String>
|
||||
getRemovedMembersList() {
|
||||
return removedMembers_;
|
||||
}
|
||||
/**
|
||||
* <code>repeated string removedMembers = 999;</code>
|
||||
*/
|
||||
public int getRemovedMembersCount() {
|
||||
return removedMembers_.size();
|
||||
}
|
||||
/**
|
||||
* <code>repeated string removedMembers = 999;</code>
|
||||
*/
|
||||
public java.lang.String getRemovedMembers(int index) {
|
||||
return removedMembers_.get(index);
|
||||
}
|
||||
/**
|
||||
* <code>repeated string removedMembers = 999;</code>
|
||||
*/
|
||||
public com.google.protobuf.ByteString
|
||||
getRemovedMembersBytes(int index) {
|
||||
return removedMembers_.getByteString(index);
|
||||
}
|
||||
|
||||
private void initFields() {
|
||||
id_ = com.google.protobuf.ByteString.EMPTY;
|
||||
type_ = org.session.libsignal.service.internal.push.SignalServiceProtos.GroupContext.Type.UNKNOWN;
|
||||
@ -24920,6 +25090,8 @@ public final class SignalServiceProtos {
|
||||
members_ = com.google.protobuf.LazyStringArrayList.EMPTY;
|
||||
avatar_ = org.session.libsignal.service.internal.push.SignalServiceProtos.AttachmentPointer.getDefaultInstance();
|
||||
admins_ = com.google.protobuf.LazyStringArrayList.EMPTY;
|
||||
newMembers_ = com.google.protobuf.LazyStringArrayList.EMPTY;
|
||||
removedMembers_ = com.google.protobuf.LazyStringArrayList.EMPTY;
|
||||
}
|
||||
private byte memoizedIsInitialized = -1;
|
||||
public final boolean isInitialized() {
|
||||
@ -24951,6 +25123,12 @@ public final class SignalServiceProtos {
|
||||
for (int i = 0; i < admins_.size(); i++) {
|
||||
output.writeBytes(6, admins_.getByteString(i));
|
||||
}
|
||||
for (int i = 0; i < newMembers_.size(); i++) {
|
||||
output.writeBytes(998, newMembers_.getByteString(i));
|
||||
}
|
||||
for (int i = 0; i < removedMembers_.size(); i++) {
|
||||
output.writeBytes(999, removedMembers_.getByteString(i));
|
||||
}
|
||||
getUnknownFields().writeTo(output);
|
||||
}
|
||||
|
||||
@ -24994,6 +25172,24 @@ public final class SignalServiceProtos {
|
||||
size += dataSize;
|
||||
size += 1 * getAdminsList().size();
|
||||
}
|
||||
{
|
||||
int dataSize = 0;
|
||||
for (int i = 0; i < newMembers_.size(); i++) {
|
||||
dataSize += com.google.protobuf.CodedOutputStream
|
||||
.computeBytesSizeNoTag(newMembers_.getByteString(i));
|
||||
}
|
||||
size += dataSize;
|
||||
size += 2 * getNewMembersList().size();
|
||||
}
|
||||
{
|
||||
int dataSize = 0;
|
||||
for (int i = 0; i < removedMembers_.size(); i++) {
|
||||
dataSize += com.google.protobuf.CodedOutputStream
|
||||
.computeBytesSizeNoTag(removedMembers_.getByteString(i));
|
||||
}
|
||||
size += dataSize;
|
||||
size += 2 * getRemovedMembersList().size();
|
||||
}
|
||||
size += getUnknownFields().getSerializedSize();
|
||||
memoizedSerializedSize = size;
|
||||
return size;
|
||||
@ -25127,6 +25323,10 @@ public final class SignalServiceProtos {
|
||||
bitField0_ = (bitField0_ & ~0x00000010);
|
||||
admins_ = com.google.protobuf.LazyStringArrayList.EMPTY;
|
||||
bitField0_ = (bitField0_ & ~0x00000020);
|
||||
newMembers_ = com.google.protobuf.LazyStringArrayList.EMPTY;
|
||||
bitField0_ = (bitField0_ & ~0x00000040);
|
||||
removedMembers_ = com.google.protobuf.LazyStringArrayList.EMPTY;
|
||||
bitField0_ = (bitField0_ & ~0x00000080);
|
||||
return this;
|
||||
}
|
||||
|
||||
@ -25187,6 +25387,18 @@ public final class SignalServiceProtos {
|
||||
bitField0_ = (bitField0_ & ~0x00000020);
|
||||
}
|
||||
result.admins_ = admins_;
|
||||
if (((bitField0_ & 0x00000040) == 0x00000040)) {
|
||||
newMembers_ = new com.google.protobuf.UnmodifiableLazyStringList(
|
||||
newMembers_);
|
||||
bitField0_ = (bitField0_ & ~0x00000040);
|
||||
}
|
||||
result.newMembers_ = newMembers_;
|
||||
if (((bitField0_ & 0x00000080) == 0x00000080)) {
|
||||
removedMembers_ = new com.google.protobuf.UnmodifiableLazyStringList(
|
||||
removedMembers_);
|
||||
bitField0_ = (bitField0_ & ~0x00000080);
|
||||
}
|
||||
result.removedMembers_ = removedMembers_;
|
||||
result.bitField0_ = to_bitField0_;
|
||||
onBuilt();
|
||||
return result;
|
||||
@ -25237,6 +25449,26 @@ public final class SignalServiceProtos {
|
||||
}
|
||||
onChanged();
|
||||
}
|
||||
if (!other.newMembers_.isEmpty()) {
|
||||
if (newMembers_.isEmpty()) {
|
||||
newMembers_ = other.newMembers_;
|
||||
bitField0_ = (bitField0_ & ~0x00000040);
|
||||
} else {
|
||||
ensureNewMembersIsMutable();
|
||||
newMembers_.addAll(other.newMembers_);
|
||||
}
|
||||
onChanged();
|
||||
}
|
||||
if (!other.removedMembers_.isEmpty()) {
|
||||
if (removedMembers_.isEmpty()) {
|
||||
removedMembers_ = other.removedMembers_;
|
||||
bitField0_ = (bitField0_ & ~0x00000080);
|
||||
} else {
|
||||
ensureRemovedMembersIsMutable();
|
||||
removedMembers_.addAll(other.removedMembers_);
|
||||
}
|
||||
onChanged();
|
||||
}
|
||||
this.mergeUnknownFields(other.getUnknownFields());
|
||||
return this;
|
||||
}
|
||||
@ -25745,6 +25977,246 @@ public final class SignalServiceProtos {
|
||||
return this;
|
||||
}
|
||||
|
||||
// repeated string newMembers = 998;
|
||||
private com.google.protobuf.LazyStringList newMembers_ = com.google.protobuf.LazyStringArrayList.EMPTY;
|
||||
private void ensureNewMembersIsMutable() {
|
||||
if (!((bitField0_ & 0x00000040) == 0x00000040)) {
|
||||
newMembers_ = new com.google.protobuf.LazyStringArrayList(newMembers_);
|
||||
bitField0_ |= 0x00000040;
|
||||
}
|
||||
}
|
||||
/**
|
||||
* <code>repeated string newMembers = 998;</code>
|
||||
*
|
||||
* <pre>
|
||||
* Loki - These fields are only used internally for the Android code base.
|
||||
* This is so that we can differentiate adding/kicking.
|
||||
* DO NOT USE WHEN SENDING MESSAGES.
|
||||
* </pre>
|
||||
*/
|
||||
public java.util.List<java.lang.String>
|
||||
getNewMembersList() {
|
||||
return java.util.Collections.unmodifiableList(newMembers_);
|
||||
}
|
||||
/**
|
||||
* <code>repeated string newMembers = 998;</code>
|
||||
*
|
||||
* <pre>
|
||||
* Loki - These fields are only used internally for the Android code base.
|
||||
* This is so that we can differentiate adding/kicking.
|
||||
* DO NOT USE WHEN SENDING MESSAGES.
|
||||
* </pre>
|
||||
*/
|
||||
public int getNewMembersCount() {
|
||||
return newMembers_.size();
|
||||
}
|
||||
/**
|
||||
* <code>repeated string newMembers = 998;</code>
|
||||
*
|
||||
* <pre>
|
||||
* Loki - These fields are only used internally for the Android code base.
|
||||
* This is so that we can differentiate adding/kicking.
|
||||
* DO NOT USE WHEN SENDING MESSAGES.
|
||||
* </pre>
|
||||
*/
|
||||
public java.lang.String getNewMembers(int index) {
|
||||
return newMembers_.get(index);
|
||||
}
|
||||
/**
|
||||
* <code>repeated string newMembers = 998;</code>
|
||||
*
|
||||
* <pre>
|
||||
* Loki - These fields are only used internally for the Android code base.
|
||||
* This is so that we can differentiate adding/kicking.
|
||||
* DO NOT USE WHEN SENDING MESSAGES.
|
||||
* </pre>
|
||||
*/
|
||||
public com.google.protobuf.ByteString
|
||||
getNewMembersBytes(int index) {
|
||||
return newMembers_.getByteString(index);
|
||||
}
|
||||
/**
|
||||
* <code>repeated string newMembers = 998;</code>
|
||||
*
|
||||
* <pre>
|
||||
* Loki - These fields are only used internally for the Android code base.
|
||||
* This is so that we can differentiate adding/kicking.
|
||||
* DO NOT USE WHEN SENDING MESSAGES.
|
||||
* </pre>
|
||||
*/
|
||||
public Builder setNewMembers(
|
||||
int index, java.lang.String value) {
|
||||
if (value == null) {
|
||||
throw new NullPointerException();
|
||||
}
|
||||
ensureNewMembersIsMutable();
|
||||
newMembers_.set(index, value);
|
||||
onChanged();
|
||||
return this;
|
||||
}
|
||||
/**
|
||||
* <code>repeated string newMembers = 998;</code>
|
||||
*
|
||||
* <pre>
|
||||
* Loki - These fields are only used internally for the Android code base.
|
||||
* This is so that we can differentiate adding/kicking.
|
||||
* DO NOT USE WHEN SENDING MESSAGES.
|
||||
* </pre>
|
||||
*/
|
||||
public Builder addNewMembers(
|
||||
java.lang.String value) {
|
||||
if (value == null) {
|
||||
throw new NullPointerException();
|
||||
}
|
||||
ensureNewMembersIsMutable();
|
||||
newMembers_.add(value);
|
||||
onChanged();
|
||||
return this;
|
||||
}
|
||||
/**
|
||||
* <code>repeated string newMembers = 998;</code>
|
||||
*
|
||||
* <pre>
|
||||
* Loki - These fields are only used internally for the Android code base.
|
||||
* This is so that we can differentiate adding/kicking.
|
||||
* DO NOT USE WHEN SENDING MESSAGES.
|
||||
* </pre>
|
||||
*/
|
||||
public Builder addAllNewMembers(
|
||||
java.lang.Iterable<java.lang.String> values) {
|
||||
ensureNewMembersIsMutable();
|
||||
super.addAll(values, newMembers_);
|
||||
onChanged();
|
||||
return this;
|
||||
}
|
||||
/**
|
||||
* <code>repeated string newMembers = 998;</code>
|
||||
*
|
||||
* <pre>
|
||||
* Loki - These fields are only used internally for the Android code base.
|
||||
* This is so that we can differentiate adding/kicking.
|
||||
* DO NOT USE WHEN SENDING MESSAGES.
|
||||
* </pre>
|
||||
*/
|
||||
public Builder clearNewMembers() {
|
||||
newMembers_ = com.google.protobuf.LazyStringArrayList.EMPTY;
|
||||
bitField0_ = (bitField0_ & ~0x00000040);
|
||||
onChanged();
|
||||
return this;
|
||||
}
|
||||
/**
|
||||
* <code>repeated string newMembers = 998;</code>
|
||||
*
|
||||
* <pre>
|
||||
* Loki - These fields are only used internally for the Android code base.
|
||||
* This is so that we can differentiate adding/kicking.
|
||||
* DO NOT USE WHEN SENDING MESSAGES.
|
||||
* </pre>
|
||||
*/
|
||||
public Builder addNewMembersBytes(
|
||||
com.google.protobuf.ByteString value) {
|
||||
if (value == null) {
|
||||
throw new NullPointerException();
|
||||
}
|
||||
ensureNewMembersIsMutable();
|
||||
newMembers_.add(value);
|
||||
onChanged();
|
||||
return this;
|
||||
}
|
||||
|
||||
// repeated string removedMembers = 999;
|
||||
private com.google.protobuf.LazyStringList removedMembers_ = com.google.protobuf.LazyStringArrayList.EMPTY;
|
||||
private void ensureRemovedMembersIsMutable() {
|
||||
if (!((bitField0_ & 0x00000080) == 0x00000080)) {
|
||||
removedMembers_ = new com.google.protobuf.LazyStringArrayList(removedMembers_);
|
||||
bitField0_ |= 0x00000080;
|
||||
}
|
||||
}
|
||||
/**
|
||||
* <code>repeated string removedMembers = 999;</code>
|
||||
*/
|
||||
public java.util.List<java.lang.String>
|
||||
getRemovedMembersList() {
|
||||
return java.util.Collections.unmodifiableList(removedMembers_);
|
||||
}
|
||||
/**
|
||||
* <code>repeated string removedMembers = 999;</code>
|
||||
*/
|
||||
public int getRemovedMembersCount() {
|
||||
return removedMembers_.size();
|
||||
}
|
||||
/**
|
||||
* <code>repeated string removedMembers = 999;</code>
|
||||
*/
|
||||
public java.lang.String getRemovedMembers(int index) {
|
||||
return removedMembers_.get(index);
|
||||
}
|
||||
/**
|
||||
* <code>repeated string removedMembers = 999;</code>
|
||||
*/
|
||||
public com.google.protobuf.ByteString
|
||||
getRemovedMembersBytes(int index) {
|
||||
return removedMembers_.getByteString(index);
|
||||
}
|
||||
/**
|
||||
* <code>repeated string removedMembers = 999;</code>
|
||||
*/
|
||||
public Builder setRemovedMembers(
|
||||
int index, java.lang.String value) {
|
||||
if (value == null) {
|
||||
throw new NullPointerException();
|
||||
}
|
||||
ensureRemovedMembersIsMutable();
|
||||
removedMembers_.set(index, value);
|
||||
onChanged();
|
||||
return this;
|
||||
}
|
||||
/**
|
||||
* <code>repeated string removedMembers = 999;</code>
|
||||
*/
|
||||
public Builder addRemovedMembers(
|
||||
java.lang.String value) {
|
||||
if (value == null) {
|
||||
throw new NullPointerException();
|
||||
}
|
||||
ensureRemovedMembersIsMutable();
|
||||
removedMembers_.add(value);
|
||||
onChanged();
|
||||
return this;
|
||||
}
|
||||
/**
|
||||
* <code>repeated string removedMembers = 999;</code>
|
||||
*/
|
||||
public Builder addAllRemovedMembers(
|
||||
java.lang.Iterable<java.lang.String> values) {
|
||||
ensureRemovedMembersIsMutable();
|
||||
super.addAll(values, removedMembers_);
|
||||
onChanged();
|
||||
return this;
|
||||
}
|
||||
/**
|
||||
* <code>repeated string removedMembers = 999;</code>
|
||||
*/
|
||||
public Builder clearRemovedMembers() {
|
||||
removedMembers_ = com.google.protobuf.LazyStringArrayList.EMPTY;
|
||||
bitField0_ = (bitField0_ & ~0x00000080);
|
||||
onChanged();
|
||||
return this;
|
||||
}
|
||||
/**
|
||||
* <code>repeated string removedMembers = 999;</code>
|
||||
*/
|
||||
public Builder addRemovedMembersBytes(
|
||||
com.google.protobuf.ByteString value) {
|
||||
if (value == null) {
|
||||
throw new NullPointerException();
|
||||
}
|
||||
ensureRemovedMembersIsMutable();
|
||||
removedMembers_.add(value);
|
||||
onChanged();
|
||||
return this;
|
||||
}
|
||||
|
||||
// @@protoc_insertion_point(builder_scope:signalservice.GroupContext)
|
||||
}
|
||||
|
||||
@ -30486,28 +30958,30 @@ public final class SignalServiceProtos {
|
||||
"thumbnail\030\005 \001(\014\022\016\n\006digest\030\006 \001(\014\022\020\n\010fileN" +
|
||||
"ame\030\007 \001(\t\022\r\n\005flags\030\010 \001(\r\022\r\n\005width\030\t \001(\r\022" +
|
||||
"\016\n\006height\030\n \001(\r\022\017\n\007caption\030\013 \001(\t\022\013\n\003url\030",
|
||||
"e \001(\t\"\032\n\005Flags\022\021\n\rVOICE_MESSAGE\020\001\"\365\001\n\014Gr" +
|
||||
"e \001(\t\"\032\n\005Flags\022\021\n\rVOICE_MESSAGE\020\001\"\243\002\n\014Gr" +
|
||||
"oupContext\022\n\n\002id\030\001 \001(\014\022.\n\004type\030\002 \001(\0162 .s" +
|
||||
"ignalservice.GroupContext.Type\022\014\n\004name\030\003" +
|
||||
" \001(\t\022\017\n\007members\030\004 \003(\t\0220\n\006avatar\030\005 \001(\0132 ." +
|
||||
"signalservice.AttachmentPointer\022\016\n\006admin" +
|
||||
"s\030\006 \003(\t\"H\n\004Type\022\013\n\007UNKNOWN\020\000\022\n\n\006UPDATE\020\001" +
|
||||
"\022\013\n\007DELIVER\020\002\022\010\n\004QUIT\020\003\022\020\n\014REQUEST_INFO\020" +
|
||||
"\004\"\356\001\n\016ContactDetails\022\016\n\006number\030\001 \001(\t\022\014\n\004" +
|
||||
"name\030\002 \001(\t\0224\n\006avatar\030\003 \001(\0132$.signalservi" +
|
||||
"ce.ContactDetails.Avatar\022\r\n\005color\030\004 \001(\t\022",
|
||||
"\022\n\nprofileKey\030\006 \001(\014\022\017\n\007blocked\030\007 \001(\010\022\023\n\013" +
|
||||
"expireTimer\030\010 \001(\r\022\020\n\010nickname\030e \001(\t\032-\n\006A" +
|
||||
"vatar\022\023\n\013contentType\030\001 \001(\t\022\016\n\006length\030\002 \001" +
|
||||
"(\r\"\367\001\n\014GroupDetails\022\n\n\002id\030\001 \001(\014\022\014\n\004name\030" +
|
||||
"\002 \001(\t\022\017\n\007members\030\003 \003(\t\0222\n\006avatar\030\004 \001(\0132\"" +
|
||||
".signalservice.GroupDetails.Avatar\022\024\n\006ac" +
|
||||
"tive\030\005 \001(\010:\004true\022\023\n\013expireTimer\030\006 \001(\r\022\r\n" +
|
||||
"\005color\030\007 \001(\t\022\017\n\007blocked\030\010 \001(\010\022\016\n\006admins\030" +
|
||||
"\t \003(\t\032-\n\006Avatar\022\023\n\013contentType\030\001 \001(\t\022\016\n\006" +
|
||||
"length\030\002 \001(\r\"\"\n\016PublicChatInfo\022\020\n\010server",
|
||||
"ID\030\001 \001(\004BB\n+org.session.libsignal.servic" +
|
||||
"e.internal.pushB\023SignalServiceProtos"
|
||||
"s\030\006 \003(\t\022\023\n\nnewMembers\030\346\007 \003(\t\022\027\n\016removedM" +
|
||||
"embers\030\347\007 \003(\t\"H\n\004Type\022\013\n\007UNKNOWN\020\000\022\n\n\006UP" +
|
||||
"DATE\020\001\022\013\n\007DELIVER\020\002\022\010\n\004QUIT\020\003\022\020\n\014REQUEST" +
|
||||
"_INFO\020\004\"\356\001\n\016ContactDetails\022\016\n\006number\030\001 \001" +
|
||||
"(\t\022\014\n\004name\030\002 \001(\t\0224\n\006avatar\030\003 \001(\0132$.signa",
|
||||
"lservice.ContactDetails.Avatar\022\r\n\005color\030" +
|
||||
"\004 \001(\t\022\022\n\nprofileKey\030\006 \001(\014\022\017\n\007blocked\030\007 \001" +
|
||||
"(\010\022\023\n\013expireTimer\030\010 \001(\r\022\020\n\010nickname\030e \001(" +
|
||||
"\t\032-\n\006Avatar\022\023\n\013contentType\030\001 \001(\t\022\016\n\006leng" +
|
||||
"th\030\002 \001(\r\"\367\001\n\014GroupDetails\022\n\n\002id\030\001 \001(\014\022\014\n" +
|
||||
"\004name\030\002 \001(\t\022\017\n\007members\030\003 \003(\t\0222\n\006avatar\030\004" +
|
||||
" \001(\0132\".signalservice.GroupDetails.Avatar" +
|
||||
"\022\024\n\006active\030\005 \001(\010:\004true\022\023\n\013expireTimer\030\006 " +
|
||||
"\001(\r\022\r\n\005color\030\007 \001(\t\022\017\n\007blocked\030\010 \001(\010\022\016\n\006a" +
|
||||
"dmins\030\t \003(\t\032-\n\006Avatar\022\023\n\013contentType\030\001 \001",
|
||||
"(\t\022\016\n\006length\030\002 \001(\r\"\"\n\016PublicChatInfo\022\020\n\010" +
|
||||
"serverID\030\001 \001(\004BB\n+org.session.libsignal." +
|
||||
"service.internal.pushB\023SignalServiceProt" +
|
||||
"os"
|
||||
};
|
||||
com.google.protobuf.Descriptors.FileDescriptor.InternalDescriptorAssigner assigner =
|
||||
new com.google.protobuf.Descriptors.FileDescriptor.InternalDescriptorAssigner() {
|
||||
@ -30651,7 +31125,7 @@ public final class SignalServiceProtos {
|
||||
internal_static_signalservice_GroupContext_fieldAccessorTable = new
|
||||
com.google.protobuf.GeneratedMessage.FieldAccessorTable(
|
||||
internal_static_signalservice_GroupContext_descriptor,
|
||||
new java.lang.String[] { "Id", "Type", "Name", "Members", "Avatar", "Admins", });
|
||||
new java.lang.String[] { "Id", "Type", "Name", "Members", "Avatar", "Admins", "NewMembers", "RemovedMembers", });
|
||||
internal_static_signalservice_ContactDetails_descriptor =
|
||||
getDescriptor().getMessageTypes().get(10);
|
||||
internal_static_signalservice_ContactDetails_fieldAccessorTable = new
|
||||
|
@ -5,7 +5,7 @@ import nl.komponents.kovenant.deferred
|
||||
import org.session.libsignal.utilities.logging.Log
|
||||
import org.session.libsignal.utilities.Base64
|
||||
import org.session.libsignal.service.loki.api.crypto.ProofOfWork
|
||||
import org.session.libsignal.service.loki.protocol.meta.TTLUtilities
|
||||
import org.session.libsignal.service.loki.utilities.TTLUtilities
|
||||
import org.session.libsignal.utilities.ThreadUtils
|
||||
import org.session.libsignal.service.loki.utilities.prettifiedDescription
|
||||
|
||||
|
@ -1,24 +0,0 @@
|
||||
package org.session.libsignal.service.loki.protocol.meta
|
||||
|
||||
import org.session.libsignal.service.loki.database.LokiAPIDatabaseProtocol
|
||||
|
||||
public class SessionMetaProtocol(private val apiDatabase: LokiAPIDatabaseProtocol, private val userPublicKey: String) {
|
||||
|
||||
// region Initialization
|
||||
companion object {
|
||||
|
||||
public lateinit var shared: SessionMetaProtocol
|
||||
|
||||
public fun configureIfNeeded(apiDatabase: LokiAPIDatabaseProtocol, userPublicKey: String) {
|
||||
if (::shared.isInitialized) { return; }
|
||||
shared = SessionMetaProtocol(apiDatabase, userPublicKey)
|
||||
}
|
||||
}
|
||||
// endregion
|
||||
|
||||
// region Utilities
|
||||
public fun isNoteToSelf(publicKey: String): Boolean {
|
||||
return userPublicKey == publicKey // return MultiDeviceProtocol.shared.getAllLinkedDevices(userPublicKey).contains(publicKey)
|
||||
}
|
||||
// endregion
|
||||
}
|
@ -1,23 +0,0 @@
|
||||
package org.session.libsignal.service.loki.protocol.sessionmanagement
|
||||
|
||||
import org.session.libsignal.libsignal.IdentityKey
|
||||
import org.session.libsignal.libsignal.ecc.Curve
|
||||
import org.session.libsignal.libsignal.state.PreKeyBundle
|
||||
|
||||
data class PreKeyBundleMessage(
|
||||
val identityKey: ByteArray,
|
||||
val deviceID: Int,
|
||||
val preKeyID: Int,
|
||||
val signedPreKeyID: Int,
|
||||
val preKey: ByteArray,
|
||||
val signedPreKey: ByteArray,
|
||||
val signedPreKeySignature: ByteArray
|
||||
) {
|
||||
|
||||
constructor(preKeyBundle: PreKeyBundle) : this(preKeyBundle.identityKey.serialize(), preKeyBundle.deviceId, preKeyBundle.preKeyId,
|
||||
preKeyBundle.signedPreKeyId, preKeyBundle.preKey.serialize(), preKeyBundle.signedPreKey.serialize(), preKeyBundle.signedPreKeySignature)
|
||||
|
||||
fun getPreKeyBundle(registrationID: Int): PreKeyBundle {
|
||||
return PreKeyBundle(registrationID, deviceID, preKeyID, Curve.decodePoint(preKey, 0), signedPreKeyID, Curve.decodePoint(signedPreKey, 0), signedPreKeySignature, IdentityKey(identityKey, 0))
|
||||
}
|
||||
}
|
@ -1,53 +0,0 @@
|
||||
package org.session.libsignal.service.loki.protocol.sessionmanagement
|
||||
|
||||
import org.session.libsignal.utilities.logging.Log
|
||||
import org.session.libsignal.libsignal.loki.SessionResetProtocol
|
||||
import org.session.libsignal.libsignal.loki.SessionResetStatus
|
||||
import org.session.libsignal.libsignal.util.guava.Optional
|
||||
import org.session.libsignal.service.api.SignalServiceMessageSender
|
||||
import org.session.libsignal.service.api.push.SignalServiceAddress
|
||||
|
||||
public class SessionManagementProtocol(private val sessionResetImpl: SessionResetProtocol, private val delegate: SessionManagementProtocolDelegate) {
|
||||
|
||||
// region Initialization
|
||||
companion object {
|
||||
|
||||
public lateinit var shared: SessionManagementProtocol
|
||||
|
||||
public fun configureIfNeeded(sessionResetImpl: SessionResetProtocol, delegate: SessionManagementProtocolDelegate) {
|
||||
if (::shared.isInitialized) { return; }
|
||||
shared = SessionManagementProtocol(sessionResetImpl, delegate)
|
||||
}
|
||||
}
|
||||
// endregion
|
||||
|
||||
// region Sending
|
||||
/**
|
||||
* Called after an end session message is sent.
|
||||
*/
|
||||
public fun setSessionResetStatusToInProgressIfNeeded(recipient: SignalServiceAddress, eventListener: Optional<SignalServiceMessageSender.EventListener>) {
|
||||
val publicKey = recipient.number
|
||||
val sessionResetStatus = sessionResetImpl.getSessionResetStatus(publicKey)
|
||||
if (sessionResetStatus == SessionResetStatus.REQUEST_RECEIVED) { return }
|
||||
Log.d("Loki", "Starting session reset")
|
||||
sessionResetImpl.setSessionResetStatus(publicKey, SessionResetStatus.IN_PROGRESS)
|
||||
if (!eventListener.isPresent) { return }
|
||||
eventListener.get().onSecurityEvent(recipient)
|
||||
}
|
||||
|
||||
public fun repairSessionIfNeeded(recipient: SignalServiceAddress, isClosedGroup: Boolean) {
|
||||
val publicKey = recipient.number
|
||||
if (!isClosedGroup) { return }
|
||||
delegate.sendSessionRequestIfNeeded(publicKey)
|
||||
}
|
||||
|
||||
public fun shouldIgnoreMissingPreKeyBundleException(isClosedGroup: Boolean): Boolean {
|
||||
// When a closed group is created, members try to establish sessions with eachother in the background through
|
||||
// session requests. Until ALL users those session requests were sent to have come online, stored the pre key
|
||||
// bundles contained in the session requests and replied with background messages to finalize the session
|
||||
// creation, a given user won't be able to successfully send a message to all members of a group. This check
|
||||
// is so that until we can do better on this front the user at least won't see this as an error in the UI.
|
||||
return isClosedGroup
|
||||
}
|
||||
// endregion
|
||||
}
|
@ -1,6 +0,0 @@
|
||||
package org.session.libsignal.service.loki.protocol.sessionmanagement
|
||||
|
||||
interface SessionManagementProtocolDelegate {
|
||||
|
||||
fun sendSessionRequestIfNeeded(publicKey: String)
|
||||
}
|
@ -1,4 +1,4 @@
|
||||
package org.session.libsignal.service.loki.protocol.meta
|
||||
package org.session.libsignal.service.loki.utilities
|
||||
|
||||
public object TTLUtilities {
|
||||
|
@ -1,3 +1,3 @@
|
||||
package org.session.libsignal.service.loki.protocol.mentions
|
||||
package org.session.libsignal.service.loki.utilities.mentions
|
||||
|
||||
data class Mention(val publicKey: String, val displayName: String)
|
@ -1,4 +1,4 @@
|
||||
package org.session.libsignal.service.loki.protocol.mentions
|
||||
package org.session.libsignal.service.loki.utilities.mentions
|
||||
|
||||
import org.session.libsignal.service.loki.database.LokiThreadDatabaseProtocol
|
||||
import org.session.libsignal.service.loki.database.LokiUserDatabaseProtocol
|
Loading…
x
Reference in New Issue
Block a user