Skip to content

feat(server): add ConnectionHandler trait for connection lifecycle hooks#1194

Merged
Benoît Cortier (CBenoit) merged 2 commits intoDevolutions:masterfrom
lamco-admin:feat/connection-handler
Apr 8, 2026
Merged

feat(server): add ConnectionHandler trait for connection lifecycle hooks#1194
Benoît Cortier (CBenoit) merged 2 commits intoDevolutions:masterfrom
lamco-admin:feat/connection-handler

Conversation

@glamberson
Copy link
Copy Markdown
Contributor

Summary

Add optional ConnectionHandler to RdpServer::run() with two lifecycle callbacks:

  • on_accept(peer) -> bool: called after accept(), return false to reject the connection before run_connection()
  • on_disconnected(peer, duration, error) -> PostConnectionAction: called after run_connection() completes, return Stop to exit the accept loop

This enables server implementations to add:

  • Pre-accept filtering (rate limiting, IP allowlists)
  • Post-disconnect cleanup (session validity checks, metrics collection)
  • Controlled shutdown when external state becomes invalid (e.g. compositor session terminated)

Both methods have default implementations that accept all connections and continue unconditionally, so existing callers are unaffected.

Motivation

lamco-rdp-server currently duplicates the entire run() accept loop (~100 lines) to add connection lifecycle hooks for D-Bus event emission, PAM peer IP tracking, and Portal session validity checks. With ConnectionHandler, it can adopt the upstream run() directly.

The key gap was PostConnectionAction::Stop: after each client disconnects, lamco checks whether the Wayland compositor session is still valid and stops accepting if not. The existing ServerEvent::Quit mechanism requires the handler to know about IronRDP internals; PostConnectionAction keeps the contract explicit.

Changes

  • server.rs: ConnectionHandler trait, PostConnectionAction enum, connection_handler field on RdpServer, hooks wired into run() accept loop
  • builder.rs: with_connection_handler() on BuilderDone, ConnectionHandler import, BuilderDone field

Test plan

  • Existing tests pass (all 5 xtask gates green)
  • Server without handler: behavior unchanged (default impls)
  • Server with handler returning Stop: accept loop exits after disconnect
  • Server with handler rejecting on_accept: connection dropped, loop continues

Add optional ConnectionHandler to RdpServer::run() with two callbacks:

- on_accept(peer) -> bool: called after accept(), return false to reject
- on_disconnected(peer, duration, error) -> PostConnectionAction: called
  after run_connection() completes, return Stop to exit the accept loop

This enables server implementations to add pre-accept filtering (rate
limiting, IP allowlists), post-disconnect cleanup (session validity
checks, metrics), and controlled shutdown when external state becomes
invalid (e.g. compositor session terminated).

Both methods have default implementations that accept all connections
and continue unconditionally, so existing callers are unaffected.
Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR introduces a configurable connection lifecycle hook mechanism for ironrdp-server by adding an optional ConnectionHandler to RdpServer::run(), enabling pre-accept filtering and post-disconnect actions (including controlled shutdown of the accept loop).

Changes:

  • Added ConnectionHandler trait with default on_accept / on_disconnected lifecycle callbacks and PostConnectionAction for post-disconnect control flow.
  • Wired the handler into the RdpServer::run() accept loop (reject-before-run and stop-after-disconnect behaviors).
  • Extended the server builder with with_connection_handler() and plumbed the handler into RdpServer::new().

Reviewed changes

Copilot reviewed 2 out of 2 changed files in this pull request and generated 1 comment.

File Description
crates/ironrdp-server/src/server.rs Defines ConnectionHandler / PostConnectionAction and integrates callbacks into the accept loop.
crates/ironrdp-server/src/builder.rs Adds builder plumbing to configure and pass a ConnectionHandler into RdpServer.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread crates/ironrdp-server/src/server.rs
Move per-connection cleanup above the ConnectionHandler callback
so it runs even when on_disconnected returns PostConnectionAction::Stop.
Copy link
Copy Markdown
Member

@CBenoit Benoît Cortier (CBenoit) left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Perfect! Thank you!

@CBenoit Benoît Cortier (CBenoit) merged commit 5c08c7f into Devolutions:master Apr 8, 2026
10 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Development

Successfully merging this pull request may close these issues.

4 participants