From c9e3b058e452e3e00ae009163a5de66e99987492 Mon Sep 17 00:00:00 2001 From: Marc-AndrĂ© Lureau Date: Tue, 3 Sep 2013 19:35:09 +0200 Subject: server: make cursor channel private MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Acked-by: Fabiano FidĂȘncio --- server/cursor-channel.c | 24 +++++++++++- server/cursor-channel.h | 18 ++------- server/red_channel.c | 12 ++++++ server/red_channel.h | 6 +++ server/red_worker.c | 99 ++++++++++++++++++++++--------------------------- server/red_worker.h | 5 +++ 6 files changed, 94 insertions(+), 70 deletions(-) diff --git a/server/cursor-channel.c b/server/cursor-channel.c index eef0121a..48f9ad37 100644 --- a/server/cursor-channel.c +++ b/server/cursor-channel.c @@ -19,6 +19,21 @@ #include "common/generated_server_marshallers.h" #include "cursor-channel.h" +struct CursorChannel { + CommonChannel common; // Must be the first thing + + CursorItem *item; + int cursor_visible; + SpicePoint16 cursor_position; + uint16_t cursor_trail_length; + uint16_t cursor_trail_frequency; + uint32_t mouse_mode; + +#ifdef RED_STATISTICS + StatNodeRef stat; +#endif +}; + #define RCC_TO_CCC(rcc) SPICE_CONTAINEROF((rcc), CursorChannelClient, common.base) #define CLIENT_CURSOR_CACHE @@ -364,7 +379,7 @@ CursorChannel* cursor_channel_new(RedWorker *worker) }; spice_info("create cursor channel"); - channel = red_worker_new_channel(worker, sizeof(CursorChannel), + channel = red_worker_new_channel(worker, sizeof(CursorChannel), "cursor_channel", SPICE_CHANNEL_CURSOR, 0, &cbs, red_channel_client_handle_message); @@ -460,3 +475,10 @@ void cursor_channel_reset(CursorChannel *cursor) } } } + +void cursor_channel_set_mouse_mode(CursorChannel *cursor, uint32_t mode) +{ + spice_return_if_fail(cursor); + + cursor->mouse_mode = mode; +} diff --git a/server/cursor-channel.h b/server/cursor-channel.h index 67e6e3fa..5d4f8ea2 100644 --- a/server/cursor-channel.h +++ b/server/cursor-channel.h @@ -38,6 +38,8 @@ enum { PIPE_ITEM_TYPE_INVAL_CURSOR_CACHE, }; +typedef struct CursorChannel CursorChannel; + typedef struct CursorItem { uint32_t group_id; int refs; @@ -66,21 +68,6 @@ typedef struct CursorChannelClient { uint32_t cursor_cache_items; } CursorChannelClient; -typedef struct CursorChannel { - CommonChannel common; // Must be the first thing - - CursorItem *item; - int cursor_visible; - SpicePoint16 cursor_position; - uint16_t cursor_trail_length; - uint16_t cursor_trail_frequency; - uint32_t mouse_mode; - -#ifdef RED_STATISTICS - StatNodeRef stat; -#endif -} CursorChannel; - G_STATIC_ASSERT(sizeof(CursorItem) <= QXL_CURSUR_DEVICE_DATA_SIZE); CursorChannel* cursor_channel_new (RedWorker *worker); @@ -88,6 +75,7 @@ void cursor_channel_disconnect (CursorChannel *cursor_channel); void cursor_channel_reset (CursorChannel *cursor); void cursor_channel_process_cmd (CursorChannel *cursor, RedCursorCmd *cursor_cmd, uint32_t group_id); +void cursor_channel_set_mouse_mode(CursorChannel *cursor, uint32_t mode); CursorItem* cursor_item_new (RedCursorCmd *cmd, uint32_t group_id); void cursor_item_unref (QXLInstance *qxl, CursorItem *cursor); diff --git a/server/red_channel.c b/server/red_channel.c index 34aa9dce..7330ae29 100644 --- a/server/red_channel.c +++ b/server/red_channel.c @@ -1151,9 +1151,21 @@ RedChannel *red_channel_create_parser(int size, } channel->incoming_cb.handle_parsed = (handle_parsed_proc)handle_parsed; channel->incoming_cb.parser = parser; + return channel; } +void red_channel_set_stat_node(RedChannel *channel, StatNodeRef stat) +{ + spice_return_if_fail(channel != NULL); + spice_return_if_fail(channel->stat == 0); + +#ifdef RED_STATISTICS + channel->stat = stat; + channel->out_bytes_counter = stat_add_counter(stat, "out_bytes", TRUE); +#endif +} + void red_channel_register_client_cbs(RedChannel *channel, ClientCbs *client_cbs) { spice_assert(client_cbs->connect || channel->type == SPICE_CHANNEL_MAIN); diff --git a/server/red_channel.h b/server/red_channel.h index 1f1538ea..201a4d27 100644 --- a/server/red_channel.h +++ b/server/red_channel.h @@ -32,6 +32,7 @@ #include "red_common.h" #include "demarshallers.h" #include "reds_stream.h" +#include "stat.h" #define MAX_SEND_BUFS 1000 #define CLIENT_ACK_WINDOW 20 @@ -127,6 +128,7 @@ typedef struct OutgoingHandler { /* Red Channel interface */ +typedef struct RedsStream RedsStream; typedef struct RedChannel RedChannel; typedef struct RedChannelClient RedChannelClient; typedef struct RedClient RedClient; @@ -335,10 +337,13 @@ struct RedChannel { // TODO: when different channel_clients are in different threads from Channel -> need to protect! pthread_t thread_id; #ifdef RED_STATISTICS + StatNodeRef stat; uint64_t *out_bytes_counter; #endif }; +#define RED_CHANNEL(Channel) ((RedChannel *)(Channel)) + /* * When an error occurs over a channel, we treat it as a warning * for spice-server and shutdown the channel. @@ -370,6 +375,7 @@ RedChannel *red_channel_create_parser(int size, channel_handle_parsed_proc handle_parsed, ChannelCbs *channel_cbs, uint32_t migration_flags); +void red_channel_set_stat_node(RedChannel *channel, StatNodeRef stat); void red_channel_register_client_cbs(RedChannel *channel, ClientCbs *client_cbs); // caps are freed when the channel is destroyed diff --git a/server/red_worker.c b/server/red_worker.c index e3999baa..ecfdea17 100644 --- a/server/red_worker.c +++ b/server/red_worker.c @@ -391,7 +391,6 @@ struct DisplayChannel { RedCompressBuf *free_compress_bufs; #ifdef RED_STATISTICS - StatNodeRef stat; uint64_t *cache_hits_counter; uint64_t *add_to_cache_counter; uint64_t *non_cache_counter; @@ -875,8 +874,8 @@ static int display_is_connected(RedWorker *worker) static int cursor_is_connected(RedWorker *worker) { - return (worker->cursor_channel && red_channel_is_connected( - &worker->cursor_channel->common.base)); + return worker->cursor_channel && + red_channel_is_connected(RED_CHANNEL(worker->cursor_channel)); } static void put_drawable_pipe_item(DrawablePipeItem *dpi) @@ -1135,7 +1134,7 @@ static inline void red_destroy_surface_item(RedWorker *worker, return; } dcc->surface_client_created[surface_id] = FALSE; - channel = &worker->display_channel->common.base; + channel = RED_CHANNEL(worker->display_channel); destroy = get_surface_destroy_item(channel, surface_id); red_channel_client_pipe_add(&dcc->common.base, &destroy->pipe_item); } @@ -2795,7 +2794,7 @@ static inline int red_current_add_equal(RedWorker *worker, DrawItem *item, TreeI /* sending the drawable to clients that already received * (or will receive) other_drawable */ - worker_ring_item = ring_get_head(&worker->display_channel->common.base.clients); + worker_ring_item = ring_get_head(&RED_CHANNEL(worker->display_channel)->clients); dpi_ring_item = ring_get_head(&other_drawable->pipes); /* dpi contains a sublist of dcc's, ordered the same */ while (worker_ring_item) { @@ -2804,7 +2803,7 @@ static inline int red_current_add_equal(RedWorker *worker, DrawItem *item, TreeI dpi = SPICE_CONTAINEROF(dpi_ring_item, DrawablePipeItem, base); while (worker_ring_item && (!dpi || dcc != dpi->dcc)) { red_pipe_add_drawable(dcc, drawable); - worker_ring_item = ring_next(&worker->display_channel->common.base.clients, + worker_ring_item = ring_next(&RED_CHANNEL(worker->display_channel)->clients, worker_ring_item); dcc = SPICE_CONTAINEROF(worker_ring_item, DisplayChannelClient, common.base.channel_link); @@ -2814,7 +2813,7 @@ static inline int red_current_add_equal(RedWorker *worker, DrawItem *item, TreeI dpi_ring_item = ring_next(&other_drawable->pipes, dpi_ring_item); } if (worker_ring_item) { - worker_ring_item = ring_next(&worker->display_channel->common.base.clients, + worker_ring_item = ring_next(&RED_CHANNEL(worker->display_channel)->clients, worker_ring_item); } } @@ -3943,7 +3942,7 @@ static int red_process_cursor(RedWorker *worker, uint32_t max_pipe_size, int *ri *ring_is_empty = FALSE; while (!cursor_is_connected(worker) || - red_channel_min_pipe_size(&worker->cursor_channel->common.base) <= max_pipe_size) { + red_channel_min_pipe_size(RED_CHANNEL(worker->cursor_channel)) <= max_pipe_size) { if (!worker->qxl->st->qif->get_cursor_command(worker->qxl, &ext_cmd)) { *ring_is_empty = TRUE; if (worker->cursor_poll_tries < CMD_RING_POLL_RETRIES) { @@ -4005,7 +4004,7 @@ static int red_process_commands(RedWorker *worker, uint32_t max_pipe_size, int * *ring_is_empty = FALSE; while (!display_is_connected(worker) || // TODO: change to average pipe size? - red_channel_min_pipe_size(&worker->display_channel->common.base) <= max_pipe_size) { + red_channel_min_pipe_size(RED_CHANNEL(worker->display_channel)) <= max_pipe_size) { if (!worker->qxl->st->qif->get_command(worker->qxl, &ext_cmd)) { *ring_is_empty = TRUE;; if (worker->display_poll_tries < CMD_RING_POLL_RETRIES) { @@ -4150,7 +4149,7 @@ static ImageItem *red_add_surface_area_image(DisplayChannelClient *dcc, int surf { DisplayChannel *display_channel = DCC_TO_DC(dcc); RedWorker *worker = display_channel->common.worker; - RedChannel *channel = &display_channel->common.base; + RedChannel *channel = RED_CHANNEL(display_channel); RedSurface *surface = &worker->surfaces[surface_id]; SpiceCanvas *canvas = surface->context.canvas; ImageItem *item; @@ -4329,7 +4328,7 @@ static void red_display_reset_compress_buf(DisplayChannelClient *dcc) static void red_display_destroy_compress_bufs(DisplayChannel *display_channel) { - spice_assert(!red_channel_is_connected(&display_channel->common.base)); + spice_assert(!red_channel_is_connected(RED_CHANNEL(display_channel))); while (display_channel->free_compress_bufs) { RedCompressBuf *buf = display_channel->free_compress_bufs; display_channel->free_compress_bufs = buf->next; @@ -4518,7 +4517,7 @@ static void red_display_clear_glz_drawables(DisplayChannel *display_channel) if (!display_channel) { return; } - DCC_FOREACH_SAFE(link, next, dcc, &display_channel->common.base) { + DCC_FOREACH_SAFE(link, next, dcc, RED_CHANNEL(display_channel)) { red_display_client_clear_glz_drawables(dcc); } } @@ -8172,10 +8171,10 @@ static void display_channel_send_item(RedChannelClient *rcc, PipeItem *pipe_item static inline void red_push(RedWorker *worker) { if (worker->cursor_channel) { - red_channel_push(&worker->cursor_channel->common.base); + red_channel_push(RED_CHANNEL(worker->cursor_channel)); } if (worker->display_channel) { - red_channel_push(&worker->display_channel->common.base); + red_channel_push(RED_CHANNEL(worker->display_channel)); } } @@ -8492,7 +8491,7 @@ static inline void red_create_surface(RedWorker *worker, uint32_t surface_id, ui static inline void flush_display_commands(RedWorker *worker) { - RedChannel *display_red_channel = &worker->display_channel->common.base; + RedChannel *display_red_channel = RED_CHANNEL(worker->display_channel); for (;;) { uint64_t end_time; @@ -8504,7 +8503,7 @@ static inline void flush_display_commands(RedWorker *worker) } while (red_process_commands(worker, MAX_PIPE_SIZE, &ring_is_empty)) { - red_channel_push(&worker->display_channel->common.base); + red_channel_push(RED_CHANNEL(worker->display_channel)); } if (ring_is_empty) { @@ -8513,7 +8512,7 @@ static inline void flush_display_commands(RedWorker *worker) end_time = red_get_monotonic_time() + DISPLAY_CLIENT_TIMEOUT; int sleep_count = 0; for (;;) { - red_channel_push(&worker->display_channel->common.base); + red_channel_push(RED_CHANNEL(worker->display_channel)); if (!display_is_connected(worker) || red_channel_max_pipe_size(display_red_channel) <= MAX_PIPE_SIZE) { break; @@ -8536,7 +8535,7 @@ static inline void flush_display_commands(RedWorker *worker) static inline void flush_cursor_commands(RedWorker *worker) { - RedChannel *cursor_red_channel = &worker->cursor_channel->common.base; + RedChannel *cursor_red_channel = RED_CHANNEL(worker->cursor_channel); for (;;) { uint64_t end_time; @@ -8548,7 +8547,7 @@ static inline void flush_cursor_commands(RedWorker *worker) } while (red_process_cursor(worker, MAX_PIPE_SIZE, &ring_is_empty)) { - red_channel_push(&worker->cursor_channel->common.base); + red_channel_push(RED_CHANNEL(worker->cursor_channel)); } if (ring_is_empty) { @@ -8557,7 +8556,7 @@ static inline void flush_cursor_commands(RedWorker *worker) end_time = red_get_monotonic_time() + DISPLAY_CLIENT_TIMEOUT; int sleep_count = 0; for (;;) { - red_channel_push(&worker->cursor_channel->common.base); + red_channel_push(RED_CHANNEL(worker->cursor_channel)); if (!cursor_is_connected(worker) || red_channel_min_pipe_size(cursor_red_channel) <= MAX_PIPE_SIZE) { break; @@ -8826,7 +8825,7 @@ static int display_channel_handle_migrate_glz_dictionary(DisplayChannelClient *d static int display_channel_handle_migrate_mark(RedChannelClient *rcc) { DisplayChannel *display_channel = SPICE_CONTAINEROF(rcc->channel, DisplayChannel, common.base); - RedChannel *channel = &display_channel->common.base; + RedChannel *channel = RED_CHANNEL(display_channel); red_channel_pipes_add_type(channel, PIPE_ITEM_TYPE_MIGRATE_DATA); return TRUE; @@ -9210,6 +9209,7 @@ CommonChannelClient *common_channel_new_client(CommonChannel *common, RedChannel *red_worker_new_channel(RedWorker *worker, int size, + const char *name, uint32_t channel_type, int migration_flags, ChannelCbs *channel_cbs, channel_handle_parsed_proc handle_parsed) @@ -9234,16 +9234,12 @@ RedChannel *red_worker_new_channel(RedWorker *worker, int size, handle_parsed, channel_cbs, migration_flags); + spice_return_val_if_fail(channel, NULL); + red_channel_set_stat_node(channel, stat_add_node(worker->stat, name, TRUE)); + common = (CommonChannel *)channel; - if (!channel) { - goto error; - } common->worker = worker; return channel; - -error: - free(channel); - return NULL; } static void display_channel_hold_pipe_item(RedChannelClient *rcc, PipeItem *item) @@ -9398,7 +9394,7 @@ static void display_channel_create(RedWorker *worker, int migrate) spice_info("create display channel"); if (!(worker->display_channel = (DisplayChannel *)red_worker_new_channel( - worker, sizeof(*display_channel), + worker, sizeof(*display_channel), "display_channel", SPICE_CHANNEL_DISPLAY, SPICE_MIGRATE_NEED_FLUSH | SPICE_MIGRATE_NEED_DATA_TRANSFER, &cbs, display_channel_handle_message))) { @@ -9407,14 +9403,12 @@ static void display_channel_create(RedWorker *worker, int migrate) } display_channel = worker->display_channel; #ifdef RED_STATISTICS - display_channel->stat = stat_add_node(worker->stat, "display_channel", TRUE); - display_channel->common.base.out_bytes_counter = stat_add_counter(display_channel->stat, - "out_bytes", TRUE); - display_channel->cache_hits_counter = stat_add_counter(display_channel->stat, + RedChannel *channel = RED_CHANNEL(display_channel); + display_channel->cache_hits_counter = stat_add_counter(channel->stat, "cache_hits", TRUE); - display_channel->add_to_cache_counter = stat_add_counter(display_channel->stat, + display_channel->add_to_cache_counter = stat_add_counter(channel->stat, "add_to_cache", TRUE); - display_channel->non_cache_counter = stat_add_counter(display_channel->stat, + display_channel->non_cache_counter = stat_add_counter(channel->stat, "non_cache", TRUE); #endif stat_compress_init(&display_channel->lz_stat, lz_stat_name); @@ -9457,14 +9451,14 @@ static void guest_set_client_capabilities(RedWorker *worker) return; } if ((worker->display_channel == NULL) || - (worker->display_channel->common.base.clients_num == 0)) { + (RED_CHANNEL(worker->display_channel)->clients_num == 0)) { worker->qxl->st->qif->set_client_capabilities(worker->qxl, FALSE, caps); } else { // Take least common denominator for (i = 0 ; i < sizeof(caps_available) / sizeof(caps_available[0]); ++i) { SET_CAP(caps, caps_available[i]); } - DCC_FOREACH_SAFE(link, next, dcc, &worker->display_channel->common.base) { + DCC_FOREACH_SAFE(link, next, dcc, RED_CHANNEL(worker->display_channel)) { rcc = (RedChannelClient *)dcc; for (i = 0 ; i < sizeof(caps_available) / sizeof(caps_available[0]); ++i) { if (!red_channel_client_test_remote_cap(rcc, caps_available[i])) @@ -9555,17 +9549,13 @@ static void red_connect_cursor(RedWorker *worker, RedClient *client, RedsStream if (!ccc) { return; } -#ifdef RED_STATISTICS - channel->stat = stat_add_node(worker->stat, "cursor_channel", TRUE); - channel->common.base.out_bytes_counter = stat_add_counter(channel->stat, "out_bytes", TRUE); -#endif RedChannelClient *rcc = &ccc->common.base; red_channel_client_ack_zero_messages_window(rcc); red_channel_client_push_set_ack(rcc); // TODO: why do we check for context.canvas? defer this to after display cc is connected // and test it's canvas? this is just a test to see if there is an active renderer? - if (worker->surfaces[0].context.canvas && !channel->common.during_target_migrate) { + if (worker->surfaces[0].context.canvas && !COMMON_CHANNEL(channel)->during_target_migrate) { red_channel_client_pipe_add_type(rcc, PIPE_ITEM_TYPE_CURSOR_INIT); } } @@ -9743,9 +9733,9 @@ static inline void dev_destroy_surfaces(RedWorker *worker) spice_assert(ring_is_empty(&worker->streams)); if (display_is_connected(worker)) { - red_channel_pipes_add_type(&worker->display_channel->common.base, + red_channel_pipes_add_type(RED_CHANNEL(worker->display_channel), PIPE_ITEM_TYPE_INVAL_PALETTE_CACHE); - red_pipes_add_verb(&worker->display_channel->common.base, + red_pipes_add_verb(RED_CHANNEL(worker->display_channel), SPICE_MSG_DISPLAY_STREAM_DESTROY_ALL); } @@ -9910,8 +9900,8 @@ static void dev_create_primary_surface(RedWorker *worker, uint32_t surface_id, } if (cursor_is_connected(worker) - && !worker->cursor_channel->common.during_target_migrate) { - red_channel_pipes_add_type(&worker->cursor_channel->common.base, + && !COMMON_CHANNEL(worker->cursor_channel)->during_target_migrate) { + red_channel_pipes_add_type(RED_CHANNEL(worker->cursor_channel), PIPE_ITEM_TYPE_CURSOR_INIT); } } @@ -10008,14 +9998,14 @@ void handle_dev_stop(void *opaque, void *payload) * purge the pipe, send destroy_all_surfaces * to the client (there is no such message right now), and start * from scratch on the destination side */ - if (!red_channel_wait_all_sent(&worker->display_channel->common.base, + if (!red_channel_wait_all_sent(RED_CHANNEL(worker->display_channel), DISPLAY_CLIENT_TIMEOUT)) { - red_channel_apply_clients(&worker->display_channel->common.base, + red_channel_apply_clients(RED_CHANNEL(worker->display_channel), red_channel_client_disconnect_if_pending_send); } - if (!red_channel_wait_all_sent(&worker->cursor_channel->common.base, + if (!red_channel_wait_all_sent(RED_CHANNEL(worker->cursor_channel), DISPLAY_CLIENT_TIMEOUT)) { - red_channel_apply_clients(&worker->cursor_channel->common.base, + red_channel_apply_clients(RED_CHANNEL(worker->cursor_channel), red_channel_client_disconnect_if_pending_send); } } @@ -10057,7 +10047,7 @@ void handle_dev_start(void *opaque, void *payload) spice_assert(!worker->running); if (worker->cursor_channel) { - worker->cursor_channel->common.during_target_migrate = FALSE; + COMMON_CHANNEL(worker->cursor_channel)->during_target_migrate = FALSE; } if (worker->display_channel) { worker->display_channel->common.during_target_migrate = FALSE; @@ -10262,7 +10252,8 @@ void handle_dev_cursor_channel_create(void *opaque, void *payload) if (!worker->cursor_channel) { worker->cursor_channel = cursor_channel_new(worker); } - red_channel = &worker->cursor_channel->common.base; + + red_channel = RED_CHANNEL(worker->cursor_channel); send_data(worker->channel, &red_channel, sizeof(RedChannel *)); } @@ -10380,8 +10371,8 @@ void handle_dev_set_mouse_mode(void *opaque, void *payload) RedWorkerMessageSetMouseMode *msg = payload; RedWorker *worker = opaque; - worker->cursor_channel->mouse_mode = msg->mode; - spice_info("mouse mode %u", worker->cursor_channel->mouse_mode); + spice_info("mouse mode %u", msg->mode); + cursor_channel_set_mouse_mode(worker->cursor_channel, msg->mode); } void handle_dev_add_memslot_async(void *opaque, void *payload) diff --git a/server/red_worker.h b/server/red_worker.h index aa977071..e78d5c2d 100644 --- a/server/red_worker.h +++ b/server/red_worker.h @@ -27,6 +27,7 @@ typedef struct RedWorker RedWorker; typedef struct CommonChannelClient { RedChannelClient base; + uint32_t id; struct RedWorker *worker; int is_low_bandwidth; @@ -37,6 +38,7 @@ typedef struct CommonChannelClient { #define CHANNEL_RECEIVE_BUF_SIZE 1024 typedef struct CommonChannel { RedChannel base; // Must be the first thing + struct RedWorker *worker; uint8_t recv_buf[CHANNEL_RECEIVE_BUF_SIZE]; uint32_t id_alloc; // bitfield. TODO - use this instead of shift scheme. @@ -47,6 +49,8 @@ typedef struct CommonChannel { of the primary surface) */ } CommonChannel; +#define COMMON_CHANNEL(Channel) ((CommonChannel*)(Channel)) + enum { PIPE_ITEM_TYPE_VERB = PIPE_ITEM_TYPE_CHANNEL_BASE, PIPE_ITEM_TYPE_INVAL_ONE, @@ -104,6 +108,7 @@ bool red_worker_run(RedWorker *worker); QXLInstance* red_worker_get_qxl(RedWorker *worker); RedChannel *red_worker_new_channel(RedWorker *worker, int size, + const char *name, uint32_t channel_type, int migration_flags, ChannelCbs *channel_cbs, channel_handle_parsed_proc handle_parsed); -- cgit