Commit b4d003f0 authored by Mygod's avatar Mygod

Refine LocalSocketListener

parent 2e289597
......@@ -23,16 +23,18 @@ package com.github.shadowsocks.bg
import android.net.LocalServerSocket
import android.net.LocalSocket
import android.net.LocalSocketAddress
import android.system.Os
import android.system.OsConstants
import com.github.shadowsocks.utils.printLog
import java.io.File
import java.io.IOException
abstract class LocalSocketListener(protected val tag: String) : Thread(tag) {
init {
setUncaughtExceptionHandler { _, t -> printLog(t) }
abstract class LocalSocketListener(name: String, socketFile: File) : Thread(name), AutoCloseable {
private val localSocket = LocalSocket().apply {
socketFile.delete() // It's a must-have to close and reuse previous local socket.
bind(LocalSocketAddress(socketFile.absolutePath, LocalSocketAddress.Namespace.FILESYSTEM))
}
protected abstract val socketFile: File
private val serverSocket = LocalServerSocket(localSocket.fileDescriptor)
@Volatile
private var running = true
......@@ -40,29 +42,21 @@ abstract class LocalSocketListener(protected val tag: String) : Thread(tag) {
* Inherited class do not need to close input/output streams as they will be closed automatically.
*/
protected abstract fun accept(socket: LocalSocket)
final override fun run() {
socketFile.delete() // It's a must-have to close and reuse previous local socket.
LocalSocket().use { localSocket ->
val serverSocket = try {
localSocket.bind(LocalSocketAddress(socketFile.absolutePath, LocalSocketAddress.Namespace.FILESYSTEM))
LocalServerSocket(localSocket.fileDescriptor)
} catch (e: IOException) {
printLog(e)
return
}
final override fun run() = localSocket.use {
while (running) {
try {
serverSocket.accept()
serverSocket.accept().use { accept(it) }
} catch (e: IOException) {
printLog(e)
if (running) printLog(e)
continue
}?.use(this::accept)
}
}
}
fun stopThread() {
override fun close() {
running = false
interrupt()
// see also: https://issuetracker.google.com/issues/36945762#comment15
Os.shutdown(localSocket.fileDescriptor, OsConstants.SHUT_RDWR)
join()
}
}
......@@ -23,18 +23,14 @@ package com.github.shadowsocks.bg
import android.net.LocalSocket
import android.os.SystemClock
import com.github.shadowsocks.aidl.TrafficStats
import com.github.shadowsocks.utils.printLog
import java.io.File
import java.io.IOException
import java.nio.ByteBuffer
import java.nio.ByteOrder
class TrafficMonitor(statFile: File) : AutoCloseable {
private val thread = object : LocalSocketListener("TrafficMonitor") {
override val socketFile = statFile
private val thread = object : LocalSocketListener("TrafficMonitor", statFile) {
override fun accept(socket: LocalSocket) {
try {
val buffer = ByteArray(16)
if (socket.inputStream.read(buffer) != 16) throw IOException("Unexpected traffic stat length")
val stat = ByteBuffer.wrap(buffer).order(ByteOrder.LITTLE_ENDIAN)
......@@ -48,16 +44,12 @@ class TrafficMonitor(statFile: File) : AutoCloseable {
current.rxTotal = rx
dirty = true
}
} catch (e: IOException) {
printLog(e)
}
}
}.apply { start() }
val current = TrafficStats()
var out = TrafficStats()
private var timestampLast = 0L
@Volatile
private var dirty = false
fun requestUpdate(): Pair<TrafficStats, Boolean> {
......@@ -87,5 +79,5 @@ class TrafficMonitor(statFile: File) : AutoCloseable {
return Pair(out, updated)
}
override fun close() = thread.stopThread()
override fun close() = thread.close()
}
......@@ -78,10 +78,9 @@ class VpnService : BaseVpnService(), LocalDnsService.Interface {
override fun close() = Os.close(fd)
}
private inner class ProtectWorker : LocalSocketListener("ShadowsocksVpnThread") {
override val socketFile: File = File(Core.deviceStorage.noBackupFilesDir, "protect_path")
override fun accept(socket: LocalSocket) = try {
private inner class ProtectWorker :
LocalSocketListener("ShadowsocksVpnThread", File(Core.deviceStorage.noBackupFilesDir, "protect_path")) {
override fun accept(socket: LocalSocket) {
socket.inputStream.read()
val fd = socket.ancillaryFileDescriptors!!.single()!!
CloseableFd(fd).use {
......@@ -96,8 +95,6 @@ class VpnService : BaseVpnService(), LocalDnsService.Interface {
} else protect(getInt.invoke(fd) as Int)
}) 0 else 1)
}
} catch (e: IOException) {
printLog(e)
}
}
inner class NullConnectionException : NullPointerException() {
......@@ -146,7 +143,7 @@ class VpnService : BaseVpnService(), LocalDnsService.Interface {
connectivity.unregisterNetworkCallback(defaultNetworkCallback)
listeningForDefaultNetwork = false
}
worker?.stopThread()
worker?.close()
worker = null
super.killProcesses()
conn?.close()
......@@ -164,9 +161,7 @@ class VpnService : BaseVpnService(), LocalDnsService.Interface {
}
override suspend fun startProcesses() {
val worker = ProtectWorker()
worker.start()
this.worker = worker
worker = ProtectWorker().apply { start() }
super.startProcesses()
......
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