diff options
author | Samuel Holland <samuel@sholland.org> | 2018-12-13 21:30:38 -0600 |
---|---|---|
committer | Samuel Holland <samuel@sholland.org> | 2018-12-15 14:46:23 -0600 |
commit | dcb0e9b3e8643bc73a67c874b9add72cc0ee8f6e (patch) | |
tree | e0f720a7315a60827d19daa8ee155f09eab61586 /app/src/main/java/com/wireguard/config | |
parent | 3497882ea6ae74ef6da0984a21398963624e9561 (diff) |
Provide semantically meaningful exceptions for translation
Signed-off-by: Jason A. Donenfeld <Jason@zx2c4.com>
Diffstat (limited to 'app/src/main/java/com/wireguard/config')
8 files changed, 262 insertions, 107 deletions
diff --git a/app/src/main/java/com/wireguard/config/BadConfigException.java b/app/src/main/java/com/wireguard/config/BadConfigException.java new file mode 100644 index 00000000..7f794a35 --- /dev/null +++ b/app/src/main/java/com/wireguard/config/BadConfigException.java @@ -0,0 +1,118 @@ +/* + * Copyright © 2018 WireGuard LLC. All Rights Reserved. + * SPDX-License-Identifier: Apache-2.0 + */ + +package com.wireguard.config; + +import android.support.annotation.Nullable; + +import com.wireguard.crypto.KeyFormatException; + +public class BadConfigException extends Exception { + private final Location location; + private final Reason reason; + private final Section section; + @Nullable private final CharSequence text; + + private BadConfigException(final Section section, final Location location, + final Reason reason, @Nullable final CharSequence text, + @Nullable final Throwable cause) { + super(cause); + this.section = section; + this.location = location; + this.reason = reason; + this.text = text; + } + + public BadConfigException(final Section section, final Location location, + final Reason reason, @Nullable final CharSequence text) { + this(section, location, reason, text, null); + } + + public BadConfigException(final Section section, final Location location, + final KeyFormatException cause) { + this(section, location, Reason.INVALID_KEY, null, cause); + } + + public BadConfigException(final Section section, final Location location, + @Nullable final CharSequence text, + final NumberFormatException cause) { + this(section, location, Reason.INVALID_NUMBER, text, cause); + } + + public BadConfigException(final Section section, final Location location, + final ParseException cause) { + this(section, location, Reason.INVALID_VALUE, cause.getText(), cause); + } + + public Location getLocation() { + return location; + } + + public Reason getReason() { + return reason; + } + + public Section getSection() { + return section; + } + + @Nullable + public CharSequence getText() { + return text; + } + + public enum Location { + TOP_LEVEL(""), + ADDRESS("Address"), + ALLOWED_IPS("AllowedIPs"), + DNS("DNS"), + ENDPOINT("Endpoint"), + EXCLUDED_APPLICATIONS("ExcludedApplications"), + LISTEN_PORT("ListenPort"), + MTU("MTU"), + PERSISTENT_KEEPALIVE("PersistentKeepalive"), + PRE_SHARED_KEY("PresharedKey"), + PRIVATE_KEY("PrivateKey"), + PUBLIC_KEY("PublicKey"); + + private final String name; + + Location(final String name) { + this.name = name; + } + + public String getName() { + return name; + } + } + + public enum Reason { + INVALID_KEY, + INVALID_NUMBER, + INVALID_VALUE, + MISSING_ATTRIBUTE, + MISSING_SECTION, + MISSING_VALUE, + SYNTAX_ERROR, + UNKNOWN_ATTRIBUTE, + UNKNOWN_SECTION + } + + public enum Section { + CONFIG("Config"), + INTERFACE("Interface"), + PEER("Peer"); + + private final String name; + + Section(final String name) { + this.name = name; + } + + public String getName() { + return name; + } + } +} diff --git a/app/src/main/java/com/wireguard/config/Config.java b/app/src/main/java/com/wireguard/config/Config.java index d2c1395f..8b393bef 100644 --- a/app/src/main/java/com/wireguard/config/Config.java +++ b/app/src/main/java/com/wireguard/config/Config.java @@ -7,6 +7,10 @@ package com.wireguard.config; import android.support.annotation.Nullable; +import com.wireguard.config.BadConfigException.Location; +import com.wireguard.config.BadConfigException.Reason; +import com.wireguard.config.BadConfigException.Section; + import java.io.BufferedReader; import java.io.IOException; import java.io.InputStream; @@ -37,23 +41,27 @@ public final class Config { /** * Parses an series of "Interface" and "Peer" sections into a {@code Config}. Throws - * {@link ParseException} if the input is not well-formed or contains unparseable sections. + * {@link BadConfigException} if the input is not well-formed or contains data that cannot + * be parsed. * - * @param stream a stream of UTF-8 text that is interpreted as a WireGuard configuration file + * @param stream a stream of UTF-8 text that is interpreted as a WireGuard configuration * @return a {@code Config} instance representing the supplied configuration */ - public static Config parse(final InputStream stream) throws IOException, ParseException { + public static Config parse(final InputStream stream) + throws IOException, BadConfigException { return parse(new BufferedReader(new InputStreamReader(stream))); } /** * Parses an series of "Interface" and "Peer" sections into a {@code Config}. Throws - * {@link ParseException} if the input is not well-formed or contains unparseable sections. + * {@link BadConfigException} if the input is not well-formed or contains data that cannot + * be parsed. * - * @param reader a BufferedReader of UTF-8 text that is interpreted as a WireGuard configuration file + * @param reader a BufferedReader of UTF-8 text that is interpreted as a WireGuard configuration * @return a {@code Config} instance representing the supplied configuration */ - public static Config parse(final BufferedReader reader) throws IOException, ParseException { + public static Config parse(final BufferedReader reader) + throws IOException, BadConfigException { final Builder builder = new Builder(); final Collection<String> interfaceLines = new ArrayList<>(); final Collection<String> peerLines = new ArrayList<>(); @@ -80,20 +88,23 @@ public final class Config { inInterfaceSection = false; inPeerSection = true; } else { - throw new ParseException("top level", line, "Unknown section name"); + throw new BadConfigException(Section.CONFIG, Location.TOP_LEVEL, + Reason.UNKNOWN_SECTION, line); } } else if (inInterfaceSection) { interfaceLines.add(line); } else if (inPeerSection) { peerLines.add(line); } else { - throw new ParseException("top level", line, "Expected [Interface] or [Peer]"); + throw new BadConfigException(Section.CONFIG, Location.TOP_LEVEL, + Reason.UNKNOWN_SECTION, line); } } if (inPeerSection) builder.parsePeer(peerLines); else if (!inInterfaceSection) - throw new ParseException("top level", "", "Empty configuration"); + throw new BadConfigException(Section.CONFIG, Location.TOP_LEVEL, + Reason.MISSING_SECTION, null); // Combine all [Interface] sections in the file. builder.parseInterface(interfaceLines); return builder.build(); @@ -192,11 +203,13 @@ public final class Config { return new Config(this); } - public Builder parseInterface(final Iterable<? extends CharSequence> lines) throws ParseException { + public Builder parseInterface(final Iterable<? extends CharSequence> lines) + throws BadConfigException { return setInterface(Interface.parse(lines)); } - public Builder parsePeer(final Iterable<? extends CharSequence> lines) throws ParseException { + public Builder parsePeer(final Iterable<? extends CharSequence> lines) + throws BadConfigException { return addPeer(Peer.parse(lines)); } diff --git a/app/src/main/java/com/wireguard/config/InetAddresses.java b/app/src/main/java/com/wireguard/config/InetAddresses.java index 989598da..487b136c 100644 --- a/app/src/main/java/com/wireguard/config/InetAddresses.java +++ b/app/src/main/java/com/wireguard/config/InetAddresses.java @@ -37,17 +37,18 @@ public final class InetAddresses { * @param address a string representing the IP address * @return an instance of {@link Inet4Address} or {@link Inet6Address}, as appropriate */ - public static InetAddress parse(final String address) { + public static InetAddress parse(final String address) throws ParseException { if (address.isEmpty()) - throw new IllegalArgumentException("Empty address"); + throw new ParseException(InetAddress.class, address, "Empty address"); try { return (InetAddress) PARSER_METHOD.invoke(null, address); } catch (final IllegalAccessException | InvocationTargetException e) { final Throwable cause = e.getCause(); // Re-throw parsing exceptions with the original type, as callers might try to catch // them. On the other hand, callers cannot be expected to handle reflection failures. - throw cause instanceof IllegalArgumentException ? - (IllegalArgumentException) cause : new RuntimeException(e); + if (cause instanceof IllegalArgumentException) + throw new ParseException(InetAddress.class, address, cause); + throw new RuntimeException(e); } } } diff --git a/app/src/main/java/com/wireguard/config/InetEndpoint.java b/app/src/main/java/com/wireguard/config/InetEndpoint.java index 355b325a..f64bc25a 100644 --- a/app/src/main/java/com/wireguard/config/InetEndpoint.java +++ b/app/src/main/java/com/wireguard/config/InetEndpoint.java @@ -42,9 +42,9 @@ public final class InetEndpoint { this.port = port; } - public static InetEndpoint parse(final String endpoint) { + public static InetEndpoint parse(final String endpoint) throws ParseException { if (FORBIDDEN_CHARACTERS.matcher(endpoint).find()) - throw new IllegalArgumentException("Forbidden characters in endpoint"); + throw new ParseException(InetEndpoint.class, endpoint, "Forbidden characters"); final URI uri; try { uri = new URI("wg://" + endpoint); @@ -52,12 +52,12 @@ public final class InetEndpoint { throw new IllegalArgumentException(e); } if (uri.getPort() < 0) - throw new IllegalArgumentException("An endpoint must specify a port (e.g. 51820)"); + throw new ParseException(InetEndpoint.class, endpoint, "Missing/invalid port number"); try { InetAddresses.parse(uri.getHost()); // Parsing ths host as a numeric address worked, so we don't need to do DNS lookups. return new InetEndpoint(uri.getHost(), true, uri.getPort()); - } catch (final IllegalArgumentException ignored) { + } catch (final ParseException ignored) { // Failed to parse the host as a numeric address, so it must be a DNS hostname/FQDN. return new InetEndpoint(uri.getHost(), false, uri.getPort()); } diff --git a/app/src/main/java/com/wireguard/config/InetNetwork.java b/app/src/main/java/com/wireguard/config/InetNetwork.java index 9e5e8c64..444af58e 100644 --- a/app/src/main/java/com/wireguard/config/InetNetwork.java +++ b/app/src/main/java/com/wireguard/config/InetNetwork.java @@ -22,19 +22,28 @@ public final class InetNetwork { this.mask = mask; } - public static InetNetwork parse(final String network) { + public static InetNetwork parse(final String network) throws ParseException { final int slash = network.lastIndexOf('/'); + final String maskString; final int rawMask; final String rawAddress; if (slash >= 0) { - rawMask = Integer.parseInt(network.substring(slash + 1), 10); + maskString = network.substring(slash + 1); + try { + rawMask = Integer.parseInt(maskString, 10); + } catch (final NumberFormatException ignored) { + throw new ParseException(Integer.class, maskString); + } rawAddress = network.substring(0, slash); } else { + maskString = ""; rawMask = -1; rawAddress = network; } final InetAddress address = InetAddresses.parse(rawAddress); final int maxMask = (address instanceof Inet4Address) ? 32 : 128; + if (rawMask > maxMask) + throw new ParseException(InetNetwork.class, maskString, "Invalid network mask"); final int mask = rawMask >= 0 && rawMask <= maxMask ? rawMask : maxMask; return new InetNetwork(address, mask); } diff --git a/app/src/main/java/com/wireguard/config/Interface.java b/app/src/main/java/com/wireguard/config/Interface.java index da30fbcc..2fd34a32 100644 --- a/app/src/main/java/com/wireguard/config/Interface.java +++ b/app/src/main/java/com/wireguard/config/Interface.java @@ -7,7 +7,11 @@ package com.wireguard.config; import android.support.annotation.Nullable; +import com.wireguard.config.BadConfigException.Location; +import com.wireguard.config.BadConfigException.Reason; +import com.wireguard.config.BadConfigException.Section; import com.wireguard.crypto.Key; +import com.wireguard.crypto.KeyFormatException; import com.wireguard.crypto.KeyPair; import java.net.InetAddress; @@ -22,7 +26,6 @@ import java.util.Set; import java9.util.Lists; import java9.util.Optional; import java9.util.stream.Collectors; -import java9.util.stream.Stream; import java9.util.stream.StreamSupport; /** @@ -60,11 +63,13 @@ public final class Interface { * @param lines An iterable sequence of lines, containing at least a private key attribute * @return An {@code Interface} with all of the attributes from {@code lines} set */ - public static Interface parse(final Iterable<? extends CharSequence> lines) throws ParseException { + public static Interface parse(final Iterable<? extends CharSequence> lines) + throws BadConfigException { final Builder builder = new Builder(); for (final CharSequence line : lines) { - final Attribute attribute = Attribute.parse(line) - .orElseThrow(() -> new ParseException("[Interface]", line, "Syntax error")); + final Attribute attribute = Attribute.parse(line).orElseThrow(() -> + new BadConfigException(Section.INTERFACE, Location.TOP_LEVEL, + Reason.SYNTAX_ERROR, line)); switch (attribute.getKey().toLowerCase(Locale.ENGLISH)) { case "address": builder.parseAddresses(attribute.getValue()); @@ -85,7 +90,8 @@ public final class Interface { builder.parsePrivateKey(attribute.getValue()); break; default: - throw new ParseException("[Interface]", attribute.getKey(), "Unknown attribute"); + throw new BadConfigException(Section.INTERFACE, Location.TOP_LEVEL, + Reason.UNKNOWN_ATTRIBUTE, attribute.getKey()); } } return builder.build(); @@ -260,9 +266,10 @@ public final class Interface { return this; } - public Interface build() { + public Interface build() throws BadConfigException { if (keyPair == null) - throw new IllegalArgumentException("Interfaces must have a private key"); + throw new BadConfigException(Section.INTERFACE, Location.PRIVATE_KEY, + Reason.MISSING_ATTRIBUTE, null); return new Interface(this); } @@ -276,57 +283,51 @@ public final class Interface { return this; } - public Builder parseAddresses(final CharSequence addresses) throws ParseException { + public Builder parseAddresses(final CharSequence addresses) throws BadConfigException { try { - final List<InetNetwork> parsed = Stream.of(Attribute.split(addresses)) - .map(InetNetwork::parse) - .collect(Collectors.toUnmodifiableList()); - return addAddresses(parsed); - } catch (final IllegalArgumentException e) { - throw new ParseException("Address", addresses, e); + for (final String address : Attribute.split(addresses)) + addAddress(InetNetwork.parse(address)); + return this; + } catch (final ParseException e) { + throw new BadConfigException(Section.INTERFACE, Location.ADDRESS, e); } } - public Builder parseDnsServers(final CharSequence dnsServers) throws ParseException { + public Builder parseDnsServers(final CharSequence dnsServers) throws BadConfigException { try { - final List<InetAddress> parsed = Stream.of(Attribute.split(dnsServers)) - .map(InetAddresses::parse) - .collect(Collectors.toUnmodifiableList()); - return addDnsServers(parsed); - } catch (final IllegalArgumentException e) { - throw new ParseException("DNS", dnsServers, e); + for (final String dnsServer : Attribute.split(dnsServers)) + addDnsServer(InetAddresses.parse(dnsServer)); + return this; + } catch (final ParseException e) { + throw new BadConfigException(Section.INTERFACE, Location.DNS, e); } } - public Builder parseExcludedApplications(final CharSequence apps) throws ParseException { - try { - return excludeApplications(Lists.of(Attribute.split(apps))); - } catch (final IllegalArgumentException e) { - throw new ParseException("ExcludedApplications", apps, e); - } + public Builder parseExcludedApplications(final CharSequence apps) { + return excludeApplications(Lists.of(Attribute.split(apps))); } - public Builder parseListenPort(final String listenPort) throws ParseException { + public Builder parseListenPort(final String listenPort) throws BadConfigException { try { return setListenPort(Integer.parseInt(listenPort)); - } catch (final IllegalArgumentException e) { - throw new ParseException("ListenPort", listenPort, e); + } catch (final NumberFormatException e) { + throw new BadConfigException(Section.INTERFACE, Location.LISTEN_PORT, listenPort, e); } } - public Builder parseMtu(final String mtu) throws ParseException { + public Builder parseMtu(final String mtu) throws BadConfigException { try { return setMtu(Integer.parseInt(mtu)); - } catch (final IllegalArgumentException e) { - throw new ParseException("MTU", mtu, e); + } catch (final NumberFormatException e) { + throw new BadConfigException(Section.INTERFACE, Location.MTU, mtu, e); } } - public Builder parsePrivateKey(final String privateKey) throws ParseException { + public Builder parsePrivateKey(final String privateKey) throws BadConfigException { try { return setKeyPair(new KeyPair(Key.fromBase64(privateKey))); - } catch (final Key.KeyFormatException e) { - throw new ParseException("PrivateKey", "(omitted)", e); + } catch (final KeyFormatException e) { + throw new BadConfigException(Section.INTERFACE, Location.PRIVATE_KEY, e); } } @@ -335,16 +336,18 @@ public final class Interface { return this; } - public Builder setListenPort(final int listenPort) { + public Builder setListenPort(final int listenPort) throws BadConfigException { if (listenPort < MIN_UDP_PORT || listenPort > MAX_UDP_PORT) - throw new IllegalArgumentException("ListenPort must be a valid UDP port number"); + throw new BadConfigException(Section.INTERFACE, Location.LISTEN_PORT, + Reason.INVALID_VALUE, String.valueOf(listenPort)); this.listenPort = listenPort == 0 ? Optional.empty() : Optional.of(listenPort); return this; } - public Builder setMtu(final int mtu) { + public Builder setMtu(final int mtu) throws BadConfigException { if (mtu < 0) - throw new IllegalArgumentException("MTU must not be negative"); + throw new BadConfigException(Section.INTERFACE, Location.LISTEN_PORT, + Reason.INVALID_VALUE, String.valueOf(mtu)); this.mtu = mtu == 0 ? Optional.empty() : Optional.of(mtu); return this; } diff --git a/app/src/main/java/com/wireguard/config/ParseException.java b/app/src/main/java/com/wireguard/config/ParseException.java index 1fccb534..c8482af2 100644 --- a/app/src/main/java/com/wireguard/config/ParseException.java +++ b/app/src/main/java/com/wireguard/config/ParseException.java @@ -5,34 +5,37 @@ package com.wireguard.config; +import android.support.annotation.Nullable; + /** - * An exception representing a failure to parse an element of a WireGuard configuration. The context - * for this failure can be retrieved with {@link #getContext}, and the text that failed to parse can - * be retrieved with {@link #getText}. */ public class ParseException extends Exception { - private final String context; + private final Class<?> parsingClass; private final CharSequence text; - public ParseException(final String context, final CharSequence text, final String message) { - super(message); - this.context = context; + public ParseException(final Class<?> parsingClass, final CharSequence text, + @Nullable final String message, @Nullable final Throwable cause) { + super(message, cause); + this.parsingClass = parsingClass; this.text = text; } - public ParseException(final String context, final CharSequence text, final Throwable cause) { - super(cause.getMessage(), cause); - this.context = context; - this.text = text; + public ParseException(final Class<?> parsingClass, final CharSequence text, + @Nullable final String message) { + this(parsingClass, text, message, null); } - public ParseException(final String context, final CharSequence text) { - this.context = context; - this.text = text; + public ParseException(final Class<?> parsingClass, final CharSequence text, + @Nullable final Throwable cause) { + this(parsingClass, text, null, cause); + } + + public ParseException(final Class<?> parsingClass, final CharSequence text) { + this(parsingClass, text, null, null); } - public String getContext() { - return context; + public Class<?> getParsingClass() { + return parsingClass; } public CharSequence getText() { diff --git a/app/src/main/java/com/wireguard/config/Peer.java b/app/src/main/java/com/wireguard/config/Peer.java index 1250fcb3..cdea030a 100644 --- a/app/src/main/java/com/wireguard/config/Peer.java +++ b/app/src/main/java/com/wireguard/config/Peer.java @@ -7,19 +7,20 @@ package com.wireguard.config; import android.support.annotation.Nullable; +import com.wireguard.config.BadConfigException.Location; +import com.wireguard.config.BadConfigException.Reason; +import com.wireguard.config.BadConfigException.Section; import com.wireguard.crypto.Key; +import com.wireguard.crypto.KeyFormatException; import java.util.Collection; import java.util.Collections; import java.util.LinkedHashSet; -import java.util.List; import java.util.Locale; import java.util.Objects; import java.util.Set; import java9.util.Optional; -import java9.util.stream.Collectors; -import java9.util.stream.Stream; /** * Represents the configuration for a WireGuard peer (a [Peer] block). Peers must have a public key, @@ -50,11 +51,13 @@ public final class Peer { * @param lines an iterable sequence of lines, containing at least a public key attribute * @return a {@code Peer} with all of its attributes set from {@code lines} */ - public static Peer parse(final Iterable<? extends CharSequence> lines) throws ParseException { + public static Peer parse(final Iterable<? extends CharSequence> lines) + throws BadConfigException { final Builder builder = new Builder(); for (final CharSequence line : lines) { - final Attribute attribute = Attribute.parse(line) - .orElseThrow(() -> new ParseException("[Peer]", line, "Syntax error")); + final Attribute attribute = Attribute.parse(line).orElseThrow(() -> + new BadConfigException(Section.PEER, Location.TOP_LEVEL, + Reason.SYNTAX_ERROR, line)); switch (attribute.getKey().toLowerCase(Locale.ENGLISH)) { case "allowedips": builder.parseAllowedIPs(attribute.getValue()); @@ -72,7 +75,8 @@ public final class Peer { builder.parsePublicKey(attribute.getValue()); break; default: - throw new ParseException("[Peer]", line, "Unknown attribute"); + throw new BadConfigException(Section.PEER, Location.TOP_LEVEL, + Reason.UNKNOWN_ATTRIBUTE, attribute.getKey()); } } return builder.build(); @@ -223,52 +227,54 @@ public final class Peer { return this; } - public Peer build() { + public Peer build() throws BadConfigException { if (publicKey == null) - throw new IllegalArgumentException("Peers must have a public key"); + throw new BadConfigException(Section.PEER, Location.PUBLIC_KEY, + Reason.MISSING_ATTRIBUTE, null); return new Peer(this); } - public Builder parseAllowedIPs(final CharSequence allowedIps) throws ParseException { + public Builder parseAllowedIPs(final CharSequence allowedIps) throws BadConfigException { try { - final List<InetNetwork> parsed = Stream.of(Attribute.split(allowedIps)) - .map(InetNetwork::parse) - .collect(Collectors.toUnmodifiableList()); - return addAllowedIps(parsed); - } catch (final IllegalArgumentException e) { - throw new ParseException("AllowedIPs", allowedIps, e); + for (final String allowedIp : Attribute.split(allowedIps)) + addAllowedIp(InetNetwork.parse(allowedIp)); + return this; + } catch (final ParseException e) { + throw new BadConfigException(Section.PEER, Location.ALLOWED_IPS, e); } } - public Builder parseEndpoint(final String endpoint) throws ParseException { + public Builder parseEndpoint(final String endpoint) throws BadConfigException { try { return setEndpoint(InetEndpoint.parse(endpoint)); - } catch (final IllegalArgumentException e) { - throw new ParseException("Endpoint", endpoint, e); + } catch (final ParseException e) { + throw new BadConfigException(Section.PEER, Location.ENDPOINT, e); } } - public Builder parsePersistentKeepalive(final String persistentKeepalive) throws ParseException { + public Builder parsePersistentKeepalive(final String persistentKeepalive) + throws BadConfigException { try { return setPersistentKeepalive(Integer.parseInt(persistentKeepalive)); - } catch (final IllegalArgumentException e) { - throw new ParseException("PersistentKeepalive", persistentKeepalive, e); + } catch (final NumberFormatException e) { + throw new BadConfigException(Section.PEER, Location.PERSISTENT_KEEPALIVE, + persistentKeepalive, e); } } - public Builder parsePreSharedKey(final String preSharedKey) throws ParseException { + public Builder parsePreSharedKey(final String preSharedKey) throws BadConfigException { try { return setPreSharedKey(Key.fromBase64(preSharedKey)); - } catch (final Key.KeyFormatException e) { - throw new ParseException("PresharedKey", preSharedKey, e); + } catch (final KeyFormatException e) { + throw new BadConfigException(Section.PEER, Location.PRE_SHARED_KEY, e); } } - public Builder parsePublicKey(final String publicKey) throws ParseException { + public Builder parsePublicKey(final String publicKey) throws BadConfigException { try { return setPublicKey(Key.fromBase64(publicKey)); - } catch (final Key.KeyFormatException e) { - throw new ParseException("PublicKey", publicKey, e); + } catch (final KeyFormatException e) { + throw new BadConfigException(Section.PEER, Location.PUBLIC_KEY, e); } } @@ -277,9 +283,11 @@ public final class Peer { return this; } - public Builder setPersistentKeepalive(final int persistentKeepalive) { + public Builder setPersistentKeepalive(final int persistentKeepalive) + throws BadConfigException { if (persistentKeepalive < 0 || persistentKeepalive > MAX_PERSISTENT_KEEPALIVE) - throw new IllegalArgumentException("Invalid value for PersistentKeepalive"); + throw new BadConfigException(Section.PEER, Location.PERSISTENT_KEEPALIVE, + Reason.INVALID_VALUE, String.valueOf(persistentKeepalive)); this.persistentKeepalive = persistentKeepalive == 0 ? Optional.empty() : Optional.of(persistentKeepalive); return this; |