package broadcast import ( "encoding/json" "goseg/config" "goseg/structs" "log/slog" "os" "reflect" "sync" "fmt" "github.com/gorilla/websocket" ) var ( logger = slog.New(slog.NewJSONHandler(os.Stdout, nil)) clients = make(map[*websocket.Conn]bool) broadcastState structs.AuthBroadcast mu sync.RWMutex // synchronize access to broadcastState ) func init(){ // initialize broadcastState global var config := config.Conf() broadcast, err := bootstrapBroadcastState(config) if err != nil { errmsg := fmt.Sprintf("Unable to initialize broadcast: %v",err) panic(errmsg) } broadcastState = broadcast } // adds ws client func RegisterClient(conn *websocket.Conn) { clients[conn] = true } // remove ws client func UnregisterClient(conn *websocket.Conn) { delete(clients, conn) } // take in config file and addt'l info to initialize broadcast func bootstrapBroadcastState(config structs.SysConfig) (structs.AuthBroadcast, error) { var res structs.AuthBroadcast return res, nil } // update broadcastState with a map of items func UpdateBroadcastState(values map[string]interface{}) error { mu.Lock() defer mu.Unlock() v := reflect.ValueOf(&broadcastState).Elem() for key, value := range values { // we are matching the map key with the broadcastState item field := v.FieldByName(key) if !field.IsValid() || !field.CanSet() { return fmt.Errorf("field %s does not exist or is not settable", key) } val := reflect.ValueOf(value) if field.Type() != val.Type() { return fmt.Errorf("type mismatch for field %s: expected %s, got %s", key, field.Type(), val.Type()) } field.Set(val) } BroadcastToClients() return nil } // return broadcast state func GetState() structs.AuthBroadcast { mu.Lock() defer mu.Unlock() return broadcastState } // broadcast the global state to all clients func BroadcastToClients() error { broadcastJson, err := json.Marshal(broadcastState) if err != nil { logger.Error("Error marshalling response:", err) return err } for client := range clients { if err := client.WriteMessage(websocket.TextMessage, broadcastJson); err != nil { logger.Error("Error writing response:", err) return err } } return nil }