Documentation
¶
Overview ¶
Package connlimit provides per-IP connection limiting. It prevents a single client IP from consuming all proxy resources via many concurrent connections (e.g. HTTP flood, slow-read attacks). It is a self-contained leaf (stdlib only, no Culvert coupling) extracted from the flat package main per ADR-0002.
Index ¶
- type ConnLimiter
- func (cl *ConnLimiter) Acquire(ip string) bool
- func (cl *ConnLimiter) ActiveConns(ip string) int64
- func (cl *ConnLimiter) ActiveIPs() int
- func (cl *ConnLimiter) Disable()
- func (cl *ConnLimiter) Enable(maxPerIP int)
- func (cl *ConnLimiter) Enabled() bool
- func (cl *ConnLimiter) MaxPerIP() int
- func (cl *ConnLimiter) Release(ip string)
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 tracks active connections per client IP.
func New ¶
func New() *ConnLimiter
New returns a ConnLimiter with the default per-IP cap, initially disabled.
func (*ConnLimiter) Acquire ¶
func (cl *ConnLimiter) Acquire(ip string) bool
Acquire records a connection from ip and reports whether it is admitted (false ⇒ the per-IP limit is exceeded and the caller should reject).
The per-IP counter is ALWAYS maintained, even while the limiter is disabled; the enabled flag gates only the rejection decision, not the accounting. This keeps Acquire and Release symmetric across a runtime disable/re-enable: every admitted connection is counted exactly once and released exactly once. If Acquire skipped counting while disabled (the historical behavior), a connection admitted during the disabled window would later be Released unconditionally and decrement a DIFFERENT, still-counted connection's slot — letting a subsequent re-enable admit past the cap (fail-open). Conversely, gating Release on enabled leaks the slot of a connection counted while enabled and released after disable, wedging that IP over-limit forever (the #503 fail-closed bug). Counting unconditionally closes both.
func (*ConnLimiter) ActiveConns ¶
func (cl *ConnLimiter) ActiveConns(ip string) int64
ActiveConns returns the current connection count for an IP (testing).
func (*ConnLimiter) ActiveIPs ¶
func (cl *ConnLimiter) ActiveIPs() int
ActiveIPs returns the number of IPs currently tracked.
func (*ConnLimiter) Disable ¶
func (cl *ConnLimiter) Disable()
Disable turns off connection limiting.
func (*ConnLimiter) Enable ¶
func (cl *ConnLimiter) Enable(maxPerIP int)
Enable turns on connection limiting.
func (*ConnLimiter) Enabled ¶
func (cl *ConnLimiter) Enabled() bool
Enabled reports whether connection limiting is currently active.
func (*ConnLimiter) MaxPerIP ¶
func (cl *ConnLimiter) MaxPerIP() int
MaxPerIP returns the current per-IP limit.
func (*ConnLimiter) Release ¶
func (cl *ConnLimiter) Release(ip string)
Release decrements the connection count for ip. It does NOT gate on enabled: Acquire counts every admitted connection unconditionally (see its doc), so Release must mirror that exactly. The decrement is guarded by map-entry presence, and the ≤0 delete prevents underflow, so releasing an IP with no live count is a safe no-op.