add dynamic speed limit

fix old user limit info not clear
fix some wrong names
This commit is contained in:
yuzuki999
2022-09-07 23:02:02 +08:00
parent 52134c6e4e
commit 5fd09079e3
10 changed files with 211 additions and 130 deletions

View File

@@ -14,6 +14,7 @@ import (
type UserInfo struct {
UID int
SpeedLimit uint64
ExpireTime int64
DeviceLimit int
}
@@ -51,7 +52,7 @@ func (l *Limiter) AddInboundLimiter(tag string, nodeInfo *panel.NodeInfo, userLi
(*userList)[i].DeviceLimit = nodeInfo.DeviceLimit
}*/
userMap.Store(fmt.Sprintf("%s|%s|%d", tag, (userList)[i].V2rayUser.Email, (userList)[i].UID),
UserInfo{
&UserInfo{
UID: (userList)[i].UID,
SpeedLimit: nodeInfo.SpeedLimit,
DeviceLimit: nodeInfo.DeviceLimit,
@@ -62,19 +63,23 @@ func (l *Limiter) AddInboundLimiter(tag string, nodeInfo *panel.NodeInfo, userLi
return nil
}
func (l *Limiter) UpdateInboundLimiter(tag string, nodeInfo *panel.NodeInfo, updatedUserList []panel.UserInfo) error {
func (l *Limiter) UpdateInboundLimiter(tag string, nodeInfo *panel.NodeInfo, added, deleted []panel.UserInfo) error {
if value, ok := l.InboundInfo.Load(tag); ok {
inboundInfo := value.(*InboundInfo)
// Update User info
for i := range updatedUserList {
for i := range added {
inboundInfo.UserInfo.Store(fmt.Sprintf("%s|%s|%d", tag,
(updatedUserList)[i].V2rayUser.Email, (updatedUserList)[i].UID), UserInfo{
UID: (updatedUserList)[i].UID,
(added)[i].V2rayUser.Email, (added)[i].UID), &UserInfo{
UID: (added)[i].UID,
SpeedLimit: nodeInfo.SpeedLimit,
DeviceLimit: nodeInfo.DeviceLimit,
})
}
for i := range deleted {
inboundInfo.UserInfo.Delete(fmt.Sprintf("%s|%s|%d", tag,
(deleted)[i].V2rayUser.Email, (deleted)[i].UID))
inboundInfo.SpeedLimiter.Delete(fmt.Sprintf("%s|%s|%d", tag,
(updatedUserList)[i].V2rayUser.Email, (updatedUserList)[i].UID)) // Delete old limiter bucket
(deleted)[i].V2rayUser.Email, (deleted)[i].UID)) // Delete limiter bucket
}
} else {
return fmt.Errorf("no such inbound in limiter: %s", tag)
@@ -87,6 +92,22 @@ func (l *Limiter) DeleteInboundLimiter(tag string) error {
return nil
}
func (l *Limiter) UpdateUserSpeedLimit(tag string, userInfo *panel.UserInfo, limit uint64, expire int64) error {
if value, ok := l.InboundInfo.Load(tag); ok {
inboundInfo := value.(*InboundInfo)
if user, ok := inboundInfo.UserInfo.Load(fmt.Sprintf("%s|%s|%d", tag, userInfo.GetUserEmail(), userInfo.UID)); ok {
user.(*UserInfo).SpeedLimit = limit
user.(*UserInfo).ExpireTime = time.Now().Add(time.Duration(expire) * time.Second).Unix()
inboundInfo.SpeedLimiter.Delete(fmt.Sprintf("%s|%s|%d", tag, userInfo.GetUserEmail(), userInfo.UID))
} else {
return fmt.Errorf("no such user in limiter: %s", userInfo.GetUserEmail())
}
return nil
} else {
return fmt.Errorf("no such inbound in limiter: %s", tag)
}
}
type UserIpList struct {
Uid int `json:"Uid"`
IpList []string `json:"Ips"`
@@ -109,7 +130,7 @@ func (l *Limiter) ListOnlineUserIp(tag string) ([]UserIpList, error) {
if len(ip) > 0 {
if u, ok := inboundInfo.UserInfo.Load(key.(string)); ok {
onlineUser = append(onlineUser, UserIpList{
Uid: u.(UserInfo).UID,
Uid: u.(*UserInfo).UID,
IpList: ip,
})
}
@@ -172,9 +193,15 @@ func (l *Limiter) CheckSpeedAndDeviceLimit(tag string, email string, ip string)
nodeLimit := inboundInfo.NodeSpeedLimit
var userLimit uint64 = 0
var deviceLimit = 0
expired := false
if v, ok := inboundInfo.UserInfo.Load(email); ok {
u := v.(UserInfo)
userLimit = u.SpeedLimit
u := v.(*UserInfo)
if u.ExpireTime < time.Now().Unix() && u.ExpireTime != 0 {
userLimit = 0
expired = true
} else {
userLimit = u.SpeedLimit
}
deviceLimit = u.DeviceLimit
}
ipMap := new(sync.Map)
@@ -203,6 +230,10 @@ func (l *Limiter) CheckSpeedAndDeviceLimit(tag string, email string, ip string)
if limit > 0 {
limiter := ratelimit.NewBucketWithQuantum(time.Second, int64(limit), int64(limit)) // Byte/s
if v, ok := inboundInfo.SpeedLimiter.LoadOrStore(email, limiter); ok {
if expired {
inboundInfo.SpeedLimiter.Store(email, limiter)
return limiter, true, false
}
bucket := v.(*ratelimit.Bucket)
return bucket, true, false
} else {

View File

@@ -10,8 +10,7 @@ import (
)
func (p *Core) RemoveInbound(tag string) error {
err := p.ihm.RemoveHandler(context.Background(), tag)
return err
return p.ihm.RemoveHandler(context.Background(), tag)
}
func (p *Core) AddInbound(config *core.InboundHandlerConfig) error {
@@ -30,8 +29,7 @@ func (p *Core) AddInbound(config *core.InboundHandlerConfig) error {
}
func (p *Core) AddInboundLimiter(tag string, nodeInfo *panel.NodeInfo, userList []panel.UserInfo) error {
err := p.dispatcher.Limiter.AddInboundLimiter(tag, nodeInfo, userList)
return err
return p.dispatcher.Limiter.AddInboundLimiter(tag, nodeInfo, userList)
}
func (p *Core) GetInboundLimiter(tag string) (*dispatcher.InboundInfo, error) {
@@ -42,12 +40,10 @@ func (p *Core) GetInboundLimiter(tag string) (*dispatcher.InboundInfo, error) {
return nil, fmt.Errorf("not found limiter")
}
func (p *Core) UpdateInboundLimiter(tag string, nodeInfo *panel.NodeInfo, updatedUserList []panel.UserInfo) error {
err := p.dispatcher.Limiter.UpdateInboundLimiter(tag, nodeInfo, updatedUserList)
return err
func (p *Core) UpdateInboundLimiter(tag string, nodeInfo *panel.NodeInfo, added, deleted []panel.UserInfo) error {
return p.dispatcher.Limiter.UpdateInboundLimiter(tag, nodeInfo, added, deleted)
}
func (p *Core) DeleteInboundLimiter(tag string) error {
err := p.dispatcher.Limiter.DeleteInboundLimiter(tag)
return err
return p.dispatcher.Limiter.DeleteInboundLimiter(tag)
}

View File

@@ -3,6 +3,7 @@ package core
import (
"context"
"fmt"
"github.com/Yuzuki616/V2bX/api/panel"
"github.com/Yuzuki616/V2bX/core/app/dispatcher"
"github.com/xtls/xray-core/common/protocol"
"github.com/xtls/xray-core/proxy"
@@ -79,6 +80,10 @@ func (p *Core) GetUserTraffic(email string, reset bool) (up int64, down int64) {
return up, down
}
func (p *Core) UpdateUserSpeedLimit(tag string, user *panel.UserInfo, speedLimit uint64, expire int64) error {
return p.dispatcher.Limiter.UpdateUserSpeedLimit(tag, user, speedLimit, expire)
}
func (p *Core) ListOnlineIp(tag string) ([]dispatcher.UserIpList, error) {
return p.dispatcher.Limiter.ListOnlineUserIp(tag)
}