Channel Architecture
RDP supports up to 32 static channels per connection:- 1 mandatory I/O channel: Carries graphics, input, and control traffic
- 31 optional static channels: Custom bidirectional data streams
Static Virtual Channels (SVCs)
Static channels are established during connection setup and persist for the session lifetime.Core Concepts
Channel Definition — SVCs are registered in the Client Network Data GCC block:- 8-byte name: ASCII identifier (e.g.,
"CLIPRDR","RDPSND","RDPDR") - Options: Compression settings
- Channel ID: Assigned by server during Basic Settings Exchange
CHANNEL_PDU_HEADER):
ironrdp-svc/src/lib.rs:655-686.
Implementing an SVC
Implement theSvcProcessor trait:
ironrdp-svc/src/lib.rs:258-295.
SvcMessage and Encoding
Response PDUs must implementSvcEncode:
SvcMessage:
ironrdp-svc/src/lib.rs:68-121.
Registering Channels
Add channels to the connector before connection:StaticChannelSet:
- Type:
get_by_type::<MyChannel>() - Channel ID:
get_by_channel_id(channel_id) - Channel Name:
get_by_channel_name(&name)
ironrdp-svc/src/lib.rs:441-607.
Processing SVC Traffic
During the active session, route SVC data to the appropriate channel:client_encode_svc_messages.
Compression
Specify compression behavior viaCompressionCondition:
ChannelOptions flags in the Channel Definition:
COMPRESS_RDP: Compress if RDP data is compressedCOMPRESS: Always compress
ironrdp-svc/src/lib.rs:123-132 and make_channel_options at line 426.
Example: Clipboard Channel
The clipboard channel (CLIPRDR) demonstrates a complete SVC implementation:crates/ironrdp-cliprdr for the full implementation.
Dynamic Virtual Channels (DVCs)
Dynamic channels are created at runtime over theDRDYNVC static channel.
DRDYNVC Protocol
The DRDYNVC channel manages dynamic channel lifecycle:- Create Request: Client requests a new DVC by name
- Create Response: Server assigns a dynamic channel ID
- Data: Bidirectional data transfer using the channel ID
- Close: Either side closes the channel
ironrdp-dvc/src/pdu.rs.
Implementing a DVC
Implement theDvcProcessor trait:
ironrdp-dvc/src/lib.rs:40-59.
DvcMessage and Encoding
DVC messages are trait objects:DvcEncode for your response types:
DvcMessage:
Data Splitting
Large DVC messages are automatically split:DataFirstPdu with total length:
ironrdp-dvc/src/lib.rs:61-102.
Client-Side DVC Management
UseDvcClient to manage dynamic channels:
ironrdp-dvc/src/client.rs.
Server-Side DVC Management
UseDvcServer for server-side channel management:
ironrdp-dvc/src/server.rs.
Example: Display Control (EGFX)
The Enhanced Graphics Pipeline uses a DVC:crates/ironrdp-displaycontrolcrates/ironrdp-egfx
Encoding and Sending
SVC Encoding
Full encoding with MCS/X.224/TPKT headers:- Chunkifies messages into ~1600 byte chunks
- Adds
CHANNEL_PDU_HEADERto each chunk - Wraps in
MCS::SendDataRequest - Wraps in X.224 Data TPDU
- Adds TPKT header
ironrdp-svc/src/lib.rs:230-256.
DVC Encoding
Wrap DVC messages in DRDYNVC PDUs, then encode as SVC:ironrdp-dvc/src/lib.rs:61-102.
Channel Lifecycle
SVC Lifecycle
- Registration: Call
with_static_channel()before connection - Negotiation: Channel included in Client Network Data GCC block
- Assignment: Server assigns channel ID in Server Network Data
- Joining: Client sends Channel Join Request (unless skipped)
- Active:
start()called, bidirectional communication enabled - Termination: Channel closes when session ends
DVC Lifecycle
- Registration: Register DVC processor with
DvcClient - Creation: Client sends Create Request over DRDYNVC
- Assignment: Server responds with Create Response containing channel ID
- Active:
start()called, bidirectional communication enabled - Closure: Either side sends Close PDU
- Cleanup:
close()called, resources released
Built-in Channels
IronRDP provides implementations for common channels:| Crate | Channel Name | Type | Description |
|---|---|---|---|
ironrdp-cliprdr | CLIPRDR | SVC | Clipboard redirection (MS-RDPECLIP) |
ironrdp-rdpdr | RDPDR | SVC | Device redirection (MS-RDPEFS) |
ironrdp-rdpsnd | RDPSND | SVC | Audio output (MS-RDPEA) |
ironrdp-echo | ECHO | SVC | Echo test channel |
ironrdp-displaycontrol | Microsoft::Windows::RDS::DisplayControl | DVC | Display configuration |
ironrdp-egfx | Microsoft::Windows::RDS::Graphics | DVC | Enhanced graphics pipeline |
ironrdp-rdpeusb | URBDRC | DVC | USB redirection |
ironrdp-ainput | Microsoft::Windows::RDS::Input | DVC | Advanced input |
Best Practices
Do:
- Implement proper error handling in
process()methods - Return empty
Vecwhen no responses are needed - Use meaningful channel names (8 bytes for SVC, descriptive for DVC)
- Leverage automatic chunkification — don’t manually split PDUs
- Downcast channels safely using
channel_processor_downcast_ref()
- Block in
process()orstart()methods (no I/O) - Return
Nonefromstart()unless explicitly intentional - Assume chunk size — use constants (
CHANNEL_CHUNK_LENGTH,MAX_DATA_SIZE) - Forget to implement
AsAny(useimpl_as_any!macro) - Mix SVC and DVC encoding — they have different lifecycles
Debugging Channels
Enable tracing to observe channel traffic:STYLE.md for logging conventions.
References
- SVC Implementation:
crates/ironrdp-svc/src/lib.rs - DVC Implementation:
crates/ironrdp-dvc/src/lib.rs - Clipboard Example:
crates/ironrdp-cliprdr - Device Redirection:
crates/ironrdp-rdpdr - MS-RDPBCGR § 2.2.6: Virtual Channel PDU structures
- MS-RDPEDYC: Dynamic Virtual Channel Extension specification

