use of org.whispersystems.signalservice.internal.ServiceResponse in project Signal-Android by WhisperSystems.
the class DonationsServiceTest method givenASubscriberId_whenIGetAnUnsuccessfulResponse_thenItIsMappedWithTheCorrectStatusCodeAndEmptyObject.
@Test
public void givenASubscriberId_whenIGetAnUnsuccessfulResponse_thenItIsMappedWithTheCorrectStatusCodeAndEmptyObject() throws Exception {
// GIVEN
SubscriberId subscriberId = SubscriberId.generate();
when(pushServiceSocket.getSubscription(subscriberId.serialize())).thenThrow(new NonSuccessfulResponseCodeException(403));
// WHEN
TestObserver<ServiceResponse<ActiveSubscription>> testObserver = testSubject.getSubscription(subscriberId).test();
// THEN
TEST_SCHEDULER.triggerActions();
verify(pushServiceSocket).getSubscription(subscriberId.serialize());
testObserver.assertComplete().assertValue(value -> value.getStatus() == 403 && !value.getResult().isPresent());
}
use of org.whispersystems.signalservice.internal.ServiceResponse in project Signal-Android by WhisperSystems.
the class ProfileService method getProfile.
public Single<ServiceResponse<ProfileAndCredential>> getProfile(SignalServiceAddress address, Optional<ProfileKey> profileKey, Optional<UnidentifiedAccess> unidentifiedAccess, SignalServiceProfile.RequestType requestType, Locale locale) {
ServiceId serviceId = address.getServiceId();
SecureRandom random = new SecureRandom();
ProfileKeyCredentialRequestContext requestContext = null;
WebSocketProtos.WebSocketRequestMessage.Builder builder = WebSocketProtos.WebSocketRequestMessage.newBuilder().setId(random.nextLong()).setVerb("GET");
if (profileKey.isPresent()) {
ProfileKeyVersion profileKeyIdentifier = profileKey.get().getProfileKeyVersion(serviceId.uuid());
String version = profileKeyIdentifier.serialize();
if (requestType == SignalServiceProfile.RequestType.PROFILE_AND_CREDENTIAL) {
requestContext = clientZkProfileOperations.createProfileKeyCredentialRequestContext(random, serviceId.uuid(), profileKey.get());
ProfileKeyCredentialRequest request = requestContext.getRequest();
String credentialRequest = Hex.toStringCondensed(request.serialize());
builder.setPath(String.format("/v1/profile/%s/%s/%s", serviceId, version, credentialRequest));
} else {
builder.setPath(String.format("/v1/profile/%s/%s", serviceId, version));
}
} else {
builder.setPath(String.format("/v1/profile/%s", address.getIdentifier()));
}
builder.addHeaders(AcceptLanguagesUtil.getAcceptLanguageHeader(locale));
WebSocketProtos.WebSocketRequestMessage requestMessage = builder.build();
ResponseMapper<ProfileAndCredential> responseMapper = DefaultResponseMapper.extend(ProfileAndCredential.class).withResponseMapper(new ProfileResponseMapper(requestType, requestContext)).build();
return signalWebSocket.request(requestMessage, unidentifiedAccess).map(responseMapper::map).onErrorResumeNext(t -> restFallback(address, profileKey, unidentifiedAccess, requestType, locale)).onErrorReturn(ServiceResponse::forUnknownError);
}
use of org.whispersystems.signalservice.internal.ServiceResponse in project Signal-Android by WhisperSystems.
the class RetrieveProfileJob method onRun.
@Override
public void onRun() throws IOException, RetryLaterException {
if (!SignalStore.account().isRegistered()) {
Log.w(TAG, "Unregistered. Skipping.");
return;
}
Stopwatch stopwatch = new Stopwatch("RetrieveProfile");
RecipientDatabase recipientDatabase = SignalDatabase.recipients();
RecipientUtil.ensureUuidsAreAvailable(context, Stream.of(Recipient.resolvedList(recipientIds)).filter(r -> r.getRegistered() != RecipientDatabase.RegisteredState.NOT_REGISTERED).toList());
List<Recipient> recipients = Recipient.resolvedList(recipientIds);
stopwatch.split("resolve-ensure");
ProfileService profileService = new ProfileService(ApplicationDependencies.getGroupsV2Operations().getProfileOperations(), ApplicationDependencies.getSignalServiceMessageReceiver(), ApplicationDependencies.getSignalWebSocket());
List<Observable<Pair<Recipient, ServiceResponse<ProfileAndCredential>>>> requests = Stream.of(recipients).filter(Recipient::hasServiceId).map(r -> ProfileUtil.retrieveProfile(context, r, getRequestType(r), profileService).toObservable()).toList();
stopwatch.split("requests");
OperationState operationState = Observable.mergeDelayError(requests).observeOn(Schedulers.io(), true).scan(new OperationState(), (state, pair) -> {
Recipient recipient = pair.first();
ProfileService.ProfileResponseProcessor processor = new ProfileService.ProfileResponseProcessor(pair.second());
if (processor.hasResult()) {
state.profiles.add(processor.getResult(recipient));
} else if (processor.notFound()) {
Log.w(TAG, "Failed to find a profile for " + recipient.getId());
if (recipient.isRegistered()) {
state.unregistered.add(recipient.getId());
}
} else if (processor.genericIoError()) {
state.retries.add(recipient.getId());
} else {
Log.w(TAG, "Failed to retrieve profile for " + recipient.getId());
}
return state;
}).lastOrError().blockingGet();
stopwatch.split("responses");
Set<RecipientId> success = SetUtil.difference(recipientIds, operationState.retries);
Map<RecipientId, ServiceId> newlyRegistered = Stream.of(operationState.profiles).map(Pair::first).filterNot(Recipient::isRegistered).collect(Collectors.toMap(Recipient::getId, r -> r.getServiceId().orNull()));
// noinspection SimplifyStreamApiCallChains
Util.chunk(operationState.profiles, 150).stream().forEach(list -> {
SignalDatabase.runInTransaction(() -> {
for (Pair<Recipient, ProfileAndCredential> profile : list) {
process(profile.first(), profile.second());
}
});
});
recipientDatabase.markProfilesFetched(success, System.currentTimeMillis());
if (operationState.unregistered.size() > 0 || newlyRegistered.size() > 0) {
Log.i(TAG, "Marking " + newlyRegistered.size() + " users as registered and " + operationState.unregistered.size() + " users as unregistered.");
recipientDatabase.bulkUpdatedRegisteredStatus(newlyRegistered, operationState.unregistered);
}
stopwatch.split("process");
for (Pair<Recipient, ProfileAndCredential> profile : operationState.profiles) {
setIdentityKey(profile.first(), profile.second().getProfile().getIdentityKey());
}
stopwatch.split("identityKeys");
long keyCount = Stream.of(operationState.profiles).map(Pair::first).map(Recipient::getProfileKey).withoutNulls().count();
Log.d(TAG, String.format(Locale.US, "Started with %d recipient(s). Found %d profile(s), and had keys for %d of them. Will retry %d.", recipients.size(), operationState.profiles.size(), keyCount, operationState.retries.size()));
stopwatch.stop(TAG);
recipientIds.clear();
recipientIds.addAll(operationState.retries);
if (recipientIds.size() > 0) {
throw new RetryLaterException();
}
}
use of org.whispersystems.signalservice.internal.ServiceResponse in project Signal-Android by WhisperSystems.
the class SignalServiceAccountManager method getRegisteredUsersWithCdsh.
public Map<String, ACI> getRegisteredUsersWithCdsh(Set<String> e164numbers, String hexPublicKey, String hexCodeHash) throws IOException {
CdshAuthResponse auth = pushServiceSocket.getCdshAuth();
CdshService service = new CdshService(configuration, hexPublicKey, hexCodeHash);
Single<ServiceResponse<Map<String, ACI>>> result = service.getRegisteredUsers(auth.getUsername(), auth.getPassword(), e164numbers);
ServiceResponse<Map<String, ACI>> response;
try {
response = result.blockingGet();
} catch (Exception e) {
throw new RuntimeException("Unexpected exception when retrieving registered users!", e);
}
if (response.getResult().isPresent()) {
return response.getResult().get();
} else if (response.getApplicationError().isPresent()) {
throw new IOException(response.getApplicationError().get());
} else if (response.getExecutionError().isPresent()) {
throw new IOException(response.getExecutionError().get());
} else {
throw new IOException("Missing result!");
}
}
use of org.whispersystems.signalservice.internal.ServiceResponse in project Signal-Android by WhisperSystems.
the class DirectoryHelper method filterForUnlistedUsers.
/**
* Users can mark themselves as 'unlisted' in CDS, meaning that even if CDS says they're
* unregistered, they might actually be registered. We need to double-check users who we already
* have UUIDs for. Also, we only want to bother doing this for users we have conversations for,
* so we will also only check for users that have a thread.
*/
private static UnlistedResult filterForUnlistedUsers(@NonNull Context context, @NonNull Set<RecipientId> inactiveIds) {
List<Recipient> possiblyUnlisted = Stream.of(inactiveIds).map(Recipient::resolved).filter(Recipient::isRegistered).filter(Recipient::hasServiceId).filter(DirectoryHelper::hasCommunicatedWith).toList();
ProfileService profileService = new ProfileService(ApplicationDependencies.getGroupsV2Operations().getProfileOperations(), ApplicationDependencies.getSignalServiceMessageReceiver(), ApplicationDependencies.getSignalWebSocket());
List<Observable<Pair<Recipient, ServiceResponse<ProfileAndCredential>>>> requests = Stream.of(possiblyUnlisted).map(r -> ProfileUtil.retrieveProfile(context, r, SignalServiceProfile.RequestType.PROFILE, profileService).toObservable().timeout(5, TimeUnit.SECONDS).onErrorReturn(t -> new Pair<>(r, ServiceResponse.forUnknownError(t)))).toList();
return Observable.mergeDelayError(requests).observeOn(Schedulers.io(), true).scan(new UnlistedResult.Builder(), (builder, pair) -> {
Recipient recipient = pair.first();
ProfileService.ProfileResponseProcessor processor = new ProfileService.ProfileResponseProcessor(pair.second());
if (processor.hasResult()) {
builder.potentiallyActiveIds.add(recipient.getId());
} else if (processor.genericIoError() || !processor.notFound()) {
builder.retries.add(recipient.getId());
builder.potentiallyActiveIds.add(recipient.getId());
}
return builder;
}).lastOrError().map(UnlistedResult.Builder::build).blockingGet();
}
Aggregations