summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorJason A. Donenfeld <Jason@zx2c4.com>2018-04-28 04:45:17 +0200
committerJason A. Donenfeld <Jason@zx2c4.com>2018-04-28 04:51:43 +0200
commit63071f57b7b501c23843f502a5d2a1ac83338bc7 (patch)
tree21a9a0f4de77b67669949534c27e033d1ee896c3
parent693228985df3aab03a53d9ae68aed7d309c4f6bd (diff)
Use validation instead of two-way binding
This is insane, but it appears to be working. We essentially store things in a separate class for editing, and then commit it back at a given time. This business with onViewStateRestored in both TunnelEditorFragment and in TunnelDetailFragment is buggy and likely wrong. In general TunnelEditorFragment should probably be rewritten. The relationship with the changed name is not clear. Signed-off-by: Jason A. Donenfeld <Jason@zx2c4.com>
-rw-r--r--app/src/main/java/com/wireguard/android/fragment/TunnelDetailFragment.java24
-rw-r--r--app/src/main/java/com/wireguard/android/fragment/TunnelEditorFragment.java44
-rw-r--r--app/src/main/java/com/wireguard/config/Attribute.java2
-rw-r--r--app/src/main/java/com/wireguard/config/Config.java62
-rw-r--r--app/src/main/java/com/wireguard/config/IPCidr.java1
-rw-r--r--app/src/main/java/com/wireguard/config/Interface.java191
-rw-r--r--app/src/main/java/com/wireguard/config/Peer.java135
-rw-r--r--app/src/main/res/layout/tunnel_detail_fragment.xml26
-rw-r--r--app/src/main/res/layout/tunnel_detail_peer.xml10
-rw-r--r--app/src/main/res/layout/tunnel_editor_fragment.xml24
-rw-r--r--app/src/main/res/layout/tunnel_editor_peer.xml10
11 files changed, 382 insertions, 147 deletions
diff --git a/app/src/main/java/com/wireguard/android/fragment/TunnelDetailFragment.java b/app/src/main/java/com/wireguard/android/fragment/TunnelDetailFragment.java
index e236da71..5592c28a 100644
--- a/app/src/main/java/com/wireguard/android/fragment/TunnelDetailFragment.java
+++ b/app/src/main/java/com/wireguard/android/fragment/TunnelDetailFragment.java
@@ -10,6 +10,7 @@ import android.view.ViewGroup;
import com.wireguard.android.R;
import com.wireguard.android.databinding.TunnelDetailFragmentBinding;
import com.wireguard.android.model.Tunnel;
+import com.wireguard.config.Config;
/**
* Fragment that shows details about a specific tunnel.
@@ -18,6 +19,7 @@ import com.wireguard.android.model.Tunnel;
public class TunnelDetailFragment extends BaseFragment {
private TunnelDetailFragmentBinding binding;
private boolean isViewStateRestored;
+ private String originalName;
@Override
public void onCreate(final Bundle savedInstanceState) {
@@ -45,16 +47,34 @@ public class TunnelDetailFragment extends BaseFragment {
super.onDestroyView();
}
+ private void onConfigLoaded(Config config) {
+ binding.setConfig(new Config.Observable(config, originalName));
+ }
+
@Override
public void onSelectedTunnelChanged(final Tunnel oldTunnel, final Tunnel newTunnel) {
- if (binding != null && isViewStateRestored)
+ if (binding != null && isViewStateRestored) {
binding.setTunnel(newTunnel);
+ if (newTunnel == null)
+ binding.setConfig(null);
+ else {
+ originalName = newTunnel.getName();
+ newTunnel.getConfigAsync().thenAccept(this::onConfigLoaded);
+ }
+ }
}
@Override
public void onViewStateRestored(final Bundle savedInstanceState) {
super.onViewStateRestored(savedInstanceState);
- binding.setTunnel(getSelectedTunnel());
+ Tunnel tunnel = getSelectedTunnel();
+ binding.setTunnel(tunnel);
+ if (tunnel == null)
+ binding.setConfig(null);
+ else {
+ originalName = tunnel.getName();
+ tunnel.getConfigAsync().thenAccept(this::onConfigLoaded);
+ }
isViewStateRestored = true;
}
}
diff --git a/app/src/main/java/com/wireguard/android/fragment/TunnelEditorFragment.java b/app/src/main/java/com/wireguard/android/fragment/TunnelEditorFragment.java
index fdb5fc20..f3316490 100644
--- a/app/src/main/java/com/wireguard/android/fragment/TunnelEditorFragment.java
+++ b/app/src/main/java/com/wireguard/android/fragment/TunnelEditorFragment.java
@@ -2,7 +2,6 @@ package com.wireguard.android.fragment;
import android.app.Activity;
import android.content.Context;
-import android.databinding.ObservableField;
import android.os.Bundle;
import android.os.Parcel;
import android.os.Parcelable;
@@ -31,11 +30,9 @@ import com.wireguard.config.Config;
public class TunnelEditorFragment extends BaseFragment {
private static final String KEY_LOCAL_CONFIG = "local_config";
- private static final String KEY_LOCAL_NAME = "local_name";
private static final String KEY_ORIGINAL_NAME = "original_name";
private static final String TAG = "WireGuard/" + TunnelEditorFragment.class.getSimpleName();
- private final ObservableField<String> localName = new ObservableField<>("");
private TunnelEditorFragmentBinding binding;
private boolean isViewStateRestored;
private Config localConfig = new Config();
@@ -56,7 +53,7 @@ public class TunnelEditorFragment extends BaseFragment {
private void onConfigLoaded(final Config config) {
localConfig = copyParcelable(config);
if (binding != null && isViewStateRestored)
- binding.setConfig(localConfig);
+ binding.setConfig(new Config.Observable(localConfig, originalName));
}
private void onConfigSaved(@SuppressWarnings("unused") final Config config,
@@ -82,20 +79,17 @@ public class TunnelEditorFragment extends BaseFragment {
super.onCreate(savedInstanceState);
if (savedInstanceState != null) {
localConfig = savedInstanceState.getParcelable(KEY_LOCAL_CONFIG);
- localName.set(savedInstanceState.getString(KEY_LOCAL_NAME));
originalName = savedInstanceState.getString(KEY_ORIGINAL_NAME);
}
// Erase the remains of creating or editing a different tunnel.
if (getSelectedTunnel() != null && !getSelectedTunnel().getName().equals(originalName)) {
// The config must be loaded asynchronously since it's not an observable property.
localConfig = null;
- getSelectedTunnel().getConfigAsync().thenAccept(this::onConfigLoaded);
originalName = getSelectedTunnel().getName();
- localName.set(originalName);
+ getSelectedTunnel().getConfigAsync().thenAccept(this::onConfigLoaded);
} else if (getSelectedTunnel() == null && originalName != null) {
localConfig = new Config();
originalName = null;
- localName.set("");
}
localTunnel = getSelectedTunnel();
setHasOptionsMenu(true);
@@ -147,14 +141,26 @@ public class TunnelEditorFragment extends BaseFragment {
switch (item.getItemId()) {
case R.id.menu_action_save:
final Tunnel selectedTunnel = getSelectedTunnel();
+ if (localConfig != null) {
+ try {
+ binding.getConfig().commitData(localConfig);
+ } catch (Exception e) {
+ final String error = ExceptionLoggers.unwrap(e).getMessage();
+ final String message = getString(R.string.config_save_error, localTunnel.getName(), error);
+ Log.e(TAG, message, e);
+ final CoordinatorLayout container = binding.mainContainer;
+ Snackbar.make(container, error, Snackbar.LENGTH_LONG).show();
+ return false;
+ }
+ }
if (selectedTunnel == null) {
- Log.d(TAG, "Attempting to create new tunnel " + localName.get());
+ Log.d(TAG, "Attempting to create new tunnel " + binding.getConfig().getName());
final TunnelManager manager = Application.getComponent().getTunnelManager();
- manager.create(localName.get(), localConfig)
+ manager.create(binding.getConfig().getName(), localConfig)
.whenComplete(this::onTunnelCreated);
- } else if (!selectedTunnel.getName().equals(localName.get())) {
- Log.d(TAG, "Attempting to rename tunnel to " + localName.get());
- selectedTunnel.setName(localName.get())
+ } else if (!selectedTunnel.getName().equals(binding.getConfig().getName())) {
+ Log.d(TAG, "Attempting to rename tunnel to " + binding.getConfig().getName());
+ selectedTunnel.setName(binding.getConfig().getName())
.whenComplete(this::onTunnelRenamed);
} else if (localConfig != null) {
Log.d(TAG, "Attempting to save config of " + selectedTunnel.getName());
@@ -170,7 +176,6 @@ public class TunnelEditorFragment extends BaseFragment {
@Override
public void onSaveInstanceState(final Bundle outState) {
outState.putParcelable(KEY_LOCAL_CONFIG, localConfig);
- outState.putString(KEY_LOCAL_NAME, localName.get());
outState.putString(KEY_ORIGINAL_NAME, originalName);
super.onSaveInstanceState(outState);
}
@@ -181,15 +186,13 @@ public class TunnelEditorFragment extends BaseFragment {
if (newTunnel != null) {
// The config must be loaded asynchronously since it's not an observable property.
localConfig = null;
- newTunnel.getConfigAsync().thenAccept(this::onConfigLoaded);
originalName = newTunnel.getName();
- localName.set(originalName);
+ newTunnel.getConfigAsync().thenAccept(this::onConfigLoaded);
} else {
localConfig = new Config();
if (binding != null && isViewStateRestored)
- binding.setConfig(localConfig);
+ binding.setConfig(new Config.Observable(localConfig, ""));
originalName = null;
- localName.set("");
}
localTunnel = newTunnel;
}
@@ -234,8 +237,9 @@ public class TunnelEditorFragment extends BaseFragment {
@Override
public void onViewStateRestored(final Bundle savedInstanceState) {
super.onViewStateRestored(savedInstanceState);
- binding.setConfig(localConfig);
- binding.setName(localName);
+ if (localConfig == null)
+ localConfig = new Config();
+ binding.setConfig(new Config.Observable(localConfig, originalName));
isViewStateRestored = true;
}
}
diff --git a/app/src/main/java/com/wireguard/config/Attribute.java b/app/src/main/java/com/wireguard/config/Attribute.java
index c98588b2..695caeda 100644
--- a/app/src/main/java/com/wireguard/config/Attribute.java
+++ b/app/src/main/java/com/wireguard/config/Attribute.java
@@ -54,6 +54,8 @@ enum Attribute {
}
public static String[] stringToList(final String string) {
+ if (string == null)
+ return new String[0];
return string.trim().split("\\s*,\\s*");
}
diff --git a/app/src/main/java/com/wireguard/config/Config.java b/app/src/main/java/com/wireguard/config/Config.java
index a3341d5f..e4731a0c 100644
--- a/app/src/main/java/com/wireguard/config/Config.java
+++ b/app/src/main/java/com/wireguard/config/Config.java
@@ -1,6 +1,9 @@
package com.wireguard.config;
+import com.android.databinding.library.baseAdapters.BR;
+
import android.databinding.BaseObservable;
+import android.databinding.Bindable;
import android.databinding.ObservableArrayList;
import android.databinding.ObservableList;
import android.os.Parcel;
@@ -11,12 +14,14 @@ import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.nio.charset.StandardCharsets;
+import java.util.ArrayList;
+import java.util.List;
/**
* Represents a wg-quick configuration file, its name, and its connection state.
*/
-public class Config extends BaseObservable implements Parcelable {
+public class Config implements Parcelable {
public static final Creator<Config> CREATOR = new Creator<Config>() {
@Override
public Config createFromParcel(final Parcel in) {
@@ -29,8 +34,59 @@ public class Config extends BaseObservable implements Parcelable {
}
};
+ public static class Observable extends BaseObservable {
+ private String name;
+ private Interface.Observable observableInterface;
+ private ObservableList<Peer.Observable> observablePeers;
+
+
+ public Observable(Config parent, String name) {
+ this.name = name;
+ loadData(parent);
+ }
+
+ public void loadData(Config parent) {
+ this.observableInterface = new Interface.Observable(parent.interfaceSection);
+ this.observablePeers = new ObservableArrayList<>();
+ for (Peer peer : parent.getPeers())
+ this.observablePeers.add(new Peer.Observable(peer));
+ }
+
+ public void commitData(Config parent) {
+ this.observableInterface.commitData(parent.interfaceSection);
+ List<Peer> newPeers = new ArrayList<>(this.observablePeers.size());
+ for (Peer.Observable observablePeer : this.observablePeers) {
+ Peer peer = new Peer();
+ observablePeer.commitData(peer);
+ newPeers.add(peer);
+ }
+ parent.peers = newPeers;
+ notifyChange();
+ }
+
+ @Bindable
+ public String getName() {
+ return name;
+ }
+
+ public void setName(String name) {
+ this.name = name;
+ notifyPropertyChanged(BR.name);
+ }
+
+ @Bindable
+ public Interface.Observable getInterfaceSection() {
+ return observableInterface;
+ }
+
+ @Bindable
+ public ObservableList<Peer.Observable> getPeers() {
+ return observablePeers;
+ }
+ }
+
private final Interface interfaceSection;
- private final ObservableList<Peer> peers = new ObservableArrayList<>();
+ private List<Peer> peers = new ArrayList<>();
public Config() {
interfaceSection = new Interface();
@@ -83,7 +139,7 @@ public class Config extends BaseObservable implements Parcelable {
return interfaceSection;
}
- public ObservableList<Peer> getPeers() {
+ public List<Peer> getPeers() {
return peers;
}
diff --git a/app/src/main/java/com/wireguard/config/IPCidr.java b/app/src/main/java/com/wireguard/config/IPCidr.java
index 07fccad4..aeb5fb36 100644
--- a/app/src/main/java/com/wireguard/config/IPCidr.java
+++ b/app/src/main/java/com/wireguard/config/IPCidr.java
@@ -6,7 +6,6 @@ import android.os.Parcelable;
import java.net.Inet4Address;
import java.net.Inet6Address;
import java.net.InetAddress;
-import java.net.UnknownHostException;
public class IPCidr implements Parcelable {
InetAddress address;
diff --git a/app/src/main/java/com/wireguard/config/Interface.java b/app/src/main/java/com/wireguard/config/Interface.java
index 03121072..2ed2b4e6 100644
--- a/app/src/main/java/com/wireguard/config/Interface.java
+++ b/app/src/main/java/com/wireguard/config/Interface.java
@@ -10,7 +10,6 @@ import com.wireguard.crypto.KeyEncoding;
import com.wireguard.crypto.Keypair;
import java.net.InetAddress;
-import java.net.UnknownHostException;
import java.util.LinkedList;
import java.util.List;
@@ -18,7 +17,7 @@ import java.util.List;
* Represents the configuration for a WireGuard interface (an [Interface] block).
*/
-public class Interface extends BaseObservable implements Parcelable {
+public class Interface implements Parcelable {
public static final Creator<Interface> CREATOR = new Creator<Interface>() {
@Override
public Interface createFromParcel(final Parcel in) {
@@ -31,12 +30,114 @@ public class Interface extends BaseObservable implements Parcelable {
}
};
+ public static class Observable extends BaseObservable {
+ private String addresses;
+ private String dnses;
+ private String publicKey;
+ private String privateKey;
+ private String listenPort;
+ private String mtu;
+
+ public Observable(Interface parent) {
+ loadData(parent);
+ }
+
+ public void loadData(Interface parent) {
+ this.addresses = parent.getAddressString();
+ this.dnses = parent.getDnsString();
+ this.publicKey = parent.getPublicKey();
+ this.privateKey = parent.getPrivateKey();
+ this.listenPort = parent.getListenPortString();
+ this.mtu = parent.getMtuString();
+ }
+
+ public void commitData(Interface parent) {
+ parent.setAddressString(this.addresses);
+ parent.setDnsString(this.dnses);
+ parent.setPrivateKey(this.privateKey);
+ parent.setListenPortString(this.listenPort);
+ parent.setMtuString(this.mtu);
+ loadData(parent);
+ notifyChange();
+ }
+
+ @Bindable
+ public String getAddresses() {
+ return addresses;
+ }
+
+ public void setAddresses(String addresses) {
+ this.addresses = addresses;
+ notifyPropertyChanged(BR.addresses);
+ }
+
+ @Bindable
+ public String getDnses() {
+ return dnses;
+ }
+
+ public void setDnses(String dnses) {
+ this.dnses = dnses;
+ notifyPropertyChanged(BR.dnses);
+ }
+
+ @Bindable
+ public String getPublicKey() {
+ return publicKey;
+ }
+
+ @Bindable
+ public String getPrivateKey() {
+ return privateKey;
+ }
+
+ public void setPrivateKey(String privateKey) {
+ this.privateKey = privateKey;
+
+ try {
+ this.publicKey = new Keypair(privateKey).getPublicKey();
+ } catch (IllegalArgumentException ignored) {
+ this.publicKey = "";
+ }
+
+ notifyPropertyChanged(BR.privateKey);
+ notifyPropertyChanged(BR.publicKey);
+ }
+
+ public void generateKeypair() {
+ Keypair keypair = new Keypair();
+ privateKey = keypair.getPrivateKey();
+ publicKey = keypair.getPublicKey();
+ notifyPropertyChanged(BR.privateKey);
+ notifyPropertyChanged(BR.publicKey);
+ }
+
+ @Bindable
+ public String getListenPort() {
+ return listenPort;
+ }
+
+ public void setListenPort(String listenPort) {
+ this.listenPort = listenPort;
+ notifyPropertyChanged(BR.listenPort);
+ }
+
+ @Bindable
+ public String getMtu() {
+ return mtu;
+ }
+
+ public void setMtu(String mtu) {
+ this.mtu = mtu;
+ notifyPropertyChanged(BR.mtu);
+ }
+ }
+
private List<IPCidr> addressList;
private List<InetAddress> dnsList;
private Keypair keypair;
private int listenPort;
private int mtu;
- private String privateKey;
public Interface() {
addressList = new LinkedList<>();
@@ -63,76 +164,63 @@ public class Interface extends BaseObservable implements Parcelable {
return 0;
}
- public void generateKeypair() {
- keypair = new Keypair();
- privateKey = keypair.getPrivateKey();
- notifyPropertyChanged(BR.privateKey);
- notifyPropertyChanged(BR.publicKey);
- }
-
- @Bindable
- public String getAddressString() {
+ private String getAddressString() {
if (addressList.isEmpty())
return null;
return Attribute.listToString(addressList);
}
- @Bindable
public IPCidr[] getAddresses() {
return addressList.toArray(new IPCidr[addressList.size()]);
}
- public List<String> getDnsStrings() {
+ private List<String> getDnsStrings() {
List<String> strings = new LinkedList<>();
for (final InetAddress addr : dnsList)
strings.add(addr.getHostAddress());
return strings;
}
- @Bindable
- public String getDnsString() {
+ private String getDnsString() {
if (dnsList.isEmpty())
return null;
return Attribute.listToString(getDnsStrings());
}
- @Bindable
public InetAddress[] getDnses() {
return dnsList.toArray(new InetAddress[dnsList.size()]);
}
- @Bindable
public int getListenPort() {
return listenPort;
}
- @Bindable
- public String getListenPortString() {
+ private String getListenPortString() {
if (listenPort == 0)
return null;
return new Integer(listenPort).toString();
}
- @Bindable
public int getMtu() {
return mtu;
}
- @Bindable
- public String getMtuString() {
+ private String getMtuString() {
if (mtu == 0)
return null;
return new Integer(mtu).toString();
}
- @Bindable
public String getPrivateKey() {
- return privateKey;
+ if (keypair == null)
+ return null;
+ return keypair.getPrivateKey();
}
- @Bindable
public String getPublicKey() {
- return keypair != null ? keypair.getPublicKey() : null;
+ if (keypair == null)
+ return null;
+ return keypair.getPublicKey();
}
public void parse(final String line) {
@@ -151,7 +239,7 @@ public class Interface extends BaseObservable implements Parcelable {
throw new IllegalArgumentException(line);
}
- public void addAddresses(String[] addresses) {
+ private void addAddresses(String[] addresses) {
if (addresses != null && addresses.length > 0) {
for (final String addr : addresses) {
if (addr.isEmpty())
@@ -159,74 +247,55 @@ public class Interface extends BaseObservable implements Parcelable {
this.addressList.add(new IPCidr(addr));
}
}
- notifyPropertyChanged(BR.addresses);
- notifyPropertyChanged(BR.addressString);
-
}
- public void setAddressString(final String addressString) {
+ private void setAddressString(final String addressString) {
this.addressList.clear();
addAddresses(Attribute.stringToList(addressString));
}
- public void addDnses(String[] dnses) {
+ private void addDnses(String[] dnses) {
if (dnses != null && dnses.length > 0) {
for (final String dns : dnses) {
this.dnsList.add(Attribute.parseIPString(dns));
}
}
- notifyPropertyChanged(BR.dnses);
- notifyPropertyChanged(BR.dnsString);
-
}
- public void setDnsString(final String dnsString) {
+ private void setDnsString(final String dnsString) {
this.dnsList.clear();
addDnses(Attribute.stringToList(dnsString));
}
- public void setListenPort(int listenPort) {
+ private void setListenPort(int listenPort) {
this.listenPort = listenPort;
- notifyPropertyChanged(BR.listenPort);
- notifyPropertyChanged(BR.listenPortString);
}
- public void setListenPortString(final String port) {
+ private void setListenPortString(final String port) {
if (port != null && !port.isEmpty())
setListenPort(Integer.parseInt(port, 10));
else
setListenPort(0);
}
- public void setMtu(int mtu) {
+ private void setMtu(int mtu) {
this.mtu = mtu;
- notifyPropertyChanged(BR.mtu);
- notifyPropertyChanged(BR.mtuString);
}
- public void setMtuString(final String mtu) {
+ private void setMtuString(final String mtu) {
if (mtu != null && !mtu.isEmpty())
setMtu(Integer.parseInt(mtu, 10));
else
setMtu(0);
}
- public void setPrivateKey(String privateKey) {
+ private void setPrivateKey(String privateKey) {
if (privateKey != null && privateKey.isEmpty())
privateKey = null;
- this.privateKey = privateKey;
- if (privateKey != null && privateKey.length() == KeyEncoding.KEY_LENGTH_BASE64) {
- try {
- keypair = new Keypair(privateKey);
- } catch (final IllegalArgumentException e) {
- keypair = null;
- throw e;
- }
- } else {
+ if (privateKey == null)
keypair = null;
- }
- notifyPropertyChanged(BR.privateKey);
- notifyPropertyChanged(BR.publicKey);
+ else
+ keypair = new Keypair(privateKey);
}
@Override
@@ -240,8 +309,8 @@ public class Interface extends BaseObservable implements Parcelable {
sb.append(Attribute.LISTEN_PORT.composeWith(listenPort));
if (mtu != 0)
sb.append(Attribute.MTU.composeWith(mtu));
- if (privateKey != null)
- sb.append(Attribute.PRIVATE_KEY.composeWith(privateKey));
+ if (keypair != null)
+ sb.append(Attribute.PRIVATE_KEY.composeWith(keypair.getPrivateKey()));
return sb.toString();
}
@@ -253,6 +322,6 @@ public class Interface extends BaseObservable implements Parcelable {
dest.writeByteArray(addr.getAddress());
dest.writeInt(listenPort);
dest.writeInt(mtu);
- dest.writeString(privateKey);
+ dest.writeString(keypair == null ? "" : keypair.getPrivateKey());
}
}
diff --git a/app/src/main/java/com/wireguard/config/Peer.java b/app/src/main/java/com/wireguard/config/Peer.java
index 9895f447..5c506b36 100644
--- a/app/src/main/java/com/wireguard/config/Peer.java
+++ b/app/src/main/java/com/wireguard/config/Peer.java
@@ -6,6 +6,7 @@ import android.os.Parcel;
import android.os.Parcelable;
import com.android.databinding.library.baseAdapters.BR;
+import com.wireguard.crypto.KeyEncoding;
import java.net.Inet6Address;
import java.net.InetSocketAddress;
@@ -19,7 +20,7 @@ import java.util.List;
* Represents the configuration for a WireGuard peer (a [Peer] block).
*/
-public class Peer extends BaseObservable implements Parcelable {
+public class Peer implements Parcelable {
public static final Creator<Peer> CREATOR = new Creator<Peer>() {
@Override
public Peer createFromParcel(final Parcel in) {
@@ -32,6 +33,92 @@ public class Peer extends BaseObservable implements Parcelable {
}
};
+ public static class Observable extends BaseObservable {
+ private String allowedIPs;
+ private String endpoint;
+ private String persistentKeepalive;
+ private String preSharedKey;
+ private String publicKey;
+
+
+ public Observable(Peer parent) {
+ loadData(parent);
+ }
+ public static Observable newInstance() {
+ return new Observable(new Peer());
+ }
+
+ public void loadData(Peer parent) {
+ this.allowedIPs = parent.getAllowedIPsString();
+ this.endpoint = parent.getEndpointString();
+ this.persistentKeepalive = parent.getPersistentKeepaliveString();
+ this.preSharedKey = parent.getPreSharedKey();
+ this.publicKey = parent.getPublicKey();
+ }
+
+ public void commitData(Peer parent) {
+ parent.setAllowedIPsString(this.allowedIPs);
+ parent.setEndpointString(this.endpoint);
+ parent.setPersistentKeepaliveString(this.persistentKeepalive);
+ parent.setPreSharedKey(this.preSharedKey);
+ parent.setPublicKey(this.publicKey);
+ if (parent.getPublicKey() == null)
+ throw new IllegalArgumentException("Peer public key may not be empty");
+ loadData(parent);
+ notifyChange();
+ }
+
+ @Bindable
+ public String getAllowedIPs() {
+ return allowedIPs;
+ }
+
+ public void setAllowedIPs(String allowedIPs) {
+ this.allowedIPs = allowedIPs;
+ notifyPropertyChanged(BR.allowedIPs);
+ }
+
+ @Bindable
+ public String getEndpoint() {
+ return endpoint;
+ }
+
+ public void setEndpoint(String endpoint) {
+ this.endpoint = endpoint;
+ notifyPropertyChanged(BR.endpoint);
+ }
+
+ @Bindable
+ public String getPersistentKeepalive() {
+ return persistentKeepalive;
+ }
+
+ public void setPersistentKeepalive(String persistentKeepalive) {
+ this.persistentKeepalive = persistentKeepalive;
+ notifyPropertyChanged(BR.persistentKeepalive);
+ }
+
+ @Bindable
+ public String getPreSharedKey() {
+ return preSharedKey;
+ }
+
+ public void setPreSharedKey(String preSharedKey) {
+ this.preSharedKey = preSharedKey;
+ notifyPropertyChanged(BR.preSharedKey);
+ }
+
+ @Bindable
+ public String getPublicKey() {
+ return publicKey;
+ }
+
+ public void setPublicKey(String publicKey) {
+ this.publicKey = publicKey;
+ notifyPropertyChanged(BR.publicKey);
+ }
+ }
+
private List<IPCidr> allowedIPsList;
private InetSocketAddress endpoint;
private int persistentKeepalive;
@@ -57,35 +144,27 @@ public class Peer extends BaseObservable implements Parcelable {
publicKey = null;
}
- public static Peer newInstance() {
- return new Peer();
- }
-
@Override
public int describeContents() {
return 0;
}
- @Bindable
- public String getAllowedIPsString() {
+ private String getAllowedIPsString() {
if (allowedIPsList.isEmpty())
return null;
return Attribute.listToString(allowedIPsList);
}
- @Bindable
public IPCidr[] getAllowedIPs() {
return allowedIPsList.toArray(new IPCidr[allowedIPsList.size()]);
}
- @Bindable
public InetSocketAddress getEndpoint() {
return endpoint;
}
- @Bindable
- public String getEndpointString() {
+ private String getEndpointString() {
if (endpoint == null)
return null;
return String.format("%s:%d", endpoint.getHostString(), endpoint.getPort());
@@ -103,24 +182,20 @@ public class Peer extends BaseObservable implements Parcelable {
return String.format("%s:%d", endpoint.getAddress().getHostAddress(), endpoint.getPort());
}
- @Bindable
public int getPersistentKeepalive() {
return persistentKeepalive;
}
- @Bindable
- public String getPersistentKeepaliveString() {
+ private String getPersistentKeepaliveString() {
if (persistentKeepalive == 0)
return null;
return new Integer(persistentKeepalive).toString();
}
- @Bindable
public String getPreSharedKey() {
return preSharedKey;
}
- @Bindable
public String getPublicKey() {
return publicKey;
}
@@ -141,28 +216,24 @@ public class Peer extends BaseObservable implements Parcelable {
throw new IllegalArgumentException(line);
}
- public void addAllowedIPs(String[] allowedIPs) {
+ private void addAllowedIPs(String[] allowedIPs) {
if (allowedIPs != null && allowedIPs.length > 0) {
for (final String allowedIP : allowedIPs) {
this.allowedIPsList.add(new IPCidr(allowedIP));
}
}
- notifyPropertyChanged(BR.allowedIPs);
- notifyPropertyChanged(BR.allowedIPsString);
}
- public void setAllowedIPsString(final String allowedIPsString) {
+ private void setAllowedIPsString(final String allowedIPsString) {
this.allowedIPsList.clear();
addAllowedIPs(Attribute.stringToList(allowedIPsString));
}
- public void setEndpoint(InetSocketAddress endpoint) {
+ private void setEndpoint(InetSocketAddress endpoint) {
this.endpoint = endpoint;
- notifyPropertyChanged(BR.endpoint);
- notifyPropertyChanged(BR.endpointString);
}
- public void setEndpointString(final String endpoint) {
+ private void setEndpointString(final String endpoint) {
if (endpoint != null && !endpoint.isEmpty()) {
InetSocketAddress constructedEndpoint;
if (endpoint.indexOf('/') != -1 || endpoint.indexOf('?') != -1 || endpoint.indexOf('#') != -1)
@@ -179,31 +250,31 @@ public class Peer extends BaseObservable implements Parcelable {
setEndpoint(null);
}
- public void setPersistentKeepalive(int persistentKeepalive) {
+ private void setPersistentKeepalive(int persistentKeepalive) {
this.persistentKeepalive = persistentKeepalive;
- notifyPropertyChanged(BR.persistentKeepalive);
- notifyPropertyChanged(BR.persistentKeepaliveString);
}
- public void setPersistentKeepaliveString(String persistentKeepalive) {
+ private void setPersistentKeepaliveString(String persistentKeepalive) {
if (persistentKeepalive != null && !persistentKeepalive.isEmpty())
setPersistentKeepalive(Integer.parseInt(persistentKeepalive, 10));
else
setPersistentKeepalive(0);
}
- public void setPreSharedKey(String preSharedKey) {
+ private void setPreSharedKey(String preSharedKey) {
if (preSharedKey != null && preSharedKey.isEmpty())
preSharedKey = null;
+ if (preSharedKey != null)
+ KeyEncoding.keyFromBase64(preSharedKey);
this.preSharedKey = preSharedKey;
- notifyPropertyChanged(BR.preSharedKey);
}
- public void setPublicKey(String publicKey) {
+ private void setPublicKey(String publicKey) {
if (publicKey != null && publicKey.isEmpty())
publicKey = null;
+ if (publicKey != null)
+ KeyEncoding.keyFromBase64(publicKey);
this.publicKey = publicKey;
- notifyPropertyChanged(BR.publicKey);
}
@Override
diff --git a/app/src/main/res/layout/tunnel_detail_fragment.xml b/app/src/main/res/layout/tunnel_detail_fragment.xml
index 900d08ed..971d8784 100644
--- a/app/src/main/res/layout/tunnel_detail_fragment.xml
+++ b/app/src/main/res/layout/tunnel_detail_fragment.xml
@@ -14,6 +14,10 @@
<variable
name="tunnel"
type="com.wireguard.android.model.Tunnel" />
+
+ <variable
+ name="config"
+ type="com.wireguard.config.Config.Observable" />
</data>
<ScrollView
@@ -92,7 +96,25 @@
android:ellipsize="end"
android:maxLines="1"
android:onClick="@{ClipboardUtils::copyTextView}"
- android:text="@{tunnel.config.interface.publicKey}" />
+ android:text="@{config.interfaceSection.publicKey}" />
+
+ <TextView
+ android:id="@+id/addresses_label"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:layout_below="@id/public_key_text"
+ android:layout_marginTop="8dp"
+ android:labelFor="@+id/addresses_text"
+ android:text="@string/addresses" />
+
+ <TextView
+ android:id="@+id/addresses_text"
+ style="?android:attr/textAppearanceMedium"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:layout_below="@+id/addresses_label"
+ android:contentDescription="@string/addresses"
+ android:text="@{config.interfaceSection.addresses}" />
</RelativeLayout>
<LinearLayout
@@ -101,7 +123,7 @@
android:layout_marginBottom="4dp"
android:divider="@null"
android:orientation="vertical"
- app:items="@{tunnel.config.peers}"
+ app:items="@{config.peers}"
app:layout="@{@layout/tunnel_detail_peer}"
tools:ignore="UselessLeaf" />
</LinearLayout>
diff --git a/app/src/main/res/layout/tunnel_detail_peer.xml b/app/src/main/res/layout/tunnel_detail_peer.xml
index bde89390..d2240e31 100644
--- a/app/src/main/res/layout/tunnel_detail_peer.xml
+++ b/app/src/main/res/layout/tunnel_detail_peer.xml
@@ -6,12 +6,8 @@
<import type="com.wireguard.android.util.ClipboardUtils" />
<variable
- name="collection"
- type="android.databinding.ObservableList&lt;com.wireguard.config.Peer&gt;" />
-
- <variable
name="item"
- type="com.wireguard.config.Peer" />
+ type="com.wireguard.config.Peer.Observable" />
</data>
<RelativeLayout
@@ -69,7 +65,7 @@
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_below="@+id/allowed_ips_label"
- android:text="@{item.allowedIPsString}" />
+ android:text="@{item.allowedIPs}" />
<TextView
android:id="@+id/endpoint_label"
@@ -86,6 +82,6 @@
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_below="@+id/endpoint_label"
- android:text="@{item.endpointString}" />
+ android:text="@{item.endpoint}" />
</RelativeLayout>
</layout>
diff --git a/app/src/main/res/layout/tunnel_editor_fragment.xml b/app/src/main/res/layout/tunnel_editor_fragment.xml
index 0d278bcb..4d56ee3e 100644
--- a/app/src/main/res/layout/tunnel_editor_fragment.xml
+++ b/app/src/main/res/layout/tunnel_editor_fragment.xml
@@ -15,11 +15,7 @@
<variable
name="config"
- type="com.wireguard.config.Config" />
-
- <variable
- name="name"
- type="android.databinding.ObservableField&lt;String&gt;" />
+ type="com.wireguard.config.Config.Observable" />
</data>
<com.commonsware.cwac.crossport.design.widget.CoordinatorLayout
@@ -71,7 +67,7 @@
android:layout_height="wrap_content"
android:layout_below="@+id/interface_name_label"
android:inputType="textNoSuggestions|textVisiblePassword"
- android:text="@={name}"
+ android:text="@={config.name}"
app:filter="@{NameInputFilter.newInstance()}" />
<TextView
@@ -91,7 +87,7 @@
android:layout_toStartOf="@+id/generate_private_key_button"
android:contentDescription="@string/public_key_description"
android:inputType="textNoSuggestions|textVisiblePassword"
- android:text="@={config.interface.privateKey}"
+ android:text="@={config.interfaceSection.privateKey}"
app:filter="@{KeyInputFilter.newInstance()}" />
<Button
@@ -101,7 +97,7 @@
android:layout_alignBottom="@id/private_key_text"
android:layout_alignParentEnd="true"
android:layout_below="@+id/private_key_label"
- android:onClick="@{() -> config.interface.generateKeypair()}"
+ android:onClick="@{() -> config.interfaceSection.generateKeypair()}"
android:text="@string/generate" />
<TextView
@@ -124,7 +120,7 @@
android:maxLines="1"
android:contentDescription="@string/public_key_description"
android:onClick="@{ClipboardUtils::copyTextView}"
- android:text="@{config.interface.publicKey}" />
+ android:text="@{config.interfaceSection.publicKey}" />
<TextView
android:id="@+id/addresses_label"
@@ -144,7 +140,7 @@
android:layout_below="@+id/addresses_label"
android:layout_toStartOf="@+id/listen_port_text"
android:inputType="textNoSuggestions|textVisiblePassword"
- android:text="@={config.interface.addressString}" />
+ android:text="@={config.interfaceSection.addresses}" />
<TextView
android:id="@+id/listen_port_label"
@@ -165,7 +161,7 @@
android:layout_alignStart="@+id/generate_private_key_button"
android:hint="@string/hint_random"
android:inputType="number"
- android:text="@={config.interface.listenPortString}"
+ android:text="@={config.interfaceSection.listenPort}"
android:textAlignment="center" />
<TextView
@@ -186,7 +182,7 @@
android:layout_below="@+id/dns_servers_label"
android:layout_toStartOf="@+id/mtu_text"
android:inputType="textNoSuggestions|textVisiblePassword"
- android:text="@={config.interface.dnsString}" />
+ android:text="@={config.interfaceSection.dnses}" />
<TextView
android:id="@+id/mtu_label"
@@ -207,7 +203,7 @@
android:layout_alignStart="@+id/generate_private_key_button"
android:hint="@string/hint_automatic"
android:inputType="number"
- android:text="@={config.interface.mtuString}"
+ android:text="@={config.interfaceSection.mtu}"
android:textAlignment="center" />
</RelativeLayout>
@@ -226,7 +222,7 @@
android:layout_marginBottom="4dp"
android:layout_marginEnd="4dp"
android:layout_marginStart="4dp"
- android:onClick="@{() -> config.peers.add(Peer.newInstance())}"
+ android:onClick="@{() -> config.peers.add(Peer.Observable.newInstance())}"
android:text="@string/add_peer" />
</LinearLayout>
</ScrollView>
diff --git a/app/src/main/res/layout/tunnel_editor_peer.xml b/app/src/main/res/layout/tunnel_editor_peer.xml
index cc5fe933..b6caab8a 100644
--- a/app/src/main/res/layout/tunnel_editor_peer.xml
+++ b/app/src/main/res/layout/tunnel_editor_peer.xml
@@ -8,11 +8,11 @@
<variable
name="collection"
- type="android.databinding.ObservableList&lt;com.wireguard.config.Peer&gt;" />
+ type="android.databinding.ObservableList&lt;com.wireguard.config.Peer.Observable&gt;" />
<variable
name="item"
- type="com.wireguard.config.Peer" />
+ type="com.wireguard.config.Peer.Observable" />
</data>
<RelativeLayout
@@ -96,7 +96,7 @@
android:layout_height="wrap_content"
android:layout_below="@+id/allowed_ips_label"
android:inputType="textNoSuggestions|textVisiblePassword"
- android:text="@={item.allowedIPsString}" />
+ android:text="@={item.allowedIPs}" />
<TextView
android:id="@+id/endpoint_label"
@@ -116,7 +116,7 @@
android:layout_below="@+id/endpoint_label"
android:layout_toStartOf="@+id/persistent_keepalive_text"
android:inputType="textNoSuggestions|textVisiblePassword"
- android:text="@={item.endpointString}" />
+ android:text="@={item.endpoint}" />
<TextView
android:id="@+id/persistent_keepalive_label"
@@ -136,7 +136,7 @@
android:layout_alignStart="@+id/persistent_keepalive_label"
android:hint="@string/hint_optional"
android:inputType="number"
- android:text="@={item.persistentKeepaliveString}"
+ android:text="@={item.persistentKeepalive}"
android:textAlignment="center" />
</RelativeLayout>
</layout>