Merge tag 'v1.14.3'

This commit is contained in:
Shtorm
2026-10-19 01:05:55 +03:00
321 changed files with 6750 additions and 5105 deletions
+4 -1
View File
@@ -59,7 +59,10 @@ func NewFallback(ctx context.Context, router adapter.Router, logger log.ContextL
return outbound, nil
}
func (s *Fallback) Start() error {
func (s *Fallback) Start(stage adapter.StartStage, scope *adapter.Scope) error {
if stage != adapter.StartStateStart {
return nil
}
for i, tag := range s.tags {
outbound, loaded := s.outbound.Outbound(tag)
if !loaded {
+9 -2
View File
@@ -26,6 +26,7 @@ func RegisterSelector(registry *outbound.Registry) {
var (
_ adapter.OutboundGroup = (*Selector)(nil)
_ adapter.Referrer = (*Selector)(nil)
_ adapter.ConnectionHandler = (*Selector)(nil)
_ adapter.PacketConnectionHandler = (*Selector)(nil)
)
@@ -88,7 +89,10 @@ func (s *Selector) Network() []string {
return selected.Network()
}
func (s *Selector) Start() error {
func (s *Selector) Start(stage adapter.StartStage, scope *adapter.Scope) error {
if stage != adapter.StartStateStart {
return nil
}
if s.useAllProviders {
var providerTags []string
for _, provider := range s.provider.Providers() {
@@ -110,7 +114,6 @@ func (s *Selector) Start() error {
if len(s.tags)+len(s.providerTags) == 0 {
return E.New("missing outbound and provider tags")
}
for i, tag := range s.tags {
detour, loaded := s.outbound.Outbound(tag)
if !loaded {
@@ -143,6 +146,10 @@ func (s *Selector) All() []string {
return s.tags
}
func (s *Selector) References() []string {
return []string{s.Now()}
}
func (s *Selector) SelectOutbound(tag string) bool {
detour, loaded := s.outbounds[tag]
if !loaded {
+70 -49
View File
@@ -33,6 +33,7 @@ func RegisterURLTest(registry *outbound.Registry) {
var (
_ adapter.OutboundGroup = (*URLTest)(nil)
_ adapter.InterfaceUpdateListener = (*URLTest)(nil)
_ adapter.Referrer = (*URLTest)(nil)
)
type URLTest struct {
@@ -87,61 +88,55 @@ func NewURLTest(ctx context.Context, router adapter.Router, logger log.ContextLo
return outbound, nil
}
func (s *URLTest) Start() error {
if s.useAllProviders {
var providerTags []string
for _, provider := range s.provider.Providers() {
providerTags = append(providerTags, provider.Tag())
s.providers[provider.Tag()] = provider
provider.RegisterCallback(s.onProviderUpdated)
}
s.providerTags = providerTags
} else {
for i, tag := range s.providerTags {
provider, loaded := s.provider.Get(tag)
if !loaded {
return E.New("outbound provider ", i, " not found: ", tag)
func (s *URLTest) Start(stage adapter.StartStage, scope *adapter.Scope) error {
switch stage {
case adapter.StartStateStart:
if s.useAllProviders {
var providerTags []string
for _, provider := range s.provider.Providers() {
providerTags = append(providerTags, provider.Tag())
s.providers[provider.Tag()] = provider
provider.RegisterCallback(s.onProviderUpdated)
}
s.providerTags = providerTags
} else {
for i, tag := range s.providerTags {
provider, loaded := s.provider.Get(tag)
if !loaded {
return E.New("outbound provider ", i, " not found: ", tag)
}
s.providers[tag] = provider
provider.RegisterCallback(s.onProviderUpdated)
}
s.providers[tag] = provider
provider.RegisterCallback(s.onProviderUpdated)
}
}
if len(s.tags)+len(s.providerTags) == 0 {
return E.New("missing outbound and provider tags")
}
outbounds := make([]adapter.Outbound, 0, len(s.tags))
for i, tag := range s.tags {
detour, loaded := s.outbound.Outbound(tag)
if !loaded {
return E.New("outbound ", i, " not found: ", tag)
if len(s.tags)+len(s.providerTags) == 0 {
return E.New("missing outbound and provider tags")
}
outbounds = append(outbounds, detour)
outbounds := make([]adapter.Outbound, 0, len(s.tags))
for i, tag := range s.tags {
detour, loaded := s.outbound.Outbound(tag)
if !loaded {
return E.New("outbound ", i, " not found: ", tag)
}
outbounds = append(outbounds, detour)
}
if len(s.tags) == 0 {
detour, _ := s.outbound.Outbound("Compatible")
s.tags = append(s.tags, detour.Tag())
outbounds = append(outbounds, detour)
}
group, err := NewURLTestGroup(s.ctx, s.outbound, s.logger, outbounds, s.link, s.interval, s.tolerance, s.idleTimeout, s.interruptExternalConnections)
if err != nil {
return err
}
s.group = group
case adapter.StartStateStarted:
s.group.PostStart()
scope.Add(s.group.Close)
}
if len(s.tags) == 0 {
detour, _ := s.outbound.Outbound("Compatible")
s.tags = append(s.tags, detour.Tag())
outbounds = append(outbounds, detour)
}
group, err := NewURLTestGroup(s.ctx, s.outbound, s.logger, outbounds, s.link, s.interval, s.tolerance, s.idleTimeout, s.interruptExternalConnections)
if err != nil {
return err
}
s.group = group
return nil
}
func (s *URLTest) PostStart() error {
s.group.PostStart()
return nil
}
func (s *URLTest) Close() error {
return common.Close(
common.PtrOrNil(s.group),
)
}
func (s *URLTest) Now() string {
if s.group.selectedOutboundTCP != nil {
return s.group.selectedOutboundTCP.Tag()
@@ -155,6 +150,21 @@ func (s *URLTest) All() []string {
return s.tags
}
func (s *URLTest) References() []string {
group := s.group
if group == nil {
return nil
}
var references []string
if group.selectedOutboundTCP != nil {
references = append(references, group.selectedOutboundTCP.Tag())
}
if group.selectedOutboundUDP != nil && group.selectedOutboundUDP != group.selectedOutboundTCP {
references = append(references, group.selectedOutboundUDP.Tag())
}
return references
}
func (s *URLTest) URLTest(ctx context.Context) (map[string]uint16, error) {
return s.group.URLTest(ctx)
}
@@ -571,6 +581,9 @@ func (b *urlTestBatch) test(outbounds []adapter.Outbound, link string, interval
testResult.err = testCtx.Err()
}
if testResult.err != nil {
if b.ctx.Err() != nil {
return nil, nil
}
b.logger.Debug("outbound ", tag, " unavailable: ", testResult.err)
b.history.DeleteURLTestHistory(tag)
} else {
@@ -592,20 +605,28 @@ func (b *urlTestBatch) test(outbounds []adapter.Outbound, link string, interval
func (g *URLTestGroup) performUpdateCheck() {
g.updateAccess.Lock()
defer g.updateAccess.Unlock()
var updated bool
var (
updated bool
selected bool
)
if outbound, exists := g.Select(N.NetworkTCP); outbound != nil && (g.selectedOutboundTCP == nil || (exists && outbound != g.selectedOutboundTCP)) {
if g.selectedOutboundTCP != nil {
updated = true
}
g.selectedOutboundTCP = outbound
selected = true
}
if outbound, exists := g.Select(N.NetworkUDP); outbound != nil && (g.selectedOutboundUDP == nil || (exists && outbound != g.selectedOutboundUDP)) {
if g.selectedOutboundUDP != nil {
updated = true
}
g.selectedOutboundUDP = outbound
selected = true
}
if updated {
g.interruptGroup.Interrupt(g.interruptExternalConnections)
}
if selected {
g.history.NotifyUpdated()
}
}