From 1d55a87adefc2d5a0b136ecbda2e6b12bb5ab2e7 Mon Sep 17 00:00:00 2001 From: Greyson Parrelli Date: Thu, 11 Apr 2019 15:55:58 -0400 Subject: [PATCH] Add support for isRecipientUpdate flag --- .../api/SignalServiceMessageSender.java | 13 +- .../api/crypto/SignalServiceCipher.java | 3 +- .../multidevice/SentTranscriptMessage.java | 15 +- .../internal/push/SignalServiceProtos.java | 178 +++++++++++++----- protobuf/SignalService.proto | 1 + 5 files changed, 156 insertions(+), 54 deletions(-) diff --git a/java/src/main/java/org/whispersystems/signalservice/api/SignalServiceMessageSender.java b/java/src/main/java/org/whispersystems/signalservice/api/SignalServiceMessageSender.java index 7cab818..b12586c 100644 --- a/java/src/main/java/org/whispersystems/signalservice/api/SignalServiceMessageSender.java +++ b/java/src/main/java/org/whispersystems/signalservice/api/SignalServiceMessageSender.java @@ -221,7 +221,7 @@ public class SignalServiceMessageSender { SendMessageResult result = sendMessage(recipient, getTargetUnidentifiedAccess(unidentifiedAccess), timestamp, content, false); if ((result.getSuccess() != null && result.getSuccess().isNeedsSync()) || (unidentifiedAccess.isPresent() && isMultiDevice.get())) { - byte[] syncMessage = createMultiDeviceSentTranscriptContent(content, Optional.of(recipient), timestamp, Collections.singletonList(result)); + byte[] syncMessage = createMultiDeviceSentTranscriptContent(content, Optional.of(recipient), timestamp, Collections.singletonList(result), false); sendMessage(localAddress, Optional.absent(), timestamp, syncMessage, false); } @@ -245,6 +245,7 @@ public class SignalServiceMessageSender { */ public List sendMessage(List recipients, List> unidentifiedAccess, + boolean isRecipientUpdate, SignalServiceDataMessage message) throws IOException, UntrustedIdentityException { @@ -261,7 +262,7 @@ public class SignalServiceMessageSender { } if (needsSyncInResults || (isMultiDevice.get())) { - byte[] syncMessage = createMultiDeviceSentTranscriptContent(content, Optional.absent(), timestamp, results); + byte[] syncMessage = createMultiDeviceSentTranscriptContent(content, Optional.absent(), timestamp, results, isRecipientUpdate); sendMessage(localAddress, Optional.absent(), timestamp, syncMessage, false); } @@ -574,11 +575,13 @@ public class SignalServiceMessageSender { return createMultiDeviceSentTranscriptContent(createMessageContent(transcript.getMessage()), Optional.of(address), transcript.getTimestamp(), - Collections.singletonList(result)); + Collections.singletonList(result), + false); } private byte[] createMultiDeviceSentTranscriptContent(byte[] content, Optional recipient, - long timestamp, List sendMessageResults) + long timestamp, List sendMessageResults, + boolean isRecipientUpdate) { try { Content.Builder container = Content.newBuilder(); @@ -605,6 +608,8 @@ public class SignalServiceMessageSender { sentMessage.setExpirationStartTimestamp(System.currentTimeMillis()); } + sentMessage.setIsRecipientUpdate(isRecipientUpdate); + return container.setSyncMessage(syncMessage.setSent(sentMessage)).build().toByteArray(); } catch (InvalidProtocolBufferException e) { throw new AssertionError(e); diff --git a/java/src/main/java/org/whispersystems/signalservice/api/crypto/SignalServiceCipher.java b/java/src/main/java/org/whispersystems/signalservice/api/crypto/SignalServiceCipher.java index 465dbf8..8b5e11e 100644 --- a/java/src/main/java/org/whispersystems/signalservice/api/crypto/SignalServiceCipher.java +++ b/java/src/main/java/org/whispersystems/signalservice/api/crypto/SignalServiceCipher.java @@ -314,7 +314,8 @@ public class SignalServiceCipher { sentContent.getTimestamp(), createSignalServiceMessage(metadata, sentContent.getMessage()), sentContent.getExpirationStartTimestamp(), - unidentifiedStatuses)); + unidentifiedStatuses, + sentContent.getIsRecipientUpdate())); } if (content.hasRequest()) { diff --git a/java/src/main/java/org/whispersystems/signalservice/api/messages/multidevice/SentTranscriptMessage.java b/java/src/main/java/org/whispersystems/signalservice/api/messages/multidevice/SentTranscriptMessage.java index 96744df..5fcfe42 100644 --- a/java/src/main/java/org/whispersystems/signalservice/api/messages/multidevice/SentTranscriptMessage.java +++ b/java/src/main/java/org/whispersystems/signalservice/api/messages/multidevice/SentTranscriptMessage.java @@ -12,6 +12,7 @@ import org.whispersystems.signalservice.api.messages.SignalServiceDataMessage; import java.util.Collections; import java.util.HashMap; import java.util.Map; +import java.util.Set; public class SentTranscriptMessage { @@ -20,15 +21,18 @@ public class SentTranscriptMessage { private final long expirationStartTimestamp; private final SignalServiceDataMessage message; private final Map unidentifiedStatus; + private final boolean isRecipientUpdate; public SentTranscriptMessage(String destination, long timestamp, SignalServiceDataMessage message, - long expirationStartTimestamp, Map unidentifiedStatus) + long expirationStartTimestamp, Map unidentifiedStatus, + boolean isRecipientUpdate) { this.destination = Optional.of(destination); this.timestamp = timestamp; this.message = message; this.expirationStartTimestamp = expirationStartTimestamp; this.unidentifiedStatus = new HashMap<>(unidentifiedStatus); + this.isRecipientUpdate = isRecipientUpdate; } public SentTranscriptMessage(long timestamp, SignalServiceDataMessage message) { @@ -37,6 +41,7 @@ public class SentTranscriptMessage { this.message = message; this.expirationStartTimestamp = 0; this.unidentifiedStatus = Collections.emptyMap(); + this.isRecipientUpdate = false; } public Optional getDestination() { @@ -61,4 +66,12 @@ public class SentTranscriptMessage { } return false; } + + public Set getRecipients() { + return unidentifiedStatus.keySet(); + } + + public boolean isRecipientUpdate() { + return isRecipientUpdate; + } } diff --git a/java/src/main/java/org/whispersystems/signalservice/internal/push/SignalServiceProtos.java b/java/src/main/java/org/whispersystems/signalservice/internal/push/SignalServiceProtos.java index 6ed8574..07d6a2a 100644 --- a/java/src/main/java/org/whispersystems/signalservice/internal/push/SignalServiceProtos.java +++ b/java/src/main/java/org/whispersystems/signalservice/internal/push/SignalServiceProtos.java @@ -23204,6 +23204,16 @@ public final class SignalServiceProtos { */ org.whispersystems.signalservice.internal.push.SignalServiceProtos.SyncMessage.Sent.UnidentifiedDeliveryStatusOrBuilder getUnidentifiedStatusOrBuilder( int index); + + // optional bool isRecipientUpdate = 6 [default = false]; + /** + * optional bool isRecipientUpdate = 6 [default = false]; + */ + boolean hasIsRecipientUpdate(); + /** + * optional bool isRecipientUpdate = 6 [default = false]; + */ + boolean getIsRecipientUpdate(); } /** * Protobuf type {@code signalservice.SyncMessage.Sent} @@ -23292,6 +23302,11 @@ public final class SignalServiceProtos { unidentifiedStatus_.add(input.readMessage(org.whispersystems.signalservice.internal.push.SignalServiceProtos.SyncMessage.Sent.UnidentifiedDeliveryStatus.PARSER, extensionRegistry)); break; } + case 48: { + bitField0_ |= 0x00000010; + isRecipientUpdate_ = input.readBool(); + break; + } } } } catch (com.google.protobuf.InvalidProtocolBufferException e) { @@ -24020,12 +24035,29 @@ public final class SignalServiceProtos { return unidentifiedStatus_.get(index); } + // optional bool isRecipientUpdate = 6 [default = false]; + public static final int ISRECIPIENTUPDATE_FIELD_NUMBER = 6; + private boolean isRecipientUpdate_; + /** + * optional bool isRecipientUpdate = 6 [default = false]; + */ + public boolean hasIsRecipientUpdate() { + return ((bitField0_ & 0x00000010) == 0x00000010); + } + /** + * optional bool isRecipientUpdate = 6 [default = false]; + */ + public boolean getIsRecipientUpdate() { + return isRecipientUpdate_; + } + private void initFields() { destination_ = ""; timestamp_ = 0L; message_ = org.whispersystems.signalservice.internal.push.SignalServiceProtos.DataMessage.getDefaultInstance(); expirationStartTimestamp_ = 0L; unidentifiedStatus_ = java.util.Collections.emptyList(); + isRecipientUpdate_ = false; } private byte memoizedIsInitialized = -1; public final boolean isInitialized() { @@ -24054,6 +24086,9 @@ public final class SignalServiceProtos { for (int i = 0; i < unidentifiedStatus_.size(); i++) { output.writeMessage(5, unidentifiedStatus_.get(i)); } + if (((bitField0_ & 0x00000010) == 0x00000010)) { + output.writeBool(6, isRecipientUpdate_); + } getUnknownFields().writeTo(output); } @@ -24083,6 +24118,10 @@ public final class SignalServiceProtos { size += com.google.protobuf.CodedOutputStream .computeMessageSize(5, unidentifiedStatus_.get(i)); } + if (((bitField0_ & 0x00000010) == 0x00000010)) { + size += com.google.protobuf.CodedOutputStream + .computeBoolSize(6, isRecipientUpdate_); + } size += getUnknownFields().getSerializedSize(); memoizedSerializedSize = size; return size; @@ -24219,6 +24258,8 @@ public final class SignalServiceProtos { } else { unidentifiedStatusBuilder_.clear(); } + isRecipientUpdate_ = false; + bitField0_ = (bitField0_ & ~0x00000020); return this; } @@ -24276,6 +24317,10 @@ public final class SignalServiceProtos { } else { result.unidentifiedStatus_ = unidentifiedStatusBuilder_.build(); } + if (((from_bitField0_ & 0x00000020) == 0x00000020)) { + to_bitField0_ |= 0x00000010; + } + result.isRecipientUpdate_ = isRecipientUpdate_; result.bitField0_ = to_bitField0_; onBuilt(); return result; @@ -24332,6 +24377,9 @@ public final class SignalServiceProtos { } } } + if (other.hasIsRecipientUpdate()) { + setIsRecipientUpdate(other.getIsRecipientUpdate()); + } this.mergeUnknownFields(other.getUnknownFields()); return this; } @@ -24856,6 +24904,39 @@ public final class SignalServiceProtos { return unidentifiedStatusBuilder_; } + // optional bool isRecipientUpdate = 6 [default = false]; + private boolean isRecipientUpdate_ ; + /** + * optional bool isRecipientUpdate = 6 [default = false]; + */ + public boolean hasIsRecipientUpdate() { + return ((bitField0_ & 0x00000020) == 0x00000020); + } + /** + * optional bool isRecipientUpdate = 6 [default = false]; + */ + public boolean getIsRecipientUpdate() { + return isRecipientUpdate_; + } + /** + * optional bool isRecipientUpdate = 6 [default = false]; + */ + public Builder setIsRecipientUpdate(boolean value) { + bitField0_ |= 0x00000020; + isRecipientUpdate_ = value; + onChanged(); + return this; + } + /** + * optional bool isRecipientUpdate = 6 [default = false]; + */ + public Builder clearIsRecipientUpdate() { + bitField0_ = (bitField0_ & ~0x00000020); + isRecipientUpdate_ = false; + onChanged(); + return this; + } + // @@protoc_insertion_point(builder_scope:signalservice.SyncMessage.Sent) } @@ -37854,7 +37935,7 @@ public final class SignalServiceProtos { "\001(\014\022,\n\005state\030\003 \001(\0162\035.signalservice.Verif" + "ied.State\022\023\n\013nullMessage\030\004 \001(\014\"2\n\005State\022", "\013\n\007DEFAULT\020\000\022\014\n\010VERIFIED\020\001\022\016\n\nUNVERIFIED" + - "\020\002\"\304\013\n\013SyncMessage\022-\n\004sent\030\001 \001(\0132\037.signa" + + "\020\002\"\346\013\n\013SyncMessage\022-\n\004sent\030\001 \001(\0132\037.signa" + "lservice.SyncMessage.Sent\0225\n\010contacts\030\002 " + "\001(\0132#.signalservice.SyncMessage.Contacts" + "\0221\n\006groups\030\003 \001(\0132!.signalservice.SyncMes" + @@ -37867,56 +37948,57 @@ public final class SignalServiceProtos { "ervice.SyncMessage.Configuration\022\017\n\007padd" + "ing\030\010 \001(\014\022M\n\024stickerPackOperation\030\n \003(\0132" + "/.signalservice.SyncMessage.StickerPackO" + - "peration\032\236\002\n\004Sent\022\023\n\013destination\030\001 \001(\t\022\021" + + "peration\032\300\002\n\004Sent\022\023\n\013destination\030\001 \001(\t\022\021" + "\n\ttimestamp\030\002 \001(\004\022+\n\007message\030\003 \001(\0132\032.sig" + "nalservice.DataMessage\022 \n\030expirationStar" + "tTimestamp\030\004 \001(\004\022V\n\022unidentifiedStatus\030\005" + " \003(\0132:.signalservice.SyncMessage.Sent.Un" + - "identifiedDeliveryStatus\032G\n\032Unidentified", - "DeliveryStatus\022\023\n\013destination\030\001 \001(\t\022\024\n\014u" + - "nidentified\030\002 \001(\010\032S\n\010Contacts\022.\n\004blob\030\001 " + - "\001(\0132 .signalservice.AttachmentPointer\022\027\n" + - "\010complete\030\002 \001(\010:\005false\0328\n\006Groups\022.\n\004blob" + - "\030\001 \001(\0132 .signalservice.AttachmentPointer" + - "\032,\n\007Blocked\022\017\n\007numbers\030\001 \003(\t\022\020\n\010groupIds" + - "\030\002 \003(\014\032\217\001\n\007Request\0225\n\004type\030\001 \001(\0162\'.signa" + - "lservice.SyncMessage.Request.Type\"M\n\004Typ" + - "e\022\013\n\007UNKNOWN\020\000\022\014\n\010CONTACTS\020\001\022\n\n\006GROUPS\020\002" + - "\022\013\n\007BLOCKED\020\003\022\021\n\rCONFIGURATION\020\004\032)\n\004Read", - "\022\016\n\006sender\030\001 \001(\t\022\021\n\ttimestamp\030\002 \001(\004\032}\n\rC" + - "onfiguration\022\024\n\014readReceipts\030\001 \001(\010\022&\n\036un" + - "identifiedDeliveryIndicators\030\002 \001(\010\022\030\n\020ty" + - "pingIndicators\030\003 \001(\010\022\024\n\014linkPreviews\030\004 \001" + - "(\010\032\234\001\n\024StickerPackOperation\022\016\n\006packId\030\001 " + - "\001(\014\022\017\n\007packKey\030\002 \001(\014\022B\n\004type\030\003 \001(\01624.sig" + - "nalservice.SyncMessage.StickerPackOperat" + - "ion.Type\"\037\n\004Type\022\013\n\007INSTALL\020\000\022\n\n\006REMOVE\020" + - "\001\"\337\001\n\021AttachmentPointer\022\n\n\002id\030\001 \001(\006\022\023\n\013c" + - "ontentType\030\002 \001(\t\022\013\n\003key\030\003 \001(\014\022\014\n\004size\030\004 ", - "\001(\r\022\021\n\tthumbnail\030\005 \001(\014\022\016\n\006digest\030\006 \001(\014\022\020" + - "\n\010fileName\030\007 \001(\t\022\r\n\005flags\030\010 \001(\r\022\r\n\005width" + - "\030\t \001(\r\022\016\n\006height\030\n \001(\r\022\017\n\007caption\030\013 \001(\t\"" + - "\032\n\005Flags\022\021\n\rVOICE_MESSAGE\020\001\"\345\001\n\014GroupCon" + - "text\022\n\n\002id\030\001 \001(\014\022.\n\004type\030\002 \001(\0162 .signals" + - "ervice.GroupContext.Type\022\014\n\004name\030\003 \001(\t\022\017" + - "\n\007members\030\004 \003(\t\0220\n\006avatar\030\005 \001(\0132 .signal" + - "service.AttachmentPointer\"H\n\004Type\022\013\n\007UNK" + - "NOWN\020\000\022\n\n\006UPDATE\020\001\022\013\n\007DELIVER\020\002\022\010\n\004QUIT\020" + - "\003\022\020\n\014REQUEST_INFO\020\004\"\207\002\n\016ContactDetails\022\016", - "\n\006number\030\001 \001(\t\022\014\n\004name\030\002 \001(\t\0224\n\006avatar\030\003" + - " \001(\0132$.signalservice.ContactDetails.Avat" + - "ar\022\r\n\005color\030\004 \001(\t\022)\n\010verified\030\005 \001(\0132\027.si" + - "gnalservice.Verified\022\022\n\nprofileKey\030\006 \001(\014" + - "\022\017\n\007blocked\030\007 \001(\010\022\023\n\013expireTimer\030\010 \001(\r\032-" + - "\n\006Avatar\022\023\n\013contentType\030\001 \001(\t\022\016\n\006length\030" + - "\002 \001(\r\"\347\001\n\014GroupDetails\022\n\n\002id\030\001 \001(\014\022\014\n\004na" + - "me\030\002 \001(\t\022\017\n\007members\030\003 \003(\t\0222\n\006avatar\030\004 \001(" + - "\0132\".signalservice.GroupDetails.Avatar\022\024\n" + - "\006active\030\005 \001(\010:\004true\022\023\n\013expireTimer\030\006 \001(\r", - "\022\r\n\005color\030\007 \001(\t\022\017\n\007blocked\030\010 \001(\010\032-\n\006Avat" + - "ar\022\023\n\013contentType\030\001 \001(\t\022\016\n\006length\030\002 \001(\rB" + - "E\n.org.whispersystems.signalservice.inte" + - "rnal.pushB\023SignalServiceProtos" + "identifiedDeliveryStatus\022 \n\021isRecipientU", + "pdate\030\006 \001(\010:\005false\032G\n\032UnidentifiedDelive" + + "ryStatus\022\023\n\013destination\030\001 \001(\t\022\024\n\014unident" + + "ified\030\002 \001(\010\032S\n\010Contacts\022.\n\004blob\030\001 \001(\0132 ." + + "signalservice.AttachmentPointer\022\027\n\010compl" + + "ete\030\002 \001(\010:\005false\0328\n\006Groups\022.\n\004blob\030\001 \001(\013" + + "2 .signalservice.AttachmentPointer\032,\n\007Bl" + + "ocked\022\017\n\007numbers\030\001 \003(\t\022\020\n\010groupIds\030\002 \003(\014" + + "\032\217\001\n\007Request\0225\n\004type\030\001 \001(\0162\'.signalservi" + + "ce.SyncMessage.Request.Type\"M\n\004Type\022\013\n\007U" + + "NKNOWN\020\000\022\014\n\010CONTACTS\020\001\022\n\n\006GROUPS\020\002\022\013\n\007BL", + "OCKED\020\003\022\021\n\rCONFIGURATION\020\004\032)\n\004Read\022\016\n\006se" + + "nder\030\001 \001(\t\022\021\n\ttimestamp\030\002 \001(\004\032}\n\rConfigu" + + "ration\022\024\n\014readReceipts\030\001 \001(\010\022&\n\036unidenti" + + "fiedDeliveryIndicators\030\002 \001(\010\022\030\n\020typingIn" + + "dicators\030\003 \001(\010\022\024\n\014linkPreviews\030\004 \001(\010\032\234\001\n" + + "\024StickerPackOperation\022\016\n\006packId\030\001 \001(\014\022\017\n" + + "\007packKey\030\002 \001(\014\022B\n\004type\030\003 \001(\01624.signalser" + + "vice.SyncMessage.StickerPackOperation.Ty" + + "pe\"\037\n\004Type\022\013\n\007INSTALL\020\000\022\n\n\006REMOVE\020\001\"\337\001\n\021" + + "AttachmentPointer\022\n\n\002id\030\001 \001(\006\022\023\n\013content", + "Type\030\002 \001(\t\022\013\n\003key\030\003 \001(\014\022\014\n\004size\030\004 \001(\r\022\021\n" + + "\tthumbnail\030\005 \001(\014\022\016\n\006digest\030\006 \001(\014\022\020\n\010file" + + "Name\030\007 \001(\t\022\r\n\005flags\030\010 \001(\r\022\r\n\005width\030\t \001(\r" + + "\022\016\n\006height\030\n \001(\r\022\017\n\007caption\030\013 \001(\t\"\032\n\005Fla" + + "gs\022\021\n\rVOICE_MESSAGE\020\001\"\345\001\n\014GroupContext\022\n" + + "\n\002id\030\001 \001(\014\022.\n\004type\030\002 \001(\0162 .signalservice" + + ".GroupContext.Type\022\014\n\004name\030\003 \001(\t\022\017\n\007memb" + + "ers\030\004 \003(\t\0220\n\006avatar\030\005 \001(\0132 .signalservic" + + "e.AttachmentPointer\"H\n\004Type\022\013\n\007UNKNOWN\020\000" + + "\022\n\n\006UPDATE\020\001\022\013\n\007DELIVER\020\002\022\010\n\004QUIT\020\003\022\020\n\014R", + "EQUEST_INFO\020\004\"\207\002\n\016ContactDetails\022\016\n\006numb" + + "er\030\001 \001(\t\022\014\n\004name\030\002 \001(\t\0224\n\006avatar\030\003 \001(\0132$" + + ".signalservice.ContactDetails.Avatar\022\r\n\005" + + "color\030\004 \001(\t\022)\n\010verified\030\005 \001(\0132\027.signalse" + + "rvice.Verified\022\022\n\nprofileKey\030\006 \001(\014\022\017\n\007bl" + + "ocked\030\007 \001(\010\022\023\n\013expireTimer\030\010 \001(\r\032-\n\006Avat" + + "ar\022\023\n\013contentType\030\001 \001(\t\022\016\n\006length\030\002 \001(\r\"" + + "\347\001\n\014GroupDetails\022\n\n\002id\030\001 \001(\014\022\014\n\004name\030\002 \001" + + "(\t\022\017\n\007members\030\003 \003(\t\0222\n\006avatar\030\004 \001(\0132\".si" + + "gnalservice.GroupDetails.Avatar\022\024\n\006activ", + "e\030\005 \001(\010:\004true\022\023\n\013expireTimer\030\006 \001(\r\022\r\n\005co" + + "lor\030\007 \001(\t\022\017\n\007blocked\030\010 \001(\010\032-\n\006Avatar\022\023\n\013" + + "contentType\030\001 \001(\t\022\016\n\006length\030\002 \001(\rBE\n.org" + + ".whispersystems.signalservice.internal.p" + + "ushB\023SignalServiceProtos" }; com.google.protobuf.Descriptors.FileDescriptor.InternalDescriptorAssigner assigner = new com.google.protobuf.Descriptors.FileDescriptor.InternalDescriptorAssigner() { @@ -38072,7 +38154,7 @@ public final class SignalServiceProtos { internal_static_signalservice_SyncMessage_Sent_fieldAccessorTable = new com.google.protobuf.GeneratedMessage.FieldAccessorTable( internal_static_signalservice_SyncMessage_Sent_descriptor, - new java.lang.String[] { "Destination", "Timestamp", "Message", "ExpirationStartTimestamp", "UnidentifiedStatus", }); + new java.lang.String[] { "Destination", "Timestamp", "Message", "ExpirationStartTimestamp", "UnidentifiedStatus", "IsRecipientUpdate", }); internal_static_signalservice_SyncMessage_Sent_UnidentifiedDeliveryStatus_descriptor = internal_static_signalservice_SyncMessage_Sent_descriptor.getNestedTypes().get(0); internal_static_signalservice_SyncMessage_Sent_UnidentifiedDeliveryStatus_fieldAccessorTable = new diff --git a/protobuf/SignalService.proto b/protobuf/SignalService.proto index 6b66d70..19b6f76 100644 --- a/protobuf/SignalService.proto +++ b/protobuf/SignalService.proto @@ -236,6 +236,7 @@ message SyncMessage { optional DataMessage message = 3; optional uint64 expirationStartTimestamp = 4; repeated UnidentifiedDeliveryStatus unidentifiedStatus = 5; + optional bool isRecipientUpdate = 6 [default = false]; } message Contacts {