mirror of
https://github.com/shtorm-7/sing-box-extended.git
synced 2026-05-14 00:51:12 +03:00
236 lines
6.2 KiB
Go
236 lines
6.2 KiB
Go
package node
|
|
|
|
import (
|
|
"context"
|
|
"sync"
|
|
|
|
"github.com/sagernet/sing-box/adapter"
|
|
boxService "github.com/sagernet/sing-box/adapter/service"
|
|
C "github.com/sagernet/sing-box/constant"
|
|
"github.com/sagernet/sing-box/log"
|
|
"github.com/sagernet/sing-box/option"
|
|
CM "github.com/sagernet/sing-box/service/manager/constant"
|
|
"github.com/sagernet/sing-box/service/node/constant"
|
|
"github.com/sagernet/sing-box/service/node/inbound"
|
|
"github.com/sagernet/sing-box/service/node/limiter"
|
|
E "github.com/sagernet/sing/common/exceptions"
|
|
"github.com/sagernet/sing/service"
|
|
)
|
|
|
|
func RegisterService(registry *boxService.Registry) {
|
|
boxService.Register[option.NodeServiceOptions](registry, C.TypeNode, NewService)
|
|
}
|
|
|
|
type Service struct {
|
|
boxService.Adapter
|
|
ctx context.Context
|
|
logger log.ContextLogger
|
|
inboundManagers map[string]constant.InboundManager
|
|
bandwidthManager constant.BandwidthLimiterManager
|
|
connectionManager constant.ConnectionLimiterManager
|
|
options option.NodeServiceOptions
|
|
|
|
mtx sync.Mutex
|
|
}
|
|
|
|
func NewService(ctx context.Context, logger log.ContextLogger, tag string, options option.NodeServiceOptions) (adapter.Service, error) {
|
|
return &Service{
|
|
Adapter: boxService.NewAdapter(C.TypeManager, tag),
|
|
ctx: ctx,
|
|
logger: logger,
|
|
options: options,
|
|
}, nil
|
|
}
|
|
|
|
func (s *Service) Start(stage adapter.StartStage) error {
|
|
if stage != adapter.StartStateStart {
|
|
return nil
|
|
}
|
|
boxManager := service.FromContext[adapter.ServiceManager](s.ctx)
|
|
serviceManager, ok := boxManager.Get(s.options.Manager)
|
|
if !ok {
|
|
return E.New("manager ", s.options.Manager, " not found")
|
|
}
|
|
nodeManager, ok := serviceManager.(CM.NodeManager)
|
|
if !ok {
|
|
return E.New("invalid ", s.options.Manager, " manager")
|
|
}
|
|
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(),
|
|
"trojan": inbound.NewTrojanManager(),
|
|
"tuic": inbound.NewTUICManager(),
|
|
"vless": inbound.NewVLESSManager(),
|
|
"vmess": inbound.NewVMessManager(),
|
|
}
|
|
s.connectionManager = limiter.NewConnectionLimiterManager(nodeManager, s.logger)
|
|
s.bandwidthManager = limiter.NewBandwidthLimiterManager()
|
|
for _, tag := range s.options.Inbounds {
|
|
inbound, ok := inboundManager.Get(tag)
|
|
if !ok {
|
|
return E.New("inbound ", tag, " not found")
|
|
}
|
|
inboundManager, ok := s.inboundManagers[inbound.Type()]
|
|
if !ok {
|
|
return E.New("inbound manager for ", tag, " not found")
|
|
}
|
|
err := inboundManager.AddUserManager(inbound)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
}
|
|
for _, limiter := range s.options.ConnectionLimiters {
|
|
outbound, ok := outboundManager.Outbound(limiter)
|
|
if !ok {
|
|
return E.New("outbound ", limiter, " not found")
|
|
}
|
|
err := s.connectionManager.AddConnectionLimiterStrategyManager(outbound)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
}
|
|
for _, limiter := range s.options.BandwidthLimiters {
|
|
outbound, ok := outboundManager.Outbound(limiter)
|
|
if !ok {
|
|
return E.New("outbound ", limiter, " not found")
|
|
}
|
|
err := s.bandwidthManager.AddBandwidthLimiterStrategyManager(outbound)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
}
|
|
return nodeManager.AddNode(s.options.UUID, s)
|
|
}
|
|
|
|
func (s *Service) UpdateUser(user CM.User) {
|
|
s.mtx.Lock()
|
|
defer s.mtx.Unlock()
|
|
manager, ok := s.inboundManagers[user.Type]
|
|
if !ok {
|
|
return
|
|
}
|
|
userManager, ok := manager.GetUserManager(user.Inbound)
|
|
if !ok {
|
|
return
|
|
}
|
|
userManager.UpdateUser(user)
|
|
}
|
|
|
|
func (s *Service) UpdateUsers(users []CM.User) {
|
|
s.mtx.Lock()
|
|
defer s.mtx.Unlock()
|
|
typedUsers := make(map[string][]CM.User)
|
|
for _, user := range users {
|
|
u, ok := typedUsers[user.Type]
|
|
if !ok {
|
|
typedUsers[user.Type] = make([]CM.User, 0)
|
|
}
|
|
typedUsers[user.Type] = append(u, user)
|
|
}
|
|
for type_, users := range typedUsers {
|
|
manager, ok := s.inboundManagers[type_]
|
|
if !ok {
|
|
continue
|
|
}
|
|
for _, user := range users {
|
|
userManager, ok := manager.GetUserManager(user.Inbound)
|
|
if !ok {
|
|
continue
|
|
}
|
|
userManager.UpdateUsers(users)
|
|
}
|
|
}
|
|
}
|
|
|
|
func (s *Service) DeleteUser(user CM.User) {
|
|
s.mtx.Lock()
|
|
defer s.mtx.Unlock()
|
|
manager, ok := s.inboundManagers[user.Type]
|
|
if !ok {
|
|
return
|
|
}
|
|
userManager, ok := manager.GetUserManager(user.Inbound)
|
|
if !ok {
|
|
return
|
|
}
|
|
userManager.DeleteUser(user.Username)
|
|
}
|
|
|
|
func (s *Service) UpdateConnectionLimiter(limiter CM.ConnectionLimiter) {
|
|
s.mtx.Lock()
|
|
defer s.mtx.Unlock()
|
|
manager, ok := s.connectionManager.GetConnectionLimiterStrategyManager(limiter.Outbound)
|
|
if !ok {
|
|
return
|
|
}
|
|
manager.UpdateConnectionLimiter(limiter)
|
|
}
|
|
|
|
func (s *Service) UpdateConnectionLimiters(limiters []CM.ConnectionLimiter) {
|
|
s.mtx.Lock()
|
|
defer s.mtx.Unlock()
|
|
for _, limiter := range limiters {
|
|
manager, ok := s.connectionManager.GetConnectionLimiterStrategyManager(limiter.Outbound)
|
|
if !ok {
|
|
continue
|
|
}
|
|
manager.UpdateConnectionLimiters(limiters)
|
|
}
|
|
}
|
|
|
|
func (s *Service) DeleteConnectionLimiter(limiter CM.ConnectionLimiter) {
|
|
s.mtx.Lock()
|
|
defer s.mtx.Unlock()
|
|
manager, ok := s.connectionManager.GetConnectionLimiterStrategyManager(limiter.Outbound)
|
|
if !ok {
|
|
return
|
|
}
|
|
manager.DeleteConnectionLimiter(limiter.Username)
|
|
}
|
|
|
|
func (s *Service) UpdateBandwidthLimiter(limiter CM.BandwidthLimiter) {
|
|
s.mtx.Lock()
|
|
defer s.mtx.Unlock()
|
|
manager, ok := s.bandwidthManager.GetBandwidthLimiterStrategyManager(limiter.Outbound)
|
|
if !ok {
|
|
return
|
|
}
|
|
manager.UpdateBandwidthLimiter(limiter)
|
|
}
|
|
|
|
func (s *Service) UpdateBandwidthLimiters(limiters []CM.BandwidthLimiter) {
|
|
s.mtx.Lock()
|
|
defer s.mtx.Unlock()
|
|
for _, limiter := range limiters {
|
|
manager, ok := s.bandwidthManager.GetBandwidthLimiterStrategyManager(limiter.Outbound)
|
|
if !ok {
|
|
continue
|
|
}
|
|
manager.UpdateBandwidthLimiters(limiters)
|
|
}
|
|
}
|
|
|
|
func (s *Service) DeleteBandwidthLimiter(limiter CM.BandwidthLimiter) {
|
|
s.mtx.Lock()
|
|
defer s.mtx.Unlock()
|
|
manager, ok := s.bandwidthManager.GetBandwidthLimiterStrategyManager(limiter.Outbound)
|
|
if !ok {
|
|
return
|
|
}
|
|
manager.DeleteBandwidthLimiter(limiter.Username)
|
|
}
|
|
|
|
func (s *Service) IsLocal() bool {
|
|
return true
|
|
}
|
|
|
|
func (s *Service) IsOnline() bool {
|
|
return true
|
|
}
|
|
|
|
func (s *Service) Close() error {
|
|
return nil
|
|
}
|