use of org.whispersystems.signalservice.internal.push.SendMessageResponse in project libsignal-service-java by signalapp.
the class SignalServiceMessagePipe method send.
public SendMessageResponse send(OutgoingPushMessageList list) throws IOException {
try {
WebSocketRequestMessage requestMessage = WebSocketRequestMessage.newBuilder().setId(SecureRandom.getInstance("SHA1PRNG").nextLong()).setVerb("PUT").setPath(String.format("/v1/messages/%s", list.getDestination())).addHeaders("content-type:application/json").setBody(ByteString.copyFrom(JsonUtil.toJson(list).getBytes())).build();
Pair<Integer, String> response = websocket.sendRequest(requestMessage).get(10, TimeUnit.SECONDS);
if (response.first() < 200 || response.first() >= 300) {
throw new IOException("Non-successful response: " + response.first());
}
if (Util.isEmpty(response.second()))
return new SendMessageResponse(false);
else
return JsonUtil.fromJson(response.second(), SendMessageResponse.class);
} catch (NoSuchAlgorithmException e) {
throw new AssertionError(e);
} catch (InterruptedException | ExecutionException | TimeoutException e) {
throw new IOException(e);
}
}
use of org.whispersystems.signalservice.internal.push.SendMessageResponse in project libsignal-service-java by signalapp.
the class SignalServiceMessageSender method sendMessage.
/**
* Send a message to a single recipient.
*
* @param recipient The message's destination.
* @param message The message.
* @throws UntrustedIdentityException
* @throws IOException
*/
public void sendMessage(SignalServiceAddress recipient, SignalServiceDataMessage message) throws UntrustedIdentityException, IOException {
byte[] content = createMessageContent(message);
long timestamp = message.getTimestamp();
boolean silent = message.getGroupInfo().isPresent() && message.getGroupInfo().get().getType() == SignalServiceGroup.Type.REQUEST_INFO;
SendMessageResponse response = sendMessage(recipient, timestamp, content, silent);
if (response != null && response.getNeedsSync()) {
byte[] syncMessage = createMultiDeviceSentTranscriptContent(content, Optional.of(recipient), timestamp);
sendMessage(localAddress, timestamp, syncMessage, false);
}
if (message.isEndSession()) {
store.deleteAllSessions(recipient.getNumber());
if (eventListener.isPresent()) {
eventListener.get().onSecurityEvent(recipient);
}
}
}
use of org.whispersystems.signalservice.internal.push.SendMessageResponse in project libsignal-service-java by signalapp.
the class SignalServiceMessageSender method sendMessage.
private void sendMessage(VerifiedMessage message) throws IOException, UntrustedIdentityException {
byte[] nullMessageBody = DataMessage.newBuilder().setBody(Base64.encodeBytes(Util.getRandomLengthBytes(140))).build().toByteArray();
NullMessage nullMessage = NullMessage.newBuilder().setPadding(ByteString.copyFrom(nullMessageBody)).build();
byte[] content = Content.newBuilder().setNullMessage(nullMessage).build().toByteArray();
SendMessageResponse response = sendMessage(new SignalServiceAddress(message.getDestination()), message.getTimestamp(), content, false);
if (response != null && response.getNeedsSync()) {
byte[] syncMessage = createMultiDeviceVerifiedContent(message, nullMessage.toByteArray());
sendMessage(localAddress, message.getTimestamp(), syncMessage, false);
}
}
use of org.whispersystems.signalservice.internal.push.SendMessageResponse in project Signal-Android by WhisperSystems.
the class SignalServiceMessageSender method sendMessage.
private SendMessageResult sendMessage(SignalServiceAddress recipient, Optional<UnidentifiedAccess> unidentifiedAccess, long timestamp, EnvelopeContent content, boolean online, CancelationSignal cancelationSignal) throws UntrustedIdentityException, IOException {
enforceMaxContentSize(content);
long startTime = System.currentTimeMillis();
for (int i = 0; i < RETRY_COUNT; i++) {
if (cancelationSignal != null && cancelationSignal.isCanceled()) {
throw new CancelationException();
}
try {
OutgoingPushMessageList messages = getEncryptedMessages(socket, recipient, unidentifiedAccess, timestamp, content, online);
if (content.getContent().isPresent() && content.getContent().get().getSyncMessage() != null && content.getContent().get().getSyncMessage().hasSent()) {
Log.d(TAG, "[sendMessage][" + timestamp + "] Sending a sent sync message to devices: " + messages.getDevices());
} else if (content.getContent().isPresent() && content.getContent().get().hasSenderKeyDistributionMessage()) {
Log.d(TAG, "[sendMessage][" + timestamp + "] Sending a SKDM to " + messages.getDestination() + " for devices: " + messages.getDevices());
}
if (cancelationSignal != null && cancelationSignal.isCanceled()) {
throw new CancelationException();
}
if (!unidentifiedAccess.isPresent()) {
try {
SendMessageResponse response = new MessagingService.SendResponseProcessor<>(messagingService.send(messages, Optional.absent()).blockingGet()).getResultOrThrow();
return SendMessageResult.success(recipient, messages.getDevices(), response.sentUnidentified(), response.getNeedsSync() || store.isMultiDevice(), System.currentTimeMillis() - startTime, content.getContent());
} catch (InvalidUnidentifiedAccessHeaderException | UnregisteredUserException | MismatchedDevicesException | StaleDevicesException e) {
// Non-technical failures shouldn't be retried with socket
throw e;
} catch (WebSocketUnavailableException e) {
Log.i(TAG, "[sendMessage][" + timestamp + "] Pipe unavailable, falling back... (" + e.getClass().getSimpleName() + ": " + e.getMessage() + ")");
} catch (IOException e) {
Log.w(TAG, e);
Log.w(TAG, "[sendMessage][" + timestamp + "] Pipe failed, falling back... (" + e.getClass().getSimpleName() + ": " + e.getMessage() + ")");
}
} else if (unidentifiedAccess.isPresent()) {
try {
SendMessageResponse response = new MessagingService.SendResponseProcessor<>(messagingService.send(messages, unidentifiedAccess).blockingGet()).getResultOrThrow();
return SendMessageResult.success(recipient, messages.getDevices(), response.sentUnidentified(), response.getNeedsSync() || store.isMultiDevice(), System.currentTimeMillis() - startTime, content.getContent());
} catch (InvalidUnidentifiedAccessHeaderException | UnregisteredUserException | MismatchedDevicesException | StaleDevicesException e) {
// Non-technical failures shouldn't be retried with socket
throw e;
} catch (WebSocketUnavailableException e) {
Log.i(TAG, "[sendMessage][" + timestamp + "] Unidentified pipe unavailable, falling back... (" + e.getClass().getSimpleName() + ": " + e.getMessage() + ")");
} catch (IOException e) {
Log.w(TAG, e);
Log.w(TAG, "[sendMessage][" + timestamp + "] Unidentified pipe failed, falling back...");
}
}
if (cancelationSignal != null && cancelationSignal.isCanceled()) {
throw new CancelationException();
}
SendMessageResponse response = socket.sendMessage(messages, unidentifiedAccess);
return SendMessageResult.success(recipient, messages.getDevices(), response.sentUnidentified(), response.getNeedsSync() || store.isMultiDevice(), System.currentTimeMillis() - startTime, content.getContent());
} catch (InvalidKeyException ike) {
Log.w(TAG, ike);
unidentifiedAccess = Optional.absent();
} catch (AuthorizationFailedException afe) {
Log.w(TAG, afe);
if (unidentifiedAccess.isPresent()) {
unidentifiedAccess = Optional.absent();
} else {
throw afe;
}
} catch (MismatchedDevicesException mde) {
Log.w(TAG, "[sendMessage][" + timestamp + "] Handling mismatched devices. (" + mde.getMessage() + ")");
handleMismatchedDevices(socket, recipient, mde.getMismatchedDevices());
} catch (StaleDevicesException ste) {
Log.w(TAG, "[sendMessage][" + timestamp + "] Handling stale devices. (" + ste.getMessage() + ")");
handleStaleDevices(recipient, ste.getStaleDevices());
}
}
throw new IOException("Failed to resolve conflicts after " + RETRY_COUNT + " attempts!");
}
use of org.whispersystems.signalservice.internal.push.SendMessageResponse in project libsignal-service-java by signalapp.
the class SignalServiceMessageSender method sendMessage.
private SendMessageResponseList sendMessage(List<SignalServiceAddress> recipients, long timestamp, byte[] content) throws IOException {
SendMessageResponseList responseList = new SendMessageResponseList();
for (SignalServiceAddress recipient : recipients) {
try {
SendMessageResponse response = sendMessage(recipient, timestamp, content, false);
responseList.addResponse(response);
} catch (UntrustedIdentityException e) {
Log.w(TAG, e);
responseList.addException(e);
} catch (UnregisteredUserException e) {
Log.w(TAG, e);
responseList.addException(e);
} catch (PushNetworkException e) {
Log.w(TAG, e);
responseList.addException(new NetworkFailureException(recipient.getNumber(), e));
}
}
return responseList;
}
Aggregations