diff options
author | Yonit Halperin <yhalperi@redhat.com> | 2011-09-20 14:59:36 +0300 |
---|---|---|
committer | Yonit Halperin <yhalperi@redhat.com> | 2011-11-02 11:30:31 +0200 |
commit | c39d842ff16be4303c48b4faa19f22cd7312b3c7 (patch) | |
tree | 2e1128735c57ab7b06bc8b1875a4114f61c656bc | |
parent | 3a1473760c0bb5da719e39ebe5cce02f5325904c (diff) |
client: support semi-seamless migration between spice servers with different protocols.
It can't actually happen right now, since switch-host migration scheme will take
place if the src/target server has protocol 1.
(cherry picked from commit 4b2bf4d88c253502003aa5e4b93a045742eec9b4 branch 0.8)
-rw-r--r-- | client/red_channel.cpp | 20 | ||||
-rw-r--r-- | client/red_channel.h | 2 | ||||
-rw-r--r-- | client/red_client.cpp | 21 | ||||
-rw-r--r-- | client/red_client.h | 3 |
4 files changed, 40 insertions, 6 deletions
diff --git a/client/red_channel.cpp b/client/red_channel.cpp index d85265b7..e8c058cc 100644 --- a/client/red_channel.cpp +++ b/client/red_channel.cpp @@ -298,6 +298,20 @@ bool RedChannelBase::test_capability(uint32_t cap) return test_capability(_remote_caps, cap); } +void RedChannelBase::swap(RedChannelBase* other) +{ + int tmp_ver; + + RedPeer::swap(other); + tmp_ver = _remote_major; + _remote_major = other->_remote_major; + other->_remote_major = tmp_ver; + + tmp_ver = _remote_minor; + _remote_minor = other->_remote_minor; + other->_remote_minor = tmp_ver; +} + SendTrigger::SendTrigger(RedChannel& channel) : _channel (channel) { @@ -493,6 +507,12 @@ void RedChannel::do_migration_disconnect_src() void RedChannel::do_migration_connect_target() { LOG_INFO(""); + ASSERT(get_client().get_protocol() != 0); + if (get_client().get_protocol() == 1) { + _marshallers = spice_message_marshallers_get1(); + } else { + _marshallers = spice_message_marshallers_get(); + } _loop.add_socket(*this); _socket_in_loop = true; on_connect_mig_target(); diff --git a/client/red_channel.h b/client/red_channel.h index ba78acce..ee5b1851 100644 --- a/client/red_channel.h +++ b/client/red_channel.h @@ -66,6 +66,8 @@ public: uint32_t get_peer_major() { return _remote_major;} uint32_t get_peer_minor() { return _remote_minor;} + virtual void swap(RedChannelBase* other); + protected: void set_common_capability(uint32_t cap); void set_capability(uint32_t cap); diff --git a/client/red_client.cpp b/client/red_client.cpp index 4fc442fb..2f6c6ce7 100644 --- a/client/red_client.cpp +++ b/client/red_client.cpp @@ -136,6 +136,7 @@ Migrate::Migrate(RedClient& client) , _connected (false) , _thread (NULL) , _pending_con (0) + , _protocol (0) { } @@ -192,7 +193,7 @@ void Migrate::swap_peer(RedChannelBase& other) curr->set_valid(false); if (!--_pending_con) { lock.unlock(); - _client.set_target(_host.c_str(), _port, _sport); + _client.set_target(_host.c_str(), _port, _sport, _protocol); abort(); } return; @@ -215,6 +216,13 @@ void Migrate::connect_one(MigChannel& channel, const RedPeer::ConnectionOptions& channel.connect(options, connection_id, _host.c_str(), _password); ++_pending_con; channel.set_valid(true); + if (_protocol == 0) { + if (channel.get_peer_major() == 1) { + _protocol = 1; + } else { + _protocol = 2; + } + } } void Migrate::run() @@ -235,7 +243,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_protocol(), + _protocol, _auth_options, _con_ciphers); connect_one(**iter, con_opt, connection_id); } @@ -445,11 +453,16 @@ RedClient::~RedClient() delete[] _agent_caps; } -void RedClient::set_target(const std::string& host, int port, int sport) +void RedClient::set_target(const std::string& host, int port, int sport, int protocol) { + if (protocol != get_protocol()) { + LOG_INFO("old protocol %d, new protocol %d", get_protocol(), protocol); + } + _port = port; _sport = sport; _host.assign(host); + set_protocol(protocol); } void RedClient::push_event(Event* event) @@ -684,10 +697,8 @@ void RedClient::on_channel_disconnect_mig_src_completed(RedChannel& channel) _pixmap_cache.clear(); _glz_window.clear(); memset(_sync_info, 0, sizeof(_sync_info)); - LOG_INFO("calling main to connect and wait for handle_init to tell all the other channels to connect"); RedChannel::connect_migration_target(); - AutoRef<MigrateEndEvent> mig_end_event(new MigrateEndEvent()); get_process_loop().push_event(*mig_end_event); } diff --git a/client/red_client.h b/client/red_client.h index 20d5ffb7..f4cd46b6 100644 --- a/client/red_client.h +++ b/client/red_client.h @@ -82,6 +82,7 @@ private: Mutex _lock; Condition _cond; int _pending_con; + int _protocol; }; class ChannelFactory { @@ -238,7 +239,7 @@ public: void activate_interval_timer(Timer* timer, unsigned int millisec); void deactivate_interval_timer(Timer* timer); - void set_target(const std::string& host, int port, int sport); + void set_target(const std::string& host, int port, int sport, int protocol = 0); void set_password(const std::string& password) { _password = password;} void set_auto_display_res(bool auto_display_res) { _auto_display_res = auto_display_res;} void set_display_setting(DisplaySetting& setting) { _display_setting = setting;} |