Introduce user level

pull/55/head
V2Ray 2015-10-31 00:38:31 +01:00
parent d585ec0593
commit b44098d752
6 changed files with 58 additions and 20 deletions

View File

@ -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
}

View File

@ -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
} }

View File

@ -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
} }

View File

@ -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],
} }

View File

@ -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)

View File

@ -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
} }