mirror of https://github.com/jetkvm/kvm.git
add queues for keyboard / mouse event
This commit is contained in:
parent
d61ea2195b
commit
7389467c2f
|
@ -24,9 +24,18 @@ const (
|
||||||
Version byte = 0x01 // Version of the HID RPC protocol
|
Version byte = 0x01 // Version of the HID RPC protocol
|
||||||
)
|
)
|
||||||
|
|
||||||
// ShouldUseEnqueue returns true if the message type should be enqueued to the HID queue.
|
// GetQueueIndex returns the index of the queue to which the message should be enqueued.
|
||||||
func ShouldUseEnqueue(messageType MessageType) bool {
|
func GetQueueIndex(messageType MessageType) int {
|
||||||
return messageType == TypeMouseReport
|
switch messageType {
|
||||||
|
case TypeHandshake:
|
||||||
|
return 0
|
||||||
|
case TypeKeyboardReport, TypeKeypressReport, TypeKeyboardLedState, TypeKeydownState:
|
||||||
|
return 1
|
||||||
|
case TypePointerReport, TypeMouseReport, TypeWheelReport:
|
||||||
|
return 2
|
||||||
|
default:
|
||||||
|
return 3
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Unmarshal unmarshals the HID RPC message from the data.
|
// Unmarshal unmarshals the HID RPC message from the data.
|
||||||
|
|
57
webrtc.go
57
webrtc.go
|
@ -6,10 +6,12 @@ import (
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"net"
|
"net"
|
||||||
"strings"
|
"strings"
|
||||||
|
"sync"
|
||||||
|
|
||||||
"github.com/coder/websocket"
|
"github.com/coder/websocket"
|
||||||
"github.com/coder/websocket/wsjson"
|
"github.com/coder/websocket/wsjson"
|
||||||
"github.com/gin-gonic/gin"
|
"github.com/gin-gonic/gin"
|
||||||
|
"github.com/jetkvm/kvm/internal/hidrpc"
|
||||||
"github.com/jetkvm/kvm/internal/logging"
|
"github.com/jetkvm/kvm/internal/logging"
|
||||||
"github.com/pion/webrtc/v4"
|
"github.com/pion/webrtc/v4"
|
||||||
"github.com/rs/zerolog"
|
"github.com/rs/zerolog"
|
||||||
|
@ -23,9 +25,11 @@ type Session struct {
|
||||||
HidChannel *webrtc.DataChannel
|
HidChannel *webrtc.DataChannel
|
||||||
shouldUmountVirtualMedia bool
|
shouldUmountVirtualMedia bool
|
||||||
|
|
||||||
|
rpcQueue chan webrtc.DataChannelMessage
|
||||||
|
|
||||||
hidRPCAvailable bool
|
hidRPCAvailable bool
|
||||||
hidQueue chan webrtc.DataChannelMessage
|
hidQueueLock sync.Mutex
|
||||||
rpcQueue chan webrtc.DataChannelMessage
|
hidQueue []chan webrtc.DataChannelMessage
|
||||||
}
|
}
|
||||||
|
|
||||||
type SessionConfig struct {
|
type SessionConfig struct {
|
||||||
|
@ -70,6 +74,23 @@ func (s *Session) ExchangeOffer(offerStr string) (string, error) {
|
||||||
return base64.StdEncoding.EncodeToString(localDescription), nil
|
return base64.StdEncoding.EncodeToString(localDescription), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (s *Session) initQueues() {
|
||||||
|
s.hidQueueLock.Lock()
|
||||||
|
defer s.hidQueueLock.Unlock()
|
||||||
|
|
||||||
|
s.hidQueue = make([]chan webrtc.DataChannelMessage, 0)
|
||||||
|
for i := 0; i < 4; i++ {
|
||||||
|
q := make(chan webrtc.DataChannelMessage, 256)
|
||||||
|
s.hidQueue = append(s.hidQueue, q)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *Session) handleQueues(index int) {
|
||||||
|
for msg := range s.hidQueue[index] {
|
||||||
|
onHidMessage(msg.Data, s)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func newSession(config SessionConfig) (*Session, error) {
|
func newSession(config SessionConfig) (*Session, error) {
|
||||||
webrtcSettingEngine := webrtc.SettingEngine{
|
webrtcSettingEngine := webrtc.SettingEngine{
|
||||||
LoggerFactory: logging.GetPionDefaultLoggerFactory(),
|
LoggerFactory: logging.GetPionDefaultLoggerFactory(),
|
||||||
|
@ -111,7 +132,7 @@ func newSession(config SessionConfig) (*Session, error) {
|
||||||
|
|
||||||
session := &Session{peerConnection: peerConnection}
|
session := &Session{peerConnection: peerConnection}
|
||||||
session.rpcQueue = make(chan webrtc.DataChannelMessage, 256)
|
session.rpcQueue = make(chan webrtc.DataChannelMessage, 256)
|
||||||
session.hidQueue = make(chan webrtc.DataChannelMessage, 256)
|
session.initQueues()
|
||||||
|
|
||||||
go func() {
|
go func() {
|
||||||
for msg := range session.rpcQueue {
|
for msg := range session.rpcQueue {
|
||||||
|
@ -120,11 +141,9 @@ func newSession(config SessionConfig) (*Session, error) {
|
||||||
}
|
}
|
||||||
}()
|
}()
|
||||||
|
|
||||||
go func() {
|
for i := 0; i < len(session.hidQueue); i++ {
|
||||||
for msg := range session.hidQueue {
|
go session.handleQueues(i)
|
||||||
onHidMessage(msg.Data, session)
|
}
|
||||||
}
|
|
||||||
}()
|
|
||||||
|
|
||||||
peerConnection.OnDataChannel(func(d *webrtc.DataChannel) {
|
peerConnection.OnDataChannel(func(d *webrtc.DataChannel) {
|
||||||
defer func() {
|
defer func() {
|
||||||
|
@ -154,7 +173,19 @@ func newSession(config SessionConfig) (*Session, error) {
|
||||||
l.Trace().Msg("received data in HID RPC message handler")
|
l.Trace().Msg("received data in HID RPC message handler")
|
||||||
|
|
||||||
// Enqueue to ensure ordered processing
|
// Enqueue to ensure ordered processing
|
||||||
session.hidQueue <- msg
|
queueIndex := hidrpc.GetQueueIndex(hidrpc.MessageType(msg.Data[0]))
|
||||||
|
if queueIndex >= len(session.hidQueue) || queueIndex < 0 {
|
||||||
|
l.Warn().Int("queueIndex", queueIndex).Msg("received data in HID RPC message handler, but queue index not found")
|
||||||
|
queueIndex = 3
|
||||||
|
}
|
||||||
|
|
||||||
|
queue := session.hidQueue[queueIndex]
|
||||||
|
if queue != nil {
|
||||||
|
queue <- msg
|
||||||
|
} else {
|
||||||
|
l.Warn().Int("queueIndex", queueIndex).Msg("received data in HID RPC message handler, but queue is nil")
|
||||||
|
return
|
||||||
|
}
|
||||||
})
|
})
|
||||||
case "rpc":
|
case "rpc":
|
||||||
session.RPCChannel = d
|
session.RPCChannel = d
|
||||||
|
@ -238,11 +269,13 @@ func newSession(config SessionConfig) (*Session, error) {
|
||||||
close(session.rpcQueue)
|
close(session.rpcQueue)
|
||||||
session.rpcQueue = nil
|
session.rpcQueue = nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// Stop HID RPC processor
|
// Stop HID RPC processor
|
||||||
if session.hidQueue != nil {
|
for i := 0; i < len(session.hidQueue); i++ {
|
||||||
close(session.hidQueue)
|
close(session.hidQueue[i])
|
||||||
session.hidQueue = nil
|
session.hidQueue[i] = nil
|
||||||
}
|
}
|
||||||
|
|
||||||
if session.shouldUmountVirtualMedia {
|
if session.shouldUmountVirtualMedia {
|
||||||
if err := rpcUnmountImage(); err != nil {
|
if err := rpcUnmountImage(); err != nil {
|
||||||
scopedLogger.Warn().Err(err).Msg("unmount image failed on connection close")
|
scopedLogger.Warn().Err(err).Msg("unmount image failed on connection close")
|
||||||
|
|
Loading…
Reference in New Issue