Refactor resolve recipient

This commit is contained in:
AsamK 2022-10-08 17:41:42 +02:00
parent 7ab013cee9
commit 51fef48016
4 changed files with 181 additions and 59 deletions

View file

@ -1179,38 +1179,11 @@ public class SignalAccount implements Closeable {
}
public RecipientResolver getRecipientResolver() {
return new RecipientResolver() {
@Override
public RecipientId resolveRecipient(final RecipientAddress address) {
return getRecipientStore().resolveRecipient(address);
}
@Override
public RecipientId resolveRecipient(final long recipientId) {
return getRecipientStore().resolveRecipient(recipientId);
}
};
return new RecipientResolver.RecipientResolverWrapper(this::getRecipientStore);
}
public RecipientTrustedResolver getRecipientTrustedResolver() {
return new RecipientTrustedResolver() {
@Override
public RecipientId resolveSelfRecipientTrusted(final RecipientAddress address) {
return getRecipientStore().resolveSelfRecipientTrusted(address);
}
@Override
public RecipientId resolveRecipientTrusted(final SignalServiceAddress address) {
return getRecipientStore().resolveRecipientTrusted(address);
}
@Override
public RecipientId resolveRecipientTrusted(
final Optional<ACI> aci, final Optional<PNI> pni, final Optional<String> number
) {
return getRecipientStore().resolveRecipientTrusted(aci, pni, number);
}
};
return new RecipientTrustedResolver.RecipientTrustedResolverWrapper(this::getRecipientStore);
}
public RecipientAddressResolver getRecipientAddressResolver() {

View file

@ -1,24 +1,50 @@
package org.asamk.signal.manager.storage.recipients;
import org.asamk.signal.manager.storage.Utils;
import org.whispersystems.signalservice.api.push.ServiceId;
import org.whispersystems.signalservice.api.push.SignalServiceAddress;
import java.util.function.Supplier;
public interface RecipientResolver {
RecipientId resolveRecipient(RecipientAddress address);
RecipientId resolveRecipient(long recipientId);
default RecipientId resolveRecipient(String identifier) {
return resolveRecipient(Utils.getRecipientAddressFromIdentifier(identifier));
}
RecipientId resolveRecipient(String identifier);
default RecipientId resolveRecipient(SignalServiceAddress address) {
return resolveRecipient(new RecipientAddress(address));
}
default RecipientId resolveRecipient(ServiceId serviceId) {
return resolveRecipient(new RecipientAddress(serviceId));
RecipientId resolveRecipient(ServiceId serviceId);
class RecipientResolverWrapper implements RecipientResolver {
private final Supplier<RecipientResolver> recipientResolverSupplier;
public RecipientResolverWrapper(final Supplier<RecipientResolver> recipientResolverSupplier) {
this.recipientResolverSupplier = recipientResolverSupplier;
}
@Override
public RecipientId resolveRecipient(final RecipientAddress address) {
return recipientResolverSupplier.get().resolveRecipient(address);
}
@Override
public RecipientId resolveRecipient(final long recipientId) {
return recipientResolverSupplier.get().resolveRecipient(recipientId);
}
@Override
public RecipientId resolveRecipient(final String identifier) {
return recipientResolverSupplier.get().resolveRecipient(identifier);
}
@Override
public RecipientId resolveRecipient(final ServiceId serviceId) {
return recipientResolverSupplier.get().resolveRecipient(serviceId);
}
}
}

View file

@ -145,6 +145,44 @@ public class RecipientStore implements RecipientIdCreator, RecipientResolver, Re
}
}
@Override
public RecipientId resolveRecipient(final String identifier) {
if (UuidUtil.isUuid(identifier)) {
return resolveRecipient(ServiceId.parseOrThrow(identifier));
} else {
return resolveRecipientByNumber(identifier);
}
}
private RecipientId resolveRecipientByNumber(final String number) {
synchronized (recipientsLock) {
final RecipientId recipientId;
try (final var connection = database.getConnection()) {
connection.setAutoCommit(false);
recipientId = resolveRecipientLocked(connection, number);
connection.commit();
} catch (SQLException e) {
throw new RuntimeException("Failed read recipient store", e);
}
return recipientId;
}
}
@Override
public RecipientId resolveRecipient(final ServiceId serviceId) {
synchronized (recipientsLock) {
final RecipientId recipientId;
try (final var connection = database.getConnection()) {
connection.setAutoCommit(false);
recipientId = resolveRecipientLocked(connection, serviceId);
connection.commit();
} catch (SQLException e) {
throw new RuntimeException("Failed read recipient store", e);
}
return recipientId;
}
}
/**
* Should only be used for recipientIds from the database.
* Where the foreign key relations ensure a valid recipientId.
@ -170,27 +208,37 @@ public class RecipientStore implements RecipientIdCreator, RecipientResolver, Re
number));
}
return resolveRecipient(new RecipientAddress(serviceId, number), false, false);
return resolveRecipient(serviceId);
}
return byNumber.get().id();
}
public RecipientId resolveRecipient(RecipientAddress address) {
return resolveRecipient(address, false, false);
synchronized (recipientsLock) {
final RecipientId recipientId;
try (final var connection = database.getConnection()) {
connection.setAutoCommit(false);
recipientId = resolveRecipientLocked(connection, address);
connection.commit();
} catch (SQLException e) {
throw new RuntimeException("Failed read recipient store", e);
}
return recipientId;
}
}
@Override
public RecipientId resolveSelfRecipientTrusted(RecipientAddress address) {
return resolveRecipient(address, true, true);
return resolveRecipientTrusted(address, true);
}
public RecipientId resolveRecipientTrusted(RecipientAddress address) {
return resolveRecipient(address, true, false);
return resolveRecipientTrusted(address, false);
}
@Override
public RecipientId resolveRecipientTrusted(SignalServiceAddress address) {
return resolveRecipient(new RecipientAddress(address), true, false);
return resolveRecipientTrusted(new RecipientAddress(address), false);
}
@Override
@ -198,7 +246,7 @@ public class RecipientStore implements RecipientIdCreator, RecipientResolver, Re
final Optional<ACI> aci, final Optional<PNI> pni, final Optional<String> number
) {
final var serviceId = aci.map(a -> (ServiceId) a).or(() -> pni);
return resolveRecipient(new RecipientAddress(serviceId, number), true, false);
return resolveRecipientTrusted(new RecipientAddress(serviceId, number), false);
}
@Override
@ -552,16 +600,12 @@ public class RecipientStore implements RecipientIdCreator, RecipientResolver, Re
}
}
/**
* @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.
*/
private RecipientId resolveRecipient(RecipientAddress address, boolean isHighTrust, boolean isSelf) {
private RecipientId resolveRecipientTrusted(RecipientAddress address, boolean isSelf) {
final Pair<RecipientId, Optional<RecipientId>> pair;
synchronized (recipientsLock) {
try (final var connection = database.getConnection()) {
connection.setAutoCommit(false);
pair = resolveRecipientLocked(connection, address, isHighTrust, isSelf);
pair = resolveRecipientTrustedLocked(connection, address, isSelf);
connection.commit();
} catch (SQLException e) {
throw new RuntimeException("Failed update recipient store", e);
@ -579,12 +623,12 @@ public class RecipientStore implements RecipientIdCreator, RecipientResolver, Re
return pair.first();
}
private Pair<RecipientId, Optional<RecipientId>> resolveRecipientLocked(
Connection connection, RecipientAddress address, boolean isHighTrust, boolean isSelf
private Pair<RecipientId, Optional<RecipientId>> resolveRecipientTrustedLocked(
Connection connection, RecipientAddress address, boolean isSelf
) throws SQLException {
if (isHighTrust && !isSelf) {
if (!isSelf) {
if (selfAddressProvider.getSelfAddress().matches(address)) {
isHighTrust = false;
return new Pair<>(resolveRecipientLocked(connection, address), Optional.empty());
}
}
final var byNumber = address.number().isEmpty()
@ -596,16 +640,10 @@ public class RecipientStore implements RecipientIdCreator, RecipientResolver, Re
if (byNumber.isEmpty() && byUuid.isEmpty()) {
logger.debug("Got new recipient, both uuid and number are unknown");
if (isHighTrust || address.serviceId().isEmpty() || address.number().isEmpty()) {
return new Pair<>(addNewRecipient(connection, address), Optional.empty());
}
return new Pair<>(addNewRecipient(connection, new RecipientAddress(address.serviceId().get())),
Optional.empty());
return new Pair<>(addNewRecipient(connection, address), Optional.empty());
}
if (!isHighTrust || address.serviceId().isEmpty() || address.number().isEmpty() || byNumber.equals(byUuid)) {
if (address.serviceId().isEmpty() || address.number().isEmpty() || byNumber.equals(byUuid)) {
return new Pair<>(byUuid.or(() -> byNumber).map(RecipientWithAddress::id).get(), Optional.empty());
}
@ -661,6 +699,64 @@ public class RecipientStore implements RecipientIdCreator, RecipientResolver, Re
return new Pair<>(byUuidRecipient.id(), Optional.of(toBeMergedRecipientId));
}
private RecipientId resolveRecipientLocked(
Connection connection, RecipientAddress address
) throws SQLException {
final var byServiceId = address.serviceId().isEmpty()
? Optional.<RecipientWithAddress>empty()
: findByServiceId(connection, address.serviceId().get());
if (byServiceId.isPresent()) {
return byServiceId.get().id();
}
final var byPni = address.pni().isEmpty()
? Optional.<RecipientWithAddress>empty()
: findByServiceId(connection, address.pni().get());
if (byPni.isPresent()) {
return byPni.get().id();
}
final var byNumber = address.number().isEmpty()
? Optional.<RecipientWithAddress>empty()
: findByNumber(connection, address.number().get());
if (byNumber.isPresent()) {
return byNumber.get().id();
}
logger.debug("Got new recipient, both serviceId and number are unknown");
if (address.serviceId().isEmpty()) {
return addNewRecipient(connection, address);
}
return addNewRecipient(connection, new RecipientAddress(address.serviceId().get()));
}
private RecipientId resolveRecipientLocked(Connection connection, ServiceId serviceId) throws SQLException {
final var recipient = findByServiceId(connection, serviceId);
if (recipient.isEmpty()) {
logger.debug("Got new recipient, serviceId is unknown");
return addNewRecipient(connection, new RecipientAddress(serviceId));
}
return recipient.get().id();
}
private RecipientId resolveRecipientLocked(Connection connection, String number) throws SQLException {
final var recipient = findByNumber(connection, number);
if (recipient.isEmpty()) {
logger.debug("Got new recipient, number is unknown");
return addNewRecipient(connection, new RecipientAddress(null, number));
}
return recipient.get().id();
}
private RecipientId addNewRecipient(
final Connection connection, final RecipientAddress address
) throws SQLException {

View file

@ -5,6 +5,7 @@ import org.whispersystems.signalservice.api.push.PNI;
import org.whispersystems.signalservice.api.push.SignalServiceAddress;
import java.util.Optional;
import java.util.function.Supplier;
public interface RecipientTrustedResolver {
@ -13,4 +14,30 @@ public interface RecipientTrustedResolver {
RecipientId resolveRecipientTrusted(SignalServiceAddress address);
RecipientId resolveRecipientTrusted(Optional<ACI> aci, Optional<PNI> pni, Optional<String> number);
class RecipientTrustedResolverWrapper implements RecipientTrustedResolver {
private final Supplier<RecipientTrustedResolver> recipientTrustedResolverSupplier;
public RecipientTrustedResolverWrapper(final Supplier<RecipientTrustedResolver> recipientTrustedResolverSupplier) {
this.recipientTrustedResolverSupplier = recipientTrustedResolverSupplier;
}
@Override
public RecipientId resolveSelfRecipientTrusted(final RecipientAddress address) {
return recipientTrustedResolverSupplier.get().resolveSelfRecipientTrusted(address);
}
@Override
public RecipientId resolveRecipientTrusted(final SignalServiceAddress address) {
return recipientTrustedResolverSupplier.get().resolveRecipientTrusted(address);
}
@Override
public RecipientId resolveRecipientTrusted(
final Optional<ACI> aci, final Optional<PNI> pni, final Optional<String> number
) {
return recipientTrustedResolverSupplier.get().resolveRecipientTrusted(aci, pni, number);
}
}
}