package listeners import ( "crypto/tls" "sync" "log/slog" ) // Config contains configuration values for a listener. type Config struct { Type string ID string Address string // 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() }