mirror of
https://github.com/oxen-io/session-android.git
synced 2025-01-12 01:33:39 +00:00
Merge pull request #477 from RyanRory/refactor-sending-fix
The Refactor: Fix sending crashes
This commit is contained in:
commit
16076fe40a
@ -255,8 +255,7 @@ public class SQLCipherOpenHelper extends SQLiteOpenHelper {
|
|||||||
"SmsSentJob",
|
"SmsSentJob",
|
||||||
"SmsReceiveJob",
|
"SmsReceiveJob",
|
||||||
"PushGroupUpdateJob",
|
"PushGroupUpdateJob",
|
||||||
"ResetThreadSessionJob",
|
"ResetThreadSessionJob");
|
||||||
"SendDeliveryReceiptJob");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (oldVersion < lokiV22) {
|
if (oldVersion < lokiV22) {
|
||||||
@ -269,7 +268,8 @@ public class SQLCipherOpenHelper extends SQLiteOpenHelper {
|
|||||||
"TypingSendJob",
|
"TypingSendJob",
|
||||||
"AttachmentUploadJob",
|
"AttachmentUploadJob",
|
||||||
"RequestGroupInfoJob",
|
"RequestGroupInfoJob",
|
||||||
"ClosedGroupUpdateMessageSendJobV2");
|
"ClosedGroupUpdateMessageSendJobV2",
|
||||||
|
"SendDeliveryReceiptJob");
|
||||||
}
|
}
|
||||||
|
|
||||||
db.setTransactionSuccessful();
|
db.setTransactionSuccessful();
|
||||||
|
@ -79,8 +79,8 @@ object MultiDeviceProtocol {
|
|||||||
closedGroupUpdate.publicKey = ByteString.copyFrom(Hex.fromStringCondensed(closedGroup.publicKey))
|
closedGroupUpdate.publicKey = ByteString.copyFrom(Hex.fromStringCondensed(closedGroup.publicKey))
|
||||||
closedGroupUpdate.name = closedGroup.name
|
closedGroupUpdate.name = closedGroup.name
|
||||||
val encryptionKeyPair = SignalServiceProtos.KeyPair.newBuilder()
|
val encryptionKeyPair = SignalServiceProtos.KeyPair.newBuilder()
|
||||||
encryptionKeyPair.publicKey = ByteString.copyFrom(closedGroup.encryptionKeyPair.publicKey.serialize().removing05PrefixIfNeeded())
|
encryptionKeyPair.publicKey = ByteString.copyFrom(closedGroup.encryptionKeyPair!!.publicKey.serialize().removing05PrefixIfNeeded())
|
||||||
encryptionKeyPair.privateKey = ByteString.copyFrom(closedGroup.encryptionKeyPair.privateKey.serialize())
|
encryptionKeyPair.privateKey = ByteString.copyFrom(closedGroup.encryptionKeyPair!!.privateKey.serialize())
|
||||||
closedGroupUpdate.encryptionKeyPair = encryptionKeyPair.build()
|
closedGroupUpdate.encryptionKeyPair = encryptionKeyPair.build()
|
||||||
closedGroupUpdate.addAllMembers(closedGroup.members.map { ByteString.copyFrom(Hex.fromStringCondensed(it)) })
|
closedGroupUpdate.addAllMembers(closedGroup.members.map { ByteString.copyFrom(Hex.fromStringCondensed(it)) })
|
||||||
closedGroupUpdate.addAllAdmins(closedGroup.admins.map { ByteString.copyFrom(Hex.fromStringCondensed(it)) })
|
closedGroupUpdate.addAllAdmins(closedGroup.admins.map { ByteString.copyFrom(Hex.fromStringCondensed(it)) })
|
||||||
|
@ -7,25 +7,14 @@ import org.session.libsignal.service.loki.utilities.toHexString
|
|||||||
|
|
||||||
sealed class Destination {
|
sealed class Destination {
|
||||||
|
|
||||||
class Contact() : Destination() {
|
class Contact(var publicKey: String) : Destination() {
|
||||||
var publicKey: String = ""
|
internal constructor(): this("")
|
||||||
internal constructor(publicKey: String): this() {
|
|
||||||
this.publicKey = publicKey
|
|
||||||
}
|
}
|
||||||
|
class ClosedGroup(var groupPublicKey: String) : Destination() {
|
||||||
|
internal constructor(): this("")
|
||||||
}
|
}
|
||||||
class ClosedGroup() : Destination() {
|
class OpenGroup(var channel: Long, var server: String) : Destination() {
|
||||||
var groupPublicKey: String = ""
|
internal constructor(): this(0, "")
|
||||||
internal constructor(groupPublicKey: String): this() {
|
|
||||||
this.groupPublicKey = groupPublicKey
|
|
||||||
}
|
|
||||||
}
|
|
||||||
class OpenGroup() : Destination() {
|
|
||||||
var channel: Long = 0
|
|
||||||
var server: String = ""
|
|
||||||
internal constructor(channel: Long, server: String): this() {
|
|
||||||
this.channel = channel
|
|
||||||
this.server = server
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
|
@ -30,18 +30,30 @@ class ClosedGroupControlMessage() : ControlMessage() {
|
|||||||
|
|
||||||
// Kind enum
|
// Kind enum
|
||||||
sealed class Kind {
|
sealed class Kind {
|
||||||
class New(val publicKey: ByteString, val name: String, val encryptionKeyPair: ECKeyPair, val members: List<ByteString>, val admins: List<ByteString>) : Kind()
|
class New(var publicKey: ByteString, var name: String, var encryptionKeyPair: ECKeyPair?, var members: List<ByteString>, var admins: List<ByteString>) : Kind() {
|
||||||
|
internal constructor(): this(ByteString.EMPTY, "", null, listOf(), listOf())
|
||||||
|
}
|
||||||
/// - Note: Deprecated in favor of more explicit group updates.
|
/// - Note: Deprecated in favor of more explicit group updates.
|
||||||
class Update(val name: String, val members: List<ByteString>) : Kind()
|
class Update(var name: String, var members: List<ByteString>) : Kind() {
|
||||||
|
internal constructor(): this("", listOf())
|
||||||
|
}
|
||||||
/// An encryption key pair encrypted for each member individually.
|
/// An encryption key pair encrypted for each member individually.
|
||||||
///
|
///
|
||||||
/// - Note: `publicKey` is only set when an encryption key pair is sent in a one-to-one context (i.e. not in a group).
|
/// - Note: `publicKey` is only set when an encryption key pair is sent in a one-to-one context (i.e. not in a group).
|
||||||
class EncryptionKeyPair(val publicKey: ByteString?, val wrappers: Collection<KeyPairWrapper>) : Kind()
|
class EncryptionKeyPair(var publicKey: ByteString?, var wrappers: Collection<KeyPairWrapper>) : Kind() {
|
||||||
class NameChange(val name: String) : Kind()
|
internal constructor(): this(null, listOf())
|
||||||
class MembersAdded(val members: List<ByteString>) : Kind()
|
}
|
||||||
class MembersRemoved( val members: List<ByteString>) : Kind()
|
class NameChange(var name: String) : Kind() {
|
||||||
class MemberLeft : Kind()
|
internal constructor(): this("")
|
||||||
class EncryptionKeyPairRequest: Kind()
|
}
|
||||||
|
class MembersAdded(var members: List<ByteString>) : Kind() {
|
||||||
|
internal constructor(): this(listOf())
|
||||||
|
}
|
||||||
|
class MembersRemoved(var members: List<ByteString>) : Kind() {
|
||||||
|
internal constructor(): this(listOf())
|
||||||
|
}
|
||||||
|
class MemberLeft() : Kind()
|
||||||
|
class EncryptionKeyPairRequest(): Kind()
|
||||||
|
|
||||||
val description: String = run {
|
val description: String = run {
|
||||||
when(this) {
|
when(this) {
|
||||||
@ -118,8 +130,8 @@ class ClosedGroupControlMessage() : ControlMessage() {
|
|||||||
val kind = kind ?: return false
|
val kind = kind ?: return false
|
||||||
return when(kind) {
|
return when(kind) {
|
||||||
is Kind.New -> {
|
is Kind.New -> {
|
||||||
!kind.publicKey.isEmpty && kind.name.isNotEmpty() && kind.encryptionKeyPair.publicKey != null
|
!kind.publicKey.isEmpty && kind.name.isNotEmpty() && kind.encryptionKeyPair!!.publicKey != null
|
||||||
&& kind.encryptionKeyPair.privateKey != null && kind.members.isNotEmpty() && kind.admins.isNotEmpty()
|
&& kind.encryptionKeyPair!!.privateKey != null && kind.members.isNotEmpty() && kind.admins.isNotEmpty()
|
||||||
}
|
}
|
||||||
is Kind.Update -> kind.name.isNotEmpty()
|
is Kind.Update -> kind.name.isNotEmpty()
|
||||||
is Kind.EncryptionKeyPair -> true
|
is Kind.EncryptionKeyPair -> true
|
||||||
@ -145,8 +157,8 @@ class ClosedGroupControlMessage() : ControlMessage() {
|
|||||||
closedGroupControlMessage.publicKey = kind.publicKey
|
closedGroupControlMessage.publicKey = kind.publicKey
|
||||||
closedGroupControlMessage.name = kind.name
|
closedGroupControlMessage.name = kind.name
|
||||||
val encryptionKeyPair = SignalServiceProtos.KeyPair.newBuilder()
|
val encryptionKeyPair = SignalServiceProtos.KeyPair.newBuilder()
|
||||||
encryptionKeyPair.publicKey = ByteString.copyFrom(kind.encryptionKeyPair.publicKey.serialize().removing05PrefixIfNeeded())
|
encryptionKeyPair.publicKey = ByteString.copyFrom(kind.encryptionKeyPair!!.publicKey.serialize().removing05PrefixIfNeeded())
|
||||||
encryptionKeyPair.privateKey = ByteString.copyFrom(kind.encryptionKeyPair.privateKey.serialize())
|
encryptionKeyPair.privateKey = ByteString.copyFrom(kind.encryptionKeyPair!!.privateKey.serialize())
|
||||||
closedGroupControlMessage.encryptionKeyPair = encryptionKeyPair.build()
|
closedGroupControlMessage.encryptionKeyPair = encryptionKeyPair.build()
|
||||||
closedGroupControlMessage.addAllMembers(kind.members)
|
closedGroupControlMessage.addAllMembers(kind.members)
|
||||||
closedGroupControlMessage.addAllAdmins(kind.admins)
|
closedGroupControlMessage.addAllAdmins(kind.admins)
|
||||||
|
@ -14,11 +14,13 @@ import org.session.libsignal.service.loki.utilities.removing05PrefixIfNeeded
|
|||||||
import org.session.libsignal.service.loki.utilities.toHexString
|
import org.session.libsignal.service.loki.utilities.toHexString
|
||||||
import org.session.libsignal.utilities.Hex
|
import org.session.libsignal.utilities.Hex
|
||||||
|
|
||||||
class ConfigurationMessage(val closedGroups: List<ClosedGroup>, val openGroups: List<String>, val contacts: List<Contact>, val displayName: String, val profilePicture: String?, val profileKey: ByteArray): ControlMessage() {
|
class ConfigurationMessage(var closedGroups: List<ClosedGroup>, var openGroups: List<String>, var contacts: List<Contact>, var displayName: String, var profilePicture: String?, var profileKey: ByteArray): ControlMessage() {
|
||||||
|
|
||||||
class ClosedGroup(val publicKey: String, val name: String, val encryptionKeyPair: ECKeyPair, val members: List<String>, val admins: List<String>) {
|
class ClosedGroup(var publicKey: String, var name: String, var encryptionKeyPair: ECKeyPair?, var members: List<String>, var admins: List<String>) {
|
||||||
val isValid: Boolean get() = members.isNotEmpty() && admins.isNotEmpty()
|
val isValid: Boolean get() = members.isNotEmpty() && admins.isNotEmpty()
|
||||||
|
|
||||||
|
internal constructor(): this("", "", null, listOf(), listOf())
|
||||||
|
|
||||||
override fun toString(): String {
|
override fun toString(): String {
|
||||||
return name
|
return name
|
||||||
}
|
}
|
||||||
@ -42,8 +44,8 @@ class ConfigurationMessage(val closedGroups: List<ClosedGroup>, val openGroups:
|
|||||||
result.publicKey = ByteString.copyFrom(Hex.fromStringCondensed(publicKey))
|
result.publicKey = ByteString.copyFrom(Hex.fromStringCondensed(publicKey))
|
||||||
result.name = name
|
result.name = name
|
||||||
val encryptionKeyPairAsProto = SignalServiceProtos.KeyPair.newBuilder()
|
val encryptionKeyPairAsProto = SignalServiceProtos.KeyPair.newBuilder()
|
||||||
encryptionKeyPairAsProto.publicKey = ByteString.copyFrom(encryptionKeyPair.publicKey.serialize().removing05PrefixIfNeeded())
|
encryptionKeyPairAsProto.publicKey = ByteString.copyFrom(encryptionKeyPair!!.publicKey.serialize().removing05PrefixIfNeeded())
|
||||||
encryptionKeyPairAsProto.privateKey = ByteString.copyFrom(encryptionKeyPair.privateKey.serialize())
|
encryptionKeyPairAsProto.privateKey = ByteString.copyFrom(encryptionKeyPair!!.privateKey.serialize())
|
||||||
result.encryptionKeyPair = encryptionKeyPairAsProto.build()
|
result.encryptionKeyPair = encryptionKeyPairAsProto.build()
|
||||||
result.addAllMembers(members.map { ByteString.copyFrom(Hex.fromStringCondensed(it)) })
|
result.addAllMembers(members.map { ByteString.copyFrom(Hex.fromStringCondensed(it)) })
|
||||||
result.addAllAdmins(admins.map { ByteString.copyFrom(Hex.fromStringCondensed(it)) })
|
result.addAllAdmins(admins.map { ByteString.copyFrom(Hex.fromStringCondensed(it)) })
|
||||||
@ -51,7 +53,10 @@ class ConfigurationMessage(val closedGroups: List<ClosedGroup>, val openGroups:
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class Contact(val publicKey: String, val name: String, val profilePicture: String?, val profileKey: ByteArray?) {
|
class Contact(var publicKey: String, var name: String, var profilePicture: String?, var profileKey: ByteArray?) {
|
||||||
|
|
||||||
|
internal constructor(): this("", "", null, null)
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
fun fromProto(proto: SignalServiceProtos.ConfigurationMessage.Contact): Contact? {
|
fun fromProto(proto: SignalServiceProtos.ConfigurationMessage.Contact): Contact? {
|
||||||
if (!proto.hasName() || !proto.hasProfileKey()) return null
|
if (!proto.hasName() || !proto.hasProfileKey()) return null
|
||||||
@ -128,6 +133,8 @@ class ConfigurationMessage(val closedGroups: List<ClosedGroup>, val openGroups:
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
internal constructor(): this(listOf(), listOf(), listOf(), "", null, byteArrayOf())
|
||||||
|
|
||||||
override fun toProto(): SignalServiceProtos.Content? {
|
override fun toProto(): SignalServiceProtos.Content? {
|
||||||
val configurationProto = SignalServiceProtos.ConfigurationMessage.newBuilder()
|
val configurationProto = SignalServiceProtos.ConfigurationMessage.newBuilder()
|
||||||
configurationProto.addAllClosedGroups(closedGroups.mapNotNull { it.toProto() })
|
configurationProto.addAllClosedGroups(closedGroups.mapNotNull { it.toProto() })
|
||||||
|
@ -110,7 +110,7 @@ private fun MessageReceiver.handleConfigurationMessage(message: ConfigurationMes
|
|||||||
val allClosedGroupPublicKeys = storage.getAllClosedGroupPublicKeys()
|
val allClosedGroupPublicKeys = storage.getAllClosedGroupPublicKeys()
|
||||||
for (closeGroup in message.closedGroups) {
|
for (closeGroup in message.closedGroups) {
|
||||||
if (allClosedGroupPublicKeys.contains(closeGroup.publicKey)) continue
|
if (allClosedGroupPublicKeys.contains(closeGroup.publicKey)) continue
|
||||||
handleNewClosedGroup(message.sender!!, message.sentTimestamp!!, closeGroup.publicKey, closeGroup.name, closeGroup.encryptionKeyPair, closeGroup.members, closeGroup.admins, message.sentTimestamp!!)
|
handleNewClosedGroup(message.sender!!, message.sentTimestamp!!, closeGroup.publicKey, closeGroup.name, closeGroup.encryptionKeyPair!!, closeGroup.members, closeGroup.admins, message.sentTimestamp!!)
|
||||||
}
|
}
|
||||||
val allOpenGroups = storage.getAllOpenGroups().map { it.value.server }
|
val allOpenGroups = storage.getAllOpenGroups().map { it.value.server }
|
||||||
for (openGroup in message.openGroups) {
|
for (openGroup in message.openGroups) {
|
||||||
@ -222,7 +222,7 @@ private fun MessageReceiver.handleNewClosedGroup(message: ClosedGroupControlMess
|
|||||||
val groupPublicKey = kind.publicKey.toByteArray().toHexString()
|
val groupPublicKey = kind.publicKey.toByteArray().toHexString()
|
||||||
val members = kind.members.map { it.toByteArray().toHexString() }
|
val members = kind.members.map { it.toByteArray().toHexString() }
|
||||||
val admins = kind.admins.map { it.toByteArray().toHexString() }
|
val admins = kind.admins.map { it.toByteArray().toHexString() }
|
||||||
handleNewClosedGroup(message.sender!!, message.sentTimestamp!!, groupPublicKey, kind.name, kind.encryptionKeyPair, members, admins, message.sentTimestamp!!)
|
handleNewClosedGroup(message.sender!!, message.sentTimestamp!!, groupPublicKey, kind.name, kind.encryptionKeyPair!!, members, admins, message.sentTimestamp!!)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Parameter @sender:String is just for inserting incoming info message
|
// Parameter @sender:String is just for inserting incoming info message
|
||||||
|
@ -76,12 +76,6 @@ object MessageSender {
|
|||||||
// Set the timestamp, sender and recipient
|
// Set the timestamp, sender and recipient
|
||||||
message.sentTimestamp ?: run { message.sentTimestamp = System.currentTimeMillis() } /* Visible messages will already have their sent timestamp set */
|
message.sentTimestamp ?: run { message.sentTimestamp = System.currentTimeMillis() } /* Visible messages will already have their sent timestamp set */
|
||||||
message.sender = userPublicKey
|
message.sender = userPublicKey
|
||||||
try {
|
|
||||||
when (destination) {
|
|
||||||
is Destination.Contact -> message.recipient = destination.publicKey
|
|
||||||
is Destination.ClosedGroup -> message.recipient = destination.groupPublicKey
|
|
||||||
is Destination.OpenGroup -> throw preconditionFailure
|
|
||||||
}
|
|
||||||
val isSelfSend = (message.recipient == userPublicKey)
|
val isSelfSend = (message.recipient == userPublicKey)
|
||||||
// Set the failure handler (need it here already for precondition failure handling)
|
// Set the failure handler (need it here already for precondition failure handling)
|
||||||
fun handleFailure(error: Exception) {
|
fun handleFailure(error: Exception) {
|
||||||
@ -91,6 +85,12 @@ object MessageSender {
|
|||||||
}
|
}
|
||||||
deferred.reject(error)
|
deferred.reject(error)
|
||||||
}
|
}
|
||||||
|
try {
|
||||||
|
when (destination) {
|
||||||
|
is Destination.Contact -> message.recipient = destination.publicKey
|
||||||
|
is Destination.ClosedGroup -> message.recipient = destination.groupPublicKey
|
||||||
|
is Destination.OpenGroup -> throw preconditionFailure
|
||||||
|
}
|
||||||
// Validate the message
|
// Validate the message
|
||||||
if (!message.isValid()) { throw Error.InvalidMessage }
|
if (!message.isValid()) { throw Error.InvalidMessage }
|
||||||
// Stop here if this is a self-send, unless it's:
|
// Stop here if this is a self-send, unless it's:
|
||||||
@ -183,15 +183,14 @@ object MessageSender {
|
|||||||
errorCount += 1
|
errorCount += 1
|
||||||
if (errorCount != promiseCount) { return@fail } // Only error out if all promises failed
|
if (errorCount != promiseCount) { return@fail } // Only error out if all promises failed
|
||||||
handleFailure(it)
|
handleFailure(it)
|
||||||
deferred.reject(it)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}.fail {
|
}.fail {
|
||||||
Log.d("Loki", "Couldn't send message due to error: $it.")
|
Log.d("Loki", "Couldn't send message due to error: $it.")
|
||||||
deferred.reject(it)
|
handleFailure(it)
|
||||||
}
|
}
|
||||||
} catch (exception: Exception) {
|
} catch (exception: Exception) {
|
||||||
deferred.reject(exception)
|
handleFailure(exception)
|
||||||
}
|
}
|
||||||
return promise
|
return promise
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user