package wsconn import ( "context" "net/http" "strconv" "github.com/gorilla/websocket" "github.com/sirupsen/logrus" "src.dualinventive.com/go/websocketserver/internal/mtiwss" "src.dualinventive.com/go/websocketserver/internal/redis" ) // clients keeps track of all current websocket clients var clients = newClientList() var redisClient *redis.Redis // SetRedis set the redis endpoint func SetRedis(r *redis.Redis) { redisClient = r } // NewWsHandlerContext creates a http.HandlerFunc which serves Websockets and relays request to MTIWss func NewWsHandlerContext(ctx context.Context, mtiwss *mtiwss.Mtiwss) http.HandlerFunc { var wsUpgrader = websocket.Upgrader{ CheckOrigin: func(r *http.Request) bool { return true }, } return func(w http.ResponseWriter, r *http.Request) { c, err := wsUpgrader.Upgrade(w, r, nil) if err != nil { logrus.Warnf("Upgrade of websocket connection failed: %v", err) return } ws := newClient(c) cctx, cancel := context.WithCancel(ctx) ws.cancel = cancel clients.Add(ws) ws.Serve(cctx, mtiwss) clients.Remove(ws) ws.Close() } } // Publish will push all updates to subscribed websocket connections func Publish(ev redis.Event, values map[string]string) { var projectID uint64 var deviceUID string if ev.Chan == redis.ChanDevice { if len(ev.Msg) != 32 { return } deviceUID = ev.Msg } else if ev.Chan == redis.ChanProject { id, err := strconv.ParseUint(ev.Msg, 10, 64) if err != nil { return } projectID = id } clients.RLock() for e := clients.list.Front(); e != nil; e = e.Next() { c := e.Value.(*client) switch ev.Chan { case redis.ChanDevice: c.PublishDeviceUIDUpdate(deviceUID, values) case redis.ChanProject: c.PublishProjectIDUpdate(projectID, values) } } clients.RUnlock() }