summaryrefslogtreecommitdiff
path: root/gtk/channel-main.c
diff options
context:
space:
mode:
authorMarc-André Lureau <marcandre.lureau@redhat.com>2010-11-26 18:16:32 +0100
committerMarc-André Lureau <marcandre.lureau@redhat.com>2010-11-26 18:17:24 +0100
commit984a74fe9c5217c16af628f7f1dbea328cd52ecc (patch)
tree2c2f8058ae22184be0be0f68b84a64d486f73c9b /gtk/channel-main.c
parentdb29073aa5b6ddc4c630e901ad4304160e22ad2f (diff)
gtk: progressive agent message recomposition
Diffstat (limited to 'gtk/channel-main.c')
-rw-r--r--gtk/channel-main.c115
1 files changed, 90 insertions, 25 deletions
diff --git a/gtk/channel-main.c b/gtk/channel-main.c
index a77144e..2d4f70c 100644
--- a/gtk/channel-main.c
+++ b/gtk/channel-main.c
@@ -31,9 +31,10 @@ struct spice_main_channel {
bool agent_connected;
bool agent_caps_received;
int agent_tokens;
- uint8_t *agent_msg;
- uint8_t *agent_msg_pos;
- uint8_t *agent_msg_size;
+ VDAgentMessage agent_msg; /* partial msg reconstruction */
+ guint8 *agent_msg_data;
+ uint8_t agent_msg_pos;
+ uint8_t agent_msg_size;
uint32_t agent_caps[VD_AGENT_CAPS_SIZE];
struct {
int x;
@@ -133,6 +134,7 @@ static void spice_main_channel_finalize(GObject *obj)
g_source_remove(c->timer_id);
}
+ g_free(c->agent_msg_data);
g_queue_free(c->agent_msg_queue);
if (G_OBJECT_CLASS(spice_main_channel_parent_class)->finalize)
@@ -438,31 +440,11 @@ static void main_handle_agent_disconnected(SpiceChannel *channel, spice_msg_in *
agent_stopped(SPICE_MAIN_CHANNEL(channel));
}
-static void main_handle_agent_data(SpiceChannel *channel, spice_msg_in *in)
+static void main_agent_handle_msg(SpiceChannel *channel,
+ VDAgentMessage *msg, gpointer payload)
{
spice_main_channel *c = SPICE_MAIN_CHANNEL(channel)->priv;
- VDAgentMessage *msg;
- void *payload;
- int len;
-
- /* spice_msg_in_hexdump(in); */
-
- if (!c->agent_msg) {
- msg = spice_msg_in_raw(in, &len);
- g_return_if_fail(len > sizeof(VDAgentMessage));
- if (msg->size + sizeof(VDAgentMessage) > len) {
- g_warning("%s: TODO: start buffer", __FUNCTION__);
- } else {
- g_return_if_fail(msg->size + sizeof(VDAgentMessage) == len);
- goto complete;
- }
- } else {
- g_warning("%s: TODO: fill buffer", __FUNCTION__);
- }
- return;
-complete:
- payload = (msg+1);
switch (msg->type) {
case VD_AGENT_ANNOUNCE_CAPABILITIES:
{
@@ -482,8 +464,32 @@ complete:
}
c->agent_caps_received = true;
g_signal_emit(channel, signals[SPICE_MAIN_AGENT_UPDATE], 0);
+
if (caps->request)
agent_announce_caps(SPICE_MAIN_CHANNEL(channel));
+ break;
+ }
+ case VD_AGENT_CLIPBOARD:
+ {
+ g_message("VD_AGENT_CLIPBOARD FIXME");
+ break;
+ }
+ case VD_AGENT_CLIPBOARD_GRAB:
+ {
+ g_message("VD_AGENT_CLIPBOARD_GRAB FIXME");
+ /* Platform::on_clipboard_grab((uint32_t *)data, */
+ /* msg->size / sizeof(uint32_t)); */
+ break;
+ }
+ case VD_AGENT_CLIPBOARD_REQUEST:
+ {
+ g_message("VD_AGENT_CLIPBOARD_REQUEST FIXME");
+ break;
+ }
+ case VD_AGENT_CLIPBOARD_RELEASE:
+ {
+ g_message("VD_AGENT_CLIPBOARD_RELEASE FIXME");
+ break;
}
case VD_AGENT_REPLY:
{
@@ -498,6 +504,65 @@ complete:
}
}
+static void main_handle_agent_data_msg(SpiceChannel *channel, guint* msg_size, guchar** msg_pos)
+{
+ spice_main_channel *c = SPICE_MAIN_CHANNEL(channel)->priv;
+ int n;
+
+ if (c->agent_msg_pos < sizeof(VDAgentMessage)) {
+ n = MIN(sizeof(VDAgentMessage) - c->agent_msg_pos, *msg_size);
+ memcpy((uint8_t*)&c->agent_msg + c->agent_msg_pos, *msg_pos, n);
+ c->agent_msg_pos += n;
+ *msg_size -= n;
+ *msg_pos += n;
+ if (c->agent_msg_pos == sizeof(VDAgentMessage)) {
+ SPICE_DEBUG("agent msg start: msg_size=%d, protocol=%d, type=%d",
+ c->agent_msg.size, c->agent_msg.protocol, c->agent_msg.type);
+ g_return_if_fail(c->agent_msg.protocol == VD_AGENT_PROTOCOL);
+ g_return_if_fail(c->agent_msg_data == NULL);
+ c->agent_msg_data = g_malloc(c->agent_msg.size);
+ }
+ }
+
+ if (c->agent_msg_pos >= sizeof(VDAgentMessage)) {
+ n = MIN(sizeof(VDAgentMessage) + c->agent_msg.size - c->agent_msg_pos, *msg_size);
+ memcpy(c->agent_msg_data + c->agent_msg_pos - sizeof(VDAgentMessage), *msg_pos, n);
+ c->agent_msg_pos += n;
+ *msg_size -= n;
+ *msg_pos += n;
+ }
+
+ if (c->agent_msg_pos == sizeof(VDAgentMessage) + c->agent_msg.size) {
+ main_agent_handle_msg(channel, &c->agent_msg, c->agent_msg_data);
+ g_free(c->agent_msg_data);
+ c->agent_msg_data = NULL;
+ c->agent_msg_pos = 0;
+ }
+}
+
+static void main_handle_agent_data(SpiceChannel *channel, spice_msg_in *in)
+{
+ spice_main_channel *c = SPICE_MAIN_CHANNEL(channel)->priv;
+ VDAgentMessage *msg;
+ guint msg_size;
+ guchar* msg_pos;
+ int len;
+
+ msg = spice_msg_in_raw(in, &len);
+ msg_size = msg->size;
+ msg_pos = msg->data;
+
+ if (c->agent_msg_pos == 0 &&
+ msg_size + sizeof(VDAgentMessage) == len) {
+ main_agent_handle_msg(channel, msg, msg + 1);
+ return;
+ }
+
+ while (msg_size > 0) {
+ main_handle_agent_data_msg(channel, &msg_size, &msg_pos);
+ }
+}
+
static void main_handle_agent_token(SpiceChannel *channel, spice_msg_in *in)
{
SpiceMsgMainAgentTokens *tokens = spice_msg_in_parsed(in);