red-pipe-item: Use inheritance on RedPipeItem

This allows to:
- reuse reference counting;
- avoid having to manually call g_free to release item memory;
- assure item is initialized;
- avoids some manual casts.

It will also allows to use smart pointers.

Signed-off-by: Frediano Ziglio <freddy77@gmail.com>
Acked-by: Julien Ropé <jrope@gmail.com>
This commit is contained in:
Frediano Ziglio 2020-06-04 21:31:05 +01:00
parent 45e964dc5a
commit a30df693cf
24 changed files with 403 additions and 482 deletions

View File

@ -76,9 +76,9 @@ static void FUNC_NAME(remove)(CHANNELCLIENT *channel_client, RedCacheItem *item)
auto id = item->id;
RedCachePipeItem *pipe_item = reinterpret_cast<RedCachePipeItem*>(item);
red_pipe_item_init(&pipe_item->base, RED_PIPE_ITEM_TYPE_INVAL_ONE);
new (pipe_item) RedCachePipeItem();
pipe_item->inval_one.id = id;
channel_client->pipe_add_tail(&pipe_item->base); // for now
channel_client->pipe_add_tail(pipe_item); // for now
}
static int FUNC_NAME(add)(CHANNELCLIENT *channel_client, uint64_t id, size_t size)

View File

@ -65,3 +65,8 @@ bool CommonGraphicsChannelClient::config_socket()
ack_set_client_window(is_low_bandwidth ? WIDE_CLIENT_ACK_WINDOW : NARROW_CLIENT_ACK_WINDOW);
return true;
}
RedCachePipeItem::RedCachePipeItem():
RedPipeItem(RED_PIPE_ITEM_TYPE_INVAL_ONE)
{
}

View File

@ -69,8 +69,8 @@ protected:
};
/* pipe item used to release a specific cached item on the client */
struct RedCachePipeItem {
RedPipeItem base;
struct RedCachePipeItem final: public RedPipeItem {
RedCachePipeItem();
SpiceMsgDisplayInvalOne inval_one;
};

View File

@ -25,41 +25,35 @@
#include "cursor-channel-client.h"
#include "reds.h"
typedef struct RedCursorPipeItem {
RedPipeItem base;
struct RedCursorPipeItem: public RedPipeItem {
using RedPipeItem::RedPipeItem;
~RedCursorPipeItem();
RedCursorCmd *red_cursor;
} RedCursorPipeItem;
static void cursor_pipe_item_free(RedPipeItem *pipe_item);
};
static RedCursorPipeItem *cursor_pipe_item_new(RedCursorCmd *cmd)
{
RedCursorPipeItem *item = g_new0(RedCursorPipeItem, 1);
RedCursorPipeItem *item = new RedCursorPipeItem(RED_PIPE_ITEM_TYPE_CURSOR);
spice_return_val_if_fail(cmd != NULL, NULL);
red_pipe_item_init_full(&item->base, RED_PIPE_ITEM_TYPE_CURSOR,
cursor_pipe_item_free);
item->red_cursor = red_cursor_cmd_ref(cmd);
return item;
}
static void cursor_pipe_item_free(RedPipeItem *base)
RedCursorPipeItem::~RedCursorPipeItem()
{
RedCursorPipeItem *pipe_item = SPICE_UPCAST(RedCursorPipeItem, base);
red_cursor_cmd_unref(pipe_item->red_cursor);
g_free(pipe_item);
red_cursor_cmd_unref(red_cursor);
}
static void cursor_channel_set_item(CursorChannel *cursor, RedCursorPipeItem *item)
{
if (item) {
red_pipe_item_ref(&item->base);
red_pipe_item_ref(item);
}
if (cursor->item) {
red_pipe_item_unref(&cursor->item->base);
red_pipe_item_unref(cursor->item);
}
cursor->item = item;
}
@ -89,7 +83,7 @@ static void cursor_fill(CursorChannelClient *ccc, RedCursorPipeItem *cursor,
if (red_cursor->data_size) {
SpiceMarshaller *m2 = spice_marshaller_get_submarshaller(m);
cursor->base.add_to_marshaller(m2, red_cursor->data, red_cursor->data_size);
cursor->add_to_marshaller(m2, red_cursor->data, red_cursor->data_size);
}
}
@ -178,10 +172,10 @@ void CursorChannelClient::send_item(RedPipeItem *pipe_item)
switch (pipe_item->type) {
case RED_PIPE_ITEM_TYPE_CURSOR:
red_marshall_cursor(ccc, m, SPICE_UPCAST(RedCursorPipeItem, pipe_item));
red_marshall_cursor(ccc, m, static_cast<RedCursorPipeItem*>(pipe_item));
break;
case RED_PIPE_ITEM_TYPE_INVAL_ONE:
red_marshall_inval(this, m, SPICE_UPCAST(RedCachePipeItem, pipe_item));
red_marshall_inval(this, m, static_cast<RedCachePipeItem*>(pipe_item));
break;
case RED_PIPE_ITEM_TYPE_CURSOR_INIT:
reset_cursor_cache();
@ -235,7 +229,7 @@ void CursorChannel::process_cmd(RedCursorCmd *cursor_cmd)
break;
default:
spice_warning("invalid cursor command %u", cursor_cmd->type);
red_pipe_item_unref(&cursor_pipe_item->base);
red_pipe_item_unref(cursor_pipe_item);
return;
}
@ -243,9 +237,9 @@ void CursorChannel::process_cmd(RedCursorCmd *cursor_cmd)
(mouse_mode == SPICE_MOUSE_MODE_SERVER
|| cursor_cmd->type != QXL_CURSOR_MOVE
|| cursor_show)) {
pipes_add(&cursor_pipe_item->base);
pipes_add(cursor_pipe_item);
} else {
red_pipe_item_unref(&cursor_pipe_item->base);
red_pipe_item_unref(cursor_pipe_item);
}
}
@ -316,7 +310,7 @@ void CursorChannel::on_connect(RedClient *client, RedStream *stream, int migrati
CursorChannel::~CursorChannel()
{
if (item) {
red_pipe_item_unref(&item->base);
red_pipe_item_unref(item);
}
}

View File

@ -626,7 +626,7 @@ static bool pipe_rendered_drawables_intersect_with_areas(DisplayChannelClient *d
if (pipe_item->type != RED_PIPE_ITEM_TYPE_DRAW)
continue;
drawable = SPICE_UPCAST(RedDrawablePipeItem, pipe_item)->drawable;
drawable = static_cast<RedDrawablePipeItem*>(pipe_item)->drawable;
if (ring_item_is_linked(&drawable->list_link))
continue; // item hasn't been rendered
@ -719,7 +719,7 @@ static void red_pipe_replace_rendered_drawables_with_images(DisplayChannelClient
prev = l->prev;
if (pipe_item->type != RED_PIPE_ITEM_TYPE_DRAW)
continue;
dpi = SPICE_UPCAST(RedDrawablePipeItem, pipe_item);
dpi = static_cast<RedDrawablePipeItem*>(pipe_item);
drawable = dpi->drawable;
if (ring_item_is_linked(&drawable->list_link))
continue; // item hasn't been rendered
@ -1969,8 +1969,8 @@ static void red_marshall_image(DisplayChannelClient *dcc,
spice_marshall_Image(src_bitmap_out, &red_image,
&bitmap_palette_out, &lzplt_palette_out);
item->base.add_to_marshaller(src_bitmap_out, item->data,
bitmap.y * bitmap.stride);
item->add_to_marshaller(src_bitmap_out, item->data,
bitmap.y * bitmap.stride);
region_remove(surface_lossy_region, &copy.base.box);
}
spice_chunks_destroy(chunks);
@ -2286,7 +2286,7 @@ static void marshall_gl_draw(RedChannelClient *rcc,
SpiceMarshaller *m,
RedPipeItem *item)
{
RedGlDrawItem *p = SPICE_UPCAST(RedGlDrawItem, item);
RedGlDrawItem *p = static_cast<RedGlDrawItem*>(item);
rcc->init_send_data(SPICE_MSG_DISPLAY_GL_DRAW);
spice_marshall_msg_display_gl_draw(m, &p->draw);
@ -2335,34 +2335,34 @@ void DisplayChannelClient::send_item(RedPipeItem *pipe_item)
::reset_send_data(dcc);
switch (pipe_item->type) {
case RED_PIPE_ITEM_TYPE_DRAW: {
RedDrawablePipeItem *dpi = SPICE_UPCAST(RedDrawablePipeItem, pipe_item);
RedDrawablePipeItem *dpi = static_cast<RedDrawablePipeItem*>(pipe_item);
marshall_qxl_drawable(this, m, dpi);
break;
}
case RED_PIPE_ITEM_TYPE_INVAL_ONE:
marshall_inval_palette(this, m, SPICE_UPCAST(RedCachePipeItem, pipe_item));
marshall_inval_palette(this, m, static_cast<RedCachePipeItem*>(pipe_item));
break;
case RED_PIPE_ITEM_TYPE_STREAM_CREATE: {
StreamCreateDestroyItem *item = SPICE_UPCAST(StreamCreateDestroyItem, pipe_item);
StreamCreateDestroyItem *item = static_cast<StreamCreateDestroyItem*>(pipe_item);
marshall_stream_start(this, m, item->agent);
break;
}
case RED_PIPE_ITEM_TYPE_STREAM_CLIP:
marshall_stream_clip(this, m, SPICE_UPCAST(VideoStreamClipItem, pipe_item));
marshall_stream_clip(this, m, static_cast<VideoStreamClipItem*>(pipe_item));
break;
case RED_PIPE_ITEM_TYPE_STREAM_DESTROY: {
StreamCreateDestroyItem *item = SPICE_UPCAST(StreamCreateDestroyItem, pipe_item);
StreamCreateDestroyItem *item = static_cast<StreamCreateDestroyItem*>(pipe_item);
marshall_stream_end(this, m, item->agent);
break;
}
case RED_PIPE_ITEM_TYPE_UPGRADE:
marshall_upgrade(this, m, SPICE_UPCAST(RedUpgradeItem, pipe_item));
marshall_upgrade(this, m, static_cast<RedUpgradeItem*>(pipe_item));
break;
case RED_PIPE_ITEM_TYPE_MIGRATE_DATA:
display_channel_marshall_migrate_data(this, m);
break;
case RED_PIPE_ITEM_TYPE_IMAGE:
red_marshall_image(this, m, SPICE_UPCAST(RedImageItem, pipe_item));
red_marshall_image(this, m, static_cast<RedImageItem*>(pipe_item));
break;
case RED_PIPE_ITEM_TYPE_PIXMAP_SYNC:
display_channel_marshall_pixmap_sync(this, m);
@ -2375,23 +2375,23 @@ void DisplayChannelClient::send_item(RedPipeItem *pipe_item)
init_send_data(SPICE_MSG_DISPLAY_INVAL_ALL_PALETTES);
break;
case RED_PIPE_ITEM_TYPE_CREATE_SURFACE: {
RedSurfaceCreateItem *surface_create = SPICE_UPCAST(RedSurfaceCreateItem, pipe_item);
RedSurfaceCreateItem *surface_create = static_cast<RedSurfaceCreateItem*>(pipe_item);
marshall_surface_create(this, m, &surface_create->surface_create);
break;
}
case RED_PIPE_ITEM_TYPE_DESTROY_SURFACE: {
RedSurfaceDestroyItem *surface_destroy = SPICE_UPCAST(RedSurfaceDestroyItem, pipe_item);
RedSurfaceDestroyItem *surface_destroy = static_cast<RedSurfaceDestroyItem*>(pipe_item);
marshall_surface_destroy(this, m, surface_destroy->surface_destroy.surface_id);
break;
}
case RED_PIPE_ITEM_TYPE_MONITORS_CONFIG: {
RedMonitorsConfigItem *monconf_item = SPICE_UPCAST(RedMonitorsConfigItem, pipe_item);
RedMonitorsConfigItem *monconf_item = static_cast<RedMonitorsConfigItem*>(pipe_item);
marshall_monitors_config(this, m, monconf_item->monitors_config);
break;
}
case RED_PIPE_ITEM_TYPE_STREAM_ACTIVATE_REPORT: {
RedStreamActivateReportItem *report_item =
SPICE_UPCAST(RedStreamActivateReportItem, pipe_item);
static_cast<RedStreamActivateReportItem*>(pipe_item);
marshall_stream_activate_report(this, m, report_item);
break;
}

View File

@ -70,25 +70,18 @@ DisplayChannelClient::~DisplayChannelClient()
g_clear_pointer(&priv->client_preferred_video_codecs, g_array_unref);
}
static RedSurfaceCreateItem *red_surface_create_item_new(RedChannel* channel,
uint32_t surface_id,
uint32_t width,
uint32_t height,
uint32_t format,
uint32_t flags)
RedSurfaceCreateItem::RedSurfaceCreateItem(uint32_t surface_id,
uint32_t width,
uint32_t height,
uint32_t format,
uint32_t flags):
RedPipeItem(RED_PIPE_ITEM_TYPE_CREATE_SURFACE)
{
RedSurfaceCreateItem *create;
create = g_new(RedSurfaceCreateItem, 1);
create->surface_create.surface_id = surface_id;
create->surface_create.width = width;
create->surface_create.height = height;
create->surface_create.flags = flags;
create->surface_create.format = format;
red_pipe_item_init(&create->base, RED_PIPE_ITEM_TYPE_CREATE_SURFACE);
return create;
surface_create.surface_id = surface_id;
surface_create.width = width;
surface_create.height = height;
surface_create.flags = flags;
surface_create.format = format;
}
bool dcc_drawable_is_in_pipe(DisplayChannelClient *dcc, Drawable *drawable)
@ -129,10 +122,10 @@ bool dcc_clear_surface_drawables_from_pipe(DisplayChannelClient *dcc, int surfac
l = l->next;
if (item->type == RED_PIPE_ITEM_TYPE_DRAW) {
dpi = SPICE_UPCAST(RedDrawablePipeItem, item);
dpi = static_cast<RedDrawablePipeItem*>(item);
drawable = dpi->drawable;
} else if (item->type == RED_PIPE_ITEM_TYPE_UPGRADE) {
drawable = SPICE_UPCAST(RedUpgradeItem, item)->drawable;
drawable = static_cast<RedUpgradeItem*>(item)->drawable;
} else {
continue;
}
@ -189,12 +182,16 @@ void dcc_create_surface(DisplayChannelClient *dcc, int surface_id)
return;
}
surface = &display->priv->surfaces[surface_id];
create = red_surface_create_item_new(display,
surface_id, surface->context.width,
surface->context.height,
surface->context.format, flags);
create = new RedSurfaceCreateItem(surface_id, surface->context.width,
surface->context.height,
surface->context.format, flags);
dcc->priv->surface_client_created[surface_id] = TRUE;
dcc->pipe_add(&create->base);
dcc->pipe_add(create);
}
RedImageItem::RedImageItem():
RedPipeItem(RED_PIPE_ITEM_TYPE_IMAGE)
{
}
// adding the pipe item after pos. If pos == NULL, adding to head.
@ -219,9 +216,7 @@ dcc_add_surface_area_image(DisplayChannelClient *dcc, int surface_id,
bpp = SPICE_SURFACE_FMT_DEPTH(surface->context.format) / 8;
stride = width * bpp;
item = (RedImageItem *)g_malloc(height * stride + sizeof(RedImageItem));
red_pipe_item_init(&item->base, RED_PIPE_ITEM_TYPE_IMAGE);
item = new (height * stride) RedImageItem();
item->surface_id = surface_id;
item->image_format =
@ -250,9 +245,9 @@ dcc_add_surface_area_image(DisplayChannelClient *dcc, int surface_id,
}
if (pipe_item_pos) {
dcc->pipe_add_after_pos(&item->base, pipe_item_pos);
dcc->pipe_add_after_pos(item, pipe_item_pos);
} else {
dcc->pipe_add(&item->base);
dcc->pipe_add(item);
}
}
@ -308,14 +303,15 @@ static void add_drawable_surface_images(DisplayChannelClient *dcc, Drawable *dra
dcc_push_surface_image(dcc, drawable->surface_id);
}
static void red_drawable_pipe_item_free(RedPipeItem *item)
RedDrawablePipeItem::RedDrawablePipeItem():
RedPipeItem(RED_PIPE_ITEM_TYPE_DRAW)
{
RedDrawablePipeItem *dpi = SPICE_UPCAST(RedDrawablePipeItem, item);
spice_assert(item->refcount == 0);
}
dpi->drawable->pipes = g_list_remove(dpi->drawable->pipes, dpi);
drawable_unref(dpi->drawable);
g_free(dpi);
RedDrawablePipeItem::~RedDrawablePipeItem()
{
drawable->pipes = g_list_remove(drawable->pipes, this);
drawable_unref(drawable);
}
static RedDrawablePipeItem *red_drawable_pipe_item_new(DisplayChannelClient *dcc,
@ -323,12 +319,10 @@ static RedDrawablePipeItem *red_drawable_pipe_item_new(DisplayChannelClient *dcc
{
RedDrawablePipeItem *dpi;
dpi = g_new0(RedDrawablePipeItem, 1);
dpi = new RedDrawablePipeItem;
dpi->drawable = drawable;
dpi->dcc = dcc;
drawable->pipes = g_list_prepend(drawable->pipes, dpi);
red_pipe_item_init_full(&dpi->base, RED_PIPE_ITEM_TYPE_DRAW,
red_drawable_pipe_item_free);
drawable->refs++;
return dpi;
}
@ -338,7 +332,7 @@ void dcc_prepend_drawable(DisplayChannelClient *dcc, Drawable *drawable)
RedDrawablePipeItem *dpi = red_drawable_pipe_item_new(dcc, drawable);
add_drawable_surface_images(dcc, drawable);
dcc->pipe_add(&dpi->base);
dcc->pipe_add(dpi);
}
void dcc_append_drawable(DisplayChannelClient *dcc, Drawable *drawable)
@ -346,7 +340,7 @@ void dcc_append_drawable(DisplayChannelClient *dcc, Drawable *drawable)
RedDrawablePipeItem *dpi = red_drawable_pipe_item_new(dcc, drawable);
add_drawable_surface_images(dcc, drawable);
dcc->pipe_add_tail(&dpi->base);
dcc->pipe_add_tail(dpi);
}
void dcc_add_drawable_after(DisplayChannelClient *dcc, Drawable *drawable, RedPipeItem *pos)
@ -354,7 +348,7 @@ void dcc_add_drawable_after(DisplayChannelClient *dcc, Drawable *drawable, RedPi
RedDrawablePipeItem *dpi = red_drawable_pipe_item_new(dcc, drawable);
add_drawable_surface_images(dcc, drawable);
dcc->pipe_add_after(&dpi->base, pos);
dcc->pipe_add_after(dpi, pos);
}
static void dcc_init_stream_agents(DisplayChannelClient *dcc)
@ -498,28 +492,18 @@ void dcc_video_stream_agent_clip(DisplayChannelClient* dcc, VideoStreamAgent *ag
{
VideoStreamClipItem *item = video_stream_clip_item_new(agent);
dcc->pipe_add(&item->base);
dcc->pipe_add(item);
}
static void red_monitors_config_item_free(RedPipeItem *pipe_item)
RedMonitorsConfigItem::~RedMonitorsConfigItem()
{
RedMonitorsConfigItem *item = SPICE_UPCAST(RedMonitorsConfigItem, pipe_item);
monitors_config_unref(item->monitors_config);
g_free(item);
monitors_config_unref(monitors_config);
}
static RedMonitorsConfigItem *red_monitors_config_item_new(RedChannel* channel,
MonitorsConfig *monitors_config)
RedMonitorsConfigItem::RedMonitorsConfigItem(MonitorsConfig *init_monitors_config):
RedPipeItem(RED_PIPE_ITEM_TYPE_MONITORS_CONFIG)
{
RedMonitorsConfigItem *mci;
mci = g_new(RedMonitorsConfigItem, 1);
mci->monitors_config = monitors_config_ref(monitors_config);
red_pipe_item_init_full(&mci->base, RED_PIPE_ITEM_TYPE_MONITORS_CONFIG,
red_monitors_config_item_free);
return mci;
monitors_config = monitors_config_ref(init_monitors_config);
}
void dcc_push_monitors_config(DisplayChannelClient *dcc)
@ -537,26 +521,18 @@ void dcc_push_monitors_config(DisplayChannelClient *dcc)
return;
}
mci = red_monitors_config_item_new(dcc->get_channel(),
monitors_config);
dcc->pipe_add(&mci->base);
mci = new RedMonitorsConfigItem(monitors_config);
dcc->pipe_add(mci);
}
static RedSurfaceDestroyItem *red_surface_destroy_item_new(uint32_t surface_id)
RedSurfaceDestroyItem::RedSurfaceDestroyItem(uint32_t surface_id):
RedPipeItem(RED_PIPE_ITEM_TYPE_DESTROY_SURFACE)
{
RedSurfaceDestroyItem *destroy;
destroy = g_new(RedSurfaceDestroyItem, 1);
destroy->surface_destroy.surface_id = surface_id;
red_pipe_item_init(&destroy->base, RED_PIPE_ITEM_TYPE_DESTROY_SURFACE);
return destroy;
surface_destroy.surface_id = surface_id;
}
RedPipeItem *dcc_gl_scanout_item_new(RedChannelClient *rcc, void *data, int num)
{
RedGlScanoutUnixItem *item;
/* FIXME: on !unix peer, start streaming with a video codec */
if (!red_stream_is_plain_unix(rcc->get_stream()) ||
!rcc->test_remote_cap(SPICE_DISPLAY_CAP_GL_SCANOUT)) {
@ -566,10 +542,7 @@ RedPipeItem *dcc_gl_scanout_item_new(RedChannelClient *rcc, void *data, int num)
return NULL;
}
item = g_new(RedGlScanoutUnixItem, 1);
red_pipe_item_init(&item->base, RED_PIPE_ITEM_TYPE_GL_SCANOUT);
return &item->base;
return new RedGlScanoutUnixItem(RED_PIPE_ITEM_TYPE_GL_SCANOUT);
}
XXX_CAST(RedChannelClient, DisplayChannelClient, DISPLAY_CHANNEL_CLIENT);
@ -589,11 +562,10 @@ RedPipeItem *dcc_gl_draw_item_new(RedChannelClient *rcc, void *data, int num)
}
dcc->priv->gl_draw_ongoing = TRUE;
item = g_new(RedGlDrawItem, 1);
item = new RedGlDrawItem(RED_PIPE_ITEM_TYPE_GL_DRAW);
item->draw = *draw;
red_pipe_item_init(&item->base, RED_PIPE_ITEM_TYPE_GL_DRAW);
return &item->base;
return item;
}
void dcc_destroy_surface(DisplayChannelClient *dcc, uint32_t surface_id)
@ -613,8 +585,8 @@ void dcc_destroy_surface(DisplayChannelClient *dcc, uint32_t surface_id)
}
dcc->priv->surface_client_created[surface_id] = FALSE;
destroy = red_surface_destroy_item_new(surface_id);
dcc->pipe_add(&destroy->base);
destroy = new RedSurfaceDestroyItem(surface_id);
dcc->pipe_add(destroy);
}
#define MIN_DIMENSION_TO_QUIC 3

View File

@ -96,22 +96,26 @@ typedef struct FreeList {
#define DCC_TO_DC(dcc) ((DisplayChannel*) dcc->get_channel())
typedef struct RedSurfaceCreateItem {
RedPipeItem base;
struct RedSurfaceCreateItem: public RedPipeItem {
RedSurfaceCreateItem(uint32_t surface_id,
uint32_t width,
uint32_t height,
uint32_t format,
uint32_t flags);
SpiceMsgSurfaceCreate surface_create;
} RedSurfaceCreateItem;
};
typedef struct RedGlScanoutUnixItem {
RedPipeItem base;
} RedGlScanoutUnixItem;
struct RedGlScanoutUnixItem: public RedPipeItem {
using RedPipeItem::RedPipeItem;
};
typedef struct RedGlDrawItem {
RedPipeItem base;
struct RedGlDrawItem: public RedPipeItem {
using RedPipeItem::RedPipeItem;
SpiceMsgDisplayGlDraw draw;
} RedGlDrawItem;
};
typedef struct RedImageItem {
RedPipeItem base;
struct RedImageItem final: public RedPipeItem {
RedImageItem();
SpicePoint pos;
int width;
int height;
@ -122,13 +126,14 @@ typedef struct RedImageItem {
uint32_t image_flags;
int can_lossy;
uint8_t data[0];
} RedImageItem;
};
typedef struct RedDrawablePipeItem {
RedPipeItem base;
struct RedDrawablePipeItem: public RedPipeItem {
RedDrawablePipeItem();
~RedDrawablePipeItem();
Drawable *drawable;
DisplayChannelClient *dcc;
} RedDrawablePipeItem;
};
DisplayChannelClient* dcc_new (DisplayChannel *display,
RedClient *client,

View File

@ -139,10 +139,11 @@ struct DisplayChannelPrivate
GLIST_FOREACH((_channel ? _channel->get_clients() : NULL), \
DisplayChannelClient, _data)
typedef struct RedMonitorsConfigItem {
RedPipeItem base;
struct RedMonitorsConfigItem: public RedPipeItem {
RedMonitorsConfigItem(MonitorsConfig *monitors_config);
~RedMonitorsConfigItem();
MonitorsConfig *monitors_config;
} RedMonitorsConfigItem;
};
enum {
RED_PIPE_ITEM_TYPE_DRAW = RED_PIPE_ITEM_TYPE_COMMON_LAST,
@ -181,10 +182,10 @@ uint32_t display_channel_generate_uid(DisplayChannel *display);
int display_channel_get_video_stream_id(DisplayChannel *display, VideoStream *stream);
VideoStream *display_channel_get_nth_video_stream(DisplayChannel *display, gint i);
typedef struct RedSurfaceDestroyItem {
RedPipeItem base;
struct RedSurfaceDestroyItem: public RedPipeItem {
RedSurfaceDestroyItem(uint32_t surface_id);
SpiceMsgSurfaceDestroy surface_destroy;
} RedSurfaceDestroyItem;
};
static inline int is_equal_path(SpicePath *path1, SpicePath *path2)
{

View File

@ -327,7 +327,7 @@ static void pipes_add_drawable_after(DisplayChannel *display,
dpi_pos_after = (RedDrawablePipeItem*) l->data;
num_other_linked++;
dcc_add_drawable_after(dpi_pos_after->dcc, drawable, &dpi_pos_after->base);
dcc_add_drawable_after(dpi_pos_after->dcc, drawable, dpi_pos_after);
}
if (num_other_linked == 0) {
@ -387,7 +387,7 @@ static void drawable_remove_from_pipes(Drawable *drawable)
RedChannelClient *rcc;
rcc = dpi->dcc;
rcc->pipe_remove_and_release(&dpi->base);
rcc->pipe_remove_and_release(dpi);
}
}

View File

@ -86,15 +86,15 @@ RedsState* spice_tablet_state_get_server(SpiceTabletState *st)
return st->reds;
}
typedef struct RedKeyModifiersPipeItem {
RedPipeItem base;
struct RedKeyModifiersPipeItem: public RedPipeItem {
RedKeyModifiersPipeItem(uint8_t modifiers);
uint8_t modifiers;
} RedKeyModifiersPipeItem;
};
typedef struct RedInputsInitPipeItem {
RedPipeItem base;
struct RedInputsInitPipeItem: public RedPipeItem {
RedInputsInitPipeItem(uint8_t modifiers);
uint8_t modifiers;
} RedInputsInitPipeItem;
};
#define KEY_MODIFIERS_TTL (MSEC_PER_SEC * 2)
@ -194,13 +194,10 @@ static uint8_t kbd_get_leds(SpiceKbdInstance *sin)
return sif->get_leds(sin);
}
static RedPipeItem *red_inputs_key_modifiers_item_new(uint8_t modifiers)
RedKeyModifiersPipeItem::RedKeyModifiersPipeItem(uint8_t init_modifiers):
RedPipeItem(RED_PIPE_ITEM_KEY_MODIFIERS),
modifiers(init_modifiers)
{
RedKeyModifiersPipeItem *item = g_new(RedKeyModifiersPipeItem, 1);
red_pipe_item_init(&item->base, RED_PIPE_ITEM_KEY_MODIFIERS);
item->modifiers = modifiers;
return &item->base;
}
void InputsChannelClient::send_item(RedPipeItem *base)
@ -214,7 +211,7 @@ void InputsChannelClient::send_item(RedPipeItem *base)
init_send_data(SPICE_MSG_INPUTS_KEY_MODIFIERS);
key_modifiers.modifiers =
SPICE_UPCAST(RedKeyModifiersPipeItem, base)->modifiers;
static_cast<RedKeyModifiersPipeItem*>(base)->modifiers;
spice_marshall_msg_inputs_key_modifiers(m, &key_modifiers);
break;
}
@ -224,7 +221,7 @@ void InputsChannelClient::send_item(RedPipeItem *base)
init_send_data(SPICE_MSG_INPUTS_INIT);
inputs_init.keyboard_modifiers =
SPICE_UPCAST(RedInputsInitPipeItem, base)->modifiers;
static_cast<RedInputsInitPipeItem*>(base)->modifiers;
spice_marshall_msg_inputs_init(m, &inputs_init);
break;
}
@ -432,14 +429,16 @@ void InputsChannel::release_keys()
}
}
RedInputsInitPipeItem::RedInputsInitPipeItem(uint8_t init_modifiers):
RedPipeItem(RED_PIPE_ITEM_INPUTS_INIT),
modifiers(init_modifiers)
{
}
void InputsChannelClient::pipe_add_init()
{
RedInputsInitPipeItem *item = g_new(RedInputsInitPipeItem, 1);
InputsChannel *inputs = get_channel();
red_pipe_item_init(&item->base, RED_PIPE_ITEM_INPUTS_INIT);
item->modifiers = kbd_get_leds(inputs->keyboard);
pipe_add_push(&item->base);
auto modifiers = kbd_get_leds(get_channel()->keyboard);
pipe_add_push(new RedInputsInitPipeItem(modifiers));
}
void InputsChannel::on_connect(RedClient *client, RedStream *stream, int migration,
@ -464,7 +463,7 @@ void InputsChannel::push_keyboard_modifiers()
if (!is_connected() || src_during_migrate) {
return;
}
pipes_add(red_inputs_key_modifiers_item_new(modifiers));
pipes_add(new RedKeyModifiersPipeItem(modifiers));
}
SPICE_GNUC_VISIBLE int spice_server_kbd_leds(SpiceKbdInstance *sin, int leds)

View File

@ -61,65 +61,67 @@ struct MainChannelClientPrivate {
uint8_t recv_buf[MAIN_CHANNEL_RECEIVE_BUF_SIZE];
};
typedef struct RedPingPipeItem {
RedPipeItem base;
struct RedPingPipeItem: public RedPipeItem {
using RedPipeItem::RedPipeItem;
int size;
} RedPingPipeItem;
};
typedef struct RedTokensPipeItem {
RedPipeItem base;
struct RedTokensPipeItem: public RedPipeItem {
using RedPipeItem::RedPipeItem;
int tokens;
} RedTokensPipeItem;
};
typedef struct RedAgentDataPipeItem {
RedPipeItem base;
struct RedAgentDataPipeItem: public RedPipeItem {
using RedPipeItem::RedPipeItem;
~RedAgentDataPipeItem();
uint8_t* data;
size_t len;
spice_marshaller_item_free_func free_data;
void *opaque;
} RedAgentDataPipeItem;
};
typedef struct RedInitPipeItem {
RedPipeItem base;
struct RedInitPipeItem: public RedPipeItem {
using RedPipeItem::RedPipeItem;
int connection_id;
int display_channels_hint;
int current_mouse_mode;
int is_client_mouse_allowed;
int multi_media_time;
int ram_hint;
} RedInitPipeItem;
};
typedef struct RedNamePipeItem {
RedPipeItem base;
struct RedNamePipeItem: public RedPipeItem {
using RedPipeItem::RedPipeItem;
SpiceMsgMainName msg;
} RedNamePipeItem;
};
typedef struct RedUuidPipeItem {
RedPipeItem base;
struct RedUuidPipeItem: public RedPipeItem {
using RedPipeItem::RedPipeItem;
SpiceMsgMainUuid msg;
} RedUuidPipeItem;
};
typedef struct RedNotifyPipeItem {
RedPipeItem base;
struct RedNotifyPipeItem: public RedPipeItem {
using RedPipeItem::RedPipeItem;
~RedNotifyPipeItem();
char *msg;
} RedNotifyPipeItem;
};
typedef struct RedMouseModePipeItem {
RedPipeItem base;
struct RedMouseModePipeItem: public RedPipeItem {
using RedPipeItem::RedPipeItem;
SpiceMouseMode current_mode;
int is_client_mouse_allowed;
} RedMouseModePipeItem;
};
typedef struct RedMultiMediaTimePipeItem {
RedPipeItem base;
struct RedMultiMediaTimePipeItem: public RedPipeItem {
using RedPipeItem::RedPipeItem;
uint32_t time;
} RedMultiMediaTimePipeItem;
};
typedef struct RedRegisteredChannelPipeItem {
RedPipeItem base;
struct RedRegisteredChannelPipeItem: public RedPipeItem {
using RedPipeItem::RedPipeItem;
uint32_t channel_type;
uint32_t channel_id;
} RedRegisteredChannelPipeItem;
};
#define ZERO_BUF_SIZE 4096
@ -157,21 +159,17 @@ void MainChannelClient::on_disconnect()
static void main_channel_client_push_ping(MainChannelClient *mcc, int size);
static void main_notify_item_free(RedPipeItem *base)
RedNotifyPipeItem::~RedNotifyPipeItem()
{
RedNotifyPipeItem *data = SPICE_UPCAST(RedNotifyPipeItem, base);
g_free(data->msg);
g_free(data);
g_free(msg);
}
static RedPipeItem *main_notify_item_new(const char *msg, int num)
{
RedNotifyPipeItem *item = g_new(RedNotifyPipeItem, 1);
RedNotifyPipeItem *item = new RedNotifyPipeItem(RED_PIPE_ITEM_TYPE_MAIN_NOTIFY);
red_pipe_item_init_full(&item->base, RED_PIPE_ITEM_TYPE_MAIN_NOTIFY,
main_notify_item_free);
item->msg = g_strdup(msg);
return &item->base;
return item;
}
void MainChannelClient::start_net_test(int test_rate)
@ -195,11 +193,10 @@ void MainChannelClient::start_net_test(int test_rate)
static RedPipeItem *red_ping_item_new(int size)
{
RedPingPipeItem *item = g_new(RedPingPipeItem, 1);
RedPingPipeItem *item = new RedPingPipeItem(RED_PIPE_ITEM_TYPE_MAIN_PING);
red_pipe_item_init(&item->base, RED_PIPE_ITEM_TYPE_MAIN_PING);
item->size = size;
return &item->base;
return item;
}
static void main_channel_client_push_ping(MainChannelClient *mcc, int size)
@ -210,11 +207,10 @@ static void main_channel_client_push_ping(MainChannelClient *mcc, int size)
static RedPipeItem *main_agent_tokens_item_new(uint32_t num_tokens)
{
RedTokensPipeItem *item = g_new(RedTokensPipeItem, 1);
RedTokensPipeItem *item = new RedTokensPipeItem(RED_PIPE_ITEM_TYPE_MAIN_AGENT_TOKEN);
red_pipe_item_init(&item->base, RED_PIPE_ITEM_TYPE_MAIN_AGENT_TOKEN);
item->tokens = num_tokens;
return &item->base;
return item;
}
@ -225,26 +221,22 @@ void MainChannelClient::push_agent_tokens(uint32_t num_tokens)
pipe_add_push(item);
}
static void main_agent_data_item_free(RedPipeItem *base)
RedAgentDataPipeItem::~RedAgentDataPipeItem()
{
RedAgentDataPipeItem *item = SPICE_UPCAST(RedAgentDataPipeItem, base);
item->free_data(item->data, item->opaque);
g_free(item);
free_data(data, opaque);
}
static RedPipeItem *main_agent_data_item_new(uint8_t* data, size_t len,
spice_marshaller_item_free_func free_data,
void *opaque)
{
RedAgentDataPipeItem *item = g_new(RedAgentDataPipeItem, 1);
RedAgentDataPipeItem *item = new RedAgentDataPipeItem(RED_PIPE_ITEM_TYPE_MAIN_AGENT_DATA);
red_pipe_item_init_full(&item->base, RED_PIPE_ITEM_TYPE_MAIN_AGENT_DATA,
main_agent_data_item_free);
item->data = data;
item->len = len;
item->free_data = free_data;
item->opaque = opaque;
return &item->base;
return item;
}
void MainChannelClient::push_agent_data(uint8_t *data, size_t len,
@ -264,16 +256,15 @@ static RedPipeItem *main_init_item_new(int connection_id,
int multi_media_time,
int ram_hint)
{
RedInitPipeItem *item = g_new(RedInitPipeItem, 1);
RedInitPipeItem *item = new RedInitPipeItem(RED_PIPE_ITEM_TYPE_MAIN_INIT);
red_pipe_item_init(&item->base, RED_PIPE_ITEM_TYPE_MAIN_INIT);
item->connection_id = connection_id;
item->display_channels_hint = display_channels_hint;
item->current_mouse_mode = current_mouse_mode;
item->is_client_mouse_allowed = is_client_mouse_allowed;
item->multi_media_time = multi_media_time;
item->ram_hint = ram_hint;
return &item->base;
return item;
}
void MainChannelClient::push_init(int display_channels_hint,
@ -291,13 +282,11 @@ void MainChannelClient::push_init(int display_channels_hint,
static RedPipeItem *main_name_item_new(const char *name)
{
RedNamePipeItem *item = (RedNamePipeItem*) g_malloc(sizeof(RedNamePipeItem) + strlen(name) + 1);
red_pipe_item_init(&item->base, RED_PIPE_ITEM_TYPE_MAIN_NAME);
RedNamePipeItem *item = new (strlen(name) + 1) RedNamePipeItem(RED_PIPE_ITEM_TYPE_MAIN_NAME);
item->msg.name_len = strlen(name) + 1;
memcpy(&item->msg.name, name, item->msg.name_len);
return &item->base;
return item;
}
void MainChannelClient::push_name(const char *name)
@ -313,12 +302,11 @@ void MainChannelClient::push_name(const char *name)
static RedPipeItem *main_uuid_item_new(const uint8_t uuid[16])
{
RedUuidPipeItem *item = g_new(RedUuidPipeItem, 1);
RedUuidPipeItem *item = new RedUuidPipeItem(RED_PIPE_ITEM_TYPE_MAIN_UUID);
red_pipe_item_init(&item->base, RED_PIPE_ITEM_TYPE_MAIN_UUID);
memcpy(item->msg.uuid, uuid, sizeof(item->msg.uuid));
return &item->base;
return item;
}
void MainChannelClient::push_uuid(const uint8_t uuid[16])
@ -340,34 +328,31 @@ void MainChannelClient::push_notify(const char *msg)
RedPipeItem *main_mouse_mode_item_new(SpiceMouseMode current_mode, int is_client_mouse_allowed)
{
RedMouseModePipeItem *item = g_new(RedMouseModePipeItem, 1);
RedMouseModePipeItem *item = new RedMouseModePipeItem(RED_PIPE_ITEM_TYPE_MAIN_MOUSE_MODE);
red_pipe_item_init(&item->base, RED_PIPE_ITEM_TYPE_MAIN_MOUSE_MODE);
item->current_mode = current_mode;
item->is_client_mouse_allowed = is_client_mouse_allowed;
return &item->base;
return item;
}
RedPipeItem *main_multi_media_time_item_new(uint32_t mm_time)
{
RedMultiMediaTimePipeItem *item;
item = g_new(RedMultiMediaTimePipeItem, 1);
red_pipe_item_init(&item->base, RED_PIPE_ITEM_TYPE_MAIN_MULTI_MEDIA_TIME);
item = new RedMultiMediaTimePipeItem(RED_PIPE_ITEM_TYPE_MAIN_MULTI_MEDIA_TIME);
item->time = mm_time;
return &item->base;
return item;
}
RedPipeItem *registered_channel_item_new(RedChannel *channel)
{
RedRegisteredChannelPipeItem *item;
item = g_new0(RedRegisteredChannelPipeItem, 1);
red_pipe_item_init(&item->base, RED_PIPE_ITEM_TYPE_MAIN_REGISTERED_CHANNEL);
item = new RedRegisteredChannelPipeItem(RED_PIPE_ITEM_TYPE_MAIN_REGISTERED_CHANNEL);
item->channel_type = channel->type();
item->channel_id = channel->id();
return &item->base;
return item;
}
void MainChannelClient::handle_migrate_connected(int success, int seamless)
@ -684,7 +669,7 @@ static void main_channel_marshall_agent_data(RedChannelClient *rcc,
{
rcc->init_send_data(SPICE_MSG_MAIN_AGENT_DATA);
/* since pipe item owns the data, keep it alive until it's sent */
item->base.add_to_marshaller(m, item->data, item->len);
item->add_to_marshaller(m, item->data, item->len);
}
static void main_channel_marshall_migrate_data_item(RedChannelClient *rcc,
@ -863,22 +848,22 @@ void MainChannelClient::send_item(RedPipeItem *base)
break;
case RED_PIPE_ITEM_TYPE_MAIN_PING:
main_channel_marshall_ping(this, m,
SPICE_UPCAST(RedPingPipeItem, base));
static_cast<RedPingPipeItem*>(base));
break;
case RED_PIPE_ITEM_TYPE_MAIN_MOUSE_MODE:
main_channel_marshall_mouse_mode(this, m,
SPICE_UPCAST(RedMouseModePipeItem, base));
static_cast<RedMouseModePipeItem*>(base));
break;
case RED_PIPE_ITEM_TYPE_MAIN_AGENT_DISCONNECTED:
main_channel_marshall_agent_disconnected(this, m, base);
break;
case RED_PIPE_ITEM_TYPE_MAIN_AGENT_TOKEN:
main_channel_marshall_tokens(this, m,
SPICE_UPCAST(RedTokensPipeItem, base));
static_cast<RedTokensPipeItem*>(base));
break;
case RED_PIPE_ITEM_TYPE_MAIN_AGENT_DATA:
main_channel_marshall_agent_data(this, m,
SPICE_UPCAST(RedAgentDataPipeItem, base));
static_cast<RedAgentDataPipeItem*>(base));
break;
case RED_PIPE_ITEM_TYPE_MAIN_MIGRATE_DATA:
main_channel_marshall_migrate_data_item(this, m, base);
@ -886,11 +871,11 @@ void MainChannelClient::send_item(RedPipeItem *base)
case RED_PIPE_ITEM_TYPE_MAIN_INIT:
priv->init_sent = TRUE;
main_channel_marshall_init(this, m,
SPICE_UPCAST(RedInitPipeItem, base));
static_cast<RedInitPipeItem*>(base));
break;
case RED_PIPE_ITEM_TYPE_MAIN_NOTIFY:
main_channel_marshall_notify(this, m,
SPICE_UPCAST(RedNotifyPipeItem, base));
static_cast<RedNotifyPipeItem*>(base));
break;
case RED_PIPE_ITEM_TYPE_MAIN_MIGRATE_BEGIN:
main_channel_marshall_migrate_begin(m, this, base);
@ -900,18 +885,18 @@ void MainChannelClient::send_item(RedPipeItem *base)
break;
case RED_PIPE_ITEM_TYPE_MAIN_MULTI_MEDIA_TIME:
main_channel_marshall_multi_media_time(this, m,
SPICE_UPCAST(RedMultiMediaTimePipeItem, base));
static_cast<RedMultiMediaTimePipeItem*>(base));
break;
case RED_PIPE_ITEM_TYPE_MAIN_MIGRATE_SWITCH_HOST:
main_channel_marshall_migrate_switch(m, this, base);
break;
case RED_PIPE_ITEM_TYPE_MAIN_NAME:
init_send_data(SPICE_MSG_MAIN_NAME);
spice_marshall_msg_main_name(m, &SPICE_UPCAST(RedNamePipeItem, base)->msg);
spice_marshall_msg_main_name(m, &static_cast<RedNamePipeItem*>(base)->msg);
break;
case RED_PIPE_ITEM_TYPE_MAIN_UUID:
init_send_data(SPICE_MSG_MAIN_UUID);
spice_marshall_msg_main_uuid(m, &SPICE_UPCAST(RedUuidPipeItem, base)->msg);
spice_marshall_msg_main_uuid(m, &static_cast<RedUuidPipeItem*>(base)->msg);
break;
case RED_PIPE_ITEM_TYPE_MAIN_AGENT_CONNECTED_TOKENS:
main_channel_marshall_agent_connected(m, this, base);
@ -925,7 +910,7 @@ void MainChannelClient::send_item(RedPipeItem *base)
return;
}
main_channel_marshall_registered_channel(this, m,
SPICE_UPCAST(RedRegisteredChannelPipeItem, base));
static_cast<RedRegisteredChannelPipeItem*>(base));
break;
default:
break;

View File

@ -239,15 +239,15 @@ static const SpiceDataHeaderOpaque mini_header_wrapper = {NULL, sizeof(SpiceMini
#define PING_TEST_LONG_TIMEOUT_MS (MSEC_PER_SEC * 60 * 5)
#define PING_TEST_IDLE_NET_TIMEOUT_MS (MSEC_PER_SEC / 10)
typedef struct RedEmptyMsgPipeItem {
RedPipeItem base;
struct RedEmptyMsgPipeItem: public RedPipeItem {
using RedPipeItem::RedPipeItem;
int msg;
} RedEmptyMsgPipeItem;
};
typedef struct MarkerPipeItem {
RedPipeItem base;
struct MarkerPipeItem: public RedPipeItem {
using RedPipeItem::RedPipeItem;
bool item_sent;
} MarkerPipeItem;
};
void RedChannelClientPrivate::start_ping_timer(uint32_t timeout)
{
@ -488,7 +488,7 @@ void RedChannelClient::send_ping()
void RedChannelClient::send_empty_msg(RedPipeItem *base)
{
RedEmptyMsgPipeItem *msg_pipe_item = SPICE_UPCAST(RedEmptyMsgPipeItem, base);
RedEmptyMsgPipeItem *msg_pipe_item = static_cast<RedEmptyMsgPipeItem*>(base);
init_send_data(msg_pipe_item->msg);
begin_send_message();
@ -512,7 +512,7 @@ void RedChannelClient::send_any_item(RedPipeItem *item)
send_ping();
break;
case RED_PIPE_ITEM_TYPE_MARKER:
SPICE_UPCAST(MarkerPipeItem, item)->item_sent = true;
static_cast<MarkerPipeItem*>(item)->item_sent = true;
break;
default:
send_item(item);
@ -1428,19 +1428,17 @@ void RedChannelClient::pipe_add_tail(RedPipeItem *item)
void RedChannelClient::pipe_add_type(int pipe_item_type)
{
RedPipeItem *item = g_new(RedPipeItem, 1);
RedPipeItem *item = new RedPipeItem(pipe_item_type);
red_pipe_item_init(item, pipe_item_type);
pipe_add(item);
}
RedPipeItem *RedChannelClient::new_empty_msg(int msg_type)
{
RedEmptyMsgPipeItem *item = g_new(RedEmptyMsgPipeItem, 1);
RedEmptyMsgPipeItem *item = new RedEmptyMsgPipeItem(RED_PIPE_ITEM_TYPE_EMPTY_MSG);
red_pipe_item_init(&item->base, RED_PIPE_ITEM_TYPE_EMPTY_MSG);
item->msg = msg_type;
return &item->base;
return item;
}
void RedChannelClient::pipe_add_empty_msg(int msg_type)
@ -1578,12 +1576,11 @@ bool RedChannelClient::wait_pipe_item_sent(GList *item_pos, int64_t timeout)
end_time = UINT64_MAX;
}
MarkerPipeItem *mark_item = g_new0(MarkerPipeItem, 1);
MarkerPipeItem *mark_item = new MarkerPipeItem(RED_PIPE_ITEM_TYPE_MARKER);
red_pipe_item_init(&mark_item->base, RED_PIPE_ITEM_TYPE_MARKER);
mark_item->item_sent = false;
red_pipe_item_ref(&mark_item->base);
pipe_add_before_pos(&mark_item->base, item_pos);
red_pipe_item_ref(mark_item);
pipe_add_before_pos(mark_item, item_pos);
for (;;) {
receive();
@ -1596,7 +1593,7 @@ bool RedChannelClient::wait_pipe_item_sent(GList *item_pos, int64_t timeout)
}
item_sent = mark_item->item_sent;
red_pipe_item_unref(&mark_item->base);
red_pipe_item_unref(mark_item);
if (!item_sent) {
// still on the queue

View File

@ -280,9 +280,7 @@ void RedChannel::pipes_add(RedPipeItem *item)
void RedChannel::pipes_add_type(int pipe_item_type)
{
RedPipeItem *item = g_new(RedPipeItem, 1);
red_pipe_item_init(item, pipe_item_type);
RedPipeItem *item = new RedPipeItem(pipe_item_type);
pipes_add(item);
}

View File

@ -20,31 +20,25 @@
#include "red-channel.h"
#include "red-pipe-item.h"
RedPipeItem::RedPipeItem(int init_type):
type(init_type)
{
// compatibility with no shared_ptr reference counting
shared_ptr_add_ref(this);
}
RedPipeItem *red_pipe_item_ref(RedPipeItem *item)
{
g_return_val_if_fail(item->refcount > 0, NULL);
g_atomic_int_inc(&item->refcount);
// this call should be replaced by shared_ptr instead
shared_ptr_add_ref(item);
return item;
}
void red_pipe_item_unref(RedPipeItem *item)
{
g_return_if_fail(item->refcount > 0);
if (g_atomic_int_dec_and_test(&item->refcount)) {
item->free_func(item);
}
}
void red_pipe_item_init_full(RedPipeItem *item,
gint type,
red_pipe_item_free_t *free_func)
{
item->type = type;
item->refcount = 1;
item->free_func = free_func ? free_func : (red_pipe_item_free_t *)g_free;
// this call should be replaced by shared_ptr instead
shared_ptr_unref(item);
}
static void marshaller_unref_pipe_item(uint8_t *, void *opaque)

View File

@ -16,40 +16,57 @@
License along with this library; if not, see <http://www.gnu.org/licenses/>.
*/
/**
* @file red-pipe-item.h
* Generic declaration for objects contained in RedChannelClient pipe.
*/
#ifndef RED_PIPE_ITEM_H_
#define RED_PIPE_ITEM_H_
#include <stddef.h>
#include <inttypes.h>
#include "common/marshaller.h"
#include "red-common.h"
#include "utils.hpp"
#include "push-visibility.h"
typedef struct RedPipeItem RedPipeItem;
/**
* Base class for objects contained in RedChannelClient pipe
*/
struct RedPipeItem: public red::shared_ptr_counted
{
SPICE_CXX_GLIB_ALLOCATOR
void *operator new(size_t len, void *p)
{
return p;
}
typedef void red_pipe_item_free_t(RedPipeItem *item);
/**
* Allows to allocate a pipe item with additional space at the end.
*
* Used with structures like
* @code{.cpp}
* struct NameItem: public RedPipeItem {
* ...
* char name[];
* }
* ...
* auto name_item = red::shared_ptr<NameItem>(new (6) NameItem(...));
* strcpy(name_item->name, "hello");
* @endcode
*/
void *operator new(size_t size, size_t additional)
{
return g_malloc(size + additional);
}
struct RedPipeItem {
int type;
RedPipeItem(int type);
const int type;
void add_to_marshaller(SpiceMarshaller *m, uint8_t *data, size_t size);
/* private */
int refcount;
red_pipe_item_free_t *free_func;
};
void red_pipe_item_init_full(RedPipeItem *item, int type, red_pipe_item_free_t free_func);
RedPipeItem *red_pipe_item_ref(RedPipeItem *item);
void red_pipe_item_unref(RedPipeItem *item);
static inline void red_pipe_item_init(RedPipeItem *item, int type)
{
red_pipe_item_init_full(item, type, NULL);
}
#include "pop-visibility.h"
#endif /* RED_PIPE_ITEM_H_ */

View File

@ -153,13 +153,15 @@ struct ChannelSecurityOptions {
ChannelSecurityOptions *next;
};
typedef struct RedVDIReadBuf {
RedPipeItem base;
struct RedVDIReadBuf final: public RedPipeItem {
using RedPipeItem::RedPipeItem;
~RedVDIReadBuf();
RedCharDeviceVDIPort *dev;
int len;
uint8_t data[SPICE_AGENT_MAX_DATA_SIZE];
} RedVDIReadBuf;
};
typedef enum {
VDI_PORT_READ_STATE_READ_HEADER,
@ -238,7 +240,6 @@ static uint32_t reds_qxl_ram_size(RedsState *reds);
static int calc_compression_level(RedsState *reds);
static RedVDIReadBuf *vdi_port_get_read_buf(RedCharDeviceVDIPort *dev);
static red_pipe_item_free_t vdi_port_read_buf_free;
static ChannelSecurityOptions *reds_find_channel_security(RedsState *reds, int id)
{
@ -405,7 +406,7 @@ static void reds_reset_vdp(RedsState *reds)
dev->priv->receive_len = sizeof(dev->priv->vdi_chunk_header);
dev->priv->message_receive_len = 0;
if (dev->priv->current_read_buf) {
red_pipe_item_unref(&dev->priv->current_read_buf->base);
red_pipe_item_unref(dev->priv->current_read_buf);
dev->priv->current_read_buf = NULL;
}
/* Reset read filter to start with clean state when the agent reconnects */
@ -658,7 +659,7 @@ static void reds_agent_remove(RedsState *reds)
static void vdi_port_read_buf_release(uint8_t *data, void *opaque)
{
RedVDIReadBuf *read_buf = (RedVDIReadBuf *)opaque;
red_pipe_item_unref(&read_buf->base);
red_pipe_item_unref(read_buf);
}
/*
@ -681,15 +682,25 @@ static AgentMsgFilterResult vdi_port_read_buf_process(RedCharDeviceVDIPort *dev,
}
}
RedVDIReadBuf::~RedVDIReadBuf()
{
dev->priv->num_read_buf--;
/* read_one_msg_from_vdi_port may have never completed because we
reached buffer limit. So we call it again so it can complete its work if
necessary. Note that since we can be called from red_char_device_wakeup
this can cause recursion, but we have protection for that */
if (dev->priv->agent_attached) {
dev->wakeup();
}
}
static RedVDIReadBuf *vdi_read_buf_new(RedCharDeviceVDIPort *dev)
{
RedVDIReadBuf *buf = g_new(RedVDIReadBuf, 1);
/* Bogus pipe item type, we only need the RingItem and refcounting
* from the base class and are not going to use the type
*/
red_pipe_item_init_full(&buf->base, -1,
vdi_port_read_buf_free);
RedVDIReadBuf *buf = new RedVDIReadBuf(-1);
buf->dev = dev;
buf->len = 0;
return buf;
@ -705,23 +716,6 @@ static RedVDIReadBuf *vdi_port_get_read_buf(RedCharDeviceVDIPort *dev)
return vdi_read_buf_new(dev);
}
static void vdi_port_read_buf_free(RedPipeItem *base)
{
RedVDIReadBuf *buf = SPICE_UPCAST(RedVDIReadBuf, base);
g_warn_if_fail(buf->base.refcount == 0);
buf->dev->priv->num_read_buf--;
/* read_one_msg_from_vdi_port may have never completed because we
reached buffer limit. So we call it again so it can complete its work if
necessary. Note that since we can be called from red_char_device_wakeup
this can cause recursion, but we have protection for that */
if (buf->dev->priv->agent_attached) {
buf->dev->wakeup();
}
g_free(buf);
}
/* certain agent capabilities can be overridden and disabled in the server. In these cases, unset
* these capabilities before sending them on to the client */
static void reds_adjust_agent_capabilities(RedsState *reds, VDAgentMessage *message)
@ -807,14 +801,14 @@ RedCharDeviceVDIPort::read_one_msg_from_device()
switch (vdi_port_read_buf_process(this, dispatch_buf)) {
case AGENT_MSG_FILTER_OK:
reds_adjust_agent_capabilities(reds, (VDAgentMessage *) dispatch_buf->data);
return &dispatch_buf->base;
return dispatch_buf;
case AGENT_MSG_FILTER_PROTO_ERROR:
reds_agent_remove(reds);
/* fall through */
case AGENT_MSG_FILTER_MONITORS_CONFIG:
/* fall through */
case AGENT_MSG_FILTER_DISCARD:
red_pipe_item_unref(&dispatch_buf->base);
red_pipe_item_unref(dispatch_buf);
}
}
} /* END switch */
@ -911,7 +905,7 @@ void reds_send_device_display_info(RedsState *reds)
void RedCharDeviceVDIPort::send_msg_to_client(RedPipeItem *msg, RedCharDeviceClientOpaque *opaque)
{
RedClient *client = (RedClient *) opaque;
RedVDIReadBuf *agent_data_buf = (RedVDIReadBuf *)msg;
RedVDIReadBuf *agent_data_buf = static_cast<RedVDIReadBuf*>(msg);
red_pipe_item_ref(msg);
client->get_main()->push_agent_data(agent_data_buf->data,
@ -1283,7 +1277,7 @@ void reds_on_main_channel_migrate(RedsState *reds, MainChannelClient *mcc)
case AGENT_MSG_FILTER_MONITORS_CONFIG:
/* fall through */
case AGENT_MSG_FILTER_DISCARD:
red_pipe_item_unref(&read_buf->base);
red_pipe_item_unref(read_buf);
}
spice_assert(agent_dev->priv->receive_len);
@ -4472,7 +4466,7 @@ RedCharDeviceVDIPort::~RedCharDeviceVDIPort()
/* make sure we have no other references to RedVDIReadBuf buffers */
reset();
if (priv->current_read_buf) {
red_pipe_item_unref(&priv->current_read_buf->base);
red_pipe_item_unref(priv->current_read_buf);
priv->current_read_buf = NULL;
}
g_free(priv->mig_data);

View File

@ -32,11 +32,11 @@ struct SmartCardChannelClientPrivate
bool msg_in_write_buf = false;
};
typedef struct RedErrorItem {
RedPipeItem base;
struct RedErrorItem: public RedPipeItem {
using RedPipeItem::RedPipeItem;
VSCMsgHeader vheader;
VSCMsgError error;
} RedErrorItem;
};
SmartCardChannelClient::SmartCardChannelClient(RedChannel *channel,
RedClient *client,
@ -129,7 +129,7 @@ void smartcard_channel_client_send_data(RedChannelClient *rcc,
void smartcard_channel_client_send_error(RedChannelClient *rcc, SpiceMarshaller *m, RedPipeItem *item)
{
RedErrorItem* error_item = SPICE_UPCAST(RedErrorItem, item);
RedErrorItem* error_item = static_cast<RedErrorItem*>(item);
smartcard_channel_client_send_data(rcc, m, item, &error_item->vheader);
}
@ -138,15 +138,13 @@ static void smartcard_channel_client_push_error(RedChannelClient *rcc,
uint32_t reader_id,
VSCErrorCode error)
{
RedErrorItem *error_item = g_new0(RedErrorItem, 1);
red_pipe_item_init(&error_item->base, RED_PIPE_ITEM_TYPE_ERROR);
RedErrorItem *error_item = new RedErrorItem(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);
error_item->error.code = error;
rcc->pipe_add_push(&error_item->base);
rcc->pipe_add_push(error_item);
}
static void smartcard_channel_client_add_reader(SmartCardChannelClient *scc)

View File

@ -67,11 +67,11 @@ struct RedCharDeviceSmartcardPrivate {
int reader_added; // has reader_add been sent to the device
};
typedef struct RedMsgItem {
RedPipeItem base;
struct RedMsgItem: public RedPipeItem {
using RedPipeItem::RedPipeItem;
~RedMsgItem();
VSCMsgHeader* vheader;
} RedMsgItem;
};
static RedMsgItem *smartcard_new_vsc_msg_item(unsigned int reader_id, const VSCMsgHeader *vheader);
@ -138,9 +138,9 @@ RedCharDeviceSmartcard::read_one_msg_from_device()
dev->priv->buf_used = remaining;
if (msg_to_client) {
if (dev->priv->scc) {
dev->priv->scc->pipe_add_push(&msg_to_client->base);
dev->priv->scc->pipe_add_push(msg_to_client);
} else {
red_pipe_item_unref(&msg_to_client->base);
red_pipe_item_unref(msg_to_client);
}
}
}
@ -338,7 +338,7 @@ SmartCardChannelClient* smartcard_char_device_get_client(RedCharDeviceSmartcard
static void smartcard_channel_send_msg(RedChannelClient *rcc,
SpiceMarshaller *m, RedPipeItem *item)
{
RedMsgItem* msg_item = SPICE_UPCAST(RedMsgItem, item);
RedMsgItem* msg_item = static_cast<RedMsgItem*>(item);
smartcard_channel_client_send_data(rcc, m, item, msg_item->vheader);
}
@ -390,19 +390,15 @@ void SmartCardChannelClient::send_item(RedPipeItem *item)
begin_send_message();
}
static void smartcard_free_vsc_msg_item(RedPipeItem *base)
RedMsgItem::~RedMsgItem()
{
RedMsgItem *item = SPICE_UPCAST(RedMsgItem, base);
g_free(item->vheader);
g_free(item);
g_free(vheader);
}
static RedMsgItem *smartcard_new_vsc_msg_item(unsigned int reader_id, const VSCMsgHeader *vheader)
{
RedMsgItem *msg_item = g_new0(RedMsgItem, 1);
RedMsgItem *msg_item = new RedMsgItem(RED_PIPE_ITEM_TYPE_SMARTCARD_DATA);
red_pipe_item_init_full(&msg_item->base, RED_PIPE_ITEM_TYPE_SMARTCARD_DATA,
smartcard_free_vsc_msg_item);
msg_item->vheader = (VSCMsgHeader*) g_memdup(vheader, sizeof(*vheader) + vheader->length);
/* We patch the reader_id, since the device only knows about itself, and
* we know about the sum of readers. */

View File

@ -74,11 +74,17 @@ struct RecordChannelClient;
struct AudioFrame;
struct AudioFrameContainer;
struct PersistentPipeItem: public RedPipeItem
/* This pipe item is never deleted and added to the queue when messages
* have to be sent.
* This is used to have a simple item in RedChannelClient queue but to send
* multiple messages in a row if possible.
* During realtime sound transmission you usually don't want to queue too
* much data or having retransmission preferring instead loosing some
* samples.
*/
struct PersistentPipeItem final: public RedPipeItem
{
PersistentPipeItem();
private:
static void item_free(RedPipeItem *item);
};
/* Connects an audio client to a Spice client */
@ -610,21 +616,8 @@ static bool playback_send_mode(PlaybackChannelClient *playback_client)
return true;
}
PersistentPipeItem::PersistentPipeItem()
{
red_pipe_item_init_full(this, RED_PIPE_ITEM_PERSISTENT, item_free);
}
/* This function is called when the "persistent" item is removed from the
* queue. Note that there is not free call as the item is allocated into
* SndChannelClient.
* This is used to have a simple item in RedChannelClient queue but to send
* multiple messages in a row if possible.
* During realtime sound transmission you usually don't want to queue too
* much data or having retransmission preferring instead loosing some
* samples.
*/
void PersistentPipeItem::item_free(RedPipeItem *item)
PersistentPipeItem::PersistentPipeItem():
RedPipeItem(RED_PIPE_ITEM_PERSISTENT)
{
}

View File

@ -45,15 +45,15 @@
struct RedVmcChannel;
class VmcChannelClient;
typedef struct RedVmcPipeItem {
RedPipeItem base;
struct RedVmcPipeItem: public RedPipeItem {
using RedPipeItem::RedPipeItem;
SpiceDataCompressionType type;
uint32_t uncompressed_data_size;
/* writes which don't fit this will get split, this is not a problem */
uint8_t buf[BUF_SIZE];
uint32_t buf_used;
} RedVmcPipeItem;
};
struct RedCharDeviceSpiceVmc: public RedCharDevice
{
@ -158,7 +158,7 @@ RedVmcChannel::~RedVmcChannel()
{
RedCharDevice::write_buffer_release(chardev, &recv_from_client_buf);
if (pipe_item) {
red_pipe_item_unref(&pipe_item->base);
red_pipe_item_unref(pipe_item);
}
}
@ -183,16 +183,19 @@ static red::shared_ptr<RedVmcChannel> red_vmc_channel_new(RedsState *reds, uint8
return red::make_shared<RedVmcChannel>(reds, channel_type, id);
}
typedef struct RedPortInitPipeItem {
RedPipeItem base;
struct RedPortInitPipeItem: public RedPipeItem {
using RedPipeItem::RedPipeItem;
~RedPortInitPipeItem();
char* name;
uint8_t opened;
} RedPortInitPipeItem;
};
struct RedPortEventPipeItem: public RedPipeItem {
using RedPipeItem::RedPipeItem;
typedef struct RedPortEventPipeItem {
RedPipeItem base;
uint8_t event;
} RedPortEventPipeItem;
};
enum {
RED_PIPE_ITEM_TYPE_SPICEVMC_DATA = RED_PIPE_ITEM_TYPE_CHANNEL_BASE,
@ -225,8 +228,7 @@ static RedVmcPipeItem* try_compress_lz4(RedVmcChannel *channel, int n, RedVmcPip
/* Client doesn't have compression cap - data will not be compressed */
return NULL;
}
msg_item_compressed = g_new0(RedVmcPipeItem, 1);
red_pipe_item_init(&msg_item_compressed->base, RED_PIPE_ITEM_TYPE_SPICEVMC_DATA);
msg_item_compressed = new RedVmcPipeItem(RED_PIPE_ITEM_TYPE_SPICEVMC_DATA);
compressed_data_count = LZ4_compress_default((char*)&msg_item->buf,
(char*)&msg_item_compressed->buf,
n,
@ -258,9 +260,8 @@ RedPipeItem* RedCharDeviceSpiceVmc::read_one_msg_from_device()
}
if (!channel->pipe_item) {
msg_item = g_new0(RedVmcPipeItem, 1);
msg_item = new RedVmcPipeItem(RED_PIPE_ITEM_TYPE_SPICEVMC_DATA);
msg_item->type = SPICE_DATA_COMPRESSION_TYPE_NONE;
red_pipe_item_init(&msg_item->base, RED_PIPE_ITEM_TYPE_SPICEVMC_DATA);
} else {
spice_assert(channel->pipe_item->buf_used == 0);
msg_item = channel->pipe_item;
@ -289,33 +290,28 @@ RedPipeItem* RedCharDeviceSpiceVmc::read_one_msg_from_device()
return NULL;
}
static void red_port_init_item_free(struct RedPipeItem *base)
RedPortInitPipeItem::~RedPortInitPipeItem()
{
RedPortInitPipeItem *item = SPICE_UPCAST(RedPortInitPipeItem, base);
g_free(item->name);
g_free(item);
g_free(name);
}
static void spicevmc_port_send_init(VmcChannelClient *rcc)
{
RedVmcChannel *channel = rcc->get_channel();
SpiceCharDeviceInstance *sin = channel->chardev_sin;
RedPortInitPipeItem *item = g_new(RedPortInitPipeItem, 1);
RedPortInitPipeItem *item = new RedPortInitPipeItem(RED_PIPE_ITEM_TYPE_PORT_INIT);
red_pipe_item_init_full(&item->base, RED_PIPE_ITEM_TYPE_PORT_INIT, red_port_init_item_free);
item->name = g_strdup(sin->portname);
item->opened = channel->port_opened;
rcc->pipe_add_push(&item->base);
rcc->pipe_add_push(item);
}
static void spicevmc_port_send_event(RedChannelClient *rcc, uint8_t event)
{
RedPortEventPipeItem *item = g_new(RedPortEventPipeItem, 1);
RedPortEventPipeItem *item = new RedPortEventPipeItem(RED_PIPE_ITEM_TYPE_PORT_EVENT);
red_pipe_item_init(&item->base, RED_PIPE_ITEM_TYPE_PORT_EVENT);
item->event = event;
rcc->pipe_add_push(&item->base);
rcc->pipe_add_push(item);
}
void RedCharDeviceSpiceVmc::remove_client(RedCharDeviceClientOpaque *opaque)
@ -510,14 +506,14 @@ static void
spicevmc_red_channel_queue_data(RedVmcChannel *channel, RedVmcPipeItem *item)
{
channel->queued_data += item->buf_used;
channel->rcc->pipe_add_push(&item->base);
channel->rcc->pipe_add_push(item);
}
static void spicevmc_red_channel_send_data(VmcChannelClient *rcc,
SpiceMarshaller *m,
RedPipeItem *item)
{
RedVmcPipeItem *i = SPICE_UPCAST(RedVmcPipeItem, item);
RedVmcPipeItem *i = static_cast<RedVmcPipeItem*>(item);
RedVmcChannel *channel = rcc->get_channel();
/* for compatibility send using not compressed data message */
@ -561,7 +557,7 @@ static void spicevmc_red_channel_send_port_init(RedChannelClient *rcc,
SpiceMarshaller *m,
RedPipeItem *item)
{
RedPortInitPipeItem *i = SPICE_UPCAST(RedPortInitPipeItem, item);
RedPortInitPipeItem *i = static_cast<RedPortInitPipeItem*>(item);
SpiceMsgPortInit init;
rcc->init_send_data(SPICE_MSG_PORT_INIT);
@ -575,7 +571,7 @@ static void spicevmc_red_channel_send_port_event(RedChannelClient *rcc,
SpiceMarshaller *m,
RedPipeItem *item)
{
RedPortEventPipeItem *i = SPICE_UPCAST(RedPortEventPipeItem, item);
RedPortEventPipeItem *i = static_cast<RedPortEventPipeItem*>(item);
SpiceMsgPortEvent event;
rcc->init_send_data(SPICE_MSG_PORT_EVENT);

View File

@ -67,17 +67,19 @@ enum {
RED_PIPE_ITEM_TYPE_MONITORS_CONFIG,
};
typedef struct StreamCreateItem {
RedPipeItem base;
struct StreamCreateItem: public RedPipeItem {
using RedPipeItem::RedPipeItem;
SpiceMsgDisplayStreamCreate stream_create;
} StreamCreateItem;
};
struct StreamDataItem: public RedPipeItem {
using RedPipeItem::RedPipeItem;
~StreamDataItem();
typedef struct StreamDataItem {
RedPipeItem base;
StreamChannel *channel;
// NOTE: this must be the last field in the structure
SpiceMsgDisplayStreamData data;
} StreamDataItem;
};
#define PRIMARY_SURFACE_ID 0
@ -210,7 +212,7 @@ void StreamChannelClient::send_item(RedPipeItem *pipe_item)
break;
}
case RED_PIPE_ITEM_TYPE_STREAM_CREATE: {
StreamCreateItem *item = SPICE_UPCAST(StreamCreateItem, pipe_item);
StreamCreateItem *item = static_cast<StreamCreateItem*>(pipe_item);
stream_id = item->stream_create.id;
init_send_data(SPICE_MSG_DISPLAY_STREAM_CREATE);
spice_marshall_msg_display_stream_create(m, &item->stream_create);
@ -231,7 +233,7 @@ void StreamChannelClient::send_item(RedPipeItem *pipe_item)
break;
}
case RED_PIPE_ITEM_TYPE_STREAM_DATA: {
StreamDataItem *item = SPICE_UPCAST(StreamDataItem, pipe_item);
StreamDataItem *item = static_cast<StreamDataItem*>(pipe_item);
init_send_data(SPICE_MSG_DISPLAY_STREAM_DATA);
spice_marshall_msg_display_stream_data(m, &item->data);
pipe_item->add_to_marshaller(m, item->data.data, item->data.data_size);
@ -424,8 +426,7 @@ StreamChannel::change_format(const StreamMsgFormat *fmt)
stream_id = (stream_id + 1) % NUM_STREAMS;
// send create stream
StreamCreateItem *item = g_new0(StreamCreateItem, 1);
red_pipe_item_init(&item->base, RED_PIPE_ITEM_TYPE_STREAM_CREATE);
StreamCreateItem *item = new StreamCreateItem(RED_PIPE_ITEM_TYPE_STREAM_CREATE);
item->stream_create.id = stream_id;
item->stream_create.flags = SPICE_STREAM_FLAGS_TOP_DOWN;
item->stream_create.codec_type = fmt->codec;
@ -435,7 +436,7 @@ StreamChannel::change_format(const StreamMsgFormat *fmt)
item->stream_create.src_height = fmt->height;
item->stream_create.dest = (SpiceRect) { 0, 0, fmt->width, fmt->height };
item->stream_create.clip = (SpiceClip) { SPICE_CLIP_TYPE_NONE, NULL };
pipes_add(&item->base);
pipes_add(item);
// activate stream report if possible
pipes_add_type(RED_PIPE_ITEM_TYPE_STREAM_ACTIVATE_REPORT);
@ -451,14 +452,9 @@ StreamChannel::update_queue_stat(int32_t num_diff, int32_t size_diff)
}
}
void
StreamChannel::data_item_free(RedPipeItem *base)
StreamDataItem::~StreamDataItem()
{
StreamDataItem *pipe_item = SPICE_UPCAST(StreamDataItem, base);
pipe_item->channel->update_queue_stat(-1, -pipe_item->data.data_size);
g_free(pipe_item);
channel->update_queue_stat(-1, -data.data_size);
}
void
@ -471,9 +467,7 @@ StreamChannel::send_data(const void *data, size_t size, uint32_t mm_time)
return;
}
StreamDataItem *item = (StreamDataItem*) g_malloc(sizeof(*item) + size);
red_pipe_item_init_full(&item->base, RED_PIPE_ITEM_TYPE_STREAM_DATA,
data_item_free);
StreamDataItem *item = new (size) StreamDataItem(RED_PIPE_ITEM_TYPE_STREAM_DATA);
item->data.base.id = stream_id;
item->data.base.multi_media_time = mm_time;
item->data.data_size = size;
@ -481,7 +475,7 @@ StreamChannel::send_data(const void *data, size_t size, uint32_t mm_time)
update_queue_stat(1, size);
// TODO try to optimize avoiding the copy
memcpy(item->data.data, data, size);
pipes_add(&item->base);
pipes_add(item);
}
void

View File

@ -50,10 +50,12 @@ struct StreamQueueStat {
typedef void (*stream_channel_queue_stat_proc)(void *opaque, const StreamQueueStat *stats,
StreamChannel *channel);
struct StreamDataItem;
struct StreamChannelClient;
struct StreamChannel final: public RedChannel
{
friend struct StreamChannelClient;
friend struct StreamDataItem;
StreamChannel(RedsState *reds, uint32_t id);
/**
@ -73,7 +75,6 @@ private:
inline void update_queue_stat(int32_t num_diff, int32_t size_diff);
void request_new_stream(StreamMsgStartStop *start);
static void data_item_free(RedPipeItem *base);
/* current video stream id, <0 if not initialized or
* we are not sending a stream */

View File

@ -64,24 +64,20 @@ static void video_stream_agent_stats_print(VideoStreamAgent *agent)
#endif
}
static void video_stream_create_destroy_item_release(RedPipeItem *base)
StreamCreateDestroyItem::~StreamCreateDestroyItem()
{
StreamCreateDestroyItem *item = SPICE_UPCAST(StreamCreateDestroyItem, base);
DisplayChannel *display = DCC_TO_DC(item->agent->dcc);
video_stream_agent_unref(display, item->agent);
g_free(item);
DisplayChannel *display = DCC_TO_DC(agent->dcc);
video_stream_agent_unref(display, agent);
}
static RedPipeItem *video_stream_create_destroy_item_new(VideoStreamAgent *agent,
gint type)
int type)
{
StreamCreateDestroyItem *item = g_new0(StreamCreateDestroyItem, 1);
StreamCreateDestroyItem *item = new StreamCreateDestroyItem(type);
red_pipe_item_init_full(&item->base, type,
video_stream_create_destroy_item_release);
agent->stream->refs++;
item->agent = agent;
return &item->base;
return item;
}
static RedPipeItem *video_stream_create_item_new(VideoStreamAgent *agent)
@ -163,24 +159,17 @@ void video_stream_agent_unref(DisplayChannel *display, VideoStreamAgent *agent)
video_stream_unref(display, agent->stream);
}
static void video_stream_clip_item_free(RedPipeItem *base)
VideoStreamClipItem::~VideoStreamClipItem()
{
g_return_if_fail(base != NULL);
VideoStreamClipItem *item = SPICE_UPCAST(VideoStreamClipItem, base);
DisplayChannel *display = DCC_TO_DC(item->stream_agent->dcc);
DisplayChannel *display = DCC_TO_DC(stream_agent->dcc);
g_return_if_fail(item->base.refcount == 0);
video_stream_agent_unref(display, item->stream_agent);
g_free(item->rects);
g_free(item);
video_stream_agent_unref(display, stream_agent);
g_free(rects);
}
VideoStreamClipItem *video_stream_clip_item_new(VideoStreamAgent *agent)
{
VideoStreamClipItem *item = g_new(VideoStreamClipItem, 1);
red_pipe_item_init_full(&item->base, RED_PIPE_ITEM_TYPE_STREAM_CLIP,
video_stream_clip_item_free);
VideoStreamClipItem *item = new VideoStreamClipItem(RED_PIPE_ITEM_TYPE_STREAM_CLIP);
item->stream_agent = agent;
agent->stream->refs++;
@ -364,7 +353,7 @@ static void before_reattach_stream(DisplayChannel *display,
dcc = dpi->dcc;
agent = dcc_get_video_stream_agent(dcc, index);
if (dcc->pipe_item_is_linked(&dpi->base)) {
if (dcc->pipe_item_is_linked(dpi)) {
#ifdef STREAM_STATS
agent->stats.num_drops_pipe++;
#endif
@ -784,14 +773,13 @@ void dcc_create_stream(DisplayChannelClient *dcc, VideoStream *stream)
dcc->pipe_add(video_stream_create_item_new(agent));
if (dcc->test_remote_cap(SPICE_DISPLAY_CAP_STREAM_REPORT)) {
RedStreamActivateReportItem *report_pipe_item = g_new0(RedStreamActivateReportItem, 1);
RedStreamActivateReportItem *report_pipe_item =
new RedStreamActivateReportItem(RED_PIPE_ITEM_TYPE_STREAM_ACTIVATE_REPORT);
agent->report_id = rand();
red_pipe_item_init(&report_pipe_item->base,
RED_PIPE_ITEM_TYPE_STREAM_ACTIVATE_REPORT);
report_pipe_item->stream_id = stream_id;
report_pipe_item->report_id = agent->report_id;
dcc->pipe_add(&report_pipe_item->base);
dcc->pipe_add(report_pipe_item);
}
#ifdef STREAM_STATS
memset(&agent->stats, 0, sizeof(StreamStats));
@ -812,17 +800,10 @@ void video_stream_agent_stop(VideoStreamAgent *agent)
}
}
static void red_upgrade_item_free(RedPipeItem *base)
RedUpgradeItem::~RedUpgradeItem()
{
g_return_if_fail(base != NULL);
RedUpgradeItem *item = SPICE_UPCAST(RedUpgradeItem, base);
g_return_if_fail(item->base.refcount == 0);
drawable_unref(item->drawable);
g_free(item->rects);
g_free(item);
drawable_unref(drawable);
g_free(rects);
}
/*
@ -861,9 +842,7 @@ static void dcc_detach_stream_gracefully(DisplayChannelClient *dcc,
}
spice_debug("stream %d: upgrade by drawable. box ==>", stream_id);
rect_debug(&stream->current->red_drawable->bbox);
upgrade_item = g_new(RedUpgradeItem, 1);
red_pipe_item_init_full(&upgrade_item->base, RED_PIPE_ITEM_TYPE_UPGRADE,
red_upgrade_item_free);
upgrade_item = new RedUpgradeItem(RED_PIPE_ITEM_TYPE_UPGRADE);
upgrade_item->drawable = stream->current;
upgrade_item->drawable->refs++;
n_rects = pixman_region32_n_rects(&upgrade_item->drawable->tree_item.base.rgn);
@ -871,7 +850,7 @@ static void dcc_detach_stream_gracefully(DisplayChannelClient *dcc,
upgrade_item->rects->num_rects = n_rects;
region_ret_rects(&upgrade_item->drawable->tree_item.base.rgn,
upgrade_item->rects->rects, n_rects);
dcc->pipe_add(&upgrade_item->base);
dcc->pipe_add(upgrade_item);
} else {
SpiceRect upgrade_area;

View File

@ -49,17 +49,18 @@ typedef struct VideoStream VideoStream;
/* This item is used to send a full quality image (lossless) of the area where the stream was.
* This to avoid the artifacts due to the lossy compression. */
typedef struct RedUpgradeItem {
RedPipeItem base;
struct RedUpgradeItem: public RedPipeItem {
using RedPipeItem::RedPipeItem;
~RedUpgradeItem();
Drawable *drawable;
SpiceClipRects *rects;
} RedUpgradeItem;
};
typedef struct RedStreamActivateReportItem {
RedPipeItem base;
struct RedStreamActivateReportItem: public RedPipeItem {
using RedPipeItem::RedPipeItem;
uint32_t stream_id;
uint32_t report_id;
} RedStreamActivateReportItem;
};
#ifdef STREAM_STATS
typedef struct StreamStats {
@ -95,19 +96,21 @@ typedef struct VideoStreamAgent {
#endif
} VideoStreamAgent;
typedef struct VideoStreamClipItem {
RedPipeItem base;
struct VideoStreamClipItem: public RedPipeItem {
using RedPipeItem::RedPipeItem;
~VideoStreamClipItem();
VideoStreamAgent *stream_agent;
int clip_type;
SpiceClipRects *rects;
} VideoStreamClipItem;
};
VideoStreamClipItem *video_stream_clip_item_new(VideoStreamAgent *agent);
typedef struct StreamCreateDestroyItem {
RedPipeItem base;
struct StreamCreateDestroyItem: public RedPipeItem {
using RedPipeItem::RedPipeItem;
~StreamCreateDestroyItem();
VideoStreamAgent *agent;
} StreamCreateDestroyItem;
};
typedef struct ItemTrace {
red_time_t time;