Search in sources :

Example 6 with AttachmentDatabase

use of org.thoughtcrime.securesms.database.AttachmentDatabase in project Signal-Android by WhisperSystems.

the class AttachmentDownloadJob method retrieveAttachment.

private void retrieveAttachment(long messageId, final AttachmentId attachmentId, final Attachment attachment) throws IOException, RetryLaterException {
    AttachmentDatabase database = SignalDatabase.attachments();
    File attachmentFile = database.getOrCreateTransferFile(attachmentId);
    try {
        SignalServiceMessageReceiver messageReceiver = ApplicationDependencies.getSignalServiceMessageReceiver();
        SignalServiceAttachmentPointer pointer = createAttachmentPointer(attachment);
        InputStream stream = messageReceiver.retrieveAttachment(pointer, attachmentFile, MAX_ATTACHMENT_SIZE, (total, progress) -> EventBus.getDefault().postSticky(new PartProgressEvent(attachment, PartProgressEvent.Type.NETWORK, total, progress)));
        database.insertAttachmentsForPlaceholder(messageId, attachmentId, stream);
    } catch (RangeException e) {
        Log.w(TAG, "Range exception, file size " + attachmentFile.length(), e);
        if (attachmentFile.delete()) {
            Log.i(TAG, "Deleted temp download file to recover");
            throw new RetryLaterException(e);
        } else {
            throw new IOException("Failed to delete temp download file following range exception");
        }
    } catch (InvalidPartException | NonSuccessfulResponseCodeException | InvalidMessageException | MmsException | MissingConfigurationException e) {
        Log.w(TAG, "Experienced exception while trying to download an attachment.", e);
        markFailed(messageId, attachmentId);
    }
}
Also used : InvalidMessageException(org.whispersystems.libsignal.InvalidMessageException) InputStream(java.io.InputStream) SignalServiceAttachmentPointer(org.whispersystems.signalservice.api.messages.SignalServiceAttachmentPointer) NonSuccessfulResponseCodeException(org.whispersystems.signalservice.api.push.exceptions.NonSuccessfulResponseCodeException) PartProgressEvent(org.thoughtcrime.securesms.events.PartProgressEvent) IOException(java.io.IOException) AttachmentDatabase(org.thoughtcrime.securesms.database.AttachmentDatabase) MmsException(org.thoughtcrime.securesms.mms.MmsException) MissingConfigurationException(org.whispersystems.signalservice.api.push.exceptions.MissingConfigurationException) SignalServiceMessageReceiver(org.whispersystems.signalservice.api.SignalServiceMessageReceiver) RangeException(org.whispersystems.signalservice.api.push.exceptions.RangeException) RetryLaterException(org.thoughtcrime.securesms.transport.RetryLaterException) File(java.io.File)

Example 7 with AttachmentDatabase

use of org.thoughtcrime.securesms.database.AttachmentDatabase in project Signal-Android by WhisperSystems.

the class AttachmentMarkUploadedJob method onRun.

@Override
public void onRun() throws Exception {
    AttachmentDatabase database = SignalDatabase.attachments();
    DatabaseAttachment databaseAttachment = database.getAttachment(attachmentId);
    if (databaseAttachment == null) {
        throw new InvalidAttachmentException("Cannot find the specified attachment.");
    }
    database.markAttachmentUploaded(messageId, databaseAttachment);
}
Also used : DatabaseAttachment(org.thoughtcrime.securesms.attachments.DatabaseAttachment) AttachmentDatabase(org.thoughtcrime.securesms.database.AttachmentDatabase)

Example 8 with AttachmentDatabase

use of org.thoughtcrime.securesms.database.AttachmentDatabase in project Signal-Android by WhisperSystems.

the class AttachmentUploadJob method onRun.

@Override
public void onRun() throws Exception {
    if (!Recipient.self().isRegistered()) {
        throw new NotPushRegisteredException();
    }
    Data inputData = getInputData();
    ResumableUploadSpec resumableUploadSpec;
    if (forceV2) {
        Log.d(TAG, "Forcing utilization of V2");
        resumableUploadSpec = null;
    } else if (inputData != null && inputData.hasString(ResumableUploadSpecJob.KEY_RESUME_SPEC)) {
        Log.d(TAG, "Using attachments V3");
        resumableUploadSpec = ResumableUploadSpec.deserialize(inputData.getString(ResumableUploadSpecJob.KEY_RESUME_SPEC));
    } else {
        Log.d(TAG, "Using attachments V2");
        resumableUploadSpec = null;
    }
    SignalServiceMessageSender messageSender = ApplicationDependencies.getSignalServiceMessageSender();
    AttachmentDatabase database = SignalDatabase.attachments();
    DatabaseAttachment databaseAttachment = database.getAttachment(attachmentId);
    if (databaseAttachment == null) {
        throw new InvalidAttachmentException("Cannot find the specified attachment.");
    }
    long timeSinceUpload = System.currentTimeMillis() - databaseAttachment.getUploadTimestamp();
    if (timeSinceUpload < UPLOAD_REUSE_THRESHOLD && !TextUtils.isEmpty(databaseAttachment.getLocation())) {
        Log.i(TAG, "We can re-use an already-uploaded file. It was uploaded " + timeSinceUpload + " ms ago. Skipping.");
        return;
    } else if (databaseAttachment.getUploadTimestamp() > 0) {
        Log.i(TAG, "This file was previously-uploaded, but too long ago to be re-used. Age: " + timeSinceUpload + " ms");
    }
    Log.i(TAG, "Uploading attachment for message " + databaseAttachment.getMmsId() + " with ID " + databaseAttachment.getAttachmentId());
    try (NotificationController notification = getNotificationForAttachment(databaseAttachment)) {
        SignalServiceAttachment localAttachment = getAttachmentFor(databaseAttachment, notification, resumableUploadSpec);
        SignalServiceAttachmentPointer remoteAttachment = messageSender.uploadAttachment(localAttachment.asStream());
        Attachment attachment = PointerAttachment.forPointer(Optional.of(remoteAttachment), null, databaseAttachment.getFastPreflightId()).get();
        database.updateAttachmentAfterUpload(databaseAttachment.getAttachmentId(), attachment, remoteAttachment.getUploadTimestamp());
    } catch (NonSuccessfulResumableUploadResponseCodeException e) {
        if (e.getCode() == 400) {
            Log.w(TAG, "Failed to upload due to a 400 when getting resumable upload information. Downgrading to attachments v2", e);
            forceV2 = true;
        }
    }
}
Also used : NotPushRegisteredException(org.thoughtcrime.securesms.net.NotPushRegisteredException) DatabaseAttachment(org.thoughtcrime.securesms.attachments.DatabaseAttachment) SignalServiceMessageSender(org.whispersystems.signalservice.api.SignalServiceMessageSender) SignalServiceAttachmentPointer(org.whispersystems.signalservice.api.messages.SignalServiceAttachmentPointer) Data(org.thoughtcrime.securesms.jobmanager.Data) PointerAttachment(org.thoughtcrime.securesms.attachments.PointerAttachment) DatabaseAttachment(org.thoughtcrime.securesms.attachments.DatabaseAttachment) SignalServiceAttachment(org.whispersystems.signalservice.api.messages.SignalServiceAttachment) Attachment(org.thoughtcrime.securesms.attachments.Attachment) AttachmentDatabase(org.thoughtcrime.securesms.database.AttachmentDatabase) NonSuccessfulResumableUploadResponseCodeException(org.whispersystems.signalservice.api.push.exceptions.NonSuccessfulResumableUploadResponseCodeException) SignalServiceAttachment(org.whispersystems.signalservice.api.messages.SignalServiceAttachment) ResumableUploadSpec(org.whispersystems.signalservice.internal.push.http.ResumableUploadSpec) NotificationController(org.thoughtcrime.securesms.service.NotificationController)

Example 9 with AttachmentDatabase

use of org.thoughtcrime.securesms.database.AttachmentDatabase in project Signal-Android by WhisperSystems.

the class AttachmentCompressionJob method onRun.

@Override
public void onRun() throws Exception {
    Log.d(TAG, "Running for: " + attachmentId);
    AttachmentDatabase database = SignalDatabase.attachments();
    DatabaseAttachment databaseAttachment = database.getAttachment(attachmentId);
    if (databaseAttachment == null) {
        throw new UndeliverableMessageException("Cannot find the specified attachment.");
    }
    if (databaseAttachment.getTransformProperties().shouldSkipTransform()) {
        Log.i(TAG, "Skipping at the direction of the TransformProperties.");
        return;
    }
    MediaConstraints mediaConstraints = mms ? MediaConstraints.getMmsMediaConstraints(mmsSubscriptionId) : MediaConstraints.getPushMediaConstraints(SentMediaQuality.fromCode(databaseAttachment.getTransformProperties().getSentMediaQuality()));
    compress(database, mediaConstraints, databaseAttachment);
}
Also used : MediaConstraints(org.thoughtcrime.securesms.mms.MediaConstraints) UndeliverableMessageException(org.thoughtcrime.securesms.transport.UndeliverableMessageException) DatabaseAttachment(org.thoughtcrime.securesms.attachments.DatabaseAttachment) AttachmentDatabase(org.thoughtcrime.securesms.database.AttachmentDatabase)

Example 10 with AttachmentDatabase

use of org.thoughtcrime.securesms.database.AttachmentDatabase in project Signal-Android by WhisperSystems.

the class MessageSender method sendPushWithPreUploadedMedia.

public static long sendPushWithPreUploadedMedia(final Context context, final OutgoingMediaMessage message, final Collection<PreUploadResult> preUploadResults, final long threadId, final SmsDatabase.InsertListener insertListener) {
    Log.i(TAG, "Sending media message with pre-uploads to " + message.getRecipient().getId() + ", thread: " + threadId);
    Preconditions.checkArgument(message.getAttachments().isEmpty(), "If the media is pre-uploaded, there should be no attachments on the message.");
    try {
        ThreadDatabase threadDatabase = SignalDatabase.threads();
        MessageDatabase mmsDatabase = SignalDatabase.mms();
        AttachmentDatabase attachmentDatabase = SignalDatabase.attachments();
        long allocatedThreadId;
        if (threadId == -1) {
            allocatedThreadId = threadDatabase.getOrCreateThreadIdFor(message.getRecipient(), message.getDistributionType());
        } else {
            allocatedThreadId = threadId;
        }
        Recipient recipient = message.getRecipient();
        long messageId = mmsDatabase.insertMessageOutbox(applyUniversalExpireTimerIfNecessary(context, recipient, message, allocatedThreadId), allocatedThreadId, false, insertListener);
        List<AttachmentId> attachmentIds = Stream.of(preUploadResults).map(PreUploadResult::getAttachmentId).toList();
        List<String> jobIds = Stream.of(preUploadResults).map(PreUploadResult::getJobIds).flatMap(Stream::of).toList();
        attachmentDatabase.updateMessageId(attachmentIds, messageId);
        sendMediaMessage(context, recipient, false, messageId, jobIds);
        onMessageSent();
        threadDatabase.update(threadId, true);
        return allocatedThreadId;
    } catch (MmsException e) {
        Log.w(TAG, e);
        return threadId;
    }
}
Also used : MessageDatabase(org.thoughtcrime.securesms.database.MessageDatabase) MmsException(org.thoughtcrime.securesms.mms.MmsException) Recipient(org.thoughtcrime.securesms.recipients.Recipient) ThreadDatabase(org.thoughtcrime.securesms.database.ThreadDatabase) AttachmentDatabase(org.thoughtcrime.securesms.database.AttachmentDatabase) AttachmentId(org.thoughtcrime.securesms.attachments.AttachmentId)

Aggregations

AttachmentDatabase (org.thoughtcrime.securesms.database.AttachmentDatabase)35 DatabaseAttachment (org.thoughtcrime.securesms.attachments.DatabaseAttachment)20 Attachment (org.thoughtcrime.securesms.attachments.Attachment)14 MmsException (org.thoughtcrime.securesms.mms.MmsException)13 IOException (java.io.IOException)12 AttachmentId (org.thoughtcrime.securesms.attachments.AttachmentId)10 NonNull (androidx.annotation.NonNull)6 LinkedList (java.util.LinkedList)6 MessageDatabase (org.thoughtcrime.securesms.database.MessageDatabase)6 Job (org.thoughtcrime.securesms.jobmanager.Job)6 UndeliverableMessageException (org.thoughtcrime.securesms.transport.UndeliverableMessageException)6 File (java.io.File)5 PartProgressEvent (org.thoughtcrime.securesms.events.PartProgressEvent)5 Stream (com.annimon.stream.Stream)4 MessageRecord (org.thoughtcrime.securesms.database.model.MessageRecord)4 MediaStream (org.thoughtcrime.securesms.mms.MediaStream)4 SignalServiceAttachmentPointer (org.whispersystems.signalservice.api.messages.SignalServiceAttachmentPointer)4 Nullable (androidx.annotation.Nullable)3 InputStream (java.io.InputStream)3 List (java.util.List)3