diff --git a/app/src/main/java/org/thoughtcrime/securesms/dependencies/ApplicationDependencyProvider.java b/app/src/main/java/org/thoughtcrime/securesms/dependencies/ApplicationDependencyProvider.java index aae6fd5b74..da6dd27118 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/dependencies/ApplicationDependencyProvider.java +++ b/app/src/main/java/org/thoughtcrime/securesms/dependencies/ApplicationDependencyProvider.java @@ -50,6 +50,7 @@ import org.thoughtcrime.securesms.shakereport.ShakeToReport; import org.thoughtcrime.securesms.util.AlarmSleepTimer; import org.thoughtcrime.securesms.util.ByteUnit; import org.thoughtcrime.securesms.util.EarlyMessageCache; +import org.thoughtcrime.securesms.util.FeatureFlags; import org.thoughtcrime.securesms.util.FrameRateTracker; import org.thoughtcrime.securesms.util.TextSecurePreferences; import org.whispersystems.libsignal.util.guava.Optional; @@ -94,7 +95,8 @@ public class ApplicationDependencyProvider implements ApplicationDependencies.Pr return new SignalServiceAccountManager(networkAccess.getConfiguration(context), new DynamicCredentialsProvider(context), BuildConfig.SIGNAL_AGENT, - provideGroupsV2Operations()); + provideGroupsV2Operations(), + FeatureFlags.okHttpAutomaticRetry()); } @Override @@ -109,7 +111,8 @@ public class ApplicationDependencyProvider implements ApplicationDependencies.Pr Optional.of(new SecurityEventListener(context)), provideClientZkOperations().getProfileOperations(), SignalExecutors.newCachedBoundedExecutor("signal-messages", 1, 16), - ByteUnit.KILOBYTES.toBytes(512)); + ByteUnit.KILOBYTES.toBytes(512), + FeatureFlags.okHttpAutomaticRetry()); } @Override @@ -121,7 +124,8 @@ public class ApplicationDependencyProvider implements ApplicationDependencies.Pr BuildConfig.SIGNAL_AGENT, new PipeConnectivityListener(), sleepTimer, - provideClientZkOperations().getProfileOperations()); + provideClientZkOperations().getProfileOperations(), + FeatureFlags.okHttpAutomaticRetry()); } @Override diff --git a/app/src/main/java/org/thoughtcrime/securesms/push/AccountManagerFactory.java b/app/src/main/java/org/thoughtcrime/securesms/push/AccountManagerFactory.java index 8c0ce6caf4..5ce93c9eaa 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/push/AccountManagerFactory.java +++ b/app/src/main/java/org/thoughtcrime/securesms/push/AccountManagerFactory.java @@ -9,6 +9,7 @@ import com.google.android.gms.security.ProviderInstaller; import org.signal.core.util.concurrent.SignalExecutors; import org.signal.core.util.logging.Log; import org.thoughtcrime.securesms.BuildConfig; +import org.thoughtcrime.securesms.util.FeatureFlags; import org.whispersystems.signalservice.api.SignalServiceAccountManager; import java.util.UUID; @@ -33,7 +34,7 @@ public class AccountManagerFactory { } return new SignalServiceAccountManager(new SignalServiceNetworkAccess(context).getConfiguration(number), - uuid, number, password, BuildConfig.SIGNAL_AGENT); + uuid, number, password, BuildConfig.SIGNAL_AGENT, FeatureFlags.okHttpAutomaticRetry()); } /** @@ -54,7 +55,7 @@ public class AccountManagerFactory { } return new SignalServiceAccountManager(new SignalServiceNetworkAccess(context).getConfiguration(number), - null, number, password, BuildConfig.SIGNAL_AGENT); + null, number, password, BuildConfig.SIGNAL_AGENT, FeatureFlags.okHttpAutomaticRetry()); } } diff --git a/app/src/main/java/org/thoughtcrime/securesms/util/FeatureFlags.java b/app/src/main/java/org/thoughtcrime/securesms/util/FeatureFlags.java index 030171e721..c9164d51fa 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/util/FeatureFlags.java +++ b/app/src/main/java/org/thoughtcrime/securesms/util/FeatureFlags.java @@ -70,6 +70,7 @@ public final class FeatureFlags { private static final String AUTOMATIC_SESSION_RESET = "android.automaticSessionReset.2"; private static final String AUTOMATIC_SESSION_INTERVAL = "android.automaticSessionResetInterval"; private static final String DEFAULT_MAX_BACKOFF = "android.defaultMaxBackoff"; + private static final String OKHTTP_AUTOMATIC_RETRY = "android.okhttpAutomaticRetry"; /** * We will only store remote values for flags in this set. If you want a flag to be controllable @@ -96,7 +97,8 @@ public final class FeatureFlags { GROUP_NAME_MAX_LENGTH, AUTOMATIC_SESSION_RESET, AUTOMATIC_SESSION_INTERVAL, - DEFAULT_MAX_BACKOFF + DEFAULT_MAX_BACKOFF, + OKHTTP_AUTOMATIC_RETRY ); @VisibleForTesting @@ -133,7 +135,8 @@ public final class FeatureFlags { GROUP_NAME_MAX_LENGTH, AUTOMATIC_SESSION_RESET, AUTOMATIC_SESSION_INTERVAL, - DEFAULT_MAX_BACKOFF + DEFAULT_MAX_BACKOFF, + OKHTTP_AUTOMATIC_RETRY ); /** @@ -308,6 +311,11 @@ public final class FeatureFlags { return getInteger(DEFAULT_MAX_BACKOFF, 60); } + /** Whether or not to allow automatic retries from OkHttp */ + public static boolean okHttpAutomaticRetry() { + return getBoolean(OKHTTP_AUTOMATIC_RETRY, false); + } + /** Only for rendering debug info. */ public static synchronized @NonNull Map getMemoryValues() { return new TreeMap<>(REMOTE_VALUES); diff --git a/libsignal/service/src/main/java/org/whispersystems/signalservice/api/SignalServiceAccountManager.java b/libsignal/service/src/main/java/org/whispersystems/signalservice/api/SignalServiceAccountManager.java index 15efcbe628..5c949e0d40 100644 --- a/libsignal/service/src/main/java/org/whispersystems/signalservice/api/SignalServiceAccountManager.java +++ b/libsignal/service/src/main/java/org/whispersystems/signalservice/api/SignalServiceAccountManager.java @@ -121,21 +121,23 @@ public class SignalServiceAccountManager { */ public SignalServiceAccountManager(SignalServiceConfiguration configuration, UUID uuid, String e164, String password, - String signalAgent) + String signalAgent, boolean automaticNetworkRetry) { this(configuration, new StaticCredentialsProvider(uuid, e164, password, null), signalAgent, - new GroupsV2Operations(ClientZkOperations.create(configuration))); + new GroupsV2Operations(ClientZkOperations.create(configuration)), + automaticNetworkRetry); } public SignalServiceAccountManager(SignalServiceConfiguration configuration, CredentialsProvider credentialsProvider, String signalAgent, - GroupsV2Operations groupsV2Operations) + GroupsV2Operations groupsV2Operations, + boolean automaticNetworkRetry) { this.groupsV2Operations = groupsV2Operations; - this.pushServiceSocket = new PushServiceSocket(configuration, credentialsProvider, signalAgent, groupsV2Operations.getProfileOperations()); + this.pushServiceSocket = new PushServiceSocket(configuration, credentialsProvider, signalAgent, groupsV2Operations.getProfileOperations(), automaticNetworkRetry); this.credentials = credentialsProvider; this.userAgent = signalAgent; } diff --git a/libsignal/service/src/main/java/org/whispersystems/signalservice/api/SignalServiceMessageReceiver.java b/libsignal/service/src/main/java/org/whispersystems/signalservice/api/SignalServiceMessageReceiver.java index 810efd57eb..2ab3478cda 100644 --- a/libsignal/service/src/main/java/org/whispersystems/signalservice/api/SignalServiceMessageReceiver.java +++ b/libsignal/service/src/main/java/org/whispersystems/signalservice/api/SignalServiceMessageReceiver.java @@ -80,9 +80,10 @@ public class SignalServiceMessageReceiver { String signalingKey, String signalAgent, ConnectivityListener listener, SleepTimer timer, - ClientZkProfileOperations clientZkProfileOperations) + ClientZkProfileOperations clientZkProfileOperations, + boolean automaticNetworkRetry) { - this(urls, new StaticCredentialsProvider(uuid, e164, password, signalingKey), signalAgent, listener, timer, clientZkProfileOperations); + this(urls, new StaticCredentialsProvider(uuid, e164, password, signalingKey), signalAgent, listener, timer, clientZkProfileOperations, automaticNetworkRetry); } /** @@ -96,11 +97,12 @@ public class SignalServiceMessageReceiver { String signalAgent, ConnectivityListener listener, SleepTimer timer, - ClientZkProfileOperations clientZkProfileOperations) + ClientZkProfileOperations clientZkProfileOperations, + boolean automaticNetworkRetry) { this.urls = urls; this.credentialsProvider = credentials; - this.socket = new PushServiceSocket(urls, credentials, signalAgent, clientZkProfileOperations); + this.socket = new PushServiceSocket(urls, credentials, signalAgent, clientZkProfileOperations, automaticNetworkRetry); this.signalAgent = signalAgent; this.connectivityListener = listener; this.sleepTimer = timer; diff --git a/libsignal/service/src/main/java/org/whispersystems/signalservice/api/SignalServiceMessageSender.java b/libsignal/service/src/main/java/org/whispersystems/signalservice/api/SignalServiceMessageSender.java index 79c5898829..aa75704f30 100644 --- a/libsignal/service/src/main/java/org/whispersystems/signalservice/api/SignalServiceMessageSender.java +++ b/libsignal/service/src/main/java/org/whispersystems/signalservice/api/SignalServiceMessageSender.java @@ -149,9 +149,10 @@ public class SignalServiceMessageSender { Optional unidentifiedPipe, Optional eventListener, ClientZkProfileOperations clientZkProfileOperations, - ExecutorService executor) + ExecutorService executor, + boolean automaticNetworkRetry) { - this(urls, new StaticCredentialsProvider(uuid, e164, password, null), store, signalAgent, isMultiDevice, pipe, unidentifiedPipe, eventListener, clientZkProfileOperations, executor, 0); + this(urls, new StaticCredentialsProvider(uuid, e164, password, null), store, signalAgent, isMultiDevice, pipe, unidentifiedPipe, eventListener, clientZkProfileOperations, executor, 0, automaticNetworkRetry); } public SignalServiceMessageSender(SignalServiceConfiguration urls, @@ -164,9 +165,10 @@ public class SignalServiceMessageSender { Optional eventListener, ClientZkProfileOperations clientZkProfileOperations, ExecutorService executor, - long maxEnvelopeSize) + long maxEnvelopeSize, + boolean automaticNetworkRetry) { - this.socket = new PushServiceSocket(urls, credentialsProvider, signalAgent, clientZkProfileOperations); + this.socket = new PushServiceSocket(urls, credentialsProvider, signalAgent, clientZkProfileOperations, automaticNetworkRetry); this.store = store; this.localAddress = new SignalServiceAddress(credentialsProvider.getUuid(), credentialsProvider.getE164()); this.pipe = new AtomicReference<>(pipe); diff --git a/libsignal/service/src/main/java/org/whispersystems/signalservice/internal/push/PushServiceSocket.java b/libsignal/service/src/main/java/org/whispersystems/signalservice/internal/push/PushServiceSocket.java index e61b6d9486..412d3ff71d 100644 --- a/libsignal/service/src/main/java/org/whispersystems/signalservice/internal/push/PushServiceSocket.java +++ b/libsignal/service/src/main/java/org/whispersystems/signalservice/internal/push/PushServiceSocket.java @@ -233,14 +233,17 @@ public class PushServiceSocket { private final String signalAgent; private final SecureRandom random; private final ClientZkProfileOperations clientZkProfileOperations; + private final boolean automaticNetworkRetry; public PushServiceSocket(SignalServiceConfiguration configuration, CredentialsProvider credentialsProvider, String signalAgent, - ClientZkProfileOperations clientZkProfileOperations) + ClientZkProfileOperations clientZkProfileOperations, + boolean automaticNetworkRetry) { this.credentialsProvider = credentialsProvider; this.signalAgent = signalAgent; + this.automaticNetworkRetry = automaticNetworkRetry; this.serviceClients = createServiceConnectionHolders(configuration.getSignalServiceUrls(), configuration.getNetworkInterceptors(), configuration.getDns()); this.cdnClientsMap = createCdnClientsMap(configuration.getSignalCdnUrlMap(), configuration.getNetworkInterceptors(), configuration.getDns()); this.contactDiscoveryClients = createConnectionHolders(configuration.getSignalContactDiscoveryUrls(), configuration.getNetworkInterceptors(), configuration.getDns()); @@ -1477,6 +1480,7 @@ public class PushServiceSocket { return baseClient.newBuilder() .connectTimeout(soTimeoutMillis, TimeUnit.MILLISECONDS) .readTimeout(soTimeoutMillis, TimeUnit.MILLISECONDS) + .retryOnConnectionFailure(automaticNetworkRetry) .build(); }