1 package org
.asamk
.signal
.manager
.helper
;
3 import org
.asamk
.signal
.manager
.SignalDependencies
;
4 import org
.asamk
.signal
.manager
.api
.RecipientIdentifier
;
5 import org
.asamk
.signal
.manager
.api
.UnregisteredRecipientException
;
6 import org
.asamk
.signal
.manager
.config
.ServiceConfig
;
7 import org
.asamk
.signal
.manager
.config
.ServiceEnvironmentConfig
;
8 import org
.asamk
.signal
.manager
.storage
.SignalAccount
;
9 import org
.asamk
.signal
.manager
.storage
.recipients
.RecipientAddress
;
10 import org
.asamk
.signal
.manager
.storage
.recipients
.RecipientId
;
11 import org
.slf4j
.Logger
;
12 import org
.slf4j
.LoggerFactory
;
13 import org
.whispersystems
.libsignal
.InvalidKeyException
;
14 import org
.whispersystems
.signalservice
.api
.push
.ACI
;
15 import org
.whispersystems
.signalservice
.api
.push
.SignalServiceAddress
;
16 import org
.whispersystems
.signalservice
.internal
.contacts
.crypto
.Quote
;
17 import org
.whispersystems
.signalservice
.internal
.contacts
.crypto
.UnauthenticatedQuoteException
;
18 import org
.whispersystems
.signalservice
.internal
.contacts
.crypto
.UnauthenticatedResponseException
;
20 import java
.io
.IOException
;
21 import java
.security
.SignatureException
;
22 import java
.util
.Collection
;
23 import java
.util
.HashSet
;
27 public class RecipientHelper
{
29 private final static Logger logger
= LoggerFactory
.getLogger(RecipientHelper
.class);
31 private final SignalAccount account
;
32 private final SignalDependencies dependencies
;
33 private final ServiceEnvironmentConfig serviceEnvironmentConfig
;
35 public RecipientHelper(final Context context
) {
36 this.account
= context
.getAccount();
37 this.dependencies
= context
.getDependencies();
38 this.serviceEnvironmentConfig
= dependencies
.getServiceEnvironmentConfig();
41 public SignalServiceAddress
resolveSignalServiceAddress(RecipientId recipientId
) {
42 final var address
= account
.getRecipientStore().resolveRecipientAddress(recipientId
);
43 if (address
.number().isEmpty() || address
.uuid().isPresent()) {
44 return address
.toSignalServiceAddress();
47 // Address in recipient store doesn't have a uuid, this shouldn't happen
48 // Try to retrieve the uuid from the server
49 final var number
= address
.number().get();
52 aci
= getRegisteredUser(number
);
53 } catch (UnregisteredRecipientException
| IOException e
) {
54 logger
.warn("Failed to get uuid for e164 number: {}", number
, e
);
55 // Return SignalServiceAddress with unknown UUID
56 return address
.toSignalServiceAddress();
58 return account
.getRecipientStore()
59 .resolveRecipientAddress(account
.getRecipientStore().resolveRecipient(aci
))
60 .toSignalServiceAddress();
63 public RecipientId
resolveRecipient(final SignalServiceAddress address
) {
64 return account
.getRecipientStore().resolveRecipient(address
);
67 public Set
<RecipientId
> resolveRecipients(Collection
<RecipientIdentifier
.Single
> recipients
) throws IOException
, UnregisteredRecipientException
{
68 final var recipientIds
= new HashSet
<RecipientId
>(recipients
.size());
69 for (var number
: recipients
) {
70 final var recipientId
= resolveRecipient(number
);
71 recipientIds
.add(recipientId
);
76 public RecipientId
resolveRecipient(final RecipientIdentifier
.Single recipient
) throws IOException
, UnregisteredRecipientException
{
77 if (recipient
instanceof RecipientIdentifier
.Uuid uuidRecipient
) {
78 return account
.getRecipientStore().resolveRecipient(ACI
.from(uuidRecipient
.uuid()));
80 final var number
= ((RecipientIdentifier
.Number
) recipient
).number();
81 return account
.getRecipientStore().resolveRecipient(number
, () -> {
83 return getRegisteredUser(number
);
84 } catch (Exception e
) {
91 public RecipientId
refreshRegisteredUser(RecipientId recipientId
) throws IOException
, UnregisteredRecipientException
{
92 final var address
= resolveSignalServiceAddress(recipientId
);
93 if (!address
.getNumber().isPresent()) {
96 final var number
= address
.getNumber().get();
97 final var uuid
= getRegisteredUser(number
);
98 return account
.getRecipientStore().resolveRecipientTrusted(new SignalServiceAddress(uuid
, number
));
101 public Map
<String
, ACI
> getRegisteredUsers(final Set
<String
> numbers
) throws IOException
{
102 final Map
<String
, ACI
> registeredUsers
;
104 registeredUsers
= dependencies
.getAccountManager()
105 .getRegisteredUsers(ServiceConfig
.getIasKeyStore(),
107 serviceEnvironmentConfig
.getCdsMrenclave());
108 } catch (Quote
.InvalidQuoteFormatException
| UnauthenticatedQuoteException
| SignatureException
| UnauthenticatedResponseException
| InvalidKeyException e
) {
109 throw new IOException(e
);
112 // Store numbers as recipients, so we have the number/uuid association
113 registeredUsers
.forEach((number
, aci
) -> account
.getRecipientStore()
114 .resolveRecipientTrusted(new SignalServiceAddress(aci
, number
)));
116 return registeredUsers
;
119 private ACI
getRegisteredUser(final String number
) throws IOException
, UnregisteredRecipientException
{
120 final Map
<String
, ACI
> aciMap
;
122 aciMap
= getRegisteredUsers(Set
.of(number
));
123 } catch (NumberFormatException e
) {
124 throw new UnregisteredRecipientException(new RecipientAddress(null, number
));
126 final var uuid
= aciMap
.get(number
);
128 throw new UnregisteredRecipientException(new RecipientAddress(null, number
));