broadcast.go 1.7 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677
  1. package broadcast
  2. import (
  3. "encoding/json"
  4. "goseg/structs"
  5. "log/slog"
  6. "os"
  7. "reflect"
  8. "sync"
  9. "github.com/gorilla/websocket"
  10. )
  11. var (
  12. logger = slog.New(slog.NewJSONHandler(os.Stdout, nil))
  13. clients = make(map[*websocket.Conn]bool)
  14. broadcastState structs.AuthBroadcast
  15. mu sync.RWMutex // synchronize access to broadcastState
  16. )
  17. func init(){
  18. // initialize broadcastState global var
  19. return
  20. }
  21. // adds ws client
  22. func RegisterClient(conn *websocket.Conn) {
  23. clients[conn] = true
  24. }
  25. // remove ws client
  26. func UnregisterClient(conn *websocket.Conn) {
  27. delete(clients, conn)
  28. }
  29. // update broadcastState with a map of items
  30. func UpdateStateWithMap(values map[string]interface{}) error {
  31. mu.Lock()
  32. defer mu.Unlock()
  33. v := reflect.ValueOf(&broadcastState).Elem()
  34. for key, value := range values {
  35. // we are matching the map key with the broadcastState item
  36. field := v.FieldByName(key)
  37. if !field.IsValid() || !field.CanSet() {
  38. return fmt.Errorf("field %s does not exist or is not settable", key)
  39. }
  40. val := reflect.ValueOf(value)
  41. if field.Type() != val.Type() {
  42. return fmt.Errorf("type mismatch for field %s: expected %s, got %s", key, field.Type(), val.Type())
  43. }
  44. field.Set(val)
  45. }
  46. broadcastToClients()
  47. return nil
  48. }
  49. // return broadcast state
  50. func GetState() structs.AuthBroadcast {
  51. mu.Lock()
  52. defer mu.Unlock()
  53. return broadcastState
  54. }
  55. // broadcast the global state to all clients
  56. func broadcastToClients() {
  57. broadcastJson, err := json.Marshal(broadcastState)
  58. if err != nil {
  59. logger.Error("Error marshalling response:", err)
  60. return
  61. }
  62. for client := range clients {
  63. if err := client.WriteMessage(websocket.TextMessage, broadcastJson); err != nil {
  64. logger.Error("Error writing response:", err)
  65. return
  66. }
  67. }
  68. }