Merge remote-tracking branch 'upstream/dev' into libsession-integration

# Conflicts:
#	app/src/main/java/org/thoughtcrime/securesms/conversation/v2/ConversationActivityV2.kt
#	app/src/main/java/org/thoughtcrime/securesms/database/ThreadDatabase.java
#	libsession/src/main/java/org/session/libsession/messaging/sending_receiving/MessageSender.kt
#	libsession/src/main/java/org/session/libsession/snode/SnodeAPI.kt
This commit is contained in:
0x330a
2023-03-31 13:41:41 +11:00
32 changed files with 328 additions and 119 deletions

View File

@@ -98,19 +98,19 @@ class BatchMessageReceiveJob(
} catch (e: Exception) {
when (e) {
is MessageReceiver.Error.DuplicateMessage, MessageReceiver.Error.SelfSend -> {
Log.i(TAG, "Couldn't receive message, failed with error: ${e.message}")
Log.i(TAG, "Couldn't receive message, failed with error: ${e.message} (id: $id)")
}
is MessageReceiver.Error -> {
if (!e.isRetryable) {
Log.e(TAG, "Couldn't receive message, failed permanently", e)
Log.e(TAG, "Couldn't receive message, failed permanently (id: $id)", e)
}
else {
Log.e(TAG, "Couldn't receive message, failed", e)
Log.e(TAG, "Couldn't receive message, failed (id: $id)", e)
failures += messageParameters
}
}
else -> {
Log.e(TAG, "Couldn't receive message, failed", e)
Log.e(TAG, "Couldn't receive message, failed (id: $id)", e)
failures += messageParameters
}
}
@@ -166,11 +166,11 @@ class BatchMessageReceiveJob(
else -> MessageReceiver.handle(message, proto, openGroupID)
}
} catch (e: Exception) {
Log.e(TAG, "Couldn't process message.", e)
Log.e(TAG, "Couldn't process message (id: $id)", e)
if (e is MessageReceiver.Error && !e.isRetryable) {
Log.e(TAG, "Message failed permanently",e)
Log.e(TAG, "Message failed permanently (id: $id)", e)
} else {
Log.e(TAG, "Message failed",e)
Log.e(TAG, "Message failed (id: $id)", e)
failures += parameters
}
}
@@ -199,12 +199,12 @@ class BatchMessageReceiveJob(
}
private fun handleSuccess(dispatcherName: String) {
Log.i(TAG, "Completed processing of ${messages.size} messages")
Log.i(TAG, "Completed processing of ${messages.size} messages (id: $id)")
this.delegate?.handleJobSucceeded(this, dispatcherName)
}
private fun handleFailure(dispatcherName: String) {
Log.i(TAG, "Handling failure of ${failures.size} messages (${messages.size - failures.size} processed successfully)")
Log.i(TAG, "Handling failure of ${failures.size} messages (${messages.size - failures.size} processed successfully) (id: $id)")
this.delegate?.handleJobFailed(this, dispatcherName, Exception("One or more jobs resulted in failure"))
}

View File

@@ -3,6 +3,7 @@ package org.session.libsession.messaging.jobs
import org.session.libsession.messaging.MessagingModuleConfiguration
import org.session.libsession.messaging.open_groups.OpenGroupApi
import org.session.libsession.messaging.utilities.Data
import org.session.libsession.snode.SnodeAPI
import org.session.libsession.utilities.GroupUtil
class GroupAvatarDownloadJob(val server: String, val room: String, val imageId: String?) : Job {
@@ -43,7 +44,7 @@ class GroupAvatarDownloadJob(val server: String, val room: String, val imageId:
val groupId = GroupUtil.getEncodedOpenGroupID("$server.$room".toByteArray())
storage.updateProfilePicture(groupId, bytes)
storage.updateTimestampUpdated(groupId, System.currentTimeMillis())
storage.updateTimestampUpdated(groupId, SnodeAPI.nowWithOffset)
delegate?.handleJobSucceeded(this, dispatcherName)
} catch (e: Exception) {
delegate?.handleJobFailed(this, dispatcherName, e)

View File

@@ -23,6 +23,7 @@ import org.session.libsession.messaging.utilities.SessionId
import org.session.libsession.messaging.utilities.SodiumUtilities
import org.session.libsession.snode.OnionRequestAPI
import org.session.libsession.snode.OnionResponse
import org.session.libsession.snode.SnodeAPI
import org.session.libsession.utilities.TextSecurePreferences
import org.session.libsignal.utilities.Base64.decode
import org.session.libsignal.utilities.Base64.encodeBytes
@@ -303,7 +304,7 @@ object OpenGroupApi {
val headers = request.headers.toMutableMap()
if (request.isAuthRequired) {
val nonce = sodium.nonce(16)
val timestamp = TimeUnit.MILLISECONDS.toSeconds(System.currentTimeMillis())
val timestamp = TimeUnit.MILLISECONDS.toSeconds(SnodeAPI.nowWithOffset)
var pubKey = ""
var signature = ByteArray(Sign.BYTES)
var bodyHash = ByteArray(0)

View File

@@ -15,6 +15,7 @@ import org.session.libsession.messaging.messages.control.UnsendRequest
import org.session.libsession.messaging.messages.visible.VisibleMessage
import org.session.libsession.messaging.utilities.SessionId
import org.session.libsession.messaging.utilities.SodiumUtilities
import org.session.libsession.snode.SnodeAPI
import org.session.libsignal.crypto.PushTransportDetails
import org.session.libsignal.protos.SignalServiceProtos
import org.session.libsignal.utilities.IdPrefix
@@ -156,7 +157,7 @@ object MessageReceiver {
message.sender = sender
message.recipient = userPublicKey
message.sentTimestamp = envelope.timestamp
message.receivedTimestamp = if (envelope.hasServerTimestamp()) envelope.serverTimestamp else System.currentTimeMillis()
message.receivedTimestamp = if (envelope.hasServerTimestamp()) envelope.serverTimestamp else SnodeAPI.nowWithOffset
message.groupPublicKey = groupPublicKey
message.openGroupServerMessageID = openGroupServerID
// Validate

View File

@@ -199,7 +199,20 @@ object MessageSender {
val hash = it["hash"] as? String
message.serverHash = hash
handleSuccessfulMessageSend(message, destination, isSyncMessage)
val shouldNotify = ((message is VisibleMessage || message is UnsendRequest || message is CallMessage) && !isSyncMessage)
val shouldNotify: Boolean = when (message) {
is VisibleMessage, is UnsendRequest -> !isSyncMessage
is CallMessage -> {
// Note: Other 'CallMessage' types are too big to send as push notifications
// so only send the 'preOffer' message as a notification
when (message.type) {
SignalServiceProtos.CallMessage.Type.PRE_OFFER -> true
else -> false
}
}
else -> false
}
/*
if (message is ClosedGroupControlMessage && message.kind is ClosedGroupControlMessage.Kind.New) {
shouldNotify = true
@@ -229,7 +242,7 @@ object MessageSender {
val deferred = deferred<Unit, Exception>()
val storage = MessagingModuleConfiguration.shared.storage
if (message.sentTimestamp == null) {
message.sentTimestamp = System.currentTimeMillis()
message.sentTimestamp = SnodeAPI.nowWithOffset
}
val userEdKeyPair = MessagingModuleConfiguration.shared.getUserED25519KeyPair()!!
var serverCapabilities = listOf<String>()

View File

@@ -50,11 +50,11 @@ fun MessageSender.create(name: String, members: Collection<String>): Promise<Str
val admins = setOf( userPublicKey )
val adminsAsData = admins.map { ByteString.copyFrom(Hex.fromStringCondensed(it)) }
storage.createGroup(groupID, name, LinkedList(members.map { Address.fromSerialized(it) }),
null, null, LinkedList(admins.map { Address.fromSerialized(it) }), System.currentTimeMillis())
null, null, LinkedList(admins.map { Address.fromSerialized(it) }), SnodeAPI.nowWithOffset)
storage.setProfileSharing(Address.fromSerialized(groupID), true)
// Send a closed group update message to all members individually
val closedGroupUpdateKind = ClosedGroupControlMessage.Kind.New(ByteString.copyFrom(Hex.fromStringCondensed(groupPublicKey)), name, encryptionKeyPair, membersAsData, adminsAsData, 0)
val sentTime = System.currentTimeMillis()
val sentTime = SnodeAPI.nowWithOffset
for (member in members) {
val closedGroupControlMessage = ClosedGroupControlMessage(closedGroupUpdateKind)
closedGroupControlMessage.sentTimestamp = sentTime
@@ -97,7 +97,7 @@ fun MessageSender.setName(groupPublicKey: String, newName: String) {
val admins = group.admins.map { it.serialize() }
// Send the update to the group
val kind = ClosedGroupControlMessage.Kind.NameChange(newName)
val sentTime = System.currentTimeMillis()
val sentTime = SnodeAPI.nowWithOffset
val closedGroupControlMessage = ClosedGroupControlMessage(kind)
closedGroupControlMessage.sentTimestamp = sentTime
send(closedGroupControlMessage, Address.fromSerialized(groupID))
@@ -137,7 +137,7 @@ fun MessageSender.addMembers(groupPublicKey: String, membersToAdd: List<String>)
val name = group.title
// Send the update to the group
val memberUpdateKind = ClosedGroupControlMessage.Kind.MembersAdded(newMembersAsData)
val sentTime = System.currentTimeMillis()
val sentTime = SnodeAPI.nowWithOffset
val closedGroupControlMessage = ClosedGroupControlMessage(memberUpdateKind)
closedGroupControlMessage.sentTimestamp = sentTime
send(closedGroupControlMessage, Address.fromSerialized(groupID))
@@ -151,7 +151,7 @@ fun MessageSender.addMembers(groupPublicKey: String, membersToAdd: List<String>)
// updates from before that timestamp. By setting the timestamp of the message below to a value
// greater than that of the `MembersAdded` message, we ensure that newly added members ignore
// the `MembersAdded` message.
closedGroupControlMessage.sentTimestamp = System.currentTimeMillis()
closedGroupControlMessage.sentTimestamp = SnodeAPI.nowWithOffset
send(closedGroupControlMessage, Address.fromSerialized(member))
}
// Notify the user
@@ -192,7 +192,7 @@ fun MessageSender.removeMembers(groupPublicKey: String, membersToRemove: List<St
val name = group.title
// Send the update to the group
val memberUpdateKind = ClosedGroupControlMessage.Kind.MembersRemoved(removeMembersAsData)
val sentTime = System.currentTimeMillis()
val sentTime = SnodeAPI.nowWithOffset
val closedGroupControlMessage = ClosedGroupControlMessage(memberUpdateKind)
closedGroupControlMessage.sentTimestamp = sentTime
send(closedGroupControlMessage, Address.fromSerialized(groupID))
@@ -223,7 +223,7 @@ fun MessageSender.leave(groupPublicKey: String, notifyUser: Boolean = true): Pro
val name = group.title
// Send the update to the group
val closedGroupControlMessage = ClosedGroupControlMessage(ClosedGroupControlMessage.Kind.MemberLeft())
val sentTime = System.currentTimeMillis()
val sentTime = SnodeAPI.nowWithOffset
closedGroupControlMessage.sentTimestamp = sentTime
storage.setActive(groupID, false)
sendNonDurably(closedGroupControlMessage, Address.fromSerialized(groupID)).success {

View File

@@ -54,10 +54,9 @@ class ClosedGroupPollerV2 {
setUpPolling(groupPublicKey)
}
fun stop() {
val storage = MessagingModuleConfiguration.shared.storage
val allGroupPublicKeys = storage.getAllClosedGroupPublicKeys()
allGroupPublicKeys.iterator().forEach { stopPolling(it) }
fun stopAll() {
futures.forEach { it.value.cancel(false) }
isPolling.forEach { isPolling[it.key] = false }
}
fun stopPolling(groupPublicKey: String) {

View File

@@ -26,6 +26,7 @@ import org.session.libsignal.utilities.ThreadUtils
import org.session.libsignal.utilities.recover
import org.session.libsignal.utilities.toHexString
import java.util.Date
import java.util.concurrent.atomic.AtomicReference
import kotlin.collections.set
private typealias Path = List<Snode>
@@ -43,13 +44,27 @@ object OnionRequestAPI {
private val snodeFailureCount = mutableMapOf<Snode, Int>()
var guardSnodes = setOf<Snode>()
var _paths: AtomicReference<List<Path>?> = AtomicReference(null)
var paths: List<Path> // Not a set to ensure we consistently show the same path to the user
get() = database.getOnionRequestPaths()
get() {
val paths = _paths.get()
if (paths != null) { return paths }
// Storing this in an atomic variable as it was causing a number of background
// ANRs when this value was accessed via the main thread after tapping on
// a notification)
val result = database.getOnionRequestPaths()
_paths.set(result)
return result
}
set(newValue) {
if (newValue.isEmpty()) {
database.clearOnionRequestPaths()
_paths.set(null)
} else {
database.setOnionRequestPaths(newValue)
_paths.set(newValue)
}
}

View File

@@ -57,7 +57,7 @@ object SnodeAPI {
internal var clockOffset = 0L
@JvmStatic
val nowWithOffset
public val nowWithOffset
get() = System.currentTimeMillis() + clockOffset
internal var forkInfo by observable(database.getForkInfo()) { _, oldValue, newValue ->
@@ -590,7 +590,7 @@ object SnodeAPI {
val parameters = message.toJSON().toMutableMap<String,Any>()
// Construct signature
if (requiresAuth) {
val sigTimestamp = System.currentTimeMillis() + SnodeAPI.clockOffset
val sigTimestamp = nowWithOffset
val ed25519PublicKey = userED25519KeyPair.publicKey.asHexString
val signature = ByteArray(Sign.BYTES)
// assume namespace here is non-zero, as zero namespace doesn't require auth

View File

@@ -26,7 +26,7 @@ class SSKEnvironment(
interface ProfileManagerProtocol {
companion object {
const val NAME_PADDED_LENGTH = 26
const val NAME_PADDED_LENGTH = 64
}
fun setNickname(context: Context, recipient: Recipient, nickname: String?)
@@ -55,4 +55,4 @@ class SSKEnvironment(
shared = SSKEnvironment(typingIndicators, readReceiptManager, profileManager, notificationManager, messageExpirationManager)
}
}
}
}