[Spice-commits] 5 commits - gtk/channel-main.c gtk/spice-gtk-session.c spice-common
Marc-André Lureau
elmarco at kemper.freedesktop.org
Wed Nov 20 01:55:22 PST 2013
gtk/channel-main.c | 187 ++++++++++++++++++++++++++++++++++--------------
gtk/spice-gtk-session.c | 9 +-
spice-common | 2
3 files changed, 142 insertions(+), 56 deletions(-)
New commits:
commit 296c8e31101b6e7a4515a7cf6a17b05ad25f7c6c
Author: Marc-André Lureau <marcandre.lureau at redhat.com>
Date: Wed Nov 6 21:56:37 2013 +0100
main: send max-clipboard to agent
Send configured max-clipboard size to the agent, after receiving agent
capabilities.
See also spice-protocol patch description:
http://lists.freedesktop.org/archives/spice-devel/2013-November/015254.html
diff --git a/gtk/channel-main.c b/gtk/channel-main.c
index 08138d6..ef2a5e5 100644
--- a/gtk/channel-main.c
+++ b/gtk/channel-main.c
@@ -170,6 +170,7 @@ static void spice_main_channel_send_migration_handshake(SpiceChannel *channel);
static void file_xfer_continue_read(SpiceFileXferTask *task);
static void file_xfer_completed(SpiceFileXferTask *task, GError *error);
static void file_xfer_flushed(SpiceMainChannel *channel, gboolean success);
+static void spice_main_set_max_clipboard(SpiceMainChannel *self, gint max);
/* ------------------------------------------------------------------ */
@@ -196,6 +197,7 @@ static const char *agent_caps[] = {
[ VD_AGENT_CAP_SPARSE_MONITORS_CONFIG ] = "sparse monitors",
[ VD_AGENT_CAP_GUEST_LINEEND_LF ] = "line-end lf",
[ VD_AGENT_CAP_GUEST_LINEEND_CRLF ] = "line-end crlf",
+ [ VD_AGENT_CAP_MAX_CLIPBOARD ] = "max-clipboard",
};
#define NAME(_a, _i) ((_i) < SPICE_N_ELEMENTS(_a) ? (_a[(_i)] ?: "?") : "?")
@@ -288,7 +290,8 @@ static void spice_main_get_property(GObject *object,
static void spice_main_set_property(GObject *gobject, guint prop_id,
const GValue *value, GParamSpec *pspec)
{
- SpiceMainChannelPrivate *c = SPICE_MAIN_CHANNEL(gobject)->priv;
+ SpiceMainChannel *self = SPICE_MAIN_CHANNEL(gobject);
+ SpiceMainChannelPrivate *c = self->priv;
switch (prop_id) {
case PROP_DISPLAY_DISABLE_WALLPAPER:
@@ -313,7 +316,7 @@ static void spice_main_set_property(GObject *gobject, guint prop_id,
c->disable_display_align = g_value_get_boolean(value);
break;
case PROP_MAX_CLIPBOARD:
- c->max_clipboard = g_value_get_int(value);
+ spice_main_set_max_clipboard(self, g_value_get_int(value));
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID(gobject, prop_id, pspec);
@@ -1816,6 +1819,34 @@ static void file_xfer_handle_status(SpiceMainChannel *channel,
file_xfer_completed(task, error);
}
+/* any context: the message is not flushed immediately,
+ you can wakeup() the channel coroutine or send_msg_queue() */
+static void agent_max_clipboard(SpiceMainChannel *self)
+{
+ VDAgentMaxClipboard msg = { .max = spice_main_get_max_clipboard(self) };
+
+ if (!test_agent_cap(self, VD_AGENT_CAP_MAX_CLIPBOARD))
+ return;
+
+ agent_msg_queue(self, VD_AGENT_MAX_CLIPBOARD, sizeof(VDAgentMaxClipboard), &msg);
+}
+
+static void spice_main_set_max_clipboard(SpiceMainChannel *self, gint max)
+{
+ SpiceMainChannelPrivate *c;
+
+ g_return_if_fail(SPICE_IS_MAIN_CHANNEL(self));
+ g_return_if_fail(max >= -1);
+
+ c = self->priv;
+ if (max == spice_main_get_max_clipboard(self))
+ return;
+
+ c->max_clipboard = max;
+ agent_max_clipboard(self);
+ spice_channel_wakeup(SPICE_CHANNEL(self), FALSE);
+}
+
/* coroutine context */
static void main_agent_handle_msg(SpiceChannel *channel,
VDAgentMessage *msg, gpointer payload)
@@ -1867,9 +1898,13 @@ static void main_agent_handle_msg(SpiceChannel *channel,
if (test_agent_cap(self, VD_AGENT_CAP_DISPLAY_CONFIG) &&
!c->agent_display_config_sent) {
agent_display_config(self);
- agent_send_msg_queue(self);
c->agent_display_config_sent = true;
}
+
+ agent_max_clipboard(self);
+
+ agent_send_msg_queue(self);
+
break;
}
case VD_AGENT_CLIPBOARD:
diff --git a/spice-common b/spice-common
index 1450bb4..261d270 160000
--- a/spice-common
+++ b/spice-common
@@ -1 +1 @@
-Subproject commit 1450bb4ddbd8ceab9192e4f84606aa5ae54c5ea6
+Subproject commit 261d270cc8e9af0915d5248df240828214ec996e
commit cf470e608e7f612d489563d52caff13aa3c68ee4
Author: Marc-André Lureau <marcandre.lureau at redhat.com>
Date: Wed Nov 6 21:51:55 2013 +0100
main: simplify usage of VD_AGENT_HAS_CAPABILITY
Introduce a helper function test_agent_cap() to clear the code a
little bit.
diff --git a/gtk/channel-main.c b/gtk/channel-main.c
index ef60739..08138d6 100644
--- a/gtk/channel-main.c
+++ b/gtk/channel-main.c
@@ -201,6 +201,16 @@ static const char *agent_caps[] = {
/* ------------------------------------------------------------------ */
+static gboolean test_agent_cap(SpiceMainChannel *channel, guint32 cap)
+{
+ SpiceMainChannelPrivate *c = channel->priv;
+
+ if (!c->agent_caps_received)
+ return FALSE;
+
+ return VD_AGENT_HAS_CAPABILITY(c->agent_caps, G_N_ELEMENTS(c->agent_caps), cap);
+}
+
static void spice_main_channel_reset_capabilties(SpiceChannel *channel)
{
spice_channel_set_capability(SPICE_CHANNEL(channel), SPICE_MAIN_CAP_SEMI_SEAMLESS_MIGRATE);
@@ -1236,9 +1246,6 @@ static void agent_announce_caps(SpiceMainChannel *channel)
free(caps);
}
-#define HAS_CLIPBOARD_SELECTION(c) \
- VD_AGENT_HAS_CAPABILITY((c)->agent_caps, G_N_ELEMENTS((c)->agent_caps), VD_AGENT_CAP_CLIPBOARD_SELECTION)
-
/* any context: the message is not flushed immediately,
you can wakeup() the channel coroutine or send_msg_queue() */
static void agent_clipboard_grab(SpiceMainChannel *channel, guint selection,
@@ -1253,13 +1260,12 @@ static void agent_clipboard_grab(SpiceMainChannel *channel, guint selection,
if (!c->agent_connected)
return;
- g_return_if_fail(VD_AGENT_HAS_CAPABILITY(c->agent_caps,
- G_N_ELEMENTS(c->agent_caps), VD_AGENT_CAP_CLIPBOARD_BY_DEMAND));
+ g_return_if_fail(test_agent_cap(channel, VD_AGENT_CAP_CLIPBOARD_BY_DEMAND));
size = sizeof(VDAgentClipboardGrab) + sizeof(uint32_t) * ntypes;
- if (HAS_CLIPBOARD_SELECTION(c))
+ if (test_agent_cap(channel, VD_AGENT_CAP_CLIPBOARD_SELECTION)) {
size += 4;
- else if (selection != VD_AGENT_CLIPBOARD_SELECTION_CLIPBOARD) {
+ } else if (selection != VD_AGENT_CLIPBOARD_SELECTION_CLIPBOARD) {
CHANNEL_DEBUG(channel, "Ignoring clipboard grab");
return;
}
@@ -1269,7 +1275,7 @@ static void agent_clipboard_grab(SpiceMainChannel *channel, guint selection,
grab = (VDAgentClipboardGrab *)msg;
- if (HAS_CLIPBOARD_SELECTION(c)) {
+ if (test_agent_cap(channel, VD_AGENT_CAP_CLIPBOARD_SELECTION)) {
msg[0] = selection;
grab = (VDAgentClipboardGrab *)(msg + 4);
}
@@ -1290,17 +1296,16 @@ static void agent_clipboard_notify(SpiceMainChannel *self, guint selection,
VDAgentClipboard *cb;
guint8 *msg;
size_t msgsize;
- gint max_clipboard = spice_main_get_max_clipboard(channel);
+ gint max_clipboard = spice_main_get_max_clipboard(self);
g_return_if_fail(c->agent_connected);
- g_return_if_fail(VD_AGENT_HAS_CAPABILITY(c->agent_caps,
- G_N_ELEMENTS(c->agent_caps), VD_AGENT_CAP_CLIPBOARD_BY_DEMAND));
+ g_return_if_fail(test_agent_cap(self, VD_AGENT_CAP_CLIPBOARD_BY_DEMAND));
g_return_if_fail(max_clipboard == -1 || size < max_clipboard);
msgsize = sizeof(VDAgentClipboard);
- if (HAS_CLIPBOARD_SELECTION(c))
+ if (test_agent_cap(self, VD_AGENT_CAP_CLIPBOARD_SELECTION)) {
msgsize += 4;
- else if (selection != VD_AGENT_CLIPBOARD_SELECTION_CLIPBOARD) {
+ } else if (selection != VD_AGENT_CLIPBOARD_SELECTION_CLIPBOARD) {
CHANNEL_DEBUG(self, "Ignoring clipboard notify");
return;
}
@@ -1310,7 +1315,7 @@ static void agent_clipboard_notify(SpiceMainChannel *self, guint selection,
cb = (VDAgentClipboard *)msg;
- if (HAS_CLIPBOARD_SELECTION(c)) {
+ if (test_agent_cap(self, VD_AGENT_CAP_CLIPBOARD_SELECTION)) {
msg[0] = selection;
cb = (VDAgentClipboard *)(msg + 4);
}
@@ -1329,14 +1334,12 @@ static void agent_clipboard_request(SpiceMainChannel *channel, guint selection,
size_t msgsize;
g_return_if_fail(c->agent_connected);
-
- g_return_if_fail(VD_AGENT_HAS_CAPABILITY(c->agent_caps,
- G_N_ELEMENTS(c->agent_caps), VD_AGENT_CAP_CLIPBOARD_BY_DEMAND));
+ g_return_if_fail(test_agent_cap(channel, VD_AGENT_CAP_CLIPBOARD_BY_DEMAND));
msgsize = sizeof(VDAgentClipboardRequest);
- if (HAS_CLIPBOARD_SELECTION(c))
+ if (test_agent_cap(channel, VD_AGENT_CAP_CLIPBOARD_SELECTION)) {
msgsize += 4;
- else if (selection != VD_AGENT_CLIPBOARD_SELECTION_CLIPBOARD) {
+ } else if (selection != VD_AGENT_CLIPBOARD_SELECTION_CLIPBOARD) {
SPICE_DEBUG("Ignoring clipboard request");
return;
}
@@ -1346,7 +1349,7 @@ static void agent_clipboard_request(SpiceMainChannel *channel, guint selection,
request = (VDAgentClipboardRequest *)msg;
- if (HAS_CLIPBOARD_SELECTION(c)) {
+ if (test_agent_cap(channel, VD_AGENT_CAP_CLIPBOARD_SELECTION)) {
msg[0] = selection;
request = (VDAgentClipboardRequest *)(msg + 4);
}
@@ -1365,11 +1368,9 @@ static void agent_clipboard_release(SpiceMainChannel *channel, guint selection)
guint8 msgsize = 0;
g_return_if_fail(c->agent_connected);
+ g_return_if_fail(test_agent_cap(channel, VD_AGENT_CAP_CLIPBOARD_BY_DEMAND));
- g_return_if_fail(VD_AGENT_HAS_CAPABILITY(c->agent_caps,
- G_N_ELEMENTS(c->agent_caps), VD_AGENT_CAP_CLIPBOARD_BY_DEMAND));
-
- if (HAS_CLIPBOARD_SELECTION(c)) {
+ if (test_agent_cap(channel, VD_AGENT_CAP_CLIPBOARD_SELECTION)) {
msg[0] = selection;
msgsize += 4;
} else if (selection != VD_AGENT_CLIPBOARD_SELECTION_CLIPBOARD) {
@@ -1830,7 +1831,7 @@ static void main_agent_handle_msg(SpiceChannel *channel,
case VD_AGENT_CLIPBOARD_REQUEST:
case VD_AGENT_CLIPBOARD_GRAB:
case VD_AGENT_CLIPBOARD:
- if (VD_AGENT_HAS_CAPABILITY(c->agent_caps, G_N_ELEMENTS(c->agent_caps), VD_AGENT_CAP_CLIPBOARD_SELECTION)) {
+ if (test_agent_cap(self, VD_AGENT_CAP_CLIPBOARD_SELECTION)) {
selection = *((guint8*)payload);
payload = ((guint8*)payload) + 4;
msg->size -= 4;
@@ -1863,7 +1864,7 @@ static void main_agent_handle_msg(SpiceChannel *channel,
if (caps->request)
agent_announce_caps(self);
- if (VD_AGENT_HAS_CAPABILITY(caps->caps, G_N_ELEMENTS(c->agent_caps), VD_AGENT_CAP_DISPLAY_CONFIG) &&
+ if (test_agent_cap(self, VD_AGENT_CAP_DISPLAY_CONFIG) &&
!c->agent_display_config_sent) {
agent_display_config(self);
agent_send_msg_queue(self);
@@ -2443,12 +2444,7 @@ gboolean spice_main_agent_test_capability(SpiceMainChannel *channel, guint32 cap
{
g_return_val_if_fail(SPICE_IS_MAIN_CHANNEL(channel), FALSE);
- SpiceMainChannelPrivate *c = channel->priv;
-
- if (!c->agent_caps_received)
- return FALSE;
-
- return VD_AGENT_HAS_CAPABILITY(c->agent_caps, G_N_ELEMENTS(c->agent_caps), cap);
+ return test_agent_cap(channel, cap);
}
/**
commit fa29f4e1793f09d6456afc03e5820bd6b5024da5
Author: Marc-André Lureau <marcandre.lureau at redhat.com>
Date: Wed Nov 6 21:50:14 2013 +0100
main: use self for main channel variable
This simplifies the following commit which uses even more
SPICE_MAIN_CHANNEL macro, and makes the code unnecessarily heavy.
diff --git a/gtk/channel-main.c b/gtk/channel-main.c
index 2c02ece..ef60739 100644
--- a/gtk/channel-main.c
+++ b/gtk/channel-main.c
@@ -1283,10 +1283,10 @@ static void agent_clipboard_grab(SpiceMainChannel *channel, guint selection,
/* any context: the message is not flushed immediately,
you can wakeup() the channel coroutine or send_msg_queue() */
-static void agent_clipboard_notify(SpiceMainChannel *channel, guint selection,
+static void agent_clipboard_notify(SpiceMainChannel *self, guint selection,
guint32 type, const guchar *data, size_t size)
{
- SpiceMainChannelPrivate *c = channel->priv;
+ SpiceMainChannelPrivate *c = self->priv;
VDAgentClipboard *cb;
guint8 *msg;
size_t msgsize;
@@ -1301,7 +1301,7 @@ static void agent_clipboard_notify(SpiceMainChannel *channel, guint selection,
if (HAS_CLIPBOARD_SELECTION(c))
msgsize += 4;
else if (selection != VD_AGENT_CLIPBOARD_SELECTION_CLIPBOARD) {
- CHANNEL_DEBUG(channel, "Ignoring clipboard notify");
+ CHANNEL_DEBUG(self, "Ignoring clipboard notify");
return;
}
@@ -1316,7 +1316,7 @@ static void agent_clipboard_notify(SpiceMainChannel *channel, guint selection,
}
cb->type = type;
- agent_msg_queue_many(channel, VD_AGENT_CLIPBOARD, msg, msgsize, data, size, NULL);
+ agent_msg_queue_many(self, VD_AGENT_CLIPBOARD, msg, msgsize, data, size, NULL);
}
/* any context: the message is not flushed immediately,
@@ -1819,7 +1819,8 @@ static void file_xfer_handle_status(SpiceMainChannel *channel,
static void main_agent_handle_msg(SpiceChannel *channel,
VDAgentMessage *msg, gpointer payload)
{
- SpiceMainChannelPrivate *c = SPICE_MAIN_CHANNEL(channel)->priv;
+ SpiceMainChannel *self = SPICE_MAIN_CHANNEL(channel);
+ SpiceMainChannelPrivate *c = self->priv;
guint8 selection = VD_AGENT_CLIPBOARD_SELECTION_CLIPBOARD;
g_return_if_fail(msg->protocol == VD_AGENT_PROTOCOL);
@@ -1857,15 +1858,15 @@ static void main_agent_handle_msg(SpiceChannel *channel,
VD_AGENT_SET_CAPABILITY(c->agent_caps, i);
}
c->agent_caps_received = true;
- emit_main_context(channel, SPICE_MAIN_AGENT_UPDATE);
+ emit_main_context(self, SPICE_MAIN_AGENT_UPDATE);
if (caps->request)
- agent_announce_caps(SPICE_MAIN_CHANNEL(channel));
+ agent_announce_caps(self);
if (VD_AGENT_HAS_CAPABILITY(caps->caps, G_N_ELEMENTS(c->agent_caps), VD_AGENT_CAP_DISPLAY_CONFIG) &&
!c->agent_display_config_sent) {
- agent_display_config(SPICE_MAIN_CHANNEL(channel));
- agent_send_msg_queue(SPICE_MAIN_CHANNEL(channel));
+ agent_display_config(self);
+ agent_send_msg_queue(self);
c->agent_display_config_sent = true;
}
break;
@@ -1873,21 +1874,21 @@ static void main_agent_handle_msg(SpiceChannel *channel,
case VD_AGENT_CLIPBOARD:
{
VDAgentClipboard *cb = payload;
- emit_main_context(channel, SPICE_MAIN_CLIPBOARD_SELECTION, selection,
+ emit_main_context(self, SPICE_MAIN_CLIPBOARD_SELECTION, selection,
cb->type, cb->data, msg->size - sizeof(VDAgentClipboard));
if (selection == VD_AGENT_CLIPBOARD_SELECTION_CLIPBOARD)
- emit_main_context(channel, SPICE_MAIN_CLIPBOARD,
+ emit_main_context(self, SPICE_MAIN_CLIPBOARD,
cb->type, cb->data, msg->size - sizeof(VDAgentClipboard));
break;
}
case VD_AGENT_CLIPBOARD_GRAB:
{
gboolean ret;
- emit_main_context(channel, SPICE_MAIN_CLIPBOARD_SELECTION_GRAB, selection,
+ emit_main_context(self, SPICE_MAIN_CLIPBOARD_SELECTION_GRAB, selection,
(guint8*)payload, msg->size / sizeof(uint32_t), &ret);
if (selection == VD_AGENT_CLIPBOARD_SELECTION_CLIPBOARD)
- emit_main_context(channel, SPICE_MAIN_CLIPBOARD_GRAB,
+ emit_main_context(self, SPICE_MAIN_CLIPBOARD_GRAB,
payload, msg->size / sizeof(uint32_t), &ret);
break;
}
@@ -1895,20 +1896,20 @@ static void main_agent_handle_msg(SpiceChannel *channel,
{
gboolean ret;
VDAgentClipboardRequest *req = payload;
- emit_main_context(channel, SPICE_MAIN_CLIPBOARD_SELECTION_REQUEST, selection,
+ emit_main_context(self, SPICE_MAIN_CLIPBOARD_SELECTION_REQUEST, selection,
req->type, &ret);
if (selection == VD_AGENT_CLIPBOARD_SELECTION_CLIPBOARD)
- emit_main_context(channel, SPICE_MAIN_CLIPBOARD_REQUEST,
+ emit_main_context(self, SPICE_MAIN_CLIPBOARD_REQUEST,
req->type, &ret);
break;
}
case VD_AGENT_CLIPBOARD_RELEASE:
{
- emit_main_context(channel, SPICE_MAIN_CLIPBOARD_SELECTION_RELEASE, selection);
+ emit_main_context(self, SPICE_MAIN_CLIPBOARD_SELECTION_RELEASE, selection);
if (selection == VD_AGENT_CLIPBOARD_SELECTION_CLIPBOARD)
- emit_main_context(channel, SPICE_MAIN_CLIPBOARD_RELEASE);
+ emit_main_context(self, SPICE_MAIN_CLIPBOARD_RELEASE);
break;
}
case VD_AGENT_REPLY:
@@ -1919,7 +1920,7 @@ static void main_agent_handle_msg(SpiceChannel *channel,
break;
}
case VD_AGENT_FILE_XFER_STATUS:
- file_xfer_handle_status(SPICE_MAIN_CHANNEL(channel), payload);
+ file_xfer_handle_status(self, payload);
break;
default:
g_warning("unhandled agent message type: %u (%s), size %u",
commit 9f96915b4289237981f18740eda90ecf36a65bd6
Author: Marc-André Lureau <marcandre.lureau at redhat.com>
Date: Wed Nov 6 20:37:23 2013 +0100
Add SPICE_MAX_CLIPBOARD environment variable
Allow to easily override default max-clipboard value with environment
variable.
diff --git a/gtk/channel-main.c b/gtk/channel-main.c
index d4b4416..2c02ece 100644
--- a/gtk/channel-main.c
+++ b/gtk/channel-main.c
@@ -220,12 +220,23 @@ static void spice_main_channel_init(SpiceMainChannel *channel)
spice_main_channel_reset_capabilties(SPICE_CHANNEL(channel));
}
+static gint spice_main_get_max_clipboard(SpiceMainChannel *self)
+{
+ g_return_val_if_fail(SPICE_IS_MAIN_CHANNEL(self), 0);
+
+ if (g_getenv("SPICE_MAX_CLIPBOARD"))
+ return atoi(g_getenv("SPICE_MAX_CLIPBOARD"));
+
+ return self->priv->max_clipboard;
+}
+
static void spice_main_get_property(GObject *object,
guint prop_id,
GValue *value,
GParamSpec *pspec)
{
- SpiceMainChannelPrivate *c = SPICE_MAIN_CHANNEL(object)->priv;
+ SpiceMainChannel *self = SPICE_MAIN_CHANNEL(object);
+ SpiceMainChannelPrivate *c = self->priv;
switch (prop_id) {
case PROP_MOUSE_MODE:
@@ -256,7 +267,7 @@ static void spice_main_get_property(GObject *object,
g_value_set_boolean(value, c->disable_display_align);
break;
case PROP_MAX_CLIPBOARD:
- g_value_set_int(value, c->max_clipboard);
+ g_value_set_int(value, spice_main_get_max_clipboard(self));
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec);
@@ -394,6 +405,18 @@ static void spice_main_channel_reset(SpiceChannel *channel, gboolean migrating)
SPICE_CHANNEL_CLASS(spice_main_channel_parent_class)->channel_reset(channel, migrating);
}
+static void spice_main_constructed(GObject *object)
+{
+ SpiceMainChannel *self = SPICE_MAIN_CHANNEL(object);
+ SpiceMainChannelPrivate *c = self->priv;
+
+ /* update default value */
+ c->max_clipboard = spice_main_get_max_clipboard(self);
+
+ if (G_OBJECT_CLASS(spice_main_channel_parent_class)->constructed)
+ G_OBJECT_CLASS(spice_main_channel_parent_class)->constructed(object);
+}
+
static void spice_main_channel_class_init(SpiceMainChannelClass *klass)
{
GObjectClass *gobject_class = G_OBJECT_CLASS(klass);
@@ -403,6 +426,7 @@ static void spice_main_channel_class_init(SpiceMainChannelClass *klass)
gobject_class->finalize = spice_main_channel_finalize;
gobject_class->get_property = spice_main_get_property;
gobject_class->set_property = spice_main_set_property;
+ gobject_class->constructed = spice_main_constructed;
channel_class->handle_msg = spice_main_handle_msg;
channel_class->iterate_write = spice_channel_iterate_write;
@@ -1266,13 +1290,12 @@ static void agent_clipboard_notify(SpiceMainChannel *channel, guint selection,
VDAgentClipboard *cb;
guint8 *msg;
size_t msgsize;
+ gint max_clipboard = spice_main_get_max_clipboard(channel);
g_return_if_fail(c->agent_connected);
-
g_return_if_fail(VD_AGENT_HAS_CAPABILITY(c->agent_caps,
G_N_ELEMENTS(c->agent_caps), VD_AGENT_CAP_CLIPBOARD_BY_DEMAND));
-
- g_return_if_fail(c->max_clipboard == -1 || size < c->max_clipboard);
+ g_return_if_fail(max_clipboard == -1 || size < max_clipboard);
msgsize = sizeof(VDAgentClipboard);
if (HAS_CLIPBOARD_SELECTION(c))
commit bc2139629a57b6ff4567c4194e24f58191361a2a
Author: Marc-André Lureau <marcandre.lureau at redhat.com>
Date: Wed Nov 6 20:14:50 2013 +0100
Block sending clipboard data > max-clipboard
Attempt to send very large clipboard data may easy cause OOM
abort, either in gdk - some patch are proposed to improve the situation,
or in spice-gtk itself.
Let's have a property that blocks unreasonably big clipboard data from
being processed (by default 100mb). Users willing to send larger data
can use the send basic drag-drop send file instead, or tweak the
property value.
diff --git a/gtk/channel-main.c b/gtk/channel-main.c
index 24f7428..d4b4416 100644
--- a/gtk/channel-main.c
+++ b/gtk/channel-main.c
@@ -106,6 +106,7 @@ struct _SpiceMainChannelPrivate {
guint switch_host_delayed_id;
guint migrate_delayed_id;
spice_migrate *migrate_data;
+ int max_clipboard;
};
struct spice_migrate {
@@ -137,6 +138,7 @@ enum {
PROP_DISPLAY_COLOR_DEPTH,
PROP_DISABLE_DISPLAY_POSITION,
PROP_DISABLE_DISPLAY_ALIGN,
+ PROP_MAX_CLIPBOARD,
};
/* Signals */
@@ -253,6 +255,9 @@ static void spice_main_get_property(GObject *object,
case PROP_DISABLE_DISPLAY_ALIGN:
g_value_set_boolean(value, c->disable_display_align);
break;
+ case PROP_MAX_CLIPBOARD:
+ g_value_set_int(value, c->max_clipboard);
+ break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec);
break;
@@ -286,6 +291,9 @@ static void spice_main_set_property(GObject *gobject, guint prop_id,
case PROP_DISABLE_DISPLAY_ALIGN:
c->disable_display_align = g_value_get_boolean(value);
break;
+ case PROP_MAX_CLIPBOARD:
+ c->max_clipboard = g_value_get_int(value);
+ break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID(gobject, prop_id, pspec);
break;
@@ -512,6 +520,24 @@ static void spice_main_channel_class_init(SpiceMainChannelClass *klass)
G_PARAM_CONSTRUCT |
G_PARAM_STATIC_STRINGS));
+ /**
+ * SpiceMainChannel:max-clipboard:
+ *
+ * Maximum size of clipboard operations in bytes (default 100MB,
+ * -1 for unlimited size);
+ *
+ * Since: 0.22
+ **/
+ g_object_class_install_property
+ (gobject_class, PROP_MAX_CLIPBOARD,
+ g_param_spec_int("max-clipboard",
+ "max clipboard",
+ "Maximum clipboard data size",
+ -1, G_MAXINT, 100 * 1024 * 1024,
+ G_PARAM_READWRITE |
+ G_PARAM_CONSTRUCT |
+ G_PARAM_STATIC_STRINGS));
+
/* TODO use notify instead */
/**
* SpiceMainChannel::main-mouse-update:
@@ -1246,6 +1272,8 @@ static void agent_clipboard_notify(SpiceMainChannel *channel, guint selection,
g_return_if_fail(VD_AGENT_HAS_CAPABILITY(c->agent_caps,
G_N_ELEMENTS(c->agent_caps), VD_AGENT_CAP_CLIPBOARD_BY_DEMAND));
+ g_return_if_fail(c->max_clipboard == -1 || size < c->max_clipboard);
+
msgsize = sizeof(VDAgentClipboard);
if (HAS_CLIPBOARD_SELECTION(c))
msgsize += 4;
diff --git a/gtk/spice-gtk-session.c b/gtk/spice-gtk-session.c
index 71ed300..eab7e2f 100644
--- a/gtk/spice-gtk-session.c
+++ b/gtk/spice-gtk-session.c
@@ -748,16 +748,19 @@ static void clipboard_received_cb(GtkClipboard *clipboard,
gchar* name;
GdkAtom atom;
int selection;
+ int max_clipboard;
selection = get_selection_from_clipboard(s, clipboard);
g_return_if_fail(selection != -1);
+ g_object_get(s->main, "max-clipboard", &max_clipboard, NULL);
len = gtk_selection_data_get_length(selection_data);
- if (len == -1) {
+ if (len == 0 || (max_clipboard != -1 && len > max_clipboard)) {
+ g_warning("discarded clipboard of size %d (max: %d)", len, max_clipboard);
+ return;
+ } else if (len == -1) {
SPICE_DEBUG("empty clipboard");
len = 0;
- } else if (len == 0) {
- SPICE_DEBUG("TODO: what should be done here?");
} else {
atom = gtk_selection_data_get_data_type(selection_data);
name = gdk_atom_name(atom);
More information about the Spice-commits
mailing list