package outbound import ( "context" "crypto/sha1" "encoding/hex" "encoding/json" "errors" "net" "regexp" "github.com/Dreamacro/clash/component/dialer" C "github.com/Dreamacro/clash/constant" ) type Base struct { name string addr string iface string tp C.AdapterType udp bool rmark int } // Name implements C.ProxyAdapter func (b *Base) Name() string { return b.name } // Type implements C.ProxyAdapter func (b *Base) Type() C.AdapterType { return b.tp } // StreamConn implements C.ProxyAdapter func (b *Base) StreamConn(c net.Conn, metadata *C.Metadata) (net.Conn, error) { return c, errors.New("no support") } // ListenPacketContext implements C.ProxyAdapter func (b *Base) ListenPacketContext(ctx context.Context, metadata *C.Metadata, opts ...dialer.Option) (C.PacketConn, error) { return nil, errors.New("no support") } // SupportUDP implements C.ProxyAdapter func (b *Base) SupportUDP() bool { return b.udp } // MarshalJSON implements C.ProxyAdapter func (b *Base) MarshalJSON() ([]byte, error) { return json.Marshal(map[string]string{ "type": b.Type().String(), }) } // Addr implements C.ProxyAdapter func (b *Base) Addr() string { return b.addr } // Unwrap implements C.ProxyAdapter func (b *Base) Unwrap(metadata *C.Metadata) C.Proxy { return nil } // DialOptions return []dialer.Option from struct func (b *Base) DialOptions(opts ...dialer.Option) []dialer.Option { if b.iface != "" { opts = append(opts, dialer.WithInterface(b.iface)) } if b.rmark != 0 { opts = append(opts, dialer.WithRoutingMark(b.rmark)) } return opts } type BasicOption struct { Interface string `proxy:"interface-name,omitempty" group:"interface-name,omitempty"` RoutingMark int `proxy:"routing-mark,omitempty" group:"routing-mark,omitempty"` } type BaseOption struct { Name string Addr string Type C.AdapterType UDP bool Interface string RoutingMark int } func NewBase(opt BaseOption) *Base { return &Base{ name: opt.Name, addr: opt.Addr, tp: opt.Type, udp: opt.UDP, iface: opt.Interface, rmark: opt.RoutingMark, } } type conn struct { net.Conn chain C.Chain } // Chains implements C.Connection func (c *conn) Chains() C.Chain { return c.chain } // AppendToChains implements C.Connection func (c *conn) AppendToChains(a C.ProxyAdapter) { c.chain = append(c.chain, a.Name()) } func NewConn(c net.Conn, a C.ProxyAdapter) C.Conn { return &conn{c, []string{a.Name()}} } type packetConn struct { net.PacketConn chain C.Chain } // Chains implements C.Connection func (c *packetConn) Chains() C.Chain { return c.chain } // AppendToChains implements C.Connection func (c *packetConn) AppendToChains(a C.ProxyAdapter) { c.chain = append(c.chain, a.Name()) } func newPacketConn(pc net.PacketConn, a C.ProxyAdapter) C.PacketConn { return &packetConn{pc, []string{a.Name()}} } func uuidMap(str string) string { match, _ := regexp.MatchString(`[\da-f]{8}(-[\da-f]{4}){3}-[\da-f]{12}$`, str) if !match { var Nil [16]byte h := sha1.New() h.Write(Nil[:]) h.Write([]byte(str)) u := h.Sum(nil)[:16] u[6] = (u[6] & 0x0f) | (5 << 4) u[8] = u[8]&(0xff>>2) | (0x02 << 6) buf := make([]byte, 36) hex.Encode(buf[0:8], u[0:4]) buf[8] = '-' hex.Encode(buf[9:13], u[4:6]) buf[13] = '-' hex.Encode(buf[14:18], u[6:8]) buf[18] = '-' hex.Encode(buf[19:23], u[8:10]) buf[23] = '-' hex.Encode(buf[24:], u[10:]) return string(buf) } return str }