system_dialer.go 2.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687
  1. package internet
  2. import (
  3. "context"
  4. "syscall"
  5. "time"
  6. "v2ray.com/core/common/net"
  7. "v2ray.com/core/common/session"
  8. )
  9. var (
  10. effectiveSystemDialer SystemDialer = DefaultSystemDialer{}
  11. )
  12. type SystemDialer interface {
  13. Dial(ctx context.Context, source net.Address, destination net.Destination, sockopt *SocketConfig) (net.Conn, error)
  14. }
  15. type DefaultSystemDialer struct {
  16. }
  17. func (DefaultSystemDialer) Dial(ctx context.Context, src net.Address, dest net.Destination, sockopt *SocketConfig) (net.Conn, error) {
  18. dialer := &net.Dialer{
  19. Timeout: time.Second * 60,
  20. DualStack: true,
  21. }
  22. if sockopt != nil {
  23. dialer.Control = func(network, address string, c syscall.RawConn) error {
  24. return c.Control(func(fd uintptr) {
  25. if err := applyOutboundSocketOptions(network, address, fd, sockopt); err != nil {
  26. newError("failed to apply socket options").Base(err).WriteToLog(session.ExportIDToError(ctx))
  27. }
  28. if dest.Network == net.Network_UDP && len(sockopt.BindAddress) > 0 && sockopt.BindPort > 0 {
  29. if err := bindAddr(fd, sockopt.BindAddress, sockopt.BindPort); err != nil {
  30. newError("failed to bind source address to ", sockopt.BindAddress).Base(err).WriteToLog(session.ExportIDToError(ctx))
  31. }
  32. }
  33. })
  34. }
  35. }
  36. if src != nil && src != net.AnyIP {
  37. var addr net.Addr
  38. if dest.Network == net.Network_TCP {
  39. addr = &net.TCPAddr{
  40. IP: src.IP(),
  41. Port: 0,
  42. }
  43. } else {
  44. addr = &net.UDPAddr{
  45. IP: src.IP(),
  46. Port: 0,
  47. }
  48. }
  49. dialer.LocalAddr = addr
  50. }
  51. return dialer.DialContext(ctx, dest.Network.SystemString(), dest.NetAddr())
  52. }
  53. type SystemDialerAdapter interface {
  54. Dial(network string, address string) (net.Conn, error)
  55. }
  56. type SimpleSystemDialer struct {
  57. adapter SystemDialerAdapter
  58. }
  59. func WithAdapter(dialer SystemDialerAdapter) SystemDialer {
  60. return &SimpleSystemDialer{
  61. adapter: dialer,
  62. }
  63. }
  64. func (v *SimpleSystemDialer) Dial(ctx context.Context, src net.Address, dest net.Destination, sockopt *SocketConfig) (net.Conn, error) {
  65. return v.adapter.Dial(dest.Network.SystemString(), dest.NetAddr())
  66. }
  67. // UseAlternativeSystemDialer replaces the current system dialer with a given one.
  68. // Caller must ensure there is no race condition.
  69. func UseAlternativeSystemDialer(dialer SystemDialer) {
  70. if dialer == nil {
  71. effectiveSystemDialer = DefaultSystemDialer{}
  72. }
  73. effectiveSystemDialer = dialer
  74. }