diff --git a/proxy/hysteria/account/config.go b/proxy/hysteria/account/config.go index 63ecaf652956..299104585440 100644 --- a/proxy/hysteria/account/config.go +++ b/proxy/hysteria/account/config.go @@ -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 } @@ -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 } diff --git a/proxy/hysteria/server.go b/proxy/hysteria/server.go index d7456dc304b8..1e54b654bfc6 100644 --- a/proxy/hysteria/server.go +++ b/proxy/hysteria/server.go @@ -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 { @@ -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 { diff --git a/transport/internet/hysteria/hub.go b/transport/internet/hysteria/hub.go index d20313b5d031..59bcd7d4251f 100644 --- a/transport/internet/hysteria/hub.go +++ b/transport/internet/hysteria/hub.go @@ -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