Remove LOCK in OmemoManager and use Manager instance instead

This commit is contained in:
Florian Schmaus 2019-08-06 08:23:10 +02:00
parent d7b7abc7eb
commit 9923268391
4 changed files with 103 additions and 132 deletions

View File

@ -55,6 +55,7 @@ public class MessageEncryptionIntegrationTest extends AbstractTwoUsersOmemoInteg
* Bob still has B2
* @throws Exception
*/
@SuppressWarnings("SynchronizeOnNonFinalField")
@SmackIntegrationTest
public void messageTest() throws Exception {
OmemoBundleElement a1 = alice.getOmemoService().getOmemoStoreBackend().packOmemoBundle(alice.getOwnDevice());
@ -74,7 +75,7 @@ public class MessageEncryptionIntegrationTest extends AbstractTwoUsersOmemoInteg
OmemoBundleElement a1_ = alice.getOmemoService().getOmemoStoreBackend().packOmemoBundle(alice.getOwnDevice());
OmemoBundleElement b2;
synchronized (bob.LOCK) { // Circumvent race condition where bundle gets replenished after getting stored in b2
synchronized (bob) { // Circumvent race condition where bundle gets replenished after getting stored in b2
b2 = bob.getOmemoService().getOmemoStoreBackend().packOmemoBundle(bob.getOwnDevice());
}

View File

@ -31,6 +31,7 @@ public class SessionRenegotiationIntegrationTest extends AbstractTwoUsersOmemoIn
super(environment);
}
@SuppressWarnings("SynchronizeOnNonFinalField")
@SmackIntegrationTest
public void sessionRenegotiationTest() throws Exception {
@ -50,7 +51,7 @@ public class SessionRenegotiationIntegrationTest extends AbstractTwoUsersOmemoIn
bob.removeOmemoMessageListener(listener1);
// Remove the session on Bobs side.
synchronized (bob.LOCK) {
synchronized (bob) {
bob.getOmemoService().getOmemoStoreBackend().removeRawSession(bob.getOwnDevice(), alice.getOwnDevice());
}

View File

@ -97,7 +97,6 @@ public final class OmemoManager extends Manager {
private static final Logger LOGGER = Logger.getLogger(OmemoManager.class.getName());
private static final Integer UNKNOWN_DEVICE_ID = -1;
final Object LOCK = new Object();
private static final WeakHashMap<XMPPConnection, TreeMap<Integer, OmemoManager>> INSTANCES = new WeakHashMap<>();
private final OmemoService<?, ?, ?, ?, ?, ?, ?, ?, ?> service;
@ -237,11 +236,10 @@ public final class OmemoManager extends Manager {
* @throws PubSubException.NotALeafNodeException
* @throws IOException
*/
public void initialize()
public synchronized void initialize()
throws SmackException.NotLoggedInException, CorruptedOmemoKeyException, InterruptedException,
SmackException.NoResponseException, SmackException.NotConnectedException, XMPPException.XMPPErrorException,
PubSubException.NotALeafNodeException, IOException {
synchronized (LOCK) {
if (!connection().isAuthenticated()) {
throw new SmackException.NotLoggedInException();
}
@ -253,7 +251,6 @@ public final class OmemoManager extends Manager {
getOmemoService().init(new LoggedInOmemoManager(this));
ServiceDiscoveryManager.getInstanceFor(connection()).addFeature(PEP_NODE_DEVICE_LIST_NOTIFY);
}
}
/**
* Initialize the manager without blocking. Once the manager is successfully initialized, the finishedCallback will
@ -313,12 +310,10 @@ public final class OmemoManager extends Manager {
throws CryptoFailedException, UndecidedOmemoIdentityException,
InterruptedException, SmackException.NotConnectedException,
SmackException.NoResponseException, SmackException.NotLoggedInException, IOException {
synchronized (LOCK) {
Set<BareJid> recipients = new HashSet<>();
recipients.add(recipient);
return encrypt(recipients, message);
}
}
/**
* OMEMO encrypt a cleartext message for multiple recipients.
@ -334,11 +329,10 @@ public final class OmemoManager extends Manager {
* @throws SmackException.NotLoggedInException
* @throws IOException
*/
public OmemoMessage.Sent encrypt(Set<BareJid> recipients, String message)
public synchronized OmemoMessage.Sent encrypt(Set<BareJid> recipients, String message)
throws CryptoFailedException, UndecidedOmemoIdentityException,
InterruptedException, SmackException.NotConnectedException,
SmackException.NoResponseException, SmackException.NotLoggedInException, IOException {
synchronized (LOCK) {
LoggedInOmemoManager guard = new LoggedInOmemoManager(this);
Set<OmemoDevice> devices = getDevicesOf(getOwnJid());
for (BareJid recipient : recipients) {
@ -346,7 +340,6 @@ public final class OmemoManager extends Manager {
}
return service.createOmemoMessage(guard, devices, message);
}
}
/**
* Encrypt a message for all recipients in the MultiUserChat.
@ -364,12 +357,11 @@ public final class OmemoManager extends Manager {
* @throws SmackException.NotLoggedInException
* @throws IOException
*/
public OmemoMessage.Sent encrypt(MultiUserChat muc, String message)
public synchronized OmemoMessage.Sent encrypt(MultiUserChat muc, String message)
throws UndecidedOmemoIdentityException, CryptoFailedException,
XMPPException.XMPPErrorException, SmackException.NotConnectedException, InterruptedException,
SmackException.NoResponseException, NoOmemoSupportException,
SmackException.NotLoggedInException, IOException {
synchronized (LOCK) {
if (!multiUserChatSupportsOmemo(muc)) {
throw new NoOmemoSupportException();
}
@ -381,7 +373,6 @@ public final class OmemoManager extends Manager {
}
return encrypt(recipients, message);
}
}
/**
* Manually decrypt an OmemoElement.
@ -496,24 +487,21 @@ public final class OmemoManager extends Manager {
* @throws SmackException.NotConnectedException
* @throws IOException
*/
public void sendRatchetUpdateMessage(OmemoDevice recipient)
public synchronized void sendRatchetUpdateMessage(OmemoDevice recipient)
throws SmackException.NotLoggedInException, CorruptedOmemoKeyException, InterruptedException,
SmackException.NoResponseException, NoSuchAlgorithmException, SmackException.NotConnectedException,
CryptoFailedException, CannotEstablishOmemoSessionException, IOException {
synchronized (LOCK) {
Message message = new Message();
message.setFrom(getOwnJid());
message.setTo(recipient.getJid());
OmemoElement element = getOmemoService()
.createRatchetUpdateElement(new LoggedInOmemoManager(this), recipient);
OmemoElement element = getOmemoService().createRatchetUpdateElement(new LoggedInOmemoManager(this), recipient);
message.addExtension(element);
// Set MAM Storage hint
StoreHint.set(message);
connection().sendStanza(message);
}
}
/**
* Returns true, if the contact has any active devices published in a deviceList.
@ -527,14 +515,12 @@ public final class OmemoManager extends Manager {
* @throws XMPPException.XMPPErrorException
* @throws IOException
*/
public boolean contactSupportsOmemo(BareJid contact)
public synchronized boolean contactSupportsOmemo(BareJid contact)
throws InterruptedException, PubSubException.NotALeafNodeException, XMPPException.XMPPErrorException,
SmackException.NotConnectedException, SmackException.NoResponseException, IOException {
synchronized (LOCK) {
OmemoCachedDeviceList deviceList = getOmemoService().refreshDeviceList(connection(), getOwnDevice(), contact);
return !deviceList.getActiveDevices().isEmpty();
}
}
/**
* Returns true, if the MUC with the EntityBareJid multiUserChat is non-anonymous and members only (prerequisite
@ -581,16 +567,14 @@ public final class OmemoManager extends Manager {
* @throws CorruptedOmemoKeyException if our identityKey is corrupted.
* @throws IOException
*/
public OmemoFingerprint getOwnFingerprint()
public synchronized OmemoFingerprint getOwnFingerprint()
throws SmackException.NotLoggedInException, CorruptedOmemoKeyException, IOException {
synchronized (LOCK) {
if (getOwnJid() == null) {
throw new SmackException.NotLoggedInException();
}
return getOmemoService().getOmemoStoreBackend().getFingerprint(getOwnDevice());
}
}
/**
* Get the fingerprint of a contacts device.
@ -604,11 +588,10 @@ public final class OmemoManager extends Manager {
* @throws SmackException.NoResponseException
* @throws IOException
*/
public OmemoFingerprint getFingerprint(OmemoDevice device)
public synchronized OmemoFingerprint getFingerprint(OmemoDevice device)
throws CannotEstablishOmemoSessionException, SmackException.NotLoggedInException,
CorruptedOmemoKeyException, SmackException.NotConnectedException, InterruptedException,
SmackException.NoResponseException, IOException {
synchronized (LOCK) {
if (getOwnJid() == null) {
throw new SmackException.NotLoggedInException();
}
@ -617,8 +600,8 @@ public final class OmemoManager extends Manager {
return getOwnFingerprint();
}
return getOmemoService().getOmemoStoreBackend().getFingerprintAndMaybeBuildSession(new LoggedInOmemoManager(this), device);
}
return getOmemoService().getOmemoStoreBackend()
.getFingerprintAndMaybeBuildSession(new LoggedInOmemoManager(this), device);
}
/**
@ -635,18 +618,17 @@ public final class OmemoManager extends Manager {
* @throws SmackException.NoResponseException
* @throws IOException
*/
public HashMap<OmemoDevice, OmemoFingerprint> getActiveFingerprints(BareJid contact)
public synchronized HashMap<OmemoDevice, OmemoFingerprint> getActiveFingerprints(BareJid contact)
throws SmackException.NotLoggedInException, CorruptedOmemoKeyException,
CannotEstablishOmemoSessionException, SmackException.NotConnectedException, InterruptedException,
SmackException.NoResponseException, IOException {
synchronized (LOCK) {
if (getOwnJid() == null) {
throw new SmackException.NotLoggedInException();
}
HashMap<OmemoDevice, OmemoFingerprint> fingerprints = new HashMap<>();
OmemoCachedDeviceList deviceList = getOmemoService().getOmemoStoreBackend()
.loadCachedDeviceList(getOwnDevice(), contact);
OmemoCachedDeviceList deviceList = getOmemoService().getOmemoStoreBackend().loadCachedDeviceList(getOwnDevice(),
contact);
for (int id : deviceList.getActiveDevices()) {
OmemoDevice device = new OmemoDevice(contact, id);
@ -659,7 +641,6 @@ public final class OmemoManager extends Manager {
return fingerprints;
}
}
/**
* Add an OmemoMessageListener. This listener will be informed about incoming OMEMO messages
@ -707,13 +688,11 @@ public final class OmemoManager extends Manager {
* @throws SmackException.NoResponseException
* @throws IOException
*/
public void requestDeviceListUpdateFor(BareJid contact)
public synchronized void requestDeviceListUpdateFor(BareJid contact)
throws InterruptedException, PubSubException.NotALeafNodeException, XMPPException.XMPPErrorException,
SmackException.NotConnectedException, SmackException.NoResponseException, IOException {
synchronized (LOCK) {
getOmemoService().refreshDeviceList(connection(), getOwnDevice(), contact);
}
}
/**
* Publish a new device list with just our own deviceId in it.
@ -728,10 +707,8 @@ public final class OmemoManager extends Manager {
public void purgeDeviceList()
throws SmackException.NotLoggedInException, InterruptedException, XMPPException.XMPPErrorException,
SmackException.NotConnectedException, SmackException.NoResponseException, IOException {
synchronized (LOCK) {
getOmemoService().purgeDeviceList(new LoggedInOmemoManager(this));
}
}
/**
* Rotate the signedPreKey published in our OmemoBundle and republish it. This should be done every now and
@ -746,10 +723,9 @@ public final class OmemoManager extends Manager {
* @throws SmackException.NotLoggedInException
* @throws IOException
*/
public void rotateSignedPreKey()
public synchronized void rotateSignedPreKey()
throws CorruptedOmemoKeyException, SmackException.NotLoggedInException, XMPPException.XMPPErrorException,
SmackException.NotConnectedException, InterruptedException, SmackException.NoResponseException, IOException {
synchronized (LOCK) {
if (!connection().isAuthenticated()) {
throw new SmackException.NotLoggedInException();
}
@ -761,7 +737,6 @@ public final class OmemoManager extends Manager {
OmemoBundleElement bundle = getOmemoService().getOmemoStoreBackend().packOmemoBundle(getOwnDevice());
OmemoService.publishBundle(connection(), getOwnDevice(), bundle);
}
}
/**
* Return true, if the given Stanza contains an OMEMO element 'encrypted'.
@ -807,40 +782,34 @@ public final class OmemoManager extends Manager {
*
* @return deviceId
*/
public Integer getDeviceId() {
synchronized (LOCK) {
public synchronized Integer getDeviceId() {
return deviceId;
}
}
/**
* Return the OmemoDevice of the user.
*
* @return omemoDevice
*/
public OmemoDevice getOwnDevice() {
synchronized (LOCK) {
public synchronized OmemoDevice getOwnDevice() {
BareJid jid = getOwnJid();
if (jid == null) {
return null;
}
return new OmemoDevice(jid, getDeviceId());
}
}
/**
* Set the deviceId of the manager to nDeviceId.
* @param nDeviceId new deviceId
*/
void setDeviceId(int nDeviceId) {
synchronized (LOCK) {
synchronized void setDeviceId(int nDeviceId) {
// Move this instance inside the HashMaps
INSTANCES.get(connection()).remove(getDeviceId());
INSTANCES.get(connection()).put(nDeviceId, this);
this.deviceId = nDeviceId;
}
}
/**
* Notify all registered OmemoMessageListeners about a received OmemoMessage.

View File

@ -1075,7 +1075,7 @@ public abstract class OmemoService<T_IdKeyPair, T_IdKey, T_PreKey, T_SigPreKey,
OmemoManager.LoggedInOmemoManager managerGuard) throws IOException {
OmemoManager manager = managerGuard.get();
// Avoid the ratchet being manipulated and the bundle being published multiple times simultaneously
synchronized (manager.LOCK) {
synchronized (manager) {
OmemoDevice userDevice = manager.getOwnDevice();
OmemoElement element = carbonCopy.getExtension(OmemoElement.NAME_ENCRYPTED, OmemoElement_VAxolotl.NAMESPACE);
if (element == null) {
@ -1130,7 +1130,7 @@ public abstract class OmemoService<T_IdKeyPair, T_IdKey, T_PreKey, T_SigPreKey,
public void onOmemoMessageStanzaReceived(Stanza stanza, OmemoManager.LoggedInOmemoManager managerGuard) throws IOException {
OmemoManager manager = managerGuard.get();
// Avoid the ratchet being manipulated and the bundle being published multiple times simultaneously
synchronized (manager.LOCK) {
synchronized (manager) {
OmemoDevice userDevice = manager.getOwnDevice();
OmemoElement element = stanza.getExtension(OmemoElement.NAME_ENCRYPTED, OmemoElement_VAxolotl.NAMESPACE);
if (element == null) {
@ -1219,7 +1219,7 @@ public abstract class OmemoService<T_IdKeyPair, T_IdKey, T_PreKey, T_SigPreKey,
OmemoMessage.Received decryptStanza(Stanza stanza, OmemoManager.LoggedInOmemoManager managerGuard) throws IOException {
OmemoManager manager = managerGuard.get();
// Avoid the ratchet being manipulated and the bundle being published multiple times simultaneously
synchronized (manager.LOCK) {
synchronized (manager) {
OmemoDevice userDevice = manager.getOwnDevice();
OmemoElement element = stanza.getExtension(OmemoElement.NAME_ENCRYPTED, OmemoElement_VAxolotl.NAMESPACE);
if (element == null) {