Skip to content

Commit

Permalink
Merge branch 'MetaCubeX:Alpha' into Alpha
Browse files Browse the repository at this point in the history
  • Loading branch information
xishang0128 authored Aug 3, 2024
2 parents f3041c6 + e4646fc commit abb0689
Show file tree
Hide file tree
Showing 51 changed files with 1,206 additions and 344 deletions.
1 change: 1 addition & 0 deletions .github/workflows/build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -153,6 +153,7 @@ jobs:
echo "BUILDTIME=$(date)" >> $GITHUB_ENV
echo "CGO_ENABLED=0" >> $GITHUB_ENV
echo "BUILDTAG=-extldflags --static" >> $GITHUB_ENV
echo "GOTOOLCHAIN=local" >> $GITHUB_ENV
- name: Setup NDK
if: ${{ matrix.jobs.goos == 'android' }}
Expand Down
3 changes: 1 addition & 2 deletions Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ WORKDIR /mihomo
COPY bin/ bin/
RUN FILE_NAME=`sh file-name.sh` && echo $FILE_NAME && \
FILE_NAME=`ls bin/ | egrep "$FILE_NAME.gz"|awk NR==1` && echo $FILE_NAME && \
mv bin/$FILE_NAME mihomo.gz && gzip -d mihomo.gz && echo "$FILE_NAME" > /mihomo-config/test
mv bin/$FILE_NAME mihomo.gz && gzip -d mihomo.gz && chmod +x mihomo && echo "$FILE_NAME" > /mihomo-config/test
FROM alpine:latest
LABEL org.opencontainers.image.source="https://github.com/MetaCubeX/mihomo"

Expand All @@ -23,5 +23,4 @@ VOLUME ["/root/.config/mihomo/"]

COPY --from=builder /mihomo-config/ /root/.config/mihomo/
COPY --from=builder /mihomo/mihomo /mihomo
RUN chmod +x /mihomo
ENTRYPOINT [ "/mihomo" ]
2 changes: 2 additions & 0 deletions adapter/inbound/addition.go
Original file line number Diff line number Diff line change
Expand Up @@ -69,3 +69,5 @@ func WithDSCP(dscp uint8) Addition {
metadata.DSCP = dscp
}
}

func Placeholder(metadata *C.Metadata) {}
2 changes: 0 additions & 2 deletions adapter/outboundgroup/loadbalance.go
Original file line number Diff line number Diff line change
Expand Up @@ -205,7 +205,6 @@ func strategyStickySessions(url string) strategyFn {
proxy := proxies[nowIdx]
if proxy.AliveForTestUrl(url) {
if nowIdx != idx {
lruCache.Delete(key)
lruCache.Set(key, nowIdx)
}

Expand All @@ -215,7 +214,6 @@ func strategyStickySessions(url string) strategyFn {
}
}

lruCache.Delete(key)
lruCache.Set(key, 0)
return proxies[0]
}
Expand Down
2 changes: 1 addition & 1 deletion adapter/outboundgroup/parser.go
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,7 @@ func ParseProxyGroup(config map[string]any, proxyMap map[string]C.Proxy, provide
}

if groupOption.IncludeAllProviders {
groupOption.Use = append(groupOption.Use, AllProviders...)
groupOption.Use = AllProviders
}
if groupOption.IncludeAllProxies {
if groupOption.Filter != "" {
Expand Down
32 changes: 32 additions & 0 deletions common/lru/lrucache.go
Original file line number Diff line number Diff line change
Expand Up @@ -223,6 +223,10 @@ func (c *LruCache[K, V]) Delete(key K) {
c.mu.Lock()
defer c.mu.Unlock()

c.delete(key)
}

func (c *LruCache[K, V]) delete(key K) {
if le, ok := c.cache[key]; ok {
c.deleteElement(le)
}
Expand Down Expand Up @@ -255,6 +259,34 @@ func (c *LruCache[K, V]) Clear() error {
return nil
}

// Compute either sets the computed new value for the key or deletes
// the value for the key. When the delete result of the valueFn function
// is set to true, the value will be deleted, if it exists. When delete
// is set to false, the value is updated to the newValue.
// The ok result indicates whether value was computed and stored, thus, is
// present in the map. The actual result contains the new value in cases where
// the value was computed and stored.
func (c *LruCache[K, V]) Compute(
key K,
valueFn func(oldValue V, loaded bool) (newValue V, delete bool),
) (actual V, ok bool) {
c.mu.Lock()
defer c.mu.Unlock()

if el := c.get(key); el != nil {
actual, ok = el.value, true
}
if newValue, del := valueFn(actual, ok); del {
if ok { // data not in cache, so needn't delete
c.delete(key)
}
return lo.Empty[V](), false
} else {
c.set(key, newValue)
return newValue, true
}
}

type entry[K comparable, V any] struct {
key K
value V
Expand Down
4 changes: 2 additions & 2 deletions common/queue/queue.go
Original file line number Diff line number Diff line change
Expand Up @@ -59,8 +59,8 @@ func (q *Queue[T]) Copy() []T {

// Len returns the number of items in this queue.
func (q *Queue[T]) Len() int64 {
q.lock.Lock()
defer q.lock.Unlock()
q.lock.RLock()
defer q.lock.RUnlock()

return int64(len(q.items))
}
Expand Down
4 changes: 2 additions & 2 deletions common/utils/callback.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,8 @@ func NewCallback[T any]() *Callback[T] {
}

func (c *Callback[T]) Register(item func(T)) io.Closer {
c.mutex.RLock()
defer c.mutex.RUnlock()
c.mutex.Lock()
defer c.mutex.Unlock()
element := c.list.PushBack(item)
return &callbackCloser[T]{
element: element,
Expand Down
10 changes: 10 additions & 0 deletions component/cidr/ipcidr_set.go
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,16 @@ func (set *IpCidrSet) Merge() error {
return nil
}

func (set *IpCidrSet) Foreach(f func(prefix netip.Prefix) bool) {
for _, r := range set.rr {
for _, prefix := range r.Prefixes() {
if !f(prefix) {
return
}
}
}
}

// ToIPSet not safe convert to *netipx.IPSet
// be careful, must be used after Merge
func (set *IpCidrSet) ToIPSet() *netipx.IPSet {
Expand Down
77 changes: 77 additions & 0 deletions component/cidr/ipcidr_set_bin.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
package cidr

import (
"encoding/binary"
"errors"
"io"
"net/netip"

"go4.org/netipx"
)

func (ss *IpCidrSet) WriteBin(w io.Writer) (err error) {
// version
_, err = w.Write([]byte{1})
if err != nil {
return err
}

// rr
err = binary.Write(w, binary.BigEndian, int64(len(ss.rr)))
if err != nil {
return err
}
for _, r := range ss.rr {
err = binary.Write(w, binary.BigEndian, r.From().As16())
if err != nil {
return err
}
err = binary.Write(w, binary.BigEndian, r.To().As16())
if err != nil {
return err
}
}

return nil
}

func ReadIpCidrSet(r io.Reader) (ss *IpCidrSet, err error) {
// version
version := make([]byte, 1)
_, err = io.ReadFull(r, version)
if err != nil {
return nil, err
}
if version[0] != 1 {
return nil, errors.New("version is invalid")
}

ss = NewIpCidrSet()
var length int64

// rr
err = binary.Read(r, binary.BigEndian, &length)
if err != nil {
return nil, err
}
if length < 1 {
return nil, errors.New("length is invalid")
}
ss.rr = make([]netipx.IPRange, length)
for i := int64(0); i < length; i++ {
var a16 [16]byte
err = binary.Read(r, binary.BigEndian, &a16)
if err != nil {
return nil, err
}
from := netip.AddrFrom16(a16).Unmap()
err = binary.Read(r, binary.BigEndian, &a16)
if err != nil {
return nil, err
}
to := netip.AddrFrom16(a16).Unmap()
ss.rr[i] = netipx.IPRangeFrom(from, to)
}

return ss, nil
}
17 changes: 17 additions & 0 deletions component/process/process.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@ package process
import (
"errors"
"net/netip"

C "github.com/metacubex/mihomo/constant"
)

var (
Expand All @@ -19,3 +21,18 @@ const (
func FindProcessName(network string, srcIP netip.Addr, srcPort int) (uint32, string, error) {
return findProcessName(network, srcIP, srcPort)
}

// PackageNameResolver
// never change type traits because it's used in CFMA
type PackageNameResolver func(metadata *C.Metadata) (string, error)

// DefaultPackageNameResolver
// never change type traits because it's used in CFMA
var DefaultPackageNameResolver PackageNameResolver

func FindPackageName(metadata *C.Metadata) (string, error) {
if resolver := DefaultPackageNameResolver; resolver != nil {
return resolver(metadata)
}
return "", ErrPlatformNotSupport
}
16 changes: 0 additions & 16 deletions component/process/process_android.go

This file was deleted.

9 changes: 0 additions & 9 deletions component/process/process_common.go

This file was deleted.

4 changes: 2 additions & 2 deletions component/process/process_darwin.go
Original file line number Diff line number Diff line change
Expand Up @@ -46,12 +46,12 @@ func findProcessName(network string, ip netip.Addr, port int) (uint32, string, e

isIPv4 := ip.Is4()

value, err := syscall.Sysctl(spath)
value, err := unix.SysctlRaw(spath)
if err != nil {
return 0, "", err
}

buf := []byte(value)
buf := value
itemSize := structSize
if network == TCP {
// rup8(sizeof(xtcpcb_n))
Expand Down
57 changes: 16 additions & 41 deletions component/process/process_linux.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,23 +2,19 @@ package process

import (
"bytes"
"context"
"encoding/binary"
"fmt"
"net/netip"
"os"
"path"
"path/filepath"
"runtime"
"strings"
"sync"
"syscall"
"unicode"
"unsafe"

"github.com/metacubex/mihomo/log"

"github.com/mdlayher/netlink"
tun "github.com/metacubex/sing-tun"
"golang.org/x/sys/unix"
)

Expand Down Expand Up @@ -63,25 +59,11 @@ type inetDiagResponse struct {
INode uint32
}

type MyCallback struct{}

var (
packageManager tun.PackageManager
once sync.Once
)

func (cb *MyCallback) OnPackagesUpdated(packageCount int, sharedCount int) {}

func (cb *MyCallback) NewError(ctx context.Context, err error) {
log.Warnln("%s", err)
}

func findProcessName(network string, ip netip.Addr, srcPort int) (uint32, string, error) {
uid, inode, err := resolveSocketByNetlink(network, ip, srcPort)
if err != nil {
return 0, "", err
}

pp, err := resolveProcessNameByProcSearch(inode, uid)
return uid, pp, err
}
Expand Down Expand Up @@ -177,45 +159,38 @@ func resolveProcessNameByProcSearch(inode, uid uint32) (string, error) {
if err != nil {
continue
}

if runtime.GOOS == "android" {
if bytes.Equal(buffer[:n], socket) {
return findPackageName(uid), nil
cmdline, err := os.ReadFile(path.Join(processPath, "cmdline"))
if err != nil {
return "", err
}

return splitCmdline(cmdline), nil
}
} else {
if bytes.Equal(buffer[:n], socket) {
return os.Readlink(filepath.Join(processPath, "exe"))
}
}

}
}

return "", fmt.Errorf("process of uid(%d),inode(%d) not found", uid, inode)
}

func findPackageName(uid uint32) string {
once.Do(func() {
callback := &MyCallback{}
var err error
packageManager, err = tun.NewPackageManager(callback)
if err != nil {
log.Warnln("%s", err)
}
err = packageManager.Start()
if err != nil {
log.Warnln("%s", err)
return
}
func splitCmdline(cmdline []byte) string {
cmdline = bytes.Trim(cmdline, " ")

idx := bytes.IndexFunc(cmdline, func(r rune) bool {
return unicode.IsControl(r) || unicode.IsSpace(r)
})

if sharedPackage, loaded := packageManager.SharedPackageByID(uid % 100000); loaded {
fmt.Println(loaded)
return sharedPackage
}
if packageName, loaded := packageManager.PackageByID(uid % 100000); loaded {
return packageName
if idx == -1 {
return filepath.Base(string(cmdline))
}
return ""
return filepath.Base(string(cmdline[:idx]))
}

func isPid(s string) bool {
Expand Down
Loading

0 comments on commit abb0689

Please sign in to comment.