Files
go-receipt-tracker/listeners/listeners.go
2025-02-03 17:49:29 -05:00

123 lines
2.7 KiB
Go

package listeners
import (
"crypto/tls"
"sync"
"log/slog"
)
// Config contains configuration values for a listener.
type Config struct {
// TLSConfig is a tls.Config configuration to be used with the listener.
// See examples folder for basic and mutual-tls use.
TLSConfig *tls.Config
}
// Listener is an interface for network listeners. A network listener listens
// for incoming client connections and adds them to the server.
type Listener interface {
Init(*slog.Logger) error // open the network address
Serve() // starting actively listening for new connections
ID() string // return the id of the listener
Address() string // the address of the listener
Protocol() string // the protocol in use by the listener
Close() // stop and close the listener
}
// Listeners contains the network listeners for the broker.
type Listeners struct {
ClientsWg sync.WaitGroup // a waitgroup that waits for all clients in all listeners to finish.
internal map[string]Listener // a map of active listeners.
sync.RWMutex
}
// New returns a new instance of Listeners.
func New() *Listeners {
return &Listeners{
internal: map[string]Listener{},
}
}
// Add adds a new listener to the listeners map, keyed on id.
func (l *Listeners) Add(val Listener) {
l.Lock()
defer l.Unlock()
l.internal[val.ID()] = val
}
// Get returns the value of a listener if it exists.
func (l *Listeners) Get(id string) (Listener, bool) {
l.RLock()
defer l.RUnlock()
val, ok := l.internal[id]
return val, ok
}
// Len returns the length of the listeners map.
func (l *Listeners) Len() int {
l.RLock()
defer l.RUnlock()
return len(l.internal)
}
// Delete removes a listener from the internal map.
func (l *Listeners) Delete(id string) {
l.Lock()
defer l.Unlock()
delete(l.internal, id)
}
// Serve starts a listener serving from the internal map.
func (l *Listeners) Serve(id string) {
l.RLock()
defer l.RUnlock()
listener := l.internal[id]
go func() {
listener.Serve()
}()
}
// ServeAll starts all listeners serving from the internal map.
func (l *Listeners) ServeAll() {
l.RLock()
i := 0
ids := make([]string, len(l.internal))
for id := range l.internal {
ids[i] = id
i++
}
l.RUnlock()
for _, id := range ids {
l.Serve(id)
}
}
// Close stops a listener from the internal map.
func (l *Listeners) Close(id string) {
l.RLock()
defer l.RUnlock()
if listener, ok := l.internal[id]; ok {
listener.Close()
}
}
// CloseAll iterates and closes all registered listeners.
func (l *Listeners) CloseAll() {
l.RLock()
i := 0
ids := make([]string, len(l.internal))
for id := range l.internal {
ids[i] = id
i++
}
l.RUnlock()
for _, id := range ids {
l.Close(id)
}
l.ClientsWg.Wait()
}