system_dialer.go 2.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384
  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) (net.Conn, error)
  14. }
  15. type DefaultSystemDialer struct {
  16. }
  17. func (DefaultSystemDialer) Dial(ctx context.Context, src net.Address, dest net.Destination) (net.Conn, error) {
  18. dialer := &net.Dialer{
  19. Timeout: time.Second * 60,
  20. DualStack: true,
  21. }
  22. streamSettings := StreamSettingsFromContext(ctx)
  23. if streamSettings != nil && streamSettings.SocketSettings != nil {
  24. config := streamSettings.SocketSettings
  25. dialer.Control = func(network, address string, c syscall.RawConn) error {
  26. return c.Control(func(fd uintptr) {
  27. if err := applyOutboundSocketOptions(network, address, fd, config); err != nil {
  28. newError("failed to apply socket options").Base(err).WriteToLog(session.ExportIDToError(ctx))
  29. }
  30. })
  31. }
  32. }
  33. if src != nil && src != net.AnyIP {
  34. var addr net.Addr
  35. if dest.Network == net.Network_TCP {
  36. addr = &net.TCPAddr{
  37. IP: src.IP(),
  38. Port: 0,
  39. }
  40. } else {
  41. addr = &net.UDPAddr{
  42. IP: src.IP(),
  43. Port: 0,
  44. }
  45. }
  46. dialer.LocalAddr = addr
  47. }
  48. return dialer.DialContext(ctx, dest.Network.SystemString(), dest.NetAddr())
  49. }
  50. type SystemDialerAdapter interface {
  51. Dial(network string, address string) (net.Conn, error)
  52. }
  53. type SimpleSystemDialer struct {
  54. adapter SystemDialerAdapter
  55. }
  56. func WithAdapter(dialer SystemDialerAdapter) SystemDialer {
  57. return &SimpleSystemDialer{
  58. adapter: dialer,
  59. }
  60. }
  61. func (v *SimpleSystemDialer) Dial(ctx context.Context, src net.Address, dest net.Destination) (net.Conn, error) {
  62. return v.adapter.Dial(dest.Network.SystemString(), dest.NetAddr())
  63. }
  64. // UseAlternativeSystemDialer replaces the current system dialer with a given one.
  65. // Caller must ensure there is no race condition.
  66. func UseAlternativeSystemDialer(dialer SystemDialer) {
  67. if dialer == nil {
  68. effectiveSystemDialer = DefaultSystemDialer{}
  69. }
  70. effectiveSystemDialer = dialer
  71. }