dialer.go 3.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687
  1. package dialer
  2. import (
  3. "context"
  4. "net"
  5. "net/netip"
  6. "time"
  7. "github.com/sagernet/sing-box/adapter"
  8. C "github.com/sagernet/sing-box/constant"
  9. "github.com/sagernet/sing-box/option"
  10. "github.com/sagernet/sing-dns"
  11. E "github.com/sagernet/sing/common/exceptions"
  12. M "github.com/sagernet/sing/common/metadata"
  13. N "github.com/sagernet/sing/common/network"
  14. "github.com/sagernet/sing/service"
  15. )
  16. func New(ctx context.Context, options option.DialerOptions) (N.Dialer, error) {
  17. networkManager := service.FromContext[adapter.NetworkManager](ctx)
  18. if options.IsWireGuardListener {
  19. return NewDefault(networkManager, options)
  20. }
  21. var (
  22. dialer N.Dialer
  23. err error
  24. )
  25. if options.Detour == "" {
  26. dialer, err = NewDefault(networkManager, options)
  27. if err != nil {
  28. return nil, err
  29. }
  30. } else {
  31. outboundManager := service.FromContext[adapter.OutboundManager](ctx)
  32. if outboundManager == nil {
  33. return nil, E.New("missing outbound manager")
  34. }
  35. dialer = NewDetour(outboundManager, options.Detour)
  36. }
  37. if networkManager == nil {
  38. return NewDefault(networkManager, options)
  39. }
  40. if options.Detour == "" {
  41. router := service.FromContext[adapter.Router](ctx)
  42. if router != nil {
  43. dialer = NewResolveDialer(
  44. router,
  45. dialer,
  46. options.Detour == "" && !options.TCPFastOpen,
  47. dns.DomainStrategy(options.DomainStrategy),
  48. time.Duration(options.FallbackDelay))
  49. }
  50. }
  51. return dialer, nil
  52. }
  53. func NewDirect(ctx context.Context, options option.DialerOptions) (ParallelInterfaceDialer, error) {
  54. if options.Detour != "" {
  55. return nil, E.New("`detour` is not supported in direct context")
  56. }
  57. networkManager := service.FromContext[adapter.NetworkManager](ctx)
  58. if options.IsWireGuardListener {
  59. return NewDefault(networkManager, options)
  60. }
  61. dialer, err := NewDefault(networkManager, options)
  62. if err != nil {
  63. return nil, err
  64. }
  65. return NewResolveParallelInterfaceDialer(
  66. service.FromContext[adapter.Router](ctx),
  67. dialer,
  68. true,
  69. dns.DomainStrategy(options.DomainStrategy),
  70. time.Duration(options.FallbackDelay),
  71. ), nil
  72. }
  73. type ParallelInterfaceDialer interface {
  74. N.Dialer
  75. DialParallelInterface(ctx context.Context, network string, destination M.Socksaddr, strategy C.NetworkStrategy, interfaceType []C.InterfaceType, fallbackInterfaceType []C.InterfaceType, fallbackDelay time.Duration) (net.Conn, error)
  76. ListenSerialInterfacePacket(ctx context.Context, destination M.Socksaddr, strategy C.NetworkStrategy, interfaceType []C.InterfaceType, fallbackInterfaceType []C.InterfaceType, fallbackDelay time.Duration) (net.PacketConn, error)
  77. }
  78. type ParallelNetworkDialer interface {
  79. DialParallelNetwork(ctx context.Context, network string, destination M.Socksaddr, destinationAddresses []netip.Addr, strategy C.NetworkStrategy, interfaceType []C.InterfaceType, fallbackInterfaceType []C.InterfaceType, fallbackDelay time.Duration) (net.Conn, error)
  80. ListenSerialNetworkPacket(ctx context.Context, destination M.Socksaddr, destinationAddresses []netip.Addr, strategy C.NetworkStrategy, interfaceType []C.InterfaceType, fallbackInterfaceType []C.InterfaceType, fallbackDelay time.Duration) (net.PacketConn, netip.Addr, error)
  81. }