mirror of
https://github.com/signalapp/Signal-Android.git
synced 2026-04-02 00:17:41 +01:00
Update SignalService.proto to match shared one.
This commit is contained in:
committed by
Alex Hart
parent
5ae51f844e
commit
f04a0533cb
@@ -316,7 +316,7 @@ class DataMessageProcessorTest_polls {
|
|||||||
|
|
||||||
private fun insertPoll(allowMultiple: Boolean = true): Long {
|
private fun insertPoll(allowMultiple: Boolean = true): Long {
|
||||||
val envelope = MessageContentFuzzer.envelope(100)
|
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()
|
val messageId = SignalDatabase.messages.insertMessageInbox(pollMessage).get()
|
||||||
SignalDatabase.polls.insertPoll("question?", allowMultiple, listOf("a", "b", "c"), alice.id.toLong(), messageId.messageId)
|
SignalDatabase.polls.insertPoll("question?", allowMultiple, listOf("a", "b", "c"), alice.id.toLong(), messageId.messageId)
|
||||||
return messageId.messageId
|
return messageId.messageId
|
||||||
|
|||||||
@@ -43,7 +43,7 @@ object MessageContentFuzzer {
|
|||||||
*/
|
*/
|
||||||
fun envelope(timestamp: Long, serverGuid: UUID = UUID.randomUUID()): Envelope {
|
fun envelope(timestamp: Long, serverGuid: UUID = UUID.randomUUID()): Envelope {
|
||||||
return Envelope.Builder()
|
return Envelope.Builder()
|
||||||
.timestamp(timestamp)
|
.clientTimestamp(timestamp)
|
||||||
.serverTimestamp(timestamp + 5)
|
.serverTimestamp(timestamp + 5)
|
||||||
.serverGuidBinary(serverGuid.toByteArray().toByteString())
|
.serverGuidBinary(serverGuid.toByteArray().toByteString())
|
||||||
.build()
|
.build()
|
||||||
@@ -292,7 +292,7 @@ object MessageContentFuzzer {
|
|||||||
body = string()
|
body = string()
|
||||||
val quoted = quoteAble.random(random)
|
val quoted = quoteAble.random(random)
|
||||||
quote = DataMessage.Quote.Builder().buildWith {
|
quote = DataMessage.Quote.Builder().buildWith {
|
||||||
id = quoted.envelope.timestamp
|
id = quoted.envelope.clientTimestamp
|
||||||
authorAciBinary = quoted.metadata.sourceServiceId.toByteString()
|
authorAciBinary = quoted.metadata.sourceServiceId.toByteString()
|
||||||
text = quoted.content.dataMessage?.body
|
text = quoted.content.dataMessage?.body
|
||||||
attachments(quoted.content.dataMessage?.attachments ?: emptyList())
|
attachments(quoted.content.dataMessage?.attachments ?: emptyList())
|
||||||
@@ -304,7 +304,7 @@ object MessageContentFuzzer {
|
|||||||
if (random.nextFloat() < 0.1 && quoteAble.isNotEmpty()) {
|
if (random.nextFloat() < 0.1 && quoteAble.isNotEmpty()) {
|
||||||
val quoted = quoteAble.random(random)
|
val quoted = quoteAble.random(random)
|
||||||
quote = DataMessage.Quote.Builder().buildWith {
|
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()
|
authorAciBinary = quoted.metadata.sourceServiceId.toByteString()
|
||||||
text = quoted.content.dataMessage?.body
|
text = quoted.content.dataMessage?.body
|
||||||
}
|
}
|
||||||
@@ -333,7 +333,7 @@ object MessageContentFuzzer {
|
|||||||
emoji = emojis.random(random)
|
emoji = emojis.random(random)
|
||||||
remove = false
|
remove = false
|
||||||
targetAuthorAciBinary = reactTo.metadata.sourceServiceId.toByteString()
|
targetAuthorAciBinary = reactTo.metadata.sourceServiceId.toByteString()
|
||||||
targetSentTimestamp = reactTo.envelope.timestamp
|
targetSentTimestamp = reactTo.envelope.clientTimestamp
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -70,8 +70,8 @@ object Generator {
|
|||||||
val serverGuid = UUID.randomUUID()
|
val serverGuid = UUID.randomUUID()
|
||||||
return Envelope.Builder()
|
return Envelope.Builder()
|
||||||
.type(Envelope.Type.fromValue(this.type))
|
.type(Envelope.Type.fromValue(this.type))
|
||||||
.sourceDevice(1)
|
.sourceDeviceId(1)
|
||||||
.timestamp(timestamp)
|
.clientTimestamp(timestamp)
|
||||||
.serverTimestamp(timestamp + 1)
|
.serverTimestamp(timestamp + 1)
|
||||||
.destinationServiceId(destination.toString())
|
.destinationServiceId(destination.toString())
|
||||||
.destinationServiceIdBinary(destination.toByteString())
|
.destinationServiceIdBinary(destination.toByteString())
|
||||||
|
|||||||
@@ -67,9 +67,9 @@ class PushProcessMessageJobMigration : JobMigration(10) {
|
|||||||
|
|
||||||
val envelope = Envelope.Builder()
|
val envelope = Envelope.Builder()
|
||||||
.sourceServiceId(sourceServiceId.toString())
|
.sourceServiceId(sourceServiceId.toString())
|
||||||
.sourceDevice(proto.metadata!!.senderDevice)
|
.sourceDeviceId(proto.metadata!!.senderDevice)
|
||||||
.destinationServiceId(destinationServiceId.toString())
|
.destinationServiceId(destinationServiceId.toString())
|
||||||
.timestamp(proto.metadata!!.timestamp)
|
.clientTimestamp(proto.metadata!!.timestamp)
|
||||||
.serverGuid(proto.metadata!!.serverGuid)
|
.serverGuid(proto.metadata!!.serverGuid)
|
||||||
.serverTimestamp(proto.metadata!!.serverReceivedTimestamp)
|
.serverTimestamp(proto.metadata!!.serverReceivedTimestamp)
|
||||||
|
|
||||||
|
|||||||
@@ -155,7 +155,7 @@ class PushProcessMessageJob private constructor(
|
|||||||
try {
|
try {
|
||||||
messageProcessor.process(result.envelope, result.content, result.metadata, result.serverDeliveredTimestamp, localMetric = localReceiveMetric, batchCache = batchCache)
|
messageProcessor.process(result.envelope, result.content, result.metadata, result.serverDeliveredTimestamp, localMetric = localReceiveMetric, batchCache = batchCache)
|
||||||
} catch (e: Exception) {
|
} 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
|
null
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -41,15 +41,15 @@ object CallMessageProcessor {
|
|||||||
|
|
||||||
if (metadata.destinationServiceId is ServiceId.PNI) {
|
if (metadata.destinationServiceId is ServiceId.PNI) {
|
||||||
if (RecipientUtil.isCallRequestAccepted(senderRecipient) && callMessage.offer != null) {
|
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)
|
RecipientUtil.shareProfileIfFirstSecureMessage(senderRecipient)
|
||||||
ProfileKeySendJob.create(senderRecipient, false)?.let { AppDependencies.jobManager.add(it) }
|
ProfileKeySendJob.create(senderRecipient, false)?.let { AppDependencies.jobManager.add(it) }
|
||||||
}
|
}
|
||||||
|
|
||||||
if (callMessage.offer != null) {
|
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 {
|
} 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
|
return
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -65,12 +65,12 @@ object CallMessageProcessor {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private fun handleCallOfferMessage(envelope: Envelope, metadata: EnvelopeMetadata, offer: Offer, senderRecipientId: RecipientId, serverDeliveredTimestamp: Long) {
|
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) {
|
val offerId = if (offer.id != null && offer.type != null && offer.opaque != null) {
|
||||||
offer.id!!
|
offer.id!!
|
||||||
} else {
|
} else {
|
||||||
warn(envelope.timestamp!!, "Invalid offer, missing id, type, or opaque")
|
warn(envelope.clientTimestamp!!, "Invalid offer, missing id, type, or opaque")
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -96,12 +96,12 @@ object CallMessageProcessor {
|
|||||||
answer: CallMessage.Answer,
|
answer: CallMessage.Answer,
|
||||||
senderRecipientId: RecipientId
|
senderRecipientId: RecipientId
|
||||||
) {
|
) {
|
||||||
log(envelope.timestamp!!, "handleCallAnswerMessage...")
|
log(envelope.clientTimestamp!!, "handleCallAnswerMessage...")
|
||||||
|
|
||||||
val answerId = if (answer.id != null && answer.opaque != null) {
|
val answerId = if (answer.id != null && answer.opaque != null) {
|
||||||
answer.id!!
|
answer.id!!
|
||||||
} else {
|
} else {
|
||||||
warn(envelope.timestamp!!, "Invalid answer, missing id or opaque")
|
warn(envelope.clientTimestamp!!, "Invalid answer, missing id or opaque")
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -122,7 +122,7 @@ object CallMessageProcessor {
|
|||||||
iceUpdateList: List<CallMessage.IceUpdate>,
|
iceUpdateList: List<CallMessage.IceUpdate>,
|
||||||
senderRecipientId: RecipientId
|
senderRecipientId: RecipientId
|
||||||
) {
|
) {
|
||||||
log(envelope.timestamp!!, "handleCallIceUpdateMessage... " + iceUpdateList.size)
|
log(envelope.clientTimestamp!!, "handleCallIceUpdateMessage... " + iceUpdateList.size)
|
||||||
|
|
||||||
val iceCandidates: MutableList<ByteArray> = ArrayList(iceUpdateList.size)
|
val iceCandidates: MutableList<ByteArray> = ArrayList(iceUpdateList.size)
|
||||||
var callId: Long = -1
|
var callId: Long = -1
|
||||||
@@ -142,7 +142,7 @@ object CallMessageProcessor {
|
|||||||
iceCandidates
|
iceCandidates
|
||||||
)
|
)
|
||||||
} else {
|
} 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?,
|
hangup: CallMessage.Hangup?,
|
||||||
senderRecipientId: RecipientId
|
senderRecipientId: RecipientId
|
||||||
) {
|
) {
|
||||||
log(envelope.timestamp!!, "handleCallHangupMessage")
|
log(envelope.clientTimestamp!!, "handleCallHangupMessage")
|
||||||
|
|
||||||
val (hangupId: Long, hangupDeviceId: Int?) = if (hangup?.id != null) {
|
val (hangupId: Long, hangupDeviceId: Int?) = if (hangup?.id != null) {
|
||||||
hangup.id!! to hangup.deviceId
|
hangup.id!! to hangup.deviceId
|
||||||
} else {
|
} else {
|
||||||
warn(envelope.timestamp!!, "Invalid hangup, null message or missing id/deviceId")
|
warn(envelope.clientTimestamp!!, "Invalid hangup, null message or missing id/deviceId")
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -170,12 +170,12 @@ object CallMessageProcessor {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private fun handleCallBusyMessage(envelope: Envelope, metadata: EnvelopeMetadata, busy: CallMessage.Busy, senderRecipientId: RecipientId) {
|
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) {
|
val busyId = if (busy.id != null) {
|
||||||
busy.id!!
|
busy.id!!
|
||||||
} else {
|
} else {
|
||||||
warn(envelope.timestamp!!, "Invalid busy, missing call id")
|
warn(envelope.clientTimestamp!!, "Invalid busy, missing call id")
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -184,12 +184,12 @@ object CallMessageProcessor {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private fun handleCallOpaqueMessage(envelope: Envelope, metadata: EnvelopeMetadata, opaque: Opaque, senderServiceId: ServiceId, serverDeliveredTimestamp: Long) {
|
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) {
|
val data = if (opaque.data_ != null) {
|
||||||
opaque.data_!!.toByteArray()
|
opaque.data_!!.toByteArray()
|
||||||
} else {
|
} else {
|
||||||
warn(envelope.timestamp!!, "Invalid opaque message, null data")
|
warn(envelope.clientTimestamp!!, "Invalid opaque message, null data")
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -149,7 +149,7 @@ object DataMessageProcessor {
|
|||||||
SignalTrace.beginSection("DataMessageProcessor#gv2PreProcessing")
|
SignalTrace.beginSection("DataMessageProcessor#gv2PreProcessing")
|
||||||
groupProcessResult = MessageContentProcessor.handleGv2PreProcessing(
|
groupProcessResult = MessageContentProcessor.handleGv2PreProcessing(
|
||||||
context = context,
|
context = context,
|
||||||
timestamp = envelope.timestamp!!,
|
timestamp = envelope.clientTimestamp!!,
|
||||||
content = content,
|
content = content,
|
||||||
metadata = metadata,
|
metadata = metadata,
|
||||||
groupId = groupId,
|
groupId = groupId,
|
||||||
@@ -171,7 +171,7 @@ object DataMessageProcessor {
|
|||||||
var messageId: MessageId? = null
|
var messageId: MessageId? = null
|
||||||
SignalTrace.beginSection("DataMessageProcessor#messageInsert")
|
SignalTrace.beginSection("DataMessageProcessor#messageInsert")
|
||||||
when {
|
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.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.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)
|
message.isStoryReaction -> insertResult = handleStoryReaction(context, envelope, metadata, message, senderRecipient.id, groupId)
|
||||||
@@ -197,7 +197,7 @@ object DataMessageProcessor {
|
|||||||
SignalTrace.beginSection("DataMessageProcessor#postProcess")
|
SignalTrace.beginSection("DataMessageProcessor#postProcess")
|
||||||
messageId = messageId ?: insertResult?.messageId?.let { MessageId(it) }
|
messageId = messageId ?: insertResult?.messageId?.let { MessageId(it) }
|
||||||
if (messageId != null) {
|
if (messageId != null) {
|
||||||
log(envelope.timestamp!!, "Inserted as messageId $messageId")
|
log(envelope.clientTimestamp!!, "Inserted as messageId $messageId")
|
||||||
}
|
}
|
||||||
|
|
||||||
if (groupId != null) {
|
if (groupId != null) {
|
||||||
@@ -206,12 +206,12 @@ object DataMessageProcessor {
|
|||||||
else -> SignalDatabase.groups.isUnknownGroup(groupId)
|
else -> SignalDatabase.groups.isUnknownGroup(groupId)
|
||||||
}
|
}
|
||||||
if (unknownGroup) {
|
if (unknownGroup) {
|
||||||
handleUnknownGroupMessage(envelope.timestamp!!, message.groupV2!!)
|
handleUnknownGroupMessage(envelope.clientTimestamp!!, message.groupV2!!)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (message.profileKey.isNotEmpty()) {
|
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) {
|
if (groupId == null && senderRecipient.hiddenState == HiddenState.HIDDEN) {
|
||||||
@@ -248,11 +248,11 @@ object DataMessageProcessor {
|
|||||||
if (insertResult != null && insertResult.threadWasNewlyCreated && !threadRecipient.isGroup && !threadRecipient.isSelf && !senderRecipient.isSystemContact) {
|
if (insertResult != null && insertResult.threadWasNewlyCreated && !threadRecipient.isGroup && !threadRecipient.isSelf && !senderRecipient.isSystemContact) {
|
||||||
val timeSinceLastSync = System.currentTimeMillis() - SignalStore.misc.lastCdsForegroundSyncTime
|
val timeSinceLastSync = System.currentTimeMillis() - SignalStore.misc.lastCdsForegroundSyncTime
|
||||||
if (timeSinceLastSync > RemoteConfig.cdsForegroundSyncInterval || timeSinceLastSync < 0) {
|
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))
|
AppDependencies.jobManager.add(DirectoryRefreshJob(false))
|
||||||
SignalStore.misc.lastCdsForegroundSyncTime = System.currentTimeMillis()
|
SignalStore.misc.lastCdsForegroundSyncTime = System.currentTimeMillis()
|
||||||
} else {
|
} 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,
|
envelope: Envelope,
|
||||||
metadata: EnvelopeMetadata
|
metadata: EnvelopeMetadata
|
||||||
): InsertResult? {
|
): InsertResult? {
|
||||||
log(envelope.timestamp!!, "End session message.")
|
log(envelope.clientTimestamp!!, "End session message.")
|
||||||
|
|
||||||
val incomingMessage = IncomingMessage(
|
val incomingMessage = IncomingMessage(
|
||||||
from = senderRecipientId,
|
from = senderRecipientId,
|
||||||
sentTimeMillis = envelope.timestamp!!,
|
sentTimeMillis = envelope.clientTimestamp!!,
|
||||||
serverTimeMillis = envelope.serverTimestamp!!,
|
serverTimeMillis = envelope.serverTimestamp!!,
|
||||||
receivedTimeMillis = System.currentTimeMillis(),
|
receivedTimeMillis = System.currentTimeMillis(),
|
||||||
isUnidentified = metadata.sealedSender,
|
isUnidentified = metadata.sealedSender,
|
||||||
@@ -356,20 +356,20 @@ object DataMessageProcessor {
|
|||||||
receivedTime: Long,
|
receivedTime: Long,
|
||||||
sideEffect: Boolean
|
sideEffect: Boolean
|
||||||
): InsertResult? {
|
): InsertResult? {
|
||||||
log(envelope.timestamp!!, "Expiration update. Side effect: $sideEffect")
|
log(envelope.clientTimestamp!!, "Expiration update. Side effect: $sideEffect")
|
||||||
|
|
||||||
if (groupId != null) {
|
if (groupId != null) {
|
||||||
warn(envelope.timestamp!!, "Expiration update received for GV2. Ignoring.")
|
warn(envelope.clientTimestamp!!, "Expiration update received for GV2. Ignoring.")
|
||||||
return null
|
return null
|
||||||
}
|
}
|
||||||
|
|
||||||
if (SignalDatabase.recipients.getExpiresInSeconds(threadRecipientId) == expiresIn.inWholeSeconds) {
|
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
|
return null
|
||||||
}
|
}
|
||||||
|
|
||||||
if (expireTimerVersion != null && expireTimerVersion < senderRecipient.expireTimerVersion) {
|
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
|
return null
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -377,7 +377,7 @@ object DataMessageProcessor {
|
|||||||
val mediaMessage = IncomingMessage(
|
val mediaMessage = IncomingMessage(
|
||||||
type = MessageType.EXPIRATION_UPDATE,
|
type = MessageType.EXPIRATION_UPDATE,
|
||||||
from = senderRecipient.id,
|
from = senderRecipient.id,
|
||||||
sentTimeMillis = envelope.timestamp!! - if (sideEffect) 1 else 0,
|
sentTimeMillis = envelope.clientTimestamp!! - if (sideEffect) 1 else 0,
|
||||||
serverTimeMillis = envelope.serverTimestamp!!,
|
serverTimeMillis = envelope.serverTimestamp!!,
|
||||||
receivedTimeMillis = receivedTime,
|
receivedTimeMillis = receivedTime,
|
||||||
expiresIn = expiresIn.inWholeMilliseconds,
|
expiresIn = expiresIn.inWholeMilliseconds,
|
||||||
@@ -419,7 +419,7 @@ object DataMessageProcessor {
|
|||||||
receivedTime: Long
|
receivedTime: Long
|
||||||
) {
|
) {
|
||||||
if (threadRecipient.expiresInSeconds.toLong() != expiresIn.inWholeSeconds || ((expireTimerVersion ?: -1) > threadRecipient.expireTimerVersion)) {
|
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)
|
handleExpirationUpdate(envelope, metadata, senderRecipient, threadRecipient.id, groupId, expiresIn, expireTimerVersion, receivedTime, true)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -433,13 +433,13 @@ object DataMessageProcessor {
|
|||||||
senderRecipientId: RecipientId,
|
senderRecipientId: RecipientId,
|
||||||
groupId: GroupId.V2?
|
groupId: GroupId.V2?
|
||||||
): InsertResult? {
|
): InsertResult? {
|
||||||
log(envelope.timestamp!!, "Story reaction.")
|
log(envelope.clientTimestamp!!, "Story reaction.")
|
||||||
|
|
||||||
val storyContext = message.storyContext!!
|
val storyContext = message.storyContext!!
|
||||||
val emoji = message.reaction!!.emoji
|
val emoji = message.reaction!!.emoji
|
||||||
|
|
||||||
if (!EmojiUtil.isEmoji(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
|
return null
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -472,18 +472,18 @@ object DataMessageProcessor {
|
|||||||
quoteModel = QuoteModel(sentTimestamp, authorRecipientId, displayText, false, story.slideDeck.asAttachments().firstOrNull(), emptyList(), QuoteModel.Type.NORMAL, bodyRanges)
|
quoteModel = QuoteModel(sentTimestamp, authorRecipientId, displayText, false, story.slideDeck.asAttachments().firstOrNull(), emptyList(), QuoteModel.Type.NORMAL, bodyRanges)
|
||||||
expiresIn = message.expireTimerDuration
|
expiresIn = message.expireTimerDuration
|
||||||
} else {
|
} else {
|
||||||
warn(envelope.timestamp!!, "Story has reactions disabled. Dropping reaction.")
|
warn(envelope.clientTimestamp!!, "Story has reactions disabled. Dropping reaction.")
|
||||||
return null
|
return null
|
||||||
}
|
}
|
||||||
} catch (e: NoSuchMessageException) {
|
} 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
|
return null
|
||||||
}
|
}
|
||||||
|
|
||||||
val mediaMessage = IncomingMessage(
|
val mediaMessage = IncomingMessage(
|
||||||
type = MessageType.STORY_REACTION,
|
type = MessageType.STORY_REACTION,
|
||||||
from = senderRecipientId,
|
from = senderRecipientId,
|
||||||
sentTimeMillis = envelope.timestamp!!,
|
sentTimeMillis = envelope.clientTimestamp!!,
|
||||||
serverTimeMillis = envelope.serverTimestamp!!,
|
serverTimeMillis = envelope.serverTimestamp!!,
|
||||||
receivedTimeMillis = System.currentTimeMillis(),
|
receivedTimeMillis = System.currentTimeMillis(),
|
||||||
parentStoryId = parentStoryId,
|
parentStoryId = parentStoryId,
|
||||||
@@ -513,7 +513,7 @@ object DataMessageProcessor {
|
|||||||
null
|
null
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
warn(envelope.timestamp!!, "Failed to insert story reaction")
|
warn(envelope.clientTimestamp!!, "Failed to insert story reaction")
|
||||||
null
|
null
|
||||||
}
|
}
|
||||||
} catch (e: MmsException) {
|
} catch (e: MmsException) {
|
||||||
@@ -533,7 +533,7 @@ object DataMessageProcessor {
|
|||||||
): MessageId? {
|
): MessageId? {
|
||||||
val reaction: DataMessage.Reaction = message.reaction!!
|
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 emoji: String? = reaction.emoji
|
||||||
val isRemove: Boolean = reaction.remove ?: false
|
val isRemove: Boolean = reaction.remove ?: false
|
||||||
@@ -541,19 +541,19 @@ object DataMessageProcessor {
|
|||||||
val targetSentTimestamp: Long = reaction.targetSentTimestamp!!
|
val targetSentTimestamp: Long = reaction.targetSentTimestamp!!
|
||||||
|
|
||||||
if (targetAuthorServiceId.isUnknown) {
|
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
|
return null
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!EmojiUtil.isEmoji(emoji)) {
|
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
|
return null
|
||||||
}
|
}
|
||||||
|
|
||||||
val targetAuthor = Recipient.externalPush(targetAuthorServiceId)
|
val targetAuthor = Recipient.externalPush(targetAuthorServiceId)
|
||||||
val targetMessage = SignalDatabase.messages.getMessageFor(targetSentTimestamp, targetAuthor.id)
|
val targetMessage = SignalDatabase.messages.getMessageFor(targetSentTimestamp, targetAuthor.id)
|
||||||
if (targetMessage == null) {
|
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) {
|
if (earlyMessageCacheEntry != null) {
|
||||||
AppDependencies.earlyMessageCache.store(targetAuthor.id, targetSentTimestamp, earlyMessageCacheEntry)
|
AppDependencies.earlyMessageCache.store(targetAuthor.id, targetSentTimestamp, earlyMessageCacheEntry)
|
||||||
PushProcessEarlyMessagesJob.enqueue()
|
PushProcessEarlyMessagesJob.enqueue()
|
||||||
@@ -562,25 +562,25 @@ object DataMessageProcessor {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (targetMessage.isRemoteDelete) {
|
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
|
return null
|
||||||
}
|
}
|
||||||
|
|
||||||
val targetThread = SignalDatabase.threads.getThreadRecord(targetMessage.threadId)
|
val targetThread = SignalDatabase.threads.getThreadRecord(targetMessage.threadId)
|
||||||
if (targetThread == null) {
|
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
|
return null
|
||||||
}
|
}
|
||||||
|
|
||||||
val targetThreadRecipientId = targetThread.recipient.id
|
val targetThreadRecipientId = targetThread.recipient.id
|
||||||
val groupRecord = SignalDatabase.groups.getGroup(targetThreadRecipientId).orNull()
|
val groupRecord = SignalDatabase.groups.getGroup(targetThreadRecipientId).orNull()
|
||||||
if (groupRecord != null && !groupRecord.members.contains(senderRecipientId)) {
|
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
|
return null
|
||||||
}
|
}
|
||||||
|
|
||||||
if (groupRecord == null && senderRecipientId != targetThreadRecipientId && Recipient.self().id != senderRecipientId) {
|
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
|
return null
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -601,7 +601,7 @@ object DataMessageProcessor {
|
|||||||
fun handleRemoteDelete(context: Context, envelope: Envelope, message: DataMessage, senderRecipientId: RecipientId, earlyMessageCacheEntry: EarlyMessageCacheEntry?): MessageId? {
|
fun handleRemoteDelete(context: Context, envelope: Envelope, message: DataMessage, senderRecipientId: RecipientId, earlyMessageCacheEntry: EarlyMessageCacheEntry?): MessageId? {
|
||||||
val delete = message.delete!!
|
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 targetSentTimestamp: Long = delete.targetSentTimestamp!!
|
||||||
val targetMessage: MessageRecord? = SignalDatabase.messages.getMessageFor(targetSentTimestamp, senderRecipientId)
|
val targetMessage: MessageRecord? = SignalDatabase.messages.getMessageFor(targetSentTimestamp, senderRecipientId)
|
||||||
@@ -616,7 +616,7 @@ object DataMessageProcessor {
|
|||||||
|
|
||||||
MessageId(targetMessage.id)
|
MessageId(targetMessage.id)
|
||||||
} else if (targetMessage == null) {
|
} 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) {
|
if (earlyMessageCacheEntry != null) {
|
||||||
AppDependencies.earlyMessageCache.store(senderRecipientId, targetSentTimestamp, earlyMessageCacheEntry)
|
AppDependencies.earlyMessageCache.store(senderRecipientId, targetSentTimestamp, earlyMessageCacheEntry)
|
||||||
PushProcessEarlyMessagesJob.enqueue()
|
PushProcessEarlyMessagesJob.enqueue()
|
||||||
@@ -624,7 +624,7 @@ object DataMessageProcessor {
|
|||||||
|
|
||||||
null
|
null
|
||||||
} else {
|
} 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
|
null
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -644,13 +644,13 @@ object DataMessageProcessor {
|
|||||||
isActivatePaymentsRequest: Boolean,
|
isActivatePaymentsRequest: Boolean,
|
||||||
isPaymentsActivated: Boolean
|
isPaymentsActivated: Boolean
|
||||||
): InsertResult? {
|
): InsertResult? {
|
||||||
log(envelope.timestamp!!, "Payment activation request: $isActivatePaymentsRequest activated: $isPaymentsActivated")
|
log(envelope.clientTimestamp!!, "Payment activation request: $isActivatePaymentsRequest activated: $isPaymentsActivated")
|
||||||
Preconditions.checkArgument(isActivatePaymentsRequest || isPaymentsActivated)
|
Preconditions.checkArgument(isActivatePaymentsRequest || isPaymentsActivated)
|
||||||
|
|
||||||
try {
|
try {
|
||||||
val mediaMessage = IncomingMessage(
|
val mediaMessage = IncomingMessage(
|
||||||
from = senderRecipientId,
|
from = senderRecipientId,
|
||||||
sentTimeMillis = envelope.timestamp!!,
|
sentTimeMillis = envelope.clientTimestamp!!,
|
||||||
serverTimeMillis = envelope.serverTimestamp!!,
|
serverTimeMillis = envelope.serverTimestamp!!,
|
||||||
receivedTimeMillis = receivedTime,
|
receivedTimeMillis = receivedTime,
|
||||||
expiresIn = message.expireTimerDuration.inWholeMilliseconds,
|
expiresIn = message.expireTimerDuration.inWholeMilliseconds,
|
||||||
@@ -675,10 +675,10 @@ object DataMessageProcessor {
|
|||||||
senderRecipientId: RecipientId,
|
senderRecipientId: RecipientId,
|
||||||
receivedTime: Long
|
receivedTime: Long
|
||||||
): InsertResult? {
|
): InsertResult? {
|
||||||
log(envelope.timestamp!!, "Payment message.")
|
log(envelope.clientTimestamp!!, "Payment message.")
|
||||||
|
|
||||||
if (message.payment?.notification?.mobileCoin?.receipt == null) {
|
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
|
return null
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -701,7 +701,7 @@ object DataMessageProcessor {
|
|||||||
val mediaMessage = IncomingMessage(
|
val mediaMessage = IncomingMessage(
|
||||||
from = senderRecipientId,
|
from = senderRecipientId,
|
||||||
body = uuid.toString(),
|
body = uuid.toString(),
|
||||||
sentTimeMillis = envelope.timestamp!!,
|
sentTimeMillis = envelope.clientTimestamp!!,
|
||||||
serverTimeMillis = envelope.serverTimestamp!!,
|
serverTimeMillis = envelope.serverTimestamp!!,
|
||||||
receivedTimeMillis = receivedTime,
|
receivedTimeMillis = receivedTime,
|
||||||
expiresIn = message.expireTimerDuration.inWholeMilliseconds,
|
expiresIn = message.expireTimerDuration.inWholeMilliseconds,
|
||||||
@@ -716,9 +716,9 @@ object DataMessageProcessor {
|
|||||||
return insertResult
|
return insertResult
|
||||||
}
|
}
|
||||||
} catch (e: PublicKeyConflictException) {
|
} 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) {
|
} catch (e: SerializationException) {
|
||||||
warn(envelope.timestamp!!, "Ignoring payment with bad data.", e)
|
warn(envelope.clientTimestamp!!, "Ignoring payment with bad data.", e)
|
||||||
} catch (e: MmsException) {
|
} catch (e: MmsException) {
|
||||||
throw StorageFailedException(e, metadata.sourceServiceId.toString(), metadata.sourceDeviceId)
|
throw StorageFailedException(e, metadata.sourceServiceId.toString(), metadata.sourceDeviceId)
|
||||||
} finally {
|
} finally {
|
||||||
@@ -743,14 +743,14 @@ object DataMessageProcessor {
|
|||||||
groupId: GroupId.V2?,
|
groupId: GroupId.V2?,
|
||||||
receivedTime: Long
|
receivedTime: Long
|
||||||
): InsertResult? {
|
): InsertResult? {
|
||||||
log(envelope.timestamp!!, "Story reply.")
|
log(envelope.clientTimestamp!!, "Story reply.")
|
||||||
|
|
||||||
val storyContext: DataMessage.StoryContext = message.storyContext!!
|
val storyContext: DataMessage.StoryContext = message.storyContext!!
|
||||||
val authorServiceId: ServiceId = ACI.parseOrThrow(storyContext.authorAci, storyContext.authorAciBinary)
|
val authorServiceId: ServiceId = ACI.parseOrThrow(storyContext.authorAci, storyContext.authorAciBinary)
|
||||||
val sentTimestamp: Long = if (storyContext.sentTimestamp != null) {
|
val sentTimestamp: Long = if (storyContext.sentTimestamp != null) {
|
||||||
storyContext.sentTimestamp!!
|
storyContext.sentTimestamp!!
|
||||||
} else {
|
} else {
|
||||||
warn(envelope.timestamp!!, "Invalid story reply, missing sentTimestamp")
|
warn(envelope.clientTimestamp!!, "Invalid story reply, missing sentTimestamp")
|
||||||
return null
|
return null
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -798,11 +798,11 @@ object DataMessageProcessor {
|
|||||||
quoteModel = QuoteModel(sentTimestamp, storyAuthorRecipientId, displayText, false, story.slideDeck.asAttachments().firstOrNull(), emptyList(), QuoteModel.Type.NORMAL, bodyRanges)
|
quoteModel = QuoteModel(sentTimestamp, storyAuthorRecipientId, displayText, false, story.slideDeck.asAttachments().firstOrNull(), emptyList(), QuoteModel.Type.NORMAL, bodyRanges)
|
||||||
expiresInMillis = message.expireTimerDuration
|
expiresInMillis = message.expireTimerDuration
|
||||||
} else {
|
} else {
|
||||||
warn(envelope.timestamp!!, "Story has replies disabled. Dropping reply.")
|
warn(envelope.clientTimestamp!!, "Story has replies disabled. Dropping reply.")
|
||||||
return null
|
return null
|
||||||
}
|
}
|
||||||
} catch (e: NoSuchMessageException) {
|
} 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
|
return null
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -811,7 +811,7 @@ object DataMessageProcessor {
|
|||||||
val mediaMessage = IncomingMessage(
|
val mediaMessage = IncomingMessage(
|
||||||
type = MessageType.NORMAL,
|
type = MessageType.NORMAL,
|
||||||
from = senderRecipient.id,
|
from = senderRecipient.id,
|
||||||
sentTimeMillis = envelope.timestamp!!,
|
sentTimeMillis = envelope.clientTimestamp!!,
|
||||||
serverTimeMillis = envelope.serverTimestamp!!,
|
serverTimeMillis = envelope.serverTimestamp!!,
|
||||||
receivedTimeMillis = System.currentTimeMillis(),
|
receivedTimeMillis = System.currentTimeMillis(),
|
||||||
parentStoryId = parentStoryId,
|
parentStoryId = parentStoryId,
|
||||||
@@ -843,7 +843,7 @@ object DataMessageProcessor {
|
|||||||
null
|
null
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
warn(envelope.timestamp!!, "Failed to insert story reply.")
|
warn(envelope.clientTimestamp!!, "Failed to insert story reply.")
|
||||||
null
|
null
|
||||||
}
|
}
|
||||||
} catch (e: MmsException) {
|
} catch (e: MmsException) {
|
||||||
@@ -880,7 +880,7 @@ object DataMessageProcessor {
|
|||||||
val mediaMessage = IncomingMessage(
|
val mediaMessage = IncomingMessage(
|
||||||
type = MessageType.NORMAL,
|
type = MessageType.NORMAL,
|
||||||
from = senderRecipient.id,
|
from = senderRecipient.id,
|
||||||
sentTimeMillis = envelope.timestamp!!,
|
sentTimeMillis = envelope.clientTimestamp!!,
|
||||||
serverTimeMillis = envelope.serverTimestamp!!,
|
serverTimeMillis = envelope.serverTimestamp!!,
|
||||||
receivedTimeMillis = receivedTime,
|
receivedTimeMillis = receivedTime,
|
||||||
expiresIn = message.expireTimerDuration.inWholeMilliseconds,
|
expiresIn = message.expireTimerDuration.inWholeMilliseconds,
|
||||||
@@ -917,7 +917,7 @@ object DataMessageProcessor {
|
|||||||
localMetrics: SignalLocalMetrics.MessageReceive?,
|
localMetrics: SignalLocalMetrics.MessageReceive?,
|
||||||
batchCache: BatchCache
|
batchCache: BatchCache
|
||||||
): InsertResult? {
|
): InsertResult? {
|
||||||
log(envelope.timestamp!!, "Media message.")
|
log(envelope.clientTimestamp!!, "Media message.")
|
||||||
|
|
||||||
notifyTypingStoppedFromIncomingMessage(context, senderRecipient, threadRecipient.id, metadata.sourceDeviceId)
|
notifyTypingStoppedFromIncomingMessage(context, senderRecipient, threadRecipient.id, metadata.sourceDeviceId)
|
||||||
|
|
||||||
@@ -925,11 +925,11 @@ object DataMessageProcessor {
|
|||||||
|
|
||||||
SignalDatabase.messages.beginTransaction()
|
SignalDatabase.messages.beginTransaction()
|
||||||
try {
|
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 contacts: List<Contact> = getContacts(message)
|
||||||
val linkPreviews: List<LinkPreview> = getLinkPreviews(message.preview, message.body ?: "", false)
|
val linkPreviews: List<LinkPreview> = getLinkPreviews(message.preview, message.body ?: "", false)
|
||||||
val mentions: List<Mention> = getMentions(message.bodyRanges.take(BODY_RANGE_PROCESSING_LIMIT))
|
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 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
|
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(
|
val mediaMessage = IncomingMessage(
|
||||||
type = MessageType.NORMAL,
|
type = MessageType.NORMAL,
|
||||||
from = senderRecipient.id,
|
from = senderRecipient.id,
|
||||||
sentTimeMillis = envelope.timestamp!!,
|
sentTimeMillis = envelope.clientTimestamp!!,
|
||||||
serverTimeMillis = envelope.serverTimestamp!!,
|
serverTimeMillis = envelope.serverTimestamp!!,
|
||||||
receivedTimeMillis = receivedTime,
|
receivedTimeMillis = receivedTime,
|
||||||
expiresIn = message.expireTimerDuration.inWholeMilliseconds,
|
expiresIn = message.expireTimerDuration.inWholeMilliseconds,
|
||||||
@@ -1018,7 +1018,7 @@ object DataMessageProcessor {
|
|||||||
localMetrics: SignalLocalMetrics.MessageReceive?,
|
localMetrics: SignalLocalMetrics.MessageReceive?,
|
||||||
batchCache: BatchCache
|
batchCache: BatchCache
|
||||||
): InsertResult? {
|
): InsertResult? {
|
||||||
log(envelope.timestamp!!, "Text message.")
|
log(envelope.clientTimestamp!!, "Text message.")
|
||||||
|
|
||||||
val body = message.body ?: ""
|
val body = message.body ?: ""
|
||||||
|
|
||||||
@@ -1029,7 +1029,7 @@ object DataMessageProcessor {
|
|||||||
val textMessage = IncomingMessage(
|
val textMessage = IncomingMessage(
|
||||||
type = MessageType.NORMAL,
|
type = MessageType.NORMAL,
|
||||||
from = senderRecipient.id,
|
from = senderRecipient.id,
|
||||||
sentTimeMillis = envelope.timestamp!!,
|
sentTimeMillis = envelope.clientTimestamp!!,
|
||||||
serverTimeMillis = envelope.serverTimestamp!!,
|
serverTimeMillis = envelope.serverTimestamp!!,
|
||||||
receivedTimeMillis = receivedTime,
|
receivedTimeMillis = receivedTime,
|
||||||
body = body,
|
body = body,
|
||||||
@@ -1058,15 +1058,15 @@ object DataMessageProcessor {
|
|||||||
senderRecipientId: RecipientId,
|
senderRecipientId: RecipientId,
|
||||||
groupId: GroupId.V2?
|
groupId: GroupId.V2?
|
||||||
) {
|
) {
|
||||||
log(envelope.timestamp!!, "Group call update message.")
|
log(envelope.clientTimestamp!!, "Group call update message.")
|
||||||
|
|
||||||
if (groupId == null) {
|
if (groupId == null) {
|
||||||
warn(envelope.timestamp!!, "Invalid group for group call update message")
|
warn(envelope.clientTimestamp!!, "Invalid group for group call update message")
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!SignalDatabase.groups.groupExists(groupId)) {
|
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
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1091,7 +1091,7 @@ object DataMessageProcessor {
|
|||||||
groupId: GroupId.V2?,
|
groupId: GroupId.V2?,
|
||||||
receivedTime: Long
|
receivedTime: Long
|
||||||
): InsertResult? {
|
): InsertResult? {
|
||||||
log(envelope.timestamp!!, "Handle poll creation")
|
log(envelope.clientTimestamp!!, "Handle poll creation")
|
||||||
val poll: DataMessage.PollCreate = message.pollCreate!!
|
val poll: DataMessage.PollCreate = message.pollCreate!!
|
||||||
|
|
||||||
handlePossibleExpirationUpdate(envelope, metadata, senderRecipient, threadRecipient, groupId, message.expireTimerDuration, message.expireTimerVersion, receivedTime)
|
handlePossibleExpirationUpdate(envelope, metadata, senderRecipient, threadRecipient, groupId, message.expireTimerDuration, message.expireTimerVersion, receivedTime)
|
||||||
@@ -1099,28 +1099,28 @@ object DataMessageProcessor {
|
|||||||
if (groupId != null) {
|
if (groupId != null) {
|
||||||
val groupRecord = SignalDatabase.groups.getGroup(groupId).orNull()
|
val groupRecord = SignalDatabase.groups.getGroup(groupId).orNull()
|
||||||
if (groupRecord != null && !groupRecord.members.contains(senderRecipient.id)) {
|
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
|
return null
|
||||||
}
|
}
|
||||||
} else if (senderRecipient.id != threadRecipient.id && senderRecipient.id != Recipient.self().id) {
|
} 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
|
return null
|
||||||
}
|
}
|
||||||
|
|
||||||
if (poll.question == null || poll.question!!.isEmpty() || poll.question!!.length > POLL_QUESTION_CHARACTER_LIMIT) {
|
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
|
return null
|
||||||
}
|
}
|
||||||
|
|
||||||
if (poll.options.isEmpty() || poll.options.size > POLL_OPTIONS_LIMIT || poll.options.any { it.isEmpty() || it.length > POLL_CHARACTER_LIMIT }) {
|
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
|
return null
|
||||||
}
|
}
|
||||||
|
|
||||||
val pollMessage = IncomingMessage(
|
val pollMessage = IncomingMessage(
|
||||||
type = MessageType.NORMAL,
|
type = MessageType.NORMAL,
|
||||||
from = senderRecipient.id,
|
from = senderRecipient.id,
|
||||||
sentTimeMillis = envelope.timestamp!!,
|
sentTimeMillis = envelope.clientTimestamp!!,
|
||||||
serverTimeMillis = envelope.serverTimestamp!!,
|
serverTimeMillis = envelope.serverTimestamp!!,
|
||||||
receivedTimeMillis = receivedTime,
|
receivedTimeMillis = receivedTime,
|
||||||
groupId = groupId,
|
groupId = groupId,
|
||||||
@@ -1159,7 +1159,7 @@ object DataMessageProcessor {
|
|||||||
val pollTerminate: DataMessage.PollTerminate = message.pollTerminate!!
|
val pollTerminate: DataMessage.PollTerminate = message.pollTerminate!!
|
||||||
val targetSentTimestamp = pollTerminate.targetSentTimestamp!!
|
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)
|
handlePossibleExpirationUpdate(envelope, metadata, senderRecipient, threadRecipient, groupId, message.expireTimerDuration, message.expireTimerVersion, receivedTime)
|
||||||
|
|
||||||
@@ -1170,14 +1170,14 @@ object DataMessageProcessor {
|
|||||||
|
|
||||||
val poll = SignalDatabase.polls.getPoll(messageId.id)
|
val poll = SignalDatabase.polls.getPoll(messageId.id)
|
||||||
if (poll == null) {
|
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
|
return null
|
||||||
}
|
}
|
||||||
|
|
||||||
val pollMessage = IncomingMessage(
|
val pollMessage = IncomingMessage(
|
||||||
type = MessageType.POLL_TERMINATE,
|
type = MessageType.POLL_TERMINATE,
|
||||||
from = senderRecipient.id,
|
from = senderRecipient.id,
|
||||||
sentTimeMillis = envelope.timestamp!!,
|
sentTimeMillis = envelope.clientTimestamp!!,
|
||||||
serverTimeMillis = envelope.serverTimestamp!!,
|
serverTimeMillis = envelope.serverTimestamp!!,
|
||||||
receivedTimeMillis = receivedTime,
|
receivedTimeMillis = receivedTime,
|
||||||
groupId = groupId,
|
groupId = groupId,
|
||||||
@@ -1207,11 +1207,11 @@ object DataMessageProcessor {
|
|||||||
val pollVote: DataMessage.PollVote = message.pollVote!!
|
val pollVote: DataMessage.PollVote = message.pollVote!!
|
||||||
val targetSentTimestamp = pollVote.targetSentTimestamp!!
|
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!!)
|
val targetAuthorServiceId: ServiceId = ServiceId.parseOrThrow(pollVote.targetAuthorAciBinary!!)
|
||||||
if (targetAuthorServiceId.isUnknown) {
|
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
|
return null
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1223,30 +1223,30 @@ object DataMessageProcessor {
|
|||||||
val targetMessage = SignalDatabase.messages.getMessageRecord(messageId.id)
|
val targetMessage = SignalDatabase.messages.getMessageRecord(messageId.id)
|
||||||
val pollId = SignalDatabase.polls.getPollId(messageId.id)
|
val pollId = SignalDatabase.polls.getPollId(messageId.id)
|
||||||
if (pollId == null) {
|
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
|
return null
|
||||||
}
|
}
|
||||||
|
|
||||||
val existingVoteCount = SignalDatabase.polls.getCurrentPollVoteCount(pollId, senderRecipient.id.toLong())
|
val existingVoteCount = SignalDatabase.polls.getCurrentPollVoteCount(pollId, senderRecipient.id.toLong())
|
||||||
val currentVoteCount = pollVote.voteCount?.toLong() ?: 0
|
val currentVoteCount = pollVote.voteCount?.toLong() ?: 0
|
||||||
if (currentVoteCount <= existingVoteCount) {
|
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
|
return null
|
||||||
}
|
}
|
||||||
|
|
||||||
val allOptionIds = SignalDatabase.polls.getPollOptionIds(pollId)
|
val allOptionIds = SignalDatabase.polls.getPollOptionIds(pollId)
|
||||||
if (pollVote.optionIndexes.any { it < 0 || it >= allOptionIds.size }) {
|
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
|
return null
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!SignalDatabase.polls.canAllowMultipleVotes(pollId) && pollVote.optionIndexes.size > 1) {
|
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
|
return null
|
||||||
}
|
}
|
||||||
|
|
||||||
if (SignalDatabase.polls.hasEnded(pollId)) {
|
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
|
return null
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1274,13 +1274,13 @@ object DataMessageProcessor {
|
|||||||
earlyMessageCacheEntry: EarlyMessageCacheEntry? = null
|
earlyMessageCacheEntry: EarlyMessageCacheEntry? = null
|
||||||
): InsertResult? {
|
): InsertResult? {
|
||||||
val pinMessage = message.pinMessage!!
|
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)
|
handlePossibleExpirationUpdate(envelope, metadata, senderRecipient, threadRecipient, groupId, message.expireTimerDuration, message.expireTimerVersion, receivedTime)
|
||||||
|
|
||||||
val targetAuthorServiceId: ServiceId = ACI.parseOrThrow(pinMessage.targetAuthorAciBinary!!)
|
val targetAuthorServiceId: ServiceId = ACI.parseOrThrow(pinMessage.targetAuthorAciBinary!!)
|
||||||
if (targetAuthorServiceId.isUnknown) {
|
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
|
return null
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1288,7 +1288,7 @@ object DataMessageProcessor {
|
|||||||
|
|
||||||
val targetMessage: MmsMessageRecord? = SignalDatabase.messages.getMessageFor(pinMessage.targetSentTimestamp!!, targetAuthor.id) as? MmsMessageRecord
|
val targetMessage: MmsMessageRecord? = SignalDatabase.messages.getMessageFor(pinMessage.targetSentTimestamp!!, targetAuthor.id) as? MmsMessageRecord
|
||||||
if (targetMessage == null) {
|
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) {
|
if (earlyMessageCacheEntry != null) {
|
||||||
AppDependencies.earlyMessageCache.store(targetAuthor.id, pinMessage.targetSentTimestamp!!, earlyMessageCacheEntry)
|
AppDependencies.earlyMessageCache.store(targetAuthor.id, pinMessage.targetSentTimestamp!!, earlyMessageCacheEntry)
|
||||||
PushProcessEarlyMessagesJob.enqueue()
|
PushProcessEarlyMessagesJob.enqueue()
|
||||||
@@ -1297,38 +1297,38 @@ object DataMessageProcessor {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (targetMessage.isRemoteDelete) {
|
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
|
return null
|
||||||
}
|
}
|
||||||
|
|
||||||
if (targetMessage.hasGiftBadge()) {
|
if (targetMessage.hasGiftBadge()) {
|
||||||
warn(envelope.timestamp!!, "[handlePinMessage] Cannot pin a gift badge")
|
warn(envelope.clientTimestamp!!, "[handlePinMessage] Cannot pin a gift badge")
|
||||||
return null
|
return null
|
||||||
}
|
}
|
||||||
|
|
||||||
val targetThread = SignalDatabase.threads.getThreadRecord(targetMessage.threadId)
|
val targetThread = SignalDatabase.threads.getThreadRecord(targetMessage.threadId)
|
||||||
if (targetThread == null) {
|
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
|
return null
|
||||||
}
|
}
|
||||||
|
|
||||||
if (targetThread.recipient.id != threadRecipient.id) {
|
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
|
return null
|
||||||
}
|
}
|
||||||
|
|
||||||
val groupRecord = SignalDatabase.groups.getGroup(threadRecipient.id).orNull()
|
val groupRecord = SignalDatabase.groups.getGroup(threadRecipient.id).orNull()
|
||||||
if (groupRecord != null && !groupRecord.members.contains(senderRecipient.id)) {
|
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
|
return null
|
||||||
}
|
}
|
||||||
if (groupRecord != null && groupRecord.attributesAccessControl == GroupAccessControl.ONLY_ADMINS && !groupRecord.isAdmin(senderRecipient)) {
|
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
|
return null
|
||||||
}
|
}
|
||||||
|
|
||||||
if (groupRecord == null && senderRecipient.id != threadRecipient.id && Recipient.self().id != senderRecipient.id) {
|
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
|
return null
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1337,7 +1337,7 @@ object DataMessageProcessor {
|
|||||||
val pinnedMessage = IncomingMessage(
|
val pinnedMessage = IncomingMessage(
|
||||||
type = MessageType.PINNED_MESSAGE,
|
type = MessageType.PINNED_MESSAGE,
|
||||||
from = senderRecipient.id,
|
from = senderRecipient.id,
|
||||||
sentTimeMillis = envelope.timestamp!!,
|
sentTimeMillis = envelope.clientTimestamp!!,
|
||||||
serverTimeMillis = envelope.serverTimestamp!!,
|
serverTimeMillis = envelope.serverTimestamp!!,
|
||||||
receivedTimeMillis = receivedTime,
|
receivedTimeMillis = receivedTime,
|
||||||
expiresIn = message.expireTimerDuration.inWholeMilliseconds,
|
expiresIn = message.expireTimerDuration.inWholeMilliseconds,
|
||||||
@@ -1350,7 +1350,7 @@ object DataMessageProcessor {
|
|||||||
val insertResult: InsertResult? = SignalDatabase.messages.insertMessageInbox(pinnedMessage).orNull()
|
val insertResult: InsertResult? = SignalDatabase.messages.insertMessageInbox(pinnedMessage).orNull()
|
||||||
|
|
||||||
return if (insertResult != null) {
|
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) {
|
if (duration != MessageTable.PIN_FOREVER) {
|
||||||
AppDependencies.pinnedMessageManager.scheduleIfNecessary()
|
AppDependencies.pinnedMessageManager.scheduleIfNecessary()
|
||||||
}
|
}
|
||||||
@@ -1368,11 +1368,11 @@ object DataMessageProcessor {
|
|||||||
earlyMessageCacheEntry: EarlyMessageCacheEntry? = null
|
earlyMessageCacheEntry: EarlyMessageCacheEntry? = null
|
||||||
): MessageId? {
|
): MessageId? {
|
||||||
val unpinMessage = message.unpinMessage!!
|
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!!)
|
val targetAuthorServiceId: ServiceId = ACI.parseOrThrow(unpinMessage.targetAuthorAciBinary!!)
|
||||||
if (targetAuthorServiceId.isUnknown) {
|
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
|
return null
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1380,7 +1380,7 @@ object DataMessageProcessor {
|
|||||||
|
|
||||||
val targetMessage: MmsMessageRecord? = SignalDatabase.messages.getMessageFor(unpinMessage.targetSentTimestamp!!, targetAuthor.id) as? MmsMessageRecord
|
val targetMessage: MmsMessageRecord? = SignalDatabase.messages.getMessageFor(unpinMessage.targetSentTimestamp!!, targetAuthor.id) as? MmsMessageRecord
|
||||||
if (targetMessage == null) {
|
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) {
|
if (earlyMessageCacheEntry != null) {
|
||||||
AppDependencies.earlyMessageCache.store(targetAuthor.id, unpinMessage.targetSentTimestamp!!, earlyMessageCacheEntry)
|
AppDependencies.earlyMessageCache.store(targetAuthor.id, unpinMessage.targetSentTimestamp!!, earlyMessageCacheEntry)
|
||||||
PushProcessEarlyMessagesJob.enqueue()
|
PushProcessEarlyMessagesJob.enqueue()
|
||||||
@@ -1389,38 +1389,38 @@ object DataMessageProcessor {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (targetMessage.isRemoteDelete) {
|
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
|
return null
|
||||||
}
|
}
|
||||||
|
|
||||||
if (targetMessage.hasGiftBadge()) {
|
if (targetMessage.hasGiftBadge()) {
|
||||||
warn(envelope.timestamp!!, "[handleUnpinMessage] Cannot pin a gift badge")
|
warn(envelope.clientTimestamp!!, "[handleUnpinMessage] Cannot pin a gift badge")
|
||||||
return null
|
return null
|
||||||
}
|
}
|
||||||
|
|
||||||
val targetThread = SignalDatabase.threads.getThreadRecord(targetMessage.threadId)
|
val targetThread = SignalDatabase.threads.getThreadRecord(targetMessage.threadId)
|
||||||
if (targetThread == null) {
|
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
|
return null
|
||||||
}
|
}
|
||||||
|
|
||||||
if (targetThread.recipient.id != threadRecipient.id) {
|
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
|
return null
|
||||||
}
|
}
|
||||||
|
|
||||||
val groupRecord = SignalDatabase.groups.getGroup(threadRecipient.id).orNull()
|
val groupRecord = SignalDatabase.groups.getGroup(threadRecipient.id).orNull()
|
||||||
if (groupRecord != null && !groupRecord.members.contains(senderRecipient.id)) {
|
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
|
return null
|
||||||
}
|
}
|
||||||
if (groupRecord != null && groupRecord.attributesAccessControl == GroupAccessControl.ONLY_ADMINS && !groupRecord.isAdmin(senderRecipient)) {
|
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
|
return null
|
||||||
}
|
}
|
||||||
|
|
||||||
if (groupRecord == null && senderRecipient.id != threadRecipient.id && Recipient.self().id != senderRecipient.id) {
|
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
|
return null
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1432,25 +1432,25 @@ object DataMessageProcessor {
|
|||||||
|
|
||||||
fun handleAdminRemoteDelete(context: Context, envelope: Envelope, message: DataMessage, senderRecipient: Recipient, threadRecipient: Recipient, earlyMessageCacheEntry: EarlyMessageCacheEntry?): MessageId? {
|
fun handleAdminRemoteDelete(context: Context, envelope: Envelope, message: DataMessage, senderRecipient: Recipient, threadRecipient: Recipient, earlyMessageCacheEntry: EarlyMessageCacheEntry?): MessageId? {
|
||||||
if (!RemoteConfig.receiveAdminDelete) {
|
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
|
return null
|
||||||
}
|
}
|
||||||
|
|
||||||
val delete = message.adminDelete!!
|
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 targetSentTimestamp: Long = delete.targetSentTimestamp!!
|
||||||
val targetAuthorServiceId: ServiceId = ACI.parseOrThrow(delete.targetAuthorAciBinary!!)
|
val targetAuthorServiceId: ServiceId = ACI.parseOrThrow(delete.targetAuthorAciBinary!!)
|
||||||
if (targetAuthorServiceId.isUnknown) {
|
if (targetAuthorServiceId.isUnknown) {
|
||||||
warn(envelope.timestamp!!, "[handleAdminRemoteDelete] Invalid author.")
|
warn(envelope.clientTimestamp!!, "[handleAdminRemoteDelete] Invalid author.")
|
||||||
return null
|
return null
|
||||||
}
|
}
|
||||||
val targetAuthor = Recipient.externalPush(targetAuthorServiceId)
|
val targetAuthor = Recipient.externalPush(targetAuthorServiceId)
|
||||||
|
|
||||||
val targetMessage: MessageRecord? = SignalDatabase.messages.getMessageFor(targetSentTimestamp, targetAuthor.id)
|
val targetMessage: MessageRecord? = SignalDatabase.messages.getMessageFor(targetSentTimestamp, targetAuthor.id)
|
||||||
if (targetMessage == null) {
|
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) {
|
if (earlyMessageCacheEntry != null) {
|
||||||
AppDependencies.earlyMessageCache.store(targetAuthor.id, targetSentTimestamp, earlyMessageCacheEntry)
|
AppDependencies.earlyMessageCache.store(targetAuthor.id, targetSentTimestamp, earlyMessageCacheEntry)
|
||||||
PushProcessEarlyMessagesJob.enqueue()
|
PushProcessEarlyMessagesJob.enqueue()
|
||||||
@@ -1460,19 +1460,19 @@ object DataMessageProcessor {
|
|||||||
|
|
||||||
val targetThread = SignalDatabase.threads.getThreadRecord(targetMessage.threadId)
|
val targetThread = SignalDatabase.threads.getThreadRecord(targetMessage.threadId)
|
||||||
if (targetThread == null) {
|
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
|
return null
|
||||||
}
|
}
|
||||||
|
|
||||||
val targetThreadRecipientId = targetThread.recipient.id
|
val targetThreadRecipientId = targetThread.recipient.id
|
||||||
if (targetThreadRecipientId != threadRecipient.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
|
return null
|
||||||
}
|
}
|
||||||
|
|
||||||
val groupRecord = SignalDatabase.groups.getGroup(targetThreadRecipientId).orNull()
|
val groupRecord = SignalDatabase.groups.getGroup(targetThreadRecipientId).orNull()
|
||||||
if (groupRecord == null || !groupRecord.isV2Group) {
|
if (groupRecord == null || !groupRecord.isV2Group) {
|
||||||
warn(envelope.timestamp!!, "[handleAdminRemoteDelete] Invalid group.")
|
warn(envelope.clientTimestamp!!, "[handleAdminRemoteDelete] Invalid group.")
|
||||||
return null
|
return null
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1481,7 +1481,7 @@ object DataMessageProcessor {
|
|||||||
AppDependencies.messageNotifier.updateNotification(context, ConversationId.fromMessageRecord(targetMessage))
|
AppDependencies.messageNotifier.updateNotification(context, ConversationId.fromMessageRecord(targetMessage))
|
||||||
MessageId(targetMessage.id)
|
MessageId(targetMessage.id)
|
||||||
} else {
|
} 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
|
null
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1627,7 +1627,7 @@ object DataMessageProcessor {
|
|||||||
): MessageId? {
|
): MessageId? {
|
||||||
val targetMessage = SignalDatabase.messages.getMessageFor(targetSentTimestamp, targetAuthor.id)
|
val targetMessage = SignalDatabase.messages.getMessageFor(targetSentTimestamp, targetAuthor.id)
|
||||||
if (targetMessage == null) {
|
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) {
|
if (earlyMessageCacheEntry != null) {
|
||||||
AppDependencies.earlyMessageCache.store(senderRecipient.id, targetSentTimestamp, earlyMessageCacheEntry)
|
AppDependencies.earlyMessageCache.store(senderRecipient.id, targetSentTimestamp, earlyMessageCacheEntry)
|
||||||
PushProcessEarlyMessagesJob.enqueue()
|
PushProcessEarlyMessagesJob.enqueue()
|
||||||
@@ -1636,22 +1636,22 @@ object DataMessageProcessor {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (targetMessage.isRemoteDelete) {
|
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
|
return null
|
||||||
}
|
}
|
||||||
|
|
||||||
val targetThread = SignalDatabase.threads.getThreadRecord(targetMessage.threadId)
|
val targetThread = SignalDatabase.threads.getThreadRecord(targetMessage.threadId)
|
||||||
if (targetThread == null) {
|
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
|
return null
|
||||||
}
|
}
|
||||||
|
|
||||||
val groupRecord = SignalDatabase.groups.getGroup(targetThread.recipient.id).orNull()
|
val groupRecord = SignalDatabase.groups.getGroup(targetThread.recipient.id).orNull()
|
||||||
if (groupRecord != null && !groupRecord.members.contains(senderRecipient.id)) {
|
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
|
return null
|
||||||
} else if (groupRecord == null && senderRecipient.id != targetThread.recipient.id && senderRecipient.id != Recipient.self().id) {
|
} 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
|
return null
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -50,13 +50,13 @@ object EditMessageProcessor {
|
|||||||
) {
|
) {
|
||||||
val editMessage = content.editMessage!!
|
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
|
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
|
val targetThreadRecipient: Recipient? = if (targetMessage != null) SignalDatabase.threads.getRecipientForThreadId(targetMessage.threadId) else null
|
||||||
|
|
||||||
if (targetMessage == null || targetThreadRecipient == 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) {
|
if (earlyMessageCacheEntry != null) {
|
||||||
AppDependencies.earlyMessageCache.store(senderRecipient.id, editMessage.targetSentTimestamp!!, earlyMessageCacheEntry)
|
AppDependencies.earlyMessageCache.store(senderRecipient.id, editMessage.targetSentTimestamp!!, earlyMessageCacheEntry)
|
||||||
@@ -78,12 +78,12 @@ object EditMessageProcessor {
|
|||||||
val validTarget = !originalMessage.isViewOnce && !originalMessage.hasAudio() && !originalMessage.hasSharedContact()
|
val validTarget = !originalMessage.isViewOnce && !originalMessage.hasAudio() && !originalMessage.hasSharedContact()
|
||||||
|
|
||||||
if (!validTiming || !validAuthor || !validGroup || !validTarget) {
|
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
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
if (groupId != null && MessageContentProcessor.handleGv2PreProcessing(context, envelope.timestamp!!, content, metadata, groupId, message.groupV2!!, senderRecipient) == MessageContentProcessor.Gv2PreProcessResult.IGNORE) {
|
if (groupId != null && MessageContentProcessor.handleGv2PreProcessing(context, envelope.clientTimestamp!!, content, metadata, groupId, message.groupV2!!, senderRecipient) == MessageContentProcessor.Gv2PreProcessResult.IGNORE) {
|
||||||
warn(envelope.timestamp!!, "[handleEditMessage] Group processor indicated we should ignore this.")
|
warn(envelope.clientTimestamp!!, "[handleEditMessage] Group processor indicated we should ignore this.")
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -187,8 +187,8 @@ object EditMessageProcessor {
|
|||||||
val textMessage = IncomingMessage(
|
val textMessage = IncomingMessage(
|
||||||
type = MessageType.NORMAL,
|
type = MessageType.NORMAL,
|
||||||
from = senderRecipientId,
|
from = senderRecipientId,
|
||||||
sentTimeMillis = envelope.timestamp!!,
|
sentTimeMillis = envelope.clientTimestamp!!,
|
||||||
serverTimeMillis = envelope.timestamp!!,
|
serverTimeMillis = envelope.clientTimestamp!!,
|
||||||
receivedTimeMillis = targetMessage.dateReceived,
|
receivedTimeMillis = targetMessage.dateReceived,
|
||||||
body = message.body,
|
body = message.body,
|
||||||
groupId = groupId,
|
groupId = groupId,
|
||||||
|
|||||||
@@ -291,8 +291,8 @@ class IncomingMessageObserver(
|
|||||||
null
|
null
|
||||||
}
|
}
|
||||||
|
|
||||||
Envelope.Type.PREKEY_BUNDLE,
|
Envelope.Type.PREKEY_MESSAGE,
|
||||||
Envelope.Type.CIPHERTEXT,
|
Envelope.Type.DOUBLE_RATCHET,
|
||||||
Envelope.Type.UNIDENTIFIED_SENDER,
|
Envelope.Type.UNIDENTIFIED_SENDER,
|
||||||
Envelope.Type.PLAINTEXT_CONTENT -> {
|
Envelope.Type.PLAINTEXT_CONTENT -> {
|
||||||
SignalTrace.beginSection("IncomingMessageObserver#processMessage")
|
SignalTrace.beginSection("IncomingMessageObserver#processMessage")
|
||||||
@@ -343,7 +343,7 @@ class IncomingMessageObserver(
|
|||||||
jobs += PushProcessMessageErrorJob(
|
jobs += PushProcessMessageErrorJob(
|
||||||
result.toMessageState(),
|
result.toMessageState(),
|
||||||
result.errorMetadata.toExceptionMetadata(),
|
result.errorMetadata.toExceptionMetadata(),
|
||||||
result.envelope.timestamp!!
|
result.envelope.clientTimestamp!!
|
||||||
)
|
)
|
||||||
|
|
||||||
AppDependencies.jobManager.startChain(jobs)
|
AppDependencies.jobManager.startChain(jobs)
|
||||||
@@ -369,9 +369,9 @@ class IncomingMessageObserver(
|
|||||||
|
|
||||||
val senderId = RecipientId.from(serviceId)
|
val senderId = RecipientId.from(serviceId)
|
||||||
|
|
||||||
Log.i(TAG, "Received server receipt. Sender: $senderId, Device: ${envelope.sourceDevice}, Timestamp: ${envelope.timestamp}")
|
Log.i(TAG, "Received server receipt. Sender: $senderId, Device: ${envelope.sourceDeviceId}, Timestamp: ${envelope.clientTimestamp}")
|
||||||
SignalDatabase.messages.incrementDeliveryReceiptCount(envelope.timestamp!!, senderId, System.currentTimeMillis())
|
SignalDatabase.messages.incrementDeliveryReceiptCount(envelope.clientTimestamp!!, senderId, System.currentTimeMillis())
|
||||||
SignalDatabase.messageLog.deleteEntryForRecipient(envelope.timestamp!!, senderId, envelope.sourceDevice!!)
|
SignalDatabase.messageLog.deleteEntryForRecipient(envelope.clientTimestamp!!, senderId, envelope.sourceDeviceId!!)
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun MessageDecryptor.Result.toMessageState(): MessageState {
|
private fun MessageDecryptor.Result.toMessageState(): MessageState {
|
||||||
|
|||||||
@@ -350,11 +350,11 @@ open class MessageContentProcessor(private val context: Context) {
|
|||||||
|
|
||||||
val earlyCacheEntries: List<EarlyMessageCacheEntry>? = AppDependencies
|
val earlyCacheEntries: List<EarlyMessageCacheEntry>? = AppDependencies
|
||||||
.earlyMessageCache
|
.earlyMessageCache
|
||||||
.retrieve(senderRecipient.id, envelope.timestamp!!)
|
.retrieve(senderRecipient.id, envelope.clientTimestamp!!)
|
||||||
.orNull()
|
.orNull()
|
||||||
|
|
||||||
if (!processingEarlyContent && earlyCacheEntries != null) {
|
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) {
|
for (entry in earlyCacheEntries) {
|
||||||
handleMessage(senderRecipient, entry.envelope, entry.content, entry.metadata, entry.serverDeliveredTimestamp, processingEarlyContent = true, localMetric = null, batchCache)
|
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)
|
val threadRecipient = getMessageDestination(content, senderRecipient)
|
||||||
|
|
||||||
if (shouldIgnore(content, senderRecipient, threadRecipient)) {
|
if (shouldIgnore(content, senderRecipient, threadRecipient)) {
|
||||||
log(envelope.timestamp!!, "Ignoring message.")
|
log(envelope.clientTimestamp!!, "Ignoring message.")
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
val pending: PendingRetryReceiptModel? = AppDependencies.pendingRetryReceiptCache.get(senderRecipient.id, envelope.timestamp!!)
|
val pending: PendingRetryReceiptModel? = AppDependencies.pendingRetryReceiptCache.get(senderRecipient.id, envelope.clientTimestamp!!)
|
||||||
val receivedTime: Long = handlePendingRetry(pending, envelope.timestamp!!, threadRecipient)
|
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()
|
localMetric?.onPreProcessComplete()
|
||||||
when {
|
when {
|
||||||
content.dataMessage != null -> {
|
content.dataMessage != null -> {
|
||||||
@@ -482,12 +482,12 @@ open class MessageContentProcessor(private val context: Context) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
content.callMessage != null -> {
|
content.callMessage != null -> {
|
||||||
log(envelope.timestamp!!, "Got call message...")
|
log(envelope.clientTimestamp!!, "Got call message...")
|
||||||
|
|
||||||
val message: CallMessage = content.callMessage!!
|
val message: CallMessage = content.callMessage!!
|
||||||
|
|
||||||
if (message.destinationDeviceId != null && message.destinationDeviceId != SignalStore.account.deviceId) {
|
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
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -541,12 +541,12 @@ open class MessageContentProcessor(private val context: Context) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
else -> {
|
else -> {
|
||||||
warn(envelope.timestamp!!, "Got unrecognized message!")
|
warn(envelope.clientTimestamp!!, "Got unrecognized message!")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (pending != null) {
|
if (pending != null) {
|
||||||
warn(envelope.timestamp!!, "Pending retry was processed. Deleting.")
|
warn(envelope.clientTimestamp!!, "Pending retry was processed. Deleting.")
|
||||||
AppDependencies.pendingRetryReceiptCache.delete(pending)
|
AppDependencies.pendingRetryReceiptCache.delete(pending)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -565,7 +565,7 @@ open class MessageContentProcessor(private val context: Context) {
|
|||||||
val threadId: Long = if (typingMessage.groupId != null) {
|
val threadId: Long = if (typingMessage.groupId != null) {
|
||||||
val groupId = GroupId.push(typingMessage.groupId!!)
|
val groupId = GroupId.push(typingMessage.groupId!!)
|
||||||
if (!SignalDatabase.groups.isCurrentMember(groupId, senderRecipient.id)) {
|
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
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -576,7 +576,7 @@ open class MessageContentProcessor(private val context: Context) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (threadId <= 0) {
|
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
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -591,19 +591,19 @@ open class MessageContentProcessor(private val context: Context) {
|
|||||||
|
|
||||||
private fun handleRetryReceipt(envelope: Envelope, metadata: EnvelopeMetadata, decryptionErrorMessage: DecryptionErrorMessage, senderRecipient: Recipient) {
|
private fun handleRetryReceipt(envelope: Envelope, metadata: EnvelopeMetadata, decryptionErrorMessage: DecryptionErrorMessage, senderRecipient: Recipient) {
|
||||||
if (!RemoteConfig.retryReceipts) {
|
if (!RemoteConfig.retryReceipts) {
|
||||||
warn(envelope.timestamp!!, "[RetryReceipt] Feature flag disabled, skipping retry receipt.")
|
warn(envelope.clientTimestamp!!, "[RetryReceipt] Feature flag disabled, skipping retry receipt.")
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
if (decryptionErrorMessage.deviceId != SignalStore.account.deviceId) {
|
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
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
val sentTimestamp = decryptionErrorMessage.timestamp
|
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) {
|
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
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -626,18 +626,18 @@ open class MessageContentProcessor(private val context: Context) {
|
|||||||
val relatedMessage = findRetryReceiptRelatedMessage(messageLogEntry, sentTimestamp)
|
val relatedMessage = findRetryReceiptRelatedMessage(messageLogEntry, sentTimestamp)
|
||||||
|
|
||||||
if (relatedMessage == null) {
|
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
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
val threadRecipient = SignalDatabase.threads.getRecipientForThreadId(relatedMessage.threadId)
|
val threadRecipient = SignalDatabase.threads.getRecipientForThreadId(relatedMessage.threadId)
|
||||||
if (threadRecipient == null) {
|
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
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!threadRecipient.isPushV2Group && !threadRecipient.isDistributionList) {
|
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
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -661,7 +661,7 @@ open class MessageContentProcessor(private val context: Context) {
|
|||||||
SignalDatabase.senderKeyShared.delete(distributionId, setOf(requesterAddress))
|
SignalDatabase.senderKeyShared.delete(distributionId, setOf(requesterAddress))
|
||||||
|
|
||||||
if (messageLogEntry != null) {
|
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(
|
AppDependencies.jobManager.add(
|
||||||
ResendMessageJob(
|
ResendMessageJob(
|
||||||
messageLogEntry.recipientId,
|
messageLogEntry.recipientId,
|
||||||
@@ -674,7 +674,7 @@ open class MessageContentProcessor(private val context: Context) {
|
|||||||
)
|
)
|
||||||
)
|
)
|
||||||
} else {
|
} 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))
|
AppDependencies.jobManager.add(SenderKeyDistributionSendJob(requester.id, threadRecipient.id))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -683,24 +683,24 @@ open class MessageContentProcessor(private val context: Context) {
|
|||||||
var archivedSession = false
|
var archivedSession = false
|
||||||
|
|
||||||
if (ServiceId.parseOrNull(envelope.destinationServiceId, envelope.destinationServiceIdBinary) is ServiceId.PNI) {
|
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
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
if (decryptionErrorMessage.ratchetKey.isPresent) {
|
if (decryptionErrorMessage.ratchetKey.isPresent) {
|
||||||
if (ratchetKeyMatches(requester, metadata.sourceDeviceId, decryptionErrorMessage.ratchetKey.get())) {
|
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)
|
AppDependencies.protocolStore.aci().sessions().archiveSession(requester.requireServiceId(), metadata.sourceDeviceId)
|
||||||
archivedSession = true
|
archivedSession = true
|
||||||
} else {
|
} 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 {
|
} 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) {
|
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(
|
AppDependencies.jobManager.add(
|
||||||
ResendMessageJob(
|
ResendMessageJob(
|
||||||
messageLogEntry.recipientId,
|
messageLogEntry.recipientId,
|
||||||
@@ -713,10 +713,10 @@ open class MessageContentProcessor(private val context: Context) {
|
|||||||
)
|
)
|
||||||
)
|
)
|
||||||
} else if (archivedSession) {
|
} 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))
|
AppDependencies.jobManager.add(NullMessageSendJob(requester.id))
|
||||||
} else {
|
} 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.")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -142,7 +142,7 @@ object MessageDecryptor {
|
|||||||
|
|
||||||
val followUpOperations: MutableList<FollowUpOperation> = mutableListOf()
|
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.")
|
Log.i(TAG, "${logPrefix(envelope)} Prekey message. Scheduling a prekey sync job.")
|
||||||
followUpOperations += FollowUpOperation {
|
followUpOperations += FollowUpOperation {
|
||||||
PreKeysSyncJob.create().asChain()
|
PreKeysSyncJob.create().asChain()
|
||||||
@@ -164,7 +164,7 @@ object MessageDecryptor {
|
|||||||
envelope.newBuilder()
|
envelope.newBuilder()
|
||||||
.sourceServiceId(if (BuildConfig.USE_STRING_ID) cipherResult.metadata.sourceServiceId.toString() else null)
|
.sourceServiceId(if (BuildConfig.USE_STRING_ID) cipherResult.metadata.sourceServiceId.toString() else null)
|
||||||
.sourceServiceIdBinary(if (RemoteConfig.useBinaryId) cipherResult.metadata.sourceServiceId.toByteString() else null)
|
.sourceServiceIdBinary(if (RemoteConfig.useBinaryId) cipherResult.metadata.sourceServiceId.toByteString() else null)
|
||||||
.sourceDevice(cipherResult.metadata.sourceDeviceId)
|
.sourceDeviceId(cipherResult.metadata.sourceDeviceId)
|
||||||
.build()
|
.build()
|
||||||
} else {
|
} else {
|
||||||
envelope
|
envelope
|
||||||
@@ -255,7 +255,7 @@ object MessageDecryptor {
|
|||||||
|
|
||||||
followUpOperations += FollowUpOperation {
|
followUpOperations += FollowUpOperation {
|
||||||
Recipient.external(e.sender)?.let {
|
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!")
|
} ?: null.logW(TAG, "${logPrefix(envelope, e)} Failed to create a recipient with the provided identifier!")
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -276,7 +276,7 @@ object MessageDecryptor {
|
|||||||
}
|
}
|
||||||
|
|
||||||
is SelfSendException -> {
|
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())
|
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)
|
Log.w(TAG, "${logPrefix(envelope)} Decryption error for a sync message! Enqueuing a session reset job.", true)
|
||||||
|
|
||||||
followUpOperations += FollowUpOperation {
|
followUpOperations += FollowUpOperation {
|
||||||
AutomaticSessionResetJob(sender.id, senderDevice, envelope.timestamp!!).asChain()
|
AutomaticSessionResetJob(sender.id, senderDevice, envelope.clientTimestamp!!).asChain()
|
||||||
}
|
}
|
||||||
|
|
||||||
return Result.Ignore(envelope, serverDeliveredTimestamp, followUpOperations)
|
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
|
// 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.
|
// 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)
|
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)
|
PreKeysSyncJob.create(forceRotationRequested = true).asChain().then(retryJob)
|
||||||
} else {
|
} else {
|
||||||
@@ -392,7 +392,7 @@ object MessageDecryptor {
|
|||||||
return@FollowUpOperation null
|
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()
|
AppDependencies.pendingRetryReceiptManager.scheduleIfNecessary()
|
||||||
null
|
null
|
||||||
}
|
}
|
||||||
@@ -491,26 +491,26 @@ object MessageDecryptor {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private fun logPrefix(envelope: Envelope): String {
|
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 {
|
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 {
|
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 {
|
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 {
|
private fun logPrefix(envelope: Envelope, exception: ProtocolException): String {
|
||||||
return if (exception.sender != null) {
|
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 {
|
} 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()
|
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)
|
val groupId: GroupId? = protocolException.parseGroupId(envelope)
|
||||||
return SendRetryReceiptJob(sender.id, Optional.ofNullable(groupId), decryptionErrorMessage)
|
return SendRetryReceiptJob(sender.id, Optional.ofNullable(groupId), decryptionErrorMessage)
|
||||||
}
|
}
|
||||||
@@ -541,7 +541,7 @@ object MessageDecryptor {
|
|||||||
try {
|
try {
|
||||||
GroupId.push(this.groupId.get())
|
GroupId.push(this.groupId.get())
|
||||||
} catch (e: BadGroupIdException) {
|
} catch (e: BadGroupIdException) {
|
||||||
Log.w(TAG, "[${envelope.timestamp}] Bad groupId!", true)
|
Log.w(TAG, "[${envelope.clientTimestamp}] Bad groupId!", true)
|
||||||
null
|
null
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
@@ -551,8 +551,8 @@ object MessageDecryptor {
|
|||||||
|
|
||||||
private fun Int.toCiphertextMessageType(): Int {
|
private fun Int.toCiphertextMessageType(): Int {
|
||||||
return when (this) {
|
return when (this) {
|
||||||
Envelope.Type.CIPHERTEXT.value -> CiphertextMessage.WHISPER_TYPE
|
Envelope.Type.DOUBLE_RATCHET.value -> CiphertextMessage.WHISPER_TYPE
|
||||||
Envelope.Type.PREKEY_BUNDLE.value -> CiphertextMessage.PREKEY_TYPE
|
Envelope.Type.PREKEY_MESSAGE.value -> CiphertextMessage.PREKEY_TYPE
|
||||||
Envelope.Type.UNIDENTIFIED_SENDER.value -> CiphertextMessage.SENDERKEY_TYPE
|
Envelope.Type.UNIDENTIFIED_SENDER.value -> CiphertextMessage.SENDERKEY_TYPE
|
||||||
Envelope.Type.PLAINTEXT_CONTENT.value -> CiphertextMessage.PLAINTEXT_CONTENT_TYPE
|
Envelope.Type.PLAINTEXT_CONTENT.value -> CiphertextMessage.PLAINTEXT_CONTENT_TYPE
|
||||||
else -> CiphertextMessage.WHISPER_TYPE
|
else -> CiphertextMessage.WHISPER_TYPE
|
||||||
|
|||||||
@@ -31,7 +31,7 @@ object ReceiptMessageProcessor {
|
|||||||
ReceiptMessage.Type.DELIVERY -> handleDeliveryReceipt(envelope, metadata, receiptMessage, senderRecipient.id, batchCache)
|
ReceiptMessage.Type.DELIVERY -> handleDeliveryReceipt(envelope, metadata, receiptMessage, senderRecipient.id, batchCache)
|
||||||
ReceiptMessage.Type.READ -> handleReadReceipt(context, senderRecipient.id, envelope, metadata, receiptMessage, earlyMessageCacheEntry, batchCache)
|
ReceiptMessage.Type.READ -> handleReadReceipt(context, senderRecipient.id, envelope, metadata, receiptMessage, earlyMessageCacheEntry, batchCache)
|
||||||
ReceiptMessage.Type.VIEWED -> handleViewedReceipt(context, envelope, metadata, receiptMessage, senderRecipient.id, earlyMessageCacheEntry)
|
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,
|
senderRecipientId: RecipientId,
|
||||||
batchCache: BatchCache
|
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
|
val stopwatch: Stopwatch? = if (VERBOSE) Stopwatch("delivery-receipt", decimalPlaces = 2) else null
|
||||||
|
|
||||||
SignalTrace.beginSection("ReceiptMessageProcessor#incrementDeliveryReceiptCounts")
|
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()
|
SignalTrace.endSection()
|
||||||
|
|
||||||
for (targetTimestamp in missingTargetTimestamps) {
|
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
|
// Early delivery receipts are special-cased in the database methods
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -79,21 +79,21 @@ object ReceiptMessageProcessor {
|
|||||||
batchCache: BatchCache
|
batchCache: BatchCache
|
||||||
) {
|
) {
|
||||||
if (!TextSecurePreferences.isReadReceiptsEnabled(context)) {
|
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
|
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")
|
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()
|
SignalTrace.endSection()
|
||||||
|
|
||||||
if (missingTargetTimestamps.isNotEmpty()) {
|
if (missingTargetTimestamps.isNotEmpty()) {
|
||||||
val selfId = Recipient.self().id
|
val selfId = Recipient.self().id
|
||||||
|
|
||||||
for (targetTimestamp in missingTargetTimestamps) {
|
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) {
|
if (earlyMessageCacheEntry != null) {
|
||||||
AppDependencies.earlyMessageCache.store(selfId, targetTimestamp, earlyMessageCacheEntry)
|
AppDependencies.earlyMessageCache.store(selfId, targetTimestamp, earlyMessageCacheEntry)
|
||||||
}
|
}
|
||||||
@@ -117,18 +117,18 @@ object ReceiptMessageProcessor {
|
|||||||
val storyViewedReceipts = SignalStore.story.viewedReceiptsEnabled
|
val storyViewedReceipts = SignalStore.story.viewedReceiptsEnabled
|
||||||
|
|
||||||
if (!readReceipts && !storyViewedReceipts) {
|
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
|
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) {
|
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) {
|
} else if (readReceipts) {
|
||||||
SignalDatabase.messages.incrementViewedNonStoryReceiptCounts(viewedReceipt.timestamp, senderRecipientId, envelope.timestamp!!)
|
SignalDatabase.messages.incrementViewedNonStoryReceiptCounts(viewedReceipt.timestamp, senderRecipientId, envelope.clientTimestamp!!)
|
||||||
} else {
|
} 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()
|
val foundTargetTimestamps: Set<Long> = viewedReceipt.timestamp.toSet() - missingTargetTimestamps.toSet()
|
||||||
@@ -138,7 +138,7 @@ object ReceiptMessageProcessor {
|
|||||||
val selfId = Recipient.self().id
|
val selfId = Recipient.self().id
|
||||||
|
|
||||||
for (targetTimestamp in missingTargetTimestamps) {
|
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) {
|
if (earlyMessageCacheEntry != null) {
|
||||||
AppDependencies.earlyMessageCache.store(selfId, targetTimestamp, earlyMessageCacheEntry)
|
AppDependencies.earlyMessageCache.store(selfId, targetTimestamp, earlyMessageCacheEntry)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -33,20 +33,20 @@ object StoryMessageProcessor {
|
|||||||
fun process(envelope: Envelope, content: Content, metadata: EnvelopeMetadata, senderRecipient: Recipient, threadRecipient: Recipient) {
|
fun process(envelope: Envelope, content: Content, metadata: EnvelopeMetadata, senderRecipient: Recipient, threadRecipient: Recipient) {
|
||||||
val storyMessage = content.storyMessage!!
|
val storyMessage = content.storyMessage!!
|
||||||
|
|
||||||
log(envelope.timestamp!!, "Story message.")
|
log(envelope.clientTimestamp!!, "Story message.")
|
||||||
|
|
||||||
if (threadRecipient.isInactiveGroup) {
|
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
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
if (threadRecipient.isGroup && !SignalDatabase.groups.isCurrentMember(threadRecipient.requireGroupId().requirePush(), senderRecipient.id)) {
|
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
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!threadRecipient.isGroup && !(senderRecipient.isProfileSharing || senderRecipient.isSystemContact)) {
|
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
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -64,7 +64,7 @@ object StoryMessageProcessor {
|
|||||||
val mediaMessage = IncomingMessage(
|
val mediaMessage = IncomingMessage(
|
||||||
type = MessageType.NORMAL,
|
type = MessageType.NORMAL,
|
||||||
from = senderRecipient.id,
|
from = senderRecipient.id,
|
||||||
sentTimeMillis = envelope.timestamp!!,
|
sentTimeMillis = envelope.clientTimestamp!!,
|
||||||
serverTimeMillis = envelope.serverTimestamp!!,
|
serverTimeMillis = envelope.serverTimestamp!!,
|
||||||
receivedTimeMillis = System.currentTimeMillis(),
|
receivedTimeMillis = System.currentTimeMillis(),
|
||||||
storyType = storyType,
|
storyType = storyType,
|
||||||
|
|||||||
@@ -162,26 +162,26 @@ object SyncMessageProcessor {
|
|||||||
|
|
||||||
when {
|
when {
|
||||||
syncMessage.sent != null -> handleSynchronizeSentMessage(context, envelope, content, metadata, syncMessage.sent!!, senderRecipient, threadRecipient, earlyMessageCacheEntry)
|
syncMessage.sent != null -> handleSynchronizeSentMessage(context, envelope, content, metadata, syncMessage.sent!!, senderRecipient, threadRecipient, earlyMessageCacheEntry)
|
||||||
syncMessage.request != null -> handleSynchronizeRequestMessage(context, syncMessage.request!!, envelope.timestamp!!)
|
syncMessage.request != null -> handleSynchronizeRequestMessage(context, syncMessage.request!!, envelope.clientTimestamp!!)
|
||||||
syncMessage.read.isNotEmpty() -> handleSynchronizeReadMessage(context, syncMessage.read, envelope.timestamp!!, earlyMessageCacheEntry)
|
syncMessage.read.isNotEmpty() -> handleSynchronizeReadMessage(context, syncMessage.read, envelope.clientTimestamp!!, earlyMessageCacheEntry)
|
||||||
syncMessage.viewed.isNotEmpty() -> handleSynchronizeViewedMessage(context, syncMessage.viewed, envelope.timestamp!!)
|
syncMessage.viewed.isNotEmpty() -> handleSynchronizeViewedMessage(context, syncMessage.viewed, envelope.clientTimestamp!!)
|
||||||
syncMessage.viewOnceOpen != null -> handleSynchronizeViewOnceOpenMessage(context, syncMessage.viewOnceOpen!!, envelope.timestamp!!, earlyMessageCacheEntry)
|
syncMessage.viewOnceOpen != null -> handleSynchronizeViewOnceOpenMessage(context, syncMessage.viewOnceOpen!!, envelope.clientTimestamp!!, earlyMessageCacheEntry)
|
||||||
syncMessage.verified != null -> handleSynchronizeVerifiedMessage(context, syncMessage.verified!!)
|
syncMessage.verified != null -> handleSynchronizeVerifiedMessage(context, syncMessage.verified!!)
|
||||||
syncMessage.stickerPackOperation.isNotEmpty() -> handleSynchronizeStickerPackOperation(syncMessage.stickerPackOperation, envelope.timestamp!!)
|
syncMessage.stickerPackOperation.isNotEmpty() -> handleSynchronizeStickerPackOperation(syncMessage.stickerPackOperation, envelope.clientTimestamp!!)
|
||||||
syncMessage.configuration != null -> handleSynchronizeConfigurationMessage(context, syncMessage.configuration!!, envelope.timestamp!!)
|
syncMessage.configuration != null -> handleSynchronizeConfigurationMessage(context, syncMessage.configuration!!, envelope.clientTimestamp!!)
|
||||||
syncMessage.blocked != null -> handleSynchronizeBlockedListMessage(syncMessage.blocked!!, envelope.timestamp!!)
|
syncMessage.blocked != null -> handleSynchronizeBlockedListMessage(syncMessage.blocked!!, envelope.clientTimestamp!!)
|
||||||
syncMessage.fetchLatest?.type != null -> handleSynchronizeFetchMessage(syncMessage.fetchLatest!!.type!!, envelope.timestamp!!)
|
syncMessage.fetchLatest?.type != null -> handleSynchronizeFetchMessage(syncMessage.fetchLatest!!.type!!, envelope.clientTimestamp!!)
|
||||||
syncMessage.messageRequestResponse != null -> handleSynchronizeMessageRequestResponse(syncMessage.messageRequestResponse!!, envelope.timestamp!!)
|
syncMessage.messageRequestResponse != null -> handleSynchronizeMessageRequestResponse(syncMessage.messageRequestResponse!!, envelope.clientTimestamp!!)
|
||||||
syncMessage.outgoingPayment != null -> handleSynchronizeOutgoingPayment(syncMessage.outgoingPayment!!, envelope.timestamp!!)
|
syncMessage.outgoingPayment != null -> handleSynchronizeOutgoingPayment(syncMessage.outgoingPayment!!, envelope.clientTimestamp!!)
|
||||||
syncMessage.contacts != null -> handleSynchronizeContacts(syncMessage.contacts!!, envelope.timestamp!!)
|
syncMessage.contacts != null -> handleSynchronizeContacts(syncMessage.contacts!!, envelope.clientTimestamp!!)
|
||||||
syncMessage.keys != null -> handleSynchronizeKeys(syncMessage.keys!!, envelope.timestamp!!)
|
syncMessage.keys != null -> handleSynchronizeKeys(syncMessage.keys!!, envelope.clientTimestamp!!)
|
||||||
syncMessage.callEvent != null -> handleSynchronizeCallEvent(syncMessage.callEvent!!, envelope.timestamp!!)
|
syncMessage.callEvent != null -> handleSynchronizeCallEvent(syncMessage.callEvent!!, envelope.clientTimestamp!!)
|
||||||
syncMessage.callLinkUpdate != null -> handleSynchronizeCallLink(syncMessage.callLinkUpdate!!, envelope.timestamp!!)
|
syncMessage.callLinkUpdate != null -> handleSynchronizeCallLink(syncMessage.callLinkUpdate!!, envelope.clientTimestamp!!)
|
||||||
syncMessage.callLogEvent != null -> handleSynchronizeCallLogEvent(syncMessage.callLogEvent!!, envelope.timestamp!!)
|
syncMessage.callLogEvent != null -> handleSynchronizeCallLogEvent(syncMessage.callLogEvent!!, envelope.clientTimestamp!!)
|
||||||
syncMessage.deleteForMe != null -> handleSynchronizeDeleteForMe(context, syncMessage.deleteForMe!!, envelope.timestamp!!, earlyMessageCacheEntry)
|
syncMessage.deleteForMe != null -> handleSynchronizeDeleteForMe(context, syncMessage.deleteForMe!!, envelope.clientTimestamp!!, earlyMessageCacheEntry)
|
||||||
syncMessage.attachmentBackfillRequest != null -> handleSynchronizeAttachmentBackfillRequest(syncMessage.attachmentBackfillRequest!!, envelope.timestamp!!)
|
syncMessage.attachmentBackfillRequest != null -> handleSynchronizeAttachmentBackfillRequest(syncMessage.attachmentBackfillRequest!!, envelope.clientTimestamp!!)
|
||||||
syncMessage.attachmentBackfillResponse != null -> warn(envelope.timestamp!!, "Contains a backfill response, but we don't handle these!")
|
syncMessage.attachmentBackfillResponse != null -> warn(envelope.clientTimestamp!!, "Contains a backfill response, but we don't handle these!")
|
||||||
else -> warn(envelope.timestamp!!, "Contains no known sync types...")
|
else -> warn(envelope.clientTimestamp!!, "Contains no known sync types...")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -196,7 +196,7 @@ object SyncMessageProcessor {
|
|||||||
threadRecipient: Recipient,
|
threadRecipient: Recipient,
|
||||||
earlyMessageCacheEntry: EarlyMessageCacheEntry?
|
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 {
|
try {
|
||||||
handlePniIdentityKeys(envelope, sent)
|
handlePniIdentityKeys(envelope, sent)
|
||||||
@@ -212,42 +212,42 @@ object SyncMessageProcessor {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (sent.isRecipientUpdate == true) {
|
if (sent.isRecipientUpdate == true) {
|
||||||
handleGroupRecipientUpdate(sent, envelope.timestamp!!)
|
handleGroupRecipientUpdate(sent, envelope.clientTimestamp!!)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
val dataMessage = if (sent.message != null) {
|
val dataMessage = if (sent.message != null) {
|
||||||
sent.message!!
|
sent.message!!
|
||||||
} else {
|
} else {
|
||||||
warn(envelope.timestamp!!, "Sync message missing nested message to sync")
|
warn(envelope.clientTimestamp!!, "Sync message missing nested message to sync")
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
val groupId: GroupId.V2? = if (dataMessage.hasGroupContext) GroupId.v2(dataMessage.groupV2!!.groupMasterKey) else null
|
val groupId: GroupId.V2? = if (dataMessage.hasGroupContext) GroupId.v2(dataMessage.groupV2!!.groupMasterKey) else null
|
||||||
|
|
||||||
if (groupId != 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
|
return
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
var threadId: Long = -1
|
var threadId: Long = -1
|
||||||
when {
|
when {
|
||||||
dataMessage.isEndSession -> threadId = handleSynchronizeSentEndSessionMessage(context, sent, envelope.timestamp!!)
|
dataMessage.isEndSession -> threadId = handleSynchronizeSentEndSessionMessage(context, sent, envelope.clientTimestamp!!)
|
||||||
dataMessage.isGroupV2Update -> {
|
dataMessage.isGroupV2Update -> {
|
||||||
handleSynchronizeSentGv2Update(context, envelope, sent)
|
handleSynchronizeSentGv2Update(context, envelope, sent)
|
||||||
threadId = SignalDatabase.threads.getOrCreateThreadIdFor(getSyncMessageDestination(sent))
|
threadId = SignalDatabase.threads.getOrCreateThreadIdFor(getSyncMessageDestination(sent))
|
||||||
}
|
}
|
||||||
dataMessage.groupCallUpdate != null -> DataMessageProcessor.handleGroupCallUpdateMessage(envelope, senderRecipient.id, groupId)
|
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.isExpirationUpdate -> threadId = handleSynchronizeSentExpirationUpdate(sent)
|
||||||
dataMessage.storyContext != null -> threadId = handleSynchronizeSentStoryReply(sent, envelope.timestamp!!)
|
dataMessage.storyContext != null -> threadId = handleSynchronizeSentStoryReply(sent, envelope.clientTimestamp!!)
|
||||||
dataMessage.reaction != null -> {
|
dataMessage.reaction != null -> {
|
||||||
DataMessageProcessor.handleReaction(context, envelope, dataMessage, senderRecipient.id, earlyMessageCacheEntry)
|
DataMessageProcessor.handleReaction(context, envelope, dataMessage, senderRecipient.id, earlyMessageCacheEntry)
|
||||||
threadId = SignalDatabase.threads.getOrCreateThreadIdFor(getSyncMessageDestination(sent))
|
threadId = SignalDatabase.threads.getOrCreateThreadIdFor(getSyncMessageDestination(sent))
|
||||||
}
|
}
|
||||||
dataMessage.hasRemoteDelete -> DataMessageProcessor.handleRemoteDelete(context, envelope, dataMessage, senderRecipient.id, earlyMessageCacheEntry)
|
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.pollCreate != null -> threadId = handleSynchronizedPollCreate(envelope, dataMessage, sent, senderRecipient)
|
||||||
dataMessage.pollVote != null -> {
|
dataMessage.pollVote != null -> {
|
||||||
DataMessageProcessor.handlePollVote(context, envelope, dataMessage, senderRecipient, earlyMessageCacheEntry)
|
DataMessageProcessor.handlePollVote(context, envelope, dataMessage, senderRecipient, earlyMessageCacheEntry)
|
||||||
@@ -264,11 +264,11 @@ object SyncMessageProcessor {
|
|||||||
DataMessageProcessor.handleAdminRemoteDelete(context, envelope, dataMessage, senderRecipient, threadRecipient, earlyMessageCacheEntry)
|
DataMessageProcessor.handleAdminRemoteDelete(context, envelope, dataMessage, senderRecipient, threadRecipient, earlyMessageCacheEntry)
|
||||||
threadId = SignalDatabase.threads.getOrCreateThreadIdFor(getSyncMessageDestination(sent))
|
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)) {
|
if (groupId != null && SignalDatabase.groups.isUnknownGroup(groupId)) {
|
||||||
DataMessageProcessor.handleUnknownGroupMessage(envelope.timestamp!!, dataMessage.groupV2!!)
|
DataMessageProcessor.handleUnknownGroupMessage(envelope.clientTimestamp!!, dataMessage.groupV2!!)
|
||||||
}
|
}
|
||||||
|
|
||||||
if (dataMessage.profileKey.isNotEmpty()) {
|
if (dataMessage.profileKey.isNotEmpty()) {
|
||||||
@@ -284,7 +284,7 @@ object SyncMessageProcessor {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (SignalStore.rateLimit.needsRecaptcha()) {
|
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)
|
RateLimitUtil.retryAllRateLimitedMessages(context)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -308,16 +308,16 @@ object SyncMessageProcessor {
|
|||||||
val address = SignalProtocolAddress(pni.toString(), SignalServiceAddress.DEFAULT_DEVICE_ID)
|
val address = SignalProtocolAddress(pni.toString(), SignalServiceAddress.DEFAULT_DEVICE_ID)
|
||||||
|
|
||||||
if (AppDependencies.protocolStore.aci().identities().getIdentity(address) != null) {
|
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
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
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())
|
val identityKey = IdentityKey(status.destinationPniIdentityKey!!.toByteArray())
|
||||||
AppDependencies.protocolStore.aci().identities().saveIdentity(address, identityKey)
|
AppDependencies.protocolStore.aci().identities().saveIdentity(address, identityKey)
|
||||||
} catch (e: InvalidKeyException) {
|
} 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
|
val senderRecipientId = senderRecipient.id
|
||||||
|
|
||||||
if (targetMessage == null) {
|
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) {
|
if (earlyMessageCacheEntry != null) {
|
||||||
AppDependencies.earlyMessageCache.store(senderRecipientId, targetSentTimestamp, earlyMessageCacheEntry)
|
AppDependencies.earlyMessageCache.store(senderRecipientId, targetSentTimestamp, earlyMessageCacheEntry)
|
||||||
PushProcessEarlyMessagesJob.enqueue()
|
PushProcessEarlyMessagesJob.enqueue()
|
||||||
@@ -358,12 +358,12 @@ object SyncMessageProcessor {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (message.isMediaMessage) {
|
if (message.isMediaMessage) {
|
||||||
handleSynchronizeSentEditMediaMessage(targetMessage, toRecipient, sent, message, envelope.timestamp!!)
|
handleSynchronizeSentEditMediaMessage(targetMessage, toRecipient, sent, message, envelope.clientTimestamp!!)
|
||||||
} else {
|
} else {
|
||||||
handleSynchronizeSentEditTextMessage(targetMessage, toRecipient, sent, message, envelope.timestamp!!)
|
handleSynchronizeSentEditTextMessage(targetMessage, toRecipient, sent, message, envelope.clientTimestamp!!)
|
||||||
}
|
}
|
||||||
} else {
|
} 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)
|
@Throws(MmsException::class)
|
||||||
private fun handleSynchronizeSentStoryMessage(envelope: Envelope, sent: Sent) {
|
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)
|
val manifest = SentStorySyncManifest.fromRecipientsSet(sent.storyMessageRecipients)
|
||||||
|
|
||||||
if (sent.isRecipientUpdate == true) {
|
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!!)
|
SignalDatabase.storySends.applySentStoryManifest(manifest, sent.timestamp!!)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@@ -686,18 +686,18 @@ object SyncMessageProcessor {
|
|||||||
|
|
||||||
@Throws(IOException::class, GroupChangeBusyException::class)
|
@Throws(IOException::class, GroupChangeBusyException::class)
|
||||||
private fun handleSynchronizeSentGv2Update(context: Context, envelope: Envelope, sent: Sent) {
|
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 dataMessage: DataMessage = sent.message!!
|
||||||
val groupId: GroupId.V2? = dataMessage.groupV2?.groupId
|
val groupId: GroupId.V2? = dataMessage.groupV2?.groupId
|
||||||
|
|
||||||
if (groupId == null) {
|
if (groupId == null) {
|
||||||
warn(envelope.timestamp!!, "GV2 update missing group id")
|
warn(envelope.clientTimestamp!!, "GV2 update missing group id")
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
if (MessageContentProcessor.updateGv2GroupFromServerOrP2PChange(context, envelope.timestamp!!, dataMessage.groupV2!!, SignalDatabase.groups.getGroup(groupId)) == null) {
|
if (MessageContentProcessor.updateGv2GroupFromServerOrP2PChange(context, envelope.clientTimestamp!!, dataMessage.groupV2!!, SignalDatabase.groups.getGroup(groupId)) == null) {
|
||||||
log(envelope.timestamp!!, "Ignoring GV2 message for group we are not currently in $groupId")
|
log(envelope.clientTimestamp!!, "Ignoring GV2 message for group we are not currently in $groupId")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1764,7 +1764,7 @@ object SyncMessageProcessor {
|
|||||||
sent: Sent,
|
sent: Sent,
|
||||||
senderRecipient: Recipient
|
senderRecipient: Recipient
|
||||||
): Long {
|
): Long {
|
||||||
log(envelope.timestamp!!, "Synchronize sent poll creation message.")
|
log(envelope.clientTimestamp!!, "Synchronize sent poll creation message.")
|
||||||
|
|
||||||
val recipient = getSyncMessageDestination(sent)
|
val recipient = getSyncMessageDestination(sent)
|
||||||
val threadId = SignalDatabase.threads.getOrCreateThreadIdFor(recipient)
|
val threadId = SignalDatabase.threads.getOrCreateThreadIdFor(recipient)
|
||||||
@@ -1795,7 +1795,7 @@ object SyncMessageProcessor {
|
|||||||
updateGroupReceiptStatus(sent, messageId, recipient.requireGroupId())
|
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)
|
SignalDatabase.messages.markAsSent(messageId, true)
|
||||||
|
|
||||||
@@ -1814,7 +1814,7 @@ object SyncMessageProcessor {
|
|||||||
senderRecipient: Recipient,
|
senderRecipient: Recipient,
|
||||||
earlyMessageCacheEntry: EarlyMessageCacheEntry?
|
earlyMessageCacheEntry: EarlyMessageCacheEntry?
|
||||||
): Long {
|
): Long {
|
||||||
log(envelope.timestamp!!, "Synchronize sent poll terminate message")
|
log(envelope.clientTimestamp!!, "Synchronize sent poll terminate message")
|
||||||
|
|
||||||
val recipient = getSyncMessageDestination(sent)
|
val recipient = getSyncMessageDestination(sent)
|
||||||
val threadId = SignalDatabase.threads.getOrCreateThreadIdFor(recipient)
|
val threadId = SignalDatabase.threads.getOrCreateThreadIdFor(recipient)
|
||||||
@@ -1827,7 +1827,7 @@ object SyncMessageProcessor {
|
|||||||
val pollTerminate = message.pollTerminate!!
|
val pollTerminate = message.pollTerminate!!
|
||||||
val targetMessage = SignalDatabase.messages.getMessageFor(pollTerminate.targetSentTimestamp!!, Recipient.self().id)
|
val targetMessage = SignalDatabase.messages.getMessageFor(pollTerminate.targetSentTimestamp!!, Recipient.self().id)
|
||||||
if (targetMessage == null) {
|
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) {
|
if (earlyMessageCacheEntry != null) {
|
||||||
AppDependencies.earlyMessageCache.store(senderRecipient.id, pollTerminate.targetSentTimestamp!!, earlyMessageCacheEntry)
|
AppDependencies.earlyMessageCache.store(senderRecipient.id, pollTerminate.targetSentTimestamp!!, earlyMessageCacheEntry)
|
||||||
PushProcessEarlyMessagesJob.enqueue()
|
PushProcessEarlyMessagesJob.enqueue()
|
||||||
@@ -1836,7 +1836,7 @@ object SyncMessageProcessor {
|
|||||||
}
|
}
|
||||||
val poll = SignalDatabase.polls.getPoll(targetMessage.id)
|
val poll = SignalDatabase.polls.getPoll(targetMessage.id)
|
||||||
if (poll == null) {
|
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
|
return -1
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1857,7 +1857,7 @@ object SyncMessageProcessor {
|
|||||||
val messageId = SignalDatabase.messages.insertMessageOutbox(outgoingMessage, threadId, false, receiptStatus, null).messageId
|
val messageId = SignalDatabase.messages.insertMessageOutbox(outgoingMessage, threadId, false, receiptStatus, null).messageId
|
||||||
SignalDatabase.messages.markAsSent(messageId, true)
|
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) {
|
if (expiresInMillis > 0) {
|
||||||
SignalDatabase.messages.markExpireStarted(messageId, sent.expirationStartTimestamp ?: 0)
|
SignalDatabase.messages.markExpireStarted(messageId, sent.expirationStartTimestamp ?: 0)
|
||||||
@@ -1874,7 +1874,7 @@ object SyncMessageProcessor {
|
|||||||
senderRecipient: Recipient,
|
senderRecipient: Recipient,
|
||||||
earlyMessageCacheEntry: EarlyMessageCacheEntry?
|
earlyMessageCacheEntry: EarlyMessageCacheEntry?
|
||||||
): Long {
|
): Long {
|
||||||
log(envelope.timestamp!!, "Synchronize pinned message")
|
log(envelope.clientTimestamp!!, "Synchronize pinned message")
|
||||||
|
|
||||||
val recipient = getSyncMessageDestination(sent)
|
val recipient = getSyncMessageDestination(sent)
|
||||||
val threadId = SignalDatabase.threads.getOrCreateThreadIdFor(recipient)
|
val threadId = SignalDatabase.threads.getOrCreateThreadIdFor(recipient)
|
||||||
@@ -1887,14 +1887,14 @@ object SyncMessageProcessor {
|
|||||||
val pinMessage = message.pinMessage!!
|
val pinMessage = message.pinMessage!!
|
||||||
val targetAuthorServiceId: ServiceId = ACI.parseOrThrow(pinMessage.targetAuthorAciBinary!!)
|
val targetAuthorServiceId: ServiceId = ACI.parseOrThrow(pinMessage.targetAuthorAciBinary!!)
|
||||||
if (targetAuthorServiceId.isUnknown) {
|
if (targetAuthorServiceId.isUnknown) {
|
||||||
warn(envelope.timestamp!!, "Unknown author")
|
warn(envelope.clientTimestamp!!, "Unknown author")
|
||||||
return -1
|
return -1
|
||||||
}
|
}
|
||||||
|
|
||||||
val targetAuthor = Recipient.externalPush(targetAuthorServiceId)
|
val targetAuthor = Recipient.externalPush(targetAuthorServiceId)
|
||||||
val targetMessage = SignalDatabase.messages.getMessageFor(pinMessage.targetSentTimestamp!!, targetAuthor.id)
|
val targetMessage = SignalDatabase.messages.getMessageFor(pinMessage.targetSentTimestamp!!, targetAuthor.id)
|
||||||
if (targetMessage == null) {
|
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) {
|
if (earlyMessageCacheEntry != null) {
|
||||||
AppDependencies.earlyMessageCache.store(senderRecipient.id, pinMessage.targetSentTimestamp!!, earlyMessageCacheEntry)
|
AppDependencies.earlyMessageCache.store(senderRecipient.id, pinMessage.targetSentTimestamp!!, earlyMessageCacheEntry)
|
||||||
PushProcessEarlyMessagesJob.enqueue()
|
PushProcessEarlyMessagesJob.enqueue()
|
||||||
@@ -1903,12 +1903,12 @@ object SyncMessageProcessor {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (targetMessage.hasGiftBadge()) {
|
if (targetMessage.hasGiftBadge()) {
|
||||||
warn(envelope.timestamp!!, "Cannot pin gift badge")
|
warn(envelope.clientTimestamp!!, "Cannot pin gift badge")
|
||||||
return -1
|
return -1
|
||||||
}
|
}
|
||||||
|
|
||||||
if (targetMessage.isRemoteDelete) {
|
if (targetMessage.isRemoteDelete) {
|
||||||
warn(envelope.timestamp!!, "Cannot pin deleted message")
|
warn(envelope.clientTimestamp!!, "Cannot pin deleted message")
|
||||||
return -1
|
return -1
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1924,7 +1924,7 @@ object SyncMessageProcessor {
|
|||||||
val messageId = SignalDatabase.messages.insertMessageOutbox(outgoingMessage, threadId, false, GroupReceiptTable.STATUS_UNKNOWN, null).messageId
|
val messageId = SignalDatabase.messages.insertMessageOutbox(outgoingMessage, threadId, false, GroupReceiptTable.STATUS_UNKNOWN, null).messageId
|
||||||
SignalDatabase.messages.markAsSent(messageId, true)
|
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) {
|
if (expiresInMillis > 0) {
|
||||||
SignalDatabase.messages.markExpireStarted(messageId, sent.expirationStartTimestamp ?: 0)
|
SignalDatabase.messages.markExpireStarted(messageId, sent.expirationStartTimestamp ?: 0)
|
||||||
|
|||||||
@@ -112,7 +112,6 @@ import org.whispersystems.signalservice.internal.push.OutgoingPushMessage;
|
|||||||
import org.whispersystems.signalservice.internal.push.OutgoingPushMessageList;
|
import org.whispersystems.signalservice.internal.push.OutgoingPushMessageList;
|
||||||
import org.whispersystems.signalservice.internal.push.PniSignatureMessage;
|
import org.whispersystems.signalservice.internal.push.PniSignatureMessage;
|
||||||
import org.whispersystems.signalservice.internal.push.Preview;
|
import org.whispersystems.signalservice.internal.push.Preview;
|
||||||
import org.whispersystems.signalservice.internal.push.ProvisioningVersion;
|
|
||||||
import org.whispersystems.signalservice.internal.push.PushAttachmentData;
|
import org.whispersystems.signalservice.internal.push.PushAttachmentData;
|
||||||
import org.whispersystems.signalservice.internal.push.PushServiceSocket;
|
import org.whispersystems.signalservice.internal.push.PushServiceSocket;
|
||||||
import org.whispersystems.signalservice.internal.push.ReceiptMessage;
|
import org.whispersystems.signalservice.internal.push.ReceiptMessage;
|
||||||
@@ -1602,8 +1601,6 @@ public class SignalServiceMessageSender {
|
|||||||
configurationMessage.linkPreviews(configuration.getLinkPreviews().get());
|
configurationMessage.linkPreviews(configuration.getLinkPreviews().get());
|
||||||
}
|
}
|
||||||
|
|
||||||
configurationMessage.provisioningVersion(ProvisioningVersion.CURRENT.getValue());
|
|
||||||
|
|
||||||
return container.syncMessage(syncMessage.configuration(configurationMessage.build()).build()).build();
|
return container.syncMessage(syncMessage.configuration(configurationMessage.build()).build()).build();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -104,8 +104,8 @@ public interface EnvelopeContent {
|
|||||||
int type;
|
int type;
|
||||||
|
|
||||||
switch (message.getType()) {
|
switch (message.getType()) {
|
||||||
case CiphertextMessage.PREKEY_TYPE: type = Type.PREKEY_BUNDLE.getValue(); break;
|
case CiphertextMessage.PREKEY_TYPE: type = Type.PREKEY_MESSAGE.getValue(); break;
|
||||||
case CiphertextMessage.WHISPER_TYPE: type = Type.CIPHERTEXT.getValue(); break;
|
case CiphertextMessage.WHISPER_TYPE: type = Type.DOUBLE_RATCHET.getValue(); break;
|
||||||
default: throw new AssertionError("Bad type: " + message.getType());
|
default: throw new AssertionError("Bad type: " + message.getType());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -187,25 +187,25 @@ public class SignalServiceCipher {
|
|||||||
throw new InvalidMessageStructureException("Non-UD envelope is missing a UUID!");
|
throw new InvalidMessageStructureException("Non-UD envelope is missing a UUID!");
|
||||||
}
|
}
|
||||||
|
|
||||||
if (envelope.type == Envelope.Type.PREKEY_BUNDLE) {
|
if (envelope.type == Envelope.Type.PREKEY_MESSAGE) {
|
||||||
SignalProtocolAddress sourceAddress = new SignalProtocolAddress(sourceServiceId.toString(), envelope.sourceDevice);
|
SignalProtocolAddress sourceAddress = new SignalProtocolAddress(sourceServiceId.toString(), envelope.sourceDeviceId);
|
||||||
SignalSessionCipher sessionCipher = new SignalSessionCipher(sessionLock, new SessionCipher(signalProtocolStore, sourceAddress));
|
SignalSessionCipher sessionCipher = new SignalSessionCipher(sessionLock, new SessionCipher(signalProtocolStore, sourceAddress));
|
||||||
|
|
||||||
paddedMessage = sessionCipher.decrypt(new PreKeySignalMessage(envelope.content.toByteArray()));
|
paddedMessage = sessionCipher.decrypt(new PreKeySignalMessage(envelope.content.toByteArray()));
|
||||||
metadata = new SignalServiceMetadata(getSourceAddress(envelope), envelope.sourceDevice, envelope.timestamp, envelope.serverTimestamp, serverDeliveredTimestamp, false, serverGuid, Optional.empty(), destinationStr);
|
metadata = new SignalServiceMetadata(getSourceAddress(envelope), envelope.sourceDeviceId, envelope.clientTimestamp, envelope.serverTimestamp, serverDeliveredTimestamp, false, serverGuid, Optional.empty(), destinationStr);
|
||||||
ciphertextMessageType = CiphertextMessage.PREKEY_TYPE;
|
ciphertextMessageType = CiphertextMessage.PREKEY_TYPE;
|
||||||
|
|
||||||
signalProtocolStore.clearSenderKeySharedWith(Collections.singleton(sourceAddress));
|
signalProtocolStore.clearSenderKeySharedWith(Collections.singleton(sourceAddress));
|
||||||
} else if (envelope.type == Envelope.Type.CIPHERTEXT) {
|
} else if (envelope.type == Envelope.Type.DOUBLE_RATCHET) {
|
||||||
SignalProtocolAddress sourceAddress = new SignalProtocolAddress(sourceServiceId.toString(), envelope.sourceDevice);
|
SignalProtocolAddress sourceAddress = new SignalProtocolAddress(sourceServiceId.toString(), envelope.sourceDeviceId);
|
||||||
SignalSessionCipher sessionCipher = new SignalSessionCipher(sessionLock, new SessionCipher(signalProtocolStore, sourceAddress));
|
SignalSessionCipher sessionCipher = new SignalSessionCipher(sessionLock, new SessionCipher(signalProtocolStore, sourceAddress));
|
||||||
|
|
||||||
paddedMessage = sessionCipher.decrypt(new SignalMessage(envelope.content.toByteArray()));
|
paddedMessage = sessionCipher.decrypt(new SignalMessage(envelope.content.toByteArray()));
|
||||||
metadata = new SignalServiceMetadata(getSourceAddress(envelope), envelope.sourceDevice, envelope.timestamp, envelope.serverTimestamp, serverDeliveredTimestamp, false, serverGuid, Optional.empty(), destinationStr);
|
metadata = new SignalServiceMetadata(getSourceAddress(envelope), envelope.sourceDeviceId, envelope.clientTimestamp, envelope.serverTimestamp, serverDeliveredTimestamp, false, serverGuid, Optional.empty(), destinationStr);
|
||||||
ciphertextMessageType = CiphertextMessage.WHISPER_TYPE;
|
ciphertextMessageType = CiphertextMessage.WHISPER_TYPE;
|
||||||
} else if (envelope.type == Envelope.Type.PLAINTEXT_CONTENT) {
|
} else if (envelope.type == Envelope.Type.PLAINTEXT_CONTENT) {
|
||||||
paddedMessage = new PlaintextContent(envelope.content.toByteArray()).getBody();
|
paddedMessage = new PlaintextContent(envelope.content.toByteArray()).getBody();
|
||||||
metadata = new SignalServiceMetadata(getSourceAddress(envelope), envelope.sourceDevice, envelope.timestamp, envelope.serverTimestamp, serverDeliveredTimestamp, false, serverGuid, Optional.empty(), destinationStr);
|
metadata = new SignalServiceMetadata(getSourceAddress(envelope), envelope.sourceDeviceId, envelope.clientTimestamp, envelope.serverTimestamp, serverDeliveredTimestamp, false, serverGuid, Optional.empty(), destinationStr);
|
||||||
ciphertextMessageType = CiphertextMessage.PLAINTEXT_CONTENT_TYPE;
|
ciphertextMessageType = CiphertextMessage.PLAINTEXT_CONTENT_TYPE;
|
||||||
} else if (envelope.type == Envelope.Type.UNIDENTIFIED_SENDER) {
|
} else if (envelope.type == Envelope.Type.UNIDENTIFIED_SENDER) {
|
||||||
SignalSealedSessionCipher sealedSessionCipher = new SignalSealedSessionCipher(sessionLock, new SealedSessionCipher(signalProtocolStore, localAddress.getServiceId().getRawUuid(), localAddress.getNumber().orElse(null), localDeviceId));
|
SignalSealedSessionCipher sealedSessionCipher = new SignalSealedSessionCipher(sessionLock, new SealedSessionCipher(signalProtocolStore, localAddress.getServiceId().getRawUuid(), localAddress.getNumber().orElse(null), localDeviceId));
|
||||||
@@ -215,7 +215,7 @@ public class SignalServiceCipher {
|
|||||||
boolean needsReceipt = true;
|
boolean needsReceipt = true;
|
||||||
|
|
||||||
if (sourceServiceId != null) {
|
if (sourceServiceId != null) {
|
||||||
Log.w(TAG, "[" + envelope.timestamp + "] Received a UD-encrypted message sent over an identified channel. Marking as needsReceipt=false");
|
Log.w(TAG, "[" + envelope.clientTimestamp + "] Received a UD-encrypted message sent over an identified channel. Marking as needsReceipt=false");
|
||||||
needsReceipt = false;
|
needsReceipt = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -226,7 +226,7 @@ public class SignalServiceCipher {
|
|||||||
}
|
}
|
||||||
|
|
||||||
paddedMessage = result.getPaddedMessage();
|
paddedMessage = result.getPaddedMessage();
|
||||||
metadata = new SignalServiceMetadata(resultAddress, result.getDeviceId(), envelope.timestamp, envelope.serverTimestamp, serverDeliveredTimestamp, needsReceipt, serverGuid, groupId, destinationStr);
|
metadata = new SignalServiceMetadata(resultAddress, result.getDeviceId(), envelope.clientTimestamp, envelope.serverTimestamp, serverDeliveredTimestamp, needsReceipt, serverGuid, groupId, destinationStr);
|
||||||
} else {
|
} else {
|
||||||
throw new InvalidMetadataMessageException("Unknown type: " + envelope.type);
|
throw new InvalidMetadataMessageException("Unknown type: " + envelope.type);
|
||||||
}
|
}
|
||||||
@@ -236,21 +236,21 @@ public class SignalServiceCipher {
|
|||||||
|
|
||||||
return new Plaintext(metadata, data, ciphertextMessageType);
|
return new Plaintext(metadata, data, ciphertextMessageType);
|
||||||
} catch (DuplicateMessageException e) {
|
} catch (DuplicateMessageException e) {
|
||||||
throw new ProtocolDuplicateMessageException(e, sourceServiceId.toString(), envelope.sourceDevice);
|
throw new ProtocolDuplicateMessageException(e, sourceServiceId.toString(), envelope.sourceDeviceId);
|
||||||
} catch (LegacyMessageException e) {
|
} catch (LegacyMessageException e) {
|
||||||
throw new ProtocolLegacyMessageException(e, sourceServiceId.toString(), envelope.sourceDevice);
|
throw new ProtocolLegacyMessageException(e, sourceServiceId.toString(), envelope.sourceDeviceId);
|
||||||
} catch (InvalidMessageException e) {
|
} catch (InvalidMessageException e) {
|
||||||
throw new ProtocolInvalidMessageException(e, sourceServiceId.toString(), envelope.sourceDevice);
|
throw new ProtocolInvalidMessageException(e, sourceServiceId.toString(), envelope.sourceDeviceId);
|
||||||
} catch (InvalidKeyIdException e) {
|
} catch (InvalidKeyIdException e) {
|
||||||
throw new ProtocolInvalidKeyIdException(e, sourceServiceId.toString(), envelope.sourceDevice);
|
throw new ProtocolInvalidKeyIdException(e, sourceServiceId.toString(), envelope.sourceDeviceId);
|
||||||
} catch (InvalidKeyException e) {
|
} catch (InvalidKeyException e) {
|
||||||
throw new ProtocolInvalidKeyException(e, sourceServiceId.toString(), envelope.sourceDevice);
|
throw new ProtocolInvalidKeyException(e, sourceServiceId.toString(), envelope.sourceDeviceId);
|
||||||
} catch (UntrustedIdentityException e) {
|
} catch (UntrustedIdentityException e) {
|
||||||
throw new ProtocolUntrustedIdentityException(e, sourceServiceId.toString(), envelope.sourceDevice);
|
throw new ProtocolUntrustedIdentityException(e, sourceServiceId.toString(), envelope.sourceDeviceId);
|
||||||
} catch (InvalidVersionException e) {
|
} catch (InvalidVersionException e) {
|
||||||
throw new ProtocolInvalidVersionException(e, sourceServiceId.toString(), envelope.sourceDevice);
|
throw new ProtocolInvalidVersionException(e, sourceServiceId.toString(), envelope.sourceDeviceId);
|
||||||
} catch (NoSessionException e) {
|
} catch (NoSessionException e) {
|
||||||
throw new ProtocolNoSessionException(e, sourceServiceId.toString(), envelope.sourceDevice);
|
throw new ProtocolNoSessionException(e, sourceServiceId.toString(), envelope.sourceDeviceId);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -83,8 +83,8 @@ object EnvelopeContentValidator {
|
|||||||
return Result.Invalid("[DataMessage] Missing timestamp!")
|
return Result.Invalid("[DataMessage] Missing timestamp!")
|
||||||
}
|
}
|
||||||
|
|
||||||
if (dataMessage.timestamp != envelope.timestamp) {
|
if (dataMessage.timestamp != envelope.clientTimestamp) {
|
||||||
return Result.Invalid("[DataMessage] Timestamps don't match! envelope: ${envelope.timestamp}, content: ${dataMessage.timestamp}")
|
return Result.Invalid("[DataMessage] Timestamps don't match! envelope: ${envelope.clientTimestamp}, content: ${dataMessage.timestamp}")
|
||||||
}
|
}
|
||||||
|
|
||||||
if (dataMessage.quote != null && ACI.parseOrNull(dataMessage.quote.authorAci, dataMessage.quote.authorAciBinary).isNullOrInvalidServiceId()) {
|
if (dataMessage.quote != null && ACI.parseOrNull(dataMessage.quote.authorAci, dataMessage.quote.authorAciBinary).isNullOrInvalidServiceId()) {
|
||||||
@@ -276,8 +276,8 @@ object EnvelopeContentValidator {
|
|||||||
private fun validateTypingMessage(envelope: Envelope, typingMessage: TypingMessage): Result {
|
private fun validateTypingMessage(envelope: Envelope, typingMessage: TypingMessage): Result {
|
||||||
return if (typingMessage.timestamp == null) {
|
return if (typingMessage.timestamp == null) {
|
||||||
return Result.Invalid("[TypingMessage] Missing timestamp!")
|
return Result.Invalid("[TypingMessage] Missing timestamp!")
|
||||||
} else if (typingMessage.timestamp != envelope.timestamp) {
|
} else if (typingMessage.timestamp != envelope.clientTimestamp) {
|
||||||
Result.Invalid("[TypingMessage] Timestamps don't match! envelope: ${envelope.timestamp}, content: ${typingMessage.timestamp}")
|
Result.Invalid("[TypingMessage] Timestamps don't match! envelope: ${envelope.clientTimestamp}, content: ${typingMessage.timestamp}")
|
||||||
} else if (typingMessage.action == null) {
|
} else if (typingMessage.action == null) {
|
||||||
Result.Invalid("[TypingMessage] Missing action!")
|
Result.Invalid("[TypingMessage] Missing action!")
|
||||||
} else {
|
} else {
|
||||||
|
|||||||
@@ -13,23 +13,79 @@ option java_outer_classname = "SignalServiceProtos";
|
|||||||
message Envelope {
|
message Envelope {
|
||||||
enum Type {
|
enum Type {
|
||||||
UNKNOWN = 0;
|
UNKNOWN = 0;
|
||||||
CIPHERTEXT = 1; // content => (version byte | SignalMessage{Content})
|
|
||||||
|
/**
|
||||||
|
* A double-ratchet message represents a "normal," "unsealed-sender" message
|
||||||
|
* encrypted using the Double Ratchet within an established Signal session.
|
||||||
|
* Double-ratchet messages include sender information in the plaintext
|
||||||
|
* portion of the `Envelope`.
|
||||||
|
*/
|
||||||
|
DOUBLE_RATCHET = 1; // content => (version byte | SignalMessage{Content})
|
||||||
|
|
||||||
reserved 2;
|
reserved 2;
|
||||||
reserved "KEY_EXCHANGE";
|
reserved "KEY_EXCHANGE";
|
||||||
PREKEY_BUNDLE = 3; // content => (version byte | PreKeySignalMessage{Content})
|
|
||||||
SERVER_DELIVERY_RECEIPT = 5; // legacyMessage => [] AND content => []
|
/**
|
||||||
UNIDENTIFIED_SENDER = 6; // legacyMessage => [] AND content => ((version byte | UnidentifiedSenderMessage) OR (version byte | Multi-Recipient Sealed Sender Format))
|
* A prekey message begins a new Signal session. The `content` of a prekey
|
||||||
SENDERKEY_MESSAGE = 7; // legacyMessage => [] AND content => (version byte | SenderKeyMessage)
|
* message is a superset of a double-ratchet message's `content` and
|
||||||
PLAINTEXT_CONTENT = 8; // legacyMessage => [] AND content => (marker byte | Content)
|
* contains the sender's identity public key and information identifying the
|
||||||
|
* pre-keys used in the message's ciphertext. Like double-ratchet messages,
|
||||||
|
* prekey messages contain sender information in the plaintext portion of
|
||||||
|
* the `Envelope`.
|
||||||
|
*/
|
||||||
|
PREKEY_MESSAGE = 3; // content => (version byte | PreKeySignalMessage{Content})
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Server delivery receipts are generated by the server when
|
||||||
|
* "unsealed-sender" messages are delivered to and acknowledged by the
|
||||||
|
* destination device. Server delivery receipts identify the sender in the
|
||||||
|
* plaintext portion of the `Envelope` and have no `content`. Note that
|
||||||
|
* receipts for sealed-sender messages are generated by clients as
|
||||||
|
* `UNIDENTIFIED_SENDER` messages.
|
||||||
|
*
|
||||||
|
* Note that, with server delivery receipts, the "client timestamp" on
|
||||||
|
* the envelope refers to the timestamp of the original message (i.e. the
|
||||||
|
* message the server just delivered) and not to the time of delivery. The
|
||||||
|
* "server timestamp" refers to the time of delivery.
|
||||||
|
*/
|
||||||
|
SERVER_DELIVERY_RECEIPT = 5; // content => []
|
||||||
|
|
||||||
|
/**
|
||||||
|
* An unidentified sender message represents a message with no sender
|
||||||
|
* information in the plaintext portion of the `Envelope`. Unidentified
|
||||||
|
* sender messages always contain an additional `subtype` in their
|
||||||
|
* `content`. They may or may not be part of an existing Signal session
|
||||||
|
* (i.e. an unidentified sender message may have a "prekey message"
|
||||||
|
* subtype or may indicate an encryption error).
|
||||||
|
*/
|
||||||
|
UNIDENTIFIED_SENDER = 6; // content => ((version byte | UnidentifiedSenderMessage) OR (version byte | Multi-Recipient Sealed Sender Format))
|
||||||
|
|
||||||
|
reserved 7;
|
||||||
|
reserved "SENDERKEY_MESSAGE";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A plaintext message is used solely to convey encryption error receipts
|
||||||
|
* and never contains encrypted message content. Encryption error receipts
|
||||||
|
* must be delivered in plaintext because, encryption/decryption of a prior
|
||||||
|
* message failed and there is no reason to believe that
|
||||||
|
* encryption/decryption of subsequent messages with the same key material
|
||||||
|
* would succeed.
|
||||||
|
*
|
||||||
|
* Critically, plaintext messages never have "real" message content
|
||||||
|
* generated by users. Plaintext messages include sender information.
|
||||||
|
*/
|
||||||
|
PLAINTEXT_CONTENT = 8; // content => (marker byte | Content)
|
||||||
|
|
||||||
|
// next: 9
|
||||||
}
|
}
|
||||||
|
|
||||||
optional Type type = 1;
|
optional Type type = 1;
|
||||||
reserved 2; // formerly optional string sourceE164 = 2;
|
reserved 2; // formerly optional string sourceE164 = 2;
|
||||||
optional string sourceServiceId = 11;
|
optional string sourceServiceId = 11;
|
||||||
optional uint32 sourceDevice = 7;
|
optional uint32 sourceDeviceId = 7;
|
||||||
optional string destinationServiceId = 13;
|
optional string destinationServiceId = 13;
|
||||||
reserved 3; // formerly optional string relay = 3;
|
reserved 3; // formerly optional string relay = 3;
|
||||||
optional uint64 timestamp = 5;
|
optional uint64 clientTimestamp = 5;
|
||||||
reserved 6; // formerly optional bytes legacyMessage = 6; // Contains an encrypted DataMessage; this field could have been set historically for type 1 or 3 messages; no longer in use
|
reserved 6; // formerly optional bytes legacyMessage = 6; // Contains an encrypted DataMessage; this field could have been set historically for type 1 or 3 messages; no longer in use
|
||||||
optional bytes content = 8; // Contains an encrypted Content
|
optional bytes content = 8; // Contains an encrypted Content
|
||||||
optional string serverGuid = 9;
|
optional string serverGuid = 9;
|
||||||
@@ -48,17 +104,20 @@ message Envelope {
|
|||||||
}
|
}
|
||||||
|
|
||||||
message Content {
|
message Content {
|
||||||
optional DataMessage dataMessage = 1;
|
oneof content {
|
||||||
optional SyncMessage syncMessage = 2;
|
DataMessage dataMessage = 1;
|
||||||
optional CallMessage callMessage = 3;
|
SyncMessage syncMessage = 2;
|
||||||
optional NullMessage nullMessage = 4;
|
CallMessage callMessage = 3;
|
||||||
optional ReceiptMessage receiptMessage = 5;
|
NullMessage nullMessage = 4;
|
||||||
optional TypingMessage typingMessage = 6;
|
ReceiptMessage receiptMessage = 5;
|
||||||
|
TypingMessage typingMessage = 6;
|
||||||
|
bytes /* DecryptionErrorMessage */ decryptionErrorMessage = 8;
|
||||||
|
StoryMessage storyMessage = 9;
|
||||||
|
EditMessage editMessage = 11;
|
||||||
|
}
|
||||||
|
|
||||||
optional bytes /* SenderKeyDistributionMessage */ senderKeyDistributionMessage = 7;
|
optional bytes /* SenderKeyDistributionMessage */ senderKeyDistributionMessage = 7;
|
||||||
optional bytes /* DecryptionErrorMessage */ decryptionErrorMessage = 8;
|
|
||||||
optional StoryMessage storyMessage = 9;
|
|
||||||
optional PniSignatureMessage pniSignatureMessage = 10;
|
optional PniSignatureMessage pniSignatureMessage = 10;
|
||||||
optional EditMessage editMessage = 11;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
message CallMessage {
|
message CallMessage {
|
||||||
@@ -331,8 +390,8 @@ message DataMessage {
|
|||||||
message PollVote {
|
message PollVote {
|
||||||
optional bytes targetAuthorAciBinary = 1;
|
optional bytes targetAuthorAciBinary = 1;
|
||||||
optional uint64 targetSentTimestamp = 2;
|
optional uint64 targetSentTimestamp = 2;
|
||||||
repeated uint32 optionIndexes = 3; // must be in the range [0, options.length) from the PollCreate
|
repeated uint32 optionIndexes = 3;
|
||||||
optional uint32 voteCount = 4; // increment this by 1 each time you vote on a given poll
|
optional uint32 voteCount = 4;
|
||||||
}
|
}
|
||||||
|
|
||||||
message PinMessage {
|
message PinMessage {
|
||||||
@@ -441,6 +500,12 @@ message TextAttachment {
|
|||||||
}
|
}
|
||||||
|
|
||||||
message Gradient {
|
message Gradient {
|
||||||
|
// Color ordering:
|
||||||
|
// 0 degrees: bottom-to-top
|
||||||
|
// 90 degrees: left-to-right
|
||||||
|
// 180 degrees: top-to-bottom
|
||||||
|
// 270 degrees: right-to-left
|
||||||
|
|
||||||
optional uint32 startColor = 1; // deprecated: this field will be removed in a future release.
|
optional uint32 startColor = 1; // deprecated: this field will be removed in a future release.
|
||||||
optional uint32 endColor = 2; // deprecated: this field will be removed in a future release.
|
optional uint32 endColor = 2; // deprecated: this field will be removed in a future release.
|
||||||
optional uint32 angle = 3; // degrees
|
optional uint32 angle = 3; // degrees
|
||||||
@@ -553,7 +618,7 @@ message SyncMessage {
|
|||||||
optional bool unidentifiedDeliveryIndicators = 2;
|
optional bool unidentifiedDeliveryIndicators = 2;
|
||||||
optional bool typingIndicators = 3;
|
optional bool typingIndicators = 3;
|
||||||
reserved /* linkPreviews */ 4;
|
reserved /* linkPreviews */ 4;
|
||||||
optional uint32 provisioningVersion = 5;
|
reserved /* provisioningVersion */ 5;
|
||||||
optional bool linkPreviews = 6;
|
optional bool linkPreviews = 6;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -688,7 +753,7 @@ message SyncMessage {
|
|||||||
optional bytes rootKey = 1;
|
optional bytes rootKey = 1;
|
||||||
optional bytes adminPasskey = 2;
|
optional bytes adminPasskey = 2;
|
||||||
optional Type type = 3; // defaults to UPDATE
|
optional Type type = 3; // defaults to UPDATE
|
||||||
reserved 4; // was epoch field, never used
|
reserved /*epoch*/ 4;
|
||||||
}
|
}
|
||||||
|
|
||||||
message CallLogEvent {
|
message CallLogEvent {
|
||||||
@@ -785,31 +850,40 @@ message SyncMessage {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
optional Sent sent = 1;
|
oneof content {
|
||||||
optional Contacts contacts = 2;
|
Sent sent = 1;
|
||||||
|
Contacts contacts = 2;
|
||||||
|
Request request = 4;
|
||||||
|
Blocked blocked = 6;
|
||||||
|
Verified verified = 7;
|
||||||
|
Configuration configuration = 9;
|
||||||
|
ViewOnceOpen viewOnceOpen = 11;
|
||||||
|
FetchLatest fetchLatest = 12;
|
||||||
|
Keys keys = 13;
|
||||||
|
MessageRequestResponse messageRequestResponse = 14;
|
||||||
|
OutgoingPayment outgoingPayment = 15;
|
||||||
|
PniChangeNumber pniChangeNumber = 18;
|
||||||
|
CallEvent callEvent = 19;
|
||||||
|
CallLinkUpdate callLinkUpdate = 20;
|
||||||
|
CallLogEvent callLogEvent = 21;
|
||||||
|
DeleteForMe deleteForMe = 22;
|
||||||
|
DeviceNameChange deviceNameChange = 23;
|
||||||
|
AttachmentBackfillRequest attachmentBackfillRequest = 24;
|
||||||
|
AttachmentBackfillResponse attachmentBackfillResponse = 25;
|
||||||
|
}
|
||||||
|
|
||||||
reserved /*groups*/ 3;
|
reserved /*groups*/ 3;
|
||||||
optional Request request = 4;
|
|
||||||
|
// Protobufs don't allow `repeated` fields to be inside of `oneof` so while
|
||||||
|
// the fields below are mutually exclusive with the rest of the values above
|
||||||
|
// we have to place them outside of `oneof`.
|
||||||
repeated Read read = 5;
|
repeated Read read = 5;
|
||||||
optional Blocked blocked = 6;
|
|
||||||
optional Verified verified = 7;
|
|
||||||
optional Configuration configuration = 9;
|
|
||||||
optional bytes padding = 8;
|
|
||||||
repeated StickerPackOperation stickerPackOperation = 10;
|
repeated StickerPackOperation stickerPackOperation = 10;
|
||||||
optional ViewOnceOpen viewOnceOpen = 11;
|
|
||||||
optional FetchLatest fetchLatest = 12;
|
|
||||||
optional Keys keys = 13;
|
|
||||||
optional MessageRequestResponse messageRequestResponse = 14;
|
|
||||||
optional OutgoingPayment outgoingPayment = 15;
|
|
||||||
repeated Viewed viewed = 16;
|
repeated Viewed viewed = 16;
|
||||||
|
|
||||||
reserved /*pniIdentity*/ 17;
|
reserved /*pniIdentity*/ 17;
|
||||||
optional PniChangeNumber pniChangeNumber = 18;
|
|
||||||
optional CallEvent callEvent = 19;
|
optional bytes padding = 8;
|
||||||
optional CallLinkUpdate callLinkUpdate = 20;
|
|
||||||
optional CallLogEvent callLogEvent = 21;
|
|
||||||
optional DeleteForMe deleteForMe = 22;
|
|
||||||
optional DeviceNameChange deviceNameChange = 23;
|
|
||||||
optional AttachmentBackfillRequest attachmentBackfillRequest = 24;
|
|
||||||
optional AttachmentBackfillResponse attachmentBackfillResponse = 25;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
message AttachmentPointer {
|
message AttachmentPointer {
|
||||||
|
|||||||
@@ -16,7 +16,7 @@ import org.whispersystems.signalservice.internal.push.BodyRange
|
|||||||
import org.whispersystems.signalservice.internal.push.Content
|
import org.whispersystems.signalservice.internal.push.Content
|
||||||
import org.whispersystems.signalservice.internal.push.DataMessage
|
import org.whispersystems.signalservice.internal.push.DataMessage
|
||||||
import org.whispersystems.signalservice.internal.push.GroupContextV2
|
import org.whispersystems.signalservice.internal.push.GroupContextV2
|
||||||
import org.whispersystems.signalservice.internal.push.SyncMessage
|
import org.whispersystems.signalservice.internal.push.PniSignatureMessage
|
||||||
|
|
||||||
class BuildSizeTreeTest {
|
class BuildSizeTreeTest {
|
||||||
|
|
||||||
@@ -136,12 +136,12 @@ class BuildSizeTreeTest {
|
|||||||
fun `multiple top-level fields are all included`() {
|
fun `multiple top-level fields are all included`() {
|
||||||
val msg = Content(
|
val msg = Content(
|
||||||
dataMessage = DataMessage(body = "hi"),
|
dataMessage = DataMessage(body = "hi"),
|
||||||
syncMessage = SyncMessage()
|
pniSignatureMessage = PniSignatureMessage()
|
||||||
)
|
)
|
||||||
val tree = msg.buildSizeTree("Content")
|
val tree = msg.buildSizeTree("Content")
|
||||||
|
|
||||||
assertThat(tree).contains("dataMessage(")
|
assertThat(tree).contains("dataMessage(")
|
||||||
assertThat(tree).contains("syncMessage(")
|
assertThat(tree).contains("pniSignatureMessage(")
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
|||||||
@@ -23,7 +23,7 @@ class EnvelopeContentValidatorTest {
|
|||||||
@Test
|
@Test
|
||||||
fun `validate - ensure mismatched timestamps are marked invalid`() {
|
fun `validate - ensure mismatched timestamps are marked invalid`() {
|
||||||
val envelope = Envelope(
|
val envelope = Envelope(
|
||||||
timestamp = 1234
|
clientTimestamp = 1234
|
||||||
)
|
)
|
||||||
|
|
||||||
val content = Content(
|
val content = Content(
|
||||||
@@ -172,11 +172,10 @@ class EnvelopeContentValidatorTest {
|
|||||||
fun `validate - plaintext content via envelope type with unexpected DataMessage is invalid`() {
|
fun `validate - plaintext content via envelope type with unexpected DataMessage is invalid`() {
|
||||||
val envelope = Envelope(
|
val envelope = Envelope(
|
||||||
type = Envelope.Type.PLAINTEXT_CONTENT,
|
type = Envelope.Type.PLAINTEXT_CONTENT,
|
||||||
timestamp = 1234
|
clientTimestamp = 1234
|
||||||
)
|
)
|
||||||
|
|
||||||
val content = Content(
|
val content = Content(
|
||||||
decryptionErrorMessage = createValidDecryptionErrorMessage(),
|
|
||||||
dataMessage = DataMessage(timestamp = 1234)
|
dataMessage = DataMessage(timestamp = 1234)
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -188,11 +187,10 @@ class EnvelopeContentValidatorTest {
|
|||||||
fun `validate - plaintext content via ciphertext message type (sealed sender) with unexpected DataMessage is invalid`() {
|
fun `validate - plaintext content via ciphertext message type (sealed sender) with unexpected DataMessage is invalid`() {
|
||||||
val envelope = Envelope(
|
val envelope = Envelope(
|
||||||
type = Envelope.Type.UNIDENTIFIED_SENDER,
|
type = Envelope.Type.UNIDENTIFIED_SENDER,
|
||||||
timestamp = 1234
|
clientTimestamp = 1234
|
||||||
)
|
)
|
||||||
|
|
||||||
val content = Content(
|
val content = Content(
|
||||||
decryptionErrorMessage = createValidDecryptionErrorMessage(),
|
|
||||||
dataMessage = DataMessage(timestamp = 1234)
|
dataMessage = DataMessage(timestamp = 1234)
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -231,7 +229,6 @@ class EnvelopeContentValidatorTest {
|
|||||||
)
|
)
|
||||||
|
|
||||||
val content = Content(
|
val content = Content(
|
||||||
decryptionErrorMessage = createValidDecryptionErrorMessage(),
|
|
||||||
syncMessage = org.whispersystems.signalservice.internal.push.SyncMessage()
|
syncMessage = org.whispersystems.signalservice.internal.push.SyncMessage()
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -242,8 +239,8 @@ class EnvelopeContentValidatorTest {
|
|||||||
@Test
|
@Test
|
||||||
fun `validate - regular encrypted message is not subject to plaintext validation`() {
|
fun `validate - regular encrypted message is not subject to plaintext validation`() {
|
||||||
val envelope = Envelope(
|
val envelope = Envelope(
|
||||||
type = Envelope.Type.CIPHERTEXT,
|
type = Envelope.Type.DOUBLE_RATCHET,
|
||||||
timestamp = 1234
|
clientTimestamp = 1234
|
||||||
)
|
)
|
||||||
|
|
||||||
val content = Content(
|
val content = Content(
|
||||||
|
|||||||
@@ -104,9 +104,9 @@ class SignalClient {
|
|||||||
|
|
||||||
return Envelope(
|
return Envelope(
|
||||||
sourceServiceId = aci.toString(),
|
sourceServiceId = aci.toString(),
|
||||||
sourceDevice = 1,
|
sourceDeviceId = 1,
|
||||||
destinationServiceId = to.aci.toString(),
|
destinationServiceId = to.aci.toString(),
|
||||||
timestamp = sentTimestamp,
|
clientTimestamp = sentTimestamp,
|
||||||
serverTimestamp = sentTimestamp,
|
serverTimestamp = sentTimestamp,
|
||||||
serverGuid = serviceGuid.toString(),
|
serverGuid = serviceGuid.toString(),
|
||||||
type = Envelope.Type.fromValue(outgoingPushMessage.type),
|
type = Envelope.Type.fromValue(outgoingPushMessage.type),
|
||||||
@@ -139,9 +139,9 @@ class SignalClient {
|
|||||||
|
|
||||||
return Envelope(
|
return Envelope(
|
||||||
sourceServiceId = aci.toString(),
|
sourceServiceId = aci.toString(),
|
||||||
sourceDevice = 1,
|
sourceDeviceId = 1,
|
||||||
destinationServiceId = to.aci.toString(),
|
destinationServiceId = to.aci.toString(),
|
||||||
timestamp = sentTimestamp,
|
clientTimestamp = sentTimestamp,
|
||||||
serverTimestamp = sentTimestamp,
|
serverTimestamp = sentTimestamp,
|
||||||
serverGuid = serverGuid.toString(),
|
serverGuid = serverGuid.toString(),
|
||||||
type = Envelope.Type.fromValue(outgoingPushMessage.type),
|
type = Envelope.Type.fromValue(outgoingPushMessage.type),
|
||||||
|
|||||||
Reference in New Issue
Block a user