kopia lustrzana https://github.com/ryukoposting/Signal-Android
Clean up message processing locks.
rodzic
0d0ee753df
commit
c0eac5564c
|
@ -12,11 +12,10 @@ import android.widget.TextView;
|
|||
import androidx.appcompat.app.AlertDialog;
|
||||
|
||||
import org.signal.core.util.logging.Log;
|
||||
import org.thoughtcrime.securesms.crypto.DatabaseSessionLock;
|
||||
import org.thoughtcrime.securesms.crypto.ReentrantSessionLock;
|
||||
import org.thoughtcrime.securesms.crypto.storage.TextSecureIdentityKeyStore;
|
||||
import org.thoughtcrime.securesms.database.DatabaseFactory;
|
||||
import org.thoughtcrime.securesms.database.MessageDatabase;
|
||||
import org.thoughtcrime.securesms.database.PushDatabase;
|
||||
import org.thoughtcrime.securesms.database.documents.IdentityKeyMismatch;
|
||||
import org.thoughtcrime.securesms.database.model.MessageRecord;
|
||||
import org.thoughtcrime.securesms.dependencies.ApplicationDependencies;
|
||||
|
@ -95,7 +94,7 @@ public class ConfirmIdentityDialog extends AlertDialog {
|
|||
{
|
||||
@Override
|
||||
protected Void doInBackground(Void... params) {
|
||||
try (SignalSessionLock.Lock unused = DatabaseSessionLock.INSTANCE.acquire()) {
|
||||
try (SignalSessionLock.Lock unused = ReentrantSessionLock.INSTANCE.acquire()) {
|
||||
SignalProtocolAddress mismatchAddress = new SignalProtocolAddress(Recipient.resolved(recipientId).requireServiceId(), 1);
|
||||
TextSecureIdentityKeyStore identityKeyStore = new TextSecureIdentityKeyStore(getContext());
|
||||
|
||||
|
|
|
@ -29,7 +29,6 @@ import android.graphics.BitmapFactory;
|
|||
import android.graphics.Canvas;
|
||||
import android.graphics.PorterDuff;
|
||||
import android.graphics.drawable.BitmapDrawable;
|
||||
import android.graphics.drawable.ColorDrawable;
|
||||
import android.os.AsyncTask;
|
||||
import android.os.Bundle;
|
||||
import android.os.Vibrator;
|
||||
|
@ -63,9 +62,8 @@ import androidx.fragment.app.FragmentTransaction;
|
|||
import org.signal.core.util.ThreadUtil;
|
||||
import org.signal.core.util.concurrent.SignalExecutors;
|
||||
import org.signal.core.util.logging.Log;
|
||||
import org.thoughtcrime.securesms.color.MaterialColor;
|
||||
import org.thoughtcrime.securesms.components.camera.CameraView;
|
||||
import org.thoughtcrime.securesms.crypto.DatabaseSessionLock;
|
||||
import org.thoughtcrime.securesms.crypto.ReentrantSessionLock;
|
||||
import org.thoughtcrime.securesms.crypto.IdentityKeyParcelable;
|
||||
import org.thoughtcrime.securesms.crypto.IdentityKeyUtil;
|
||||
import org.thoughtcrime.securesms.database.DatabaseFactory;
|
||||
|
@ -87,16 +85,13 @@ import org.thoughtcrime.securesms.util.IdentityUtil;
|
|||
import org.thoughtcrime.securesms.util.TextSecurePreferences;
|
||||
import org.thoughtcrime.securesms.util.Util;
|
||||
import org.thoughtcrime.securesms.util.ViewUtil;
|
||||
import org.thoughtcrime.securesms.util.WindowUtil;
|
||||
import org.whispersystems.libsignal.IdentityKey;
|
||||
import org.whispersystems.libsignal.fingerprint.Fingerprint;
|
||||
import org.whispersystems.libsignal.fingerprint.FingerprintParsingException;
|
||||
import org.whispersystems.libsignal.fingerprint.FingerprintVersionMismatchException;
|
||||
import org.whispersystems.libsignal.fingerprint.NumericFingerprintGenerator;
|
||||
import org.whispersystems.signalservice.api.SignalSessionLock;
|
||||
import org.whispersystems.signalservice.api.util.UuidUtil;
|
||||
|
||||
import java.io.UnsupportedEncodingException;
|
||||
import java.nio.charset.Charset;
|
||||
import java.util.Locale;
|
||||
|
||||
|
@ -615,7 +610,7 @@ public class VerifyIdentityActivity extends PassphraseRequiredActivity implement
|
|||
final RecipientId recipientId = recipient.getId();
|
||||
|
||||
SignalExecutors.BOUNDED.execute(() -> {
|
||||
try (SignalSessionLock.Lock unused = DatabaseSessionLock.INSTANCE.acquire()) {
|
||||
try (SignalSessionLock.Lock unused = ReentrantSessionLock.INSTANCE.acquire()) {
|
||||
if (isChecked) {
|
||||
Log.i(TAG, "Saving identity: " + recipientId);
|
||||
DatabaseFactory.getIdentityDatabase(getActivity())
|
||||
|
|
|
@ -8,7 +8,7 @@ import androidx.annotation.NonNull;
|
|||
import androidx.appcompat.app.AlertDialog;
|
||||
|
||||
import org.thoughtcrime.securesms.R;
|
||||
import org.thoughtcrime.securesms.crypto.DatabaseSessionLock;
|
||||
import org.thoughtcrime.securesms.crypto.ReentrantSessionLock;
|
||||
import org.thoughtcrime.securesms.database.DatabaseFactory;
|
||||
import org.thoughtcrime.securesms.database.IdentityDatabase;
|
||||
import org.thoughtcrime.securesms.database.IdentityDatabase.IdentityRecord;
|
||||
|
@ -43,7 +43,7 @@ public class UntrustedSendDialog extends AlertDialog.Builder implements DialogIn
|
|||
final IdentityDatabase identityDatabase = DatabaseFactory.getIdentityDatabase(getContext());
|
||||
|
||||
SimpleTask.run(() -> {
|
||||
try(SignalSessionLock.Lock unused = DatabaseSessionLock.INSTANCE.acquire()) {
|
||||
try(SignalSessionLock.Lock unused = ReentrantSessionLock.INSTANCE.acquire()) {
|
||||
for (IdentityRecord identityRecord : untrustedRecords) {
|
||||
identityDatabase.setApproval(identityRecord.getRecipientId(), true);
|
||||
}
|
||||
|
|
|
@ -8,7 +8,7 @@ import androidx.annotation.NonNull;
|
|||
import androidx.appcompat.app.AlertDialog;
|
||||
|
||||
import org.thoughtcrime.securesms.R;
|
||||
import org.thoughtcrime.securesms.crypto.DatabaseSessionLock;
|
||||
import org.thoughtcrime.securesms.crypto.ReentrantSessionLock;
|
||||
import org.thoughtcrime.securesms.database.DatabaseFactory;
|
||||
import org.thoughtcrime.securesms.database.IdentityDatabase;
|
||||
import org.thoughtcrime.securesms.database.IdentityDatabase.IdentityRecord;
|
||||
|
@ -44,7 +44,7 @@ public class UnverifiedSendDialog extends AlertDialog.Builder implements DialogI
|
|||
new AsyncTask<Void, Void, Void>() {
|
||||
@Override
|
||||
protected Void doInBackground(Void... params) {
|
||||
try(SignalSessionLock.Lock unused = DatabaseSessionLock.INSTANCE.acquire()) {
|
||||
try(SignalSessionLock.Lock unused = ReentrantSessionLock.INSTANCE.acquire()) {
|
||||
for (IdentityRecord identityRecord : untrustedRecords) {
|
||||
identityDatabase.setVerified(identityRecord.getRecipientId(),
|
||||
identityRecord.getIdentityKey(),
|
||||
|
|
|
@ -143,7 +143,7 @@ import org.thoughtcrime.securesms.conversation.ui.error.SafetyNumberChangeDialog
|
|||
import org.thoughtcrime.securesms.conversation.ui.groupcall.GroupCallViewModel;
|
||||
import org.thoughtcrime.securesms.conversation.ui.mentions.MentionsPickerViewModel;
|
||||
import org.thoughtcrime.securesms.search.MessageResult;
|
||||
import org.thoughtcrime.securesms.crypto.DatabaseSessionLock;
|
||||
import org.thoughtcrime.securesms.crypto.ReentrantSessionLock;
|
||||
import org.thoughtcrime.securesms.crypto.SecurityEvent;
|
||||
import org.thoughtcrime.securesms.database.DatabaseFactory;
|
||||
import org.thoughtcrime.securesms.database.DraftDatabase;
|
||||
|
@ -3759,7 +3759,7 @@ public class ConversationActivity extends PassphraseRequiredActivity
|
|||
new AsyncTask<Void, Void, Void>() {
|
||||
@Override
|
||||
protected Void doInBackground(Void... params) {
|
||||
try (SignalSessionLock.Lock unused = DatabaseSessionLock.INSTANCE.acquire()) {
|
||||
try (SignalSessionLock.Lock unused = ReentrantSessionLock.INSTANCE.acquire()) {
|
||||
for (IdentityRecord identityRecord : unverifiedIdentities) {
|
||||
identityDatabase.setVerified(identityRecord.getRecipientId(),
|
||||
identityRecord.getIdentityKey(),
|
||||
|
|
|
@ -12,8 +12,8 @@ import com.annimon.stream.Stream;
|
|||
|
||||
import org.signal.core.util.concurrent.SignalExecutors;
|
||||
import org.signal.core.util.logging.Log;
|
||||
import org.thoughtcrime.securesms.crypto.DatabaseSessionLock;
|
||||
import org.thoughtcrime.securesms.crypto.SessionUtil;
|
||||
import org.thoughtcrime.securesms.crypto.ReentrantSessionLock;
|
||||
import org.thoughtcrime.securesms.crypto.storage.TextSecureIdentityKeyStore;
|
||||
import org.thoughtcrime.securesms.database.DatabaseFactory;
|
||||
import org.thoughtcrime.securesms.database.IdentityDatabase;
|
||||
|
@ -96,7 +96,7 @@ final class SafetyNumberChangeRepository {
|
|||
private TrustAndVerifyResult trustOrVerifyChangedRecipientsInternal(@NonNull List<ChangedRecipient> changedRecipients) {
|
||||
IdentityDatabase identityDatabase = DatabaseFactory.getIdentityDatabase(context);
|
||||
|
||||
try(SignalSessionLock.Lock unused = DatabaseSessionLock.INSTANCE.acquire()) {
|
||||
try(SignalSessionLock.Lock unused = ReentrantSessionLock.INSTANCE.acquire()) {
|
||||
for (ChangedRecipient changedRecipient : changedRecipients) {
|
||||
IdentityRecord identityRecord = changedRecipient.getIdentityRecord();
|
||||
|
||||
|
@ -122,7 +122,7 @@ final class SafetyNumberChangeRepository {
|
|||
Log.d(TAG, "No changed recipients to process, will still process message record");
|
||||
}
|
||||
|
||||
try(SignalSessionLock.Lock unused = DatabaseSessionLock.INSTANCE.acquire()) {
|
||||
try(SignalSessionLock.Lock unused = ReentrantSessionLock.INSTANCE.acquire()) {
|
||||
for (ChangedRecipient changedRecipient : changedRecipients) {
|
||||
SignalProtocolAddress mismatchAddress = new SignalProtocolAddress(changedRecipient.getRecipient().requireServiceId(), 1);
|
||||
TextSecureIdentityKeyStore identityKeyStore = new TextSecureIdentityKeyStore(context);
|
||||
|
|
|
@ -1,64 +0,0 @@
|
|||
package org.thoughtcrime.securesms.crypto;
|
||||
|
||||
import org.whispersystems.signalservice.api.SignalSessionLock;
|
||||
|
||||
import java.util.concurrent.locks.ReentrantLock;
|
||||
|
||||
/**
|
||||
* An implementation of {@link SignalSessionLock} that effectively re-uses our database lock.
|
||||
*/
|
||||
public enum DatabaseSessionLock implements SignalSessionLock {
|
||||
|
||||
INSTANCE;
|
||||
|
||||
public static final long NO_OWNER = -1;
|
||||
|
||||
private static final ReentrantLock LEGACY_LOCK = new ReentrantLock();
|
||||
|
||||
private volatile long ownerThreadId = NO_OWNER;
|
||||
|
||||
@Override
|
||||
public Lock acquire() {
|
||||
LEGACY_LOCK.lock();
|
||||
return LEGACY_LOCK::unlock;
|
||||
|
||||
// TODO [greyson][db] Revisit after improving database locking
|
||||
// SQLiteDatabase db = DatabaseFactory.getInstance(ApplicationDependencies.getApplication()).getRawDatabase();
|
||||
//
|
||||
// if (db.isDbLockedByCurrentThread()) {
|
||||
// return () -> {};
|
||||
// }
|
||||
//
|
||||
// db.beginTransaction();
|
||||
//
|
||||
// ownerThreadId = Thread.currentThread().getId();
|
||||
//
|
||||
// return () -> {
|
||||
// ownerThreadId = -1;
|
||||
// db.setTransactionSuccessful();
|
||||
// db.endTransaction();
|
||||
// };
|
||||
}
|
||||
|
||||
/**
|
||||
* Important: Only truly useful for debugging. Do not rely on this for functionality. There's tiny
|
||||
* windows where this state might not be fully accurate.
|
||||
*
|
||||
* @return True if it's likely that some other thread owns this lock, and it's not you.
|
||||
*/
|
||||
public boolean isLikelyHeldByOtherThread() {
|
||||
long ownerThreadId = this.ownerThreadId;
|
||||
return ownerThreadId != -1 && ownerThreadId == Thread.currentThread().getId();
|
||||
}
|
||||
|
||||
/**
|
||||
* Important: Only truly useful for debugging. Do not rely on this for functionality. There's a
|
||||
* tiny window where a thread may still own the lock, but the state we track around it has been
|
||||
* cleared.
|
||||
*
|
||||
* @return The ID of the thread that likely owns this lock, or {@link #NO_OWNER} if no one owns it.
|
||||
*/
|
||||
public long getLikeyOwnerThreadId() {
|
||||
return ownerThreadId;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,21 @@
|
|||
package org.thoughtcrime.securesms.crypto;
|
||||
|
||||
import org.whispersystems.signalservice.api.SignalSessionLock;
|
||||
|
||||
import java.util.concurrent.locks.ReentrantLock;
|
||||
|
||||
/**
|
||||
* An implementation of {@link SignalSessionLock} that is backed by a {@link ReentrantLock}.
|
||||
*/
|
||||
public enum ReentrantSessionLock implements SignalSessionLock {
|
||||
|
||||
INSTANCE;
|
||||
|
||||
private static final ReentrantLock LOCK = new ReentrantLock();
|
||||
|
||||
@Override
|
||||
public Lock acquire() {
|
||||
LOCK.lock();
|
||||
return LOCK::unlock;
|
||||
}
|
||||
}
|
|
@ -18,7 +18,7 @@ public final class SenderKeyUtil {
|
|||
* Clears the state for a sender key session we created. It will naturally get re-created when it is next needed, rotating the key.
|
||||
*/
|
||||
public static void rotateOurKey(@NonNull Context context, @NonNull DistributionId distributionId) {
|
||||
try (SignalSessionLock.Lock unused = DatabaseSessionLock.INSTANCE.acquire()) {
|
||||
try (SignalSessionLock.Lock unused = ReentrantSessionLock.INSTANCE.acquire()) {
|
||||
new SignalSenderKeyStore(context).deleteAllFor(Recipient.self().getId(), distributionId);
|
||||
DatabaseFactory.getSenderKeySharedDatabase(context).deleteAllFor(distributionId);
|
||||
}
|
||||
|
@ -35,7 +35,7 @@ public final class SenderKeyUtil {
|
|||
* Deletes all stored state around session keys. Should only really be used when the user is re-registering.
|
||||
*/
|
||||
public static void clearAllState(@NonNull Context context) {
|
||||
try (SignalSessionLock.Lock unused = DatabaseSessionLock.INSTANCE.acquire()) {
|
||||
try (SignalSessionLock.Lock unused = ReentrantSessionLock.INSTANCE.acquire()) {
|
||||
new SignalSenderKeyStore(context).deleteAll();
|
||||
DatabaseFactory.getSenderKeySharedDatabase(context).deleteAll();
|
||||
}
|
||||
|
|
|
@ -4,14 +4,12 @@ import android.content.Context;
|
|||
|
||||
import androidx.annotation.NonNull;
|
||||
|
||||
import org.thoughtcrime.securesms.crypto.DatabaseSessionLock;
|
||||
import org.thoughtcrime.securesms.database.DatabaseFactory;
|
||||
import org.whispersystems.signalservice.api.SignalServiceSenderKeyStore;
|
||||
import org.whispersystems.signalservice.api.push.DistributionId;
|
||||
import org.thoughtcrime.securesms.recipients.RecipientId;
|
||||
import org.whispersystems.libsignal.SignalProtocolAddress;
|
||||
import org.whispersystems.libsignal.groups.state.SenderKeyRecord;
|
||||
import org.whispersystems.signalservice.api.SignalSessionLock;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.Set;
|
||||
|
@ -25,6 +23,8 @@ import javax.annotation.Nullable;
|
|||
*/
|
||||
public final class SignalSenderKeyStore implements SignalServiceSenderKeyStore {
|
||||
|
||||
private static final Object LOCK = new Object();
|
||||
|
||||
private final Context context;
|
||||
|
||||
public SignalSenderKeyStore(@NonNull Context context) {
|
||||
|
@ -33,7 +33,7 @@ public final class SignalSenderKeyStore implements SignalServiceSenderKeyStore {
|
|||
|
||||
@Override
|
||||
public void storeSenderKey(@NonNull SignalProtocolAddress sender, @NonNull UUID distributionId, @NonNull SenderKeyRecord record) {
|
||||
try (SignalSessionLock.Lock unused = DatabaseSessionLock.INSTANCE.acquire()) {
|
||||
synchronized (LOCK) {
|
||||
RecipientId recipientId = RecipientId.fromExternalPush(sender.getName());
|
||||
DatabaseFactory.getSenderKeyDatabase(context).store(recipientId, sender.getDeviceId(), DistributionId.from(distributionId), record);
|
||||
}
|
||||
|
@ -41,7 +41,7 @@ public final class SignalSenderKeyStore implements SignalServiceSenderKeyStore {
|
|||
|
||||
@Override
|
||||
public @Nullable SenderKeyRecord loadSenderKey(@NonNull SignalProtocolAddress sender, @NonNull UUID distributionId) {
|
||||
try (SignalSessionLock.Lock unused = DatabaseSessionLock.INSTANCE.acquire()) {
|
||||
synchronized (LOCK) {
|
||||
RecipientId recipientId = RecipientId.fromExternalPush(sender.getName());
|
||||
return DatabaseFactory.getSenderKeyDatabase(context).load(recipientId, sender.getDeviceId(), DistributionId.from(distributionId));
|
||||
}
|
||||
|
@ -49,21 +49,21 @@ public final class SignalSenderKeyStore implements SignalServiceSenderKeyStore {
|
|||
|
||||
@Override
|
||||
public Set<SignalProtocolAddress> getSenderKeySharedWith(DistributionId distributionId) {
|
||||
try (SignalSessionLock.Lock unused = DatabaseSessionLock.INSTANCE.acquire()) {
|
||||
synchronized (LOCK) {
|
||||
return DatabaseFactory.getSenderKeySharedDatabase(context).getSharedWith(distributionId);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void markSenderKeySharedWith(DistributionId distributionId, Collection<SignalProtocolAddress> addresses) {
|
||||
try (SignalSessionLock.Lock unused = DatabaseSessionLock.INSTANCE.acquire()) {
|
||||
synchronized (LOCK) {
|
||||
DatabaseFactory.getSenderKeySharedDatabase(context).markAsShared(distributionId, addresses);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void clearSenderKeySharedWith(DistributionId distributionId, Collection<SignalProtocolAddress> addresses) {
|
||||
try (SignalSessionLock.Lock unused = DatabaseSessionLock.INSTANCE.acquire()) {
|
||||
synchronized (LOCK) {
|
||||
DatabaseFactory.getSenderKeySharedDatabase(context).delete(distributionId, addresses);
|
||||
}
|
||||
}
|
||||
|
@ -72,7 +72,7 @@ public final class SignalSenderKeyStore implements SignalServiceSenderKeyStore {
|
|||
* Removes all sender key session state for all devices for the provided recipient-distributionId pair.
|
||||
*/
|
||||
public void deleteAllFor(@NonNull RecipientId recipientId, @NonNull DistributionId distributionId) {
|
||||
try (SignalSessionLock.Lock unused = DatabaseSessionLock.INSTANCE.acquire()) {
|
||||
synchronized (LOCK) {
|
||||
DatabaseFactory.getSenderKeyDatabase(context).deleteAllFor(recipientId, distributionId);
|
||||
}
|
||||
}
|
||||
|
@ -81,7 +81,7 @@ public final class SignalSenderKeyStore implements SignalServiceSenderKeyStore {
|
|||
* Deletes all sender key session state.
|
||||
*/
|
||||
public void deleteAll() {
|
||||
try (SignalSessionLock.Lock unused = DatabaseSessionLock.INSTANCE.acquire()) {
|
||||
synchronized (LOCK) {
|
||||
DatabaseFactory.getSenderKeyDatabase(context).deleteAll();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -5,7 +5,6 @@ import android.content.Context;
|
|||
import androidx.annotation.NonNull;
|
||||
|
||||
import org.signal.core.util.logging.Log;
|
||||
import org.thoughtcrime.securesms.crypto.DatabaseSessionLock;
|
||||
import org.thoughtcrime.securesms.crypto.IdentityKeyUtil;
|
||||
import org.thoughtcrime.securesms.crypto.SessionUtil;
|
||||
import org.thoughtcrime.securesms.database.DatabaseFactory;
|
||||
|
@ -21,7 +20,6 @@ import org.whispersystems.libsignal.IdentityKeyPair;
|
|||
import org.whispersystems.libsignal.SignalProtocolAddress;
|
||||
import org.whispersystems.libsignal.state.IdentityKeyStore;
|
||||
import org.whispersystems.libsignal.util.guava.Optional;
|
||||
import org.whispersystems.signalservice.api.SignalSessionLock;
|
||||
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
|
@ -49,7 +47,7 @@ public class TextSecureIdentityKeyStore implements IdentityKeyStore {
|
|||
}
|
||||
|
||||
public @NonNull SaveResult saveIdentity(SignalProtocolAddress address, IdentityKey identityKey, boolean nonBlockingApproval) {
|
||||
try (SignalSessionLock.Lock unused = DatabaseSessionLock.INSTANCE.acquire()) {
|
||||
synchronized (LOCK) {
|
||||
IdentityDatabase identityDatabase = DatabaseFactory.getIdentityDatabase(context);
|
||||
RecipientId recipientId = RecipientId.fromExternalPush(address.getName());
|
||||
Optional<IdentityRecord> identityRecord = identityDatabase.getIdentity(recipientId);
|
||||
|
@ -96,7 +94,7 @@ public class TextSecureIdentityKeyStore implements IdentityKeyStore {
|
|||
|
||||
@Override
|
||||
public boolean isTrustedIdentity(SignalProtocolAddress address, IdentityKey identityKey, Direction direction) {
|
||||
try (SignalSessionLock.Lock unused = DatabaseSessionLock.INSTANCE.acquire()) {
|
||||
synchronized (LOCK) {
|
||||
if (DatabaseFactory.getRecipientDatabase(context).containsPhoneOrUuid(address.getName())) {
|
||||
IdentityDatabase identityDatabase = DatabaseFactory.getIdentityDatabase(context);
|
||||
RecipientId ourRecipientId = Recipient.self().getId();
|
||||
|
|
|
@ -5,14 +5,12 @@ import android.content.Context;
|
|||
import androidx.annotation.NonNull;
|
||||
|
||||
import org.signal.core.util.logging.Log;
|
||||
import org.thoughtcrime.securesms.crypto.DatabaseSessionLock;
|
||||
import org.thoughtcrime.securesms.database.DatabaseFactory;
|
||||
import org.whispersystems.libsignal.InvalidKeyIdException;
|
||||
import org.whispersystems.libsignal.state.PreKeyRecord;
|
||||
import org.whispersystems.libsignal.state.PreKeyStore;
|
||||
import org.whispersystems.libsignal.state.SignedPreKeyRecord;
|
||||
import org.whispersystems.libsignal.state.SignedPreKeyStore;
|
||||
import org.whispersystems.signalservice.api.SignalSessionLock;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
|
@ -21,6 +19,8 @@ public class TextSecurePreKeyStore implements PreKeyStore, SignedPreKeyStore {
|
|||
@SuppressWarnings("unused")
|
||||
private static final String TAG = Log.tag(TextSecurePreKeyStore.class);
|
||||
|
||||
private static final Object LOCK = new Object();
|
||||
|
||||
@NonNull
|
||||
private final Context context;
|
||||
|
||||
|
@ -30,7 +30,7 @@ public class TextSecurePreKeyStore implements PreKeyStore, SignedPreKeyStore {
|
|||
|
||||
@Override
|
||||
public PreKeyRecord loadPreKey(int preKeyId) throws InvalidKeyIdException {
|
||||
try (SignalSessionLock.Lock unused = DatabaseSessionLock.INSTANCE.acquire()) {
|
||||
synchronized (LOCK) {
|
||||
PreKeyRecord preKeyRecord = DatabaseFactory.getPreKeyDatabase(context).getPreKey(preKeyId);
|
||||
|
||||
if (preKeyRecord == null) throw new InvalidKeyIdException("No such key: " + preKeyId);
|
||||
|
@ -40,7 +40,7 @@ public class TextSecurePreKeyStore implements PreKeyStore, SignedPreKeyStore {
|
|||
|
||||
@Override
|
||||
public SignedPreKeyRecord loadSignedPreKey(int signedPreKeyId) throws InvalidKeyIdException {
|
||||
try (SignalSessionLock.Lock unused = DatabaseSessionLock.INSTANCE.acquire()) {
|
||||
synchronized (LOCK) {
|
||||
SignedPreKeyRecord signedPreKeyRecord = DatabaseFactory.getSignedPreKeyDatabase(context).getSignedPreKey(signedPreKeyId);
|
||||
|
||||
if (signedPreKeyRecord == null) throw new InvalidKeyIdException("No such signed prekey: " + signedPreKeyId);
|
||||
|
@ -50,21 +50,21 @@ public class TextSecurePreKeyStore implements PreKeyStore, SignedPreKeyStore {
|
|||
|
||||
@Override
|
||||
public List<SignedPreKeyRecord> loadSignedPreKeys() {
|
||||
try (SignalSessionLock.Lock unused = DatabaseSessionLock.INSTANCE.acquire()) {
|
||||
synchronized (LOCK) {
|
||||
return DatabaseFactory.getSignedPreKeyDatabase(context).getAllSignedPreKeys();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void storePreKey(int preKeyId, PreKeyRecord record) {
|
||||
try (SignalSessionLock.Lock unused = DatabaseSessionLock.INSTANCE.acquire()) {
|
||||
synchronized (LOCK) {
|
||||
DatabaseFactory.getPreKeyDatabase(context).insertPreKey(preKeyId, record);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void storeSignedPreKey(int signedPreKeyId, SignedPreKeyRecord record) {
|
||||
try (SignalSessionLock.Lock unused = DatabaseSessionLock.INSTANCE.acquire()) {
|
||||
synchronized (LOCK) {
|
||||
DatabaseFactory.getSignedPreKeyDatabase(context).insertSignedPreKey(signedPreKeyId, record);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -5,7 +5,6 @@ import android.content.Context;
|
|||
import androidx.annotation.NonNull;
|
||||
|
||||
import org.signal.core.util.logging.Log;
|
||||
import org.thoughtcrime.securesms.crypto.DatabaseSessionLock;
|
||||
import org.thoughtcrime.securesms.database.DatabaseFactory;
|
||||
import org.thoughtcrime.securesms.database.SessionDatabase;
|
||||
import org.thoughtcrime.securesms.database.SessionDatabase.RecipientDevice;
|
||||
|
@ -16,7 +15,6 @@ import org.whispersystems.libsignal.SignalProtocolAddress;
|
|||
import org.whispersystems.libsignal.protocol.CiphertextMessage;
|
||||
import org.whispersystems.libsignal.state.SessionRecord;
|
||||
import org.whispersystems.signalservice.api.SignalServiceSessionStore;
|
||||
import org.whispersystems.signalservice.api.SignalSessionLock;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
@ -26,6 +24,8 @@ public class TextSecureSessionStore implements SignalServiceSessionStore {
|
|||
|
||||
private static final String TAG = Log.tag(TextSecureSessionStore.class);
|
||||
|
||||
private static final Object LOCK = new Object();
|
||||
|
||||
@NonNull private final Context context;
|
||||
|
||||
public TextSecureSessionStore(@NonNull Context context) {
|
||||
|
@ -34,7 +34,7 @@ public class TextSecureSessionStore implements SignalServiceSessionStore {
|
|||
|
||||
@Override
|
||||
public SessionRecord loadSession(@NonNull SignalProtocolAddress address) {
|
||||
try (SignalSessionLock.Lock unused = DatabaseSessionLock.INSTANCE.acquire()) {
|
||||
synchronized (LOCK) {
|
||||
RecipientId recipientId = RecipientId.fromExternalPush(address.getName());
|
||||
SessionRecord sessionRecord = DatabaseFactory.getSessionDatabase(context).load(recipientId, address.getDeviceId());
|
||||
|
||||
|
@ -49,7 +49,7 @@ public class TextSecureSessionStore implements SignalServiceSessionStore {
|
|||
|
||||
@Override
|
||||
public List<SessionRecord> loadExistingSessions(List<SignalProtocolAddress> addresses) throws NoSessionException {
|
||||
try (SignalSessionLock.Lock unused = DatabaseSessionLock.INSTANCE.acquire()) {
|
||||
synchronized (LOCK) {
|
||||
List<RecipientDevice> ids = addresses.stream()
|
||||
.map(address -> new RecipientDevice(RecipientId.fromExternalPush(address.getName()), address.getDeviceId()))
|
||||
.collect(Collectors.toList());
|
||||
|
@ -68,7 +68,7 @@ public class TextSecureSessionStore implements SignalServiceSessionStore {
|
|||
|
||||
@Override
|
||||
public void storeSession(@NonNull SignalProtocolAddress address, @NonNull SessionRecord record) {
|
||||
try (SignalSessionLock.Lock unused = DatabaseSessionLock.INSTANCE.acquire()) {
|
||||
synchronized (LOCK) {
|
||||
RecipientId id = RecipientId.fromExternalPush(address.getName());
|
||||
DatabaseFactory.getSessionDatabase(context).store(id, address.getDeviceId(), record);
|
||||
}
|
||||
|
@ -76,7 +76,7 @@ public class TextSecureSessionStore implements SignalServiceSessionStore {
|
|||
|
||||
@Override
|
||||
public boolean containsSession(SignalProtocolAddress address) {
|
||||
try (SignalSessionLock.Lock unused = DatabaseSessionLock.INSTANCE.acquire()) {
|
||||
synchronized (LOCK) {
|
||||
if (DatabaseFactory.getRecipientDatabase(context).containsPhoneOrUuid(address.getName())) {
|
||||
RecipientId recipientId = RecipientId.fromExternalPush(address.getName());
|
||||
SessionRecord sessionRecord = DatabaseFactory.getSessionDatabase(context).load(recipientId, address.getDeviceId());
|
||||
|
@ -92,7 +92,7 @@ public class TextSecureSessionStore implements SignalServiceSessionStore {
|
|||
|
||||
@Override
|
||||
public void deleteSession(SignalProtocolAddress address) {
|
||||
try (SignalSessionLock.Lock unused = DatabaseSessionLock.INSTANCE.acquire()) {
|
||||
synchronized (LOCK) {
|
||||
if (DatabaseFactory.getRecipientDatabase(context).containsPhoneOrUuid(address.getName())) {
|
||||
RecipientId recipientId = RecipientId.fromExternalPush(address.getName());
|
||||
DatabaseFactory.getSessionDatabase(context).delete(recipientId, address.getDeviceId());
|
||||
|
@ -104,7 +104,7 @@ public class TextSecureSessionStore implements SignalServiceSessionStore {
|
|||
|
||||
@Override
|
||||
public void deleteAllSessions(String name) {
|
||||
try (SignalSessionLock.Lock unused = DatabaseSessionLock.INSTANCE.acquire()) {
|
||||
synchronized (LOCK) {
|
||||
if (DatabaseFactory.getRecipientDatabase(context).containsPhoneOrUuid(name)) {
|
||||
RecipientId recipientId = RecipientId.fromExternalPush(name);
|
||||
DatabaseFactory.getSessionDatabase(context).deleteAllFor(recipientId);
|
||||
|
@ -114,7 +114,7 @@ public class TextSecureSessionStore implements SignalServiceSessionStore {
|
|||
|
||||
@Override
|
||||
public List<Integer> getSubDeviceSessions(String name) {
|
||||
try (SignalSessionLock.Lock unused = DatabaseSessionLock.INSTANCE.acquire()) {
|
||||
synchronized (LOCK) {
|
||||
if (DatabaseFactory.getRecipientDatabase(context).containsPhoneOrUuid(name)) {
|
||||
RecipientId recipientId = RecipientId.fromExternalPush(name);
|
||||
return DatabaseFactory.getSessionDatabase(context).getSubDevices(recipientId);
|
||||
|
@ -127,7 +127,7 @@ public class TextSecureSessionStore implements SignalServiceSessionStore {
|
|||
|
||||
@Override
|
||||
public void archiveSession(SignalProtocolAddress address) {
|
||||
try (SignalSessionLock.Lock unused = DatabaseSessionLock.INSTANCE.acquire()) {
|
||||
synchronized (LOCK) {
|
||||
if (DatabaseFactory.getRecipientDatabase(context).containsPhoneOrUuid(address.getName())) {
|
||||
RecipientId recipientId = RecipientId.fromExternalPush(address.getName());
|
||||
archiveSession(recipientId, address.getDeviceId());
|
||||
|
@ -136,7 +136,7 @@ public class TextSecureSessionStore implements SignalServiceSessionStore {
|
|||
}
|
||||
|
||||
public void archiveSession(@NonNull RecipientId recipientId, int deviceId) {
|
||||
try (SignalSessionLock.Lock unused = DatabaseSessionLock.INSTANCE.acquire()) {
|
||||
synchronized (LOCK) {
|
||||
SessionRecord session = DatabaseFactory.getSessionDatabase(context).load(recipientId, deviceId);
|
||||
if (session != null) {
|
||||
session.archiveCurrentState();
|
||||
|
@ -146,7 +146,7 @@ public class TextSecureSessionStore implements SignalServiceSessionStore {
|
|||
}
|
||||
|
||||
public void archiveSiblingSessions(@NonNull SignalProtocolAddress address) {
|
||||
try (SignalSessionLock.Lock unused = DatabaseSessionLock.INSTANCE.acquire()) {
|
||||
synchronized (LOCK) {
|
||||
if (DatabaseFactory.getRecipientDatabase(context).containsPhoneOrUuid(address.getName())) {
|
||||
RecipientId recipientId = RecipientId.fromExternalPush(address.getName());
|
||||
List<SessionDatabase.SessionRow> sessions = DatabaseFactory.getSessionDatabase(context).getAllFor(recipientId);
|
||||
|
@ -164,7 +164,7 @@ public class TextSecureSessionStore implements SignalServiceSessionStore {
|
|||
}
|
||||
|
||||
public void archiveAllSessions() {
|
||||
try (SignalSessionLock.Lock unused = DatabaseSessionLock.INSTANCE.acquire()) {
|
||||
synchronized (LOCK) {
|
||||
List<SessionDatabase.SessionRow> sessions = DatabaseFactory.getSessionDatabase(context).getAll();
|
||||
|
||||
for (SessionDatabase.SessionRow row : sessions) {
|
||||
|
|
|
@ -10,7 +10,7 @@ import org.signal.core.util.logging.Log;
|
|||
import org.thoughtcrime.securesms.BuildConfig;
|
||||
import org.thoughtcrime.securesms.components.TypingStatusRepository;
|
||||
import org.thoughtcrime.securesms.components.TypingStatusSender;
|
||||
import org.thoughtcrime.securesms.crypto.DatabaseSessionLock;
|
||||
import org.thoughtcrime.securesms.crypto.ReentrantSessionLock;
|
||||
import org.thoughtcrime.securesms.crypto.storage.SignalProtocolStoreImpl;
|
||||
import org.thoughtcrime.securesms.database.DatabaseObserver;
|
||||
import org.thoughtcrime.securesms.database.JobDatabase;
|
||||
|
@ -109,7 +109,7 @@ public class ApplicationDependencyProvider implements ApplicationDependencies.Pr
|
|||
return new SignalServiceMessageSender(provideSignalServiceNetworkAccess().getConfiguration(context),
|
||||
new DynamicCredentialsProvider(context),
|
||||
new SignalProtocolStoreImpl(context),
|
||||
DatabaseSessionLock.INSTANCE,
|
||||
ReentrantSessionLock.INSTANCE,
|
||||
BuildConfig.SIGNAL_AGENT,
|
||||
TextSecurePreferences.isMultiDevice(context),
|
||||
Optional.fromNullable(IncomingMessageObserver.getPipe()),
|
||||
|
|
|
@ -8,53 +8,20 @@ import androidx.core.app.NotificationCompat;
|
|||
import androidx.core.app.NotificationManagerCompat;
|
||||
|
||||
import org.signal.core.util.logging.Log;
|
||||
import org.signal.libsignal.metadata.InvalidMetadataMessageException;
|
||||
import org.signal.libsignal.metadata.InvalidMetadataVersionException;
|
||||
import org.signal.libsignal.metadata.ProtocolDuplicateMessageException;
|
||||
import org.signal.libsignal.metadata.ProtocolException;
|
||||
import org.signal.libsignal.metadata.ProtocolInvalidKeyException;
|
||||
import org.signal.libsignal.metadata.ProtocolInvalidKeyIdException;
|
||||
import org.signal.libsignal.metadata.ProtocolInvalidMessageException;
|
||||
import org.signal.libsignal.metadata.ProtocolInvalidVersionException;
|
||||
import org.signal.libsignal.metadata.ProtocolLegacyMessageException;
|
||||
import org.signal.libsignal.metadata.ProtocolNoSessionException;
|
||||
import org.signal.libsignal.metadata.ProtocolUntrustedIdentityException;
|
||||
import org.signal.libsignal.metadata.SelfSendException;
|
||||
import org.thoughtcrime.securesms.MainActivity;
|
||||
import org.thoughtcrime.securesms.R;
|
||||
import org.thoughtcrime.securesms.crypto.IdentityKeyUtil;
|
||||
import org.thoughtcrime.securesms.crypto.UnidentifiedAccessUtil;
|
||||
import org.thoughtcrime.securesms.crypto.storage.SignalProtocolStoreImpl;
|
||||
import org.thoughtcrime.securesms.crypto.DatabaseSessionLock;
|
||||
import org.thoughtcrime.securesms.database.DatabaseFactory;
|
||||
import org.thoughtcrime.securesms.database.NoSuchMessageException;
|
||||
import org.thoughtcrime.securesms.database.PushDatabase;
|
||||
import org.thoughtcrime.securesms.dependencies.ApplicationDependencies;
|
||||
import org.thoughtcrime.securesms.groups.BadGroupIdException;
|
||||
import org.thoughtcrime.securesms.groups.GroupId;
|
||||
import org.thoughtcrime.securesms.jobmanager.Data;
|
||||
import org.thoughtcrime.securesms.jobmanager.Job;
|
||||
import org.thoughtcrime.securesms.jobmanager.JobManager;
|
||||
import org.thoughtcrime.securesms.messages.MessageContentProcessor;
|
||||
import org.thoughtcrime.securesms.messages.MessageContentProcessor.ExceptionMetadata;
|
||||
import org.thoughtcrime.securesms.messages.MessageContentProcessor.MessageState;
|
||||
import org.thoughtcrime.securesms.messages.MessageDecryptionUtil;
|
||||
import org.thoughtcrime.securesms.messages.MessageDecryptionUtil.DecryptionResult;
|
||||
import org.thoughtcrime.securesms.notifications.NotificationChannels;
|
||||
import org.thoughtcrime.securesms.recipients.Recipient;
|
||||
import org.thoughtcrime.securesms.transport.RetryLaterException;
|
||||
import org.thoughtcrime.securesms.util.GroupUtil;
|
||||
import org.thoughtcrime.securesms.util.TextSecurePreferences;
|
||||
import org.whispersystems.libsignal.state.SignalProtocolStore;
|
||||
import org.whispersystems.libsignal.util.guava.Optional;
|
||||
import org.whispersystems.signalservice.api.crypto.SignalServiceCipher;
|
||||
import org.whispersystems.signalservice.api.messages.SignalServiceContent;
|
||||
import org.whispersystems.signalservice.api.messages.SignalServiceEnvelope;
|
||||
import org.whispersystems.signalservice.api.push.SignalServiceAddress;
|
||||
import org.whispersystems.signalservice.internal.push.UnsupportedDataMessageException;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
|
||||
|
|
|
@ -7,13 +7,12 @@ import androidx.annotation.NonNull;
|
|||
import androidx.annotation.Nullable;
|
||||
|
||||
import org.signal.core.util.logging.Log;
|
||||
import org.thoughtcrime.securesms.crypto.DatabaseSessionLock;
|
||||
import org.thoughtcrime.securesms.crypto.ReentrantSessionLock;
|
||||
import org.thoughtcrime.securesms.crypto.IdentityKeyUtil;
|
||||
import org.thoughtcrime.securesms.database.DatabaseFactory;
|
||||
import org.thoughtcrime.securesms.database.GroupDatabase;
|
||||
import org.thoughtcrime.securesms.database.MessageDatabase.SyncMessageId;
|
||||
import org.thoughtcrime.securesms.database.MmsSmsDatabase;
|
||||
import org.thoughtcrime.securesms.database.PushDatabase;
|
||||
import org.thoughtcrime.securesms.dependencies.ApplicationDependencies;
|
||||
import org.thoughtcrime.securesms.groups.BadGroupIdException;
|
||||
import org.thoughtcrime.securesms.groups.GroupChangeBusyException;
|
||||
|
@ -25,7 +24,6 @@ import org.thoughtcrime.securesms.jobs.PushProcessMessageJob;
|
|||
import org.thoughtcrime.securesms.messages.MessageDecryptionUtil.DecryptionResult;
|
||||
import org.thoughtcrime.securesms.recipients.Recipient;
|
||||
import org.thoughtcrime.securesms.recipients.RecipientId;
|
||||
import org.thoughtcrime.securesms.util.FeatureFlags;
|
||||
import org.thoughtcrime.securesms.util.GroupUtil;
|
||||
import org.thoughtcrime.securesms.util.SetUtil;
|
||||
import org.thoughtcrime.securesms.util.Stopwatch;
|
||||
|
@ -123,12 +121,7 @@ public class IncomingMessageProcessor {
|
|||
|
||||
stopwatch.split("queue-check");
|
||||
|
||||
long ownerThreadId = DatabaseSessionLock.INSTANCE.getLikeyOwnerThreadId();
|
||||
if (ownerThreadId != DatabaseSessionLock.NO_OWNER && ownerThreadId != Thread.currentThread().getId()) {
|
||||
Log.i(TAG, "It is likely that some other thread has this lock. Owner: " + ownerThreadId + ", Us: " + Thread.currentThread().getId());
|
||||
}
|
||||
|
||||
try (SignalSessionLock.Lock unused = DatabaseSessionLock.INSTANCE.acquire()) {
|
||||
try (SignalSessionLock.Lock unused = ReentrantSessionLock.INSTANCE.acquire()) {
|
||||
Log.i(TAG, "Acquired lock while processing message " + envelope.getTimestamp() + ".");
|
||||
|
||||
DecryptionResult result = MessageDecryptionUtil.decrypt(context, envelope);
|
||||
|
|
|
@ -18,7 +18,7 @@ import org.signal.libsignal.metadata.ProtocolLegacyMessageException;
|
|||
import org.signal.libsignal.metadata.ProtocolNoSessionException;
|
||||
import org.signal.libsignal.metadata.ProtocolUntrustedIdentityException;
|
||||
import org.signal.libsignal.metadata.SelfSendException;
|
||||
import org.thoughtcrime.securesms.crypto.DatabaseSessionLock;
|
||||
import org.thoughtcrime.securesms.crypto.ReentrantSessionLock;
|
||||
import org.thoughtcrime.securesms.crypto.UnidentifiedAccessUtil;
|
||||
import org.thoughtcrime.securesms.crypto.storage.SignalProtocolStoreImpl;
|
||||
import org.thoughtcrime.securesms.database.DatabaseFactory;
|
||||
|
@ -68,7 +68,7 @@ public final class MessageDecryptionUtil {
|
|||
public static @NonNull DecryptionResult decrypt(@NonNull Context context, @NonNull SignalServiceEnvelope envelope) {
|
||||
SignalProtocolStore axolotlStore = new SignalProtocolStoreImpl(context);
|
||||
SignalServiceAddress localAddress = new SignalServiceAddress(Optional.of(TextSecurePreferences.getLocalUuid(context)), Optional.of(TextSecurePreferences.getLocalNumber(context)));
|
||||
SignalServiceCipher cipher = new SignalServiceCipher(localAddress, axolotlStore, DatabaseSessionLock.INSTANCE, UnidentifiedAccessUtil.getCertificateValidator());
|
||||
SignalServiceCipher cipher = new SignalServiceCipher(localAddress, axolotlStore, ReentrantSessionLock.INSTANCE, UnidentifiedAccessUtil.getCertificateValidator());
|
||||
List<Job> jobs = new LinkedList<>();
|
||||
|
||||
if (envelope.isPreKeySignalMessage()) {
|
||||
|
|
|
@ -9,7 +9,7 @@ import androidx.annotation.StringRes;
|
|||
import org.signal.core.util.concurrent.SignalExecutors;
|
||||
import org.signal.core.util.logging.Log;
|
||||
import org.thoughtcrime.securesms.R;
|
||||
import org.thoughtcrime.securesms.crypto.DatabaseSessionLock;
|
||||
import org.thoughtcrime.securesms.crypto.ReentrantSessionLock;
|
||||
import org.thoughtcrime.securesms.crypto.storage.TextSecureIdentityKeyStore;
|
||||
import org.thoughtcrime.securesms.crypto.storage.TextSecureSessionStore;
|
||||
import org.thoughtcrime.securesms.database.DatabaseFactory;
|
||||
|
@ -143,7 +143,7 @@ public final class IdentityUtil {
|
|||
}
|
||||
|
||||
public static void saveIdentity(Context context, String user, IdentityKey identityKey) {
|
||||
try(SignalSessionLock.Lock unused = DatabaseSessionLock.INSTANCE.acquire()) {
|
||||
try(SignalSessionLock.Lock unused = ReentrantSessionLock.INSTANCE.acquire()) {
|
||||
IdentityKeyStore identityKeyStore = new TextSecureIdentityKeyStore(context);
|
||||
SessionStore sessionStore = new TextSecureSessionStore(context);
|
||||
SignalProtocolAddress address = new SignalProtocolAddress(user, 1);
|
||||
|
@ -160,7 +160,7 @@ public final class IdentityUtil {
|
|||
}
|
||||
|
||||
public static void processVerifiedMessage(Context context, VerifiedMessage verifiedMessage) {
|
||||
try(SignalSessionLock.Lock unused = DatabaseSessionLock.INSTANCE.acquire()) {
|
||||
try(SignalSessionLock.Lock unused = ReentrantSessionLock.INSTANCE.acquire()) {
|
||||
IdentityDatabase identityDatabase = DatabaseFactory.getIdentityDatabase(context);
|
||||
Recipient recipient = Recipient.externalPush(context, verifiedMessage.getDestination());
|
||||
Optional<IdentityRecord> identityRecord = identityDatabase.getIdentity(recipient.getId());
|
||||
|
|
Ładowanie…
Reference in New Issue