diff --git a/option/group.go b/option/group.go index 02b3a5ec..d0d1aa1d 100644 --- a/option/group.go +++ b/option/group.go @@ -10,6 +10,7 @@ type SelectorOutboundOptions struct { type URLTestOutboundOptions struct { Outbounds []string `json:"outbounds"` + Costs map[string]uint16 `json:"costs,omitempty"` URL string `json:"url,omitempty"` Interval badoption.Duration `json:"interval,omitempty"` Tolerance uint16 `json:"tolerance,omitempty"` diff --git a/protocol/group/urltest.go b/protocol/group/urltest.go index 26967279..da064e21 100644 --- a/protocol/group/urltest.go +++ b/protocol/group/urltest.go @@ -39,6 +39,7 @@ type URLTest struct { connection adapter.ConnectionManager logger log.ContextLogger tags []string + costs map[string]uint16 link string interval time.Duration tolerance uint16 @@ -61,6 +62,7 @@ func NewURLTest(ctx context.Context, router adapter.Router, logger log.ContextLo tolerance: options.Tolerance, idleTimeout: time.Duration(options.IdleTimeout), interruptExternalConnections: options.InterruptExistConnections, + costs: options.Costs, } if len(outbound.tags) == 0 { return nil, E.New("missing tags") @@ -77,7 +79,7 @@ func (s *URLTest) Start() error { } outbounds = append(outbounds, detour) } - group, err := NewURLTestGroup(s.ctx, s.outbound, s.logger, outbounds, s.link, s.interval, s.tolerance, s.idleTimeout, s.interruptExternalConnections) + group, err := NewURLTestGroup(s.ctx, s.outbound, s.logger, outbounds, s.costs, s.link, s.interval, s.tolerance, s.idleTimeout, s.interruptExternalConnections) if err != nil { return err } @@ -194,6 +196,7 @@ type URLTestGroup struct { pauseCallback *list.Element[pause.Callback] logger log.Logger outbounds []adapter.Outbound + costs map[string]uint16 link string interval time.Duration tolerance uint16 @@ -211,7 +214,7 @@ type URLTestGroup struct { lastActive common.TypedValue[time.Time] } -func NewURLTestGroup(ctx context.Context, outboundManager adapter.OutboundManager, logger log.Logger, outbounds []adapter.Outbound, link string, interval time.Duration, tolerance uint16, idleTimeout time.Duration, interruptExternalConnections bool) (*URLTestGroup, error) { +func NewURLTestGroup(ctx context.Context, outboundManager adapter.OutboundManager, logger log.Logger, outbounds []adapter.Outbound, costs map[string]uint16, link string, interval time.Duration, tolerance uint16, idleTimeout time.Duration, interruptExternalConnections bool) (*URLTestGroup, error) { if interval == 0 { interval = C.DefaultURLTestInterval } @@ -221,6 +224,9 @@ func NewURLTestGroup(ctx context.Context, outboundManager adapter.OutboundManage if idleTimeout == 0 { idleTimeout = C.DefaultURLTestIdleTimeout } + if costs == nil { + costs = map[string]uint16{} + } if interval > idleTimeout { return nil, E.New("interval must be less or equal than idle_timeout") } @@ -237,6 +243,7 @@ func NewURLTestGroup(ctx context.Context, outboundManager adapter.OutboundManage outbound: outboundManager, logger: logger, outbounds: outbounds, + costs: costs, link: link, interval: interval, tolerance: tolerance, @@ -398,7 +405,11 @@ func (g *URLTestGroup) urlTest(ctx context.Context, force bool) (map[string]uint Delay: t, }) resultAccess.Lock() - result[tag] = t + add_latency, exist := g.costs[tag] + if !exist { + add_latency = 0 + } + result[tag] = t + add_latency resultAccess.Unlock() } return nil, nil