diff --git a/conf/conf.go b/conf/conf.go index 0b46104..e54997c 100644 --- a/conf/conf.go +++ b/conf/conf.go @@ -23,6 +23,7 @@ func New() *Conf { Type: "xray", XrayConfig: &XrayConfig{ LogConfig: NewLogConfig(), + AssetPath: "/etc/V2bX/", DnsConfigPath: "", InboundConfigPath: "", OutboundConfigPath: "", @@ -35,9 +36,6 @@ func New() *Conf { } func (p *Conf) LoadFromPath(filePath string) error { - confPath := path.Dir(filePath) - os.Setenv("XRAY_LOCATION_ASSET", confPath) - os.Setenv("XRAY_LOCATION_CONFIG", confPath) f, err := os.Open(filePath) if err != nil { return fmt.Errorf("open config file error: %s", err) diff --git a/conf/conf_test.go b/conf/conf_test.go index 1c4f917..44bc756 100644 --- a/conf/conf_test.go +++ b/conf/conf_test.go @@ -7,13 +7,13 @@ import ( func TestConf_LoadFromPath(t *testing.T) { c := New() - t.Log(c.LoadFromPath("../example/config.yml.example"), c.NodesConfig[0].ControllerConfig.EnableXtls) + t.Log(c.LoadFromPath("../example/config.yml.example")) } func TestConf_Watch(t *testing.T) { c := New() - c.Watch("../example/config.yml.example", func() { + log.Println(c.Watch("../example/config.yml.example", func() { log.Println(1) - }) + })) select {} } diff --git a/conf/core.go b/conf/core.go index 99eb4a0..ce4fc08 100644 --- a/conf/core.go +++ b/conf/core.go @@ -7,6 +7,7 @@ type CoreConfig struct { type XrayConfig struct { LogConfig *LogConfig `yaml:"Log"` + AssetPath string `yaml:"AssetPath"` DnsConfigPath string `yaml:"DnsConfigPath"` RouteConfigPath string `yaml:"RouteConfigPath"` ConnectionConfig *ConnectionConfig `yaml:"ConnectionConfig"` diff --git a/core/core.go b/core/core.go index 6f02499..ad00877 100644 --- a/core/core.go +++ b/core/core.go @@ -12,6 +12,25 @@ var ( ) func NewCore(c *conf.CoreConfig) (Core, error) { + // multi core + if types := strings.Split(c.Type, " "); len(types) > 1 { + var cs []Core + for _, t := range types { + f, ok := cores[strings.ToLower(c.Type)] + if !ok { + return nil, errors.New("unknown core type: " + t) + } + core1, err := f(c) + if err != nil { + return nil, err + } + cs = append(cs, core1) + } + return &Selecter{ + cores: cs, + }, nil + } + // one core if f, ok := cores[strings.ToLower(c.Type)]; ok { return f(c) } else { diff --git a/core/hy/hy.go b/core/hy/hy.go index a5eca71..e261e10 100644 --- a/core/hy/hy.go +++ b/core/hy/hy.go @@ -2,10 +2,11 @@ package hy import ( "fmt" + "sync" + "github.com/Yuzuki616/V2bX/conf" vCore "github.com/Yuzuki616/V2bX/core" "github.com/hashicorp/go-multierror" - "sync" ) func init() { @@ -40,3 +41,9 @@ func (h *Hy) Close() error { } return nil } + +func (h *Hy) Protocols() []string { + return []string{ + "hysteria", + } +} diff --git a/core/interface.go b/core/interface.go index 56513e0..0af41fa 100644 --- a/core/interface.go +++ b/core/interface.go @@ -19,4 +19,5 @@ type Core interface { AddUsers(p *AddUsersParams) (added int, err error) GetUserTraffic(tag, uuid string, reset bool) (up int64, down int64) DelUsers(users []string, tag string) error + Protocols() []string } diff --git a/core/selecter.go b/core/selecter.go new file mode 100644 index 0000000..38127a9 --- /dev/null +++ b/core/selecter.go @@ -0,0 +1,98 @@ +package core + +import ( + "errors" + "sync" + + "github.com/Yuzuki616/V2bX/api/panel" + "github.com/Yuzuki616/V2bX/conf" + "github.com/hashicorp/go-multierror" +) + +type Selecter struct { + cores []Core + nodes sync.Map +} + +func (s *Selecter) Start() error { + for i := range s.cores { + err := s.cores[i].Start() + return err + } + return nil +} + +func (s *Selecter) Close() error { + var errs error + for i := range s.cores { + errs = multierror.Append(errs, s.cores[i].Close()) + } + return errs +} + +func isSupported(protocol string, protocols []string) bool { + for i := range protocols { + if protocol == protocols[i] { + return true + } + } + return false +} + +func (s *Selecter) AddNode(tag string, info *panel.NodeInfo, config *conf.ControllerConfig) error { + for i := range s.cores { + if !isSupported(info.Type, s.cores[i].Protocols()) { + continue + } + err := s.cores[i].AddNode(tag, info, config) + if err != nil { + return err + } + s.nodes.Store(tag, i) + } + return errors.New("the node type is not support") +} + +func (s *Selecter) DelNode(tag string) error { + if t, e := s.nodes.Load(tag); e { + err := s.cores[t.(int)].DelNode(tag) + if err != nil { + return err + } + s.nodes.Delete(tag) + return nil + } + return errors.New("the node is not have") +} + +func (s *Selecter) AddUsers(p *AddUsersParams) (added int, err error) { + t, e := s.nodes.Load(p.Tag) + if !e { + return 0, errors.New("the node is not have") + } + return s.cores[t.(int)].AddUsers(p) +} + +func (s *Selecter) GetUserTraffic(tag, uuid string, reset bool) (up int64, down int64) { + t, e := s.nodes.Load(tag) + if !e { + return 0, 0 + } + return s.cores[t.(int)].GetUserTraffic(tag, uuid, reset) +} + +func (s *Selecter) DelUsers(users []string, tag string) error { + t, e := s.nodes.Load(tag) + if !e { + return errors.New("the node is not have") + } + return s.cores[t.(int)].DelUsers(users, tag) +} + +func (s *Selecter) Protocols() []string { + protocols := make([]string, 0) + for i := range s.cores { + protocols = append(protocols, s.cores[i].Protocols()...) + } + return protocols +} diff --git a/core/xray/core.go b/core/xray/xray.go similarity index 97% rename from core/xray/core.go rename to core/xray/xray.go index 55fa3fa..280eb10 100644 --- a/core/xray/core.go +++ b/core/xray/xray.go @@ -53,6 +53,7 @@ func parseConnectionConfig(c *conf.ConnectionConfig) (policy *coreConf.Policy) { } func getCore(c *conf.XrayConfig) *core.Instance { + os.Setenv("XRAY_LOCATION_ASSET", c.AssetPath) // Log Config coreLogConfig := &coreConf.LogConfig{} coreLogConfig.LogLevel = c.LogConfig.Level @@ -183,3 +184,11 @@ func (c *Core) Close() error { } return nil } + +func (c *Core) Protocols() []string { + return []string{ + "v2ray", + "shadowsocks", + "trojan", + } +} diff --git a/example/config.yml.example b/example/config.yml.example index 49f3c37..b27f79e 100644 --- a/example/config.yml.example +++ b/example/config.yml.example @@ -1,5 +1,5 @@ CoreConfig: - Type: "xray" # Core type + Type: "xray" # Core type. if you need many cores, use " " to split XrayConfig: Log: Level: warning # Log level: none, error, warning, info, debug @@ -41,7 +41,7 @@ Nodes: Dest: 80 # Required, Destination of fallback, check https://xtls.github.io/config/features/fallback.html for details. ProxyProtocolVer: 0 # Send PROXY protocol version, 0 for dsable HyOptions: - Resolver: "udp://1.1.1.1:53", // DNS resolver address + Resolver: "udp://1.1.1.1:53" # DNS resolver address ResolvePreference: 64 # DNS IPv4/IPv6 preference. Available options: "64" (IPv6 first, fallback to IPv4), "46" (IPv4 first, fallback to IPv6), "6" (IPv6 only), "4" (IPv4 only) SendDevice: "eth0" # Bind device for outbound connections (usually requires root) LimitConfig: