diff --git a/adapter/outbound/hysteria2.go b/adapter/outbound/hysteria2.go index e7ad91df..57c15a12 100644 --- a/adapter/outbound/hysteria2.go +++ b/adapter/outbound/hysteria2.go @@ -19,7 +19,6 @@ import ( "github.com/metacubex/sing-quic/hysteria2" M "github.com/sagernet/sing/common/metadata" - N "github.com/sagernet/sing/common/network" ) func init() { @@ -31,7 +30,7 @@ type Hysteria2 struct { option *Hysteria2Option client *hysteria2.Client - dialer *hy2SingDialer + dialer proxydialer.SingDialer } type Hysteria2Option struct { @@ -53,40 +52,9 @@ type Hysteria2Option struct { CWND int `proxy:"cwnd,omitempty"` } -type hy2SingDialer struct { - dialer dialer.Dialer - proxyName string -} - -var _ N.Dialer = (*hy2SingDialer)(nil) - -func (d *hy2SingDialer) DialContext(ctx context.Context, network string, destination M.Socksaddr) (net.Conn, error) { - var cDialer C.Dialer = d.dialer - if len(d.proxyName) > 0 { - pd, err := proxydialer.NewByName(d.proxyName, d.dialer) - if err != nil { - return nil, err - } - cDialer = pd - } - return cDialer.DialContext(ctx, network, destination.String()) -} - -func (d *hy2SingDialer) ListenPacket(ctx context.Context, destination M.Socksaddr) (net.PacketConn, error) { - var cDialer C.Dialer = d.dialer - if len(d.proxyName) > 0 { - pd, err := proxydialer.NewByName(d.proxyName, d.dialer) - if err != nil { - return nil, err - } - cDialer = pd - } - return cDialer.ListenPacket(ctx, "udp", "", destination.AddrPort()) -} - func (h *Hysteria2) DialContext(ctx context.Context, metadata *C.Metadata, opts ...dialer.Option) (_ C.Conn, err error) { options := h.Base.DialOptions(opts...) - h.dialer.dialer = dialer.NewDialer(options...) + h.dialer.SetDialer(dialer.NewDialer(options...)) c, err := h.client.DialConn(ctx, M.ParseSocksaddr(metadata.RemoteAddress())) if err != nil { return nil, err @@ -96,7 +64,7 @@ func (h *Hysteria2) DialContext(ctx context.Context, metadata *C.Metadata, opts func (h *Hysteria2) ListenPacketContext(ctx context.Context, metadata *C.Metadata, opts ...dialer.Option) (_ C.PacketConn, err error) { options := h.Base.DialOptions(opts...) - h.dialer.dialer = dialer.NewDialer(options...) + h.dialer.SetDialer(dialer.NewDialer(options...)) pc, err := h.client.ListenPacket(ctx) if err != nil { return nil, err @@ -149,7 +117,7 @@ func NewHysteria2(option Hysteria2Option) (*Hysteria2, error) { tlsConfig.NextProtos = option.ALPN } - singDialer := &hy2SingDialer{dialer: dialer.NewDialer(), proxyName: option.DialerProxy} + singDialer := proxydialer.NewByNameSingDialer(option.DialerProxy, dialer.NewDialer()) clientOptions := hysteria2.ClientOptions{ Context: context.TODO(), diff --git a/adapter/outbound/singmux.go b/adapter/outbound/singmux.go index 9a977318..c9f50ce9 100644 --- a/adapter/outbound/singmux.go +++ b/adapter/outbound/singmux.go @@ -3,7 +3,6 @@ package outbound import ( "context" "errors" - "net" "runtime" CN "github.com/Dreamacro/clash/common/net" @@ -15,14 +14,13 @@ import ( mux "github.com/sagernet/sing-mux" E "github.com/sagernet/sing/common/exceptions" M "github.com/sagernet/sing/common/metadata" - N "github.com/sagernet/sing/common/network" ) type SingMux struct { C.ProxyAdapter base ProxyBase client *mux.Client - dialer *muxSingDialer + dialer proxydialer.SingDialer onlyTcp bool } @@ -41,27 +39,9 @@ type ProxyBase interface { DialOptions(opts ...dialer.Option) []dialer.Option } -type muxSingDialer struct { - dialer dialer.Dialer - proxy C.ProxyAdapter - statistic bool -} - -var _ N.Dialer = (*muxSingDialer)(nil) - -func (d *muxSingDialer) DialContext(ctx context.Context, network string, destination M.Socksaddr) (net.Conn, error) { - var cDialer C.Dialer = proxydialer.New(d.proxy, d.dialer, d.statistic) - return cDialer.DialContext(ctx, network, destination.String()) -} - -func (d *muxSingDialer) ListenPacket(ctx context.Context, destination M.Socksaddr) (net.PacketConn, error) { - var cDialer C.Dialer = proxydialer.New(d.proxy, d.dialer, d.statistic) - return cDialer.ListenPacket(ctx, "udp", "", destination.AddrPort()) -} - func (s *SingMux) DialContext(ctx context.Context, metadata *C.Metadata, opts ...dialer.Option) (_ C.Conn, err error) { options := s.base.DialOptions(opts...) - s.dialer.dialer = dialer.NewDialer(options...) + s.dialer.SetDialer(dialer.NewDialer(options...)) c, err := s.client.DialContext(ctx, "tcp", M.ParseSocksaddr(metadata.RemoteAddress())) if err != nil { return nil, err @@ -74,7 +54,7 @@ func (s *SingMux) ListenPacketContext(ctx context.Context, metadata *C.Metadata, return s.ProxyAdapter.ListenPacketContext(ctx, metadata, opts...) } options := s.base.DialOptions(opts...) - s.dialer.dialer = dialer.NewDialer(options...) + s.dialer.SetDialer(dialer.NewDialer(options...)) // sing-mux use stream-oriented udp with a special address, so we need a net.UDPAddr if !metadata.Resolved() { @@ -114,7 +94,7 @@ func closeSingMux(s *SingMux) { } func NewSingMux(option SingMuxOption, proxy C.ProxyAdapter, base ProxyBase) (C.ProxyAdapter, error) { - singDialer := &muxSingDialer{dialer: dialer.NewDialer(), proxy: proxy, statistic: option.Statistic} + singDialer := proxydialer.NewSingDialer(proxy, dialer.NewDialer(), option.Statistic) client, err := mux.NewClient(mux.Options{ Dialer: singDialer, Protocol: option.Protocol, diff --git a/adapter/outbound/wireguard.go b/adapter/outbound/wireguard.go index c1050ac6..6a11a234 100644 --- a/adapter/outbound/wireguard.go +++ b/adapter/outbound/wireguard.go @@ -27,7 +27,6 @@ import ( "github.com/sagernet/sing/common/debug" E "github.com/sagernet/sing/common/exceptions" M "github.com/sagernet/sing/common/metadata" - N "github.com/sagernet/sing/common/network" "github.com/sagernet/wireguard-go/device" ) @@ -36,7 +35,7 @@ type WireGuard struct { bind *wireguard.ClientBind device *device.Device tunDevice wireguard.Device - dialer *wgSingDialer + dialer proxydialer.SingDialer startOnce sync.Once startErr error resolver *dns.Resolver @@ -70,37 +69,6 @@ type WireGuardPeerOption struct { AllowedIPs []string `proxy:"allowed-ips,omitempty"` } -type wgSingDialer struct { - dialer dialer.Dialer - proxyName string -} - -var _ N.Dialer = (*wgSingDialer)(nil) - -func (d *wgSingDialer) DialContext(ctx context.Context, network string, destination M.Socksaddr) (net.Conn, error) { - var cDialer C.Dialer = d.dialer - if len(d.proxyName) > 0 { - pd, err := proxydialer.NewByName(d.proxyName, d.dialer) - if err != nil { - return nil, err - } - cDialer = pd - } - return cDialer.DialContext(ctx, network, destination.String()) -} - -func (d *wgSingDialer) ListenPacket(ctx context.Context, destination M.Socksaddr) (net.PacketConn, error) { - var cDialer C.Dialer = d.dialer - if len(d.proxyName) > 0 { - pd, err := proxydialer.NewByName(d.proxyName, d.dialer) - if err != nil { - return nil, err - } - cDialer = pd - } - return cDialer.ListenPacket(ctx, "udp", "", destination.AddrPort()) -} - type wgSingErrorHandler struct { name string } @@ -168,7 +136,7 @@ func NewWireGuard(option WireGuardOption) (*WireGuard, error) { rmark: option.RoutingMark, prefer: C.NewDNSPrefer(option.IPVersion), }, - dialer: &wgSingDialer{dialer: dialer.NewDialer(), proxyName: option.DialerProxy}, + dialer: proxydialer.NewByNameSingDialer(option.DialerProxy, dialer.NewDialer()), } runtime.SetFinalizer(outbound, closeWireGuard) @@ -355,7 +323,7 @@ func closeWireGuard(w *WireGuard) { func (w *WireGuard) DialContext(ctx context.Context, metadata *C.Metadata, opts ...dialer.Option) (_ C.Conn, err error) { options := w.Base.DialOptions(opts...) - w.dialer.dialer = dialer.NewDialer(options...) + w.dialer.SetDialer(dialer.NewDialer(options...)) var conn net.Conn w.startOnce.Do(func() { w.startErr = w.tunDevice.Start() @@ -387,7 +355,7 @@ func (w *WireGuard) DialContext(ctx context.Context, metadata *C.Metadata, opts func (w *WireGuard) ListenPacketContext(ctx context.Context, metadata *C.Metadata, opts ...dialer.Option) (_ C.PacketConn, err error) { options := w.Base.DialOptions(opts...) - w.dialer.dialer = dialer.NewDialer(options...) + w.dialer.SetDialer(dialer.NewDialer(options...)) var pc net.PacketConn w.startOnce.Do(func() { w.startErr = w.tunDevice.Start() diff --git a/component/proxydialer/sing.go b/component/proxydialer/sing.go new file mode 100644 index 00000000..9b116527 --- /dev/null +++ b/component/proxydialer/sing.go @@ -0,0 +1,82 @@ +package proxydialer + +import ( + "context" + "net" + + C "github.com/Dreamacro/clash/constant" + + M "github.com/sagernet/sing/common/metadata" + N "github.com/sagernet/sing/common/network" +) + +type SingDialer interface { + N.Dialer + SetDialer(dialer C.Dialer) +} + +type singDialer proxyDialer + +var _ N.Dialer = (*singDialer)(nil) + +func (d *singDialer) DialContext(ctx context.Context, network string, destination M.Socksaddr) (net.Conn, error) { + return (*proxyDialer)(d).DialContext(ctx, network, destination.String()) +} + +func (d *singDialer) ListenPacket(ctx context.Context, destination M.Socksaddr) (net.PacketConn, error) { + return (*proxyDialer)(d).ListenPacket(ctx, "udp", "", destination.AddrPort()) +} + +func (d *singDialer) SetDialer(dialer C.Dialer) { + (*proxyDialer)(d).dialer = dialer +} + +func NewSingDialer(proxy C.ProxyAdapter, dialer C.Dialer, statistic bool) SingDialer { + return (*singDialer)(&proxyDialer{ + proxy: proxy, + dialer: dialer, + statistic: statistic, + }) +} + +type byNameSingDialer struct { + dialer C.Dialer + proxyName string +} + +var _ N.Dialer = (*byNameSingDialer)(nil) + +func (d *byNameSingDialer) DialContext(ctx context.Context, network string, destination M.Socksaddr) (net.Conn, error) { + var cDialer C.Dialer = d.dialer + if len(d.proxyName) > 0 { + pd, err := NewByName(d.proxyName, d.dialer) + if err != nil { + return nil, err + } + cDialer = pd + } + return cDialer.DialContext(ctx, network, destination.String()) +} + +func (d *byNameSingDialer) ListenPacket(ctx context.Context, destination M.Socksaddr) (net.PacketConn, error) { + var cDialer C.Dialer = d.dialer + if len(d.proxyName) > 0 { + pd, err := NewByName(d.proxyName, d.dialer) + if err != nil { + return nil, err + } + cDialer = pd + } + return cDialer.ListenPacket(ctx, "udp", "", destination.AddrPort()) +} + +func (d *byNameSingDialer) SetDialer(dialer C.Dialer) { + d.dialer = dialer +} + +func NewByNameSingDialer(proxyName string, dialer C.Dialer) SingDialer { + return &byNameSingDialer{ + dialer: dialer, + proxyName: proxyName, + } +}