So that file-xfers which are still on progress on user-switch keep working, and so that vdagentd can send the client a file-xfer cancel if the per-session vdagent goes away while a file-xfer is active. Signed-off-by: Hans de Goede <hdegoede@xxxxxxxxxx> --- Makefile.am | 4 ++-- src/vdagentd.c | 73 ++++++++++++++++++++++++++++++++++++++++++++++++---------- 2 files changed, 63 insertions(+), 14 deletions(-) diff --git a/Makefile.am b/Makefile.am index d218183..c551e0b 100644 --- a/Makefile.am +++ b/Makefile.am @@ -8,8 +8,8 @@ src_spice_vdagent_CFLAGS = $(X_CFLAGS) $(SPICE_CFLAGS) $(GLIB2_CFLAGS) src_spice_vdagent_LDADD = $(X_LIBS) $(SPICE_LIBS) $(GLIB2_LIBS) src_spice_vdagent_SOURCES = src/vdagent.c src/vdagent-x11.c src/vdagent-x11-randr.c src/vdagent-file-xfers.c src/udscs.c -src_spice_vdagentd_CFLAGS = $(DBUS_CFLAGS) $(LIBSYSTEMD_LOGIN_CFLAGS) $(PCIACCESS_CFLAGS) $(SPICE_CFLAGS) -src_spice_vdagentd_LDADD = $(DBUS_LIBS) $(LIBSYSTEMD_LOGIN_LIBS) $(PCIACCESS_LIBS) $(SPICE_LIBS) +src_spice_vdagentd_CFLAGS = $(DBUS_CFLAGS) $(LIBSYSTEMD_LOGIN_CFLAGS) $(PCIACCESS_CFLAGS) $(SPICE_CFLAGS) $(GLIB2_CFLAGS) +src_spice_vdagentd_LDADD = $(DBUS_LIBS) $(LIBSYSTEMD_LOGIN_LIBS) $(PCIACCESS_LIBS) $(SPICE_LIBS) $(GLIB2_LIBS) src_spice_vdagentd_SOURCES = src/vdagentd.c \ src/vdagentd-uinput.c \ src/vdagentd-xorg-conf.c \ diff --git a/src/vdagentd.c b/src/vdagentd.c index 2fa19e9..108755a 100644 --- a/src/vdagentd.c +++ b/src/vdagentd.c @@ -34,6 +34,7 @@ #include <sys/select.h> #include <sys/stat.h> #include <spice/vd_agent.h> +#include <glib.h> #include "udscs.h" #include "vdagentd-proto.h" @@ -58,6 +59,7 @@ static const char *uinput_device = "/dev/uinput"; static int debug = 0; static struct udscs_server *server = NULL; static struct vdagent_virtio_port *virtio_port = NULL; +static GHashTable *active_xfers = NULL; #ifdef HAVE_SESSION_INFO static struct session_info *session_info = NULL; #endif @@ -216,32 +218,61 @@ static void do_client_clipboard(struct vdagent_virtio_port *vport, data, size); } +static void cancel_file_xfer(struct vdagent_virtio_port *vport, + const char *msg, uint32_t id) +{ + VDAgentFileXferStatusMessage status = { + .id = id, + .result = VD_AGENT_FILE_XFER_STATUS_CANCELLED, + }; + syslog(LOG_WARNING, msg, id); + if (vport) + vdagent_virtio_port_write(vport, VDP_CLIENT_PORT, + VD_AGENT_FILE_XFER_STATUS, 0, + (uint8_t *)&status, sizeof(status)); +} + static void do_client_file_xfer(struct vdagent_virtio_port *vport, VDAgentMessage *message_header, uint8_t *data) { - uint32_t msg_type; + uint32_t msg_type, id; + struct udscs_connection *conn; - if (!active_session_conn) { - syslog(LOG_WARNING, + switch (message_header->type) { + case VD_AGENT_FILE_XFER_START: { + VDAgentFileXferStartMessage *s = (VDAgentFileXferStartMessage *)data; + if (!active_session_conn) { + cancel_file_xfer(vport, "Could not find an agent connnection belonging to the " - "active session, ignoring client clipboard request"); + "active session, cancelling client file-xfer request %u", + s->id); + return; + } + udscs_write(active_session_conn, VDAGENTD_FILE_XFER_START, 0, 0, + data, message_header->size); return; } - - switch (message_header->type) { - case VD_AGENT_FILE_XFER_START: - msg_type = VDAGENTD_FILE_XFER_START; - break; - case VD_AGENT_FILE_XFER_STATUS: + case VD_AGENT_FILE_XFER_STATUS: { + VDAgentFileXferStatusMessage *s = (VDAgentFileXferStatusMessage *)data; msg_type = VDAGENTD_FILE_XFER_STATUS; + id = s->id; break; - case VD_AGENT_FILE_XFER_DATA: + } + case VD_AGENT_FILE_XFER_DATA: { + VDAgentFileXferDataMessage *d = (VDAgentFileXferDataMessage *)data; msg_type = VDAGENTD_FILE_XFER_DATA; + id = d->id; break; } + } - udscs_write(active_session_conn, msg_type, 0, 0, data, message_header->size); + conn = g_hash_table_lookup(active_xfers, GUINT_TO_POINTER(id)); + if (!conn) { + cancel_file_xfer(vport, "Could not find file-xfer %u, cancelling", id); + return; + } + udscs_write(conn, msg_type, 0, 0, data, message_header->size); } int virtio_port_read_complete( @@ -539,6 +570,16 @@ void update_active_session_connection(void) check_xorg_resolution(); } +gboolean remove_active_xfers(gpointer key, gpointer value, gpointer conn) +{ + if (value == conn) { + cancel_file_xfer(virtio_port, "Agent disc; cancelling file-xfer %u", + GPOINTER_TO_UINT(key)); + return 1; + } else + return 0; +} + void agent_connect(struct udscs_connection *conn) { #ifdef HAVE_SESSION_INFO @@ -580,6 +621,8 @@ void agent_disconnect(struct udscs_connection *conn) { struct agent_data *agent_data = udscs_get_user_data(conn); + g_hash_table_foreach_remove(active_xfers, remove_active_xfers, conn); + #ifndef HAVE_SESSION_INFO if (conn == active_session_conn) active_session_conn = NULL; @@ -655,6 +698,11 @@ void agent_read_complete(struct udscs_connection **connp, vdagent_virtio_port_write(virtio_port, VDP_CLIENT_PORT, VD_AGENT_FILE_XFER_STATUS, 0, (uint8_t *)&status, sizeof(status)); + if (status.result == VD_AGENT_FILE_XFER_STATUS_CAN_SEND_DATA) + g_hash_table_insert(active_xfers, GUINT_TO_POINTER(status.id), + *connp); + else + g_hash_table_remove(active_xfers, GUINT_TO_POINTER(status.id)); break; } @@ -851,6 +899,7 @@ int main(int argc, char *argv[]) } #endif + active_xfers = g_hash_table_new(g_direct_hash, g_direct_equal); main_loop(); release_clipboards(); -- 1.8.1.4 _______________________________________________ Spice-devel mailing list Spice-devel@xxxxxxxxxxxxxxxxxxxxx http://lists.freedesktop.org/mailman/listinfo/spice-devel