place/api/read/read.go

120 lines
2.2 KiB
Go

package read
import (
"log"
"sync"
"time"
"git.tek.govt.hu/dowerx/place/api/structs"
"git.tek.govt.hu/dowerx/place/config"
"git.tek.govt.hu/dowerx/place/storage"
"github.com/gin-gonic/gin"
"github.com/gorilla/websocket"
)
var upgrader = websocket.Upgrader{
ReadBufferSize: 1024,
WriteBufferSize: 1024,
}
type ConnectionsMap struct {
sync.Mutex
Items map[*websocket.Conn]chan structs.Pixel
}
func (c *ConnectionsMap) Send(pixel structs.Pixel) {
c.Lock()
for _, v := range c.Items {
v <- pixel
}
c.Unlock()
}
var Connections ConnectionsMap = ConnectionsMap{Items: make(map[*websocket.Conn]chan structs.Pixel)}
func Info(c *gin.Context) {
conf := config.GetConfig()
c.JSON(200, gin.H{
"tileSize": conf.TileSize,
"canvasSize": conf.CanvasSize,
"timeout": conf.Timeout,
})
}
func Tile(c *gin.Context) {
var coords structs.Coordinates
if c.ShouldBind(&coords) != nil {
c.AbortWithStatus(400)
return
}
buffer, err := storage.GetTile(coords.X, coords.Y)
if err != nil {
c.AbortWithError(500, err)
return
}
c.Status(200)
c.Header("Content-Type", "image/png")
c.Writer.Write(buffer.Bytes())
}
func Continuous(c *gin.Context) {
conn, err := upgrader.Upgrade(c.Writer, c.Request, nil)
if err != nil {
return
}
Connections.Lock()
Connections.Items[conn] = make(chan structs.Pixel)
Connections.Unlock()
conn.SetReadDeadline(time.Now().Add(time.Second * 60))
conn.SetPongHandler(func(string) error {
conn.SetReadDeadline(time.Now().Add(time.Second * 60))
return nil
})
// send pings
go func() {
ticker := time.NewTicker(30 * time.Second)
defer ticker.Stop()
for range ticker.C {
if err := conn.WriteControl(websocket.PingMessage, nil, time.Now().Add(10*time.Second)); err != nil {
return
}
}
}()
// defer: close connection, remove channel
defer func() {
Connections.Lock()
for k, v := range Connections.Items {
if k == conn {
close(v)
delete(Connections.Items, k)
break
}
}
Connections.Unlock()
conn.Close()
log.Println("removed connection")
}()
// send updates
go func() {
for pixel := range Connections.Items[conn] {
conn.WriteJSON(pixel)
}
}()
// read loop to keep the connetion alive
for {
_, _, err := conn.ReadMessage()
if err != nil {
break
}
}
}