mirror of
https://github.com/signalapp/Signal-Android.git
synced 2026-04-24 19:00:26 +01:00
Update to the new attachment upload form libsignal method.
This commit is contained in:
@@ -12,6 +12,9 @@ import org.signal.core.util.Util
|
||||
import org.signal.core.util.concurrent.SignalExecutors
|
||||
import org.signal.core.util.inRoundedDays
|
||||
import org.signal.core.util.logging.Log
|
||||
import org.signal.libsignal.net.RequestResult
|
||||
import org.signal.libsignal.net.RetryLaterException
|
||||
import org.signal.libsignal.net.UploadTooLargeException
|
||||
import org.signal.protos.resumableuploads.ResumableUpload
|
||||
import org.thoughtcrime.securesms.R
|
||||
import org.thoughtcrime.securesms.attachments.Attachment
|
||||
@@ -171,8 +174,15 @@ class AttachmentUploadJob private constructor(
|
||||
try {
|
||||
val existingSpec = uploadSpec?.let { ResumableUploadSpec.from(it) }
|
||||
|
||||
val ciphertextLength = AttachmentCipherStreamUtil.getCiphertextLength(PaddingInputStream.getPaddedSize(databaseAttachment.size))
|
||||
|
||||
val uploadForm = if (existingSpec == null) {
|
||||
SignalNetwork.attachments.getAttachmentV4UploadForm().successOrThrow()
|
||||
when (val result = SignalNetwork.attachments.getAttachmentV4UploadForm(ciphertextLength)) {
|
||||
is RequestResult.Success -> result.result
|
||||
is RequestResult.NonSuccess -> throw result.error
|
||||
is RequestResult.RetryableNetworkError -> throw RetryLaterException(result.retryAfter)
|
||||
is RequestResult.ApplicationError -> throw result.cause
|
||||
}
|
||||
} else {
|
||||
null
|
||||
}
|
||||
@@ -288,8 +298,16 @@ class AttachmentUploadJob private constructor(
|
||||
database.setTransferProgressFailed(attachmentId, databaseAttachment.mmsId)
|
||||
}
|
||||
|
||||
override fun getNextRunAttemptBackoff(pastAttemptCount: Int, exception: java.lang.Exception): Long {
|
||||
if (exception is RetryLaterException && exception.duration != null) {
|
||||
return exception.duration.toMillis()
|
||||
}
|
||||
|
||||
return super.getNextRunAttemptBackoff(pastAttemptCount, exception)
|
||||
}
|
||||
|
||||
override fun onShouldRetry(exception: Exception): Boolean {
|
||||
return exception is IOException && exception !is NotPushRegisteredException
|
||||
return exception is IOException && exception !is NotPushRegisteredException && exception !is UploadTooLargeException
|
||||
}
|
||||
|
||||
@Throws(InvalidAttachmentException::class)
|
||||
|
||||
@@ -261,7 +261,6 @@ public final class JobManagerFactories {
|
||||
put(RemoteDeleteSendJob.KEY, new RemoteDeleteSendJob.Factory());
|
||||
put(ReportSpamJob.KEY, new ReportSpamJob.Factory());
|
||||
put(ResendMessageJob.KEY, new ResendMessageJob.Factory());
|
||||
put(ResumableUploadSpecJob.KEY, new ResumableUploadSpecJob.Factory());
|
||||
put(RequestGroupV2InfoWorkerJob.KEY, new RequestGroupV2InfoWorkerJob.Factory());
|
||||
put(RequestGroupV2InfoJob.KEY, new RequestGroupV2InfoJob.Factory());
|
||||
put(LocalBackupRestoreMediaJob.KEY, new LocalBackupRestoreMediaJob.Factory());
|
||||
@@ -431,6 +430,7 @@ public final class JobManagerFactories {
|
||||
put("BackupRestoreJob", new FailingJob.Factory());
|
||||
put("BackfillDigestsMigrationJob", new PassingMigrationJob.Factory());
|
||||
put("BackfillDigestJob", new FailingJob.Factory());
|
||||
put("ResumableUploadSpecJob", new FailingJob.Factory());
|
||||
}};
|
||||
}
|
||||
|
||||
|
||||
@@ -35,7 +35,9 @@ import org.thoughtcrime.securesms.util.AppForegroundObserver;
|
||||
import org.thoughtcrime.securesms.util.RemoteConfig;
|
||||
import org.thoughtcrime.securesms.util.TextSecurePreferences;
|
||||
import org.whispersystems.signalservice.api.SignalServiceMessageSender;
|
||||
import org.whispersystems.signalservice.api.crypto.AttachmentCipherStreamUtil;
|
||||
import org.whispersystems.signalservice.api.crypto.UntrustedIdentityException;
|
||||
import org.whispersystems.signalservice.internal.crypto.PaddingInputStream;
|
||||
import org.whispersystems.signalservice.api.messages.SignalServiceAttachment;
|
||||
import org.whispersystems.signalservice.api.messages.SignalServiceAttachmentStream;
|
||||
import org.whispersystems.signalservice.api.messages.multidevice.ContactsMessage;
|
||||
@@ -288,7 +290,7 @@ public class MultiDeviceContactUpdateJob extends BaseJob {
|
||||
.withStream(stream)
|
||||
.withContentType("application/octet-stream")
|
||||
.withLength(length)
|
||||
.withResumableUploadSpec(messageSender.getResumableUploadSpec());
|
||||
.withResumableUploadSpec(messageSender.getResumableUploadSpec(AttachmentCipherStreamUtil.getCiphertextLength(PaddingInputStream.getPaddedSize(length))));
|
||||
|
||||
messageSender.sendSyncMessage(SignalServiceSyncMessage.forContacts(new ContactsMessage(attachmentStream.build(), complete))
|
||||
);
|
||||
|
||||
@@ -17,7 +17,9 @@ import org.thoughtcrime.securesms.net.NotPushRegisteredException;
|
||||
import org.thoughtcrime.securesms.recipients.Recipient;
|
||||
import org.thoughtcrime.securesms.util.RemoteConfig;
|
||||
import org.whispersystems.signalservice.api.SignalServiceMessageSender;
|
||||
import org.whispersystems.signalservice.api.crypto.AttachmentCipherStreamUtil;
|
||||
import org.whispersystems.signalservice.api.crypto.UntrustedIdentityException;
|
||||
import org.whispersystems.signalservice.internal.crypto.PaddingInputStream;
|
||||
import org.whispersystems.signalservice.api.messages.SignalServiceAttachment;
|
||||
import org.whispersystems.signalservice.api.messages.SignalServiceAttachmentStream;
|
||||
import org.whispersystems.signalservice.api.messages.multidevice.ContactsMessage;
|
||||
@@ -26,6 +28,7 @@ import org.whispersystems.signalservice.api.messages.multidevice.DeviceContactsO
|
||||
import org.whispersystems.signalservice.api.messages.multidevice.SignalServiceSyncMessage;
|
||||
import org.whispersystems.signalservice.api.push.exceptions.PushNetworkException;
|
||||
import org.whispersystems.signalservice.api.push.exceptions.ServerRejectedException;
|
||||
import org.whispersystems.signalservice.internal.push.http.ResumableUploadSpec;
|
||||
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.ByteArrayOutputStream;
|
||||
@@ -88,11 +91,14 @@ public class MultiDeviceProfileKeyUpdateJob extends BaseJob {
|
||||
out.close();
|
||||
|
||||
SignalServiceMessageSender messageSender = AppDependencies.getSignalServiceMessageSender();
|
||||
long dataLength = baos.toByteArray().length;
|
||||
long ciphertextLength = AttachmentCipherStreamUtil.getCiphertextLength(PaddingInputStream.getPaddedSize(dataLength));
|
||||
ResumableUploadSpec uploadSpec = messageSender.getResumableUploadSpec(ciphertextLength);
|
||||
SignalServiceAttachmentStream attachmentStream = SignalServiceAttachment.newStreamBuilder()
|
||||
.withStream(new ByteArrayInputStream(baos.toByteArray()))
|
||||
.withContentType("application/octet-stream")
|
||||
.withLength(baos.toByteArray().length)
|
||||
.withResumableUploadSpec(messageSender.getResumableUploadSpec())
|
||||
.withLength(dataLength)
|
||||
.withResumableUploadSpec(uploadSpec)
|
||||
.build();
|
||||
|
||||
SignalServiceSyncMessage syncMessage = SignalServiceSyncMessage.forContacts(new ContactsMessage(attachmentStream, false));
|
||||
|
||||
@@ -60,7 +60,9 @@ import org.thoughtcrime.securesms.recipients.RecipientUtil;
|
||||
import org.thoughtcrime.securesms.transport.RetryLaterException;
|
||||
import org.thoughtcrime.securesms.transport.UndeliverableMessageException;
|
||||
import org.thoughtcrime.securesms.util.MediaUtil;
|
||||
import org.whispersystems.signalservice.api.crypto.AttachmentCipherStreamUtil;
|
||||
import org.whispersystems.signalservice.api.messages.AttachmentTransferProgress;
|
||||
import org.whispersystems.signalservice.internal.crypto.PaddingInputStream;
|
||||
import org.whispersystems.signalservice.api.messages.SignalServiceAttachment;
|
||||
import org.whispersystems.signalservice.api.messages.SignalServiceAttachmentPointer;
|
||||
import org.whispersystems.signalservice.api.messages.SignalServiceAttachmentRemoteId;
|
||||
@@ -70,6 +72,7 @@ import org.whispersystems.signalservice.api.messages.shared.SharedContact;
|
||||
import org.whispersystems.signalservice.api.push.exceptions.ProofRequiredException;
|
||||
import org.whispersystems.signalservice.api.push.exceptions.ServerRejectedException;
|
||||
import org.whispersystems.signalservice.internal.push.BodyRange;
|
||||
import org.whispersystems.signalservice.internal.push.http.ResumableUploadSpec;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
@@ -171,9 +174,12 @@ public abstract class PushSendJob extends SendJob {
|
||||
|
||||
try {
|
||||
if (attachment.getUri() == null || attachment.size == 0) throw new IOException("Assertion failed, outgoing attachment has no data!");
|
||||
InputStream is = PartAuthority.getAttachmentStream(context, attachment.getUri());
|
||||
InputStream inputStream = PartAuthority.getAttachmentStream(context, attachment.getUri());
|
||||
long ciphertextLength = AttachmentCipherStreamUtil.getCiphertextLength(PaddingInputStream.getPaddedSize(attachment.size));
|
||||
ResumableUploadSpec uploadSpec = AppDependencies.getSignalServiceMessageSender().getResumableUploadSpec(ciphertextLength);
|
||||
|
||||
return SignalServiceAttachment.newStreamBuilder()
|
||||
.withStream(is)
|
||||
.withStream(inputStream)
|
||||
.withContentType(attachment.contentType)
|
||||
.withLength(attachment.size)
|
||||
.withFileName(attachment.fileName)
|
||||
@@ -185,7 +191,7 @@ public abstract class PushSendJob extends SendJob {
|
||||
.withHeight(attachment.height)
|
||||
.withCaption(attachment.caption)
|
||||
.withUuid(attachment.uuid)
|
||||
.withResumableUploadSpec(AppDependencies.getSignalServiceMessageSender().getResumableUploadSpec())
|
||||
.withResumableUploadSpec(uploadSpec)
|
||||
.withListener(new SignalServiceAttachment.ProgressListener() {
|
||||
@Override
|
||||
public void onAttachmentProgress(@NonNull AttachmentTransferProgress progress) {
|
||||
|
||||
@@ -1,67 +0,0 @@
|
||||
package org.thoughtcrime.securesms.jobs;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
|
||||
import org.signal.core.util.logging.Log;
|
||||
import org.thoughtcrime.securesms.dependencies.AppDependencies;
|
||||
import org.thoughtcrime.securesms.jobmanager.JsonJobData;
|
||||
import org.thoughtcrime.securesms.jobmanager.Job;
|
||||
import org.whispersystems.signalservice.internal.push.http.ResumableUploadSpec;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
/**
|
||||
* No longer used. Functionality has been merged into {@link AttachmentUploadJob}.
|
||||
*/
|
||||
@Deprecated
|
||||
public class ResumableUploadSpecJob extends BaseJob {
|
||||
|
||||
private static final String TAG = Log.tag(ResumableUploadSpecJob.class);
|
||||
|
||||
static final String KEY_RESUME_SPEC = "resume_spec";
|
||||
|
||||
public static final String KEY = "ResumableUploadSpecJob";
|
||||
|
||||
private ResumableUploadSpecJob(@NonNull Parameters parameters) {
|
||||
super(parameters);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onRun() throws Exception {
|
||||
ResumableUploadSpec resumableUploadSpec = AppDependencies.getSignalServiceMessageSender()
|
||||
.getResumableUploadSpec();
|
||||
|
||||
setOutputData(new JsonJobData.Builder()
|
||||
.putString(KEY_RESUME_SPEC, resumableUploadSpec.serialize())
|
||||
.serialize());
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean onShouldRetry(@NonNull Exception e) {
|
||||
return e instanceof IOException;
|
||||
}
|
||||
|
||||
@Override
|
||||
public @Nullable byte[] serialize() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NonNull String getFactoryKey() {
|
||||
return KEY;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onFailure() {
|
||||
|
||||
}
|
||||
|
||||
public static class Factory implements Job.Factory<ResumableUploadSpecJob> {
|
||||
|
||||
@Override
|
||||
public @NonNull ResumableUploadSpecJob create(@NonNull Parameters parameters, @Nullable byte[] serializedData) {
|
||||
return new ResumableUploadSpecJob(parameters);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -10,6 +10,7 @@ import org.signal.core.util.logging.logD
|
||||
import org.signal.core.util.logging.logI
|
||||
import org.signal.core.util.logging.logW
|
||||
import org.signal.core.util.toByteArray
|
||||
import org.signal.libsignal.net.RequestResult
|
||||
import org.signal.libsignal.protocol.InvalidKeyException
|
||||
import org.signal.libsignal.protocol.ecc.ECPublicKey
|
||||
import org.thoughtcrime.securesms.attachments.AttachmentUploadUtil
|
||||
@@ -337,11 +338,11 @@ object LinkDeviceRepository {
|
||||
}
|
||||
|
||||
Log.d(TAG, "[createAndUploadArchive] Fetching an upload form...")
|
||||
val uploadForm = when (val result = NetworkResult.withRetry { SignalNetwork.attachments.getAttachmentV4UploadForm() }) {
|
||||
is NetworkResult.Success -> result.result.logD(TAG, "[createAndUploadArchive] Successfully retrieved upload form.")
|
||||
is NetworkResult.ApplicationError -> throw result.throwable
|
||||
is NetworkResult.NetworkError -> return LinkUploadArchiveResult.NetworkError(result.exception).logW(TAG, "[createAndUploadArchive] Network error when fetching form.", result.exception)
|
||||
is NetworkResult.StatusCodeError -> return LinkUploadArchiveResult.NetworkError(result.exception).logW(TAG, "[createAndUploadArchive] Status code error when fetching form.", result.exception)
|
||||
val uploadForm = when (val result = SignalNetwork.attachments.getAttachmentV4UploadForm(tempBackupFile.length())) {
|
||||
is RequestResult.Success -> result.result.logD(TAG, "[createAndUploadArchive] Successfully retrieved upload form.")
|
||||
is RequestResult.ApplicationError -> throw result.cause
|
||||
is RequestResult.RetryableNetworkError -> return LinkUploadArchiveResult.NetworkError(result.networkError).logW(TAG, "[createAndUploadArchive] Network error when fetching form.", result.networkError)
|
||||
is RequestResult.NonSuccess -> return LinkUploadArchiveResult.BadRequest(result.error).logW(TAG, "[createAndUploadArchive] Upload too large when fetching form.", result.error)
|
||||
}
|
||||
|
||||
if (cancellationSignal()) {
|
||||
|
||||
Reference in New Issue
Block a user