-
Notifications
You must be signed in to change notification settings - Fork 731
GUACAMOLE-522: USB Device Redirection. #610
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: main
Are you sure you want to change the base?
Conversation
|
Extremely interested in this PR, what is blocking it, since this is a awesome added feature :D |
Nothing is blocking it - just the time required to review the PR. |
|
@aleitner The usbconnect_handler is defined as a function pointer type and struct member, but there's no implementation assigned to it. It is incomplete same for other functions usbdata_handler and usbdisconnect_handler |
|
@coolkingh Yes, this is the framework for it that provides methods for handling USB device redirection. This particular pull request does not implement it concretely for any of the protocols. Once this pull request is merged the changes can be made at the protocol level (RDP, SSH, etc.) that would actually enable this to function for a particular protocol. |
|
@necouchman What's the point of merging if implementation is incomplete for any of the protocol. |
|
@coolkingh The point is that the base components - the Guacamole protocol bits and hooks for the handler functions - are available in case someone wants to use them. The second sentence of this pull request says:
This indicates to me that @aleitner never intended this pull request to fully implement USB redirection support in any of the protocols, but only to provide these core components. There are several reasons why we might decide to merge only the core framework components and not the protocol-specific implementations. We often break complex implementations into multiple pull requests, where a more basic or foundational level of code is done prior to the detailed or specific implementations. It can make it easier to track down when bugs are introduced, it helps to break up work among people who have varying degrees of time and expertise, etc. In the case of WebUSB support, I would imagine that this part - the addition of it to the Guacamole protocol and the implementation of the hooks - is the simpler part, whereas implementing the actual protocol-level of support will require a lot more time and effort to hook in these handlers to FreeRDP, libssh, libvncserver, etc. It makes sense to go ahead and get the framework/infrastructure out and available so that others who want to work on the protocol-level components can do so. |
necouchman
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@aleitner Overall looks pretty good to me - my comments are mostly about documentation and not the actual implementation, aside from the one question about a protocol-level usbconnect function.
| /** | ||
| * Sends a usbdisconnect instruction over the given guac_socket connection, | ||
| * requesting that the client disconnect the specified USB device. | ||
| * | ||
| * @param socket | ||
| * The guac_socket connection to use. | ||
| * | ||
| * @param device_id | ||
| * The unique identifier of the USB device that should be disconnected. | ||
| * | ||
| * @return | ||
| * Zero on success, non-zero on error. | ||
| */ | ||
| int guac_protocol_send_usbdisconnect(guac_socket* socket, | ||
| const char* device_id); | ||
|
|
||
| /** | ||
| * Sends a usbdata instruction over the given guac_socket connection, | ||
| * sending USB data to a specific endpoint on a client-side USB device. | ||
| * | ||
| * @param socket | ||
| * The guac_socket connection to use. | ||
| * | ||
| * @param device_id | ||
| * The unique identifier of the USB device. | ||
| * | ||
| * @param endpoint_number | ||
| * The endpoint number to send data to. | ||
| * | ||
| * @param data | ||
| * The base64-encoded data to send to the USB device. | ||
| * | ||
| * @return | ||
| * Zero on success, non-zero on error. | ||
| */ | ||
| int guac_protocol_send_usbdata(guac_socket* socket, const char* device_id, | ||
| int endpoint_number, const char* data); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should there be a matching connect function implemented, here? I understand that the disconnect function is provided so that a user could disconnect a USB device while a connection is still active - I think it would also be useful to be able to connect a USB device after a connection has already started, which would likely require a connect function?
Or is there some other reason to implement a protocol-level disconnect but not a connect?
| /** | ||
| * Handler for Guacamole USB connect events, invoked when a "usbconnect" | ||
| * instruction has been received from a user. This indicates that the user | ||
| * has connected a USB device via WebUSB and it is available for redirection. | ||
| * | ||
| * @param user | ||
| * The user that connected the USB device. | ||
| * | ||
| * @param device_id | ||
| * The unique identifier for the USB device. | ||
| * | ||
| * @param vendor_id | ||
| * The vendor ID of the USB device. | ||
| * | ||
| * @param product_id | ||
| * The product ID of the USB device. | ||
| * | ||
| * @param device_name | ||
| * The human-readable name of the device. | ||
| * | ||
| * @param serial_number | ||
| * The serial number of the device, if available. | ||
| * | ||
| * @param device_class | ||
| * The USB device class. | ||
| * | ||
| * @param device_subclass | ||
| * The USB device subclass. | ||
| * | ||
| * @param device_protocol | ||
| * The USB device protocol. | ||
| * | ||
| * @param interface_data | ||
| * Encoded string containing interface and endpoint information in the | ||
| * format: "iface_num:class:subclass:protocol:ep_num:dir:type:size,..." | ||
| * | ||
| * @return | ||
| * Zero if the USB connect event was handled successfully, or non-zero if | ||
| * an error occurred. | ||
| */ | ||
| typedef int guac_user_usbconnect_handler(guac_user* user, const char* device_id, | ||
| int vendor_id, int product_id, const char* device_name, | ||
| const char* serial_number, int device_class, int device_subclass, | ||
| int device_protocol, const char* interface_data); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It might be good to indicate more explicitly which of these arguments is required and which is optional?One of them - serial_number - says "if available", which indicates it may be optional - is that the only one that isn't required and is optional, and the rest are required?
| * @param endpoint_number | ||
| * The endpoint number to send data to. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I poked around in the code for anything else that refers to endpoint_number, and I don't see this mentioned anywhere else. This may need a little more documentation - the rest of the arguments, here, are pretty self-explanatory, but endpoint_number doesn't really mean much to me?
| * @param endpoint_number | ||
| * The endpoint number the data originated from. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
As with the mention about in protocol.h - endpoint_number probably needs some more thorough documentation as it appears to be a newly-introduced concept, here.
| * The handler takes the user that connected the device, the device ID, | ||
| * vendor ID, product ID, device name, serial number, device class, | ||
| * device subclass, device protocol, and interface data. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
As mentioned, above, it might be good to document which of these is required and which may be optional.
|
|
||
| /** | ||
| * Internal initial handler for the usbconnect instruction. When a usbconnect | ||
| * instruction is received, this handler will be called. The client's |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The client's should probably be The user's, as this is a user handler, not a client handler?
|
|
||
| /** | ||
| * Internal initial handler for the usbdata instruction. When a usbdata | ||
| * instruction is received, this handler will be called. The client's |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
client's -> user's
| /** | ||
| * Internal initial handler for the usbdisconnect instruction. When a | ||
| * usbdisconnect instruction is received, this handler will be called. | ||
| * The client's usbdisconnect handler will be invoked if defined. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
client's -> user's
This PR implements the server-side protocol support for Web USB device redirection, complementing the client-side PR. This provides the infrastructure for Guacamole protocol plugins (RDP, VNC, etc.) to handle USB device redirection from browser clients.
Data Flow
usbconnectwith device descriptors and interface/endpoint datausbconnect_handleris invoked to establish redirectionusbdatamessages flow between client device and server handlerusbdisconnectNew Protocol Instructions
usbdataandusbdisconnectinstructions for sending data to USB devices and requesting disconnectionusbconnect,usbdata, andusbdisconnectinstructionsHandlers
guac_user_usbconnect_handler: Processes USB device connections with full device metadata (vendor/product IDs, interfaces, endpoints)guac_user_usbdata_handler: Handles USB data transfer from the client with USB endpoint and transfer type information.guac_user_usbdisconnect_handler: Manages USB device disconnection events.