mirror of https://github.com/jetkvm/kvm.git
clean up code
This commit is contained in:
parent
a95789f417
commit
53789ebd75
121
hidrpc.go
121
hidrpc.go
|
@ -39,63 +39,7 @@ func handleHidRPCMessage(message hidrpc.Message, session *Session) {
|
||||||
rpcCancelKeyboardMacro()
|
rpcCancelKeyboardMacro()
|
||||||
return
|
return
|
||||||
case hidrpc.TypeKeypressKeepAliveReport:
|
case hidrpc.TypeKeypressKeepAliveReport:
|
||||||
session.keepAliveJitterLock.Lock()
|
rpcErr = handleHidRPCKeypressKeepAlive(session)
|
||||||
defer session.keepAliveJitterLock.Unlock()
|
|
||||||
|
|
||||||
now := time.Now()
|
|
||||||
|
|
||||||
// Tunables
|
|
||||||
// Keep in mind
|
|
||||||
// macOS default: 15 * 15 = 225ms https://discussions.apple.com/thread/1316947?sortBy=rank
|
|
||||||
// Linux default: 250ms https://man.archlinux.org/man/kbdrate.8.en
|
|
||||||
// Windows default: 1s `HKEY_CURRENT_USER\Control Panel\Accessibility\Keyboard Response\AutoRepeatDelay`
|
|
||||||
|
|
||||||
const expectedRate = 50 * time.Millisecond // expected keepalive interval
|
|
||||||
const maxLateness = 50 * time.Millisecond // max jitter we'll tolerate OR jitter budget
|
|
||||||
const baseExtension = expectedRate + maxLateness // 100ms extension on perfect tick
|
|
||||||
|
|
||||||
const maxStaleness = 225 * time.Millisecond // discard ancient packets outright
|
|
||||||
|
|
||||||
// 1) Staleness guard: ensures packets that arrive far beyond the life of a valid key hold
|
|
||||||
// (e.g. after a network stall, retransmit burst, or machine sleep) are ignored outright.
|
|
||||||
// This prevents “zombie” keepalives from reviving a key that should already be released.
|
|
||||||
if !session.lastTimerResetTime.IsZero() && now.Sub(session.lastTimerResetTime) > maxStaleness {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
validTick := true
|
|
||||||
timerExtension := baseExtension
|
|
||||||
|
|
||||||
if !session.lastKeepAliveArrivalTime.IsZero() {
|
|
||||||
timeSinceLastTick := now.Sub(session.lastKeepAliveArrivalTime)
|
|
||||||
lateness := timeSinceLastTick - expectedRate
|
|
||||||
|
|
||||||
if lateness > 0 {
|
|
||||||
if lateness <= maxLateness {
|
|
||||||
// --- Small lateness (within jitterBudget) ---
|
|
||||||
// This is normal jitter (e.g., Wi-Fi contention).
|
|
||||||
// We still accept the tick, but *reduce the extension*
|
|
||||||
// so that the total hold time stays aligned with REAL client side intent.
|
|
||||||
timerExtension -= lateness
|
|
||||||
} else {
|
|
||||||
// --- Large lateness (beyond jitterBudget) ---
|
|
||||||
// This is likely a retransmit stall or ordering delay.
|
|
||||||
// We reject the tick entirely and DO NOT extend,
|
|
||||||
// so the auto-release still fires on time.
|
|
||||||
validTick = false
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if validTick {
|
|
||||||
// Only valid ticks update our state and extend the timer.
|
|
||||||
session.lastKeepAliveArrivalTime = now
|
|
||||||
session.lastTimerResetTime = now
|
|
||||||
if ug := getUsbGadget(); ug != nil {
|
|
||||||
ug.DelayAutoReleaseWithDuration(timerExtension)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// On a miss: do not advance any state — keeps baseline stable.
|
|
||||||
case hidrpc.TypePointerReport:
|
case hidrpc.TypePointerReport:
|
||||||
pointerReport, err := message.PointerReport()
|
pointerReport, err := message.PointerReport()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -159,6 +103,69 @@ func onHidMessage(msg hidQueueMessage, session *Session) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Tunables
|
||||||
|
// Keep in mind
|
||||||
|
// macOS default: 15 * 15 = 225ms https://discussions.apple.com/thread/1316947?sortBy=rank
|
||||||
|
// Linux default: 250ms https://man.archlinux.org/man/kbdrate.8.en
|
||||||
|
// Windows default: 1s `HKEY_CURRENT_USER\Control Panel\Accessibility\Keyboard Response\AutoRepeatDelay`
|
||||||
|
|
||||||
|
const expectedRate = 50 * time.Millisecond // expected keepalive interval
|
||||||
|
const maxLateness = 50 * time.Millisecond // max jitter we'll tolerate OR jitter budget
|
||||||
|
const baseExtension = expectedRate + maxLateness // 100ms extension on perfect tick
|
||||||
|
|
||||||
|
const maxStaleness = 225 * time.Millisecond // discard ancient packets outright
|
||||||
|
|
||||||
|
func handleHidRPCKeypressKeepAlive(session *Session) error {
|
||||||
|
session.keepAliveJitterLock.Lock()
|
||||||
|
defer session.keepAliveJitterLock.Unlock()
|
||||||
|
|
||||||
|
now := time.Now()
|
||||||
|
|
||||||
|
// 1) Staleness guard: ensures packets that arrive far beyond the life of a valid key hold
|
||||||
|
// (e.g. after a network stall, retransmit burst, or machine sleep) are ignored outright.
|
||||||
|
// This prevents “zombie” keepalives from reviving a key that should already be released.
|
||||||
|
if !session.lastTimerResetTime.IsZero() && now.Sub(session.lastTimerResetTime) > maxStaleness {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
validTick := true
|
||||||
|
timerExtension := baseExtension
|
||||||
|
|
||||||
|
if !session.lastKeepAliveArrivalTime.IsZero() {
|
||||||
|
timeSinceLastTick := now.Sub(session.lastKeepAliveArrivalTime)
|
||||||
|
lateness := timeSinceLastTick - expectedRate
|
||||||
|
|
||||||
|
if lateness > 0 {
|
||||||
|
if lateness <= maxLateness {
|
||||||
|
// --- Small lateness (within jitterBudget) ---
|
||||||
|
// This is normal jitter (e.g., Wi-Fi contention).
|
||||||
|
// We still accept the tick, but *reduce the extension*
|
||||||
|
// so that the total hold time stays aligned with REAL client side intent.
|
||||||
|
timerExtension -= lateness
|
||||||
|
} else {
|
||||||
|
// --- Large lateness (beyond jitterBudget) ---
|
||||||
|
// This is likely a retransmit stall or ordering delay.
|
||||||
|
// We reject the tick entirely and DO NOT extend,
|
||||||
|
// so the auto-release still fires on time.
|
||||||
|
validTick = false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if !validTick {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
// Only valid ticks update our state and extend the timer.
|
||||||
|
session.lastKeepAliveArrivalTime = now
|
||||||
|
session.lastTimerResetTime = now
|
||||||
|
if gadget != nil {
|
||||||
|
gadget.DelayAutoReleaseWithDuration(timerExtension)
|
||||||
|
}
|
||||||
|
|
||||||
|
// On a miss: do not advance any state — keeps baseline stable.
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
func handleHidRPCKeyboardInput(message hidrpc.Message) error {
|
func handleHidRPCKeyboardInput(message hidrpc.Message) error {
|
||||||
switch message.Type() {
|
switch message.Type() {
|
||||||
case hidrpc.TypeKeypressReport:
|
case hidrpc.TypeKeypressReport:
|
||||||
|
|
4
usb.go
4
usb.go
|
@ -8,10 +8,6 @@ import (
|
||||||
|
|
||||||
var gadget *usbgadget.UsbGadget
|
var gadget *usbgadget.UsbGadget
|
||||||
|
|
||||||
func getUsbGadget() *usbgadget.UsbGadget {
|
|
||||||
return gadget
|
|
||||||
}
|
|
||||||
|
|
||||||
// initUsbGadget initializes the USB gadget.
|
// initUsbGadget initializes the USB gadget.
|
||||||
// call it only after the config is loaded.
|
// call it only after the config is loaded.
|
||||||
func initUsbGadget() {
|
func initUsbGadget() {
|
||||||
|
|
Loading…
Reference in New Issue