summaryrefslogtreecommitdiffstats
path: root/server/red_dispatcher.c
diff options
context:
space:
mode:
authorYonit Halperin <yhalperi@redhat.com>2011-08-03 18:36:04 +0300
committerAlon Levy <alevy@redhat.com>2011-08-23 18:27:46 +0300
commitf84dfeb0aac4b6b49bc447a2140cbc7c2882de51 (patch)
tree67797cd53349553b101bf1f9c5ea4057b123bacb /server/red_dispatcher.c
parent1db936e64cfe955a757d9d77302f104f68a58bfd (diff)
downloadspice-f84dfeb0aac4b6b49bc447a2140cbc7c2882de51.tar.gz
spice-f84dfeb0aac4b6b49bc447a2140cbc7c2882de51.tar.xz
spice-f84dfeb0aac4b6b49bc447a2140cbc7c2882de51.zip
server: registering RedChannel in reds, instead of Channel
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.
Diffstat (limited to 'server/red_dispatcher.c')
-rw-r--r--server/red_dispatcher.c163
1 files changed, 99 insertions, 64 deletions
diff --git a/server/red_dispatcher.c b/server/red_dispatcher.c
index 8cbdec9d..c00dc580 100644
--- a/server/red_dispatcher.c
+++ b/server/red_dispatcher.c
@@ -76,10 +76,10 @@ extern spice_wan_compression_t zlib_glz_state;
static RedDispatcher *dispatchers = NULL;
-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)
+static void red_dispatcher_set_display_peer(RedChannel *channel, RedClient *client,
+ RedsStream *stream, int migration,
+ int num_common_caps, uint32_t *common_caps, int num_caps,
+ uint32_t *caps)
{
RedDispatcher *dispatcher;
@@ -92,23 +92,41 @@ static void red_dispatcher_set_peer(Channel *channel, RedClient *client,
send_data(dispatcher->channel, &migration, sizeof(int));
}
-static void red_dispatcher_shutdown_peer(Channel *channel)
+static void red_dispatcher_disconnect_display_peer(RedChannelClient *rcc)
{
- RedDispatcher *dispatcher = (RedDispatcher *)channel->data;
+ RedDispatcher *dispatcher;
+
+ if (!rcc->channel) {
+ return;
+ }
+
+ dispatcher = (RedDispatcher *)rcc->channel->data;
+
red_printf("");
RedWorkerMessage message = RED_WORKER_MESSAGE_DISPLAY_DISCONNECT;
write_message(dispatcher->channel, &message);
+ send_data(dispatcher->channel, &rcc, sizeof(RedChannelClient *));
+
+ // TODO: we turned it to be sync, due to client_destroy . Should we support async? - for this we will need ref count
+ // for channels
+ read_message(dispatcher->channel, &message);
+ ASSERT(message == RED_WORKER_MESSAGE_READY);
}
-static void red_dispatcher_migrate(Channel *channel)
+static void red_dispatcher_display_migrate(RedChannelClient *rcc)
{
- RedDispatcher *dispatcher = (RedDispatcher *)channel->data;
- red_printf("channel type %u id %u", channel->type, channel->id);
+ RedDispatcher *dispatcher;
+ if (!rcc->channel) {
+ return;
+ }
+ dispatcher = (RedDispatcher *)rcc->channel->data;
+ red_printf("channel type %u id %u", rcc->channel->type, rcc->channel->id);
RedWorkerMessage message = RED_WORKER_MESSAGE_DISPLAY_MIGRATE;
write_message(dispatcher->channel, &message);
+ send_data(dispatcher->channel, &rcc, sizeof(RedChannelClient *));
}
-static void red_dispatcher_set_cursor_peer(Channel *channel, RedClient *client, RedsStream *stream,
+static void red_dispatcher_set_cursor_peer(RedChannel *channel, RedClient *client, RedsStream *stream,
int migration, int num_common_caps,
uint32_t *common_caps, int num_caps,
uint32_t *caps)
@@ -122,18 +140,33 @@ static void red_dispatcher_set_cursor_peer(Channel *channel, RedClient *client,
send_data(dispatcher->channel, &migration, sizeof(int));
}
-static void red_dispatcher_shutdown_cursor_peer(Channel *channel)
+static void red_dispatcher_disconnect_cursor_peer(RedChannelClient *rcc)
{
- RedDispatcher *dispatcher = (RedDispatcher *)channel->data;
+ RedDispatcher *dispatcher;
+
+ if (!rcc->channel) {
+ return;
+ }
+
+ dispatcher = (RedDispatcher *)rcc->channel->data;
red_printf("");
RedWorkerMessage message = RED_WORKER_MESSAGE_CURSOR_DISCONNECT;
write_message(dispatcher->channel, &message);
+ send_data(dispatcher->channel, &rcc, sizeof(RedChannelClient *));
+
+ read_message(dispatcher->channel, &message);
+ ASSERT(message == RED_WORKER_MESSAGE_READY);
}
-static void red_dispatcher_cursor_migrate(Channel *channel)
+static void red_dispatcher_cursor_migrate(RedChannelClient *rcc)
{
- RedDispatcher *dispatcher = (RedDispatcher *)channel->data;
- red_printf("channel type %u id %u", channel->type, channel->id);
+ RedDispatcher *dispatcher;
+
+ if (!rcc->channel) {
+ return;
+ }
+ dispatcher = (RedDispatcher *)rcc->channel->data;
+ red_printf("channel type %u id %u", rcc->channel->type, rcc->channel->id);
RedWorkerMessage message = RED_WORKER_MESSAGE_CURSOR_MIGRATE;
write_message(dispatcher->channel, &message);
}
@@ -591,36 +624,6 @@ 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;
@@ -867,6 +870,32 @@ void red_dispatcher_async_complete(struct RedDispatcher *dispatcher, uint64_t co
dispatcher->qxl->st->qif->async_complete(dispatcher->qxl, cookie);
}
+static RedChannel *red_dispatcher_display_channel_create(RedDispatcher *dispatcher)
+{
+ RedWorkerMessage message = RED_WORKER_MESSAGE_DISPLAY_CHANNEL_CREATE;
+ RedChannel *display_channel;
+
+ write_message(dispatcher->channel, &message);
+
+ receive_data(dispatcher->channel, &display_channel, sizeof(RedChannel *));
+ read_message(dispatcher->channel, &message);
+ ASSERT(message == RED_WORKER_MESSAGE_READY);
+ return display_channel;
+}
+
+static RedChannel *red_dispatcher_cursor_channel_create(RedDispatcher *dispatcher)
+{
+ RedWorkerMessage message = RED_WORKER_MESSAGE_CURSOR_CHANNEL_CREATE;
+ RedChannel *cursor_channel;
+
+ write_message(dispatcher->channel, &message);
+
+ receive_data(dispatcher->channel, &cursor_channel, sizeof(RedChannel *));
+ read_message(dispatcher->channel, &message);
+ ASSERT(message == RED_WORKER_MESSAGE_READY);
+ return cursor_channel;
+}
+
RedDispatcher *red_dispatcher_init(QXLInstance *qxl)
{
RedDispatcher *dispatcher;
@@ -875,10 +904,11 @@ RedDispatcher *red_dispatcher_init(QXLInstance *qxl)
WorkerInitData init_data;
QXLDevInitInfo init_info;
int r;
- Channel *reds_channel;
- Channel *cursor_channel;
+ RedChannel *display_channel;
+ RedChannel *cursor_channel;
sigset_t thread_sig_mask;
sigset_t curr_sig_mask;
+ ClientCbs client_cbs = {0,};
quic_init();
sw_canvas_init();
@@ -950,23 +980,28 @@ RedDispatcher *red_dispatcher_init(QXLInstance *qxl)
read_message(dispatcher->channel, &message);
ASSERT(message == RED_WORKER_MESSAGE_READY);
- reds_channel = spice_new0(Channel, 1);
- reds_channel->type = SPICE_CHANNEL_DISPLAY;
- reds_channel->id = qxl->id;
- reds_channel->link = red_dispatcher_set_peer;
- reds_channel->shutdown = red_dispatcher_shutdown_peer;
- reds_channel->migrate = red_dispatcher_migrate;
- reds_channel->data = dispatcher;
- reds_register_channel(reds_channel);
-
- cursor_channel = spice_new0(Channel, 1);
- cursor_channel->type = SPICE_CHANNEL_CURSOR;
- cursor_channel->id = qxl->id;
- cursor_channel->link = red_dispatcher_set_cursor_peer;
- cursor_channel->shutdown = red_dispatcher_shutdown_cursor_peer;
- cursor_channel->migrate = red_dispatcher_cursor_migrate;
- cursor_channel->data = dispatcher;
- reds_register_channel(cursor_channel);
+ display_channel = red_dispatcher_display_channel_create(dispatcher);
+
+ if (display_channel) {
+ client_cbs.connect = red_dispatcher_set_display_peer;
+ client_cbs.disconnect = red_dispatcher_disconnect_display_peer;
+ client_cbs.migrate = red_dispatcher_display_migrate;
+ red_channel_register_client_cbs(display_channel, &client_cbs);
+ red_channel_set_data(display_channel, dispatcher);
+ reds_register_channel(display_channel);
+ }
+
+ cursor_channel = red_dispatcher_cursor_channel_create(dispatcher);
+
+ if (cursor_channel) {
+ client_cbs.connect = red_dispatcher_set_cursor_peer;
+ client_cbs.disconnect = red_dispatcher_disconnect_cursor_peer;
+ client_cbs.migrate = red_dispatcher_cursor_migrate;
+ red_channel_register_client_cbs(cursor_channel, &client_cbs);
+ red_channel_set_data(cursor_channel, dispatcher);
+ reds_register_channel(cursor_channel);
+ }
+
qxl->st->qif->attache_worker(qxl, &dispatcher->base);
qxl->st->qif->set_compression_level(qxl, calc_compression_level());