mirror of https://github.com/v2ray/v2ray-core
Introduce user level
parent
d585ec0593
commit
b44098d752
|
@ -10,12 +10,14 @@ import (
|
||||||
type ConfigUser struct {
|
type ConfigUser struct {
|
||||||
Id *config.ID
|
Id *config.ID
|
||||||
Email string
|
Email string
|
||||||
|
LevelValue config.UserLevel
|
||||||
}
|
}
|
||||||
|
|
||||||
func (u *ConfigUser) UnmarshalJSON(data []byte) error {
|
func (u *ConfigUser) UnmarshalJSON(data []byte) error {
|
||||||
type rawUser struct {
|
type rawUser struct {
|
||||||
IdString string `json:"id"`
|
IdString string `json:"id"`
|
||||||
EmailString string `json:"email"`
|
EmailString string `json:"email"`
|
||||||
|
LevelInt int `json:"level"`
|
||||||
}
|
}
|
||||||
var rawUserValue rawUser
|
var rawUserValue rawUser
|
||||||
if err := json.Unmarshal(data, &rawUserValue); err != nil {
|
if err := json.Unmarshal(data, &rawUserValue); err != nil {
|
||||||
|
@ -27,9 +29,14 @@ func (u *ConfigUser) UnmarshalJSON(data []byte) error {
|
||||||
}
|
}
|
||||||
u.Id = id
|
u.Id = id
|
||||||
u.Email = rawUserValue.EmailString
|
u.Email = rawUserValue.EmailString
|
||||||
|
u.LevelValue = config.UserLevel(rawUserValue.LevelInt)
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (u *ConfigUser) ID() *config.ID {
|
func (u *ConfigUser) ID() *config.ID {
|
||||||
return u.Id
|
return u.Id
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (this *ConfigUser) Level() config.UserLevel {
|
||||||
|
return this.LevelValue
|
||||||
|
}
|
|
@ -1,5 +1,27 @@
|
||||||
package config
|
package config
|
||||||
|
|
||||||
|
type UserLevel int
|
||||||
|
|
||||||
|
const (
|
||||||
|
UserLevelAdmin = UserLevel(999)
|
||||||
|
UserLevelUntrusted = UserLevel(0)
|
||||||
|
)
|
||||||
|
|
||||||
type User interface {
|
type User interface {
|
||||||
ID() *ID
|
ID() *ID
|
||||||
|
Level() UserLevel
|
||||||
|
}
|
||||||
|
|
||||||
|
type UserSettings struct {
|
||||||
|
PayloadReadTimeout int
|
||||||
|
}
|
||||||
|
|
||||||
|
func GetUserSettings(level UserLevel) UserSettings {
|
||||||
|
settings := UserSettings {
|
||||||
|
PayloadReadTimeout: 120,
|
||||||
|
}
|
||||||
|
if level > 0 {
|
||||||
|
settings.PayloadReadTimeout = 0
|
||||||
|
}
|
||||||
|
return settings
|
||||||
}
|
}
|
||||||
|
|
|
@ -15,11 +15,11 @@ const (
|
||||||
|
|
||||||
type UserSet interface {
|
type UserSet interface {
|
||||||
AddUser(user config.User) error
|
AddUser(user config.User) error
|
||||||
GetUser(timeHash []byte) (*config.ID, int64, bool)
|
GetUser(timeHash []byte) (config.User, int64, bool)
|
||||||
}
|
}
|
||||||
|
|
||||||
type TimedUserSet struct {
|
type TimedUserSet struct {
|
||||||
validUserIds []*config.ID
|
validUsers []config.User
|
||||||
userHash map[string]indexTimePair
|
userHash map[string]indexTimePair
|
||||||
userHashDeleteQueue *collect.TimedQueue
|
userHashDeleteQueue *collect.TimedQueue
|
||||||
access sync.RWMutex
|
access sync.RWMutex
|
||||||
|
@ -32,7 +32,7 @@ type indexTimePair struct {
|
||||||
|
|
||||||
func NewTimedUserSet() UserSet {
|
func NewTimedUserSet() UserSet {
|
||||||
tus := &TimedUserSet{
|
tus := &TimedUserSet{
|
||||||
validUserIds: make([]*config.ID, 0, 16),
|
validUsers: make([]config.User, 0, 16),
|
||||||
userHash: make(map[string]indexTimePair, 512),
|
userHash: make(map[string]indexTimePair, 512),
|
||||||
userHashDeleteQueue: collect.NewTimedQueue(updateIntervalSec),
|
userHashDeleteQueue: collect.NewTimedQueue(updateIntervalSec),
|
||||||
access: sync.RWMutex{},
|
access: sync.RWMutex{},
|
||||||
|
@ -67,8 +67,8 @@ func (us *TimedUserSet) updateUserHash(tick <-chan time.Time) {
|
||||||
|
|
||||||
for now := range tick {
|
for now := range tick {
|
||||||
nowSec := now.Unix() + cacheDurationSec
|
nowSec := now.Unix() + cacheDurationSec
|
||||||
for idx, id := range us.validUserIds {
|
for idx, user := range us.validUsers {
|
||||||
us.generateNewHashes(lastSec, nowSec, idx, id)
|
us.generateNewHashes(lastSec, nowSec, idx, user.ID())
|
||||||
}
|
}
|
||||||
lastSec = nowSec
|
lastSec = nowSec
|
||||||
}
|
}
|
||||||
|
@ -76,8 +76,8 @@ func (us *TimedUserSet) updateUserHash(tick <-chan time.Time) {
|
||||||
|
|
||||||
func (us *TimedUserSet) AddUser(user config.User) error {
|
func (us *TimedUserSet) AddUser(user config.User) error {
|
||||||
id := user.ID()
|
id := user.ID()
|
||||||
idx := len(us.validUserIds)
|
idx := len(us.validUsers)
|
||||||
us.validUserIds = append(us.validUserIds, id)
|
us.validUsers = append(us.validUsers, user)
|
||||||
|
|
||||||
nowSec := time.Now().Unix()
|
nowSec := time.Now().Unix()
|
||||||
lastSec := nowSec - cacheDurationSec
|
lastSec := nowSec - cacheDurationSec
|
||||||
|
@ -86,12 +86,12 @@ func (us *TimedUserSet) AddUser(user config.User) error {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (us TimedUserSet) GetUser(userHash []byte) (*config.ID, int64, bool) {
|
func (us TimedUserSet) GetUser(userHash []byte) (config.User, int64, bool) {
|
||||||
defer us.access.RUnlock()
|
defer us.access.RUnlock()
|
||||||
us.access.RLock()
|
us.access.RLock()
|
||||||
pair, found := us.userHash[string(userHash)]
|
pair, found := us.userHash[string(userHash)]
|
||||||
if found {
|
if found {
|
||||||
return us.validUserIds[pair.index], pair.timeSec, true
|
return us.validUsers[pair.index], pair.timeSec, true
|
||||||
}
|
}
|
||||||
return nil, 0, false
|
return nil, 0, false
|
||||||
}
|
}
|
||||||
|
|
|
@ -75,12 +75,12 @@ func (r *VMessRequestReader) Read(reader io.Reader) (*VMessRequest, error) {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
userId, timeSec, valid := r.vUserSet.GetUser(buffer.Value[:nBytes])
|
userObj, timeSec, valid := r.vUserSet.GetUser(buffer.Value[:nBytes])
|
||||||
if !valid {
|
if !valid {
|
||||||
return nil, proxyerrors.InvalidAuthentication
|
return nil, proxyerrors.InvalidAuthentication
|
||||||
}
|
}
|
||||||
|
|
||||||
aesCipher, err := aes.NewCipher(userId.CmdKey())
|
aesCipher, err := aes.NewCipher(userObj.ID().CmdKey())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
@ -98,7 +98,7 @@ func (r *VMessRequestReader) Read(reader io.Reader) (*VMessRequest, error) {
|
||||||
bufferLen := nBytes
|
bufferLen := nBytes
|
||||||
|
|
||||||
request := &VMessRequest{
|
request := &VMessRequest{
|
||||||
UserId: *userId,
|
UserId: *userObj.ID(),
|
||||||
Version: buffer.Value[0],
|
Version: buffer.Value[0],
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -14,12 +14,17 @@ import (
|
||||||
|
|
||||||
type TestUser struct {
|
type TestUser struct {
|
||||||
id *config.ID
|
id *config.ID
|
||||||
|
level config.UserLevel
|
||||||
}
|
}
|
||||||
|
|
||||||
func (u *TestUser) ID() *config.ID {
|
func (u *TestUser) ID() *config.ID {
|
||||||
return u.id
|
return u.id
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (this *TestUser) Level() config.UserLevel {
|
||||||
|
return this.level
|
||||||
|
}
|
||||||
|
|
||||||
func TestVMessSerialization(t *testing.T) {
|
func TestVMessSerialization(t *testing.T) {
|
||||||
assert := unit.Assert(t)
|
assert := unit.Assert(t)
|
||||||
|
|
||||||
|
@ -28,8 +33,10 @@ func TestVMessSerialization(t *testing.T) {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
userSet := mocks.MockUserSet{[]*config.ID{}, make(map[string]int), make(map[string]int64)}
|
userSet := mocks.MockUserSet{[]config.User{}, make(map[string]int), make(map[string]int64)}
|
||||||
userSet.AddUser(&TestUser{userId})
|
userSet.AddUser(&TestUser{
|
||||||
|
id: userId,
|
||||||
|
})
|
||||||
|
|
||||||
request := new(VMessRequest)
|
request := new(VMessRequest)
|
||||||
request.Version = byte(0x01)
|
request.Version = byte(0x01)
|
||||||
|
@ -72,8 +79,10 @@ func TestVMessSerialization(t *testing.T) {
|
||||||
|
|
||||||
func BenchmarkVMessRequestWriting(b *testing.B) {
|
func BenchmarkVMessRequestWriting(b *testing.B) {
|
||||||
userId, _ := config.NewID("2b2966ac-16aa-4fbf-8d81-c5f172a3da51")
|
userId, _ := config.NewID("2b2966ac-16aa-4fbf-8d81-c5f172a3da51")
|
||||||
userSet := mocks.MockUserSet{[]*config.ID{}, make(map[string]int), make(map[string]int64)}
|
userSet := mocks.MockUserSet{[]config.User{}, make(map[string]int), make(map[string]int64)}
|
||||||
userSet.AddUser(&TestUser{userId})
|
userSet.AddUser(&TestUser{
|
||||||
|
id: userId,
|
||||||
|
})
|
||||||
|
|
||||||
request := new(VMessRequest)
|
request := new(VMessRequest)
|
||||||
request.Version = byte(0x01)
|
request.Version = byte(0x01)
|
||||||
|
|
|
@ -5,20 +5,20 @@ import (
|
||||||
)
|
)
|
||||||
|
|
||||||
type MockUserSet struct {
|
type MockUserSet struct {
|
||||||
UserIds []*config.ID
|
Users []config.User
|
||||||
UserHashes map[string]int
|
UserHashes map[string]int
|
||||||
Timestamps map[string]int64
|
Timestamps map[string]int64
|
||||||
}
|
}
|
||||||
|
|
||||||
func (us *MockUserSet) AddUser(user config.User) error {
|
func (us *MockUserSet) AddUser(user config.User) error {
|
||||||
us.UserIds = append(us.UserIds, user.ID())
|
us.Users = append(us.Users, user)
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (us *MockUserSet) GetUser(userhash []byte) (*config.ID, int64, bool) {
|
func (us *MockUserSet) GetUser(userhash []byte) (config.User, int64, bool) {
|
||||||
idx, found := us.UserHashes[string(userhash)]
|
idx, found := us.UserHashes[string(userhash)]
|
||||||
if found {
|
if found {
|
||||||
return us.UserIds[idx], us.Timestamps[string(userhash)], true
|
return us.Users[idx], us.Timestamps[string(userhash)], true
|
||||||
}
|
}
|
||||||
return nil, 0, false
|
return nil, 0, false
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue