src.dualinventive.com/go/websocketserver/internal/wsconn/wsconn.go

79 lines
1.8 KiB
Go

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()
}