From: AsamK Date: Wed, 21 Apr 2021 16:06:48 +0000 (+0200) Subject: Store messages in cache by recipient id X-Git-Tag: v0.8.2~43 X-Git-Url: https://git.nmode.ca/signal-cli/commitdiff_plain/2ef59d692ae92615105c6aa2603677a3fa584200?ds=sidebyside Store messages in cache by recipient id --- diff --git a/lib/src/main/java/org/asamk/signal/manager/Manager.java b/lib/src/main/java/org/asamk/signal/manager/Manager.java index a8eaa9ab..60263dd9 100644 --- a/lib/src/main/java/org/asamk/signal/manager/Manager.java +++ b/lib/src/main/java/org/asamk/signal/manager/Manager.java @@ -1629,6 +1629,15 @@ public class Manager implements Closeable { try { content = decryptMessage(envelope); } catch (org.whispersystems.libsignal.UntrustedIdentityException e) { + if (!envelope.hasSource()) { + final var recipientId = resolveRecipient(((org.whispersystems.libsignal.UntrustedIdentityException) e) + .getName()); + try { + account.getMessageCache().replaceSender(cachedMessage, recipientId); + } catch (IOException ioException) { + logger.warn("Failed to move cached message to recipient folder: {}", ioException.getMessage()); + } + } return; } catch (Exception er) { // All other errors are not recoverable, so delete the cached message @@ -1671,8 +1680,11 @@ public class Manager implements Closeable { final CachedMessage[] cachedMessage = {null}; try { var result = messagePipe.readOrEmpty(timeout, unit, envelope1 -> { + final var recipientId = envelope1.hasSource() + ? resolveRecipient(envelope1.getSourceIdentifier()) + : null; // store message on disk, before acknowledging receipt to the server - cachedMessage[0] = account.getMessageCache().cacheMessage(envelope1); + cachedMessage[0] = account.getMessageCache().cacheMessage(envelope1, recipientId); }); if (result.isPresent()) { envelope = result.get(); @@ -1703,8 +1715,7 @@ public class Manager implements Closeable { if (envelope.hasSource()) { // Store uuid if we don't have it already - var source = envelope.getSourceAddress(); - resolveSignalServiceAddress(source); + resolveRecipientTrusted(envelope.getSourceAddress()); } if (!envelope.isReceipt()) { try { @@ -1736,8 +1747,19 @@ public class Manager implements Closeable { } else { handler.handleMessage(envelope, content, exception); } - if (!(exception instanceof org.whispersystems.libsignal.UntrustedIdentityException)) { - if (cachedMessage[0] != null) { + if (cachedMessage[0] != null) { + if (exception instanceof org.whispersystems.libsignal.UntrustedIdentityException) { + if (!envelope.hasSource()) { + final var recipientId = resolveRecipient(((org.whispersystems.libsignal.UntrustedIdentityException) exception) + .getName()); + try { + cachedMessage[0] = account.getMessageCache().replaceSender(cachedMessage[0], recipientId); + } catch (IOException ioException) { + logger.warn("Failed to move cached message to recipient folder: {}", + ioException.getMessage()); + } + } + } else { cachedMessage[0].delete(); } } @@ -2461,7 +2483,12 @@ public class Manager implements Closeable { var canonicalizedNumber = UuidUtil.isUuid(identifier) ? identifier : PhoneNumberFormatter.formatNumber(identifier, account.getUsername()); - var address = Utils.getSignalServiceAddressFromIdentifier(canonicalizedNumber); + + return resolveRecipient(canonicalizedNumber); + } + + private RecipientId resolveRecipient(final String identifier) { + var address = Utils.getSignalServiceAddressFromIdentifier(identifier); return resolveRecipient(address); } diff --git a/lib/src/main/java/org/asamk/signal/manager/storage/SignalAccount.java b/lib/src/main/java/org/asamk/signal/manager/storage/SignalAccount.java index b1b888cc..9aa283a2 100644 --- a/lib/src/main/java/org/asamk/signal/manager/storage/SignalAccount.java +++ b/lib/src/main/java/org/asamk/signal/manager/storage/SignalAccount.java @@ -244,6 +244,7 @@ public class SignalAccount implements Closeable { private void mergeRecipients(RecipientId recipientId, RecipientId toBeMergedRecipientId) { sessionStore.mergeRecipients(recipientId, toBeMergedRecipientId); identityKeyStore.mergeRecipients(recipientId, toBeMergedRecipientId); + messageCache.mergeRecipients(recipientId, toBeMergedRecipientId); } public static File getFileName(File dataPath, String username) { diff --git a/lib/src/main/java/org/asamk/signal/manager/storage/messageCache/CachedMessage.java b/lib/src/main/java/org/asamk/signal/manager/storage/messageCache/CachedMessage.java index 404153b3..941c4fa9 100644 --- a/lib/src/main/java/org/asamk/signal/manager/storage/messageCache/CachedMessage.java +++ b/lib/src/main/java/org/asamk/signal/manager/storage/messageCache/CachedMessage.java @@ -19,6 +19,10 @@ public final class CachedMessage { this.file = file; } + File getFile() { + return file; + } + public SignalServiceEnvelope loadEnvelope() { try { return MessageCacheUtils.loadEnvelope(file); @@ -34,5 +38,10 @@ public final class CachedMessage { } catch (IOException e) { logger.warn("Failed to delete cached message file “{}”, ignoring: {}", file, e.getMessage()); } + // Delete parent directory, if empty + try { + Files.delete(file.toPath().getParent()); + } catch (IOException ignored) { + } } } diff --git a/lib/src/main/java/org/asamk/signal/manager/storage/messageCache/MessageCache.java b/lib/src/main/java/org/asamk/signal/manager/storage/messageCache/MessageCache.java index 6d604300..76e402ad 100644 --- a/lib/src/main/java/org/asamk/signal/manager/storage/messageCache/MessageCache.java +++ b/lib/src/main/java/org/asamk/signal/manager/storage/messageCache/MessageCache.java @@ -1,5 +1,6 @@ package org.asamk.signal.manager.storage.messageCache; +import org.asamk.signal.manager.storage.recipients.RecipientId; import org.asamk.signal.manager.util.IOUtils; import org.asamk.signal.manager.util.MessageCacheUtils; import org.slf4j.Logger; @@ -49,12 +50,11 @@ public class MessageCache { }).map(CachedMessage::new).collect(Collectors.toList()); } - public CachedMessage cacheMessage(SignalServiceEnvelope envelope) { + public CachedMessage cacheMessage(SignalServiceEnvelope envelope, RecipientId recipientId) { final var now = new Date().getTime(); - final var source = envelope.hasSource() ? envelope.getSourceAddress().getLegacyIdentifier() : ""; try { - var cacheFile = getMessageCacheFile(source, now, envelope.getTimestamp()); + var cacheFile = getMessageCacheFile(recipientId, now, envelope.getTimestamp()); MessageCacheUtils.storeEnvelope(envelope, cacheFile); return new CachedMessage(cacheFile); } catch (IOException e) { @@ -63,17 +63,53 @@ public class MessageCache { } } - private File getMessageCachePath(String sender) { - if (sender == null || sender.isEmpty()) { + public CachedMessage replaceSender(CachedMessage cachedMessage, RecipientId sender) throws IOException { + final var cacheFile = getMessageCacheFile(sender, cachedMessage.getFile().getName()); + if (cacheFile.equals(cachedMessage.getFile())) { + return cachedMessage; + } + Files.move(cachedMessage.getFile().toPath(), cacheFile.toPath()); + return new CachedMessage(cacheFile); + } + + private File getMessageCachePath(RecipientId recipientId) { + if (recipientId == null) { return messageCachePath; } + var sender = String.valueOf(recipientId.getId()); return new File(messageCachePath, sender.replace("/", "_")); } - private File getMessageCacheFile(String sender, long now, long timestamp) throws IOException { - var cachePath = getMessageCachePath(sender); + private File getMessageCacheFile(RecipientId recipientId, String filename) throws IOException { + var cachePath = getMessageCachePath(recipientId); + IOUtils.createPrivateDirectories(cachePath); + return new File(cachePath, filename); + } + + private File getMessageCacheFile(RecipientId recipientId, long now, long timestamp) throws IOException { + var cachePath = getMessageCachePath(recipientId); IOUtils.createPrivateDirectories(cachePath); return new File(cachePath, now + "_" + timestamp); } + + public void mergeRecipients(final RecipientId recipientId, final RecipientId toBeMergedRecipientId) { + final var toBeMergedMessageCachePath = getMessageCachePath(toBeMergedRecipientId); + if (!toBeMergedMessageCachePath.exists()) { + return; + } + + for (var file : Objects.requireNonNull(toBeMergedMessageCachePath.listFiles())) { + if (!file.isFile()) { + continue; + } + + try { + final var cacheFile = getMessageCacheFile(recipientId, file.getName()); + Files.move(file.toPath(), cacheFile.toPath()); + } catch (IOException e) { + logger.warn("Failed to move cache file “{}”, ignoring: {}", file, e.getMessage()); + } + } + } }