summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorSamuel Holland <samuel@sholland.org>2017-07-29 17:30:33 -0500
committerSamuel Holland <samuel@sholland.org>2017-07-29 17:30:33 -0500
commit748d780a47ecf3fb11c048939eb1bdc20654b37a (patch)
tree028cf53f279c354db64ec1c7f32bc17ae1c9bc09
parent0494dd1404baec0d93944ceba888852a88b2acdb (diff)
Profile: Parse config file to a string per attribute
This parser should be able to handle any valid WireGuard or wg-quick configuration file. It separates the file into a single interface object and a peer object for each peer. All "[Interface]" sections in the file are combined into the one object. For now, later lines in a block with the same key overwrite earlier lines. This is only relevant for attributes that are lists, such as Address and AllowedIPs, where additional lines may be expected to append to the list. Signed-off-by: Jason A. Donenfeld <Jason@zx2c4.com>
-rw-r--r--app/src/main/java/com/wireguard/config/Attribute.java57
-rw-r--r--app/src/main/java/com/wireguard/config/Interface.java99
-rw-r--r--app/src/main/java/com/wireguard/config/Peer.java83
-rw-r--r--app/src/main/java/com/wireguard/config/Profile.java61
4 files changed, 274 insertions, 26 deletions
diff --git a/app/src/main/java/com/wireguard/config/Attribute.java b/app/src/main/java/com/wireguard/config/Attribute.java
new file mode 100644
index 00000000..7629456a
--- /dev/null
+++ b/app/src/main/java/com/wireguard/config/Attribute.java
@@ -0,0 +1,57 @@
+package com.wireguard.config;
+
+import java.util.HashMap;
+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"),
+ PRIVATE_KEY("PrivateKey"),
+ PUBLIC_KEY("PublicKey");
+
+ private static final Map<String, Attribute> map;
+
+ static {
+ map = new HashMap<>(Attribute.values().length);
+ for (Attribute key : Attribute.values())
+ map.put(key.getToken(), key);
+ }
+
+ public static Attribute match(String line) {
+ return map.get(line.split("\\s|=")[0]);
+ }
+
+ private final String token;
+ private final Pattern pattern;
+
+ Attribute(String token) {
+ this.pattern = Pattern.compile(token + "\\s*=\\s*(\\S.*)");
+ this.token = token;
+ }
+
+ public String composeWith(String value) {
+ return token + " = " + value + "\n";
+ }
+
+ public String getToken() {
+ return token;
+ }
+
+ public String parseFrom(String line) {
+ final Matcher matcher = pattern.matcher(line);
+ if (matcher.matches())
+ return matcher.group(1);
+ return null;
+ }
+}
diff --git a/app/src/main/java/com/wireguard/config/Interface.java b/app/src/main/java/com/wireguard/config/Interface.java
new file mode 100644
index 00000000..828f2c47
--- /dev/null
+++ b/app/src/main/java/com/wireguard/config/Interface.java
@@ -0,0 +1,99 @@
+package com.wireguard.config;
+
+import android.databinding.BaseObservable;
+import android.databinding.Bindable;
+import android.databinding.Observable;
+
+import com.wireguard.android.BR;
+
+/**
+ * Represents the configuration for a WireGuard interface (an [Interface] block).
+ */
+
+public class Interface extends BaseObservable implements Observable {
+ private String address;
+ private String dns;
+ private String listenPort;
+ private String mtu;
+ private String privateKey;
+
+ @Bindable
+ public String getAddress() {
+ return address;
+ }
+
+ @Bindable
+ public String getDns() {
+ return dns;
+ }
+
+ @Bindable
+ public String getListenPort() {
+ return listenPort;
+ }
+
+ @Bindable
+ public String getMtu() {
+ return mtu;
+ }
+
+ @Bindable
+ public String getPrivateKey() {
+ return privateKey;
+ }
+
+ public void parseFrom(String line) {
+ final Attribute key = Attribute.match(line);
+ if (key == Attribute.ADDRESS)
+ address = key.parseFrom(line);
+ else if (key == Attribute.DNS)
+ dns = key.parseFrom(line);
+ else if (key == Attribute.LISTEN_PORT)
+ listenPort = key.parseFrom(line);
+ else if (key == Attribute.MTU)
+ mtu = key.parseFrom(line);
+ else if (key == Attribute.PRIVATE_KEY)
+ privateKey = key.parseFrom(line);
+ }
+
+ public void setAddress(String address) {
+ this.address = address;
+ notifyPropertyChanged(BR.address);
+ }
+
+ public void setDns(String dns) {
+ this.dns = dns;
+ notifyPropertyChanged(BR.dns);
+ }
+
+ public void setListenPort(String listenPort) {
+ this.listenPort = listenPort;
+ notifyPropertyChanged(BR.listenPort);
+ }
+
+ public void setMtu(String mtu) {
+ this.mtu = mtu;
+ notifyPropertyChanged(BR.mtu);
+ }
+
+ public void setPrivateKey(String privateKey) {
+ this.privateKey = privateKey;
+ notifyPropertyChanged(BR.privateKey);
+ }
+
+ @Override
+ public String toString() {
+ final StringBuilder sb = new StringBuilder().append("[Interface]\n");
+ if (address != null)
+ sb.append(Attribute.ADDRESS.composeWith(address));
+ if (dns != null)
+ sb.append(Attribute.DNS.composeWith(dns));
+ if (listenPort != null)
+ sb.append(Attribute.LISTEN_PORT.composeWith(listenPort));
+ if (mtu != null)
+ sb.append(Attribute.MTU.composeWith(mtu));
+ if (privateKey != null)
+ sb.append(Attribute.PRIVATE_KEY.composeWith(privateKey));
+ return sb.toString();
+ }
+}
diff --git a/app/src/main/java/com/wireguard/config/Peer.java b/app/src/main/java/com/wireguard/config/Peer.java
new file mode 100644
index 00000000..64977a16
--- /dev/null
+++ b/app/src/main/java/com/wireguard/config/Peer.java
@@ -0,0 +1,83 @@
+package com.wireguard.config;
+
+import android.databinding.BaseObservable;
+import android.databinding.Bindable;
+import android.databinding.Observable;
+
+import com.android.databinding.library.baseAdapters.BR;
+
+/**
+ * Represents the configuration for a WireGuard peer (a [Peer] block).
+ */
+
+public class Peer extends BaseObservable implements Observable {
+ private String allowedIPs;
+ private String endpoint;
+ private String persistentKeepalive;
+ private String publicKey;
+
+ @Bindable
+ public String getAllowedIPs() {
+ return allowedIPs;
+ }
+
+ @Bindable
+ public String getEndpoint() {
+ return endpoint;
+ }
+
+ @Bindable
+ public String getPersistentKeepalive() {
+ return persistentKeepalive;
+ }
+
+ @Bindable
+ public String getPublicKey() {
+ return publicKey;
+ }
+
+ public void parseFrom(String line) {
+ final Attribute key = Attribute.match(line);
+ if (key == Attribute.ALLOWED_IPS)
+ allowedIPs = key.parseFrom(line);
+ else if (key == Attribute.ENDPOINT)
+ endpoint = key.parseFrom(line);
+ else if (key == Attribute.PERSISTENT_KEEPALIVE)
+ persistentKeepalive = key.parseFrom(line);
+ else if (key == Attribute.PUBLIC_KEY)
+ publicKey = key.parseFrom(line);
+ }
+
+ public void setAllowedIPs(String allowedIPs) {
+ this.allowedIPs = allowedIPs;
+ notifyPropertyChanged(BR.allowedIPs);
+ }
+
+ public void setEndpoint(String endpoint) {
+ this.endpoint = endpoint;
+ notifyPropertyChanged(BR.endpoint);
+ }
+
+ public void setPersistentKeepalive(String persistentKeepalive) {
+ this.persistentKeepalive = persistentKeepalive;
+ notifyPropertyChanged(BR.persistentKeepalive);
+ }
+
+ public void setPublicKey(String publicKey) {
+ this.publicKey = publicKey;
+ notifyPropertyChanged(BR.publicKey);
+ }
+
+ public String toString() {
+ final StringBuilder sb = new StringBuilder().append("[Peer]\n");
+ if (allowedIPs != null)
+ sb.append(Attribute.ALLOWED_IPS.composeWith(allowedIPs));
+ if (endpoint != null)
+ sb.append(Attribute.ENDPOINT.composeWith(endpoint));
+ if (persistentKeepalive != null)
+ sb.append(Attribute.PERSISTENT_KEEPALIVE.composeWith(persistentKeepalive));
+ if (publicKey != null)
+ sb.append(Attribute.PUBLIC_KEY.composeWith(publicKey));
+ return sb.toString();
+ }
+}
diff --git a/app/src/main/java/com/wireguard/config/Profile.java b/app/src/main/java/com/wireguard/config/Profile.java
index b8fd55a4..d929131c 100644
--- a/app/src/main/java/com/wireguard/config/Profile.java
+++ b/app/src/main/java/com/wireguard/config/Profile.java
@@ -1,56 +1,65 @@
package com.wireguard.config;
-import android.databinding.BaseObservable;
-import android.databinding.Bindable;
-import android.databinding.Observable;
-
-import com.wireguard.android.BR;
+import android.databinding.ObservableArrayList;
+import android.databinding.ObservableList;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
+import java.nio.charset.StandardCharsets;
/**
* Represents a wg-quick profile.
*/
-public class Profile extends BaseObservable implements Observable {
- private String config;
+public class Profile {
+ private final Interface iface = new Interface();
private final String name;
+ private final ObservableList<Peer> peers = new ObservableArrayList<>();
public Profile(String name) {
this.name = name;
}
- public void fromStream(InputStream stream)
- throws IOException {
- final StringBuilder sb = new StringBuilder(stream.available());
- String line;
- try (BufferedReader reader = new BufferedReader(new InputStreamReader(stream))) {
- while ((line = reader.readLine()) != null)
- sb.append(line).append('\n');
- }
- setConfig(sb.toString());
- }
-
- @Bindable
- public String getConfig() {
- return config;
+ public Interface getInterface() {
+ return iface;
}
- @Bindable
public String getName() {
return name;
}
- public void setConfig(String config) {
- this.config = config;
- notifyPropertyChanged(BR.config);
+ public ObservableList<Peer> getPeers() {
+ return peers;
+ }
+
+ public void parseFrom(InputStream stream)
+ throws IOException {
+ try (BufferedReader reader = new BufferedReader(
+ new InputStreamReader(stream, StandardCharsets.UTF_8))) {
+ Peer currentPeer = null;
+ String line;
+ while ((line = reader.readLine()) != null) {
+ if (line.equals("[Interface]")) {
+ currentPeer = null;
+ } else if (line.equals("[Peer]")) {
+ currentPeer = new Peer();
+ peers.add(currentPeer);
+ } else if (currentPeer == null) {
+ iface.parseFrom(line);
+ } else {
+ currentPeer.parseFrom(line);
+ }
+ }
+ }
}
@Override
public String toString() {
- return getConfig();
+ StringBuilder sb = new StringBuilder().append(iface.toString());
+ for (Peer peer : peers)
+ sb.append(peer.toString());
+ return sb.toString();
}
}