use of org.whispersystems.signalservice.api.messages.SendMessageResult in project Signal-Android by WhisperSystems.
the class SignalServiceMessageSender method createMultiDeviceSentTranscriptContent.
private Content createMultiDeviceSentTranscriptContent(Content content, Optional<SignalServiceAddress> recipient, long timestamp, List<SendMessageResult> sendMessageResults, boolean isRecipientUpdate) {
Content.Builder container = Content.newBuilder();
SyncMessage.Builder syncMessage = createSyncMessageBuilder();
SyncMessage.Sent.Builder sentMessage = SyncMessage.Sent.newBuilder();
DataMessage dataMessage = content.getDataMessage();
sentMessage.setTimestamp(timestamp);
sentMessage.setMessage(dataMessage);
for (SendMessageResult result : sendMessageResults) {
if (result.getSuccess() != null) {
SyncMessage.Sent.UnidentifiedDeliveryStatus.Builder builder = SyncMessage.Sent.UnidentifiedDeliveryStatus.newBuilder();
builder.setDestinationUuid(result.getAddress().getServiceId().toString());
if (result.getAddress().getNumber().isPresent()) {
builder.setDestinationE164(result.getAddress().getNumber().get());
}
builder.setUnidentified(result.getSuccess().isUnidentified());
sentMessage.addUnidentifiedStatus(builder.build());
}
}
if (recipient.isPresent()) {
sentMessage.setDestinationUuid(recipient.get().getServiceId().toString());
if (recipient.get().getNumber().isPresent()) {
sentMessage.setDestinationE164(recipient.get().getNumber().get());
}
}
if (dataMessage.getExpireTimer() > 0) {
sentMessage.setExpirationStartTimestamp(System.currentTimeMillis());
}
if (dataMessage.getIsViewOnce()) {
dataMessage = dataMessage.toBuilder().clearAttachments().build();
sentMessage.setMessage(dataMessage);
}
sentMessage.setIsRecipientUpdate(isRecipientUpdate);
return container.setSyncMessage(syncMessage.setSent(sentMessage)).build();
}
use of org.whispersystems.signalservice.api.messages.SendMessageResult in project Signal-Android by WhisperSystems.
the class SignalServiceMessageSender method sendGroupDataMessage.
/**
* Sends a {@link SignalServiceDataMessage} to a group using sender keys.
*/
public List<SendMessageResult> sendGroupDataMessage(DistributionId distributionId, List<SignalServiceAddress> recipients, List<UnidentifiedAccess> unidentifiedAccess, boolean isRecipientUpdate, ContentHint contentHint, SignalServiceDataMessage message, SenderKeyGroupEvents sendEvents) throws IOException, UntrustedIdentityException, NoSessionException, InvalidKeyException, InvalidRegistrationIdException {
Log.d(TAG, "[" + message.getTimestamp() + "] Sending a group data message to " + recipients.size() + " recipients using DistributionId " + distributionId);
Content content = createMessageContent(message);
Optional<byte[]> groupId = message.getGroupId();
List<SendMessageResult> results = sendGroupMessage(distributionId, recipients, unidentifiedAccess, message.getTimestamp(), content, contentHint, groupId.orNull(), false, sendEvents);
sendEvents.onMessageSent();
if (store.isMultiDevice()) {
Content syncMessage = createMultiDeviceSentTranscriptContent(content, Optional.absent(), message.getTimestamp(), results, isRecipientUpdate);
EnvelopeContent syncMessageContent = EnvelopeContent.encrypted(syncMessage, ContentHint.IMPLICIT, Optional.absent());
sendMessage(localAddress, Optional.absent(), message.getTimestamp(), syncMessageContent, false, null);
}
sendEvents.onSyncMessageSent();
return results;
}
use of org.whispersystems.signalservice.api.messages.SendMessageResult 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;
}
use of org.whispersystems.signalservice.api.messages.SendMessageResult in project Signal-Android by WhisperSystems.
the class SignalServiceMessageSender method sendDataMessage.
/**
* Send a message to a single recipient.
*
* @param recipient The message's destination.
* @param message The message.
* @throws UntrustedIdentityException
* @throws IOException
*/
public SendMessageResult sendDataMessage(SignalServiceAddress recipient, Optional<UnidentifiedAccessPair> unidentifiedAccess, ContentHint contentHint, SignalServiceDataMessage message, IndividualSendEvents sendEvents) throws UntrustedIdentityException, IOException {
Log.d(TAG, "[" + message.getTimestamp() + "] Sending a data message.");
Content content = createMessageContent(message);
EnvelopeContent envelopeContent = EnvelopeContent.encrypted(content, contentHint, message.getGroupId());
sendEvents.onMessageEncrypted();
long timestamp = message.getTimestamp();
SendMessageResult result = sendMessage(recipient, getTargetUnidentifiedAccess(unidentifiedAccess), timestamp, envelopeContent, false, null);
sendEvents.onMessageSent();
if (result.getSuccess() != null && result.getSuccess().isNeedsSync()) {
Content syncMessage = createMultiDeviceSentTranscriptContent(content, Optional.of(recipient), timestamp, Collections.singletonList(result), false);
EnvelopeContent syncMessageContent = EnvelopeContent.encrypted(syncMessage, ContentHint.IMPLICIT, Optional.absent());
sendMessage(localAddress, Optional.absent(), timestamp, syncMessageContent, false, null);
}
sendEvents.onSyncMessageSent();
return result;
}
use of org.whispersystems.signalservice.api.messages.SendMessageResult in project Signal-Android by WhisperSystems.
the class SignalServiceMessageSender method createMultiDeviceSentTranscriptContent.
private Content createMultiDeviceSentTranscriptContent(SentTranscriptMessage transcript, boolean unidentifiedAccess) throws IOException {
SignalServiceAddress address = transcript.getDestination().get();
Content content = createMessageContent(transcript.getMessage());
SendMessageResult result = SendMessageResult.success(address, Collections.emptyList(), unidentifiedAccess, true, -1, Optional.of(content));
return createMultiDeviceSentTranscriptContent(content, Optional.of(address), transcript.getTimestamp(), Collections.singletonList(result), false);
}
Aggregations