summaryrefslogtreecommitdiffstats
path: root/server/red_channel.h
diff options
context:
space:
mode:
authorAlon Levy <alevy@redhat.com>2011-04-11 12:44:00 +0300
committerAlon Levy <alevy@redhat.com>2011-08-23 17:56:44 +0300
commit448ed75bd6c8db7ca48cab8aa1256a262e87fcc0 (patch)
tree653fa73b47966052cc0cec9184090c0b3349fc89 /server/red_channel.h
parent22084c4703282699a34dfb72f3c6318159ddcedf (diff)
downloadspice-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.h25
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