tun device work fine

This commit is contained in:
Kr328 committed 2019-11-19 14:36:17 +08:00
1 parent 6cecb23dd8
commit e8a3335e21
11 files changed
+165 -50

No files matched your search

+3 -3
View File
@@ -23,9 +23,9 @@ func main() {
} else {
return
}
if err := server.Start(os.Args[1]) ; err != nil {
fmt.Println("[CONTROLLER] ERROR={"+ err.Error() +"}")
if err := server.Start(os.Args[1]); err != nil {
fmt.Println("[CONTROLLER] ERROR={" + err.Error() + "}")
return
}
+6 -4
View File
@@ -52,10 +52,12 @@ func LoadDefault() {
Proxies: map[string]constant.Proxy{},
}
global, _ := adapters.NewSelector("GLOBAL", make([]constant.Proxy, 0))
reject := adapters.NewProxy(adapters.NewReject())
direct := adapters.NewProxy(adapters.NewDirect())
global, _ := adapters.NewSelector("GLOBAL", []constant.Proxy{direct})
defaultC.Proxies["DIRECT"] = adapters.NewProxy(adapters.NewDirect())
defaultC.Proxies["REJECT"] = adapters.NewProxy(adapters.NewReject())
defaultC.Proxies["DIRECT"] = direct
defaultC.Proxies["REJECT"] = reject
defaultC.Proxies["GLOBAL"] = adapters.NewProxy(global)
executor.ApplyConfig(defaultC, true)
@@ -67,7 +69,7 @@ func LoadFromFile(path string) error {
if err != nil {
return err
}
executor.ApplyConfig(cfg, true)
return nil
}
+4
View File
@@ -12,6 +12,8 @@ import (
func handleProfileDefault(client *net.UnixConn) {
profile.LoadDefault()
log.Infoln("Profile default loaded")
client.Close()
}
@@ -46,5 +48,7 @@ func handleProfileReload(client *net.UnixConn) {
binary.Write(client, binary.BigEndian, uint32(0))
}
log.Infoln("Profile " + payload.Path + " loaded")
client.Close()
}
+10 -6
View File
@@ -8,17 +8,21 @@ import (
)
const (
commandPing = 0
commandTunStart = 1
commandTunStop = 2
commandPing = 0
commandTunStart = 1
commandTunStop = 2
commandProfileDefault = 3
commandProfileReload = 4
)
var handlers map[int]func(*net.UnixConn) = make(map[int]func(*net.UnixConn))
func init() {
handlers[commandPing] = handlePing // ping.go
handlers[commandTunStart] = handleTunStart // tun.go
handlers[commandTunStop] = handleTunStop // tun.go
handlers[commandPing] = handlePing // ping.go
handlers[commandTunStart] = handleTunStart // tun.go
handlers[commandTunStop] = handleTunStop // tun.go
handlers[commandProfileDefault] = handleProfileDefault // profile.go
handlers[commandProfileReload] = handleProfileReload // profile.go
}
// Start local control server
+7 -4
View File
@@ -15,9 +15,8 @@ const (
func handleTunStart(client *net.UnixConn) {
buffer := make([]byte, unix.CmsgLen(4*1))
data := make([]byte, 8)
_, noob, _, _, err := client.ReadMsgUnix(data, buffer)
_, noob, _, _, err := client.ReadMsgUnix(nil, buffer)
if err != nil {
log.Warnln("Read tun socket failure, %s", err.Error())
return
@@ -35,9 +34,13 @@ func handleTunStart(client *net.UnixConn) {
return
}
mtu := binary.BigEndian.Uint32(data)
var mtu uint32
var end uint32
if binary.BigEndian.Uint32(data[4:]) != tunCommandEnd {
binary.Read(client, binary.BigEndian, &mtu)
binary.Read(client, binary.BigEndian, &end)
if end != tunCommandEnd {
log.Warnln("Invalid tun command end")
return
}
@@ -1,9 +1,108 @@
package com.github.kr328.clash.core
import android.content.Context
import java.io.File
import android.net.LocalSocket
import android.net.LocalSocketAddress
import android.net.Uri
import android.os.ParcelFileDescriptor
import android.util.Log
import org.json.JSONObject
import java.io.*
class Clash(context: Context, clashDir: File, controllerPath: File) :
class Clash(private val context: Context, clashDir: File, private val controllerPath: File) :
ClashProcess(context, clashDir, controllerPath) {
companion object {
const val COMMAND_PING = 0
const val COMMAND_TUN_START = 1
const val COMMAND_TUN_STOP = 2
const val COMMAND_PROFILE_DEFAULT = 3
const val COMMAND_PROFILE_RELOAD = 4
const val PING_REPLY = 233
}
private val cacheFile = context.cacheDir.resolve("config.yaml")
fun ping(): Boolean {
try {
return runControl(COMMAND_PING) {_, input, _ ->
input.readInt() == PING_REPLY
}
}
catch (e: IOException) {
Log.w(TAG, "Clash ping failure", e)
}
return false
}
@Throws(IOException::class)
@Synchronized
fun loadProfile(url: Uri) {
synchronized(cacheFile) {
context.contentResolver.openInputStream(url)?.use {
it.copyTo(FileOutputStream(cacheFile))
}
runControl(COMMAND_PROFILE_RELOAD) {_, input, output ->
output.writeString(JSONObject().apply {
put("path", cacheFile.absolutePath)
}.toString())
val result = input.readString()
if (result.isNotEmpty()) {
throw IOException(JSONObject(result).getString("error"))
}
}
}
}
@Throws(IOException::class)
fun startTunDevice(fd: FileDescriptor, mtu: Int) {
runControl(COMMAND_TUN_START) { socket, _, output ->
socket.setFileDescriptorsForSend(arrayOf(fd))
socket.outputStream.write(0)
socket.outputStream.flush()
output.writeInt(mtu)
output.writeInt(0x243)
}
}
private fun <R>runControl(command: Int, block: (LocalSocket, DataInputStream, DataOutputStream) -> R): R {
val socket = LocalSocket()
socket.connect(LocalSocketAddress(controllerPath.absolutePath, LocalSocketAddress.Namespace.FILESYSTEM))
val input = DataInputStream(socket.inputStream)
val output = DataOutputStream(socket.outputStream)
output.writeInt(command)
val result = block(socket, input, output)
try {
input.close()
output.close()
socket.close()
}
catch (ignore: IOException) {
}
return result
}
private fun DataOutputStream.writeString(string: String) {
this.writeInt(string.length)
this.writeBytes(string)
}
private fun DataInputStream.readString(): String {
val len = this.readInt()
val buffer = ByteArray(len)
this.read(buffer)
return String(buffer)
}
}
@@ -5,9 +5,9 @@ import android.util.Log
import java.io.File
import java.io.IOException
abstract class ClashProcess(context: Context, clashDir: File, private val controllerPath: File) {
abstract class ClashProcess(context: Context, clashDir: File, controllerPath: File) {
companion object {
private const val TAG = "ClashForAndroid"
const val TAG = "ClashForAndroid"
private const val CLASH_COMMAND = "\"{CLASH}\" \"{CONTROLLER}\" 2>&1"
private val PID_PATTERN = Regex("PID=(\\d+)")
private const val CONTROLLER_STATUS_PREFIX = "[CONTROLLER]"
@@ -57,6 +57,8 @@ abstract class ClashProcess(context: Context, clashDir: File, private val contro
if ( error != null )
throw IOException("Controller: $error")
break
}
}