refactor NodeInfo

This commit is contained in:
yuzuki999 2023-08-19 20:06:42 +08:00
parent 42e86bf94c
commit 42407d5c62
13 changed files with 333 additions and 391 deletions

View File

@ -3,21 +3,45 @@ package panel
import ( import (
"encoding/base64" "encoding/base64"
"fmt" "fmt"
"github.com/InazumaV/V2bX/common/crypt"
"reflect" "reflect"
"strconv" "strconv"
"strings" "strings"
"time" "time"
"github.com/InazumaV/V2bX/common/crypt"
"github.com/goccy/go-json" "github.com/goccy/go-json"
) )
type CommonNodeRsp struct { // Security type
const (
None = 0
Tls = 1
Reality = 2
)
type NodeInfo struct {
Id int
Type string
Security int
PushInterval time.Duration
PullInterval time.Duration
RawDNS RawDNS
Rules Rules
// origin
VAllss *VAllssNode
Shadowsocks *ShadowsocksNode
Trojan *TrojanNode
Hysteria *HysteriaNode
Common *CommonNode
}
type CommonNode struct {
Host string `json:"host"` Host string `json:"host"`
ServerPort int `json:"server_port"` ServerPort int `json:"server_port"`
ServerName string `json:"server_name"` ServerName string `json:"server_name"`
Routes []Route `json:"routes"` Routes []Route `json:"routes"`
BaseConfig BaseConfig `json:"base_config"` BaseConfig *BaseConfig `json:"base_config"`
} }
type Route struct { type Route struct {
@ -31,45 +55,50 @@ type BaseConfig struct {
PullInterval any `json:"pull_interval"` PullInterval any `json:"pull_interval"`
} }
type V2rayNodeRsp struct { // VAllssNode is vmess and vless node info
type VAllssNode struct {
CommonNode
Tls int `json:"tls"` Tls int `json:"tls"`
TlsSettings TlsSettings `json:"tls_settings"`
Network string `json:"network"` Network string `json:"network"`
NetworkSettings json.RawMessage `json:"networkSettings"` NetworkSettings json.RawMessage `json:"networkSettings"`
ServerName string `json:"server_name"` ServerName string `json:"server_name"`
// vless only
Flow string `json:"flow"`
RealityConfig RealityConfig
} }
type ShadowsocksNodeRsp struct { type TlsSettings struct {
ServerName []string `json:"sever_name"`
ServerPort string `json:"server_port"`
ShortIds []string `json:"short_ids"`
PrivateKey string `json:"-"`
}
type RealityConfig struct {
Dest string `json:"Dest"`
Xver uint64 `json:"Xver"`
MinClientVer string `json:"MinClientVer"`
MaxClientVer string `json:"MaxClientVer"`
MaxTimeDiff uint64 `json:"MaxTimeDiff"`
}
type ShadowsocksNode struct {
CommonNode
Cipher string `json:"cipher"` Cipher string `json:"cipher"`
ServerKey string `json:"server_key"` ServerKey string `json:"server_key"`
} }
type HysteriaNodeRsp struct { type TrojanNode CommonNode
type HysteriaNode struct {
CommonNode
UpMbps int `json:"up_mbps"` UpMbps int `json:"up_mbps"`
DownMbps int `json:"down_mbps"` DownMbps int `json:"down_mbps"`
Obfs string `json:"obfs"` Obfs string `json:"obfs"`
} }
type NodeInfo struct {
Id int
Type string
Rules Rules
Host string
Port int
Network string
RawDNS RawDNS
ExtraConfig V2rayExtraConfig
NetworkSettings json.RawMessage
Tls bool
ServerName string
UpMbps int
DownMbps int
ServerKey string
Cipher string
HyObfs string
PushInterval time.Duration
PullInterval time.Duration
}
type RawDNS struct { type RawDNS struct {
DNSMap map[string]map[string]interface{} DNSMap map[string]map[string]interface{}
DNSJson []byte DNSJson []byte
@ -80,24 +109,6 @@ type Rules struct {
Protocol []string Protocol []string
} }
type V2rayExtraConfig struct {
EnableVless string `json:"EnableVless"`
VlessFlow string `json:"VlessFlow"`
EnableReality string `json:"EnableReality"`
RealityConfig *RealityConfig `json:"RealityConfig"`
}
type RealityConfig struct {
Dest string `yaml:"Dest" json:"Dest"`
Xver string `yaml:"Xver" json:"Xver"`
ServerNames []string `yaml:"ServerNames" json:"ServerNames"`
PrivateKey string `yaml:"PrivateKey" json:"PrivateKey"`
MinClientVer string `yaml:"MinClientVer" json:"MinClientVer"`
MaxClientVer string `yaml:"MaxClientVer" json:"MaxClientVer"`
MaxTimeDiff string `yaml:"MaxTimeDiff" json:"MaxTimeDiff"`
ShortIds []string `yaml:"ShortIds" json:"ShortIds"`
}
func (c *Client) GetNodeInfo() (node *NodeInfo, err error) { func (c *Client) GetNodeInfo() (node *NodeInfo, err error) {
const path = "/api/v1/server/UniProxy/config" const path = "/api/v1/server/UniProxy/config"
r, err := c.client. r, err := c.client.
@ -110,7 +121,6 @@ func (c *Client) GetNodeInfo() (node *NodeInfo, err error) {
if r.StatusCode() == 304 { if r.StatusCode() == 304 {
return nil, nil return nil, nil
} }
// parse common params
node = &NodeInfo{ node = &NodeInfo{
Id: c.NodeId, Id: c.NodeId,
Type: c.NodeType, Type: c.NodeType,
@ -119,26 +129,72 @@ func (c *Client) GetNodeInfo() (node *NodeInfo, err error) {
DNSJson: []byte(""), DNSJson: []byte(""),
}, },
} }
common := CommonNodeRsp{} // parse protocol params
err = json.Unmarshal(r.Body(), &common) var cm *CommonNode
switch c.NodeType {
case "vmess", "vless":
rsp := &VAllssNode{}
err = json.Unmarshal(r.Body(), rsp)
if err != nil { if err != nil {
return nil, fmt.Errorf("decode common params error: %s", err) return nil, fmt.Errorf("decode v2ray params error: %s", err)
}
cm = &rsp.CommonNode
node.VAllss = rsp
node.Security = node.VAllss.Tls
if len(rsp.NetworkSettings) > 0 {
/*err = json.Unmarshal(rsp.NetworkSettings, &rsp.RealityConfig)
if err != nil {
return nil, fmt.Errorf("decode reality config error: %s", err)
}*/
if node.Security == Reality {
key := crypt.GenX25519Private([]byte(strconv.Itoa(c.NodeId) + c.NodeType + c.Token))
rsp.TlsSettings.PrivateKey = base64.RawURLEncoding.EncodeToString(key)
}
}
case "shadowsocks":
rsp := &ShadowsocksNode{}
err = json.Unmarshal(r.Body(), rsp)
if err != nil {
return nil, fmt.Errorf("decode v2ray params error: %s", err)
}
cm = &rsp.CommonNode
node.Shadowsocks = rsp
node.Security = None
case "trojan":
rsp := &TrojanNode{}
err = json.Unmarshal(r.Body(), rsp)
if err != nil {
return nil, fmt.Errorf("decode v2ray params error: %s", err)
}
cm = (*CommonNode)(rsp)
node.Trojan = rsp
node.Security = Tls
case "hysteria":
rsp := &HysteriaNode{}
err = json.Unmarshal(r.Body(), rsp)
if err != nil {
return nil, fmt.Errorf("decode v2ray params error: %s", err)
}
cm = &rsp.CommonNode
node.Hysteria = rsp
node.Security = Tls
} }
for i := range common.Routes { // parse rules and dns
for i := range cm.Routes {
var matchs []string var matchs []string
if _, ok := common.Routes[i].Match.(string); ok { if _, ok := cm.Routes[i].Match.(string); ok {
matchs = strings.Split(common.Routes[i].Match.(string), ",") matchs = strings.Split(cm.Routes[i].Match.(string), ",")
} else if _, ok = common.Routes[i].Match.([]string); ok { } else if _, ok = cm.Routes[i].Match.([]string); ok {
matchs = common.Routes[i].Match.([]string) matchs = cm.Routes[i].Match.([]string)
} else { } else {
temp := common.Routes[i].Match.([]interface{}) temp := cm.Routes[i].Match.([]interface{})
matchs = make([]string, len(temp)) matchs = make([]string, len(temp))
for i := range temp { for i := range temp {
matchs[i] = temp[i].(string) matchs[i] = temp[i].(string)
} }
} }
switch common.Routes[i].Action { switch cm.Routes[i].Action {
case "block": case "block":
for _, v := range matchs { for _, v := range matchs {
if strings.HasPrefix(v, "protocol:") { if strings.HasPrefix(v, "protocol:") {
@ -156,7 +212,7 @@ func (c *Client) GetNodeInfo() (node *NodeInfo, err error) {
} }
if matchs[0] != "main" { if matchs[0] != "main" {
node.RawDNS.DNSMap[strconv.Itoa(i)] = map[string]interface{}{ node.RawDNS.DNSMap[strconv.Itoa(i)] = map[string]interface{}{
"address": common.Routes[i].ActionValue, "address": cm.Routes[i].ActionValue,
"domains": domains, "domains": domains,
} }
} else { } else {
@ -166,57 +222,16 @@ func (c *Client) GetNodeInfo() (node *NodeInfo, err error) {
} }
} }
} }
node.ServerName = common.ServerName
node.Host = common.Host // set interval
node.Port = common.ServerPort node.PushInterval = intervalToTime(cm.BaseConfig.PushInterval)
node.PullInterval = intervalToTime(common.BaseConfig.PullInterval) node.PullInterval = intervalToTime(cm.BaseConfig.PullInterval)
node.PushInterval = intervalToTime(common.BaseConfig.PushInterval)
// parse protocol params node.Common = cm
switch c.NodeType { // clear
case "v2ray": cm.Routes = nil
rsp := V2rayNodeRsp{} cm.BaseConfig = nil
err = json.Unmarshal(r.Body(), &rsp)
if err != nil {
return nil, fmt.Errorf("decode v2ray params error: %s", err)
}
node.Network = rsp.Network
node.NetworkSettings = rsp.NetworkSettings
node.ServerName = rsp.ServerName
if rsp.Tls == 1 {
node.Tls = true
}
err = json.Unmarshal(rsp.NetworkSettings, &node.ExtraConfig)
if err != nil {
return nil, fmt.Errorf("decode v2ray extra error: %s", err)
}
if node.ExtraConfig.EnableReality == "true" {
if node.ExtraConfig.RealityConfig == nil {
node.ExtraConfig.EnableReality = "false"
} else {
key := crypt.GenX25519Private([]byte(strconv.Itoa(c.NodeId) + c.NodeType + c.Token))
node.ExtraConfig.RealityConfig.PrivateKey = base64.RawURLEncoding.EncodeToString(key)
}
}
case "shadowsocks":
rsp := ShadowsocksNodeRsp{}
err = json.Unmarshal(r.Body(), &rsp)
if err != nil {
return nil, fmt.Errorf("decode v2ray params error: %s", err)
}
node.ServerKey = rsp.ServerKey
node.Cipher = rsp.Cipher
case "trojan":
node.Tls = true
case "hysteria":
rsp := HysteriaNodeRsp{}
err = json.Unmarshal(r.Body(), &rsp)
if err != nil {
return nil, fmt.Errorf("decode v2ray params error: %s", err)
}
node.DownMbps = rsp.DownMbps
node.UpMbps = rsp.UpMbps
node.HyObfs = rsp.Obfs
}
c.nodeEtag = r.Header().Get("ETag") c.nodeEtag = r.Header().Get("ETag")
return return
} }

View File

@ -46,7 +46,14 @@ func New(c *conf.ApiConfig) (*Client, error) {
// Check node type // Check node type
c.NodeType = strings.ToLower(c.NodeType) c.NodeType = strings.ToLower(c.NodeType)
switch c.NodeType { switch c.NodeType {
case "v2ray", "trojan", "shadowsocks", "hysteria": case "v2ray":
c.NodeType = "vmess"
case
"vmess",
"trojan",
"shadowsocks",
"hysteria",
"vless":
default: default:
return nil, fmt.Errorf("unsupported Node type: %s", c.NodeType) return nil, fmt.Errorf("unsupported Node type: %s", c.NodeType)
} }

View File

@ -9,16 +9,4 @@ type CertConfig struct {
Provider string `yaml:"Provider"` // alidns, cloudflare, gandi, godaddy.... Provider string `yaml:"Provider"` // alidns, cloudflare, gandi, godaddy....
Email string `yaml:"Email"` Email string `yaml:"Email"`
DNSEnv map[string]string `yaml:"DNSEnv"` DNSEnv map[string]string `yaml:"DNSEnv"`
RealityConfig *RealityConfig `yaml:"RealityConfig"`
}
type RealityConfig struct {
Dest string `yaml:"Dest" json:"Dest"`
Xver uint64 `yaml:"Xver" json:"Xver"`
ServerNames []string `yaml:"ServerNames" json:"ServerNames"`
PrivateKey string `yaml:"PrivateKey" json:"PrivateKey"`
MinClientVer string `yaml:"MinClientVer" json:"MinClientVer"`
MaxClientVer string `yaml:"MaxClientVer" json:"MaxClientVer"`
MaxTimeDiff uint64 `yaml:"MaxTimeDiff" json:"MaxTimeDiff"`
ShortIds []string `yaml:"ShortIds" json:"ShortIds"`
} }

View File

@ -7,10 +7,10 @@ import (
type AddUsersParams struct { type AddUsersParams struct {
Tag string Tag string
Config *conf.Options Users []panel.UserInfo
UserInfo []panel.UserInfo *panel.NodeInfo
NodeInfo *panel.NodeInfo
} }
type Core interface { type Core interface {
Start() error Start() error
Close() error Close() error

View File

@ -5,7 +5,6 @@ import (
"crypto/rand" "crypto/rand"
"encoding/base64" "encoding/base64"
"fmt" "fmt"
"github.com/google/uuid"
"net/netip" "net/netip"
"net/url" "net/url"
"strconv" "strconv"
@ -33,7 +32,7 @@ func getInboundOptions(tag string, info *panel.NodeInfo, c *conf.Options) (optio
} }
listen := option.ListenOptions{ listen := option.ListenOptions{
Listen: (*option.ListenAddress)(&addr), Listen: (*option.ListenAddress)(&addr),
ListenPort: uint16(info.Port), ListenPort: uint16(info.Common.ServerPort),
ProxyProtocol: c.SingOptions.EnableProxyProtocol, ProxyProtocol: c.SingOptions.EnableProxyProtocol,
TCPFastOpen: c.SingOptions.TCPFastOpen, TCPFastOpen: c.SingOptions.TCPFastOpen,
InboundOptions: option.InboundOptions{ InboundOptions: option.InboundOptions{
@ -42,83 +41,56 @@ func getInboundOptions(tag string, info *panel.NodeInfo, c *conf.Options) (optio
}, },
} }
var tls option.InboundTLSOptions var tls option.InboundTLSOptions
if info.Tls || info.Type == "hysteria" { switch info.Security {
case panel.Tls:
if c.CertConfig == nil { if c.CertConfig == nil {
return option.Inbound{}, fmt.Errorf("the CertConfig is not vail") return option.Inbound{}, fmt.Errorf("the CertConfig is not vail")
} }
tls.Enabled = true
tls.Insecure = true
tls.ServerName = info.ServerName
switch c.CertConfig.CertMode { switch c.CertConfig.CertMode {
case "none", "": case "none", "":
break // disable break // disable
case "reality":
if c.CertConfig.RealityConfig == nil {
return option.Inbound{}, fmt.Errorf("RealityConfig is not valid")
}
rc := c.CertConfig.RealityConfig
tls.ServerName = rc.ServerNames[0]
if len(rc.ShortIds) == 0 {
rc.ShortIds = []string{""}
}
dest, _ := strconv.Atoi(rc.Dest)
mtd, _ := strconv.Atoi(strconv.FormatUint(rc.MaxTimeDiff, 10))
tls.Reality = &option.InboundRealityOptions{
Enabled: true,
ShortID: rc.ShortIds,
PrivateKey: rc.PrivateKey,
MaxTimeDifference: option.Duration(time.Duration(mtd) * time.Second),
Handshake: option.InboundRealityHandshakeOptions{
ServerOptions: option.ServerOptions{
Server: rc.ServerNames[0],
ServerPort: uint16(dest),
},
},
}
case "remote":
if info.ExtraConfig.EnableReality == "true" {
if c.CertConfig.RealityConfig == nil {
return option.Inbound{}, fmt.Errorf("RealityConfig is not valid")
}
rc := info.ExtraConfig.RealityConfig
if len(rc.ShortIds) == 0 {
rc.ShortIds = []string{""}
}
dest, _ := strconv.Atoi(rc.Dest)
mtd, _ := strconv.Atoi(rc.MaxTimeDiff)
tls.Reality = &option.InboundRealityOptions{
Enabled: true,
ShortID: rc.ShortIds,
PrivateKey: rc.PrivateKey,
MaxTimeDifference: option.Duration(time.Duration(mtd) * time.Second),
Handshake: option.InboundRealityHandshakeOptions{
ServerOptions: option.ServerOptions{
Server: rc.ServerNames[0],
ServerPort: uint16(dest),
},
},
}
}
default: default:
tls.Enabled = true
tls.CertificatePath = c.CertConfig.CertFile tls.CertificatePath = c.CertConfig.CertFile
tls.KeyPath = c.CertConfig.KeyFile tls.KeyPath = c.CertConfig.KeyFile
} }
case panel.Reality:
tls.Enabled = true
v := info.VAllss
tls.ServerName = v.TlsSettings.PrivateKey
if len(v.TlsSettings.ShortIds) == 0 {
v.TlsSettings.ShortIds = []string{""}
}
dest, _ := strconv.Atoi(v.TlsSettings.ServerPort)
mtd, _ := strconv.Atoi(strconv.FormatUint(v.RealityConfig.MaxTimeDiff, 10))
tls.Reality = &option.InboundRealityOptions{
Enabled: true,
ShortID: v.TlsSettings.ShortIds,
PrivateKey: v.TlsSettings.PrivateKey,
MaxTimeDifference: option.Duration(time.Duration(mtd) * time.Second),
Handshake: option.InboundRealityHandshakeOptions{
ServerOptions: option.ServerOptions{
Server: v.TlsSettings.ServerName[0],
ServerPort: uint16(dest),
},
},
}
} }
in := option.Inbound{ in := option.Inbound{
Tag: tag, Tag: tag,
} }
switch info.Type { switch info.Type {
case "v2ray": case "vmess", "vless":
n := info.VAllss
t := option.V2RayTransportOptions{ t := option.V2RayTransportOptions{
Type: info.Network, Type: n.Network,
} }
switch info.Network { switch n.Network {
case "tcp": case "tcp":
t.Type = "" t.Type = ""
case "ws": case "ws":
network := WsNetworkConfig{} network := WsNetworkConfig{}
err := json.Unmarshal(info.NetworkSettings, &network) err := json.Unmarshal(n.NetworkSettings, &network)
if err != nil { if err != nil {
return option.Inbound{}, fmt.Errorf("decode NetworkSettings error: %s", err) return option.Inbound{}, fmt.Errorf("decode NetworkSettings error: %s", err)
} }
@ -141,12 +113,13 @@ func getInboundOptions(tag string, info *panel.NodeInfo, c *conf.Options) (optio
Headers: h, Headers: h,
} }
case "grpc": case "grpc":
err := json.Unmarshal(info.NetworkSettings, &t.GRPCOptions) err := json.Unmarshal(n.NetworkSettings, &t.GRPCOptions)
if err != nil { if err != nil {
return option.Inbound{}, fmt.Errorf("decode NetworkSettings error: %s", err) return option.Inbound{}, fmt.Errorf("decode NetworkSettings error: %s", err)
} }
} }
if info.ExtraConfig.EnableVless == "true" { tls.ServerName = n.ServerName
if info.Type == "vless" {
in.Type = "vless" in.Type = "vless"
in.VLESSOptions = option.VLESSInboundOptions{ in.VLESSOptions = option.VLESSInboundOptions{
ListenOptions: listen, ListenOptions: listen,
@ -163,8 +136,9 @@ func getInboundOptions(tag string, info *panel.NodeInfo, c *conf.Options) (optio
} }
case "shadowsocks": case "shadowsocks":
in.Type = "shadowsocks" in.Type = "shadowsocks"
n := info.Shadowsocks
var keyLength int var keyLength int
switch info.Cipher { switch n.Cipher {
case "2022-blake3-aes-128-gcm": case "2022-blake3-aes-128-gcm":
keyLength = 16 keyLength = 16
case "2022-blake3-aes-256-gcm": case "2022-blake3-aes-256-gcm":
@ -174,13 +148,13 @@ func getInboundOptions(tag string, info *panel.NodeInfo, c *conf.Options) (optio
} }
in.ShadowsocksOptions = option.ShadowsocksInboundOptions{ in.ShadowsocksOptions = option.ShadowsocksInboundOptions{
ListenOptions: listen, ListenOptions: listen,
Method: info.Cipher, Method: n.Cipher,
} }
p := make([]byte, keyLength) p := make([]byte, keyLength)
_, _ = rand.Read(p) _, _ = rand.Read(p)
randomPasswd := string(p) randomPasswd := string(p)
if strings.Contains(info.Cipher, "2022") { if strings.Contains(n.Cipher, "2022") {
in.ShadowsocksOptions.Password = info.ServerKey in.ShadowsocksOptions.Password = n.ServerKey
randomPasswd = base64.StdEncoding.EncodeToString([]byte(randomPasswd)) randomPasswd = base64.StdEncoding.EncodeToString([]byte(randomPasswd))
} }
in.ShadowsocksOptions.Users = []option.ShadowsocksUser{{ in.ShadowsocksOptions.Users = []option.ShadowsocksUser{{
@ -188,27 +162,9 @@ func getInboundOptions(tag string, info *panel.NodeInfo, c *conf.Options) (optio
}} }}
case "trojan": case "trojan":
in.Type = "trojan" in.Type = "trojan"
t := option.V2RayTransportOptions{
Type: info.Network,
}
switch info.Network {
case "tcp":
t.Type = ""
case "grpc":
err := json.Unmarshal(info.NetworkSettings, &t.GRPCOptions)
if err != nil {
return option.Inbound{}, fmt.Errorf("decode NetworkSettings error: %s", err)
}
}
randomPasswd := uuid.New().String()
in.TrojanOptions = option.TrojanInboundOptions{ in.TrojanOptions = option.TrojanInboundOptions{
ListenOptions: listen, ListenOptions: listen,
Users: []option.TrojanUser{{
Name: randomPasswd,
Password: randomPasswd,
}},
TLS: &tls, TLS: &tls,
Transport: &t,
} }
if c.SingOptions.FallBackConfigs != nil { if c.SingOptions.FallBackConfigs != nil {
// fallback handling // fallback handling
@ -230,9 +186,9 @@ func getInboundOptions(tag string, info *panel.NodeInfo, c *conf.Options) (optio
in.Type = "hysteria" in.Type = "hysteria"
in.HysteriaOptions = option.HysteriaInboundOptions{ in.HysteriaOptions = option.HysteriaInboundOptions{
ListenOptions: listen, ListenOptions: listen,
UpMbps: info.UpMbps, UpMbps: info.Hysteria.UpMbps,
DownMbps: info.DownMbps, DownMbps: info.Hysteria.DownMbps,
Obfs: info.HyObfs, Obfs: info.Hysteria.Obfs,
TLS: &tls, TLS: &tls,
} }
} }

View File

@ -264,7 +264,8 @@ func (b *Box) Router() adapter.Router {
func (b *Box) Protocols() []string { func (b *Box) Protocols() []string {
return []string{ return []string{
"v2ray", "vmess",
"vless",
"shadowsocks", "shadowsocks",
"trojan", "trojan",
"hysteria", "hysteria",

View File

@ -13,58 +13,58 @@ import (
func (b *Box) AddUsers(p *core.AddUsersParams) (added int, err error) { func (b *Box) AddUsers(p *core.AddUsersParams) (added int, err error) {
switch p.NodeInfo.Type { switch p.NodeInfo.Type {
case "v2ray": case "vmess", "vless":
if p.NodeInfo.ExtraConfig.EnableVless == "true" { if p.NodeInfo.Type == "vless" {
us := make([]option.VLESSUser, len(p.UserInfo)) us := make([]option.VLESSUser, len(p.Users))
for i := range p.UserInfo { for i := range p.Users {
us[i] = option.VLESSUser{ us[i] = option.VLESSUser{
Name: p.UserInfo[i].Uuid, Name: p.Users[i].Uuid,
Flow: p.NodeInfo.ExtraConfig.VlessFlow, Flow: p.VAllss.Flow,
UUID: p.UserInfo[i].Uuid, UUID: p.Users[i].Uuid,
} }
} }
err = b.inbounds[p.Tag].(*inbound.VLESS).AddUsers(us) err = b.inbounds[p.Tag].(*inbound.VLESS).AddUsers(us)
} else { } else {
us := make([]option.VMessUser, len(p.UserInfo)) us := make([]option.VMessUser, len(p.Users))
for i := range p.UserInfo { for i := range p.Users {
us[i] = option.VMessUser{ us[i] = option.VMessUser{
Name: p.UserInfo[i].Uuid, Name: p.Users[i].Uuid,
UUID: p.UserInfo[i].Uuid, UUID: p.Users[i].Uuid,
} }
} }
err = b.inbounds[p.Tag].(*inbound.VMess).AddUsers(us) err = b.inbounds[p.Tag].(*inbound.VMess).AddUsers(us)
} }
case "shadowsocks": case "shadowsocks":
us := make([]option.ShadowsocksUser, len(p.UserInfo)) us := make([]option.ShadowsocksUser, len(p.Users))
for i := range p.UserInfo { for i := range p.Users {
var password = p.UserInfo[i].Uuid var password = p.Users[i].Uuid
switch p.NodeInfo.Cipher { switch p.Shadowsocks.Cipher {
case "2022-blake3-aes-128-gcm": case "2022-blake3-aes-128-gcm":
password = base64.StdEncoding.EncodeToString([]byte(password[:16])) password = base64.StdEncoding.EncodeToString([]byte(password[:16]))
case "2022-blake3-aes-256-gcm": case "2022-blake3-aes-256-gcm":
password = base64.StdEncoding.EncodeToString([]byte(password[:32])) password = base64.StdEncoding.EncodeToString([]byte(password[:32]))
} }
us[i] = option.ShadowsocksUser{ us[i] = option.ShadowsocksUser{
Name: p.UserInfo[i].Uuid, Name: p.Users[i].Uuid,
Password: password, Password: password,
} }
} }
err = b.inbounds[p.Tag].(*inbound.ShadowsocksMulti).AddUsers(us) err = b.inbounds[p.Tag].(*inbound.ShadowsocksMulti).AddUsers(us)
case "trojan": case "trojan":
us := make([]option.TrojanUser, len(p.UserInfo)) us := make([]option.TrojanUser, len(p.Users))
for i := range p.UserInfo { for i := range p.Users {
us[i] = option.TrojanUser{ us[i] = option.TrojanUser{
Name: p.UserInfo[i].Uuid, Name: p.Users[i].Uuid,
Password: p.UserInfo[i].Uuid, Password: p.Users[i].Uuid,
} }
} }
err = b.inbounds[p.Tag].(*inbound.Trojan).AddUsers(us) err = b.inbounds[p.Tag].(*inbound.Trojan).AddUsers(us)
case "hysteria": case "hysteria":
us := make([]option.HysteriaUser, len(p.UserInfo)) us := make([]option.HysteriaUser, len(p.Users))
for i := range p.UserInfo { for i := range p.Users {
us[i] = option.HysteriaUser{ us[i] = option.HysteriaUser{
Name: p.UserInfo[i].Uuid, Name: p.Users[i].Uuid,
AuthString: p.UserInfo[i].Uuid, AuthString: p.Users[i].Uuid,
} }
} }
err = b.inbounds[p.Tag].(*inbound.Hysteria).AddUsers(us) err = b.inbounds[p.Tag].(*inbound.Hysteria).AddUsers(us)
@ -72,7 +72,7 @@ func (b *Box) AddUsers(p *core.AddUsersParams) (added int, err error) {
if err != nil { if err != nil {
return 0, err return 0, err
} }
return len(p.UserInfo), err return len(p.Users), err
} }
func (b *Box) GetUserTraffic(tag, uuid string, reset bool) (up int64, down int64) { func (b *Box) GetUserTraffic(tag, uuid string, reset bool) (up int64, down int64) {

View File

@ -6,8 +6,6 @@ import (
"encoding/hex" "encoding/hex"
"errors" "errors"
"fmt" "fmt"
"strconv"
"github.com/InazumaV/V2bX/api/panel" "github.com/InazumaV/V2bX/api/panel"
"github.com/InazumaV/V2bX/conf" "github.com/InazumaV/V2bX/conf"
"github.com/goccy/go-json" "github.com/goccy/go-json"
@ -17,141 +15,121 @@ import (
) )
// BuildInbound build Inbound config for different protocol // BuildInbound build Inbound config for different protocol
func buildInbound(config *conf.Options, nodeInfo *panel.NodeInfo, tag string) (*core.InboundHandlerConfig, error) { func buildInbound(option *conf.Options, nodeInfo *panel.NodeInfo, tag string) (*core.InboundHandlerConfig, error) {
in := &coreConf.InboundDetourConfig{} in := &coreConf.InboundDetourConfig{}
// Set network protocol
t := coreConf.TransportProtocol(nodeInfo.Network)
in.StreamSetting = &coreConf.StreamConfig{Network: &t}
var err error var err error
var network string
switch nodeInfo.Type { switch nodeInfo.Type {
case "v2ray": case "v2ray":
err = buildV2ray(config, nodeInfo, in) err = buildV2ray(option, nodeInfo, in)
network = nodeInfo.VAllss.Network
case "trojan": case "trojan":
err = buildTrojan(config, in) err = buildTrojan(option, in)
case "shadowsocks": case "shadowsocks":
err = buildShadowsocks(config, nodeInfo, in) err = buildShadowsocks(option, nodeInfo, in)
default: default:
return nil, fmt.Errorf("unsupported node type: %s, Only support: V2ray, Trojan, Shadowsocks", nodeInfo.Type) return nil, fmt.Errorf("unsupported node type: %s, Only support: V2ray, Trojan, Shadowsocks", nodeInfo.Type)
} }
if err != nil { if err != nil {
return nil, err return nil, err
} }
// Set network protocol
t := coreConf.TransportProtocol(network)
in.StreamSetting = &coreConf.StreamConfig{Network: &t}
// Set server port // Set server port
in.PortList = &coreConf.PortList{ in.PortList = &coreConf.PortList{
Range: []coreConf.PortRange{{From: uint32(nodeInfo.Port), To: uint32(nodeInfo.Port)}}, Range: []coreConf.PortRange{
{
From: uint32(nodeInfo.Common.ServerPort),
To: uint32(nodeInfo.Common.ServerPort),
}},
} }
// Set Listen IP address // Set Listen IP address
ipAddress := net.ParseAddress(config.ListenIP) ipAddress := net.ParseAddress(option.ListenIP)
in.ListenOn = &coreConf.Address{Address: ipAddress} in.ListenOn = &coreConf.Address{Address: ipAddress}
// Set SniffingConfig // Set SniffingConfig
sniffingConfig := &coreConf.SniffingConfig{ sniffingConfig := &coreConf.SniffingConfig{
Enabled: true, Enabled: true,
DestOverride: &coreConf.StringList{"http", "tls"}, DestOverride: &coreConf.StringList{"http", "tls"},
} }
if config.XrayOptions.DisableSniffing { if option.XrayOptions.DisableSniffing {
sniffingConfig.Enabled = false sniffingConfig.Enabled = false
} }
in.SniffingConfig = sniffingConfig in.SniffingConfig = sniffingConfig
if *in.StreamSetting.Network == "tcp" { switch network {
case "tcp":
if in.StreamSetting.TCPSettings != nil { if in.StreamSetting.TCPSettings != nil {
in.StreamSetting.TCPSettings.AcceptProxyProtocol = config.XrayOptions.EnableProxyProtocol in.StreamSetting.TCPSettings.AcceptProxyProtocol = option.XrayOptions.EnableProxyProtocol
} else { } else {
tcpSetting := &coreConf.TCPConfig{ tcpSetting := &coreConf.TCPConfig{
AcceptProxyProtocol: config.XrayOptions.EnableProxyProtocol, AcceptProxyProtocol: option.XrayOptions.EnableProxyProtocol,
} //Enable proxy protocol } //Enable proxy protocol
in.StreamSetting.TCPSettings = tcpSetting in.StreamSetting.TCPSettings = tcpSetting
} }
} else if *in.StreamSetting.Network == "ws" { case "ws":
in.StreamSetting.WSSettings = &coreConf.WebSocketConfig{ in.StreamSetting.WSSettings = &coreConf.WebSocketConfig{
AcceptProxyProtocol: config.XrayOptions.EnableProxyProtocol} //Enable proxy protocol AcceptProxyProtocol: option.XrayOptions.EnableProxyProtocol} //Enable proxy protocol
default:
socketConfig := &coreConf.SocketConfig{
AcceptProxyProtocol: option.XrayOptions.EnableProxyProtocol,
TFO: option.XrayOptions.EnableTFO,
} //Enable proxy protocol
in.StreamSetting.SocketSettings = socketConfig
} }
// Set TLS or Reality settings // Set TLS or Reality settings
if nodeInfo.Tls { switch nodeInfo.Security {
if config.CertConfig == nil { case panel.Tls:
// Normal tls
if option.CertConfig == nil {
return nil, errors.New("the CertConfig is not vail") return nil, errors.New("the CertConfig is not vail")
} }
switch config.CertConfig.CertMode { switch option.CertConfig.CertMode {
case "none", "": case "none", "":
break // disable break // disable
case "reality":
// Reality
in.StreamSetting.Security = "reality"
d, err := json.Marshal(config.CertConfig.RealityConfig.Dest)
if err != nil {
return nil, fmt.Errorf("marshal reality dest error: %s", err)
}
if len(config.CertConfig.RealityConfig.ShortIds) == 0 {
config.CertConfig.RealityConfig.ShortIds = []string{""}
}
in.StreamSetting.REALITYSettings = &coreConf.REALITYConfig{
Dest: d,
Xver: config.CertConfig.RealityConfig.Xver,
ServerNames: config.CertConfig.RealityConfig.ServerNames,
PrivateKey: config.CertConfig.RealityConfig.PrivateKey,
MinClientVer: config.CertConfig.RealityConfig.MinClientVer,
MaxClientVer: config.CertConfig.RealityConfig.MaxClientVer,
MaxTimeDiff: config.CertConfig.RealityConfig.MaxTimeDiff,
ShortIds: config.CertConfig.RealityConfig.ShortIds,
}
break
case "remote":
if nodeInfo.ExtraConfig.EnableReality == "true" {
rc := nodeInfo.ExtraConfig.RealityConfig
in.StreamSetting.Security = "reality"
d, err := json.Marshal(rc.Dest)
if err != nil {
return nil, fmt.Errorf("marshal reality dest error: %s", err)
}
if len(rc.ShortIds) == 0 {
rc.ShortIds = []string{""}
}
Xver, _ := strconv.ParseUint(rc.Xver, 10, 64)
MaxTimeDiff, _ := strconv.ParseUint(rc.Xver, 10, 64)
in.StreamSetting.REALITYSettings = &coreConf.REALITYConfig{
Dest: d,
Xver: Xver,
ServerNames: rc.ServerNames,
PrivateKey: rc.PrivateKey,
MinClientVer: rc.MinClientVer,
MaxClientVer: rc.MaxClientVer,
MaxTimeDiff: MaxTimeDiff,
ShortIds: rc.ShortIds,
}
break
}
default: default:
{
// Normal tls
in.StreamSetting.Security = "tls" in.StreamSetting.Security = "tls"
in.StreamSetting.TLSSettings = &coreConf.TLSConfig{ in.StreamSetting.TLSSettings = &coreConf.TLSConfig{
Certs: []*coreConf.TLSCertConfig{ Certs: []*coreConf.TLSCertConfig{
{ {
CertFile: config.CertConfig.CertFile, CertFile: option.CertConfig.CertFile,
KeyFile: config.CertConfig.KeyFile, KeyFile: option.CertConfig.KeyFile,
OcspStapling: 3600, OcspStapling: 3600,
}, },
}, },
RejectUnknownSNI: config.CertConfig.RejectUnknownSni, RejectUnknownSNI: option.CertConfig.RejectUnknownSni,
} }
} }
case panel.Reality:
// Reality
in.StreamSetting.Security = "reality"
v := nodeInfo.VAllss
d, err := json.Marshal(v.RealityConfig.Dest)
if err != nil {
return nil, fmt.Errorf("marshal reality dest error: %s", err)
} }
short := nodeInfo.VAllss.TlsSettings.ShortIds
if len(short) == 0 {
short = []string{""}
} }
// Support ProxyProtocol for any transport protocol in.StreamSetting.REALITYSettings = &coreConf.REALITYConfig{
if *in.StreamSetting.Network != "tcp" && Dest: d,
*in.StreamSetting.Network != "ws" && Xver: v.RealityConfig.Xver,
config.XrayOptions.EnableProxyProtocol { ServerNames: v.TlsSettings.ServerName,
socketConfig := &coreConf.SocketConfig{ PrivateKey: v.TlsSettings.PrivateKey,
AcceptProxyProtocol: config.XrayOptions.EnableProxyProtocol, MinClientVer: v.RealityConfig.MinClientVer,
TFO: config.XrayOptions.EnableTFO, MaxClientVer: v.RealityConfig.MaxClientVer,
} //Enable proxy protocol MaxTimeDiff: v.RealityConfig.MaxTimeDiff,
in.StreamSetting.SocketSettings = socketConfig ShortIds: short,
}
break
} }
in.Tag = tag in.Tag = tag
return in.Build() return in.Build()
} }
func buildV2ray(config *conf.Options, nodeInfo *panel.NodeInfo, inbound *coreConf.InboundDetourConfig) error { func buildV2ray(config *conf.Options, nodeInfo *panel.NodeInfo, inbound *coreConf.InboundDetourConfig) error {
if nodeInfo.ExtraConfig.EnableVless == "true" { v := nodeInfo.VAllss
if nodeInfo.Type == "vless" {
//Set vless //Set vless
inbound.Protocol = "vless" inbound.Protocol = "vless"
if config.XrayOptions.EnableFallback { if config.XrayOptions.EnableFallback {
@ -188,22 +166,22 @@ func buildV2ray(config *conf.Options, nodeInfo *panel.NodeInfo, inbound *coreCon
} }
inbound.Settings = (*json.RawMessage)(&s) inbound.Settings = (*json.RawMessage)(&s)
} }
if len(nodeInfo.NetworkSettings) == 0 { if len(v.NetworkSettings) == 0 {
return nil return nil
} }
switch nodeInfo.Network { switch v.Network {
case "tcp": case "tcp":
err := json.Unmarshal(nodeInfo.NetworkSettings, &inbound.StreamSetting.TCPSettings) err := json.Unmarshal(v.NetworkSettings, &inbound.StreamSetting.TCPSettings)
if err != nil { if err != nil {
return fmt.Errorf("unmarshal tcp settings error: %s", err) return fmt.Errorf("unmarshal tcp settings error: %s", err)
} }
case "ws": case "ws":
err := json.Unmarshal(nodeInfo.NetworkSettings, &inbound.StreamSetting.WSSettings) err := json.Unmarshal(v.NetworkSettings, &inbound.StreamSetting.WSSettings)
if err != nil { if err != nil {
return fmt.Errorf("unmarshal ws settings error: %s", err) return fmt.Errorf("unmarshal ws settings error: %s", err)
} }
case "grpc": case "grpc":
err := json.Unmarshal(nodeInfo.NetworkSettings, &inbound.StreamSetting.GRPCConfig) err := json.Unmarshal(v.NetworkSettings, &inbound.StreamSetting.GRPCConfig)
if err != nil { if err != nil {
return fmt.Errorf("unmarshal grpc settings error: %s", err) return fmt.Errorf("unmarshal grpc settings error: %s", err)
} }
@ -239,8 +217,9 @@ func buildTrojan(config *conf.Options, inbound *coreConf.InboundDetourConfig) er
func buildShadowsocks(config *conf.Options, nodeInfo *panel.NodeInfo, inbound *coreConf.InboundDetourConfig) error { func buildShadowsocks(config *conf.Options, nodeInfo *panel.NodeInfo, inbound *coreConf.InboundDetourConfig) error {
inbound.Protocol = "shadowsocks" inbound.Protocol = "shadowsocks"
s := nodeInfo.Shadowsocks
settings := &coreConf.ShadowsocksServerConfig{ settings := &coreConf.ShadowsocksServerConfig{
Cipher: nodeInfo.Cipher, Cipher: s.Cipher,
} }
p := make([]byte, 32) p := make([]byte, 32)
_, err := rand.Read(p) _, err := rand.Read(p)
@ -248,9 +227,9 @@ func buildShadowsocks(config *conf.Options, nodeInfo *panel.NodeInfo, inbound *c
return fmt.Errorf("generate random password error: %s", err) return fmt.Errorf("generate random password error: %s", err)
} }
randomPasswd := hex.EncodeToString(p) randomPasswd := hex.EncodeToString(p)
cipher := nodeInfo.Cipher cipher := s.Cipher
if nodeInfo.ServerKey != "" { if s.ServerKey != "" {
settings.Password = nodeInfo.ServerKey settings.Password = s.ServerKey
randomPasswd = base64.StdEncoding.EncodeToString([]byte(randomPasswd)) randomPasswd = base64.StdEncoding.EncodeToString([]byte(randomPasswd))
cipher = "" cipher = ""
} }
@ -266,8 +245,8 @@ func buildShadowsocks(config *conf.Options, nodeInfo *panel.NodeInfo, inbound *c
} }
t := coreConf.TransportProtocol("tcp") t := coreConf.TransportProtocol("tcp")
inbound.StreamSetting = &coreConf.StreamConfig{Network: &t} inbound.StreamSetting = &coreConf.StreamConfig{Network: &t}
s, err := json.Marshal(settings) sets, err := json.Marshal(settings)
inbound.Settings = (*json.RawMessage)(&s) inbound.Settings = (*json.RawMessage)(&sets)
if err != nil { if err != nil {
return fmt.Errorf("marshal shadowsocks settings error: %s", err) return fmt.Errorf("marshal shadowsocks settings error: %s", err)
} }

View File

@ -71,21 +71,19 @@ func (c *Core) GetUserTraffic(tag, uuid string, reset bool) (up int64, down int6
} }
func (c *Core) AddUsers(p *vCore.AddUsersParams) (added int, err error) { func (c *Core) AddUsers(p *vCore.AddUsersParams) (added int, err error) {
users := make([]*protocol.User, 0, len(p.UserInfo)) users := make([]*protocol.User, 0, len(p.Users))
switch p.NodeInfo.Type { switch p.NodeInfo.Type {
case "v2ray": case "vmess":
if p.NodeInfo.ExtraConfig.EnableVless == "true" { users = buildVmessUsers(p.Tag, p.Users)
users = buildVlessUsers(p.Tag, p.UserInfo, p.NodeInfo.ExtraConfig.VlessFlow) case "vless":
} else { users = buildVlessUsers(p.Tag, p.Users, p.VAllss.Flow)
users = buildVmessUsers(p.Tag, p.UserInfo)
}
case "trojan": case "trojan":
users = buildTrojanUsers(p.Tag, p.UserInfo) users = buildTrojanUsers(p.Tag, p.Users)
case "shadowsocks": case "shadowsocks":
users = buildSSUsers(p.Tag, users = buildSSUsers(p.Tag,
p.UserInfo, p.Users,
p.NodeInfo.Cipher, p.Shadowsocks.Cipher,
p.NodeInfo.ServerKey) p.Shadowsocks.ServerKey)
default: default:
return 0, fmt.Errorf("unsupported node type: %s", p.NodeInfo.Type) return 0, fmt.Errorf("unsupported node type: %s", p.NodeInfo.Type)
} }

View File

@ -188,7 +188,8 @@ func (c *Core) Close() error {
func (c *Core) Protocols() []string { func (c *Core) Protocols() []string {
return []string{ return []string{
"v2ray", "vmess",
"vless",
"shadowsocks", "shadowsocks",
"trojan", "trojan",
} }

View File

@ -31,7 +31,7 @@ func (c *Controller) renewCertTask() error {
func (c *Controller) requestCert() error { func (c *Controller) requestCert() error {
switch c.CertConfig.CertMode { switch c.CertConfig.CertMode {
case "reality", "none", "": case "none", "":
case "file": case "file":
if c.CertConfig.CertFile == "" || c.CertConfig.KeyFile == "" { if c.CertConfig.CertFile == "" || c.CertConfig.KeyFile == "" {
return fmt.Errorf("cert file path or key file path not exist") return fmt.Errorf("cert file path or key file path not exist")

View File

@ -65,7 +65,7 @@ func (c *Controller) Start() error {
return fmt.Errorf("update rule error: %s", err) return fmt.Errorf("update rule error: %s", err)
} }
c.limiter = l c.limiter = l
if node.Tls || node.Type == "hysteria" { if node.Security == panel.Tls {
err = c.requestCert() err = c.requestCert()
if err != nil { if err != nil {
return fmt.Errorf("request cert error: %s", err) return fmt.Errorf("request cert error: %s", err)
@ -78,8 +78,7 @@ func (c *Controller) Start() error {
} }
added, err := c.server.AddUsers(&vCore.AddUsersParams{ added, err := c.server.AddUsers(&vCore.AddUsersParams{
Tag: c.tag, Tag: c.tag,
Config: c.Options, Users: c.userList,
UserInfo: c.userList,
NodeInfo: node, NodeInfo: node,
}) })
if err != nil { if err != nil {

View File

@ -26,9 +26,9 @@ func (c *Controller) startTasks(node *panel.NodeInfo) {
_ = c.nodeInfoMonitorPeriodic.Start(false) _ = c.nodeInfoMonitorPeriodic.Start(false)
log.WithField("tag", c.tag).Info("Start report node status") log.WithField("tag", c.tag).Info("Start report node status")
_ = c.userReportPeriodic.Start(false) _ = c.userReportPeriodic.Start(false)
if node.Tls { if node.Security == panel.Tls {
switch c.CertConfig.CertMode { switch c.CertConfig.CertMode {
case "reality", "none", "", "file": case "none", "", "file", "self":
default: default:
c.renewCertPeriodic = &task.Task{ c.renewCertPeriodic = &task.Task{
Interval: time.Hour * 24, Interval: time.Hour * 24,
@ -51,7 +51,7 @@ func (c *Controller) startTasks(node *panel.NodeInfo) {
func (c *Controller) nodeInfoMonitor() (err error) { func (c *Controller) nodeInfoMonitor() (err error) {
// get node info // get node info
newNodeInfo, err := c.apiClient.GetNodeInfo() newN, err := c.apiClient.GetNodeInfo()
if err != nil { if err != nil {
log.WithFields(log.Fields{ log.WithFields(log.Fields{
"tag": c.tag, "tag": c.tag,
@ -60,7 +60,7 @@ func (c *Controller) nodeInfoMonitor() (err error) {
return nil return nil
} }
// get user info // get user info
newUserInfo, err := c.apiClient.GetUserList() newU, err := c.apiClient.GetUserList()
if err != nil { if err != nil {
log.WithFields(log.Fields{ log.WithFields(log.Fields{
"tag": c.tag, "tag": c.tag,
@ -68,11 +68,11 @@ func (c *Controller) nodeInfoMonitor() (err error) {
}).Error("Get user list failed") }).Error("Get user list failed")
return nil return nil
} }
if newNodeInfo != nil { if newN != nil {
c.info = newNodeInfo c.info = newN
// nodeInfo changed // nodeInfo changed
if newUserInfo != nil { if newU != nil {
c.userList = newUserInfo c.userList = newU
} }
c.traffic = make(map[string]int64) c.traffic = make(map[string]int64)
// Remove old tag // Remove old tag
@ -88,10 +88,10 @@ func (c *Controller) nodeInfoMonitor() (err error) {
// Remove Old limiter // Remove Old limiter
limiter.DeleteLimiter(c.tag) limiter.DeleteLimiter(c.tag)
// Add new Limiter // Add new Limiter
c.tag = c.buildNodeTag(newNodeInfo) c.tag = c.buildNodeTag(newN)
l := limiter.AddLimiter(c.tag, &c.LimitConfig, c.userList) l := limiter.AddLimiter(c.tag, &c.LimitConfig, c.userList)
// check cert // check cert
if newNodeInfo.Tls || newNodeInfo.Type == "hysteria" { if newN.Security == panel.Tls {
err = c.requestCert() err = c.requestCert()
if err != nil { if err != nil {
log.WithFields(log.Fields{ log.WithFields(log.Fields{
@ -102,7 +102,7 @@ func (c *Controller) nodeInfoMonitor() (err error) {
} }
} }
// add new node // add new node
err = c.server.AddNode(c.tag, newNodeInfo, c.Options) err = c.server.AddNode(c.tag, newN, c.Options)
if err != nil { if err != nil {
log.WithFields(log.Fields{ log.WithFields(log.Fields{
"tag": c.tag, "tag": c.tag,
@ -112,9 +112,8 @@ func (c *Controller) nodeInfoMonitor() (err error) {
} }
_, err = c.server.AddUsers(&vCore.AddUsersParams{ _, err = c.server.AddUsers(&vCore.AddUsersParams{
Tag: c.tag, Tag: c.tag,
Config: c.Options, Users: c.userList,
UserInfo: c.userList, NodeInfo: newN,
NodeInfo: newNodeInfo,
}) })
if err != nil { if err != nil {
log.WithFields(log.Fields{ log.WithFields(log.Fields{
@ -123,7 +122,7 @@ func (c *Controller) nodeInfoMonitor() (err error) {
}).Error("Add users failed") }).Error("Add users failed")
return nil return nil
} }
err = l.UpdateRule(&newNodeInfo.Rules) err = l.UpdateRule(&newN.Rules)
if err != nil { if err != nil {
log.WithFields(log.Fields{ log.WithFields(log.Fields{
"tag": c.tag, "tag": c.tag,
@ -133,15 +132,15 @@ func (c *Controller) nodeInfoMonitor() (err error) {
} }
c.limiter = l c.limiter = l
// Check interval // Check interval
if c.nodeInfoMonitorPeriodic.Interval != newNodeInfo.PullInterval && if c.nodeInfoMonitorPeriodic.Interval != newN.PullInterval &&
newNodeInfo.PullInterval != 0 { newN.PullInterval != 0 {
c.nodeInfoMonitorPeriodic.Interval = newNodeInfo.PullInterval c.nodeInfoMonitorPeriodic.Interval = newN.PullInterval
c.nodeInfoMonitorPeriodic.Close() c.nodeInfoMonitorPeriodic.Close()
_ = c.nodeInfoMonitorPeriodic.Start(false) _ = c.nodeInfoMonitorPeriodic.Start(false)
} }
if c.userReportPeriodic.Interval != newNodeInfo.PushInterval && if c.userReportPeriodic.Interval != newN.PushInterval &&
newNodeInfo.PushInterval != 0 { newN.PushInterval != 0 {
c.userReportPeriodic.Interval = newNodeInfo.PullInterval c.userReportPeriodic.Interval = newN.PullInterval
c.userReportPeriodic.Close() c.userReportPeriodic.Close()
_ = c.userReportPeriodic.Start(false) _ = c.userReportPeriodic.Start(false)
} }
@ -151,10 +150,10 @@ func (c *Controller) nodeInfoMonitor() (err error) {
} }
// node no changed, check users // node no changed, check users
if len(newUserInfo) == 0 { if len(newU) == 0 {
return nil return nil
} }
deleted, added := compareUserList(c.userList, newUserInfo) deleted, added := compareUserList(c.userList, newU)
if len(deleted) > 0 { if len(deleted) > 0 {
// have deleted users // have deleted users
err = c.server.DelUsers(deleted, c.tag) err = c.server.DelUsers(deleted, c.tag)
@ -170,9 +169,8 @@ func (c *Controller) nodeInfoMonitor() (err error) {
// have added users // have added users
_, err = c.server.AddUsers(&vCore.AddUsersParams{ _, err = c.server.AddUsers(&vCore.AddUsersParams{
Tag: c.tag, Tag: c.tag,
Config: c.Options,
NodeInfo: c.info, NodeInfo: c.info,
UserInfo: added, Users: added,
}) })
if err != nil { if err != nil {
log.WithFields(log.Fields{ log.WithFields(log.Fields{
@ -199,7 +197,7 @@ func (c *Controller) nodeInfoMonitor() (err error) {
} }
} }
} }
c.userList = newUserInfo c.userList = newU
if len(added)+len(deleted) != 0 { if len(added)+len(deleted) != 0 {
log.WithField("tag", c.tag). log.WithField("tag", c.tag).
Infof("%d user deleted, %d user added", len(deleted), len(added)) Infof("%d user deleted, %d user added", len(deleted), len(added))