Compare commits

...
13 Commits
Author SHA1 Message Date
Max Lv d5fd487ff9 Bump version 2018-04-13 01:35:24 -07:00
Max Lv 89c5d94275 Merge pull request #1747 from Mygod/guarded-process-pool
Manage all processes with GuardedProcessPool
2018-04-12 16:56:31 +08:00
Mygod 0b98a2d4e7 Fix #1716 #1718 2018-04-10 13:20:37 -07:00
Mygod 1bc851dac0 Fix cache inconsistency 2018-04-10 11:54:44 -07:00
Max Lv 37ea3d3f02 Ensure the plugin process is killed. 2018-04-10 01:01:01 -07:00
Mygod 518e25d205 Refine plugin lib 2018-04-10 00:32:43 -07:00
Mygod 43e2731604 Update plugin lib version 2018-04-09 22:20:30 -07:00
Mygod 84c12e705f Update dependencies 2018-04-09 22:17:32 -07:00
Mygod 77ea376b46 Update build.gradle 2018-04-09 22:14:32 -07:00
Mygod 68f3f8b20d Manage all processes with GuardedProcessPool
This way we can destroy the processes and wait for them to exit in parallel, and ensure the process is destroyed so that we won't encounter strange port being used issue at the same time.
2018-04-09 21:54:11 -07:00
Mygod 7226f8aab4 Update shadowsocks-libev 2018-04-09 21:52:55 -07:00
Mygod 36b46d6f32 Refine code style 2018-04-08 20:49:31 -07:00
Max Lv 7687a19cc1 Update GFW List 2018-04-08 18:03:11 -07:00
19 changed files with 104 additions and 285 deletions
+3 -3
View File
@@ -8,8 +8,8 @@ buildscript {
minSdkVersion = 21 minSdkVersion = 21
sdkVersion = 27 sdkVersion = 27
buildToolsVersion = '27.0.3' buildToolsVersion = '27.0.3'
supportLibraryVersion = '27.1.0' supportLibraryVersion = '27.1.1'
takisoftFixVersion = '27.1.0.0' takisoftFixVersion = '27.1.1.0'
playServicesVersion = '12.0.1' playServicesVersion = '12.0.1'
junitVersion = '4.12' junitVersion = '4.12'
androidTestVersion = '1.0.1' androidTestVersion = '1.0.1'
@@ -22,7 +22,7 @@ buildscript {
} }
dependencies { dependencies {
classpath 'com.android.tools.build:gradle:3.1.0' classpath 'com.android.tools.build:gradle:3.1.1'
classpath 'com.github.ben-manes:gradle-versions-plugin:0.17.0' classpath 'com.github.ben-manes:gradle-versions-plugin:0.17.0'
classpath 'com.google.gms:google-services:3.2.1' classpath 'com.google.gms:google-services:3.2.1'
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlinVersion" classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlinVersion"
+3 -3
View File
@@ -21,8 +21,8 @@ android {
applicationId "com.github.shadowsocks" applicationId "com.github.shadowsocks"
minSdkVersion rootProject.minSdkVersion minSdkVersion rootProject.minSdkVersion
targetSdkVersion rootProject.sdkVersion targetSdkVersion rootProject.sdkVersion
versionCode 4050500 versionCode 4050600
versionName "4.5.5" versionName "4.5.6"
testApplicationId "com.github.shadowsocks.test" testApplicationId "com.github.shadowsocks.test"
testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner" testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
resConfigs "fa", "fr", "ja", "ko", "ru", "zh-rCN", "zh-rTW" resConfigs "fa", "fr", "ja", "ko", "ru", "zh-rCN", "zh-rTW"
@@ -64,7 +64,7 @@ dependencies {
implementation "com.google.android.gms:play-services-vision:$playServicesVersion" implementation "com.google.android.gms:play-services-vision:$playServicesVersion"
implementation "com.google.firebase:firebase-config:$playServicesVersion" implementation "com.google.firebase:firebase-config:$playServicesVersion"
implementation 'com.j256.ormlite:ormlite-android:5.1' implementation 'com.j256.ormlite:ormlite-android:5.1'
implementation 'com.mikepenz:materialdrawer:6.0.6' implementation 'com.mikepenz:materialdrawer:6.0.7'
implementation 'com.squareup.okhttp3:okhttp:3.10.0' implementation 'com.squareup.okhttp3:okhttp:3.10.0'
implementation "com.takisoft.fix:preference-v7-simplemenu:$takisoftFixVersion" implementation "com.takisoft.fix:preference-v7-simplemenu:$takisoftFixVersion"
implementation 'com.twofortyfouram:android-plugin-api-for-locale:1.0.2' implementation 'com.twofortyfouram:android-plugin-api-for-locale:1.0.2'
+1 -1
View File
@@ -72,7 +72,7 @@
<activity <activity
android:name=".VpnRequestActivity" android:name=".VpnRequestActivity"
android:theme="@style/Theme.Translucent" android:theme="@style/Theme.AppCompat.Translucent"
android:excludeFromRecents="true" android:excludeFromRecents="true"
android:taskAffinity="" android:taskAffinity=""
android:launchMode="singleTask"/> android:launchMode="singleTask"/>
+3 -58
View File
@@ -5634,9 +5634,7 @@
(^|\.)blogs\.libraryinformationtechnology\.com$ (^|\.)blogs\.libraryinformationtechnology\.com$
(^|\.)blogs\.tampabay\.com$ (^|\.)blogs\.tampabay\.com$
(^|\.)blogs\.yahoo\.co\.jp$ (^|\.)blogs\.yahoo\.co\.jp$
(^|\.)blogspot\.com$ (^|\.)blogspot(\.[a-zA-Z0-9]([a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?){1,2}$
(^|\.)blogspot\.hk$
(^|\.)blogspot\.jp$
(^|\.)blogtd\.net$ (^|\.)blogtd\.net$
(^|\.)blogtd\.org$ (^|\.)blogtd\.org$
(^|\.)bloodshed\.net$ (^|\.)bloodshed\.net$
@@ -6875,61 +6873,8 @@
(^|\.)goodtv\.com\.tw$ (^|\.)goodtv\.com\.tw$
(^|\.)goodtv\.tv$ (^|\.)goodtv\.tv$
(^|\.)goofind\.com$ (^|\.)goofind\.com$
(^|\.)google\.ae$ (^|\.)google(\.[a-zA-Z0-9]([a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?){1,2}$
(^|\.)google\.am$ (^|\.)googleapis(\.[a-zA-Z0-9]([a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?){1,2}$
(^|\.)google\.as$
(^|\.)google\.at$
(^|\.)google\.az$
(^|\.)google\.ba$
(^|\.)google\.be$
(^|\.)google\.bg$
(^|\.)google\.ca$
(^|\.)google\.calstate\.edu$
(^|\.)google\.cd$
(^|\.)google\.ci$
(^|\.)google\.co\.id$
(^|\.)google\.co\.jp$
(^|\.)google\.co\.kr$
(^|\.)google\.co\.ma$
(^|\.)google\.co\.uk$
(^|\.)google\.com$
(^|\.)google\.de$
(^|\.)google\.dj$
(^|\.)google\.dk$
(^|\.)google\.es$
(^|\.)google\.fi$
(^|\.)google\.fm$
(^|\.)google\.fr$
(^|\.)google\.gg$
(^|\.)google\.gl$
(^|\.)google\.gr$
(^|\.)google\.ie$
(^|\.)google\.is$
(^|\.)google\.it$
(^|\.)google\.jo$
(^|\.)google\.kz$
(^|\.)google\.lv$
(^|\.)google\.mn$
(^|\.)google\.ms$
(^|\.)google\.nl$
(^|\.)google\.no$
(^|\.)google\.nu$
(^|\.)google\.ro$
(^|\.)google\.ru$
(^|\.)google\.rw$
(^|\.)google\.sc$
(^|\.)google\.sh$
(^|\.)google\.sk$
(^|\.)google\.sm$
(^|\.)google\.sn$
(^|\.)google\.tk$
(^|\.)google\.tm$
(^|\.)google\.to$
(^|\.)google\.tt$
(^|\.)google\.vu$
(^|\.)google\.ws$
(^|\.)googleapis\.cn$
(^|\.)googleapis\.com$
(^|\.)googleapps\.com$ (^|\.)googleapps\.com$
(^|\.)googlearth\.com$ (^|\.)googlearth\.com$
(^|\.)googleartproject\.com$ (^|\.)googleartproject\.com$
@@ -5648,9 +5648,7 @@
(^|\.)blogs\.libraryinformationtechnology\.com$ (^|\.)blogs\.libraryinformationtechnology\.com$
(^|\.)blogs\.tampabay\.com$ (^|\.)blogs\.tampabay\.com$
(^|\.)blogs\.yahoo\.co\.jp$ (^|\.)blogs\.yahoo\.co\.jp$
(^|\.)blogspot\.com$ (^|\.)blogspot(\.[a-zA-Z0-9]([a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?){1,2}$
(^|\.)blogspot\.hk$
(^|\.)blogspot\.jp$
(^|\.)blogtd\.net$ (^|\.)blogtd\.net$
(^|\.)blogtd\.org$ (^|\.)blogtd\.org$
(^|\.)bloodshed\.net$ (^|\.)bloodshed\.net$
@@ -6889,61 +6887,8 @@
(^|\.)goodtv\.com\.tw$ (^|\.)goodtv\.com\.tw$
(^|\.)goodtv\.tv$ (^|\.)goodtv\.tv$
(^|\.)goofind\.com$ (^|\.)goofind\.com$
(^|\.)google\.ae$ (^|\.)google(\.[a-zA-Z0-9]([a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?){1,2}$
(^|\.)google\.am$ (^|\.)googleapis(\.[a-zA-Z0-9]([a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?){1,2}$
(^|\.)google\.as$
(^|\.)google\.at$
(^|\.)google\.az$
(^|\.)google\.ba$
(^|\.)google\.be$
(^|\.)google\.bg$
(^|\.)google\.ca$
(^|\.)google\.calstate\.edu$
(^|\.)google\.cd$
(^|\.)google\.ci$
(^|\.)google\.co\.id$
(^|\.)google\.co\.jp$
(^|\.)google\.co\.kr$
(^|\.)google\.co\.ma$
(^|\.)google\.co\.uk$
(^|\.)google\.com$
(^|\.)google\.de$
(^|\.)google\.dj$
(^|\.)google\.dk$
(^|\.)google\.es$
(^|\.)google\.fi$
(^|\.)google\.fm$
(^|\.)google\.fr$
(^|\.)google\.gg$
(^|\.)google\.gl$
(^|\.)google\.gr$
(^|\.)google\.ie$
(^|\.)google\.is$
(^|\.)google\.it$
(^|\.)google\.jo$
(^|\.)google\.kz$
(^|\.)google\.lv$
(^|\.)google\.mn$
(^|\.)google\.ms$
(^|\.)google\.nl$
(^|\.)google\.no$
(^|\.)google\.nu$
(^|\.)google\.ro$
(^|\.)google\.ru$
(^|\.)google\.rw$
(^|\.)google\.sc$
(^|\.)google\.sh$
(^|\.)google\.sk$
(^|\.)google\.sm$
(^|\.)google\.sn$
(^|\.)google\.tk$
(^|\.)google\.tm$
(^|\.)google\.to$
(^|\.)google\.tt$
(^|\.)google\.vu$
(^|\.)google\.ws$
(^|\.)googleapis\.cn$
(^|\.)googleapis\.com$
(^|\.)googleapps\.com$ (^|\.)googleapps\.com$
(^|\.)googlearth\.com$ (^|\.)googlearth\.com$
(^|\.)googleartproject\.com$ (^|\.)googleartproject\.com$
+3 -58
View File
@@ -561,9 +561,7 @@
(^|\.)blogs\.libraryinformationtechnology\.com$ (^|\.)blogs\.libraryinformationtechnology\.com$
(^|\.)blogs\.tampabay\.com$ (^|\.)blogs\.tampabay\.com$
(^|\.)blogs\.yahoo\.co\.jp$ (^|\.)blogs\.yahoo\.co\.jp$
(^|\.)blogspot\.com$ (^|\.)blogspot(\.[a-zA-Z0-9]([a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?){1,2}$
(^|\.)blogspot\.hk$
(^|\.)blogspot\.jp$
(^|\.)blogtd\.net$ (^|\.)blogtd\.net$
(^|\.)blogtd\.org$ (^|\.)blogtd\.org$
(^|\.)bloodshed\.net$ (^|\.)bloodshed\.net$
@@ -1802,61 +1800,8 @@
(^|\.)goodtv\.com\.tw$ (^|\.)goodtv\.com\.tw$
(^|\.)goodtv\.tv$ (^|\.)goodtv\.tv$
(^|\.)goofind\.com$ (^|\.)goofind\.com$
(^|\.)google\.ae$ (^|\.)google(\.[a-zA-Z0-9]([a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?){1,2}$
(^|\.)google\.am$ (^|\.)googleapis(\.[a-zA-Z0-9]([a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?){1,2}$
(^|\.)google\.as$
(^|\.)google\.at$
(^|\.)google\.az$
(^|\.)google\.ba$
(^|\.)google\.be$
(^|\.)google\.bg$
(^|\.)google\.ca$
(^|\.)google\.calstate\.edu$
(^|\.)google\.cd$
(^|\.)google\.ci$
(^|\.)google\.co\.id$
(^|\.)google\.co\.jp$
(^|\.)google\.co\.kr$
(^|\.)google\.co\.ma$
(^|\.)google\.co\.uk$
(^|\.)google\.com$
(^|\.)google\.de$
(^|\.)google\.dj$
(^|\.)google\.dk$
(^|\.)google\.es$
(^|\.)google\.fi$
(^|\.)google\.fm$
(^|\.)google\.fr$
(^|\.)google\.gg$
(^|\.)google\.gl$
(^|\.)google\.gr$
(^|\.)google\.ie$
(^|\.)google\.is$
(^|\.)google\.it$
(^|\.)google\.jo$
(^|\.)google\.kz$
(^|\.)google\.lv$
(^|\.)google\.mn$
(^|\.)google\.ms$
(^|\.)google\.nl$
(^|\.)google\.no$
(^|\.)google\.nu$
(^|\.)google\.ro$
(^|\.)google\.ru$
(^|\.)google\.rw$
(^|\.)google\.sc$
(^|\.)google\.sh$
(^|\.)google\.sk$
(^|\.)google\.sm$
(^|\.)google\.sn$
(^|\.)google\.tk$
(^|\.)google\.tm$
(^|\.)google\.to$
(^|\.)google\.tt$
(^|\.)google\.vu$
(^|\.)google\.ws$
(^|\.)googleapis\.cn$
(^|\.)googleapis\.com$
(^|\.)googleapps\.com$ (^|\.)googleapps\.com$
(^|\.)googlearth\.com$ (^|\.)googlearth\.com$
(^|\.)googleartproject\.com$ (^|\.)googleartproject\.com$
@@ -123,7 +123,10 @@ class ProfilesFragment : ToolbarFragment(), Toolbar.OnMenuItemClickListener {
private var adView: AdView? = null private var adView: AdView? = null
init { init {
edit.setOnClickListener { startConfig(item) } edit.setOnClickListener {
item = ProfileManager.getProfile(item.id)!!
startConfig(item)
}
TooltipCompat.setTooltipText(edit, edit.contentDescription) TooltipCompat.setTooltipText(edit, edit.contentDescription)
itemView.setOnClickListener(this) itemView.setOnClickListener(this)
val share = itemView.findViewById<View>(R.id.share) val share = itemView.findViewById<View>(R.id.share)
@@ -38,13 +38,13 @@ class AclSyncJob(private val route: String) : Job() {
return when (parts[0]) { return when (parts[0]) {
TAG -> AclSyncJob(parts[1]) TAG -> AclSyncJob(parts[1])
else -> { else -> {
Log.w(TAG, "Unknown job tag: " + tag) Log.w(TAG, "Unknown job tag: $tag")
null null
} }
} }
} }
fun schedule(route: String): Int = JobRequest.Builder(TAG + ':' + route) fun schedule(route: String): Int = JobRequest.Builder("$TAG:$route")
.setExecutionWindow(TimeUnit.SECONDS.toMillis(10), TimeUnit.DAYS.toMillis(28)) .setExecutionWindow(TimeUnit.SECONDS.toMillis(10), TimeUnit.DAYS.toMillis(28))
.setRequirementsEnforced(true) .setRequirementsEnforced(true)
.setRequiredNetworkType(JobRequest.NetworkType.UNMETERED) .setRequiredNetworkType(JobRequest.NetworkType.UNMETERED)
@@ -76,7 +76,7 @@ object BaseService {
@Volatile var state = STOPPED @Volatile var state = STOPPED
@Volatile var plugin = PluginOptions() @Volatile var plugin = PluginOptions()
@Volatile var pluginPath: String? = null @Volatile var pluginPath: String? = null
var sslocalProcess: GuardedProcess? = null val processes = GuardedProcessPool()
var timer: Timer? = null var timer: Timer? = null
var trafficMonitorThread: TrafficMonitorThread? = null var trafficMonitorThread: TrafficMonitorThread? = null
@@ -274,7 +274,7 @@ object BaseService {
if (TcpFastOpen.sendEnabled) cmd += "--fast-open" if (TcpFastOpen.sendEnabled) cmd += "--fast-open"
data.sslocalProcess = GuardedProcess(cmd).start() data.processes.start(cmd)
} }
fun createNotification(profileName: String): ServiceNotification fun createNotification(profileName: String): ServiceNotification
@@ -285,11 +285,7 @@ object BaseService {
else startService(Intent(this, javaClass)) else startService(Intent(this, javaClass))
} }
fun killProcesses() { fun killProcesses() = data.processes.killAll()
val data = data
data.sslocalProcess?.destroy()
data.sslocalProcess = null
}
fun stopRunner(stopService: Boolean, msg: String? = null) { fun stopRunner(stopService: Boolean, msg: String? = null) {
// channge the state // channge the state
@@ -31,31 +31,34 @@ import com.github.shadowsocks.utils.thread
import java.io.File import java.io.File
import java.io.IOException import java.io.IOException
import java.io.InputStream import java.io.InputStream
import java.util.concurrent.Semaphore import java.util.*
import java.util.concurrent.ArrayBlockingQueue
class GuardedProcess(private val cmd: List<String>) { class GuardedProcessPool {
companion object { companion object {
private const val TAG = "GuardedProcess" private const val TAG = "GuardedProcessPool"
private val dummy = IOException()
} }
private lateinit var guardThread: Thread private inner class Guard(private val cmd: List<String>, private val onRestartCallback: (() -> Unit)?) {
@Volatile val cmdName = File(cmd.first()).nameWithoutExtension
private var isDestroyed = false val excQueue = ArrayBlockingQueue<IOException>(1) // ArrayBlockingQueue doesn't want null
@Volatile private var pushed = false
private lateinit var process: Process
private val name = File(cmd.first()).nameWithoutExtension
private fun streamLogger(input: InputStream, logger: (String, String) -> Int) = thread("StreamLogger-$name") { private fun streamLogger(input: InputStream, logger: (String, String) -> Int) =
try { thread("StreamLogger-$cmdName") {
input.bufferedReader().useLines { it.forEach { logger(TAG, it) } } try {
} catch (_: IOException) { } // ignore input.bufferedReader().useLines { it.forEach { logger(TAG, it) } }
} } catch (_: IOException) { } // ignore
}
private fun pushException(ioException: IOException?) {
if (pushed) return
excQueue.put(ioException ?: dummy)
pushed = true
}
fun start(onRestartCallback: (() -> Unit)? = null): GuardedProcess { fun looper() {
val semaphore = Semaphore(1) var process: Process? = null
semaphore.acquire()
var ioException: IOException? = null
guardThread = thread("GuardThread-$name") {
try { try {
var callback: (() -> Unit)? = null var callback: (() -> Unit)? = null
while (!isDestroyed) { while (!isDestroyed) {
@@ -72,44 +75,54 @@ class GuardedProcess(private val cmd: List<String>) {
if (callback == null) callback = onRestartCallback else callback() if (callback == null) callback = onRestartCallback else callback()
semaphore.release() pushException(null)
process.waitFor() process.waitFor()
synchronized(this) { synchronized(this) {
if (SystemClock.elapsedRealtime() - startTime < 1000) { if (SystemClock.elapsedRealtime() - startTime < 1000) {
Log.w(TAG, "process exit too fast, stop guard: " + Commandline.toString(cmd)) Log.w(TAG, "process exit too fast, stop guard: $cmdName")
isDestroyed = true isDestroyed = true
} }
} }
} }
} catch (_: InterruptedException) { } catch (_: InterruptedException) {
if (BuildConfig.DEBUG) Log.d(TAG, "thread interrupt, destroy process: " + Commandline.toString(cmd)) if (BuildConfig.DEBUG) Log.d(TAG, "thread interrupt, destroy process: $cmdName")
destroyProcess()
} catch (e: IOException) { } catch (e: IOException) {
ioException = e pushException(e)
} finally { } finally {
semaphore.release() if (process != null) {
if (Build.VERSION.SDK_INT < 24) @Suppress("DEPRECATION") {
JniHelper.sigtermCompat(process)
JniHelper.waitForCompat(process, 500)
}
process.destroy()
process.waitFor() // ensure the process is destroyed
}
pushException(null)
} }
} }
semaphore.acquire() }
if (ioException != null) throw ioException!!
private val guardThreads = HashSet<Thread>()
@Volatile
private var isDestroyed = false
fun start(cmd: List<String>, onRestartCallback: (() -> Unit)? = null): GuardedProcessPool {
val guard = Guard(cmd, onRestartCallback)
guardThreads.add(thread("GuardThread-${guard.cmdName}", block = guard::looper))
val ioException = guard.excQueue.take()
if (ioException !== dummy) throw ioException
return this return this
} }
fun destroy() { fun killAll() {
isDestroyed = true isDestroyed = true
guardThread.interrupt() guardThreads.forEach { it.interrupt() }
destroyProcess()
try { try {
guardThread.join() guardThreads.forEach { it.join() }
} catch (_: InterruptedException) { } } catch (_: InterruptedException) { }
}
private fun destroyProcess() { guardThreads.clear()
if (Build.VERSION.SDK_INT < 24) @Suppress("DEPRECATION") { isDestroyed = false
JniHelper.sigtermCompat(process)
JniHelper.waitForCompat(process, 500)
}
process.destroy()
} }
} }
@@ -28,19 +28,9 @@ import org.json.JSONArray
import org.json.JSONObject import org.json.JSONObject
import java.io.File import java.io.File
import java.net.Inet6Address import java.net.Inet6Address
import java.util.*
/**
* This object also uses WeakMap to simulate the effects of multi-inheritance, but more lightweight.
*/
object LocalDnsService { object LocalDnsService {
interface Interface : BaseService.Interface { interface Interface : BaseService.Interface {
var overtureProcess: GuardedProcess?
get() = overtureProcesses[this]
set(value) {
if (value == null) overtureProcesses.remove(this) else overtureProcesses[this] = value
}
override fun startNativeProcesses() { override fun startNativeProcesses() {
super.startNativeProcesses() super.startNativeProcesses()
val data = data val data = data
@@ -96,18 +86,10 @@ object LocalDnsService {
return file return file
} }
if (!profile.udpdns) overtureProcess = GuardedProcess(buildAdditionalArguments(arrayListOf( if (!profile.udpdns) data.processes.start(buildAdditionalArguments(arrayListOf(
File(app.applicationInfo.nativeLibraryDir, Executable.OVERTURE).absolutePath, File(app.applicationInfo.nativeLibraryDir, Executable.OVERTURE).absolutePath,
"-c", buildOvertureConfig("overture.conf") "-c", buildOvertureConfig("overture.conf")
))).start() )))
}
override fun killProcesses() {
super.killProcesses()
overtureProcess?.destroy()
overtureProcess = null
} }
} }
private val overtureProcesses = WeakHashMap<Interface, GuardedProcess>()
} }
@@ -40,18 +40,14 @@ class TransproxyService : Service(), LocalDnsService.Interface {
override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int = override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int =
super<LocalDnsService.Interface>.onStartCommand(intent, flags, startId) super<LocalDnsService.Interface>.onStartCommand(intent, flags, startId)
private var sstunnelProcess: GuardedProcess? = null
private var redsocksProcess: GuardedProcess? = null
private fun startDNSTunnel() { private fun startDNSTunnel() {
val cmd = arrayListOf(File(applicationInfo.nativeLibraryDir, Executable.SS_TUNNEL).absolutePath, data.processes.start(listOf(File(applicationInfo.nativeLibraryDir, Executable.SS_TUNNEL).absolutePath,
"-t", "10", "-t", "10",
"-b", "127.0.0.1", "-b", "127.0.0.1",
"-u", "-u",
"-l", DataStore.portLocalDns.toString(), // ss-tunnel listens on the same port as overture "-l", DataStore.portLocalDns.toString(), // ss-tunnel listens on the same port as overture
"-L", data.profile!!.remoteDns.split(",").first().trim() + ":53", "-L", data.profile!!.remoteDns.split(",").first().trim() + ":53",
"-c", data.shadowsocksConfigFile!!.absolutePath) // config is already built by BaseService.Interface "-c", data.shadowsocksConfigFile!!.absolutePath)) // config is already built by BaseService.Interface
sstunnelProcess = GuardedProcess(cmd).start()
} }
private fun startRedsocksDaemon() { private fun startRedsocksDaemon() {
@@ -70,10 +66,8 @@ redsocks {
type = socks5; type = socks5;
} }
""") """)
redsocksProcess = GuardedProcess(arrayListOf( data.processes.start(listOf(
File(applicationInfo.nativeLibraryDir, Executable.REDSOCKS).absolutePath, File(applicationInfo.nativeLibraryDir, Executable.REDSOCKS).absolutePath, "-c", "redsocks.conf"))
"-c", "redsocks.conf")
).start()
} }
override fun startNativeProcesses() { override fun startNativeProcesses() {
@@ -81,12 +75,4 @@ redsocks {
super.startNativeProcesses() super.startNativeProcesses()
if (data.profile!!.udpdns) startDNSTunnel() if (data.profile!!.udpdns) startDNSTunnel()
} }
override fun killProcesses() {
super.killProcesses()
sstunnelProcess?.destroy()
sstunnelProcess = null
redsocksProcess?.destroy()
redsocksProcess = null
}
} }
@@ -116,7 +116,6 @@ class VpnService : BaseVpnService(), LocalDnsService.Interface {
private var conn: ParcelFileDescriptor? = null private var conn: ParcelFileDescriptor? = null
private var worker: ProtectWorker? = null private var worker: ProtectWorker? = null
private var tun2socksProcess: GuardedProcess? = null
private var underlyingNetwork: Network? = null private var underlyingNetwork: Network? = null
@TargetApi(28) @TargetApi(28)
set(value) { set(value) {
@@ -155,8 +154,6 @@ class VpnService : BaseVpnService(), LocalDnsService.Interface {
worker?.stopThread() worker?.stopThread()
worker = null worker = null
super.killProcesses() super.killProcesses()
tun2socksProcess?.destroy()
tun2socksProcess = null
conn?.close() conn?.close()
conn = null conn = null
} }
@@ -256,7 +253,7 @@ class VpnService : BaseVpnService(), LocalDnsService.Interface {
cmd += "--dnsgw" cmd += "--dnsgw"
cmd += "127.0.0.1:${DataStore.portLocalDns}" cmd += "127.0.0.1:${DataStore.portLocalDns}"
} }
tun2socksProcess = GuardedProcess(cmd).start { sendFd(fd) } data.processes.start(cmd) { sendFd(fd) }
return fd return fd
} }
-10
View File
@@ -1,15 +1,5 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<resources> <resources>
<style name="Theme.Translucent" parent="Theme.AppCompat.Dialog">
<item name="android:windowBackground">@android:color/transparent</item>
<item name="android:windowFrame">@null</item>
<item name="android:windowContentOverlay">@null</item>
<item name="android:windowAnimationStyle">@null</item>
<item name="android:backgroundDimEnabled">false</item>
<item name="android:windowIsTranslucent">true</item>
<item name="android:windowNoTitle">true</item>
<item name="android:windowCloseOnTouchOutside">false</item>
</style>
<style name="StyledScrollerTextAppearance" parent="@android:style/TextAppearance"> <style name="StyledScrollerTextAppearance" parent="@android:style/TextAppearance">
<item name="android:textSize">24sp</item> <item name="android:textSize">24sp</item>
<item name="android:textStyle">bold</item> <item name="android:textStyle">bold</item>
+5
View File
@@ -1,3 +1,8 @@
* 0.1.1:
* Rewritten in Kotlin;
* Fix assert not working;
* Min API 21;
* Update support library version to 27.1.1.
* 0.0.4: * 0.0.4:
* Enlarge text size of number pickers; * Enlarge text size of number pickers;
* Update support library version to 26.0.0. * Update support library version to 26.0.0.
+2 -2
View File
@@ -10,8 +10,8 @@ android {
defaultConfig { defaultConfig {
minSdkVersion rootProject.minSdkVersion minSdkVersion rootProject.minSdkVersion
targetSdkVersion rootProject.sdkVersion targetSdkVersion rootProject.sdkVersion
versionCode 5 versionCode 6
versionName "0.1.0" versionName "0.1.1"
testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner" testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
} }
+2 -1
View File
@@ -153,7 +153,8 @@ This corresponds to `com.github.shadowsocks.plugin.NativePluginProvider` in the
... ...
<provider android:name=".BinaryProvider" <provider android:name=".BinaryProvider"
android:exported="true" android:exported="true"
android:authorities="$FULLY_QUALIFIED_NAME_OF_YOUR_CONTENTPROVIDER"> android:authorities="$FULLY_QUALIFIED_NAME_OF_YOUR_CONTENTPROVIDER"
tools:ignore="ExportedContentProvider">
<intent-filter> <intent-filter>
<action android:name="com.github.shadowsocks.plugin.ACTION_NATIVE_PLUGIN"/> <action android:name="com.github.shadowsocks.plugin.ACTION_NATIVE_PLUGIN"/>
</intent-filter> </intent-filter>
+11
View File
@@ -11,4 +11,15 @@
<item name="preferenceCategory_marginBottom">8dp</item> <item name="preferenceCategory_marginBottom">8dp</item>
<item name="windowActionModeOverlay">true</item> <item name="windowActionModeOverlay">true</item>
</style> </style>
<style name="Theme.AppCompat.Translucent" parent="Theme.AppCompat.Dialog">
<item name="android:windowBackground">@android:color/transparent</item>
<item name="android:windowFrame">@null</item>
<item name="android:windowContentOverlay">@null</item>
<item name="android:windowAnimationStyle">@null</item>
<item name="android:backgroundDimEnabled">false</item>
<item name="android:windowIsTranslucent">true</item>
<item name="android:windowNoTitle">true</item>
<item name="android:windowCloseOnTouchOutside">false</item>
<item name="windowNoTitle">true</item>
</style>
</resources> </resources>