summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorHans de Goede <hdegoede@redhat.com>2013-02-28 15:38:38 +0100
committerHans de Goede <hdegoede@redhat.com>2013-03-06 16:22:15 +0100
commit4b0748ddcc4f0c4fdc892aff63cbc88dc9e391df (patch)
treea40b6caf0d2ce00a5cddcadb5f96c2ffe32ffc42
parenteb7a99011cb79dc6f464b2d6a7277f5272b9074e (diff)
downloadvd_agent-4b0748ddcc4f0c4fdc892aff63cbc88dc9e391df.tar.gz
vd_agent-4b0748ddcc4f0c4fdc892aff63cbc88dc9e391df.tar.xz
vd_agent-4b0748ddcc4f0c4fdc892aff63cbc88dc9e391df.zip
vdagentd: Track which file-xfer id belongs to which session-agent
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@redhat.com>
-rw-r--r--Makefile.am4
-rw-r--r--src/vdagentd.c73
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();