Add new admin panel, failover, dns fallback, providers, limiters. Update XHTTP

This commit is contained in:
Sergei Maklagin
2026-05-11 00:59:35 +03:00
parent 652e0baf57
commit 3bd162ed6f
241 changed files with 36409 additions and 4086 deletions

View File

@@ -0,0 +1,18 @@
package constant
import (
"github.com/sagernet/sing-box/adapter"
C "github.com/sagernet/sing-box/service/manager/constant"
)
type RateLimiterManager interface {
AddRateLimiterStrategyManager(outbound adapter.Outbound) error
GetRateLimiterStrategyManager(tag string) (RateLimiterStrategyManager, bool)
GetRateLimiterStrategyManagerTags() []string
}
type RateLimiterStrategyManager interface {
UpdateRateLimiter(limiter C.RateLimiter)
UpdateRateLimiters(limiter []C.RateLimiter)
DeleteRateLimiter(username string)
}

View File

@@ -0,0 +1,18 @@
package constant
import (
"github.com/sagernet/sing-box/adapter"
C "github.com/sagernet/sing-box/service/manager/constant"
)
type TrafficLimiterManager interface {
AddTrafficLimiterStrategyManager(outbound adapter.Outbound) error
GetTrafficLimiterStrategyManager(tag string) (TrafficLimiterStrategyManager, bool)
GetTrafficLimiterStrategyManagerTags() []string
}
type TrafficLimiterStrategyManager interface {
UpdateTrafficLimiter(limiter C.TrafficLimiter)
UpdateTrafficLimiters(limiter []C.TrafficLimiter)
DeleteTrafficLimiter(username string)
}

View File

@@ -42,7 +42,7 @@ func (m *HysteriaManager) GetUserManagerTags() []string {
m.access.Lock()
defer m.access.Unlock()
tags := make([]string, 0, len(m.inbounds))
for tag, _ := range m.inbounds {
for tag := range m.inbounds {
tags = append(tags, tag)
}
return tags

View File

@@ -42,7 +42,7 @@ func (m *Hysteria2Manager) GetUserManagerTags() []string {
m.access.Lock()
defer m.access.Unlock()
tags := make([]string, 0, len(m.inbounds))
for tag, _ := range m.inbounds {
for tag := range m.inbounds {
tags = append(tags, tag)
}
return tags

View File

@@ -42,7 +42,7 @@ func (m *MTProxyManager) GetUserManagerTags() []string {
m.access.Lock()
defer m.access.Unlock()
tags := make([]string, 0, len(m.inbounds))
for tag, _ := range m.inbounds {
for tag := range m.inbounds {
tags = append(tags, tag)
}
return tags

View File

@@ -42,7 +42,7 @@ func (m *TrojanManager) GetUserManagerTags() []string {
m.access.Lock()
defer m.access.Unlock()
tags := make([]string, 0, len(m.inbounds))
for tag, _ := range m.inbounds {
for tag := range m.inbounds {
tags = append(tags, tag)
}
return tags

View File

@@ -42,7 +42,7 @@ func (m *TUICManager) GetUserManagerTags() []string {
m.access.Lock()
defer m.access.Unlock()
tags := make([]string, 0, len(m.inbounds))
for tag, _ := range m.inbounds {
for tag := range m.inbounds {
tags = append(tags, tag)
}
return tags

View File

@@ -42,7 +42,7 @@ func (m *VLESSManager) GetUserManagerTags() []string {
m.access.Lock()
defer m.access.Unlock()
tags := make([]string, 0, len(m.inbounds))
for tag, _ := range m.inbounds {
for tag := range m.inbounds {
tags = append(tags, tag)
}
return tags

View File

@@ -42,7 +42,7 @@ func (m *VMessManager) GetUserManagerTags() []string {
m.mtx.Lock()
defer m.mtx.Unlock()
tags := make([]string, 0, len(m.inbounds))
for tag, _ := range m.inbounds {
for tag := range m.inbounds {
tags = append(tags, tag)
}
return tags

View File

@@ -1,9 +1,11 @@
package limiter
import (
"context"
"sync"
"github.com/sagernet/sing-box/adapter"
"github.com/sagernet/sing-box/log"
"github.com/sagernet/sing-box/protocol/limiter/bandwidth"
CM "github.com/sagernet/sing-box/service/manager/constant"
"github.com/sagernet/sing-box/service/node/constant"
@@ -15,14 +17,21 @@ type ManagedBandwidthStrategy interface {
}
type BandwidthLimiterManager struct {
ctx context.Context
nodeManager CM.NodeManager
logger log.ContextLogger
managers map[string]*BandwidthLimiterStrategyManager
mtx sync.Mutex
}
func NewBandwidthLimiterManager() *BandwidthLimiterManager {
func NewBandwidthLimiterManager(ctx context.Context, nodeManager CM.NodeManager, logger log.ContextLogger) *BandwidthLimiterManager {
return &BandwidthLimiterManager{
managers: make(map[string]*BandwidthLimiterStrategyManager),
ctx: ctx,
nodeManager: nodeManager,
logger: logger,
managers: make(map[string]*BandwidthLimiterStrategyManager),
}
}
@@ -38,6 +47,7 @@ func (m *BandwidthLimiterManager) AddBandwidthLimiterStrategyManager(outbound ad
return E.New("strategy for outbound ", outbound.Tag(), " is not manager")
}
m.managers[outbound.Tag()] = &BandwidthLimiterStrategyManager{
manager: m,
strategy: strategy,
strategiesMap: make(map[string]bandwidth.BandwidthStrategy),
}
@@ -55,13 +65,14 @@ func (m *BandwidthLimiterManager) GetBandwidthLimiterStrategyManagerTags() []str
m.mtx.Lock()
defer m.mtx.Unlock()
tags := make([]string, 0, len(m.managers))
for tag, _ := range m.managers {
for tag := range m.managers {
tags = append(tags, tag)
}
return tags
}
type BandwidthLimiterStrategyManager struct {
manager *BandwidthLimiterManager
strategy ManagedBandwidthStrategy
strategiesMap map[string]bandwidth.BandwidthStrategy
@@ -75,8 +86,9 @@ func (i *BandwidthLimiterStrategyManager) postUpdate() {
func (i *BandwidthLimiterStrategyManager) UpdateBandwidthLimiter(limiter CM.BandwidthLimiter) {
i.mtx.Lock()
defer i.mtx.Unlock()
strategy, err := bandwidth.CreateStrategy(limiter.Strategy, limiter.Mode, limiter.ConnectionType, limiter.RawSpeed)
strategy, err := bandwidth.CreateStrategy(limiter.Strategy, limiter.Mode, limiter.ConnectionType, limiter.RawSpeed, limiter.FlowKeys)
if err != nil {
i.manager.logger.ErrorContext(i.manager.ctx, err)
return
}
i.strategiesMap[limiter.Username] = strategy
@@ -89,9 +101,10 @@ func (i *BandwidthLimiterStrategyManager) UpdateBandwidthLimiters(limiters []CM.
clear(i.strategiesMap)
newStrategiesMap := make(map[string]bandwidth.BandwidthStrategy)
for _, limiter := range limiters {
strategy, err := bandwidth.CreateStrategy(limiter.Strategy, limiter.Mode, limiter.ConnectionType, limiter.RawSpeed)
strategy, err := bandwidth.CreateStrategy(limiter.Strategy, limiter.Mode, limiter.ConnectionType, limiter.RawSpeed, limiter.FlowKeys)
if err != nil {
return
i.manager.logger.ErrorContext(i.manager.ctx, err)
continue
}
newStrategiesMap[limiter.Username] = strategy
}

View File

@@ -18,18 +18,21 @@ type ManagedConnectionStrategy interface {
}
type ConnectionLimiterManager struct {
ctx context.Context
nodeManager CM.NodeManager
managers map[string]*ConnectionLimiterStrategyManager
logger log.Logger
logger log.ContextLogger
managers map[string]*ConnectionLimiterStrategyManager
mtx sync.Mutex
}
func NewConnectionLimiterManager(nodeManager CM.NodeManager, logger log.Logger) *ConnectionLimiterManager {
func NewConnectionLimiterManager(ctx context.Context, nodeManager CM.NodeManager, logger log.ContextLogger) *ConnectionLimiterManager {
return &ConnectionLimiterManager{
ctx: ctx,
nodeManager: nodeManager,
managers: make(map[string]*ConnectionLimiterStrategyManager),
logger: logger,
managers: make(map[string]*ConnectionLimiterStrategyManager),
}
}
@@ -45,9 +48,9 @@ func (m *ConnectionLimiterManager) AddConnectionLimiterStrategyManager(outbound
return E.New("strategy ", strategy, " is not manager")
}
m.managers[outbound.Tag()] = &ConnectionLimiterStrategyManager{
manager: m,
strategy: strategy,
strategiesMap: make(map[string]connection.ConnectionStrategy),
manager: m,
}
return nil
}
@@ -63,17 +66,17 @@ func (m *ConnectionLimiterManager) GetConnectionLimiterStrategyManagerTags() []s
m.mtx.Lock()
defer m.mtx.Unlock()
tags := make([]string, 0, len(m.managers))
for tag, _ := range m.managers {
for tag := range m.managers {
tags = append(tags, tag)
}
return tags
}
type ConnectionLimiterStrategyManager struct {
manager *ConnectionLimiterManager
strategy ManagedConnectionStrategy
strategiesMap map[string]connection.ConnectionStrategy
tag string
manager *ConnectionLimiterManager
mtx sync.Mutex
}
@@ -87,10 +90,12 @@ func (i *ConnectionLimiterStrategyManager) UpdateConnectionLimiter(limiter CM.Co
defer i.mtx.Unlock()
lock, err := i.createLock(limiter)
if err != nil {
i.manager.logger.ErrorContext(i.manager.ctx, err)
return
}
strategy, err := connection.CreateStrategy(limiter.Strategy, limiter.ConnectionType, lock)
if err != nil {
i.manager.logger.ErrorContext(i.manager.ctx, err)
return
}
i.strategiesMap[limiter.Username] = strategy
@@ -105,11 +110,13 @@ func (i *ConnectionLimiterStrategyManager) UpdateConnectionLimiters(limiters []C
for _, limiter := range limiters {
lock, err := i.createLock(limiter)
if err != nil {
return
i.manager.logger.ErrorContext(i.manager.ctx, err)
continue
}
strategy, err := connection.CreateStrategy(limiter.Strategy, limiter.ConnectionType, lock)
if err != nil {
return
i.manager.logger.ErrorContext(i.manager.ctx, err)
continue
}
newStrategiesMap[limiter.Username] = strategy
}
@@ -128,7 +135,7 @@ func (i *ConnectionLimiterStrategyManager) createLock(limiter CM.ConnectionLimit
switch limiter.LockType {
case "manager":
return i.newManagerLock(limiter.ID), nil
case "":
case "default", "":
return connection.NewDefaultLock(limiter.Count), nil
default:
return nil, E.New("unknown lock type \"", limiter.LockType, "\"")

View File

@@ -0,0 +1,129 @@
package limiter
import (
"context"
"sync"
"time"
"github.com/sagernet/sing-box/adapter"
"github.com/sagernet/sing-box/log"
"github.com/sagernet/sing-box/protocol/limiter/rate"
CM "github.com/sagernet/sing-box/service/manager/constant"
"github.com/sagernet/sing-box/service/node/constant"
E "github.com/sagernet/sing/common/exceptions"
)
type ManagedRateStrategy interface {
UpdateStrategies(strategies map[string]rate.RateStrategy)
}
type RateLimiterManager struct {
ctx context.Context
nodeManager CM.NodeManager
logger log.ContextLogger
managers map[string]*RateLimiterStrategyManager
mtx sync.Mutex
}
func NewRateLimiterManager(ctx context.Context, nodeManager CM.NodeManager, logger log.ContextLogger) *RateLimiterManager {
return &RateLimiterManager{
ctx: ctx,
nodeManager: nodeManager,
logger: logger,
managers: make(map[string]*RateLimiterStrategyManager),
}
}
func (m *RateLimiterManager) AddRateLimiterStrategyManager(outbound adapter.Outbound) error {
m.mtx.Lock()
defer m.mtx.Unlock()
limiter, ok := outbound.(*rate.Outbound)
if !ok {
return E.New("invalid rate limiter: ", outbound.Tag())
}
strategy, ok := limiter.GetStrategy().(ManagedRateStrategy)
if !ok {
return E.New("strategy for outbound ", outbound.Tag(), " is not manager")
}
m.managers[outbound.Tag()] = &RateLimiterStrategyManager{
manager: m,
strategy: strategy,
strategiesMap: make(map[string]rate.RateStrategy),
}
return nil
}
func (m *RateLimiterManager) GetRateLimiterStrategyManager(tag string) (constant.RateLimiterStrategyManager, bool) {
m.mtx.Lock()
defer m.mtx.Unlock()
manager, ok := m.managers[tag]
return manager, ok
}
func (m *RateLimiterManager) GetRateLimiterStrategyManagerTags() []string {
m.mtx.Lock()
defer m.mtx.Unlock()
tags := make([]string, 0, len(m.managers))
for tag := range m.managers {
tags = append(tags, tag)
}
return tags
}
type RateLimiterStrategyManager struct {
manager *RateLimiterManager
strategy ManagedRateStrategy
strategiesMap map[string]rate.RateStrategy
mtx sync.Mutex
}
func (i *RateLimiterStrategyManager) postUpdate() {
i.strategy.UpdateStrategies(i.strategiesMap)
}
func (i *RateLimiterStrategyManager) createStrategy(limiter CM.RateLimiter) (rate.RateStrategy, error) {
interval, err := time.ParseDuration(limiter.Interval)
if err != nil {
return nil, err
}
return rate.CreateStrategy(limiter.Strategy, limiter.ConnectionType, int(limiter.Count), interval)
}
func (i *RateLimiterStrategyManager) UpdateRateLimiter(limiter CM.RateLimiter) {
i.mtx.Lock()
defer i.mtx.Unlock()
strategy, err := i.createStrategy(limiter)
if err != nil {
i.manager.logger.ErrorContext(i.manager.ctx, err)
return
}
i.strategiesMap[limiter.Username] = strategy
i.postUpdate()
}
func (i *RateLimiterStrategyManager) UpdateRateLimiters(limiters []CM.RateLimiter) {
i.mtx.Lock()
defer i.mtx.Unlock()
clear(i.strategiesMap)
newStrategiesMap := make(map[string]rate.RateStrategy)
for _, limiter := range limiters {
strategy, err := i.createStrategy(limiter)
if err != nil {
i.manager.logger.ErrorContext(i.manager.ctx, err)
continue
}
newStrategiesMap[limiter.Username] = strategy
}
i.strategiesMap = newStrategiesMap
i.postUpdate()
}
func (i *RateLimiterStrategyManager) DeleteRateLimiter(username string) {
i.mtx.Lock()
defer i.mtx.Unlock()
delete(i.strategiesMap, username)
i.postUpdate()
}

View File

@@ -0,0 +1,216 @@
package limiter
import (
"context"
"sync"
"time"
"github.com/sagernet/sing-box/adapter"
"github.com/sagernet/sing-box/log"
"github.com/sagernet/sing-box/protocol/limiter/traffic"
CM "github.com/sagernet/sing-box/service/manager/constant"
"github.com/sagernet/sing-box/service/node/constant"
E "github.com/sagernet/sing/common/exceptions"
)
type ManagedTrafficStrategy interface {
UpdateStrategies(strategies map[string]traffic.TrafficStrategy)
}
type TrafficLimiterManager struct {
ctx context.Context
nodeManager CM.NodeManager
logger log.ContextLogger
managers map[string]*TrafficLimiterStrategyManager
mtx sync.Mutex
}
func NewTrafficLimiterManager(ctx context.Context, nodeManager CM.NodeManager, logger log.ContextLogger) *TrafficLimiterManager {
manager := &TrafficLimiterManager{
ctx: ctx,
nodeManager: nodeManager,
logger: logger,
managers: make(map[string]*TrafficLimiterStrategyManager),
}
go func() {
timer := time.NewTimer(time.Second * 5)
for {
select {
case <-ctx.Done():
return
default:
}
select {
case <-timer.C:
for _, strategyManager := range manager.managers {
strategyManager.mtx.Lock()
for _, limiter := range strategyManager.limiters {
err := limiter.UpdateRemainingTraffic()
if err != nil {
logger.ErrorContext(ctx, err)
}
}
strategyManager.mtx.Unlock()
}
timer.Reset(time.Second * 5)
case <-ctx.Done():
return
}
}
}()
return manager
}
func (m *TrafficLimiterManager) AddTrafficLimiterStrategyManager(outbound adapter.Outbound) error {
m.mtx.Lock()
defer m.mtx.Unlock()
limiter, ok := outbound.(*traffic.Outbound)
if !ok {
return E.New("invalid traffic limiter: ", outbound.Tag())
}
strategy, ok := limiter.GetStrategy().(ManagedTrafficStrategy)
if !ok {
return E.New("strategy ", outbound.Tag(), " is not manager")
}
m.managers[outbound.Tag()] = &TrafficLimiterStrategyManager{
manager: m,
strategy: strategy,
strategiesMap: make(map[string]traffic.TrafficStrategy),
limiters: make(map[string]*TrafficLimiter),
}
return nil
}
func (m *TrafficLimiterManager) GetTrafficLimiterStrategyManager(tag string) (constant.TrafficLimiterStrategyManager, bool) {
m.mtx.Lock()
defer m.mtx.Unlock()
manager, ok := m.managers[tag]
return manager, ok
}
func (m *TrafficLimiterManager) GetTrafficLimiterStrategyManagerTags() []string {
m.mtx.Lock()
defer m.mtx.Unlock()
tags := make([]string, 0, len(m.managers))
for tag := range m.managers {
tags = append(tags, tag)
}
return tags
}
type TrafficLimiterStrategyManager struct {
manager *TrafficLimiterManager
strategy ManagedTrafficStrategy
strategiesMap map[string]traffic.TrafficStrategy
limiters map[string]*TrafficLimiter
mtx sync.Mutex
}
func (i *TrafficLimiterStrategyManager) postUpdate() {
i.strategy.UpdateStrategies(i.strategiesMap)
}
func (i *TrafficLimiterStrategyManager) UpdateTrafficLimiter(limiter CM.TrafficLimiter) {
i.mtx.Lock()
defer i.mtx.Unlock()
trafficLimiter := NewTrafficLimiter(i.manager.nodeManager, limiter)
strategy, err := traffic.CreateStrategy(trafficLimiter, limiter.Strategy, limiter.Mode)
if err != nil {
i.manager.logger.ErrorContext(i.manager.ctx, err)
return
}
i.limiters[limiter.Username] = trafficLimiter
i.strategiesMap[limiter.Username] = strategy
i.postUpdate()
}
func (i *TrafficLimiterStrategyManager) UpdateTrafficLimiters(limiters []CM.TrafficLimiter) {
i.mtx.Lock()
defer i.mtx.Unlock()
clear(i.strategiesMap)
newStrategiesMap := make(map[string]traffic.TrafficStrategy)
for _, limiter := range limiters {
trafficLimiter := NewTrafficLimiter(i.manager.nodeManager, limiter)
strategy, err := traffic.CreateStrategy(trafficLimiter, limiter.Strategy, limiter.Mode)
if err != nil {
i.manager.logger.ErrorContext(i.manager.ctx, err)
continue
}
i.limiters[limiter.Username] = trafficLimiter
newStrategiesMap[limiter.Username] = strategy
}
i.strategiesMap = newStrategiesMap
i.postUpdate()
}
func (i *TrafficLimiterStrategyManager) DeleteTrafficLimiter(username string) {
i.mtx.Lock()
defer i.mtx.Unlock()
delete(i.strategiesMap, username)
i.postUpdate()
}
type TrafficLimiter struct {
manager CM.NodeManager
limiter CM.TrafficLimiter
new uint64
mtx sync.Mutex
}
func NewTrafficLimiter(manager CM.NodeManager, limiter CM.TrafficLimiter) *TrafficLimiter {
return &TrafficLimiter{manager: manager, limiter: limiter}
}
func (l *TrafficLimiter) Can(n uint64) error {
l.mtx.Lock()
defer l.mtx.Unlock()
if l.limiter.RawUsed == l.limiter.RawQuota {
return E.New("traffic limit exceeded")
}
if l.limiter.RawUsed+n > l.limiter.RawQuota {
l.new += l.limiter.RawQuota - l.limiter.RawUsed
l.limiter.RawUsed = l.limiter.RawQuota
return E.New("traffic limit exceeded")
}
return nil
}
func (l *TrafficLimiter) Add(n uint64) error {
l.mtx.Lock()
defer l.mtx.Unlock()
if l.limiter.RawUsed == l.limiter.RawQuota {
return E.New("traffic limit exceeded")
}
if l.limiter.RawUsed+n > l.limiter.RawQuota {
l.new += l.limiter.RawQuota - l.limiter.RawUsed
l.limiter.RawUsed = l.limiter.RawQuota
return E.New("traffic limit exceeded")
}
l.limiter.RawUsed += n
l.new += n
return nil
}
func (l *TrafficLimiter) UpdateRemainingTraffic() error {
l.mtx.Lock()
if l.new == 0 {
l.mtx.Unlock()
return nil
}
new := l.new
l.new = 0
l.mtx.Unlock()
newUsed, err := l.manager.AddTrafficUsage(l.limiter.ID, new)
l.mtx.Lock()
defer l.mtx.Unlock()
if err == nil {
l.limiter.RawUsed = newUsed
} else {
l.new += new
}
return nil
}

View File

@@ -28,6 +28,8 @@ type Service struct {
inboundManagers map[string]constant.InboundManager
bandwidthManager constant.BandwidthLimiterManager
connectionManager constant.ConnectionLimiterManager
trafficManager constant.TrafficLimiterManager
rateManager constant.RateLimiterManager
options option.NodeServiceOptions
mtx sync.Mutex
@@ -60,13 +62,16 @@ func (s *Service) Start(stage adapter.StartStage) error {
s.inboundManagers = map[string]constant.InboundManager{
"hysteria": inbound.NewHysteriaManager(),
"hysteria2": inbound.NewHysteria2Manager(),
"mtproxy": inbound.NewMTProxyManager(),
"trojan": inbound.NewTrojanManager(),
"tuic": inbound.NewTUICManager(),
"vless": inbound.NewVLESSManager(),
"vmess": inbound.NewVMessManager(),
}
s.connectionManager = limiter.NewConnectionLimiterManager(nodeManager, s.logger)
s.bandwidthManager = limiter.NewBandwidthLimiterManager()
s.connectionManager = limiter.NewConnectionLimiterManager(s.ctx, nodeManager, s.logger)
s.bandwidthManager = limiter.NewBandwidthLimiterManager(s.ctx, nodeManager, s.logger)
s.trafficManager = limiter.NewTrafficLimiterManager(s.ctx, nodeManager, s.logger)
s.rateManager = limiter.NewRateLimiterManager(s.ctx, nodeManager, s.logger)
for _, tag := range s.options.Inbounds {
inbound, ok := inboundManager.Get(tag)
if !ok {
@@ -94,13 +99,33 @@ func (s *Service) Start(stage adapter.StartStage) error {
for _, limiter := range s.options.BandwidthLimiters {
outbound, ok := outboundManager.Outbound(limiter)
if !ok {
return E.New("outbound ", limiter, " not found")
return E.New("outbound " + limiter + " not found")
}
err := s.bandwidthManager.AddBandwidthLimiterStrategyManager(outbound)
if err != nil {
return err
}
}
for _, limiter := range s.options.TrafficLimiters {
outbound, ok := outboundManager.Outbound(limiter)
if !ok {
return E.New("outbound ", limiter, " not found")
}
err := s.trafficManager.AddTrafficLimiterStrategyManager(outbound)
if err != nil {
return err
}
}
for _, limiter := range s.options.RateLimiters {
outbound, ok := outboundManager.Outbound(limiter)
if !ok {
return E.New("outbound ", limiter, " not found")
}
err := s.rateManager.AddRateLimiterStrategyManager(outbound)
if err != nil {
return err
}
}
return nodeManager.AddNode(s.options.UUID, s)
}
@@ -222,6 +247,70 @@ func (s *Service) DeleteBandwidthLimiter(limiter CM.BandwidthLimiter) {
manager.DeleteBandwidthLimiter(limiter.Username)
}
func (s *Service) UpdateTrafficLimiter(limiter CM.TrafficLimiter) {
s.mtx.Lock()
defer s.mtx.Unlock()
manager, ok := s.trafficManager.GetTrafficLimiterStrategyManager(limiter.Outbound)
if !ok {
return
}
manager.UpdateTrafficLimiter(limiter)
}
func (s *Service) UpdateTrafficLimiters(limiters []CM.TrafficLimiter) {
s.mtx.Lock()
defer s.mtx.Unlock()
for _, limiter := range limiters {
manager, ok := s.trafficManager.GetTrafficLimiterStrategyManager(limiter.Outbound)
if !ok {
continue
}
manager.UpdateTrafficLimiters(limiters)
}
}
func (s *Service) DeleteTrafficLimiter(limiter CM.TrafficLimiter) {
s.mtx.Lock()
defer s.mtx.Unlock()
manager, ok := s.trafficManager.GetTrafficLimiterStrategyManager(limiter.Outbound)
if !ok {
return
}
manager.DeleteTrafficLimiter(limiter.Username)
}
func (s *Service) UpdateRateLimiter(limiter CM.RateLimiter) {
s.mtx.Lock()
defer s.mtx.Unlock()
manager, ok := s.rateManager.GetRateLimiterStrategyManager(limiter.Outbound)
if !ok {
return
}
manager.UpdateRateLimiter(limiter)
}
func (s *Service) UpdateRateLimiters(limiters []CM.RateLimiter) {
s.mtx.Lock()
defer s.mtx.Unlock()
for _, limiter := range limiters {
manager, ok := s.rateManager.GetRateLimiterStrategyManager(limiter.Outbound)
if !ok {
continue
}
manager.UpdateRateLimiters(limiters)
}
}
func (s *Service) DeleteRateLimiter(limiter CM.RateLimiter) {
s.mtx.Lock()
defer s.mtx.Unlock()
manager, ok := s.rateManager.GetRateLimiterStrategyManager(limiter.Outbound)
if !ok {
return
}
manager.DeleteRateLimiter(limiter.Username)
}
func (s *Service) IsLocal() bool {
return true
}