Add usermethod for postponing prekey deletion to OmemoManager

This commit is contained in:
Paul Schaub 2018-12-04 15:51:38 +01:00
parent 45574e6bbb
commit a0838b99cd
Signed by: vanitasvitae
GPG Key ID: 62BEE9264BF17311
2 changed files with 84 additions and 2 deletions

View File

@ -30,6 +30,8 @@ import java.util.Set;
import java.util.SortedSet;
import java.util.TreeMap;
import java.util.WeakHashMap;
import java.util.concurrent.ScheduledFuture;
import java.util.concurrent.TimeUnit;
import java.util.logging.Level;
import java.util.logging.Logger;
@ -272,6 +274,54 @@ public final class OmemoManager extends Manager {
});
}
/**
* Temporarily postpone the deletion of used PreKeys for {@code millis} milliseconds.
* During that period, used preKeys will not be deleted immediately, but rather queued for later deletion.
* Once the time period has past, queued preKeys are deleted and normal behaviour is resumed.
*
* Recommended values for {@code millis} are around 1000 * 60 * 3.
*
* @param millis period in milliseconds from now, in which preKeys are not deleted immediately.
*/
public void temporarilyPostponePreKeyDeletion(long millis) {
final OmemoStore<?,?,?,?,?,?,?,?,?> store = getOmemoService().getOmemoStoreBackend();
final OmemoDevice userDevice = getOwnDevice();
if (userDevice == null) {
throw new IllegalStateException("No OmemoDevice has been determined yet. OmemoManager needs to be initialized.");
}
store.postponePreKeyDeletion(userDevice);
ScheduledFuture<?> result = schedule(new Runnable() {
@Override
public void run() {
Async.go(new Runnable() {
@Override
public void run() {
// Delete any queued preKeys and resume default deletion behaviour
store.resumePreKeyDeletion(userDevice);
// Count preKeys and generate new ones
int preKeyCount = store.loadOmemoPreKeys(userDevice).size();
try {
store.replenishKeys(userDevice);
// If necessary, publish new bundle
if (preKeyCount != store.loadOmemoPreKeys(userDevice).size()) {
OmemoBundleElement bundle = store.packOmemoBundle(userDevice);
OmemoService.publishBundle(getConnection(), userDevice, bundle);
}
} catch (CorruptedOmemoKeyException e) {
LOGGER.log(Level.SEVERE, "Omemo IdentityKey seems to be corrupted for " + userDevice, e);
} catch (InterruptedException | SmackException.NoResponseException | XMPPException.XMPPErrorException | SmackException.NotConnectedException e) {
LOGGER.log(Level.SEVERE, "Exception while publishing OMEMO bundle.", e);
}
}
});
}
}, millis, TimeUnit.MILLISECONDS);
}
/**
* Return a set of all OMEMO capable devices of a contact.
* Note, that this method does not explicitly refresh the device list of the contact, so it might be outdated.

View File

@ -129,6 +129,14 @@ public abstract class OmemoStore<T_IdKeyPair, T_IdKey, T_PreKey, T_SigPreKey, T_
return cached;
}
/**
* Return true, if we are currently postponing deletion of preKeys for messages that are addressed to
* {@code userDevice}. In such case, used preKeys are not deleted immediately, but instead are queued for later
* deletion.
*
* @param userDevice our device
* @return true if prekey deletion is postponed, false if prekeys are deleted immediately
*/
public boolean isPostponingPreKeyDeletion(OmemoDevice userDevice) {
synchronized (postponePreKeyDeletion) {
Boolean postpone = postponePreKeyDeletion.get(userDevice);
@ -140,12 +148,23 @@ public abstract class OmemoStore<T_IdKeyPair, T_IdKey, T_PreKey, T_SigPreKey, T_
}
}
/**
* Postpone preKey deletion for now. Used preKeys are queued for deletion at a later point in time.
*
* @param userDevice our device
*/
public void postponePreKeyDeletion(OmemoDevice userDevice) {
LOGGER.log(Level.INFO, "Postponing prekey deletion for " + userDevice);
synchronized (postponePreKeyDeletion) {
postponePreKeyDeletion.put(userDevice, Boolean.TRUE);
}
}
/**
* Resume immediate preKey deletion. This immediately deletes all preKeys which have been queued for deletion.
*
* @param userDevice our device
*/
public void resumePreKeyDeletion(OmemoDevice userDevice) {
synchronized (postponePreKeyDeletion) {
postponePreKeyDeletion.put(userDevice, Boolean.FALSE);
@ -153,15 +172,28 @@ public abstract class OmemoStore<T_IdKeyPair, T_IdKey, T_PreKey, T_SigPreKey, T_
}
}
public void queuePreKeyForDeletion(OmemoDevice userDevice, int deviceId) {
/**
* Queue a used preKey for later deletion. The key is not deleted immediately, but marked as "to be deleted".
* Deletion takes place, once {@link #deleteQueuedPreKeys(OmemoDevice)} is called (for example via
* {@link #resumePreKeyDeletion(OmemoDevice)}).
*
* @param userDevice our device
* @param preKeyId id of the preKey which will be queued for later deletion
*/
public void queuePreKeyForDeletion(OmemoDevice userDevice, int preKeyId) {
Set<Integer> preKeyIds = preKeyDeletionQueues.get(userDevice);
if (preKeyIds == null) {
preKeyIds = new HashSet<>();
preKeyDeletionQueues.put(userDevice, preKeyIds);
}
preKeyIds.add(deviceId);
preKeyIds.add(preKeyId);
}
/**
* Delete all preKeys which have been queued for deletion via {@link #queuePreKeyForDeletion(OmemoDevice, int)}.
*
* @param userDevice our device
*/
public void deleteQueuedPreKeys(OmemoDevice userDevice) {
Set<Integer> queuedPreKeys = preKeyDeletionQueues.get(userDevice);
if (queuedPreKeys == null) {