diff --git a/server/cursor-channel.c b/server/cursor-channel.c index 444d89be..c0b2fda1 100644 --- a/server/cursor-channel.c +++ b/server/cursor-channel.c @@ -48,7 +48,6 @@ G_STATIC_ASSERT(sizeof(CursorItem) <= QXL_CURSUR_DEVICE_DATA_SIZE); typedef struct RedCursorPipeItem { RedPipeItem base; CursorItem *cursor_item; - int refs; } RedCursorPipeItem; struct CursorChannel { @@ -82,6 +81,8 @@ struct CursorChannelClient { #include "cache-item.tmpl.c" #undef CLIENT_CURSOR_CACHE +static void cursor_pipe_item_free(RedCursorPipeItem *pipe_item); + static CursorItem *cursor_item_new(QXLInstance *qxl, RedCursorCmd *cmd) { CursorItem *cursor_item; @@ -136,8 +137,8 @@ static RedPipeItem *new_cursor_pipe_item(RedChannelClient *rcc, void *data, int { RedCursorPipeItem *item = spice_malloc0(sizeof(RedCursorPipeItem)); - red_pipe_item_init(&item->base, RED_PIPE_ITEM_TYPE_CURSOR); - item->refs = 1; + red_pipe_item_init_full(&item->base, RED_PIPE_ITEM_TYPE_CURSOR, + (GDestroyNotify)cursor_pipe_item_free); item->cursor_item = data; item->cursor_item->refs++; return &item->base; @@ -203,15 +204,9 @@ void cursor_channel_disconnect(CursorChannel *cursor_channel) } -static void put_cursor_pipe_item(CursorChannelClient *ccc, - RedCursorPipeItem *pipe_item) +static void cursor_pipe_item_free(RedCursorPipeItem *pipe_item) { spice_return_if_fail(pipe_item); - spice_return_if_fail(pipe_item->refs > 0); - - if (--pipe_item->refs) { - return; - } spice_assert(!red_pipe_item_is_linked(&pipe_item->base)); @@ -227,42 +222,6 @@ static void cursor_channel_client_on_disconnect(RedChannelClient *rcc) red_reset_cursor_cache(rcc); } -// TODO: share code between before/after_push since most of the items need the same -// release -static void cursor_channel_client_release_item_before_push(CursorChannelClient *ccc, - RedPipeItem *item) -{ - switch (item->type) { - case RED_PIPE_ITEM_TYPE_CURSOR: { - RedCursorPipeItem *cursor_pipe_item = SPICE_CONTAINEROF(item, RedCursorPipeItem, base); - put_cursor_pipe_item(ccc, cursor_pipe_item); - break; - } - case RED_PIPE_ITEM_TYPE_INVAL_ONE: - case RED_PIPE_ITEM_TYPE_VERB: - case RED_PIPE_ITEM_TYPE_CURSOR_INIT: - case RED_PIPE_ITEM_TYPE_INVAL_CURSOR_CACHE: - free(item); - break; - default: - spice_error("invalid pipe item type"); - } -} - -static void cursor_channel_client_release_item_after_push(CursorChannelClient *ccc, - RedPipeItem *item) -{ - switch (item->type) { - case RED_PIPE_ITEM_TYPE_CURSOR: { - RedCursorPipeItem *cursor_pipe_item = SPICE_CONTAINEROF(item, RedCursorPipeItem, base); - put_cursor_pipe_item(ccc, cursor_pipe_item); - break; - } - default: - spice_critical("invalid item type"); - } -} - static void red_marshall_cursor_init(RedChannelClient *rcc, SpiceMarshaller *base_marshaller, RedPipeItem *pipe_item) { @@ -354,7 +313,6 @@ static inline void red_marshall_inval(RedChannelClient *rcc, static void cursor_channel_send_item(RedChannelClient *rcc, RedPipeItem *pipe_item) { SpiceMarshaller *m = red_channel_client_get_marshaller(rcc); - CursorChannelClient *ccc = RCC_TO_CCC(rcc); switch (pipe_item->type) { case RED_PIPE_ITEM_TYPE_CURSOR: @@ -378,16 +336,15 @@ static void cursor_channel_send_item(RedChannelClient *rcc, RedPipeItem *pipe_it spice_error("invalid pipe item type"); } - cursor_channel_client_release_item_before_push(ccc, pipe_item); + red_pipe_item_unref(pipe_item); red_channel_client_begin_send_message(rcc); } static RedCursorPipeItem *cursor_pipe_item_ref(RedCursorPipeItem *item) { spice_return_val_if_fail(item, NULL); - spice_return_val_if_fail(item->refs > 0, NULL); - item->refs++; + red_pipe_item_ref(item); return item; } @@ -402,20 +359,6 @@ static void cursor_channel_hold_pipe_item(RedChannelClient *rcc, RedPipeItem *it cursor_pipe_item_ref(cursor_pipe_item); } -static void cursor_channel_release_item(RedChannelClient *rcc, RedPipeItem *item, int item_pushed) -{ - CursorChannelClient *ccc = RCC_TO_CCC(rcc); - - spice_assert(item); - - if (item_pushed) { - cursor_channel_client_release_item_after_push(ccc, item); - } else { - spice_debug("not pushed (%d)", item->type); - cursor_channel_client_release_item_before_push(ccc, item); - } -} - CursorChannel* cursor_channel_new(RedWorker *worker) { CursorChannel *cursor_channel; @@ -424,7 +367,6 @@ CursorChannel* cursor_channel_new(RedWorker *worker) .on_disconnect = cursor_channel_client_on_disconnect, .send_item = cursor_channel_send_item, .hold_item = cursor_channel_hold_pipe_item, - .release_item = cursor_channel_release_item }; spice_info("create cursor channel"); diff --git a/server/dcc-send.c b/server/dcc-send.c index 5f967cc5..f0f2e16e 100644 --- a/server/dcc-send.c +++ b/server/dcc-send.c @@ -2383,8 +2383,8 @@ void dcc_send_item(DisplayChannelClient *dcc, RedPipeItem *pipe_item) marshall_inval_palette(rcc, m, (RedCacheItem *)pipe_item); break; case RED_PIPE_ITEM_TYPE_STREAM_CREATE: { - StreamAgent *agent = SPICE_CONTAINEROF(pipe_item, StreamAgent, create_item); - marshall_stream_start(rcc, m, agent); + StreamCreateDestroyItem *item = SPICE_CONTAINEROF(pipe_item, StreamCreateDestroyItem, base); + marshall_stream_start(rcc, m, item->agent); break; } case RED_PIPE_ITEM_TYPE_STREAM_CLIP: { @@ -2393,8 +2393,8 @@ void dcc_send_item(DisplayChannelClient *dcc, RedPipeItem *pipe_item) break; } case RED_PIPE_ITEM_TYPE_STREAM_DESTROY: { - StreamAgent *agent = SPICE_CONTAINEROF(pipe_item, StreamAgent, destroy_item); - marshall_stream_end(rcc, m, agent); + StreamCreateDestroyItem *item = SPICE_CONTAINEROF(pipe_item, StreamCreateDestroyItem, base); + marshall_stream_end(rcc, m, item->agent); break; } case RED_PIPE_ITEM_TYPE_UPGRADE: @@ -2455,7 +2455,7 @@ void dcc_send_item(DisplayChannelClient *dcc, RedPipeItem *pipe_item) spice_warn_if_reached(); } - dcc_release_item(dcc, pipe_item, FALSE); + red_pipe_item_unref(pipe_item); // a message is pending if (red_channel_client_send_message_pending(rcc)) { diff --git a/server/dcc.c b/server/dcc.c index db77cc7c..b9e4eb32 100644 --- a/server/dcc.c +++ b/server/dcc.c @@ -288,7 +288,9 @@ void red_drawable_pipe_item_free(RedPipeItem *item) spice_assert(item->refcount == 0); spice_warn_if_fail(!ring_item_is_linked(&item->link)); - spice_warn_if_fail(!ring_item_is_linked(&dpi->base)); + if (ring_item_is_linked(&dpi->base)) { + ring_remove(&dpi->base); + } drawable_unref(dpi->drawable); free(dpi); } @@ -343,8 +345,6 @@ static void dcc_init_stream_agents(DisplayChannelClient *dcc) agent->stream = &display->streams_buf[i]; region_init(&agent->vis_region); region_init(&agent->clip); - red_pipe_item_init(&agent->create_item, RED_PIPE_ITEM_TYPE_STREAM_CREATE); - red_pipe_item_init(&agent->destroy_item, RED_PIPE_ITEM_TYPE_STREAM_DESTROY); } dcc->use_video_encoder_rate_control = red_channel_client_test_remote_cap(RED_CHANNEL_CLIENT(dcc), SPICE_DISPLAY_CAP_STREAM_REPORT); @@ -1607,89 +1607,3 @@ int dcc_handle_migrate_data(DisplayChannelClient *dcc, uint32_t size, void *mess red_channel_client_ack_zero_messages_window(RED_CHANNEL_CLIENT(dcc)); return TRUE; } - -static void release_item_after_push(RedPipeItem *item) -{ - switch (item->type) { - case RED_PIPE_ITEM_TYPE_DRAW: - case RED_PIPE_ITEM_TYPE_IMAGE: - case RED_PIPE_ITEM_TYPE_STREAM_CLIP: - case RED_PIPE_ITEM_TYPE_MONITORS_CONFIG: - case RED_PIPE_ITEM_TYPE_UPGRADE: - red_pipe_item_unref(item); - break; - case RED_PIPE_ITEM_TYPE_GL_SCANOUT: - case RED_PIPE_ITEM_TYPE_GL_DRAW: - case RED_PIPE_ITEM_TYPE_VERB: - free(item); - break; - default: - spice_critical("invalid item type"); - } -} - -// TODO: share code between before/after_push since most of the items need the same -// release -static void release_item_before_push(DisplayChannelClient *dcc, RedPipeItem *item) -{ - DisplayChannel *display = DCC_TO_DC(dcc); - - spice_debug("item.type: %d", item->type); - switch (item->type) { - case RED_PIPE_ITEM_TYPE_DRAW: { - RedDrawablePipeItem *dpi = SPICE_CONTAINEROF(item, RedDrawablePipeItem, dpi_pipe_item); - ring_remove(&dpi->base); - red_pipe_item_unref(item); - break; - } - case RED_PIPE_ITEM_TYPE_STREAM_CREATE: { - StreamAgent *agent = SPICE_CONTAINEROF(item, StreamAgent, create_item); - stream_agent_unref(display, agent); - break; - } - case RED_PIPE_ITEM_TYPE_STREAM_DESTROY: { - StreamAgent *agent = SPICE_CONTAINEROF(item, StreamAgent, destroy_item); - stream_agent_unref(display, agent); - break; - } - case RED_PIPE_ITEM_TYPE_STREAM_CLIP: - case RED_PIPE_ITEM_TYPE_UPGRADE: - case RED_PIPE_ITEM_TYPE_IMAGE: - case RED_PIPE_ITEM_TYPE_MONITORS_CONFIG: - red_pipe_item_unref(item); - break; - case RED_PIPE_ITEM_TYPE_CREATE_SURFACE: { - RedSurfaceCreateItem *surface_create = SPICE_CONTAINEROF(item, RedSurfaceCreateItem, - pipe_item); - free(surface_create); - break; - } - case RED_PIPE_ITEM_TYPE_DESTROY_SURFACE: { - RedSurfaceDestroyItem *surface_destroy = SPICE_CONTAINEROF(item, RedSurfaceDestroyItem, - pipe_item); - free(surface_destroy); - break; - } - case RED_PIPE_ITEM_TYPE_INVAL_ONE: - case RED_PIPE_ITEM_TYPE_VERB: - case RED_PIPE_ITEM_TYPE_MIGRATE_DATA: - case RED_PIPE_ITEM_TYPE_PIXMAP_SYNC: - case RED_PIPE_ITEM_TYPE_PIXMAP_RESET: - case RED_PIPE_ITEM_TYPE_INVAL_PALETTE_CACHE: - case RED_PIPE_ITEM_TYPE_STREAM_ACTIVATE_REPORT: - case RED_PIPE_ITEM_TYPE_GL_SCANOUT: - case RED_PIPE_ITEM_TYPE_GL_DRAW: - free(item); - break; - default: - spice_critical("invalid item type"); - } -} - -void dcc_release_item(DisplayChannelClient *dcc, RedPipeItem *item, int item_pushed) -{ - if (item_pushed) - release_item_after_push(item); - else - release_item_before_push(dcc, item); -} diff --git a/server/dcc.h b/server/dcc.h index 1dd53bd7..864a7681 100644 --- a/server/dcc.h +++ b/server/dcc.h @@ -122,8 +122,8 @@ struct DisplayChannelClient { #define RCC_TO_DCC(rcc) SPICE_CONTAINEROF((rcc), DisplayChannelClient, common.base) typedef struct RedSurfaceCreateItem { - SpiceMsgSurfaceCreate surface_create; RedPipeItem pipe_item; + SpiceMsgSurfaceCreate surface_create; } RedSurfaceCreateItem; typedef struct RedGlScanoutUnixItem { @@ -154,7 +154,6 @@ typedef struct RedDrawablePipeItem { RedPipeItem dpi_pipe_item; /* link for the client's pipe itself */ Drawable *drawable; DisplayChannelClient *dcc; - uint8_t refs; } RedDrawablePipeItem; DisplayChannelClient* dcc_new (DisplayChannel *display, @@ -204,9 +203,6 @@ void dcc_append_drawable (DisplayCha void dcc_add_drawable_after (DisplayChannelClient *dcc, Drawable *drawable, RedPipeItem *pos); -void dcc_release_item (DisplayChannelClient *dcc, - RedPipeItem *item, - int item_pushed); void dcc_send_item (DisplayChannelClient *dcc, RedPipeItem *item); int dcc_clear_surface_drawables_from_pipe (DisplayChannelClient *dcc, diff --git a/server/display-channel.c b/server/display-channel.c index 7715b959..1487f100 100644 --- a/server/display-channel.c +++ b/server/display-channel.c @@ -1946,14 +1946,6 @@ static void hold_item(RedChannelClient *rcc, RedPipeItem *item) } } -static void release_item(RedChannelClient *rcc, RedPipeItem *item, int item_pushed) -{ - DisplayChannelClient *dcc = RCC_TO_DCC(rcc); - - spice_return_if_fail(item != NULL); - dcc_release_item(dcc, item, item_pushed); -} - static int handle_migrate_flush_mark(RedChannelClient *rcc) { DisplayChannel *display_channel = SPICE_CONTAINEROF(rcc->channel, DisplayChannel, common.base); @@ -1995,7 +1987,6 @@ DisplayChannel* display_channel_new(SpiceServer *reds, RedWorker *worker, .on_disconnect = on_disconnect, .send_item = send_item, .hold_item = hold_item, - .release_item = release_item, .handle_migrate_flush_mark = handle_migrate_flush_mark, .handle_migrate_data = handle_migrate_data, .handle_migrate_data_get_serial = handle_migrate_data_get_serial diff --git a/server/display-channel.h b/server/display-channel.h index 76668de8..647d8c06 100644 --- a/server/display-channel.h +++ b/server/display-channel.h @@ -241,8 +241,8 @@ static inline int get_stream_id(DisplayChannel *display, Stream *stream) } typedef struct RedSurfaceDestroyItem { - SpiceMsgSurfaceDestroy surface_destroy; RedPipeItem pipe_item; + SpiceMsgSurfaceDestroy surface_destroy; } RedSurfaceDestroyItem; typedef struct RedUpgradeItem { diff --git a/server/inputs-channel.c b/server/inputs-channel.c index 0ce12dea..a3c9fb2d 100644 --- a/server/inputs-channel.c +++ b/server/inputs-channel.c @@ -254,12 +254,6 @@ static void inputs_channel_send_migrate_data(RedChannelClient *rcc, spice_marshaller_add_uint16(m, icc->motion_count); } -static void inputs_channel_release_pipe_item(RedChannelClient *rcc, - RedPipeItem *base, int item_pushed) -{ - free(base); -} - static void inputs_channel_send_item(RedChannelClient *rcc, RedPipeItem *base) { SpiceMarshaller *m = red_channel_client_get_marshaller(rcc); @@ -627,7 +621,6 @@ InputsChannel* inputs_channel_new(RedsState *reds) channel_cbs.on_disconnect = inputs_channel_on_disconnect; channel_cbs.send_item = inputs_channel_send_item; channel_cbs.hold_item = inputs_channel_hold_pipe_item; - channel_cbs.release_item = inputs_channel_release_pipe_item; channel_cbs.alloc_recv_buf = inputs_channel_alloc_msg_rcv_buf; channel_cbs.release_recv_buf = inputs_channel_release_msg_rcv_buf; channel_cbs.handle_migrate_data = inputs_channel_handle_migrate_data; diff --git a/server/main-channel.c b/server/main-channel.c index 98ce6608..d540796f 100644 --- a/server/main-channel.c +++ b/server/main-channel.c @@ -165,9 +165,6 @@ enum NetTestStage { NET_TEST_STAGE_COMPLETE, }; -static void main_channel_release_pipe_item(RedChannelClient *rcc, - RedPipeItem *base, int item_pushed); - int main_channel_is_connected(MainChannel *main_chan) { return red_channel_is_connected(&main_chan->base); @@ -250,13 +247,20 @@ static RedPipeItem *main_agent_tokens_item_new(RedChannelClient *rcc, uint32_t n return &item->base; } +static void main_agent_data_item_free(RedAgentDataPipeItem *item) +{ + item->free_data(item->data, item->opaque); + free(item); +} + static RedPipeItem *main_agent_data_item_new(RedChannelClient *rcc, uint8_t* data, size_t len, spice_marshaller_item_free_func free_data, void *opaque) { RedAgentDataPipeItem *item = spice_malloc(sizeof(RedAgentDataPipeItem)); - red_pipe_item_init(&item->base, RED_PIPE_ITEM_TYPE_MAIN_AGENT_DATA); + red_pipe_item_init_full(&item->base, RED_PIPE_ITEM_TYPE_MAIN_AGENT_DATA, + (GDestroyNotify)main_agent_data_item_free); item->data = data; item->len = len; item->free_data = free_data; @@ -302,12 +306,19 @@ static RedPipeItem *main_uuid_item_new(MainChannelClient *mcc, const uint8_t uui return &item->base; } +static void main_notify_item_free(RedNotifyPipeItem *data) +{ + free(data->msg); + free(data); +} + static RedPipeItem *main_notify_item_new(RedChannelClient *rcc, void *data, int num) { RedNotifyPipeItem *item = spice_malloc(sizeof(RedNotifyPipeItem)); const char *msg = data; - red_pipe_item_init(&item->base, RED_PIPE_ITEM_TYPE_MAIN_NOTIFY); + red_pipe_item_init_full(&item->base, RED_PIPE_ITEM_TYPE_MAIN_NOTIFY, + (GDestroyNotify)main_notify_item_free); item->msg = spice_strdup(msg); return &item->base; } @@ -712,7 +723,7 @@ static void main_channel_send_item(RedChannelClient *rcc, RedPipeItem *base) spice_printerr("Init msg for client %p was not sent yet " "(client is probably during semi-seamless migration). Ignoring msg type %d", rcc->client, base->type); - main_channel_release_pipe_item(rcc, base, FALSE); + red_pipe_item_unref(base); return; } switch (base->type) { @@ -783,27 +794,6 @@ static void main_channel_send_item(RedChannelClient *rcc, RedPipeItem *base) red_channel_client_begin_send_message(rcc); } -static void main_channel_release_pipe_item(RedChannelClient *rcc, - RedPipeItem *base, int item_pushed) -{ - switch (base->type) { - case RED_PIPE_ITEM_TYPE_MAIN_AGENT_DATA: { - RedAgentDataPipeItem *data = (RedAgentDataPipeItem *)base; - - data->free_data(data->data, data->opaque); - break; - } - case RED_PIPE_ITEM_TYPE_MAIN_NOTIFY: { - RedNotifyPipeItem *data = (RedNotifyPipeItem *)base; - free(data->msg); - break; - } - default: - break; - } - free(base); -} - static void main_channel_client_handle_migrate_connected(MainChannelClient *mcc, int success, int seamless) @@ -1165,7 +1155,6 @@ MainChannel* main_channel_new(RedsState *reds) channel_cbs.on_disconnect = main_channel_client_on_disconnect; channel_cbs.send_item = main_channel_send_item; channel_cbs.hold_item = main_channel_hold_pipe_item; - channel_cbs.release_item = main_channel_release_pipe_item; channel_cbs.alloc_recv_buf = main_channel_alloc_msg_rcv_buf; channel_cbs.release_recv_buf = main_channel_release_msg_rcv_buf; channel_cbs.handle_migrate_flush_mark = main_channel_handle_migrate_flush_mark; diff --git a/server/red-channel.c b/server/red-channel.c index a99c6c6f..9aef3636 100644 --- a/server/red-channel.c +++ b/server/red-channel.c @@ -578,28 +578,13 @@ static void red_channel_client_send_item(RedChannelClient *rcc, RedPipeItem *ite rcc->channel->channel_cbs.send_item(rcc, item); return; } - free(item); -} - -static void red_channel_client_release_item(RedChannelClient *rcc, RedPipeItem *item, int item_pushed) -{ - switch (item->type) { - case RED_PIPE_ITEM_TYPE_SET_ACK: - case RED_PIPE_ITEM_TYPE_EMPTY_MSG: - case RED_PIPE_ITEM_TYPE_MIGRATE: - case RED_PIPE_ITEM_TYPE_PING: - free(item); - break; - default: - rcc->channel->channel_cbs.release_item(rcc, item, item_pushed); - } + red_pipe_item_unref(item); } static inline void red_channel_client_release_sent_item(RedChannelClient *rcc) { if (rcc->send_data.item) { - red_channel_client_release_item(rcc, - rcc->send_data.item, TRUE); + red_pipe_item_unref(rcc->send_data.item); rcc->send_data.item = NULL; } } @@ -1030,7 +1015,7 @@ RedChannel *red_channel_create(int size, spice_assert(size >= sizeof(*channel)); spice_assert(channel_cbs->config_socket && channel_cbs->on_disconnect && handle_message && - channel_cbs->alloc_recv_buf && channel_cbs->release_item); + channel_cbs->alloc_recv_buf); spice_assert(channel_cbs->handle_migrate_data || !(migration_flags & SPICE_MIGRATE_NEED_DATA_TRANSFER)); channel = spice_malloc0(size); @@ -1663,7 +1648,7 @@ static inline gboolean client_pipe_add(RedChannelClient *rcc, RedPipeItem *item, spice_assert(rcc && item); if (SPICE_UNLIKELY(!red_channel_client_is_connected(rcc))) { spice_debug("rcc is disconnected %p", rcc); - red_channel_client_release_item(rcc, item, FALSE); + red_pipe_item_unref(item); return FALSE; } if (ring_is_empty(&rcc->pipe) && rcc->stream->watch) { @@ -1770,12 +1755,9 @@ int red_channel_is_connected(RedChannel *channel) return channel && (channel->clients_num > 0); } -void red_channel_client_clear_sent_item(RedChannelClient *rcc) +static void red_channel_client_clear_sent_item(RedChannelClient *rcc) { - if (rcc->send_data.item) { - red_channel_client_release_item(rcc, rcc->send_data.item, TRUE); - rcc->send_data.item = NULL; - } + red_channel_client_release_sent_item(rcc); rcc->send_data.blocked = FALSE; rcc->send_data.size = 0; } @@ -1789,7 +1771,7 @@ void red_channel_client_pipe_clear(RedChannelClient *rcc) } while ((item = (RedPipeItem *)ring_get_head(&rcc->pipe))) { ring_remove(&item->link); - red_channel_client_release_item(rcc, item, FALSE); + red_pipe_item_unref(item); } rcc->pipe_size = 0; } @@ -2033,7 +2015,7 @@ void red_channel_client_pipe_remove_and_release(RedChannelClient *rcc, RedPipeItem *item) { red_channel_client_pipe_remove(rcc, item); - red_channel_client_release_item(rcc, item, FALSE); + red_pipe_item_unref(item); } /* @@ -2398,7 +2380,7 @@ int red_channel_client_wait_pipe_item_sent(RedChannelClient *rcc, red_channel_client_push(rcc); } - red_channel_client_release_item(rcc, item, TRUE); + red_pipe_item_unref(item); if (item_in_pipe) { spice_warning("timeout"); return FALSE; diff --git a/server/red-channel.h b/server/red-channel.h index 03e64077..63cb2d93 100644 --- a/server/red-channel.h +++ b/server/red-channel.h @@ -159,8 +159,6 @@ typedef void (*channel_disconnect_proc)(RedChannelClient *rcc); typedef int (*channel_configure_socket_proc)(RedChannelClient *rcc); typedef void (*channel_send_pipe_item_proc)(RedChannelClient *rcc, RedPipeItem *item); typedef void (*channel_hold_pipe_item_proc)(RedChannelClient *rcc, RedPipeItem *item); -typedef void (*channel_release_pipe_item_proc)(RedChannelClient *rcc, - RedPipeItem *item, int item_pushed); typedef void (*channel_on_incoming_error_proc)(RedChannelClient *rcc); typedef void (*channel_on_outgoing_error_proc)(RedChannelClient *rcc); @@ -188,7 +186,6 @@ typedef struct { channel_disconnect_proc on_disconnect; channel_send_pipe_item_proc send_item; channel_hold_pipe_item_proc hold_item; - channel_release_pipe_item_proc release_item; channel_alloc_msg_recv_buf_proc alloc_recv_buf; channel_release_msg_recv_buf_proc release_recv_buf; channel_handle_migrate_flush_mark_proc handle_migrate_flush_mark; diff --git a/server/smartcard.c b/server/smartcard.c index e483eecb..a75f01c3 100644 --- a/server/smartcard.c +++ b/server/smartcard.c @@ -504,16 +504,6 @@ static void smartcard_channel_send_item(RedChannelClient *rcc, RedPipeItem *item red_channel_client_begin_send_message(rcc); } -static void smartcard_channel_release_pipe_item(RedChannelClient *rcc, - RedPipeItem *item, int item_pushed) -{ - if (item->type == RED_PIPE_ITEM_TYPE_SMARTCARD_DATA) { - red_pipe_item_unref(item); - } else { - free(item); - } -} - static void smartcard_channel_on_disconnect(RedChannelClient *rcc) { SmartCardChannelClient *scc = SPICE_CONTAINEROF(rcc, SmartCardChannelClient, base); @@ -541,7 +531,6 @@ static void smartcard_push_error(RedChannelClient *rcc, uint32_t reader_id, VSCE red_pipe_item_init(&error_item->base, RED_PIPE_ITEM_TYPE_ERROR); - error_item->base.type = RED_PIPE_ITEM_TYPE_ERROR; error_item->vheader.reader_id = reader_id; error_item->vheader.type = VSC_Error; error_item->vheader.length = sizeof(error_item->error); @@ -797,7 +786,6 @@ static void smartcard_init(RedsState *reds) channel_cbs.on_disconnect = smartcard_channel_on_disconnect; channel_cbs.send_item = smartcard_channel_send_item; channel_cbs.hold_item = smartcard_channel_hold_pipe_item; - channel_cbs.release_item = smartcard_channel_release_pipe_item; channel_cbs.alloc_recv_buf = smartcard_channel_alloc_msg_rcv_buf; channel_cbs.release_recv_buf = smartcard_channel_release_msg_rcv_buf; channel_cbs.handle_migrate_flush_mark = smartcard_channel_client_handle_migrate_flush_mark; diff --git a/server/spicevmc.c b/server/spicevmc.c index bdaa3c3f..14d34b49 100644 --- a/server/spicevmc.c +++ b/server/spicevmc.c @@ -431,23 +431,12 @@ static void spicevmc_red_channel_send_item(RedChannelClient *rcc, break; default: spice_error("bad pipe item %d", item->type); - free(item); + red_pipe_item_unref(item); return; } red_channel_client_begin_send_message(rcc); } -static void spicevmc_red_channel_release_pipe_item(RedChannelClient *rcc, - RedPipeItem *item, - int item_pushed) -{ - if (item->type == RED_PIPE_ITEM_TYPE_SPICEVMC_DATA) { - red_pipe_item_unref(item); - } else { - free(item); - } -} - static void spicevmc_connect(RedChannel *channel, RedClient *client, RedsStream *stream, int migration, int num_common_caps, uint32_t *common_caps, int num_caps, uint32_t *caps) @@ -509,7 +498,6 @@ RedCharDevice *spicevmc_device_connect(RedsState *reds, channel_cbs.on_disconnect = spicevmc_red_channel_client_on_disconnect; channel_cbs.send_item = spicevmc_red_channel_send_item; channel_cbs.hold_item = spicevmc_red_channel_hold_pipe_item; - channel_cbs.release_item = spicevmc_red_channel_release_pipe_item; channel_cbs.alloc_recv_buf = spicevmc_red_channel_alloc_msg_rcv_buf; channel_cbs.release_recv_buf = spicevmc_red_channel_release_msg_rcv_buf; channel_cbs.handle_migrate_flush_mark = spicevmc_channel_client_handle_migrate_flush_mark; diff --git a/server/stream.c b/server/stream.c index 35eb7c25..4c733dea 100644 --- a/server/stream.c +++ b/server/stream.c @@ -63,6 +63,36 @@ void stream_agent_stats_print(StreamAgent *agent) #endif } +static void stream_create_destroy_item_release(RedPipeItem *base) +{ + StreamCreateDestroyItem *item = SPICE_CONTAINEROF(base, StreamCreateDestroyItem, base); + DisplayChannel *display = (DisplayChannel*)item->agent->dcc->common.base.channel; + stream_agent_unref(display, item->agent); + free(item); +} + +static RedPipeItem *stream_create_destroy_item_new(StreamAgent *agent, gint type) +{ + StreamCreateDestroyItem *item = spice_new0(StreamCreateDestroyItem, 1); + + red_pipe_item_init_full(&item->base, type, + (GDestroyNotify)stream_create_destroy_item_release); + agent->stream->refs++; + item->agent = agent; + return &item->base; +} + +static RedPipeItem *stream_create_item_new(StreamAgent *agent) +{ + return stream_create_destroy_item_new(agent, RED_PIPE_ITEM_TYPE_STREAM_CREATE); +} + +static RedPipeItem *stream_destroy_item_new(StreamAgent *agent) +{ + return stream_create_destroy_item_new(agent, RED_PIPE_ITEM_TYPE_STREAM_DESTROY); +} + + void stream_stop(DisplayChannel *display, Stream *stream) { DisplayChannelClient *dcc; @@ -78,7 +108,6 @@ void stream_stop(DisplayChannel *display, Stream *stream) stream_agent = &dcc->stream_agents[get_stream_id(display, stream)]; region_clear(&stream_agent->vis_region); region_clear(&stream_agent->clip); - spice_assert(!red_pipe_item_is_linked(&stream_agent->destroy_item)); if (stream_agent->video_encoder && dcc->use_video_encoder_rate_control) { uint64_t stream_bit_rate = stream_agent->video_encoder->get_bit_rate(stream_agent->video_encoder); @@ -89,8 +118,7 @@ void stream_stop(DisplayChannel *display, Stream *stream) dcc->streams_max_bit_rate = stream_bit_rate; } } - stream->refs++; - red_channel_client_pipe_add(RED_CHANNEL_CLIENT(dcc), &stream_agent->destroy_item); + red_channel_client_pipe_add(RED_CHANNEL_CLIENT(dcc), stream_destroy_item_new(stream_agent)); stream_agent_stats_print(stream_agent); } display->streams_size_total -= stream->width * stream->height; @@ -702,7 +730,6 @@ void dcc_create_stream(DisplayChannelClient *dcc, Stream *stream) spice_return_if_fail(region_is_empty(&agent->vis_region)); - stream->refs++; if (stream->current) { agent->frames = 1; region_clone(&agent->vis_region, &stream->current->tree_item.base.rgn); @@ -728,7 +755,7 @@ void dcc_create_stream(DisplayChannelClient *dcc, Stream *stream) } else { agent->video_encoder = mjpeg_encoder_new(0, NULL); } - red_channel_client_pipe_add(RED_CHANNEL_CLIENT(dcc), &agent->create_item); + red_channel_client_pipe_add(RED_CHANNEL_CLIENT(dcc), stream_create_item_new(agent)); if (red_channel_client_test_remote_cap(RED_CHANNEL_CLIENT(dcc), SPICE_DISPLAY_CAP_STREAM_REPORT)) { RedStreamActivateReportItem *report_pipe_item = spice_malloc0(sizeof(*report_pipe_item)); diff --git a/server/stream.h b/server/stream.h index 3c8d7614..511d7525 100644 --- a/server/stream.h +++ b/server/stream.h @@ -82,8 +82,6 @@ typedef struct StreamAgent { vis_region will contain c2 and also the part of c1/c2 that still displays fragments of the video */ - RedPipeItem create_item; - RedPipeItem destroy_item; Stream *stream; uint64_t last_send_time; VideoEncoder *video_encoder; @@ -109,6 +107,11 @@ typedef struct RedStreamClipItem { RedStreamClipItem * red_stream_clip_item_new (StreamAgent *agent); +typedef struct StreamCreateDestroyItem { + RedPipeItem base; + StreamAgent *agent; +} StreamCreateDestroyItem; + typedef struct ItemTrace { red_time_t time; red_time_t first_frame_time;