Files
MWClash/core/tun.go

119 lines
1.8 KiB
Go
Raw Normal View History

2024-04-30 23:38:49 +08:00
//go:build android
package main
import "C"
import (
"core/platform"
2024-04-30 23:38:49 +08:00
t "core/tun"
"errors"
2024-04-30 23:38:49 +08:00
"github.com/metacubex/mihomo/component/dialer"
"github.com/metacubex/mihomo/log"
"golang.org/x/sync/semaphore"
"sync"
"syscall"
"time"
)
var tunLock sync.Mutex
var tun *t.Tun
type FdMap struct {
m sync.Map
}
func (cm *FdMap) Store(key int) {
cm.m.Store(key, nil)
}
func (cm *FdMap) Load(key int) bool {
_, ok := cm.m.Load(key)
if !ok {
return false
}
return true
}
var fdMap FdMap
2024-04-30 23:38:49 +08:00
//export startTUN
2024-06-06 22:04:29 +08:00
func startTUN(fd C.int) {
go func() {
2024-06-16 19:04:33 +08:00
tunLock.Lock()
2024-06-06 22:04:29 +08:00
defer tunLock.Unlock()
2024-04-30 23:38:49 +08:00
2024-06-06 22:04:29 +08:00
if tun != nil {
tun.Close()
tun = nil
}
f := int(fd)
gateway := "172.16.0.1/30"
portal := "172.16.0.2"
dns := "0.0.0.0"
2024-04-30 23:38:49 +08:00
2024-06-06 22:04:29 +08:00
tempTun := &t.Tun{Closed: false, Limit: semaphore.NewWeighted(4)}
2024-04-30 23:38:49 +08:00
2024-06-06 22:04:29 +08:00
closer, err := t.Start(f, gateway, portal, dns)
2024-04-30 23:38:49 +08:00
2024-06-06 22:04:29 +08:00
if err != nil {
log.Errorln("startTUN error: %v", err)
tempTun.Close()
}
2024-04-30 23:38:49 +08:00
2024-06-06 22:04:29 +08:00
tempTun.Closer = closer
2024-04-30 23:38:49 +08:00
2024-06-06 22:04:29 +08:00
tun = tempTun
}()
2024-04-30 23:38:49 +08:00
}
//export stopTun
func stopTun() {
2024-06-06 22:04:29 +08:00
go func() {
2024-06-16 19:04:33 +08:00
tunLock.Lock()
2024-06-06 22:04:29 +08:00
defer tunLock.Unlock()
if tun != nil {
tun.Close()
tun = nil
}
}()
2024-04-30 23:38:49 +08:00
}
var errBlocked = errors.New("blocked")
//export setFdMap
func setFdMap(fd C.long) {
fdInt := int(fd)
go func() {
fdMap.Store(fdInt)
}()
}
2024-04-30 23:38:49 +08:00
func init() {
dialer.DefaultSocketHook = func(network, address string, conn syscall.RawConn) error {
if platform.ShouldBlockConnection() {
return errBlocked
}
2024-04-30 23:38:49 +08:00
return conn.Control(func(fd uintptr) {
fdInt := int(fd)
timeout := time.After(100 * time.Millisecond)
2024-04-30 23:38:49 +08:00
if tun != nil {
tun.MarkSocket(fdInt)
}
for {
select {
case <-timeout:
return
default:
exists := fdMap.Load(fdInt)
if exists {
return
}
time.Sleep(10 * time.Millisecond)
}
2024-04-30 23:38:49 +08:00
}
2024-04-30 23:38:49 +08:00
})
}
}