mirror of
https://github.com/mumble-voip/grumble.git
synced 2025-12-19 21:59:59 -08:00
MaxUsers: modifies existing sessionpool similar to Murmur MaxUsersPerChannel: already implemented, inconsistent name AllowPing: affects registration, too DefaultChannel RememberChannel ServerPassword SendOSInfo: already implemented, inconsistent name Config keys are renamed to conform to murmur.ini
101 lines
2.5 KiB
Go
101 lines
2.5 KiB
Go
// Copyright (c) 2011 The Grumble Authors
|
|
// The use of this source code is goverened by a BSD-style
|
|
// license that can be found in the LICENSE-file.
|
|
|
|
// Package sessionpool implements a reuse pool for session IDs.
|
|
package sessionpool
|
|
|
|
import (
|
|
"errors"
|
|
"math"
|
|
"sync"
|
|
)
|
|
|
|
// A SessionPool is a pool for session IDs.
|
|
// IDs are re-used in MRU order, for ease of implementation in Go.
|
|
type SessionPool struct {
|
|
mutex sync.Mutex
|
|
used map[uint32]bool
|
|
unused []uint32
|
|
cur uint32
|
|
max uint32
|
|
}
|
|
|
|
// Create a new SessionPool container.
|
|
func New(max uint32) (pool *SessionPool) {
|
|
pool = new(SessionPool)
|
|
if max == 0 {
|
|
pool.max = math.MaxUint32
|
|
} else {
|
|
pool.max = max
|
|
}
|
|
return
|
|
}
|
|
|
|
// Enable use-tracking for the SessionPool.
|
|
//
|
|
// When enabled, the SessionPool stores all session IDs
|
|
// returned by Get() internally. When an ID is reclaimed,
|
|
// the SessionPool checks whether the ID being reclaimed
|
|
// is in its list of used IDs. If this is not the case,
|
|
// the program will panic.
|
|
func (pool *SessionPool) EnableUseTracking() {
|
|
if len(pool.unused) != 0 || pool.cur != 0 {
|
|
panic("Attempt to enable use tracking on an existing SessionPool.")
|
|
}
|
|
pool.used = make(map[uint32]bool)
|
|
}
|
|
|
|
// Get a new session ID from the SessionPool.
|
|
// Must be reclaimed using Reclaim() when done using it.
|
|
func (pool *SessionPool) Get() (id uint32, err error) {
|
|
pool.mutex.Lock()
|
|
defer pool.mutex.Unlock()
|
|
|
|
// If use tracking is enabled, mark our returned session id as used.
|
|
if pool.used != nil {
|
|
defer func() {
|
|
pool.used[id] = true
|
|
}()
|
|
}
|
|
|
|
// First, look in the unused stack.
|
|
length := len(pool.unused)
|
|
if length > 0 {
|
|
id = pool.unused[length-1]
|
|
pool.unused = pool.unused[:length-1]
|
|
return
|
|
}
|
|
|
|
// Check for depletion. If cur is max,
|
|
// there aren't any session IDs left, since the
|
|
// increment below would return an out of range ID.
|
|
if pool.cur == pool.max {
|
|
err = errors.New("depleted session pool")
|
|
return
|
|
}
|
|
|
|
// Increment the next session id and return it.
|
|
// Note: By incrementing and *then* returning, we skip 0.
|
|
// This is deliberate, as 0 is an invalid session ID in Mumble.
|
|
pool.cur += 1
|
|
id = pool.cur
|
|
return
|
|
}
|
|
|
|
// Reclaim a session ID so it can be reused.
|
|
func (pool *SessionPool) Reclaim(id uint32) {
|
|
pool.mutex.Lock()
|
|
defer pool.mutex.Unlock()
|
|
|
|
// Check whether this ID is marked as being in use.
|
|
if pool.used != nil {
|
|
_, inUse := pool.used[id]
|
|
if !inUse {
|
|
panic("Attempt to reclaim invalid session ID")
|
|
}
|
|
delete(pool.used, id)
|
|
}
|
|
|
|
pool.unused = append(pool.unused, id)
|
|
}
|