use of org.whispersystems.signalservice.api.push.exceptions.PushNetworkException in project Signal-Android by WhisperSystems.
the class PushServiceSocket method sendGroupMessage.
public SendGroupMessageResponse sendGroupMessage(byte[] body, byte[] joinedUnidentifiedAccess, long timestamp, boolean online) throws IOException {
ServiceConnectionHolder connectionHolder = (ServiceConnectionHolder) getRandom(serviceClients, random);
String path = String.format(Locale.US, GROUP_MESSAGE_PATH, timestamp, online);
Request.Builder requestBuilder = new Request.Builder();
requestBuilder.url(String.format("%s%s", connectionHolder.getUrl(), path));
requestBuilder.put(RequestBody.create(MediaType.get("application/vnd.signal-messenger.mrm"), body));
requestBuilder.addHeader("Unidentified-Access-Key", Base64.encodeBytes(joinedUnidentifiedAccess));
if (signalAgent != null) {
requestBuilder.addHeader("X-Signal-Agent", signalAgent);
}
if (connectionHolder.getHostHeader().isPresent()) {
requestBuilder.addHeader("Host", connectionHolder.getHostHeader().get());
}
Call call = connectionHolder.getUnidentifiedClient().newCall(requestBuilder.build());
synchronized (connections) {
connections.add(call);
}
Response response;
try {
response = call.execute();
} catch (IOException e) {
throw new PushNetworkException(e);
} finally {
synchronized (connections) {
connections.remove(call);
}
}
switch(response.code()) {
case 200:
return readBodyJson(response.body(), SendGroupMessageResponse.class);
case 401:
throw new InvalidUnidentifiedAccessHeaderException();
case 404:
throw new NotFoundException("At least one unregistered user in message send.");
case 409:
GroupMismatchedDevices[] mismatchedDevices = readBodyJson(response.body(), GroupMismatchedDevices[].class);
throw new GroupMismatchedDevicesException(mismatchedDevices);
case 410:
GroupStaleDevices[] staleDevices = readBodyJson(response.body(), GroupStaleDevices[].class);
throw new GroupStaleDevicesException(staleDevices);
case 508:
throw new ServerRejectedException();
default:
throw new NonSuccessfulResponseCodeException(response.code());
}
}
use of org.whispersystems.signalservice.api.push.exceptions.PushNetworkException in project Signal-Android by WhisperSystems.
the class PushServiceSocket method makeServiceRequest.
private Response makeServiceRequest(String urlFragment, String method, RequestBody body, Map<String, String> headers, ResponseCodeHandler responseCodeHandler, Optional<UnidentifiedAccess> unidentifiedAccessKey, boolean doNotAddAuthenticationOrUnidentifiedAccessKey) throws NonSuccessfulResponseCodeException, PushNetworkException, MalformedResponseException {
Response response = getServiceConnection(urlFragment, method, body, headers, unidentifiedAccessKey, doNotAddAuthenticationOrUnidentifiedAccessKey);
ResponseBody responseBody = response.body();
try {
responseCodeHandler.handle(response.code(), responseBody);
return validateServiceResponse(response);
} catch (NonSuccessfulResponseCodeException | PushNetworkException | MalformedResponseException e) {
if (responseBody != null) {
responseBody.close();
}
throw e;
}
}
use of org.whispersystems.signalservice.api.push.exceptions.PushNetworkException in project Signal-Android by WhisperSystems.
the class PushServiceSocket method uploadToCdn2.
private byte[] uploadToCdn2(String resumableUrl, InputStream data, String contentType, long length, OutputStreamFactory outputStreamFactory, ProgressListener progressListener, CancelationSignal cancelationSignal) throws IOException {
ConnectionHolder connectionHolder = getRandom(cdnClientsMap.get(2), random);
OkHttpClient okHttpClient = connectionHolder.getClient().newBuilder().connectTimeout(soTimeoutMillis, TimeUnit.MILLISECONDS).readTimeout(soTimeoutMillis, TimeUnit.MILLISECONDS).build();
ResumeInfo resumeInfo = getResumeInfo(resumableUrl, length);
DigestingRequestBody file = new DigestingRequestBody(data, outputStreamFactory, contentType, length, progressListener, cancelationSignal, resumeInfo.contentStart);
if (resumeInfo.contentStart == length) {
Log.w(TAG, "Resume start point == content length");
try (NowhereBufferedSink buffer = new NowhereBufferedSink()) {
file.writeTo(buffer);
}
return file.getTransmittedDigest();
}
Request.Builder request = new Request.Builder().url(buildConfiguredUrl(connectionHolder, resumableUrl)).put(file).addHeader("Content-Range", resumeInfo.contentRange);
if (connectionHolder.getHostHeader().isPresent()) {
request.header("host", connectionHolder.getHostHeader().get());
}
Call call = okHttpClient.newCall(request.build());
synchronized (connections) {
connections.add(call);
}
try {
Response response;
try {
response = call.execute();
} catch (IOException e) {
throw new PushNetworkException(e);
}
if (response.isSuccessful())
return file.getTransmittedDigest();
else
throw new NonSuccessfulResponseCodeException(response.code(), "Response: " + response);
} finally {
synchronized (connections) {
connections.remove(call);
}
}
}
use of org.whispersystems.signalservice.api.push.exceptions.PushNetworkException in project Signal-Android by WhisperSystems.
the class PushServiceSocket method getServiceConnection.
private Response getServiceConnection(String urlFragment, String method, RequestBody body, Map<String, String> headers, Optional<UnidentifiedAccess> unidentifiedAccess, boolean doNotAddAuthenticationOrUnidentifiedAccessKey) throws PushNetworkException {
try {
OkHttpClient okHttpClient = buildOkHttpClient(unidentifiedAccess.isPresent());
Call call = okHttpClient.newCall(buildServiceRequest(urlFragment, method, body, headers, unidentifiedAccess, doNotAddAuthenticationOrUnidentifiedAccessKey));
synchronized (connections) {
connections.add(call);
}
try {
return call.execute();
} finally {
synchronized (connections) {
connections.remove(call);
}
}
} catch (IOException e) {
throw new PushNetworkException(e);
}
}
use of org.whispersystems.signalservice.api.push.exceptions.PushNetworkException in project Signal-Android by WhisperSystems.
the class SignalServiceMessageSender method sendMessage.
private List<SendMessageResult> sendMessage(List<SignalServiceAddress> recipients, List<Optional<UnidentifiedAccess>> unidentifiedAccess, long timestamp, EnvelopeContent content, boolean online, PartialSendCompleteListener partialListener, CancelationSignal cancelationSignal) throws IOException {
Log.d(TAG, "[" + timestamp + "] Sending to " + recipients.size() + " recipients.");
enforceMaxContentSize(content);
long startTime = System.currentTimeMillis();
List<Future<SendMessageResult>> futureResults = new LinkedList<>();
Iterator<SignalServiceAddress> recipientIterator = recipients.iterator();
Iterator<Optional<UnidentifiedAccess>> unidentifiedAccessIterator = unidentifiedAccess.iterator();
while (recipientIterator.hasNext()) {
SignalServiceAddress recipient = recipientIterator.next();
Optional<UnidentifiedAccess> access = unidentifiedAccessIterator.next();
futureResults.add(executor.submit(() -> {
SendMessageResult result = sendMessage(recipient, access, timestamp, content, online, cancelationSignal);
if (partialListener != null) {
partialListener.onPartialSendComplete(result);
}
return result;
}));
}
List<SendMessageResult> results = new ArrayList<>(futureResults.size());
recipientIterator = recipients.iterator();
for (Future<SendMessageResult> futureResult : futureResults) {
SignalServiceAddress recipient = recipientIterator.next();
try {
results.add(futureResult.get());
} catch (ExecutionException e) {
if (e.getCause() instanceof UntrustedIdentityException) {
Log.w(TAG, e);
results.add(SendMessageResult.identityFailure(recipient, ((UntrustedIdentityException) e.getCause()).getIdentityKey()));
} else if (e.getCause() instanceof UnregisteredUserException) {
Log.w(TAG, "[" + timestamp + "] Found unregistered user.");
results.add(SendMessageResult.unregisteredFailure(recipient));
} else if (e.getCause() instanceof PushNetworkException) {
Log.w(TAG, e);
results.add(SendMessageResult.networkFailure(recipient));
} else if (e.getCause() instanceof ServerRejectedException) {
Log.w(TAG, e);
throw ((ServerRejectedException) e.getCause());
} else if (e.getCause() instanceof ProofRequiredException) {
Log.w(TAG, e);
results.add(SendMessageResult.proofRequiredFailure(recipient, (ProofRequiredException) e.getCause()));
} else {
throw new IOException(e);
}
} catch (InterruptedException e) {
throw new IOException(e);
}
}
double sendsForAverage = 0;
for (SendMessageResult result : results) {
if (result.getSuccess() != null && result.getSuccess().getDuration() != -1) {
sendsForAverage++;
}
}
double average = 0;
if (sendsForAverage > 0) {
for (SendMessageResult result : results) {
if (result.getSuccess() != null && result.getSuccess().getDuration() != -1) {
average += result.getSuccess().getDuration() / sendsForAverage;
}
}
}
Log.d(TAG, "[" + timestamp + "] Completed send to " + recipients.size() + " recipients in " + (System.currentTimeMillis() - startTime) + " ms, with an average time of " + Math.round(average) + " ms per send.");
return results;
}
Aggregations