mirror of
https://github.com/signalapp/Signal-Android.git
synced 2025-12-22 20:18:36 +00:00
Clean up GSE usage and remove combined-UAK fallback for multi-recipient send.
This commit is contained in:
committed by
Michelle Tang
parent
99fb70c20c
commit
7499bd77b4
@@ -62,7 +62,6 @@ import org.thoughtcrime.securesms.jobs.CheckServiceReachabilityJob;
|
||||
import org.thoughtcrime.securesms.jobs.DownloadLatestEmojiDataJob;
|
||||
import org.thoughtcrime.securesms.jobs.EmojiSearchIndexDownloadJob;
|
||||
import org.thoughtcrime.securesms.jobs.FcmRefreshJob;
|
||||
import org.thoughtcrime.securesms.jobs.RetryPendingSendsJob;
|
||||
import org.thoughtcrime.securesms.jobs.FontDownloaderJob;
|
||||
import org.thoughtcrime.securesms.jobs.GroupRingCleanupJob;
|
||||
import org.thoughtcrime.securesms.jobs.GroupV2UpdateSelfProfileKeyJob;
|
||||
@@ -76,13 +75,13 @@ import org.thoughtcrime.securesms.jobs.RefreshSvrCredentialsJob;
|
||||
import org.thoughtcrime.securesms.jobs.RestoreOptimizedMediaJob;
|
||||
import org.thoughtcrime.securesms.jobs.RetrieveProfileJob;
|
||||
import org.thoughtcrime.securesms.jobs.RetrieveRemoteAnnouncementsJob;
|
||||
import org.thoughtcrime.securesms.jobs.RetryPendingSendsJob;
|
||||
import org.thoughtcrime.securesms.jobs.StoryOnboardingDownloadJob;
|
||||
import org.thoughtcrime.securesms.keyvalue.KeepMessagesDuration;
|
||||
import org.thoughtcrime.securesms.keyvalue.SignalStore;
|
||||
import org.thoughtcrime.securesms.logging.CustomSignalProtocolLogger;
|
||||
import org.thoughtcrime.securesms.logging.PersistentLogger;
|
||||
import org.thoughtcrime.securesms.messageprocessingalarm.RoutineMessageFetchReceiver;
|
||||
import org.thoughtcrime.securesms.messages.GroupSendEndorsementInternalNotifier;
|
||||
import org.thoughtcrime.securesms.migrations.ApplicationMigrations;
|
||||
import org.thoughtcrime.securesms.mms.SignalGlideComponents;
|
||||
import org.thoughtcrime.securesms.mms.SignalGlideModule;
|
||||
@@ -227,7 +226,6 @@ public class ApplicationContext extends Application implements AppForegroundObse
|
||||
.addPostRender(GroupRingCleanupJob::enqueue)
|
||||
.addPostRender(LinkedDeviceInactiveCheckJob::enqueueIfNecessary)
|
||||
.addPostRender(() -> ActiveCallManager.clearNotifications(this))
|
||||
.addPostRender(() -> GroupSendEndorsementInternalNotifier.init())
|
||||
.addPostRender(RestoreOptimizedMediaJob::enqueueIfNecessary)
|
||||
.addPostRender(RetryPendingSendsJob::enqueueForAll)
|
||||
.execute();
|
||||
|
||||
@@ -14,12 +14,10 @@ import androidx.core.app.NotificationManagerCompat
|
||||
import org.signal.core.util.PendingIntentFlags
|
||||
import org.signal.core.util.logging.Log
|
||||
import org.thoughtcrime.securesms.R
|
||||
import org.thoughtcrime.securesms.dependencies.AppDependencies
|
||||
import org.thoughtcrime.securesms.logsubmit.SubmitDebugLogActivity
|
||||
import org.thoughtcrime.securesms.notifications.NotificationChannels
|
||||
import org.thoughtcrime.securesms.notifications.NotificationIds
|
||||
import org.thoughtcrime.securesms.util.RemoteConfig
|
||||
import org.whispersystems.signalservice.api.crypto.SealedSenderAccess
|
||||
import kotlin.time.Duration
|
||||
import kotlin.time.Duration.Companion.milliseconds
|
||||
import kotlin.time.Duration.Companion.minutes
|
||||
@@ -27,7 +25,7 @@ import kotlin.time.Duration.Companion.minutes
|
||||
/**
|
||||
* Internal user only notifier when "bad" things happen with group send endorsement sends.
|
||||
*/
|
||||
object GroupSendEndorsementInternalNotifier : SealedSenderAccess.FallbackListener {
|
||||
object GroupSendEndorsementInternalNotifier {
|
||||
|
||||
private const val TAG = "GSENotifier"
|
||||
|
||||
@@ -36,27 +34,14 @@ object GroupSendEndorsementInternalNotifier : SealedSenderAccess.FallbackListene
|
||||
|
||||
private var lastMissingNotify: Duration = 0.milliseconds
|
||||
|
||||
private var lastFallbackNotify: Duration = 0.milliseconds
|
||||
|
||||
@JvmStatic
|
||||
fun init() {
|
||||
if (RemoteConfig.internalUser) {
|
||||
SealedSenderAccess.fallbackListener = this
|
||||
}
|
||||
fun maybePostGroupSendFallbackError(context: Context) {
|
||||
if (!RemoteConfig.internalUser) {
|
||||
return
|
||||
}
|
||||
|
||||
override fun onAccessToTokenFallback() {
|
||||
Log.w(TAG, "Fallback from access key to token", Throwable())
|
||||
postFallbackError(AppDependencies.application)
|
||||
}
|
||||
Log.internal().w(TAG, "Group send with GSE failed, GSE was likely out of date or incorrect", Throwable())
|
||||
|
||||
override fun onTokenToAccessFallback(hasAccessKeyFallback: Boolean) {
|
||||
Log.w(TAG, "Fallback from token hasAccessKey=$hasAccessKeyFallback", Throwable())
|
||||
postFallbackError(AppDependencies.application)
|
||||
}
|
||||
|
||||
@JvmStatic
|
||||
fun postGroupSendFallbackError(context: Context) {
|
||||
val now = System.currentTimeMillis().milliseconds
|
||||
if (lastGroupSendNotify + 5.minutes > now && skippedGroupSendNotifies < 5) {
|
||||
skippedGroupSendNotifies++
|
||||
@@ -65,8 +50,8 @@ object GroupSendEndorsementInternalNotifier : SealedSenderAccess.FallbackListene
|
||||
|
||||
val notification: Notification = NotificationCompat.Builder(context, NotificationChannels.getInstance().FAILURES)
|
||||
.setSmallIcon(R.drawable.ic_notification)
|
||||
.setContentTitle("[Internal-only] GSE failed for group send")
|
||||
.setContentText("Please tap to send a debug log")
|
||||
.setContentTitle("[Internal-only] Group send failure (GSE)")
|
||||
.setContentText("Please tap to get a debug log")
|
||||
.setContentIntent(PendingIntent.getActivity(context, 0, Intent(context, SubmitDebugLogActivity::class.java), PendingIntentFlags.mutable()))
|
||||
.build()
|
||||
|
||||
@@ -77,7 +62,13 @@ object GroupSendEndorsementInternalNotifier : SealedSenderAccess.FallbackListene
|
||||
}
|
||||
|
||||
@JvmStatic
|
||||
fun postMissingGroupSendEndorsement(context: Context) {
|
||||
fun maybePostMissingGroupSendEndorsement(context: Context) {
|
||||
if (!RemoteConfig.internalUser) {
|
||||
return
|
||||
}
|
||||
|
||||
Log.internal().w(TAG, "GSE missing for recipient", Throwable())
|
||||
|
||||
val now = System.currentTimeMillis().milliseconds
|
||||
if (lastMissingNotify + 5.minutes > now) {
|
||||
return
|
||||
@@ -85,8 +76,8 @@ object GroupSendEndorsementInternalNotifier : SealedSenderAccess.FallbackListene
|
||||
|
||||
val notification: Notification = NotificationCompat.Builder(context, NotificationChannels.getInstance().FAILURES)
|
||||
.setSmallIcon(R.drawable.ic_notification)
|
||||
.setContentTitle("[Internal-only] GSE missing for recipient")
|
||||
.setContentText("Please tap to send a debug log")
|
||||
.setContentTitle("[Internal-only] Missing recipient (GSE)")
|
||||
.setContentText("Please tap to get a debug log")
|
||||
.setContentIntent(PendingIntent.getActivity(context, 0, Intent(context, SubmitDebugLogActivity::class.java), PendingIntentFlags.mutable()))
|
||||
.build()
|
||||
|
||||
@@ -94,23 +85,4 @@ object GroupSendEndorsementInternalNotifier : SealedSenderAccess.FallbackListene
|
||||
|
||||
lastMissingNotify = now
|
||||
}
|
||||
|
||||
@JvmStatic
|
||||
fun postFallbackError(context: Context) {
|
||||
val now = System.currentTimeMillis().milliseconds
|
||||
if (lastFallbackNotify + 5.minutes > now) {
|
||||
return
|
||||
}
|
||||
|
||||
val notification: Notification = NotificationCompat.Builder(context, NotificationChannels.getInstance().FAILURES)
|
||||
.setSmallIcon(R.drawable.ic_notification)
|
||||
.setContentTitle("[Internal-only] GSE fallback occurred!")
|
||||
.setContentText("Please tap to send a debug log")
|
||||
.setContentIntent(PendingIntent.getActivity(context, 0, Intent(context, SubmitDebugLogActivity::class.java), PendingIntentFlags.mutable()))
|
||||
.build()
|
||||
|
||||
NotificationManagerCompat.from(context).notify(NotificationIds.INTERNAL_ERROR, notification)
|
||||
|
||||
lastFallbackNotify = now
|
||||
}
|
||||
}
|
||||
|
||||
@@ -14,8 +14,8 @@ import org.signal.libsignal.protocol.NoSessionException;
|
||||
import org.signal.libsignal.zkgroup.groups.GroupSecretParams;
|
||||
import org.signal.libsignal.zkgroup.groupsend.GroupSendEndorsement;
|
||||
import org.signal.libsignal.zkgroup.groupsend.GroupSendFullToken;
|
||||
import org.thoughtcrime.securesms.crypto.SenderKeyUtil;
|
||||
import org.thoughtcrime.securesms.crypto.SealedSenderAccessUtil;
|
||||
import org.thoughtcrime.securesms.crypto.SenderKeyUtil;
|
||||
import org.thoughtcrime.securesms.database.MessageSendLogTables;
|
||||
import org.thoughtcrime.securesms.database.SignalDatabase;
|
||||
import org.thoughtcrime.securesms.database.model.DistributionListId;
|
||||
@@ -34,7 +34,6 @@ import org.thoughtcrime.securesms.recipients.RecipientUtil;
|
||||
import org.thoughtcrime.securesms.util.RecipientAccessList;
|
||||
import org.thoughtcrime.securesms.util.RemoteConfig;
|
||||
import org.thoughtcrime.securesms.util.SignalLocalMetrics;
|
||||
import org.thoughtcrime.securesms.util.TextSecurePreferences;
|
||||
import org.thoughtcrime.securesms.util.Util;
|
||||
import org.whispersystems.signalservice.api.CancelationException;
|
||||
import org.whispersystems.signalservice.api.SignalServiceMessageSender;
|
||||
@@ -161,11 +160,11 @@ public final class GroupSendUtil {
|
||||
* Handles all of the logic of sending to a group. Will do sender key sends and legacy 1:1 sends as-needed, and give you back a list of
|
||||
* {@link SendMessageResult}s just like we're used to.
|
||||
*
|
||||
* @param groupId The groupId of the group you're sending to, or null if you're sending to a collection of recipients not joined by a group.
|
||||
* @param groupId The groupId of the group you're sending to
|
||||
*/
|
||||
@WorkerThread
|
||||
public static List<SendMessageResult> sendCallMessage(@NonNull Context context,
|
||||
@Nullable GroupId.V2 groupId,
|
||||
@NonNull GroupId.V2 groupId,
|
||||
@NonNull List<Recipient> allTargets,
|
||||
@NonNull SignalServiceCallMessage message)
|
||||
throws IOException, UntrustedIdentityException
|
||||
@@ -292,9 +291,11 @@ public final class GroupSendUtil {
|
||||
groupSendEndorsementRecords = SignalDatabase.groups().getGroupSendEndorsements(groupId);
|
||||
} catch (GroupChangeException | IOException e) {
|
||||
if (groupSendEndorsementExpiration == 0) {
|
||||
Log.w(TAG, "Unable to update group send endorsements, falling back to access key", e);
|
||||
Log.w(TAG, "Unable to update group send endorsements, falling back to legacy", e);
|
||||
useGroupSendEndorsements = false;
|
||||
groupSendEndorsementRecords = new GroupSendEndorsementRecords(Collections.emptyMap());
|
||||
|
||||
GroupSendEndorsementInternalNotifier.maybePostGroupSendFallbackError(context);
|
||||
} else {
|
||||
Log.w(TAG, "Unable to update group send endorsements, using what we have", e);
|
||||
}
|
||||
@@ -308,49 +309,38 @@ public final class GroupSendUtil {
|
||||
List<Recipient> senderKeyTargets = new LinkedList<>();
|
||||
List<Recipient> legacyTargets = new LinkedList<>();
|
||||
|
||||
// Determine recipients that can be sent to via sender key vs must use legacy fan-out
|
||||
if (distributionId == null) {
|
||||
Log.i(TAG, "No DistributionId. Using legacy.");
|
||||
legacyTargets.addAll(registeredTargets);
|
||||
} else if (isStorySend) {
|
||||
Log.i(TAG, "Sending a story. Using sender key for all " + allTargets.size() + " recipients.");
|
||||
senderKeyTargets.addAll(registeredTargets);
|
||||
} else if (!useGroupSendEndorsements) {
|
||||
Log.i(TAG, "No group send endorsements, using legacy for all " + allTargets.size() + " recipients.");
|
||||
legacyTargets.addAll(registeredTargets);
|
||||
} else {
|
||||
for (Recipient recipient : registeredTargets) {
|
||||
Optional<UnidentifiedAccess> access = recipients.getAccessPair(recipient.getId());
|
||||
boolean validMembership = groupId == null || (groupRecord.isPresent() && groupRecord.get().getMembers().contains(recipient.getId()));
|
||||
|
||||
if (useGroupSendEndorsements) {
|
||||
boolean validMembership = groupRecord.get().getMembers().contains(recipient.getId());
|
||||
GroupSendEndorsement groupSendEndorsement = groupSendEndorsementRecords.getEndorsement(recipient.getId());
|
||||
|
||||
if (groupSendEndorsement != null && recipient.getHasAci() && validMembership) {
|
||||
senderKeyTargets.add(recipient);
|
||||
} else {
|
||||
legacyTargets.add(recipient);
|
||||
if (validMembership) {
|
||||
Log.w(TAG, "Should be using group send endorsement but not found for " + recipient.getId());
|
||||
if (RemoteConfig.internalUser()) {
|
||||
GroupSendEndorsementInternalNotifier.postMissingGroupSendEndorsement(context);
|
||||
GroupSendEndorsementInternalNotifier.maybePostMissingGroupSendEndorsement(context);
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// Use sender key
|
||||
if (recipient.getHasServiceId() &&
|
||||
access.isPresent() &&
|
||||
validMembership)
|
||||
{
|
||||
senderKeyTargets.add(recipient);
|
||||
} else {
|
||||
legacyTargets.add(recipient);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (distributionId == null) {
|
||||
Log.i(TAG, "No DistributionId. Using legacy.");
|
||||
legacyTargets.addAll(senderKeyTargets);
|
||||
senderKeyTargets.clear();
|
||||
} else if (isStorySend) {
|
||||
Log.i(TAG, "Sending a story. Using sender key for all " + allTargets.size() + " recipients.");
|
||||
senderKeyTargets.clear();
|
||||
senderKeyTargets.addAll(registeredTargets);
|
||||
legacyTargets.clear();
|
||||
} else if (SignalStore.internal().getRemoveSenderKeyMinimum()) {
|
||||
// Enforce minimum number of sender key destinations
|
||||
if (SignalStore.internal().getRemoveSenderKeyMinimum()) {
|
||||
Log.i(TAG, "Sender key minimum removed. Using for " + senderKeyTargets.size() + " recipients.");
|
||||
} else if (senderKeyTargets.size() < 2) {
|
||||
Log.i(TAG, "Too few sender-key-capable users (" + senderKeyTargets.size() + "). Doing all legacy sends.");
|
||||
} else if (senderKeyTargets.size() < 2 && !isStorySend) {
|
||||
Log.i(TAG, "Too few sender-key-capable users (" + senderKeyTargets.size() + ") for non-story send. Doing all legacy sends.");
|
||||
legacyTargets.addAll(senderKeyTargets);
|
||||
senderKeyTargets.clear();
|
||||
} else {
|
||||
@@ -431,8 +421,8 @@ public final class GroupSendUtil {
|
||||
Log.w(TAG, "Someone had a bad UD header. Falling back to legacy sends.", e);
|
||||
legacyTargets.addAll(senderKeyTargets);
|
||||
|
||||
if (useGroupSendEndorsements && RemoteConfig.internalUser()) {
|
||||
GroupSendEndorsementInternalNotifier.postGroupSendFallbackError(context);
|
||||
if (useGroupSendEndorsements) {
|
||||
GroupSendEndorsementInternalNotifier.maybePostGroupSendFallbackError(context);
|
||||
}
|
||||
} catch (NoSessionException e) {
|
||||
Log.w(TAG, "No session. Falling back to legacy sends.", e);
|
||||
@@ -712,6 +702,8 @@ public final class GroupSendUtil {
|
||||
@Nullable PartialSendBatchCompleteListener partialListener)
|
||||
throws NoSessionException, UntrustedIdentityException, InvalidKeyException, IOException, InvalidRegistrationIdException
|
||||
{
|
||||
Preconditions.checkNotNull(groupSendEndorsements, "GSEs must be non-null for non-story sender key send.");
|
||||
|
||||
messageSender.sendGroupTyping(distributionId, targets, access, groupSendEndorsements, message);
|
||||
List<SendMessageResult> results = targets.stream().map(a -> SendMessageResult.success(a, Collections.emptyList(), true, false, -1, Optional.empty())).collect(Collectors.toList());
|
||||
|
||||
@@ -780,6 +772,8 @@ public final class GroupSendUtil {
|
||||
@Nullable PartialSendBatchCompleteListener partialSendListener)
|
||||
throws NoSessionException, UntrustedIdentityException, InvalidKeyException, IOException, InvalidRegistrationIdException
|
||||
{
|
||||
Preconditions.checkNotNull(groupSendEndorsements, "GSEs must be non-null for non-story sender key send.");
|
||||
|
||||
return messageSender.sendCallMessage(distributionId, targets, access, groupSendEndorsements, message, partialSendListener);
|
||||
}
|
||||
|
||||
|
||||
@@ -6,6 +6,7 @@
|
||||
package org.whispersystems.signalservice.api;
|
||||
|
||||
import org.signal.core.util.Base64;
|
||||
import org.signal.libsignal.metadata.certificate.SenderCertificate;
|
||||
import org.signal.libsignal.protocol.IdentityKey;
|
||||
import org.signal.libsignal.protocol.IdentityKeyPair;
|
||||
import org.signal.libsignal.protocol.InvalidKeyException;
|
||||
@@ -138,6 +139,7 @@ import java.util.Iterator;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
import java.util.Optional;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.ExecutorService;
|
||||
@@ -286,7 +288,7 @@ public class SignalServiceMessageSender {
|
||||
public void sendGroupTyping(DistributionId distributionId,
|
||||
List<SignalServiceAddress> recipients,
|
||||
List<UnidentifiedAccess> unidentifiedAccess,
|
||||
@Nullable GroupSendEndorsements groupSendEndorsements,
|
||||
@Nonnull GroupSendEndorsements groupSendEndorsements,
|
||||
SignalServiceTypingMessage message)
|
||||
throws IOException, UntrustedIdentityException, InvalidKeyException, NoSessionException, InvalidRegistrationIdException
|
||||
{
|
||||
@@ -388,7 +390,7 @@ public class SignalServiceMessageSender {
|
||||
public List<SendMessageResult> sendCallMessage(DistributionId distributionId,
|
||||
List<SignalServiceAddress> recipients,
|
||||
List<UnidentifiedAccess> unidentifiedAccess,
|
||||
@Nullable GroupSendEndorsements groupSendEndorsements,
|
||||
@Nonnull GroupSendEndorsements groupSendEndorsements,
|
||||
SignalServiceCallMessage message,
|
||||
PartialSendBatchCompleteListener partialListener)
|
||||
throws IOException, UntrustedIdentityException, InvalidKeyException, NoSessionException, InvalidRegistrationIdException
|
||||
@@ -2356,6 +2358,7 @@ public class SignalServiceMessageSender {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
|
||||
Preconditions.checkArgument(groupSendEndorsements != null || story, "[" + timestamp + "] GSE is null and not sending a story");
|
||||
Preconditions.checkArgument(recipients.size() == unidentifiedAccess.size(), "[" + timestamp + "] Unidentified access mismatch!");
|
||||
|
||||
Map<ServiceId, UnidentifiedAccess> accessBySid = new HashMap<>();
|
||||
@@ -2366,7 +2369,8 @@ public class SignalServiceMessageSender {
|
||||
accessBySid.put(addressIterator.next().getServiceId(), accessIterator.next());
|
||||
}
|
||||
|
||||
SealedSenderAccess sealedSenderAccess = SealedSenderAccess.forGroupSend(groupSendEndorsements, unidentifiedAccess, story);
|
||||
SenderCertificate senderCertificate = unidentifiedAccess.stream().filter(Objects::nonNull).findFirst().map(UnidentifiedAccess::getUnidentifiedCertificate).orElse(null);
|
||||
SealedSenderAccess sealedSenderAccess = SealedSenderAccess.forGroupSend(senderCertificate, groupSendEndorsements, story);
|
||||
|
||||
for (int i = 0; i < RETRY_COUNT; i++) {
|
||||
GroupTargetInfo targetInfo = buildGroupTargetInfo(recipients);
|
||||
@@ -2493,13 +2497,9 @@ public class SignalServiceMessageSender {
|
||||
handleStaleDevices(address, stale.getDevices());
|
||||
}
|
||||
} catch (InvalidUnidentifiedAccessHeaderException e) {
|
||||
sealedSenderAccess = sealedSenderAccess.switchToFallback();
|
||||
if (sealedSenderAccess != null) {
|
||||
Log.w(TAG, "[sendGroupMessage][" + timestamp + "] Handling invalid group send endorsements. (" + e.getMessage() + ")");
|
||||
} else {
|
||||
Log.w(TAG, "[sendGroupMessage][" + timestamp + "] Invalid access header. (" + e.getMessage() + ")");
|
||||
throw e;
|
||||
}
|
||||
}
|
||||
|
||||
Log.w(TAG, "[sendGroupMessage][" + timestamp + "] Attempt failed (i = " + i + ")");
|
||||
}
|
||||
|
||||
@@ -9,7 +9,6 @@ import org.signal.core.util.Base64
|
||||
import org.signal.libsignal.metadata.certificate.SenderCertificate
|
||||
import org.signal.libsignal.zkgroup.groupsend.GroupSendFullToken
|
||||
import org.whispersystems.signalservice.api.groupsv2.GroupSendEndorsements
|
||||
import org.whispersystems.util.ByteArrayUtil
|
||||
|
||||
/**
|
||||
* Provides single interface for the various ways to send via sealed sender.
|
||||
@@ -25,6 +24,8 @@ sealed class SealedSenderAccess {
|
||||
|
||||
abstract fun switchToFallback(): SealedSenderAccess?
|
||||
|
||||
open fun applyHeader(): Boolean = true
|
||||
|
||||
/**
|
||||
* For sending to an single recipient using group send endorsement/token first and then fallback to
|
||||
* access key if available.
|
||||
@@ -39,7 +40,6 @@ sealed class SealedSenderAccess {
|
||||
override val headerValue: String by lazy { Base64.encodeWithPadding(groupSendToken.serialize()) }
|
||||
|
||||
override fun switchToFallback(): SealedSenderAccess? {
|
||||
fallbackListener?.onTokenToAccessFallback(unidentifiedAccess != null)
|
||||
return if (unidentifiedAccess != null) {
|
||||
IndividualUnidentifiedAccessFirst(unidentifiedAccess)
|
||||
} else {
|
||||
@@ -66,7 +66,6 @@ sealed class SealedSenderAccess {
|
||||
override fun switchToFallback(): SealedSenderAccess? {
|
||||
val groupSendToken = createGroupSendToken?.create()
|
||||
return if (groupSendToken != null) {
|
||||
fallbackListener?.onAccessToTokenFallback()
|
||||
IndividualGroupSendTokenFirst(groupSendToken, senderCertificate)
|
||||
} else {
|
||||
null
|
||||
@@ -92,27 +91,15 @@ sealed class SealedSenderAccess {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* For sending to a "group" of recipients using access keys.
|
||||
*/
|
||||
class GroupUnidentifiedAccess(
|
||||
private val unidentifiedAccess: List<UnidentifiedAccess>,
|
||||
override val senderCertificate: SenderCertificate = unidentifiedAccess.first().unidentifiedCertificate
|
||||
) : SealedSenderAccess() {
|
||||
|
||||
override val headerName: String = "Unidentified-Access-Key"
|
||||
override val headerValue: String by lazy {
|
||||
var joinedUnidentifiedAccess = ByteArray(16)
|
||||
for (access in unidentifiedAccess) {
|
||||
joinedUnidentifiedAccess = ByteArrayUtil.xor(joinedUnidentifiedAccess, access.unidentifiedAccessKey)
|
||||
}
|
||||
|
||||
Base64.encodeWithPadding(joinedUnidentifiedAccess)
|
||||
}
|
||||
class StorySendNoop(override val senderCertificate: SenderCertificate) : SealedSenderAccess() {
|
||||
override val headerName: String = ""
|
||||
override val headerValue: String = ""
|
||||
|
||||
override fun switchToFallback(): SealedSenderAccess? {
|
||||
return null
|
||||
}
|
||||
|
||||
override fun applyHeader(): Boolean = false
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -122,14 +109,7 @@ sealed class SealedSenderAccess {
|
||||
fun create(): GroupSendFullToken?
|
||||
}
|
||||
|
||||
interface FallbackListener {
|
||||
fun onAccessToTokenFallback()
|
||||
fun onTokenToAccessFallback(hasAccessKeyFallback: Boolean)
|
||||
}
|
||||
|
||||
companion object {
|
||||
var fallbackListener: FallbackListener? = null
|
||||
|
||||
@JvmField
|
||||
val NONE: SealedSenderAccess? = null
|
||||
|
||||
@@ -178,12 +158,12 @@ sealed class SealedSenderAccess {
|
||||
}
|
||||
|
||||
@JvmStatic
|
||||
fun forGroupSend(groupSendEndorsements: GroupSendEndorsements?, unidentifiedAccess: List<UnidentifiedAccess>, forStory: Boolean): SealedSenderAccess {
|
||||
return if (groupSendEndorsements != null && !forStory) {
|
||||
GroupGroupSendToken(groupSendEndorsements)
|
||||
} else {
|
||||
GroupUnidentifiedAccess(unidentifiedAccess)
|
||||
fun forGroupSend(senderCertificate: SenderCertificate?, groupSendEndorsements: GroupSendEndorsements?, forStory: Boolean): SealedSenderAccess {
|
||||
if (forStory) {
|
||||
return StorySendNoop(senderCertificate!!)
|
||||
}
|
||||
|
||||
return GroupGroupSendToken(groupSendEndorsements!!)
|
||||
}
|
||||
|
||||
@JvmStatic
|
||||
|
||||
@@ -287,7 +287,9 @@ sealed class SignalWebSocket(
|
||||
class UnauthenticatedWebSocket(connectionFactory: WebSocketFactory, canConnect: CanConnect, sleepTimer: SleepTimer, disconnectTimeoutMs: Long) : SignalWebSocket(connectionFactory, canConnect, sleepTimer, disconnectTimeoutMs.milliseconds) {
|
||||
fun request(requestMessage: WebSocketRequestMessage, sealedSenderAccess: SealedSenderAccess): Single<WebsocketResponse> {
|
||||
val headers: MutableList<String> = requestMessage.headers.toMutableList()
|
||||
if (sealedSenderAccess.applyHeader()) {
|
||||
headers.add(sealedSenderAccess.header)
|
||||
}
|
||||
|
||||
val message = requestMessage
|
||||
.newBuilder()
|
||||
|
||||
Reference in New Issue
Block a user