From 4482bfcabbe66dc4b4c288eeca80c773c2de081b Mon Sep 17 00:00:00 2001 From: Greyson Parrelli Date: Thu, 28 Jan 2021 18:25:27 -0500 Subject: [PATCH] Ensure NonSuccessfulReponseCodeException knows the response code. --- .../api/SignalServiceMessagePipe.java | 2 +- .../api/SignalServiceMessageSender.java | 5 +- .../AuthorizationFailedException.java | 4 +- .../exceptions/CaptchaRequiredException.java | 3 + .../push/exceptions/ConflictException.java | 2 +- .../DeprecatedVersionException.java | 3 + .../ExpectationFailedException.java | 3 + .../MalformedResponseException.java | 17 ++++ .../push/exceptions/NoContentException.java | 2 +- .../NonSuccessfulResponseCodeException.java | 16 +++- .../push/exceptions/NotFoundException.java | 2 +- .../api/push/exceptions/RangeException.java | 2 +- .../push/exceptions/RateLimitException.java | 2 +- ...teAttestationResponseExpiredException.java | 2 +- .../exceptions/ServerRejectedException.java | 3 + .../UsernameMalformedException.java | 3 + .../exceptions/UsernameTakenException.java | 3 + .../push/DeviceLimitExceededException.java | 1 + .../internal/push/LockedException.java | 1 + .../internal/push/PushServiceSocket.java | 96 +++++++++---------- .../internal/push/RemoteAttestationUtil.java | 5 +- .../push/exceptions/ForbiddenException.java | 3 + .../push/exceptions/GroupExistsException.java | 3 + .../exceptions/GroupNotFoundException.java | 3 + .../GroupPatchNotAcceptedException.java | 3 + .../MismatchedDevicesException.java | 1 + .../push/exceptions/NotInGroupException.java | 3 + .../exceptions/StaleDevicesException.java | 1 + 28 files changed, 131 insertions(+), 63 deletions(-) create mode 100644 libsignal/service/src/main/java/org/whispersystems/signalservice/api/push/exceptions/MalformedResponseException.java diff --git a/libsignal/service/src/main/java/org/whispersystems/signalservice/api/SignalServiceMessagePipe.java b/libsignal/service/src/main/java/org/whispersystems/signalservice/api/SignalServiceMessagePipe.java index c7dea7a21..826b5172f 100644 --- a/libsignal/service/src/main/java/org/whispersystems/signalservice/api/SignalServiceMessagePipe.java +++ b/libsignal/service/src/main/java/org/whispersystems/signalservice/api/SignalServiceMessagePipe.java @@ -262,7 +262,7 @@ public class SignalServiceMessagePipe { if (response.getStatus() == 404) { throw new NotFoundException("Not found"); } else if (response.getStatus() < 200 || response.getStatus() >= 300) { - throw new NonSuccessfulResponseCodeException("Non-successful response: " + response.getStatus()); + throw new NonSuccessfulResponseCodeException(response.getStatus(), "Non-successful response: " + response.getStatus()); } SignalServiceProfile signalServiceProfile = JsonUtil.fromJson(response.getBody(), SignalServiceProfile.class); 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 e004ce03c..6a3d5d049 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 @@ -51,6 +51,7 @@ import org.whispersystems.signalservice.api.messages.multidevice.ViewOnceOpenMes import org.whispersystems.signalservice.api.messages.shared.SharedContact; import org.whispersystems.signalservice.api.push.SignalServiceAddress; import org.whispersystems.signalservice.api.push.exceptions.AuthorizationFailedException; +import org.whispersystems.signalservice.api.push.exceptions.MalformedResponseException; import org.whispersystems.signalservice.api.push.exceptions.NonSuccessfulResponseCodeException; import org.whispersystems.signalservice.api.push.exceptions.PushNetworkException; import org.whispersystems.signalservice.api.push.exceptions.ServerRejectedException; @@ -409,7 +410,9 @@ public class SignalServiceMessageSender { } } - private SignalServiceAttachmentPointer uploadAttachmentV2(SignalServiceAttachmentStream attachment, byte[] attachmentKey, PushAttachmentData attachmentData) throws NonSuccessfulResponseCodeException, PushNetworkException { + private SignalServiceAttachmentPointer uploadAttachmentV2(SignalServiceAttachmentStream attachment, byte[] attachmentKey, PushAttachmentData attachmentData) + throws NonSuccessfulResponseCodeException, PushNetworkException, MalformedResponseException + { AttachmentV2UploadAttributes v2UploadAttributes = null; Optional localPipe = pipe.get(); diff --git a/libsignal/service/src/main/java/org/whispersystems/signalservice/api/push/exceptions/AuthorizationFailedException.java b/libsignal/service/src/main/java/org/whispersystems/signalservice/api/push/exceptions/AuthorizationFailedException.java index d1daad144..758fbca98 100644 --- a/libsignal/service/src/main/java/org/whispersystems/signalservice/api/push/exceptions/AuthorizationFailedException.java +++ b/libsignal/service/src/main/java/org/whispersystems/signalservice/api/push/exceptions/AuthorizationFailedException.java @@ -7,7 +7,7 @@ package org.whispersystems.signalservice.api.push.exceptions; public class AuthorizationFailedException extends NonSuccessfulResponseCodeException { - public AuthorizationFailedException(String s) { - super(s); + public AuthorizationFailedException(int code, String s) { + super(code, s); } } diff --git a/libsignal/service/src/main/java/org/whispersystems/signalservice/api/push/exceptions/CaptchaRequiredException.java b/libsignal/service/src/main/java/org/whispersystems/signalservice/api/push/exceptions/CaptchaRequiredException.java index 999ca3bce..87852c02c 100644 --- a/libsignal/service/src/main/java/org/whispersystems/signalservice/api/push/exceptions/CaptchaRequiredException.java +++ b/libsignal/service/src/main/java/org/whispersystems/signalservice/api/push/exceptions/CaptchaRequiredException.java @@ -1,4 +1,7 @@ package org.whispersystems.signalservice.api.push.exceptions; public class CaptchaRequiredException extends NonSuccessfulResponseCodeException { + public CaptchaRequiredException() { + super(402); + } } diff --git a/libsignal/service/src/main/java/org/whispersystems/signalservice/api/push/exceptions/ConflictException.java b/libsignal/service/src/main/java/org/whispersystems/signalservice/api/push/exceptions/ConflictException.java index 830433721..e817180c9 100644 --- a/libsignal/service/src/main/java/org/whispersystems/signalservice/api/push/exceptions/ConflictException.java +++ b/libsignal/service/src/main/java/org/whispersystems/signalservice/api/push/exceptions/ConflictException.java @@ -5,6 +5,6 @@ package org.whispersystems.signalservice.api.push.exceptions; */ public class ConflictException extends NonSuccessfulResponseCodeException { public ConflictException() { - super("Conflict"); + super(409, "Conflict"); } } diff --git a/libsignal/service/src/main/java/org/whispersystems/signalservice/api/push/exceptions/DeprecatedVersionException.java b/libsignal/service/src/main/java/org/whispersystems/signalservice/api/push/exceptions/DeprecatedVersionException.java index 1136044f2..b4e218c24 100644 --- a/libsignal/service/src/main/java/org/whispersystems/signalservice/api/push/exceptions/DeprecatedVersionException.java +++ b/libsignal/service/src/main/java/org/whispersystems/signalservice/api/push/exceptions/DeprecatedVersionException.java @@ -1,4 +1,7 @@ package org.whispersystems.signalservice.api.push.exceptions; public class DeprecatedVersionException extends NonSuccessfulResponseCodeException { + public DeprecatedVersionException() { + super(499); + } } diff --git a/libsignal/service/src/main/java/org/whispersystems/signalservice/api/push/exceptions/ExpectationFailedException.java b/libsignal/service/src/main/java/org/whispersystems/signalservice/api/push/exceptions/ExpectationFailedException.java index 1b3b76d7b..01d753485 100644 --- a/libsignal/service/src/main/java/org/whispersystems/signalservice/api/push/exceptions/ExpectationFailedException.java +++ b/libsignal/service/src/main/java/org/whispersystems/signalservice/api/push/exceptions/ExpectationFailedException.java @@ -6,4 +6,7 @@ package org.whispersystems.signalservice.api.push.exceptions; public class ExpectationFailedException extends NonSuccessfulResponseCodeException { + public ExpectationFailedException() { + super(417); + } } diff --git a/libsignal/service/src/main/java/org/whispersystems/signalservice/api/push/exceptions/MalformedResponseException.java b/libsignal/service/src/main/java/org/whispersystems/signalservice/api/push/exceptions/MalformedResponseException.java new file mode 100644 index 000000000..719fa738d --- /dev/null +++ b/libsignal/service/src/main/java/org/whispersystems/signalservice/api/push/exceptions/MalformedResponseException.java @@ -0,0 +1,17 @@ +package org.whispersystems.signalservice.api.push.exceptions; + +import java.io.IOException; + +/** + * Indicates that a response is malformed or otherwise in an unexpected format. + */ +public class MalformedResponseException extends IOException { + + public MalformedResponseException(String message) { + super(message); + } + + public MalformedResponseException(String message, IOException e) { + super(message, e); + } +} diff --git a/libsignal/service/src/main/java/org/whispersystems/signalservice/api/push/exceptions/NoContentException.java b/libsignal/service/src/main/java/org/whispersystems/signalservice/api/push/exceptions/NoContentException.java index 4b46a4887..181dc249f 100644 --- a/libsignal/service/src/main/java/org/whispersystems/signalservice/api/push/exceptions/NoContentException.java +++ b/libsignal/service/src/main/java/org/whispersystems/signalservice/api/push/exceptions/NoContentException.java @@ -8,6 +8,6 @@ package org.whispersystems.signalservice.api.push.exceptions; public class NoContentException extends NonSuccessfulResponseCodeException { public NoContentException(String s) { - super(s); + super(204, s); } } diff --git a/libsignal/service/src/main/java/org/whispersystems/signalservice/api/push/exceptions/NonSuccessfulResponseCodeException.java b/libsignal/service/src/main/java/org/whispersystems/signalservice/api/push/exceptions/NonSuccessfulResponseCodeException.java index 47bfde75c..4cc60411c 100644 --- a/libsignal/service/src/main/java/org/whispersystems/signalservice/api/push/exceptions/NonSuccessfulResponseCodeException.java +++ b/libsignal/service/src/main/java/org/whispersystems/signalservice/api/push/exceptions/NonSuccessfulResponseCodeException.java @@ -8,13 +8,23 @@ package org.whispersystems.signalservice.api.push.exceptions; import java.io.IOException; +/** + * Indicates a server response that is not successful, typically something outside the 2xx range. + */ public class NonSuccessfulResponseCodeException extends IOException { - public NonSuccessfulResponseCodeException() { - super(); + private final int code; + + public NonSuccessfulResponseCodeException(int code) { + this.code = code; } - public NonSuccessfulResponseCodeException(String s) { + public NonSuccessfulResponseCodeException(int code, String s) { super(s); + this.code = code; + } + + public int getCode() { + return code; } } diff --git a/libsignal/service/src/main/java/org/whispersystems/signalservice/api/push/exceptions/NotFoundException.java b/libsignal/service/src/main/java/org/whispersystems/signalservice/api/push/exceptions/NotFoundException.java index 97cd6bd17..1129e7f86 100644 --- a/libsignal/service/src/main/java/org/whispersystems/signalservice/api/push/exceptions/NotFoundException.java +++ b/libsignal/service/src/main/java/org/whispersystems/signalservice/api/push/exceptions/NotFoundException.java @@ -8,6 +8,6 @@ package org.whispersystems.signalservice.api.push.exceptions; public class NotFoundException extends NonSuccessfulResponseCodeException { public NotFoundException(String s) { - super(s); + super(404, s); } } diff --git a/libsignal/service/src/main/java/org/whispersystems/signalservice/api/push/exceptions/RangeException.java b/libsignal/service/src/main/java/org/whispersystems/signalservice/api/push/exceptions/RangeException.java index b1cbc57f9..d1db9619f 100644 --- a/libsignal/service/src/main/java/org/whispersystems/signalservice/api/push/exceptions/RangeException.java +++ b/libsignal/service/src/main/java/org/whispersystems/signalservice/api/push/exceptions/RangeException.java @@ -9,6 +9,6 @@ package org.whispersystems.signalservice.api.push.exceptions; public final class RangeException extends NonSuccessfulResponseCodeException { public RangeException(long requested) { - super("Range request out of bounds " + requested); + super(416, "Range request out of bounds " + requested); } } diff --git a/libsignal/service/src/main/java/org/whispersystems/signalservice/api/push/exceptions/RateLimitException.java b/libsignal/service/src/main/java/org/whispersystems/signalservice/api/push/exceptions/RateLimitException.java index d5888a039..2e3653a94 100644 --- a/libsignal/service/src/main/java/org/whispersystems/signalservice/api/push/exceptions/RateLimitException.java +++ b/libsignal/service/src/main/java/org/whispersystems/signalservice/api/push/exceptions/RateLimitException.java @@ -8,6 +8,6 @@ package org.whispersystems.signalservice.api.push.exceptions; public class RateLimitException extends NonSuccessfulResponseCodeException { public RateLimitException(String s) { - super(s); + super(413, s); } } diff --git a/libsignal/service/src/main/java/org/whispersystems/signalservice/api/push/exceptions/RemoteAttestationResponseExpiredException.java b/libsignal/service/src/main/java/org/whispersystems/signalservice/api/push/exceptions/RemoteAttestationResponseExpiredException.java index a51dbec22..f6f5f4ac3 100644 --- a/libsignal/service/src/main/java/org/whispersystems/signalservice/api/push/exceptions/RemoteAttestationResponseExpiredException.java +++ b/libsignal/service/src/main/java/org/whispersystems/signalservice/api/push/exceptions/RemoteAttestationResponseExpiredException.java @@ -8,6 +8,6 @@ package org.whispersystems.signalservice.api.push.exceptions; public class RemoteAttestationResponseExpiredException extends NonSuccessfulResponseCodeException { public RemoteAttestationResponseExpiredException(String message) { - super(message); + super(409, message); } } diff --git a/libsignal/service/src/main/java/org/whispersystems/signalservice/api/push/exceptions/ServerRejectedException.java b/libsignal/service/src/main/java/org/whispersystems/signalservice/api/push/exceptions/ServerRejectedException.java index 2b26c9c6e..59ef77147 100644 --- a/libsignal/service/src/main/java/org/whispersystems/signalservice/api/push/exceptions/ServerRejectedException.java +++ b/libsignal/service/src/main/java/org/whispersystems/signalservice/api/push/exceptions/ServerRejectedException.java @@ -4,4 +4,7 @@ package org.whispersystems.signalservice.api.push.exceptions; * Indicates the server has rejected the request and we should stop retrying. */ public class ServerRejectedException extends NonSuccessfulResponseCodeException { + public ServerRejectedException() { + super(508); + } } diff --git a/libsignal/service/src/main/java/org/whispersystems/signalservice/api/push/exceptions/UsernameMalformedException.java b/libsignal/service/src/main/java/org/whispersystems/signalservice/api/push/exceptions/UsernameMalformedException.java index 246338015..e8f39a127 100644 --- a/libsignal/service/src/main/java/org/whispersystems/signalservice/api/push/exceptions/UsernameMalformedException.java +++ b/libsignal/service/src/main/java/org/whispersystems/signalservice/api/push/exceptions/UsernameMalformedException.java @@ -1,4 +1,7 @@ package org.whispersystems.signalservice.api.push.exceptions; public class UsernameMalformedException extends NonSuccessfulResponseCodeException { + public UsernameMalformedException() { + super(400); + } } diff --git a/libsignal/service/src/main/java/org/whispersystems/signalservice/api/push/exceptions/UsernameTakenException.java b/libsignal/service/src/main/java/org/whispersystems/signalservice/api/push/exceptions/UsernameTakenException.java index 09782da2f..d90d6cfa3 100644 --- a/libsignal/service/src/main/java/org/whispersystems/signalservice/api/push/exceptions/UsernameTakenException.java +++ b/libsignal/service/src/main/java/org/whispersystems/signalservice/api/push/exceptions/UsernameTakenException.java @@ -1,4 +1,7 @@ package org.whispersystems.signalservice.api.push.exceptions; public class UsernameTakenException extends NonSuccessfulResponseCodeException { + public UsernameTakenException() { + super(409); + } } diff --git a/libsignal/service/src/main/java/org/whispersystems/signalservice/internal/push/DeviceLimitExceededException.java b/libsignal/service/src/main/java/org/whispersystems/signalservice/internal/push/DeviceLimitExceededException.java index ccb03bca6..791731ec6 100644 --- a/libsignal/service/src/main/java/org/whispersystems/signalservice/internal/push/DeviceLimitExceededException.java +++ b/libsignal/service/src/main/java/org/whispersystems/signalservice/internal/push/DeviceLimitExceededException.java @@ -7,6 +7,7 @@ public class DeviceLimitExceededException extends NonSuccessfulResponseCodeExcep private final DeviceLimit deviceLimit; public DeviceLimitExceededException(DeviceLimit deviceLimit) { + super(411); this.deviceLimit = deviceLimit; } diff --git a/libsignal/service/src/main/java/org/whispersystems/signalservice/internal/push/LockedException.java b/libsignal/service/src/main/java/org/whispersystems/signalservice/internal/push/LockedException.java index 37ad5701c..4ec2310a2 100644 --- a/libsignal/service/src/main/java/org/whispersystems/signalservice/internal/push/LockedException.java +++ b/libsignal/service/src/main/java/org/whispersystems/signalservice/internal/push/LockedException.java @@ -10,6 +10,7 @@ public final class LockedException extends NonSuccessfulResponseCodeException { private final String basicStorageCredentials; LockedException(int length, long timeRemaining, String basicStorageCredentials) { + super(423); this.length = length; this.timeRemaining = timeRemaining; this.basicStorageCredentials = basicStorageCredentials; 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 92105c416..22ca7fec8 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 @@ -54,6 +54,7 @@ import org.whispersystems.signalservice.api.push.exceptions.ConflictException; import org.whispersystems.signalservice.api.push.exceptions.ContactManifestMismatchException; import org.whispersystems.signalservice.api.push.exceptions.DeprecatedVersionException; import org.whispersystems.signalservice.api.push.exceptions.ExpectationFailedException; +import org.whispersystems.signalservice.api.push.exceptions.MalformedResponseException; import org.whispersystems.signalservice.api.push.exceptions.MissingConfigurationException; import org.whispersystems.signalservice.api.push.exceptions.NoContentException; import org.whispersystems.signalservice.api.push.exceptions.NonSuccessfulResponseCodeException; @@ -623,13 +624,13 @@ public class PushServiceSocket { return JsonUtil.fromJson(body, SignalServiceProfile.class); } catch (IOException e) { Log.w(TAG, e); - throw new NonSuccessfulResponseCodeException("Unable to parse entity"); + throw new MalformedResponseException("Unable to parse entity", e); } }); } public SignalServiceProfile retrieveProfileByUsername(String username, Optional unidentifiedAccess) - throws NonSuccessfulResponseCodeException, PushNetworkException + throws NonSuccessfulResponseCodeException, PushNetworkException, MalformedResponseException { String response = makeServiceRequest(String.format(PROFILE_USERNAME_PATH, username), "GET", null, NO_HEADERS, unidentifiedAccess); @@ -637,7 +638,7 @@ public class PushServiceSocket { return JsonUtil.fromJson(response, SignalServiceProfile.class); } catch (IOException e) { Log.w(TAG, e); - throw new NonSuccessfulResponseCodeException("Unable to parse entity"); + throw new MalformedResponseException("Unable to parse entity", e); } } @@ -656,7 +657,7 @@ public class PushServiceSocket { } private ProfileAndCredential formatProfileAndCredentialBody(ProfileKeyCredentialRequestContext requestContext, String body) - throws NonSuccessfulResponseCodeException + throws MalformedResponseException { try { SignalServiceProfile signalServiceProfile = JsonUtil.fromJson(body, SignalServiceProfile.class); @@ -672,7 +673,7 @@ public class PushServiceSocket { } } catch (IOException e) { Log.w(TAG, e); - throw new NonSuccessfulResponseCodeException("Unable to parse entity"); + throw new MalformedResponseException("Unable to parse entity", e); } } @@ -688,7 +689,7 @@ public class PushServiceSocket { return JsonUtil.fromJson(body, SignalServiceProfile.class); } catch (IOException e) { Log.w(TAG, e); - throw new NonSuccessfulResponseCodeException("Unable to parse entity"); + throw new MalformedResponseException("Unable to parse entity", e); } }); } @@ -707,7 +708,7 @@ public class PushServiceSocket { * @return The avatar URL path, if one was written. */ public Optional writeProfile(SignalServiceProfileWrite signalServiceProfileWrite, ProfileAvatarData profileAvatar) - throws NonSuccessfulResponseCodeException, PushNetworkException + throws NonSuccessfulResponseCodeException, PushNetworkException, MalformedResponseException { String requestBody = JsonUtil.toJson(signalServiceProfileWrite); ProfileAvatarUploadAttributes formAttributes; @@ -719,7 +720,7 @@ public class PushServiceSocket { formAttributes = JsonUtil.fromJson(response, ProfileAvatarUploadAttributes.class); } catch (IOException e) { Log.w(TAG, e); - throw new NonSuccessfulResponseCodeException("Unable to parse entity"); + throw new MalformedResponseException("Unable to parse entity", e); } uploadToCdn0(AVATAR_UPLOAD_PATH, formAttributes.getAcl(), formAttributes.getKey(), @@ -756,7 +757,7 @@ public class PushServiceSocket { } public List retrieveDirectory(Set contactTokens) - throws NonSuccessfulResponseCodeException, PushNetworkException + throws NonSuccessfulResponseCodeException, PushNetworkException, MalformedResponseException { try { ContactTokenList contactTokenList = new ContactTokenList(new LinkedList<>(contactTokens)); @@ -766,7 +767,7 @@ public class PushServiceSocket { return activeTokens.getContacts(); } catch (IOException e) { Log.w(TAG, e); - throw new NonSuccessfulResponseCodeException("Unable to parse entity"); + throw new MalformedResponseException("Unable to parse entity", e); } } @@ -801,7 +802,7 @@ public class PushServiceSocket { if (body != null) { return JsonUtil.fromJson(body.string(), TokenResponse.class); } else { - throw new NonSuccessfulResponseCodeException("Empty response!"); + throw new MalformedResponseException("Empty response!"); } } @@ -813,7 +814,7 @@ public class PushServiceSocket { if (body != null) { return JsonUtil.fromJson(body.string(), DiscoveryResponse.class); } else { - throw new NonSuccessfulResponseCodeException("Empty response!"); + throw new MalformedResponseException("Empty response!"); } } @@ -825,7 +826,7 @@ public class PushServiceSocket { if (body != null) { return JsonUtil.fromJson(body.string(), KeyBackupResponse.class); } else { - throw new NonSuccessfulResponseCodeException("Empty response!"); + throw new MalformedResponseException("Empty response!"); } } @@ -899,23 +900,27 @@ public class PushServiceSocket { } } - public AttachmentV2UploadAttributes getAttachmentV2UploadAttributes() throws NonSuccessfulResponseCodeException, PushNetworkException { + public AttachmentV2UploadAttributes getAttachmentV2UploadAttributes() + throws NonSuccessfulResponseCodeException, PushNetworkException, MalformedResponseException + { String response = makeServiceRequest(ATTACHMENT_V2_PATH, "GET", null); try { return JsonUtil.fromJson(response, AttachmentV2UploadAttributes.class); } catch (IOException e) { Log.w(TAG, e); - throw new NonSuccessfulResponseCodeException("Unable to parse entity"); + throw new MalformedResponseException("Unable to parse entity", e); } } - public AttachmentV3UploadAttributes getAttachmentV3UploadAttributes() throws NonSuccessfulResponseCodeException, PushNetworkException { + public AttachmentV3UploadAttributes getAttachmentV3UploadAttributes() + throws NonSuccessfulResponseCodeException, PushNetworkException, MalformedResponseException + { String response = makeServiceRequest(ATTACHMENT_V3_PATH, "GET", null); try { return JsonUtil.fromJson(response, AttachmentV3UploadAttributes.class); } catch (IOException e) { Log.w(TAG, e); - throw new NonSuccessfulResponseCodeException("Unable to parse entity"); + throw new MalformedResponseException("Unable to parse entity", e); } } @@ -1053,7 +1058,7 @@ public class PushServiceSocket { } } - throw new NonSuccessfulResponseCodeException("Response: " + response); + throw new NonSuccessfulResponseCodeException(response.code(), "Response: " + response); } private byte[] uploadToCdn0(String path, String acl, String key, String policy, String algorithm, @@ -1109,7 +1114,7 @@ public class PushServiceSocket { } if (response.isSuccessful()) return file.getTransmittedDigest(); - else throw new NonSuccessfulResponseCodeException("Response: " + response); + else throw new NonSuccessfulResponseCodeException(response.code(), "Response: " + response); } finally { synchronized (connections) { connections.remove(call); @@ -1159,7 +1164,7 @@ public class PushServiceSocket { if (response.isSuccessful()) { return response.header("location"); } else { - throw new NonSuccessfulResponseCodeException("Response: " + response); + throw new NonSuccessfulResponseCodeException(response.code(), "Response: " + response); } } finally { synchronized (connections) { @@ -1211,7 +1216,7 @@ public class PushServiceSocket { } if (response.isSuccessful()) return file.getTransmittedDigest(); - else throw new NonSuccessfulResponseCodeException("Response: " + response); + else throw new NonSuccessfulResponseCodeException(response.code(), "Response: " + response); } finally { synchronized (connections) { connections.remove(call); @@ -1269,7 +1274,7 @@ public class PushServiceSocket { } else if (response.code() == 404) { throw new ResumeLocationInvalidException(); } else { - throw new NonSuccessfulResponseCodeException("Response: " + response); + throw new NonSuccessfulResponseCodeException(response.code(), "Response: " + response); } } finally { synchronized (connections) { @@ -1300,31 +1305,31 @@ public class PushServiceSocket { } private String makeServiceRequest(String urlFragment, String method, String jsonBody) - throws NonSuccessfulResponseCodeException, PushNetworkException + throws NonSuccessfulResponseCodeException, PushNetworkException, MalformedResponseException { return makeServiceRequest(urlFragment, method, jsonBody, NO_HEADERS, NO_HANDLER, Optional.absent()); } private String makeServiceRequest(String urlFragment, String method, String jsonBody, Map headers) - throws NonSuccessfulResponseCodeException, PushNetworkException + throws NonSuccessfulResponseCodeException, PushNetworkException, MalformedResponseException { return makeServiceRequest(urlFragment, method, jsonBody, headers, NO_HANDLER, Optional.absent()); } private String makeServiceRequest(String urlFragment, String method, String jsonBody, Map headers, ResponseCodeHandler responseCodeHandler) - throws NonSuccessfulResponseCodeException, PushNetworkException + throws NonSuccessfulResponseCodeException, PushNetworkException, MalformedResponseException { return makeServiceRequest(urlFragment, method, jsonBody, headers, responseCodeHandler, Optional.absent()); } private String makeServiceRequest(String urlFragment, String method, String jsonBody, Map headers, Optional unidentifiedAccessKey) - throws NonSuccessfulResponseCodeException, PushNetworkException + throws NonSuccessfulResponseCodeException, PushNetworkException, MalformedResponseException { return makeServiceRequest(urlFragment, method, jsonBody, headers, NO_HANDLER, unidentifiedAccessKey); } private String makeServiceRequest(String urlFragment, String method, String jsonBody, Map headers, ResponseCodeHandler responseCodeHandler, Optional unidentifiedAccessKey) - throws NonSuccessfulResponseCodeException, PushNetworkException + throws NonSuccessfulResponseCodeException, PushNetworkException, MalformedResponseException { ResponseBody responseBody = makeServiceBodyRequest(urlFragment, method, jsonRequestBody(jsonBody), headers, responseCodeHandler, unidentifiedAccessKey); try { @@ -1382,7 +1387,7 @@ public class PushServiceSocket { Map headers, ResponseCodeHandler responseCodeHandler, Optional unidentifiedAccessKey) - throws NonSuccessfulResponseCodeException, PushNetworkException + throws NonSuccessfulResponseCodeException, PushNetworkException, MalformedResponseException { return makeServiceRequest(urlFragment, method, body, headers, responseCodeHandler, unidentifiedAccessKey).body(); } @@ -1393,7 +1398,7 @@ public class PushServiceSocket { Map headers, ResponseCodeHandler responseCodeHandler, Optional unidentifiedAccessKey) - throws NonSuccessfulResponseCodeException, PushNetworkException + throws NonSuccessfulResponseCodeException, PushNetworkException, MalformedResponseException { Response response = getServiceConnection(urlFragment, method, body, headers, unidentifiedAccessKey); @@ -1402,7 +1407,8 @@ public class PushServiceSocket { return validateServiceResponse(response); } - private Response validateServiceResponse(Response response) throws NonSuccessfulResponseCodeException, PushNetworkException { + private Response validateServiceResponse(Response response) + throws NonSuccessfulResponseCodeException, PushNetworkException, MalformedResponseException { int responseCode = response.code(); String responseMessage = response.message(); @@ -1411,7 +1417,7 @@ public class PushServiceSocket { throw new RateLimitException("Rate limit exceeded: " + responseCode); case 401: case 403: - throw new AuthorizationFailedException("Authorization failed!"); + throw new AuthorizationFailedException(responseCode, "Authorization failed!"); case 404: throw new NotFoundException("Not found"); case 409: @@ -1444,7 +1450,7 @@ public class PushServiceSocket { } if (responseCode != 200 && responseCode != 204) { - throw new NonSuccessfulResponseCodeException("Bad response: " + responseCode + " " + responseMessage); + throw new NonSuccessfulResponseCodeException(responseCode, "Bad response: " + responseCode + " " + responseMessage); } return response; @@ -1591,14 +1597,14 @@ public class PushServiceSocket { switch (response.code()) { case 401: case 403: - throw new AuthorizationFailedException("Authorization failed!"); + throw new AuthorizationFailedException(response.code(), "Authorization failed!"); case 409: throw new RemoteAttestationResponseExpiredException("Remote attestation response expired"); case 429: throw new RateLimitException("Rate limit exceeded: " + response.code()); } - throw new NonSuccessfulResponseCodeException("Response: " + response); + throw new NonSuccessfulResponseCodeException(response.code(), "Response: " + response); } private ResponseBody makeStorageRequest(String authorization, String path, String method, RequestBody body) @@ -1665,7 +1671,7 @@ public class PushServiceSocket { throw new NoContentException("No content!"); case 401: case 403: - throw new AuthorizationFailedException("Authorization failed!"); + throw new AuthorizationFailedException(response.code(), "Authorization failed!"); case 404: throw new NotFoundException("Not found"); case 409: @@ -1680,7 +1686,7 @@ public class PushServiceSocket { throw new DeprecatedVersionException(); } - throw new NonSuccessfulResponseCodeException("Response: " + response); + throw new NonSuccessfulResponseCodeException(response.code(), "Response: " + response); } public CallingResponse makeCallingRequest(long requestId, String url, String httpMethod, List> headers, byte[] body) { @@ -1852,17 +1858,15 @@ public class PushServiceSocket { /** * Converts {@link IOException} on body reading to {@link PushNetworkException}. - * {@link IOException} during json parsing is converted to a {@link NonSuccessfulResponseCodeException} + * {@link IOException} during json parsing is converted to a {@link MalformedResponseException} */ - private static T readBodyJson(ResponseBody body, Class clazz) - throws PushNetworkException, NonSuccessfulResponseCodeException - { + private static T readBodyJson(ResponseBody body, Class clazz) throws PushNetworkException, MalformedResponseException { String json = readBodyString(body); try { return JsonUtil.fromJson(json, clazz); } catch (JsonProcessingException e) { Log.w(TAG, e); - throw new NonSuccessfulResponseCodeException("Unable to parse entity"); + throw new MalformedResponseException("Unable to parse entity", e); } catch (IOException e) { throw new PushNetworkException(e); } @@ -1873,13 +1877,9 @@ public class PushServiceSocket { * {@link IOException} during json parsing is converted to a {@link NonSuccessfulResponseCodeException} with response code detail. */ private static T readResponseJson(Response response, Class clazz) - throws PushNetworkException, NonSuccessfulResponseCodeException + throws PushNetworkException, MalformedResponseException { - try { return readBodyJson(response.body(), clazz); - } catch (NonSuccessfulResponseCodeException e) { - throw new NonSuccessfulResponseCodeException("Bad response: " + response.code() + " " + response.message()); - } } private static class GcmRegistrationId { @@ -2066,7 +2066,7 @@ public class PushServiceSocket { } public GroupHistory getGroupsV2GroupHistory(int fromVersion, GroupsV2AuthorizationString authorization) - throws NonSuccessfulResponseCodeException, PushNetworkException, InvalidProtocolBufferException + throws IOException, InvalidProtocolBufferException { Response response = makeStorageRequestResponse(authorization.toString(), String.format(Locale.US, GROUPSV2_GROUP_CHANGES, fromVersion), @@ -2085,7 +2085,7 @@ public class PushServiceSocket { return new GroupHistory(groupChanges, contentRange); } else { Log.w(TAG, "Unable to parse Content-Range header: " + contentRangeHeader); - throw new NonSuccessfulResponseCodeException("Unable to parse content range header on 206"); + throw new MalformedResponseException("Unable to parse content range header on 206"); } } diff --git a/libsignal/service/src/main/java/org/whispersystems/signalservice/internal/push/RemoteAttestationUtil.java b/libsignal/service/src/main/java/org/whispersystems/signalservice/internal/push/RemoteAttestationUtil.java index 984ee2f01..92f82e2db 100644 --- a/libsignal/service/src/main/java/org/whispersystems/signalservice/internal/push/RemoteAttestationUtil.java +++ b/libsignal/service/src/main/java/org/whispersystems/signalservice/internal/push/RemoteAttestationUtil.java @@ -4,6 +4,7 @@ import org.whispersystems.libsignal.InvalidKeyException; import org.whispersystems.libsignal.ecc.Curve; import org.whispersystems.libsignal.ecc.ECKeyPair; import org.whispersystems.signalservice.api.crypto.InvalidCiphertextException; +import org.whispersystems.signalservice.api.push.exceptions.MalformedResponseException; import org.whispersystems.signalservice.api.push.exceptions.NonSuccessfulResponseCodeException; import org.whispersystems.signalservice.internal.contacts.crypto.Quote; import org.whispersystems.signalservice.internal.contacts.crypto.RemoteAttestation; @@ -61,7 +62,7 @@ public final class RemoteAttestationUtil { Map attestations = new HashMap<>(); if (response.getAttestations().isEmpty() || response.getAttestations().size() > 3) { - throw new NonSuccessfulResponseCodeException("Incorrect number of attestations: " + response.getAttestations().size()); + throw new MalformedResponseException("Incorrect number of attestations: " + response.getAttestations().size()); } for (Map.Entry entry : response.getAttestations().entrySet()) { @@ -92,7 +93,7 @@ public final class RemoteAttestationUtil { ResponseBody body = response.body(); if (body == null) { - throw new NonSuccessfulResponseCodeException("Empty response!"); + throw new MalformedResponseException("Empty response!"); } return new ResponsePair(body.string(), parseCookies(response)); diff --git a/libsignal/service/src/main/java/org/whispersystems/signalservice/internal/push/exceptions/ForbiddenException.java b/libsignal/service/src/main/java/org/whispersystems/signalservice/internal/push/exceptions/ForbiddenException.java index dddfa86f1..99407f7f4 100644 --- a/libsignal/service/src/main/java/org/whispersystems/signalservice/internal/push/exceptions/ForbiddenException.java +++ b/libsignal/service/src/main/java/org/whispersystems/signalservice/internal/push/exceptions/ForbiddenException.java @@ -3,4 +3,7 @@ package org.whispersystems.signalservice.internal.push.exceptions; import org.whispersystems.signalservice.api.push.exceptions.NonSuccessfulResponseCodeException; public final class ForbiddenException extends NonSuccessfulResponseCodeException { + public ForbiddenException() { + super(403); + } } diff --git a/libsignal/service/src/main/java/org/whispersystems/signalservice/internal/push/exceptions/GroupExistsException.java b/libsignal/service/src/main/java/org/whispersystems/signalservice/internal/push/exceptions/GroupExistsException.java index 760dfda86..4c596e66a 100644 --- a/libsignal/service/src/main/java/org/whispersystems/signalservice/internal/push/exceptions/GroupExistsException.java +++ b/libsignal/service/src/main/java/org/whispersystems/signalservice/internal/push/exceptions/GroupExistsException.java @@ -3,4 +3,7 @@ package org.whispersystems.signalservice.internal.push.exceptions; import org.whispersystems.signalservice.api.push.exceptions.NonSuccessfulResponseCodeException; public final class GroupExistsException extends NonSuccessfulResponseCodeException { + public GroupExistsException() { + super(409); + } } diff --git a/libsignal/service/src/main/java/org/whispersystems/signalservice/internal/push/exceptions/GroupNotFoundException.java b/libsignal/service/src/main/java/org/whispersystems/signalservice/internal/push/exceptions/GroupNotFoundException.java index 1dc53061a..f36f1ae13 100644 --- a/libsignal/service/src/main/java/org/whispersystems/signalservice/internal/push/exceptions/GroupNotFoundException.java +++ b/libsignal/service/src/main/java/org/whispersystems/signalservice/internal/push/exceptions/GroupNotFoundException.java @@ -3,4 +3,7 @@ package org.whispersystems.signalservice.internal.push.exceptions; import org.whispersystems.signalservice.api.push.exceptions.NonSuccessfulResponseCodeException; public final class GroupNotFoundException extends NonSuccessfulResponseCodeException { + public GroupNotFoundException() { + super(404); + } } diff --git a/libsignal/service/src/main/java/org/whispersystems/signalservice/internal/push/exceptions/GroupPatchNotAcceptedException.java b/libsignal/service/src/main/java/org/whispersystems/signalservice/internal/push/exceptions/GroupPatchNotAcceptedException.java index b73195c7f..faf051b47 100644 --- a/libsignal/service/src/main/java/org/whispersystems/signalservice/internal/push/exceptions/GroupPatchNotAcceptedException.java +++ b/libsignal/service/src/main/java/org/whispersystems/signalservice/internal/push/exceptions/GroupPatchNotAcceptedException.java @@ -3,4 +3,7 @@ package org.whispersystems.signalservice.internal.push.exceptions; import org.whispersystems.signalservice.api.push.exceptions.NonSuccessfulResponseCodeException; public final class GroupPatchNotAcceptedException extends NonSuccessfulResponseCodeException { + public GroupPatchNotAcceptedException() { + super(400); + } } diff --git a/libsignal/service/src/main/java/org/whispersystems/signalservice/internal/push/exceptions/MismatchedDevicesException.java b/libsignal/service/src/main/java/org/whispersystems/signalservice/internal/push/exceptions/MismatchedDevicesException.java index 26838d642..494e4c1b9 100644 --- a/libsignal/service/src/main/java/org/whispersystems/signalservice/internal/push/exceptions/MismatchedDevicesException.java +++ b/libsignal/service/src/main/java/org/whispersystems/signalservice/internal/push/exceptions/MismatchedDevicesException.java @@ -14,6 +14,7 @@ public class MismatchedDevicesException extends NonSuccessfulResponseCodeExcepti private final MismatchedDevices mismatchedDevices; public MismatchedDevicesException(MismatchedDevices mismatchedDevices) { + super(409); this.mismatchedDevices = mismatchedDevices; } diff --git a/libsignal/service/src/main/java/org/whispersystems/signalservice/internal/push/exceptions/NotInGroupException.java b/libsignal/service/src/main/java/org/whispersystems/signalservice/internal/push/exceptions/NotInGroupException.java index eb7502b66..2c3c01a9f 100644 --- a/libsignal/service/src/main/java/org/whispersystems/signalservice/internal/push/exceptions/NotInGroupException.java +++ b/libsignal/service/src/main/java/org/whispersystems/signalservice/internal/push/exceptions/NotInGroupException.java @@ -3,4 +3,7 @@ package org.whispersystems.signalservice.internal.push.exceptions; import org.whispersystems.signalservice.api.push.exceptions.NonSuccessfulResponseCodeException; public final class NotInGroupException extends NonSuccessfulResponseCodeException { + public NotInGroupException() { + super(403); + } } diff --git a/libsignal/service/src/main/java/org/whispersystems/signalservice/internal/push/exceptions/StaleDevicesException.java b/libsignal/service/src/main/java/org/whispersystems/signalservice/internal/push/exceptions/StaleDevicesException.java index 64a1f3207..f6120914d 100644 --- a/libsignal/service/src/main/java/org/whispersystems/signalservice/internal/push/exceptions/StaleDevicesException.java +++ b/libsignal/service/src/main/java/org/whispersystems/signalservice/internal/push/exceptions/StaleDevicesException.java @@ -14,6 +14,7 @@ public class StaleDevicesException extends NonSuccessfulResponseCodeException { private final StaleDevices staleDevices; public StaleDevicesException(StaleDevices staleDevices) { + super(410); this.staleDevices = staleDevices; }