Initial WebSocket refactor.

This commit is contained in:
Cody Henthorne
2021-07-09 10:01:24 -04:00
committed by Greyson Parrelli
parent 916006e664
commit 5d6d78a51e
30 changed files with 1438 additions and 869 deletions

View File

@@ -16,7 +16,6 @@ import org.thoughtcrime.securesms.database.DatabaseFactory;
import org.thoughtcrime.securesms.database.RecipientDatabase;
import org.thoughtcrime.securesms.dependencies.ApplicationDependencies;
import org.thoughtcrime.securesms.keyvalue.SignalStore;
import org.thoughtcrime.securesms.messages.IncomingMessageObserver;
import org.thoughtcrime.securesms.payments.MobileCoinPublicAddress;
import org.thoughtcrime.securesms.payments.MobileCoinPublicAddressProfileUtil;
import org.thoughtcrime.securesms.payments.PaymentsAddressException;
@@ -27,10 +26,9 @@ import org.thoughtcrime.securesms.recipients.RecipientUtil;
import org.whispersystems.libsignal.IdentityKey;
import org.whispersystems.libsignal.IdentityKeyPair;
import org.whispersystems.libsignal.InvalidKeyException;
import org.whispersystems.libsignal.util.Pair;
import org.whispersystems.libsignal.util.guava.Optional;
import org.whispersystems.signalservice.api.SignalServiceAccountManager;
import org.whispersystems.signalservice.api.SignalServiceMessagePipe;
import org.whispersystems.signalservice.api.SignalServiceMessageReceiver;
import org.whispersystems.signalservice.api.crypto.InvalidCiphertextException;
import org.whispersystems.signalservice.api.crypto.ProfileCipher;
import org.whispersystems.signalservice.api.crypto.UnidentifiedAccess;
@@ -38,18 +36,14 @@ import org.whispersystems.signalservice.api.crypto.UnidentifiedAccessPair;
import org.whispersystems.signalservice.api.profiles.ProfileAndCredential;
import org.whispersystems.signalservice.api.profiles.SignalServiceProfile;
import org.whispersystems.signalservice.api.push.SignalServiceAddress;
import org.whispersystems.signalservice.api.push.exceptions.NotFoundException;
import org.whispersystems.signalservice.api.push.exceptions.PushNetworkException;
import org.whispersystems.signalservice.api.services.ProfileService;
import org.whispersystems.signalservice.api.util.StreamDetails;
import org.whispersystems.signalservice.internal.ServiceResponse;
import org.whispersystems.signalservice.internal.push.SignalServiceProtos;
import org.whispersystems.signalservice.internal.util.concurrent.CascadingFuture;
import org.whispersystems.signalservice.internal.util.concurrent.ListenableFuture;
import java.io.IOException;
import java.util.Arrays;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;
import io.reactivex.rxjava3.core.Single;
/**
* Aids in the retrieval and decryption of profiles.
@@ -67,40 +61,26 @@ public final class ProfileUtil {
@NonNull SignalServiceProfile.RequestType requestType)
throws IOException
{
try {
return retrieveProfile(context, recipient, requestType).get(10, TimeUnit.SECONDS);
} catch (ExecutionException e) {
if (e.getCause() instanceof PushNetworkException) {
throw (PushNetworkException) e.getCause();
} else if (e.getCause() instanceof NotFoundException) {
throw (NotFoundException) e.getCause();
} else {
throw new IOException(e);
}
} catch (InterruptedException | TimeoutException e) {
throw new PushNetworkException(e);
}
ProfileService profileService = new ProfileService(ApplicationDependencies.getGroupsV2Operations().getProfileOperations(),
ApplicationDependencies.getSignalServiceMessageReceiver(),
ApplicationDependencies.getSignalWebSocket());
Pair<Recipient, ServiceResponse<ProfileAndCredential>> response = retrieveProfile(context, recipient, requestType, profileService).blockingGet();
return new ProfileService.ProfileResponseProcessor(response.second()).getResultOrThrow();
}
public static @NonNull ListenableFuture<ProfileAndCredential> retrieveProfile(@NonNull Context context,
@NonNull Recipient recipient,
@NonNull SignalServiceProfile.RequestType requestType)
public static Single<Pair<Recipient, ServiceResponse<ProfileAndCredential>>> retrieveProfile(@NonNull Context context,
@NonNull Recipient recipient,
@NonNull SignalServiceProfile.RequestType requestType,
@NonNull ProfileService profileService)
{
SignalServiceAddress address = toSignalServiceAddress(context, recipient);
Optional<UnidentifiedAccess> unidentifiedAccess = getUnidentifiedAccess(context, recipient);
Optional<ProfileKey> profileKey = ProfileKeyUtil.profileKeyOptional(recipient.getProfileKey());
if (unidentifiedAccess.isPresent()) {
return new CascadingFuture<>(Arrays.asList(() -> getPipeRetrievalFuture(address, profileKey, unidentifiedAccess, requestType),
() -> getSocketRetrievalFuture(address, profileKey, unidentifiedAccess, requestType),
() -> getPipeRetrievalFuture(address, profileKey, Optional.absent(), requestType),
() -> getSocketRetrievalFuture(address, profileKey, Optional.absent(), requestType)),
e -> !(e instanceof NotFoundException));
} else {
return new CascadingFuture<>(Arrays.asList(() -> getPipeRetrievalFuture(address, profileKey, Optional.absent(), requestType),
() -> getSocketRetrievalFuture(address, profileKey, Optional.absent(), requestType)),
e -> !(e instanceof NotFoundException));
}
return profileService.getProfile(address, profileKey, unidentifiedAccess, requestType)
.map(p -> new Pair<>(recipient, p))
.onErrorReturn(t -> new Pair<>(recipient, ServiceResponse.forUnknownError(t)));
}
public static @Nullable String decryptString(@NonNull ProfileKey profileKey, @Nullable byte[] encryptedString)
@@ -126,7 +106,7 @@ public final class ProfileUtil {
@WorkerThread
public static @NonNull MobileCoinPublicAddress getAddressForRecipient(@NonNull Recipient recipient)
throws InterruptedException, ExecutionException, PaymentsAddressException
throws IOException, PaymentsAddressException
{
ProfileKey profileKey;
try {
@@ -135,7 +115,7 @@ public final class ProfileUtil {
Log.w(TAG, "Profile key not available for " + recipient.getId());
throw new PaymentsAddressException(PaymentsAddressException.Code.NO_PROFILE_KEY);
}
ProfileAndCredential profileAndCredential = ProfileUtil.retrieveProfile(ApplicationDependencies.getApplication(), recipient, SignalServiceProfile.RequestType.PROFILE).get();
ProfileAndCredential profileAndCredential = ProfileUtil.retrieveProfileSync(ApplicationDependencies.getApplication(), recipient, SignalServiceProfile.RequestType.PROFILE);
SignalServiceProfile profile = profileAndCredential.getProfile();
byte[] encryptedPaymentsAddress = profile.getPaymentAddress();
@@ -277,32 +257,6 @@ public final class ProfileUtil {
}
}
private static @NonNull ListenableFuture<ProfileAndCredential> getPipeRetrievalFuture(@NonNull SignalServiceAddress address,
@NonNull Optional<ProfileKey> profileKey,
@NonNull Optional<UnidentifiedAccess> unidentifiedAccess,
@NonNull SignalServiceProfile.RequestType requestType)
throws IOException
{
SignalServiceMessagePipe authPipe = IncomingMessageObserver.getPipe();
SignalServiceMessagePipe unidentifiedPipe = IncomingMessageObserver.getUnidentifiedPipe();
SignalServiceMessagePipe pipe = unidentifiedPipe != null && unidentifiedAccess.isPresent() ? unidentifiedPipe
: authPipe;
if (pipe != null) {
return pipe.getProfile(address, profileKey, unidentifiedAccess, requestType);
}
throw new IOException("No pipe available!");
}
private static @NonNull ListenableFuture<ProfileAndCredential> getSocketRetrievalFuture(@NonNull SignalServiceAddress address,
@NonNull Optional<ProfileKey> profileKey,
@NonNull Optional<UnidentifiedAccess> unidentifiedAccess,
@NonNull SignalServiceProfile.RequestType requestType)
{
SignalServiceMessageReceiver receiver = ApplicationDependencies.getSignalServiceMessageReceiver();
return receiver.retrieveProfile(address, profileKey, unidentifiedAccess, requestType);
}
private static Optional<UnidentifiedAccess> getUnidentifiedAccess(@NonNull Context context, @NonNull Recipient recipient) {
Optional<UnidentifiedAccessPair> unidentifiedAccess = UnidentifiedAccessUtil.getAccessFor(context, recipient, false);