fix: look at early expiring incoming messages for delete after read

This commit is contained in:
0x330a 2023-01-13 16:38:37 +11:00
parent 2048e08c86
commit f0aba3a973
No known key found for this signature in database
GPG Key ID: 267811D6E6A2698C
8 changed files with 71 additions and 35 deletions

View File

@ -572,7 +572,7 @@ class ConversationActivityV2 : PassphraseRequiredActionBarActivity(), InputBarDe
private fun setUpOutdatedClientBanner() {
val recipient = viewModel.recipient ?: return
if (!ExpirationConfiguration.isNewConfigEnabled && recipient.isContactRecipient &&
if (ExpirationConfiguration.isNewConfigEnabled && recipient.isContactRecipient &&
recipient.disappearingState == DisappearingState.LEGACY &&
viewModel.expirationConfiguration?.isEnabled == true
) {

View File

@ -84,9 +84,6 @@ public class ExpiringMessageManager implements SSKEnvironment.MessageExpirationM
if (expiryType == ExpirationType.DELETE_AFTER_SEND_VALUE && message.getSentTimestamp() != null && senderPublicKey != null) {
startAnyExpiration(message.getSentTimestamp(), senderPublicKey, expireStartedAt);
}
if (message.getId() != null) {
DatabaseComponent.get(context).smsDatabase().deleteMessage(message.getId());
}
}
private void insertIncomingExpirationTimerMessage(ExpirationTimerUpdate message, long expireStartedAt) {

View File

@ -18,7 +18,7 @@ import org.session.libsession.messaging.sending_receiving.MessageReceiver
import org.session.libsession.messaging.sending_receiving.handle
import org.session.libsession.messaging.sending_receiving.handleOpenGroupReactions
import org.session.libsession.messaging.sending_receiving.handleVisibleMessage
import org.session.libsession.messaging.sending_receiving.updateExpirationConfigurationIfNeeded
import org.session.libsession.messaging.sending_receiving.updateExpiryIfNeeded
import org.session.libsession.messaging.utilities.Data
import org.session.libsession.messaging.utilities.SessionId
import org.session.libsession.messaging.utilities.SodiumUtilities
@ -113,7 +113,7 @@ class BatchMessageReceiveJob(
messages.forEach { (parameters, message, proto) ->
try {
if (message is VisibleMessage) {
MessageReceiver.updateExpirationConfigurationIfNeeded(message, proto, openGroupID)
MessageReceiver.updateExpiryIfNeeded(message, proto, openGroupID)
val messageId = MessageReceiver.handleVisibleMessage(message, proto, openGroupID,
runIncrement = false,
runThreadUpdate = false,

View File

@ -13,5 +13,6 @@ class ExpirationConfiguration(
companion object {
val isNewConfigEnabled = false /* TODO: System.currentTimeMillis() > 1_676_851_200_000 // 13/02/2023 */
const val LAST_READ_TEST = 1673587663000L
}
}

View File

@ -35,11 +35,12 @@ object MessageReceiver {
object InvalidGroupPublicKey: Error("Invalid group public key.")
object NoGroupKeyPair: Error("Missing group key pair.")
object NoUserED25519KeyPair : Error("Couldn't find user ED25519 key pair.")
object ExpiredMessage: Error("Message has already expired, prevent adding")
internal val isRetryable: Boolean = when (this) {
is DuplicateMessage, is InvalidMessage, is UnknownMessage,
is UnknownEnvelopeType, is InvalidSignature, is NoData,
is SenderBlocked, is SelfSend -> false
is SenderBlocked, is SelfSend, is ExpiredMessage -> false
else -> true
}
}
@ -49,7 +50,7 @@ object MessageReceiver {
openGroupServerID: Long?,
isOutgoing: Boolean? = null,
otherBlindedPublicKey: String? = null,
openGroupPublicKey: String? = null,
openGroupPublicKey: String? = null
): Pair<Message, SignalServiceProtos.Content> {
val storage = MessagingModuleConfiguration.shared.storage
val userPublicKey = storage.getUserPublicKey()
@ -179,4 +180,5 @@ object MessageReceiver {
// Return
return Pair(message, proto)
}
}

View File

@ -39,7 +39,6 @@ import org.session.libsession.utilities.ProfileKeyUtil
import org.session.libsession.utilities.SSKEnvironment
import org.session.libsession.utilities.TextSecurePreferences
import org.session.libsession.utilities.recipients.Recipient
import org.session.libsession.utilities.recipients.Recipient.DisappearingState
import org.session.libsignal.crypto.ecc.DjbECPrivateKey
import org.session.libsignal.crypto.ecc.DjbECPublicKey
import org.session.libsignal.crypto.ecc.ECKeyPair
@ -63,7 +62,7 @@ internal fun MessageReceiver.isBlocked(publicKey: String): Boolean {
}
fun MessageReceiver.handle(message: Message, proto: SignalServiceProtos.Content, openGroupID: String?) {
updateExpirationConfigurationIfNeeded(message, proto, openGroupID)
MessageReceiver.updateExpiryIfNeeded(message, proto, openGroupID)
when (message) {
is ReadReceipt -> handleReadReceipt(message)
is TypingIndicator -> handleTypingIndicator(message)
@ -82,29 +81,6 @@ fun MessageReceiver.handle(message: Message, proto: SignalServiceProtos.Content,
}
}
fun MessageReceiver.updateExpirationConfigurationIfNeeded(message: Message, proto: SignalServiceProtos.Content, openGroupID: String?) {
val storage = MessagingModuleConfiguration.shared.storage
val disappearingState = if (proto.hasExpirationTimer()) DisappearingState.UPDATED else DisappearingState.LEGACY
if (!proto.hasLastDisappearingMessageChangeTimestamp() || !ExpirationConfiguration.isNewConfigEnabled) return
val threadID = storage.getOrCreateThreadIdFor(message.sender!!, message.groupPublicKey, openGroupID)
if (threadID <= 0) return
storage.updateDisappearingState(threadID, disappearingState)
val localConfig = storage.getExpirationConfiguration(threadID)
if (localConfig != null && localConfig.updatedTimestampMs > proto.lastDisappearingMessageChangeTimestamp) return
val durationSeconds = if (proto.hasExpirationTimer()) proto.expirationTimer else 0
val type = if (proto.hasExpirationType()) proto.expirationType else null
val remoteConfig = ExpirationConfiguration(
threadID,
durationSeconds,
type?.number ?: -1,
proto.lastDisappearingMessageChangeTimestamp
)
storage.setExpirationConfiguration(remoteConfig)
if (message is ExpirationTimerUpdate) {
SSKEnvironment.shared.messageExpirationManager.setExpirationTimer(message, type?.number ?: -1)
}
}
// region Control Messages
private fun MessageReceiver.handleReadReceipt(message: ReadReceipt) {
val context = MessagingModuleConfiguration.shared.context
@ -256,6 +232,63 @@ fun handleMessageRequestResponse(message: MessageRequestResponse) {
}
//endregion
fun MessageReceiver.updateExpiryIfNeeded(message: Message, proto: SignalServiceProtos.Content, openGroupID: String?) {
val storage = MessagingModuleConfiguration.shared.storage
val sentTime = message.sentTimestamp ?: throw MessageReceiver.Error.InvalidMessage
if (!proto.hasLastDisappearingMessageChangeTimestamp()) return
val threadID = storage.getOrCreateThreadIdFor(message.sender!!, message.groupPublicKey, openGroupID)
if (threadID <= 0) throw MessageReceiver.Error.NoThread
val localConfig = storage.getExpirationConfiguration(threadID)
val durationSeconds = if (proto.hasExpirationTimer()) proto.expirationTimer else 0
val type = if (proto.hasExpirationType()) proto.expirationType else null
val remoteConfig = ExpirationConfiguration(
threadID,
durationSeconds,
type?.number ?: -1,
proto.lastDisappearingMessageChangeTimestamp
)
val (shouldUpdateConfig, configToUse) =
if (localConfig != null && localConfig.updatedTimestampMs > proto.lastDisappearingMessageChangeTimestamp) {
false to localConfig
} else {
true to remoteConfig
}
val recipient = storage.getRecipientForThread(threadID) ?: throw MessageReceiver.Error.NoThread
// don't update any values for open groups
if (recipient.isOpenGroupRecipient && type != null) throw MessageReceiver.Error.InvalidMessage
if ((recipient.isGroupRecipient || recipient.isLocalNumber)
&& type == ExpirationType.DELETE_AFTER_READ) {
// don't allow deleteAfterRead if we are sending to note to self or a group, treat the entire message as invalid
throw MessageReceiver.Error.InvalidMessage
}
// handle a delete after send expired fetch
if (type == ExpirationType.DELETE_AFTER_SEND
&& sentTime + configToUse.durationSeconds <= SnodeAPI.nowWithClockOffset) {
throw MessageReceiver.Error.ExpiredMessage
}
// handle a delete after read last known config value (test) TODO: actually implement this with shared config library
if (type == ExpirationType.DELETE_AFTER_READ
&& sentTime + configToUse.durationSeconds <= ExpirationConfiguration.LAST_READ_TEST) {
throw MessageReceiver.Error.ExpiredMessage
}
if (shouldUpdateConfig) {
val disappearingState = if (proto.hasExpirationType()) Recipient.DisappearingState.UPDATED else Recipient.DisappearingState.LEGACY
storage.updateDisappearingState(threadID, disappearingState)
storage.setExpirationConfiguration(configToUse)
}
if (message is ExpirationTimerUpdate) {
SSKEnvironment.shared.messageExpirationManager.setExpirationTimer(message, type?.number ?: -1)
}
}
fun MessageReceiver.handleVisibleMessage(message: VisibleMessage,
proto: SignalServiceProtos.Content,
openGroupID: String?,

View File

@ -25,7 +25,6 @@ import org.session.libsignal.utilities.Snode
import org.session.libsignal.utilities.ThreadUtils
import org.session.libsignal.utilities.recover
import org.session.libsignal.utilities.toHexString
import java.util.Date
import kotlin.collections.set
private typealias Path = List<Snode>
@ -594,7 +593,7 @@ object OnionRequestAPI {
}
if (body["t"] != null) {
val timestamp = body["t"] as Long
val offset = timestamp - Date().time
val offset = timestamp - System.currentTimeMillis()
SnodeAPI.clockOffset = offset
}
if (body.containsKey("hf")) {

View File

@ -56,6 +56,10 @@ object SnodeAPI {
* user's clock is incorrect.
*/
var clockOffset = 0L
val nowWithClockOffset
get() = System.currentTimeMillis() + clockOffset
internal var forkInfo by observable(database.getForkInfo()) { _, oldValue, newValue ->
if (newValue > oldValue) {
Log.d("Loki", "Setting new fork info new: $newValue, old: $oldValue")