system_dialer.go 2.2 KB

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