summaryrefslogtreecommitdiffhomepage
path: root/ui
diff options
context:
space:
mode:
Diffstat (limited to 'ui')
-rw-r--r--ui/src/main/java/com/wireguard/android/fragment/TunnelDetailFragment.kt2
-rw-r--r--ui/src/main/java/com/wireguard/android/model/ObservableTunnel.kt102
-rw-r--r--ui/src/main/java/com/wireguard/android/viewmodel/PeerDetail.kt38
-rw-r--r--ui/src/main/res/layout/tunnel_detail_fragment.xml1
-rw-r--r--ui/src/main/res/layout/tunnel_detail_peer.xml14
5 files changed, 134 insertions, 23 deletions
diff --git a/ui/src/main/java/com/wireguard/android/fragment/TunnelDetailFragment.kt b/ui/src/main/java/com/wireguard/android/fragment/TunnelDetailFragment.kt
index ed49d56d..50d43690 100644
--- a/ui/src/main/java/com/wireguard/android/fragment/TunnelDetailFragment.kt
+++ b/ui/src/main/java/com/wireguard/android/fragment/TunnelDetailFragment.kt
@@ -112,7 +112,7 @@ class TunnelDetailFragment : BaseFragment() {
for (i in 0 until binding.peersLayout.childCount) {
val peer: TunnelDetailPeerBinding = DataBindingUtil.getBinding(binding.peersLayout.getChildAt(i))
?: continue
- val publicKey = peer.item!!.peer.publicKey
+ val publicKey = peer.item!!.publicKey
val rx = statistics.peerRx(publicKey)
val tx = statistics.peerTx(publicKey)
if (rx == 0L && tx == 0L) {
diff --git a/ui/src/main/java/com/wireguard/android/model/ObservableTunnel.kt b/ui/src/main/java/com/wireguard/android/model/ObservableTunnel.kt
index ef22f846..9684ffab 100644
--- a/ui/src/main/java/com/wireguard/android/model/ObservableTunnel.kt
+++ b/ui/src/main/java/com/wireguard/android/model/ObservableTunnel.kt
@@ -7,6 +7,7 @@ package com.wireguard.android.model
import android.util.Log
import androidx.databinding.BaseObservable
import androidx.databinding.Bindable
+import com.wireguard.android.Application
import com.wireguard.android.BR
import com.wireguard.android.backend.Dhcp
import com.wireguard.android.backend.Statistics
@@ -14,10 +15,12 @@ import com.wireguard.android.backend.Tunnel
import com.wireguard.android.databinding.Keyed
import com.wireguard.android.util.applicationScope
import com.wireguard.android.viewmodel.ConfigDetail
+import com.wireguard.android.viewmodel.PeerDetail
import com.wireguard.config.Config
import com.wireguard.config.InetEndpoint
-import com.wireguard.crypto.Key;
-import java.util.Optional;
+import com.wireguard.config.InetNetwork
+import com.wireguard.crypto.Key
+import java.util.Optional
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext
@@ -63,10 +66,12 @@ class ObservableTunnel internal constructor(
if (state != Tunnel.State.UP) {
onStatisticsChanged(null)
onDhcpChanged(null)
- onEndpointChange(null, null)
+ Application.getCoroutineScope().launch {
+ onPeersReset()
+ }
} else {
configDetail?.peers?.forEach {
- var endpoint: InetEndpoint? = it.peer.endpoint.orElse(null)
+ var endpoint: InetEndpoint? = it.peer?.endpoint?.orElse(null)
it.endpoint = Optional.ofNullable(endpoint?.getResolved()?.get())
}
}
@@ -118,8 +123,8 @@ class ObservableTunnel internal constructor(
}
fun onConfigChanged(config: Config?): ConfigDetail? {
- this.config = config
this.configDetail = ConfigDetail(config)
+ this.config = config
notifyPropertyChanged(BR.config)
return configDetail
}
@@ -171,18 +176,89 @@ class ObservableTunnel internal constructor(
return dhcp
}
- override fun onEndpointChange(publicKey: Key?, newEndpoint: InetEndpoint?) {
+ // Remove dynamic peers, and reset static peers
+ fun onPeersReset() {
+ Log.i(TAG, "ObservableTunnel onPeersReset")
+ var toRemove: MutableList<PeerDetail> = ArrayList()
+
+ configDetail?.peers?.forEach {
+ if (it.peer == null) {
+ toRemove.add(it)
+ } else {
+ it.endpoint = Optional.empty()
+ }
+ }
+
+ toRemove.forEach {
+ Log.i(TAG, "ObservableTunnel remove " + it)
+ configDetail?.peers?.remove(it)
+ }
+ }
+
+ override fun onEndpointChange(publicKey: Key, newEndpoint: InetEndpoint?) {
+ Application.getCoroutineScope().launch {
+ onEndpointChanged(publicKey, newEndpoint)
+ }
+ }
+
+ private fun onEndpointChanged(publicKey: Key, newEndpoint: InetEndpoint?) {
+
Log.i(TAG, "ObservableTunnel onEndpointChange " + newEndpoint)
+ var peer: PeerDetail? = null
+
configDetail?.peers?.forEach {
- Log.i(TAG, "ObservableTunnel peer " + it + ", " + it.peer)
- if (publicKey == null || it.peer.publicKey.equals(publicKey)) {
- if (newEndpoint == null) {
- it.endpoint = it.peer.endpoint
- } else {
- it.endpoint = newEndpoint.getResolved()
- }
+ if (it.publicKey.equals(publicKey) == true) {
+ Log.i(TAG, "ObservableTunnel peer " + it + ", " + it.peer)
+ peer = it;
+ }
+ }
+
+ if (peer == null) {
+ Log.i(TAG, "ObservableTunnel create peer " + publicKey)
+ peer = PeerDetail(publicKey)
+ configDetail?.peers?.add(peer)
+ }
+
+ var peer2: PeerDetail = peer!!
+
+ if (newEndpoint != null) {
+ peer2.endpoint = newEndpoint.getResolved()
+ } else {
+ var peer3 = peer2.peer
+ peer2.endpoint = if (peer3 != null) peer3.endpoint else Optional.empty()
+ }
+ }
+
+ fun lookupPeer(publicKey: Key): PeerDetail {
+ configDetail?.peers?.forEach {
+ if (it.publicKey.equals(publicKey) == true) {
+ Log.i(TAG, "ObservableTunnel peer " + it + ", " + it.peer)
+ return it
}
}
+
+ Log.i(TAG, "ObservableTunnel create peer " + publicKey)
+ var peer: PeerDetail = PeerDetail(publicKey)
+ configDetail?.peers?.add(peer)
+
+ return peer
+ }
+
+ override fun onAllowedIpsChange(publicKey: Key, addNetworks: List<InetNetwork>?, removeNetworks: List<InetNetwork>?) {
+ Application.getCoroutineScope().launch {
+ onAllowedIpsChanged(publicKey, addNetworks, removeNetworks)
+ }
+ }
+
+ private fun onAllowedIpsChanged(publicKey: Key, addNetworks: List<InetNetwork>?, removeNetworks: List<InetNetwork>?) {
+ var peer: PeerDetail = lookupPeer(publicKey)
+
+ removeNetworks?.let() {
+ peer.allowedIps.removeAll(removeNetworks)
+ }
+ addNetworks?.let() {
+ peer.allowedIps.addAll(addNetworks)
+ }
}
diff --git a/ui/src/main/java/com/wireguard/android/viewmodel/PeerDetail.kt b/ui/src/main/java/com/wireguard/android/viewmodel/PeerDetail.kt
index abc81998..80b32fd5 100644
--- a/ui/src/main/java/com/wireguard/android/viewmodel/PeerDetail.kt
+++ b/ui/src/main/java/com/wireguard/android/viewmodel/PeerDetail.kt
@@ -4,25 +4,37 @@ import android.util.Log
import androidx.databinding.BaseObservable
import androidx.databinding.Bindable
import androidx.databinding.Observable
+import androidx.databinding.ObservableList
+import androidx.databinding.ObservableArrayList
import com.wireguard.android.BR
import com.wireguard.config.InetEndpoint
+import com.wireguard.config.InetNetwork
import com.wireguard.config.Peer
+import com.wireguard.crypto.Key;
import java.util.Optional;
+import kotlin.collections.LinkedHashSet
+
class PeerDetail : BaseObservable {
- var peer: Peer
+ var peer: Peer?
private var owner: ConfigDetail? = null
@get:Bindable
+ var publicKey: Key
+
+ @get:Bindable
+ var allowedIps: ObservableList<InetNetwork> = ObservableArrayList<InetNetwork>()
+
+ @get:Bindable
var endpoint: Optional<InetEndpoint> = Optional.empty()
get() {
if (!field.isEmpty()) {
return field
} else {
- return peer.endpoint
+ return Optional.ofNullable(peer?.endpoint?.get())
}
}
@@ -32,8 +44,20 @@ class PeerDetail : BaseObservable {
notifyPropertyChanged(BR.endpoint)
}
+ @get:Bindable
+ var persistentKeepalive: Optional<Int> = Optional.empty()
+
constructor(other: Peer) {
peer = other
+ publicKey = other.getPublicKey()
+ allowedIps.addAll(other.getAllowedIps())
+ endpoint = other.getEndpoint();
+ persistentKeepalive = other.getPersistentKeepalive()
+ }
+
+ constructor(publicKey: Key) {
+ peer = null
+ this.publicKey = publicKey
}
fun bind(owner: ConfigDetail) {
@@ -45,6 +69,16 @@ class PeerDetail : BaseObservable {
super.addOnPropertyChangedCallback(callback)
}
+ /**
+ * Converts the {@code Peer} into a string suitable for debugging purposes. The {@code Peer} is
+ * identified by its public key and (if known) its endpoint.
+ *
+ * @return a concise single-line identifier for the {@code Peer}
+ */
+ override fun toString(): String {
+ return "(Peer " + publicKey.toBase64() + ")"
+ }
+
companion object {
private const val TAG = "WireGuard/PeerDetail"
}
diff --git a/ui/src/main/res/layout/tunnel_detail_fragment.xml b/ui/src/main/res/layout/tunnel_detail_fragment.xml
index 1c4c25d6..59112d5e 100644
--- a/ui/src/main/res/layout/tunnel_detail_fragment.xml
+++ b/ui/src/main/res/layout/tunnel_detail_fragment.xml
@@ -367,6 +367,7 @@
android:layout_marginTop="8dp"
android:divider="@null"
android:orientation="vertical"
+ app:fragment="@{fragment}"
app:items="@{config.peers}"
app:layout="@{@layout/tunnel_detail_peer}"
app:layout_constraintStart_toStartOf="parent"
diff --git a/ui/src/main/res/layout/tunnel_detail_peer.xml b/ui/src/main/res/layout/tunnel_detail_peer.xml
index e70c3df5..b4a07003 100644
--- a/ui/src/main/res/layout/tunnel_detail_peer.xml
+++ b/ui/src/main/res/layout/tunnel_detail_peer.xml
@@ -52,7 +52,7 @@
android:nextFocusForward="@id/pre_shared_key_text"
android:onClick="@{ClipboardUtils::copyTextView}"
android:singleLine="true"
- android:text="@{item.peer.publicKey.toBase64}"
+ android:text="@{item.publicKey.toBase64}"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/public_key_label"
tools:text="wOs2eguFEohqIZxlSJ1CAT9584tc6ejj9hfGFsoBVkA=" />
@@ -93,7 +93,7 @@
android:layout_marginTop="8dp"
android:labelFor="@+id/allowed_ips_text"
android:text="@string/allowed_ips"
- android:visibility="@{item.peer.allowedIps.isEmpty() ? android.view.View.GONE : android.view.View.VISIBLE}"
+ android:visibility="@{item.allowedIps.isEmpty() ? android.view.View.GONE : android.view.View.VISIBLE}"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/pre_shared_key_text" />
@@ -107,8 +107,8 @@
android:nextFocusDown="@id/endpoint_text"
android:nextFocusForward="@id/endpoint_text"
android:onClick="@{ClipboardUtils::copyTextView}"
- android:text="@{item.peer.allowedIps}"
- android:visibility="@{item.peer.allowedIps.isEmpty() ? android.view.View.GONE : android.view.View.VISIBLE}"
+ android:text="@{item.allowedIps}"
+ android:visibility="@{item.allowedIps.isEmpty() ? android.view.View.GONE : android.view.View.VISIBLE}"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/allowed_ips_label"
tools:text="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" />
@@ -147,7 +147,7 @@
android:layout_marginTop="8dp"
android:labelFor="@+id/persistent_keepalive_text"
android:text="@string/persistent_keepalive"
- android:visibility="@{!item.peer.persistentKeepalive.isPresent() ? android.view.View.GONE : android.view.View.VISIBLE}"
+ android:visibility="@{!item.persistentKeepalive.isPresent() ? android.view.View.GONE : android.view.View.VISIBLE}"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/endpoint_text" />
@@ -161,8 +161,8 @@
android:nextFocusDown="@id/transfer_text"
android:nextFocusForward="@id/transfer_text"
android:onClick="@{ClipboardUtils::copyTextView}"
- android:text="@{@plurals/persistent_keepalive_seconds_unit(item.peer.persistentKeepalive.orElse(0), item.peer.persistentKeepalive.orElse(0))}"
- android:visibility="@{!item.peer.persistentKeepalive.isPresent() ? android.view.View.GONE : android.view.View.VISIBLE}"
+ android:text="@{@plurals/persistent_keepalive_seconds_unit(item.persistentKeepalive.orElse(0), item.persistentKeepalive.orElse(0))}"
+ android:visibility="@{!item.persistentKeepalive.isPresent() ? android.view.View.GONE : android.view.View.VISIBLE}"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/persistent_keepalive_label"
tools:text="every 3 seconds" />