Cloak/internal/server/usermanager/user.go

108 lines
2.8 KiB
Go
Raw Normal View History

2018-11-07 21:16:13 +00:00
package usermanager
import (
"log"
"net"
"sync"
"sync/atomic"
mux "github.com/cbeuw/Cloak/internal/multiplex"
2018-11-07 21:16:13 +00:00
)
2018-11-22 21:55:23 +00:00
// for the ease of using json package
type UserInfo struct {
UID []byte
// ALL of the following fields have to be accessed atomically
SessionsCap uint32
UpRate int64
DownRate int64
UpCredit int64
DownCredit int64
ExpiryTime int64
2018-11-07 21:16:13 +00:00
}
type User struct {
2018-11-07 21:16:13 +00:00
up *Userpanel
2018-11-22 21:55:23 +00:00
arrUID [32]byte
2018-11-07 21:16:13 +00:00
2018-11-22 21:55:23 +00:00
// TODO: use pointer here instead because we don't want to accidentally read
// UserInfo's Credits?
UserInfo
2018-11-07 21:16:13 +00:00
valve *mux.Valve
sessionsM sync.RWMutex
sessions map[uint32]*mux.Session
}
2018-11-22 21:55:23 +00:00
func MakeUser(up *Userpanel, uinfo UserInfo) *User {
// this instance of valve is shared across ALL sessions of a user
valve := mux.MakeValve(uinfo.UpRate, uinfo.DownRate, &uinfo.UpCredit, &uinfo.DownCredit)
u := &User{
2018-11-22 21:55:23 +00:00
up: up,
UserInfo: uinfo,
valve: valve,
sessions: make(map[uint32]*mux.Session),
2018-11-07 21:16:13 +00:00
}
2018-11-22 21:55:23 +00:00
copy(u.arrUID[:], uinfo.UID)
2018-11-07 21:16:13 +00:00
return u
}
2018-11-22 21:55:23 +00:00
func (u *User) addUpCredit(delta int64) { u.valve.AddRxCredit(delta) }
func (u *User) addDownCredit(delta int64) { u.valve.AddTxCredit(delta) }
func (u *User) setSessionsCap(cap uint32) { atomic.StoreUint32(&u.SessionsCap, cap) }
func (u *User) setUpRate(rate int64) { u.valve.SetRxRate(rate) }
func (u *User) setDownRate(rate int64) { u.valve.SetTxRate(rate) }
func (u *User) setUpCredit(n int64) { u.valve.SetRxCredit(n) }
func (u *User) setDownCredit(n int64) { u.valve.SetTxCredit(n) }
func (u *User) setExpiryTime(time int64) { atomic.StoreInt64(&u.ExpiryTime, time) }
func (u *User) updateInfo(uinfo UserInfo) {
u.setSessionsCap(uinfo.SessionsCap)
u.setUpCredit(uinfo.UpCredit)
u.setDownCredit(uinfo.DownCredit)
u.setUpRate(uinfo.UpRate)
u.setDownRate(uinfo.DownRate)
u.setExpiryTime(uinfo.ExpiryTime)
2018-11-07 21:16:13 +00:00
}
func (u *User) GetSession(sessionID uint32) *mux.Session {
2018-11-07 21:16:13 +00:00
u.sessionsM.RLock()
2018-11-24 00:55:26 +00:00
sesh := u.sessions[sessionID]
u.sessionsM.RUnlock()
return sesh
2018-11-07 21:16:13 +00:00
}
func (u *User) PutSession(sessionID uint32, sesh *mux.Session) {
2018-11-07 21:16:13 +00:00
u.sessionsM.Lock()
u.sessions[sessionID] = sesh
u.sessionsM.Unlock()
}
func (u *User) DelSession(sessionID uint32) {
2018-11-07 21:16:13 +00:00
u.sessionsM.Lock()
delete(u.sessions, sessionID)
if len(u.sessions) == 0 {
u.sessionsM.Unlock()
2018-11-22 21:55:23 +00:00
u.up.delActiveUser(u.UID)
2018-11-07 21:16:13 +00:00
return
}
u.sessionsM.Unlock()
}
func (u *User) GetOrCreateSession(sessionID uint32, obfs func(*mux.Frame) []byte, deobfs func([]byte) *mux.Frame, obfsedRead func(net.Conn, []byte) (int, error)) (sesh *mux.Session, existing bool) {
2018-11-22 21:55:23 +00:00
// TODO: session cap
u.sessionsM.Lock()
if sesh = u.sessions[sessionID]; sesh != nil {
2018-11-24 00:55:26 +00:00
u.sessionsM.Unlock()
return sesh, true
2018-11-07 21:16:13 +00:00
} else {
log.Printf("Creating session %v\n", sessionID)
2018-11-07 21:16:13 +00:00
sesh = mux.MakeSession(sessionID, u.valve, obfs, deobfs, obfsedRead)
u.sessions[sessionID] = sesh
2018-11-24 00:55:26 +00:00
u.sessionsM.Unlock()
return sesh, false
2018-11-07 21:16:13 +00:00
}
}