Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
125 changes: 49 additions & 76 deletions proxy/hysteria/account/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,25 +3,32 @@ package account
import (
"sync"

"github.com/xtls/xray-core/common/errors"
"github.com/xtls/xray-core/common/net"
"github.com/xtls/xray-core/common/protocol"
"github.com/xtls/xray-core/common/uuid"

"google.golang.org/protobuf/proto"
)

func (a *Account) AsAccount() (protocol.Account, error) {
var VR net.Port
if id, err := uuid.ParseString(a.Auth); err == nil {
VR = net.PortFromBytes(id[6:8])
}
return &MemoryAccount{
Auth: a.Auth,
VR: VR,
}, nil
}

type MemoryAccount struct {
Auth string
VR net.Port
}

func (a *MemoryAccount) Equals(another protocol.Account) bool {
if account, ok := another.(*MemoryAccount); ok {
return a.Auth == account.Auth
func (a *MemoryAccount) Equals(other protocol.Account) bool {
if b, ok := other.(*MemoryAccount); ok {
return a.Auth == b.Auth
}
return false
}
Expand All @@ -33,97 +40,63 @@ func (a *MemoryAccount) ToProto() proto.Message {
}

type Validator struct {
emails map[string]struct{}
users map[string]*protocol.MemoryUser

mutex sync.Mutex
users sync.Map
}

func NewValidator() *Validator {
return &Validator{
emails: make(map[string]struct{}),
users: make(map[string]*protocol.MemoryUser),
}
return &Validator{}
}

func (v *Validator) Add(u *protocol.MemoryUser) error {
v.mutex.Lock()
defer v.mutex.Unlock()

if u.Email != "" {
if _, ok := v.emails[u.Email]; ok {
return errors.New("User ", u.Email, " already exists.")
}
v.emails[u.Email] = struct{}{}
}
v.users[u.Account.(*MemoryAccount).Auth] = u

func (v *Validator) Add(user *protocol.MemoryUser) error {
v.users.Store(user.Account.(*MemoryAccount).Auth, user)
return nil
}

func (v *Validator) Del(email string) error {
if email == "" {
return errors.New("Email must not be empty.")
func (v *Validator) DelByEmail(email string) error {
if user := v.GetByEmail(email); user != nil {
v.users.Delete(user.Account.(*MemoryAccount).Auth)
}

v.mutex.Lock()
defer v.mutex.Unlock()

if _, ok := v.emails[email]; !ok {
return errors.New("User ", email, " not found.")
}
delete(v.emails, email)
for key, user := range v.users {
if user.Email == email {
delete(v.users, key)
break
}
}

return nil
}

func (v *Validator) Get(auth string) *protocol.MemoryUser {
v.mutex.Lock()
defer v.mutex.Unlock()

return v.users[auth]
}

func (v *Validator) GetByEmail(email string) *protocol.MemoryUser {
if email == "" {
return nil
}

v.mutex.Lock()
defer v.mutex.Unlock()

if _, ok := v.emails[email]; ok {
for _, user := range v.users {
if user.Email == email {
return user
}
}
if value, ok := v.users.Load(auth); ok {
return value.(*protocol.MemoryUser)
}

return nil
}

func (v *Validator) GetAll() []*protocol.MemoryUser {
v.mutex.Lock()
defer v.mutex.Unlock()

users := make([]*protocol.MemoryUser, 0, len(v.users))
for _, user := range v.users {
users = append(users, user)
}
func (v *Validator) GetByEmail(email string) (user *protocol.MemoryUser) {
v.users.Range(func(key, value any) bool {
if value.(*protocol.MemoryUser).Email == email {
user = value.(*protocol.MemoryUser)
return false
}
return true
})
return
}

return users
func (v *Validator) GetAll() (users []*protocol.MemoryUser) {
v.users.Range(func(key, value any) bool {
users = append(users, value.(*protocol.MemoryUser))
return true
})
return
}

func (v *Validator) GetCount() int64 {
v.mutex.Lock()
defer v.mutex.Unlock()
func (v *Validator) GetCount() (count int64) {
v.users.Range(func(key, value any) bool {
count++
return true
})
return
}

return int64(len(v.users))
func (v *Validator) NotEmpty() (not_empty bool) {
v.users.Range(func(key, value any) bool {
not_empty = true
return false
})
return
}
17 changes: 10 additions & 7 deletions proxy/hysteria/server.go
Original file line number Diff line number Diff line change
Expand Up @@ -59,12 +59,12 @@ func (s *Server) HysteriaInboundValidator() *account.Validator {
return s.validator
}

func (s *Server) AddUser(ctx context.Context, u *protocol.MemoryUser) error {
return s.validator.Add(u)
func (s *Server) AddUser(ctx context.Context, user *protocol.MemoryUser) error {
return s.validator.Add(user)
}

func (s *Server) RemoveUser(ctx context.Context, e string) error {
return s.validator.Del(e)
func (s *Server) RemoveUser(ctx context.Context, email string) error {
return s.validator.DelByEmail(email)
}

func (s *Server) GetUser(ctx context.Context, email string) *protocol.MemoryUser {
Expand All @@ -91,9 +91,12 @@ func (s *Server) Process(ctx context.Context, network net.Network, conn stat.Con

iConn := stat.TryUnwrapStatsConn(conn)

type User interface{ User() *protocol.MemoryUser }
if v, ok := iConn.(User); ok && v.User() != nil {
inbound.User = v.User()
if v, ok := iConn.(interface{ User() *protocol.MemoryUser }); ok {
user := v.User()
if user != nil {
inbound.User = user
inbound.VlessRoute = user.Account.(*account.MemoryAccount).VR
}
}

if _, ok := iConn.(*hysteria.InterConn); ok {
Expand Down
2 changes: 1 addition & 1 deletion transport/internet/hysteria/hub.go
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@ func (h *httpHandler) AuthHTTP(w http.ResponseWriter, r *http.Request) bool {

var user *protocol.MemoryUser
var ok bool
if h.validator != nil && h.validator.GetCount() > 0 {
if h.validator != nil && h.validator.NotEmpty() {
user = h.validator.Get(auth)
} else if h.config.Auth != "" {
ok = auth == h.config.Auth
Expand Down