use start process instead of jni
This commit is contained in:
5 files changed
+151
-40
No files matched your search
@@ -9,25 +9,30 @@ import (
|
||||
"github.com/Dreamacro/clash/constant"
|
||||
|
||||
"github.com/kr328/clash/profile"
|
||||
"github.com/kr328/clash/server"
|
||||
)
|
||||
|
||||
func main() int {
|
||||
if len(os.Args) != 1 {
|
||||
func main() {
|
||||
if len(os.Args) != 2 {
|
||||
fmt.Println("Invalid argument")
|
||||
return -1
|
||||
return
|
||||
}
|
||||
|
||||
fmt.Println("[CLASH] PID =", int(os.Getpid()))
|
||||
|
||||
if cwd, err := os.Getwd(); err == nil {
|
||||
constant.SetHomeDir(cwd)
|
||||
} else {
|
||||
return -1
|
||||
return
|
||||
}
|
||||
|
||||
profile.LoadDefault()
|
||||
|
||||
server.Start(os.Args[1])
|
||||
|
||||
sigCh := make(chan os.Signal, 1)
|
||||
signal.Notify(sigCh, syscall.SIGINT, syscall.SIGTERM)
|
||||
<-sigCh
|
||||
|
||||
return 0
|
||||
return
|
||||
}
|
||||
@@ -0,0 +1,50 @@
|
||||
package server
|
||||
|
||||
import (
|
||||
"encoding/binary"
|
||||
"encoding/json"
|
||||
"net"
|
||||
|
||||
"github.com/Dreamacro/clash/log"
|
||||
"github.com/kr328/clash/profile"
|
||||
)
|
||||
|
||||
func handleProfileDefault(client *net.UnixConn) {
|
||||
profile.LoadDefault()
|
||||
|
||||
client.Close()
|
||||
}
|
||||
|
||||
func handleProfileReload(client *net.UnixConn) {
|
||||
packet, err := readCommandPacket(client)
|
||||
if err != nil {
|
||||
log.Warnln("Read profile payload failure, %s", err.Error())
|
||||
}
|
||||
|
||||
var payload struct {
|
||||
Path string `json:"path"`
|
||||
}
|
||||
|
||||
err = json.Unmarshal(packet, &payload)
|
||||
if err != nil {
|
||||
log.Warnln("Parse profile payload failure, %s", err.Error())
|
||||
}
|
||||
|
||||
err = profile.LoadFromFile(payload.Path)
|
||||
|
||||
if err != nil {
|
||||
var reply struct {
|
||||
Err string `json:"error"`
|
||||
}
|
||||
|
||||
reply.Err = err.Error()
|
||||
|
||||
buffer, _ := json.Marshal(&reply)
|
||||
|
||||
writeCommandPacket(client, buffer)
|
||||
} else {
|
||||
binary.Write(client, binary.BigEndian, uint32(0))
|
||||
}
|
||||
|
||||
client.Close()
|
||||
}
|
||||
@@ -1,36 +1,56 @@
|
||||
package server
|
||||
|
||||
import (
|
||||
"encoding/binary"
|
||||
"net"
|
||||
|
||||
"golang.org/x/sys/unix"
|
||||
|
||||
"github.com/Dreamacro/clash/log"
|
||||
|
||||
"github.com/kr328/clash/tun"
|
||||
"golang.org/x/sys/unix"
|
||||
)
|
||||
|
||||
const (
|
||||
tunCommandEnd = 0x243
|
||||
)
|
||||
|
||||
func handleTunStart(client *net.UnixConn) {
|
||||
buffer, err := readCommandPackage(client)
|
||||
buffer := make([]byte, unix.CmsgLen(4*1))
|
||||
data := make([]byte, 8)
|
||||
|
||||
_, noob, _, _, err := client.ReadMsgUnix(data, buffer)
|
||||
if err != nil {
|
||||
log.Warnln("Read packet from unix socket failure %s", err.Error())
|
||||
log.Warnln("Read tun socket failure, %s", err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
msg, err := unix.ParseSocketControlMessage(buffer)
|
||||
msg, err := unix.ParseSocketControlMessage(buffer[:noob])
|
||||
if err != nil || len(msg) != 1 {
|
||||
log.Warnln("Parse control package failure %s", err.Error())
|
||||
log.Warnln("Parse tun socket failure, %s", err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
fds, err := unix.ParseUnixRights(&msg[0])
|
||||
if err != nil {
|
||||
log.Warnln("Parse control package failure %s", err.Error())
|
||||
log.Warnln("Parse tun socket failure, %s", err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
tun.NewTunProxy(fds[0])
|
||||
mtu := binary.BigEndian.Uint32(data)
|
||||
|
||||
if binary.BigEndian.Uint32(data[4:]) != tunCommandEnd {
|
||||
log.Warnln("Invalid tun command end")
|
||||
return
|
||||
}
|
||||
|
||||
tun.StartTunProxy(fds[0], int(mtu))
|
||||
}
|
||||
|
||||
func handleTunStop(client *net.UnixConn) {
|
||||
buf, _ := readCommandPacket(client)
|
||||
|
||||
if tunCommandEnd != binary.BigEndian.Uint32(buf) {
|
||||
log.Warnln("Invalid tun command end")
|
||||
}
|
||||
|
||||
tun.StopTunProxy()
|
||||
}
|
||||
@@ -2,12 +2,13 @@ package server
|
||||
|
||||
import (
|
||||
"encoding/binary"
|
||||
"errors"
|
||||
"io"
|
||||
"net"
|
||||
)
|
||||
|
||||
func readCommandPackage(client *net.UnixConn) ([]byte, error) {
|
||||
var packageSize int32
|
||||
func readCommandPacket(client *net.UnixConn) ([]byte, error) {
|
||||
var packageSize uint32
|
||||
|
||||
if err := binary.Read(client, binary.BigEndian, &packageSize); err != nil {
|
||||
return nil, err
|
||||
@@ -15,9 +16,26 @@ func readCommandPackage(client *net.UnixConn) ([]byte, error) {
|
||||
|
||||
buffer := make([]byte, packageSize)
|
||||
|
||||
if readSize, err := io.ReadFull(client, buffer); err != nil || int32(readSize) != packageSize {
|
||||
if readSize, err := io.ReadFull(client, buffer); err != nil || uint32(readSize) != packageSize {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return buffer, nil
|
||||
}
|
||||
|
||||
func writeCommandPacket(client *net.UnixConn, buffer []byte) error {
|
||||
if err := binary.Write(client, binary.BigEndian, uint32(len(buffer))); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
n, err := client.Write(buffer)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if n != len(buffer) {
|
||||
return errors.New("Write invalid data size")
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
@@ -10,7 +10,7 @@ import (
|
||||
"github.com/Dreamacro/clash/component/socks5"
|
||||
C "github.com/Dreamacro/clash/constant"
|
||||
"github.com/Dreamacro/clash/log"
|
||||
"github.com/Dreamacro/clash/tunnel"
|
||||
T "github.com/Dreamacro/clash/tunnel"
|
||||
|
||||
"encoding/binary"
|
||||
|
||||
@@ -24,25 +24,44 @@ import (
|
||||
"github.com/google/netstack/waiter"
|
||||
)
|
||||
|
||||
var (
|
||||
tun = tunnel.Instance()
|
||||
ipstack *stack.Stack
|
||||
)
|
||||
|
||||
// TunAdapter tun device handler
|
||||
type TunAdapter struct {
|
||||
type tun struct {
|
||||
device *TunDevice
|
||||
ipstack *stack.Stack
|
||||
}
|
||||
|
||||
// NewTunProxy create TunProxy under Linux OS.
|
||||
func NewTunProxy(fd int, mtu int) (*TunAdapter, error) {
|
||||
var (
|
||||
tunnel = T.Instance()
|
||||
instance *tun
|
||||
)
|
||||
|
||||
// StartTunProxy - start
|
||||
func StartTunProxy(fd, mtu int) error {
|
||||
if instance != nil {
|
||||
instance.close()
|
||||
}
|
||||
|
||||
var err error
|
||||
instance, err = newTunProxy(fd, mtu)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// StopTunProxy - stop
|
||||
func StopTunProxy() {
|
||||
instance.close()
|
||||
instance = nil
|
||||
}
|
||||
|
||||
func newTunProxy(fd int, mtu int) (*tun, error) {
|
||||
tundev, err := OpenTunDevice(fd, mtu)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("Can't open tun: %v", err)
|
||||
}
|
||||
|
||||
ipstack = stack.New(stack.Options{
|
||||
ipstack := stack.New(stack.Options{
|
||||
NetworkProtocols: []stack.NetworkProtocol{ipv4.NewProtocol(), ipv6.NewProtocol()},
|
||||
TransportProtocols: []stack.TransportProtocol{tcp.NewProtocol(), udp.NewProtocol()},
|
||||
})
|
||||
@@ -76,7 +95,7 @@ func NewTunProxy(fd int, mtu int) (*TunAdapter, error) {
|
||||
|
||||
conn := gonet.NewConn(&wq, ep)
|
||||
target := getAddr(ep.Info().(*tcp.EndpointInfo).ID)
|
||||
tun.Add(adapters.NewSocket(target, conn, C.REDIR, C.TCP))
|
||||
tunnel.Add(adapters.NewSocket(target, conn, C.REDIR, C.TCP))
|
||||
|
||||
})
|
||||
ipstack.SetTransportProtocolHandler(tcp.ProtocolNumber, tcpFwd.HandlePacket)
|
||||
@@ -91,26 +110,25 @@ func NewTunProxy(fd int, mtu int) (*TunAdapter, error) {
|
||||
|
||||
conn := gonet.NewConn(&wq, ep)
|
||||
target := getAddr(ep.Info().(*stack.TransportEndpointInfo).ID)
|
||||
tun.Add(adapters.NewSocket(target, conn, C.REDIR, C.UDP))
|
||||
tunnel.Add(adapters.NewSocket(target, conn, C.REDIR, C.UDP))
|
||||
|
||||
})
|
||||
ipstack.SetTransportProtocolHandler(udp.ProtocolNumber, udpFwd.HandlePacket)
|
||||
|
||||
tl := &TunAdapter{
|
||||
tl := &tun{
|
||||
device: tundev,
|
||||
ipstack: ipstack,
|
||||
}
|
||||
|
||||
android.Info("Tun device opened")
|
||||
log.Infoln("Tun device opened")
|
||||
|
||||
return tl, nil
|
||||
}
|
||||
|
||||
// Close close the TunAdapter
|
||||
func (t *TunAdapter) Close() {
|
||||
func (t *tun) close() {
|
||||
t.device.Close()
|
||||
ipstack.Close()
|
||||
t.ipstack.Close()
|
||||
}
|
||||
|
||||
func getAddr(id stack.TransportEndpointID) socks5.Addr {
|
||||
@@ -126,11 +144,11 @@ func getAddr(id stack.TransportEndpointID) socks5.Addr {
|
||||
copy(addr[1:1+net.IPv4len], []byte(ipv4))
|
||||
addr[1+net.IPv4len], addr[1+net.IPv4len+1] = port[0], port[1]
|
||||
return addr
|
||||
} else {
|
||||
addr := make([]byte, 1+net.IPv6len+2)
|
||||
addr[0] = socks5.AtypIPv6
|
||||
copy(addr[1:1+net.IPv6len], []byte(id.LocalAddress))
|
||||
addr[1+net.IPv6len], addr[1+net.IPv6len+1] = port[0], port[1]
|
||||
return addr
|
||||
}
|
||||
|
||||
addr := make([]byte, 1+net.IPv6len+2)
|
||||
addr[0] = socks5.AtypIPv6
|
||||
copy(addr[1:1+net.IPv6len], []byte(id.LocalAddress))
|
||||
addr[1+net.IPv6len], addr[1+net.IPv6len+1] = port[0], port[1]
|
||||
return addr
|
||||
}
|
||||
Reference in new issue
Block a user