Update SignalService.proto to match shared one.

This commit is contained in:
Greyson Parrelli
2026-03-26 09:37:44 -04:00
committed by Alex Hart
parent 5ae51f844e
commit f04a0533cb
22 changed files with 413 additions and 345 deletions

View File

@@ -316,7 +316,7 @@ class DataMessageProcessorTest_polls {
private fun insertPoll(allowMultiple: Boolean = true): Long {
val envelope = MessageContentFuzzer.envelope(100)
val pollMessage = IncomingMessage(type = MessageType.NORMAL, from = alice.id, sentTimeMillis = envelope.timestamp!!, serverTimeMillis = envelope.serverTimestamp!!, receivedTimeMillis = 0, groupId = groupId)
val pollMessage = IncomingMessage(type = MessageType.NORMAL, from = alice.id, sentTimeMillis = envelope.clientTimestamp!!, serverTimeMillis = envelope.serverTimestamp!!, receivedTimeMillis = 0, groupId = groupId)
val messageId = SignalDatabase.messages.insertMessageInbox(pollMessage).get()
SignalDatabase.polls.insertPoll("question?", allowMultiple, listOf("a", "b", "c"), alice.id.toLong(), messageId.messageId)
return messageId.messageId

View File

@@ -43,7 +43,7 @@ object MessageContentFuzzer {
*/
fun envelope(timestamp: Long, serverGuid: UUID = UUID.randomUUID()): Envelope {
return Envelope.Builder()
.timestamp(timestamp)
.clientTimestamp(timestamp)
.serverTimestamp(timestamp + 5)
.serverGuidBinary(serverGuid.toByteArray().toByteString())
.build()
@@ -292,7 +292,7 @@ object MessageContentFuzzer {
body = string()
val quoted = quoteAble.random(random)
quote = DataMessage.Quote.Builder().buildWith {
id = quoted.envelope.timestamp
id = quoted.envelope.clientTimestamp
authorAciBinary = quoted.metadata.sourceServiceId.toByteString()
text = quoted.content.dataMessage?.body
attachments(quoted.content.dataMessage?.attachments ?: emptyList())
@@ -304,7 +304,7 @@ object MessageContentFuzzer {
if (random.nextFloat() < 0.1 && quoteAble.isNotEmpty()) {
val quoted = quoteAble.random(random)
quote = DataMessage.Quote.Builder().buildWith {
id = random.nextLong(quoted.envelope.timestamp!! - 1000000, quoted.envelope.timestamp!!)
id = random.nextLong(quoted.envelope.clientTimestamp!! - 1000000, quoted.envelope.clientTimestamp!!)
authorAciBinary = quoted.metadata.sourceServiceId.toByteString()
text = quoted.content.dataMessage?.body
}
@@ -333,7 +333,7 @@ object MessageContentFuzzer {
emoji = emojis.random(random)
remove = false
targetAuthorAciBinary = reactTo.metadata.sourceServiceId.toByteString()
targetSentTimestamp = reactTo.envelope.timestamp
targetSentTimestamp = reactTo.envelope.clientTimestamp
}
}
}

View File

@@ -70,8 +70,8 @@ object Generator {
val serverGuid = UUID.randomUUID()
return Envelope.Builder()
.type(Envelope.Type.fromValue(this.type))
.sourceDevice(1)
.timestamp(timestamp)
.sourceDeviceId(1)
.clientTimestamp(timestamp)
.serverTimestamp(timestamp + 1)
.destinationServiceId(destination.toString())
.destinationServiceIdBinary(destination.toByteString())

View File

@@ -67,9 +67,9 @@ class PushProcessMessageJobMigration : JobMigration(10) {
val envelope = Envelope.Builder()
.sourceServiceId(sourceServiceId.toString())
.sourceDevice(proto.metadata!!.senderDevice)
.sourceDeviceId(proto.metadata!!.senderDevice)
.destinationServiceId(destinationServiceId.toString())
.timestamp(proto.metadata!!.timestamp)
.clientTimestamp(proto.metadata!!.timestamp)
.serverGuid(proto.metadata!!.serverGuid)
.serverTimestamp(proto.metadata!!.serverReceivedTimestamp)

View File

@@ -155,7 +155,7 @@ class PushProcessMessageJob private constructor(
try {
messageProcessor.process(result.envelope, result.content, result.metadata, result.serverDeliveredTimestamp, localMetric = localReceiveMetric, batchCache = batchCache)
} catch (e: Exception) {
Log.e(TAG, "Failed to process message with timestamp ${result.envelope.timestamp}. Dropping.", e)
Log.e(TAG, "Failed to process message with timestamp ${result.envelope.clientTimestamp}. Dropping.", e)
}
null
}

View File

@@ -41,15 +41,15 @@ object CallMessageProcessor {
if (metadata.destinationServiceId is ServiceId.PNI) {
if (RecipientUtil.isCallRequestAccepted(senderRecipient) && callMessage.offer != null) {
log(envelope.timestamp!!, "Received call offer message at our PNI from trusted sender, responding with profile and pni signature")
log(envelope.clientTimestamp!!, "Received call offer message at our PNI from trusted sender, responding with profile and pni signature")
RecipientUtil.shareProfileIfFirstSecureMessage(senderRecipient)
ProfileKeySendJob.create(senderRecipient, false)?.let { AppDependencies.jobManager.add(it) }
}
if (callMessage.offer != null) {
log(envelope.timestamp!!, "Call message at our PNI is an offer, continuing.")
log(envelope.clientTimestamp!!, "Call message at our PNI is an offer, continuing.")
} else {
log(envelope.timestamp!!, "Call message at our PNI is not an offer, ignoring.")
log(envelope.clientTimestamp!!, "Call message at our PNI is not an offer, ignoring.")
return
}
}
@@ -65,12 +65,12 @@ object CallMessageProcessor {
}
private fun handleCallOfferMessage(envelope: Envelope, metadata: EnvelopeMetadata, offer: Offer, senderRecipientId: RecipientId, serverDeliveredTimestamp: Long) {
log(envelope.timestamp!!, "handleCallOfferMessage...")
log(envelope.clientTimestamp!!, "handleCallOfferMessage...")
val offerId = if (offer.id != null && offer.type != null && offer.opaque != null) {
offer.id!!
} else {
warn(envelope.timestamp!!, "Invalid offer, missing id, type, or opaque")
warn(envelope.clientTimestamp!!, "Invalid offer, missing id, type, or opaque")
return
}
@@ -96,12 +96,12 @@ object CallMessageProcessor {
answer: CallMessage.Answer,
senderRecipientId: RecipientId
) {
log(envelope.timestamp!!, "handleCallAnswerMessage...")
log(envelope.clientTimestamp!!, "handleCallAnswerMessage...")
val answerId = if (answer.id != null && answer.opaque != null) {
answer.id!!
} else {
warn(envelope.timestamp!!, "Invalid answer, missing id or opaque")
warn(envelope.clientTimestamp!!, "Invalid answer, missing id or opaque")
return
}
@@ -122,7 +122,7 @@ object CallMessageProcessor {
iceUpdateList: List<CallMessage.IceUpdate>,
senderRecipientId: RecipientId
) {
log(envelope.timestamp!!, "handleCallIceUpdateMessage... " + iceUpdateList.size)
log(envelope.clientTimestamp!!, "handleCallIceUpdateMessage... " + iceUpdateList.size)
val iceCandidates: MutableList<ByteArray> = ArrayList(iceUpdateList.size)
var callId: Long = -1
@@ -142,7 +142,7 @@ object CallMessageProcessor {
iceCandidates
)
} else {
warn(envelope.timestamp!!, "Invalid ice updates, all missing opaque and/or call id")
warn(envelope.clientTimestamp!!, "Invalid ice updates, all missing opaque and/or call id")
}
}
@@ -152,12 +152,12 @@ object CallMessageProcessor {
hangup: CallMessage.Hangup?,
senderRecipientId: RecipientId
) {
log(envelope.timestamp!!, "handleCallHangupMessage")
log(envelope.clientTimestamp!!, "handleCallHangupMessage")
val (hangupId: Long, hangupDeviceId: Int?) = if (hangup?.id != null) {
hangup.id!! to hangup.deviceId
} else {
warn(envelope.timestamp!!, "Invalid hangup, null message or missing id/deviceId")
warn(envelope.clientTimestamp!!, "Invalid hangup, null message or missing id/deviceId")
return
}
@@ -170,12 +170,12 @@ object CallMessageProcessor {
}
private fun handleCallBusyMessage(envelope: Envelope, metadata: EnvelopeMetadata, busy: CallMessage.Busy, senderRecipientId: RecipientId) {
log(envelope.timestamp!!, "handleCallBusyMessage")
log(envelope.clientTimestamp!!, "handleCallBusyMessage")
val busyId = if (busy.id != null) {
busy.id!!
} else {
warn(envelope.timestamp!!, "Invalid busy, missing call id")
warn(envelope.clientTimestamp!!, "Invalid busy, missing call id")
return
}
@@ -184,12 +184,12 @@ object CallMessageProcessor {
}
private fun handleCallOpaqueMessage(envelope: Envelope, metadata: EnvelopeMetadata, opaque: Opaque, senderServiceId: ServiceId, serverDeliveredTimestamp: Long) {
log(envelope.timestamp!!, "handleCallOpaqueMessage")
log(envelope.clientTimestamp!!, "handleCallOpaqueMessage")
val data = if (opaque.data_ != null) {
opaque.data_!!.toByteArray()
} else {
warn(envelope.timestamp!!, "Invalid opaque message, null data")
warn(envelope.clientTimestamp!!, "Invalid opaque message, null data")
return
}

View File

@@ -149,7 +149,7 @@ object DataMessageProcessor {
SignalTrace.beginSection("DataMessageProcessor#gv2PreProcessing")
groupProcessResult = MessageContentProcessor.handleGv2PreProcessing(
context = context,
timestamp = envelope.timestamp!!,
timestamp = envelope.clientTimestamp!!,
content = content,
metadata = metadata,
groupId = groupId,
@@ -171,7 +171,7 @@ object DataMessageProcessor {
var messageId: MessageId? = null
SignalTrace.beginSection("DataMessageProcessor#messageInsert")
when {
message.isInvalid -> handleInvalidMessage(context, senderRecipient.id, groupId, envelope.timestamp!!)
message.isInvalid -> handleInvalidMessage(context, senderRecipient.id, groupId, envelope.clientTimestamp!!)
message.isEndSession -> insertResult = handleEndSessionMessage(context, senderRecipient.id, envelope, metadata)
message.isExpirationUpdate -> insertResult = handleExpirationUpdate(envelope, metadata, senderRecipient, threadRecipient.id, groupId, message.expireTimerDuration, message.expireTimerVersion, receivedTime, false)
message.isStoryReaction -> insertResult = handleStoryReaction(context, envelope, metadata, message, senderRecipient.id, groupId)
@@ -197,7 +197,7 @@ object DataMessageProcessor {
SignalTrace.beginSection("DataMessageProcessor#postProcess")
messageId = messageId ?: insertResult?.messageId?.let { MessageId(it) }
if (messageId != null) {
log(envelope.timestamp!!, "Inserted as messageId $messageId")
log(envelope.clientTimestamp!!, "Inserted as messageId $messageId")
}
if (groupId != null) {
@@ -206,12 +206,12 @@ object DataMessageProcessor {
else -> SignalDatabase.groups.isUnknownGroup(groupId)
}
if (unknownGroup) {
handleUnknownGroupMessage(envelope.timestamp!!, message.groupV2!!)
handleUnknownGroupMessage(envelope.clientTimestamp!!, message.groupV2!!)
}
}
if (message.profileKey.isNotEmpty()) {
handleProfileKey(envelope.timestamp!!, message.profileKey!!.toByteArray(), senderRecipient)
handleProfileKey(envelope.clientTimestamp!!, message.profileKey!!.toByteArray(), senderRecipient)
}
if (groupId == null && senderRecipient.hiddenState == HiddenState.HIDDEN) {
@@ -248,11 +248,11 @@ object DataMessageProcessor {
if (insertResult != null && insertResult.threadWasNewlyCreated && !threadRecipient.isGroup && !threadRecipient.isSelf && !senderRecipient.isSystemContact) {
val timeSinceLastSync = System.currentTimeMillis() - SignalStore.misc.lastCdsForegroundSyncTime
if (timeSinceLastSync > RemoteConfig.cdsForegroundSyncInterval || timeSinceLastSync < 0) {
log(envelope.timestamp!!, "New 1:1 chat. Scheduling a CDS sync to see if they match someone in our contacts.")
log(envelope.clientTimestamp!!, "New 1:1 chat. Scheduling a CDS sync to see if they match someone in our contacts.")
AppDependencies.jobManager.add(DirectoryRefreshJob(false))
SignalStore.misc.lastCdsForegroundSyncTime = System.currentTimeMillis()
} else {
warn(envelope.timestamp!!, "New 1:1 chat, but performed a CDS sync $timeSinceLastSync ms ago, which is less than our threshold. Skipping CDS sync.")
warn(envelope.clientTimestamp!!, "New 1:1 chat, but performed a CDS sync $timeSinceLastSync ms ago, which is less than our threshold. Skipping CDS sync.")
}
}
@@ -316,11 +316,11 @@ object DataMessageProcessor {
envelope: Envelope,
metadata: EnvelopeMetadata
): InsertResult? {
log(envelope.timestamp!!, "End session message.")
log(envelope.clientTimestamp!!, "End session message.")
val incomingMessage = IncomingMessage(
from = senderRecipientId,
sentTimeMillis = envelope.timestamp!!,
sentTimeMillis = envelope.clientTimestamp!!,
serverTimeMillis = envelope.serverTimestamp!!,
receivedTimeMillis = System.currentTimeMillis(),
isUnidentified = metadata.sealedSender,
@@ -356,20 +356,20 @@ object DataMessageProcessor {
receivedTime: Long,
sideEffect: Boolean
): InsertResult? {
log(envelope.timestamp!!, "Expiration update. Side effect: $sideEffect")
log(envelope.clientTimestamp!!, "Expiration update. Side effect: $sideEffect")
if (groupId != null) {
warn(envelope.timestamp!!, "Expiration update received for GV2. Ignoring.")
warn(envelope.clientTimestamp!!, "Expiration update received for GV2. Ignoring.")
return null
}
if (SignalDatabase.recipients.getExpiresInSeconds(threadRecipientId) == expiresIn.inWholeSeconds) {
log(envelope.timestamp!!, "No change in message expiry for group. Ignoring.")
log(envelope.clientTimestamp!!, "No change in message expiry for group. Ignoring.")
return null
}
if (expireTimerVersion != null && expireTimerVersion < senderRecipient.expireTimerVersion) {
log(envelope.timestamp!!, "Old expireTimerVersion. Received: $expireTimerVersion, Current: ${senderRecipient.expireTimerVersion}. Ignoring.")
log(envelope.clientTimestamp!!, "Old expireTimerVersion. Received: $expireTimerVersion, Current: ${senderRecipient.expireTimerVersion}. Ignoring.")
return null
}
@@ -377,7 +377,7 @@ object DataMessageProcessor {
val mediaMessage = IncomingMessage(
type = MessageType.EXPIRATION_UPDATE,
from = senderRecipient.id,
sentTimeMillis = envelope.timestamp!! - if (sideEffect) 1 else 0,
sentTimeMillis = envelope.clientTimestamp!! - if (sideEffect) 1 else 0,
serverTimeMillis = envelope.serverTimestamp!!,
receivedTimeMillis = receivedTime,
expiresIn = expiresIn.inWholeMilliseconds,
@@ -419,7 +419,7 @@ object DataMessageProcessor {
receivedTime: Long
) {
if (threadRecipient.expiresInSeconds.toLong() != expiresIn.inWholeSeconds || ((expireTimerVersion ?: -1) > threadRecipient.expireTimerVersion)) {
warn(envelope.timestamp!!, "Message expire time didn't match thread expire time. Handling timer update.")
warn(envelope.clientTimestamp!!, "Message expire time didn't match thread expire time. Handling timer update.")
handleExpirationUpdate(envelope, metadata, senderRecipient, threadRecipient.id, groupId, expiresIn, expireTimerVersion, receivedTime, true)
}
}
@@ -433,13 +433,13 @@ object DataMessageProcessor {
senderRecipientId: RecipientId,
groupId: GroupId.V2?
): InsertResult? {
log(envelope.timestamp!!, "Story reaction.")
log(envelope.clientTimestamp!!, "Story reaction.")
val storyContext = message.storyContext!!
val emoji = message.reaction!!.emoji
if (!EmojiUtil.isEmoji(emoji)) {
warn(envelope.timestamp!!, "Story reaction text is not a valid emoji! Ignoring the message.")
warn(envelope.clientTimestamp!!, "Story reaction text is not a valid emoji! Ignoring the message.")
return null
}
@@ -472,18 +472,18 @@ object DataMessageProcessor {
quoteModel = QuoteModel(sentTimestamp, authorRecipientId, displayText, false, story.slideDeck.asAttachments().firstOrNull(), emptyList(), QuoteModel.Type.NORMAL, bodyRanges)
expiresIn = message.expireTimerDuration
} else {
warn(envelope.timestamp!!, "Story has reactions disabled. Dropping reaction.")
warn(envelope.clientTimestamp!!, "Story has reactions disabled. Dropping reaction.")
return null
}
} catch (e: NoSuchMessageException) {
warn(envelope.timestamp!!, "Couldn't find story for reaction.", e)
warn(envelope.clientTimestamp!!, "Couldn't find story for reaction.", e)
return null
}
val mediaMessage = IncomingMessage(
type = MessageType.STORY_REACTION,
from = senderRecipientId,
sentTimeMillis = envelope.timestamp!!,
sentTimeMillis = envelope.clientTimestamp!!,
serverTimeMillis = envelope.serverTimestamp!!,
receivedTimeMillis = System.currentTimeMillis(),
parentStoryId = parentStoryId,
@@ -513,7 +513,7 @@ object DataMessageProcessor {
null
}
} else {
warn(envelope.timestamp!!, "Failed to insert story reaction")
warn(envelope.clientTimestamp!!, "Failed to insert story reaction")
null
}
} catch (e: MmsException) {
@@ -533,7 +533,7 @@ object DataMessageProcessor {
): MessageId? {
val reaction: DataMessage.Reaction = message.reaction!!
log(envelope.timestamp!!, "Handle reaction for message " + reaction.targetSentTimestamp!!)
log(envelope.clientTimestamp!!, "Handle reaction for message " + reaction.targetSentTimestamp!!)
val emoji: String? = reaction.emoji
val isRemove: Boolean = reaction.remove ?: false
@@ -541,19 +541,19 @@ object DataMessageProcessor {
val targetSentTimestamp: Long = reaction.targetSentTimestamp!!
if (targetAuthorServiceId.isUnknown) {
warn(envelope.timestamp!!, "Reaction was to an unknown UUID! Ignoring the message.")
warn(envelope.clientTimestamp!!, "Reaction was to an unknown UUID! Ignoring the message.")
return null
}
if (!EmojiUtil.isEmoji(emoji)) {
warn(envelope.timestamp!!, "Reaction text is not a valid emoji! Ignoring the message.")
warn(envelope.clientTimestamp!!, "Reaction text is not a valid emoji! Ignoring the message.")
return null
}
val targetAuthor = Recipient.externalPush(targetAuthorServiceId)
val targetMessage = SignalDatabase.messages.getMessageFor(targetSentTimestamp, targetAuthor.id)
if (targetMessage == null) {
warn(envelope.timestamp!!, "[handleReaction] Could not find matching message! Putting it in the early message cache. timestamp: " + targetSentTimestamp + " author: " + targetAuthor.id)
warn(envelope.clientTimestamp!!, "[handleReaction] Could not find matching message! Putting it in the early message cache. timestamp: " + targetSentTimestamp + " author: " + targetAuthor.id)
if (earlyMessageCacheEntry != null) {
AppDependencies.earlyMessageCache.store(targetAuthor.id, targetSentTimestamp, earlyMessageCacheEntry)
PushProcessEarlyMessagesJob.enqueue()
@@ -562,25 +562,25 @@ object DataMessageProcessor {
}
if (targetMessage.isRemoteDelete) {
warn(envelope.timestamp!!, "[handleReaction] Found a matching message, but it's flagged as remotely deleted. timestamp: " + targetSentTimestamp + " author: " + targetAuthor.id)
warn(envelope.clientTimestamp!!, "[handleReaction] Found a matching message, but it's flagged as remotely deleted. timestamp: " + targetSentTimestamp + " author: " + targetAuthor.id)
return null
}
val targetThread = SignalDatabase.threads.getThreadRecord(targetMessage.threadId)
if (targetThread == null) {
warn(envelope.timestamp!!, "[handleReaction] Could not find a thread for the message! timestamp: " + targetSentTimestamp + " author: " + targetAuthor.id)
warn(envelope.clientTimestamp!!, "[handleReaction] Could not find a thread for the message! timestamp: " + targetSentTimestamp + " author: " + targetAuthor.id)
return null
}
val targetThreadRecipientId = targetThread.recipient.id
val groupRecord = SignalDatabase.groups.getGroup(targetThreadRecipientId).orNull()
if (groupRecord != null && !groupRecord.members.contains(senderRecipientId)) {
warn(envelope.timestamp!!, "[handleReaction] Reaction author is not in the group! timestamp: " + targetSentTimestamp + " author: " + targetAuthor.id)
warn(envelope.clientTimestamp!!, "[handleReaction] Reaction author is not in the group! timestamp: " + targetSentTimestamp + " author: " + targetAuthor.id)
return null
}
if (groupRecord == null && senderRecipientId != targetThreadRecipientId && Recipient.self().id != senderRecipientId) {
warn(envelope.timestamp!!, "[handleReaction] Reaction author is not a part of the 1:1 thread! timestamp: " + targetSentTimestamp + " author: " + targetAuthor.id)
warn(envelope.clientTimestamp!!, "[handleReaction] Reaction author is not a part of the 1:1 thread! timestamp: " + targetSentTimestamp + " author: " + targetAuthor.id)
return null
}
@@ -601,7 +601,7 @@ object DataMessageProcessor {
fun handleRemoteDelete(context: Context, envelope: Envelope, message: DataMessage, senderRecipientId: RecipientId, earlyMessageCacheEntry: EarlyMessageCacheEntry?): MessageId? {
val delete = message.delete!!
log(envelope.timestamp!!, "Remote delete for message ${delete.targetSentTimestamp}")
log(envelope.clientTimestamp!!, "Remote delete for message ${delete.targetSentTimestamp}")
val targetSentTimestamp: Long = delete.targetSentTimestamp!!
val targetMessage: MessageRecord? = SignalDatabase.messages.getMessageFor(targetSentTimestamp, senderRecipientId)
@@ -616,7 +616,7 @@ object DataMessageProcessor {
MessageId(targetMessage.id)
} else if (targetMessage == null) {
warn(envelope.timestamp!!, "[handleRemoteDelete] Could not find matching message! timestamp: $targetSentTimestamp author: $senderRecipientId")
warn(envelope.clientTimestamp!!, "[handleRemoteDelete] Could not find matching message! timestamp: $targetSentTimestamp author: $senderRecipientId")
if (earlyMessageCacheEntry != null) {
AppDependencies.earlyMessageCache.store(senderRecipientId, targetSentTimestamp, earlyMessageCacheEntry)
PushProcessEarlyMessagesJob.enqueue()
@@ -624,7 +624,7 @@ object DataMessageProcessor {
null
} else {
warn(envelope.timestamp!!, "[handleRemoteDelete] Invalid remote delete! deleteTime: ${envelope.serverTimestamp!!}, targetTime: ${targetMessage.serverTimestamp}, deleteAuthor: $senderRecipientId, targetAuthor: ${targetMessage.fromRecipient.id}")
warn(envelope.clientTimestamp!!, "[handleRemoteDelete] Invalid remote delete! deleteTime: ${envelope.serverTimestamp!!}, targetTime: ${targetMessage.serverTimestamp}, deleteAuthor: $senderRecipientId, targetAuthor: ${targetMessage.fromRecipient.id}")
null
}
}
@@ -644,13 +644,13 @@ object DataMessageProcessor {
isActivatePaymentsRequest: Boolean,
isPaymentsActivated: Boolean
): InsertResult? {
log(envelope.timestamp!!, "Payment activation request: $isActivatePaymentsRequest activated: $isPaymentsActivated")
log(envelope.clientTimestamp!!, "Payment activation request: $isActivatePaymentsRequest activated: $isPaymentsActivated")
Preconditions.checkArgument(isActivatePaymentsRequest || isPaymentsActivated)
try {
val mediaMessage = IncomingMessage(
from = senderRecipientId,
sentTimeMillis = envelope.timestamp!!,
sentTimeMillis = envelope.clientTimestamp!!,
serverTimeMillis = envelope.serverTimestamp!!,
receivedTimeMillis = receivedTime,
expiresIn = message.expireTimerDuration.inWholeMilliseconds,
@@ -675,10 +675,10 @@ object DataMessageProcessor {
senderRecipientId: RecipientId,
receivedTime: Long
): InsertResult? {
log(envelope.timestamp!!, "Payment message.")
log(envelope.clientTimestamp!!, "Payment message.")
if (message.payment?.notification?.mobileCoin?.receipt == null) {
warn(envelope.timestamp!!, "Ignoring payment message without notification")
warn(envelope.clientTimestamp!!, "Ignoring payment message without notification")
return null
}
@@ -701,7 +701,7 @@ object DataMessageProcessor {
val mediaMessage = IncomingMessage(
from = senderRecipientId,
body = uuid.toString(),
sentTimeMillis = envelope.timestamp!!,
sentTimeMillis = envelope.clientTimestamp!!,
serverTimeMillis = envelope.serverTimestamp!!,
receivedTimeMillis = receivedTime,
expiresIn = message.expireTimerDuration.inWholeMilliseconds,
@@ -716,9 +716,9 @@ object DataMessageProcessor {
return insertResult
}
} catch (e: PublicKeyConflictException) {
warn(envelope.timestamp!!, "Ignoring payment with public key already in database")
warn(envelope.clientTimestamp!!, "Ignoring payment with public key already in database")
} catch (e: SerializationException) {
warn(envelope.timestamp!!, "Ignoring payment with bad data.", e)
warn(envelope.clientTimestamp!!, "Ignoring payment with bad data.", e)
} catch (e: MmsException) {
throw StorageFailedException(e, metadata.sourceServiceId.toString(), metadata.sourceDeviceId)
} finally {
@@ -743,14 +743,14 @@ object DataMessageProcessor {
groupId: GroupId.V2?,
receivedTime: Long
): InsertResult? {
log(envelope.timestamp!!, "Story reply.")
log(envelope.clientTimestamp!!, "Story reply.")
val storyContext: DataMessage.StoryContext = message.storyContext!!
val authorServiceId: ServiceId = ACI.parseOrThrow(storyContext.authorAci, storyContext.authorAciBinary)
val sentTimestamp: Long = if (storyContext.sentTimestamp != null) {
storyContext.sentTimestamp!!
} else {
warn(envelope.timestamp!!, "Invalid story reply, missing sentTimestamp")
warn(envelope.clientTimestamp!!, "Invalid story reply, missing sentTimestamp")
return null
}
@@ -798,11 +798,11 @@ object DataMessageProcessor {
quoteModel = QuoteModel(sentTimestamp, storyAuthorRecipientId, displayText, false, story.slideDeck.asAttachments().firstOrNull(), emptyList(), QuoteModel.Type.NORMAL, bodyRanges)
expiresInMillis = message.expireTimerDuration
} else {
warn(envelope.timestamp!!, "Story has replies disabled. Dropping reply.")
warn(envelope.clientTimestamp!!, "Story has replies disabled. Dropping reply.")
return null
}
} catch (e: NoSuchMessageException) {
warn(envelope.timestamp!!, "Couldn't find story for reply.", e)
warn(envelope.clientTimestamp!!, "Couldn't find story for reply.", e)
return null
}
@@ -811,7 +811,7 @@ object DataMessageProcessor {
val mediaMessage = IncomingMessage(
type = MessageType.NORMAL,
from = senderRecipient.id,
sentTimeMillis = envelope.timestamp!!,
sentTimeMillis = envelope.clientTimestamp!!,
serverTimeMillis = envelope.serverTimestamp!!,
receivedTimeMillis = System.currentTimeMillis(),
parentStoryId = parentStoryId,
@@ -843,7 +843,7 @@ object DataMessageProcessor {
null
}
} else {
warn(envelope.timestamp!!, "Failed to insert story reply.")
warn(envelope.clientTimestamp!!, "Failed to insert story reply.")
null
}
} catch (e: MmsException) {
@@ -880,7 +880,7 @@ object DataMessageProcessor {
val mediaMessage = IncomingMessage(
type = MessageType.NORMAL,
from = senderRecipient.id,
sentTimeMillis = envelope.timestamp!!,
sentTimeMillis = envelope.clientTimestamp!!,
serverTimeMillis = envelope.serverTimestamp!!,
receivedTimeMillis = receivedTime,
expiresIn = message.expireTimerDuration.inWholeMilliseconds,
@@ -917,7 +917,7 @@ object DataMessageProcessor {
localMetrics: SignalLocalMetrics.MessageReceive?,
batchCache: BatchCache
): InsertResult? {
log(envelope.timestamp!!, "Media message.")
log(envelope.clientTimestamp!!, "Media message.")
notifyTypingStoppedFromIncomingMessage(context, senderRecipient, threadRecipient.id, metadata.sourceDeviceId)
@@ -925,11 +925,11 @@ object DataMessageProcessor {
SignalDatabase.messages.beginTransaction()
try {
val quoteModel: QuoteModel? = getValidatedQuote(context, envelope.timestamp!!, message, senderRecipient, threadRecipient)
val quoteModel: QuoteModel? = getValidatedQuote(context, envelope.clientTimestamp!!, message, senderRecipient, threadRecipient)
val contacts: List<Contact> = getContacts(message)
val linkPreviews: List<LinkPreview> = getLinkPreviews(message.preview, message.body ?: "", false)
val mentions: List<Mention> = getMentions(message.bodyRanges.take(BODY_RANGE_PROCESSING_LIMIT))
val sticker: Attachment? = getStickerAttachment(envelope.timestamp!!, message)
val sticker: Attachment? = getStickerAttachment(envelope.clientTimestamp!!, message)
val attachments: List<Attachment> = message.attachments.toPointersWithinLimit()
val messageRanges: BodyRangeList? = if (message.bodyRanges.isNotEmpty()) message.bodyRanges.asSequence().take(BODY_RANGE_PROCESSING_LIMIT).filter { Util.allAreNull(it.mentionAci, it.mentionAciBinary) }.toList().toBodyRangeList() else null
@@ -938,7 +938,7 @@ object DataMessageProcessor {
val mediaMessage = IncomingMessage(
type = MessageType.NORMAL,
from = senderRecipient.id,
sentTimeMillis = envelope.timestamp!!,
sentTimeMillis = envelope.clientTimestamp!!,
serverTimeMillis = envelope.serverTimestamp!!,
receivedTimeMillis = receivedTime,
expiresIn = message.expireTimerDuration.inWholeMilliseconds,
@@ -1018,7 +1018,7 @@ object DataMessageProcessor {
localMetrics: SignalLocalMetrics.MessageReceive?,
batchCache: BatchCache
): InsertResult? {
log(envelope.timestamp!!, "Text message.")
log(envelope.clientTimestamp!!, "Text message.")
val body = message.body ?: ""
@@ -1029,7 +1029,7 @@ object DataMessageProcessor {
val textMessage = IncomingMessage(
type = MessageType.NORMAL,
from = senderRecipient.id,
sentTimeMillis = envelope.timestamp!!,
sentTimeMillis = envelope.clientTimestamp!!,
serverTimeMillis = envelope.serverTimestamp!!,
receivedTimeMillis = receivedTime,
body = body,
@@ -1058,15 +1058,15 @@ object DataMessageProcessor {
senderRecipientId: RecipientId,
groupId: GroupId.V2?
) {
log(envelope.timestamp!!, "Group call update message.")
log(envelope.clientTimestamp!!, "Group call update message.")
if (groupId == null) {
warn(envelope.timestamp!!, "Invalid group for group call update message")
warn(envelope.clientTimestamp!!, "Invalid group for group call update message")
return
}
if (!SignalDatabase.groups.groupExists(groupId)) {
warn(envelope.timestamp!!, "Received group call update message for unknown groupId: $groupId")
warn(envelope.clientTimestamp!!, "Received group call update message for unknown groupId: $groupId")
return
}
@@ -1091,7 +1091,7 @@ object DataMessageProcessor {
groupId: GroupId.V2?,
receivedTime: Long
): InsertResult? {
log(envelope.timestamp!!, "Handle poll creation")
log(envelope.clientTimestamp!!, "Handle poll creation")
val poll: DataMessage.PollCreate = message.pollCreate!!
handlePossibleExpirationUpdate(envelope, metadata, senderRecipient, threadRecipient, groupId, message.expireTimerDuration, message.expireTimerVersion, receivedTime)
@@ -1099,28 +1099,28 @@ object DataMessageProcessor {
if (groupId != null) {
val groupRecord = SignalDatabase.groups.getGroup(groupId).orNull()
if (groupRecord != null && !groupRecord.members.contains(senderRecipient.id)) {
warn(envelope.timestamp!!, "[handlePollCreate] Poll author is not in the group. author $senderRecipient")
warn(envelope.clientTimestamp!!, "[handlePollCreate] Poll author is not in the group. author $senderRecipient")
return null
}
} else if (senderRecipient.id != threadRecipient.id && senderRecipient.id != Recipient.self().id) {
warn(envelope.timestamp!!, "[handlePollCreate] Sender is not a part of the 1:1 thread!")
warn(envelope.clientTimestamp!!, "[handlePollCreate] Sender is not a part of the 1:1 thread!")
return null
}
if (poll.question == null || poll.question!!.isEmpty() || poll.question!!.length > POLL_QUESTION_CHARACTER_LIMIT) {
warn(envelope.timestamp!!, "[handlePollCreate] Poll question is invalid.")
warn(envelope.clientTimestamp!!, "[handlePollCreate] Poll question is invalid.")
return null
}
if (poll.options.isEmpty() || poll.options.size > POLL_OPTIONS_LIMIT || poll.options.any { it.isEmpty() || it.length > POLL_CHARACTER_LIMIT }) {
warn(envelope.timestamp!!, "[handlePollCreate] Poll option is invalid.")
warn(envelope.clientTimestamp!!, "[handlePollCreate] Poll option is invalid.")
return null
}
val pollMessage = IncomingMessage(
type = MessageType.NORMAL,
from = senderRecipient.id,
sentTimeMillis = envelope.timestamp!!,
sentTimeMillis = envelope.clientTimestamp!!,
serverTimeMillis = envelope.serverTimestamp!!,
receivedTimeMillis = receivedTime,
groupId = groupId,
@@ -1159,7 +1159,7 @@ object DataMessageProcessor {
val pollTerminate: DataMessage.PollTerminate = message.pollTerminate!!
val targetSentTimestamp = pollTerminate.targetSentTimestamp!!
log(envelope.timestamp!!, "Handle poll termination for poll $targetSentTimestamp")
log(envelope.clientTimestamp!!, "Handle poll termination for poll $targetSentTimestamp")
handlePossibleExpirationUpdate(envelope, metadata, senderRecipient, threadRecipient, groupId, message.expireTimerDuration, message.expireTimerVersion, receivedTime)
@@ -1170,14 +1170,14 @@ object DataMessageProcessor {
val poll = SignalDatabase.polls.getPoll(messageId.id)
if (poll == null) {
warn(envelope.timestamp!!, "[handlePollTerminate] Poll was not found. timestamp: $targetSentTimestamp author: ${senderRecipient.id}")
warn(envelope.clientTimestamp!!, "[handlePollTerminate] Poll was not found. timestamp: $targetSentTimestamp author: ${senderRecipient.id}")
return null
}
val pollMessage = IncomingMessage(
type = MessageType.POLL_TERMINATE,
from = senderRecipient.id,
sentTimeMillis = envelope.timestamp!!,
sentTimeMillis = envelope.clientTimestamp!!,
serverTimeMillis = envelope.serverTimestamp!!,
receivedTimeMillis = receivedTime,
groupId = groupId,
@@ -1207,11 +1207,11 @@ object DataMessageProcessor {
val pollVote: DataMessage.PollVote = message.pollVote!!
val targetSentTimestamp = pollVote.targetSentTimestamp!!
log(envelope.timestamp!!, "Handle poll vote for poll $targetSentTimestamp")
log(envelope.clientTimestamp!!, "Handle poll vote for poll $targetSentTimestamp")
val targetAuthorServiceId: ServiceId = ServiceId.parseOrThrow(pollVote.targetAuthorAciBinary!!)
if (targetAuthorServiceId.isUnknown) {
warn(envelope.timestamp!!, "[handlePollVote] Vote was to an unknown UUID! Ignoring the message.")
warn(envelope.clientTimestamp!!, "[handlePollVote] Vote was to an unknown UUID! Ignoring the message.")
return null
}
@@ -1223,30 +1223,30 @@ object DataMessageProcessor {
val targetMessage = SignalDatabase.messages.getMessageRecord(messageId.id)
val pollId = SignalDatabase.polls.getPollId(messageId.id)
if (pollId == null) {
warn(envelope.timestamp!!, "[handlePollVote] Poll was not found. timestamp: $targetSentTimestamp author: ${senderRecipient.id}")
warn(envelope.clientTimestamp!!, "[handlePollVote] Poll was not found. timestamp: $targetSentTimestamp author: ${senderRecipient.id}")
return null
}
val existingVoteCount = SignalDatabase.polls.getCurrentPollVoteCount(pollId, senderRecipient.id.toLong())
val currentVoteCount = pollVote.voteCount?.toLong() ?: 0
if (currentVoteCount <= existingVoteCount) {
warn(envelope.timestamp!!, "[handlePollVote] Incoming vote count was not higher. timestamp: $targetSentTimestamp author: ${senderRecipient.id}")
warn(envelope.clientTimestamp!!, "[handlePollVote] Incoming vote count was not higher. timestamp: $targetSentTimestamp author: ${senderRecipient.id}")
return null
}
val allOptionIds = SignalDatabase.polls.getPollOptionIds(pollId)
if (pollVote.optionIndexes.any { it < 0 || it >= allOptionIds.size }) {
warn(envelope.timestamp!!, "[handlePollVote] Invalid option indexes. timestamp: $targetSentTimestamp author: ${senderRecipient.id}")
warn(envelope.clientTimestamp!!, "[handlePollVote] Invalid option indexes. timestamp: $targetSentTimestamp author: ${senderRecipient.id}")
return null
}
if (!SignalDatabase.polls.canAllowMultipleVotes(pollId) && pollVote.optionIndexes.size > 1) {
warn(envelope.timestamp!!, "[handlePollVote] Can not vote multiple times. timestamp: $targetSentTimestamp author: ${senderRecipient.id}")
warn(envelope.clientTimestamp!!, "[handlePollVote] Can not vote multiple times. timestamp: $targetSentTimestamp author: ${senderRecipient.id}")
return null
}
if (SignalDatabase.polls.hasEnded(pollId)) {
warn(envelope.timestamp!!, "[handlePollVote] Poll has already ended. timestamp: $targetSentTimestamp author: ${senderRecipient.id}")
warn(envelope.clientTimestamp!!, "[handlePollVote] Poll has already ended. timestamp: $targetSentTimestamp author: ${senderRecipient.id}")
return null
}
@@ -1274,13 +1274,13 @@ object DataMessageProcessor {
earlyMessageCacheEntry: EarlyMessageCacheEntry? = null
): InsertResult? {
val pinMessage = message.pinMessage!!
log(envelope.timestamp!!, "[handlePinMessage] Pin message for " + pinMessage.targetSentTimestamp)
log(envelope.clientTimestamp!!, "[handlePinMessage] Pin message for " + pinMessage.targetSentTimestamp)
handlePossibleExpirationUpdate(envelope, metadata, senderRecipient, threadRecipient, groupId, message.expireTimerDuration, message.expireTimerVersion, receivedTime)
val targetAuthorServiceId: ServiceId = ACI.parseOrThrow(pinMessage.targetAuthorAciBinary!!)
if (targetAuthorServiceId.isUnknown) {
warn(envelope.timestamp!!, "[handlePinMessage] Unknown target author! Ignoring the message.")
warn(envelope.clientTimestamp!!, "[handlePinMessage] Unknown target author! Ignoring the message.")
return null
}
@@ -1288,7 +1288,7 @@ object DataMessageProcessor {
val targetMessage: MmsMessageRecord? = SignalDatabase.messages.getMessageFor(pinMessage.targetSentTimestamp!!, targetAuthor.id) as? MmsMessageRecord
if (targetMessage == null) {
warn(envelope.timestamp!!, "[handlePinMessage] Could not find matching message! Putting it in the early message cache. timestamp: ${pinMessage.targetSentTimestamp}")
warn(envelope.clientTimestamp!!, "[handlePinMessage] Could not find matching message! Putting it in the early message cache. timestamp: ${pinMessage.targetSentTimestamp}")
if (earlyMessageCacheEntry != null) {
AppDependencies.earlyMessageCache.store(targetAuthor.id, pinMessage.targetSentTimestamp!!, earlyMessageCacheEntry)
PushProcessEarlyMessagesJob.enqueue()
@@ -1297,38 +1297,38 @@ object DataMessageProcessor {
}
if (targetMessage.isRemoteDelete) {
warn(envelope.timestamp!!, "[handlePinMessage] Found a matching message, but it's flagged as remotely deleted. timestamp: ${pinMessage.targetSentTimestamp}")
warn(envelope.clientTimestamp!!, "[handlePinMessage] Found a matching message, but it's flagged as remotely deleted. timestamp: ${pinMessage.targetSentTimestamp}")
return null
}
if (targetMessage.hasGiftBadge()) {
warn(envelope.timestamp!!, "[handlePinMessage] Cannot pin a gift badge")
warn(envelope.clientTimestamp!!, "[handlePinMessage] Cannot pin a gift badge")
return null
}
val targetThread = SignalDatabase.threads.getThreadRecord(targetMessage.threadId)
if (targetThread == null) {
warn(envelope.timestamp!!, "[handlePinMessage] Could not find a thread for the message! timestamp: ${pinMessage.targetSentTimestamp}")
warn(envelope.clientTimestamp!!, "[handlePinMessage] Could not find a thread for the message! timestamp: ${pinMessage.targetSentTimestamp}")
return null
}
if (targetThread.recipient.id != threadRecipient.id) {
warn(envelope.timestamp!!, "[handlePinMessage] Target message is in a different thread than the thread recipient! timestamp: ${pinMessage.targetSentTimestamp}")
warn(envelope.clientTimestamp!!, "[handlePinMessage] Target message is in a different thread than the thread recipient! timestamp: ${pinMessage.targetSentTimestamp}")
return null
}
val groupRecord = SignalDatabase.groups.getGroup(threadRecipient.id).orNull()
if (groupRecord != null && !groupRecord.members.contains(senderRecipient.id)) {
warn(envelope.timestamp!!, "[handlePinMessage] Sender is not in the group! timestamp: ${pinMessage.targetSentTimestamp}")
warn(envelope.clientTimestamp!!, "[handlePinMessage] Sender is not in the group! timestamp: ${pinMessage.targetSentTimestamp}")
return null
}
if (groupRecord != null && groupRecord.attributesAccessControl == GroupAccessControl.ONLY_ADMINS && !groupRecord.isAdmin(senderRecipient)) {
warn(envelope.timestamp!!, "[handlePinMessage] Sender needs to be an admin! timestamp: ${pinMessage.targetSentTimestamp}")
warn(envelope.clientTimestamp!!, "[handlePinMessage] Sender needs to be an admin! timestamp: ${pinMessage.targetSentTimestamp}")
return null
}
if (groupRecord == null && senderRecipient.id != threadRecipient.id && Recipient.self().id != senderRecipient.id) {
warn(envelope.timestamp!!, "[handlePinMessage] Sender is not a part of the 1:1 thread! timestamp: ${pinMessage.targetSentTimestamp}")
warn(envelope.clientTimestamp!!, "[handlePinMessage] Sender is not a part of the 1:1 thread! timestamp: ${pinMessage.targetSentTimestamp}")
return null
}
@@ -1337,7 +1337,7 @@ object DataMessageProcessor {
val pinnedMessage = IncomingMessage(
type = MessageType.PINNED_MESSAGE,
from = senderRecipient.id,
sentTimeMillis = envelope.timestamp!!,
sentTimeMillis = envelope.clientTimestamp!!,
serverTimeMillis = envelope.serverTimestamp!!,
receivedTimeMillis = receivedTime,
expiresIn = message.expireTimerDuration.inWholeMilliseconds,
@@ -1350,7 +1350,7 @@ object DataMessageProcessor {
val insertResult: InsertResult? = SignalDatabase.messages.insertMessageInbox(pinnedMessage).orNull()
return if (insertResult != null) {
log(envelope.timestamp!!, "Inserted a pinned message update at ${insertResult.messageId}")
log(envelope.clientTimestamp!!, "Inserted a pinned message update at ${insertResult.messageId}")
if (duration != MessageTable.PIN_FOREVER) {
AppDependencies.pinnedMessageManager.scheduleIfNecessary()
}
@@ -1368,11 +1368,11 @@ object DataMessageProcessor {
earlyMessageCacheEntry: EarlyMessageCacheEntry? = null
): MessageId? {
val unpinMessage = message.unpinMessage!!
log(envelope.timestamp!!, "[handleUnpinMessage] Unpin message for ${unpinMessage.targetSentTimestamp}")
log(envelope.clientTimestamp!!, "[handleUnpinMessage] Unpin message for ${unpinMessage.targetSentTimestamp}")
val targetAuthorServiceId: ServiceId = ACI.parseOrThrow(unpinMessage.targetAuthorAciBinary!!)
if (targetAuthorServiceId.isUnknown) {
warn(envelope.timestamp!!, "[handleUnpinMessage] Unknown target author! Ignoring the message.")
warn(envelope.clientTimestamp!!, "[handleUnpinMessage] Unknown target author! Ignoring the message.")
return null
}
@@ -1380,7 +1380,7 @@ object DataMessageProcessor {
val targetMessage: MmsMessageRecord? = SignalDatabase.messages.getMessageFor(unpinMessage.targetSentTimestamp!!, targetAuthor.id) as? MmsMessageRecord
if (targetMessage == null) {
warn(envelope.timestamp!!, "[handleUnpinMessage] Could not find matching message! Putting it in the early message cache. timestamp: ${unpinMessage.targetSentTimestamp}")
warn(envelope.clientTimestamp!!, "[handleUnpinMessage] Could not find matching message! Putting it in the early message cache. timestamp: ${unpinMessage.targetSentTimestamp}")
if (earlyMessageCacheEntry != null) {
AppDependencies.earlyMessageCache.store(targetAuthor.id, unpinMessage.targetSentTimestamp!!, earlyMessageCacheEntry)
PushProcessEarlyMessagesJob.enqueue()
@@ -1389,38 +1389,38 @@ object DataMessageProcessor {
}
if (targetMessage.isRemoteDelete) {
warn(envelope.timestamp!!, "[handleUnpinMessage] Found a matching message, but it's flagged as remotely deleted. timestamp: ${unpinMessage.targetSentTimestamp}")
warn(envelope.clientTimestamp!!, "[handleUnpinMessage] Found a matching message, but it's flagged as remotely deleted. timestamp: ${unpinMessage.targetSentTimestamp}")
return null
}
if (targetMessage.hasGiftBadge()) {
warn(envelope.timestamp!!, "[handleUnpinMessage] Cannot pin a gift badge")
warn(envelope.clientTimestamp!!, "[handleUnpinMessage] Cannot pin a gift badge")
return null
}
val targetThread = SignalDatabase.threads.getThreadRecord(targetMessage.threadId)
if (targetThread == null) {
warn(envelope.timestamp!!, "[handleUnpinMessage] Could not find a thread for the message! timestamp: ${unpinMessage.targetSentTimestamp}")
warn(envelope.clientTimestamp!!, "[handleUnpinMessage] Could not find a thread for the message! timestamp: ${unpinMessage.targetSentTimestamp}")
return null
}
if (targetThread.recipient.id != threadRecipient.id) {
warn(envelope.timestamp!!, "[handleUnpinMessage] Target message is in a different thread than the thread recipient! timestamp: ${unpinMessage.targetSentTimestamp}")
warn(envelope.clientTimestamp!!, "[handleUnpinMessage] Target message is in a different thread than the thread recipient! timestamp: ${unpinMessage.targetSentTimestamp}")
return null
}
val groupRecord = SignalDatabase.groups.getGroup(threadRecipient.id).orNull()
if (groupRecord != null && !groupRecord.members.contains(senderRecipient.id)) {
warn(envelope.timestamp!!, "[handleUnpinMessage] Sender is not in the group! timestamp: ${unpinMessage.targetSentTimestamp}")
warn(envelope.clientTimestamp!!, "[handleUnpinMessage] Sender is not in the group! timestamp: ${unpinMessage.targetSentTimestamp}")
return null
}
if (groupRecord != null && groupRecord.attributesAccessControl == GroupAccessControl.ONLY_ADMINS && !groupRecord.isAdmin(senderRecipient)) {
warn(envelope.timestamp!!, "[handleUnpinMessage] Sender needs to be an admin! timestamp: ${unpinMessage.targetSentTimestamp}")
warn(envelope.clientTimestamp!!, "[handleUnpinMessage] Sender needs to be an admin! timestamp: ${unpinMessage.targetSentTimestamp}")
return null
}
if (groupRecord == null && senderRecipient.id != threadRecipient.id && Recipient.self().id != senderRecipient.id) {
warn(envelope.timestamp!!, "[handleUnpinMessage] Sender is not a part of the 1:1 thread! timestamp: ${unpinMessage.targetSentTimestamp}")
warn(envelope.clientTimestamp!!, "[handleUnpinMessage] Sender is not a part of the 1:1 thread! timestamp: ${unpinMessage.targetSentTimestamp}")
return null
}
@@ -1432,25 +1432,25 @@ object DataMessageProcessor {
fun handleAdminRemoteDelete(context: Context, envelope: Envelope, message: DataMessage, senderRecipient: Recipient, threadRecipient: Recipient, earlyMessageCacheEntry: EarlyMessageCacheEntry?): MessageId? {
if (!RemoteConfig.receiveAdminDelete) {
log(envelope.timestamp!!, "Admin delete is not allowed due to remote config.")
log(envelope.clientTimestamp!!, "Admin delete is not allowed due to remote config.")
return null
}
val delete = message.adminDelete!!
log(envelope.timestamp!!, "Admin delete for message ${delete.targetSentTimestamp}")
log(envelope.clientTimestamp!!, "Admin delete for message ${delete.targetSentTimestamp}")
val targetSentTimestamp: Long = delete.targetSentTimestamp!!
val targetAuthorServiceId: ServiceId = ACI.parseOrThrow(delete.targetAuthorAciBinary!!)
if (targetAuthorServiceId.isUnknown) {
warn(envelope.timestamp!!, "[handleAdminRemoteDelete] Invalid author.")
warn(envelope.clientTimestamp!!, "[handleAdminRemoteDelete] Invalid author.")
return null
}
val targetAuthor = Recipient.externalPush(targetAuthorServiceId)
val targetMessage: MessageRecord? = SignalDatabase.messages.getMessageFor(targetSentTimestamp, targetAuthor.id)
if (targetMessage == null) {
warn(envelope.timestamp!!, "[handleAdminRemoteDelete] Could not find matching message! timestamp: $targetSentTimestamp")
warn(envelope.clientTimestamp!!, "[handleAdminRemoteDelete] Could not find matching message! timestamp: $targetSentTimestamp")
if (earlyMessageCacheEntry != null) {
AppDependencies.earlyMessageCache.store(targetAuthor.id, targetSentTimestamp, earlyMessageCacheEntry)
PushProcessEarlyMessagesJob.enqueue()
@@ -1460,19 +1460,19 @@ object DataMessageProcessor {
val targetThread = SignalDatabase.threads.getThreadRecord(targetMessage.threadId)
if (targetThread == null) {
warn(envelope.timestamp!!, "[handleAdminRemoteDelete] Could not find a thread for the message! timestamp: $targetSentTimestamp author: ${targetAuthor.id}")
warn(envelope.clientTimestamp!!, "[handleAdminRemoteDelete] Could not find a thread for the message! timestamp: $targetSentTimestamp author: ${targetAuthor.id}")
return null
}
val targetThreadRecipientId = targetThread.recipient.id
if (targetThreadRecipientId != threadRecipient.id) {
warn(envelope.timestamp!!, "[handleAdminRemoteDelete] Target message is in a different thread than the admin delete! timestamp: $targetSentTimestamp")
warn(envelope.clientTimestamp!!, "[handleAdminRemoteDelete] Target message is in a different thread than the admin delete! timestamp: $targetSentTimestamp")
return null
}
val groupRecord = SignalDatabase.groups.getGroup(targetThreadRecipientId).orNull()
if (groupRecord == null || !groupRecord.isV2Group) {
warn(envelope.timestamp!!, "[handleAdminRemoteDelete] Invalid group.")
warn(envelope.clientTimestamp!!, "[handleAdminRemoteDelete] Invalid group.")
return null
}
@@ -1481,7 +1481,7 @@ object DataMessageProcessor {
AppDependencies.messageNotifier.updateNotification(context, ConversationId.fromMessageRecord(targetMessage))
MessageId(targetMessage.id)
} else {
warn(envelope.timestamp!!, "[handleAdminRemoteDelete] Invalid admin delete! deleteTime: ${envelope.serverTimestamp!!}, targetTime: ${targetMessage.serverTimestamp}, deleteAuthor: ${senderRecipient.id}, targetAuthor: ${targetMessage.fromRecipient.id}, isAdmin: ${groupRecord.isAdmin(senderRecipient)}")
warn(envelope.clientTimestamp!!, "[handleAdminRemoteDelete] Invalid admin delete! deleteTime: ${envelope.serverTimestamp!!}, targetTime: ${targetMessage.serverTimestamp}, deleteAuthor: ${senderRecipient.id}, targetAuthor: ${targetMessage.fromRecipient.id}, isAdmin: ${groupRecord.isAdmin(senderRecipient)}")
null
}
}
@@ -1627,7 +1627,7 @@ object DataMessageProcessor {
): MessageId? {
val targetMessage = SignalDatabase.messages.getMessageFor(targetSentTimestamp, targetAuthor.id)
if (targetMessage == null) {
warn(envelope.timestamp!!, "[handlePollValidation] Could not find matching message! Putting it in the early message cache. timestamp: $targetSentTimestamp author: ${targetAuthor.id}")
warn(envelope.clientTimestamp!!, "[handlePollValidation] Could not find matching message! Putting it in the early message cache. timestamp: $targetSentTimestamp author: ${targetAuthor.id}")
if (earlyMessageCacheEntry != null) {
AppDependencies.earlyMessageCache.store(senderRecipient.id, targetSentTimestamp, earlyMessageCacheEntry)
PushProcessEarlyMessagesJob.enqueue()
@@ -1636,22 +1636,22 @@ object DataMessageProcessor {
}
if (targetMessage.isRemoteDelete) {
warn(envelope.timestamp!!, "[handlePollValidation] Found a matching message, but it's flagged as remotely deleted. timestamp: $targetSentTimestamp author: ${targetAuthor.id}")
warn(envelope.clientTimestamp!!, "[handlePollValidation] Found a matching message, but it's flagged as remotely deleted. timestamp: $targetSentTimestamp author: ${targetAuthor.id}")
return null
}
val targetThread = SignalDatabase.threads.getThreadRecord(targetMessage.threadId)
if (targetThread == null) {
warn(envelope.timestamp!!, "[handlePollValidation] Could not find a thread for the message. timestamp: $targetSentTimestamp author: ${targetAuthor.id}")
warn(envelope.clientTimestamp!!, "[handlePollValidation] Could not find a thread for the message. timestamp: $targetSentTimestamp author: ${targetAuthor.id}")
return null
}
val groupRecord = SignalDatabase.groups.getGroup(targetThread.recipient.id).orNull()
if (groupRecord != null && !groupRecord.members.contains(senderRecipient.id)) {
warn(envelope.timestamp!!, "[handlePollValidation] Sender is not in the group. timestamp: $targetSentTimestamp author: ${targetAuthor.id}")
warn(envelope.clientTimestamp!!, "[handlePollValidation] Sender is not in the group. timestamp: $targetSentTimestamp author: ${targetAuthor.id}")
return null
} else if (groupRecord == null && senderRecipient.id != targetThread.recipient.id && senderRecipient.id != Recipient.self().id) {
warn(envelope.timestamp!!, "[handlePollValidation] Sender is not a part of the 1:1 thread!")
warn(envelope.clientTimestamp!!, "[handlePollValidation] Sender is not a part of the 1:1 thread!")
return null
}

View File

@@ -50,13 +50,13 @@ object EditMessageProcessor {
) {
val editMessage = content.editMessage!!
log(envelope.timestamp!!, "[handleEditMessage] Edit message for " + editMessage.targetSentTimestamp)
log(envelope.clientTimestamp!!, "[handleEditMessage] Edit message for " + editMessage.targetSentTimestamp)
var targetMessage: MmsMessageRecord? = SignalDatabase.messages.getMessageFor(editMessage.targetSentTimestamp!!, senderRecipient.id) as? MmsMessageRecord
val targetThreadRecipient: Recipient? = if (targetMessage != null) SignalDatabase.threads.getRecipientForThreadId(targetMessage.threadId) else null
if (targetMessage == null || targetThreadRecipient == null) {
warn(envelope.timestamp!!, "[handleEditMessage] Could not find matching message! timestamp: ${editMessage.targetSentTimestamp} author: ${senderRecipient.id}")
warn(envelope.clientTimestamp!!, "[handleEditMessage] Could not find matching message! timestamp: ${editMessage.targetSentTimestamp} author: ${senderRecipient.id}")
if (earlyMessageCacheEntry != null) {
AppDependencies.earlyMessageCache.store(senderRecipient.id, editMessage.targetSentTimestamp!!, earlyMessageCacheEntry)
@@ -78,12 +78,12 @@ object EditMessageProcessor {
val validTarget = !originalMessage.isViewOnce && !originalMessage.hasAudio() && !originalMessage.hasSharedContact()
if (!validTiming || !validAuthor || !validGroup || !validTarget) {
warn(envelope.timestamp!!, "[handleEditMessage] Invalid message edit! editTime: ${envelope.serverTimestamp}, targetTime: ${originalMessage.serverTimestamp}, editAuthor: ${senderRecipient.id}, targetAuthor: ${originalMessage.fromRecipient.id}, editThread: ${threadRecipient.id}, targetThread: ${targetThreadRecipient.id}, validity: (timing: $validTiming, author: $validAuthor, group: $validGroup, target: $validTarget)")
warn(envelope.clientTimestamp!!, "[handleEditMessage] Invalid message edit! editTime: ${envelope.serverTimestamp}, targetTime: ${originalMessage.serverTimestamp}, editAuthor: ${senderRecipient.id}, targetAuthor: ${originalMessage.fromRecipient.id}, editThread: ${threadRecipient.id}, targetThread: ${targetThreadRecipient.id}, validity: (timing: $validTiming, author: $validAuthor, group: $validGroup, target: $validTarget)")
return
}
if (groupId != null && MessageContentProcessor.handleGv2PreProcessing(context, envelope.timestamp!!, content, metadata, groupId, message.groupV2!!, senderRecipient) == MessageContentProcessor.Gv2PreProcessResult.IGNORE) {
warn(envelope.timestamp!!, "[handleEditMessage] Group processor indicated we should ignore this.")
if (groupId != null && MessageContentProcessor.handleGv2PreProcessing(context, envelope.clientTimestamp!!, content, metadata, groupId, message.groupV2!!, senderRecipient) == MessageContentProcessor.Gv2PreProcessResult.IGNORE) {
warn(envelope.clientTimestamp!!, "[handleEditMessage] Group processor indicated we should ignore this.")
return
}
@@ -187,8 +187,8 @@ object EditMessageProcessor {
val textMessage = IncomingMessage(
type = MessageType.NORMAL,
from = senderRecipientId,
sentTimeMillis = envelope.timestamp!!,
serverTimeMillis = envelope.timestamp!!,
sentTimeMillis = envelope.clientTimestamp!!,
serverTimeMillis = envelope.clientTimestamp!!,
receivedTimeMillis = targetMessage.dateReceived,
body = message.body,
groupId = groupId,

View File

@@ -291,8 +291,8 @@ class IncomingMessageObserver(
null
}
Envelope.Type.PREKEY_BUNDLE,
Envelope.Type.CIPHERTEXT,
Envelope.Type.PREKEY_MESSAGE,
Envelope.Type.DOUBLE_RATCHET,
Envelope.Type.UNIDENTIFIED_SENDER,
Envelope.Type.PLAINTEXT_CONTENT -> {
SignalTrace.beginSection("IncomingMessageObserver#processMessage")
@@ -343,7 +343,7 @@ class IncomingMessageObserver(
jobs += PushProcessMessageErrorJob(
result.toMessageState(),
result.errorMetadata.toExceptionMetadata(),
result.envelope.timestamp!!
result.envelope.clientTimestamp!!
)
AppDependencies.jobManager.startChain(jobs)
@@ -369,9 +369,9 @@ class IncomingMessageObserver(
val senderId = RecipientId.from(serviceId)
Log.i(TAG, "Received server receipt. Sender: $senderId, Device: ${envelope.sourceDevice}, Timestamp: ${envelope.timestamp}")
SignalDatabase.messages.incrementDeliveryReceiptCount(envelope.timestamp!!, senderId, System.currentTimeMillis())
SignalDatabase.messageLog.deleteEntryForRecipient(envelope.timestamp!!, senderId, envelope.sourceDevice!!)
Log.i(TAG, "Received server receipt. Sender: $senderId, Device: ${envelope.sourceDeviceId}, Timestamp: ${envelope.clientTimestamp}")
SignalDatabase.messages.incrementDeliveryReceiptCount(envelope.clientTimestamp!!, senderId, System.currentTimeMillis())
SignalDatabase.messageLog.deleteEntryForRecipient(envelope.clientTimestamp!!, senderId, envelope.sourceDeviceId!!)
}
private fun MessageDecryptor.Result.toMessageState(): MessageState {

View File

@@ -350,11 +350,11 @@ open class MessageContentProcessor(private val context: Context) {
val earlyCacheEntries: List<EarlyMessageCacheEntry>? = AppDependencies
.earlyMessageCache
.retrieve(senderRecipient.id, envelope.timestamp!!)
.retrieve(senderRecipient.id, envelope.clientTimestamp!!)
.orNull()
if (!processingEarlyContent && earlyCacheEntries != null) {
log(envelope.timestamp!!, "Found " + earlyCacheEntries.size + " dependent item(s) that were retrieved earlier. Processing.")
log(envelope.clientTimestamp!!, "Found " + earlyCacheEntries.size + " dependent item(s) that were retrieved earlier. Processing.")
for (entry in earlyCacheEntries) {
handleMessage(senderRecipient, entry.envelope, entry.content, entry.metadata, entry.serverDeliveredTimestamp, processingEarlyContent = true, localMetric = null, batchCache)
}
@@ -442,14 +442,14 @@ open class MessageContentProcessor(private val context: Context) {
val threadRecipient = getMessageDestination(content, senderRecipient)
if (shouldIgnore(content, senderRecipient, threadRecipient)) {
log(envelope.timestamp!!, "Ignoring message.")
log(envelope.clientTimestamp!!, "Ignoring message.")
return
}
val pending: PendingRetryReceiptModel? = AppDependencies.pendingRetryReceiptCache.get(senderRecipient.id, envelope.timestamp!!)
val receivedTime: Long = handlePendingRetry(pending, envelope.timestamp!!, threadRecipient)
val pending: PendingRetryReceiptModel? = AppDependencies.pendingRetryReceiptCache.get(senderRecipient.id, envelope.clientTimestamp!!)
val receivedTime: Long = handlePendingRetry(pending, envelope.clientTimestamp!!, threadRecipient)
log(envelope.timestamp!!, "Beginning message processing. Sender: " + formatSender(senderRecipient.id, metadata.sourceServiceId, metadata.sourceDeviceId))
log(envelope.clientTimestamp!!, "Beginning message processing. Sender: " + formatSender(senderRecipient.id, metadata.sourceServiceId, metadata.sourceDeviceId))
localMetric?.onPreProcessComplete()
when {
content.dataMessage != null -> {
@@ -482,12 +482,12 @@ open class MessageContentProcessor(private val context: Context) {
}
content.callMessage != null -> {
log(envelope.timestamp!!, "Got call message...")
log(envelope.clientTimestamp!!, "Got call message...")
val message: CallMessage = content.callMessage!!
if (message.destinationDeviceId != null && message.destinationDeviceId != SignalStore.account.deviceId) {
log(envelope.timestamp!!, "Ignoring call message that is not for this device! intended: ${message.destinationDeviceId}, this: ${SignalStore.account.deviceId}")
log(envelope.clientTimestamp!!, "Ignoring call message that is not for this device! intended: ${message.destinationDeviceId}, this: ${SignalStore.account.deviceId}")
return
}
@@ -541,12 +541,12 @@ open class MessageContentProcessor(private val context: Context) {
}
else -> {
warn(envelope.timestamp!!, "Got unrecognized message!")
warn(envelope.clientTimestamp!!, "Got unrecognized message!")
}
}
if (pending != null) {
warn(envelope.timestamp!!, "Pending retry was processed. Deleting.")
warn(envelope.clientTimestamp!!, "Pending retry was processed. Deleting.")
AppDependencies.pendingRetryReceiptCache.delete(pending)
}
}
@@ -565,7 +565,7 @@ open class MessageContentProcessor(private val context: Context) {
val threadId: Long = if (typingMessage.groupId != null) {
val groupId = GroupId.push(typingMessage.groupId!!)
if (!SignalDatabase.groups.isCurrentMember(groupId, senderRecipient.id)) {
warn(envelope.timestamp!!, "Seen typing indicator for non-member " + senderRecipient.id)
warn(envelope.clientTimestamp!!, "Seen typing indicator for non-member " + senderRecipient.id)
return
}
@@ -576,7 +576,7 @@ open class MessageContentProcessor(private val context: Context) {
}
if (threadId <= 0) {
warn(envelope.timestamp!!, "Couldn't find a matching thread for a typing message.")
warn(envelope.clientTimestamp!!, "Couldn't find a matching thread for a typing message.")
return
}
@@ -591,19 +591,19 @@ open class MessageContentProcessor(private val context: Context) {
private fun handleRetryReceipt(envelope: Envelope, metadata: EnvelopeMetadata, decryptionErrorMessage: DecryptionErrorMessage, senderRecipient: Recipient) {
if (!RemoteConfig.retryReceipts) {
warn(envelope.timestamp!!, "[RetryReceipt] Feature flag disabled, skipping retry receipt.")
warn(envelope.clientTimestamp!!, "[RetryReceipt] Feature flag disabled, skipping retry receipt.")
return
}
if (decryptionErrorMessage.deviceId != SignalStore.account.deviceId) {
log(envelope.timestamp!!, "[RetryReceipt] Received a DecryptionErrorMessage targeting a linked device. Ignoring.")
log(envelope.clientTimestamp!!, "[RetryReceipt] Received a DecryptionErrorMessage targeting a linked device. Ignoring.")
return
}
val sentTimestamp = decryptionErrorMessage.timestamp
warn(envelope.timestamp!!, "[RetryReceipt] Received a retry receipt from ${formatSender(senderRecipient.id, metadata.sourceServiceId, metadata.sourceDeviceId)} for message with timestamp $sentTimestamp.")
warn(envelope.clientTimestamp!!, "[RetryReceipt] Received a retry receipt from ${formatSender(senderRecipient.id, metadata.sourceServiceId, metadata.sourceDeviceId)} for message with timestamp $sentTimestamp.")
if (!senderRecipient.hasServiceId) {
warn(envelope.timestamp!!, "[RetryReceipt] Requester ${senderRecipient.id} somehow has no UUID! timestamp: $sentTimestamp")
warn(envelope.clientTimestamp!!, "[RetryReceipt] Requester ${senderRecipient.id} somehow has no UUID! timestamp: $sentTimestamp")
return
}
@@ -626,18 +626,18 @@ open class MessageContentProcessor(private val context: Context) {
val relatedMessage = findRetryReceiptRelatedMessage(messageLogEntry, sentTimestamp)
if (relatedMessage == null) {
warn(envelope.timestamp!!, "[RetryReceipt-SK] The related message could not be found! There shouldn't be any sender key resends where we can't find the related message. Skipping.")
warn(envelope.clientTimestamp!!, "[RetryReceipt-SK] The related message could not be found! There shouldn't be any sender key resends where we can't find the related message. Skipping.")
return
}
val threadRecipient = SignalDatabase.threads.getRecipientForThreadId(relatedMessage.threadId)
if (threadRecipient == null) {
warn(envelope.timestamp!!, "[RetryReceipt-SK] Could not find a thread recipient! Skipping.")
warn(envelope.clientTimestamp!!, "[RetryReceipt-SK] Could not find a thread recipient! Skipping.")
return
}
if (!threadRecipient.isPushV2Group && !threadRecipient.isDistributionList) {
warn(envelope.timestamp!!, "[RetryReceipt-SK] Thread recipient is not a V2 group or distribution list! Skipping.")
warn(envelope.clientTimestamp!!, "[RetryReceipt-SK] Thread recipient is not a V2 group or distribution list! Skipping.")
return
}
@@ -661,7 +661,7 @@ open class MessageContentProcessor(private val context: Context) {
SignalDatabase.senderKeyShared.delete(distributionId, setOf(requesterAddress))
if (messageLogEntry != null) {
warn(envelope.timestamp!!, "[RetryReceipt-SK] Found MSL entry for ${requester.id} ($requesterAddress) with timestamp $sentTimestamp. Scheduling a resend.")
warn(envelope.clientTimestamp!!, "[RetryReceipt-SK] Found MSL entry for ${requester.id} ($requesterAddress) with timestamp $sentTimestamp. Scheduling a resend.")
AppDependencies.jobManager.add(
ResendMessageJob(
messageLogEntry.recipientId,
@@ -674,7 +674,7 @@ open class MessageContentProcessor(private val context: Context) {
)
)
} else {
warn(envelope.timestamp!!, "[RetryReceipt-SK] Unable to find MSL entry for ${requester.id} ($requesterAddress) with timestamp $sentTimestamp for ${if (groupId != null) "group $groupId" else "distribution list"}. Scheduling a job to send them the SenderKeyDistributionMessage. Membership will be checked there.")
warn(envelope.clientTimestamp!!, "[RetryReceipt-SK] Unable to find MSL entry for ${requester.id} ($requesterAddress) with timestamp $sentTimestamp for ${if (groupId != null) "group $groupId" else "distribution list"}. Scheduling a job to send them the SenderKeyDistributionMessage. Membership will be checked there.")
AppDependencies.jobManager.add(SenderKeyDistributionSendJob(requester.id, threadRecipient.id))
}
}
@@ -683,24 +683,24 @@ open class MessageContentProcessor(private val context: Context) {
var archivedSession = false
if (ServiceId.parseOrNull(envelope.destinationServiceId, envelope.destinationServiceIdBinary) is ServiceId.PNI) {
warn(envelope.timestamp!!, "[RetryReceipt-I] Destination is our PNI. Ignoring.")
warn(envelope.clientTimestamp!!, "[RetryReceipt-I] Destination is our PNI. Ignoring.")
return
}
if (decryptionErrorMessage.ratchetKey.isPresent) {
if (ratchetKeyMatches(requester, metadata.sourceDeviceId, decryptionErrorMessage.ratchetKey.get())) {
warn(envelope.timestamp!!, "[RetryReceipt-I] Ratchet key matches. Archiving the session.")
warn(envelope.clientTimestamp!!, "[RetryReceipt-I] Ratchet key matches. Archiving the session.")
AppDependencies.protocolStore.aci().sessions().archiveSession(requester.requireServiceId(), metadata.sourceDeviceId)
archivedSession = true
} else {
log(envelope.timestamp!!, "[RetryReceipt-I] Ratchet key does not match. Leaving the session as-is.")
log(envelope.clientTimestamp!!, "[RetryReceipt-I] Ratchet key does not match. Leaving the session as-is.")
}
} else {
warn(envelope.timestamp!!, "[RetryReceipt-I] Missing ratchet key! Can't archive session.")
warn(envelope.clientTimestamp!!, "[RetryReceipt-I] Missing ratchet key! Can't archive session.")
}
if (messageLogEntry != null) {
warn(envelope.timestamp!!, "[RetryReceipt-I] Found an entry in the MSL. Resending.")
warn(envelope.clientTimestamp!!, "[RetryReceipt-I] Found an entry in the MSL. Resending.")
AppDependencies.jobManager.add(
ResendMessageJob(
messageLogEntry.recipientId,
@@ -713,10 +713,10 @@ open class MessageContentProcessor(private val context: Context) {
)
)
} else if (archivedSession) {
warn(envelope.timestamp!!, "[RetryReceipt-I] Could not find an entry in the MSL, but we archived the session, so we're sending a null message to complete the reset.")
warn(envelope.clientTimestamp!!, "[RetryReceipt-I] Could not find an entry in the MSL, but we archived the session, so we're sending a null message to complete the reset.")
AppDependencies.jobManager.add(NullMessageSendJob(requester.id))
} else {
warn(envelope.timestamp!!, "[RetryReceipt-I] Could not find an entry in the MSL. Skipping.")
warn(envelope.clientTimestamp!!, "[RetryReceipt-I] Could not find an entry in the MSL. Skipping.")
}
}

View File

@@ -142,7 +142,7 @@ object MessageDecryptor {
val followUpOperations: MutableList<FollowUpOperation> = mutableListOf()
if (envelope.type == Envelope.Type.PREKEY_BUNDLE) {
if (envelope.type == Envelope.Type.PREKEY_MESSAGE) {
Log.i(TAG, "${logPrefix(envelope)} Prekey message. Scheduling a prekey sync job.")
followUpOperations += FollowUpOperation {
PreKeysSyncJob.create().asChain()
@@ -164,7 +164,7 @@ object MessageDecryptor {
envelope.newBuilder()
.sourceServiceId(if (BuildConfig.USE_STRING_ID) cipherResult.metadata.sourceServiceId.toString() else null)
.sourceServiceIdBinary(if (RemoteConfig.useBinaryId) cipherResult.metadata.sourceServiceId.toByteString() else null)
.sourceDevice(cipherResult.metadata.sourceDeviceId)
.sourceDeviceId(cipherResult.metadata.sourceDeviceId)
.build()
} else {
envelope
@@ -255,7 +255,7 @@ object MessageDecryptor {
followUpOperations += FollowUpOperation {
Recipient.external(e.sender)?.let {
AutomaticSessionResetJob(it.id, e.senderDevice, envelope.timestamp!!).asChain()
AutomaticSessionResetJob(it.id, e.senderDevice, envelope.clientTimestamp!!).asChain()
} ?: null.logW(TAG, "${logPrefix(envelope, e)} Failed to create a recipient with the provided identifier!")
}
@@ -276,7 +276,7 @@ object MessageDecryptor {
}
is SelfSendException -> {
Log.i(TAG, "[${envelope.timestamp}] Dropping sealed sender message from self!", e)
Log.i(TAG, "[${envelope.clientTimestamp}] Dropping sealed sender message from self!", e)
Result.Ignore(envelope, serverDeliveredTimestamp, followUpOperations.toUnmodifiableList())
}
@@ -320,7 +320,7 @@ object MessageDecryptor {
Log.w(TAG, "${logPrefix(envelope)} Decryption error for a sync message! Enqueuing a session reset job.", true)
followUpOperations += FollowUpOperation {
AutomaticSessionResetJob(sender.id, senderDevice, envelope.timestamp!!).asChain()
AutomaticSessionResetJob(sender.id, senderDevice, envelope.clientTimestamp!!).asChain()
}
return Result.Ignore(envelope, serverDeliveredTimestamp, followUpOperations)
@@ -355,7 +355,7 @@ object MessageDecryptor {
// Note: if the message is sealed sender, it's envelope type will be UNIDENTIFIED_SENDER. The only way we can currently check if the error is
// prekey-related in that situation is using a string match.
if (envelope.type == Envelope.Type.PREKEY_BUNDLE || protocolException.message?.lowercase()?.contains("prekey") == true) {
if (envelope.type == Envelope.Type.PREKEY_MESSAGE || protocolException.message?.lowercase()?.contains("prekey") == true) {
Log.w(TAG, "${logPrefix(envelope, senderServiceId)} Got a decryption error on a prekey message. Forcing a prekey rotation before requesting the retry.", true)
PreKeysSyncJob.create(forceRotationRequested = true).asChain().then(retryJob)
} else {
@@ -392,7 +392,7 @@ object MessageDecryptor {
return@FollowUpOperation null
}
AppDependencies.pendingRetryReceiptCache.insert(sender.id, senderDevice, envelope.timestamp!!, receivedTimestamp, threadId)
AppDependencies.pendingRetryReceiptCache.insert(sender.id, senderDevice, envelope.clientTimestamp!!, receivedTimestamp, threadId)
AppDependencies.pendingRetryReceiptManager.scheduleIfNecessary()
null
}
@@ -491,26 +491,26 @@ object MessageDecryptor {
}
private fun logPrefix(envelope: Envelope): String {
return logPrefix(envelope.timestamp!!, ServiceId.parseOrNull(envelope.sourceServiceId, envelope.sourceServiceIdBinary)?.logString() ?: "<sealed>", envelope.sourceDevice)
return logPrefix(envelope.clientTimestamp!!, ServiceId.parseOrNull(envelope.sourceServiceId, envelope.sourceServiceIdBinary)?.logString() ?: "<sealed>", envelope.sourceDeviceId)
}
private fun logPrefix(envelope: Envelope, sender: ServiceId?): String {
return logPrefix(envelope.timestamp!!, sender?.logString() ?: "?", envelope.sourceDevice)
return logPrefix(envelope.clientTimestamp!!, sender?.logString() ?: "?", envelope.sourceDeviceId)
}
private fun logPrefix(envelope: Envelope, sender: String): String {
return logPrefix(envelope.timestamp!!, ServiceId.parseOrNull(sender)?.logString() ?: "?", envelope.sourceDevice)
return logPrefix(envelope.clientTimestamp!!, ServiceId.parseOrNull(sender)?.logString() ?: "?", envelope.sourceDeviceId)
}
private fun logPrefix(envelope: Envelope, cipherResult: SignalServiceCipherResult): String {
return logPrefix(envelope.timestamp!!, cipherResult.metadata.sourceServiceId.logString(), cipherResult.metadata.sourceDeviceId)
return logPrefix(envelope.clientTimestamp!!, cipherResult.metadata.sourceServiceId.logString(), cipherResult.metadata.sourceDeviceId)
}
private fun logPrefix(envelope: Envelope, exception: ProtocolException): String {
return if (exception.sender != null) {
logPrefix(envelope.timestamp!!, ServiceId.parseOrNull(exception.sender)?.logString() ?: "?", exception.senderDevice)
logPrefix(envelope.clientTimestamp!!, ServiceId.parseOrNull(exception.sender)?.logString() ?: "?", exception.senderDevice)
} else {
logPrefix(envelope.timestamp!!, ServiceId.parseOrNull(envelope.sourceServiceId, envelope.sourceServiceIdBinary).toString(), envelope.sourceDevice)
logPrefix(envelope.clientTimestamp!!, ServiceId.parseOrNull(envelope.sourceServiceId, envelope.sourceServiceIdBinary).toString(), envelope.sourceDeviceId)
}
}
@@ -531,7 +531,7 @@ object MessageDecryptor {
envelopeType = envelope.type!!.value.toCiphertextMessageType()
}
val decryptionErrorMessage: DecryptionErrorMessage = DecryptionErrorMessage.forOriginalMessage(originalContent, envelopeType, envelope.timestamp!!, protocolException.senderDevice)
val decryptionErrorMessage: DecryptionErrorMessage = DecryptionErrorMessage.forOriginalMessage(originalContent, envelopeType, envelope.clientTimestamp!!, protocolException.senderDevice)
val groupId: GroupId? = protocolException.parseGroupId(envelope)
return SendRetryReceiptJob(sender.id, Optional.ofNullable(groupId), decryptionErrorMessage)
}
@@ -541,7 +541,7 @@ object MessageDecryptor {
try {
GroupId.push(this.groupId.get())
} catch (e: BadGroupIdException) {
Log.w(TAG, "[${envelope.timestamp}] Bad groupId!", true)
Log.w(TAG, "[${envelope.clientTimestamp}] Bad groupId!", true)
null
}
} else {
@@ -551,8 +551,8 @@ object MessageDecryptor {
private fun Int.toCiphertextMessageType(): Int {
return when (this) {
Envelope.Type.CIPHERTEXT.value -> CiphertextMessage.WHISPER_TYPE
Envelope.Type.PREKEY_BUNDLE.value -> CiphertextMessage.PREKEY_TYPE
Envelope.Type.DOUBLE_RATCHET.value -> CiphertextMessage.WHISPER_TYPE
Envelope.Type.PREKEY_MESSAGE.value -> CiphertextMessage.PREKEY_TYPE
Envelope.Type.UNIDENTIFIED_SENDER.value -> CiphertextMessage.SENDERKEY_TYPE
Envelope.Type.PLAINTEXT_CONTENT.value -> CiphertextMessage.PLAINTEXT_CONTENT_TYPE
else -> CiphertextMessage.WHISPER_TYPE

View File

@@ -31,7 +31,7 @@ object ReceiptMessageProcessor {
ReceiptMessage.Type.DELIVERY -> handleDeliveryReceipt(envelope, metadata, receiptMessage, senderRecipient.id, batchCache)
ReceiptMessage.Type.READ -> handleReadReceipt(context, senderRecipient.id, envelope, metadata, receiptMessage, earlyMessageCacheEntry, batchCache)
ReceiptMessage.Type.VIEWED -> handleViewedReceipt(context, envelope, metadata, receiptMessage, senderRecipient.id, earlyMessageCacheEntry)
else -> warn(envelope.timestamp!!, "Unknown recipient message type ${receiptMessage.type}")
else -> warn(envelope.clientTimestamp!!, "Unknown recipient message type ${receiptMessage.type}")
}
}
@@ -43,15 +43,15 @@ object ReceiptMessageProcessor {
senderRecipientId: RecipientId,
batchCache: BatchCache
) {
log(envelope.timestamp!!, "Processing delivery receipts. Sender: $senderRecipientId, Device: ${metadata.sourceDeviceId}, Timestamps: ${deliveryReceipt.timestamp.joinToString(", ")}")
log(envelope.clientTimestamp!!, "Processing delivery receipts. Sender: $senderRecipientId, Device: ${metadata.sourceDeviceId}, Timestamps: ${deliveryReceipt.timestamp.joinToString(", ")}")
val stopwatch: Stopwatch? = if (VERBOSE) Stopwatch("delivery-receipt", decimalPlaces = 2) else null
SignalTrace.beginSection("ReceiptMessageProcessor#incrementDeliveryReceiptCounts")
val missingTargetTimestamps: Set<Long> = SignalDatabase.messages.incrementDeliveryReceiptCounts(deliveryReceipt.timestamp, senderRecipientId, envelope.timestamp!!, stopwatch, batchCache.deliveryReceiptLookupCache)
val missingTargetTimestamps: Set<Long> = SignalDatabase.messages.incrementDeliveryReceiptCounts(deliveryReceipt.timestamp, senderRecipientId, envelope.clientTimestamp!!, stopwatch, batchCache.deliveryReceiptLookupCache)
SignalTrace.endSection()
for (targetTimestamp in missingTargetTimestamps) {
warn(envelope.timestamp!!, "[handleDeliveryReceipt] Could not find matching message! targetTimestamp: $targetTimestamp, receiptAuthor: $senderRecipientId")
warn(envelope.clientTimestamp!!, "[handleDeliveryReceipt] Could not find matching message! targetTimestamp: $targetTimestamp, receiptAuthor: $senderRecipientId")
// Early delivery receipts are special-cased in the database methods
}
@@ -79,21 +79,21 @@ object ReceiptMessageProcessor {
batchCache: BatchCache
) {
if (!TextSecurePreferences.isReadReceiptsEnabled(context)) {
log(envelope.timestamp!!, "Ignoring read receipts for IDs: " + readReceipt.timestamp.joinToString(", "))
log(envelope.clientTimestamp!!, "Ignoring read receipts for IDs: " + readReceipt.timestamp.joinToString(", "))
return
}
log(envelope.timestamp!!, "Processing read receipts. Sender: $senderRecipientId, Device: ${metadata.sourceDeviceId}, Timestamps: ${readReceipt.timestamp.joinToString(", ")}")
log(envelope.clientTimestamp!!, "Processing read receipts. Sender: $senderRecipientId, Device: ${metadata.sourceDeviceId}, Timestamps: ${readReceipt.timestamp.joinToString(", ")}")
SignalTrace.beginSection("ReceiptMessageProcessor#incrementReadReceiptCounts")
val missingTargetTimestamps: Set<Long> = SignalDatabase.messages.incrementReadReceiptCounts(readReceipt.timestamp, senderRecipientId, envelope.timestamp!!, batchCache.readReceiptLookupCache)
val missingTargetTimestamps: Set<Long> = SignalDatabase.messages.incrementReadReceiptCounts(readReceipt.timestamp, senderRecipientId, envelope.clientTimestamp!!, batchCache.readReceiptLookupCache)
SignalTrace.endSection()
if (missingTargetTimestamps.isNotEmpty()) {
val selfId = Recipient.self().id
for (targetTimestamp in missingTargetTimestamps) {
warn(envelope.timestamp!!, "[handleReadReceipt] Could not find matching message! targetTimestamp: $targetTimestamp, receiptAuthor: $senderRecipientId | Receipt, so associating with message from self ($selfId)")
warn(envelope.clientTimestamp!!, "[handleReadReceipt] Could not find matching message! targetTimestamp: $targetTimestamp, receiptAuthor: $senderRecipientId | Receipt, so associating with message from self ($selfId)")
if (earlyMessageCacheEntry != null) {
AppDependencies.earlyMessageCache.store(selfId, targetTimestamp, earlyMessageCacheEntry)
}
@@ -117,18 +117,18 @@ object ReceiptMessageProcessor {
val storyViewedReceipts = SignalStore.story.viewedReceiptsEnabled
if (!readReceipts && !storyViewedReceipts) {
log(envelope.timestamp!!, "Ignoring viewed receipts for IDs: ${viewedReceipt.timestamp.joinToString(", ")}")
log(envelope.clientTimestamp!!, "Ignoring viewed receipts for IDs: ${viewedReceipt.timestamp.joinToString(", ")}")
return
}
log(envelope.timestamp!!, "Processing viewed receipts. Sender: $senderRecipientId, Device: ${metadata.sourceDeviceId}, Only Stories: ${!readReceipts}, Timestamps: ${viewedReceipt.timestamp.joinToString(", ")}")
log(envelope.clientTimestamp!!, "Processing viewed receipts. Sender: $senderRecipientId, Device: ${metadata.sourceDeviceId}, Only Stories: ${!readReceipts}, Timestamps: ${viewedReceipt.timestamp.joinToString(", ")}")
val missingTargetTimestamps: Set<Long> = if (readReceipts && storyViewedReceipts) {
SignalDatabase.messages.incrementViewedReceiptCounts(viewedReceipt.timestamp, senderRecipientId, envelope.timestamp!!)
SignalDatabase.messages.incrementViewedReceiptCounts(viewedReceipt.timestamp, senderRecipientId, envelope.clientTimestamp!!)
} else if (readReceipts) {
SignalDatabase.messages.incrementViewedNonStoryReceiptCounts(viewedReceipt.timestamp, senderRecipientId, envelope.timestamp!!)
SignalDatabase.messages.incrementViewedNonStoryReceiptCounts(viewedReceipt.timestamp, senderRecipientId, envelope.clientTimestamp!!)
} else {
SignalDatabase.messages.incrementViewedStoryReceiptCounts(viewedReceipt.timestamp, senderRecipientId, envelope.timestamp!!)
SignalDatabase.messages.incrementViewedStoryReceiptCounts(viewedReceipt.timestamp, senderRecipientId, envelope.clientTimestamp!!)
}
val foundTargetTimestamps: Set<Long> = viewedReceipt.timestamp.toSet() - missingTargetTimestamps.toSet()
@@ -138,7 +138,7 @@ object ReceiptMessageProcessor {
val selfId = Recipient.self().id
for (targetTimestamp in missingTargetTimestamps) {
warn(envelope.timestamp!!, "[handleViewedReceipt] Could not find matching message! targetTimestamp: $targetTimestamp, receiptAuthor: $senderRecipientId | Receipt so associating with message from self ($selfId)")
warn(envelope.clientTimestamp!!, "[handleViewedReceipt] Could not find matching message! targetTimestamp: $targetTimestamp, receiptAuthor: $senderRecipientId | Receipt so associating with message from self ($selfId)")
if (earlyMessageCacheEntry != null) {
AppDependencies.earlyMessageCache.store(selfId, targetTimestamp, earlyMessageCacheEntry)
}

View File

@@ -33,20 +33,20 @@ object StoryMessageProcessor {
fun process(envelope: Envelope, content: Content, metadata: EnvelopeMetadata, senderRecipient: Recipient, threadRecipient: Recipient) {
val storyMessage = content.storyMessage!!
log(envelope.timestamp!!, "Story message.")
log(envelope.clientTimestamp!!, "Story message.")
if (threadRecipient.isInactiveGroup) {
warn(envelope.timestamp!!, "Dropping a group story from a group we're no longer in.")
warn(envelope.clientTimestamp!!, "Dropping a group story from a group we're no longer in.")
return
}
if (threadRecipient.isGroup && !SignalDatabase.groups.isCurrentMember(threadRecipient.requireGroupId().requirePush(), senderRecipient.id)) {
warn(envelope.timestamp!!, "Dropping a group story from a user who's no longer a member.")
warn(envelope.clientTimestamp!!, "Dropping a group story from a user who's no longer a member.")
return
}
if (!threadRecipient.isGroup && !(senderRecipient.isProfileSharing || senderRecipient.isSystemContact)) {
warn(envelope.timestamp!!, "Dropping story from an untrusted source.")
warn(envelope.clientTimestamp!!, "Dropping story from an untrusted source.")
return
}
@@ -64,7 +64,7 @@ object StoryMessageProcessor {
val mediaMessage = IncomingMessage(
type = MessageType.NORMAL,
from = senderRecipient.id,
sentTimeMillis = envelope.timestamp!!,
sentTimeMillis = envelope.clientTimestamp!!,
serverTimeMillis = envelope.serverTimestamp!!,
receivedTimeMillis = System.currentTimeMillis(),
storyType = storyType,

View File

@@ -162,26 +162,26 @@ object SyncMessageProcessor {
when {
syncMessage.sent != null -> handleSynchronizeSentMessage(context, envelope, content, metadata, syncMessage.sent!!, senderRecipient, threadRecipient, earlyMessageCacheEntry)
syncMessage.request != null -> handleSynchronizeRequestMessage(context, syncMessage.request!!, envelope.timestamp!!)
syncMessage.read.isNotEmpty() -> handleSynchronizeReadMessage(context, syncMessage.read, envelope.timestamp!!, earlyMessageCacheEntry)
syncMessage.viewed.isNotEmpty() -> handleSynchronizeViewedMessage(context, syncMessage.viewed, envelope.timestamp!!)
syncMessage.viewOnceOpen != null -> handleSynchronizeViewOnceOpenMessage(context, syncMessage.viewOnceOpen!!, envelope.timestamp!!, earlyMessageCacheEntry)
syncMessage.request != null -> handleSynchronizeRequestMessage(context, syncMessage.request!!, envelope.clientTimestamp!!)
syncMessage.read.isNotEmpty() -> handleSynchronizeReadMessage(context, syncMessage.read, envelope.clientTimestamp!!, earlyMessageCacheEntry)
syncMessage.viewed.isNotEmpty() -> handleSynchronizeViewedMessage(context, syncMessage.viewed, envelope.clientTimestamp!!)
syncMessage.viewOnceOpen != null -> handleSynchronizeViewOnceOpenMessage(context, syncMessage.viewOnceOpen!!, envelope.clientTimestamp!!, earlyMessageCacheEntry)
syncMessage.verified != null -> handleSynchronizeVerifiedMessage(context, syncMessage.verified!!)
syncMessage.stickerPackOperation.isNotEmpty() -> handleSynchronizeStickerPackOperation(syncMessage.stickerPackOperation, envelope.timestamp!!)
syncMessage.configuration != null -> handleSynchronizeConfigurationMessage(context, syncMessage.configuration!!, envelope.timestamp!!)
syncMessage.blocked != null -> handleSynchronizeBlockedListMessage(syncMessage.blocked!!, envelope.timestamp!!)
syncMessage.fetchLatest?.type != null -> handleSynchronizeFetchMessage(syncMessage.fetchLatest!!.type!!, envelope.timestamp!!)
syncMessage.messageRequestResponse != null -> handleSynchronizeMessageRequestResponse(syncMessage.messageRequestResponse!!, envelope.timestamp!!)
syncMessage.outgoingPayment != null -> handleSynchronizeOutgoingPayment(syncMessage.outgoingPayment!!, envelope.timestamp!!)
syncMessage.contacts != null -> handleSynchronizeContacts(syncMessage.contacts!!, envelope.timestamp!!)
syncMessage.keys != null -> handleSynchronizeKeys(syncMessage.keys!!, envelope.timestamp!!)
syncMessage.callEvent != null -> handleSynchronizeCallEvent(syncMessage.callEvent!!, envelope.timestamp!!)
syncMessage.callLinkUpdate != null -> handleSynchronizeCallLink(syncMessage.callLinkUpdate!!, envelope.timestamp!!)
syncMessage.callLogEvent != null -> handleSynchronizeCallLogEvent(syncMessage.callLogEvent!!, envelope.timestamp!!)
syncMessage.deleteForMe != null -> handleSynchronizeDeleteForMe(context, syncMessage.deleteForMe!!, envelope.timestamp!!, earlyMessageCacheEntry)
syncMessage.attachmentBackfillRequest != null -> handleSynchronizeAttachmentBackfillRequest(syncMessage.attachmentBackfillRequest!!, envelope.timestamp!!)
syncMessage.attachmentBackfillResponse != null -> warn(envelope.timestamp!!, "Contains a backfill response, but we don't handle these!")
else -> warn(envelope.timestamp!!, "Contains no known sync types...")
syncMessage.stickerPackOperation.isNotEmpty() -> handleSynchronizeStickerPackOperation(syncMessage.stickerPackOperation, envelope.clientTimestamp!!)
syncMessage.configuration != null -> handleSynchronizeConfigurationMessage(context, syncMessage.configuration!!, envelope.clientTimestamp!!)
syncMessage.blocked != null -> handleSynchronizeBlockedListMessage(syncMessage.blocked!!, envelope.clientTimestamp!!)
syncMessage.fetchLatest?.type != null -> handleSynchronizeFetchMessage(syncMessage.fetchLatest!!.type!!, envelope.clientTimestamp!!)
syncMessage.messageRequestResponse != null -> handleSynchronizeMessageRequestResponse(syncMessage.messageRequestResponse!!, envelope.clientTimestamp!!)
syncMessage.outgoingPayment != null -> handleSynchronizeOutgoingPayment(syncMessage.outgoingPayment!!, envelope.clientTimestamp!!)
syncMessage.contacts != null -> handleSynchronizeContacts(syncMessage.contacts!!, envelope.clientTimestamp!!)
syncMessage.keys != null -> handleSynchronizeKeys(syncMessage.keys!!, envelope.clientTimestamp!!)
syncMessage.callEvent != null -> handleSynchronizeCallEvent(syncMessage.callEvent!!, envelope.clientTimestamp!!)
syncMessage.callLinkUpdate != null -> handleSynchronizeCallLink(syncMessage.callLinkUpdate!!, envelope.clientTimestamp!!)
syncMessage.callLogEvent != null -> handleSynchronizeCallLogEvent(syncMessage.callLogEvent!!, envelope.clientTimestamp!!)
syncMessage.deleteForMe != null -> handleSynchronizeDeleteForMe(context, syncMessage.deleteForMe!!, envelope.clientTimestamp!!, earlyMessageCacheEntry)
syncMessage.attachmentBackfillRequest != null -> handleSynchronizeAttachmentBackfillRequest(syncMessage.attachmentBackfillRequest!!, envelope.clientTimestamp!!)
syncMessage.attachmentBackfillResponse != null -> warn(envelope.clientTimestamp!!, "Contains a backfill response, but we don't handle these!")
else -> warn(envelope.clientTimestamp!!, "Contains no known sync types...")
}
}
@@ -196,7 +196,7 @@ object SyncMessageProcessor {
threadRecipient: Recipient,
earlyMessageCacheEntry: EarlyMessageCacheEntry?
) {
log(envelope.timestamp!!, "Processing sent transcript for message with ID ${sent.timestamp!!}")
log(envelope.clientTimestamp!!, "Processing sent transcript for message with ID ${sent.timestamp!!}")
try {
handlePniIdentityKeys(envelope, sent)
@@ -212,42 +212,42 @@ object SyncMessageProcessor {
}
if (sent.isRecipientUpdate == true) {
handleGroupRecipientUpdate(sent, envelope.timestamp!!)
handleGroupRecipientUpdate(sent, envelope.clientTimestamp!!)
return
}
val dataMessage = if (sent.message != null) {
sent.message!!
} else {
warn(envelope.timestamp!!, "Sync message missing nested message to sync")
warn(envelope.clientTimestamp!!, "Sync message missing nested message to sync")
return
}
val groupId: GroupId.V2? = if (dataMessage.hasGroupContext) GroupId.v2(dataMessage.groupV2!!.groupMasterKey) else null
if (groupId != null) {
if (MessageContentProcessor.handleGv2PreProcessing(context, envelope.timestamp!!, content, metadata, groupId, dataMessage.groupV2!!, senderRecipient) == MessageContentProcessor.Gv2PreProcessResult.IGNORE) {
if (MessageContentProcessor.handleGv2PreProcessing(context, envelope.clientTimestamp!!, content, metadata, groupId, dataMessage.groupV2!!, senderRecipient) == MessageContentProcessor.Gv2PreProcessResult.IGNORE) {
return
}
}
var threadId: Long = -1
when {
dataMessage.isEndSession -> threadId = handleSynchronizeSentEndSessionMessage(context, sent, envelope.timestamp!!)
dataMessage.isEndSession -> threadId = handleSynchronizeSentEndSessionMessage(context, sent, envelope.clientTimestamp!!)
dataMessage.isGroupV2Update -> {
handleSynchronizeSentGv2Update(context, envelope, sent)
threadId = SignalDatabase.threads.getOrCreateThreadIdFor(getSyncMessageDestination(sent))
}
dataMessage.groupCallUpdate != null -> DataMessageProcessor.handleGroupCallUpdateMessage(envelope, senderRecipient.id, groupId)
dataMessage.isEmptyGroupV2Message -> warn(envelope.timestamp!!, "Empty GV2 message! Doing nothing.")
dataMessage.isEmptyGroupV2Message -> warn(envelope.clientTimestamp!!, "Empty GV2 message! Doing nothing.")
dataMessage.isExpirationUpdate -> threadId = handleSynchronizeSentExpirationUpdate(sent)
dataMessage.storyContext != null -> threadId = handleSynchronizeSentStoryReply(sent, envelope.timestamp!!)
dataMessage.storyContext != null -> threadId = handleSynchronizeSentStoryReply(sent, envelope.clientTimestamp!!)
dataMessage.reaction != null -> {
DataMessageProcessor.handleReaction(context, envelope, dataMessage, senderRecipient.id, earlyMessageCacheEntry)
threadId = SignalDatabase.threads.getOrCreateThreadIdFor(getSyncMessageDestination(sent))
}
dataMessage.hasRemoteDelete -> DataMessageProcessor.handleRemoteDelete(context, envelope, dataMessage, senderRecipient.id, earlyMessageCacheEntry)
dataMessage.isMediaMessage -> threadId = handleSynchronizeSentMediaMessage(context, sent, envelope.timestamp!!, senderRecipient, threadRecipient)
dataMessage.isMediaMessage -> threadId = handleSynchronizeSentMediaMessage(context, sent, envelope.clientTimestamp!!, senderRecipient, threadRecipient)
dataMessage.pollCreate != null -> threadId = handleSynchronizedPollCreate(envelope, dataMessage, sent, senderRecipient)
dataMessage.pollVote != null -> {
DataMessageProcessor.handlePollVote(context, envelope, dataMessage, senderRecipient, earlyMessageCacheEntry)
@@ -264,11 +264,11 @@ object SyncMessageProcessor {
DataMessageProcessor.handleAdminRemoteDelete(context, envelope, dataMessage, senderRecipient, threadRecipient, earlyMessageCacheEntry)
threadId = SignalDatabase.threads.getOrCreateThreadIdFor(getSyncMessageDestination(sent))
}
else -> threadId = handleSynchronizeSentTextMessage(sent, envelope.timestamp!!)
else -> threadId = handleSynchronizeSentTextMessage(sent, envelope.clientTimestamp!!)
}
if (groupId != null && SignalDatabase.groups.isUnknownGroup(groupId)) {
DataMessageProcessor.handleUnknownGroupMessage(envelope.timestamp!!, dataMessage.groupV2!!)
DataMessageProcessor.handleUnknownGroupMessage(envelope.clientTimestamp!!, dataMessage.groupV2!!)
}
if (dataMessage.profileKey.isNotEmpty()) {
@@ -284,7 +284,7 @@ object SyncMessageProcessor {
}
if (SignalStore.rateLimit.needsRecaptcha()) {
log(envelope.timestamp!!, "Got a sent transcript while in reCAPTCHA mode. Assuming we're good to message again.")
log(envelope.clientTimestamp!!, "Got a sent transcript while in reCAPTCHA mode. Assuming we're good to message again.")
RateLimitUtil.retryAllRateLimitedMessages(context)
}
@@ -308,16 +308,16 @@ object SyncMessageProcessor {
val address = SignalProtocolAddress(pni.toString(), SignalServiceAddress.DEFAULT_DEVICE_ID)
if (AppDependencies.protocolStore.aci().identities().getIdentity(address) != null) {
log(envelope.timestamp!!, "Ignoring identity on sent transcript for $pni because we already have one.")
log(envelope.clientTimestamp!!, "Ignoring identity on sent transcript for $pni because we already have one.")
continue
}
try {
log(envelope.timestamp!!, "Saving identity from sent transcript for $pni")
log(envelope.clientTimestamp!!, "Saving identity from sent transcript for $pni")
val identityKey = IdentityKey(status.destinationPniIdentityKey!!.toByteArray())
AppDependencies.protocolStore.aci().identities().saveIdentity(address, identityKey)
} catch (e: InvalidKeyException) {
warn(envelope.timestamp!!, "Failed to deserialize identity key for $pni")
warn(envelope.clientTimestamp!!, "Failed to deserialize identity key for $pni")
}
}
}
@@ -344,7 +344,7 @@ object SyncMessageProcessor {
val senderRecipientId = senderRecipient.id
if (targetMessage == null) {
warn(envelope.timestamp!!, "[handleSynchronizeSentEditMessage] Could not find matching message! targetTimestamp: $targetSentTimestamp author: $senderRecipientId")
warn(envelope.clientTimestamp!!, "[handleSynchronizeSentEditMessage] Could not find matching message! targetTimestamp: $targetSentTimestamp author: $senderRecipientId")
if (earlyMessageCacheEntry != null) {
AppDependencies.earlyMessageCache.store(senderRecipientId, targetSentTimestamp, earlyMessageCacheEntry)
PushProcessEarlyMessagesJob.enqueue()
@@ -358,12 +358,12 @@ object SyncMessageProcessor {
}
if (message.isMediaMessage) {
handleSynchronizeSentEditMediaMessage(targetMessage, toRecipient, sent, message, envelope.timestamp!!)
handleSynchronizeSentEditMediaMessage(targetMessage, toRecipient, sent, message, envelope.clientTimestamp!!)
} else {
handleSynchronizeSentEditTextMessage(targetMessage, toRecipient, sent, message, envelope.timestamp!!)
handleSynchronizeSentEditTextMessage(targetMessage, toRecipient, sent, message, envelope.clientTimestamp!!)
}
} else {
warn(envelope.timestamp!!, "[handleSynchronizeSentEditMessage] Invalid message edit! editTime: ${envelope.serverTimestamp}, targetTime: ${targetMessage.serverTimestamp}, sendAuthor: $senderRecipientId, targetAuthor: ${targetMessage.fromRecipient.id}")
warn(envelope.clientTimestamp!!, "[handleSynchronizeSentEditMessage] Invalid message edit! editTime: ${envelope.serverTimestamp}, targetTime: ${targetMessage.serverTimestamp}, sendAuthor: $senderRecipientId, targetAuthor: ${targetMessage.fromRecipient.id}")
}
}
@@ -510,12 +510,12 @@ object SyncMessageProcessor {
@Throws(MmsException::class)
private fun handleSynchronizeSentStoryMessage(envelope: Envelope, sent: Sent) {
log(envelope.timestamp!!, "Synchronize sent story message for " + sent.timestamp)
log(envelope.clientTimestamp!!, "Synchronize sent story message for " + sent.timestamp)
val manifest = SentStorySyncManifest.fromRecipientsSet(sent.storyMessageRecipients)
if (sent.isRecipientUpdate == true) {
log(envelope.timestamp!!, "Processing recipient update for story message and exiting...")
log(envelope.clientTimestamp!!, "Processing recipient update for story message and exiting...")
SignalDatabase.storySends.applySentStoryManifest(manifest, sent.timestamp!!)
return
}
@@ -686,18 +686,18 @@ object SyncMessageProcessor {
@Throws(IOException::class, GroupChangeBusyException::class)
private fun handleSynchronizeSentGv2Update(context: Context, envelope: Envelope, sent: Sent) {
log(envelope.timestamp!!, "Synchronize sent GV2 update for message with timestamp " + sent.timestamp!!)
log(envelope.clientTimestamp!!, "Synchronize sent GV2 update for message with timestamp " + sent.timestamp!!)
val dataMessage: DataMessage = sent.message!!
val groupId: GroupId.V2? = dataMessage.groupV2?.groupId
if (groupId == null) {
warn(envelope.timestamp!!, "GV2 update missing group id")
warn(envelope.clientTimestamp!!, "GV2 update missing group id")
return
}
if (MessageContentProcessor.updateGv2GroupFromServerOrP2PChange(context, envelope.timestamp!!, dataMessage.groupV2!!, SignalDatabase.groups.getGroup(groupId)) == null) {
log(envelope.timestamp!!, "Ignoring GV2 message for group we are not currently in $groupId")
if (MessageContentProcessor.updateGv2GroupFromServerOrP2PChange(context, envelope.clientTimestamp!!, dataMessage.groupV2!!, SignalDatabase.groups.getGroup(groupId)) == null) {
log(envelope.clientTimestamp!!, "Ignoring GV2 message for group we are not currently in $groupId")
}
}
@@ -1764,7 +1764,7 @@ object SyncMessageProcessor {
sent: Sent,
senderRecipient: Recipient
): Long {
log(envelope.timestamp!!, "Synchronize sent poll creation message.")
log(envelope.clientTimestamp!!, "Synchronize sent poll creation message.")
val recipient = getSyncMessageDestination(sent)
val threadId = SignalDatabase.threads.getOrCreateThreadIdFor(recipient)
@@ -1795,7 +1795,7 @@ object SyncMessageProcessor {
updateGroupReceiptStatus(sent, messageId, recipient.requireGroupId())
}
log(envelope.timestamp!!, "Inserted sync poll create message as messageId $messageId")
log(envelope.clientTimestamp!!, "Inserted sync poll create message as messageId $messageId")
SignalDatabase.messages.markAsSent(messageId, true)
@@ -1814,7 +1814,7 @@ object SyncMessageProcessor {
senderRecipient: Recipient,
earlyMessageCacheEntry: EarlyMessageCacheEntry?
): Long {
log(envelope.timestamp!!, "Synchronize sent poll terminate message")
log(envelope.clientTimestamp!!, "Synchronize sent poll terminate message")
val recipient = getSyncMessageDestination(sent)
val threadId = SignalDatabase.threads.getOrCreateThreadIdFor(recipient)
@@ -1827,7 +1827,7 @@ object SyncMessageProcessor {
val pollTerminate = message.pollTerminate!!
val targetMessage = SignalDatabase.messages.getMessageFor(pollTerminate.targetSentTimestamp!!, Recipient.self().id)
if (targetMessage == null) {
warn(envelope.timestamp!!, "Unable to find target message for poll termination. Putting in early message cache.")
warn(envelope.clientTimestamp!!, "Unable to find target message for poll termination. Putting in early message cache.")
if (earlyMessageCacheEntry != null) {
AppDependencies.earlyMessageCache.store(senderRecipient.id, pollTerminate.targetSentTimestamp!!, earlyMessageCacheEntry)
PushProcessEarlyMessagesJob.enqueue()
@@ -1836,7 +1836,7 @@ object SyncMessageProcessor {
}
val poll = SignalDatabase.polls.getPoll(targetMessage.id)
if (poll == null) {
warn(envelope.timestamp!!, "Unable to find poll for poll termination. Dropping.")
warn(envelope.clientTimestamp!!, "Unable to find poll for poll termination. Dropping.")
return -1
}
@@ -1857,7 +1857,7 @@ object SyncMessageProcessor {
val messageId = SignalDatabase.messages.insertMessageOutbox(outgoingMessage, threadId, false, receiptStatus, null).messageId
SignalDatabase.messages.markAsSent(messageId, true)
log(envelope.timestamp!!, "Inserted sync poll end message as messageId $messageId")
log(envelope.clientTimestamp!!, "Inserted sync poll end message as messageId $messageId")
if (expiresInMillis > 0) {
SignalDatabase.messages.markExpireStarted(messageId, sent.expirationStartTimestamp ?: 0)
@@ -1874,7 +1874,7 @@ object SyncMessageProcessor {
senderRecipient: Recipient,
earlyMessageCacheEntry: EarlyMessageCacheEntry?
): Long {
log(envelope.timestamp!!, "Synchronize pinned message")
log(envelope.clientTimestamp!!, "Synchronize pinned message")
val recipient = getSyncMessageDestination(sent)
val threadId = SignalDatabase.threads.getOrCreateThreadIdFor(recipient)
@@ -1887,14 +1887,14 @@ object SyncMessageProcessor {
val pinMessage = message.pinMessage!!
val targetAuthorServiceId: ServiceId = ACI.parseOrThrow(pinMessage.targetAuthorAciBinary!!)
if (targetAuthorServiceId.isUnknown) {
warn(envelope.timestamp!!, "Unknown author")
warn(envelope.clientTimestamp!!, "Unknown author")
return -1
}
val targetAuthor = Recipient.externalPush(targetAuthorServiceId)
val targetMessage = SignalDatabase.messages.getMessageFor(pinMessage.targetSentTimestamp!!, targetAuthor.id)
if (targetMessage == null) {
warn(envelope.timestamp!!, "Unable to find target message for sync message. Putting in early message cache.")
warn(envelope.clientTimestamp!!, "Unable to find target message for sync message. Putting in early message cache.")
if (earlyMessageCacheEntry != null) {
AppDependencies.earlyMessageCache.store(senderRecipient.id, pinMessage.targetSentTimestamp!!, earlyMessageCacheEntry)
PushProcessEarlyMessagesJob.enqueue()
@@ -1903,12 +1903,12 @@ object SyncMessageProcessor {
}
if (targetMessage.hasGiftBadge()) {
warn(envelope.timestamp!!, "Cannot pin gift badge")
warn(envelope.clientTimestamp!!, "Cannot pin gift badge")
return -1
}
if (targetMessage.isRemoteDelete) {
warn(envelope.timestamp!!, "Cannot pin deleted message")
warn(envelope.clientTimestamp!!, "Cannot pin deleted message")
return -1
}
@@ -1924,7 +1924,7 @@ object SyncMessageProcessor {
val messageId = SignalDatabase.messages.insertMessageOutbox(outgoingMessage, threadId, false, GroupReceiptTable.STATUS_UNKNOWN, null).messageId
SignalDatabase.messages.markAsSent(messageId, true)
log(envelope.timestamp!!, "Inserted sync pin message as messageId $messageId")
log(envelope.clientTimestamp!!, "Inserted sync pin message as messageId $messageId")
if (expiresInMillis > 0) {
SignalDatabase.messages.markExpireStarted(messageId, sent.expirationStartTimestamp ?: 0)