diff --git a/mobile/src/main/java/be/mygod/vpnhotspot/SettingsPreferenceFragment.kt b/mobile/src/main/java/be/mygod/vpnhotspot/SettingsPreferenceFragment.kt index fadb0be0..0394f9c3 100644 --- a/mobile/src/main/java/be/mygod/vpnhotspot/SettingsPreferenceFragment.kt +++ b/mobile/src/main/java/be/mygod/vpnhotspot/SettingsPreferenceFragment.kt @@ -12,6 +12,7 @@ import androidx.preference.Preference import androidx.preference.SwitchPreference import be.mygod.vpnhotspot.App.Companion.app import be.mygod.vpnhotspot.net.Routing +import be.mygod.vpnhotspot.net.Routing.Companion.IPTABLES import be.mygod.vpnhotspot.net.monitor.FallbackUpstreamMonitor import be.mygod.vpnhotspot.net.monitor.UpstreamMonitor import be.mygod.vpnhotspot.preference.AlwaysAutoCompleteEditTextPreferenceDialogFragmentCompat @@ -87,7 +88,7 @@ class SettingsPreferenceFragment : PreferenceFragmentCompat() { |ip rule |echo |echo iptables -nvx -L vpnhotspot_fwd - |iptables -nvx -L vpnhotspot_fwd + |$IPTABLES -nvx -L vpnhotspot_fwd |echo |echo logcat-su |logcat -d diff --git a/mobile/src/main/java/be/mygod/vpnhotspot/net/Routing.kt b/mobile/src/main/java/be/mygod/vpnhotspot/net/Routing.kt index 4fea3e60..762a2064 100644 --- a/mobile/src/main/java/be/mygod/vpnhotspot/net/Routing.kt +++ b/mobile/src/main/java/be/mygod/vpnhotspot/net/Routing.kt @@ -34,21 +34,21 @@ class Routing(val downstream: String, ownerAddress: InterfaceAddress? = null) { * * Source: https://android.googlesource.com/platform/external/iptables/+/android-5.0.0_r1/iptables/iptables.c#1574 */ - private val IPTABLES = if (Build.VERSION.SDK_INT >= 26) "iptables -w 1" else "iptables -w" + val IPTABLES = if (Build.VERSION.SDK_INT >= 26) "iptables -w 1" else "iptables -w" fun clean() { TrafficRecorder.clean() RootSession.use { - it.submit("$IPTABLES -t nat -F PREROUTING") - it.submit("while $IPTABLES -D FORWARD -j vpnhotspot_fwd; do done") - it.submit("$IPTABLES -F vpnhotspot_fwd") - it.submit("$IPTABLES -X vpnhotspot_fwd") - it.submit("while $IPTABLES -t nat -D POSTROUTING -j vpnhotspot_masquerade; do done") - it.submit("$IPTABLES -t nat -F vpnhotspot_masquerade") - it.submit("$IPTABLES -t nat -X vpnhotspot_masquerade") - it.submit("while ip rule del priority $RULE_PRIORITY_UPSTREAM; do done") - it.submit("while ip rule del priority $RULE_PRIORITY_UPSTREAM_FALLBACK; do done") - it.submit("while ip rule del iif lo uidrange 0-0 lookup local_network priority 11000; do done") + it.execQuiet("$IPTABLES -t nat -F PREROUTING") + it.execQuiet("while $IPTABLES -D FORWARD -j vpnhotspot_fwd; do done") + it.execQuiet("$IPTABLES -F vpnhotspot_fwd") + it.execQuiet("$IPTABLES -X vpnhotspot_fwd") + it.execQuiet("while $IPTABLES -t nat -D POSTROUTING -j vpnhotspot_masquerade; do done") + it.execQuiet("$IPTABLES -t nat -F vpnhotspot_masquerade") + it.execQuiet("$IPTABLES -t nat -X vpnhotspot_masquerade") + it.execQuiet("while ip rule del priority $RULE_PRIORITY_UPSTREAM; do done") + it.execQuiet("while ip rule del priority $RULE_PRIORITY_UPSTREAM_FALLBACK; do done") + it.execQuiet("while ip rule del iif lo uidrange 0-0 lookup local_network priority 11000; do done") } } diff --git a/mobile/src/main/java/be/mygod/vpnhotspot/net/monitor/TrafficRecorder.kt b/mobile/src/main/java/be/mygod/vpnhotspot/net/monitor/TrafficRecorder.kt index 74fde249..f17affdb 100644 --- a/mobile/src/main/java/be/mygod/vpnhotspot/net/monitor/TrafficRecorder.kt +++ b/mobile/src/main/java/be/mygod/vpnhotspot/net/monitor/TrafficRecorder.kt @@ -1,7 +1,8 @@ package be.mygod.vpnhotspot.net.monitor -import android.os.SystemClock import android.util.LongSparseArray +import androidx.core.os.postDelayed +import be.mygod.vpnhotspot.net.Routing.Companion.IPTABLES import be.mygod.vpnhotspot.room.AppDatabase import be.mygod.vpnhotspot.room.TrafficRecord import be.mygod.vpnhotspot.room.insert @@ -49,7 +50,7 @@ object TrafficRecorder { val minute = TimeUnit.MINUTES.toMillis(1) var timeout = minute - now % minute if (foregroundListeners.isNotEmpty() && timeout > 1000) timeout = 1000 - RootSession.handler.postAtTime(this::update, this, SystemClock.uptimeMillis() + timeout) + RootSession.handler.postDelayed(timeout, this) { update(true) } scheduled = true } @@ -60,7 +61,7 @@ object TrafficRecorder { private fun doUpdate(timestamp: Long) { val oldRecords = LongSparseArray() - for (line in RootSession.use { it.execOutUnjoined("iptables -nvx -L vpnhotspot_fwd") }.asSequence().drop(2)) { + for (line in RootSession.use { it.execOutUnjoined("$IPTABLES -nvx -L vpnhotspot_fwd") }.asSequence().drop(2)) { val columns = line.split("\\s+".toRegex()).filter { it.isNotEmpty() } try { check(columns.size >= 9) @@ -119,24 +120,19 @@ object TrafficRecorder { } foregroundListeners(records.values, oldRecords) } - fun update() { + fun update(timeout: Boolean = false) { synchronized(this) { - val wasScheduled = scheduled - scheduled = false + if (timeout) scheduled = false if (records.isEmpty()) return val timestamp = System.currentTimeMillis() - if (timestamp - lastUpdate > 100) { - try { - doUpdate(timestamp) - } catch (e: RuntimeException) { - Timber.w(e) - SmartSnackbar.make(e.localizedMessage) - } - lastUpdate = timestamp - } else if (wasScheduled) { - scheduled = true - return + if (!timeout && timestamp - lastUpdate <= 100) return + try { + doUpdate(timestamp) + } catch (e: RuntimeException) { + Timber.w(e) + SmartSnackbar.make(e.localizedMessage) } + lastUpdate = timestamp scheduleUpdateLocked() } } diff --git a/mobile/src/main/java/be/mygod/vpnhotspot/util/RootSession.kt b/mobile/src/main/java/be/mygod/vpnhotspot/util/RootSession.kt index 68d161b0..ab9048c9 100644 --- a/mobile/src/main/java/be/mygod/vpnhotspot/util/RootSession.kt +++ b/mobile/src/main/java/be/mygod/vpnhotspot/util/RootSession.kt @@ -85,11 +85,13 @@ class RootSession : AutoCloseable { */ fun submit(command: String) { val result = execQuiet(command) - if (result.code != 0) Timber.v("$command exited with ${result.code}") - var msg = result.err.joinToString("\n").trim() - if (msg.isNotEmpty()) Timber.v(msg) - msg = result.out.joinToString("\n").trim() - if (msg.isNotEmpty()) Timber.v(msg) + val err = result.err.joinToString("\n") { "E $it" }.trim() + val out = result.out.joinToString("\n").trim() + if (result.code != 0 || err.isNotEmpty() || out.isNotEmpty()) { + Timber.v("$command exited with ${result.code}") + if (err.isNotEmpty()) Timber.v(err) + if (out.isNotEmpty()) Timber.v(out) + } } fun execQuiet(command: String, redirect: Boolean = false): Shell.Result {