From 448ed75bd6c8db7ca48cab8aa1256a262e87fcc0 Mon Sep 17 00:00:00 2001 From: Alon Levy Date: Mon, 11 Apr 2011 12:44:00 +0300 Subject: 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. --- server/red_dispatcher.c | 37 +++++++++++++++++++++++++++++++++++-- 1 file changed, 35 insertions(+), 2 deletions(-) (limited to 'server/red_dispatcher.c') diff --git a/server/red_dispatcher.c b/server/red_dispatcher.c index 8f4a8a8f..8cbdec9d 100644 --- a/server/red_dispatcher.c +++ b/server/red_dispatcher.c @@ -76,7 +76,8 @@ extern spice_wan_compression_t zlib_glz_state; static RedDispatcher *dispatchers = NULL; -static void red_dispatcher_set_peer(Channel *channel, RedsStream *stream, int migration, +static void red_dispatcher_set_peer(Channel *channel, RedClient *client, + RedsStream *stream, int migration, int num_common_caps, uint32_t *common_caps, int num_caps, uint32_t *caps) { @@ -86,6 +87,7 @@ static void red_dispatcher_set_peer(Channel *channel, RedsStream *stream, int mi dispatcher = (RedDispatcher *)channel->data; RedWorkerMessage message = RED_WORKER_MESSAGE_DISPLAY_CONNECT; write_message(dispatcher->channel, &message); + send_data(dispatcher->channel, &client, sizeof(RedClient *)); send_data(dispatcher->channel, &stream, sizeof(RedsStream *)); send_data(dispatcher->channel, &migration, sizeof(int)); } @@ -106,7 +108,7 @@ static void red_dispatcher_migrate(Channel *channel) write_message(dispatcher->channel, &message); } -static void red_dispatcher_set_cursor_peer(Channel *channel, RedsStream *stream, +static void red_dispatcher_set_cursor_peer(Channel *channel, RedClient *client, RedsStream *stream, int migration, int num_common_caps, uint32_t *common_caps, int num_caps, uint32_t *caps) @@ -115,6 +117,7 @@ static void red_dispatcher_set_cursor_peer(Channel *channel, RedsStream *stream, red_printf(""); RedWorkerMessage message = RED_WORKER_MESSAGE_CURSOR_CONNECT; write_message(dispatcher->channel, &message); + send_data(dispatcher->channel, &client, sizeof(RedClient *)); send_data(dispatcher->channel, &stream, sizeof(RedsStream *)); send_data(dispatcher->channel, &migration, sizeof(int)); } @@ -588,6 +591,36 @@ static void qxl_worker_loadvm_commands(QXLWorker *qxl_worker, red_dispatcher_loadvm_commands((RedDispatcher*)qxl_worker, ext, count); } +static void red_dispatcher_send_disconnect(RedDispatcher *dispatcher, + struct RedChannelClient *rcc, RedWorkerMessage message) +{ + write_message(dispatcher->channel, &message); + send_data(dispatcher->channel, &rcc, sizeof(struct RedChannelClient *)); +} + +void red_dispatcher_disconnect_display_client(RedDispatcher *dispatcher, + struct RedChannelClient *rcc) +{ + RedWorkerMessage message = RED_WORKER_MESSAGE_STOP; + + red_dispatcher_send_disconnect(dispatcher, rcc, + RED_WORKER_MESSAGE_DISPLAY_DISCONNECT_CLIENT); + read_message(dispatcher->channel, &message); + ASSERT(message == RED_WORKER_MESSAGE_READY); +} + +void red_dispatcher_disconnect_cursor_client(RedDispatcher *dispatcher, + struct RedChannelClient *rcc) +{ + RedWorkerMessage message = RED_WORKER_MESSAGE_STOP; + + red_dispatcher_send_disconnect(dispatcher, rcc, + RED_WORKER_MESSAGE_CURSOR_DISCONNECT_CLIENT); + read_message(dispatcher->channel, &message); + ASSERT(message == RED_WORKER_MESSAGE_READY); +} + + void red_dispatcher_set_mm_time(uint32_t mm_time) { RedDispatcher *now = dispatchers; -- cgit