mirror of
https://github.com/SagerNet/sing-box.git
synced 2024-11-29 12:01:29 +00:00
Remove urltest outbound
This commit is contained in:
parent
c240f1b359
commit
c0a2f77258
|
@ -25,3 +25,10 @@ type OutboundGroup interface {
|
||||||
Now() string
|
Now() string
|
||||||
All() []string
|
All() []string
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func OutboundTag(detour Outbound) string {
|
||||||
|
if group, isGroup := detour.(OutboundGroup); isGroup {
|
||||||
|
return group.Now()
|
||||||
|
}
|
||||||
|
return detour.Tag()
|
||||||
|
}
|
||||||
|
|
|
@ -6,7 +6,6 @@ import (
|
||||||
"net/netip"
|
"net/netip"
|
||||||
|
|
||||||
"github.com/sagernet/sing-box/common/geoip"
|
"github.com/sagernet/sing-box/common/geoip"
|
||||||
"github.com/sagernet/sing-box/common/urltest"
|
|
||||||
"github.com/sagernet/sing-dns"
|
"github.com/sagernet/sing-dns"
|
||||||
"github.com/sagernet/sing/common/control"
|
"github.com/sagernet/sing/common/control"
|
||||||
N "github.com/sagernet/sing/common/network"
|
N "github.com/sagernet/sing/common/network"
|
||||||
|
@ -40,7 +39,6 @@ type Router interface {
|
||||||
|
|
||||||
Rules() []Rule
|
Rules() []Rule
|
||||||
SetTrafficController(controller TrafficController)
|
SetTrafficController(controller TrafficController)
|
||||||
URLTestHistoryStorage(create bool) *urltest.HistoryStorage
|
|
||||||
}
|
}
|
||||||
|
|
||||||
type Rule interface {
|
type Rule interface {
|
||||||
|
|
|
@ -16,5 +16,4 @@ const (
|
||||||
|
|
||||||
const (
|
const (
|
||||||
TypeSelector = "selector"
|
TypeSelector = "selector"
|
||||||
TypeURLTest = "urltest"
|
|
||||||
)
|
)
|
||||||
|
|
|
@ -22,7 +22,6 @@
|
||||||
| `shadowsocks` | [Shadowsocks](./shadowsocks) |
|
| `shadowsocks` | [Shadowsocks](./shadowsocks) |
|
||||||
| `dns` | [DNS](./dns) |
|
| `dns` | [DNS](./dns) |
|
||||||
| `selector` | [Selector](./selector) |
|
| `selector` | [Selector](./selector) |
|
||||||
| `urltest` | [URLTest](./urltest) |
|
|
||||||
|
|
||||||
#### tag
|
#### tag
|
||||||
|
|
||||||
|
|
|
@ -1,41 +0,0 @@
|
||||||
### Structure
|
|
||||||
|
|
||||||
```json
|
|
||||||
{
|
|
||||||
"outbounds": [
|
|
||||||
{
|
|
||||||
"type": "urltest",
|
|
||||||
"tag": "auto",
|
|
||||||
|
|
||||||
"outbounds": [
|
|
||||||
"proxy-a",
|
|
||||||
"proxy-b",
|
|
||||||
"proxy-c"
|
|
||||||
],
|
|
||||||
"url": "http://www.gstatic.com/generate_204",
|
|
||||||
"interval": "1m",
|
|
||||||
"tolerance": 50
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
### Fields
|
|
||||||
|
|
||||||
#### outbounds
|
|
||||||
|
|
||||||
==Required==
|
|
||||||
|
|
||||||
List of outbound tags to test.
|
|
||||||
|
|
||||||
#### url
|
|
||||||
|
|
||||||
The URL to test. `http://www.gstatic.com/generate_204` will be used if empty.
|
|
||||||
|
|
||||||
#### interval
|
|
||||||
|
|
||||||
The test interval. `1m` will be used if empty.
|
|
||||||
|
|
||||||
#### tolerance
|
|
||||||
|
|
||||||
The test tolerance in milliseconds. `50` will be used if empty.
|
|
|
@ -77,16 +77,13 @@ func proxyInfo(server *Server, detour adapter.Outbound) *badjson.JSONObject {
|
||||||
case C.TypeSelector:
|
case C.TypeSelector:
|
||||||
clashType = "Selector"
|
clashType = "Selector"
|
||||||
isGroup = true
|
isGroup = true
|
||||||
case C.TypeURLTest:
|
|
||||||
clashType = "URLTest"
|
|
||||||
isGroup = true
|
|
||||||
default:
|
default:
|
||||||
clashType = "Unknown"
|
clashType = "Unknown"
|
||||||
}
|
}
|
||||||
info.Put("type", clashType)
|
info.Put("type", clashType)
|
||||||
info.Put("name", detour.Tag())
|
info.Put("name", detour.Tag())
|
||||||
info.Put("udp", common.Contains(detour.Network(), C.NetworkUDP))
|
info.Put("udp", common.Contains(detour.Network(), C.NetworkUDP))
|
||||||
delayHistory := server.router.URLTestHistoryStorage(false).LoadURLTestHistory(outbound.RealTag(detour))
|
delayHistory := server.urlTestHistory.LoadURLTestHistory(adapter.OutboundTag(detour))
|
||||||
if delayHistory != nil {
|
if delayHistory != nil {
|
||||||
info.Put("history", []*urltest.History{delayHistory})
|
info.Put("history", []*urltest.History{delayHistory})
|
||||||
} else {
|
} else {
|
||||||
|
@ -218,9 +215,9 @@ func getProxyDelay(server *Server) func(w http.ResponseWriter, r *http.Request)
|
||||||
defer func() {
|
defer func() {
|
||||||
realTag := outbound.RealTag(proxy)
|
realTag := outbound.RealTag(proxy)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
server.router.URLTestHistoryStorage(true).DeleteURLTestHistory(realTag)
|
server.urlTestHistory.DeleteURLTestHistory(realTag)
|
||||||
} else {
|
} else {
|
||||||
server.router.URLTestHistoryStorage(true).StoreURLTestHistory(realTag, &urltest.History{
|
server.urlTestHistory.StoreURLTestHistory(realTag, &urltest.History{
|
||||||
Time: time.Now(),
|
Time: time.Now(),
|
||||||
Delay: delay,
|
Delay: delay,
|
||||||
})
|
})
|
||||||
|
|
|
@ -12,6 +12,7 @@ import (
|
||||||
|
|
||||||
"github.com/sagernet/sing-box/adapter"
|
"github.com/sagernet/sing-box/adapter"
|
||||||
"github.com/sagernet/sing-box/common/json"
|
"github.com/sagernet/sing-box/common/json"
|
||||||
|
"github.com/sagernet/sing-box/common/urltest"
|
||||||
C "github.com/sagernet/sing-box/constant"
|
C "github.com/sagernet/sing-box/constant"
|
||||||
"github.com/sagernet/sing-box/experimental/clashapi/trafficontrol"
|
"github.com/sagernet/sing-box/experimental/clashapi/trafficontrol"
|
||||||
"github.com/sagernet/sing-box/log"
|
"github.com/sagernet/sing-box/log"
|
||||||
|
@ -33,6 +34,7 @@ type Server struct {
|
||||||
logger log.Logger
|
logger log.Logger
|
||||||
httpServer *http.Server
|
httpServer *http.Server
|
||||||
trafficManager *trafficontrol.Manager
|
trafficManager *trafficontrol.Manager
|
||||||
|
urlTestHistory *urltest.HistoryStorage
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewServer(router adapter.Router, logFactory log.ObservableFactory, options option.ClashAPIOptions) *Server {
|
func NewServer(router adapter.Router, logFactory log.ObservableFactory, options option.ClashAPIOptions) *Server {
|
||||||
|
@ -46,6 +48,7 @@ func NewServer(router adapter.Router, logFactory log.ObservableFactory, options
|
||||||
Handler: chiRouter,
|
Handler: chiRouter,
|
||||||
},
|
},
|
||||||
trafficManager,
|
trafficManager,
|
||||||
|
urltest.NewHistoryStorage(),
|
||||||
}
|
}
|
||||||
cors := cors.New(cors.Options{
|
cors := cors.New(cors.Options{
|
||||||
AllowedOrigins: []string{"*"},
|
AllowedOrigins: []string{"*"},
|
||||||
|
|
|
@ -57,7 +57,6 @@ nav:
|
||||||
- Shadowsocks: configuration/outbound/shadowsocks.md
|
- Shadowsocks: configuration/outbound/shadowsocks.md
|
||||||
- DNS: configuration/outbound/dns.md
|
- DNS: configuration/outbound/dns.md
|
||||||
- Selector: configuration/outbound/selector.md
|
- Selector: configuration/outbound/selector.md
|
||||||
- URLTest: configuration/outbound/urltest.md
|
|
||||||
- Route:
|
- Route:
|
||||||
- configuration/route/index.md
|
- configuration/route/index.md
|
||||||
- GeoIP: configuration/route/geoip.md
|
- GeoIP: configuration/route/geoip.md
|
||||||
|
|
|
@ -10,10 +10,3 @@ type SelectorOutboundOptions struct {
|
||||||
Outbounds []string `json:"outbounds"`
|
Outbounds []string `json:"outbounds"`
|
||||||
Default string `json:"default,omitempty"`
|
Default string `json:"default,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type URLTestOutboundOptions struct {
|
|
||||||
Outbounds []string `json:"outbounds"`
|
|
||||||
URL string `json:"url,omitempty"`
|
|
||||||
Interval Duration `json:"interval,omitempty"`
|
|
||||||
Tolerance uint16 `json:"tolerance,omitempty"`
|
|
||||||
}
|
|
||||||
|
|
|
@ -16,7 +16,6 @@ type _Outbound struct {
|
||||||
ShadowsocksOptions ShadowsocksOutboundOptions `json:"-"`
|
ShadowsocksOptions ShadowsocksOutboundOptions `json:"-"`
|
||||||
VMessOptions VMessOutboundOptions `json:"-"`
|
VMessOptions VMessOutboundOptions `json:"-"`
|
||||||
SelectorOptions SelectorOutboundOptions `json:"-"`
|
SelectorOptions SelectorOutboundOptions `json:"-"`
|
||||||
URLTestOptions URLTestOutboundOptions `json:"-"`
|
|
||||||
}
|
}
|
||||||
|
|
||||||
type Outbound _Outbound
|
type Outbound _Outbound
|
||||||
|
@ -38,8 +37,6 @@ func (h Outbound) MarshalJSON() ([]byte, error) {
|
||||||
v = h.VMessOptions
|
v = h.VMessOptions
|
||||||
case C.TypeSelector:
|
case C.TypeSelector:
|
||||||
v = h.SelectorOptions
|
v = h.SelectorOptions
|
||||||
case C.TypeURLTest:
|
|
||||||
v = h.URLTestOptions
|
|
||||||
default:
|
default:
|
||||||
return nil, E.New("unknown outbound type: ", h.Type)
|
return nil, E.New("unknown outbound type: ", h.Type)
|
||||||
}
|
}
|
||||||
|
@ -67,8 +64,6 @@ func (h *Outbound) UnmarshalJSON(bytes []byte) error {
|
||||||
v = &h.VMessOptions
|
v = &h.VMessOptions
|
||||||
case C.TypeSelector:
|
case C.TypeSelector:
|
||||||
v = &h.SelectorOptions
|
v = &h.SelectorOptions
|
||||||
case C.TypeURLTest:
|
|
||||||
v = &h.URLTestOptions
|
|
||||||
default:
|
default:
|
||||||
return E.New("unknown outbound type: ", h.Type)
|
return E.New("unknown outbound type: ", h.Type)
|
||||||
}
|
}
|
||||||
|
|
|
@ -29,8 +29,6 @@ func New(router adapter.Router, logger log.ContextLogger, options option.Outboun
|
||||||
return NewVMess(router, logger, options.Tag, options.VMessOptions)
|
return NewVMess(router, logger, options.Tag, options.VMessOptions)
|
||||||
case C.TypeSelector:
|
case C.TypeSelector:
|
||||||
return NewSelector(router, logger, options.Tag, options.SelectorOptions)
|
return NewSelector(router, logger, options.Tag, options.SelectorOptions)
|
||||||
case C.TypeURLTest:
|
|
||||||
return NewURLTest(router, logger, options.Tag, options.URLTestOptions)
|
|
||||||
default:
|
default:
|
||||||
return nil, E.New("unknown outbound type: ", options.Type)
|
return nil, E.New("unknown outbound type: ", options.Type)
|
||||||
}
|
}
|
||||||
|
|
|
@ -103,3 +103,10 @@ func (s *Selector) NewConnection(ctx context.Context, conn net.Conn, metadata ad
|
||||||
func (s *Selector) NewPacketConnection(ctx context.Context, conn N.PacketConn, metadata adapter.InboundContext) error {
|
func (s *Selector) NewPacketConnection(ctx context.Context, conn N.PacketConn, metadata adapter.InboundContext) error {
|
||||||
return s.selected.NewPacketConnection(ctx, conn, metadata)
|
return s.selected.NewPacketConnection(ctx, conn, metadata)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func RealTag(detour adapter.Outbound) string {
|
||||||
|
if group, isGroup := detour.(adapter.OutboundGroup); isGroup {
|
||||||
|
return group.Now()
|
||||||
|
}
|
||||||
|
return detour.Tag()
|
||||||
|
}
|
||||||
|
|
|
@ -1,249 +0,0 @@
|
||||||
package outbound
|
|
||||||
|
|
||||||
import (
|
|
||||||
"context"
|
|
||||||
"net"
|
|
||||||
"sort"
|
|
||||||
"time"
|
|
||||||
|
|
||||||
"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/log"
|
|
||||||
"github.com/sagernet/sing-box/option"
|
|
||||||
"github.com/sagernet/sing/common"
|
|
||||||
"github.com/sagernet/sing/common/batch"
|
|
||||||
E "github.com/sagernet/sing/common/exceptions"
|
|
||||||
M "github.com/sagernet/sing/common/metadata"
|
|
||||||
N "github.com/sagernet/sing/common/network"
|
|
||||||
)
|
|
||||||
|
|
||||||
var (
|
|
||||||
_ adapter.Outbound = (*URLTest)(nil)
|
|
||||||
_ adapter.OutboundGroup = (*URLTest)(nil)
|
|
||||||
)
|
|
||||||
|
|
||||||
type URLTest struct {
|
|
||||||
myOutboundAdapter
|
|
||||||
tags []string
|
|
||||||
link string
|
|
||||||
interval time.Duration
|
|
||||||
tolerance uint16
|
|
||||||
group *URLTestGroup
|
|
||||||
}
|
|
||||||
|
|
||||||
func NewURLTest(router adapter.Router, logger log.ContextLogger, tag string, options option.URLTestOutboundOptions) (*URLTest, error) {
|
|
||||||
outbound := &URLTest{
|
|
||||||
myOutboundAdapter: myOutboundAdapter{
|
|
||||||
protocol: C.TypeURLTest,
|
|
||||||
router: router,
|
|
||||||
logger: logger,
|
|
||||||
tag: tag,
|
|
||||||
},
|
|
||||||
tags: options.Outbounds,
|
|
||||||
link: options.URL,
|
|
||||||
interval: time.Duration(options.Interval),
|
|
||||||
tolerance: options.Tolerance,
|
|
||||||
}
|
|
||||||
if len(outbound.tags) == 0 {
|
|
||||||
return nil, E.New("missing tags")
|
|
||||||
}
|
|
||||||
return outbound, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s *URLTest) Network() []string {
|
|
||||||
if s.group == nil {
|
|
||||||
return []string{C.NetworkTCP, C.NetworkUDP}
|
|
||||||
}
|
|
||||||
return s.group.Select().Network()
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s *URLTest) Start() error {
|
|
||||||
outbounds := make([]adapter.Outbound, 0, len(s.tags))
|
|
||||||
for i, tag := range s.tags {
|
|
||||||
detour, loaded := s.router.Outbound(tag)
|
|
||||||
if !loaded {
|
|
||||||
return E.New("outbound ", i, " not found: ", tag)
|
|
||||||
}
|
|
||||||
outbounds = append(outbounds, detour)
|
|
||||||
}
|
|
||||||
s.group = NewURLTestGroup(s.router, s.logger, outbounds, s.link, s.interval, s.tolerance)
|
|
||||||
return s.group.Start()
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s URLTest) Close() error {
|
|
||||||
return common.Close(
|
|
||||||
common.PtrOrNil(s.group),
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s *URLTest) Now() string {
|
|
||||||
return s.group.Select().Tag()
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s *URLTest) All() []string {
|
|
||||||
return s.tags
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s *URLTest) DialContext(ctx context.Context, network string, destination M.Socksaddr) (net.Conn, error) {
|
|
||||||
return s.group.Select().DialContext(ctx, network, destination)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s *URLTest) ListenPacket(ctx context.Context, destination M.Socksaddr) (net.PacketConn, error) {
|
|
||||||
return s.group.Select().ListenPacket(ctx, destination)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s *URLTest) NewConnection(ctx context.Context, conn net.Conn, metadata adapter.InboundContext) error {
|
|
||||||
return s.group.Select().NewConnection(ctx, conn, metadata)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s *URLTest) NewPacketConnection(ctx context.Context, conn N.PacketConn, metadata adapter.InboundContext) error {
|
|
||||||
return s.group.Select().NewPacketConnection(ctx, conn, metadata)
|
|
||||||
}
|
|
||||||
|
|
||||||
type URLTestGroup struct {
|
|
||||||
router adapter.Router
|
|
||||||
logger log.Logger
|
|
||||||
outbounds []adapter.Outbound
|
|
||||||
link string
|
|
||||||
interval time.Duration
|
|
||||||
tolerance uint16
|
|
||||||
|
|
||||||
ticker *time.Ticker
|
|
||||||
close chan struct{}
|
|
||||||
}
|
|
||||||
|
|
||||||
func NewURLTestGroup(router adapter.Router, logger log.Logger, outbounds []adapter.Outbound, link string, interval time.Duration, tolerance uint16) *URLTestGroup {
|
|
||||||
if link == "" {
|
|
||||||
//goland:noinspection HttpUrlsUsage
|
|
||||||
link = "http://www.gstatic.com/generate_204"
|
|
||||||
}
|
|
||||||
if interval == 0 {
|
|
||||||
interval = C.DefaultURLTestInterval
|
|
||||||
}
|
|
||||||
if tolerance == 0 {
|
|
||||||
tolerance = 50
|
|
||||||
}
|
|
||||||
return &URLTestGroup{
|
|
||||||
router: router,
|
|
||||||
logger: logger,
|
|
||||||
outbounds: outbounds,
|
|
||||||
link: link,
|
|
||||||
interval: interval,
|
|
||||||
tolerance: tolerance,
|
|
||||||
close: make(chan struct{}),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (g *URLTestGroup) Start() error {
|
|
||||||
g.ticker = time.NewTicker(g.interval)
|
|
||||||
go g.loopCheck()
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (g *URLTestGroup) Close() error {
|
|
||||||
g.ticker.Stop()
|
|
||||||
close(g.close)
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (g *URLTestGroup) Select() adapter.Outbound {
|
|
||||||
var minDelay uint16
|
|
||||||
var minTime time.Time
|
|
||||||
var minOutbound adapter.Outbound
|
|
||||||
for _, detour := range g.outbounds {
|
|
||||||
history := g.router.URLTestHistoryStorage(false).LoadURLTestHistory(RealTag(detour))
|
|
||||||
if history == nil {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
if minDelay == 0 || minDelay > history.Delay+g.tolerance || minDelay > history.Delay-g.tolerance && minTime.Before(history.Time) {
|
|
||||||
minDelay = history.Delay
|
|
||||||
minTime = history.Time
|
|
||||||
minOutbound = detour
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if minOutbound == nil {
|
|
||||||
minOutbound = g.outbounds[0]
|
|
||||||
}
|
|
||||||
return minOutbound
|
|
||||||
}
|
|
||||||
|
|
||||||
func (g *URLTestGroup) Fallback(used adapter.Outbound) []adapter.Outbound {
|
|
||||||
outbounds := make([]adapter.Outbound, 0, len(g.outbounds)-1)
|
|
||||||
for _, detour := range g.outbounds {
|
|
||||||
if detour != used {
|
|
||||||
outbounds = append(outbounds, detour)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
sort.Slice(outbounds, func(i, j int) bool {
|
|
||||||
oi := outbounds[i]
|
|
||||||
oj := outbounds[j]
|
|
||||||
hi := g.router.URLTestHistoryStorage(false).LoadURLTestHistory(RealTag(oi))
|
|
||||||
if hi == nil {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
hj := g.router.URLTestHistoryStorage(false).LoadURLTestHistory(RealTag(oj))
|
|
||||||
if hj == nil {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
return hi.Delay < hj.Delay
|
|
||||||
})
|
|
||||||
return outbounds
|
|
||||||
}
|
|
||||||
|
|
||||||
func (g *URLTestGroup) loopCheck() {
|
|
||||||
go g.checkOutbounds()
|
|
||||||
for {
|
|
||||||
select {
|
|
||||||
case <-g.close:
|
|
||||||
return
|
|
||||||
case <-g.ticker.C:
|
|
||||||
g.checkOutbounds()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (g *URLTestGroup) checkOutbounds() {
|
|
||||||
b, _ := batch.New(context.Background(), batch.WithConcurrencyNum[any](10))
|
|
||||||
checked := make(map[string]bool)
|
|
||||||
for _, detour := range g.outbounds {
|
|
||||||
tag := detour.Tag()
|
|
||||||
realTag := RealTag(detour)
|
|
||||||
if checked[realTag] {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
history := g.router.URLTestHistoryStorage(false).LoadURLTestHistory(realTag)
|
|
||||||
if history != nil && time.Now().Sub(history.Time) < g.interval {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
checked[realTag] = true
|
|
||||||
p, loaded := g.router.Outbound(realTag)
|
|
||||||
if !loaded {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
b.Go(realTag, func() (any, error) {
|
|
||||||
ctx, cancel := context.WithTimeout(context.Background(), C.URLTestTimeout)
|
|
||||||
defer cancel()
|
|
||||||
t, err := urltest.URLTest(ctx, g.link, p)
|
|
||||||
if err != nil {
|
|
||||||
g.logger.Debug("outbound ", tag, " unavailable: ", err)
|
|
||||||
g.router.URLTestHistoryStorage(true).DeleteURLTestHistory(realTag)
|
|
||||||
} else {
|
|
||||||
g.logger.Debug("outbound ", tag, " available: ", t, "ms")
|
|
||||||
g.router.URLTestHistoryStorage(true).StoreURLTestHistory(realTag, &urltest.History{
|
|
||||||
Time: time.Now(),
|
|
||||||
Delay: t,
|
|
||||||
})
|
|
||||||
}
|
|
||||||
return nil, nil
|
|
||||||
})
|
|
||||||
}
|
|
||||||
b.Wait()
|
|
||||||
}
|
|
||||||
|
|
||||||
func RealTag(detour adapter.Outbound) string {
|
|
||||||
if group, isGroup := detour.(adapter.OutboundGroup); isGroup {
|
|
||||||
return group.Now()
|
|
||||||
}
|
|
||||||
return detour.Tag()
|
|
||||||
}
|
|
|
@ -21,7 +21,6 @@ import (
|
||||||
"github.com/sagernet/sing-box/common/geosite"
|
"github.com/sagernet/sing-box/common/geosite"
|
||||||
"github.com/sagernet/sing-box/common/process"
|
"github.com/sagernet/sing-box/common/process"
|
||||||
"github.com/sagernet/sing-box/common/sniff"
|
"github.com/sagernet/sing-box/common/sniff"
|
||||||
"github.com/sagernet/sing-box/common/urltest"
|
|
||||||
"github.com/sagernet/sing-box/common/warning"
|
"github.com/sagernet/sing-box/common/warning"
|
||||||
C "github.com/sagernet/sing-box/constant"
|
C "github.com/sagernet/sing-box/constant"
|
||||||
"github.com/sagernet/sing-box/log"
|
"github.com/sagernet/sing-box/log"
|
||||||
|
@ -93,7 +92,6 @@ type Router struct {
|
||||||
interfaceMonitor DefaultInterfaceMonitor
|
interfaceMonitor DefaultInterfaceMonitor
|
||||||
defaultMark int
|
defaultMark int
|
||||||
trafficController adapter.TrafficController
|
trafficController adapter.TrafficController
|
||||||
urlTestHistoryStorage *urltest.HistoryStorage
|
|
||||||
processSearcher process.Searcher
|
processSearcher process.Searcher
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -699,13 +697,6 @@ func (r *Router) SetTrafficController(controller adapter.TrafficController) {
|
||||||
r.trafficController = controller
|
r.trafficController = controller
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r *Router) URLTestHistoryStorage(create bool) *urltest.HistoryStorage {
|
|
||||||
if r.urlTestHistoryStorage == nil && create {
|
|
||||||
r.urlTestHistoryStorage = urltest.NewHistoryStorage()
|
|
||||||
}
|
|
||||||
return r.urlTestHistoryStorage
|
|
||||||
}
|
|
||||||
|
|
||||||
func hasRule(rules []option.Rule, cond func(rule option.DefaultRule) bool) bool {
|
func hasRule(rules []option.Rule, cond func(rule option.DefaultRule) bool) bool {
|
||||||
for _, rule := range rules {
|
for _, rule := range rules {
|
||||||
switch rule.Type {
|
switch rule.Type {
|
||||||
|
|
Loading…
Reference in a new issue