Bundle e164 and relay into PushDestination
This commit is contained in:
parent
ca3c82f581
commit
246cd10454
4 changed files with 92 additions and 51 deletions
|
@ -0,0 +1,35 @@
|
||||||
|
package org.whispersystems.textsecure.push;
|
||||||
|
|
||||||
|
import android.content.Context;
|
||||||
|
|
||||||
|
import org.whispersystems.textsecure.directory.Directory;
|
||||||
|
import org.whispersystems.textsecure.util.PhoneNumberFormatter;
|
||||||
|
|
||||||
|
public class PushDestination {
|
||||||
|
|
||||||
|
private final String e164number;
|
||||||
|
private final String relay;
|
||||||
|
|
||||||
|
private PushDestination(String e164number, String relay) {
|
||||||
|
this.e164number = e164number;
|
||||||
|
this.relay = relay;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getNumber() {
|
||||||
|
return e164number;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getRelay() {
|
||||||
|
return relay;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static PushDestination getInstance(Context context,
|
||||||
|
PushServiceSocket.PushCredentials credentials,
|
||||||
|
String destinationNumber)
|
||||||
|
{
|
||||||
|
String e164destination = PhoneNumberFormatter.formatNumber(destinationNumber, credentials.getLocalNumber(context));
|
||||||
|
String relay = Directory.getInstance(context).getRelay(e164destination);
|
||||||
|
|
||||||
|
return new PushDestination(e164destination, relay);
|
||||||
|
}
|
||||||
|
}
|
|
@ -84,31 +84,32 @@ public class PushServiceSocket {
|
||||||
makeRequest(REGISTER_GCM_PATH, "DELETE", null);
|
makeRequest(REGISTER_GCM_PATH, "DELETE", null);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void sendMessage(String relay, String recipient, byte[] body, int type)
|
public void sendMessage(PushDestination recipient, byte[] body, int type)
|
||||||
throws IOException
|
throws IOException
|
||||||
{
|
{
|
||||||
OutgoingPushMessage message = new OutgoingPushMessage(relay, recipient, body, type);
|
OutgoingPushMessage message = new OutgoingPushMessage(recipient.getRelay(),
|
||||||
|
recipient.getNumber(),
|
||||||
|
body, type);
|
||||||
|
|
||||||
sendMessage(new OutgoingPushMessageList(message));
|
sendMessage(new OutgoingPushMessageList(message));
|
||||||
}
|
}
|
||||||
|
|
||||||
public void sendMessage(List<String> relays, List<String> recipients,
|
public void sendMessage(List<PushDestination> recipients,
|
||||||
List<byte[]> bodies, List<Integer> types)
|
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<PushDestination> 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();
|
PushDestination 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(relay, recipient, body, type));
|
messages.add(new OutgoingPushMessage(recipient.getRelay(), recipient.getNumber(), body, type));
|
||||||
}
|
}
|
||||||
|
|
||||||
sendMessage(new OutgoingPushMessageList(messages));
|
sendMessage(new OutgoingPushMessageList(messages));
|
||||||
|
@ -143,11 +144,11 @@ 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 relay, String number) throws IOException {
|
public PreKeyEntity getPreKey(PushDestination destination) throws IOException {
|
||||||
String path = String.format(PREKEY_PATH, number);
|
String path = String.format(PREKEY_PATH, destination.getNumber());
|
||||||
|
|
||||||
if (relay != null) {
|
if (destination.getRelay() != null) {
|
||||||
path = path + "?relay=" + relay;
|
path = path + "?relay=" + destination.getRelay();
|
||||||
}
|
}
|
||||||
|
|
||||||
String responseText = makeRequest(path, "GET", null);
|
String responseText = makeRequest(path, "GET", null);
|
||||||
|
|
|
@ -28,6 +28,7 @@ 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;
|
||||||
import org.whispersystems.textsecure.push.PushAttachmentPointer;
|
import org.whispersystems.textsecure.push.PushAttachmentPointer;
|
||||||
|
import org.whispersystems.textsecure.push.PushDestination;
|
||||||
import org.whispersystems.textsecure.push.PushMessageProtos.PushMessageContent;
|
import org.whispersystems.textsecure.push.PushMessageProtos.PushMessageContent;
|
||||||
import org.whispersystems.textsecure.push.PushServiceSocket;
|
import org.whispersystems.textsecure.push.PushServiceSocket;
|
||||||
import org.whispersystems.textsecure.push.PushTransportDetails;
|
import org.whispersystems.textsecure.push.PushTransportDetails;
|
||||||
|
@ -55,19 +56,20 @@ public class PushTransport extends BaseTransport {
|
||||||
|
|
||||||
public void deliver(SmsMessageRecord message) throws IOException {
|
public void deliver(SmsMessageRecord message) throws IOException {
|
||||||
try {
|
try {
|
||||||
PushServiceSocket socket = new PushServiceSocket(context, TextSecurePushCredentials.getInstance());
|
TextSecurePushCredentials credentials = TextSecurePushCredentials.getInstance();
|
||||||
|
|
||||||
String localNumber = TextSecurePreferences.getLocalNumber(context);
|
|
||||||
Recipient recipient = message.getIndividualRecipient();
|
Recipient recipient = message.getIndividualRecipient();
|
||||||
|
PushServiceSocket socket = new PushServiceSocket(context, credentials);
|
||||||
|
PushDestination destination = PushDestination.getInstance(context, credentials,
|
||||||
|
recipient.getNumber());
|
||||||
|
|
||||||
String plaintextBody = message.getBody().getBody();
|
String plaintextBody = message.getBody().getBody();
|
||||||
PushMessageContent.Builder builder = PushMessageContent.newBuilder();
|
byte[] plaintext = PushMessageContent.newBuilder()
|
||||||
byte[] plaintext = builder.setBody(plaintextBody).build().toByteArray();
|
.setBody(plaintextBody)
|
||||||
String recipientCanonicalNumber = PhoneNumberFormatter.formatNumber(recipient.getNumber(), localNumber);
|
.build().toByteArray();
|
||||||
String relay = Directory.getInstance(context).getRelay(recipientCanonicalNumber);
|
|
||||||
|
|
||||||
Pair<Integer, byte[]> typeAndCiphertext = getEncryptedMessage(socket, recipient, recipientCanonicalNumber, plaintext);
|
Pair<Integer, byte[]> typeAndCiphertext = getEncryptedMessage(socket, recipient, destination, plaintext);
|
||||||
|
|
||||||
socket.sendMessage(relay, recipientCanonicalNumber, typeAndCiphertext.second, typeAndCiphertext.first);
|
socket.sendMessage(destination, 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) {
|
||||||
|
@ -76,16 +78,17 @@ public class PushTransport extends BaseTransport {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void deliver(SendReq message, List<String> destinations) throws IOException {
|
public void deliver(SendReq message, List<PushDestination> destinations) throws IOException {
|
||||||
try {
|
try {
|
||||||
PushServiceSocket socket = new PushServiceSocket(context, TextSecurePushCredentials.getInstance());
|
TextSecurePushCredentials credentials = TextSecurePushCredentials.getInstance();
|
||||||
|
PushServiceSocket socket = new PushServiceSocket(context, credentials);
|
||||||
String messageBody = PartParser.getMessageText(message.getBody());
|
String messageBody = PartParser.getMessageText(message.getBody());
|
||||||
List<String> relays = new LinkedList<String>();
|
|
||||||
List<byte[]> ciphertext = new LinkedList<byte[]>();
|
List<byte[]> ciphertext = new LinkedList<byte[]>();
|
||||||
List<Integer> types = new LinkedList<Integer>();
|
List<Integer> types = new LinkedList<Integer>();
|
||||||
|
|
||||||
for (String destination : destinations) {
|
for (PushDestination destination : destinations) {
|
||||||
Recipients recipients = RecipientFactory.getRecipientsFromString(context, destination, false);
|
Recipients recipients = RecipientFactory.getRecipientsFromString(context, destination.getNumber(), false);
|
||||||
List<PushAttachmentPointer> attachments = getPushAttachmentPointers(socket, message.getBody());
|
List<PushAttachmentPointer> attachments = getPushAttachmentPointers(socket, message.getBody());
|
||||||
PushMessageContent.Builder builder = PushMessageContent.newBuilder();
|
PushMessageContent.Builder builder = PushMessageContent.newBuilder();
|
||||||
|
|
||||||
|
@ -108,12 +111,11 @@ 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(relays, destinations, ciphertext, types);
|
socket.sendMessage(destinations, ciphertext, types);
|
||||||
|
|
||||||
} catch (RateLimitException e) {
|
} catch (RateLimitException e) {
|
||||||
Log.w("PushTransport", e);
|
Log.w("PushTransport", e);
|
||||||
|
@ -148,8 +150,10 @@ public class PushTransport extends BaseTransport {
|
||||||
return attachments;
|
return attachments;
|
||||||
}
|
}
|
||||||
|
|
||||||
private Pair<Integer, byte[]> getEncryptedMessage(PushServiceSocket socket, Recipient recipient,
|
private Pair<Integer, byte[]> getEncryptedMessage(PushServiceSocket socket,
|
||||||
String canonicalRecipientNumber, byte[] plaintext)
|
Recipient recipient,
|
||||||
|
PushDestination pushDestination,
|
||||||
|
byte[] plaintext)
|
||||||
throws IOException
|
throws IOException
|
||||||
{
|
{
|
||||||
if (KeyUtil.isNonPrekeySessionFor(context, masterSecret, recipient)) {
|
if (KeyUtil.isNonPrekeySessionFor(context, masterSecret, recipient)) {
|
||||||
|
@ -162,7 +166,7 @@ public class PushTransport extends BaseTransport {
|
||||||
return new Pair<Integer, byte[]>(OutgoingPushMessage.TYPE_MESSAGE_PREKEY_BUNDLE, ciphertext);
|
return new Pair<Integer, byte[]>(OutgoingPushMessage.TYPE_MESSAGE_PREKEY_BUNDLE, ciphertext);
|
||||||
} else {
|
} else {
|
||||||
Log.w("PushTransport", "Sending prekeybundle ciphertext message for new session...");
|
Log.w("PushTransport", "Sending prekeybundle ciphertext message for new session...");
|
||||||
byte[] ciphertext = getEncryptedPrekeyBundleMessageForNewSession(socket, recipient, canonicalRecipientNumber, plaintext);
|
byte[] ciphertext = getEncryptedPrekeyBundleMessageForNewSession(socket, recipient, pushDestination, plaintext);
|
||||||
return new Pair<Integer, byte[]>(OutgoingPushMessage.TYPE_MESSAGE_PREKEY_BUNDLE, ciphertext);
|
return new Pair<Integer, byte[]>(OutgoingPushMessage.TYPE_MESSAGE_PREKEY_BUNDLE, ciphertext);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -182,14 +186,13 @@ public class PushTransport extends BaseTransport {
|
||||||
|
|
||||||
private byte[] getEncryptedPrekeyBundleMessageForNewSession(PushServiceSocket socket,
|
private byte[] getEncryptedPrekeyBundleMessageForNewSession(PushServiceSocket socket,
|
||||||
Recipient recipient,
|
Recipient recipient,
|
||||||
String canonicalRecipientNumber,
|
PushDestination pushDestination,
|
||||||
byte[] plaintext)
|
byte[] plaintext)
|
||||||
throws IOException
|
throws IOException
|
||||||
{
|
{
|
||||||
IdentityKeyPair identityKeyPair = IdentityKeyUtil.getIdentityKeyPair(context, masterSecret);
|
IdentityKeyPair identityKeyPair = IdentityKeyUtil.getIdentityKeyPair(context, masterSecret);
|
||||||
IdentityKey identityKey = identityKeyPair.getPublicKey();
|
IdentityKey identityKey = identityKeyPair.getPublicKey();
|
||||||
String relay = Directory.getInstance(context).getRelay(canonicalRecipientNumber);
|
PreKeyEntity preKey = socket.getPreKey(pushDestination);
|
||||||
PreKeyEntity preKey = socket.getPreKey(relay, canonicalRecipientNumber);
|
|
||||||
KeyExchangeProcessor processor = new KeyExchangeProcessor(context, masterSecret, recipient);
|
KeyExchangeProcessor processor = new KeyExchangeProcessor(context, masterSecret, recipient);
|
||||||
|
|
||||||
processor.processKeyExchangeMessage(preKey);
|
processor.processKeyExchangeMessage(preKey);
|
||||||
|
|
|
@ -29,6 +29,7 @@ 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.ContactTokenDetails;
|
||||||
|
import org.whispersystems.textsecure.push.PushDestination;
|
||||||
import org.whispersystems.textsecure.push.PushServiceSocket;
|
import org.whispersystems.textsecure.push.PushServiceSocket;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
@ -80,7 +81,7 @@ public class UniversalTransport {
|
||||||
return mmsTransport.deliver(mediaMessage);
|
return mmsTransport.deliver(mediaMessage);
|
||||||
}
|
}
|
||||||
|
|
||||||
List<String> destinations = getMediaDestinations(mediaMessage);
|
List<PushDestination> destinations = getMediaDestinations(mediaMessage);
|
||||||
|
|
||||||
if (isPushTransport(destinations)) {
|
if (isPushTransport(destinations)) {
|
||||||
try {
|
try {
|
||||||
|
@ -97,24 +98,25 @@ public class UniversalTransport {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private List<String> getMediaDestinations(SendReq mediaMessage) {
|
private List<PushDestination> getMediaDestinations(SendReq mediaMessage) {
|
||||||
LinkedList<String> destinations = new LinkedList<String>();
|
TextSecurePushCredentials credentials = TextSecurePushCredentials.getInstance();
|
||||||
|
LinkedList<PushDestination> destinations = new LinkedList<PushDestination>();
|
||||||
|
|
||||||
if (mediaMessage.getTo() != null) {
|
if (mediaMessage.getTo() != null) {
|
||||||
for (EncodedStringValue to : mediaMessage.getTo()) {
|
for (EncodedStringValue to : mediaMessage.getTo()) {
|
||||||
destinations.add(Util.canonicalizeNumber(context, to.getString()));
|
destinations.add(PushDestination.getInstance(context, credentials, to.getString()));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (mediaMessage.getCc() != null) {
|
if (mediaMessage.getCc() != null) {
|
||||||
for (EncodedStringValue cc : mediaMessage.getCc()) {
|
for (EncodedStringValue cc : mediaMessage.getCc()) {
|
||||||
destinations.add(Util.canonicalizeNumber(context, cc.getString()));
|
destinations.add(PushDestination.getInstance(context, credentials, cc.getString()));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (mediaMessage.getBcc() != null) {
|
if (mediaMessage.getBcc() != null) {
|
||||||
for (EncodedStringValue bcc : mediaMessage.getBcc()) {
|
for (EncodedStringValue bcc : mediaMessage.getBcc()) {
|
||||||
destinations.add(Util.canonicalizeNumber(context, bcc.getString()));
|
destinations.add(PushDestination.getInstance(context, credentials, bcc.getString()));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -147,9 +149,9 @@ public class UniversalTransport {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private boolean isPushTransport(List<String> destinations) {
|
private boolean isPushTransport(List<PushDestination> destinations) {
|
||||||
for (String destination : destinations) {
|
for (PushDestination destination : destinations) {
|
||||||
if (!isPushTransport(destination)) {
|
if (!isPushTransport(destination.getNumber())) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Reference in a new issue