Files
rkKVM/http/ws/ws.go
2024-10-30 13:23:52 +01:00

160 lines
2.6 KiB
Go

package ws
import (
"encoding/json"
"net/http"
"rkkvm/config"
"rkkvm/http/hw/hid"
"github.com/gin-gonic/gin"
"github.com/gorilla/websocket"
log "github.com/sirupsen/logrus"
"time"
)
type Stream struct {
Type string `json:"type"`
State int `json:"state"`
}
const (
KeyboardEvent int = 1
MouseEvent int = 2
)
type client struct {
conn *websocket.Conn
hid *hid.Hid
keyboard chan []int
mouse chan []int
watcher chan struct{}
}
var upgrader = websocket.Upgrader{
ReadBufferSize: 1024,
WriteBufferSize: 1024,
CheckOrigin: func(r *http.Request) bool {
return true
},
}
func ConnHandler(c *gin.Context) {
conn, err := upgrader.Upgrade(c.Writer, c.Request, nil)
if err != nil {
log.Errorf("Couldn't upgrade websocket: %s", err)
return
}
log.Debugf("websocket connected")
cl := &client{
hid: hid.GetHid(),
conn: conn,
keyboard: make(chan []int, 200),
mouse: make(chan []int, 200),
watcher: make(chan struct{}, 1),
}
go cl.Start()
}
func (c *client) Start() {
defer c.Clean()
c.hid.Open()
go c.hid.Keyboard(c.keyboard)
go c.hid.Mouse(c.mouse)
if config.Get().NanoKVMUISupport {
go c.Watch()
}
_ = c.Read()
}
func (c *client) Read() error {
var zeroTime time.Time
_ = c.conn.SetReadDeadline(zeroTime)
for {
_, message, err := c.conn.ReadMessage()
if err != nil {
return err
}
log.Tracef("receive message: %s", message)
var event []int
err = json.Unmarshal(message, &event)
if err != nil {
log.Debugf("receive invalid message: %s", message)
continue
}
if event[0] == KeyboardEvent {
c.keyboard <- event[1:]
} else if event[0] == MouseEvent {
c.mouse <- event[1:]
}
}
}
func (c *client) Write(message []byte) error {
_ = c.conn.SetWriteDeadline(time.Now().Add(10 * time.Second))
return c.conn.WriteMessage(websocket.TextMessage, message)
}
func (c *client) Watch() {
ticker := time.NewTicker(1 * time.Second)
defer ticker.Stop()
for {
select {
case <-ticker.C:
{
//state := stream.Get().GetState()
/*state, err := stream.GetState()
if err != nil {
continue
}*/
message, _ := json.Marshal(&Stream{
Type: "stream",
//State: utils.BoolToInt(state.Result.Source.Online),
State: 1,
})
err := c.Write(message)
if err != nil {
return
}
}
case <-c.watcher:
return
}
}
}
func (c *client) Clean() {
_ = c.conn.Close()
go clearQueue(c.keyboard)
close(c.keyboard)
go clearQueue(c.mouse)
close(c.mouse)
close(c.watcher)
c.hid.Close()
log.Debug("websocket disconnected")
}
func clearQueue(queue chan []int) {
for range queue {
}
}