Fix flashback caused by process

This commit is contained in:
chen08209
2024-06-16 19:04:33 +08:00
parent 05abf2d56d
commit 90bb670442
19 changed files with 316 additions and 459 deletions

View File

@@ -82,13 +82,13 @@ type Delay struct {
}
type Process struct {
Id int64 `json:"id"`
Metadata constant.Metadata `json:"metadata"`
Id int64 `json:"id"`
Metadata *constant.Metadata `json:"metadata"`
}
type ProcessMapItem struct {
Id int64 `json:"id"`
Value *string `json:"value"`
Id int64 `json:"id"`
Value string `json:"value"`
}
type Now struct {
@@ -396,8 +396,6 @@ func applyConfig(isPatch bool) {
if isPatch {
patchConfig(cfg.General)
} else {
runtime.GC()
executor.Shutdown()
hub.UltraApplyConfig(cfg, true)
}
}

View File

@@ -13,6 +13,7 @@ const (
Now MessageType = "now"
Process MessageType = "process"
Request MessageType = "request"
Run MessageType = "run"
)
type Message struct {
@@ -20,11 +21,18 @@ type Message struct {
Data interface{} `json:"data"`
}
func (message *Message) Json() string {
data, _ := json.Marshal(message)
return string(data)
func (message *Message) Json() (string, error) {
data, err := json.Marshal(message)
return string(data), err
}
func SendMessage(message Message) {
SendToPort(*Port, message.Json())
if Port == nil {
return
}
s, err := message.Json()
if err != nil {
return
}
SendToPort(*Port, s)
}

View File

@@ -1,42 +0,0 @@
//go:build android
package platform
import "syscall"
var nullFd int
var maxFdCount int
func init() {
fd, err := syscall.Open("/dev/null", syscall.O_WRONLY, 0644)
if err != nil {
panic(err.Error())
}
nullFd = fd
var limit syscall.Rlimit
if err := syscall.Getrlimit(syscall.RLIMIT_NOFILE, &limit); err != nil {
maxFdCount = 1024
} else {
maxFdCount = int(limit.Cur)
}
maxFdCount = maxFdCount / 4 * 3
}
func ShouldBlockConnection() bool {
fd, err := syscall.Dup(nullFd)
if err != nil {
return true
}
_ = syscall.Close(fd)
if fd > maxFdCount {
return true
}
return false
}

View File

@@ -1,171 +0,0 @@
//go:build android
package platform
import (
"bufio"
"encoding/binary"
"encoding/hex"
"fmt"
"net"
"os"
"strconv"
"strings"
"unsafe"
)
var netIndexOfLocal = -1
var netIndexOfUid = -1
var nativeEndian binary.ByteOrder
func QuerySocketUidFromProcFs(source, _ net.Addr) int {
if netIndexOfLocal < 0 || netIndexOfUid < 0 {
return -1
}
network := source.Network()
if strings.HasSuffix(network, "4") || strings.HasSuffix(network, "6") {
network = network[:len(network)-1]
}
path := "/proc/net/" + network
var sIP net.IP
var sPort int
switch s := source.(type) {
case *net.TCPAddr:
sIP = s.IP
sPort = s.Port
case *net.UDPAddr:
sIP = s.IP
sPort = s.Port
default:
return -1
}
sIP = sIP.To16()
if sIP == nil {
return -1
}
uid := doQuery(path+"6", sIP, sPort)
if uid == -1 {
sIP = sIP.To4()
if sIP == nil {
return -1
}
uid = doQuery(path, sIP, sPort)
}
return uid
}
func doQuery(path string, sIP net.IP, sPort int) int {
file, err := os.Open(path)
if err != nil {
return -1
}
defer file.Close()
reader := bufio.NewReader(file)
var bytes [2]byte
binary.BigEndian.PutUint16(bytes[:], uint16(sPort))
local := fmt.Sprintf("%s:%s", hex.EncodeToString(nativeEndianIP(sIP)), hex.EncodeToString(bytes[:]))
for {
row, _, err := reader.ReadLine()
if err != nil {
return -1
}
fields := strings.Fields(string(row))
if len(fields) <= netIndexOfLocal || len(fields) <= netIndexOfUid {
continue
}
if strings.EqualFold(local, fields[netIndexOfLocal]) {
uid, err := strconv.Atoi(fields[netIndexOfUid])
if err != nil {
return -1
}
return uid
}
}
}
func nativeEndianIP(ip net.IP) []byte {
result := make([]byte, len(ip))
for i := 0; i < len(ip); i += 4 {
value := binary.BigEndian.Uint32(ip[i:])
nativeEndian.PutUint32(result[i:], value)
}
return result
}
func init() {
file, err := os.Open("/proc/net/tcp")
if err != nil {
return
}
defer file.Close()
reader := bufio.NewReader(file)
header, _, err := reader.ReadLine()
if err != nil {
return
}
columns := strings.Fields(string(header))
var txQueue, rxQueue, tr, tmWhen bool
for idx, col := range columns {
offset := 0
if txQueue && rxQueue {
offset--
}
if tr && tmWhen {
offset--
}
switch col {
case "tx_queue":
txQueue = true
case "rx_queue":
rxQueue = true
case "tr":
tr = true
case "tm->when":
tmWhen = true
case "local_address":
netIndexOfLocal = idx + offset
case "uid":
netIndexOfUid = idx + offset
}
}
}
func init() {
var x uint32 = 0x01020304
if *(*byte)(unsafe.Pointer(&x)) == 0x01 {
nativeEndian = binary.BigEndian
} else {
nativeEndian = binary.LittleEndian
}
}

View File

@@ -9,16 +9,30 @@ import (
"errors"
"github.com/metacubex/mihomo/component/process"
"github.com/metacubex/mihomo/constant"
"github.com/metacubex/mihomo/log"
"sync"
"sync/atomic"
"time"
)
var (
counter int64
)
type ProcessMap struct {
m sync.Map
}
var processMap = make(map[int64]*string)
func (cm *ProcessMap) Store(key int64, value string) {
cm.m.Store(key, value)
}
func (cm *ProcessMap) Load(key int64) (string, bool) {
value, ok := cm.m.Load(key)
if !ok || value == nil {
return "", false
}
return value.(string), true
}
var counter int64 = 0
var processMap ProcessMap
func init() {
process.DefaultPackageNameResolver = func(metadata *constant.Metadata) (string, error) {
@@ -29,31 +43,24 @@ func init() {
timeout := time.After(200 * time.Millisecond)
message := &bridge.Message{
bridge.SendMessage(bridge.Message{
Type: bridge.Process,
Data: Process{
Id: id,
Metadata: *metadata,
Metadata: metadata,
},
}
bridge.SendMessage(*message)
})
for {
select {
case <-timeout:
return "", errors.New("package resolver timeout")
default:
value, exists := processMap[counter]
value, exists := processMap.Load(id)
if exists {
if value != nil {
log.Infoln("[PKG] %s --> %s by [%s]", metadata.SourceAddress(), metadata.RemoteAddress(), *value)
return *value, nil
} else {
return "", process.ErrInvalidNetwork
}
return value, nil
}
time.Sleep(10 * time.Millisecond)
time.Sleep(20 * time.Millisecond)
}
}
}
@@ -61,12 +68,15 @@ func init() {
//export setProcessMap
func setProcessMap(s *C.char) {
if s == nil {
return
}
go func() {
paramsString := C.GoString(s)
var processMapItem = &ProcessMapItem{}
err := json.Unmarshal([]byte(paramsString), processMapItem)
if err == nil {
processMap[processMapItem.Id] = processMapItem.Value
processMap.Store(processMapItem.Id, processMapItem.Value)
}
}()
}

View File

@@ -4,13 +4,10 @@ package main
import "C"
import (
"core/platform"
t "core/tun"
"errors"
"github.com/metacubex/mihomo/component/dialer"
"github.com/metacubex/mihomo/log"
"golang.org/x/sync/semaphore"
"strconv"
"sync"
"syscall"
"time"
@@ -18,16 +15,11 @@ import (
var tunLock sync.Mutex
var tun *t.Tun
var runTime *time.Time
//export startTUN
func startTUN(fd C.int) {
tunLock.Lock()
now := time.Now()
runTime = &now
go func() {
tunLock.Lock()
defer tunLock.Unlock()
if tun != nil {
@@ -43,6 +35,8 @@ func startTUN(fd C.int) {
closer, err := t.Start(f, gateway, portal, dns)
applyConfig(true)
if err != nil {
log.Errorln("startTUN error: %v", err)
tempTun.Close()
@@ -51,30 +45,18 @@ func startTUN(fd C.int) {
tempTun.Closer = closer
tun = tempTun
applyConfig(true)
}()
}
//export getRunTime
func getRunTime() *C.char {
if runTime == nil {
return C.CString("")
}
return C.CString(strconv.FormatInt(runTime.UnixMilli(), 10))
}
//export stopTun
func stopTun() {
tunLock.Lock()
runTime = nil
go func() {
tunLock.Lock()
defer tunLock.Unlock()
if tun != nil {
tun.Close()
applyConfig(true)
tun = nil
}
}()
@@ -82,9 +64,6 @@ func stopTun() {
func init() {
dialer.DefaultSocketHook = func(network, address string, conn syscall.RawConn) error {
if platform.ShouldBlockConnection() {
return errors.New("blocked")
}
return conn.Control(func(fd uintptr) {
if tun != nil {
tun.MarkSocket(int(fd))