160 lines
2.6 KiB
Go
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 {
|
|
}
|
|
}
|