Client -> agent messages can spawn multiple VDIChunks. When this happens the agent re-assembles the chunks into a complete VDAgentMessage before processing it. The server only guarentees coherency at the chunk level, so it is not possible for a partial chunk to get delivered to the agent. But it is possible for some chunks of a VDAgentMessage to be delivered to the agent followed by a client to disconnect without the rest of the VDAgentMessage being delivered! This will leave the agent in a wrong state, and the first messages send to it by the next client to connect will get seen as the rest of the VDAgentMessage from the previous client. This patch sends the agent a new VD_AGENT_CLIENT_DISCONNECTED message from the VDP_SERVER_PORT, on which the agent can then reset its VDP_CLIENT_PORT state. Note that no capability check is done for this, since the capabilities are something negotiated between client and agent. The server will simply always send this message on client disconnect, relying on older agents discarding the message since it has an unknown type (which both the windows and linux agents already do). Signed-off-by: Hans de Goede <hdegoede@xxxxxxxxxx> --- server/reds.c | 24 +++++++++++++++++++++++- 1 file changed, 23 insertions(+), 1 deletion(-) diff --git a/server/reds.c b/server/reds.c index ec80e9e..5c46909 100644 --- a/server/reds.c +++ b/server/reds.c @@ -563,7 +563,29 @@ void reds_client_disconnect(RedClient *client) // TODO: we need to handle agent properly for all clients!!!! (e.g., cut and paste, how? Maybe throw away messages // if we are in the middle of one from another client) if (reds->num_clients == 0) { - /* Reset write filter to start with clean state on client reconnect */ + /* Let the agent know the client is disconnected */ + if (reds->agent_state.base) { + SpiceCharDeviceWriteBuffer *char_dev_buf; + VDInternalBuf *internal_buf; + uint32_t total_msg_size; + + total_msg_size = sizeof(VDIChunkHeader) + sizeof(VDAgentMessage); + char_dev_buf = spice_char_device_write_buffer_get_server_no_token( + reds->agent_state.base, total_msg_size); + char_dev_buf->buf_used = total_msg_size; + internal_buf = (VDInternalBuf *)char_dev_buf->buf; + internal_buf->chunk_header.port = VDP_SERVER_PORT; + internal_buf->chunk_header.size = sizeof(VDAgentMessage); + internal_buf->header.protocol = VD_AGENT_PROTOCOL; + internal_buf->header.type = VD_AGENT_CLIENT_DISCONNECTED; + internal_buf->header.opaque = 0; + internal_buf->header.size = 0; + + spice_char_device_write_buffer_add(reds->agent_state.base, + char_dev_buf); + } + + /* Reset write filter to start with clean state on client reconnect */ agent_msg_filter_init(&reds->agent_state.write_filter, agent_copypaste, TRUE); -- 1.8.1.4 _______________________________________________ Spice-devel mailing list Spice-devel@xxxxxxxxxxxxxxxxxxxxx http://lists.freedesktop.org/mailman/listinfo/spice-devel