2020-12-02 06:39:02 +01:00
|
|
|
package org.session.libsession.messaging.jobs
|
2020-11-25 02:06:41 +01:00
|
|
|
|
2021-01-22 03:30:00 +01:00
|
|
|
import com.esotericsoftware.kryo.Kryo
|
|
|
|
import com.esotericsoftware.kryo.io.Input
|
|
|
|
import com.esotericsoftware.kryo.io.Output
|
2021-04-26 03:14:45 +02:00
|
|
|
import org.session.libsession.messaging.MessagingModuleConfiguration
|
2021-05-12 02:43:17 +02:00
|
|
|
import org.session.libsession.messaging.jobs.Job.Companion.MAX_BUFFER_SIZE
|
2020-12-07 05:22:02 +01:00
|
|
|
import org.session.libsession.messaging.messages.Destination
|
|
|
|
import org.session.libsession.messaging.messages.Message
|
2020-12-15 05:50:15 +01:00
|
|
|
import org.session.libsession.messaging.messages.visible.VisibleMessage
|
|
|
|
import org.session.libsession.messaging.sending_receiving.MessageSender
|
2021-02-03 02:22:40 +01:00
|
|
|
import org.session.libsignal.utilities.logging.Log
|
2020-12-07 05:22:02 +01:00
|
|
|
|
|
|
|
class MessageSendJob(val message: Message, val destination: Destination) : Job {
|
2021-05-12 08:48:18 +02:00
|
|
|
|
2021-05-13 01:38:39 +02:00
|
|
|
object AwaitingAttachmentUploadException : Exception("Awaiting attachment upload.")
|
2021-05-12 08:48:18 +02:00
|
|
|
|
2020-12-02 06:39:02 +01:00
|
|
|
override var delegate: JobDelegate? = null
|
|
|
|
override var id: String? = null
|
|
|
|
override var failureCount: Int = 0
|
|
|
|
|
|
|
|
override val maxFailureCount: Int = 10
|
2021-05-12 08:17:25 +02:00
|
|
|
|
2020-12-02 06:39:02 +01:00
|
|
|
companion object {
|
2021-03-02 02:24:09 +01:00
|
|
|
val TAG = MessageSendJob::class.simpleName
|
2021-01-28 05:24:27 +01:00
|
|
|
val KEY: String = "MessageSendJob"
|
2021-01-22 03:30:00 +01:00
|
|
|
|
2021-04-26 02:58:48 +02:00
|
|
|
// Keys used for database storage
|
2021-05-12 08:17:25 +02:00
|
|
|
private val MESSAGE_KEY = "message"
|
|
|
|
private val DESTINATION_KEY = "destination"
|
2020-12-02 06:39:02 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
override fun execute() {
|
2021-04-26 03:14:45 +02:00
|
|
|
val messageDataProvider = MessagingModuleConfiguration.shared.messageDataProvider
|
2020-12-15 05:50:15 +01:00
|
|
|
val message = message as? VisibleMessage
|
2021-05-12 08:17:25 +02:00
|
|
|
if (message != null) {
|
|
|
|
if (!messageDataProvider.isOutgoingMessage(message.sentTimestamp!!)) return // The message has been deleted
|
2021-03-09 00:50:02 +01:00
|
|
|
val attachmentIDs = mutableListOf<Long>()
|
|
|
|
attachmentIDs.addAll(message.attachmentIDs)
|
|
|
|
message.quote?.let { it.attachmentID?.let { attachmentID -> attachmentIDs.add(attachmentID) } }
|
|
|
|
message.linkPreview?.let { it.attachmentID?.let { attachmentID -> attachmentIDs.add(attachmentID) } }
|
|
|
|
val attachments = attachmentIDs.mapNotNull { messageDataProvider.getDatabaseAttachment(it) }
|
2021-03-02 07:22:56 +01:00
|
|
|
val attachmentsToUpload = attachments.filter { it.url.isNullOrEmpty() }
|
2020-12-15 05:50:15 +01:00
|
|
|
attachmentsToUpload.forEach {
|
2021-04-26 03:14:45 +02:00
|
|
|
if (MessagingModuleConfiguration.shared.storage.getAttachmentUploadJob(it.attachmentId.rowId) != null) {
|
2020-12-15 05:50:15 +01:00
|
|
|
// Wait for it to finish
|
|
|
|
} else {
|
2021-03-02 07:22:56 +01:00
|
|
|
val job = AttachmentUploadJob(it.attachmentId.rowId, message.threadID!!.toString(), message, id!!)
|
2020-12-15 05:50:15 +01:00
|
|
|
JobQueue.shared.add(job)
|
|
|
|
}
|
|
|
|
}
|
2021-05-12 08:48:18 +02:00
|
|
|
if (attachmentsToUpload.isNotEmpty()) {
|
2021-05-13 01:38:39 +02:00
|
|
|
this.handleFailure(AwaitingAttachmentUploadException)
|
2021-05-12 08:48:18 +02:00
|
|
|
return
|
|
|
|
} // Wait for all attachments to upload before continuing
|
2020-12-15 05:50:15 +01:00
|
|
|
}
|
|
|
|
MessageSender.send(this.message, this.destination).success {
|
|
|
|
this.handleSuccess()
|
|
|
|
}.fail { exception ->
|
|
|
|
Log.e(TAG, "Couldn't send message due to error: $exception.")
|
2021-05-12 08:17:25 +02:00
|
|
|
if (exception is MessageSender.Error) {
|
|
|
|
if (!exception.isRetryable) { this.handlePermanentFailure(exception) }
|
2020-12-15 05:50:15 +01:00
|
|
|
}
|
|
|
|
this.handleFailure(exception)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
private fun handleSuccess() {
|
|
|
|
delegate?.handleJobSucceeded(this)
|
|
|
|
}
|
|
|
|
|
|
|
|
private fun handlePermanentFailure(error: Exception) {
|
|
|
|
delegate?.handleJobFailedPermanently(this, error)
|
|
|
|
}
|
|
|
|
|
|
|
|
private fun handleFailure(error: Exception) {
|
|
|
|
Log.w(TAG, "Failed to send $message::class.simpleName.")
|
|
|
|
val message = message as? VisibleMessage
|
2021-05-12 08:17:25 +02:00
|
|
|
if (message != null) {
|
|
|
|
if (!MessagingModuleConfiguration.shared.messageDataProvider.isOutgoingMessage(message.sentTimestamp!!)) {
|
|
|
|
return // The message has been deleted
|
|
|
|
}
|
2020-12-15 05:50:15 +01:00
|
|
|
}
|
|
|
|
delegate?.handleJobFailed(this, error)
|
2020-12-02 06:39:02 +01:00
|
|
|
}
|
2021-01-22 03:30:00 +01:00
|
|
|
|
2021-01-22 05:19:41 +01:00
|
|
|
override fun serialize(): Data {
|
2021-01-22 03:30:00 +01:00
|
|
|
val kryo = Kryo()
|
|
|
|
kryo.isRegistrationRequired = false
|
2021-05-12 02:43:17 +02:00
|
|
|
val output = Output(ByteArray(4096), MAX_BUFFER_SIZE)
|
2021-05-12 08:17:25 +02:00
|
|
|
// Message
|
2021-03-03 05:14:45 +01:00
|
|
|
kryo.writeClassAndObject(output, message)
|
2021-01-22 03:30:00 +01:00
|
|
|
output.close()
|
2021-03-17 03:55:30 +01:00
|
|
|
val serializedMessage = output.toBytes()
|
|
|
|
output.clear()
|
2021-05-12 08:17:25 +02:00
|
|
|
// Destination
|
2021-03-03 05:14:45 +01:00
|
|
|
kryo.writeClassAndObject(output, destination)
|
2021-01-22 03:30:00 +01:00
|
|
|
output.close()
|
2021-03-17 03:55:30 +01:00
|
|
|
val serializedDestination = output.toBytes()
|
2021-05-12 08:17:25 +02:00
|
|
|
output.clear()
|
|
|
|
// Serialize
|
|
|
|
return Data.Builder()
|
|
|
|
.putByteArray(MESSAGE_KEY, serializedMessage)
|
|
|
|
.putByteArray(DESTINATION_KEY, serializedDestination)
|
|
|
|
.build()
|
2021-01-22 03:30:00 +01:00
|
|
|
}
|
|
|
|
|
2021-01-28 05:24:27 +01:00
|
|
|
override fun getFactoryKey(): String {
|
2021-03-03 05:14:45 +01:00
|
|
|
return KEY
|
2021-01-28 05:24:27 +01:00
|
|
|
}
|
|
|
|
|
2021-05-12 08:17:25 +02:00
|
|
|
class Factory : Job.Factory<MessageSendJob> {
|
2021-04-26 02:58:48 +02:00
|
|
|
|
2021-05-12 08:21:53 +02:00
|
|
|
override fun create(data: Data): MessageSendJob? {
|
2021-05-12 08:17:25 +02:00
|
|
|
val serializedMessage = data.getByteArray(MESSAGE_KEY)
|
|
|
|
val serializedDestination = data.getByteArray(DESTINATION_KEY)
|
2021-01-22 03:30:00 +01:00
|
|
|
val kryo = Kryo()
|
2021-05-12 08:17:25 +02:00
|
|
|
// Message
|
|
|
|
val messageInput = Input(serializedMessage)
|
2021-05-12 08:21:53 +02:00
|
|
|
val message: Message
|
|
|
|
try {
|
|
|
|
message = kryo.readClassAndObject(messageInput) as Message
|
|
|
|
} catch (e: Exception) {
|
|
|
|
Log.e("Loki", "Couldn't deserialize message send job.", e)
|
|
|
|
return null
|
|
|
|
}
|
2021-05-12 08:17:25 +02:00
|
|
|
messageInput.close()
|
|
|
|
// Destination
|
|
|
|
val destinationInput = Input(serializedDestination)
|
2021-05-12 08:21:53 +02:00
|
|
|
val destination: Destination
|
|
|
|
try {
|
|
|
|
destination = kryo.readClassAndObject(destinationInput) as Destination
|
|
|
|
} catch (e: Exception) {
|
|
|
|
Log.e("Loki", "Couldn't deserialize message send job.", e)
|
|
|
|
return null
|
2021-05-12 02:43:17 +02:00
|
|
|
}
|
2021-05-12 08:17:25 +02:00
|
|
|
destinationInput.close()
|
|
|
|
// Return
|
2021-01-28 05:24:27 +01:00
|
|
|
return MessageSendJob(message, destination)
|
2021-01-22 03:30:00 +01:00
|
|
|
}
|
|
|
|
}
|
2020-11-25 02:06:41 +01:00
|
|
|
}
|