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 4a497c5f..d31e7626 100644 --- a/mobile/src/main/java/be/mygod/vpnhotspot/net/Routing.kt +++ b/mobile/src/main/java/be/mygod/vpnhotspot/net/Routing.kt @@ -14,7 +14,6 @@ import be.mygod.vpnhotspot.util.RootSession import be.mygod.vpnhotspot.util.computeIfAbsentCompat import be.mygod.vpnhotspot.widget.SmartSnackbar import timber.log.Timber -import java.lang.RuntimeException import java.net.* import java.util.concurrent.atomic.AtomicLong @@ -61,10 +60,15 @@ class Routing(val downstream: String, ownerAddress: InterfaceAddress? = null) : } } + private fun RootSession.Transaction.iptables(command: String, revert: String) { + val result = execQuiet(command, revert) + val message = RootSession.checkOutput(command, result, err = false) + if (result.err.isNotEmpty()) Timber.i(message) // busy wait message + } private fun RootSession.Transaction.iptablesAdd(content: String, table: String = "filter") = - exec("$IPTABLES -t $table -A $content", "$IPTABLES -t $table -D $content", true) + iptables("$IPTABLES -t $table -A $content", "$IPTABLES -t $table -D $content") private fun RootSession.Transaction.iptablesInsert(content: String, table: String = "filter") = - exec("$IPTABLES -t $table -I $content", "$IPTABLES -t $table -D $content", true) + iptables("$IPTABLES -t $table -I $content", "$IPTABLES -t $table -D $content") } class InterfaceNotFoundException : SocketException() { 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 abfe5d0f..c965ad1f 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 @@ -67,7 +67,7 @@ object TrafficRecorder { loop@ for (line in RootSession.use { val command = "$IPTABLES -nvx -L vpnhotspot_fwd" val result = it.execQuiet(command) - val message = it.checkOutput(command, result, false, false) + val message = RootSession.checkOutput(command, result, false, false) if (result.err.isNotEmpty()) Timber.i(message) result.out.drop(2) }) { diff --git a/mobile/src/main/java/be/mygod/vpnhotspot/net/wifi/P2pSupplicantConfiguration.kt b/mobile/src/main/java/be/mygod/vpnhotspot/net/wifi/P2pSupplicantConfiguration.kt index a6a83e0c..e078553e 100644 --- a/mobile/src/main/java/be/mygod/vpnhotspot/net/wifi/P2pSupplicantConfiguration.kt +++ b/mobile/src/main/java/be/mygod/vpnhotspot/net/wifi/P2pSupplicantConfiguration.kt @@ -49,7 +49,7 @@ class P2pSupplicantConfiguration(private val group: WifiP2pGroup, ownerAddress: var target: NetworkBlock? = null val command = "cat $CONF_PATH_TREBLE || cat $CONF_PATH_LEGACY" val shell = it.execQuiet(command) - it.checkOutput(command, shell, false, false) + RootSession.checkOutput(command, shell, false, false) val parser = Parser(shell.out) try { val bssid = group.owner.deviceAddress ?: ownerAddress 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 d53dbec5..d4f39f51 100644 --- a/mobile/src/main/java/be/mygod/vpnhotspot/util/RootSession.kt +++ b/mobile/src/main/java/be/mygod/vpnhotspot/util/RootSession.kt @@ -54,16 +54,18 @@ class RootSession : AutoCloseable { instance.haltTimeout() instance.close() } + + fun checkOutput(command: String, result: Shell.Result, out: Boolean = result.out.isNotEmpty(), + err: Boolean = result.err.isNotEmpty()): String { + val msg = StringBuilder("$command exited with ${result.code}") + if (out) result.out.forEach { msg.append("\n$it") } + if (err) result.err.forEach { msg.append("\nE $it") } + if (!result.isSuccess || out || err) throw UnexpectedOutputException(msg.toString()) + return msg.toString() + } } class UnexpectedOutputException(msg: String) : RuntimeException(msg) - fun checkOutput(command: String, result: Shell.Result, out: Boolean = result.out.isNotEmpty(), - err: Boolean = result.err.isNotEmpty()): String { - val msg = StringBuilder("$command exited with ${result.code}") - if (out) result.out.forEach { msg.append("\n$it") } - if (err) result.err.forEach { msg.append("\nE $it") } - if (!result.isSuccess || out || err) throw UnexpectedOutputException(msg.toString()) else return msg.toString() - } private val shell = Shell.newInstance("su") private val stdout = ArrayList() @@ -114,15 +116,11 @@ class RootSession : AutoCloseable { inner class Transaction { private val revertCommands = LinkedList() - fun exec(command: String, revert: String? = null, wait: Boolean = false) { + fun exec(command: String, revert: String? = null) = checkOutput(command, execQuiet(command, revert)) + fun execQuiet(command: String, revert: String? = null): Shell.Result { if (revert != null) revertCommands.addFirst(revert) // add first just in case exec fails - if (wait) { - val result = this@RootSession.execQuiet(command) - val message = checkOutput(command, result, err = false) - if (result.err.isNotEmpty()) Timber.i(message) - } else this@RootSession.exec(command) + return this@RootSession.execQuiet(command) } - fun execQuiet(command: String) = this@RootSession.execQuiet(command) fun commit() = unlock() diff --git a/mobile/src/main/java/be/mygod/vpnhotspot/widget/SmartSnackbar.kt b/mobile/src/main/java/be/mygod/vpnhotspot/widget/SmartSnackbar.kt index d155d6f2..4faad0ed 100644 --- a/mobile/src/main/java/be/mygod/vpnhotspot/widget/SmartSnackbar.kt +++ b/mobile/src/main/java/be/mygod/vpnhotspot/widget/SmartSnackbar.kt @@ -9,7 +9,6 @@ import androidx.lifecycle.Lifecycle import androidx.lifecycle.LifecycleObserver import androidx.lifecycle.OnLifecycleEvent import be.mygod.vpnhotspot.App.Companion.app -import be.mygod.vpnhotspot.R import com.google.android.material.snackbar.Snackbar import com.topjohnwu.superuser.NoShellException @@ -21,7 +20,7 @@ sealed class SmartSnackbar { fun make(@StringRes text: Int): SmartSnackbar = make(app.getText(text)) fun make(text: CharSequence? = ""): SmartSnackbar { val holder = holder - return if (holder == null) { + return if (holder == null) @SuppressLint("ShowToast") { if (Looper.myLooper() == null) Looper.prepare() ToastWrapper(Toast.makeText(app, text, Toast.LENGTH_LONG)) } else SnackbarWrapper(Snackbar.make(holder, text ?: null.toString(), Snackbar.LENGTH_LONG))