mirror of
https://github.com/signalapp/Signal-Android.git
synced 2025-12-24 13:08:46 +00:00
Insert resent messages at the proper location.
This commit is contained in:
committed by
Alex Hart
parent
90a27d2227
commit
a1c8573fad
@@ -244,6 +244,15 @@ class InternalSettingsFragment : DSLSettingsFragment(R.string.preferences__inter
|
||||
}
|
||||
)
|
||||
|
||||
switchPref(
|
||||
title = DSLSettingsText.from(R.string.preferences__internal_delay_resends),
|
||||
summary = DSLSettingsText.from(R.string.preferences__internal_delay_resending_messages_in_response_to_retry_receipts),
|
||||
isChecked = state.delayResends,
|
||||
onClick = {
|
||||
viewModel.setDelayResends(!state.delayResends)
|
||||
}
|
||||
)
|
||||
|
||||
dividerPref()
|
||||
|
||||
sectionHeaderPref(R.string.preferences__internal_calling)
|
||||
|
||||
@@ -15,4 +15,5 @@ data class InternalSettingsState(
|
||||
val useBuiltInEmojiSet: Boolean,
|
||||
val emojiVersion: EmojiFiles.Version?,
|
||||
val removeSenderKeyMinimium: Boolean,
|
||||
val delayResends: Boolean,
|
||||
)
|
||||
|
||||
@@ -70,6 +70,11 @@ class InternalSettingsViewModel(private val repository: InternalSettingsReposito
|
||||
refresh()
|
||||
}
|
||||
|
||||
fun setDelayResends(enabled: Boolean) {
|
||||
preferenceDataStore.putBoolean(InternalValues.DELAY_RESENDS, enabled)
|
||||
refresh()
|
||||
}
|
||||
|
||||
fun setInternalGroupCallingServer(server: String?) {
|
||||
preferenceDataStore.putString(InternalValues.CALLING_SERVER, server)
|
||||
refresh()
|
||||
@@ -91,7 +96,8 @@ class InternalSettingsViewModel(private val repository: InternalSettingsReposito
|
||||
callingServer = SignalStore.internalValues().groupCallingServer(),
|
||||
useBuiltInEmojiSet = SignalStore.internalValues().forceBuiltInEmoji(),
|
||||
emojiVersion = null,
|
||||
removeSenderKeyMinimium = SignalStore.internalValues().removeSenderKeyMinimum()
|
||||
removeSenderKeyMinimium = SignalStore.internalValues().removeSenderKeyMinimum(),
|
||||
delayResends = SignalStore.internalValues().delayResends()
|
||||
)
|
||||
|
||||
class Factory(private val repository: InternalSettingsRepository) : ViewModelProvider.Factory {
|
||||
|
||||
@@ -1342,7 +1342,7 @@ public class MmsDatabase extends MessageDatabase {
|
||||
contentValues.put(THREAD_ID, threadId);
|
||||
contentValues.put(CONTENT_LOCATION, contentLocation);
|
||||
contentValues.put(STATUS, Status.DOWNLOAD_INITIALIZED);
|
||||
contentValues.put(DATE_RECEIVED, retrieved.isPushMessage() ? System.currentTimeMillis() : generatePduCompatTimestamp());
|
||||
contentValues.put(DATE_RECEIVED, retrieved.isPushMessage() ? retrieved.getReceivedTimeMillis() : generatePduCompatTimestamp(retrieved.getReceivedTimeMillis()));
|
||||
contentValues.put(PART_COUNT, retrieved.getAttachments().size());
|
||||
contentValues.put(SUBSCRIPTION_ID, retrieved.getSubscriptionId());
|
||||
contentValues.put(EXPIRES_IN, retrieved.getExpiresIn());
|
||||
@@ -1448,7 +1448,7 @@ public class MmsDatabase extends MessageDatabase {
|
||||
contentValues.put(MESSAGE_BOX, Types.BASE_INBOX_TYPE);
|
||||
contentValues.put(THREAD_ID, threadId);
|
||||
contentValues.put(STATUS, Status.DOWNLOAD_INITIALIZED);
|
||||
contentValues.put(DATE_RECEIVED, generatePduCompatTimestamp());
|
||||
contentValues.put(DATE_RECEIVED, generatePduCompatTimestamp(System.currentTimeMillis()));
|
||||
contentValues.put(READ, Util.isDefaultSmsProvider(context) ? 0 : 1);
|
||||
contentValues.put(SUBSCRIPTION_ID, subscriptionId);
|
||||
|
||||
@@ -2174,8 +2174,7 @@ public class MmsDatabase extends MessageDatabase {
|
||||
}
|
||||
}
|
||||
|
||||
private long generatePduCompatTimestamp() {
|
||||
final long time = System.currentTimeMillis();
|
||||
private long generatePduCompatTimestamp(long time) {
|
||||
return time - (time % 1000);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1115,7 +1115,7 @@ public class SmsDatabase extends MessageDatabase {
|
||||
ContentValues values = new ContentValues();
|
||||
values.put(RECIPIENT_ID, message.getSender().serialize());
|
||||
values.put(ADDRESS_DEVICE_ID, message.getSenderDeviceId());
|
||||
values.put(DATE_RECEIVED, System.currentTimeMillis());
|
||||
values.put(DATE_RECEIVED, message.getReceivedTimestampMillis());
|
||||
values.put(DATE_SENT, message.getSentTimestampMillis());
|
||||
values.put(DATE_SERVER, message.getServerTimestampMillis());
|
||||
values.put(PROTOCOL, message.getProtocol());
|
||||
|
||||
@@ -248,7 +248,7 @@ public final class GroupV1MessageProcessor {
|
||||
} else {
|
||||
MessageDatabase smsDatabase = DatabaseFactory.getSmsDatabase(context);
|
||||
String body = Base64.encodeBytes(storage.toByteArray());
|
||||
IncomingTextMessage incoming = new IncomingTextMessage(Recipient.externalHighTrustPush(context, content.getSender()).getId(), content.getSenderDevice(), content.getTimestamp(), content.getServerReceivedTimestamp(), body, Optional.of(GroupId.v1orThrow(group.getGroupId())), 0, content.isNeedsReceipt(), content.getServerUuid());
|
||||
IncomingTextMessage incoming = new IncomingTextMessage(Recipient.externalHighTrustPush(context, content.getSender()).getId(), content.getSenderDevice(), content.getTimestamp(), content.getServerReceivedTimestamp(), System.currentTimeMillis(), body, Optional.of(GroupId.v1orThrow(group.getGroupId())), 0, content.isNeedsReceipt(), content.getServerUuid());
|
||||
IncomingGroupUpdateMessage groupMessage = new IncomingGroupUpdateMessage(incoming, storage, body);
|
||||
|
||||
Optional<InsertResult> insertResult = smsDatabase.insertMessageInbox(groupMessage);
|
||||
|
||||
@@ -521,7 +521,7 @@ public final class GroupsV2StateProcessor {
|
||||
} else {
|
||||
MessageDatabase smsDatabase = DatabaseFactory.getSmsDatabase(context);
|
||||
RecipientId sender = RecipientId.from(editor.get(), null);
|
||||
IncomingTextMessage incoming = new IncomingTextMessage(sender, -1, timestamp, timestamp, "", Optional.of(groupId), 0, false, null);
|
||||
IncomingTextMessage incoming = new IncomingTextMessage(sender, -1, timestamp, timestamp, timestamp, "", Optional.of(groupId), 0, false, null);
|
||||
IncomingGroupUpdateMessage groupMessage = new IncomingGroupUpdateMessage(incoming, decryptedGroupV2Context);
|
||||
|
||||
if (!smsDatabase.insertMessageInbox(groupMessage).isPresent()) {
|
||||
|
||||
@@ -248,7 +248,7 @@ public class MmsDownloadJob extends BaseJob {
|
||||
group = Optional.of(DatabaseFactory.getGroupDatabase(context).getOrCreateMmsGroupForMembers(recipients));
|
||||
}
|
||||
|
||||
IncomingMediaMessage message = new IncomingMediaMessage(from, group, body, retrieved.getDate() * 1000L, -1, attachments, subscriptionId, 0, false, false, false, Optional.of(sharedContacts));
|
||||
IncomingMediaMessage message = new IncomingMediaMessage(from, group, body, retrieved.getDate() * 1000L, -1, System.currentTimeMillis(), attachments, subscriptionId, 0, false, false, false, Optional.of(sharedContacts));
|
||||
Optional<InsertResult> insertResult = database.insertMessageInbox(message, contentLocation, threadId);
|
||||
|
||||
if (insertResult.isPresent()) {
|
||||
|
||||
@@ -6,26 +6,34 @@ import androidx.annotation.Nullable;
|
||||
import com.google.protobuf.ByteString;
|
||||
import com.google.protobuf.InvalidProtocolBufferException;
|
||||
|
||||
import org.signal.core.util.ThreadUtil;
|
||||
import org.signal.core.util.logging.Log;
|
||||
import org.thoughtcrime.securesms.crypto.UnidentifiedAccessUtil;
|
||||
import org.thoughtcrime.securesms.crypto.storage.SignalSenderKeyStore;
|
||||
import org.thoughtcrime.securesms.dependencies.ApplicationDependencies;
|
||||
import org.thoughtcrime.securesms.groups.GroupId;
|
||||
import org.thoughtcrime.securesms.jobmanager.Data;
|
||||
import org.thoughtcrime.securesms.jobmanager.Job;
|
||||
import org.thoughtcrime.securesms.jobmanager.impl.NetworkConstraint;
|
||||
import org.thoughtcrime.securesms.keyvalue.SignalStore;
|
||||
import org.thoughtcrime.securesms.recipients.Recipient;
|
||||
import org.thoughtcrime.securesms.recipients.RecipientId;
|
||||
import org.thoughtcrime.securesms.recipients.RecipientUtil;
|
||||
import org.whispersystems.libsignal.SignalProtocolAddress;
|
||||
import org.whispersystems.libsignal.protocol.SenderKeyDistributionMessage;
|
||||
import org.whispersystems.libsignal.util.guava.Optional;
|
||||
import org.whispersystems.signalservice.api.SignalServiceMessageSender;
|
||||
import org.whispersystems.signalservice.api.crypto.ContentHint;
|
||||
import org.whispersystems.signalservice.api.crypto.UnidentifiedAccessPair;
|
||||
import org.whispersystems.signalservice.api.messages.SendMessageResult;
|
||||
import org.whispersystems.signalservice.api.push.DistributionId;
|
||||
import org.whispersystems.signalservice.api.push.SignalServiceAddress;
|
||||
import org.whispersystems.signalservice.api.push.exceptions.PushNetworkException;
|
||||
import org.whispersystems.signalservice.internal.push.SignalServiceProtos.Content;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
/**
|
||||
* Resends a previously-sent message in response to receiving a retry receipt.
|
||||
@@ -36,6 +44,8 @@ public class ResendMessageJob extends BaseJob {
|
||||
|
||||
public static final String KEY = "ResendMessageJob";
|
||||
|
||||
private static final String TAG = Log.tag(ResendMessageJob.class);
|
||||
|
||||
private final RecipientId recipientId;
|
||||
private final long sentTimestamp;
|
||||
private final Content content;
|
||||
@@ -50,7 +60,6 @@ public class ResendMessageJob extends BaseJob {
|
||||
private static final String KEY_GROUP_ID = "group_id";
|
||||
private static final String KEY_DISTRIBUTION_ID = "distribution_id";
|
||||
|
||||
// TODO [greyson] Maybe just pass in the MessageLogEntry?
|
||||
public ResendMessageJob(@NonNull RecipientId recipientId,
|
||||
long sentTimestamp,
|
||||
@NonNull Content content,
|
||||
@@ -108,6 +117,11 @@ public class ResendMessageJob extends BaseJob {
|
||||
|
||||
@Override
|
||||
protected void onRun() throws Exception {
|
||||
if (SignalStore.internalValues().delayResends()) {
|
||||
Log.w(TAG, "Delaying resend by 10 sec because of an internal preference.");
|
||||
ThreadUtil.sleep(10000);
|
||||
}
|
||||
|
||||
SignalServiceMessageSender messageSender = ApplicationDependencies.getSignalServiceMessageSender();
|
||||
Recipient recipient = Recipient.resolved(recipientId);
|
||||
SignalServiceAddress address = RecipientUtil.toSignalServiceAddress(context, recipient);
|
||||
@@ -121,7 +135,17 @@ public class ResendMessageJob extends BaseJob {
|
||||
contentToSend = contentToSend.toBuilder().setSenderKeyDistributionMessage(distributionBytes).build();
|
||||
}
|
||||
|
||||
messageSender.resendContent(address, access, sentTimestamp, contentToSend, contentHint, Optional.fromNullable(groupId).transform(GroupId::getDecodedId));
|
||||
SendMessageResult result = messageSender.resendContent(address, access, sentTimestamp, contentToSend, contentHint, Optional.fromNullable(groupId).transform(GroupId::getDecodedId));
|
||||
|
||||
if (result.isSuccess() && distributionId != null) {
|
||||
List<SignalProtocolAddress> addresses = result.getSuccess()
|
||||
.getDevices()
|
||||
.stream()
|
||||
.map(device -> new SignalProtocolAddress(recipient.requireServiceId(), device))
|
||||
.collect(Collectors.toList());
|
||||
|
||||
new SignalSenderKeyStore(context).markSenderKeySharedWith(distributionId, addresses);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -4,6 +4,7 @@ import androidx.annotation.NonNull;
|
||||
|
||||
import org.signal.core.util.logging.Log;
|
||||
import org.thoughtcrime.securesms.crypto.UnidentifiedAccessUtil;
|
||||
import org.thoughtcrime.securesms.crypto.storage.SignalSenderKeyStore;
|
||||
import org.thoughtcrime.securesms.database.DatabaseFactory;
|
||||
import org.thoughtcrime.securesms.database.GroupDatabase;
|
||||
import org.thoughtcrime.securesms.dependencies.ApplicationDependencies;
|
||||
@@ -14,16 +15,19 @@ import org.thoughtcrime.securesms.jobmanager.impl.NetworkConstraint;
|
||||
import org.thoughtcrime.securesms.recipients.Recipient;
|
||||
import org.thoughtcrime.securesms.recipients.RecipientId;
|
||||
import org.thoughtcrime.securesms.recipients.RecipientUtil;
|
||||
import org.whispersystems.libsignal.SignalProtocolAddress;
|
||||
import org.whispersystems.libsignal.protocol.SenderKeyDistributionMessage;
|
||||
import org.whispersystems.libsignal.util.guava.Optional;
|
||||
import org.whispersystems.signalservice.api.SignalServiceMessageSender;
|
||||
import org.whispersystems.signalservice.api.crypto.UnidentifiedAccessPair;
|
||||
import org.whispersystems.signalservice.api.messages.SendMessageResult;
|
||||
import org.whispersystems.signalservice.api.push.DistributionId;
|
||||
import org.whispersystems.signalservice.api.push.SignalServiceAddress;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
/**
|
||||
* Sends a {@link SenderKeyDistributionMessage} to a target recipient.
|
||||
@@ -92,7 +96,17 @@ public final class SenderKeyDistributionSendJob extends BaseJob {
|
||||
SenderKeyDistributionMessage message = messageSender.getOrCreateNewGroupSession(distributionId);
|
||||
List<Optional<UnidentifiedAccessPair>> access = UnidentifiedAccessUtil.getAccessFor(context, Collections.singletonList(recipient));
|
||||
|
||||
messageSender.sendSenderKeyDistributionMessage(address, access, message, groupId.getDecodedId());
|
||||
SendMessageResult result = messageSender.sendSenderKeyDistributionMessage(address, access, message, groupId.getDecodedId()).get(0);
|
||||
|
||||
if (result.isSuccess()) {
|
||||
List<SignalProtocolAddress> addresses = result.getSuccess()
|
||||
.getDevices()
|
||||
.stream()
|
||||
.map(device -> new SignalProtocolAddress(recipient.requireServiceId(), device))
|
||||
.collect(Collectors.toList());
|
||||
|
||||
new SignalSenderKeyStore(context).markSenderKeySharedWith(distributionId, addresses);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -21,6 +21,7 @@ public final class InternalValues extends SignalStoreValues {
|
||||
public static final String FORCE_CENSORSHIP = "internal.force_censorship";
|
||||
public static final String FORCE_BUILT_IN_EMOJI = "internal.force_built_in_emoji";
|
||||
public static final String REMOVE_SENDER_KEY_MINIMUM = "internal.remove_sender_key_minimum";
|
||||
public static final String DELAY_RESENDS = "internal.delay_resends";
|
||||
public static final String CALLING_SERVER = "internal.calling_server";
|
||||
|
||||
InternalValues(KeyValueStore store) {
|
||||
@@ -99,6 +100,13 @@ public final class InternalValues extends SignalStoreValues {
|
||||
return FeatureFlags.internalUser() && getBoolean(REMOVE_SENDER_KEY_MINIMUM, false);
|
||||
}
|
||||
|
||||
/**
|
||||
* Delay resending messages in response to retry receipts by 10 seconds.
|
||||
*/
|
||||
public synchronized boolean delayResends() {
|
||||
return FeatureFlags.internalUser() && getBoolean(DELAY_RESENDS, false);
|
||||
}
|
||||
|
||||
/**
|
||||
* Disable initiating a GV1->GV2 auto-migration. You can still recognize a group has been
|
||||
* auto-migrated.
|
||||
|
||||
@@ -188,6 +188,10 @@ public final class GroupSendUtil {
|
||||
|
||||
int successCount = (int) results.stream().filter(SendMessageResult::isSuccess).count();
|
||||
Log.d(TAG, "Successfully sent using sender key to " + successCount + "/" + targets.size() + " sender key targets.");
|
||||
|
||||
if (sendOperation.shouldIncludeInMessageLog()) {
|
||||
DatabaseFactory.getMessageLogDatabase(context).insertIfPossible(sendOperation.getSentTimestamp(), senderKeyTargets, results, sendOperation.getContentHint(), sendOperation.getRelatedMessageId(), sendOperation.isRelatedMessageMms());
|
||||
}
|
||||
} catch (NoSessionException e) {
|
||||
Log.w(TAG, "No session. Falling back to legacy sends.", e);
|
||||
legacyTargets.addAll(senderKeyTargets);
|
||||
@@ -198,9 +202,6 @@ public final class GroupSendUtil {
|
||||
}
|
||||
|
||||
if (cancelationSignal != null && cancelationSignal.isCanceled()) {
|
||||
if (sendOperation.shouldIncludeInMessageLog()) {
|
||||
DatabaseFactory.getMessageLogDatabase(context).insertIfPossible(sendOperation.getSentTimestamp(), allTargets, allResults, sendOperation.getContentHint(), sendOperation.getRelatedMessageId(), sendOperation.isRelatedMessageMms());
|
||||
}
|
||||
throw new CancelationException();
|
||||
}
|
||||
|
||||
@@ -217,10 +218,10 @@ public final class GroupSendUtil {
|
||||
|
||||
int successCount = (int) results.stream().filter(SendMessageResult::isSuccess).count();
|
||||
Log.d(TAG, "Successfully using 1:1 to " + successCount + "/" + targets.size() + " legacy targets.");
|
||||
}
|
||||
|
||||
if (sendOperation.shouldIncludeInMessageLog()) {
|
||||
DatabaseFactory.getMessageLogDatabase(context).insertIfPossible(sendOperation.getSentTimestamp(), allTargets, allResults, sendOperation.getContentHint(), sendOperation.getRelatedMessageId(), sendOperation.isRelatedMessageMms());
|
||||
if (sendOperation.shouldIncludeInMessageLog()) {
|
||||
DatabaseFactory.getMessageLogDatabase(context).insertIfPossible(sendOperation.getSentTimestamp(), legacyTargets, results, sendOperation.getContentHint(), sendOperation.getRelatedMessageId(), sendOperation.isRelatedMessageMms());
|
||||
}
|
||||
}
|
||||
|
||||
return allResults;
|
||||
|
||||
@@ -159,8 +159,8 @@ public class IncomingMessageProcessor {
|
||||
}
|
||||
|
||||
private void processReceipt(@NonNull SignalServiceEnvelope envelope) {
|
||||
Log.i(TAG, "Received server receipt for " + envelope.getTimestamp());
|
||||
Recipient sender = Recipient.externalHighTrustPush(context, envelope.getSourceAddress());
|
||||
Log.i(TAG, "Received server receipt. Sender: " + sender.getId() + ", Device: " + envelope.getSourceDevice() + ", Timestamp: " + envelope.getTimestamp());
|
||||
|
||||
mmsSmsDatabase.incrementDeliveryReceiptCount(new SyncMessageId(sender.getId(), envelope.getTimestamp()), System.currentTimeMillis());
|
||||
DatabaseFactory.getMessageLogDatabase(context).deleteEntryForRecipient(envelope.getTimestamp(), sender.getId(), envelope.getSourceDevice());
|
||||
|
||||
@@ -45,6 +45,7 @@ import org.thoughtcrime.securesms.database.model.Mention;
|
||||
import org.thoughtcrime.securesms.database.model.MessageLogEntry;
|
||||
import org.thoughtcrime.securesms.database.model.MessageRecord;
|
||||
import org.thoughtcrime.securesms.database.model.MmsMessageRecord;
|
||||
import org.thoughtcrime.securesms.database.model.PendingRetryReceiptModel;
|
||||
import org.thoughtcrime.securesms.database.model.ReactionRecord;
|
||||
import org.thoughtcrime.securesms.database.model.StickerRecord;
|
||||
import org.thoughtcrime.securesms.database.model.ThreadRecord;
|
||||
@@ -229,6 +230,10 @@ public final class MessageContentProcessor {
|
||||
return;
|
||||
}
|
||||
|
||||
RecipientId senderId = RecipientId.fromHighTrust(content.getSender());
|
||||
PendingRetryReceiptModel pending = DatabaseFactory.getPendingRetryReceiptDatabase(context).get(senderId, content.getTimestamp());
|
||||
long receivedTime = handlePendingRetry(pending, content);
|
||||
|
||||
log(String.valueOf(content.getTimestamp()), "Beginning message processing.");
|
||||
|
||||
if (content.getSenderKeyDistributionMessage().isPresent()) {
|
||||
@@ -249,13 +254,13 @@ public final class MessageContentProcessor {
|
||||
|
||||
if (isInvalidMessage(message)) handleInvalidMessage(content.getSender(), content.getSenderDevice(), groupId, content.getTimestamp(), smsMessageId);
|
||||
else if (message.isEndSession()) handleEndSessionMessage(content, smsMessageId);
|
||||
else if (message.isGroupV1Update()) handleGroupV1Message(content, message, smsMessageId, groupId.get().requireV1());
|
||||
else if (message.isExpirationUpdate()) handleExpirationUpdate(content, message, smsMessageId, groupId);
|
||||
else if (message.isGroupV1Update()) handleGroupV1Message(content, message, smsMessageId, groupId.get().requireV1(), receivedTime);
|
||||
else if (message.isExpirationUpdate()) handleExpirationUpdate(content, message, smsMessageId, groupId, receivedTime);
|
||||
else if (message.getReaction().isPresent()) handleReaction(content, message);
|
||||
else if (message.getRemoteDelete().isPresent()) handleRemoteDelete(content, message);
|
||||
else if (message.getPayment().isPresent()) handlePayment(content, message);
|
||||
else if (isMediaMessage) handleMediaMessage(content, message, smsMessageId);
|
||||
else if (message.getBody().isPresent()) handleTextMessage(content, message, smsMessageId, groupId);
|
||||
else if (isMediaMessage) handleMediaMessage(content, message, smsMessageId, receivedTime);
|
||||
else if (message.getBody().isPresent()) handleTextMessage(content, message, smsMessageId, groupId, receivedTime);
|
||||
else if (Build.VERSION.SDK_INT > 19 && message.getGroupCallUpdate().isPresent()) handleGroupCallUpdateMessage(content, message, groupId);
|
||||
|
||||
if (groupId.isPresent() && groupDatabase.isUnknownGroup(groupId.get())) {
|
||||
@@ -332,11 +337,18 @@ public final class MessageContentProcessor {
|
||||
handleTypingMessage(content, content.getTypingMessage().get());
|
||||
} else if (content.getDecryptionErrorMessage().isPresent()) {
|
||||
handleRetryReceipt(content, content.getDecryptionErrorMessage().get());
|
||||
} else if (content.getSenderKeyDistributionMessage().isPresent()) {
|
||||
// Already handled, here in order to prevent unrecognized message log
|
||||
} else {
|
||||
warn(String.valueOf(content.getTimestamp()), "Got unrecognized message!");
|
||||
}
|
||||
|
||||
resetRecipientToPush(Recipient.externalPush(context, content.getSender()));
|
||||
|
||||
if (pending != null) {
|
||||
warn(content.getTimestamp(), "Pending retry was processed. Deleting.");
|
||||
DatabaseFactory.getPendingRetryReceiptDatabase(context).delete(pending.getId());
|
||||
}
|
||||
} catch (StorageFailedException e) {
|
||||
warn(String.valueOf(content.getTimestamp()), e);
|
||||
handleCorruptMessage(e.getSender(), e.getSenderDevice(), timestamp, smsMessageId);
|
||||
@@ -345,6 +357,33 @@ public final class MessageContentProcessor {
|
||||
}
|
||||
}
|
||||
|
||||
private long handlePendingRetry(PendingRetryReceiptModel pending, SignalServiceContent content) throws BadGroupIdException {
|
||||
long receivedTime = System.currentTimeMillis();
|
||||
|
||||
if (pending != null) {
|
||||
warn(content.getTimestamp(), "Incoming message matches a pending retry we were expecting.");
|
||||
|
||||
Recipient destination = getMessageDestination(content);
|
||||
Long threadId = DatabaseFactory.getThreadDatabase(context).getThreadIdFor(destination.getId());
|
||||
|
||||
if (threadId != null) {
|
||||
ThreadDatabase.ConversationMetadata metadata = DatabaseFactory.getThreadDatabase(context).getConversationMetadata(threadId);
|
||||
long visibleThread = ApplicationDependencies.getMessageNotifier().getVisibleThread();
|
||||
|
||||
if (threadId != visibleThread && metadata.getLastSeen() > 0 && metadata.getLastSeen() < pending.getReceivedTimestamp()) {
|
||||
receivedTime = pending.getReceivedTimestamp();
|
||||
warn(content.getTimestamp(), "Thread has not been opened yet. Using received timestamp of " + receivedTime);
|
||||
} else {
|
||||
warn(content.getTimestamp(), "Thread was opened after receiving the original message. Using the current time for received time. (Last seen: " + metadata.getLastSeen() + ", ThreadVisible: " + (threadId == visibleThread) + ")");
|
||||
}
|
||||
} else {
|
||||
warn(content.getTimestamp(), "Could not find a thread for the pending message. Using current time for received time.");
|
||||
}
|
||||
}
|
||||
|
||||
return receivedTime;
|
||||
}
|
||||
|
||||
private void handlePayment(@NonNull SignalServiceContent content, @NonNull SignalServiceDataMessage message) {
|
||||
if (!message.getPayment().isPresent()) {
|
||||
throw new AssertionError();
|
||||
@@ -611,6 +650,7 @@ public final class MessageContentProcessor {
|
||||
content.getSenderDevice(),
|
||||
content.getTimestamp(),
|
||||
content.getServerReceivedTimestamp(),
|
||||
System.currentTimeMillis(),
|
||||
"",
|
||||
Optional.absent(),
|
||||
0,
|
||||
@@ -667,13 +707,14 @@ public final class MessageContentProcessor {
|
||||
private void handleGroupV1Message(@NonNull SignalServiceContent content,
|
||||
@NonNull SignalServiceDataMessage message,
|
||||
@NonNull Optional<Long> smsMessageId,
|
||||
@NonNull GroupId.V1 groupId)
|
||||
@NonNull GroupId.V1 groupId,
|
||||
long receivedTime)
|
||||
throws StorageFailedException, BadGroupIdException
|
||||
{
|
||||
GroupV1MessageProcessor.process(context, content, message, false);
|
||||
|
||||
if (message.getExpiresInSeconds() != 0 && message.getExpiresInSeconds() != getMessageDestination(content, message).getExpireMessages()) {
|
||||
handleExpirationUpdate(content, message, Optional.absent(), Optional.of(groupId));
|
||||
handleExpirationUpdate(content, message, Optional.absent(), Optional.of(groupId), receivedTime);
|
||||
}
|
||||
|
||||
if (smsMessageId.isPresent()) {
|
||||
@@ -703,7 +744,8 @@ public final class MessageContentProcessor {
|
||||
private void handleExpirationUpdate(@NonNull SignalServiceContent content,
|
||||
@NonNull SignalServiceDataMessage message,
|
||||
@NonNull Optional<Long> smsMessageId,
|
||||
@NonNull Optional<GroupId> groupId)
|
||||
@NonNull Optional<GroupId> groupId,
|
||||
long receivedTime)
|
||||
throws StorageFailedException, BadGroupIdException
|
||||
{
|
||||
if (groupId.isPresent() && groupId.get().isV2()) {
|
||||
@@ -726,6 +768,7 @@ public final class MessageContentProcessor {
|
||||
IncomingMediaMessage mediaMessage = new IncomingMediaMessage(sender.getId(),
|
||||
content.getTimestamp(),
|
||||
content.getServerReceivedTimestamp(),
|
||||
receivedTime,
|
||||
-1,
|
||||
expiresInSeconds * 1000L,
|
||||
true,
|
||||
@@ -1150,7 +1193,8 @@ public final class MessageContentProcessor {
|
||||
|
||||
private void handleMediaMessage(@NonNull SignalServiceContent content,
|
||||
@NonNull SignalServiceDataMessage message,
|
||||
@NonNull Optional<Long> smsMessageId)
|
||||
@NonNull Optional<Long> smsMessageId,
|
||||
long receivedTime)
|
||||
throws StorageFailedException, BadGroupIdException
|
||||
{
|
||||
notifyTypingStoppedFromIncomingMessage(getMessageDestination(content, message), content.getSender(), content.getSenderDevice());
|
||||
@@ -1170,6 +1214,7 @@ public final class MessageContentProcessor {
|
||||
IncomingMediaMessage mediaMessage = new IncomingMediaMessage(RecipientId.fromHighTrust(content.getSender()),
|
||||
message.getTimestamp(),
|
||||
content.getServerReceivedTimestamp(),
|
||||
receivedTime,
|
||||
-1,
|
||||
message.getExpiresInSeconds() * 1000L,
|
||||
false,
|
||||
@@ -1373,7 +1418,8 @@ public final class MessageContentProcessor {
|
||||
private void handleTextMessage(@NonNull SignalServiceContent content,
|
||||
@NonNull SignalServiceDataMessage message,
|
||||
@NonNull Optional<Long> smsMessageId,
|
||||
@NonNull Optional<GroupId> groupId)
|
||||
@NonNull Optional<GroupId> groupId,
|
||||
long receivedTime)
|
||||
throws StorageFailedException, BadGroupIdException
|
||||
{
|
||||
MessageDatabase database = DatabaseFactory.getSmsDatabase(context);
|
||||
@@ -1381,7 +1427,7 @@ public final class MessageContentProcessor {
|
||||
Recipient recipient = getMessageDestination(content, message);
|
||||
|
||||
if (message.getExpiresInSeconds() != recipient.getExpireMessages()) {
|
||||
handleExpirationUpdate(content, message, Optional.absent(), groupId);
|
||||
handleExpirationUpdate(content, message, Optional.absent(), groupId, receivedTime);
|
||||
}
|
||||
|
||||
Long threadId;
|
||||
@@ -1395,6 +1441,7 @@ public final class MessageContentProcessor {
|
||||
content.getSenderDevice(),
|
||||
message.getTimestamp(),
|
||||
content.getServerReceivedTimestamp(),
|
||||
receivedTime,
|
||||
body,
|
||||
groupId,
|
||||
message.getExpiresInSeconds() * 1000L,
|
||||
@@ -1603,12 +1650,13 @@ public final class MessageContentProcessor {
|
||||
return;
|
||||
}
|
||||
|
||||
log("Processing viewed reciepts for IDs: " + Util.join(message.getTimestamps(), ","));
|
||||
Recipient sender = Recipient.externalHighTrustPush(context, content.getSender());
|
||||
log(TAG, "Processing viewed receipts. Sender: " + sender.getId() + ", Device: " + content.getSenderDevice() + ", Timestamps: " + Util.join(message.getTimestamps(), ", "));
|
||||
|
||||
List<SyncMessageId> ids = Stream.of(message.getTimestamps())
|
||||
.map(t -> new SyncMessageId(sender.getId(), t))
|
||||
.toList();
|
||||
|
||||
Recipient sender = Recipient.externalHighTrustPush(context, content.getSender());
|
||||
List<SyncMessageId> ids = Stream.of(message.getTimestamps())
|
||||
.map(t -> new SyncMessageId(sender.getId(), t))
|
||||
.toList();
|
||||
Collection<SyncMessageId> unhandled = DatabaseFactory.getMmsSmsDatabase(context)
|
||||
.incrementViewedReceiptCounts(ids, content.getTimestamp());
|
||||
|
||||
@@ -1622,12 +1670,12 @@ public final class MessageContentProcessor {
|
||||
private void handleDeliveryReceipt(@NonNull SignalServiceContent content,
|
||||
@NonNull SignalServiceReceiptMessage message)
|
||||
{
|
||||
log(TAG, "Processing delivery receipts for IDs: " + Util.join(message.getTimestamps(), ", "));
|
||||
Recipient sender = Recipient.externalHighTrustPush(context, content.getSender());
|
||||
log(TAG, "Processing delivery receipts. Sender: " + sender.getId() + ", Device: " + content.getSenderDevice() + ", Timestamps: " + Util.join(message.getTimestamps(), ", "));
|
||||
|
||||
Recipient sender = Recipient.externalHighTrustPush(context, content.getSender());
|
||||
List<SyncMessageId> ids = Stream.of(message.getTimestamps())
|
||||
.map(t -> new SyncMessageId(sender.getId(), t))
|
||||
.toList();
|
||||
List<SyncMessageId> ids = Stream.of(message.getTimestamps())
|
||||
.map(t -> new SyncMessageId(sender.getId(), t))
|
||||
.toList();
|
||||
|
||||
DatabaseFactory.getMmsSmsDatabase(context).incrementDeliveryReceiptCounts(ids, System.currentTimeMillis());
|
||||
DatabaseFactory.getMessageLogDatabase(context).deleteEntriesForRecipient(message.getTimestamps(), sender.getId(), content.getSenderDevice());
|
||||
@@ -1642,12 +1690,12 @@ public final class MessageContentProcessor {
|
||||
return;
|
||||
}
|
||||
|
||||
log("Processing read receipts for IDs: " + Util.join(message.getTimestamps(), ", "));
|
||||
Recipient sender = Recipient.externalHighTrustPush(context, content.getSender());
|
||||
log(TAG, "Processing read receipts. Sender: " + sender.getId() + ", Device: " + content.getSenderDevice() + ", Timestamps: " + Util.join(message.getTimestamps(), ", "));
|
||||
|
||||
Recipient sender = Recipient.externalHighTrustPush(context, content.getSender());
|
||||
List<SyncMessageId> ids = Stream.of(message.getTimestamps())
|
||||
.map(t -> new SyncMessageId(sender.getId(), t))
|
||||
.toList();
|
||||
List<SyncMessageId> ids = Stream.of(message.getTimestamps())
|
||||
.map(t -> new SyncMessageId(sender.getId(), t))
|
||||
.toList();
|
||||
|
||||
Collection<SyncMessageId> unhandled = DatabaseFactory.getMmsSmsDatabase(context).incrementReadReceiptCounts(ids, content.getTimestamp());
|
||||
|
||||
@@ -2016,7 +2064,7 @@ public final class MessageContentProcessor {
|
||||
private Optional<InsertResult> insertPlaceholder(@NonNull String sender, int senderDevice, long timestamp, Optional<GroupId> groupId) {
|
||||
MessageDatabase database = DatabaseFactory.getSmsDatabase(context);
|
||||
IncomingTextMessage textMessage = new IncomingTextMessage(Recipient.external(context, sender).getId(),
|
||||
senderDevice, timestamp, -1, "",
|
||||
senderDevice, timestamp, -1, System.currentTimeMillis(), "",
|
||||
groupId, 0, false, null);
|
||||
|
||||
textMessage = new IncomingEncryptedMessage(textMessage, "");
|
||||
@@ -2029,6 +2077,11 @@ public final class MessageContentProcessor {
|
||||
return getGroupRecipient(message.getMessage().getGroupContext()).or(() -> Recipient.externalPush(context, message.getDestination().get()));
|
||||
}
|
||||
|
||||
private Recipient getMessageDestination(@NonNull SignalServiceContent content) throws BadGroupIdException {
|
||||
SignalServiceDataMessage message = content.getDataMessage().orNull();
|
||||
return getGroupRecipient(message != null ? message.getGroupContext() : Optional.absent()).or(() -> Recipient.externalHighTrustPush(context, content.getSender()));
|
||||
}
|
||||
|
||||
private Recipient getMessageDestination(@NonNull SignalServiceContent content,
|
||||
@NonNull SignalServiceDataMessage message)
|
||||
throws BadGroupIdException
|
||||
@@ -2056,7 +2109,7 @@ public final class MessageContentProcessor {
|
||||
Recipient author = Recipient.externalPush(context, sender);
|
||||
long threadId = DatabaseFactory.getThreadDatabase(context).getThreadIdFor(conversationRecipient);
|
||||
|
||||
if (threadId > 0) {
|
||||
if (threadId > 0 && TextSecurePreferences.isTypingIndicatorsEnabled(context)) {
|
||||
Log.d(TAG, "Typing stopped on thread " + threadId + " due to an incoming message.");
|
||||
ApplicationDependencies.getTypingStatusRepository().onTypingStopped(context, threadId, author, device, true);
|
||||
}
|
||||
|
||||
@@ -26,8 +26,9 @@ public class IncomingMediaMessage {
|
||||
private final String body;
|
||||
private final boolean push;
|
||||
private final long sentTimeMillis;
|
||||
private final long serverTimeMillis;
|
||||
private final int subscriptionId;
|
||||
private final long serverTimeMillis;
|
||||
private final long receivedTimeMillis;
|
||||
private final int subscriptionId;
|
||||
private final long expiresIn;
|
||||
private final boolean expirationUpdate;
|
||||
private final QuoteModel quote;
|
||||
@@ -45,6 +46,7 @@ public class IncomingMediaMessage {
|
||||
String body,
|
||||
long sentTimeMillis,
|
||||
long serverTimeMillis,
|
||||
long receivedTimeMillis,
|
||||
List<Attachment> attachments,
|
||||
int subscriptionId,
|
||||
long expiresIn,
|
||||
@@ -53,19 +55,20 @@ public class IncomingMediaMessage {
|
||||
boolean unidentified,
|
||||
Optional<List<Contact>> sharedContacts)
|
||||
{
|
||||
this.from = from;
|
||||
this.groupId = groupId.orNull();
|
||||
this.sentTimeMillis = sentTimeMillis;
|
||||
this.serverTimeMillis = serverTimeMillis;
|
||||
this.body = body;
|
||||
this.push = false;
|
||||
this.subscriptionId = subscriptionId;
|
||||
this.expiresIn = expiresIn;
|
||||
this.expirationUpdate = expirationUpdate;
|
||||
this.viewOnce = viewOnce;
|
||||
this.quote = null;
|
||||
this.unidentified = unidentified;
|
||||
this.serverGuid = null;
|
||||
this.from = from;
|
||||
this.groupId = groupId.orNull();
|
||||
this.sentTimeMillis = sentTimeMillis;
|
||||
this.serverTimeMillis = serverTimeMillis;
|
||||
this.receivedTimeMillis = receivedTimeMillis;
|
||||
this.body = body;
|
||||
this.push = false;
|
||||
this.subscriptionId = subscriptionId;
|
||||
this.expiresIn = expiresIn;
|
||||
this.expirationUpdate = expirationUpdate;
|
||||
this.viewOnce = viewOnce;
|
||||
this.quote = null;
|
||||
this.unidentified = unidentified;
|
||||
this.serverGuid = null;
|
||||
|
||||
this.attachments.addAll(attachments);
|
||||
this.sharedContacts.addAll(sharedContacts.or(Collections.emptyList()));
|
||||
@@ -75,6 +78,7 @@ public class IncomingMediaMessage {
|
||||
public IncomingMediaMessage(@NonNull RecipientId from,
|
||||
long sentTimeMillis,
|
||||
long serverTimeMillis,
|
||||
long receivedTimeMillis,
|
||||
int subscriptionId,
|
||||
long expiresIn,
|
||||
boolean expirationUpdate,
|
||||
@@ -90,17 +94,18 @@ public class IncomingMediaMessage {
|
||||
Optional<Attachment> sticker,
|
||||
@Nullable String serverGuid)
|
||||
{
|
||||
this.push = true;
|
||||
this.from = from;
|
||||
this.sentTimeMillis = sentTimeMillis;
|
||||
this.serverTimeMillis = serverTimeMillis;
|
||||
this.body = body.orNull();
|
||||
this.subscriptionId = subscriptionId;
|
||||
this.expiresIn = expiresIn;
|
||||
this.expirationUpdate = expirationUpdate;
|
||||
this.viewOnce = viewOnce;
|
||||
this.quote = quote.orNull();
|
||||
this.unidentified = unidentified;
|
||||
this.push = true;
|
||||
this.from = from;
|
||||
this.sentTimeMillis = sentTimeMillis;
|
||||
this.serverTimeMillis = serverTimeMillis;
|
||||
this.receivedTimeMillis = receivedTimeMillis;
|
||||
this.body = body.orNull();
|
||||
this.subscriptionId = subscriptionId;
|
||||
this.expiresIn = expiresIn;
|
||||
this.expirationUpdate = expirationUpdate;
|
||||
this.viewOnce = viewOnce;
|
||||
this.quote = quote.orNull();
|
||||
this.unidentified = unidentified;
|
||||
|
||||
if (group.isPresent()) this.groupId = GroupUtil.idFromGroupContextOrThrow(group.get());
|
||||
else this.groupId = null;
|
||||
@@ -153,6 +158,10 @@ public class IncomingMediaMessage {
|
||||
return serverTimeMillis;
|
||||
}
|
||||
|
||||
public long getReceivedTimeMillis() {
|
||||
return receivedTimeMillis;
|
||||
}
|
||||
|
||||
public long getExpiresIn() {
|
||||
return expiresIn;
|
||||
}
|
||||
|
||||
@@ -6,7 +6,7 @@ import org.whispersystems.libsignal.util.guava.Optional;
|
||||
public class IncomingJoinedMessage extends IncomingTextMessage {
|
||||
|
||||
public IncomingJoinedMessage(RecipientId sender) {
|
||||
super(sender, 1, System.currentTimeMillis(), -1, null, Optional.absent(), 0, false, null);
|
||||
super(sender, 1, System.currentTimeMillis(), -1, System.currentTimeMillis(), null, Optional.absent(), 0, false, null);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -39,6 +39,7 @@ public class IncomingTextMessage implements Parcelable {
|
||||
private final String pseudoSubject;
|
||||
private final long sentTimestampMillis;
|
||||
private final long serverTimestampMillis;
|
||||
private final long receivedTimestampMillis;
|
||||
@Nullable private final GroupId groupId;
|
||||
private final boolean push;
|
||||
private final int subscriptionId;
|
||||
@@ -47,84 +48,89 @@ public class IncomingTextMessage implements Parcelable {
|
||||
@Nullable private final String serverGuid;
|
||||
|
||||
public IncomingTextMessage(@NonNull RecipientId sender, @NonNull SmsMessage message, int subscriptionId) {
|
||||
this.message = message.getDisplayMessageBody();
|
||||
this.sender = sender;
|
||||
this.senderDeviceId = SignalServiceAddress.DEFAULT_DEVICE_ID;
|
||||
this.protocol = message.getProtocolIdentifier();
|
||||
this.serviceCenterAddress = message.getServiceCenterAddress();
|
||||
this.replyPathPresent = message.isReplyPathPresent();
|
||||
this.pseudoSubject = message.getPseudoSubject();
|
||||
this.sentTimestampMillis = message.getTimestampMillis();
|
||||
this.serverTimestampMillis = -1;
|
||||
this.subscriptionId = subscriptionId;
|
||||
this.expiresInMillis = 0;
|
||||
this.groupId = null;
|
||||
this.push = false;
|
||||
this.unidentified = false;
|
||||
this.serverGuid = null;
|
||||
this.message = message.getDisplayMessageBody();
|
||||
this.sender = sender;
|
||||
this.senderDeviceId = SignalServiceAddress.DEFAULT_DEVICE_ID;
|
||||
this.protocol = message.getProtocolIdentifier();
|
||||
this.serviceCenterAddress = message.getServiceCenterAddress();
|
||||
this.replyPathPresent = message.isReplyPathPresent();
|
||||
this.pseudoSubject = message.getPseudoSubject();
|
||||
this.sentTimestampMillis = message.getTimestampMillis();
|
||||
this.serverTimestampMillis = -1;
|
||||
this.receivedTimestampMillis = System.currentTimeMillis();
|
||||
this.subscriptionId = subscriptionId;
|
||||
this.expiresInMillis = 0;
|
||||
this.groupId = null;
|
||||
this.push = false;
|
||||
this.unidentified = false;
|
||||
this.serverGuid = null;
|
||||
}
|
||||
|
||||
public IncomingTextMessage(@NonNull RecipientId sender,
|
||||
int senderDeviceId,
|
||||
long sentTimestampMillis,
|
||||
long serverTimestampMillis,
|
||||
long receivedTimestampMillis,
|
||||
String encodedBody,
|
||||
Optional<GroupId> groupId,
|
||||
long expiresInMillis,
|
||||
boolean unidentified,
|
||||
String serverGuid)
|
||||
{
|
||||
this.message = encodedBody;
|
||||
this.sender = sender;
|
||||
this.senderDeviceId = senderDeviceId;
|
||||
this.protocol = 31337;
|
||||
this.serviceCenterAddress = "GCM";
|
||||
this.replyPathPresent = true;
|
||||
this.pseudoSubject = "";
|
||||
this.sentTimestampMillis = sentTimestampMillis;
|
||||
this.serverTimestampMillis = serverTimestampMillis;
|
||||
this.push = true;
|
||||
this.subscriptionId = -1;
|
||||
this.expiresInMillis = expiresInMillis;
|
||||
this.unidentified = unidentified;
|
||||
this.groupId = groupId.orNull();
|
||||
this.serverGuid = serverGuid;
|
||||
this.message = encodedBody;
|
||||
this.sender = sender;
|
||||
this.senderDeviceId = senderDeviceId;
|
||||
this.protocol = 31337;
|
||||
this.serviceCenterAddress = "GCM";
|
||||
this.replyPathPresent = true;
|
||||
this.pseudoSubject = "";
|
||||
this.sentTimestampMillis = sentTimestampMillis;
|
||||
this.serverTimestampMillis = serverTimestampMillis;
|
||||
this.receivedTimestampMillis = receivedTimestampMillis;
|
||||
this.push = true;
|
||||
this.subscriptionId = -1;
|
||||
this.expiresInMillis = expiresInMillis;
|
||||
this.unidentified = unidentified;
|
||||
this.groupId = groupId.orNull();
|
||||
this.serverGuid = serverGuid;
|
||||
}
|
||||
|
||||
public IncomingTextMessage(Parcel in) {
|
||||
this.message = in.readString();
|
||||
this.sender = in.readParcelable(IncomingTextMessage.class.getClassLoader());
|
||||
this.senderDeviceId = in.readInt();
|
||||
this.protocol = in.readInt();
|
||||
this.serviceCenterAddress = in.readString();
|
||||
this.replyPathPresent = (in.readInt() == 1);
|
||||
this.pseudoSubject = in.readString();
|
||||
this.sentTimestampMillis = in.readLong();
|
||||
this.serverTimestampMillis = in.readLong();
|
||||
this.groupId = GroupId.parseNullableOrThrow(in.readString());
|
||||
this.push = (in.readInt() == 1);
|
||||
this.subscriptionId = in.readInt();
|
||||
this.expiresInMillis = in.readLong();
|
||||
this.unidentified = in.readInt() == 1;
|
||||
this.serverGuid = in.readString();
|
||||
this.message = in.readString();
|
||||
this.sender = in.readParcelable(IncomingTextMessage.class.getClassLoader());
|
||||
this.senderDeviceId = in.readInt();
|
||||
this.protocol = in.readInt();
|
||||
this.serviceCenterAddress = in.readString();
|
||||
this.replyPathPresent = (in.readInt() == 1);
|
||||
this.pseudoSubject = in.readString();
|
||||
this.sentTimestampMillis = in.readLong();
|
||||
this.serverTimestampMillis = in.readLong();
|
||||
this.receivedTimestampMillis = in.readLong();
|
||||
this.groupId = GroupId.parseNullableOrThrow(in.readString());
|
||||
this.push = (in.readInt() == 1);
|
||||
this.subscriptionId = in.readInt();
|
||||
this.expiresInMillis = in.readLong();
|
||||
this.unidentified = in.readInt() == 1;
|
||||
this.serverGuid = in.readString();
|
||||
}
|
||||
|
||||
public IncomingTextMessage(IncomingTextMessage base, String newBody) {
|
||||
this.message = newBody;
|
||||
this.sender = base.getSender();
|
||||
this.senderDeviceId = base.getSenderDeviceId();
|
||||
this.protocol = base.getProtocol();
|
||||
this.serviceCenterAddress = base.getServiceCenterAddress();
|
||||
this.replyPathPresent = base.isReplyPathPresent();
|
||||
this.pseudoSubject = base.getPseudoSubject();
|
||||
this.sentTimestampMillis = base.getSentTimestampMillis();
|
||||
this.serverTimestampMillis = base.getServerTimestampMillis();
|
||||
this.groupId = base.getGroupId();
|
||||
this.push = base.isPush();
|
||||
this.subscriptionId = base.getSubscriptionId();
|
||||
this.expiresInMillis = base.getExpiresIn();
|
||||
this.unidentified = base.isUnidentified();
|
||||
this.serverGuid = base.getServerGuid();
|
||||
this.message = newBody;
|
||||
this.sender = base.getSender();
|
||||
this.senderDeviceId = base.getSenderDeviceId();
|
||||
this.protocol = base.getProtocol();
|
||||
this.serviceCenterAddress = base.getServiceCenterAddress();
|
||||
this.replyPathPresent = base.isReplyPathPresent();
|
||||
this.pseudoSubject = base.getPseudoSubject();
|
||||
this.sentTimestampMillis = base.getSentTimestampMillis();
|
||||
this.serverTimestampMillis = base.getServerTimestampMillis();
|
||||
this.receivedTimestampMillis = base.getReceivedTimestampMillis();
|
||||
this.groupId = base.getGroupId();
|
||||
this.push = base.isPush();
|
||||
this.subscriptionId = base.getSubscriptionId();
|
||||
this.expiresInMillis = base.getExpiresIn();
|
||||
this.unidentified = base.isUnidentified();
|
||||
this.serverGuid = base.getServerGuid();
|
||||
}
|
||||
|
||||
public IncomingTextMessage(List<IncomingTextMessage> fragments) {
|
||||
@@ -134,40 +140,42 @@ public class IncomingTextMessage implements Parcelable {
|
||||
body.append(message.getMessageBody());
|
||||
}
|
||||
|
||||
this.message = body.toString();
|
||||
this.sender = fragments.get(0).getSender();
|
||||
this.senderDeviceId = fragments.get(0).getSenderDeviceId();
|
||||
this.protocol = fragments.get(0).getProtocol();
|
||||
this.serviceCenterAddress = fragments.get(0).getServiceCenterAddress();
|
||||
this.replyPathPresent = fragments.get(0).isReplyPathPresent();
|
||||
this.pseudoSubject = fragments.get(0).getPseudoSubject();
|
||||
this.sentTimestampMillis = fragments.get(0).getSentTimestampMillis();
|
||||
this.serverTimestampMillis = fragments.get(0).getServerTimestampMillis();
|
||||
this.groupId = fragments.get(0).getGroupId();
|
||||
this.push = fragments.get(0).isPush();
|
||||
this.subscriptionId = fragments.get(0).getSubscriptionId();
|
||||
this.expiresInMillis = fragments.get(0).getExpiresIn();
|
||||
this.unidentified = fragments.get(0).isUnidentified();
|
||||
this.serverGuid = fragments.get(0).getServerGuid();
|
||||
this.message = body.toString();
|
||||
this.sender = fragments.get(0).getSender();
|
||||
this.senderDeviceId = fragments.get(0).getSenderDeviceId();
|
||||
this.protocol = fragments.get(0).getProtocol();
|
||||
this.serviceCenterAddress = fragments.get(0).getServiceCenterAddress();
|
||||
this.replyPathPresent = fragments.get(0).isReplyPathPresent();
|
||||
this.pseudoSubject = fragments.get(0).getPseudoSubject();
|
||||
this.sentTimestampMillis = fragments.get(0).getSentTimestampMillis();
|
||||
this.serverTimestampMillis = fragments.get(0).getServerTimestampMillis();
|
||||
this.receivedTimestampMillis = fragments.get(0).getReceivedTimestampMillis();
|
||||
this.groupId = fragments.get(0).getGroupId();
|
||||
this.push = fragments.get(0).isPush();
|
||||
this.subscriptionId = fragments.get(0).getSubscriptionId();
|
||||
this.expiresInMillis = fragments.get(0).getExpiresIn();
|
||||
this.unidentified = fragments.get(0).isUnidentified();
|
||||
this.serverGuid = fragments.get(0).getServerGuid();
|
||||
}
|
||||
|
||||
protected IncomingTextMessage(@NonNull RecipientId sender, @Nullable GroupId groupId)
|
||||
{
|
||||
this.message = "";
|
||||
this.sender = sender;
|
||||
this.senderDeviceId = SignalServiceAddress.DEFAULT_DEVICE_ID;
|
||||
this.protocol = 31338;
|
||||
this.serviceCenterAddress = "Outgoing";
|
||||
this.replyPathPresent = true;
|
||||
this.pseudoSubject = "";
|
||||
this.sentTimestampMillis = System.currentTimeMillis();
|
||||
this.serverTimestampMillis = sentTimestampMillis;
|
||||
this.groupId = groupId;
|
||||
this.push = true;
|
||||
this.subscriptionId = -1;
|
||||
this.expiresInMillis = 0;
|
||||
this.unidentified = false;
|
||||
this.serverGuid = null;
|
||||
this.message = "";
|
||||
this.sender = sender;
|
||||
this.senderDeviceId = SignalServiceAddress.DEFAULT_DEVICE_ID;
|
||||
this.protocol = 31338;
|
||||
this.serviceCenterAddress = "Outgoing";
|
||||
this.replyPathPresent = true;
|
||||
this.pseudoSubject = "";
|
||||
this.sentTimestampMillis = System.currentTimeMillis();
|
||||
this.serverTimestampMillis = sentTimestampMillis;
|
||||
this.receivedTimestampMillis = sentTimestampMillis;
|
||||
this.groupId = groupId;
|
||||
this.push = true;
|
||||
this.subscriptionId = -1;
|
||||
this.expiresInMillis = 0;
|
||||
this.unidentified = false;
|
||||
this.serverGuid = null;
|
||||
}
|
||||
|
||||
public int getSubscriptionId() {
|
||||
@@ -186,6 +194,10 @@ public class IncomingTextMessage implements Parcelable {
|
||||
return serverTimestampMillis;
|
||||
}
|
||||
|
||||
public long getReceivedTimestampMillis() {
|
||||
return receivedTimestampMillis;
|
||||
}
|
||||
|
||||
public String getPseudoSubject() {
|
||||
return pseudoSubject;
|
||||
}
|
||||
|
||||
@@ -74,7 +74,7 @@ public final class IdentityUtil {
|
||||
if (groupRecord.getMembers().contains(recipient.getId()) && groupRecord.isActive() && !groupRecord.isMms()) {
|
||||
|
||||
if (remote) {
|
||||
IncomingTextMessage incoming = new IncomingTextMessage(recipient.getId(), 1, time, -1, null, Optional.of(groupRecord.getId()), 0, false, null);
|
||||
IncomingTextMessage incoming = new IncomingTextMessage(recipient.getId(), 1, time, -1, time, null, Optional.of(groupRecord.getId()), 0, false, null);
|
||||
|
||||
if (verified) incoming = new IncomingIdentityVerifiedMessage(incoming);
|
||||
else incoming = new IncomingIdentityDefaultMessage(incoming);
|
||||
@@ -96,7 +96,7 @@ public final class IdentityUtil {
|
||||
}
|
||||
|
||||
if (remote) {
|
||||
IncomingTextMessage incoming = new IncomingTextMessage(recipient.getId(), 1, time, -1, null, Optional.absent(), 0, false, null);
|
||||
IncomingTextMessage incoming = new IncomingTextMessage(recipient.getId(), 1, time, -1, time, null, Optional.absent(), 0, false, null);
|
||||
|
||||
if (verified) incoming = new IncomingIdentityVerifiedMessage(incoming);
|
||||
else incoming = new IncomingIdentityDefaultMessage(incoming);
|
||||
@@ -125,7 +125,7 @@ public final class IdentityUtil {
|
||||
|
||||
while ((groupRecord = reader.getNext()) != null) {
|
||||
if (groupRecord.getMembers().contains(recipientId) && groupRecord.isActive()) {
|
||||
IncomingTextMessage incoming = new IncomingTextMessage(recipientId, 1, time, time, null, Optional.of(groupRecord.getId()), 0, false, null);
|
||||
IncomingTextMessage incoming = new IncomingTextMessage(recipientId, 1, time, time, time, null, Optional.of(groupRecord.getId()), 0, false, null);
|
||||
IncomingIdentityUpdateMessage groupUpdate = new IncomingIdentityUpdateMessage(incoming);
|
||||
|
||||
smsDatabase.insertMessageInbox(groupUpdate);
|
||||
@@ -133,7 +133,7 @@ public final class IdentityUtil {
|
||||
}
|
||||
}
|
||||
|
||||
IncomingTextMessage incoming = new IncomingTextMessage(recipientId, 1, time, -1, null, Optional.absent(), 0, false, null);
|
||||
IncomingTextMessage incoming = new IncomingTextMessage(recipientId, 1, time, -1, time, null, Optional.absent(), 0, false, null);
|
||||
IncomingIdentityUpdateMessage individualUpdate = new IncomingIdentityUpdateMessage(incoming);
|
||||
Optional<InsertResult> insertResult = smsDatabase.insertMessageInbox(individualUpdate);
|
||||
|
||||
|
||||
@@ -2459,6 +2459,8 @@
|
||||
<string name="preferences__internal_click_to_delete_all_sharing_state" translatable="false">Click to delete all sharing state</string>
|
||||
<string name="preferences__internal_remove_two_person_minimum" translatable="false">Remove 2 person minimum</string>
|
||||
<string name="preferences__internal_remove_the_requirement_that_you_need" translatable="false">Remove the requirement that you need at least 2 recipients to use sender key.</string>
|
||||
<string name="preferences__internal_delay_resends" translatable="false">Delay resends</string>
|
||||
<string name="preferences__internal_delay_resending_messages_in_response_to_retry_receipts" translatable="false">Delay resending messages in response to retry receipts by 10 seconds.</string>
|
||||
<string name="preferences__internal_calling" translatable="false">Group call server</string>
|
||||
<string name="preferences__internal_calling_default" translatable="false">Default</string>
|
||||
<string name="preferences__internal_calling_s_server" translatable="false">%1$s server</string>
|
||||
|
||||
@@ -1753,7 +1753,7 @@ public class SignalServiceMessageSender {
|
||||
.collect(Collectors.toList());
|
||||
|
||||
Set<String> successUuids = successes.stream().map(a -> a.getUuid().get().toString()).collect(Collectors.toSet());
|
||||
Set<SignalProtocolAddress> successAddresses = destinations.stream().filter(a -> successUuids.contains(a.getName())).collect(Collectors.toSet());;
|
||||
Set<SignalProtocolAddress> successAddresses = destinations.stream().filter(a -> successUuids.contains(a.getName())).collect(Collectors.toSet());
|
||||
|
||||
store.markSenderKeySharedWith(distributionId, successAddresses);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user