mirror of
https://github.com/oxen-io/session-android.git
synced 2025-02-17 13:58:25 +00:00
Support for server federation.
This commit is contained in:
parent
25a2ad7289
commit
fa5ccc3f8a
@ -6,9 +6,10 @@ option java_outer_classname = "PushMessageProtos";
|
|||||||
message IncomingPushMessageSignal {
|
message IncomingPushMessageSignal {
|
||||||
optional uint32 type = 1;
|
optional uint32 type = 1;
|
||||||
optional string source = 2;
|
optional string source = 2;
|
||||||
repeated string destinations = 3;
|
optional string relay = 3;
|
||||||
optional uint64 timestamp = 4;
|
repeated string destinations = 4;
|
||||||
optional bytes message = 5; // Contains an encrypted IncomingPushMessageContent
|
optional uint64 timestamp = 5;
|
||||||
|
optional bytes message = 6; // Contains an encrypted PushMessageContent
|
||||||
}
|
}
|
||||||
|
|
||||||
message PushMessageContent {
|
message PushMessageContent {
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
package org.whispersystems.textsecure;
|
package org.whispersystems.textsecure;
|
||||||
|
|
||||||
public class Release {
|
public class Release {
|
||||||
public static final String PUSH_SERVICE_URL = "https://gcm.textsecure.whispersystems.org";
|
public static final String PUSH_SERVICE_URL = "https://federated.textsecure.whispersystems.org";
|
||||||
// public static final String PUSH_SERVICE_URL = "http://192.168.1.135:8080";
|
// public static final String PUSH_SERVICE_URL = "http://192.168.1.135:8080";
|
||||||
public static final boolean ENFORCE_SSL = true;
|
public static final boolean ENFORCE_SSL = true;
|
||||||
}
|
}
|
||||||
|
@ -132,6 +132,9 @@ public class PreKeyUtil {
|
|||||||
private static class PreKeyRecordIdComparator implements Comparator<String> {
|
private static class PreKeyRecordIdComparator implements Comparator<String> {
|
||||||
@Override
|
@Override
|
||||||
public int compare(String lhs, String rhs) {
|
public int compare(String lhs, String rhs) {
|
||||||
|
if (lhs.equals(PreKeyIndex.FILE_NAME)) return -1;
|
||||||
|
else if (rhs.equals(PreKeyIndex.FILE_NAME)) return 1;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
long lhsLong = Long.parseLong(lhs);
|
long lhsLong = Long.parseLong(lhs);
|
||||||
long rhsLong = Long.parseLong(rhs);
|
long rhsLong = Long.parseLong(rhs);
|
||||||
|
@ -9,6 +9,7 @@ import android.net.Uri;
|
|||||||
import android.provider.ContactsContract.CommonDataKinds.Phone;
|
import android.provider.ContactsContract.CommonDataKinds.Phone;
|
||||||
import android.util.Log;
|
import android.util.Log;
|
||||||
|
|
||||||
|
import org.whispersystems.textsecure.push.ContactTokenDetails;
|
||||||
import org.whispersystems.textsecure.util.Base64;
|
import org.whispersystems.textsecure.util.Base64;
|
||||||
import org.whispersystems.textsecure.util.PhoneNumberFormatter;
|
import org.whispersystems.textsecure.util.PhoneNumberFormatter;
|
||||||
import org.whispersystems.textsecure.util.Util;
|
import org.whispersystems.textsecure.util.Util;
|
||||||
@ -29,11 +30,15 @@ public class Directory {
|
|||||||
private static final String ID = "_id";
|
private static final String ID = "_id";
|
||||||
private static final String TOKEN = "token";
|
private static final String TOKEN = "token";
|
||||||
private static final String REGISTERED = "registered";
|
private static final String REGISTERED = "registered";
|
||||||
|
private static final String RELAY = "relay";
|
||||||
private static final String SUPPORTS_SMS = "supports_sms";
|
private static final String SUPPORTS_SMS = "supports_sms";
|
||||||
private static final String TIMESTAMP = "timestamp";
|
private static final String TIMESTAMP = "timestamp";
|
||||||
private static final String CREATE_TABLE = "CREATE TABLE " + TABLE_NAME + "(" + ID + " INTEGER PRIMARY KEY, " +
|
private static final String CREATE_TABLE = "CREATE TABLE " + TABLE_NAME + "(" + ID + " INTEGER PRIMARY KEY, " +
|
||||||
TOKEN + " TEXT UNIQUE, " + REGISTERED + " INTEGER, " +
|
TOKEN + " TEXT UNIQUE, " +
|
||||||
SUPPORTS_SMS + " INTEGER, " + TIMESTAMP + " INTEGER);";
|
REGISTERED + " INTEGER, " +
|
||||||
|
RELAY + " TEXT " +
|
||||||
|
SUPPORTS_SMS + " INTEGER, " +
|
||||||
|
TIMESTAMP + " INTEGER);";
|
||||||
|
|
||||||
private static Directory instance;
|
private static Directory instance;
|
||||||
|
|
||||||
@ -79,27 +84,49 @@ public class Directory {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setToken(String token, boolean active) {
|
public String getRelay(String e164number) {
|
||||||
|
String token = getToken(e164number);
|
||||||
|
SQLiteDatabase database = databaseHelper.getReadableDatabase();
|
||||||
|
Cursor cursor = null;
|
||||||
|
|
||||||
|
try {
|
||||||
|
cursor = database.query(TABLE_NAME, null, TOKEN + " = ?", new String[]{token}, null, null, null);
|
||||||
|
|
||||||
|
if (cursor != null && cursor.moveToFirst()) {
|
||||||
|
return cursor.getString(cursor.getColumnIndexOrThrow(RELAY));
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
} finally {
|
||||||
|
if (cursor != null)
|
||||||
|
cursor.close();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setToken(ContactTokenDetails token, boolean active) {
|
||||||
SQLiteDatabase db = databaseHelper.getWritableDatabase();
|
SQLiteDatabase db = databaseHelper.getWritableDatabase();
|
||||||
ContentValues values = new ContentValues();
|
ContentValues values = new ContentValues();
|
||||||
values.put(TOKEN, token);
|
values.put(TOKEN, token.getToken());
|
||||||
|
values.put(RELAY, token.getRelay());
|
||||||
values.put(REGISTERED, active ? 1 : 0);
|
values.put(REGISTERED, active ? 1 : 0);
|
||||||
|
values.put(SUPPORTS_SMS, token.isSupportsSms());
|
||||||
values.put(TIMESTAMP, System.currentTimeMillis());
|
values.put(TIMESTAMP, System.currentTimeMillis());
|
||||||
db.replace(TABLE_NAME, null, values);
|
db.replace(TABLE_NAME, null, values);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setTokens(List<String> activeTokens, Collection<String> inactiveTokens) {
|
public void setTokens(List<ContactTokenDetails> activeTokens, Collection<String> inactiveTokens) {
|
||||||
long timestamp = System.currentTimeMillis();
|
long timestamp = System.currentTimeMillis();
|
||||||
SQLiteDatabase db = databaseHelper.getWritableDatabase();
|
SQLiteDatabase db = databaseHelper.getWritableDatabase();
|
||||||
db.beginTransaction();
|
db.beginTransaction();
|
||||||
|
|
||||||
try {
|
try {
|
||||||
for (String token : activeTokens) {
|
for (ContactTokenDetails token : activeTokens) {
|
||||||
Log.w("Directory", "Adding active token: " + token);
|
Log.w("Directory", "Adding active token: " + token);
|
||||||
ContentValues values = new ContentValues();
|
ContentValues values = new ContentValues();
|
||||||
values.put(TOKEN, token);
|
values.put(TOKEN, token.getToken());
|
||||||
values.put(REGISTERED, 1);
|
values.put(REGISTERED, 1);
|
||||||
values.put(TIMESTAMP, timestamp);
|
values.put(TIMESTAMP, timestamp);
|
||||||
|
values.put(RELAY, token.getRelay());
|
||||||
db.replace(TABLE_NAME, null, values);
|
db.replace(TABLE_NAME, null, values);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -125,7 +152,7 @@ public class Directory {
|
|||||||
try {
|
try {
|
||||||
cursor = context.getContentResolver().query(uri, new String[] {Phone.NUMBER}, null, null, null);
|
cursor = context.getContentResolver().query(uri, new String[] {Phone.NUMBER}, null, null, null);
|
||||||
|
|
||||||
while (cursor.moveToNext()) {
|
while (cursor != null && cursor.moveToNext()) {
|
||||||
String rawNumber = cursor.getString(0);
|
String rawNumber = cursor.getString(0);
|
||||||
|
|
||||||
if (rawNumber != null) {
|
if (rawNumber != null) {
|
||||||
@ -134,12 +161,13 @@ public class Directory {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
cursor.close();
|
if (cursor != null)
|
||||||
|
cursor.close();
|
||||||
|
|
||||||
cursor = databaseHelper.getReadableDatabase().query(TABLE_NAME, new String[] {TOKEN},
|
cursor = databaseHelper.getReadableDatabase().query(TABLE_NAME, new String[] {TOKEN},
|
||||||
null, null, null, null, null);
|
null, null, null, null, null);
|
||||||
|
|
||||||
while (cursor.moveToNext()) {
|
while (cursor != null && cursor.moveToNext()) {
|
||||||
results.add(cursor.getString(0));
|
results.add(cursor.getString(0));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -0,0 +1,41 @@
|
|||||||
|
package org.whispersystems.textsecure.push;
|
||||||
|
|
||||||
|
import com.google.thoughtcrimegson.Gson;
|
||||||
|
|
||||||
|
public class ContactTokenDetails {
|
||||||
|
|
||||||
|
private String token;
|
||||||
|
private String relay;
|
||||||
|
private boolean supportsSms;
|
||||||
|
|
||||||
|
public ContactTokenDetails() {}
|
||||||
|
|
||||||
|
public ContactTokenDetails(String token) {
|
||||||
|
this.token = token;
|
||||||
|
}
|
||||||
|
|
||||||
|
public ContactTokenDetails(String token, String relay) {
|
||||||
|
this.token = token;
|
||||||
|
this.relay = relay;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getToken() {
|
||||||
|
return token;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getRelay() {
|
||||||
|
return relay;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setRelay(String relay) {
|
||||||
|
this.relay = relay;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isSupportsSms() {
|
||||||
|
return supportsSms;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String toString() {
|
||||||
|
return new Gson().toJson(this);
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,14 @@
|
|||||||
|
package org.whispersystems.textsecure.push;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
public class ContactTokenDetailsList {
|
||||||
|
|
||||||
|
private List<ContactTokenDetails> contacts;
|
||||||
|
|
||||||
|
public ContactTokenDetailsList() {}
|
||||||
|
|
||||||
|
public List<ContactTokenDetails> getContacts() {
|
||||||
|
return contacts;
|
||||||
|
}
|
||||||
|
}
|
@ -43,14 +43,16 @@ public class IncomingPushMessage implements PushMessage, Parcelable {
|
|||||||
private List<String> destinations;
|
private List<String> destinations;
|
||||||
private byte[] message;
|
private byte[] message;
|
||||||
private long timestamp;
|
private long timestamp;
|
||||||
|
private String relay;
|
||||||
|
|
||||||
private IncomingPushMessage(IncomingPushMessage message, byte[] body) {
|
private IncomingPushMessage(IncomingPushMessage message, byte[] body) {
|
||||||
this.type = message.type;
|
this.type = message.type;
|
||||||
this.source = message.source;
|
this.source = message.source;
|
||||||
|
this.timestamp = message.timestamp;
|
||||||
|
this.relay = message.relay;
|
||||||
|
this.message = body;
|
||||||
this.destinations = new LinkedList<String>();
|
this.destinations = new LinkedList<String>();
|
||||||
this.destinations.addAll(message.destinations);
|
this.destinations.addAll(message.destinations);
|
||||||
this.message = body;
|
|
||||||
this.timestamp = message.timestamp;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public IncomingPushMessage(IncomingPushMessageSignal signal) {
|
public IncomingPushMessage(IncomingPushMessageSignal signal) {
|
||||||
@ -59,12 +61,18 @@ public class IncomingPushMessage implements PushMessage, Parcelable {
|
|||||||
this.destinations = signal.getDestinationsList();
|
this.destinations = signal.getDestinationsList();
|
||||||
this.message = signal.getMessage().toByteArray();
|
this.message = signal.getMessage().toByteArray();
|
||||||
this.timestamp = signal.getTimestamp();
|
this.timestamp = signal.getTimestamp();
|
||||||
|
this.relay = signal.getRelay();
|
||||||
}
|
}
|
||||||
|
|
||||||
public IncomingPushMessage(Parcel in) {
|
public IncomingPushMessage(Parcel in) {
|
||||||
this.destinations = new LinkedList<String>();
|
this.destinations = new LinkedList<String>();
|
||||||
this.type = in.readInt();
|
this.type = in.readInt();
|
||||||
this.source = in.readString();
|
this.source = in.readString();
|
||||||
|
|
||||||
|
if (in.readInt() == 1) {
|
||||||
|
this.relay = in.readString();
|
||||||
|
}
|
||||||
|
|
||||||
in.readStringList(destinations);
|
in.readStringList(destinations);
|
||||||
this.message = new byte[in.readInt()];
|
this.message = new byte[in.readInt()];
|
||||||
in.readByteArray(this.message);
|
in.readByteArray(this.message);
|
||||||
@ -82,6 +90,10 @@ public class IncomingPushMessage implements PushMessage, Parcelable {
|
|||||||
this.timestamp = timestamp;
|
this.timestamp = timestamp;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public String getRelay() {
|
||||||
|
return relay;
|
||||||
|
}
|
||||||
|
|
||||||
public long getTimestampMillis() {
|
public long getTimestampMillis() {
|
||||||
return timestamp;
|
return timestamp;
|
||||||
}
|
}
|
||||||
@ -107,6 +119,10 @@ public class IncomingPushMessage implements PushMessage, Parcelable {
|
|||||||
public void writeToParcel(Parcel dest, int flags) {
|
public void writeToParcel(Parcel dest, int flags) {
|
||||||
dest.writeInt(type);
|
dest.writeInt(type);
|
||||||
dest.writeString(source);
|
dest.writeString(source);
|
||||||
|
dest.writeInt(relay == null ? 0 : 1);
|
||||||
|
if (relay != null) {
|
||||||
|
dest.writeString(relay);
|
||||||
|
}
|
||||||
dest.writeStringList(destinations);
|
dest.writeStringList(destinations);
|
||||||
dest.writeInt(message.length);
|
dest.writeInt(message.length);
|
||||||
dest.writeByteArray(message);
|
dest.writeByteArray(message);
|
||||||
|
@ -23,8 +23,14 @@ public class OutgoingPushMessage implements PushMessage {
|
|||||||
private int type;
|
private int type;
|
||||||
private String destination;
|
private String destination;
|
||||||
private String body;
|
private String body;
|
||||||
|
private String relay;
|
||||||
|
|
||||||
public OutgoingPushMessage(String destination, byte[] body, int type) {
|
public OutgoingPushMessage(String destination, byte[] body, int type) {
|
||||||
|
this(null, destination, body, type);
|
||||||
|
}
|
||||||
|
|
||||||
|
public OutgoingPushMessage(String relay, String destination, byte[] body, int type) {
|
||||||
|
this.relay = relay;
|
||||||
this.destination = destination;
|
this.destination = destination;
|
||||||
this.body = Base64.encodeBytes(body);
|
this.body = Base64.encodeBytes(body);
|
||||||
this.type = type;
|
this.type = type;
|
||||||
@ -41,4 +47,8 @@ public class OutgoingPushMessage implements PushMessage {
|
|||||||
public int getType() {
|
public int getType() {
|
||||||
return type;
|
return type;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public String getRelay() {
|
||||||
|
return relay;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -19,16 +19,20 @@ public final class PushMessageProtos {
|
|||||||
boolean hasSource();
|
boolean hasSource();
|
||||||
String getSource();
|
String getSource();
|
||||||
|
|
||||||
// repeated string destinations = 3;
|
// optional string relay = 3;
|
||||||
|
boolean hasRelay();
|
||||||
|
String getRelay();
|
||||||
|
|
||||||
|
// repeated string destinations = 4;
|
||||||
java.util.List<String> getDestinationsList();
|
java.util.List<String> getDestinationsList();
|
||||||
int getDestinationsCount();
|
int getDestinationsCount();
|
||||||
String getDestinations(int index);
|
String getDestinations(int index);
|
||||||
|
|
||||||
// optional uint64 timestamp = 4;
|
// optional uint64 timestamp = 5;
|
||||||
boolean hasTimestamp();
|
boolean hasTimestamp();
|
||||||
long getTimestamp();
|
long getTimestamp();
|
||||||
|
|
||||||
// optional bytes message = 5;
|
// optional bytes message = 6;
|
||||||
boolean hasMessage();
|
boolean hasMessage();
|
||||||
com.google.protobuf.ByteString getMessage();
|
com.google.protobuf.ByteString getMessage();
|
||||||
}
|
}
|
||||||
@ -103,8 +107,40 @@ public final class PushMessageProtos {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// repeated string destinations = 3;
|
// optional string relay = 3;
|
||||||
public static final int DESTINATIONS_FIELD_NUMBER = 3;
|
public static final int RELAY_FIELD_NUMBER = 3;
|
||||||
|
private java.lang.Object relay_;
|
||||||
|
public boolean hasRelay() {
|
||||||
|
return ((bitField0_ & 0x00000004) == 0x00000004);
|
||||||
|
}
|
||||||
|
public String getRelay() {
|
||||||
|
java.lang.Object ref = relay_;
|
||||||
|
if (ref instanceof String) {
|
||||||
|
return (String) ref;
|
||||||
|
} else {
|
||||||
|
com.google.protobuf.ByteString bs =
|
||||||
|
(com.google.protobuf.ByteString) ref;
|
||||||
|
String s = bs.toStringUtf8();
|
||||||
|
if (com.google.protobuf.Internal.isValidUtf8(bs)) {
|
||||||
|
relay_ = s;
|
||||||
|
}
|
||||||
|
return s;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
private com.google.protobuf.ByteString getRelayBytes() {
|
||||||
|
java.lang.Object ref = relay_;
|
||||||
|
if (ref instanceof String) {
|
||||||
|
com.google.protobuf.ByteString b =
|
||||||
|
com.google.protobuf.ByteString.copyFromUtf8((String) ref);
|
||||||
|
relay_ = b;
|
||||||
|
return b;
|
||||||
|
} else {
|
||||||
|
return (com.google.protobuf.ByteString) ref;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// repeated string destinations = 4;
|
||||||
|
public static final int DESTINATIONS_FIELD_NUMBER = 4;
|
||||||
private com.google.protobuf.LazyStringList destinations_;
|
private com.google.protobuf.LazyStringList destinations_;
|
||||||
public java.util.List<String>
|
public java.util.List<String>
|
||||||
getDestinationsList() {
|
getDestinationsList() {
|
||||||
@ -117,21 +153,21 @@ public final class PushMessageProtos {
|
|||||||
return destinations_.get(index);
|
return destinations_.get(index);
|
||||||
}
|
}
|
||||||
|
|
||||||
// optional uint64 timestamp = 4;
|
// optional uint64 timestamp = 5;
|
||||||
public static final int TIMESTAMP_FIELD_NUMBER = 4;
|
public static final int TIMESTAMP_FIELD_NUMBER = 5;
|
||||||
private long timestamp_;
|
private long timestamp_;
|
||||||
public boolean hasTimestamp() {
|
public boolean hasTimestamp() {
|
||||||
return ((bitField0_ & 0x00000004) == 0x00000004);
|
return ((bitField0_ & 0x00000008) == 0x00000008);
|
||||||
}
|
}
|
||||||
public long getTimestamp() {
|
public long getTimestamp() {
|
||||||
return timestamp_;
|
return timestamp_;
|
||||||
}
|
}
|
||||||
|
|
||||||
// optional bytes message = 5;
|
// optional bytes message = 6;
|
||||||
public static final int MESSAGE_FIELD_NUMBER = 5;
|
public static final int MESSAGE_FIELD_NUMBER = 6;
|
||||||
private com.google.protobuf.ByteString message_;
|
private com.google.protobuf.ByteString message_;
|
||||||
public boolean hasMessage() {
|
public boolean hasMessage() {
|
||||||
return ((bitField0_ & 0x00000008) == 0x00000008);
|
return ((bitField0_ & 0x00000010) == 0x00000010);
|
||||||
}
|
}
|
||||||
public com.google.protobuf.ByteString getMessage() {
|
public com.google.protobuf.ByteString getMessage() {
|
||||||
return message_;
|
return message_;
|
||||||
@ -140,6 +176,7 @@ public final class PushMessageProtos {
|
|||||||
private void initFields() {
|
private void initFields() {
|
||||||
type_ = 0;
|
type_ = 0;
|
||||||
source_ = "";
|
source_ = "";
|
||||||
|
relay_ = "";
|
||||||
destinations_ = com.google.protobuf.LazyStringArrayList.EMPTY;
|
destinations_ = com.google.protobuf.LazyStringArrayList.EMPTY;
|
||||||
timestamp_ = 0L;
|
timestamp_ = 0L;
|
||||||
message_ = com.google.protobuf.ByteString.EMPTY;
|
message_ = com.google.protobuf.ByteString.EMPTY;
|
||||||
@ -162,14 +199,17 @@ public final class PushMessageProtos {
|
|||||||
if (((bitField0_ & 0x00000002) == 0x00000002)) {
|
if (((bitField0_ & 0x00000002) == 0x00000002)) {
|
||||||
output.writeBytes(2, getSourceBytes());
|
output.writeBytes(2, getSourceBytes());
|
||||||
}
|
}
|
||||||
for (int i = 0; i < destinations_.size(); i++) {
|
|
||||||
output.writeBytes(3, destinations_.getByteString(i));
|
|
||||||
}
|
|
||||||
if (((bitField0_ & 0x00000004) == 0x00000004)) {
|
if (((bitField0_ & 0x00000004) == 0x00000004)) {
|
||||||
output.writeUInt64(4, timestamp_);
|
output.writeBytes(3, getRelayBytes());
|
||||||
|
}
|
||||||
|
for (int i = 0; i < destinations_.size(); i++) {
|
||||||
|
output.writeBytes(4, destinations_.getByteString(i));
|
||||||
}
|
}
|
||||||
if (((bitField0_ & 0x00000008) == 0x00000008)) {
|
if (((bitField0_ & 0x00000008) == 0x00000008)) {
|
||||||
output.writeBytes(5, message_);
|
output.writeUInt64(5, timestamp_);
|
||||||
|
}
|
||||||
|
if (((bitField0_ & 0x00000010) == 0x00000010)) {
|
||||||
|
output.writeBytes(6, message_);
|
||||||
}
|
}
|
||||||
getUnknownFields().writeTo(output);
|
getUnknownFields().writeTo(output);
|
||||||
}
|
}
|
||||||
@ -188,6 +228,10 @@ public final class PushMessageProtos {
|
|||||||
size += com.google.protobuf.CodedOutputStream
|
size += com.google.protobuf.CodedOutputStream
|
||||||
.computeBytesSize(2, getSourceBytes());
|
.computeBytesSize(2, getSourceBytes());
|
||||||
}
|
}
|
||||||
|
if (((bitField0_ & 0x00000004) == 0x00000004)) {
|
||||||
|
size += com.google.protobuf.CodedOutputStream
|
||||||
|
.computeBytesSize(3, getRelayBytes());
|
||||||
|
}
|
||||||
{
|
{
|
||||||
int dataSize = 0;
|
int dataSize = 0;
|
||||||
for (int i = 0; i < destinations_.size(); i++) {
|
for (int i = 0; i < destinations_.size(); i++) {
|
||||||
@ -197,13 +241,13 @@ public final class PushMessageProtos {
|
|||||||
size += dataSize;
|
size += dataSize;
|
||||||
size += 1 * getDestinationsList().size();
|
size += 1 * getDestinationsList().size();
|
||||||
}
|
}
|
||||||
if (((bitField0_ & 0x00000004) == 0x00000004)) {
|
|
||||||
size += com.google.protobuf.CodedOutputStream
|
|
||||||
.computeUInt64Size(4, timestamp_);
|
|
||||||
}
|
|
||||||
if (((bitField0_ & 0x00000008) == 0x00000008)) {
|
if (((bitField0_ & 0x00000008) == 0x00000008)) {
|
||||||
size += com.google.protobuf.CodedOutputStream
|
size += com.google.protobuf.CodedOutputStream
|
||||||
.computeBytesSize(5, message_);
|
.computeUInt64Size(5, timestamp_);
|
||||||
|
}
|
||||||
|
if (((bitField0_ & 0x00000010) == 0x00000010)) {
|
||||||
|
size += com.google.protobuf.CodedOutputStream
|
||||||
|
.computeBytesSize(6, message_);
|
||||||
}
|
}
|
||||||
size += getUnknownFields().getSerializedSize();
|
size += getUnknownFields().getSerializedSize();
|
||||||
memoizedSerializedSize = size;
|
memoizedSerializedSize = size;
|
||||||
@ -333,12 +377,14 @@ public final class PushMessageProtos {
|
|||||||
bitField0_ = (bitField0_ & ~0x00000001);
|
bitField0_ = (bitField0_ & ~0x00000001);
|
||||||
source_ = "";
|
source_ = "";
|
||||||
bitField0_ = (bitField0_ & ~0x00000002);
|
bitField0_ = (bitField0_ & ~0x00000002);
|
||||||
destinations_ = com.google.protobuf.LazyStringArrayList.EMPTY;
|
relay_ = "";
|
||||||
bitField0_ = (bitField0_ & ~0x00000004);
|
bitField0_ = (bitField0_ & ~0x00000004);
|
||||||
timestamp_ = 0L;
|
destinations_ = com.google.protobuf.LazyStringArrayList.EMPTY;
|
||||||
bitField0_ = (bitField0_ & ~0x00000008);
|
bitField0_ = (bitField0_ & ~0x00000008);
|
||||||
message_ = com.google.protobuf.ByteString.EMPTY;
|
timestamp_ = 0L;
|
||||||
bitField0_ = (bitField0_ & ~0x00000010);
|
bitField0_ = (bitField0_ & ~0x00000010);
|
||||||
|
message_ = com.google.protobuf.ByteString.EMPTY;
|
||||||
|
bitField0_ = (bitField0_ & ~0x00000020);
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -385,19 +431,23 @@ public final class PushMessageProtos {
|
|||||||
to_bitField0_ |= 0x00000002;
|
to_bitField0_ |= 0x00000002;
|
||||||
}
|
}
|
||||||
result.source_ = source_;
|
result.source_ = source_;
|
||||||
if (((bitField0_ & 0x00000004) == 0x00000004)) {
|
if (((from_bitField0_ & 0x00000004) == 0x00000004)) {
|
||||||
destinations_ = new com.google.protobuf.UnmodifiableLazyStringList(
|
|
||||||
destinations_);
|
|
||||||
bitField0_ = (bitField0_ & ~0x00000004);
|
|
||||||
}
|
|
||||||
result.destinations_ = destinations_;
|
|
||||||
if (((from_bitField0_ & 0x00000008) == 0x00000008)) {
|
|
||||||
to_bitField0_ |= 0x00000004;
|
to_bitField0_ |= 0x00000004;
|
||||||
}
|
}
|
||||||
result.timestamp_ = timestamp_;
|
result.relay_ = relay_;
|
||||||
|
if (((bitField0_ & 0x00000008) == 0x00000008)) {
|
||||||
|
destinations_ = new com.google.protobuf.UnmodifiableLazyStringList(
|
||||||
|
destinations_);
|
||||||
|
bitField0_ = (bitField0_ & ~0x00000008);
|
||||||
|
}
|
||||||
|
result.destinations_ = destinations_;
|
||||||
if (((from_bitField0_ & 0x00000010) == 0x00000010)) {
|
if (((from_bitField0_ & 0x00000010) == 0x00000010)) {
|
||||||
to_bitField0_ |= 0x00000008;
|
to_bitField0_ |= 0x00000008;
|
||||||
}
|
}
|
||||||
|
result.timestamp_ = timestamp_;
|
||||||
|
if (((from_bitField0_ & 0x00000020) == 0x00000020)) {
|
||||||
|
to_bitField0_ |= 0x00000010;
|
||||||
|
}
|
||||||
result.message_ = message_;
|
result.message_ = message_;
|
||||||
result.bitField0_ = to_bitField0_;
|
result.bitField0_ = to_bitField0_;
|
||||||
onBuilt();
|
onBuilt();
|
||||||
@ -421,10 +471,13 @@ public final class PushMessageProtos {
|
|||||||
if (other.hasSource()) {
|
if (other.hasSource()) {
|
||||||
setSource(other.getSource());
|
setSource(other.getSource());
|
||||||
}
|
}
|
||||||
|
if (other.hasRelay()) {
|
||||||
|
setRelay(other.getRelay());
|
||||||
|
}
|
||||||
if (!other.destinations_.isEmpty()) {
|
if (!other.destinations_.isEmpty()) {
|
||||||
if (destinations_.isEmpty()) {
|
if (destinations_.isEmpty()) {
|
||||||
destinations_ = other.destinations_;
|
destinations_ = other.destinations_;
|
||||||
bitField0_ = (bitField0_ & ~0x00000004);
|
bitField0_ = (bitField0_ & ~0x00000008);
|
||||||
} else {
|
} else {
|
||||||
ensureDestinationsIsMutable();
|
ensureDestinationsIsMutable();
|
||||||
destinations_.addAll(other.destinations_);
|
destinations_.addAll(other.destinations_);
|
||||||
@ -479,17 +532,22 @@ public final class PushMessageProtos {
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case 26: {
|
case 26: {
|
||||||
|
bitField0_ |= 0x00000004;
|
||||||
|
relay_ = input.readBytes();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case 34: {
|
||||||
ensureDestinationsIsMutable();
|
ensureDestinationsIsMutable();
|
||||||
destinations_.add(input.readBytes());
|
destinations_.add(input.readBytes());
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case 32: {
|
case 40: {
|
||||||
bitField0_ |= 0x00000008;
|
bitField0_ |= 0x00000010;
|
||||||
timestamp_ = input.readUInt64();
|
timestamp_ = input.readUInt64();
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case 42: {
|
case 50: {
|
||||||
bitField0_ |= 0x00000010;
|
bitField0_ |= 0x00000020;
|
||||||
message_ = input.readBytes();
|
message_ = input.readBytes();
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -556,12 +614,48 @@ public final class PushMessageProtos {
|
|||||||
onChanged();
|
onChanged();
|
||||||
}
|
}
|
||||||
|
|
||||||
// repeated string destinations = 3;
|
// optional string relay = 3;
|
||||||
|
private java.lang.Object relay_ = "";
|
||||||
|
public boolean hasRelay() {
|
||||||
|
return ((bitField0_ & 0x00000004) == 0x00000004);
|
||||||
|
}
|
||||||
|
public String getRelay() {
|
||||||
|
java.lang.Object ref = relay_;
|
||||||
|
if (!(ref instanceof String)) {
|
||||||
|
String s = ((com.google.protobuf.ByteString) ref).toStringUtf8();
|
||||||
|
relay_ = s;
|
||||||
|
return s;
|
||||||
|
} else {
|
||||||
|
return (String) ref;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
public Builder setRelay(String value) {
|
||||||
|
if (value == null) {
|
||||||
|
throw new NullPointerException();
|
||||||
|
}
|
||||||
|
bitField0_ |= 0x00000004;
|
||||||
|
relay_ = value;
|
||||||
|
onChanged();
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
public Builder clearRelay() {
|
||||||
|
bitField0_ = (bitField0_ & ~0x00000004);
|
||||||
|
relay_ = getDefaultInstance().getRelay();
|
||||||
|
onChanged();
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
void setRelay(com.google.protobuf.ByteString value) {
|
||||||
|
bitField0_ |= 0x00000004;
|
||||||
|
relay_ = value;
|
||||||
|
onChanged();
|
||||||
|
}
|
||||||
|
|
||||||
|
// repeated string destinations = 4;
|
||||||
private com.google.protobuf.LazyStringList destinations_ = com.google.protobuf.LazyStringArrayList.EMPTY;
|
private com.google.protobuf.LazyStringList destinations_ = com.google.protobuf.LazyStringArrayList.EMPTY;
|
||||||
private void ensureDestinationsIsMutable() {
|
private void ensureDestinationsIsMutable() {
|
||||||
if (!((bitField0_ & 0x00000004) == 0x00000004)) {
|
if (!((bitField0_ & 0x00000008) == 0x00000008)) {
|
||||||
destinations_ = new com.google.protobuf.LazyStringArrayList(destinations_);
|
destinations_ = new com.google.protobuf.LazyStringArrayList(destinations_);
|
||||||
bitField0_ |= 0x00000004;
|
bitField0_ |= 0x00000008;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
public java.util.List<String>
|
public java.util.List<String>
|
||||||
@ -602,7 +696,7 @@ public final class PushMessageProtos {
|
|||||||
}
|
}
|
||||||
public Builder clearDestinations() {
|
public Builder clearDestinations() {
|
||||||
destinations_ = com.google.protobuf.LazyStringArrayList.EMPTY;
|
destinations_ = com.google.protobuf.LazyStringArrayList.EMPTY;
|
||||||
bitField0_ = (bitField0_ & ~0x00000004);
|
bitField0_ = (bitField0_ & ~0x00000008);
|
||||||
onChanged();
|
onChanged();
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
@ -612,31 +706,31 @@ public final class PushMessageProtos {
|
|||||||
onChanged();
|
onChanged();
|
||||||
}
|
}
|
||||||
|
|
||||||
// optional uint64 timestamp = 4;
|
// optional uint64 timestamp = 5;
|
||||||
private long timestamp_ ;
|
private long timestamp_ ;
|
||||||
public boolean hasTimestamp() {
|
public boolean hasTimestamp() {
|
||||||
return ((bitField0_ & 0x00000008) == 0x00000008);
|
return ((bitField0_ & 0x00000010) == 0x00000010);
|
||||||
}
|
}
|
||||||
public long getTimestamp() {
|
public long getTimestamp() {
|
||||||
return timestamp_;
|
return timestamp_;
|
||||||
}
|
}
|
||||||
public Builder setTimestamp(long value) {
|
public Builder setTimestamp(long value) {
|
||||||
bitField0_ |= 0x00000008;
|
bitField0_ |= 0x00000010;
|
||||||
timestamp_ = value;
|
timestamp_ = value;
|
||||||
onChanged();
|
onChanged();
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
public Builder clearTimestamp() {
|
public Builder clearTimestamp() {
|
||||||
bitField0_ = (bitField0_ & ~0x00000008);
|
bitField0_ = (bitField0_ & ~0x00000010);
|
||||||
timestamp_ = 0L;
|
timestamp_ = 0L;
|
||||||
onChanged();
|
onChanged();
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
// optional bytes message = 5;
|
// optional bytes message = 6;
|
||||||
private com.google.protobuf.ByteString message_ = com.google.protobuf.ByteString.EMPTY;
|
private com.google.protobuf.ByteString message_ = com.google.protobuf.ByteString.EMPTY;
|
||||||
public boolean hasMessage() {
|
public boolean hasMessage() {
|
||||||
return ((bitField0_ & 0x00000010) == 0x00000010);
|
return ((bitField0_ & 0x00000020) == 0x00000020);
|
||||||
}
|
}
|
||||||
public com.google.protobuf.ByteString getMessage() {
|
public com.google.protobuf.ByteString getMessage() {
|
||||||
return message_;
|
return message_;
|
||||||
@ -645,13 +739,13 @@ public final class PushMessageProtos {
|
|||||||
if (value == null) {
|
if (value == null) {
|
||||||
throw new NullPointerException();
|
throw new NullPointerException();
|
||||||
}
|
}
|
||||||
bitField0_ |= 0x00000010;
|
bitField0_ |= 0x00000020;
|
||||||
message_ = value;
|
message_ = value;
|
||||||
onChanged();
|
onChanged();
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
public Builder clearMessage() {
|
public Builder clearMessage() {
|
||||||
bitField0_ = (bitField0_ & ~0x00000010);
|
bitField0_ = (bitField0_ & ~0x00000020);
|
||||||
message_ = getDefaultInstance().getMessage();
|
message_ = getDefaultInstance().getMessage();
|
||||||
onChanged();
|
onChanged();
|
||||||
return this;
|
return this;
|
||||||
@ -1833,15 +1927,16 @@ public final class PushMessageProtos {
|
|||||||
static {
|
static {
|
||||||
java.lang.String[] descriptorData = {
|
java.lang.String[] descriptorData = {
|
||||||
"\n\037IncomingPushMessageSignal.proto\022\ntexts" +
|
"\n\037IncomingPushMessageSignal.proto\022\ntexts" +
|
||||||
"ecure\"s\n\031IncomingPushMessageSignal\022\014\n\004ty" +
|
"ecure\"\202\001\n\031IncomingPushMessageSignal\022\014\n\004t" +
|
||||||
"pe\030\001 \001(\r\022\016\n\006source\030\002 \001(\t\022\024\n\014destinations" +
|
"ype\030\001 \001(\r\022\016\n\006source\030\002 \001(\t\022\r\n\005relay\030\003 \001(\t" +
|
||||||
"\030\003 \003(\t\022\021\n\ttimestamp\030\004 \001(\004\022\017\n\007message\030\005 \001" +
|
"\022\024\n\014destinations\030\004 \003(\t\022\021\n\ttimestamp\030\005 \001(" +
|
||||||
"(\014\"\254\001\n\022PushMessageContent\022\014\n\004body\030\001 \001(\t\022" +
|
"\004\022\017\n\007message\030\006 \001(\014\"\254\001\n\022PushMessageConten" +
|
||||||
"E\n\013attachments\030\002 \003(\01320.textsecure.PushMe" +
|
"t\022\014\n\004body\030\001 \001(\t\022E\n\013attachments\030\002 \003(\01320.t" +
|
||||||
"ssageContent.AttachmentPointer\032A\n\021Attach" +
|
"extsecure.PushMessageContent.AttachmentP" +
|
||||||
"mentPointer\022\n\n\002id\030\001 \001(\006\022\023\n\013contentType\030\002" +
|
"ointer\032A\n\021AttachmentPointer\022\n\n\002id\030\001 \001(\006\022" +
|
||||||
" \001(\t\022\013\n\003key\030\003 \001(\014B7\n\"org.whispersystems." +
|
"\023\n\013contentType\030\002 \001(\t\022\013\n\003key\030\003 \001(\014B7\n\"org" +
|
||||||
"textsecure.pushB\021PushMessageProtos"
|
".whispersystems.textsecure.pushB\021PushMes",
|
||||||
|
"sageProtos"
|
||||||
};
|
};
|
||||||
com.google.protobuf.Descriptors.FileDescriptor.InternalDescriptorAssigner assigner =
|
com.google.protobuf.Descriptors.FileDescriptor.InternalDescriptorAssigner assigner =
|
||||||
new com.google.protobuf.Descriptors.FileDescriptor.InternalDescriptorAssigner() {
|
new com.google.protobuf.Descriptors.FileDescriptor.InternalDescriptorAssigner() {
|
||||||
@ -1853,7 +1948,7 @@ public final class PushMessageProtos {
|
|||||||
internal_static_textsecure_IncomingPushMessageSignal_fieldAccessorTable = new
|
internal_static_textsecure_IncomingPushMessageSignal_fieldAccessorTable = new
|
||||||
com.google.protobuf.GeneratedMessage.FieldAccessorTable(
|
com.google.protobuf.GeneratedMessage.FieldAccessorTable(
|
||||||
internal_static_textsecure_IncomingPushMessageSignal_descriptor,
|
internal_static_textsecure_IncomingPushMessageSignal_descriptor,
|
||||||
new java.lang.String[] { "Type", "Source", "Destinations", "Timestamp", "Message", },
|
new java.lang.String[] { "Type", "Source", "Relay", "Destinations", "Timestamp", "Message", },
|
||||||
org.whispersystems.textsecure.push.PushMessageProtos.IncomingPushMessageSignal.class,
|
org.whispersystems.textsecure.push.PushMessageProtos.IncomingPushMessageSignal.class,
|
||||||
org.whispersystems.textsecure.push.PushMessageProtos.IncomingPushMessageSignal.Builder.class);
|
org.whispersystems.textsecure.push.PushMessageProtos.IncomingPushMessageSignal.Builder.class);
|
||||||
internal_static_textsecure_PushMessageContent_descriptor =
|
internal_static_textsecure_PushMessageContent_descriptor =
|
||||||
|
@ -5,6 +5,7 @@ import android.util.Log;
|
|||||||
import android.util.Pair;
|
import android.util.Pair;
|
||||||
|
|
||||||
import com.google.thoughtcrimegson.Gson;
|
import com.google.thoughtcrimegson.Gson;
|
||||||
|
|
||||||
import org.whispersystems.textsecure.R;
|
import org.whispersystems.textsecure.R;
|
||||||
import org.whispersystems.textsecure.Release;
|
import org.whispersystems.textsecure.Release;
|
||||||
import org.whispersystems.textsecure.crypto.IdentityKey;
|
import org.whispersystems.textsecure.crypto.IdentityKey;
|
||||||
@ -12,9 +13,6 @@ import org.whispersystems.textsecure.storage.PreKeyRecord;
|
|||||||
import org.whispersystems.textsecure.util.Base64;
|
import org.whispersystems.textsecure.util.Base64;
|
||||||
import org.whispersystems.textsecure.util.Util;
|
import org.whispersystems.textsecure.util.Util;
|
||||||
|
|
||||||
import javax.net.ssl.HttpsURLConnection;
|
|
||||||
import javax.net.ssl.SSLContext;
|
|
||||||
import javax.net.ssl.TrustManagerFactory;
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.io.FileOutputStream;
|
import java.io.FileOutputStream;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
@ -34,6 +32,10 @@ import java.util.LinkedList;
|
|||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
|
||||||
|
import javax.net.ssl.HttpsURLConnection;
|
||||||
|
import javax.net.ssl.SSLContext;
|
||||||
|
import javax.net.ssl.TrustManagerFactory;
|
||||||
|
|
||||||
public class PushServiceSocket {
|
public class PushServiceSocket {
|
||||||
|
|
||||||
private static final String CREATE_ACCOUNT_SMS_PATH = "/v1/accounts/sms/code/%s";
|
private static final String CREATE_ACCOUNT_SMS_PATH = "/v1/accounts/sms/code/%s";
|
||||||
@ -78,28 +80,31 @@ public class PushServiceSocket {
|
|||||||
makeRequest(REGISTER_GCM_PATH, "DELETE", null);
|
makeRequest(REGISTER_GCM_PATH, "DELETE", null);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void sendMessage(String recipient, byte[] body, int type)
|
public void sendMessage(String relay, String recipient, byte[] body, int type)
|
||||||
throws IOException
|
throws IOException
|
||||||
{
|
{
|
||||||
OutgoingPushMessage message = new OutgoingPushMessage(recipient, body, type);
|
OutgoingPushMessage message = new OutgoingPushMessage(relay, recipient, body, type);
|
||||||
sendMessage(new OutgoingPushMessageList(message));
|
sendMessage(new OutgoingPushMessageList(message));
|
||||||
}
|
}
|
||||||
|
|
||||||
public void sendMessage(List<String> recipients, List<byte[]> bodies, List<Integer> types)
|
public void sendMessage(List<String> relays, List<String> recipients,
|
||||||
|
List<byte[]> bodies, List<Integer> types)
|
||||||
throws IOException
|
throws IOException
|
||||||
{
|
{
|
||||||
List<OutgoingPushMessage> messages = new LinkedList<OutgoingPushMessage>();
|
List<OutgoingPushMessage> messages = new LinkedList<OutgoingPushMessage>();
|
||||||
|
|
||||||
|
Iterator<String> relaysIterator = relays.iterator();
|
||||||
Iterator<String> recipientsIterator = recipients.iterator();
|
Iterator<String> recipientsIterator = recipients.iterator();
|
||||||
Iterator<byte[]> bodiesIterator = bodies.iterator();
|
Iterator<byte[]> bodiesIterator = bodies.iterator();
|
||||||
Iterator<Integer> typesIterator = types.iterator();
|
Iterator<Integer> typesIterator = types.iterator();
|
||||||
|
|
||||||
while (recipientsIterator.hasNext()) {
|
while (recipientsIterator.hasNext()) {
|
||||||
|
String relay = relaysIterator.next();
|
||||||
String recipient = recipientsIterator.next();
|
String recipient = recipientsIterator.next();
|
||||||
byte[] body = bodiesIterator.next();
|
byte[] body = bodiesIterator.next();
|
||||||
int type = typesIterator.next();
|
int type = typesIterator.next();
|
||||||
|
|
||||||
messages.add(new OutgoingPushMessage(recipient, body, type));
|
messages.add(new OutgoingPushMessage(relay, recipient, body, type));
|
||||||
}
|
}
|
||||||
|
|
||||||
sendMessage(new OutgoingPushMessageList(messages));
|
sendMessage(new OutgoingPushMessageList(messages));
|
||||||
@ -134,8 +139,14 @@ public class PushServiceSocket {
|
|||||||
makeRequest(String.format(PREKEY_PATH, ""), "PUT", PreKeyList.toJson(new PreKeyList(lastResortEntity, entities)));
|
makeRequest(String.format(PREKEY_PATH, ""), "PUT", PreKeyList.toJson(new PreKeyList(lastResortEntity, entities)));
|
||||||
}
|
}
|
||||||
|
|
||||||
public PreKeyEntity getPreKey(String number) throws IOException {
|
public PreKeyEntity getPreKey(String number, String relay) throws IOException {
|
||||||
String responseText = makeRequest(String.format(PREKEY_PATH, number), "GET", null);
|
String path = String.format(PREKEY_PATH, number);
|
||||||
|
|
||||||
|
if (relay != null) {
|
||||||
|
path = path + "?relay=" + relay;
|
||||||
|
}
|
||||||
|
|
||||||
|
String responseText = makeRequest(path, "GET", null);
|
||||||
Log.w("PushServiceSocket", "Got prekey: " + responseText);
|
Log.w("PushServiceSocket", "Got prekey: " + responseText);
|
||||||
return PreKeyEntity.fromJson(responseText);
|
return PreKeyEntity.fromJson(responseText);
|
||||||
}
|
}
|
||||||
@ -170,11 +181,11 @@ public class PushServiceSocket {
|
|||||||
return attachment;
|
return attachment;
|
||||||
}
|
}
|
||||||
|
|
||||||
public List<String> retrieveDirectory(Set<String> contactTokens) {
|
public List<ContactTokenDetails> retrieveDirectory(Set<String> contactTokens) {
|
||||||
try {
|
try {
|
||||||
ContactTokenList contactTokenList = new ContactTokenList(new LinkedList(contactTokens));
|
ContactTokenList contactTokenList = new ContactTokenList(new LinkedList(contactTokens));
|
||||||
String response = makeRequest(DIRECTORY_TOKENS_PATH, "PUT", new Gson().toJson(contactTokenList));
|
String response = makeRequest(DIRECTORY_TOKENS_PATH, "PUT", new Gson().toJson(contactTokenList));
|
||||||
ContactTokenList activeTokens = new Gson().fromJson(response, ContactTokenList.class);
|
ContactTokenDetailsList activeTokens = new Gson().fromJson(response, ContactTokenDetailsList.class);
|
||||||
|
|
||||||
return activeTokens.getContacts();
|
return activeTokens.getContacts();
|
||||||
} catch (IOException ioe) {
|
} catch (IOException ioe) {
|
||||||
@ -183,12 +194,12 @@ public class PushServiceSocket {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean isRegisteredUser(String contactToken) throws IOException {
|
public ContactTokenDetails getContactTokenDetails(String contactToken) throws IOException {
|
||||||
try {
|
try {
|
||||||
makeRequest(String.format(DIRECTORY_VERIFY_PATH, contactToken), "GET", null);
|
String response = makeRequest(String.format(DIRECTORY_VERIFY_PATH, contactToken), "GET", null);
|
||||||
return true;
|
return new Gson().fromJson(response, ContactTokenDetails.class);
|
||||||
} catch (NotFoundException nfe) {
|
} catch (NotFoundException nfe) {
|
||||||
return false;
|
return null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -311,6 +322,9 @@ public class PushServiceSocket {
|
|||||||
context.init(null, trustManagerFactory.getTrustManagers(), null);
|
context.init(null, trustManagerFactory.getTrustManagers(), null);
|
||||||
|
|
||||||
URL url = new URL(String.format("%s%s", Release.PUSH_SERVICE_URL, urlFragment));
|
URL url = new URL(String.format("%s%s", Release.PUSH_SERVICE_URL, urlFragment));
|
||||||
|
Log.w("PushServiceSocket", "Push service URL: " + Release.PUSH_SERVICE_URL);
|
||||||
|
Log.w("PushServiceSocket", "Opening URL: " + url);
|
||||||
|
|
||||||
HttpURLConnection connection = (HttpURLConnection)url.openConnection();
|
HttpURLConnection connection = (HttpURLConnection)url.openConnection();
|
||||||
|
|
||||||
if (Release.ENFORCE_SSL) {
|
if (Release.ENFORCE_SSL) {
|
||||||
|
@ -10,6 +10,8 @@ import org.thoughtcrime.securesms.service.SendReceiveService;
|
|||||||
import org.thoughtcrime.securesms.util.TextSecurePreferences;
|
import org.thoughtcrime.securesms.util.TextSecurePreferences;
|
||||||
import org.whispersystems.textsecure.crypto.InvalidVersionException;
|
import org.whispersystems.textsecure.crypto.InvalidVersionException;
|
||||||
import org.whispersystems.textsecure.directory.Directory;
|
import org.whispersystems.textsecure.directory.Directory;
|
||||||
|
import org.whispersystems.textsecure.directory.NotInDirectoryException;
|
||||||
|
import org.whispersystems.textsecure.push.ContactTokenDetails;
|
||||||
import org.whispersystems.textsecure.push.IncomingEncryptedPushMessage;
|
import org.whispersystems.textsecure.push.IncomingEncryptedPushMessage;
|
||||||
import org.whispersystems.textsecure.push.IncomingPushMessage;
|
import org.whispersystems.textsecure.push.IncomingPushMessage;
|
||||||
import org.whispersystems.textsecure.push.PushServiceSocket;
|
import org.whispersystems.textsecure.push.PushServiceSocket;
|
||||||
@ -59,13 +61,16 @@ public class GcmIntentService extends GCMBaseIntentService {
|
|||||||
IncomingEncryptedPushMessage encryptedMessage = new IncomingEncryptedPushMessage(data, sessionKey);
|
IncomingEncryptedPushMessage encryptedMessage = new IncomingEncryptedPushMessage(data, sessionKey);
|
||||||
IncomingPushMessage message = encryptedMessage.getIncomingPushMessage();
|
IncomingPushMessage message = encryptedMessage.getIncomingPushMessage();
|
||||||
|
|
||||||
|
if (!isActiveNumber(context, message.getSource())) {
|
||||||
|
Directory directory = Directory.getInstance(context);
|
||||||
|
String contactToken = directory.getToken(message.getSource());
|
||||||
|
ContactTokenDetails contactTokenDetails = new ContactTokenDetails(contactToken, message.getRelay());
|
||||||
|
directory.setToken(contactTokenDetails, true);
|
||||||
|
}
|
||||||
|
|
||||||
Intent service = new Intent(context, SendReceiveService.class);
|
Intent service = new Intent(context, SendReceiveService.class);
|
||||||
service.setAction(SendReceiveService.RECEIVE_PUSH_ACTION);
|
service.setAction(SendReceiveService.RECEIVE_PUSH_ACTION);
|
||||||
service.putExtra("message", message);
|
service.putExtra("message", message);
|
||||||
|
|
||||||
Directory directory = Directory.getInstance(context);
|
|
||||||
directory.setToken(directory.getToken(message.getSource()), true);
|
|
||||||
|
|
||||||
context.startService(service);
|
context.startService(service);
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
Log.w("GcmIntentService", e);
|
Log.w("GcmIntentService", e);
|
||||||
@ -84,4 +89,16 @@ public class GcmIntentService extends GCMBaseIntentService {
|
|||||||
String password = TextSecurePreferences.getPushServerPassword(context);
|
String password = TextSecurePreferences.getPushServerPassword(context);
|
||||||
return new PushServiceSocket(context, localNumber, password);
|
return new PushServiceSocket(context, localNumber, password);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private boolean isActiveNumber(Context context, String e164number) {
|
||||||
|
boolean isActiveNumber;
|
||||||
|
|
||||||
|
try {
|
||||||
|
isActiveNumber = Directory.getInstance(context).isActiveNumber(e164number);
|
||||||
|
} catch (NotInDirectoryException e) {
|
||||||
|
isActiveNumber = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return isActiveNumber;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -10,6 +10,7 @@ import android.util.Log;
|
|||||||
|
|
||||||
import org.thoughtcrime.securesms.util.TextSecurePreferences;
|
import org.thoughtcrime.securesms.util.TextSecurePreferences;
|
||||||
import org.whispersystems.textsecure.directory.Directory;
|
import org.whispersystems.textsecure.directory.Directory;
|
||||||
|
import org.whispersystems.textsecure.push.ContactTokenDetails;
|
||||||
import org.whispersystems.textsecure.push.PushServiceSocket;
|
import org.whispersystems.textsecure.push.PushServiceSocket;
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
@ -61,11 +62,14 @@ public class DirectoryRefreshService extends Service {
|
|||||||
String password = TextSecurePreferences.getPushServerPassword(context);
|
String password = TextSecurePreferences.getPushServerPassword(context);
|
||||||
PushServiceSocket socket = new PushServiceSocket(context, localNumber, password);
|
PushServiceSocket socket = new PushServiceSocket(context, localNumber, password);
|
||||||
|
|
||||||
Set<String> eligibleContactTokens = directory.getPushEligibleContactTokens(localNumber);
|
Set<String> eligibleContactTokens = directory.getPushEligibleContactTokens(localNumber);
|
||||||
List<String> activeTokens = socket.retrieveDirectory(eligibleContactTokens);
|
List<ContactTokenDetails> activeTokens = socket.retrieveDirectory(eligibleContactTokens);
|
||||||
|
|
||||||
if (activeTokens != null) {
|
if (activeTokens != null) {
|
||||||
eligibleContactTokens.removeAll(activeTokens);
|
for (ContactTokenDetails activeToken : activeTokens) {
|
||||||
|
eligibleContactTokens.remove(activeToken.getToken());
|
||||||
|
}
|
||||||
|
|
||||||
directory.setTokens(activeTokens, eligibleContactTokens);
|
directory.setTokens(activeTokens, eligibleContactTokens);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -20,6 +20,7 @@ import org.whispersystems.textsecure.crypto.IdentityKey;
|
|||||||
import org.whispersystems.textsecure.crypto.MasterSecret;
|
import org.whispersystems.textsecure.crypto.MasterSecret;
|
||||||
import org.whispersystems.textsecure.crypto.PreKeyUtil;
|
import org.whispersystems.textsecure.crypto.PreKeyUtil;
|
||||||
import org.whispersystems.textsecure.directory.Directory;
|
import org.whispersystems.textsecure.directory.Directory;
|
||||||
|
import org.whispersystems.textsecure.push.ContactTokenDetails;
|
||||||
import org.whispersystems.textsecure.push.PushServiceSocket;
|
import org.whispersystems.textsecure.push.PushServiceSocket;
|
||||||
import org.whispersystems.textsecure.storage.PreKeyRecord;
|
import org.whispersystems.textsecure.storage.PreKeyRecord;
|
||||||
import org.whispersystems.textsecure.util.Util;
|
import org.whispersystems.textsecure.util.Util;
|
||||||
@ -282,11 +283,13 @@ public class RegistrationService extends Service {
|
|||||||
String gcmRegistrationId = waitForGcmRegistrationId();
|
String gcmRegistrationId = waitForGcmRegistrationId();
|
||||||
socket.registerGcmId(gcmRegistrationId);
|
socket.registerGcmId(gcmRegistrationId);
|
||||||
|
|
||||||
Set<String> contactTokens = Directory.getInstance(this).getPushEligibleContactTokens(number);
|
Set<String> contactTokens = Directory.getInstance(this).getPushEligibleContactTokens(number);
|
||||||
List<String> activeTokens = socket.retrieveDirectory(contactTokens);
|
List<ContactTokenDetails> activeTokens = socket.retrieveDirectory(contactTokens);
|
||||||
|
|
||||||
if (activeTokens != null) {
|
if (activeTokens != null) {
|
||||||
contactTokens.removeAll(activeTokens);
|
for (ContactTokenDetails activeToken : activeTokens) {
|
||||||
|
contactTokens.remove(activeToken.getToken());
|
||||||
|
}
|
||||||
Directory.getInstance(this).setTokens(activeTokens, contactTokens);
|
Directory.getInstance(this).setTokens(activeTokens, contactTokens);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -22,6 +22,7 @@ import org.whispersystems.textsecure.crypto.KeyUtil;
|
|||||||
import org.whispersystems.textsecure.crypto.MasterSecret;
|
import org.whispersystems.textsecure.crypto.MasterSecret;
|
||||||
import org.whispersystems.textsecure.crypto.MessageCipher;
|
import org.whispersystems.textsecure.crypto.MessageCipher;
|
||||||
import org.whispersystems.textsecure.crypto.protocol.PreKeyBundleMessage;
|
import org.whispersystems.textsecure.crypto.protocol.PreKeyBundleMessage;
|
||||||
|
import org.whispersystems.textsecure.directory.Directory;
|
||||||
import org.whispersystems.textsecure.push.OutgoingPushMessage;
|
import org.whispersystems.textsecure.push.OutgoingPushMessage;
|
||||||
import org.whispersystems.textsecure.push.PreKeyEntity;
|
import org.whispersystems.textsecure.push.PreKeyEntity;
|
||||||
import org.whispersystems.textsecure.push.PushAttachmentData;
|
import org.whispersystems.textsecure.push.PushAttachmentData;
|
||||||
@ -61,12 +62,12 @@ public class PushTransport extends BaseTransport {
|
|||||||
String plaintextBody = message.getBody().getBody();
|
String plaintextBody = message.getBody().getBody();
|
||||||
PushMessageContent.Builder builder = PushMessageContent.newBuilder();
|
PushMessageContent.Builder builder = PushMessageContent.newBuilder();
|
||||||
byte[] plaintext = builder.setBody(plaintextBody).build().toByteArray();
|
byte[] plaintext = builder.setBody(plaintextBody).build().toByteArray();
|
||||||
String recipientCanonicalNumber = PhoneNumberFormatter.formatNumber(recipient.getNumber(),
|
String recipientCanonicalNumber = PhoneNumberFormatter.formatNumber(recipient.getNumber(), localNumber);
|
||||||
localNumber);
|
String relay = Directory.getInstance(context).getRelay(recipientCanonicalNumber);
|
||||||
|
|
||||||
Pair<Integer, byte[]> typeAndCiphertext = getEncryptedMessage(socket, recipient, recipientCanonicalNumber, plaintext);
|
Pair<Integer, byte[]> typeAndCiphertext = getEncryptedMessage(socket, recipient, recipientCanonicalNumber, plaintext);
|
||||||
|
|
||||||
socket.sendMessage(recipientCanonicalNumber, typeAndCiphertext.second, typeAndCiphertext.first);
|
socket.sendMessage(relay, recipientCanonicalNumber, typeAndCiphertext.second, typeAndCiphertext.first);
|
||||||
|
|
||||||
context.sendBroadcast(constructSentIntent(context, message.getId(), message.getType()));
|
context.sendBroadcast(constructSentIntent(context, message.getId(), message.getType()));
|
||||||
} catch (RateLimitException e) {
|
} catch (RateLimitException e) {
|
||||||
@ -81,7 +82,8 @@ public class PushTransport extends BaseTransport {
|
|||||||
String password = TextSecurePreferences.getPushServerPassword(context);
|
String password = TextSecurePreferences.getPushServerPassword(context);
|
||||||
PushServiceSocket socket = new PushServiceSocket(context, localNumber, password);
|
PushServiceSocket socket = new PushServiceSocket(context, localNumber, password);
|
||||||
String messageBody = PartParser.getMessageText(message.getBody());
|
String messageBody = PartParser.getMessageText(message.getBody());
|
||||||
List<byte[]> ciphertext = new LinkedList<byte[]> ();
|
List<String> relays = new LinkedList<String>();
|
||||||
|
List<byte[]> ciphertext = new LinkedList<byte[]>();
|
||||||
List<Integer> types = new LinkedList<Integer>();
|
List<Integer> types = new LinkedList<Integer>();
|
||||||
|
|
||||||
for (String destination : destinations) {
|
for (String destination : destinations) {
|
||||||
@ -108,11 +110,12 @@ public class PushTransport extends BaseTransport {
|
|||||||
Pair<Integer, byte[]> typeAndCiphertext = getEncryptedMessage(socket, recipients.getPrimaryRecipient(),
|
Pair<Integer, byte[]> typeAndCiphertext = getEncryptedMessage(socket, recipients.getPrimaryRecipient(),
|
||||||
destination, plaintext);
|
destination, plaintext);
|
||||||
|
|
||||||
|
relays.add(Directory.getInstance(context).getRelay(destination));
|
||||||
types.add(typeAndCiphertext.first);
|
types.add(typeAndCiphertext.first);
|
||||||
ciphertext.add(typeAndCiphertext.second);
|
ciphertext.add(typeAndCiphertext.second);
|
||||||
}
|
}
|
||||||
|
|
||||||
socket.sendMessage(destinations, ciphertext, types);
|
socket.sendMessage(relays, destinations, ciphertext, types);
|
||||||
|
|
||||||
} catch (RateLimitException e) {
|
} catch (RateLimitException e) {
|
||||||
Log.w("PushTransport", e);
|
Log.w("PushTransport", e);
|
||||||
@ -187,7 +190,8 @@ public class PushTransport extends BaseTransport {
|
|||||||
{
|
{
|
||||||
IdentityKeyPair identityKeyPair = IdentityKeyUtil.getIdentityKeyPair(context, masterSecret);
|
IdentityKeyPair identityKeyPair = IdentityKeyUtil.getIdentityKeyPair(context, masterSecret);
|
||||||
IdentityKey identityKey = identityKeyPair.getPublicKey();
|
IdentityKey identityKey = identityKeyPair.getPublicKey();
|
||||||
PreKeyEntity preKey = socket.getPreKey(canonicalRecipientNumber);
|
String relay = Directory.getInstance(context).getRelay(canonicalRecipientNumber);
|
||||||
|
PreKeyEntity preKey = socket.getPreKey(canonicalRecipientNumber, relay);
|
||||||
KeyExchangeProcessor processor = new KeyExchangeProcessor(context, masterSecret, recipient);
|
KeyExchangeProcessor processor = new KeyExchangeProcessor(context, masterSecret, recipient);
|
||||||
|
|
||||||
processor.processKeyExchangeMessage(preKey);
|
processor.processKeyExchangeMessage(preKey);
|
||||||
|
@ -27,6 +27,7 @@ import org.thoughtcrime.securesms.util.Util;
|
|||||||
import org.whispersystems.textsecure.crypto.MasterSecret;
|
import org.whispersystems.textsecure.crypto.MasterSecret;
|
||||||
import org.whispersystems.textsecure.directory.Directory;
|
import org.whispersystems.textsecure.directory.Directory;
|
||||||
import org.whispersystems.textsecure.directory.NotInDirectoryException;
|
import org.whispersystems.textsecure.directory.NotInDirectoryException;
|
||||||
|
import org.whispersystems.textsecure.push.ContactTokenDetails;
|
||||||
import org.whispersystems.textsecure.push.PushServiceSocket;
|
import org.whispersystems.textsecure.push.PushServiceSocket;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
@ -126,15 +127,20 @@ public class UniversalTransport {
|
|||||||
return directory.isActiveNumber(destination);
|
return directory.isActiveNumber(destination);
|
||||||
} catch (NotInDirectoryException e) {
|
} catch (NotInDirectoryException e) {
|
||||||
try {
|
try {
|
||||||
String localNumber = TextSecurePreferences.getLocalNumber(context);
|
String localNumber = TextSecurePreferences.getLocalNumber(context);
|
||||||
String pushPassword = TextSecurePreferences.getPushServerPassword(context);
|
String pushPassword = TextSecurePreferences.getPushServerPassword(context);
|
||||||
String contactToken = directory.getToken(destination);
|
String contactToken = directory.getToken(destination);
|
||||||
PushServiceSocket socket = new PushServiceSocket(context, localNumber, pushPassword);
|
PushServiceSocket socket = new PushServiceSocket(context, localNumber, pushPassword);
|
||||||
boolean registeredUser = socket.isRegisteredUser(contactToken);
|
ContactTokenDetails registeredUser = socket.getContactTokenDetails(contactToken);
|
||||||
|
|
||||||
directory.setToken(contactToken, registeredUser);
|
if (registeredUser == null) {
|
||||||
|
registeredUser = new ContactTokenDetails(contactToken);
|
||||||
return registeredUser;
|
directory.setToken(registeredUser, false);
|
||||||
|
return false;
|
||||||
|
} else {
|
||||||
|
directory.setToken(registeredUser, true);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
} catch (IOException e1) {
|
} catch (IOException e1) {
|
||||||
Log.w("UniversalTransport", e1);
|
Log.w("UniversalTransport", e1);
|
||||||
return false;
|
return false;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user