--- /dev/null
+package org.asamk.signal.manager;
+
+import org.whispersystems.signalservice.api.push.SignalServiceAddress;
+
+import java.util.Arrays;
+import java.util.Objects;
+
+interface HandleAction {
+
+ void execute(Manager m) throws Throwable;
+}
+
+class SendReceiptAction implements HandleAction {
+
+ private final SignalServiceAddress address;
+ private final long timestamp;
+
+ public SendReceiptAction(final SignalServiceAddress address, final long timestamp) {
+ this.address = address;
+ this.timestamp = timestamp;
+ }
+
+ @Override
+ public void execute(Manager m) throws Throwable {
+ m.sendReceipt(address, timestamp);
+ }
+
+ @Override
+ public boolean equals(final Object o) {
+ if (this == o) return true;
+ if (o == null || getClass() != o.getClass()) return false;
+ final SendReceiptAction that = (SendReceiptAction) o;
+ return timestamp == that.timestamp &&
+ address.equals(that.address);
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(address, timestamp);
+ }
+}
+
+class SendSyncContactsAction implements HandleAction {
+
+ private static final SendSyncContactsAction INSTANCE = new SendSyncContactsAction();
+
+ private SendSyncContactsAction() {
+ }
+
+ public static SendSyncContactsAction create() {
+ return INSTANCE;
+ }
+
+ @Override
+ public void execute(Manager m) throws Throwable {
+ m.sendContacts();
+ }
+}
+
+class SendSyncGroupsAction implements HandleAction {
+
+ private static final SendSyncGroupsAction INSTANCE = new SendSyncGroupsAction();
+
+ private SendSyncGroupsAction() {
+ }
+
+ public static SendSyncGroupsAction create() {
+ return INSTANCE;
+ }
+
+ @Override
+ public void execute(Manager m) throws Throwable {
+ m.sendGroups();
+ }
+}
+
+class SendSyncBlockedListAction implements HandleAction {
+
+ private static final SendSyncBlockedListAction INSTANCE = new SendSyncBlockedListAction();
+
+ private SendSyncBlockedListAction() {
+ }
+
+ public static SendSyncBlockedListAction create() {
+ return INSTANCE;
+ }
+
+ @Override
+ public void execute(Manager m) throws Throwable {
+ m.sendBlockedList();
+ }
+}
+
+class SendGroupInfoRequestAction implements HandleAction {
+
+ private final SignalServiceAddress address;
+ private final byte[] groupId;
+
+ public SendGroupInfoRequestAction(final SignalServiceAddress address, final byte[] groupId) {
+ this.address = address;
+ this.groupId = groupId;
+ }
+
+ @Override
+ public void execute(Manager m) throws Throwable {
+ m.sendGroupInfoRequest(groupId, address);
+ }
+
+ @Override
+ public boolean equals(final Object o) {
+ if (this == o) return true;
+ if (o == null || getClass() != o.getClass()) return false;
+ final SendGroupInfoRequestAction that = (SendGroupInfoRequestAction) o;
+ return address.equals(that.address) &&
+ Arrays.equals(groupId, that.groupId);
+ }
+
+ @Override
+ public int hashCode() {
+ int result = Objects.hash(address);
+ result = 31 * result + Arrays.hashCode(groupId);
+ return result;
+ }
+}
+
+class SendGroupUpdateAction implements HandleAction {
+
+ private final SignalServiceAddress address;
+ private final byte[] groupId;
+
+ public SendGroupUpdateAction(final SignalServiceAddress address, final byte[] groupId) {
+ this.address = address;
+ this.groupId = groupId;
+ }
+
+ @Override
+ public void execute(Manager m) throws Throwable {
+ m.sendUpdateGroupMessage(groupId, address);
+ }
+
+ @Override
+ public boolean equals(final Object o) {
+ if (this == o) return true;
+ if (o == null || getClass() != o.getClass()) return false;
+ final SendGroupUpdateAction that = (SendGroupUpdateAction) o;
+ return address.equals(that.address) &&
+ Arrays.equals(groupId, that.groupId);
+ }
+
+ @Override
+ public int hashCode() {
+ int result = Objects.hash(address);
+ result = 31 * result + Arrays.hashCode(groupId);
+ return result;
+ }
+}
return g.groupId;
}
- private void sendUpdateGroupMessage(byte[] groupId, SignalServiceAddress recipient) throws IOException, EncapsulatedExceptions, NotAGroupMemberException, GroupNotFoundException, AttachmentInvalidException {
+ void sendUpdateGroupMessage(byte[] groupId, SignalServiceAddress recipient) throws IOException, EncapsulatedExceptions, NotAGroupMemberException, GroupNotFoundException, AttachmentInvalidException {
if (groupId == null) {
return;
}
.withExpiration(g.messageExpirationTime);
}
- private void sendGroupInfoRequest(byte[] groupId, SignalServiceAddress recipient) throws IOException, EncapsulatedExceptions {
+ void sendGroupInfoRequest(byte[] groupId, SignalServiceAddress recipient) throws IOException, EncapsulatedExceptions {
if (groupId == null) {
return;
}
sendMessageLegacy(messageBuilder, Collections.singleton(recipient));
}
- private void sendReceipt(SignalServiceAddress remoteAddress, long messageId) throws IOException, UntrustedIdentityException {
+ void sendReceipt(SignalServiceAddress remoteAddress, long messageId) throws IOException, UntrustedIdentityException {
SignalServiceReceiptMessage receiptMessage = new SignalServiceReceiptMessage(SignalServiceReceiptMessage.Type.DELIVERY,
Collections.singletonList(messageId),
System.currentTimeMillis());
account.getSignalProtocolStore().deleteAllSessions(source);
}
- private void handleSignalServiceDataMessage(SignalServiceDataMessage message, boolean isSync, SignalServiceAddress source, SignalServiceAddress destination, boolean ignoreAttachments) {
+ private List<HandleAction> handleSignalServiceDataMessage(SignalServiceDataMessage message, boolean isSync, SignalServiceAddress source, SignalServiceAddress destination, boolean ignoreAttachments) {
+ List<HandleAction> actions = new ArrayList<>();
if (message.getGroupContext().isPresent() && message.getGroupContext().get().getGroupV1().isPresent()) {
SignalServiceGroup groupInfo = message.getGroupContext().get().getGroupV1().get();
GroupInfo group = account.getGroupStore().getGroup(groupInfo.getGroupId());
account.getGroupStore().updateGroup(group);
break;
case DELIVER:
- if (group == null) {
- try {
- sendGroupInfoRequest(groupInfo.getGroupId(), source);
- } catch (IOException | EncapsulatedExceptions e) {
- e.printStackTrace();
- }
+ if (group == null && !isSync) {
+ actions.add(new SendGroupInfoRequestAction(source, groupInfo.getGroupId()));
}
break;
case QUIT:
}
break;
case REQUEST_INFO:
- if (group != null) {
- try {
- sendUpdateGroupMessage(groupInfo.getGroupId(), source);
- } catch (IOException | EncapsulatedExceptions | AttachmentInvalidException e) {
- e.printStackTrace();
- } catch (GroupNotFoundException | NotAGroupMemberException e) {
- // We have left this group, so don't send a group update message
- }
+ if (group != null && !isSync) {
+ actions.add(new SendGroupUpdateAction(source, group.groupId));
}
break;
}
}
}
}
+ return actions;
}
private void retryFailedReceivedMessages(ReceiveMessageHandler handler, boolean ignoreAttachments) {
} catch (Exception e) {
return;
}
- handleMessage(envelope, content, ignoreAttachments);
+ List<HandleAction> actions = handleMessage(envelope, content, ignoreAttachments);
+ for (HandleAction action : actions) {
+ try {
+ action.execute(this);
+ } catch (Throwable e) {
+ e.printStackTrace();
+ }
+ }
}
account.save();
handler.handleMessage(envelope, content, null);
retryFailedReceivedMessages(handler, ignoreAttachments);
final SignalServiceMessageReceiver messageReceiver = getMessageReceiver();
+ Set<HandleAction> queuedActions = null;
+
if (messagePipe == null) {
messagePipe = messageReceiver.createMessagePipe();
}
// Received indicator that server queue is empty
hasCaughtUpWithOldMessages = true;
+ if (queuedActions != null) {
+ for (HandleAction action : queuedActions) {
+ try {
+ action.execute(this);
+ } catch (Throwable e) {
+ e.printStackTrace();
+ }
+ }
+ queuedActions.clear();
+ queuedActions = null;
+ }
+
// Continue to wait another timeout for new messages
continue;
}
} catch (Exception e) {
exception = e;
}
- handleMessage(envelope, content, ignoreAttachments);
+ List<HandleAction> actions = handleMessage(envelope, content, ignoreAttachments);
+ if (hasCaughtUpWithOldMessages) {
+ for (HandleAction action : actions) {
+ try {
+ action.execute(this);
+ } catch (Throwable e) {
+ e.printStackTrace();
+ }
+ }
+ } else {
+ if (queuedActions == null) {
+ queuedActions = new HashSet<>();
+ }
+ queuedActions.addAll(actions);
+ }
}
account.save();
if (!isMessageBlocked(envelope, content)) {
return false;
}
- private void handleMessage(SignalServiceEnvelope envelope, SignalServiceContent content, boolean ignoreAttachments) {
+ private List<HandleAction> handleMessage(SignalServiceEnvelope envelope, SignalServiceContent content, boolean ignoreAttachments) {
+ List<HandleAction> actions = new ArrayList<>();
if (content != null) {
SignalServiceAddress sender;
if (!envelope.isUnidentifiedSender() && envelope.hasSource()) {
SignalServiceDataMessage message = content.getDataMessage().get();
if (content.isNeedsReceipt()) {
- try {
- sendReceipt(sender, message.getTimestamp());
- } catch (IOException | UntrustedIdentityException | IllegalArgumentException e) {
- e.printStackTrace();
- }
+ actions.add(new SendReceiptAction(sender, message.getTimestamp()));
}
- handleSignalServiceDataMessage(message, false, sender, account.getSelfAddress(), ignoreAttachments);
+ actions.addAll(handleSignalServiceDataMessage(message, false, sender, account.getSelfAddress(), ignoreAttachments));
}
if (content.getSyncMessage().isPresent()) {
account.setMultiDevice(true);
SignalServiceSyncMessage syncMessage = content.getSyncMessage().get();
if (syncMessage.getSent().isPresent()) {
SentTranscriptMessage message = syncMessage.getSent().get();
- handleSignalServiceDataMessage(message.getMessage(), true, sender, message.getDestination().orNull(), ignoreAttachments);
+ actions.addAll(handleSignalServiceDataMessage(message.getMessage(), true, sender, message.getDestination().orNull(), ignoreAttachments));
}
if (syncMessage.getRequest().isPresent()) {
RequestMessage rm = syncMessage.getRequest().get();
if (rm.isContactsRequest()) {
- try {
- sendContacts();
- } catch (UntrustedIdentityException | IOException | IllegalArgumentException e) {
- e.printStackTrace();
- }
+ actions.add(SendSyncContactsAction.create());
}
if (rm.isGroupsRequest()) {
- try {
- sendGroups();
- } catch (UntrustedIdentityException | IOException | IllegalArgumentException e) {
- e.printStackTrace();
- }
+ actions.add(SendSyncGroupsAction.create());
}
if (rm.isBlockedListRequest()) {
- try {
- sendBlockedList();
- } catch (UntrustedIdentityException | IOException | IllegalArgumentException e) {
- e.printStackTrace();
- }
+ actions.add(SendSyncBlockedListAction.create());
}
// TODO Handle rm.isConfigurationRequest();
}
}
}
}
+ return actions;
}
private File getContactAvatarFile(String number) {
return messageReceiver.retrieveAttachment(pointer, tmpFile, ServiceConfig.MAX_ATTACHMENT_SIZE);
}
- private void sendGroups() throws IOException, UntrustedIdentityException {
+ void sendGroups() throws IOException, UntrustedIdentityException {
File groupsFile = IOUtils.createTempFile();
try {
}
}
- private void sendBlockedList() throws IOException, UntrustedIdentityException {
+ void sendBlockedList() throws IOException, UntrustedIdentityException {
List<SignalServiceAddress> addresses = new ArrayList<>();
for (ContactInfo record : account.getContactStore().getContacts()) {
if (record.blocked) {