### Install DevolutionsGateway PowerShell Module Source: https://github.com/devolutions/ironrdp/blob/master/web-client/iron-svelte-client/README.md This PowerShell command installs the `DevolutionsGateway` module, which provides cmdlets for managing Devolutions Gateway resources, including token generation. ```powershell Install-Module -Name DevolutionsGateway ``` -------------------------------- ### Capture Screenshot (Blocking Client Example) Source: https://context7.com/devolutions/ironrdp/llms.txt Capture a screenshot from a remote RDP server using a blocking client example. This example demonstrates how to save the remote desktop content to a file, with options for compression. ```bash # Capture a screenshot from an RDP server cargo run --example=screenshot -- --host -u -p -o out.png # With compression enabled cargo run --example=screenshot -- --host 192.168.1.100 -u admin -p secret -o screenshot.png --compression-enabled true --compression-level 3 ``` -------------------------------- ### Run tokengen Server with Cargo Source: https://github.com/devolutions/ironrdp/blob/master/web-client/iron-svelte-client/README.md This command executes the `tokengen` server using Cargo, the Rust package manager. This is part of the automatic token generation process and requires the Rust toolchain to be installed. ```shell cargo run -- server ``` -------------------------------- ### Install Iron Remote Desktop Web Component Source: https://github.com/devolutions/ironrdp/blob/master/web-client/iron-remote-desktop/README.md Installs the Iron Remote Desktop Web Component using npm. This command fetches the component from JFrog Artifactory, making it available for use in your project. ```shell $ npm install @devolutions/iron-remote-desktop ``` -------------------------------- ### Rust Documentation: Inline Code Comments as Sentences Source: https://github.com/devolutions/ironrdp/blob/master/STYLE.md Advises on writing inline code comments in Rust as proper sentences, starting with a capital letter and ending with a period, to encourage more contextual information. Exceptions are made for very brief comments. ```rust // GOOD // When building a library, `-` in the artifact name are replaced by `_`. let artifact_name = format!( "{}.wasm" , package.replace('-', "_")); // BAD // when building a library, `-` in the artifact name are replaced by `_` let artifact_name = format!( "{}.wasm" , package.replace('-', "_")); ``` -------------------------------- ### Initialize IronRDP WebComponent in Vite + Svelte + TS Source: https://github.com/devolutions/ironrdp/blob/master/web-client/iron-remote-desktop/index.html This snippet shows how to select the IronRDP WebComponent using its tag name and attach an event listener for the 'ready' event. The 'ready' event is emitted when the component has finished loading and is ready for interaction. The event detail provides access to user interaction methods, such as setting visibility. ```typescript var el = document.querySelector('iron-remote-desktop'); el.addEventListener('ready', (e) => { console.log('WebComponent Loaded'); e.detail.irgUserInteraction.setVisibility(true); }); ``` -------------------------------- ### Rust: Pushing Allocations to Call Site Source: https://github.com/devolutions/ironrdp/blob/master/STYLE.md Suggests that if an allocation is necessary, it should be performed by the caller rather than the function itself. This makes the performance costs explicit and allows the caller to reuse existing allocations efficiently. ```rust // GOOD fn frobnicate(s: String) { /* snip */ } // BAD fn frobnicate(s: &str) { let s = s.to_string(); /* snip */ } ``` -------------------------------- ### Rust Documentation: Linking to Reference Documents Source: https://github.com/devolutions/ironrdp/blob/master/STYLE.md Demonstrates the correct way to add doc comments in Rust, specifically focusing on linking to external reference documents using a reference-style link format. This improves cross-referencing between code and specifications. ```rust // GOOD /// [2.2.3.3.8] Server Drive Query Information Request (DR_DRIVE_QUERY_INFORMATION_REQ) /// /// The server issues a query information request on a redirected file system device. /// /// [2.2.3.3.8]: https://docs.microsoft.com/en-us/openspecs/windows_protocols/ms-rdpefs/e43dcd68-2980-40a9-9238-344b6cf94946 pub struct ServerDriveQueryInformationRequest { /* snip */ } // BAD (no doc comment) pub struct ServerDriveQueryInformationRequest { /* snip */ } // BAD (non reference-style links make barely readable, very long lines) /// [2.2.3.3.8](https://docs.microsoft.com/en-us/openspecs/windows_protocols/ms-rdpefs/e43dcd68-2980-40a9-9238-344b6cf94946) Server Drive Query Information Request (DR_DRIVE_QUERY_INFORMATION_REQ) /// /// The server issues a query information request on a redirected file system device. pub struct ServerDriveQueryInformationRequest { /* snip */ } // BAD (long link) /// [2.2.3.3.8 Server Drive Query Information Request (DR_DRIVE_QUERY_INFORMATION_REQ)] /// /// The server issues a query information request on a redirected file system device. /// /// [2.2.3.3.8 Server Drive Query Information Request (DR_DRIVE_QUERY_INFORMATION_REQ)]: https://docs.microsoft.com/en-us/openspecs/windows_protocols/ms-rdpefs/e43dcd68-2980-40a9-9238-344b6cf94946 pub struct ServerDriveQueryInformationRequest { /* snip */ } ``` -------------------------------- ### Rust: Formatting Size Definitions with Inline Comments Source: https://github.com/devolutions/ironrdp/blob/master/STYLE.md Demonstrates the recommended way to define sizes and lengths in Rust using inline comments for clarity. This approach improves readability by associating each numerical value with its corresponding field name, making it easier to understand memory layouts and calculations. ```rust // GOOD const FIXED_PART_SIZE: usize = 1 /* Version */ + 1 /* Endianness */ + 2 /* CommonHeaderLength */ + 4 /* Filler */; // GOOD const FIXED_PART_SIZE: usize = 1 // Version + 1 // Endianness + 2 // CommonHeaderLength + 4; // Filler // GOOD fn size(&self) -> usize { 4 // ReturnCode + 4 // cBytes + self.reader_names.size() // mszReaderNames + 4 // dwState + 4 // dwProtocol + self.atr.len() // pbAtr + 4 // cbAtrLen } // BAD const FIXED_PART_SIZE: usize = 1 + 1 + 2 + 4; // BAD const FIXED_PART_SIZE: usize = size_of::() + size_of::() + size_of::() + size_of::(); // BAD fn size(&self) -> usize { size_of::() * 5 + self.reader_names.size() + self.atr.len() } ``` -------------------------------- ### Rust: Context Parameters First in Function Signatures Source: https://github.com/devolutions/ironrdp/blob/master/STYLE.md Recommends placing context parameters at the beginning of function signatures. This improves consistency, especially when non-context parameters are lambdas, and suggests packing multiple context parameters into a `struct Ctx` for better organization. ```rust // GOOD fn do_something(connector: &mut ClientConnector, certificate: &[u8]) { let public_key = extract_public_key(certificate); do_something_else(connector, public_key, |kind| /* … */); } fn do_something_else(connector: &mut ClientConnector, public_key: &[u8], op: impl Fn(KeyKind) -> bool) { /* ... */ } // BAD fn do_something(certificate: &[u8], connector: &mut ClientConnector) { let public_key = extract_public_key(certificate); do_something_else(|kind| /* … */, connector, public_key); } fn do_something_else(op: impl Fn(KeyKind) -> bool, connector: &mut ClientConnector, public_key: &[u8]) { /* ... */ } ``` -------------------------------- ### Enable Stub TLS Backend in Cargo.toml Source: https://github.com/devolutions/ironrdp/blob/master/crates/ironrdp-tls/README.md This example illustrates how to enable the `stub` TLS backend for `ironrdp-tls` in `Cargo.toml`. The stub backend is useful for compilation with minimal dependencies, but it will fail at runtime if used. This feature should be used cautiously and typically for testing or build-time purposes. ```toml ironrdp-tls = { version = "x.y.z", features = ["stub-tls"] } ``` -------------------------------- ### Control RDP Session with UserInteraction Methods Source: https://github.com/devolutions/ironrdp/blob/master/web-client/iron-remote-desktop/README.md Provides examples of essential `UserInteraction` methods for controlling an active RDP session. These include sending special key combinations, managing session visibility, resizing the display, and controlling clipboard functionality. ```typescript // Send Ctrl+Alt+Del userInteraction.ctrlAltDel(); // Send Meta key (Windows key) userInteraction.metaKey(); // Show or hide the rendering canvas userInteraction.setVisibility(true); // Set the canvas scaling behavior userInteraction.setScale('fit'); // or 'real', 'full' // Shutdown the active session userInteraction.shutdown(); // Enable or disable clipboard userInteraction.setEnableClipboard(true); // Resize the screen userInteraction.resize(1920, 1080, 1); // Set keyboard Unicode mode userInteraction.setKeyboardUnicodeMode(true); // Override cursor style userInteraction.setCursorStyleOverride('url("my-cursor.png")'); userInteraction.setCursorStyleOverride(null); // Reset to default ``` -------------------------------- ### Rust Helper Functions: Avoiding Single-Use Functions Source: https://github.com/devolutions/ironrdp/blob/master/STYLE.md Illustrates the preference for using blocks of code over single-use helper functions in Rust to avoid churn and tight coupling. Exceptions are made for cases requiring 'return' or '?' operators. ```rust // GOOD let buf = { let mut buf = WriteBuf::new(); buf.write_u32(42); buf }; // BAD let buf = prepare_buf(42); // Somewhere else fn prepare_buf(value: u32) -> WriteBuf { let mut buf = WriteBuf::new(); buf.write_u32(value); buf } ``` -------------------------------- ### Documenting Loop Invariants in Rust Source: https://github.com/devolutions/ironrdp/blob/master/STYLE.md Demonstrates the correct placement and format for documenting loop invariants in Rust code. Invariants should be placed before or at the beginning of the loop and clearly marked with 'INVARIANT:'. This aids in understanding the code's state during execution. ```rust // GOOD /// Computes the smallest index such that, if `x` is inserted at this index, the array remains sorted. fn insertion_point(xs: &[i32], x: i32) -> usize { let mut lo = 0; let mut hi = xs.len(); while lo < hi { // INVARIANT: for i in 0..lo: xs[i] < x // INVARIANT: for i in hi..: x <= xs[i] let mid = lo + (hi - lo) / 2; if xs[mid] < x { lo = mid + 1; } else { hi = mid; } } lo } // BAD fn insertion_point(xs: &[i32], x: i32) -> usize { let mut lo = 0; let mut hi = xs.len(); while lo < hi { let mid = lo + (hi - lo) / 2; if xs[mid] < x { lo = mid + 1; } else { hi = mid; } } // INVARIANT: for i in 0..lo: xs[i] < x // INVARIANT: for i in hi..: x <= xs[i] lo } ``` -------------------------------- ### Explaining Assumptions Referencing Invariants in Rust Source: https://github.com/devolutions/ironrdp/blob/master/STYLE.md Provides guidance on explaining non-obvious assumptions in Rust code by referencing established invariants. When referencing an invariant, do not use the 'INVARIANT:' prefix; instead, clearly state the assumption and its relation to the invariant. This improves code review clarity and prevents misunderstandings. ```rust // GOOD // Per invariants: width * dst_n_samples <= 10_000 * 4 < usize::MAX #[allow(clippy::arithmetic_side_effects)] let dst_stride = usize::from(width) * dst_n_samples; // BAD #[allow(clippy::arithmetic_side_effects)] let dst_stride = usize::from(width) * dst_n_samples; // BAD // INVARIANT: width * dst_n_samples <= 10_000 * 4 < usize::MAX #[allow(clippy::arithmetic_side_effects)] let dst_stride = usize::from(width) * dst_n_samples; ``` -------------------------------- ### Rust Logging: Info and Error Message Formatting Source: https://github.com/devolutions/ironrdp/blob/master/STYLE.md Demonstrates correct formatting for info and error log messages in Rust using the 'tracing' crate. Emphasizes starting info messages with a capital letter and using structured fields for diagnostic information in error messages. ```rust // GOOD info!("Connect to RDP host"); // BAD info!("connect to RDP host."); ``` ```rust // GOOD info!(%server_addr, "Looked up server address"); // BAD info!("Looked up server address: {server_addr}"); ``` ```rust // GOOD error!(?error, "Active stage failed"); error!(error = ?e, "Active stage failed"); error!(%error, "Active stage failed"); error!(error = format!( "{err:#}" ), "Active stage failed"); // BAD error!(?e, "Active stage failed"); error!(%err, "Active stage failed"); ``` -------------------------------- ### Defining Local Invariants in Rust Source: https://github.com/devolutions/ironrdp/blob/master/STYLE.md Shows the correct way to define local invariants within Rust code using the 'INVARIANT:' comment prefix. This is intended for invariants that hold true for a specific block of code, such as a loop or a section within a function. It contrasts with the 'BAD' example, which omits the prefix. ```rust // GOOD // INVARIANT: for i in 0..lo: xs[i] < x // BAD // for i in 0..lo: xs[i] < x ``` -------------------------------- ### Run IronRDP GUI Client (Rust) Source: https://github.com/devolutions/ironrdp/blob/master/crates/ironrdp-client-glutin/README.md This snippet demonstrates the command-line usage for running the IronRDP GUI client. It specifies essential parameters like username, password, and connection details. The command utilizes Rust's cargo build system. ```bash cargo run --bin ironrdp-gui-client -- -u SimpleUsername -p SimplePassword! --avc444 --thin-client --small-cache --capabilities 0xf 192.168.1.100:3389 ``` -------------------------------- ### Generate RSA Key Pair using OpenSSL Source: https://github.com/devolutions/ironrdp/blob/master/web-client/iron-svelte-client/README.md This snippet demonstrates how to generate an RSA key pair using OpenSSL, which is required for configuring the Devolutions Gateway. It includes commands for generating the private key and the corresponding public key in PEM format. ```shell $ openssl genrsa -out provisioner.key 2048 $ openssl rsa -in provisioner.key -outform PEM -pubout -out provisioner.pem ``` -------------------------------- ### Rust RDP Server Implementation with IronRDP Source: https://context7.com/devolutions/ironrdp/llms.txt Provides a framework for building RDP servers using the `ironrdp-server` crate. It includes handling keyboard and mouse input, managing display updates with bitmap data, and setting up server credentials and TLS. Requires `tokio` and `anyhow` for async operations and error handling. ```rust use ironrdp::server::{ RdpServer, RdpServerDisplay, RdpServerDisplayUpdates, RdpServerInputHandler, BitmapUpdate, DisplayUpdate, KeyboardEvent, MouseEvent, PixelFormat, Credentials, TlsIdentityCtx, }; use ironrdp::connector::DesktopSize; use std::num::{NonZeroU16, NonZeroUsize}; #[derive(Clone)] struct MyInputHandler; impl RdpServerInputHandler for MyInputHandler { fn keyboard(&mut self, event: KeyboardEvent) { println!("Keyboard event: {:?}", event); } fn mouse(&mut self, event: MouseEvent) { println!("Mouse event: {:?}", event); } } struct MyDisplayUpdates; #[async_trait::async_trait] impl RdpServerDisplayUpdates for MyDisplayUpdates { async fn next_update(&mut self) -> anyhow::Result> { // Generate a random colored rectangle update let width = NonZeroU16::new(100).unwrap(); let height = NonZeroU16::new(100).unwrap(); let stride = NonZeroUsize::new(400).unwrap(); // width * 4 bytes per pixel let mut data = vec![0u8; 100 * 100 * 4]; // Fill with color data... Ok(Some(DisplayUpdate::Bitmap(BitmapUpdate { x: 0, y: 0, width, height, format: PixelFormat::BgrA32, data: data.into(), stride, }))) } } #[derive(Clone)] struct MyDisplayHandler; #[async_trait::async_trait] impl RdpServerDisplay for MyDisplayHandler { async fn size(&mut self) -> DesktopSize { DesktopSize { width: 1920, height: 1080 } } async fn updates(&mut self) -> anyhow::Result> { Ok(Box::new(MyDisplayUpdates)) } } #[tokio::main] async fn main() -> anyhow::Result<()> { let bind_addr = "127.0.0.1:3389".parse()?; let handler = MyInputHandler; let display = MyDisplayHandler; // Build server with TLS identity let identity = TlsIdentityCtx::init_from_paths("cert.pem", "key.pem")?; let acceptor = identity.make_acceptor()?; let mut server = RdpServer::builder() .with_addr(bind_addr) .with_hybrid(acceptor, identity.pub_key) // Enable NLA .with_input_handler(handler) .with_display_handler(display) .build(); // Set authentication credentials server.set_credentials(Some(Credentials { username: "user".to_owned(), password: "password".to_owned(), domain: None, })); server.run().await } ``` -------------------------------- ### Run RDP Client (CLI) Source: https://context7.com/devolutions/ironrdp/llms.txt Connect to an RDP server using the `ironrdp-client` binary. This command-line tool allows for basic RDP connections with specified host, username, password, and an optional port. ```bash # Connect to an RDP server using the built-in client cargo run --bin ironrdp-client -- --username --password # Example with explicit port cargo run --bin ironrdp-client -- 192.168.1.100 --username admin --password secret --port 3389 ``` -------------------------------- ### Rust: Preferring Less Than/Less Than or Equal To Operators Source: https://github.com/devolutions/ironrdp/blob/master/STYLE.md Advocates for using `<` and `<=` operators instead of `>` and `>=` for range checks. This promotes a consistent, left-to-right reading order, making conditions easier to visualize and understand. ```rust /// GOOD if lo <= x && x <= hi {} if x < lo || hi < x {} /// BAD if x >= lo && x <= hi {} if x < lo || x > hi {} ``` -------------------------------- ### Rust: Positive State Invariant Checks Source: https://github.com/devolutions/ironrdp/blob/master/STYLE.md Establishes invariants positively by preferring `if !invariant` or `check_invariant` over checking the negated condition. This improves code readability by clearly stating the condition under which the code proceeds. ```rust // GOOD if !(idx < len) { return None; } // GOOD check_invariant(idx < len)?; // GOOD ensure!(idx < len); // GOOD debug_assert!(idx < len); // GOOD if idx < len { /* ... */ } else { return None; } // BAD if idx >= len { return None; } ``` -------------------------------- ### HTML Usage of Iron Remote Desktop Web Component Source: https://github.com/devolutions/ironrdp/blob/master/web-client/iron-remote-desktop/README.md Illustrates how to embed and configure the Iron Remote Desktop Web Component within an HTML page. It shows basic usage and how to set component parameters via attributes. ```html ``` -------------------------------- ### Rust Enum for Network Codes (Initial) Source: https://github.com/devolutions/ironrdp/blob/master/crates/ironrdp-pdu/README.md An example of a Rust enum representing network codes. This basic enum is not suitable for protocols that require forward or backward compatibility as it cannot accommodate new values without modification. ```rust #[repr(u32)] #[derive(Debug, Clone, Copy, PartialEq, Eq)] pub enum MyNetworkCode { FirstValue = 0, SecondValue = 1, } ``` -------------------------------- ### Rust Local Helper Functions: Placement and Nesting Source: https://github.com/devolutions/ironrdp/blob/master/STYLE.md Provides guidance on the placement and nesting of local helper functions in Rust. Nested functions should be placed at the end of the enclosing function and not exceed one level of nesting. ```rust // GOOD fn func() -> u32 { return helper(); fn helper() -> u32 { /* ... */ } } // BAD fn func() -> u32 { fn helper() -> u32 { /* ... */ } helper() } ``` -------------------------------- ### Connect to RDP Session using UserInteraction Source: https://github.com/devolutions/ironrdp/blob/master/web-client/iron-remote-desktop/README.md Demonstrates how to establish an RDP connection using the `connect` method of the `UserInteraction` object. This method requires credentials, destination details, and optional parameters for session configuration. ```typescript connect( username: string, password: string, destination: string, proxyAddress: string, serverDomain: string, authToken: string, desktopSize?: DesktopSize, preConnectionBlob?: string, kdc_proxy_url?: string, use_display_control: boolean, ): Observable; ``` -------------------------------- ### Rust: Avoiding Unnecessary Allocations Source: https://github.com/devolutions/ironrdp/blob/master/STYLE.md Emphasizes avoiding heap allocations like `Vec` or `String` when iterators or other efficient alternatives suffice. This practice leads to better runtime performance by reducing memory overhead and allocation costs. ```rust // GOOD let second_word = text.split(' ').nth(1)?; // BAD let words: Vec<&str> = text.split(' ').collect(); let second_word = words.get(1)?; ``` -------------------------------- ### Rust User Code Handling Unknown Network Codes Source: https://github.com/devolutions/ironrdp/blob/master/crates/ironrdp-pdu/README.md Example of user code that relies on matching the `Unknown` variant of a network code enum. This code can fail silently when the library is updated to recognize a previously unknown value. ```rust // User code fn handle_network_code(reader: /* … */) { let value = reader.read_u32(); let code = MyNetworkCode::from_u32(value); if code == MyNetworkCode::Unknown(2) { // The library doesn’t know about this value yet, but we need to handle it because […] } } ``` -------------------------------- ### Encoding with WriteBuf Buffer Management in Rust Source: https://github.com/devolutions/ironrdp/blob/master/crates/ironrdp-pdu/README.md Illustrates encoding a PDU using `WriteBuf`, which simplifies buffer management by handling memory allocation and tracking the filled region automatically. This approach is more concise and less error-prone. ```rust pub fn encode_buf(pdu: &T, buf: &mut WriteBuf) -> PduResult { let pdu_size = pdu.size(); let dst = buf.unfilled_to(pdu_size); let mut cursor = WriteCursor::new(dst); encode_cursor(pdu, &mut cursor)?; let written = cursor.pos(); buf.advance(written); Ok(written) } fn somewhere_else() -> PduResult<()> { let mut state_machine = /* … */; let mut buf = WriteBuf::new(); while !state_machine.is_terminal() { let pdus = state_machine.step(); buf.clear(); for pdu in pdus { encode_buf(&pdu, &mut buf)?; } let filled = buf.filled(); // Do something with `filled` } Ok(()) } ``` -------------------------------- ### Rust Clipboard Integration with IronRDP Source: https://context7.com/devolutions/ironrdp/llms.txt Implements clipboard sharing between client and server using the `ironrdp-cliprdr` crate. It covers initializing the clipboard channel, initiating copy and paste operations, and submitting clipboard data responses. Requires a `CliprdrBackend` implementation. ```rust use ironrdp::cliprdr::{Cliprdr, CliprdrClient, CliprdrSvcMessages}; use ironrdp::cliprdr::backend::CliprdrBackend; use ironrdp::cliprdr::pdu::{ClipboardFormat, ClipboardFormatId, OwnedFormatDataResponse}; // Initialize clipboard channel with a backend implementation fn setup_clipboard(backend: Box) -> CliprdrClient { Cliprdr::new(backend) } // Initiate copy operation (when user copies to clipboard) fn initiate_copy( cliprdr: &CliprdrClient, formats: &[ ClipboardFormat ], ) -> Result, ironrdp_pdu::PduError> { cliprdr.initiate_copy(formats) } // Initiate paste operation (request data from remote) fn initiate_paste( cliprdr: &CliprdrClient, format_id: ClipboardFormatId, ) -> Result, ironrdp_pdu::PduError> { cliprdr.initiate_paste(format_id) } // Submit clipboard data response fn submit_data( cliprdr: &CliprdrClient, response: OwnedFormatDataResponse, ) -> Result, ironrdp_pdu::PduError> { cliprdr.submit_format_data(response) } ``` -------------------------------- ### Generate Devolutions Gateway Token with PowerShell Source: https://github.com/devolutions/ironrdp/blob/master/web-client/iron-svelte-client/README.md This PowerShell command generates a Devolutions Gateway token of type ASSOCIATION. It requires the path to the private key, the destination host, and specifies the RDP application protocol. ```powershell New-DGatewayToken -Type ASSOCIATION -PrivateKeyFile -DestinationHost -ApplicationProtocol rdp ``` -------------------------------- ### Documenting Field Invariants in Rust Source: https://github.com/devolutions/ironrdp/blob/master/STYLE.md Illustrates how to document invariants for struct fields in Rust. The 'INVARIANT:' tag should be placed within the doc comment directly associated with the field declaration. This ensures invariants are visible in generated documentation and IDE tooltips. ```rust // GOOD struct BitmapInfoHeader { /// INVARIANT: `width.abs() <= u16::MAX` width: i32, } // BAD /// INVARIANT: `width.abs() <= u16::MAX` struct BitmapInfoHeader { width: i32, } // BAD struct BitmapInfoHeader { width: i32, } impl BitmapInfoHeader { fn new(width: i32) -> Option { // INVARIANT: width.abs() <= u16::MAX if !(width.abs() <= i32::from(u16::MAX)) { return None; } Some(BitmapInfoHeader { width }) } } ``` -------------------------------- ### Encoding with Vec Buffer Management in Rust Source: https://github.com/devolutions/ironrdp/blob/master/crates/ironrdp-pdu/README.md Demonstrates how to encode a PDU into a `Vec`, including manual buffer resizing and tracking of the filled region. This approach requires more explicit bookkeeping for buffer management. ```rust pub fn encode_buf(pdu: &T, buf: &mut Vec, filled_len: usize) -> PduResult { let pdu_size = pdu.size(); // Resize the buffer, making sure there is enough space to fit the serialized PDU if buf.len() < pdu_size { buf.resize(filled_len + pdu_size, 0); } // Proceed to actually serialize the PDU into the buffer… let mut cursor = WriteCursor::new(&mut buf[filled_len..]); encode_cursor(pdu, &mut cursor)?; let written = cursor.pos(); Ok(written) } fn somewhere_else() -> PduResult<()> { let mut state_machine = /* … */; let mut buf = Vec::new(); let mut filled_len; while !state_machine.is_terminal() { let pdus = state_machine.step(); filled_len = 0; buf.shrink_to(16384); // Maintain up to 16 kib around for pdu in pdus { filled_len += encode_buf(&pdu, &mut buf, filled_len)?; } let filled = &buf[..filled_len]; // Do something with `filled` } Ok(()) } ``` -------------------------------- ### Handle Keyboard and Mouse Input Events (Rust) Source: https://context7.com/devolutions/ironrdp/llms.txt The `ironrdp-input` crate in Rust provides utilities for managing input states and generating RDP input events. This snippet demonstrates building a transaction of input operations, including mouse movements, button presses/releases, key presses/releases, and Unicode character input, then applying them to generate events. It also shows how to synchronize lock key states with the server. ```rust use ironrdp_input::{Database, Operation, MouseButton, MousePosition, Scancode}; use ironrdp::pdu::input::fast_path::FastPathInputEvent; fn handle_input() -> Vec { let mut input_db = Database::new(); // Build a transaction of input operations let operations = vec![ // Move mouse to position (500, 300) Operation::MouseMove(MousePosition { x: 500, y: 300 }), // Press left mouse button Operation::MouseButtonPressed(MouseButton::Left), // Release left mouse button Operation::MouseButtonReleased(MouseButton::Left), // Press 'A' key (scancode 0x1E) Operation::KeyPressed(Scancode::from_u8(false, 0x1E)), // Release 'A' key Operation::KeyReleased(Scancode::from_u8(false, 0x1E)), // Type Unicode character Operation::UnicodeKeyPressed(''), Operation::UnicodeKeyReleased(''), // Mouse wheel scroll Operation::WheelRotations(ironrdp_input::WheelRotations { is_vertical: true, rotation_units: 120, // One notch up }), ]; // Apply transaction and get RDP input events let events = input_db.apply(operations); events.into_vec() } // Synchronize lock key state with server fn sync_lock_keys() -> FastPathInputEvent { ironrdp_input::synchronize_event( false, // scroll_lock true, // num_lock false, // caps_lock false, // kana_lock ) } ``` -------------------------------- ### Disable Default Features for IronRDP TLS in Cargo.toml Source: https://github.com/devolutions/ironrdp/blob/master/crates/ironrdp-tls/README.md This example demonstrates how to explicitly disable default features for the `ironrdp-tls` crate in `Cargo.toml`. This is useful when you want to ensure that no TLS backend is enabled by default and you intend to manually select a specific backend using the `features` argument. ```toml ironrdp-tls = { version = "x.y.z", default-features = false } ```