github.com/xmplusdev/xmcore@v1.8.11-0.20240412132628-5518b55526af/transport/internet/system_dialer.go (about)

     1  package internet
     2  
     3  import (
     4  	"context"
     5  	"syscall"
     6  	"time"
     7  
     8  	"github.com/sagernet/sing/common/control"
     9  	"github.com/xmplusdev/xmcore/common/net"
    10  	"github.com/xmplusdev/xmcore/common/session"
    11  	"github.com/xmplusdev/xmcore/features/dns"
    12  	"github.com/xmplusdev/xmcore/features/outbound"
    13  )
    14  
    15  var effectiveSystemDialer SystemDialer = &DefaultSystemDialer{}
    16  
    17  type SystemDialer interface {
    18  	Dial(ctx context.Context, source net.Address, destination net.Destination, sockopt *SocketConfig) (net.Conn, error)
    19  	DestIpAddress() net.IP
    20  }
    21  
    22  type DefaultSystemDialer struct {
    23  	controllers []control.Func
    24  	dns         dns.Client
    25  	obm         outbound.Manager
    26  }
    27  
    28  func resolveSrcAddr(network net.Network, src net.Address) net.Addr {
    29  	if src == nil || src == net.AnyIP {
    30  		return nil
    31  	}
    32  
    33  	if network == net.Network_TCP {
    34  		return &net.TCPAddr{
    35  			IP:   src.IP(),
    36  			Port: 0,
    37  		}
    38  	}
    39  
    40  	return &net.UDPAddr{
    41  		IP:   src.IP(),
    42  		Port: 0,
    43  	}
    44  }
    45  
    46  func hasBindAddr(sockopt *SocketConfig) bool {
    47  	return sockopt != nil && len(sockopt.BindAddress) > 0 && sockopt.BindPort > 0
    48  }
    49  
    50  func (d *DefaultSystemDialer) Dial(ctx context.Context, src net.Address, dest net.Destination, sockopt *SocketConfig) (net.Conn, error) {
    51  	newError("dialing to " + dest.String()).AtDebug().WriteToLog()
    52  
    53  	if dest.Network == net.Network_UDP && !hasBindAddr(sockopt) {
    54  		srcAddr := resolveSrcAddr(net.Network_UDP, src)
    55  		if srcAddr == nil {
    56  			srcAddr = &net.UDPAddr{
    57  				IP:   []byte{0, 0, 0, 0},
    58  				Port: 0,
    59  			}
    60  		}
    61  		packetConn, err := ListenSystemPacket(ctx, srcAddr, sockopt)
    62  		if err != nil {
    63  			return nil, err
    64  		}
    65  		destAddr, err := net.ResolveUDPAddr("udp", dest.NetAddr())
    66  		if err != nil {
    67  			return nil, err
    68  		}
    69  		if sockopt != nil {
    70  			sys, err := packetConn.(*net.UDPConn).SyscallConn()
    71  			if err != nil {
    72  				return nil, err
    73  			}
    74  			sys.Control(func(fd uintptr) {
    75  				if err := applyOutboundSocketOptions("udp", dest.NetAddr(), fd, sockopt); err != nil {
    76  					newError("failed to apply socket options").Base(err).WriteToLog(session.ExportIDToError(ctx))
    77  				}
    78  			})
    79  		}
    80  		return &PacketConnWrapper{
    81  			Conn: packetConn,
    82  			Dest: destAddr,
    83  		}, nil
    84  	}
    85  	goStdKeepAlive := time.Duration(0)
    86  	if sockopt != nil && (sockopt.TcpKeepAliveInterval != 0 || sockopt.TcpKeepAliveIdle != 0) {
    87  		goStdKeepAlive = time.Duration(-1)
    88  	}
    89  	dialer := &net.Dialer{
    90  		Timeout:   time.Second * 16,
    91  		LocalAddr: resolveSrcAddr(dest.Network, src),
    92  		KeepAlive: goStdKeepAlive,
    93  	}
    94  
    95  	if sockopt != nil || len(d.controllers) > 0 {
    96  		if sockopt != nil && sockopt.TcpMptcp {
    97  			dialer.SetMultipathTCP(true)
    98  		}
    99  		dialer.Control = func(network, address string, c syscall.RawConn) error {
   100  			for _, ctl := range d.controllers {
   101  				if err := ctl(network, address, c); err != nil {
   102  					newError("failed to apply external controller").Base(err).WriteToLog(session.ExportIDToError(ctx))
   103  				}
   104  			}
   105  			return c.Control(func(fd uintptr) {
   106  				if sockopt != nil {
   107  					if err := applyOutboundSocketOptions(network, address, fd, sockopt); err != nil {
   108  						newError("failed to apply socket options").Base(err).WriteToLog(session.ExportIDToError(ctx))
   109  					}
   110  					if dest.Network == net.Network_UDP && hasBindAddr(sockopt) {
   111  						if err := bindAddr(fd, sockopt.BindAddress, sockopt.BindPort); err != nil {
   112  							newError("failed to bind source address to ", sockopt.BindAddress).Base(err).WriteToLog(session.ExportIDToError(ctx))
   113  						}
   114  					}
   115  				}
   116  			})
   117  		}
   118  	}
   119  
   120  	return dialer.DialContext(ctx, dest.Network.SystemString(), dest.NetAddr())
   121  }
   122  
   123  func (d *DefaultSystemDialer) DestIpAddress() net.IP {
   124  	return nil
   125  }
   126  
   127  type PacketConnWrapper struct {
   128  	Conn net.PacketConn
   129  	Dest net.Addr
   130  }
   131  
   132  func (c *PacketConnWrapper) Close() error {
   133  	return c.Conn.Close()
   134  }
   135  
   136  func (c *PacketConnWrapper) LocalAddr() net.Addr {
   137  	return c.Conn.LocalAddr()
   138  }
   139  
   140  func (c *PacketConnWrapper) RemoteAddr() net.Addr {
   141  	return c.Dest
   142  }
   143  
   144  func (c *PacketConnWrapper) Write(p []byte) (int, error) {
   145  	return c.Conn.WriteTo(p, c.Dest)
   146  }
   147  
   148  func (c *PacketConnWrapper) Read(p []byte) (int, error) {
   149  	n, _, err := c.Conn.ReadFrom(p)
   150  	return n, err
   151  }
   152  
   153  func (c *PacketConnWrapper) WriteTo(p []byte, d net.Addr) (int, error) {
   154  	return c.Conn.WriteTo(p, d)
   155  }
   156  
   157  func (c *PacketConnWrapper) ReadFrom(p []byte) (int, net.Addr, error) {
   158  	return c.Conn.ReadFrom(p)
   159  }
   160  
   161  func (c *PacketConnWrapper) SetDeadline(t time.Time) error {
   162  	return c.Conn.SetDeadline(t)
   163  }
   164  
   165  func (c *PacketConnWrapper) SetReadDeadline(t time.Time) error {
   166  	return c.Conn.SetReadDeadline(t)
   167  }
   168  
   169  func (c *PacketConnWrapper) SetWriteDeadline(t time.Time) error {
   170  	return c.Conn.SetWriteDeadline(t)
   171  }
   172  
   173  type SystemDialerAdapter interface {
   174  	Dial(network string, address string) (net.Conn, error)
   175  }
   176  
   177  type SimpleSystemDialer struct {
   178  	adapter SystemDialerAdapter
   179  }
   180  
   181  func WithAdapter(dialer SystemDialerAdapter) SystemDialer {
   182  	return &SimpleSystemDialer{
   183  		adapter: dialer,
   184  	}
   185  }
   186  
   187  func (v *SimpleSystemDialer) Dial(ctx context.Context, src net.Address, dest net.Destination, sockopt *SocketConfig) (net.Conn, error) {
   188  	return v.adapter.Dial(dest.Network.SystemString(), dest.NetAddr())
   189  }
   190  
   191  func (d *SimpleSystemDialer) DestIpAddress() net.IP {
   192  	return nil
   193  }
   194  
   195  // UseAlternativeSystemDialer replaces the current system dialer with a given one.
   196  // Caller must ensure there is no race condition.
   197  //
   198  // xray:api:stable
   199  func UseAlternativeSystemDialer(dialer SystemDialer) {
   200  	if dialer == nil {
   201  		dialer = &DefaultSystemDialer{}
   202  	}
   203  	effectiveSystemDialer = dialer
   204  }
   205  
   206  // RegisterDialerController adds a controller to the effective system dialer.
   207  // The controller can be used to operate on file descriptors before they are put into use.
   208  // It only works when effective dialer is the default dialer.
   209  //
   210  // xray:api:beta
   211  func RegisterDialerController(ctl control.Func) error {
   212  	if ctl == nil {
   213  		return newError("nil listener controller")
   214  	}
   215  
   216  	dialer, ok := effectiveSystemDialer.(*DefaultSystemDialer)
   217  	if !ok {
   218  		return newError("RegisterListenerController not supported in custom dialer")
   219  	}
   220  
   221  	dialer.controllers = append(dialer.controllers, ctl)
   222  	return nil
   223  }