diff --git a/adapter/inbound/addition.go b/adapter/inbound/addition.go new file mode 100644 index 00000000..4d57fcee --- /dev/null +++ b/adapter/inbound/addition.go @@ -0,0 +1,15 @@ +package inbound + +import ( + C "github.com/Dreamacro/clash/constant" +) + +type Addition struct { + InName string + SpecialRules string +} + +func (a Addition) Apply(metadata *C.Metadata) { + metadata.InName = a.InName + metadata.SpecialRules = a.SpecialRules +} diff --git a/adapter/inbound/http.go b/adapter/inbound/http.go index 0637b39a..94040078 100644 --- a/adapter/inbound/http.go +++ b/adapter/inbound/http.go @@ -9,16 +9,13 @@ import ( ) // NewHTTP receive normal http request and return HTTPContext -func NewHTTP(target socks5.Addr, source net.Addr, conn net.Conn) *context.ConnContext { - return NewHTTPWithInfos(target, source, conn, "", "") -} - -func NewHTTPWithInfos(target socks5.Addr, source net.Addr, conn net.Conn, inName, specialRules string) *context.ConnContext { +func NewHTTP(target socks5.Addr, source net.Addr, conn net.Conn, additions ...Addition) *context.ConnContext { metadata := parseSocksAddr(target) metadata.NetWork = C.TCP metadata.Type = C.HTTP - metadata.InName = inName - metadata.SpecialRules = specialRules + for _, addition := range additions { + addition.Apply(metadata) + } if ip, port, err := parseAddr(source.String()); err == nil { metadata.SrcIP = ip metadata.SrcPort = port diff --git a/adapter/inbound/https.go b/adapter/inbound/https.go index dbc17835..3fff2371 100644 --- a/adapter/inbound/https.go +++ b/adapter/inbound/https.go @@ -9,15 +9,12 @@ import ( ) // NewHTTPS receive CONNECT request and return ConnContext -func NewHTTPS(request *http.Request, conn net.Conn) *context.ConnContext { - return NewHTTPSWithInfos(request, conn, "", "") -} - -func NewHTTPSWithInfos(request *http.Request, conn net.Conn, inName, specialRules string) *context.ConnContext { +func NewHTTPS(request *http.Request, conn net.Conn, additions ...Addition) *context.ConnContext { metadata := parseHTTPAddr(request) metadata.Type = C.HTTPS - metadata.SpecialRules = specialRules - metadata.InName = inName + for _, addition := range additions { + addition.Apply(metadata) + } if ip, port, err := parseAddr(conn.RemoteAddr().String()); err == nil { metadata.SrcIP = ip metadata.SrcPort = port diff --git a/adapter/inbound/packet.go b/adapter/inbound/packet.go index a84a3008..d1fcb05d 100644 --- a/adapter/inbound/packet.go +++ b/adapter/inbound/packet.go @@ -16,12 +16,14 @@ func (s *PacketAdapter) Metadata() *C.Metadata { return s.metadata } -func NewPacketWithInfos(target socks5.Addr, packet C.UDPPacket, source C.Type, inName, specialRules string) C.PacketAdapter { +// NewPacket is PacketAdapter generator +func NewPacket(target socks5.Addr, packet C.UDPPacket, source C.Type, additions ...Addition) C.PacketAdapter { metadata := parseSocksAddr(target) metadata.NetWork = C.UDP metadata.Type = source - metadata.InName = inName - metadata.SpecialRules = specialRules + for _, addition := range additions { + addition.Apply(metadata) + } if ip, port, err := parseAddr(packet.LocalAddr().String()); err == nil { metadata.SrcIP = ip metadata.SrcPort = port @@ -38,8 +40,3 @@ func NewPacketWithInfos(target socks5.Addr, packet C.UDPPacket, source C.Type, i metadata, } } - -// NewPacket is PacketAdapter generator -func NewPacket(target socks5.Addr, packet C.UDPPacket, source C.Type) C.PacketAdapter { - return NewPacketWithInfos(target, packet, source, "", "") -} diff --git a/adapter/inbound/socket.go b/adapter/inbound/socket.go index 34f31cf3..557b22ab 100644 --- a/adapter/inbound/socket.go +++ b/adapter/inbound/socket.go @@ -9,12 +9,15 @@ import ( "github.com/Dreamacro/clash/transport/socks5" ) -func NewSocketWithInfos(target socks5.Addr, conn net.Conn, source C.Type, inName, specialRules string) *context.ConnContext { +// NewSocket receive TCP inbound and return ConnContext +func NewSocket(target socks5.Addr, conn net.Conn, source C.Type, additions ...Addition) *context.ConnContext { metadata := parseSocksAddr(target) metadata.NetWork = C.TCP metadata.Type = source - metadata.SpecialRules = specialRules - metadata.InName = inName + for _, addition := range additions { + addition.Apply(metadata) + } + remoteAddr := conn.RemoteAddr() // Filter when net.Addr interface is nil @@ -36,11 +39,6 @@ func NewSocketWithInfos(target socks5.Addr, conn net.Conn, source C.Type, inName return context.NewConnContext(conn, metadata) } -// NewSocket receive TCP inbound and return ConnContext -func NewSocket(target socks5.Addr, conn net.Conn, source C.Type) *context.ConnContext { - return NewSocketWithInfos(target, conn, source, "", "") -} - func NewInner(conn net.Conn, dst string, host string) *context.ConnContext { metadata := &C.Metadata{} metadata.NetWork = C.TCP diff --git a/constant/listener.go b/constant/listener.go index 09ecdb76..cb7ab456 100644 --- a/constant/listener.go +++ b/constant/listener.go @@ -9,8 +9,9 @@ type Listener interface { } type AdvanceListener interface { - Close() + Close() error Config() string + AddrList() (addrList []net.Addr) HandleConn(conn net.Conn, in chan<- ConnContext) } diff --git a/listener/autoredir/tcp.go b/listener/autoredir/tcp.go index 5e675540..67b57022 100644 --- a/listener/autoredir/tcp.go +++ b/listener/autoredir/tcp.go @@ -11,12 +11,11 @@ import ( ) type Listener struct { - listener net.Listener - addr string - closed bool - name string - specialRules string - lookupFunc func(netip.AddrPort) (socks5.Addr, error) + listener net.Listener + addr string + closed bool + additions []inbound.Addition + lookupFunc func(netip.AddrPort) (socks5.Addr, error) } // RawAddress implements C.Listener @@ -58,23 +57,24 @@ func (l *Listener) handleRedir(conn net.Conn, in chan<- C.ConnContext) { _ = conn.(*net.TCPConn).SetKeepAlive(true) - in <- inbound.NewSocketWithInfos(target, conn, C.REDIR, l.name, l.specialRules) + in <- inbound.NewSocket(target, conn, C.REDIR, l.additions...) } -func New(addr string, in chan<- C.ConnContext) (*Listener, error) { - return NewWithInfos(addr, "DEFAULT-REDIR", "", in) -} - -func NewWithInfos(addr, name, specialRules string, in chan<- C.ConnContext) (*Listener, error) { +func New(addr string, in chan<- C.ConnContext, additions ...inbound.Addition) (*Listener, error) { + if len(additions) == 0 { + additions = []inbound.Addition{{ + InName: "DEFAULT-REDIR", + SpecialRules: "", + }} + } l, err := net.Listen("tcp", addr) if err != nil { return nil, err } rl := &Listener{ - listener: l, - addr: addr, - name: name, - specialRules: specialRules, + listener: l, + addr: addr, + additions: additions, } go func() { diff --git a/listener/http/client.go b/listener/http/client.go index 64208e17..15c21f91 100644 --- a/listener/http/client.go +++ b/listener/http/client.go @@ -12,7 +12,7 @@ import ( "github.com/Dreamacro/clash/transport/socks5" ) -func newClient(source net.Addr, name, specialRules string, in chan<- C.ConnContext) *http.Client { +func newClient(source net.Addr, in chan<- C.ConnContext, additions ...inbound.Addition) *http.Client { return &http.Client{ Transport: &http.Transport{ // from http.DefaultTransport @@ -32,7 +32,7 @@ func newClient(source net.Addr, name, specialRules string, in chan<- C.ConnConte left, right := net.Pipe() - in <- inbound.NewHTTPWithInfos(dstAddr, source, right, name, specialRules) + in <- inbound.NewHTTP(dstAddr, source, right, additions...) return left, nil }, diff --git a/listener/http/proxy.go b/listener/http/proxy.go index afded98e..a95f7195 100644 --- a/listener/http/proxy.go +++ b/listener/http/proxy.go @@ -14,8 +14,8 @@ import ( "github.com/Dreamacro/clash/log" ) -func HandleConn(name, specialRules string, c net.Conn, in chan<- C.ConnContext, cache *cache.LruCache[string, bool]) { - client := newClient(c.RemoteAddr(), name, specialRules, in) +func HandleConn(c net.Conn, in chan<- C.ConnContext, cache *cache.LruCache[string, bool], additions ...inbound.Addition) { + client := newClient(c.RemoteAddr(), in, additions...) defer client.CloseIdleConnections() conn := N.NewBufferedConn(c) @@ -48,7 +48,7 @@ func HandleConn(name, specialRules string, c net.Conn, in chan<- C.ConnContext, break // close connection } - in <- inbound.NewHTTPSWithInfos(request, conn, name, specialRules) + in <- inbound.NewHTTPS(request, conn, additions...) return // hijack connection } @@ -61,7 +61,7 @@ func HandleConn(name, specialRules string, c net.Conn, in chan<- C.ConnContext, request.RequestURI = "" if isUpgradeRequest(request) { - handleUpgrade(name, specialRules, conn, request, in) + handleUpgrade(conn, request, in, additions...) return // hijack connection } diff --git a/listener/http/server.go b/listener/http/server.go index fa51ba28..c8379955 100644 --- a/listener/http/server.go +++ b/listener/http/server.go @@ -9,11 +9,9 @@ import ( ) type Listener struct { - listener net.Listener - addr string - closed bool - name string - specialRules string + listener net.Listener + addr string + closed bool } // RawAddress implements C.Listener @@ -32,15 +30,17 @@ func (l *Listener) Close() error { return l.listener.Close() } -func New(addr string, in chan<- C.ConnContext) (*Listener, error) { - return NewWithAuthenticate(addr, "DEFAULT-HTTP", "", in, true) +func New(addr string, in chan<- C.ConnContext, additions ...inbound.Addition) (*Listener, error) { + return NewWithAuthenticate(addr, in, true, additions...) } -func NewWithInfos(addr, name, specialRules string, in chan<- C.ConnContext) (*Listener, error) { - return NewWithAuthenticate(addr, name, specialRules, in, true) -} - -func NewWithAuthenticate(addr, name, specialRules string, in chan<- C.ConnContext, authenticate bool) (*Listener, error) { +func NewWithAuthenticate(addr string, in chan<- C.ConnContext, authenticate bool, additions ...inbound.Addition) (*Listener, error) { + if len(additions) == 0 { + additions = []inbound.Addition{{ + InName: "DEFAULT-HTTP", + SpecialRules: "", + }} + } l, err := inbound.Listen("tcp", addr) if err != nil { @@ -53,10 +53,8 @@ func NewWithAuthenticate(addr, name, specialRules string, in chan<- C.ConnContex } hl := &Listener{ - listener: l, - name: name, - specialRules: specialRules, - addr: addr, + listener: l, + addr: addr, } go func() { for { @@ -67,7 +65,7 @@ func NewWithAuthenticate(addr, name, specialRules string, in chan<- C.ConnContex } continue } - go HandleConn(hl.name, hl.specialRules, conn, in, c) + go HandleConn(conn, in, c, additions...) } }() diff --git a/listener/http/upgrade.go b/listener/http/upgrade.go index a4601995..90e28f0a 100644 --- a/listener/http/upgrade.go +++ b/listener/http/upgrade.go @@ -25,7 +25,7 @@ func isUpgradeRequest(req *http.Request) bool { return false } -func handleUpgrade(name, specialRules string, conn net.Conn, request *http.Request, in chan<- C.ConnContext) { +func handleUpgrade(conn net.Conn, request *http.Request, in chan<- C.ConnContext, additions ...inbound.Addition) { defer conn.Close() removeProxyHeaders(request.Header) @@ -43,7 +43,7 @@ func handleUpgrade(name, specialRules string, conn net.Conn, request *http.Reque left, right := net.Pipe() - in <- inbound.NewHTTPWithInfos(dstAddr, conn.RemoteAddr(), right, name, specialRules) + in <- inbound.NewHTTP(dstAddr, conn.RemoteAddr(), right, additions...) var bufferedLeft *N.BufferedConn if request.TLS != nil { diff --git a/listener/inbound/base.go b/listener/inbound/base.go index 7428e716..df61b0ea 100644 --- a/listener/inbound/base.go +++ b/listener/inbound/base.go @@ -6,6 +6,7 @@ import ( "net/netip" "strconv" + "github.com/Dreamacro/clash/adapter/inbound" C "github.com/Dreamacro/clash/constant" ) @@ -28,7 +29,7 @@ func NewBase(options *BaseOption) (*Base, error) { return &Base{ name: options.Name(), listenAddr: addr, - specialRules: options.PreferRulesName, + specialRules: options.SpecialRules, port: options.Port, config: options, }, nil @@ -64,13 +65,17 @@ func (*Base) Listen(tcpIn chan<- C.ConnContext, udpIn chan<- C.PacketAdapter) er return nil } +func (b *Base) Additions() []inbound.Addition { + return b.config.Additions() +} + var _ C.InboundListener = (*Base)(nil) type BaseOption struct { - NameStr string `inbound:"name"` - Listen string `inbound:"listen,omitempty"` - Port int `inbound:"port"` - PreferRulesName string `inbound:"rule,omitempty"` + NameStr string `inbound:"name"` + Listen string `inbound:"listen,omitempty"` + Port int `inbound:"port"` + SpecialRules string `inbound:"rule,omitempty"` } func (o BaseOption) Name() string { @@ -81,6 +86,13 @@ func (o BaseOption) Equal(config C.InboundConfig) bool { return optionToString(o) == optionToString(config) } +func (o BaseOption) Additions() []inbound.Addition { + return []inbound.Addition{{ + InName: o.NameStr, + SpecialRules: o.SpecialRules, + }} +} + var _ C.InboundConfig = (*BaseOption)(nil) func optionToString(option any) string { diff --git a/listener/inbound/http.go b/listener/inbound/http.go index b6edb479..b19f0154 100644 --- a/listener/inbound/http.go +++ b/listener/inbound/http.go @@ -44,7 +44,7 @@ func (h *HTTP) Address() string { // Listen implements constant.InboundListener func (h *HTTP) Listen(tcpIn chan<- C.ConnContext, udpIn chan<- C.PacketAdapter) error { var err error - h.l, err = http.NewWithInfos(h.RawAddress(), h.name, h.specialRules, tcpIn) + h.l, err = http.New(h.RawAddress(), tcpIn, h.Additions()...) if err != nil { return err } diff --git a/listener/inbound/mixed.go b/listener/inbound/mixed.go index f29caebb..651ab486 100644 --- a/listener/inbound/mixed.go +++ b/listener/inbound/mixed.go @@ -52,12 +52,12 @@ func (m *Mixed) Address() string { // Listen implements constant.InboundListener func (m *Mixed) Listen(tcpIn chan<- C.ConnContext, udpIn chan<- C.PacketAdapter) error { var err error - m.l, err = mixed.NewWithInfos(m.RawAddress(), m.name, m.specialRules, tcpIn) + m.l, err = mixed.New(m.RawAddress(), tcpIn, m.Additions()...) if err != nil { return err } if m.udp { - m.lUDP, err = socks.NewUDPWithInfos(m.Address(), m.name, m.specialRules, udpIn) + m.lUDP, err = socks.NewUDP(m.Address(), udpIn, m.Additions()...) if err != nil { return err } diff --git a/listener/inbound/redir.go b/listener/inbound/redir.go index 9f0f35b4..37b5aab9 100644 --- a/listener/inbound/redir.go +++ b/listener/inbound/redir.go @@ -44,7 +44,7 @@ func (r *Redir) Address() string { // Listen implements constant.InboundListener func (r *Redir) Listen(tcpIn chan<- C.ConnContext, udpIn chan<- C.PacketAdapter) error { var err error - r.l, err = redir.NewWithInfos(r.Address(), r.name, r.specialRules, tcpIn) + r.l, err = redir.New(r.Address(), tcpIn, r.Additions()...) if err != nil { return err } diff --git a/listener/inbound/socks.go b/listener/inbound/socks.go index 9727350b..010d08f9 100644 --- a/listener/inbound/socks.go +++ b/listener/inbound/socks.go @@ -70,11 +70,11 @@ func (s *Socks) Address() string { // Listen implements constant.InboundListener func (s *Socks) Listen(tcpIn chan<- C.ConnContext, udpIn chan<- C.PacketAdapter) error { var err error - if s.stl, err = socks.NewWithInfos(s.RawAddress(), s.name, s.specialRules, tcpIn); err != nil { + if s.stl, err = socks.New(s.RawAddress(), tcpIn, s.Additions()...); err != nil { return err } if s.udp { - if s.sul, err = socks.NewUDPWithInfos(s.RawAddress(), s.name, s.specialRules, udpIn); err != nil { + if s.sul, err = socks.NewUDP(s.RawAddress(), udpIn, s.Additions()...); err != nil { return err } } diff --git a/listener/inbound/tproxy.go b/listener/inbound/tproxy.go index c3e34033..223ebd93 100644 --- a/listener/inbound/tproxy.go +++ b/listener/inbound/tproxy.go @@ -51,13 +51,13 @@ func (t *TProxy) Address() string { // Listen implements constant.InboundListener func (t *TProxy) Listen(tcpIn chan<- C.ConnContext, udpIn chan<- C.PacketAdapter) error { var err error - t.lTCP, err = tproxy.NewWithInfos(t.RawAddress(), t.name, t.specialRules, tcpIn) + t.lTCP, err = tproxy.New(t.RawAddress(), tcpIn, t.Additions()...) if err != nil { return err } if t.udp { if t.lUDP != nil { - t.lUDP, err = tproxy.NewUDPWithInfos(t.Address(), t.name, t.specialRules, udpIn) + t.lUDP, err = tproxy.NewUDP(t.Address(), udpIn, t.Additions()...) if err != nil { return err } diff --git a/listener/inbound/tuic.go b/listener/inbound/tuic.go index e64d53bf..efe5d8b2 100644 --- a/listener/inbound/tuic.go +++ b/listener/inbound/tuic.go @@ -59,18 +59,23 @@ func (t *Tuic) Address() string { // Listen implements constant.InboundListener func (t *Tuic) Listen(tcpIn chan<- C.ConnContext, udpIn chan<- C.PacketAdapter) error { var err error - t.l, err = tuic.New(LC.TuicServer{ - Enable: true, - Listen: t.RawAddress(), - Token: t.config.Token, - Certificate: t.config.Certificate, - PrivateKey: t.config.PrivateKey, - CongestionController: t.config.CongestionController, - MaxIdleTime: t.config.MaxIdleTime, - AuthenticationTimeout: t.config.AuthenticationTimeout, - ALPN: t.config.ALPN, - MaxUdpRelayPacketSize: t.config.MaxUdpRelayPacketSize, - }, tcpIn, udpIn) + t.l, err = tuic.New( + LC.TuicServer{ + Enable: true, + Listen: t.RawAddress(), + Token: t.config.Token, + Certificate: t.config.Certificate, + PrivateKey: t.config.PrivateKey, + CongestionController: t.config.CongestionController, + MaxIdleTime: t.config.MaxIdleTime, + AuthenticationTimeout: t.config.AuthenticationTimeout, + ALPN: t.config.ALPN, + MaxUdpRelayPacketSize: t.config.MaxUdpRelayPacketSize, + }, + tcpIn, + udpIn, + t.Additions()..., + ) if err != nil { return err } diff --git a/listener/mixed/mixed.go b/listener/mixed/mixed.go index 34b4b1af..47beaf65 100644 --- a/listener/mixed/mixed.go +++ b/listener/mixed/mixed.go @@ -14,12 +14,10 @@ import ( ) type Listener struct { - listener net.Listener - addr string - name string - specialRules string - cache *cache.LruCache[string, bool] - closed bool + listener net.Listener + addr string + cache *cache.LruCache[string, bool] + closed bool } // RawAddress implements C.Listener @@ -38,22 +36,22 @@ func (l *Listener) Close() error { return l.listener.Close() } -func New(addr string, in chan<- C.ConnContext) (*Listener, error) { - return NewWithInfos(addr, "DEFAULT-MIXED", "", in) -} - -func NewWithInfos(addr, name, specialRules string, in chan<- C.ConnContext) (*Listener, error) { +func New(addr string, in chan<- C.ConnContext, additions ...inbound.Addition) (*Listener, error) { + if len(additions) == 0 { + additions = []inbound.Addition{{ + InName: "DEFAULT-MIXED", + SpecialRules: "", + }} + } l, err := inbound.Listen("tcp", addr) if err != nil { return nil, err } ml := &Listener{ - listener: l, - addr: addr, - name: name, - specialRules: specialRules, - cache: cache.New[string, bool](cache.WithAge[string, bool](30)), + listener: l, + addr: addr, + cache: cache.New[string, bool](cache.WithAge[string, bool](30)), } go func() { for { @@ -64,14 +62,14 @@ func NewWithInfos(addr, name, specialRules string, in chan<- C.ConnContext) (*Li } continue } - go handleConn(ml.name, ml.specialRules, c, in, ml.cache) + go handleConn(c, in, ml.cache, additions...) } }() return ml, nil } -func handleConn(name, specialRules string, conn net.Conn, in chan<- C.ConnContext, cache *cache.LruCache[string, bool]) { +func handleConn(conn net.Conn, in chan<- C.ConnContext, cache *cache.LruCache[string, bool], additions ...inbound.Addition) { conn.(*net.TCPConn).SetKeepAlive(true) bufConn := N.NewBufferedConn(conn) @@ -82,10 +80,10 @@ func handleConn(name, specialRules string, conn net.Conn, in chan<- C.ConnContex switch head[0] { case socks4.Version: - socks.HandleSocks4(name, specialRules, bufConn, in) + socks.HandleSocks4(bufConn, in, additions...) case socks5.Version: - socks.HandleSocks5(name, specialRules, bufConn, in) + socks.HandleSocks5(bufConn, in, additions...) default: - http.HandleConn(name, specialRules, bufConn, in, cache) + http.HandleConn(bufConn, in, cache, additions...) } } diff --git a/listener/redir/tcp.go b/listener/redir/tcp.go index 150f1da5..6849605a 100644 --- a/listener/redir/tcp.go +++ b/listener/redir/tcp.go @@ -8,11 +8,9 @@ import ( ) type Listener struct { - listener net.Listener - addr string - closed bool - name string - specialRules string + listener net.Listener + addr string + closed bool } // RawAddress implements C.Listener @@ -31,20 +29,20 @@ func (l *Listener) Close() error { return l.listener.Close() } -func New(addr string, in chan<- C.ConnContext) (*Listener, error) { - return NewWithInfos(addr, "DEFAULT-REDIR", "", in) -} - -func NewWithInfos(addr, name, specialRules string, in chan<- C.ConnContext) (*Listener, error) { +func New(addr string, in chan<- C.ConnContext, additions ...inbound.Addition) (*Listener, error) { + if len(additions) == 0 { + additions = []inbound.Addition{{ + InName: "DEFAULT-REDIR", + SpecialRules: "", + }} + } l, err := net.Listen("tcp", addr) if err != nil { return nil, err } rl := &Listener{ - listener: l, - addr: addr, - name: name, - specialRules: specialRules, + listener: l, + addr: addr, } go func() { @@ -56,18 +54,18 @@ func NewWithInfos(addr, name, specialRules string, in chan<- C.ConnContext) (*Li } continue } - go handleRedir(rl.name, rl.specialRules, c, in) + go handleRedir(c, in, additions...) } }() return rl, nil } -func handleRedir(name, specialRules string, conn net.Conn, in chan<- C.ConnContext) { +func handleRedir(conn net.Conn, in chan<- C.ConnContext, additions ...inbound.Addition) { target, err := parserPacket(conn) if err != nil { conn.Close() return } conn.(*net.TCPConn).SetKeepAlive(true) - in <- inbound.NewSocketWithInfos(target, conn, C.REDIR, name, specialRules) + in <- inbound.NewSocket(target, conn, C.REDIR, additions...) } diff --git a/listener/shadowsocks/tcp.go b/listener/shadowsocks/tcp.go index ab235e18..9d4b13b3 100644 --- a/listener/shadowsocks/tcp.go +++ b/listener/shadowsocks/tcp.go @@ -71,20 +71,37 @@ func New(config string, tcpIn chan<- C.ConnContext, udpIn chan<- C.PacketAdapter return sl, nil } -func (l *Listener) Close() { - l.closed = true +func (l *Listener) Close() error { + var retErr error for _, lis := range l.listeners { - _ = lis.Close() + err := lis.Close() + if err != nil { + retErr = err + } } for _, lis := range l.udpListeners { - _ = lis.Close() + err := lis.Close() + if err != nil { + retErr = err + } } + return retErr } func (l *Listener) Config() string { return l.config } +func (l *Listener) AddrList() (addrList []net.Addr) { + for _, lis := range l.listeners { + addrList = append(addrList, lis.Addr()) + } + for _, lis := range l.udpListeners { + addrList = append(addrList, lis.LocalAddr()) + } + return +} + func (l *Listener) HandleConn(conn net.Conn, in chan<- C.ConnContext) { conn = l.pickCipher.StreamConn(conn) diff --git a/listener/shadowsocks/udp.go b/listener/shadowsocks/udp.go index 6357afa9..3f058406 100644 --- a/listener/shadowsocks/udp.go +++ b/listener/shadowsocks/udp.go @@ -53,6 +53,10 @@ func (l *UDPListener) Close() error { return l.packetConn.Close() } +func (l *UDPListener) LocalAddr() net.Addr { + return l.packetConn.LocalAddr() +} + func handleSocksUDP(pc net.PacketConn, in chan<- C.PacketAdapter, buf []byte, addr net.Addr) { tgtAddr := socks5.SplitAddr(buf) if tgtAddr == nil { diff --git a/listener/sing_shadowsocks/server.go b/listener/sing_shadowsocks/server.go index 967d64fa..c0f62f78 100644 --- a/listener/sing_shadowsocks/server.go +++ b/listener/sing_shadowsocks/server.go @@ -126,20 +126,38 @@ func New(config string, tcpIn chan<- C.ConnContext, udpIn chan<- C.PacketAdapter return sl, nil } -func (l *Listener) Close() { +func (l *Listener) Close() error { l.closed = true + var retErr error for _, lis := range l.listeners { - _ = lis.Close() + err := lis.Close() + if err != nil { + retErr = err + } } for _, lis := range l.udpListeners { - _ = lis.Close() + err := lis.Close() + if err != nil { + retErr = err + } } + return retErr } func (l *Listener) Config() string { return l.config } +func (l *Listener) AddrList() (addrList []net.Addr) { + for _, lis := range l.listeners { + addrList = append(addrList, lis.Addr()) + } + for _, lis := range l.udpListeners { + addrList = append(addrList, lis.LocalAddr()) + } + return +} + func (l *Listener) HandleConn(conn net.Conn, in chan<- C.ConnContext) { err := l.service.NewConnection(context.TODO(), conn, metadata.Metadata{ Protocol: "shadowsocks", diff --git a/listener/sing_tun/server.go b/listener/sing_tun/server.go index aeba8999..bebff736 100644 --- a/listener/sing_tun/server.go +++ b/listener/sing_tun/server.go @@ -272,9 +272,9 @@ func parseRange(uidRanges []ranges.Range[uint32], rangeList []string) ([]ranges. return uidRanges, nil } -func (l *Listener) Close() { +func (l *Listener) Close() error { l.closed = true - _ = common.Close( + return common.Close( l.tunStack, l.tunIf, l.defaultInterfaceMonitor, diff --git a/listener/sing_vmess/server.go b/listener/sing_vmess/server.go index 997fc6b0..ca1ecdbd 100644 --- a/listener/sing_vmess/server.go +++ b/listener/sing_vmess/server.go @@ -80,18 +80,33 @@ func New(config string, tcpIn chan<- C.ConnContext, udpIn chan<- C.PacketAdapter return sl, nil } -func (l *Listener) Close() { +func (l *Listener) Close() error { l.closed = true + var retErr error for _, lis := range l.listeners { - _ = lis.Close() + err := lis.Close() + if err != nil { + retErr = err + } } - _ = l.service.Close() + err := l.service.Close() + if err != nil { + retErr = err + } + return retErr } func (l *Listener) Config() string { return l.config } +func (l *Listener) AddrList() (addrList []net.Addr) { + for _, lis := range l.listeners { + addrList = append(addrList, lis.Addr()) + } + return +} + func (l *Listener) HandleConn(conn net.Conn, in chan<- C.ConnContext) { err := l.service.NewConnection(context.TODO(), conn, metadata.Metadata{ Protocol: "vmess", diff --git a/listener/socks/tcp.go b/listener/socks/tcp.go index dc0aff8f..e2cb9d9a 100644 --- a/listener/socks/tcp.go +++ b/listener/socks/tcp.go @@ -13,11 +13,9 @@ import ( ) type Listener struct { - listener net.Listener - addr string - closed bool - specialRules string - name string + listener net.Listener + addr string + closed bool } // RawAddress implements C.Listener @@ -36,21 +34,21 @@ func (l *Listener) Close() error { return l.listener.Close() } -func New(addr string, in chan<- C.ConnContext) (*Listener, error) { - return NewWithInfos(addr, "DEFAULT-SOCKS", "", in) -} - -func NewWithInfos(addr, name, specialRules string, in chan<- C.ConnContext) (*Listener, error) { +func New(addr string, in chan<- C.ConnContext, additions ...inbound.Addition) (*Listener, error) { + if len(additions) == 0 { + additions = []inbound.Addition{{ + InName: "DEFAULT-SOCKS", + SpecialRules: "", + }} + } l, err := inbound.Listen("tcp", addr) if err != nil { return nil, err } sl := &Listener{ - listener: l, - addr: addr, - name: name, - specialRules: specialRules, + listener: l, + addr: addr, } go func() { for { @@ -61,14 +59,14 @@ func NewWithInfos(addr, name, specialRules string, in chan<- C.ConnContext) (*Li } continue } - go handleSocks(sl.name, sl.specialRules, c, in) + go handleSocks(c, in, additions...) } }() return sl, nil } -func handleSocks(name, specialRules string, conn net.Conn, in chan<- C.ConnContext) { +func handleSocks(conn net.Conn, in chan<- C.ConnContext, additions ...inbound.Addition) { conn.(*net.TCPConn).SetKeepAlive(true) bufConn := N.NewBufferedConn(conn) head, err := bufConn.Peek(1) @@ -79,24 +77,24 @@ func handleSocks(name, specialRules string, conn net.Conn, in chan<- C.ConnConte switch head[0] { case socks4.Version: - HandleSocks4(name, specialRules, bufConn, in) + HandleSocks4(bufConn, in, additions...) case socks5.Version: - HandleSocks5(name, specialRules, bufConn, in) + HandleSocks5(bufConn, in, additions...) default: conn.Close() } } -func HandleSocks4(name, specialRules string, conn net.Conn, in chan<- C.ConnContext) { +func HandleSocks4(conn net.Conn, in chan<- C.ConnContext, additions ...inbound.Addition) { addr, _, err := socks4.ServerHandshake(conn, authStore.Authenticator()) if err != nil { conn.Close() return } - in <- inbound.NewSocketWithInfos(socks5.ParseAddr(addr), conn, C.SOCKS4, name, specialRules) + in <- inbound.NewSocket(socks5.ParseAddr(addr), conn, C.SOCKS4, additions...) } -func HandleSocks5(name, specialRules string, conn net.Conn, in chan<- C.ConnContext) { +func HandleSocks5(conn net.Conn, in chan<- C.ConnContext, additions ...inbound.Addition) { target, command, err := socks5.ServerHandshake(conn, authStore.Authenticator()) if err != nil { conn.Close() @@ -107,5 +105,5 @@ func HandleSocks5(name, specialRules string, conn net.Conn, in chan<- C.ConnCont io.Copy(io.Discard, conn) return } - in <- inbound.NewSocketWithInfos(target, conn, C.SOCKS5, name, specialRules) + in <- inbound.NewSocket(target, conn, C.SOCKS5, additions...) } diff --git a/listener/socks/udp.go b/listener/socks/udp.go index c7232d9d..a718e21b 100644 --- a/listener/socks/udp.go +++ b/listener/socks/udp.go @@ -12,11 +12,9 @@ import ( ) type UDPListener struct { - packetConn net.PacketConn - addr string - closed bool - name string - specialRules string + packetConn net.PacketConn + addr string + closed bool } // RawAddress implements C.Listener @@ -35,11 +33,13 @@ func (l *UDPListener) Close() error { return l.packetConn.Close() } -func NewUDP(addr string, in chan<- C.PacketAdapter) (*UDPListener, error) { - return NewUDPWithInfos(addr, "DEFAULT-SOCKS", "", in) -} - -func NewUDPWithInfos(addr, name, specialRules string, in chan<- C.PacketAdapter) (*UDPListener, error) { +func NewUDP(addr string, in chan<- C.PacketAdapter, additions ...inbound.Addition) (*UDPListener, error) { + if len(additions) == 0 { + additions = []inbound.Addition{{ + InName: "DEFAULT-SOCKS", + SpecialRules: "", + }} + } l, err := net.ListenPacket("udp", addr) if err != nil { return nil, err @@ -50,10 +50,8 @@ func NewUDPWithInfos(addr, name, specialRules string, in chan<- C.PacketAdapter) } sl := &UDPListener{ - packetConn: l, - addr: addr, - specialRules: specialRules, - name: name, + packetConn: l, + addr: addr, } go func() { for { @@ -66,14 +64,14 @@ func NewUDPWithInfos(addr, name, specialRules string, in chan<- C.PacketAdapter) } continue } - handleSocksUDP(sl.name, sl.specialRules, l, in, buf[:n], remoteAddr) + handleSocksUDP(l, in, buf[:n], remoteAddr, additions...) } }() return sl, nil } -func handleSocksUDP(name, specialRules string, pc net.PacketConn, in chan<- C.PacketAdapter, buf []byte, addr net.Addr) { +func handleSocksUDP(pc net.PacketConn, in chan<- C.PacketAdapter, buf []byte, addr net.Addr, additions ...inbound.Addition) { target, payload, err := socks5.DecodeUDPPacket(buf) if err != nil { // Unresolved UDP packet, return buffer to the pool @@ -87,7 +85,7 @@ func handleSocksUDP(name, specialRules string, pc net.PacketConn, in chan<- C.Pa bufRef: buf, } select { - case in <- inbound.NewPacketWithInfos(target, packet, C.SOCKS5, name, specialRules): + case in <- inbound.NewPacket(target, packet, C.SOCKS5, additions...): default: } } diff --git a/listener/tproxy/tproxy.go b/listener/tproxy/tproxy.go index 857eb5e0..59b8f090 100644 --- a/listener/tproxy/tproxy.go +++ b/listener/tproxy/tproxy.go @@ -9,11 +9,9 @@ import ( ) type Listener struct { - listener net.Listener - addr string - closed bool - name string - specialRules string + listener net.Listener + addr string + closed bool } // RawAddress implements C.Listener @@ -32,17 +30,19 @@ func (l *Listener) Close() error { return l.listener.Close() } -func (l *Listener) handleTProxy(name, specialRules string, conn net.Conn, in chan<- C.ConnContext) { +func (l *Listener) handleTProxy(conn net.Conn, in chan<- C.ConnContext, additions ...inbound.Addition) { target := socks5.ParseAddrToSocksAddr(conn.LocalAddr()) conn.(*net.TCPConn).SetKeepAlive(true) - in <- inbound.NewSocketWithInfos(target, conn, C.TPROXY, name, specialRules) + in <- inbound.NewSocket(target, conn, C.TPROXY, additions...) } -func New(addr string, in chan<- C.ConnContext) (*Listener, error) { - return NewWithInfos(addr, "DEFAULT-TPROXY", "", in) -} - -func NewWithInfos(addr, name, specialRules string, in chan<- C.ConnContext) (*Listener, error) { +func New(addr string, in chan<- C.ConnContext, additions ...inbound.Addition) (*Listener, error) { + if len(additions) == 0 { + additions = []inbound.Addition{{ + InName: "DEFAULT-TPROXY", + SpecialRules: "", + }} + } l, err := net.Listen("tcp", addr) if err != nil { return nil, err @@ -60,10 +60,8 @@ func NewWithInfos(addr, name, specialRules string, in chan<- C.ConnContext) (*Li } rl := &Listener{ - listener: l, - addr: addr, - name: name, - specialRules: specialRules, + listener: l, + addr: addr, } go func() { @@ -75,7 +73,7 @@ func NewWithInfos(addr, name, specialRules string, in chan<- C.ConnContext) (*Li } continue } - go rl.handleTProxy(rl.name, rl.specialRules, c, in) + go rl.handleTProxy(c, in, additions...) } }() diff --git a/listener/tproxy/udp.go b/listener/tproxy/udp.go index c25bf103..9488a668 100644 --- a/listener/tproxy/udp.go +++ b/listener/tproxy/udp.go @@ -11,11 +11,9 @@ import ( ) type UDPListener struct { - packetConn net.PacketConn - addr string - closed bool - name string - specialRules string + packetConn net.PacketConn + addr string + closed bool } // RawAddress implements C.Listener @@ -34,11 +32,13 @@ func (l *UDPListener) Close() error { return l.packetConn.Close() } -func NewUDP(addr string, in chan<- C.PacketAdapter) (*UDPListener, error) { - return NewUDPWithInfos(addr, "DEFAULT-TPROXY", "", in) -} - -func NewUDPWithInfos(addr, name, specialRules string, in chan<- C.PacketAdapter) (*UDPListener, error) { +func NewUDP(addr string, in chan<- C.PacketAdapter, additions ...inbound.Addition) (*UDPListener, error) { + if len(additions) == 0 { + additions = []inbound.Addition{{ + InName: "DEFAULT-TPROXY", + SpecialRules: "", + }} + } l, err := net.ListenPacket("udp", addr) if err != nil { return nil, err @@ -83,14 +83,14 @@ func NewUDPWithInfos(addr, name, specialRules string, in chan<- C.PacketAdapter) // try to unmap 4in6 address lAddr = netip.AddrPortFrom(lAddr.Addr().Unmap(), lAddr.Port()) } - handlePacketConn(rl.name, rl.specialRules, l, in, buf[:n], lAddr, rAddr) + handlePacketConn(l, in, buf[:n], lAddr, rAddr, additions...) } }() return rl, nil } -func handlePacketConn(name, specialRules string, pc net.PacketConn, in chan<- C.PacketAdapter, buf []byte, lAddr, rAddr netip.AddrPort) { +func handlePacketConn(pc net.PacketConn, in chan<- C.PacketAdapter, buf []byte, lAddr, rAddr netip.AddrPort, additions ...inbound.Addition) { target := socks5.AddrFromStdAddrPort(rAddr) pkt := &packet{ pc: pc, @@ -98,7 +98,7 @@ func handlePacketConn(name, specialRules string, pc net.PacketConn, in chan<- C. buf: buf, } select { - case in <- inbound.NewPacketWithInfos(target, pkt, C.TPROXY, name, specialRules): + case in <- inbound.NewPacket(target, pkt, C.TPROXY, additions...): default: } } diff --git a/listener/tuic/server.go b/listener/tuic/server.go index 1e7209a8..a5ed7151 100644 --- a/listener/tuic/server.go +++ b/listener/tuic/server.go @@ -25,11 +25,13 @@ type Listener struct { servers []*tuic.Server } -func New(config LC.TuicServer, tcpIn chan<- C.ConnContext, udpIn chan<- C.PacketAdapter) (*Listener, error) { - return NewWithInfos("DEFAULT-TUIC", "", config, tcpIn, udpIn) -} - -func NewWithInfos(name, specialRules string, config LC.TuicServer, tcpIn chan<- C.ConnContext, udpIn chan<- C.PacketAdapter) (*Listener, error) { +func New(config LC.TuicServer, tcpIn chan<- C.ConnContext, udpIn chan<- C.PacketAdapter, additions ...inbound.Addition) (*Listener, error) { + if len(additions) == 0 { + additions = []inbound.Addition{{ + InName: "DEFAULT-TUIC", + SpecialRules: "", + }} + } cert, err := CN.ParseCert(config.Certificate, config.PrivateKey) if err != nil { return nil, err @@ -61,12 +63,12 @@ func NewWithInfos(name, specialRules string, config LC.TuicServer, tcpIn chan<- option := &tuic.ServerOption{ HandleTcpFn: func(conn net.Conn, addr socks5.Addr) error { - tcpIn <- inbound.NewSocketWithInfos(addr, conn, C.TUIC, name, specialRules) + tcpIn <- inbound.NewSocket(addr, conn, C.TUIC, additions...) return nil }, HandleUdpFn: func(addr socks5.Addr, packet C.UDPPacket) error { select { - case udpIn <- inbound.NewPacketWithInfos(addr, packet, C.TUIC, name, specialRules): + case udpIn <- inbound.NewPacket(addr, packet, C.TUIC, additions...): default: } return nil @@ -116,7 +118,6 @@ func NewWithInfos(name, specialRules string, config LC.TuicServer, tcpIn chan<- return sl, nil } -// Close implements C.Listener func (l *Listener) Close() error { l.closed = true var retErr error @@ -144,4 +145,4 @@ func (l *Listener) AddrList() (addrList []net.Addr) { addrList = append(addrList, lis.LocalAddr()) } return -} \ No newline at end of file +}