2023-11-11 15:32:57 +13:00
|
|
|
// Package websockets is used to broadcast messages to connected clients
|
2022-07-29 23:23:08 +12:00
|
|
|
package websockets
|
|
|
|
|
|
|
|
import (
|
|
|
|
"encoding/json"
|
|
|
|
|
2023-09-25 18:08:04 +13:00
|
|
|
"github.com/axllent/mailpit/internal/logger"
|
2022-07-29 23:23:08 +12:00
|
|
|
)
|
|
|
|
|
|
|
|
// Hub maintains the set of active clients and broadcasts messages to the
|
|
|
|
// clients.
|
|
|
|
type Hub struct {
|
|
|
|
// Registered clients.
|
|
|
|
Clients map[*Client]bool
|
|
|
|
|
|
|
|
// Inbound messages from the clients.
|
|
|
|
Broadcast chan []byte
|
|
|
|
|
|
|
|
// Register requests from the clients.
|
|
|
|
register chan *Client
|
|
|
|
|
|
|
|
// Unregister requests from clients.
|
|
|
|
unregister chan *Client
|
|
|
|
}
|
|
|
|
|
2022-10-13 02:47:51 +13:00
|
|
|
// WebsocketNotification struct for responses
|
|
|
|
type WebsocketNotification struct {
|
|
|
|
Type string
|
|
|
|
Data interface{}
|
|
|
|
}
|
|
|
|
|
2022-07-29 23:23:08 +12:00
|
|
|
// NewHub returns a new hub configuration
|
|
|
|
func NewHub() *Hub {
|
|
|
|
return &Hub{
|
|
|
|
Broadcast: make(chan []byte),
|
|
|
|
register: make(chan *Client),
|
|
|
|
unregister: make(chan *Client),
|
|
|
|
Clients: make(map[*Client]bool),
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Run runs the listener
|
|
|
|
func (h *Hub) Run() {
|
|
|
|
for {
|
|
|
|
select {
|
|
|
|
case client := <-h.register:
|
2023-11-11 15:32:57 +13:00
|
|
|
if _, ok := h.Clients[client]; !ok {
|
|
|
|
logger.Log().Debugf("[websocket] client %s connected", client.conn.RemoteAddr().String())
|
|
|
|
h.Clients[client] = true
|
|
|
|
}
|
2022-07-29 23:23:08 +12:00
|
|
|
case client := <-h.unregister:
|
|
|
|
if _, ok := h.Clients[client]; ok {
|
2023-11-11 15:32:57 +13:00
|
|
|
logger.Log().Debugf("[websocket] client %s disconnected", client.conn.RemoteAddr().String())
|
2022-07-29 23:23:08 +12:00
|
|
|
delete(h.Clients, client)
|
|
|
|
close(client.send)
|
|
|
|
}
|
|
|
|
case message := <-h.Broadcast:
|
|
|
|
for client := range h.Clients {
|
|
|
|
select {
|
|
|
|
case client.send <- message:
|
|
|
|
default:
|
|
|
|
close(client.send)
|
|
|
|
delete(h.Clients, client)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Broadcast will spawn a broadcast message to all connected clients
|
|
|
|
func Broadcast(t string, msg interface{}) {
|
2023-09-25 16:53:25 +13:00
|
|
|
if MessageHub == nil || len(MessageHub.Clients) == 0 {
|
2022-07-29 23:23:08 +12:00
|
|
|
return
|
|
|
|
}
|
|
|
|
|
2022-10-13 02:47:51 +13:00
|
|
|
w := WebsocketNotification{}
|
2022-07-29 23:23:08 +12:00
|
|
|
w.Type = t
|
|
|
|
w.Data = msg
|
|
|
|
b, err := json.Marshal(w)
|
|
|
|
|
|
|
|
if err != nil {
|
2024-01-01 15:25:38 +13:00
|
|
|
logger.Log().Errorf("[websocket] broadcast received invalid data: %s", err.Error())
|
2023-10-20 23:15:58 +13:00
|
|
|
return
|
2022-07-29 23:23:08 +12:00
|
|
|
}
|
|
|
|
|
|
|
|
go func() { MessageHub.Broadcast <- b }()
|
|
|
|
}
|