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
|
import be.mygod.vpnhotspot.App.Companion.app
|
||||||
|
|
||||||
class InterfaceMonitor(val iface: String) : UpstreamMonitor() {
|
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) {
|
private fun setPresent(present: Boolean) = synchronized(this) {
|
||||||
val old = currentIface != null
|
val old = currentIface != null
|
||||||
if (present == old) return
|
if (present == old) return
|
||||||
@@ -33,7 +13,7 @@ class InterfaceMonitor(val iface: String) : UpstreamMonitor() {
|
|||||||
} else callbacks.forEach { it.onLost() }
|
} else callbacks.forEach { it.onLost() }
|
||||||
}
|
}
|
||||||
|
|
||||||
private var monitor: IpLinkMonitor? = null
|
private var registered = false
|
||||||
override var currentIface: String? = null
|
override var currentIface: String? = null
|
||||||
private set
|
private set
|
||||||
override val currentLinkProperties get() = app.connectivity.allNetworks
|
override val currentLinkProperties get() = app.connectivity.allNetworks
|
||||||
@@ -41,18 +21,14 @@ class InterfaceMonitor(val iface: String) : UpstreamMonitor() {
|
|||||||
.singleOrNull { it?.interfaceName == iface }
|
.singleOrNull { it?.interfaceName == iface }
|
||||||
|
|
||||||
override fun registerCallbackLocked(callback: Callback) {
|
override fun registerCallbackLocked(callback: Callback) {
|
||||||
var monitor = monitor
|
if (!registered) {
|
||||||
if (monitor == null) {
|
IpLinkMonitor.registerCallback(this, iface, this::setPresent)
|
||||||
monitor = IpLinkMonitor()
|
registered = true
|
||||||
this.monitor = monitor
|
|
||||||
monitor.run()
|
|
||||||
} else if (currentIface != null) callback.onAvailable(iface, currentDns)
|
} else if (currentIface != null) callback.onAvailable(iface, currentDns)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun destroyLocked() {
|
override fun destroyLocked() {
|
||||||
val monitor = monitor ?: return
|
IpLinkMonitor.unregisterCallback(this)
|
||||||
this.monitor = null
|
registered = false
|
||||||
currentIface = null
|
|
||||||
monitor.destroy()
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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