Add urgency flag to message sends.

fork-5.53.8
Cody Henthorne 2022-08-01 13:06:51 -04:00 zatwierdzone przez Greyson Parrelli
rodzic c7cd261641
commit dc04c8ed98
38 zmienionych plików z 256 dodań i 139 usunięć

Wyświetl plik

@ -6,6 +6,8 @@ import net.zetetic.database.sqlcipher.SQLiteConstraintException
import org.signal.core.util.CursorUtil import org.signal.core.util.CursorUtil
import org.signal.core.util.SqlUtil import org.signal.core.util.SqlUtil
import org.signal.core.util.logging.Log import org.signal.core.util.logging.Log
import org.signal.core.util.requireBoolean
import org.signal.core.util.toInt
import org.thoughtcrime.securesms.database.model.MessageId import org.thoughtcrime.securesms.database.model.MessageId
import org.thoughtcrime.securesms.database.model.MessageLogEntry import org.thoughtcrime.securesms.database.model.MessageLogEntry
import org.thoughtcrime.securesms.recipients.Recipient import org.thoughtcrime.securesms.recipients.Recipient
@ -67,13 +69,15 @@ class MessageSendLogDatabase constructor(context: Context?, databaseHelper: Sign
const val DATE_SENT = "date_sent" const val DATE_SENT = "date_sent"
const val CONTENT = "content" const val CONTENT = "content"
const val CONTENT_HINT = "content_hint" const val CONTENT_HINT = "content_hint"
const val URGENT = "urgent"
const val CREATE_TABLE = """ const val CREATE_TABLE = """
CREATE TABLE $TABLE_NAME ( CREATE TABLE $TABLE_NAME (
$ID INTEGER PRIMARY KEY, $ID INTEGER PRIMARY KEY,
$DATE_SENT INTEGER NOT NULL, $DATE_SENT INTEGER NOT NULL,
$CONTENT BLOB NOT NULL, $CONTENT BLOB NOT NULL,
$CONTENT_HINT INTEGER NOT NULL $CONTENT_HINT INTEGER NOT NULL,
$URGENT INTEGER NOT NULL DEFAULT 1
) )
""" """
@ -152,31 +156,31 @@ class MessageSendLogDatabase constructor(context: Context?, databaseHelper: Sign
} }
/** @return The ID of the inserted entry, or -1 if none was inserted. Can be used with [addRecipientToExistingEntryIfPossible] */ /** @return The ID of the inserted entry, or -1 if none was inserted. Can be used with [addRecipientToExistingEntryIfPossible] */
fun insertIfPossible(recipientId: RecipientId, sentTimestamp: Long, sendMessageResult: SendMessageResult, contentHint: ContentHint, messageId: MessageId): Long { fun insertIfPossible(recipientId: RecipientId, sentTimestamp: Long, sendMessageResult: SendMessageResult, contentHint: ContentHint, messageId: MessageId, urgent: Boolean): Long {
if (!FeatureFlags.retryReceipts()) return -1 if (!FeatureFlags.retryReceipts()) return -1
if (sendMessageResult.isSuccess && sendMessageResult.success.content.isPresent) { if (sendMessageResult.isSuccess && sendMessageResult.success.content.isPresent) {
val recipientDevice = listOf(RecipientDevice(recipientId, sendMessageResult.success.devices)) val recipientDevice = listOf(RecipientDevice(recipientId, sendMessageResult.success.devices))
return insert(recipientDevice, sentTimestamp, sendMessageResult.success.content.get(), contentHint, listOf(messageId)) return insert(recipientDevice, sentTimestamp, sendMessageResult.success.content.get(), contentHint, listOf(messageId), urgent)
} }
return -1 return -1
} }
/** @return The ID of the inserted entry, or -1 if none was inserted. Can be used with [addRecipientToExistingEntryIfPossible] */ /** @return The ID of the inserted entry, or -1 if none was inserted. Can be used with [addRecipientToExistingEntryIfPossible] */
fun insertIfPossible(recipientId: RecipientId, sentTimestamp: Long, sendMessageResult: SendMessageResult, contentHint: ContentHint, messageIds: List<MessageId>): Long { fun insertIfPossible(recipientId: RecipientId, sentTimestamp: Long, sendMessageResult: SendMessageResult, contentHint: ContentHint, messageIds: List<MessageId>, urgent: Boolean): Long {
if (!FeatureFlags.retryReceipts()) return -1 if (!FeatureFlags.retryReceipts()) return -1
if (sendMessageResult.isSuccess && sendMessageResult.success.content.isPresent) { if (sendMessageResult.isSuccess && sendMessageResult.success.content.isPresent) {
val recipientDevice = listOf(RecipientDevice(recipientId, sendMessageResult.success.devices)) val recipientDevice = listOf(RecipientDevice(recipientId, sendMessageResult.success.devices))
return insert(recipientDevice, sentTimestamp, sendMessageResult.success.content.get(), contentHint, messageIds) return insert(recipientDevice, sentTimestamp, sendMessageResult.success.content.get(), contentHint, messageIds, urgent)
} }
return -1 return -1
} }
/** @return The ID of the inserted entry, or -1 if none was inserted. Can be used with [addRecipientToExistingEntryIfPossible] */ /** @return The ID of the inserted entry, or -1 if none was inserted. Can be used with [addRecipientToExistingEntryIfPossible] */
fun insertIfPossible(sentTimestamp: Long, possibleRecipients: List<Recipient>, results: List<SendMessageResult>, contentHint: ContentHint, messageId: MessageId): Long { fun insertIfPossible(sentTimestamp: Long, possibleRecipients: List<Recipient>, results: List<SendMessageResult>, contentHint: ContentHint, messageId: MessageId, urgent: Boolean): Long {
if (!FeatureFlags.retryReceipts()) return -1 if (!FeatureFlags.retryReceipts()) return -1
val accessList = RecipientAccessList(possibleRecipients) val accessList = RecipientAccessList(possibleRecipients)
@ -194,10 +198,10 @@ class MessageSendLogDatabase constructor(context: Context?, databaseHelper: Sign
val content: SignalServiceProtos.Content = results.first { it.isSuccess && it.success.content.isPresent }.success.content.get() val content: SignalServiceProtos.Content = results.first { it.isSuccess && it.success.content.isPresent }.success.content.get()
return insert(recipientDevices, sentTimestamp, content, contentHint, listOf(messageId)) return insert(recipientDevices, sentTimestamp, content, contentHint, listOf(messageId), urgent)
} }
fun addRecipientToExistingEntryIfPossible(payloadId: Long, recipientId: RecipientId, sentTimestamp: Long, sendMessageResult: SendMessageResult, contentHint: ContentHint, messageId: MessageId): Long { fun addRecipientToExistingEntryIfPossible(payloadId: Long, recipientId: RecipientId, sentTimestamp: Long, sendMessageResult: SendMessageResult, contentHint: ContentHint, messageId: MessageId, urgent: Boolean): Long {
if (!FeatureFlags.retryReceipts()) return payloadId if (!FeatureFlags.retryReceipts()) return payloadId
if (sendMessageResult.isSuccess && sendMessageResult.success.content.isPresent) { if (sendMessageResult.isSuccess && sendMessageResult.success.content.isPresent) {
@ -218,9 +222,9 @@ class MessageSendLogDatabase constructor(context: Context?, databaseHelper: Sign
db.setTransactionSuccessful() db.setTransactionSuccessful()
} catch (e: SQLiteConstraintException) { } catch (e: SQLiteConstraintException) {
Log.w(TAG, "Failed to append to existing entry. Creating a new one.") Log.w(TAG, "Failed to append to existing entry. Creating a new one.")
val payloadId = insertIfPossible(recipientId, sentTimestamp, sendMessageResult, contentHint, messageId) val newPayloadId = insertIfPossible(recipientId, sentTimestamp, sendMessageResult, contentHint, messageId, urgent)
db.setTransactionSuccessful() db.setTransactionSuccessful()
return payloadId return newPayloadId
} finally { } finally {
db.endTransaction() db.endTransaction()
} }
@ -229,7 +233,7 @@ class MessageSendLogDatabase constructor(context: Context?, databaseHelper: Sign
return payloadId return payloadId
} }
private fun insert(recipients: List<RecipientDevice>, dateSent: Long, content: SignalServiceProtos.Content, contentHint: ContentHint, messageIds: List<MessageId>): Long { private fun insert(recipients: List<RecipientDevice>, dateSent: Long, content: SignalServiceProtos.Content, contentHint: ContentHint, messageIds: List<MessageId>, urgent: Boolean): Long {
val db = databaseHelper.signalWritableDatabase val db = databaseHelper.signalWritableDatabase
db.beginTransaction() db.beginTransaction()
@ -238,6 +242,7 @@ class MessageSendLogDatabase constructor(context: Context?, databaseHelper: Sign
put(PayloadTable.DATE_SENT, dateSent) put(PayloadTable.DATE_SENT, dateSent)
put(PayloadTable.CONTENT, content.toByteArray()) put(PayloadTable.CONTENT, content.toByteArray())
put(PayloadTable.CONTENT_HINT, contentHint.type) put(PayloadTable.CONTENT_HINT, contentHint.type)
put(PayloadTable.URGENT, urgent.toInt())
} }
val payloadId: Long = db.insert(PayloadTable.TABLE_NAME, null, payloadValues) val payloadId: Long = db.insert(PayloadTable.TABLE_NAME, null, payloadValues)
@ -304,6 +309,7 @@ class MessageSendLogDatabase constructor(context: Context?, databaseHelper: Sign
dateSent = CursorUtil.requireLong(entryCursor, PayloadTable.DATE_SENT), dateSent = CursorUtil.requireLong(entryCursor, PayloadTable.DATE_SENT),
content = SignalServiceProtos.Content.parseFrom(CursorUtil.requireBlob(entryCursor, PayloadTable.CONTENT)), content = SignalServiceProtos.Content.parseFrom(CursorUtil.requireBlob(entryCursor, PayloadTable.CONTENT)),
contentHint = ContentHint.fromType(CursorUtil.requireInt(entryCursor, PayloadTable.CONTENT_HINT)), contentHint = ContentHint.fromType(CursorUtil.requireInt(entryCursor, PayloadTable.CONTENT_HINT)),
urgent = entryCursor.requireBoolean(PayloadTable.URGENT),
relatedMessages = messageIds relatedMessages = messageIds
) )
} }

Wyświetl plik

@ -94,7 +94,8 @@ public class PushDatabase extends Database {
cursor.getLong(cursor.getColumnIndexOrThrow(SERVER_RECEIVED_TIMESTAMP)), cursor.getLong(cursor.getColumnIndexOrThrow(SERVER_RECEIVED_TIMESTAMP)),
cursor.getLong(cursor.getColumnIndexOrThrow(SERVER_DELIVERED_TIMESTAMP)), cursor.getLong(cursor.getColumnIndexOrThrow(SERVER_DELIVERED_TIMESTAMP)),
cursor.getString(cursor.getColumnIndexOrThrow(SERVER_GUID)), cursor.getString(cursor.getColumnIndexOrThrow(SERVER_GUID)),
""); "",
true);
} }
} catch (IOException e) { } catch (IOException e) {
Log.w(TAG, e); Log.w(TAG, e);
@ -180,7 +181,8 @@ public class PushDatabase extends Database {
serverReceivedTimestamp, serverReceivedTimestamp,
serverDeliveredTimestamp, serverDeliveredTimestamp,
serverGuid, serverGuid,
""); "",
true);
} catch (IOException e) { } catch (IOException e) {
throw new AssertionError(e); throw new AssertionError(e);
} }

Wyświetl plik

@ -26,6 +26,7 @@ import org.thoughtcrime.securesms.conversation.colors.ChatColors
import org.thoughtcrime.securesms.conversation.colors.ChatColorsMapper.entrySet import org.thoughtcrime.securesms.conversation.colors.ChatColorsMapper.entrySet
import org.thoughtcrime.securesms.database.KeyValueDatabase import org.thoughtcrime.securesms.database.KeyValueDatabase
import org.thoughtcrime.securesms.database.RecipientDatabase import org.thoughtcrime.securesms.database.RecipientDatabase
import org.thoughtcrime.securesms.database.helpers.migration.UrgentMslFlagMigration
import org.thoughtcrime.securesms.database.model.databaseprotos.ReactionList import org.thoughtcrime.securesms.database.model.databaseprotos.ReactionList
import org.thoughtcrime.securesms.dependencies.ApplicationDependencies import org.thoughtcrime.securesms.dependencies.ApplicationDependencies
import org.thoughtcrime.securesms.groups.GroupId import org.thoughtcrime.securesms.groups.GroupId
@ -203,8 +204,9 @@ object SignalDatabaseMigrations {
private const val QUOTE_INDEX = 147 private const val QUOTE_INDEX = 147
private const val MY_STORY_PRIVACY_MODE = 148 private const val MY_STORY_PRIVACY_MODE = 148
private const val EXPIRING_PROFILE_CREDENTIALS = 149 private const val EXPIRING_PROFILE_CREDENTIALS = 149
private const val URGENT_FLAG = 150
const val DATABASE_VERSION = 149 const val DATABASE_VERSION = 150
@JvmStatic @JvmStatic
fun migrate(context: Application, db: SQLiteDatabase, oldVersion: Int, newVersion: Int) { fun migrate(context: Application, db: SQLiteDatabase, oldVersion: Int, newVersion: Int) {
@ -2663,6 +2665,10 @@ object SignalDatabaseMigrations {
if (oldVersion < EXPIRING_PROFILE_CREDENTIALS) { if (oldVersion < EXPIRING_PROFILE_CREDENTIALS) {
db.execSQL("UPDATE recipient SET profile_key_credential = NULL") db.execSQL("UPDATE recipient SET profile_key_credential = NULL")
} }
if (oldVersion < URGENT_FLAG) {
UrgentMslFlagMigration.migrate(context, db, oldVersion, newVersion)
}
} }
@JvmStatic @JvmStatic

Wyświetl plik

@ -0,0 +1,11 @@
package org.thoughtcrime.securesms.database.helpers.migration
import android.app.Application
import net.zetetic.database.sqlcipher.SQLiteDatabase
/**
* Simple interface for allowing database migrations to live outside of [org.thoughtcrime.securesms.database.helpers.SignalDatabaseMigrations].
*/
interface SignalDatabaseMigration {
fun migrate(context: Application, db: SQLiteDatabase, oldVersion: Int, newVersion: Int)
}

Wyświetl plik

@ -0,0 +1,14 @@
package org.thoughtcrime.securesms.database.helpers.migration
import android.app.Application
import net.zetetic.database.sqlcipher.SQLiteDatabase
/**
* Adding an urgent flag to message envelopes to help with notifications. Need to track flag in
* MSL table so can be resent with the correct urgency.
*/
object UrgentMslFlagMigration : SignalDatabaseMigration {
override fun migrate(context: Application, db: SQLiteDatabase, oldVersion: Int, newVersion: Int) {
db.execSQL("ALTER TABLE msl_payload ADD COLUMN urgent INTEGER NOT NULL DEFAULT 1")
}
}

Wyświetl plik

@ -12,6 +12,8 @@ data class MessageLogEntry(
val dateSent: Long, val dateSent: Long,
val content: SignalServiceProtos.Content, val content: SignalServiceProtos.Content,
val contentHint: ContentHint, val contentHint: ContentHint,
@get:JvmName("isUrgent")
val urgent: Boolean,
val relatedMessages: List<MessageId> val relatedMessages: List<MessageId>
) { ) {
val hasRelatedMessage: Boolean val hasRelatedMessage: Boolean

Wyświetl plik

@ -1273,16 +1273,7 @@ final class GroupManagerV2 {
GroupId.V2 groupId = GroupId.v2(masterKey); GroupId.V2 groupId = GroupId.v2(masterKey);
Recipient groupRecipient = Recipient.externalGroupExact(groupId); Recipient groupRecipient = Recipient.externalGroupExact(groupId);
DecryptedGroupV2Context decryptedGroupV2Context = GroupProtoUtil.createDecryptedGroupV2Context(masterKey, groupMutation, signedGroupChange); DecryptedGroupV2Context decryptedGroupV2Context = GroupProtoUtil.createDecryptedGroupV2Context(masterKey, groupMutation, signedGroupChange);
OutgoingGroupUpdateMessage outgoingMessage = new OutgoingGroupUpdateMessage(groupRecipient, OutgoingGroupUpdateMessage outgoingMessage = new OutgoingGroupUpdateMessage(groupRecipient, decryptedGroupV2Context, System.currentTimeMillis());
decryptedGroupV2Context,
null,
System.currentTimeMillis(),
0,
false,
null,
Collections.emptyList(),
Collections.emptyList(),
Collections.emptyList());
DecryptedGroupChange plainGroupChange = groupMutation.getGroupChange(); DecryptedGroupChange plainGroupChange = groupMutation.getGroupChange();

Wyświetl plik

@ -465,17 +465,7 @@ public class GroupsV2StateProcessor {
.build(); .build();
DecryptedGroupV2Context decryptedGroupV2Context = GroupProtoUtil.createDecryptedGroupV2Context(masterKey, new GroupMutation(decryptedGroup, simulatedGroupChange, simulatedGroupState), null); DecryptedGroupV2Context decryptedGroupV2Context = GroupProtoUtil.createDecryptedGroupV2Context(masterKey, new GroupMutation(decryptedGroup, simulatedGroupChange, simulatedGroupState), null);
OutgoingGroupUpdateMessage leaveMessage = new OutgoingGroupUpdateMessage(groupRecipient, decryptedGroupV2Context, System.currentTimeMillis());
OutgoingGroupUpdateMessage leaveMessage = new OutgoingGroupUpdateMessage(groupRecipient,
decryptedGroupV2Context,
null,
System.currentTimeMillis(),
0,
false,
null,
Collections.emptyList(),
Collections.emptyList(),
Collections.emptyList());
try { try {
MessageDatabase mmsDatabase = SignalDatabase.mms(); MessageDatabase mmsDatabase = SignalDatabase.mms();
@ -703,7 +693,7 @@ public class GroupsV2StateProcessor {
ThreadDatabase threadDatabase = SignalDatabase.threads(); ThreadDatabase threadDatabase = SignalDatabase.threads();
RecipientId recipientId = recipientDatabase.getOrInsertFromGroupId(groupId); RecipientId recipientId = recipientDatabase.getOrInsertFromGroupId(groupId);
Recipient recipient = Recipient.resolved(recipientId); Recipient recipient = Recipient.resolved(recipientId);
OutgoingGroupUpdateMessage outgoingMessage = new OutgoingGroupUpdateMessage(recipient, decryptedGroupV2Context, null, timestamp, 0, false, null, Collections.emptyList(), Collections.emptyList(), Collections.emptyList()); OutgoingGroupUpdateMessage outgoingMessage = new OutgoingGroupUpdateMessage(recipient, decryptedGroupV2Context, timestamp);
long threadId = threadDatabase.getOrCreateThreadIdFor(recipient); long threadId = threadDatabase.getOrCreateThreadIdFor(recipient);
long messageId = mmsDatabase.insertMessageOutbox(outgoingMessage, threadId, false, null); long messageId = mmsDatabase.insertMessageOutbox(outgoingMessage, threadId, false, null);

Wyświetl plik

@ -161,7 +161,8 @@ public class GroupCallUpdateSendJob extends BaseJob {
nonSelfDestinations, nonSelfDestinations,
false, false,
ContentHint.DEFAULT, ContentHint.DEFAULT,
dataMessage); dataMessage,
false);
if (includesSelf) { if (includesSelf) {
results.add(ApplicationDependencies.getSignalServiceMessageSender().sendSyncMessage(dataMessage)); results.add(ApplicationDependencies.getSignalServiceMessageSender().sendSyncMessage(dataMessage));

Wyświetl plik

@ -110,7 +110,7 @@ public final class PaymentNotificationSendJob extends BaseJob {
.withPayment(new SignalServiceDataMessage.Payment(new SignalServiceDataMessage.PaymentNotification(payment.getReceipt(), payment.getNote()))) .withPayment(new SignalServiceDataMessage.Payment(new SignalServiceDataMessage.PaymentNotification(payment.getReceipt(), payment.getNote())))
.build(); .build();
SendMessageResult sendMessageResult = messageSender.sendDataMessage(address, unidentifiedAccess, ContentHint.DEFAULT, dataMessage, IndividualSendEvents.EMPTY); SendMessageResult sendMessageResult = messageSender.sendDataMessage(address, unidentifiedAccess, ContentHint.DEFAULT, dataMessage, IndividualSendEvents.EMPTY, false);
if (sendMessageResult.getIdentityFailure() != null) { if (sendMessageResult.getIdentityFailure() != null) {
Log.w(TAG, "Identity failure for " + recipient.getId()); Log.w(TAG, "Identity failure for " + recipient.getId());

Wyświetl plik

@ -153,7 +153,7 @@ public class ProfileKeySendJob extends BaseJob {
.withTimestamp(System.currentTimeMillis()) .withTimestamp(System.currentTimeMillis())
.withProfileKey(Recipient.self().resolve().getProfileKey()); .withProfileKey(Recipient.self().resolve().getProfileKey());
List<SendMessageResult> results = GroupSendUtil.sendUnresendableDataMessage(context, null, destinations, false, ContentHint.IMPLICIT, dataMessage.build()); List<SendMessageResult> results = GroupSendUtil.sendUnresendableDataMessage(context, null, destinations, false, ContentHint.IMPLICIT, dataMessage.build(), false);
return GroupSendJobHelper.getCompletedSends(destinations, results).completed; return GroupSendJobHelper.getCompletedSends(destinations, results).completed;
} }

Wyświetl plik

@ -292,7 +292,7 @@ public final class PushGroupSendJob extends PushSendJob {
.withExpiration(groupRecipient.getExpiresInSeconds()) .withExpiration(groupRecipient.getExpiresInSeconds())
.asGroupMessage(group) .asGroupMessage(group)
.build(); .build();
return GroupSendUtil.sendResendableDataMessage(context, groupRecipient.requireGroupId().requireV2(), destinations, isRecipientUpdate, ContentHint.IMPLICIT, new MessageId(messageId, true), groupDataMessage); return GroupSendUtil.sendResendableDataMessage(context, groupRecipient.requireGroupId().requireV2(), destinations, isRecipientUpdate, ContentHint.IMPLICIT, new MessageId(messageId, true), groupDataMessage, message.isUrgent());
} else { } else {
throw new UndeliverableMessageException("Messages can no longer be sent to V1 groups!"); throw new UndeliverableMessageException("Messages can no longer be sent to V1 groups!");
} }
@ -351,7 +351,8 @@ public final class PushGroupSendJob extends PushSendJob {
isRecipientUpdate, isRecipientUpdate,
ContentHint.RESENDABLE, ContentHint.RESENDABLE,
new MessageId(messageId, true), new MessageId(messageId, true),
groupMessageBuilder.build()); groupMessageBuilder.build(),
message.isUrgent());
} }
} catch (ServerRejectedException e) { } catch (ServerRejectedException e) {
throw new UndeliverableMessageException(e); throw new UndeliverableMessageException(e);

Wyświetl plik

@ -175,7 +175,7 @@ public final class PushGroupSilentUpdateSendJob extends BaseJob {
.asGroupMessage(group) .asGroupMessage(group)
.build(); .build();
List<SendMessageResult> results = GroupSendUtil.sendUnresendableDataMessage(context, groupId, destinations, false, ContentHint.IMPLICIT, groupDataMessage); List<SendMessageResult> results = GroupSendUtil.sendUnresendableDataMessage(context, groupId, destinations, false, ContentHint.IMPLICIT, groupDataMessage, false);
return GroupSendJobHelper.getCompletedSends(destinations, results).completed; return GroupSendJobHelper.getCompletedSends(destinations, results).completed;
} }

Wyświetl plik

@ -254,11 +254,11 @@ public class PushMediaSendJob extends PushSendJob {
if (Util.equals(SignalStore.account().getAci(), address.getServiceId())) { if (Util.equals(SignalStore.account().getAci(), address.getServiceId())) {
Optional<UnidentifiedAccessPair> syncAccess = UnidentifiedAccessUtil.getAccessForSync(context); Optional<UnidentifiedAccessPair> syncAccess = UnidentifiedAccessUtil.getAccessForSync(context);
SendMessageResult result = messageSender.sendSyncMessage(mediaMessage); SendMessageResult result = messageSender.sendSyncMessage(mediaMessage);
SignalDatabase.messageLog().insertIfPossible(messageRecipient.getId(), message.getSentTimeMillis(), result, ContentHint.RESENDABLE, new MessageId(messageId, true)); SignalDatabase.messageLog().insertIfPossible(messageRecipient.getId(), message.getSentTimeMillis(), result, ContentHint.RESENDABLE, new MessageId(messageId, true), false);
return syncAccess.isPresent(); return syncAccess.isPresent();
} else { } else {
SendMessageResult result = messageSender.sendDataMessage(address, UnidentifiedAccessUtil.getAccessFor(context, messageRecipient), ContentHint.RESENDABLE, mediaMessage, IndividualSendEvents.EMPTY); SendMessageResult result = messageSender.sendDataMessage(address, UnidentifiedAccessUtil.getAccessFor(context, messageRecipient), ContentHint.RESENDABLE, mediaMessage, IndividualSendEvents.EMPTY, message.isUrgent());
SignalDatabase.messageLog().insertIfPossible(messageRecipient.getId(), message.getSentTimeMillis(), result, ContentHint.RESENDABLE, new MessageId(messageId, true)); SignalDatabase.messageLog().insertIfPossible(messageRecipient.getId(), message.getSentTimeMillis(), result, ContentHint.RESENDABLE, new MessageId(messageId, true), message.isUrgent());
return result.getSuccess().isUnidentified(); return result.getSuccess().isUnidentified();
} }
} catch (UnregisteredUserException e) { } catch (UnregisteredUserException e) {

Wyświetl plik

@ -194,13 +194,13 @@ public class PushTextSendJob extends PushSendJob {
SignalLocalMetrics.IndividualMessageSend.onDeliveryStarted(messageId); SignalLocalMetrics.IndividualMessageSend.onDeliveryStarted(messageId);
SendMessageResult result = messageSender.sendSyncMessage(textSecureMessage); SendMessageResult result = messageSender.sendSyncMessage(textSecureMessage);
SignalDatabase.messageLog().insertIfPossible(messageRecipient.getId(), message.getDateSent(), result, ContentHint.RESENDABLE, new MessageId(messageId, false)); SignalDatabase.messageLog().insertIfPossible(messageRecipient.getId(), message.getDateSent(), result, ContentHint.RESENDABLE, new MessageId(messageId, false), false);
return syncAccess.isPresent(); return syncAccess.isPresent();
} else { } else {
SignalLocalMetrics.IndividualMessageSend.onDeliveryStarted(messageId); SignalLocalMetrics.IndividualMessageSend.onDeliveryStarted(messageId);
SendMessageResult result = messageSender.sendDataMessage(address, unidentifiedAccess, ContentHint.RESENDABLE, textSecureMessage, new MetricEventListener(messageId)); SendMessageResult result = messageSender.sendDataMessage(address, unidentifiedAccess, ContentHint.RESENDABLE, textSecureMessage, new MetricEventListener(messageId), true);
SignalDatabase.messageLog().insertIfPossible(messageRecipient.getId(), message.getDateSent(), result, ContentHint.RESENDABLE, new MessageId(messageId, false)); SignalDatabase.messageLog().insertIfPossible(messageRecipient.getId(), message.getDateSent(), result, ContentHint.RESENDABLE, new MessageId(messageId, false), true);
return result.getSuccess().isUnidentified(); return result.getSuccess().isUnidentified();
} }
} catch (UnregisteredUserException e) { } catch (UnregisteredUserException e) {

Wyświetl plik

@ -242,7 +242,8 @@ public class ReactionSendJob extends BaseJob {
false, false,
ContentHint.RESENDABLE, ContentHint.RESENDABLE,
messageId, messageId,
dataMessage); dataMessage,
true);
if (includesSelf) { if (includesSelf) {
results.add(ApplicationDependencies.getSignalServiceMessageSender().sendSyncMessage(dataMessage)); results.add(ApplicationDependencies.getSignalServiceMessageSender().sendSyncMessage(dataMessage));

Wyświetl plik

@ -214,7 +214,8 @@ public class RemoteDeleteSendJob extends BaseJob {
false, false,
ContentHint.RESENDABLE, ContentHint.RESENDABLE,
new MessageId(messageId, isMms), new MessageId(messageId, isMms),
dataMessage); dataMessage,
true);
return GroupSendJobHelper.getCompletedSends(destinations, results); return GroupSendJobHelper.getCompletedSends(destinations, results);
} }

Wyświetl plik

@ -51,6 +51,7 @@ public class ResendMessageJob extends BaseJob {
private final long sentTimestamp; private final long sentTimestamp;
private final Content content; private final Content content;
private final ContentHint contentHint; private final ContentHint contentHint;
private final boolean urgent;
private final GroupId.V2 groupId; private final GroupId.V2 groupId;
private final DistributionId distributionId; private final DistributionId distributionId;
@ -58,6 +59,7 @@ public class ResendMessageJob extends BaseJob {
private static final String KEY_SENT_TIMESTAMP = "sent_timestamp"; private static final String KEY_SENT_TIMESTAMP = "sent_timestamp";
private static final String KEY_CONTENT = "content"; private static final String KEY_CONTENT = "content";
private static final String KEY_CONTENT_HINT = "content_hint"; private static final String KEY_CONTENT_HINT = "content_hint";
private static final String KEY_URGENT = "urgent";
private static final String KEY_GROUP_ID = "group_id"; private static final String KEY_GROUP_ID = "group_id";
private static final String KEY_DISTRIBUTION_ID = "distribution_id"; private static final String KEY_DISTRIBUTION_ID = "distribution_id";
@ -65,6 +67,7 @@ public class ResendMessageJob extends BaseJob {
long sentTimestamp, long sentTimestamp,
@NonNull Content content, @NonNull Content content,
@NonNull ContentHint contentHint, @NonNull ContentHint contentHint,
boolean urgent,
@Nullable GroupId.V2 groupId, @Nullable GroupId.V2 groupId,
@Nullable DistributionId distributionId) @Nullable DistributionId distributionId)
{ {
@ -72,6 +75,7 @@ public class ResendMessageJob extends BaseJob {
sentTimestamp, sentTimestamp,
content, content,
contentHint, contentHint,
urgent,
groupId, groupId,
distributionId, distributionId,
new Parameters.Builder().setQueue(recipientId.toQueueKey()) new Parameters.Builder().setQueue(recipientId.toQueueKey())
@ -85,6 +89,7 @@ public class ResendMessageJob extends BaseJob {
long sentTimestamp, long sentTimestamp,
@NonNull Content content, @NonNull Content content,
@NonNull ContentHint contentHint, @NonNull ContentHint contentHint,
boolean urgent,
@Nullable GroupId.V2 groupId, @Nullable GroupId.V2 groupId,
@Nullable DistributionId distributionId, @Nullable DistributionId distributionId,
@NonNull Parameters parameters) @NonNull Parameters parameters)
@ -95,6 +100,7 @@ public class ResendMessageJob extends BaseJob {
this.sentTimestamp = sentTimestamp; this.sentTimestamp = sentTimestamp;
this.content = content; this.content = content;
this.contentHint = contentHint; this.contentHint = contentHint;
this.urgent = urgent;
this.groupId = groupId; this.groupId = groupId;
this.distributionId = distributionId; this.distributionId = distributionId;
} }
@ -106,6 +112,7 @@ public class ResendMessageJob extends BaseJob {
.putLong(KEY_SENT_TIMESTAMP, sentTimestamp) .putLong(KEY_SENT_TIMESTAMP, sentTimestamp)
.putBlobAsString(KEY_CONTENT, content.toByteArray()) .putBlobAsString(KEY_CONTENT, content.toByteArray())
.putInt(KEY_CONTENT_HINT, contentHint.getType()) .putInt(KEY_CONTENT_HINT, contentHint.getType())
.putBoolean(KEY_URGENT, urgent)
.putBlobAsString(KEY_GROUP_ID, groupId != null ? groupId.getDecodedId() : null) .putBlobAsString(KEY_GROUP_ID, groupId != null ? groupId.getDecodedId() : null)
.putString(KEY_DISTRIBUTION_ID, distributionId != null ? distributionId.toString() : null) .putString(KEY_DISTRIBUTION_ID, distributionId != null ? distributionId.toString() : null)
.build(); .build();
@ -152,7 +159,7 @@ public class ResendMessageJob extends BaseJob {
contentToSend = contentToSend.toBuilder().setSenderKeyDistributionMessage(distributionBytes).build(); contentToSend = contentToSend.toBuilder().setSenderKeyDistributionMessage(distributionBytes).build();
} }
SendMessageResult result = messageSender.resendContent(address, access, sentTimestamp, contentToSend, contentHint, Optional.ofNullable(groupId).map(GroupId::getDecodedId)); SendMessageResult result = messageSender.resendContent(address, access, sentTimestamp, contentToSend, contentHint, Optional.ofNullable(groupId).map(GroupId::getDecodedId), urgent);
if (result.isSuccess() && distributionId != null) { if (result.isSuccess() && distributionId != null) {
List<SignalProtocolAddress> addresses = result.getSuccess() List<SignalProtocolAddress> addresses = result.getSuccess()
@ -195,6 +202,7 @@ public class ResendMessageJob extends BaseJob {
data.getLong(KEY_SENT_TIMESTAMP), data.getLong(KEY_SENT_TIMESTAMP),
content, content,
ContentHint.fromType(data.getInt(KEY_CONTENT_HINT)), ContentHint.fromType(data.getInt(KEY_CONTENT_HINT)),
data.getBooleanOrDefault(KEY_URGENT, true),
groupId, groupId,
distributionId, distributionId,
parameters); parameters);

Wyświetl plik

@ -122,7 +122,7 @@ public class SendDeliveryReceiptJob extends BaseJob {
receiptMessage); receiptMessage);
if (messageId != null) { if (messageId != null) {
SignalDatabase.messageLog().insertIfPossible(recipientId, timestamp, result, ContentHint.IMPLICIT, messageId); SignalDatabase.messageLog().insertIfPossible(recipientId, timestamp, result, ContentHint.IMPLICIT, messageId, false);
} }
} }

Wyświetl plik

@ -186,7 +186,7 @@ public class SendReadReceiptJob extends BaseJob {
receiptMessage); receiptMessage);
if (Util.hasItems(messageIds)) { if (Util.hasItems(messageIds)) {
SignalDatabase.messageLog().insertIfPossible(recipientId, timestamp, result, ContentHint.IMPLICIT, messageIds); SignalDatabase.messageLog().insertIfPossible(recipientId, timestamp, result, ContentHint.IMPLICIT, messageIds, false);
} }
} }

Wyświetl plik

@ -182,7 +182,7 @@ public class SendViewedReceiptJob extends BaseJob {
receiptMessage); receiptMessage);
if (Util.hasItems(messageIds)) { if (Util.hasItems(messageIds)) {
SignalDatabase.messageLog().insertIfPossible(recipientId, timestamp, result, ContentHint.IMPLICIT, messageIds); SignalDatabase.messageLog().insertIfPossible(recipientId, timestamp, result, ContentHint.IMPLICIT, messageIds, false);
} }
} }

Wyświetl plik

@ -101,7 +101,7 @@ public final class SenderKeyDistributionSendJob extends BaseJob {
SenderKeyDistributionMessage message = messageSender.getOrCreateNewGroupSession(distributionId); SenderKeyDistributionMessage message = messageSender.getOrCreateNewGroupSession(distributionId);
List<Optional<UnidentifiedAccessPair>> access = UnidentifiedAccessUtil.getAccessFor(context, Collections.singletonList(recipient)); List<Optional<UnidentifiedAccessPair>> access = UnidentifiedAccessUtil.getAccessFor(context, Collections.singletonList(recipient));
SendMessageResult result = messageSender.sendSenderKeyDistributionMessage(distributionId, address, access, message, Optional.of(groupId.getDecodedId())).get(0); SendMessageResult result = messageSender.sendSenderKeyDistributionMessage(distributionId, address, access, message, Optional.of(groupId.getDecodedId()), false).get(0);
if (result.isSuccess()) { if (result.isSuccess()) {
List<SignalProtocolAddress> addresses = result.getSuccess() List<SignalProtocolAddress> addresses = result.getSuccess()

Wyświetl plik

@ -88,10 +88,11 @@ public final class GroupSendUtil {
boolean isRecipientUpdate, boolean isRecipientUpdate,
ContentHint contentHint, ContentHint contentHint,
@NonNull MessageId messageId, @NonNull MessageId messageId,
@NonNull SignalServiceDataMessage message) @NonNull SignalServiceDataMessage message,
boolean urgent)
throws IOException, UntrustedIdentityException throws IOException, UntrustedIdentityException
{ {
return sendMessage(context, groupId, getDistributionId(groupId), messageId, allTargets, isRecipientUpdate, DataSendOperation.resendable(message, contentHint, messageId), null); return sendMessage(context, groupId, getDistributionId(groupId), messageId, allTargets, isRecipientUpdate, DataSendOperation.resendable(message, contentHint, messageId, urgent), null);
} }
/** /**
@ -109,10 +110,11 @@ public final class GroupSendUtil {
@NonNull List<Recipient> allTargets, @NonNull List<Recipient> allTargets,
boolean isRecipientUpdate, boolean isRecipientUpdate,
ContentHint contentHint, ContentHint contentHint,
@NonNull SignalServiceDataMessage message) @NonNull SignalServiceDataMessage message,
boolean urgent)
throws IOException, UntrustedIdentityException throws IOException, UntrustedIdentityException
{ {
return sendMessage(context, groupId, getDistributionId(groupId), null, allTargets, isRecipientUpdate, DataSendOperation.unresendable(message, contentHint), null); return sendMessage(context, groupId, getDistributionId(groupId), null, allTargets, isRecipientUpdate, DataSendOperation.unresendable(message, contentHint, urgent), null);
} }
/** /**
@ -295,7 +297,7 @@ public final class GroupSendUtil {
Log.d(TAG, "Successfully sent using sender key to " + successCount + "/" + targets.size() + " sender key targets."); Log.d(TAG, "Successfully sent using sender key to " + successCount + "/" + targets.size() + " sender key targets.");
if (sendOperation.shouldIncludeInMessageLog()) { if (sendOperation.shouldIncludeInMessageLog()) {
SignalDatabase.messageLog().insertIfPossible(sendOperation.getSentTimestamp(), senderKeyTargets, results, sendOperation.getContentHint(), sendOperation.getRelatedMessageId()); SignalDatabase.messageLog().insertIfPossible(sendOperation.getSentTimestamp(), senderKeyTargets, results, sendOperation.getContentHint(), sendOperation.getRelatedMessageId(), sendOperation.isUrgent());
} }
if (relatedMessageId != null) { if (relatedMessageId != null) {
@ -353,9 +355,9 @@ public final class GroupSendUtil {
synchronized (entryId) { synchronized (entryId) {
if (entryId.get() == -1) { if (entryId.get() == -1) {
entryId.set(messageLogDatabase.insertIfPossible(recipients.requireRecipientId(result.getAddress()), sendOperation.getSentTimestamp(), result, sendOperation.getContentHint(), sendOperation.getRelatedMessageId())); entryId.set(messageLogDatabase.insertIfPossible(recipients.requireRecipientId(result.getAddress()), sendOperation.getSentTimestamp(), result, sendOperation.getContentHint(), sendOperation.getRelatedMessageId(), sendOperation.isUrgent()));
} else { } else {
entryId.set(messageLogDatabase.addRecipientToExistingEntryIfPossible(entryId.get(), recipients.requireRecipientId(result.getAddress()), sendOperation.getSentTimestamp(), result, sendOperation.getContentHint(), sendOperation.getRelatedMessageId())); entryId.set(messageLogDatabase.addRecipientToExistingEntryIfPossible(entryId.get(), recipients.requireRecipientId(result.getAddress()), sendOperation.getSentTimestamp(), result, sendOperation.getContentHint(), sendOperation.getRelatedMessageId(), sendOperation.isUrgent()));
} }
} }
}, cancelationSignal); }, cancelationSignal);
@ -424,6 +426,7 @@ public final class GroupSendUtil {
long getSentTimestamp(); long getSentTimestamp();
boolean shouldIncludeInMessageLog(); boolean shouldIncludeInMessageLog();
@NonNull MessageId getRelatedMessageId(); @NonNull MessageId getRelatedMessageId();
boolean isUrgent();
} }
private static class DataSendOperation implements SendOperation { private static class DataSendOperation implements SendOperation {
@ -431,20 +434,22 @@ public final class GroupSendUtil {
private final ContentHint contentHint; private final ContentHint contentHint;
private final MessageId relatedMessageId; private final MessageId relatedMessageId;
private final boolean resendable; private final boolean resendable;
private final boolean urgent;
public static DataSendOperation resendable(@NonNull SignalServiceDataMessage message, @NonNull ContentHint contentHint, @NonNull MessageId relatedMessageId) { public static DataSendOperation resendable(@NonNull SignalServiceDataMessage message, @NonNull ContentHint contentHint, @NonNull MessageId relatedMessageId, boolean urgent) {
return new DataSendOperation(message, contentHint, true, relatedMessageId); return new DataSendOperation(message, contentHint, true, relatedMessageId, urgent);
} }
public static DataSendOperation unresendable(@NonNull SignalServiceDataMessage message, @NonNull ContentHint contentHint) { public static DataSendOperation unresendable(@NonNull SignalServiceDataMessage message, @NonNull ContentHint contentHint, boolean urgent) {
return new DataSendOperation(message, contentHint, false, null); return new DataSendOperation(message, contentHint, false, null, urgent);
} }
private DataSendOperation(@NonNull SignalServiceDataMessage message, @NonNull ContentHint contentHint, boolean resendable, @Nullable MessageId relatedMessageId) { private DataSendOperation(@NonNull SignalServiceDataMessage message, @NonNull ContentHint contentHint, boolean resendable, @Nullable MessageId relatedMessageId, boolean urgent) {
this.message = message; this.message = message;
this.contentHint = contentHint; this.contentHint = contentHint;
this.resendable = resendable; this.resendable = resendable;
this.relatedMessageId = relatedMessageId; this.relatedMessageId = relatedMessageId;
this.urgent = urgent;
if (resendable && relatedMessageId == null) { if (resendable && relatedMessageId == null) {
throw new IllegalArgumentException("If a message is resendable, it must have a related message ID!"); throw new IllegalArgumentException("If a message is resendable, it must have a related message ID!");
@ -460,7 +465,7 @@ public final class GroupSendUtil {
throws NoSessionException, UntrustedIdentityException, InvalidKeyException, IOException, InvalidRegistrationIdException throws NoSessionException, UntrustedIdentityException, InvalidKeyException, IOException, InvalidRegistrationIdException
{ {
SenderKeyGroupEvents listener = relatedMessageId != null ? new SenderKeyMetricEventListener(relatedMessageId.getId()) : SenderKeyGroupEvents.EMPTY; SenderKeyGroupEvents listener = relatedMessageId != null ? new SenderKeyMetricEventListener(relatedMessageId.getId()) : SenderKeyGroupEvents.EMPTY;
return messageSender.sendGroupDataMessage(distributionId, targets, access, isRecipientUpdate, contentHint, message, listener); return messageSender.sendGroupDataMessage(distributionId, targets, access, isRecipientUpdate, contentHint, message, listener, urgent);
} }
@Override @Override
@ -473,7 +478,7 @@ public final class GroupSendUtil {
throws IOException, UntrustedIdentityException throws IOException, UntrustedIdentityException
{ {
LegacyGroupEvents listener = relatedMessageId != null ? new LegacyMetricEventListener(relatedMessageId.getId()) : LegacyGroupEvents.EMPTY; LegacyGroupEvents listener = relatedMessageId != null ? new LegacyMetricEventListener(relatedMessageId.getId()) : LegacyGroupEvents.EMPTY;
return messageSender.sendDataMessage(targets, access, isRecipientUpdate, contentHint, message, listener, partialListener, cancelationSignal); return messageSender.sendDataMessage(targets, access, isRecipientUpdate, contentHint, message, listener, partialListener, cancelationSignal, urgent);
} }
@Override @Override
@ -499,6 +504,11 @@ public final class GroupSendUtil {
throw new UnsupportedOperationException(); throw new UnsupportedOperationException();
} }
} }
@Override
public boolean isUrgent() {
return urgent;
}
} }
private static class TypingSendOperation implements SendOperation { private static class TypingSendOperation implements SendOperation {
@ -553,6 +563,11 @@ public final class GroupSendUtil {
public @NonNull MessageId getRelatedMessageId() { public @NonNull MessageId getRelatedMessageId() {
throw new UnsupportedOperationException(); throw new UnsupportedOperationException();
} }
@Override
public boolean isUrgent() {
return false;
}
} }
private static class CallSendOperation implements SendOperation { private static class CallSendOperation implements SendOperation {
@ -605,6 +620,11 @@ public final class GroupSendUtil {
public @NonNull MessageId getRelatedMessageId() { public @NonNull MessageId getRelatedMessageId() {
throw new UnsupportedOperationException(); throw new UnsupportedOperationException();
} }
@Override
public boolean isUrgent() {
return message.isUrgent();
}
} }
public static class StorySendOperation implements SendOperation { public static class StorySendOperation implements SendOperation {
@ -670,6 +690,11 @@ public final class GroupSendUtil {
public @NonNull MessageId getRelatedMessageId() { public @NonNull MessageId getRelatedMessageId() {
return relatedMessageId; return relatedMessageId;
} }
@Override
public boolean isUrgent() {
return false;
}
} }
private static final class SenderKeyMetricEventListener implements SenderKeyGroupEvents { private static final class SenderKeyMetricEventListener implements SenderKeyGroupEvents {

Wyświetl plik

@ -2694,6 +2694,7 @@ public final class MessageContentProcessor {
messageLogEntry.getDateSent(), messageLogEntry.getDateSent(),
messageLogEntry.getContent(), messageLogEntry.getContent(),
messageLogEntry.getContentHint(), messageLogEntry.getContentHint(),
messageLogEntry.isUrgent(),
groupId, groupId,
distributionId)); distributionId));
} else { } else {
@ -2735,6 +2736,7 @@ public final class MessageContentProcessor {
messageLogEntry.getDateSent(), messageLogEntry.getDateSent(),
messageLogEntry.getContent(), messageLogEntry.getContent(),
messageLogEntry.getContentHint(), messageLogEntry.getContentHint(),
messageLogEntry.isUrgent(),
null, null,
null)); null));
} else if (archivedSession) { } else if (archivedSession) {

Wyświetl plik

@ -32,4 +32,8 @@ public class OutgoingExpirationUpdateMessage extends OutgoingSecureMediaMessage
return true; return true;
} }
@Override
public boolean isUrgent() {
return false;
}
} }

Wyświetl plik

@ -67,16 +67,9 @@ public final class OutgoingGroupUpdateMessage extends OutgoingSecureMediaMessage
public OutgoingGroupUpdateMessage(@NonNull Recipient recipient, public OutgoingGroupUpdateMessage(@NonNull Recipient recipient,
@NonNull DecryptedGroupV2Context group, @NonNull DecryptedGroupV2Context group,
@Nullable final Attachment avatar, long sentTimeMillis)
long sentTimeMillis,
long expireIn,
boolean viewOnce,
@Nullable QuoteModel quote,
@NonNull List<Contact> contacts,
@NonNull List<LinkPreview> previews,
@NonNull List<Mention> mentions)
{ {
this(recipient, new MessageGroupContext(group), getAttachments(avatar), sentTimeMillis, expireIn, viewOnce, quote, contacts, previews, mentions); this(recipient, new MessageGroupContext(group), Collections.emptyList(), sentTimeMillis, 0, false, null, Collections.emptyList(), Collections.emptyList(), Collections.emptyList());
} }
@Override @Override
@ -100,6 +93,11 @@ public final class OutgoingGroupUpdateMessage extends OutgoingSecureMediaMessage
return messageGroupContext.requireGroupV2Properties(); return messageGroupContext.requireGroupV2Properties();
} }
@Override
public boolean isUrgent() {
return false;
}
private static List<Attachment> getAttachments(@Nullable Attachment avatar) { private static List<Attachment> getAttachments(@Nullable Attachment avatar) {
return avatar == null ? Collections.emptyList() : Collections.singletonList(avatar); return avatar == null ? Collections.emptyList() : Collections.singletonList(avatar);
} }

Wyświetl plik

@ -249,6 +249,10 @@ public class OutgoingMediaMessage {
return giftBadge; return giftBadge;
} }
public boolean isUrgent() {
return true;
}
private static String buildMessage(SlideDeck slideDeck, String message) { private static String buildMessage(SlideDeck slideDeck, String message) {
if (!TextUtils.isEmpty(message) && !TextUtils.isEmpty(slideDeck.getBody())) { if (!TextUtils.isEmpty(message) && !TextUtils.isEmpty(slideDeck.getBody())) {
return slideDeck.getBody() + "\n\n" + message; return slideDeck.getBody() + "\n\n" + message;

Wyświetl plik

@ -225,7 +225,8 @@ public class SignalServiceMessageReceiver {
entity.getServerTimestamp(), entity.getServerTimestamp(),
messageResult.getServerDeliveredTimestamp(), messageResult.getServerDeliveredTimestamp(),
entity.getServerUuid(), entity.getServerUuid(),
entity.getDestinationUuid()); entity.getDestinationUuid(),
entity.isUrgent());
} else { } else {
envelope = new SignalServiceEnvelope(entity.getType(), envelope = new SignalServiceEnvelope(entity.getType(),
entity.getTimestamp(), entity.getTimestamp(),
@ -234,7 +235,8 @@ public class SignalServiceMessageReceiver {
entity.getServerTimestamp(), entity.getServerTimestamp(),
messageResult.getServerDeliveredTimestamp(), messageResult.getServerDeliveredTimestamp(),
entity.getServerUuid(), entity.getServerUuid(),
entity.getDestinationUuid()); entity.getDestinationUuid(),
entity.isUrgent());
} }
callback.onMessage(envelope); callback.onMessage(envelope);

Wyświetl plik

@ -203,7 +203,7 @@ public class SignalServiceMessageSender {
Content content = createReceiptContent(message); Content content = createReceiptContent(message);
EnvelopeContent envelopeContent = EnvelopeContent.encrypted(content, ContentHint.IMPLICIT, Optional.empty()); EnvelopeContent envelopeContent = EnvelopeContent.encrypted(content, ContentHint.IMPLICIT, Optional.empty());
return sendMessage(recipient, getTargetUnidentifiedAccess(unidentifiedAccess), message.getWhen(), envelopeContent, false, null); return sendMessage(recipient, getTargetUnidentifiedAccess(unidentifiedAccess), message.getWhen(), envelopeContent, false, null, false);
} }
/** /**
@ -219,7 +219,7 @@ public class SignalServiceMessageSender {
PlaintextContent content = new PlaintextContent(errorMessage); PlaintextContent content = new PlaintextContent(errorMessage);
EnvelopeContent envelopeContent = EnvelopeContent.plaintext(content, groupId); EnvelopeContent envelopeContent = EnvelopeContent.plaintext(content, groupId);
sendMessage(recipient, getTargetUnidentifiedAccess(unidentifiedAccess), System.currentTimeMillis(), envelopeContent, false, null); sendMessage(recipient, getTargetUnidentifiedAccess(unidentifiedAccess), System.currentTimeMillis(), envelopeContent, false, null, false);
} }
/** /**
@ -234,7 +234,7 @@ public class SignalServiceMessageSender {
Content content = createTypingContent(message); Content content = createTypingContent(message);
EnvelopeContent envelopeContent = EnvelopeContent.encrypted(content, ContentHint.IMPLICIT, Optional.empty()); EnvelopeContent envelopeContent = EnvelopeContent.encrypted(content, ContentHint.IMPLICIT, Optional.empty());
sendMessage(recipients, getTargetUnidentifiedAccess(unidentifiedAccess), message.getTimestamp(), envelopeContent, true, null, cancelationSignal); sendMessage(recipients, getTargetUnidentifiedAccess(unidentifiedAccess), message.getTimestamp(), envelopeContent, true, null, cancelationSignal, false);
} }
/** /**
@ -247,7 +247,7 @@ public class SignalServiceMessageSender {
throws IOException, UntrustedIdentityException, InvalidKeyException, NoSessionException, InvalidRegistrationIdException throws IOException, UntrustedIdentityException, InvalidKeyException, NoSessionException, InvalidRegistrationIdException
{ {
Content content = createTypingContent(message); Content content = createTypingContent(message);
sendGroupMessage(distributionId, recipients, unidentifiedAccess, message.getTimestamp(), content, ContentHint.IMPLICIT, message.getGroupId(), true, SenderKeyGroupEvents.EMPTY); sendGroupMessage(distributionId, recipients, unidentifiedAccess, message.getTimestamp(), content, ContentHint.IMPLICIT, message.getGroupId(), true, SenderKeyGroupEvents.EMPTY, false);
} }
public List<SendMessageResult> sendStory(List<SignalServiceAddress> recipients, public List<SendMessageResult> sendStory(List<SignalServiceAddress> recipients,
@ -260,7 +260,7 @@ public class SignalServiceMessageSender {
{ {
Content content = createStoryContent(message); Content content = createStoryContent(message);
EnvelopeContent envelopeContent = EnvelopeContent.encrypted(content, ContentHint.RESENDABLE, Optional.empty()); EnvelopeContent envelopeContent = EnvelopeContent.encrypted(content, ContentHint.RESENDABLE, Optional.empty());
List<SendMessageResult> sendMessageResults = sendMessage(recipients, getTargetUnidentifiedAccess(unidentifiedAccess), timestamp, envelopeContent, false, null, null); List<SendMessageResult> sendMessageResults = sendMessage(recipients, getTargetUnidentifiedAccess(unidentifiedAccess), timestamp, envelopeContent, false, null, null, false);
if (store.isMultiDevice()) { if (store.isMultiDevice()) {
SignalServiceSyncMessage syncMessage = createSelfSendSyncMessageForStory(message, timestamp, isRecipientUpdate, manifest); SignalServiceSyncMessage syncMessage = createSelfSendSyncMessageForStory(message, timestamp, isRecipientUpdate, manifest);
@ -284,7 +284,7 @@ public class SignalServiceMessageSender {
throws IOException, UntrustedIdentityException, InvalidKeyException, NoSessionException, InvalidRegistrationIdException throws IOException, UntrustedIdentityException, InvalidKeyException, NoSessionException, InvalidRegistrationIdException
{ {
Content content = createStoryContent(message); Content content = createStoryContent(message);
List<SendMessageResult> sendMessageResults = sendGroupMessage(distributionId, recipients, unidentifiedAccess, timestamp, content, ContentHint.RESENDABLE, groupId, false, SenderKeyGroupEvents.EMPTY); List<SendMessageResult> sendMessageResults = sendGroupMessage(distributionId, recipients, unidentifiedAccess, timestamp, content, ContentHint.RESENDABLE, groupId, false, SenderKeyGroupEvents.EMPTY, false);
if (store.isMultiDevice()) { if (store.isMultiDevice()) {
SignalServiceSyncMessage syncMessage = createSelfSendSyncMessageForStory(message, timestamp, isRecipientUpdate, manifest); SignalServiceSyncMessage syncMessage = createSelfSendSyncMessageForStory(message, timestamp, isRecipientUpdate, manifest);
@ -310,7 +310,7 @@ public class SignalServiceMessageSender {
Content content = createCallContent(message); Content content = createCallContent(message);
EnvelopeContent envelopeContent = EnvelopeContent.encrypted(content, ContentHint.DEFAULT, Optional.empty()); EnvelopeContent envelopeContent = EnvelopeContent.encrypted(content, ContentHint.DEFAULT, Optional.empty());
sendMessage(recipient, getTargetUnidentifiedAccess(unidentifiedAccess), System.currentTimeMillis(), envelopeContent, false, null); sendMessage(recipient, getTargetUnidentifiedAccess(unidentifiedAccess), System.currentTimeMillis(), envelopeContent, false, null, message.isUrgent());
} }
public List<SendMessageResult> sendCallMessage(List<SignalServiceAddress> recipients, public List<SendMessageResult> sendCallMessage(List<SignalServiceAddress> recipients,
@ -321,7 +321,7 @@ public class SignalServiceMessageSender {
Content content = createCallContent(message); Content content = createCallContent(message);
EnvelopeContent envelopeContent = EnvelopeContent.encrypted(content, ContentHint.DEFAULT, Optional.empty()); EnvelopeContent envelopeContent = EnvelopeContent.encrypted(content, ContentHint.DEFAULT, Optional.empty());
return sendMessage(recipients, getTargetUnidentifiedAccess(unidentifiedAccess), System.currentTimeMillis(), envelopeContent, false, null, null); return sendMessage(recipients, getTargetUnidentifiedAccess(unidentifiedAccess), System.currentTimeMillis(), envelopeContent, false, null, null, message.isUrgent());
} }
public List<SendMessageResult> sendCallMessage(DistributionId distributionId, public List<SendMessageResult> sendCallMessage(DistributionId distributionId,
@ -331,7 +331,7 @@ public class SignalServiceMessageSender {
throws IOException, UntrustedIdentityException, InvalidKeyException, NoSessionException, InvalidRegistrationIdException throws IOException, UntrustedIdentityException, InvalidKeyException, NoSessionException, InvalidRegistrationIdException
{ {
Content content = createCallContent(message); Content content = createCallContent(message);
return sendGroupMessage(distributionId, recipients, unidentifiedAccess, message.getTimestamp().get(), content, ContentHint.IMPLICIT, message.getGroupId(), false, SenderKeyGroupEvents.EMPTY); return sendGroupMessage(distributionId, recipients, unidentifiedAccess, message.getTimestamp().get(), content, ContentHint.IMPLICIT, message.getGroupId(), false, SenderKeyGroupEvents.EMPTY, message.isUrgent());
} }
/** /**
@ -360,7 +360,8 @@ public class SignalServiceMessageSender {
Optional<UnidentifiedAccessPair> unidentifiedAccess, Optional<UnidentifiedAccessPair> unidentifiedAccess,
ContentHint contentHint, ContentHint contentHint,
SignalServiceDataMessage message, SignalServiceDataMessage message,
IndividualSendEvents sendEvents) IndividualSendEvents sendEvents,
boolean urgent)
throws UntrustedIdentityException, IOException throws UntrustedIdentityException, IOException
{ {
Log.d(TAG, "[" + message.getTimestamp() + "] Sending a data message."); Log.d(TAG, "[" + message.getTimestamp() + "] Sending a data message.");
@ -371,7 +372,7 @@ public class SignalServiceMessageSender {
sendEvents.onMessageEncrypted(); sendEvents.onMessageEncrypted();
long timestamp = message.getTimestamp(); long timestamp = message.getTimestamp();
SendMessageResult result = sendMessage(recipient, getTargetUnidentifiedAccess(unidentifiedAccess), timestamp, envelopeContent, false, null); SendMessageResult result = sendMessage(recipient, getTargetUnidentifiedAccess(unidentifiedAccess), timestamp, envelopeContent, false, null, urgent);
sendEvents.onMessageSent(); sendEvents.onMessageSent();
@ -379,7 +380,7 @@ public class SignalServiceMessageSender {
Content syncMessage = createMultiDeviceSentTranscriptContent(content, Optional.of(recipient), timestamp, Collections.singletonList(result), false, Collections.emptySet()); Content syncMessage = createMultiDeviceSentTranscriptContent(content, Optional.of(recipient), timestamp, Collections.singletonList(result), false, Collections.emptySet());
EnvelopeContent syncMessageContent = EnvelopeContent.encrypted(syncMessage, ContentHint.IMPLICIT, Optional.empty()); EnvelopeContent syncMessageContent = EnvelopeContent.encrypted(syncMessage, ContentHint.IMPLICIT, Optional.empty());
sendMessage(localAddress, Optional.empty(), timestamp, syncMessageContent, false, null); sendMessage(localAddress, Optional.empty(), timestamp, syncMessageContent, false, null, false);
} }
sendEvents.onSyncMessageSent(); sendEvents.onSyncMessageSent();
@ -403,7 +404,8 @@ public class SignalServiceMessageSender {
List<SignalServiceAddress> recipients, List<SignalServiceAddress> recipients,
List<Optional<UnidentifiedAccessPair>> unidentifiedAccess, List<Optional<UnidentifiedAccessPair>> unidentifiedAccess,
SenderKeyDistributionMessage message, SenderKeyDistributionMessage message,
Optional<byte[]> groupId) Optional<byte[]> groupId,
boolean urgent)
throws IOException throws IOException
{ {
ByteString distributionBytes = ByteString.copyFrom(message.serialize()); ByteString distributionBytes = ByteString.copyFrom(message.serialize());
@ -412,7 +414,7 @@ public class SignalServiceMessageSender {
long timestamp = System.currentTimeMillis(); long timestamp = System.currentTimeMillis();
Log.d(TAG, "[" + timestamp + "] Sending SKDM to " + recipients.size() + " recipients for DistributionId " + distributionId); Log.d(TAG, "[" + timestamp + "] Sending SKDM to " + recipients.size() + " recipients for DistributionId " + distributionId);
return sendMessage(recipients, getTargetUnidentifiedAccess(unidentifiedAccess), timestamp, envelopeContent, false, null, null); return sendMessage(recipients, getTargetUnidentifiedAccess(unidentifiedAccess), timestamp, envelopeContent, false, null, null, urgent);
} }
/** /**
@ -430,13 +432,14 @@ public class SignalServiceMessageSender {
long timestamp, long timestamp,
Content content, Content content,
ContentHint contentHint, ContentHint contentHint,
Optional<byte[]> groupId) Optional<byte[]> groupId,
boolean urgent)
throws UntrustedIdentityException, IOException throws UntrustedIdentityException, IOException
{ {
EnvelopeContent envelopeContent = EnvelopeContent.encrypted(content, contentHint, groupId); EnvelopeContent envelopeContent = EnvelopeContent.encrypted(content, contentHint, groupId);
Optional<UnidentifiedAccess> access = unidentifiedAccess.isPresent() ? unidentifiedAccess.get().getTargetUnidentifiedAccess() : Optional.empty(); Optional<UnidentifiedAccess> access = unidentifiedAccess.isPresent() ? unidentifiedAccess.get().getTargetUnidentifiedAccess() : Optional.empty();
return sendMessage(address, access, timestamp, envelopeContent, false, null); return sendMessage(address, access, timestamp, envelopeContent, false, null, urgent);
} }
/** /**
@ -448,14 +451,15 @@ public class SignalServiceMessageSender {
boolean isRecipientUpdate, boolean isRecipientUpdate,
ContentHint contentHint, ContentHint contentHint,
SignalServiceDataMessage message, SignalServiceDataMessage message,
SenderKeyGroupEvents sendEvents) SenderKeyGroupEvents sendEvents,
boolean urgent)
throws IOException, UntrustedIdentityException, NoSessionException, InvalidKeyException, InvalidRegistrationIdException throws IOException, UntrustedIdentityException, NoSessionException, InvalidKeyException, InvalidRegistrationIdException
{ {
Log.d(TAG, "[" + message.getTimestamp() + "] Sending a group data message to " + recipients.size() + " recipients using DistributionId " + distributionId); Log.d(TAG, "[" + message.getTimestamp() + "] Sending a group data message to " + recipients.size() + " recipients using DistributionId " + distributionId);
Content content = createMessageContent(message); Content content = createMessageContent(message);
Optional<byte[]> groupId = message.getGroupId(); Optional<byte[]> groupId = message.getGroupId();
List<SendMessageResult> results = sendGroupMessage(distributionId, recipients, unidentifiedAccess, message.getTimestamp(), content, contentHint, groupId, false, sendEvents); List<SendMessageResult> results = sendGroupMessage(distributionId, recipients, unidentifiedAccess, message.getTimestamp(), content, contentHint, groupId, false, sendEvents, urgent);
sendEvents.onMessageSent(); sendEvents.onMessageSent();
@ -463,7 +467,7 @@ public class SignalServiceMessageSender {
Content syncMessage = createMultiDeviceSentTranscriptContent(content, Optional.empty(), message.getTimestamp(), results, isRecipientUpdate, Collections.emptySet()); Content syncMessage = createMultiDeviceSentTranscriptContent(content, Optional.empty(), message.getTimestamp(), results, isRecipientUpdate, Collections.emptySet());
EnvelopeContent syncMessageContent = EnvelopeContent.encrypted(syncMessage, ContentHint.IMPLICIT, Optional.empty()); EnvelopeContent syncMessageContent = EnvelopeContent.encrypted(syncMessage, ContentHint.IMPLICIT, Optional.empty());
sendMessage(localAddress, Optional.empty(), message.getTimestamp(), syncMessageContent, false, null); sendMessage(localAddress, Optional.empty(), message.getTimestamp(), syncMessageContent, false, null, false);
} }
sendEvents.onSyncMessageSent(); sendEvents.onSyncMessageSent();
@ -484,7 +488,8 @@ public class SignalServiceMessageSender {
SignalServiceDataMessage message, SignalServiceDataMessage message,
LegacyGroupEvents sendEvents, LegacyGroupEvents sendEvents,
PartialSendCompleteListener partialListener, PartialSendCompleteListener partialListener,
CancelationSignal cancelationSignal) CancelationSignal cancelationSignal,
boolean urgent)
throws IOException, UntrustedIdentityException throws IOException, UntrustedIdentityException
{ {
Log.d(TAG, "[" + message.getTimestamp() + "] Sending a data message to " + recipients.size() + " recipients."); Log.d(TAG, "[" + message.getTimestamp() + "] Sending a data message to " + recipients.size() + " recipients.");
@ -492,7 +497,7 @@ public class SignalServiceMessageSender {
Content content = createMessageContent(message); Content content = createMessageContent(message);
EnvelopeContent envelopeContent = EnvelopeContent.encrypted(content, contentHint, message.getGroupId()); EnvelopeContent envelopeContent = EnvelopeContent.encrypted(content, contentHint, message.getGroupId());
long timestamp = message.getTimestamp(); long timestamp = message.getTimestamp();
List<SendMessageResult> results = sendMessage(recipients, getTargetUnidentifiedAccess(unidentifiedAccess), timestamp, envelopeContent, false, partialListener, cancelationSignal); List<SendMessageResult> results = sendMessage(recipients, getTargetUnidentifiedAccess(unidentifiedAccess), timestamp, envelopeContent, false, partialListener, cancelationSignal, urgent);
boolean needsSyncInResults = false; boolean needsSyncInResults = false;
sendEvents.onMessageSent(); sendEvents.onMessageSent();
@ -513,7 +518,7 @@ public class SignalServiceMessageSender {
Content syncMessage = createMultiDeviceSentTranscriptContent(content, recipient, timestamp, results, isRecipientUpdate, Collections.emptySet()); Content syncMessage = createMultiDeviceSentTranscriptContent(content, recipient, timestamp, results, isRecipientUpdate, Collections.emptySet());
EnvelopeContent syncMessageContent = EnvelopeContent.encrypted(syncMessage, ContentHint.IMPLICIT, Optional.empty()); EnvelopeContent syncMessageContent = EnvelopeContent.encrypted(syncMessage, ContentHint.IMPLICIT, Optional.empty());
sendMessage(localAddress, Optional.empty(), timestamp, syncMessageContent, false, null); sendMessage(localAddress, Optional.empty(), timestamp, syncMessageContent, false, null, false);
} }
sendEvents.onSyncMessageSent(); sendEvents.onSyncMessageSent();
@ -531,14 +536,15 @@ public class SignalServiceMessageSender {
throws IOException, UntrustedIdentityException throws IOException, UntrustedIdentityException
{ {
Content content; Content content;
boolean urgent = false;
if (message.getContacts().isPresent()) { if (message.getContacts().isPresent()) {
content = createMultiDeviceContactsContent(message.getContacts().get().getContactsStream().asStream(), content = createMultiDeviceContactsContent(message.getContacts().get().getContactsStream().asStream(), message.getContacts().get().isComplete());
message.getContacts().get().isComplete());
} else if (message.getGroups().isPresent()) { } else if (message.getGroups().isPresent()) {
content = createMultiDeviceGroupsContent(message.getGroups().get().asStream()); content = createMultiDeviceGroupsContent(message.getGroups().get().asStream());
} else if (message.getRead().isPresent()) { } else if (message.getRead().isPresent()) {
content = createMultiDeviceReadContent(message.getRead().get()); content = createMultiDeviceReadContent(message.getRead().get());
urgent = true;
} else if (message.getViewed().isPresent()) { } else if (message.getViewed().isPresent()) {
content = createMultiDeviceViewedContent(message.getViewed().get()); content = createMultiDeviceViewedContent(message.getViewed().get());
} else if (message.getViewOnceOpen().isPresent()) { } else if (message.getViewOnceOpen().isPresent()) {
@ -563,6 +569,7 @@ public class SignalServiceMessageSender {
return sendVerifiedSyncMessage(message.getVerified().get()); return sendVerifiedSyncMessage(message.getVerified().get());
} else if (message.getRequest().isPresent()) { } else if (message.getRequest().isPresent()) {
content = createRequestContent(message.getRequest().get().getRequest()); content = createRequestContent(message.getRequest().get().getRequest());
urgent = message.getRequest().get().isUrgent();
} else if (message.getPniIdentity().isPresent()) { } else if (message.getPniIdentity().isPresent()) {
content = createPniIdentityContent(message.getPniIdentity().get()); content = createPniIdentityContent(message.getPniIdentity().get());
} else { } else {
@ -574,7 +581,7 @@ public class SignalServiceMessageSender {
EnvelopeContent envelopeContent = EnvelopeContent.encrypted(content, ContentHint.IMPLICIT, Optional.empty()); EnvelopeContent envelopeContent = EnvelopeContent.encrypted(content, ContentHint.IMPLICIT, Optional.empty());
return sendMessage(localAddress, Optional.empty(), timestamp, envelopeContent, false, null); return sendMessage(localAddress, Optional.empty(), timestamp, envelopeContent, false, null, urgent);
} }
public void setSoTimeoutMillis(long soTimeoutMillis) { public void setSoTimeoutMillis(long soTimeoutMillis) {
@ -711,13 +718,13 @@ public class SignalServiceMessageSender {
EnvelopeContent envelopeContent = EnvelopeContent.encrypted(content, ContentHint.IMPLICIT, Optional.empty()); EnvelopeContent envelopeContent = EnvelopeContent.encrypted(content, ContentHint.IMPLICIT, Optional.empty());
SendMessageResult result = sendMessage(message.getDestination(), Optional.empty(), message.getTimestamp(), envelopeContent, false, null); SendMessageResult result = sendMessage(message.getDestination(), Optional.empty(), message.getTimestamp(), envelopeContent, false, null, false);
if (result.getSuccess().isNeedsSync()) { if (result.getSuccess().isNeedsSync()) {
Content syncMessage = createMultiDeviceVerifiedContent(message, nullMessage.toByteArray()); Content syncMessage = createMultiDeviceVerifiedContent(message, nullMessage.toByteArray());
EnvelopeContent syncMessageContent = EnvelopeContent.encrypted(syncMessage, ContentHint.IMPLICIT, Optional.empty()); EnvelopeContent syncMessageContent = EnvelopeContent.encrypted(syncMessage, ContentHint.IMPLICIT, Optional.empty());
sendMessage(localAddress, Optional.empty(), message.getTimestamp(), syncMessageContent, false, null); sendMessage(localAddress, Optional.empty(), message.getTimestamp(), syncMessageContent, false, null, false);
} }
return result; return result;
@ -741,7 +748,7 @@ public class SignalServiceMessageSender {
EnvelopeContent envelopeContent = EnvelopeContent.encrypted(content, ContentHint.IMPLICIT, Optional.empty()); EnvelopeContent envelopeContent = EnvelopeContent.encrypted(content, ContentHint.IMPLICIT, Optional.empty());
return sendMessage(address, getTargetUnidentifiedAccess(unidentifiedAccess), System.currentTimeMillis(), envelopeContent, false, null); return sendMessage(address, getTargetUnidentifiedAccess(unidentifiedAccess), System.currentTimeMillis(), envelopeContent, false, null, false);
} }
private Content createTypingContent(SignalServiceTypingMessage message) { private Content createTypingContent(SignalServiceTypingMessage message) {
@ -1616,7 +1623,8 @@ public class SignalServiceMessageSender {
EnvelopeContent content, EnvelopeContent content,
boolean online, boolean online,
PartialSendCompleteListener partialListener, PartialSendCompleteListener partialListener,
CancelationSignal cancelationSignal) CancelationSignal cancelationSignal,
boolean urgent)
throws IOException throws IOException
{ {
Log.d(TAG, "[" + timestamp + "] Sending to " + recipients.size() + " recipients."); Log.d(TAG, "[" + timestamp + "] Sending to " + recipients.size() + " recipients.");
@ -1631,7 +1639,7 @@ public class SignalServiceMessageSender {
SignalServiceAddress recipient = recipientIterator.next(); SignalServiceAddress recipient = recipientIterator.next();
Optional<UnidentifiedAccess> access = unidentifiedAccessIterator.next(); Optional<UnidentifiedAccess> access = unidentifiedAccessIterator.next();
futureResults.add(executor.submit(() -> { futureResults.add(executor.submit(() -> {
SendMessageResult result = sendMessage(recipient, access, timestamp, content, online, cancelationSignal); SendMessageResult result = sendMessage(recipient, access, timestamp, content, online, cancelationSignal, urgent);
if (partialListener != null) { if (partialListener != null) {
partialListener.onPartialSendComplete(result); partialListener.onPartialSendComplete(result);
} }
@ -1698,7 +1706,8 @@ public class SignalServiceMessageSender {
long timestamp, long timestamp,
EnvelopeContent content, EnvelopeContent content,
boolean online, boolean online,
CancelationSignal cancelationSignal) CancelationSignal cancelationSignal,
boolean urgent)
throws UntrustedIdentityException, IOException throws UntrustedIdentityException, IOException
{ {
enforceMaxContentSize(content); enforceMaxContentSize(content);
@ -1711,7 +1720,7 @@ public class SignalServiceMessageSender {
} }
try { try {
OutgoingPushMessageList messages = getEncryptedMessages(socket, recipient, unidentifiedAccess, timestamp, content, online); OutgoingPushMessageList messages = getEncryptedMessages(socket, recipient, unidentifiedAccess, timestamp, content, online, urgent);
if (content.getContent().isPresent() && content.getContent().get().getSyncMessage() != null && content.getContent().get().getSyncMessage().hasSent()) { if (content.getContent().isPresent() && content.getContent().get().getSyncMessage() != null && content.getContent().get().getSyncMessage().hasSent()) {
Log.d(TAG, "[sendMessage][" + timestamp + "] Sending a sent sync message to devices: " + messages.getDevices()); Log.d(TAG, "[sendMessage][" + timestamp + "] Sending a sent sync message to devices: " + messages.getDevices());
@ -1796,7 +1805,8 @@ public class SignalServiceMessageSender {
ContentHint contentHint, ContentHint contentHint,
Optional<byte[]> groupId, Optional<byte[]> groupId,
boolean online, boolean online,
SenderKeyGroupEvents sendEvents) SenderKeyGroupEvents sendEvents,
boolean urgent)
throws IOException, UntrustedIdentityException, NoSessionException, InvalidKeyException, InvalidRegistrationIdException throws IOException, UntrustedIdentityException, NoSessionException, InvalidKeyException, InvalidRegistrationIdException
{ {
if (recipients.isEmpty()) { if (recipients.isEmpty()) {
@ -1833,7 +1843,7 @@ public class SignalServiceMessageSender {
}) })
.collect(Collectors.toList()); .collect(Collectors.toList());
List<SendMessageResult> results = sendSenderKeyDistributionMessage(distributionId, needsSenderKey, access, message, groupId); List<SendMessageResult> results = sendSenderKeyDistributionMessage(distributionId, needsSenderKey, access, message, groupId, urgent);
List<SignalServiceAddress> successes = results.stream() List<SignalServiceAddress> successes = results.stream()
.filter(SendMessageResult::isSuccess) .filter(SendMessageResult::isSuccess)
@ -1895,7 +1905,7 @@ public class SignalServiceMessageSender {
try { try {
try { try {
SendGroupMessageResponse response = new MessagingService.SendResponseProcessor<>(messagingService.sendToGroup(ciphertext, joinedUnidentifiedAccess, timestamp, online).blockingGet()).getResultOrThrow(); SendGroupMessageResponse response = new MessagingService.SendResponseProcessor<>(messagingService.sendToGroup(ciphertext, joinedUnidentifiedAccess, timestamp, online, urgent).blockingGet()).getResultOrThrow();
return transformGroupResponseToMessageResults(targetInfo.devices, response, content); return transformGroupResponseToMessageResults(targetInfo.devices, response, content);
} catch (InvalidUnidentifiedAccessHeaderException | NotFoundException | GroupMismatchedDevicesException | GroupStaleDevicesException e) { } catch (InvalidUnidentifiedAccessHeaderException | NotFoundException | GroupMismatchedDevicesException | GroupStaleDevicesException e) {
// Non-technical failures shouldn't be retried with socket // Non-technical failures shouldn't be retried with socket
@ -1906,7 +1916,7 @@ public class SignalServiceMessageSender {
Log.w(TAG, "[sendGroupMessage][" + timestamp + "] Pipe failed, falling back... (" + e.getClass().getSimpleName() + ": " + e.getMessage() + ")"); Log.w(TAG, "[sendGroupMessage][" + timestamp + "] Pipe failed, falling back... (" + e.getClass().getSimpleName() + ": " + e.getMessage() + ")");
} }
SendGroupMessageResponse response = socket.sendGroupMessage(ciphertext, joinedUnidentifiedAccess, timestamp, online); SendGroupMessageResponse response = socket.sendGroupMessage(ciphertext, joinedUnidentifiedAccess, timestamp, online, urgent);
return transformGroupResponseToMessageResults(targetInfo.devices, response, content); return transformGroupResponseToMessageResults(targetInfo.devices, response, content);
} catch (GroupMismatchedDevicesException e) { } catch (GroupMismatchedDevicesException e) {
Log.w(TAG, "[sendGroupMessage][" + timestamp + "] Handling mismatched devices. (" + e.getMessage() + ")"); Log.w(TAG, "[sendGroupMessage][" + timestamp + "] Handling mismatched devices. (" + e.getMessage() + ")");
@ -2070,7 +2080,8 @@ public class SignalServiceMessageSender {
Optional<UnidentifiedAccess> unidentifiedAccess, Optional<UnidentifiedAccess> unidentifiedAccess,
long timestamp, long timestamp,
EnvelopeContent plaintext, EnvelopeContent plaintext,
boolean online) boolean online,
boolean urgent)
throws IOException, InvalidKeyException, UntrustedIdentityException throws IOException, InvalidKeyException, UntrustedIdentityException
{ {
List<OutgoingPushMessage> messages = new LinkedList<>(); List<OutgoingPushMessage> messages = new LinkedList<>();
@ -2091,7 +2102,7 @@ public class SignalServiceMessageSender {
} }
} }
return new OutgoingPushMessageList(recipient.getIdentifier(), timestamp, messages, online); return new OutgoingPushMessageList(recipient.getIdentifier(), timestamp, messages, online, urgent);
} }
private OutgoingPushMessage getEncryptedMessage(PushServiceSocket socket, private OutgoingPushMessage getEncryptedMessage(PushServiceSocket socket,

Wyświetl plik

@ -65,14 +65,16 @@ public class SignalServiceEnvelope {
long serverReceivedTimestamp, long serverReceivedTimestamp,
long serverDeliveredTimestamp, long serverDeliveredTimestamp,
String uuid, String uuid,
String destinationUuid) String destinationUuid,
boolean urgent)
{ {
Envelope.Builder builder = Envelope.newBuilder() Envelope.Builder builder = Envelope.newBuilder()
.setType(Envelope.Type.valueOf(type)) .setType(Envelope.Type.valueOf(type))
.setSourceDevice(senderDevice) .setSourceDevice(senderDevice)
.setTimestamp(timestamp) .setTimestamp(timestamp)
.setServerTimestamp(serverReceivedTimestamp) .setServerTimestamp(serverReceivedTimestamp)
.setDestinationUuid(destinationUuid); .setDestinationUuid(destinationUuid)
.setUrgent(urgent);
if (sender.isPresent()) { if (sender.isPresent()) {
builder.setSourceUuid(sender.get().getServiceId().toString()); builder.setSourceUuid(sender.get().getServiceId().toString());
@ -100,13 +102,15 @@ public class SignalServiceEnvelope {
long serverReceivedTimestamp, long serverReceivedTimestamp,
long serverDeliveredTimestamp, long serverDeliveredTimestamp,
String uuid, String uuid,
String destinationUuid) String destinationUuid,
boolean urgent)
{ {
Envelope.Builder builder = Envelope.newBuilder() Envelope.Builder builder = Envelope.newBuilder()
.setType(Envelope.Type.valueOf(type)) .setType(Envelope.Type.valueOf(type))
.setTimestamp(timestamp) .setTimestamp(timestamp)
.setServerTimestamp(serverReceivedTimestamp) .setServerTimestamp(serverReceivedTimestamp)
.setDestinationUuid(destinationUuid); .setDestinationUuid(destinationUuid)
.setUrgent(urgent);
if (uuid != null) { if (uuid != null) {
builder.setServerGuid(uuid); builder.setServerGuid(uuid);
@ -273,6 +277,9 @@ public class SignalServiceEnvelope {
return envelope.getDestinationUuid(); return envelope.getDestinationUuid();
} }
public boolean isUrgent() {
return envelope.getUrgent();
}
private SignalServiceEnvelopeProto.Builder serializeToProto() { private SignalServiceEnvelopeProto.Builder serializeToProto() {
SignalServiceEnvelopeProto.Builder builder = SignalServiceEnvelopeProto.newBuilder() SignalServiceEnvelopeProto.Builder builder = SignalServiceEnvelopeProto.newBuilder()
@ -280,7 +287,8 @@ public class SignalServiceEnvelope {
.setDeviceId(getSourceDevice()) .setDeviceId(getSourceDevice())
.setTimestamp(getTimestamp()) .setTimestamp(getTimestamp())
.setServerReceivedTimestamp(getServerReceivedTimestamp()) .setServerReceivedTimestamp(getServerReceivedTimestamp())
.setServerDeliveredTimestamp(getServerDeliveredTimestamp()); .setServerDeliveredTimestamp(getServerDeliveredTimestamp())
.setUrgent(isUrgent());
if (getSourceUuid().isPresent()) { if (getSourceUuid().isPresent()) {
builder.setSourceUuid(getSourceUuid().get()); builder.setSourceUuid(getSourceUuid().get());
@ -330,6 +338,7 @@ public class SignalServiceEnvelope {
proto.getServerReceivedTimestamp(), proto.getServerReceivedTimestamp(),
proto.getServerDeliveredTimestamp(), proto.getServerDeliveredTimestamp(),
proto.getServerGuid(), proto.getServerGuid(),
proto.getDestinationUuid()); proto.getDestinationUuid(),
proto.getUrgent());
} }
} }

Wyświetl plik

@ -198,4 +198,10 @@ public class SignalServiceCallMessage {
public Optional<Long> getTimestamp() { public Optional<Long> getTimestamp() {
return timestamp; return timestamp;
} }
public boolean isUrgent() {
return offerMessage.isPresent() ||
hangupMessage.isPresent() ||
opaqueMessage.map(m -> m.getUrgency() == OpaqueMessage.Urgency.HANDLE_IMMEDIATELY).orElse(false);
}
} }

Wyświetl plik

@ -47,4 +47,8 @@ public class RequestMessage {
public boolean isPniIdentityRequest() { public boolean isPniIdentityRequest() {
return request.getType() == Request.Type.PNI_IDENTITY; return request.getType() == Request.Type.PNI_IDENTITY;
} }
public boolean isUrgent() {
return isContactsRequest() || isKeysRequest() || isPniIdentityRequest();
}
} }

Wyświetl plik

@ -72,13 +72,13 @@ public class MessagingService {
.onErrorReturn(ServiceResponse::forUnknownError); .onErrorReturn(ServiceResponse::forUnknownError);
} }
public Single<ServiceResponse<SendGroupMessageResponse>> sendToGroup(byte[] body, byte[] joinedUnidentifiedAccess, long timestamp, boolean online) { public Single<ServiceResponse<SendGroupMessageResponse>> sendToGroup(byte[] body, byte[] joinedUnidentifiedAccess, long timestamp, boolean online, boolean urgent) {
List<String> headers = new LinkedList<String>() {{ List<String> headers = new LinkedList<String>() {{
add("content-type:application/vnd.signal-messenger.mrm"); add("content-type:application/vnd.signal-messenger.mrm");
add("Unidentified-Access-Key:" + Base64.encodeBytes(joinedUnidentifiedAccess)); add("Unidentified-Access-Key:" + Base64.encodeBytes(joinedUnidentifiedAccess));
}}; }};
String path = String.format(Locale.US, "/v1/messages/multi_recipient?ts=%s&online=%s", timestamp, online); String path = String.format(Locale.US, "/v1/messages/multi_recipient?ts=%s&online=%s&urgent=%s", timestamp, online, urgent);
WebSocketRequestMessage requestMessage = WebSocketRequestMessage.newBuilder() WebSocketRequestMessage requestMessage = WebSocketRequestMessage.newBuilder()
.setId(new SecureRandom().nextLong()) .setId(new SecureRandom().nextLong())

Wyświetl plik

@ -26,15 +26,20 @@ public class OutgoingPushMessageList {
@JsonProperty @JsonProperty
private boolean online; private boolean online;
@JsonProperty
private boolean urgent;
public OutgoingPushMessageList(String destination, public OutgoingPushMessageList(String destination,
long timestamp, long timestamp,
List<OutgoingPushMessage> messages, List<OutgoingPushMessage> messages,
boolean online) boolean online,
boolean urgent)
{ {
this.timestamp = timestamp; this.timestamp = timestamp;
this.destination = destination; this.destination = destination;
this.messages = messages; this.messages = messages;
this.online = online; this.online = online;
this.urgent = urgent;
} }
public String getDestination() { public String getDestination() {
@ -53,6 +58,10 @@ public class OutgoingPushMessageList {
return online; return online;
} }
public boolean isUrgent() {
return urgent;
}
@JsonIgnore @JsonIgnore
public List<Integer> getDevices() { public List<Integer> getDevices() {
return messages.stream().map(OutgoingPushMessage::getDestinationDeviceId).collect(Collectors.toList()); return messages.stream().map(OutgoingPushMessage::getDestinationDeviceId).collect(Collectors.toList());

Wyświetl plik

@ -212,7 +212,7 @@ public class PushServiceSocket {
private static final String DIRECTORY_AUTH_PATH = "/v1/directory/auth"; private static final String DIRECTORY_AUTH_PATH = "/v1/directory/auth";
private static final String MESSAGE_PATH = "/v1/messages/%s"; private static final String MESSAGE_PATH = "/v1/messages/%s";
private static final String GROUP_MESSAGE_PATH = "/v1/messages/multi_recipient?ts=%s&online=%s"; private static final String GROUP_MESSAGE_PATH = "/v1/messages/multi_recipient?ts=%s&online=%s&urgent=%s";
private static final String SENDER_ACK_MESSAGE_PATH = "/v1/messages/%s/%d"; private static final String SENDER_ACK_MESSAGE_PATH = "/v1/messages/%s/%d";
private static final String UUID_ACK_MESSAGE_PATH = "/v1/messages/uuid/%s"; private static final String UUID_ACK_MESSAGE_PATH = "/v1/messages/uuid/%s";
private static final String ATTACHMENT_V2_PATH = "/v2/attachments/form/upload"; private static final String ATTACHMENT_V2_PATH = "/v2/attachments/form/upload";
@ -463,12 +463,12 @@ public class PushServiceSocket {
return JsonUtil.fromJson(responseText, SenderCertificate.class).getCertificate(); return JsonUtil.fromJson(responseText, SenderCertificate.class).getCertificate();
} }
public SendGroupMessageResponse sendGroupMessage(byte[] body, byte[] joinedUnidentifiedAccess, long timestamp, boolean online) public SendGroupMessageResponse sendGroupMessage(byte[] body, byte[] joinedUnidentifiedAccess, long timestamp, boolean online, boolean urgent)
throws IOException throws IOException
{ {
ServiceConnectionHolder connectionHolder = (ServiceConnectionHolder) getRandom(serviceClients, random); ServiceConnectionHolder connectionHolder = (ServiceConnectionHolder) getRandom(serviceClients, random);
String path = String.format(Locale.US, GROUP_MESSAGE_PATH, timestamp, online); String path = String.format(Locale.US, GROUP_MESSAGE_PATH, timestamp, online, urgent);
Request.Builder requestBuilder = new Request.Builder(); Request.Builder requestBuilder = new Request.Builder();
requestBuilder.url(String.format("%s%s", connectionHolder.getUrl(), path)); requestBuilder.url(String.format("%s%s", connectionHolder.getUrl(), path));

Wyświetl plik

@ -37,6 +37,9 @@ public class SignalServiceEnvelopeEntity {
@JsonProperty @JsonProperty
private String guid; private String guid;
@JsonProperty
private Boolean urgent;
public SignalServiceEnvelopeEntity() {} public SignalServiceEnvelopeEntity() {}
public int getType() { public int getType() {
@ -86,4 +89,8 @@ public class SignalServiceEnvelopeEntity {
public String getDestinationUuid() { public String getDestinationUuid() {
return destinationUuid; return destinationUuid;
} }
public boolean isUrgent() {
return urgent == null || urgent;
}
} }

Wyświetl plik

@ -33,6 +33,7 @@ message SignalServiceEnvelopeProto {
optional int64 serverDeliveredTimestamp = 9; optional int64 serverDeliveredTimestamp = 9;
optional string serverGuid = 10; optional string serverGuid = 10;
optional string destinationUuid = 11; optional string destinationUuid = 11;
optional bool urgent = 12 [default = true];
} }
message MetadataProto { message MetadataProto {

Wyświetl plik

@ -33,7 +33,8 @@ message Envelope {
optional bytes content = 8; // Contains an encrypted Content optional bytes content = 8; // Contains an encrypted Content
optional string serverGuid = 9; optional string serverGuid = 9;
optional uint64 serverTimestamp = 10; optional uint64 serverTimestamp = 10;
// NEXT ID: 14 optional bool urgent = 14 [default = true];
// NEXT ID: 15
} }
message Content { message Content {