diff options
author | Alon Levy <alevy@redhat.com> | 2011-04-11 12:44:00 +0300 |
---|---|---|
committer | Alon Levy <alevy@redhat.com> | 2011-08-23 17:56:44 +0300 |
commit | 448ed75bd6c8db7ca48cab8aa1256a262e87fcc0 (patch) | |
tree | 653fa73b47966052cc0cec9184090c0b3349fc89 /server/red_channel.h | |
parent | 22084c4703282699a34dfb72f3c6318159ddcedf (diff) | |
download | spice-448ed75bd6c8db7ca48cab8aa1256a262e87fcc0.tar.gz spice-448ed75bd6c8db7ca48cab8aa1256a262e87fcc0.tar.xz spice-448ed75bd6c8db7ca48cab8aa1256a262e87fcc0.zip |
server: Add RedClient
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.
Diffstat (limited to 'server/red_channel.h')
-rw-r--r-- | server/red_channel.h | 25 |
1 files changed, 24 insertions, 1 deletions
diff --git a/server/red_channel.h b/server/red_channel.h index 2bd3054c..874fdf09 100644 --- a/server/red_channel.h +++ b/server/red_channel.h @@ -140,7 +140,9 @@ typedef uint64_t (*channel_handle_migrate_data_get_serial_proc)(RedChannelClient struct RedChannelClient { RingItem channel_link; + RingItem client_link; RedChannel *channel; + RedClient *client; RedsStream *stream; struct { uint32_t generation; @@ -172,6 +174,7 @@ struct RedChannel { int handle_acks; RedChannelClient *rcc; + uint32_t clients_num; OutgoingHandlerInterface outgoing_cb; IncomingHandlerInterface incoming_cb; @@ -219,6 +222,7 @@ RedChannel *red_channel_create_parser(int size, SpiceCoreInterface *core, int migrate, int handle_acks, channel_configure_socket_proc config_socket, + channel_disconnect_proc disconnect, spice_parse_channel_func_t parser, channel_handle_parsed_proc handle_parsed, channel_alloc_msg_recv_buf_proc alloc_recv_buf, @@ -231,13 +235,19 @@ RedChannel *red_channel_create_parser(int size, channel_handle_migrate_flush_mark_proc handle_migrate_flush_mark, channel_handle_migrate_data_proc handle_migrate_data, channel_handle_migrate_data_get_serial_proc handle_migrate_data_get_serial); -RedChannelClient *red_channel_client_create(int size, RedChannel *channel, +RedChannelClient *red_channel_client_create(int size, RedChannel *channel, RedClient *client, RedsStream *stream); int red_channel_is_connected(RedChannel *channel); void red_channel_client_destroy(RedChannelClient *rcc); void red_channel_destroy(RedChannel *channel); +/* shutdown is the only safe thing to do out of the client/channel + * thread. It will not touch the rings, just shutdown the socket. + * It should be followed by some way to gurantee a disconnection. */ +void red_channel_client_shutdown(RedChannelClient *rcc); +void red_channel_shutdown(RedChannel *channel); + /* should be called when a new channel is ready to send messages */ void red_channel_init_outgoing_messages_window(RedChannel *channel); @@ -350,4 +360,17 @@ typedef void (*channel_client_visitor_data)(RedChannelClient *rcc, void *data); void red_channel_apply_clients(RedChannel *channel, channel_client_visitor v); void red_channel_apply_clients_data(RedChannel *channel, channel_client_visitor_data v, void *data); +struct RedClient { + RingItem link; + Ring channels; + int channels_num; + int disconnecting; + MainChannelClient *mcc; +}; + +RedClient *red_client_new(); +void red_client_destroy(RedClient *client); +void red_client_set_main(RedClient *client, MainChannelClient *mcc); +MainChannelClient *red_client_get_main(RedClient *client); + #endif |