mirror of
https://github.com/oxen-io/session-android.git
synced 2025-02-20 06:08:27 +00:00
Fix duplicate message handling
This commit is contained in:
parent
7d241eab6c
commit
2a3d06e485
@ -351,7 +351,7 @@ class Storage(context: Context, helper: SQLCipherOpenHelper) : Database(context,
|
|||||||
DatabaseFactory.getLokiAPIDatabase(context).removeLastDeletionServerID(group, server)
|
DatabaseFactory.getLokiAPIDatabase(context).removeLastDeletionServerID(group, server)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun isDuplicateMessage(timestamp: Long, sender: String): Boolean {
|
override fun isDuplicateMessage(timestamp: Long): Boolean {
|
||||||
return getReceivedMessageTimestamps().contains(timestamp)
|
return getReceivedMessageTimestamps().contains(timestamp)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -27,19 +27,21 @@ class PushNotificationService : FirebaseMessagingService() {
|
|||||||
val data = base64EncodedData?.let { Base64.decode(it) }
|
val data = base64EncodedData?.let { Base64.decode(it) }
|
||||||
if (data != null) {
|
if (data != null) {
|
||||||
try {
|
try {
|
||||||
JobQueue.shared.add(MessageReceiveJob(MessageWrapper.unwrap(data).toByteArray(),true))
|
val envelopeAsData = MessageWrapper.unwrap(data).toByteArray()
|
||||||
|
val job = MessageReceiveJob(envelopeAsData,true)
|
||||||
|
JobQueue.shared.add(job)
|
||||||
} catch (e: Exception) {
|
} catch (e: Exception) {
|
||||||
Log.d("Loki", "Failed to unwrap data for message due to error: $e.")
|
Log.d("Loki", "Failed to unwrap data for message due to error: $e.")
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
Log.d("Loki", "Failed to decode data for message.")
|
Log.d("Loki", "Failed to decode data for message.")
|
||||||
val builder = NotificationCompat.Builder(this, NotificationChannels.OTHER)
|
val builder = NotificationCompat.Builder(this, NotificationChannels.OTHER)
|
||||||
.setSmallIcon(network.loki.messenger.R.drawable.ic_notification)
|
.setSmallIcon(network.loki.messenger.R.drawable.ic_notification)
|
||||||
.setColor(this.getResources().getColor(network.loki.messenger.R.color.textsecure_primary))
|
.setColor(this.getResources().getColor(network.loki.messenger.R.color.textsecure_primary))
|
||||||
.setContentTitle("Session")
|
.setContentTitle("Session")
|
||||||
.setContentText("You've got a new message.")
|
.setContentText("You've got a new message.")
|
||||||
.setPriority(NotificationCompat.PRIORITY_DEFAULT)
|
.setPriority(NotificationCompat.PRIORITY_DEFAULT)
|
||||||
.setAutoCancel(true)
|
.setAutoCancel(true)
|
||||||
with(NotificationManagerCompat.from(this)) {
|
with(NotificationManagerCompat.from(this)) {
|
||||||
notify(11111, builder.build())
|
notify(11111, builder.build())
|
||||||
}
|
}
|
||||||
|
@ -92,7 +92,7 @@ interface StorageProtocol {
|
|||||||
fun removeLastDeletionServerId(room: String, server: String)
|
fun removeLastDeletionServerId(room: String, server: String)
|
||||||
|
|
||||||
// Message Handling
|
// Message Handling
|
||||||
fun isDuplicateMessage(timestamp: Long, sender: String): Boolean
|
fun isDuplicateMessage(timestamp: Long): Boolean
|
||||||
fun getReceivedMessageTimestamps(): Set<Long>
|
fun getReceivedMessageTimestamps(): Set<Long>
|
||||||
fun addReceivedMessageTimestamp(timestamp: Long)
|
fun addReceivedMessageTimestamp(timestamp: Long)
|
||||||
fun removeReceivedMessageTimestamps(timestamps: Set<Long>)
|
fun removeReceivedMessageTimestamps(timestamps: Set<Long>)
|
||||||
|
@ -38,12 +38,6 @@ object MessageReceiver {
|
|||||||
val isOpenGroupMessage = (openGroupServerID != null)
|
val isOpenGroupMessage = (openGroupServerID != null)
|
||||||
// Parse the envelope
|
// Parse the envelope
|
||||||
val envelope = SignalServiceProtos.Envelope.parseFrom(data)
|
val envelope = SignalServiceProtos.Envelope.parseFrom(data)
|
||||||
// If the message failed to process the first time around we retry it later (if the error is retryable). In this case the timestamp
|
|
||||||
// will already be in the database but we don't want to treat the message as a duplicate. The isRetry flag is a simple workaround
|
|
||||||
// for this issue.
|
|
||||||
if (storage.isDuplicateMessage(envelope.timestamp, GroupUtil.doubleEncodeGroupID(envelope.source)) && !isRetry) {
|
|
||||||
throw Error.DuplicateMessage
|
|
||||||
}
|
|
||||||
// Decrypt the contents
|
// Decrypt the contents
|
||||||
val ciphertext = envelope.content ?: throw Error.NoData
|
val ciphertext = envelope.content ?: throw Error.NoData
|
||||||
var plaintext: ByteArray? = null
|
var plaintext: ByteArray? = null
|
||||||
@ -90,8 +84,6 @@ object MessageReceiver {
|
|||||||
else -> throw Error.UnknownEnvelopeType
|
else -> throw Error.UnknownEnvelopeType
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// Don't process the envelope any further if the message has been handled already
|
|
||||||
if (storage.isDuplicateMessage(envelope.timestamp, sender!!) && !isRetry) throw Error.DuplicateMessage
|
|
||||||
// Don't process the envelope any further if the sender is blocked
|
// Don't process the envelope any further if the sender is blocked
|
||||||
if (isBlocked(sender!!)) throw Error.SenderBlocked
|
if (isBlocked(sender!!)) throw Error.SenderBlocked
|
||||||
// Parse the proto
|
// Parse the proto
|
||||||
@ -119,6 +111,19 @@ object MessageReceiver {
|
|||||||
var isValid = message.isValid()
|
var isValid = message.isValid()
|
||||||
if (message is VisibleMessage && !isValid && proto.dataMessage.attachmentsCount != 0) { isValid = true }
|
if (message is VisibleMessage && !isValid && proto.dataMessage.attachmentsCount != 0) { isValid = true }
|
||||||
if (!isValid) { throw Error.InvalidMessage }
|
if (!isValid) { throw Error.InvalidMessage }
|
||||||
|
// If the message failed to process the first time around we retry it later (if the error is retryable). In this case the timestamp
|
||||||
|
// will already be in the database but we don't want to treat the message as a duplicate. The isRetry flag is a simple workaround
|
||||||
|
// for this issue.
|
||||||
|
if (message is ClosedGroupControlMessage && message.kind is ClosedGroupControlMessage.Kind.New) {
|
||||||
|
// Allow duplicates in this case to avoid the following situation:
|
||||||
|
// • The app performed a background poll or received a push notification
|
||||||
|
// • This method was invoked and the received message timestamps table was updated
|
||||||
|
// • Processing wasn't finished
|
||||||
|
// • The user doesn't see the new closed group
|
||||||
|
} else {
|
||||||
|
if (storage.isDuplicateMessage(envelope.timestamp)) { throw Error.DuplicateMessage }
|
||||||
|
storage.addReceivedMessageTimestamp(envelope.timestamp)
|
||||||
|
}
|
||||||
// Return
|
// Return
|
||||||
return Pair(message, proto)
|
return Pair(message, proto)
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user