[Spice-commits] 10 commits - client/demarshallers.h client/display_channel.cpp client/inputs_channel.cpp client/inputs_channel.h client/Makefile.am client/marshallers.h 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 Makefile.am python_modules/codegen.py python_modules/demarshal.py python_modules/marshal.py python_modules/ptypes.py spice1.proto spice_codegen.py

Alexander Larsson alexl at kemper.freedesktop.org
Tue Jun 22 08:36:05 PDT 2010


 Makefile.am                  |    2 
 client/Makefile.am           |   16 
 client/demarshallers.h       |    1 
 client/display_channel.cpp   |   15 
 client/inputs_channel.cpp    |   29 -
 client/inputs_channel.h      |    4 
 client/marshallers.h         |   61 ++
 client/record_channel.cpp    |    7 
 client/red_channel.cpp       |  101 +++-
 client/red_channel.h         |   23 -
 client/red_client.cpp        |   16 
 client/red_client.h          |    3 
 client/red_peer.cpp          |    1 
 client/red_peer.h            |    5 
 client/tunnel_channel.cpp    |   33 -
 client/windows/generate.bat  |    3 
 client/windows/generate1.bat |    2 
 client/windows/redc.vcproj   |   49 +-
 client/x11/Makefile.am       |    4 
 python_modules/codegen.py    |    1 
 python_modules/demarshal.py  |   23 -
 python_modules/marshal.py    |   36 +
 python_modules/ptypes.py     |    4 
 spice1.proto                 |  934 +++++++++++++++++++++++++++++++++++++++++++
 spice_codegen.py             |   11 
 25 files changed, 1276 insertions(+), 108 deletions(-)

New commits:
commit 72cf104c2897b4dd124c8a65df02e6895a9f1d88
Author: Alexander Larsson <alexl at redhat.com>
Date:   Tue Jun 22 16:36:42 2010 +0200

    client: Support connecting to a major==1 server

diff --git a/client/red_channel.cpp b/client/red_channel.cpp
index 2e6130c..d499e8c 100644
--- a/client/red_channel.cpp
+++ b/client/red_channel.cpp
@@ -42,7 +42,8 @@ RedChannelBase::~RedChannelBase()
 {
 }
 
-void RedChannelBase::link(uint32_t connection_id, const std::string& password)
+void RedChannelBase::link(uint32_t connection_id, const std::string& password,
+                          int protocol)
 {
     SpiceLinkHeader header;
     SpiceLinkMess link_mess;
@@ -54,11 +55,19 @@ void RedChannelBase::link(uint32_t connection_id, const std::string& password)
     int nRSASize;
     BIO *bioKey;
     RSA *rsa;
+    uint8_t *buffer, *p;
 
     header.magic = SPICE_MAGIC;
     header.size = sizeof(link_mess);
-    header.major_version = SPICE_VERSION_MAJOR;
-    header.minor_version = SPICE_VERSION_MINOR;
+    if (protocol == 1) {
+        /* protocol 1 == major 1, old 0.4 protocol, last active minor */
+        header.major_version = 1;
+        header.minor_version = 3;
+    } else if (protocol == 2) {
+        /* protocol 2 == current */
+        header.major_version = SPICE_VERSION_MAJOR;
+        header.minor_version = SPICE_VERSION_MINOR;
+    }
     link_mess.connection_id = connection_id;
     link_mess.channel_type = _type;
     link_mess.channel_id = _id;
@@ -66,30 +75,44 @@ void RedChannelBase::link(uint32_t connection_id, const std::string& password)
     link_mess.num_channel_caps = get_caps().size();
     link_mess.caps_offset = sizeof(link_mess);
     header.size += (link_mess.num_common_caps + link_mess.num_channel_caps) * sizeof(uint32_t);
-    send((uint8_t*)&header, sizeof(header));
-    send((uint8_t*)&link_mess, sizeof(link_mess));
 
+    buffer =
+        new uint8_t[sizeof(header) + sizeof(link_mess) +
+                    _common_caps.size() * sizeof(uint32_t) +
+                    _caps.size() * sizeof(uint32_t)];
+    p = buffer;
+
+    memcpy(p, (uint8_t*)&header, sizeof(header));
+    p += sizeof(header);
+    memcpy(p, (uint8_t*)&link_mess, sizeof(link_mess));
+    p += sizeof(link_mess);
     for (i = 0; i < _common_caps.size(); i++) {
-        send((uint8_t*)&_common_caps[i], sizeof(uint32_t));
+        *(uint32_t *)p = _common_caps[i];
+        p += sizeof(uint32_t);
     }
 
     for (i = 0; i < _caps.size(); i++) {
-        send((uint8_t*)&_caps[i], sizeof(uint32_t));
+        *(uint32_t *)p = _caps[i];
+        p += sizeof(uint32_t);
     }
 
+    send(buffer, p - buffer);
+    delete [] buffer;
+
     recive((uint8_t*)&header, sizeof(header));
 
     if (header.magic != SPICE_MAGIC) {
         THROW_ERR(SPICEC_ERROR_CODE_CONNECT_FAILED, "bad magic");
     }
 
-    if (header.major_version != SPICE_VERSION_MAJOR) {
+    if (header.major_version != protocol) {
         THROW_ERR(SPICEC_ERROR_CODE_VERSION_MISMATCH,
                   "version mismatch: expect %u got %u",
-                  SPICE_VERSION_MAJOR,
+                  protocol,
                   header.major_version);
     }
 
+    _remote_major = header.major_version;
     _remote_minor = header.minor_version;
 
     AutoArray<uint8_t> reply_buf(new uint8_t[header.size]);
@@ -160,21 +183,39 @@ void RedChannelBase::link(uint32_t connection_id, const std::string& password)
 void RedChannelBase::connect(const ConnectionOptions& options, uint32_t connection_id,
                              const char* host, std::string password)
 {
-    if (options.allow_unsecure()) {
-        try {
-            RedPeer::connect_unsecure(host, options.unsecure_port);
-            link(connection_id, password);
-            return;
-        } catch (...) {
-            if (!options.allow_secure()) {
-                throw;
+    int protocol = options.protocol;
+
+    if (protocol == 0) { /* AUTO, try major 2 first */
+        protocol = 2;
+    }
+
+ retry:
+    try {
+        if (options.allow_unsecure()) {
+            try {
+                RedPeer::connect_unsecure(host, options.unsecure_port);
+                link(connection_id, password, protocol);
+                return;
+            } catch (...) {
+                if (!options.allow_secure()) {
+                    throw;
+                }
+                RedPeer::close();
             }
-            RedPeer::close();
         }
+        ASSERT(options.allow_secure());
+        RedPeer::connect_secure(options, host);
+        link(connection_id, password, protocol);
+    } catch (Exception& e) {
+        if (protocol == 2 &&
+            options.protocol == 0 &&
+            e.get_error_code() == SPICEC_ERROR_CODE_VERSION_MISMATCH) {
+            RedPeer::cleanup();
+            protocol = 1;
+            goto retry;
+        }
+        throw;
     }
-    ASSERT(options.allow_secure());
-    RedPeer::connect_secure(options, host);
-    link(connection_id, password);
 }
 
 void RedChannelBase::set_capability(ChannelCaps& caps, uint32_t cap)
@@ -237,6 +278,7 @@ RedChannel::RedChannel(RedClient& client, uint8_t type, uint8_t id,
                        RedChannel::MessageHandler* handler,
                        Platform::ThreadPriority worker_priority)
     : RedChannelBase(type, id, ChannelCaps(), ChannelCaps())
+    , _marshallers (NULL)
     , _client (client)
     , _state (PASSIVE_STATE)
     , _action (WAIT_ACTION)
@@ -258,7 +300,6 @@ RedChannel::RedChannel(RedClient& client, uint8_t type, uint8_t id,
 {
     _loop.add_trigger(_send_trigger);
     _loop.add_trigger(_abort_trigger);
-    _marshallers = spice_message_marshallers_get();
 }
 
 RedChannel::~RedChannel()
@@ -398,11 +439,22 @@ void RedChannel::run()
                 ConnectionOptions con_options(_client.get_connection_options(get_type()),
                                               _client.get_port(),
                                               _client.get_sport(),
+                                              _client.get_protocol(),
                                               _client.get_host_auth_options(),
                                               _client.get_connection_ciphers());
                 RedChannelBase::connect(con_options, _client.get_connection_id(),
                                         _client.get_host().c_str(),
                                         _client.get_password().c_str());
+                /* If automatic protocol, remember the first connect protocol type */
+                if (_client.get_protocol() == 0) {
+                    _client.set_protocol(get_peer_major());
+                }
+                /* Initialize when we know the remote major version */
+                if (_client.get_peer_major() == 1) {
+                    _marshallers = spice_message_marshallers_get1();
+                } else {
+                    _marshallers = spice_message_marshallers_get();
+                }
                 on_connect();
                 set_state(CONNECTED_STATE);
                 _loop.add_socket(*this);
diff --git a/client/red_channel.h b/client/red_channel.h
index d973a45..fd01f20 100644
--- a/client/red_channel.h
+++ b/client/red_channel.h
@@ -63,6 +63,7 @@ public:
     const ChannelCaps& get_common_caps() { return _common_caps;}
     const ChannelCaps& get_caps() {return _caps;}
 
+     uint32_t get_peer_major() { return _remote_major;}
      uint32_t get_peer_minor() { return _remote_minor;}
 
 protected:
@@ -74,7 +75,7 @@ protected:
 private:
     void set_capability(ChannelCaps& caps, uint32_t cap);
     bool test_capability(const ChannelCaps& caps, uint32_t cap);
-    void link(uint32_t connection_id, const std::string& password);
+    void link(uint32_t connection_id, const std::string& password, int protocol);
 
 private:
     uint8_t _type;
@@ -86,6 +87,7 @@ private:
     ChannelCaps _remote_common_caps;
     ChannelCaps _remote_caps;
 
+    uint32_t _remote_major;
     uint32_t _remote_minor;
 };
 
@@ -253,8 +255,10 @@ private:
 template <class HandlerClass, unsigned int channel_id>
 MessageHandlerImp<HandlerClass, channel_id>::MessageHandlerImp(HandlerClass& obj)
     : _obj (obj)
+    , _parser (NULL)
 {
-    _parser = spice_get_server_channel_parser(channel_id, &_max_messages);
+    /* max_messages is always from current as its larger than for backwards compat */
+    spice_get_server_channel_parser(channel_id, &_max_messages);
     _handlers = new Handler[_max_messages + 1];
     memset(_handlers, 0, sizeof(Handler) * (_max_messages + 1));
 }
@@ -270,6 +274,16 @@ void MessageHandlerImp<HandlerClass, channel_id>::handle_message(RedPeer::Compun
     size_t parsed_size;
     message_destructor_t parsed_free;
 
+    if (_parser == NULL) {
+	/* We need to do this lazily rather than at constuction because we
+	   don't know the major until we've connected */
+	if (_obj.get_peer_major() == 1) {
+	    _parser = spice_get_server_channel_parser1(channel_id, NULL);
+	} else {
+	    _parser = spice_get_server_channel_parser(channel_id, NULL);
+	}
+    }
+
     if (message.sub_list()) {
         SpiceSubMessageList *sub_list;
         sub_list = (SpiceSubMessageList *)(message.data() + message.sub_list());
@@ -295,12 +309,12 @@ void MessageHandlerImp<HandlerClass, channel_id>::handle_message(RedPeer::Compun
     type = message.type();
     size = message.size();
     parsed = _parser(msg, msg + size, type, _obj.get_peer_minor(), &parsed_size, &parsed_free);
-    RedPeer::InMessage main_message(type, parsed_size, parsed);
 
     if (parsed == NULL) {
         THROW("failed to parse message channel %d type %d", channel_id, type);
     }
 
+    RedPeer::InMessage main_message(type, parsed_size, parsed);
     (_obj.*_handlers[type])(&main_message);
     parsed_free(parsed);
 }
diff --git a/client/red_client.cpp b/client/red_client.cpp
index f5b52d6..573e4b2 100644
--- a/client/red_client.cpp
+++ b/client/red_client.cpp
@@ -171,7 +171,9 @@ void Migrate::run()
     DBG(0, "");
     try {
         conn_type = _client.get_connection_options(SPICE_CHANNEL_MAIN);
-        RedPeer::ConnectionOptions con_opt(conn_type, _port, _sport, _auth_options, _con_ciphers);
+        RedPeer::ConnectionOptions con_opt(conn_type, _port, _sport,
+					   _client.get_peer_major(),
+					   _auth_options, _con_ciphers);
         MigChannels::iterator iter = _channels.begin();
         connection_id = _client.get_connection_id();
         connect_one(**iter, con_opt, connection_id);
@@ -179,6 +181,7 @@ void Migrate::run()
         for (++iter; iter != _channels.end(); ++iter) {
             conn_type = _client.get_connection_options((*iter)->get_type());
             con_opt = RedPeer::ConnectionOptions(conn_type, _port, _sport,
+						 _client.get_peer_major(),
                                                  _auth_options, _con_ciphers);
             connect_one(**iter, con_opt, connection_id);
         }
@@ -211,7 +214,7 @@ void Migrate::start(const SpiceMsgMainMigrationBegin* migrate)
 {
     DBG(0, "");
     abort();
-    if ((SPICE_VERSION_MAJOR == 1) && (_client.get_peer_minor() < 2)) {
+    if ((_client.get_peer_major() == 1) && (_client.get_peer_minor() < 2)) {
         LOG_INFO("server minor version incompatible for destination authentication"
                  "(missing dest pubkey in SpiceMsgMainMigrationBegin)");
         OldRedMigrationBegin* old_migrate = (OldRedMigrationBegin*)migrate;
@@ -304,6 +307,7 @@ RedClient::RedClient(Application& application)
     , _application (application)
     , _port (-1)
     , _sport (-1)
+    , _protocol (0)
     , _connection_id (0)
     , _mouse_mode (SPICE_MOUSE_MODE_SERVER)
     , _notify_disconnect (false)
diff --git a/client/red_client.h b/client/red_client.h
index 1b81328..52a3456 100644
--- a/client/red_client.h
+++ b/client/red_client.h
@@ -152,6 +152,8 @@ public:
     const std::string& get_host() { return _host;}
     int get_port() { return _port;}
     int get_sport() { return _sport;}
+    int get_protocol() { return _protocol;}
+    void set_protocol(int protocol) { _protocol = protocol;}
     virtual uint32_t get_connection_id() { return _connection_id;}
     uint32_t get_mouse_mode() { return _mouse_mode;}
     Application& get_application() { return _application;}
@@ -212,6 +214,7 @@ private:
     std::string _host;
     int _port;
     int _sport;
+    int _protocol;
     std::string _password;
     uint32_t _connection_id;
     uint32_t _mouse_mode;
diff --git a/client/red_peer.h b/client/red_peer.h
index 001f9fa..25a3560 100644
--- a/client/red_peer.h
+++ b/client/red_peer.h
@@ -73,11 +73,13 @@ public:
         };
 
         ConnectionOptions(Type in_type, int in_port, int in_sport,
+			  int in_protocol,
                           const HostAuthOptions& in_host_auth,
                           const std::string& in_ciphers)
             : type (in_type)
             , unsecure_port (in_port)
             , secure_port (in_sport)
+            , protocol (in_protocol)
             , host_auth (in_host_auth)
             , ciphers (in_ciphers)
         {
@@ -99,6 +101,7 @@ public:
         Type type;
         int unsecure_port;
         int secure_port;
+        int protocol; // 0 == auto
         HostAuthOptions host_auth; // for secure connection
         std::string ciphers;
     };
@@ -130,10 +133,10 @@ protected:
     static bool verify_subject(X509* cert, const HostAuthOptions::CertFieldValueList& subject);
 
     static int ssl_verify_callback(int preverify_ok, X509_STORE_CTX *ctx);
+    void cleanup();
 
 private:
     void shutdown();
-    void cleanup();
 
 private:
     SOCKET _peer;
commit 652c13e71b8c203fc701edb6bad365c50e7cf1aa
Author: Alexander Larsson <alexl at redhat.com>
Date:   Tue Jun 22 16:35:48 2010 +0200

    Implement display_mode message needed for backwards compat

diff --git a/client/display_channel.cpp b/client/display_channel.cpp
index 67c3083..736e9fb 100644
--- a/client/display_channel.cpp
+++ b/client/display_channel.cpp
@@ -615,6 +615,7 @@ DisplayChannel::DisplayChannel(RedClient& client, uint32_t id,
     handler->set_handler(SPICE_MSG_DISCONNECTING, &DisplayChannel::handle_disconnect);
     handler->set_handler(SPICE_MSG_NOTIFY, &DisplayChannel::handle_notify);
 
+    handler->set_handler(SPICE_MSG_DISPLAY_MODE, &DisplayChannel::handle_mode);
     handler->set_handler(SPICE_MSG_DISPLAY_MARK, &DisplayChannel::handle_mark);
     handler->set_handler(SPICE_MSG_DISPLAY_RESET, &DisplayChannel::handle_reset);
 
@@ -1195,6 +1196,17 @@ void DisplayChannel::create_canvas(int surface_id, const std::vector<int>& canva
     }
 }
 
+void DisplayChannel::handle_mode(RedPeer::InMessage* message)
+{
+    SpiceMsgDisplayMode *mode = (SpiceMsgDisplayMode *)message->data();
+
+    if (screen()) {
+        destroy_primary_surface();
+    }
+    create_primary_surface(mode->x_res, mode->y_res,
+                           mode->bits == 32 ? SPICE_SURFACE_FMT_32_xRGB : SPICE_SURFACE_FMT_16_555);
+}
+
 void DisplayChannel::handle_mark(RedPeer::InMessage *message)
 {
     _mark = true;
commit 2788b2ec462da943f5899429bd9bb3ba0ec5c8b9
Author: Alexander Larsson <alexl at redhat.com>
Date:   Tue Jun 22 16:35:13 2010 +0200

    Generate marshaller/demarshallers for old protocol

diff --git a/Makefile.am b/Makefile.am
index 5701e25..0caf9fe 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -6,4 +6,4 @@ pkgconfig_DATA = spice-server.pc
 DISTCLEANFILES =                                \
 	spice-server.pc
 
-EXTRA_DIST = spice.proto spice_codegen.py
+EXTRA_DIST = spice.proto spice1.proto spice_codegen.py
diff --git a/client/Makefile.am b/client/Makefile.am
index 5c0ec8d..255787e 100644
--- a/client/Makefile.am
+++ b/client/Makefile.am
@@ -3,14 +3,20 @@ NULL =
 SUBDIRS = . $(red_target)
 DIST_SUBDIRS = x11 #windows
 
-spice_built_sources = generated_demarshallers.cpp generated_marshallers.cpp
+spice_built_sources = generated_demarshallers.cpp generated_marshallers.cpp generated_demarshallers1.cpp generated_marshallers1.cpp
 
 generated_demarshallers.cpp: $(top_srcdir)/spice.proto
 	$(PYTHON) $(top_srcdir)/spice_codegen.py --generate-demarshallers --client --include common.h --include messages.h $(top_srcdir)/spice.proto generated_demarshallers.cpp
 
+generated_demarshallers1.cpp: $(top_srcdir)/spice1.proto
+	$(PYTHON) $(top_srcdir)/spice_codegen.py --generate-demarshallers --client --include common.h --include messages.h --prefix 1 $(top_srcdir)/spice1.proto generated_demarshallers1.cpp
+
 generated_marshallers.cpp: $(top_srcdir)/spice.proto
 	$(PYTHON) $(top_srcdir)/spice_codegen.py --generate-marshallers -P --include messages.h --include marshallers.h --client $(top_srcdir)/spice.proto generated_marshallers.cpp
 
+generated_marshallers1.cpp: $(top_srcdir)/spice1.proto
+	$(PYTHON) $(top_srcdir)/spice_codegen.py --generate-marshallers -P --include messages.h --include marshallers.h --client --prefix 1 $(top_srcdir)/spice1.proto generated_marshallers1.cpp
+
 if SUPPORT_GL
 GL_SRCS =				\
 	gl_canvas.cpp			\
@@ -44,8 +50,10 @@ RED_COMMON_SRCS =			\
 	demarshallers.h			\
 	marshallers.h			\
 	generated_demarshallers.cpp	\
+	generated_demarshallers1.cpp	\
 	marshaller.cpp			\
 	generated_marshallers.cpp	\
+	generated_marshallers1.cpp	\
 	cursor_channel.cpp		\
 	cursor_channel.h		\
 	cursor.cpp			\
diff --git a/client/demarshallers.h b/client/demarshallers.h
index ab0fc58..fc2f75a 100644
--- a/client/demarshallers.h
+++ b/client/demarshallers.h
@@ -22,6 +22,7 @@ typedef uint8_t * (*spice_parse_channel_func_t)(uint8_t *message_start, uint8_t
 						size_t *size_out, message_destructor_t *free_message);
 
 spice_parse_channel_func_t spice_get_server_channel_parser(uint32_t channel, unsigned int *max_message_type);
+spice_parse_channel_func_t spice_get_server_channel_parser1(uint32_t channel, unsigned int *max_message_type);
 
 #endif
 
diff --git a/client/marshallers.h b/client/marshallers.h
index 7806f29..1e6be11 100644
--- a/client/marshallers.h
+++ b/client/marshallers.h
@@ -56,5 +56,6 @@ typedef struct {
 } SpiceMessageMarshallers;
 
 SpiceMessageMarshallers *spice_message_marshallers_get(void);
+SpiceMessageMarshallers *spice_message_marshallers_get1(void);
 
 #endif
diff --git a/client/windows/generate.bat b/client/windows/generate.bat
index 3757bb0..1bb62b4 100644
--- a/client/windows/generate.bat
+++ b/client/windows/generate.bat
@@ -1,3 +1,2 @@
 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
+python ..\..\spice_codegen.py --generate-marshallers -P --include messages.h --include marshallers.h --client ..\..\spice.proto ..\generated_marshallers.cpp
diff --git a/client/windows/generate1.bat b/client/windows/generate1.bat
new file mode 100644
index 0000000..d720353
--- /dev/null
+++ b/client/windows/generate1.bat
@@ -0,0 +1,2 @@
+python ..\..\spice_codegen.py -d -c  -i common.h -i messages.h --prefix 1 ..\..\spice1.proto ..\generated_demarshallers1.cpp
+python ..\..\spice_codegen.py --generate-marshallers -P --include messages.h  --include marshallers.h --client --prefix 1 ..\..\spice1.proto ..\generated_marshallers1.cpp
diff --git a/client/windows/redc.vcproj b/client/windows/redc.vcproj
index 37ca23a..80e875b 100644
--- a/client/windows/redc.vcproj
+++ b/client/windows/redc.vcproj
@@ -236,6 +236,18 @@
 				>
 			</File>
 			<File
+				RelativePath="..\generated_demarshallers1.cpp"
+				>
+			</File>
+			<File
+				RelativePath="..\generated_marshallers.cpp"
+				>
+			</File>
+			<File
+				RelativePath="..\generated_marshallers1.cpp"
+				>
+			</File>
+			<File
 				RelativePath="..\glz_decoder.cpp"
 				>
 			</File>
@@ -504,14 +516,6 @@
 				>
 			</File>
 			<File
-				RelativePath="..\generated_marshallers.cpp"
-				>
-			</File>
-			<File
-				RelativePath="..\generated_marshallers.h"
-				>
-			</File>
-			<File
 				RelativePath="..\..\common\win\my_getopt-1.5\getopt.h"
 				>
 			</File>
@@ -717,7 +721,7 @@
 					Description="Generating demarshaller"
 					CommandLine="generate.bat"
 					AdditionalDependencies=""
-					Outputs="$(ProjectDir)/../generated_demarshallers.cpp;$(ProjectDir)/../generated_marshallers.h;$(ProjectDir)/../generated_marshallers.cpp"
+					Outputs="$(ProjectDir)/../generated_demarshallers.cpp;$(ProjectDir)/../generated_marshallers.cpp"
 				/>
 			</FileConfiguration>
 			<FileConfiguration
@@ -727,7 +731,32 @@
 					Name="VCCustomBuildTool"
 					Description="Generating demarshaller"
 					CommandLine="generate.bat"
-					Outputs="$(ProjectDir)/../generated_demarshallers.cpp;$(ProjectDir)/../generated_marshallers.h;$(ProjectDir)/../generated_marshallers.cpp"
+					Outputs="$(ProjectDir)/../generated_demarshallers.cpp;$(ProjectDir)/../generated_marshallers.cpp"
+				/>
+			</FileConfiguration>
+		</File>
+		<File
+			RelativePath="..\..\spice1.proto"
+			>
+			<FileConfiguration
+				Name="Debug|Win32"
+				>
+				<Tool
+					Name="VCCustomBuildTool"
+					Description="Generating old demarshaller"
+					CommandLine="generate1.bat"
+					AdditionalDependencies=""
+					Outputs="$(ProjectDir)/../generated_demarshallers1.cpp;$(ProjectDir)/../generated_marshallers1.cpp"
+				/>
+			</FileConfiguration>
+			<FileConfiguration
+				Name="Release|Win32"
+				>
+				<Tool
+					Name="VCCustomBuildTool"
+					Description="Generating old demarshaller"
+					CommandLine="generate1.bat"
+					Outputs="$(ProjectDir)/../generated_demarshallers1.cpp;$(ProjectDir)/../generated_marshallers1.cpp"
 				/>
 			</FileConfiguration>
 		</File>
diff --git a/client/x11/Makefile.am b/client/x11/Makefile.am
index 394eed0..d92a96d 100644
--- a/client/x11/Makefile.am
+++ b/client/x11/Makefile.am
@@ -38,9 +38,11 @@ RED_COMMON_SRCS =					\
 	$(CLIENT_DIR)/cache.hpp				\
 	$(CLIENT_DIR)/demarshallers.h			\
 	$(CLIENT_DIR)/generated_demarshallers.cpp	\
+	$(CLIENT_DIR)/generated_demarshallers1.cpp	\
 	$(CLIENT_DIR)/marshaller.cpp			\
 	$(CLIENT_DIR)/marshallers.h			\
 	$(CLIENT_DIR)/generated_marshallers.cpp		\
+	$(CLIENT_DIR)/generated_marshallers1.cpp	\
 	$(CLIENT_DIR)/sw_canvas.cpp			\
 	$(CLIENT_DIR)/canvas.cpp			\
 	$(CLIENT_DIR)/canvas.h				\
commit ededfd7ebb94efac11a00982f52c59f5d44a0f43
Author: Alexander Larsson <alexl at redhat.com>
Date:   Tue Jun 22 16:31:40 2010 +0200

    Add spice1.proto describing the 0.4 version of the network protocolx

diff --git a/spice1.proto b/spice1.proto
new file mode 100644
index 0000000..0efe74b
--- /dev/null
+++ b/spice1.proto
@@ -0,0 +1,934 @@
+/* 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) @as_ptr(data_len);
+    } 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 @nomarshal;
+	uint8 zero @end @ctype(uint8_t) @zero  @nomarshal;
+    } 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 @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;
+
+    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,
+};
+
+flags8 image_flags {
+    CACHE_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,
+};
+
+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 @outvar(cliprects);
+    case PATH:
+        Path *data @outvar(clippath);
+    } u @anon;
+};
+
+struct DisplayBase {
+    uint32 surface_id @virtual(0);
+    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 @outvar(bitmap);
+    } 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 @nomarshal;
+} @ctype(SpiceQUICData);
+
+struct LZPLTData {
+    bitmap_flags flags;
+    uint32 data_size;
+    switch (flags) {
+    case PAL_FROM_CACHE:
+	uint64 palette;
+    default:
+	Palette *palette @nonnull @outvar(lzplt);
+    } pal @anon;
+    uint8 data[data_size] @end @nomarshal;
+};
+
+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:
+        BinaryData binary_data @ctype(SpiceQUICData);
+    case LZ_PLT:
+        LZPLTData lzplt_data @ctype(SpiceLZPLTData);
+    } 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 @nomarshal;
+};
+
+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 @virtual(0);
+	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  @nomarshal;
+	uint8 padding[pad_size] @end @ctype(uint8_t)  @nomarshal; /* 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 @outvar(brush);
+	    uint16 rop_decriptor;
+	    QMask mask @outvar(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 @outvar(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 @outvar(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 @outvar(mask);
+	} @ctype(SpiceCopy) data;
+    } draw_blend;
+
+    message {
+	DisplayBase base;
+	struct Blackness {
+	    QMask mask @outvar(mask);
+	} data;
+    } draw_blackness;
+
+    message {
+	DisplayBase base;
+	struct Whiteness {
+	    QMask mask @outvar(mask);
+	} data;
+    } draw_whiteness;
+
+    message {
+	DisplayBase base;
+	struct Invers {
+	    QMask mask @outvar(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 @outvar(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 @outvar(fore_brush);
+	    Brush back_brush @outvar(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 {
+	    int8 alpha_flags @virtual(0);
+	    uint8 alpha;
+	    Image *src_bitmap;
+	    Rect src_area;
+	} data;
+    } draw_alpha_blend;
+
+ 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 @as_ptr(data_size);
+};
+
+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 @as_ptr(data_size);
+    } @ctype(SpiceMsgPlaybackPacket) data = 101;
+
+    message {
+	uint32 time;
+	audio_data_mode mode;
+	uint8 data[] @end @as_ptr(data_size);
+    } 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 @nomarshal @as_ptr(data_size);
+    } @ctype(SpiceMsgcRecordPacket) data = 101;
+
+    message {
+	uint32 time;
+	audio_data_mode mode;
+	uint8 data[] @end @as_ptr(data_size);
+    } mode;
+
+    message {
+	uint32 time;
+    } start_mark;
+};
+
+protocol Spice {
+    MainChannel main = 1;
+    DisplayChannel display;
+    InputsChannel inputs;
+    CursorChannel cursor;
+    PlaybackChannel playback;
+    RecordChannel record;
+};
commit 381025b1c3101548f478dacfa09fa13596a6d1d8
Author: Alexander Larsson <alexl at redhat.com>
Date:   Tue Jun 22 16:03:34 2010 +0200

    Add support for @virtual markup in spice protocol
    
    This means the member is not sent on the network at all.
    Instead its initialized to the attribute argument when demarshalled.
    
    This is useful for backwards compatibility support.

diff --git a/python_modules/demarshal.py b/python_modules/demarshal.py
index eee659f..a0697a9 100644
--- a/python_modules/demarshal.py
+++ b/python_modules/demarshal.py
@@ -400,6 +400,9 @@ def write_validate_item(writer, container, item, scope, parent_scope, start,
 
 def write_validate_member(writer, container, member, parent_scope, start,
                           want_nw_size, want_mem_size, want_extra_size):
+    if member.has_attr("virtual"):
+        return
+
     if member.has_minor_attr():
         prefix = "if (minor >= %s)" % (member.get_minor_attr())
         newline = False
@@ -740,6 +743,10 @@ def write_parse_pointer(writer, t, at_end, dest, member_name, is_64bit, scope):
         writer.statement("n_ptr++")
 
 def write_member_parser(writer, container, member, dest, scope):
+    if member.has_attr("virtual"):
+        writer.assign(dest.get_ref(member.name), member.attributes["virtual"][0])
+        return
+
     if member.is_switch():
         write_switch_parser(writer, container, member, dest, scope)
         return
diff --git a/python_modules/marshal.py b/python_modules/marshal.py
index c4bb896..c5afd7c 100644
--- a/python_modules/marshal.py
+++ b/python_modules/marshal.py
@@ -266,6 +266,9 @@ def write_switch_marshaller(writer, container, switch, src, scope):
 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("virtual"):
+        writer.comment("Don't marshall @virtual %s" % member.name).newline()
+        return
     if member.has_attr("nomarshal"):
         writer.comment("Don't marshall @nomarshal %s" % member.name).newline()
         return
diff --git a/python_modules/ptypes.py b/python_modules/ptypes.py
index fe8a321..101538c 100644
--- a/python_modules/ptypes.py
+++ b/python_modules/ptypes.py
@@ -518,9 +518,13 @@ class Member(Containee):
         return self.has_end_attr()
 
     def is_fixed_nw_size(self):
+        if self.has_attr("virtual"):
+            return True
         return self.member_type.is_fixed_nw_size()
 
     def get_fixed_nw_size(self):
+        if self.has_attr("virtual"):
+            return 0
         size = self.member_type.get_fixed_nw_size()
         if self.has_minor_attr():
             minor = self.get_minor_attr()
commit 759a3d5446a5ebeaf074529c28bc97ad0599ef39
Author: Alexander Larsson <alexl at redhat.com>
Date:   Tue Jun 22 16:03:02 2010 +0200

    Make internal generated marshaller functions static

diff --git a/python_modules/demarshal.py b/python_modules/demarshal.py
index 8d86e84..eee659f 100644
--- a/python_modules/demarshal.py
+++ b/python_modules/demarshal.py
@@ -149,7 +149,7 @@ def write_validate_struct_function(writer, struct):
 
     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 = writer.function(validate_function, "static 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");
@@ -661,7 +661,7 @@ def write_parse_ptr_function(writer, target_type):
     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 = writer.function(parse_function, "static 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")
 
@@ -932,7 +932,7 @@ def write_channel_parser(writer, channel, server):
         function_name = "parse_%s_msgc" % channel.name
     writer.newline()
     scope = writer.function(function_name,
-                            "uint8_t *",
+                            "static uint8_t *",
                             "uint8_t *message_start, uint8_t *message_end, uint16_t message_type, int minor, size_t *size_out, message_destructor_t *free_message")
 
     helpers = writer.function_helper()
diff --git a/python_modules/marshal.py b/python_modules/marshal.py
index 76081a9..c4bb896 100644
--- a/python_modules/marshal.py
+++ b/python_modules/marshal.py
@@ -115,7 +115,7 @@ def write_marshal_ptr_function(writer, target_type):
     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)
+        scope = writer.function(marshal_function, "SPICE_GNUC_UNUSED static 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 + ");")
commit c621b2bdf14bbc596ec90e917a2c40fa8dc8a4e8
Author: Alexander Larsson <alexl at redhat.com>
Date:   Tue Jun 22 16:01:57 2010 +0200

    Support extra prefix in code generators
    
    This is require when we add a new spice.proto for the old (major 1)
    protocol description.

diff --git a/python_modules/codegen.py b/python_modules/codegen.py
index 5bb659a..af6636b 100644
--- a/python_modules/codegen.py
+++ b/python_modules/codegen.py
@@ -113,6 +113,7 @@ class CodeWriter:
         writer.at_line_start = self.at_line_start
         writer.generated = self.generated
         writer.options = self.options
+        writer.public_prefix = self.public_prefix
 
         return writer;
 
diff --git a/python_modules/demarshal.py b/python_modules/demarshal.py
index b1c4135..8d86e84 100644
--- a/python_modules/demarshal.py
+++ b/python_modules/demarshal.py
@@ -966,9 +966,9 @@ def write_channel_parser(writer, channel, server):
 def write_get_channel_parser(writer, channel_parsers, max_channel, is_server):
     writer.newline()
     if is_server:
-        function_name = "spice_get_server_channel_parser"
+        function_name = "spice_get_server_channel_parser" + writer.public_prefix
     else:
-        function_name = "spice_get_client_channel_parser"
+        function_name = "spice_get_client_channel_parser" + writer.public_prefix
 
     scope = writer.function(function_name,
                             "spice_parse_channel_func_t",
@@ -1015,15 +1015,15 @@ def write_full_protocol_parser(writer, is_server):
         function_name = "spice_parse_msg"
     else:
         function_name = "spice_parse_reply"
-    scope = writer.function(function_name,
+    scope = writer.function(function_name + writer.public_prefix,
                             "uint8_t *",
                             "uint8_t *message_start, uint8_t *message_end, uint32_t channel, uint16_t message_type, int minor, size_t *size_out, message_destructor_t *free_message")
     scope.variable_def("spice_parse_channel_func_t", "func" )
 
     if is_server:
-        writer.assign("func", "spice_get_server_channel_parser(channel, NULL)")
+        writer.assign("func", "spice_get_server_channel_parser%s(channel, NULL)" % writer.public_prefix)
     else:
-        writer.assign("func", "spice_get_client_channel_parser(channel, NULL)")
+        writer.assign("func", "spice_get_client_channel_parser%s(channel, NULL)" % writer.public_prefix)
 
     with writer.if_block("func != NULL"):
         writer.statement("return func(message_start, message_end, message_type, minor, size_out, free_message)")
diff --git a/python_modules/marshal.py b/python_modules/marshal.py
index 4279cf0..76081a9 100644
--- a/python_modules/marshal.py
+++ b/python_modules/marshal.py
@@ -360,7 +360,7 @@ def write_protocol_marshaller(writer, proto, is_server, private_marshallers):
                 functions[f] = True
 
     if private_marshallers:
-        scope = writer.function("spice_message_marshallers_get",
+        scope = writer.function("spice_message_marshallers_get" +  writer.public_prefix,
                                 "SpiceMessageMarshallers *",
                                 "void")
         writer.writeln("static SpiceMessageMarshallers marshallers = {NULL};").newline()
diff --git a/spice_codegen.py b/spice_codegen.py
index 0034250..1d2314a 100755
--- a/spice_codegen.py
+++ b/spice_codegen.py
@@ -113,6 +113,8 @@ parser.add_option("-k", "--keep-identical-file",
 parser.add_option("-i", "--include",
                   action="append", dest="includes", metavar="FILE",
                   help="Include FILE in generated code")
+parser.add_option("--prefix", dest="prefix",
+                  help="set public symbol prefix", default="")
 
 (options, args) = parser.parse_args()
 
@@ -134,6 +136,8 @@ writer = codegen.CodeWriter()
 writer.header = codegen.CodeWriter()
 writer.set_option("source", os.path.basename(proto_file))
 
+writer.public_prefix = options.prefix
+
 if options.assert_on_error:
     writer.set_option("assert_on_error")
 
commit 36fd22a9db6edee0cc1700eeeab36a9f084a31d8
Author: Alexander Larsson <alexl at redhat.com>
Date:   Tue Jun 22 12:03:21 2010 +0200

    Add more emacs mode headers

diff --git a/client/red_channel.cpp b/client/red_channel.cpp
index a65917a..2e6130c 100644
--- a/client/red_channel.cpp
+++ b/client/red_channel.cpp
@@ -1,3 +1,4 @@
+/* -*- Mode: C; c-basic-offset: 4; indent-tabs-mode: nil -*- */
 /*
    Copyright (C) 2009 Red Hat, Inc.
 
diff --git a/client/red_peer.cpp b/client/red_peer.cpp
index 9a608ad..2d9f5b9 100644
--- a/client/red_peer.cpp
+++ b/client/red_peer.cpp
@@ -1,3 +1,4 @@
+/* -*- Mode: C; c-basic-offset: 4; indent-tabs-mode: nil -*- */
 /*
    Copyright (C) 2009 Red Hat, Inc.
 
commit 5c05a24ba14b1942309a703866aac76772f5f201
Author: Alexander Larsson <alexl at redhat.com>
Date:   Tue Jun 22 10:35:03 2010 +0200

    Convert client to use indirect calls for message marshalling
    
    This is required to support multiple versions

diff --git a/client/Makefile.am b/client/Makefile.am
index fb69ce6..5c0ec8d 100644
--- a/client/Makefile.am
+++ b/client/Makefile.am
@@ -3,17 +3,13 @@ NULL =
 SUBDIRS = . $(red_target)
 DIST_SUBDIRS = x11 #windows
 
-spice_built_sources = generated_demarshallers.cpp generated_marshallers.cpp generated_marshallers.h
+spice_built_sources = generated_demarshallers.cpp generated_marshallers.cpp
 
 generated_demarshallers.cpp: $(top_srcdir)/spice.proto
 	$(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) --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
+	$(PYTHON) $(top_srcdir)/spice_codegen.py --generate-marshallers -P --include messages.h --include marshallers.h --client $(top_srcdir)/spice.proto generated_marshallers.cpp
 
 if SUPPORT_GL
 GL_SRCS =				\
@@ -46,10 +42,10 @@ RED_COMMON_SRCS =			\
 	cmd_line_parser.h		\
 	common.h			\
 	demarshallers.h			\
+	marshallers.h			\
 	generated_demarshallers.cpp	\
 	marshaller.cpp			\
 	generated_marshallers.cpp	\
-	generated_marshallers.h		\
 	cursor_channel.cpp		\
 	cursor_channel.h		\
 	cursor.cpp			\
diff --git a/client/display_channel.cpp b/client/display_channel.cpp
index 5286aed..67c3083 100644
--- a/client/display_channel.cpp
+++ b/client/display_channel.cpp
@@ -42,7 +42,6 @@
 #include "inputs_channel.h"
 #include "cursor_channel.h"
 #include "mjpeg_decoder.h"
-#include "generated_marshallers.h"
 
 class CreatePrimarySurfaceEvent: public SyncEvent {
 public:
@@ -1029,7 +1028,7 @@ void DisplayChannel::on_connect()
     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);
+    _marshallers->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 6fd0b4f..09fc9e1 100644
--- a/client/inputs_channel.cpp
+++ b/client/inputs_channel.cpp
@@ -22,7 +22,6 @@
 #include "red_client.h"
 #include "application.h"
 #include "display_channel.h"
-#include "generated_marshallers.h"
 
 #define SYNC_REMOTH_MODIFIRES
 
@@ -127,10 +126,8 @@ void MotionMessage::release()
 
 RedPeer::OutMessage& MotionMessage::peer_message()
 {
-    SpiceMsgcMouseMotion motion;
 
-    _channel.set_motion_event(motion);
-    spice_marshall_msgc_inputs_mouse_motion(_marshaller, &motion);
+    _channel.marshall_motion_event(_marshaller);
 
     return *this;
 }
@@ -159,9 +156,7 @@ void PositionMessage::release()
 
 RedPeer::OutMessage& PositionMessage::peer_message()
 {
-    SpiceMsgcMousePosition pos;
-    _channel.set_position_event(pos);
-    spice_marshall_msgc_inputs_mouse_position(_marshaller, &pos);
+    _channel.marshall_position_event(_marshaller);
     return *this;
 }
 
@@ -260,18 +255,23 @@ void InputsChannel::handle_motion_ack(RedPeer::InMessage* message)
     }
 }
 
-void InputsChannel::set_motion_event(SpiceMsgcMouseMotion& motion)
+void InputsChannel::marshall_motion_event(SpiceMarshaller *marshaller)
 {
+    SpiceMsgcMouseMotion motion;
+
     Lock lock(_motion_lock);
     motion.buttons_state = _mouse_buttons_state;
     motion.dx = _mouse_dx;
     motion.dy = _mouse_dy;
     _mouse_dx = _mouse_dy = 0;
     _active_motion = false;
+
+    _marshallers->msgc_inputs_mouse_motion(marshaller, &motion);
 }
 
-void InputsChannel::set_position_event(SpiceMsgcMousePosition& position)
+void InputsChannel::marshall_position_event(SpiceMarshaller *marshaller)
 {
+    SpiceMsgcMousePosition position;
     Lock lock(_motion_lock);
     position.buttons_state = _mouse_buttons_state;
     position.x = _mouse_x;
@@ -280,6 +280,7 @@ void InputsChannel::set_position_event(SpiceMsgcMousePosition& position)
     _mouse_x = _mouse_y = ~0;
     _display_id = -1;
     _active_motion = false;
+    _marshallers->msgc_inputs_mouse_position(marshaller, &position);
 }
 
 void InputsChannel::on_mouse_motion(int dx, int dy, int buttons_state)
@@ -322,7 +323,7 @@ void InputsChannel::on_mouse_down(int button, int buttons_state)
     SpiceMsgcMousePress event;
     event.button = button;
     event.buttons_state = buttons_state;
-    spice_marshall_msgc_inputs_mouse_press(message->marshaller(), &event);
+    _marshallers->msgc_inputs_mouse_press(message->marshaller(), &event);
 
     post_message(message);
 }
@@ -335,7 +336,7 @@ void InputsChannel::on_mouse_up(int button, int buttons_state)
     SpiceMsgcMouseRelease event;
     event.button = button;
     event.buttons_state = buttons_state;
-    spice_marshall_msgc_inputs_mouse_release(message->marshaller(), &event);
+    _marshallers->msgc_inputs_mouse_release(message->marshaller(), &event);
     post_message(message);
 }
 
@@ -362,7 +363,7 @@ void InputsChannel::on_key_down(RedKey key)
     Message* message = new Message(SPICE_MSGC_INPUTS_KEY_DOWN);
     SpiceMsgcKeyDown event;
     event.code = scan_code;
-    spice_marshall_msgc_inputs_key_down(message->marshaller(), &event);
+    _marshallers->msgc_inputs_key_down(message->marshaller(), &event);
 
     post_message(message);
 }
@@ -378,7 +379,7 @@ void InputsChannel::on_key_up(RedKey key)
     Message* message = new Message(SPICE_MSGC_INPUTS_KEY_UP);
     SpiceMsgcKeyUp event;
     event.code = scan_code;
-    spice_marshall_msgc_inputs_key_up(message->marshaller(), &event);
+    _marshallers->msgc_inputs_key_up(message->marshaller(), &event);
     post_message(message);
 }
 
@@ -407,7 +408,7 @@ void InputsChannel::on_focus_in()
     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);
+    _marshallers->msgc_inputs_key_modifiers(message->marshaller(), &modifiers);
     post_message(message);
 #else
     set_local_modifiers();
diff --git a/client/inputs_channel.h b/client/inputs_channel.h
index 59a7923..9a0e8ff 100644
--- a/client/inputs_channel.h
+++ b/client/inputs_channel.h
@@ -45,8 +45,8 @@ protected:
     virtual void on_migrate();
 
 private:
-    void set_motion_event(SpiceMsgcMouseMotion& motion_event);
-    void set_position_event(SpiceMsgcMousePosition& position_event);
+    void marshall_motion_event(SpiceMarshaller *marshaller);
+    void marshall_position_event(SpiceMarshaller *marshaller);
     void set_local_modifiers();
 
     void handle_init(RedPeer::InMessage* message);
diff --git a/client/marshallers.h b/client/marshallers.h
new file mode 100644
index 0000000..7806f29
--- /dev/null
+++ b/client/marshallers.h
@@ -0,0 +1,60 @@
+/* -*- 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_MARSHALLERS
+#define _H_MARSHALLERS
+
+#include <spice/protocol.h>
+#include <marshaller.h>
+#include <messages.h>
+
+typedef struct {
+    void (*SpiceMsgEmpty)(SpiceMarshaller *m, SpiceMsgEmpty *msg);
+    void (*SpiceMsgData)(SpiceMarshaller *m, SpiceMsgData *msg);
+    void (*msgc_ack_sync)(SpiceMarshaller *m, SpiceMsgcAckSync *msg);
+    void (*msgc_pong)(SpiceMarshaller *m, SpiceMsgPing *msg);
+    void (*msgc_disconnecting)(SpiceMarshaller *m, SpiceMsgDisconnect *msg);
+    void (*msgc_main_client_info)(SpiceMarshaller *m, SpiceMsgcClientInfo *msg);
+    void (*msgc_main_mouse_mode_request)(SpiceMarshaller *m, SpiceMsgcMainMouseModeRequest *msg);
+    void (*msgc_main_agent_start)(SpiceMarshaller *m, SpiceMsgcMainAgentStart *msg);
+    void (*msgc_main_agent_token)(SpiceMarshaller *m, SpiceMsgcMainAgentTokens *msg);
+    void (*msgc_display_init)(SpiceMarshaller *m, SpiceMsgcDisplayInit *msg);
+    void (*msgc_inputs_key_down)(SpiceMarshaller *m, SpiceMsgcKeyDown *msg);
+    void (*msgc_inputs_key_up)(SpiceMarshaller *m, SpiceMsgcKeyUp *msg);
+    void (*msgc_inputs_key_modifiers)(SpiceMarshaller *m, SpiceMsgcKeyModifiers *msg);
+    void (*msgc_inputs_mouse_motion)(SpiceMarshaller *m, SpiceMsgcMouseMotion *msg);
+    void (*msgc_inputs_mouse_position)(SpiceMarshaller *m, SpiceMsgcMousePosition *msg);
+    void (*msgc_inputs_mouse_press)(SpiceMarshaller *m, SpiceMsgcMousePress *msg);
+    void (*msgc_inputs_mouse_release)(SpiceMarshaller *m, SpiceMsgcMouseRelease *msg);
+    void (*msgc_record_data)(SpiceMarshaller *m, SpiceMsgcRecordPacket *msg);
+    void (*msgc_record_mode)(SpiceMarshaller *m, SpiceMsgcRecordMode *msg);
+    void (*msgc_record_start_mark)(SpiceMarshaller *m, SpiceMsgcRecordStartMark *msg);
+    void (*msgc_tunnel_service_add)(SpiceMarshaller *m, SpiceMsgcTunnelAddGenericService *msg, SpiceMarshaller **name_out, SpiceMarshaller **description_out);
+    void (*msgc_tunnel_service_remove)(SpiceMarshaller *m, SpiceMsgcTunnelRemoveService *msg);
+    void (*msgc_tunnel_socket_open_ack)(SpiceMarshaller *m, SpiceMsgcTunnelSocketOpenAck *msg);
+    void (*msgc_tunnel_socket_open_nack)(SpiceMarshaller *m, SpiceMsgcTunnelSocketOpenNack *msg);
+    void (*msgc_tunnel_socket_fin)(SpiceMarshaller *m, SpiceMsgcTunnelSocketFin *msg);
+    void (*msgc_tunnel_socket_closed)(SpiceMarshaller *m, SpiceMsgcTunnelSocketClosed *msg);
+    void (*msgc_tunnel_socket_closed_ack)(SpiceMarshaller *m, SpiceMsgcTunnelSocketClosedAck *msg);
+    void (*msgc_tunnel_socket_data)(SpiceMarshaller *m, SpiceMsgcTunnelSocketData *msg);
+    void (*msgc_tunnel_socket_token)(SpiceMarshaller *m, SpiceMsgcTunnelSocketTokens *msg);
+} SpiceMessageMarshallers;
+
+SpiceMessageMarshallers *spice_message_marshallers_get(void);
+
+#endif
diff --git a/client/record_channel.cpp b/client/record_channel.cpp
index 155e8d9..084866c 100644
--- a/client/record_channel.cpp
+++ b/client/record_channel.cpp
@@ -19,7 +19,6 @@
 #include "red_client.h"
 #include "audio_channels.h"
 #include "audio_devices.h"
-#include "generated_marshallers.h"
 
 #define NUM_SAMPLES_MESSAGES 4
 
@@ -122,7 +121,7 @@ void RecordChannel::on_connect()
     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);
+    _marshallers->msgc_record_mode(message->marshaller(), &mode);
     post_message(message);
 }
 
@@ -131,7 +130,7 @@ void RecordChannel::send_start_mark()
     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);
+    _marshallers->msgc_record_start_mark(message->marshaller(), &start_mark);
     post_message(message);
 }
 
@@ -260,7 +259,7 @@ void RecordChannel::push_frame(uint8_t *frame)
     peer_message.reset(SPICE_MSGC_RECORD_DATA);
     SpiceMsgcRecordPacket packet;
     packet.time = get_mm_time();
-    spice_marshall_msgc_record_data(peer_message.marshaller(), &packet);
+    _marshallers->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 7065b0a..a65917a 100644
--- a/client/red_channel.cpp
+++ b/client/red_channel.cpp
@@ -21,7 +21,6 @@
 #include "application.h"
 #include "debug.h"
 #include "utils.h"
-#include "generated_marshallers.h"
 
 #include "openssl/rsa.h"
 #include "openssl/evp.h"
@@ -258,6 +257,7 @@ RedChannel::RedChannel(RedClient& client, uint8_t type, uint8_t id,
 {
     _loop.add_trigger(_send_trigger);
     _loop.add_trigger(_abort_trigger);
+    _marshallers = spice_message_marshallers_get();
 }
 
 RedChannel::~RedChannel()
@@ -646,7 +646,7 @@ void RedChannel::handle_set_ack(RedPeer::InMessage* message)
     Message *response = new Message(SPICE_MSGC_ACK_SYNC);
     SpiceMsgcAckSync sync;
     sync.generation = ack->generation;
-    spice_marshall_msgc_ack_sync(response->marshaller(), &sync);
+    _marshallers->msgc_ack_sync(response->marshaller(), &sync);
     post_message(response);
 }
 
@@ -654,7 +654,7 @@ void RedChannel::handle_ping(RedPeer::InMessage* message)
 {
     SpiceMsgPing *ping = (SpiceMsgPing *)message->data();
     Message *pong = new Message(SPICE_MSGC_PONG);
-    spice_marshall_msgc_pong(pong->marshaller(), ping);
+    _marshallers->msgc_pong(pong->marshaller(), ping);
     post_message(pong);
 }
 
diff --git a/client/red_channel.h b/client/red_channel.h
index c2528ab..d973a45 100644
--- a/client/red_channel.h
+++ b/client/red_channel.h
@@ -25,6 +25,7 @@
 #include "platform.h"
 #include "process_loop.h"
 #include "demarshallers.h"
+#include "marshallers.h"
 
 enum {
     PASSIVE_STATE,
@@ -144,6 +145,8 @@ protected:
     void handle_disconnect(RedPeer::InMessage* message);
     void handle_notify(RedPeer::InMessage* message);
 
+    SpiceMessageMarshallers *_marshallers;
+
 private:
     void set_state(int state);
     void run();
diff --git a/client/red_client.cpp b/client/red_client.cpp
index c079f3d..f5b52d6 100644
--- a/client/red_client.cpp
+++ b/client/red_client.cpp
@@ -22,7 +22,7 @@
 #include "process_loop.h"
 #include "utils.h"
 #include "debug.h"
-#include "generated_marshallers.h"
+#include "marshallers.h"
 
 #ifdef __GNUC__
 typedef struct __attribute__ ((__packed__)) OldRedMigrationBegin {
@@ -701,7 +701,7 @@ void RedClient::set_mouse_mode(uint32_t supported_modes, uint32_t current_mode)
         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(),
+	_marshallers->msgc_main_mouse_mode_request(message->marshaller(),
 						    &mouse_mode_request);
 
         post_message(message);
@@ -722,7 +722,7 @@ void RedClient::handle_init(RedPeer::InMessage* message)
         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);
+	_marshallers->msgc_main_agent_start(msg->marshaller(), &agent_start);
         post_message(msg);
     }
     if (_auto_display_res) {
@@ -763,7 +763,7 @@ void RedClient::handle_agent_connected(RedPeer::InMessage* message)
     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);
+    _marshallers->msgc_main_agent_start(msg->marshaller(), &agent_start);
     post_message(msg);
     if (_auto_display_res && !_agent_mon_config_sent) {
         send_agent_monitors_config();
diff --git a/client/tunnel_channel.cpp b/client/tunnel_channel.cpp
index 1464b1d..0b55aff 100644
--- a/client/tunnel_channel.cpp
+++ b/client/tunnel_channel.cpp
@@ -21,7 +21,6 @@
 
 #include "common.h"
 #include "tunnel_channel.h"
-#include "generated_marshallers.h"
 #include <spice/protocol.h>
 
 #define SOCKET_WINDOW_SIZE 60
@@ -100,7 +99,8 @@ public:
     virtual void release_buf();
 
     static void init(uint32_t max_data_size);
-    static OutSocketMessage& alloc_message(uint16_t id);
+    static OutSocketMessage& alloc_message(uint16_t id, SpiceMessageMarshallers *marshallers);
+
     static void clear_free_messages();
 
 protected:
@@ -143,7 +143,7 @@ void OutSocketMessage::init(uint32_t max_data_size)
     _max_data_size = max_data_size;
 }
 
-OutSocketMessage& OutSocketMessage::alloc_message(uint16_t id)
+OutSocketMessage& OutSocketMessage::alloc_message(uint16_t id, SpiceMessageMarshallers *marshallers)
 {
     OutSocketMessage* ret;
     if (!_free_messages.empty()) {
@@ -156,7 +156,7 @@ OutSocketMessage& OutSocketMessage::alloc_message(uint16_t id)
 
     SpiceMsgcTunnelSocketData data;
     data.connection_id = id;
-    spice_marshall_msgc_tunnel_socket_data(ret->marshaller(), &data);
+    marshallers->msgc_tunnel_socket_data(ret->marshaller(), &data);
     ret->_the_buf = spice_marshaller_reserve_space(ret->marshaller(), _max_data_size);
 
     return *ret;
@@ -189,7 +189,7 @@ struct TunnelService {
 class TunnelChannel::TunnelSocket: public ClientNetSocket {
 public:
     TunnelSocket(uint16_t id, TunnelService& dst_service, ProcessLoop& process_loop,
-                 EventHandler & event_handler);
+                 EventHandler & event_handler, SpiceMessageMarshallers *marshallers);
     virtual ~TunnelSocket() {}
 
     void set_num_tokens(uint32_t tokens) {_num_tokens = tokens;}
@@ -201,24 +201,27 @@ public:
     bool     get_guest_closed() {return _guest_closed;}
 
 protected:
-    virtual ReceiveBuffer& alloc_receive_buffer() {return OutSocketMessage::alloc_message(id());}
+    virtual ReceiveBuffer& alloc_receive_buffer() {return OutSocketMessage::alloc_message(id(), _marshallers);}
 
 private:
     uint32_t _num_tokens;
     uint32_t _server_num_tokens;
     uint32_t _service_id;
     bool _guest_closed;
+    SpiceMessageMarshallers *_marshallers;
 };
 
 TunnelChannel::TunnelSocket::TunnelSocket(uint16_t id, TunnelService& dst_service,
                                           ProcessLoop& process_loop,
-                                          ClientNetSocket::EventHandler& event_handler)
+                                          ClientNetSocket::EventHandler& event_handler,
+					  SpiceMessageMarshallers *marshallers)
     : ClientNetSocket(id, dst_service.ip, htons((uint16_t)dst_service.port),
                       process_loop, event_handler)
     , _num_tokens (0)
     , _server_num_tokens (0)
     , _service_id (dst_service.id)
     , _guest_closed (false)
+    , _marshallers(marshallers)
 {
 }
 
@@ -295,7 +298,7 @@ void TunnelChannel::send_service(TunnelService& service)
         add.ip.type = SPICE_TUNNEL_IP_TYPE_IPv4;
     }
 
-    spice_marshall_msgc_tunnel_service_add(service_msg->marshaller(), &add.base,
+    _marshallers->msgc_tunnel_service_add(service_msg->marshaller(), &add.base,
                                            &name_out, &description_out);
 
     if (service.type == SPICE_TUNNEL_SERVICE_TYPE_IPP) {
@@ -348,7 +351,7 @@ void TunnelChannel::handle_socket_open(RedPeer::InMessage* message)
               open_msg->service_id);
     }
 
-    sckt = new TunnelSocket(open_msg->connection_id, *service, get_process_loop(), *this);
+    sckt = new TunnelSocket(open_msg->connection_id, *service, get_process_loop(), *this, _marshallers);
 
     if (sckt->connect(open_msg->tokens)) {
         _sockets[open_msg->connection_id] = sckt;
@@ -358,12 +361,12 @@ void TunnelChannel::handle_socket_open(RedPeer::InMessage* message)
         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);
+        _marshallers->msgc_tunnel_socket_open_ack(out_msg->marshaller(), &ack);
     } else {
         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);
+        _marshallers->msgc_tunnel_socket_open_nack(out_msg->marshaller(), &nack);
         delete sckt;
     }
 
@@ -486,7 +489,7 @@ void TunnelChannel::on_socket_fin_recv(ClientNetSocket& sckt)
     DBG(0, "FIN from client coonection id=%d", tunnel_sckt->id());
     SpiceMsgcTunnelSocketFin fin;
     fin.connection_id = tunnel_sckt->id();
-    spice_marshall_msgc_tunnel_socket_fin(out_msg->marshaller(), &fin);
+    _marshallers->msgc_tunnel_socket_fin(out_msg->marshaller(), &fin);
     post_message(out_msg);
 }
 
@@ -500,7 +503,7 @@ void TunnelChannel::on_socket_disconnect(ClientNetSocket& sckt)
         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);
+        _marshallers->msgc_tunnel_socket_closed_ack(out_msg->marshaller(), &ack);
         _sockets[tunnel_sckt->id()] = NULL;
         delete &sckt;
     } else { // close initiated by client
@@ -508,7 +511,7 @@ void TunnelChannel::on_socket_disconnect(ClientNetSocket& sckt)
         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);
+        _marshallers->msgc_tunnel_socket_closed(out_msg->marshaller(), &closed);
     }
 
     post_message(out_msg);
@@ -525,7 +528,7 @@ void TunnelChannel::on_socket_message_send_done(ClientNetSocket& sckt)
         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);
+        _marshallers->msgc_tunnel_socket_token(out_msg->marshaller(), &tokens_msg);
         post_message(out_msg);
 
         tunnel_sckt->set_num_tokens(0);
diff --git a/client/x11/Makefile.am b/client/x11/Makefile.am
index 81036fb..394eed0 100644
--- a/client/x11/Makefile.am
+++ b/client/x11/Makefile.am
@@ -39,7 +39,7 @@ RED_COMMON_SRCS =					\
 	$(CLIENT_DIR)/demarshallers.h			\
 	$(CLIENT_DIR)/generated_demarshallers.cpp	\
 	$(CLIENT_DIR)/marshaller.cpp			\
-	$(CLIENT_DIR)/generated_marshallers.h		\
+	$(CLIENT_DIR)/marshallers.h			\
 	$(CLIENT_DIR)/generated_marshallers.cpp		\
 	$(CLIENT_DIR)/sw_canvas.cpp			\
 	$(CLIENT_DIR)/canvas.cpp			\
commit 5341b632e2b1d2527303cce3f69a8146a8d48489
Author: Alexander Larsson <alexl at redhat.com>
Date:   Tue Jun 22 10:32:08 2010 +0200

    Support creating marshallers that are called indirectly
    
    This is needed if we want to switch marshallers depending on what
    major version the remote side has.

diff --git a/python_modules/marshal.py b/python_modules/marshal.py
index 4cbf942..4279cf0 100644
--- a/python_modules/marshal.py
+++ b/python_modules/marshal.py
@@ -310,7 +310,7 @@ def write_container_marshaller(writer, container, src):
             writer.out_prefix = saved_out_prefix
             write_member_marshaller(writer, container, m, src, scope)
 
-def write_message_marshaller(writer, message, is_server):
+def write_message_marshaller(writer, message, is_server, private):
     writer.out_prefix = ""
     function_name = "spice_marshall_" + message.c_name()
     if writer.is_generated("marshaller", function_name):
@@ -323,10 +323,11 @@ def write_message_marshaller(writer, message, is_server):
         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 + ");")
+    if not private:
+        writer.header.writeln("void " + function_name + "(SpiceMarshaller *m, %s *msg" % message.c_type() + names_args + ");")
 
     scope = writer.function(function_name,
-                            "void",
+                            "static void" if private else "void",
                             "SpiceMarshaller *m, %s *msg" % message.c_type() + names_args)
     scope.variable_def("SPICE_GNUC_UNUSED uint8_t *", "end")
 
@@ -341,18 +342,36 @@ def write_message_marshaller(writer, message, is_server):
 
     writer.end_block()
     writer.newline()
+    return function_name
 
-def write_protocol_marshaller(writer, proto, is_server):
+def write_protocol_marshaller(writer, proto, is_server, private_marshallers):
+    functions = {}
     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)
+                f = write_message_marshaller(writer, message, is_server, private_marshallers)
+                functions[f] = True
         else:
             for m in channel.server_messages:
                 message = m.message_type
-                write_message_marshaller(writer, message, is_server)
+                f= write_message_marshaller(writer, message, is_server, private_marshallers)
+                functions[f] = True
+
+    if private_marshallers:
+        scope = writer.function("spice_message_marshallers_get",
+                                "SpiceMessageMarshallers *",
+                                "void")
+        writer.writeln("static SpiceMessageMarshallers marshallers = {NULL};").newline()
+        for f in sorted(functions.keys()):
+            member = f[len("spice_marshall_"):]
+            writer.assign("marshallers.%s" % member, f)
+
+        writer.newline()
+        writer.statement("return &marshallers")
+        writer.end_block()
+        writer.newline()
 
 def write_trailer(writer):
     writer.header.writeln("#endif")
diff --git a/spice_codegen.py b/spice_codegen.py
index c8d0d5f..0034250 100755
--- a/spice_codegen.py
+++ b/spice_codegen.py
@@ -86,6 +86,9 @@ parser.add_option("-d", "--generate-demarshallers",
 parser.add_option("-m", "--generate-marshallers",
                   action="store_true", dest="generate_marshallers", default=False,
                   help="Generate message marshallers")
+parser.add_option("-P", "--private-marshallers",
+                  action="store_true", dest="private_marshallers", default=False,
+                  help="Generate private message marshallers")
 parser.add_option("-M", "--generate-struct-marshaller",
                   action="append", dest="struct_marshallers",
                   help="Generate struct marshallers")
@@ -163,9 +166,9 @@ if options.generate_marshallers:
         print >> sys.stderr, "Must specify client and/or server"
         sys.exit(1)
     if options.server:
-        marshal.write_protocol_marshaller(writer, proto, False)
+        marshal.write_protocol_marshaller(writer, proto, False, options.private_marshallers)
     if options.client:
-        marshal.write_protocol_marshaller(writer, proto, True)
+        marshal.write_protocol_marshaller(writer, proto, True, options.private_marshallers)
 
 if options.struct_marshallers:
     for structname in options.struct_marshallers:


More information about the Spice-commits mailing list