[Spice-devel] [PATCH spice-gtk 3/5] Add support for SPICE_COMMON_CAP_MINI_HEADER
Yonit Halperin
yhalperi at redhat.com
Sun Jan 8 00:53:48 PST 2012
Don't send/receive serial and sub_list when the server supports the
above cap.
---
gtk/channel-base.c | 8 ++-
gtk/spice-channel-priv.h | 12 ++++-
gtk/spice-channel.c | 121 ++++++++++++++++++++++++++++++++++------------
3 files changed, 103 insertions(+), 38 deletions(-)
diff --git a/gtk/channel-base.c b/gtk/channel-base.c
index a6a2892..4d93093 100644
--- a/gtk/channel-base.c
+++ b/gtk/channel-base.c
@@ -134,8 +134,9 @@ void spice_channel_handle_migrate(SpiceChannel *channel, SpiceMsgIn *in)
spice_channel_recv_msg(channel, get_msg_handler, &data);
if (!data) {
g_warning("expected SPICE_MSG_MIGRATE_DATA, got empty message");
- } else if (data->header.type != SPICE_MSG_MIGRATE_DATA) {
- g_warning("expected SPICE_MSG_MIGRATE_DATA, got %d", data->header.type);
+ } else if (spice_header_wrapper_get_msg_type(data->header) != SPICE_MSG_MIGRATE_DATA) {
+ g_warning("expected SPICE_MSG_MIGRATE_DATA, got %d",
+ spice_header_wrapper_get_msg_type(data->header));
}
}
@@ -143,7 +144,8 @@ void spice_channel_handle_migrate(SpiceChannel *channel, SpiceMsgIn *in)
if ((mig->flags & SPICE_MIGRATE_NEED_DATA_TRANSFER) && (data != NULL)) {
out = spice_msg_out_new(SPICE_CHANNEL(channel), SPICE_MSGC_MIGRATE_DATA);
- spice_marshaller_add(out->marshaller, data->data, data->header.size);
+ spice_marshaller_add(out->marshaller, data->data,
+ spice_header_wrapper_get_msg_size(data->header));
spice_msg_out_send_internal(out);
}
}
diff --git a/gtk/spice-channel-priv.h b/gtk/spice-channel-priv.h
index df35e4c..38ca23c 100644
--- a/gtk/spice-channel-priv.h
+++ b/gtk/spice-channel-priv.h
@@ -37,22 +37,25 @@
#include "demarshallers.h"
#include "ssl_verify.h"
+#include "spice-header.h"
G_BEGIN_DECLS
+
struct _SpiceMsgOut {
int refcount;
SpiceChannel *channel;
SpiceMessageMarshallers *marshallers;
SpiceMarshaller *marshaller;
- SpiceDataHeader *header;
+ SpiceHeaderWrapper *header;
gboolean ro_check;
};
struct _SpiceMsgIn {
int refcount;
SpiceChannel *channel;
- SpiceDataHeader header;
+ uint8_t header_buf[MAX_SPICE_DATA_HEADER_SIZE];
+ SpiceHeaderWrapper *header;
uint8_t *data;
int hpos,dpos;
uint8_t *parsed;
@@ -86,6 +89,10 @@ struct _SpiceChannelPrivate {
unsigned int sasl_decoded_offset;
#endif
+ gboolean use_mini_header;
+ uint64_t out_serial;
+ uint64_t in_serial;
+
/* not swapped */
SpiceSession *session;
struct coroutine coroutine;
@@ -109,7 +116,6 @@ struct _SpiceChannelPrivate {
int connection_id;
int channel_id;
int channel_type;
- int serial;
SpiceLinkHeader link_hdr;
SpiceLinkMess link_msg;
SpiceLinkHeader peer_hdr;
diff --git a/gtk/spice-channel.c b/gtk/spice-channel.c
index c4abd7b..2e33cda 100644
--- a/gtk/spice-channel.c
+++ b/gtk/spice-channel.c
@@ -41,6 +41,7 @@
#include <ctype.h>
#include "gio-coroutine.h"
+#include "spice-header.h"
static void spice_channel_handle_msg(SpiceChannel *channel, SpiceMsgIn *msg);
static void spice_channel_write_msg(SpiceChannel *channel, SpiceMsgOut *out);
@@ -98,7 +99,8 @@ static void spice_channel_init(SpiceChannel *channel)
c = channel->priv = SPICE_CHANNEL_GET_PRIVATE(channel);
- c->serial = 1;
+ c->out_serial = 1;
+ c->in_serial = 1;
c->fd = -1;
strcpy(c->name, "?");
c->caps = g_array_new(FALSE, TRUE, sizeof(guint32));
@@ -106,6 +108,7 @@ static void spice_channel_init(SpiceChannel *channel)
c->remote_caps = g_array_new(FALSE, TRUE, sizeof(guint32));
c->remote_common_caps = g_array_new(FALSE, TRUE, sizeof(guint32));
spice_channel_set_common_capability(channel, SPICE_COMMON_CAP_PROTOCOL_AUTH_SELECTION);
+ spice_channel_set_common_capability(channel, SPICE_COMMON_CAP_MINI_HEADER);
g_queue_init(&c->xmit_queue);
g_static_mutex_init(&c->xmit_queue_lock);
c->main_thread = g_thread_self();
@@ -359,6 +362,13 @@ SpiceMsgIn *spice_msg_in_new(SpiceChannel *channel)
in = spice_new0(SpiceMsgIn, 1);
in->refcount = 1;
in->channel = channel;
+ if (channel->priv->use_mini_header) {
+ in->header = SPICE_HEADER_WRAPPER(g_object_new(SPICE_TYPE_MINI_HEADER, NULL));
+ } else {
+ in->header = SPICE_HEADER_WRAPPER(g_object_new(SPICE_TYPE_FULL_HEADER, NULL));
+ }
+ spice_header_wrapper_set_data(in->header, in->header_buf);
+
return in;
}
@@ -371,8 +381,8 @@ SpiceMsgIn *spice_msg_in_sub_new(SpiceChannel *channel, SpiceMsgIn *parent,
g_return_val_if_fail(channel != NULL, NULL);
in = spice_msg_in_new(channel);
- in->header.type = sub->type;
- in->header.size = sub->size;
+ spice_header_wrapper_set_msg_type(in->header, sub->type);
+ spice_header_wrapper_set_msg_size(in->header, sub->size);
in->data = (uint8_t*)(sub+1);
in->dpos = sub->size;
in->parent = parent;
@@ -403,6 +413,7 @@ void spice_msg_in_unref(SpiceMsgIn *in)
} else {
free(in->data);
}
+ g_object_unref(in->header);
free(in);
}
@@ -411,7 +422,7 @@ int spice_msg_in_type(SpiceMsgIn *in)
{
g_return_val_if_fail(in != NULL, -1);
- return in->header.type;
+ return spice_header_wrapper_get_msg_type(in->header);
}
G_GNUC_INTERNAL
@@ -453,10 +464,19 @@ G_GNUC_INTERNAL
void spice_msg_in_hexdump(SpiceMsgIn *in)
{
SpiceChannelPrivate *c = in->channel->priv;
+ uint64_t serial = c->in_serial;
+ int sub_list = 0;
+
+ if (!c->use_mini_header) {
+ SpiceFullHeader *full_header = SPICE_FULL_HEADER(in->header);
+ serial = spice_full_header_get_msg_serial(full_header);
+ sub_list = spice_full_header_get_msg_sub_list(full_header);
+ }
fprintf(stderr, "--\n<< hdr: %s serial %" PRIu64 " type %d size %d sub-list %d\n",
- c->name, in->header.serial, in->header.type,
- in->header.size, in->header.sub_list);
+ c->name,
+ serial, spice_header_wrapper_get_msg_type(in->header),
+ spice_header_wrapper_get_msg_size(in->header), sub_list);
hexdump("<< msg", in->data, in->dpos);
}
@@ -464,10 +484,17 @@ G_GNUC_INTERNAL
void spice_msg_out_hexdump(SpiceMsgOut *out, unsigned char *data, int len)
{
SpiceChannelPrivate *c = out->channel->priv;
+ uint64_t serial = c->out_serial;
+ int sub_list = 0;
+ if (!c->use_mini_header) {
+ SpiceFullHeader *full_header = SPICE_FULL_HEADER(out->header);
+ serial = spice_full_header_get_msg_serial(full_header);
+ sub_list = spice_full_header_get_msg_sub_list(full_header);
+ }
fprintf(stderr, "--\n>> hdr: %s serial %" PRIu64 " type %d size %d sub-list %d\n",
- c->name, out->header->serial, out->header->type,
- out->header->size, out->header->sub_list);
+ c->name, serial, spice_header_wrapper_get_msg_type(out->header),
+ spice_header_wrapper_get_msg_size(out->header), sub_list);
hexdump(">> msg", data, len);
}
@@ -500,6 +527,7 @@ SpiceMsgOut *spice_msg_out_new(SpiceChannel *channel, int type)
{
SpiceChannelPrivate *c = channel->priv;
SpiceMsgOut *out;
+ uint8_t *header_buf;
g_return_val_if_fail(c != NULL, NULL);
@@ -510,12 +538,23 @@ SpiceMsgOut *spice_msg_out_new(SpiceChannel *channel, int type)
out->marshallers = c->marshallers;
out->marshaller = spice_marshaller_new();
- out->header = (SpiceDataHeader *)
- spice_marshaller_reserve_space(out->marshaller, sizeof(SpiceDataHeader));
- spice_marshaller_set_base(out->marshaller, sizeof(SpiceDataHeader));
- out->header->serial = c->serial++;
- out->header->type = type;
- out->header->sub_list = 0;
+ if (c->use_mini_header) {
+ out->header = SPICE_HEADER_WRAPPER(g_object_new(SPICE_TYPE_MINI_HEADER, NULL));
+ } else {
+ out->header = SPICE_HEADER_WRAPPER(g_object_new(SPICE_TYPE_FULL_HEADER, NULL));
+ }
+
+ header_buf = spice_marshaller_reserve_space(out->marshaller,
+ spice_header_wrapper_get_header_size(out->header));
+ spice_header_wrapper_set_data(out->header, header_buf);
+ spice_marshaller_set_base(out->marshaller, spice_header_wrapper_get_header_size(out->header));
+ spice_header_wrapper_set_msg_type(out->header, type);
+
+ if (!c->use_mini_header) {
+ spice_full_header_set_msg_serial(SPICE_FULL_HEADER(out->header), c->out_serial);
+ spice_full_header_set_msg_sub_list(SPICE_FULL_HEADER(out->header), 0);
+ }
+ c->out_serial++;
return out;
}
@@ -536,6 +575,7 @@ void spice_msg_out_unref(SpiceMsgOut *out)
if (out->refcount > 0)
return;
spice_marshaller_destroy(out->marshaller);
+ g_object_unref(out->header);
free(out);
}
@@ -710,6 +750,7 @@ static void spice_channel_write_msg(SpiceChannel *channel, SpiceMsgOut *out)
uint8_t *data;
int free_data;
size_t len;
+ uint32_t msg_size;
g_return_if_fail(channel != NULL);
g_return_if_fail(out != NULL);
@@ -721,8 +762,9 @@ static void spice_channel_write_msg(SpiceChannel *channel, SpiceMsgOut *out)
return;
}
- out->header->size =
- spice_marshaller_get_total_size(out->marshaller) - sizeof(SpiceDataHeader);
+ msg_size = spice_marshaller_get_total_size(out->marshaller) -
+ spice_header_wrapper_get_header_size(out->header);
+ spice_header_wrapper_set_msg_size(out->header, msg_size);
data = spice_marshaller_linearize(out->marshaller, 0, &len, &free_data);
/* spice_msg_out_hexdump(out, data, len); */
spice_channel_write(channel, data, len);
@@ -1569,7 +1611,8 @@ static void spice_channel_recv_link_msg(SpiceChannel *channel)
goto error;
}
}
-
+ c->use_mini_header = spice_channel_test_common_capability(channel,
+ SPICE_COMMON_CAP_MINI_HEADER);
return;
error:
@@ -1600,54 +1643,66 @@ void spice_channel_recv_msg(SpiceChannel *channel,
{
SpiceChannelPrivate *c = channel->priv;
SpiceMsgIn *in;
+ int header_size;
+ int msg_size;
+ int msg_type;
+ int sub_list_offset = 0;
int rc;
if (!c->msg_in) {
c->msg_in = spice_msg_in_new(channel);
}
in = c->msg_in;
+ header_size = spice_header_wrapper_get_header_size(in->header);
/* receive message */
- if (in->hpos < sizeof(in->header)) {
- rc = spice_channel_read(channel, (uint8_t*)&in->header + in->hpos,
- sizeof(in->header) - in->hpos);
+ if (in->hpos < header_size) {
+ rc = spice_channel_read(channel, in->header_buf + in->hpos,
+ header_size - in->hpos);
if (rc < 0) {
g_critical("recv hdr: %s", strerror(errno));
return;
}
in->hpos += rc;
- if (in->hpos < sizeof(in->header))
+ if (in->hpos < header_size)
return;
- in->data = spice_malloc(in->header.size);
+ in->data = spice_malloc(spice_header_wrapper_get_msg_size(in->header));
}
- if (in->dpos < in->header.size) {
+ msg_size = spice_header_wrapper_get_msg_size(in->header);
+ if (in->dpos < msg_size) {
rc = spice_channel_read(channel, in->data + in->dpos,
- in->header.size - in->dpos);
+ msg_size - in->dpos);
if (rc < 0) {
g_critical("recv msg: %s", strerror(errno));
return;
}
in->dpos += rc;
- if (in->dpos < in->header.size)
+ if (in->dpos < msg_size)
return;
}
- if (in->header.type == SPICE_MSG_LIST || in->header.sub_list) {
+ msg_type = spice_header_wrapper_get_msg_type(in->header);
+ if (!c->use_mini_header) {
+ sub_list_offset = spice_full_header_get_msg_sub_list(SPICE_FULL_HEADER(in->header));
+ }
+
+ if (msg_type == SPICE_MSG_LIST || sub_list_offset) {
SpiceSubMessageList *sub_list;
SpiceSubMessage *sub;
SpiceMsgIn *sub_in;
int i;
- sub_list = (SpiceSubMessageList *)(in->data + in->header.sub_list);
+ sub_list = (SpiceSubMessageList *)(in->data + sub_list_offset);
for (i = 0; i < sub_list->size; i++) {
sub = (SpiceSubMessage *)(in->data + sub_list->sub_messages[i]);
sub_in = spice_msg_in_sub_new(channel, in, sub);
sub_in->parsed = c->parser(sub_in->data, sub_in->data + sub_in->dpos,
- sub_in->header.type, c->peer_hdr.minor_version,
+ spice_header_wrapper_get_msg_type(sub_in->header),
+ c->peer_hdr.minor_version,
&sub_in->psize, &sub_in->pfree);
if (sub_in->parsed == NULL) {
g_critical("failed to parse sub-message: %s type %d",
- c->name, sub_in->header.type);
+ c->name, spice_header_wrapper_get_msg_type(sub_in->header));
return;
}
msg_handler(channel, sub_in, data);
@@ -1665,16 +1720,16 @@ void spice_channel_recv_msg(SpiceChannel *channel,
}
}
- if (in->header.type == SPICE_MSG_LIST) {
+ if (msg_type == SPICE_MSG_LIST) {
goto end;
}
/* parse message */
- in->parsed = c->parser(in->data, in->data + in->dpos, in->header.type,
+ in->parsed = c->parser(in->data, in->data + in->dpos, msg_type,
c->peer_hdr.minor_version, &in->psize, &in->pfree);
if (in->parsed == NULL) {
g_critical("failed to parse message: %s type %d",
- c->name, in->header.type);
+ c->name, msg_type);
goto end;
}
@@ -1684,6 +1739,7 @@ void spice_channel_recv_msg(SpiceChannel *channel,
msg_handler(channel, in, data);
end:
+ c->in_serial++;
/* release message */
c->msg_in = NULL;
spice_msg_in_unref(in);
@@ -2224,6 +2280,7 @@ static void channel_reset(SpiceChannel *channel, gboolean migrating)
g_array_set_size(c->caps, 0);
/* Restore our default capabilities in case the channel gets re-used */
spice_channel_set_common_capability(channel, SPICE_COMMON_CAP_PROTOCOL_AUTH_SELECTION);
+ spice_channel_set_common_capability(channel, SPICE_COMMON_CAP_MINI_HEADER);
}
/* system or coroutine context */
--
1.7.6.4
More information about the Spice-devel
mailing list