github.com/Uhtred009/v2ray-core-1@v4.31.2+incompatible/transport/internet/system_dialer.go (about)

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