Open SourceLamco RDP › Clipboard-rdp

lamco-rdp-clipboard

IronRDP CliprdrBackend implementation — bridges CLIPRDR SVC to any ClipboardSink

v0.3 · MIT/Apache-2.0

IronRDP CLIPRDR, done right

IronRDP’s CLIPRDR static virtual channel is where clipboard events arrive in an RDP session — but the trait surface is synchronous, called from the message-processing loop, and has no built-in concept of a backend abstraction. lamco-rdp-clipboard provides the bridge: a CliprdrBackend implementation that queues events for async processing and delegates to any ClipboardSink from lamco-clipboard-core. File transfer (MS-RDPECLIP FileContents) included.

ARCHITECTURE

How the bridge works

┌────────────────────────────────────────────────────────────────────┐
│                       lamco-rdp-clipboard                          │
│  ┌─────────────────────┐         ┌───────────────────────────────┐ │
│  │ RdpCliprdrBackend   │◄───────►│   ClipboardSink (trait)       │ │
│  │ (CliprdrBackend)    │         │   - Portal                    │ │
│  └─────────────────────┘         │   - X11                       │ │
│            ▲                     │   - Memory (testing)          │ │
│            │                     └───────────────────────────────┘ │
│            ▼                                                       │
│  ┌─────────────────────┐                                           │
│  │ ironrdp-cliprdr     │                                           │
│  │ (CLIPRDR SVC)       │                                           │
│  └─────────────────────┘                                           │
└────────────────────────────────────────────────────────────────────┘

Event model

The ClipboardEvent enum covers every CLIPRDR interaction:

Event Meaning
ReadyBackend initialized, channel ready
RequestFormatListRequest to send local format list
NegotiatedCapabilitiesCapabilities negotiated with peer
RemoteCopyRemote clipboard content changed
FormatDataRequestPeer requests specific format data
FormatDataResponsePeer sent requested data
FileContentsRequestPeer requests a file chunk
FileContentsResponsePeer sent a file chunk
Lock / UnlockClipboard lock operations

Quick start

Cargo.toml
[dependencies]
lamco-rdp-clipboard = "0.3"
factory + event loop
use lamco_rdp_clipboard::{RdpCliprdrFactory, ClipboardEvent};
use ironrdp_cliprdr::backend::CliprdrBackendFactory;

// Create a factory with a temp directory for file transfers
let factory = RdpCliprdrFactory::new("/tmp/clipboard");

// Subscribe to clipboard events
let receiver = factory.subscribe();

// Build a backend for IronRDP
let backend = factory.build_cliprdr_backend();

// Process events asynchronously
loop {
    for event in receiver.drain() {
        match event {
            ClipboardEvent::Ready => println!("Clipboard ready"),
            ClipboardEvent::RemoteCopy { formats } => {
                println!("Remote copy: {} formats", formats.len());
            }
            ClipboardEvent::FormatDataRequest { format_id } => {
                println!("Data requested: {:?}", format_id);
            }
            _ => {}
        }
    }
}

The backend is non-blocking by design — CliprdrBackend trait methods queue events instead of blocking the RDP message loop.