2023-06-09 09:20:41 -04:00
|
|
|
package core
|
|
|
|
|
|
|
|
import (
|
|
|
|
"errors"
|
2023-09-02 05:30:28 -04:00
|
|
|
"fmt"
|
2023-09-16 08:03:02 -04:00
|
|
|
"strings"
|
2023-06-09 09:20:41 -04:00
|
|
|
"sync"
|
|
|
|
|
2025-01-10 02:33:05 -05:00
|
|
|
"github.com/hashicorp/go-multierror"
|
|
|
|
|
2023-07-29 07:27:15 -04:00
|
|
|
"github.com/InazumaV/V2bX/api/panel"
|
|
|
|
"github.com/InazumaV/V2bX/conf"
|
2023-06-09 09:20:41 -04:00
|
|
|
)
|
|
|
|
|
2023-06-18 21:56:18 -04:00
|
|
|
type Selector struct {
|
2023-09-16 08:03:02 -04:00
|
|
|
cores map[string]Core
|
2023-06-09 09:20:41 -04:00
|
|
|
nodes sync.Map
|
|
|
|
}
|
|
|
|
|
2023-09-16 08:03:02 -04:00
|
|
|
func NewSelector(c []conf.CoreConfig) (Core, error) {
|
|
|
|
cs := make(map[string]Core, len(c))
|
|
|
|
for _, t := range c {
|
|
|
|
f, ok := cores[strings.ToLower(t.Type)]
|
|
|
|
if !ok {
|
|
|
|
return nil, errors.New("unknown core type: " + t.Type)
|
|
|
|
}
|
|
|
|
core1, err := f(&t)
|
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
if t.Name == "" {
|
|
|
|
cs[t.Type] = core1
|
|
|
|
} else {
|
|
|
|
cs[t.Name] = core1
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return &Selector{
|
|
|
|
cores: cs,
|
|
|
|
}, nil
|
|
|
|
}
|
|
|
|
|
2023-06-18 21:56:18 -04:00
|
|
|
func (s *Selector) Start() error {
|
2023-06-09 09:20:41 -04:00
|
|
|
for i := range s.cores {
|
|
|
|
err := s.cores[i].Start()
|
2023-09-11 11:55:11 -04:00
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
2023-06-09 09:20:41 -04:00
|
|
|
}
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
2023-06-18 21:56:18 -04:00
|
|
|
func (s *Selector) Close() error {
|
2023-06-09 09:20:41 -04:00
|
|
|
var errs error
|
|
|
|
for i := range s.cores {
|
2023-10-19 01:44:47 -04:00
|
|
|
err := s.cores[i].Close()
|
|
|
|
if err != nil {
|
|
|
|
errs = multierror.Append(errs, err)
|
|
|
|
}
|
2023-06-09 09:20:41 -04:00
|
|
|
}
|
|
|
|
return errs
|
|
|
|
}
|
|
|
|
|
|
|
|
func isSupported(protocol string, protocols []string) bool {
|
|
|
|
for i := range protocols {
|
|
|
|
if protocol == protocols[i] {
|
|
|
|
return true
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return false
|
|
|
|
}
|
|
|
|
|
2023-08-20 03:13:52 -04:00
|
|
|
func (s *Selector) AddNode(tag string, info *panel.NodeInfo, option *conf.Options) error {
|
2023-09-16 08:03:02 -04:00
|
|
|
var core Core
|
|
|
|
if len(option.CoreName) > 0 {
|
|
|
|
// use name to select core
|
|
|
|
if c, ok := s.cores[option.CoreName]; ok {
|
|
|
|
core = c
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
// use type to select core
|
|
|
|
for _, c := range s.cores {
|
|
|
|
if len(option.Core) == 0 {
|
|
|
|
if !isSupported(info.Type, c.Protocols()) {
|
|
|
|
continue
|
|
|
|
}
|
|
|
|
} else if option.Core != c.Type() {
|
2023-09-02 15:23:30 -04:00
|
|
|
continue
|
|
|
|
}
|
2023-09-16 08:03:02 -04:00
|
|
|
core = c
|
2023-06-09 09:20:41 -04:00
|
|
|
}
|
2023-09-16 08:03:02 -04:00
|
|
|
}
|
|
|
|
if core == nil {
|
|
|
|
return errors.New("the node type is not support")
|
|
|
|
}
|
|
|
|
if len(option.Core) == 0 {
|
|
|
|
option.Core = core.Type()
|
|
|
|
err := option.UnmarshalJSON(option.RawOptions)
|
2023-06-09 09:20:41 -04:00
|
|
|
if err != nil {
|
2023-09-16 08:03:02 -04:00
|
|
|
return fmt.Errorf("unmarshal option error: %s", err)
|
2023-06-09 09:20:41 -04:00
|
|
|
}
|
2023-09-16 08:03:02 -04:00
|
|
|
option.RawOptions = nil
|
2023-06-09 09:20:41 -04:00
|
|
|
}
|
2023-09-16 08:03:02 -04:00
|
|
|
err := core.AddNode(tag, info, option)
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
s.nodes.Store(tag, core)
|
|
|
|
return nil
|
2023-06-09 09:20:41 -04:00
|
|
|
}
|
|
|
|
|
2023-06-18 21:56:18 -04:00
|
|
|
func (s *Selector) DelNode(tag string) error {
|
2023-06-09 09:20:41 -04:00
|
|
|
if t, e := s.nodes.Load(tag); e {
|
2023-10-17 06:22:04 -04:00
|
|
|
err := t.(Core).DelNode(tag)
|
2023-06-09 09:20:41 -04:00
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
s.nodes.Delete(tag)
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
return errors.New("the node is not have")
|
|
|
|
}
|
|
|
|
|
2023-06-18 21:56:18 -04:00
|
|
|
func (s *Selector) AddUsers(p *AddUsersParams) (added int, err error) {
|
2023-06-09 09:20:41 -04:00
|
|
|
t, e := s.nodes.Load(p.Tag)
|
|
|
|
if !e {
|
|
|
|
return 0, errors.New("the node is not have")
|
|
|
|
}
|
2023-09-16 08:03:02 -04:00
|
|
|
return t.(Core).AddUsers(p)
|
2023-06-09 09:20:41 -04:00
|
|
|
}
|
|
|
|
|
2023-06-18 21:56:18 -04:00
|
|
|
func (s *Selector) GetUserTraffic(tag, uuid string, reset bool) (up int64, down int64) {
|
2023-06-09 09:20:41 -04:00
|
|
|
t, e := s.nodes.Load(tag)
|
|
|
|
if !e {
|
|
|
|
return 0, 0
|
|
|
|
}
|
2023-09-16 08:03:02 -04:00
|
|
|
return t.(Core).GetUserTraffic(tag, uuid, reset)
|
2023-06-09 09:20:41 -04:00
|
|
|
}
|
|
|
|
|
2025-01-10 02:33:05 -05:00
|
|
|
func (s *Selector) DelUsers(users []panel.UserInfo, tag string, info *panel.NodeInfo) error {
|
2023-06-09 09:20:41 -04:00
|
|
|
t, e := s.nodes.Load(tag)
|
|
|
|
if !e {
|
|
|
|
return errors.New("the node is not have")
|
|
|
|
}
|
2025-01-10 02:33:05 -05:00
|
|
|
return t.(Core).DelUsers(users, tag, info)
|
2023-06-09 09:20:41 -04:00
|
|
|
}
|
|
|
|
|
2023-06-18 21:56:18 -04:00
|
|
|
func (s *Selector) Protocols() []string {
|
2023-06-09 09:20:41 -04:00
|
|
|
protocols := make([]string, 0)
|
|
|
|
for i := range s.cores {
|
|
|
|
protocols = append(protocols, s.cores[i].Protocols()...)
|
|
|
|
}
|
|
|
|
return protocols
|
|
|
|
}
|
2023-08-20 03:13:52 -04:00
|
|
|
|
|
|
|
func (s *Selector) Type() string {
|
2023-09-02 05:45:32 -04:00
|
|
|
t := "Selector("
|
2023-09-16 08:03:02 -04:00
|
|
|
var flag bool
|
|
|
|
for n, c := range s.cores {
|
|
|
|
if flag {
|
2023-09-02 05:45:32 -04:00
|
|
|
t += " "
|
2023-09-16 08:03:02 -04:00
|
|
|
} else {
|
|
|
|
flag = true
|
|
|
|
}
|
|
|
|
if len(n) == 0 {
|
|
|
|
t += c.Type()
|
|
|
|
} else {
|
|
|
|
t += n
|
2023-09-02 05:45:32 -04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
t += ")"
|
|
|
|
return t
|
2023-08-20 03:13:52 -04:00
|
|
|
}
|