Commit 734056ea authored by Mygod's avatar Mygod

Remove dependency on libsuperuser

There is no longer a reason to use this overkill.

* Turning on tcp_fastopen is replaced by manual su call;
* Call to chmod binary is replaced by Os.chmod, which is better at error reporting. (also bumps plugin library to 1.0.0)
parent 5627357a
......@@ -78,7 +78,6 @@ dependencies {
api 'com.google.firebase:firebase-core:16.0.6'
api 'com.squareup.okhttp3:okhttp:3.12.1'
api "com.takisoft.preferencex:preferencex:$preferencexVersion"
api 'eu.chainfire:libsuperuser:1.0.0.201811281328'
kapt "androidx.room:room-compiler:$roomVersion"
testImplementation "androidx.room:room-testing:$roomVersion"
testImplementation "junit:junit:$junitVersion"
......
......@@ -110,7 +110,7 @@ object Core {
// handle data restored/crash
if (Build.VERSION.SDK_INT >= 24 && DataStore.directBootAware &&
app.getSystemService<UserManager>()?.isUserUnlocked == true) DirectBoot.flushTrafficStats()
if (DataStore.tcpFastOpen) TcpFastOpen.enabledAsync(true)
if (DataStore.tcpFastOpen && !TcpFastOpen.sendEnabled) TcpFastOpen.enabledAsync()
if (DataStore.publicStore.getLong(Key.assetUpdateTime, -1) != packageInfo.lastUpdateTime) {
val assetManager = app.assets
for (dir in arrayOf("acl", "overture"))
......
......@@ -26,17 +26,17 @@ import android.content.ContentResolver
import android.content.Intent
import android.content.pm.PackageManager
import android.content.pm.Signature
import android.database.Cursor
import android.net.Uri
import android.system.Os
import android.util.Base64
import android.util.Log
import androidx.core.os.bundleOf
import com.crashlytics.android.Crashlytics
import com.github.shadowsocks.Core
import com.github.shadowsocks.Core.app
import com.github.shadowsocks.utils.Commandline
import com.github.shadowsocks.utils.printLog
import com.github.shadowsocks.utils.signaturesCompat
import eu.chainfire.libsuperuser.Shell
import java.io.File
import java.io.FileNotFoundException
......@@ -162,7 +162,6 @@ object PluginManager {
private fun initNativeSlow(cr: ContentResolver, options: PluginOptions, uri: Uri): String? {
var initialized = false
fun entryNotFound(): Nothing = throw IndexOutOfBoundsException("Plugin entry binary not found")
val list = ArrayList<String>()
val pluginDir = File(Core.deviceStorage.noBackupFilesDir, "plugin")
(cr.query(uri, arrayOf(PluginContract.COLUMN_PATH, PluginContract.COLUMN_MODE), null, null, null)
?: return null).use { cursor ->
......@@ -177,12 +176,15 @@ object PluginManager {
cr.openInputStream(uri.buildUpon().path(path).build())!!.use { inStream ->
file.outputStream().use { outStream -> inStream.copyTo(outStream) }
}
list += Commandline.toString(arrayOf("chmod", cursor.getString(1), file.absolutePath))
Os.chmod(file.absolutePath, when (cursor.getType(1)) {
Cursor.FIELD_TYPE_INTEGER -> cursor.getInt(1)
Cursor.FIELD_TYPE_STRING -> cursor.getString(1).toInt(8)
else -> throw IllegalArgumentException()
})
if (path == options.id) initialized = true
} while (cursor.moveToNext())
}
if (!initialized) entryNotFound()
Shell.SH.run(list)
return File(pluginDir, options.id).absolutePath
}
}
......@@ -20,10 +20,12 @@
package com.github.shadowsocks.utils
import eu.chainfire.libsuperuser.Shell
import java.io.File
import java.io.IOException
object TcpFastOpen {
private const val PATH = "/proc/sys/net/ipv4/tcp_fastopen"
/**
* Is kernel version >= 3.7.1.
*/
......@@ -41,16 +43,19 @@ object TcpFastOpen {
}
val sendEnabled: Boolean get() {
val file = File("/proc/sys/net/ipv4/tcp_fastopen")
val file = File(PATH)
// File.readText doesn't work since this special file will return length 0
return file.canRead() && file.bufferedReader().use { it.readText() }.trim().toInt() and 1 > 0
}
fun enabled(value: Boolean): String? = if (sendEnabled == value) null else Shell.run("su", arrayOf(
"if echo " + (if (value) 3 else 0) + " > /proc/sys/net/ipv4/tcp_fastopen; then",
" echo Success.",
"else",
" echo Failed.",
"fi"), null, true)?.joinToString("\n")
fun enabledAsync(value: Boolean) = thread("TcpFastOpen") { enabled(value) }.join(1000)
fun enabled(): String? {
return try {
val process = ProcessBuilder("su", "-c", "echo 3 > $PATH")
.redirectErrorStream(true).start()
process.inputStream.bufferedReader().readText()
} catch (e: IOException) {
e.localizedMessage
}
}
fun enabledAsync() = thread("TcpFastOpen") { enabled() }.join(1000)
}
......@@ -57,6 +57,7 @@
<string name="direct_boot_aware_summary">Your selected profile information will be less protected</string>
<string name="tcp_fastopen_summary">Toggling might require ROOT permission</string>
<string name="tcp_fastopen_summary_unsupported">Unsupported kernel version: %s &lt; 3.7.1</string>
<string name="tcp_fastopen_failure">Toggle failed</string>
<string name="udp_dns">DNS Forwarding</string>
<string name="udp_dns_summary">Forward all DNS requests to remote</string>
......
......@@ -54,10 +54,13 @@ class GlobalSettingsPreferenceFragment : PreferenceFragmentCompat() {
val tfo = findPreference(Key.tfo) as SwitchPreference
tfo.isChecked = DataStore.tcpFastOpen
tfo.setOnPreferenceChangeListener { _, value ->
if (value as Boolean) {
val result = TcpFastOpen.enabled(true)
if (result != null && result != "Success.") (activity as MainActivity).snackbar(result).show()
TcpFastOpen.sendEnabled
if (value as Boolean && !TcpFastOpen.sendEnabled) {
val result = TcpFastOpen.enabled()?.trim()
if (TcpFastOpen.sendEnabled) true else {
(activity as MainActivity).snackbar(
if (result.isNullOrEmpty()) getText(R.string.tcp_fastopen_failure) else result).show()
false
}
} else true
}
if (!TcpFastOpen.supported) {
......
* 0.2.0:
* 1.0.0:
* `PathProvider` now takes `Int` instead of `String` for file modes;
* Refactor to AndroidX;
* No longer depends on preference libraries.
* 0.1.1:
......
......@@ -11,7 +11,7 @@ android {
minSdkVersion rootProject.minSdkVersion
targetSdkVersion rootProject.sdkVersion
versionCode 7
versionName "0.2.0"
versionName "1.0.0"
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
}
......
......@@ -30,14 +30,14 @@ import java.io.File
class PathProvider internal constructor(baseUri: Uri, private val cursor: MatrixCursor) {
private val basePath = baseUri.path?.trim('/') ?: ""
fun addPath(path: String, mode: String = "644"): PathProvider {
fun addPath(path: String, mode: Int = 0b110100100): PathProvider {
val trimmed = path.trim('/')
if (trimmed.startsWith(basePath)) cursor.newRow()
.add(PluginContract.COLUMN_PATH, trimmed)
.add(PluginContract.COLUMN_MODE, mode)
return this
}
fun addTo(file: File, to: String = "", mode: String = "644"): PathProvider {
fun addTo(file: File, to: String = "", mode: Int = 0b110100100): PathProvider {
var sub = to + file.name
if (basePath.startsWith(sub)) if (file.isDirectory) {
sub += '/'
......@@ -45,7 +45,7 @@ class PathProvider internal constructor(baseUri: Uri, private val cursor: Matrix
} else addPath(sub, mode)
return this
}
fun addAt(file: File, at: String = "", mode: String = "644"): PathProvider {
fun addAt(file: File, at: String = "", mode: Int = 0b110100100): PathProvider {
if (basePath.startsWith(at))
if (file.isDirectory) file.listFiles().forEach { addTo(it, at, mode) } else addPath(at, mode)
return this
......
......@@ -170,10 +170,13 @@ class MainPreferenceFragment : LeanbackPreferenceFragment(), ShadowsocksConnecti
tfo = findPreference(Key.tfo) as SwitchPreference
tfo.isChecked = DataStore.tcpFastOpen
tfo.setOnPreferenceChangeListener { _, value ->
if (value as Boolean) {
val result = TcpFastOpen.enabled(true)
if (result != null && result != "Success.") Toast.makeText(activity, result, Toast.LENGTH_LONG).show()
TcpFastOpen.sendEnabled
if (value as Boolean && !TcpFastOpen.sendEnabled) {
val result = TcpFastOpen.enabled()?.trim()
if (TcpFastOpen.sendEnabled) true else {
Toast.makeText(activity, if (result.isNullOrEmpty())
getText(R.string.tcp_fastopen_failure) else result, Toast.LENGTH_SHORT).show()
false
}
} else true
}
if (!TcpFastOpen.supported) {
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment