package main import ( "context" "encoding/json" "log" "net/http" "sync" "time" "github.com/gorilla/websocket" "github.com/grafov/bcast" "github.com/kataras/go-events" ) func init() { log.Println("ws.go loading..") go ws_clients.Broadcast(0) ws_msg = make(chan interface{}) go func() { for { select { case msg := <-ws_msg: ws_clients.Send(msg) } } }() // Since httprouter seems to not like doing websocket stuff, we run a seperate server for it.. for now.. go func() { app.mux.HandleFunc("/ws", http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { log.Printf("WS connection from %v\n", r.RemoteAddr) conn, err := upgrader.Upgrade(w, r, nil) if err != nil { log.Println(err) return } err = handleWS(conn) if err != nil { log.Printf("WS connection closed, %v\n", r.RemoteAddr) } })) }() log.Println("ws.go done.") } type WSmsg struct { Event string Payload json.RawMessage } var ws_clients = bcast.NewGroup() var ws_msg chan interface{} var WSMutex = &sync.Mutex{} var upgrader = websocket.Upgrader{ ReadBufferSize: 1024, WriteBufferSize: 1024, } func handleWS(c *websocket.Conn) error { memb := ws_clients.Join() defer memb.Close() ctx, cancel := context.WithCancel(context.Background()) defer cancel() go func() { ticker := time.NewTicker(30 * time.Second) for { select { case <-ctx.Done(): return case <-ticker.C: c.WriteControl(websocket.PingMessage, []byte{}, time.Now().Add(10*time.Second)) case msg := <-memb.Read: c.SetWriteDeadline(time.Now().Add(10 * time.Second)) c.WriteJSON(msg) } } }() c.SetPongHandler(func(d string) error { return nil }) msg := app.songInfoEvent("song_info") c.SetWriteDeadline(time.Now().Add(10 * time.Second)) c.WriteJSON(msg) if app.ambiance.IsPlaying() { msg := make(map[string]interface{}) out := make(map[string]interface{}) msg["event"] = "ambiance_play" out["type"] = app.curamb msg["payload"] = out c.WriteJSON(msg) } else { msg := make(map[string]interface{}) msg["event"] = "ambiance_stop" c.WriteJSON(msg) } for { var msg WSmsg err := c.ReadJSON(&msg) if err != nil { return err } app.events.Emit(events.EventName(msg.Event), msg.Payload) } }