mirror of
https://github.com/SagerNet/sing-tun.git
synced 2025-04-03 03:47:39 +03:00
Fix monitor
This commit is contained in:
parent
59b86002c4
commit
0a68b9f1d8
9 changed files with 80 additions and 87 deletions
|
@ -1,16 +1,15 @@
|
|||
package tun
|
||||
|
||||
import (
|
||||
"context"
|
||||
"net"
|
||||
"net/netip"
|
||||
"os"
|
||||
"sync"
|
||||
"syscall"
|
||||
"time"
|
||||
|
||||
"github.com/sagernet/sing/common"
|
||||
"github.com/sagernet/sing/common/buf"
|
||||
E "github.com/sagernet/sing/common/exceptions"
|
||||
"github.com/sagernet/sing/common/logger"
|
||||
"github.com/sagernet/sing/common/x/list"
|
||||
|
||||
"golang.org/x/net/route"
|
||||
|
@ -18,61 +17,63 @@ import (
|
|||
)
|
||||
|
||||
type networkUpdateMonitor struct {
|
||||
errorHandler E.Handler
|
||||
|
||||
access sync.Mutex
|
||||
callbacks list.List[NetworkUpdateCallback]
|
||||
routeSocket *os.File
|
||||
routeSocket int
|
||||
logger logger.Logger
|
||||
}
|
||||
|
||||
func NewNetworkUpdateMonitor(errorHandler E.Handler) (NetworkUpdateMonitor, error) {
|
||||
return &networkUpdateMonitor{
|
||||
errorHandler: errorHandler,
|
||||
}, nil
|
||||
func NewNetworkUpdateMonitor(logger logger.Logger) (NetworkUpdateMonitor, error) {
|
||||
return &networkUpdateMonitor{logger: logger}, nil
|
||||
}
|
||||
|
||||
func (m *networkUpdateMonitor) Start() error {
|
||||
routeSocket, err := unix.Socket(unix.AF_ROUTE, unix.SOCK_RAW, 0)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
err = unix.SetNonblock(routeSocket, true)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
m.routeSocket = os.NewFile(uintptr(routeSocket), "route")
|
||||
go m.loopUpdate()
|
||||
return nil
|
||||
}
|
||||
|
||||
func (m *networkUpdateMonitor) loopUpdate() {
|
||||
rawConn, err := m.routeSocket.SyscallConn()
|
||||
for {
|
||||
err := m.loopUpdate0()
|
||||
if err != nil {
|
||||
m.logger.Error("listen network update: ", err)
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (m *networkUpdateMonitor) loopUpdate0() error {
|
||||
routeSocket, err := unix.Socket(unix.AF_ROUTE, unix.SOCK_RAW, 0)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
m.loopUpdate1(os.NewFile(uintptr(routeSocket), "route"))
|
||||
return nil
|
||||
}
|
||||
|
||||
func (m *networkUpdateMonitor) loopUpdate1(routeSocketFile *os.File) {
|
||||
defer routeSocketFile.Close()
|
||||
buffer := buf.NewPacket()
|
||||
defer buffer.Release()
|
||||
n, err := routeSocketFile.Read(buffer.FreeBytes())
|
||||
if err != nil {
|
||||
m.errorHandler.NewError(context.Background(), E.Cause(err, "create raw route connection"))
|
||||
return
|
||||
}
|
||||
for {
|
||||
var innerErr error
|
||||
err = rawConn.Read(func(fd uintptr) (done bool) {
|
||||
var msg [2048]byte
|
||||
_, innerErr = unix.Read(int(fd), msg[:])
|
||||
return innerErr != unix.EWOULDBLOCK
|
||||
})
|
||||
if innerErr != nil {
|
||||
err = innerErr
|
||||
}
|
||||
if err != nil {
|
||||
break
|
||||
}
|
||||
m.emit()
|
||||
buffer.Truncate(n)
|
||||
messages, err := route.ParseRIB(route.RIBTypeRoute, buffer.Bytes())
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
if err != syscall.EAGAIN {
|
||||
m.errorHandler.NewError(context.Background(), E.Cause(err, "read route message"))
|
||||
for _, message := range messages {
|
||||
if _, isRouteMessage := message.(*route.RouteMessage); isRouteMessage {
|
||||
m.emit()
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (m *networkUpdateMonitor) Close() error {
|
||||
return common.Close(common.PtrOrNil(m.routeSocket))
|
||||
return unix.Close(m.routeSocket)
|
||||
}
|
||||
|
||||
func (m *defaultInterfaceMonitor) checkUpdate() error {
|
||||
|
@ -116,7 +117,7 @@ func (m *defaultInterfaceMonitor) checkUpdate() error {
|
|||
continue
|
||||
}
|
||||
if routeMessage.Flags&unix.RTF_IFSCOPE != 0 {
|
||||
continue
|
||||
// continue
|
||||
}
|
||||
defaultInterface = routeInterface
|
||||
break
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue