mirror of
https://gitlab.uni-freiburg.de/opensourcevdi/spice
synced 2026-01-01 04:45:37 +00:00
Replace RedChannel::clients with GList
Instead of using a Ring, use a GList to store the list of channel clients. This allows us to iterate the clients without poking inside of the client struct to get the channel_link. This is required in order to make the RedChannelClient struct private.
This commit is contained in:
parent
6c4e86cbe3
commit
4028fb1c79
@ -223,7 +223,7 @@ void display_channel_surface_unref(DisplayChannel *display, uint32_t surface_id)
|
||||
RedSurface *surface = &display->surfaces[surface_id];
|
||||
QXLInstance *qxl = display->common.qxl;
|
||||
DisplayChannelClient *dcc;
|
||||
RingItem *link, *next;
|
||||
GList *link, *next;
|
||||
|
||||
if (--surface->refs != 0) {
|
||||
return;
|
||||
@ -256,7 +256,7 @@ static void streams_update_visible_region(DisplayChannel *display, Drawable *dra
|
||||
{
|
||||
Ring *ring;
|
||||
RingItem *item;
|
||||
RingItem *dcc_ring_item, *next;
|
||||
GList *link, *next;
|
||||
DisplayChannelClient *dcc;
|
||||
|
||||
if (!red_channel_is_connected(RED_CHANNEL(display))) {
|
||||
@ -280,7 +280,7 @@ static void streams_update_visible_region(DisplayChannel *display, Drawable *dra
|
||||
continue;
|
||||
}
|
||||
|
||||
FOREACH_DCC(display, dcc_ring_item, next, dcc) {
|
||||
FOREACH_DCC(display, link, next, dcc) {
|
||||
agent = &dcc->stream_agents[get_stream_id(display, stream)];
|
||||
|
||||
if (region_intersects(&agent->vis_region, &drawable->tree_item.base.rgn)) {
|
||||
@ -295,10 +295,10 @@ static void streams_update_visible_region(DisplayChannel *display, Drawable *dra
|
||||
static void pipes_add_drawable(DisplayChannel *display, Drawable *drawable)
|
||||
{
|
||||
DisplayChannelClient *dcc;
|
||||
RingItem *dcc_ring_item, *next;
|
||||
GList *link, *next;
|
||||
|
||||
spice_warn_if_fail(ring_is_empty(&drawable->pipes));
|
||||
FOREACH_DCC(display, dcc_ring_item, next, dcc) {
|
||||
FOREACH_DCC(display, link, next, dcc) {
|
||||
dcc_prepend_drawable(dcc, drawable);
|
||||
}
|
||||
}
|
||||
@ -320,9 +320,9 @@ static void pipes_add_drawable_after(DisplayChannel *display,
|
||||
return;
|
||||
}
|
||||
if (num_other_linked != display->common.base.clients_num) {
|
||||
RingItem *item, *next;
|
||||
GList *link, *next;
|
||||
spice_debug("TODO: not O(n^2)");
|
||||
FOREACH_DCC(display, item, next, dcc) {
|
||||
FOREACH_DCC(display, link, next, dcc) {
|
||||
int sent = 0;
|
||||
DRAWABLE_FOREACH_DPI_SAFE(pos_after, dpi_link, dpi_next, dpi_pos_after) {
|
||||
if (dpi_pos_after->dcc == dcc) {
|
||||
@ -467,34 +467,32 @@ static int current_add_equal(DisplayChannel *display, DrawItem *item, TreeItem *
|
||||
|
||||
DisplayChannelClient *dcc;
|
||||
RedDrawablePipeItem *dpi;
|
||||
RingItem *worker_ring_item, *dpi_ring_item;
|
||||
RingItem *dpi_ring_item;
|
||||
GList *link;
|
||||
|
||||
other_drawable->refs++;
|
||||
current_remove_drawable(display, other_drawable);
|
||||
|
||||
/* sending the drawable to clients that already received
|
||||
* (or will receive) other_drawable */
|
||||
worker_ring_item = ring_get_head(&RED_CHANNEL(display)->clients);
|
||||
link = RED_CHANNEL(display)->clients;
|
||||
dpi_ring_item = ring_get_head(&other_drawable->pipes);
|
||||
/* dpi contains a sublist of dcc's, ordered the same */
|
||||
while (worker_ring_item) {
|
||||
dcc = SPICE_CONTAINEROF(worker_ring_item, DisplayChannelClient,
|
||||
common.base.channel_link);
|
||||
while (link) {
|
||||
dcc = link->data;
|
||||
dpi = SPICE_UPCAST(RedDrawablePipeItem, dpi_ring_item);
|
||||
while (worker_ring_item && (!dpi || dcc != dpi->dcc)) {
|
||||
while (link && (!dpi || dcc != dpi->dcc)) {
|
||||
dcc_prepend_drawable(dcc, drawable);
|
||||
worker_ring_item = ring_next(&RED_CHANNEL(display)->clients,
|
||||
worker_ring_item);
|
||||
dcc = SPICE_CONTAINEROF(worker_ring_item, DisplayChannelClient,
|
||||
common.base.channel_link);
|
||||
link = link->next;
|
||||
if (link)
|
||||
dcc = link->data;
|
||||
}
|
||||
|
||||
if (dpi_ring_item) {
|
||||
dpi_ring_item = ring_next(&other_drawable->pipes, dpi_ring_item);
|
||||
}
|
||||
if (worker_ring_item) {
|
||||
worker_ring_item = ring_next(&RED_CHANNEL(display)->clients,
|
||||
worker_ring_item);
|
||||
if (link) {
|
||||
link = link->next;
|
||||
}
|
||||
}
|
||||
/* not sending other_drawable where possible */
|
||||
@ -1171,9 +1169,9 @@ int display_channel_wait_for_migrate_data(DisplayChannel *display)
|
||||
}
|
||||
|
||||
spice_debug(NULL);
|
||||
spice_warn_if_fail(channel->clients_num == 1);
|
||||
spice_warn_if_fail(g_list_length(channel->clients) == 1);
|
||||
|
||||
rcc = SPICE_CONTAINEROF(ring_get_head(&channel->clients), RedChannelClient, channel_link);
|
||||
rcc = g_list_nth_data(channel->clients, 0);
|
||||
|
||||
red_channel_client_ref(rcc);
|
||||
for (;;) {
|
||||
@ -1210,24 +1208,24 @@ void display_channel_flush_all_surfaces(DisplayChannel *display)
|
||||
|
||||
void display_channel_free_glz_drawables_to_free(DisplayChannel *display)
|
||||
{
|
||||
RingItem *link, *next;
|
||||
GList *link, *next;
|
||||
DisplayChannelClient *dcc;
|
||||
|
||||
spice_return_if_fail(display);
|
||||
|
||||
DCC_FOREACH_SAFE(link, next, dcc, RED_CHANNEL(display)) {
|
||||
FOREACH_DCC(display, link, next, dcc) {
|
||||
dcc_free_glz_drawables_to_free(dcc);
|
||||
}
|
||||
}
|
||||
|
||||
void display_channel_free_glz_drawables(DisplayChannel *display)
|
||||
{
|
||||
RingItem *link, *next;
|
||||
GList *link, *next;
|
||||
DisplayChannelClient *dcc;
|
||||
|
||||
spice_return_if_fail(display);
|
||||
|
||||
DCC_FOREACH_SAFE(link, next, dcc, RED_CHANNEL(display)) {
|
||||
FOREACH_DCC(display, link, next, dcc) {
|
||||
dcc_free_glz_drawables(dcc);
|
||||
}
|
||||
}
|
||||
@ -1270,11 +1268,11 @@ void display_channel_free_some(DisplayChannel *display)
|
||||
{
|
||||
int n = 0;
|
||||
DisplayChannelClient *dcc;
|
||||
RingItem *item, *next;
|
||||
GList *link, *next;
|
||||
|
||||
spice_debug("#draw=%d, #glz_draw=%d", display->drawable_count,
|
||||
display->glz_drawable_count);
|
||||
FOREACH_DCC(display, item, next, dcc) {
|
||||
FOREACH_DCC(display, link, next, dcc) {
|
||||
GlzSharedDictionary *glz_dict = dcc ? dcc->glz_dict : NULL;
|
||||
|
||||
if (glz_dict) {
|
||||
@ -1289,7 +1287,7 @@ void display_channel_free_some(DisplayChannel *display)
|
||||
free_one_drawable(display, TRUE);
|
||||
}
|
||||
|
||||
FOREACH_DCC(display, item, next, dcc) {
|
||||
FOREACH_DCC(display, link, next, dcc) {
|
||||
GlzSharedDictionary *glz_dict = dcc ? dcc->glz_dict : NULL;
|
||||
|
||||
if (glz_dict) {
|
||||
@ -1761,10 +1759,10 @@ void display_channel_update(DisplayChannel *display,
|
||||
static void clear_surface_drawables_from_pipes(DisplayChannel *display, int surface_id,
|
||||
int wait_if_used)
|
||||
{
|
||||
RingItem *item, *next;
|
||||
GList *link, *next;
|
||||
DisplayChannelClient *dcc;
|
||||
|
||||
FOREACH_DCC(display, item, next, dcc) {
|
||||
FOREACH_DCC(display, link, next, dcc) {
|
||||
if (!dcc_clear_surface_drawables_from_pipe(dcc, surface_id, wait_if_used)) {
|
||||
red_channel_client_disconnect(RED_CHANNEL_CLIENT(dcc));
|
||||
}
|
||||
@ -1828,9 +1826,9 @@ void display_channel_destroy_surfaces(DisplayChannel *display)
|
||||
static void send_create_surface(DisplayChannel *display, int surface_id, int image_ready)
|
||||
{
|
||||
DisplayChannelClient *dcc;
|
||||
RingItem *item, *next;
|
||||
GList *link, *next;
|
||||
|
||||
FOREACH_DCC(display, item, next, dcc) {
|
||||
FOREACH_DCC(display, link, next, dcc) {
|
||||
dcc_create_surface(dcc, surface_id);
|
||||
if (image_ready)
|
||||
dcc_push_surface_image(dcc, surface_id);
|
||||
|
||||
@ -226,14 +226,14 @@ struct DisplayChannel {
|
||||
stat_info_t lz4_stat;
|
||||
};
|
||||
|
||||
#define LINK_TO_DCC(ptr) SPICE_CONTAINEROF(ptr, DisplayChannelClient, \
|
||||
common.base.channel_link)
|
||||
#define DCC_FOREACH_SAFE(link, next, dcc, channel) \
|
||||
SAFE_FOREACH(link, next, channel, &(channel)->clients, dcc, LINK_TO_DCC(link))
|
||||
|
||||
|
||||
#define FOREACH_DCC(display_channel, link, next, dcc) \
|
||||
DCC_FOREACH_SAFE(link, next, dcc, RED_CHANNEL(display_channel))
|
||||
#define FOREACH_DCC(channel, _link, _next, _data) \
|
||||
for (_link = (channel ? RED_CHANNEL(channel)->clients : NULL), \
|
||||
_next = (_link ? _link->next : NULL), \
|
||||
_data = (_link ? _link->data : NULL); \
|
||||
_link; \
|
||||
_link = _next, \
|
||||
_next = (_link ? _link->next : NULL), \
|
||||
_data = (_link ? _link->data : NULL))
|
||||
|
||||
static inline int get_stream_id(DisplayChannel *display, Stream *stream)
|
||||
{
|
||||
|
||||
@ -42,12 +42,12 @@ static void main_channel_client_on_disconnect(RedChannelClient *rcc)
|
||||
|
||||
RedClient *main_channel_get_client_by_link_id(MainChannel *main_chan, uint32_t connection_id)
|
||||
{
|
||||
RingItem *link;
|
||||
GList *link;
|
||||
MainChannelClient *mcc;
|
||||
RedChannelClient *rcc;
|
||||
|
||||
RING_FOREACH(link, &main_chan->base.clients) {
|
||||
rcc = SPICE_CONTAINEROF(link, RedChannelClient, channel_link);
|
||||
for (link = main_chan->base.clients; link != NULL; link = link->next) {
|
||||
rcc = link->data;
|
||||
mcc = (MainChannelClient*) rcc;
|
||||
if (main_channel_client_get_connection_id(mcc) == connection_id) {
|
||||
return rcc->client;
|
||||
@ -328,11 +328,10 @@ MainChannel* main_channel_new(RedsState *reds)
|
||||
|
||||
static int main_channel_connect_semi_seamless(MainChannel *main_channel)
|
||||
{
|
||||
RingItem *client_link;
|
||||
GList *link;
|
||||
|
||||
RING_FOREACH(client_link, &main_channel->base.clients) {
|
||||
RedChannelClient *rcc = SPICE_CONTAINEROF(client_link, RedChannelClient,
|
||||
channel_link);
|
||||
for (link = main_channel->base.clients; link != NULL; link = link->next) {
|
||||
RedChannelClient *rcc = link->data;
|
||||
MainChannelClient *mcc = (MainChannelClient*)rcc;
|
||||
if (main_channel_client_connect_semi_seamless(mcc))
|
||||
main_channel->num_clients_mig_wait++;
|
||||
@ -342,13 +341,12 @@ static int main_channel_connect_semi_seamless(MainChannel *main_channel)
|
||||
|
||||
static int main_channel_connect_seamless(MainChannel *main_channel)
|
||||
{
|
||||
RingItem *client_link;
|
||||
GList *link;
|
||||
|
||||
spice_assert(main_channel->base.clients_num == 1);
|
||||
spice_assert(g_list_length(main_channel->base.clients) == 1);
|
||||
|
||||
RING_FOREACH(client_link, &main_channel->base.clients) {
|
||||
RedChannelClient *rcc = SPICE_CONTAINEROF(client_link, RedChannelClient,
|
||||
channel_link);
|
||||
for (link = main_channel->base.clients; link != NULL; link = link->next) {
|
||||
RedChannelClient *rcc = link->data;
|
||||
MainChannelClient *mcc = (MainChannelClient*)rcc;
|
||||
main_channel_client_connect_seamless(mcc);
|
||||
main_channel->num_clients_mig_wait++;
|
||||
@ -369,11 +367,9 @@ int main_channel_migrate_connect(MainChannel *main_channel, RedsMigSpice *mig_ta
|
||||
if (!try_seamless) {
|
||||
return main_channel_connect_semi_seamless(main_channel);
|
||||
} else {
|
||||
RingItem *client_item;
|
||||
RedChannelClient *rcc;
|
||||
|
||||
client_item = ring_get_head(&main_channel->base.clients);
|
||||
rcc = SPICE_CONTAINEROF(client_item, RedChannelClient, channel_link);
|
||||
rcc = g_list_nth_data(main_channel->base.clients, 0);
|
||||
|
||||
if (!red_channel_client_test_remote_cap(rcc,
|
||||
SPICE_MAIN_CAP_SEAMLESS_MIGRATE)) {
|
||||
@ -387,11 +383,10 @@ int main_channel_migrate_connect(MainChannel *main_channel, RedsMigSpice *mig_ta
|
||||
|
||||
void main_channel_migrate_cancel_wait(MainChannel *main_chan)
|
||||
{
|
||||
RingItem *client_link;
|
||||
GList *link;
|
||||
|
||||
RING_FOREACH(client_link, &main_chan->base.clients) {
|
||||
RedChannelClient *rcc = SPICE_CONTAINEROF(client_link, RedChannelClient,
|
||||
channel_link);
|
||||
for (link = main_chan->base.clients; link != NULL; link = link->next) {
|
||||
RedChannelClient *rcc = link->data;
|
||||
MainChannelClient *mcc = (MainChannelClient*)rcc;
|
||||
main_channel_client_migrate_cancel_wait(mcc);
|
||||
}
|
||||
@ -400,19 +395,18 @@ void main_channel_migrate_cancel_wait(MainChannel *main_chan)
|
||||
|
||||
int main_channel_migrate_src_complete(MainChannel *main_chan, int success)
|
||||
{
|
||||
RingItem *client_link;
|
||||
GList *link;
|
||||
int semi_seamless_count = 0;
|
||||
|
||||
spice_printerr("");
|
||||
|
||||
if (ring_is_empty(&main_chan->base.clients)) {
|
||||
if (!main_chan->base.clients) {
|
||||
spice_printerr("no peer connected");
|
||||
return 0;
|
||||
}
|
||||
|
||||
RING_FOREACH(client_link, &main_chan->base.clients) {
|
||||
RedChannelClient *rcc = SPICE_CONTAINEROF(client_link, RedChannelClient,
|
||||
channel_link);
|
||||
for (link = main_chan->base.clients; link != NULL; link = link->next) {
|
||||
RedChannelClient *rcc = link->data;
|
||||
MainChannelClient *mcc = (MainChannelClient*)rcc;
|
||||
if (main_channel_client_migrate_src_complete(mcc, success))
|
||||
semi_seamless_count++;
|
||||
|
||||
@ -332,14 +332,7 @@ void red_channel_client_receive(RedChannelClient *rcc)
|
||||
|
||||
void red_channel_receive(RedChannel *channel)
|
||||
{
|
||||
RingItem *link;
|
||||
RingItem *next;
|
||||
RedChannelClient *rcc;
|
||||
|
||||
RING_FOREACH_SAFE(link, next, &channel->clients) {
|
||||
rcc = SPICE_CONTAINEROF(link, RedChannelClient, channel_link);
|
||||
red_channel_client_receive(rcc);
|
||||
}
|
||||
g_list_foreach(channel->clients, (GFunc)red_channel_client_receive, NULL);
|
||||
}
|
||||
|
||||
static void red_peer_handle_outgoing(RedsStream *stream, OutgoingHandler *handler)
|
||||
@ -644,8 +637,7 @@ static void red_channel_client_pipe_remove(RedChannelClient *rcc, RedPipeItem *i
|
||||
static void red_channel_add_client(RedChannel *channel, RedChannelClient *rcc)
|
||||
{
|
||||
spice_assert(rcc);
|
||||
ring_add(&channel->clients, &rcc->channel_link);
|
||||
channel->clients_num++;
|
||||
channel->clients = g_list_prepend(channel->clients, rcc);
|
||||
}
|
||||
|
||||
static void red_channel_client_set_remote_caps(RedChannelClient* rcc,
|
||||
@ -683,10 +675,10 @@ int red_channel_client_test_remote_cap(RedChannelClient *rcc, uint32_t cap)
|
||||
|
||||
int red_channel_test_remote_common_cap(RedChannel *channel, uint32_t cap)
|
||||
{
|
||||
RingItem *link;
|
||||
GList *link;
|
||||
|
||||
RING_FOREACH(link, &channel->clients) {
|
||||
RedChannelClient *rcc = SPICE_CONTAINEROF(link, RedChannelClient, channel_link);
|
||||
for (link = channel->clients; link != NULL; link = link->next) {
|
||||
RedChannelClient *rcc = link->data;
|
||||
|
||||
if (!red_channel_client_test_remote_common_cap(rcc, cap)) {
|
||||
return FALSE;
|
||||
@ -697,10 +689,10 @@ int red_channel_test_remote_common_cap(RedChannel *channel, uint32_t cap)
|
||||
|
||||
int red_channel_test_remote_cap(RedChannel *channel, uint32_t cap)
|
||||
{
|
||||
RingItem *link;
|
||||
GList *link;
|
||||
|
||||
RING_FOREACH(link, &channel->clients) {
|
||||
RedChannelClient *rcc = SPICE_CONTAINEROF(link, RedChannelClient, channel_link);
|
||||
for (link = channel->clients; link != NULL; link = link->next) {
|
||||
RedChannelClient *rcc = link->data;
|
||||
|
||||
if (!red_channel_client_test_remote_cap(rcc, cap)) {
|
||||
return FALSE;
|
||||
@ -908,7 +900,7 @@ RedChannelClient *red_channel_client_create(int size, RedChannel *channel, RedCl
|
||||
stream->socket,
|
||||
SPICE_WATCH_EVENT_READ,
|
||||
red_channel_client_event, rcc);
|
||||
rcc->id = channel->clients_num;
|
||||
rcc->id = g_list_length(channel->clients);
|
||||
red_channel_add_client(channel, rcc);
|
||||
red_client_add_channel(client, rcc);
|
||||
red_channel_ref(channel);
|
||||
@ -977,16 +969,17 @@ int red_channel_client_is_waiting_for_migrate_data(RedChannelClient *rcc)
|
||||
int red_channel_is_waiting_for_migrate_data(RedChannel *channel)
|
||||
{
|
||||
RedChannelClient *rcc;
|
||||
guint n_clients = g_list_length(channel->clients);
|
||||
|
||||
if (!red_channel_is_connected(channel)) {
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if (channel->clients_num > 1) {
|
||||
if (n_clients > 1) {
|
||||
return FALSE;
|
||||
}
|
||||
spice_assert(channel->clients_num == 1);
|
||||
rcc = SPICE_CONTAINEROF(ring_get_head(&channel->clients), RedChannelClient, channel_link);
|
||||
spice_assert(n_clients == 1);
|
||||
rcc = g_list_nth_data(channel->clients, 0);
|
||||
return red_channel_client_is_waiting_for_migrate_data(rcc);
|
||||
}
|
||||
|
||||
@ -1045,7 +1038,6 @@ RedChannel *red_channel_create(int size,
|
||||
|
||||
channel->reds = reds;
|
||||
channel->core = core;
|
||||
ring_init(&channel->clients);
|
||||
|
||||
// TODO: send incoming_cb as parameters instead of duplicating?
|
||||
channel->incoming_cb.alloc_msg_buf = (alloc_msg_recv_buf_proc)channel_cbs->alloc_recv_buf;
|
||||
@ -1112,7 +1104,6 @@ RedChannel *red_channel_create_dummy(int size, RedsState *reds, uint32_t type, u
|
||||
channel->refs = 1;
|
||||
channel->reds = reds;
|
||||
channel->core = &dummy_core;
|
||||
ring_init(&channel->clients);
|
||||
client_cbs.connect = red_channel_client_default_connect;
|
||||
client_cbs.disconnect = red_channel_client_default_disconnect;
|
||||
client_cbs.migrate = red_channel_client_default_migrate;
|
||||
@ -1279,17 +1270,11 @@ void red_channel_client_destroy(RedChannelClient *rcc)
|
||||
|
||||
void red_channel_destroy(RedChannel *channel)
|
||||
{
|
||||
RingItem *link;
|
||||
RingItem *next;
|
||||
|
||||
if (!channel) {
|
||||
return;
|
||||
}
|
||||
RING_FOREACH_SAFE(link, next, &channel->clients) {
|
||||
red_channel_client_destroy(
|
||||
SPICE_CONTAINEROF(link, RedChannelClient, channel_link));
|
||||
}
|
||||
|
||||
g_list_foreach(channel->clients, (GFunc)red_channel_client_destroy, NULL);
|
||||
red_channel_unref(channel);
|
||||
}
|
||||
|
||||
@ -1312,12 +1297,7 @@ void red_channel_client_send(RedChannelClient *rcc)
|
||||
|
||||
void red_channel_send(RedChannel *channel)
|
||||
{
|
||||
RingItem *link;
|
||||
RingItem *next;
|
||||
|
||||
RING_FOREACH_SAFE(link, next, &channel->clients) {
|
||||
red_channel_client_send(SPICE_CONTAINEROF(link, RedChannelClient, channel_link));
|
||||
}
|
||||
g_list_foreach(channel->clients, (GFunc)red_channel_client_send, NULL);
|
||||
}
|
||||
|
||||
static inline int red_channel_client_waiting_for_ack(RedChannelClient *rcc)
|
||||
@ -1372,17 +1352,11 @@ void red_channel_client_push(RedChannelClient *rcc)
|
||||
|
||||
void red_channel_push(RedChannel *channel)
|
||||
{
|
||||
RingItem *link;
|
||||
RingItem *next;
|
||||
RedChannelClient *rcc;
|
||||
|
||||
if (!channel) {
|
||||
return;
|
||||
}
|
||||
RING_FOREACH_SAFE(link, next, &channel->clients) {
|
||||
rcc = SPICE_CONTAINEROF(link, RedChannelClient, channel_link);
|
||||
red_channel_client_push(rcc);
|
||||
}
|
||||
|
||||
g_list_foreach(channel->clients, (GFunc)red_channel_client_push, NULL);
|
||||
}
|
||||
|
||||
int red_channel_client_get_roundtrip_ms(RedChannelClient *rcc)
|
||||
@ -1403,13 +1377,7 @@ static void red_channel_client_init_outgoing_messages_window(RedChannelClient *r
|
||||
// specific
|
||||
void red_channel_init_outgoing_messages_window(RedChannel *channel)
|
||||
{
|
||||
RingItem *link;
|
||||
RingItem *next;
|
||||
|
||||
RING_FOREACH_SAFE(link, next, &channel->clients) {
|
||||
red_channel_client_init_outgoing_messages_window(
|
||||
SPICE_CONTAINEROF(link, RedChannelClient, channel_link));
|
||||
}
|
||||
g_list_foreach(channel->clients, (GFunc)red_channel_client_init_outgoing_messages_window, NULL);
|
||||
}
|
||||
|
||||
static void red_channel_handle_migrate_flush_mark(RedChannelClient *rcc)
|
||||
@ -1726,15 +1694,16 @@ void red_channel_client_pipe_add_type(RedChannelClient *rcc, int pipe_item_type)
|
||||
red_channel_client_push(rcc);
|
||||
}
|
||||
|
||||
static void red_channel_client_pipe_add_type_proxy(gpointer data, gpointer user_data)
|
||||
{
|
||||
int type = GPOINTER_TO_INT(user_data);
|
||||
red_channel_client_pipe_add_type(data, type);
|
||||
}
|
||||
|
||||
void red_channel_pipes_add_type(RedChannel *channel, int pipe_item_type)
|
||||
{
|
||||
RingItem *link, *next;
|
||||
|
||||
RING_FOREACH_SAFE(link, next, &channel->clients) {
|
||||
red_channel_client_pipe_add_type(
|
||||
SPICE_CONTAINEROF(link, RedChannelClient, channel_link),
|
||||
pipe_item_type);
|
||||
}
|
||||
g_list_foreach(channel->clients, red_channel_client_pipe_add_type_proxy,
|
||||
GINT_TO_POINTER(pipe_item_type));
|
||||
}
|
||||
|
||||
void red_channel_client_pipe_add_empty_msg(RedChannelClient *rcc, int msg_type)
|
||||
@ -1747,21 +1716,22 @@ void red_channel_client_pipe_add_empty_msg(RedChannelClient *rcc, int msg_type)
|
||||
red_channel_client_push(rcc);
|
||||
}
|
||||
|
||||
static void red_channel_client_pipe_add_empty_msg_proxy(gpointer data, gpointer user_data)
|
||||
{
|
||||
int type = GPOINTER_TO_INT(user_data);
|
||||
red_channel_client_pipe_add_empty_msg(data, type);
|
||||
}
|
||||
|
||||
void red_channel_pipes_add_empty_msg(RedChannel *channel, int msg_type)
|
||||
{
|
||||
RingItem *link, *next;
|
||||
|
||||
RING_FOREACH_SAFE(link, next, &channel->clients) {
|
||||
red_channel_client_pipe_add_empty_msg(
|
||||
SPICE_CONTAINEROF(link, RedChannelClient, channel_link),
|
||||
msg_type);
|
||||
}
|
||||
g_list_foreach(channel->clients, red_channel_client_pipe_add_empty_msg_proxy, GINT_TO_POINTER(msg_type));
|
||||
}
|
||||
|
||||
int red_channel_client_is_connected(RedChannelClient *rcc)
|
||||
{
|
||||
if (!rcc->dummy) {
|
||||
return ring_item_is_linked(&rcc->channel_link);
|
||||
return rcc->channel
|
||||
&& (g_list_find(rcc->channel->clients, rcc) != NULL);
|
||||
} else {
|
||||
return rcc->dummy_connected;
|
||||
}
|
||||
@ -1769,7 +1739,7 @@ int red_channel_client_is_connected(RedChannelClient *rcc)
|
||||
|
||||
int red_channel_is_connected(RedChannel *channel)
|
||||
{
|
||||
return channel && (channel->clients_num > 0);
|
||||
return channel && channel->clients;
|
||||
}
|
||||
|
||||
static void red_channel_client_clear_sent_item(RedChannelClient *rcc)
|
||||
@ -1805,6 +1775,8 @@ void red_channel_client_ack_set_client_window(RedChannelClient *rcc, int client_
|
||||
|
||||
static void red_channel_remove_client(RedChannelClient *rcc)
|
||||
{
|
||||
GList *link;
|
||||
|
||||
if (!pthread_equal(pthread_self(), rcc->channel->thread_id)) {
|
||||
spice_warning("channel type %d id %d - "
|
||||
"channel->thread_id (0x%lx) != pthread_self (0x%lx)."
|
||||
@ -1813,11 +1785,11 @@ static void red_channel_remove_client(RedChannelClient *rcc)
|
||||
rcc->channel->type, rcc->channel->id,
|
||||
rcc->channel->thread_id, pthread_self());
|
||||
}
|
||||
spice_return_if_fail(ring_item_is_linked(&rcc->channel_link));
|
||||
spice_return_if_fail(rcc->channel);
|
||||
link = g_list_find(rcc->channel->clients, rcc);
|
||||
spice_return_if_fail(link != NULL);
|
||||
|
||||
ring_remove(&rcc->channel_link);
|
||||
spice_assert(rcc->channel->clients_num > 0);
|
||||
rcc->channel->clients_num--;
|
||||
rcc->channel->clients = g_list_remove_link(rcc->channel->clients, link);
|
||||
// TODO: should we set rcc->channel to NULL???
|
||||
}
|
||||
|
||||
@ -1831,11 +1803,12 @@ static void red_client_remove_channel(RedChannelClient *rcc)
|
||||
|
||||
static void red_channel_client_disconnect_dummy(RedChannelClient *rcc)
|
||||
{
|
||||
GList *link;
|
||||
spice_assert(rcc->dummy);
|
||||
if (ring_item_is_linked(&rcc->channel_link)) {
|
||||
if (rcc->channel && (link = g_list_find(rcc->channel->clients, rcc))) {
|
||||
spice_printerr("rcc=%p (channel=%p type=%d id=%d)", rcc, rcc->channel,
|
||||
rcc->channel->type, rcc->channel->id);
|
||||
red_channel_remove_client(rcc);
|
||||
red_channel_remove_client(link->data);
|
||||
}
|
||||
rcc->dummy_connected = FALSE;
|
||||
}
|
||||
@ -1870,13 +1843,7 @@ void red_channel_client_disconnect(RedChannelClient *rcc)
|
||||
|
||||
void red_channel_disconnect(RedChannel *channel)
|
||||
{
|
||||
RingItem *link;
|
||||
RingItem *next;
|
||||
|
||||
RING_FOREACH_SAFE(link, next, &channel->clients) {
|
||||
red_channel_client_disconnect(
|
||||
SPICE_CONTAINEROF(link, RedChannelClient, channel_link));
|
||||
}
|
||||
g_list_foreach(channel->clients, (GFunc)red_channel_client_disconnect, NULL);
|
||||
}
|
||||
|
||||
RedChannelClient *red_channel_client_create_dummy(int size,
|
||||
@ -1926,26 +1893,24 @@ error:
|
||||
|
||||
void red_channel_apply_clients(RedChannel *channel, channel_client_callback cb)
|
||||
{
|
||||
RingItem *link;
|
||||
RingItem *next;
|
||||
RedChannelClient *rcc;
|
||||
g_list_foreach(channel->clients, (GFunc)cb, NULL);
|
||||
}
|
||||
|
||||
RING_FOREACH_SAFE(link, next, &channel->clients) {
|
||||
rcc = SPICE_CONTAINEROF(link, RedChannelClient, channel_link);
|
||||
cb(rcc);
|
||||
}
|
||||
void red_channel_apply_clients_data(RedChannel *channel, channel_client_callback_data cb, void *data)
|
||||
{
|
||||
g_list_foreach(channel->clients, (GFunc)cb, data);
|
||||
}
|
||||
|
||||
int red_channel_all_blocked(RedChannel *channel)
|
||||
{
|
||||
RingItem *link;
|
||||
GList *link;
|
||||
RedChannelClient *rcc;
|
||||
|
||||
if (!channel || channel->clients_num == 0) {
|
||||
if (!channel || !channel->clients) {
|
||||
return FALSE;
|
||||
}
|
||||
RING_FOREACH(link, &channel->clients) {
|
||||
rcc = SPICE_CONTAINEROF(link, RedChannelClient, channel_link);
|
||||
for (link = channel->clients; link != NULL; link = link->next) {
|
||||
rcc = link->data;
|
||||
if (!rcc->send_data.blocked) {
|
||||
return FALSE;
|
||||
}
|
||||
@ -1955,11 +1920,11 @@ int red_channel_all_blocked(RedChannel *channel)
|
||||
|
||||
int red_channel_any_blocked(RedChannel *channel)
|
||||
{
|
||||
RingItem *link;
|
||||
GList *link;
|
||||
RedChannelClient *rcc;
|
||||
|
||||
RING_FOREACH(link, &channel->clients) {
|
||||
rcc = SPICE_CONTAINEROF(link, RedChannelClient, channel_link);
|
||||
for (link = channel->clients; link != NULL; link = link->next) {
|
||||
rcc = link->data;
|
||||
if (rcc->send_data.blocked) {
|
||||
return TRUE;
|
||||
}
|
||||
@ -2002,20 +1967,23 @@ void red_channel_client_set_header_sub_list(RedChannelClient *rcc, uint32_t sub_
|
||||
|
||||
int red_channel_get_first_socket(RedChannel *channel)
|
||||
{
|
||||
if (!channel || channel->clients_num == 0) {
|
||||
RedChannelClient *rcc;
|
||||
|
||||
if (!channel || !channel->clients) {
|
||||
return -1;
|
||||
}
|
||||
return SPICE_CONTAINEROF(ring_get_head(&channel->clients),
|
||||
RedChannelClient, channel_link)->stream->socket;
|
||||
rcc = g_list_nth_data(channel->clients, 0);
|
||||
|
||||
return rcc->stream->socket;
|
||||
}
|
||||
|
||||
int red_channel_no_item_being_sent(RedChannel *channel)
|
||||
{
|
||||
RingItem *link;
|
||||
GList *link;
|
||||
RedChannelClient *rcc;
|
||||
|
||||
RING_FOREACH(link, &channel->clients) {
|
||||
rcc = SPICE_CONTAINEROF(link, RedChannelClient, channel_link);
|
||||
for (link = channel->clients; link != NULL; link = link->next) {
|
||||
rcc = link->data;
|
||||
if (!red_channel_client_no_item_being_sent(rcc)) {
|
||||
return FALSE;
|
||||
}
|
||||
@ -2252,7 +2220,7 @@ static int red_channel_pipes_create_batch(RedChannel *channel,
|
||||
new_pipe_item_t creator, void *data,
|
||||
rcc_item_t pipe_add)
|
||||
{
|
||||
RingItem *link, *next;
|
||||
GList *link, *next;
|
||||
RedChannelClient *rcc;
|
||||
RedPipeItem *item;
|
||||
int num = 0, n = 0;
|
||||
@ -2260,13 +2228,16 @@ static int red_channel_pipes_create_batch(RedChannel *channel,
|
||||
spice_assert(creator != NULL);
|
||||
spice_assert(pipe_add != NULL);
|
||||
|
||||
RING_FOREACH_SAFE(link, next, &channel->clients) {
|
||||
rcc = SPICE_CONTAINEROF(link, RedChannelClient, channel_link);
|
||||
link = channel->clients;
|
||||
while (link != NULL) {
|
||||
next = link->next;
|
||||
rcc = link->data;
|
||||
item = (*creator)(rcc, data, num++);
|
||||
if (item) {
|
||||
(*pipe_add)(rcc, item);
|
||||
n++;
|
||||
}
|
||||
link = next;
|
||||
}
|
||||
|
||||
return n;
|
||||
@ -2296,12 +2267,12 @@ void red_channel_pipes_new_add_tail(RedChannel *channel, new_pipe_item_t creator
|
||||
|
||||
uint32_t red_channel_max_pipe_size(RedChannel *channel)
|
||||
{
|
||||
RingItem *link;
|
||||
GList *link;
|
||||
RedChannelClient *rcc;
|
||||
uint32_t pipe_size = 0;
|
||||
|
||||
RING_FOREACH(link, &channel->clients) {
|
||||
rcc = SPICE_CONTAINEROF(link, RedChannelClient, channel_link);
|
||||
for (link = channel->clients; link != NULL; link = link->next) {
|
||||
rcc = link->data;
|
||||
pipe_size = MAX(pipe_size, rcc->pipe_size);
|
||||
}
|
||||
return pipe_size;
|
||||
@ -2309,12 +2280,12 @@ uint32_t red_channel_max_pipe_size(RedChannel *channel)
|
||||
|
||||
uint32_t red_channel_min_pipe_size(RedChannel *channel)
|
||||
{
|
||||
RingItem *link;
|
||||
GList *link;
|
||||
RedChannelClient *rcc;
|
||||
uint32_t pipe_size = ~0;
|
||||
|
||||
RING_FOREACH(link, &channel->clients) {
|
||||
rcc = SPICE_CONTAINEROF(link, RedChannelClient, channel_link);
|
||||
for (link = channel->clients; link != NULL; link = link->next) {
|
||||
rcc = link->data;
|
||||
pipe_size = MIN(pipe_size, rcc->pipe_size);
|
||||
}
|
||||
return pipe_size == ~0 ? 0 : pipe_size;
|
||||
@ -2322,12 +2293,12 @@ uint32_t red_channel_min_pipe_size(RedChannel *channel)
|
||||
|
||||
uint32_t red_channel_sum_pipes_size(RedChannel *channel)
|
||||
{
|
||||
RingItem *link;
|
||||
GList *link;
|
||||
RedChannelClient *rcc;
|
||||
uint32_t sum = 0;
|
||||
|
||||
RING_FOREACH(link, &channel->clients) {
|
||||
rcc = SPICE_CONTAINEROF(link, RedChannelClient, channel_link);
|
||||
for (link = channel->clients; link != NULL; link = link->next) {
|
||||
rcc = link->data;
|
||||
sum += rcc->pipe_size;
|
||||
}
|
||||
return sum;
|
||||
|
||||
@ -307,7 +307,7 @@ struct RedChannel {
|
||||
// However RCC still holds a reference to the Channel.
|
||||
// Maybe replace these logic with ref count?
|
||||
// TODO: rename to 'connected_clients'?
|
||||
Ring clients;
|
||||
GList *clients;
|
||||
uint32_t clients_num;
|
||||
|
||||
OutgoingHandlerInterface outgoing_cb;
|
||||
@ -548,6 +548,7 @@ uint32_t red_channel_sum_pipes_size(RedChannel *channel);
|
||||
typedef void (*channel_client_callback)(RedChannelClient *rcc);
|
||||
typedef void (*channel_client_callback_data)(RedChannelClient *rcc, void *data);
|
||||
void red_channel_apply_clients(RedChannel *channel, channel_client_callback v);
|
||||
void red_channel_apply_clients_data(RedChannel *channel, channel_client_callback_data v, void * data);
|
||||
struct RedsState* red_channel_get_server(RedChannel *channel);
|
||||
|
||||
struct RedClient {
|
||||
|
||||
@ -500,7 +500,7 @@ static void guest_set_client_capabilities(RedWorker *worker)
|
||||
int i;
|
||||
DisplayChannelClient *dcc;
|
||||
RedChannelClient *rcc;
|
||||
RingItem *link, *next;
|
||||
GList *link, *next;
|
||||
uint8_t caps[SPICE_CAPABILITIES_SIZE] = { 0 };
|
||||
int caps_available[] = {
|
||||
SPICE_DISPLAY_CAP_SIZED_STREAM,
|
||||
@ -533,7 +533,7 @@ static void guest_set_client_capabilities(RedWorker *worker)
|
||||
for (i = 0 ; i < sizeof(caps_available) / sizeof(caps_available[0]); ++i) {
|
||||
SET_CAP(caps, caps_available[i]);
|
||||
}
|
||||
DCC_FOREACH_SAFE(link, next, dcc, RED_CHANNEL(worker->display_channel)) {
|
||||
FOREACH_DCC(worker->display_channel, link, next, dcc) {
|
||||
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]))
|
||||
@ -646,7 +646,7 @@ static void display_update_monitors_config(DisplayChannel *display,
|
||||
static void red_worker_push_monitors_config(RedWorker *worker)
|
||||
{
|
||||
DisplayChannelClient *dcc;
|
||||
RingItem *item, *next;
|
||||
GList *item, *next;
|
||||
|
||||
FOREACH_DCC(worker->display_channel, item, next, dcc) {
|
||||
dcc_push_monitors_config(dcc);
|
||||
|
||||
@ -75,19 +75,16 @@ static inline void red_pipe_add_verb(RedChannelClient* rcc, uint16_t verb)
|
||||
red_channel_client_pipe_add(rcc, &item->base);
|
||||
}
|
||||
|
||||
#define LINK_TO_RCC(ptr) SPICE_CONTAINEROF(ptr, RedChannelClient, channel_link)
|
||||
#define RCC_FOREACH_SAFE(link, next, rcc, channel) \
|
||||
SAFE_FOREACH(link, next, channel, &(channel)->clients, rcc, LINK_TO_RCC(link))
|
||||
static inline void red_pipe_add_verb_proxy(RedChannelClient *rcc, gpointer data)
|
||||
{
|
||||
uint16_t verb = GPOINTER_TO_UINT(data);
|
||||
red_pipe_add_verb(rcc, verb);
|
||||
}
|
||||
|
||||
|
||||
static inline void red_pipes_add_verb(RedChannel *channel, uint16_t verb)
|
||||
{
|
||||
RedChannelClient *rcc;
|
||||
RingItem *link, *next;
|
||||
|
||||
RCC_FOREACH_SAFE(link, next, rcc, channel) {
|
||||
red_pipe_add_verb(rcc, verb);
|
||||
}
|
||||
red_channel_apply_clients_data(channel, red_pipe_add_verb_proxy, GUINT_TO_POINTER(verb));
|
||||
}
|
||||
|
||||
RedWorker* red_worker_new(QXLInstance *qxl,
|
||||
|
||||
@ -96,13 +96,13 @@ static RedPipeItem *stream_destroy_item_new(StreamAgent *agent)
|
||||
void stream_stop(DisplayChannel *display, Stream *stream)
|
||||
{
|
||||
DisplayChannelClient *dcc;
|
||||
RingItem *item, *next;
|
||||
GList *link, *next;
|
||||
|
||||
spice_return_if_fail(ring_item_is_linked(&stream->link));
|
||||
spice_return_if_fail(!stream->current);
|
||||
|
||||
spice_debug("stream %d", get_stream_id(display, stream));
|
||||
FOREACH_DCC(display, item, next, dcc) {
|
||||
FOREACH_DCC(display, link, next, dcc) {
|
||||
StreamAgent *stream_agent;
|
||||
|
||||
stream_agent = &dcc->stream_agents[get_stream_id(display, stream)];
|
||||
@ -289,7 +289,7 @@ static int is_next_stream_frame(DisplayChannel *display,
|
||||
static void attach_stream(DisplayChannel *display, Drawable *drawable, Stream *stream)
|
||||
{
|
||||
DisplayChannelClient *dcc;
|
||||
RingItem *item, *next;
|
||||
GList *link, *next;
|
||||
|
||||
spice_assert(drawable && stream);
|
||||
spice_assert(!drawable->stream && !stream->current);
|
||||
@ -308,7 +308,7 @@ static void attach_stream(DisplayChannel *display, Drawable *drawable, Stream *s
|
||||
stream->num_input_frames++;
|
||||
}
|
||||
|
||||
FOREACH_DCC(display, item, next, dcc) {
|
||||
FOREACH_DCC(display, link, next, dcc) {
|
||||
StreamAgent *agent;
|
||||
QRegion clip_in_draw_dest;
|
||||
|
||||
@ -350,6 +350,7 @@ static void before_reattach_stream(DisplayChannel *display,
|
||||
int index;
|
||||
StreamAgent *agent;
|
||||
RingItem *ring_item, *next;
|
||||
GList *link, *link_next;
|
||||
|
||||
spice_return_if_fail(stream->current);
|
||||
|
||||
@ -385,7 +386,7 @@ static void before_reattach_stream(DisplayChannel *display,
|
||||
}
|
||||
|
||||
|
||||
FOREACH_DCC(display, ring_item, next, dcc) {
|
||||
FOREACH_DCC(display, link, link_next, dcc) {
|
||||
double drop_factor;
|
||||
|
||||
agent = &dcc->stream_agents[index];
|
||||
@ -430,7 +431,7 @@ static Stream *display_channel_stream_try_new(DisplayChannel *display)
|
||||
static void display_channel_create_stream(DisplayChannel *display, Drawable *drawable)
|
||||
{
|
||||
DisplayChannelClient *dcc;
|
||||
RingItem *dcc_ring_item, *next;
|
||||
GList *link, *next;
|
||||
Stream *stream;
|
||||
SpiceRect* src_rect;
|
||||
|
||||
@ -467,7 +468,7 @@ static void display_channel_create_stream(DisplayChannel *display, Drawable *dra
|
||||
stream->input_fps_start_time = drawable->creation_time;
|
||||
display->streams_size_total += stream->width * stream->height;
|
||||
display->stream_count++;
|
||||
FOREACH_DCC(display, dcc_ring_item, next, dcc) {
|
||||
FOREACH_DCC(display, link, next, dcc) {
|
||||
dcc_create_stream(dcc, stream);
|
||||
}
|
||||
spice_debug("stream %d %dx%d (%d, %d) (%d, %d) %u fps",
|
||||
@ -870,10 +871,10 @@ clear_vis_region:
|
||||
static void detach_stream_gracefully(DisplayChannel *display, Stream *stream,
|
||||
Drawable *update_area_limit)
|
||||
{
|
||||
RingItem *item, *next;
|
||||
GList *link, *next;
|
||||
DisplayChannelClient *dcc;
|
||||
|
||||
FOREACH_DCC(display, item, next, dcc) {
|
||||
FOREACH_DCC(display, link, next, dcc) {
|
||||
dcc_detach_stream_gracefully(dcc, stream, update_area_limit);
|
||||
}
|
||||
if (stream->current) {
|
||||
@ -895,7 +896,7 @@ void stream_detach_behind(DisplayChannel *display, QRegion *region, Drawable *dr
|
||||
{
|
||||
Ring *ring = &display->streams;
|
||||
RingItem *item = ring_get_head(ring);
|
||||
RingItem *dcc_ring_item, *next;
|
||||
GList *link, *next;
|
||||
DisplayChannelClient *dcc;
|
||||
bool is_connected = red_channel_is_connected(RED_CHANNEL(display));
|
||||
|
||||
@ -904,7 +905,7 @@ void stream_detach_behind(DisplayChannel *display, QRegion *region, Drawable *dr
|
||||
int detach = 0;
|
||||
item = ring_next(ring, item);
|
||||
|
||||
FOREACH_DCC(display, dcc_ring_item, next, dcc) {
|
||||
FOREACH_DCC(display, link, next, dcc) {
|
||||
StreamAgent *agent = &dcc->stream_agents[get_stream_id(display, stream)];
|
||||
|
||||
if (region_intersects(&agent->vis_region, region)) {
|
||||
|
||||
Loading…
Reference in New Issue
Block a user