From 827decf80356ffbc46dfc8b18f3c3deecd416d8f Mon Sep 17 00:00:00 2001 From: Alex P Date: Tue, 14 Oct 2025 23:35:36 +0300 Subject: [PATCH] fix: resolve intermittent mouse control loss and add permission logging Root cause: Session pointer inconsistency during RPC/HID message processing. The RPC and HID queue handlers were fetching a fresh session copy from the session manager instead of using the original session pointer. This caused permission checks to fail when the session was promoted to primary, because the Mode field was updated in the manager's copy but not reflected in the queue handler's copy. Changes: - Revert RPC queue handler to use original session pointer (webrtc.go:320) - Revert HID queue handler to use original session pointer (webrtc.go:196) - Add debug logging for permission check failures (hidrpc.go:31-34, 57-61, 71-75) This ensures that when a session's Mode is updated in the session manager, the change is immediately visible to all message handlers, preventing the race condition where mouse/keyboard input would be silently dropped due to HasPermission() checks failing on stale session state. The permission logging will help diagnose any remaining edge cases where input is blocked unexpectedly. --- hidrpc.go | 12 ++++++++++++ webrtc.go | 20 ++------------------ 2 files changed, 14 insertions(+), 18 deletions(-) diff --git a/hidrpc.go b/hidrpc.go index e80b996b..1a7e1d3c 100644 --- a/hidrpc.go +++ b/hidrpc.go @@ -28,6 +28,10 @@ func handleHidRPCMessage(message hidrpc.Message, session *Session) { session.hidRPCAvailable = true case hidrpc.TypeKeypressReport, hidrpc.TypeKeyboardReport: if !session.HasPermission(PermissionKeyboardInput) { + logger.Debug(). + Str("sessionID", session.ID). + Str("mode", string(session.Mode)). + Msg("keyboard input blocked: session lacks PermissionKeyboardInput") return } rpcErr = handleHidRPCKeyboardInput(message) @@ -54,6 +58,10 @@ func handleHidRPCMessage(message hidrpc.Message, session *Session) { rpcErr = handleHidRPCKeypressKeepAlive(session) case hidrpc.TypePointerReport: if !session.HasPermission(PermissionMouseInput) { + logger.Debug(). + Str("sessionID", session.ID). + Str("mode", string(session.Mode)). + Msg("pointer report blocked: session lacks PermissionMouseInput") return } pointerReport, err := message.PointerReport() @@ -64,6 +72,10 @@ func handleHidRPCMessage(message hidrpc.Message, session *Session) { rpcErr = rpcAbsMouseReport(int16(pointerReport.X), int16(pointerReport.Y), pointerReport.Button) case hidrpc.TypeMouseReport: if !session.HasPermission(PermissionMouseInput) { + logger.Debug(). + Str("sessionID", session.ID). + Str("mode", string(session.Mode)). + Msg("mouse report blocked: session lacks PermissionMouseInput") return } mouseReport, err := message.MouseReport() diff --git a/webrtc.go b/webrtc.go index d5edaef4..639ceb86 100644 --- a/webrtc.go +++ b/webrtc.go @@ -193,14 +193,7 @@ func (s *Session) initQueues() { func (s *Session) handleQueues(index int) { for msg := range s.hidQueue[index] { - // Get current session from manager to ensure we have the latest state - currentSession := sessionManager.GetSession(s.ID) - if currentSession != nil { - onHidMessage(msg, currentSession) - } else { - // Session was removed, use original to avoid nil panic - onHidMessage(msg, s) - } + onHidMessage(msg, s) } } @@ -324,16 +317,7 @@ func newSession(config SessionConfig) (*Session, error) { go func() { for msg := range session.rpcQueue { // TODO: only use goroutine if the task is asynchronous - go func(m webrtc.DataChannelMessage) { - // Get current session from manager to ensure we have the latest state - currentSession := sessionManager.GetSession(session.ID) - if currentSession != nil { - onRPCMessage(m, currentSession) - } else { - // Session was removed, use original to avoid nil panic - onRPCMessage(m, session) - } - }(msg) + go onRPCMessage(msg, session) } }()