From a5c648340243e6c48c8a40a57c9809bc704952a9 Mon Sep 17 00:00:00 2001 From: yuzuki999 Date: Fri, 3 Jun 2022 01:22:56 +0800 Subject: [PATCH] fix bugs --- api/apimodel.go | 24 ++++--- api/v2board/v2board.go | 66 ++++++++++++------- common/limiter/limiter.go | 16 ++--- service/controller/control.go | 8 +-- service/controller/controller.go | 94 +++++++++++++++++++--------- service/controller/inboundbuilder.go | 29 ++++----- service/controller/userbuilder.go | 82 ++++++++++++++++-------- 7 files changed, 205 insertions(+), 114 deletions(-) diff --git a/api/apimodel.go b/api/apimodel.go index 7c1b9f2..44c1d18 100644 --- a/api/apimodel.go +++ b/api/apimodel.go @@ -59,15 +59,19 @@ type TrojanUserInfo struct { Password string `json:"password"` } type UserInfo struct { - UID int `json:"id"` DeviceLimit int `json:"device_limit"` SpeedLimit uint64 `json:"speed_limit"` + UID int `json:"id"` Port int `json:"port"` Cipher string `json:"cipher"` Secret string `json:"secret"` V2rayUser *V2RayUserInfo `json:"v2ray_user"` TrojanUser *TrojanUserInfo `json:"trojan_user"` } +type UserListBody struct { + //Msg string `json:"msg"` + Data []UserInfo `json:"data"` +} func (p *UserInfo) GetUserEmail() string { if p.V2rayUser != nil { @@ -79,14 +83,16 @@ func (p *UserInfo) GetUserEmail() string { } type NodeInfo struct { - NodeType string - NodeId int - TLSType string - EnableVless bool - EnableTls bool - V2ray *V2rayConfig - Trojan *TrojanConfig - SS *SSConfig + RspMd5 string + NodeType string + NodeId int + TLSType string + EnableVless bool + EnableTls bool + EnableSS2022 bool + V2ray *V2rayConfig + Trojan *TrojanConfig + SS *SSConfig } type SSConfig struct { diff --git a/api/v2board/v2board.go b/api/v2board/v2board.go index 94cedb0..52375bf 100644 --- a/api/v2board/v2board.go +++ b/api/v2board/v2board.go @@ -2,10 +2,11 @@ package v2board import ( "bufio" + md52 "crypto/md5" "fmt" "github.com/Yuzuki616/V2bX/api" "github.com/go-resty/resty/v2" - json "github.com/goccy/go-json" + "github.com/goccy/go-json" "log" "os" "regexp" @@ -16,18 +17,21 @@ import ( // APIClient create an api client to the panel. type APIClient struct { - client *resty.Client - APIHost string - NodeID int - Key string - NodeType string - EnableVless bool - EnableXTLS bool - SpeedLimit float64 - DeviceLimit int - LocalRuleList []api.DetectRule - RemoteRuleCache *api.Rule - access sync.Mutex + client *resty.Client + APIHost string + NodeID int + Key string + NodeType string + EnableSS2022 bool + EnableVless bool + EnableXTLS bool + SpeedLimit float64 + DeviceLimit int + LocalRuleList []api.DetectRule + RemoteRuleCache *api.Rule + access sync.Mutex + NodeInfoRspMd5 [16]byte + UserListCheckNum int } // New create an api instance @@ -61,6 +65,7 @@ func New(apiConfig *api.Config) *APIClient { Key: apiConfig.Key, APIHost: apiConfig.APIHost, NodeType: apiConfig.NodeType, + EnableSS2022: apiConfig.EnableSS2022, EnableVless: apiConfig.EnableVless, EnableXTLS: apiConfig.EnableXTLS, SpeedLimit: apiConfig.SpeedLimit, @@ -96,7 +101,7 @@ func readLocalRuleList(path string) (LocalRuleList []api.DetectRule) { // handle first encountered error while reading if err := fileScanner.Err(); err != nil { log.Fatalf("Error while reading file: %s", err) - return make([]api.DetectRule, 0) + return []api.DetectRule{} } file.Close() @@ -153,6 +158,13 @@ func (c *APIClient) GetNodeInfo() (nodeInfo *api.NodeInfo, err error) { default: return nil, fmt.Errorf("unsupported Node type: %s", c.NodeType) } + md := md52.Sum(res.Body()) + if c.NodeInfoRspMd5 != [16]byte{} { + if c.NodeInfoRspMd5 == md { + return nil, nil + } + } + c.NodeInfoRspMd5 = md res, err = c.client.R(). SetQueryParam("local_port", "1"). ForceContentType("application/json"). @@ -168,10 +180,6 @@ func (c *APIClient) GetNodeInfo() (nodeInfo *api.NodeInfo, err error) { nodeInfo, err = c.ParseV2rayNodeResponse(res.Body()) case "Trojan": nodeInfo, err = c.ParseTrojanNodeResponse(res.Body()) - case "Shadowsocks": - nodeInfo, err = c.ParseSSNodeResponse() - default: - return nil, fmt.Errorf("unsupported Node type: %s", c.NodeType) } return nodeInfo, nil } @@ -192,16 +200,25 @@ func (c *APIClient) GetUserList() (UserList *[]api.UserInfo, err error) { res, err := c.client.R(). ForceContentType("application/json"). Get(path) - var userList []api.UserInfo err = c.checkResponse(res, path, err) if err != nil { return nil, err } + var userList *api.UserListBody err = json.Unmarshal(res.Body(), &userList) if err != nil { return nil, fmt.Errorf("unmarshal userlist error: %s", err) } - return &userList, nil + checkNum := userList.Data[len(userList.Data)-1].UID + + userList.Data[len(userList.Data)/2-1].UID + + userList.Data[0].UID + if c.UserListCheckNum != 0 { + if c.UserListCheckNum == checkNum { + return nil, nil + } + } + c.UserListCheckNum = userList.Data[len(userList.Data)-1].UID + return &userList.Data, nil } // ReportUserTraffic reports the user traffic @@ -286,8 +303,9 @@ func (c *APIClient) ParseSSNodeResponse() (*api.NodeInfo, error) { return nil, err } node := &api.NodeInfo{ - NodeType: c.NodeType, - NodeId: c.NodeID, + EnableSS2022: c.EnableSS2022, + NodeType: c.NodeType, + NodeId: c.NodeID, SS: &api.SSConfig{ Port: port, TransportProtocol: "tcp", @@ -300,6 +318,10 @@ func (c *APIClient) ParseSSNodeResponse() (*api.NodeInfo, error) { // ParseV2rayNodeResponse parse the response for the given nodeinfor format func (c *APIClient) ParseV2rayNodeResponse(body []byte) (*api.NodeInfo, error) { node := &api.NodeInfo{V2ray: &api.V2rayConfig{}} + err := json.Unmarshal(body, node.V2ray) + if err != nil { + return nil, fmt.Errorf("unmarshal nodeinfo error: %s", err) + } node.NodeType = c.NodeType node.NodeId = c.NodeID c.RemoteRuleCache = &node.V2ray.Routing.Rules[0] diff --git a/common/limiter/limiter.go b/common/limiter/limiter.go index 6e84928..e0061ef 100644 --- a/common/limiter/limiter.go +++ b/common/limiter/limiter.go @@ -54,18 +54,18 @@ func (l *Limiter) AddInboundLimiter(tag string, nodeSpeedLimit uint64, userList return nil } -func (l *Limiter) UpdateInboundLimiter(tag string, updatedUserList *[]api.UserInfo) error { +func (l *Limiter) UpdateInboundLimiter(tag string, updatedUserList *[]api.UserInfo, usersIndex *[]int) error { if value, ok := l.InboundInfo.Load(tag); ok { inboundInfo := value.(*InboundInfo) // Update User info - for _, u := range *updatedUserList { - inboundInfo.UserInfo.Store(fmt.Sprintf("%s|%s|%d", tag, u.GetUserEmail(), u.UID), UserInfo{ - UID: u.UID, - SpeedLimit: u.SpeedLimit, - DeviceLimit: u.DeviceLimit, + for _, u := range *usersIndex { + inboundInfo.UserInfo.Store(fmt.Sprintf("%s|%s|%d", tag, (*updatedUserList)[u].GetUserEmail(), (*updatedUserList)[u].UID), UserInfo{ + UID: (*updatedUserList)[u].UID, + SpeedLimit: (*updatedUserList)[u].SpeedLimit, + DeviceLimit: (*updatedUserList)[u].DeviceLimit, }) - inboundInfo.BucketHub.Delete(fmt.Sprintf("%s|%s|%d", tag, u.GetUserEmail(), u.UID)) // Delete old limiter bucket + inboundInfo.BucketHub.Delete(fmt.Sprintf("%s|%s|%d", tag, (*updatedUserList)[u].GetUserEmail(), (*updatedUserList)[u].UID)) // Delete old limiter bucket } } else { return fmt.Errorf("no such inbound in limiter: %s", tag) @@ -142,7 +142,7 @@ func (l *Limiter) GetUserBucket(tag string, email string, ip string) (limiter *r } limit := determineRate(nodeLimit, userLimit) // If need the Speed limit if limit > 0 { - limiter := ratelimit.NewBucketWithQuantum(time.Duration(time.Second), int64(limit), int64(limit)) // Byte/s + limiter := ratelimit.NewBucketWithQuantum(time.Second, int64(limit), int64(limit)) // Byte/s if v, ok := inboundInfo.BucketHub.LoadOrStore(email, limiter); ok { bucket := v.(*ratelimit.Bucket) return bucket, true, false diff --git a/service/controller/control.go b/service/controller/control.go index 67ceb12..45fe3b6 100644 --- a/service/controller/control.go +++ b/service/controller/control.go @@ -63,7 +63,7 @@ func (c *Controller) addUsers(users []*protocol.User, tag string) error { inboundManager := c.server.GetFeature(inbound.ManagerType()).(inbound.Manager) handler, err := inboundManager.GetHandler(context.Background(), tag) if err != nil { - return fmt.Errorf("No such inbound tag: %s", err) + return fmt.Errorf("no such inbound tag: %s", err) } inboundInstance, ok := handler.(proxy.GetInbound) if !ok { @@ -91,7 +91,7 @@ func (c *Controller) removeUsers(users []string, tag string) error { inboundManager := c.server.GetFeature(inbound.ManagerType()).(inbound.Manager) handler, err := inboundManager.GetHandler(context.Background(), tag) if err != nil { - return fmt.Errorf("No such inbound tag: %s", err) + return fmt.Errorf("no such inbound tag: %s", err) } inboundInstance, ok := handler.(proxy.GetInbound) if !ok { @@ -135,9 +135,9 @@ func (c *Controller) AddInboundLimiter(tag string, nodeSpeedLimit uint64, userLi return err } -func (c *Controller) UpdateInboundLimiter(tag string, updatedUserList *[]api.UserInfo) error { +func (c *Controller) UpdateInboundLimiter(tag string, updatedUserList *[]api.UserInfo, usersIndex *[]int) error { dispather := c.server.GetFeature(routing.DispatcherType()).(*mydispatcher.DefaultDispatcher) - err := dispather.Limiter.UpdateInboundLimiter(tag, updatedUserList) + err := dispather.Limiter.UpdateInboundLimiter(tag, updatedUserList, usersIndex) return err } diff --git a/service/controller/controller.go b/service/controller/controller.go index bf15e5f..f4790ee 100644 --- a/service/controller/controller.go +++ b/service/controller/controller.go @@ -4,7 +4,6 @@ import ( "fmt" "log" "math" - "reflect" "time" "github.com/Yuzuki616/V2bX/api" @@ -65,6 +64,9 @@ func (c *Controller) Start() error { } //sync controller userList c.userList = userInfo + if err := c.AddInboundLimiter(c.Tag, 0, userInfo); err != nil { + log.Print(err) + } // Add Rule Manager if !c.config.DisableGetRule { if ruleList, err := c.apiClient.GetNodeRule(); err != nil { @@ -124,7 +126,6 @@ func (c *Controller) nodeInfoMonitor() (err error) { log.Print(err) return nil } - // Update User newUserInfo, err := c.apiClient.GetUserList() if err != nil { @@ -134,7 +135,7 @@ func (c *Controller) nodeInfoMonitor() (err error) { var nodeInfoChanged = false // If nodeInfo changed - if !reflect.DeepEqual(c.nodeInfo, newNodeInfo) { + if newNodeInfo != nil { // Remove old tag oldtag := c.Tag err := c.removeOldTag(oldtag) @@ -142,13 +143,6 @@ func (c *Controller) nodeInfoMonitor() (err error) { log.Print(err) return nil } - if c.nodeInfo.NodeType == "Shadowsocks-Plugin" { - err = c.removeOldTag(fmt.Sprintf("dokodemo-door_%s+1", c.Tag)) - } - if err != nil { - log.Print(err) - return nil - } // Add new tag c.nodeInfo = newNodeInfo c.Tag = c.buildNodeTag() @@ -188,7 +182,9 @@ func (c *Controller) nodeInfoMonitor() (err error) { log.Print(err) } } - + if newUserInfo == nil { + return nil + } if nodeInfoChanged { err = c.addNewUser(newUserInfo, newNodeInfo) if err != nil { @@ -199,8 +195,10 @@ func (c *Controller) nodeInfoMonitor() (err error) { deleted, added := compareUserList(c.userList, newUserInfo) if len(deleted) > 0 { deletedEmail := make([]string, len(deleted)) - for i, u := range deleted { - deletedEmail[i] = fmt.Sprintf("%s|%d|%d", c.Tag, c.nodeInfo.NodeId, u.UID) + for i := range deleted { + deletedEmail[i] = fmt.Sprintf("%s|%s|%d", c.Tag, + (*c.userList)[deleted[i]].GetUserEmail(), + (*c.userList)[deleted[i]].UID) } err := c.removeUsers(deletedEmail, c.Tag) if err != nil { @@ -208,12 +206,17 @@ func (c *Controller) nodeInfoMonitor() (err error) { } } if len(added) > 0 { - err = c.addNewUser(&added, c.nodeInfo) + err = c.addNewUserFromIndex(newUserInfo, &added, c.nodeInfo) if err != nil { log.Print(err) } + // Add Limiter + if err := c.AddInboundLimiter(c.Tag, 0, newUserInfo); err != nil { + log.Print(err) + return nil + } // Update Limiter - if err := c.UpdateInboundLimiter(c.Tag, &added); err != nil { + if err := c.UpdateInboundLimiter(c.Tag, newUserInfo, &added); err != nil { log.Print(err) } } @@ -263,21 +266,21 @@ func (c *Controller) addNewUser(userInfo *[]api.UserInfo, nodeInfo *api.NodeInfo users := make([]*protocol.User, 0) if nodeInfo.NodeType == "V2ray" { if nodeInfo.EnableVless { - users = c.buildVlessUser(userInfo) + users = c.buildVlessUsers(userInfo) } else { alterID := 0 alterID = (*userInfo)[0].V2rayUser.AlterId if alterID >= 0 && alterID < math.MaxUint16 { - users = c.buildVmessUser(userInfo, uint16(alterID)) + users = c.buildVmessUsers(userInfo, uint16(alterID)) } else { - users = c.buildVmessUser(userInfo, 0) + users = c.buildVmessUsers(userInfo, 0) return fmt.Errorf("AlterID should between 0 to 1<<16 - 1, set it to 0 for now") } } } else if nodeInfo.NodeType == "Trojan" { - users = c.buildTrojanUser(userInfo) + users = c.buildTrojanUsers(userInfo) } else if nodeInfo.NodeType == "Shadowsocks" { - users = c.buildSSUser(userInfo, nodeInfo.SS.CypherMethod) + users = c.buildSSUsers(userInfo, nodeInfo.SS.CypherMethod) } else { return fmt.Errorf("unsupported node type: %s", nodeInfo.NodeType) } @@ -289,28 +292,59 @@ func (c *Controller) addNewUser(userInfo *[]api.UserInfo, nodeInfo *api.NodeInfo return nil } -func compareUserList(old, new *[]api.UserInfo) (deleted, added []api.UserInfo) { +func (c *Controller) addNewUserFromIndex(userInfo *[]api.UserInfo, userIndex *[]int, nodeInfo *api.NodeInfo) (err error) { + users := make([]*protocol.User, 0, len(*userIndex)) + for _, v := range *userIndex { + if nodeInfo.NodeType == "V2ray" { + if nodeInfo.EnableVless { + users = append(users, c.buildVlessUser(&(*userInfo)[v])) + } else { + alterID := 0 + alterID = (*userInfo)[0].V2rayUser.AlterId + if alterID >= 0 && alterID < math.MaxUint16 { + users = append(users, c.buildVmessUser(&(*userInfo)[v], uint16(alterID))) + } else { + users = append(users, c.buildVmessUser(&(*userInfo)[v], 0)) + return fmt.Errorf("AlterID should between 0 to 1<<16 - 1, set it to 0 for now") + } + } + } else if nodeInfo.NodeType == "Trojan" { + users = append(users, c.buildTrojanUser(&(*userInfo)[v])) + } else if nodeInfo.NodeType == "Shadowsocks" { + users = append(users, c.buildSSUser(&(*userInfo)[v], nodeInfo.SS.CypherMethod)) + } else { + return fmt.Errorf("unsupported node type: %s", nodeInfo.NodeType) + } + } + err = c.addUsers(users, c.Tag) + if err != nil { + return err + } + log.Printf("[%s: %d] Added %d new users", c.nodeInfo.NodeType, c.nodeInfo.NodeId, len(*userIndex)) + return nil +} + +func compareUserList(old, new *[]api.UserInfo) (deleted, added []int) { tmp := map[int]int{} + tmp2 := map[int]int{} for i := range *old { tmp[(*old)[i].UID] = i } l := len(tmp) for i := range *new { tmp[(*new)[i].UID] = i + tmp2[(*new)[i].UID] = i if l != len(tmp) { - tmp[(*new)[i].UID] = i - added = append(added, (*new)[i]) + added = append(added, i) l++ - } else { - delete(tmp, (*new)[i].UID) - l-- } } + tmp = nil + l = len(tmp2) for i := range *old { - tmp[(*old)[i].UID] = i - if l == len(tmp) { - deleted = append(deleted, (*old)[i]) - } else { + tmp2[(*old)[i].UID] = i + if l != len(tmp2) { + deleted = append(deleted, i) l++ } } diff --git a/service/controller/inboundbuilder.go b/service/controller/inboundbuilder.go index 0b05de2..cdd0e03 100644 --- a/service/controller/inboundbuilder.go +++ b/service/controller/inboundbuilder.go @@ -62,8 +62,7 @@ func InboundBuilder(config *Config, nodeInfo *api.NodeInfo, tag string) (*core.I nodeInfo.V2ray.Inbounds[0].StreamSetting = &conf.StreamConfig{Network: &t} } else if nodeInfo.NodeType == "Shadowsocks" { nodeInfo.V2ray = &api.V2rayConfig{} - nodeInfo.V2ray.Inbounds = make([]conf.InboundDetourConfig, 1) - nodeInfo.V2ray.Inbounds[0].Protocol = "shadowsocks" + nodeInfo.V2ray.Inbounds = []conf.InboundDetourConfig{{Protocol: "shadowsocks"}} proxySetting = &conf.ShadowsocksServerConfig{} randomPasswd := uuid.New() defaultSSuser := &conf.ShadowsocksUserConfig{ @@ -82,7 +81,9 @@ func InboundBuilder(config *Config, nodeInfo *api.NodeInfo, tag string) (*core.I } t := conf.TransportProtocol(nodeInfo.SS.TransportProtocol) nodeInfo.V2ray.Inbounds[0].StreamSetting = &conf.StreamConfig{Network: &t} - } else if nodeInfo.NodeType == "dokodemo-door" { + } else { + return nil, fmt.Errorf("unsupported node type: %s, Only support: V2ray, Trojan, Shadowsocks, and Shadowsocks-Plugin", nodeInfo.NodeType) + } /*else if nodeInfo.NodeType == "dokodemo-door" { nodeInfo.V2ray = &api.V2rayConfig{} nodeInfo.V2ray.Inbounds = make([]conf.InboundDetourConfig, 1) nodeInfo.V2ray.Inbounds[0].Protocol = "dokodemo-door" @@ -93,9 +94,7 @@ func InboundBuilder(config *Config, nodeInfo *api.NodeInfo, tag string) (*core.I Host: "v1.mux.cool", NetworkList: []string{"tcp", "udp"}, } - } else { - return nil, fmt.Errorf("unsupported node type: %s, Only support: V2ray, Trojan, Shadowsocks, and Shadowsocks-Plugin", nodeInfo.NodeType) - } + }*/ // Build Listen IP address ipAddress := net.ParseAddress(config.ListenIP) nodeInfo.V2ray.Inbounds[0].ListenOn = &conf.Address{Address: ipAddress} @@ -120,13 +119,15 @@ func InboundBuilder(config *Config, nodeInfo *api.NodeInfo, tag string) (*core.I if *nodeInfo.V2ray.Inbounds[0].StreamSetting.Network == "tcp" { if nodeInfo.NodeType == "V2ray" { nodeInfo.V2ray.Inbounds[0].StreamSetting.TCPSettings.AcceptProxyProtocol = config.EnableProxyProtocol + } else { + tcpSetting := &conf.TCPConfig{ + AcceptProxyProtocol: config.EnableProxyProtocol, + } + nodeInfo.V2ray.Inbounds[0].StreamSetting.TCPSettings = tcpSetting } - tcpSetting := &conf.TCPConfig{ - AcceptProxyProtocol: config.EnableProxyProtocol, - } - nodeInfo.V2ray.Inbounds[0].StreamSetting.TCPSettings = tcpSetting - } else if *nodeInfo.V2ray.Inbounds[0].StreamSetting.Network == "websocket" { - nodeInfo.V2ray.Inbounds[0].StreamSetting.WSSettings.AcceptProxyProtocol = config.EnableProxyProtocol + } else if *nodeInfo.V2ray.Inbounds[0].StreamSetting.Network == "ws" { + nodeInfo.V2ray.Inbounds[0].StreamSetting.WSSettings = &conf.WebSocketConfig{ + AcceptProxyProtocol: config.EnableProxyProtocol} } // Build TLS and XTLS settings if nodeInfo.EnableTls && config.CertConfig.CertMode != "none" { @@ -162,8 +163,8 @@ func InboundBuilder(config *Config, nodeInfo *api.NodeInfo, tag string) (*core.I } nodeInfo.V2ray.Inbounds[0].StreamSetting.SocketSettings = sockoptConfig } - *nodeInfo.V2ray.Inbounds[0].Settings = setting - + nodeInfo.V2ray.Inbounds[0].Settings = &setting + nodeInfo.V2ray.Inbounds[0].Tag = tag return nodeInfo.V2ray.Inbounds[0].Build() } diff --git a/service/controller/userbuilder.go b/service/controller/userbuilder.go index 1389e06..e22a92e 100644 --- a/service/controller/userbuilder.go +++ b/service/controller/userbuilder.go @@ -13,9 +13,7 @@ import ( "github.com/xtls/xray-core/proxy/vless" ) -var AEADMethod = []shadowsocks.CipherType{shadowsocks.CipherType_AES_128_GCM, shadowsocks.CipherType_AES_256_GCM, shadowsocks.CipherType_CHACHA20_POLY1305, shadowsocks.CipherType_XCHACHA20_POLY1305} - -func (c *Controller) buildVmessUser(userInfo *[]api.UserInfo, serverAlterID uint16) (users []*protocol.User) { +func (c *Controller) buildVmessUsers(userInfo *[]api.UserInfo, serverAlterID uint16) (users []*protocol.User) { users = make([]*protocol.User, len(*userInfo)) for i, user := range *userInfo { vmessAccount := &conf.VMessAccount{ @@ -32,7 +30,21 @@ func (c *Controller) buildVmessUser(userInfo *[]api.UserInfo, serverAlterID uint return users } -func (c *Controller) buildVlessUser(userInfo *[]api.UserInfo) (users []*protocol.User) { +func (c *Controller) buildVmessUser(userInfo *api.UserInfo, serverAlterID uint16) (user *protocol.User) { + vmessAccount := &conf.VMessAccount{ + ID: userInfo.V2rayUser.Uuid, + AlterIds: serverAlterID, + Security: "auto", + } + user = &protocol.User{ + Level: 0, + Email: c.buildUserTag(userInfo), // Email: InboundTag|email|uid + Account: serial.ToTypedMessage(vmessAccount.Build()), + } + return user +} + +func (c *Controller) buildVlessUsers(userInfo *[]api.UserInfo) (users []*protocol.User) { users = make([]*protocol.User, len(*userInfo)) for i, user := range *userInfo { vlessAccount := &vless.Account{ @@ -48,7 +60,20 @@ func (c *Controller) buildVlessUser(userInfo *[]api.UserInfo) (users []*protocol return users } -func (c *Controller) buildTrojanUser(userInfo *[]api.UserInfo) (users []*protocol.User) { +func (c *Controller) buildVlessUser(userInfo *api.UserInfo) (user *protocol.User) { + vlessAccount := &vless.Account{ + Id: userInfo.V2rayUser.Uuid, + Flow: "xtls-rprx-direct", + } + user = &protocol.User{ + Level: 0, + Email: c.buildUserTag(userInfo), + Account: serial.ToTypedMessage(vlessAccount), + } + return user +} + +func (c *Controller) buildTrojanUsers(userInfo *[]api.UserInfo) (users []*protocol.User) { users = make([]*protocol.User, len(*userInfo)) for i, user := range *userInfo { trojanAccount := &trojan.Account{ @@ -64,6 +89,19 @@ func (c *Controller) buildTrojanUser(userInfo *[]api.UserInfo) (users []*protoco return users } +func (c *Controller) buildTrojanUser(userInfo *api.UserInfo) (user *protocol.User) { + trojanAccount := &trojan.Account{ + Password: userInfo.V2rayUser.Uuid, + Flow: "xtls-rprx-direct", + } + user = &protocol.User{ + Level: 0, + Email: c.buildUserTag(userInfo), + Account: serial.ToTypedMessage(trojanAccount), + } + return user +} + func cipherFromString(c string) shadowsocks.CipherType { switch strings.ToLower(c) { case "aes-128-gcm", "aead_aes_128_gcm": @@ -79,7 +117,7 @@ func cipherFromString(c string) shadowsocks.CipherType { } } -func (c *Controller) buildSSUser(userInfo *[]api.UserInfo, method string) (users []*protocol.User) { +func (c *Controller) buildSSUsers(userInfo *[]api.UserInfo, method string) (users []*protocol.User) { users = make([]*protocol.User, 0) cypherMethod := cipherFromString(method) @@ -97,28 +135,18 @@ func (c *Controller) buildSSUser(userInfo *[]api.UserInfo, method string) (users return users } -func (c *Controller) buildSSPluginUser(userInfo *[]api.UserInfo) (users []*protocol.User) { - users = make([]*protocol.User, 0) - - for _, user := range *userInfo { - // Check if the cypher method is AEAD - cypherMethod := cipherFromString(user.Cipher) - for _, aeadMethod := range AEADMethod { - if aeadMethod == cypherMethod { - ssAccount := &shadowsocks.Account{ - Password: user.Secret, - CipherType: cypherMethod, - } - users = append(users, &protocol.User{ - Level: 0, - Email: c.buildUserTag(&user), - Account: serial.ToTypedMessage(ssAccount), - }) - } - } - +func (c *Controller) buildSSUser(userInfo *api.UserInfo, method string) (user *protocol.User) { + cypherMethod := cipherFromString(method) + ssAccount := &shadowsocks.Account{ + Password: userInfo.Secret, + CipherType: cypherMethod, } - return users + user = &protocol.User{ + Level: 0, + Email: c.buildUserTag(userInfo), + Account: serial.ToTypedMessage(ssAccount), + } + return user } func (c *Controller) buildUserTag(user *api.UserInfo) string {