[Spice-commits] 34 commits - client/canvas.cpp client/canvas.h client/cursor_channel.cpp client/cursor_channel.h client/cursor.h client/demarshallers.h client/display_channel.cpp client/display_channel.h client/inputs_channel.cpp client/Makefile.am client/marshaller.cpp client/playback_channel.cpp client/record_channel.cpp client/red_channel.cpp client/red_channel.h client/red_client.cpp client/red_client.h client/red_peer.cpp client/red_peer.h client/tunnel_channel.cpp client/windows client/x11 common/canvas_base.c common/canvas_base.h common/gdi_canvas.c common/gl_canvas.c common/Makefile.am common/marshaller.c common/marshaller.h common/mem.c common/mem.h common/messages.h common/sw_canvas.c configure.ac Makefile.am python_modules/codegen.py python_modules/demarshal.py python_modules/__init__.py python_modules/Makefile.am python_modules/marshal.py python_modules/ptypes.py python_modules/spice_parser.py server/demarshallers.h server/Makefile.am server/red_common.h server/reds.c se rver/red_worker.c server/snd_worker.c spice_codegen.py spice.proto
Alexander Larsson
alexl at kemper.freedesktop.org
Fri Jun 18 12:23:18 PDT 2010
Makefile.am | 4
client/Makefile.am | 25
client/canvas.cpp | 102 --
client/canvas.h | 3
client/cursor.h | 2
client/cursor_channel.cpp | 48 -
client/cursor_channel.h | 2
client/demarshallers.h | 25
client/display_channel.cpp | 154 +--
client/display_channel.h | 3
client/inputs_channel.cpp | 87 +
client/marshaller.cpp | 24
client/playback_channel.cpp | 57 -
client/record_channel.cpp | 65 -
client/red_channel.cpp | 28
client/red_channel.h | 89 +
client/red_client.cpp | 94 +-
client/red_client.h | 2
client/red_peer.cpp | 65 -
client/red_peer.h | 19
client/tunnel_channel.cpp | 151 +--
client/windows/generate.bat | 3
client/windows/redc.vcproj | 79 +
client/x11/Makefile.am | 6
common/Makefile.am | 2
common/canvas_base.c | 54 -
common/canvas_base.h | 1
common/gdi_canvas.c | 21
common/gl_canvas.c | 19
common/marshaller.c | 590 +++++++++++++
common/marshaller.h | 62 +
common/mem.c | 12
common/mem.h | 2
common/messages.h | 498 +++++++++++
common/sw_canvas.c | 10
configure.ac | 2
python_modules/Makefile.am | 6
python_modules/codegen.py | 354 +++++++
python_modules/demarshal.py | 1045 +++++++++++++++++++++++
python_modules/marshal.py | 358 +++++++
python_modules/ptypes.py | 965 +++++++++++++++++++++
python_modules/spice_parser.py | 157 +++
server/Makefile.am | 18
server/demarshallers.h | 25
server/red_common.h | 2
server/red_worker.c | 1855 +++++++++++++++++++++++------------------
server/reds.c | 577 +++++-------
server/snd_worker.c | 301 ++----
spice.proto | 1086 ++++++++++++++++++++++++
spice_codegen.py | 200 ++++
50 files changed, 7399 insertions(+), 1960 deletions(-)
New commits:
commit ae4436215cb113a02eac73c6afd368166090967c
Author: Alexander Larsson <alexl at redhat.com>
Date: Fri Jun 18 21:10:25 2010 +0200
Make generated marshallers build on win32
diff --git a/client/windows/generate.bat b/client/windows/generate.bat
new file mode 100644
index 0000000..3757bb0
--- /dev/null
+++ b/client/windows/generate.bat
@@ -0,0 +1,3 @@
+python ..\..\spice_codegen.py -d -c -i common.h -i messages.h ..\..\spice.proto ..\generated_demarshallers.cpp
+python ..\..\spice_codegen.py --generate-marshallers --include messages.h --client ..\..\spice.proto ..\generated_marshallers.cpp
+python ..\..\spice_codegen.py --generate-marshallers --client -H ..\..\spice.proto ..\generated_marshallers.h
diff --git a/client/windows/redc.vcproj b/client/windows/redc.vcproj
index a178a33..8f9e509 100644
--- a/client/windows/redc.vcproj
+++ b/client/windows/redc.vcproj
@@ -220,10 +220,6 @@
>
</File>
<File
- RelativePath="..\generated_demarshallers.cpp"
- >
- </File>
- <File
RelativePath="..\display_channel.cpp"
>
</File>
@@ -236,6 +232,10 @@
>
</File>
<File
+ RelativePath="..\generated_demarshallers.cpp"
+ >
+ </File>
+ <File
RelativePath="..\glz_decoder.cpp"
>
</File>
@@ -500,6 +500,14 @@
>
</File>
<File
+ RelativePath="..\generated_marshallers.cpp"
+ >
+ </File>
+ <File
+ RelativePath="..\generated_marshallers.h"
+ >
+ </File>
+ <File
RelativePath="..\..\common\win\my_getopt-1.5\getopt.h"
>
</File>
@@ -544,6 +552,10 @@
>
</File>
<File
+ RelativePath="..\marshaller.cpp"
+ >
+ </File>
+ <File
RelativePath="..\menu.h"
>
</File>
@@ -695,9 +707,9 @@
<Tool
Name="VCCustomBuildTool"
Description="Generating demarshaller"
- CommandLine="python $(ProjectDir)\..\..\spice_codegen.py -d -c -i common.h $(ProjectDir)\..\..\spice.proto $(ProjectDir)\..\generated_demarshallers.cpp
"
+ CommandLine="generate.bat"
AdditionalDependencies=""
- Outputs="$(ProjectDir)/../generated_demarshallers.cpp"
+ Outputs="$(ProjectDir)/../generated_demarshallers.cpp;$(ProjectDir)/../generated_marshallers.h;$(ProjectDir)/../generated_marshallers.cpp"
/>
</FileConfiguration>
<FileConfiguration
@@ -706,8 +718,8 @@
<Tool
Name="VCCustomBuildTool"
Description="Generating demarshaller"
- CommandLine="python $(ProjectDir)\..\..\spice_codegen.py -d -c -i common.h $(ProjectDir)\..\..\spice.proto $(ProjectDir)\..\generated_demarshallers.cpp"
- Outputs="$(ProjectDir)/../generated_demarshallers.cpp"
+ CommandLine="generate.bat"
+ Outputs="$(ProjectDir)/../generated_demarshallers.cpp;$(ProjectDir)/../generated_marshallers.h;$(ProjectDir)/../generated_marshallers.cpp"
/>
</FileConfiguration>
</File>
diff --git a/common/marshaller.c b/common/marshaller.c
index 13385e5..5844b89 100644
--- a/common/marshaller.c
+++ b/common/marshaller.c
@@ -491,6 +491,7 @@ void spice_marshaller_flush(SpiceMarshaller *m)
}
}
+#ifndef WIN32
int spice_marshaller_fill_iovec(SpiceMarshaller *m, struct iovec *vec,
int n_vec, size_t skip_bytes)
{
@@ -522,6 +523,7 @@ int spice_marshaller_fill_iovec(SpiceMarshaller *m, struct iovec *vec,
return v;
}
+#endif
void spice_marshaller_add_uint64(SpiceMarshaller *m, uint64_t v)
{
diff --git a/common/marshaller.h b/common/marshaller.h
index 3b159aa..a60e97b 100644
--- a/common/marshaller.h
+++ b/common/marshaller.h
@@ -20,7 +20,9 @@
#define _H_MARSHALLER
#include <spice/types.h>
+#ifndef WIN32
#include <sys/uio.h>
+#endif
typedef struct SpiceMarshaller SpiceMarshaller;
typedef void (*spice_marshaller_item_free_func)(uint8_t *data, void *opaque);
@@ -44,8 +46,10 @@ size_t spice_marshaller_get_size(SpiceMarshaller *m);
size_t spice_marshaller_get_total_size(SpiceMarshaller *m);
SpiceMarshaller *spice_marshaller_get_submarshaller(SpiceMarshaller *m);
SpiceMarshaller *spice_marshaller_get_ptr_submarshaller(SpiceMarshaller *m, int is_64bit);
+#ifndef WIN32
int spice_marshaller_fill_iovec(SpiceMarshaller *m, struct iovec *vec,
int n_vec, size_t skip_bytes);
+#endif
void spice_marshaller_add_uint64(SpiceMarshaller *m, uint64_t v);
void spice_marshaller_add_int64(SpiceMarshaller *m, int64_t v);
void spice_marshaller_add_uint32(SpiceMarshaller *m, uint32_t v);
diff --git a/python_modules/marshal.py b/python_modules/marshal.py
index 23b029a..4cbf942 100644
--- a/python_modules/marshal.py
+++ b/python_modules/marshal.py
@@ -18,6 +18,7 @@ def write_includes(writer):
writer.newline()
writer.writeln("#ifdef _MSC_VER")
writer.writeln("#pragma warning(disable:4101)")
+ writer.writeln("#pragma warning(disable:4018)")
writer.writeln("#endif")
writer.newline()
commit 0f2e0378348f87c8e408a1db59783e1d9c00d68d
Author: Alexander Larsson <alexl at redhat.com>
Date: Fri Jun 18 20:18:32 2010 +0200
Add server/demarshaller.h
diff --git a/server/demarshallers.h b/server/demarshallers.h
new file mode 100644
index 0000000..e568cd0
--- /dev/null
+++ b/server/demarshallers.h
@@ -0,0 +1,25 @@
+/*
+ Copyright (C) 2010 Red Hat, Inc.
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this library; if not, see <http://www.gnu.org/licenses/>.
+*/
+#ifndef _H_DEMARSHAL
+#define _H_DEMARSHAL
+
+typedef uint8_t * (*spice_parse_channel_func_t)(uint8_t *message_start, uint8_t *message_end, uint16_t message_type, int minor, size_t *size_out);
+
+spice_parse_channel_func_t spice_get_client_channel_parser(uint32_t channel, unsigned int *max_message_type);
+
+#endif
+
commit 972951dbb78ecb8b9b7549a1302a49a00ad1b44b
Author: Alexander Larsson <alexl at redhat.com>
Date: Fri Jun 18 17:12:31 2010 +0200
Make sound data @as_ptr to avoid copying data
diff --git a/client/playback_channel.cpp b/client/playback_channel.cpp
index 9ac6ed6..1e902a9 100644
--- a/client/playback_channel.cpp
+++ b/client/playback_channel.cpp
@@ -295,8 +295,8 @@ void PlaybackChannel::handle_stop(RedPeer::InMessage* message)
void PlaybackChannel::handle_raw_data(RedPeer::InMessage* message)
{
SpiceMsgPlaybackPacket* packet = (SpiceMsgPlaybackPacket*)message->data();
- uint8_t* data = (uint8_t*)(packet + 1);
- uint32_t size = message->size() - sizeof(*packet);
+ uint8_t* data = packet->data;
+ uint32_t size = packet->data_size;
#ifdef WAVE_CAPTURE
put_wave_data(data, size);
return;
@@ -315,8 +315,8 @@ void PlaybackChannel::handle_raw_data(RedPeer::InMessage* message)
void PlaybackChannel::handle_celt_data(RedPeer::InMessage* message)
{
SpiceMsgPlaybackPacket* packet = (SpiceMsgPlaybackPacket*)message->data();
- uint8_t* data = (uint8_t*)(packet + 1);
- uint32_t size = message->size() - sizeof(*packet);
+ uint8_t* data = packet->data;
+ uint32_t size = packet->data_size;
celt_int16_t pcm[256 * 2];
if (celt051_decode(_celt_decoder, data, size, pcm) != CELT_OK) {
diff --git a/common/messages.h b/common/messages.h
index e317949..7575f07 100644
--- a/common/messages.h
+++ b/common/messages.h
@@ -368,7 +368,8 @@ typedef struct SpiceMsgcMouseRelease {
typedef struct SpiceMsgPlaybackMode {
uint32_t time;
uint32_t mode; //SPICE_AUDIO_DATA_MODE_?
- uint8_t data[0];
+ uint8_t *data;
+ uint32_t data_size;
} SpiceMsgPlaybackMode, SpiceMsgcRecordMode;
typedef struct SpiceMsgPlaybackStart {
@@ -380,7 +381,8 @@ typedef struct SpiceMsgPlaybackStart {
typedef struct SpiceMsgPlaybackPacket {
uint32_t time;
- uint8_t data[0];
+ uint8_t *data;
+ uint32_t data_size;
} SpiceMsgPlaybackPacket, SpiceMsgcRecordPacket;
typedef struct SpiceMsgRecordStart {
diff --git a/server/snd_worker.c b/server/snd_worker.c
index 544da3b..d55380c 100644
--- a/server/snd_worker.c
+++ b/server/snd_worker.c
@@ -281,7 +281,7 @@ static int snd_record_handle_write(RecordChannel *record_channel, size_t size, v
}
packet = (SpiceMsgcRecordPacket *)message;
- size = size - sizeof(*packet);
+ size = packet->data_size;
if (record_channel->mode == SPICE_AUDIO_DATA_MODE_CELT_0_5_1) {
int celt_err = celt051_decode(record_channel->celt_decoder, packet->data, size,
diff --git a/spice.proto b/spice.proto
index bad9ed3..6cedfac 100644
--- a/spice.proto
+++ b/spice.proto
@@ -921,13 +921,13 @@ channel PlaybackChannel : BaseChannel {
server:
message {
uint32 time;
- uint8 data[] @end;
+ uint8 data[] @end @as_ptr(data_size);
} @ctype(SpiceMsgPlaybackPacket) data = 101;
message {
uint32 time;
audio_data_mode mode;
- uint8 data[] @end;
+ uint8 data[] @end @as_ptr(data_size);
} mode;
message {
@@ -952,13 +952,13 @@ channel RecordChannel : BaseChannel {
client:
message {
uint32 time;
- uint8 data[] @end @nomarshal;
+ uint8 data[] @end @nomarshal @as_ptr(data_size);
} @ctype(SpiceMsgcRecordPacket) data = 101;
message {
uint32 time;
audio_data_mode mode;
- uint8 data[] @end;
+ uint8 data[] @end @as_ptr(data_size);
} mode;
message {
commit 4ce4364f84a1b458b715f4c5fa83ea20fd26f749
Author: Alexander Larsson <alexl at redhat.com>
Date: Fri Jun 18 17:12:07 2010 +0200
Make ping data @as_ptr to avoid copying data
diff --git a/common/messages.h b/common/messages.h
index 2ba14bf..e317949 100644
--- a/common/messages.h
+++ b/common/messages.h
@@ -150,6 +150,8 @@ typedef struct SpiceMsgMainMouseMode {
typedef struct SpiceMsgPing {
uint32_t id;
uint64_t timestamp;
+ void *data;
+ uint32_t data_len;
} SpiceMsgPing;
typedef struct SpiceMsgMainAgentDisconnect {
diff --git a/spice.proto b/spice.proto
index 6750d2d..bad9ed3 100644
--- a/spice.proto
+++ b/spice.proto
@@ -111,7 +111,7 @@ channel BaseChannel {
message {
uint32 id;
uint64 timestamp;
- uint8 data[] @end @ctype(uint8_t);
+ uint8 data[] @end @ctype(uint8_t) @as_ptr(data_len);
} ping;
message {
commit 3c8cb83af5cbe85e6ab41ec1c0b41c5a29230d9e
Author: Alexander Larsson <alexl at redhat.com>
Date: Fri Jun 18 17:11:39 2010 +0200
Make cursor data @as_ptr to avoid copying data
diff --git a/client/cursor_channel.cpp b/client/cursor_channel.cpp
index 26eb4c8..c973e9d 100644
--- a/client/cursor_channel.cpp
+++ b/client/cursor_channel.cpp
@@ -485,7 +485,7 @@ void CursorChannel::create_native_cursor(CursorData* cursor)
cursor->set_opaque(native_cursor);
}
-void CursorChannel::set_cursor(SpiceCursor& red_cursor, int data_size, int x, int y, bool visible)
+void CursorChannel::set_cursor(SpiceCursor& red_cursor, int x, int y, bool visible)
{
CursorData *cursor;
@@ -497,7 +497,7 @@ void CursorChannel::set_cursor(SpiceCursor& red_cursor, int data_size, int x, in
if (red_cursor.flags & SPICE_CURSOR_FLAGS_FROM_CACHE) {
cursor = _cursor_cache.get(red_cursor.header.unique);
} else {
- cursor = new CursorData(red_cursor, data_size);
+ cursor = new CursorData(red_cursor, red_cursor.data_size);
if (red_cursor.flags & SPICE_CURSOR_FLAGS_CACHE_ME) {
ASSERT(red_cursor.header.unique);
_cursor_cache.add(red_cursor.header.unique, cursor);
@@ -560,7 +560,7 @@ void CursorChannel::handle_init(RedPeer::InMessage *message)
attach_to_screen(get_client().get_application(), get_id());
remove_cursor();
_cursor_cache.clear();
- set_cursor(init->cursor, message->size() - sizeof(SpiceMsgCursorInit), init->position.x,
+ set_cursor(init->cursor, init->position.x,
init->position.y, init->visible != 0);
}
@@ -574,7 +574,7 @@ void CursorChannel::handle_reset(RedPeer::InMessage *message)
void CursorChannel::handle_cursor_set(RedPeer::InMessage* message)
{
SpiceMsgCursorSet* set = (SpiceMsgCursorSet*)message->data();
- set_cursor(set->cursor, message->size() - sizeof(SpiceMsgCursorSet), set->position.x,
+ set_cursor(set->cursor, set->position.x,
set->position.y, set->visible != 0);
}
diff --git a/client/cursor_channel.h b/client/cursor_channel.h
index 3d6218f..c9e32b4 100644
--- a/client/cursor_channel.h
+++ b/client/cursor_channel.h
@@ -63,7 +63,7 @@ private:
static void create_native_cursor(CursorData* cursor);
void update_display_cursor();
- void set_cursor(SpiceCursor& red_cursor, int data_size, int x, int y, bool visible);
+ void set_cursor(SpiceCursor& red_cursor, int x, int y, bool visible);
void remove_cursor();
virtual void copy_pixels(const QRegion& dest_region, RedDrawable& dest_dc);
diff --git a/common/messages.h b/common/messages.h
index f6c2aeb..2ba14bf 100644
--- a/common/messages.h
+++ b/common/messages.h
@@ -173,7 +173,8 @@ typedef struct SpiceMsgcMainMouseModeRequest {
typedef struct SpiceCursor {
uint32_t flags;
SpiceCursorHeader header;
- uint8_t data[0];
+ uint32_t data_size;
+ uint8_t *data;
} SpiceCursor;
typedef struct SpiceMsgDisplayMode {
diff --git a/spice.proto b/spice.proto
index 093c808..6750d2d 100644
--- a/spice.proto
+++ b/spice.proto
@@ -867,7 +867,7 @@ struct CursorHeader {
struct Cursor {
cursor_flags flags;
CursorHeader header;
- uint8 data[] @end;
+ uint8 data[] @end @as_ptr(data_size);
};
channel CursorChannel : BaseChannel {
commit 7fa29ea67e5202d4a3f6678445cef9bcad54aa79
Author: Alexander Larsson <alexl at redhat.com>
Date: Fri Jun 18 17:09:58 2010 +0200
Support @as_ptr in demarshaller to avoid copying data unnecessary
diff --git a/python_modules/demarshal.py b/python_modules/demarshal.py
index fcd6850..8b90458 100644
--- a/python_modules/demarshal.py
+++ b/python_modules/demarshal.py
@@ -760,7 +760,19 @@ def write_member_parser(writer, container, member, dest, scope):
#TODO validate e.g. flags and enums
elif t.is_array():
nelements = read_array_len(writer, member.name, t, dest, scope, handles_bytes = True)
- write_array_parser(writer, nelements, t, dest, scope)
+ if member.has_attr("as_ptr") and t.element_type.is_fixed_nw_size():
+ writer.comment("use array as pointer").newline()
+ writer.assign(dest.get_ref(member.name), "(%s *)in" % t.element_type.c_type())
+ len_var = member.attributes["as_ptr"]
+ if len(len_var) > 0:
+ writer.assign(dest.get_ref(len_var[0]), nelements)
+ el_size = t.element_type.get_fixed_nw_size()
+ if el_size != 1:
+ writer.increment("in", "%s * %s" % (nelements, el_size))
+ else:
+ writer.increment("in", "%s" % (nelements))
+ else:
+ write_array_parser(writer, nelements, t, dest, scope)
elif t.is_struct():
if member.has_end_attr():
dest2 = dest.child_at_end(writer, t)
commit 0b82006733e2eba89c32ac4dfb35e6db49cfa992
Author: Alexander Larsson <alexl at redhat.com>
Date: Fri Jun 18 15:44:04 2010 +0200
Make pointer types in messages be 64bit in memory
Right now we always assume pointers are stored as SPICE_ADDRESS,
i.e. 64bit, independent on the size sent on the network.
This is required for 64bit architectures of course, but slightly overkill
on 32bit architectures, so needs fixing when all SPICE_ADDRESS elements
can be made internal.
diff --git a/common/messages.h b/common/messages.h
index cf9523e..f6c2aeb 100644
--- a/common/messages.h
+++ b/common/messages.h
@@ -442,8 +442,8 @@ typedef struct SpiceMsgcTunnelAddGenericService {
uint32_t id;
uint32_t group;
uint32_t port;
- uint32_t name;
- uint32_t description;
+ uint64_t name;
+ uint64_t description;
} SpiceMsgcTunnelAddGenericService;
typedef struct SpiceMsgcTunnelAddPrintService {
commit 3a07edb4afa00dd897a3b9f07c9b5c10f5b39b8e
Author: Alexander Larsson <alexl at redhat.com>
Date: Fri Jun 18 15:10:57 2010 +0200
Don't pack the message structures
diff --git a/common/messages.h b/common/messages.h
index 7f6fe07..cf9523e 100644
--- a/common/messages.h
+++ b/common/messages.h
@@ -33,29 +33,27 @@
#include <spice/protocol.h>
-#include <spice/start-packed.h>
-
-typedef struct SPICE_ATTR_PACKED SpiceMsgData {
+typedef struct SpiceMsgData {
uint32_t data_size;
uint8_t data[0];
} SpiceMsgData;
-typedef struct SPICE_ATTR_PACKED SpiceMsgEmpty {
+typedef struct SpiceMsgEmpty {
} SpiceMsgEmpty;
-typedef struct SPICE_ATTR_PACKED SpiceMsgInputsInit {
+typedef struct SpiceMsgInputsInit {
uint32_t keyboard_modifiers;
} SpiceMsgInputsInit;
-typedef struct SPICE_ATTR_PACKED SpiceMsgInputsKeyModifiers {
+typedef struct SpiceMsgInputsKeyModifiers {
uint32_t modifiers;
} SpiceMsgInputsKeyModifiers;
-typedef struct SPICE_ATTR_PACKED SpiceMsgMainMultiMediaTime {
+typedef struct SpiceMsgMainMultiMediaTime {
uint32_t time;
} SpiceMsgMainMultiMediaTime;
-typedef struct SPICE_ATTR_PACKED SpiceMsgMainMigrationBegin {
+typedef struct SpiceMsgMainMigrationBegin {
uint16_t port;
uint16_t sport;
uint32_t host_offset;
@@ -65,7 +63,7 @@ typedef struct SPICE_ATTR_PACKED SpiceMsgMainMigrationBegin {
uint32_t pub_key_size;
} SpiceMsgMainMigrationBegin;
-typedef struct SPICE_ATTR_PACKED SpiceMsgMainMigrationSwitchHost {
+typedef struct SpiceMsgMainMigrationSwitchHost {
uint16_t port;
uint16_t sport;
uint32_t host_offset;
@@ -75,46 +73,46 @@ typedef struct SPICE_ATTR_PACKED SpiceMsgMainMigrationSwitchHost {
} SpiceMsgMainMigrationSwitchHost;
-typedef struct SPICE_ATTR_PACKED SpiceMsgMigrate {
+typedef struct SpiceMsgMigrate {
uint32_t flags;
} SpiceMsgMigrate;
-typedef struct SPICE_ATTR_PACKED SpiceResourceID {
+typedef struct SpiceResourceID {
uint8_t type;
uint64_t id;
} SpiceResourceID;
-typedef struct SPICE_ATTR_PACKED SpiceResourceList {
+typedef struct SpiceResourceList {
uint16_t count;
SpiceResourceID resources[0];
} SpiceResourceList;
-typedef struct SPICE_ATTR_PACKED SpiceMsgSetAck {
+typedef struct SpiceMsgSetAck {
uint32_t generation;
uint32_t window;
} SpiceMsgSetAck;
-typedef struct SPICE_ATTR_PACKED SpiceMsgcAckSync {
+typedef struct SpiceMsgcAckSync {
uint32_t generation;
} SpiceMsgcAckSync;
-typedef struct SPICE_ATTR_PACKED SpiceWaitForChannel {
+typedef struct SpiceWaitForChannel {
uint8_t channel_type;
uint8_t channel_id;
uint64_t message_serial;
} SpiceWaitForChannel;
-typedef struct SPICE_ATTR_PACKED SpiceMsgWaitForChannels {
+typedef struct SpiceMsgWaitForChannels {
uint8_t wait_count;
SpiceWaitForChannel wait_list[0];
} SpiceMsgWaitForChannels;
-typedef struct SPICE_ATTR_PACKED SpiceChannelId {
+typedef struct SpiceChannelId {
uint8_t type;
uint8_t id;
} SpiceChannelId;
-typedef struct SPICE_ATTR_PACKED SpiceMsgMainInit {
+typedef struct SpiceMsgMainInit {
uint32_t session_id;
uint32_t display_channels_hint;
uint32_t supported_mouse_modes;
@@ -125,12 +123,12 @@ typedef struct SPICE_ATTR_PACKED SpiceMsgMainInit {
uint32_t ram_hint;
} SpiceMsgMainInit;
-typedef struct SPICE_ATTR_PACKED SpiceMsgDisconnect {
+typedef struct SpiceMsgDisconnect {
uint64_t time_stamp;
uint32_t reason; // SPICE_ERR_?
} SpiceMsgDisconnect;
-typedef struct SPICE_ATTR_PACKED SpiceMsgNotify {
+typedef struct SpiceMsgNotify {
uint64_t time_stamp;
uint32_t severity;
uint32_t visibilty;
@@ -139,52 +137,52 @@ typedef struct SPICE_ATTR_PACKED SpiceMsgNotify {
uint8_t message[0];
} SpiceMsgNotify;
-typedef struct SPICE_ATTR_PACKED SpiceMsgChannels {
+typedef struct SpiceMsgChannels {
uint32_t num_of_channels;
SpiceChannelId channels[0];
} SpiceMsgChannels;
-typedef struct SPICE_ATTR_PACKED SpiceMsgMainMouseMode {
+typedef struct SpiceMsgMainMouseMode {
uint32_t supported_modes;
uint32_t current_mode;
} SpiceMsgMainMouseMode;
-typedef struct SPICE_ATTR_PACKED SpiceMsgPing {
+typedef struct SpiceMsgPing {
uint32_t id;
uint64_t timestamp;
} SpiceMsgPing;
-typedef struct SPICE_ATTR_PACKED SpiceMsgMainAgentDisconnect {
+typedef struct SpiceMsgMainAgentDisconnect {
uint32_t error_code; // SPICE_ERR_?
} SpiceMsgMainAgentDisconnect;
#define SPICE_AGENT_MAX_DATA_SIZE 2048
-typedef struct SPICE_ATTR_PACKED SpiceMsgMainAgentTokens {
+typedef struct SpiceMsgMainAgentTokens {
uint32_t num_tokens;
} SpiceMsgMainAgentTokens, SpiceMsgcMainAgentTokens, SpiceMsgcMainAgentStart;
-typedef struct SPICE_ATTR_PACKED SpiceMsgcClientInfo {
+typedef struct SpiceMsgcClientInfo {
uint64_t cache_size;
} SpiceMsgcClientInfo;
-typedef struct SPICE_ATTR_PACKED SpiceMsgcMainMouseModeRequest {
+typedef struct SpiceMsgcMainMouseModeRequest {
uint32_t mode;
} SpiceMsgcMainMouseModeRequest;
-typedef struct SPICE_ATTR_PACKED SpiceCursor {
+typedef struct SpiceCursor {
uint32_t flags;
SpiceCursorHeader header;
uint8_t data[0];
} SpiceCursor;
-typedef struct SPICE_ATTR_PACKED SpiceMsgDisplayMode {
+typedef struct SpiceMsgDisplayMode {
uint32_t x_res;
uint32_t y_res;
uint32_t bits;
} SpiceMsgDisplayMode;
-typedef struct SPICE_ATTR_PACKED SpiceMsgSurfaceCreate {
+typedef struct SpiceMsgSurfaceCreate {
uint32_t surface_id;
uint32_t width;
uint32_t height;
@@ -192,83 +190,83 @@ typedef struct SPICE_ATTR_PACKED SpiceMsgSurfaceCreate {
uint32_t flags;
} SpiceMsgSurfaceCreate;
-typedef struct SPICE_ATTR_PACKED SpiceMsgSurfaceDestroy {
+typedef struct SpiceMsgSurfaceDestroy {
uint32_t surface_id;
} SpiceMsgSurfaceDestroy;
-typedef struct SPICE_ATTR_PACKED SpiceMsgDisplayBase {
+typedef struct SpiceMsgDisplayBase {
uint32_t surface_id;
SpiceRect box;
SpiceClip clip;
} SpiceMsgDisplayBase;
-typedef struct SPICE_ATTR_PACKED SpiceMsgDisplayDrawFill {
+typedef struct SpiceMsgDisplayDrawFill {
SpiceMsgDisplayBase base;
SpiceFill data;
} SpiceMsgDisplayDrawFill;
-typedef struct SPICE_ATTR_PACKED SpiceMsgDisplayDrawOpaque {
+typedef struct SpiceMsgDisplayDrawOpaque {
SpiceMsgDisplayBase base;
SpiceOpaque data;
} SpiceMsgDisplayDrawOpaque;
-typedef struct SPICE_ATTR_PACKED SpiceMsgDisplayDrawCopy {
+typedef struct SpiceMsgDisplayDrawCopy {
SpiceMsgDisplayBase base;
SpiceCopy data;
} SpiceMsgDisplayDrawCopy;
-typedef struct SPICE_ATTR_PACKED SpiceMsgDisplayDrawTransparent {
+typedef struct SpiceMsgDisplayDrawTransparent {
SpiceMsgDisplayBase base;
SpiceTransparent data;
} SpiceMsgDisplayDrawTransparent;
-typedef struct SPICE_ATTR_PACKED SpiceMsgDisplayDrawAlphaBlend {
+typedef struct SpiceMsgDisplayDrawAlphaBlend {
SpiceMsgDisplayBase base;
SpiceAlphaBlnd data;
} SpiceMsgDisplayDrawAlphaBlend;
-typedef struct SPICE_ATTR_PACKED SpiceMsgDisplayCopyBits {
+typedef struct SpiceMsgDisplayCopyBits {
SpiceMsgDisplayBase base;
SpicePoint src_pos;
} SpiceMsgDisplayCopyBits;
typedef SpiceMsgDisplayDrawCopy SpiceMsgDisplayDrawBlend;
-typedef struct SPICE_ATTR_PACKED SpiceMsgDisplayDrawRop3 {
+typedef struct SpiceMsgDisplayDrawRop3 {
SpiceMsgDisplayBase base;
SpiceRop3 data;
} SpiceMsgDisplayDrawRop3;
-typedef struct SPICE_ATTR_PACKED SpiceMsgDisplayDrawBlackness {
+typedef struct SpiceMsgDisplayDrawBlackness {
SpiceMsgDisplayBase base;
SpiceBlackness data;
} SpiceMsgDisplayDrawBlackness;
-typedef struct SPICE_ATTR_PACKED SpiceMsgDisplayDrawWhiteness {
+typedef struct SpiceMsgDisplayDrawWhiteness {
SpiceMsgDisplayBase base;
SpiceWhiteness data;
} SpiceMsgDisplayDrawWhiteness;
-typedef struct SPICE_ATTR_PACKED SpiceMsgDisplayDrawInvers {
+typedef struct SpiceMsgDisplayDrawInvers {
SpiceMsgDisplayBase base;
SpiceInvers data;
} SpiceMsgDisplayDrawInvers;
-typedef struct SPICE_ATTR_PACKED SpiceMsgDisplayDrawStroke {
+typedef struct SpiceMsgDisplayDrawStroke {
SpiceMsgDisplayBase base;
SpiceStroke data;
} SpiceMsgDisplayDrawStroke;
-typedef struct SPICE_ATTR_PACKED SpiceMsgDisplayDrawText {
+typedef struct SpiceMsgDisplayDrawText {
SpiceMsgDisplayBase base;
SpiceText data;
} SpiceMsgDisplayDrawText;
-typedef struct SPICE_ATTR_PACKED SpiceMsgDisplayInvalOne {
+typedef struct SpiceMsgDisplayInvalOne {
uint64_t id;
} SpiceMsgDisplayInvalOne;
-typedef struct SPICE_ATTR_PACKED SpiceMsgDisplayStreamCreate {
+typedef struct SpiceMsgDisplayStreamCreate {
uint32_t surface_id;
uint32_t id;
uint32_t flags;
@@ -282,7 +280,7 @@ typedef struct SPICE_ATTR_PACKED SpiceMsgDisplayStreamCreate {
SpiceClip clip;
} SpiceMsgDisplayStreamCreate;
-typedef struct SPICE_ATTR_PACKED SpiceMsgDisplayStreamData {
+typedef struct SpiceMsgDisplayStreamData {
uint32_t id;
uint32_t multi_media_time;
uint32_t data_size;
@@ -290,16 +288,16 @@ typedef struct SPICE_ATTR_PACKED SpiceMsgDisplayStreamData {
uint8_t data[0];
} SpiceMsgDisplayStreamData;
-typedef struct SPICE_ATTR_PACKED SpiceMsgDisplayStreamClip {
+typedef struct SpiceMsgDisplayStreamClip {
uint32_t id;
SpiceClip clip;
} SpiceMsgDisplayStreamClip;
-typedef struct SPICE_ATTR_PACKED SpiceMsgDisplayStreamDestroy {
+typedef struct SpiceMsgDisplayStreamDestroy {
uint32_t id;
} SpiceMsgDisplayStreamDestroy;
-typedef struct SPICE_ATTR_PACKED SpiceMsgCursorInit {
+typedef struct SpiceMsgCursorInit {
SpicePoint16 position;
uint16_t trail_length;
uint16_t trail_frequency;
@@ -307,109 +305,109 @@ typedef struct SPICE_ATTR_PACKED SpiceMsgCursorInit {
SpiceCursor cursor;
} SpiceMsgCursorInit;
-typedef struct SPICE_ATTR_PACKED SpiceMsgCursorSet {
+typedef struct SpiceMsgCursorSet {
SpicePoint16 position;
uint8_t visible;
SpiceCursor cursor;
} SpiceMsgCursorSet;
-typedef struct SPICE_ATTR_PACKED SpiceMsgCursorMove {
+typedef struct SpiceMsgCursorMove {
SpicePoint16 position;
} SpiceMsgCursorMove;
-typedef struct SPICE_ATTR_PACKED SpiceMsgCursorTrail {
+typedef struct SpiceMsgCursorTrail {
uint16_t length;
uint16_t frequency;
} SpiceMsgCursorTrail;
-typedef struct SPICE_ATTR_PACKED SpiceMsgcDisplayInit {
+typedef struct SpiceMsgcDisplayInit {
uint8_t pixmap_cache_id;
int64_t pixmap_cache_size; //in pixels
uint8_t glz_dictionary_id;
int32_t glz_dictionary_window_size; // in pixels
} SpiceMsgcDisplayInit;
-typedef struct SPICE_ATTR_PACKED SpiceMsgcKeyDown {
+typedef struct SpiceMsgcKeyDown {
uint32_t code;
} SpiceMsgcKeyDown;
-typedef struct SPICE_ATTR_PACKED SpiceMsgcKeyUp {
+typedef struct SpiceMsgcKeyUp {
uint32_t code;
} SpiceMsgcKeyUp;
-typedef struct SPICE_ATTR_PACKED SpiceMsgcKeyModifiers {
+typedef struct SpiceMsgcKeyModifiers {
uint32_t modifiers;
} SpiceMsgcKeyModifiers;
-typedef struct SPICE_ATTR_PACKED SpiceMsgcMouseMotion {
+typedef struct SpiceMsgcMouseMotion {
int32_t dx;
int32_t dy;
uint32_t buttons_state;
} SpiceMsgcMouseMotion;
-typedef struct SPICE_ATTR_PACKED SpiceMsgcMousePosition {
+typedef struct SpiceMsgcMousePosition {
uint32_t x;
uint32_t y;
uint32_t buttons_state;
uint8_t display_id;
} SpiceMsgcMousePosition;
-typedef struct SPICE_ATTR_PACKED SpiceMsgcMousePress {
+typedef struct SpiceMsgcMousePress {
int32_t button;
int32_t buttons_state;
} SpiceMsgcMousePress;
-typedef struct SPICE_ATTR_PACKED SpiceMsgcMouseRelease {
+typedef struct SpiceMsgcMouseRelease {
int32_t button;
int32_t buttons_state;
} SpiceMsgcMouseRelease;
-typedef struct SPICE_ATTR_PACKED SpiceMsgPlaybackMode {
+typedef struct SpiceMsgPlaybackMode {
uint32_t time;
uint32_t mode; //SPICE_AUDIO_DATA_MODE_?
uint8_t data[0];
} SpiceMsgPlaybackMode, SpiceMsgcRecordMode;
-typedef struct SPICE_ATTR_PACKED SpiceMsgPlaybackStart {
+typedef struct SpiceMsgPlaybackStart {
uint32_t channels;
uint32_t format; //SPICE_AUDIO_FMT_?
uint32_t frequency;
uint32_t time;
} SpiceMsgPlaybackStart;
-typedef struct SPICE_ATTR_PACKED SpiceMsgPlaybackPacket {
+typedef struct SpiceMsgPlaybackPacket {
uint32_t time;
uint8_t data[0];
} SpiceMsgPlaybackPacket, SpiceMsgcRecordPacket;
-typedef struct SPICE_ATTR_PACKED SpiceMsgRecordStart {
+typedef struct SpiceMsgRecordStart {
uint32_t channels;
uint32_t format; //SPICE_AUDIO_FMT_?
uint32_t frequency;
} SpiceMsgRecordStart;
-typedef struct SPICE_ATTR_PACKED SpiceMsgcRecordStartMark {
+typedef struct SpiceMsgcRecordStartMark {
uint32_t time;
} SpiceMsgcRecordStartMark;
-typedef struct SPICE_ATTR_PACKED SpiceMsgTunnelInit {
+typedef struct SpiceMsgTunnelInit {
uint16_t max_num_of_sockets;
uint32_t max_socket_data_size;
} SpiceMsgTunnelInit;
-typedef struct SPICE_ATTR_PACKED SpiceMsgTunnelIpInfo {
+typedef struct SpiceMsgTunnelIpInfo {
uint16_t type;
uint8_t data[0];
} SpiceMsgTunnelIpInfo;
typedef uint8_t SpiceTunnelIPv4[4];
-typedef struct SPICE_ATTR_PACKED SpiceMsgTunnelServiceIpMap {
+typedef struct SpiceMsgTunnelServiceIpMap {
uint32_t service_id;
SpiceMsgTunnelIpInfo virtual_ip;
} SpiceMsgTunnelServiceIpMap;
-typedef struct SPICE_ATTR_PACKED SpiceMsgTunnelSocketOpen {
+typedef struct SpiceMsgTunnelSocketOpen {
uint16_t connection_id;
uint32_t service_id;
uint32_t tokens;
@@ -417,29 +415,29 @@ typedef struct SPICE_ATTR_PACKED SpiceMsgTunnelSocketOpen {
/* connection id must be the first field in msgs directed to a specific connection */
-typedef struct SPICE_ATTR_PACKED SpiceMsgTunnelSocketFin {
+typedef struct SpiceMsgTunnelSocketFin {
uint16_t connection_id;
} SpiceMsgTunnelSocketFin;
-typedef struct SPICE_ATTR_PACKED SpiceMsgTunnelSocketClose {
+typedef struct SpiceMsgTunnelSocketClose {
uint16_t connection_id;
} SpiceMsgTunnelSocketClose;
-typedef struct SPICE_ATTR_PACKED SpiceMsgTunnelSocketData {
+typedef struct SpiceMsgTunnelSocketData {
uint16_t connection_id;
uint8_t data[0];
} SpiceMsgTunnelSocketData;
-typedef struct SPICE_ATTR_PACKED SpiceMsgTunnelSocketTokens {
+typedef struct SpiceMsgTunnelSocketTokens {
uint16_t connection_id;
uint32_t num_tokens;
} SpiceMsgTunnelSocketTokens;
-typedef struct SPICE_ATTR_PACKED SpiceMsgTunnelSocketClosedAck {
+typedef struct SpiceMsgTunnelSocketClosedAck {
uint16_t connection_id;
} SpiceMsgTunnelSocketClosedAck;
-typedef struct SPICE_ATTR_PACKED SpiceMsgcTunnelAddGenericService {
+typedef struct SpiceMsgcTunnelAddGenericService {
uint32_t type;
uint32_t id;
uint32_t group;
@@ -448,50 +446,48 @@ typedef struct SPICE_ATTR_PACKED SpiceMsgcTunnelAddGenericService {
uint32_t description;
} SpiceMsgcTunnelAddGenericService;
-typedef struct SPICE_ATTR_PACKED SpiceMsgcTunnelAddPrintService {
+typedef struct SpiceMsgcTunnelAddPrintService {
SpiceMsgcTunnelAddGenericService base;
SpiceMsgTunnelIpInfo ip;
} SpiceMsgcTunnelAddPrintService;
-typedef struct SPICE_ATTR_PACKED SpiceMsgcTunnelRemoveService {
+typedef struct SpiceMsgcTunnelRemoveService {
uint32_t id;
} SpiceMsgcTunnelRemoveService;
/* connection id must be the first field in msgs directed to a specific connection */
-typedef struct SPICE_ATTR_PACKED SpiceMsgcTunnelSocketOpenAck {
+typedef struct SpiceMsgcTunnelSocketOpenAck {
uint16_t connection_id;
uint32_t tokens;
} SpiceMsgcTunnelSocketOpenAck;
-typedef struct SPICE_ATTR_PACKED SpiceMsgcTunnelSocketOpenNack {
+typedef struct SpiceMsgcTunnelSocketOpenNack {
uint16_t connection_id;
} SpiceMsgcTunnelSocketOpenNack;
-typedef struct SPICE_ATTR_PACKED SpiceMsgcTunnelSocketData {
+typedef struct SpiceMsgcTunnelSocketData {
uint16_t connection_id;
uint8_t data[0];
} SpiceMsgcTunnelSocketData;
-typedef struct SPICE_ATTR_PACKED SpiceMsgcTunnelSocketFin {
+typedef struct SpiceMsgcTunnelSocketFin {
uint16_t connection_id;
} SpiceMsgcTunnelSocketFin;
-typedef struct SPICE_ATTR_PACKED SpiceMsgcTunnelSocketClosed {
+typedef struct SpiceMsgcTunnelSocketClosed {
uint16_t connection_id;
} SpiceMsgcTunnelSocketClosed;
-typedef struct SPICE_ATTR_PACKED SpiceMsgcTunnelSocketClosedAck {
+typedef struct SpiceMsgcTunnelSocketClosedAck {
uint16_t connection_id;
} SpiceMsgcTunnelSocketClosedAck;
-typedef struct SPICE_ATTR_PACKED SpiceMsgcTunnelSocketTokens {
+typedef struct SpiceMsgcTunnelSocketTokens {
uint16_t connection_id;
uint32_t num_tokens;
} SpiceMsgcTunnelSocketTokens;
-#include <spice/end-packed.h>
-
#endif /* _H_SPICE_PROTOCOL */
commit 4c1094acce7a062d28fc2c7c45b2e0357105c7bf
Author: Alexander Larsson <alexl at redhat.com>
Date: Fri Jun 18 14:05:59 2010 +0200
Make all message structs internal to spice
We move all message structs from spice-protocol to spice as
we want to be able to change these as needed internally. The
on-network format is no longer defined by these structures anyway,
but rather by the spice protocol description.
diff --git a/client/Makefile.am b/client/Makefile.am
index f140203..86d7c3e 100644
--- a/client/Makefile.am
+++ b/client/Makefile.am
@@ -6,11 +6,11 @@ DIST_SUBDIRS = x11 #windows
spice_built_sources = generated_demarshallers.cpp generated_marshallers.cpp generated_marshallers.h
generated_demarshallers.cpp: $(top_srcdir)/spice.proto
- $(PYTHON) $(top_srcdir)/spice_codegen.py --generate-demarshallers --client --include common.h $(top_srcdir)/spice.proto generated_demarshallers.cpp
+ $(PYTHON) $(top_srcdir)/spice_codegen.py --generate-demarshallers --client --include common.h --include messages.h $(top_srcdir)/spice.proto generated_demarshallers.cpp
STRUCTS=
generated_marshallers.cpp: $(top_srcdir)/spice.proto
- $(PYTHON) $(top_srcdir)/spice_codegen.py --generate-marshallers $(STRUCTS) --client $(top_srcdir)/spice.proto generated_marshallers.cpp
+ $(PYTHON) $(top_srcdir)/spice_codegen.py --generate-marshallers $(STRUCTS) --include messages.h --client $(top_srcdir)/spice.proto generated_marshallers.cpp
generated_marshallers.h: $(top_srcdir)/spice.proto
$(PYTHON) $(top_srcdir)/spice_codegen.py --generate-marshallers $(STRUCTS) --client -H $(top_srcdir)/spice.proto generated_marshallers.h
diff --git a/client/canvas.h b/client/canvas.h
index c988a52..ff70e11 100644
--- a/client/canvas.h
+++ b/client/canvas.h
@@ -22,7 +22,7 @@
#include "common.h"
#include "debug.h"
#include "region.h"
-#include <spice/protocol.h>
+#include "messages.h"
#include "cache.hpp"
#include "shared_cache.hpp"
#include "canvas_base.h"
diff --git a/client/cursor.h b/client/cursor.h
index a756543..f5084cd 100644
--- a/client/cursor.h
+++ b/client/cursor.h
@@ -19,7 +19,7 @@
#define _H_CURSOR_
#include "threads.h"
-#include <spice/protocol.h>
+#include "messages.h"
#include "red_window_p.h"
class CursorOpaque {
diff --git a/client/red_client.h b/client/red_client.h
index 51c1780..1b81328 100644
--- a/client/red_client.h
+++ b/client/red_client.h
@@ -27,7 +27,7 @@
#include "inputs_channel.h"
#include "cursor_channel.h"
#include "audio_channels.h"
-#include <spice/protocol.h>
+#include "messages.h"
#include <spice/vd_agent.h>
#include "process_loop.h"
diff --git a/common/messages.h b/common/messages.h
new file mode 100644
index 0000000..7f6fe07
--- /dev/null
+++ b/common/messages.h
@@ -0,0 +1,497 @@
+/*
+ Copyright (C) 2009-2010 Red Hat, Inc.
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions are
+ met:
+
+ * Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in
+ the documentation and/or other materials provided with the
+ distribution.
+ * Neither the name of the copyright holder nor the names of its
+ contributors may be used to endorse or promote products derived
+ from this software without specific prior written permission.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER AND CONTRIBUTORS "AS
+ IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
+ PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+#ifndef _H_MESSAGES
+#define _H_MESSAGES
+
+#include <spice/protocol.h>
+
+#include <spice/start-packed.h>
+
+typedef struct SPICE_ATTR_PACKED SpiceMsgData {
+ uint32_t data_size;
+ uint8_t data[0];
+} SpiceMsgData;
+
+typedef struct SPICE_ATTR_PACKED SpiceMsgEmpty {
+} SpiceMsgEmpty;
+
+typedef struct SPICE_ATTR_PACKED SpiceMsgInputsInit {
+ uint32_t keyboard_modifiers;
+} SpiceMsgInputsInit;
+
+typedef struct SPICE_ATTR_PACKED SpiceMsgInputsKeyModifiers {
+ uint32_t modifiers;
+} SpiceMsgInputsKeyModifiers;
+
+typedef struct SPICE_ATTR_PACKED SpiceMsgMainMultiMediaTime {
+ uint32_t time;
+} SpiceMsgMainMultiMediaTime;
+
+typedef struct SPICE_ATTR_PACKED SpiceMsgMainMigrationBegin {
+ uint16_t port;
+ uint16_t sport;
+ uint32_t host_offset;
+ uint32_t host_size;
+ uint16_t pub_key_type;
+ uint32_t pub_key_offset;
+ uint32_t pub_key_size;
+} SpiceMsgMainMigrationBegin;
+
+typedef struct SPICE_ATTR_PACKED SpiceMsgMainMigrationSwitchHost {
+ uint16_t port;
+ uint16_t sport;
+ uint32_t host_offset;
+ uint32_t host_size;
+ uint32_t cert_subject_offset;
+ uint32_t cert_subject_size;
+} SpiceMsgMainMigrationSwitchHost;
+
+
+typedef struct SPICE_ATTR_PACKED SpiceMsgMigrate {
+ uint32_t flags;
+} SpiceMsgMigrate;
+
+typedef struct SPICE_ATTR_PACKED SpiceResourceID {
+ uint8_t type;
+ uint64_t id;
+} SpiceResourceID;
+
+typedef struct SPICE_ATTR_PACKED SpiceResourceList {
+ uint16_t count;
+ SpiceResourceID resources[0];
+} SpiceResourceList;
+
+typedef struct SPICE_ATTR_PACKED SpiceMsgSetAck {
+ uint32_t generation;
+ uint32_t window;
+} SpiceMsgSetAck;
+
+typedef struct SPICE_ATTR_PACKED SpiceMsgcAckSync {
+ uint32_t generation;
+} SpiceMsgcAckSync;
+
+typedef struct SPICE_ATTR_PACKED SpiceWaitForChannel {
+ uint8_t channel_type;
+ uint8_t channel_id;
+ uint64_t message_serial;
+} SpiceWaitForChannel;
+
+typedef struct SPICE_ATTR_PACKED SpiceMsgWaitForChannels {
+ uint8_t wait_count;
+ SpiceWaitForChannel wait_list[0];
+} SpiceMsgWaitForChannels;
+
+typedef struct SPICE_ATTR_PACKED SpiceChannelId {
+ uint8_t type;
+ uint8_t id;
+} SpiceChannelId;
+
+typedef struct SPICE_ATTR_PACKED SpiceMsgMainInit {
+ uint32_t session_id;
+ uint32_t display_channels_hint;
+ uint32_t supported_mouse_modes;
+ uint32_t current_mouse_mode;
+ uint32_t agent_connected;
+ uint32_t agent_tokens;
+ uint32_t multi_media_time;
+ uint32_t ram_hint;
+} SpiceMsgMainInit;
+
+typedef struct SPICE_ATTR_PACKED SpiceMsgDisconnect {
+ uint64_t time_stamp;
+ uint32_t reason; // SPICE_ERR_?
+} SpiceMsgDisconnect;
+
+typedef struct SPICE_ATTR_PACKED SpiceMsgNotify {
+ uint64_t time_stamp;
+ uint32_t severity;
+ uint32_t visibilty;
+ uint32_t what;
+ uint32_t message_len;
+ uint8_t message[0];
+} SpiceMsgNotify;
+
+typedef struct SPICE_ATTR_PACKED SpiceMsgChannels {
+ uint32_t num_of_channels;
+ SpiceChannelId channels[0];
+} SpiceMsgChannels;
+
+typedef struct SPICE_ATTR_PACKED SpiceMsgMainMouseMode {
+ uint32_t supported_modes;
+ uint32_t current_mode;
+} SpiceMsgMainMouseMode;
+
+typedef struct SPICE_ATTR_PACKED SpiceMsgPing {
+ uint32_t id;
+ uint64_t timestamp;
+} SpiceMsgPing;
+
+typedef struct SPICE_ATTR_PACKED SpiceMsgMainAgentDisconnect {
+ uint32_t error_code; // SPICE_ERR_?
+} SpiceMsgMainAgentDisconnect;
+
+#define SPICE_AGENT_MAX_DATA_SIZE 2048
+
+typedef struct SPICE_ATTR_PACKED SpiceMsgMainAgentTokens {
+ uint32_t num_tokens;
+} SpiceMsgMainAgentTokens, SpiceMsgcMainAgentTokens, SpiceMsgcMainAgentStart;
+
+typedef struct SPICE_ATTR_PACKED SpiceMsgcClientInfo {
+ uint64_t cache_size;
+} SpiceMsgcClientInfo;
+
+typedef struct SPICE_ATTR_PACKED SpiceMsgcMainMouseModeRequest {
+ uint32_t mode;
+} SpiceMsgcMainMouseModeRequest;
+
+typedef struct SPICE_ATTR_PACKED SpiceCursor {
+ uint32_t flags;
+ SpiceCursorHeader header;
+ uint8_t data[0];
+} SpiceCursor;
+
+typedef struct SPICE_ATTR_PACKED SpiceMsgDisplayMode {
+ uint32_t x_res;
+ uint32_t y_res;
+ uint32_t bits;
+} SpiceMsgDisplayMode;
+
+typedef struct SPICE_ATTR_PACKED SpiceMsgSurfaceCreate {
+ uint32_t surface_id;
+ uint32_t width;
+ uint32_t height;
+ uint32_t format;
+ uint32_t flags;
+} SpiceMsgSurfaceCreate;
+
+typedef struct SPICE_ATTR_PACKED SpiceMsgSurfaceDestroy {
+ uint32_t surface_id;
+} SpiceMsgSurfaceDestroy;
+
+typedef struct SPICE_ATTR_PACKED SpiceMsgDisplayBase {
+ uint32_t surface_id;
+ SpiceRect box;
+ SpiceClip clip;
+} SpiceMsgDisplayBase;
+
+typedef struct SPICE_ATTR_PACKED SpiceMsgDisplayDrawFill {
+ SpiceMsgDisplayBase base;
+ SpiceFill data;
+} SpiceMsgDisplayDrawFill;
+
+typedef struct SPICE_ATTR_PACKED SpiceMsgDisplayDrawOpaque {
+ SpiceMsgDisplayBase base;
+ SpiceOpaque data;
+} SpiceMsgDisplayDrawOpaque;
+
+typedef struct SPICE_ATTR_PACKED SpiceMsgDisplayDrawCopy {
+ SpiceMsgDisplayBase base;
+ SpiceCopy data;
+} SpiceMsgDisplayDrawCopy;
+
+typedef struct SPICE_ATTR_PACKED SpiceMsgDisplayDrawTransparent {
+ SpiceMsgDisplayBase base;
+ SpiceTransparent data;
+} SpiceMsgDisplayDrawTransparent;
+
+typedef struct SPICE_ATTR_PACKED SpiceMsgDisplayDrawAlphaBlend {
+ SpiceMsgDisplayBase base;
+ SpiceAlphaBlnd data;
+} SpiceMsgDisplayDrawAlphaBlend;
+
+typedef struct SPICE_ATTR_PACKED SpiceMsgDisplayCopyBits {
+ SpiceMsgDisplayBase base;
+ SpicePoint src_pos;
+} SpiceMsgDisplayCopyBits;
+
+typedef SpiceMsgDisplayDrawCopy SpiceMsgDisplayDrawBlend;
+
+typedef struct SPICE_ATTR_PACKED SpiceMsgDisplayDrawRop3 {
+ SpiceMsgDisplayBase base;
+ SpiceRop3 data;
+} SpiceMsgDisplayDrawRop3;
+
+typedef struct SPICE_ATTR_PACKED SpiceMsgDisplayDrawBlackness {
+ SpiceMsgDisplayBase base;
+ SpiceBlackness data;
+} SpiceMsgDisplayDrawBlackness;
+
+typedef struct SPICE_ATTR_PACKED SpiceMsgDisplayDrawWhiteness {
+ SpiceMsgDisplayBase base;
+ SpiceWhiteness data;
+} SpiceMsgDisplayDrawWhiteness;
+
+typedef struct SPICE_ATTR_PACKED SpiceMsgDisplayDrawInvers {
+ SpiceMsgDisplayBase base;
+ SpiceInvers data;
+} SpiceMsgDisplayDrawInvers;
+
+typedef struct SPICE_ATTR_PACKED SpiceMsgDisplayDrawStroke {
+ SpiceMsgDisplayBase base;
+ SpiceStroke data;
+} SpiceMsgDisplayDrawStroke;
+
+typedef struct SPICE_ATTR_PACKED SpiceMsgDisplayDrawText {
+ SpiceMsgDisplayBase base;
+ SpiceText data;
+} SpiceMsgDisplayDrawText;
+
+typedef struct SPICE_ATTR_PACKED SpiceMsgDisplayInvalOne {
+ uint64_t id;
+} SpiceMsgDisplayInvalOne;
+
+typedef struct SPICE_ATTR_PACKED SpiceMsgDisplayStreamCreate {
+ uint32_t surface_id;
+ uint32_t id;
+ uint32_t flags;
+ uint32_t codec_type;
+ uint64_t stamp;
+ uint32_t stream_width;
+ uint32_t stream_height;
+ uint32_t src_width;
+ uint32_t src_height;
+ SpiceRect dest;
+ SpiceClip clip;
+} SpiceMsgDisplayStreamCreate;
+
+typedef struct SPICE_ATTR_PACKED SpiceMsgDisplayStreamData {
+ uint32_t id;
+ uint32_t multi_media_time;
+ uint32_t data_size;
+ uint32_t pad_size;
+ uint8_t data[0];
+} SpiceMsgDisplayStreamData;
+
+typedef struct SPICE_ATTR_PACKED SpiceMsgDisplayStreamClip {
+ uint32_t id;
+ SpiceClip clip;
+} SpiceMsgDisplayStreamClip;
+
+typedef struct SPICE_ATTR_PACKED SpiceMsgDisplayStreamDestroy {
+ uint32_t id;
+} SpiceMsgDisplayStreamDestroy;
+
+typedef struct SPICE_ATTR_PACKED SpiceMsgCursorInit {
+ SpicePoint16 position;
+ uint16_t trail_length;
+ uint16_t trail_frequency;
+ uint8_t visible;
+ SpiceCursor cursor;
+} SpiceMsgCursorInit;
+
+typedef struct SPICE_ATTR_PACKED SpiceMsgCursorSet {
+ SpicePoint16 position;
+ uint8_t visible;
+ SpiceCursor cursor;
+} SpiceMsgCursorSet;
+
+typedef struct SPICE_ATTR_PACKED SpiceMsgCursorMove {
+ SpicePoint16 position;
+} SpiceMsgCursorMove;
+
+typedef struct SPICE_ATTR_PACKED SpiceMsgCursorTrail {
+ uint16_t length;
+ uint16_t frequency;
+} SpiceMsgCursorTrail;
+
+typedef struct SPICE_ATTR_PACKED SpiceMsgcDisplayInit {
+ uint8_t pixmap_cache_id;
+ int64_t pixmap_cache_size; //in pixels
+ uint8_t glz_dictionary_id;
+ int32_t glz_dictionary_window_size; // in pixels
+} SpiceMsgcDisplayInit;
+
+typedef struct SPICE_ATTR_PACKED SpiceMsgcKeyDown {
+ uint32_t code;
+} SpiceMsgcKeyDown;
+
+typedef struct SPICE_ATTR_PACKED SpiceMsgcKeyUp {
+ uint32_t code;
+} SpiceMsgcKeyUp;
+
+typedef struct SPICE_ATTR_PACKED SpiceMsgcKeyModifiers {
+ uint32_t modifiers;
+} SpiceMsgcKeyModifiers;
+
+typedef struct SPICE_ATTR_PACKED SpiceMsgcMouseMotion {
+ int32_t dx;
+ int32_t dy;
+ uint32_t buttons_state;
+} SpiceMsgcMouseMotion;
+
+typedef struct SPICE_ATTR_PACKED SpiceMsgcMousePosition {
+ uint32_t x;
+ uint32_t y;
+ uint32_t buttons_state;
+ uint8_t display_id;
+} SpiceMsgcMousePosition;
+
+typedef struct SPICE_ATTR_PACKED SpiceMsgcMousePress {
+ int32_t button;
+ int32_t buttons_state;
+} SpiceMsgcMousePress;
+
+typedef struct SPICE_ATTR_PACKED SpiceMsgcMouseRelease {
+ int32_t button;
+ int32_t buttons_state;
+} SpiceMsgcMouseRelease;
+
+typedef struct SPICE_ATTR_PACKED SpiceMsgPlaybackMode {
+ uint32_t time;
+ uint32_t mode; //SPICE_AUDIO_DATA_MODE_?
+ uint8_t data[0];
+} SpiceMsgPlaybackMode, SpiceMsgcRecordMode;
+
+typedef struct SPICE_ATTR_PACKED SpiceMsgPlaybackStart {
+ uint32_t channels;
+ uint32_t format; //SPICE_AUDIO_FMT_?
+ uint32_t frequency;
+ uint32_t time;
+} SpiceMsgPlaybackStart;
+
+typedef struct SPICE_ATTR_PACKED SpiceMsgPlaybackPacket {
+ uint32_t time;
+ uint8_t data[0];
+} SpiceMsgPlaybackPacket, SpiceMsgcRecordPacket;
+
+typedef struct SPICE_ATTR_PACKED SpiceMsgRecordStart {
+ uint32_t channels;
+ uint32_t format; //SPICE_AUDIO_FMT_?
+ uint32_t frequency;
+} SpiceMsgRecordStart;
+
+typedef struct SPICE_ATTR_PACKED SpiceMsgcRecordStartMark {
+ uint32_t time;
+} SpiceMsgcRecordStartMark;
+
+typedef struct SPICE_ATTR_PACKED SpiceMsgTunnelInit {
+ uint16_t max_num_of_sockets;
+ uint32_t max_socket_data_size;
+} SpiceMsgTunnelInit;
+
+typedef struct SPICE_ATTR_PACKED SpiceMsgTunnelIpInfo {
+ uint16_t type;
+ uint8_t data[0];
+} SpiceMsgTunnelIpInfo;
+
+typedef uint8_t SpiceTunnelIPv4[4];
+
+typedef struct SPICE_ATTR_PACKED SpiceMsgTunnelServiceIpMap {
+ uint32_t service_id;
+ SpiceMsgTunnelIpInfo virtual_ip;
+} SpiceMsgTunnelServiceIpMap;
+
+typedef struct SPICE_ATTR_PACKED SpiceMsgTunnelSocketOpen {
+ uint16_t connection_id;
+ uint32_t service_id;
+ uint32_t tokens;
+} SpiceMsgTunnelSocketOpen;
+
+/* connection id must be the first field in msgs directed to a specific connection */
+
+typedef struct SPICE_ATTR_PACKED SpiceMsgTunnelSocketFin {
+ uint16_t connection_id;
+} SpiceMsgTunnelSocketFin;
+
+typedef struct SPICE_ATTR_PACKED SpiceMsgTunnelSocketClose {
+ uint16_t connection_id;
+} SpiceMsgTunnelSocketClose;
+
+typedef struct SPICE_ATTR_PACKED SpiceMsgTunnelSocketData {
+ uint16_t connection_id;
+ uint8_t data[0];
+} SpiceMsgTunnelSocketData;
+
+typedef struct SPICE_ATTR_PACKED SpiceMsgTunnelSocketTokens {
+ uint16_t connection_id;
+ uint32_t num_tokens;
+} SpiceMsgTunnelSocketTokens;
+
+typedef struct SPICE_ATTR_PACKED SpiceMsgTunnelSocketClosedAck {
+ uint16_t connection_id;
+} SpiceMsgTunnelSocketClosedAck;
+
+typedef struct SPICE_ATTR_PACKED SpiceMsgcTunnelAddGenericService {
+ uint32_t type;
+ uint32_t id;
+ uint32_t group;
+ uint32_t port;
+ uint32_t name;
+ uint32_t description;
+} SpiceMsgcTunnelAddGenericService;
+
+typedef struct SPICE_ATTR_PACKED SpiceMsgcTunnelAddPrintService {
+ SpiceMsgcTunnelAddGenericService base;
+ SpiceMsgTunnelIpInfo ip;
+} SpiceMsgcTunnelAddPrintService;
+
+typedef struct SPICE_ATTR_PACKED SpiceMsgcTunnelRemoveService {
+ uint32_t id;
+} SpiceMsgcTunnelRemoveService;
+
+/* connection id must be the first field in msgs directed to a specific connection */
+
+typedef struct SPICE_ATTR_PACKED SpiceMsgcTunnelSocketOpenAck {
+ uint16_t connection_id;
+ uint32_t tokens;
+} SpiceMsgcTunnelSocketOpenAck;
+
+typedef struct SPICE_ATTR_PACKED SpiceMsgcTunnelSocketOpenNack {
+ uint16_t connection_id;
+} SpiceMsgcTunnelSocketOpenNack;
+
+typedef struct SPICE_ATTR_PACKED SpiceMsgcTunnelSocketData {
+ uint16_t connection_id;
+ uint8_t data[0];
+} SpiceMsgcTunnelSocketData;
+
+typedef struct SPICE_ATTR_PACKED SpiceMsgcTunnelSocketFin {
+ uint16_t connection_id;
+} SpiceMsgcTunnelSocketFin;
+
+typedef struct SPICE_ATTR_PACKED SpiceMsgcTunnelSocketClosed {
+ uint16_t connection_id;
+} SpiceMsgcTunnelSocketClosed;
+
+typedef struct SPICE_ATTR_PACKED SpiceMsgcTunnelSocketClosedAck {
+ uint16_t connection_id;
+} SpiceMsgcTunnelSocketClosedAck;
+
+typedef struct SPICE_ATTR_PACKED SpiceMsgcTunnelSocketTokens {
+ uint16_t connection_id;
+ uint32_t num_tokens;
+} SpiceMsgcTunnelSocketTokens;
+
+#include <spice/end-packed.h>
+
+#endif /* _H_SPICE_PROTOCOL */
+
+
diff --git a/server/Makefile.am b/server/Makefile.am
index 8d507a4..9a6ac88 100644
--- a/server/Makefile.am
+++ b/server/Makefile.am
@@ -25,7 +25,7 @@ generated_demarshallers.c: $(top_srcdir)/spice.proto
STRUCTS=-M String -M Rect -M Point -M DisplayBase -M Fill -M Opaque -M Copy -M Blend -M Blackness -M Whiteness -M Invers -M Rop3 -M Stroke -M Text -M Transparent -M AlphaBlnd -M PathSegment
generated_marshallers.c: $(top_srcdir)/spice.proto
- $(PYTHON) $(top_srcdir)/spice_codegen.py --generate-marshallers $(STRUCTS) --server $(top_srcdir)/spice.proto generated_marshallers.c
+ $(PYTHON) $(top_srcdir)/spice_codegen.py --include red_common.h --generate-marshallers $(STRUCTS) --server $(top_srcdir)/spice.proto generated_marshallers.c
generated_marshallers.h: $(top_srcdir)/spice.proto
$(PYTHON) $(top_srcdir)/spice_codegen.py --generate-marshallers $(STRUCTS) --server -H $(top_srcdir)/spice.proto generated_marshallers.h
diff --git a/server/red_common.h b/server/red_common.h
index 2df1a16..c863922 100644
--- a/server/red_common.h
+++ b/server/red_common.h
@@ -23,7 +23,7 @@
#include "spice.h"
#include "mem.h"
-#include <spice/protocol.h>
+#include <messages.h>
#include <spice/macros.h>
#define ASSERT(x) if (!(x)) { \
commit 185a320c9be85d07586e5d475c991770853fec77
Author: Alexander Larsson <alexl at redhat.com>
Date: Fri Jun 18 13:43:45 2010 +0200
Allow multiple --include args
diff --git a/spice_codegen.py b/spice_codegen.py
index 0e9551f..c8d0d5f 100755
--- a/spice_codegen.py
+++ b/spice_codegen.py
@@ -108,7 +108,7 @@ parser.add_option("-k", "--keep-identical-file",
action="store_true", dest="keep_identical_file", default=False,
help="Print errors")
parser.add_option("-i", "--include",
- dest="include", default=None, metavar="FILE",
+ action="append", dest="includes", metavar="FILE",
help="Include FILE in generated code")
(options, args) = parser.parse_args()
@@ -137,8 +137,9 @@ if options.assert_on_error:
if options.print_error:
writer.set_option("print_error")
-if options.include:
- writer.writeln('#include "%s"' % options.include)
+if options.includes:
+ for i in options.includes:
+ writer.writeln('#include "%s"' % i)
if options.generate_enums:
write_enums(writer)
commit c553fafe4b1c9db32ea3e83b314ff23dfd44f554
Author: Alexander Larsson <alexl at redhat.com>
Date: Fri Jun 18 10:22:57 2010 +0200
Use generated demarshallers in server
diff --git a/server/red_worker.c b/server/red_worker.c
index 8b40116..387861c 100644
--- a/server/red_worker.c
+++ b/server/red_worker.c
@@ -51,6 +51,7 @@
#include "jpeg_encoder.h"
#include "rect.h"
#include "marshaller.h"
+#include "demarshallers.h"
#include "generated_marshallers.h"
//#define COMPRESS_STAT
@@ -348,11 +349,12 @@ typedef struct RedChannel RedChannel;
typedef void (*disconnect_channel_proc)(RedChannel *channel);
typedef void (*hold_item_proc)(void *item);
typedef void (*release_item_proc)(RedChannel *channel, void *item);
-typedef int (*handle_message_proc)(RedChannel *channel, SpiceDataHeader *message);
+typedef int (*handle_message_proc)(RedChannel *channel, size_t size, uint32_t type, void *message);
struct RedChannel {
EventListener listener;
uint32_t id;
+ spice_parse_channel_func_t parser;
struct RedWorker *worker;
RedsStreamContext *peer;
int migrate;
@@ -9888,15 +9890,11 @@ static void on_new_display_channel(RedWorker *worker)
}
}
-static int channel_handle_message(RedChannel *channel, SpiceDataHeader *message)
+static int channel_handle_message(RedChannel *channel, size_t size, uint32_t type, void *message)
{
- switch (message->type) {
+ switch (type) {
case SPICE_MSGC_ACK_SYNC:
- if (message->size != sizeof(uint32_t)) {
- red_printf("bad message size");
- return FALSE;
- }
- channel->client_ack_generation = *(uint32_t *)(message + 1);
+ channel->client_ack_generation = *(uint32_t *)message;
break;
case SPICE_MSGC_ACK:
if (channel->client_ack_generation == channel->ack_generation) {
@@ -9906,7 +9904,7 @@ static int channel_handle_message(RedChannel *channel, SpiceDataHeader *message)
case SPICE_MSGC_DISCONNECTING:
break;
default:
- red_printf("invalid message type %u", message->type);
+ red_printf("invalid message type %u", type);
return FALSE;
}
return TRUE;
@@ -10146,7 +10144,7 @@ static int display_channel_handle_migrate_mark(DisplayChannel *channel)
return TRUE;
}
-static int display_channel_handle_migrate_data(DisplayChannel *channel, SpiceDataHeader *message)
+static int display_channel_handle_migrate_data(DisplayChannel *channel, size_t size, void *message)
{
DisplayChannelMigrateData *migrate_data;
int i;
@@ -10156,11 +10154,11 @@ static int display_channel_handle_migrate_data(DisplayChannel *channel, SpiceDat
return FALSE;
}
channel->expect_migrate_data = FALSE;
- if (message->size < sizeof(*migrate_data)) {
+ if (size < sizeof(*migrate_data)) {
red_printf("bad message size");
return FALSE;
}
- migrate_data = (DisplayChannelMigrateData *)(message + 1);
+ migrate_data = (DisplayChannelMigrateData *)message;
if (migrate_data->magic != DISPLAY_MIGRATE_DATA_MAGIC ||
migrate_data->version != DISPLAY_MIGRATE_DATA_VERSION) {
red_printf("invalid content");
@@ -10197,26 +10195,22 @@ static int display_channel_handle_migrate_data(DisplayChannel *channel, SpiceDat
return TRUE;
}
-static int display_channel_handle_message(RedChannel *channel, SpiceDataHeader *message)
+static int display_channel_handle_message(RedChannel *channel, size_t size, uint32_t type, void *message)
{
- switch (message->type) {
+ switch (type) {
case SPICE_MSGC_DISPLAY_INIT:
- if (message->size != sizeof(SpiceMsgcDisplayInit)) {
- red_printf("bad message size");
- return FALSE;
- }
if (!((DisplayChannel *)channel)->expect_init) {
red_printf("unexpected SPICE_MSGC_DISPLAY_INIT");
return FALSE;
}
((DisplayChannel *)channel)->expect_init = FALSE;
- return display_channel_init((DisplayChannel *)channel, (SpiceMsgcDisplayInit *)(message + 1));
+ return display_channel_init((DisplayChannel *)channel, (SpiceMsgcDisplayInit *)message);
case SPICE_MSGC_MIGRATE_FLUSH_MARK:
return display_channel_handle_migrate_mark((DisplayChannel *)channel);
case SPICE_MSGC_MIGRATE_DATA:
- return display_channel_handle_migrate_data((DisplayChannel *)channel, message);
+ return display_channel_handle_migrate_data((DisplayChannel *)channel, size, message);
default:
- return channel_handle_message(channel, message);
+ return channel_handle_message(channel, size, type, message);
}
}
@@ -10249,19 +10243,34 @@ static void red_receive(RedChannel *channel)
} else {
channel->recive_data.now += n;
for (;;) {
- SpiceDataHeader *message = channel->recive_data.message;
- n = channel->recive_data.now - (uint8_t *)message;
+ SpiceDataHeader *header = channel->recive_data.message;
+ uint8_t *data = (uint8_t *)(header+1);
+ size_t parsed_size;
+ uint8_t *parsed;
+
+ n = channel->recive_data.now - (uint8_t *)header;
if (n < sizeof(SpiceDataHeader) ||
- n < sizeof(SpiceDataHeader) + message->size) {
+ n < sizeof(SpiceDataHeader) + header->size) {
break;
}
- if (!channel->handle_message(channel, message)) {
+ parsed = channel->parser((void *)data, data + header->size, header->type,
+ SPICE_VERSION_MINOR, &parsed_size);
+
+ if (parsed == NULL) {
+ red_printf("failed to parse message type %d", header->type);
+ channel->disconnect(channel);
+ return;
+ }
+
+ if (!channel->handle_message(channel, parsed_size, header->type, parsed)) {
+ free(parsed);
channel->disconnect(channel);
return;
}
- channel->recive_data.message = (SpiceDataHeader *)((uint8_t *)message +
- sizeof(SpiceDataHeader) +
- message->size);
+ free(parsed);
+ channel->recive_data.message = (SpiceDataHeader *)((uint8_t *)header +
+ sizeof(SpiceDataHeader) +
+ header->size);
}
if (channel->recive_data.now == (uint8_t *)channel->recive_data.message) {
@@ -10276,7 +10285,8 @@ static void red_receive(RedChannel *channel)
}
}
-static RedChannel *__new_channel(RedWorker *worker, int size, RedsStreamContext *peer, int migrate,
+static RedChannel *__new_channel(RedWorker *worker, int size, uint32_t channel_id,
+ RedsStreamContext *peer, int migrate,
event_listener_action_proc handler,
disconnect_channel_proc disconnect,
hold_item_proc hold_item,
@@ -10306,6 +10316,7 @@ static RedChannel *__new_channel(RedWorker *worker, int size, RedsStreamContext
ASSERT(size >= sizeof(*channel));
channel = spice_malloc0(size);
channel->id = worker->id;
+ channel->parser = spice_get_client_channel_parser(channel_id, NULL);
channel->listener.refs = 1;
channel->listener.action = handler;
channel->disconnect = disconnect;
@@ -10408,7 +10419,8 @@ static void handle_new_display_channel(RedWorker *worker, RedsStreamContext *pee
red_disconnect_display((RedChannel *)worker->display_channel);
- if (!(display_channel = (DisplayChannel *)__new_channel(worker, sizeof(*display_channel), peer,
+ if (!(display_channel = (DisplayChannel *)__new_channel(worker, sizeof(*display_channel),
+ SPICE_CHANNEL_DISPLAY, peer,
migrate, handle_channel_events,
red_disconnect_display,
display_channel_hold_item,
@@ -10508,7 +10520,8 @@ static void red_connect_cursor(RedWorker *worker, RedsStreamContext *peer, int m
red_disconnect_cursor((RedChannel *)worker->cursor_channel);
- if (!(channel = (CursorChannel *)__new_channel(worker, sizeof(*channel), peer, migrate,
+ if (!(channel = (CursorChannel *)__new_channel(worker, sizeof(*channel),
+ SPICE_CHANNEL_CURSOR, peer, migrate,
handle_channel_events,
red_disconnect_cursor,
cursor_channel_hold_item,
diff --git a/server/reds.c b/server/reds.c
index fee1cbf..f9d91db 100644
--- a/server/reds.c
+++ b/server/reds.c
@@ -52,6 +52,7 @@
#include "stat.h"
#include "ring.h"
#include "config.h"
+#include "demarshallers.h"
#include "marshaller.h"
#include "generated_marshallers.h"
#ifdef HAVE_SLIRP
@@ -113,11 +114,12 @@ static void openssl_init();
#define CAPS_LOCK_SCAN_CODE 0x3a
typedef struct IncomingHandler {
+ spice_parse_channel_func_t parser;
void *opaque;
int shut;
uint8_t buf[RECIVE_BUF_SIZE];
uint32_t end_pos;
- void (*handle_message)(void *opaque, SpiceDataHeader *message);
+ void (*handle_message)(void *opaque, size_t size, uint32_t type, void *message);
} IncomingHandler;
typedef struct OutgoingHandler {
@@ -792,9 +794,19 @@ static int handle_incoming(RedsStreamContext *peer, IncomingHandler *handler)
end = buf + pos;
while (buf + sizeof(SpiceDataHeader) <= end &&
buf + sizeof(SpiceDataHeader) + (header = (SpiceDataHeader *)buf)->size <= end) {
- buf += sizeof(SpiceDataHeader) + header->size;
- handler->handle_message(handler->opaque, header);
+ uint8_t *data = (uint8_t *)(header+1);
+ size_t parsed_size;
+ uint8_t *parsed;
+ buf += sizeof(SpiceDataHeader) + header->size;
+ parsed = handler->parser(data, data + header->size, header->type,
+ SPICE_VERSION_MINOR, &parsed_size);
+ if (parsed == NULL) {
+ red_printf("failed to parse message type %d", header->type);
+ return -1;
+ }
+ handler->handle_message(handler->opaque, parsed_size, header->type, parsed);
+ free(parsed);
if (handler->shut) {
return -1;
}
@@ -1586,9 +1598,9 @@ static void main_channel_recive_migrate_data(MainMigrateData *data, uint8_t *end
ASSERT(state->num_client_tokens + state->num_tokens == REDS_AGENT_WINDOW_SIZE);
}
-static void reds_main_handle_message(void *opaque, SpiceDataHeader *message)
+static void reds_main_handle_message(void *opaque, size_t size, uint32_t type, void *message)
{
- switch (message->type) {
+ switch (type) {
case SPICE_MSGC_MAIN_AGENT_START: {
SpiceMsgcMainAgentTokens *agent_start;
@@ -1596,7 +1608,7 @@ static void reds_main_handle_message(void *opaque, SpiceDataHeader *message)
if (!reds->peer) {
return;
}
- agent_start = (SpiceMsgcMainAgentTokens *)(message + 1);
+ agent_start = (SpiceMsgcMainAgentTokens *)message;
reds->agent_state.client_agent_started = TRUE;
reds->agent_state.send_tokens = agent_start->num_tokens;
read_from_vdi_port();
@@ -1624,7 +1636,7 @@ static void reds_main_handle_message(void *opaque, SpiceDataHeader *message)
break;
}
- if (message->size > SPICE_AGENT_MAX_DATA_SIZE) {
+ if (size > SPICE_AGENT_MAX_DATA_SIZE) {
red_printf("invalid agent message");
reds_disconnect();
break;
@@ -1638,9 +1650,9 @@ static void reds_main_handle_message(void *opaque, SpiceDataHeader *message)
ring_remove(ring_item);
buf = (VDAgentExtBuf *)ring_item;
buf->base.now = (uint8_t *)&buf->base.chunk_header.port;
- buf->base.write_len = message->size + sizeof(VDIChunkHeader);
- buf->base.chunk_header.size = message->size;
- memcpy(buf->buf, message + 1, message->size);
+ buf->base.write_len = size + sizeof(VDIChunkHeader);
+ buf->base.chunk_header.size = size;
+ memcpy(buf->buf, message, size);
ring_add(&reds->agent_state.write_queue, ring_item);
write_to_vdi_port();
break;
@@ -1653,7 +1665,7 @@ static void reds_main_handle_message(void *opaque, SpiceDataHeader *message)
break;
}
- token = (SpiceMsgcMainAgentTokens *)(message + 1);
+ token = (SpiceMsgcMainAgentTokens *)message;
reds->agent_state.send_tokens += token->num_tokens;
read_from_vdi_port();
break;
@@ -1674,7 +1686,7 @@ static void reds_main_handle_message(void *opaque, SpiceDataHeader *message)
}
break;
case SPICE_MSGC_MAIN_MOUSE_MODE_REQUEST: {
- switch (((SpiceMsgcMainMouseModeRequest *)(message + 1))->mode) {
+ switch (((SpiceMsgcMainMouseModeRequest *)message)->mode) {
case SPICE_MOUSE_MODE_CLIENT:
if (reds->is_client_mouse_allowed) {
reds_set_mouse_mode(SPICE_MOUSE_MODE_CLIENT);
@@ -1691,7 +1703,7 @@ static void reds_main_handle_message(void *opaque, SpiceDataHeader *message)
break;
}
case SPICE_MSGC_PONG: {
- SpiceMsgPing *ping = (SpiceMsgPing *)(message + 1);
+ SpiceMsgPing *ping = (SpiceMsgPing *)message;
uint64_t roundtrip;
struct timespec ts;
@@ -1743,15 +1755,15 @@ static void reds_main_handle_message(void *opaque, SpiceDataHeader *message)
main_channel_push_migrate_data_item();
break;
case SPICE_MSGC_MIGRATE_DATA:
- main_channel_recive_migrate_data((MainMigrateData *)(message + 1),
- (uint8_t *)(message + 1) + message->size);
+ main_channel_recive_migrate_data((MainMigrateData *)message,
+ ((uint8_t *)message) + size);
reds->mig_target = FALSE;
while (write_to_vdi_port() || read_from_vdi_port());
break;
case SPICE_MSGC_DISCONNECTING:
break;
default:
- red_printf("unexpected type %d", message->type);
+ red_printf("unexpected type %d", type);
}
}
@@ -2058,12 +2070,12 @@ static uint8_t kbd_get_leds(SpiceKbdInstance *sin)
return sif->get_leds(sin);
}
-static void inputs_handle_input(void *opaque, SpiceDataHeader *header)
+static void inputs_handle_input(void *opaque, size_t size, uint32_t type, void *message)
{
InputsState *state = (InputsState *)opaque;
- uint8_t *buf = (uint8_t *)(header + 1);
+ uint8_t *buf = (uint8_t *)message;
- switch (header->type) {
+ switch (type) {
case SPICE_MSGC_INPUTS_KEY_DOWN: {
SpiceMsgcKeyDown *key_up = (SpiceMsgcKeyDown *)buf;
if (key_up->code == CAPS_LOCK_SCAN_CODE || key_up->code == NUM_LOCK_SCAN_CODE ||
@@ -2216,7 +2228,7 @@ static void inputs_handle_input(void *opaque, SpiceDataHeader *header)
case SPICE_MSGC_DISCONNECTING:
break;
default:
- red_printf("unexpected type %d", header->type);
+ red_printf("unexpected type %d", type);
}
}
@@ -2344,6 +2356,7 @@ static void inputs_link(Channel *channel, RedsStreamContext *peer, int migration
inputs_state->peer = peer;
inputs_state->end_pos = 0;
inputs_state->channel = channel;
+ inputs_state->in_handler.parser = spice_get_client_channel_parser(SPICE_CHANNEL_INPUTS, NULL);
inputs_state->in_handler.opaque = inputs_state;
inputs_state->in_handler.handle_message = inputs_handle_input;
inputs_state->out_handler.length = 0;
@@ -3571,6 +3584,7 @@ static void do_spice_init(SpiceCoreInterface *core_interface)
reds->listen_socket = -1;
reds->secure_listen_socket = -1;
reds->peer = NULL;
+ reds->in_handler.parser = spice_get_client_channel_parser(SPICE_CHANNEL_MAIN, NULL);
reds->in_handler.handle_message = reds_main_handle_message;
ring_init(&reds->outgoing.pipe);
reds->outgoing.vec = reds->outgoing.vec_buf;
diff --git a/server/snd_worker.c b/server/snd_worker.c
index cd9af97..544da3b 100644
--- a/server/snd_worker.c
+++ b/server/snd_worker.c
@@ -30,6 +30,7 @@
#include "snd_worker.h"
#include "marshaller.h"
#include "generated_marshallers.h"
+#include "demarshallers.h"
#define MAX_SEND_VEC 100
@@ -65,7 +66,7 @@ enum RecordCommand {
typedef struct SndChannel SndChannel;
typedef void (*send_messages_proc)(void *in_channel);
-typedef int (*handle_message_proc)(SndChannel *channel, SpiceDataHeader *message);
+typedef int (*handle_message_proc)(SndChannel *channel, size_t size, uint32_t type, void *message);
typedef void (*on_message_done_proc)(SndChannel *channel);
typedef void (*cleanup_channel_proc)(SndChannel *channel);
@@ -74,6 +75,7 @@ typedef struct SndWorker SndWorker;
struct SndChannel {
RedsStreamContext *peer;
SndWorker *worker;
+ spice_parse_channel_func_t parser;
int active;
int client_active;
@@ -266,12 +268,11 @@ static int snd_send_data(SndChannel *channel)
return TRUE;
}
-static int snd_record_handle_write(RecordChannel *record_channel, SpiceDataHeader *message)
+static int snd_record_handle_write(RecordChannel *record_channel, size_t size, void *message)
{
SpiceMsgcRecordPacket *packet;
uint32_t write_pos;
uint32_t* data;
- uint32_t size;
uint32_t len;
uint32_t now;
@@ -279,8 +280,8 @@ static int snd_record_handle_write(RecordChannel *record_channel, SpiceDataHeade
return FALSE;
}
- packet = (SpiceMsgcRecordPacket *)(message + 1);
- size = message->size - sizeof(*packet);
+ packet = (SpiceMsgcRecordPacket *)message;
+ size = size - sizeof(*packet);
if (record_channel->mode == SPICE_AUDIO_DATA_MODE_CELT_0_5_1) {
int celt_err = celt051_decode(record_channel->celt_decoder, packet->data, size,
@@ -316,34 +317,34 @@ static int snd_record_handle_write(RecordChannel *record_channel, SpiceDataHeade
return TRUE;
}
-static int snd_playback_handle_message(SndChannel *channel, SpiceDataHeader *message)
+static int snd_playback_handle_message(SndChannel *channel, size_t size, uint32_t type, void *message)
{
if (!channel) {
return FALSE;
}
- switch (message->type) {
+ switch (type) {
case SPICE_MSGC_DISCONNECTING:
break;
default:
- red_printf("invalid message type %u", message->type);
+ red_printf("invalid message type %u", type);
return FALSE;
}
return TRUE;
}
-static int snd_record_handle_message(SndChannel *channel, SpiceDataHeader *message)
+static int snd_record_handle_message(SndChannel *channel, size_t size, uint32_t type, void *message)
{
RecordChannel *record_channel = (RecordChannel *)channel;
if (!channel) {
return FALSE;
}
- switch (message->type) {
+ switch (type) {
case SPICE_MSGC_RECORD_DATA:
- return snd_record_handle_write((RecordChannel *)channel, message);
+ return snd_record_handle_write((RecordChannel *)channel, size, message);
case SPICE_MSGC_RECORD_MODE: {
- SpiceMsgcRecordMode *mode = (SpiceMsgcRecordMode *)(message + 1);
+ SpiceMsgcRecordMode *mode = (SpiceMsgcRecordMode *)message;
record_channel->mode = mode->mode;
record_channel->mode_time = mode->time;
if (record_channel->mode != SPICE_AUDIO_DATA_MODE_CELT_0_5_1 &&
@@ -353,14 +354,14 @@ static int snd_record_handle_message(SndChannel *channel, SpiceDataHeader *messa
break;
}
case SPICE_MSGC_RECORD_START_MARK: {
- SpiceMsgcRecordStartMark *mark = (SpiceMsgcRecordStartMark *)(message + 1);
+ SpiceMsgcRecordStartMark *mark = (SpiceMsgcRecordStartMark *)message;
record_channel->start_time = mark->time;
break;
}
case SPICE_MSGC_DISCONNECTING:
break;
case SPICE_MSGC_MIGRATE_DATA: {
- RecordMigrateData* mig_data = (RecordMigrateData *)(message + 1);
+ RecordMigrateData* mig_data = (RecordMigrateData *)message;
if (mig_data->version != RECORD_MIG_VERSION) {
red_printf("invalid mig version");
break;
@@ -371,7 +372,7 @@ static int snd_record_handle_message(SndChannel *channel, SpiceDataHeader *messa
break;
}
default:
- red_printf("invalid message type %u", message->type);
+ red_printf("invalid message type %u", type);
return FALSE;
}
return TRUE;
@@ -410,18 +411,31 @@ static void snd_receive(void* data)
} else {
channel->recive_data.now += n;
for (;;) {
- SpiceDataHeader *message = channel->recive_data.message;
- n = channel->recive_data.now - (uint8_t *)message;
- if (n < sizeof(SpiceDataHeader) || n < sizeof(SpiceDataHeader) + message->size) {
+ SpiceDataHeader *header = channel->recive_data.message;
+ uint8_t *data = (uint8_t *)(header+1);
+ size_t parsed_size;
+ uint8_t *parsed;
+
+ n = channel->recive_data.now - (uint8_t *)header;
+ if (n < sizeof(SpiceDataHeader) || n < sizeof(SpiceDataHeader) + header->size) {
break;
}
- if (!channel->handle_message(channel, message)) {
+ parsed = channel->parser((void *)data, data + header->size, header->type,
+ SPICE_VERSION_MINOR, &parsed_size);
+ if (parsed == NULL) {
+ red_printf("failed to parse message type %d", header->type);
+ snd_disconnect_channel(channel);
+ return;
+ }
+ if (!channel->handle_message(channel, parsed_size, header->type, parsed)) {
+ free(parsed);
snd_disconnect_channel(channel);
return;
}
- channel->recive_data.message = (SpiceDataHeader *)((uint8_t *)message +
+ free(parsed);
+ channel->recive_data.message = (SpiceDataHeader *)((uint8_t *)header +
sizeof(SpiceDataHeader) +
- message->size);
+ header->size);
}
if (channel->recive_data.now == (uint8_t *)channel->recive_data.message) {
channel->recive_data.now = channel->recive_data.buf;
@@ -718,7 +732,8 @@ static void snd_record_send(void* data)
}
}
-static SndChannel *__new_channel(SndWorker *worker, int size, RedsStreamContext *peer,
+static SndChannel *__new_channel(SndWorker *worker, int size, uint32_t channel_id,
+ RedsStreamContext *peer,
int migrate, send_messages_proc send_messages,
handle_message_proc handle_message,
on_message_done_proc on_message_done,
@@ -758,6 +773,7 @@ static SndChannel *__new_channel(SndWorker *worker, int size, RedsStreamContext
ASSERT(size >= sizeof(*channel));
channel = spice_malloc0(size);
+ channel->parser = spice_get_client_channel_parser(channel_id, NULL);
channel->peer = peer;
channel->worker = worker;
channel->recive_data.message = (SpiceDataHeader *)channel->recive_data.buf;
@@ -941,6 +957,7 @@ static void snd_set_playback_peer(Channel *channel, RedsStreamContext *peer, int
if (!(playback_channel = (PlaybackChannel *)__new_channel(worker,
sizeof(*playback_channel),
+ SPICE_CHANNEL_PLAYBACK,
peer,
migration,
snd_playback_send,
@@ -1106,6 +1123,7 @@ static void snd_set_record_peer(Channel *channel, RedsStreamContext *peer, int m
if (!(record_channel = (RecordChannel *)__new_channel(worker,
sizeof(*record_channel),
+ SPICE_CHANNEL_RECORD,
peer,
migration,
snd_record_send,
commit ec10a1662fb8b7c0f9ba8c26c506028a6b21ee44
Author: Alexander Larsson <alexl at redhat.com>
Date: Thu Jun 17 11:20:22 2010 +0200
Generate demarshallers on server side
diff --git a/server/Makefile.am b/server/Makefile.am
index 7cd9218..8d507a4 100644
--- a/server/Makefile.am
+++ b/server/Makefile.am
@@ -18,7 +18,10 @@ INCLUDES = \
$(VISIBILITY_HIDDEN_CFLAGS) \
$(NULL)
-spice_built_sources = generated_marshallers.c generated_marshallers.h
+spice_built_sources = generated_marshallers.c generated_marshallers.h generated_demarshallers.c
+
+generated_demarshallers.c: $(top_srcdir)/spice.proto
+ $(PYTHON) $(top_srcdir)/spice_codegen.py --generate-demarshallers --server --include red_common.h $(top_srcdir)/spice.proto generated_demarshallers.c
STRUCTS=-M String -M Rect -M Point -M DisplayBase -M Fill -M Opaque -M Copy -M Blend -M Blackness -M Whiteness -M Invers -M Rop3 -M Stroke -M Text -M Transparent -M AlphaBlnd -M PathSegment
generated_marshallers.c: $(top_srcdir)/spice.proto
@@ -99,6 +102,7 @@ libspice_server_la_SOURCES = \
red_channel.c \
spice.h \
spice-experimental.h \
+ generated_demarshallers.c \
generated_marshallers.c \
generated_marshallers.h \
$(TUNNEL_SRCS) \
commit 4e44b7cf95421ebdf9890653cf7b110fad340f3a
Author: Alexander Larsson <alexl at redhat.com>
Date: Thu Jun 17 11:19:31 2010 +0200
Make tunnel_service_add members be of cstring array size
diff --git a/spice.proto b/spice.proto
index d41137f..093c808 100644
--- a/spice.proto
+++ b/spice.proto
@@ -1031,8 +1031,8 @@ channel TunnelChannel : BaseChannel {
uint32 id;
uint32 group;
uint32 port;
- uint8 *name[] @ptr32;
- uint8 *description[] @ptr32;
+ uint8 *name[cstring()] @ptr32 @nocopy;
+ uint8 *description[cstring()] @ptr32 @nocopy;
switch (type) {
case IPP:
TunnelIpInfo ip @ctype(SpiceMsgTunnelIpInfo);
commit ee91ed475dc5b9ea8f5ee05faa3dd153306e3471
Author: Alexander Larsson <alexl at redhat.com>
Date: Thu Jun 17 10:15:15 2010 +0200
Switch client to use generated marshallers
diff --git a/client/Makefile.am b/client/Makefile.am
index fa7dbb6..f140203 100644
--- a/client/Makefile.am
+++ b/client/Makefile.am
@@ -36,6 +36,7 @@ RED_COMMON_SRCS = \
common.h \
demarshallers.h \
generated_demarshallers.cpp \
+ marshaller.cpp \
generated_marshallers.cpp \
generated_marshallers.h \
cursor_channel.cpp \
diff --git a/client/display_channel.cpp b/client/display_channel.cpp
index 9cc5550..5286aed 100644
--- a/client/display_channel.cpp
+++ b/client/display_channel.cpp
@@ -42,6 +42,7 @@
#include "inputs_channel.h"
#include "cursor_channel.h"
#include "mjpeg_decoder.h"
+#include "generated_marshallers.h"
class CreatePrimarySurfaceEvent: public SyncEvent {
public:
@@ -1022,12 +1023,13 @@ private:
void DisplayChannel::on_connect()
{
- Message* message = new Message(SPICE_MSGC_DISPLAY_INIT, sizeof(SpiceMsgcDisplayInit));
- SpiceMsgcDisplayInit* init = (SpiceMsgcDisplayInit*)message->data();
- init->pixmap_cache_id = 1;
- init->pixmap_cache_size = get_client().get_pixmap_cache_size();
- init->glz_dictionary_id = 1;
- init->glz_dictionary_window_size = get_client().get_glz_window_size();
+ Message* message = new Message(SPICE_MSGC_DISPLAY_INIT);
+ SpiceMsgcDisplayInit init;
+ init.pixmap_cache_id = 1;
+ init.pixmap_cache_size = get_client().get_pixmap_cache_size();
+ init.glz_dictionary_id = 1;
+ init.glz_dictionary_window_size = get_client().get_glz_window_size();
+ spice_marshall_msgc_display_init(message->marshaller(), &init);
post_message(message);
AutoRef<AttachChannelsEvent> attach_channels(new AttachChannelsEvent(*this));
get_client().push_event(*attach_channels);
diff --git a/client/inputs_channel.cpp b/client/inputs_channel.cpp
index 4e99563..6fd0b4f 100644
--- a/client/inputs_channel.cpp
+++ b/client/inputs_channel.cpp
@@ -22,6 +22,7 @@
#include "red_client.h"
#include "application.h"
#include "display_channel.h"
+#include "generated_marshallers.h"
#define SYNC_REMOTH_MODIFIRES
@@ -114,7 +115,7 @@ private:
MotionMessage::MotionMessage(InputsChannel& channel)
: RedChannel::OutMessage()
- , RedPeer::OutMessage(SPICE_MSGC_INPUTS_MOUSE_MOTION, sizeof(SpiceMsgcMouseMotion))
+ , RedPeer::OutMessage(SPICE_MSGC_INPUTS_MOUSE_MOTION)
, _channel (channel)
{
}
@@ -126,7 +127,11 @@ void MotionMessage::release()
RedPeer::OutMessage& MotionMessage::peer_message()
{
- _channel.set_motion_event(*(SpiceMsgcMouseMotion*)data());
+ SpiceMsgcMouseMotion motion;
+
+ _channel.set_motion_event(motion);
+ spice_marshall_msgc_inputs_mouse_motion(_marshaller, &motion);
+
return *this;
}
@@ -142,7 +147,7 @@ private:
PositionMessage::PositionMessage(InputsChannel& channel)
: RedChannel::OutMessage()
- , RedPeer::OutMessage(SPICE_MSGC_INPUTS_MOUSE_POSITION, sizeof(SpiceMsgcMousePosition))
+ , RedPeer::OutMessage(SPICE_MSGC_INPUTS_MOUSE_POSITION)
, _channel (channel)
{
}
@@ -154,7 +159,9 @@ void PositionMessage::release()
RedPeer::OutMessage& PositionMessage::peer_message()
{
- _channel.set_position_event(*(SpiceMsgcMousePosition*)data());
+ SpiceMsgcMousePosition pos;
+ _channel.set_position_event(pos);
+ spice_marshall_msgc_inputs_mouse_position(_marshaller, &pos);
return *this;
}
@@ -311,10 +318,12 @@ void InputsChannel::on_mouse_down(int button, int buttons_state)
{
Message* message;
- message = new Message(SPICE_MSGC_INPUTS_MOUSE_PRESS, sizeof(SpiceMsgcMouseRelease));
- SpiceMsgcMousePress* event = (SpiceMsgcMousePress*)message->data();
- event->button = button;
- event->buttons_state = buttons_state;
+ message = new Message(SPICE_MSGC_INPUTS_MOUSE_PRESS);
+ SpiceMsgcMousePress event;
+ event.button = button;
+ event.buttons_state = buttons_state;
+ spice_marshall_msgc_inputs_mouse_press(message->marshaller(), &event);
+
post_message(message);
}
@@ -322,10 +331,11 @@ void InputsChannel::on_mouse_up(int button, int buttons_state)
{
Message* message;
- message = new Message(SPICE_MSGC_INPUTS_MOUSE_RELEASE, sizeof(SpiceMsgcMouseRelease));
- SpiceMsgcMouseRelease* event = (SpiceMsgcMouseRelease*)message->data();
- event->button = button;
- event->buttons_state = buttons_state;
+ message = new Message(SPICE_MSGC_INPUTS_MOUSE_RELEASE);
+ SpiceMsgcMouseRelease event;
+ event.button = button;
+ event.buttons_state = buttons_state;
+ spice_marshall_msgc_inputs_mouse_release(message->marshaller(), &event);
post_message(message);
}
@@ -349,9 +359,11 @@ void InputsChannel::on_key_down(RedKey key)
return;
}
- Message* message = new Message(SPICE_MSGC_INPUTS_KEY_DOWN, sizeof(SpiceMsgcKeyDown));
- SpiceMsgcKeyDown* event = (SpiceMsgcKeyDown*)message->data();
- event->code = scan_code;
+ Message* message = new Message(SPICE_MSGC_INPUTS_KEY_DOWN);
+ SpiceMsgcKeyDown event;
+ event.code = scan_code;
+ spice_marshall_msgc_inputs_key_down(message->marshaller(), &event);
+
post_message(message);
}
@@ -363,9 +375,10 @@ void InputsChannel::on_key_up(RedKey key)
return;
}
- Message* message = new Message(SPICE_MSGC_INPUTS_KEY_UP, sizeof(SpiceMsgcKeyUp));
- SpiceMsgcKeyUp* event = (SpiceMsgcKeyUp*)message->data();
- event->code = scan_code;
+ Message* message = new Message(SPICE_MSGC_INPUTS_KEY_UP);
+ SpiceMsgcKeyUp event;
+ event.code = scan_code;
+ spice_marshall_msgc_inputs_key_up(message->marshaller(), &event);
post_message(message);
}
@@ -391,9 +404,10 @@ void InputsChannel::set_local_modifiers()
void InputsChannel::on_focus_in()
{
#ifdef SYNC_REMOTH_MODIFIRES
- Message* message = new Message(SPICE_MSGC_INPUTS_KEY_MODIFIERS, sizeof(SpiceMsgcKeyDown));
- SpiceMsgcKeyModifiers* modifiers = (SpiceMsgcKeyModifiers*)message->data();
- modifiers->modifiers = Platform::get_keyboard_lock_modifiers();
+ Message* message = new Message(SPICE_MSGC_INPUTS_KEY_MODIFIERS);
+ SpiceMsgcKeyModifiers modifiers;
+ modifiers.modifiers = Platform::get_keyboard_lock_modifiers();
+ spice_marshall_msgc_inputs_key_modifiers(message->marshaller(), &modifiers);
post_message(message);
#else
set_local_modifiers();
diff --git a/client/record_channel.cpp b/client/record_channel.cpp
index a48df60..155e8d9 100644
--- a/client/record_channel.cpp
+++ b/client/record_channel.cpp
@@ -19,6 +19,7 @@
#include "red_client.h"
#include "audio_channels.h"
#include "audio_devices.h"
+#include "generated_marshallers.h"
#define NUM_SAMPLES_MESSAGES 4
@@ -33,23 +34,23 @@ public:
RecordSamplesMessage(RecordChannel& channel);
virtual ~RecordSamplesMessage();
- virtual RedPeer::OutMessage& peer_message() { return *_massage;}
+ virtual RedPeer::OutMessage& peer_message() { return *_message;}
virtual void release();
private:
RecordChannel& _channel;
- RedPeer::OutMessage *_massage;
+ RedPeer::OutMessage *_message;
};
RecordSamplesMessage::RecordSamplesMessage(RecordChannel& channel)
: _channel (channel)
- , _massage (new Message(SPICE_MSGC_RECORD_DATA, sizeof(SpiceMsgcRecordPacket) + 4096))
+ , _message (new Message(SPICE_MSGC_RECORD_DATA))
{
}
RecordSamplesMessage::~RecordSamplesMessage()
{
- delete _massage;
+ delete _message;
}
void RecordSamplesMessage::release()
@@ -115,19 +116,22 @@ bool RecordChannel::abort(void)
void RecordChannel::on_connect()
{
- Message* message = new Message(SPICE_MSGC_RECORD_MODE, sizeof(SpiceMsgcRecordMode));
- SpiceMsgcRecordMode *mode = (SpiceMsgcRecordMode *)message->data();
- mode->time = get_mm_time();
- mode->mode = _mode = test_capability(SPICE_RECORD_CAP_CELT_0_5_1) ? RecordChannel::data_mode :
+ Message* message = new Message(SPICE_MSGC_RECORD_MODE);
+ SpiceMsgcRecordMode mode;
+ mode.time = get_mm_time();
+ mode.mode = _mode =
+ test_capability(SPICE_RECORD_CAP_CELT_0_5_1) ? RecordChannel::data_mode :
SPICE_AUDIO_DATA_MODE_RAW;
+ spice_marshall_msgc_record_mode(message->marshaller(), &mode);
post_message(message);
}
void RecordChannel::send_start_mark()
{
- Message* message = new Message(SPICE_MSGC_RECORD_START_MARK, sizeof(SpiceMsgcRecordStartMark));
- SpiceMsgcRecordStartMark *start_mark = (SpiceMsgcRecordStartMark *)message->data();
- start_mark->time = get_mm_time();
+ Message* message = new Message(SPICE_MSGC_RECORD_START_MARK);
+ SpiceMsgcRecordStartMark start_mark;
+ start_mark.time = get_mm_time();
+ spice_marshall_msgc_record_start_mark(message->marshaller(), &start_mark);
post_message(message);
}
@@ -253,10 +257,11 @@ void RecordChannel::push_frame(uint8_t *frame)
n = _frame_bytes;
}
RedPeer::OutMessage& peer_message = message->peer_message();
- peer_message.resize(n + sizeof(SpiceMsgcRecordPacket));
- SpiceMsgcRecordPacket* packet = (SpiceMsgcRecordPacket*)peer_message.data();
- packet->time = get_mm_time();
- memcpy(packet->data, frame, n);
+ peer_message.reset(SPICE_MSGC_RECORD_DATA);
+ SpiceMsgcRecordPacket packet;
+ packet.time = get_mm_time();
+ spice_marshall_msgc_record_data(peer_message.marshaller(), &packet);
+ spice_marshaller_add(peer_message.marshaller(), frame, n);
post_message(message);
}
diff --git a/client/red_channel.cpp b/client/red_channel.cpp
index 475cec4..7065b0a 100644
--- a/client/red_channel.cpp
+++ b/client/red_channel.cpp
@@ -21,6 +21,7 @@
#include "application.h"
#include "debug.h"
#include "utils.h"
+#include "generated_marshallers.h"
#include "openssl/rsa.h"
#include "openssl/evp.h"
@@ -507,7 +508,7 @@ void RedChannel::on_send_trigger()
void RedChannel::on_message_recived()
{
if (_message_ack_count && !--_message_ack_count) {
- post_message(new Message(SPICE_MSGC_ACK, 0));
+ post_message(new Message(SPICE_MSGC_ACK));
_message_ack_count = _message_ack_window;
}
}
@@ -547,8 +548,8 @@ void RedChannel::on_event()
{
if (_outgoing_message) {
RedPeer::OutMessage& peer_message = _outgoing_message->peer_message();
- _outgoing_pos += send(peer_message.base() + _outgoing_pos,
- peer_message.message_size() - _outgoing_pos);
+
+ _outgoing_pos += do_send(peer_message, _outgoing_pos);
if (_outgoing_pos == peer_message.message_size()) {
_outgoing_message->release();
_outgoing_message = NULL;
@@ -592,7 +593,7 @@ void RedChannel::send_migrate_flush_mark()
{
if (_outgoing_message) {
RedPeer::OutMessage& peer_message = _outgoing_message->peer_message();
- send(peer_message.base() + _outgoing_pos, peer_message.message_size() - _outgoing_pos);
+ do_send(peer_message, _outgoing_pos);
_outgoing_message->release();
_outgoing_message = NULL;
}
@@ -605,7 +606,7 @@ void RedChannel::send_migrate_flush_mark()
send(message.get()->peer_message());
}
lock.unlock();
- std::auto_ptr<RedPeer::OutMessage> message(new RedPeer::OutMessage(SPICE_MSGC_MIGRATE_FLUSH_MARK, 0));
+ std::auto_ptr<RedPeer::OutMessage> message(new RedPeer::OutMessage(SPICE_MSGC_MIGRATE_FLUSH_MARK));
send(*message);
}
@@ -627,9 +628,8 @@ void RedChannel::handle_migrate(RedPeer::InMessage* message)
if ((*data_message)->type() != SPICE_MSG_MIGRATE_DATA) {
THROW("expect SPICE_MSG_MIGRATE_DATA");
}
- std::auto_ptr<RedPeer::OutMessage> message(new RedPeer::OutMessage(SPICE_MSGC_MIGRATE_DATA,
- (*data_message)->size()));
- memcpy(message->data(), (*data_message)->data(), (*data_message)->size());
+ std::auto_ptr<RedPeer::OutMessage> message(new RedPeer::OutMessage(SPICE_MSGC_MIGRATE_DATA));
+ spice_marshaller_add(message->marshaller(), (*data_message)->data(), (*data_message)->size());
send(*message);
}
_loop.add_socket(*this);
@@ -643,16 +643,18 @@ void RedChannel::handle_set_ack(RedPeer::InMessage* message)
{
SpiceMsgSetAck* ack = (SpiceMsgSetAck*)message->data();
_message_ack_window = _message_ack_count = ack->window;
- Message *responce = new Message(SPICE_MSGC_ACK_SYNC, sizeof(uint32_t));
- *(uint32_t *)responce->data() = ack->generation;
- post_message(responce);
+ Message *response = new Message(SPICE_MSGC_ACK_SYNC);
+ SpiceMsgcAckSync sync;
+ sync.generation = ack->generation;
+ spice_marshall_msgc_ack_sync(response->marshaller(), &sync);
+ post_message(response);
}
void RedChannel::handle_ping(RedPeer::InMessage* message)
{
SpiceMsgPing *ping = (SpiceMsgPing *)message->data();
- Message *pong = new Message(SPICE_MSGC_PONG, sizeof(SpiceMsgPing));
- *(SpiceMsgPing *)pong->data() = *ping;
+ Message *pong = new Message(SPICE_MSGC_PONG);
+ spice_marshall_msgc_pong(pong->marshaller(), ping);
post_message(pong);
}
diff --git a/client/red_channel.h b/client/red_channel.h
index 8d6b62f..a9d3ee5 100644
--- a/client/red_channel.h
+++ b/client/red_channel.h
@@ -212,9 +212,9 @@ public:
class Message: public RedChannel::OutMessage, public RedPeer::OutMessage {
public:
- Message(uint32_t type, uint32_t size)
+ Message(uint32_t type)
: RedChannel::OutMessage()
- , RedPeer::OutMessage(type, size)
+ , RedPeer::OutMessage(type)
{
}
diff --git a/client/red_client.cpp b/client/red_client.cpp
index 8778eeb..c079f3d 100644
--- a/client/red_client.cpp
+++ b/client/red_client.cpp
@@ -22,6 +22,7 @@
#include "process_loop.h"
#include "utils.h"
#include "debug.h"
+#include "generated_marshallers.h"
#ifdef __GNUC__
typedef struct __attribute__ ((__packed__)) OldRedMigrationBegin {
@@ -190,10 +191,10 @@ void Migrate::run()
Lock lock(_lock);
_cond.notify_one();
if (_connected) {
- Message* message = new Message(SPICE_MSGC_MAIN_MIGRATE_CONNECTED, 0);
+ Message* message = new Message(SPICE_MSGC_MAIN_MIGRATE_CONNECTED);
_client.post_message(message);
} else {
- Message* message = new Message(SPICE_MSGC_MAIN_MIGRATE_CONNECT_ERROR, 0);
+ Message* message = new Message(SPICE_MSGC_MAIN_MIGRATE_CONNECT_ERROR);
_client.post_message(message);
}
_running = false;
@@ -593,16 +594,17 @@ void RedClient::send_agent_monitors_config()
}
}
- Message* message = new Message(SPICE_MSGC_MAIN_AGENT_DATA,sizeof(VDAgentMessage) +
- sizeof(VDAgentMonitorsConfig) +
- monitors.size() * sizeof(VDAgentMonConfig));
- VDAgentMessage* msg = (VDAgentMessage*)message->data();
+ Message* message = new Message(SPICE_MSGC_MAIN_AGENT_DATA);
+ VDAgentMessage* msg = (VDAgentMessage*)
+ spice_marshaller_reserve_space(message->marshaller(), sizeof(VDAgentMessage));
msg->protocol = VD_AGENT_PROTOCOL;
msg->type = VD_AGENT_MONITORS_CONFIG;
msg->opaque = 0;
msg->size = sizeof(VDAgentMonitorsConfig) + monitors.size() * sizeof(VDAgentMonConfig);
- VDAgentMonitorsConfig* mon_config = (VDAgentMonitorsConfig*)msg->data;
+ VDAgentMonitorsConfig* mon_config = (VDAgentMonitorsConfig*)
+ spice_marshaller_reserve_space(message->marshaller(),
+ sizeof(VDAgentMonitorsConfig) + monitors.size() * sizeof(VDAgentMonConfig));
mon_config->num_of_monitors = monitors.size();
mon_config->flags = 0;
if (Platform::is_monitors_pos_valid()) {
@@ -696,9 +698,12 @@ void RedClient::set_mouse_mode(uint32_t supported_modes, uint32_t current_mode)
}
// FIXME: use configured mouse mode (currently, use client mouse mode if supported by server)
if ((supported_modes & SPICE_MOUSE_MODE_CLIENT) && (current_mode != SPICE_MOUSE_MODE_CLIENT)) {
- Message* message = new Message(SPICE_MSGC_MAIN_MOUSE_MODE_REQUEST, sizeof(SpiceMsgcMainMouseModeRequest));
- SpiceMsgcMainMouseModeRequest* mouse_mode_request = (SpiceMsgcMainMouseModeRequest*)message->data();
- mouse_mode_request->mode = SPICE_MOUSE_MODE_CLIENT;
+ Message* message = new Message(SPICE_MSGC_MAIN_MOUSE_MODE_REQUEST);
+ SpiceMsgcMainMouseModeRequest mouse_mode_request;
+ mouse_mode_request.mode = SPICE_MOUSE_MODE_CLIENT;
+ spice_marshall_msgc_main_mouse_mode_request(message->marshaller(),
+ &mouse_mode_request);
+
post_message(message);
}
}
@@ -714,9 +719,10 @@ void RedClient::handle_init(RedPeer::InMessage* message)
_agent_tokens = init->agent_tokens;
_agent_connected = !!init->agent_connected;
if (_agent_connected) {
- Message* msg = new Message(SPICE_MSGC_MAIN_AGENT_START, sizeof(SpiceMsgcMainAgentStart));
- SpiceMsgcMainAgentStart* agent_start = (SpiceMsgcMainAgentStart *)msg->data();
- agent_start->num_tokens = ~0;
+ Message* msg = new Message(SPICE_MSGC_MAIN_AGENT_START);
+ SpiceMsgcMainAgentStart agent_start;
+ agent_start.num_tokens = ~0;
+ spice_marshall_msgc_main_agent_start(msg->marshaller(), &agent_start);
post_message(msg);
}
if (_auto_display_res) {
@@ -725,7 +731,7 @@ void RedClient::handle_init(RedPeer::InMessage* message)
send_agent_monitors_config();
}
} else {
- post_message(new Message(SPICE_MSGC_MAIN_ATTACH_CHANNELS, 0));
+ post_message(new Message(SPICE_MSGC_MAIN_ATTACH_CHANNELS));
}
}
@@ -754,9 +760,10 @@ void RedClient::handle_agent_connected(RedPeer::InMessage* message)
{
DBG(0, "");
_agent_connected = true;
- Message* msg = new Message(SPICE_MSGC_MAIN_AGENT_START, sizeof(SpiceMsgcMainAgentStart));
- SpiceMsgcMainAgentStart* agent_start = (SpiceMsgcMainAgentStart *)msg->data();
- agent_start->num_tokens = ~0;
+ Message* msg = new Message(SPICE_MSGC_MAIN_AGENT_START);
+ SpiceMsgcMainAgentStart agent_start;
+ agent_start.num_tokens = ~0;
+ spice_marshall_msgc_main_agent_start(msg->marshaller(), &agent_start);
post_message(msg);
if (_auto_display_res && !_agent_mon_config_sent) {
send_agent_monitors_config();
@@ -781,7 +788,7 @@ void RedClient::on_agent_reply(VDAgentReply* reply)
}
switch (reply->type) {
case VD_AGENT_MONITORS_CONFIG:
- post_message(new Message(SPICE_MSGC_MAIN_ATTACH_CHANNELS, 0));
+ post_message(new Message(SPICE_MSGC_MAIN_ATTACH_CHANNELS));
_application.deactivate_interval_timer(*_agent_timer);
break;
default:
diff --git a/client/red_peer.cpp b/client/red_peer.cpp
index be18dfb..9a608ad 100644
--- a/client/red_peer.cpp
+++ b/client/red_peer.cpp
@@ -726,38 +726,59 @@ uint32_t RedPeer::send(uint8_t *buf, uint32_t size)
return pos - buf;
}
+uint32_t RedPeer::do_send(RedPeer::OutMessage& message, uint32_t skip_bytes)
+{
+ uint8_t *data;
+ int free_data;
+ size_t len;
+ uint32_t res;
+
+ data = spice_marshaller_linearize(message.marshaller(), skip_bytes,
+ &len, &free_data);
+
+ res = send(data, len);
+
+ if (free_data) {
+ free(data);
+ }
+ return res;
+}
+
uint32_t RedPeer::send(RedPeer::OutMessage& message)
{
+
message.header().serial = ++_serial;
- return send(message.base(), message.message_size());
+ message.header().size = message.message_size() - sizeof(SpiceDataHeader);
+
+ return do_send(message, 0);
}
-RedPeer::OutMessage::OutMessage(uint32_t type, uint32_t size)
- : _data (new uint8_t[size + sizeof(SpiceDataHeader)])
- , _size (size)
+RedPeer::OutMessage::OutMessage(uint32_t type)
+ : _marshaller (spice_marshaller_new())
{
- header().type = type;
- header().size = size;
+ SpiceDataHeader *header;
+ header = (SpiceDataHeader *)
+ spice_marshaller_reserve_space(_marshaller, sizeof(SpiceDataHeader));
+ spice_marshaller_set_base(_marshaller, sizeof(SpiceDataHeader));
+
+ header->type = type;
+ header->sub_list = 0;
}
-RedPeer::OutMessage::~OutMessage()
+void RedPeer::OutMessage::reset(uint32_t type)
{
- delete[] _data;
+ spice_marshaller_reset(_marshaller);
+
+ SpiceDataHeader *header;
+ header = (SpiceDataHeader *)
+ spice_marshaller_reserve_space(_marshaller, sizeof(SpiceDataHeader));
+ spice_marshaller_set_base(_marshaller, sizeof(SpiceDataHeader));
+
+ header->type = type;
+ header->sub_list = 0;
}
-void RedPeer::OutMessage::resize(uint32_t size)
+RedPeer::OutMessage::~OutMessage()
{
- if (size <= _size) {
- header().size = size;
- return;
- }
- uint32_t type = header().type;
- delete[] _data;
- _data = NULL;
- _size = 0;
- _data = new uint8_t[size + sizeof(SpiceDataHeader)];
- _size = size;
- header().type = type;
- header().size = size;
+ spice_marshaller_destroy(_marshaller);
}
-
diff --git a/client/red_peer.h b/client/red_peer.h
index f24e5e7..001f9fa 100644
--- a/client/red_peer.h
+++ b/client/red_peer.h
@@ -26,6 +26,7 @@
#include "process_loop.h"
#include "threads.h"
#include "platform_utils.h"
+#include "marshaller.h"
class RedPeer: protected EventSources::Socket {
public:
@@ -111,6 +112,7 @@ public:
void enable() { _shut = false;}
virtual CompundInMessage* recive();
+ uint32_t do_send(OutMessage& message, uint32_t skip_bytes);
uint32_t send(OutMessage& message);
uint32_t recive(uint8_t* buf, uint32_t size);
@@ -194,20 +196,19 @@ private:
class RedPeer::OutMessage {
public:
- OutMessage(uint32_t type, uint32_t size);
+ OutMessage(uint32_t type);
virtual ~OutMessage();
- SpiceDataHeader& header() { return *(SpiceDataHeader *)_data;}
- uint8_t* data() { return _data + sizeof(SpiceDataHeader);}
- void resize(uint32_t size);
+ SpiceMarshaller *marshaller() { return _marshaller;}
+ void reset(uint32_t type);
private:
- uint32_t message_size() { return header().size + sizeof(SpiceDataHeader);}
- uint8_t* base() { return _data;}
+ uint32_t message_size() { return spice_marshaller_get_total_size(_marshaller);}
+ uint8_t* base() { return spice_marshaller_get_ptr(_marshaller);}
+ SpiceDataHeader& header() { return *(SpiceDataHeader *)base();}
-private:
- uint8_t* _data;
- uint32_t _size;
+protected:
+ SpiceMarshaller *_marshaller;
friend class RedPeer;
friend class RedChannel;
diff --git a/client/tunnel_channel.cpp b/client/tunnel_channel.cpp
index cecd9ba..1464b1d 100644
--- a/client/tunnel_channel.cpp
+++ b/client/tunnel_channel.cpp
@@ -21,6 +21,7 @@
#include "common.h"
#include "tunnel_channel.h"
+#include "generated_marshallers.h"
#include <spice/protocol.h>
#define SOCKET_WINDOW_SIZE 60
@@ -93,13 +94,13 @@ public:
virtual RedPeer::OutMessage& peer_message() { return *this;}
virtual void release();
- virtual uint8_t* buf();
+ virtual uint8_t* buf() { return _the_buf; };
virtual uint32_t buf_max_size() {return _max_data_size;}
virtual void set_buf_size(uint32_t size);
virtual void release_buf();
static void init(uint32_t max_data_size);
- static OutSocketMessage& alloc_message();
+ static OutSocketMessage& alloc_message(uint16_t id);
static void clear_free_messages();
protected:
@@ -109,26 +110,22 @@ protected:
private:
static std::list<OutSocketMessage*> _free_messages;
static uint32_t _max_data_size;
+ uint8_t *_the_buf;
};
std::list<OutSocketMessage*> OutSocketMessage::_free_messages;
uint32_t OutSocketMessage::_max_data_size;
OutSocketMessage::OutSocketMessage()
- : RedPeer::OutMessage(SPICE_MSGC_TUNNEL_SOCKET_DATA, sizeof(SpiceMsgcTunnelSocketData) + _max_data_size)
+ : RedPeer::OutMessage(SPICE_MSGC_TUNNEL_SOCKET_DATA)
, RedChannel::OutMessage()
, ClientNetSocket::ReceiveBuffer()
{
}
-uint8_t* OutSocketMessage::buf()
-{
- return ((SpiceMsgcTunnelSocketData*)RedPeer::OutMessage::data())->data;
-}
-
void OutSocketMessage::set_buf_size(uint32_t size)
{
- RedPeer::OutMessage::header().size = size + sizeof(SpiceMsgcTunnelSocketData);
+ spice_marshaller_unreserve_space(_marshaller, _max_data_size - size);
}
void OutSocketMessage::release()
@@ -146,16 +143,22 @@ void OutSocketMessage::init(uint32_t max_data_size)
_max_data_size = max_data_size;
}
-OutSocketMessage& OutSocketMessage::alloc_message()
+OutSocketMessage& OutSocketMessage::alloc_message(uint16_t id)
{
OutSocketMessage* ret;
if (!_free_messages.empty()) {
ret = _free_messages.front();
_free_messages.pop_front();
+ spice_marshaller_reset(ret->marshaller());
} else {
ret = new OutSocketMessage();
}
+ SpiceMsgcTunnelSocketData data;
+ data.connection_id = id;
+ spice_marshall_msgc_tunnel_socket_data(ret->marshaller(), &data);
+ ret->_the_buf = spice_marshaller_reserve_space(ret->marshaller(), _max_data_size);
+
return *ret;
}
@@ -198,7 +201,7 @@ public:
bool get_guest_closed() {return _guest_closed;}
protected:
- virtual ReceiveBuffer& alloc_receive_buffer() {return OutSocketMessage::alloc_message();}
+ virtual ReceiveBuffer& alloc_receive_buffer() {return OutSocketMessage::alloc_message(id());}
private:
uint32_t _num_tokens;
@@ -275,45 +278,33 @@ void TunnelChannel::handle_init(RedPeer::InMessage* message)
void TunnelChannel::send_service(TunnelService& service)
{
- int msg_size = 0;
- msg_size += service.name.length() + 1;
- msg_size += service.description.length() + 1;
-
- if (service.type == SPICE_TUNNEL_SERVICE_TYPE_IPP) {
- msg_size += sizeof(SpiceMsgcTunnelAddPrintService) + sizeof(SpiceTunnelIPv4);
- } else if (service.type == SPICE_TUNNEL_SERVICE_TYPE_GENERIC) {
- msg_size += sizeof(SpiceMsgcTunnelAddGenericService);
- } else {
+ if (service.type != SPICE_TUNNEL_SERVICE_TYPE_IPP &&
+ service.type == SPICE_TUNNEL_SERVICE_TYPE_GENERIC) {
THROW("%s: invalid service type", __FUNCTION__);
}
- Message* service_msg = new Message(SPICE_MSGC_TUNNEL_SERVICE_ADD, msg_size);
- SpiceMsgcTunnelAddGenericService* out_service = (SpiceMsgcTunnelAddGenericService*)service_msg->data();
- out_service->id = service.id;
- out_service->group = service.group;
- out_service->type = service.type;
- out_service->port = service.port;
- int cur_offset;
+ Message* service_msg = new Message(SPICE_MSGC_TUNNEL_SERVICE_ADD);
+ SpiceMsgcTunnelAddPrintService add;
+ SpiceMarshaller *name_out, *description_out;
+ add.base.id = service.id;
+ add.base.group = service.group;
+ add.base.type = service.type;
+ add.base.port = service.port;
+
if (service.type == SPICE_TUNNEL_SERVICE_TYPE_IPP) {
- cur_offset = sizeof(SpiceMsgcTunnelAddPrintService);
- ((SpiceMsgcTunnelAddPrintService*)out_service)->ip.type = SPICE_TUNNEL_IP_TYPE_IPv4;
- memcpy(((SpiceMsgcTunnelAddPrintService*)out_service)->ip.data, &(service.ip.s_addr),
- sizeof(SpiceTunnelIPv4));
- cur_offset += sizeof(SpiceTunnelIPv4);
- } else {
- cur_offset = sizeof(SpiceMsgcTunnelAddGenericService);
+ add.ip.type = SPICE_TUNNEL_IP_TYPE_IPv4;
}
- out_service->name = cur_offset;
- service.name.copy((char*)(service_msg->data() + cur_offset), service.name.length());
- (service_msg->data() + cur_offset)[service.name.length()] = '\0';
- cur_offset += service.name.length() + 1;
+ spice_marshall_msgc_tunnel_service_add(service_msg->marshaller(), &add.base,
+ &name_out, &description_out);
- out_service->description = cur_offset;
- service.description.copy((char*)(service_msg->data() + cur_offset),
- service.description.length());
- (service_msg->data() + cur_offset)[service.description.length()] = '\0';
- cur_offset += service.description.length() + 1;
+ if (service.type == SPICE_TUNNEL_SERVICE_TYPE_IPP) {
+ spice_marshaller_add(service_msg->marshaller(), (uint8_t *)&(service.ip.s_addr),
+ sizeof(SpiceTunnelIPv4));
+ }
+
+ spice_marshaller_add(name_out, (uint8_t *)service.name.c_str(), service.name.length() + 1);
+ spice_marshaller_add(description_out, (uint8_t *)service.description.c_str(), service.description.length() + 1);
post_message(service_msg);
}
@@ -361,15 +352,18 @@ void TunnelChannel::handle_socket_open(RedPeer::InMessage* message)
if (sckt->connect(open_msg->tokens)) {
_sockets[open_msg->connection_id] = sckt;
- out_msg = new Message(SPICE_MSGC_TUNNEL_SOCKET_OPEN_ACK, sizeof(SpiceMsgcTunnelSocketOpenAck));
+ out_msg = new Message(SPICE_MSGC_TUNNEL_SOCKET_OPEN_ACK);
sckt->set_num_tokens(0);
sckt->set_server_num_tokens(SOCKET_WINDOW_SIZE);
-
- ((SpiceMsgcTunnelSocketOpenAck*)out_msg->data())->connection_id = open_msg->connection_id;
- ((SpiceMsgcTunnelSocketOpenAck*)out_msg->data())->tokens = SOCKET_WINDOW_SIZE;
+ SpiceMsgcTunnelSocketOpenAck ack;
+ ack.connection_id = open_msg->connection_id;
+ ack.tokens = SOCKET_WINDOW_SIZE;
+ spice_marshall_msgc_tunnel_socket_open_ack(out_msg->marshaller(), &ack);
} else {
- out_msg = new Message(SPICE_MSGC_TUNNEL_SOCKET_OPEN_NACK, sizeof(SpiceMsgcTunnelSocketOpenNack));
- ((SpiceMsgcTunnelSocketOpenNack*)out_msg->data())->connection_id = open_msg->connection_id;
+ out_msg = new Message(SPICE_MSGC_TUNNEL_SOCKET_OPEN_NACK);
+ SpiceMsgcTunnelSocketOpenNack nack;
+ nack.connection_id = open_msg->connection_id;
+ spice_marshall_msgc_tunnel_socket_open_nack(out_msg->marshaller(), &nack);
delete sckt;
}
@@ -480,19 +474,19 @@ void TunnelChannel::handle_socket_token(RedPeer::InMessage* message)
void TunnelChannel::on_socket_message_recv_done(ClientNetSocket& sckt,
ClientNetSocket::ReceiveBuffer& buf)
{
- TunnelChannel::TunnelSocket* tunnel_sckt = static_cast<TunnelChannel::TunnelSocket*>(&sckt);
OutSocketMessage* out_msg = static_cast<OutSocketMessage*>(&buf);
- ((SpiceMsgcTunnelSocketData*)(out_msg->data()))->connection_id = tunnel_sckt->id();
post_message(out_msg);
}
void TunnelChannel::on_socket_fin_recv(ClientNetSocket& sckt)
{
TunnelChannel::TunnelSocket* tunnel_sckt = static_cast<TunnelChannel::TunnelSocket*>(&sckt);
- Message* out_msg = new Message(SPICE_MSGC_TUNNEL_SOCKET_FIN, sizeof(SpiceMsgcTunnelSocketFin));
+ Message* out_msg = new Message(SPICE_MSGC_TUNNEL_SOCKET_FIN);
DBG(0, "FIN from client coonection id=%d", tunnel_sckt->id());
- ((SpiceMsgcTunnelSocketFin*)out_msg->data())->connection_id = tunnel_sckt->id();
+ SpiceMsgcTunnelSocketFin fin;
+ fin.connection_id = tunnel_sckt->id();
+ spice_marshall_msgc_tunnel_socket_fin(out_msg->marshaller(), &fin);
post_message(out_msg);
}
@@ -503,14 +497,18 @@ void TunnelChannel::on_socket_disconnect(ClientNetSocket& sckt)
// close initiated by server -> needs ack
if (tunnel_sckt->get_guest_closed()) {
DBG(0, "send close ack connection_id=%d", tunnel_sckt->id());
- out_msg = new Message(SPICE_MSGC_TUNNEL_SOCKET_CLOSED_ACK, sizeof(SpiceMsgcTunnelSocketClosedAck));
- ((SpiceMsgcTunnelSocketClosedAck*)out_msg->data())->connection_id = tunnel_sckt->id();
+ out_msg = new Message(SPICE_MSGC_TUNNEL_SOCKET_CLOSED_ACK);
+ SpiceMsgcTunnelSocketClosedAck ack;
+ ack.connection_id = tunnel_sckt->id();
+ spice_marshall_msgc_tunnel_socket_closed_ack(out_msg->marshaller(), &ack);
_sockets[tunnel_sckt->id()] = NULL;
delete &sckt;
} else { // close initiated by client
DBG(0, "send close coonection_id=%d", tunnel_sckt->id());
- out_msg = new Message(SPICE_MSGC_TUNNEL_SOCKET_CLOSED, sizeof(SpiceMsgcTunnelSocketClosed));
- ((SpiceMsgcTunnelSocketClosed*)out_msg->data())->connection_id = tunnel_sckt->id();
+ out_msg = new Message(SPICE_MSGC_TUNNEL_SOCKET_CLOSED);
+ SpiceMsgcTunnelSocketClosed closed;
+ closed.connection_id = tunnel_sckt->id();
+ spice_marshall_msgc_tunnel_socket_closed(out_msg->marshaller(), &closed);
}
post_message(out_msg);
@@ -523,10 +521,11 @@ void TunnelChannel::on_socket_message_send_done(ClientNetSocket& sckt)
num_tokens++;
if (num_tokens == SOCKET_TOKENS_TO_SEND) {
- Message* out_msg = new Message(SPICE_MSGC_TUNNEL_SOCKET_TOKEN, sizeof(SpiceMsgcTunnelSocketTokens));
- SpiceMsgcTunnelSocketTokens* tokens_msg = (SpiceMsgcTunnelSocketTokens*)out_msg->data();
- tokens_msg->connection_id = tunnel_sckt->id();
- tokens_msg->num_tokens = num_tokens;
+ Message* out_msg = new Message(SPICE_MSGC_TUNNEL_SOCKET_TOKEN);
+ SpiceMsgcTunnelSocketTokens tokens_msg;
+ tokens_msg.connection_id = tunnel_sckt->id();
+ tokens_msg.num_tokens = num_tokens;
+ spice_marshall_msgc_tunnel_socket_token(out_msg->marshaller(), &tokens_msg);
post_message(out_msg);
tunnel_sckt->set_num_tokens(0);
commit 13026676627887a7d85abb49a0468150ac75ebe6
Author: Alexander Larsson <alexl at redhat.com>
Date: Wed Jun 16 10:32:00 2010 +0200
Generate and link marshallers into client
diff --git a/client/Makefile.am b/client/Makefile.am
index f8ccb98..fa7dbb6 100644
--- a/client/Makefile.am
+++ b/client/Makefile.am
@@ -3,11 +3,18 @@ NULL =
SUBDIRS = . $(red_target)
DIST_SUBDIRS = x11 #windows
-spice_built_sources = generated_demarshallers.cpp
+spice_built_sources = generated_demarshallers.cpp generated_marshallers.cpp generated_marshallers.h
generated_demarshallers.cpp: $(top_srcdir)/spice.proto
$(PYTHON) $(top_srcdir)/spice_codegen.py --generate-demarshallers --client --include common.h $(top_srcdir)/spice.proto generated_demarshallers.cpp
+STRUCTS=
+generated_marshallers.cpp: $(top_srcdir)/spice.proto
+ $(PYTHON) $(top_srcdir)/spice_codegen.py --generate-marshallers $(STRUCTS) --client $(top_srcdir)/spice.proto generated_marshallers.cpp
+
+generated_marshallers.h: $(top_srcdir)/spice.proto
+ $(PYTHON) $(top_srcdir)/spice_codegen.py --generate-marshallers $(STRUCTS) --client -H $(top_srcdir)/spice.proto generated_marshallers.h
+
RED_COMMON_SRCS = \
application.cpp \
application.h \
@@ -29,6 +36,8 @@ RED_COMMON_SRCS = \
common.h \
demarshallers.h \
generated_demarshallers.cpp \
+ generated_marshallers.cpp \
+ generated_marshallers.h \
cursor_channel.cpp \
cursor_channel.h \
cursor.cpp \
diff --git a/client/marshaller.cpp b/client/marshaller.cpp
new file mode 100644
index 0000000..14bd096
--- /dev/null
+++ b/client/marshaller.cpp
@@ -0,0 +1,24 @@
+/*
+ Copyright (C) 2009 Red Hat, Inc.
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this library; if not, see <http://www.gnu.org/licenses/>.
+*/
+
+#include "common.h"
+#include "utils.h"
+
+
+#define CANVAS_ERROR(format, ...) THROW(format, ## __VA_ARGS__)
+
+#include "../common/marshaller.c"
diff --git a/client/x11/Makefile.am b/client/x11/Makefile.am
index 82a08dd..cbc9c52 100644
--- a/client/x11/Makefile.am
+++ b/client/x11/Makefile.am
@@ -39,6 +39,9 @@ RED_COMMON_SRCS = \
$(CLIENT_DIR)/cache.hpp \
$(CLIENT_DIR)/demarshallers.h \
$(CLIENT_DIR)/generated_demarshallers.cpp \
+ $(CLIENT_DIR)/marshaller.cpp \
+ $(CLIENT_DIR)/generated_marshallers.h \
+ $(CLIENT_DIR)/generated_marshallers.cpp \
$(CLIENT_DIR)/sw_canvas.cpp \
$(CLIENT_DIR)/canvas.cpp \
$(CLIENT_DIR)/canvas.h \
commit d9772344e60d9930ab35b7e88d4fd491314175d1
Author: Alexander Larsson <alexl at redhat.com>
Date: Tue Jun 15 15:43:21 2010 +0200
Re-enable cache freeing
I don't know why this was disabled but it seems like a bad idea
diff --git a/server/red_worker.c b/server/red_worker.c
index 80abb7c..8b40116 100644
--- a/server/red_worker.c
+++ b/server/red_worker.c
@@ -8382,7 +8382,7 @@ static inline void display_begin_send_massage(DisplayChannel *channel, void *ite
{
FreeList *free_list = &channel->send_data.free_list;
- if (0 && free_list->res->count) {
+ if (free_list->res->count) {
int sub_list_len = 1;
SpiceMarshaller *wait_m = NULL;
SpiceMarshaller *inval_m;
commit 04e0c6e5b2027c3457d62380c1433aab6490d7ed
Author: Alexander Larsson <alexl at redhat.com>
Date: Tue Jun 15 19:15:27 2010 +0200
Convert reds.c to use SpiceMarshaller
diff --git a/server/reds.c b/server/reds.c
index ed5d212..fee1cbf 100644
--- a/server/reds.c
+++ b/server/reds.c
@@ -1,3 +1,4 @@
+/* -*- Mode: C; c-basic-offset: 4; indent-tabs-mode: nil -*- */
/*
Copyright (C) 2009 Red Hat, Inc.
@@ -51,6 +52,8 @@
#include "stat.h"
#include "ring.h"
#include "config.h"
+#include "marshaller.h"
+#include "generated_marshallers.h"
#ifdef HAVE_SLIRP
#include "red_tunnel_worker.h"
#endif
@@ -148,14 +151,13 @@ typedef struct MonitorMode {
typedef struct RedsOutItem RedsOutItem;
struct RedsOutItem {
RingItem link;
- void (*prepare)(RedsOutItem *item, struct iovec* vec, int *len);
- void (*release)(RedsOutItem *item);
+ SpiceMarshaller *m;
+ SpiceDataHeader *header;
};
typedef struct VDIReadBuf {
- RedsOutItem out_item;
+ RingItem link;
int len;
- SpiceDataHeader header;
uint8_t data[SPICE_AGENT_MAX_DATA_SIZE];
} VDIReadBuf;
@@ -353,18 +355,12 @@ struct ChannelSecurityOptions {
ChannelSecurityOptions *next;
};
-typedef struct PingItem {
- RedsOutItem base;
- SpiceDataHeader header;
- SpiceMsgPing ping;
- int size;
-} PingItem;
-
#define ZERO_BUF_SIZE 4096
static uint8_t zero_page[ZERO_BUF_SIZE] = {0};
static void reds_push();
+static void reds_out_item_free(RedsOutItem *item);
static ChannelSecurityOptions *channels_security = NULL;
static int default_channel_security =
@@ -693,7 +689,7 @@ static void reds_reset_vdp()
state->recive_len = sizeof(state->vdi_chunk_header);
state->message_recive_len = 0;
if (state->current_read_buf) {
- ring_add(&state->read_bufs, &state->current_read_buf->out_item.link);
+ ring_add(&state->read_bufs, &state->current_read_buf->link);
state->current_read_buf = NULL;
}
state->client_agent_started = FALSE;
@@ -706,13 +702,13 @@ static void reds_reset_outgoing()
RingItem *ring_item;
if (outgoing->item) {
- outgoing->item->release(outgoing->item);
+ reds_out_item_free(outgoing->item);
outgoing->item = NULL;
}
while ((ring_item = ring_get_tail(&outgoing->pipe))) {
RedsOutItem *out_item = (RedsOutItem *)ring_item;
ring_remove(ring_item);
- out_item->release(out_item);
+ reds_out_item_free(out_item);
}
outgoing->vec_size = 0;
outgoing->vec = outgoing->vec_buf;
@@ -881,49 +877,31 @@ static int outgoing_write(RedsStreamContext *peer, OutgoingHandler *handler, voi
return OUTGOING_OK;
}
-typedef struct SimpleOutItem {
- RedsOutItem base;
- SpiceDataHeader header;
- uint8_t data[0];
-} SimpleOutItem;
-
-static void reds_prepare_basic_out_item(RedsOutItem *in_item, struct iovec* vec, int *len)
+static RedsOutItem *new_out_item(uint32_t type)
{
- SimpleOutItem *item = (SimpleOutItem *)in_item;
-
- vec[0].iov_base = &item->header;
- vec[0].iov_len = sizeof(item->header);
- if (item->header.size) {
- vec[1].iov_base = item->data;
- vec[1].iov_len = item->header.size;
- *len = 2;
- } else {
- *len = 1;
- }
-}
-
-static void reds_free_basic_out_item(RedsOutItem *item)
-{
- free(item);
-}
+ RedsOutItem *item;
-static SimpleOutItem *new_simple_out_item(uint32_t type, int message_size)
-{
- SimpleOutItem *item;
+ item = spice_new(RedsOutItem, 1);
+ ring_item_init(&item->link);
- item = (SimpleOutItem *)spice_malloc(sizeof(*item) + message_size);
- ring_item_init(&item->base.link);
- item->base.prepare = reds_prepare_basic_out_item;
- item->base.release = reds_free_basic_out_item;
+ item->m = spice_marshaller_new();
+ item->header = (SpiceDataHeader *)
+ spice_marshaller_reserve_space(item->m, sizeof(SpiceDataHeader));
+ spice_marshaller_set_base(item->m, sizeof(SpiceDataHeader));
- item->header.serial = ++reds->serial;
- item->header.type = type;
- item->header.size = message_size;
- item->header.sub_list = 0;
+ item->header->serial = ++reds->serial;
+ item->header->type = type;
+ item->header->sub_list = 0;
return item;
}
+static void reds_out_item_free(RedsOutItem *item)
+{
+ spice_marshaller_destroy(item->m);
+ free(item);
+}
+
static void reds_push_pipe_item(RedsOutItem *item)
{
ring_add(&reds->outgoing.pipe, &item->link);
@@ -933,14 +911,12 @@ static void reds_push_pipe_item(RedsOutItem *item)
static void reds_send_channels()
{
SpiceMsgChannels* channels_info;
- SimpleOutItem *item;
- int message_size;
+ RedsOutItem *item;
Channel *channel;
int i;
- message_size = sizeof(SpiceMsgChannels) + reds->num_of_channels * sizeof(SpiceChannelId);
- item = new_simple_out_item(SPICE_MSG_MAIN_CHANNELS_LIST, message_size);
- channels_info = (SpiceMsgChannels *)item->data;
+ item = new_out_item(SPICE_MSG_MAIN_CHANNELS_LIST);
+ channels_info = (SpiceMsgChannels *)spice_malloc(sizeof(SpiceMsgChannels) + reds->num_of_channels * sizeof(SpiceChannelId));
channels_info->num_of_channels = reds->num_of_channels;
channel = reds->channels;
@@ -950,59 +926,34 @@ static void reds_send_channels()
channels_info->channels[i].id = channel->id;
channel = channel->next;
}
- reds_push_pipe_item(&item->base);
-}
-
-static void reds_prepare_ping_item(RedsOutItem *in_item, struct iovec* vec, int *len)
-{
- PingItem *item = (PingItem *)in_item;
-
- vec[0].iov_base = &item->header;
- vec[0].iov_len = sizeof(item->header);
- vec[1].iov_base = &item->ping;
- vec[1].iov_len = sizeof(item->ping);
- int size = item->size;
- int pos = 2;
- while (size) {
- ASSERT(pos < REDS_MAX_SEND_IOVEC);
- int now = MIN(ZERO_BUF_SIZE, size);
- size -= now;
- vec[pos].iov_base = zero_page;
- vec[pos].iov_len = now;
- pos++;
- }
- *len = pos;
-}
-
-static void reds_free_ping_item(RedsOutItem *item)
-{
- free(item);
+ spice_marshall_msg_main_channels_list(item->m, channels_info);
+ free(channels_info);
+ reds_push_pipe_item(item);
}
static int send_ping(int size)
{
struct timespec time_space;
- PingItem *item;
+ RedsOutItem *item;
+ SpiceMsgPing ping;
if (!reds->peer) {
return FALSE;
}
- item = spice_new(PingItem, 1);
- ring_item_init(&item->base.link);
- item->base.prepare = reds_prepare_ping_item;
- item->base.release = reds_free_ping_item;
+ item = new_out_item(SPICE_MSG_PING);
+ ping.id = ++reds->ping_id;
+ clock_gettime(CLOCK_MONOTONIC, &time_space);
+ ping.timestamp = time_space.tv_sec * 1000000LL + time_space.tv_nsec / 1000LL;
+ spice_marshall_msg_ping(item->m, &ping);
- item->header.serial = ++reds->serial;
- item->header.type = SPICE_MSG_PING;
- item->header.size = sizeof(item->ping) + size;
- item->header.sub_list = 0;
+ while (size > 0) {
+ int now = MIN(ZERO_BUF_SIZE, size);
+ size -= now;
+ spice_marshaller_add_ref(item->m, zero_page, now);
+ }
- item->ping.id = ++reds->ping_id;
- clock_gettime(CLOCK_MONOTONIC, &time_space);
- item->ping.timestamp = time_space.tv_sec * 1000000LL + time_space.tv_nsec / 1000LL;
+ reds_push_pipe_item(item);
- item->size = size;
- reds_push_pipe_item(&item->base);
return TRUE;
}
@@ -1044,21 +995,23 @@ static void ping_timer_cb()
static void reds_send_mouse_mode()
{
- SpiceMsgMainMouseMode *mouse_mode;
- SimpleOutItem *item;
+ SpiceMsgMainMouseMode mouse_mode;
+ RedsOutItem *item;
if (!reds->peer) {
return;
}
- item = new_simple_out_item(SPICE_MSG_MAIN_MOUSE_MODE, sizeof(SpiceMsgMainMouseMode));
- mouse_mode = (SpiceMsgMainMouseMode *)item->data;
- mouse_mode->supported_modes = SPICE_MOUSE_MODE_SERVER;
+ item = new_out_item(SPICE_MSG_MAIN_MOUSE_MODE);
+ mouse_mode.supported_modes = SPICE_MOUSE_MODE_SERVER;
if (reds->is_client_mouse_allowed) {
- mouse_mode->supported_modes |= SPICE_MOUSE_MODE_CLIENT;
+ mouse_mode.supported_modes |= SPICE_MOUSE_MODE_CLIENT;
}
- mouse_mode->current_mode = reds->mouse_mode;
- reds_push_pipe_item(&item->base);
+ mouse_mode.current_mode = reds->mouse_mode;
+
+ spice_marshall_msg_main_mouse_mode(item->m, &mouse_mode);
+
+ reds_push_pipe_item(item);
}
static void reds_set_mouse_mode(uint32_t mode)
@@ -1092,20 +1045,21 @@ static void reds_update_mouse_mode()
static void reds_send_agent_connected()
{
- SimpleOutItem *item;
- item = new_simple_out_item(SPICE_MSG_MAIN_AGENT_CONNECTED, 0);
- reds_push_pipe_item(&item->base);
+ RedsOutItem *item;
+
+ item = new_out_item(SPICE_MSG_MAIN_AGENT_CONNECTED);
+ reds_push_pipe_item(item);
}
static void reds_send_agent_disconnected()
{
- SpiceMsgMainAgentDisconnect *disconnect;
- SimpleOutItem *item;
+ SpiceMsgMainAgentDisconnect disconnect;
+ RedsOutItem *item;
- item = new_simple_out_item(SPICE_MSG_MAIN_AGENT_DISCONNECTED, sizeof(SpiceMsgMainAgentDisconnect));
- disconnect = (SpiceMsgMainAgentDisconnect *)item->data;
- disconnect->error_code = SPICE_LINK_ERR_OK;
- reds_push_pipe_item(&item->base);
+ item = new_out_item(SPICE_MSG_MAIN_AGENT_DISCONNECTED);
+ disconnect.error_code = SPICE_LINK_ERR_OK;
+ spice_marshall_msg_main_agent_disconnected(item->m, &disconnect);
+ reds_push_pipe_item(item);
}
static void reds_agent_remove()
@@ -1137,20 +1091,22 @@ static void reds_agent_remove()
static void reds_send_tokens()
{
- SpiceMsgMainAgentTokens *tokens;
- SimpleOutItem *item;
+ SpiceMsgMainAgentTokens tokens;
+ RedsOutItem *item;
if (!reds->peer) {
return;
}
- item = new_simple_out_item(SPICE_MSG_MAIN_AGENT_TOKEN, sizeof(SpiceMsgMainAgentTokens));
- tokens = (SpiceMsgMainAgentTokens *)item->data;
- tokens->num_tokens = reds->agent_state.num_tokens;
- reds->agent_state.num_client_tokens += tokens->num_tokens;
+ item = new_out_item(SPICE_MSG_MAIN_AGENT_TOKEN);
+ tokens.num_tokens = reds->agent_state.num_tokens;
+ reds->agent_state.num_client_tokens += tokens.num_tokens;
ASSERT(reds->agent_state.num_client_tokens <= REDS_AGENT_WINDOW_SIZE);
reds->agent_state.num_tokens = 0;
- reds_push_pipe_item(&item->base);
+
+ spice_marshall_msg_main_agent_token(item->m, &tokens);
+
+ reds_push_pipe_item(item);
}
static int write_to_vdi_port()
@@ -1188,27 +1144,41 @@ static int write_to_vdi_port()
return total;
}
+static int read_from_vdi_port(void);
+
+void vdi_read_buf_release(uint8_t *data, void *opaque)
+{
+ VDIReadBuf *buf = (VDIReadBuf *)opaque;
+
+ ring_add(&reds->agent_state.read_bufs, &buf->link);
+ read_from_vdi_port();
+}
+
static void dispatch_vdi_port_data(int port, VDIReadBuf *buf)
{
VDIPortState *state = &reds->agent_state;
+ RedsOutItem *item;
+
switch (port) {
case VDP_CLIENT_PORT: {
- buf->header.serial = ++reds->serial;
- buf->header.size = buf->len;
- reds_push_pipe_item(&buf->out_item);
+ item = new_out_item(SPICE_MSG_MAIN_AGENT_DATA);
+
+ spice_marshaller_add_ref_full(item->m, buf->data, buf->len,
+ vdi_read_buf_release, buf);
+ reds_push_pipe_item(item);
break;
}
case VDP_SERVER_PORT:
- ring_add(&state->read_bufs, &buf->out_item.link);
+ ring_add(&state->read_bufs, &buf->link);
break;
default:
- ring_add(&state->read_bufs, &buf->out_item.link);
+ ring_add(&state->read_bufs, &buf->link);
red_printf("invalid port");
reds_agent_remove();
}
}
-static int read_from_vdi_port()
+static int read_from_vdi_port(void)
{
VDIPortState *state = &reds->agent_state;
SpiceVDIPortInterface *sif;
@@ -1346,112 +1316,69 @@ typedef struct WriteQueueInfo {
uint32_t len;
} WriteQueueInfo;
-typedef struct SendMainMigrateItem {
- RedsOutItem base;
- SpiceDataHeader header;
- MainMigrateData data;
- WriteQueueInfo queue_info[REDS_AGENT_WINDOW_SIZE + REDS_NUM_INTERNAL_AGENT_MESSAGES];
-} SendMainMigrateItem;
-
-static void main_channel_send_migrate_data_item(RedsOutItem *in_item, struct iovec* vec_start,
- int *len)
+static void main_channel_push_migrate_data_item()
{
- SendMainMigrateItem *item = (SendMainMigrateItem *)in_item;
+ RedsOutItem *item;
+ MainMigrateData *data;
VDIPortState *state = &reds->agent_state;
- struct iovec* vec;
int buf_index;
RingItem *now;
- vec = vec_start;
-
- item->header.serial = ++reds->serial;
- item->header.type = SPICE_MSG_MIGRATE_DATA;
- item->header.size = sizeof(item->data);
- item->header.sub_list = 0;
-
- vec[0].iov_base = &item->header;
- vec[0].iov_len = sizeof(item->header);
- vec[1].iov_base = &item->data;
- vec[1].iov_len = sizeof(item->data);
-
- vec += 2;
- *len = 2;
+ item = new_out_item(SPICE_MSG_MIGRATE_DATA);
- item->data.version = MAIN_CHANNEL_MIG_DATA_VERSION;
- item->data.serial = reds->serial;
- item->data.ping_id = reds->ping_id;
+ data = (MainMigrateData *)spice_marshaller_reserve_space(item->m, sizeof(MainMigrateData));
+ data->version = MAIN_CHANNEL_MIG_DATA_VERSION;
+ data->serial = reds->serial;
+ data->ping_id = reds->ping_id;
- item->data.agent_connected = !!state->connected;
- item->data.client_agent_started = state->client_agent_started;
- item->data.num_client_tokens = state->num_client_tokens;
- item->data.send_tokens = state->send_tokens;
-
- item->data.read_state = state->read_state;
- item->data.vdi_chunk_header = state->vdi_chunk_header;
- item->data.recive_len = state->recive_len;
- item->data.message_recive_len = state->message_recive_len;
+ data->agent_connected = !!state->connected;
+ data->client_agent_started = state->client_agent_started;
+ data->num_client_tokens = state->num_client_tokens;
+ data->send_tokens = state->send_tokens;
+ data->read_state = state->read_state;
+ data->vdi_chunk_header = state->vdi_chunk_header;
+ data->recive_len = state->recive_len;
+ data->message_recive_len = state->message_recive_len;
if (state->current_read_buf) {
- item->data.read_buf_len = state->current_read_buf->len;
- if ((vec->iov_len = item->data.read_buf_len - item->data.recive_len)) {
- vec->iov_base = state->current_read_buf->data;
- item->header.size += vec->iov_len;
- vec++;
- (*len)++;
+ data->read_buf_len = state->current_read_buf->len;
+
+ if (data->read_buf_len - data->recive_len) {
+ spice_marshaller_add_ref(item->m,
+ state->current_read_buf->data,
+ data->read_buf_len - data->recive_len);
}
} else {
- item->data.read_buf_len = 0;
+ data->read_buf_len = 0;
}
now = &state->write_queue;
- item->data.write_queue_size = 0;
+ data->write_queue_size = 0;
while ((now = ring_prev(&state->write_queue, now))) {
- item->data.write_queue_size++;
- }
- if (!item->data.write_queue_size) {
- return;
+ data->write_queue_size++;
}
- ASSERT(item->data.write_queue_size <= sizeof(item->queue_info) / sizeof(item->queue_info[0]));
- vec->iov_base = item->queue_info;
- vec->iov_len = item->data.write_queue_size * sizeof(item->queue_info[0]);
- item->header.size += vec->iov_len;
- vec++;
- (*len)++;
+ if (data->write_queue_size) {
+ WriteQueueInfo *queue_info;
- buf_index = 0;
- now = &state->write_queue;
- while ((now = ring_prev(&state->write_queue, now))) {
- VDIPortBuf *buf = (VDIPortBuf *)now;
- item->queue_info[buf_index].port = buf->chunk_header.port;
- item->queue_info[buf_index++].len = buf->write_len;
- ASSERT(vec - vec_start < REDS_MAX_SEND_IOVEC);
- vec->iov_base = buf->now;
- vec->iov_len = buf->write_len;
- item->header.size += vec->iov_len;
- vec++;
- (*len)++;
- }
-}
-
-static void main_channelrelease_migrate_data_item(RedsOutItem *in_item)
-{
- SendMainMigrateItem *item = (SendMainMigrateItem *)in_item;
- free(item);
-}
-
-static void main_channel_push_migrate_data_item()
-{
- SendMainMigrateItem *item;
+ queue_info = (WriteQueueInfo *)
+ spice_marshaller_reserve_space(item->m,
+ data->write_queue_size * sizeof(queue_info[0]));
- item = spice_new0(SendMainMigrateItem, 1);
- ring_item_init(&item->base.link);
- item->base.prepare = main_channel_send_migrate_data_item;
- item->base.release = main_channelrelease_migrate_data_item;
+ buf_index = 0;
+ now = &state->write_queue;
+ while ((now = ring_prev(&state->write_queue, now))) {
+ VDIPortBuf *buf = (VDIPortBuf *)now;
+ queue_info[buf_index].port = buf->chunk_header.port;
+ queue_info[buf_index++].len = buf->write_len;
+ spice_marshaller_add_ref(item->m, buf->now, buf->write_len);
+ }
+ }
reds_push_pipe_item((RedsOutItem *)item);
}
+
static int main_channel_restore_vdi_read_state(MainMigrateData *data, uint8_t **in_pos,
uint8_t *end)
{
@@ -1858,7 +1785,7 @@ static int reds_send_data()
} else {
outgoing->vec = reds_iovec_skip(outgoing->vec, n, &outgoing->vec_size);
if (!outgoing->vec_size) {
- outgoing->item->release(outgoing->item);
+ reds_out_item_free(outgoing->item);
outgoing->item = NULL;
outgoing->vec = outgoing->vec_buf;
return TRUE;
@@ -1870,15 +1797,22 @@ static int reds_send_data()
static void reds_push()
{
RedsOutgoingData *outgoing = &reds->outgoing;
- RingItem *item;
+ RingItem *ring_item;
+ RedsOutItem *item;
for (;;) {
- if (!reds->peer || outgoing->item || !(item = ring_get_tail(&outgoing->pipe))) {
+ if (!reds->peer || outgoing->item || !(ring_item = ring_get_tail(&outgoing->pipe))) {
return;
}
- ring_remove(item);
- outgoing->item = (RedsOutItem *)item;
- outgoing->item->prepare(outgoing->item, outgoing->vec_buf, &outgoing->vec_size);
+ ring_remove(ring_item);
+ outgoing->item = item = (RedsOutItem *)ring_item;
+
+ spice_marshaller_flush(item->m);
+ item->header->size = spice_marshaller_get_total_size(item->m) - sizeof(SpiceDataHeader);
+
+ outgoing->vec_size = spice_marshaller_fill_iovec(item->m,
+ outgoing->vec_buf,
+ REDS_MAX_SEND_IOVEC, 0);
reds_send_data();
}
}
@@ -2063,24 +1997,26 @@ static void reds_handle_main_link(RedLinkInfo *link)
reds_main_event, NULL);
if (!reds->mig_target) {
- SimpleOutItem *item;
- SpiceMsgMainInit *init;
-
- item = new_simple_out_item(SPICE_MSG_MAIN_INIT, sizeof(SpiceMsgMainInit));
- init = (SpiceMsgMainInit *)item->data;
- init->session_id = connection_id;
- init->display_channels_hint = red_dispatcher_count();
- init->current_mouse_mode = reds->mouse_mode;
- init->supported_mouse_modes = SPICE_MOUSE_MODE_SERVER;
+ RedsOutItem *item;
+ SpiceMsgMainInit init;
+
+ item = new_out_item(SPICE_MSG_MAIN_INIT);
+ init.session_id = connection_id;
+ init.display_channels_hint = red_dispatcher_count();
+ init.current_mouse_mode = reds->mouse_mode;
+ init.supported_mouse_modes = SPICE_MOUSE_MODE_SERVER;
if (reds->is_client_mouse_allowed) {
- init->supported_mouse_modes |= SPICE_MOUSE_MODE_CLIENT;
+ init.supported_mouse_modes |= SPICE_MOUSE_MODE_CLIENT;
}
- init->agent_connected = !!vdagent;
- init->agent_tokens = REDS_AGENT_WINDOW_SIZE;
+ init.agent_connected = !!vdagent;
+ init.agent_tokens = REDS_AGENT_WINDOW_SIZE;
reds->agent_state.num_client_tokens = REDS_AGENT_WINDOW_SIZE;
- init->multi_media_time = reds_get_mm_time() - MM_TIME_DELTA;
- init->ram_hint = red_dispatcher_qxl_ram_size();
- reds_push_pipe_item(&item->base);
+ init.multi_media_time = reds_get_mm_time() - MM_TIME_DELTA;
+ init.ram_hint = red_dispatcher_qxl_ram_size();
+
+ spice_marshall_msg_main_init(item->m, &init);
+
+ reds_push_pipe_item(item);
reds_start_net_test();
}
}
@@ -2516,25 +2452,23 @@ static void reds_handle_other_links(RedLinkInfo *link)
reds_send_link_result(link, SPICE_LINK_ERR_OK);
reds_show_new_channel(link);
if (link_mess->channel_type == SPICE_CHANNEL_INPUTS && !link->peer->ssl) {
- SimpleOutItem *item;
- SpiceMsgNotify *notify;
+ RedsOutItem *item;
+ SpiceMsgNotify notify;
char *mess = "keyboard channel is insecure";
const int mess_len = strlen(mess);
- if (!(item = new_simple_out_item(SPICE_MSG_NOTIFY, sizeof(SpiceMsgNotify) + mess_len + 1))) {
- red_printf("alloc item failed");
- reds_disconnect();
- return;
- }
+ item = new_out_item(SPICE_MSG_NOTIFY);
+
+ notify.time_stamp = get_time_stamp();
+ notify.severity = SPICE_NOTIFY_SEVERITY_WARN;
+ notify.visibilty = SPICE_NOTIFY_VISIBILITY_HIGH;
+ notify.what = SPICE_WARN_GENERAL;
+ notify.message_len = mess_len;
- notify = (SpiceMsgNotify *)item->data;
- notify->time_stamp = get_time_stamp();
- notify->severity = SPICE_NOTIFY_SEVERITY_WARN;
- notify->visibilty = SPICE_NOTIFY_VISIBILITY_HIGH;
- notify->what = SPICE_WARN_GENERAL;
- notify->message_len = mess_len;
- memcpy(notify->message, mess, mess_len + 1);
- reds_push_pipe_item(&item->base);
+ spice_marshall_msg_notify(item->m, ¬ify);
+ spice_marshaller_add(item->m, (uint8_t *)mess, mess_len + 1);
+
+ reds_push_pipe_item(item);
}
peer = link->peer;
link->link_mess = NULL;
@@ -3220,25 +3154,26 @@ typedef struct RedsMigCertPubKeyInfo {
static void reds_mig_continue(void)
{
RedsMigSpice *s = reds->mig_spice;
- SpiceMsgMainMigrationBegin *migrate;
- SimpleOutItem *item;
+ SpiceMsgMainMigrationBegin migrate;
+ RedsOutItem *item;
int host_len;
red_printf("");
host_len = strlen(s->host) + 1;
- item = new_simple_out_item(SPICE_MSG_MAIN_MIGRATE_BEGIN,
- sizeof(SpiceMsgMainMigrationBegin) + host_len + s->cert_pub_key_len);
- migrate = (SpiceMsgMainMigrationBegin *)item->data;
- migrate->port = s->port;
- migrate->sport = s->sport;
- migrate->host_offset = sizeof(SpiceMsgMainMigrationBegin);
- migrate->host_size = host_len;
- migrate->pub_key_type = s->cert_pub_key_type;
- migrate->pub_key_offset = sizeof(SpiceMsgMainMigrationBegin) + host_len;
- migrate->pub_key_size = s->cert_pub_key_len;
- memcpy((uint8_t*)(migrate) + migrate->host_offset , s->host, host_len);
- memcpy((uint8_t*)(migrate) + migrate->pub_key_offset, s->cert_pub_key, s->cert_pub_key_len);
- reds_push_pipe_item(&item->base);
+ item = new_out_item(SPICE_MSG_MAIN_MIGRATE_BEGIN);
+
+ migrate.port = s->port;
+ migrate.sport = s->sport;
+ migrate.host_offset = sizeof(SpiceMsgMainMigrationBegin);
+ migrate.host_size = host_len;
+ migrate.pub_key_type = s->cert_pub_key_type;
+ migrate.pub_key_offset = sizeof(SpiceMsgMainMigrationBegin) + host_len;
+ migrate.pub_key_size = s->cert_pub_key_len;
+ spice_marshall_msg_main_migrate_begin(item->m, &migrate);
+ spice_marshaller_add(item->m, (uint8_t *)s->host, host_len);
+ spice_marshaller_add(item->m, s->cert_pub_key, s->cert_pub_key_len);
+
+ reds_push_pipe_item(item);
free(reds->mig_spice->host);
free(reds->mig_spice);
@@ -3287,7 +3222,7 @@ error:
static void reds_mig_finished(int completed)
{
- SimpleOutItem *item;
+ RedsOutItem *item;
red_printf("");
if (reds->listen_watch != NULL) {
@@ -3306,23 +3241,24 @@ static void reds_mig_finished(int completed)
if (completed) {
Channel *channel;
- SpiceMsgMigrate *migrate;
+ SpiceMsgMigrate migrate;
reds->mig_wait_disconnect = TRUE;
core->timer_start(reds->mig_timer, MIGRATE_TIMEOUT);
- item = new_simple_out_item(SPICE_MSG_MIGRATE, sizeof(SpiceMsgMigrate));
- migrate = (SpiceMsgMigrate *)item->data;
- migrate->flags = SPICE_MIGRATE_NEED_FLUSH | SPICE_MIGRATE_NEED_DATA_TRANSFER;
- reds_push_pipe_item(&item->base);
+ item = new_out_item(SPICE_MSG_MIGRATE);
+ migrate.flags = SPICE_MIGRATE_NEED_FLUSH | SPICE_MIGRATE_NEED_DATA_TRANSFER;
+ spice_marshall_msg_migrate(item->m, &migrate);
+
+ reds_push_pipe_item(item);
channel = reds->channels;
while (channel) {
channel->migrate(channel);
channel = channel->next;
}
} else {
- item = new_simple_out_item(SPICE_MSG_MAIN_MIGRATE_CANCEL, 0);
- reds_push_pipe_item(&item->base);
+ item = new_out_item(SPICE_MSG_MAIN_MIGRATE_CANCEL);
+ reds_push_pipe_item(item);
reds_mig_cleanup();
}
}
@@ -3353,22 +3289,18 @@ void reds_update_mm_timer(uint32_t mm_time)
void reds_enable_mm_timer()
{
- SpiceMsgMainMultiMediaTime *time_mes;
- SimpleOutItem *item;
+ SpiceMsgMainMultiMediaTime time_mes;
+ RedsOutItem *item;
core->timer_start(reds->mm_timer, MM_TIMER_GRANULARITY_MS);
if (!reds->peer) {
return;
}
- if (!(item = new_simple_out_item(SPICE_MSG_MAIN_MULTI_MEDIA_TIME, sizeof(SpiceMsgMainMultiMediaTime)))) {
- red_printf("alloc item failed");
- reds_disconnect();
- return;
- }
- time_mes = (SpiceMsgMainMultiMediaTime *)item->data;
- time_mes->time = reds_get_mm_time() - MM_TIME_DELTA;
- reds_push_pipe_item(&item->base);
+ item = new_out_item(SPICE_MSG_MAIN_MULTI_MEDIA_TIME);
+ time_mes.time = reds_get_mm_time() - MM_TIME_DELTA;
+ spice_marshall_msg_main_multi_media_time(item->m, &time_mes);
+ reds_push_pipe_item(item);
}
void reds_desable_mm_timer()
@@ -3584,25 +3516,6 @@ static void free_internal_agent_buff(VDIPortBuf *in_buf)
}
}
-void reds_prepare_read_buf(RedsOutItem *in_nuf, struct iovec* vec, int *len)
-{
- VDIReadBuf *buf = (VDIReadBuf *)in_nuf;
-
- vec[0].iov_base = &buf->header;
- vec[0].iov_len = sizeof(buf->header);
- vec[1].iov_base = buf->data;
- vec[1].iov_len = buf->len;
- *len = 2;
-}
-
-void reds_release_read_buf(RedsOutItem *in_nuf)
-{
- VDIReadBuf *buf = (VDIReadBuf *)in_nuf;
-
- ring_add(&reds->agent_state.read_bufs, &buf->out_item.link);
- read_from_vdi_port();
-}
-
static void init_vd_agent_resources()
{
VDIPortState *state = &reds->agent_state;
@@ -3640,12 +3553,8 @@ static void init_vd_agent_resources()
for (i = 0; i < REDS_VDI_PORT_NUM_RECIVE_BUFFS; i++) {
VDIReadBuf *buf = spice_new0(VDIReadBuf, 1);
- buf->out_item.prepare = reds_prepare_read_buf;
- buf->out_item.release = reds_release_read_buf;
- buf->header.type = SPICE_MSG_MAIN_AGENT_DATA;
- buf->header.sub_list = 0;
- ring_item_init(&buf->out_item.link);
- ring_add(&reds->agent_state.read_bufs, &buf->out_item.link);
+ ring_item_init(&buf->link);
+ ring_add(&reds->agent_state.read_bufs, &buf->link);
}
}
commit 8418da7ab24eb46547543a886d798759f39891f1
Author: Alexander Larsson <alexl at redhat.com>
Date: Tue Jun 15 17:36:04 2010 +0200
Convert snd_worker.c to use SpiceMarshaller and generated marshallers
diff --git a/server/snd_worker.c b/server/snd_worker.c
index 2deb8a3..cd9af97 100644
--- a/server/snd_worker.c
+++ b/server/snd_worker.c
@@ -1,3 +1,4 @@
+/* -*- Mode: C; c-basic-offset: 4; indent-tabs-mode: nil -*- */
/*
Copyright (C) 2009 Red Hat, Inc.
@@ -27,9 +28,10 @@
#include "reds.h"
#include "red_dispatcher.h"
#include "snd_worker.h"
+#include "marshaller.h"
+#include "generated_marshallers.h"
#define MAX_SEND_VEC 100
-#define MAX_SEND_BUFS 200
#define RECIVE_BUF_SIZE (16 * 1024 * 2)
@@ -61,11 +63,6 @@ enum RecordCommand {
#define SND_RECORD_MIGRATE_MASK (1 << SND_RECORD_MIGRATE)
#define SND_RECORD_CTRL_MASK (1 << SND_RECORD_CTRL)
-typedef struct BufDescriptor {
- uint32_t size;
- uint8_t *data;
-} BufDescriptor;
-
typedef struct SndChannel SndChannel;
typedef void (*send_messages_proc)(void *in_channel);
typedef int (*handle_message_proc)(SndChannel *channel, SpiceDataHeader *message);
@@ -90,10 +87,9 @@ struct SndChannel {
uint32_t ack_messages;
struct {
- SpiceDataHeader header;
- uint32_t n_bufs;
- BufDescriptor bufs[MAX_SEND_BUFS];
-
+ uint64_t serial;
+ SpiceDataHeader *header;
+ SpiceMarshaller *marshaller;
uint32_t size;
uint32_t pos;
} send_data;
@@ -129,12 +125,7 @@ typedef struct PlaybackChannel {
int celt_allowed;
uint32_t mode;
struct {
- union {
- SpiceMsgPlaybackMode mode;
- SpiceMsgPlaybackStart start;
- SpiceMsgMigrate migrate;
- uint8_t celt_buf[CELT_COMPRESSED_FRAME_BYTES];
- } u;
+ uint8_t celt_buf[CELT_COMPRESSED_FRAME_BYTES];
} send_data;
} PlaybackChannel;
@@ -165,12 +156,6 @@ typedef struct __attribute__ ((__packed__)) RecordMigrateData {
uint32_t mode_time;
} RecordMigrateData;
-typedef struct __attribute__ ((__packed__)) RecordMigrateMessage {
- SpiceMsgMigrate migrate;
- SpiceDataHeader header;
- RecordMigrateData data;
-} RecordMigrateMessage;
-
typedef struct RecordChannel {
SndChannel base;
uint32_t samples[RECORD_SAMPLES_SIZE];
@@ -182,12 +167,6 @@ typedef struct RecordChannel {
CELTDecoder *celt_decoder;
CELTMode *celt_mode;
uint32_t celt_buf[FRAME_SIZE];
- struct {
- union {
- SpiceMsgRecordStart start;
- RecordMigrateMessage migrate;
- } u;
- } send_data;
} RecordChannel;
static SndWorker *workers = NULL;
@@ -195,46 +174,6 @@ static uint32_t playback_compression = SPICE_AUDIO_DATA_MODE_CELT_0_5_1;
static void snd_receive(void* data);
-static inline BufDescriptor *snd_find_buf(SndChannel *channel, int buf_pos, int *buf_offset)
-{
- BufDescriptor *buf;
- int pos = 0;
-
- for (buf = channel->send_data.bufs; buf_pos >= pos + buf->size; buf++) {
- pos += buf->size;
- ASSERT(buf != &channel->send_data.bufs[channel->send_data.n_bufs - 1]);
- }
- *buf_offset = buf_pos - pos;
- return buf;
-}
-
-static inline uint32_t __snd_fill_iovec(BufDescriptor *buf, int skip, struct iovec *vec,
- int *vec_index, long phys_delta)
-{
- uint32_t size = 0;
- vec[*vec_index].iov_base = buf->data + skip;
- vec[*vec_index].iov_len = size = buf->size - skip;
- (*vec_index)++;
- return size;
-}
-
-static inline void snd_fill_iovec(SndChannel *channel, struct iovec *vec, int *vec_size)
-{
- int vec_index = 0;
- uint32_t pos = channel->send_data.pos;
- ASSERT(channel->send_data.size != pos && channel->send_data.size > pos);
-
- do {
- BufDescriptor *buf;
- int buf_offset;
-
- buf = snd_find_buf(channel, pos, &buf_offset);
- ASSERT(buf);
- pos += __snd_fill_iovec(buf, buf_offset, vec, &vec_index, 0);
- } while (vec_index < MAX_SEND_VEC && pos != channel->send_data.size);
- *vec_size = vec_index;
-}
-
static void snd_disconnect_channel(SndChannel *channel)
{
SndWorker *worker;
@@ -248,6 +187,7 @@ static void snd_disconnect_channel(SndChannel *channel)
core->watch_remove(channel->peer->watch);
channel->peer->watch = NULL;
channel->peer->cb_free(channel->peer);
+ spice_marshaller_destroy(channel->send_data.marshaller);
free(channel);
}
@@ -299,7 +239,8 @@ static int snd_send_data(SndChannel *channel)
break;
}
- snd_fill_iovec(channel, vec, &vec_size);
+ vec_size = spice_marshaller_fill_iovec(channel->send_data.marshaller,
+ vec, MAX_SEND_VEC, channel->send_data.pos);
if ((n = channel->peer->cb_writev(channel->peer->ctx, vec, vec_size)) == -1) {
switch (errno) {
case EAGAIN:
@@ -506,76 +447,75 @@ static void snd_event(int fd, int event, void *data)
}
}
-static inline void __snd_add_buf(SndChannel *channel, void *data, uint32_t size)
-{
- int pos = channel->send_data.n_bufs++;
- ASSERT(pos < MAX_SEND_BUFS);
- channel->send_data.bufs[pos].size = size;
- channel->send_data.bufs[pos].data = data;
-}
-
-static void snd_add_buf(SndChannel *channel, void *data, uint32_t size)
-{
- __snd_add_buf(channel, data, size);
- channel->send_data.header.size += size;
-}
-
static inline int snd_reset_send_data(SndChannel *channel, uint16_t verb)
{
if (!channel) {
return FALSE;
}
+ spice_marshaller_reset(channel->send_data.marshaller);
+ channel->send_data.header = (SpiceDataHeader *)
+ spice_marshaller_reserve_space(channel->send_data.marshaller, sizeof(SpiceDataHeader));
+ spice_marshaller_set_base(channel->send_data.marshaller, sizeof(SpiceDataHeader));
channel->send_data.pos = 0;
- channel->send_data.n_bufs = 0;
- channel->send_data.header.sub_list = 0;
- channel->send_data.header.size = 0;
- channel->send_data.header.type = verb;
- ++channel->send_data.header.serial;
- __snd_add_buf(channel, &channel->send_data.header, sizeof(SpiceDataHeader));
+ channel->send_data.header->sub_list = 0;
+ channel->send_data.header->size = 0;
+ channel->send_data.header->type = verb;
+ channel->send_data.header->serial = ++channel->send_data.serial;
return TRUE;
}
+static int snd_begin_send_message(SndChannel *channel)
+{
+ spice_marshaller_flush(channel->send_data.marshaller);
+ channel->send_data.size = spice_marshaller_get_total_size(channel->send_data.marshaller);
+ channel->send_data.header->size = channel->send_data.size - sizeof(SpiceDataHeader);
+ channel->send_data.header = NULL; /* avoid writing to this until we have a new message */
+ return snd_send_data(channel);
+}
+
+
static int snd_playback_send_migrate(PlaybackChannel *channel)
{
+ SpiceMsgMigrate migrate;
+
if (!snd_reset_send_data((SndChannel *)channel, SPICE_MSG_MIGRATE)) {
return FALSE;
}
- channel->send_data.u.migrate.flags = 0;
- snd_add_buf((SndChannel *)channel, &channel->send_data.u.migrate,
- sizeof(channel->send_data.u.migrate));
- channel->base.send_data.size = channel->base.send_data.header.size + sizeof(SpiceDataHeader);
- return snd_send_data((SndChannel *)channel);
+ migrate.flags = 0;
+ spice_marshall_msg_migrate(channel->base.send_data.marshaller, &migrate);
+
+ return snd_begin_send_message((SndChannel *)channel);
}
static int snd_playback_send_start(PlaybackChannel *playback_channel)
{
SndChannel *channel = (SndChannel *)playback_channel;
- SpiceMsgPlaybackStart *start;
+ SpiceMsgPlaybackStart start;
+
if (!snd_reset_send_data(channel, SPICE_MSG_PLAYBACK_START)) {
return FALSE;
}
- start = &playback_channel->send_data.u.start;
- start->channels = SPICE_INTERFACE_PLAYBACK_CHAN;
- start->frequency = SPICE_INTERFACE_PLAYBACK_FREQ;
+ start.channels = SPICE_INTERFACE_PLAYBACK_CHAN;
+ start.frequency = SPICE_INTERFACE_PLAYBACK_FREQ;
ASSERT(SPICE_INTERFACE_PLAYBACK_FMT == SPICE_INTERFACE_AUDIO_FMT_S16);
- start->format = SPICE_AUDIO_FMT_S16;
- start->time = reds_get_mm_time();
- snd_add_buf(channel, start, sizeof(*start));
+ start.format = SPICE_AUDIO_FMT_S16;
+ start.time = reds_get_mm_time();
+ spice_marshall_msg_playback_start(channel->send_data.marshaller, &start);
- channel->send_data.size = sizeof(SpiceDataHeader) + sizeof(*start);
- return snd_send_data(channel);
+ return snd_begin_send_message(channel);
}
static int snd_playback_send_stop(PlaybackChannel *playback_channel)
{
SndChannel *channel = (SndChannel *)playback_channel;
+
if (!snd_reset_send_data(channel, SPICE_MSG_PLAYBACK_STOP)) {
return FALSE;
}
- channel->send_data.size = sizeof(SpiceDataHeader);
- return snd_send_data(channel);
+
+ return snd_begin_send_message(channel);
}
static int snd_playback_send_ctl(PlaybackChannel *playback_channel)
@@ -592,30 +532,30 @@ static int snd_playback_send_ctl(PlaybackChannel *playback_channel)
static int snd_record_send_start(RecordChannel *record_channel)
{
SndChannel *channel = (SndChannel *)record_channel;
- SpiceMsgRecordStart *start;
+ SpiceMsgRecordStart start;
+
if (!snd_reset_send_data(channel, SPICE_MSG_RECORD_START)) {
return FALSE;
}
- start = &record_channel->send_data.u.start;
- start->channels = SPICE_INTERFACE_RECORD_CHAN;
- start->frequency = SPICE_INTERFACE_RECORD_FREQ;
+ start.channels = SPICE_INTERFACE_RECORD_CHAN;
+ start.frequency = SPICE_INTERFACE_RECORD_FREQ;
ASSERT(SPICE_INTERFACE_RECORD_FMT == SPICE_INTERFACE_AUDIO_FMT_S16);
- start->format = SPICE_AUDIO_FMT_S16;
- snd_add_buf(channel, start, sizeof(*start));
+ start.format = SPICE_AUDIO_FMT_S16;
+ spice_marshall_msg_record_start(channel->send_data.marshaller, &start);
- channel->send_data.size = sizeof(SpiceDataHeader) + sizeof(*start);
- return snd_send_data(channel);
+ return snd_begin_send_message(channel);
}
static int snd_record_send_stop(RecordChannel *record_channel)
{
SndChannel *channel = (SndChannel *)record_channel;
+
if (!snd_reset_send_data(channel, SPICE_MSG_RECORD_STOP)) {
return FALSE;
}
- channel->send_data.size = sizeof(SpiceDataHeader);
- return snd_send_data(channel);
+
+ return snd_begin_send_message(channel);
}
static int snd_record_send_ctl(RecordChannel *record_channel)
@@ -632,29 +572,35 @@ static int snd_record_send_ctl(RecordChannel *record_channel)
static int snd_record_send_migrate(RecordChannel *record_channel)
{
SndChannel *channel = (SndChannel *)record_channel;
- RecordMigrateMessage* migrate;
+ SpiceMsgMigrate migrate;
+ SpiceDataHeader *header;
+ RecordMigrateData *data;
if (!snd_reset_send_data(channel, SPICE_MSG_MIGRATE)) {
return FALSE;
}
- migrate = &record_channel->send_data.u.migrate;
- migrate->migrate.flags = SPICE_MIGRATE_NEED_DATA_TRANSFER;
- migrate->header.type = SPICE_MSG_MIGRATE_DATA;
- migrate->header.size = sizeof(RecordMigrateData);
- migrate->header.serial = ++channel->send_data.header.serial;
- migrate->header.sub_list = 0;
+ migrate.flags = SPICE_MIGRATE_NEED_DATA_TRANSFER;
+ spice_marshall_msg_migrate(channel->send_data.marshaller, &migrate);
+
+ header = (SpiceDataHeader *)spice_marshaller_reserve_space(channel->send_data.marshaller,
+ sizeof(SpiceDataHeader));
+ header->type = SPICE_MSG_MIGRATE_DATA;
+ header->size = sizeof(RecordMigrateData);
+ header->serial = ++channel->send_data.serial;
+ header->sub_list = 0;
- migrate->data.version = RECORD_MIG_VERSION;
- migrate->data.serial = channel->send_data.header.serial;
- migrate->data.start_time = record_channel->start_time;
- migrate->data.mode = record_channel->mode;
- migrate->data.mode_time = record_channel->mode_time;
+ data = (RecordMigrateData *)spice_marshaller_reserve_space(channel->send_data.marshaller,
+ sizeof(RecordMigrateData));
+ data->version = RECORD_MIG_VERSION;
+ data->serial = channel->send_data.serial;
+ data->start_time = record_channel->start_time;
+ data->mode = record_channel->mode;
+ data->mode_time = record_channel->mode_time;
+
+ channel->send_data.size = spice_marshaller_get_total_size(channel->send_data.marshaller);
+ channel->send_data.header->size = channel->send_data.size - sizeof(SpiceDataHeader) - sizeof(SpiceDataHeader) - sizeof(*data);
- snd_add_buf(channel, migrate, sizeof(*migrate));
- channel->send_data.size = channel->send_data.header.size + sizeof(SpiceDataHeader);
- channel->send_data.header.size -= sizeof(migrate->header);
- channel->send_data.header.size -= sizeof(migrate->data);
return snd_send_data(channel);
}
@@ -662,46 +608,48 @@ static int snd_playback_send_write(PlaybackChannel *playback_channel)
{
SndChannel *channel = (SndChannel *)playback_channel;
AudioFrame *frame;
+ SpiceMsgPlaybackPacket msg;
if (!snd_reset_send_data(channel, SPICE_MSG_PLAYBACK_DATA)) {
return FALSE;
}
frame = playback_channel->in_progress;
- snd_add_buf(channel, &frame->time, sizeof(frame->time));
+ msg.time = frame->time;
+
+ spice_marshall_msg_playback_data(channel->send_data.marshaller, &msg);
+
if (playback_channel->mode == SPICE_AUDIO_DATA_MODE_CELT_0_5_1) {
int n = celt051_encode(playback_channel->celt_encoder, (celt_int16_t *)frame->samples, NULL,
- playback_channel->send_data.u.celt_buf, CELT_COMPRESSED_FRAME_BYTES);
+ playback_channel->send_data.celt_buf, CELT_COMPRESSED_FRAME_BYTES);
if (n < 0) {
red_printf("celt encode failed");
snd_disconnect_channel(channel);
return FALSE;
}
- snd_add_buf(channel, playback_channel->send_data.u.celt_buf, n);
+ spice_marshaller_add_ref(channel->send_data.marshaller,
+ playback_channel->send_data.celt_buf, n);
} else {
- snd_add_buf(channel, frame->samples, sizeof(frame->samples));
+ spice_marshaller_add_ref(channel->send_data.marshaller,
+ (uint8_t *)frame->samples, sizeof(frame->samples));
}
- channel->send_data.size = channel->send_data.header.size + sizeof(SpiceDataHeader);
-
- return snd_send_data(channel);
+ return snd_begin_send_message(channel);
}
static int playback_send_mode(PlaybackChannel *playback_channel)
{
SndChannel *channel = (SndChannel *)playback_channel;
- SpiceMsgPlaybackMode *mode;
+ SpiceMsgPlaybackMode mode;
if (!snd_reset_send_data(channel, SPICE_MSG_PLAYBACK_MODE)) {
return FALSE;
}
- mode = &playback_channel->send_data.u.mode;
- mode->time = reds_get_mm_time();
- mode->mode = playback_channel->mode;
- snd_add_buf(channel, mode, sizeof(*mode));
+ mode.time = reds_get_mm_time();
+ mode.mode = playback_channel->mode;
+ spice_marshall_msg_playback_mode(channel->send_data.marshaller, &mode);
- channel->send_data.size = channel->send_data.header.size + sizeof(SpiceDataHeader);
- return snd_send_data(channel);
+ return snd_begin_send_message(channel);
}
static void snd_playback_send(void* data)
@@ -815,6 +763,7 @@ static SndChannel *__new_channel(SndWorker *worker, int size, RedsStreamContext
channel->recive_data.message = (SpiceDataHeader *)channel->recive_data.buf;
channel->recive_data.now = channel->recive_data.buf;
channel->recive_data.end = channel->recive_data.buf + sizeof(channel->recive_data.buf);
+ channel->send_data.marshaller = spice_marshaller_new();
peer->watch = core->watch_add(peer->socket, SPICE_WATCH_EVENT_READ,
snd_event, channel);
commit cfc86f33409ad1e401ad9107d51aba68123971ec
Author: Alexander Larsson <alexl at redhat.com>
Date: Fri Jun 11 17:18:33 2010 +0200
Convert red_worker.c to use SpiceMarshaller for marshalling
diff --git a/server/red_worker.c b/server/red_worker.c
index efdfebc..80abb7c 100644
--- a/server/red_worker.c
+++ b/server/red_worker.c
@@ -50,6 +50,8 @@
#include "red_memslots.h"
#include "jpeg_encoder.h"
#include "rect.h"
+#include "marshaller.h"
+#include "generated_marshallers.h"
//#define COMPRESS_STAT
//#define DUMP_BITMAP
@@ -71,7 +73,6 @@
#define DISPLAY_CLIENT_TIMEOUT 15000000000ULL //nano
#define DISPLAY_CLIENT_RETRY_INTERVAL 10000 //micro
-#define DISPLAY_MAX_SUB_MESSAGES 10
#define DISPLAY_FREE_LIST_DEFAULT_SIZE 128
@@ -213,7 +214,6 @@ struct EventListener {
enum {
BUF_TYPE_RAW = 1,
- BUF_TYPE_COMPRESS_BUF,
BUF_TYPE_CHUNK,
};
@@ -318,7 +318,6 @@ typedef struct LocalCursor {
SpiceCursor red_cursor;
} LocalCursor;
-#define MAX_SEND_BUFS 20
#define MAX_BITMAPS 4
#define MAX_PIPE_SIZE 50
#define RECIVE_BUF_SIZE 1024
@@ -368,12 +367,9 @@ struct RedChannel {
struct {
int blocked;
- SpiceDataHeader header;
- union {
- SpiceMsgSetAck ack;
- } u;
- uint32_t n_bufs;
- BufDescriptor bufs[MAX_SEND_BUFS];
+ uint64_t serial;
+ SpiceDataHeader *header;
+ SpiceMarshaller *marshaller;
uint32_t size;
uint32_t pos;
void *item;
@@ -662,51 +658,12 @@ struct DisplayChannel {
QRegion surface_client_lossy_region[NUM_SURFACES];
struct {
- union {
- SpiceMsgDisplayDrawFill fill;
- SpiceMsgDisplayDrawOpaque opaque;
- SpiceMsgDisplayDrawCopy copy;
- SpiceMsgDisplayDrawTransparent transparent;
- SpiceMsgDisplayDrawAlphaBlend alpha_blend;
- SpiceMsgDisplayCopyBits copy_bits;
- SpiceMsgDisplayDrawBlend blend;
- SpiceMsgDisplayDrawRop3 rop3;
- SpiceMsgDisplayDrawBlackness blackness;
- SpiceMsgDisplayDrawWhiteness whiteness;
- SpiceMsgDisplayDrawInvers invers;
- SpiceMsgDisplayDrawStroke stroke;
- SpiceMsgDisplayDrawText text;
- SpiceMsgDisplayMode mode;
- SpiceMsgDisplayInvalOne inval_one;
- SpiceMsgSurfaceCreate surface_create;
- SpiceMsgSurfaceDestroy surface_destroy;
- WaitForChannels wait;
- struct {
- SpiceMsgDisplayStreamCreate message;
- uint32_t num_rects;
- } stream_create;
- SpiceMsgDisplayStreamClip stream_clip;
- SpiceMsgDisplayStreamData stream_data;
- SpiceMsgDisplayStreamDestroy stream_destroy;
- SpiceMsgMigrate migrate;
- DisplayChannelMigrateData migrate_data;
- } u;
-
- uint32_t bitmap_pos;
- RedImage images[MAX_BITMAPS];
-
uint32_t stream_outbuf_size;
uint8_t *stream_outbuf; // caution stream buffer is also used as compress bufs!!!
RedCompressBuf *free_compress_bufs;
RedCompressBuf *used_compress_bufs;
- struct {
- SpiceSubMessageList sub_list;
- uint32_t sub_messages[DISPLAY_MAX_SUB_MESSAGES];
- } sub_list;
- SpicedSubMessage sub_header[DISPLAY_MAX_SUB_MESSAGES];
-
FreeList free_list;
} send_data;
@@ -734,16 +691,6 @@ typedef struct CursorChannel {
long cursor_cache_available;
uint32_t cursor_cache_items;
- struct {
- union {
- SpiceMsgCursorInit cursor_init;
- SpiceMsgCursorSet cursor_set;
- SpiceMsgCursorMove cursor_move;
- SpiceMsgCursorTrail cursor_trail;
- SpiceMsgDisplayInvalOne inval_one;
- SpiceMsgMigrate migrate;
- } u;
- } send_data;
#ifdef RED_STATISTICS
StatNodeRef stat;
#endif
@@ -1403,7 +1350,7 @@ static inline void red_pipe_add_image_item_after(RedWorker *worker, ImageItem *i
static inline uint64_t channel_message_serial(RedChannel *channel)
{
- return channel->send_data.header.serial;
+ return channel->send_data.header->serial;
}
static void release_image_item(ImageItem *item)
@@ -5082,7 +5029,7 @@ static int red_process_commands(RedWorker *worker, uint32_t max_pipe_size)
}
n++;
if ((worker->display_channel && worker->display_channel->base.send_data.blocked) ||
- red_now() - start > 10 * 1000 * 1000) {
+ red_now() - start > 10 * 1000 * 1000) {
worker->epoll_timeout = 0;
return n;
}
@@ -5204,100 +5151,226 @@ static void red_add_surface_image(RedWorker *worker, int surface_id)
display_channel_push(worker);
}
-static void inline __add_buf(RedChannel *channel, uint32_t type, void *data, uint32_t size,
- uint32_t slot_id, uint32_t group_id)
+static uint8_t *chunk_linearize(RedWorker *worker, QXLDataChunk *first_chunk,
+ int memslot_id, uint32_t group_id, size_t expected_size,
+ int *free_chunk)
{
- int pos = channel->send_data.n_bufs++;
- ASSERT(pos < MAX_SEND_BUFS);
- channel->send_data.bufs[pos].type = type;
- channel->send_data.bufs[pos].size = size;
- channel->send_data.bufs[pos].data = data;
- channel->send_data.bufs[pos].slot_id = slot_id;
- channel->send_data.bufs[pos].group_id = group_id;
+ uint8_t *data, *ptr;
+ QXLDataChunk *chunk;
+ int data_size;
+ QXLPHYSICAL next_chunk;
+
+ data_size = first_chunk->data_size;
+ next_chunk = first_chunk->next_chunk;
+
+ if (next_chunk == 0) {
+ ASSERT(expected_size <= data_size);
+ validate_virt(&worker->mem_slots, (unsigned long)first_chunk->data, memslot_id, data_size, group_id);
+ *free_chunk = FALSE;
+ return first_chunk->data;
+ }
+
+ data = spice_malloc(expected_size);
+ *free_chunk = TRUE;
+
+ ptr = data;
+ chunk = first_chunk;
+ while (chunk != NULL && expected_size > 0) {
+ data_size = chunk->data_size;
+ next_chunk = chunk->next_chunk;
+
+ if (data_size > expected_size) {
+ data_size = expected_size;
+ }
+ expected_size -= data_size;
+
+ if (data_size) {
+ validate_virt(&worker->mem_slots, (unsigned long)chunk->data, memslot_id, data_size, group_id);
+ memcpy(ptr, chunk->data, data_size);
+ ptr += data_size;
+ }
+
+ chunk = next_chunk ?
+ (QXLDataChunk *)get_virt(&worker->mem_slots, next_chunk, sizeof(QXLDataChunk),
+ group_id) :
+ NULL;
+ }
+ ASSERT(expected_size == 0)
+
+ return data;
+}
+
+typedef struct {
+ uint32_t type;
+ void *data;
+ uint32_t size;
+ uint32_t slot_id;
+ uint32_t group_id;
+} AddBufInfo;
+
+static void marshaller_add_compressed(RedWorker *worker, SpiceMarshaller *m,
+ RedCompressBuf *comp_buf, size_t size)
+{
+ size_t max = size;
+ size_t now;
+ do {
+ ASSERT(comp_buf);
+ now = MIN(sizeof(comp_buf->buf), max);
+ max -= now;
+ spice_marshaller_add_ref(m, (uint8_t*)comp_buf->buf, now);
+ comp_buf = comp_buf->send_next;
+ } while (max);
}
-static void add_buf(RedChannel *channel, uint32_t type, void *data, uint32_t size,
- uint32_t slot_id, uint32_t group_id)
+static void marshaller_add_chunk(RedWorker *worker, SpiceMarshaller *m, QXLDataChunk *chunk, size_t size,
+ int memslot_id, uint32_t group_id)
{
- __add_buf(channel, type, data, size, slot_id, group_id);
- channel->send_data.header.size += size;
+ while (chunk != NULL && size > 0) {
+ int data_size = chunk->data_size;
+
+ if (data_size > size)
+ data_size = size;
+ size -= data_size;
+
+ if (data_size) {
+ validate_virt(&worker->mem_slots, (unsigned long)chunk->data, memslot_id, data_size, group_id);
+ spice_marshaller_add_ref(m, (uint8_t *)chunk->data, data_size);
+ }
+ chunk = chunk->next_chunk ?
+ (QXLDataChunk *)get_virt(&worker->mem_slots, chunk->next_chunk, sizeof(QXLDataChunk),
+ group_id) :
+ NULL;
+ }
}
-static void fill_path(DisplayChannel *display_channel, QXLPHYSICAL *in_path, uint32_t group_id)
+static void add_buf_from_info(RedChannel *channel, SpiceMarshaller *m, AddBufInfo *info)
+{
+ QXLDataChunk *chunk;
+
+ if (info->data) {
+ switch (info->type) {
+ case BUF_TYPE_RAW:
+ spice_marshaller_add_ref(m, info->data, info->size);
+ break;
+ case BUF_TYPE_CHUNK:
+ chunk = (QXLDataChunk *)info->data;
+ marshaller_add_chunk(channel->worker, m, chunk,
+ info->size, info->slot_id, info->group_id);
+ break;
+ }
+ }
+}
+
+
+static void fill_path(DisplayChannel *display_channel, SpiceMarshaller *m,
+ QXLPHYSICAL in_path, uint32_t group_id)
{
RedWorker *worker;
RedChannel *channel = &display_channel->base;
int memslot_id;
+ uint8_t *path_data, *p;
+ int free_path_data;
worker = channel->worker;
- ASSERT(in_path && *in_path);
- memslot_id = get_memslot_id(&worker->mem_slots, *in_path);
- QXLPath *path = (QXLPath *)get_virt(&worker->mem_slots, *in_path, sizeof(QXLPath), group_id);
- *in_path = channel->send_data.header.size;
- add_buf(channel, BUF_TYPE_RAW, &path->data_size, sizeof(uint32_t), 0, 0);
- add_buf(channel, BUF_TYPE_CHUNK, &path->chunk, path->data_size, memslot_id, group_id);
+ size_t data_size;
+ ASSERT(in_path);
+ memslot_id = get_memslot_id(&worker->mem_slots, in_path);
+
+ QXLPath *path = (QXLPath *)get_virt(&worker->mem_slots, in_path, sizeof(QXLPath), group_id);
+
+ data_size = path->data_size;
+ spice_marshaller_add_uint32(m, data_size);
+ path_data = chunk_linearize(worker, &path->chunk,
+ memslot_id, group_id, data_size,
+ &free_path_data);
+
+ p = path_data;
+ while (p < path_data + data_size) {
+ p = spice_marshall_PathSegment(m, (SpicePathSeg *)p);
+ }
+
+ if (free_path_data) {
+ free(path_data);
+ }
}
-static void fill_str(DisplayChannel *display_channel, QXLPHYSICAL *in_str, uint32_t group_id)
+static void fill_str(DisplayChannel *display_channel, SpiceMarshaller *m,
+ QXLPHYSICAL in_str, uint32_t group_id)
{
RedWorker *worker;
RedChannel *channel = &display_channel->base;
int memslot_id;
+ SpiceString string;
+
worker = channel->worker;
- ASSERT(in_str && *in_str);
- memslot_id = get_memslot_id(&worker->mem_slots, *in_str);
- QXLString *str = (QXLString *)get_virt(&worker->mem_slots, *in_str, sizeof(QXLString), group_id);
- *in_str = channel->send_data.header.size;
- add_buf(channel, BUF_TYPE_RAW, &str->length, sizeof(uint32_t), 0, 0);
- add_buf(channel, BUF_TYPE_CHUNK, &str->chunk, str->data_size, memslot_id, group_id);
+
+ ASSERT(in_str);
+ memslot_id = get_memslot_id(&worker->mem_slots, in_str);
+ QXLString *str = (QXLString *)get_virt(&worker->mem_slots, in_str, sizeof(QXLString), group_id);
+ string.length = str->length;
+ string.flags = str->flags;
+ spice_marshall_String(m, &string);
+ /* TODO: This doesn't properly marshal the glyph data */
+ marshaller_add_chunk(worker, m, &str->chunk,
+ str->data_size, memslot_id, group_id);
}
-static inline void fill_rects_clip(RedChannel *channel, QXLPHYSICAL *in_clip, uint32_t group_id)
+static inline void fill_rects_clip(RedChannel *channel, SpiceMarshaller *m, QXLPHYSICAL in_clip, uint32_t group_id)
{
RedWorker *worker = channel->worker;
QXLClipRects *clip;
- int memslot_id = get_memslot_id(&worker->mem_slots, *in_clip);
+ uint8_t *rects, *r;
+ int free_rects, i;
+ int memslot_id = get_memslot_id(&worker->mem_slots, in_clip);
- ASSERT(in_clip && *in_clip);
- clip = (QXLClipRects *)get_virt(&worker->mem_slots, *in_clip, sizeof(QXLClipRects), group_id);
- *in_clip = channel->send_data.header.size;
- add_buf(channel, BUF_TYPE_RAW, &clip->num_rects, sizeof(uint32_t), 0, 0);
- add_buf(channel, BUF_TYPE_CHUNK, &clip->chunk, clip->num_rects * sizeof(SpiceRect), memslot_id,
- group_id);
-}
+ ASSERT(in_clip);
+ clip = (QXLClipRects *)get_virt(&worker->mem_slots, in_clip, sizeof(QXLClipRects), group_id);
+ spice_marshaller_add_uint32(m, clip->num_rects);
+ rects = chunk_linearize(worker, &clip->chunk,
+ memslot_id, group_id, clip->num_rects * sizeof(SpiceRect),
+ &free_rects);
-static void fill_base(DisplayChannel *display_channel, SpiceMsgDisplayBase *base, Drawable *drawable,
- uint32_t size, uint32_t surface_id)
-{
- RedChannel *channel = &display_channel->base;
- add_buf(channel, BUF_TYPE_RAW, base, size, 0, 0);
- base->surface_id = surface_id;
- base->box = drawable->qxl_drawable->bbox;
- base->clip = drawable->qxl_drawable->clip;
+ r = rects;
+ for (i = 0; i < clip->num_rects; i++) {
+ r = spice_marshall_Rect(m, (SpiceRect *)r);
+ }
- if (base->clip.type == SPICE_CLIP_TYPE_RECTS) {
- fill_rects_clip(channel, &base->clip.data, drawable->group_id);
- } else if (base->clip.type == SPICE_CLIP_TYPE_PATH) {
- fill_path(display_channel, &base->clip.data, drawable->group_id);
+ if (free_rects) {
+ free(rects);
}
}
-static inline RedImage *alloc_image(DisplayChannel *display_channel)
+static void fill_base(DisplayChannel *display_channel, Drawable *drawable)
{
- ASSERT(display_channel->send_data.bitmap_pos < MAX_BITMAPS);
- return &display_channel->send_data.images[display_channel->send_data.bitmap_pos++];
+ RedChannel *channel = &display_channel->base;
+ SpiceMsgDisplayBase base;
+ SpiceMarshaller *cliprects_data_out, *clippath_data_out;
+
+ base.surface_id = drawable->surface_id;
+ base.box = drawable->qxl_drawable->bbox;
+ base.clip = drawable->qxl_drawable->clip;
+
+ spice_marshall_DisplayBase(channel->send_data.marshaller, &base,
+ &cliprects_data_out, &clippath_data_out);
+ if (cliprects_data_out) {
+ fill_rects_clip(channel, cliprects_data_out, base.clip.data, drawable->group_id);
+ } else if (clippath_data_out) {
+ fill_path(display_channel, clippath_data_out, base.clip.data, drawable->group_id);
+ }
}
/* io_palette is relative address of the palette*/
static inline void fill_palette(DisplayChannel *display_channel, SPICE_ADDRESS *io_palette, uint8_t *flags,
- uint32_t group_id)
+ uint32_t group_id, SpicePalette **palette_out)
{
RedChannel *channel = &display_channel->base;
RedWorker *worker = channel->worker;
SpicePalette *palette;
+ *palette_out = NULL;
if (!(*io_palette)) {
return;
}
+
palette = (SpicePalette *)get_virt(&worker->mem_slots, *io_palette, sizeof(SpicePalette), group_id);
if (palette->unique) {
if (red_palette_cache_find(display_channel, palette->unique)) {
@@ -5309,9 +5382,7 @@ static inline void fill_palette(DisplayChannel *display_channel, SPICE_ADDRESS *
*flags |= SPICE_BITMAP_FLAGS_PAL_CACHE_ME;
}
}
- *io_palette = channel->send_data.header.size;
- add_buf(channel, BUF_TYPE_RAW, palette,
- sizeof(SpicePalette) + palette->num_ents * sizeof(uint32_t), 0, 0);
+ *palette_out = palette;
}
static inline RedCompressBuf *red_display_alloc_compress_buf(DisplayChannel *display_channel)
@@ -6114,11 +6185,9 @@ static const LzImageType MAP_BITMAP_FMT_TO_LZ_IMAGE_TYPE[] = {
};
typedef struct compress_send_data_t {
- uint32_t raw_size;
void* comp_buf;
uint32_t comp_buf_size;
- SPICE_ADDRESS *plt_ptr;
- uint8_t *flags_ptr;
+ SpicePalette *lzplt_palette;
int is_lossy;
} compress_send_data_t;
@@ -6180,15 +6249,11 @@ static inline int red_glz_compress_image(DisplayChannel *display_channel,
dest->descriptor.type = SPICE_IMAGE_TYPE_GLZ_RGB;
dest->lz_rgb.data_size = size;
- o_comp_data->raw_size = sizeof(SpiceLZRGBImage);
o_comp_data->comp_buf = glz_data->data.bufs_head;
o_comp_data->comp_buf_size = size;
- o_comp_data->plt_ptr = NULL;
- o_comp_data->flags_ptr = NULL;
- o_comp_data->is_lossy = FALSE;
stat_compress_add(&display_channel->glz_stat, start_time, src->stride * src->y,
- o_comp_data->comp_buf_size);
+ size);
return TRUE;
}
@@ -6256,25 +6321,21 @@ static inline int red_lz_compress_image(DisplayChannel *display_channel,
dest->descriptor.type = SPICE_IMAGE_TYPE_LZ_RGB;
dest->lz_rgb.data_size = size;
- o_comp_data->raw_size = sizeof(SpiceLZRGBImage);
o_comp_data->comp_buf = lz_data->data.bufs_head;
o_comp_data->comp_buf_size = size;
- o_comp_data->plt_ptr = NULL;
- o_comp_data->flags_ptr = NULL;
} else {
dest->descriptor.type = SPICE_IMAGE_TYPE_LZ_PLT;
dest->lz_plt.data_size = size;
dest->lz_plt.flags = src->flags & SPICE_BITMAP_FLAGS_TOP_DOWN;
dest->lz_plt.palette = src->palette;
- o_comp_data->raw_size = sizeof(SpiceLZPLTImage);
o_comp_data->comp_buf = lz_data->data.bufs_head;
o_comp_data->comp_buf_size = size;
- o_comp_data->plt_ptr = &(dest->lz_plt.palette);
- o_comp_data->flags_ptr = &(dest->lz_plt.flags);
+
+ fill_palette(display_channel, &(dest->lz_plt.palette), &(dest->lz_plt.flags),
+ group_id, &o_comp_data->lzplt_palette);
}
- o_comp_data->is_lossy = FALSE;
stat_compress_add(&display_channel->lz_stat, start_time, src->stride * src->y,
o_comp_data->comp_buf_size);
return TRUE;
@@ -6412,12 +6473,10 @@ static int red_jpeg_compress_image(DisplayChannel *display_channel, RedImage *de
dest->descriptor.type = SPICE_IMAGE_TYPE_JPEG;
dest->jpeg.data_size = size;
- o_comp_data->raw_size = sizeof(SpiceJPEGImage);
o_comp_data->comp_buf = jpeg_data->data.bufs_head;
o_comp_data->comp_buf_size = size;
- o_comp_data->plt_ptr = NULL;
- o_comp_data->flags_ptr = NULL;
o_comp_data->is_lossy = TRUE;
+
stat_compress_add(&display_channel->jpeg_stat, start_time, src->stride * src->y,
o_comp_data->comp_buf_size);
return TRUE;
@@ -6559,12 +6618,8 @@ static inline int red_quic_compress_image(DisplayChannel *display_channel, RedIm
dest->descriptor.type = SPICE_IMAGE_TYPE_QUIC;
dest->quic.data_size = size << 2;
- o_comp_data->raw_size = sizeof(SpiceQUICImage);
o_comp_data->comp_buf = quic_data->data.bufs_head;
o_comp_data->comp_buf_size = size << 2;
- o_comp_data->plt_ptr = NULL;
- o_comp_data->flags_ptr = NULL;
- o_comp_data->is_lossy = FALSE;
stat_compress_add(&display_channel->quic_stat, start_time, src->stride * src->y,
o_comp_data->comp_buf_size);
@@ -6658,8 +6713,9 @@ static inline int red_compress_image(DisplayChannel *display_channel,
/* using the global dictionary only if it is not freezed */
pthread_rwlock_rdlock(&display_channel->glz_dict->encode_lock);
if (!display_channel->glz_dict->migrate_freeze) {
- ret = red_glz_compress_image(
- display_channel, dest, src, drawable, o_comp_data);
+ ret = red_glz_compress_image(display_channel,
+ dest, src,
+ drawable, o_comp_data);
} else {
glz = FALSE;
}
@@ -6714,58 +6770,60 @@ typedef enum {
/* if the number of times fill_bits can be called per one qxl_drawable increases -
MAX_LZ_DRAWABLE_INSTANCES must be increased as well */
-static FillBitsType fill_bits(DisplayChannel *display_channel, QXLPHYSICAL *in_bitmap,
- Drawable *drawable, int can_lossy)
+static FillBitsType fill_bits(DisplayChannel *display_channel, SpiceMarshaller *m,
+ QXLPHYSICAL in_bitmap, Drawable *drawable, int can_lossy)
{
RedChannel *channel = &display_channel->base;
RedWorker *worker = channel->worker;
- RedImage *image;
+ RedImage image;
QXLImage *qxl_image;
uint8_t *data;
int memslot_id;
- compress_send_data_t comp_send_data;
+ compress_send_data_t comp_send_data = {0};
+ SpiceMarshaller *bitmap_palette_out, *data_out, *lzplt_palette_out;
- if (*in_bitmap == 0) {
+ if (in_bitmap == 0) {
ASSERT(drawable->self_bitmap);
qxl_image = (QXLImage *)drawable->self_bitmap;
} else {
- qxl_image = (QXLImage *)get_virt(&worker->mem_slots, *in_bitmap, sizeof(QXLImage),
+ qxl_image = (QXLImage *)get_virt(&worker->mem_slots, in_bitmap, sizeof(QXLImage),
drawable->group_id);
}
- image = alloc_image(display_channel);
-
- image->descriptor.id = qxl_image->descriptor.id;
- image->descriptor.type = qxl_image->descriptor.type;
- image->descriptor.flags = 0;
+ image.descriptor.id = qxl_image->descriptor.id;
+ image.descriptor.type = qxl_image->descriptor.type;
+ image.descriptor.flags = 0;
if (qxl_image->descriptor.flags & QXL_IMAGE_HIGH_BITS_SET) {
- image->descriptor.flags |= SPICE_IMAGE_FLAGS_HIGH_BITS_SET;
+ image.descriptor.flags |= SPICE_IMAGE_FLAGS_HIGH_BITS_SET;
}
- image->descriptor.width = qxl_image->descriptor.width;
- image->descriptor.height = qxl_image->descriptor.height;
+ image.descriptor.width = qxl_image->descriptor.width;
+ image.descriptor.height = qxl_image->descriptor.height;
- memslot_id = get_memslot_id(&worker->mem_slots, *in_bitmap);
- *in_bitmap = channel->send_data.header.size;
+ memslot_id = get_memslot_id(&worker->mem_slots, in_bitmap);
if ((qxl_image->descriptor.flags & QXL_IMAGE_CACHE)) {
int lossy_cache_item;
- if (pixmap_cache_hit(display_channel->pixmap_cache, image->descriptor.id,
+ if (pixmap_cache_hit(display_channel->pixmap_cache, image.descriptor.id,
&lossy_cache_item, display_channel)) {
if (can_lossy || !lossy_cache_item) {
if (!display_channel->enable_jpeg || lossy_cache_item) {
- image->descriptor.type = SPICE_IMAGE_TYPE_FROM_CACHE;
+ image.descriptor.type = SPICE_IMAGE_TYPE_FROM_CACHE;
} else {
// making sure, in multiple monitor scenario, that lossy items that
// should have been replaced with lossless data by one display channel,
// will be retrieved as lossless by another display channel.
- image->descriptor.type = SPICE_IMAGE_TYPE_FROM_CACHE_LOSSLESS;
+ image.descriptor.type = SPICE_IMAGE_TYPE_FROM_CACHE_LOSSLESS;
}
- add_buf(channel, BUF_TYPE_RAW, image, sizeof(SpiceImageDescriptor), 0, 0);
+ spice_marshall_Image(m, (SpiceImageDescriptor *)&image,
+ &bitmap_palette_out, &data_out, &lzplt_palette_out);
+ ASSERT(bitmap_palette_out == NULL);
+ ASSERT(data_out == NULL);
+ ASSERT(lzplt_palette_out == NULL);
stat_inc_counter(display_channel->cache_hits_counter, 1);
return FILL_BITS_TYPE_CACHE;
} else {
pixmap_cache_set_lossy(display_channel->pixmap_cache, qxl_image->descriptor.id,
FALSE);
- image->descriptor.flags |= SPICE_IMAGE_FLAGS_CACHE_REPLACE_ME;
+ image.descriptor.flags |= SPICE_IMAGE_FLAGS_CACHE_REPLACE_ME;
}
}
}
@@ -6779,13 +6837,17 @@ static FillBitsType fill_bits(DisplayChannel *display_channel, QXLPHYSICAL *in_b
validate_surface(worker, surface_id);
surface = &worker->surfaces[surface_id];
- image->descriptor.type = SPICE_IMAGE_TYPE_SURFACE;
- image->descriptor.flags = 0;
- image->descriptor.width = surface->context.width;
- image->descriptor.height = surface->context.height;
-
- image->surface.surface_id = surface_id;
- add_buf(channel, BUF_TYPE_RAW, image, sizeof(SpiceSurfaceImage), 0, 0);
+ image.descriptor.type = SPICE_IMAGE_TYPE_SURFACE;
+ image.descriptor.flags = 0;
+ image.descriptor.width = surface->context.width;
+ image.descriptor.height = surface->context.height;
+
+ image.surface.surface_id = surface_id;
+ spice_marshall_Image(m, (SpiceImageDescriptor *)&image,
+ &bitmap_palette_out, &data_out, &lzplt_palette_out);
+ ASSERT(bitmap_palette_out == NULL);
+ ASSERT(data_out == NULL);
+ ASSERT(lzplt_palette_out == NULL);
return FILL_BITS_TYPE_SURFACE;
}
case SPICE_IMAGE_TYPE_BITMAP:
@@ -6795,101 +6857,114 @@ static FillBitsType fill_bits(DisplayChannel *display_channel, QXLPHYSICAL *in_b
/* Images must be added to the cache only after they are compressed
in order to prevent starvation in the client between pixmap_cache and
global dictionary (in cases of multiple monitors) */
- if (!red_compress_image(display_channel, image, &qxl_image->bitmap,
+ if (!red_compress_image(display_channel, &image, &qxl_image->bitmap,
drawable, can_lossy, &comp_send_data)) {
uint32_t y;
uint32_t stride;
SPICE_ADDRESS image_data;
+ SpicePalette *palette;
+
+ red_display_add_image_to_pixmap_cache(display_channel, qxl_image, &image, FALSE);
- red_display_add_image_to_pixmap_cache(display_channel, qxl_image, image, FALSE);
+ image.bitmap = qxl_image->bitmap;
+ y = image.bitmap.y;
+ stride = image.bitmap.stride;
+ image_data = image.bitmap.data;
+ image.bitmap.flags = image.bitmap.flags & SPICE_BITMAP_FLAGS_TOP_DOWN;
- image->bitmap = qxl_image->bitmap;
- y = image->bitmap.y;
- stride = image->bitmap.stride;
- image_data = image->bitmap.data;
- image->bitmap.flags = image->bitmap.flags & SPICE_BITMAP_FLAGS_TOP_DOWN;
+ fill_palette(display_channel, &image.bitmap.palette, &image.bitmap.flags,
+ drawable->group_id, &palette);
+ spice_marshall_Image(m, (SpiceImageDescriptor *)&image,
+ &bitmap_palette_out, &data_out, &lzplt_palette_out);
+ ASSERT(lzplt_palette_out == NULL);
+
+ if (palette) {
+ spice_marshall_Palette(bitmap_palette_out, palette);
+ }
- add_buf(channel, BUF_TYPE_RAW, image, sizeof(SpiceBitmapImage), 0, 0);
- fill_palette(display_channel, &(image->bitmap.palette), &(image->bitmap.flags),
- drawable->group_id);
- image->bitmap.data = channel->send_data.header.size;
if (qxl_image->bitmap.flags & QXL_BITMAP_DIRECT) {
data = (uint8_t *)get_virt(&worker->mem_slots, image_data, stride * y, drawable->group_id);
- add_buf(channel, BUF_TYPE_RAW, data, y * stride, 0, 0);
+ spice_marshaller_add_ref(data_out, data, y * stride);
} else {
data = (uint8_t *)get_virt(&worker->mem_slots, image_data, sizeof(QXLDataChunk),
drawable->group_id);
- add_buf(channel, BUF_TYPE_CHUNK, data, y * stride, memslot_id, drawable->group_id);
+ marshaller_add_chunk(worker, data_out, (QXLDataChunk *)data,
+ y * stride, memslot_id, drawable->group_id);
}
return FILL_BITS_TYPE_BITMAP;
} else {
- red_display_add_image_to_pixmap_cache(display_channel, qxl_image, image,
+ red_display_add_image_to_pixmap_cache(display_channel, qxl_image, &image,
comp_send_data.is_lossy);
- add_buf((RedChannel *)display_channel, BUF_TYPE_RAW, image, comp_send_data.raw_size,
- 0, 0);
- add_buf((RedChannel *)display_channel, BUF_TYPE_COMPRESS_BUF,
- comp_send_data.comp_buf, comp_send_data.comp_buf_size, 0, 0);
+ spice_marshall_Image(m, (SpiceImageDescriptor *)&image,
+ &bitmap_palette_out, &data_out, &lzplt_palette_out);
+ ASSERT(bitmap_palette_out == NULL);
- if (comp_send_data.plt_ptr != NULL) {
- fill_palette(display_channel, comp_send_data.plt_ptr, comp_send_data.flags_ptr,
- drawable->group_id);
+ marshaller_add_compressed(worker, m, comp_send_data.comp_buf,
+ comp_send_data.comp_buf_size);
+
+ if (comp_send_data.lzplt_palette) {
+ spice_marshall_Palette(lzplt_palette_out, comp_send_data.lzplt_palette);
}
+
ASSERT(!comp_send_data.is_lossy || can_lossy);
return (comp_send_data.is_lossy ? FILL_BITS_TYPE_COMPRESS_LOSSY :
FILL_BITS_TYPE_COMPRESS_LOSSLESS);
}
break;
case SPICE_IMAGE_TYPE_QUIC:
- red_display_add_image_to_pixmap_cache(display_channel, qxl_image, image, FALSE);
- image->quic = qxl_image->quic;
- add_buf(channel, BUF_TYPE_RAW, image, sizeof(SpiceQUICImage), 0, 0);
- add_buf(channel, BUF_TYPE_CHUNK, qxl_image->quic.data, qxl_image->quic.data_size,
- memslot_id, drawable->group_id);
+ red_display_add_image_to_pixmap_cache(display_channel, qxl_image, &image, FALSE);
+ image.quic = qxl_image->quic;
+ spice_marshall_Image(m, (SpiceImageDescriptor *)&image,
+ &bitmap_palette_out, &data_out, &lzplt_palette_out);
+ ASSERT(bitmap_palette_out == NULL);
+ ASSERT(lzplt_palette_out == NULL);
+ marshaller_add_chunk(worker, m, (QXLDataChunk *)qxl_image->quic.data,
+ qxl_image->quic.data_size,
+ memslot_id, drawable->group_id);
return FILL_BITS_TYPE_COMPRESS_LOSSLESS;
default:
- red_error("invalid image type %u", image->descriptor.type);
+ red_error("invalid image type %u", image.descriptor.type);
}
}
-static void fill_brush(DisplayChannel *display_channel, SpiceBrush *brush, Drawable *drawable)
+static void fill_mask(DisplayChannel *display_channel, SpiceMarshaller *m,
+ SPICE_ADDRESS mask_bitmap, Drawable *drawable)
{
- if (brush->type == SPICE_BRUSH_TYPE_PATTERN) {
- fill_bits(display_channel, &brush->u.pattern.pat, drawable, FALSE);
- }
-}
-
-static void fill_mask(DisplayChannel *display_channel, SpiceQMask *mask, Drawable *drawable)
-{
- if (mask->bitmap) {
+ if (mask_bitmap && m) {
if (display_channel->base.worker->image_compression != SPICE_IMAGE_COMPRESS_OFF) {
spice_image_compression_t save_img_comp =
display_channel->base.worker->image_compression;
display_channel->base.worker->image_compression = SPICE_IMAGE_COMPRESS_OFF;
- fill_bits(display_channel, &mask->bitmap, drawable, FALSE);
+ fill_bits(display_channel, m, mask_bitmap, drawable, FALSE);
display_channel->base.worker->image_compression = save_img_comp;
} else {
- fill_bits(display_channel, &mask->bitmap, drawable, FALSE);
+ fill_bits(display_channel, m, mask_bitmap, drawable, FALSE);
}
}
}
-static void fill_attr(DisplayChannel *display_channel, SpiceLineAttr *attr, uint32_t group_id)
+static void fill_attr(DisplayChannel *display_channel, SpiceMarshaller *m, SpiceLineAttr *attr, uint32_t group_id)
{
- if (attr->style_nseg) {
- RedChannel *channel = &display_channel->base;
- uint8_t *buf = (uint8_t *)get_virt(&channel->worker->mem_slots, attr->style,
- attr->style_nseg * sizeof(uint32_t), group_id);
- ASSERT(attr->style);
- attr->style = channel->send_data.header.size;
- add_buf(channel, BUF_TYPE_RAW, buf, attr->style_nseg * sizeof(uint32_t), 0, 0);
+ RedChannel *channel = &display_channel->base;
+ uint32_t *style;
+ int i;
+
+ if (m && attr->style_nseg) {
+ style = (uint32_t *)get_virt(&channel->worker->mem_slots, attr->style,
+ attr->style_nseg * sizeof(uint32_t), group_id);
+ for (i = 0 ; i < attr->style_nseg; i++) {
+ spice_marshaller_add_uint32(m, style[i]);
+ }
}
}
-static void fill_cursor(CursorChannel *cursor_channel, SpiceCursor *red_cursor, CursorItem *cursor)
+static void fill_cursor(CursorChannel *cursor_channel, SpiceCursor *red_cursor, CursorItem *cursor, AddBufInfo *addbuf)
{
RedChannel *channel = &cursor_channel->base;
+ addbuf->data = NULL;
+
if (!cursor) {
red_cursor->flags = SPICE_CURSOR_FLAGS_NONE;
return;
@@ -6916,35 +6991,41 @@ static void fill_cursor(CursorChannel *cursor_channel, SpiceCursor *red_cursor,
}
if (qxl_cursor->data_size) {
- add_buf(channel, BUF_TYPE_CHUNK, &qxl_cursor->chunk, qxl_cursor->data_size,
- get_memslot_id(&channel->worker->mem_slots, cursor_cmd->u.set.shape), cursor->group_id);
+ addbuf->type = BUF_TYPE_CHUNK;
+ addbuf->data = &qxl_cursor->chunk;
+ addbuf->size = qxl_cursor->data_size;
+ addbuf->slot_id = get_memslot_id(&channel->worker->mem_slots, cursor_cmd->u.set.shape);
+ addbuf->group_id = cursor->group_id;
}
} else {
LocalCursor *local_cursor;
ASSERT(cursor->type == CURSOR_TYPE_LOCAL);
local_cursor = (LocalCursor *)cursor;
*red_cursor = local_cursor->red_cursor;
- add_buf(channel, BUF_TYPE_RAW, local_cursor->red_cursor.data, local_cursor->data_size, 0,
- 0);
+ addbuf->type = BUF_TYPE_RAW;
+ addbuf->data = local_cursor->red_cursor.data;
+ addbuf->size = local_cursor->data_size;
+ addbuf->slot_id = 0;
+ addbuf->group_id = 0;
}
}
static inline void red_channel_reset_send_data(RedChannel *channel)
{
+ spice_marshaller_reset(channel->send_data.marshaller);
+ channel->send_data.header = (SpiceDataHeader *)
+ spice_marshaller_reserve_space(channel->send_data.marshaller, sizeof(SpiceDataHeader));
+ spice_marshaller_set_base(channel->send_data.marshaller, sizeof(SpiceDataHeader));
channel->send_data.pos = 0;
- channel->send_data.n_bufs = 1;
- channel->send_data.header.size = 0;
- channel->send_data.header.sub_list = 0;
- ++channel->send_data.header.serial;
- channel->send_data.bufs[0].type = BUF_TYPE_RAW;
- channel->send_data.bufs[0].size = sizeof(SpiceDataHeader);
- channel->send_data.bufs[0].data = (void *)&channel->send_data.header;
+ channel->send_data.header->type = 0;
+ channel->send_data.header->size = 0;
+ channel->send_data.header->sub_list = 0;
+ channel->send_data.header->serial = ++channel->send_data.serial;
}
static inline void red_display_reset_send_data(DisplayChannel *channel)
{
red_channel_reset_send_data((RedChannel *)channel);
- channel->send_data.bitmap_pos = 0;
red_display_reset_compress_buf(channel);
channel->send_data.free_list.res->count = 0;
memset(channel->send_data.free_list.sync, 0, sizeof(channel->send_data.free_list.sync));
@@ -7323,13 +7404,39 @@ static void red_add_lossless_drawable_dependencies(RedWorker *worker,
}
}
-static inline void red_lossy_send_qxl_draw_fill(RedWorker *worker,
- DisplayChannel *display_channel,
- Drawable *item)
+static void red_send_qxl_draw_fill(RedWorker *worker,
+ DisplayChannel *display_channel,
+ Drawable *item)
+{
+ RedChannel *channel = &display_channel->base;
+ QXLDrawable *drawable = item->qxl_drawable;
+ SpiceMarshaller *brush_pat_out;
+ SpiceMarshaller *mask_bitmap_out;
+ SpiceFill fill;
+
+ fill_base(display_channel, item);
+
+ channel->send_data.header->type = SPICE_MSG_DISPLAY_DRAW_FILL;
+ fill = drawable->u.fill;
+ spice_marshall_Fill(channel->send_data.marshaller,
+ &fill,
+ &brush_pat_out,
+ &mask_bitmap_out);
+
+ if (brush_pat_out) {
+ fill_bits(display_channel, brush_pat_out, fill.brush.u.pattern.pat, item, FALSE);
+ }
+
+ fill_mask(display_channel, mask_bitmap_out, fill.mask.bitmap, item);
+}
+
+
+static void red_lossy_send_qxl_draw_fill(RedWorker *worker,
+ DisplayChannel *display_channel,
+ Drawable *item)
{
QXLDrawable *drawable = item->qxl_drawable;
- RedChannel *channel = &display_channel->base;
int dest_allowed_lossy = FALSE;
int dest_is_lossy = FALSE;
SpiceRect dest_lossy_area;
@@ -7342,23 +7449,19 @@ static inline void red_lossy_send_qxl_draw_fill(RedWorker *worker,
dest_allowed_lossy = !((rop & SPICE_ROPD_OP_OR) ||
(rop & SPICE_ROPD_OP_AND) ||
(rop & SPICE_ROPD_OP_XOR));
-
+
brush_is_lossy = is_brush_lossy(display_channel, &drawable->u.fill.brush, item,
&brush_bitmap_data);
if (!dest_allowed_lossy) {
dest_is_lossy = is_surface_area_lossy(display_channel, item->surface_id, &drawable->bbox,
&dest_lossy_area);
}
-
- if (!dest_is_lossy &&
+
+ if (!dest_is_lossy &&
!(brush_is_lossy && (brush_bitmap_data.type == BITMAP_DATA_TYPE_SURFACE))) {
int has_mask = !!drawable->u.fill.mask.bitmap;
- channel->send_data.header.type = SPICE_MSG_DISPLAY_DRAW_FILL;
- fill_base(display_channel, &display_channel->send_data.u.fill.base, item,
- sizeof(SpiceMsgDisplayDrawFill), item->surface_id);
- display_channel->send_data.u.fill.data = drawable->u.fill;
- fill_brush(display_channel, &display_channel->send_data.u.fill.data.brush, item);
- fill_mask(display_channel, &display_channel->send_data.u.fill.data.mask, item);
+
+ red_send_qxl_draw_fill(worker, display_channel, item);
// eitehr the brush operation is opaque, or the dest is not lossy
surface_lossy_region_update(worker, display_channel, item, has_mask, FALSE);
@@ -7384,12 +7487,44 @@ static inline void red_lossy_send_qxl_draw_fill(RedWorker *worker,
}
}
-static inline void red_lossy_send_qxl_draw_opaque(RedWorker *worker,
- DisplayChannel *display_channel,
- Drawable *item)
+static FillBitsType red_send_qxl_draw_opaque(RedWorker *worker,
+ DisplayChannel *display_channel,
+ Drawable *item, int src_allowed_lossy)
{
- QXLDrawable *drawable = item->qxl_drawable;
RedChannel *channel = &display_channel->base;
+ QXLDrawable *drawable = item->qxl_drawable;
+ SpiceMarshaller *brush_pat_out;
+ SpiceMarshaller *src_bitmap_out;
+ SpiceMarshaller *mask_bitmap_out;
+ SpiceOpaque opaque;
+ FillBitsType src_send_type;
+
+ fill_base(display_channel, item);
+
+ channel->send_data.header->type = SPICE_MSG_DISPLAY_DRAW_OPAQUE;
+ opaque = drawable->u.opaque;
+ spice_marshall_Opaque(channel->send_data.marshaller,
+ &opaque,
+ &src_bitmap_out,
+ &brush_pat_out,
+ &mask_bitmap_out);
+
+ src_send_type = fill_bits(display_channel, src_bitmap_out, opaque.src_bitmap, item,
+ src_allowed_lossy);
+
+ if (brush_pat_out) {
+ fill_bits(display_channel, brush_pat_out, opaque.brush.u.pattern.pat, item, FALSE);
+ }
+ fill_mask(display_channel, mask_bitmap_out, opaque.mask.bitmap, item);
+
+ return src_send_type;
+}
+
+static void red_lossy_send_qxl_draw_opaque(RedWorker *worker,
+ DisplayChannel *display_channel,
+ Drawable *item)
+{
+ QXLDrawable *drawable = item->qxl_drawable;
int src_allowed_lossy;
int rop;
@@ -7418,15 +7553,7 @@ static inline void red_lossy_send_qxl_draw_opaque(RedWorker *worker,
FillBitsType src_send_type;
int has_mask = !!drawable->u.opaque.mask.bitmap;
- channel->send_data.header.type = SPICE_MSG_DISPLAY_DRAW_OPAQUE;
- fill_base(display_channel, &display_channel->send_data.u.opaque.base, item,
- sizeof(SpiceMsgDisplayDrawOpaque), item->surface_id);
- display_channel->send_data.u.opaque.data = drawable->u.opaque;
- src_send_type = fill_bits(display_channel,
- &display_channel->send_data.u.opaque.data.src_bitmap,
- item, src_allowed_lossy);
- fill_brush(display_channel, &display_channel->send_data.u.opaque.data.brush, item);
- fill_mask(display_channel, &display_channel->send_data.u.opaque.data.mask, item);
+ src_send_type = red_send_qxl_draw_opaque(worker, display_channel, item, src_allowed_lossy);
if (src_send_type == FILL_BITS_TYPE_COMPRESS_LOSSY) {
src_is_lossy = TRUE;
@@ -7457,12 +7584,38 @@ static inline void red_lossy_send_qxl_draw_opaque(RedWorker *worker,
}
}
-static inline void red_lossy_send_qxl_draw_copy(RedWorker *worker,
- DisplayChannel *display_channel,
- Drawable *item)
+static FillBitsType red_send_qxl_draw_copy(RedWorker *worker,
+ DisplayChannel *display_channel,
+ Drawable *item, int src_allowed_lossy)
{
- QXLDrawable *drawable = item->qxl_drawable;
RedChannel *channel = &display_channel->base;
+ QXLDrawable *drawable = item->qxl_drawable;
+ SpiceMarshaller *src_bitmap_out;
+ SpiceMarshaller *mask_bitmap_out;
+ SpiceCopy copy;
+ FillBitsType src_send_type;
+
+ fill_base(display_channel, item);
+
+ channel->send_data.header->type = SPICE_MSG_DISPLAY_DRAW_COPY;
+
+ copy = drawable->u.copy;
+ spice_marshall_Copy(channel->send_data.marshaller,
+ ©,
+ &src_bitmap_out,
+ &mask_bitmap_out);
+
+ src_send_type = fill_bits(display_channel, src_bitmap_out, copy.src_bitmap, item, src_allowed_lossy);
+ fill_mask(display_channel, mask_bitmap_out, copy.mask.bitmap, item);
+
+ return src_send_type;
+}
+
+static void red_lossy_send_qxl_draw_copy(RedWorker *worker,
+ DisplayChannel *display_channel,
+ Drawable *item)
+{
+ QXLDrawable *drawable = item->qxl_drawable;
int has_mask = !!drawable->u.copy.mask.bitmap;
int src_is_lossy;
BitmapData src_bitmap_data;
@@ -7471,13 +7624,7 @@ static inline void red_lossy_send_qxl_draw_copy(RedWorker *worker,
src_is_lossy = is_bitmap_lossy(display_channel, drawable->u.copy.src_bitmap,
&drawable->u.copy.src_area, item, &src_bitmap_data);
- channel->send_data.header.type = SPICE_MSG_DISPLAY_DRAW_COPY;
- fill_base(display_channel, &display_channel->send_data.u.copy.base, item,
- sizeof(SpiceMsgDisplayDrawCopy), item->surface_id);
- display_channel->send_data.u.copy.data = drawable->u.copy;
- src_send_type = fill_bits(display_channel, &display_channel->send_data.u.copy.data.src_bitmap,
- item, TRUE);
- fill_mask(display_channel, &display_channel->send_data.u.copy.data.mask, item);
+ src_send_type = red_send_qxl_draw_copy(worker, display_channel, item, TRUE);
if (src_send_type == FILL_BITS_TYPE_COMPRESS_LOSSY) {
src_is_lossy = TRUE;
@@ -7489,25 +7636,37 @@ static inline void red_lossy_send_qxl_draw_copy(RedWorker *worker,
src_is_lossy);
}
-static inline void red_lossy_send_qxl_draw_transparent(RedWorker *worker,
- DisplayChannel *display_channel,
- Drawable *item)
+static void red_send_qxl_draw_transparent(RedWorker *worker,
+ DisplayChannel *display_channel,
+ Drawable *item)
{
- QXLDrawable *drawable = item->qxl_drawable;
RedChannel *channel = &display_channel->base;
+ QXLDrawable *drawable = item->qxl_drawable;
+ SpiceMarshaller *src_bitmap_out;
+ SpiceTransparent transparent;
+
+ fill_base(display_channel, item);
+ channel->send_data.header->type = SPICE_MSG_DISPLAY_DRAW_TRANSPARENT;
+ transparent = drawable->u.transparent;
+ spice_marshall_Transparent(channel->send_data.marshaller,
+ &transparent,
+ &src_bitmap_out);
+ fill_bits(display_channel, src_bitmap_out, transparent.src_bitmap, item, FALSE);
+}
+
+static void red_lossy_send_qxl_draw_transparent(RedWorker *worker,
+ DisplayChannel *display_channel,
+ Drawable *item)
+{
+ QXLDrawable *drawable = item->qxl_drawable;
int src_is_lossy;
BitmapData src_bitmap_data;
src_is_lossy = is_bitmap_lossy(display_channel, drawable->u.transparent.src_bitmap,
&drawable->u.transparent.src_area, item, &src_bitmap_data);
- if (!src_is_lossy || (src_bitmap_data.type != BITMAP_DATA_TYPE_SURFACE)) {
- channel->send_data.header.type = SPICE_MSG_DISPLAY_DRAW_TRANSPARENT;
- fill_base(display_channel, &display_channel->send_data.u.transparent.base, item,
- sizeof(SpiceMsgDisplayDrawTransparent), item->surface_id);
- display_channel->send_data.u.transparent.data = drawable->u.transparent;
- fill_bits(display_channel, &display_channel->send_data.u.transparent.data.src_bitmap,
- item, FALSE);
+ if (!src_is_lossy || (src_bitmap_data.type != BITMAP_DATA_TYPE_SURFACE)) {
+ red_send_qxl_draw_transparent(worker, display_channel, item);
// don't update surface lossy region since transperent areas might be lossy
} else {
@@ -7522,26 +7681,41 @@ static inline void red_lossy_send_qxl_draw_transparent(RedWorker *worker,
}
}
-static inline void red_lossy_send_qxl_draw_alpha_blend(RedWorker *worker,
- DisplayChannel *display_channel,
- Drawable *item)
+static FillBitsType red_send_qxl_draw_alpha_blend(RedWorker *worker,
+ DisplayChannel *display_channel,
+ Drawable *item,
+ int src_allowed_lossy)
{
- QXLDrawable *drawable = item->qxl_drawable;
RedChannel *channel = &display_channel->base;
+ QXLDrawable *drawable = item->qxl_drawable;
+ SpiceMarshaller *src_bitmap_out;
+ SpiceAlphaBlnd alpha_blend;
+ FillBitsType src_send_type;
+
+ fill_base(display_channel, item);
+ channel->send_data.header->type = SPICE_MSG_DISPLAY_DRAW_ALPHA_BLEND;
+ alpha_blend = drawable->u.alpha_blend;
+ spice_marshall_AlphaBlnd(channel->send_data.marshaller,
+ &alpha_blend,
+ &src_bitmap_out);
+ src_send_type = fill_bits(display_channel, src_bitmap_out, alpha_blend.src_bitmap, item, src_allowed_lossy);
+
+ return src_send_type;
+}
+
+static void red_lossy_send_qxl_draw_alpha_blend(RedWorker *worker,
+ DisplayChannel *display_channel,
+ Drawable *item)
+{
+ QXLDrawable *drawable = item->qxl_drawable;
int src_is_lossy;
BitmapData src_bitmap_data;
FillBitsType src_send_type;
src_is_lossy = is_bitmap_lossy(display_channel, drawable->u.alpha_blend.src_bitmap,
&drawable->u.alpha_blend.src_area, item, &src_bitmap_data);
-
- channel->send_data.header.type = SPICE_MSG_DISPLAY_DRAW_ALPHA_BLEND;
- fill_base(display_channel, &display_channel->send_data.u.alpha_blend.base, item,
- sizeof(SpiceMsgDisplayDrawAlphaBlend), item->surface_id);
- display_channel->send_data.u.alpha_blend.data = drawable->u.alpha_blend;
- src_send_type = fill_bits(display_channel,
- &display_channel->send_data.u.alpha_blend.data.src_bitmap,
- item, TRUE);
+
+ src_send_type = red_send_qxl_draw_alpha_blend(worker, display_channel, item, TRUE);
if (src_send_type == FILL_BITS_TYPE_COMPRESS_LOSSY) {
src_is_lossy = TRUE;
@@ -7554,27 +7728,37 @@ static inline void red_lossy_send_qxl_draw_alpha_blend(RedWorker *worker,
} // else, the area stays lossy/lossless as the destination
}
-static inline void red_lossy_send_qxl_copy_bits(RedWorker *worker,
- DisplayChannel *display_channel,
- Drawable *item)
+static void red_send_qxl_copy_bits(RedWorker *worker,
+ DisplayChannel *display_channel,
+ Drawable *item)
{
- QXLDrawable *drawable = item->qxl_drawable;
RedChannel *channel = &display_channel->base;
+ QXLDrawable *drawable = item->qxl_drawable;
+ SpicePoint copy_bits;
+
+ fill_base(display_channel, item);
+ channel->send_data.header->type = SPICE_MSG_DISPLAY_COPY_BITS;
+ copy_bits = drawable->u.copy_bits.src_pos;
+ spice_marshall_Point(channel->send_data.marshaller,
+ ©_bits);
+}
+
+static void red_lossy_send_qxl_copy_bits(RedWorker *worker,
+ DisplayChannel *display_channel,
+ Drawable *item)
+{
+ QXLDrawable *drawable = item->qxl_drawable;
SpiceRect src_rect;
int horz_offset;
int vert_offset;
int src_is_lossy;
SpiceRect src_lossy_area;
- channel->send_data.header.type = SPICE_MSG_DISPLAY_COPY_BITS;
- fill_base(display_channel, &display_channel->send_data.u.copy_bits.base, item,
- sizeof(SpiceMsgDisplayCopyBits), item->surface_id);
- display_channel->send_data.u.copy_bits.src_pos = drawable->u.copy_bits.src_pos;
-
+ red_send_qxl_copy_bits(worker, display_channel, item);
+
horz_offset = drawable->u.copy_bits.src_pos.x - drawable->bbox.left;
vert_offset = drawable->u.copy_bits.src_pos.y - drawable->bbox.top;
-
src_rect.left = drawable->u.copy_bits.src_pos.x;
src_rect.top = drawable->u.copy_bits.src_pos.y;
src_rect.right = drawable->bbox.right + horz_offset;
@@ -7587,12 +7771,34 @@ static inline void red_lossy_send_qxl_copy_bits(RedWorker *worker,
src_is_lossy);
}
-static inline void red_lossy_send_qxl_draw_blend(RedWorker *worker,
- DisplayChannel *display_channel,
- Drawable *item)
+static void red_send_qxl_draw_blend(RedWorker *worker,
+ DisplayChannel *display_channel,
+ Drawable *item)
{
- QXLDrawable *drawable = item->qxl_drawable;
RedChannel *channel = &display_channel->base;
+ QXLDrawable *drawable = item->qxl_drawable;
+ SpiceMarshaller *src_bitmap_out;
+ SpiceMarshaller *mask_bitmap_out;
+ SpiceBlend blend;
+
+ fill_base(display_channel, item);
+ channel->send_data.header->type = SPICE_MSG_DISPLAY_DRAW_BLEND;
+ blend = drawable->u.blend;
+ spice_marshall_Blend(channel->send_data.marshaller,
+ &blend,
+ &src_bitmap_out,
+ &mask_bitmap_out);
+
+ fill_bits(display_channel, src_bitmap_out, blend.src_bitmap, item, FALSE);
+
+ fill_mask(display_channel, mask_bitmap_out, blend.mask.bitmap, item);
+}
+
+static void red_lossy_send_qxl_draw_blend(RedWorker *worker,
+ DisplayChannel *display_channel,
+ Drawable *item)
+{
+ QXLDrawable *drawable = item->qxl_drawable;
int src_is_lossy;
BitmapData src_bitmap_data;
int dest_is_lossy;
@@ -7603,18 +7809,13 @@ static inline void red_lossy_send_qxl_draw_blend(RedWorker *worker,
dest_is_lossy = is_surface_area_lossy(display_channel, drawable->surface_id,
&drawable->bbox, &dest_lossy_area);
- if (!dest_is_lossy && (!src_is_lossy || (src_bitmap_data.type != BITMAP_DATA_TYPE_SURFACE))) {
- channel->send_data.header.type = SPICE_MSG_DISPLAY_DRAW_BLEND;
- fill_base(display_channel, &display_channel->send_data.u.blend.base, item,
- sizeof(SpiceMsgDisplayDrawBlend), item->surface_id);
- display_channel->send_data.u.blend.data = drawable->u.blend;
- fill_bits(display_channel, &display_channel->send_data.u.blend.data.src_bitmap,
- item, FALSE);
- fill_mask(display_channel, &display_channel->send_data.u.blend.data.mask, item);
+ if (!dest_is_lossy &&
+ (!src_is_lossy || (src_bitmap_data.type != BITMAP_DATA_TYPE_SURFACE))) {
+ red_send_qxl_draw_blend(worker, display_channel, item);
} else {
int resend_surface_ids[2];
SpiceRect *resend_areas[2];
- int num_resend = 0;
+ int num_resend = 0;
if (src_is_lossy && (src_bitmap_data.type == BITMAP_DATA_TYPE_SURFACE)) {
resend_surface_ids[num_resend] = src_bitmap_data.id;
@@ -7633,61 +7834,130 @@ static inline void red_lossy_send_qxl_draw_blend(RedWorker *worker,
}
}
-static inline void red_lossy_send_qxl_draw_blackness(RedWorker *worker,
- DisplayChannel *display_channel,
- Drawable *item)
+static void red_send_qxl_draw_blackness(RedWorker *worker,
+ DisplayChannel *display_channel,
+ Drawable *item)
{
- QXLDrawable *drawable = item->qxl_drawable;
RedChannel *channel = &display_channel->base;
+ QXLDrawable *drawable = item->qxl_drawable;
+ SpiceMarshaller *mask_bitmap_out;
+ SpiceBlackness blackness;
+
+ fill_base(display_channel, item);
+ channel->send_data.header->type = SPICE_MSG_DISPLAY_DRAW_BLACKNESS;
+ blackness = drawable->u.blackness;
+
+ spice_marshall_Blackness(channel->send_data.marshaller,
+ &blackness,
+ &mask_bitmap_out);
+
+ fill_mask(display_channel, mask_bitmap_out, blackness.mask.bitmap, item);
+}
+
+static void red_lossy_send_qxl_draw_blackness(RedWorker *worker,
+ DisplayChannel *display_channel,
+ Drawable *item)
+{
+ QXLDrawable *drawable = item->qxl_drawable;
int has_mask = !!drawable->u.blackness.mask.bitmap;
- channel->send_data.header.type = SPICE_MSG_DISPLAY_DRAW_BLACKNESS;
- fill_base(display_channel, &display_channel->send_data.u.blackness.base, item,
- sizeof(SpiceMsgDisplayDrawBlackness), item->surface_id);
- display_channel->send_data.u.blackness.data = drawable->u.blackness;
- fill_mask(display_channel, &display_channel->send_data.u.blackness.data.mask, item);
+ red_send_qxl_draw_blackness(worker, display_channel, item);
surface_lossy_region_update(worker, display_channel, item, has_mask, FALSE);
}
-static inline void red_lossy_send_qxl_draw_whiteness(RedWorker *worker,
- DisplayChannel *display_channel,
- Drawable *item)
+static void red_send_qxl_draw_whiteness(RedWorker *worker,
+ DisplayChannel *display_channel,
+ Drawable *item)
{
- QXLDrawable *drawable = item->qxl_drawable;
RedChannel *channel = &display_channel->base;
+ QXLDrawable *drawable = item->qxl_drawable;
+ SpiceMarshaller *mask_bitmap_out;
+ SpiceWhiteness whiteness;
+
+ fill_base(display_channel, item);
+ channel->send_data.header->type = SPICE_MSG_DISPLAY_DRAW_WHITENESS;
+ whiteness = drawable->u.whiteness;
+
+ spice_marshall_Whiteness(channel->send_data.marshaller,
+ &whiteness,
+ &mask_bitmap_out);
+
+ fill_mask(display_channel, mask_bitmap_out, whiteness.mask.bitmap, item);
+}
+
+static void red_lossy_send_qxl_draw_whiteness(RedWorker *worker,
+ DisplayChannel *display_channel,
+ Drawable *item)
+{
+ QXLDrawable *drawable = item->qxl_drawable;
int has_mask = !!drawable->u.whiteness.mask.bitmap;
- channel->send_data.header.type = SPICE_MSG_DISPLAY_DRAW_WHITENESS;
- fill_base(display_channel, &display_channel->send_data.u.whiteness.base, item,
- sizeof(SpiceMsgDisplayDrawWhiteness), item->surface_id);
- display_channel->send_data.u.whiteness.data = drawable->u.whiteness;
- fill_mask(display_channel, &display_channel->send_data.u.whiteness.data.mask, item);
+ red_send_qxl_draw_whiteness(worker, display_channel, item);
surface_lossy_region_update(worker, display_channel, item, has_mask, FALSE);
}
-static inline void red_lossy_send_qxl_draw_inverse(RedWorker *worker,
- DisplayChannel *display_channel,
- Drawable *item)
+static void red_send_qxl_draw_inverse(RedWorker *worker,
+ DisplayChannel *display_channel,
+ Drawable *item)
{
QXLDrawable *drawable = item->qxl_drawable;
+ SpiceMarshaller *mask_bitmap_out;
RedChannel *channel = &display_channel->base;
+ SpiceInvers inverse;
+
+ fill_base(display_channel, item);
+ channel->send_data.header->type = SPICE_MSG_DISPLAY_DRAW_INVERS;
+ inverse = drawable->u.invers;
- channel->send_data.header.type = SPICE_MSG_DISPLAY_DRAW_INVERS;
- fill_base(display_channel, &display_channel->send_data.u.invers.base, item,
- sizeof(SpiceMsgDisplayDrawInvers), item->surface_id);
- display_channel->send_data.u.invers.data = drawable->u.invers;
- fill_mask(display_channel, &display_channel->send_data.u.invers.data.mask, item);
+ spice_marshall_Invers(channel->send_data.marshaller,
+ &inverse,
+ &mask_bitmap_out);
+
+ fill_mask(display_channel, mask_bitmap_out, inverse.mask.bitmap, item);
}
-static inline void red_lossy_send_qxl_draw_rop3(RedWorker *worker,
- DisplayChannel *display_channel,
- Drawable *item)
+static void red_lossy_send_qxl_draw_inverse(RedWorker *worker,
+ DisplayChannel *display_channel,
+ Drawable *item)
+{
+ red_send_qxl_draw_inverse(worker, display_channel, item);
+}
+
+static void red_send_qxl_draw_rop3(RedWorker *worker,
+ DisplayChannel *display_channel,
+ Drawable *item)
{
QXLDrawable *drawable = item->qxl_drawable;
RedChannel *channel = &display_channel->base;
+ SpiceRop3 rop3;
+ SpiceMarshaller *src_bitmap_out;
+ SpiceMarshaller *brush_pat_out;
+ SpiceMarshaller *mask_bitmap_out;
+
+ fill_base(display_channel, item);
+ channel->send_data.header->type = SPICE_MSG_DISPLAY_DRAW_ROP3;
+ rop3 = drawable->u.rop3;
+ spice_marshall_Rop3(channel->send_data.marshaller,
+ &rop3,
+ &src_bitmap_out,
+ &brush_pat_out,
+ &mask_bitmap_out);
+ fill_bits(display_channel, src_bitmap_out, rop3.src_bitmap, item, FALSE);
+
+ if (brush_pat_out) {
+ fill_bits(display_channel, brush_pat_out, rop3.brush.u.pattern.pat, item, FALSE);
+ }
+ fill_mask(display_channel, mask_bitmap_out, rop3.mask.bitmap, item);
+}
+
+static void red_lossy_send_qxl_draw_rop3(RedWorker *worker,
+ DisplayChannel *display_channel,
+ Drawable *item)
+{
+ QXLDrawable *drawable = item->qxl_drawable;
int src_is_lossy;
BitmapData src_bitmap_data;
int brush_is_lossy;
@@ -7706,14 +7976,7 @@ static inline void red_lossy_send_qxl_draw_rop3(RedWorker *worker,
(!brush_is_lossy || (brush_bitmap_data.type != BITMAP_DATA_TYPE_SURFACE)) &&
!dest_is_lossy) {
int has_mask = !!drawable->u.rop3.mask.bitmap;
- channel->send_data.header.type = SPICE_MSG_DISPLAY_DRAW_ROP3;
- fill_base(display_channel, &display_channel->send_data.u.rop3.base, item,
- sizeof(SpiceMsgDisplayDrawRop3), item->surface_id);
- display_channel->send_data.u.rop3.data = drawable->u.rop3;
- fill_bits(display_channel, &display_channel->send_data.u.rop3.data.src_bitmap,
- item, FALSE);
- fill_brush(display_channel, &display_channel->send_data.u.rop3.data.brush, item);
- fill_mask(display_channel, &display_channel->send_data.u.rop3.data.mask, item);
+ red_send_qxl_draw_rop3(worker, display_channel, item);
surface_lossy_region_update(worker, display_channel, item, has_mask, FALSE);
} else {
@@ -7744,12 +8007,39 @@ static inline void red_lossy_send_qxl_draw_rop3(RedWorker *worker,
}
}
-static inline void red_lossy_send_qxl_draw_stroke(RedWorker *worker,
- DisplayChannel *display_channel,
- Drawable *item)
+static void red_send_qxl_draw_stroke(RedWorker *worker,
+ DisplayChannel *display_channel,
+ Drawable *item)
{
QXLDrawable *drawable = item->qxl_drawable;
RedChannel *channel = &display_channel->base;
+ SpiceStroke stroke;
+ SpiceMarshaller *brush_pat_out;
+ SpiceMarshaller *path_out;
+ SpiceMarshaller *style_out;
+
+ fill_base(display_channel, item);
+
+ channel->send_data.header->type = SPICE_MSG_DISPLAY_DRAW_STROKE;
+ stroke = drawable->u.stroke;
+ spice_marshall_Stroke(channel->send_data.marshaller,
+ &stroke,
+ &path_out,
+ &style_out,
+ &brush_pat_out);
+
+ fill_path(display_channel, path_out, stroke.path, item->group_id);
+ fill_attr(display_channel, style_out, &stroke.attr, item->group_id);
+ if (brush_pat_out) {
+ fill_bits(display_channel, brush_pat_out, stroke.brush.u.pattern.pat, item, FALSE);
+ }
+}
+
+static void red_lossy_send_qxl_draw_stroke(RedWorker *worker,
+ DisplayChannel *display_channel,
+ Drawable *item)
+{
+ QXLDrawable *drawable = item->qxl_drawable;
int brush_is_lossy;
BitmapData brush_bitmap_data;
int dest_is_lossy = FALSE;
@@ -7763,24 +8053,18 @@ static inline void red_lossy_send_qxl_draw_stroke(RedWorker *worker,
rop = drawable->u.stroke.fore_mode;
// assuming that if the brush type is solid, the destination can
- // be lossy, no matter what the rop is.
+ // be lossy, no matter what the rop is.
if (drawable->u.stroke.brush.type != SPICE_BRUSH_TYPE_SOLID &&
((rop & SPICE_ROPD_OP_OR) || (rop & SPICE_ROPD_OP_AND) ||
(rop & SPICE_ROPD_OP_XOR))) {
dest_is_lossy = is_surface_area_lossy(display_channel, drawable->surface_id,
&drawable->bbox, &dest_lossy_area);
}
-
+
if (!dest_is_lossy &&
(!brush_is_lossy || (brush_bitmap_data.type != BITMAP_DATA_TYPE_SURFACE)))
{
- channel->send_data.header.type = SPICE_MSG_DISPLAY_DRAW_STROKE;
- fill_base(display_channel, &display_channel->send_data.u.stroke.base, item,
- sizeof(SpiceMsgDisplayDrawStroke), item->surface_id);
- display_channel->send_data.u.stroke.data = drawable->u.stroke;
- fill_path(display_channel, &display_channel->send_data.u.stroke.data.path, item->group_id);
- fill_attr(display_channel, &display_channel->send_data.u.stroke.data.attr, item->group_id);
- fill_brush(display_channel, &display_channel->send_data.u.stroke.data.brush, item);
+ red_send_qxl_draw_stroke(worker, display_channel, item);
} else {
int resend_surface_ids[2];
SpiceRect *resend_areas[2];
@@ -7805,12 +8089,42 @@ static inline void red_lossy_send_qxl_draw_stroke(RedWorker *worker,
}
-static inline void red_lossy_send_qxl_draw_text(RedWorker *worker,
- DisplayChannel *display_channel,
- Drawable *item)
+static void red_send_qxl_draw_text(RedWorker *worker,
+ DisplayChannel *display_channel,
+ Drawable *item)
{
QXLDrawable *drawable = item->qxl_drawable;
RedChannel *channel = &display_channel->base;
+ SpiceText text;
+ SpiceMarshaller *brush_pat_out;
+ SpiceMarshaller *back_brush_pat_out;
+ SpiceMarshaller *str_out;
+
+ fill_base(display_channel, item);
+
+ channel->send_data.header->type = SPICE_MSG_DISPLAY_DRAW_TEXT;
+ text = drawable->u.text;
+ spice_marshall_Text(channel->send_data.marshaller,
+ &text,
+ &str_out,
+ &brush_pat_out,
+ &back_brush_pat_out);
+
+ if (brush_pat_out) {
+ fill_bits(display_channel, brush_pat_out, text.fore_brush.u.pattern.pat, item, FALSE);
+ }
+ if (back_brush_pat_out) {
+ fill_bits(display_channel, back_brush_pat_out, text.back_brush.u.pattern.pat, item, FALSE);
+ }
+
+ fill_str(display_channel, str_out, text.str, item->group_id);
+}
+
+static void red_lossy_send_qxl_draw_text(RedWorker *worker,
+ DisplayChannel *display_channel,
+ Drawable *item)
+{
+ QXLDrawable *drawable = item->qxl_drawable;
int fg_is_lossy;
BitmapData fg_bitmap_data;
int bg_is_lossy;
@@ -7843,13 +8157,7 @@ static inline void red_lossy_send_qxl_draw_text(RedWorker *worker,
if (!dest_is_lossy &&
(!fg_is_lossy || (fg_bitmap_data.type != BITMAP_DATA_TYPE_SURFACE)) &&
(!bg_is_lossy || (bg_bitmap_data.type != BITMAP_DATA_TYPE_SURFACE))) {
- channel->send_data.header.type = SPICE_MSG_DISPLAY_DRAW_TEXT;
- fill_base(display_channel, &display_channel->send_data.u.text.base, item,
- sizeof(SpiceMsgDisplayDrawText), item->surface_id);
- display_channel->send_data.u.text.data = drawable->u.text;
- fill_brush(display_channel, &display_channel->send_data.u.text.data.fore_brush, item);
- fill_brush(display_channel, &display_channel->send_data.u.text.data.back_brush, item);
- fill_str(display_channel, &display_channel->send_data.u.text.data.str, item->group_id);
+ red_send_qxl_draw_text(worker, display_channel, item);
} else {
int resend_surface_ids[3];
SpiceRect *resend_areas[3];
@@ -7907,7 +8215,7 @@ static void red_lossy_send_qxl_drawable(RedWorker *worker, DisplayChannel *displ
break;
case QXL_DRAW_WHITENESS:
red_lossy_send_qxl_draw_whiteness(worker, display_channel, item);
- break;
+ break;
case QXL_DRAW_INVERS:
red_lossy_send_qxl_draw_inverse(worker, display_channel, item);
break;
@@ -7916,7 +8224,7 @@ static void red_lossy_send_qxl_drawable(RedWorker *worker, DisplayChannel *displ
break;
case QXL_DRAW_STROKE:
red_lossy_send_qxl_draw_stroke(worker, display_channel, item);
- break;
+ break;
case QXL_DRAW_TEXT:
red_lossy_send_qxl_draw_text(worker, display_channel, item);
break;
@@ -7925,7 +8233,7 @@ static void red_lossy_send_qxl_drawable(RedWorker *worker, DisplayChannel *displ
}
// a message is pending
- if (display_channel->base.send_data.header.size) {
+ if (display_channel->base.send_data.header->type != 0) {
display_begin_send_massage(display_channel, &item->pipe_item);
}
}
@@ -7935,113 +8243,45 @@ static inline void red_send_qxl_drawable(RedWorker *worker, DisplayChannel *disp
{
QXLDrawable *drawable = item->qxl_drawable;
- RedChannel *channel = &display_channel->base;
switch (drawable->type) {
case QXL_DRAW_FILL:
- channel->send_data.header.type = SPICE_MSG_DISPLAY_DRAW_FILL;
- fill_base(display_channel, &display_channel->send_data.u.fill.base, item,
- sizeof(SpiceMsgDisplayDrawFill), item->surface_id);
- display_channel->send_data.u.fill.data = drawable->u.fill;
- fill_brush(display_channel, &display_channel->send_data.u.fill.data.brush, item);
- fill_mask(display_channel, &display_channel->send_data.u.fill.data.mask, item);
+ red_send_qxl_draw_fill(worker, display_channel, item);
break;
case QXL_DRAW_OPAQUE:
- channel->send_data.header.type = SPICE_MSG_DISPLAY_DRAW_OPAQUE;
- fill_base(display_channel, &display_channel->send_data.u.opaque.base, item,
- sizeof(SpiceMsgDisplayDrawOpaque), item->surface_id);
- display_channel->send_data.u.opaque.data = drawable->u.opaque;
- fill_bits(display_channel, &display_channel->send_data.u.opaque.data.src_bitmap,
- item, FALSE);
- fill_brush(display_channel, &display_channel->send_data.u.opaque.data.brush, item);
- fill_mask(display_channel, &display_channel->send_data.u.opaque.data.mask, item);
+ red_send_qxl_draw_opaque(worker, display_channel, item, FALSE);
break;
case QXL_DRAW_COPY:
- channel->send_data.header.type = SPICE_MSG_DISPLAY_DRAW_COPY;
- fill_base(display_channel, &display_channel->send_data.u.copy.base, item,
- sizeof(SpiceMsgDisplayDrawCopy), item->surface_id);
- display_channel->send_data.u.copy.data = drawable->u.copy;
- fill_bits(display_channel, &display_channel->send_data.u.copy.data.src_bitmap, item, FALSE);
- fill_mask(display_channel, &display_channel->send_data.u.copy.data.mask, item);
+ red_send_qxl_draw_copy(worker, display_channel, item, FALSE);
break;
case QXL_DRAW_TRANSPARENT:
- channel->send_data.header.type = SPICE_MSG_DISPLAY_DRAW_TRANSPARENT;
- fill_base(display_channel, &display_channel->send_data.u.transparent.base, item,
- sizeof(SpiceMsgDisplayDrawTransparent), item->surface_id);
- display_channel->send_data.u.transparent.data = drawable->u.transparent;
- fill_bits(display_channel, &display_channel->send_data.u.transparent.data.src_bitmap,
- item, FALSE);
+ red_send_qxl_draw_transparent(worker, display_channel, item);
break;
case QXL_DRAW_ALPHA_BLEND:
- channel->send_data.header.type = SPICE_MSG_DISPLAY_DRAW_ALPHA_BLEND;
- fill_base(display_channel, &display_channel->send_data.u.alpha_blend.base, item,
- sizeof(SpiceMsgDisplayDrawAlphaBlend), item->surface_id);
- display_channel->send_data.u.alpha_blend.data = drawable->u.alpha_blend;
- fill_bits(display_channel, &display_channel->send_data.u.alpha_blend.data.src_bitmap,
- item, FALSE);
+ red_send_qxl_draw_alpha_blend(worker, display_channel, item, FALSE);
break;
case QXL_COPY_BITS:
- channel->send_data.header.type = SPICE_MSG_DISPLAY_COPY_BITS;
- fill_base(display_channel, &display_channel->send_data.u.copy_bits.base, item,
- sizeof(SpiceMsgDisplayCopyBits), item->surface_id);
- display_channel->send_data.u.copy_bits.src_pos = drawable->u.copy_bits.src_pos;
+ red_send_qxl_copy_bits(worker, display_channel, item);
break;
case QXL_DRAW_BLEND:
- channel->send_data.header.type = SPICE_MSG_DISPLAY_DRAW_BLEND;
- fill_base(display_channel, &display_channel->send_data.u.blend.base, item,
- sizeof(SpiceMsgDisplayDrawBlend), item->surface_id);
- display_channel->send_data.u.blend.data = drawable->u.blend;
- fill_bits(display_channel, &display_channel->send_data.u.blend.data.src_bitmap,
- item, FALSE);
- fill_mask(display_channel, &display_channel->send_data.u.blend.data.mask, item);
+ red_send_qxl_draw_blend(worker, display_channel, item);
break;
case QXL_DRAW_BLACKNESS:
- channel->send_data.header.type = SPICE_MSG_DISPLAY_DRAW_BLACKNESS;
- fill_base(display_channel, &display_channel->send_data.u.blackness.base, item,
- sizeof(SpiceMsgDisplayDrawBlackness), item->surface_id);
- display_channel->send_data.u.blackness.data = drawable->u.blackness;
- fill_mask(display_channel, &display_channel->send_data.u.blackness.data.mask, item);
+ red_send_qxl_draw_blackness(worker, display_channel, item);
break;
case QXL_DRAW_WHITENESS:
- channel->send_data.header.type = SPICE_MSG_DISPLAY_DRAW_WHITENESS;
- fill_base(display_channel, &display_channel->send_data.u.whiteness.base, item,
- sizeof(SpiceMsgDisplayDrawWhiteness), item->surface_id);
- display_channel->send_data.u.whiteness.data = drawable->u.whiteness;
- fill_mask(display_channel, &display_channel->send_data.u.whiteness.data.mask, item);
+ red_send_qxl_draw_whiteness(worker, display_channel, item);
break;
case QXL_DRAW_INVERS:
- channel->send_data.header.type = SPICE_MSG_DISPLAY_DRAW_INVERS;
- fill_base(display_channel, &display_channel->send_data.u.invers.base, item,
- sizeof(SpiceMsgDisplayDrawInvers), item->surface_id);
- display_channel->send_data.u.invers.data = drawable->u.invers;
- fill_mask(display_channel, &display_channel->send_data.u.invers.data.mask, item);
+ red_send_qxl_draw_inverse(worker, display_channel, item);
break;
case QXL_DRAW_ROP3:
- channel->send_data.header.type = SPICE_MSG_DISPLAY_DRAW_ROP3;
- fill_base(display_channel, &display_channel->send_data.u.rop3.base, item,
- sizeof(SpiceMsgDisplayDrawRop3), item->surface_id);
- display_channel->send_data.u.rop3.data = drawable->u.rop3;
- fill_bits(display_channel, &display_channel->send_data.u.rop3.data.src_bitmap,
- item, FALSE);
- fill_brush(display_channel, &display_channel->send_data.u.rop3.data.brush, item);
- fill_mask(display_channel, &display_channel->send_data.u.rop3.data.mask, item);
+ red_send_qxl_draw_rop3(worker, display_channel, item);
break;
case QXL_DRAW_STROKE:
- channel->send_data.header.type = SPICE_MSG_DISPLAY_DRAW_STROKE;
- fill_base(display_channel, &display_channel->send_data.u.stroke.base, item,
- sizeof(SpiceMsgDisplayDrawStroke), item->surface_id);
- display_channel->send_data.u.stroke.data = drawable->u.stroke;
- fill_path(display_channel, &display_channel->send_data.u.stroke.data.path, item->group_id);
- fill_attr(display_channel, &display_channel->send_data.u.stroke.data.attr, item->group_id);
- fill_brush(display_channel, &display_channel->send_data.u.stroke.data.brush, item);
+ red_send_qxl_draw_stroke(worker, display_channel, item);
break;
case QXL_DRAW_TEXT:
- channel->send_data.header.type = SPICE_MSG_DISPLAY_DRAW_TEXT;
- fill_base(display_channel, &display_channel->send_data.u.text.base, item,
- sizeof(SpiceMsgDisplayDrawText), item->surface_id);
- display_channel->send_data.u.text.data = drawable->u.text;
- fill_brush(display_channel, &display_channel->send_data.u.text.data.fore_brush, item);
- fill_brush(display_channel, &display_channel->send_data.u.text.data.back_brush, item);
- fill_str(display_channel, &display_channel->send_data.u.text.data.str, item->group_id);
+ red_send_qxl_draw_text(worker, display_channel, item);
break;
default:
red_error("invalid type");
@@ -8051,105 +8291,6 @@ static inline void red_send_qxl_drawable(RedWorker *worker, DisplayChannel *disp
#define MAX_SEND_VEC 100
-static inline BufDescriptor *find_buf(RedChannel *channel, int buf_pos, int *buf_offset)
-{
- BufDescriptor *buf;
- int pos = 0;
-
- for (buf = channel->send_data.bufs; buf_pos >= pos + buf->size; buf++) {
- pos += buf->size;
- ASSERT(buf != &channel->send_data.bufs[channel->send_data.n_bufs - 1]);
- }
- *buf_offset = buf_pos - pos;
- return buf;
-}
-
-static inline uint32_t __fill_iovec(RedWorker *worker, BufDescriptor *buf, int skip,
- struct iovec *vec, int *vec_index)
-{
- uint32_t size = 0;
-
- switch (buf->type) {
- case BUF_TYPE_RAW:
- vec[*vec_index].iov_base = buf->data + skip;
- vec[*vec_index].iov_len = size = buf->size - skip;
- (*vec_index)++;
- break;
- case BUF_TYPE_COMPRESS_BUF: {
- RedCompressBuf *comp_buf = (RedCompressBuf *)buf->data;
- int max = buf->size - skip;
- int now;
- do {
- ASSERT(comp_buf);
- if (skip >= sizeof(comp_buf->buf)) {
- skip -= sizeof(comp_buf->buf);
- comp_buf = comp_buf->send_next;
- continue;
- }
- now = MIN(sizeof(comp_buf->buf) - skip, max);
- max -= now;
- size += now;
- vec[*vec_index].iov_base = (uint8_t*)comp_buf->buf + skip;
- vec[*vec_index].iov_len = now;
- skip = 0;
- comp_buf = comp_buf->send_next;
- (*vec_index)++;
- } while (max && *vec_index < MAX_SEND_VEC);
- break;
- }
- case BUF_TYPE_CHUNK: {
- QXLDataChunk *chunk = (QXLDataChunk *)buf->data;
- do {
- int data_size = chunk->data_size;
- int skip_now = MIN(data_size, skip);
- skip -= skip_now;
- data_size -= skip_now;
-
- if (data_size) {
- validate_virt(&worker->mem_slots, (unsigned long)chunk->data, buf->slot_id, data_size,
- buf->group_id);
- size += data_size;
- vec[*vec_index].iov_base = chunk->data + skip_now;
- vec[*vec_index].iov_len = data_size;
- (*vec_index)++;
- }
- chunk = chunk->next_chunk ?
- (QXLDataChunk *)get_virt(&worker->mem_slots, chunk->next_chunk, sizeof(QXLDataChunk),
- buf->group_id) :
- NULL;
- } while (chunk && *vec_index < MAX_SEND_VEC);
- break;
- }
- default:
- red_error("invalid type");
- }
- return size;
-}
-
-static inline void fill_iovec(RedChannel *channel, struct iovec *vec, int *vec_size)
-{
- int rc, vec_index = 0;
- uint32_t pos = channel->send_data.pos;
-
- ASSERT(channel->send_data.size != pos && channel->send_data.size > pos);
-
- do {
- BufDescriptor *buf;
- int buf_offset;
-
- buf = find_buf(channel, pos, &buf_offset);
- ASSERT(buf);
- rc = __fill_iovec(channel->worker, buf, buf_offset, vec, &vec_index);
- if (rc == 0) {
- fprintf(stderr, "%s: got only %d of %d bytes\n", __FUNCTION__,
- pos, channel->send_data.size);
- abort();
- }
- pos += rc;
- } while (vec_index < MAX_SEND_VEC && pos != channel->send_data.size);
- *vec_size = vec_index;
-}
-
static void inline channel_release_res(RedChannel *channel)
{
if (!channel->send_data.item) {
@@ -8174,7 +8315,8 @@ static void red_send_data(RedChannel *channel, void *item)
}
break;
}
- fill_iovec(channel, vec, &vec_size);
+ vec_size = spice_marshaller_fill_iovec(channel->send_data.marshaller,
+ vec, MAX_SEND_VEC, channel->send_data.pos);
ASSERT(channel->peer);
if ((n = channel->peer->cb_writev(channel->peer->ctx, vec, vec_size)) == -1) {
switch (errno) {
@@ -8228,8 +8370,11 @@ static void display_channel_push_release(DisplayChannel *channel, uint8_t type,
static inline void red_begin_send_massage(RedChannel *channel, void *item)
{
- channel->send_data.size = channel->send_data.header.size + sizeof(SpiceDataHeader);
+ spice_marshaller_flush(channel->send_data.marshaller);
+ channel->send_data.size = spice_marshaller_get_total_size(channel->send_data.marshaller);
+ channel->send_data.header->size = channel->send_data.size - sizeof(SpiceDataHeader);
channel->messages_window++;
+ channel->send_data.header = NULL; /* avoid writing to this until we have a new message */
red_send_data(channel, item);
}
@@ -8238,11 +8383,20 @@ static inline void display_begin_send_massage(DisplayChannel *channel, void *ite
FreeList *free_list = &channel->send_data.free_list;
if (0 && free_list->res->count) {
+ int sub_list_len = 1;
+ SpiceMarshaller *wait_m = NULL;
+ SpiceMarshaller *inval_m;
int sync_count = 0;
- int sub_index;
int i;
- channel->base.send_data.header.sub_list = channel->base.send_data.header.size;
+ inval_m = spice_marshaller_get_submarshaller(channel->base.send_data.marshaller);
+
+ /* type + size + submessage */
+ spice_marshaller_add_uint16(inval_m, SPICE_MSG_DISPLAY_INVAL_LIST);
+ spice_marshaller_add_uint32(inval_m,
+ sizeof(*free_list->res) + free_list->res->count * sizeof(free_list->res->resources[0]));
+ spice_marshall_msg_display_inval_list(inval_m, free_list->res);
+
for (i = 0; i < MAX_CACHE_CLIENTS; i++) {
if (i != channel->base.id && free_list->sync[i] != 0) {
free_list->wait.header.wait_list[sync_count].channel_type = SPICE_CHANNEL_DISPLAY;
@@ -8250,36 +8404,26 @@ static inline void display_begin_send_massage(DisplayChannel *channel, void *ite
free_list->wait.header.wait_list[sync_count++].message_serial = free_list->sync[i];
}
}
- SpiceSubMessageList *sub_list = &channel->send_data.sub_list.sub_list;
- SpicedSubMessage *sub_header = channel->send_data.sub_header;
+ free_list->wait.header.wait_count = sync_count;
+
if (sync_count) {
- sub_list->size = 2;
- add_buf((RedChannel*)channel, BUF_TYPE_RAW, sub_list,
- sizeof(*sub_list) + 2 * sizeof(sub_list->sub_messages[0]), 0, 0);
- sub_list->sub_messages[0] = channel->base.send_data.header.size;
- sub_header[0].type = SPICE_MSG_WAIT_FOR_CHANNELS;
- sub_header[0].size = sizeof(free_list->wait.header) +
- sync_count * sizeof(free_list->wait.buf[0]);
- add_buf((RedChannel*)channel, BUF_TYPE_RAW, sub_header, sizeof(*sub_header), 0, 0);
- free_list->wait.header.wait_count = sync_count;
- add_buf((RedChannel*)channel, BUF_TYPE_RAW, &free_list->wait.header,
- sub_header[0].size, 0, 0);
- sub_list->sub_messages[1] = channel->base.send_data.header.size;
- sub_index = 1;
- } else {
- sub_list->size = 1;
- add_buf((RedChannel*)channel, BUF_TYPE_RAW, sub_list,
- sizeof(*sub_list) + sizeof(sub_list->sub_messages[0]), 0, 0);
- sub_list->sub_messages[0] = channel->base.send_data.header.size;
- sub_index = 0;
- }
- sub_header[sub_index].type = SPICE_MSG_DISPLAY_INVAL_LIST;
- sub_header[sub_index].size = sizeof(*free_list->res) + free_list->res->count *
- sizeof(free_list->res->resources[0]);
- add_buf((RedChannel*)channel, BUF_TYPE_RAW, &sub_header[sub_index], sizeof(*sub_header), 0,
- 0);
- add_buf((RedChannel*)channel, BUF_TYPE_RAW, free_list->res, sub_header[sub_index].size, 0,
- 0);
+ wait_m = spice_marshaller_get_submarshaller(channel->base.send_data.marshaller);
+
+ /* type + size + submessage */
+ spice_marshaller_add_uint16(wait_m, SPICE_MSG_WAIT_FOR_CHANNELS);
+ spice_marshaller_add_uint32(wait_m,
+ sizeof(free_list->wait.header) + sync_count * sizeof(free_list->wait.buf[0]));
+ spice_marshall_msg_wait_for_channels(wait_m, &free_list->wait.header);
+ sub_list_len++;
+ }
+
+ SpiceMarshaller *sub_list_m = spice_marshaller_get_submarshaller(channel->base.send_data.marshaller);
+ spice_marshaller_add_uint16(sub_list_m, sub_list_len);
+ if (wait_m) {
+ spice_marshaller_add_uint32(sub_list_m, spice_marshaller_get_offset(wait_m));
+ }
+ spice_marshaller_add_uint32(sub_list_m, spice_marshaller_get_offset(inval_m));
+ channel->base.send_data.header->sub_list = spice_marshaller_get_offset(sub_list_m);
}
red_begin_send_massage((RedChannel *)channel, item);
}
@@ -8297,6 +8441,7 @@ static inline void red_unref_channel(RedChannel *channel)
{
ASSERT(channel);
if (!--channel->listener.refs) {
+ spice_marshaller_destroy(channel->send_data.marshaller);
free(channel);
}
}
@@ -8565,17 +8710,18 @@ static inline int red_send_stream_data(DisplayChannel *display_channel, Drawable
red_display_share_stream_buf(display_channel);
}
- channel->send_data.header.type = SPICE_MSG_DISPLAY_STREAM_DATA;
+ channel->send_data.header->type = SPICE_MSG_DISPLAY_STREAM_DATA;
+
+ SpiceMsgDisplayStreamData stream_data;
- SpiceMsgDisplayStreamData* stream_data = &display_channel->send_data.u.stream_data;
- add_buf(channel, BUF_TYPE_RAW, stream_data, sizeof(SpiceMsgDisplayStreamData), 0, 0);
- add_buf(channel, BUF_TYPE_RAW, display_channel->send_data.stream_outbuf,
- n + PADDING, 0, 0);
+ stream_data.id = stream - worker->streams_buf;
+ stream_data.multi_media_time = drawable->qxl_drawable->mm_time;
+ stream_data.data_size = n;
+ stream_data.pad_size = PADDING;
+ spice_marshall_msg_display_stream_data(channel->send_data.marshaller, &stream_data);
+ spice_marshaller_add_ref(channel->send_data.marshaller,
+ display_channel->send_data.stream_outbuf, n + PADDING);
- stream_data->id = stream - worker->streams_buf;
- stream_data->multi_media_time = drawable->qxl_drawable->mm_time;
- stream_data->data_size = n;
- stream_data->pad_size = PADDING;
display_begin_send_massage(display_channel, NULL);
agent->lats_send_time = time_now;
return TRUE;
@@ -8599,136 +8745,139 @@ static inline void send_qxl_drawable(DisplayChannel *display_channel, Drawable *
static void red_send_set_ack(RedChannel *channel)
{
+ SpiceMsgSetAck ack;
+
ASSERT(channel);
- channel->send_data.header.type = SPICE_MSG_SET_ACK;
- channel->send_data.u.ack.generation = ++channel->ack_generation;
- channel->send_data.u.ack.window = channel->client_ack_window;
+ channel->send_data.header->type = SPICE_MSG_SET_ACK;
+ ack.generation = ++channel->ack_generation;
+ ack.window = channel->client_ack_window;
channel->messages_window = 0;
- add_buf(channel, BUF_TYPE_RAW, &channel->send_data.u.ack, sizeof(SpiceMsgSetAck), 0, 0);
+ spice_marshall_msg_set_ack(channel->send_data.marshaller, &ack);
+
red_begin_send_massage(channel, NULL);
}
static inline void red_send_verb(RedChannel *channel, uint16_t verb)
{
ASSERT(channel);
- channel->send_data.header.type = verb;
+ channel->send_data.header->type = verb;
red_begin_send_massage(channel, NULL);
}
static inline void display_send_verb(DisplayChannel *channel, uint16_t verb)
{
ASSERT(channel);
- channel->base.send_data.header.type = verb;
+ channel->base.send_data.header->type = verb;
display_begin_send_massage(channel, NULL);
}
-static inline void __red_send_inval(RedChannel *channel, CacheItem *cach_item,
- SpiceMsgDisplayInvalOne *inval_one)
+static inline void __red_send_inval(RedChannel *channel, CacheItem *cach_item)
{
- channel->send_data.header.type = cach_item->inval_type;
- inval_one->id = *(uint64_t *)&cach_item->id;
- add_buf(channel, BUF_TYPE_RAW, inval_one, sizeof(*inval_one), 0, 0);
+ SpiceMsgDisplayInvalOne inval_one;
+
+ channel->send_data.header->type = cach_item->inval_type;
+ inval_one.id = *(uint64_t *)&cach_item->id;
+
+ spice_marshall_msg_cursor_inval_one(channel->send_data.marshaller, &inval_one);
}
-static void red_send_inval(RedChannel *channel, CacheItem *cach_item, SpiceMsgDisplayInvalOne *inval_one)
+static void red_send_inval(RedChannel *channel, CacheItem *cach_item)
{
- __red_send_inval(channel, cach_item, inval_one);
+ __red_send_inval(channel, cach_item);
red_begin_send_massage(channel, NULL);
}
static void red_display_send_inval(DisplayChannel *display_channel, CacheItem *cach_item)
{
- __red_send_inval((RedChannel *)display_channel, cach_item,
- &display_channel->send_data.u.inval_one);
+ __red_send_inval((RedChannel *)display_channel, cach_item);
display_begin_send_massage(display_channel, NULL);
}
static void display_channel_send_migrate(DisplayChannel *display_channel)
{
- display_channel->base.send_data.header.type = SPICE_MSG_MIGRATE;
- display_channel->send_data.u.migrate.flags = SPICE_MIGRATE_NEED_FLUSH |
- SPICE_MIGRATE_NEED_DATA_TRANSFER;
- add_buf((RedChannel*)display_channel, BUF_TYPE_RAW, &display_channel->send_data.u.migrate,
- sizeof(display_channel->send_data.u.migrate), 0, 0);
+ SpiceMsgMigrate migrate;
+
+ display_channel->base.send_data.header->type = SPICE_MSG_MIGRATE;
+ migrate.flags = SPICE_MIGRATE_NEED_FLUSH | SPICE_MIGRATE_NEED_DATA_TRANSFER;
+ spice_marshall_msg_migrate(display_channel->base.send_data.marshaller, &migrate);
display_channel->expect_migrate_mark = TRUE;
display_begin_send_massage(display_channel, NULL);
}
static void display_channel_send_migrate_data(DisplayChannel *display_channel)
{
- DisplayChannelMigrateData* display_data;
+ DisplayChannelMigrateData display_data;
+
+ display_channel->base.send_data.header->type = SPICE_MSG_MIGRATE_DATA;
- display_channel->base.send_data.header.type = SPICE_MSG_MIGRATE_DATA;
ASSERT(display_channel->pixmap_cache);
- display_data = &display_channel->send_data.u.migrate_data;
- display_data->magic = DISPLAY_MIGRATE_DATA_MAGIC;
+ display_data.magic = DISPLAY_MIGRATE_DATA_MAGIC;
ASSERT(MAX_CACHE_CLIENTS == 4); //MIGRATE_DATA_VERSION dependent
- display_data->version = DISPLAY_MIGRATE_DATA_VERSION;
+ display_data.version = DISPLAY_MIGRATE_DATA_VERSION;
- display_data->message_serial = channel_message_serial((RedChannel *)display_channel);
+ display_data.message_serial = channel_message_serial((RedChannel *)display_channel);
- display_data->pixmap_cache_freezer = pixmap_cache_freeze(display_channel->pixmap_cache);
- display_data->pixmap_cache_id = display_channel->pixmap_cache->id;
- display_data->pixmap_cache_size = display_channel->pixmap_cache->size;
- memcpy(display_data->pixmap_cache_clients, display_channel->pixmap_cache->sync,
- sizeof(display_data->pixmap_cache_clients));
+ display_data.pixmap_cache_freezer = pixmap_cache_freeze(display_channel->pixmap_cache);
+ display_data.pixmap_cache_id = display_channel->pixmap_cache->id;
+ display_data.pixmap_cache_size = display_channel->pixmap_cache->size;
+ memcpy(display_data.pixmap_cache_clients, display_channel->pixmap_cache->sync,
+ sizeof(display_data.pixmap_cache_clients));
ASSERT(display_channel->glz_dict);
red_freeze_glz(display_channel);
- display_data->glz_dict_id = display_channel->glz_dict->id;
+ display_data.glz_dict_id = display_channel->glz_dict->id;
glz_enc_dictionary_get_restore_data(display_channel->glz_dict->dict,
- &display_data->glz_dict_restore_data,
+ &display_data.glz_dict_restore_data,
&display_channel->glz_data.usr);
- add_buf((RedChannel *)display_channel, BUF_TYPE_RAW, &display_channel->send_data.u.migrate_data,
- sizeof(display_channel->send_data.u.migrate_data), 0, 0);
+ spice_marshaller_add_ref(display_channel->base.send_data.marshaller,
+ (uint8_t *)&display_data, sizeof(display_data));
display_begin_send_massage(display_channel, NULL);
}
static void display_channel_pixmap_sync(DisplayChannel *display_channel)
{
- SpiceMsgWaitForChannels *wait;
+ SpiceMsgWaitForChannels wait;
PixmapCache *pixmap_cache;
- display_channel->base.send_data.header.type = SPICE_MSG_WAIT_FOR_CHANNELS;
- wait = &display_channel->send_data.u.wait.header;
+ display_channel->base.send_data.header->type = SPICE_MSG_WAIT_FOR_CHANNELS;
pixmap_cache = display_channel->pixmap_cache;
pthread_mutex_lock(&pixmap_cache->lock);
- wait->wait_count = 1;
- wait->wait_list[0].channel_type = SPICE_CHANNEL_DISPLAY;
- wait->wait_list[0].channel_id = pixmap_cache->generation_initiator.client;
- wait->wait_list[0].message_serial = pixmap_cache->generation_initiator.message;
+ wait.wait_count = 1;
+ wait.wait_list[0].channel_type = SPICE_CHANNEL_DISPLAY;
+ wait.wait_list[0].channel_id = pixmap_cache->generation_initiator.client;
+ wait.wait_list[0].message_serial = pixmap_cache->generation_initiator.message;
display_channel->pixmap_cache_generation = pixmap_cache->generation;
display_channel->pending_pixmaps_sync = FALSE;
pthread_mutex_unlock(&pixmap_cache->lock);
- add_buf((RedChannel *)display_channel, BUF_TYPE_RAW, wait,
- sizeof(*wait) + sizeof(wait->wait_list[0]), 0, 0);
+ spice_marshall_msg_wait_for_channels(display_channel->base.send_data.marshaller, &wait);
+
display_begin_send_massage(display_channel, NULL);
}
static void display_channel_reset_cache(DisplayChannel *display_channel)
{
- SpiceMsgWaitForChannels *wait = &display_channel->send_data.u.wait.header;
+ SpiceMsgWaitForChannels wait;
- display_channel->base.send_data.header.type = SPICE_MSG_DISPLAY_INVAL_ALL_PIXMAPS;
- pixmap_cache_reset(display_channel->pixmap_cache, display_channel, wait);
+ display_channel->base.send_data.header->type = SPICE_MSG_DISPLAY_INVAL_ALL_PIXMAPS;
+ pixmap_cache_reset(display_channel->pixmap_cache, display_channel, &wait);
- add_buf((RedChannel *)display_channel, BUF_TYPE_RAW, wait,
- sizeof(*wait) + wait->wait_count * sizeof(wait->wait_list[0]), 0, 0);
+ spice_marshall_msg_display_inval_all_pixmaps(display_channel->base.send_data.marshaller,
+ &wait);
display_begin_send_massage(display_channel, NULL);
}
static void red_send_image(DisplayChannel *display_channel, ImageItem *item)
{
RedChannel *channel;
- RedImage *red_image;
+ RedImage red_image;
RedWorker *worker;
SpiceBitmap bitmap;
QRegion *surface_lossy_region;
@@ -8736,19 +8885,19 @@ static void red_send_image(DisplayChannel *display_channel, ImageItem *item)
int lossy_comp = FALSE;
int lz_comp = FALSE;
spice_image_compression_t comp_mode;
+ SpiceMsgDisplayDrawCopy copy;
+ SpiceMarshaller *cliprects_data_out, *clippath_data_out, *src_bitmap_out, *mask_bitmap_out;
+ SpiceMarshaller *bitmap_palette_out, *data_out, *lzplt_palette_out;
ASSERT(display_channel && item);
channel = &display_channel->base;
worker = channel->worker;
- red_image = alloc_image(display_channel);
- ASSERT(red_image);
-
- QXL_SET_IMAGE_ID(red_image, QXL_IMAGE_GROUP_RED, ++worker->bits_unique);
- red_image->descriptor.type = SPICE_IMAGE_TYPE_BITMAP;
- red_image->descriptor.flags = item->image_flags;
- red_image->descriptor.width = item->width;
- red_image->descriptor.height = item->height;
+ QXL_SET_IMAGE_ID(&red_image, QXL_IMAGE_GROUP_RED, ++worker->bits_unique);
+ red_image.descriptor.type = SPICE_IMAGE_TYPE_BITMAP;
+ red_image.descriptor.flags = item->image_flags;
+ red_image.descriptor.width = item->width;
+ red_image.descriptor.height = item->height;
bitmap.format = item->image_format;
bitmap.flags = QXL_BITMAP_DIRECT;
@@ -8759,26 +8908,35 @@ static void red_send_image(DisplayChannel *display_channel, ImageItem *item)
bitmap.palette = 0;
bitmap.data = (SPICE_ADDRESS)item->data;
- channel->send_data.header.type = SPICE_MSG_DISPLAY_DRAW_COPY;
-
- add_buf(channel, BUF_TYPE_RAW, &display_channel->send_data.u.copy, sizeof(SpiceMsgDisplayDrawCopy), 0, 0);
- display_channel->send_data.u.copy.base.surface_id = item->surface_id;
- display_channel->send_data.u.copy.base.box.left = item->pos.x;
- display_channel->send_data.u.copy.base.box.top = item->pos.y;
- display_channel->send_data.u.copy.base.box.right = item->pos.x + bitmap.x;
- display_channel->send_data.u.copy.base.box.bottom = item->pos.y + bitmap.y;
- display_channel->send_data.u.copy.base.clip.type = SPICE_CLIP_TYPE_NONE;
- display_channel->send_data.u.copy.base.clip.data = 0;
- display_channel->send_data.u.copy.data.rop_decriptor = SPICE_ROPD_OP_PUT;
- display_channel->send_data.u.copy.data.src_area.left = 0;
- display_channel->send_data.u.copy.data.src_area.top = 0;
- display_channel->send_data.u.copy.data.src_area.right = bitmap.x;
- display_channel->send_data.u.copy.data.src_area.bottom = bitmap.y;
- display_channel->send_data.u.copy.data.scale_mode = 0;
- display_channel->send_data.u.copy.data.src_bitmap = channel->send_data.header.size;
- display_channel->send_data.u.copy.data.mask.bitmap = 0;
-
- compress_send_data_t comp_send_data;
+ channel->send_data.header->type = SPICE_MSG_DISPLAY_DRAW_COPY;
+
+ copy.base.surface_id = item->surface_id;
+ copy.base.box.left = item->pos.x;
+ copy.base.box.top = item->pos.y;
+ copy.base.box.right = item->pos.x + bitmap.x;
+ copy.base.box.bottom = item->pos.y + bitmap.y;
+ copy.base.clip.type = SPICE_CLIP_TYPE_NONE;
+ copy.base.clip.data = 0;
+ copy.data.rop_decriptor = SPICE_ROPD_OP_PUT;
+ copy.data.src_area.left = 0;
+ copy.data.src_area.top = 0;
+ copy.data.src_area.right = bitmap.x;
+ copy.data.src_area.bottom = bitmap.y;
+ copy.data.scale_mode = 0;
+ copy.data.src_bitmap = 0;
+ copy.data.mask.flags = 0;
+ copy.data.mask.flags = 0;
+ copy.data.mask.pos.x = 0;
+ copy.data.mask.pos.y = 0;
+ copy.data.mask.bitmap = 0;
+
+ SpiceMarshaller *m = channel->send_data.marshaller;
+
+ spice_marshall_msg_display_draw_copy(m, ©,
+ &cliprects_data_out, &clippath_data_out,
+ &src_bitmap_out, &mask_bitmap_out);
+
+ compress_send_data_t comp_send_data = {0};
comp_mode = display_channel->base.worker->image_compression;
@@ -8803,39 +8961,47 @@ static void red_send_image(DisplayChannel *display_channel, ImageItem *item)
}
if (lossy_comp) {
- comp_succeeded = red_jpeg_compress_image(display_channel, red_image,
+ comp_succeeded = red_jpeg_compress_image(display_channel, &red_image,
&bitmap, &comp_send_data,
worker->mem_slots.internal_groupslot_id);
} else {
if (!lz_comp) {
- comp_succeeded = red_quic_compress_image(display_channel, red_image, &bitmap,
+ comp_succeeded = red_quic_compress_image(display_channel, &red_image, &bitmap,
&comp_send_data,
worker->mem_slots.internal_groupslot_id);
} else {
- comp_succeeded = red_lz_compress_image(display_channel, red_image, &bitmap,
+ comp_succeeded = red_lz_compress_image(display_channel, &red_image, &bitmap,
&comp_send_data,
worker->mem_slots.internal_groupslot_id);
}
}
-
+
surface_lossy_region = &display_channel->surface_client_lossy_region[item->surface_id];
if (comp_succeeded) {
- add_buf(channel, BUF_TYPE_RAW, red_image, comp_send_data.raw_size, 0, 0);
- add_buf(channel, BUF_TYPE_COMPRESS_BUF, comp_send_data.comp_buf,
- comp_send_data.comp_buf_size, 0, 0);
+ spice_marshall_Image(src_bitmap_out, (SpiceImageDescriptor *)&red_image,
+ &bitmap_palette_out, &data_out, &lzplt_palette_out);
+
+ marshaller_add_compressed(worker, src_bitmap_out,
+ comp_send_data.comp_buf, comp_send_data.comp_buf_size);
+
+ if (comp_send_data.lzplt_palette) {
+ spice_marshall_Palette(lzplt_palette_out, comp_send_data.lzplt_palette);
+ }
+
if (lossy_comp) {
- region_add(surface_lossy_region, &display_channel->send_data.u.copy.base.box);
+ region_add(surface_lossy_region, ©.base.box);
} else {
- region_remove(surface_lossy_region, &display_channel->send_data.u.copy.base.box);
+ region_remove(surface_lossy_region, ©.base.box);
}
} else {
- red_image->descriptor.type = SPICE_IMAGE_TYPE_BITMAP;
- red_image->bitmap = bitmap;
- red_image->bitmap.flags &= ~QXL_BITMAP_DIRECT;
- add_buf(channel, BUF_TYPE_RAW, red_image, sizeof(SpiceBitmapImage), 0, 0);
- red_image->bitmap.data = channel->send_data.header.size;
- add_buf(channel, BUF_TYPE_RAW, item->data, bitmap.y * bitmap.stride, 0, 0);
- region_remove(surface_lossy_region, &display_channel->send_data.u.copy.base.box);
+ red_image.descriptor.type = SPICE_IMAGE_TYPE_BITMAP;
+ red_image.bitmap = bitmap;
+ red_image.bitmap.flags &= ~QXL_BITMAP_DIRECT;
+
+ spice_marshall_Image(src_bitmap_out, (SpiceImageDescriptor *)&red_image,
+ &bitmap_palette_out, &data_out, &lzplt_palette_out);
+ spice_marshaller_add_ref(data_out, item->data, bitmap.y * bitmap.stride);
+ region_remove(surface_lossy_region, ©.base.box);
}
display_begin_send_massage(display_channel, &item->link);
}
@@ -8844,27 +9010,37 @@ static void red_display_send_upgrade(DisplayChannel *display_channel, UpgradeIte
{
RedChannel *channel;
QXLDrawable *qxl_drawable;
- SpiceMsgDisplayDrawCopy *copy = &display_channel->send_data.u.copy;
+ SpiceMsgDisplayDrawCopy copy;
+ SpiceMarshaller *cliprects_data_out, *clippath_data_out, *src_bitmap_out, *mask_bitmap_out;
+ int i;
ASSERT(display_channel && item && item->drawable);
channel = &display_channel->base;
- channel->send_data.header.type = SPICE_MSG_DISPLAY_DRAW_COPY;
+ channel->send_data.header->type = SPICE_MSG_DISPLAY_DRAW_COPY;
qxl_drawable = item->drawable->qxl_drawable;
ASSERT(qxl_drawable->type == QXL_DRAW_COPY);
ASSERT(qxl_drawable->u.copy.rop_decriptor == SPICE_ROPD_OP_PUT);
ASSERT(qxl_drawable->u.copy.mask.bitmap == 0);
- add_buf(channel, BUF_TYPE_RAW, copy, sizeof(SpiceMsgDisplayDrawCopy), 0, 0);
- copy->base.surface_id = 0;
- copy->base.box = qxl_drawable->bbox;
- copy->base.clip.type = SPICE_CLIP_TYPE_RECTS;
- copy->base.clip.data = channel->send_data.header.size;
- add_buf(channel, BUF_TYPE_RAW, &item->n_rects, sizeof(uint32_t), 0, 0);
- add_buf(channel, BUF_TYPE_RAW, item->rects, sizeof(SpiceRect) * item->n_rects, 0, 0);
- copy->data = qxl_drawable->u.copy;
- fill_bits(display_channel, ©->data.src_bitmap, item->drawable, FALSE);
+ copy.base.surface_id = 0;
+ copy.base.box = qxl_drawable->bbox;
+ copy.base.clip.type = SPICE_CLIP_TYPE_RECTS;
+ copy.base.clip.data = 0;
+ copy.data = qxl_drawable->u.copy;
+
+ SpiceMarshaller *m = channel->send_data.marshaller;
+
+ spice_marshall_msg_display_draw_copy(m, ©,
+ &cliprects_data_out, &clippath_data_out,
+ &src_bitmap_out, &mask_bitmap_out);
+
+ spice_marshaller_add_uint32(cliprects_data_out, item->n_rects);
+ for (i = 0; i < item->n_rects; i++) {
+ spice_marshall_Rect(cliprects_data_out, &item->rects[i]);
+ }
+ fill_bits(display_channel, src_bitmap_out, copy.data.src_bitmap, item->drawable, FALSE);
display_begin_send_massage(display_channel, &item->base);
}
@@ -8876,35 +9052,44 @@ static void red_display_send_stream_start(DisplayChannel *display_channel, Strea
agent->lats_send_time = 0;
ASSERT(stream);
- channel->send_data.header.type = SPICE_MSG_DISPLAY_STREAM_CREATE;
- SpiceMsgDisplayStreamCreate *stream_create = &display_channel->send_data.u.stream_create.message;
- stream_create->surface_id = 0;
- stream_create->id = agent - display_channel->stream_agents;
- stream_create->flags = stream->top_down ? SPICE_STREAM_FLAGS_TOP_DOWN : 0;
- stream_create->codec_type = SPICE_VIDEO_CODEC_TYPE_MJPEG;
-
- stream_create->src_width = stream->width;
- stream_create->src_height = stream->height;
- stream_create->stream_width = SPICE_ALIGN(stream_create->src_width, 2);
- stream_create->stream_height = SPICE_ALIGN(stream_create->src_height, 2);
- stream_create->dest = stream->dest_area;
-
- add_buf(channel, BUF_TYPE_RAW, stream_create, sizeof(*stream_create), 0, 0);
+ channel->send_data.header->type = SPICE_MSG_DISPLAY_STREAM_CREATE;
+ SpiceMsgDisplayStreamCreate stream_create;
+ SpiceMarshaller *cliprects_data_out, *clippath_data_out;
+
+ stream_create.surface_id = 0;
+ stream_create.id = agent - display_channel->stream_agents;
+ stream_create.flags = stream->top_down ? SPICE_STREAM_FLAGS_TOP_DOWN : 0;
+ stream_create.codec_type = SPICE_VIDEO_CODEC_TYPE_MJPEG;
+
+ stream_create.src_width = stream->width;
+ stream_create.src_height = stream->height;
+ stream_create.stream_width = SPICE_ALIGN(stream_create.src_width, 2);
+ stream_create.stream_height = SPICE_ALIGN(stream_create.src_height, 2);
+ stream_create.dest = stream->dest_area;
+
+ if (stream->current) {
+ QXLDrawable *qxl_drawable = stream->current->qxl_drawable;
+ stream_create.clip = qxl_drawable->clip;
+ } else {
+ stream_create.clip.type = SPICE_CLIP_TYPE_RECTS;
+ stream_create.clip.data = 0;
+ }
+
+ spice_marshall_msg_display_stream_create(channel->send_data.marshaller, &stream_create,
+ &cliprects_data_out, &clippath_data_out);
+
+
if (stream->current) {
QXLDrawable *qxl_drawable = stream->current->qxl_drawable;
- stream_create->clip = qxl_drawable->clip;
if (qxl_drawable->clip.type == SPICE_CLIP_TYPE_RECTS) {
- fill_rects_clip(channel, &stream_create->clip.data, stream->current->group_id);
+ fill_rects_clip(channel, cliprects_data_out, stream_create.clip.data,
+ stream->current->group_id);
} else {
ASSERT(qxl_drawable->clip.type == SPICE_CLIP_TYPE_NONE);
}
display_begin_send_massage(display_channel, &stream->current->pipe_item);
} else {
- stream_create->clip.type = SPICE_CLIP_TYPE_RECTS;
- stream_create->clip.data = channel->send_data.header.size;
- display_channel->send_data.u.stream_create.num_rects = 0;
- add_buf(channel, BUF_TYPE_RAW, &display_channel->send_data.u.stream_create.num_rects,
- sizeof(uint32_t), 0, 0);
+ spice_marshaller_add_uint32(cliprects_data_out, 0);
display_begin_send_massage(display_channel, NULL);
}
}
@@ -8916,20 +9101,26 @@ static void red_display_send_stream_clip(DisplayChannel *display_channel,
StreamAgent *agent = item->stream_agent;
Stream *stream = agent->stream;
+ int i;
ASSERT(stream);
- channel->send_data.header.type = SPICE_MSG_DISPLAY_STREAM_CLIP;
- SpiceMsgDisplayStreamClip *stream_clip = &display_channel->send_data.u.stream_clip;
- add_buf(channel, BUF_TYPE_RAW, stream_clip, sizeof(*stream_clip), 0, 0);
- stream_clip->id = agent - display_channel->stream_agents;
- if ((stream_clip->clip.type = item->clip_type) == SPICE_CLIP_TYPE_NONE) {
- stream_clip->clip.data = 0;
- } else {
- ASSERT(stream_clip->clip.type == SPICE_CLIP_TYPE_RECTS);
- stream_clip->clip.data = channel->send_data.header.size;
- add_buf(channel, BUF_TYPE_RAW, &item->n_rects, sizeof(uint32_t), 0, 0);
- add_buf(channel, BUF_TYPE_RAW, item->rects, item->n_rects * sizeof(SpiceRect), 0, 0);
+ channel->send_data.header->type = SPICE_MSG_DISPLAY_STREAM_CLIP;
+ SpiceMsgDisplayStreamClip stream_clip;
+ SpiceMarshaller *cliprects_data_out, *clippath_data_out;
+
+ stream_clip.id = agent - display_channel->stream_agents;
+ stream_clip.clip.type = item->clip_type;
+ stream_clip.clip.data = 0;
+
+ spice_marshall_msg_display_stream_clip(channel->send_data.marshaller, &stream_clip,
+ &cliprects_data_out, &clippath_data_out);
+
+ if (stream_clip.clip.type == SPICE_CLIP_TYPE_RECTS) {
+ spice_marshaller_add_uint32(cliprects_data_out, item->n_rects);
+ for (i = 0; i < item->n_rects; i++) {
+ spice_marshall_Rect(cliprects_data_out, &item->rects[i]);
+ }
}
display_begin_send_massage(display_channel, item);
}
@@ -8937,35 +9128,41 @@ static void red_display_send_stream_clip(DisplayChannel *display_channel,
static void red_display_send_stream_end(DisplayChannel *display_channel, StreamAgent* agent)
{
RedChannel *channel = &display_channel->base;
- channel->send_data.header.type = SPICE_MSG_DISPLAY_STREAM_DESTROY;
- display_channel->send_data.u.stream_destroy.id = agent - display_channel->stream_agents;
- add_buf(channel, BUF_TYPE_RAW, &display_channel->send_data.u.stream_destroy,
- sizeof(SpiceMsgDisplayStreamDestroy), 0, 0);
+ SpiceMsgDisplayStreamDestroy destroy;
+
+ channel->send_data.header->type = SPICE_MSG_DISPLAY_STREAM_DESTROY;
+ destroy.id = agent - display_channel->stream_agents;
+
+ spice_marshall_msg_display_stream_destroy(channel->send_data.marshaller, &destroy);
+
display_begin_send_massage(display_channel, NULL);
}
static void red_cursor_send_inval(CursorChannel *channel, CacheItem *cach_item)
{
ASSERT(channel);
- red_send_inval((RedChannel *)channel, cach_item, &channel->send_data.u.inval_one);
+ red_send_inval((RedChannel *)channel, cach_item);
}
static void red_send_cursor_init(CursorChannel *channel)
{
RedWorker *worker;
+ SpiceMsgCursorInit msg;
+ AddBufInfo info;
+
ASSERT(channel);
worker = channel->base.worker;
- channel->base.send_data.header.type = SPICE_MSG_CURSOR_INIT;
- channel->send_data.u.cursor_init.visible = worker->cursor_visible;
- channel->send_data.u.cursor_init.position = worker->cursor_position;
- channel->send_data.u.cursor_init.trail_length = worker->cursor_trail_length;
- channel->send_data.u.cursor_init.trail_frequency = worker->cursor_trail_frequency;
- add_buf(&channel->base, BUF_TYPE_RAW, &channel->send_data.u.cursor_init, sizeof(SpiceMsgCursorInit),
- 0, 0);
+ channel->base.send_data.header->type = SPICE_MSG_CURSOR_INIT;
+ msg.visible = worker->cursor_visible;
+ msg.position = worker->cursor_position;
+ msg.trail_length = worker->cursor_trail_length;
+ msg.trail_frequency = worker->cursor_trail_frequency;
- fill_cursor(channel, &channel->send_data.u.cursor_init.cursor, worker->cursor);
+ fill_cursor(channel, &msg.cursor, worker->cursor, &info);
+ spice_marshall_msg_cursor_init(channel->base.send_data.marshaller, &msg);
+ add_buf_from_info(&channel->base, channel->base.send_data.marshaller, &info);
red_begin_send_massage(&channel->base, worker->cursor);
}
@@ -8973,16 +9170,19 @@ static void red_send_cursor_init(CursorChannel *channel)
static void red_send_local_cursor(CursorChannel *cursor_channel, LocalCursor *cursor)
{
RedChannel *channel;
+ SpiceMsgCursorSet cursor_set;
+ AddBufInfo info;
ASSERT(cursor_channel);
channel = &cursor_channel->base;
- channel->send_data.header.type = SPICE_MSG_CURSOR_SET;
- cursor_channel->send_data.u.cursor_set.position = cursor->position;
- cursor_channel->send_data.u.cursor_set.visible = channel->worker->cursor_visible;
- add_buf(channel, BUF_TYPE_RAW, &cursor_channel->send_data.u.cursor_set,
- sizeof(SpiceMsgCursorSet), 0, 0);
- fill_cursor(cursor_channel, &cursor_channel->send_data.u.cursor_set.cursor, &cursor->base);
+ channel->send_data.header->type = SPICE_MSG_CURSOR_SET;
+ cursor_set.position = cursor->position;
+ cursor_set.visible = channel->worker->cursor_visible;
+
+ fill_cursor(cursor_channel, &cursor_set.cursor, &cursor->base, &info);
+ spice_marshall_msg_cursor_set(channel->send_data.marshaller, &cursor_set);
+ add_buf_from_info(channel, channel->send_data.marshaller, &info);
red_begin_send_massage(channel, cursor);
@@ -8991,10 +9191,12 @@ static void red_send_local_cursor(CursorChannel *cursor_channel, LocalCursor *cu
static void cursor_channel_send_migrate(CursorChannel *cursor_channel)
{
- cursor_channel->base.send_data.header.type = SPICE_MSG_MIGRATE;
- cursor_channel->send_data.u.migrate.flags = 0;
- add_buf((RedChannel*)cursor_channel, BUF_TYPE_RAW, &cursor_channel->send_data.u.migrate,
- sizeof(cursor_channel->send_data.u.migrate), 0, 0);
+ SpiceMsgMigrate migrate;
+
+ cursor_channel->base.send_data.header->type = SPICE_MSG_MIGRATE;
+ migrate.flags = 0;
+
+ spice_marshall_msg_migrate(cursor_channel->base.send_data.marshaller, &migrate);
red_begin_send_massage((RedChannel*)cursor_channel, NULL);
}
@@ -9002,36 +9204,49 @@ static void red_send_cursor(CursorChannel *cursor_channel, CursorItem *cursor)
{
RedChannel *channel;
QXLCursorCmd *cmd;
+ SpiceMarshaller *m;
ASSERT(cursor_channel);
channel = &cursor_channel->base;
+ m = channel->send_data.marshaller;
cmd = cursor->qxl_cursor;
switch (cmd->type) {
case QXL_CURSOR_MOVE:
- channel->send_data.header.type = SPICE_MSG_CURSOR_MOVE;
- cursor_channel->send_data.u.cursor_move.position = cmd->u.position;
- add_buf(channel, BUF_TYPE_RAW, &cursor_channel->send_data.u.cursor_move,
- sizeof(SpiceMsgCursorMove), 0, 0);
- break;
+ {
+ SpiceMsgCursorMove cursor_move;
+ channel->send_data.header->type = SPICE_MSG_CURSOR_MOVE;
+ cursor_move.position = cmd->u.position;
+ spice_marshall_msg_cursor_move(m, &cursor_move);
+ break;
+ }
case QXL_CURSOR_SET:
- channel->send_data.header.type = SPICE_MSG_CURSOR_SET;
- cursor_channel->send_data.u.cursor_set.position = cmd->u.set.position;
- cursor_channel->send_data.u.cursor_set.visible = channel->worker->cursor_visible;
- add_buf(channel, BUF_TYPE_RAW, &cursor_channel->send_data.u.cursor_set,
- sizeof(SpiceMsgCursorSet), 0, 0);
- fill_cursor(cursor_channel, &cursor_channel->send_data.u.cursor_set.cursor, cursor);
- break;
+ {
+ SpiceMsgCursorSet cursor_set;
+ AddBufInfo info;
+
+ channel->send_data.header->type = SPICE_MSG_CURSOR_SET;
+ cursor_set.position = cmd->u.set.position;
+ cursor_set.visible = channel->worker->cursor_visible;
+
+ fill_cursor(cursor_channel, &cursor_set.cursor, cursor, &info);
+ spice_marshall_msg_cursor_set(m, &cursor_set);
+ add_buf_from_info(channel, m, &info);
+ break;
+ }
case QXL_CURSOR_HIDE:
- channel->send_data.header.type = SPICE_MSG_CURSOR_HIDE;
+ channel->send_data.header->type = SPICE_MSG_CURSOR_HIDE;
break;
case QXL_CURSOR_TRAIL:
- channel->send_data.header.type = SPICE_MSG_CURSOR_TRAIL;
- cursor_channel->send_data.u.cursor_trail.length = cmd->u.trail.length;
- cursor_channel->send_data.u.cursor_trail.frequency = cmd->u.trail.frequency;
- add_buf(channel, BUF_TYPE_RAW, &cursor_channel->send_data.u.cursor_trail,
- sizeof(SpiceMsgCursorTrail), 0, 0);
+ {
+ SpiceMsgCursorTrail cursor_trail;
+
+ channel->send_data.header->type = SPICE_MSG_CURSOR_TRAIL;
+ cursor_trail.length = cmd->u.trail.length;
+ cursor_trail.frequency = cmd->u.trail.frequency;
+ spice_marshall_msg_cursor_trail(m, &cursor_trail);
+ }
break;
default:
red_error("bad cursor command %d", cmd->type);
@@ -9050,11 +9265,9 @@ static void red_send_surface_create(DisplayChannel *display, SpiceMsgSurfaceCrea
channel = &display->base;
region_init(&display->surface_client_lossy_region[surface_create->surface_id]);
- channel->send_data.header.type = SPICE_MSG_DISPLAY_SURFACE_CREATE;
- display->send_data.u.surface_create = *surface_create;
+ channel->send_data.header->type = SPICE_MSG_DISPLAY_SURFACE_CREATE;
- add_buf(channel, BUF_TYPE_RAW, &display->send_data.u.surface_create,
- sizeof(SpiceMsgSurfaceCreate), 0, 0);
+ spice_marshall_msg_display_surface_create(channel->send_data.marshaller, surface_create);
red_begin_send_massage(channel, NULL);
}
@@ -9062,16 +9275,17 @@ static void red_send_surface_create(DisplayChannel *display, SpiceMsgSurfaceCrea
static void red_send_surface_destroy(DisplayChannel *display, uint32_t surface_id)
{
RedChannel *channel;
+ SpiceMsgSurfaceDestroy surface_destroy;
ASSERT(display);
channel = &display->base;
region_destroy(&display->surface_client_lossy_region[surface_id]);
- channel->send_data.header.type = SPICE_MSG_DISPLAY_SURFACE_DESTROY;
- display->send_data.u.surface_destroy.surface_id = surface_id;
+ channel->send_data.header->type = SPICE_MSG_DISPLAY_SURFACE_DESTROY;
+
+ surface_destroy.surface_id = surface_id;
- add_buf(channel, BUF_TYPE_RAW, &display->send_data.u.surface_destroy,
- sizeof(SpiceMsgSurfaceDestroy), 0, 0);
+ spice_marshall_msg_display_surface_destroy(channel->send_data.marshaller, &surface_destroy);
red_begin_send_massage(channel, NULL);
}
@@ -9327,6 +9541,7 @@ static void red_disconnect_channel(RedChannel *channel)
channel->peer = NULL;
channel->send_data.blocked = FALSE;
channel->send_data.size = channel->send_data.pos = 0;
+ spice_marshaller_reset(channel->send_data.marshaller);
red_unref_channel(channel);
}
@@ -9951,8 +10166,8 @@ static int display_channel_handle_migrate_data(DisplayChannel *channel, SpiceDat
red_printf("invalid content");
return FALSE;
}
- ASSERT(channel->base.send_data.header.serial == 0);
- channel->base.send_data.header.serial = migrate_data->message_serial;
+ ASSERT(channel->base.send_data.serial == 0);
+ channel->base.send_data.serial = migrate_data->message_serial;
if (!(channel->pixmap_cache = red_get_pixmap_cache(migrate_data->pixmap_cache_id, -1))) {
return FALSE;
}
@@ -10108,6 +10323,7 @@ static RedChannel *__new_channel(RedWorker *worker, int size, RedsStreamContext
channel->recive_data.now = channel->recive_data.buf;
channel->recive_data.end = channel->recive_data.buf + sizeof(channel->recive_data.buf);
ring_init(&channel->pipe);
+ channel->send_data.marshaller = spice_marshaller_new();
event.events = EPOLLIN | EPOLLOUT | EPOLLET;
event.data.ptr = channel;
commit e2728082d0d11b7293a93bedb93dac98511fb561
Author: Alexander Larsson <alexl at redhat.com>
Date: Tue Jun 1 18:14:51 2010 +0200
Generate marshallers in server
diff --git a/server/Makefile.am b/server/Makefile.am
index ff97a40..7cd9218 100644
--- a/server/Makefile.am
+++ b/server/Makefile.am
@@ -18,6 +18,15 @@ INCLUDES = \
$(VISIBILITY_HIDDEN_CFLAGS) \
$(NULL)
+spice_built_sources = generated_marshallers.c generated_marshallers.h
+
+STRUCTS=-M String -M Rect -M Point -M DisplayBase -M Fill -M Opaque -M Copy -M Blend -M Blackness -M Whiteness -M Invers -M Rop3 -M Stroke -M Text -M Transparent -M AlphaBlnd -M PathSegment
+generated_marshallers.c: $(top_srcdir)/spice.proto
+ $(PYTHON) $(top_srcdir)/spice_codegen.py --generate-marshallers $(STRUCTS) --server $(top_srcdir)/spice.proto generated_marshallers.c
+
+generated_marshallers.h: $(top_srcdir)/spice.proto
+ $(PYTHON) $(top_srcdir)/spice_codegen.py --generate-marshallers $(STRUCTS) --server -H $(top_srcdir)/spice.proto generated_marshallers.h
+
COMMON_SRCS = \
$(top_srcdir)/common/sw_canvas.c \
$(top_srcdir)/common/pixman_utils.c \
@@ -90,6 +99,8 @@ libspice_server_la_SOURCES = \
red_channel.c \
spice.h \
spice-experimental.h \
+ generated_marshallers.c \
+ generated_marshallers.h \
$(TUNNEL_SRCS) \
$(COMMON_SRCS) \
$(NULL)
@@ -104,3 +115,5 @@ EXTRA_DIST = \
glz_encode_match_tmpl.c \
glz_encode_tmpl.c \
$(NULL)
+
+BUILT_SOURCES = $(spice_built_sources)
commit c36efa5950e07f7795c8b34709f1e770adfad80d
Author: Alexander Larsson <alexl at redhat.com>
Date: Thu Jun 17 10:07:36 2010 +0200
Use @ptr32 for 32bit offsets in spice.proto
diff --git a/spice.proto b/spice.proto
index 7952f9a..d41137f 100644
--- a/spice.proto
+++ b/spice.proto
@@ -1031,8 +1031,8 @@ channel TunnelChannel : BaseChannel {
uint32 id;
uint32 group;
uint32 port;
- uint32 name;
- uint32 description;
+ uint8 *name[] @ptr32;
+ uint8 *description[] @ptr32;
switch (type) {
case IPP:
TunnelIpInfo ip @ctype(SpiceMsgTunnelIpInfo);
commit 635ad37ee9df0861860f49dc602044b356f08cb2
Author: Alexander Larsson <alexl at redhat.com>
Date: Fri Jun 11 16:39:27 2010 +0200
Add @nomarshal in a few places where we're marshalling manually
diff --git a/spice.proto b/spice.proto
index 32ad869..7952f9a 100644
--- a/spice.proto
+++ b/spice.proto
@@ -130,8 +130,8 @@ channel BaseChannel {
notify_visibility visibilty;
uint32 what; /* error_code/warn_code/info_code */
uint32 message_len;
- uint8 message[message_len] @end;
- uint8 zero @end @ctype(uint8_t) @zero;
+ uint8 message[message_len] @end @nomarshal;
+ uint8 zero @end @ctype(uint8_t) @zero @nomarshal;
} notify;
client:
@@ -171,8 +171,8 @@ channel MainChannel : BaseChannel {
pubkey_type pub_key_type @minor(2);
uint32 pub_key_offset @minor(2);
uint32 pub_key_size @minor(2);
- uint8 host_data[host_size] @end @ctype(uint8_t) @zero_terminated;
- uint8 pub_key_data[pub_key_size] @minor(2) @end @ctype(uint8_t) @zero_terminated;
+ uint8 host_data[host_size] @end @ctype(uint8_t) @zero_terminated @nomarshal;
+ uint8 pub_key_data[pub_key_size] @minor(2) @end @ctype(uint8_t) @zero_terminated @nomarshal;
} @ctype(SpiceMsgMainMigrationBegin) migrate_begin = 101;
Empty migrate_cancel;
@@ -455,7 +455,7 @@ struct BitmapData {
struct BinaryData {
uint32 data_size;
- uint8 data[data_size] @end;
+ uint8 data[data_size] @end @nomarshal;
} @ctype(SpiceQUICData);
struct LZPLTData {
@@ -467,7 +467,7 @@ struct LZPLTData {
default:
Palette *palette @nonnull @outvar(lzplt);
} pal @anon;
- uint8 data[data_size] @end;
+ uint8 data[data_size] @end @nomarshal;
};
struct Surface {
@@ -561,7 +561,7 @@ struct String {
RasterGlyphA4 glyphs[length] @ctype(SpiceRasterGlyph);
case RASTER_A8:
RasterGlyphA8 glyphs[length] @ctype(SpiceRasterGlyph);
- } u @end;
+ } u @end @nomarshal;
};
channel DisplayChannel : BaseChannel {
@@ -614,8 +614,8 @@ channel DisplayChannel : BaseChannel {
uint32 multi_media_time;
uint32 data_size;
uint32 pad_size;
- uint8 data[data_size] @end;
- uint8 padding[pad_size] @end @ctype(uint8_t); /* Uhm, why are we sending padding over network? */
+ uint8 data[data_size] @end @nomarshal;
+ uint8 padding[pad_size] @end @ctype(uint8_t) @nomarshal; /* Uhm, why are we sending padding over network? */
} stream_data;
message {
@@ -952,7 +952,7 @@ channel RecordChannel : BaseChannel {
client:
message {
uint32 time;
- uint8 data[] @end;
+ uint8 data[] @end @nomarshal;
} @ctype(SpiceMsgcRecordPacket) data = 101;
message {
@@ -982,7 +982,7 @@ struct TunnelIpInfo {
switch (type) {
case IPv4:
uint8 ipv4[4] @ctype(uint8_t);
- } u @end;
+ } u @end @nomarshal;
} @ctype(SpiceMsgTunnelIpInfo);
channel TunnelChannel : BaseChannel {
commit a7284761be3d45b2be4bab27725556a668dc491e
Author: Alexander Larsson <alexl at redhat.com>
Date: Tue Jun 1 21:54:16 2010 +0200
spice.proto: add @outvar markup
With this we can reference pointer member with no naming conflicts
diff --git a/spice.proto b/spice.proto
index dec6a63..32ad869 100644
--- a/spice.proto
+++ b/spice.proto
@@ -409,9 +409,9 @@ struct Clip {
case NONE:
uint64 data @zero;
case RECTS:
- ClipRects *data;
+ ClipRects *data @outvar(cliprects);
case PATH:
- Path *data;
+ Path *data @outvar(clippath);
} u @anon;
};
@@ -448,7 +448,7 @@ struct BitmapData {
case PAL_FROM_CACHE:
uint64 palette;
default:
- Palette *palette;
+ Palette *palette @outvar(bitmap);
} pal @anon;
uint8 *data[image_size(8, stride, y)] @nocopy; /* pointer to array, not array of pointers as in C */
} @ctype(SpiceBitmap);
@@ -465,7 +465,7 @@ struct LZPLTData {
case PAL_FROM_CACHE:
uint64 palette;
default:
- Palette *palette @nonnull;
+ Palette *palette @nonnull @outvar(lzplt);
} pal @anon;
uint8 data[data_size] @end;
};
@@ -632,9 +632,9 @@ channel DisplayChannel : BaseChannel {
message {
DisplayBase base;
struct Fill {
- Brush brush;
+ Brush brush @outvar(brush);
uint16 rop_decriptor;
- QMask mask;
+ QMask mask @outvar(mask);
} data;
} draw_fill = 302;
@@ -646,7 +646,7 @@ channel DisplayChannel : BaseChannel {
Brush brush;
ropd rop_decriptor;
image_scale_mode scale_mode;
- QMask mask;
+ QMask mask @outvar(mask);
} data;
} draw_opaque;
@@ -657,7 +657,7 @@ channel DisplayChannel : BaseChannel {
Rect src_area;
ropd rop_decriptor;
image_scale_mode scale_mode;
- QMask mask;
+ QMask mask @outvar(mask);
} data;
} draw_copy;
@@ -668,28 +668,28 @@ channel DisplayChannel : BaseChannel {
Rect src_area;
ropd rop_decriptor;
image_scale_mode scale_mode;
- QMask mask;
+ QMask mask @outvar(mask);
} @ctype(SpiceCopy) data;
} draw_blend;
message {
DisplayBase base;
struct Blackness {
- QMask mask;
+ QMask mask @outvar(mask);
} data;
} draw_blackness;
message {
DisplayBase base;
struct Whiteness {
- QMask mask;
+ QMask mask @outvar(mask);
} data;
} draw_whiteness;
message {
DisplayBase base;
struct Invers {
- QMask mask;
+ QMask mask @outvar(mask);
} data;
} draw_invers;
@@ -701,7 +701,7 @@ channel DisplayChannel : BaseChannel {
Brush brush;
uint8 rop3;
image_scale_mode scale_mode;
- QMask mask;
+ QMask mask @outvar(mask);
} data;
} draw_rop3;
@@ -721,8 +721,8 @@ channel DisplayChannel : BaseChannel {
struct Text {
String *str;
Rect back_area;
- Brush fore_brush;
- Brush back_brush;
+ Brush fore_brush @outvar(fore_brush);
+ Brush back_brush @outvar(back_brush);
uint16 fore_mode;
uint16 back_mode;
} data;
commit 936b3f01f9ba9779385986e1beb342007ec7e981
Author: Alexander Larsson <alexl at redhat.com>
Date: Mon Jun 14 16:11:39 2010 +0200
Add support for generating message and structure marshallers
diff --git a/python_modules/marshal.py b/python_modules/marshal.py
new file mode 100644
index 0000000..23b029a
--- /dev/null
+++ b/python_modules/marshal.py
@@ -0,0 +1,357 @@
+import ptypes
+import codegen
+
+def write_includes(writer):
+ writer.header.writeln("#include <spice/protocol.h>")
+ writer.header.writeln("#include <marshaller.h>")
+ writer.header.newline()
+ writer.header.writeln("#ifndef _GENERATED_HEADERS_H")
+ writer.header.writeln("#define _GENERATED_HEADERS_H")
+
+ writer.writeln("#include <string.h>")
+ writer.writeln("#include <assert.h>")
+ writer.writeln("#include <stdlib.h>")
+ writer.writeln("#include <stdio.h>")
+ writer.writeln("#include <spice/protocol.h>")
+ writer.writeln("#include <spice/macros.h>")
+ writer.writeln("#include <marshaller.h>")
+ writer.newline()
+ writer.writeln("#ifdef _MSC_VER")
+ writer.writeln("#pragma warning(disable:4101)")
+ writer.writeln("#endif")
+ writer.newline()
+
+class MarshallingSource:
+ def __init__(self):
+ pass
+
+ def child_at_end(self, t):
+ return RootMarshallingSource(self, t.c_type(), t.sizeof())
+
+ def child_sub(self, member):
+ return SubMarshallingSource(self, member)
+
+ def declare(self, writer):
+ return writer.optional_block(self.reuse_scope)
+
+ def is_toplevel(self):
+ return self.parent_src == None and not self.is_helper
+
+class RootMarshallingSource(MarshallingSource):
+ def __init__(self, parent_src, c_type, sizeof, pointer = None):
+ self.is_helper = False
+ self.reuse_scope = None
+ self.parent_src = parent_src
+ if parent_src:
+ self.base_var = codegen.increment_identifier(parent_src.base_var)
+ else:
+ self.base_var = "src"
+ self.c_type = c_type
+ self.sizeof = sizeof
+ self.pointer = pointer # None == at "end"
+
+ def get_self_ref(self):
+ return self.base_var
+
+ def get_ref(self, member):
+ return self.base_var + "->" + member
+
+ def declare(self, writer):
+ if self.reuse_scope:
+ scope = self.reuse_scope
+ else:
+ writer.begin_block()
+ scope = writer.get_subwriter()
+
+ scope.variable_def(self.c_type + " *", self.base_var)
+ if not self.reuse_scope:
+ scope.newline()
+
+ if self.pointer:
+ writer.assign(self.base_var, "(%s *)%s" % (self.c_type, self.pointer))
+ else:
+ writer.assign(self.base_var, "(%s *)end" % self.c_type)
+ writer.increment("end", "%s" % self.sizeof)
+ writer.newline()
+
+ if self.reuse_scope:
+ return writer.no_block(self.reuse_scope)
+ else:
+ return writer.partial_block(scope)
+
+class SubMarshallingSource(MarshallingSource):
+ def __init__(self, parent_src, member):
+ self.reuse_scope = None
+ self.parent_src = parent_src
+ self.base_var = parent_src.base_var
+ self.member = member
+ self.is_helper = False
+
+ def get_self_ref(self):
+ return "&%s" % self.parent_src.get_ref(self.member)
+
+ def get_ref(self, member):
+ return self.parent_src.get_ref(self.member) + "." + member
+
+def write_marshal_ptr_function(writer, target_type):
+ if target_type.is_array():
+ marshal_function = "spice_marshall_array_%s" % target_type.element_type.primitive_type()
+ else:
+ marshal_function = "spice_marshall_%s" % target_type.name
+ if writer.is_generated("marshaller", marshal_function):
+ return marshal_function
+
+ writer.set_is_generated("marshaller", marshal_function)
+
+ names = target_type.get_pointer_names()
+ names_args = ""
+ if len(names) > 0:
+ n = map(lambda name: ", SpiceMarshaller **%s" % name, names)
+ names_args = "".join(n)
+
+ header = writer.header
+ writer = writer.function_helper()
+ writer.header = header
+ writer.out_prefix = ""
+ if target_type.is_array():
+ scope = writer.function(marshal_function, "void *", "SpiceMarshaller *m, %s_t *ptr, int count" % target_type.element_type.primitive_type() + names_args)
+ else:
+ scope = writer.function(marshal_function, "void *", "SpiceMarshaller *m, %s *ptr" % target_type.c_type() + names_args)
+ header.writeln("void *" + marshal_function + "(SpiceMarshaller *m, %s *msg" % target_type.c_type() + names_args + ");")
+ scope.variable_def("SPICE_GNUC_UNUSED uint8_t *", "end")
+
+ for n in names:
+ writer.assign("*%s" % n, "NULL")
+
+ writer.newline()
+ writer.assign("end", "(uint8_t *)(ptr+1)")
+
+ if target_type.is_struct():
+ src = RootMarshallingSource(None, target_type.c_type(), target_type.sizeof(), "ptr")
+ src.reuse_scope = scope
+ write_container_marshaller(writer, target_type, src)
+ elif target_type.is_array() and target_type.element_type.is_primitive():
+ with writer.index() as index:
+ with writer.for_loop(index, "count") as array_scope:
+ writer.statement("spice_marshaller_add_%s(m, *ptr++)" % (target_type.element_type.primitive_type()))
+ else:
+ writer.todo("Unsuppored pointer marshaller type")
+
+ writer.statement("return end")
+
+ writer.end_block()
+
+ return marshal_function
+
+def get_array_size(array, container_src):
+ if array.is_constant_length():
+ return array.size
+ elif array.is_identifier_length():
+ return container_src.get_ref(array.size)
+ elif array.is_remaining_length():
+ raise NotImplementedError("remaining size array sizes marshalling not supported")
+ elif array.is_image_size_length():
+ bpp = array.size[1]
+ width = array.size[2]
+ rows = array.size[3]
+ width_v = container_src.get_ref(width)
+ rows_v = container_src.get_ref(rows)
+ # TODO: Handle multiplication overflow
+ if bpp == 8:
+ return "(%s * %s)" % (width_v, rows_v)
+ elif bpp == 1:
+ return "(((%s + 7) / 8 ) * %s)" % (width_v, rows_v)
+ else:
+ return "(((%s * %s + 7) / 8 ) * %s)" % (bpp, width_v, rows_v)
+ elif array.is_bytes_length():
+ return container_src.get_ref(array.size[1])
+ else:
+ raise NotImplementedError("TODO array size type not handled yet")
+
+def write_array_marshaller(writer, at_end, member, array, container_src, scope):
+ element_type = array.element_type
+
+ if array.is_remaining_length():
+ writer.comment("Remaining data must be appended manually").newline()
+ return
+
+ nelements = get_array_size(array, container_src)
+ is_byte_size = array.is_bytes_length()
+
+ if is_byte_size:
+ element = "%s__bytes" % member.name
+ else:
+ element = "%s__element" % member.name
+
+ if not at_end:
+ writer.assign(element, container_src.get_ref(member.name))
+
+ if is_byte_size:
+ scope.variable_def("size_t", "array_end")
+ writer.assign("array_end", "spice_marshaller_get_size(m) + %s" % nelements)
+
+ with writer.index(no_block = is_byte_size) as index:
+ with writer.while_loop("spice_marshaller_get_size(m) < array_end") if is_byte_size else writer.for_loop(index, nelements) as array_scope:
+ array_scope.variable_def(element_type.c_type() + " *", element)
+ if at_end:
+ writer.assign(element, "(%s *)end" % element_type.c_type())
+ writer.increment("end", element_type.sizeof())
+
+ if element_type.is_primitive():
+ writer.statement("spice_marshaller_add_%s(m, *%s)" % (element_type.primitive_type(), element))
+ elif element_type.is_struct():
+ src2 = RootMarshallingSource(container_src, element_type.c_type(), element_type.sizeof(), element)
+ src2.reuse_scope = array_scope
+ write_container_marshaller(writer, element_type, src2)
+ else:
+ writer.todo("array element unhandled type").newline()
+
+ if not at_end:
+ writer.statement("%s++" % element)
+
+def write_switch_marshaller(writer, container, switch, src, scope):
+ var = container.lookup_member(switch.variable)
+ var_type = var.member_type
+
+ saved_out_prefix = writer.out_prefix
+ first = True
+ for c in switch.cases:
+ check = c.get_check(src.get_ref(switch.variable), var_type)
+ m = c.member
+ writer.out_prefix = saved_out_prefix
+ if m.has_attr("outvar"):
+ writer.out_prefix = "%s_%s" % (m.attributes["outvar"][0], writer.out_prefix)
+ with writer.if_block(check, not first, False) as block:
+ t = m.member_type
+ if switch.has_end_attr():
+ src2 = src.child_at_end(m.member_type)
+ elif switch.has_attr("anon"):
+ src2 = src
+ else:
+ if t.is_struct():
+ src2 = src.child_sub(switch.name + "." + m.name)
+ else:
+ src2 = src.child_sub(switch.name)
+ src2.reuse_scope = block
+
+ if t.is_struct():
+ write_container_marshaller(writer, t, src2)
+ elif t.is_pointer():
+ ptr_func = write_marshal_ptr_function(writer, t.target_type)
+ writer.assign("*%s_out" % (writer.out_prefix + m.name), "spice_marshaller_get_ptr_submarshaller(m, %s)" % ("0" if m.has_attr("ptr32") else "1"))
+ elif t.is_primitive():
+ if m.has_attr("zero"):
+ writer.statement("spice_marshaller_add_%s(m, 0)" % (t.primitive_type()))
+ else:
+ writer.statement("spice_marshaller_add_%s(m, %s)" % (t.primitive_type(), src2.get_ref(m.name)))
+ #TODO validate e.g. flags and enums
+ elif t.is_array():
+ write_array_marshaller(writer, switch.has_end_attr(), m, t, src, scope)
+ else:
+ writer.todo("Can't handle type %s" % m.member_type)
+
+ if switch.has_attr("fixedsize"):
+ remaining = switch.get_fixed_nw_size() - t.get_fixed_nw_size()
+ if remaining != 0:
+ writer.statement("spice_marshaller_reserve_space(m, %s)" % remaining)
+
+ first = False
+ if switch.has_attr("fixedsize"):
+ with writer.block(" else"):
+ writer.statement("spice_marshaller_reserve_space(m, %s)" % switch.get_fixed_nw_size())
+
+ writer.newline()
+
+def write_member_marshaller(writer, container, member, src, scope):
+ if member.has_attr("outvar"):
+ writer.out_prefix = "%s_%s" % (member.attributes["outvar"][0], writer.out_prefix)
+ if member.has_attr("nomarshal"):
+ writer.comment("Don't marshall @nomarshal %s" % member.name).newline()
+ return
+ if member.is_switch():
+ write_switch_marshaller(writer, container, member, src, scope)
+ return
+
+ t = member.member_type
+
+ if t.is_pointer():
+# if member.has_attr("nocopy"):
+# writer.comment("Reuse data from network message").newline()
+# writer.assign(src.get_ref(member.name), "(size_t)(message_start + consume_uint64(&in))")
+# else:
+# write_parse_pointer(writer, t, member.has_end_attr(), src, member.name, scope)
+ ptr_func = write_marshal_ptr_function(writer, t.target_type)
+ writer.assign("*%s_out" % (writer.out_prefix + member.name), "spice_marshaller_get_ptr_submarshaller(m, %s)" % ("0" if member.has_attr("ptr32") else "1"))
+ elif t.is_primitive():
+ if member.has_attr("zero"):
+ writer.statement("spice_marshaller_add_%s(m, 0)" % (t.primitive_type()))
+ elif member.has_end_attr():
+ writer.statement("spice_marshaller_add_%s(m, *(%s_t *)end)" % (t.primitive_type(), t.primitive_type()))
+ writer.increment("end", t.sizeof())
+ else:
+ writer.statement("spice_marshaller_add_%s(m, %s)" % (t.primitive_type(), src.get_ref(member.name)))
+ elif t.is_array():
+ write_array_marshaller(writer, member.has_end_attr(), member, t, src, scope)
+ elif t.is_struct():
+ if member.has_end_attr():
+ src2 = src.child_at_end(t)
+ else:
+ src2 = src.child_sub(member.name)
+ writer.comment(member.name)
+ write_container_marshaller(writer, t, src2)
+ else:
+ raise NotImplementedError("TODO can't handle parsing of %s" % t)
+
+def write_container_marshaller(writer, container, src):
+ saved_out_prefix = writer.out_prefix
+ with src.declare(writer) as scope:
+ for m in container.members:
+ writer.out_prefix = saved_out_prefix
+ write_member_marshaller(writer, container, m, src, scope)
+
+def write_message_marshaller(writer, message, is_server):
+ writer.out_prefix = ""
+ function_name = "spice_marshall_" + message.c_name()
+ if writer.is_generated("marshaller", function_name):
+ return function_name
+ writer.set_is_generated("marshaller", function_name)
+
+ names = message.get_pointer_names()
+ names_args = ""
+ if len(names) > 0:
+ n = map(lambda name: ", SpiceMarshaller **%s" % name, names)
+ names_args = "".join(n)
+
+ writer.header.writeln("void " + function_name + "(SpiceMarshaller *m, %s *msg" % message.c_type() + names_args + ");")
+
+ scope = writer.function(function_name,
+ "void",
+ "SpiceMarshaller *m, %s *msg" % message.c_type() + names_args)
+ scope.variable_def("SPICE_GNUC_UNUSED uint8_t *", "end")
+
+ for n in names:
+ writer.assign("*%s" % n, "NULL")
+
+ src = RootMarshallingSource(None, message.c_type(), message.sizeof(), "msg")
+ src.reuse_scope = scope
+
+ writer.assign("end", "(uint8_t *)(msg+1)")
+ write_container_marshaller(writer, message, src)
+
+ writer.end_block()
+ writer.newline()
+
+def write_protocol_marshaller(writer, proto, is_server):
+ for c in proto.channels:
+ channel = c.channel_type
+ if is_server:
+ for m in channel.client_messages:
+ message = m.message_type
+ write_message_marshaller(writer, message, is_server)
+ else:
+ for m in channel.server_messages:
+ message = m.message_type
+ write_message_marshaller(writer, message, is_server)
+
+def write_trailer(writer):
+ writer.header.writeln("#endif")
diff --git a/spice_codegen.py b/spice_codegen.py
index f897ce8..0e9551f 100755
--- a/spice_codegen.py
+++ b/spice_codegen.py
@@ -8,6 +8,7 @@ from python_modules import spice_parser
from python_modules import ptypes
from python_modules import codegen
from python_modules import demarshal
+from python_modules import marshal
def write_channel_enums(writer, channel, client):
messages = filter(lambda m : m.channel == channel, \
@@ -82,9 +83,18 @@ parser.add_option("-e", "--generate-enums",
parser.add_option("-d", "--generate-demarshallers",
action="store_true", dest="generate_demarshallers", default=False,
help="Generate demarshallers")
+parser.add_option("-m", "--generate-marshallers",
+ action="store_true", dest="generate_marshallers", default=False,
+ help="Generate message marshallers")
+parser.add_option("-M", "--generate-struct-marshaller",
+ action="append", dest="struct_marshallers",
+ help="Generate struct marshallers")
parser.add_option("-a", "--assert-on-error",
action="store_true", dest="assert_on_error", default=False,
help="Assert on error")
+parser.add_option("-H", "--header",
+ action="store_true", dest="header", default=False,
+ help="Generate header")
parser.add_option("-p", "--print-error",
action="store_true", dest="print_error", default=False,
help="Print errors")
@@ -118,6 +128,7 @@ if proto == None:
codegen.set_prefix(proto.name)
writer = codegen.CodeWriter()
+writer.header = codegen.CodeWriter()
writer.set_option("source", os.path.basename(proto_file))
if options.assert_on_error:
@@ -143,7 +154,30 @@ if options.generate_demarshallers:
if options.client:
demarshal.write_protocol_parser(writer, proto, True)
-content = writer.getvalue()
+if options.generate_marshallers or (options.struct_marshallers and len(options.struct_marshallers) > 0):
+ marshal.write_includes(writer)
+
+if options.generate_marshallers:
+ if not options.server and not options.client:
+ print >> sys.stderr, "Must specify client and/or server"
+ sys.exit(1)
+ if options.server:
+ marshal.write_protocol_marshaller(writer, proto, False)
+ if options.client:
+ marshal.write_protocol_marshaller(writer, proto, True)
+
+if options.struct_marshallers:
+ for structname in options.struct_marshallers:
+ t = ptypes.lookup_type(structname)
+ marshal.write_marshal_ptr_function(writer, t)
+
+if options.generate_marshallers or (options.struct_marshallers and len(options.struct_marshallers) > 0):
+ marshal.write_trailer(writer)
+
+if options.header:
+ content = writer.header.getvalue()
+else:
+ content = writer.getvalue()
if options.keep_identical_file:
try:
f = open(dest_file, 'rb')
commit 0cca1ed2af3f74ec6519382c2d52dbfaa9762700
Author: Alexander Larsson <alexl at redhat.com>
Date: Mon Jun 14 16:11:04 2010 +0200
Add SpiceMarshaller for easy marshalling
diff --git a/common/Makefile.am b/common/Makefile.am
index 222965e..5c1d6e0 100644
--- a/common/Makefile.am
+++ b/common/Makefile.am
@@ -39,6 +39,8 @@ COMMON_SRCS = \
lz_config.h \
lz_decompress_tmpl.c \
lz.h \
+ marshaller.h \
+ marshaller.c \
quic_family_tmpl.c \
quic_rgb_tmpl.c \
quic_tmpl.c \
diff --git a/common/marshaller.c b/common/marshaller.c
new file mode 100644
index 0000000..13385e5
--- /dev/null
+++ b/common/marshaller.c
@@ -0,0 +1,588 @@
+/* -*- Mode: C; c-basic-offset: 4; indent-tabs-mode: nil -*- */
+/*
+ Copyright (C) 2010 Red Hat, Inc.
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this library; if not, see <http://www.gnu.org/licenses/>.
+*/
+
+#include "config.h"
+
+#include "marshaller.h"
+#include "mem.h"
+#include <string.h>
+#include <stdlib.h>
+#include <assert.h>
+
+#ifdef WORDS_BIGENDIAN
+#define write_int8(ptr,v) (*((int8_t *)(ptr)) = v)
+#define write_uint8(ptr,v) (*((uint8_t *)(ptr)) = v)
+#define write_int16(ptr,v) (*((int16_t)(ptr)) = SPICE_BYTESWAP16((uint16_t)(v)))
+#define write_uint16(ptr,v) (*((uint16_t)(ptr)) = SPICE_BYTESWAP16((uint16_t)(v)))
+#define write_int32(ptr,v) (*((int32_t)(ptr)) = SPICE_BYTESWAP32((uint32_t)(v)))
+#define write_uint32(ptr,v) (*((uint32_t)(ptr)) = SPICE_BYTESWAP32((uint32_t)(v)))
+#define write_int64(ptr,v) (*((int64_t)(ptr)) = SPICE_BYTESWAP64((uint63_t)(v)))
+#define write_uint64(ptr,v) (*((uint64_t)(ptr)) = SPICE_BYTESWAP64((uint63_t)(v)))
+#else
+#define write_int8(ptr,v) (*((int8_t *)(ptr)) = v)
+#define write_uint8(ptr,v) (*((uint8_t *)(ptr)) = v)
+#define write_int16(ptr,v) (*((int16_t *)(ptr)) = v)
+#define write_uint16(ptr,v) (*((uint16_t *)(ptr)) = v)
+#define write_int32(ptr,v) (*((int32_t *)(ptr)) = v)
+#define write_uint32(ptr,v) (*((uint32_t *)(ptr)) = v)
+#define write_int64(ptr,v) (*((int64_t *)(ptr)) = v)
+#define write_uint64(ptr,v) (*((uint64_t *)(ptr)) = v)
+#endif
+
+typedef struct {
+ uint8_t *data;
+ size_t len;
+ spice_marshaller_item_free_func free_data;
+ void *opaque;
+} MarshallerItem;
+
+/* Try to fit in 4k page with 2*pointer-size overhead (next ptr and malloc size) */
+#define MARSHALLER_BUFFER_SIZE (4096 - sizeof(void *) * 2)
+
+typedef struct MarshallerBuffer MarshallerBuffer;
+struct MarshallerBuffer {
+ MarshallerBuffer *next;
+ uint8_t data[MARSHALLER_BUFFER_SIZE];
+};
+
+#define N_STATIC_ITEMS 4
+
+typedef struct SpiceMarshallerData SpiceMarshallerData;
+
+typedef struct {
+ SpiceMarshaller *marshaller;
+ int item_nr;
+ int is_64bit;
+ size_t offset;
+} MarshallerRef;
+
+struct SpiceMarshaller {
+ size_t total_size;
+ SpiceMarshallerData *data;
+ SpiceMarshaller *next;
+
+ MarshallerRef pointer_ref;
+
+ int n_items;
+ int items_size; /* number of items availible in items */
+ MarshallerItem *items;
+
+ MarshallerItem static_items[N_STATIC_ITEMS];
+};
+
+struct SpiceMarshallerData {
+ size_t total_size;
+ size_t base;
+ SpiceMarshaller *marshallers;
+ SpiceMarshaller *last_marshaller;
+
+ size_t current_buffer_position;
+ MarshallerBuffer *current_buffer;
+ MarshallerItem *current_buffer_item;
+ MarshallerBuffer *buffers;
+
+ SpiceMarshaller static_marshaller;
+ MarshallerBuffer static_buffer;
+};
+
+static void spice_marshaller_init(SpiceMarshaller *m,
+ SpiceMarshallerData *data)
+{
+ m->data = data;
+ m->next = NULL;
+ m->total_size = 0;
+ m->pointer_ref.marshaller = NULL;
+ m->n_items = 0;
+ m->items_size = N_STATIC_ITEMS;
+ m->items = m->static_items;
+}
+
+SpiceMarshaller *spice_marshaller_new(void)
+{
+ SpiceMarshallerData *d;
+ SpiceMarshaller *m;
+
+ d = spice_new(SpiceMarshallerData, 1);
+
+ d->last_marshaller = d->marshallers = &d->static_marshaller;
+ d->total_size = 0;
+ d->base = 0;
+ d->buffers = &d->static_buffer;
+ d->buffers->next = NULL;
+ d->current_buffer = d->buffers;
+ d->current_buffer_position = 0;
+ d->current_buffer_item = NULL;
+
+ m = &d->static_marshaller;
+ spice_marshaller_init(m, d);
+
+ return m;
+}
+
+static void free_item_data(SpiceMarshaller *m)
+{
+ MarshallerItem *item;
+ int i;
+
+ /* Free all user data */
+ for (i = 0; i < m->n_items; i++) {
+ item = &m->items[i];
+ if (item->free_data != NULL) {
+ item->free_data(item->data, item->opaque);
+ }
+ }
+}
+
+static void free_items(SpiceMarshaller *m)
+{
+ if (m->items != m->static_items) {
+ free(m->items);
+ }
+}
+
+void spice_marshaller_reset(SpiceMarshaller *m)
+{
+ SpiceMarshaller *m2;
+ SpiceMarshallerData *d;
+
+ /* Only supported for root marshaller */
+ assert(m->data->marshallers == m);
+
+ for (m2 = m; m2 != NULL; m2 = m2->next) {
+ free_item_data(m2);
+
+ /* Free non-root marshallers */
+ if (m2 != m) {
+ free_items(m2);
+ free(m2);
+ }
+ }
+
+ m->next = NULL;
+ m->n_items = 0;
+ m->total_size = 0;
+
+ d = m->data;
+ d->last_marshaller = d->marshallers;
+ d->total_size = 0;
+ d->base = 0;
+ d->current_buffer_item = NULL;
+ d->current_buffer = d->buffers;
+ d->current_buffer_position = 0;
+}
+
+void spice_marshaller_destroy(SpiceMarshaller *m)
+{
+ MarshallerBuffer *buf, *next;
+ SpiceMarshallerData *d;
+
+ /* Only supported for root marshaller */
+ assert(m->data->marshallers == m);
+
+ spice_marshaller_reset(m);
+
+ free_items(m);
+
+ d = m->data;
+
+ buf = d->buffers->next;
+ while (buf != NULL) {
+ next = buf->next;
+ free(buf);
+ buf = next;
+ }
+
+ free(d);
+}
+
+static MarshallerItem *spice_marshaller_add_item(SpiceMarshaller *m)
+{
+ MarshallerItem *item;
+
+ if (m->n_items == m->items_size) {
+ int items_size = m->items_size * 2;
+
+ if (m->items == m->static_items) {
+ m->items = spice_new(MarshallerItem, items_size);
+ memcpy(m->items, m->static_items, sizeof(MarshallerItem) * m->n_items);
+ } else {
+ m->items = spice_renew(MarshallerItem, m->items, items_size);
+ }
+ m->items_size = items_size;
+ }
+ item = &m->items[m->n_items++];
+ item->free_data = NULL;
+
+ return item;
+}
+
+static size_t remaining_buffer_size(SpiceMarshallerData *d)
+{
+ return MARSHALLER_BUFFER_SIZE - d->current_buffer_position;
+}
+
+uint8_t *spice_marshaller_reserve_space(SpiceMarshaller *m, size_t size)
+{
+ MarshallerItem *item;
+ SpiceMarshallerData *d;
+ uint8_t *res;
+
+ if (size == 0) {
+ return NULL;
+ }
+
+ d = m->data;
+
+ /* Check current item */
+ item = &m->items[m->n_items - 1];
+ if (item == d->current_buffer_item &&
+ remaining_buffer_size(d) >= size) {
+ assert(m->n_items >= 1);
+ /* We can piggy back on existing item+buffer */
+ res = item->data + item->len;
+ item->len += size;
+ d->current_buffer_position += size;
+ d->total_size += size;
+ m->total_size += size;
+ return res;
+ }
+
+ item = spice_marshaller_add_item(m);
+
+ if (remaining_buffer_size(d) >= size) {
+ /* Fits in current buffer */
+ item->data = d->current_buffer->data + d->current_buffer_position;
+ item->len = size;
+ d->current_buffer_position += size;
+ d->current_buffer_item = item;
+ } else if (size > MARSHALLER_BUFFER_SIZE / 2) {
+ /* Large item, allocate by itself */
+ item->data = (uint8_t *)spice_malloc(size);
+ item->len = size;
+ item->free_data = (spice_marshaller_item_free_func)free;
+ item->opaque = NULL;
+ } else {
+ /* Use next buffer */
+ if (d->current_buffer->next == NULL) {
+ d->current_buffer->next = spice_new(MarshallerBuffer, 1);
+ d->current_buffer->next->next = NULL;
+ }
+ d->current_buffer = d->current_buffer->next;
+ d->current_buffer_position = size;
+ d->current_buffer_item = item;
+ item->data = d->current_buffer->data;
+ item->len = size;
+ }
+
+ d->total_size += size;
+ m->total_size += size;
+ return item->data;
+}
+
+void spice_marshaller_unreserve_space(SpiceMarshaller *m, size_t size)
+{
+ MarshallerItem *item;
+
+ if (size == 0) {
+ return;
+ }
+
+ item = &m->items[m->n_items - 1];
+
+ assert(item->len >= size);
+ item->len -= size;
+}
+
+uint8_t *spice_marshaller_add_ref_full(SpiceMarshaller *m, uint8_t *data, size_t size,
+ spice_marshaller_item_free_func free_data, void *opaque)
+{
+ MarshallerItem *item;
+ SpiceMarshallerData *d;
+
+ if (data == NULL || size == 0) {
+ return NULL;
+ }
+
+ item = spice_marshaller_add_item(m);
+ item->data = data;
+ item->len = size;
+ item->free_data = free_data;
+ item->opaque = opaque;
+
+ d = m->data;
+ m->total_size += size;
+ d->total_size += size;
+
+ return data;
+}
+
+uint8_t *spice_marshaller_add(SpiceMarshaller *m, uint8_t *data, size_t size)
+{
+ uint8_t *ptr;
+
+ ptr = spice_marshaller_reserve_space(m, size);
+ memcpy(ptr, data, size);
+ return ptr;
+}
+
+uint8_t *spice_marshaller_add_ref(SpiceMarshaller *m, uint8_t *data, size_t size)
+{
+ return spice_marshaller_add_ref_full(m, data, size, NULL, NULL);
+}
+
+SpiceMarshaller *spice_marshaller_get_submarshaller(SpiceMarshaller *m)
+{
+ SpiceMarshallerData *d;
+ SpiceMarshaller *m2;
+
+ d = m->data;
+
+ m2 = spice_new(SpiceMarshaller, 1);
+ spice_marshaller_init(m2, d);
+
+ d->last_marshaller->next = m2;
+ d->last_marshaller = m2;
+
+ return m2;
+}
+
+SpiceMarshaller *spice_marshaller_get_ptr_submarshaller(SpiceMarshaller *m, int is_64bit)
+{
+ SpiceMarshaller *m2;
+ uint8_t *p;
+ int size;
+
+ size = is_64bit ? 8 : 4;
+
+ p = spice_marshaller_reserve_space(m, size);
+ memset(p, 0, size);
+ m2 = spice_marshaller_get_submarshaller(m);
+ m2->pointer_ref.marshaller = m;
+ m2->pointer_ref.item_nr = m->n_items - 1;
+ m2->pointer_ref.offset = m->items[m->n_items - 1].len - size;
+ m2->pointer_ref.is_64bit = is_64bit;
+
+ return m2;
+}
+
+uint8_t *lookup_ref(MarshallerRef *ref)
+{
+ MarshallerItem *item;
+
+ item = &ref->marshaller->items[ref->item_nr];
+ return item->data + ref->offset;
+}
+
+
+void spice_marshaller_set_base(SpiceMarshaller *m, size_t base)
+{
+ /* Only supported for root marshaller */
+ assert(m->data->marshallers == m);
+
+ m->data->base = base;
+}
+
+uint8_t *spice_marshaller_linearize(SpiceMarshaller *m, size_t skip_bytes,
+ size_t *len, int *free_res)
+{
+ MarshallerItem *item;
+ uint8_t *res, *p;
+ int i;
+
+ /* Only supported for root marshaller */
+ assert(m->data->marshallers == m);
+
+ if (m->n_items == 1) {
+ *free_res = FALSE;
+ if (m->items[0].len <= skip_bytes) {
+ *len = 0;
+ return NULL;
+ }
+ *len = m->items[0].len - skip_bytes;
+ return m->items[0].data + skip_bytes;
+ }
+
+ *free_res = TRUE;
+ res = (uint8_t *)spice_malloc(m->data->total_size - skip_bytes);
+ *len = m->data->total_size - skip_bytes;
+ p = res;
+
+ do {
+ for (i = 0; i < m->n_items; i++) {
+ item = &m->items[i];
+
+ if (item->len <= skip_bytes) {
+ skip_bytes -= item->len;
+ continue;
+ }
+ memcpy(p, item->data + skip_bytes, item->len - skip_bytes);
+ p += item->len - skip_bytes;
+ skip_bytes = 0;
+ }
+ m = m->next;
+ } while (m != NULL);
+
+ return res;
+}
+
+uint8_t *spice_marshaller_get_ptr(SpiceMarshaller *m)
+{
+ return m->items[0].data;
+}
+
+size_t spice_marshaller_get_offset(SpiceMarshaller *m)
+{
+ SpiceMarshaller *m2;
+ size_t offset;
+
+ offset = 0;
+ m2 = m->data->marshallers;
+ while (m2 != m) {
+ offset += m2->total_size;
+ m2 = m2->next;
+ }
+ return offset - m->data->base;
+}
+
+size_t spice_marshaller_get_size(SpiceMarshaller *m)
+{
+ return m->total_size;
+}
+
+size_t spice_marshaller_get_total_size(SpiceMarshaller *m)
+{
+ return m->data->total_size;
+}
+
+void spice_marshaller_flush(SpiceMarshaller *m)
+{
+ SpiceMarshaller *m2;
+ uint8_t *ptr_pos;
+
+ /* Only supported for root marshaller */
+ assert(m->data->marshallers == m);
+
+ for (m2 = m; m2 != NULL; m2 = m2->next) {
+ if (m2->pointer_ref.marshaller != NULL && m2->total_size > 0) {
+ ptr_pos = lookup_ref(&m2->pointer_ref);
+ if (m2->pointer_ref.is_64bit) {
+ write_uint64(ptr_pos,
+ spice_marshaller_get_offset(m2));
+ } else {
+ write_uint32(ptr_pos,
+ spice_marshaller_get_offset(m2));
+ }
+ }
+ }
+}
+
+int spice_marshaller_fill_iovec(SpiceMarshaller *m, struct iovec *vec,
+ int n_vec, size_t skip_bytes)
+{
+ MarshallerItem *item;
+ int v, i;
+
+ /* Only supported for root marshaller */
+ assert(m->data->marshallers == m);
+
+ v = 0;
+ do {
+ for (i = 0; i < m->n_items; i++) {
+ item = &m->items[i];
+
+ if (item->len <= skip_bytes) {
+ skip_bytes -= item->len;
+ continue;
+ }
+ if (v == n_vec) {
+ return v; /* Not enough space in vec */
+ }
+ vec[v].iov_base = item->data + skip_bytes;
+ vec[v].iov_len = item->len - skip_bytes;
+ skip_bytes = 0;
+ v++;
+ }
+ m = m->next;
+ } while (m != NULL);
+
+ return v;
+}
+
+void spice_marshaller_add_uint64(SpiceMarshaller *m, uint64_t v)
+{
+ uint8_t *ptr;
+
+ ptr = spice_marshaller_reserve_space(m, sizeof(uint64_t));
+ write_uint64(ptr, v);
+}
+
+void spice_marshaller_add_int64(SpiceMarshaller *m, int64_t v)
+{
+ uint8_t *ptr;
+
+ ptr = spice_marshaller_reserve_space(m, sizeof(int64_t));
+ write_int64(ptr, v);
+}
+
+void spice_marshaller_add_uint32(SpiceMarshaller *m, uint32_t v)
+{
+ uint8_t *ptr;
+
+ ptr = spice_marshaller_reserve_space(m, sizeof(uint32_t));
+ write_uint32(ptr, v);
+}
+
+void spice_marshaller_add_int32(SpiceMarshaller *m, int32_t v)
+{
+ uint8_t *ptr;
+
+ ptr = spice_marshaller_reserve_space(m, sizeof(int32_t));
+ write_int32(ptr, v);
+}
+
+void spice_marshaller_add_uint16(SpiceMarshaller *m, uint16_t v)
+{
+ uint8_t *ptr;
+
+ ptr = spice_marshaller_reserve_space(m, sizeof(uint16_t));
+ write_uint16(ptr, v);
+}
+
+void spice_marshaller_add_int16(SpiceMarshaller *m, int16_t v)
+{
+ uint8_t *ptr;
+
+ ptr = spice_marshaller_reserve_space(m, sizeof(int16_t));
+ write_int16(ptr, v);
+}
+
+void spice_marshaller_add_uint8(SpiceMarshaller *m, uint8_t v)
+{
+ uint8_t *ptr;
+
+ ptr = spice_marshaller_reserve_space(m, sizeof(uint8_t));
+ write_uint8(ptr, v);
+}
+
+void spice_marshaller_add_int8(SpiceMarshaller *m, int8_t v)
+{
+ uint8_t *ptr;
+
+ ptr = spice_marshaller_reserve_space(m, sizeof(int8_t));
+ write_int8(ptr, v);
+}
diff --git a/common/marshaller.h b/common/marshaller.h
new file mode 100644
index 0000000..3b159aa
--- /dev/null
+++ b/common/marshaller.h
@@ -0,0 +1,58 @@
+/* -*- Mode: C; c-basic-offset: 4; indent-tabs-mode: nil -*- */
+/*
+ Copyright (C) 2010 Red Hat, Inc.
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this library; if not, see <http://www.gnu.org/licenses/>.
+*/
+
+#ifndef _H_MARSHALLER
+#define _H_MARSHALLER
+
+#include <spice/types.h>
+#include <sys/uio.h>
+
+typedef struct SpiceMarshaller SpiceMarshaller;
+typedef void (*spice_marshaller_item_free_func)(uint8_t *data, void *opaque);
+
+SpiceMarshaller *spice_marshaller_new(void);
+void spice_marshaller_reset(SpiceMarshaller *m);
+void spice_marshaller_destroy(SpiceMarshaller *m);
+uint8_t *spice_marshaller_reserve_space(SpiceMarshaller *m, size_t size);
+void spice_marshaller_unreserve_space(SpiceMarshaller *m, size_t size);
+uint8_t *spice_marshaller_add(SpiceMarshaller *m, uint8_t *data, size_t size);
+uint8_t *spice_marshaller_add_ref(SpiceMarshaller *m, uint8_t *data, size_t size);
+uint8_t *spice_marshaller_add_ref_full(SpiceMarshaller *m, uint8_t *data, size_t size,
+ spice_marshaller_item_free_func free_data, void *opaque);
+void spice_marshaller_flush(SpiceMarshaller *m);
+void spice_marshaller_set_base(SpiceMarshaller *m, size_t base);
+uint8_t *spice_marshaller_linearize(SpiceMarshaller *m, size_t skip,
+ size_t *len, int *free_res);
+uint8_t *spice_marshaller_get_ptr(SpiceMarshaller *m);
+size_t spice_marshaller_get_offset(SpiceMarshaller *m);
+size_t spice_marshaller_get_size(SpiceMarshaller *m);
+size_t spice_marshaller_get_total_size(SpiceMarshaller *m);
+SpiceMarshaller *spice_marshaller_get_submarshaller(SpiceMarshaller *m);
+SpiceMarshaller *spice_marshaller_get_ptr_submarshaller(SpiceMarshaller *m, int is_64bit);
+int spice_marshaller_fill_iovec(SpiceMarshaller *m, struct iovec *vec,
+ int n_vec, size_t skip_bytes);
+void spice_marshaller_add_uint64(SpiceMarshaller *m, uint64_t v);
+void spice_marshaller_add_int64(SpiceMarshaller *m, int64_t v);
+void spice_marshaller_add_uint32(SpiceMarshaller *m, uint32_t v);
+void spice_marshaller_add_int32(SpiceMarshaller *m, int32_t v);
+void spice_marshaller_add_uint16(SpiceMarshaller *m, uint16_t v);
+void spice_marshaller_add_int16(SpiceMarshaller *m, int16_t v);
+void spice_marshaller_add_uint8(SpiceMarshaller *m, uint8_t v);
+void spice_marshaller_add_int8(SpiceMarshaller *m, int8_t v);
+
+#endif
diff --git a/server/Makefile.am b/server/Makefile.am
index 8d93618..ff97a40 100644
--- a/server/Makefile.am
+++ b/server/Makefile.am
@@ -31,6 +31,7 @@ COMMON_SRCS = \
$(top_srcdir)/common/lz.c \
$(top_srcdir)/common/canvas_utils.c \
$(top_srcdir)/common/mem.c \
+ $(top_srcdir)/common/marshaller.c \
$(NULL)
lib_LTLIBRARIES = libspice-server.la
commit 1a0b3fbdbb4d0c0cb54415e361dcd2af164ecdd7
Author: Alexander Larsson <alexl at redhat.com>
Date: Wed May 26 15:46:42 2010 +0200
Generate demarshalling code on win32 too
diff --git a/client/windows/redc.vcproj b/client/windows/redc.vcproj
index f980c21..a178a33 100644
--- a/client/windows/redc.vcproj
+++ b/client/windows/redc.vcproj
@@ -29,6 +29,10 @@
/>
<Tool
Name="VCCustomBuildTool"
+ Description=""
+ CommandLine=""
+ AdditionalDependencies=""
+ Outputs=""
/>
<Tool
Name="VCXMLDataGeneratorTool"
@@ -192,10 +196,6 @@
>
</File>
<File
- RelativePath="..\sw_canvas.cpp"
- >
- </File>
- <File
RelativePath="..\canvas.cpp"
>
</File>
@@ -220,6 +220,10 @@
>
</File>
<File
+ RelativePath="..\generated_demarshallers.cpp"
+ >
+ </File>
+ <File
RelativePath="..\display_channel.cpp"
>
</File>
@@ -350,10 +354,6 @@
>
</File>
<File
- RelativePath="..\red_sw_canvas.cpp"
- >
- </File>
- <File
RelativePath="..\red_channel.cpp"
>
</File>
@@ -378,11 +378,15 @@
>
</File>
<File
+ RelativePath=".\red_pixmap_gdi.cpp"
+ >
+ </File>
+ <File
RelativePath=".\red_pixmap_sw.cpp"
>
</File>
<File
- RelativePath=".\red_pixmap_gdi.cpp"
+ RelativePath="..\red_sw_canvas.cpp"
>
</File>
<File
@@ -418,6 +422,10 @@
>
</File>
<File
+ RelativePath="..\sw_canvas.cpp"
+ >
+ </File>
+ <File
RelativePath="..\threads.cpp"
>
</File>
@@ -472,6 +480,10 @@
>
</File>
<File
+ RelativePath="..\demarshallers.h"
+ >
+ </File>
+ <File
RelativePath="..\display_channel.h"
>
</File>
@@ -572,10 +584,6 @@
>
</File>
<File
- RelativePath="..\red_sw_canvas.h"
- >
- </File>
- <File
RelativePath="..\red_channel.h"
>
</File>
@@ -600,6 +608,10 @@
>
</File>
<File
+ RelativePath="..\red_sw_canvas.h"
+ >
+ </File>
+ <File
RelativePath="..\red_window.h"
>
</File>
@@ -674,6 +686,31 @@
>
</File>
</Filter>
+ <File
+ RelativePath="..\..\spice.proto"
+ >
+ <FileConfiguration
+ Name="Debug|Win32"
+ >
+ <Tool
+ Name="VCCustomBuildTool"
+ Description="Generating demarshaller"
+ CommandLine="python $(ProjectDir)\..\..\spice_codegen.py -d -c -i common.h $(ProjectDir)\..\..\spice.proto $(ProjectDir)\..\generated_demarshallers.cpp
"
+ AdditionalDependencies=""
+ Outputs="$(ProjectDir)/../generated_demarshallers.cpp"
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32"
+ >
+ <Tool
+ Name="VCCustomBuildTool"
+ Description="Generating demarshaller"
+ CommandLine="python $(ProjectDir)\..\..\spice_codegen.py -d -c -i common.h $(ProjectDir)\..\..\spice.proto $(ProjectDir)\..\generated_demarshallers.cpp"
+ Outputs="$(ProjectDir)/../generated_demarshallers.cpp"
+ />
+ </FileConfiguration>
+ </File>
</Files>
<Globals>
</Globals>
commit 4154d7028943ca4bf0f1ff2e0480d688fc081fcc
Author: Alexander Larsson <alexl at redhat.com>
Date: Tue May 25 16:01:18 2010 +0200
Client: Use the autogenerated demarshallers
When a message has been read from the network we now pass it into
the generated demarshaller for the channel. The demarshaller converts
the network data to in-memory structures that is passed on to the
spice internals.
Additionally it also:
* Converts endianness
* Validates sizes of message and any pointers in it
* Localizes offsets (converts them to pointers)
* Checks for zero offsets in messages where they are not supported
Some of this was previously done using custom code in the client, this
is now removed.
diff --git a/client/Makefile.am b/client/Makefile.am
index ab80bfb..f8ccb98 100644
--- a/client/Makefile.am
+++ b/client/Makefile.am
@@ -27,6 +27,8 @@ RED_COMMON_SRCS = \
cmd_line_parser.cpp \
cmd_line_parser.h \
common.h \
+ demarshallers.h \
+ generated_demarshallers.cpp \
cursor_channel.cpp \
cursor_channel.h \
cursor.cpp \
diff --git a/client/canvas.cpp b/client/canvas.cpp
index 4ed1e18..284a814 100644
--- a/client/canvas.cpp
+++ b/client/canvas.cpp
@@ -44,95 +44,14 @@ void Canvas::clear()
}
}
-
-inline void Canvas::access_test(void *ptr, size_t size)
-{
- if ((unsigned long)ptr < _base || (unsigned long)ptr + size > _max) {
- THROW("access violation %p %lu", ptr, size);
- }
-}
-
-void Canvas::localalize_ptr(SPICE_ADDRESS* data)
-{
- if (*data) {
- *data += _base;
- }
-}
-
-void Canvas::localalize_image(SPICE_ADDRESS* in_bitmap)
-{
- SpiceImageDescriptor* image;
-
- ASSERT(*in_bitmap);
- localalize_ptr(in_bitmap);
- image = (SpiceImageDescriptor*)SPICE_GET_ADDRESS(*in_bitmap);
- switch (image->type) {
- case SPICE_IMAGE_TYPE_SURFACE:
- break;
- case SPICE_IMAGE_TYPE_BITMAP: {
- SpiceBitmapImage *bitmap = (SpiceBitmapImage *)image;
- localalize_ptr(&bitmap->bitmap.data);
- if (bitmap->bitmap.palette && !(bitmap->bitmap.flags & SPICE_BITMAP_FLAGS_PAL_FROM_CACHE)) {
- localalize_ptr(&bitmap->bitmap.palette);
- }
- break;
- }
- case SPICE_IMAGE_TYPE_LZ_PLT: {
- SpiceLZPLTImage *lzImage = (SpiceLZPLTImage *)image;
- ASSERT(lzImage->lz_plt.palette);
- if (!(lzImage->lz_plt.flags & SPICE_BITMAP_FLAGS_PAL_FROM_CACHE)) {
- localalize_ptr(&lzImage->lz_plt.palette);
- }
- break;
- }
- case SPICE_IMAGE_TYPE_LZ_RGB:
- case SPICE_IMAGE_TYPE_GLZ_RGB:
- case SPICE_IMAGE_TYPE_QUIC:
- case SPICE_IMAGE_TYPE_JPEG:
- break;
- case SPICE_IMAGE_TYPE_FROM_CACHE:
- case SPICE_IMAGE_TYPE_FROM_CACHE_LOSSLESS:
- break;
- default:
- THROW("invalid image type %u", image->type);
- }
-}
-
-void Canvas::localalize_brush(SpiceBrush& brush)
-{
- if (brush.type == SPICE_BRUSH_TYPE_PATTERN) {
- localalize_image(&brush.u.pattern.pat);
- }
-}
-
-void Canvas::localalize_attr(SpiceLineAttr& attr)
-{
- if (attr.style_nseg) {
- localalize_ptr(&attr.style);
- }
-}
-
-void Canvas::localalize_mask(SpiceQMask& mask)
-{
- if (mask.bitmap) {
- localalize_image(&mask.bitmap);
- }
-}
-
void Canvas::begin_draw(SpiceMsgDisplayBase& base, int size, size_t min_size)
{
_base = (unsigned long)&base;
- _max = _base + size;
- _canvas->ops->set_access_params(_canvas, _base, _max);
- access_test(&base, min_size);
- localalize_ptr(&base.clip.data);
}
void Canvas::draw_fill(SpiceMsgDisplayDrawFill& fill, int size)
{
begin_draw(fill.base, size, sizeof(SpiceMsgDisplayDrawFill));
- localalize_brush(fill.data.brush);
- localalize_mask(fill.data.mask);
_canvas->ops->draw_fill(_canvas, &fill.base.box, &fill.base.clip, &fill.data);
touched_bbox(&fill.base.box);
}
@@ -140,9 +59,6 @@ void Canvas::draw_fill(SpiceMsgDisplayDrawFill& fill, int size)
void Canvas::draw_text(SpiceMsgDisplayDrawText& text, int size)
{
begin_draw(text.base, size, sizeof(SpiceMsgDisplayDrawText));
- localalize_brush(text.data.fore_brush);
- localalize_brush(text.data.back_brush);
- localalize_ptr(&text.data.str);
_canvas->ops->draw_text(_canvas, &text.base.box, &text.base.clip, &text.data);
touched_bbox(&text.base.box);
}
@@ -150,9 +66,6 @@ void Canvas::draw_text(SpiceMsgDisplayDrawText& text, int size)
void Canvas::draw_opaque(SpiceMsgDisplayDrawOpaque& opaque, int size)
{
begin_draw(opaque.base, size, sizeof(SpiceMsgDisplayDrawOpaque));
- localalize_brush(opaque.data.brush);
- localalize_image(&opaque.data.src_bitmap);
- localalize_mask(opaque.data.mask);
_canvas->ops->draw_opaque(_canvas, &opaque.base.box, &opaque.base.clip, &opaque.data);
touched_bbox(&opaque.base.box);
}
@@ -160,8 +73,6 @@ void Canvas::draw_opaque(SpiceMsgDisplayDrawOpaque& opaque, int size)
void Canvas::draw_copy(SpiceMsgDisplayDrawCopy& copy, int size)
{
begin_draw(copy.base, size, sizeof(SpiceMsgDisplayDrawCopy));
- localalize_image(©.data.src_bitmap);
- localalize_mask(copy.data.mask);
_canvas->ops->draw_copy(_canvas, ©.base.box, ©.base.clip, ©.data);
touched_bbox(©.base.box);
}
@@ -169,7 +80,6 @@ void Canvas::draw_copy(SpiceMsgDisplayDrawCopy& copy, int size)
void Canvas::draw_transparent(SpiceMsgDisplayDrawTransparent& transparent, int size)
{
begin_draw(transparent.base, size, sizeof(SpiceMsgDisplayDrawTransparent));
- localalize_image(&transparent.data.src_bitmap);
_canvas->ops->draw_transparent(_canvas, &transparent.base.box, &transparent.base.clip, &transparent.data);
touched_bbox(&transparent.base.box);
}
@@ -177,7 +87,6 @@ void Canvas::draw_transparent(SpiceMsgDisplayDrawTransparent& transparent, int s
void Canvas::draw_alpha_blend(SpiceMsgDisplayDrawAlphaBlend& alpha_blend, int size)
{
begin_draw(alpha_blend.base, size, sizeof(SpiceMsgDisplayDrawAlphaBlend));
- localalize_image(&alpha_blend.data.src_bitmap);
_canvas->ops->draw_alpha_blend(_canvas, &alpha_blend.base.box, &alpha_blend.base.clip, &alpha_blend.data);
touched_bbox(&alpha_blend.base.box);
}
@@ -192,8 +101,6 @@ void Canvas::copy_bits(SpiceMsgDisplayCopyBits& copy, int size)
void Canvas::draw_blend(SpiceMsgDisplayDrawBlend& blend, int size)
{
begin_draw(blend.base, size, sizeof(SpiceMsgDisplayDrawBlend));
- localalize_image(&blend.data.src_bitmap);
- localalize_mask(blend.data.mask);
_canvas->ops->draw_blend(_canvas, &blend.base.box, &blend.base.clip, &blend.data);
touched_bbox(&blend.base.box);
}
@@ -201,7 +108,6 @@ void Canvas::draw_blend(SpiceMsgDisplayDrawBlend& blend, int size)
void Canvas::draw_blackness(SpiceMsgDisplayDrawBlackness& blackness, int size)
{
begin_draw(blackness.base, size, sizeof(SpiceMsgDisplayDrawBlackness));
- localalize_mask(blackness.data.mask);
_canvas->ops->draw_blackness(_canvas, &blackness.base.box, &blackness.base.clip, &blackness.data);
touched_bbox(&blackness.base.box);
}
@@ -209,7 +115,6 @@ void Canvas::draw_blackness(SpiceMsgDisplayDrawBlackness& blackness, int size)
void Canvas::draw_whiteness(SpiceMsgDisplayDrawWhiteness& whiteness, int size)
{
begin_draw(whiteness.base, size, sizeof(SpiceMsgDisplayDrawWhiteness));
- localalize_mask(whiteness.data.mask);
_canvas->ops->draw_whiteness(_canvas, &whiteness.base.box, &whiteness.base.clip, &whiteness.data);
touched_bbox(&whiteness.base.box);
}
@@ -217,7 +122,6 @@ void Canvas::draw_whiteness(SpiceMsgDisplayDrawWhiteness& whiteness, int size)
void Canvas::draw_invers(SpiceMsgDisplayDrawInvers& invers, int size)
{
begin_draw(invers.base, size, sizeof(SpiceMsgDisplayDrawInvers));
- localalize_mask(invers.data.mask);
_canvas->ops->draw_invers(_canvas, &invers.base.box, &invers.base.clip, &invers.data);
touched_bbox(&invers.base.box);
}
@@ -225,9 +129,6 @@ void Canvas::draw_invers(SpiceMsgDisplayDrawInvers& invers, int size)
void Canvas::draw_rop3(SpiceMsgDisplayDrawRop3& rop3, int size)
{
begin_draw(rop3.base, size, sizeof(SpiceMsgDisplayDrawRop3));
- localalize_brush(rop3.data.brush);
- localalize_image(&rop3.data.src_bitmap);
- localalize_mask(rop3.data.mask);
_canvas->ops->draw_rop3(_canvas, &rop3.base.box, &rop3.base.clip, &rop3.data);
touched_bbox(&rop3.base.box);
}
@@ -235,9 +136,6 @@ void Canvas::draw_rop3(SpiceMsgDisplayDrawRop3& rop3, int size)
void Canvas::draw_stroke(SpiceMsgDisplayDrawStroke& stroke, int size)
{
begin_draw(stroke.base, size, sizeof(SpiceMsgDisplayDrawStroke));
- localalize_brush(stroke.data.brush);
- localalize_ptr(&stroke.data.path);
- localalize_attr(stroke.data.attr);
_canvas->ops->draw_stroke(_canvas, &stroke.base.box, &stroke.base.clip, &stroke.data);
touched_bbox(&stroke.base.box);
}
diff --git a/client/canvas.h b/client/canvas.h
index f0314b9..c988a52 100644
--- a/client/canvas.h
+++ b/client/canvas.h
@@ -452,7 +452,6 @@ private:
void localalize_ptr(SPICE_ADDRESS* data);
void localalize_image(SPICE_ADDRESS* in_bitmap);
void localalize_brush(SpiceBrush& brush);
- void localalize_attr(SpiceLineAttr& attr);
void localalize_mask(SpiceQMask& mask);
void begin_draw(SpiceMsgDisplayBase& base, int size, size_t min_size);
diff --git a/client/cursor_channel.cpp b/client/cursor_channel.cpp
index 44cacd4..26eb4c8 100644
--- a/client/cursor_channel.cpp
+++ b/client/cursor_channel.cpp
@@ -348,10 +348,10 @@ private:
CursorChannel& _channel;
};
-class CursorHandler: public MessageHandlerImp<CursorChannel, SPICE_MSG_END_CURSOR> {
+class CursorHandler: public MessageHandlerImp<CursorChannel, SPICE_CHANNEL_CURSOR> {
public:
CursorHandler(CursorChannel& channel)
- : MessageHandlerImp<CursorChannel, SPICE_MSG_END_CURSOR>(channel) {}
+ : MessageHandlerImp<CursorChannel, SPICE_CHANNEL_CURSOR>(channel) {}
};
CursorChannel::CursorChannel(RedClient& client, uint32_t id)
@@ -363,27 +363,21 @@ CursorChannel::CursorChannel(RedClient& client, uint32_t id)
{
CursorHandler* handler = static_cast<CursorHandler*>(get_message_handler());
- handler->set_handler(SPICE_MSG_MIGRATE, &CursorChannel::handle_migrate, 0);
- handler->set_handler(SPICE_MSG_SET_ACK, &CursorChannel::handle_set_ack, sizeof(SpiceMsgSetAck));
- handler->set_handler(SPICE_MSG_PING, &CursorChannel::handle_ping, sizeof(SpiceMsgPing));
- handler->set_handler(SPICE_MSG_WAIT_FOR_CHANNELS, &CursorChannel::handle_wait_for_channels,
- sizeof(SpiceMsgWaitForChannels));
- handler->set_handler(SPICE_MSG_DISCONNECTING, &CursorChannel::handle_disconnect,
- sizeof(SpiceMsgDisconnect));
- handler->set_handler(SPICE_MSG_NOTIFY, &CursorChannel::handle_notify, sizeof(SpiceMsgNotify));
-
- handler->set_handler(SPICE_MSG_CURSOR_INIT, &CursorChannel::handle_init, sizeof(SpiceMsgCursorInit));
- handler->set_handler(SPICE_MSG_CURSOR_RESET, &CursorChannel::handle_reset, 0);
- handler->set_handler(SPICE_MSG_CURSOR_SET, &CursorChannel::handle_cursor_set,
- sizeof(SpiceMsgCursorSet));
- handler->set_handler(SPICE_MSG_CURSOR_MOVE, &CursorChannel::handle_cursor_move,
- sizeof(SpiceMsgCursorMove));
- handler->set_handler(SPICE_MSG_CURSOR_HIDE, &CursorChannel::handle_cursor_hide, 0);
- handler->set_handler(SPICE_MSG_CURSOR_TRAIL, &CursorChannel::handle_cursor_trail,
- sizeof(SpiceMsgCursorTrail));
- handler->set_handler(SPICE_MSG_CURSOR_INVAL_ONE, &CursorChannel::handle_inval_one,
- sizeof(SpiceMsgDisplayInvalOne));
- handler->set_handler(SPICE_MSG_CURSOR_INVAL_ALL, &CursorChannel::handle_inval_all, 0);
+ handler->set_handler(SPICE_MSG_MIGRATE, &CursorChannel::handle_migrate);
+ handler->set_handler(SPICE_MSG_SET_ACK, &CursorChannel::handle_set_ack);
+ handler->set_handler(SPICE_MSG_PING, &CursorChannel::handle_ping);
+ handler->set_handler(SPICE_MSG_WAIT_FOR_CHANNELS, &CursorChannel::handle_wait_for_channels);
+ handler->set_handler(SPICE_MSG_DISCONNECTING, &CursorChannel::handle_disconnect);
+ handler->set_handler(SPICE_MSG_NOTIFY, &CursorChannel::handle_notify);
+
+ handler->set_handler(SPICE_MSG_CURSOR_INIT, &CursorChannel::handle_init);
+ handler->set_handler(SPICE_MSG_CURSOR_RESET, &CursorChannel::handle_reset);
+ handler->set_handler(SPICE_MSG_CURSOR_SET, &CursorChannel::handle_cursor_set);
+ handler->set_handler(SPICE_MSG_CURSOR_MOVE, &CursorChannel::handle_cursor_move);
+ handler->set_handler(SPICE_MSG_CURSOR_HIDE, &CursorChannel::handle_cursor_hide);
+ handler->set_handler(SPICE_MSG_CURSOR_TRAIL, &CursorChannel::handle_cursor_trail);
+ handler->set_handler(SPICE_MSG_CURSOR_INVAL_ONE, &CursorChannel::handle_inval_one);
+ handler->set_handler(SPICE_MSG_CURSOR_INVAL_ALL, &CursorChannel::handle_inval_all);
}
CursorChannel::~CursorChannel()
diff --git a/client/demarshallers.h b/client/demarshallers.h
new file mode 100644
index 0000000..8118973
--- /dev/null
+++ b/client/demarshallers.h
@@ -0,0 +1,25 @@
+/*
+ Copyright (C) 2010 Red Hat, Inc.
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this library; if not, see <http://www.gnu.org/licenses/>.
+*/
+#ifndef _H_DEMARSHAL
+#define _H_DEMARSHAL
+
+typedef uint8_t * (*spice_parse_channel_func_t)(uint8_t *message_start, uint8_t *message_end, uint16_t message_type, int minor, size_t *size_out);
+
+spice_parse_channel_func_t spice_get_server_channel_parser(uint32_t channel, unsigned int *max_message_type);
+
+#endif
+
diff --git a/client/display_channel.cpp b/client/display_channel.cpp
index 5d18517..9cc5550 100644
--- a/client/display_channel.cpp
+++ b/client/display_channel.cpp
@@ -578,10 +578,10 @@ Canvas* DisplaySurfacesManger::get_canvas(int surface_id)
return canvases.get(surface_id);
}
-class DisplayHandler: public MessageHandlerImp<DisplayChannel, SPICE_MSG_END_DISPLAY> {
+class DisplayHandler: public MessageHandlerImp<DisplayChannel, SPICE_CHANNEL_DISPLAY> {
public:
DisplayHandler(DisplayChannel& channel)
- : MessageHandlerImp<DisplayChannel, SPICE_MSG_END_DISPLAY>(channel) {}
+ : MessageHandlerImp<DisplayChannel, SPICE_CHANNEL_DISPLAY>(channel) {}
};
DisplayChannel::DisplayChannel(RedClient& client, uint32_t id,
@@ -608,42 +608,33 @@ DisplayChannel::DisplayChannel(RedClient& client, uint32_t id,
{
DisplayHandler* handler = static_cast<DisplayHandler*>(get_message_handler());
- handler->set_handler(SPICE_MSG_MIGRATE, &DisplayChannel::handle_migrate, 0);
- handler->set_handler(SPICE_MSG_SET_ACK, &DisplayChannel::handle_set_ack, sizeof(SpiceMsgSetAck));
- handler->set_handler(SPICE_MSG_PING, &DisplayChannel::handle_ping, sizeof(SpiceMsgPing));
- handler->set_handler(SPICE_MSG_WAIT_FOR_CHANNELS, &DisplayChannel::handle_wait_for_channels,
- sizeof(SpiceMsgWaitForChannels));
- handler->set_handler(SPICE_MSG_DISCONNECTING, &DisplayChannel::handle_disconnect,
- sizeof(SpiceMsgDisconnect));
- handler->set_handler(SPICE_MSG_NOTIFY, &DisplayChannel::handle_notify, sizeof(SpiceMsgNotify));
+ handler->set_handler(SPICE_MSG_MIGRATE, &DisplayChannel::handle_migrate);
+ handler->set_handler(SPICE_MSG_SET_ACK, &DisplayChannel::handle_set_ack);
+ handler->set_handler(SPICE_MSG_PING, &DisplayChannel::handle_ping);
+ handler->set_handler(SPICE_MSG_WAIT_FOR_CHANNELS, &DisplayChannel::handle_wait_for_channels);
+ handler->set_handler(SPICE_MSG_DISCONNECTING, &DisplayChannel::handle_disconnect);
+ handler->set_handler(SPICE_MSG_NOTIFY, &DisplayChannel::handle_notify);
- handler->set_handler(SPICE_MSG_DISPLAY_MARK, &DisplayChannel::handle_mark, 0);
- handler->set_handler(SPICE_MSG_DISPLAY_RESET, &DisplayChannel::handle_reset, 0);
+ handler->set_handler(SPICE_MSG_DISPLAY_MARK, &DisplayChannel::handle_mark);
+ handler->set_handler(SPICE_MSG_DISPLAY_RESET, &DisplayChannel::handle_reset);
handler->set_handler(SPICE_MSG_DISPLAY_INVAL_LIST,
- &DisplayChannel::handle_inval_list,
- sizeof(SpiceResourceList));
+ &DisplayChannel::handle_inval_list);
handler->set_handler(SPICE_MSG_DISPLAY_INVAL_ALL_PIXMAPS,
- &DisplayChannel::handle_inval_all_pixmaps,
- sizeof(SpiceMsgWaitForChannels));
+ &DisplayChannel::handle_inval_all_pixmaps);
handler->set_handler(SPICE_MSG_DISPLAY_INVAL_PALETTE,
- &DisplayChannel::handle_inval_palette, sizeof(SpiceMsgDisplayInvalOne));
+ &DisplayChannel::handle_inval_palette);
handler->set_handler(SPICE_MSG_DISPLAY_INVAL_ALL_PALETTES,
- &DisplayChannel::handle_inval_all_palettes, 0);
-
- handler->set_handler(SPICE_MSG_DISPLAY_STREAM_CREATE, &DisplayChannel::handle_stream_create,
- sizeof(SpiceMsgDisplayStreamCreate));
- handler->set_handler(SPICE_MSG_DISPLAY_STREAM_CLIP, &DisplayChannel::handle_stream_clip,
- sizeof(SpiceMsgDisplayStreamClip));
- handler->set_handler(SPICE_MSG_DISPLAY_STREAM_DESTROY, &DisplayChannel::handle_stream_destroy,
- sizeof(SpiceMsgDisplayStreamDestroy));
+ &DisplayChannel::handle_inval_all_palettes);
+
+ handler->set_handler(SPICE_MSG_DISPLAY_STREAM_CREATE, &DisplayChannel::handle_stream_create);
+ handler->set_handler(SPICE_MSG_DISPLAY_STREAM_CLIP, &DisplayChannel::handle_stream_clip);
+ handler->set_handler(SPICE_MSG_DISPLAY_STREAM_DESTROY, &DisplayChannel::handle_stream_destroy);
handler->set_handler(SPICE_MSG_DISPLAY_STREAM_DESTROY_ALL,
- &DisplayChannel::handle_stream_destroy_all, 0);
+ &DisplayChannel::handle_stream_destroy_all);
- handler->set_handler(SPICE_MSG_DISPLAY_SURFACE_CREATE, &DisplayChannel::handle_surface_create,
- sizeof(SpiceMsgSurfaceCreate));
- handler->set_handler(SPICE_MSG_DISPLAY_SURFACE_DESTROY, &DisplayChannel::handle_surface_destroy,
- sizeof(SpiceMsgSurfaceDestroy));
+ handler->set_handler(SPICE_MSG_DISPLAY_SURFACE_CREATE, &DisplayChannel::handle_surface_create);
+ handler->set_handler(SPICE_MSG_DISPLAY_SURFACE_DESTROY, &DisplayChannel::handle_surface_destroy);
get_process_loop().add_trigger(_streams_trigger);
#ifdef USE_OGL
@@ -678,55 +669,43 @@ void DisplayChannel::set_draw_handlers()
{
DisplayHandler* handler = static_cast<DisplayHandler*>(get_message_handler());
- handler->set_handler(SPICE_MSG_DISPLAY_COPY_BITS, &DisplayChannel::handle_copy_bits,
- sizeof(SpiceMsgDisplayCopyBits));
-
- handler->set_handler(SPICE_MSG_DISPLAY_DRAW_FILL, &DisplayChannel::handle_draw_fill,
- sizeof(SpiceMsgDisplayDrawFill));
- handler->set_handler(SPICE_MSG_DISPLAY_DRAW_OPAQUE, &DisplayChannel::handle_draw_opaque,
- sizeof(SpiceMsgDisplayDrawOpaque));
- handler->set_handler(SPICE_MSG_DISPLAY_DRAW_COPY, &DisplayChannel::handle_draw_copy,
- sizeof(SpiceMsgDisplayDrawCopy));
- handler->set_handler(SPICE_MSG_DISPLAY_DRAW_BLEND, &DisplayChannel::handle_draw_blend,
- sizeof(SpiceMsgDisplayDrawBlend));
- handler->set_handler(SPICE_MSG_DISPLAY_DRAW_BLACKNESS, &DisplayChannel::handle_draw_blackness,
- sizeof(SpiceMsgDisplayDrawBlackness));
- handler->set_handler(SPICE_MSG_DISPLAY_DRAW_WHITENESS, &DisplayChannel::handle_draw_whiteness,
- sizeof(SpiceMsgDisplayDrawWhiteness));
- handler->set_handler(SPICE_MSG_DISPLAY_DRAW_INVERS, &DisplayChannel::handle_draw_invers,
- sizeof(SpiceMsgDisplayDrawInvers));
- handler->set_handler(SPICE_MSG_DISPLAY_DRAW_ROP3, &DisplayChannel::handle_draw_rop3,
- sizeof(SpiceMsgDisplayDrawRop3));
- handler->set_handler(SPICE_MSG_DISPLAY_DRAW_STROKE, &DisplayChannel::handle_draw_stroke,
- sizeof(SpiceMsgDisplayDrawStroke));
- handler->set_handler(SPICE_MSG_DISPLAY_DRAW_TEXT, &DisplayChannel::handle_draw_text,
- sizeof(SpiceMsgDisplayDrawText));
+ handler->set_handler(SPICE_MSG_DISPLAY_COPY_BITS, &DisplayChannel::handle_copy_bits);
+
+ handler->set_handler(SPICE_MSG_DISPLAY_DRAW_FILL, &DisplayChannel::handle_draw_fill);
+ handler->set_handler(SPICE_MSG_DISPLAY_DRAW_OPAQUE, &DisplayChannel::handle_draw_opaque);
+ handler->set_handler(SPICE_MSG_DISPLAY_DRAW_COPY, &DisplayChannel::handle_draw_copy);
+ handler->set_handler(SPICE_MSG_DISPLAY_DRAW_BLEND, &DisplayChannel::handle_draw_blend);
+ handler->set_handler(SPICE_MSG_DISPLAY_DRAW_BLACKNESS, &DisplayChannel::handle_draw_blackness);
+ handler->set_handler(SPICE_MSG_DISPLAY_DRAW_WHITENESS, &DisplayChannel::handle_draw_whiteness);
+ handler->set_handler(SPICE_MSG_DISPLAY_DRAW_INVERS, &DisplayChannel::handle_draw_invers);
+ handler->set_handler(SPICE_MSG_DISPLAY_DRAW_ROP3, &DisplayChannel::handle_draw_rop3);
+ handler->set_handler(SPICE_MSG_DISPLAY_DRAW_STROKE, &DisplayChannel::handle_draw_stroke);
+ handler->set_handler(SPICE_MSG_DISPLAY_DRAW_TEXT, &DisplayChannel::handle_draw_text);
handler->set_handler(SPICE_MSG_DISPLAY_DRAW_TRANSPARENT,
- &DisplayChannel::handle_draw_transparent, sizeof(SpiceMsgDisplayDrawTransparent));
+ &DisplayChannel::handle_draw_transparent);
handler->set_handler(SPICE_MSG_DISPLAY_DRAW_ALPHA_BLEND,
- &DisplayChannel::handle_draw_alpha_blend, sizeof(SpiceMsgDisplayDrawAlphaBlend));
- handler->set_handler(SPICE_MSG_DISPLAY_STREAM_DATA, &DisplayChannel::handle_stream_data,
- sizeof(SpiceMsgDisplayStreamData));
+ &DisplayChannel::handle_draw_alpha_blend);
+ handler->set_handler(SPICE_MSG_DISPLAY_STREAM_DATA, &DisplayChannel::handle_stream_data);
}
void DisplayChannel::clear_draw_handlers()
{
DisplayHandler* handler = static_cast<DisplayHandler*>(get_message_handler());
- handler->set_handler(SPICE_MSG_DISPLAY_COPY_BITS, NULL, 0);
- handler->set_handler(SPICE_MSG_DISPLAY_DRAW_FILL, NULL, 0);
- handler->set_handler(SPICE_MSG_DISPLAY_DRAW_OPAQUE, NULL, 0);
- handler->set_handler(SPICE_MSG_DISPLAY_DRAW_COPY, NULL, 0);
- handler->set_handler(SPICE_MSG_DISPLAY_DRAW_BLEND, NULL, 0);
- handler->set_handler(SPICE_MSG_DISPLAY_DRAW_BLACKNESS, NULL, 0);
- handler->set_handler(SPICE_MSG_DISPLAY_DRAW_WHITENESS, NULL, 0);
- handler->set_handler(SPICE_MSG_DISPLAY_DRAW_INVERS, NULL, 0);
- handler->set_handler(SPICE_MSG_DISPLAY_DRAW_ROP3, NULL, 0);
- handler->set_handler(SPICE_MSG_DISPLAY_DRAW_STROKE, NULL, 0);
- handler->set_handler(SPICE_MSG_DISPLAY_DRAW_TEXT, NULL, 0);
- handler->set_handler(SPICE_MSG_DISPLAY_DRAW_TRANSPARENT, NULL, 0);
- handler->set_handler(SPICE_MSG_DISPLAY_DRAW_ALPHA_BLEND, NULL, 0);
- handler->set_handler(SPICE_MSG_DISPLAY_STREAM_DATA, NULL, 0);
+ handler->set_handler(SPICE_MSG_DISPLAY_COPY_BITS, NULL);
+ handler->set_handler(SPICE_MSG_DISPLAY_DRAW_FILL, NULL);
+ handler->set_handler(SPICE_MSG_DISPLAY_DRAW_OPAQUE, NULL);
+ handler->set_handler(SPICE_MSG_DISPLAY_DRAW_COPY, NULL);
+ handler->set_handler(SPICE_MSG_DISPLAY_DRAW_BLEND, NULL);
+ handler->set_handler(SPICE_MSG_DISPLAY_DRAW_BLACKNESS, NULL);
+ handler->set_handler(SPICE_MSG_DISPLAY_DRAW_WHITENESS, NULL);
+ handler->set_handler(SPICE_MSG_DISPLAY_DRAW_INVERS, NULL);
+ handler->set_handler(SPICE_MSG_DISPLAY_DRAW_ROP3, NULL);
+ handler->set_handler(SPICE_MSG_DISPLAY_DRAW_STROKE, NULL);
+ handler->set_handler(SPICE_MSG_DISPLAY_DRAW_TEXT, NULL);
+ handler->set_handler(SPICE_MSG_DISPLAY_DRAW_TRANSPARENT, NULL);
+ handler->set_handler(SPICE_MSG_DISPLAY_DRAW_ALPHA_BLEND, NULL);
+ handler->set_handler(SPICE_MSG_DISPLAY_STREAM_DATA, NULL);
}
void DisplayChannel::copy_pixels(const QRegion& dest_region,
@@ -1289,20 +1268,13 @@ void DisplayChannel::handle_inval_all_palettes(RedPeer::InMessage* message)
}
void DisplayChannel::set_clip_rects(const SpiceClip& clip, uint32_t& num_clip_rects,
- SpiceRect*& clip_rects, unsigned long addr_offset,
- uint8_t *min, uint8_t *max)
+ SpiceRect*& clip_rects)
{
switch (clip.type) {
case SPICE_CLIP_TYPE_RECTS: {
- uint32_t* n = (uint32_t*)SPICE_GET_ADDRESS(clip.data + addr_offset);
- if (n < (uint32_t*)min || n + 1 > (uint32_t*)max) {
- THROW("access violation");
- }
+ uint32_t* n = (uint32_t*)SPICE_GET_ADDRESS(clip.data);
num_clip_rects = *n;
clip_rects = (SpiceRect *)(n + 1);
- if (clip_rects + num_clip_rects > (SpiceRect*)max) {
- THROW("access violation");
- }
break;
}
case SPICE_CLIP_TYPE_NONE:
@@ -1330,9 +1302,7 @@ void DisplayChannel::handle_stream_create(RedPeer::InMessage* message)
uint32_t num_clip_rects;
SpiceRect* clip_rects;
- set_clip_rects(stream_create->clip, num_clip_rects, clip_rects,
- (unsigned long)message->data(), (uint8_t*)(stream_create + 1),
- message->data() + message->size());
+ set_clip_rects(stream_create->clip, num_clip_rects, clip_rects);
_streams[stream_create->id] = new VideoStream(get_client(), *surfaces_mngr.get_canvas(surface_id),
*this, stream_create->codec_type,
!!(stream_create->flags & SPICE_STREAM_FLAGS_TOP_DOWN),
@@ -1379,9 +1349,7 @@ void DisplayChannel::handle_stream_clip(RedPeer::InMessage* message)
if (message->size() < sizeof(SpiceMsgDisplayStreamClip)) {
THROW("access violation");
}
- set_clip_rects(clip_data->clip, num_clip_rects, clip_rects,
- (unsigned long)message->data(), (uint8_t*)(clip_data + 1),
- message->data() + message->size());
+ set_clip_rects(clip_data->clip, num_clip_rects, clip_rects);
Lock lock(_streams_lock);
stream->set_clip(clip_data->clip.type, num_clip_rects, clip_rects);
}
diff --git a/client/display_channel.h b/client/display_channel.h
index 52b0cef..c56adf6 100644
--- a/client/display_channel.h
+++ b/client/display_channel.h
@@ -189,8 +189,7 @@ private:
void activate_streams_timer();
void stream_update_request(uint32_t update_time);
- static void set_clip_rects(const SpiceClip& clip, uint32_t& num_clip_rects, SpiceRect*& clip_rects,
- unsigned long addr_offset, uint8_t *min, uint8_t *max);
+ static void set_clip_rects(const SpiceClip& clip, uint32_t& num_clip_rects, SpiceRect*& clip_rects);
private:
DisplaySurfacesManger surfaces_mngr;
PixmapCache& _pixmap_cache;
diff --git a/client/inputs_channel.cpp b/client/inputs_channel.cpp
index 46fc015..4e99563 100644
--- a/client/inputs_channel.cpp
+++ b/client/inputs_channel.cpp
@@ -158,10 +158,10 @@ RedPeer::OutMessage& PositionMessage::peer_message()
return *this;
}
-class InputsMessHandler: public MessageHandlerImp<InputsChannel, SPICE_MSG_END_INPUTS> {
+class InputsMessHandler: public MessageHandlerImp<InputsChannel, SPICE_CHANNEL_INPUTS> {
public:
InputsMessHandler(InputsChannel& channel)
- : MessageHandlerImp<InputsChannel, SPICE_MSG_END_INPUTS>(channel) {}
+ : MessageHandlerImp<InputsChannel, SPICE_CHANNEL_INPUTS>(channel) {}
};
InputsChannel::InputsChannel(RedClient& client, uint32_t id)
@@ -177,19 +177,16 @@ InputsChannel::InputsChannel(RedClient& client, uint32_t id)
, _active_modifiers_event (false)
{
InputsMessHandler* handler = static_cast<InputsMessHandler*>(get_message_handler());
- handler->set_handler(SPICE_MSG_MIGRATE, &InputsChannel::handle_migrate, 0);
- handler->set_handler(SPICE_MSG_SET_ACK, &InputsChannel::handle_set_ack, sizeof(SpiceMsgSetAck));
- handler->set_handler(SPICE_MSG_PING, &InputsChannel::handle_ping, sizeof(SpiceMsgPing));
- handler->set_handler(SPICE_MSG_WAIT_FOR_CHANNELS, &InputsChannel::handle_wait_for_channels,
- sizeof(SpiceMsgWaitForChannels));
- handler->set_handler(SPICE_MSG_DISCONNECTING, &InputsChannel::handle_disconnect,
- sizeof(SpiceMsgDisconnect));
- handler->set_handler(SPICE_MSG_NOTIFY, &InputsChannel::handle_notify, sizeof(SpiceMsgNotify));
-
- handler->set_handler(SPICE_MSG_INPUTS_INIT, &InputsChannel::handle_init, sizeof(SpiceMsgInputsInit));
- handler->set_handler(SPICE_MSG_INPUTS_KEY_MODIFIERS, &InputsChannel::handle_modifaiers,
- sizeof(SpiceMsgInputsKeyModifiers));
- handler->set_handler(SPICE_MSG_INPUTS_MOUSE_MOTION_ACK, &InputsChannel::handle_motion_ack, 0);
+ handler->set_handler(SPICE_MSG_MIGRATE, &InputsChannel::handle_migrate);
+ handler->set_handler(SPICE_MSG_SET_ACK, &InputsChannel::handle_set_ack);
+ handler->set_handler(SPICE_MSG_PING, &InputsChannel::handle_ping);
+ handler->set_handler(SPICE_MSG_WAIT_FOR_CHANNELS, &InputsChannel::handle_wait_for_channels);
+ handler->set_handler(SPICE_MSG_DISCONNECTING, &InputsChannel::handle_disconnect);
+ handler->set_handler(SPICE_MSG_NOTIFY, &InputsChannel::handle_notify);
+
+ handler->set_handler(SPICE_MSG_INPUTS_INIT, &InputsChannel::handle_init);
+ handler->set_handler(SPICE_MSG_INPUTS_KEY_MODIFIERS, &InputsChannel::handle_modifaiers);
+ handler->set_handler(SPICE_MSG_INPUTS_MOUSE_MOTION_ACK, &InputsChannel::handle_motion_ack);
}
InputsChannel::~InputsChannel()
diff --git a/client/playback_channel.cpp b/client/playback_channel.cpp
index 3e8bb46..9ac6ed6 100644
--- a/client/playback_channel.cpp
+++ b/client/playback_channel.cpp
@@ -137,10 +137,10 @@ static void end_wave()
#endif
-class PlaybackHandler: public MessageHandlerImp<PlaybackChannel, SPICE_MSG_END_PLAYBACK> {
+class PlaybackHandler: public MessageHandlerImp<PlaybackChannel, SPICE_CHANNEL_PLAYBACK> {
public:
PlaybackHandler(PlaybackChannel& channel)
- : MessageHandlerImp<PlaybackChannel, SPICE_MSG_END_PLAYBACK>(channel) {}
+ : MessageHandlerImp<PlaybackChannel, SPICE_CHANNEL_PLAYBACK>(channel) {}
};
PlaybackChannel::PlaybackChannel(RedClient& client, uint32_t id)
@@ -157,17 +157,14 @@ PlaybackChannel::PlaybackChannel(RedClient& client, uint32_t id)
#endif
PlaybackHandler* handler = static_cast<PlaybackHandler*>(get_message_handler());
- handler->set_handler(SPICE_MSG_MIGRATE, &PlaybackChannel::handle_migrate, 0);
- handler->set_handler(SPICE_MSG_SET_ACK, &PlaybackChannel::handle_set_ack, sizeof(SpiceMsgSetAck));
- handler->set_handler(SPICE_MSG_PING, &PlaybackChannel::handle_ping, sizeof(SpiceMsgPing));
- handler->set_handler(SPICE_MSG_WAIT_FOR_CHANNELS, &PlaybackChannel::handle_wait_for_channels,
- sizeof(SpiceMsgWaitForChannels));
- handler->set_handler(SPICE_MSG_DISCONNECTING, &PlaybackChannel::handle_disconnect,
- sizeof(SpiceMsgDisconnect));
- handler->set_handler(SPICE_MSG_NOTIFY, &PlaybackChannel::handle_notify, sizeof(SpiceMsgNotify));
+ handler->set_handler(SPICE_MSG_MIGRATE, &PlaybackChannel::handle_migrate);
+ handler->set_handler(SPICE_MSG_SET_ACK, &PlaybackChannel::handle_set_ack);
+ handler->set_handler(SPICE_MSG_PING, &PlaybackChannel::handle_ping);
+ handler->set_handler(SPICE_MSG_WAIT_FOR_CHANNELS, &PlaybackChannel::handle_wait_for_channels);
+ handler->set_handler(SPICE_MSG_DISCONNECTING, &PlaybackChannel::handle_disconnect);
+ handler->set_handler(SPICE_MSG_NOTIFY, &PlaybackChannel::handle_notify);
- handler->set_handler(SPICE_MSG_PLAYBACK_MODE, &PlaybackChannel::handle_mode,
- sizeof(SpiceMsgPlaybackMode));
+ handler->set_handler(SPICE_MSG_PLAYBACK_MODE, &PlaybackChannel::handle_mode);
set_capability(SPICE_PLAYBACK_CAP_CELT_0_5_1);
}
@@ -195,9 +192,9 @@ void PlaybackChannel::set_data_handler()
PlaybackHandler* handler = static_cast<PlaybackHandler*>(get_message_handler());
if (_mode == SPICE_AUDIO_DATA_MODE_RAW) {
- handler->set_handler(SPICE_MSG_PLAYBACK_DATA, &PlaybackChannel::handle_raw_data, 0);
+ handler->set_handler(SPICE_MSG_PLAYBACK_DATA, &PlaybackChannel::handle_raw_data);
} else if (_mode == SPICE_AUDIO_DATA_MODE_CELT_0_5_1) {
- handler->set_handler(SPICE_MSG_PLAYBACK_DATA, &PlaybackChannel::handle_celt_data, 0);
+ handler->set_handler(SPICE_MSG_PLAYBACK_DATA, &PlaybackChannel::handle_celt_data);
} else {
THROW("invalid mode");
}
@@ -218,8 +215,7 @@ void PlaybackChannel::handle_mode(RedPeer::InMessage* message)
}
PlaybackHandler* handler = static_cast<PlaybackHandler*>(get_message_handler());
- handler->set_handler(SPICE_MSG_PLAYBACK_START, &PlaybackChannel::handle_start,
- sizeof(SpiceMsgPlaybackStart));
+ handler->set_handler(SPICE_MSG_PLAYBACK_START, &PlaybackChannel::handle_start);
}
void PlaybackChannel::null_handler(RedPeer::InMessage* message)
@@ -230,10 +226,10 @@ void PlaybackChannel::disable()
{
PlaybackHandler* handler = static_cast<PlaybackHandler*>(get_message_handler());
- handler->set_handler(SPICE_MSG_PLAYBACK_START, &PlaybackChannel::null_handler, 0);
- handler->set_handler(SPICE_MSG_PLAYBACK_STOP, &PlaybackChannel::null_handler, 0);
- handler->set_handler(SPICE_MSG_PLAYBACK_MODE, &PlaybackChannel::null_handler, 0);
- handler->set_handler(SPICE_MSG_PLAYBACK_DATA, &PlaybackChannel::null_handler, 0);
+ handler->set_handler(SPICE_MSG_PLAYBACK_START, &PlaybackChannel::null_handler);
+ handler->set_handler(SPICE_MSG_PLAYBACK_STOP, &PlaybackChannel::null_handler);
+ handler->set_handler(SPICE_MSG_PLAYBACK_MODE, &PlaybackChannel::null_handler);
+ handler->set_handler(SPICE_MSG_PLAYBACK_DATA, &PlaybackChannel::null_handler);
}
void PlaybackChannel::handle_start(RedPeer::InMessage* message)
@@ -241,8 +237,8 @@ void PlaybackChannel::handle_start(RedPeer::InMessage* message)
PlaybackHandler* handler = static_cast<PlaybackHandler*>(get_message_handler());
SpiceMsgPlaybackStart* start = (SpiceMsgPlaybackStart*)message->data();
- handler->set_handler(SPICE_MSG_PLAYBACK_START, NULL, 0);
- handler->set_handler(SPICE_MSG_PLAYBACK_STOP, &PlaybackChannel::handle_stop, 0);
+ handler->set_handler(SPICE_MSG_PLAYBACK_START, NULL);
+ handler->set_handler(SPICE_MSG_PLAYBACK_STOP, &PlaybackChannel::handle_stop);
#ifdef WAVE_CAPTURE
start_wave();
@@ -285,10 +281,9 @@ void PlaybackChannel::handle_stop(RedPeer::InMessage* message)
{
PlaybackHandler* handler = static_cast<PlaybackHandler*>(get_message_handler());
- handler->set_handler(SPICE_MSG_PLAYBACK_STOP, NULL, 0);
- handler->set_handler(SPICE_MSG_PLAYBACK_DATA, NULL, 0);
- handler->set_handler(SPICE_MSG_PLAYBACK_START, &PlaybackChannel::handle_start,
- sizeof(SpiceMsgPlaybackStart));
+ handler->set_handler(SPICE_MSG_PLAYBACK_STOP, NULL);
+ handler->set_handler(SPICE_MSG_PLAYBACK_DATA, NULL);
+ handler->set_handler(SPICE_MSG_PLAYBACK_START, &PlaybackChannel::handle_start);
#ifdef WAVE_CAPTURE
end_wave();
diff --git a/client/record_channel.cpp b/client/record_channel.cpp
index 893cc63..a48df60 100644
--- a/client/record_channel.cpp
+++ b/client/record_channel.cpp
@@ -59,10 +59,10 @@ void RecordSamplesMessage::release()
int RecordChannel::data_mode = SPICE_AUDIO_DATA_MODE_CELT_0_5_1;
-class RecordHandler: public MessageHandlerImp<RecordChannel, SPICE_MSGC_END_RECORD> {
+class RecordHandler: public MessageHandlerImp<RecordChannel, SPICE_CHANNEL_RECORD> {
public:
RecordHandler(RecordChannel& channel)
- : MessageHandlerImp<RecordChannel, SPICE_MSGC_END_RECORD>(channel) {}
+ : MessageHandlerImp<RecordChannel, SPICE_CHANNEL_RECORD>(channel) {}
};
RecordChannel::RecordChannel(RedClient& client, uint32_t id)
@@ -78,16 +78,14 @@ RecordChannel::RecordChannel(RedClient& client, uint32_t id)
RecordHandler* handler = static_cast<RecordHandler*>(get_message_handler());
- handler->set_handler(SPICE_MSG_MIGRATE, &RecordChannel::handle_migrate, 0);
- handler->set_handler(SPICE_MSG_SET_ACK, &RecordChannel::handle_set_ack, sizeof(SpiceMsgSetAck));
- handler->set_handler(SPICE_MSG_PING, &RecordChannel::handle_ping, sizeof(SpiceMsgPing));
- handler->set_handler(SPICE_MSG_WAIT_FOR_CHANNELS, &RecordChannel::handle_wait_for_channels,
- sizeof(SpiceMsgWaitForChannels));
- handler->set_handler(SPICE_MSG_DISCONNECTING, &RecordChannel::handle_disconnect,
- sizeof(SpiceMsgDisconnect));
- handler->set_handler(SPICE_MSG_NOTIFY, &RecordChannel::handle_notify, sizeof(SpiceMsgNotify));
+ handler->set_handler(SPICE_MSG_MIGRATE, &RecordChannel::handle_migrate);
+ handler->set_handler(SPICE_MSG_SET_ACK, &RecordChannel::handle_set_ack);
+ handler->set_handler(SPICE_MSG_PING, &RecordChannel::handle_ping);
+ handler->set_handler(SPICE_MSG_WAIT_FOR_CHANNELS, &RecordChannel::handle_wait_for_channels);
+ handler->set_handler(SPICE_MSG_DISCONNECTING, &RecordChannel::handle_disconnect);
+ handler->set_handler(SPICE_MSG_NOTIFY, &RecordChannel::handle_notify);
- handler->set_handler(SPICE_MSG_RECORD_START, &RecordChannel::handle_start, sizeof(SpiceMsgRecordStart));
+ handler->set_handler(SPICE_MSG_RECORD_START, &RecordChannel::handle_start);
set_capability(SPICE_RECORD_CAP_CELT_0_5_1);
}
@@ -138,8 +136,8 @@ void RecordChannel::handle_start(RedPeer::InMessage* message)
RecordHandler* handler = static_cast<RecordHandler*>(get_message_handler());
SpiceMsgRecordStart* start = (SpiceMsgRecordStart*)message->data();
- handler->set_handler(SPICE_MSG_RECORD_START, NULL, 0);
- handler->set_handler(SPICE_MSG_RECORD_STOP, &RecordChannel::handle_stop, 0);
+ handler->set_handler(SPICE_MSG_RECORD_START, NULL);
+ handler->set_handler(SPICE_MSG_RECORD_STOP, &RecordChannel::handle_stop);
ASSERT(!_wave_recorder && !_celt_mode && !_celt_encoder);
// for now support only one setting
@@ -176,8 +174,8 @@ void RecordChannel::handle_start(RedPeer::InMessage* message)
void RecordChannel::handle_stop(RedPeer::InMessage* message)
{
RecordHandler* handler = static_cast<RecordHandler*>(get_message_handler());
- handler->set_handler(SPICE_MSG_RECORD_START, &RecordChannel::handle_start, sizeof(SpiceMsgRecordStart));
- handler->set_handler(SPICE_MSG_RECORD_STOP, NULL, 0);
+ handler->set_handler(SPICE_MSG_RECORD_START, &RecordChannel::handle_start);
+ handler->set_handler(SPICE_MSG_RECORD_STOP, NULL);
if (!_wave_recorder) {
return;
}
diff --git a/client/red_channel.h b/client/red_channel.h
index d80a331..8d6b62f 100644
--- a/client/red_channel.h
+++ b/client/red_channel.h
@@ -24,6 +24,7 @@
#include "red_peer.h"
#include "platform.h"
#include "process_loop.h"
+#include "demarshallers.h"
enum {
PASSIVE_STATE,
@@ -230,67 +231,83 @@ public:
};
-template <class HandlerClass, unsigned int end_message>
+template <class HandlerClass, unsigned int channel_id>
class MessageHandlerImp: public RedChannel::MessageHandler {
public:
MessageHandlerImp(HandlerClass& obj);
- virtual ~MessageHandlerImp() {}
+ ~MessageHandlerImp() { delete [] _handlers; };
virtual void handle_message(RedPeer::CompundInMessage& message);
typedef void (HandlerClass::*Handler)(RedPeer::InMessage* message);
- void set_handler(unsigned int id, Handler handler, size_t mess_size);
+ void set_handler(unsigned int id, Handler handler);
private:
HandlerClass& _obj;
- struct HandlerInfo {
- Handler handler;
- size_t mess_size;
- };
-
- HandlerInfo _handlers[end_message];
+ unsigned int _max_messages;
+ spice_parse_channel_func_t _parser;
+ Handler *_handlers;
};
-template <class HandlerClass, unsigned int end_message>
-MessageHandlerImp<HandlerClass, end_message>::MessageHandlerImp(HandlerClass& obj)
+template <class HandlerClass, unsigned int channel_id>
+MessageHandlerImp<HandlerClass, channel_id>::MessageHandlerImp(HandlerClass& obj)
: _obj (obj)
{
- memset(_handlers, 0, sizeof(_handlers));
+ _parser = spice_get_server_channel_parser(channel_id, &_max_messages);
+ _handlers = new Handler[_max_messages + 1];
+ memset(_handlers, 0, sizeof(Handler) * (_max_messages + 1));
}
-template <class HandlerClass, unsigned int end_message>
-void MessageHandlerImp<HandlerClass, end_message>::handle_message(RedPeer::CompundInMessage&
- message)
+template <class HandlerClass, unsigned int channel_id>
+void MessageHandlerImp<HandlerClass, channel_id>::handle_message(RedPeer::CompundInMessage&
+ message)
{
- if (message.type() >= end_message || !_handlers[message.type()].handler) {
- THROW("bad message type %d", message.type());
- }
- if (message.size() < _handlers[message.type()].mess_size) {
- THROW("bad message size, type %d size %d expected %d",
- message.type(),
- message.size(),
- _handlers[message.type()].mess_size);
- }
+ uint8_t *msg;
+ uint8_t *parsed;
+ uint16_t type;
+ uint32_t size;
+ size_t parsed_size;
+
if (message.sub_list()) {
SpiceSubMessageList *sub_list;
sub_list = (SpiceSubMessageList *)(message.data() + message.sub_list());
for (int i = 0; i < sub_list->size; i++) {
SpicedSubMessage *sub = (SpicedSubMessage *)(message.data() + sub_list->sub_messages[i]);
- //todo: test size
- RedPeer::InMessage sub_message(sub->type, sub->size, (uint8_t *)(sub + 1));
- (_obj.*_handlers[sub_message.type()].handler)(&sub_message);
+ msg = (uint8_t *)(sub + 1);
+ type = sub->type;
+ size = sub->size;
+ parsed = _parser(msg, msg + size, type, _obj.get_peer_minor(), &parsed_size);
+
+ if (parsed == NULL) {
+ THROW("failed to parse message type %d", type);
+ }
+
+ RedPeer::InMessage sub_message(type, parsed_size, parsed);
+ (_obj.*_handlers[type])(&sub_message);
+
+ free(parsed);
}
}
- (_obj.*_handlers[message.type()].handler)(&message);
+
+ msg = message.data();
+ type = message.type();
+ size = message.size();
+ parsed = _parser(msg, msg + size, type, _obj.get_peer_minor(), &parsed_size);
+ RedPeer::InMessage main_message(type, parsed_size, parsed);
+
+ if (parsed == NULL) {
+ THROW("failed to parse message channel %d type %d", channel_id, type);
+ }
+
+ (_obj.*_handlers[type])(&main_message);
+ free(parsed);
}
-template <class HandlerClass, unsigned int end_message>
-void MessageHandlerImp<HandlerClass, end_message>::set_handler(unsigned int id, Handler handler,
- size_t mess_size)
+template <class HandlerClass, unsigned int channel_id>
+void MessageHandlerImp<HandlerClass, channel_id>::set_handler(unsigned int id, Handler handler)
{
- if (id >= end_message) {
+ if (id > _max_messages) {
THROW("bad handler id");
}
- _handlers[id].handler = handler;
- _handlers[id].mess_size = mess_size;
+ _handlers[id] = handler;
}
#endif
diff --git a/client/red_client.cpp b/client/red_client.cpp
index 8424a94..8778eeb 100644
--- a/client/red_client.cpp
+++ b/client/red_client.cpp
@@ -293,9 +293,9 @@ void AgentTimer::response(AbstractProcessLoop& events_loop)
THROW_ERR(SPICEC_ERROR_CODE_AGENT_TIMEOUT, "vdagent timeout");
}
-class MainChannelLoop: public MessageHandlerImp<RedClient, SPICE_MSG_END_MAIN> {
+class MainChannelLoop: public MessageHandlerImp<RedClient, SPICE_CHANNEL_MAIN> {
public:
- MainChannelLoop(RedClient& client): MessageHandlerImp<RedClient, SPICE_MSG_END_MAIN>(client) {}
+ MainChannelLoop(RedClient& client): MessageHandlerImp<RedClient, SPICE_CHANNEL_MAIN>(client) {}
};
RedClient::RedClient(Application& application)
@@ -320,35 +320,26 @@ RedClient::RedClient(Application& application)
{
MainChannelLoop* message_loop = static_cast<MainChannelLoop*>(get_message_handler());
- message_loop->set_handler(SPICE_MSG_MIGRATE, &RedClient::handle_migrate, 0);
- message_loop->set_handler(SPICE_MSG_SET_ACK, &RedClient::handle_set_ack, sizeof(SpiceMsgSetAck));
- message_loop->set_handler(SPICE_MSG_PING, &RedClient::handle_ping, sizeof(SpiceMsgPing));
- message_loop->set_handler(SPICE_MSG_WAIT_FOR_CHANNELS, &RedClient::handle_wait_for_channels,
- sizeof(SpiceMsgWaitForChannels));
- message_loop->set_handler(SPICE_MSG_DISCONNECTING, &RedClient::handle_disconnect,
- sizeof(SpiceMsgDisconnect));
- message_loop->set_handler(SPICE_MSG_NOTIFY, &RedClient::handle_notify, sizeof(SpiceMsgNotify));
-
- message_loop->set_handler(SPICE_MSG_MAIN_MIGRATE_BEGIN, &RedClient::handle_migrate_begin,
- sizeof(SpiceMsgMainMigrationBegin));
- message_loop->set_handler(SPICE_MSG_MAIN_MIGRATE_CANCEL, &RedClient::handle_migrate_cancel, 0);
+ message_loop->set_handler(SPICE_MSG_MIGRATE, &RedClient::handle_migrate);
+ message_loop->set_handler(SPICE_MSG_SET_ACK, &RedClient::handle_set_ack);
+ message_loop->set_handler(SPICE_MSG_PING, &RedClient::handle_ping);
+ message_loop->set_handler(SPICE_MSG_WAIT_FOR_CHANNELS, &RedClient::handle_wait_for_channels);
+ message_loop->set_handler(SPICE_MSG_DISCONNECTING, &RedClient::handle_disconnect);
+ message_loop->set_handler(SPICE_MSG_NOTIFY, &RedClient::handle_notify);
+
+ message_loop->set_handler(SPICE_MSG_MAIN_MIGRATE_BEGIN, &RedClient::handle_migrate_begin);
+ message_loop->set_handler(SPICE_MSG_MAIN_MIGRATE_CANCEL, &RedClient::handle_migrate_cancel);
message_loop->set_handler(SPICE_MSG_MAIN_MIGRATE_SWITCH_HOST,
- &RedClient::handle_migrate_switch_host,
- sizeof(SpiceMsgMainMigrationSwitchHost));
- message_loop->set_handler(SPICE_MSG_MAIN_INIT, &RedClient::handle_init, sizeof(SpiceMsgMainInit));
- message_loop->set_handler(SPICE_MSG_MAIN_CHANNELS_LIST, &RedClient::handle_channels,
- sizeof(SpiceMsgChannels));
- message_loop->set_handler(SPICE_MSG_MAIN_MOUSE_MODE, &RedClient::handle_mouse_mode,
- sizeof(SpiceMsgMainMouseMode));
- message_loop->set_handler(SPICE_MSG_MAIN_MULTI_MEDIA_TIME, &RedClient::handle_mm_time,
- sizeof(SpiceMsgMainMultiMediaTime));
-
- message_loop->set_handler(SPICE_MSG_MAIN_AGENT_CONNECTED, &RedClient::handle_agent_connected, 0);
- message_loop->set_handler(SPICE_MSG_MAIN_AGENT_DISCONNECTED, &RedClient::handle_agent_disconnected,
- sizeof(SpiceMsgMainAgentDisconnect));
- message_loop->set_handler(SPICE_MSG_MAIN_AGENT_DATA, &RedClient::handle_agent_data, 0);
- message_loop->set_handler(SPICE_MSG_MAIN_AGENT_TOKEN, &RedClient::handle_agent_tokens,
- sizeof(SpiceMsgMainAgentTokens));
+ &RedClient::handle_migrate_switch_host);
+ message_loop->set_handler(SPICE_MSG_MAIN_INIT, &RedClient::handle_init);
+ message_loop->set_handler(SPICE_MSG_MAIN_CHANNELS_LIST, &RedClient::handle_channels);
+ message_loop->set_handler(SPICE_MSG_MAIN_MOUSE_MODE, &RedClient::handle_mouse_mode);
+ message_loop->set_handler(SPICE_MSG_MAIN_MULTI_MEDIA_TIME, &RedClient::handle_mm_time);
+
+ message_loop->set_handler(SPICE_MSG_MAIN_AGENT_CONNECTED, &RedClient::handle_agent_connected);
+ message_loop->set_handler(SPICE_MSG_MAIN_AGENT_DISCONNECTED, &RedClient::handle_agent_disconnected);
+ message_loop->set_handler(SPICE_MSG_MAIN_AGENT_DATA, &RedClient::handle_agent_data);
+ message_loop->set_handler(SPICE_MSG_MAIN_AGENT_TOKEN, &RedClient::handle_agent_tokens);
start();
}
diff --git a/client/tunnel_channel.cpp b/client/tunnel_channel.cpp
index 1b7d7cb..cecd9ba 100644
--- a/client/tunnel_channel.cpp
+++ b/client/tunnel_channel.cpp
@@ -219,10 +219,10 @@ TunnelChannel::TunnelSocket::TunnelSocket(uint16_t id, TunnelService& dst_servic
{
}
-class TunnelHandler: public MessageHandlerImp<TunnelChannel, SPICE_MSG_END_TUNNEL> {
+class TunnelHandler: public MessageHandlerImp<TunnelChannel, SPICE_CHANNEL_TUNNEL> {
public:
TunnelHandler(TunnelChannel& channel)
- : MessageHandlerImp<TunnelChannel, SPICE_MSG_END_TUNNEL>(channel) {}
+ : MessageHandlerImp<TunnelChannel, SPICE_CHANNEL_TUNNEL>(channel) {}
};
TunnelChannel::TunnelChannel(RedClient& client, uint32_t id)
@@ -236,29 +236,27 @@ TunnelChannel::TunnelChannel(RedClient& client, uint32_t id)
{
TunnelHandler* handler = static_cast<TunnelHandler*>(get_message_handler());
- handler->set_handler(SPICE_MSG_MIGRATE, &TunnelChannel::handle_migrate, 0);
- handler->set_handler(SPICE_MSG_SET_ACK, &TunnelChannel::handle_set_ack, sizeof(SpiceMsgSetAck));
- handler->set_handler(SPICE_MSG_PING, &TunnelChannel::handle_ping, sizeof(SpiceMsgPing));
- handler->set_handler(SPICE_MSG_WAIT_FOR_CHANNELS, &TunnelChannel::handle_wait_for_channels,
- sizeof(SpiceMsgWaitForChannels));
+ handler->set_handler(SPICE_MSG_MIGRATE, &TunnelChannel::handle_migrate);
+ handler->set_handler(SPICE_MSG_SET_ACK, &TunnelChannel::handle_set_ack);
+ handler->set_handler(SPICE_MSG_PING, &TunnelChannel::handle_ping);
+ handler->set_handler(SPICE_MSG_WAIT_FOR_CHANNELS, &TunnelChannel::handle_wait_for_channels);
handler->set_handler(SPICE_MSG_TUNNEL_INIT,
- &TunnelChannel::handle_init, sizeof(SpiceMsgTunnelInit));
+ &TunnelChannel::handle_init);
handler->set_handler(SPICE_MSG_TUNNEL_SERVICE_IP_MAP,
- &TunnelChannel::handle_service_ip_map, sizeof(SpiceMsgTunnelServiceIpMap));
+ &TunnelChannel::handle_service_ip_map);
handler->set_handler(SPICE_MSG_TUNNEL_SOCKET_OPEN,
- &TunnelChannel::handle_socket_open, sizeof(SpiceMsgTunnelSocketOpen));
+ &TunnelChannel::handle_socket_open);
handler->set_handler(SPICE_MSG_TUNNEL_SOCKET_CLOSE,
- &TunnelChannel::handle_socket_close, sizeof(SpiceMsgTunnelSocketClose));
+ &TunnelChannel::handle_socket_close);
handler->set_handler(SPICE_MSG_TUNNEL_SOCKET_FIN,
- &TunnelChannel::handle_socket_fin, sizeof(SpiceMsgTunnelSocketFin));
+ &TunnelChannel::handle_socket_fin);
handler->set_handler(SPICE_MSG_TUNNEL_SOCKET_TOKEN,
- &TunnelChannel::handle_socket_token, sizeof(SpiceMsgTunnelSocketTokens));
+ &TunnelChannel::handle_socket_token);
handler->set_handler(SPICE_MSG_TUNNEL_SOCKET_CLOSED_ACK,
- &TunnelChannel::handle_socket_closed_ack,
- sizeof(SpiceMsgTunnelSocketClosedAck));
+ &TunnelChannel::handle_socket_closed_ack);
handler->set_handler(SPICE_MSG_TUNNEL_SOCKET_DATA,
- &TunnelChannel::handle_socket_data, sizeof(SpiceMsgTunnelSocketData));
+ &TunnelChannel::handle_socket_data);
}
TunnelChannel::~TunnelChannel()
diff --git a/client/windows/redc.vcproj b/client/windows/redc.vcproj
index c0ba905..f980c21 100644
--- a/client/windows/redc.vcproj
+++ b/client/windows/redc.vcproj
@@ -43,7 +43,7 @@
Name="VCCLCompilerTool"
Optimization="0"
AdditionalIncludeDirectories=".;..;..\..\common;..\..\..\spice-protocol;..\..\common\win;"..\..\common\win\my_getopt-1.5";"$(SPICE_LIBS)\include";"$(SPICE_LIBS)\include\pixman-1";"$(SPICE_LIBS)\include\CEGUI-0.6.2""
- PreprocessorDefinitions="WIN32;_DEBUG;_WINDOWS;SW_CANVAS_ACCESS_TEST;SW_CANVAS_CACHE;RED_DEBUG;SW_CANVAS_NO_CHUNKS;_WIN32_WINNT=0x0500;LOG4CPLUS_STATIC;USE_GLZ;PTW32_STATIC_LIB;CEGUI_STATIC"
+ PreprocessorDefinitions="WIN32;_DEBUG;_WINDOWS;SW_CANVAS_CACHE;RED_DEBUG;SW_CANVAS_NO_CHUNKS;_WIN32_WINNT=0x0500;LOG4CPLUS_STATIC;USE_GLZ;PTW32_STATIC_LIB;CEGUI_STATIC"
MinimalRebuild="false"
BasicRuntimeChecks="3"
RuntimeLibrary="1"
@@ -125,7 +125,7 @@
<Tool
Name="VCCLCompilerTool"
AdditionalIncludeDirectories=".;..;..\..\..\spice-protocol;..\..\common;..\..\common\win;"..\..\common\win\my_getopt-1.5";"$(SPICE_LIBS)\include";"$(SPICE_LIBS)\include\pixman-1";"$(SPICE_LIBS)\include\CEGUI-0.6.2""
- PreprocessorDefinitions="WIN32;_WINDOWS;SW_CANVAS_ACCESS_TEST;SW_CANVAS_CACHE;SW_CANVAS_NO_CHUNKS;_WIN32_WINNT=0x0500;LOG4CPLUS_STATIC;USE_GLZ;PTW32_STATIC_LIB;CEGUI_STATIC"
+ PreprocessorDefinitions="WIN32;_WINDOWS;SW_CANVAS_CACHE;SW_CANVAS_NO_CHUNKS;_WIN32_WINNT=0x0500;LOG4CPLUS_STATIC;USE_GLZ;PTW32_STATIC_LIB;CEGUI_STATIC"
RuntimeLibrary="0"
UsePrecompiledHeader="0"
WarningLevel="3"
diff --git a/client/x11/Makefile.am b/client/x11/Makefile.am
index 26140f4..82a08dd 100644
--- a/client/x11/Makefile.am
+++ b/client/x11/Makefile.am
@@ -6,7 +6,6 @@ CLIENT_DIR=$(top_srcdir)/client
SUBDIRS = images
INCLUDES = \
- -DSW_CANVAS_ACCESS_TEST \
-DSW_CANVAS_CACHE \
-DSW_CANVAS_NO_CHUNKS \
-DUSE_GLZ \
@@ -38,6 +37,8 @@ RED_COMMON_SRCS = \
$(CLIENT_DIR)/audio_channels.h \
$(CLIENT_DIR)/audio_devices.h \
$(CLIENT_DIR)/cache.hpp \
+ $(CLIENT_DIR)/demarshallers.h \
+ $(CLIENT_DIR)/generated_demarshallers.cpp \
$(CLIENT_DIR)/sw_canvas.cpp \
$(CLIENT_DIR)/canvas.cpp \
$(CLIENT_DIR)/canvas.h \
diff --git a/common/canvas_base.c b/common/canvas_base.c
index aac472c..26bc52c 100644
--- a/common/canvas_base.c
+++ b/common/canvas_base.c
@@ -43,16 +43,6 @@
}
#endif
-#ifdef SW_CANVAS_ACCESS_TEST
-#define access_test(cancas, ptr, size) \
- if ((unsigned long)(ptr) < (cancas)->base || \
- (unsigned long)(ptr) + (size) > (cancas)->max) { \
- CANVAS_ERROR("access violation 0x%lx %lu", (unsigned long)ptr, (unsigned long)(size)); \
- }
-#else
-#define access_test(cancas, base, size)
-#endif
-
#ifndef ASSERT
#define ASSERT(x) if (!(x)) { \
printf("%s: ASSERT %s failed\n", __FUNCTION__, #x); \
@@ -175,10 +165,6 @@ typedef struct CanvasBase {
uint32_t color_shift;
uint32_t color_mask;
QuicData quic_data;
-#ifdef SW_CANVAS_ACCESS_TEST
- unsigned long base;
- unsigned long max;
-#endif
uint32_t format;
int width;
@@ -630,7 +616,6 @@ static pixman_image_t *canvas_bitmap_to_surface(CanvasBase *canvas, SpiceBitmap*
src = (uint8_t *)SPICE_GET_ADDRESS(bitmap->data);
src_stride = bitmap->stride;
- access_test(canvas, src, bitmap->y * src_stride);
if (want_original) {
format = spice_bitmap_format_to_pixman(bitmap->format, canvas->format);
@@ -672,8 +657,6 @@ static inline SpicePalette *canvas_get_palette(CanvasBase *canvas, SPICE_ADDRESS
palette = canvas->palette_cache->ops->get(canvas->palette_cache, base_palette);
} else if (flags & SPICE_BITMAP_FLAGS_PAL_CACHE_ME) {
palette = (SpicePalette *)SPICE_GET_ADDRESS(base_palette);
- access_test(canvas, palette, sizeof(SpicePalette));
- access_test(canvas, palette, sizeof(SpicePalette) + palette->num_ents * sizeof(uint32_t));
canvas->palette_cache->ops->put(canvas->palette_cache, palette);
} else {
palette = (SpicePalette *)SPICE_GET_ADDRESS(base_palette);
@@ -990,11 +973,9 @@ static void dump_surface(pixman_image_t *surface, int cache)
static SpiceCanvas *canvas_get_surface_internal(CanvasBase *canvas, SPICE_ADDRESS addr)
{
SpiceImageDescriptor *descriptor = (SpiceImageDescriptor *)SPICE_GET_ADDRESS(addr);
- access_test(canvas, descriptor, sizeof(SpiceImageDescriptor));
if (descriptor->type == SPICE_IMAGE_TYPE_SURFACE) {
SpiceSurfaceImage *surface = (SpiceSurfaceImage *)descriptor;
- access_test(canvas, descriptor, sizeof(SpiceSurfaceImage));
return canvas->surfaces->ops->get(canvas->surfaces, surface->surface.surface_id);
}
return NULL;
@@ -1005,11 +986,9 @@ static SpiceCanvas *canvas_get_surface_mask_internal(CanvasBase *canvas, SPICE_A
SpiceImageDescriptor *descriptor;
descriptor = (SpiceImageDescriptor *)SPICE_GET_ADDRESS(addr);
- access_test(canvas, descriptor, sizeof(SpiceImageDescriptor));
if (descriptor->type == SPICE_IMAGE_TYPE_SURFACE) {
SpiceSurfaceImage *surface = (SpiceSurfaceImage *)descriptor;
- access_test(canvas, descriptor, sizeof(SpiceSurfaceImage));
return canvas->surfaces->ops->get(canvas->surfaces, surface->surface.surface_id);
}
return NULL;
@@ -1034,7 +1013,6 @@ static pixman_image_t *canvas_get_image_internal(CanvasBase *canvas, SPICE_ADDRE
pixman_image_t *surface, *converted;
pixman_format_code_t wanted_format, surface_format;
int saved_want_original;
- access_test(canvas, descriptor, sizeof(SpiceImageDescriptor));
#ifdef DEBUG_LZ
LOG_DEBUG("canvas_get_image image type: " << (int)descriptor->type);
#endif
@@ -1063,19 +1041,16 @@ static pixman_image_t *canvas_get_image_internal(CanvasBase *canvas, SPICE_ADDRE
switch (descriptor->type) {
case SPICE_IMAGE_TYPE_QUIC: {
SpiceQUICImage *image = (SpiceQUICImage *)descriptor;
- access_test(canvas, descriptor, sizeof(SpiceQUICImage));
surface = canvas_get_quic(canvas, image, 0, want_original);
break;
}
#ifdef SW_CANVAS_NO_CHUNKS
case SPICE_IMAGE_TYPE_LZ_PLT: {
- access_test(canvas, descriptor, sizeof(SpiceLZPLTImage));
LZImage *image = (LZImage *)descriptor;
surface = canvas_get_lz(canvas, image, 0, want_original);
break;
}
case SPICE_IMAGE_TYPE_LZ_RGB: {
- access_test(canvas, descriptor, sizeof(SpiceLZRGBImage));
LZImage *image = (LZImage *)descriptor;
surface = canvas_get_lz(canvas, image, 0, want_original);
break;
@@ -1083,13 +1058,11 @@ static pixman_image_t *canvas_get_image_internal(CanvasBase *canvas, SPICE_ADDRE
#endif
case SPICE_IMAGE_TYPE_JPEG: {
SpiceJPEGImage *image = (SpiceJPEGImage *)descriptor;
- access_test(canvas, descriptor, sizeof(SpiceJPEGImage));
surface = canvas_get_jpeg(canvas, image, 0);
break;
}
#if defined(SW_CANVAS_CACHE)
case SPICE_IMAGE_TYPE_GLZ_RGB: {
- access_test(canvas, descriptor, sizeof(SpiceLZRGBImage));
LZImage *image = (LZImage *)descriptor;
surface = canvas_get_glz(canvas, image, want_original);
break;
@@ -1106,7 +1079,6 @@ static pixman_image_t *canvas_get_image_internal(CanvasBase *canvas, SPICE_ADDRE
#endif
case SPICE_IMAGE_TYPE_BITMAP: {
SpiceBitmapImage *bitmap = (SpiceBitmapImage *)descriptor;
- access_test(canvas, descriptor, sizeof(SpiceBitmapImage));
surface = canvas_get_bits(canvas, &bitmap->bitmap, want_original);
break;
}
@@ -1213,8 +1185,6 @@ static pixman_image_t *canvas_get_image_internal(CanvasBase *canvas, SPICE_ADDRE
SpiceImageDescriptor *descriptor = (SpiceImageDescriptor *)SPICE_GET_ADDRESS(addr);
pixman_format_code_t format;
- access_test(canvas, descriptor, sizeof(SpiceImageDescriptor));
-
/* When touching, never load image. */
if (!real_get) {
return NULL;
@@ -1223,12 +1193,10 @@ static pixman_image_t *canvas_get_image_internal(CanvasBase *canvas, SPICE_ADDRE
switch (descriptor->type) {
case SPICE_IMAGE_TYPE_QUIC: {
SpiceQUICImage *image = (SpiceQUICImage *)descriptor;
- access_test(canvas, descriptor, sizeof(SpiceQUICImage));
return canvas_get_quic(canvas, image, 0);
}
case SPICE_IMAGE_TYPE_BITMAP: {
SpiceBitmapImage *bitmap = (SpiceBitmapImage *)descriptor;
- access_test(canvas, descriptor, sizeof(SpiceBitmapImage));
return canvas_get_bits(canvas, &bitmap->bitmap, want_original, &format);
}
default:
@@ -1323,7 +1291,6 @@ static pixman_image_t *canvas_get_bitmap_mask(CanvasBase *canvas, SpiceBitmap* b
src_line = (uint8_t *)SPICE_GET_ADDRESS(bitmap->data);
src_stride = bitmap->stride;
end_line = src_line + (bitmap->y * src_stride);
- access_test(canvas, src_line, end_line - src_line);
line_size = SPICE_ALIGN(bitmap->x, 8) >> 3;
dest_stride = pixman_image_get_stride(surface);
@@ -1455,7 +1422,6 @@ static pixman_image_t *canvas_get_mask(CanvasBase *canvas, SpiceQMask *mask, int
}
descriptor = (SpiceImageDescriptor *)SPICE_GET_ADDRESS(mask->bitmap);
- access_test(canvas, descriptor, sizeof(SpiceImageDescriptor));
need_invers = mask->flags & SPICE_MASK_FLAGS_INVERS;
#ifdef SW_CANVAS_CACHE
@@ -1467,7 +1433,6 @@ static pixman_image_t *canvas_get_mask(CanvasBase *canvas, SpiceQMask *mask, int
switch (descriptor->type) {
case SPICE_IMAGE_TYPE_BITMAP: {
SpiceBitmapImage *bitmap = (SpiceBitmapImage *)descriptor;
- access_test(canvas, descriptor, sizeof(SpiceBitmapImage));
is_invers = need_invers && !cache_me;
surface = canvas_get_bitmap_mask(canvas, &bitmap->bitmap, is_invers);
break;
@@ -1668,18 +1633,14 @@ static pixman_image_t *canvas_get_str_mask(CanvasBase *canvas, SpiceString *str,
ASSERT(str->length > 0);
- access_test(canvas, glyph, sizeof(SpiceRasterGlyph));
next_glyph = canvas_next_raster_glyph(glyph, bpp);
- access_test(canvas, glyph, (uint8_t*)next_glyph - (uint8_t*)glyph);
canvas_raster_glyph_box(glyph, &bounds);
for (i = 1; i < str->length; i++) {
SpiceRect glyph_box;
glyph = next_glyph;
- access_test(canvas, glyph, sizeof(SpiceRasterGlyph));
next_glyph = canvas_next_raster_glyph(glyph, bpp);
- access_test(canvas, glyph, (uint8_t*)next_glyph - (uint8_t*)glyph);
canvas_raster_glyph_box(glyph, &glyph_box);
rect_union(&bounds, &glyph_box);
}
@@ -1860,14 +1821,6 @@ static int quic_usr_more_lines(QuicUsrContext *usr, uint8_t **lines)
return 0;
}
-#ifdef SW_CANVAS_ACCESS_TEST
-static void __canvas_set_access_params(CanvasBase *canvas, unsigned long base, unsigned long max)
-{
- canvas->base = base;
- canvas->max = max;
-}
-#endif
-
static void canvas_base_destroy(CanvasBase *canvas)
{
quic_destroy(canvas->quic_data.quic);
@@ -1920,10 +1873,8 @@ static void canvas_clip_pixman(CanvasBase *canvas,
break;
case SPICE_CLIP_TYPE_RECTS: {
uint32_t *n = (uint32_t *)SPICE_GET_ADDRESS(clip->data);
- access_test(canvas, n, sizeof(uint32_t));
SpiceRect *now = (SpiceRect *)(n + 1);
- access_test(canvas, now, (unsigned long)(now + *n) - (unsigned long)now);
pixman_region32_t clip;
@@ -3073,7 +3024,6 @@ static void canvas_draw_stroke(SpiceCanvas *spice_canvas, SpiceRect *bbox,
gc.base.lineStyle = LineOnOffDash;
gc.base.dash = (unsigned char *)spice_malloc(nseg);
gc.base.numInDashList = nseg;
- access_test(canvas, style, nseg * sizeof(*style));
if (stroke->attr.flags & SPICE_LINE_FLAGS_START_WITH_GAP) {
gc.base.dash[stroke->attr.style_nseg - 1] = fix_to_int(style[0]);
@@ -3118,19 +3068,15 @@ static void canvas_draw_stroke(SpiceCanvas *spice_canvas, SpiceRect *bbox,
}
data_size = (uint32_t*)SPICE_GET_ADDRESS(stroke->path);
- access_test(canvas, data_size, sizeof(uint32_t));
more = *data_size;
seg = (SpicePathSeg*)(data_size + 1);
stroke_lines_init(&lines);
do {
- access_test(canvas, seg, sizeof(SpicePathSeg));
-
uint32_t flags = seg->flags;
SpicePointFix* point = (SpicePointFix*)seg->data;
SpicePointFix* end_point = point + seg->count;
- access_test(canvas, point, (unsigned long)end_point - (unsigned long)point);
ASSERT(point < end_point);
more -= ((unsigned long)end_point - (unsigned long)seg);
seg = (SpicePathSeg*)end_point;
diff --git a/common/canvas_base.h b/common/canvas_base.h
index 1bbe465..b54fce5 100644
--- a/common/canvas_base.h
+++ b/common/canvas_base.h
@@ -142,7 +142,6 @@ typedef struct {
void (*read_bits)(SpiceCanvas *canvas, uint8_t *dest, int dest_stride, const SpiceRect *area);
void (*group_start)(SpiceCanvas *canvas, QRegion *region);
void (*group_end)(SpiceCanvas *canvas);
- void (*set_access_params)(SpiceCanvas *canvas, unsigned long base, unsigned long max);
void (*destroy)(SpiceCanvas *canvas);
/* Implementation vfuncs */
diff --git a/common/gdi_canvas.c b/common/gdi_canvas.c
index 20113fe..fea2390 100644
--- a/common/gdi_canvas.c
+++ b/common/gdi_canvas.c
@@ -311,18 +311,14 @@ uint32_t raster_ops[] = {
static void set_path(GdiCanvas *canvas, void *addr)
{
uint32_t* data_size = (uint32_t*)addr;
- access_test(&canvas->base, data_size, sizeof(uint32_t));
uint32_t more = *data_size;
SpicePathSeg* seg = (SpicePathSeg*)(data_size + 1);
do {
- access_test(&canvas->base, seg, sizeof(SpicePathSeg));
-
uint32_t flags = seg->flags;
SpicePointFix* point = (SpicePointFix*)seg->data;
SpicePointFix* end_point = point + seg->count;
- access_test(&canvas->base, point, (unsigned long)end_point - (unsigned long)point);
ASSERT(point < end_point);
more -= ((unsigned long)end_point - (unsigned long)seg);
seg = (SpicePathSeg*)end_point;
@@ -399,11 +395,9 @@ static void set_clip(GdiCanvas *canvas, SpiceClip *clip)
break;
case SPICE_CLIP_TYPE_RECTS: {
uint32_t *n = (uint32_t *)SPICE_GET_ADDRESS(clip->data);
- access_test(&canvas->base, n, sizeof(uint32_t));
SpiceRect *now = (SpiceRect *)(n + 1);
SpiceRect *end = now + *n;
- access_test(&canvas->base, now, (unsigned long)end - (unsigned long)now);
if (now < end) {
HRGN main_hrgn;
@@ -1643,8 +1637,6 @@ static uint32_t *gdi_get_userstyle(GdiCanvas *canvas, uint8_t nseg, SPICE_ADDRES
uint32_t *local_style;
int i;
- access_test(&canvas->base, style, nseg * sizeof(*style));
-
if (nseg == 0) {
CANVAS_ERROR("bad nseg");
}
@@ -1835,14 +1827,6 @@ static void gdi_canvas_clear(SpiceCanvas *spice_canvas)
{
}
-static void gdi_canvas_set_access_params(SpiceCanvas *spice_canvas, unsigned long base, unsigned long max)
-{
-#ifdef SW_CANVAS_ACCESS_TEST
- GdiCanvas *canvas = (GdiCanvas *)spice_canvas;
- __canvas_set_access_params(&canvas->base, base, max);
-#endif
-}
-
static void gdi_canvas_destroy(SpiceCanvas *spice_canvas)
{
GdiCanvas *canvas = (GdiCanvas *)spice_canvas;
@@ -1915,7 +1899,6 @@ void gdi_canvas_init() //unsafe global function
gdi_canvas_ops.draw_alpha_blend = gdi_canvas_draw_alpha_blend;
gdi_canvas_ops.put_image = gdi_canvas_put_image;
gdi_canvas_ops.clear = gdi_canvas_clear;
- gdi_canvas_ops.set_access_params = gdi_canvas_set_access_params;
gdi_canvas_ops.destroy = gdi_canvas_destroy;
rop3_init();
diff --git a/common/gl_canvas.c b/common/gl_canvas.c
index 00caf89..444fa4b 100644
--- a/common/gl_canvas.c
+++ b/common/gl_canvas.c
@@ -115,18 +115,14 @@ static GLCPath get_path(GLCanvas *canvas, void *addr)
{
GLCPath path = glc_path_create(canvas->glc);
uint32_t* data_size = (uint32_t*)addr;
- access_test(&canvas->base, data_size, sizeof(uint32_t));
uint32_t more = *data_size;
SpicePathSeg* seg = (SpicePathSeg*)(data_size + 1);
do {
- access_test(&canvas->base, seg, sizeof(SpicePathSeg));
-
uint32_t flags = seg->flags;
SpicePointFix* point = (SpicePointFix*)seg->data;
SpicePointFix* end_point = point + seg->count;
- access_test(&canvas->base, point, (unsigned long)end_point - (unsigned long)point);
ASSERT(point < end_point);
more -= ((unsigned long)end_point - (unsigned long)seg);
seg = (SpicePathSeg*)end_point;
@@ -183,10 +179,8 @@ static void set_clip(GLCanvas *canvas, SpiceRect *bbox, SpiceClip *clip)
break;
case SPICE_CLIP_TYPE_RECTS: {
uint32_t *n = (uint32_t *)SPICE_GET_ADDRESS(clip->data);
- access_test(&canvas->base, n, sizeof(uint32_t));
SpiceRect *now = (SpiceRect *)(n + 1);
SpiceRect *end = now + *n;
- access_test(&canvas->base, now, (unsigned long)end - (unsigned long)now);
if (*n == 0) {
rect.x = rect.y = 0;
@@ -810,14 +804,6 @@ static void gl_canvas_group_end(SpiceCanvas *spice_canvas)
glc_clear_mask(canvas->glc, GLC_MASK_B);
}
-static void gl_canvas_set_access_params(SpiceCanvas *spice_canvas, unsigned long base, unsigned long max)
-{
-#ifdef SW_CANVAS_ACCESS_TEST
- GLCanvas *canvas = (GLCanvas *)spice_canvas;
- __canvas_set_access_params(&canvas->base, base, max);
-#endif
-}
-
static int need_init = 1;
static SpiceCanvasOps gl_canvas_ops;
@@ -926,7 +912,6 @@ void gl_canvas_init() //unsafe global function
gl_canvas_ops.read_bits = gl_canvas_read_bits;
gl_canvas_ops.group_start = gl_canvas_group_start;
gl_canvas_ops.group_end = gl_canvas_group_end;
- gl_canvas_ops.set_access_params = gl_canvas_set_access_params;
gl_canvas_ops.destroy = gl_canvas_destroy;
rop3_init();
diff --git a/common/sw_canvas.c b/common/sw_canvas.c
index 8280362..c1a7392 100644
--- a/common/sw_canvas.c
+++ b/common/sw_canvas.c
@@ -1144,15 +1144,6 @@ static void canvas_clear(SpiceCanvas *spice_canvas)
0);
}
-static void canvas_set_access_params(SpiceCanvas *spice_canvas,
- unsigned long base, unsigned long max)
-{
-#ifdef SW_CANVAS_ACCESS_TEST
- SwCanvas *canvas = (SwCanvas *)spice_canvas;
- __canvas_set_access_params(&canvas->base, base, max);
-#endif
-}
-
static void canvas_destroy(SpiceCanvas *spice_canvas)
{
SwCanvas *canvas = (SwCanvas *)spice_canvas;
@@ -1306,7 +1297,6 @@ void sw_canvas_init() //unsafe global function
sw_canvas_ops.put_image = canvas_put_image;
sw_canvas_ops.clear = canvas_clear;
sw_canvas_ops.read_bits = canvas_read_bits;
- sw_canvas_ops.set_access_params = canvas_set_access_params;
sw_canvas_ops.destroy = canvas_destroy;
sw_canvas_ops.fill_solid_spans = fill_solid_spans;
commit 17bbef4df334bd8d98d3960143f229d753b4b0a3
Author: Alexander Larsson <alexl at redhat.com>
Date: Wed May 26 13:59:51 2010 +0200
Generate demarshallers in client
diff --git a/client/Makefile.am b/client/Makefile.am
index 55bc0f8..ab80bfb 100644
--- a/client/Makefile.am
+++ b/client/Makefile.am
@@ -1,8 +1,13 @@
NULL =
-SUBDIRS = $(red_target)
+SUBDIRS = . $(red_target)
DIST_SUBDIRS = x11 #windows
+spice_built_sources = generated_demarshallers.cpp
+
+generated_demarshallers.cpp: $(top_srcdir)/spice.proto
+ $(PYTHON) $(top_srcdir)/spice_codegen.py --generate-demarshallers --client --include common.h $(top_srcdir)/spice.proto generated_demarshallers.cpp
+
RED_COMMON_SRCS = \
application.cpp \
application.h \
@@ -90,4 +95,8 @@ RED_COMMON_SRCS = \
utils.h \
$(NULL)
-EXTRA_DIST = $(RED_COMMON_SRCS)
+MAINTAINERCLEANFILES = $(spice_built_sources)
+
+EXTRA_DIST = $(RED_COMMON_SRCS) $(spice_built_sources)
+
+BUILT_SOURCES = $(spice_built_sources)
diff --git a/configure.ac b/configure.ac
index 08804bf..3114a1a 100644
--- a/configure.ac
+++ b/configure.ac
@@ -25,6 +25,7 @@ AC_CANONICAL_HOST
AC_PROG_LIBTOOL
AM_PROG_CC_C_O
AC_C_BIGENDIAN
+AC_PATH_PROGS(PYTHON, python2 python)
SPICE_LT_VERSION=m4_format("%d:%d:%d", 1, 0, 0)
AC_SUBST(SPICE_LT_VERSION)
commit b228d18d5c8a2feb8319de50d5e6cc8925e11545
Author: Alexander Larsson <alexl at redhat.com>
Date: Wed May 26 12:24:48 2010 +0200
Add python code to automake system
diff --git a/Makefile.am b/Makefile.am
index 6640259..5701e25 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -1,7 +1,9 @@
-SUBDIRS = common server client
+SUBDIRS = common server client python_modules
pkgconfigdir = $(libdir)/pkgconfig
pkgconfig_DATA = spice-server.pc
DISTCLEANFILES = \
spice-server.pc
+
+EXTRA_DIST = spice.proto spice_codegen.py
diff --git a/configure.ac b/configure.ac
index 0958b6d..08804bf 100644
--- a/configure.ac
+++ b/configure.ac
@@ -337,6 +337,7 @@ AC_OUTPUT([
Makefile
spice-server.pc
common/Makefile
+python_modules/Makefile
server/Makefile
client/Makefile
client/x11/Makefile
diff --git a/python_modules/Makefile.am b/python_modules/Makefile.am
new file mode 100644
index 0000000..4b3c960
--- /dev/null
+++ b/python_modules/Makefile.am
@@ -0,0 +1,6 @@
+NULL =
+
+PYTHON_MODULES = __init__.py codegen.py demarshal.py ptypes.py spice_parser.py
+
+EXTRA_DIST = $(PYTHON_MODULES)
+
diff --git a/spice_codegen.py b/spice_codegen.py
new file mode 100755
index 0000000..f897ce8
--- /dev/null
+++ b/spice_codegen.py
@@ -0,0 +1,165 @@
+#!/usr/bin/env python
+
+import os
+import sys
+from optparse import OptionParser
+import traceback
+from python_modules import spice_parser
+from python_modules import ptypes
+from python_modules import codegen
+from python_modules import demarshal
+
+def write_channel_enums(writer, channel, client):
+ messages = filter(lambda m : m.channel == channel, \
+ channel.client_messages if client else channel.server_messages)
+ if len(messages) == 0:
+ return
+ writer.begin_block("enum")
+ i = 0;
+ if client:
+ prefix = [ "MSGC" ]
+ else:
+ prefix = [ "MSG" ]
+ if channel.member_name:
+ prefix.append(channel.member_name.upper())
+ prefix.append(None) # To be replaced with name
+ for m in messages:
+ prefix[-1] = m.name.upper()
+ enum = codegen.prefix_underscore_upper(*prefix)
+ if m.value == i:
+ writer.writeln("%s," % enum)
+ i = i + 1
+ else:
+ writer.writeln("%s = %s," % (enum, m.value))
+ i = m.value + 1
+ if channel.member_name:
+ prefix[-1] = prefix[-2]
+ prefix[-2] = "END"
+ writer.newline()
+ writer.writeln("%s" % (codegen.prefix_underscore_upper(*prefix)))
+ writer.end_block(semicolon=True)
+ writer.newline()
+
+def write_enums(writer):
+ writer.writeln("#ifndef _H_SPICE_ENUMS")
+ writer.writeln("#define _H_SPICE_ENUMS")
+ writer.newline()
+ writer.comment("Generated from %s, don't edit" % writer.options["source"]).newline()
+ writer.newline()
+
+ # Define enums
+ for t in ptypes.get_named_types():
+ if isinstance(t, ptypes.EnumBaseType):
+ t.c_define(writer)
+
+ i = 0;
+ writer.begin_block("enum")
+ for c in proto.channels:
+ enum = codegen.prefix_underscore_upper("CHANNEL", c.name.upper())
+ if c.value == i:
+ writer.writeln("%s," % enum)
+ i = i + 1
+ else:
+ writer.writeln("%s = %s," % (enum, c.value))
+ i = c.value + 1
+ writer.newline()
+ writer.writeln("SPICE_END_CHANNEL")
+ writer.end_block(semicolon=True)
+ writer.newline()
+
+ for c in ptypes.get_named_types():
+ if not isinstance(c, ptypes.ChannelType):
+ continue
+ write_channel_enums(writer, c, False)
+ write_channel_enums(writer, c, True)
+
+ writer.writeln("#endif /* _H_SPICE_ENUMS */")
+
+parser = OptionParser(usage="usage: %prog [options] <protocol_file> <destination file>")
+parser.add_option("-e", "--generate-enums",
+ action="store_true", dest="generate_enums", default=False,
+ help="Generate enums")
+parser.add_option("-d", "--generate-demarshallers",
+ action="store_true", dest="generate_demarshallers", default=False,
+ help="Generate demarshallers")
+parser.add_option("-a", "--assert-on-error",
+ action="store_true", dest="assert_on_error", default=False,
+ help="Assert on error")
+parser.add_option("-p", "--print-error",
+ action="store_true", dest="print_error", default=False,
+ help="Print errors")
+parser.add_option("-s", "--server",
+ action="store_true", dest="server", default=False,
+ help="Print errors")
+parser.add_option("-c", "--client",
+ action="store_true", dest="client", default=False,
+ help="Print errors")
+parser.add_option("-k", "--keep-identical-file",
+ action="store_true", dest="keep_identical_file", default=False,
+ help="Print errors")
+parser.add_option("-i", "--include",
+ dest="include", default=None, metavar="FILE",
+ help="Include FILE in generated code")
+
+(options, args) = parser.parse_args()
+
+if len(args) == 0:
+ parser.error("No protocol file specified")
+
+if len(args) == 1:
+ parser.error("No destination file specified")
+
+proto_file = args[0]
+dest_file = args[1]
+proto = spice_parser.parse(proto_file)
+
+if proto == None:
+ exit(1)
+
+codegen.set_prefix(proto.name)
+writer = codegen.CodeWriter()
+writer.set_option("source", os.path.basename(proto_file))
+
+if options.assert_on_error:
+ writer.set_option("assert_on_error")
+
+if options.print_error:
+ writer.set_option("print_error")
+
+if options.include:
+ writer.writeln('#include "%s"' % options.include)
+
+if options.generate_enums:
+ write_enums(writer)
+
+if options.generate_demarshallers:
+ if not options.server and not options.client:
+ print >> sys.stderr, "Must specify client and/or server"
+ sys.exit(1)
+ demarshal.write_includes(writer)
+
+ if options.server:
+ demarshal.write_protocol_parser(writer, proto, False)
+ if options.client:
+ demarshal.write_protocol_parser(writer, proto, True)
+
+content = writer.getvalue()
+if options.keep_identical_file:
+ try:
+ f = open(dest_file, 'rb')
+ old_content = f.read()
+ f.close()
+
+ if content == old_content:
+ print "No changes to %s" % dest_file
+ sys.exit(0)
+
+ except IOError:
+ pass
+
+f = open(dest_file, 'wb')
+f.write(content)
+f.close()
+
+print "Wrote %s" % dest_file
+sys.exit(0)
diff --git a/spice_gen.py b/spice_gen.py
deleted file mode 100755
index f897ce8..0000000
--- a/spice_gen.py
+++ /dev/null
@@ -1,165 +0,0 @@
-#!/usr/bin/env python
-
-import os
-import sys
-from optparse import OptionParser
-import traceback
-from python_modules import spice_parser
-from python_modules import ptypes
-from python_modules import codegen
-from python_modules import demarshal
-
-def write_channel_enums(writer, channel, client):
- messages = filter(lambda m : m.channel == channel, \
- channel.client_messages if client else channel.server_messages)
- if len(messages) == 0:
- return
- writer.begin_block("enum")
- i = 0;
- if client:
- prefix = [ "MSGC" ]
- else:
- prefix = [ "MSG" ]
- if channel.member_name:
- prefix.append(channel.member_name.upper())
- prefix.append(None) # To be replaced with name
- for m in messages:
- prefix[-1] = m.name.upper()
- enum = codegen.prefix_underscore_upper(*prefix)
- if m.value == i:
- writer.writeln("%s," % enum)
- i = i + 1
- else:
- writer.writeln("%s = %s," % (enum, m.value))
- i = m.value + 1
- if channel.member_name:
- prefix[-1] = prefix[-2]
- prefix[-2] = "END"
- writer.newline()
- writer.writeln("%s" % (codegen.prefix_underscore_upper(*prefix)))
- writer.end_block(semicolon=True)
- writer.newline()
-
-def write_enums(writer):
- writer.writeln("#ifndef _H_SPICE_ENUMS")
- writer.writeln("#define _H_SPICE_ENUMS")
- writer.newline()
- writer.comment("Generated from %s, don't edit" % writer.options["source"]).newline()
- writer.newline()
-
- # Define enums
- for t in ptypes.get_named_types():
- if isinstance(t, ptypes.EnumBaseType):
- t.c_define(writer)
-
- i = 0;
- writer.begin_block("enum")
- for c in proto.channels:
- enum = codegen.prefix_underscore_upper("CHANNEL", c.name.upper())
- if c.value == i:
- writer.writeln("%s," % enum)
- i = i + 1
- else:
- writer.writeln("%s = %s," % (enum, c.value))
- i = c.value + 1
- writer.newline()
- writer.writeln("SPICE_END_CHANNEL")
- writer.end_block(semicolon=True)
- writer.newline()
-
- for c in ptypes.get_named_types():
- if not isinstance(c, ptypes.ChannelType):
- continue
- write_channel_enums(writer, c, False)
- write_channel_enums(writer, c, True)
-
- writer.writeln("#endif /* _H_SPICE_ENUMS */")
-
-parser = OptionParser(usage="usage: %prog [options] <protocol_file> <destination file>")
-parser.add_option("-e", "--generate-enums",
- action="store_true", dest="generate_enums", default=False,
- help="Generate enums")
-parser.add_option("-d", "--generate-demarshallers",
- action="store_true", dest="generate_demarshallers", default=False,
- help="Generate demarshallers")
-parser.add_option("-a", "--assert-on-error",
- action="store_true", dest="assert_on_error", default=False,
- help="Assert on error")
-parser.add_option("-p", "--print-error",
- action="store_true", dest="print_error", default=False,
- help="Print errors")
-parser.add_option("-s", "--server",
- action="store_true", dest="server", default=False,
- help="Print errors")
-parser.add_option("-c", "--client",
- action="store_true", dest="client", default=False,
- help="Print errors")
-parser.add_option("-k", "--keep-identical-file",
- action="store_true", dest="keep_identical_file", default=False,
- help="Print errors")
-parser.add_option("-i", "--include",
- dest="include", default=None, metavar="FILE",
- help="Include FILE in generated code")
-
-(options, args) = parser.parse_args()
-
-if len(args) == 0:
- parser.error("No protocol file specified")
-
-if len(args) == 1:
- parser.error("No destination file specified")
-
-proto_file = args[0]
-dest_file = args[1]
-proto = spice_parser.parse(proto_file)
-
-if proto == None:
- exit(1)
-
-codegen.set_prefix(proto.name)
-writer = codegen.CodeWriter()
-writer.set_option("source", os.path.basename(proto_file))
-
-if options.assert_on_error:
- writer.set_option("assert_on_error")
-
-if options.print_error:
- writer.set_option("print_error")
-
-if options.include:
- writer.writeln('#include "%s"' % options.include)
-
-if options.generate_enums:
- write_enums(writer)
-
-if options.generate_demarshallers:
- if not options.server and not options.client:
- print >> sys.stderr, "Must specify client and/or server"
- sys.exit(1)
- demarshal.write_includes(writer)
-
- if options.server:
- demarshal.write_protocol_parser(writer, proto, False)
- if options.client:
- demarshal.write_protocol_parser(writer, proto, True)
-
-content = writer.getvalue()
-if options.keep_identical_file:
- try:
- f = open(dest_file, 'rb')
- old_content = f.read()
- f.close()
-
- if content == old_content:
- print "No changes to %s" % dest_file
- sys.exit(0)
-
- except IOError:
- pass
-
-f = open(dest_file, 'wb')
-f.write(content)
-f.close()
-
-print "Wrote %s" % dest_file
-sys.exit(0)
commit 0366e7395c97e51b8a6294c10176bef73e1bdcf7
Author: Alexander Larsson <alexl at redhat.com>
Date: Wed May 26 12:19:58 2010 +0200
Initial import of spice protocol description and demarshall generator
The "spice.proto" file describes in detail the networking prototcol
that spice uses and spice_codegen.py can parse this and generate
demarshallers for such network messages.
diff --git a/python_modules/__init__.py b/python_modules/__init__.py
new file mode 100644
index 0000000..e69de29
diff --git a/python_modules/codegen.py b/python_modules/codegen.py
new file mode 100644
index 0000000..5bb659a
--- /dev/null
+++ b/python_modules/codegen.py
@@ -0,0 +1,354 @@
+from cStringIO import StringIO
+
+def camel_to_underscores(s, upper = False):
+ res = ""
+ for i in range(len(s)):
+ c = s[i]
+ if i > 0 and c.isupper():
+ res = res + "_"
+ if upper:
+ res = res + c.upper()
+ else:
+ res = res + c.lower()
+ return res
+
+def underscores_to_camel(s):
+ res = ""
+ do_upper = True
+ for i in range(len(s)):
+ c = s[i]
+ if c == "_":
+ do_upper = True
+ else:
+ if do_upper:
+ res = res + c.upper()
+ else:
+ res = res + c
+ do_upper = False
+ return res
+
+proto_prefix = "Temp"
+
+def set_prefix(prefix):
+ global proto_prefix
+ global proto_prefix_upper
+ global proto_prefix_lower
+ proto_prefix = prefix
+ proto_prefix_upper = prefix.upper()
+ proto_prefix_lower = prefix.lower()
+
+def prefix_underscore_upper(*args):
+ s = proto_prefix_upper
+ for arg in args:
+ s = s + "_" + arg
+ return s
+
+def prefix_underscore_lower(*args):
+ s = proto_prefix_lower
+ for arg in args:
+ s = s + "_" + arg
+ return s
+
+def prefix_camel(*args):
+ s = proto_prefix
+ for arg in args:
+ s = s + underscores_to_camel(arg)
+ return s
+
+def increment_identifier(idf):
+ v = idf[-1:]
+ if v.isdigit():
+ return idf[:-1] + str(int(v) + 1)
+ return idf + "2"
+
+def sum_array(array):
+ if len(array) == 0:
+ return 0
+ return " + ".join(array)
+
+class CodeWriter:
+ def __init__(self):
+ self.out = StringIO()
+ self.contents = [self.out]
+ self.indentation = 0
+ self.at_line_start = True
+ self.indexes = ["i", "j", "k", "ii", "jj", "kk"]
+ self.current_index = 0
+ self.generated = {}
+ self.vars = []
+ self.has_error_check = False
+ self.options = {}
+ self.function_helper_writer = None
+
+ def set_option(self, opt, value = True):
+ self.options[opt] = value
+
+ def has_option(self, opt):
+ return self.options.has_key(opt)
+
+ def set_is_generated(self, kind, name):
+ if not self.generated.has_key(kind):
+ v = {}
+ self.generated[kind] = v
+ else:
+ v = self.generated[kind]
+ v[name] = 1
+
+ def is_generated(self, kind, name):
+ if not self.generated.has_key(kind):
+ return False
+ v = self.generated[kind]
+ return v.has_key(name)
+
+ def getvalue(self):
+ strs = map(lambda writer: writer.getvalue(), self.contents)
+ return "".join(strs)
+
+ def get_subwriter(self):
+ writer = CodeWriter()
+ self.contents.append(writer)
+ self.out = StringIO()
+ self.contents.append(self.out)
+ writer.indentation = self.indentation
+ writer.at_line_start = self.at_line_start
+ writer.generated = self.generated
+ writer.options = self.options
+
+ return writer;
+
+ def write(self, s):
+ # Ensure its a string
+ s = str(s)
+
+ if len(s) == 0:
+ return
+
+ if self.at_line_start:
+ for i in range(self.indentation):
+ self.out.write(" ")
+ self.at_line_start = False
+ self.out.write(s)
+ return self
+
+ def newline(self):
+ self.out.write("\n")
+ self.at_line_start = True
+ return self
+
+ def writeln(self, s):
+ self.write(s)
+ self.newline()
+ return self
+
+ def label(self, s):
+ self.indentation = self.indentation - 1
+ self.write(s + ":")
+ self.indentation = self.indentation + 1
+ self.newline()
+
+ def statement(self, s):
+ self.write(s)
+ self.write(";")
+ self.newline()
+ return self
+
+ def assign(self, var, val):
+ self.write("%s = %s" % (var, val))
+ self.write(";")
+ self.newline()
+ return self
+
+ def increment(self, var, val):
+ self.write("%s += %s" % (var, val))
+ self.write(";")
+ self.newline()
+ return self
+
+ def comment(self, str):
+ self.write("/* " + str + " */")
+ return self
+
+ def todo(self, str):
+ self.comment("TODO: *** %s ***" % str).newline()
+ return self
+
+ def error_check(self, check, label = "error"):
+ self.has_error_check = True
+ with self.block("if (SPICE_UNLIKELY(%s))" % check):
+ if self.has_option("print_error"):
+ self.statement('printf("%%s: Caught error - %s", __PRETTY_FUNCTION__)' % check)
+ if self.has_option("assert_on_error"):
+ self.statement("assert(0)")
+ self.statement("goto %s" % label)
+
+ def indent(self):
+ self.indentation += 4;
+
+ def unindent(self):
+ self.indentation -= 4;
+ if self.indentation < 0:
+ self.indenttation = 0
+
+ def begin_block(self, prefix= "", comment = ""):
+ if len(prefix) > 0:
+ self.write(prefix)
+ if self.at_line_start:
+ self.write("{")
+ else:
+ self.write(" {")
+ if len(comment) > 0:
+ self.write(" ")
+ self.comment(comment)
+ self.newline()
+ self.indent()
+
+ def end_block(self, semicolon=False, newline=True):
+ self.unindent()
+ if self.at_line_start:
+ self.write("}")
+ else:
+ self.write(" }")
+ if semicolon:
+ self.write(";")
+ if newline:
+ self.newline()
+
+ class Block:
+ def __init__(self, writer, semicolon, newline):
+ self.writer = writer
+ self.semicolon = semicolon
+ self.newline = newline
+
+ def __enter__(self):
+ return self.writer.get_subwriter()
+
+ def __exit__(self, exc_type, exc_value, traceback):
+ self.writer.end_block(self.semicolon, self.newline)
+
+ class PartialBlock:
+ def __init__(self, writer, scope, semicolon, newline):
+ self.writer = writer
+ self.scope = scope
+ self.semicolon = semicolon
+ self.newline = newline
+
+ def __enter__(self):
+ return self.scope
+
+ def __exit__(self, exc_type, exc_value, traceback):
+ self.writer.end_block(self.semicolon, self.newline)
+
+ class NoBlock:
+ def __init__(self, scope):
+ self.scope = scope
+
+ def __enter__(self):
+ return self.scope
+
+ def __exit__(self, exc_type, exc_value, traceback):
+ pass
+
+ def block(self, prefix= "", comment = "", semicolon=False, newline=True):
+ self.begin_block(prefix, comment)
+ return self.Block(self, semicolon, newline)
+
+ def partial_block(self, scope, semicolon=False, newline=True):
+ return self.PartialBlock(self, scope, semicolon, newline)
+
+ def no_block(self, scope):
+ return self.NoBlock(scope)
+
+ def optional_block(self, scope):
+ if scope != None:
+ return self.NoBlock(scope)
+ return self.block()
+
+ def for_loop(self, index, limit):
+ return self.block("for (%s = 0; %s < %s; %s++)" % (index, index, limit, index))
+
+ def while_loop(self, expr):
+ return self.block("while (%s)" % (expr))
+
+ def if_block(self, check, elseif=False, newline=True):
+ s = "if (%s)" % (check)
+ if elseif:
+ s = " else " + s
+ self.begin_block(s, "")
+ return self.Block(self, False, newline)
+
+ def variable_defined(self, name):
+ for n in self.vars:
+ if n == name:
+ return True
+ return False
+
+ def variable_def(self, ctype, *names):
+ for n in names:
+ # Strip away initialization
+ i = n.find("=")
+ if i != -1:
+ n = n[0:i]
+ self.vars.append(n.strip())
+ # only add space for non-pointer types
+ if ctype[-1] == "*":
+ ctype = ctype[:-1].rstrip()
+ self.writeln("%s *%s;"%(ctype, ", *".join(names)))
+ else:
+ self.writeln("%s %s;"%(ctype, ", ".join(names)))
+ return self
+
+ def function_helper(self):
+ if self.function_helper_writer != None:
+ writer = self.function_helper_writer.get_subwriter()
+ self.function_helper_writer.newline()
+ else:
+ writer = self.get_subwriter()
+ return writer
+
+ def function(self, name, return_type, args, static = False):
+ self.has_error_check = False
+ self.function_helper_writer = self.get_subwriter()
+ if static:
+ self.write("static ")
+ self.write(return_type)
+ self.write(" %s(%s)"% (name, args)).newline()
+ self.begin_block()
+ self.function_variables_writer = self.get_subwriter()
+ self.function_variables = {}
+ return self.function_variables_writer
+
+ def macro(self, name, args, define):
+ self.write("#define %s(%s) %s" % (name, args, define)).newline()
+
+ def add_function_variable(self, ctype, name):
+ if self.function_variables.has_key(name):
+ assert(self.function_variables[name] == ctype)
+ else:
+ self.function_variables[name] = ctype
+ self.function_variables_writer.variable_def(ctype, name)
+
+ def pop_index(self):
+ index = self.indexes[self.current_index]
+ self.current_index = self.current_index + 1
+ self.add_function_variable("uint32_t", index)
+ return index
+
+ def push_index(self):
+ self.current_index = self.current_index - 1
+
+ class Index:
+ def __init__(self, writer, val):
+ self.writer = writer
+ self.val = val
+
+ def __enter__(self):
+ return self.val
+
+ def __exit__(self, exc_type, exc_value, traceback):
+ self.writer.push_index()
+
+ def index(self, no_block = False):
+ if no_block:
+ return self.no_block(None)
+ val = self.pop_index()
+ return self.Index(self, val)
diff --git a/python_modules/demarshal.py b/python_modules/demarshal.py
new file mode 100644
index 0000000..fcd6850
--- /dev/null
+++ b/python_modules/demarshal.py
@@ -0,0 +1,1033 @@
+import ptypes
+import codegen
+
+
+def write_parser_helpers(writer):
+ if writer.is_generated("helper", "demarshaller"):
+ return
+
+ writer.set_is_generated("helper", "demarshaller")
+
+ writer = writer.function_helper()
+
+ writer.writeln("#ifdef WORDS_BIGENDIAN")
+ for size in [8, 16, 32, 64]:
+ for sign in ["", "u"]:
+ utype = "uint%d" % (size)
+ type = "%sint%d" % (sign, size)
+ swap = "SPICE_BYTESWAP%d" % size
+ if size == 8:
+ writer.macro("read_%s" % type, "ptr", "(*((%s_t *)(ptr)))" % type)
+ else:
+ writer.macro("read_%s" % type, "ptr", "((%s_t)%s(*((%s_t *)(ptr)))" % (type, swap, utype))
+ writer.writeln("#else")
+ for size in [8, 16, 32, 64]:
+ for sign in ["", "u"]:
+ type = "%sint%d" % (sign, size)
+ writer.macro("read_%s" % type, "ptr", "(*((%s_t *)(ptr)))" % type)
+ writer.writeln("#endif")
+
+ for size in [8, 16, 32, 64]:
+ for sign in ["", "u"]:
+ writer.newline()
+ type = "%sint%d" % (sign, size)
+ ctype = "%s_t" % type
+ scope = writer.function("SPICE_GNUC_UNUSED consume_%s" % type, ctype, "uint8_t **ptr", True)
+ scope.variable_def(ctype, "val")
+ writer.assign("val", "read_%s(*ptr)" % type)
+ writer.increment("*ptr", size / 8)
+ writer.statement("return val")
+ writer.end_block()
+
+ writer.newline()
+ writer.statement("typedef struct PointerInfo PointerInfo")
+ writer.statement("typedef uint8_t * (*parse_func_t)(uint8_t *message_start, uint8_t *message_end, uint8_t *struct_data, PointerInfo *ptr_info, int minor)")
+ writer.statement("typedef uint8_t * (*parse_msg_func_t)(uint8_t *message_start, uint8_t *message_end, int minor, size_t *size_out)")
+ writer.statement("typedef uint8_t * (*spice_parse_channel_func_t)(uint8_t *message_start, uint8_t *message_end, uint16_t message_type, int minor, size_t *size_out)")
+
+ writer.newline()
+ writer.begin_block("struct PointerInfo")
+ writer.variable_def("uint64_t", "offset")
+ writer.variable_def("parse_func_t", "parse")
+ writer.variable_def("SPICE_ADDRESS *", "dest")
+ writer.variable_def("uint32_t", "nelements")
+ writer.end_block(semicolon=True)
+
+def write_read_primitive(writer, start, container, name, scope):
+ m = container.lookup_member(name)
+ assert(m.is_primitive())
+ writer.assign("pos", start + " + " + container.get_nw_offset(m, "", "__nw_size"))
+ writer.error_check("pos + %s > message_end" % m.member_type.get_fixed_nw_size())
+
+ var = "%s__value" % (name)
+ scope.variable_def(m.member_type.c_type(), var)
+ writer.assign(var, "read_%s(pos)" % (m.member_type.primitive_type()))
+ return var
+
+def write_read_primitive_item(writer, item, scope):
+ assert(item.type.is_primitive())
+ writer.assign("pos", item.get_position())
+ writer.error_check("pos + %s > message_end" % item.type.get_fixed_nw_size())
+ var = "%s__value" % (item.subprefix)
+ scope.variable_def(item.type.c_type(), var)
+ writer.assign(var, "read_%s(pos)" % (item.type.primitive_type()))
+ return var
+
+class ItemInfo:
+ def __init__(self, type, prefix, position):
+ self.type = type
+ self.prefix = prefix
+ self.subprefix = prefix
+ self.position = position
+ self.non_null = False
+ self.member = None
+
+ def nw_size(self):
+ return self.prefix + "__nw_size"
+
+ def mem_size(self):
+ return self.prefix + "__mem_size"
+
+ def extra_size(self):
+ return self.prefix + "__extra_size"
+
+ def get_position(self):
+ return self.position
+
+class MemberItemInfo(ItemInfo):
+ def __init__(self, member, container, start):
+ if not member.is_switch():
+ self.type = member.member_type
+ self.prefix = member.name
+ self.subprefix = member.name
+ self.non_null = member.has_attr("nonnull")
+ self.position = "(%s + %s)" % (start, container.get_nw_offset(member, "", "__nw_size"))
+ self.member = member
+
+def write_validate_switch_member(writer, container, switch_member, scope, parent_scope, start,
+ want_nw_size, want_mem_size, want_extra_size):
+ var = container.lookup_member(switch_member.variable)
+ var_type = var.member_type
+
+ v = write_read_primitive(writer, start, container, switch_member.variable, parent_scope)
+
+ item = MemberItemInfo(switch_member, container, start)
+
+ first = True
+ for c in switch_member.cases:
+ check = c.get_check(v, var_type)
+ m = c.member
+ with writer.if_block(check, not first, False) as if_scope:
+ item.type = c.member.member_type
+ item.subprefix = item.prefix + "_" + m.name
+ item.non_null = c.member.has_attr("nonnull")
+ sub_want_extra_size = want_extra_size
+ if sub_want_extra_size and not m.contains_extra_size():
+ writer.assign(item.extra_size(), 0)
+ sub_want_extra_size = False
+
+ write_validate_item(writer, container, item, if_scope, scope, start,
+ want_nw_size, want_mem_size, sub_want_extra_size)
+
+ first = False
+
+ with writer.block(" else"):
+ if want_nw_size:
+ writer.assign(item.nw_size(), 0)
+ if want_mem_size:
+ writer.assign(item.mem_size(), 0)
+ if want_extra_size:
+ writer.assign(item.extra_size(), 0)
+
+ writer.newline()
+
+def write_validate_struct_function(writer, struct):
+ validate_function = "validate_%s" % struct.c_type()
+ if writer.is_generated("validator", validate_function):
+ return validate_function
+
+ writer.set_is_generated("validator", validate_function)
+ writer = writer.function_helper()
+ scope = writer.function(validate_function, "intptr_t", "uint8_t *message_start, uint8_t *message_end, SPICE_ADDRESS offset, int minor")
+ scope.variable_def("uint8_t *", "start = message_start + offset")
+ scope.variable_def("SPICE_GNUC_UNUSED uint8_t *", "pos");
+ scope.variable_def("size_t", "mem_size", "nw_size");
+ num_pointers = struct.get_num_pointers()
+ if num_pointers != 0:
+ scope.variable_def("SPICE_GNUC_UNUSED intptr_t", "ptr_size");
+
+ writer.newline()
+ with writer.if_block("offset == 0"):
+ writer.statement("return 0")
+
+ writer.newline()
+ writer.error_check("start >= message_end")
+
+ writer.newline()
+ write_validate_container(writer, None, struct, "start", scope, True, True, False)
+
+ writer.newline()
+ writer.comment("Check if struct fits in reported side").newline()
+ writer.error_check("start + nw_size > message_end")
+
+ writer.statement("return mem_size")
+
+ writer.newline()
+ writer.label("error")
+ writer.statement("return -1")
+
+ writer.end_block()
+
+ return validate_function
+
+def write_validate_pointer_item(writer, container, item, scope, parent_scope, start,
+ want_nw_size, want_mem_size, want_extra_size):
+ if want_nw_size:
+ writer.assign(item.nw_size(), 8)
+
+ if want_mem_size or want_extra_size:
+ target_type = item.type.target_type
+
+ v = write_read_primitive_item(writer, item, scope)
+ if item.non_null:
+ writer.error_check("%s == 0" % v)
+
+ # pointer target is struct, or array of primitives
+ # if array, need no function check
+
+ if target_type.is_array():
+ writer.error_check("message_start + %s >= message_end" % v)
+
+
+ assert target_type.element_type.is_primitive()
+
+ array_item = ItemInfo(target_type, "%s__array" % item.prefix, start)
+ scope.variable_def("uint32_t", array_item.nw_size())
+ scope.variable_def("uint32_t", array_item.mem_size())
+ if target_type.is_cstring_length():
+ writer.assign(array_item.nw_size(), "spice_strnlen((char *)message_start + %s, message_end - (message_start + %s))" % (v, v))
+ writer.error_check("*(message_start + %s + %s) != 0" % (v, array_item.nw_size()))
+ writer.assign(array_item.mem_size(), array_item.nw_size())
+ else:
+ write_validate_array_item(writer, container, array_item, scope, parent_scope, start,
+ True, True, False)
+ writer.error_check("message_start + %s + %s > message_end" % (v, array_item.nw_size()))
+
+ if want_extra_size:
+ if item.member and item.member.has_attr("nocopy"):
+ writer.comment("@nocopy, so no extra size").newline()
+ writer.assign(item.extra_size(), 0)
+ elif target_type.element_type.get_fixed_nw_size == 1:
+ writer.assign(item.extra_size(), array_item.mem_size())
+ # If not bytes or zero, add padding needed for alignment
+ else:
+ writer.assign(item.extra_size(), "%s + /* for alignment */ 3" % array_item.mem_size())
+ if want_mem_size:
+ writer.assign(item.mem_size(), "sizeof(void *) + %s" % array_item.mem_size())
+
+ elif target_type.is_struct():
+ validate_function = write_validate_struct_function(writer, target_type)
+ writer.assign("ptr_size", "%s(message_start, message_end, %s, minor)" % (validate_function, v))
+ writer.error_check("ptr_size < 0")
+
+ if want_extra_size:
+ writer.assign(item.extra_size(), "ptr_size + /* for alignment */ 3")
+ if want_mem_size:
+ writer.assign(item.mem_size(), "sizeof(void *) + ptr_size")
+ else:
+ raise NotImplementedError("pointer to unsupported type %s" % target_type)
+
+
+def write_validate_array_item(writer, container, item, scope, parent_scope, start,
+ want_nw_size, want_mem_size, want_extra_size):
+ array = item.type
+ is_byte_size = False
+ element_type = array.element_type
+ if array.is_bytes_length():
+ nelements = "%s__nbytes" %(item.prefix)
+ else:
+ nelements = "%s__nelements" %(item.prefix)
+ if not parent_scope.variable_defined(nelements):
+ parent_scope.variable_def("uint32_t", nelements)
+
+ if array.is_constant_length():
+ writer.assign(nelements, array.size)
+ elif array.is_remaining_length():
+ if element_type.is_fixed_nw_size():
+ if element_type.get_fixed_nw_size() == 1:
+ writer.assign(nelements, "message_end - %s" % item.get_position())
+ else:
+ writer.assign(nelements, "(message_end - %s) / (%s)" %(item.get_position(), element_type.get_fixed_nw_size()))
+ else:
+ raise NotImplementedError("TODO array[] of dynamic element size not done yet")
+ elif array.is_identifier_length():
+ v = write_read_primitive(writer, start, container, array.size, scope)
+ writer.assign(nelements, v)
+ elif array.is_image_size_length():
+ bpp = array.size[1]
+ width = array.size[2]
+ rows = array.size[3]
+ width_v = write_read_primitive(writer, start, container, width, scope)
+ rows_v = write_read_primitive(writer, start, container, rows, scope)
+ # TODO: Handle multiplication overflow
+ if bpp == 8:
+ writer.assign(nelements, "%s * %s" % (width_v, rows_v))
+ elif bpp == 1:
+ writer.assign(nelements, "((%s + 7) / 8 ) * %s" % (width_v, rows_v))
+ else:
+ writer.assign(nelements, "((%s * %s + 7) / 8 ) * %s" % (bpp, width_v, rows_v))
+ elif array.is_bytes_length():
+ is_byte_size = True
+ v = write_read_primitive(writer, start, container, array.size[1], scope)
+ writer.assign(nelements, v)
+ elif array.is_cstring_length():
+ writer.todo("cstring array size type not handled yet")
+ else:
+ writer.todo("array size type not handled yet")
+
+ writer.newline()
+
+ nw_size = item.nw_size()
+ mem_size = item.mem_size()
+ extra_size = item.extra_size()
+
+ if is_byte_size and want_nw_size:
+ writer.assign(nw_size, nelements)
+ want_nw_size = False
+
+ if element_type.is_fixed_nw_size() and want_nw_size:
+ element_size = element_type.get_fixed_nw_size()
+ # TODO: Overflow check the multiplication
+ if element_size == 1:
+ writer.assign(nw_size, nelements)
+ else:
+ writer.assign(nw_size, "(%s) * %s" % (element_size, nelements))
+ want_nw_size = False
+
+ if element_type.is_fixed_sizeof() and want_mem_size and not is_byte_size:
+ # TODO: Overflow check the multiplication
+ writer.assign(mem_size, "%s * %s" % (element_type.sizeof(), nelements))
+ want_mem_size = False
+
+ if not element_type.contains_extra_size() and want_extra_size:
+ writer.assign(extra_size, 0)
+ want_extra_size = False
+
+ if not (want_mem_size or want_nw_size or want_extra_size):
+ return
+
+ start2 = codegen.increment_identifier(start)
+ scope.variable_def("uint8_t *", "%s = %s" % (start2, item.get_position()))
+ if is_byte_size:
+ start2_end = "%s_array_end" % start2
+ scope.variable_def("uint8_t *", start2_end)
+
+ element_item = ItemInfo(element_type, "%s__element" % item.prefix, start2)
+
+ element_nw_size = element_item.nw_size()
+ element_mem_size = element_item.mem_size()
+ scope.variable_def("uint32_t", element_nw_size)
+ scope.variable_def("uint32_t", element_mem_size)
+
+ if want_nw_size:
+ writer.assign(nw_size, 0)
+ if want_mem_size:
+ writer.assign(mem_size, 0)
+ if want_extra_size:
+ writer.assign(extra_size, 0)
+
+ want_element_nw_size = want_nw_size
+ if element_type.is_fixed_nw_size():
+ start_increment = element_type.get_fixed_nw_size()
+ else:
+ want_element_nw_size = True
+ start_increment = element_nw_size
+
+ if is_byte_size:
+ writer.assign(start2_end, "%s + %s" % (start2, nelements))
+
+ with writer.index(no_block = is_byte_size) as index:
+ with writer.while_loop("%s < %s" % (start2, start2_end) ) if is_byte_size else writer.for_loop(index, nelements) as scope:
+ write_validate_item(writer, container, element_item, scope, parent_scope, start2,
+ want_element_nw_size, want_mem_size, want_extra_size)
+
+ if want_nw_size:
+ writer.increment(nw_size, element_nw_size)
+ if want_mem_size:
+ writer.increment(mem_size, element_mem_size)
+ if want_extra_size:
+ writer.increment(extra_size, element_extra_size)
+
+ writer.increment(start2, start_increment)
+ if is_byte_size:
+ writer.error_check("%s != %s" % (start2, start2_end))
+
+def write_validate_struct_item(writer, container, item, scope, parent_scope, start,
+ want_nw_size, want_mem_size, want_extra_size):
+ struct = item.type
+ start2 = codegen.increment_identifier(start)
+ scope.variable_def("SPICE_GNUC_UNUSED uint8_t *", start2 + " = %s" % (item.get_position()))
+
+ write_validate_container(writer, item.prefix, struct, start2, scope, want_nw_size, want_mem_size, want_extra_size)
+
+def write_validate_primitive_item(writer, container, item, scope, parent_scope, start,
+ want_nw_size, want_mem_size, want_extra_size):
+ if want_nw_size:
+ nw_size = item.nw_size()
+ writer.assign(nw_size, item.type.get_fixed_nw_size())
+ if want_mem_size:
+ mem_size = item.mem_size()
+ writer.assign(mem_size, item.type.sizeof())
+ assert not want_extra_size
+
+def write_validate_item(writer, container, item, scope, parent_scope, start,
+ want_nw_size, want_mem_size, want_extra_size):
+ if item.type.is_pointer():
+ write_validate_pointer_item(writer, container, item, scope, parent_scope, start,
+ want_nw_size, want_mem_size, want_extra_size)
+ elif item.type.is_array():
+ write_validate_array_item(writer, container, item, scope, parent_scope, start,
+ want_nw_size, want_mem_size, want_extra_size)
+ elif item.type.is_struct():
+ write_validate_struct_item(writer, container, item, scope, parent_scope, start,
+ want_nw_size, want_mem_size, want_extra_size)
+ elif item.type.is_primitive():
+ write_validate_primitive_item(writer, container, item, scope, parent_scope, start,
+ want_nw_size, want_mem_size, want_extra_size)
+ else:
+ writer.todo("Implement validation of %s" % item.type)
+
+def write_validate_member(writer, container, member, parent_scope, start,
+ want_nw_size, want_mem_size, want_extra_size):
+ if member.has_minor_attr():
+ prefix = "if (minor >= %s)" % (member.get_minor_attr())
+ newline = False
+ else:
+ prefix = ""
+ newline = True
+ item = MemberItemInfo(member, container, start)
+ with writer.block(prefix, newline=newline, comment=member.name) as scope:
+ if member.is_switch():
+ write_validate_switch_member(writer, container, member, scope, parent_scope, start,
+ want_nw_size, want_mem_size, want_extra_size)
+ else:
+ write_validate_item(writer, container, item, scope, parent_scope, start,
+ want_nw_size, want_mem_size, want_extra_size)
+
+ if member.has_minor_attr():
+ with writer.block(" else", comment = "minor < %s" % (member.get_minor_attr())):
+ if member.is_array():
+ nelements = "%s__nelements" %(item.prefix)
+ writer.assign(nelements, 0)
+ if want_nw_size:
+ writer.assign(item.nw_size(), 0)
+
+ if want_mem_size:
+ if member.is_fixed_sizeof():
+ writer.assign(item.mem_size(), member.sizeof())
+ elif member.is_array():
+ writer.assign(item.mem_size(), 0)
+ else:
+ raise NotImplementedError("TODO minor check for non-constant items")
+
+ assert not want_extra_size
+
+def write_validate_container(writer, prefix, container, start, parent_scope, want_nw_size, want_mem_size, want_extra_size):
+ for m in container.members:
+ sub_want_nw_size = want_nw_size and not m.is_fixed_nw_size()
+ sub_want_mem_size = m.is_extra_size()
+ sub_want_extra_size = not m.is_extra_size() and m.contains_extra_size()
+
+ defs = ["size_t"]
+ if sub_want_nw_size:
+ defs.append (m.name + "__nw_size")
+ if sub_want_mem_size:
+ defs.append (m.name + "__mem_size")
+ if sub_want_extra_size:
+ defs.append (m.name + "__extra_size")
+
+ if sub_want_nw_size or sub_want_mem_size or sub_want_extra_size:
+ parent_scope.variable_def(*defs)
+ write_validate_member(writer, container, m, parent_scope, start,
+ sub_want_nw_size, sub_want_mem_size, sub_want_extra_size)
+ writer.newline()
+
+ if want_nw_size:
+ if prefix:
+ nw_size = prefix + "__nw_size"
+ else:
+ nw_size = "nw_size"
+
+ size = 0
+ for m in container.members:
+ if m.is_fixed_nw_size():
+ size = size + m.get_fixed_nw_size()
+
+ nm_sum = str(size)
+ for m in container.members:
+ if not m.is_fixed_nw_size():
+ nm_sum = nm_sum + " + " + m.name + "__nw_size"
+
+ writer.assign(nw_size, nm_sum)
+
+ if want_mem_size:
+ if prefix:
+ mem_size = prefix + "__mem_size"
+ else:
+ mem_size = "mem_size"
+
+ mem_sum = container.sizeof()
+ for m in container.members:
+ if m.is_extra_size():
+ mem_sum = mem_sum + " + " + m.name + "__mem_size"
+ elif m.contains_extra_size():
+ mem_sum = mem_sum + " + " + m.name + "__extra_size"
+
+ writer.assign(mem_size, mem_sum)
+
+ if want_extra_size:
+ if prefix:
+ extra_size = prefix + "__extra_size"
+ else:
+ extra_size = "extra_size"
+
+ extra_sum = []
+ for m in container.members:
+ if m.is_extra_size():
+ extra_sum.append(m.name + "__mem_size")
+ elif m.contains_extra_size():
+ extra_sum.append(m.name + "__extra_size")
+ writer.assign(extra_size, codegen.sum_array(extra_sum))
+
+class DemarshallingDestination:
+ def __init__(self):
+ pass
+
+ def child_at_end(self, writer, t):
+ return RootDemarshallingDestination(self, t.c_type(), t.sizeof())
+
+ def child_sub(self, member):
+ return SubDemarshallingDestination(self, member)
+
+ def declare(self, writer):
+ return writer.optional_block(self.reuse_scope)
+
+ def is_toplevel(self):
+ return self.parent_dest == None and not self.is_helper
+
+class RootDemarshallingDestination(DemarshallingDestination):
+ def __init__(self, parent_dest, c_type, sizeof, pointer = None):
+ self.is_helper = False
+ self.reuse_scope = None
+ self.parent_dest = parent_dest
+ if parent_dest:
+ self.base_var = codegen.increment_identifier(parent_dest.base_var)
+ else:
+ self.base_var = "out"
+ self.c_type = c_type
+ self.sizeof = sizeof
+ self.pointer = pointer # None == at "end"
+
+ def get_ref(self, member):
+ return self.base_var + "->" + member
+
+ def declare(self, writer):
+ if self.reuse_scope:
+ scope = self.reuse_scope
+ else:
+ writer.begin_block()
+ scope = writer.get_subwriter()
+
+ scope.variable_def(self.c_type + " *", self.base_var)
+ if not self.reuse_scope:
+ scope.newline()
+
+ if self.pointer:
+ writer.assign(self.base_var, "(%s *)%s" % (self.c_type, self.pointer))
+ else:
+ writer.assign(self.base_var, "(%s *)end" % (self.c_type))
+ writer.increment("end", self.sizeof)
+ writer.newline()
+
+ if self.reuse_scope:
+ return writer.no_block(self.reuse_scope)
+ else:
+ return writer.partial_block(scope)
+
+class SubDemarshallingDestination(DemarshallingDestination):
+ def __init__(self, parent_dest, member):
+ self.reuse_scope = None
+ self.parent_dest = parent_dest
+ self.base_var = parent_dest.base_var
+ self.member = member
+ self.is_helper = False
+
+ def get_ref(self, member):
+ return self.parent_dest.get_ref(self.member) + "." + member
+
+def read_array_len(writer, prefix, array, dest, scope, handles_bytes = False):
+ if array.is_bytes_length():
+ nelements = "%s__nbytes" % prefix
+ else:
+ nelements = "%s__nelements" % prefix
+ if dest.is_toplevel():
+ return nelements # Already there for toplevel, need not recalculate
+ element_type = array.element_type
+ scope.variable_def("uint32_t", nelements)
+ if array.is_constant_length():
+ writer.assign(nelements, array.size)
+ elif array.is_identifier_length():
+ writer.assign(nelements, dest.get_ref(array.size))
+ elif array.is_remaining_length():
+ if element_type.is_fixed_nw_size():
+ writer.assign(nelements, "(message_end - in) / (%s)" %(element_type.get_fixed_nw_size()))
+ else:
+ raise NotImplementedError("TODO array[] of dynamic element size not done yet")
+ elif array.is_image_size_length():
+ bpp = array.size[1]
+ width = array.size[2]
+ rows = array.size[3]
+ width_v = dest.get_ref(width)
+ rows_v = dest.get_ref(rows)
+ # TODO: Handle multiplication overflow
+ if bpp == 8:
+ writer.assign(nelements, "%s * %s" % (width_v, rows_v))
+ elif bpp == 1:
+ writer.assign(nelements, "((%s + 7) / 8 ) * %s" % (width_v, rows_v))
+ else:
+ writer.assign(nelements, "((%s * %s + 7) / 8 ) * %s" % (bpp, width_v, rows_v))
+ elif array.is_bytes_length():
+ if not handles_bytes:
+ raise NotImplementedError("handling of bytes() not supported here yet")
+ writer.assign(nelements, dest.get_ref(array.size[1]))
+ else:
+ raise NotImplementedError("TODO array size type not handled yet")
+ return nelements
+
+def write_switch_parser(writer, container, switch, dest, scope):
+ var = container.lookup_member(switch.variable)
+ var_type = var.member_type
+
+ if switch.has_attr("fixedsize"):
+ scope.variable_def("uint8_t *", "in_save")
+ writer.assign("in_save", "in")
+
+ first = True
+ for c in switch.cases:
+ check = c.get_check(dest.get_ref(switch.variable), var_type)
+ m = c.member
+ with writer.if_block(check, not first, False) as block:
+ t = m.member_type
+ if switch.has_end_attr():
+ dest2 = dest.child_at_end(writer, m.member_type)
+ elif switch.has_attr("anon"):
+ dest2 = dest
+ else:
+ if t.is_struct():
+ dest2 = dest.child_sub(switch.name + "." + m.name)
+ else:
+ dest2 = dest.child_sub(switch.name)
+ dest2.reuse_scope = block
+
+ if t.is_struct():
+ write_container_parser(writer, t, dest2)
+ elif t.is_pointer():
+ write_parse_pointer(writer, t, False, dest2, m.name, not m.has_attr("ptr32"), block)
+ elif t.is_primitive():
+ writer.assign(dest2.get_ref(m.name), "consume_%s(&in)" % (t.primitive_type()))
+ #TODO validate e.g. flags and enums
+ elif t.is_array():
+ nelements = read_array_len(writer, m.name, t, dest, block)
+ write_array_parser(writer, nelements, t, dest, block)
+ else:
+ writer.todo("Can't handle type %s" % m.member_type)
+
+ first = False
+
+ writer.newline()
+
+ if switch.has_attr("fixedsize"):
+ writer.assign("in", "in_save + %s" % switch.get_fixed_nw_size())
+
+def write_parse_ptr_function(writer, target_type):
+ if target_type.is_array():
+ parse_function = "parse_array_%s" % target_type.element_type.primitive_type()
+ else:
+ parse_function = "parse_struct_%s" % target_type.c_type()
+ if writer.is_generated("parser", parse_function):
+ return parse_function
+
+ writer.set_is_generated("parser", parse_function)
+
+ writer = writer.function_helper()
+ scope = writer.function(parse_function, "uint8_t *", "uint8_t *message_start, uint8_t *message_end, uint8_t *struct_data, PointerInfo *this_ptr_info, int minor")
+ scope.variable_def("uint8_t *", "in = message_start + this_ptr_info->offset")
+ scope.variable_def("uint8_t *", "end")
+
+ num_pointers = target_type.get_num_pointers()
+ if num_pointers != 0:
+ scope.variable_def("SPICE_GNUC_UNUSED intptr_t", "ptr_size");
+ scope.variable_def("uint32_t", "n_ptr=0");
+ scope.variable_def("PointerInfo", "ptr_info[%s]" % num_pointers)
+
+ writer.newline()
+ if target_type.is_array():
+ writer.assign("end", "struct_data")
+ else:
+ writer.assign("end", "struct_data + %s" % (target_type.sizeof()))
+
+ dest = RootDemarshallingDestination(None, target_type.c_type(), target_type.sizeof(), "struct_data")
+ dest.is_helper = True
+ dest.reuse_scope = scope
+ if target_type.is_array():
+ write_array_parser(writer, "this_ptr_info->nelements", target_type, dest, scope)
+ else:
+ write_container_parser(writer, target_type, dest)
+
+ if num_pointers != 0:
+ write_ptr_info_check(writer)
+
+ writer.statement("return end")
+
+ if writer.has_error_check:
+ writer.newline()
+ writer.label("error")
+ writer.statement("return NULL")
+
+ writer.end_block()
+
+ return parse_function
+
+def write_array_parser(writer, nelements, array, dest, scope):
+ is_byte_size = array.is_bytes_length()
+
+ element_type = array.element_type
+ if element_type == ptypes.uint8 or element_type == ptypes.int8:
+ writer.statement("memcpy(end, in, %s)" % (nelements))
+ writer.increment("in", nelements)
+ writer.increment("end", nelements)
+ else:
+ if is_byte_size:
+ scope.variable_def("uint8_t *", "array_end")
+ writer.assign("array_end", "end + %s" % nelements)
+ with writer.index(no_block = is_byte_size) as index:
+ with writer.while_loop("end < array_end") if is_byte_size else writer.for_loop(index, nelements) as array_scope:
+ if element_type.is_primitive():
+ writer.statement("*(%s *)end = consume_%s(&in)" % (element_type.c_type(), element_type.primitive_type()))
+ writer.increment("end", element_type.sizeof())
+ else:
+ dest2 = dest.child_at_end(writer, element_type)
+ dest2.reuse_scope = array_scope
+ write_container_parser(writer, element_type, dest2)
+
+def write_parse_pointer(writer, t, at_end, dest, member_name, is_64bit, scope):
+ target_type = t.target_type
+ if is_64bit:
+ writer.assign("ptr_info[n_ptr].offset", "consume_uint64(&in)")
+ else:
+ writer.assign("ptr_info[n_ptr].offset", "consume_uint32(&in)")
+ writer.assign("ptr_info[n_ptr].parse", write_parse_ptr_function(writer, target_type))
+ if at_end:
+ writer.assign("ptr_info[n_ptr].dest", "end")
+ writer.increment("end", "sizeof(SPICE_ADDRESS)");
+ else:
+ writer.assign("ptr_info[n_ptr].dest", "&%s" % dest.get_ref(member_name))
+ if target_type.is_array():
+ nelements = read_array_len(writer, member_name, target_type, dest, scope)
+ writer.assign("ptr_info[n_ptr].nelements", nelements)
+
+ writer.statement("n_ptr++")
+
+def write_member_parser(writer, container, member, dest, scope):
+ if member.is_switch():
+ write_switch_parser(writer, container, member, dest, scope)
+ return
+
+ t = member.member_type
+
+ if t.is_pointer():
+ if member.has_attr("nocopy"):
+ writer.comment("Reuse data from network message").newline()
+ writer.assign(dest.get_ref(member.name), "(size_t)(message_start + consume_uint64(&in))")
+ else:
+ write_parse_pointer(writer, t, member.has_end_attr(), dest, member.name, not member.has_attr("ptr32"), scope)
+ elif t.is_primitive():
+ if member.has_end_attr():
+ writer.statement("*(%s *)end = consume_%s(&in)" % (t.c_type(), t.primitive_type()))
+ writer.increment("end", t.sizeof())
+ else:
+ writer.assign(dest.get_ref(member.name), "consume_%s(&in)" % (t.primitive_type()))
+ #TODO validate e.g. flags and enums
+ elif t.is_array():
+ nelements = read_array_len(writer, member.name, t, dest, scope, handles_bytes = True)
+ write_array_parser(writer, nelements, t, dest, scope)
+ elif t.is_struct():
+ if member.has_end_attr():
+ dest2 = dest.child_at_end(writer, t)
+ else:
+ dest2 = dest.child_sub(member.name)
+ writer.comment(member.name)
+ write_container_parser(writer, t, dest2)
+ else:
+ raise NotImplementedError("TODO can't handle parsing of %s" % t)
+
+def write_container_parser(writer, container, dest):
+ with dest.declare(writer) as scope:
+ for m in container.members:
+ if m.has_minor_attr():
+ writer.begin_block("if (minor >= %s)" % m.get_minor_attr())
+ write_member_parser(writer, container, m, dest, scope)
+ if m.has_minor_attr():
+ # We need to zero out the fixed part of all optional fields
+ if not m.member_type.is_array():
+ writer.end_block(newline=False)
+ writer.begin_block(" else")
+ # TODO: This is not right for fields that don't exist in the struct
+ if m.member_type.is_primitive():
+ writer.assign(dest.get_ref(m.name), "0")
+ elif m.is_fixed_sizeof():
+ writer.statement("memset ((char *)&%s, 0, %s)" % (dest.get_ref(m.name), m.sizeof()))
+ else:
+ raise NotImplementedError("TODO Clear optional dynamic fields")
+ writer.end_block()
+
+def write_ptr_info_check(writer):
+ writer.newline()
+ with writer.index() as index:
+ with writer.for_loop(index, "n_ptr") as scope:
+ offset = "ptr_info[%s].offset" % index
+ function = "ptr_info[%s].parse" % index
+ dest = "ptr_info[%s].dest" % index
+ with writer.if_block("%s == 0" % offset, newline=False):
+ writer.assign("*%s" % dest, "0")
+ with writer.block(" else"):
+ writer.comment("Align to 32 bit").newline()
+ writer.assign("end", "(uint8_t *)SPICE_ALIGN((size_t)end, 4)")
+ writer.assign("*%s" % dest, "(size_t)end")
+ writer.assign("end", "%s(message_start, message_end, end, &ptr_info[%s], minor)" % (function, index))
+ writer.error_check("end == NULL")
+ writer.newline()
+
+def write_msg_parser(writer, message):
+ msg_name = message.c_name()
+ function_name = "parse_%s" % msg_name
+ if writer.is_generated("demarshaller", function_name):
+ return function_name
+ writer.set_is_generated("demarshaller", function_name)
+
+ msg_type = message.c_type()
+ msg_sizeof = message.sizeof()
+
+ writer.newline()
+ parent_scope = writer.function(function_name,
+ "uint8_t *",
+ "uint8_t *message_start, uint8_t *message_end, int minor, size_t *size", True)
+ parent_scope.variable_def("SPICE_GNUC_UNUSED uint8_t *", "pos");
+ parent_scope.variable_def("uint8_t *", "start = message_start");
+ parent_scope.variable_def("uint8_t *", "data = NULL");
+ parent_scope.variable_def("size_t", "mem_size", "nw_size");
+ if not message.has_attr("nocopy"):
+ parent_scope.variable_def("uint8_t *", "in", "end");
+ num_pointers = message.get_num_pointers()
+ if num_pointers != 0:
+ parent_scope.variable_def("SPICE_GNUC_UNUSED intptr_t", "ptr_size");
+ parent_scope.variable_def("uint32_t", "n_ptr=0");
+ parent_scope.variable_def("PointerInfo", "ptr_info[%s]" % num_pointers)
+ writer.newline()
+
+ write_parser_helpers(writer)
+
+ write_validate_container(writer, None, message, "start", parent_scope, True, True, False)
+
+ writer.newline()
+
+ writer.comment("Check if message fits in reported side").newline()
+ with writer.block("if (start + nw_size > message_end)"):
+ writer.statement("return NULL")
+
+ writer.newline().comment("Validated extents and calculated size").newline()
+
+ if message.has_attr("nocopy"):
+ writer.assign("data", "message_start")
+ writer.assign("*size", "message_end - message_start")
+ else:
+ writer.assign("data", "(uint8_t *)malloc(mem_size)")
+ writer.error_check("data == NULL")
+ writer.assign("end", "data + %s" % (msg_sizeof))
+ writer.assign("in", "start").newline()
+
+ dest = RootDemarshallingDestination(None, msg_type, msg_sizeof, "data")
+ dest.reuse_scope = parent_scope
+ write_container_parser(writer, message, dest)
+
+ writer.newline()
+ writer.statement("assert(in <= message_end)")
+
+ if num_pointers != 0:
+ write_ptr_info_check(writer)
+
+ writer.statement("assert(end <= data + mem_size)")
+
+ writer.newline()
+ writer.assign("*size", "end - data")
+
+ writer.statement("return data")
+ writer.newline()
+ if writer.has_error_check:
+ writer.label("error")
+ with writer.block("if (data != NULL)"):
+ writer.statement("free(data)")
+ writer.statement("return NULL")
+ writer.end_block()
+
+ return function_name
+
+def write_channel_parser(writer, channel, server):
+ writer.newline()
+ ids = {}
+ min_id = 1000000
+ if server:
+ messages = channel.server_messages
+ else:
+ messages = channel.client_messages
+ for m in messages:
+ ids[m.value] = m
+
+ ranges = []
+ ids2 = ids.copy()
+ while len(ids2) > 0:
+ end = start = min(ids2.keys())
+ while ids2.has_key(end):
+ del ids2[end]
+ end = end + 1
+
+ ranges.append( (start, end) )
+
+ if server:
+ function_name = "parse_%s_msg" % channel.name
+ else:
+ function_name = "parse_%s_msgc" % channel.name
+ writer.newline()
+ scope = writer.function(function_name,
+ "uint8_t *",
+ "uint8_t *message_start, uint8_t *message_end, uint16_t message_type, int minor, size_t *size_out")
+
+ helpers = writer.function_helper()
+
+ d = 0
+ for r in ranges:
+ d = d + 1
+ writer.write("static parse_msg_func_t funcs%d[%d] = " % (d, r[1] - r[0]));
+ writer.begin_block()
+ for i in range(r[0], r[1]):
+ func = write_msg_parser(helpers, ids[i].message_type)
+ writer.write(func)
+ if i != r[1] -1:
+ writer.write(",")
+ writer.newline()
+
+ writer.end_block(semicolon = True)
+
+ d = 0
+ for r in ranges:
+ d = d + 1
+ with writer.if_block("message_type >= %d && message_type < %d" % (r[0], r[1]), d > 1, False):
+ writer.statement("return funcs%d[message_type-%d](message_start, message_end, minor, size_out)" % (d, r[0]))
+ writer.newline()
+
+ writer.statement("return NULL")
+ writer.end_block()
+
+ return function_name
+
+def write_get_channel_parser(writer, channel_parsers, max_channel, is_server):
+ writer.newline()
+ if is_server:
+ function_name = "spice_get_server_channel_parser"
+ else:
+ function_name = "spice_get_client_channel_parser"
+
+ scope = writer.function(function_name,
+ "spice_parse_channel_func_t",
+ "uint32_t channel, unsigned int *max_message_type")
+
+ writer.write("static struct {spice_parse_channel_func_t func; unsigned int max_messages; } channels[%d] = " % (max_channel+1))
+ writer.begin_block()
+ for i in range(0, max_channel + 1):
+ writer.write("{ ")
+ if channel_parsers.has_key(i):
+ writer.write(channel_parsers[i][1])
+ writer.write(", ")
+
+ channel = channel_parsers[i][0]
+ max_msg = 0
+ if is_server:
+ messages = channel.server_messages
+ else:
+ messages = channel.client_messages
+ for m in messages:
+ max_msg = max(max_msg, m.value)
+ writer.write(max_msg)
+ else:
+ writer.write("NULL, 0")
+ writer.write("}")
+
+ if i != max_channel:
+ writer.write(",")
+ writer.newline()
+ writer.end_block(semicolon = True)
+
+ with writer.if_block("channel < %d" % (max_channel + 1)):
+ with writer.if_block("max_message_type != NULL"):
+ writer.assign("*max_message_type", "channels[channel].max_messages")
+ writer.statement("return channels[channel].func")
+
+ writer.statement("return NULL")
+ writer.end_block()
+
+
+def write_full_protocol_parser(writer, is_server):
+ writer.newline()
+ if is_server:
+ function_name = "spice_parse_msg"
+ else:
+ function_name = "spice_parse_reply"
+ scope = writer.function(function_name,
+ "uint8_t *",
+ "uint8_t *message_start, uint8_t *message_end, uint32_t channel, uint16_t message_type, int minor, size_t *size_out")
+ scope.variable_def("spice_parse_channel_func_t", "func" )
+
+ if is_server:
+ writer.assign("func", "spice_get_server_channel_parser(channel, NULL)")
+ else:
+ writer.assign("func", "spice_get_client_channel_parser(channel, NULL)")
+
+ with writer.if_block("func != NULL"):
+ writer.statement("return func(message_start, message_end, message_type, minor, size_out)")
+
+ writer.statement("return NULL")
+ writer.end_block()
+
+def write_protocol_parser(writer, proto, is_server):
+ max_channel = 0
+ parsers = {}
+
+ for channel in proto.channels:
+ max_channel = max(max_channel, channel.value)
+
+ parsers[channel.value] = (channel.channel_type, write_channel_parser(writer, channel.channel_type, is_server))
+
+ write_get_channel_parser(writer, parsers, max_channel, is_server)
+ write_full_protocol_parser(writer, is_server)
+
+def write_includes(writer):
+ writer.writeln("#include <string.h>")
+ writer.writeln("#include <assert.h>")
+ writer.writeln("#include <stdlib.h>")
+ writer.writeln("#include <stdio.h>")
+ writer.writeln("#include <spice/protocol.h>")
+ writer.writeln("#include <spice/macros.h>")
+ writer.newline()
+ writer.writeln("#ifdef _MSC_VER")
+ writer.writeln("#pragma warning(disable:4101)")
+ writer.writeln("#endif")
diff --git a/python_modules/ptypes.py b/python_modules/ptypes.py
new file mode 100644
index 0000000..fe8a321
--- /dev/null
+++ b/python_modules/ptypes.py
@@ -0,0 +1,965 @@
+import codegen
+import types
+
+_types_by_name = {}
+_types = []
+
+def type_exists(name):
+ return _types_by_name.has_key(name)
+
+def lookup_type(name):
+ return _types_by_name[name]
+
+def get_named_types():
+ return _types
+
+class FixedSize:
+ def __init__(self, val = 0, minor = 0):
+ if isinstance(val, FixedSize):
+ self.vals = val.vals
+ else:
+ self.vals = [0] * (minor + 1)
+ self.vals[minor] = val
+
+ def __add__(self, other):
+ if isinstance(other, types.IntType):
+ other = FixedSize(other)
+
+ new = FixedSize()
+ l = max(len(self.vals), len(other.vals))
+ shared = min(len(self.vals), len(other.vals))
+
+ new.vals = [0] * l
+
+ for i in range(shared):
+ new.vals[i] = self.vals[i] + other.vals[i]
+
+ for i in range(shared,len(self.vals)):
+ new.vals[i] = self.vals[i];
+
+ for i in range(shared,len(other.vals)):
+ new.vals[i] = new.vals[i] + other.vals[i];
+
+ return new
+
+ def __radd__(self, other):
+ return self.__add__(other)
+
+ def __str__(self):
+ s = "%d" % (self.vals[0])
+
+ for i in range(1,len(self.vals)):
+ if self.vals[i] > 0:
+ s = s + " + ((minor >= %d)?%d:0)" % (i, self.vals[i])
+ return s
+
+class Type:
+ def __init__(self):
+ self.attributes = {}
+ self.registred = False
+ self.name = None
+
+ def has_name(self):
+ return self.name != None
+
+ def get_type(self, recursive=False):
+ return self
+
+ def is_primitive(self):
+ return False
+
+ def is_fixed_sizeof(self):
+ return True
+
+ def is_extra_size(self):
+ return False
+
+ def contains_extra_size(self):
+ return False
+
+ def is_fixed_nw_size(self):
+ return True
+
+ def is_array(self):
+ return isinstance(self, ArrayType)
+
+ def is_struct(self):
+ return isinstance(self, StructType)
+
+ def is_pointer(self):
+ return isinstance(self, PointerType)
+
+ def get_num_pointers(self):
+ return 0
+
+ def get_pointer_names(self):
+ return []
+
+ def sizeof(self):
+ return "sizeof(%s)" % (self.c_type())
+
+ def __repr__(self):
+ return self.__str__()
+
+ def __str__(self):
+ if self.name != None:
+ return self.name
+ return "anonymous type"
+
+ def resolve(self):
+ return self
+
+ def register(self):
+ if self.registred or self.name == None:
+ return
+ self.registred = True
+ if _types_by_name.has_key(self.name):
+ raise Exception, "Type %s already defined" % self.name
+ _types.append(self)
+ _types_by_name[self.name] = self
+
+ def has_pointer(self):
+ return False
+
+ def has_attr(self, name):
+ return self.attributes.has_key(name)
+
+class TypeRef(Type):
+ def __init__(self, name):
+ Type.__init__(self)
+ self.name = name
+
+ def __str__(self):
+ return "ref to %s" % (self.name)
+
+ def resolve(self):
+ if not _types_by_name.has_key(self.name):
+ raise Exception, "Unknown type %s" % self.name
+ return _types_by_name[self.name]
+
+ def register(self):
+ assert True, "Can't register TypeRef!"
+
+
+class IntegerType(Type):
+ def __init__(self, bits, signed):
+ Type.__init__(self)
+ self.bits = bits
+ self.signed = signed
+
+ if signed:
+ self.name = "int%d" % bits
+ else:
+ self.name = "uint%d" % bits
+
+ def primitive_type(self):
+ return self.name
+
+ def c_type(self):
+ return self.name + "_t"
+
+ def get_fixed_nw_size(self):
+ return self.bits / 8
+
+ def is_primitive(self):
+ return True
+
+class TypeAlias(Type):
+ def __init__(self, name, the_type, attribute_list):
+ Type.__init__(self)
+ self.name = name
+ self.the_type = the_type
+ for attr in attribute_list:
+ self.attributes[attr[0][1:]] = attr[1:]
+
+ def get_type(self, recursive=False):
+ if recursive:
+ return self.the_type.get_type(True)
+ else:
+ return self.the_type
+
+ def primitive_type(self):
+ return self.the_type.primitive_type()
+
+ def resolve(self):
+ self.the_type = self.the_type.resolve()
+ return self
+
+ def __str__(self):
+ return "alias %s" % self.name
+
+ def is_primitive(self):
+ return self.the_type.is_primitive()
+
+ def is_fixed_sizeof(self):
+ return self.the_type.is_fixed_sizeof()
+
+ def is_fixed_nw_size(self):
+ return self.the_type.is_fixed_nw_size()
+
+ def get_fixed_nw_size(self):
+ return self.the_type.get_fixed_nw_size()
+
+ def get_num_pointers(self):
+ return self.the_type.get_num_pointers()
+
+ def get_pointer_names(self):
+ return self.the_type.get_pointer_names()
+
+ def c_type(self):
+ if self.has_attr("ctype"):
+ return self.attributes["ctype"][0]
+ return self.name
+
+ def has_pointer(self):
+ return self.the_type.has_pointer()
+
+class EnumBaseType(Type):
+ def is_enum(self):
+ return isinstance(self, EnumType)
+
+ def primitive_type(self):
+ return "uint%d" % (self.bits)
+
+ def c_type(self):
+ return "uint%d_t" % (self.bits)
+
+ def c_name(self):
+ return codegen.prefix_camel(self.name)
+
+ def c_enumname(self, value):
+ if self.has_attr("prefix"):
+ return self.attributes["prefix"][0] + self.names[value]
+ return codegen.prefix_underscore_upper(self.name.upper(), self.names[value])
+
+ def c_enumname_by_name(self, name):
+ if self.has_attr("prefix"):
+ return self.attributes["prefix"][0] + self.names[value]
+ return codegen.prefix_underscore_upper(self.name.upper(), name)
+
+ def is_primitive(self):
+ return True
+
+ def get_fixed_nw_size(self):
+ return self.bits / 8
+
+class EnumType(EnumBaseType):
+ def __init__(self, bits, name, enums, attribute_list):
+ Type.__init__(self)
+ self.bits = bits
+ self.name = name
+
+ last = -1
+ names = {}
+ values = {}
+ for v in enums:
+ name = v[0]
+ if len(v) > 1:
+ value = v[1]
+ else:
+ value = last + 1
+ last = value
+
+ assert not names.has_key(value)
+ names[value] = name
+ values[name] = value
+
+ self.names = names
+ self.values = values
+
+ for attr in attribute_list:
+ self.attributes[attr[0][1:]] = attr[1:]
+
+ def __str__(self):
+ return "enum %s" % self.name
+
+ def c_define(self, writer):
+ writer.write("enum ")
+ writer.write(self.c_name())
+ writer.begin_block()
+ values = self.names.keys()
+ values.sort()
+ current_default = 0
+ for i in values:
+ writer.write(self.c_enumname(i))
+ if i != current_default:
+ writer.write(" = %d" % (i))
+ writer.write(",")
+ writer.newline()
+ current_default = i + 1
+ writer.newline()
+ writer.write(codegen.prefix_underscore_upper(self.name.upper(), "ENUM_END"))
+ writer.newline()
+ writer.end_block(semicolon=True)
+ writer.newline()
+
+class FlagsType(EnumBaseType):
+ def __init__(self, bits, name, flags, attribute_list):
+ Type.__init__(self)
+ self.bits = bits
+ self.name = name
+
+ last = -1
+ names = {}
+ values = {}
+ for v in flags:
+ name = v[0]
+ if len(v) > 1:
+ value = v[1]
+ else:
+ value = last + 1
+ last = value
+
+ assert not names.has_key(value)
+ names[value] = name
+ values[name] = value
+
+ self.names = names
+ self.values = values
+
+ for attr in attribute_list:
+ self.attributes[attr[0][1:]] = attr[1:]
+
+ def __str__(self):
+ return "flags %s" % self.name
+
+ def c_define(self, writer):
+ writer.write("enum ")
+ writer.write(self.c_name())
+ writer.begin_block()
+ values = self.names.keys()
+ values.sort()
+ mask = 0
+ for i in values:
+ writer.write(self.c_enumname(i))
+ mask = mask | (1<<i)
+ writer.write(" = (1 << %d)" % (i))
+ writer.write(",")
+ writer.newline()
+ current_default = i + 1
+ writer.newline()
+ writer.write(codegen.prefix_underscore_upper(self.name.upper(), "MASK"))
+ writer.write(" = 0x%x" % (mask))
+ writer.newline()
+ writer.end_block(semicolon=True)
+ writer.newline()
+
+class ArrayType(Type):
+ def __init__(self, element_type, size):
+ Type.__init__(self)
+ self.name = None
+
+ self.element_type = element_type
+ self.size = size
+
+ def __str__(self):
+ if self.size == None:
+ return "%s[]" % (str(self.element_type))
+ else:
+ return "%s[%s]" % (str(self.element_type), str(self.size))
+
+ def resolve(self):
+ self.element_type = self.element_type.resolve()
+ return self
+
+ def is_constant_length(self):
+ return isinstance(self.size, types.IntType)
+
+ def is_remaining_length(self):
+ return isinstance(self.size, types.StringType) and len(self.size) == 0
+
+ def is_identifier_length(self):
+ return isinstance(self.size, types.StringType) and len(self.size) > 0
+
+ def is_image_size_length(self):
+ if isinstance(self.size, types.IntType) or isinstance(self.size, types.StringType):
+ return False
+ return self.size[0] == "image_size"
+
+ def is_bytes_length(self):
+ if isinstance(self.size, types.IntType) or isinstance(self.size, types.StringType):
+ return False
+ return self.size[0] == "bytes"
+
+ def is_cstring_length(self):
+ if isinstance(self.size, types.IntType) or isinstance(self.size, types.StringType):
+ return False
+ return self.size[0] == "cstring"
+
+ def is_fixed_sizeof(self):
+ return self.is_constant_length() and self.element_type.is_fixed_sizeof()
+
+ def is_fixed_nw_size(self):
+ return self.is_constant_length() and self.element_type.is_fixed_nw_size()
+
+ def get_fixed_nw_size(self):
+ if not self.is_fixed_nw_size():
+ raise Exception, "Not a fixed size type"
+
+ return self.element_type.get_fixed_nw_size() * self.size
+
+ def get_num_pointers(self):
+ element_count = self.element_type.get_num_pointers()
+ if element_count == 0:
+ return 0
+ if self.is_constant_length(self):
+ return element_count * self.size
+ raise Exception, "Pointers in dynamic arrays not supported"
+
+ def get_pointer_names(self):
+ element_count = self.element_type.get_num_pointers()
+ if element_count == 0:
+ return []
+ raise Exception, "Pointer names in arrays not supported"
+
+ def contains_extra_size(self):
+ return self.element_type.contains_extra_size()
+
+ def sizeof(self):
+ return "%s * %s" % (self.element_type.sizeof(), self.size)
+
+ def c_type(self):
+ return self.element_type.c_type()
+
+class PointerType(Type):
+ def __init__(self, target_type):
+ Type.__init__(self)
+ self.name = None
+ self.target_type = target_type
+
+ def __str__(self):
+ return "%s*" % (str(self.target_type))
+
+ def resolve(self):
+ self.target_type = self.target_type.resolve()
+ return self
+
+ def get_fixed_size(self):
+ return 8 # offsets are 64bit
+
+ def is_fixed_nw_size(self):
+ return True
+
+ def is_primitive(self):
+ return True
+
+ def primitive_type(self):
+ return "uint64"
+
+ def get_fixed_nw_size(self):
+ return 8
+
+ def c_type(self):
+ return "SPICE_ADDRESS"
+
+ def has_pointer(self):
+ return True
+
+ def contains_extra_size(self):
+ return True
+
+ def get_num_pointers(self):
+ return 1
+
+class Containee:
+ def __init__(self):
+ self.attributes = {}
+
+ def is_switch(self):
+ return False
+
+ def is_pointer(self):
+ return not self.is_switch() and self.member_type.is_pointer()
+
+ def is_array(self):
+ return not self.is_switch() and self.member_type.is_array()
+
+ def is_struct(self):
+ return not self.is_switch() and self.member_type.is_struct()
+
+ def is_primitive(self):
+ return not self.is_switch() and self.member_type.is_primitive()
+
+ def has_attr(self, name):
+ return self.attributes.has_key(name)
+
+ def has_minor_attr(self):
+ return self.has_attr("minor")
+
+ def has_end_attr(self):
+ return self.has_attr("end")
+
+ def get_minor_attr(self):
+ return self.attributes["minor"][0]
+
+class Member(Containee):
+ def __init__(self, name, member_type, attribute_list):
+ Containee.__init__(self)
+ self.name = name
+ self.member_type = member_type
+ for attr in attribute_list:
+ self.attributes[attr[0][1:]] = attr[1:]
+
+ def resolve(self, container):
+ self.container = container
+ self.member_type = self.member_type.resolve()
+ self.member_type.register()
+ return self
+
+ def is_primitive(self):
+ return self.member_type.is_primitive()
+
+ def is_fixed_sizeof(self):
+ if self.has_end_attr():
+ return False
+ return self.member_type.is_fixed_sizeof()
+
+ def is_extra_size(self):
+ return self.has_end_attr()
+
+ def is_fixed_nw_size(self):
+ return self.member_type.is_fixed_nw_size()
+
+ def get_fixed_nw_size(self):
+ size = self.member_type.get_fixed_nw_size()
+ if self.has_minor_attr():
+ minor = self.get_minor_attr()
+ size = FixedSize(size, minor)
+ return size
+
+ def contains_extra_size(self):
+ return self.member_type.contains_extra_size()
+
+ def sizeof(self):
+ return self.member_type.sizeof()
+
+ def __repr__(self):
+ return "%s (%s)" % (str(self.name), str(self.member_type))
+
+ def has_pointer(self):
+ return self.member_type.has_pointer()
+
+ def get_num_pointers(self):
+ return self.member_type.get_num_pointers()
+
+ def get_pointer_names(self):
+ if self.member_type.is_pointer():
+ names = [self.name + "_out"]
+ else:
+ names = self.member_type.get_pointer_names()
+ if self.has_attr("outvar"):
+ prefix = self.attributes["outvar"][0]
+ names = map(lambda name: prefix + "_" + name, names)
+ return names
+
+class SwitchCase:
+ def __init__(self, values, member):
+ self.values = values
+ self.member = member
+ self.members = [member]
+
+ def get_check(self, var_cname, var_type):
+ checks = []
+ for v in self.values:
+ if v == None:
+ return "1"
+ elif var_type.is_enum():
+ checks.append("%s == %s" % (var_cname, var_type.c_enumname_by_name(v)))
+ else:
+ checks.append("(%s & %s)" % (var_cname, var_type.c_enumname_by_name(v)))
+ return " || ".join(checks)
+
+ def resolve(self, container):
+ self.switch = container
+ self.member = self.member.resolve(self)
+ return self
+
+ def has_pointer(self):
+ return self.member.has_pointer()
+
+ def get_num_pointers(self):
+ return self.member.get_num_pointers()
+
+ def get_pointer_names(self):
+ return self.member.get_pointer_names()
+
+class Switch(Containee):
+ def __init__(self, variable, cases, name, attribute_list):
+ Containee.__init__(self)
+ self.variable = variable
+ self.name = name
+ self.cases = cases
+ for attr in attribute_list:
+ self.attributes[attr[0][1:]] = attr[1:]
+
+ def is_switch(self):
+ return True
+
+ def has_switch_member(self, member):
+ for c in self.cases:
+ if c.member == member:
+ return True
+ return False
+
+ def resolve(self, container):
+ self.container = container
+ self.cases = map(lambda c : c.resolve(self), self.cases)
+ return self
+
+ def __repr__(self):
+ return "switch on %s %s" % (str(self.variable),str(self.name))
+
+ def is_fixed_sizeof(self):
+ # Kinda weird, but we're unlikely to have a real struct if there is an @end
+ if self.has_end_attr():
+ return False
+ return True
+
+ def is_fixed_nw_size(self):
+ if self.has_attr("fixedsize"):
+ return True
+
+ size = None
+ for c in self.cases:
+ if not c.member.is_fixed_nw_size():
+ return False
+ if size == None:
+ size = c.member.get_fixed_nw_size()
+ elif size != c.member.get_fixed_nw_size():
+ return False
+ return True
+
+ def is_extra_size(self):
+ return self.has_end_attr()
+
+ def contains_extra_size(self):
+ for c in self.cases:
+ if c.member.is_extra_size():
+ return True
+ if c.member.contains_extra_size():
+ return True
+ return False
+
+ def get_fixed_nw_size(self):
+ if not self.is_fixed_nw_size():
+ raise Exception, "Not a fixed size type"
+ size = 0;
+ for c in self.cases:
+ size = max(size, c.member.get_fixed_nw_size())
+ return size
+
+ def sizeof(self):
+ return "sizeof(((%s *)NULL)->%s)" % (self.container.c_type(),
+ self.name)
+
+ def has_pointer(self):
+ for c in self.cases:
+ if c.has_pointer():
+ return True
+ return False
+
+ def get_num_pointers(self):
+ count = 0
+ for c in self.cases:
+ count = max(count, c.get_num_pointers())
+ return count
+
+ def get_pointer_names(self):
+ names = []
+ for c in self.cases:
+ names = names + c.get_pointer_names()
+ return names
+
+class ContainerType(Type):
+ def is_fixed_sizeof(self):
+ for m in self.members:
+ if not m.is_fixed_sizeof():
+ return False
+ return True
+
+ def contains_extra_size(self):
+ for m in self.members:
+ if m.is_extra_size():
+ return True
+ if m.contains_extra_size():
+ return True
+ return False
+
+ def is_fixed_nw_size(self):
+ for i in self.members:
+ if not i.is_fixed_nw_size():
+ return False
+ return True
+
+ def get_fixed_nw_size(self):
+ size = 0
+ for i in self.members:
+ size = size + i.get_fixed_nw_size()
+ return size
+
+ def get_fixed_nw_offset(self, member):
+ size = 0
+ for i in self.members:
+ if i == member:
+ break
+ if i.is_fixed_nw_size():
+ size = size + i.get_fixed_nw_size()
+ return size
+
+ def resolve(self):
+ self.members = map(lambda m : m.resolve(self), self.members)
+ return self
+
+ def get_num_pointers(self):
+ count = 0
+ for m in self.members:
+ count = count + m.get_num_pointers()
+ return count
+
+ def get_pointer_names(self):
+ names = []
+ for m in self.members:
+ names = names + m.get_pointer_names()
+ return names
+
+ def has_pointer(self):
+ for m in self.members:
+ if m.has_pointer():
+ return True
+ return False
+
+ def get_nw_offset(self, member, prefix = "", postfix = ""):
+ fixed = self.get_fixed_nw_offset(member)
+ v = []
+ for m in self.members:
+ if m == member:
+ break
+ if m.is_switch() and m.has_switch_member(member):
+ break
+ if not m.is_fixed_nw_size():
+ v.append(prefix + m.name + postfix)
+ if len(v) > 0:
+ return str(fixed) + " + " + (" + ".join(v))
+ else:
+ return str(fixed)
+
+ def lookup_member(self, name):
+ return self.members_by_name[name]
+
+class StructType(ContainerType):
+ def __init__(self, name, members, attribute_list):
+ Type.__init__(self)
+ self.name = name
+ self.members = members
+ self.members_by_name = {}
+ for m in members:
+ self.members_by_name[m.name] = m
+ for attr in attribute_list:
+ self.attributes[attr[0][1:]] = attr[1:]
+
+ def __str__(self):
+ if self.name == None:
+ return "anonymous struct"
+ else:
+ return "struct %s" % self.name
+
+ def c_type(self):
+ if self.has_attr("ctype"):
+ return self.attributes["ctype"][0]
+ return codegen.prefix_camel(self.name)
+
+class MessageType(ContainerType):
+ def __init__(self, name, members, attribute_list):
+ Type.__init__(self)
+ self.name = name
+ self.members = members
+ self.members_by_name = {}
+ for m in members:
+ self.members_by_name[m.name] = m
+ self.reverse_members = {} # ChannelMembers referencing this message
+ for attr in attribute_list:
+ self.attributes[attr[0][1:]] = attr[1:]
+
+ def __str__(self):
+ if self.name == None:
+ return "anonymous message"
+ else:
+ return "message %s" % self.name
+
+ def c_name(self):
+ if self.name == None:
+ cms = self.reverse_members.keys()
+ if len(cms) != 1:
+ raise "Unknown typename for message"
+ cm = cms[0]
+ channelname = cm.channel.member_name
+ if channelname == None:
+ channelname = ""
+ else:
+ channelname = channelname + "_"
+ if cm.is_server:
+ return "msg_" + channelname + cm.name
+ else:
+ return "msgc_" + channelname + cm.name
+ else:
+ return codegen.prefix_camel("Msg", self.name)
+
+ def c_type(self):
+ if self.has_attr("ctype"):
+ return self.attributes["ctype"][0]
+ if self.name == None:
+ cms = self.reverse_members.keys()
+ if len(cms) != 1:
+ raise "Unknown typename for message"
+ cm = cms[0]
+ channelname = cm.channel.member_name
+ if channelname == None:
+ channelname = ""
+ if cm.is_server:
+ return codegen.prefix_camel("Msg", channelname, cm.name)
+ else:
+ return codegen.prefix_camel("Msgc", channelname, cm.name)
+ else:
+ return codegen.prefix_camel("Msg", self.name)
+
+class ChannelMember(Containee):
+ def __init__(self, name, message_type, value):
+ Containee.__init__(self)
+ self.name = name
+ self.message_type = message_type
+ self.value = value
+
+ def resolve(self, channel):
+ self.channel = channel
+ self.message_type = self.message_type.resolve()
+ self.message_type.reverse_members[self] = 1
+
+ return self
+
+ def __repr__(self):
+ return "%s (%s)" % (str(self.name), str(self.message_type))
+
+class ChannelType(Type):
+ def __init__(self, name, base, members):
+ Type.__init__(self)
+ self.name = name
+ self.base = base
+ self.member_name = None
+ self.members = members
+
+ def __str__(self):
+ if self.name == None:
+ return "anonymous channel"
+ else:
+ return "channel %s" % self.name
+
+ def is_fixed_nw_size(self):
+ return False
+
+ def get_client_message(self, name):
+ return self.client_messages_byname[name]
+
+ def get_server_message(self, name):
+ return self.server_messages_byname[name]
+
+ def resolve(self):
+ if self.base != None:
+ self.base = self.base.resolve()
+
+ server_messages = self.base.server_messages[:]
+ server_messages_byname = self.base.server_messages_byname.copy()
+ client_messages = self.base.client_messages[:]
+ client_messages_byname = self.base.client_messages_byname.copy()
+ else:
+ server_messages = []
+ server_messages_byname = {}
+ client_messages = []
+ client_messages_byname = {}
+
+ server_count = 1
+ client_count = 1
+
+ server = True
+ for m in self.members:
+ if m == "server":
+ server = True
+ elif m == "client":
+ server = False
+ elif server:
+ m.is_server = True
+ m = m.resolve(self)
+ if m.value:
+ server_count = m.value + 1
+ else:
+ m.value = server_count
+ server_count = server_count + 1
+ server_messages.append(m)
+ server_messages_byname[m.name] = m
+ else:
+ m.is_server = False
+ m = m.resolve(self)
+ if m.value:
+ client_count = m.value + 1
+ else:
+ m.value = client_count
+ client_count = client_count + 1
+ client_messages.append(m)
+ client_messages_byname[m.name] = m
+
+ self.server_messages = server_messages
+ self.server_messages_byname = server_messages_byname
+ self.client_messages = client_messages
+ self.client_messages_byname = client_messages_byname
+
+ return self
+
+class ProtocolMember:
+ def __init__(self, name, channel_type, value):
+ self.name = name
+ self.channel_type = channel_type
+ self.value = value
+
+ def resolve(self, protocol):
+ self.channel_type = self.channel_type.resolve()
+ assert(self.channel_type.member_name == None)
+ self.channel_type.member_name = self.name
+ return self
+
+ def __repr__(self):
+ return "%s (%s)" % (str(self.name), str(self.channel_type))
+
+class ProtocolType(Type):
+ def __init__(self, name, channels):
+ Type.__init__(self)
+ self.name = name
+ self.channels = channels
+
+ def __str__(self):
+ if self.name == None:
+ return "anonymous protocol"
+ else:
+ return "protocol %s" % self.name
+
+ def is_fixed_nw_size(self):
+ return False
+
+ def resolve(self):
+ count = 1
+ for m in self.channels:
+ m = m.resolve(self)
+ if m.value:
+ count = m.value + 1
+ else:
+ m.value = count
+ count = count + 1
+
+ return self
+
+int8 = IntegerType(8, True)
+uint8 = IntegerType(8, False)
+int16 = IntegerType(16, True)
+uint16 = IntegerType(16, False)
+int32 = IntegerType(32, True)
+uint32 = IntegerType(32, False)
+int64 = IntegerType(64, True)
+uint64 = IntegerType(64, False)
diff --git a/python_modules/spice_parser.py b/python_modules/spice_parser.py
new file mode 100644
index 0000000..65916b3
--- /dev/null
+++ b/python_modules/spice_parser.py
@@ -0,0 +1,157 @@
+from pyparsing import Literal, CaselessLiteral, Word, OneOrMore, ZeroOrMore, \
+ Forward, delimitedList, Group, Optional, Combine, alphas, nums, restOfLine, cStyleComment, \
+ alphanums, ParseException, ParseResults, Keyword, StringEnd, replaceWith
+
+import ptypes
+import sys
+
+cvtInt = lambda toks: int(toks[0])
+
+def parseVariableDef(toks):
+ t = toks[0][0]
+ pointer = toks[0][1]
+ name = toks[0][2]
+ array_size = toks[0][3]
+ attributes = toks[0][4]
+
+ if array_size != None:
+ t = ptypes.ArrayType(t, array_size)
+
+ if pointer != None:
+ t = ptypes.PointerType(t);
+
+ return ptypes.Member(name, t, attributes)
+
+bnf = None
+def SPICE_BNF():
+ global bnf
+
+ if not bnf:
+
+ # punctuation
+ colon = Literal(":").suppress()
+ lbrace = Literal("{").suppress()
+ rbrace = Literal("}").suppress()
+ lbrack = Literal("[").suppress()
+ rbrack = Literal("]").suppress()
+ lparen = Literal("(").suppress()
+ rparen = Literal(")").suppress()
+ equals = Literal("=").suppress()
+ comma = Literal(",").suppress()
+ semi = Literal(";").suppress()
+
+ # primitive types
+ int8_ = Keyword("int8").setParseAction(replaceWith(ptypes.int8))
+ uint8_ = Keyword("uint8").setParseAction(replaceWith(ptypes.uint8))
+ int16_ = Keyword("int16").setParseAction(replaceWith(ptypes.int16))
+ uint16_ = Keyword("uint16").setParseAction(replaceWith(ptypes.uint16))
+ int32_ = Keyword("int32").setParseAction(replaceWith(ptypes.int32))
+ uint32_ = Keyword("uint32").setParseAction(replaceWith(ptypes.uint32))
+ int64_ = Keyword("int64").setParseAction(replaceWith(ptypes.int64))
+ uint64_ = Keyword("uint64").setParseAction(replaceWith(ptypes.uint64))
+
+ # keywords
+ channel_ = Keyword("channel")
+ enum32_ = Keyword("enum32").setParseAction(replaceWith(32))
+ enum16_ = Keyword("enum16").setParseAction(replaceWith(16))
+ enum8_ = Keyword("enum8").setParseAction(replaceWith(8))
+ flags32_ = Keyword("flags32").setParseAction(replaceWith(32))
+ flags16_ = Keyword("flags16").setParseAction(replaceWith(16))
+ flags8_ = Keyword("flags8").setParseAction(replaceWith(8))
+ channel_ = Keyword("channel")
+ server_ = Keyword("server")
+ client_ = Keyword("client")
+ protocol_ = Keyword("protocol")
+ typedef_ = Keyword("typedef")
+ struct_ = Keyword("struct")
+ message_ = Keyword("message")
+ image_size_ = Keyword("image_size")
+ bytes_ = Keyword("bytes")
+ cstring_ = Keyword("cstring")
+ switch_ = Keyword("switch")
+ default_ = Keyword("default")
+ case_ = Keyword("case")
+
+ identifier = Word( alphas, alphanums + "_" )
+ enumname = Word( alphanums + "_" )
+
+ integer = ( Combine( CaselessLiteral("0x") + Word( nums+"abcdefABCDEF" ) ) |
+ Word( nums+"+-", nums ) ).setName("int").setParseAction(cvtInt)
+
+ typename = identifier.copy().setParseAction(lambda toks : ptypes.TypeRef(str(toks[0])))
+
+ # This is just normal "types", i.e. not channels or messages
+ typeSpec = Forward()
+
+ attributeValue = integer ^ identifier
+ attribute = Group(Combine ("@" + identifier) + Optional(lparen + delimitedList(attributeValue) + rparen))
+ attributes = Group(ZeroOrMore(attribute))
+ arraySizeSpecImage = Group(image_size_ + lparen + integer + comma + identifier + comma + identifier + rparen)
+ arraySizeSpecBytes = Group(bytes_ + lparen + identifier + rparen)
+ arraySizeSpecCString = Group(cstring_ + lparen + rparen)
+ arraySizeSpec = lbrack + Optional(identifier ^ integer ^ arraySizeSpecImage ^ arraySizeSpecBytes ^arraySizeSpecCString, default="") + rbrack
+ variableDef = Group(typeSpec + Optional("*", default=None) + identifier + Optional(arraySizeSpec, default=None) + attributes - semi) \
+ .setParseAction(parseVariableDef)
+
+ switchCase = Group(Group(OneOrMore(default_.setParseAction(replaceWith(None)) + colon | case_.suppress() + identifier + colon)) + variableDef) \
+ .setParseAction(lambda toks: ptypes.SwitchCase(toks[0][0], toks[0][1]))
+ switchBody = Group(switch_ + lparen + identifier + rparen + lbrace + Group(OneOrMore(switchCase)) + rbrace + identifier + attributes - semi) \
+ .setParseAction(lambda toks: ptypes.Switch(toks[0][1], toks[0][2], toks[0][3], toks[0][4]))
+ messageBody = structBody = Group(lbrace + ZeroOrMore(variableDef | switchBody) + rbrace)
+ structSpec = Group(struct_ + identifier + structBody + attributes).setParseAction(lambda toks: ptypes.StructType(toks[0][1], toks[0][2], toks[0][3]))
+
+ # have to use longest match for type, in case a user-defined type name starts with a keyword type, like "channel_type"
+ typeSpec << ( structSpec ^ int8_ ^ uint8_ ^ int16_ ^ uint16_ ^
+ int32_ ^ uint32_ ^ int64_ ^ uint64_ ^
+ typename).setName("type")
+
+ flagsBody = enumBody = Group(lbrace + delimitedList(Group (enumname + Optional(equals + integer))) + Optional(comma) + rbrace)
+
+ messageSpec = Group(message_ + messageBody + attributes).setParseAction(lambda toks: ptypes.MessageType(None, toks[0][1], toks[0][2])) | typename
+
+ channelParent = Optional(colon + typename, default=None)
+ channelMessage = Group(messageSpec + identifier + Optional(equals + integer, default=None) + semi) \
+ .setParseAction(lambda toks: ptypes.ChannelMember(toks[0][1], toks[0][0], toks[0][2]))
+ channelBody = channelParent + Group(lbrace + ZeroOrMore( server_ + colon | client_ + colon | channelMessage) + rbrace)
+
+ enum_ = (enum32_ | enum16_ | enum8_)
+ flags_ = (flags32_ | flags16_ | flags8_)
+ enumDef = Group(enum_ + identifier + enumBody + attributes - semi).setParseAction(lambda toks: ptypes.EnumType(toks[0][0], toks[0][1], toks[0][2], toks[0][3]))
+ flagsDef = Group(flags_ + identifier + flagsBody + attributes - semi).setParseAction(lambda toks: ptypes.FlagsType(toks[0][0], toks[0][1], toks[0][2], toks[0][3]))
+ messageDef = Group(message_ + identifier + messageBody + attributes - semi).setParseAction(lambda toks: ptypes.MessageType(toks[0][1], toks[0][2], toks[0][3]))
+ channelDef = Group(channel_ + identifier + channelBody - semi).setParseAction(lambda toks: ptypes.ChannelType(toks[0][1], toks[0][2], toks[0][3]))
+ structDef = Group(struct_ + identifier + structBody + attributes - semi).setParseAction(lambda toks: ptypes.StructType(toks[0][1], toks[0][2], toks[0][3]))
+ typedefDef = Group(typedef_ + identifier + typeSpec + attributes - semi).setParseAction(lambda toks: ptypes.TypeAlias(toks[0][1], toks[0][2], toks[0][3]))
+
+ definitions = typedefDef | structDef | enumDef | flagsDef | messageDef | channelDef
+
+ protocolChannel = Group(typename + identifier + Optional(equals + integer, default=None) + semi) \
+ .setParseAction(lambda toks: ptypes.ProtocolMember(toks[0][1], toks[0][0], toks[0][2]))
+ protocolDef = Group(protocol_ + identifier + Group(lbrace + ZeroOrMore(protocolChannel) + rbrace) + semi) \
+ .setParseAction(lambda toks: ptypes.ProtocolType(toks[0][1], toks[0][2]))
+
+ bnf = ZeroOrMore (definitions) + protocolDef + StringEnd()
+
+ singleLineComment = "//" + restOfLine
+ bnf.ignore( singleLineComment )
+ bnf.ignore( cStyleComment )
+
+ return bnf
+
+
+def parse(filename):
+ try:
+ bnf = SPICE_BNF()
+ types = bnf.parseFile(filename)
+ except ParseException, err:
+ print >> sys.stderr, err.line
+ print >> sys.stderr, " "*(err.column-1) + "^"
+ print >> sys.stderr, err
+ return None
+
+ for t in types:
+ t.resolve()
+ t.register()
+ protocol = types[-1]
+ return protocol
+
diff --git a/spice.proto b/spice.proto
new file mode 100644
index 0000000..dec6a63
--- /dev/null
+++ b/spice.proto
@@ -0,0 +1,1086 @@
+/* built in types:
+ int8, uint8, 16, 32, 64
+*/
+
+typedef fixed28_4 int32 @ctype(SPICE_FIXED28_4);
+
+struct Point {
+ int32 x;
+ int32 y;
+};
+
+struct Point16 {
+ int16 x;
+ int16 y;
+};
+
+struct PointFix {
+ fixed28_4 x;
+ fixed28_4 y;
+};
+
+struct Rect {
+ int32 top;
+ int32 left;
+ int32 bottom;
+ int32 right;
+};
+
+enum32 link_err {
+ OK,
+ ERROR,
+ INVALID_MAGIC,
+ INVALID_DATA,
+ VERSION_MISMATCH,
+ NEED_SECURED,
+ NEED_UNSECURED,
+ PERMISSION_DENIED,
+ BAD_CONNECTION_ID,
+ CHANNEL_NOT_AVAILABLE
+};
+
+enum32 warn_code {
+ WARN_GENERAL
+} @prefix(SPICE_);
+
+enum32 info_code {
+ INFO_GENERAL
+} @prefix(SPICE_);
+
+flags32 migrate_flags {
+ NEED_FLUSH,
+ NEED_DATA_TRANSFER
+} @prefix(SPICE_MIGRATE_);
+
+enum32 notify_severity {
+ INFO,
+ WARN,
+ ERROR,
+};
+
+enum32 notify_visibility {
+ LOW,
+ MEDIUM,
+ HIGH,
+};
+
+flags32 mouse_mode {
+ SERVER,
+ CLIENT,
+};
+
+enum16 pubkey_type {
+ INVALID,
+ RSA,
+ RSA2,
+ DSA,
+ DSA1,
+ DSA2,
+ DSA3,
+ DSA4,
+ DH,
+ EC,
+};
+
+message Empty {
+};
+
+message Data {
+ uint8 data[] @end @ctype(uint8_t);
+} @nocopy;
+
+struct ChannelWait {
+ uint8 channel_type;
+ uint8 channel_id;
+ uint64 message_serial;
+} @ctype(SpiceWaitForChannel);
+
+channel BaseChannel {
+ server:
+ message {
+ migrate_flags flags;
+ } migrate;
+
+ Data migrate_data;
+
+ message {
+ uint32 generation;
+ uint32 window;
+ } set_ack;
+
+ message {
+ uint32 id;
+ uint64 timestamp;
+ uint8 data[] @end @ctype(uint8_t);
+ } ping;
+
+ message {
+ uint8 wait_count;
+ ChannelWait wait_list[wait_count] @end;
+ } wait_for_channels;
+
+ message {
+ uint64 time_stamp;
+ link_err reason;
+ } @ctype(SpiceMsgDisconnect) disconnecting;
+
+ message {
+ uint64 time_stamp;
+ notify_severity severity;
+ notify_visibility visibilty;
+ uint32 what; /* error_code/warn_code/info_code */
+ uint32 message_len;
+ uint8 message[message_len] @end;
+ uint8 zero @end @ctype(uint8_t) @zero;
+ } notify;
+
+ client:
+ message {
+ uint32 generation;
+ } ack_sync;
+
+ Empty ack;
+
+ message {
+ uint32 id;
+ uint64 timestamp;
+ } @ctype(SpiceMsgPing) pong;
+
+ Empty migrate_flush_mark;
+
+ Data migrate_data;
+
+ message {
+ uint64 time_stamp;
+ link_err reason;
+ } @ctype(SpiceMsgDisconnect) disconnecting;
+};
+
+struct ChannelId {
+ uint8 type;
+ uint8 id;
+};
+
+channel MainChannel : BaseChannel {
+ server:
+ message {
+ uint16 port;
+ uint16 sport;
+ uint32 host_offset;
+ uint32 host_size;
+ pubkey_type pub_key_type @minor(2);
+ uint32 pub_key_offset @minor(2);
+ uint32 pub_key_size @minor(2);
+ uint8 host_data[host_size] @end @ctype(uint8_t) @zero_terminated;
+ uint8 pub_key_data[pub_key_size] @minor(2) @end @ctype(uint8_t) @zero_terminated;
+ } @ctype(SpiceMsgMainMigrationBegin) migrate_begin = 101;
+
+ Empty migrate_cancel;
+
+ message {
+ uint32 session_id;
+ uint32 display_channels_hint;
+ uint32 supported_mouse_modes;
+ uint32 current_mouse_mode;
+ uint32 agent_connected;
+ uint32 agent_tokens;
+ uint32 multi_media_time;
+ uint32 ram_hint;
+ } init;
+
+ message {
+ uint32 num_of_channels;
+ ChannelId channels[num_of_channels] @end;
+ } @ctype(SpiceMsgChannels) channels_list;
+
+ message {
+ mouse_mode supported_modes;
+ mouse_mode current_mode @unique_flag;
+ } mouse_mode;
+
+ message {
+ uint32 time;
+ } @ctype(SpiceMsgMainMultiMediaTime) multi_media_time;
+
+ Empty agent_connected;
+
+ message {
+ link_err error_code;
+ } @ctype(SpiceMsgMainAgentDisconnect) agent_disconnected;
+
+ Data agent_data;
+
+ message {
+ uint32 num_tokens;
+ } @ctype(SpiceMsgMainAgentTokens) agent_token;
+
+ message {
+ uint16 port;
+ uint16 sport;
+ uint32 host_offset;
+ uint32 host_size;
+ uint32 cert_subject_offset;
+ uint32 cert_subject_size;
+ uint8 host_data[host_size] @end @ctype(uint8_t) @zero_terminated;
+ uint8 cert_subject_data[cert_subject_size] @end @ctype(uint8_t) @zero_terminated;
+ } @ctype(SpiceMsgMainMigrationSwitchHost) migrate_switch_host;
+
+ client:
+ message {
+ uint64 cache_size;
+ } @ctype(SpiceMsgcClientInfo) client_info = 101;
+
+ Empty migrate_connected;
+
+ Empty migrate_connect_error;
+
+ Empty attach_channels;
+
+ message {
+ mouse_mode mode;
+ } mouse_mode_request;
+
+ message {
+ uint32 num_tokens;
+ } agent_start;
+
+ Data agent_data;
+
+ message {
+ uint32 num_tokens;
+ } @ctype(SpiceMsgcMainAgentTokens) agent_token;
+};
+
+enum32 clip_type {
+ NONE,
+ RECTS,
+ PATH,
+};
+
+flags32 path_flags { /* TODO: C enum names changes */
+ BEGIN = 0,
+ END = 1,
+ CLOSE = 3,
+ BEZIER = 4,
+} @prefix(SPICE_PATH_);
+
+enum32 video_codec_type {
+ MJPEG = 1,
+};
+
+flags32 stream_flags {
+ TOP_DOWN = 0,
+};
+
+enum32 brush_type {
+ NONE,
+ SOLID,
+ PATTERN,
+};
+
+flags8 mask_flags {
+ INVERS,
+};
+
+enum8 image_type {
+ BITMAP,
+ QUIC,
+ RESERVED,
+ LZ_PLT = 100,
+ LZ_RGB,
+ GLZ_RGB,
+ FROM_CACHE,
+ SURFACE,
+ JPEG,
+ FROM_CACHE_LOSSLESS,
+};
+
+flags8 image_flags {
+ CACHE_ME,
+ HIGH_BITS_SET,
+ CACHE_REPLACE_ME,
+};
+
+enum8 bitmap_fmt {
+ INVALID,
+ 1BIT_LE,
+ 1BIT_BE,
+ 4BIT_LE,
+ 4BIT_BE,
+ 8BIT /* 8bit indexed mode */,
+ 16BIT, /* 0555 mode */
+ 24BIT /* 3 byte, brg */,
+ 32BIT /* 4 byte, xrgb in little endian format */,
+ RGBA /* 4 byte, argb in little endian format */
+};
+
+flags8 bitmap_flags {
+ PAL_CACHE_ME,
+ PAL_FROM_CACHE,
+ TOP_DOWN,
+};
+
+enum8 image_scale_mode {
+ INTERPOLATE,
+ NEAREST,
+};
+
+flags16 ropd {
+ INVERS_SRC,
+ INVERS_BRUSH,
+ INVERS_DEST,
+ OP_PUT,
+ OP_OR,
+ OP_AND,
+ OP_XOR,
+ OP_BLACKNESS,
+ OP_WHITENESS,
+ OP_INVERS,
+ INVERS_RES,
+};
+
+flags8 line_flags {
+ STYLED = 3,
+ START_WITH_GAP = 2,
+};
+
+enum8 line_cap {
+ ROUND,
+ SQUARE,
+ BUTT,
+};
+
+enum8 line_join {
+ ROUND,
+ BEVEL,
+ MITER,
+};
+
+flags16 string_flags {
+ RASTER_A1,
+ RASTER_A4,
+ RASTER_A8,
+ RASTER_TOP_DOWN,
+};
+
+flags32 surface_flags {
+ PRIMARY
+};
+
+enum32 surface_fmt {
+ INVALID,
+ 1_A = 1,
+ 8_A = 8,
+ 16_555 = 16 ,
+ 16_565 = 80,
+ 32_xRGB = 32,
+ 32_ARGB = 96
+};
+
+flags16 alpha_flags {
+ DEST_HAS_ALPHA,
+ SRC_SURFACE_HAS_ALPHA
+};
+
+enum8 resource_type {
+ INVALID,
+ PIXMAP
+} @prefix(SPICE_RES_TYPE_);
+
+struct ClipRects {
+ uint32 num_rects;
+ Rect rects[num_rects] @end;
+};
+
+struct PathSegment {
+ path_flags flags;
+ uint32 count;
+ PointFix points[count] @end;
+} @ctype(SpicePathSeg);
+
+struct Path {
+ uint32 size;
+ PathSegment segments[bytes(size)] @end;
+};
+
+struct Clip {
+ clip_type type;
+ switch (type) {
+ case NONE:
+ uint64 data @zero;
+ case RECTS:
+ ClipRects *data;
+ case PATH:
+ Path *data;
+ } u @anon;
+};
+
+struct DisplayBase {
+ uint32 surface_id;
+ Rect box;
+ Clip clip;
+} @ctype(SpiceMsgDisplayBase);
+
+struct ResourceID {
+ uint8 type;
+ uint64 id;
+};
+
+struct WaitForChannel {
+ uint8 channel_type;
+ uint8 channel_id;
+ uint64 message_serial;
+};
+
+struct Palette {
+ uint64 unique;
+ uint16 num_ents;
+ uint32 ents[num_ents] @end;
+};
+
+struct BitmapData {
+ bitmap_fmt format;
+ bitmap_flags flags;
+ uint32 x;
+ uint32 y;
+ uint32 stride;
+ switch (flags) {
+ case PAL_FROM_CACHE:
+ uint64 palette;
+ default:
+ Palette *palette;
+ } pal @anon;
+ uint8 *data[image_size(8, stride, y)] @nocopy; /* pointer to array, not array of pointers as in C */
+} @ctype(SpiceBitmap);
+
+struct BinaryData {
+ uint32 data_size;
+ uint8 data[data_size] @end;
+} @ctype(SpiceQUICData);
+
+struct LZPLTData {
+ bitmap_flags flags;
+ uint32 data_size;
+ switch (flags) {
+ case PAL_FROM_CACHE:
+ uint64 palette;
+ default:
+ Palette *palette @nonnull;
+ } pal @anon;
+ uint8 data[data_size] @end;
+};
+
+struct Surface {
+ uint32 surface_id;
+};
+
+struct Image {
+ uint64 id;
+ image_type type;
+ image_flags flags;
+ uint32 width;
+ uint32 height;
+
+ switch (type) {
+ case BITMAP:
+ BitmapData bitmap_data @ctype(SpiceBitmap);
+ case QUIC:
+ case LZ_RGB:
+ case GLZ_RGB:
+ case JPEG:
+ BinaryData binary_data @ctype(SpiceQUICData);
+ case LZ_PLT:
+ LZPLTData lzplt_data @ctype(SpiceLZPLTData);
+ case SURFACE:
+ Surface surface_data;
+ } u @end;
+} @ctype(SpiceImageDescriptor);
+
+struct Pattern {
+ Image *pat @nonnull;
+ Point pos;
+};
+
+struct Brush {
+ brush_type type;
+ switch (type) {
+ case SOLID:
+ uint32 color;
+ case PATTERN:
+ Pattern pattern;
+ } u @fixedsize;
+};
+
+struct QMask {
+ mask_flags flags;
+ Point pos;
+ Image *bitmap;
+};
+
+struct LineAttr {
+ line_flags flags;
+ line_join join_style;
+ line_cap end_style;
+ uint8 style_nseg;
+ fixed28_4 width;
+ fixed28_4 miter_limit;
+ fixed28_4 *style[style_nseg];
+};
+
+struct RasterGlyphA1 {
+ Point render_pos;
+ Point glyph_origin;
+ uint16 width;
+ uint16 height;
+ uint8 data[image_size(1, width, height)] @end;
+} @ctype(SpiceRasterGlyph);
+
+struct RasterGlyphA4 {
+ Point render_pos;
+ Point glyph_origin;
+ uint16 width;
+ uint16 height;
+ uint8 data[image_size(4, width, height)] @end;
+} @ctype(SpiceRasterGlyph);
+
+struct RasterGlyphA8 {
+ Point render_pos;
+ Point glyph_origin;
+ uint16 width;
+ uint16 height;
+ uint8 data[image_size(8, width, height)] @end;
+} @ctype(SpiceRasterGlyph);
+
+struct String {
+ uint16 length;
+ string_flags flags; /* Special: Only one of a1/a4/a8 set */
+ switch (flags) {
+ case RASTER_A1:
+ RasterGlyphA1 glyphs[length] @ctype(SpiceRasterGlyph);
+ case RASTER_A4:
+ RasterGlyphA4 glyphs[length] @ctype(SpiceRasterGlyph);
+ case RASTER_A8:
+ RasterGlyphA8 glyphs[length] @ctype(SpiceRasterGlyph);
+ } u @end;
+};
+
+channel DisplayChannel : BaseChannel {
+ server:
+ message {
+ uint32 x_res;
+ uint32 y_res;
+ uint32 bits;
+ } mode = 101;
+
+ Empty mark;
+ Empty reset;
+ message {
+ DisplayBase base;
+ Point src_pos;
+ } copy_bits;
+
+ message {
+ uint16 count;
+ ResourceID resources[count] @end;
+ } @ctype(SpiceResourceList) inval_list;
+
+ message {
+ uint8 wait_count;
+ WaitForChannel wait_list[wait_count] @end;
+ } @ctype(SpiceMsgWaitForChannels) inval_all_pixmaps;
+
+ message {
+ uint64 id;
+ } @ctype(SpiceMsgDisplayInvalOne) inval_palette;
+
+ Empty inval_all_palettes;
+
+ message {
+ uint32 surface_id;
+ uint32 id;
+ stream_flags flags;
+ video_codec_type codec_type;
+ uint64 stamp;
+ uint32 stream_width;
+ uint32 stream_height;
+ uint32 src_width;
+ uint32 src_height;
+ Rect dest;
+ Clip clip;
+ } stream_create = 122;
+
+ message {
+ uint32 id;
+ uint32 multi_media_time;
+ uint32 data_size;
+ uint32 pad_size;
+ uint8 data[data_size] @end;
+ uint8 padding[pad_size] @end @ctype(uint8_t); /* Uhm, why are we sending padding over network? */
+ } stream_data;
+
+ message {
+ uint32 id;
+ Clip clip;
+ } stream_clip;
+
+ message {
+ uint32 id;
+ } stream_destroy;
+
+ Empty stream_destroy_all;
+
+ message {
+ DisplayBase base;
+ struct Fill {
+ Brush brush;
+ uint16 rop_decriptor;
+ QMask mask;
+ } data;
+ } draw_fill = 302;
+
+ message {
+ DisplayBase base;
+ struct Opaque {
+ Image *src_bitmap;
+ Rect src_area;
+ Brush brush;
+ ropd rop_decriptor;
+ image_scale_mode scale_mode;
+ QMask mask;
+ } data;
+ } draw_opaque;
+
+ message {
+ DisplayBase base;
+ struct Copy {
+ Image *src_bitmap;
+ Rect src_area;
+ ropd rop_decriptor;
+ image_scale_mode scale_mode;
+ QMask mask;
+ } data;
+ } draw_copy;
+
+ message {
+ DisplayBase base;
+ struct Blend {
+ Image *src_bitmap;
+ Rect src_area;
+ ropd rop_decriptor;
+ image_scale_mode scale_mode;
+ QMask mask;
+ } @ctype(SpiceCopy) data;
+ } draw_blend;
+
+ message {
+ DisplayBase base;
+ struct Blackness {
+ QMask mask;
+ } data;
+ } draw_blackness;
+
+ message {
+ DisplayBase base;
+ struct Whiteness {
+ QMask mask;
+ } data;
+ } draw_whiteness;
+
+ message {
+ DisplayBase base;
+ struct Invers {
+ QMask mask;
+ } data;
+ } draw_invers;
+
+ message {
+ DisplayBase base;
+ struct Rop3 {
+ Image *src_bitmap;
+ Rect src_area;
+ Brush brush;
+ uint8 rop3;
+ image_scale_mode scale_mode;
+ QMask mask;
+ } data;
+ } draw_rop3;
+
+ message {
+ DisplayBase base;
+ struct Stroke {
+ Path *path;
+ LineAttr attr;
+ Brush brush;
+ uint16 fore_mode;
+ uint16 back_mode;
+ } data;
+ } draw_stroke;
+
+ message {
+ DisplayBase base;
+ struct Text {
+ String *str;
+ Rect back_area;
+ Brush fore_brush;
+ Brush back_brush;
+ uint16 fore_mode;
+ uint16 back_mode;
+ } data;
+ } draw_text;
+
+ message {
+ DisplayBase base;
+ struct Transparent {
+ Image *src_bitmap;
+ Rect src_area;
+ uint32 src_color;
+ uint32 true_color;
+ } data;
+ } draw_transparent;
+
+ message {
+ DisplayBase base;
+ struct AlphaBlnd {
+ alpha_flags alpha_flags;
+ uint8 alpha;
+ Image *src_bitmap;
+ Rect src_area;
+ } data;
+ } draw_alpha_blend;
+
+ message {
+ uint32 surface_id;
+ uint32 width;
+ uint32 height;
+ uint32 format;
+ surface_flags flags;
+ } @ctype(SpiceMsgSurfaceCreate) surface_create;
+
+ message {
+ uint32 surface_id;
+ } @ctype(SpiceMsgSurfaceDestroy) surface_destroy;
+
+ client:
+ message {
+ uint8 pixmap_cache_id;
+ int64 pixmap_cache_size; //in pixels
+ uint8 glz_dictionary_id;
+ int32 glz_dictionary_window_size; // in pixels
+ } init = 101;
+};
+
+flags32 keyboard_modifier_flags {
+ SCROLL_LOCK,
+ NUM_LOCK,
+ CAPS_LOCK
+};
+
+enum32 mouse_button {
+ INVALID,
+ LEFT,
+ MIDDLE,
+ RIGHT,
+ UP,
+ DOWN,
+};
+
+flags32 mouse_button_mask {
+ LEFT,
+ MIDDLE,
+ RIGHT
+};
+
+channel InputsChannel : BaseChannel {
+ client:
+ message {
+ uint32 code;
+ } @ctype(SpiceMsgcKeyDown) key_down = 101;
+
+ message {
+ uint32 code;
+ } @ctype(SpiceMsgcKeyUp) key_up;
+
+ message {
+ keyboard_modifier_flags modifiers;
+ } @ctype(SpiceMsgcKeyModifiers) key_modifiers;
+
+ message {
+ int32 dx;
+ int32 dy;
+ mouse_button_mask buttons_state;
+ } @ctype(SpiceMsgcMouseMotion) mouse_motion = 111;
+
+ message {
+ uint32 x;
+ uint32 y;
+ mouse_button_mask buttons_state;
+ uint8 display_id;
+ } @ctype(SpiceMsgcMousePosition) mouse_position;
+
+ message {
+ mouse_button button;
+ mouse_button_mask buttons_state;
+ } @ctype(SpiceMsgcMousePress) mouse_press;
+
+ message {
+ mouse_button button;
+ mouse_button_mask buttons_state;
+ } @ctype(SpiceMsgcMouseRelease) mouse_release;
+
+ server:
+ message {
+ keyboard_modifier_flags keyboard_modifiers;
+ } init = 101;
+
+ message {
+ keyboard_modifier_flags modifiers;
+ } key_modifiers;
+
+ Empty mouse_motion_ack = 111;
+};
+
+enum16 cursor_type {
+ ALPHA,
+ MONO,
+ COLOR4,
+ COLOR8,
+ COLOR16,
+ COLOR24,
+ COLOR32,
+};
+
+flags32 cursor_flags {
+ NONE, /* Means no cursor */
+ CACHE_ME,
+ FROM_CACHE,
+};
+
+struct CursorHeader {
+ uint64 unique;
+ cursor_type type;
+ uint16 width;
+ uint16 height;
+ uint16 hot_spot_x;
+ uint16 hot_spot_y;
+};
+
+struct Cursor {
+ cursor_flags flags;
+ CursorHeader header;
+ uint8 data[] @end;
+};
+
+channel CursorChannel : BaseChannel {
+ server:
+ message {
+ Point16 position;
+ uint16 trail_length;
+ uint16 trail_frequency;
+ uint8 visible;
+ Cursor cursor;
+ } init = 101;
+
+ Empty reset;
+
+ message {
+ Point16 position;
+ uint8 visible;
+ Cursor cursor;
+ } set;
+
+ message {
+ Point16 position;
+ } move;
+
+ Empty hide;
+
+ message {
+ uint16 length;
+ uint16 frequency;
+ } trail;
+
+ message {
+ uint64 id;
+ } @ctype(SpiceMsgDisplayInvalOne) inval_one;
+
+ Empty inval_all;
+};
+
+enum32 audio_data_mode {
+ INVALID,
+ RAW,
+ CELT_0_5_1,
+};
+
+enum32 audio_fmt {
+ INVALID,
+ S16,
+};
+
+channel PlaybackChannel : BaseChannel {
+ server:
+ message {
+ uint32 time;
+ uint8 data[] @end;
+ } @ctype(SpiceMsgPlaybackPacket) data = 101;
+
+ message {
+ uint32 time;
+ audio_data_mode mode;
+ uint8 data[] @end;
+ } mode;
+
+ message {
+ uint32 channels;
+ audio_fmt format;
+ uint32 frequency;
+ uint32 time;
+ } start;
+
+ Empty stop;
+};
+
+channel RecordChannel : BaseChannel {
+ server:
+ message {
+ uint32 channels;
+ audio_fmt format;
+ uint32 frequency;
+ } start = 101;
+
+ Empty stop;
+ client:
+ message {
+ uint32 time;
+ uint8 data[] @end;
+ } @ctype(SpiceMsgcRecordPacket) data = 101;
+
+ message {
+ uint32 time;
+ audio_data_mode mode;
+ uint8 data[] @end;
+ } mode;
+
+ message {
+ uint32 time;
+ } start_mark;
+};
+
+enum32 tunnel_service_type {
+ INVALID,
+ GENERIC,
+ IPP,
+};
+
+enum16 tunnel_ip_type {
+ INVALID,
+ IPv4,
+};
+
+struct TunnelIpInfo {
+ tunnel_ip_type type;
+ switch (type) {
+ case IPv4:
+ uint8 ipv4[4] @ctype(uint8_t);
+ } u @end;
+} @ctype(SpiceMsgTunnelIpInfo);
+
+channel TunnelChannel : BaseChannel {
+ server:
+ message {
+ uint16 max_num_of_sockets;
+ uint32 max_socket_data_size;
+ } init = 101;
+
+ message {
+ uint32 service_id;
+ TunnelIpInfo virtual_ip;
+ } service_ip_map;
+
+ message {
+ uint16 connection_id;
+ uint32 service_id;
+ uint32 tokens;
+ } socket_open;
+
+ message {
+ uint16 connection_id;
+ } socket_fin;
+
+ message {
+ uint16 connection_id;
+ } socket_close;
+
+ message {
+ uint16 connection_id;
+ uint8 data[] @end;
+ } socket_data;
+
+ message {
+ uint16 connection_id;
+ } socket_closed_ack;
+
+ message {
+ uint16 connection_id;
+ uint32 num_tokens;
+ } @ctype(SpiceMsgTunnelSocketTokens) socket_token;
+
+ client:
+ message {
+ tunnel_service_type type;
+ uint32 id;
+ uint32 group;
+ uint32 port;
+ uint32 name;
+ uint32 description;
+ switch (type) {
+ case IPP:
+ TunnelIpInfo ip @ctype(SpiceMsgTunnelIpInfo);
+ } u @end;
+ } @ctype(SpiceMsgcTunnelAddGenericService) service_add = 101;
+
+ message {
+ uint32 id;
+ } @ctype(SpiceMsgcTunnelRemoveService) service_remove;
+
+ message {
+ uint16 connection_id;
+ uint32 tokens;
+ } socket_open_ack;
+
+ message {
+ uint16 connection_id;
+ } socket_open_nack;
+
+ message {
+ uint16 connection_id;
+ } socket_fin;
+
+ message {
+ uint16 connection_id;
+ } socket_closed;
+
+ message {
+ uint16 connection_id;
+ } socket_closed_ack;
+
+ message {
+ uint16 connection_id;
+ uint8 data[] @end;
+ } socket_data;
+
+ message {
+ uint16 connection_id;
+ uint32 num_tokens;
+ } @ctype(SpiceMsgcTunnelSocketTokens) socket_token;
+};
+
+protocol Spice {
+ MainChannel main = 1;
+ DisplayChannel display;
+ InputsChannel inputs;
+ CursorChannel cursor;
+ PlaybackChannel playback;
+ RecordChannel record;
+ TunnelChannel tunnel;
+};
diff --git a/spice_gen.py b/spice_gen.py
new file mode 100755
index 0000000..f897ce8
--- /dev/null
+++ b/spice_gen.py
@@ -0,0 +1,165 @@
+#!/usr/bin/env python
+
+import os
+import sys
+from optparse import OptionParser
+import traceback
+from python_modules import spice_parser
+from python_modules import ptypes
+from python_modules import codegen
+from python_modules import demarshal
+
+def write_channel_enums(writer, channel, client):
+ messages = filter(lambda m : m.channel == channel, \
+ channel.client_messages if client else channel.server_messages)
+ if len(messages) == 0:
+ return
+ writer.begin_block("enum")
+ i = 0;
+ if client:
+ prefix = [ "MSGC" ]
+ else:
+ prefix = [ "MSG" ]
+ if channel.member_name:
+ prefix.append(channel.member_name.upper())
+ prefix.append(None) # To be replaced with name
+ for m in messages:
+ prefix[-1] = m.name.upper()
+ enum = codegen.prefix_underscore_upper(*prefix)
+ if m.value == i:
+ writer.writeln("%s," % enum)
+ i = i + 1
+ else:
+ writer.writeln("%s = %s," % (enum, m.value))
+ i = m.value + 1
+ if channel.member_name:
+ prefix[-1] = prefix[-2]
+ prefix[-2] = "END"
+ writer.newline()
+ writer.writeln("%s" % (codegen.prefix_underscore_upper(*prefix)))
+ writer.end_block(semicolon=True)
+ writer.newline()
+
+def write_enums(writer):
+ writer.writeln("#ifndef _H_SPICE_ENUMS")
+ writer.writeln("#define _H_SPICE_ENUMS")
+ writer.newline()
+ writer.comment("Generated from %s, don't edit" % writer.options["source"]).newline()
+ writer.newline()
+
+ # Define enums
+ for t in ptypes.get_named_types():
+ if isinstance(t, ptypes.EnumBaseType):
+ t.c_define(writer)
+
+ i = 0;
+ writer.begin_block("enum")
+ for c in proto.channels:
+ enum = codegen.prefix_underscore_upper("CHANNEL", c.name.upper())
+ if c.value == i:
+ writer.writeln("%s," % enum)
+ i = i + 1
+ else:
+ writer.writeln("%s = %s," % (enum, c.value))
+ i = c.value + 1
+ writer.newline()
+ writer.writeln("SPICE_END_CHANNEL")
+ writer.end_block(semicolon=True)
+ writer.newline()
+
+ for c in ptypes.get_named_types():
+ if not isinstance(c, ptypes.ChannelType):
+ continue
+ write_channel_enums(writer, c, False)
+ write_channel_enums(writer, c, True)
+
+ writer.writeln("#endif /* _H_SPICE_ENUMS */")
+
+parser = OptionParser(usage="usage: %prog [options] <protocol_file> <destination file>")
+parser.add_option("-e", "--generate-enums",
+ action="store_true", dest="generate_enums", default=False,
+ help="Generate enums")
+parser.add_option("-d", "--generate-demarshallers",
+ action="store_true", dest="generate_demarshallers", default=False,
+ help="Generate demarshallers")
+parser.add_option("-a", "--assert-on-error",
+ action="store_true", dest="assert_on_error", default=False,
+ help="Assert on error")
+parser.add_option("-p", "--print-error",
+ action="store_true", dest="print_error", default=False,
+ help="Print errors")
+parser.add_option("-s", "--server",
+ action="store_true", dest="server", default=False,
+ help="Print errors")
+parser.add_option("-c", "--client",
+ action="store_true", dest="client", default=False,
+ help="Print errors")
+parser.add_option("-k", "--keep-identical-file",
+ action="store_true", dest="keep_identical_file", default=False,
+ help="Print errors")
+parser.add_option("-i", "--include",
+ dest="include", default=None, metavar="FILE",
+ help="Include FILE in generated code")
+
+(options, args) = parser.parse_args()
+
+if len(args) == 0:
+ parser.error("No protocol file specified")
+
+if len(args) == 1:
+ parser.error("No destination file specified")
+
+proto_file = args[0]
+dest_file = args[1]
+proto = spice_parser.parse(proto_file)
+
+if proto == None:
+ exit(1)
+
+codegen.set_prefix(proto.name)
+writer = codegen.CodeWriter()
+writer.set_option("source", os.path.basename(proto_file))
+
+if options.assert_on_error:
+ writer.set_option("assert_on_error")
+
+if options.print_error:
+ writer.set_option("print_error")
+
+if options.include:
+ writer.writeln('#include "%s"' % options.include)
+
+if options.generate_enums:
+ write_enums(writer)
+
+if options.generate_demarshallers:
+ if not options.server and not options.client:
+ print >> sys.stderr, "Must specify client and/or server"
+ sys.exit(1)
+ demarshal.write_includes(writer)
+
+ if options.server:
+ demarshal.write_protocol_parser(writer, proto, False)
+ if options.client:
+ demarshal.write_protocol_parser(writer, proto, True)
+
+content = writer.getvalue()
+if options.keep_identical_file:
+ try:
+ f = open(dest_file, 'rb')
+ old_content = f.read()
+ f.close()
+
+ if content == old_content:
+ print "No changes to %s" % dest_file
+ sys.exit(0)
+
+ except IOError:
+ pass
+
+f = open(dest_file, 'wb')
+f.write(content)
+f.close()
+
+print "Wrote %s" % dest_file
+sys.exit(0)
commit aa6b7b5beb4768e2384e21bfd4c1608cc1d39c39
Author: Alexander Larsson <alexl at redhat.com>
Date: Wed May 26 21:43:13 2010 +0200
Use the correctly spelled enum values from the new generated enums
diff --git a/client/playback_channel.cpp b/client/playback_channel.cpp
index e1aa065..3e8bb46 100644
--- a/client/playback_channel.cpp
+++ b/client/playback_channel.cpp
@@ -147,7 +147,7 @@ PlaybackChannel::PlaybackChannel(RedClient& client, uint32_t id)
: RedChannel(client, SPICE_CHANNEL_PLAYBACK, id, new PlaybackHandler(*this),
Platform::PRIORITY_HIGH)
, _wave_player (NULL)
- , _mode (SPICE_AUDIO_DATA_MODE_INVALD)
+ , _mode (SPICE_AUDIO_DATA_MODE_INVALID)
, _celt_mode (NULL)
, _celt_decoder (NULL)
, _playing (false)
diff --git a/client/record_channel.cpp b/client/record_channel.cpp
index 329dced..893cc63 100644
--- a/client/record_channel.cpp
+++ b/client/record_channel.cpp
@@ -68,7 +68,7 @@ public:
RecordChannel::RecordChannel(RedClient& client, uint32_t id)
: RedChannel(client, SPICE_CHANNEL_RECORD, id, new RecordHandler(*this))
, _wave_recorder (NULL)
- , _mode (SPICE_AUDIO_DATA_MODE_INVALD)
+ , _mode (SPICE_AUDIO_DATA_MODE_INVALID)
, _celt_mode (NULL)
, _celt_encoder (NULL)
{
commit 1ba1ce52ed2b70c9d5671f17e8047c3d548da96a
Author: Alexander Larsson <alexl at redhat.com>
Date: Fri Jun 18 16:31:31 2010 +0200
Use the new enums for keyboard modifier flags
diff --git a/client/inputs_channel.cpp b/client/inputs_channel.cpp
index 21a1412..46fc015 100644
--- a/client/inputs_channel.cpp
+++ b/client/inputs_channel.cpp
@@ -376,15 +376,15 @@ void InputsChannel::set_local_modifiers()
{
unsigned int modifiers = 0;
- if (_modifiers & SPICE_SCROLL_LOCK_MODIFIER) {
+ if (_modifiers & SPICE_KEYBOARD_MODIFIER_FLAGS_SCROLL_LOCK) {
modifiers |= Platform::SCROLL_LOCK_MODIFIER;
}
- if (_modifiers & SPICE_NUM_LOCK_MODIFIER) {
+ if (_modifiers & SPICE_KEYBOARD_MODIFIER_FLAGS_NUM_LOCK) {
modifiers |= Platform::NUM_LOCK_MODIFIER;
}
- if (_modifiers & SPICE_CAPS_LOCK_MODIFIER) {
+ if (_modifiers & SPICE_KEYBOARD_MODIFIER_FLAGS_CAPS_LOCK) {
modifiers |= Platform::CAPS_LOCK_MODIFIER;
}
diff --git a/server/reds.c b/server/reds.c
index 051fc30..ed5d212 100644
--- a/server/reds.c
+++ b/server/reds.c
@@ -2259,16 +2259,18 @@ static void inputs_handle_input(void *opaque, SpiceDataHeader *header)
break;
}
leds = kbd_get_leds(keyboard);
- if ((modifiers->modifiers & SPICE_SCROLL_LOCK_MODIFIER) !=
- (leds & SPICE_SCROLL_LOCK_MODIFIER)) {
+ if ((modifiers->modifiers & SPICE_KEYBOARD_MODIFIER_FLAGS_SCROLL_LOCK) !=
+ (leds & SPICE_KEYBOARD_MODIFIER_FLAGS_SCROLL_LOCK)) {
kbd_push_scan(keyboard, SCROLL_LOCK_SCAN_CODE);
kbd_push_scan(keyboard, SCROLL_LOCK_SCAN_CODE | 0x80);
}
- if ((modifiers->modifiers & SPICE_NUM_LOCK_MODIFIER) != (leds & SPICE_NUM_LOCK_MODIFIER)) {
+ if ((modifiers->modifiers & SPICE_KEYBOARD_MODIFIER_FLAGS_NUM_LOCK) !=
+ (leds & SPICE_KEYBOARD_MODIFIER_FLAGS_NUM_LOCK)) {
kbd_push_scan(keyboard, NUM_LOCK_SCAN_CODE);
kbd_push_scan(keyboard, NUM_LOCK_SCAN_CODE | 0x80);
}
- if ((modifiers->modifiers & SPICE_CAPS_LOCK_MODIFIER) != (leds & SPICE_CAPS_LOCK_MODIFIER)) {
+ if ((modifiers->modifiers & SPICE_KEYBOARD_MODIFIER_FLAGS_CAPS_LOCK) !=
+ (leds & SPICE_KEYBOARD_MODIFIER_FLAGS_CAPS_LOCK)) {
kbd_push_scan(keyboard, CAPS_LOCK_SCAN_CODE);
kbd_push_scan(keyboard, CAPS_LOCK_SCAN_CODE | 0x80);
}
commit ef8a8dae07f400f2573fc6f507bd98c6815d816e
Author: Alexander Larsson <alexl at redhat.com>
Date: Wed May 26 21:16:25 2010 +0200
There are multiple line attribute flags enums, use only one
diff --git a/common/gdi_canvas.c b/common/gdi_canvas.c
index d01d9cd..20113fe 100644
--- a/common/gdi_canvas.c
+++ b/common/gdi_canvas.c
@@ -1799,10 +1799,10 @@ static void gdi_canvas_draw_stroke(SpiceCanvas *spice_canvas, SpiceRect *bbox, S
SetMiterLimit(canvas->dc, (FLOAT)fix_to_double(stroke->attr.miter_limit), &old_miter);
#endif
- if (stroke->attr.flags & SPICE_LINE_ATTR_STYLED) {
+ if (stroke->attr.flags & SPICE_LINE_FLAGS_STYLED) {
user_style = gdi_get_userstyle(canvas, stroke->attr.style_nseg,
stroke->attr.style,
- !!(stroke->attr.flags & SPICE_LINE_ATTR_STARTGAP));
+ !!(stroke->attr.flags & SPICE_LINE_FLAGS_START_WITH_GAP));
hpen = ExtCreatePen(PS_GEOMETRIC | ps_join | line_cap | PS_USERSTYLE,
(uint32_t)fix_to_double(stroke->attr.width),
&logbrush, stroke->attr.style_nseg, (DWORD *)user_style);
diff --git a/common/gl_canvas.c b/common/gl_canvas.c
index f98c72a..00caf89 100644
--- a/common/gl_canvas.c
+++ b/common/gl_canvas.c
@@ -630,8 +630,8 @@ static void gl_canvas_draw_stroke(SpiceCanvas *spice_canvas, SpiceRect *bbox, Sp
set_op(canvas, stroke->fore_mode);
set_brush(canvas, &stroke->brush);
- if (stroke->attr.flags & SPICE_LINE_ATTR_STYLED) {
- WARN("SPICE_LINE_ATTR_STYLED");
+ if (stroke->attr.flags & SPICE_LINE_FLAGS_STYLED) {
+ WARN("SPICE_LINE_FLAGS_STYLED");
}
glc_set_line_width(canvas->glc, fix_to_double(stroke->attr.width));
commit 1d1792c217bee2f7aed28cbee60fc170bb56ecae
Author: Alexander Larsson <alexl at redhat.com>
Date: Thu Jun 17 11:18:27 2010 +0200
Add spice_strnlen
diff --git a/common/mem.c b/common/mem.c
index ec274bb..ffb2fa4 100644
--- a/common/mem.c
+++ b/common/mem.c
@@ -28,6 +28,18 @@
}
#endif
+size_t spice_strnlen(const char *str, size_t max_len)
+{
+ size_t len = 0;
+
+ while (len < max_len && *str != 0) {
+ len++;
+ str++;
+ }
+
+ return len;
+}
+
char *spice_strdup(const char *str)
{
char *copy;
diff --git a/common/mem.h b/common/mem.h
index 2087760..9b257ad 100644
--- a/common/mem.h
+++ b/common/mem.h
@@ -33,6 +33,8 @@ void *spice_malloc_n_m(size_t n_blocks, size_t n_block_bytes, size_t extra_size)
void *spice_malloc0_n(size_t n_blocks, size_t n_block_bytes) SPICE_GNUC_MALLOC SPICE_GNUC_ALLOC_SIZE2(1,2);
void *spice_realloc_n(void *mem, size_t n_blocks, size_t n_block_bytes) SPICE_GNUC_WARN_UNUSED_RESULT;
+size_t spice_strnlen(const char *str, size_t max_len);
+
/* Optimize: avoid the call to the (slower) _n function if we can
* determine at compile-time that no overflow happens.
*/
More information about the Spice-commits
mailing list