68 lines
1.4 KiB
Go
68 lines
1.4 KiB
Go
package session
|
|
|
|
import (
|
|
"crypto/rand"
|
|
"encoding/hex"
|
|
"fmt"
|
|
"sort"
|
|
"sync"
|
|
)
|
|
|
|
// Registry is the daemon's set of live sessions.
|
|
type Registry struct {
|
|
mu sync.RWMutex
|
|
sessions map[string]*Session
|
|
}
|
|
|
|
func NewRegistry() *Registry {
|
|
return &Registry{sessions: make(map[string]*Session)}
|
|
}
|
|
|
|
// Create starts a new session and registers it under a fresh ID.
|
|
func (r *Registry) Create(opts Options) (*Session, error) {
|
|
r.mu.Lock()
|
|
defer r.mu.Unlock()
|
|
var id string
|
|
for {
|
|
b := make([]byte, 3)
|
|
if _, err := rand.Read(b); err != nil {
|
|
return nil, fmt.Errorf("generating session id: %w", err)
|
|
}
|
|
id = hex.EncodeToString(b)
|
|
if _, taken := r.sessions[id]; !taken {
|
|
break
|
|
}
|
|
}
|
|
s, err := New(id, opts)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
r.sessions[id] = s
|
|
return s, nil
|
|
}
|
|
|
|
// Get returns the session or nil.
|
|
func (r *Registry) Get(id string) *Session {
|
|
r.mu.RLock()
|
|
defer r.mu.RUnlock()
|
|
return r.sessions[id]
|
|
}
|
|
|
|
// List returns all sessions sorted by ID.
|
|
func (r *Registry) List() []*Session {
|
|
r.mu.RLock()
|
|
defer r.mu.RUnlock()
|
|
out := make([]*Session, 0, len(r.sessions))
|
|
for _, s := range r.sessions {
|
|
out = append(out, s)
|
|
}
|
|
sort.Slice(out, func(i, j int) bool { return out[i].ID < out[j].ID })
|
|
return out
|
|
}
|
|
|
|
// Remove unregisters a session (the caller is responsible for Kill).
|
|
func (r *Registry) Remove(id string) {
|
|
r.mu.Lock()
|
|
defer r.mu.Unlock()
|
|
delete(r.sessions, id)
|
|
}
|