Update TextSecure envelope protobuf.

Support envelope 'content' field.

// FREEBIE
This commit is contained in:
Moxie Marlinspike 2015-06-15 15:42:05 -07:00
parent 79f36664ef
commit 53bdd946d6
19 changed files with 438 additions and 284 deletions

View File

@ -1,3 +1,3 @@
all:
protoc --java_out=../src/main/java/ OutgoingMessageSignal.proto PubSubMessage.proto
protoc --java_out=../src/main/java/ TextSecure.proto PubSubMessage.proto

View File

@ -19,23 +19,22 @@ package textsecure;
option java_package = "org.whispersystems.textsecuregcm.entities";
option java_outer_classname = "MessageProtos";
message OutgoingMessageSignal {
message Envelope {
enum Type {
UNKNOWN = 0;
CIPHERTEXT = 1;
KEY_EXCHANGE = 2;
PREKEY_BUNDLE = 3;
// PLAINTEXT = 4;
RECEIPT = 5;
}
optional uint32 type = 1;
optional string source = 2;
optional uint32 sourceDevice = 7;
optional string relay = 3;
// repeated string destinations = 4;
optional uint64 timestamp = 5;
optional bytes message = 6;
optional Type type = 1;
optional string source = 2;
optional uint32 sourceDevice = 7;
optional string relay = 3;
optional uint64 timestamp = 5;
optional bytes legacyMessage = 6; // Contains an encrypted DataMessage
optional bytes content = 8; // Contains an encrypted Content
}
message ProvisioningUuid {

View File

@ -23,7 +23,7 @@ import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.whispersystems.textsecuregcm.entities.IncomingMessage;
import org.whispersystems.textsecuregcm.entities.IncomingMessageList;
import org.whispersystems.textsecuregcm.entities.MessageProtos.OutgoingMessageSignal;
import org.whispersystems.textsecuregcm.entities.MessageProtos.Envelope;
import org.whispersystems.textsecuregcm.entities.MessageResponse;
import org.whispersystems.textsecuregcm.entities.MismatchedDevices;
import org.whispersystems.textsecuregcm.entities.OutgoingMessageEntity;
@ -169,7 +169,7 @@ public class MessageController {
try {
Optional<OutgoingMessageEntity> message = messagesManager.delete(account.getNumber(), source, timestamp);
if (message.isPresent() && message.get().getType() != OutgoingMessageSignal.Type.RECEIPT_VALUE) {
if (message.isPresent() && message.get().getType() != Envelope.Type.RECEIPT_VALUE) {
receiptSender.sendReceipt(account,
message.get().getSource(),
message.get().getTimestamp(),
@ -212,16 +212,21 @@ public class MessageController {
throws NoSuchUserException, IOException
{
try {
Optional<byte[]> messageBody = getMessageBody(incomingMessage);
OutgoingMessageSignal.Builder messageBuilder = OutgoingMessageSignal.newBuilder();
Optional<byte[]> messageBody = getMessageBody(incomingMessage);
Optional<byte[]> messageContent = getMessageContent(incomingMessage);
Envelope.Builder messageBuilder = Envelope.newBuilder();
messageBuilder.setType(incomingMessage.getType())
messageBuilder.setType(Envelope.Type.valueOf(incomingMessage.getType()))
.setSource(source.getNumber())
.setTimestamp(timestamp == 0 ? System.currentTimeMillis() : timestamp)
.setSourceDevice((int)source.getAuthenticatedDevice().get().getId());
.setSourceDevice((int) source.getAuthenticatedDevice().get().getId());
if (messageBody.isPresent()) {
messageBuilder.setMessage(ByteString.copyFrom(messageBody.get()));
messageBuilder.setLegacyMessage(ByteString.copyFrom(messageBody.get()));
}
if (messageContent.isPresent()) {
messageBuilder.setContent(ByteString.copyFrom(messageContent.get()));
}
if (source.getRelay().isPresent()) {
@ -343,6 +348,8 @@ public class MessageController {
}
private Optional<byte[]> getMessageBody(IncomingMessage message) {
if (Util.isEmpty(message.getBody())) return Optional.absent();
try {
return Optional.of(Base64.decode(message.getBody()));
} catch (IOException ioe) {
@ -350,4 +357,15 @@ public class MessageController {
return Optional.absent();
}
}
private Optional<byte[]> getMessageContent(IncomingMessage message) {
if (Util.isEmpty(message.getContent())) return Optional.absent();
try {
return Optional.of(Base64.decode(message.getContent()));
} catch (IOException ioe) {
logger.debug("Bad B64", ioe);
return Optional.absent();
}
}
}

View File

@ -18,7 +18,7 @@ package org.whispersystems.textsecuregcm.entities;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.whispersystems.textsecuregcm.entities.MessageProtos.OutgoingMessageSignal;
import org.whispersystems.textsecuregcm.entities.MessageProtos.Envelope;
import org.whispersystems.textsecuregcm.util.Base64;
import org.whispersystems.textsecuregcm.util.Util;
@ -44,8 +44,7 @@ public class EncryptedOutgoingMessage {
private final byte[] serialized;
private final String serializedAndEncoded;
public EncryptedOutgoingMessage(OutgoingMessageSignal outgoingMessage,
String signalingKey)
public EncryptedOutgoingMessage(Envelope outgoingMessage, String signalingKey)
throws CryptoEncodingException
{
byte[] plaintext = outgoingMessage.toByteArray();

View File

@ -34,9 +34,11 @@ public class IncomingMessage {
private int destinationRegistrationId;
@JsonProperty
@NotEmpty
private String body;
@JsonProperty
private String content;
@JsonProperty
private String relay;
@ -67,4 +69,8 @@ public class IncomingMessage {
public int getDestinationRegistrationId() {
return destinationRegistrationId;
}
public String getContent() {
return content;
}
}

View File

@ -1,5 +1,5 @@
// Generated by the protocol buffer compiler. DO NOT EDIT!
// source: OutgoingMessageSignal.proto
// source: TextSecure.proto
package org.whispersystems.textsecuregcm.entities;
@ -8,18 +8,18 @@ public final class MessageProtos {
public static void registerAllExtensions(
com.google.protobuf.ExtensionRegistry registry) {
}
public interface OutgoingMessageSignalOrBuilder
public interface EnvelopeOrBuilder
extends com.google.protobuf.MessageOrBuilder {
// optional uint32 type = 1;
// optional .textsecure.Envelope.Type type = 1;
/**
* <code>optional uint32 type = 1;</code>
* <code>optional .textsecure.Envelope.Type type = 1;</code>
*/
boolean hasType();
/**
* <code>optional uint32 type = 1;</code>
* <code>optional .textsecure.Envelope.Type type = 1;</code>
*/
int getType();
org.whispersystems.textsecuregcm.entities.MessageProtos.Envelope.Type getType();
// optional string source = 2;
/**
@ -64,50 +64,68 @@ public final class MessageProtos {
// optional uint64 timestamp = 5;
/**
* <code>optional uint64 timestamp = 5;</code>
*
* <pre>
* repeated string destinations = 4;
* </pre>
*/
boolean hasTimestamp();
/**
* <code>optional uint64 timestamp = 5;</code>
*
* <pre>
* repeated string destinations = 4;
* </pre>
*/
long getTimestamp();
// optional bytes message = 6;
// optional bytes legacyMessage = 6;
/**
* <code>optional bytes message = 6;</code>
* <code>optional bytes legacyMessage = 6;</code>
*
* <pre>
* Contains an encrypted DataMessage
* </pre>
*/
boolean hasMessage();
boolean hasLegacyMessage();
/**
* <code>optional bytes message = 6;</code>
* <code>optional bytes legacyMessage = 6;</code>
*
* <pre>
* Contains an encrypted DataMessage
* </pre>
*/
com.google.protobuf.ByteString getMessage();
com.google.protobuf.ByteString getLegacyMessage();
// optional bytes content = 8;
/**
* <code>optional bytes content = 8;</code>
*
* <pre>
* Contains an encrypted Content
* </pre>
*/
boolean hasContent();
/**
* <code>optional bytes content = 8;</code>
*
* <pre>
* Contains an encrypted Content
* </pre>
*/
com.google.protobuf.ByteString getContent();
}
/**
* Protobuf type {@code textsecure.OutgoingMessageSignal}
* Protobuf type {@code textsecure.Envelope}
*/
public static final class OutgoingMessageSignal extends
public static final class Envelope extends
com.google.protobuf.GeneratedMessage
implements OutgoingMessageSignalOrBuilder {
// Use OutgoingMessageSignal.newBuilder() to construct.
private OutgoingMessageSignal(com.google.protobuf.GeneratedMessage.Builder<?> builder) {
implements EnvelopeOrBuilder {
// Use Envelope.newBuilder() to construct.
private Envelope(com.google.protobuf.GeneratedMessage.Builder<?> builder) {
super(builder);
this.unknownFields = builder.getUnknownFields();
}
private OutgoingMessageSignal(boolean noInit) { this.unknownFields = com.google.protobuf.UnknownFieldSet.getDefaultInstance(); }
private Envelope(boolean noInit) { this.unknownFields = com.google.protobuf.UnknownFieldSet.getDefaultInstance(); }
private static final OutgoingMessageSignal defaultInstance;
public static OutgoingMessageSignal getDefaultInstance() {
private static final Envelope defaultInstance;
public static Envelope getDefaultInstance() {
return defaultInstance;
}
public OutgoingMessageSignal getDefaultInstanceForType() {
public Envelope getDefaultInstanceForType() {
return defaultInstance;
}
@ -117,7 +135,7 @@ public final class MessageProtos {
getUnknownFields() {
return this.unknownFields;
}
private OutgoingMessageSignal(
private Envelope(
com.google.protobuf.CodedInputStream input,
com.google.protobuf.ExtensionRegistryLite extensionRegistry)
throws com.google.protobuf.InvalidProtocolBufferException {
@ -141,8 +159,14 @@ public final class MessageProtos {
break;
}
case 8: {
bitField0_ |= 0x00000001;
type_ = input.readUInt32();
int rawValue = input.readEnum();
org.whispersystems.textsecuregcm.entities.MessageProtos.Envelope.Type value = org.whispersystems.textsecuregcm.entities.MessageProtos.Envelope.Type.valueOf(rawValue);
if (value == null) {
unknownFields.mergeVarintField(1, rawValue);
} else {
bitField0_ |= 0x00000001;
type_ = value;
}
break;
}
case 18: {
@ -162,7 +186,7 @@ public final class MessageProtos {
}
case 50: {
bitField0_ |= 0x00000020;
message_ = input.readBytes();
legacyMessage_ = input.readBytes();
break;
}
case 56: {
@ -170,6 +194,11 @@ public final class MessageProtos {
sourceDevice_ = input.readUInt32();
break;
}
case 66: {
bitField0_ |= 0x00000040;
content_ = input.readBytes();
break;
}
}
}
} catch (com.google.protobuf.InvalidProtocolBufferException e) {
@ -184,33 +213,33 @@ public final class MessageProtos {
}
public static final com.google.protobuf.Descriptors.Descriptor
getDescriptor() {
return org.whispersystems.textsecuregcm.entities.MessageProtos.internal_static_textsecure_OutgoingMessageSignal_descriptor;
return org.whispersystems.textsecuregcm.entities.MessageProtos.internal_static_textsecure_Envelope_descriptor;
}
protected com.google.protobuf.GeneratedMessage.FieldAccessorTable
internalGetFieldAccessorTable() {
return org.whispersystems.textsecuregcm.entities.MessageProtos.internal_static_textsecure_OutgoingMessageSignal_fieldAccessorTable
return org.whispersystems.textsecuregcm.entities.MessageProtos.internal_static_textsecure_Envelope_fieldAccessorTable
.ensureFieldAccessorsInitialized(
org.whispersystems.textsecuregcm.entities.MessageProtos.OutgoingMessageSignal.class, org.whispersystems.textsecuregcm.entities.MessageProtos.OutgoingMessageSignal.Builder.class);
org.whispersystems.textsecuregcm.entities.MessageProtos.Envelope.class, org.whispersystems.textsecuregcm.entities.MessageProtos.Envelope.Builder.class);
}
public static com.google.protobuf.Parser<OutgoingMessageSignal> PARSER =
new com.google.protobuf.AbstractParser<OutgoingMessageSignal>() {
public OutgoingMessageSignal parsePartialFrom(
public static com.google.protobuf.Parser<Envelope> PARSER =
new com.google.protobuf.AbstractParser<Envelope>() {
public Envelope parsePartialFrom(
com.google.protobuf.CodedInputStream input,
com.google.protobuf.ExtensionRegistryLite extensionRegistry)
throws com.google.protobuf.InvalidProtocolBufferException {
return new OutgoingMessageSignal(input, extensionRegistry);
return new Envelope(input, extensionRegistry);
}
};
@java.lang.Override
public com.google.protobuf.Parser<OutgoingMessageSignal> getParserForType() {
public com.google.protobuf.Parser<Envelope> getParserForType() {
return PARSER;
}
/**
* Protobuf enum {@code textsecure.OutgoingMessageSignal.Type}
* Protobuf enum {@code textsecure.Envelope.Type}
*/
public enum Type
implements com.google.protobuf.ProtocolMessageEnum {
@ -230,14 +259,10 @@ public final class MessageProtos {
* <code>PREKEY_BUNDLE = 3;</code>
*/
PREKEY_BUNDLE(3, 3),
/**
* <code>PLAINTEXT = 4;</code>
*/
PLAINTEXT(4, 4),
/**
* <code>RECEIPT = 5;</code>
*/
RECEIPT(5, 5),
RECEIPT(4, 5),
;
/**
@ -256,10 +281,6 @@ public final class MessageProtos {
* <code>PREKEY_BUNDLE = 3;</code>
*/
public static final int PREKEY_BUNDLE_VALUE = 3;
/**
* <code>PLAINTEXT = 4;</code>
*/
public static final int PLAINTEXT_VALUE = 4;
/**
* <code>RECEIPT = 5;</code>
*/
@ -274,7 +295,6 @@ public final class MessageProtos {
case 1: return CIPHERTEXT;
case 2: return KEY_EXCHANGE;
case 3: return PREKEY_BUNDLE;
case 4: return PLAINTEXT;
case 5: return RECEIPT;
default: return null;
}
@ -302,7 +322,7 @@ public final class MessageProtos {
}
public static final com.google.protobuf.Descriptors.EnumDescriptor
getDescriptor() {
return org.whispersystems.textsecuregcm.entities.MessageProtos.OutgoingMessageSignal.getDescriptor().getEnumTypes().get(0);
return org.whispersystems.textsecuregcm.entities.MessageProtos.Envelope.getDescriptor().getEnumTypes().get(0);
}
private static final Type[] VALUES = values();
@ -324,23 +344,23 @@ public final class MessageProtos {
this.value = value;
}
// @@protoc_insertion_point(enum_scope:textsecure.OutgoingMessageSignal.Type)
// @@protoc_insertion_point(enum_scope:textsecure.Envelope.Type)
}
private int bitField0_;
// optional uint32 type = 1;
// optional .textsecure.Envelope.Type type = 1;
public static final int TYPE_FIELD_NUMBER = 1;
private int type_;
private org.whispersystems.textsecuregcm.entities.MessageProtos.Envelope.Type type_;
/**
* <code>optional uint32 type = 1;</code>
* <code>optional .textsecure.Envelope.Type type = 1;</code>
*/
public boolean hasType() {
return ((bitField0_ & 0x00000001) == 0x00000001);
}
/**
* <code>optional uint32 type = 1;</code>
* <code>optional .textsecure.Envelope.Type type = 1;</code>
*/
public int getType() {
public org.whispersystems.textsecuregcm.entities.MessageProtos.Envelope.Type getType() {
return type_;
}
@ -451,48 +471,73 @@ public final class MessageProtos {
private long timestamp_;
/**
* <code>optional uint64 timestamp = 5;</code>
*
* <pre>
* repeated string destinations = 4;
* </pre>
*/
public boolean hasTimestamp() {
return ((bitField0_ & 0x00000010) == 0x00000010);
}
/**
* <code>optional uint64 timestamp = 5;</code>
*
* <pre>
* repeated string destinations = 4;
* </pre>
*/
public long getTimestamp() {
return timestamp_;
}
// optional bytes message = 6;
public static final int MESSAGE_FIELD_NUMBER = 6;
private com.google.protobuf.ByteString message_;
// optional bytes legacyMessage = 6;
public static final int LEGACYMESSAGE_FIELD_NUMBER = 6;
private com.google.protobuf.ByteString legacyMessage_;
/**
* <code>optional bytes message = 6;</code>
* <code>optional bytes legacyMessage = 6;</code>
*
* <pre>
* Contains an encrypted DataMessage
* </pre>
*/
public boolean hasMessage() {
public boolean hasLegacyMessage() {
return ((bitField0_ & 0x00000020) == 0x00000020);
}
/**
* <code>optional bytes message = 6;</code>
* <code>optional bytes legacyMessage = 6;</code>
*
* <pre>
* Contains an encrypted DataMessage
* </pre>
*/
public com.google.protobuf.ByteString getMessage() {
return message_;
public com.google.protobuf.ByteString getLegacyMessage() {
return legacyMessage_;
}
// optional bytes content = 8;
public static final int CONTENT_FIELD_NUMBER = 8;
private com.google.protobuf.ByteString content_;
/**
* <code>optional bytes content = 8;</code>
*
* <pre>
* Contains an encrypted Content
* </pre>
*/
public boolean hasContent() {
return ((bitField0_ & 0x00000040) == 0x00000040);
}
/**
* <code>optional bytes content = 8;</code>
*
* <pre>
* Contains an encrypted Content
* </pre>
*/
public com.google.protobuf.ByteString getContent() {
return content_;
}
private void initFields() {
type_ = 0;
type_ = org.whispersystems.textsecuregcm.entities.MessageProtos.Envelope.Type.UNKNOWN;
source_ = "";
sourceDevice_ = 0;
relay_ = "";
timestamp_ = 0L;
message_ = com.google.protobuf.ByteString.EMPTY;
legacyMessage_ = com.google.protobuf.ByteString.EMPTY;
content_ = com.google.protobuf.ByteString.EMPTY;
}
private byte memoizedIsInitialized = -1;
public final boolean isInitialized() {
@ -507,7 +552,7 @@ public final class MessageProtos {
throws java.io.IOException {
getSerializedSize();
if (((bitField0_ & 0x00000001) == 0x00000001)) {
output.writeUInt32(1, type_);
output.writeEnum(1, type_.getNumber());
}
if (((bitField0_ & 0x00000002) == 0x00000002)) {
output.writeBytes(2, getSourceBytes());
@ -519,11 +564,14 @@ public final class MessageProtos {
output.writeUInt64(5, timestamp_);
}
if (((bitField0_ & 0x00000020) == 0x00000020)) {
output.writeBytes(6, message_);
output.writeBytes(6, legacyMessage_);
}
if (((bitField0_ & 0x00000004) == 0x00000004)) {
output.writeUInt32(7, sourceDevice_);
}
if (((bitField0_ & 0x00000040) == 0x00000040)) {
output.writeBytes(8, content_);
}
getUnknownFields().writeTo(output);
}
@ -535,7 +583,7 @@ public final class MessageProtos {
size = 0;
if (((bitField0_ & 0x00000001) == 0x00000001)) {
size += com.google.protobuf.CodedOutputStream
.computeUInt32Size(1, type_);
.computeEnumSize(1, type_.getNumber());
}
if (((bitField0_ & 0x00000002) == 0x00000002)) {
size += com.google.protobuf.CodedOutputStream
@ -551,12 +599,16 @@ public final class MessageProtos {
}
if (((bitField0_ & 0x00000020) == 0x00000020)) {
size += com.google.protobuf.CodedOutputStream
.computeBytesSize(6, message_);
.computeBytesSize(6, legacyMessage_);
}
if (((bitField0_ & 0x00000004) == 0x00000004)) {
size += com.google.protobuf.CodedOutputStream
.computeUInt32Size(7, sourceDevice_);
}
if (((bitField0_ & 0x00000040) == 0x00000040)) {
size += com.google.protobuf.CodedOutputStream
.computeBytesSize(8, content_);
}
size += getUnknownFields().getSerializedSize();
memoizedSerializedSize = size;
return size;
@ -569,53 +621,53 @@ public final class MessageProtos {
return super.writeReplace();
}
public static org.whispersystems.textsecuregcm.entities.MessageProtos.OutgoingMessageSignal parseFrom(
public static org.whispersystems.textsecuregcm.entities.MessageProtos.Envelope parseFrom(
com.google.protobuf.ByteString data)
throws com.google.protobuf.InvalidProtocolBufferException {
return PARSER.parseFrom(data);
}
public static org.whispersystems.textsecuregcm.entities.MessageProtos.OutgoingMessageSignal parseFrom(
public static org.whispersystems.textsecuregcm.entities.MessageProtos.Envelope parseFrom(
com.google.protobuf.ByteString data,
com.google.protobuf.ExtensionRegistryLite extensionRegistry)
throws com.google.protobuf.InvalidProtocolBufferException {
return PARSER.parseFrom(data, extensionRegistry);
}
public static org.whispersystems.textsecuregcm.entities.MessageProtos.OutgoingMessageSignal parseFrom(byte[] data)
public static org.whispersystems.textsecuregcm.entities.MessageProtos.Envelope parseFrom(byte[] data)
throws com.google.protobuf.InvalidProtocolBufferException {
return PARSER.parseFrom(data);
}
public static org.whispersystems.textsecuregcm.entities.MessageProtos.OutgoingMessageSignal parseFrom(
public static org.whispersystems.textsecuregcm.entities.MessageProtos.Envelope parseFrom(
byte[] data,
com.google.protobuf.ExtensionRegistryLite extensionRegistry)
throws com.google.protobuf.InvalidProtocolBufferException {
return PARSER.parseFrom(data, extensionRegistry);
}
public static org.whispersystems.textsecuregcm.entities.MessageProtos.OutgoingMessageSignal parseFrom(java.io.InputStream input)
public static org.whispersystems.textsecuregcm.entities.MessageProtos.Envelope parseFrom(java.io.InputStream input)
throws java.io.IOException {
return PARSER.parseFrom(input);
}
public static org.whispersystems.textsecuregcm.entities.MessageProtos.OutgoingMessageSignal parseFrom(
public static org.whispersystems.textsecuregcm.entities.MessageProtos.Envelope parseFrom(
java.io.InputStream input,
com.google.protobuf.ExtensionRegistryLite extensionRegistry)
throws java.io.IOException {
return PARSER.parseFrom(input, extensionRegistry);
}
public static org.whispersystems.textsecuregcm.entities.MessageProtos.OutgoingMessageSignal parseDelimitedFrom(java.io.InputStream input)
public static org.whispersystems.textsecuregcm.entities.MessageProtos.Envelope parseDelimitedFrom(java.io.InputStream input)
throws java.io.IOException {
return PARSER.parseDelimitedFrom(input);
}
public static org.whispersystems.textsecuregcm.entities.MessageProtos.OutgoingMessageSignal parseDelimitedFrom(
public static org.whispersystems.textsecuregcm.entities.MessageProtos.Envelope parseDelimitedFrom(
java.io.InputStream input,
com.google.protobuf.ExtensionRegistryLite extensionRegistry)
throws java.io.IOException {
return PARSER.parseDelimitedFrom(input, extensionRegistry);
}
public static org.whispersystems.textsecuregcm.entities.MessageProtos.OutgoingMessageSignal parseFrom(
public static org.whispersystems.textsecuregcm.entities.MessageProtos.Envelope parseFrom(
com.google.protobuf.CodedInputStream input)
throws java.io.IOException {
return PARSER.parseFrom(input);
}
public static org.whispersystems.textsecuregcm.entities.MessageProtos.OutgoingMessageSignal parseFrom(
public static org.whispersystems.textsecuregcm.entities.MessageProtos.Envelope parseFrom(
com.google.protobuf.CodedInputStream input,
com.google.protobuf.ExtensionRegistryLite extensionRegistry)
throws java.io.IOException {
@ -624,7 +676,7 @@ public final class MessageProtos {
public static Builder newBuilder() { return Builder.create(); }
public Builder newBuilderForType() { return newBuilder(); }
public static Builder newBuilder(org.whispersystems.textsecuregcm.entities.MessageProtos.OutgoingMessageSignal prototype) {
public static Builder newBuilder(org.whispersystems.textsecuregcm.entities.MessageProtos.Envelope prototype) {
return newBuilder().mergeFrom(prototype);
}
public Builder toBuilder() { return newBuilder(this); }
@ -636,24 +688,24 @@ public final class MessageProtos {
return builder;
}
/**
* Protobuf type {@code textsecure.OutgoingMessageSignal}
* Protobuf type {@code textsecure.Envelope}
*/
public static final class Builder extends
com.google.protobuf.GeneratedMessage.Builder<Builder>
implements org.whispersystems.textsecuregcm.entities.MessageProtos.OutgoingMessageSignalOrBuilder {
implements org.whispersystems.textsecuregcm.entities.MessageProtos.EnvelopeOrBuilder {
public static final com.google.protobuf.Descriptors.Descriptor
getDescriptor() {
return org.whispersystems.textsecuregcm.entities.MessageProtos.internal_static_textsecure_OutgoingMessageSignal_descriptor;
return org.whispersystems.textsecuregcm.entities.MessageProtos.internal_static_textsecure_Envelope_descriptor;
}
protected com.google.protobuf.GeneratedMessage.FieldAccessorTable
internalGetFieldAccessorTable() {
return org.whispersystems.textsecuregcm.entities.MessageProtos.internal_static_textsecure_OutgoingMessageSignal_fieldAccessorTable
return org.whispersystems.textsecuregcm.entities.MessageProtos.internal_static_textsecure_Envelope_fieldAccessorTable
.ensureFieldAccessorsInitialized(
org.whispersystems.textsecuregcm.entities.MessageProtos.OutgoingMessageSignal.class, org.whispersystems.textsecuregcm.entities.MessageProtos.OutgoingMessageSignal.Builder.class);
org.whispersystems.textsecuregcm.entities.MessageProtos.Envelope.class, org.whispersystems.textsecuregcm.entities.MessageProtos.Envelope.Builder.class);
}
// Construct using org.whispersystems.textsecuregcm.entities.MessageProtos.OutgoingMessageSignal.newBuilder()
// Construct using org.whispersystems.textsecuregcm.entities.MessageProtos.Envelope.newBuilder()
private Builder() {
maybeForceBuilderInitialization();
}
@ -673,7 +725,7 @@ public final class MessageProtos {
public Builder clear() {
super.clear();
type_ = 0;
type_ = org.whispersystems.textsecuregcm.entities.MessageProtos.Envelope.Type.UNKNOWN;
bitField0_ = (bitField0_ & ~0x00000001);
source_ = "";
bitField0_ = (bitField0_ & ~0x00000002);
@ -683,8 +735,10 @@ public final class MessageProtos {
bitField0_ = (bitField0_ & ~0x00000008);
timestamp_ = 0L;
bitField0_ = (bitField0_ & ~0x00000010);
message_ = com.google.protobuf.ByteString.EMPTY;
legacyMessage_ = com.google.protobuf.ByteString.EMPTY;
bitField0_ = (bitField0_ & ~0x00000020);
content_ = com.google.protobuf.ByteString.EMPTY;
bitField0_ = (bitField0_ & ~0x00000040);
return this;
}
@ -694,23 +748,23 @@ public final class MessageProtos {
public com.google.protobuf.Descriptors.Descriptor
getDescriptorForType() {
return org.whispersystems.textsecuregcm.entities.MessageProtos.internal_static_textsecure_OutgoingMessageSignal_descriptor;
return org.whispersystems.textsecuregcm.entities.MessageProtos.internal_static_textsecure_Envelope_descriptor;
}
public org.whispersystems.textsecuregcm.entities.MessageProtos.OutgoingMessageSignal getDefaultInstanceForType() {
return org.whispersystems.textsecuregcm.entities.MessageProtos.OutgoingMessageSignal.getDefaultInstance();
public org.whispersystems.textsecuregcm.entities.MessageProtos.Envelope getDefaultInstanceForType() {
return org.whispersystems.textsecuregcm.entities.MessageProtos.Envelope.getDefaultInstance();
}
public org.whispersystems.textsecuregcm.entities.MessageProtos.OutgoingMessageSignal build() {
org.whispersystems.textsecuregcm.entities.MessageProtos.OutgoingMessageSignal result = buildPartial();
public org.whispersystems.textsecuregcm.entities.MessageProtos.Envelope build() {
org.whispersystems.textsecuregcm.entities.MessageProtos.Envelope result = buildPartial();
if (!result.isInitialized()) {
throw newUninitializedMessageException(result);
}
return result;
}
public org.whispersystems.textsecuregcm.entities.MessageProtos.OutgoingMessageSignal buildPartial() {
org.whispersystems.textsecuregcm.entities.MessageProtos.OutgoingMessageSignal result = new org.whispersystems.textsecuregcm.entities.MessageProtos.OutgoingMessageSignal(this);
public org.whispersystems.textsecuregcm.entities.MessageProtos.Envelope buildPartial() {
org.whispersystems.textsecuregcm.entities.MessageProtos.Envelope result = new org.whispersystems.textsecuregcm.entities.MessageProtos.Envelope(this);
int from_bitField0_ = bitField0_;
int to_bitField0_ = 0;
if (((from_bitField0_ & 0x00000001) == 0x00000001)) {
@ -736,23 +790,27 @@ public final class MessageProtos {
if (((from_bitField0_ & 0x00000020) == 0x00000020)) {
to_bitField0_ |= 0x00000020;
}
result.message_ = message_;
result.legacyMessage_ = legacyMessage_;
if (((from_bitField0_ & 0x00000040) == 0x00000040)) {
to_bitField0_ |= 0x00000040;
}
result.content_ = content_;
result.bitField0_ = to_bitField0_;
onBuilt();
return result;
}
public Builder mergeFrom(com.google.protobuf.Message other) {
if (other instanceof org.whispersystems.textsecuregcm.entities.MessageProtos.OutgoingMessageSignal) {
return mergeFrom((org.whispersystems.textsecuregcm.entities.MessageProtos.OutgoingMessageSignal)other);
if (other instanceof org.whispersystems.textsecuregcm.entities.MessageProtos.Envelope) {
return mergeFrom((org.whispersystems.textsecuregcm.entities.MessageProtos.Envelope)other);
} else {
super.mergeFrom(other);
return this;
}
}
public Builder mergeFrom(org.whispersystems.textsecuregcm.entities.MessageProtos.OutgoingMessageSignal other) {
if (other == org.whispersystems.textsecuregcm.entities.MessageProtos.OutgoingMessageSignal.getDefaultInstance()) return this;
public Builder mergeFrom(org.whispersystems.textsecuregcm.entities.MessageProtos.Envelope other) {
if (other == org.whispersystems.textsecuregcm.entities.MessageProtos.Envelope.getDefaultInstance()) return this;
if (other.hasType()) {
setType(other.getType());
}
@ -772,8 +830,11 @@ public final class MessageProtos {
if (other.hasTimestamp()) {
setTimestamp(other.getTimestamp());
}
if (other.hasMessage()) {
setMessage(other.getMessage());
if (other.hasLegacyMessage()) {
setLegacyMessage(other.getLegacyMessage());
}
if (other.hasContent()) {
setContent(other.getContent());
}
this.mergeUnknownFields(other.getUnknownFields());
return this;
@ -787,11 +848,11 @@ public final class MessageProtos {
com.google.protobuf.CodedInputStream input,
com.google.protobuf.ExtensionRegistryLite extensionRegistry)
throws java.io.IOException {
org.whispersystems.textsecuregcm.entities.MessageProtos.OutgoingMessageSignal parsedMessage = null;
org.whispersystems.textsecuregcm.entities.MessageProtos.Envelope parsedMessage = null;
try {
parsedMessage = PARSER.parsePartialFrom(input, extensionRegistry);
} catch (com.google.protobuf.InvalidProtocolBufferException e) {
parsedMessage = (org.whispersystems.textsecuregcm.entities.MessageProtos.OutgoingMessageSignal) e.getUnfinishedMessage();
parsedMessage = (org.whispersystems.textsecuregcm.entities.MessageProtos.Envelope) e.getUnfinishedMessage();
throw e;
} finally {
if (parsedMessage != null) {
@ -802,35 +863,38 @@ public final class MessageProtos {
}
private int bitField0_;
// optional uint32 type = 1;
private int type_ ;
// optional .textsecure.Envelope.Type type = 1;
private org.whispersystems.textsecuregcm.entities.MessageProtos.Envelope.Type type_ = org.whispersystems.textsecuregcm.entities.MessageProtos.Envelope.Type.UNKNOWN;
/**
* <code>optional uint32 type = 1;</code>
* <code>optional .textsecure.Envelope.Type type = 1;</code>
*/
public boolean hasType() {
return ((bitField0_ & 0x00000001) == 0x00000001);
}
/**
* <code>optional uint32 type = 1;</code>
* <code>optional .textsecure.Envelope.Type type = 1;</code>
*/
public int getType() {
public org.whispersystems.textsecuregcm.entities.MessageProtos.Envelope.Type getType() {
return type_;
}
/**
* <code>optional uint32 type = 1;</code>
* <code>optional .textsecure.Envelope.Type type = 1;</code>
*/
public Builder setType(int value) {
public Builder setType(org.whispersystems.textsecuregcm.entities.MessageProtos.Envelope.Type value) {
if (value == null) {
throw new NullPointerException();
}
bitField0_ |= 0x00000001;
type_ = value;
onChanged();
return this;
}
/**
* <code>optional uint32 type = 1;</code>
* <code>optional .textsecure.Envelope.Type type = 1;</code>
*/
public Builder clearType() {
bitField0_ = (bitField0_ & ~0x00000001);
type_ = 0;
type_ = org.whispersystems.textsecuregcm.entities.MessageProtos.Envelope.Type.UNKNOWN;
onChanged();
return this;
}
@ -1020,30 +1084,18 @@ public final class MessageProtos {
private long timestamp_ ;
/**
* <code>optional uint64 timestamp = 5;</code>
*
* <pre>
* repeated string destinations = 4;
* </pre>
*/
public boolean hasTimestamp() {
return ((bitField0_ & 0x00000010) == 0x00000010);
}
/**
* <code>optional uint64 timestamp = 5;</code>
*
* <pre>
* repeated string destinations = 4;
* </pre>
*/
public long getTimestamp() {
return timestamp_;
}
/**
* <code>optional uint64 timestamp = 5;</code>
*
* <pre>
* repeated string destinations = 4;
* </pre>
*/
public Builder setTimestamp(long value) {
bitField0_ |= 0x00000010;
@ -1053,10 +1105,6 @@ public final class MessageProtos {
}
/**
* <code>optional uint64 timestamp = 5;</code>
*
* <pre>
* repeated string destinations = 4;
* </pre>
*/
public Builder clearTimestamp() {
bitField0_ = (bitField0_ & ~0x00000010);
@ -1065,51 +1113,119 @@ public final class MessageProtos {
return this;
}
// optional bytes message = 6;
private com.google.protobuf.ByteString message_ = com.google.protobuf.ByteString.EMPTY;
// optional bytes legacyMessage = 6;
private com.google.protobuf.ByteString legacyMessage_ = com.google.protobuf.ByteString.EMPTY;
/**
* <code>optional bytes message = 6;</code>
* <code>optional bytes legacyMessage = 6;</code>
*
* <pre>
* Contains an encrypted DataMessage
* </pre>
*/
public boolean hasMessage() {
public boolean hasLegacyMessage() {
return ((bitField0_ & 0x00000020) == 0x00000020);
}
/**
* <code>optional bytes message = 6;</code>
* <code>optional bytes legacyMessage = 6;</code>
*
* <pre>
* Contains an encrypted DataMessage
* </pre>
*/
public com.google.protobuf.ByteString getMessage() {
return message_;
public com.google.protobuf.ByteString getLegacyMessage() {
return legacyMessage_;
}
/**
* <code>optional bytes message = 6;</code>
* <code>optional bytes legacyMessage = 6;</code>
*
* <pre>
* Contains an encrypted DataMessage
* </pre>
*/
public Builder setMessage(com.google.protobuf.ByteString value) {
public Builder setLegacyMessage(com.google.protobuf.ByteString value) {
if (value == null) {
throw new NullPointerException();
}
bitField0_ |= 0x00000020;
message_ = value;
legacyMessage_ = value;
onChanged();
return this;
}
/**
* <code>optional bytes message = 6;</code>
* <code>optional bytes legacyMessage = 6;</code>
*
* <pre>
* Contains an encrypted DataMessage
* </pre>
*/
public Builder clearMessage() {
public Builder clearLegacyMessage() {
bitField0_ = (bitField0_ & ~0x00000020);
message_ = getDefaultInstance().getMessage();
legacyMessage_ = getDefaultInstance().getLegacyMessage();
onChanged();
return this;
}
// @@protoc_insertion_point(builder_scope:textsecure.OutgoingMessageSignal)
// optional bytes content = 8;
private com.google.protobuf.ByteString content_ = com.google.protobuf.ByteString.EMPTY;
/**
* <code>optional bytes content = 8;</code>
*
* <pre>
* Contains an encrypted Content
* </pre>
*/
public boolean hasContent() {
return ((bitField0_ & 0x00000040) == 0x00000040);
}
/**
* <code>optional bytes content = 8;</code>
*
* <pre>
* Contains an encrypted Content
* </pre>
*/
public com.google.protobuf.ByteString getContent() {
return content_;
}
/**
* <code>optional bytes content = 8;</code>
*
* <pre>
* Contains an encrypted Content
* </pre>
*/
public Builder setContent(com.google.protobuf.ByteString value) {
if (value == null) {
throw new NullPointerException();
}
bitField0_ |= 0x00000040;
content_ = value;
onChanged();
return this;
}
/**
* <code>optional bytes content = 8;</code>
*
* <pre>
* Contains an encrypted Content
* </pre>
*/
public Builder clearContent() {
bitField0_ = (bitField0_ & ~0x00000040);
content_ = getDefaultInstance().getContent();
onChanged();
return this;
}
// @@protoc_insertion_point(builder_scope:textsecure.Envelope)
}
static {
defaultInstance = new OutgoingMessageSignal(true);
defaultInstance = new Envelope(true);
defaultInstance.initFields();
}
// @@protoc_insertion_point(class_scope:textsecure.OutgoingMessageSignal)
// @@protoc_insertion_point(class_scope:textsecure.Envelope)
}
public interface ProvisioningUuidOrBuilder
@ -1584,10 +1700,10 @@ public final class MessageProtos {
}
private static com.google.protobuf.Descriptors.Descriptor
internal_static_textsecure_OutgoingMessageSignal_descriptor;
internal_static_textsecure_Envelope_descriptor;
private static
com.google.protobuf.GeneratedMessage.FieldAccessorTable
internal_static_textsecure_OutgoingMessageSignal_fieldAccessorTable;
internal_static_textsecure_Envelope_fieldAccessorTable;
private static com.google.protobuf.Descriptors.Descriptor
internal_static_textsecure_ProvisioningUuid_descriptor;
private static
@ -1602,28 +1718,28 @@ public final class MessageProtos {
descriptor;
static {
java.lang.String[] descriptorData = {
"\n\033OutgoingMessageSignal.proto\022\ntextsecur" +
"e\"\344\001\n\025OutgoingMessageSignal\022\014\n\004type\030\001 \001(" +
"\r\022\016\n\006source\030\002 \001(\t\022\024\n\014sourceDevice\030\007 \001(\r\022" +
"\r\n\005relay\030\003 \001(\t\022\021\n\ttimestamp\030\005 \001(\004\022\017\n\007mes" +
"sage\030\006 \001(\014\"d\n\004Type\022\013\n\007UNKNOWN\020\000\022\016\n\nCIPHE" +
"RTEXT\020\001\022\020\n\014KEY_EXCHANGE\020\002\022\021\n\rPREKEY_BUND" +
"LE\020\003\022\r\n\tPLAINTEXT\020\004\022\013\n\007RECEIPT\020\005\" \n\020Prov" +
"isioningUuid\022\014\n\004uuid\030\001 \001(\tB:\n)org.whispe" +
"rsystems.textsecuregcm.entitiesB\rMessage" +
"Protos"
"\n\020TextSecure.proto\022\ntextsecure\"\372\001\n\010Envel" +
"ope\022\'\n\004type\030\001 \001(\0162\031.textsecure.Envelope." +
"Type\022\016\n\006source\030\002 \001(\t\022\024\n\014sourceDevice\030\007 \001" +
"(\r\022\r\n\005relay\030\003 \001(\t\022\021\n\ttimestamp\030\005 \001(\004\022\025\n\r" +
"legacyMessage\030\006 \001(\014\022\017\n\007content\030\010 \001(\014\"U\n\004" +
"Type\022\013\n\007UNKNOWN\020\000\022\016\n\nCIPHERTEXT\020\001\022\020\n\014KEY" +
"_EXCHANGE\020\002\022\021\n\rPREKEY_BUNDLE\020\003\022\013\n\007RECEIP" +
"T\020\005\" \n\020ProvisioningUuid\022\014\n\004uuid\030\001 \001(\tB:\n" +
")org.whispersystems.textsecuregcm.entiti" +
"esB\rMessageProtos"
};
com.google.protobuf.Descriptors.FileDescriptor.InternalDescriptorAssigner assigner =
new com.google.protobuf.Descriptors.FileDescriptor.InternalDescriptorAssigner() {
public com.google.protobuf.ExtensionRegistry assignDescriptors(
com.google.protobuf.Descriptors.FileDescriptor root) {
descriptor = root;
internal_static_textsecure_OutgoingMessageSignal_descriptor =
internal_static_textsecure_Envelope_descriptor =
getDescriptor().getMessageTypes().get(0);
internal_static_textsecure_OutgoingMessageSignal_fieldAccessorTable = new
internal_static_textsecure_Envelope_fieldAccessorTable = new
com.google.protobuf.GeneratedMessage.FieldAccessorTable(
internal_static_textsecure_OutgoingMessageSignal_descriptor,
new java.lang.String[] { "Type", "Source", "SourceDevice", "Relay", "Timestamp", "Message", });
internal_static_textsecure_Envelope_descriptor,
new java.lang.String[] { "Type", "Source", "SourceDevice", "Relay", "Timestamp", "LegacyMessage", "Content", });
internal_static_textsecure_ProvisioningUuid_descriptor =
getDescriptor().getMessageTypes().get(1);
internal_static_textsecure_ProvisioningUuid_fieldAccessorTable = new

View File

@ -26,10 +26,14 @@ public class OutgoingMessageEntity {
@JsonProperty
private byte[] message;
@JsonProperty
private byte[] content;
public OutgoingMessageEntity() {}
public OutgoingMessageEntity(long id, int type, String relay, long timestamp,
String source, int sourceDevice, byte[] message)
String source, int sourceDevice, byte[] message,
byte[] content)
{
this.id = id;
this.type = type;
@ -38,6 +42,7 @@ public class OutgoingMessageEntity {
this.source = source;
this.sourceDevice = sourceDevice;
this.message = message;
this.content = content;
}
public int getType() {
@ -64,7 +69,12 @@ public class OutgoingMessageEntity {
return message;
}
public byte[] getContent() {
return content;
}
public long getId() {
return id;
}
}

View File

@ -29,11 +29,9 @@ import org.whispersystems.textsecuregcm.storage.Device;
import org.whispersystems.textsecuregcm.util.Util;
import org.whispersystems.textsecuregcm.websocket.WebsocketAddress;
import java.util.LinkedHashMap;
import java.util.concurrent.TimeUnit;
import io.dropwizard.lifecycle.Managed;
import static org.whispersystems.textsecuregcm.entities.MessageProtos.OutgoingMessageSignal;
import static org.whispersystems.textsecuregcm.entities.MessageProtos.Envelope;
public class PushSender {
@ -51,7 +49,7 @@ public class PushSender {
this.webSocketSender = websocketSender;
}
public void sendMessage(Account account, Device device, OutgoingMessageSignal message)
public void sendMessage(Account account, Device device, Envelope message)
throws NotPushRegisteredException, TransientPushFailureException
{
if (device.getGcmId() != null) sendGcmMessage(account, device, message);
@ -64,21 +62,21 @@ public class PushSender {
return webSocketSender;
}
private void sendGcmMessage(Account account, Device device, OutgoingMessageSignal message)
private void sendGcmMessage(Account account, Device device, Envelope message)
throws TransientPushFailureException, NotPushRegisteredException
{
if (device.getFetchesMessages()) sendNotificationGcmMessage(account, device, message);
else sendPayloadGcmMessage(account, device, message);
}
private void sendPayloadGcmMessage(Account account, Device device, OutgoingMessageSignal message)
private void sendPayloadGcmMessage(Account account, Device device, Envelope message)
throws TransientPushFailureException, NotPushRegisteredException
{
try {
String number = account.getNumber();
long deviceId = device.getId();
String registrationId = device.getGcmId();
boolean isReceipt = message.getType() == OutgoingMessageSignal.Type.RECEIPT_VALUE;
boolean isReceipt = message.getType() == Envelope.Type.RECEIPT;
EncryptedOutgoingMessage encryptedMessage = new EncryptedOutgoingMessage(message, device.getSignalingKey());
GcmMessage gcmMessage = new GcmMessage(registrationId, number, (int) deviceId,
encryptedMessage.toEncodedString(), isReceipt, false);
@ -89,7 +87,7 @@ public class PushSender {
}
}
private void sendNotificationGcmMessage(Account account, Device device, OutgoingMessageSignal message)
private void sendNotificationGcmMessage(Account account, Device device, Envelope message)
throws TransientPushFailureException
{
DeliveryStatus deliveryStatus = webSocketSender.sendMessage(account, device, message, WebsocketSender.Type.GCM);
@ -102,12 +100,12 @@ public class PushSender {
}
}
private void sendApnMessage(Account account, Device device, OutgoingMessageSignal outgoingMessage)
private void sendApnMessage(Account account, Device device, Envelope outgoingMessage)
throws TransientPushFailureException
{
DeliveryStatus deliveryStatus = webSocketSender.sendMessage(account, device, outgoingMessage, WebsocketSender.Type.APN);
if (!deliveryStatus.isDelivered() && outgoingMessage.getType() != OutgoingMessageSignal.Type.RECEIPT_VALUE) {
if (!deliveryStatus.isDelivered() && outgoingMessage.getType() != Envelope.Type.RECEIPT) {
ApnMessage apnMessage;
if (!Util.isEmpty(device.getVoipApnId())) {
@ -127,7 +125,7 @@ public class PushSender {
}
}
private void sendWebSocketMessage(Account account, Device device, OutgoingMessageSignal outgoingMessage)
private void sendWebSocketMessage(Account account, Device device, Envelope outgoingMessage)
{
webSocketSender.sendMessage(account, device, outgoingMessage, WebsocketSender.Type.WEB);
}

View File

@ -2,7 +2,7 @@ package org.whispersystems.textsecuregcm.push;
import com.google.common.base.Optional;
import org.whispersystems.textsecuregcm.controllers.NoSuchUserException;
import org.whispersystems.textsecuregcm.entities.MessageProtos;
import org.whispersystems.textsecuregcm.entities.MessageProtos.Envelope;
import org.whispersystems.textsecuregcm.federation.FederatedClientManager;
import org.whispersystems.textsecuregcm.federation.NoSuchPeerException;
import org.whispersystems.textsecuregcm.storage.Account;
@ -55,15 +55,13 @@ public class ReceiptSender {
private void sendDirectReceipt(Account source, String destination, long messageId)
throws NotPushRegisteredException, TransientPushFailureException, NoSuchUserException
{
Account destinationAccount = getDestinationAccount(destination);
Set<Device> destinationDevices = destinationAccount.getDevices();
MessageProtos.OutgoingMessageSignal.Builder message =
MessageProtos.OutgoingMessageSignal.newBuilder()
.setSource(source.getNumber())
.setSourceDevice((int) source.getAuthenticatedDevice().get().getId())
.setTimestamp(messageId)
.setType(MessageProtos.OutgoingMessageSignal.Type.RECEIPT_VALUE);
Account destinationAccount = getDestinationAccount(destination);
Set<Device> destinationDevices = destinationAccount.getDevices();
Envelope.Builder message = Envelope.newBuilder()
.setSource(source.getNumber())
.setSourceDevice((int) source.getAuthenticatedDevice().get().getId())
.setTimestamp(messageId)
.setType(Envelope.Type.RECEIPT);
if (source.getRelay().isPresent()) {
message.setRelay(source.getRelay().get());

View File

@ -31,7 +31,7 @@ import org.whispersystems.textsecuregcm.websocket.ProvisioningAddress;
import org.whispersystems.textsecuregcm.websocket.WebsocketAddress;
import static com.codahale.metrics.MetricRegistry.name;
import static org.whispersystems.textsecuregcm.entities.MessageProtos.OutgoingMessageSignal;
import static org.whispersystems.textsecuregcm.entities.MessageProtos.Envelope;
import static org.whispersystems.textsecuregcm.storage.PubSubProtos.PubSubMessage;
public class WebsocketSender {
@ -66,7 +66,7 @@ public class WebsocketSender {
this.pubSubManager = pubSubManager;
}
public DeliveryStatus sendMessage(Account account, Device device, OutgoingMessageSignal message, Type channel) {
public DeliveryStatus sendMessage(Account account, Device device, Envelope message, Type channel) {
WebsocketAddress address = new WebsocketAddress(account.getNumber(), device.getId());
PubSubMessage pubSubMessage = PubSubMessage.newBuilder()
.setType(PubSubMessage.Type.DELIVER)

View File

@ -10,7 +10,7 @@ import org.skife.jdbi.v2.sqlobject.SqlQuery;
import org.skife.jdbi.v2.sqlobject.SqlUpdate;
import org.skife.jdbi.v2.sqlobject.customizers.Mapper;
import org.skife.jdbi.v2.tweak.ResultSetMapper;
import org.whispersystems.textsecuregcm.entities.MessageProtos.OutgoingMessageSignal;
import org.whispersystems.textsecuregcm.entities.MessageProtos.Envelope;
import org.whispersystems.textsecuregcm.entities.OutgoingMessageEntity;
import java.lang.annotation.Annotation;
@ -33,11 +33,12 @@ public abstract class Messages {
private static final String DESTINATION = "destination";
private static final String DESTINATION_DEVICE = "destination_device";
private static final String MESSAGE = "message";
private static final String CONTENT = "content";
@SqlQuery("INSERT INTO messages (" + TYPE + ", " + RELAY + ", " + TIMESTAMP + ", " + SOURCE + ", " + SOURCE_DEVICE + ", " + DESTINATION + ", " + DESTINATION_DEVICE + ", " + MESSAGE + ") " +
"VALUES (:type, :relay, :timestamp, :source, :source_device, :destination, :destination_device, :message) " +
"RETURNING (SELECT COUNT(id) FROM messages WHERE " + DESTINATION + " = :destination AND " + DESTINATION_DEVICE + " = :destination_device AND " + TYPE + " != " + OutgoingMessageSignal.Type.RECEIPT_VALUE + ")")
abstract int store(@MessageBinder OutgoingMessageSignal message,
@SqlQuery("INSERT INTO messages (" + TYPE + ", " + RELAY + ", " + TIMESTAMP + ", " + SOURCE + ", " + SOURCE_DEVICE + ", " + DESTINATION + ", " + DESTINATION_DEVICE + ", " + MESSAGE + ", " + CONTENT + ") " +
"VALUES (:type, :relay, :timestamp, :source, :source_device, :destination, :destination_device, :message, :content) " +
"RETURNING (SELECT COUNT(id) FROM messages WHERE " + DESTINATION + " = :destination AND " + DESTINATION_DEVICE + " = :destination_device AND " + TYPE + " != " + Envelope.Type.RECEIPT_VALUE + ")")
abstract int store(@MessageBinder Envelope message,
@Bind("destination") String destination,
@Bind("destination_device") long destinationDevice);
@ -71,7 +72,8 @@ public abstract class Messages {
resultSet.getLong(TIMESTAMP),
resultSet.getString(SOURCE),
resultSet.getInt(SOURCE_DEVICE),
resultSet.getBytes(MESSAGE));
resultSet.getBytes(MESSAGE),
resultSet.getBytes(CONTENT));
}
}
@ -82,18 +84,19 @@ public abstract class Messages {
public static class AccountBinderFactory implements BinderFactory {
@Override
public Binder build(Annotation annotation) {
return new Binder<MessageBinder, OutgoingMessageSignal>() {
return new Binder<MessageBinder, Envelope>() {
@Override
public void bind(SQLStatement<?> sql,
MessageBinder accountBinder,
OutgoingMessageSignal message)
Envelope message)
{
sql.bind(TYPE, message.getType());
sql.bind(TYPE, message.getType().getNumber());
sql.bind(RELAY, message.getRelay());
sql.bind(TIMESTAMP, message.getTimestamp());
sql.bind(SOURCE, message.getSource());
sql.bind(SOURCE_DEVICE, message.getSourceDevice());
sql.bind(MESSAGE, message.getMessage().toByteArray());
sql.bind(MESSAGE, message.hasLegacyMessage() ? message.getLegacyMessage().toByteArray() : null);
sql.bind(CONTENT, message.hasContent() ? message.getContent().toByteArray() : null);
}
};
}

View File

@ -2,9 +2,8 @@ package org.whispersystems.textsecuregcm.storage;
import com.google.common.base.Optional;
import org.whispersystems.textsecuregcm.entities.MessageProtos.OutgoingMessageSignal;
import org.whispersystems.textsecuregcm.entities.MessageProtos.Envelope;
import org.whispersystems.textsecuregcm.entities.OutgoingMessageEntity;
import org.whispersystems.textsecuregcm.util.Pair;
import java.util.List;
@ -16,7 +15,7 @@ public class MessagesManager {
this.messages = messages;
}
public int insert(String destination, long destinationDevice, OutgoingMessageSignal message) {
public int insert(String destination, long destinationDevice, Envelope message) {
return this.messages.store(message, destination, destinationDevice) + 1;
}

View File

@ -4,9 +4,8 @@ import com.google.protobuf.InvalidProtocolBufferException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.whispersystems.dispatch.DispatchChannel;
import org.whispersystems.textsecuregcm.entities.MessageProtos.OutgoingMessageSignal;
import org.whispersystems.textsecuregcm.entities.MessageProtos.Envelope;
import org.whispersystems.textsecuregcm.storage.MessagesManager;
import org.whispersystems.textsecuregcm.storage.PubSubProtos;
import org.whispersystems.textsecuregcm.storage.PubSubProtos.PubSubMessage;
public class DeadLetterHandler implements DispatchChannel {
@ -29,7 +28,7 @@ public class DeadLetterHandler implements DispatchChannel {
switch (pubSubMessage.getType().getNumber()) {
case PubSubMessage.Type.DELIVER_VALUE:
OutgoingMessageSignal message = OutgoingMessageSignal.parseFrom(pubSubMessage.getContent());
Envelope message = Envelope.parseFrom(pubSubMessage.getContent());
messagesManager.insert(address.getNumber(), address.getDeviceId(), message);
break;
}

View File

@ -29,7 +29,7 @@ import javax.ws.rs.WebApplicationException;
import java.io.IOException;
import java.util.List;
import static org.whispersystems.textsecuregcm.entities.MessageProtos.OutgoingMessageSignal;
import static org.whispersystems.textsecuregcm.entities.MessageProtos.Envelope;
import static org.whispersystems.textsecuregcm.storage.PubSubProtos.PubSubMessage;
public class WebSocketConnection implements DispatchChannel {
@ -69,7 +69,7 @@ public class WebSocketConnection implements DispatchChannel {
processStoredMessages();
break;
case PubSubMessage.Type.DELIVER_VALUE:
sendMessage(OutgoingMessageSignal.parseFrom(pubSubMessage.getContent()), Optional.<Long>absent());
sendMessage(Envelope.parseFrom(pubSubMessage.getContent()), Optional.<Long>absent());
break;
default:
logger.warn("Unknown pubsub message: " + pubSubMessage.getType().getNumber());
@ -88,7 +88,7 @@ public class WebSocketConnection implements DispatchChannel {
processStoredMessages();
}
private void sendMessage(final OutgoingMessageSignal message,
private void sendMessage(final Envelope message,
final Optional<Long> storedMessageId)
{
try {
@ -99,7 +99,7 @@ public class WebSocketConnection implements DispatchChannel {
Futures.addCallback(response, new FutureCallback<WebSocketResponseMessage>() {
@Override
public void onSuccess(@Nullable WebSocketResponseMessage response) {
boolean isReceipt = message.getType() == OutgoingMessageSignal.Type.RECEIPT_VALUE;
boolean isReceipt = message.getType() == Envelope.Type.RECEIPT;
if (isSuccessResponse(response)) {
if (storedMessageId.isPresent()) messagesManager.delete(account.getNumber(), storedMessageId.get());
@ -123,7 +123,7 @@ public class WebSocketConnection implements DispatchChannel {
}
}
private void requeueMessage(OutgoingMessageSignal message) {
private void requeueMessage(Envelope message) {
try {
pushSender.sendMessage(account, device, message);
} catch (NotPushRegisteredException | TransientPushFailureException e) {
@ -132,7 +132,7 @@ public class WebSocketConnection implements DispatchChannel {
}
}
private void sendDeliveryReceiptFor(OutgoingMessageSignal message) {
private void sendDeliveryReceiptFor(Envelope message) {
try {
receiptSender.sendReceipt(account, message.getSource(), message.getTimestamp(),
message.hasRelay() ? Optional.of(message.getRelay()) :
@ -148,12 +148,19 @@ public class WebSocketConnection implements DispatchChannel {
List<OutgoingMessageEntity> messages = messagesManager.getMessagesForDevice(account.getNumber(), device.getId());
for (OutgoingMessageEntity message : messages) {
OutgoingMessageSignal.Builder builder = OutgoingMessageSignal.newBuilder()
.setType(message.getType())
.setMessage(ByteString.copyFrom(message.getMessage()))
.setSourceDevice(message.getSourceDevice())
.setSource(message.getSource())
.setTimestamp(message.getTimestamp());
Envelope.Builder builder = Envelope.newBuilder()
.setType(Envelope.Type.valueOf(message.getType()))
.setSourceDevice(message.getSourceDevice())
.setSource(message.getSource())
.setTimestamp(message.getTimestamp());
if (message.getMessage() != null) {
builder.setLegacyMessage(ByteString.copyFrom(message.getMessage()));
}
if (message.getContent() != null) {
builder.setContent(ByteString.copyFrom(message.getContent()));
}
if (message.getRelay() != null && !message.getRelay().isEmpty()) {
builder.setRelay(message.getRelay());

View File

@ -57,4 +57,12 @@
</createIndex>
</changeSet>
<changeSet id="2" author="moxie">
<addColumn tableName="messages">
<column name="content" type="bytea"/>
</addColumn>
<dropNotNullConstraint tableName="messages" columnName="message"/>
</changeSet>
</databaseChangeLog>

View File

@ -106,7 +106,7 @@ public class FederatedControllerTest {
assertThat("Good Response", response.getStatus(), is(equalTo(204)));
verify(pushSender).sendMessage(any(Account.class), any(Device.class), any(MessageProtos.OutgoingMessageSignal.class));
verify(pushSender).sendMessage(any(Account.class), any(Device.class), any(MessageProtos.Envelope.class));
}
@Test

View File

@ -3,13 +3,12 @@ package org.whispersystems.textsecuregcm.tests.controllers;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.google.common.base.Optional;
import com.sun.jersey.api.client.ClientResponse;
import org.hamcrest.CoreMatchers;
import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
import org.whispersystems.textsecuregcm.controllers.MessageController;
import org.whispersystems.textsecuregcm.entities.IncomingMessageList;
import org.whispersystems.textsecuregcm.entities.MessageProtos;
import org.whispersystems.textsecuregcm.entities.MessageProtos.Envelope;
import org.whispersystems.textsecuregcm.entities.MismatchedDevices;
import org.whispersystems.textsecuregcm.entities.OutgoingMessageEntity;
import org.whispersystems.textsecuregcm.entities.OutgoingMessageEntityList;
@ -25,7 +24,6 @@ import org.whispersystems.textsecuregcm.storage.AccountsManager;
import org.whispersystems.textsecuregcm.storage.Device;
import org.whispersystems.textsecuregcm.storage.MessagesManager;
import org.whispersystems.textsecuregcm.tests.util.AuthHelper;
import org.whispersystems.textsecuregcm.util.SystemMapper;
import javax.ws.rs.core.MediaType;
import java.util.HashSet;
@ -100,7 +98,7 @@ public class MessageControllerTest {
assertThat("Good Response", response.getStatus(), is(equalTo(200)));
verify(pushSender, times(1)).sendMessage(any(Account.class), any(Device.class), any(MessageProtos.OutgoingMessageSignal.class));
verify(pushSender, times(1)).sendMessage(any(Account.class), any(Device.class), any(Envelope.class));
}
@Test
@ -114,7 +112,7 @@ public class MessageControllerTest {
assertThat("Good Response", response.getStatus(), is(equalTo(200)));
verify(pushSender, times(1)).sendMessage(any(Account.class), any(Device.class), any(MessageProtos.OutgoingMessageSignal.class));
verify(pushSender, times(1)).sendMessage(any(Account.class), any(Device.class), any(Envelope.class));
}
@Test
@ -164,7 +162,7 @@ public class MessageControllerTest {
assertThat("Good Response Code", response.getStatus(), is(equalTo(200)));
verify(pushSender, times(2)).sendMessage(any(Account.class), any(Device.class), any(MessageProtos.OutgoingMessageSignal.class));
verify(pushSender, times(2)).sendMessage(any(Account.class), any(Device.class), any(Envelope.class));
}
@Test
@ -193,8 +191,8 @@ public class MessageControllerTest {
final long timestampTwo = 313388;
List<OutgoingMessageEntity> messages = new LinkedList<OutgoingMessageEntity>() {{
add(new OutgoingMessageEntity(1L, MessageProtos.OutgoingMessageSignal.Type.CIPHERTEXT_VALUE, null, timestampOne, "+14152222222", 2, "hi there".getBytes()));
add(new OutgoingMessageEntity(2L, MessageProtos.OutgoingMessageSignal.Type.RECEIPT_VALUE, null, timestampTwo, "+14152222222", 2, null));
add(new OutgoingMessageEntity(1L, Envelope.Type.CIPHERTEXT_VALUE, null, timestampOne, "+14152222222", 2, "hi there".getBytes(), null));
add(new OutgoingMessageEntity(2L, Envelope.Type.RECEIPT_VALUE, null, timestampTwo, "+14152222222", 2, null, null));
}};
when(messagesManager.getMessagesForDevice(eq(AuthHelper.VALID_NUMBER), eq(1L))).thenReturn(messages);
@ -220,15 +218,15 @@ public class MessageControllerTest {
long timestamp = System.currentTimeMillis();
when(messagesManager.delete(AuthHelper.VALID_NUMBER, "+14152222222", 31337))
.thenReturn(Optional.of(new OutgoingMessageEntity(31337L,
MessageProtos.OutgoingMessageSignal.Type.CIPHERTEXT_VALUE,
Envelope.Type.CIPHERTEXT_VALUE,
null, timestamp,
"+14152222222", 1, "hi".getBytes())));
"+14152222222", 1, "hi".getBytes(), null)));
when(messagesManager.delete(AuthHelper.VALID_NUMBER, "+14152222222", 31338))
.thenReturn(Optional.of(new OutgoingMessageEntity(31337L,
MessageProtos.OutgoingMessageSignal.Type.RECEIPT_VALUE,
Envelope.Type.RECEIPT_VALUE,
null, System.currentTimeMillis(),
"+14152222222", 1, null)));
"+14152222222", 1, null, null)));
when(messagesManager.delete(AuthHelper.VALID_NUMBER, "+14152222222", 31339))

View File

@ -8,6 +8,7 @@ import org.junit.Rule;
import org.junit.Test;
import org.whispersystems.textsecuregcm.controllers.ReceiptController;
import org.whispersystems.textsecuregcm.entities.MessageProtos;
import org.whispersystems.textsecuregcm.entities.MessageProtos.Envelope;
import org.whispersystems.textsecuregcm.federation.FederatedClientManager;
import org.whispersystems.textsecuregcm.push.PushSender;
import org.whispersystems.textsecuregcm.push.ReceiptSender;
@ -70,7 +71,7 @@ public class ReceiptControllerTest {
assertThat(response.getStatus() == 204);
verify(pushSender, times(1)).sendMessage(any(Account.class), any(Device.class), any(MessageProtos.OutgoingMessageSignal.class));
verify(pushSender, times(1)).sendMessage(any(Account.class), any(Device.class), any(Envelope.class));
}
@Test
@ -82,7 +83,7 @@ public class ReceiptControllerTest {
assertThat(response.getStatus() == 204);
verify(pushSender, times(2)).sendMessage(any(Account.class), any(Device.class), any(MessageProtos.OutgoingMessageSignal.class));
verify(pushSender, times(2)).sendMessage(any(Account.class), any(Device.class), any(Envelope.class));
}

View File

@ -5,7 +5,6 @@ import com.google.common.util.concurrent.SettableFuture;
import com.google.protobuf.ByteString;
import org.eclipse.jetty.websocket.api.UpgradeRequest;
import org.junit.Test;
import org.mockito.ArgumentCaptor;
import org.mockito.invocation.InvocationOnMock;
import org.mockito.stubbing.Answer;
import org.whispersystems.textsecuregcm.auth.AccountAuthenticator;
@ -20,7 +19,6 @@ import org.whispersystems.textsecuregcm.storage.MessagesManager;
import org.whispersystems.textsecuregcm.storage.PubSubManager;
import org.whispersystems.textsecuregcm.storage.PubSubProtos;
import org.whispersystems.textsecuregcm.util.Base64;
import org.whispersystems.textsecuregcm.util.Pair;
import org.whispersystems.textsecuregcm.websocket.AuthenticatedConnectListener;
import org.whispersystems.textsecuregcm.websocket.WebSocketAccountAuthenticator;
import org.whispersystems.textsecuregcm.websocket.WebSocketConnection;
@ -28,7 +26,6 @@ import org.whispersystems.textsecuregcm.websocket.WebsocketAddress;
import org.whispersystems.websocket.WebSocketClient;
import org.whispersystems.websocket.messages.WebSocketResponseMessage;
import org.whispersystems.websocket.session.WebSocketSessionContext;
import org.whispersystems.websocket.setup.WebSocketConnectListener;
import java.io.IOException;
import java.util.HashMap;
@ -38,12 +35,10 @@ import java.util.List;
import java.util.Set;
import io.dropwizard.auth.basic.BasicCredentials;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.*;
import static org.mockito.Matchers.eq;
import static org.mockito.Mockito.*;
import static org.whispersystems.textsecuregcm.entities.MessageProtos.OutgoingMessageSignal;
import static org.whispersystems.textsecuregcm.entities.MessageProtos.Envelope;
public class WebSocketConnectionTest {
@ -169,21 +164,21 @@ public class WebSocketConnectionTest {
@Test
public void testOnlineSend() throws Exception {
MessagesManager storedMessages = mock(MessagesManager.class);
OutgoingMessageSignal firstMessage = OutgoingMessageSignal.newBuilder()
.setMessage(ByteString.copyFrom("first".getBytes()))
.setSource("sender1")
.setTimestamp(System.currentTimeMillis())
.setSourceDevice(1)
.setType(OutgoingMessageSignal.Type.CIPHERTEXT_VALUE)
.build();
Envelope firstMessage = Envelope.newBuilder()
.setLegacyMessage(ByteString.copyFrom("first".getBytes()))
.setSource("sender1")
.setTimestamp(System.currentTimeMillis())
.setSourceDevice(1)
.setType(Envelope.Type.CIPHERTEXT)
.build();
OutgoingMessageSignal secondMessage = OutgoingMessageSignal.newBuilder()
.setMessage(ByteString.copyFrom("second".getBytes()))
.setSource("sender2")
.setTimestamp(System.currentTimeMillis())
.setSourceDevice(2)
.setType(OutgoingMessageSignal.Type.CIPHERTEXT_VALUE)
.build();
Envelope secondMessage = Envelope.newBuilder()
.setLegacyMessage(ByteString.copyFrom("second".getBytes()))
.setSource("sender2")
.setTimestamp(System.currentTimeMillis())
.setSourceDevice(2)
.setType(Envelope.Type.CIPHERTEXT)
.build();
List<OutgoingMessageEntity> pendingMessages = new LinkedList<>();
@ -246,15 +241,15 @@ public class WebSocketConnectionTest {
futures.get(0).setException(new IOException());
verify(receiptSender, times(1)).sendReceipt(eq(account), eq("sender2"), eq(secondMessage.getTimestamp()), eq(Optional.<String>absent()));
verify(pushSender, times(1)).sendMessage(eq(account), eq(device), any(OutgoingMessageSignal.class));
verify(pushSender, times(1)).sendMessage(eq(account), eq(device), any(Envelope.class));
connection.onDispatchUnsubscribed(websocketAddress.serialize());
verify(client).close(anyInt(), anyString());
}
private OutgoingMessageEntity createMessage(long id, String sender, long timestamp, boolean receipt, String content) {
return new OutgoingMessageEntity(id, receipt ? OutgoingMessageSignal.Type.RECEIPT_VALUE : OutgoingMessageSignal.Type.CIPHERTEXT_VALUE,
null, timestamp, sender, 1, content.getBytes());
return new OutgoingMessageEntity(id, receipt ? Envelope.Type.RECEIPT_VALUE : Envelope.Type.CIPHERTEXT_VALUE,
null, timestamp, sender, 1, content.getBytes(), null);
}
}