diff --git a/common/trafficcontrol/manager.go b/common/trafficcontrol/manager.go deleted file mode 100644 index 86134a77..00000000 --- a/common/trafficcontrol/manager.go +++ /dev/null @@ -1,145 +0,0 @@ -package trafficcontrol - -import ( - "io" - "net" - "sync" - "sync/atomic" - - "github.com/sagernet/sing/common/buf" - "github.com/sagernet/sing/common/bufio" - M "github.com/sagernet/sing/common/metadata" - N "github.com/sagernet/sing/common/network" -) - -type Manager[U comparable] struct { - access sync.Mutex - users map[U]*Traffic -} - -type Traffic struct { - Upload uint64 - Download uint64 -} - -func NewManager[U comparable]() *Manager[U] { - return &Manager[U]{ - users: make(map[U]*Traffic), - } -} - -func (m *Manager[U]) Reset() { - m.users = make(map[U]*Traffic) -} - -func (m *Manager[U]) TrackConnection(user U, conn net.Conn) net.Conn { - m.access.Lock() - defer m.access.Unlock() - var traffic *Traffic - if t, loaded := m.users[user]; loaded { - traffic = t - } else { - traffic = new(Traffic) - m.users[user] = traffic - } - return &TrackConn{conn, traffic} -} - -func (m *Manager[U]) TrackPacketConnection(user U, conn N.PacketConn) N.PacketConn { - m.access.Lock() - defer m.access.Unlock() - var traffic *Traffic - if t, loaded := m.users[user]; loaded { - traffic = t - } else { - traffic = new(Traffic) - m.users[user] = traffic - } - return &TrackPacketConn{conn, traffic} -} - -func (m *Manager[U]) ReadTraffics() map[U]Traffic { - m.access.Lock() - defer m.access.Unlock() - - trafficMap := make(map[U]Traffic) - for user, traffic := range m.users { - upload := atomic.SwapUint64(&traffic.Upload, 0) - download := atomic.SwapUint64(&traffic.Download, 0) - if upload == 0 && download == 0 { - continue - } - trafficMap[user] = Traffic{ - Upload: upload, - Download: download, - } - } - return trafficMap -} - -type TrackConn struct { - net.Conn - *Traffic -} - -func (c *TrackConn) Read(p []byte) (n int, err error) { - n, err = c.Conn.Read(p) - if n > 0 { - atomic.AddUint64(&c.Upload, uint64(n)) - } - return -} - -func (c *TrackConn) Write(p []byte) (n int, err error) { - n, err = c.Conn.Write(p) - if n > 0 { - atomic.AddUint64(&c.Download, uint64(n)) - } - return -} - -func (c *TrackConn) WriteTo(w io.Writer) (n int64, err error) { - n, err = bufio.Copy(w, c.Conn) - if n > 0 { - atomic.AddUint64(&c.Upload, uint64(n)) - } - return -} - -func (c *TrackConn) ReadFrom(r io.Reader) (n int64, err error) { - n, err = bufio.Copy(c.Conn, r) - if n > 0 { - atomic.AddUint64(&c.Download, uint64(n)) - } - return -} - -func (c *TrackConn) Upstream() any { - return c.Conn -} - -type TrackPacketConn struct { - N.PacketConn - *Traffic -} - -func (c *TrackPacketConn) ReadPacket(buffer *buf.Buffer) (M.Socksaddr, error) { - destination, err := c.PacketConn.ReadPacket(buffer) - if err == nil { - atomic.AddUint64(&c.Upload, uint64(buffer.Len())) - } - return destination, err -} - -func (c *TrackPacketConn) WritePacket(buffer *buf.Buffer, destination M.Socksaddr) error { - n := buffer.Len() - err := c.PacketConn.WritePacket(buffer, destination) - if err == nil { - atomic.AddUint64(&c.Download, uint64(n)) - } - return err -} - -func (c *TrackPacketConn) Upstream() any { - return c.PacketConn -} diff --git a/inbound/shadowsocks_control.go b/inbound/shadowsocks_control.go deleted file mode 100644 index 1a6c02ae..00000000 --- a/inbound/shadowsocks_control.go +++ /dev/null @@ -1,94 +0,0 @@ -package inbound - -import ( - "encoding/json" - "io" - "net/http" - - C "github.com/sagernet/sing-box/constant" - "github.com/sagernet/sing-box/option" - "github.com/sagernet/sing/common" - E "github.com/sagernet/sing/common/exceptions" - F "github.com/sagernet/sing/common/format" - - "github.com/go-chi/chi/v5" - "github.com/go-chi/render" -) - -func (h *ShadowsocksMulti) createHandler() http.Handler { - router := chi.NewRouter() - router.Get("/", h.handleHello) - router.Put("/users", h.handleUpdateUsers) - router.Get("/traffics", h.handleReadTraffics) - return router -} - -func (h *ShadowsocksMulti) handleHello(writer http.ResponseWriter, request *http.Request) { - render.JSON(writer, request, render.M{ - "server": "sing-box", - "version": C.Version, - }) -} - -func (h *ShadowsocksMulti) handleUpdateUsers(writer http.ResponseWriter, request *http.Request) { - var users []option.ShadowsocksUser - err := readRequest(request, &users) - if err != nil { - h.newError(E.Cause(err, "controller: update users: parse request")) - writer.WriteHeader(http.StatusBadRequest) - writer.Write([]byte(F.ToString(err))) - return - } - users = append([]option.ShadowsocksUser{{ - Name: "control", - Password: h.users[0].Password, - }}, users...) - err = h.service.UpdateUsersWithPasswords(common.MapIndexed(users, func(index int, user option.ShadowsocksUser) int { - return index - }), common.Map(users, func(user option.ShadowsocksUser) string { - return user.Password - })) - if err != nil { - h.newError(E.Cause(err, "controller: update users")) - writer.WriteHeader(http.StatusBadRequest) - writer.Write([]byte(F.ToString(err))) - return - } - h.users = users - h.trafficManager.Reset() - writer.WriteHeader(http.StatusNoContent) - h.logger.Info("controller: updated ", len(users)-1, " users") -} - -type ShadowsocksUserTraffic struct { - Name string `json:"name,omitempty"` - Upload uint64 `json:"upload,omitempty"` - Download uint64 `json:"download,omitempty"` -} - -func (h *ShadowsocksMulti) handleReadTraffics(writer http.ResponseWriter, request *http.Request) { - h.logger.Debug("controller: traffics sent") - trafficMap := h.trafficManager.ReadTraffics() - if len(trafficMap) == 0 { - writer.WriteHeader(http.StatusNoContent) - return - } - traffics := make([]ShadowsocksUserTraffic, 0, len(trafficMap)) - for user, traffic := range trafficMap { - traffics = append(traffics, ShadowsocksUserTraffic{ - Name: h.users[user].Name, - Upload: traffic.Upload, - Download: traffic.Download, - }) - } - render.JSON(writer, request, traffics) -} - -func readRequest(request *http.Request, v any) error { - defer request.Body.Close() - content, err := io.ReadAll(request.Body) - if err != nil { - return err - } - return json.Unmarshal(content, v) -} diff --git a/inbound/shadowsocks_multi.go b/inbound/shadowsocks_multi.go index 242a8ccf..caf9183a 100644 --- a/inbound/shadowsocks_multi.go +++ b/inbound/shadowsocks_multi.go @@ -3,12 +3,9 @@ package inbound import ( "context" "net" - "net/http" "os" "github.com/sagernet/sing-box/adapter" - "github.com/sagernet/sing-box/common/pipelistener" - "github.com/sagernet/sing-box/common/trafficcontrol" C "github.com/sagernet/sing-box/constant" "github.com/sagernet/sing-box/log" "github.com/sagernet/sing-box/option" @@ -16,7 +13,6 @@ import ( "github.com/sagernet/sing/common" "github.com/sagernet/sing/common/auth" "github.com/sagernet/sing/common/buf" - E "github.com/sagernet/sing/common/exceptions" F "github.com/sagernet/sing/common/format" N "github.com/sagernet/sing/common/network" ) @@ -28,12 +24,8 @@ var ( type ShadowsocksMulti struct { myInboundAdapter - service *shadowaead_2022.MultiService[int] - users []option.ShadowsocksUser - controlEnabled bool - controller *http.Server - controllerPipe *pipelistener.Listener - trafficManager *trafficcontrol.Manager[int] + service *shadowaead_2022.MultiService[int] + users []option.ShadowsocksUser } func newShadowsocksMulti(ctx context.Context, router adapter.Router, logger log.ContextLogger, tag string, options option.ShadowsocksInboundOptions) (*ShadowsocksMulti, error) { @@ -62,20 +54,7 @@ func newShadowsocksMulti(ctx context.Context, router adapter.Router, logger log. udpTimeout, adapter.NewUpstreamContextHandler(inbound.newConnection, inbound.newPacketConnection, inbound), ) - users := options.Users - if options.ControlPassword != "" { - inbound.controlEnabled = true - users = append([]option.ShadowsocksUser{{ - Name: "control", - Password: options.ControlPassword, - }}, users...) - inbound.controller = &http.Server{Handler: inbound.createHandler()} - inbound.trafficManager = trafficcontrol.NewManager[int]() - } - if err != nil { - return nil, err - } - err = service.UpdateUsersWithPasswords(common.MapIndexed(users, func(index int, user option.ShadowsocksUser) int { + err = service.UpdateUsersWithPasswords(common.MapIndexed(options.Users, func(index int, user option.ShadowsocksUser) int { return index }), common.Map(options.Users, func(user option.ShadowsocksUser) string { return user.Password @@ -85,30 +64,10 @@ func newShadowsocksMulti(ctx context.Context, router adapter.Router, logger log. } inbound.service = service inbound.packetUpstream = service - inbound.users = users + inbound.users = options.Users return inbound, err } -func (h *ShadowsocksMulti) Start() error { - if h.controlEnabled { - h.controllerPipe = pipelistener.New(16) - go func() { - err := h.controller.Serve(h.controllerPipe) - if err != nil { - h.newError(E.Cause(err, "controller serve error")) - } - }() - } - return h.myInboundAdapter.Start() -} - -func (h *ShadowsocksMulti) Close() error { - if h.controlEnabled { - h.controllerPipe.Close() - } - return h.myInboundAdapter.Close() -} - func (h *ShadowsocksMulti) NewConnection(ctx context.Context, conn net.Conn, metadata adapter.InboundContext) error { return h.service.NewConnection(adapter.WithContext(log.ContextWithNewID(ctx), &metadata), conn, adapter.UpstreamMetadata(metadata)) } @@ -126,11 +85,6 @@ func (h *ShadowsocksMulti) newConnection(ctx context.Context, conn net.Conn, met if !loaded { return os.ErrInvalid } - if userIndex == 0 && h.controlEnabled { - h.logger.InfoContext(ctx, "inbound control connection") - h.controllerPipe.Serve(conn) - return nil - } user := h.users[userIndex].Name if user == "" { user = F.ToString(userIndex)