change project structure

add across nodes ip limit
add user ip recorder
del config file watch
This commit is contained in:
yuzuki999
2022-07-28 23:00:05 +08:00
parent c702ea1461
commit efcdffb20d
43 changed files with 877 additions and 893 deletions

View File

@@ -19,9 +19,9 @@ type UserInfo struct {
type InboundInfo struct {
Tag string
NodeSpeedLimit uint64
UserInfo *sync.Map // Key: Email value: UserInfo
BucketHub *sync.Map // key: Email, value: *ratelimit.Bucket
UserOnlineIP *sync.Map // Key: Email Value: *sync.Map: Key: IP, Value: UID
UserInfo *sync.Map // Key: Uid value: UserInfo
BucketHub *sync.Map // key: Uid, value: *ratelimit.Bucket
UserOnlineIP *sync.Map // Key: Uid Value: *sync.Map: Key: IP, Value: bool
}
type Limiter struct {
@@ -49,7 +49,7 @@ func (l *Limiter) AddInboundLimiter(tag string, nodeInfo *api.NodeInfo, userList
if (*userList)[i].DeviceLimit == 0 {
(*userList)[i].DeviceLimit = nodeInfo.DeviceLimit
}*/
userMap.Store(fmt.Sprintf("%s|%s|%d", tag, (*userList)[i].GetUserEmail(), (*userList)[i].UID), UserInfo{
userMap.Store(fmt.Sprintf("%s|%s|%d", tag, (*userList)[i].V2rayUser.Email, (*userList)[i].UID), UserInfo{
UID: (*userList)[i].UID,
SpeedLimit: nodeInfo.SpeedLimit,
DeviceLimit: nodeInfo.DeviceLimit,
@@ -60,24 +60,19 @@ func (l *Limiter) AddInboundLimiter(tag string, nodeInfo *api.NodeInfo, userList
return nil
}
func (l *Limiter) UpdateInboundLimiter(tag string, nodeInfo *api.NodeInfo, updatedUserList *[]api.UserInfo, usersIndex *[]int) error {
func (l *Limiter) UpdateInboundLimiter(tag string, nodeInfo *api.NodeInfo, updatedUserList *[]api.UserInfo) error {
if value, ok := l.InboundInfo.Load(tag); ok {
inboundInfo := value.(*InboundInfo)
// Update User info
for _, u := range *usersIndex {
/*if (*updatedUserList)[u].SpeedLimit == 0 {
(*updatedUserList)[u].SpeedLimit = nodeInfo.SpeedLimit
}
if (*updatedUserList)[u].DeviceLimit == 0 {
(*updatedUserList)[u].DeviceLimit = nodeInfo.DeviceLimit
}*/
inboundInfo.UserInfo.Store(fmt.Sprintf("%s|%s|%d", tag, (*updatedUserList)[u].GetUserEmail(), (*updatedUserList)[u].UID), UserInfo{
UID: (*updatedUserList)[u].UID,
for i := range *updatedUserList {
inboundInfo.UserInfo.Store(fmt.Sprintf("%s|%s|%d", tag,
(*updatedUserList)[i].V2rayUser.Email, (*updatedUserList)[i].UID), UserInfo{
UID: (*updatedUserList)[i].UID,
SpeedLimit: nodeInfo.SpeedLimit,
DeviceLimit: nodeInfo.DeviceLimit,
})
inboundInfo.BucketHub.Delete(fmt.Sprintf("%s|%s|%d", tag, (*updatedUserList)[u].GetUserEmail(), (*updatedUserList)[u].UID)) // Delete old limiter bucket
inboundInfo.BucketHub.Delete(fmt.Sprintf("%s|%s|%d", tag,
(*updatedUserList)[i].V2rayUser.Email, (*updatedUserList)[i].UID)) // Delete old limiter bucket
}
} else {
return fmt.Errorf("no such inbound in limiter: %s", tag)
@@ -90,34 +85,78 @@ func (l *Limiter) DeleteInboundLimiter(tag string) error {
return nil
}
func (l *Limiter) GetOnlineDevice(tag string) (*[]api.OnlineUser, error) {
onlineUser := make([]api.OnlineUser, 0)
type UserIp struct {
Uid int `json:"Uid"`
IPs []string `json:"Ips"`
}
func (l *Limiter) GetOnlineUserIp(tag string) (*[]UserIp, error) {
if value, ok := l.InboundInfo.Load(tag); ok {
inboundInfo := value.(*InboundInfo)
// Clear Speed Limiter bucket for users who are not online
inboundInfo.BucketHub.Range(func(key, value interface{}) bool {
email := key.(string)
if _, exists := inboundInfo.UserOnlineIP.Load(email); !exists {
inboundInfo.BucketHub.Delete(email)
if _, exists := inboundInfo.UserOnlineIP.Load(key.(string)); !exists {
inboundInfo.BucketHub.Delete(key.(string))
}
return true
})
onlineUser := make([]UserIp, 0)
var ipMap *sync.Map
inboundInfo.UserOnlineIP.Range(func(key, value interface{}) bool {
ipMap := value.(*sync.Map)
ipMap.Range(func(key, value interface{}) bool {
ip := key.(string)
uid := value.(int)
onlineUser = append(onlineUser, api.OnlineUser{UID: uid, IP: ip})
ipMap = value.(*sync.Map)
var ip []string
ipMap.Range(func(key, v interface{}) bool {
if v.(bool) {
ip = append(ip, key.(string))
}
return true
})
email := key.(string)
inboundInfo.UserOnlineIP.Delete(email) // Reset online device
if len(ip) > 0 {
if u, ok := inboundInfo.UserInfo.Load(key.(string)); ok {
onlineUser = append(onlineUser, UserIp{
Uid: u.(UserInfo).UID,
IPs: ip,
})
}
}
return true
})
if len(onlineUser) == 0 {
return nil, nil
}
return &onlineUser, nil
} else {
return nil, fmt.Errorf("no such inbound in limiter: %s", tag)
}
return &onlineUser, nil
}
func (l *Limiter) UpdateOnlineUserIP(tag string, userIpList *[]UserIp) {
if v, ok := l.InboundInfo.Load(tag); ok {
inboundInfo := v.(*InboundInfo)
//Clear old IP
inboundInfo.UserOnlineIP.Range(func(key, value interface{}) bool {
inboundInfo.UserOnlineIP.Delete(key)
return true
})
// Update User Online IP
for i := range *userIpList {
ipMap := new(sync.Map)
for _, userIp := range (*userIpList)[i].IPs {
ipMap.Store(userIp, false)
}
inboundInfo.UserOnlineIP.Store((*userIpList)[i].Uid, ipMap)
}
}
}
func (l *Limiter) ClearOnlineUserIP(tag string) {
if v, ok := l.InboundInfo.Load(tag); ok {
inboundInfo := v.(*InboundInfo)
inboundInfo.UserOnlineIP.Range(func(key, value interface{}) bool {
inboundInfo.UserOnlineIP.Delete(key)
return true
})
}
}
func (l *Limiter) GetUserBucket(tag string, email string, ip string) (limiter *ratelimit.Bucket, SpeedLimit bool, Reject bool) {
@@ -126,21 +165,18 @@ func (l *Limiter) GetUserBucket(tag string, email string, ip string) (limiter *r
nodeLimit := inboundInfo.NodeSpeedLimit
var userLimit uint64 = 0
var deviceLimit = 0
var uid = 0
if v, ok := inboundInfo.UserInfo.Load(email); ok {
u := v.(UserInfo)
uid = u.UID
userLimit = u.SpeedLimit
deviceLimit = u.DeviceLimit
}
// Report online device
ipMap := new(sync.Map)
ipMap.Store(ip, uid)
ipMap.Store(ip, true)
// If any device is online
if v, ok := inboundInfo.UserOnlineIP.LoadOrStore(email, ipMap); ok {
ipMap := v.(*sync.Map)
// If this ip is a new device
if _, ok := ipMap.LoadOrStore(ip, uid); !ok {
if online, ok := ipMap.LoadOrStore(ip, true); !ok {
counter := 0
ipMap.Range(func(key, value interface{}) bool {
counter++
@@ -150,6 +186,10 @@ func (l *Limiter) GetUserBucket(tag string, email string, ip string) (limiter *r
ipMap.Delete(ip)
return nil, false, true
}
} else {
if !online.(bool) {
ipMap.Store(ip, true)
}
}
}
limit := determineRate(nodeLimit, userLimit) // If need the Speed limit