2fas-server/internal/websocket/common/hub.go
Krzysztof Dryś 4f2707c07f
fix: concurrency problems in ws handler (#14)
* fix: concurrency problems in ws handler

Synchronise access to hubs, properly remove hubs when they no longer
have clients.
2023-11-22 09:34:57 +01:00

65 lines
1.0 KiB
Go

package common
import (
"sync"
)
type Hub struct {
id string
onHubHasNoClients func(id string)
clients *sync.Map
}
func NewHub(id string, notifyOnEmpty func(id string)) *Hub {
h := &Hub{
id: id,
clients: &sync.Map{},
onHubHasNoClients: notifyOnEmpty,
}
return h
}
func (h *Hub) registerClient(c *Client) {
h.clients.Store(c, struct{}{})
}
func (h *Hub) unregisterClient(c *Client) {
_, ok := h.clients.LoadAndDelete(c)
if !ok {
return
}
close(c.send)
if h.isEmpty() {
h.onHubHasNoClients(h.id)
}
}
func (h *Hub) sendToClient(c *Client, msg []byte) {
_, ok := h.clients.Load(c)
if !ok {
return
}
select {
case c.send <- msg:
default:
h.unregisterClient(c)
}
}
func (h *Hub) broadcastMsg(msg []byte) {
h.clients.Range(func(key, value any) bool {
c := key.(*Client)
h.sendToClient(c, msg)
return true
})
}
func (h *Hub) isEmpty() bool {
isEmpty := true
h.clients.Range(func(key, value any) bool {
isEmpty = false
return false
})
return isEmpty
}