Fix outbound start sequence

This commit is contained in:
世界 2023-06-13 22:38:05 +08:00
parent 4f12eba944
commit 8d5b9d240a
No known key found for this signature in database
GPG key ID: CD109927C34A63C4
23 changed files with 197 additions and 105 deletions

View file

@ -13,6 +13,7 @@ type Outbound interface {
Type() string
Tag() string
Network() []string
Dependencies() []string
N.Dialer
NewConnection(ctx context.Context, conn net.Conn, metadata InboundContext) error
NewPacketConnection(ctx context.Context, conn N.PacketConn, metadata InboundContext) error

15
box.go
View file

@ -217,20 +217,9 @@ func (s *Box) preStart() error {
return E.Cause(err, "pre-starting ", serviceName)
}
}
for i, out := range s.outbounds {
var tag string
if out.Tag() == "" {
tag = F.ToString(i)
} else {
tag = out.Tag()
}
if starter, isStarter := out.(common.Starter); isStarter {
s.logger.Trace("initializing outbound/", out.Type(), "[", tag, "]")
err := starter.Start()
err := s.startOutbounds()
if err != nil {
return E.Cause(err, "initialize outbound/", out.Type(), "[", tag, "]")
}
}
return err
}
return s.router.Start()
}

76
box_outbound.go Normal file
View file

@ -0,0 +1,76 @@
package box
import (
"strings"
"github.com/sagernet/sing-box/adapter"
"github.com/sagernet/sing/common"
E "github.com/sagernet/sing/common/exceptions"
F "github.com/sagernet/sing/common/format"
)
func (s *Box) startOutbounds() error {
outboundTags := make(map[adapter.Outbound]string)
outbounds := make(map[string]adapter.Outbound)
for i, outboundToStart := range s.outbounds {
var outboundTag string
if outboundToStart.Tag() == "" {
outboundTag = F.ToString(i)
} else {
outboundTag = outboundToStart.Tag()
}
outboundTags[outboundToStart] = outboundTag
outbounds[outboundTag] = outboundToStart
}
started := make(map[string]bool)
for {
canContinue := false
startOne:
for _, outboundToStart := range s.outbounds {
outboundTag := outboundTags[outboundToStart]
if started[outboundTag] {
continue
}
dependencies := outboundToStart.Dependencies()
for _, dependency := range dependencies {
if !started[dependency] {
continue startOne
}
}
started[outboundTag] = true
canContinue = true
if starter, isStarter := outboundToStart.(common.Starter); isStarter {
s.logger.Trace("initializing outbound/", outboundToStart.Type(), "[", outboundTag, "]")
err := starter.Start()
if err != nil {
return E.Cause(err, "initialize outbound/", outboundToStart.Type(), "[", outboundTag, "]")
}
}
}
if len(started) == len(s.outbounds) {
break
}
if canContinue {
continue
}
currentOutbound := common.Find(s.outbounds, func(it adapter.Outbound) bool {
return !started[outboundTags[it]]
})
var lintOutbound func(oTree []string, oCurrent adapter.Outbound) error
lintOutbound = func(oTree []string, oCurrent adapter.Outbound) error {
problemOutboundTag := common.Find(oCurrent.Dependencies(), func(it string) bool {
return !started[it]
})
if common.Contains(oTree, problemOutboundTag) {
return E.New("circular outbound dependency: ", strings.Join(oTree, " -> "), " -> ", problemOutboundTag)
}
problemOutbound := outbounds[problemOutboundTag]
if problemOutbound == nil {
return E.New("dependency[", problemOutbound, "] not found for outbound[", outboundTags[oCurrent], "]")
}
return lintOutbound(append(oTree, problemOutboundTag), problemOutbound)
}
return lintOutbound([]string{outboundTags[currentOutbound]}, currentOutbound)
}
return nil
}

2
go.mod
View file

@ -25,7 +25,7 @@ require (
github.com/sagernet/gvisor v0.0.0-20230611140528-4411f7659a08
github.com/sagernet/quic-go v0.0.0-20230202071646-a8c8afb18b32
github.com/sagernet/reality v0.0.0-20230406110435-ee17307e7691
github.com/sagernet/sing v0.2.5-0.20230611070640-2812461739c3
github.com/sagernet/sing v0.2.5-0.20230613142554-a3b120b25eab
github.com/sagernet/sing-dns v0.1.5-0.20230426113254-25d948c44223
github.com/sagernet/sing-mux v0.0.0-20230517134606-1ebe6bb26646
github.com/sagernet/sing-shadowsocks v0.2.2-0.20230509053848-d83f8fe1194c

4
go.sum
View file

@ -118,8 +118,8 @@ github.com/sagernet/reality v0.0.0-20230406110435-ee17307e7691 h1:5Th31OC6yj8byL
github.com/sagernet/reality v0.0.0-20230406110435-ee17307e7691/go.mod h1:B8lp4WkQ1PwNnrVMM6KyuFR20pU8jYBD+A4EhJovEXU=
github.com/sagernet/sing v0.0.0-20220817130738-ce854cda8522/go.mod h1:QVsS5L/ZA2Q5UhQwLrn0Trw+msNd/NPGEhBKR/ioWiY=
github.com/sagernet/sing v0.1.8/go.mod h1:jt1w2u7lJQFFSGLiRrRIs5YWmx4kAPfWuOejuDW9qMk=
github.com/sagernet/sing v0.2.5-0.20230611070640-2812461739c3 h1:OnlfGM8HncECbFiV4s6uAX961fm2UpEKSCXYBLZ1Chg=
github.com/sagernet/sing v0.2.5-0.20230611070640-2812461739c3/go.mod h1:Ta8nHnDLAwqySzKhGoKk4ZIB+vJ3GTKj7UPrWYvM+4w=
github.com/sagernet/sing v0.2.5-0.20230613142554-a3b120b25eab h1:9AVUIqqz/UJCgIrcJBU9mb06JXzfQ/FgEmlgdPgo2dk=
github.com/sagernet/sing v0.2.5-0.20230613142554-a3b120b25eab/go.mod h1:Ta8nHnDLAwqySzKhGoKk4ZIB+vJ3GTKj7UPrWYvM+4w=
github.com/sagernet/sing-dns v0.1.5-0.20230426113254-25d948c44223 h1:L4eMuM07iSHY3UCknFnuFuHoe5clZuF2Xnf2wwA6Lwc=
github.com/sagernet/sing-dns v0.1.5-0.20230426113254-25d948c44223/go.mod h1:ZKuuqgsHRxDahYrzgSgy4vIAGGuKPlIf4hLcNzYzLkY=
github.com/sagernet/sing-mux v0.0.0-20230517134606-1ebe6bb26646 h1:X3ADfMqeGns1Q1FlXc9kaL9FwW1UM6D6tEQo8jFstpc=

View file

@ -11,6 +11,7 @@ import (
"github.com/sagernet/sing-box/adapter"
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/buf"
"github.com/sagernet/sing/common/bufio"
@ -25,6 +26,7 @@ type myOutboundAdapter struct {
router adapter.Router
logger log.ContextLogger
tag string
dependencies []string
}
func (a *myOutboundAdapter) Type() string {
@ -39,10 +41,21 @@ func (a *myOutboundAdapter) Network() []string {
return a.network
}
func (a *myOutboundAdapter) Dependencies() []string {
return a.dependencies
}
func (a *myOutboundAdapter) NewError(ctx context.Context, err error) {
NewError(a.logger, ctx, err)
}
func withDialerDependency(options option.DialerOptions) []string {
if options.Detour != "" {
return []string{options.Detour}
}
return nil
}
func NewConnection(ctx context.Context, this N.Dialer, conn net.Conn, metadata adapter.InboundContext) error {
ctx = adapter.WithContext(ctx, &metadata)
var outConn net.Conn

View file

@ -45,6 +45,7 @@ func NewDirect(router adapter.Router, logger log.ContextLogger, tag string, opti
router: router,
logger: logger,
tag: tag,
dependencies: withDialerDependency(options.DialerOptions),
},
domainStrategy: dns.DomainStrategy(options.DomainStrategy),
fallbackDelay: time.Duration(options.FallbackDelay),

View file

@ -44,6 +44,7 @@ func NewHTTP(router adapter.Router, logger log.ContextLogger, tag string, option
router: router,
logger: logger,
tag: tag,
dependencies: withDialerDependency(options.DialerOptions),
},
sHTTP.NewClient(sHTTP.Options{
Dialer: detour,

View file

@ -124,6 +124,7 @@ func NewHysteria(ctx context.Context, router adapter.Router, logger log.ContextL
router: router,
logger: logger,
tag: tag,
dependencies: withDialerDependency(options.DialerOptions),
},
ctx: ctx,
dialer: dialer.New(router, options.DialerOptions),

View file

@ -33,6 +33,7 @@ func NewSelector(router adapter.Router, logger log.ContextLogger, tag string, op
router: router,
logger: logger,
tag: tag,
dependencies: options.Outbounds,
},
tags: options.Outbounds,
defaultTag: options.Default,

View file

@ -46,6 +46,7 @@ func NewShadowsocks(ctx context.Context, router adapter.Router, logger log.Conte
router: router,
logger: logger,
tag: tag,
dependencies: withDialerDependency(options.DialerOptions),
},
dialer: dialer.New(router, options.DialerOptions),
method: method,

View file

@ -44,6 +44,7 @@ func NewShadowsocksR(ctx context.Context, router adapter.Router, logger log.Cont
router: router,
logger: logger,
tag: tag,
dependencies: withDialerDependency(options.DialerOptions),
},
dialer: dialer.New(router, options.DialerOptions),
serverAddr: options.ServerOptions.Build(),

View file

@ -32,6 +32,7 @@ func NewShadowTLS(ctx context.Context, router adapter.Router, logger log.Context
router: router,
logger: logger,
tag: tag,
dependencies: withDialerDependency(options.DialerOptions),
},
}
if options.TLS == nil || !options.TLS.Enabled {

View file

@ -44,6 +44,7 @@ func NewSocks(router adapter.Router, logger log.ContextLogger, tag string, optio
router: router,
logger: logger,
tag: tag,
dependencies: withDialerDependency(options.DialerOptions),
},
client: socks.NewClient(dialer.New(router, options.DialerOptions), options.ServerOptions.Build(), version, options.Username, options.Password),
resolve: version == socks.Version4,

View file

@ -51,6 +51,7 @@ func NewSSH(ctx context.Context, router adapter.Router, logger log.ContextLogger
router: router,
logger: logger,
tag: tag,
dependencies: withDialerDependency(options.DialerOptions),
},
ctx: ctx,
dialer: dialer.New(router, options.DialerOptions),

View file

@ -73,6 +73,7 @@ func NewTor(ctx context.Context, router adapter.Router, logger log.ContextLogger
router: router,
logger: logger,
tag: tag,
dependencies: withDialerDependency(options.DialerOptions),
},
ctx: ctx,
proxy: NewProxyListener(ctx, logger, dialer.New(router, options.DialerOptions)),

View file

@ -40,6 +40,7 @@ func NewTrojan(ctx context.Context, router adapter.Router, logger log.ContextLog
router: router,
logger: logger,
tag: tag,
dependencies: withDialerDependency(options.DialerOptions),
},
dialer: dialer.New(router, options.DialerOptions),
serverAddr: options.ServerOptions.Build(),

View file

@ -43,6 +43,7 @@ func NewURLTest(ctx context.Context, router adapter.Router, logger log.ContextLo
router: router,
logger: logger,
tag: tag,
dependencies: options.Outbounds,
},
ctx: ctx,
tags: options.Outbounds,

View file

@ -43,6 +43,7 @@ func NewVLESS(ctx context.Context, router adapter.Router, logger log.ContextLogg
router: router,
logger: logger,
tag: tag,
dependencies: withDialerDependency(options.DialerOptions),
},
dialer: dialer.New(router, options.DialerOptions),
serverAddr: options.ServerOptions.Build(),

View file

@ -42,6 +42,7 @@ func NewVMess(ctx context.Context, router adapter.Router, logger log.ContextLogg
router: router,
logger: logger,
tag: tag,
dependencies: withDialerDependency(options.DialerOptions),
},
dialer: dialer.New(router, options.DialerOptions),
serverAddr: options.ServerOptions.Build(),

View file

@ -45,6 +45,7 @@ func NewWireGuard(ctx context.Context, router adapter.Router, logger log.Context
router: router,
logger: logger,
tag: tag,
dependencies: withDialerDependency(options.DialerOptions),
},
}
var reserved [3]uint8

View file

@ -8,13 +8,6 @@ import (
"net/netip"
"os"
"github.com/sagernet/sing-tun"
"github.com/sagernet/sing/common/buf"
E "github.com/sagernet/sing/common/exceptions"
M "github.com/sagernet/sing/common/metadata"
N "github.com/sagernet/sing/common/network"
wgTun "github.com/sagernet/wireguard-go/tun"
"github.com/sagernet/gvisor/pkg/buffer"
"github.com/sagernet/gvisor/pkg/tcpip"
"github.com/sagernet/gvisor/pkg/tcpip/adapters/gonet"
@ -25,6 +18,12 @@ import (
"github.com/sagernet/gvisor/pkg/tcpip/transport/icmp"
"github.com/sagernet/gvisor/pkg/tcpip/transport/tcp"
"github.com/sagernet/gvisor/pkg/tcpip/transport/udp"
"github.com/sagernet/sing-tun"
"github.com/sagernet/sing/common/buf"
E "github.com/sagernet/sing/common/exceptions"
M "github.com/sagernet/sing/common/metadata"
N "github.com/sagernet/sing/common/network"
wgTun "github.com/sagernet/wireguard-go/tun"
)
var _ Device = (*StackDevice)(nil)

View file

@ -10,14 +10,13 @@ import (
"net/netip"
"time"
"github.com/sagernet/sing-tun"
M "github.com/sagernet/sing/common/metadata"
"github.com/sagernet/gvisor/pkg/tcpip"
"github.com/sagernet/gvisor/pkg/tcpip/adapters/gonet"
"github.com/sagernet/gvisor/pkg/tcpip/stack"
"github.com/sagernet/gvisor/pkg/tcpip/transport/tcp"
"github.com/sagernet/gvisor/pkg/waiter"
"github.com/sagernet/sing-tun"
M "github.com/sagernet/sing/common/metadata"
)
func DialTCPWithBind(ctx context.Context, s *stack.Stack, localAddr, remoteAddr tcpip.FullAddress, network tcpip.NetworkProtocolNumber) (*gonet.TCPConn, error) {