diff options
author | Samuel Holland <samuel@sholland.org> | 2018-12-15 14:45:14 -0600 |
---|---|---|
committer | Samuel Holland <samuel@sholland.org> | 2018-12-15 14:46:23 -0600 |
commit | 2e8d566bd42ac747ad276eb5e328ee2303c48c26 (patch) | |
tree | 50cd35a1bc93e6668a9db982af50b7e5b70c6e1e /app/src/main/java/com/wireguard/android/util | |
parent | dcb0e9b3e8643bc73a67c874b9add72cc0ee8f6e (diff) |
Clean up error messages
Signed-off-by: Jason A. Donenfeld <Jason@zx2c4.com>
Diffstat (limited to 'app/src/main/java/com/wireguard/android/util')
3 files changed, 132 insertions, 51 deletions
diff --git a/app/src/main/java/com/wireguard/android/util/ErrorMessages.java b/app/src/main/java/com/wireguard/android/util/ErrorMessages.java new file mode 100644 index 00000000..0f49448c --- /dev/null +++ b/app/src/main/java/com/wireguard/android/util/ErrorMessages.java @@ -0,0 +1,130 @@ +/* + * Copyright © 2018 WireGuard LLC. All Rights Reserved. + * SPDX-License-Identifier: Apache-2.0 + */ + +package com.wireguard.android.util; + +import android.content.res.Resources; +import android.support.annotation.Nullable; + +import com.wireguard.android.Application; +import com.wireguard.android.R; +import com.wireguard.config.BadConfigException; +import com.wireguard.config.BadConfigException.Location; +import com.wireguard.config.BadConfigException.Reason; +import com.wireguard.config.InetEndpoint; +import com.wireguard.config.InetNetwork; +import com.wireguard.config.ParseException; +import com.wireguard.crypto.Key.Format; +import com.wireguard.crypto.KeyFormatException; +import com.wireguard.crypto.KeyFormatException.Type; + +import java.net.InetAddress; +import java.util.EnumMap; +import java.util.Map; + +import java9.util.Maps; + +public final class ErrorMessages { + private static final Map<Reason, Integer> BCE_REASON_MAP = new EnumMap<>(Maps.of( + Reason.INVALID_KEY, R.string.bad_config_reason_invalid_key, + Reason.INVALID_NUMBER, R.string.bad_config_reason_invalid_number, + Reason.INVALID_VALUE, R.string.bad_config_reason_invalid_value, + Reason.MISSING_ATTRIBUTE, R.string.bad_config_reason_missing_attribute, + Reason.MISSING_SECTION, R.string.bad_config_reason_missing_section, + Reason.MISSING_VALUE, R.string.bad_config_reason_missing_value, + Reason.SYNTAX_ERROR, R.string.bad_config_reason_syntax_error, + Reason.UNKNOWN_ATTRIBUTE, R.string.bad_config_reason_unknown_attribute, + Reason.UNKNOWN_SECTION, R.string.bad_config_reason_unknown_section + )); + private static final Map<Format, Integer> KFE_FORMAT_MAP = new EnumMap<>(Maps.of( + Format.BASE64, R.string.key_length_explanation_base64, + Format.BINARY, R.string.key_length_explanation_binary, + Format.HEX, R.string.key_length_explanation_hex + )); + private static final Map<Type, Integer> KFE_TYPE_MAP = new EnumMap<>(Maps.of( + Type.CONTENTS, R.string.key_contents_error, + Type.LENGTH, R.string.key_length_error + )); + private static final Map<Class, Integer> PE_CLASS_MAP = Maps.of( + InetAddress.class, R.string.parse_error_inet_address, + InetEndpoint.class, R.string.parse_error_inet_endpoint, + InetNetwork.class, R.string.parse_error_inet_network, + Integer.class, R.string.parse_error_integer + ); + + private ErrorMessages() { + // Prevent instantiation + } + + public static String get(@Nullable final Throwable throwable) { + final Resources resources = Application.get().getResources(); + if (throwable == null) + return resources.getString(R.string.unknown_error); + final Throwable rootCause = rootCause(throwable); + final String message; + if (rootCause instanceof BadConfigException) { + final BadConfigException bce = (BadConfigException) rootCause; + final String reason = getBadConfigExceptionReason(resources, bce); + final String context = bce.getLocation() == Location.TOP_LEVEL ? + resources.getString(R.string.bad_config_context_top_level, + bce.getSection().getName()) : + resources.getString(R.string.bad_config_context, + bce.getSection().getName(), + bce.getLocation().getName()); + final String explanation = getBadConfigExceptionExplanation(resources, bce); + message = resources.getString(R.string.bad_config_error, reason, context) + explanation; + } else if (rootCause.getMessage() != null) { + message = rootCause.getMessage(); + } else { + final String errorType = rootCause.getClass().getSimpleName(); + message = resources.getString(R.string.generic_error, errorType); + } + return message; + } + + private static String getBadConfigExceptionExplanation(final Resources resources, + final BadConfigException bce) { + if (bce.getCause() instanceof KeyFormatException) { + final KeyFormatException kfe = (KeyFormatException) bce.getCause(); + if (kfe.getType() == Type.LENGTH) + return resources.getString(KFE_FORMAT_MAP.get(kfe.getFormat())); + } else if (bce.getCause() instanceof ParseException) { + final ParseException pe = (ParseException) bce.getCause(); + if (pe.getMessage() != null) + return ": " + pe.getMessage(); + } else if (bce.getLocation() == Location.LISTEN_PORT) { + return resources.getString(R.string.bad_config_explanation_udp_port); + } else if (bce.getLocation() == Location.MTU) { + return resources.getString(R.string.bad_config_explanation_positive_number); + } else if (bce.getLocation() == Location.PERSISTENT_KEEPALIVE) { + return resources.getString(R.string.bad_config_explanation_pka); + } + return ""; + } + + private static String getBadConfigExceptionReason(final Resources resources, + final BadConfigException bce) { + if (bce.getCause() instanceof KeyFormatException) { + final KeyFormatException kfe = (KeyFormatException) bce.getCause(); + return resources.getString(KFE_TYPE_MAP.get(kfe.getType())); + } else if (bce.getCause() instanceof ParseException) { + final ParseException pe = (ParseException) bce.getCause(); + final String type = resources.getString(PE_CLASS_MAP.containsKey(pe.getParsingClass()) ? + PE_CLASS_MAP.get(pe.getParsingClass()) : R.string.parse_error_generic); + return resources.getString(R.string.parse_error_reason, type, pe.getText()); + } + return resources.getString(BCE_REASON_MAP.get(bce.getReason()), bce.getText()); + } + + private static Throwable rootCause(final Throwable throwable) { + Throwable cause = throwable; + while (cause.getCause() != null) { + if (cause instanceof BadConfigException) + break; + cause = cause.getCause(); + } + return cause; + } +} diff --git a/app/src/main/java/com/wireguard/android/util/ExceptionLoggers.java b/app/src/main/java/com/wireguard/android/util/ExceptionLoggers.java index 3cb5ca9f..5188112c 100644 --- a/app/src/main/java/com/wireguard/android/util/ExceptionLoggers.java +++ b/app/src/main/java/com/wireguard/android/util/ExceptionLoggers.java @@ -5,17 +5,9 @@ package com.wireguard.android.util; -import android.content.res.Resources; import android.support.annotation.Nullable; import android.util.Log; -import com.wireguard.android.Application; -import com.wireguard.android.R; -import com.wireguard.config.BadConfigException; -import com.wireguard.config.ParseException; -import com.wireguard.crypto.KeyFormatException; - -import java9.util.concurrent.CompletionException; import java9.util.function.BiConsumer; /** @@ -28,53 +20,12 @@ public enum ExceptionLoggers implements BiConsumer<Object, Throwable> { E(Log.ERROR); private static final String TAG = "WireGuard/" + ExceptionLoggers.class.getSimpleName(); - private final int priority; ExceptionLoggers(final int priority) { this.priority = priority; } - public static Throwable unwrap(final Throwable throwable) { - if (throwable instanceof CompletionException && throwable.getCause() != null) - return throwable.getCause(); - if (throwable instanceof ParseException && throwable.getCause() != null) - return throwable.getCause(); - return throwable; - } - - public static String unwrapMessage(final Throwable throwable) { - final Throwable innerThrowable = unwrap(throwable); - final Resources resources = Application.get().getResources(); - String message; - if (innerThrowable instanceof BadConfigException) { - final BadConfigException configException = (BadConfigException) innerThrowable; - message = resources.getString(R.string.parse_error, configException.getText(), configException.getLocation()); - final Throwable cause = unwrap(configException); - if (cause.getMessage() != null) - message += ": " + cause.getMessage(); - } else if (innerThrowable instanceof KeyFormatException) { - final KeyFormatException keyFormatException = (KeyFormatException) innerThrowable; - switch (keyFormatException.getFormat()) { - case BASE64: - message = resources.getString(R.string.key_length_base64_exception_message); - break; - case BINARY: - message = resources.getString(R.string.key_length_exception_message); - break; - case HEX: - message = resources.getString(R.string.key_length_hex_exception_message); - break; - default: - // Will never happen, as getFormat is not nullable. - message = null; - } - } else { - message = innerThrowable.getMessage(); - } - return message != null ? message : innerThrowable.getClass().getSimpleName(); - } - @Override public void accept(final Object result, @Nullable final Throwable throwable) { if (throwable != null) diff --git a/app/src/main/java/com/wireguard/android/util/RootShell.java b/app/src/main/java/com/wireguard/android/util/RootShell.java index e48e3564..2dc02b56 100644 --- a/app/src/main/java/com/wireguard/android/util/RootShell.java +++ b/app/src/main/java/com/wireguard/android/util/RootShell.java @@ -123,9 +123,9 @@ public class RootShell { } } if (markersSeen != 4) - throw new IOException(context.getString(R.string.marker_count_error, markersSeen)); + throw new IOException(context.getString(R.string.shell_marker_count_error, markersSeen)); if (errnoStdout != errnoStderr) - throw new IOException(context.getString(R.string.exit_status_read_error)); + throw new IOException(context.getString(R.string.shell_exit_status_read_error)); Log.v(TAG, "exit: " + errnoStdout); return errnoStdout; } |