From 2c4c6bf87c1704a64e7331eead6d52dc97be74db Mon Sep 17 00:00:00 2001 From: Nicholas Date: Wed, 7 Jun 2023 14:46:01 -0400 Subject: [PATCH] Allow registration with landlines. --- .../RegistrationSessionProcessor.kt | 42 ++++++++++++------- .../fragments/EnterPhoneNumberFragment.java | 32 ++++++++++---- app/src/main/res/values/strings.xml | 8 ++++ .../exceptions/MalformedRequestException.kt | 8 ++++ .../exceptions/RegistrationRetryException.kt | 8 ++++ .../internal/push/PushServiceSocket.java | 23 +++++++--- 6 files changed, 92 insertions(+), 29 deletions(-) create mode 100644 libsignal/service/src/main/java/org/whispersystems/signalservice/api/push/exceptions/MalformedRequestException.kt create mode 100644 libsignal/service/src/main/java/org/whispersystems/signalservice/api/push/exceptions/RegistrationRetryException.kt diff --git a/app/src/main/java/org/thoughtcrime/securesms/registration/RegistrationSessionProcessor.kt b/app/src/main/java/org/thoughtcrime/securesms/registration/RegistrationSessionProcessor.kt index b24143df8a..0eb3d937d5 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/registration/RegistrationSessionProcessor.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/registration/RegistrationSessionProcessor.kt @@ -4,10 +4,12 @@ import org.whispersystems.signalservice.api.push.exceptions.AlreadyVerifiedExcep import org.whispersystems.signalservice.api.push.exceptions.ExternalServiceFailureException import org.whispersystems.signalservice.api.push.exceptions.ImpossiblePhoneNumberException import org.whispersystems.signalservice.api.push.exceptions.InvalidTransportModeException +import org.whispersystems.signalservice.api.push.exceptions.MalformedRequestException import org.whispersystems.signalservice.api.push.exceptions.MustRequestNewCodeException import org.whispersystems.signalservice.api.push.exceptions.NoSuchSessionException import org.whispersystems.signalservice.api.push.exceptions.NonNormalizedPhoneNumberException import org.whispersystems.signalservice.api.push.exceptions.RateLimitException +import org.whispersystems.signalservice.api.push.exceptions.RegistrationRetryException import org.whispersystems.signalservice.api.push.exceptions.TokenNotAcceptedException import org.whispersystems.signalservice.api.util.Preconditions import org.whispersystems.signalservice.internal.ServiceResponse @@ -167,6 +169,30 @@ sealed class RegistrationSessionProcessor(response: ServiceResponse) : RegistrationSessionProcessor(response) { override fun verificationCodeRequestSuccess(): Boolean = false @@ -174,21 +200,5 @@ sealed class RegistrationSessionProcessor(response: ServiceResponse) : RegistrationSessionProcessor(response) { override fun verificationCodeRequestSuccess(): Boolean = hasResult() - - fun isAlreadyVerified(): Boolean { - return error is AlreadyVerifiedException - } - - fun mustRequestNewCode(): Boolean { - return error is MustRequestNewCodeException - } - - fun externalServiceFailure(): Boolean { - return error is ExternalServiceFailureException - } - - fun invalidTransportModeFailure(): Boolean { - return error is InvalidTransportModeException - } } } diff --git a/app/src/main/java/org/thoughtcrime/securesms/registration/fragments/EnterPhoneNumberFragment.java b/app/src/main/java/org/thoughtcrime/securesms/registration/fragments/EnterPhoneNumberFragment.java index 6b8283b54b..79a06c234d 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/registration/fragments/EnterPhoneNumberFragment.java +++ b/app/src/main/java/org/thoughtcrime/securesms/registration/fragments/EnterPhoneNumberFragment.java @@ -1,6 +1,7 @@ package org.thoughtcrime.securesms.registration.fragments; import android.content.Context; +import android.content.DialogInterface; import android.os.Bundle; import android.text.TextUtils; import android.view.LayoutInflater; @@ -286,8 +287,9 @@ public final class EnterPhoneNumberFragment extends LoggingFragment implements R } private void requestVerificationCode(@NonNull Mode mode) { - NavController navController = NavHostFragment.findNavController(this); - MccMncProducer mccMncProducer = new MccMncProducer(requireContext()); + NavController navController = NavHostFragment.findNavController(this); + MccMncProducer mccMncProducer = new MccMncProducer(requireContext()); + final DialogInterface.OnClickListener proceedToNextScreen = (dialog, which) -> SafeNavigation.safeNavigate(navController, EnterPhoneNumberFragmentDirections.actionEnterVerificationCode()); Disposable request = viewModel.requestVerificationCode(mode, mccMncProducer.getMcc(), mccMncProducer.getMnc()) .doOnSubscribe(unused -> SignalStore.account().setRegistered(false)) .observeOn(AndroidSchedulers.mainThread()) @@ -314,11 +316,23 @@ public final class EnterPhoneNumberFragment extends LoggingFragment implements R } else if (processor.isTokenRejected()) { Log.i(TAG, "The server did not accept the information.", processor.getError()); showErrorDialog(register.getContext(), getString(R.string.RegistrationActivity_we_need_to_verify_that_youre_human)); - } else if (processor instanceof RegistrationSessionProcessor.RegistrationSessionProcessorForVerification - && ((RegistrationSessionProcessor.RegistrationSessionProcessorForVerification) processor).externalServiceFailure()) - { + } else if (processor.externalServiceFailure()) { Log.w(TAG, "The server reported a failure with an external service.", processor.getError()); - showErrorDialog(register.getContext(), getString(R.string.RegistrationActivity_external_service_error)); + showErrorDialog(register.getContext(), getString(R.string.RegistrationActivity_unable_to_connect_to_service), proceedToNextScreen); + } else if (processor.invalidTransportModeFailure()) { + Log.w(TAG, "The server reported an invalid transport mode failure.", processor.getError()); + new MaterialAlertDialogBuilder(register.getContext()) + .setMessage(R.string.RegistrationActivity_we_couldnt_send_you_a_verification_code) + .setPositiveButton(R.string.RegistrationActivity_voice_call, (dialog, which) -> requestVerificationCode(Mode.PHONE_CALL)) + .setNegativeButton(R.string.RegistrationActivity_cancel, null) + .show(); + } else if ( processor.isMalformedRequest()){ + Log.w(TAG, "The server reported a malformed request.", processor.getError()); + showErrorDialog(register.getContext(), getString(R.string.RegistrationActivity_unable_to_connect_to_service), proceedToNextScreen); + + } else if (processor.isRetryException()) { + Log.w(TAG, "The server reported a failure that is retryable.", processor.getError()); + showErrorDialog(register.getContext(), getString(R.string.RegistrationActivity_unable_to_connect_to_service), proceedToNextScreen); } else { Log.i(TAG, "Unknown error during verification code request", processor.getError()); showErrorDialog(register.getContext(), getString(R.string.RegistrationActivity_unable_to_connect_to_service)); @@ -343,7 +357,11 @@ public final class EnterPhoneNumberFragment extends LoggingFragment implements R } public void showErrorDialog(Context context, String msg) { - new MaterialAlertDialogBuilder(context).setMessage(msg).setPositiveButton(R.string.ok, null).show(); + showErrorDialog(context, msg, null); + } + + public void showErrorDialog(Context context, String msg, DialogInterface.OnClickListener positiveButtonListener) { + new MaterialAlertDialogBuilder(context).setMessage(msg).setPositiveButton(R.string.ok, positiveButtonListener).show(); } @Override diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 7aef2138a6..e88b1faf75 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -1856,6 +1856,10 @@ You\'ve made too many attempts to register this number. Please try again in %s. Unable to connect to service. Please check network connection and try again. + + An unexpected error occurred. + + We couldn\'t send you a verification code via SMS. Try receiving your code via voice call instead. Unable to request a verification code. Please check network connection and try again. Non-standard number format @@ -1874,6 +1878,10 @@ We need to verify that you\'re human. Signal was unable to send an SMS code due to an external failure. + + Voice Call + + Cancel Next Continue Take privacy with you.\nBe yourself in every message. diff --git a/libsignal/service/src/main/java/org/whispersystems/signalservice/api/push/exceptions/MalformedRequestException.kt b/libsignal/service/src/main/java/org/whispersystems/signalservice/api/push/exceptions/MalformedRequestException.kt new file mode 100644 index 0000000000..c027e20dc7 --- /dev/null +++ b/libsignal/service/src/main/java/org/whispersystems/signalservice/api/push/exceptions/MalformedRequestException.kt @@ -0,0 +1,8 @@ +/* + * Copyright 2023 Signal Messenger, LLC + * SPDX-License-Identifier: AGPL-3.0-only + */ + +package org.whispersystems.signalservice.api.push.exceptions + +class MalformedRequestException : NonSuccessfulResponseCodeException(400) diff --git a/libsignal/service/src/main/java/org/whispersystems/signalservice/api/push/exceptions/RegistrationRetryException.kt b/libsignal/service/src/main/java/org/whispersystems/signalservice/api/push/exceptions/RegistrationRetryException.kt new file mode 100644 index 0000000000..5b2e2b91ea --- /dev/null +++ b/libsignal/service/src/main/java/org/whispersystems/signalservice/api/push/exceptions/RegistrationRetryException.kt @@ -0,0 +1,8 @@ +/* + * Copyright 2023 Signal Messenger, LLC + * SPDX-License-Identifier: AGPL-3.0-only + */ + +package org.whispersystems.signalservice.api.push.exceptions + +class RegistrationRetryException : NonSuccessfulResponseCodeException(429) 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 c0d1d9a83c..3e02008af8 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 @@ -69,6 +69,7 @@ import org.whispersystems.signalservice.api.push.exceptions.ExternalServiceFailu import org.whispersystems.signalservice.api.push.exceptions.HttpConflictException; import org.whispersystems.signalservice.api.push.exceptions.IncorrectRegistrationRecoveryPasswordException; import org.whispersystems.signalservice.api.push.exceptions.InvalidTransportModeException; +import org.whispersystems.signalservice.api.push.exceptions.MalformedRequestException; import org.whispersystems.signalservice.api.push.exceptions.MalformedResponseException; import org.whispersystems.signalservice.api.push.exceptions.MissingConfigurationException; import org.whispersystems.signalservice.api.push.exceptions.MustRequestNewCodeException; @@ -82,6 +83,7 @@ import org.whispersystems.signalservice.api.push.exceptions.PushChallengeRequire import org.whispersystems.signalservice.api.push.exceptions.PushNetworkException; import org.whispersystems.signalservice.api.push.exceptions.RangeException; import org.whispersystems.signalservice.api.push.exceptions.RateLimitException; +import org.whispersystems.signalservice.api.push.exceptions.RegistrationRetryException; import org.whispersystems.signalservice.api.push.exceptions.RemoteAttestationResponseExpiredException; import org.whispersystems.signalservice.api.push.exceptions.ResumeLocationInvalidException; import org.whispersystems.signalservice.api.push.exceptions.ServerRejectedException; @@ -2553,7 +2555,10 @@ public class PushServiceSocket { @Override public void handle(int responseCode, ResponseBody body) throws NonSuccessfulResponseCodeException, PushNetworkException { - if (responseCode == 403) { + + if (responseCode == 400) { + throw new MalformedRequestException(); + } else if (responseCode == 403) { throw new IncorrectRegistrationRecoveryPasswordException(); } else if (responseCode == 404) { throw new NoSuchSessionException(); @@ -2572,13 +2577,17 @@ public class PushServiceSocket { } else { throw new HttpConflictException(); } - } else if (responseCode == 502) { + } else if (responseCode == 418) { + throw new InvalidTransportModeException(); + } else if (responseCode == 429) { + throw new RegistrationRetryException(); + } else if (responseCode == 440) { VerificationCodeFailureResponseBody response; try { response = JsonUtil.fromJson(body.string(), VerificationCodeFailureResponseBody.class); } catch (IOException e) { Log.e(TAG, "Unable to read response body.", e); - throw new NonSuccessfulResponseCodeException(502); + throw new NonSuccessfulResponseCodeException(responseCode); } throw new ExternalServiceFailureException(response.getPermanentFailure(), response.getReason()); } @@ -2615,7 +2624,9 @@ public class PushServiceSocket { } private static class RegistrationCodeRequestResponseHandler implements ResponseCodeHandler { - @Override public void handle(int responseCode, ResponseBody body) throws NonSuccessfulResponseCodeException, PushNetworkException { + @Override + public void handle(int responseCode, ResponseBody body) throws NonSuccessfulResponseCodeException, PushNetworkException { + switch (responseCode) { case 400: throw new InvalidTransportModeException(); @@ -2637,13 +2648,13 @@ public class PushServiceSocket { } else { throw new HttpConflictException(); } - case 502: + case 440: VerificationCodeFailureResponseBody codeFailureResponse; try { codeFailureResponse = JsonUtil.fromJson(body.string(), VerificationCodeFailureResponseBody.class); } catch (IOException e) { Log.e(TAG, "Unable to read response body.", e); - throw new NonSuccessfulResponseCodeException(502); + throw new NonSuccessfulResponseCodeException(responseCode); } throw new ExternalServiceFailureException(codeFailureResponse.getPermanentFailure(), codeFailureResponse.getReason());