2017-07-30 00:30:33 +02:00
|
|
|
package com.wireguard.config;
|
|
|
|
|
2018-04-17 05:20:17 +02:00
|
|
|
import android.text.TextUtils;
|
|
|
|
|
2018-04-27 18:29:14 +02:00
|
|
|
import java.lang.reflect.InvocationTargetException;
|
|
|
|
import java.lang.reflect.Method;
|
|
|
|
import java.net.InetAddress;
|
2017-07-30 00:30:33 +02:00
|
|
|
import java.util.HashMap;
|
2018-04-27 18:33:39 +02:00
|
|
|
import java.util.Locale;
|
2017-07-30 00:30:33 +02:00
|
|
|
import java.util.Map;
|
|
|
|
import java.util.regex.Matcher;
|
|
|
|
import java.util.regex.Pattern;
|
|
|
|
|
|
|
|
/**
|
|
|
|
* The set of valid attributes for an interface or peer in a WireGuard configuration file.
|
|
|
|
*/
|
|
|
|
|
|
|
|
enum Attribute {
|
|
|
|
ADDRESS("Address"),
|
|
|
|
ALLOWED_IPS("AllowedIPs"),
|
|
|
|
DNS("DNS"),
|
|
|
|
ENDPOINT("Endpoint"),
|
|
|
|
LISTEN_PORT("ListenPort"),
|
|
|
|
MTU("MTU"),
|
|
|
|
PERSISTENT_KEEPALIVE("PersistentKeepalive"),
|
2017-11-26 23:45:41 +01:00
|
|
|
PRESHARED_KEY("PresharedKey"),
|
2017-07-30 00:30:33 +02:00
|
|
|
PRIVATE_KEY("PrivateKey"),
|
|
|
|
PUBLIC_KEY("PublicKey");
|
|
|
|
|
2018-04-30 18:37:52 +02:00
|
|
|
private static final String[] EMPTY_LIST = new String[0];
|
2018-01-01 09:06:37 +01:00
|
|
|
private static final Map<String, Attribute> KEY_MAP;
|
2018-04-30 18:37:52 +02:00
|
|
|
private static final Pattern LIST_SEPARATOR_PATTERN = Pattern.compile("\\s*,\\s*");
|
|
|
|
private static final Method NUMERIC_ADDRESS_PARSER;
|
2018-01-01 09:06:37 +01:00
|
|
|
private static final Pattern SEPARATOR_PATTERN = Pattern.compile("\\s|=");
|
2017-07-30 00:30:33 +02:00
|
|
|
|
|
|
|
static {
|
2018-01-01 09:06:37 +01:00
|
|
|
KEY_MAP = new HashMap<>(Attribute.values().length);
|
|
|
|
for (final Attribute key : Attribute.values()) {
|
|
|
|
KEY_MAP.put(key.token, key);
|
|
|
|
}
|
2017-07-30 00:30:33 +02:00
|
|
|
}
|
|
|
|
|
2018-04-30 18:39:12 +02:00
|
|
|
static {
|
|
|
|
try {
|
2018-04-30 18:37:52 +02:00
|
|
|
NUMERIC_ADDRESS_PARSER = InetAddress.class.getMethod("parseNumericAddress", String.class);
|
|
|
|
} catch (final Exception e) {
|
2018-04-30 18:39:12 +02:00
|
|
|
throw new RuntimeException(e);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-07-30 00:30:33 +02:00
|
|
|
private final Pattern pattern;
|
2018-01-01 09:06:37 +01:00
|
|
|
private final String token;
|
2017-07-30 00:30:33 +02:00
|
|
|
|
2017-08-13 14:24:03 +02:00
|
|
|
Attribute(final String token) {
|
|
|
|
pattern = Pattern.compile(token + "\\s*=\\s*(\\S.*)");
|
2017-07-30 00:30:33 +02:00
|
|
|
this.token = token;
|
|
|
|
}
|
|
|
|
|
2018-04-30 18:37:52 +02:00
|
|
|
public static <T> String iterableToString(final Iterable<T> iterable) {
|
|
|
|
return TextUtils.join(", ", iterable);
|
2018-04-17 05:20:17 +02:00
|
|
|
}
|
|
|
|
|
2018-04-30 18:39:12 +02:00
|
|
|
public static Attribute match(final CharSequence line) {
|
|
|
|
return KEY_MAP.get(SEPARATOR_PATTERN.split(line)[0]);
|
2018-04-27 18:29:14 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
public static InetAddress parseIPString(final String address) {
|
|
|
|
if (address == null || address.isEmpty())
|
|
|
|
throw new IllegalArgumentException("Empty address");
|
|
|
|
try {
|
2018-04-30 18:37:52 +02:00
|
|
|
return (InetAddress) NUMERIC_ADDRESS_PARSER.invoke(null, address);
|
|
|
|
} catch (final IllegalAccessException e) {
|
2018-04-27 18:29:14 +02:00
|
|
|
throw new RuntimeException(e);
|
2018-04-30 18:37:52 +02:00
|
|
|
} catch (final InvocationTargetException e) {
|
2018-04-27 18:29:14 +02:00
|
|
|
if (e.getCause() instanceof IllegalArgumentException)
|
2018-04-30 18:39:12 +02:00
|
|
|
throw (IllegalArgumentException) e.getCause();
|
2018-04-27 18:29:14 +02:00
|
|
|
else
|
|
|
|
throw new IllegalArgumentException(e.getCause());
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-04-30 18:39:12 +02:00
|
|
|
public static String[] stringToList(final String string) {
|
|
|
|
if (string == null)
|
2018-04-30 18:37:52 +02:00
|
|
|
return EMPTY_LIST;
|
|
|
|
return LIST_SEPARATOR_PATTERN.split(string.trim());
|
2018-04-30 18:39:12 +02:00
|
|
|
}
|
|
|
|
|
2018-01-01 09:06:37 +01:00
|
|
|
public String composeWith(final Object value) {
|
|
|
|
return String.format("%s = %s%n", token, value);
|
2017-07-30 00:30:33 +02:00
|
|
|
}
|
|
|
|
|
2018-04-18 05:28:31 +02:00
|
|
|
public String composeWith(final int value) {
|
2018-04-27 18:33:39 +02:00
|
|
|
return String.format(Locale.getDefault(), "%s = %d%n", token, value);
|
2018-04-18 05:28:31 +02:00
|
|
|
}
|
|
|
|
|
2018-04-30 18:37:52 +02:00
|
|
|
public <T> String composeWith(final Iterable<T> value) {
|
|
|
|
return String.format("%s = %s%n", token, iterableToString(value));
|
2018-04-17 05:20:17 +02:00
|
|
|
}
|
|
|
|
|
2018-01-01 09:06:37 +01:00
|
|
|
public String parse(final CharSequence line) {
|
2017-07-30 00:30:33 +02:00
|
|
|
final Matcher matcher = pattern.matcher(line);
|
2018-01-01 09:06:37 +01:00
|
|
|
return matcher.matches() ? matcher.group(1) : null;
|
2017-07-30 00:30:33 +02:00
|
|
|
}
|
2018-04-17 05:20:17 +02:00
|
|
|
|
|
|
|
public String[] parseList(final CharSequence line) {
|
|
|
|
final Matcher matcher = pattern.matcher(line);
|
|
|
|
return matcher.matches() ? stringToList(matcher.group(1)) : null;
|
|
|
|
}
|
2017-07-30 00:30:33 +02:00
|
|
|
}
|