use start process instead of jni

This commit is contained in:
Kr328 committed 2019-11-19 09:23:54 +08:00
1 parent cf4e1c5b95
commit 21b9d0fa27
5 files changed
+151 -40

No files matched your search

+10 -5
View File
@@ -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
}
+50
View File
@@ -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()
}
+29 -9
View File
@@ -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()
}
+21 -3
View File
@@ -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
}
+41 -23
View File
@@ -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
}