mirror of
https://gitclone.com/github.com/MetaCubeX/Clash.Meta
synced 2025-05-12 21:18:03 +08:00
chore: apply the default interface/mark of the dialer in the final stage
This commit is contained in:
parent
9c5067e519
commit
619c9dc0c6
@ -20,34 +20,16 @@ const (
|
|||||||
DefaultUDPTimeout = DefaultTCPTimeout
|
DefaultUDPTimeout = DefaultTCPTimeout
|
||||||
)
|
)
|
||||||
|
|
||||||
type dialFunc func(ctx context.Context, network string, ips []netip.Addr, port string, opt *option) (net.Conn, error)
|
type dialFunc func(ctx context.Context, network string, ips []netip.Addr, port string, opt option) (net.Conn, error)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
dialMux sync.Mutex
|
dialMux sync.Mutex
|
||||||
IP4PEnable bool
|
|
||||||
actualSingleStackDialContext = serialSingleStackDialContext
|
actualSingleStackDialContext = serialSingleStackDialContext
|
||||||
actualDualStackDialContext = serialDualStackDialContext
|
actualDualStackDialContext = serialDualStackDialContext
|
||||||
tcpConcurrent = false
|
tcpConcurrent = false
|
||||||
fallbackTimeout = 300 * time.Millisecond
|
fallbackTimeout = 300 * time.Millisecond
|
||||||
)
|
)
|
||||||
|
|
||||||
func applyOptions(options ...Option) *option {
|
|
||||||
opt := &option{
|
|
||||||
interfaceName: DefaultInterface.Load(),
|
|
||||||
routingMark: int(DefaultRoutingMark.Load()),
|
|
||||||
}
|
|
||||||
|
|
||||||
for _, o := range DefaultOptions {
|
|
||||||
o(opt)
|
|
||||||
}
|
|
||||||
|
|
||||||
for _, o := range options {
|
|
||||||
o(opt)
|
|
||||||
}
|
|
||||||
|
|
||||||
return opt
|
|
||||||
}
|
|
||||||
|
|
||||||
func DialContext(ctx context.Context, network, address string, options ...Option) (net.Conn, error) {
|
func DialContext(ctx context.Context, network, address string, options ...Option) (net.Conn, error) {
|
||||||
opt := applyOptions(options...)
|
opt := applyOptions(options...)
|
||||||
|
|
||||||
@ -77,38 +59,43 @@ func DialContext(ctx context.Context, network, address string, options ...Option
|
|||||||
}
|
}
|
||||||
|
|
||||||
func ListenPacket(ctx context.Context, network, address string, rAddrPort netip.AddrPort, options ...Option) (net.PacketConn, error) {
|
func ListenPacket(ctx context.Context, network, address string, rAddrPort netip.AddrPort, options ...Option) (net.PacketConn, error) {
|
||||||
cfg := applyOptions(options...)
|
opt := applyOptions(options...)
|
||||||
|
|
||||||
lc := &net.ListenConfig{}
|
lc := &net.ListenConfig{}
|
||||||
if cfg.addrReuse {
|
if opt.addrReuse {
|
||||||
addrReuseToListenConfig(lc)
|
addrReuseToListenConfig(lc)
|
||||||
}
|
}
|
||||||
if DefaultSocketHook != nil { // ignore interfaceName, routingMark when DefaultSocketHook not null (in CMFA)
|
if DefaultSocketHook != nil { // ignore interfaceName, routingMark when DefaultSocketHook not null (in CMFA)
|
||||||
socketHookToListenConfig(lc)
|
socketHookToListenConfig(lc)
|
||||||
} else {
|
} else {
|
||||||
interfaceName := cfg.interfaceName
|
if opt.interfaceName == "" {
|
||||||
if interfaceName == "" {
|
opt.interfaceName = DefaultInterface.Load()
|
||||||
|
}
|
||||||
|
if opt.interfaceName == "" {
|
||||||
if finder := DefaultInterfaceFinder.Load(); finder != nil {
|
if finder := DefaultInterfaceFinder.Load(); finder != nil {
|
||||||
interfaceName = finder.FindInterfaceName(rAddrPort.Addr())
|
opt.interfaceName = finder.FindInterfaceName(rAddrPort.Addr())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if rAddrPort.Addr().Unmap().IsLoopback() {
|
if rAddrPort.Addr().Unmap().IsLoopback() {
|
||||||
// avoid "The requested address is not valid in its context."
|
// avoid "The requested address is not valid in its context."
|
||||||
interfaceName = ""
|
opt.interfaceName = ""
|
||||||
}
|
}
|
||||||
if interfaceName != "" {
|
if opt.interfaceName != "" {
|
||||||
bind := bindIfaceToListenConfig
|
bind := bindIfaceToListenConfig
|
||||||
if cfg.fallbackBind {
|
if opt.fallbackBind {
|
||||||
bind = fallbackBindIfaceToListenConfig
|
bind = fallbackBindIfaceToListenConfig
|
||||||
}
|
}
|
||||||
addr, err := bind(interfaceName, lc, network, address, rAddrPort)
|
addr, err := bind(opt.interfaceName, lc, network, address, rAddrPort)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
address = addr
|
address = addr
|
||||||
}
|
}
|
||||||
if cfg.routingMark != 0 {
|
if opt.routingMark == 0 {
|
||||||
bindMarkToListenConfig(cfg.routingMark, lc, network, address)
|
opt.routingMark = int(DefaultRoutingMark.Load())
|
||||||
|
}
|
||||||
|
if opt.routingMark != 0 {
|
||||||
|
bindMarkToListenConfig(opt.routingMark, lc, network, address)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -134,7 +121,7 @@ func GetTcpConcurrent() bool {
|
|||||||
return tcpConcurrent
|
return tcpConcurrent
|
||||||
}
|
}
|
||||||
|
|
||||||
func dialContext(ctx context.Context, network string, destination netip.Addr, port string, opt *option) (net.Conn, error) {
|
func dialContext(ctx context.Context, network string, destination netip.Addr, port string, opt option) (net.Conn, error) {
|
||||||
var address string
|
var address string
|
||||||
destination, port = resolver.LookupIP4P(destination, port)
|
destination, port = resolver.LookupIP4P(destination, port)
|
||||||
address = net.JoinHostPort(destination.String(), port)
|
address = net.JoinHostPort(destination.String(), port)
|
||||||
@ -159,21 +146,26 @@ func dialContext(ctx context.Context, network string, destination netip.Addr, po
|
|||||||
if DefaultSocketHook != nil { // ignore interfaceName, routingMark and tfo when DefaultSocketHook not null (in CMFA)
|
if DefaultSocketHook != nil { // ignore interfaceName, routingMark and tfo when DefaultSocketHook not null (in CMFA)
|
||||||
socketHookToToDialer(dialer)
|
socketHookToToDialer(dialer)
|
||||||
} else {
|
} else {
|
||||||
interfaceName := opt.interfaceName // don't change the "opt", it's a pointer
|
if opt.interfaceName == "" {
|
||||||
if interfaceName == "" {
|
opt.interfaceName = DefaultInterface.Load()
|
||||||
|
}
|
||||||
|
if opt.interfaceName == "" {
|
||||||
if finder := DefaultInterfaceFinder.Load(); finder != nil {
|
if finder := DefaultInterfaceFinder.Load(); finder != nil {
|
||||||
interfaceName = finder.FindInterfaceName(destination)
|
opt.interfaceName = finder.FindInterfaceName(destination)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if interfaceName != "" {
|
if opt.interfaceName != "" {
|
||||||
bind := bindIfaceToDialer
|
bind := bindIfaceToDialer
|
||||||
if opt.fallbackBind {
|
if opt.fallbackBind {
|
||||||
bind = fallbackBindIfaceToDialer
|
bind = fallbackBindIfaceToDialer
|
||||||
}
|
}
|
||||||
if err := bind(interfaceName, dialer, network, destination); err != nil {
|
if err := bind(opt.interfaceName, dialer, network, destination); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if opt.routingMark == 0 {
|
||||||
|
opt.routingMark = int(DefaultRoutingMark.Load())
|
||||||
|
}
|
||||||
if opt.routingMark != 0 {
|
if opt.routingMark != 0 {
|
||||||
bindMarkToDialer(opt.routingMark, dialer, network, destination)
|
bindMarkToDialer(opt.routingMark, dialer, network, destination)
|
||||||
}
|
}
|
||||||
@ -185,26 +177,26 @@ func dialContext(ctx context.Context, network string, destination netip.Addr, po
|
|||||||
return dialer.DialContext(ctx, network, address)
|
return dialer.DialContext(ctx, network, address)
|
||||||
}
|
}
|
||||||
|
|
||||||
func serialSingleStackDialContext(ctx context.Context, network string, ips []netip.Addr, port string, opt *option) (net.Conn, error) {
|
func serialSingleStackDialContext(ctx context.Context, network string, ips []netip.Addr, port string, opt option) (net.Conn, error) {
|
||||||
return serialDialContext(ctx, network, ips, port, opt)
|
return serialDialContext(ctx, network, ips, port, opt)
|
||||||
}
|
}
|
||||||
|
|
||||||
func serialDualStackDialContext(ctx context.Context, network string, ips []netip.Addr, port string, opt *option) (net.Conn, error) {
|
func serialDualStackDialContext(ctx context.Context, network string, ips []netip.Addr, port string, opt option) (net.Conn, error) {
|
||||||
return dualStackDialContext(ctx, serialDialContext, network, ips, port, opt)
|
return dualStackDialContext(ctx, serialDialContext, network, ips, port, opt)
|
||||||
}
|
}
|
||||||
|
|
||||||
func concurrentSingleStackDialContext(ctx context.Context, network string, ips []netip.Addr, port string, opt *option) (net.Conn, error) {
|
func concurrentSingleStackDialContext(ctx context.Context, network string, ips []netip.Addr, port string, opt option) (net.Conn, error) {
|
||||||
return parallelDialContext(ctx, network, ips, port, opt)
|
return parallelDialContext(ctx, network, ips, port, opt)
|
||||||
}
|
}
|
||||||
|
|
||||||
func concurrentDualStackDialContext(ctx context.Context, network string, ips []netip.Addr, port string, opt *option) (net.Conn, error) {
|
func concurrentDualStackDialContext(ctx context.Context, network string, ips []netip.Addr, port string, opt option) (net.Conn, error) {
|
||||||
if opt.prefer != 4 && opt.prefer != 6 {
|
if opt.prefer != 4 && opt.prefer != 6 {
|
||||||
return parallelDialContext(ctx, network, ips, port, opt)
|
return parallelDialContext(ctx, network, ips, port, opt)
|
||||||
}
|
}
|
||||||
return dualStackDialContext(ctx, parallelDialContext, network, ips, port, opt)
|
return dualStackDialContext(ctx, parallelDialContext, network, ips, port, opt)
|
||||||
}
|
}
|
||||||
|
|
||||||
func dualStackDialContext(ctx context.Context, dialFn dialFunc, network string, ips []netip.Addr, port string, opt *option) (net.Conn, error) {
|
func dualStackDialContext(ctx context.Context, dialFn dialFunc, network string, ips []netip.Addr, port string, opt option) (net.Conn, error) {
|
||||||
ipv4s, ipv6s := resolver.SortationAddr(ips)
|
ipv4s, ipv6s := resolver.SortationAddr(ips)
|
||||||
if len(ipv4s) == 0 && len(ipv6s) == 0 {
|
if len(ipv4s) == 0 && len(ipv6s) == 0 {
|
||||||
return nil, ErrorNoIpAddress
|
return nil, ErrorNoIpAddress
|
||||||
@ -285,7 +277,7 @@ loop:
|
|||||||
return nil, errors.Join(errs...)
|
return nil, errors.Join(errs...)
|
||||||
}
|
}
|
||||||
|
|
||||||
func parallelDialContext(ctx context.Context, network string, ips []netip.Addr, port string, opt *option) (net.Conn, error) {
|
func parallelDialContext(ctx context.Context, network string, ips []netip.Addr, port string, opt option) (net.Conn, error) {
|
||||||
if len(ips) == 0 {
|
if len(ips) == 0 {
|
||||||
return nil, ErrorNoIpAddress
|
return nil, ErrorNoIpAddress
|
||||||
}
|
}
|
||||||
@ -324,7 +316,7 @@ func parallelDialContext(ctx context.Context, network string, ips []netip.Addr,
|
|||||||
return nil, os.ErrDeadlineExceeded
|
return nil, os.ErrDeadlineExceeded
|
||||||
}
|
}
|
||||||
|
|
||||||
func serialDialContext(ctx context.Context, network string, ips []netip.Addr, port string, opt *option) (net.Conn, error) {
|
func serialDialContext(ctx context.Context, network string, ips []netip.Addr, port string, opt option) (net.Conn, error) {
|
||||||
if len(ips) == 0 {
|
if len(ips) == 0 {
|
||||||
return nil, ErrorNoIpAddress
|
return nil, ErrorNoIpAddress
|
||||||
}
|
}
|
||||||
@ -390,5 +382,5 @@ func (d Dialer) ListenPacket(ctx context.Context, network, address string, rAddr
|
|||||||
|
|
||||||
func NewDialer(options ...Option) Dialer {
|
func NewDialer(options ...Option) Dialer {
|
||||||
opt := applyOptions(options...)
|
opt := applyOptions(options...)
|
||||||
return Dialer{Opt: *opt}
|
return Dialer{Opt: opt}
|
||||||
}
|
}
|
||||||
|
@ -10,7 +10,6 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
DefaultOptions []Option
|
|
||||||
DefaultInterface = atomic.NewTypedValue[string]("")
|
DefaultInterface = atomic.NewTypedValue[string]("")
|
||||||
DefaultRoutingMark = atomic.NewInt32(0)
|
DefaultRoutingMark = atomic.NewInt32(0)
|
||||||
|
|
||||||
@ -117,9 +116,13 @@ func WithOption(o option) Option {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func IsZeroOptions(opts []Option) bool {
|
func IsZeroOptions(opts []Option) bool {
|
||||||
var opt option
|
return applyOptions(opts...) == option{}
|
||||||
for _, o := range opts {
|
}
|
||||||
|
|
||||||
|
func applyOptions(options ...Option) option {
|
||||||
|
opt := option{}
|
||||||
|
for _, o := range options {
|
||||||
o(&opt)
|
o(&opt)
|
||||||
}
|
}
|
||||||
return opt == option{}
|
return opt
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user