summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorJason A. Donenfeld <Jason@zx2c4.com>2020-03-20 23:36:00 -0600
committerJason A. Donenfeld <Jason@zx2c4.com>2020-03-21 03:06:56 -0600
commit902a1ce46e88ed9ae552e68961e19ce156b17ccf (patch)
tree504c434b758c5def5c3eb89ff94690fa5e3555dc
parent55849cad65b699ff16886085db996fc6ce3dec3e (diff)
viewmodel: port to kotlin
Signed-off-by: Jason A. Donenfeld <Jason@zx2c4.com>
-rw-r--r--ui/build.gradle1
-rw-r--r--ui/src/main/java/com/wireguard/android/fragment/TunnelEditorFragment.kt8
-rw-r--r--ui/src/main/java/com/wireguard/android/viewmodel/ConfigProxy.java96
-rw-r--r--ui/src/main/java/com/wireguard/android/viewmodel/ConfigProxy.kt77
-rw-r--r--ui/src/main/java/com/wireguard/android/viewmodel/InterfaceProxy.java192
-rw-r--r--ui/src/main/java/com/wireguard/android/viewmodel/InterfaceProxy.kt135
-rw-r--r--ui/src/main/java/com/wireguard/android/viewmodel/PeerProxy.java382
-rw-r--r--ui/src/main/java/com/wireguard/android/viewmodel/PeerProxy.kt288
8 files changed, 505 insertions, 674 deletions
diff --git a/ui/build.gradle b/ui/build.gradle
index d9f20d3d..bc4bd740 100644
--- a/ui/build.gradle
+++ b/ui/build.gradle
@@ -1,5 +1,6 @@
apply plugin: 'com.android.application'
apply plugin: 'kotlin-android'
+apply plugin: 'kotlin-kapt'
version wireguardVersionName
group groupName
diff --git a/ui/src/main/java/com/wireguard/android/fragment/TunnelEditorFragment.kt b/ui/src/main/java/com/wireguard/android/fragment/TunnelEditorFragment.kt
index 387d0962..b6f3043b 100644
--- a/ui/src/main/java/com/wireguard/android/fragment/TunnelEditorFragment.kt
+++ b/ui/src/main/java/com/wireguard/android/fragment/TunnelEditorFragment.kt
@@ -83,7 +83,7 @@ class TunnelEditorFragment : BaseFragment(), AppExclusionListener {
override fun onExcludedAppsSelected(excludedApps: List<String>) {
requireNotNull(binding) { "Tried to set excluded apps while no view was loaded" }
- binding!!.config!!.getInterface().excludedApplications.apply {
+ binding!!.config!!.`interface`.excludedApplications.apply {
clear()
addAll(excludedApps)
}
@@ -125,12 +125,12 @@ class TunnelEditorFragment : BaseFragment(), AppExclusionListener {
tunnel == null -> {
Log.d(TAG, "Attempting to create new tunnel " + binding!!.name)
val manager = Application.getTunnelManager()
- manager.create(binding!!.name, newConfig)
+ manager.create(binding!!.name!!, newConfig)
.whenComplete(this::onTunnelCreated)
}
tunnel!!.name != binding!!.name -> {
Log.d(TAG, "Attempting to rename tunnel to " + binding!!.name)
- tunnel!!.setName(binding!!.name)
+ tunnel!!.setName(binding!!.name!!)
.whenComplete { _, t -> onTunnelRenamed(tunnel!!, newConfig, t) }
}
else -> {
@@ -147,7 +147,7 @@ class TunnelEditorFragment : BaseFragment(), AppExclusionListener {
@Suppress("UNUSED_PARAMETER")
fun onRequestSetExcludedApplications(view: View?) {
if (binding != null) {
- val excludedApps = ArrayList(binding!!.config!!.getInterface().excludedApplications)
+ val excludedApps = ArrayList(binding!!.config!!.`interface`.excludedApplications)
val fragment = AppListDialogFragment.newInstance(excludedApps, this)
fragment.show(parentFragmentManager, null)
}
diff --git a/ui/src/main/java/com/wireguard/android/viewmodel/ConfigProxy.java b/ui/src/main/java/com/wireguard/android/viewmodel/ConfigProxy.java
deleted file mode 100644
index d44a5976..00000000
--- a/ui/src/main/java/com/wireguard/android/viewmodel/ConfigProxy.java
+++ /dev/null
@@ -1,96 +0,0 @@
-/*
- * Copyright © 2017-2019 WireGuard LLC. All Rights Reserved.
- * SPDX-License-Identifier: Apache-2.0
- */
-
-package com.wireguard.android.viewmodel;
-
-import android.os.Parcel;
-import android.os.Parcelable;
-
-import com.wireguard.config.BadConfigException;
-import com.wireguard.config.Config;
-import com.wireguard.config.Peer;
-import com.wireguard.util.NonNullForAll;
-
-import java.util.ArrayList;
-import java.util.Collection;
-
-import androidx.databinding.ObservableArrayList;
-import androidx.databinding.ObservableList;
-
-@NonNullForAll
-public class ConfigProxy implements Parcelable {
- public static final Parcelable.Creator<ConfigProxy> CREATOR = new ConfigProxyCreator();
-
- private final InterfaceProxy interfaze;
- private final ObservableList<PeerProxy> peers = new ObservableArrayList<>();
-
- private ConfigProxy(final Parcel in) {
- interfaze = in.readParcelable(InterfaceProxy.class.getClassLoader());
- in.readTypedList(peers, PeerProxy.CREATOR);
- for (final PeerProxy proxy : peers)
- proxy.bind(this);
- }
-
- public ConfigProxy(final Config other) {
- interfaze = new InterfaceProxy(other.getInterface());
- for (final Peer peer : other.getPeers()) {
- final PeerProxy proxy = new PeerProxy(peer);
- peers.add(proxy);
- proxy.bind(this);
- }
- }
-
- public ConfigProxy() {
- interfaze = new InterfaceProxy();
- }
-
- public PeerProxy addPeer() {
- final PeerProxy proxy = new PeerProxy();
- peers.add(proxy);
- proxy.bind(this);
- return proxy;
- }
-
- @Override
- public int describeContents() {
- return 0;
- }
-
- public InterfaceProxy getInterface() {
- return interfaze;
- }
-
- public ObservableList<PeerProxy> getPeers() {
- return peers;
- }
-
- public Config resolve() throws BadConfigException {
- final Collection<Peer> resolvedPeers = new ArrayList<>();
- for (final PeerProxy proxy : peers)
- resolvedPeers.add(proxy.resolve());
- return new Config.Builder()
- .setInterface(interfaze.resolve())
- .addPeers(resolvedPeers)
- .build();
- }
-
- @Override
- public void writeToParcel(final Parcel dest, final int flags) {
- dest.writeParcelable(interfaze, flags);
- dest.writeTypedList(peers);
- }
-
- private static class ConfigProxyCreator implements Parcelable.Creator<ConfigProxy> {
- @Override
- public ConfigProxy createFromParcel(final Parcel in) {
- return new ConfigProxy(in);
- }
-
- @Override
- public ConfigProxy[] newArray(final int size) {
- return new ConfigProxy[size];
- }
- }
-}
diff --git a/ui/src/main/java/com/wireguard/android/viewmodel/ConfigProxy.kt b/ui/src/main/java/com/wireguard/android/viewmodel/ConfigProxy.kt
new file mode 100644
index 00000000..36774c3f
--- /dev/null
+++ b/ui/src/main/java/com/wireguard/android/viewmodel/ConfigProxy.kt
@@ -0,0 +1,77 @@
+/*
+ * Copyright © 2017-2019 WireGuard LLC. All Rights Reserved.
+ * SPDX-License-Identifier: Apache-2.0
+ */
+package com.wireguard.android.viewmodel
+
+import android.os.Parcel
+import android.os.Parcelable
+import androidx.databinding.ObservableArrayList
+import androidx.databinding.ObservableList
+import com.wireguard.config.BadConfigException
+import com.wireguard.config.Config
+import com.wireguard.config.Peer
+import java.util.ArrayList
+
+class ConfigProxy : Parcelable {
+ val `interface`: InterfaceProxy
+ val peers: ObservableList<PeerProxy> = ObservableArrayList()
+
+ private constructor(parcel: Parcel) {
+ `interface` = parcel.readParcelable(InterfaceProxy::class.java.classLoader)!!
+ parcel.readTypedList(peers, PeerProxy.CREATOR)
+ peers.forEach { it.bind(this) }
+ }
+
+ constructor(other: Config) {
+ `interface` = InterfaceProxy(other.getInterface())
+ other.peers.forEach {
+ val proxy = PeerProxy(it)
+ peers.add(proxy)
+ proxy.bind(this)
+ }
+ }
+
+ constructor() {
+ `interface` = InterfaceProxy()
+ }
+
+ fun addPeer(): PeerProxy {
+ val proxy = PeerProxy()
+ peers.add(proxy)
+ proxy.bind(this)
+ return proxy
+ }
+
+ override fun describeContents() = 0
+
+ @Throws(BadConfigException::class)
+ fun resolve(): Config {
+ val resolvedPeers: MutableCollection<Peer> = ArrayList()
+ peers.forEach { resolvedPeers.add(it.resolve()) }
+ return Config.Builder()
+ .setInterface(`interface`.resolve())
+ .addPeers(resolvedPeers)
+ .build()
+ }
+
+ override fun writeToParcel(dest: Parcel, flags: Int) {
+ dest.writeParcelable(`interface`, flags)
+ dest.writeTypedList(peers)
+ }
+
+ private class ConfigProxyCreator : Parcelable.Creator<ConfigProxy> {
+ override fun createFromParcel(parcel: Parcel): ConfigProxy {
+ return ConfigProxy(parcel)
+ }
+
+ override fun newArray(size: Int): Array<ConfigProxy?> {
+ return arrayOfNulls(size)
+ }
+ }
+
+ companion object {
+ @JvmField
+ val CREATOR: Parcelable.Creator<ConfigProxy> = ConfigProxyCreator()
+ }
+}
diff --git a/ui/src/main/java/com/wireguard/android/viewmodel/InterfaceProxy.java b/ui/src/main/java/com/wireguard/android/viewmodel/InterfaceProxy.java
deleted file mode 100644
index 2bf87ea4..00000000
--- a/ui/src/main/java/com/wireguard/android/viewmodel/InterfaceProxy.java
+++ /dev/null
@@ -1,192 +0,0 @@
-/*
- * Copyright © 2017-2019 WireGuard LLC. All Rights Reserved.
- * SPDX-License-Identifier: Apache-2.0
- */
-
-package com.wireguard.android.viewmodel;
-
-import android.os.Parcel;
-import android.os.Parcelable;
-
-import com.wireguard.android.BR;
-import com.wireguard.config.Attribute;
-import com.wireguard.config.BadConfigException;
-import com.wireguard.config.Interface;
-import com.wireguard.crypto.Key;
-import com.wireguard.crypto.KeyFormatException;
-import com.wireguard.crypto.KeyPair;
-import com.wireguard.util.NonNullForAll;
-
-import java.net.InetAddress;
-import java.util.List;
-
-import androidx.databinding.BaseObservable;
-import androidx.databinding.Bindable;
-import androidx.databinding.ObservableArrayList;
-import androidx.databinding.ObservableList;
-import java9.util.stream.Collectors;
-import java9.util.stream.StreamSupport;
-
-@NonNullForAll
-public class InterfaceProxy extends BaseObservable implements Parcelable {
- public static final Parcelable.Creator<InterfaceProxy> CREATOR = new InterfaceProxyCreator();
-
- private final ObservableList<String> excludedApplications = new ObservableArrayList<>();
- private String addresses;
- private String dnsServers;
- private String listenPort;
- private String mtu;
- private String privateKey;
- private String publicKey;
-
- private InterfaceProxy(final Parcel in) {
- addresses = in.readString();
- dnsServers = in.readString();
- in.readStringList(excludedApplications);
- listenPort = in.readString();
- mtu = in.readString();
- privateKey = in.readString();
- publicKey = in.readString();
- }
-
- public InterfaceProxy(final Interface other) {
- addresses = Attribute.join(other.getAddresses());
- final List<String> dnsServerStrings = StreamSupport.stream(other.getDnsServers())
- .map(InetAddress::getHostAddress)
- .collect(Collectors.toUnmodifiableList());
- dnsServers = Attribute.join(dnsServerStrings);
- excludedApplications.addAll(other.getExcludedApplications());
- listenPort = other.getListenPort().map(String::valueOf).orElse("");
- mtu = other.getMtu().map(String::valueOf).orElse("");
- final KeyPair keyPair = other.getKeyPair();
- privateKey = keyPair.getPrivateKey().toBase64();
- publicKey = keyPair.getPublicKey().toBase64();
- }
-
- public InterfaceProxy() {
- addresses = "";
- dnsServers = "";
- listenPort = "";
- mtu = "";
- privateKey = "";
- publicKey = "";
- }
-
- @Override
- public int describeContents() {
- return 0;
- }
-
- public void generateKeyPair() {
- final KeyPair keyPair = new KeyPair();
- privateKey = keyPair.getPrivateKey().toBase64();
- publicKey = keyPair.getPublicKey().toBase64();
- notifyPropertyChanged(BR.privateKey);
- notifyPropertyChanged(BR.publicKey);
- }
-
- @Bindable
- public String getAddresses() {
- return addresses;
- }
-
- @Bindable
- public String getDnsServers() {
- return dnsServers;
- }
-
- public ObservableList<String> getExcludedApplications() {
- return excludedApplications;
- }
-
- @Bindable
- public String getListenPort() {
- return listenPort;
- }
-
- @Bindable
- public String getMtu() {
- return mtu;
- }
-
- @Bindable
- public String getPrivateKey() {
- return privateKey;
- }
-
- @Bindable
- public String getPublicKey() {
- return publicKey;
- }
-
- public Interface resolve() throws BadConfigException {
- final Interface.Builder builder = new Interface.Builder();
- if (!addresses.isEmpty())
- builder.parseAddresses(addresses);
- if (!dnsServers.isEmpty())
- builder.parseDnsServers(dnsServers);
- if (!excludedApplications.isEmpty())
- builder.excludeApplications(excludedApplications);
- if (!listenPort.isEmpty())
- builder.parseListenPort(listenPort);
- if (!mtu.isEmpty())
- builder.parseMtu(mtu);
- if (!privateKey.isEmpty())
- builder.parsePrivateKey(privateKey);
- return builder.build();
- }
-
- public void setAddresses(final String addresses) {
- this.addresses = addresses;
- notifyPropertyChanged(BR.addresses);
- }
-
- public void setDnsServers(final String dnsServers) {
- this.dnsServers = dnsServers;
- notifyPropertyChanged(BR.dnsServers);
- }
-
- public void setListenPort(final String listenPort) {
- this.listenPort = listenPort;
- notifyPropertyChanged(BR.listenPort);
- }
-
- public void setMtu(final String mtu) {
- this.mtu = mtu;
- notifyPropertyChanged(BR.mtu);
- }
-
- public void setPrivateKey(final String privateKey) {
- this.privateKey = privateKey;
- try {
- publicKey = new KeyPair(Key.fromBase64(privateKey)).getPublicKey().toBase64();
- } catch (final KeyFormatException ignored) {
- publicKey = "";
- }
- notifyPropertyChanged(BR.privateKey);
- notifyPropertyChanged(BR.publicKey);
- }
-
- @Override
- public void writeToParcel(final Parcel dest, final int flags) {
- dest.writeString(addresses);
- dest.writeString(dnsServers);
- dest.writeStringList(excludedApplications);
- dest.writeString(listenPort);
- dest.writeString(mtu);
- dest.writeString(privateKey);
- dest.writeString(publicKey);
- }
-
- private static class InterfaceProxyCreator implements Parcelable.Creator<InterfaceProxy> {
- @Override
- public InterfaceProxy createFromParcel(final Parcel in) {
- return new InterfaceProxy(in);
- }
-
- @Override
- public InterfaceProxy[] newArray(final int size) {
- return new InterfaceProxy[size];
- }
- }
-}
diff --git a/ui/src/main/java/com/wireguard/android/viewmodel/InterfaceProxy.kt b/ui/src/main/java/com/wireguard/android/viewmodel/InterfaceProxy.kt
new file mode 100644
index 00000000..53f2fa24
--- /dev/null
+++ b/ui/src/main/java/com/wireguard/android/viewmodel/InterfaceProxy.kt
@@ -0,0 +1,135 @@
+/*
+ * Copyright © 2017-2019 WireGuard LLC. All Rights Reserved.
+ * SPDX-License-Identifier: Apache-2.0
+ */
+package com.wireguard.android.viewmodel
+
+import android.os.Parcel
+import android.os.Parcelable
+import androidx.databinding.BaseObservable
+import androidx.databinding.Bindable
+import androidx.databinding.ObservableArrayList
+import androidx.databinding.ObservableList
+import com.wireguard.android.BR
+import com.wireguard.config.Attribute
+import com.wireguard.config.BadConfigException
+import com.wireguard.config.Interface
+import com.wireguard.crypto.Key
+import com.wireguard.crypto.KeyFormatException
+import com.wireguard.crypto.KeyPair
+
+class InterfaceProxy : BaseObservable, Parcelable {
+ @get:Bindable
+ val excludedApplications: ObservableList<String> = ObservableArrayList()
+
+ @get:Bindable
+ var addresses: String = ""
+ set(value) {
+ field = value
+ notifyPropertyChanged(BR.addresses)
+ }
+
+ @get:Bindable
+ var dnsServers: String = ""
+ set(value) {
+ field = value
+ notifyPropertyChanged(BR.dnsServers)
+ }
+
+ @get:Bindable
+ var listenPort: String = ""
+ set(value) {
+ field = value
+ notifyPropertyChanged(BR.listenPort)
+ }
+
+ @get:Bindable
+ var mtu: String = ""
+ set(value) {
+ field = value
+ notifyPropertyChanged(BR.mtu)
+ }
+
+ @get:Bindable
+ var privateKey: String = ""
+ set(value) {
+ field = value
+ notifyPropertyChanged(BR.privateKey)
+ notifyPropertyChanged(BR.publicKey)
+ }
+
+ @get:Bindable
+ val publicKey: String
+ get() = try {
+ KeyPair(Key.fromBase64(privateKey)).publicKey.toBase64()
+ } catch (ignored: KeyFormatException) {
+ ""
+ }
+
+ private constructor(parcel: Parcel) {
+ addresses = parcel.readString() ?: ""
+ dnsServers = parcel.readString() ?: ""
+ parcel.readStringList(excludedApplications)
+ listenPort = parcel.readString() ?: ""
+ mtu = parcel.readString() ?: ""
+ privateKey = parcel.readString() ?: ""
+ }
+
+ constructor(other: Interface) {
+ addresses = Attribute.join(other.addresses)
+ val dnsServerStrings = other.dnsServers.map { it.hostAddress }
+ dnsServers = Attribute.join(dnsServerStrings)
+ excludedApplications.addAll(other.excludedApplications)
+ listenPort = other.listenPort.map { it.toString() }.orElse("")
+ mtu = other.mtu.map { it.toString() }.orElse("")
+ val keyPair = other.keyPair
+ privateKey = keyPair.privateKey.toBase64()
+ }
+
+ constructor()
+
+ override fun describeContents() = 0
+
+ fun generateKeyPair() {
+ val keyPair = KeyPair()
+ privateKey = keyPair.privateKey.toBase64()
+ notifyPropertyChanged(BR.privateKey)
+ notifyPropertyChanged(BR.publicKey)
+ }
+
+ @Throws(BadConfigException::class)
+ fun resolve(): Interface {
+ val builder = Interface.Builder()
+ if (addresses.isNotEmpty()) builder.parseAddresses(addresses)
+ if (dnsServers.isNotEmpty()) builder.parseDnsServers(dnsServers)
+ if (excludedApplications.isNotEmpty()) builder.excludeApplications(excludedApplications)
+ if (listenPort.isNotEmpty()) builder.parseListenPort(listenPort)
+ if (mtu.isNotEmpty()) builder.parseMtu(mtu)
+ if (privateKey.isNotEmpty()) builder.parsePrivateKey(privateKey)
+ return builder.build()
+ }
+
+ override fun writeToParcel(dest: Parcel, flags: Int) {
+ dest.writeString(addresses)
+ dest.writeString(dnsServers)
+ dest.writeStringList(excludedApplications)
+ dest.writeString(listenPort)
+ dest.writeString(mtu)
+ dest.writeString(privateKey)
+ }
+
+ private class InterfaceProxyCreator : Parcelable.Creator<InterfaceProxy> {
+ override fun createFromParcel(parcel: Parcel): InterfaceProxy {
+ return InterfaceProxy(parcel)
+ }
+
+ override fun newArray(size: Int): Array<InterfaceProxy?> {
+ return arrayOfNulls(size)
+ }
+ }
+
+ companion object {
+ @JvmField
+ val CREATOR: Parcelable.Creator<InterfaceProxy> = InterfaceProxyCreator()
+ }
+}
diff --git a/ui/src/main/java/com/wireguard/android/viewmodel/PeerProxy.java b/ui/src/main/java/com/wireguard/android/viewmodel/PeerProxy.java
deleted file mode 100644
index 6e01d35c..00000000
--- a/ui/src/main/java/com/wireguard/android/viewmodel/PeerProxy.java
+++ /dev/null
@@ -1,382 +0,0 @@
-/*
- * Copyright © 2017-2019 WireGuard LLC. All Rights Reserved.
- * SPDX-License-Identifier: Apache-2.0
- */
-
-package com.wireguard.android.viewmodel;
-
-import android.os.Parcel;
-import android.os.Parcelable;
-
-import com.wireguard.android.BR;
-import com.wireguard.config.Attribute;
-import com.wireguard.config.BadConfigException;
-import com.wireguard.config.InetEndpoint;
-import com.wireguard.config.Peer;
-import com.wireguard.crypto.Key;
-import com.wireguard.util.NonNullForAll;
-
-import java.lang.ref.WeakReference;
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.LinkedHashSet;
-import java.util.List;
-import java.util.Set;
-
-import androidx.annotation.Nullable;
-import androidx.databinding.BaseObservable;
-import androidx.databinding.Bindable;
-import androidx.databinding.Observable;
-import androidx.databinding.ObservableList;
-import java9.util.Lists;
-import java9.util.Sets;
-import java9.util.stream.Collectors;
-import java9.util.stream.Stream;
-
-@NonNullForAll
-public class PeerProxy extends BaseObservable implements Parcelable {
- public static final Parcelable.Creator<PeerProxy> CREATOR = new PeerProxyCreator();
- private static final Set<String> IPV4_PUBLIC_NETWORKS = new LinkedHashSet<>(Lists.of(
- "0.0.0.0/5", "8.0.0.0/7", "11.0.0.0/8", "12.0.0.0/6", "16.0.0.0/4", "32.0.0.0/3",
- "64.0.0.0/2", "128.0.0.0/3", "160.0.0.0/5", "168.0.0.0/6", "172.0.0.0/12",
- "172.32.0.0/11", "172.64.0.0/10", "172.128.0.0/9", "173.0.0.0/8", "174.0.0.0/7",
- "176.0.0.0/4", "192.0.0.0/9", "192.128.0.0/11", "192.160.0.0/13", "192.169.0.0/16",
- "192.170.0.0/15", "192.172.0.0/14", "192.176.0.0/12", "192.192.0.0/10",
- "193.0.0.0/8", "194.0.0.0/7", "196.0.0.0/6", "200.0.0.0/5", "208.0.0.0/4"
- ));
- private static final Set<String> IPV4_WILDCARD = Sets.of("0.0.0.0/0");
-
- private final List<String> dnsRoutes = new ArrayList<>();
- private String allowedIps;
- private AllowedIpsState allowedIpsState = AllowedIpsState.INVALID;
- private String endpoint;
- @Nullable private InterfaceDnsListener interfaceDnsListener;
- @Nullable private ConfigProxy owner;
- @Nullable private PeerListListener peerListListener;
- private String persistentKeepalive;
- private String preSharedKey;
- private String publicKey;
- private int totalPeers;
-
- private PeerProxy(final Parcel in) {
- allowedIps = in.readString();
- endpoint = in.readString();
- persistentKeepalive = in.readString();
- preSharedKey = in.readString();
- publicKey = in.readString();
- }
-
- public PeerProxy(final Peer other) {
- allowedIps = Attribute.join(other.getAllowedIps());
- endpoint = other.getEndpoint().map(InetEndpoint::toString).orElse("");
- persistentKeepalive = other.getPersistentKeepalive().map(String::valueOf).orElse("");
- preSharedKey = other.getPreSharedKey().map(Key::toBase64).orElse("");
- publicKey = other.getPublicKey().toBase64();
- }
-
- public PeerProxy() {
- allowedIps = "";
- endpoint = "";
- persistentKeepalive = "";
- preSharedKey = "";
- publicKey = "";
- }
-
- public void bind(final ConfigProxy owner) {
- final InterfaceProxy interfaze = owner.getInterface();
- final ObservableList<PeerProxy> peers = owner.getPeers();
- if (interfaceDnsListener == null)
- interfaceDnsListener = new InterfaceDnsListener(this);
- interfaze.addOnPropertyChangedCallback(interfaceDnsListener);
- setInterfaceDns(interfaze.getDnsServers());
- if (peerListListener == null)
- peerListListener = new PeerListListener(this);
- peers.addOnListChangedCallback(peerListListener);
- setTotalPeers(peers.size());
- this.owner = owner;
- }
-
- private void calculateAllowedIpsState() {
- final AllowedIpsState newState;
- if (totalPeers == 1) {
- // String comparison works because we only care if allowedIps is a superset of one of
- // the above sets of (valid) *networks*. We are not checking for a superset based on
- // the individual addresses in each set.
- final Collection<String> networkStrings = getAllowedIpsSet();
- // If allowedIps contains both the wildcard and the public networks, then private
- // networks aren't excluded!
- if (networkStrings.containsAll(IPV4_WILDCARD))
- newState = AllowedIpsState.CONTAINS_IPV4_WILDCARD;
- else if (networkStrings.containsAll(IPV4_PUBLIC_NETWORKS))
- newState = AllowedIpsState.CONTAINS_IPV4_PUBLIC_NETWORKS;
- else
- newState = AllowedIpsState.OTHER;
- } else {
- newState = AllowedIpsState.INVALID;
- }
- if (newState != allowedIpsState) {
- allowedIpsState = newState;
- notifyPropertyChanged(BR.ableToExcludePrivateIps);
- notifyPropertyChanged(BR.excludingPrivateIps);
- }
- }
-
- @Override
- public int describeContents() {
- return 0;
- }
-
- @Bindable
- public String getAllowedIps() {
- return allowedIps;
- }
-
- private Set<String> getAllowedIpsSet() {
- return new LinkedHashSet<>(Lists.of(Attribute.split(allowedIps)));
- }
-
- @Bindable
- public String getEndpoint() {
- return endpoint;
- }
-
- @Bindable
- public String getPersistentKeepalive() {
- return persistentKeepalive;
- }
-
- @Bindable
- public String getPreSharedKey() {
- return preSharedKey;
- }
-
- @Bindable
- public String getPublicKey() {
- return publicKey;
- }
-
- @Bindable
- public boolean isAbleToExcludePrivateIps() {
- return allowedIpsState == AllowedIpsState.CONTAINS_IPV4_PUBLIC_NETWORKS
- || allowedIpsState == AllowedIpsState.CONTAINS_IPV4_WILDCARD;
- }
-
- @Bindable
- public boolean isExcludingPrivateIps() {
- return allowedIpsState == AllowedIpsState.CONTAINS_IPV4_PUBLIC_NETWORKS;
- }
-
- public Peer resolve() throws BadConfigException {
- final Peer.Builder builder = new Peer.Builder();
- if (!allowedIps.isEmpty())
- builder.parseAllowedIPs(allowedIps);
- if (!endpoint.isEmpty())
- builder.parseEndpoint(endpoint);
- if (!persistentKeepalive.isEmpty())
- builder.parsePersistentKeepalive(persistentKeepalive);
- if (!preSharedKey.isEmpty())
- builder.parsePreSharedKey(preSharedKey);
- if (!publicKey.isEmpty())
- builder.parsePublicKey(publicKey);
- return builder.build();
- }
-
- public void setAllowedIps(final String allowedIps) {
- this.allowedIps = allowedIps;
- notifyPropertyChanged(BR.allowedIps);
- calculateAllowedIpsState();
- }
-
- public void setEndpoint(final String endpoint) {
- this.endpoint = endpoint;
- notifyPropertyChanged(BR.endpoint);
- }
-
- public void setExcludingPrivateIps(final boolean excludingPrivateIps) {
- if (!isAbleToExcludePrivateIps() || isExcludingPrivateIps() == excludingPrivateIps)
- return;
- final Set<String> oldNetworks = excludingPrivateIps ? IPV4_WILDCARD : IPV4_PUBLIC_NETWORKS;
- final Set<String> newNetworks = excludingPrivateIps ? IPV4_PUBLIC_NETWORKS : IPV4_WILDCARD;
- final Collection<String> input = getAllowedIpsSet();
- final int outputSize = input.size() - oldNetworks.size() + newNetworks.size();
- final Collection<String> output = new LinkedHashSet<>(outputSize);
- boolean replaced = false;
- // Replace the first instance of the wildcard with the public network list, or vice versa.
- for (final String network : input) {
- if (oldNetworks.contains(network)) {
- if (!replaced) {
- for (final String replacement : newNetworks)
- if (!output.contains(replacement))
- output.add(replacement);
- replaced = true;
- }
- } else if (!output.contains(network)) {
- output.add(network);
- }
- }
- // DNS servers only need to handled specially when we're excluding private IPs.
- if (excludingPrivateIps)
- output.addAll(dnsRoutes);
- else
- output.removeAll(dnsRoutes);
- allowedIps = Attribute.join(output);
- allowedIpsState = excludingPrivateIps ?
- AllowedIpsState.CONTAINS_IPV4_PUBLIC_NETWORKS : AllowedIpsState.CONTAINS_IPV4_WILDCARD;
- notifyPropertyChanged(BR.allowedIps);
- notifyPropertyChanged(BR.excludingPrivateIps);
- }
-
- private void setInterfaceDns(final CharSequence dnsServers) {
- final List<String> newDnsRoutes = Stream.of(Attribute.split(dnsServers))
- .filter(server -> !server.contains(":"))
- .map(server -> server + "/32")
- .collect(Collectors.toUnmodifiableList());
- if (allowedIpsState == AllowedIpsState.CONTAINS_IPV4_PUBLIC_NETWORKS) {
- final Collection<String> input = getAllowedIpsSet();
- final Collection<String> output = new LinkedHashSet<>(input.size() + 1);
- // Yes, this is quadratic in the number of DNS servers, but most users have 1 or 2.
- for (final String network : input)
- if (!dnsRoutes.contains(network) || newDnsRoutes.contains(network))
- output.add(network);
- // Since output is a Set, this does the Right Thing™ (it does not duplicate networks).
- output.addAll(newDnsRoutes);
- // None of the public networks are /32s, so this cannot change the AllowedIPs state.
- allowedIps = Attribute.join(output);
- notifyPropertyChanged(BR.allowedIps);
- }
- dnsRoutes.clear();
- dnsRoutes.addAll(newDnsRoutes);
- }
-
- public void setPersistentKeepalive(final String persistentKeepalive) {
- this.persistentKeepalive = persistentKeepalive;
- notifyPropertyChanged(BR.persistentKeepalive);
- }
-
- public void setPreSharedKey(final String preSharedKey) {
- this.preSharedKey = preSharedKey;
- notifyPropertyChanged(BR.preSharedKey);
- }
-
- public void setPublicKey(final String publicKey) {
- this.publicKey = publicKey;
- notifyPropertyChanged(BR.publicKey);
- }
-
- private void setTotalPeers(final int totalPeers) {
- if (this.totalPeers == totalPeers)
- return;
- this.totalPeers = totalPeers;
- calculateAllowedIpsState();
- }
-
- public void unbind() {
- if (owner == null)
- return;
- final InterfaceProxy interfaze = owner.getInterface();
- final ObservableList<PeerProxy> peers = owner.getPeers();
- if (interfaceDnsListener != null)
- interfaze.removeOnPropertyChangedCallback(interfaceDnsListener);
- if (peerListListener != null)
- peers.removeOnListChangedCallback(peerListListener);
- peers.remove(this);
- setInterfaceDns("");
- setTotalPeers(0);
- owner = null;
- }
-
- @Override
- public void writeToParcel(final Parcel dest, final int flags) {
- dest.writeString(allowedIps);
- dest.writeString(endpoint);
- dest.writeString(persistentKeepalive);
- dest.writeString(preSharedKey);
- dest.writeString(publicKey);
- }
-
- private enum AllowedIpsState {
- CONTAINS_IPV4_PUBLIC_NETWORKS,
- CONTAINS_IPV4_WILDCARD,
- INVALID,
- OTHER
- }
-
- private static final class InterfaceDnsListener extends Observable.OnPropertyChangedCallback {
- private final WeakReference<PeerProxy> weakPeerProxy;
-
- private InterfaceDnsListener(final PeerProxy peerProxy) {
- weakPeerProxy = new WeakReference<>(peerProxy);
- }
-
- @Override
- public void onPropertyChanged(final Observable sender, final int propertyId) {
- @Nullable final PeerProxy peerProxy = weakPeerProxy.get();
- if (peerProxy == null) {
- sender.removeOnPropertyChangedCallback(this);
- return;
- }
- // This shouldn't be possible, but try to avoid a ClassCastException anyway.
- if (!(sender instanceof InterfaceProxy))
- return;
- if (!(propertyId == BR._all || propertyId == BR.dnsServers))
- return;
- peerProxy.setInterfaceDns(((InterfaceProxy) sender).getDnsServers());
- }
- }
-
- private static final class PeerListListener
- extends ObservableList.OnListChangedCallback<ObservableList<PeerProxy>> {
- private final WeakReference<PeerProxy> weakPeerProxy;
-
- private PeerListListener(final PeerProxy peerProxy) {
- weakPeerProxy = new WeakReference<>(peerProxy);
- }
-
- @Override
- public void onChanged(final ObservableList<PeerProxy> sender) {
- @Nullable final PeerProxy peerProxy = weakPeerProxy.get();
- if (peerProxy == null) {
- sender.removeOnListChangedCallback(this);
- return;
- }
- peerProxy.setTotalPeers(sender.size());
- }
-
- @Override
- public void onItemRangeChanged(final ObservableList<PeerProxy> sender,
- final int positionStart, final int itemCount) {
- // Do nothing.
- }
-
- @Override
- public void onItemRangeInserted(final ObservableList<PeerProxy> sender,
- final int positionStart, final int itemCount) {
- onChanged(sender);
- }
-
- @Override
- public void onItemRangeMoved(final ObservableList<PeerProxy> sender,
- final int fromPosition, final int toPosition,
- final int itemCount) {
- // Do nothing.
- }
-
- @Override
- public void onItemRangeRemoved(final ObservableList<PeerProxy> sender,
- final int positionStart, final int itemCount) {
- onChanged(sender);
- }
- }
-
- private static class PeerProxyCreator implements Parcelable.Creator<PeerProxy> {
- @Override
- public PeerProxy createFromParcel(final Parcel in) {
- return new PeerProxy(in);
- }
-
- @Override
- public PeerProxy[] newArray(final int size) {
- return new PeerProxy[size];
- }
- }
-}
diff --git a/ui/src/main/java/com/wireguard/android/viewmodel/PeerProxy.kt b/ui/src/main/java/com/wireguard/android/viewmodel/PeerProxy.kt
new file mode 100644
index 00000000..6ac04f72
--- /dev/null
+++ b/ui/src/main/java/com/wireguard/android/viewmodel/PeerProxy.kt
@@ -0,0 +1,288 @@
+/*
+ * Copyright © 2017-2019 WireGuard LLC. All Rights Reserved.
+ * SPDX-License-Identifier: Apache-2.0
+ */
+package com.wireguard.android.viewmodel
+
+import android.os.Parcel
+import android.os.Parcelable
+import androidx.databinding.BaseObservable
+import androidx.databinding.Bindable
+import androidx.databinding.Observable
+import androidx.databinding.Observable.OnPropertyChangedCallback
+import androidx.databinding.ObservableList
+import com.wireguard.android.BR
+import com.wireguard.config.Attribute
+import com.wireguard.config.BadConfigException
+import com.wireguard.config.Peer
+import java.lang.ref.WeakReference
+import java.util.ArrayList
+import java.util.LinkedHashSet
+
+class PeerProxy : BaseObservable, Parcelable {
+ private val dnsRoutes: MutableList<String?> = ArrayList()
+ private var allowedIpsState = AllowedIpsState.INVALID
+ private var interfaceDnsListener: InterfaceDnsListener? = null
+ private var peerListListener: PeerListListener? = null
+ private var owner: ConfigProxy? = null
+ private var totalPeers = 0
+
+ @get:Bindable
+ var allowedIps: String = ""
+ set(value) {
+ field = value
+ notifyPropertyChanged(BR.allowedIps)
+ calculateAllowedIpsState()
+ }
+
+ @get:Bindable
+ var endpoint: String = ""
+ set(value) {
+ field = value
+ notifyPropertyChanged(BR.endpoint)
+ }
+
+ @get:Bindable
+ var persistentKeepalive: String = ""
+ set(value) {
+ field = value
+ notifyPropertyChanged(BR.persistentKeepalive)
+ }
+
+ @get:Bindable
+ var preSharedKey: String = ""
+ set(value) {
+ field = value
+ notifyPropertyChanged(BR.preSharedKey)
+ }
+
+ @get:Bindable
+ var publicKey: String = ""
+ set(value) {
+ field = value
+ notifyPropertyChanged(BR.publicKey)
+ }
+
+ @get:Bindable
+ val isAbleToExcludePrivateIps: Boolean
+ get() = allowedIpsState == AllowedIpsState.CONTAINS_IPV4_PUBLIC_NETWORKS || allowedIpsState == AllowedIpsState.CONTAINS_IPV4_WILDCARD
+
+ @get:Bindable
+ val isExcludingPrivateIps: Boolean
+ get() = allowedIpsState == AllowedIpsState.CONTAINS_IPV4_PUBLIC_NETWORKS
+
+ private constructor(parcel: Parcel) {
+ allowedIps = parcel.readString() ?: ""
+ endpoint = parcel.readString() ?: ""
+ persistentKeepalive = parcel.readString() ?: ""
+ preSharedKey = parcel.readString() ?: ""
+ publicKey = parcel.readString() ?: ""
+ }
+
+ constructor(other: Peer) {
+ allowedIps = Attribute.join(other.allowedIps)
+ endpoint = other.endpoint.map { it.toString() }.orElse("")
+ persistentKeepalive = other.persistentKeepalive.map { it.toString() }.orElse("")
+ preSharedKey = other.preSharedKey.map { it.toBase64() }.orElse("")
+ publicKey = other.publicKey.toBase64()
+ }
+
+ constructor()
+
+ fun bind(owner: ConfigProxy) {
+ val interfaze: InterfaceProxy = owner.`interface`
+ val peers = owner.peers
+ if (interfaceDnsListener == null) interfaceDnsListener = InterfaceDnsListener(this)
+ interfaze.addOnPropertyChangedCallback(interfaceDnsListener!!)
+ setInterfaceDns(interfaze.dnsServers)
+ if (peerListListener == null) peerListListener = PeerListListener(this)
+ peers.addOnListChangedCallback(peerListListener)
+ setTotalPeers(peers.size)
+ this.owner = owner
+ }
+
+ private fun calculateAllowedIpsState() {
+ val newState: AllowedIpsState
+ newState = if (totalPeers == 1) {
+ // String comparison works because we only care if allowedIps is a superset of one of
+ // the above sets of (valid) *networks*. We are not checking for a superset based on
+ // the individual addresses in each set.
+ val networkStrings: Collection<String> = getAllowedIpsSet()
+ // If allowedIps contains both the wildcard and the public networks, then private
+ // networks aren't excluded!
+ if (networkStrings.containsAll(IPV4_WILDCARD))
+ AllowedIpsState.CONTAINS_IPV4_WILDCARD
+ else if (networkStrings.containsAll(IPV4_PUBLIC_NETWORKS))
+ AllowedIpsState.CONTAINS_IPV4_PUBLIC_NETWORKS
+ else
+ AllowedIpsState.OTHER
+ } else {
+ AllowedIpsState.INVALID
+ }
+ if (newState != allowedIpsState) {
+ allowedIpsState = newState
+ notifyPropertyChanged(BR.ableToExcludePrivateIps)
+ notifyPropertyChanged(BR.excludingPrivateIps)
+ }
+ }
+
+ override fun describeContents() = 0
+
+ private fun getAllowedIpsSet() = setOf(*Attribute.split(allowedIps))
+
+ // Replace the first instance of the wildcard with the public network list, or vice versa.
+ // DNS servers only need to handled specially when we're excluding private IPs.
+ fun setExcludingPrivateIps(excludingPrivateIps: Boolean) {
+ if (!isAbleToExcludePrivateIps || isExcludingPrivateIps == excludingPrivateIps) return
+ val oldNetworks = if (excludingPrivateIps) IPV4_WILDCARD else IPV4_PUBLIC_NETWORKS
+ val newNetworks = if (excludingPrivateIps) IPV4_PUBLIC_NETWORKS else IPV4_WILDCARD
+ val input: Collection<String> = getAllowedIpsSet()
+ val outputSize = input.size - oldNetworks.size + newNetworks.size
+ val output: MutableCollection<String?> = LinkedHashSet(outputSize)
+ var replaced = false
+ // Replace the first instance of the wildcard with the public network list, or vice versa.
+ for (network in input) {
+ if (oldNetworks.contains(network)) {
+ if (!replaced) {
+ for (replacement in newNetworks) if (!output.contains(replacement)) output.add(replacement)
+ replaced = true
+ }
+ } else if (!output.contains(network)) {
+ output.add(network)
+ }
+ }
+ // DNS servers only need to handled specially when we're excluding private IPs.
+ if (excludingPrivateIps) output.addAll(dnsRoutes) else output.removeAll(dnsRoutes)
+ allowedIps = Attribute.join(output)
+ allowedIpsState = if (excludingPrivateIps) AllowedIpsState.CONTAINS_IPV4_PUBLIC_NETWORKS else AllowedIpsState.CONTAINS_IPV4_WILDCARD
+ notifyPropertyChanged(BR.allowedIps)
+ notifyPropertyChanged(BR.excludingPrivateIps)
+ }
+
+ @Throws(BadConfigException::class)
+ fun resolve(): Peer {
+ val builder = Peer.Builder()
+ if (allowedIps.isNotEmpty()) builder.parseAllowedIPs(allowedIps)
+ if (endpoint.isNotEmpty()) builder.parseEndpoint(endpoint)
+ if (persistentKeepalive.isNotEmpty()) builder.parsePersistentKeepalive(persistentKeepalive)
+ if (preSharedKey.isNotEmpty()) builder.parsePreSharedKey(preSharedKey)
+ if (publicKey.isNotEmpty()) builder.parsePublicKey(publicKey)
+ return builder.build()
+ }
+
+ private fun setInterfaceDns(dnsServers: CharSequence) {
+ val newDnsRoutes = Attribute.split(dnsServers).filter { !it.contains(":") }.map { "$it/32" }
+ if (allowedIpsState == AllowedIpsState.CONTAINS_IPV4_PUBLIC_NETWORKS) {
+ val input = getAllowedIpsSet()
+ // Yes, this is quadratic in the number of DNS servers, but most users have 1 or 2.
+ val output = input.filter { !dnsRoutes.contains(it) || newDnsRoutes.contains(it) }.plus(newDnsRoutes).distinct()
+ // None of the public networks are /32s, so this cannot change the AllowedIPs state.
+ allowedIps = Attribute.join(output)
+ notifyPropertyChanged(BR.allowedIps)
+ }
+ dnsRoutes.clear()
+ dnsRoutes.addAll(newDnsRoutes)
+ }
+
+ private fun setTotalPeers(totalPeers: Int) {
+ if (this.totalPeers == totalPeers) return
+ this.totalPeers = totalPeers
+ calculateAllowedIpsState()
+ }
+
+ fun unbind() {
+ if (owner == null) return
+ val interfaze: InterfaceProxy = owner!!.`interface`
+ val peers = owner!!.peers
+ if (interfaceDnsListener != null) interfaze.removeOnPropertyChangedCallback(interfaceDnsListener!!)
+ if (peerListListener != null) peers.removeOnListChangedCallback(peerListListener)
+ peers.remove(this)
+ setInterfaceDns("")
+ setTotalPeers(0)
+ owner = null
+ }
+
+ override fun writeToParcel(dest: Parcel, flags: Int) {
+ dest.writeString(allowedIps)
+ dest.writeString(endpoint)
+ dest.writeString(persistentKeepalive)
+ dest.writeString(preSharedKey)
+ dest.writeString(publicKey)
+ }
+
+ private enum class AllowedIpsState {
+ CONTAINS_IPV4_PUBLIC_NETWORKS, CONTAINS_IPV4_WILDCARD, INVALID, OTHER
+ }
+
+ private class InterfaceDnsListener constructor(peerProxy: PeerProxy) : OnPropertyChangedCallback() {
+ private val weakPeerProxy: WeakReference<PeerProxy> = WeakReference(peerProxy)
+ override fun onPropertyChanged(sender: Observable, propertyId: Int) {
+ val peerProxy = weakPeerProxy.get()
+ if (peerProxy == null) {
+ sender.removeOnPropertyChangedCallback(this)
+ return
+ }
+ // This shouldn't be possible, but try to avoid a ClassCastException anyway.
+ if (sender !is InterfaceProxy) return
+ if (!(propertyId == BR._all || propertyId == BR.dnsServers)) return
+ peerProxy.setInterfaceDns(sender.dnsServers)
+ }
+ }
+
+ private class PeerListListener(peerProxy: PeerProxy) : ObservableList.OnListChangedCallback<ObservableList<PeerProxy?>>() {
+ private val weakPeerProxy: WeakReference<PeerProxy> = WeakReference(peerProxy)
+ override fun onChanged(sender: ObservableList<PeerProxy?>) {
+ val peerProxy = weakPeerProxy.get()
+ if (peerProxy == null) {
+ sender.removeOnListChangedCallback(this)
+ return
+ }
+ peerProxy.setTotalPeers(sender.size)
+ }
+
+ override fun onItemRangeChanged(sender: ObservableList<PeerProxy?>,
+ positionStart: Int, itemCount: Int) {
+ // Do nothing.
+ }
+
+ override fun onItemRangeInserted(sender: ObservableList<PeerProxy?>,
+ positionStart: Int, itemCount: Int) {
+ onChanged(sender)
+ }
+
+ override fun onItemRangeMoved(sender: ObservableList<PeerProxy?>,
+ fromPosition: Int, toPosition: Int,
+ itemCount: Int) {
+ // Do nothing.
+ }
+
+ override fun onItemRangeRemoved(sender: ObservableList<PeerProxy?>,
+ positionStart: Int, itemCount: Int) {
+ onChanged(sender)
+ }
+ }
+
+ private class PeerProxyCreator : Parcelable.Creator<PeerProxy> {
+ override fun createFromParcel(parcel: Parcel): PeerProxy {
+ return PeerProxy(parcel)
+ }
+
+ override fun newArray(size: Int): Array<PeerProxy?> {
+ return arrayOfNulls(size)
+ }
+ }
+
+ companion object {
+ @JvmField
+ val CREATOR: Parcelable.Creator<PeerProxy> = PeerProxyCreator()
+ private val IPV4_PUBLIC_NETWORKS = setOf(
+ "0.0.0.0/5", "8.0.0.0/7", "11.0.0.0/8", "12.0.0.0/6", "16.0.0.0/4", "32.0.0.0/3",
+ "64.0.0.0/2", "128.0.0.0/3", "160.0.0.0/5", "168.0.0.0/6", "172.0.0.0/12",
+ "172.32.0.0/11", "172.64.0.0/10", "172.128.0.0/9", "173.0.0.0/8", "174.0.0.0/7",
+ "176.0.0.0/4", "192.0.0.0/9", "192.128.0.0/11", "192.160.0.0/13", "192.169.0.0/16",
+ "192.170.0.0/15", "192.172.0.0/14", "192.176.0.0/12", "192.192.0.0/10",
+ "193.0.0.0/8", "194.0.0.0/7", "196.0.0.0/6", "200.0.0.0/5", "208.0.0.0/4"
+ )
+ private val IPV4_WILDCARD = setOf("0.0.0.0/0")
+ }
+}