lamco-rdp-server Changelog
The full version history for lamco-rdp-server, newest first, following the
Keep a Changelog
structure the project uses in its repository. The current release is 1.4.4. Older detail beyond the
entries reproduced here lives in the repository CHANGELOG.md.
1.4.4 (2026-07-03)
Added
Unified multi-transport accept layer. A Listener trait and
AcceptDispatcher put protocol and transport binding behind one uniform interface.
- AF_VSOCK transport for Hyper-V Enhanced Session Mode (closes #52). Tri-state
config (
auto,enabled,disabled) with Hyper-V DMI auto-detection. Enabled by thevsockCargo feature. - WebSocket and RDCleanPath transport for browser and WASM clients, which
removes the separate ws-rdp-proxy from production deployments. Enabled by the
websocketCargo feature. This transport ships experimental in 1.4.4 (not yet exercised end to end against the WASM client). - LISTEN_FDS multi-fd socket activation. systemd can pass TCP, Unix, vsock, and WebSocket file descriptors together to one binary; descriptors are dispatched by socket name with positional fallback.
Vulkan Video encoder. Cross-vendor H.264 encoding via
VK_KHR_video_encode_h264, working on NVIDIA, Intel, and AMD GPUs with Vulkan Video
driver support. Enabled by the vulkan-video Cargo feature, inside the
hardware-encoding umbrella alongside VA-API and NVENC.
HTTP metrics server. Prometheus /metrics and JSON /health
endpoints on a lightweight tiny-http server. Enabled by the metrics-server Cargo feature.
Session health sensor framework. A HealthSensor trait with concrete
sensors for PipeWire, Portal, Mutter, EGFX, and the active encoder backend; a
SensorRegistry for per-session ownership plus a snapshot collector; and closed-loop
signaling where damage detection feeds encoding decisions and compositor-crash detection cascades
through the session lifecycle. The GUI Status and Performance tabs surface health output alongside
live damage-source, FPS, and activity telemetry.
Linux-to-Windows clipboard file copy on native installs, via
initiate_file_copy with a live RDP sender wired into the FUSE read handler.
Unicode keyboard input. XKB keysym mapping for non-ASCII characters.
COSMIC pointer injection via /dev/uinput as an interim path while
the COSMIC input portal matures.
PAM environment self-check. At startup the server reads the kernel
no_new_privs bit from /proc/self/status; when it is set, PAM
authentication is advertised as unavailable (the sgid-shadow unix_chkpwd helper
cannot elevate, so every login would fail) and the server falls back loudly to the recommended
auth method.
OpenH264 licensing surface. A --licenses flag prints the
third-party license notices, reproducing Cisco's OpenH264 binary license in full. The license text
also ships in the package, and in the Flatpak under /app/share/licenses. Cisco's
attribution appears in the EGFX codec settings, where H.264 is configured.
Changed
- Session lifecycle is now per-connection on GNOME/Mutter. A
SessionLifecyclePolicyabstraction (PersistentversusPerConnection) replaces the single long-lived RemoteDesktop and ScreenCast session. Mutter Direct creates a fresh, dialog-free session on each connect and releases it on disconnect, so the server serves many sequential RDP sessions without a restart. Previously Mutter's idle timeout reaped the one session about eight seconds after a client left, with no rebuild path. - License: BUSL-1.1 revision. The Licensor is now Lamco Development LLC following LLC formation. The Additional Use Grant is a single conditional grant with four qualifying classes (non-profit, single server instance, non-commercial education or research, and Community Edition), and the Change Date is 2029-06-01, on which this version converts to Apache-2.0.
- lamco-pipewire de-bundled to crates.io 0.4.4 (was a vendored copy); 0.4.4
carries the DMA-BUF negotiation fix for the zero-data root cause.
xdg-desktop-portal-genericlikewise de-bundled to crates.io 0.4.0. - MSRV is 1.89 (was 1.88), on Rust edition 2024.
- IronRDP fork relocated to the organization-owned
lamco-admin/IronRDPand curated-rebased onto upstream master. The accept path migrated torun_connection_with(stream, TransportTls::AlreadyDone), andRdpsndServerHandlersplit intochoose_formatplusstart. - Dependency upgrades: ashpd 0.13.7 (portal notification, background, and secret features), cudarc 0.19 for NVENC, vk-video 0.3.1, and the pipewire stack advanced accordingly.
- ZGFX compression default remains
never. An interim change toalwayswas reverted: the LZ77 variant degrades to quadratic time on already-compressed H.264 payloads and stalls the EGFX pipeline on large IDR frames. - EGFX gate timer is now per-connection (was per-server-uptime, which broke multi-connection scenarios), with a gate timeout for clients that never open a DVC channel.
- libei is the default input protocol, with touch and relative-pointer support.
- VA-API hardened: reference-frame management, rate control, triple-buffered output, and SIMD NV12 conversion.
guiis now a default Cargo feature. A plaincargo build --releaseproduces bothlamco-rdp-serverandlamco-rdp-server-gui; packaging that already opted intogui(Debian, RPM Fusion, OBS, Flatpak) is unchanged. Headless, server-only builds must now pass--no-default-featuresand re-enable what they need.- OpenH264 on Flatpak reflects the freedesktop extension retirement. The
org.freedesktop.Platform.openh264extension is retired and absent on the 25.08 runtime, andcodecs-extra(x264/ffmpeg) is not a patent-covered substitute. Software H.264 uses Cisco's binary, which the user installs separately per Cisco's license; the app does not bundle or auto-download it, and the not-found guidance now points to hardware encoding, a native package, or Cisco's release list.
Fixed
- PAM was unusable on the hardened system service. The system unit's
seccomp options imply
NoNewPrivileges, which the startup self-check read as "PAM unavailable", silently downgradingauth_method=pamto unauthenticated in exactly the multi-user case where PAM matters. The system unit now joins theshadowgroup sopam_unixreads/etc/shadowdirectly, keeping the full seccomp hardening, and the self-check recognizes the direct-read path. - Packaged systemd units SIGSYS-killed the server at startup and made PAM
authentication impossible. Both units dropped
NoNewPrivileges=yesand theSystemCallFilter=~@privileged @resourcesdeny: libpipewire's realtime scheduling setup crashed the server during PipeWire init, the@privilegeddeny killed pam_unix's in-processsetuid, andNoNewPrivilegesblocked the sgid-shadowunix_chkpwdhelper and the setuidfusermount3from elevating. The@system-serviceallowlist,ProtectSystem=strict, andRestrictRealtime=yesremain in place. - GNOME served only one RDP session before needing a restart. Root-caused to the persistent-session model colliding with Mutter's idle-timeout reaping, and fixed by the per-connection lifecycle rework plus its follow-on races: capture-node rebinding is now keyed on session re-establishment rather than PipeWire node-id equality; the pipeline no longer pauses on unserved or probe disconnects; EGFX shared handler state resets on each new connection; and Mutter clipboard signal listeners re-subscribe after re-establishment.
- GNOME 49 input stopped working until a lazy Mutter EIS lifecycle with a
correct keep-alive connection was added (closes #45). The EIS capability bind mask is now
accumulated from advertised
Seat::Capabilityevents instead of a blanket union. - KDE Windows-to-Linux clipboard file transfer was broken because Klipper
re-announced a file URI as
text/plainand the cooperation handler forwarded that re-announcement, discarding the portal's block decision;SendInitiateCopyis now gated on the portal sync decision. The persistent clipboard monitor also bindsext-data-control-v1(which KWin exposes, notwlr-data-control-v1), and Klipper empty-selection clearing is gated to KDE. - sway and wlroots color skew (blue rendered as brown): the portal-generic
direct-frame bridge defaulted every frame to BGRx, but sway delivers
Xbgr8888(RGBx byte order) via wlr-screencopy. The bridge now honors thewl_shmcapture format and swaps the R and B channels in place. - COSMIC delivered zero frames compared with 1.4.2; capture is now routed to the portal-generic embedded strategy via a capture-protocol gate.
- WebSocket and RDCleanPath listener could drop a connection mid-handshake when another transport won the shared accept race. The handshake now runs in a background task off the cancellable accept path.
- SIMD damage detection corrected on aarch64 (NEON) and AVX2; the AVX2 kernel is now runtime-dispatched so stock baseline-x86_64 packages use it instead of falling back to scalar.
- GUI fixes: 38 text-input fields that silently discarded typed text now
write back to the fields the renderer reads from; notification messages render; file dialogs
degrade gracefully when no FileChooser portal is present; startup skips the wgpu hardware
probe on virtual GPUs;
LAMCO_GUI_SOFTWAREis honored before the GPU probe; "Stop Server" now stops a D-Bus-connected server; and log-directory writability is validated with pre-init failures classified correctly. - GUI failed to detect externally-started servers. The headless server now
writes its PID to
$XDG_RUNTIME_DIR/lamco-rdp-server.pidat startup and removes it on shutdown, so a server started via systemd, SSH, or any other launcher is visible to the GUI. - TLS material now self-heals at startup, after logging init, and Snap sandboxing is detected, fixing a confusing headless-start failure after a user config was removed.
- Health monitoring no longer flags an idle static desktop as a video stall (health is driven by authoritative stream-state events, not frame timing), reports an idle capture stream as healthy between clients, and gates the EGFX channel-closed warning on an active client.
- EGFX: V8 client support and a handler-state race (#4); uncompressed
fallback, buffer-tier selection, and virgl flip;
gfx_server_handlepreserved under contention;egfx_needs_initreset on reconnection; OpenH264CONSTANT_IDcorrected from 1 to 0; SPS/PPS prepending removed on P-frames; and degenerate metablock rects rejected so strict RDP clients no longer disconnect. - Clipboard: Mutter D-Bus array-of-strings MIME parsing, double-request
caching, poll-based FD reads, and FD close after
selection_write_done; FUSE access/getxattr/listxattr operations implemented; all pending serials answered in Windows-to-Linux file paste; stale-format and idempotent-disconnect edge cases; andfile://URIs percent-encoded with three duplicate implementations de-duplicated. - EIS: pointer-absolute device separation, a RefCell panic, event timeouts,
deferred activation,
start_emulating, the DMA-BUF-to-MemFd fallback on virtual GPUs, a keycode offset, and capture-device regions for coordinate mapping. - Portal input injection recovers when the ScreenCast stream pauses (#30); virtual GPUs are detected and forced to MemFd over DMA-BUF, which was returning zero data (#43, #47).
- Protocol and compatibility: IPv6 dual-stack listen; FreeRDP 3.x TLS
negotiation (#40);
auth_method=noneno longer rejects clients that send credentials (#35); FUSE clipboard stale-mount cleanup on restart (#46); Hyper-V Enhanced Session Mode via AF_VSOCK (#52); andcliprdrfile transfer aligned with the new auto Lock/Unlock contract.
Security
- Startup exposure warning when
auth_method=noneis combined with a non-loopbacklisten_addr, that is, an unauthenticated RDP listener reachable on the network. The Portal still gates screen capture interactively, so this warns rather than refuses. unsafe_codelints migrated to#[expect(reason = "...")]with documented justification.- Eliminated undefined behavior in
server_process.
Previous releases
1.4.2 (2026-03-10)
DirectChannel capture and protocol routing; PAM authentication with rate limiting and packaged
service files; figment-based config loading with --generate-config; compositor-aware
input auto-detection (libei versus wlr); libei default input with touch and relative-pointer
support; VA-API hardening; EGFX improvements (V8 bitmap fallback, per-connection gate timer, DVC
gate timeout); clipboard eager-fetch for data-control providers. Fixes: V8 EGFX frame drops (#34),
idle CPU spin loops (#36), silent capture failure when WAYLAND_DISPLAY is unset
(#37), and FUSE mount-failure messaging (#39).
1.4.1 (2026-03-03)
Packaging maintenance release. Distribution-channel fixes (cros-libva quilt patch refresh, systemd hardening, libfuse3 runtime dependency). No application code changes from 1.4.0.
1.4.0 (2026-02-24)
Session health monitoring with a D-Bus signal relay; clipboard provider architecture built on
ext-data-control-v1 and wlr-data-control-v1 with a persistent
data-control monitor; view-only (ScreenCast-only) mode; OpenH264 dynamic loading of Cisco's
pre-built binary; the Community Edition designation for the Flatpak and Snap distributions; and a
D-Bus management interface.
Full history for 1.3.x and earlier is in the repository CHANGELOG.md (see the
repository link below).
See also: Documentation, Features, Platforms, Sessions, FAQ, Download, and the per-compositor guides (GNOME/Mutter, KDE/KWin, sway/wlroots, Hyprland, COSMIC).