Commit Graph

9 Commits

Author SHA1 Message Date
Alex P 40ccecc902 fix: address critical race conditions and security issues in multi-session
This commit resolves multiple critical issues in the multi-session implementation:

Race Conditions Fixed:
- Add primaryPromotionLock mutex to prevent dual-primary corruption
- Implement atomic nickname reservation before session addition
- Add corruption detection and auto-fix in transferPrimaryRole
- Implement broadcast coalescing to prevent storms

Security Improvements:
- Add permission check for HID RPC handshake
- Implement sliding window rate limiting for emergency promotions
- Add global RPC rate limiter (2000 req/sec across all sessions)
- Enhance nickname validation (control chars, zero-width chars, unicode)

Reliability Enhancements:
- Add 5-second timeouts to all WebSocket writes
- Add RPC queue monitoring (warns at 200+ messages)
- Verify grace period memory leak protection
- Verify goroutine cleanup on session removal

Technical Details:
- Use double-locking pattern (primaryPromotionLock → mu)
- Implement deferred cleanup for failed nickname reservations
- Use atomic.Bool for broadcast coalescing
- Add trust scoring for emergency promotion selection

Files Modified:
- session_manager.go: Core session management fixes
- session_cleanup_handlers.go: Rate limiting for emergency promotions
- hidrpc.go: Permission checks for handshake
- jsonrpc_session_handlers.go: Enhanced nickname validation
- jsonrpc.go: Global RPC rate limiting
- webrtc.go: WebSocket timeouts and queue monitoring

Total: 266 insertions, 73 deletions across 6 files
2025-10-17 14:28:16 +03:00
Alex P 9a10d3ed38 refactor: revert unrelated USB gadget type changes
Remove int→int16 type signature changes from internal/usbgadget/ that were
not essential to multi-session functionality. These changes should be part
of a separate USB improvement PR.

Changes:
- Revert AbsMouseReport signature to use int instead of int16
- Remove int16 casts in hidrpc.go calling code
- Update usb.go wrapper functions to match

This keeps the multi-session PR focused on session management without
coupling unrelated USB gadget refactoring.
2025-10-17 11:51:09 +03:00
Alex P da85b54fc2 [WIP] Optimizations: code readiness optimizations 2025-10-17 10:44:18 +03:00
Alex P 827decf803 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.
2025-10-14 23:35:36 +03:00
Alex P 8d51aaa8eb fix: prevent session timeout when jiggler is active
The jiggler sends keep-alive packets every 50ms to prevent keyboard
auto-release, but wasn't updating the session's LastActive timestamp.
This caused the backend to timeout and demote the primary session after
5 minutes (default primaryTimeout), even with active jiggler.

Primary fix:
- Add UpdateLastActive call to handleHidRPCKeepressKeepAlive() in hidrpc.go
- Ensures jiggler packets prevent session timeout

Defensive enhancement:
- Add WebSocket fallback for emergency promotion signals in session_manager.go
- Store WebSocket reference in Session struct (webrtc.go)
- Handle connectionModeChanged via WebSocket in devices.$id.tsx
- Provides reliable signaling when WebRTC data channel is stale
2025-10-13 13:10:12 +03:00
Alex P cd70efb83f feat: multi-session support with role-based permissions
Implements concurrent WebRTC session management with granular permission control, enabling multiple users to connect simultaneously with different access levels.

Features:
- Session modes: Primary (full control), Observer (view-only), Queued, Pending
- Role-based permissions (31 permissions across video, input, settings, system)
- Session approval workflow with configurable access control
- Primary control transfer, request, and approval mechanisms
- Grace period reconnection (prevents interruption on network issues)
- Automatic session timeout and cleanup
- Nickname system with browser-based auto-generation
- Trust-based emergency promotion (deadlock prevention)
- Session blacklisting (prevents transfer abuse)

Technical Implementation:
- Centralized permission system (internal/session package)
- Broadcast throttling (100ms global, 50ms per-session) for DoS protection
- Defense-in-depth permission validation
- Pre-allocated event maps for hot-path performance
- Lock-free session iteration with snapshot pattern
- Comprehensive session management UI with real-time updates

New Files:
- session_manager.go (1628 lines) - Core session lifecycle
- internal/session/permissions.go (306 lines) - Permission rules
- session_permissions.go (77 lines) - Package integration
- datachannel_helpers.go (11 lines) - Permission denied handler
- errors.go (10 lines) - Error definitions
- 14 new UI components (session management, approval dialogs, overlays)

50 files changed, 5836 insertions(+), 442 deletions(-)
2025-10-08 18:52:45 +03:00
Aveline afb146d78c
feat: release keyPress automatically (#796)
* feat: release keyPress automatically

* send keepalive when pressing the key

* remove logging

* clean up logging

* chore: use unreliable channel to send keepalive events

* chore: use ordered unreliable channel for pointer events

* chore: adjust auto release key interval

* chore: update logging for kbdAutoReleaseLock

* chore: update comment for KEEPALIVE_INTERVAL

* fix: should cancelAutorelease when pressed is true

* fix: handshake won't happen if webrtc reconnects

* chore: add trace log for writeWithTimeout

* chore: add timeout for KeypressReport

* chore: use the proper key to send release command

* refactor: simplify HID RPC keyboard input handling and improve key state management

- Updated `handleHidRPCKeyboardInput` to return errors directly instead of keys down state.
- Refactored `rpcKeyboardReport` and `rpcKeypressReport` to return errors instead of states.
- Introduced a queue for managing key down state updates in the `Session` struct to prevent input handling stalls.
- Adjusted the `UpdateKeysDown` method to handle state changes more efficiently.
- Removed unnecessary logging and commented-out code for clarity.

* refactor: enhance keyboard auto-release functionality and key state management

* fix: correct Windows default auto-repeat delay comment from 1ms to 1s

* refactor: send keypress as early as possible

* refactor: replace console.warn with console.info for HID RPC channel events

* refactor: remove unused NewKeypressKeepAliveMessage function from HID RPC

* fix: handle error in key release process and log warnings

* fix: log warning on keypress report failure

* fix: update auto-release keyboard interval to 225

* refactor: enhance keep-alive handling and jitter compensation in HID RPC

- Implemented staleness guard to ignore outdated keep-alive packets.
- Added jitter compensation logic to adjust timer extensions based on packet arrival times.
- Introduced new methods for managing keep-alive state and reset functionality in the Session struct.
- Updated auto-release delay mechanism to use dynamic durations based on keep-alive timing.
- Adjusted keep-alive interval in the UI to improve responsiveness.

* gofmt

* clean up code

* chore: use dynamic duration for scheduleAutoRelease

* Use harcoded timer reset value for now

* fix: prevent nil pointer dereference when stopping timers in Close method

* refactor: remove nil check for kbdAutoReleaseTimers in DelayAutoReleaseWithDuration

* refactor: optimize dependencies in useHidRpc hooks

* refactor: streamline keep-alive timer management in useKeyboard hook

* refactor: clarify comments in useKeyboard hook for resetKeyboardState function

* refactor: reduce keysDownStateQueueSize

* refactor: close and reset keysDownStateQueue in newSession function

* chore: resolve conflicts

* resolve conflicts

---------

Co-authored-by: Adam Shiervani <adam.shiervani@gmail.com>
2025-09-18 13:35:47 +02:00
Aveline 72e3013337
feat: send all paste keystrokes to backend (#789)
* feat: send all paste keystrokes to backend

* feat: cancel paste mode

* wip: send macro using hidRPC channel

* add delay

* feat: allow paste progress to be cancelled

* allow user to override delay

* chore: clear keysDownState

* fix: use currentSession.reportHidRPCKeyboardMacroState

* fix: jsonrpc.go:1142:21: Error return value is not checked (errcheck)

* fix: performance issue of Uint8Array concat

* chore: hide delay option when debugMode isn't enabled

* feat: use clientSide macro if backend doesn't support macros

* fix: update keysDownState handling

* minor issues

* refactor

* fix: send duplicated keyDownState

* chore: add max length for paste text

---------

Co-authored-by: Adam Shiervani <adam.shiervani@gmail.com>
2025-09-18 13:00:57 +02:00
Aveline bcc307b147
feat: hid rpc channel (#755)
* feat: use hidRpcChannel to save bandwidth

* chore: simplify handshake of hid rpc

* add logs

* chore: add timeout when writing to hid endpoints

* fix issues

* chore: show hid rpc version

* refactor hidrpc marshal / unmarshal

* add queues for keyboard / mouse event

* chore: change logging level of JSONRPC send event to trace

* minor changes related to logging

* fix: nil check

* chore: add comments and remove unused code

* add useMouse

* chore: log msg data only when debug or trace mode

* chore: make tslint happy

* chore: unlock keyboardStateLock before calling onKeysDownChange

* chore: remove keyPressReportApiAvailable

* chore: change version handle

* chore: clean up unused functions

* remove comments
2025-09-04 22:27:56 +02:00