Prevent creating 2 ip link monitors
This commit is contained in:
@@ -3,26 +3,6 @@ package be.mygod.vpnhotspot.net.monitor
|
||||
import be.mygod.vpnhotspot.App.Companion.app
|
||||
|
||||
class InterfaceMonitor(val iface: String) : UpstreamMonitor() {
|
||||
companion object {
|
||||
/**
|
||||
* Based on: https://android.googlesource.com/platform/external/iproute2/+/70556c1/ip/ipaddress.c#1053
|
||||
*/
|
||||
private val parser = "^(Deleted )?-?\\d+: ([^:@]+)".toRegex()
|
||||
}
|
||||
|
||||
private inner class IpLinkMonitor : IpMonitor() {
|
||||
override val monitoredObject: String get() = "link"
|
||||
|
||||
override fun processLine(line: String) {
|
||||
val match = parser.find(line) ?: return
|
||||
if (match.groupValues[2] != iface) return
|
||||
setPresent(match.groupValues[1].isEmpty())
|
||||
}
|
||||
|
||||
override fun processLines(lines: Sequence<String>) =
|
||||
setPresent(lines.any { parser.find(it)?.groupValues?.get(2) == iface })
|
||||
}
|
||||
|
||||
private fun setPresent(present: Boolean) = synchronized(this) {
|
||||
val old = currentIface != null
|
||||
if (present == old) return
|
||||
@@ -33,7 +13,7 @@ class InterfaceMonitor(val iface: String) : UpstreamMonitor() {
|
||||
} else callbacks.forEach { it.onLost() }
|
||||
}
|
||||
|
||||
private var monitor: IpLinkMonitor? = null
|
||||
private var registered = false
|
||||
override var currentIface: String? = null
|
||||
private set
|
||||
override val currentLinkProperties get() = app.connectivity.allNetworks
|
||||
@@ -41,18 +21,14 @@ class InterfaceMonitor(val iface: String) : UpstreamMonitor() {
|
||||
.singleOrNull { it?.interfaceName == iface }
|
||||
|
||||
override fun registerCallbackLocked(callback: Callback) {
|
||||
var monitor = monitor
|
||||
if (monitor == null) {
|
||||
monitor = IpLinkMonitor()
|
||||
this.monitor = monitor
|
||||
monitor.run()
|
||||
if (!registered) {
|
||||
IpLinkMonitor.registerCallback(this, iface, this::setPresent)
|
||||
registered = true
|
||||
} else if (currentIface != null) callback.onAvailable(iface, currentDns)
|
||||
}
|
||||
|
||||
override fun destroyLocked() {
|
||||
val monitor = monitor ?: return
|
||||
this.monitor = null
|
||||
currentIface = null
|
||||
monitor.destroy()
|
||||
IpLinkMonitor.unregisterCallback(this)
|
||||
registered = false
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,43 @@
|
||||
package be.mygod.vpnhotspot.net.monitor
|
||||
|
||||
class IpLinkMonitor private constructor() : IpMonitor() {
|
||||
companion object {
|
||||
/**
|
||||
* Based on: https://android.googlesource.com/platform/external/iproute2/+/70556c1/ip/ipaddress.c#1053
|
||||
*/
|
||||
private val parser = "^(Deleted )?-?\\d+: ([^:@]+)".toRegex()
|
||||
|
||||
private val callbacks = HashMap<Any, Pair<String, (Boolean) -> Unit>>()
|
||||
private var instance: IpLinkMonitor? = null
|
||||
|
||||
fun registerCallback(owner: Any, iface: String, callback: (Boolean) -> Unit) {
|
||||
check(callbacks.put(owner, Pair(iface, callback)) == null)
|
||||
var monitor = instance
|
||||
if (monitor == null) {
|
||||
monitor = IpLinkMonitor()
|
||||
instance = monitor
|
||||
}
|
||||
monitor.flush()
|
||||
}
|
||||
fun unregisterCallback(owner: Any) {
|
||||
if (callbacks.remove(owner) == null || callbacks.isNotEmpty()) return
|
||||
instance?.destroy()
|
||||
instance = null
|
||||
}
|
||||
}
|
||||
|
||||
override val monitoredObject: String get() = "link"
|
||||
|
||||
override fun processLine(line: String) {
|
||||
val match = parser.find(line) ?: return
|
||||
val iface = match.groupValues[2]
|
||||
val present = match.groupValues[1].isEmpty()
|
||||
for ((target, callback) in callbacks.values) if (target == iface) callback(present)
|
||||
}
|
||||
|
||||
override fun processLines(lines: Sequence<String>) {
|
||||
val present = HashSet<String>()
|
||||
for (it in lines) present.add((parser.find(it) ?: continue).groupValues[2])
|
||||
callbacks.values.forEach { (iface, callback) -> callback(present.contains(iface)) }
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user