Move auto-redirect and bridge index allocation out of constructors

This commit is contained in:
世界
2026-10-09 12:36:03 +08:00
parent f9fcb8964f
commit 02537831e1
5 changed files with 58 additions and 58 deletions
+13 -6
View File
@@ -50,21 +50,28 @@ type backendBase struct {
readGroup sync.WaitGroup
}
func (b *backendBase) init(ctx context.Context, logger logger.ContextLogger, networkManager adapter.NetworkManager, tag string, options option.BridgeOutboundOptions) error {
index, err := allocateBridgeIndex()
if err != nil {
return err
}
func (b *backendBase) init(ctx context.Context, logger logger.ContextLogger, networkManager adapter.NetworkManager, tag string, options option.BridgeOutboundOptions) {
b.ctx = ctx
b.logger = logger
b.networkManager = networkManager
b.tag = tag
b.index = index
b.bridgeName = options.BridgeName
if b.bridgeName == "" {
b.bridgeName = "bridge"
}
b.boundInterface = options.Interface
}
func (b *backendBase) allocateIndex(scope *adapter.Scope) error {
index, err := allocateBridgeIndex()
if err != nil {
return err
}
scope.Add(func() error {
releaseBridgeIndex(index)
return nil
})
b.index = index
b.inet4Port = addressAt(bridgeInet4Base, index)
b.inet6Port = addressAt(bridgeInet6Base, index)
return nil
+7 -10
View File
@@ -59,12 +59,7 @@ func newBackend(ctx context.Context, logger logger.ContextLogger, networkManager
instance := &backendDarwin{
writeBatch: make([]*buf.Buffer, 0, bridgeWriteBatchSize),
}
err := instance.init(ctx, logger, networkManager, tag, options)
if err != nil {
return nil, err
}
instance.inet4Local = addressAt(bridgeInet4LocalBase, instance.index)
instance.inet6Local = addressAt(bridgeInet6LocalBase, instance.index)
instance.init(ctx, logger, networkManager, tag, options)
platformInterface := service.FromContext[adapter.PlatformInterface](ctx)
if platformInterface != nil && platformInterface.UsePlatformBridge() {
instance.platform = platformInterface
@@ -75,10 +70,12 @@ func newBackend(ctx context.Context, logger logger.ContextLogger, networkManager
func (b *backendDarwin) Start(stage adapter.StartStage, scope *adapter.Scope) error {
switch stage {
case adapter.StartStateInitialize:
scope.Add(func() error {
releaseBridgeIndex(b.index)
return nil
})
err := b.allocateIndex(scope)
if err != nil {
return err
}
b.inet4Local = addressAt(bridgeInet4LocalBase, b.index)
b.inet6Local = addressAt(bridgeInet6LocalBase, b.index)
case adapter.StartStateStart:
b.closed = scope.Context().Done()
if b.platform != nil {
+8 -11
View File
@@ -42,10 +42,7 @@ type backendLinux struct {
func newBackend(ctx context.Context, logger logger.ContextLogger, networkManager adapter.NetworkManager, tag string, options option.BridgeOutboundOptions) (Backend, error) {
instance := &backendLinux{}
err := instance.init(ctx, logger, networkManager, tag, options)
if err != nil {
return nil, err
}
instance.init(ctx, logger, networkManager, tag, options)
platformInterface := service.FromContext[adapter.PlatformInterface](ctx)
if platformInterface != nil && platformInterface.UsePlatformBridge() {
instance.platform = platformInterface
@@ -56,9 +53,6 @@ func newBackend(ctx context.Context, logger logger.ContextLogger, networkManager
}
if instance.boundInterface != "" || instance.platform != nil {
instance.routeTable = options.IPRoute2TableIndex
if instance.routeTable == 0 {
instance.routeTable = defaultBridgeTableIndexBase + int(instance.index)
}
}
return instance, nil
}
@@ -66,10 +60,13 @@ func newBackend(ctx context.Context, logger logger.ContextLogger, networkManager
func (b *backendLinux) Start(stage adapter.StartStage, scope *adapter.Scope) error {
switch stage {
case adapter.StartStateInitialize:
scope.Add(func() error {
releaseBridgeIndex(b.index)
return nil
})
err := b.allocateIndex(scope)
if err != nil {
return err
}
if b.routeTable == 0 && (b.boundInterface != "" || b.platform != nil) {
b.routeTable = defaultBridgeTableIndexBase + int(b.index)
}
case adapter.StartStateStart:
b.closed = scope.Context().Done()
if b.platform != nil {
+2 -8
View File
@@ -133,20 +133,14 @@ type backendWindows struct {
func newBackend(ctx context.Context, logger logger.ContextLogger, networkManager adapter.NetworkManager, tag string, options option.BridgeOutboundOptions) (Backend, error) {
instance := &backendWindows{}
err := instance.init(ctx, logger, networkManager, tag, options)
if err != nil {
return nil, err
}
instance.init(ctx, logger, networkManager, tag, options)
return instance, nil
}
func (b *backendWindows) Start(stage adapter.StartStage, scope *adapter.Scope) error {
switch stage {
case adapter.StartStateInitialize:
scope.Add(func() error {
releaseBridgeIndex(b.index)
return nil
})
return b.allocateIndex(scope)
case adapter.StartStateStart:
return b.start(scope)
}
+28 -23
View File
@@ -51,6 +51,8 @@ type Inbound struct {
tunStack tun.Stack
platformInterface adapter.PlatformInterface
platformOptions option.TunPlatformOptions
enableAutoRedirect bool
disableNFTables bool
autoRedirect tun.AutoRedirect
routeRuleSet []adapter.RuleSet
routeExcludeRuleSet []adapter.RuleSet
@@ -256,22 +258,12 @@ func NewInbound(ctx context.Context, router adapter.Router, logger log.ContextLo
if !options.AutoRoute {
return nil, E.New("`auto_route` is required by `auto_redirect`")
}
disableNFTables, dErr := strconv.ParseBool(os.Getenv("DISABLE_NFTABLES"))
inbound.autoRedirect, err = tun.NewAutoRedirect(tun.AutoRedirectOptions{
TunOptions: &inbound.tunOptions,
Context: ctx,
Handler: (*autoRedirectHandler)(inbound),
Logger: logger,
NetworkMonitor: networkManager.NetworkMonitor(),
InterfaceFinder: networkManager.InterfaceFinder(),
TableName: "sing-box",
DisableNFTables: dErr == nil && disableNFTables,
RouteAddressSet: &inbound.routeAddressSet,
RouteExcludeAddressSet: &inbound.routeExcludeAddressSet,
})
if err != nil {
return nil, E.Cause(err, "initialize auto-redirect")
if !C.IsLinux {
return nil, E.New("`auto_redirect` is only supported on Linux")
}
disableNFTables, parseErr := strconv.ParseBool(os.Getenv("DISABLE_NFTABLES"))
inbound.enableAutoRedirect = true
inbound.disableNFTables = parseErr == nil && disableNFTables
if !C.IsAndroid {
inbound.tunOptions.AutoRedirectMarkMode = true
if options.NetNs == "" {
@@ -328,9 +320,6 @@ func (t *Inbound) Tag() string {
func (t *Inbound) Start(stage adapter.StartStage, scope *adapter.Scope) error {
switch stage {
case adapter.StartStateInitialize:
if t.autoRedirect != nil {
scope.Add(t.autoRedirect.Close)
}
if t.tunOptions.DNSModeOrDefault() != tun.DNSModeDisabled && len(t.tunOptions.DNSAddress) == 0 {
inet4DNSAddress, _ := t.tunOptions.Inet4DNSAddress()
inet6DNSAddress, _ := t.tunOptions.Inet6DNSAddress()
@@ -374,6 +363,24 @@ func (t *Inbound) Start(stage adapter.StartStage, scope *adapter.Scope) error {
t.tunOptions.NetNs = manager.ResolvePath(t.tunOptions.NetNs)
}
}
var err error
if t.enableAutoRedirect {
t.autoRedirect, err = tun.NewAutoRedirect(tun.AutoRedirectOptions{
TunOptions: &t.tunOptions,
Context: t.ctx,
Handler: (*autoRedirectHandler)(t),
Logger: t.logger,
NetworkMonitor: t.networkManager.NetworkMonitor(),
InterfaceFinder: t.networkManager.InterfaceFinder(),
TableName: "sing-box",
DisableNFTables: t.disableNFTables,
RouteAddressSet: &t.routeAddressSet,
RouteExcludeAddressSet: &t.routeExcludeAddressSet,
})
if err != nil {
return E.Cause(err, "initialize auto-redirect")
}
}
if t.platformInterface == nil || C.IsWindows {
for _, routeRuleSet := range t.routeRuleSet {
ipSets := routeRuleSet.ExtractIPSet()
@@ -406,10 +413,7 @@ func (t *Inbound) Start(stage adapter.StartStage, scope *adapter.Scope) error {
}
}
}
var (
tunInterface tun.Tun
err error
)
var tunInterface tun.Tun
monitor := taskmonitor.New(t.logger, C.StartTimeout)
tunOptions := t.tunOptions
if t.autoRedirect == nil && !(runtime.GOOS == "android" && t.platformInterface != nil) {
@@ -492,8 +496,9 @@ func (t *Inbound) Start(stage adapter.StartStage, scope *adapter.Scope) error {
return E.Cause(err, "starting TUN interface")
}
if t.autoRedirect != nil {
scope.Add(t.autoRedirect.Close)
monitor.Start("initialize auto-redirect")
err := t.autoRedirect.Start()
err = t.autoRedirect.Start()
monitor.Finish()
if err != nil {
return E.Cause(err, "auto-redirect")