Stop sending media in an infinite loop in case of error (part of #587)

Not sure how this commit fix it, but the issue is not observed anymore with it
This commit is contained in:
Benoit Marty 2019-09-25 14:09:26 +02:00
parent f3039601bf
commit f077cc8467
4 changed files with 77 additions and 83 deletions

View file

@ -17,7 +17,6 @@
package im.vector.matrix.android.internal.crypto.attachments
import android.util.Base64
import arrow.core.Try
import im.vector.matrix.android.internal.crypto.model.rest.EncryptedFileInfo
import im.vector.matrix.android.internal.crypto.model.rest.EncryptedFileKey
import timber.log.Timber
@ -50,7 +49,7 @@ object MXEncryptedAttachments {
* @param mimetype the mime type
* @return the encryption file info
*/
fun encryptAttachment(attachmentStream: InputStream, mimetype: String): Try<EncryptionResult> {
fun encryptAttachment(attachmentStream: InputStream, mimetype: String): EncryptionResult {
val t0 = System.currentTimeMillis()
val secureRandom = SecureRandom()
@ -70,7 +69,7 @@ object MXEncryptedAttachments {
val outStream = ByteArrayOutputStream()
try {
outStream.use {
val encryptCipher = Cipher.getInstance(CIPHER_ALGORITHM)
val secretKeySpec = SecretKeySpec(key, SECRET_KEY_SPEC_ALGORITHM)
val ivParameterSpec = IvParameterSpec(initVectorBytes)
@ -114,19 +113,7 @@ object MXEncryptedAttachments {
)
Timber.v("Encrypt in ${System.currentTimeMillis() - t0} ms")
return Try.just(result)
} catch (oom: OutOfMemoryError) {
Timber.e(oom, "## encryptAttachment failed")
return Try.Failure(oom)
} catch (e: Exception) {
Timber.e(e, "## encryptAttachment failed")
return Try.Failure(e)
} finally {
try {
outStream.close()
} catch (e: Exception) {
Timber.e(e, "## encryptAttachment() : fail to close outStream")
}
return result
}
}

View file

@ -30,6 +30,7 @@ import retrofit2.Call
import retrofit2.Callback
import retrofit2.Response
import timber.log.Timber
import java.io.IOException
import kotlin.coroutines.resume
import kotlin.coroutines.resumeWithException
@ -50,6 +51,24 @@ internal suspend fun <T> Call<T>.awaitResponse(): Response<T> {
}
}
internal suspend fun okhttp3.Call.awaitResponse(): okhttp3.Response {
return suspendCancellableCoroutine { continuation ->
continuation.invokeOnCancellation {
cancel()
}
enqueue(object : okhttp3.Callback {
override fun onResponse(call: okhttp3.Call, response: okhttp3.Response) {
continuation.resume(response)
}
override fun onFailure(call: okhttp3.Call, e: IOException) {
continuation.resumeWithException(e)
}
})
}
}
/**
* Convert a retrofit Response to a Failure, and eventually parse errorBody to convert it to a MatrixError
*/

View file

@ -16,12 +16,11 @@
package im.vector.matrix.android.internal.session.content
import arrow.core.Try
import arrow.core.Try.Companion.raise
import com.squareup.moshi.Moshi
import im.vector.matrix.android.api.auth.data.SessionParams
import im.vector.matrix.android.internal.di.Authenticated
import im.vector.matrix.android.internal.network.ProgressRequestBody
import im.vector.matrix.android.internal.network.awaitResponse
import im.vector.matrix.android.internal.network.toFailure
import okhttp3.*
import java.io.File
@ -38,28 +37,26 @@ internal class FileUploader @Inject constructor(@Authenticated
private val responseAdapter = moshi.adapter(ContentUploadResponse::class.java)
fun uploadFile(file: File,
filename: String?,
mimeType: String,
progressListener: ProgressRequestBody.Listener? = null): Try<ContentUploadResponse> {
suspend fun uploadFile(file: File,
filename: String?,
mimeType: String,
progressListener: ProgressRequestBody.Listener? = null): ContentUploadResponse {
val uploadBody = RequestBody.create(MediaType.parse(mimeType), file)
return upload(uploadBody, filename, progressListener)
}
fun uploadByteArray(byteArray: ByteArray,
filename: String?,
mimeType: String,
progressListener: ProgressRequestBody.Listener? = null): Try<ContentUploadResponse> {
suspend fun uploadByteArray(byteArray: ByteArray,
filename: String?,
mimeType: String,
progressListener: ProgressRequestBody.Listener? = null): ContentUploadResponse {
val uploadBody = RequestBody.create(MediaType.parse(mimeType), byteArray)
return upload(uploadBody, filename, progressListener)
}
private fun upload(uploadBody: RequestBody, filename: String?, progressListener: ProgressRequestBody.Listener?): Try<ContentUploadResponse> {
val urlBuilder = HttpUrl.parse(uploadUrl)?.newBuilder() ?: return raise(RuntimeException())
private suspend fun upload(uploadBody: RequestBody, filename: String?, progressListener: ProgressRequestBody.Listener?): ContentUploadResponse {
val urlBuilder = HttpUrl.parse(uploadUrl)?.newBuilder() ?: throw RuntimeException()
val httpUrl = urlBuilder
.addQueryParameter("filename", filename)
@ -72,19 +69,15 @@ internal class FileUploader @Inject constructor(@Authenticated
.post(requestBody)
.build()
return Try {
okHttpClient.newCall(request).execute().use { response ->
if (!response.isSuccessful) {
throw response.toFailure()
} else {
response.body()?.source()?.let {
responseAdapter.fromJson(it)
}
?: throw IOException()
return okHttpClient.newCall(request).awaitResponse().use { response ->
if (!response.isSuccessful) {
throw response.toFailure()
} else {
response.body()?.source()?.let {
responseAdapter.fromJson(it)
}
?: throw IOException()
}
}
}
}

View file

@ -93,32 +93,28 @@ internal class UploadContentWorker(context: Context, params: WorkerParameters) :
}
}
val contentUploadResponse = if (params.isRoomEncrypted) {
Timber.v("Encrypt thumbnail")
contentUploadStateTracker.setEncryptingThumbnail(eventId)
MXEncryptedAttachments.encryptAttachment(ByteArrayInputStream(thumbnailData.bytes), thumbnailData.mimeType)
.flatMap { encryptionResult ->
uploadedThumbnailEncryptedFileInfo = encryptionResult.encryptedFileInfo
try {
val contentUploadResponse = if (params.isRoomEncrypted) {
Timber.v("Encrypt thumbnail")
contentUploadStateTracker.setEncryptingThumbnail(eventId)
val encryptionResult = MXEncryptedAttachments.encryptAttachment(ByteArrayInputStream(thumbnailData.bytes), thumbnailData.mimeType)
uploadedThumbnailEncryptedFileInfo = encryptionResult.encryptedFileInfo
fileUploader.uploadByteArray(encryptionResult.encryptedByteArray,
"thumb_${attachment.name}",
"application/octet-stream",
thumbnailProgressListener)
} else {
fileUploader.uploadByteArray(thumbnailData.bytes,
"thumb_${attachment.name}",
thumbnailData.mimeType,
thumbnailProgressListener)
}
fileUploader
.uploadByteArray(encryptionResult.encryptedByteArray,
"thumb_${attachment.name}",
"application/octet-stream",
thumbnailProgressListener)
}
} else {
fileUploader
.uploadByteArray(thumbnailData.bytes,
"thumb_${attachment.name}",
thumbnailData.mimeType,
thumbnailProgressListener)
uploadedThumbnailUrl = contentUploadResponse.contentUri
} catch (t: Throwable) {
Timber.e(t)
return handleFailure(params, t)
}
contentUploadResponse
.fold(
{ Timber.e(it) },
{ uploadedThumbnailUrl = it.contentUri }
)
}
val progressListener = object : ProgressRequestBody.Listener {
@ -133,27 +129,26 @@ internal class UploadContentWorker(context: Context, params: WorkerParameters) :
var uploadedFileEncryptedFileInfo: EncryptedFileInfo? = null
val contentUploadResponse = if (params.isRoomEncrypted) {
Timber.v("Encrypt file")
contentUploadStateTracker.setEncrypting(eventId)
return try {
val contentUploadResponse = if (params.isRoomEncrypted) {
Timber.v("Encrypt file")
contentUploadStateTracker.setEncrypting(eventId)
MXEncryptedAttachments.encryptAttachment(FileInputStream(attachmentFile), attachment.mimeType)
.flatMap { encryptionResult ->
uploadedFileEncryptedFileInfo = encryptionResult.encryptedFileInfo
val encryptionResult = MXEncryptedAttachments.encryptAttachment(FileInputStream(attachmentFile), attachment.mimeType)
uploadedFileEncryptedFileInfo = encryptionResult.encryptedFileInfo
fileUploader
.uploadByteArray(encryptionResult.encryptedByteArray, attachment.name, "application/octet-stream", progressListener)
}
} else {
fileUploader
.uploadFile(attachmentFile, attachment.name, attachment.mimeType, progressListener)
fileUploader
.uploadByteArray(encryptionResult.encryptedByteArray, attachment.name, "application/octet-stream", progressListener)
} else {
fileUploader
.uploadFile(attachmentFile, attachment.name, attachment.mimeType, progressListener)
}
handleSuccess(params, contentUploadResponse.contentUri, uploadedFileEncryptedFileInfo, uploadedThumbnailUrl, uploadedThumbnailEncryptedFileInfo)
} catch (t: Throwable) {
Timber.e(t)
handleFailure(params, t)
}
return contentUploadResponse
.fold(
{ handleFailure(params, it) },
{ handleSuccess(params, it.contentUri, uploadedFileEncryptedFileInfo, uploadedThumbnailUrl, uploadedThumbnailEncryptedFileInfo) }
)
}
private fun handleFailure(params: Params, failure: Throwable): Result {