From c8b9ab1911f1941c65795733fcd3ad6304d9682d Mon Sep 17 00:00:00 2001 From: AsamK Date: Sun, 5 Dec 2021 12:00:31 +0100 Subject: [PATCH 01/16] Improve handling of unregistered account --- .../org/asamk/signal/manager/ManagerImpl.java | 36 ++++++++++++++++--- 1 file changed, 32 insertions(+), 4 deletions(-) diff --git a/lib/src/main/java/org/asamk/signal/manager/ManagerImpl.java b/lib/src/main/java/org/asamk/signal/manager/ManagerImpl.java index 269edb3b..87d3d0d0 100644 --- a/lib/src/main/java/org/asamk/signal/manager/ManagerImpl.java +++ b/lib/src/main/java/org/asamk/signal/manager/ManagerImpl.java @@ -77,9 +77,11 @@ import org.whispersystems.signalservice.api.messages.SignalServiceReceiptMessage import org.whispersystems.signalservice.api.messages.SignalServiceTypingMessage; import org.whispersystems.signalservice.api.push.ACI; import org.whispersystems.signalservice.api.push.SignalServiceAddress; +import org.whispersystems.signalservice.api.push.exceptions.AuthorizationFailedException; import org.whispersystems.signalservice.api.util.DeviceNameUtil; import org.whispersystems.signalservice.api.util.InvalidNumberException; import org.whispersystems.signalservice.api.util.PhoneNumberFormatter; +import org.whispersystems.signalservice.api.websocket.WebSocketConnectionState; import org.whispersystems.signalservice.api.websocket.WebSocketUnavailableException; import org.whispersystems.signalservice.internal.contacts.crypto.Quote; import org.whispersystems.signalservice.internal.contacts.crypto.UnauthenticatedQuoteException; @@ -111,6 +113,9 @@ import java.util.concurrent.locks.ReentrantLock; import java.util.stream.Collectors; import java.util.stream.Stream; +import io.reactivex.rxjava3.core.Observable; +import io.reactivex.rxjava3.schedulers.Schedulers; + import static org.asamk.signal.manager.config.ServiceConfig.capabilities; public class ManagerImpl implements Manager { @@ -267,11 +272,16 @@ public class ManagerImpl implements Manager { days); } } - preKeyHelper.refreshPreKeysIfNecessary(); - if (account.getAci() == null) { - account.setAci(dependencies.getAccountManager().getOwnAci()); + try { + preKeyHelper.refreshPreKeysIfNecessary(); + if (account.getAci() == null) { + account.setAci(dependencies.getAccountManager().getOwnAci()); + } + updateAccountAttributes(null); + } catch (AuthorizationFailedException e) { + account.setRegistered(false); + throw e; } - updateAccountAttributes(null); } /** @@ -1096,6 +1106,12 @@ public class ManagerImpl implements Manager { Map queuedActions = new HashMap<>(); final var signalWebSocket = dependencies.getSignalWebSocket(); + final var webSocketStateDisposable = Observable.merge(signalWebSocket.getUnidentifiedWebSocketState(), + signalWebSocket.getWebSocketState()) + .subscribeOn(Schedulers.computation()) + .observeOn(Schedulers.computation()) + .distinctUntilChanged() + .subscribe(this::onWebSocketStateChange); signalWebSocket.connect(); hasCaughtUpWithOldMessages = false; @@ -1201,6 +1217,18 @@ public class ManagerImpl implements Manager { handleQueuedActions(queuedActions.keySet()); queuedActions.clear(); dependencies.getSignalWebSocket().disconnect(); + webSocketStateDisposable.dispose(); + } + + private void onWebSocketStateChange(final WebSocketConnectionState s) { + if (s.equals(WebSocketConnectionState.AUTHENTICATION_FAILED)) { + account.setRegistered(false); + try { + close(); + } catch (IOException e) { + e.printStackTrace(); + } + } } @Override -- 2.51.0 From 6c1013b02442c9e3d95d471aeaeabeaf62c32269 Mon Sep 17 00:00:00 2001 From: AsamK Date: Sun, 5 Dec 2021 12:00:49 +0100 Subject: [PATCH 02/16] Improve error message when an account is already in use --- .../java/org/asamk/signal/dbus/DbusSignalControlImpl.java | 5 +++++ .../asamk/signal/jsonrpc/SignalJsonRpcDispatcherHandler.java | 4 ++++ 2 files changed, 9 insertions(+) diff --git a/src/main/java/org/asamk/signal/dbus/DbusSignalControlImpl.java b/src/main/java/org/asamk/signal/dbus/DbusSignalControlImpl.java index 2e9ae08b..dc23fed9 100644 --- a/src/main/java/org/asamk/signal/dbus/DbusSignalControlImpl.java +++ b/src/main/java/org/asamk/signal/dbus/DbusSignalControlImpl.java @@ -15,6 +15,7 @@ import org.freedesktop.dbus.DBusPath; import java.io.IOException; import java.net.URI; +import java.nio.channels.OverlappingFileLockException; import java.util.List; import java.util.concurrent.TimeoutException; import java.util.stream.Collectors; @@ -60,6 +61,8 @@ public class DbusSignalControlImpl implements org.asamk.SignalControl { } catch (CaptchaRequiredException e) { String message = captcha == null ? "Captcha required for verification." : "Invalid captcha given."; throw new SignalControl.Error.RequiresCaptcha(message); + } catch (OverlappingFileLockException e) { + throw new SignalControl.Error.Failure("Account is already in use"); } catch (IOException e) { throw new SignalControl.Error.Failure(e.getClass().getSimpleName() + " " + e.getMessage()); } @@ -76,6 +79,8 @@ public class DbusSignalControlImpl implements org.asamk.SignalControl { ) throws Error.Failure, Error.InvalidNumber { try (final RegistrationManager registrationManager = c.getNewRegistrationManager(number)) { registrationManager.verifyAccount(verificationCode, pin); + } catch (OverlappingFileLockException e) { + throw new SignalControl.Error.Failure("Account is already in use"); } catch (IOException | PinLockedException | IncorrectPinException e) { throw new SignalControl.Error.Failure(e.getClass().getSimpleName() + " " + e.getMessage()); } diff --git a/src/main/java/org/asamk/signal/jsonrpc/SignalJsonRpcDispatcherHandler.java b/src/main/java/org/asamk/signal/jsonrpc/SignalJsonRpcDispatcherHandler.java index 23c89f26..8d13ad28 100644 --- a/src/main/java/org/asamk/signal/jsonrpc/SignalJsonRpcDispatcherHandler.java +++ b/src/main/java/org/asamk/signal/jsonrpc/SignalJsonRpcDispatcherHandler.java @@ -27,6 +27,7 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; import java.io.IOException; +import java.nio.channels.OverlappingFileLockException; import java.util.HashMap; import java.util.Map; import java.util.Objects; @@ -182,6 +183,9 @@ public class SignalJsonRpcDispatcherHandler { final var registrationManager = c.getNewRegistrationManager(params.get("account").asText()); ((ObjectNode) params).remove("account"); return registrationManager; + } catch (OverlappingFileLockException e) { + logger.warn("Account is already in use"); + return null; } catch (IOException | IllegalStateException e) { logger.warn("Failed to load registration manager", e); return null; -- 2.51.0 From 124d10d6f86fb516c771b7a1162d507d1de2858f Mon Sep 17 00:00:00 2001 From: AsamK Date: Sun, 5 Dec 2021 12:01:12 +0100 Subject: [PATCH 03/16] Fix issue when loading a legacy account file without aci --- .../java/org/asamk/signal/manager/storage/SignalAccount.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) 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 343814b9..c5f659fa 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 @@ -532,7 +532,7 @@ public class SignalAccount implements Closeable { if (legacyRecipientStore != null) { recipientStore.resolveRecipientsTrusted(legacyRecipientStore.getAddresses()); } - recipientStore.resolveRecipientTrusted(getSelfAddress()); + getSelfRecipientId(); migrated = true; } -- 2.51.0 From 32c2fae2f7561972bcd5bf16a41397ec1b15be49 Mon Sep 17 00:00:00 2001 From: AsamK Date: Sun, 5 Dec 2021 12:34:29 +0100 Subject: [PATCH 04/16] Update reflect-config.json --- graalvm-config-dir/reflect-config.json | 46 ++++++++++++++++++++++++++ 1 file changed, 46 insertions(+) diff --git a/graalvm-config-dir/reflect-config.json b/graalvm-config-dir/reflect-config.json index 94182c11..a6d83165 100644 --- a/graalvm-config-dir/reflect-config.json +++ b/graalvm-config-dir/reflect-config.json @@ -254,6 +254,12 @@ "name":"java.util.Locale", "methods":[{"name":"getUnicodeLocaleType","parameterTypes":["java.lang.String"] }]} , +{ + "name":"java.util.Optional", + "allDeclaredFields":true, + "queryAllDeclaredMethods":true, + "queryAllDeclaredConstructors":true} +, { "name":"java.util.RandomAccess", "allDeclaredMethods":true} @@ -698,6 +704,12 @@ {"name":"unidentifiedDeliveryIndicators","parameterTypes":[] } ]} , +{ + "name":"org.asamk.signal.manager.storage.contacts.LegacyContactInfo", + "allDeclaredFields":true, + "queryAllDeclaredMethods":true, + "queryAllDeclaredConstructors":true} +, { "name":"org.asamk.signal.manager.storage.contacts.LegacyJsonContactsStore", "allDeclaredFields":true, @@ -732,6 +744,17 @@ "allDeclaredMethods":true, "allDeclaredConstructors":true} , +{ + "name":"org.asamk.signal.manager.storage.groups.GroupStore$Storage$GroupV1$JsonRecipientAddress", + "allDeclaredFields":true, + "queryAllDeclaredMethods":true, + "queryAllDeclaredConstructors":true, + "methods":[ + {"name":"","parameterTypes":["java.lang.String","java.lang.String"] }, + {"name":"number","parameterTypes":[] }, + {"name":"uuid","parameterTypes":[] } + ]} +, { "name":"org.asamk.signal.manager.storage.groups.GroupStore$Storage$GroupV1$MembersDeserializer", "methods":[{"name":"","parameterTypes":[] }]} @@ -820,6 +843,12 @@ "name":"org.asamk.signal.manager.storage.recipients.LegacyRecipientStore$RecipientStoreDeserializer", "methods":[{"name":"","parameterTypes":[] }]} , +{ + "name":"org.asamk.signal.manager.storage.recipients.RecipientAddress", + "allDeclaredFields":true, + "queryAllDeclaredMethods":true, + "queryAllDeclaredConstructors":true} +, { "name":"org.asamk.signal.manager.storage.recipients.RecipientStore$Storage", "allDeclaredFields":true, @@ -1604,6 +1633,23 @@ "name":"org.signal.storageservice.protos.groups.local.DecryptedTimer", "fields":[{"name":"duration_"}]} , +{ + "name":"org.signal.zkgroup.internal.ByteArray", + "allDeclaredFields":true, + "queryAllDeclaredMethods":true} +, +{ + "name":"org.signal.zkgroup.profiles.ProfileKey", + "allDeclaredFields":true, + "queryAllDeclaredMethods":true, + "queryAllDeclaredConstructors":true} +, +{ + "name":"org.signal.zkgroup.profiles.ProfileKeyCredential", + "allDeclaredFields":true, + "queryAllDeclaredMethods":true, + "queryAllDeclaredConstructors":true} +, { "name":"org.whispersystems.libsignal.state.IdentityKeyStore", "allDeclaredMethods":true} -- 2.51.0 From a5013dd08db9768d59c9125df5f64657c24940c0 Mon Sep 17 00:00:00 2001 From: AsamK Date: Sun, 5 Dec 2021 15:32:28 +0100 Subject: [PATCH 05/16] Close account if user is not registered --- lib/src/main/java/org/asamk/signal/manager/Manager.java | 1 + 1 file changed, 1 insertion(+) 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 c9f2bad1..81c2eeb7 100644 --- a/lib/src/main/java/org/asamk/signal/manager/Manager.java +++ b/lib/src/main/java/org/asamk/signal/manager/Manager.java @@ -60,6 +60,7 @@ public interface Manager extends Closeable { var account = SignalAccount.load(pathConfig.dataPath(), number, true, trustNewIdentity); if (!account.isRegistered()) { + account.close(); throw new NotRegisteredException(); } -- 2.51.0 From 16bf7af297910f8c7bc5bea3e28c8d0479c95f0c Mon Sep 17 00:00:00 2001 From: AsamK Date: Sun, 5 Dec 2021 14:41:13 +0100 Subject: [PATCH 06/16] Remove jackson from lib's api --- build.gradle.kts | 9 +++++---- lib/build.gradle.kts | 10 +++++----- 2 files changed, 10 insertions(+), 9 deletions(-) diff --git a/build.gradle.kts b/build.gradle.kts index f5d5150a..c9521e72 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -36,10 +36,11 @@ repositories { } dependencies { - implementation("org.bouncycastle:bcprov-jdk15on:1.69") - implementation("net.sourceforge.argparse4j:argparse4j:0.9.0") - implementation("com.github.hypfvieh:dbus-java-transport-native-unixsocket:4.0.0-beta") - implementation("org.slf4j:slf4j-simple:1.7.32") + implementation("org.bouncycastle", "bcprov-jdk15on", "1.69") + implementation("com.fasterxml.jackson.core", "jackson-databind", "2.13.0") + implementation("net.sourceforge.argparse4j", "argparse4j", "0.9.0") + implementation("com.github.hypfvieh", "dbus-java-transport-native-unixsocket", "4.0.0-beta") + implementation("org.slf4j", "slf4j-simple", "1.7.32") implementation("org.slf4j", "jul-to-slf4j", "1.7.32") implementation(project(":lib")) } diff --git a/lib/build.gradle.kts b/lib/build.gradle.kts index 8e278ef4..d3007f2a 100644 --- a/lib/build.gradle.kts +++ b/lib/build.gradle.kts @@ -14,11 +14,11 @@ repositories { } dependencies { - implementation("com.github.turasa:signal-service-java:2.15.3_unofficial_34") - api("com.fasterxml.jackson.core", "jackson-databind", "2.13.0") - implementation("com.google.protobuf:protobuf-javalite:3.11.4") - implementation("org.bouncycastle:bcprov-jdk15on:1.69") - implementation("org.slf4j:slf4j-api:1.7.32") + implementation("com.github.turasa", "signal-service-java", "2.15.3_unofficial_34") + implementation("com.fasterxml.jackson.core", "jackson-databind", "2.13.0") + implementation("com.google.protobuf", "protobuf-javalite", "3.11.4") + implementation("org.bouncycastle", "bcprov-jdk15on", "1.69") + implementation("org.slf4j", "slf4j-api", "1.7.32") } configurations { -- 2.51.0 From c9928043b2d23ae89de376eb1b567c7f66e461fe Mon Sep 17 00:00:00 2001 From: AsamK Date: Sun, 5 Dec 2021 15:15:53 +0100 Subject: [PATCH 07/16] Copy managers list to prevent ConcurrentModificationException --- .../java/org/asamk/signal/manager/MultiAccountManagerImpl.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/lib/src/main/java/org/asamk/signal/manager/MultiAccountManagerImpl.java b/lib/src/main/java/org/asamk/signal/manager/MultiAccountManagerImpl.java index 8fd1d5aa..74c4c20a 100644 --- a/lib/src/main/java/org/asamk/signal/manager/MultiAccountManagerImpl.java +++ b/lib/src/main/java/org/asamk/signal/manager/MultiAccountManagerImpl.java @@ -7,6 +7,7 @@ import org.slf4j.LoggerFactory; import java.io.File; import java.io.IOException; import java.net.URI; +import java.util.ArrayList; import java.util.Collection; import java.util.HashMap; import java.util.HashSet; @@ -124,7 +125,7 @@ public class MultiAccountManagerImpl implements MultiAccountManager { @Override public void close() { synchronized (managers) { - for (var m : managers) { + for (var m : new ArrayList<>(managers)) { try { m.close(); } catch (IOException e) { -- 2.51.0 From a53bb1c4c67d428af0f3d425bfa3339850491c77 Mon Sep 17 00:00:00 2001 From: AsamK Date: Sun, 5 Dec 2021 16:08:14 +0100 Subject: [PATCH 08/16] Adapt error message for multi-account only commands --- src/main/java/org/asamk/signal/App.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/org/asamk/signal/App.java b/src/main/java/org/asamk/signal/App.java index f42fef1e..e9f4d79f 100644 --- a/src/main/java/org/asamk/signal/App.java +++ b/src/main/java/org/asamk/signal/App.java @@ -196,7 +196,7 @@ public class App { } if (!(command instanceof LocalCommand)) { - throw new UserErrorException("Command only works via dbus"); + throw new UserErrorException("Command only works in multi-account mode"); } handleLocalCommand((LocalCommand) command, -- 2.51.0 From cb346fdec4ba5b5a340958699fef31aa7b2a2df5 Mon Sep 17 00:00:00 2001 From: AsamK Date: Sun, 5 Dec 2021 16:12:33 +0100 Subject: [PATCH 09/16] Update CHANGELOG.md --- CHANGELOG.md | 30 +++++++++++++++++++++++++++++- 1 file changed, 29 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 3e60c8a4..6d8912cc 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,7 +1,35 @@ # Changelog ## [Unreleased] -**Attention**: Now requires Java 17 +**Attention**: Now requires Java 17 and libsignal-client version 0.10 + +### Added +- The daemon command now provides a JSON-RPC based socket interface (`--socket` and `--tcp`) +- New daemon command flag `--receive-mode` to configure when messages are received +- New daemon command flag `--no-receive-stdout` to prevent outputting messages on stdout +- New command `listAccounts` that lists all registered local accounts +- New command `removeContact` +- Extend `send` command to allow sending mentions (`--mention`) and quotes (`--quote-timestamp`, `--quote-author`, `--quote-message`, `--quote-mention`) +- New dbus method sendViewedReceipt (Thanks @John Freed) +- New dbus methods unregister, deleteAccount +- New dbus events MessageReceivedV2, ReceiptReceivedV2, SyncMessageReceivedV2 that provide an extras parameter with additional message info as a key/value map +- New dbus object Configuration to read and update configuration values (Thanks @John Freed) +- Payment info in json receive output (Thanks @technillogue) +- `-c` alias for `--config` (Thanks @technillogue) + +### Changed +- libzkgroup dependency is no longer required +- Renamed `-u` and `--username` flags to `-a` and `--account` to prevent confusion with upcoming Signal usernames. The old flags are also still supported for now. +- Respect phone number sharing mode and unlisted state set by main device +- Adapt register command to reactivate account if possible. + By default the unregister command just deactivates the account, in which case it can be reactivated without sms verification if the local data is still available. + If the account was deleted (with --delete-account) it cannot be reactivated. +- dbus-java now uses Java 16 native unix sockets, which should provide better cross-platform compatibility + +### Fixed +- Registering an existing unregistered account now works reliably in daemon mode +- Fixed an issue with loading some old config files without UUID +- More reliable send behavior if some recipients are unregistered ## [0.9.2] - 2021-10-24 ### Fixed -- 2.51.0 From c3a9022bec11aa2c1333ce7ee1aae29b8212d760 Mon Sep 17 00:00:00 2001 From: AsamK Date: Sun, 5 Dec 2021 16:26:18 +0100 Subject: [PATCH 10/16] Add debug log when reading message from stdin --- src/main/java/org/asamk/signal/commands/SendCommand.java | 1 + 1 file changed, 1 insertion(+) diff --git a/src/main/java/org/asamk/signal/commands/SendCommand.java b/src/main/java/org/asamk/signal/commands/SendCommand.java index f73d3e70..1af21d53 100644 --- a/src/main/java/org/asamk/signal/commands/SendCommand.java +++ b/src/main/java/org/asamk/signal/commands/SendCommand.java @@ -104,6 +104,7 @@ public class SendCommand implements JsonRpcLocalCommand { var messageText = ns.getString("message"); if (messageText == null) { + logger.debug("Reading message from stdin..."); try { messageText = IOUtils.readAll(System.in, Charset.defaultCharset()); } catch (IOException e) { -- 2.51.0 From 8867a7b9eeb3353d059613544899b262f4f47579 Mon Sep 17 00:00:00 2001 From: AsamK Date: Mon, 6 Dec 2021 18:55:37 +0100 Subject: [PATCH 11/16] Convert RecipientAddress to record --- .../org/asamk/signal/manager/ManagerImpl.java | 4 +- .../manager/api/RecipientIdentifier.java | 8 +-- .../storage/recipients/RecipientAddress.java | 54 ++++--------------- .../storage/recipients/RecipientStore.java | 38 ++++++------- .../signal/commands/ListContactsCommand.java | 4 +- .../signal/commands/ListGroupsCommand.java | 4 +- .../commands/ListIdentitiesCommand.java | 6 +-- .../org/asamk/signal/dbus/DbusSignalImpl.java | 4 +- .../org/asamk/signal/json/JsonMention.java | 4 +- .../signal/json/JsonMessageEnvelope.java | 8 +-- .../java/org/asamk/signal/json/JsonQuote.java | 4 +- .../org/asamk/signal/json/JsonReaction.java | 4 +- .../signal/json/JsonSyncDataMessage.java | 4 +- .../signal/json/JsonSyncReadMessage.java | 4 +- 14 files changed, 59 insertions(+), 91 deletions(-) diff --git a/lib/src/main/java/org/asamk/signal/manager/ManagerImpl.java b/lib/src/main/java/org/asamk/signal/manager/ManagerImpl.java index 87d3d0d0..eedb1a59 100644 --- a/lib/src/main/java/org/asamk/signal/manager/ManagerImpl.java +++ b/lib/src/main/java/org/asamk/signal/manager/ManagerImpl.java @@ -1436,13 +1436,13 @@ public class ManagerImpl implements Manager { private SignalServiceAddress resolveSignalServiceAddress(RecipientId recipientId) { final var address = account.getRecipientStore().resolveRecipientAddress(recipientId); - if (address.getUuid().isPresent()) { + if (address.uuid().isPresent()) { return address.toSignalServiceAddress(); } // Address in recipient store doesn't have a uuid, this shouldn't happen // Try to retrieve the uuid from the server - final var number = address.getNumber().get(); + final var number = address.number().get(); final ACI aci; try { aci = getRegisteredUser(number); diff --git a/lib/src/main/java/org/asamk/signal/manager/api/RecipientIdentifier.java b/lib/src/main/java/org/asamk/signal/manager/api/RecipientIdentifier.java index 5d6c7ae9..aa7ab547 100644 --- a/lib/src/main/java/org/asamk/signal/manager/api/RecipientIdentifier.java +++ b/lib/src/main/java/org/asamk/signal/manager/api/RecipientIdentifier.java @@ -36,10 +36,10 @@ public sealed interface RecipientIdentifier { } static Single fromAddress(RecipientAddress address) { - if (address.getNumber().isPresent()) { - return new Number(address.getNumber().get()); - } else if (address.getUuid().isPresent()) { - return new Uuid(address.getUuid().get()); + if (address.number().isPresent()) { + return new Number(address.number().get()); + } else if (address.uuid().isPresent()) { + return new Uuid(address.uuid().get()); } throw new AssertionError("RecipientAddress without identifier"); } diff --git a/lib/src/main/java/org/asamk/signal/manager/storage/recipients/RecipientAddress.java b/lib/src/main/java/org/asamk/signal/manager/storage/recipients/RecipientAddress.java index 1e33c47e..2f762ff7 100644 --- a/lib/src/main/java/org/asamk/signal/manager/storage/recipients/RecipientAddress.java +++ b/lib/src/main/java/org/asamk/signal/manager/storage/recipients/RecipientAddress.java @@ -6,27 +6,21 @@ import org.whispersystems.signalservice.api.push.SignalServiceAddress; import java.util.Optional; import java.util.UUID; -public class RecipientAddress { +public record RecipientAddress(Optional uuid, Optional number) { public static final UUID UNKNOWN_UUID = ACI.UNKNOWN.uuid(); - private final Optional uuid; - private final Optional e164; - /** * Construct a RecipientAddress. * - * @param uuid The UUID of the user, if available. - * @param e164 The phone number of the user, if available. + * @param uuid The UUID of the user, if available. + * @param number The phone number of the user, if available. */ - public RecipientAddress(Optional uuid, Optional e164) { + public RecipientAddress { uuid = uuid.isPresent() && uuid.get().equals(UNKNOWN_UUID) ? Optional.empty() : uuid; - if (uuid.isEmpty() && e164.isEmpty()) { + if (uuid.isEmpty() && number.isEmpty()) { throw new AssertionError("Must have either a UUID or E164 number!"); } - - this.uuid = uuid; - this.e164 = e164; } public RecipientAddress(UUID uuid, String e164) { @@ -41,27 +35,19 @@ public class RecipientAddress { this(Optional.of(uuid), Optional.empty()); } - public Optional getNumber() { - return e164; - } - - public Optional getUuid() { - return uuid; - } - public String getIdentifier() { if (uuid.isPresent()) { return uuid.get().toString(); - } else if (e164.isPresent()) { - return e164.get(); + } else if (number.isPresent()) { + return number.get(); } else { throw new AssertionError("Given the checks in the constructor, this should not be possible."); } } public String getLegacyIdentifier() { - if (e164.isPresent()) { - return e164.get(); + if (number.isPresent()) { + return number.get(); } else if (uuid.isPresent()) { return uuid.get().toString(); } else { @@ -71,30 +57,12 @@ public class RecipientAddress { public boolean matches(RecipientAddress other) { return (uuid.isPresent() && other.uuid.isPresent() && uuid.get().equals(other.uuid.get())) || ( - e164.isPresent() && other.e164.isPresent() && e164.get().equals(other.e164.get()) + number.isPresent() && other.number.isPresent() && number.get().equals(other.number.get()) ); } public SignalServiceAddress toSignalServiceAddress() { return new SignalServiceAddress(ACI.from(uuid.orElse(UNKNOWN_UUID)), - org.whispersystems.libsignal.util.guava.Optional.fromNullable(e164.orElse(null))); - } - - @Override - public boolean equals(final Object o) { - if (this == o) return true; - if (o == null || getClass() != o.getClass()) return false; - - final RecipientAddress that = (RecipientAddress) o; - - if (!uuid.equals(that.uuid)) return false; - return e164.equals(that.e164); - } - - @Override - public int hashCode() { - int result = uuid.hashCode(); - result = 31 * result + e164.hashCode(); - return result; + org.whispersystems.libsignal.util.guava.Optional.fromNullable(number.orElse(null))); } } diff --git a/lib/src/main/java/org/asamk/signal/manager/storage/recipients/RecipientStore.java b/lib/src/main/java/org/asamk/signal/manager/storage/recipients/RecipientStore.java index 10f67c2a..84b09e3a 100644 --- a/lib/src/main/java/org/asamk/signal/manager/storage/recipients/RecipientStore.java +++ b/lib/src/main/java/org/asamk/signal/manager/storage/recipients/RecipientStore.java @@ -151,7 +151,7 @@ public class RecipientStore implements RecipientResolver, ContactsStore, Profile synchronized (recipients) { byNumber = findByNumberLocked(number); } - if (byNumber.isEmpty() || byNumber.get().getAddress().getUuid().isEmpty()) { + if (byNumber.isEmpty() || byNumber.get().getAddress().uuid().isEmpty()) { final var aci = aciSupplier.get(); if (aci == null) { throw new UnregisteredUserException(number, null); @@ -234,7 +234,7 @@ public class RecipientStore implements RecipientResolver, ContactsStore, Profile storeRecipientLocked(recipientId, Recipient.newBuilder() .withRecipientId(recipientId) - .withAddress(new RecipientAddress(recipient.getAddress().getUuid().orElse(null))) + .withAddress(new RecipientAddress(recipient.getAddress().uuid().orElse(null))) .build()); } } @@ -320,24 +320,24 @@ public class RecipientStore implements RecipientResolver, ContactsStore, Profile private Pair> resolveRecipientLocked( RecipientAddress address, boolean isHighTrust ) { - final var byNumber = address.getNumber().isEmpty() + final var byNumber = address.number().isEmpty() ? Optional.empty() - : findByNumberLocked(address.getNumber().get()); - final var byUuid = address.getUuid().isEmpty() + : findByNumberLocked(address.number().get()); + final var byUuid = address.uuid().isEmpty() ? Optional.empty() - : findByUuidLocked(address.getUuid().get()); + : findByUuidLocked(address.uuid().get()); if (byNumber.isEmpty() && byUuid.isEmpty()) { logger.debug("Got new recipient, both uuid and number are unknown"); - if (isHighTrust || address.getUuid().isEmpty() || address.getNumber().isEmpty()) { + if (isHighTrust || address.uuid().isEmpty() || address.number().isEmpty()) { return new Pair<>(addNewRecipientLocked(address), Optional.empty()); } - return new Pair<>(addNewRecipientLocked(new RecipientAddress(address.getUuid().get())), Optional.empty()); + return new Pair<>(addNewRecipientLocked(new RecipientAddress(address.uuid().get())), Optional.empty()); } - if (!isHighTrust || address.getUuid().isEmpty() || address.getNumber().isEmpty() || byNumber.equals(byUuid)) { + if (!isHighTrust || address.uuid().isEmpty() || address.number().isEmpty() || byNumber.equals(byUuid)) { return new Pair<>(byUuid.or(() -> byNumber).map(Recipient::getRecipientId).get(), Optional.empty()); } @@ -348,12 +348,12 @@ public class RecipientStore implements RecipientResolver, ContactsStore, Profile } if (byUuid.isEmpty()) { - if (byNumber.get().getAddress().getUuid().isPresent()) { + if (byNumber.get().getAddress().uuid().isPresent()) { logger.debug( "Got recipient existing with number, but different uuid, so stripping its number and adding new recipient"); updateRecipientAddressLocked(byNumber.get().getRecipientId(), - new RecipientAddress(byNumber.get().getAddress().getUuid().get())); + new RecipientAddress(byNumber.get().getAddress().uuid().get())); return new Pair<>(addNewRecipientLocked(address), Optional.empty()); } @@ -362,12 +362,12 @@ public class RecipientStore implements RecipientResolver, ContactsStore, Profile return new Pair<>(byNumber.get().getRecipientId(), Optional.empty()); } - if (byNumber.get().getAddress().getUuid().isPresent()) { + if (byNumber.get().getAddress().uuid().isPresent()) { logger.debug( "Got separate recipients for high trust number and uuid, recipient for number has different uuid, so stripping its number"); updateRecipientAddressLocked(byNumber.get().getRecipientId(), - new RecipientAddress(byNumber.get().getAddress().getUuid().get())); + new RecipientAddress(byNumber.get().getAddress().uuid().get())); updateRecipientAddressLocked(byUuid.get().getRecipientId(), address); return new Pair<>(byUuid.get().getRecipientId(), Optional.empty()); } @@ -430,9 +430,9 @@ public class RecipientStore implements RecipientResolver, ContactsStore, Profile private Optional findByNumberLocked(final String number) { return recipients.entrySet() .stream() - .filter(entry -> entry.getValue().getAddress().getNumber().isPresent() && number.equals(entry.getValue() + .filter(entry -> entry.getValue().getAddress().number().isPresent() && number.equals(entry.getValue() .getAddress() - .getNumber() + .number() .get())) .findFirst() .map(Map.Entry::getValue); @@ -441,9 +441,9 @@ public class RecipientStore implements RecipientResolver, ContactsStore, Profile private Optional findByUuidLocked(final UUID uuid) { return recipients.entrySet() .stream() - .filter(entry -> entry.getValue().getAddress().getUuid().isPresent() && uuid.equals(entry.getValue() + .filter(entry -> entry.getValue().getAddress().uuid().isPresent() && uuid.equals(entry.getValue() .getAddress() - .getUuid() + .uuid() .get())) .findFirst() .map(Map.Entry::getValue); @@ -479,8 +479,8 @@ public class RecipientStore implements RecipientResolver, ContactsStore, Profile .map(Enum::name) .collect(Collectors.toSet())); return new Storage.Recipient(pair.getKey().id(), - recipient.getAddress().getNumber().orElse(null), - recipient.getAddress().getUuid().map(UUID::toString).orElse(null), + recipient.getAddress().number().orElse(null), + recipient.getAddress().uuid().map(UUID::toString).orElse(null), recipient.getProfileKey() == null ? null : base64.encodeToString(recipient.getProfileKey().serialize()), diff --git a/src/main/java/org/asamk/signal/commands/ListContactsCommand.java b/src/main/java/org/asamk/signal/commands/ListContactsCommand.java index 98c21141..308044dc 100644 --- a/src/main/java/org/asamk/signal/commands/ListContactsCommand.java +++ b/src/main/java/org/asamk/signal/commands/ListContactsCommand.java @@ -43,8 +43,8 @@ public class ListContactsCommand implements JsonRpcLocalCommand { final var jsonContacts = contacts.stream().map(contactPair -> { final var address = contactPair.first(); final var contact = contactPair.second(); - return new JsonContact(address.getNumber().orElse(null), - address.getUuid().map(UUID::toString).orElse(null), + return new JsonContact(address.number().orElse(null), + address.uuid().map(UUID::toString).orElse(null), contact.getName(), contact.isBlocked(), contact.getMessageExpirationTime()); diff --git a/src/main/java/org/asamk/signal/commands/ListGroupsCommand.java b/src/main/java/org/asamk/signal/commands/ListGroupsCommand.java index 8326125f..e5a273f5 100644 --- a/src/main/java/org/asamk/signal/commands/ListGroupsCommand.java +++ b/src/main/java/org/asamk/signal/commands/ListGroupsCommand.java @@ -41,8 +41,8 @@ public class ListGroupsCommand implements JsonRpcLocalCommand { private static Set resolveJsonMembers(Set addresses) { return addresses.stream() - .map(address -> new JsonGroupMember(address.getNumber().orElse(null), - address.getUuid().map(UUID::toString).orElse(null))) + .map(address -> new JsonGroupMember(address.number().orElse(null), + address.uuid().map(UUID::toString).orElse(null))) .collect(Collectors.toSet()); } diff --git a/src/main/java/org/asamk/signal/commands/ListIdentitiesCommand.java b/src/main/java/org/asamk/signal/commands/ListIdentitiesCommand.java index c3cfbce8..5a442bd9 100644 --- a/src/main/java/org/asamk/signal/commands/ListIdentitiesCommand.java +++ b/src/main/java/org/asamk/signal/commands/ListIdentitiesCommand.java @@ -31,7 +31,7 @@ public class ListIdentitiesCommand implements JsonRpcLocalCommand { private static void printIdentityFingerprint(PlainTextWriter writer, Identity theirId) { writer.println("{}: {} Added: {} Fingerprint: {} Safety Number: {}", - theirId.recipient().getNumber().orElse(null), + theirId.recipient().number().orElse(null), theirId.trustLevel(), theirId.dateAdded(), Hex.toString(theirId.getFingerprint()), @@ -67,8 +67,8 @@ public class ListIdentitiesCommand implements JsonRpcLocalCommand { final var address = id.recipient(); var safetyNumber = Util.formatSafetyNumber(id.safetyNumber()); var scannableSafetyNumber = id.scannableSafetyNumber(); - return new JsonIdentity(address.getNumber().orElse(null), - address.getUuid().map(UUID::toString).orElse(null), + return new JsonIdentity(address.number().orElse(null), + address.uuid().map(UUID::toString).orElse(null), Hex.toString(id.getFingerprint()), safetyNumber, scannableSafetyNumber == null diff --git a/src/main/java/org/asamk/signal/dbus/DbusSignalImpl.java b/src/main/java/org/asamk/signal/dbus/DbusSignalImpl.java index 5d7eb491..e59c7f86 100644 --- a/src/main/java/org/asamk/signal/dbus/DbusSignalImpl.java +++ b/src/main/java/org/asamk/signal/dbus/DbusSignalImpl.java @@ -679,7 +679,7 @@ public class DbusSignalImpl implements Signal { public List listNumbers() { return Stream.concat(m.getIdentities().stream().map(Identity::recipient), m.getContacts().stream().map(Pair::first)) - .map(a -> a.getNumber().orElse(null)) + .map(a -> a.number().orElse(null)) .filter(Objects::nonNull) .distinct() .collect(Collectors.toList()); @@ -698,7 +698,7 @@ public class DbusSignalImpl implements Signal { // Try profiles if no contact name was found for (var identity : m.getIdentities()) { final var address = identity.recipient(); - var number = address.getNumber().orElse(null); + var number = address.number().orElse(null); if (number != null) { Profile profile = null; try { diff --git a/src/main/java/org/asamk/signal/json/JsonMention.java b/src/main/java/org/asamk/signal/json/JsonMention.java index d8001088..c4c962a0 100644 --- a/src/main/java/org/asamk/signal/json/JsonMention.java +++ b/src/main/java/org/asamk/signal/json/JsonMention.java @@ -9,8 +9,8 @@ public record JsonMention(@Deprecated String name, String number, String uuid, i static JsonMention from(MessageEnvelope.Data.Mention mention) { final var address = mention.recipient(); return new JsonMention(address.getLegacyIdentifier(), - address.getNumber().orElse(null), - address.getUuid().map(UUID::toString).orElse(null), + address.number().orElse(null), + address.uuid().map(UUID::toString).orElse(null), mention.start(), mention.length()); } diff --git a/src/main/java/org/asamk/signal/json/JsonMessageEnvelope.java b/src/main/java/org/asamk/signal/json/JsonMessageEnvelope.java index b7e1cf2a..0c1d0738 100644 --- a/src/main/java/org/asamk/signal/json/JsonMessageEnvelope.java +++ b/src/main/java/org/asamk/signal/json/JsonMessageEnvelope.java @@ -34,14 +34,14 @@ public record JsonMessageEnvelope( if (envelope.sourceAddress().isPresent()) { final var sourceAddress = envelope.sourceAddress().get(); source = sourceAddress.getLegacyIdentifier(); - sourceNumber = sourceAddress.getNumber().orElse(null); - sourceUuid = sourceAddress.getUuid().map(UUID::toString).orElse(null); + sourceNumber = sourceAddress.number().orElse(null); + sourceUuid = sourceAddress.uuid().map(UUID::toString).orElse(null); sourceDevice = envelope.sourceDevice(); } else if (exception instanceof UntrustedIdentityException e) { final var sender = e.getSender(); source = sender.getLegacyIdentifier(); - sourceNumber = sender.getNumber().orElse(null); - sourceUuid = sender.getUuid().map(UUID::toString).orElse(null); + sourceNumber = sender.number().orElse(null); + sourceUuid = sender.uuid().map(UUID::toString).orElse(null); sourceDevice = e.getSenderDevice(); } else { source = null; diff --git a/src/main/java/org/asamk/signal/json/JsonQuote.java b/src/main/java/org/asamk/signal/json/JsonQuote.java index 05dc8f41..d8d3c17f 100644 --- a/src/main/java/org/asamk/signal/json/JsonQuote.java +++ b/src/main/java/org/asamk/signal/json/JsonQuote.java @@ -23,8 +23,8 @@ public record JsonQuote( final var id = quote.id(); final var address = quote.author(); final var author = address.getLegacyIdentifier(); - final var authorNumber = address.getNumber().orElse(null); - final var authorUuid = address.getUuid().map(UUID::toString).orElse(null); + final var authorNumber = address.number().orElse(null); + final var authorUuid = address.uuid().map(UUID::toString).orElse(null); final var text = quote.text().orElse(null); final var mentions = quote.mentions().size() > 0 ? quote.mentions() diff --git a/src/main/java/org/asamk/signal/json/JsonReaction.java b/src/main/java/org/asamk/signal/json/JsonReaction.java index 04037b6e..71da4df5 100644 --- a/src/main/java/org/asamk/signal/json/JsonReaction.java +++ b/src/main/java/org/asamk/signal/json/JsonReaction.java @@ -17,8 +17,8 @@ public record JsonReaction( final var emoji = reaction.emoji(); final var address = reaction.targetAuthor(); final var targetAuthor = address.getLegacyIdentifier(); - final var targetAuthorNumber = address.getNumber().orElse(null); - final var targetAuthorUuid = address.getUuid().map(UUID::toString).orElse(null); + final var targetAuthorNumber = address.number().orElse(null); + final var targetAuthorUuid = address.uuid().map(UUID::toString).orElse(null); final var targetSentTimestamp = reaction.targetSentTimestamp(); final var isRemove = reaction.isRemove(); return new JsonReaction(emoji, diff --git a/src/main/java/org/asamk/signal/json/JsonSyncDataMessage.java b/src/main/java/org/asamk/signal/json/JsonSyncDataMessage.java index 7eea0472..0accddc1 100644 --- a/src/main/java/org/asamk/signal/json/JsonSyncDataMessage.java +++ b/src/main/java/org/asamk/signal/json/JsonSyncDataMessage.java @@ -17,8 +17,8 @@ record JsonSyncDataMessage( if (transcriptMessage.destination().isPresent()) { final var address = transcriptMessage.destination().get(); return new JsonSyncDataMessage(address.getLegacyIdentifier(), - address.getNumber().orElse(null), - address.getUuid().map(UUID::toString).orElse(null), + address.number().orElse(null), + address.uuid().map(UUID::toString).orElse(null), JsonDataMessage.from(transcriptMessage.message())); } else { diff --git a/src/main/java/org/asamk/signal/json/JsonSyncReadMessage.java b/src/main/java/org/asamk/signal/json/JsonSyncReadMessage.java index 3d04f94d..50c6ecee 100644 --- a/src/main/java/org/asamk/signal/json/JsonSyncReadMessage.java +++ b/src/main/java/org/asamk/signal/json/JsonSyncReadMessage.java @@ -11,8 +11,8 @@ record JsonSyncReadMessage( static JsonSyncReadMessage from(MessageEnvelope.Sync.Read readMessage) { final var senderAddress = readMessage.sender(); final var sender = senderAddress.getLegacyIdentifier(); - final var senderNumber = senderAddress.getNumber().orElse(null); - final var senderUuid = senderAddress.getUuid().map(UUID::toString).orElse(null); + final var senderNumber = senderAddress.number().orElse(null); + final var senderUuid = senderAddress.uuid().map(UUID::toString).orElse(null); final var timestamp = readMessage.timestamp(); return new JsonSyncReadMessage(sender, senderNumber, senderUuid, timestamp); } -- 2.51.0 From 9c811ecc0210e9cddc5c13632b76f09e851f2342 Mon Sep 17 00:00:00 2001 From: AsamK Date: Mon, 6 Dec 2021 19:18:18 +0100 Subject: [PATCH 12/16] Extend logging in RecipientStore --- .../storage/recipients/RecipientStore.java | 57 ++++++++++++------- 1 file changed, 36 insertions(+), 21 deletions(-) diff --git a/lib/src/main/java/org/asamk/signal/manager/storage/recipients/RecipientStore.java b/lib/src/main/java/org/asamk/signal/manager/storage/recipients/RecipientStore.java index 84b09e3a..8ead4c29 100644 --- a/lib/src/main/java/org/asamk/signal/manager/storage/recipients/RecipientStore.java +++ b/lib/src/main/java/org/asamk/signal/manager/storage/recipients/RecipientStore.java @@ -230,6 +230,7 @@ public class RecipientStore implements RecipientResolver, ContactsStore, Profile public void deleteRecipientData(final RecipientId recipientId) { synchronized (recipients) { + logger.debug("Deleting recipient data for {}", recipientId); final var recipient = recipients.get(recipientId); storeRecipientLocked(recipientId, Recipient.newBuilder() @@ -342,45 +343,57 @@ public class RecipientStore implements RecipientResolver, ContactsStore, Profile } if (byNumber.isEmpty()) { - logger.debug("Got recipient existing with uuid, updating with high trust number"); + logger.debug("Got recipient {} existing with uuid, updating with high trust number", + byUuid.get().getRecipientId()); updateRecipientAddressLocked(byUuid.get().getRecipientId(), address); return new Pair<>(byUuid.get().getRecipientId(), Optional.empty()); } + final var byNumberRecipient = byNumber.get(); + if (byUuid.isEmpty()) { - if (byNumber.get().getAddress().uuid().isPresent()) { + if (byNumberRecipient.getAddress().uuid().isPresent()) { logger.debug( - "Got recipient existing with number, but different uuid, so stripping its number and adding new recipient"); + "Got recipient {} existing with number, but different uuid, so stripping its number and adding new recipient", + byNumberRecipient.getRecipientId()); - updateRecipientAddressLocked(byNumber.get().getRecipientId(), - new RecipientAddress(byNumber.get().getAddress().uuid().get())); + updateRecipientAddressLocked(byNumberRecipient.getRecipientId(), + new RecipientAddress(byNumberRecipient.getAddress().uuid().get())); return new Pair<>(addNewRecipientLocked(address), Optional.empty()); } - logger.debug("Got recipient existing with number and no uuid, updating with high trust uuid"); - updateRecipientAddressLocked(byNumber.get().getRecipientId(), address); - return new Pair<>(byNumber.get().getRecipientId(), Optional.empty()); + logger.debug("Got recipient {} existing with number and no uuid, updating with high trust uuid", + byNumberRecipient.getRecipientId()); + updateRecipientAddressLocked(byNumberRecipient.getRecipientId(), address); + return new Pair<>(byNumberRecipient.getRecipientId(), Optional.empty()); } - if (byNumber.get().getAddress().uuid().isPresent()) { - logger.debug( - "Got separate recipients for high trust number and uuid, recipient for number has different uuid, so stripping its number"); + final var byUuidRecipient = byUuid.get(); - updateRecipientAddressLocked(byNumber.get().getRecipientId(), - new RecipientAddress(byNumber.get().getAddress().uuid().get())); - updateRecipientAddressLocked(byUuid.get().getRecipientId(), address); - return new Pair<>(byUuid.get().getRecipientId(), Optional.empty()); + if (byNumberRecipient.getAddress().uuid().isPresent()) { + logger.debug( + "Got separate recipients for high trust number {} and uuid {}, recipient for number has different uuid, so stripping its number", + byNumberRecipient.getRecipientId(), + byUuidRecipient.getRecipientId()); + + updateRecipientAddressLocked(byNumberRecipient.getRecipientId(), + new RecipientAddress(byNumberRecipient.getAddress().uuid().get())); + updateRecipientAddressLocked(byUuidRecipient.getRecipientId(), address); + return new Pair<>(byUuidRecipient.getRecipientId(), Optional.empty()); } - logger.debug("Got separate recipients for high trust number and uuid, need to merge them"); - updateRecipientAddressLocked(byUuid.get().getRecipientId(), address); - mergeRecipientsLocked(byUuid.get().getRecipientId(), byNumber.get().getRecipientId()); - recipientsMerged.put(byNumber.get().getRecipientId(), byUuid.get().getRecipientId()); - return new Pair<>(byUuid.get().getRecipientId(), byNumber.map(Recipient::getRecipientId)); + logger.debug("Got separate recipients for high trust number {} and uuid {}, need to merge them", + byNumberRecipient.getRecipientId(), + byUuidRecipient.getRecipientId()); + updateRecipientAddressLocked(byUuidRecipient.getRecipientId(), address); + mergeRecipientsLocked(byUuidRecipient.getRecipientId(), byNumberRecipient.getRecipientId()); + recipientsMerged.put(byNumberRecipient.getRecipientId(), byUuidRecipient.getRecipientId()); + return new Pair<>(byUuidRecipient.getRecipientId(), byNumber.map(Recipient::getRecipientId)); } private RecipientId addNewRecipientLocked(final RecipientAddress address) { final var nextRecipientId = nextIdLocked(); + logger.debug("Adding new recipient {} with address {}", nextRecipientId, address); storeRecipientLocked(nextRecipientId, new Recipient(nextRecipientId, address, null, null, null, null)); return nextRecipientId; } @@ -394,7 +407,9 @@ public class RecipientStore implements RecipientResolver, ContactsStore, Profile private Recipient getRecipientLocked(RecipientId recipientId) { while (recipientsMerged.containsKey(recipientId)) { - recipientId = recipientsMerged.get(recipientId); + final var newRecipientId = recipientsMerged.get(recipientId); + logger.debug("Using {} instead of {}, because recipients have been merged", newRecipientId, recipientId); + recipientId = newRecipientId; } return recipients.get(recipientId); } -- 2.51.0 From bbe74ef020aadad887d51f41f5fe0fd5a8caad91 Mon Sep 17 00:00:00 2001 From: AsamK Date: Mon, 6 Dec 2021 19:37:14 +0100 Subject: [PATCH 13/16] Always use correct recipientId after recipients were merged --- .../storage/recipients/RecipientStore.java | 42 ++++++++++--------- 1 file changed, 22 insertions(+), 20 deletions(-) diff --git a/lib/src/main/java/org/asamk/signal/manager/storage/recipients/RecipientStore.java b/lib/src/main/java/org/asamk/signal/manager/storage/recipients/RecipientStore.java index 8ead4c29..24f36b25 100644 --- a/lib/src/main/java/org/asamk/signal/manager/storage/recipients/RecipientStore.java +++ b/lib/src/main/java/org/asamk/signal/manager/storage/recipients/RecipientStore.java @@ -130,7 +130,8 @@ public class RecipientStore implements RecipientResolver, ContactsStore, Profile public Recipient getRecipient(RecipientId recipientId) { synchronized (recipients) { - return getRecipientLocked(recipientId); + recipientId = getActualRecipientId(recipientId); + return recipients.get(recipientId); } } @@ -198,15 +199,16 @@ public class RecipientStore implements RecipientResolver, ContactsStore, Profile } @Override - public void storeContact(final RecipientId recipientId, final Contact contact) { + public void storeContact(RecipientId recipientId, final Contact contact) { synchronized (recipients) { + recipientId = getActualRecipientId(recipientId); final var recipient = recipients.get(recipientId); storeRecipientLocked(recipientId, Recipient.newBuilder(recipient).withContact(contact).build()); } } @Override - public Contact getContact(final RecipientId recipientId) { + public Contact getContact(RecipientId recipientId) { final var recipient = getRecipient(recipientId); return recipient == null ? null : recipient.getContact(); } @@ -221,15 +223,17 @@ public class RecipientStore implements RecipientResolver, ContactsStore, Profile } @Override - public void deleteContact(final RecipientId recipientId) { + public void deleteContact(RecipientId recipientId) { synchronized (recipients) { + recipientId = getActualRecipientId(recipientId); final var recipient = recipients.get(recipientId); storeRecipientLocked(recipientId, Recipient.newBuilder(recipient).withContact(null).build()); } } - public void deleteRecipientData(final RecipientId recipientId) { + public void deleteRecipientData(RecipientId recipientId) { synchronized (recipients) { + recipientId = getActualRecipientId(recipientId); logger.debug("Deleting recipient data for {}", recipientId); final var recipient = recipients.get(recipientId); storeRecipientLocked(recipientId, @@ -259,16 +263,18 @@ public class RecipientStore implements RecipientResolver, ContactsStore, Profile } @Override - public void storeProfile(final RecipientId recipientId, final Profile profile) { + public void storeProfile(RecipientId recipientId, final Profile profile) { synchronized (recipients) { + recipientId = getActualRecipientId(recipientId); final var recipient = recipients.get(recipientId); storeRecipientLocked(recipientId, Recipient.newBuilder(recipient).withProfile(profile).build()); } } @Override - public void storeProfileKey(final RecipientId recipientId, final ProfileKey profileKey) { + public void storeProfileKey(RecipientId recipientId, final ProfileKey profileKey) { synchronized (recipients) { + recipientId = getActualRecipientId(recipientId); final var recipient = recipients.get(recipientId); if (profileKey != null && profileKey.equals(recipient.getProfileKey())) { return; @@ -286,10 +292,9 @@ public class RecipientStore implements RecipientResolver, ContactsStore, Profile } @Override - public void storeProfileKeyCredential( - final RecipientId recipientId, final ProfileKeyCredential profileKeyCredential - ) { + public void storeProfileKeyCredential(RecipientId recipientId, final ProfileKeyCredential profileKeyCredential) { synchronized (recipients) { + recipientId = getActualRecipientId(recipientId); final var recipient = recipients.get(recipientId); storeRecipientLocked(recipientId, Recipient.newBuilder(recipient).withProfileKeyCredential(profileKeyCredential).build()); @@ -387,7 +392,6 @@ public class RecipientStore implements RecipientResolver, ContactsStore, Profile byUuidRecipient.getRecipientId()); updateRecipientAddressLocked(byUuidRecipient.getRecipientId(), address); mergeRecipientsLocked(byUuidRecipient.getRecipientId(), byNumberRecipient.getRecipientId()); - recipientsMerged.put(byNumberRecipient.getRecipientId(), byUuidRecipient.getRecipientId()); return new Pair<>(byUuidRecipient.getRecipientId(), byNumber.map(Recipient::getRecipientId)); } @@ -398,26 +402,23 @@ public class RecipientStore implements RecipientResolver, ContactsStore, Profile return nextRecipientId; } - private void updateRecipientAddressLocked( - final RecipientId recipientId, final RecipientAddress address - ) { + private void updateRecipientAddressLocked(RecipientId recipientId, final RecipientAddress address) { + recipientId = getActualRecipientId(recipientId); final var recipient = recipients.get(recipientId); storeRecipientLocked(recipientId, Recipient.newBuilder(recipient).withAddress(address).build()); } - private Recipient getRecipientLocked(RecipientId recipientId) { + private RecipientId getActualRecipientId(RecipientId recipientId) { while (recipientsMerged.containsKey(recipientId)) { final var newRecipientId = recipientsMerged.get(recipientId); logger.debug("Using {} instead of {}, because recipients have been merged", newRecipientId, recipientId); recipientId = newRecipientId; } - return recipients.get(recipientId); + return recipientId; } - private void storeRecipientLocked( - final RecipientId recipientId, final Recipient recipient - ) { - final var existingRecipient = getRecipientLocked(recipientId); + private void storeRecipientLocked(final RecipientId recipientId, final Recipient recipient) { + final var existingRecipient = recipients.get(recipientId); if (existingRecipient == null || !existingRecipient.equals(recipient)) { recipients.put(recipientId, recipient); saveLocked(); @@ -439,6 +440,7 @@ public class RecipientStore implements RecipientResolver, ContactsStore, Profile : toBeMergedRecipient.getProfileKeyCredential(), recipient.getProfile() != null ? recipient.getProfile() : toBeMergedRecipient.getProfile())); recipients.remove(toBeMergedRecipientId); + recipientsMerged.put(toBeMergedRecipientId, recipientId); saveLocked(); } -- 2.51.0 From 10df4338b1a810797c17fffb8d859c4654adbb93 Mon Sep 17 00:00:00 2001 From: AsamK Date: Tue, 7 Dec 2021 00:02:24 +0100 Subject: [PATCH 14/16] Improve behavior of changed recipient id --- .../manager/storage/groups/GroupStore.java | 5 ++- .../storage/identities/IdentityKeyStore.java | 4 +- .../storage/recipients/RecipientId.java | 40 +++++++++++++++-- .../storage/recipients/RecipientResolver.java | 2 + .../storage/recipients/RecipientStore.java | 44 ++++++++++++------- .../senderKeys/SenderKeyRecordStore.java | 12 +++-- .../senderKeys/SenderKeySharedStore.java | 6 ++- .../storage/sessions/SessionStore.java | 10 ++++- 8 files changed, 95 insertions(+), 28 deletions(-) diff --git a/lib/src/main/java/org/asamk/signal/manager/storage/groups/GroupStore.java b/lib/src/main/java/org/asamk/signal/manager/storage/groups/GroupStore.java index cfa39bc9..5d8bf2c1 100644 --- a/lib/src/main/java/org/asamk/signal/manager/storage/groups/GroupStore.java +++ b/lib/src/main/java/org/asamk/signal/manager/storage/groups/GroupStore.java @@ -36,6 +36,7 @@ import java.util.Base64; import java.util.HashMap; import java.util.List; import java.util.Map; +import java.util.Objects; import java.util.stream.Collectors; public class GroupStore { @@ -82,8 +83,8 @@ public class GroupStore { m.number)); } - return RecipientId.of(m.recipientId); - }).collect(Collectors.toSet()); + return recipientResolver.resolveRecipient(m.recipientId); + }).filter(Objects::nonNull).collect(Collectors.toSet()); return new GroupInfoV1(GroupIdV1.fromBase64(g1.groupId), g1.expectedV2Id == null ? null : GroupIdV2.fromBase64(g1.expectedV2Id), diff --git a/lib/src/main/java/org/asamk/signal/manager/storage/identities/IdentityKeyStore.java b/lib/src/main/java/org/asamk/signal/manager/storage/identities/IdentityKeyStore.java index 9e89861a..fef06c5b 100644 --- a/lib/src/main/java/org/asamk/signal/manager/storage/identities/IdentityKeyStore.java +++ b/lib/src/main/java/org/asamk/signal/manager/storage/identities/IdentityKeyStore.java @@ -26,6 +26,7 @@ import java.util.Date; import java.util.HashMap; import java.util.List; import java.util.Map; +import java.util.Objects; import java.util.regex.Pattern; import java.util.stream.Collectors; @@ -161,7 +162,8 @@ public class IdentityKeyStore implements org.whispersystems.libsignal.state.Iden } return Arrays.stream(files) .filter(f -> identityFileNamePattern.matcher(f.getName()).matches()) - .map(f -> RecipientId.of(Integer.parseInt(f.getName()))) + .map(f -> resolver.resolveRecipient(Long.parseLong(f.getName()))) + .filter(Objects::nonNull) .map(this::loadIdentityLocked) .collect(Collectors.toList()); } diff --git a/lib/src/main/java/org/asamk/signal/manager/storage/recipients/RecipientId.java b/lib/src/main/java/org/asamk/signal/manager/storage/recipients/RecipientId.java index d7aa373d..cea637ec 100644 --- a/lib/src/main/java/org/asamk/signal/manager/storage/recipients/RecipientId.java +++ b/lib/src/main/java/org/asamk/signal/manager/storage/recipients/RecipientId.java @@ -1,8 +1,42 @@ package org.asamk.signal.manager.storage.recipients; -public record RecipientId(long id) { +import java.util.Objects; - public static RecipientId of(long id) { - return new RecipientId(id); +public final class RecipientId { + + private long id; + private final RecipientStore recipientStore; + + RecipientId(long id, final RecipientStore recipientStore) { + this.id = id; + this.recipientStore = recipientStore; + } + + public long id() { + if (recipientStore != null) { + final var actualRecipientId = recipientStore.getActualRecipientId(this.id); + if (actualRecipientId != this.id) { + this.id = actualRecipientId; + } + } + return this.id; + } + + @Override + public boolean equals(Object obj) { + if (obj == this) return true; + if (obj == null || obj.getClass() != this.getClass()) return false; + var that = (RecipientId) obj; + return this.id() == that.id(); + } + + @Override + public int hashCode() { + return Objects.hash(id()); + } + + @Override + public String toString() { + return "RecipientId[" + "id=" + id() + ']'; } } diff --git a/lib/src/main/java/org/asamk/signal/manager/storage/recipients/RecipientResolver.java b/lib/src/main/java/org/asamk/signal/manager/storage/recipients/RecipientResolver.java index 06747684..487001a0 100644 --- a/lib/src/main/java/org/asamk/signal/manager/storage/recipients/RecipientResolver.java +++ b/lib/src/main/java/org/asamk/signal/manager/storage/recipients/RecipientResolver.java @@ -12,4 +12,6 @@ public interface RecipientResolver { RecipientId resolveRecipient(SignalServiceAddress address); RecipientId resolveRecipient(ACI aci); + + RecipientId resolveRecipient(long recipientId); } diff --git a/lib/src/main/java/org/asamk/signal/manager/storage/recipients/RecipientStore.java b/lib/src/main/java/org/asamk/signal/manager/storage/recipients/RecipientStore.java index 24f36b25..706110db 100644 --- a/lib/src/main/java/org/asamk/signal/manager/storage/recipients/RecipientStore.java +++ b/lib/src/main/java/org/asamk/signal/manager/storage/recipients/RecipientStore.java @@ -44,7 +44,7 @@ public class RecipientStore implements RecipientResolver, ContactsStore, Profile private final RecipientMergeHandler recipientMergeHandler; private final Map recipients; - private final Map recipientsMerged = new HashMap<>(); + private final Map recipientsMerged = new HashMap<>(); private long lastId; @@ -52,8 +52,14 @@ public class RecipientStore implements RecipientResolver, ContactsStore, Profile final var objectMapper = Utils.createStorageObjectMapper(); try (var inputStream = new FileInputStream(file)) { final var storage = objectMapper.readValue(inputStream, Storage.class); + + final var recipientStore = new RecipientStore(objectMapper, + file, + recipientMergeHandler, + new HashMap<>(), + storage.lastId); final var recipients = storage.recipients.stream().map(r -> { - final var recipientId = new RecipientId(r.id); + final var recipientId = new RecipientId(r.id, recipientStore); final var address = new RecipientAddress(Optional.ofNullable(r.uuid).map(UuidUtil::parseOrThrow), Optional.ofNullable(r.number)); @@ -101,7 +107,9 @@ public class RecipientStore implements RecipientResolver, ContactsStore, Profile return new Recipient(recipientId, address, contact, profileKey, profileKeyCredential, profile); }).collect(Collectors.toMap(Recipient::getRecipientId, r -> r)); - return new RecipientStore(objectMapper, file, recipientMergeHandler, recipients, storage.lastId); + recipientStore.addRecipients(recipients); + + return recipientStore; } catch (FileNotFoundException e) { logger.debug("Creating new recipient store."); return new RecipientStore(objectMapper, file, recipientMergeHandler, new HashMap<>(), 0); @@ -130,7 +138,6 @@ public class RecipientStore implements RecipientResolver, ContactsStore, Profile public Recipient getRecipient(RecipientId recipientId) { synchronized (recipients) { - recipientId = getActualRecipientId(recipientId); return recipients.get(recipientId); } } @@ -140,6 +147,12 @@ public class RecipientStore implements RecipientResolver, ContactsStore, Profile return resolveRecipient(new RecipientAddress(aci == null ? null : aci.uuid()), false); } + @Override + public RecipientId resolveRecipient(final long recipientId) { + final var recipient = getRecipient(new RecipientId(recipientId, this)); + return recipient == null ? null : recipient.getRecipientId(); + } + @Override public RecipientId resolveRecipient(final String identifier) { return resolveRecipient(Utils.getRecipientAddressFromIdentifier(identifier), false); @@ -201,7 +214,6 @@ public class RecipientStore implements RecipientResolver, ContactsStore, Profile @Override public void storeContact(RecipientId recipientId, final Contact contact) { synchronized (recipients) { - recipientId = getActualRecipientId(recipientId); final var recipient = recipients.get(recipientId); storeRecipientLocked(recipientId, Recipient.newBuilder(recipient).withContact(contact).build()); } @@ -225,7 +237,6 @@ public class RecipientStore implements RecipientResolver, ContactsStore, Profile @Override public void deleteContact(RecipientId recipientId) { synchronized (recipients) { - recipientId = getActualRecipientId(recipientId); final var recipient = recipients.get(recipientId); storeRecipientLocked(recipientId, Recipient.newBuilder(recipient).withContact(null).build()); } @@ -233,7 +244,6 @@ public class RecipientStore implements RecipientResolver, ContactsStore, Profile public void deleteRecipientData(RecipientId recipientId) { synchronized (recipients) { - recipientId = getActualRecipientId(recipientId); logger.debug("Deleting recipient data for {}", recipientId); final var recipient = recipients.get(recipientId); storeRecipientLocked(recipientId, @@ -265,7 +275,6 @@ public class RecipientStore implements RecipientResolver, ContactsStore, Profile @Override public void storeProfile(RecipientId recipientId, final Profile profile) { synchronized (recipients) { - recipientId = getActualRecipientId(recipientId); final var recipient = recipients.get(recipientId); storeRecipientLocked(recipientId, Recipient.newBuilder(recipient).withProfile(profile).build()); } @@ -274,7 +283,6 @@ public class RecipientStore implements RecipientResolver, ContactsStore, Profile @Override public void storeProfileKey(RecipientId recipientId, final ProfileKey profileKey) { synchronized (recipients) { - recipientId = getActualRecipientId(recipientId); final var recipient = recipients.get(recipientId); if (profileKey != null && profileKey.equals(recipient.getProfileKey())) { return; @@ -294,7 +302,6 @@ public class RecipientStore implements RecipientResolver, ContactsStore, Profile @Override public void storeProfileKeyCredential(RecipientId recipientId, final ProfileKeyCredential profileKeyCredential) { synchronized (recipients) { - recipientId = getActualRecipientId(recipientId); final var recipient = recipients.get(recipientId); storeRecipientLocked(recipientId, Recipient.newBuilder(recipient).withProfileKeyCredential(profileKeyCredential).build()); @@ -307,6 +314,10 @@ public class RecipientStore implements RecipientResolver, ContactsStore, Profile } } + private void addRecipients(final Map recipients) { + this.recipients.putAll(recipients); + } + /** * @param isHighTrust true, if the number/uuid connection was obtained from a trusted source. * Has no effect, if the address contains only a number or a uuid. @@ -391,8 +402,10 @@ public class RecipientStore implements RecipientResolver, ContactsStore, Profile byNumberRecipient.getRecipientId(), byUuidRecipient.getRecipientId()); updateRecipientAddressLocked(byUuidRecipient.getRecipientId(), address); - mergeRecipientsLocked(byUuidRecipient.getRecipientId(), byNumberRecipient.getRecipientId()); - return new Pair<>(byUuidRecipient.getRecipientId(), byNumber.map(Recipient::getRecipientId)); + // Create a fixed RecipientId that won't update its id after merge + final var toBeMergedRecipientId = new RecipientId(byNumberRecipient.getRecipientId().id(), null); + mergeRecipientsLocked(byUuidRecipient.getRecipientId(), toBeMergedRecipientId); + return new Pair<>(byUuidRecipient.getRecipientId(), Optional.of(toBeMergedRecipientId)); } private RecipientId addNewRecipientLocked(final RecipientAddress address) { @@ -403,12 +416,11 @@ public class RecipientStore implements RecipientResolver, ContactsStore, Profile } private void updateRecipientAddressLocked(RecipientId recipientId, final RecipientAddress address) { - recipientId = getActualRecipientId(recipientId); final var recipient = recipients.get(recipientId); storeRecipientLocked(recipientId, Recipient.newBuilder(recipient).withAddress(address).build()); } - private RecipientId getActualRecipientId(RecipientId recipientId) { + long getActualRecipientId(long recipientId) { while (recipientsMerged.containsKey(recipientId)) { final var newRecipientId = recipientsMerged.get(recipientId); logger.debug("Using {} instead of {}, because recipients have been merged", newRecipientId, recipientId); @@ -440,7 +452,7 @@ public class RecipientStore implements RecipientResolver, ContactsStore, Profile : toBeMergedRecipient.getProfileKeyCredential(), recipient.getProfile() != null ? recipient.getProfile() : toBeMergedRecipient.getProfile())); recipients.remove(toBeMergedRecipientId); - recipientsMerged.put(toBeMergedRecipientId, recipientId); + recipientsMerged.put(toBeMergedRecipientId.id(), recipientId.id()); saveLocked(); } @@ -467,7 +479,7 @@ public class RecipientStore implements RecipientResolver, ContactsStore, Profile } private RecipientId nextIdLocked() { - return new RecipientId(++this.lastId); + return new RecipientId(++this.lastId, this); } private void saveLocked() { diff --git a/lib/src/main/java/org/asamk/signal/manager/storage/senderKeys/SenderKeyRecordStore.java b/lib/src/main/java/org/asamk/signal/manager/storage/senderKeys/SenderKeyRecordStore.java index fb26fa00..caddebcc 100644 --- a/lib/src/main/java/org/asamk/signal/manager/storage/senderKeys/SenderKeyRecordStore.java +++ b/lib/src/main/java/org/asamk/signal/manager/storage/senderKeys/SenderKeyRecordStore.java @@ -17,6 +17,7 @@ import java.util.Arrays; import java.util.HashMap; import java.util.List; import java.util.Map; +import java.util.Objects; import java.util.UUID; import java.util.regex.Matcher; import java.util.regex.Pattern; @@ -139,9 +140,14 @@ public class SenderKeyRecordStore implements org.whispersystems.libsignal.groups return Arrays.stream(files) .map(f -> senderKeyFileNamePattern.matcher(f.getName())) .filter(Matcher::matches) - .map(matcher -> new Key(RecipientId.of(Long.parseLong(matcher.group(1))), - Integer.parseInt(matcher.group(2)), - UUID.fromString(matcher.group(3)))) + .map(matcher -> { + final var recipientId = resolver.resolveRecipient(Long.parseLong(matcher.group(1))); + if (recipientId == null) { + return null; + } + return new Key(recipientId, Integer.parseInt(matcher.group(2)), UUID.fromString(matcher.group(3))); + }) + .filter(Objects::nonNull) .collect(Collectors.toList()); } diff --git a/lib/src/main/java/org/asamk/signal/manager/storage/senderKeys/SenderKeySharedStore.java b/lib/src/main/java/org/asamk/signal/manager/storage/senderKeys/SenderKeySharedStore.java index 08197aec..ba852338 100644 --- a/lib/src/main/java/org/asamk/signal/manager/storage/senderKeys/SenderKeySharedStore.java +++ b/lib/src/main/java/org/asamk/signal/manager/storage/senderKeys/SenderKeySharedStore.java @@ -47,7 +47,11 @@ public class SenderKeySharedStore { final var storage = objectMapper.readValue(inputStream, Storage.class); final var sharedSenderKeys = new HashMap>(); for (final var senderKey : storage.sharedSenderKeys) { - final var entry = new SenderKeySharedEntry(RecipientId.of(senderKey.recipientId), senderKey.deviceId); + final var recipientId = resolver.resolveRecipient(senderKey.recipientId); + if (recipientId == null) { + continue; + } + final var entry = new SenderKeySharedEntry(recipientId, senderKey.deviceId); final var uuid = UuidUtil.parseOrNull(senderKey.distributionId); if (uuid == null) { logger.warn("Read invalid distribution id from storage {}, ignoring", senderKey.distributionId); diff --git a/lib/src/main/java/org/asamk/signal/manager/storage/sessions/SessionStore.java b/lib/src/main/java/org/asamk/signal/manager/storage/sessions/SessionStore.java index 627ef45e..8011a69d 100644 --- a/lib/src/main/java/org/asamk/signal/manager/storage/sessions/SessionStore.java +++ b/lib/src/main/java/org/asamk/signal/manager/storage/sessions/SessionStore.java @@ -238,8 +238,14 @@ public class SessionStore implements SignalServiceSessionStore { return Arrays.stream(files) .map(f -> sessionFileNamePattern.matcher(f.getName())) .filter(Matcher::matches) - .map(matcher -> new Key(RecipientId.of(Long.parseLong(matcher.group(1))), - Integer.parseInt(matcher.group(2)))) + .map(matcher -> { + final var recipientId = resolver.resolveRecipient(Long.parseLong(matcher.group(1))); + if (recipientId == null) { + return null; + } + return new Key(recipientId, Integer.parseInt(matcher.group(2))); + }) + .filter(Objects::nonNull) .collect(Collectors.toList()); } -- 2.51.0 From e9caf21bd3ff5e3d90191f5b44bc5c1df640523a Mon Sep 17 00:00:00 2001 From: AsamK Date: Tue, 7 Dec 2021 00:02:47 +0100 Subject: [PATCH 15/16] Print uuid in listIdentities command if number unknown --- .../java/org/asamk/signal/commands/ListIdentitiesCommand.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/org/asamk/signal/commands/ListIdentitiesCommand.java b/src/main/java/org/asamk/signal/commands/ListIdentitiesCommand.java index 5a442bd9..680df886 100644 --- a/src/main/java/org/asamk/signal/commands/ListIdentitiesCommand.java +++ b/src/main/java/org/asamk/signal/commands/ListIdentitiesCommand.java @@ -31,7 +31,7 @@ public class ListIdentitiesCommand implements JsonRpcLocalCommand { private static void printIdentityFingerprint(PlainTextWriter writer, Identity theirId) { writer.println("{}: {} Added: {} Fingerprint: {} Safety Number: {}", - theirId.recipient().number().orElse(null), + theirId.recipient().getLegacyIdentifier(), theirId.trustLevel(), theirId.dateAdded(), Hex.toString(theirId.getFingerprint()), -- 2.51.0 From c3f05395267a72a6bb102f168fc1d6a3ec4d1dbf Mon Sep 17 00:00:00 2001 From: AsamK Date: Wed, 8 Dec 2021 22:31:49 +0100 Subject: [PATCH 16/16] Update libsignal-service-java --- CHANGELOG.md | 2 +- lib/build.gradle.kts | 2 +- lib/src/main/java/org/asamk/signal/manager/ManagerImpl.java | 2 +- .../main/java/org/asamk/signal/manager/config/LiveConfig.java | 2 +- .../java/org/asamk/signal/manager/config/SandboxConfig.java | 2 +- .../java/org/asamk/signal/manager/storage/SignalAccount.java | 3 +-- 6 files changed, 6 insertions(+), 7 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 6d8912cc..8a55013b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,7 +1,7 @@ # Changelog ## [Unreleased] -**Attention**: Now requires Java 17 and libsignal-client version 0.10 +**Attention**: Now requires Java 17 and libsignal-client version 0.11 ### Added - The daemon command now provides a JSON-RPC based socket interface (`--socket` and `--tcp`) diff --git a/lib/build.gradle.kts b/lib/build.gradle.kts index d3007f2a..ae626bc9 100644 --- a/lib/build.gradle.kts +++ b/lib/build.gradle.kts @@ -14,7 +14,7 @@ repositories { } dependencies { - implementation("com.github.turasa", "signal-service-java", "2.15.3_unofficial_34") + implementation("com.github.turasa", "signal-service-java", "2.15.3_unofficial_35") implementation("com.fasterxml.jackson.core", "jackson-databind", "2.13.0") implementation("com.google.protobuf", "protobuf-javalite", "3.11.4") implementation("org.bouncycastle", "bcprov-jdk15on", "1.69") diff --git a/lib/src/main/java/org/asamk/signal/manager/ManagerImpl.java b/lib/src/main/java/org/asamk/signal/manager/ManagerImpl.java index eedb1a59..b2dbe60a 100644 --- a/lib/src/main/java/org/asamk/signal/manager/ManagerImpl.java +++ b/lib/src/main/java/org/asamk/signal/manager/ManagerImpl.java @@ -275,7 +275,7 @@ public class ManagerImpl implements Manager { try { preKeyHelper.refreshPreKeysIfNecessary(); if (account.getAci() == null) { - account.setAci(dependencies.getAccountManager().getOwnAci()); + account.setAci(ACI.parseOrNull(dependencies.getAccountManager().getWhoAmI().getAci())); } updateAccountAttributes(null); } catch (AuthorizationFailedException e) { diff --git a/lib/src/main/java/org/asamk/signal/manager/config/LiveConfig.java b/lib/src/main/java/org/asamk/signal/manager/config/LiveConfig.java index 0da1f2f9..ec9099ef 100644 --- a/lib/src/main/java/org/asamk/signal/manager/config/LiveConfig.java +++ b/lib/src/main/java/org/asamk/signal/manager/config/LiveConfig.java @@ -46,7 +46,7 @@ class LiveConfig { private final static Optional proxy = Optional.absent(); private final static byte[] zkGroupServerPublicParams = Base64.getDecoder() - .decode("AMhf5ywVwITZMsff/eCyudZx9JDmkkkbV6PInzG4p8x3VqVJSFiMvnvlEKWuRob/1eaIetR31IYeAbm0NdOuHH8Qi+Rexi1wLlpzIo1gstHWBfZzy1+qHRV5A4TqPp15YzBPm0WSggW6PbSn+F4lf57VCnHF7p8SvzAA2ZZJPYJURt8X7bbg+H3i+PEjH9DXItNEqs2sNcug37xZQDLm7X36nOoGPs54XsEGzPdEV+itQNGUFEjY6X9Uv+Acuks7NpyGvCoKxGwgKgE5XyJ+nNKlyHHOLb6N1NuHyBrZrgtY"); + .decode("AMhf5ywVwITZMsff/eCyudZx9JDmkkkbV6PInzG4p8x3VqVJSFiMvnvlEKWuRob/1eaIetR31IYeAbm0NdOuHH8Qi+Rexi1wLlpzIo1gstHWBfZzy1+qHRV5A4TqPp15YzBPm0WSggW6PbSn+F4lf57VCnHF7p8SvzAA2ZZJPYJURt8X7bbg+H3i+PEjH9DXItNEqs2sNcug37xZQDLm7X36nOoGPs54XsEGzPdEV+itQNGUFEjY6X9Uv+Acuks7NpyGvCoKxGwgKgE5XyJ+nNKlyHHOLb6N1NuHyBrZrgtY/JYJHRooo5CEqYKBqdFnmbTVGEkCvJKxLnjwKWf+fEPoWeQFj5ObDjcKMZf2Jm2Ae69x+ikU5gBXsRmoF94GXQ=="); static SignalServiceConfiguration createDefaultServiceConfiguration( final List interceptors diff --git a/lib/src/main/java/org/asamk/signal/manager/config/SandboxConfig.java b/lib/src/main/java/org/asamk/signal/manager/config/SandboxConfig.java index 975c95d3..f767a019 100644 --- a/lib/src/main/java/org/asamk/signal/manager/config/SandboxConfig.java +++ b/lib/src/main/java/org/asamk/signal/manager/config/SandboxConfig.java @@ -46,7 +46,7 @@ class SandboxConfig { private final static Optional proxy = Optional.absent(); private final static byte[] zkGroupServerPublicParams = Base64.getDecoder() - .decode("ABSY21VckQcbSXVNCGRYJcfWHiAMZmpTtTELcDmxgdFbtp/bWsSxZdMKzfCp8rvIs8ocCU3B37fT3r4Mi5qAemeGeR2X+/YmOGR5ofui7tD5mDQfstAI9i+4WpMtIe8KC3wU5w3Inq3uNWVmoGtpKndsNfwJrCg0Hd9zmObhypUnSkfYn2ooMOOnBpfdanRtrvetZUayDMSC5iSRcXKpdlukrpzzsCIvEwjwQlJYVPOQPj4V0F4UXXBdHSLK05uoPBCQG8G9rYIGedYsClJXnbrgGYG3eMTG5hnx4X4ntARB"); + .decode("ABSY21VckQcbSXVNCGRYJcfWHiAMZmpTtTELcDmxgdFbtp/bWsSxZdMKzfCp8rvIs8ocCU3B37fT3r4Mi5qAemeGeR2X+/YmOGR5ofui7tD5mDQfstAI9i+4WpMtIe8KC3wU5w3Inq3uNWVmoGtpKndsNfwJrCg0Hd9zmObhypUnSkfYn2ooMOOnBpfdanRtrvetZUayDMSC5iSRcXKpdlukrpzzsCIvEwjwQlJYVPOQPj4V0F4UXXBdHSLK05uoPBCQG8G9rYIGedYsClJXnbrgGYG3eMTG5hnx4X4ntARBgELuMWWUEEfSK0mjXg+/2lPmWcTZWR9nkqgQQP0tbzuiPm74H2wMO4u1Wafe+UwyIlIT9L7KLS19Aw8r4sPrXQ=="); static SignalServiceConfiguration createDefaultServiceConfiguration( final List interceptors 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 c5f659fa..364c61e9 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 @@ -63,7 +63,6 @@ import java.util.Base64; import java.util.Date; import java.util.HashSet; import java.util.List; -import java.util.UUID; public class SignalAccount implements Closeable { @@ -413,7 +412,7 @@ public class SignalAccount implements Closeable { registered = Utils.getNotNullNode(rootNode, "registered").asBoolean(); if (rootNode.hasNonNull("uuid")) { try { - aci = ACI.from(UUID.fromString(rootNode.get("uuid").asText())); + aci = ACI.parseOrThrow(rootNode.get("uuid").asText()); } catch (IllegalArgumentException e) { throw new IOException("Config file contains an invalid uuid, needs to be a valid UUID", e); } -- 2.51.0