[Spice-devel] [RFC] [PATCH spice-protocol] DND: Add VD_AGENT_DND_*

Hans de Goede hdegoede at redhat.com
Sat Nov 17 07:26:46 PST 2012


Hi,

First of all many many thanks for working on this. For a first version these
patches look very good!

Second sorry for being a bit late with this reply I started composing it a
week ago, and then other stuff got in the way. In the mean time you've had
some other replies so some of the things in here may repeat stuff said
in other mails ...

But I would like to first settle on a final agent protocol, which supports
all features we want before merging any parts of this, as once merged we
can no longer change the proto.

So I've been discussing this a bit with Alon, and thinking about it, and
in the end I think we need the following messages:

1) VD_AGENT_FILE_XFER_STATUS

enum VDAgentFileXferResult { VD_AGENT_FILE_XFER_SUCCESS, VD_AGENT_FILE_XFER_DISK_FULL, VD_AGENT_FILE_XFER_CANCELLED };

typedef struct SPICE_ATTR_PACKED VDAgentFileXferStatusMessage{
    uint32_t id;
    uint32_t result;
} VDAgentFileXferStatusMessage;

2) VD_AGENT_FILE_XFER_START

typedef struct SPICE_ATTR_PACKED VDAgentFileXferStartMessage{
    uint32_t id;
    uint64_t file_size;
    uint8_t file_name[0];
} VDAgentFileXferStartMessage;

3) VD_AGENT_FILE_XFER_DATA

typedef struct SPICE_ATTR_PACKED VDAgentFileXferDataMessage{
    uint32_t id;
    uint64_t size;
    uint8_t data[0];
} VDAgentFileXferDataMessage;

The id-field is there to allow multiple simultaneous file transfers,
this is useful ie when a user drag and drops a dvd iso, and then
while that is transferring also drags and drops a word file he wants
to work on, without having to wait for the iso transfer to finish,
before the word document gets send.

Here are some examples to clarify how this would work at the protocol
level:

Steps of a single file file-transfer:
1) Client sends a VD_AGENT_FILE_XFER_START
2) Agent reserves diskspace and sends an
    VD_AGENT_FILE_XFER_STATUS with a VD_AGENT_FILE_XFER_SUCCESS
    result
3) Client sends VD_AGENT_FILE_XFER_DATA messages until it has
    send file-size bytes of data.

Steps of a too large file-transfer:
1) Client sends a VD_AGENT_FILE_XFER_START
2) Agent fails to reserve diskspace and sends an
    VD_AGENT_FILE_XFER_STATUS with a VD_AGENT_FILE_XFER_DISK_FULL
    result
3) Client shows error dialog to the user

Steps of a cancelled file-transfer
1) Client sends a VD_AGENT_FILE_XFER_START
2) Agent reserves diskspace and sends an
    VD_AGENT_FILE_XFER_STATUS with a VD_AGENT_FILE_XFER_SUCCESS
    result
3) Since this is a large file, which will take a while, the client
    shows a window with a progress bar and a cancel button
4) Client sends some VD_AGENT_FILE_XFER_DATA messages
5) user clicks cancel
6) Client sends a VD_AGENT_FILE_XFER_STATUS with a
    VD_AGENT_FILE_XFER_CANCELLED result, stops sending
    further data and closes the progress dialog
7) The agent frees the reserved diskspace upon reception of
    the VD_AGENT_FILE_XFER_CANCELLED result

Steps of a multi file file-transfer
1) Client sends a VD_AGENT_FILE_XFER_START, id = 1
2) Agent reserves diskspace and sends an
    VD_AGENT_FILE_XFER_STATUS with a VD_AGENT_FILE_XFER_SUCCESS
    result, id = 1
3) Client sends some VD_AGENT_FILE_XFER_DATA messages with id = 1
4) Client sends a VD_AGENT_FILE_XFER_START, id = 2
5) Agent reserves diskspace for id = 2 and sends an
    VD_AGENT_FILE_XFER_STATUS with a VD_AGENT_FILE_XFER_SUCCESS
    result, id = 2
6) Client sends some VD_AGENT_FILE_XFER_DATA messages with id = 1
7) Client sends some VD_AGENT_FILE_XFER_DATA messages with id = 2
8) 6 and 7 repeat, sending some data for each transfer until id = 2
    is finished.
9) Client sends VD_AGENT_FILE_XFER_DATA messages with id = 2 until it
    has finished too

###

So about the spice-gtk implementation, both for copy and paste to keep
working, as well as for multiple file transfers at the same time to work,
the spice-gtk implementation cannot simply out the entire file in the
agent msg queue in one go. So we need a mechanism to put some data in
the agent msg queue, and then get called back when the queue is empty.

I think the easiest way to do this is to:
1) add a callback ( + opaque context pointer) to the SpiceMsgOut struct,
    with the callback prototype matching that of a GIdle function
2) Have a new spice_msg_out_new_callback function to create SpiceMsgOut
    structs with the callback set, rather then with a regular msg
3) Have spice_msg_out_send call this callback rather then queuing the
    packet when encountering such a callback SpiceMsgOut; and
4) spice_msg_out_send_internal schedule calling the callback through
    g_idle_add
5) The file xfer code would then queue some agent messages with data,
    followed by a callback SpiceMsgOut, which will then caused the
    file xfer code to get called for more data when the agent queue is
    empty

This way we can have multiple file transfers going at the same time,
and keep copy and paste (and other agent messages) working while
a file is being transferred.

And as already mentioned, the function to add some file data to
the agent message queue should use async gio code, to ensure to
not freeze the client while waiting for disk io.

I believe that at least for the Linux agent the agent code can
simply use synchronous file-io.

Regards,

Hans


More information about the Spice-devel mailing list