Add OpenVPN, TrustTunnel, Sudoku, inbound managers. Fixes

This commit is contained in:
Shtorm
2026-06-04 01:47:50 +03:00
parent 9b3da79c32
commit 195a33379d
164 changed files with 16665 additions and 1332 deletions

View File

@@ -0,0 +1,89 @@
package inbound
import (
"sync"
"github.com/sagernet/sing-box/adapter"
"github.com/sagernet/sing-box/option"
"github.com/sagernet/sing-box/protocol/anytls"
CM "github.com/sagernet/sing-box/service/manager/constant"
"github.com/sagernet/sing-box/service/node/constant"
)
type AnyTLSManager struct {
inbounds map[string]*AnyTLSUserManager
mtx sync.Mutex
}
func NewAnyTLSManager() *AnyTLSManager {
return &AnyTLSManager{
inbounds: make(map[string]*AnyTLSUserManager),
}
}
func (m *AnyTLSManager) AddUserManager(inbound adapter.Inbound) error {
m.mtx.Lock()
defer m.mtx.Unlock()
m.inbounds[inbound.Tag()] = &AnyTLSUserManager{
inbound: inbound.(*anytls.Inbound),
usersMap: make(map[string]option.AnyTLSUser),
}
return nil
}
func (m *AnyTLSManager) GetUserManager(tag string) (constant.UserManager, bool) {
m.mtx.Lock()
defer m.mtx.Unlock()
inbound, ok := m.inbounds[tag]
return inbound, ok
}
func (m *AnyTLSManager) GetUserManagerTags() []string {
m.mtx.Lock()
defer m.mtx.Unlock()
tags := make([]string, 0, len(m.inbounds))
for tag := range m.inbounds {
tags = append(tags, tag)
}
return tags
}
type AnyTLSUserManager struct {
inbound *anytls.Inbound
usersMap map[string]option.AnyTLSUser
mtx sync.Mutex
}
func (i *AnyTLSUserManager) postUpdate() {
users := make([]option.AnyTLSUser, 0, len(i.usersMap))
for _, user := range i.usersMap {
users = append(users, user)
}
i.inbound.UpdateUsers(users)
}
func (i *AnyTLSUserManager) UpdateUser(user CM.User) {
i.mtx.Lock()
defer i.mtx.Unlock()
i.usersMap[user.Username] = option.AnyTLSUser{Name: user.Username, Password: user.Password}
i.postUpdate()
}
func (i *AnyTLSUserManager) UpdateUsers(users []CM.User) {
i.mtx.Lock()
defer i.mtx.Unlock()
clear(i.usersMap)
for _, user := range users {
i.usersMap[user.Username] = option.AnyTLSUser{Name: user.Username, Password: user.Password}
}
i.postUpdate()
}
func (i *AnyTLSUserManager) DeleteUser(username string) {
i.mtx.Lock()
defer i.mtx.Unlock()
delete(i.usersMap, username)
i.postUpdate()
}

View File

@@ -0,0 +1,89 @@
package inbound
import (
"sync"
"github.com/sagernet/sing-box/adapter"
"github.com/sagernet/sing-box/protocol/http"
CM "github.com/sagernet/sing-box/service/manager/constant"
"github.com/sagernet/sing-box/service/node/constant"
"github.com/sagernet/sing/common/auth"
)
type HTTPManager struct {
inbounds map[string]*HTTPUserManager
mtx sync.Mutex
}
func NewHTTPManager() *HTTPManager {
return &HTTPManager{
inbounds: make(map[string]*HTTPUserManager),
}
}
func (m *HTTPManager) AddUserManager(inbound adapter.Inbound) error {
m.mtx.Lock()
defer m.mtx.Unlock()
m.inbounds[inbound.Tag()] = &HTTPUserManager{
inbound: inbound.(*http.Inbound),
usersMap: make(map[string]auth.User),
}
return nil
}
func (m *HTTPManager) GetUserManager(tag string) (constant.UserManager, bool) {
m.mtx.Lock()
defer m.mtx.Unlock()
inbound, ok := m.inbounds[tag]
return inbound, ok
}
func (m *HTTPManager) GetUserManagerTags() []string {
m.mtx.Lock()
defer m.mtx.Unlock()
tags := make([]string, 0, len(m.inbounds))
for tag := range m.inbounds {
tags = append(tags, tag)
}
return tags
}
type HTTPUserManager struct {
inbound *http.Inbound
usersMap map[string]auth.User
mtx sync.Mutex
}
func (i *HTTPUserManager) postUpdate() {
users := make([]auth.User, 0, len(i.usersMap))
for _, user := range i.usersMap {
users = append(users, user)
}
i.inbound.UpdateUsers(users)
}
func (i *HTTPUserManager) UpdateUser(user CM.User) {
i.mtx.Lock()
defer i.mtx.Unlock()
i.usersMap[user.Username] = auth.User{Username: user.Username, Password: user.Password}
i.postUpdate()
}
func (i *HTTPUserManager) UpdateUsers(users []CM.User) {
i.mtx.Lock()
defer i.mtx.Unlock()
clear(i.usersMap)
for _, user := range users {
i.usersMap[user.Username] = auth.User{Username: user.Username, Password: user.Password}
}
i.postUpdate()
}
func (i *HTTPUserManager) DeleteUser(username string) {
i.mtx.Lock()
defer i.mtx.Unlock()
delete(i.usersMap, username)
i.postUpdate()
}

View File

@@ -11,8 +11,9 @@ import (
)
type HysteriaManager struct {
access sync.Mutex
inbounds map[string]*HysteriaUserManager
mtx sync.Mutex
}
func NewHysteriaManager() *HysteriaManager {
@@ -22,8 +23,8 @@ func NewHysteriaManager() *HysteriaManager {
}
func (m *HysteriaManager) AddUserManager(inbound adapter.Inbound) error {
m.access.Lock()
defer m.access.Unlock()
m.mtx.Lock()
defer m.mtx.Unlock()
m.inbounds[inbound.Tag()] = &HysteriaUserManager{
inbound: inbound.(*hysteria.Inbound),
usersMap: make(map[string]option.HysteriaUser),
@@ -32,15 +33,15 @@ func (m *HysteriaManager) AddUserManager(inbound adapter.Inbound) error {
}
func (m *HysteriaManager) GetUserManager(tag string) (constant.UserManager, bool) {
m.access.Lock()
defer m.access.Unlock()
m.mtx.Lock()
defer m.mtx.Unlock()
inbound, ok := m.inbounds[tag]
return inbound, ok
}
func (m *HysteriaManager) GetUserManagerTags() []string {
m.access.Lock()
defer m.access.Unlock()
m.mtx.Lock()
defer m.mtx.Unlock()
tags := make([]string, 0, len(m.inbounds))
for tag := range m.inbounds {
tags = append(tags, tag)

View File

@@ -11,8 +11,9 @@ import (
)
type Hysteria2Manager struct {
access sync.Mutex
inbounds map[string]*Hysteria2UserManager
mtx sync.Mutex
}
func NewHysteria2Manager() *Hysteria2Manager {
@@ -22,8 +23,8 @@ func NewHysteria2Manager() *Hysteria2Manager {
}
func (m *Hysteria2Manager) AddUserManager(inbound adapter.Inbound) error {
m.access.Lock()
defer m.access.Unlock()
m.mtx.Lock()
defer m.mtx.Unlock()
m.inbounds[inbound.Tag()] = &Hysteria2UserManager{
inbound: inbound.(*hysteria2.Inbound),
usersMap: make(map[string]option.Hysteria2User),
@@ -32,15 +33,15 @@ func (m *Hysteria2Manager) AddUserManager(inbound adapter.Inbound) error {
}
func (m *Hysteria2Manager) GetUserManager(tag string) (constant.UserManager, bool) {
m.access.Lock()
defer m.access.Unlock()
m.mtx.Lock()
defer m.mtx.Unlock()
inbound, ok := m.inbounds[tag]
return inbound, ok
}
func (m *Hysteria2Manager) GetUserManagerTags() []string {
m.access.Lock()
defer m.access.Unlock()
m.mtx.Lock()
defer m.mtx.Unlock()
tags := make([]string, 0, len(m.inbounds))
for tag := range m.inbounds {
tags = append(tags, tag)

View File

@@ -0,0 +1,89 @@
package inbound
import (
"sync"
"github.com/sagernet/sing-box/adapter"
"github.com/sagernet/sing-box/protocol/mixed"
CM "github.com/sagernet/sing-box/service/manager/constant"
"github.com/sagernet/sing-box/service/node/constant"
"github.com/sagernet/sing/common/auth"
)
type MixedManager struct {
inbounds map[string]*MixedUserManager
mtx sync.Mutex
}
func NewMixedManager() *MixedManager {
return &MixedManager{
inbounds: make(map[string]*MixedUserManager),
}
}
func (m *MixedManager) AddUserManager(inbound adapter.Inbound) error {
m.mtx.Lock()
defer m.mtx.Unlock()
m.inbounds[inbound.Tag()] = &MixedUserManager{
inbound: inbound.(*mixed.Inbound),
usersMap: make(map[string]auth.User),
}
return nil
}
func (m *MixedManager) GetUserManager(tag string) (constant.UserManager, bool) {
m.mtx.Lock()
defer m.mtx.Unlock()
inbound, ok := m.inbounds[tag]
return inbound, ok
}
func (m *MixedManager) GetUserManagerTags() []string {
m.mtx.Lock()
defer m.mtx.Unlock()
tags := make([]string, 0, len(m.inbounds))
for tag := range m.inbounds {
tags = append(tags, tag)
}
return tags
}
type MixedUserManager struct {
inbound *mixed.Inbound
usersMap map[string]auth.User
mtx sync.Mutex
}
func (i *MixedUserManager) postUpdate() {
users := make([]auth.User, 0, len(i.usersMap))
for _, user := range i.usersMap {
users = append(users, user)
}
i.inbound.UpdateUsers(users)
}
func (i *MixedUserManager) UpdateUser(user CM.User) {
i.mtx.Lock()
defer i.mtx.Unlock()
i.usersMap[user.Username] = auth.User{Username: user.Username, Password: user.Password}
i.postUpdate()
}
func (i *MixedUserManager) UpdateUsers(users []CM.User) {
i.mtx.Lock()
defer i.mtx.Unlock()
clear(i.usersMap)
for _, user := range users {
i.usersMap[user.Username] = auth.User{Username: user.Username, Password: user.Password}
}
i.postUpdate()
}
func (i *MixedUserManager) DeleteUser(username string) {
i.mtx.Lock()
defer i.mtx.Unlock()
delete(i.usersMap, username)
i.postUpdate()
}

View File

@@ -11,8 +11,9 @@ import (
)
type MTProxyManager struct {
access sync.Mutex
inbounds map[string]*MTProxyUserManager
mtx sync.Mutex
}
func NewMTProxyManager() *MTProxyManager {
@@ -22,8 +23,8 @@ func NewMTProxyManager() *MTProxyManager {
}
func (m *MTProxyManager) AddUserManager(inbound adapter.Inbound) error {
m.access.Lock()
defer m.access.Unlock()
m.mtx.Lock()
defer m.mtx.Unlock()
m.inbounds[inbound.Tag()] = &MTProxyUserManager{
inbound: inbound.(*mtproxy.Inbound),
usersMap: make(map[string]option.MTProxyUser),
@@ -32,15 +33,15 @@ func (m *MTProxyManager) AddUserManager(inbound adapter.Inbound) error {
}
func (m *MTProxyManager) GetUserManager(tag string) (constant.UserManager, bool) {
m.access.Lock()
defer m.access.Unlock()
m.mtx.Lock()
defer m.mtx.Unlock()
inbound, ok := m.inbounds[tag]
return inbound, ok
}
func (m *MTProxyManager) GetUserManagerTags() []string {
m.access.Lock()
defer m.access.Unlock()
m.mtx.Lock()
defer m.mtx.Unlock()
tags := make([]string, 0, len(m.inbounds))
for tag := range m.inbounds {
tags = append(tags, tag)

View File

@@ -0,0 +1,89 @@
package inbound
import (
"sync"
"github.com/sagernet/sing-box/adapter"
"github.com/sagernet/sing-box/protocol/naive"
CM "github.com/sagernet/sing-box/service/manager/constant"
"github.com/sagernet/sing-box/service/node/constant"
"github.com/sagernet/sing/common/auth"
)
type NaiveManager struct {
inbounds map[string]*NaiveUserManager
mtx sync.Mutex
}
func NewNaiveManager() *NaiveManager {
return &NaiveManager{
inbounds: make(map[string]*NaiveUserManager),
}
}
func (m *NaiveManager) AddUserManager(inbound adapter.Inbound) error {
m.mtx.Lock()
defer m.mtx.Unlock()
m.inbounds[inbound.Tag()] = &NaiveUserManager{
inbound: inbound.(*naive.Inbound),
usersMap: make(map[string]auth.User),
}
return nil
}
func (m *NaiveManager) GetUserManager(tag string) (constant.UserManager, bool) {
m.mtx.Lock()
defer m.mtx.Unlock()
inbound, ok := m.inbounds[tag]
return inbound, ok
}
func (m *NaiveManager) GetUserManagerTags() []string {
m.mtx.Lock()
defer m.mtx.Unlock()
tags := make([]string, 0, len(m.inbounds))
for tag := range m.inbounds {
tags = append(tags, tag)
}
return tags
}
type NaiveUserManager struct {
inbound *naive.Inbound
usersMap map[string]auth.User
mtx sync.Mutex
}
func (i *NaiveUserManager) postUpdate() {
users := make([]auth.User, 0, len(i.usersMap))
for _, user := range i.usersMap {
users = append(users, user)
}
i.inbound.UpdateUsers(users)
}
func (i *NaiveUserManager) UpdateUser(user CM.User) {
i.mtx.Lock()
defer i.mtx.Unlock()
i.usersMap[user.Username] = auth.User{Username: user.Username, Password: user.Password}
i.postUpdate()
}
func (i *NaiveUserManager) UpdateUsers(users []CM.User) {
i.mtx.Lock()
defer i.mtx.Unlock()
clear(i.usersMap)
for _, user := range users {
i.usersMap[user.Username] = auth.User{Username: user.Username, Password: user.Password}
}
i.postUpdate()
}
func (i *NaiveUserManager) DeleteUser(username string) {
i.mtx.Lock()
defer i.mtx.Unlock()
delete(i.usersMap, username)
i.postUpdate()
}

View File

@@ -0,0 +1,89 @@
package inbound
import (
"sync"
"github.com/sagernet/sing-box/adapter"
"github.com/sagernet/sing-box/protocol/socks"
CM "github.com/sagernet/sing-box/service/manager/constant"
"github.com/sagernet/sing-box/service/node/constant"
"github.com/sagernet/sing/common/auth"
)
type SocksManager struct {
inbounds map[string]*SocksUserManager
mtx sync.Mutex
}
func NewSocksManager() *SocksManager {
return &SocksManager{
inbounds: make(map[string]*SocksUserManager),
}
}
func (m *SocksManager) AddUserManager(inbound adapter.Inbound) error {
m.mtx.Lock()
defer m.mtx.Unlock()
m.inbounds[inbound.Tag()] = &SocksUserManager{
inbound: inbound.(*socks.Inbound),
usersMap: make(map[string]auth.User),
}
return nil
}
func (m *SocksManager) GetUserManager(tag string) (constant.UserManager, bool) {
m.mtx.Lock()
defer m.mtx.Unlock()
inbound, ok := m.inbounds[tag]
return inbound, ok
}
func (m *SocksManager) GetUserManagerTags() []string {
m.mtx.Lock()
defer m.mtx.Unlock()
tags := make([]string, 0, len(m.inbounds))
for tag := range m.inbounds {
tags = append(tags, tag)
}
return tags
}
type SocksUserManager struct {
inbound *socks.Inbound
usersMap map[string]auth.User
mtx sync.Mutex
}
func (i *SocksUserManager) postUpdate() {
users := make([]auth.User, 0, len(i.usersMap))
for _, user := range i.usersMap {
users = append(users, user)
}
i.inbound.UpdateUsers(users)
}
func (i *SocksUserManager) UpdateUser(user CM.User) {
i.mtx.Lock()
defer i.mtx.Unlock()
i.usersMap[user.Username] = auth.User{Username: user.Username, Password: user.Password}
i.postUpdate()
}
func (i *SocksUserManager) UpdateUsers(users []CM.User) {
i.mtx.Lock()
defer i.mtx.Unlock()
clear(i.usersMap)
for _, user := range users {
i.usersMap[user.Username] = auth.User{Username: user.Username, Password: user.Password}
}
i.postUpdate()
}
func (i *SocksUserManager) DeleteUser(username string) {
i.mtx.Lock()
defer i.mtx.Unlock()
delete(i.usersMap, username)
i.postUpdate()
}

View File

@@ -11,8 +11,9 @@ import (
)
type TrojanManager struct {
access sync.Mutex
inbounds map[string]*TrojanUserManager
mtx sync.Mutex
}
func NewTrojanManager() *TrojanManager {
@@ -22,8 +23,8 @@ func NewTrojanManager() *TrojanManager {
}
func (m *TrojanManager) AddUserManager(inbound adapter.Inbound) error {
m.access.Lock()
defer m.access.Unlock()
m.mtx.Lock()
defer m.mtx.Unlock()
m.inbounds[inbound.Tag()] = &TrojanUserManager{
inbound: inbound.(*trojan.Inbound),
usersMap: make(map[string]option.TrojanUser),
@@ -32,15 +33,15 @@ func (m *TrojanManager) AddUserManager(inbound adapter.Inbound) error {
}
func (m *TrojanManager) GetUserManager(tag string) (constant.UserManager, bool) {
m.access.Lock()
defer m.access.Unlock()
m.mtx.Lock()
defer m.mtx.Unlock()
inbound, ok := m.inbounds[tag]
return inbound, ok
}
func (m *TrojanManager) GetUserManagerTags() []string {
m.access.Lock()
defer m.access.Unlock()
m.mtx.Lock()
defer m.mtx.Unlock()
tags := make([]string, 0, len(m.inbounds))
for tag := range m.inbounds {
tags = append(tags, tag)

View File

@@ -0,0 +1,89 @@
package inbound
import (
"sync"
"github.com/sagernet/sing-box/adapter"
"github.com/sagernet/sing-box/option"
"github.com/sagernet/sing-box/protocol/trusttunnel"
CM "github.com/sagernet/sing-box/service/manager/constant"
"github.com/sagernet/sing-box/service/node/constant"
)
type TrustTunnelManager struct {
inbounds map[string]*TrustTunnelUserManager
mtx sync.Mutex
}
func NewTrustTunnelManager() *TrustTunnelManager {
return &TrustTunnelManager{
inbounds: make(map[string]*TrustTunnelUserManager),
}
}
func (m *TrustTunnelManager) AddUserManager(inbound adapter.Inbound) error {
m.mtx.Lock()
defer m.mtx.Unlock()
m.inbounds[inbound.Tag()] = &TrustTunnelUserManager{
inbound: inbound.(*trusttunnel.Inbound),
usersMap: make(map[string]option.TrustTunnelUser),
}
return nil
}
func (m *TrustTunnelManager) GetUserManager(tag string) (constant.UserManager, bool) {
m.mtx.Lock()
defer m.mtx.Unlock()
inbound, ok := m.inbounds[tag]
return inbound, ok
}
func (m *TrustTunnelManager) GetUserManagerTags() []string {
m.mtx.Lock()
defer m.mtx.Unlock()
tags := make([]string, 0, len(m.inbounds))
for tag := range m.inbounds {
tags = append(tags, tag)
}
return tags
}
type TrustTunnelUserManager struct {
inbound *trusttunnel.Inbound
usersMap map[string]option.TrustTunnelUser
mtx sync.Mutex
}
func (i *TrustTunnelUserManager) postUpdate() {
users := make([]option.TrustTunnelUser, 0, len(i.usersMap))
for _, user := range i.usersMap {
users = append(users, user)
}
i.inbound.UpdateUsers(users)
}
func (i *TrustTunnelUserManager) UpdateUser(user CM.User) {
i.mtx.Lock()
defer i.mtx.Unlock()
i.usersMap[user.Username] = option.TrustTunnelUser{Name: user.Username, Password: user.Password}
i.postUpdate()
}
func (i *TrustTunnelUserManager) UpdateUsers(users []CM.User) {
i.mtx.Lock()
defer i.mtx.Unlock()
clear(i.usersMap)
for _, user := range users {
i.usersMap[user.Username] = option.TrustTunnelUser{Name: user.Username, Password: user.Password}
}
i.postUpdate()
}
func (i *TrustTunnelUserManager) DeleteUser(username string) {
i.mtx.Lock()
defer i.mtx.Unlock()
delete(i.usersMap, username)
i.postUpdate()
}

View File

@@ -11,8 +11,9 @@ import (
)
type TUICManager struct {
access sync.Mutex
inbounds map[string]*TUICUserManager
mtx sync.Mutex
}
func NewTUICManager() *TUICManager {
@@ -22,8 +23,8 @@ func NewTUICManager() *TUICManager {
}
func (m *TUICManager) AddUserManager(inbound adapter.Inbound) error {
m.access.Lock()
defer m.access.Unlock()
m.mtx.Lock()
defer m.mtx.Unlock()
m.inbounds[inbound.Tag()] = &TUICUserManager{
inbound: inbound.(*tuic.Inbound),
usersMap: make(map[string]option.TUICUser),
@@ -32,15 +33,15 @@ func (m *TUICManager) AddUserManager(inbound adapter.Inbound) error {
}
func (m *TUICManager) GetUserManager(tag string) (constant.UserManager, bool) {
m.access.Lock()
defer m.access.Unlock()
m.mtx.Lock()
defer m.mtx.Unlock()
inbound, ok := m.inbounds[tag]
return inbound, ok
}
func (m *TUICManager) GetUserManagerTags() []string {
m.access.Lock()
defer m.access.Unlock()
m.mtx.Lock()
defer m.mtx.Unlock()
tags := make([]string, 0, len(m.inbounds))
for tag := range m.inbounds {
tags = append(tags, tag)

View File

@@ -11,8 +11,9 @@ import (
)
type VLESSManager struct {
access sync.Mutex
inbounds map[string]*VLESSUserManager
mtx sync.Mutex
}
func NewVLESSManager() *VLESSManager {
@@ -22,8 +23,8 @@ func NewVLESSManager() *VLESSManager {
}
func (m *VLESSManager) AddUserManager(inbound adapter.Inbound) error {
m.access.Lock()
defer m.access.Unlock()
m.mtx.Lock()
defer m.mtx.Unlock()
m.inbounds[inbound.Tag()] = &VLESSUserManager{
inbound: inbound.(*vless.Inbound),
usersMap: make(map[string]option.VLESSUser),
@@ -32,15 +33,15 @@ func (m *VLESSManager) AddUserManager(inbound adapter.Inbound) error {
}
func (m *VLESSManager) GetUserManager(tag string) (constant.UserManager, bool) {
m.access.Lock()
defer m.access.Unlock()
m.mtx.Lock()
defer m.mtx.Unlock()
inbound, ok := m.inbounds[tag]
return inbound, ok
}
func (m *VLESSManager) GetUserManagerTags() []string {
m.access.Lock()
defer m.access.Unlock()
m.mtx.Lock()
defer m.mtx.Unlock()
tags := make([]string, 0, len(m.inbounds))
for tag := range m.inbounds {
tags = append(tags, tag)

View File

@@ -12,7 +12,8 @@ import (
type VMessManager struct {
inbounds map[string]*VMessUserManager
mtx sync.Mutex
mtx sync.Mutex
}
func NewVMessManager() *VMessManager {

View File

@@ -2,6 +2,7 @@ package limiter
import (
"context"
"slices"
"sync"
"github.com/sagernet/sing-box/adapter"
@@ -50,6 +51,7 @@ func (m *BandwidthLimiterManager) AddBandwidthLimiterStrategyManager(outbound ad
manager: m,
strategy: strategy,
strategiesMap: make(map[string]bandwidth.BandwidthStrategy),
limitersMap: make(map[string]CM.BandwidthLimiter),
}
return nil
}
@@ -75,6 +77,7 @@ type BandwidthLimiterStrategyManager struct {
manager *BandwidthLimiterManager
strategy ManagedBandwidthStrategy
strategiesMap map[string]bandwidth.BandwidthStrategy
limitersMap map[string]CM.BandwidthLimiter
mtx sync.Mutex
}
@@ -86,12 +89,25 @@ func (i *BandwidthLimiterStrategyManager) postUpdate() {
func (i *BandwidthLimiterStrategyManager) UpdateBandwidthLimiter(limiter CM.BandwidthLimiter) {
i.mtx.Lock()
defer i.mtx.Unlock()
if existing, ok := i.strategiesMap[limiter.Username]; ok {
oldLimiter := i.limitersMap[limiter.Username]
if isSameStrategy(oldLimiter, limiter) {
if oldLimiter.RawSpeed != limiter.RawSpeed {
if s, ok := existing.(bandwidth.SpeedUpdater); ok {
s.SetSpeed(limiter.RawSpeed)
}
}
i.limitersMap[limiter.Username] = limiter
return
}
}
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
i.limitersMap[limiter.Username] = limiter
i.postUpdate()
}
@@ -118,3 +134,10 @@ func (i *BandwidthLimiterStrategyManager) DeleteBandwidthLimiter(username string
delete(i.strategiesMap, username)
i.postUpdate()
}
func isSameStrategy(a, b CM.BandwidthLimiter) bool {
return a.Strategy == b.Strategy &&
a.Mode == b.Mode &&
a.ConnectionType == b.ConnectionType &&
slices.Equal(a.FlowKeys, b.FlowKeys)
}

View File

@@ -6,6 +6,7 @@ import (
"time"
"github.com/sagernet/sing-box/adapter"
"github.com/sagernet/sing-box/common/onclose"
"github.com/sagernet/sing-box/log"
"github.com/sagernet/sing-box/protocol/limiter/connection"
CM "github.com/sagernet/sing-box/service/manager/constant"
@@ -45,7 +46,7 @@ func (m *ConnectionLimiterManager) AddConnectionLimiterStrategyManager(outbound
}
strategy, ok := limiter.GetStrategy().(ManagedConnectionStrategy)
if !ok {
return E.New("strategy ", strategy, " is not manager")
return E.New("strategy for outbound ", outbound.Tag(), " is not manager")
}
m.managers[outbound.Tag()] = &ConnectionLimiterStrategyManager{
manager: m,
@@ -152,7 +153,7 @@ type ManagerLock struct {
func (i *ConnectionLimiterStrategyManager) newManagerLock(limiterId int) connection.LockIDGetter {
conns := make(map[string]*ManagerLock)
mtx := sync.Mutex{}
return func(id string) (connection.CloseHandlerFunc, context.Context, error) {
return func(id string) (onclose.CloseHandlerFunc, context.Context, error) {
mtx.Lock()
defer mtx.Unlock()
conn, ok := conns[id]
@@ -171,6 +172,7 @@ func (i *ConnectionLimiterStrategyManager) newManagerLock(limiterId int) connect
case <-time.After(time.Second * 5):
err := nodeManager.RefreshLock(limiterId, id, handleId)
if err != nil {
i.manager.logger.ErrorContext(ctx, "failed to refresh lock: ", err)
cancel()
return
}
@@ -185,18 +187,17 @@ func (i *ConnectionLimiterStrategyManager) newManagerLock(limiterId int) connect
conns[id] = conn
}
conn.handles++
var once sync.Once
return func() {
once.Do(func() {
mtx.Lock()
defer mtx.Unlock()
conn.handles--
if conn.handles == 0 {
conn.cancel()
i.manager.nodeManager.ReleaseLock(limiterId, id, conn.handleId)
delete(conns, id)
mtx.Lock()
defer mtx.Unlock()
conn.handles--
if conn.handles == 0 {
conn.cancel()
if err := i.manager.nodeManager.ReleaseLock(limiterId, id, conn.handleId); err != nil {
i.manager.logger.ErrorContext(i.manager.ctx, "failed to release lock: ", err)
}
})
delete(conns, id)
}
}, conn.ctx, nil
}
}

View File

@@ -212,5 +212,5 @@ func (l *TrafficLimiter) UpdateRemainingTraffic() error {
} else {
l.new += new
}
return nil
return err
}

View File

@@ -24,6 +24,7 @@ func RegisterService(registry *boxService.Registry) {
type Service struct {
boxService.Adapter
ctx context.Context
cancel context.CancelFunc
logger log.ContextLogger
inboundManagers map[string]constant.InboundManager
bandwidthManager constant.BandwidthLimiterManager
@@ -32,13 +33,17 @@ type Service struct {
rateManager constant.RateLimiterManager
options option.NodeServiceOptions
nodeManager CM.NodeManager
mtx sync.Mutex
}
func NewService(ctx context.Context, logger log.ContextLogger, tag string, options option.NodeServiceOptions) (adapter.Service, error) {
ctx, cancel := context.WithCancel(ctx)
return &Service{
Adapter: boxService.NewAdapter(C.TypeManager, tag),
Adapter: boxService.NewAdapter(C.TypeNode, tag),
ctx: ctx,
cancel: cancel,
logger: logger,
options: options,
}, nil
@@ -57,16 +62,23 @@ func (s *Service) Start(stage adapter.StartStage) error {
if !ok {
return E.New("invalid ", s.options.Manager, " manager")
}
s.nodeManager = nodeManager
inboundManager := service.FromContext[adapter.InboundManager](s.ctx)
outboundManager := service.FromContext[adapter.OutboundManager](s.ctx)
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(),
"anytls": inbound.NewAnyTLSManager(),
"http": inbound.NewHTTPManager(),
"hysteria": inbound.NewHysteriaManager(),
"hysteria2": inbound.NewHysteria2Manager(),
"mixed": inbound.NewMixedManager(),
"mtproxy": inbound.NewMTProxyManager(),
"naive": inbound.NewNaiveManager(),
"socks": inbound.NewSocksManager(),
"trojan": inbound.NewTrojanManager(),
"trusttunnel": inbound.NewTrustTunnelManager(),
"tuic": inbound.NewTUICManager(),
"vless": inbound.NewVLESSManager(),
"vmess": inbound.NewVMessManager(),
}
s.connectionManager = limiter.NewConnectionLimiterManager(s.ctx, nodeManager, s.logger)
s.bandwidthManager = limiter.NewBandwidthLimiterManager(s.ctx, nodeManager, s.logger)
@@ -320,5 +332,6 @@ func (s *Service) IsOnline() bool {
}
func (s *Service) Close() error {
s.cancel()
return nil
}