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 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 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()); + public Interface getInterface() { + return iface; } - @Bindable - public String getConfig() { - return config; - } - - @Bindable public String getName() { return name; } - public void setConfig(String config) { - this.config = config; - notifyPropertyChanged(BR.config); + public ObservableList 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(); } }