chore: rebuild relay
This commit is contained in:
parent
f09afc8d8a
commit
ec0136af1b
15 changed files with 296 additions and 246 deletions
|
@ -57,26 +57,26 @@ func (b *Base) DialContext(ctx context.Context, metadata *C.Metadata, opts ...di
|
||||||
return nil, errors.New("no support")
|
return nil, errors.New("no support")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// DialContextWithDialer implements C.ProxyAdapter
|
||||||
|
func (b *Base) DialContextWithDialer(ctx context.Context, dialer C.Dialer, metadata *C.Metadata) (_ C.Conn, err error) {
|
||||||
|
return nil, errors.New("no support")
|
||||||
|
}
|
||||||
|
|
||||||
// ListenPacketContext implements C.ProxyAdapter
|
// ListenPacketContext implements C.ProxyAdapter
|
||||||
func (b *Base) ListenPacketContext(ctx context.Context, metadata *C.Metadata, opts ...dialer.Option) (C.PacketConn, error) {
|
func (b *Base) ListenPacketContext(ctx context.Context, metadata *C.Metadata, opts ...dialer.Option) (C.PacketConn, error) {
|
||||||
return nil, errors.New("no support")
|
return nil, errors.New("no support")
|
||||||
}
|
}
|
||||||
|
|
||||||
// ListenPacketOnPacketConn implements C.ProxyAdapter
|
// ListenPacketWithDialer implements C.ProxyAdapter
|
||||||
func (b *Base) ListenPacketOnPacketConn(ctx context.Context, c C.PacketConn, metadata *C.Metadata) (C.PacketConn, error) {
|
func (b *Base) ListenPacketWithDialer(ctx context.Context, dialer C.Dialer, metadata *C.Metadata) (_ C.PacketConn, err error) {
|
||||||
return nil, errors.New("no support")
|
return nil, errors.New("no support")
|
||||||
}
|
}
|
||||||
|
|
||||||
// SupportLPPC implements C.ProxyAdapter
|
// SupportWithDialer implements C.ProxyAdapter
|
||||||
func (b *Base) SupportLPPC() bool {
|
func (b *Base) SupportWithDialer() bool {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
// ListenPacketOnStreamConn implements C.ProxyAdapter
|
|
||||||
func (b *Base) ListenPacketOnStreamConn(c net.Conn, metadata *C.Metadata) (_ C.PacketConn, err error) {
|
|
||||||
return nil, errors.New("no support")
|
|
||||||
}
|
|
||||||
|
|
||||||
// SupportUOT implements C.ProxyAdapter
|
// SupportUOT implements C.ProxyAdapter
|
||||||
func (b *Base) SupportUOT() bool {
|
func (b *Base) SupportUOT() bool {
|
||||||
return false
|
return false
|
||||||
|
|
|
@ -61,7 +61,12 @@ func (h *Http) StreamConn(c net.Conn, metadata *C.Metadata) (net.Conn, error) {
|
||||||
|
|
||||||
// DialContext implements C.ProxyAdapter
|
// DialContext implements C.ProxyAdapter
|
||||||
func (h *Http) DialContext(ctx context.Context, metadata *C.Metadata, opts ...dialer.Option) (_ C.Conn, err error) {
|
func (h *Http) DialContext(ctx context.Context, metadata *C.Metadata, opts ...dialer.Option) (_ C.Conn, err error) {
|
||||||
c, err := dialer.DialContext(ctx, "tcp", h.addr, h.Base.DialOptions(opts...)...)
|
return h.DialContextWithDialer(ctx, dialer.Dialer{Options: h.Base.DialOptions(opts...)}, metadata)
|
||||||
|
}
|
||||||
|
|
||||||
|
// DialContextWithDialer implements C.ProxyAdapter
|
||||||
|
func (h *Http) DialContextWithDialer(ctx context.Context, dialer C.Dialer, metadata *C.Metadata) (_ C.Conn, err error) {
|
||||||
|
c, err := dialer.DialContext(ctx, "tcp", h.addr)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("%s connect error: %w", h.addr, err)
|
return nil, fmt.Errorf("%s connect error: %w", h.addr, err)
|
||||||
}
|
}
|
||||||
|
@ -79,6 +84,11 @@ func (h *Http) DialContext(ctx context.Context, metadata *C.Metadata, opts ...di
|
||||||
return NewConn(c, h), nil
|
return NewConn(c, h), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// SupportWithDialer implements C.ProxyAdapter
|
||||||
|
func (h *Http) SupportWithDialer() bool {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
func (h *Http) shakeHand(metadata *C.Metadata, rw io.ReadWriter) error {
|
func (h *Http) shakeHand(metadata *C.Metadata, rw io.ReadWriter) error {
|
||||||
addr := metadata.RemoteAddress()
|
addr := metadata.RemoteAddress()
|
||||||
req := &http.Request{
|
req := &http.Request{
|
||||||
|
|
|
@ -84,7 +84,12 @@ func (ss *ShadowSocks) StreamConn(c net.Conn, metadata *C.Metadata) (net.Conn, e
|
||||||
|
|
||||||
// DialContext implements C.ProxyAdapter
|
// DialContext implements C.ProxyAdapter
|
||||||
func (ss *ShadowSocks) DialContext(ctx context.Context, metadata *C.Metadata, opts ...dialer.Option) (_ C.Conn, err error) {
|
func (ss *ShadowSocks) DialContext(ctx context.Context, metadata *C.Metadata, opts ...dialer.Option) (_ C.Conn, err error) {
|
||||||
c, err := dialer.DialContext(ctx, "tcp", ss.addr, ss.Base.DialOptions(opts...)...)
|
return ss.DialContextWithDialer(ctx, dialer.Dialer{Options: ss.Base.DialOptions(opts...)}, metadata)
|
||||||
|
}
|
||||||
|
|
||||||
|
// DialContextWithDialer implements C.ProxyAdapter
|
||||||
|
func (ss *ShadowSocks) DialContextWithDialer(ctx context.Context, dialer C.Dialer, metadata *C.Metadata) (_ C.Conn, err error) {
|
||||||
|
c, err := dialer.DialContext(ctx, "tcp", ss.addr)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("%s connect error: %w", ss.addr, err)
|
return nil, fmt.Errorf("%s connect error: %w", ss.addr, err)
|
||||||
}
|
}
|
||||||
|
@ -100,8 +105,13 @@ func (ss *ShadowSocks) DialContext(ctx context.Context, metadata *C.Metadata, op
|
||||||
|
|
||||||
// ListenPacketContext implements C.ProxyAdapter
|
// ListenPacketContext implements C.ProxyAdapter
|
||||||
func (ss *ShadowSocks) ListenPacketContext(ctx context.Context, metadata *C.Metadata, opts ...dialer.Option) (C.PacketConn, error) {
|
func (ss *ShadowSocks) ListenPacketContext(ctx context.Context, metadata *C.Metadata, opts ...dialer.Option) (C.PacketConn, error) {
|
||||||
|
return ss.ListenPacketWithDialer(ctx, dialer.Dialer{Options: ss.Base.DialOptions(opts...)}, metadata)
|
||||||
|
}
|
||||||
|
|
||||||
|
// ListenPacketWithDialer implements C.ProxyAdapter
|
||||||
|
func (ss *ShadowSocks) ListenPacketWithDialer(ctx context.Context, dialer C.Dialer, metadata *C.Metadata) (_ C.PacketConn, err error) {
|
||||||
if ss.option.UDPOverTCP {
|
if ss.option.UDPOverTCP {
|
||||||
tcpConn, err := ss.DialContext(ctx, metadata, opts...)
|
tcpConn, err := ss.DialContextWithDialer(ctx, dialer, metadata)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
@ -112,7 +122,7 @@ func (ss *ShadowSocks) ListenPacketContext(ctx context.Context, metadata *C.Meta
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
pc, err := dialer.ListenPacket(ctx, dialer.ParseNetwork("udp", addr.AddrPort().Addr()), "", ss.Base.DialOptions(opts...)...)
|
pc, err := dialer.ListenPacket(ctx, "udp", "", addr.AddrPort())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
@ -120,19 +130,8 @@ func (ss *ShadowSocks) ListenPacketContext(ctx context.Context, metadata *C.Meta
|
||||||
return newPacketConn(pc, ss), nil
|
return newPacketConn(pc, ss), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// ListenPacketOnPacketConn implements C.ProxyAdapter
|
// SupportWithDialer implements C.ProxyAdapter
|
||||||
func (ss *ShadowSocks) ListenPacketOnPacketConn(ctx context.Context, c C.PacketConn, metadata *C.Metadata) (_ C.PacketConn, err error) {
|
func (ss *ShadowSocks) SupportWithDialer() bool {
|
||||||
addr, err := resolveUDPAddrWithPrefer(ctx, "udp", ss.addr, ss.prefer)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
pc := ss.method.DialPacketConn(&bufio.BindPacketConn{PacketConn: c, Addr: addr})
|
|
||||||
return newPacketConn(pc, ss), nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// SupportLPPC implements C.ProxyAdapter
|
|
||||||
func (ss *ShadowSocks) SupportLPPC() bool {
|
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -60,7 +60,12 @@ func (ssr *ShadowSocksR) StreamConn(c net.Conn, metadata *C.Metadata) (net.Conn,
|
||||||
|
|
||||||
// DialContext implements C.ProxyAdapter
|
// DialContext implements C.ProxyAdapter
|
||||||
func (ssr *ShadowSocksR) DialContext(ctx context.Context, metadata *C.Metadata, opts ...dialer.Option) (_ C.Conn, err error) {
|
func (ssr *ShadowSocksR) DialContext(ctx context.Context, metadata *C.Metadata, opts ...dialer.Option) (_ C.Conn, err error) {
|
||||||
c, err := dialer.DialContext(ctx, "tcp", ssr.addr, ssr.Base.DialOptions(opts...)...)
|
return ssr.DialContextWithDialer(ctx, dialer.Dialer{Options: ssr.Base.DialOptions(opts...)}, metadata)
|
||||||
|
}
|
||||||
|
|
||||||
|
// DialContextWithDialer implements C.ProxyAdapter
|
||||||
|
func (ssr *ShadowSocksR) DialContextWithDialer(ctx context.Context, dialer C.Dialer, metadata *C.Metadata) (_ C.Conn, err error) {
|
||||||
|
c, err := dialer.DialContext(ctx, "tcp", ssr.addr)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("%s connect error: %w", ssr.addr, err)
|
return nil, fmt.Errorf("%s connect error: %w", ssr.addr, err)
|
||||||
}
|
}
|
||||||
|
@ -76,12 +81,17 @@ func (ssr *ShadowSocksR) DialContext(ctx context.Context, metadata *C.Metadata,
|
||||||
|
|
||||||
// ListenPacketContext implements C.ProxyAdapter
|
// ListenPacketContext implements C.ProxyAdapter
|
||||||
func (ssr *ShadowSocksR) ListenPacketContext(ctx context.Context, metadata *C.Metadata, opts ...dialer.Option) (C.PacketConn, error) {
|
func (ssr *ShadowSocksR) ListenPacketContext(ctx context.Context, metadata *C.Metadata, opts ...dialer.Option) (C.PacketConn, error) {
|
||||||
|
return ssr.ListenPacketWithDialer(ctx, dialer.Dialer{Options: ssr.Base.DialOptions(opts...)}, metadata)
|
||||||
|
}
|
||||||
|
|
||||||
|
// ListenPacketWithDialer implements C.ProxyAdapter
|
||||||
|
func (ssr *ShadowSocksR) ListenPacketWithDialer(ctx context.Context, dialer C.Dialer, metadata *C.Metadata) (_ C.PacketConn, err error) {
|
||||||
addr, err := resolveUDPAddrWithPrefer(ctx, "udp", ssr.addr, ssr.prefer)
|
addr, err := resolveUDPAddrWithPrefer(ctx, "udp", ssr.addr, ssr.prefer)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
pc, err := dialer.ListenPacket(ctx, dialer.ParseNetwork("udp", addr.AddrPort().Addr()), "", ssr.Base.DialOptions(opts...)...)
|
pc, err := dialer.ListenPacket(ctx, "udp", "", addr.AddrPort())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
@ -91,20 +101,8 @@ func (ssr *ShadowSocksR) ListenPacketContext(ctx context.Context, metadata *C.Me
|
||||||
return newPacketConn(&ssPacketConn{PacketConn: pc, rAddr: addr}, ssr), nil
|
return newPacketConn(&ssPacketConn{PacketConn: pc, rAddr: addr}, ssr), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// ListenPacketOnPacketConn implements C.ProxyAdapter
|
// SupportWithDialer implements C.ProxyAdapter
|
||||||
func (ssr *ShadowSocksR) ListenPacketOnPacketConn(ctx context.Context, c C.PacketConn, metadata *C.Metadata) (_ C.PacketConn, err error) {
|
func (ssr *ShadowSocksR) SupportWithDialer() bool {
|
||||||
addr, err := resolveUDPAddrWithPrefer(ctx, "udp", ssr.addr, ssr.prefer)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
pc := ssr.cipher.PacketConn(c)
|
|
||||||
pc = ssr.protocol.PacketConn(pc)
|
|
||||||
return newPacketConn(&ssPacketConn{PacketConn: pc, rAddr: addr}, ssr), nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// SupportLPPC implements C.ProxyAdapter
|
|
||||||
func (ssr *ShadowSocksR) SupportLPPC() bool {
|
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -78,7 +78,12 @@ func (s *Snell) DialContext(ctx context.Context, metadata *C.Metadata, opts ...d
|
||||||
return NewConn(c, s), err
|
return NewConn(c, s), err
|
||||||
}
|
}
|
||||||
|
|
||||||
c, err := dialer.DialContext(ctx, "tcp", s.addr, s.Base.DialOptions(opts...)...)
|
return s.DialContextWithDialer(ctx, dialer.Dialer{Options: s.Base.DialOptions(opts...)}, metadata)
|
||||||
|
}
|
||||||
|
|
||||||
|
// DialContextWithDialer implements C.ProxyAdapter
|
||||||
|
func (s *Snell) DialContextWithDialer(ctx context.Context, dialer C.Dialer, metadata *C.Metadata) (_ C.Conn, err error) {
|
||||||
|
c, err := dialer.DialContext(ctx, "tcp", s.addr)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("%s connect error: %w", s.addr, err)
|
return nil, fmt.Errorf("%s connect error: %w", s.addr, err)
|
||||||
}
|
}
|
||||||
|
@ -94,7 +99,12 @@ func (s *Snell) DialContext(ctx context.Context, metadata *C.Metadata, opts ...d
|
||||||
|
|
||||||
// ListenPacketContext implements C.ProxyAdapter
|
// ListenPacketContext implements C.ProxyAdapter
|
||||||
func (s *Snell) ListenPacketContext(ctx context.Context, metadata *C.Metadata, opts ...dialer.Option) (C.PacketConn, error) {
|
func (s *Snell) ListenPacketContext(ctx context.Context, metadata *C.Metadata, opts ...dialer.Option) (C.PacketConn, error) {
|
||||||
c, err := dialer.DialContext(ctx, "tcp", s.addr, s.Base.DialOptions(opts...)...)
|
return s.ListenPacketWithDialer(ctx, dialer.Dialer{Options: s.Base.DialOptions(opts...)}, metadata)
|
||||||
|
}
|
||||||
|
|
||||||
|
// ListenPacketWithDialer implements C.ProxyAdapter
|
||||||
|
func (s *Snell) ListenPacketWithDialer(ctx context.Context, dialer C.Dialer, metadata *C.Metadata) (C.PacketConn, error) {
|
||||||
|
c, err := dialer.DialContext(ctx, "tcp", s.addr)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
@ -110,10 +120,9 @@ func (s *Snell) ListenPacketContext(ctx context.Context, metadata *C.Metadata, o
|
||||||
return newPacketConn(pc, s), nil
|
return newPacketConn(pc, s), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// ListenPacketOnStreamConn implements C.ProxyAdapter
|
// SupportWithDialer implements C.ProxyAdapter
|
||||||
func (s *Snell) ListenPacketOnStreamConn(c net.Conn, metadata *C.Metadata) (_ C.PacketConn, err error) {
|
func (s *Snell) SupportWithDialer() bool {
|
||||||
pc := snell.PacketConn(c)
|
return true
|
||||||
return newPacketConn(pc, s), nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// SupportUOT implements C.ProxyAdapter
|
// SupportUOT implements C.ProxyAdapter
|
||||||
|
|
|
@ -65,7 +65,12 @@ func (ss *Socks5) StreamConn(c net.Conn, metadata *C.Metadata) (net.Conn, error)
|
||||||
|
|
||||||
// DialContext implements C.ProxyAdapter
|
// DialContext implements C.ProxyAdapter
|
||||||
func (ss *Socks5) DialContext(ctx context.Context, metadata *C.Metadata, opts ...dialer.Option) (_ C.Conn, err error) {
|
func (ss *Socks5) DialContext(ctx context.Context, metadata *C.Metadata, opts ...dialer.Option) (_ C.Conn, err error) {
|
||||||
c, err := dialer.DialContext(ctx, "tcp", ss.addr, ss.Base.DialOptions(opts...)...)
|
return ss.DialContextWithDialer(ctx, dialer.Dialer{Options: ss.Base.DialOptions(opts...)}, metadata)
|
||||||
|
}
|
||||||
|
|
||||||
|
// DialContextWithDialer implements C.ProxyAdapter
|
||||||
|
func (ss *Socks5) DialContextWithDialer(ctx context.Context, dialer C.Dialer, metadata *C.Metadata) (_ C.Conn, err error) {
|
||||||
|
c, err := dialer.DialContext(ctx, "tcp", ss.addr)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("%s connect error: %w", ss.addr, err)
|
return nil, fmt.Errorf("%s connect error: %w", ss.addr, err)
|
||||||
}
|
}
|
||||||
|
@ -83,6 +88,11 @@ func (ss *Socks5) DialContext(ctx context.Context, metadata *C.Metadata, opts ..
|
||||||
return NewConn(c, ss), nil
|
return NewConn(c, ss), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// SupportWithDialer implements C.ProxyAdapter
|
||||||
|
func (ss *Socks5) SupportWithDialer() bool {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
// ListenPacketContext implements C.ProxyAdapter
|
// ListenPacketContext implements C.ProxyAdapter
|
||||||
func (ss *Socks5) ListenPacketContext(ctx context.Context, metadata *C.Metadata, opts ...dialer.Option) (_ C.PacketConn, err error) {
|
func (ss *Socks5) ListenPacketContext(ctx context.Context, metadata *C.Metadata, opts ...dialer.Option) (_ C.PacketConn, err error) {
|
||||||
c, err := dialer.DialContext(ctx, "tcp", ss.addr, ss.Base.DialOptions(opts...)...)
|
c, err := dialer.DialContext(ctx, "tcp", ss.addr, ss.Base.DialOptions(opts...)...)
|
||||||
|
|
|
@ -120,8 +120,12 @@ func (t *Trojan) DialContext(ctx context.Context, metadata *C.Metadata, opts ...
|
||||||
|
|
||||||
return NewConn(c, t), nil
|
return NewConn(c, t), nil
|
||||||
}
|
}
|
||||||
|
return t.DialContextWithDialer(ctx, dialer.Dialer{Options: t.Base.DialOptions(opts...)}, metadata)
|
||||||
|
}
|
||||||
|
|
||||||
c, err := dialer.DialContext(ctx, "tcp", t.addr, t.Base.DialOptions(opts...)...)
|
// DialContextWithDialer implements C.ProxyAdapter
|
||||||
|
func (t *Trojan) DialContextWithDialer(ctx context.Context, dialer C.Dialer, metadata *C.Metadata) (_ C.Conn, err error) {
|
||||||
|
c, err := dialer.DialContext(ctx, "tcp", t.addr)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("%s connect error: %w", t.addr, err)
|
return nil, fmt.Errorf("%s connect error: %w", t.addr, err)
|
||||||
}
|
}
|
||||||
|
@ -152,19 +156,30 @@ func (t *Trojan) ListenPacketContext(ctx context.Context, metadata *C.Metadata,
|
||||||
defer func() {
|
defer func() {
|
||||||
safeConnClose(c, err)
|
safeConnClose(c, err)
|
||||||
}()
|
}()
|
||||||
} else {
|
err = t.instance.WriteHeader(c, trojan.CommandUDP, serializesSocksAddr(metadata))
|
||||||
c, err = dialer.DialContext(ctx, "tcp", t.addr, t.Base.DialOptions(opts...)...)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("%s connect error: %w", t.addr, err)
|
return nil, err
|
||||||
}
|
|
||||||
defer func() {
|
|
||||||
safeConnClose(c, err)
|
|
||||||
}()
|
|
||||||
tcpKeepAlive(c)
|
|
||||||
c, err = t.plainStream(c)
|
|
||||||
if err != nil {
|
|
||||||
return nil, fmt.Errorf("%s connect error: %w", t.addr, err)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pc := t.instance.PacketConn(c)
|
||||||
|
return newPacketConn(pc, t), err
|
||||||
|
}
|
||||||
|
return t.ListenPacketWithDialer(ctx, dialer.Dialer{Options: t.Base.DialOptions(opts...)}, metadata)
|
||||||
|
}
|
||||||
|
|
||||||
|
// ListenPacketWithDialer implements C.ProxyAdapter
|
||||||
|
func (t *Trojan) ListenPacketWithDialer(ctx context.Context, dialer C.Dialer, metadata *C.Metadata) (_ C.PacketConn, err error) {
|
||||||
|
c, err := dialer.DialContext(ctx, "tcp", t.addr)
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("%s connect error: %w", t.addr, err)
|
||||||
|
}
|
||||||
|
defer func() {
|
||||||
|
safeConnClose(c, err)
|
||||||
|
}()
|
||||||
|
tcpKeepAlive(c)
|
||||||
|
c, err = t.plainStream(c)
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("%s connect error: %w", t.addr, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
err = t.instance.WriteHeader(c, trojan.CommandUDP, serializesSocksAddr(metadata))
|
err = t.instance.WriteHeader(c, trojan.CommandUDP, serializesSocksAddr(metadata))
|
||||||
|
@ -176,6 +191,11 @@ func (t *Trojan) ListenPacketContext(ctx context.Context, metadata *C.Metadata,
|
||||||
return newPacketConn(pc, t), err
|
return newPacketConn(pc, t), err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// SupportWithDialer implements C.ProxyAdapter
|
||||||
|
func (t *Trojan) SupportWithDialer() bool {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
// ListenPacketOnStreamConn implements C.ProxyAdapter
|
// ListenPacketOnStreamConn implements C.ProxyAdapter
|
||||||
func (t *Trojan) ListenPacketOnStreamConn(c net.Conn, metadata *C.Metadata) (_ C.PacketConn, err error) {
|
func (t *Trojan) ListenPacketOnStreamConn(c net.Conn, metadata *C.Metadata) (_ C.PacketConn, err error) {
|
||||||
pc := t.instance.PacketConn(c)
|
pc := t.instance.PacketConn(c)
|
||||||
|
|
|
@ -219,8 +219,12 @@ func (v *Vless) DialContext(ctx context.Context, metadata *C.Metadata, opts ...d
|
||||||
|
|
||||||
return NewConn(c, v), nil
|
return NewConn(c, v), nil
|
||||||
}
|
}
|
||||||
|
return v.DialContextWithDialer(ctx, dialer.Dialer{Options: v.Base.DialOptions(opts...)}, metadata)
|
||||||
|
}
|
||||||
|
|
||||||
c, err := dialer.DialContext(ctx, "tcp", v.addr, v.Base.DialOptions(opts...)...)
|
// DialContextWithDialer implements C.ProxyAdapter
|
||||||
|
func (v *Vless) DialContextWithDialer(ctx context.Context, dialer C.Dialer, metadata *C.Metadata) (_ C.Conn, err error) {
|
||||||
|
c, err := dialer.DialContext(ctx, "tcp", v.addr)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("%s connect error: %s", v.addr, err.Error())
|
return nil, fmt.Errorf("%s connect error: %s", v.addr, err.Error())
|
||||||
}
|
}
|
||||||
|
@ -256,18 +260,36 @@ func (v *Vless) ListenPacketContext(ctx context.Context, metadata *C.Metadata, o
|
||||||
}()
|
}()
|
||||||
|
|
||||||
c, err = v.client.StreamConn(c, parseVlessAddr(metadata))
|
c, err = v.client.StreamConn(c, parseVlessAddr(metadata))
|
||||||
} else {
|
|
||||||
c, err = dialer.DialContext(ctx, "tcp", v.addr, v.Base.DialOptions(opts...)...)
|
|
||||||
if err != nil {
|
|
||||||
return nil, fmt.Errorf("%s connect error: %s", v.addr, err.Error())
|
|
||||||
}
|
|
||||||
tcpKeepAlive(c)
|
|
||||||
defer func() {
|
|
||||||
safeConnClose(c, err)
|
|
||||||
}()
|
|
||||||
|
|
||||||
c, err = v.StreamConn(c, metadata)
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("new vless client error: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
return v.ListenPacketOnStreamConn(c, metadata)
|
||||||
}
|
}
|
||||||
|
return v.ListenPacketWithDialer(ctx, dialer.Dialer{Options: v.Base.DialOptions(opts...)}, metadata)
|
||||||
|
}
|
||||||
|
|
||||||
|
// ListenPacketWithDialer implements C.ProxyAdapter
|
||||||
|
func (v *Vless) ListenPacketWithDialer(ctx context.Context, dialer C.Dialer, metadata *C.Metadata) (_ C.PacketConn, err error) {
|
||||||
|
// vless use stream-oriented udp with a special address, so we needs a net.UDPAddr
|
||||||
|
if !metadata.Resolved() {
|
||||||
|
ip, err := resolver.ResolveIP(ctx, metadata.Host)
|
||||||
|
if err != nil {
|
||||||
|
return nil, errors.New("can't resolve ip")
|
||||||
|
}
|
||||||
|
metadata.DstIP = ip
|
||||||
|
}
|
||||||
|
c, err := dialer.DialContext(ctx, "tcp", v.addr)
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("%s connect error: %s", v.addr, err.Error())
|
||||||
|
}
|
||||||
|
tcpKeepAlive(c)
|
||||||
|
defer func() {
|
||||||
|
safeConnClose(c, err)
|
||||||
|
}()
|
||||||
|
|
||||||
|
c, err = v.StreamConn(c, metadata)
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("new vless client error: %v", err)
|
return nil, fmt.Errorf("new vless client error: %v", err)
|
||||||
|
@ -276,6 +298,11 @@ func (v *Vless) ListenPacketContext(ctx context.Context, metadata *C.Metadata, o
|
||||||
return v.ListenPacketOnStreamConn(c, metadata)
|
return v.ListenPacketOnStreamConn(c, metadata)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// SupportWithDialer implements C.ProxyAdapter
|
||||||
|
func (v *Vless) SupportWithDialer() bool {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
// ListenPacketOnStreamConn implements C.ProxyAdapter
|
// ListenPacketOnStreamConn implements C.ProxyAdapter
|
||||||
func (v *Vless) ListenPacketOnStreamConn(c net.Conn, metadata *C.Metadata) (_ C.PacketConn, err error) {
|
func (v *Vless) ListenPacketOnStreamConn(c net.Conn, metadata *C.Metadata) (_ C.PacketConn, err error) {
|
||||||
return newPacketConn(&vlessPacketConn{Conn: c, rAddr: metadata.UDPAddr()}, v), nil
|
return newPacketConn(&vlessPacketConn{Conn: c, rAddr: metadata.UDPAddr()}, v), nil
|
||||||
|
|
|
@ -232,8 +232,12 @@ func (v *Vmess) DialContext(ctx context.Context, metadata *C.Metadata, opts ...d
|
||||||
|
|
||||||
return NewConn(c, v), nil
|
return NewConn(c, v), nil
|
||||||
}
|
}
|
||||||
|
return v.DialContextWithDialer(ctx, dialer.Dialer{Options: v.Base.DialOptions(opts...)}, metadata)
|
||||||
|
}
|
||||||
|
|
||||||
c, err := dialer.DialContext(ctx, "tcp", v.addr, v.Base.DialOptions(opts...)...)
|
// DialContextWithDialer implements C.ProxyAdapter
|
||||||
|
func (v *Vmess) DialContextWithDialer(ctx context.Context, dialer C.Dialer, metadata *C.Metadata) (_ C.Conn, err error) {
|
||||||
|
c, err := dialer.DialContext(ctx, "tcp", v.addr)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("%s connect error: %s", v.addr, err.Error())
|
return nil, fmt.Errorf("%s connect error: %s", v.addr, err.Error())
|
||||||
}
|
}
|
||||||
|
@ -280,29 +284,47 @@ func (v *Vmess) ListenPacketContext(ctx context.Context, metadata *C.Metadata, o
|
||||||
} else {
|
} else {
|
||||||
c, err = v.client.DialPacketConn(c, M.ParseSocksaddr(metadata.RemoteAddress()))
|
c, err = v.client.DialPacketConn(c, M.ParseSocksaddr(metadata.RemoteAddress()))
|
||||||
}
|
}
|
||||||
} else {
|
|
||||||
c, err = dialer.DialContext(ctx, "tcp", v.addr, v.Base.DialOptions(opts...)...)
|
|
||||||
if err != nil {
|
|
||||||
return nil, fmt.Errorf("%s connect error: %s", v.addr, err.Error())
|
|
||||||
}
|
|
||||||
tcpKeepAlive(c)
|
|
||||||
defer func() {
|
|
||||||
safeConnClose(c, err)
|
|
||||||
}()
|
|
||||||
|
|
||||||
c, err = v.StreamConn(c, metadata)
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("new vmess client error: %v", err)
|
||||||
|
}
|
||||||
|
return v.ListenPacketOnStreamConn(c, metadata)
|
||||||
|
}
|
||||||
|
c, err = dialer.DialContext(ctx, "tcp", v.addr, v.Base.DialOptions(opts...)...)
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("%s connect error: %s", v.addr, err.Error())
|
||||||
|
}
|
||||||
|
tcpKeepAlive(c)
|
||||||
|
defer func() {
|
||||||
|
safeConnClose(c, err)
|
||||||
|
}()
|
||||||
|
|
||||||
|
c, err = v.StreamConn(c, metadata)
|
||||||
|
return v.ListenPacketWithDialer(ctx, dialer.Dialer{Options: v.Base.DialOptions(opts...)}, metadata)
|
||||||
|
}
|
||||||
|
|
||||||
|
// ListenPacketWithDialer implements C.ProxyAdapter
|
||||||
|
func (v *Vmess) ListenPacketWithDialer(ctx context.Context, dialer C.Dialer, metadata *C.Metadata) (_ C.PacketConn, err error) {
|
||||||
|
// vmess use stream-oriented udp with a special address, so we needs a net.UDPAddr
|
||||||
|
if !metadata.Resolved() {
|
||||||
|
ip, err := resolver.ResolveIP(ctx, metadata.Host)
|
||||||
|
if err != nil {
|
||||||
|
return nil, errors.New("can't resolve ip")
|
||||||
|
}
|
||||||
|
metadata.DstIP = ip
|
||||||
}
|
}
|
||||||
|
|
||||||
|
c, err := dialer.DialContext(ctx, "tcp", v.addr)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("new vmess client error: %v", err)
|
return nil, fmt.Errorf("new vmess client error: %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
if v.option.PacketAddr {
|
return v.ListenPacketOnStreamConn(c, metadata)
|
||||||
return newPacketConn(&threadSafePacketConn{PacketConn: packetaddr.NewBindConn(c)}, v), nil
|
}
|
||||||
} else if pc, ok := c.(net.PacketConn); ok {
|
|
||||||
return newPacketConn(&threadSafePacketConn{PacketConn: pc}, v), nil
|
// SupportWithDialer implements C.ProxyAdapter
|
||||||
}
|
func (v *Vmess) SupportWithDialer() bool {
|
||||||
return newPacketConn(&vmessPacketConn{Conn: c, rAddr: metadata.UDPAddr()}, v), nil
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
// ListenPacketOnStreamConn implements C.ProxyAdapter
|
// ListenPacketOnStreamConn implements C.ProxyAdapter
|
||||||
|
|
|
@ -3,10 +3,12 @@ package outboundgroup
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"fmt"
|
|
||||||
"net"
|
"net"
|
||||||
|
"net/netip"
|
||||||
|
"strings"
|
||||||
|
|
||||||
"github.com/Dreamacro/clash/adapter/outbound"
|
"github.com/Dreamacro/clash/adapter/outbound"
|
||||||
|
N "github.com/Dreamacro/clash/common/net"
|
||||||
"github.com/Dreamacro/clash/component/dialer"
|
"github.com/Dreamacro/clash/component/dialer"
|
||||||
C "github.com/Dreamacro/clash/constant"
|
C "github.com/Dreamacro/clash/constant"
|
||||||
"github.com/Dreamacro/clash/constant/provider"
|
"github.com/Dreamacro/clash/constant/provider"
|
||||||
|
@ -16,6 +18,36 @@ type Relay struct {
|
||||||
*GroupBase
|
*GroupBase
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type proxyDialer struct {
|
||||||
|
proxy C.Proxy
|
||||||
|
dialer C.Dialer
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p proxyDialer) DialContext(ctx context.Context, network, address string) (net.Conn, error) {
|
||||||
|
currentMeta, err := addrToMetadata(address)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
if strings.Contains(network, "udp") { // should not support this operation
|
||||||
|
currentMeta.NetWork = C.UDP
|
||||||
|
pc, err := p.proxy.ListenPacketWithDialer(ctx, p.dialer, currentMeta)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return N.NewBindPacketConn(pc, currentMeta.UDPAddr()), nil
|
||||||
|
}
|
||||||
|
return p.proxy.DialContextWithDialer(ctx, p.dialer, currentMeta)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p proxyDialer) ListenPacket(ctx context.Context, network, address string, rAddrPort netip.AddrPort) (net.PacketConn, error) {
|
||||||
|
currentMeta, err := addrToMetadata(rAddrPort.String())
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
currentMeta.NetWork = C.UDP
|
||||||
|
return p.proxy.ListenPacketWithDialer(ctx, p.dialer, currentMeta)
|
||||||
|
}
|
||||||
|
|
||||||
// DialContext implements C.ProxyAdapter
|
// DialContext implements C.ProxyAdapter
|
||||||
func (r *Relay) DialContext(ctx context.Context, metadata *C.Metadata, opts ...dialer.Option) (C.Conn, error) {
|
func (r *Relay) DialContext(ctx context.Context, metadata *C.Metadata, opts ...dialer.Option) (C.Conn, error) {
|
||||||
proxies, chainProxies := r.proxies(metadata, true)
|
proxies, chainProxies := r.proxies(metadata, true)
|
||||||
|
@ -26,47 +58,20 @@ func (r *Relay) DialContext(ctx context.Context, metadata *C.Metadata, opts ...d
|
||||||
case 1:
|
case 1:
|
||||||
return proxies[0].DialContext(ctx, metadata, r.Base.DialOptions(opts...)...)
|
return proxies[0].DialContext(ctx, metadata, r.Base.DialOptions(opts...)...)
|
||||||
}
|
}
|
||||||
|
var d C.Dialer
|
||||||
first := proxies[0]
|
d = dialer.Dialer{Options: r.Base.DialOptions(opts...)}
|
||||||
|
for _, proxy := range proxies[:len(proxies)-1] {
|
||||||
|
d = proxyDialer{
|
||||||
|
proxy: proxy,
|
||||||
|
dialer: d,
|
||||||
|
}
|
||||||
|
}
|
||||||
last := proxies[len(proxies)-1]
|
last := proxies[len(proxies)-1]
|
||||||
|
conn, err := last.DialContextWithDialer(ctx, d, metadata)
|
||||||
var c net.Conn
|
|
||||||
var currentMeta *C.Metadata
|
|
||||||
var err error
|
|
||||||
|
|
||||||
currentMeta, err = addrToMetadata(proxies[1].Addr())
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
c, err = first.DialContext(ctx, currentMeta, r.Base.DialOptions(opts...)...)
|
|
||||||
if err != nil {
|
|
||||||
return nil, fmt.Errorf("%s connect error: %w", first.Addr(), err)
|
|
||||||
}
|
|
||||||
|
|
||||||
first = proxies[1]
|
|
||||||
|
|
||||||
for _, proxy := range proxies[2:] {
|
|
||||||
currentMeta, err = addrToMetadata(proxy.Addr())
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
c, err = first.StreamConn(c, currentMeta)
|
|
||||||
if err != nil {
|
|
||||||
return nil, fmt.Errorf("%s connect error: %w", first.Addr(), err)
|
|
||||||
}
|
|
||||||
|
|
||||||
first = proxy
|
|
||||||
}
|
|
||||||
|
|
||||||
c, err = last.StreamConn(c, metadata)
|
|
||||||
if err != nil {
|
|
||||||
return nil, fmt.Errorf("%s connect error: %w", last.Addr(), err)
|
|
||||||
}
|
|
||||||
|
|
||||||
conn := outbound.NewConn(c, last)
|
|
||||||
|
|
||||||
for i := len(chainProxies) - 2; i >= 0; i-- {
|
for i := len(chainProxies) - 2; i >= 0; i-- {
|
||||||
conn.AppendToChains(chainProxies[i])
|
conn.AppendToChains(chainProxies[i])
|
||||||
}
|
}
|
||||||
|
@ -87,95 +92,18 @@ func (r *Relay) ListenPacketContext(ctx context.Context, metadata *C.Metadata, o
|
||||||
return proxies[0].ListenPacketContext(ctx, metadata, r.Base.DialOptions(opts...)...)
|
return proxies[0].ListenPacketContext(ctx, metadata, r.Base.DialOptions(opts...)...)
|
||||||
}
|
}
|
||||||
|
|
||||||
udtId := -1
|
var d C.Dialer
|
||||||
for i, proxy := range proxies {
|
d = dialer.Dialer{Options: r.Base.DialOptions(opts...)}
|
||||||
if !proxy.SupportUDP() {
|
for _, proxy := range proxies[:len(proxies)-1] {
|
||||||
return nil, fmt.Errorf("%s don't support udp", proxy.Name())
|
d = proxyDialer{
|
||||||
}
|
proxy: proxy,
|
||||||
if proxy.SupportUOT() {
|
dialer: d,
|
||||||
udtId = i // we need the latest id, so don't break
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
first := proxies[0]
|
|
||||||
last := proxies[len(proxies)-1]
|
last := proxies[len(proxies)-1]
|
||||||
|
pc, err := last.ListenPacketWithDialer(ctx, d, metadata)
|
||||||
var pc C.PacketConn
|
|
||||||
var currentMeta *C.Metadata
|
|
||||||
if udtId != -1 {
|
|
||||||
c, err := dialer.DialContext(ctx, "tcp", first.Addr(), r.Base.DialOptions(opts...)...)
|
|
||||||
if err != nil {
|
|
||||||
return nil, fmt.Errorf("%s connect error: %w", first.Addr(), err)
|
|
||||||
}
|
|
||||||
tcpKeepAlive(c)
|
|
||||||
|
|
||||||
for _, proxy := range proxies[1 : udtId+1] {
|
|
||||||
currentMeta, err = addrToMetadata(proxy.Addr())
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
c, err = first.StreamConn(c, currentMeta)
|
|
||||||
if err != nil {
|
|
||||||
return nil, fmt.Errorf("%s connect error: %w", first.Addr(), err)
|
|
||||||
}
|
|
||||||
|
|
||||||
first = proxy
|
|
||||||
}
|
|
||||||
|
|
||||||
if first == last {
|
|
||||||
currentMeta = metadata
|
|
||||||
} else {
|
|
||||||
currentMeta, err = addrToMetadata(proxies[udtId+1].Addr())
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
currentMeta.NetWork = C.UDP
|
|
||||||
}
|
|
||||||
c, err = first.StreamConn(c, currentMeta)
|
|
||||||
if err != nil {
|
|
||||||
return nil, fmt.Errorf("%s connect error: %w", first.Addr(), err)
|
|
||||||
}
|
|
||||||
|
|
||||||
pc, err = first.ListenPacketOnStreamConn(c, currentMeta)
|
|
||||||
if err != nil {
|
|
||||||
return nil, fmt.Errorf("%s connect error: %w", first.Addr(), err)
|
|
||||||
}
|
|
||||||
if first == last {
|
|
||||||
return pc, nil
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
currentMeta, err = addrToMetadata(proxies[1].Addr())
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
currentMeta.NetWork = C.UDP
|
|
||||||
pc, err = first.ListenPacketContext(ctx, currentMeta, r.Base.DialOptions(opts...)...)
|
|
||||||
if err != nil {
|
|
||||||
return nil, fmt.Errorf("%s connect error: %w", first.Addr(), err)
|
|
||||||
}
|
|
||||||
udtId = 0
|
|
||||||
}
|
|
||||||
|
|
||||||
first = proxies[udtId+1]
|
|
||||||
for _, proxy := range proxies[udtId+2:] {
|
|
||||||
currentMeta, err = addrToMetadata(proxy.Addr())
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
currentMeta.NetWork = C.UDP
|
|
||||||
|
|
||||||
pc, err = first.ListenPacketOnPacketConn(ctx, pc, currentMeta)
|
|
||||||
if err != nil {
|
|
||||||
return nil, fmt.Errorf("%s connect error: %w", first.Addr(), err)
|
|
||||||
}
|
|
||||||
|
|
||||||
first = proxy
|
|
||||||
}
|
|
||||||
|
|
||||||
pc, err = last.ListenPacketOnPacketConn(ctx, pc, metadata)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("%s connect error: %w", last.Addr(), err)
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
for i := len(chainProxies) - 2; i >= 0; i-- {
|
for i := len(chainProxies) - 2; i >= 0; i-- {
|
||||||
|
@ -201,7 +129,7 @@ func (r *Relay) SupportUDP() bool {
|
||||||
if proxy.SupportUOT() {
|
if proxy.SupportUOT() {
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
if !proxy.SupportLPPC() {
|
if !proxy.SupportWithDialer() {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -24,7 +24,7 @@ func addrToMetadata(rawAddress string) (addr *C.Metadata, err error) {
|
||||||
} else {
|
} else {
|
||||||
addr = &C.Metadata{
|
addr = &C.Metadata{
|
||||||
Host: "",
|
Host: "",
|
||||||
DstIP: ip,
|
DstIP: ip.Unmap(),
|
||||||
DstPort: port,
|
DstPort: port,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
36
common/net/bind.go
Normal file
36
common/net/bind.go
Normal file
|
@ -0,0 +1,36 @@
|
||||||
|
package net
|
||||||
|
|
||||||
|
import "net"
|
||||||
|
|
||||||
|
type bindPacketConn struct {
|
||||||
|
net.PacketConn
|
||||||
|
rAddr net.Addr
|
||||||
|
}
|
||||||
|
|
||||||
|
func (wpc *bindPacketConn) Read(b []byte) (n int, err error) {
|
||||||
|
n, _, err = wpc.PacketConn.ReadFrom(b)
|
||||||
|
return n, err
|
||||||
|
}
|
||||||
|
|
||||||
|
func (wpc *bindPacketConn) Write(b []byte) (n int, err error) {
|
||||||
|
return wpc.PacketConn.WriteTo(b, wpc.rAddr)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (wpc *bindPacketConn) RemoteAddr() net.Addr {
|
||||||
|
return wpc.rAddr
|
||||||
|
}
|
||||||
|
|
||||||
|
func (wpc *bindPacketConn) LocalAddr() net.Addr {
|
||||||
|
if wpc.PacketConn.LocalAddr() == nil {
|
||||||
|
return &net.UDPAddr{IP: net.IPv4zero, Port: 0}
|
||||||
|
} else {
|
||||||
|
return wpc.PacketConn.LocalAddr()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewBindPacketConn(pc net.PacketConn, rAddr net.Addr) net.Conn {
|
||||||
|
return &bindPacketConn{
|
||||||
|
PacketConn: pc,
|
||||||
|
rAddr: rAddr,
|
||||||
|
}
|
||||||
|
}
|
|
@ -444,3 +444,15 @@ func concurrentIPv6DialContext(ctx context.Context, network, address string, opt
|
||||||
|
|
||||||
return concurrentDialContext(ctx, network, ips, port, opt)
|
return concurrentDialContext(ctx, network, ips, port, opt)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type Dialer struct {
|
||||||
|
Options []Option
|
||||||
|
}
|
||||||
|
|
||||||
|
func (d Dialer) DialContext(ctx context.Context, network, address string) (net.Conn, error) {
|
||||||
|
return DialContext(ctx, network, address, d.Options...)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (d Dialer) ListenPacket(ctx context.Context, network, address string, rAddrPort netip.AddrPort) (net.PacketConn, error) {
|
||||||
|
return ListenPacket(ctx, ParseNetwork(network, rAddrPort.Addr()), address, d.Options...)
|
||||||
|
}
|
||||||
|
|
|
@ -4,6 +4,7 @@ import (
|
||||||
"context"
|
"context"
|
||||||
"fmt"
|
"fmt"
|
||||||
"net"
|
"net"
|
||||||
|
"net/netip"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/Dreamacro/clash/component/dialer"
|
"github.com/Dreamacro/clash/component/dialer"
|
||||||
|
@ -81,6 +82,11 @@ type PacketConn interface {
|
||||||
// WriteWithMetadata(p []byte, metadata *Metadata) (n int, err error)
|
// WriteWithMetadata(p []byte, metadata *Metadata) (n int, err error)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type Dialer interface {
|
||||||
|
DialContext(ctx context.Context, network, address string) (net.Conn, error)
|
||||||
|
ListenPacket(ctx context.Context, network, address string, rAddrPort netip.AddrPort) (net.PacketConn, error)
|
||||||
|
}
|
||||||
|
|
||||||
type ProxyAdapter interface {
|
type ProxyAdapter interface {
|
||||||
Name() string
|
Name() string
|
||||||
Type() AdapterType
|
Type() AdapterType
|
||||||
|
@ -89,6 +95,7 @@ type ProxyAdapter interface {
|
||||||
SupportTFO() bool
|
SupportTFO() bool
|
||||||
MarshalJSON() ([]byte, error)
|
MarshalJSON() ([]byte, error)
|
||||||
|
|
||||||
|
// Deprecated: use DialContextWithDialer and ListenPacketWithDialer instead.
|
||||||
// StreamConn wraps a protocol around net.Conn with Metadata.
|
// StreamConn wraps a protocol around net.Conn with Metadata.
|
||||||
//
|
//
|
||||||
// Examples:
|
// Examples:
|
||||||
|
@ -106,10 +113,10 @@ type ProxyAdapter interface {
|
||||||
|
|
||||||
// SupportUOT return UDP over TCP support
|
// SupportUOT return UDP over TCP support
|
||||||
SupportUOT() bool
|
SupportUOT() bool
|
||||||
ListenPacketOnStreamConn(c net.Conn, metadata *Metadata) (PacketConn, error)
|
|
||||||
|
|
||||||
SupportLPPC() bool
|
SupportWithDialer() bool
|
||||||
ListenPacketOnPacketConn(ctx context.Context, c PacketConn, metadata *Metadata) (PacketConn, error)
|
DialContextWithDialer(ctx context.Context, dialer Dialer, metadata *Metadata) (Conn, error)
|
||||||
|
ListenPacketWithDialer(ctx context.Context, dialer Dialer, metadata *Metadata) (PacketConn, error)
|
||||||
|
|
||||||
// Unwrap extracts the proxy from a proxy-group. It returns nil when nothing to extract.
|
// Unwrap extracts the proxy from a proxy-group. It returns nil when nothing to extract.
|
||||||
Unwrap(metadata *Metadata, touch bool) Proxy
|
Unwrap(metadata *Metadata, touch bool) Proxy
|
||||||
|
|
32
dns/util.go
32
dns/util.go
|
@ -11,6 +11,7 @@ import (
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/Dreamacro/clash/common/cache"
|
"github.com/Dreamacro/clash/common/cache"
|
||||||
|
N "github.com/Dreamacro/clash/common/net"
|
||||||
"github.com/Dreamacro/clash/common/nnip"
|
"github.com/Dreamacro/clash/common/nnip"
|
||||||
"github.com/Dreamacro/clash/common/picker"
|
"github.com/Dreamacro/clash/common/picker"
|
||||||
"github.com/Dreamacro/clash/component/dialer"
|
"github.com/Dreamacro/clash/component/dialer"
|
||||||
|
@ -134,32 +135,6 @@ func msgToDomain(msg *D.Msg) string {
|
||||||
return ""
|
return ""
|
||||||
}
|
}
|
||||||
|
|
||||||
type wrapPacketConn struct {
|
|
||||||
net.PacketConn
|
|
||||||
rAddr net.Addr
|
|
||||||
}
|
|
||||||
|
|
||||||
func (wpc *wrapPacketConn) Read(b []byte) (n int, err error) {
|
|
||||||
n, _, err = wpc.PacketConn.ReadFrom(b)
|
|
||||||
return n, err
|
|
||||||
}
|
|
||||||
|
|
||||||
func (wpc *wrapPacketConn) Write(b []byte) (n int, err error) {
|
|
||||||
return wpc.PacketConn.WriteTo(b, wpc.rAddr)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (wpc *wrapPacketConn) RemoteAddr() net.Addr {
|
|
||||||
return wpc.rAddr
|
|
||||||
}
|
|
||||||
|
|
||||||
func (wpc *wrapPacketConn) LocalAddr() net.Addr {
|
|
||||||
if wpc.PacketConn.LocalAddr() == nil {
|
|
||||||
return &net.UDPAddr{IP: net.IPv4zero, Port: 0}
|
|
||||||
} else {
|
|
||||||
return wpc.PacketConn.LocalAddr()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
type dialHandler func(ctx context.Context, network, addr string) (net.Conn, error)
|
type dialHandler func(ctx context.Context, network, addr string) (net.Conn, error)
|
||||||
|
|
||||||
func getDialHandler(r *Resolver, proxyAdapter string, opts ...dialer.Option) dialHandler {
|
func getDialHandler(r *Resolver, proxyAdapter string, opts ...dialer.Option) dialHandler {
|
||||||
|
@ -213,10 +188,7 @@ func getDialHandler(r *Resolver, proxyAdapter string, opts ...dialer.Option) dia
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
return &wrapPacketConn{
|
return N.NewBindPacketConn(packetConn, metadata.UDPAddr()), nil
|
||||||
PacketConn: packetConn,
|
|
||||||
rAddr: metadata.UDPAddr(),
|
|
||||||
}, nil
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue