We will add a qemu call to spice_server_migrate_start when migration starts.
For now, it does nothing, but we may need this notification in the future.
(cherry picked from commit b821316771 branch 0.8)
(1) not sending anything to a migrated client till we recieve SPICE_MSGC_MIGRATE_END
(2) start a new client migration (handle client_migrate_info) only after SPICE_MSGC_MIGRATE_END
from the previous migration was received for this client
(3) use the correct ticket
Note: we assume the same channles are linked before and ater migration. i.e.,
SPICE_MSGC_MAIN_ATTACH_CHANNELS is not sent from the clients.
If the migration has completed successfully:
(1) send MSG_MAIN_MIGRATE_END to the clients that are connected to the target
(2) send MSG_MAIN_SWITCH_HOST to all the other clients
If the migration failed, send MSG_MAIN_MIGRATE_CANCEL to clients that are
connected to the target.
(cherry picked from commit 4b82580fc3 branch 0.8;
Was modified to support multiple clients, and the separation of main_channel from reds)
Conflicts:
server/reds.c
(1) send SPICE_MSG_MAIN_MIGRATE_BEGIN upon spice_server_migrate_connect
(to all the clients that support it)
(2) wait for SPICE_MSGC_MAIN_MIGRATE_(CONNECTED|CONNECT_ERROR) from all the relevant clients,
or a timeout, in order to complete client_migrate_info monitor command
(cherry picked from commit 5560c56ef0 branch 0.8;
Was modified to support the separation of main channel from reds, and multiple clients)
Conflicts:
server/reds.c
semi-seamless migration details:
migration source side
---------------------
(1) spice_server_migrate_connect (*): tell client to link
to the target side - send SPICE_MSG_MAIN_MIGRATE_BEGIN.
This should be called upon client_migrate_info cmd.
client_migrate_info is asynchronous.
(2) Complete spice_server_migrate_connect only when the client has been connected
to the target - wait for SPICE_MSGC_MAIN_MIGRATE_(CONNECTED|CONNECT_ERROR) or a timeout.
(3) spice_server_migrate_end: tell client migration it can switch to the target - send
SPICE_MSG_MAIN_MIGRATE_END.
(4) client cleans up all data related to the connection to the source and switches to the target.
It sends SPICE_MSGC_MAIN_MIGRATE_END.
migration target side
---------------------
(1) the server identifies itself as a migraiton target since the client is linked with (connection_id != 0)
(2) server doesn't start the channels' logic (channel->link) till it receives SPICE_MSGC_MAIN_MIGRATE_END
from the client.
* After migration starts, the target qemu is blocked and cannot accept new spice client
connections. Thus, we trigger the connection to the target upon client_migrate_info
command.
(cherry picked from commit 6e56bea67c branch 0.8)
Conflicts:
server/spice.h
The code for setting and testing channel capabilities was
unnecessarily duplicated. Now it is in red_channel.
RedsChannel was dropped from Reds; It was used only for holding
the channels common capabilities, which are now held in RedChannel.
add main_dispatcher, a message passing mechanism for sending messages to
the main thread. The main thread is the thread that implements
SpiceCoreInterface, which is assumed to be a single thread.
Similar to the async operation of red_worker, a socket pair is created
and used to pass messages. The messages are a fixed size to ease
parsing. A single message is defined to pass a channel_event.
RHBZ: 746950
FDBZ: 41858
This patch is 0.8 branch only, for the master branch there should be a
better approach to share code with red_dispatcher and ready the way for
later adding more threads.
cherry-pick from 0.8 80caf07e09
Conflicts:
server/reds.c
Several functions in server/ were not specifying an argument list,
ie they were declared as void foo(); When compiling with
-Wstrict-prototypes, this leads to:
test_playback.c:93:5: erreur: function declaration isn’t a prototype
[-Werror=strict-prototypes]
While discussing various things with Alon in Vancouver, it came up that
having a channel which simply passes through data coming out of a qemu
chardev frontend unmodified, like the usbredir channel does, can be used
for a lot of other cases too. To facilitate this the usbredir channel code
will be turned into a generic spicevmc channel, which is just a passthrough
to the client, from the spicevmc chardev.
This patch renames usbredir.c to spicevmc.c and changes the prefix of all
functions / structs to match. This should make clear that the code is not
usbredir specific.
Some examples of why having a generic spicevmc pass through is good:
1) We could add a monitor channel, allowing access to the qemu monitor from
the spice client, since the monitor is a chardev frontend we could re-use
the generic spicevmc channel server code, so all that is needed to add this
(server side) would be reserving a new channel id for this.
2) We could allow users to come up with new channels of their own, without
requiring qemu or server modification. The idea is to allow doing something
like this on the qemu startup cmdline:
-chardev spicevmc,name=generic,channelid=128
To ensure these new "generic" channels cannot conflict with newly added
official types, they must start at the SPICE_CHANNEL_USER_DEFINED_START value
(128).
These new user defined channels could then either be used with a special
modified client, with client plugins (if we add support for those), or
by exporting them on the client side for use by an external ap, see below.
3) We could also add support to the client to make user-defined channels
end in a unix socket / pipe, allowing handling of the data by an external app,
we could for example have a new spice client cmdline argument like this:
--custom-channel unixsocket=/tmp/mysocket,channelid=128
This would allow for something like:
$random app on guest -> virtio-serial -> spicevmc chardev ->
-> spicevmc channel -> unix socket -> $random app on client
4) On hind sight this could also have been used for the smartcard stuff,
with a 1 channel / reader model, rather then the current multiplexing code
where we've our own multiplexing protocol wrapper over the libcacard
smartcard protocol.
Signed-off-by: Hans de Goede <hdegoede@redhat.com>
Merging the functionality of reds::channel, into RedChannel.
In addition, cleanup and fix disconnection code: before this patch,
red_dispatcher_disconnect_display_client
could have been called from the red_worker thread
(and it must be called only from the io thread).
RedChannel holds only connected channel clients. RedClient holds all the
channel clients that were created till it is destroyed
(and then it destroys them as well).
Note: snd_channel still doesn't use red_channel, however it
creates dummy channel and channel clients, in order to register itself
in reds.
server/red_channel.c: a channel is connected if it holds at least one channel client
Previously I changed RedChannel to hold only connected channel clients and
RedClient, to hold all the channel clients as long as it is not destroyed.
usbredir: multichannel has not been tested, it just compiles.
The main channel deals with connecting new clients, announcing mouse mode
changes, and the agent channel. The implementation is currently done without
any changes to the protocol, so everything has to be either broadcast or
to a specific client.
channels list - specific client
mouse mode - broadcast
agent - broadcast
notify - broadcast (should have two modes, and use the appropriate)
Notable TODOs:
* migration testing
* agent tokens are wrongly sent (or did I fix that? check)
Expose additional api to find a client given a connection_id. The connection_id
is first set when the first channel connects, which is the main channel.
It could also be kept in the RedClient instead, not sure.
TODO:
multiple todo's added for multiclient handling. I don't remember why
I wrote them exactly, and besides if I did any migration tests. So: TODO.
cleanup only. Note that the ping function is half used since the opt parameter
stopped being called with anything but NULL, should be returned at some point,
specifically when we drop the 250kbyte ping on start and do a continuous check
for latency and bandwidth.
See:
81945d897 - server: add new vd interface QTerm2Interface, Yaniv Kamay
introducing the usage of ping with a non NULL opt
3f7ea8e7a - zap qterm interfaces, Gerd Hoffman
removing it
Secondary channels are those that don't support multiple clients. The
support added in this patch just doesn't let the second or more connected
client receive the unsupported channels in the channels list sent by the
server to the client. This doesn't handle the situation where:
client A connects (gets all channels)
client B connects (gets supported multiple client channels)
client A disconnects (Suboptimal 1: B doesn't get new channels at this point)
client C connects (Suboptimal 2: C doesn't get the full list of channels, but
the partial one)
Specifically the channels that only support a single client are:
sound (both playback and record channels)
smartcard
tunnel
That means RedClient tracks a ring of channels. Right now there will be only
a single client because of the disconnection mechanism - whenever a new
client comes we disconnect all existing clients. But this patch adds already
a ring of clients to reds.c (stored in RedServer).
There is a known problem handling many connections and disconnections at the
same time, trigerrable easily by the following script:
export NEW_DISPLAY=:3.0
Xephyr $NEW_DISPLAY -noreset &
for ((i = 0 ; i < 5; ++i)); do
for ((j = 0 ; j < 10; ++j)); do
DISPLAY=$NEW_DISPLAY c_win7x86_qxl_tests &
done
sleep 2;
done
I fixed a few of the problems resulting from this in the same patch. This
required already introducing a few other changes:
* make sure all removal of channels happens in the main thread, for that
two additional dispatcher calls are added to remove a specific channel
client (RED_WORKER_MESSAGE_CURSOR_DISCONNECT_CLIENT and
RED_WORKER_MESSAGE_DISPLAY_DISCONNECT_CLIENT).
* change some asserts in input channel.
* make main channel disconnect not recursive
* introduce disconnect call back to red_channel_create_parser
The remaining abort is from a double free in the main channel, still can't
find it (doesn't happen when running under valgrind - probably due to the
slowness resulting from that), but is easy to see when running under gdb.
use MainChannel* instead of Channel* for a many functions in main_channel.h
(affects main_channel.c and reds.c).
some one liner fixes are hidden in here too.
The check this patch removes causes us to not set vdagent to NULL, nor
update the mouse mode when the guest agent disconnects when no client is
attached. Which leads to a non working mouse, and on agent reconnect a
"spice_server_char_device_add_interface: vdagent already attached" message
instead of a successful re-add of the agent interface .
hansg: Note this is commit 443994ba from the 0.8 branch, which I did
not forward port back then because it seemed unnecessary on master, but it
turns out that the (wrong) check was just hidden in another place on master.
When qemu creates a channel, reds.c contains code to check the
minor/major channel versions known to QEMU (ie the ones that were
current in spice-server when QEMU was compiled) and to compare these
versions against the current ones the currently installed spice-server
version.
According to kraxel [1], the rules for these interface numbers are:
"The purpose of the versions is exactly to avoid the need for a new
soname. The rules are basically:
(1) You add stuff to the interface, strictly append-only to not break
binary compatibility.
(2) You bump the minor version of the interface.
(3) You check the minor version at runtime to figure whenever the
added fields contain valid stuff or not.
An example is here (core interface, minor goes from 2 to 3, new
channel_event callback):
http://cgit.freedesktop.org/spice/spice/commit/?id=97f33fa86aa6edd25111b173dc0d9599ac29f879
"
The code currently refuses to create a channel if QEMU minor version is
less than the current spice-server version. This does not correspond
to the intended behaviour, this patch changes to fail is qemu was compiled
with a spice-server that is *newer* than the one currently installed. This
case is something we cannot support nicely.
[1] http://lists.freedesktop.org/archives/spice-devel/2011-July/004440.html
qemu calls spice_server_migrate_switch even if it didn't do a
spice_server_migrate_info first. Fix the resulting error by not pushing
a switch host tag to the pipe in this case, and add a check anyway in the
marshalling code just in case.
With -Wpointer-arith, gcc complains about void pointer arithmetic.
This is not a big deal with gcc, but could be with other compilers,
so it's better to cast to char */uint8_t * before doing the
arithmetic on such pointers.
When using config.h, it must be the very first include in all source
files since it contains #define that may change the compilation process
(eg libc structure layout changes when it's used to enable large file
support on 32 bit x86 archs). This commit adds it at the beginning
of all .c and .cpp files
The check this patch removes causes us to not set vdagent to NULL, nor
update the mouse mode when the guest agent disconnects when no client is
attached. Which leads to a non working mouse, and on agent reconnect a
"spice_server_char_device_add_interface: vdagent already attached" message
instead of a successful re-add of the agent interface .
This ensures that if the client or agent connects to the client-agent
"tunnel" while the other side is halfway through sending a multi part
message, the rest of the message gets discarded, and the connecting
party starts getting data at the beginning of the next message.
The agent message filter keeps track of messages as they are being send
reset the relevant filter to its initial state when one of the 2 ends
of the agent<->client "tunnel" disconnects.
read_from_vdi_port calls dispatch_vdi_port data, which will disconnect
the guest agent if it sends invalid data. It would then try to read more
data from the disconnected guest agent resulting in a NULL ptr dereference,
this patch fixes this.
write_to_vdi_port() was checking for reds->agent_state.connected to determine
wether it could write queued data. But agent_state.connected reflects if
*both* ends are connected. If the client has disconnected, but the guest agent
is still connected and some data is still pending (like a final clipboard
release from the client), then this data should be written to the guest agent.
We were calling reds_reset_vdp on client disconnect, which is not a good
idea. reds_reset_vdp does 3 things:
1) It resets the state related to reading chunks from the spicevmc virtio
port. If the client disconnects while the guest agent is in the middle
of sending a chunk, this will lead to an inconsistent state, and lots
of printing of "dispatch_vdi_port_data: invalid port" messages caused
by this inconsistent state sometimes followed by a segfault.
This can be triggered by copy and pasting something large (say
a screenshot) from the guest to the spice-gtk client, as the spice-gtk
client currently has a bug causing it to crash when receiving a multi
chunk vdagent messages. Without this patch (and with the spice-gtk bug
present) I can consistently reproduce this.
2) It clears any buffered writes from the client to the guest still pending
because the virtio port cannot consume data fast enough. Since the agent
itself is still running fine, throwing away writes for it because the
client has disconnected makes no sense. Esp, since on clean exit the
client may very well send a clipboard release message directly
before closing the connection, and this may get lost this way.
3) It sets client_agent_started to false, this is the only thing which
actually makes sense to do on client disconnect.
Note that since we no longer reset the vdp state on client disconnect, we
must now reset it on agent disconnect even if we don't have a client. So
the reds_reset_vdp call in reds_agent_remove() gets moved to the top,
above both the agent_state.connected and reds->peer checks which will
both fail in the no client case.
dispatch_vdi_port_data, was calling vdi_read_buf_release when no client
is connected to free the passed in buf. The only difference between
vdi_read_buf_release and directly adding the buffer back to the ring
with ring_add, is that vdi_read_buf_release calls read_from_vdi_port
after adding the buffer back. But dispatch_vdi_port_data only gets called
from read_from_vdi_port itself, thus this would lead to recursing into
read_from_vdi_port. read_from_vdi_port is protected against recursion and
will immediately return if called recursively. Thus calling
vdi_read_buf_release from dispatch_vdi_port_data is pointless, instead
simply putting the buffer back in the ring suffices.
Also bump SPICE_SERVER_VERSION to 0x000801 as 0.8.1 will be the
first version with the new API for this, and we need to be able to
detect the presence of this API in qemu.
The current assert(reds->agent_state.connected) tiggers if when
the agent disconnected there was still data waiting to be sent (for
instance if there is a bug in the client handling clipboard and it
is killed while a large clipboard transfer is in progress). So first
call to reds_agent_remove happens from spice_server_char_device_remove_interface,
and then it is called again (triggering the assert) from free_item_data
from read_from_vdi_port because of the channel destruction.
Other option would be to not call it from one of the paths - but that
is suboptimal:
* if there is no data in the pipe, the second call never happens.
* the second call has to be there anyway, because it may fail during
parsing data from the agent.
This patch fixes a segfault on this assert when a client starts passing
from guest agent to client a large clipboard and dies in the middle. There
is still another assert happening occasionally at marshaller which I don't
have a fix for (but it doesn't seem to be related).
We introduce 2 public functions to integrate with the library user.
spice_server_set_sasl() - turn on SASL
spice_server_set_sasl_appname() - specify the name of the app (It is
used for where to find the default configuration file)
The patch for QEMU is on its way.
https://bugs.freedesktop.org/show_bug.cgi?id=34795