session-android/libsession/src/main/java/org/session/libsession/messaging/jobs/MessageSendJob.kt

142 lines
5.6 KiB
Kotlin
Raw Normal View History

2020-12-02 06:39:02 +01:00
package org.session.libsession.messaging.jobs
2020-11-25 02:06:41 +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
import org.session.libsession.messaging.jobs.Job.Companion.MAX_BUFFER_SIZE
import org.session.libsession.messaging.messages.Destination
import org.session.libsession.messaging.messages.Message
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
class MessageSendJob(val message: Message, val destination: Destination) : Job {
object AwaitingAttachmentUploadException : Exception("Awaiting attachment upload.")
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-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
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() }
attachmentsToUpload.forEach {
2021-04-26 03:14:45 +02:00
if (MessagingModuleConfiguration.shared.storage.getAttachmentUploadJob(it.attachmentId.rowId) != null) {
// 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!!)
JobQueue.shared.add(job)
}
}
if (attachmentsToUpload.isNotEmpty()) {
this.handleFailure(AwaitingAttachmentUploadException)
return
} // Wait for all attachments to upload before continuing
}
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) }
}
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
}
}
delegate?.handleJobFailed(this, error)
2020-12-02 06:39:02 +01:00
}
2021-01-22 05:19:41 +01:00
override fun serialize(): Data {
val kryo = Kryo()
kryo.isRegistrationRequired = false
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)
output.close()
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)
output.close()
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-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
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)
val kryo = Kryo()
2021-05-12 08:17:25 +02:00
// Message
val messageInput = Input(serializedMessage)
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)
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 08:17:25 +02:00
destinationInput.close()
// Return
2021-01-28 05:24:27 +01:00
return MessageSendJob(message, destination)
}
}
2020-11-25 02:06:41 +01:00
}