limiter

package
v0.1.7 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Aug 3, 2026 License: GPL-3.0 Imports: 6 Imported by: 0

Documentation

Overview

Package limiter is to control the links that go into the dispatcher

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

This section is empty.

Types

type ConnLimiter

type ConnLimiter struct {
	// contains filtered or unexported fields
}

ConnLimiter caps concurrent TCP connections per join key (doc/11 §9, T5). Unlike the V2bX reference (which mutates a sync.Map per connection), the count is held as an *atomic.Int64 per key. Decrement happens in the wrapped conn's Close() (doc/11 §3.2 方式 B), so abnormal/timeout teardown never leaks a slot.

The cap is resolved per node tag: SetTagLimit records a MaxConnPerUser for a tag (the NodeTag segment of the join key "tag|email|uid"), and maxPerUser is the process-wide fallback for tags without an explicit entry. Both <= 0 mean "unlimited" for that tag.

func NewConnLimiter

func NewConnLimiter(maxPerUser int) *ConnLimiter

NewConnLimiter returns a ConnLimiter whose default per-key cap is maxPerUser concurrent TCP connections for tags without an explicit SetTagLimit entry. maxPerUser <= 0 leaves the default unlimited; per-tag limits still apply.

func (*ConnLimiter) AddConnCount

func (c *ConnLimiter) AddConnCount(key, ip string, isTcp bool) (reject bool)

AddConnCount records a new connection for key and returns whether it must be rejected. Only TCP is counted (isTcp=false is passed straight through); concurrency for UDP is governed by the online-IP check instead. When the per-user cap is exceeded the increment is rolled back and reject=true.

func (*ConnLimiter) DelConnCount

func (c *ConnLimiter) DelConnCount(key, ip string)

DelConnCount releases a connection slot for key (called from the wrapped conn's Close()). The counter is never driven below zero. Keys are only ever present in the count map when AddConnCount actually counted them, so an unknown key is a safe no-op regardless of the current limit configuration.

func (*ConnLimiter) SetTagLimit

func (c *ConnLimiter) SetTagLimit(tag string, max int)

SetTagLimit sets (or, with max <= 0, clears) the per-user concurrent-TCP cap for a node tag. It is called from the panel's AddNode path before the node serves traffic; a later call overwrites the prior value for the tag.

type InboundInfo

type InboundInfo struct {
	Tag            string
	NodeSpeedLimit uint64
	UserInfo       *sync.Map // Key: Email value: UserInfo
	BucketHub      *sync.Map // key: Email, value: *rate.Limiter
	UserOnlineIP   *sync.Map // Key: Email, value: {Key: IP, value: UID}
	// DeviceLock serialises the device-count check per user. Key: Email,
	// value: *sync.Mutex. Without it the "store my IP, count, reject if over"
	// sequence races with itself and two concurrent new devices can both be
	// rejected. Entries are evicted with the rest of the user's state in
	// DeleteUsers.
	DeviceLock *sync.Map
}

type Limiter

type Limiter struct {
	InboundInfo *sync.Map // Key: Tag, Value: *InboundInfo
	// contains filtered or unexported fields
}

func New

func New() *Limiter

func (*Limiter) AddInboundLimiter

func (l *Limiter) AddInboundLimiter(tag string, nodeSpeedLimit uint64, userList *[]api.UserInfo) error

func (*Limiter) ClearUserThrottle added in v0.1.0

func (l *Limiter) ClearUserThrottle(tag, key string)

ClearUserThrottle drops the override and restores the panel-authoritative rate on the live bucket.

func (*Limiter) DeleteInboundLimiter

func (l *Limiter) DeleteInboundLimiter(tag string) error

func (*Limiter) DeleteUsers

func (l *Limiter) DeleteUsers(tag string, keys []string)

DeleteUsers evicts the given join keys from the inbound's per-user maps. It is called when a node's users are removed (DelUsers) so the limiter does not retain a stale UserInfo entry for a user the inbound no longer authenticates. (BucketHub/UserOnlineIP also self-clean via GetOnlineDevice, but pruning them here reclaims the memory immediately.) A missing tag is a no-op.

func (*Limiter) GetOnlineDevice

func (l *Limiter) GetOnlineDevice(tag string) (*[]api.OnlineUser, error)

func (*Limiter) GetUserBucket

func (l *Limiter) GetUserBucket(tag string, email string, ip string) (limiter *rate.Limiter, SpeedLimit bool, Reject bool)

func (*Limiter) SetAutoLimit added in v0.1.0

func (l *Limiter) SetAutoLimit(tag string, on bool)

SetAutoLimit records whether a node runs the dynamic speed limiter.

It decides whether an UNLIMITED user still gets a bucket. Without one, a connection opened while the user had no limit can never be throttled later: the wrapper is chosen once, at setup, from a nil bucket (doc/14 C-11) — so a heavy user who trips the limiter keeps their existing flows at line rate, which is exactly the flow the limiter was aiming at. With one, the bucket starts at rate.Inf and a later SetLimit reaches every live connection through the pointer they already share.

Gated per node rather than always-on because the bucket costs two mutex acquisitions per buffer on the data path, and a node with no dynamic limiting has nothing that could ever change an unlimited user's rate mid-connection.

Kept outside InboundInfo on purpose: AddInboundLimiter REPLACES that struct on every node (re)registration, which would drop the flag.

func (*Limiter) SetUserThrottle added in v0.1.0

func (l *Limiter) SetUserThrottle(tag, key string, speed uint64)

SetUserThrottle applies a dynamic speed override and pushes it to the user's live bucket, so connections already open are throttled too.

func (*Limiter) UpdateInboundLimiter

func (l *Limiter) UpdateInboundLimiter(tag string, updatedUserList *[]api.UserInfo) error

type UserInfo

type UserInfo struct {
	UID         int
	SpeedLimit  uint64
	DeviceLimit int
}

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL