Skip to content

clipboard-rdp: Make SelectionTransfer requests async

Quoting the two main commits here:

Currently, when gnome-remote-desktop handles a SelectionTransfer-
signal, the mime type content is requested synchronously from the
respective backend.
Since this process is done synchronously, the main thread is blocked
and cannot handle any other events, such as input events.
With additional network latency, this becomes worse.

To allow the backend implementations to transform to an asynchronous
implementation, split up the SelectionTransfer handling.
The signal will now just emit the request on the backend and the
backend will, when it has the response ready submit the response
itself.

Both the RDP and VNC backend will currently still function as before,
as the handling is just split up.
Since the VNC backend does not support delayed rendering of clipboard
data, no further changes will happen for the VNC backend.
The RDP backend, on the other hand, will be reworked in the next commit
to handle mime type content requests asynchronously.
The previous commit split up the SelectionTransfer handling, allowing
the backends to handle mime type content requests for the client in an
asynchronous way.
In order to handle the mime type content requests asynchronously, split
up grd_clipboard_rdp_request_client_content_for_mime_type() into
multiple parts:

The first part, about retrieving the mime type content from the
FormatData cache remains.
Same with the next part, when gnome-remote-desktop fails a request,
when a new FormatList is received from the client, since mstsc will
then not submit any FormatDataResponse in that situation.

Next, implement the new part:

If a there is currently already a mime type content request pending,
just enqueue the new request.
This is done with a hash table and a queue.
The hash table tracks all serials for a request for each specific mime
type.
This allows gnome-remote-desktop to group multiple requests into one
request.
If a response for the mime type content request is received, all
serials are answered together.
The queue preserves the order of these mime type content requests, so
that all requests are handled fairly, while also tracking the
respective MimeTypeTables, which contain the foreign format ids, which
are necessary for the mime type content conversion operations.

If no mime type content request is pending, send the mime type content
request via a FormatDataRequest and save the serial.
Also create a timeout source to abort the current request in case no
FormatDataResponse is sent by the client.

After sending the mime type content request, the new
grd_clipboard_rdp_request_client_content_for_mime_type() procedure ends
here.

If the client did not send the FormatDataResponse and the timeout
source runs, abort the current mime type content request by answering
all serials for this request with a fail response.
Then send the next mime type content request, if there is one queued.

If the mime type content request is still pending, but a new FormatList
is received from the client, abort all pending and queued mime type
content requests.
This is necessary, since mstsc will not answer these requests any more,
so gnome-remote-desktop has to fake their responses.

If a FormatDataResponse is received, gnome-remote-desktop can handle
the response for the mime type request.
For this, the CLIPRDR thread queues the task via a GSource onto the
main thread and duplicates the response.
This is necessary, as the FormatDataResponse, owned by the CLIPRDR
thread, is only valid as long as the callback function runs.
If there is no current mime type content request pending, the response
is discarded.

The handling of the FormatDataResponse on the main thread uses the last
part of the old
grd_clipboard_rdp_request_client_content_for_mime_type() function.
First, the data is extracted and the flags are checked.
If the response was successful, convert the received mime type content,
if necessary.
After this, answer all serials for the given mime type.
If the response was not successful, answer all serials for the given
mime type with a fail response.
At the end of this handling, send the next mime type content request,
if there is one queued.

Merge request reports