protocol: Forward lifecycle Start stage to nested outbounds in vpn, failover and limiters

This commit is contained in:
Shtorm
2026-09-05 04:30:03 +03:00
parent 08703c9035
commit 64605fc47a
6 changed files with 71 additions and 49 deletions
+17 -5
View File
@@ -27,6 +27,7 @@ type Failover struct {
outbound.Adapter outbound.Adapter
ctx context.Context ctx context.Context
outbound adapter.OutboundManager outbound adapter.OutboundManager
outbounds []adapter.Outbound
logger logger.ContextLogger logger logger.ContextLogger
dial DialStrategy dial DialStrategy
uotClient *uot.Client uotClient *uot.Client
@@ -50,11 +51,12 @@ func NewFailover(ctx context.Context, router adapter.Router, logger log.ContextL
return nil, err return nil, err
} }
outbound := &Failover{ outbound := &Failover{
Adapter: outbound.NewAdapter(C.TypeFailover, tag, []string{N.NetworkTCP, N.NetworkUDP}, []string{}), Adapter: outbound.NewAdapter(C.TypeFailover, tag, []string{N.NetworkTCP, N.NetworkUDP}, []string{}),
ctx: ctx, ctx: ctx,
outbound: service.FromContext[adapter.OutboundManager](ctx), outbound: service.FromContext[adapter.OutboundManager](ctx),
logger: logger, outbounds: outbounds,
dial: dial, logger: logger,
dial: dial,
} }
outbound.uotClient = &uot.Client{ outbound.uotClient = &uot.Client{
Dialer: outbound, Dialer: outbound,
@@ -63,6 +65,16 @@ func NewFailover(ctx context.Context, router adapter.Router, logger log.ContextL
return outbound, nil return outbound, nil
} }
func (f *Failover) Start(stage adapter.StartStage) error {
for _, outbound := range f.outbounds {
err := adapter.LegacyStart(outbound, stage)
if err != nil {
return err
}
}
return nil
}
func (f *Failover) DialContext(ctx context.Context, network string, destination M.Socksaddr) (net.Conn, error) { func (f *Failover) DialContext(ctx context.Context, network string, destination M.Socksaddr) (net.Conn, error) {
if N.NetworkName(network) == N.NetworkUDP { if N.NetworkName(network) == N.NetworkUDP {
return f.uotClient.DialContext(ctx, network, destination) return f.uotClient.DialContext(ctx, network, destination)
+13 -11
View File
@@ -24,6 +24,8 @@ func RegisterOutbound(registry *outbound.Registry) {
outbound.Register[option.BandwidthLimiterOutboundOptions](registry, C.TypeBandwidthLimiter, NewOutbound) outbound.Register[option.BandwidthLimiterOutboundOptions](registry, C.TypeBandwidthLimiter, NewOutbound)
} }
var _ adapter.Lifecycle = (*Outbound)(nil)
type Outbound struct { type Outbound struct {
outbound.Adapter outbound.Adapter
ctx context.Context ctx context.Context
@@ -87,19 +89,19 @@ func (h *Outbound) Network() []string {
return []string{N.NetworkTCP, N.NetworkUDP} return []string{N.NetworkTCP, N.NetworkUDP}
} }
func (h *Outbound) Start() error { func (h *Outbound) Start(stage adapter.StartStage) error {
detour, loaded := h.outbound.Outbound(h.outboundTag) if stage == adapter.StartStateStart {
if !loaded { detour, loaded := h.outbound.Outbound(h.outboundTag)
return E.New("outbound not found: ", h.outboundTag) if !loaded {
} return E.New("outbound not found: ", h.outboundTag)
h.detour = detour
for _, stage := range []adapter.StartStage{adapter.StartStateStart, adapter.StartStatePostStart, adapter.StartStateStarted} {
err := h.router.Start(stage)
if err != nil {
return err
} }
h.detour = detour
} }
return nil return h.router.Start(stage)
}
func (h *Outbound) Close() error {
return h.router.Close()
} }
func (h *Outbound) DialContext(ctx context.Context, network string, destination M.Socksaddr) (net.Conn, error) { func (h *Outbound) DialContext(ctx context.Context, network string, destination M.Socksaddr) (net.Conn, error) {
+13 -11
View File
@@ -24,6 +24,8 @@ func RegisterOutbound(registry *outbound.Registry) {
outbound.Register[option.ConnectionLimiterOutboundOptions](registry, C.TypeConnectionLimiter, NewOutbound) outbound.Register[option.ConnectionLimiterOutboundOptions](registry, C.TypeConnectionLimiter, NewOutbound)
} }
var _ adapter.Lifecycle = (*Outbound)(nil)
type Outbound struct { type Outbound struct {
outbound.Adapter outbound.Adapter
ctx context.Context ctx context.Context
@@ -87,19 +89,19 @@ func (h *Outbound) Network() []string {
return []string{N.NetworkTCP, N.NetworkUDP} return []string{N.NetworkTCP, N.NetworkUDP}
} }
func (h *Outbound) Start() error { func (h *Outbound) Start(stage adapter.StartStage) error {
detour, loaded := h.outbound.Outbound(h.outboundTag) if stage == adapter.StartStateStart {
if !loaded { detour, loaded := h.outbound.Outbound(h.outboundTag)
return E.New("outbound not found: ", h.outboundTag) if !loaded {
} return E.New("outbound not found: ", h.outboundTag)
h.detour = detour
for _, stage := range []adapter.StartStage{adapter.StartStateStart, adapter.StartStatePostStart, adapter.StartStateStarted} {
err := h.router.Start(stage)
if err != nil {
return err
} }
h.detour = detour
} }
return nil return h.router.Start(stage)
}
func (h *Outbound) Close() error {
return h.router.Close()
} }
func (h *Outbound) DialContext(ctx context.Context, network string, destination M.Socksaddr) (net.Conn, error) { func (h *Outbound) DialContext(ctx context.Context, network string, destination M.Socksaddr) (net.Conn, error) {
+11 -11
View File
@@ -85,19 +85,19 @@ func (h *Outbound) Network() []string {
return []string{N.NetworkTCP, N.NetworkUDP} return []string{N.NetworkTCP, N.NetworkUDP}
} }
func (h *Outbound) Start() error { func (h *Outbound) Start(stage adapter.StartStage) error {
detour, loaded := h.outbound.Outbound(h.outboundTag) if stage == adapter.StartStateStart {
if !loaded { detour, loaded := h.outbound.Outbound(h.outboundTag)
return E.New("outbound not found: ", h.outboundTag) if !loaded {
} return E.New("outbound not found: ", h.outboundTag)
h.detour = detour
for _, stage := range []adapter.StartStage{adapter.StartStateStart, adapter.StartStatePostStart, adapter.StartStateStarted} {
err := h.router.Start(stage)
if err != nil {
return err
} }
h.detour = detour
} }
return nil return h.router.Start(stage)
}
func (h *Outbound) Close() error {
return h.router.Close()
} }
func (h *Outbound) DialContext(ctx context.Context, network string, destination M.Socksaddr) (net.Conn, error) { func (h *Outbound) DialContext(ctx context.Context, network string, destination M.Socksaddr) (net.Conn, error) {
+13 -11
View File
@@ -23,6 +23,8 @@ func RegisterOutbound(registry *outbound.Registry) {
outbound.Register[option.TrafficLimiterOutboundOptions](registry, C.TypeTrafficLimiter, NewOutbound) outbound.Register[option.TrafficLimiterOutboundOptions](registry, C.TypeTrafficLimiter, NewOutbound)
} }
var _ adapter.Lifecycle = (*Outbound)(nil)
type Outbound struct { type Outbound struct {
outbound.Adapter outbound.Adapter
ctx context.Context ctx context.Context
@@ -63,19 +65,19 @@ func (h *Outbound) Network() []string {
return []string{N.NetworkTCP, N.NetworkUDP} return []string{N.NetworkTCP, N.NetworkUDP}
} }
func (h *Outbound) Start() error { func (h *Outbound) Start(stage adapter.StartStage) error {
detour, loaded := h.outbound.Outbound(h.outboundTag) if stage == adapter.StartStateStart {
if !loaded { detour, loaded := h.outbound.Outbound(h.outboundTag)
return E.New("outbound not found: ", h.outboundTag) if !loaded {
} return E.New("outbound not found: ", h.outboundTag)
h.detour = detour
for _, stage := range []adapter.StartStage{adapter.StartStateStart, adapter.StartStatePostStart, adapter.StartStateStarted} {
err := h.router.Start(stage)
if err != nil {
return err
} }
h.detour = detour
} }
return nil return h.router.Start(stage)
}
func (h *Outbound) Close() error {
return h.router.Close()
} }
func (h *Outbound) DialContext(ctx context.Context, network string, destination M.Socksaddr) (net.Conn, error) { func (h *Outbound) DialContext(ctx context.Context, network string, destination M.Socksaddr) (net.Conn, error) {
+4
View File
@@ -78,6 +78,10 @@ func NewClientEndpoint(ctx context.Context, router adapter.Router, logger log.Co
} }
func (c *ClientEndpoint) Start(stage adapter.StartStage) error { func (c *ClientEndpoint) Start(stage adapter.StartStage) error {
err := adapter.LegacyStart(c.outbound, stage)
if err != nil {
return err
}
if stage != adapter.StartStatePostStart { if stage != adapter.StartStatePostStart {
return nil return nil
} }