-
Notifications
You must be signed in to change notification settings - Fork 301
refactor(server): define the USB device announce type #1933
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: master
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -23,7 +23,7 @@ use ironrdp_rdpeusb::{ | |
| server::{UrbdrcControlServerBackend, UrbdrcDeviceServerBackend}, | ||
| }; | ||
| use ironrdp_usb::{ | ||
| InterfaceSelection, TransferType, | ||
| InterfaceSelection, TransferType, UsbSpeed, | ||
| control::GetDescriptorRequest, | ||
| descriptor::{ConfigurationDescriptorSet, InterfaceDescriptor, ValidConfigurationDescriptorSet}, | ||
| endpoint::EndpointAddress, | ||
|
|
@@ -1425,6 +1425,8 @@ pub(crate) struct UsbRedirServer { | |
|
|
||
| pub trait UsbRedirDevice: Send { | ||
| /// Called when the client announces the device with `ADD_DEVICE`. | ||
| /// | ||
| /// This is the first callback, and it is invoked exactly once. | ||
|
Comment on lines
+1428
to
+1429
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. [skeptical] 'First callback, invoked exactly once' contract on device_added is over-strong — low 🟡 — Inspection of ironrdp-rdpeusb's UrbdrcDeviceServer resolves the prior question: AddDev is forwarded to the backend only when state == AwaitingDevice and then transitions to Ready, so duplicate announcements are ignored and device_added runs at most once; no other backend callback precedes it for a well-behaved client. But the contract as written still overpromises: a device channel closed before ADD_DEVICE invokes only close(), so device_added may never run, and DevTextRsp is processed in any non-retracted state, so a nonconforming client can deliver device_text before device_added. Soften to 'at most once, and the first callback in normal operation' or note the close-before-announce path, especially since the new device_instance_id doc encourages keying per-device state on the announcement. |
||
| fn device_added(&mut self, info: RdpUsbDeviceAnnounceInfo); | ||
|
|
||
| fn device_text(&mut self, device_text: DeviceText); | ||
|
|
@@ -1440,9 +1442,48 @@ pub trait UsbRedirDevice: Send { | |
| fn close(&mut self) {} | ||
| } | ||
|
|
||
| /// A redirected USB device as the client announced it. | ||
| #[derive(Debug, Clone)] | ||
| #[non_exhaustive] | ||
| pub struct UsbDeviceAnnounce { | ||
| /// Identity the client assigned to the redirected device. | ||
| /// | ||
| /// It is opaque to the server and stable for the lifetime of the device | ||
| /// channel, which makes it usable as a key for per-device state. | ||
| pub device_instance_id: String, | ||
| /// Device identifiers reported by the client, most specific first. | ||
| pub hw_ids: Vec<String>, | ||
| /// Identifiers of the device classes the client reports the device is | ||
| /// compatible with, most specific first. | ||
| pub compat_ids: Vec<String>, | ||
| /// Identifier shared by every function of the same physical device, which | ||
| /// groups the announcements of a composite device. | ||
| pub container_id: String, | ||
| /// Bus speed the client reports the device is operating at. | ||
| /// | ||
| /// RDPEUSB reports only whether the device is operating at high speed, so | ||
| /// this is always either [`UsbSpeed::High`] or [`UsbSpeed::Full`]. A | ||
| /// low-speed device is announced as full speed, because the protocol has no | ||
| /// encoding to distinguish the two. | ||
| pub speed: UsbSpeed, | ||
| } | ||
|
|
||
| impl From<DeviceAnnounce> for UsbDeviceAnnounce { | ||
| fn from(value: DeviceAnnounce) -> Self { | ||
| Self { | ||
| device_instance_id: value.device_instance_id, | ||
| hw_ids: value.hw_ids, | ||
| compat_ids: value.compat_ids, | ||
| container_id: value.container_id, | ||
| speed: value.usb_device_caps.device_speed.into(), | ||
| } | ||
| } | ||
| } | ||
|
|
||
| /// A device announcement together with the handle which drives that device. | ||
| #[derive(Debug)] | ||
| pub struct RdpUsbDeviceAnnounceInfo { | ||
| pub announce: DeviceAnnounce, | ||
| pub announce: UsbDeviceAnnounce, | ||
| pub usb_handle: UsbDeviceHandle, | ||
| } | ||
|
|
||
|
|
@@ -1508,7 +1549,7 @@ impl UsbRedirServer { | |
| impl UrbdrcDeviceServerBackend for UsbRedirServer { | ||
| fn add_device(&mut self, device: DeviceAnnounce) -> PduResult<()> { | ||
| self.device.device_added(RdpUsbDeviceAnnounceInfo { | ||
| announce: device, | ||
| announce: device.into(), | ||
| usb_handle: self.handle.clone(), | ||
| }); | ||
| Ok(()) | ||
|
|
||
Uh oh!
There was an error while loading. Please reload this page.