diff --git a/.github/CRONET_GO_VERSION b/.github/CRONET_GO_VERSION index a703eff56..52565262a 100644 --- a/.github/CRONET_GO_VERSION +++ b/.github/CRONET_GO_VERSION @@ -1 +1 @@ -abd78bb191a815236485ad929716845ffb41465a +34ec1a064c64f274c4e70bf7a9c7de4bb12331f6 diff --git a/adapter/connections.go b/adapter/connections.go index 0682d05a0..a0b9c0ef8 100644 --- a/adapter/connections.go +++ b/adapter/connections.go @@ -9,6 +9,10 @@ import ( type ConnectionManager interface { Lifecycle + Count() int + CloseAll() + TrackConn(conn net.Conn) net.Conn + TrackPacketConn(conn net.PacketConn) net.PacketConn NewConnection(ctx context.Context, this N.Dialer, conn net.Conn, metadata InboundContext, onClose N.CloseHandlerFunc) NewPacketConnection(ctx context.Context, this N.Dialer, conn N.PacketConn, metadata InboundContext, onClose N.CloseHandlerFunc) } diff --git a/box.go b/box.go index 7885b0d41..fe116b317 100644 --- a/box.go +++ b/box.go @@ -125,7 +125,10 @@ func New(options Options) (*Box, error) { ctx = pause.WithDefaultManager(ctx) experimentalOptions := common.PtrValueOrDefault(options.Experimental) - applyDebugOptions(common.PtrValueOrDefault(experimentalOptions.Debug)) + err := applyDebugOptions(common.PtrValueOrDefault(experimentalOptions.Debug)) + if err != nil { + return nil, err + } var needCacheFile bool var needClashAPI bool var needV2RayAPI bool diff --git a/cmd/internal/build_libbox/main.go b/cmd/internal/build_libbox/main.go index e9cbb1ef3..c12821693 100644 --- a/cmd/internal/build_libbox/main.go +++ b/cmd/internal/build_libbox/main.go @@ -63,7 +63,7 @@ func init() { sharedFlags = append(sharedFlags, "-ldflags", "-X github.com/sagernet/sing-box/constant.Version="+currentTag+" -X internal/godebug.defaultGODEBUG=multipathtcp=0 -s -w -buildid= -checklinkname=0") debugFlags = append(debugFlags, "-ldflags", "-X github.com/sagernet/sing-box/constant.Version="+currentTag+" -X internal/godebug.defaultGODEBUG=multipathtcp=0 -checklinkname=0") - sharedTags = append(sharedTags, "with_gvisor", "with_quic", "with_wireguard", "with_utls", "with_naive_outbound", "with_clash_api", "with_conntrack", "badlinkname", "tfogo_checklinkname0") + sharedTags = append(sharedTags, "with_gvisor", "with_quic", "with_wireguard", "with_utls", "with_naive_outbound", "with_clash_api", "badlinkname", "tfogo_checklinkname0") darwinTags = append(darwinTags, "with_dhcp", "grpcnotrace") // memcTags = append(memcTags, "with_tailscale") sharedTags = append(sharedTags, "with_tailscale", "ts_omit_logtail", "ts_omit_ssh", "ts_omit_drive", "ts_omit_taildrop", "ts_omit_webclient", "ts_omit_doctor", "ts_omit_capture", "ts_omit_kube", "ts_omit_aws", "ts_omit_synology", "ts_omit_bird") diff --git a/common/conntrack/conn.go b/common/conntrack/conn.go deleted file mode 100644 index 4773d6a82..000000000 --- a/common/conntrack/conn.go +++ /dev/null @@ -1,54 +0,0 @@ -package conntrack - -import ( - "io" - "net" - - "github.com/sagernet/sing/common/x/list" -) - -type Conn struct { - net.Conn - element *list.Element[io.Closer] -} - -func NewConn(conn net.Conn) (net.Conn, error) { - connAccess.Lock() - element := openConnection.PushBack(conn) - connAccess.Unlock() - if KillerEnabled { - err := KillerCheck() - if err != nil { - conn.Close() - return nil, err - } - } - return &Conn{ - Conn: conn, - element: element, - }, nil -} - -func (c *Conn) Close() error { - if c.element.Value != nil { - connAccess.Lock() - if c.element.Value != nil { - openConnection.Remove(c.element) - c.element.Value = nil - } - connAccess.Unlock() - } - return c.Conn.Close() -} - -func (c *Conn) Upstream() any { - return c.Conn -} - -func (c *Conn) ReaderReplaceable() bool { - return true -} - -func (c *Conn) WriterReplaceable() bool { - return true -} diff --git a/common/conntrack/killer.go b/common/conntrack/killer.go deleted file mode 100644 index e0a71e5cb..000000000 --- a/common/conntrack/killer.go +++ /dev/null @@ -1,35 +0,0 @@ -package conntrack - -import ( - runtimeDebug "runtime/debug" - "time" - - E "github.com/sagernet/sing/common/exceptions" - "github.com/sagernet/sing/common/memory" -) - -var ( - KillerEnabled bool - MemoryLimit uint64 - killerLastCheck time.Time -) - -func KillerCheck() error { - if !KillerEnabled { - return nil - } - nowTime := time.Now() - if nowTime.Sub(killerLastCheck) < 3*time.Second { - return nil - } - killerLastCheck = nowTime - if memory.Total() > MemoryLimit { - Close() - go func() { - time.Sleep(time.Second) - runtimeDebug.FreeOSMemory() - }() - return E.New("out of memory") - } - return nil -} diff --git a/common/conntrack/packet_conn.go b/common/conntrack/packet_conn.go deleted file mode 100644 index c7274637e..000000000 --- a/common/conntrack/packet_conn.go +++ /dev/null @@ -1,55 +0,0 @@ -package conntrack - -import ( - "io" - "net" - - "github.com/sagernet/sing/common/bufio" - "github.com/sagernet/sing/common/x/list" -) - -type PacketConn struct { - net.PacketConn - element *list.Element[io.Closer] -} - -func NewPacketConn(conn net.PacketConn) (net.PacketConn, error) { - connAccess.Lock() - element := openConnection.PushBack(conn) - connAccess.Unlock() - if KillerEnabled { - err := KillerCheck() - if err != nil { - conn.Close() - return nil, err - } - } - return &PacketConn{ - PacketConn: conn, - element: element, - }, nil -} - -func (c *PacketConn) Close() error { - if c.element.Value != nil { - connAccess.Lock() - if c.element.Value != nil { - openConnection.Remove(c.element) - c.element.Value = nil - } - connAccess.Unlock() - } - return c.PacketConn.Close() -} - -func (c *PacketConn) Upstream() any { - return bufio.NewPacketConn(c.PacketConn) -} - -func (c *PacketConn) ReaderReplaceable() bool { - return true -} - -func (c *PacketConn) WriterReplaceable() bool { - return true -} diff --git a/common/conntrack/track.go b/common/conntrack/track.go deleted file mode 100644 index 2c3e328b3..000000000 --- a/common/conntrack/track.go +++ /dev/null @@ -1,47 +0,0 @@ -package conntrack - -import ( - "io" - "sync" - - "github.com/sagernet/sing/common" - "github.com/sagernet/sing/common/x/list" -) - -var ( - connAccess sync.RWMutex - openConnection list.List[io.Closer] -) - -func Count() int { - if !Enabled { - return 0 - } - return openConnection.Len() -} - -func List() []io.Closer { - if !Enabled { - return nil - } - connAccess.RLock() - defer connAccess.RUnlock() - connList := make([]io.Closer, 0, openConnection.Len()) - for element := openConnection.Front(); element != nil; element = element.Next() { - connList = append(connList, element.Value) - } - return connList -} - -func Close() { - if !Enabled { - return - } - connAccess.Lock() - defer connAccess.Unlock() - for element := openConnection.Front(); element != nil; element = element.Next() { - common.Close(element.Value) - element.Value = nil - } - openConnection.Init() -} diff --git a/common/conntrack/track_disable.go b/common/conntrack/track_disable.go deleted file mode 100644 index 174d8b6eb..000000000 --- a/common/conntrack/track_disable.go +++ /dev/null @@ -1,5 +0,0 @@ -//go:build !with_conntrack - -package conntrack - -const Enabled = false diff --git a/common/conntrack/track_enable.go b/common/conntrack/track_enable.go deleted file mode 100644 index a4bf9986a..000000000 --- a/common/conntrack/track_enable.go +++ /dev/null @@ -1,5 +0,0 @@ -//go:build with_conntrack - -package conntrack - -const Enabled = true diff --git a/common/dialer/default.go b/common/dialer/default.go index 3ab2e05a0..ad37834c0 100644 --- a/common/dialer/default.go +++ b/common/dialer/default.go @@ -9,7 +9,6 @@ import ( "time" "github.com/sagernet/sing-box/adapter" - "github.com/sagernet/sing-box/common/conntrack" "github.com/sagernet/sing-box/common/listener" C "github.com/sagernet/sing-box/constant" "github.com/sagernet/sing-box/option" @@ -37,6 +36,7 @@ type DefaultDialer struct { udpAddr4 string udpAddr6 string netns string + connectionManager adapter.ConnectionManager networkManager adapter.NetworkManager networkStrategy *C.NetworkStrategy defaultNetworkStrategy bool @@ -47,6 +47,7 @@ type DefaultDialer struct { } func NewDefault(ctx context.Context, options option.DialerOptions) (*DefaultDialer, error) { + connectionManager := service.FromContext[adapter.ConnectionManager](ctx) networkManager := service.FromContext[adapter.NetworkManager](ctx) platformInterface := service.FromContext[adapter.PlatformInterface](ctx) @@ -206,6 +207,7 @@ func NewDefault(ctx context.Context, options option.DialerOptions) (*DefaultDial udpAddr4: udpAddr4, udpAddr6: udpAddr6, netns: options.NetNs, + connectionManager: connectionManager, networkManager: networkManager, networkStrategy: networkStrategy, defaultNetworkStrategy: defaultNetworkStrategy, @@ -238,7 +240,7 @@ func (d *DefaultDialer) DialContext(ctx context.Context, network string, address return nil, E.New("domain not resolved") } if d.networkStrategy == nil { - return trackConn(listener.ListenNetworkNamespace[net.Conn](d.netns, func() (net.Conn, error) { + return d.trackConn(listener.ListenNetworkNamespace[net.Conn](d.netns, func() (net.Conn, error) { switch N.NetworkName(network) { case N.NetworkUDP: if !address.IsIPv6() { @@ -303,12 +305,12 @@ func (d *DefaultDialer) DialParallelInterface(ctx context.Context, network strin if !fastFallback && !isPrimary { d.networkLastFallback.Store(time.Now()) } - return trackConn(conn, nil) + return d.trackConn(conn, nil) } func (d *DefaultDialer) ListenPacket(ctx context.Context, destination M.Socksaddr) (net.PacketConn, error) { if d.networkStrategy == nil { - return trackPacketConn(listener.ListenNetworkNamespace[net.PacketConn](d.netns, func() (net.PacketConn, error) { + return d.trackPacketConn(listener.ListenNetworkNamespace[net.PacketConn](d.netns, func() (net.PacketConn, error) { if destination.IsIPv6() { return d.udpListener.ListenPacket(ctx, N.NetworkUDP, d.udpAddr6) } else if destination.IsIPv4() && !destination.Addr.IsUnspecified() { @@ -360,23 +362,23 @@ func (d *DefaultDialer) ListenSerialInterfacePacket(ctx context.Context, destina return nil, err } } - return trackPacketConn(packetConn, nil) + return d.trackPacketConn(packetConn, nil) } func (d *DefaultDialer) WireGuardControl() control.Func { return d.udpListener.Control } -func trackConn(conn net.Conn, err error) (net.Conn, error) { - if !conntrack.Enabled || err != nil { +func (d *DefaultDialer) trackConn(conn net.Conn, err error) (net.Conn, error) { + if d.connectionManager == nil || err != nil { return conn, err } - return conntrack.NewConn(conn) + return d.connectionManager.TrackConn(conn), nil } -func trackPacketConn(conn net.PacketConn, err error) (net.PacketConn, error) { - if !conntrack.Enabled || err != nil { +func (d *DefaultDialer) trackPacketConn(conn net.PacketConn, err error) (net.PacketConn, error) { + if d.connectionManager == nil || err != nil { return conn, err } - return conntrack.NewPacketConn(conn) + return d.connectionManager.TrackPacketConn(conn), nil } diff --git a/constant/proxy.go b/constant/proxy.go index a51936234..4130c631a 100644 --- a/constant/proxy.go +++ b/constant/proxy.go @@ -30,6 +30,7 @@ const ( TypeSSMAPI = "ssm-api" TypeCCM = "ccm" TypeOCM = "ocm" + TypeOOMKiller = "oom-killer" ) const ( diff --git a/daemon/instance.go b/daemon/instance.go index 5947452f9..4ed741822 100644 --- a/daemon/instance.go +++ b/daemon/instance.go @@ -7,10 +7,12 @@ import ( "github.com/sagernet/sing-box" "github.com/sagernet/sing-box/adapter" "github.com/sagernet/sing-box/common/urltest" + C "github.com/sagernet/sing-box/constant" "github.com/sagernet/sing-box/experimental/deprecated" "github.com/sagernet/sing-box/include" "github.com/sagernet/sing-box/log" "github.com/sagernet/sing-box/option" + "github.com/sagernet/sing/common" E "github.com/sagernet/sing/common/exceptions" "github.com/sagernet/sing/common/json" "github.com/sagernet/sing/service" @@ -21,6 +23,7 @@ type Instance struct { ctx context.Context cancel context.CancelFunc instance *box.Box + connectionManager adapter.ConnectionManager clashServer adapter.ClashServer cacheFile adapter.CacheFile pauseManager pause.Manager @@ -84,6 +87,15 @@ func (s *StartedService) newInstance(profileContent string, overrideOptions *Ove } } } + if s.oomKiller && C.IsIos { + if !common.Any(options.Services, func(it option.Service) bool { + return it.Type == C.TypeOOMKiller + }) { + options.Services = append(options.Services, option.Service{ + Type: C.TypeOOMKiller, + }) + } + } urlTestHistoryStorage := urltest.NewHistoryStorage() ctx = service.ContextWithPtr(ctx, urlTestHistoryStorage) i := &Instance{ @@ -101,6 +113,7 @@ func (s *StartedService) newInstance(profileContent string, overrideOptions *Ove return nil, err } i.instance = boxInstance + i.connectionManager = service.FromContext[adapter.ConnectionManager](ctx) i.clashServer = service.FromContext[adapter.ClashServer](ctx) i.pauseManager = service.FromContext[pause.Manager](ctx) i.cacheFile = service.FromContext[adapter.CacheFile](ctx) diff --git a/daemon/started_service.go b/daemon/started_service.go index 7c6fa9457..5e677f7ac 100644 --- a/daemon/started_service.go +++ b/daemon/started_service.go @@ -8,7 +8,6 @@ import ( "time" "github.com/sagernet/sing-box/adapter" - "github.com/sagernet/sing-box/common/conntrack" "github.com/sagernet/sing-box/common/urltest" "github.com/sagernet/sing-box/experimental/clashapi" "github.com/sagernet/sing-box/experimental/clashapi/trafficontrol" @@ -36,6 +35,7 @@ type StartedService struct { handler PlatformHandler debug bool logMaxLines int + oomKiller bool // workingDirectory string // tempDirectory string // userID int @@ -67,6 +67,7 @@ type ServiceOptions struct { Handler PlatformHandler Debug bool LogMaxLines int + OOMKiller bool // WorkingDirectory string // TempDirectory string // UserID int @@ -81,6 +82,7 @@ func NewStartedService(options ServiceOptions) *StartedService { handler: options.Handler, debug: options.Debug, logMaxLines: options.LogMaxLines, + oomKiller: options.OOMKiller, // workingDirectory: options.WorkingDirectory, // tempDirectory: options.TempDirectory, // userID: options.UserID, @@ -409,10 +411,12 @@ func (s *StartedService) readStatus() *Status { var status Status status.Memory = memory.Inuse() status.Goroutines = int32(runtime.NumGoroutine()) - status.ConnectionsOut = int32(conntrack.Count()) s.serviceAccess.RLock() nowService := s.instance s.serviceAccess.RUnlock() + if nowService != nil && nowService.connectionManager != nil { + status.ConnectionsOut = int32(nowService.connectionManager.Count()) + } if nowService != nil { if clashServer := nowService.clashServer; clashServer != nil { status.TrafficAvailable = true @@ -993,7 +997,12 @@ func (s *StartedService) CloseConnection(ctx context.Context, request *CloseConn } func (s *StartedService) CloseAllConnections(ctx context.Context, empty *emptypb.Empty) (*emptypb.Empty, error) { - conntrack.Close() + s.serviceAccess.RLock() + nowService := s.instance + s.serviceAccess.RUnlock() + if nowService != nil && nowService.connectionManager != nil { + nowService.connectionManager.CloseAll() + } return &emptypb.Empty{}, nil } diff --git a/debug.go b/debug.go index 1726c10e9..f620172be 100644 --- a/debug.go +++ b/debug.go @@ -3,11 +3,11 @@ package box import ( "runtime/debug" - "github.com/sagernet/sing-box/common/conntrack" "github.com/sagernet/sing-box/option" + E "github.com/sagernet/sing/common/exceptions" ) -func applyDebugOptions(options option.DebugOptions) { +func applyDebugOptions(options option.DebugOptions) error { applyDebugListenOption(options) if options.GCPercent != nil { debug.SetGCPercent(*options.GCPercent) @@ -26,9 +26,9 @@ func applyDebugOptions(options option.DebugOptions) { } if options.MemoryLimit.Value() != 0 { debug.SetMemoryLimit(int64(float64(options.MemoryLimit.Value()) / 1.5)) - conntrack.MemoryLimit = options.MemoryLimit.Value() } if options.OOMKiller != nil { - conntrack.KillerEnabled = *options.OOMKiller + return E.New("legacy oom_killer in debug options is removed, use oom-killer service instead") } + return nil } diff --git a/experimental/libbox/command_server.go b/experimental/libbox/command_server.go index e33002816..1c2412b69 100644 --- a/experimental/libbox/command_server.go +++ b/experimental/libbox/command_server.go @@ -60,6 +60,7 @@ func NewCommandServer(handler CommandServerHandler, platformInterface PlatformIn Handler: (*platformHandler)(server), Debug: sDebug, LogMaxLines: sLogMaxLines, + OOMKiller: memoryLimitEnabled, // WorkingDirectory: sWorkingPath, // TempDirectory: sTempPath, // UserID: sUserID, diff --git a/experimental/libbox/ffi.json b/experimental/libbox/ffi.json index 283338712..81fae27da 100644 --- a/experimental/libbox/ffi.json +++ b/experimental/libbox/ffi.json @@ -29,7 +29,6 @@ "with_utls", "with_naive_outbound", "with_clash_api", - "with_conntrack", "badlinkname", "tfogo_checklinkname0", "with_tailscale", @@ -59,7 +58,6 @@ "with_wireguard", "with_utls", "with_clash_api", - "with_conntrack", "badlinkname", "tfogo_checklinkname0", "with_tailscale", @@ -90,7 +88,6 @@ "with_utls", "with_naive_outbound", "with_clash_api", - "with_conntrack", "badlinkname", "tfogo_checklinkname0", "with_dhcp", @@ -134,7 +131,6 @@ "with_naive_outbound", "with_purego", "with_clash_api", - "with_conntrack", "badlinkname", "tfogo_checklinkname0", "with_tailscale", diff --git a/experimental/libbox/memory.go b/experimental/libbox/memory.go index b10c67014..b0b87f73f 100644 --- a/experimental/libbox/memory.go +++ b/experimental/libbox/memory.go @@ -4,20 +4,23 @@ import ( "math" runtimeDebug "runtime/debug" - "github.com/sagernet/sing-box/common/conntrack" + C "github.com/sagernet/sing-box/constant" ) +var memoryLimitEnabled bool + func SetMemoryLimit(enabled bool) { - const memoryLimit = 45 * 1024 * 1024 - const memoryLimitGo = memoryLimit / 1.5 + memoryLimitEnabled = enabled + const memoryLimitGo = 45 * 1024 * 1024 if enabled { runtimeDebug.SetGCPercent(10) - runtimeDebug.SetMemoryLimit(memoryLimitGo) - conntrack.KillerEnabled = true - conntrack.MemoryLimit = memoryLimit + if C.IsIos { + runtimeDebug.SetMemoryLimit(memoryLimitGo) + } } else { runtimeDebug.SetGCPercent(100) - runtimeDebug.SetMemoryLimit(math.MaxInt64) - conntrack.KillerEnabled = false + if C.IsIos { + runtimeDebug.SetMemoryLimit(math.MaxInt64) + } } } diff --git a/go.mod b/go.mod index 0523b73fc..506b54cf0 100644 --- a/go.mod +++ b/go.mod @@ -27,8 +27,8 @@ require ( github.com/sagernet/asc-go v0.0.0-20241217030726-d563060fe4e1 github.com/sagernet/bbolt v0.0.0-20231014093535-ea5cb2fe9f0a github.com/sagernet/cors v1.2.1 - github.com/sagernet/cronet-go v0.0.0-20260221042137-abd78bb191a8 - github.com/sagernet/cronet-go/all v0.0.0-20260221042137-abd78bb191a8 + github.com/sagernet/cronet-go v0.0.0-20260226034600-34ec1a064c64 + github.com/sagernet/cronet-go/all v0.0.0-20260226034600-34ec1a064c64 github.com/sagernet/fswatch v0.1.1 github.com/sagernet/gomobile v0.1.11 github.com/sagernet/gvisor v0.0.0-20250811.0-sing-box-mod.1 @@ -105,35 +105,35 @@ require ( github.com/prometheus-community/pro-bing v0.4.0 // indirect github.com/quic-go/qpack v0.6.0 // indirect github.com/safchain/ethtool v0.3.0 // indirect - github.com/sagernet/cronet-go/lib/android_386 v0.0.0-20260221041448-e52d68fd87fe // indirect - github.com/sagernet/cronet-go/lib/android_amd64 v0.0.0-20260221041448-e52d68fd87fe // indirect - github.com/sagernet/cronet-go/lib/android_arm v0.0.0-20260221041448-e52d68fd87fe // indirect - github.com/sagernet/cronet-go/lib/android_arm64 v0.0.0-20260221041448-e52d68fd87fe // indirect - github.com/sagernet/cronet-go/lib/darwin_amd64 v0.0.0-20260221041448-e52d68fd87fe // indirect - github.com/sagernet/cronet-go/lib/darwin_arm64 v0.0.0-20260221041448-e52d68fd87fe // indirect - github.com/sagernet/cronet-go/lib/ios_amd64_simulator v0.0.0-20260221041448-e52d68fd87fe // indirect - github.com/sagernet/cronet-go/lib/ios_arm64 v0.0.0-20260221041448-e52d68fd87fe // indirect - github.com/sagernet/cronet-go/lib/ios_arm64_simulator v0.0.0-20260221041448-e52d68fd87fe // indirect - github.com/sagernet/cronet-go/lib/linux_386 v0.0.0-20260221041448-e52d68fd87fe // indirect - github.com/sagernet/cronet-go/lib/linux_386_musl v0.0.0-20260221041448-e52d68fd87fe // indirect - github.com/sagernet/cronet-go/lib/linux_amd64 v0.0.0-20260221041448-e52d68fd87fe // indirect - github.com/sagernet/cronet-go/lib/linux_amd64_musl v0.0.0-20260221041448-e52d68fd87fe // indirect - github.com/sagernet/cronet-go/lib/linux_arm v0.0.0-20260221041448-e52d68fd87fe // indirect - github.com/sagernet/cronet-go/lib/linux_arm64 v0.0.0-20260221041448-e52d68fd87fe // indirect - github.com/sagernet/cronet-go/lib/linux_arm64_musl v0.0.0-20260221041448-e52d68fd87fe // indirect - github.com/sagernet/cronet-go/lib/linux_arm_musl v0.0.0-20260221041448-e52d68fd87fe // indirect - github.com/sagernet/cronet-go/lib/linux_loong64 v0.0.0-20260221041448-e52d68fd87fe // indirect - github.com/sagernet/cronet-go/lib/linux_loong64_musl v0.0.0-20260221041448-e52d68fd87fe // indirect - github.com/sagernet/cronet-go/lib/linux_mips64le v0.0.0-20260221041448-e52d68fd87fe // indirect - github.com/sagernet/cronet-go/lib/linux_mipsle v0.0.0-20260221041448-e52d68fd87fe // indirect - github.com/sagernet/cronet-go/lib/linux_mipsle_musl v0.0.0-20260221041448-e52d68fd87fe // indirect - github.com/sagernet/cronet-go/lib/linux_riscv64 v0.0.0-20260221041448-e52d68fd87fe // indirect - github.com/sagernet/cronet-go/lib/linux_riscv64_musl v0.0.0-20260221041448-e52d68fd87fe // indirect - github.com/sagernet/cronet-go/lib/tvos_amd64_simulator v0.0.0-20260221041448-e52d68fd87fe // indirect - github.com/sagernet/cronet-go/lib/tvos_arm64 v0.0.0-20260221041448-e52d68fd87fe // indirect - github.com/sagernet/cronet-go/lib/tvos_arm64_simulator v0.0.0-20260221041448-e52d68fd87fe // indirect - github.com/sagernet/cronet-go/lib/windows_amd64 v0.0.0-20260221041448-e52d68fd87fe // indirect - github.com/sagernet/cronet-go/lib/windows_arm64 v0.0.0-20260221041448-e52d68fd87fe // indirect + github.com/sagernet/cronet-go/lib/android_386 v0.0.0-20260226033953-5745aabe7717 // indirect + github.com/sagernet/cronet-go/lib/android_amd64 v0.0.0-20260226033953-5745aabe7717 // indirect + github.com/sagernet/cronet-go/lib/android_arm v0.0.0-20260226033953-5745aabe7717 // indirect + github.com/sagernet/cronet-go/lib/android_arm64 v0.0.0-20260226033953-5745aabe7717 // indirect + github.com/sagernet/cronet-go/lib/darwin_amd64 v0.0.0-20260226033953-5745aabe7717 // indirect + github.com/sagernet/cronet-go/lib/darwin_arm64 v0.0.0-20260226033953-5745aabe7717 // indirect + github.com/sagernet/cronet-go/lib/ios_amd64_simulator v0.0.0-20260226033953-5745aabe7717 // indirect + github.com/sagernet/cronet-go/lib/ios_arm64 v0.0.0-20260226033953-5745aabe7717 // indirect + github.com/sagernet/cronet-go/lib/ios_arm64_simulator v0.0.0-20260226033953-5745aabe7717 // indirect + github.com/sagernet/cronet-go/lib/linux_386 v0.0.0-20260226033953-5745aabe7717 // indirect + github.com/sagernet/cronet-go/lib/linux_386_musl v0.0.0-20260226033953-5745aabe7717 // indirect + github.com/sagernet/cronet-go/lib/linux_amd64 v0.0.0-20260226033953-5745aabe7717 // indirect + github.com/sagernet/cronet-go/lib/linux_amd64_musl v0.0.0-20260226033953-5745aabe7717 // indirect + github.com/sagernet/cronet-go/lib/linux_arm v0.0.0-20260226033953-5745aabe7717 // indirect + github.com/sagernet/cronet-go/lib/linux_arm64 v0.0.0-20260226033953-5745aabe7717 // indirect + github.com/sagernet/cronet-go/lib/linux_arm64_musl v0.0.0-20260226033953-5745aabe7717 // indirect + github.com/sagernet/cronet-go/lib/linux_arm_musl v0.0.0-20260226033953-5745aabe7717 // indirect + github.com/sagernet/cronet-go/lib/linux_loong64 v0.0.0-20260226033953-5745aabe7717 // indirect + github.com/sagernet/cronet-go/lib/linux_loong64_musl v0.0.0-20260226033953-5745aabe7717 // indirect + github.com/sagernet/cronet-go/lib/linux_mips64le v0.0.0-20260226033953-5745aabe7717 // indirect + github.com/sagernet/cronet-go/lib/linux_mipsle v0.0.0-20260226033953-5745aabe7717 // indirect + github.com/sagernet/cronet-go/lib/linux_mipsle_musl v0.0.0-20260226033953-5745aabe7717 // indirect + github.com/sagernet/cronet-go/lib/linux_riscv64 v0.0.0-20260226033953-5745aabe7717 // indirect + github.com/sagernet/cronet-go/lib/linux_riscv64_musl v0.0.0-20260226033953-5745aabe7717 // indirect + github.com/sagernet/cronet-go/lib/tvos_amd64_simulator v0.0.0-20260226033953-5745aabe7717 // indirect + github.com/sagernet/cronet-go/lib/tvos_arm64 v0.0.0-20260226033953-5745aabe7717 // indirect + github.com/sagernet/cronet-go/lib/tvos_arm64_simulator v0.0.0-20260226033953-5745aabe7717 // indirect + github.com/sagernet/cronet-go/lib/windows_amd64 v0.0.0-20260226033953-5745aabe7717 // indirect + github.com/sagernet/cronet-go/lib/windows_arm64 v0.0.0-20260226033953-5745aabe7717 // indirect github.com/sagernet/netlink v0.0.0-20240612041022-b9a21c07ac6a // indirect github.com/sagernet/nftables v0.3.0-beta.4 // indirect github.com/spf13/pflag v1.0.9 // indirect diff --git a/go.sum b/go.sum index 738a415b1..c9478c270 100644 --- a/go.sum +++ b/go.sum @@ -152,68 +152,68 @@ github.com/sagernet/bbolt v0.0.0-20231014093535-ea5cb2fe9f0a h1:+NkI2670SQpQWvkk github.com/sagernet/bbolt v0.0.0-20231014093535-ea5cb2fe9f0a/go.mod h1:63s7jpZqcDAIpj8oI/1v4Izok+npJOHACFCU6+huCkM= github.com/sagernet/cors v1.2.1 h1:Cv5Z8y9YSD6Gm+qSpNrL3LO4lD3eQVvbFYJSG7JCMHQ= github.com/sagernet/cors v1.2.1/go.mod h1:O64VyOjjhrkLmQIjF4KGRrJO/5dVXFdpEmCW/eISRAI= -github.com/sagernet/cronet-go v0.0.0-20260221042137-abd78bb191a8 h1:XcZiLUXnYE74RvqVdsyxgIInBuFaZbABx2Hom5U6uuk= -github.com/sagernet/cronet-go v0.0.0-20260221042137-abd78bb191a8/go.mod h1:hwFHBEjjthyEquDULbr4c4ucMedp8Drb6Jvm2kt/0Bw= -github.com/sagernet/cronet-go/all v0.0.0-20260221042137-abd78bb191a8 h1:uaUy9opPmPYD+viUeUnBzT+lw5b19j6pC/iKew7u13I= -github.com/sagernet/cronet-go/all v0.0.0-20260221042137-abd78bb191a8/go.mod h1:Gn1d0D8adjp7mlgSv+/pVLJsG+engIMBp/R4+1MOhlk= -github.com/sagernet/cronet-go/lib/android_386 v0.0.0-20260221041448-e52d68fd87fe h1:iKIZJsvD+D3sdAzAeeOodJBxnFL9OVs1LTq3xnmQ6wQ= -github.com/sagernet/cronet-go/lib/android_386 v0.0.0-20260221041448-e52d68fd87fe/go.mod h1:XXDwdjX/T8xftoeJxQmbBoYXZp8MAPFR2CwbFuTpEtw= -github.com/sagernet/cronet-go/lib/android_amd64 v0.0.0-20260221041448-e52d68fd87fe h1:/YhWKKVb3uQ5JmBQwFEOKg8QK2w0Ky6dxEb/UHrhQww= -github.com/sagernet/cronet-go/lib/android_amd64 v0.0.0-20260221041448-e52d68fd87fe/go.mod h1:iNiUGoLtnr8/JTuVNj7XJbmpOAp2C6+B81KDrPxwaZM= -github.com/sagernet/cronet-go/lib/android_arm v0.0.0-20260221041448-e52d68fd87fe h1:h+XF746wRtYKavUeS8//Vro6s9f0F6+pI8VQFLMLg6E= -github.com/sagernet/cronet-go/lib/android_arm v0.0.0-20260221041448-e52d68fd87fe/go.mod h1:19ILNUOGIzRdOqa2mq+iY0JoHxuieB7/lnjYeaA2vEc= -github.com/sagernet/cronet-go/lib/android_arm64 v0.0.0-20260221041448-e52d68fd87fe h1:yMs96D9ErwAG8gEHV6zaQ5cp9ZPNBHExxJ5+u8cZ644= -github.com/sagernet/cronet-go/lib/android_arm64 v0.0.0-20260221041448-e52d68fd87fe/go.mod h1:JxzGyQf94Cr6sBShKqODGDyRUlESfJK/Njcz9Lz6qMQ= -github.com/sagernet/cronet-go/lib/darwin_amd64 v0.0.0-20260221041448-e52d68fd87fe h1:HUJtGjXcB+70W+YfeLgue6X1u69XLN0Ar56Ipg3gtvY= -github.com/sagernet/cronet-go/lib/darwin_amd64 v0.0.0-20260221041448-e52d68fd87fe/go.mod h1:KN+9T9TBycGOLzmKU4QdcHAJEj6Nlx48ifnlTvvHMvs= -github.com/sagernet/cronet-go/lib/darwin_arm64 v0.0.0-20260221041448-e52d68fd87fe h1:ivo7JwVqDTMf/qVfpKYdwcIc+NzKGyMJ/WLj/TTNYXg= -github.com/sagernet/cronet-go/lib/darwin_arm64 v0.0.0-20260221041448-e52d68fd87fe/go.mod h1:kojvtUc29KKnk8hs2QIANynVR59921SnGWA9kXohHc0= -github.com/sagernet/cronet-go/lib/ios_amd64_simulator v0.0.0-20260221041448-e52d68fd87fe h1:HdWJLwa/Ie3jsueJ0O2mZd4V/NP1UJ6bamdcNHWsYEo= -github.com/sagernet/cronet-go/lib/ios_amd64_simulator v0.0.0-20260221041448-e52d68fd87fe/go.mod h1:hkQzRE5GDbaH1/ioqYh0Taho4L6i0yLRCVEZ5xHz5M0= -github.com/sagernet/cronet-go/lib/ios_arm64 v0.0.0-20260221041448-e52d68fd87fe h1:A9PWi2xCI+TCr9ALr+BO76WCCk1JnRyjeEH0/+rdyRc= -github.com/sagernet/cronet-go/lib/ios_arm64 v0.0.0-20260221041448-e52d68fd87fe/go.mod h1:tzVJFTOm66UxLxy6K0ZN5Ic2PC79e+sKKnt+V9puEa4= -github.com/sagernet/cronet-go/lib/ios_arm64_simulator v0.0.0-20260221041448-e52d68fd87fe h1:aMOUWbGjkPBFqObA+uAJOfVuBkHfvz2sibNgOJqjuBs= -github.com/sagernet/cronet-go/lib/ios_arm64_simulator v0.0.0-20260221041448-e52d68fd87fe/go.mod h1:M/pN6m3j0HFU6/y83n0HU6GLYys3tYdr/xTE8hVEGMo= -github.com/sagernet/cronet-go/lib/linux_386 v0.0.0-20260221041448-e52d68fd87fe h1:CzE+sJ2iOvJwOuZhpiDV5VlQrBaNJAZhDCafly+TH9c= -github.com/sagernet/cronet-go/lib/linux_386 v0.0.0-20260221041448-e52d68fd87fe/go.mod h1:cGh5hO6eljCo6KMQ/Cel8Xgq4+etL0awZLRBDVG1EZQ= -github.com/sagernet/cronet-go/lib/linux_386_musl v0.0.0-20260221041448-e52d68fd87fe h1:2grC2CeyUiYVgqG7BGKpJvjFzYv0wL64QMoBqOHVZsI= -github.com/sagernet/cronet-go/lib/linux_386_musl v0.0.0-20260221041448-e52d68fd87fe/go.mod h1:JFE0/cxaKkx0wqPMZU7MgaplQlU0zudv82dROJjClKU= -github.com/sagernet/cronet-go/lib/linux_amd64 v0.0.0-20260221041448-e52d68fd87fe h1:+N9/LauocInR5kxXU+L5bQe1bndCZUC+6L0FaozWZNI= -github.com/sagernet/cronet-go/lib/linux_amd64 v0.0.0-20260221041448-e52d68fd87fe/go.mod h1:vU8VftFeSt7fURCa3JXD6+k6ss1YAX+idQjPvHmJ2tI= -github.com/sagernet/cronet-go/lib/linux_amd64_musl v0.0.0-20260221041448-e52d68fd87fe h1:mRJcjGtKG/eaPL4sZ4Ij+e7aLdg1AEXNI1PgRnxI6H8= -github.com/sagernet/cronet-go/lib/linux_amd64_musl v0.0.0-20260221041448-e52d68fd87fe/go.mod h1:vCe4OUuL+XOUge9v3MyTD45BnuAXiH+DkjN9quDXJzQ= -github.com/sagernet/cronet-go/lib/linux_arm v0.0.0-20260221041448-e52d68fd87fe h1:UkWiTAxUAjTtsu7e52cvMrmbShz+ahTdGkhF9mEIIZU= -github.com/sagernet/cronet-go/lib/linux_arm v0.0.0-20260221041448-e52d68fd87fe/go.mod h1:w9amBWrvjtohQzBGCKJ7LCh22LhTIJs4sE7cYaKQzM0= -github.com/sagernet/cronet-go/lib/linux_arm64 v0.0.0-20260221041448-e52d68fd87fe h1:giJVex0bwZy+DwmPwfZ+NZmafBRTsaZ+QUaD2Fkacxs= -github.com/sagernet/cronet-go/lib/linux_arm64 v0.0.0-20260221041448-e52d68fd87fe/go.mod h1:TqlsFtcYS/etTeck46kHBeT8Le0Igw1Q/AV88UnMS3s= -github.com/sagernet/cronet-go/lib/linux_arm64_musl v0.0.0-20260221041448-e52d68fd87fe h1:XkjAQkciY78eSMF/9VdaWRWb+OfPvoIxVKx5gHGfSIg= -github.com/sagernet/cronet-go/lib/linux_arm64_musl v0.0.0-20260221041448-e52d68fd87fe/go.mod h1:B6Qd0vys8sv9OKVRN6J9RqDzYRGE938Fb2zrYdBDyTQ= -github.com/sagernet/cronet-go/lib/linux_arm_musl v0.0.0-20260221041448-e52d68fd87fe h1:8uDfbPXAL0MWqGI8bm6YJghRmGvK08z4jEIGoODKqTI= -github.com/sagernet/cronet-go/lib/linux_arm_musl v0.0.0-20260221041448-e52d68fd87fe/go.mod h1:3tXMMFY7AHugOVBZ5Al7cL7JKsnFOe5bMVr0hZPk3ow= -github.com/sagernet/cronet-go/lib/linux_loong64 v0.0.0-20260221041448-e52d68fd87fe h1:Ucs4htbATTdG7YGHCyQ4vMYRhltVvsapZ95THRNssr4= -github.com/sagernet/cronet-go/lib/linux_loong64 v0.0.0-20260221041448-e52d68fd87fe/go.mod h1:Wt5uFdU3tnmm8YzobYewwdF7Mt6SucRQg6xeTNWC3Tk= -github.com/sagernet/cronet-go/lib/linux_loong64_musl v0.0.0-20260221041448-e52d68fd87fe h1:oeQjTH4lveV4M7/hqOJFfwQ9UfWvkFZEXTc00R2acuk= -github.com/sagernet/cronet-go/lib/linux_loong64_musl v0.0.0-20260221041448-e52d68fd87fe/go.mod h1:lyIF6wKBLwWa5ZXaAKbAoewewl+yCHo2iYev39Mbj4E= -github.com/sagernet/cronet-go/lib/linux_mips64le v0.0.0-20260221041448-e52d68fd87fe h1:NWABhpSuXcN61hF0CUqwliJXxEbmHidoAHxtB61V3GA= -github.com/sagernet/cronet-go/lib/linux_mips64le v0.0.0-20260221041448-e52d68fd87fe/go.mod h1:H46PnSTTZNcZokLLiDeMDaHiS1l14PH3tzWi0eykjD8= -github.com/sagernet/cronet-go/lib/linux_mipsle v0.0.0-20260221041448-e52d68fd87fe h1:+0VrQdlGR/zLjPzinXFqFR2sdzF2BXoXu7f8xaMuwtg= -github.com/sagernet/cronet-go/lib/linux_mipsle v0.0.0-20260221041448-e52d68fd87fe/go.mod h1:RBhSUDAKWq7fswtV4nQUQhuaTLcX3ettR7teA7/yf2w= -github.com/sagernet/cronet-go/lib/linux_mipsle_musl v0.0.0-20260221041448-e52d68fd87fe h1:DYW55QJOZBI4Znjhc0IiusF+IMg4R2dHPX0KnZC6gSo= -github.com/sagernet/cronet-go/lib/linux_mipsle_musl v0.0.0-20260221041448-e52d68fd87fe/go.mod h1:wRzoIOGG4xbpp3Gh3triLKwMwYriScXzFtunLYhY4w0= -github.com/sagernet/cronet-go/lib/linux_riscv64 v0.0.0-20260221041448-e52d68fd87fe h1:xbbZtyXOxYJMplsyv371ddQb7QrEnyXIIGdUK/3WNTE= -github.com/sagernet/cronet-go/lib/linux_riscv64 v0.0.0-20260221041448-e52d68fd87fe/go.mod h1:LNiZXmWil1OPwKCheqQjtakZlJuKGFz+iv2eGF76Hhs= -github.com/sagernet/cronet-go/lib/linux_riscv64_musl v0.0.0-20260221041448-e52d68fd87fe h1:YSH2lVT+Sn29lQQbwhDpxZvGjVSg80SUfW4JQ8vM3aA= -github.com/sagernet/cronet-go/lib/linux_riscv64_musl v0.0.0-20260221041448-e52d68fd87fe/go.mod h1:YFDGKTkpkJGc5+hnX/RYosZyTWg9h+68VB55fYRRLYc= -github.com/sagernet/cronet-go/lib/tvos_amd64_simulator v0.0.0-20260221041448-e52d68fd87fe h1:gQ1veofYJr8Z1hBVM2PIrn4+EMKvwh+zWpYBr+mxgQ8= -github.com/sagernet/cronet-go/lib/tvos_amd64_simulator v0.0.0-20260221041448-e52d68fd87fe/go.mod h1:aaX0YGl8nhGmfRWI8bc3BtDjY8Vzx6O0cS/e1uqxDq4= -github.com/sagernet/cronet-go/lib/tvos_arm64 v0.0.0-20260221041448-e52d68fd87fe h1:e2TMlbEottRCDfTWxUSw4Jl5dK8IInV02XIvLKVjLbM= -github.com/sagernet/cronet-go/lib/tvos_arm64 v0.0.0-20260221041448-e52d68fd87fe/go.mod h1:EdzMKA96xITc42QEI+ct4SwqX8Dn3ltKK8wzdkLWpSc= -github.com/sagernet/cronet-go/lib/tvos_arm64_simulator v0.0.0-20260221041448-e52d68fd87fe h1:Cgh+DP/Ns1djisz+LFxA1nEhyF6EEU5ZdVxNTkiX2BI= -github.com/sagernet/cronet-go/lib/tvos_arm64_simulator v0.0.0-20260221041448-e52d68fd87fe/go.mod h1:qix4kv1TTAJ5tY4lJ9vjhe9EY4mM+B7H5giOhbxDVcc= -github.com/sagernet/cronet-go/lib/windows_amd64 v0.0.0-20260221041448-e52d68fd87fe h1:VCtjRmkI1IkKdWQ3Jh7j/ze5fhBQJZo1JR70cVKLaKw= -github.com/sagernet/cronet-go/lib/windows_amd64 v0.0.0-20260221041448-e52d68fd87fe/go.mod h1:lm9w/oCCRyBiUa3G8lDQTT8x/ONUvgVR2iV9fVzUZB8= -github.com/sagernet/cronet-go/lib/windows_arm64 v0.0.0-20260221041448-e52d68fd87fe h1:SKePXZMEPUY5zA1VFBPbPOxZsfb/wkMNZAvjPO7hL+I= -github.com/sagernet/cronet-go/lib/windows_arm64 v0.0.0-20260221041448-e52d68fd87fe/go.mod h1:n34YyLgapgjWdKa0IoeczjAFCwD3/dxbsH5sucKw0bw= +github.com/sagernet/cronet-go v0.0.0-20260226034600-34ec1a064c64 h1:2hcUvxlEbzs4hbt9l0oeBpUfet2PHzaV6X6zNTDMkvQ= +github.com/sagernet/cronet-go v0.0.0-20260226034600-34ec1a064c64/go.mod h1:hwFHBEjjthyEquDULbr4c4ucMedp8Drb6Jvm2kt/0Bw= +github.com/sagernet/cronet-go/all v0.0.0-20260226034600-34ec1a064c64 h1:f5TU9VAbhtm/SMLKctjMiSNUoQso4S6kEPUm5yNglNo= +github.com/sagernet/cronet-go/all v0.0.0-20260226034600-34ec1a064c64/go.mod h1:ohbVnfJvBzdv7R87Nz0fAmkLSTF9lCKrQC2rIqsQPY4= +github.com/sagernet/cronet-go/lib/android_386 v0.0.0-20260226033953-5745aabe7717 h1:vtE5zVWFQuNls2jHb5edFCFYJblGY9qrqTVpoW2V/h4= +github.com/sagernet/cronet-go/lib/android_386 v0.0.0-20260226033953-5745aabe7717/go.mod h1:XXDwdjX/T8xftoeJxQmbBoYXZp8MAPFR2CwbFuTpEtw= +github.com/sagernet/cronet-go/lib/android_amd64 v0.0.0-20260226033953-5745aabe7717 h1:+d5efMdtHbizXb4Vuai/11uNpWXmwOCfVgQcICA3kgk= +github.com/sagernet/cronet-go/lib/android_amd64 v0.0.0-20260226033953-5745aabe7717/go.mod h1:iNiUGoLtnr8/JTuVNj7XJbmpOAp2C6+B81KDrPxwaZM= +github.com/sagernet/cronet-go/lib/android_arm v0.0.0-20260226033953-5745aabe7717 h1:6BYObS6w5sWnNLChKT1fOYJnJt/+p6du8fSyDb3DLwo= +github.com/sagernet/cronet-go/lib/android_arm v0.0.0-20260226033953-5745aabe7717/go.mod h1:19ILNUOGIzRdOqa2mq+iY0JoHxuieB7/lnjYeaA2vEc= +github.com/sagernet/cronet-go/lib/android_arm64 v0.0.0-20260226033953-5745aabe7717 h1:UbgjfMai+duPsftAT94zr4KcnACuJhjaxQkpup6TWLk= +github.com/sagernet/cronet-go/lib/android_arm64 v0.0.0-20260226033953-5745aabe7717/go.mod h1:JxzGyQf94Cr6sBShKqODGDyRUlESfJK/Njcz9Lz6qMQ= +github.com/sagernet/cronet-go/lib/darwin_amd64 v0.0.0-20260226033953-5745aabe7717 h1:KRrzFzsWWgy8XPHfp2hEX7wTuc7ILQZiFKIATvuyCHU= +github.com/sagernet/cronet-go/lib/darwin_amd64 v0.0.0-20260226033953-5745aabe7717/go.mod h1:KN+9T9TBycGOLzmKU4QdcHAJEj6Nlx48ifnlTvvHMvs= +github.com/sagernet/cronet-go/lib/darwin_arm64 v0.0.0-20260226033953-5745aabe7717 h1:bTp8j/GqUsS0P2aaTcbs7alSvUoywx+YIWyoCcVA05I= +github.com/sagernet/cronet-go/lib/darwin_arm64 v0.0.0-20260226033953-5745aabe7717/go.mod h1:kojvtUc29KKnk8hs2QIANynVR59921SnGWA9kXohHc0= +github.com/sagernet/cronet-go/lib/ios_amd64_simulator v0.0.0-20260226033953-5745aabe7717 h1:PKuCYfGpSfnzgRJjRR5em/yU5SoI4Yvx3r0C2k1Ksh4= +github.com/sagernet/cronet-go/lib/ios_amd64_simulator v0.0.0-20260226033953-5745aabe7717/go.mod h1:hkQzRE5GDbaH1/ioqYh0Taho4L6i0yLRCVEZ5xHz5M0= +github.com/sagernet/cronet-go/lib/ios_arm64 v0.0.0-20260226033953-5745aabe7717 h1:w5ytvTm42ncUIFbLueN/ilp2ZaHrr5GC76Kc/Oxw4qI= +github.com/sagernet/cronet-go/lib/ios_arm64 v0.0.0-20260226033953-5745aabe7717/go.mod h1:tzVJFTOm66UxLxy6K0ZN5Ic2PC79e+sKKnt+V9puEa4= +github.com/sagernet/cronet-go/lib/ios_arm64_simulator v0.0.0-20260226033953-5745aabe7717 h1:2BjQH02cCF6spz/WG8bJHBPhZtF4Or5D73L+n5fZbNE= +github.com/sagernet/cronet-go/lib/ios_arm64_simulator v0.0.0-20260226033953-5745aabe7717/go.mod h1:M/pN6m3j0HFU6/y83n0HU6GLYys3tYdr/xTE8hVEGMo= +github.com/sagernet/cronet-go/lib/linux_386 v0.0.0-20260226033953-5745aabe7717 h1:N9KUwDODj5eP5uqdSmbMufml2nGPc7oX4H5NPAjADIs= +github.com/sagernet/cronet-go/lib/linux_386 v0.0.0-20260226033953-5745aabe7717/go.mod h1:cGh5hO6eljCo6KMQ/Cel8Xgq4+etL0awZLRBDVG1EZQ= +github.com/sagernet/cronet-go/lib/linux_386_musl v0.0.0-20260226033953-5745aabe7717 h1:v2p6tqpQVI6RR1HamuJmkz01Ght4miQ79YhzQtOYowk= +github.com/sagernet/cronet-go/lib/linux_386_musl v0.0.0-20260226033953-5745aabe7717/go.mod h1:JFE0/cxaKkx0wqPMZU7MgaplQlU0zudv82dROJjClKU= +github.com/sagernet/cronet-go/lib/linux_amd64 v0.0.0-20260226033953-5745aabe7717 h1:glPUIWUUAlOII+L0UI7/JAJ8o0wqAT7qVmWB4AcPyWs= +github.com/sagernet/cronet-go/lib/linux_amd64 v0.0.0-20260226033953-5745aabe7717/go.mod h1:vU8VftFeSt7fURCa3JXD6+k6ss1YAX+idQjPvHmJ2tI= +github.com/sagernet/cronet-go/lib/linux_amd64_musl v0.0.0-20260226033953-5745aabe7717 h1:0QKgSc5nBrR6H1ImsOlaBbVQ7onoFhwxTBwiOnUn0es= +github.com/sagernet/cronet-go/lib/linux_amd64_musl v0.0.0-20260226033953-5745aabe7717/go.mod h1:vCe4OUuL+XOUge9v3MyTD45BnuAXiH+DkjN9quDXJzQ= +github.com/sagernet/cronet-go/lib/linux_arm v0.0.0-20260226033953-5745aabe7717 h1:DsrfMoWf05lLrwdo0s/6wAC/4smeDgT4+t/iJtwGD+g= +github.com/sagernet/cronet-go/lib/linux_arm v0.0.0-20260226033953-5745aabe7717/go.mod h1:w9amBWrvjtohQzBGCKJ7LCh22LhTIJs4sE7cYaKQzM0= +github.com/sagernet/cronet-go/lib/linux_arm64 v0.0.0-20260226033953-5745aabe7717 h1:bYqI37NWgvxVBeWL50/ts23uGiyHv7QfH/Ylu5lvgLs= +github.com/sagernet/cronet-go/lib/linux_arm64 v0.0.0-20260226033953-5745aabe7717/go.mod h1:TqlsFtcYS/etTeck46kHBeT8Le0Igw1Q/AV88UnMS3s= +github.com/sagernet/cronet-go/lib/linux_arm64_musl v0.0.0-20260226033953-5745aabe7717 h1:zg8keyQA2sniD4gqMwbUVdf57M1cmGobumOtZy1CYJs= +github.com/sagernet/cronet-go/lib/linux_arm64_musl v0.0.0-20260226033953-5745aabe7717/go.mod h1:B6Qd0vys8sv9OKVRN6J9RqDzYRGE938Fb2zrYdBDyTQ= +github.com/sagernet/cronet-go/lib/linux_arm_musl v0.0.0-20260226033953-5745aabe7717 h1:cgyVkTyccMGiCayGgcvfc+q0b5GdhqSk+3UMmGhlCi0= +github.com/sagernet/cronet-go/lib/linux_arm_musl v0.0.0-20260226033953-5745aabe7717/go.mod h1:3tXMMFY7AHugOVBZ5Al7cL7JKsnFOe5bMVr0hZPk3ow= +github.com/sagernet/cronet-go/lib/linux_loong64 v0.0.0-20260226033953-5745aabe7717 h1:anuE3B73oIvDOGJGvenfkQTm3NY2vL84aM062t8DZ4Y= +github.com/sagernet/cronet-go/lib/linux_loong64 v0.0.0-20260226033953-5745aabe7717/go.mod h1:Wt5uFdU3tnmm8YzobYewwdF7Mt6SucRQg6xeTNWC3Tk= +github.com/sagernet/cronet-go/lib/linux_loong64_musl v0.0.0-20260226033953-5745aabe7717 h1:kYN/amWzLOZMm5evPwlmumnswBNPeFZiKINKP73AsuA= +github.com/sagernet/cronet-go/lib/linux_loong64_musl v0.0.0-20260226033953-5745aabe7717/go.mod h1:lyIF6wKBLwWa5ZXaAKbAoewewl+yCHo2iYev39Mbj4E= +github.com/sagernet/cronet-go/lib/linux_mips64le v0.0.0-20260226033953-5745aabe7717 h1:S7rlC1Knzs3+It2u6AnhGUgiLU1QUzvoV3JXWvwE4n8= +github.com/sagernet/cronet-go/lib/linux_mips64le v0.0.0-20260226033953-5745aabe7717/go.mod h1:H46PnSTTZNcZokLLiDeMDaHiS1l14PH3tzWi0eykjD8= +github.com/sagernet/cronet-go/lib/linux_mipsle v0.0.0-20260226033953-5745aabe7717 h1:FeyB5ZyFHAWkU1DETmUjLEM9GUFWoIndV8usT4AjGOk= +github.com/sagernet/cronet-go/lib/linux_mipsle v0.0.0-20260226033953-5745aabe7717/go.mod h1:RBhSUDAKWq7fswtV4nQUQhuaTLcX3ettR7teA7/yf2w= +github.com/sagernet/cronet-go/lib/linux_mipsle_musl v0.0.0-20260226033953-5745aabe7717 h1:loU7PsyqI7dplbFGjQKoMT4IVYuzVyfW88FIq+7gbmY= +github.com/sagernet/cronet-go/lib/linux_mipsle_musl v0.0.0-20260226033953-5745aabe7717/go.mod h1:wRzoIOGG4xbpp3Gh3triLKwMwYriScXzFtunLYhY4w0= +github.com/sagernet/cronet-go/lib/linux_riscv64 v0.0.0-20260226033953-5745aabe7717 h1:XSVrZ18XauiYMf+G0CzZETteQF0r1NOoA1gVXlZWjUI= +github.com/sagernet/cronet-go/lib/linux_riscv64 v0.0.0-20260226033953-5745aabe7717/go.mod h1:LNiZXmWil1OPwKCheqQjtakZlJuKGFz+iv2eGF76Hhs= +github.com/sagernet/cronet-go/lib/linux_riscv64_musl v0.0.0-20260226033953-5745aabe7717 h1:oTRK4T5pQ1ZYQh7Avr5u3bsDnXkloSVqwBljRy8FHOY= +github.com/sagernet/cronet-go/lib/linux_riscv64_musl v0.0.0-20260226033953-5745aabe7717/go.mod h1:YFDGKTkpkJGc5+hnX/RYosZyTWg9h+68VB55fYRRLYc= +github.com/sagernet/cronet-go/lib/tvos_amd64_simulator v0.0.0-20260226033953-5745aabe7717 h1:J18xRmUa9lle+Y6pYkQ7OMq2B9eox5Bmm4MkbuQPQm0= +github.com/sagernet/cronet-go/lib/tvos_amd64_simulator v0.0.0-20260226033953-5745aabe7717/go.mod h1:aaX0YGl8nhGmfRWI8bc3BtDjY8Vzx6O0cS/e1uqxDq4= +github.com/sagernet/cronet-go/lib/tvos_arm64 v0.0.0-20260226033953-5745aabe7717 h1:PC9gKeDN3wmcFxwiBEM57W0YwEz1uFGqawwssEQe494= +github.com/sagernet/cronet-go/lib/tvos_arm64 v0.0.0-20260226033953-5745aabe7717/go.mod h1:EdzMKA96xITc42QEI+ct4SwqX8Dn3ltKK8wzdkLWpSc= +github.com/sagernet/cronet-go/lib/tvos_arm64_simulator v0.0.0-20260226033953-5745aabe7717 h1:STlbMnsydaymby26m3wNfeYYI7HoiZ6+wxQ75Si1g8E= +github.com/sagernet/cronet-go/lib/tvos_arm64_simulator v0.0.0-20260226033953-5745aabe7717/go.mod h1:qix4kv1TTAJ5tY4lJ9vjhe9EY4mM+B7H5giOhbxDVcc= +github.com/sagernet/cronet-go/lib/windows_amd64 v0.0.0-20260226033953-5745aabe7717 h1:qWtpoBxmHyb49IRtMAFkJIRlL4KCYW5Fe6YptYhItpM= +github.com/sagernet/cronet-go/lib/windows_amd64 v0.0.0-20260226033953-5745aabe7717/go.mod h1:lm9w/oCCRyBiUa3G8lDQTT8x/ONUvgVR2iV9fVzUZB8= +github.com/sagernet/cronet-go/lib/windows_arm64 v0.0.0-20260226033953-5745aabe7717 h1:7ohuWJ0PswrU7Xw/xfL6OrIh7sXybGNOgh6DaL+urdY= +github.com/sagernet/cronet-go/lib/windows_arm64 v0.0.0-20260226033953-5745aabe7717/go.mod h1:n34YyLgapgjWdKa0IoeczjAFCwD3/dxbsH5sucKw0bw= github.com/sagernet/fswatch v0.1.1 h1:YqID+93B7VRfqIH3PArW/XpJv5H4OLEVWDfProGoRQs= github.com/sagernet/fswatch v0.1.1/go.mod h1:nz85laH0mkQqJfaOrqPpkwtU1znMFNVTpT/5oRsVz/o= github.com/sagernet/gomobile v0.1.11 h1:niMQAspvuThup5eRZQpsGcbM76zAvnsGr7RUIpnQMDQ= diff --git a/include/oom_killer.go b/include/oom_killer.go new file mode 100644 index 000000000..3f70d9d0e --- /dev/null +++ b/include/oom_killer.go @@ -0,0 +1,10 @@ +package include + +import ( + "github.com/sagernet/sing-box/adapter/service" + "github.com/sagernet/sing-box/service/oomkiller" +) + +func registerOOMKillerService(registry *service.Registry) { + oomkiller.RegisterService(registry) +} diff --git a/include/registry.go b/include/registry.go index d909b8500..64a49b61a 100644 --- a/include/registry.go +++ b/include/registry.go @@ -137,6 +137,7 @@ func ServiceRegistry() *service.Registry { registerDERPService(registry) registerCCMService(registry) registerOCMService(registry) + registerOOMKillerService(registry) return registry } diff --git a/option/oom_killer.go b/option/oom_killer.go new file mode 100644 index 000000000..9fbbde848 --- /dev/null +++ b/option/oom_killer.go @@ -0,0 +1,3 @@ +package option + +type OOMKillerServiceOptions struct{} diff --git a/protocol/naive/outbound.go b/protocol/naive/outbound.go index dcc1aec52..8249a1fef 100644 --- a/protocol/naive/outbound.go +++ b/protocol/naive/outbound.go @@ -254,6 +254,10 @@ func (h *Outbound) ListenPacket(ctx context.Context, destination M.Socksaddr) (n return h.uotClient.ListenPacket(ctx, destination) } +func (h *Outbound) InterfaceUpdated() { + h.client.Engine().CloseAllConnections() +} + func (h *Outbound) Close() error { return h.client.Close() } diff --git a/route/conn.go b/route/conn.go index 3e9c831c1..899d29391 100644 --- a/route/conn.go +++ b/route/conn.go @@ -44,16 +44,52 @@ func (m *ConnectionManager) Start(stage adapter.StartStage) error { return nil } -func (m *ConnectionManager) Close() error { +func (m *ConnectionManager) Count() int { + return m.connections.Len() +} + +func (m *ConnectionManager) CloseAll() { m.access.Lock() - defer m.access.Unlock() - for element := m.connections.Front(); element != nil; element = element.Next() { - common.Close(element.Value) + var closers []io.Closer + for element := m.connections.Front(); element != nil; { + nextElement := element.Next() + closers = append(closers, element.Value) + m.connections.Remove(element) + element = nextElement } - m.connections.Init() + m.access.Unlock() + for _, closer := range closers { + common.Close(closer) + } +} + +func (m *ConnectionManager) Close() error { + m.CloseAll() return nil } +func (m *ConnectionManager) TrackConn(conn net.Conn) net.Conn { + m.access.Lock() + element := m.connections.PushBack(conn) + m.access.Unlock() + return &trackedConn{ + Conn: conn, + manager: m, + element: element, + } +} + +func (m *ConnectionManager) TrackPacketConn(conn net.PacketConn) net.PacketConn { + m.access.Lock() + element := m.connections.PushBack(conn) + m.access.Unlock() + return &trackedPacketConn{ + PacketConn: conn, + manager: m, + element: element, + } +} + func (m *ConnectionManager) NewConnection(ctx context.Context, this N.Dialer, conn net.Conn, metadata adapter.InboundContext, onClose N.CloseHandlerFunc) { ctx = adapter.WithContext(ctx, &metadata) var ( @@ -92,14 +128,6 @@ func (m *ConnectionManager) NewConnection(ctx context.Context, this N.Dialer, co if metadata.TLSFragment || metadata.TLSRecordFragment { remoteConn = tf.NewConn(remoteConn, ctx, metadata.TLSFragment, metadata.TLSRecordFragment, metadata.TLSFragmentFallbackDelay) } - m.access.Lock() - element := m.connections.PushBack(conn) - m.access.Unlock() - onClose = N.AppendClose(onClose, func(it error) { - m.access.Lock() - defer m.access.Unlock() - m.connections.Remove(element) - }) var done atomic.Bool if m.kickWriteHandshake(ctx, conn, remoteConn, false, &done, onClose) { return @@ -216,14 +244,6 @@ func (m *ConnectionManager) NewPacketConnection(ctx context.Context, this N.Dial ctx, conn = canceler.NewPacketConn(ctx, conn, udpTimeout) } destination := bufio.NewPacketConn(remotePacketConn) - m.access.Lock() - element := m.connections.PushBack(conn) - m.access.Unlock() - onClose = N.AppendClose(onClose, func(it error) { - m.access.Lock() - defer m.access.Unlock() - m.connections.Remove(element) - }) var done atomic.Bool go m.packetConnectionCopy(ctx, conn, destination, false, &done, onClose) go m.packetConnectionCopy(ctx, destination, conn, true, &done, onClose) @@ -242,7 +262,9 @@ func (m *ConnectionManager) connectionCopy(ctx context.Context, source net.Conn, destination.Close() } if done.Swap(true) { - onClose(err) + if onClose != nil { + onClose(err) + } common.Close(source, destination) } if !direction { @@ -303,7 +325,9 @@ func (m *ConnectionManager) kickWriteHandshake(ctx context.Context, source net.C return false } if !done.Swap(true) { - onClose(err) + if onClose != nil { + onClose(err) + } } common.Close(source, destination) if !direction { @@ -334,7 +358,59 @@ func (m *ConnectionManager) packetConnectionCopy(ctx context.Context, source N.P } } if !done.Swap(true) { - onClose(err) + if onClose != nil { + onClose(err) + } } common.Close(source, destination) } + +type trackedConn struct { + net.Conn + manager *ConnectionManager + element *list.Element[io.Closer] +} + +func (c *trackedConn) Close() error { + c.manager.access.Lock() + c.manager.connections.Remove(c.element) + c.manager.access.Unlock() + return c.Conn.Close() +} + +func (c *trackedConn) Upstream() any { + return c.Conn +} + +func (c *trackedConn) ReaderReplaceable() bool { + return true +} + +func (c *trackedConn) WriterReplaceable() bool { + return true +} + +type trackedPacketConn struct { + net.PacketConn + manager *ConnectionManager + element *list.Element[io.Closer] +} + +func (c *trackedPacketConn) Close() error { + c.manager.access.Lock() + c.manager.connections.Remove(c.element) + c.manager.access.Unlock() + return c.PacketConn.Close() +} + +func (c *trackedPacketConn) Upstream() any { + return bufio.NewPacketConn(c.PacketConn) +} + +func (c *trackedPacketConn) ReaderReplaceable() bool { + return true +} + +func (c *trackedPacketConn) WriterReplaceable() bool { + return true +} diff --git a/route/network.go b/route/network.go index b53142b57..b8eefdc06 100644 --- a/route/network.go +++ b/route/network.go @@ -13,7 +13,6 @@ import ( "time" "github.com/sagernet/sing-box/adapter" - "github.com/sagernet/sing-box/common/conntrack" "github.com/sagernet/sing-box/common/settings" "github.com/sagernet/sing-box/common/taskmonitor" C "github.com/sagernet/sing-box/constant" @@ -48,6 +47,7 @@ type NetworkManager struct { powerListener winpowrprof.EventListener pauseManager pause.Manager platformInterface adapter.PlatformInterface + connectionManager adapter.ConnectionManager endpoint adapter.EndpointManager inbound adapter.InboundManager outbound adapter.OutboundManager @@ -90,6 +90,7 @@ func NewNetworkManager(ctx context.Context, logger logger.ContextLogger, options }, pauseManager: service.FromContext[pause.Manager](ctx), platformInterface: service.FromContext[adapter.PlatformInterface](ctx), + connectionManager: service.FromContext[adapter.ConnectionManager](ctx), endpoint: service.FromContext[adapter.EndpointManager](ctx), inbound: service.FromContext[adapter.InboundManager](ctx), outbound: service.FromContext[adapter.OutboundManager](ctx), @@ -450,7 +451,9 @@ func (r *NetworkManager) UpdateWIFIState() { } func (r *NetworkManager) ResetNetwork() { - conntrack.Close() + if r.connectionManager != nil { + r.connectionManager.CloseAll() + } for _, endpoint := range r.endpoint.Endpoints() { listener, isListener := endpoint.(adapter.InterfaceUpdateListener) diff --git a/route/route.go b/route/route.go index fd025a1b3..240d0343a 100644 --- a/route/route.go +++ b/route/route.go @@ -9,7 +9,6 @@ import ( "time" "github.com/sagernet/sing-box/adapter" - "github.com/sagernet/sing-box/common/conntrack" "github.com/sagernet/sing-box/common/process" "github.com/sagernet/sing-box/common/sniff" C "github.com/sagernet/sing-box/constant" @@ -80,7 +79,6 @@ func (r *Router) routeConnection(ctx context.Context, conn net.Conn, metadata ad injectable.NewConnectionEx(ctx, conn, metadata, onClose) return nil } - conntrack.KillerCheck() metadata.Network = N.NetworkTCP switch metadata.Destination.Fqdn { case mux.Destination.Fqdn: @@ -216,8 +214,6 @@ func (r *Router) routePacketConnection(ctx context.Context, conn N.PacketConn, m injectable.NewPacketConnectionEx(ctx, conn, metadata, onClose) return nil } - conntrack.KillerCheck() - // TODO: move to UoT metadata.Network = N.NetworkUDP diff --git a/service/oomkiller/service.go b/service/oomkiller/service.go new file mode 100644 index 000000000..fb486ab9a --- /dev/null +++ b/service/oomkiller/service.go @@ -0,0 +1,138 @@ +//go:build darwin && cgo + +package oomkiller + +/* +#include + +static dispatch_source_t memoryPressureSource; + +extern void goMemoryPressureCallback(unsigned long status); + +static void startMemoryPressureMonitor() { + memoryPressureSource = dispatch_source_create( + DISPATCH_SOURCE_TYPE_MEMORYPRESSURE, + 0, + DISPATCH_MEMORYPRESSURE_WARN | DISPATCH_MEMORYPRESSURE_CRITICAL, + dispatch_get_global_queue(QOS_CLASS_DEFAULT, 0) + ); + dispatch_source_set_event_handler(memoryPressureSource, ^{ + unsigned long status = dispatch_source_get_data(memoryPressureSource); + goMemoryPressureCallback(status); + }); + dispatch_activate(memoryPressureSource); +} + +static void stopMemoryPressureMonitor() { + if (memoryPressureSource) { + dispatch_source_cancel(memoryPressureSource); + memoryPressureSource = NULL; + } +} +*/ +import "C" + +import ( + "context" + runtimeDebug "runtime/debug" + "sync" + + "github.com/sagernet/sing-box/adapter" + boxService "github.com/sagernet/sing-box/adapter/service" + boxConstant "github.com/sagernet/sing-box/constant" + "github.com/sagernet/sing-box/log" + "github.com/sagernet/sing-box/option" + "github.com/sagernet/sing/common/memory" + "github.com/sagernet/sing/service" +) + +func RegisterService(registry *boxService.Registry) { + boxService.Register[option.OOMKillerServiceOptions](registry, boxConstant.TypeOOMKiller, NewService) +} + +var ( + globalAccess sync.Mutex + globalServices []*Service +) + +type Service struct { + boxService.Adapter + logger log.ContextLogger + router adapter.Router +} + +func NewService(ctx context.Context, logger log.ContextLogger, tag string, options option.OOMKillerServiceOptions) (adapter.Service, error) { + return &Service{ + Adapter: boxService.NewAdapter(boxConstant.TypeOOMKiller, tag), + logger: logger, + router: service.FromContext[adapter.Router](ctx), + }, nil +} + +func (s *Service) Start(stage adapter.StartStage) error { + if stage != adapter.StartStateStart { + return nil + } + globalAccess.Lock() + isFirst := len(globalServices) == 0 + globalServices = append(globalServices, s) + globalAccess.Unlock() + if isFirst { + C.startMemoryPressureMonitor() + } + s.logger.Info("started memory pressure monitor") + return nil +} + +func (s *Service) Close() error { + globalAccess.Lock() + for i, service := range globalServices { + if service == s { + globalServices = append(globalServices[:i], globalServices[i+1:]...) + break + } + } + isLast := len(globalServices) == 0 + globalAccess.Unlock() + if isLast { + C.stopMemoryPressureMonitor() + } + return nil +} + +//export goMemoryPressureCallback +func goMemoryPressureCallback(status C.ulong) { + globalAccess.Lock() + services := make([]*Service, len(globalServices)) + copy(services, globalServices) + globalAccess.Unlock() + if len(services) == 0 { + return + } + criticalFlag := C.ulong(C.DISPATCH_MEMORYPRESSURE_CRITICAL) + warnFlag := C.ulong(C.DISPATCH_MEMORYPRESSURE_WARN) + isCritical := status&criticalFlag != 0 + isWarning := status&warnFlag != 0 + var level string + switch { + case isCritical: + level = "critical" + case isWarning: + level = "warning" + default: + level = "normal" + } + for _, s := range services { + if isCritical { + s.logger.Error("memory pressure: ", level, ", usage: ", memory.Total()/(1024*1024), " MiB, resetting network") + s.router.ResetNetwork() + } else if isWarning { + s.logger.Warn("memory pressure: ", level, ", usage: ", memory.Total()/(1024*1024), " MiB") + } else { + s.logger.Debug("memory pressure: ", level, ", usage: ", memory.Total()/(1024*1024), " MiB") + } + } + if isCritical { + runtimeDebug.FreeOSMemory() + } +} diff --git a/service/oomkiller/service_stub.go b/service/oomkiller/service_stub.go new file mode 100644 index 000000000..425f525e7 --- /dev/null +++ b/service/oomkiller/service_stub.go @@ -0,0 +1,39 @@ +//go:build !darwin || !cgo + +package oomkiller + +import ( + "context" + + "github.com/sagernet/sing-box/adapter" + boxService "github.com/sagernet/sing-box/adapter/service" + C "github.com/sagernet/sing-box/constant" + "github.com/sagernet/sing-box/log" + "github.com/sagernet/sing-box/option" + E "github.com/sagernet/sing/common/exceptions" +) + +func RegisterService(registry *boxService.Registry) { + boxService.Register[option.OOMKillerServiceOptions](registry, C.TypeOOMKiller, NewService) +} + +type Service struct { + boxService.Adapter +} + +func NewService(ctx context.Context, logger log.ContextLogger, tag string, options option.OOMKillerServiceOptions) (adapter.Service, error) { + return &Service{ + Adapter: boxService.NewAdapter(C.TypeOOMKiller, tag), + }, nil +} + +func (s *Service) Start(stage adapter.StartStage) error { + if stage != adapter.StartStateStart { + return nil + } + return E.New("memory pressure monitoring is not available on this platform") +} + +func (s *Service) Close() error { + return nil +}