mirror of
https://github.com/SagerNet/sing-box.git
synced 2024-12-26 14:35:38 +08:00
Fix default dialer on legacy xiaomi systems
This commit is contained in:
parent
f72118135e
commit
339e3e6c15
|
@ -2,8 +2,10 @@ package dialer
|
|||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"net"
|
||||
"net/netip"
|
||||
"syscall"
|
||||
"time"
|
||||
|
||||
"github.com/sagernet/sing-box/adapter"
|
||||
|
@ -26,20 +28,21 @@ var (
|
|||
)
|
||||
|
||||
type DefaultDialer struct {
|
||||
dialer4 tcpDialer
|
||||
dialer6 tcpDialer
|
||||
udpDialer4 net.Dialer
|
||||
udpDialer6 net.Dialer
|
||||
udpListener net.ListenConfig
|
||||
udpAddr4 string
|
||||
udpAddr6 string
|
||||
isWireGuardListener bool
|
||||
networkManager adapter.NetworkManager
|
||||
networkStrategy *C.NetworkStrategy
|
||||
networkType []C.InterfaceType
|
||||
fallbackNetworkType []C.InterfaceType
|
||||
networkFallbackDelay time.Duration
|
||||
networkLastFallback atomic.TypedValue[time.Time]
|
||||
dialer4 tcpDialer
|
||||
dialer6 tcpDialer
|
||||
udpDialer4 net.Dialer
|
||||
udpDialer6 net.Dialer
|
||||
udpListener net.ListenConfig
|
||||
udpAddr4 string
|
||||
udpAddr6 string
|
||||
isWireGuardListener bool
|
||||
networkManager adapter.NetworkManager
|
||||
networkStrategy *C.NetworkStrategy
|
||||
defaultNetworkStrategy bool
|
||||
networkType []C.InterfaceType
|
||||
fallbackNetworkType []C.InterfaceType
|
||||
networkFallbackDelay time.Duration
|
||||
networkLastFallback atomic.TypedValue[time.Time]
|
||||
}
|
||||
|
||||
func NewDefault(ctx context.Context, options option.DialerOptions) (*DefaultDialer, error) {
|
||||
|
@ -47,13 +50,14 @@ func NewDefault(ctx context.Context, options option.DialerOptions) (*DefaultDial
|
|||
platformInterface := service.FromContext[platform.Interface](ctx)
|
||||
|
||||
var (
|
||||
dialer net.Dialer
|
||||
listener net.ListenConfig
|
||||
interfaceFinder control.InterfaceFinder
|
||||
networkStrategy *C.NetworkStrategy
|
||||
networkType []C.InterfaceType
|
||||
fallbackNetworkType []C.InterfaceType
|
||||
networkFallbackDelay time.Duration
|
||||
dialer net.Dialer
|
||||
listener net.ListenConfig
|
||||
interfaceFinder control.InterfaceFinder
|
||||
networkStrategy *C.NetworkStrategy
|
||||
defaultNetworkStrategy bool
|
||||
networkType []C.InterfaceType
|
||||
fallbackNetworkType []C.InterfaceType
|
||||
networkFallbackDelay time.Duration
|
||||
)
|
||||
if networkManager != nil {
|
||||
interfaceFinder = networkManager.InterfaceFinder()
|
||||
|
@ -98,6 +102,7 @@ func NewDefault(ctx context.Context, options option.DialerOptions) (*DefaultDial
|
|||
networkStrategy = (*C.NetworkStrategy)(options.NetworkStrategy)
|
||||
if networkStrategy == nil {
|
||||
networkStrategy = common.Ptr(C.NetworkStrategyDefault)
|
||||
defaultNetworkStrategy = true
|
||||
}
|
||||
networkType = common.Map(options.NetworkType, option.InterfaceType.Build)
|
||||
fallbackNetworkType = common.Map(options.FallbackNetworkType, option.InterfaceType.Build)
|
||||
|
@ -192,19 +197,20 @@ func NewDefault(ctx context.Context, options option.DialerOptions) (*DefaultDial
|
|||
return nil, err
|
||||
}
|
||||
return &DefaultDialer{
|
||||
dialer4: tcpDialer4,
|
||||
dialer6: tcpDialer6,
|
||||
udpDialer4: udpDialer4,
|
||||
udpDialer6: udpDialer6,
|
||||
udpListener: listener,
|
||||
udpAddr4: udpAddr4,
|
||||
udpAddr6: udpAddr6,
|
||||
isWireGuardListener: options.IsWireGuardListener,
|
||||
networkManager: networkManager,
|
||||
networkStrategy: networkStrategy,
|
||||
networkType: networkType,
|
||||
fallbackNetworkType: fallbackNetworkType,
|
||||
networkFallbackDelay: networkFallbackDelay,
|
||||
dialer4: tcpDialer4,
|
||||
dialer6: tcpDialer6,
|
||||
udpDialer4: udpDialer4,
|
||||
udpDialer6: udpDialer6,
|
||||
udpListener: listener,
|
||||
udpAddr4: udpAddr4,
|
||||
udpAddr6: udpAddr6,
|
||||
isWireGuardListener: options.IsWireGuardListener,
|
||||
networkManager: networkManager,
|
||||
networkStrategy: networkStrategy,
|
||||
defaultNetworkStrategy: defaultNetworkStrategy,
|
||||
networkType: networkType,
|
||||
fallbackNetworkType: fallbackNetworkType,
|
||||
networkFallbackDelay: networkFallbackDelay,
|
||||
}, nil
|
||||
}
|
||||
|
||||
|
@ -265,7 +271,13 @@ func (d *DefaultDialer) DialParallelInterface(ctx context.Context, network strin
|
|||
conn, isPrimary, err = d.dialParallelInterfaceFastFallback(ctx, dialer, network, address.String(), *strategy, interfaceType, fallbackInterfaceType, fallbackDelay, d.networkLastFallback.Store)
|
||||
}
|
||||
if err != nil {
|
||||
return nil, err
|
||||
// bind interface failed on legacy xiaomi systems
|
||||
if d.defaultNetworkStrategy && errors.Is(err, syscall.EPERM) {
|
||||
d.networkStrategy = nil
|
||||
return d.DialContext(ctx, network, address)
|
||||
} else {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
if !fastFallback && !isPrimary {
|
||||
d.networkLastFallback.Store(time.Now())
|
||||
|
@ -307,7 +319,17 @@ func (d *DefaultDialer) ListenSerialInterfacePacket(ctx context.Context, destina
|
|||
if destination.IsIPv4() && !destination.Addr.IsUnspecified() {
|
||||
network += "4"
|
||||
}
|
||||
return trackPacketConn(d.listenSerialInterfacePacket(ctx, d.udpListener, network, "", *strategy, interfaceType, fallbackInterfaceType, fallbackDelay))
|
||||
packetConn, err := d.listenSerialInterfacePacket(ctx, d.udpListener, network, "", *strategy, interfaceType, fallbackInterfaceType, fallbackDelay)
|
||||
if err != nil {
|
||||
// bind interface failed on legacy xiaomi systems
|
||||
if d.defaultNetworkStrategy && errors.Is(err, syscall.EPERM) {
|
||||
d.networkStrategy = nil
|
||||
return d.ListenPacket(ctx, destination)
|
||||
} else {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
return trackPacketConn(packetConn, nil)
|
||||
}
|
||||
|
||||
func (d *DefaultDialer) ListenPacketCompat(network, address string) (net.PacketConn, error) {
|
||||
|
|
|
@ -35,7 +35,7 @@ func (d *DefaultDialer) dialParallelInterface(ctx context.Context, dialer net.Di
|
|||
conn, err := perNetDialer.DialContext(ctx, network, addr)
|
||||
if err != nil {
|
||||
select {
|
||||
case results <- dialResult{error: E.Cause(err, "dial ", iif.Name, " (", iif.Name, ")"), primary: primary}:
|
||||
case results <- dialResult{error: E.Cause(err, "dial ", iif.Name, " (", iif.Index, ")"), primary: primary}:
|
||||
case <-returned:
|
||||
}
|
||||
} else {
|
||||
|
@ -107,7 +107,7 @@ func (d *DefaultDialer) dialParallelInterfaceFastFallback(ctx context.Context, d
|
|||
conn, err := perNetDialer.DialContext(ctx, network, addr)
|
||||
if err != nil {
|
||||
select {
|
||||
case results <- dialResult{error: E.Cause(err, "dial ", iif.Name, " (", iif.Name, ")"), primary: primary}:
|
||||
case results <- dialResult{error: E.Cause(err, "dial ", iif.Name, " (", iif.Index, ")"), primary: primary}:
|
||||
case <-returned:
|
||||
}
|
||||
} else {
|
||||
|
@ -157,7 +157,7 @@ func (d *DefaultDialer) listenSerialInterfacePacket(ctx context.Context, listene
|
|||
if err == nil {
|
||||
return conn, nil
|
||||
}
|
||||
errors = append(errors, E.Cause(err, "listen ", primaryInterface.Name, " (", primaryInterface.Name, ")"))
|
||||
errors = append(errors, E.Cause(err, "listen ", primaryInterface.Name, " (", primaryInterface.Index, ")"))
|
||||
}
|
||||
for _, fallbackInterface := range fallbackInterfaces {
|
||||
perNetListener := listener
|
||||
|
@ -166,7 +166,7 @@ func (d *DefaultDialer) listenSerialInterfacePacket(ctx context.Context, listene
|
|||
if err == nil {
|
||||
return conn, nil
|
||||
}
|
||||
errors = append(errors, E.Cause(err, "listen ", fallbackInterface.Name, " (", fallbackInterface.Name, ")"))
|
||||
errors = append(errors, E.Cause(err, "listen ", fallbackInterface.Name, " (", fallbackInterface.Index, ")"))
|
||||
}
|
||||
return nil, E.Errors(errors...)
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue
Block a user