summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--server/common-graphics-channel.cpp50
-rw-r--r--server/common-graphics-channel.h37
-rw-r--r--server/cursor-channel-client.cpp66
-rw-r--r--server/cursor-channel-client.h34
-rw-r--r--server/cursor-channel.cpp4
-rw-r--r--server/dcc-private.h16
-rw-r--r--server/dcc-send.cpp3
-rw-r--r--server/dcc.cpp206
-rw-r--r--server/dcc.h42
-rw-r--r--server/display-channel.cpp2
-rw-r--r--server/inputs-channel-client.cpp87
-rw-r--r--server/inputs-channel-client.h33
-rw-r--r--server/inputs-channel.cpp2
-rw-r--r--server/main-channel-client.cpp160
-rw-r--r--server/main-channel-client.h37
-rw-r--r--server/main-channel.cpp2
-rw-r--r--server/red-channel-client.cpp281
-rw-r--r--server/red-channel-client.h49
-rw-r--r--server/red-common.h20
-rw-r--r--server/smartcard-channel-client.cpp129
-rw-r--r--server/smartcard-channel-client.h38
-rw-r--r--server/smartcard.cpp2
-rw-r--r--server/sound.cpp355
-rw-r--r--server/spicevmc.cpp72
-rw-r--r--server/stream-channel.cpp105
-rw-r--r--server/tests/test-channel.cpp47
26 files changed, 589 insertions, 1290 deletions
diff --git a/server/common-graphics-channel.cpp b/server/common-graphics-channel.cpp
index 24a5d1ba..fee57166 100644
--- a/server/common-graphics-channel.cpp
+++ b/server/common-graphics-channel.cpp
@@ -22,8 +22,6 @@
#include "dcc.h"
#include "red-client.h"
-#define CHANNEL_RECEIVE_BUF_SIZE 1024
-
struct CommonGraphicsChannelPrivate
{
int during_target_migrate; /* TRUE when the client that is associated with the channel
@@ -36,43 +34,32 @@ struct CommonGraphicsChannelPrivate
G_DEFINE_ABSTRACT_TYPE_WITH_PRIVATE(CommonGraphicsChannel, common_graphics_channel,
RED_TYPE_CHANNEL)
-struct CommonGraphicsChannelClientPrivate {
- uint8_t recv_buf[CHANNEL_RECEIVE_BUF_SIZE];
-};
-
-G_DEFINE_TYPE_WITH_PRIVATE(CommonGraphicsChannelClient, common_graphics_channel_client,
- RED_TYPE_CHANNEL_CLIENT)
-
-static uint8_t *common_alloc_recv_buf(RedChannelClient *rcc, uint16_t type, uint32_t size)
+uint8_t *CommonGraphicsChannelClient::alloc_recv_buf(uint16_t type, uint32_t size)
{
- CommonGraphicsChannelClient *common = COMMON_GRAPHICS_CHANNEL_CLIENT(rcc);
-
/* SPICE_MSGC_MIGRATE_DATA is the only client message whose size is dynamic */
if (type == SPICE_MSGC_MIGRATE_DATA) {
return (uint8_t *) g_malloc(size);
}
- if (size > sizeof(common->priv->recv_buf)) {
- spice_warning("unexpected message size %u (max is %zd)", size,
- sizeof(common->priv->recv_buf));
+ if (size > sizeof(recv_buf)) {
+ spice_warning("unexpected message size %u (max is %zd)", size, sizeof(recv_buf));
return NULL;
}
- return common->priv->recv_buf;
+ return recv_buf;
}
-static void common_release_recv_buf(RedChannelClient *rcc, uint16_t type, uint32_t size,
- uint8_t* msg)
+void CommonGraphicsChannelClient::release_recv_buf(uint16_t type, uint32_t size, uint8_t* msg)
{
if (type == SPICE_MSGC_MIGRATE_DATA) {
g_free(msg);
}
}
-bool common_channel_client_config_socket(RedChannelClient *rcc)
+bool CommonGraphicsChannelClient::config_socket()
{
- RedClient *client = rcc->get_client();
+ RedClient *client = get_client();
MainChannelClient *mcc = red_client_get_main(client);
- RedStream *stream = rcc->get_stream();
+ RedStream *stream = get_stream();
gboolean is_low_bandwidth;
// TODO - this should be dynamic, not one time at channel creation
@@ -87,8 +74,8 @@ bool common_channel_client_config_socket(RedChannelClient *rcc)
red_stream_set_no_delay(stream, !is_low_bandwidth);
}
// TODO: move wide/narrow ack setting to red_channel.
- rcc->ack_set_client_window(is_low_bandwidth ? WIDE_CLIENT_ACK_WINDOW : NARROW_CLIENT_ACK_WINDOW);
- return TRUE;
+ ack_set_client_window(is_low_bandwidth ? WIDE_CLIENT_ACK_WINDOW : NARROW_CLIENT_ACK_WINDOW);
+ return true;
}
@@ -112,20 +99,3 @@ gboolean common_graphics_channel_get_during_target_migrate(CommonGraphicsChannel
{
return self->priv->during_target_migrate;
}
-
-static void
-common_graphics_channel_client_init(CommonGraphicsChannelClient *self)
-{
- self->priv = (CommonGraphicsChannelClientPrivate*)
- common_graphics_channel_client_get_instance_private(self);
-}
-
-static void
-common_graphics_channel_client_class_init(CommonGraphicsChannelClientClass *klass)
-{
- RedChannelClientClass *client_class = RED_CHANNEL_CLIENT_CLASS(klass);
-
- client_class->config_socket = common_channel_client_config_socket;
- client_class->alloc_recv_buf = common_alloc_recv_buf;
- client_class->release_recv_buf = common_release_recv_buf;
-}
diff --git a/server/common-graphics-channel.h b/server/common-graphics-channel.h
index a9d76e4c..b19f1413 100644
--- a/server/common-graphics-channel.h
+++ b/server/common-graphics-channel.h
@@ -25,8 +25,6 @@
G_BEGIN_DECLS
-bool common_channel_client_config_socket(RedChannelClient *rcc);
-
#define COMMON_CLIENT_TIMEOUT (NSEC_PER_SEC * 30)
#define TYPE_COMMON_GRAPHICS_CHANNEL common_graphics_channel_get_type()
@@ -65,34 +63,19 @@ enum {
RED_PIPE_ITEM_TYPE_COMMON_LAST
};
-#define TYPE_COMMON_GRAPHICS_CHANNEL_CLIENT common_graphics_channel_client_get_type()
-
-#define COMMON_GRAPHICS_CHANNEL_CLIENT(obj) \
- (G_TYPE_CHECK_INSTANCE_CAST((obj), TYPE_COMMON_GRAPHICS_CHANNEL_CLIENT, \
- CommonGraphicsChannelClient))
-#define COMMON_GRAPHICS_CHANNEL_CLIENT_CLASS(klass) \
- (G_TYPE_CHECK_CLASS_CAST((klass), TYPE_COMMON_GRAPHICS_CHANNEL_CLIENT, \
- CommonGraphicsChannelClientClass))
-#define COMMON_IS_GRAPHICS_CHANNEL_CLIENT(obj) \
- (G_TYPE_CHECK_INSTANCE_TYPE((obj), TYPE_COMMON_GRAPHICS_CHANNEL_CLIENT))
-#define COMMON_IS_GRAPHICS_CHANNEL_CLIENT_CLASS(klass) \
- (G_TYPE_CHECK_CLASS_TYPE((klass), TYPE_COMMON_GRAPHICS_CHANNEL_CLIENT))
-#define COMMON_GRAPHICS_CHANNEL_CLIENT_GET_CLASS(obj) \
- (G_TYPE_INSTANCE_GET_CLASS((obj), TYPE_COMMON_GRAPHICS_CHANNEL_CLIENT, \
- CommonGraphicsChannelClientClass))
-
-struct CommonGraphicsChannelClientPrivate;
-
-struct CommonGraphicsChannelClient: public RedChannelClient
+class CommonGraphicsChannelClient: public RedChannelClient
{
- CommonGraphicsChannelClientPrivate *priv;
-};
+ enum { CHANNEL_RECEIVE_BUF_SIZE = 1024 };
+ uint8_t recv_buf[CHANNEL_RECEIVE_BUF_SIZE];
-struct CommonGraphicsChannelClientClass {
- RedChannelClientClass parent_class;
-};
+public:
+ using RedChannelClient::RedChannelClient;
-GType common_graphics_channel_client_get_type(void) G_GNUC_CONST;
+protected:
+ virtual uint8_t *alloc_recv_buf(uint16_t type, uint32_t size) override;
+ virtual void release_recv_buf(uint16_t type, uint32_t size, uint8_t *msg) override;
+ virtual bool config_socket() override;
+};
G_END_DECLS
diff --git a/server/cursor-channel-client.cpp b/server/cursor-channel-client.cpp
index dd64580c..15600b7f 100644
--- a/server/cursor-channel-client.cpp
+++ b/server/cursor-channel-client.cpp
@@ -35,32 +35,13 @@
struct CursorChannelClientPrivate
{
+ SPICE_CXX_GLIB_ALLOCATOR
+
RedCacheItem *cursor_cache[CURSOR_CACHE_HASH_SIZE];
- Ring cursor_cache_lru;
- long cursor_cache_available;
+ Ring cursor_cache_lru = { nullptr, nullptr };
+ long cursor_cache_available = 0;
};
-G_DEFINE_TYPE_WITH_PRIVATE(CursorChannelClient, cursor_channel_client,
- TYPE_COMMON_GRAPHICS_CHANNEL_CLIENT)
-
-static void cursor_channel_client_on_disconnect(RedChannelClient *rcc);
-
-static void
-cursor_channel_client_class_init(CursorChannelClientClass *klass)
-{
- RedChannelClientClass *client_class = RED_CHANNEL_CLIENT_CLASS(klass);
-
- client_class->on_disconnect = cursor_channel_client_on_disconnect;
-}
-
-static void
-cursor_channel_client_init(CursorChannelClient *self)
-{
- self->priv = (CursorChannelClientPrivate*) cursor_channel_client_get_instance_private(self);
- ring_init(&self->priv->cursor_cache_lru);
- self->priv->cursor_cache_available = CLIENT_CURSOR_CACHE_SIZE;
-}
-
#define CLIENT_CURSOR_CACHE
#include "cache-item.tmpl.cpp"
#undef CLIENT_CURSOR_CACHE
@@ -74,12 +55,9 @@ void cursor_channel_client_reset_cursor_cache(CursorChannelClient *ccc)
red_cursor_cache_reset(ccc, CLIENT_CURSOR_CACHE_SIZE);
}
-static void cursor_channel_client_on_disconnect(RedChannelClient *rcc)
+void CursorChannelClient::on_disconnect()
{
- if (!rcc) {
- return;
- }
- cursor_channel_client_reset_cursor_cache(CURSOR_CHANNEL_CLIENT(rcc));
+ cursor_channel_client_reset_cursor_cache(this);
}
void cursor_channel_client_migrate(RedChannelClient *rcc)
@@ -90,20 +68,32 @@ void cursor_channel_client_migrate(RedChannelClient *rcc)
RedChannelClient::default_migrate(rcc);
}
+CursorChannelClient::CursorChannelClient(RedChannel *channel,
+ RedClient *client,
+ RedStream *stream,
+ RedChannelCapabilities *caps):
+ CommonGraphicsChannelClient(channel, client, stream, caps)
+{
+ priv = new CursorChannelClientPrivate();
+ ring_init(&priv->cursor_cache_lru);
+ priv->cursor_cache_available = CLIENT_CURSOR_CACHE_SIZE;
+}
+
+CursorChannelClient::~CursorChannelClient()
+{
+ delete priv;
+}
+
CursorChannelClient* cursor_channel_client_new(CursorChannel *cursor, RedClient *client, RedStream *stream,
int mig_target,
RedChannelCapabilities *caps)
{
- CursorChannelClient *rcc;
-
- rcc = (CursorChannelClient*)
- g_initable_new(TYPE_CURSOR_CHANNEL_CLIENT,
- NULL, NULL,
- "channel", cursor,
- "client", client,
- "stream", stream,
- "caps", caps,
- NULL);
+ auto rcc = new CursorChannelClient(RED_CHANNEL(cursor), client, stream, caps);
+
+ if (!rcc->init()) {
+ rcc->unref();
+ rcc = nullptr;
+ }
common_graphics_channel_set_during_target_migrate(COMMON_GRAPHICS_CHANNEL(cursor), mig_target);
return rcc;
diff --git a/server/cursor-channel-client.h b/server/cursor-channel-client.h
index 5688f1f3..38f22530 100644
--- a/server/cursor-channel-client.h
+++ b/server/cursor-channel-client.h
@@ -19,8 +19,6 @@
#ifndef CURSOR_CHANNEL_CLIENT_H_
#define CURSOR_CHANNEL_CLIENT_H_
-#include <glib-object.h>
-
#include "cache-item.h"
#include "red-common.h"
#include "red-channel-client.h"
@@ -29,33 +27,21 @@
G_BEGIN_DECLS
-#define TYPE_CURSOR_CHANNEL_CLIENT cursor_channel_client_get_type()
-
-#define CURSOR_CHANNEL_CLIENT(obj) \
- (G_TYPE_CHECK_INSTANCE_CAST((obj), TYPE_CURSOR_CHANNEL_CLIENT, CursorChannelClient))
-#define CURSOR_CHANNEL_CLIENT_CLASS(klass) \
- (G_TYPE_CHECK_CLASS_CAST((klass), TYPE_CURSOR_CHANNEL_CLIENT, CursorChannelClientClass))
-#define IS_CURSOR_CHANNEL_CLIENT(obj) \
- (G_TYPE_CHECK_INSTANCE_TYPE((obj), TYPE_CURSOR_CHANNEL_CLIENT))
-#define IS_CURSOR_CHANNEL_CLIENT_CLASS(klass) \
- (G_TYPE_CHECK_CLASS_TYPE((klass), TYPE_CURSOR_CHANNEL_CLIENT))
-#define CURSOR_CHANNEL_CLIENT_GET_CLASS(obj) \
- (G_TYPE_INSTANCE_GET_CLASS((obj), TYPE_CURSOR_CHANNEL_CLIENT, CursorChannelClientClass))
-
struct CursorChannelClientPrivate;
-struct CursorChannelClient final: public CommonGraphicsChannelClient
+class CursorChannelClient final: public CommonGraphicsChannelClient
{
- CursorChannelClientPrivate *priv;
+protected:
+ ~CursorChannelClient();
+public:
+ CursorChannelClient(RedChannel *channel,
+ RedClient *client,
+ RedStream *stream,
+ RedChannelCapabilities *caps);
+ virtual void on_disconnect() override;
+ CursorChannelClientPrivate *priv = nullptr;
};
-struct CursorChannelClientClass
-{
- RedChannelClientClass parent_class;
-};
-
-GType cursor_channel_client_get_type(void) G_GNUC_CONST;
-
CursorChannelClient* cursor_channel_client_new(CursorChannel *cursor,
RedClient *client,
RedStream *stream,
diff --git a/server/cursor-channel.cpp b/server/cursor-channel.cpp
index b084ef72..ba44ff55 100644
--- a/server/cursor-channel.cpp
+++ b/server/cursor-channel.cpp
@@ -193,6 +193,8 @@ static inline void red_marshall_inval(RedChannelClient *rcc,
spice_marshall_msg_cursor_inval_one(base_marshaller, &inval_one);
}
+XXX_CAST(RedChannelClient, CursorChannelClient, CURSOR_CHANNEL_CLIENT);
+
static void cursor_channel_send_item(RedChannelClient *rcc, RedPipeItem *pipe_item)
{
SpiceMarshaller *m = rcc->get_marshaller();
@@ -211,7 +213,7 @@ static void cursor_channel_send_item(RedChannelClient *rcc, RedPipeItem *pipe_it
break;
case RED_PIPE_ITEM_TYPE_INVAL_CURSOR_CACHE:
cursor_channel_client_reset_cursor_cache(ccc);
- rcc->init_send_data(SPICE_MSG_CURSOR_INVAL_ALL);
+ ccc->init_send_data(SPICE_MSG_CURSOR_INVAL_ALL);
break;
default:
spice_error("invalid pipe item type");
diff --git a/server/dcc-private.h b/server/dcc-private.h
index c171d999..13b1b660 100644
--- a/server/dcc-private.h
+++ b/server/dcc-private.h
@@ -27,22 +27,24 @@
struct DisplayChannelClientPrivate
{
- uint32_t id;
+ SPICE_CXX_GLIB_ALLOCATOR
+
+ uint32_t id = 0;
SpiceImageCompression image_compression;
spice_wan_compression_t jpeg_state;
spice_wan_compression_t zlib_glz_state;
ImageEncoders encoders;
- int expect_init;
+ int expect_init = 0;
- PixmapCache *pixmap_cache;
- uint32_t pixmap_cache_generation;
- int pending_pixmaps_sync;
+ PixmapCache *pixmap_cache = nullptr;
+ uint32_t pixmap_cache_generation = 0;
+ int pending_pixmaps_sync = 0;
RedCacheItem *palette_cache[PALETTE_CACHE_HASH_SIZE];
- Ring palette_cache_lru;
- long palette_cache_available;
+ Ring palette_cache_lru = { nullptr, nullptr };
+ long palette_cache_available = CLIENT_PALETTE_CACHE_SIZE;
struct {
FreeList free_list;
diff --git a/server/dcc-send.cpp b/server/dcc-send.cpp
index 3cde9710..2b0fd319 100644
--- a/server/dcc-send.cpp
+++ b/server/dcc-send.cpp
@@ -24,6 +24,9 @@
#include "display-channel-private.h"
#include "red-qxl.h"
+// XXX this should go away with virtual on the right class (client!)
+XXX_CAST(RedChannelClient, DisplayChannelClient, DISPLAY_CHANNEL_CLIENT)
+
typedef enum {
FILL_BITS_TYPE_INVALID,
FILL_BITS_TYPE_CACHE,
diff --git a/server/dcc.cpp b/server/dcc.cpp
index d9ac0047..6173fd1c 100644
--- a/server/dcc.cpp
+++ b/server/dcc.cpp
@@ -25,157 +25,50 @@
#include "main-channel-client.h"
#include <spice-server-enums.h>
-G_DEFINE_TYPE(DisplayChannelClient, display_channel_client, TYPE_COMMON_GRAPHICS_CHANNEL_CLIENT)
-
#define DISPLAY_CLIENT_SHORT_TIMEOUT 15000000000ULL //nano
#define DISPLAY_FREE_LIST_DEFAULT_SIZE 128
-enum
-{
- PROP0,
- PROP_IMAGE_COMPRESSION,
- PROP_JPEG_STATE,
- PROP_ZLIB_GLZ_STATE
-};
-
-static bool dcc_config_socket(RedChannelClient *rcc);
-static void dcc_on_disconnect(RedChannelClient *rcc);
-
-static void
-display_channel_client_get_property(GObject *object,
- guint property_id,
- GValue *value,
- GParamSpec *pspec)
-{
- DisplayChannelClient *self = DISPLAY_CHANNEL_CLIENT(object);
-
- switch (property_id)
- {
- case PROP_IMAGE_COMPRESSION:
- g_value_set_enum(value, self->priv->image_compression);
- break;
- case PROP_JPEG_STATE:
- g_value_set_enum(value, self->priv->jpeg_state);
- break;
- case PROP_ZLIB_GLZ_STATE:
- g_value_set_enum(value, self->priv->zlib_glz_state);
- break;
- default:
- G_OBJECT_WARN_INVALID_PROPERTY_ID(object, property_id, pspec);
- }
-}
-
-static void
-display_channel_client_set_property(GObject *object,
- guint property_id,
- const GValue *value,
- GParamSpec *pspec)
-{
- DisplayChannelClient *self = DISPLAY_CHANNEL_CLIENT(object);
-
- switch (property_id)
- {
- case PROP_IMAGE_COMPRESSION:
- self->priv->image_compression = (SpiceImageCompression) g_value_get_enum(value);
- break;
- case PROP_JPEG_STATE:
- self->priv->jpeg_state = (spice_wan_compression_t) g_value_get_enum(value);
- break;
- case PROP_ZLIB_GLZ_STATE:
- self->priv->zlib_glz_state = (spice_wan_compression_t) g_value_get_enum(value);
- break;
- default:
- G_OBJECT_WARN_INVALID_PROPERTY_ID(object, property_id, pspec);
- }
-}
-
static void dcc_init_stream_agents(DisplayChannelClient *dcc);
-static void
-display_channel_client_constructed(GObject *object)
+DisplayChannelClient::DisplayChannelClient(DisplayChannel *display,
+ RedClient *client, RedStream *stream,
+ RedChannelCapabilities *caps,
+ uint32_t id,
+ SpiceImageCompression image_compression,
+ spice_wan_compression_t jpeg_state,
+ spice_wan_compression_t zlib_glz_state):
+ CommonGraphicsChannelClient(RED_CHANNEL(display), client, stream, caps, true)
{
- DisplayChannelClient *self = DISPLAY_CHANNEL_CLIENT(object);
+ priv = new DisplayChannelClientPrivate;
- G_OBJECT_CLASS(display_channel_client_parent_class)->constructed(object);
+ // XXX from display_channel_client_init, put somewhere else
+ ring_init(&priv->palette_cache_lru);
+ // todo: tune quality according to bandwidth
+ priv->encoders.jpeg_quality = 85;
- dcc_init_stream_agents(self);
+ priv->send_data.free_list.res = (SpiceResourceList*)
+ g_malloc(sizeof(SpiceResourceList) +
+ DISPLAY_FREE_LIST_DEFAULT_SIZE * sizeof(SpiceResourceID));
+ priv->send_data.free_list.res_size = DISPLAY_FREE_LIST_DEFAULT_SIZE;
- image_encoders_init(&self->priv->encoders, &DCC_TO_DC(self)->priv->encoder_shared_data);
-}
-static void
-display_channel_client_finalize(GObject *object)
-{
- DisplayChannelClient *self = DISPLAY_CHANNEL_CLIENT(object);
+ priv->image_compression = image_compression;
+ priv->jpeg_state = jpeg_state;
+ priv->zlib_glz_state = zlib_glz_state;
- g_clear_pointer(&self->priv->preferred_video_codecs, g_array_unref);
- g_clear_pointer(&self->priv->client_preferred_video_codecs, g_array_unref);
- g_free(self->priv);
- G_OBJECT_CLASS(display_channel_client_parent_class)->finalize(object);
-}
+ priv->id = id;
-static void
-display_channel_client_class_init(DisplayChannelClientClass *klass)
-{
- GObjectClass *object_class = G_OBJECT_CLASS(klass);
- RedChannelClientClass *client_class = RED_CHANNEL_CLIENT_CLASS(klass);
-
- object_class->get_property = display_channel_client_get_property;
- object_class->set_property = display_channel_client_set_property;
- object_class->constructed = display_channel_client_constructed;
- object_class->finalize = display_channel_client_finalize;
-
- client_class->config_socket = dcc_config_socket;
- client_class->on_disconnect = dcc_on_disconnect;
-
- g_object_class_install_property(object_class,
- PROP_IMAGE_COMPRESSION,
- g_param_spec_enum("image-compression",
- "image compression",
- "Image compression type",
- SPICE_TYPE_SPICE_IMAGE_COMPRESSION_T,
- SPICE_IMAGE_COMPRESSION_INVALID,
- G_PARAM_CONSTRUCT | G_PARAM_READWRITE |
- G_PARAM_STATIC_STRINGS));
-
- g_object_class_install_property(object_class,
- PROP_JPEG_STATE,
- g_param_spec_enum("jpeg-state",
- "jpeg state",
- "JPEG compression state",
- SPICE_TYPE_SPICE_WAN_COMPRESSION_T,
- SPICE_WAN_COMPRESSION_INVALID,
- G_PARAM_CONSTRUCT | G_PARAM_READWRITE |
- G_PARAM_STATIC_STRINGS));
-
- g_object_class_install_property(object_class,
- PROP_ZLIB_GLZ_STATE,
- g_param_spec_enum("zlib-glz-state",
- "zlib glz state",
- "zlib glz state",
- SPICE_TYPE_SPICE_WAN_COMPRESSION_T,
- SPICE_WAN_COMPRESSION_INVALID,
- G_PARAM_CONSTRUCT | G_PARAM_READWRITE |
- G_PARAM_STATIC_STRINGS));
+ image_encoders_init(&priv->encoders, &DCC_TO_DC(this)->priv->encoder_shared_data);
+
+ dcc_init_stream_agents(this);
}
-static void display_channel_client_init(DisplayChannelClient *self)
+DisplayChannelClient::~DisplayChannelClient()
{
- /* we need to allocate the private data manually here since
- * g_type_class_add_private() doesn't support private structs larger than
- * 64k */
- self->priv = g_new0(DisplayChannelClientPrivate, 1);
-
- ring_init(&self->priv->palette_cache_lru);
- self->priv->palette_cache_available = CLIENT_PALETTE_CACHE_SIZE;
- // todo: tune quality according to bandwidth
- self->priv->encoders.jpeg_quality = 85;
-
- self->priv->send_data.free_list.res = (SpiceResourceList*)
- g_malloc(sizeof(SpiceResourceList) +
- DISPLAY_FREE_LIST_DEFAULT_SIZE * sizeof(SpiceResourceID));
- self->priv->send_data.free_list.res_size = DISPLAY_FREE_LIST_DEFAULT_SIZE;
+ g_clear_pointer(&priv->preferred_video_codecs, g_array_unref);
+ g_clear_pointer(&priv->client_preferred_video_codecs, g_array_unref);
+ g_free(priv);
}
static RedSurfaceCreateItem *red_surface_create_item_new(RedChannel* channel,
@@ -491,25 +384,15 @@ DisplayChannelClient *dcc_new(DisplayChannel *display,
spice_wan_compression_t zlib_glz_state)
{
- DisplayChannelClient *dcc;
-
- dcc = (DisplayChannelClient*)
- g_initable_new(TYPE_DISPLAY_CHANNEL_CLIENT,
- NULL, NULL,
- "channel", display,
- "client", client,
- "stream", stream,
- "monitor-latency", TRUE,
- "caps", caps,
- "image-compression", image_compression,
- "jpeg-state", jpeg_state,
- "zlib-glz-state", zlib_glz_state,
- NULL);
+ auto dcc =
+ new DisplayChannelClient(display, client, stream, caps, display->priv->qxl->id,
+ image_compression, jpeg_state, zlib_glz_state);
+ if (!dcc->init()) {
+ dcc->unref();
+ dcc = nullptr;
+ }
spice_debug("New display (client %p) dcc %p stream %p", client, dcc, stream);
common_graphics_channel_set_during_target_migrate(display, mig_target);
- if (dcc) {
- dcc->priv->id = display->priv->qxl->id;
- }
return dcc;
}
@@ -695,6 +578,8 @@ RedPipeItem *dcc_gl_scanout_item_new(RedChannelClient *rcc, void *data, int num)
return &item->base;
}
+XXX_CAST(RedChannelClient, DisplayChannelClient, DISPLAY_CHANNEL_CLIENT);
+
RedPipeItem *dcc_gl_draw_item_new(RedChannelClient *rcc, void *data, int num)
{
DisplayChannelClient *dcc = DISPLAY_CHANNEL_CLIENT(rcc);
@@ -1374,28 +1259,25 @@ void dcc_set_max_stream_bit_rate(DisplayChannelClient *dcc, uint64_t rate)
dcc->priv->streams_max_bit_rate = rate;
}
-static bool dcc_config_socket(RedChannelClient *rcc)
+bool DisplayChannelClient::config_socket()
{
- RedClient *client = rcc->get_client();
+ RedClient *client = get_client();
MainChannelClient *mcc = red_client_get_main(client);
- DISPLAY_CHANNEL_CLIENT(rcc)->is_low_bandwidth = main_channel_client_is_low_bandwidth(mcc);
+ is_low_bandwidth = main_channel_client_is_low_bandwidth(mcc);
- return common_channel_client_config_socket(rcc);
+ return CommonGraphicsChannelClient::config_socket();
}
-static void dcc_on_disconnect(RedChannelClient *rcc)
+void DisplayChannelClient::on_disconnect()
{
DisplayChannel *display;
- DisplayChannelClient *dcc;
spice_debug("trace");
- spice_return_if_fail(rcc != NULL);
- dcc = DISPLAY_CHANNEL_CLIENT(rcc);
- display = DCC_TO_DC(dcc);
+ display = DCC_TO_DC(this);
- dcc_stop(dcc); // TODO: start/stop -> connect/disconnect?
+ dcc_stop(this); // TODO: start/stop -> connect/disconnect?
display_channel_compress_stats_print(display);
// this was the last channel client
diff --git a/server/dcc.h b/server/dcc.h
index 740829b1..3974d284 100644
--- a/server/dcc.h
+++ b/server/dcc.h
@@ -19,8 +19,6 @@
#ifndef DCC_H_
#define DCC_H_
-#include <glib-object.h>
-
#include "image-encoders.h"
#include "image-cache.h"
#include "pixmap-cache.h"
@@ -29,34 +27,30 @@
G_BEGIN_DECLS
-#define TYPE_DISPLAY_CHANNEL_CLIENT display_channel_client_get_type()
-
-#define DISPLAY_CHANNEL_CLIENT(obj) \
- (G_TYPE_CHECK_INSTANCE_CAST((obj), TYPE_DISPLAY_CHANNEL_CLIENT, DisplayChannelClient))
-#define DISPLAY_CHANNEL_CLIENT_CLASS(klass) \
- (G_TYPE_CHECK_CLASS_CAST((klass), TYPE_DISPLAY_CHANNEL_CLIENT, DisplayChannelClientClass))
-#define IS_DISPLAY_CHANNEL_CLIENT(obj) \
- (G_TYPE_CHECK_INSTANCE_TYPE((obj), TYPE_DISPLAY_CHANNEL_CLIENT))
-#define IS_DISPLAY_CHANNEL_CLIENT_CLASS(klass) \
- (G_TYPE_CHECK_CLASS_TYPE((klass), TYPE_DISPLAY_CHANNEL_CLIENT))
-#define DISPLAY_CHANNEL_CLIENT_GET_CLASS(obj) \
- (G_TYPE_INSTANCE_GET_CLASS((obj), TYPE_DISPLAY_CHANNEL_CLIENT, DisplayChannelClientClass))
-
+struct DisplayChannel;
struct DisplayChannelClientPrivate;
-struct DisplayChannelClient final: public CommonGraphicsChannelClient
+class DisplayChannelClient final: public CommonGraphicsChannelClient
{
- int is_low_bandwidth;
+protected:
+ ~DisplayChannelClient();
+public:
+ DisplayChannelClient(DisplayChannel *display,
+ RedClient *client, RedStream *stream,
+ RedChannelCapabilities *caps,
+ uint32_t id,
+ SpiceImageCompression image_compression,
+ spice_wan_compression_t jpeg_state,
+ spice_wan_compression_t zlib_glz_state);
+
+ virtual bool config_socket() override;
+ virtual void on_disconnect() override;
+
+ DisplayChannelClientPrivate *priv = nullptr;
- DisplayChannelClientPrivate *priv;
-};
-
-struct DisplayChannelClientClass {
- CommonGraphicsChannelClientClass parent_class;
+ int is_low_bandwidth;
};
-GType display_channel_client_get_type(void) G_GNUC_CONST;
-
#define PALETTE_CACHE_HASH_SHIFT 8
#define PALETTE_CACHE_HASH_SIZE (1 << PALETTE_CACHE_HASH_SHIFT)
#define PALETTE_CACHE_HASH_MASK (PALETTE_CACHE_HASH_SIZE - 1)
diff --git a/server/display-channel.cpp b/server/display-channel.cpp
index 339a1a39..91d5829c 100644
--- a/server/display-channel.cpp
+++ b/server/display-channel.cpp
@@ -21,6 +21,8 @@
#include "display-channel-private.h"
#include "red-qxl.h"
+XXX_CAST(RedChannelClient, DisplayChannelClient, DISPLAY_CHANNEL_CLIENT);
+
G_DEFINE_TYPE(DisplayChannel, display_channel, TYPE_COMMON_GRAPHICS_CHANNEL)
static void display_channel_connect(RedChannel *channel, RedClient *client,
diff --git a/server/inputs-channel-client.cpp b/server/inputs-channel-client.cpp
index b55b4d8b..71e1f1c3 100644
--- a/server/inputs-channel-client.cpp
+++ b/server/inputs-channel-client.cpp
@@ -20,68 +20,25 @@
#include "migration-protocol.h"
#include "red-channel-client.h"
-// TODO: RECEIVE_BUF_SIZE used to be the same for inputs_channel and main_channel
-// since it was defined once in reds.c which contained both.
-// Now that they are split we can give a more fitting value for inputs - what
-// should it be?
-#define REDS_AGENT_WINDOW_SIZE 10
-#define REDS_NUM_INTERNAL_AGENT_MESSAGES 1
-
-// approximate max receive message size
-#define RECEIVE_BUF_SIZE \
- (4096 + (REDS_AGENT_WINDOW_SIZE + REDS_NUM_INTERNAL_AGENT_MESSAGES) * SPICE_AGENT_MAX_DATA_SIZE)
-
-struct InputsChannelClientPrivate
-{
- uint16_t motion_count;
- uint8_t recv_buf[RECEIVE_BUF_SIZE];
-};
-
-G_DEFINE_TYPE_WITH_PRIVATE(InputsChannelClient, inputs_channel_client, RED_TYPE_CHANNEL_CLIENT)
+XXX_CAST(RedChannelClient, InputsChannelClient, INPUTS_CHANNEL_CLIENT);
-static uint8_t *
-inputs_channel_client_alloc_msg_rcv_buf(RedChannelClient *rcc,
- uint16_t type, uint32_t size)
+uint8_t *InputsChannelClient::alloc_recv_buf(uint16_t type, uint32_t size)
{
- InputsChannelClient *icc = INPUTS_CHANNEL_CLIENT(rcc);
-
- if (size > sizeof(icc->priv->recv_buf)) {
- red_channel_warning(rcc->get_channel(),
- "error: too large incoming message");
+ if (size > sizeof(recv_buf)) {
+ red_channel_warning(get_channel(), "error: too large incoming message");
return NULL;
}
- return icc->priv->recv_buf;
+ return recv_buf;
}
-static void
-inputs_channel_client_release_msg_rcv_buf(RedChannelClient *rcc,
- uint16_t type, uint32_t size, uint8_t *msg)
+void InputsChannelClient::release_recv_buf(uint16_t type, uint32_t size, uint8_t *msg)
{
}
-static void inputs_channel_client_on_disconnect(RedChannelClient *rcc)
+void InputsChannelClient::on_disconnect()
{
- if (!rcc) {
- return;
- }
- inputs_release_keys(INPUTS_CHANNEL(rcc->get_channel()));
-}
-
-static void
-inputs_channel_client_class_init(InputsChannelClientClass *klass)
-{
- RedChannelClientClass *client_class = RED_CHANNEL_CLIENT_CLASS(klass);
-
- client_class->alloc_recv_buf = inputs_channel_client_alloc_msg_rcv_buf;
- client_class->release_recv_buf = inputs_channel_client_release_msg_rcv_buf;
- client_class->on_disconnect = inputs_channel_client_on_disconnect;
-}
-
-static void
-inputs_channel_client_init(InputsChannelClient *self)
-{
- self->priv = (InputsChannelClientPrivate *) inputs_channel_client_get_instance_private(self);
+ inputs_release_keys(INPUTS_CHANNEL(get_channel()));
}
RedChannelClient* inputs_channel_client_create(RedChannel *channel,
@@ -89,17 +46,11 @@ RedChannelClient* inputs_channel_client_create(RedChannel *channel,
RedStream *stream,
RedChannelCapabilities *caps)
{
- RedChannelClient *rcc;
-
- rcc = (RedChannelClient *)
- g_initable_new(TYPE_INPUTS_CHANNEL_CLIENT,
- NULL, NULL,
- "channel", channel,
- "client", client,
- "stream", stream,
- "caps", caps,
- NULL);
-
+ auto rcc = new InputsChannelClient(channel, client, stream, caps);
+ if (!rcc->init()) {
+ delete rcc;
+ rcc = nullptr;
+ }
return rcc;
}
@@ -113,16 +64,16 @@ void inputs_channel_client_send_migrate_data(RedChannelClient *rcc,
spice_marshaller_add_uint32(m, SPICE_MIGRATE_DATA_INPUTS_MAGIC);
spice_marshaller_add_uint32(m, SPICE_MIGRATE_DATA_INPUTS_VERSION);
- spice_marshaller_add_uint16(m, icc->priv->motion_count);
+ spice_marshaller_add_uint16(m, icc->motion_count);
}
void inputs_channel_client_handle_migrate_data(InputsChannelClient *icc,
uint16_t motion_count)
{
- icc->priv->motion_count = motion_count;
+ icc->motion_count = motion_count;
- for (; icc->priv->motion_count >= SPICE_INPUT_MOTION_ACK_BUNCH;
- icc->priv->motion_count -= SPICE_INPUT_MOTION_ACK_BUNCH) {
+ for (; icc->motion_count >= SPICE_INPUT_MOTION_ACK_BUNCH;
+ icc->motion_count -= SPICE_INPUT_MOTION_ACK_BUNCH) {
icc->pipe_add_type(RED_PIPE_ITEM_MOUSE_MOTION_ACK);
}
}
@@ -131,9 +82,9 @@ void inputs_channel_client_on_mouse_motion(InputsChannelClient *icc)
{
InputsChannel *inputs_channel = INPUTS_CHANNEL(icc->get_channel());
- if (++icc->priv->motion_count % SPICE_INPUT_MOTION_ACK_BUNCH == 0 &&
+ if (++icc->motion_count % SPICE_INPUT_MOTION_ACK_BUNCH == 0 &&
!inputs_channel_is_src_during_migrate(inputs_channel)) {
icc->pipe_add_type(RED_PIPE_ITEM_MOUSE_MOTION_ACK);
- icc->priv->motion_count = 0;
+ icc->motion_count = 0;
}
}
diff --git a/server/inputs-channel-client.h b/server/inputs-channel-client.h
index 4d979a05..141383b2 100644
--- a/server/inputs-channel-client.h
+++ b/server/inputs-channel-client.h
@@ -18,31 +18,34 @@
#ifndef INPUTS_CHANNEL_CLIENT_H_
#define INPUTS_CHANNEL_CLIENT_H_
-#include <glib-object.h>
-
#include "red-channel-client.h"
#include "inputs-channel.h"
G_BEGIN_DECLS
-#define TYPE_INPUTS_CHANNEL_CLIENT inputs_channel_client_get_type()
-
-#define INPUTS_CHANNEL_CLIENT(obj) \
- (G_TYPE_CHECK_INSTANCE_CAST((obj), TYPE_INPUTS_CHANNEL_CLIENT, InputsChannelClient))
+// TODO: RECEIVE_BUF_SIZE used to be the same for inputs_channel and main_channel
+// since it was defined once in reds.c which contained both.
+// Now that they are split we can give a more fitting value for inputs - what
+// should it be?
+#define REDS_AGENT_WINDOW_SIZE 10
+#define REDS_NUM_INTERNAL_AGENT_MESSAGES 1
-struct InputsChannelClientPrivate;
+// approximate max receive message size
+#define RECEIVE_BUF_SIZE \
+ (4096 + (REDS_AGENT_WINDOW_SIZE + REDS_NUM_INTERNAL_AGENT_MESSAGES) * SPICE_AGENT_MAX_DATA_SIZE)
-struct InputsChannelClient final: public RedChannelClient
+class InputsChannelClient final: public RedChannelClient
{
- InputsChannelClientPrivate *priv;
-};
+ uint8_t recv_buf[RECEIVE_BUF_SIZE];
+public:
+ uint16_t motion_count; // XXX private
-struct InputsChannelClientClass
-{
- RedChannelClientClass parent_class;
-};
+ using RedChannelClient::RedChannelClient;
-GType inputs_channel_client_get_type(void) G_GNUC_CONST;
+ virtual uint8_t *alloc_recv_buf(uint16_t type, uint32_t size) override;
+ virtual void release_recv_buf(uint16_t type, uint32_t size, uint8_t *msg) override;
+ virtual void on_disconnect() override;
+};
RedChannelClient* inputs_channel_client_create(RedChannel *channel,
RedClient *client,
diff --git a/server/inputs-channel.cpp b/server/inputs-channel.cpp
index 67ead1db..9199eead 100644
--- a/server/inputs-channel.cpp
+++ b/server/inputs-channel.cpp
@@ -40,6 +40,8 @@
#include "migration-protocol.h"
#include "utils.h"
+XXX_CAST(RedChannelClient, InputsChannelClient, INPUTS_CHANNEL_CLIENT);
+
struct InputsChannel final: public RedChannel
{
VDAgentMouseState mouse_state;
diff --git a/server/main-channel-client.cpp b/server/main-channel-client.cpp
index f5e7c643..3d8cf6b6 100644
--- a/server/main-channel-client.cpp
+++ b/server/main-channel-client.cpp
@@ -43,24 +43,24 @@ typedef enum {
(4096 + (REDS_AGENT_WINDOW_SIZE + REDS_NUM_INTERNAL_AGENT_MESSAGES) * SPICE_AGENT_MAX_DATA_SIZE)
struct MainChannelClientPrivate {
+ SPICE_CXX_GLIB_ALLOCATOR
+
uint32_t connection_id;
- uint32_t ping_id;
- uint32_t net_test_id;
- NetTestStage net_test_stage;
- uint64_t latency;
- uint64_t bitrate_per_sec;
- int mig_wait_connect;
- int mig_connect_ok;
- int mig_wait_prev_complete;
- int mig_wait_prev_try_seamless;
- int init_sent;
- int seamless_mig_dst;
- bool initial_channels_list_sent;
+ uint32_t ping_id = 0;
+ uint32_t net_test_id = 0;
+ NetTestStage net_test_stage = NET_TEST_STAGE_INVALID;
+ uint64_t latency = 0;
+ uint64_t bitrate_per_sec = ~0;
+ int mig_wait_connect = 0;
+ int mig_connect_ok = 0;
+ int mig_wait_prev_complete = 0;
+ int mig_wait_prev_try_seamless = 0;
+ int init_sent = 0;
+ int seamless_mig_dst = 0;
+ bool initial_channels_list_sent = false;
uint8_t recv_buf[MAIN_CHANNEL_RECEIVE_BUF_SIZE];
};
-G_DEFINE_TYPE_WITH_PRIVATE(MainChannelClient, main_channel_client, RED_TYPE_CHANNEL_CLIENT)
-
typedef struct RedPingPipeItem {
RedPipeItem base;
int size;
@@ -125,68 +125,23 @@ typedef struct RedRegisteredChannelPipeItem {
static const uint8_t zero_page[ZERO_BUF_SIZE] = {0};
-enum {
- PROP0,
- PROP_CONNECTION_ID
-};
-
-static void main_channel_client_get_property(GObject *object,
- guint property_id,
- GValue *value,
- GParamSpec *pspec)
-{
- MainChannelClient *self = MAIN_CHANNEL_CLIENT(object);
-
- switch (property_id)
- {
- case PROP_CONNECTION_ID:
- g_value_set_uint(value, self->priv->connection_id);
- break;
- default:
- G_OBJECT_WARN_INVALID_PROPERTY_ID(object, property_id, pspec);
- }
-}
-
-static void main_channel_client_set_property(GObject *object,
- guint property_id,
- const GValue *value,
- GParamSpec *pspec)
-{
- MainChannelClient *self = MAIN_CHANNEL_CLIENT(object);
-
- switch (property_id)
- {
- case PROP_CONNECTION_ID:
- self->priv->connection_id = g_value_get_uint(value);
- break;
- default:
- G_OBJECT_WARN_INVALID_PROPERTY_ID(object, property_id, pspec);
- }
-}
-
-static uint8_t *
-main_channel_client_alloc_msg_rcv_buf(RedChannelClient *rcc,
- uint16_t type, uint32_t size)
+uint8_t *MainChannelClient::alloc_recv_buf(uint16_t type, uint32_t size)
{
- MainChannelClient *mcc = MAIN_CHANNEL_CLIENT(rcc);
-
if (type == SPICE_MSGC_MAIN_AGENT_DATA) {
- RedChannel *channel = rcc->get_channel();
- return reds_get_agent_data_buffer(channel->get_server(), mcc, size);
- } else if (size > sizeof(mcc->priv->recv_buf)) {
+ RedChannel *channel = get_channel();
+ return reds_get_agent_data_buffer(channel->get_server(), this, size);
+ } else if (size > sizeof(priv->recv_buf)) {
/* message too large, caller will log a message and close the connection */
return NULL;
} else {
- return mcc->priv->recv_buf;
+ return priv->recv_buf;
}
}
-static void
-main_channel_client_release_msg_rcv_buf(RedChannelClient *rcc,
- uint16_t type, uint32_t size, uint8_t *msg)
+void MainChannelClient::release_recv_buf(uint16_t type, uint32_t size, uint8_t *msg)
{
if (type == SPICE_MSGC_MAIN_AGENT_DATA) {
- RedChannel *channel = rcc->get_channel();
+ RedChannel *channel = get_channel();
reds_release_agent_data_buffer(channel->get_server(), msg);
}
}
@@ -194,42 +149,11 @@ main_channel_client_release_msg_rcv_buf(RedChannelClient *rcc,
/*
* When the main channel is disconnected, disconnect the entire client.
*/
-static void main_channel_client_on_disconnect(RedChannelClient *rcc)
+void MainChannelClient::on_disconnect()
{
- RedsState *reds = rcc->get_channel()->get_server();
+ RedsState *reds = get_channel()->get_server();
main_dispatcher_client_disconnect(reds_get_main_dispatcher(reds),
- rcc->get_client());
-}
-
-static void main_channel_client_class_init(MainChannelClientClass *klass)
-{
- GObjectClass *object_class = G_OBJECT_CLASS(klass);
- RedChannelClientClass *client_class = RED_CHANNEL_CLIENT_CLASS(klass);
-
- object_class->get_property = main_channel_client_get_property;
- object_class->set_property = main_channel_client_set_property;
-
- client_class->alloc_recv_buf = main_channel_client_alloc_msg_rcv_buf;
- client_class->release_recv_buf = main_channel_client_release_msg_rcv_buf;
- client_class->on_disconnect = main_channel_client_on_disconnect;
-
- g_object_class_install_property(object_class,
- PROP_CONNECTION_ID,
- g_param_spec_uint("connection-id",
- "Connection ID",
- "Connection ID",
- 0,
- G_MAXUINT,
- 0,
- G_PARAM_CONSTRUCT_ONLY |
- G_PARAM_READWRITE |
- G_PARAM_STATIC_STRINGS));
-}
-
-static void main_channel_client_init(MainChannelClient *self)
-{
- self->priv = (MainChannelClientPrivate *) main_channel_client_get_instance_private(self);
- self->priv->bitrate_per_sec = ~0;
+ get_client());
}
static void main_channel_client_push_ping(MainChannelClient *mcc, int size);
@@ -602,22 +526,32 @@ gboolean main_channel_client_migrate_src_complete(MainChannelClient *mcc,
return ret;
}
+
+MainChannelClient::MainChannelClient(MainChannel *channel,
+ RedClient *client,
+ RedStream *stream,
+ RedChannelCapabilities *caps,
+ uint32_t connection_id):
+ RedChannelClient(RED_CHANNEL(channel), client, stream, caps),
+ priv(new MainChannelClientPrivate())
+{
+ priv->connection_id = connection_id;
+}
+
+MainChannelClient::~MainChannelClient()
+{
+ delete priv;
+}
+
MainChannelClient *main_channel_client_create(MainChannel *main_chan, RedClient *client,
RedStream *stream, uint32_t connection_id,
RedChannelCapabilities *caps)
{
- MainChannelClient *mcc;
-
- mcc = (MainChannelClient *)
- g_initable_new(TYPE_MAIN_CHANNEL_CLIENT,
- NULL, NULL,
- "channel", main_chan,
- "client", client,
- "stream", stream,
- "caps", caps,
- "connection-id", connection_id,
- NULL);
-
+ auto mcc = new MainChannelClient(main_chan, client, stream, caps, connection_id);
+ if (!mcc->init()) {
+ mcc->unref();
+ mcc = nullptr;
+ }
return mcc;
}
@@ -642,6 +576,8 @@ uint64_t main_channel_client_get_roundtrip_ms(MainChannelClient *mcc)
return mcc->priv->latency / 1000;
}
+XXX_CAST(RedChannelClient, MainChannelClient, MAIN_CHANNEL_CLIENT);
+
void main_channel_client_migrate(RedChannelClient *rcc)
{
RedChannel *channel = rcc->get_channel();
diff --git a/server/main-channel-client.h b/server/main-channel-client.h
index 2090b596..7653978d 100644
--- a/server/main-channel-client.h
+++ b/server/main-channel-client.h
@@ -18,7 +18,6 @@
#ifndef MAIN_CHANNEL_CLIENT_H_
#define MAIN_CHANNEL_CLIENT_H_
-#include <glib-object.h>
#include <common/messages.h>
#include "red-channel-client.h"
@@ -26,33 +25,25 @@
G_BEGIN_DECLS
-#define TYPE_MAIN_CHANNEL_CLIENT main_channel_client_get_type()
-
-#define MAIN_CHANNEL_CLIENT(obj) \
- (G_TYPE_CHECK_INSTANCE_CAST((obj), TYPE_MAIN_CHANNEL_CLIENT, MainChannelClient))
-#define MAIN_CHANNEL_CLIENT_CLASS(klass) \
- (G_TYPE_CHECK_CLASS_CAST((klass), TYPE_MAIN_CHANNEL_CLIENT, MainChannelClientClass))
-#define IS_MAIN_CHANNEL_CLIENT(obj) \
- (G_TYPE_CHECK_INSTANCE_TYPE((obj), TYPE_MAIN_CHANNEL_CLIENT))
-#define IS_MAIN_CHANNEL_CLIENT_CLASS(klass) \
- (G_TYPE_CHECK_CLASS_TYPE((klass), TYPE_MAIN_CHANNEL_CLIENT))
-#define MAIN_CHANNEL_CLIENT_GET_CLASS(obj) \
- (G_TYPE_INSTANCE_GET_CLASS((obj), TYPE_MAIN_CHANNEL_CLIENT, MainChannelClientClass))
-
struct MainChannelClientPrivate;
-struct MainChannelClient final: public RedChannelClient
-{
- MainChannelClientPrivate *priv;
-};
-
-struct MainChannelClientClass
+class MainChannelClient final: public RedChannelClient
{
- RedChannelClientClass parent_class;
+protected:
+ ~MainChannelClient();
+public:
+ MainChannelClient(MainChannel *channel,
+ RedClient *client,
+ RedStream *stream,
+ RedChannelCapabilities *caps,
+ uint32_t connection_id);
+
+ virtual uint8_t *alloc_recv_buf(uint16_t type, uint32_t size) override;
+ virtual void release_recv_buf(uint16_t type, uint32_t size, uint8_t *msg) override;
+ virtual void on_disconnect() override;
+ MainChannelClientPrivate *const priv = nullptr;
};
-GType main_channel_client_get_type(void) G_GNUC_CONST;
-
MainChannelClient *main_channel_client_create(MainChannel *main_chan, RedClient *client,
RedStream *stream, uint32_t connection_id,
RedChannelCapabilities *caps);
diff --git a/server/main-channel.cpp b/server/main-channel.cpp
index f867254f..8764cc84 100644
--- a/server/main-channel.cpp
+++ b/server/main-channel.cpp
@@ -45,6 +45,8 @@ int main_channel_is_connected(MainChannel *main_chan)
return main_chan && main_chan->is_connected();
}
+XXX_CAST(RedChannelClient, MainChannelClient, MAIN_CHANNEL_CLIENT);
+
RedClient *main_channel_get_client_by_link_id(MainChannel *main_chan, uint32_t connection_id)
{
RedChannelClient *rcc;
diff --git a/server/red-channel-client.cpp b/server/red-channel-client.cpp
index b60b89d8..5b10a7ff 100644
--- a/server/red-channel-client.cpp
+++ b/server/red-channel-client.cpp
@@ -115,6 +115,8 @@ typedef struct IncomingMessageBuffer {
struct RedChannelClientPrivate
{
+ SPICE_CXX_GLIB_ALLOCATOR
+
RedChannel *channel;
RedClient *client;
RedStream *stream;
@@ -196,9 +198,7 @@ static const SpiceDataHeaderOpaque mini_header_wrapper = {NULL, sizeof(SpiceMini
mini_header_get_msg_size};
static void red_channel_client_clear_sent_item(RedChannelClient *rcc);
-static void red_channel_client_initable_interface_init(GInitableIface *iface);
static void red_channel_client_set_message_serial(RedChannelClient *channel, uint64_t);
-static bool red_channel_client_config_socket(RedChannelClient *rcc);
/*
* When an error occurs over a channel, we treat it as a warning
@@ -210,24 +210,6 @@ static bool red_channel_client_config_socket(RedChannelClient *rcc);
rcc->shutdown(); \
} while (0)
-G_DEFINE_TYPE_WITH_CODE(RedChannelClient, red_channel_client, G_TYPE_OBJECT,
- G_IMPLEMENT_INTERFACE(G_TYPE_INITABLE,
- red_channel_client_initable_interface_init);
- G_ADD_PRIVATE(RedChannelClient));
-
-static gboolean red_channel_client_initable_init(GInitable *initable,
- GCancellable *cancellable,
- GError **error);
-
-enum {
- PROP0,
- PROP_STREAM,
- PROP_CHANNEL,
- PROP_CLIENT,
- PROP_MONITOR_LATENCY,
- PROP_CAPS
-};
-
#define PING_TEST_TIMEOUT_MS (MSEC_PER_SEC * 15)
#define PING_TEST_LONG_TIMEOUT_MS (MSEC_PER_SEC * 60 * 5)
#define PING_TEST_IDLE_NET_TIMEOUT_MS (MSEC_PER_SEC / 10)
@@ -284,112 +266,60 @@ static void red_channel_client_restart_ping_timer(RedChannelClient *rcc)
red_channel_client_start_ping_timer(rcc, timeout);
}
-static void
-red_channel_client_get_property(GObject *object,
- guint property_id,
- GValue *value,
- GParamSpec *pspec)
+RedChannelClient::~RedChannelClient()
{
- RedChannelClient *self = RED_CHANNEL_CLIENT(object);
+ red_timer_remove(priv->latency_monitor.timer);
+ priv->latency_monitor.timer = NULL;
- switch (property_id)
- {
- case PROP_STREAM:
- g_value_set_pointer(value, self->priv->stream);
- break;
- case PROP_CHANNEL:
- g_value_set_object(value, self->priv->channel);
- break;
- case PROP_CLIENT:
- g_value_set_object(value, self->priv->client);
- break;
- case PROP_MONITOR_LATENCY:
- g_value_set_boolean(value, self->priv->monitor_latency);
- break;
- default:
- G_OBJECT_WARN_INVALID_PROPERTY_ID(object, property_id, pspec);
+ red_timer_remove(priv->connectivity_monitor.timer);
+ priv->connectivity_monitor.timer = NULL;
+
+ red_stream_free(priv->stream);
+ priv->stream = NULL;
+
+ if (priv->send_data.main.marshaller) {
+ spice_marshaller_destroy(priv->send_data.main.marshaller);
}
-}
-static void
-red_channel_client_set_property(GObject *object,
- guint property_id,
- const GValue *value,
- GParamSpec *pspec)
-{
- RedChannelClient *self = RED_CHANNEL_CLIENT(object);
+ if (priv->send_data.urgent.marshaller) {
+ spice_marshaller_destroy(priv->send_data.urgent.marshaller);
+ }
- switch (property_id)
- {
- case PROP_STREAM:
- self->priv->stream = (RedStream*) g_value_get_pointer(value);
- break;
- case PROP_CHANNEL:
- if (self->priv->channel)
- g_object_unref(self->priv->channel);
- self->priv->channel = (RedChannel *) g_value_dup_object(value);
- break;
- case PROP_CLIENT:
- self->priv->client = (RedClient *) g_value_get_object(value);
- break;
- case PROP_MONITOR_LATENCY:
- self->priv->monitor_latency = g_value_get_boolean(value);
- break;
- case PROP_CAPS:
- {
- RedChannelCapabilities *caps = (RedChannelCapabilities *) g_value_get_boxed(value);
- if (caps) {
- red_channel_capabilities_reset(&self->priv->remote_caps);
- red_channel_capabilities_init(&self->priv->remote_caps, caps);
- }
- }
- break;
- default:
- G_OBJECT_WARN_INVALID_PROPERTY_ID(object, property_id, pspec);
+ red_channel_capabilities_reset(&priv->remote_caps);
+ if (priv->channel) {
+ g_object_unref(priv->channel);
}
+ delete priv;
}
-static void
-red_channel_client_finalize(GObject *object)
+RedChannelClient::RedChannelClient(RedChannel *channel,
+ RedClient *client,
+ RedStream *stream,
+ RedChannelCapabilities *caps,
+ bool monitor_latency)
{
- RedChannelClient *self = RED_CHANNEL_CLIENT(object);
-
- red_timer_remove(self->priv->latency_monitor.timer);
- self->priv->latency_monitor.timer = NULL;
+ RedChannelClient *self = this;
- red_timer_remove(self->priv->connectivity_monitor.timer);
- self->priv->connectivity_monitor.timer = NULL;
+ // XXX initialize
+ priv = new RedChannelClientPrivate();
- red_stream_free(self->priv->stream);
- self->priv->stream = NULL;
+ // blocks send message (maybe use send_data.blocked + block flags)
+ self->priv->ack_data.messages_window = ~0;
+ self->priv->ack_data.client_generation = ~0;
+ self->priv->ack_data.client_window = CLIENT_ACK_WINDOW;
+ self->priv->send_data.main.marshaller = spice_marshaller_new();
+ self->priv->send_data.urgent.marshaller = spice_marshaller_new();
- if (self->priv->send_data.main.marshaller) {
- spice_marshaller_destroy(self->priv->send_data.main.marshaller);
- }
+ self->priv->send_data.marshaller = self->priv->send_data.main.marshaller;
- if (self->priv->send_data.urgent.marshaller) {
- spice_marshaller_destroy(self->priv->send_data.urgent.marshaller);
- }
+ g_queue_init(&self->priv->pipe);
red_channel_capabilities_reset(&self->priv->remote_caps);
- if (self->priv->channel) {
- g_object_unref(self->priv->channel);
- }
+ red_channel_capabilities_init(&self->priv->remote_caps, caps);
- G_OBJECT_CLASS(red_channel_client_parent_class)->finalize(object);
-}
-
-static void red_channel_client_initable_interface_init(GInitableIface *iface)
-{
- iface->init = red_channel_client_initable_init;
-}
-
-static void red_channel_client_constructed(GObject *object)
-{
- RedChannelClient *self = RED_CHANNEL_CLIENT(object);
-
- RedChannelClientClass *klass = RED_CHANNEL_CLIENT_GET_CLASS(self);
- spice_assert(klass->alloc_recv_buf && klass->release_recv_buf);
+ priv->channel = (RedChannel*) g_object_ref(channel);
+ priv->client = client;
+ priv->stream = stream;
self->priv->outgoing.pos = 0;
self->priv->outgoing.size = 0;
@@ -405,81 +335,12 @@ static void red_channel_client_constructed(GObject *object)
}
self->priv->incoming.header.data = self->priv->incoming.header_buf;
- RedChannel *channel = self->priv->channel;
RedsState* reds = channel->get_server();
const RedStatNode *node = channel->get_stat_node();
stat_init_counter(&self->priv->out_messages, reds, node, "out_messages", TRUE);
stat_init_counter(&self->priv->out_bytes, reds, node, "out_bytes", TRUE);
}
-static void red_channel_client_class_init(RedChannelClientClass *klass)
-{
- GObjectClass *object_class = G_OBJECT_CLASS(klass);
- GParamSpec *spec;
-
- g_debug("%s", G_STRFUNC);
-
- object_class->get_property = red_channel_client_get_property;
- object_class->set_property = red_channel_client_set_property;
- object_class->finalize = red_channel_client_finalize;
- object_class->constructed = red_channel_client_constructed;
-
- spec = g_param_spec_pointer("stream", "stream",
- "Associated RedStream",
- G_PARAM_STATIC_STRINGS
- | G_PARAM_READWRITE
- | G_PARAM_CONSTRUCT_ONLY);
- g_object_class_install_property(object_class, PROP_STREAM, spec);
-
- spec = g_param_spec_object("channel", "channel",
- "Associated RedChannel",
- RED_TYPE_CHANNEL,
- G_PARAM_STATIC_STRINGS
- | G_PARAM_READWRITE
- | G_PARAM_CONSTRUCT_ONLY);
- g_object_class_install_property(object_class, PROP_CHANNEL, spec);
-
- spec = g_param_spec_object("client", "client",
- "Associated RedClient",
- RED_TYPE_CLIENT,
- G_PARAM_STATIC_STRINGS
- | G_PARAM_READWRITE
- | G_PARAM_CONSTRUCT_ONLY);
- g_object_class_install_property(object_class, PROP_CLIENT, spec);
-
- spec = g_param_spec_boolean("monitor-latency", "monitor-latency",
- "Whether to monitor latency for this client",
- FALSE,
- G_PARAM_STATIC_STRINGS
- | G_PARAM_READWRITE
- | G_PARAM_CONSTRUCT_ONLY);
- g_object_class_install_property(object_class, PROP_MONITOR_LATENCY, spec);
-
- spec = g_param_spec_boxed("caps", "caps",
- "Capabilities",
- RED_TYPE_CHANNEL_CAPABILITIES,
- G_PARAM_STATIC_STRINGS
- | G_PARAM_WRITABLE
- | G_PARAM_CONSTRUCT_ONLY);
- g_object_class_install_property(object_class, PROP_CAPS, spec);
-}
-
-static void
-red_channel_client_init(RedChannelClient *self)
-{
- self->priv = (RedChannelClientPrivate *) red_channel_client_get_instance_private(self);
- // blocks send message (maybe use send_data.blocked + block flags)
- self->priv->ack_data.messages_window = ~0;
- self->priv->ack_data.client_generation = ~0;
- self->priv->ack_data.client_window = CLIENT_ACK_WINDOW;
- self->priv->send_data.main.marshaller = spice_marshaller_new();
- self->priv->send_data.urgent.marshaller = spice_marshaller_new();
-
- self->priv->send_data.marshaller = self->priv->send_data.main.marshaller;
-
- g_queue_init(&self->priv->pipe);
-}
-
RedChannel* RedChannelClient::get_channel()
{
return priv->channel;
@@ -912,13 +773,11 @@ static void mini_header_set_msg_sub_list(SpiceDataHeaderOpaque *header, uint32_t
spice_error("attempt to set header sub list on mini header");
}
-static gboolean red_channel_client_initable_init(GInitable *initable,
- GCancellable *cancellable,
- GError **error)
+bool RedChannelClient::init()
{
GError *local_error = NULL;
SpiceCoreInterfaceInternal *core;
- RedChannelClient *self = RED_CHANNEL_CLIENT(initable);
+ RedChannelClient *self = this;
if (!self->priv->stream) {
g_set_error_literal(&local_error,
@@ -928,7 +787,7 @@ static gboolean red_channel_client_initable_init(GInitable *initable,
goto cleanup;
}
- if (!red_channel_client_config_socket(self)) {
+ if (!self->config_socket()) {
g_set_error_literal(&local_error,
SPICE_SERVER_ERROR,
SPICE_SERVER_ERROR_FAILED,
@@ -967,7 +826,7 @@ cleanup:
red_channel_warning(self->get_channel(),
"Failed to create channel client: %s",
local_error->message);
- g_propagate_error(error, local_error);
+ g_error_free(local_error);
}
return local_error == NULL;
}
@@ -1048,34 +907,6 @@ void RedChannelClient::shutdown()
}
}
-static bool red_channel_client_config_socket(RedChannelClient *rcc)
-{
- RedChannelClientClass *klass = RED_CHANNEL_CLIENT_GET_CLASS(rcc);
-
- if (!klass->config_socket) {
- return TRUE;
- }
-
- return klass->config_socket(rcc);
-}
-
-static uint8_t *red_channel_client_alloc_msg_buf(RedChannelClient *rcc,
- uint16_t type, uint32_t size)
-{
- RedChannelClientClass *klass = RED_CHANNEL_CLIENT_GET_CLASS(rcc);
-
- return klass->alloc_recv_buf(rcc, type, size);
-}
-
-static void red_channel_client_release_msg_buf(RedChannelClient *rcc,
- uint16_t type, uint32_t size,
- uint8_t *msg)
-{
- RedChannelClientClass *klass = RED_CHANNEL_CLIENT_GET_CLASS(rcc);
-
- klass->release_recv_buf(rcc, type, size, msg);
-}
-
static void red_channel_client_handle_outgoing(RedChannelClient *rcc)
{
RedStream *stream = rcc->priv->stream;
@@ -1221,7 +1052,7 @@ static void red_channel_client_handle_incoming(RedChannelClient *rcc)
msg_type = buffer->header.get_msg_type(&buffer->header);
if (buffer->msg_pos < msg_size) {
if (!buffer->msg) {
- buffer->msg = red_channel_client_alloc_msg_buf(rcc, msg_type, msg_size);
+ buffer->msg = rcc->alloc_recv_buf(msg_type, msg_size);
if (buffer->msg == NULL && rcc->priv->block_read) {
// if we are blocked by flow control just return, message will be read
// when data will be available
@@ -1238,8 +1069,7 @@ static void red_channel_client_handle_incoming(RedChannelClient *rcc)
buffer->msg + buffer->msg_pos,
msg_size - buffer->msg_pos);
if (bytes_read == -1) {
- red_channel_client_release_msg_buf(rcc, msg_type, msg_size,
- buffer->msg);
+ rcc->release_recv_buf(msg_type, msg_size, buffer->msg);
buffer->msg = NULL;
rcc->disconnect();
return;
@@ -1257,9 +1087,7 @@ static void red_channel_client_handle_incoming(RedChannelClient *rcc)
&parsed_size, &parsed_free);
if (parsed == NULL) {
red_channel_warning(channel, "failed to parse message type %d", msg_type);
- red_channel_client_release_msg_buf(rcc,
- msg_type, msg_size,
- buffer->msg);
+ rcc->release_recv_buf(msg_type, msg_size, buffer->msg);
buffer->msg = NULL;
rcc->disconnect();
return;
@@ -1270,9 +1098,7 @@ static void red_channel_client_handle_incoming(RedChannelClient *rcc)
parsed_free(parsed);
}
buffer->msg_pos = 0;
- red_channel_client_release_msg_buf(rcc,
- msg_type, msg_size,
- buffer->msg);
+ rcc->release_recv_buf(msg_type, msg_size, buffer->msg);
buffer->msg = NULL;
buffer->header_pos = 0;
@@ -1711,15 +1537,6 @@ void RedChannelClient::push_set_ack()
pipe_add_type(RED_PIPE_ITEM_TYPE_SET_ACK);
}
-static void red_channel_client_on_disconnect(RedChannelClient *rcc)
-{
- RedChannelClientClass *klass = RED_CHANNEL_CLIENT_GET_CLASS(rcc);
-
- if (klass->on_disconnect != NULL) {
- klass->on_disconnect(rcc);
- }
-}
-
void RedChannelClient::disconnect()
{
RedChannel *channel = priv->channel;
@@ -1738,7 +1555,7 @@ void RedChannelClient::disconnect()
priv->connectivity_monitor.timer = NULL;
channel->remove_client(this);
- red_channel_client_on_disconnect(this);
+ on_disconnect();
// remove client from RedClient
// NOTE this may trigger the free of the object, if we are in a watch/timer
// we should make sure we keep a reference
diff --git a/server/red-channel-client.h b/server/red-channel-client.h
index 102074ec..d38cad60 100644
--- a/server/red-channel-client.h
+++ b/server/red-channel-client.h
@@ -18,8 +18,6 @@
#ifndef RED_CHANNEL_CLIENT_H_
#define RED_CHANNEL_CLIENT_H_
-#include <glib-object.h>
-#include <gio/gio.h>
#include <common/marshaller.h>
#include "red-pipe-item.h"
@@ -28,12 +26,28 @@
G_BEGIN_DECLS
-#define RED_TYPE_CHANNEL_CLIENT red_channel_client_get_type()
+struct RedChannelClientPrivate;
-SPICE_DECLARE_TYPE(RedChannelClient, red_channel_client, CHANNEL_CLIENT);
-
-struct RedChannelClient: public GObject
+class RedChannelClient
{
+public:
+ SPICE_CXX_GLIB_ALLOCATOR
+
+ // This is made protected to avoid allocation on stack conflicting with
+ // reference counting
+protected:
+ virtual ~RedChannelClient();
+
+public:
+ RedChannelClient(RedChannel *channel,
+ RedClient *client,
+ RedStream *stream,
+ RedChannelCapabilities *caps,
+ bool monitor_latency=false);
+ virtual bool init();
+
+ RedChannelClientPrivate *priv = nullptr;
+
bool is_connected() const;
static void default_migrate(RedChannelClient *rcc);
bool is_waiting_for_migrate_data() const;
@@ -137,22 +151,19 @@ struct RedChannelClient: public GObject
void block_read();
void unblock_read();
- void ref() { g_object_ref(this); }
- void unref() { g_object_unref(this); }
-
- RedChannelClientPrivate *priv;
-};
-
-struct RedChannelClientClass
-{
- GObjectClass parent_class;
+ void ref() { g_atomic_int_inc(&_ref); }
+ void unref() { if (g_atomic_int_dec_and_test(&_ref)) delete this; }
/* configure socket connected to the client */
- bool (*config_socket)(RedChannelClient *rcc);
- uint8_t *(*alloc_recv_buf)(RedChannelClient *channel, uint16_t type, uint32_t size);
- void (*release_recv_buf)(RedChannelClient *channel, uint16_t type, uint32_t size, uint8_t *msg);
+ virtual bool config_socket() { return true; }
+ virtual uint8_t *alloc_recv_buf(uint16_t type, uint32_t size)=0;
+ virtual void release_recv_buf(uint16_t type, uint32_t size, uint8_t *msg)=0;
+
+ virtual void on_disconnect() {};
- void (*on_disconnect)(RedChannelClient *rcc);
+ /* Private data */
+private:
+ gint _ref = 1;
};
#define SPICE_SERVER_ERROR spice_server_error_quark()
diff --git a/server/red-common.h b/server/red-common.h
index 378be9f4..68e9be0a 100644
--- a/server/red-common.h
+++ b/server/red-common.h
@@ -128,6 +128,20 @@ typedef struct GListIter {
{ return G_TYPE_INSTANCE_GET_CLASS(obj, \
module_obj_name ## _get_type(), ModuleObjName ## Class); }
+/* This macro allows to use GLib for a class hieranrchy allocation.
+ * The aims are:
+ * - do not depend on C++ runtime, just C;
+ * - do not throw memory exception from a C library;
+ * - zero out the structure like GOject did, we are not still
+ * initializing automatically all members;
+ * - do not allow to allocate array of this type, do not mix fine
+ * with reference counting and inheritance.
+ */
+#define SPICE_CXX_GLIB_ALLOCATOR \
+ void *operator new(size_t size) { return g_malloc0(size); } \
+ void operator delete(void *p) { g_free(p); } \
+ void* operator new[](size_t count);
+
#ifdef __cplusplus
#include <glib-object.h>
@@ -137,6 +151,12 @@ inline GParamFlags operator|(GParamFlags a, GParamFlags b)
}
#endif
+// XXX todo remove, just for easy portability
+#define XXX_CAST(from, to, name) \
+static inline to* name(from *p) { \
+ return p ? static_cast<to*>(p) : nullptr; \
+}
+
SPICE_END_DECLS
#endif /* RED_COMMON_H_ */
diff --git a/server/smartcard-channel-client.cpp b/server/smartcard-channel-client.cpp
index ac825ab9..6cfbeacb 100644
--- a/server/smartcard-channel-client.cpp
+++ b/server/smartcard-channel-client.cpp
@@ -20,140 +20,111 @@
#include "smartcard-channel-client.h"
+XXX_CAST(RedChannelClient, SmartCardChannelClient, SMARTCARD_CHANNEL_CLIENT)
+
struct SmartCardChannelClientPrivate
{
- RedCharDeviceSmartcard *smartcard;
+ SPICE_CXX_GLIB_ALLOCATOR
+
+ RedCharDeviceSmartcard *smartcard = nullptr;
/* read_from_client/write_to_device buffer.
* The beginning of the buffer should always be VSCMsgHeader*/
- RedCharDeviceWriteBuffer *write_buf;
- int msg_in_write_buf; /* was the client msg received into a RedCharDeviceWriteBuffer
- * or was it explicitly malloced */
+ RedCharDeviceWriteBuffer *write_buf = nullptr;
+ /* was the client msg received into a RedCharDeviceWriteBuffer
+ * or was it explicitly malloced */
+ bool msg_in_write_buf = false;
};
-G_DEFINE_TYPE_WITH_PRIVATE(SmartCardChannelClient, smart_card_channel_client,
- RED_TYPE_CHANNEL_CLIENT)
-
typedef struct RedErrorItem {
RedPipeItem base;
VSCMsgHeader vheader;
VSCMsgError error;
} RedErrorItem;
-static uint8_t *
-smartcard_channel_client_alloc_msg_rcv_buf(RedChannelClient *rcc, uint16_t type, uint32_t size);
-static void
-smartcard_channel_client_release_msg_rcv_buf(RedChannelClient *rcc, uint16_t type,
- uint32_t size, uint8_t *msg);
-static void smartcard_channel_client_on_disconnect(RedChannelClient *rcc);
-
-static void smart_card_channel_client_finalize(GObject *object)
-{
- SmartCardChannelClient *self = SMARTCARD_CHANNEL_CLIENT(object);
-
- if (self->priv->smartcard)
- g_object_remove_weak_pointer(G_OBJECT(self->priv->smartcard),
- (gpointer*)&self->priv->smartcard);
- G_OBJECT_CLASS(smart_card_channel_client_parent_class)->finalize(object);
-}
-
-static void smart_card_channel_client_class_init(SmartCardChannelClientClass *klass)
+SmartCardChannelClient::SmartCardChannelClient(RedChannel *channel,
+ RedClient *client,
+ RedStream *stream,
+ RedChannelCapabilities *caps):
+ RedChannelClient(channel, client, stream, caps),
+ priv(new SmartCardChannelClientPrivate())
{
- GObjectClass *object_class = G_OBJECT_CLASS(klass);
-
- RedChannelClientClass *client_class = RED_CHANNEL_CLIENT_CLASS(klass);
- client_class->alloc_recv_buf = smartcard_channel_client_alloc_msg_rcv_buf;
- client_class->release_recv_buf = smartcard_channel_client_release_msg_rcv_buf;
- client_class->on_disconnect = smartcard_channel_client_on_disconnect;
-
- object_class->finalize = smart_card_channel_client_finalize;
}
-static void
-smart_card_channel_client_init(SmartCardChannelClient *self)
+SmartCardChannelClient::~SmartCardChannelClient()
{
- self->priv = (SmartCardChannelClientPrivate*)
- smart_card_channel_client_get_instance_private(self);
+ if (priv->smartcard) {
+ g_object_remove_weak_pointer(G_OBJECT(priv->smartcard),
+ (gpointer*)&priv->smartcard);
+ }
+ delete priv;
}
SmartCardChannelClient* smartcard_channel_client_create(RedChannel *channel,
RedClient *client, RedStream *stream,
RedChannelCapabilities *caps)
{
- SmartCardChannelClient *rcc;
-
- rcc = (SmartCardChannelClient *)
- g_initable_new(TYPE_SMARTCARD_CHANNEL_CLIENT,
- NULL, NULL,
- "channel", channel,
- "client", client,
- "stream", stream,
- "caps", caps,
- NULL);
-
+ auto rcc = new SmartCardChannelClient(channel, client, stream, caps);
+ if (!rcc->init()) {
+ rcc->unref();
+ rcc = nullptr;
+ }
return rcc;
}
-static uint8_t *
-smartcard_channel_client_alloc_msg_rcv_buf(RedChannelClient *rcc,
- uint16_t type, uint32_t size)
+uint8_t *
+SmartCardChannelClient::alloc_recv_buf(uint16_t type, uint32_t size)
{
- SmartCardChannelClient *scc = SMARTCARD_CHANNEL_CLIENT(rcc);
-
/* TODO: only one reader is actually supported. When we fix the code to support
* multiple readers, we will probably associate different devices to
* different channels */
- if (!scc->priv->smartcard) {
- scc->priv->msg_in_write_buf = FALSE;
- return (uint8_t*) g_malloc(size);
+ if (!priv->smartcard) {
+ priv->msg_in_write_buf = FALSE;
+ return (uint8_t *) g_malloc(size);
} else {
RedCharDeviceSmartcard *smartcard;
spice_assert(smartcard_get_n_readers() == 1);
- smartcard = scc->priv->smartcard;
- spice_assert(smartcard_char_device_get_client(smartcard) || scc->priv->smartcard);
- spice_assert(!scc->priv->write_buf);
- scc->priv->write_buf =
- red_char_device_write_buffer_get_client(RED_CHAR_DEVICE(smartcard), rcc, size);
+ smartcard = priv->smartcard;
+ spice_assert(smartcard_char_device_get_client(smartcard) || priv->smartcard);
+ spice_assert(!priv->write_buf);
+ priv->write_buf =
+ red_char_device_write_buffer_get_client(RED_CHAR_DEVICE(smartcard), this, size);
- if (!scc->priv->write_buf) {
+ if (!priv->write_buf) {
spice_error("failed to allocate write buffer");
return NULL;
}
- scc->priv->msg_in_write_buf = TRUE;
- return scc->priv->write_buf->buf;
+ priv->msg_in_write_buf = TRUE;
+ return priv->write_buf->buf;
}
}
-static void
-smartcard_channel_client_release_msg_rcv_buf(RedChannelClient *rcc,
- uint16_t type, uint32_t size, uint8_t *msg)
+void
+SmartCardChannelClient::release_recv_buf(uint16_t type, uint32_t size, uint8_t *msg)
{
- SmartCardChannelClient *scc = SMARTCARD_CHANNEL_CLIENT(rcc);
-
/* todo: only one reader is actually supported. When we fix the code to support
* multiple readers, we will porbably associate different devices to
* differenc channels */
- if (!scc->priv->msg_in_write_buf) {
- spice_assert(!scc->priv->write_buf);
+ if (!priv->msg_in_write_buf) {
+ spice_assert(!priv->write_buf);
g_free(msg);
} else {
- if (scc->priv->write_buf) { /* msg hasn't been pushed to the guest */
- spice_assert(scc->priv->write_buf->buf == msg);
- red_char_device_write_buffer_release(RED_CHAR_DEVICE(scc->priv->smartcard),
- &scc->priv->write_buf);
+ if (priv->write_buf) { /* msg hasn't been pushed to the guest */
+ spice_assert(priv->write_buf->buf == msg);
+ red_char_device_write_buffer_release(RED_CHAR_DEVICE(priv->smartcard),
+ &priv->write_buf);
}
}
}
-static void smartcard_channel_client_on_disconnect(RedChannelClient *rcc)
+void SmartCardChannelClient::on_disconnect()
{
- SmartCardChannelClient *scc = SMARTCARD_CHANNEL_CLIENT(rcc);
- RedCharDeviceSmartcard *device = scc->priv->smartcard;
+ RedCharDeviceSmartcard *device = priv->smartcard;
if (device) {
- smartcard_char_device_detach_client(device, scc);
+ smartcard_char_device_detach_client(device, this);
smartcard_char_device_notify_reader_remove(device);
}
}
diff --git a/server/smartcard-channel-client.h b/server/smartcard-channel-client.h
index c0b340db..b7e8de26 100644
--- a/server/smartcard-channel-client.h
+++ b/server/smartcard-channel-client.h
@@ -18,39 +18,29 @@
#ifndef SMARTCARD_CHANNEL_CLIENT_H_
#define SMARTCARD_CHANNEL_CLIENT_H_
-#include <glib-object.h>
-
#include "smartcard.h"
G_BEGIN_DECLS
-#define TYPE_SMARTCARD_CHANNEL_CLIENT smart_card_channel_client_get_type()
-
-#define SMARTCARD_CHANNEL_CLIENT(obj) \
- (G_TYPE_CHECK_INSTANCE_CAST((obj), TYPE_SMARTCARD_CHANNEL_CLIENT, SmartCardChannelClient))
-#define SMARTCARD_CHANNEL_CLIENT_CLASS(klass) \
- (G_TYPE_CHECK_CLASS_CAST((klass), TYPE_SMARTCARD_CHANNEL_CLIENT, SmartCardChannelClientClass))
-#define IS_SMARTCARD_CHANNEL_CLIENT(obj) \
- (G_TYPE_CHECK_INSTANCE_TYPE((obj), TYPE_SMARTCARD_CHANNEL_CLIENT))
-#define IS_SMARTCARD_CHANNEL_CLIENT_CLASS(klass) \
- (G_TYPE_CHECK_CLASS_TYPE((klass), TYPE_SMARTCARD_CHANNEL_CLIENT))
-#define SMARTCARD_CHANNEL_CLIENT_GET_CLASS(obj) \
- (G_TYPE_INSTANCE_GET_CLASS((obj), TYPE_SMARTCARD_CHANNEL_CLIENT, SmartCardChannelClientClass))
-
struct SmartCardChannelClientPrivate;
-struct SmartCardChannelClient final: public RedChannelClient
+class SmartCardChannelClient final: public RedChannelClient
{
- SmartCardChannelClientPrivate *priv;
+protected:
+ ~SmartCardChannelClient();
+public:
+ SmartCardChannelClientPrivate *const priv = nullptr;
+ SmartCardChannelClient(RedChannel *channel,
+ RedClient *client,
+ RedStream *stream,
+ RedChannelCapabilities *caps);
+
+private:
+ virtual uint8_t *alloc_recv_buf(uint16_t type, uint32_t size) override;
+ virtual void release_recv_buf(uint16_t type, uint32_t size, uint8_t *msg) override;
+ virtual void on_disconnect() override;
};
-struct SmartCardChannelClientClass
-{
- RedChannelClientClass parent_class;
-};
-
-GType smart_card_channel_client_get_type(void) G_GNUC_CONST;
-
SmartCardChannelClient* smartcard_channel_client_create(RedChannel *channel,
RedClient *client, RedStream *stream,
RedChannelCapabilities *caps);
diff --git a/server/smartcard.cpp b/server/smartcard.cpp
index 3e0fa6ae..4f3b77cb 100644
--- a/server/smartcard.cpp
+++ b/server/smartcard.cpp
@@ -30,6 +30,8 @@
#include "smartcard-channel-client.h"
#include "migration-protocol.h"
+XXX_CAST(RedChannelClient, SmartCardChannelClient, SMARTCARD_CHANNEL_CLIENT)
+
/*
* TODO: the code doesn't really support multiple readers.
* For example: smartcard_char_device_add_to_readers calls smartcard_init,
diff --git a/server/sound.cpp b/server/sound.cpp
index 51deb0da..ee7aef55 100644
--- a/server/sound.cpp
+++ b/server/sound.cpp
@@ -79,19 +79,17 @@ typedef struct SpiceRecordState RecordChannel;
typedef void (*snd_channel_on_message_done_proc)(SndChannelClient *client);
-#define TYPE_SND_CHANNEL_CLIENT snd_channel_client_get_type()
-#define SND_CHANNEL_CLIENT(obj) \
- (G_TYPE_CHECK_INSTANCE_CAST((obj), TYPE_SND_CHANNEL_CLIENT, SndChannelClient))
-GType snd_channel_client_get_type(void) G_GNUC_CONST;
-
struct PersistentPipeItem: public RedPipeItem
{
SndChannelClient *client;
};
/* Connects an audio client to a Spice client */
-struct SndChannelClient: public RedChannelClient
+class SndChannelClient: public RedChannelClient
{
+public:
+ using RedChannelClient::RedChannelClient;
+
bool active;
bool client_active;
@@ -103,19 +101,13 @@ struct SndChannelClient: public RedChannelClient
PersistentPipeItem persistent_pipe_item;
snd_channel_on_message_done_proc on_message_done;
-};
-
-typedef struct SndChannelClientClass {
- RedChannelClientClass parent_class;
-} SndChannelClientClass;
-
-static void playback_channel_client_initable_interface_init(GInitableIface *iface);
-static void record_channel_client_initable_interface_init(GInitableIface *iface);
-static GInitableIface *playback_channel_client_parent_initable_iface;
-static GInitableIface *record_channel_client_parent_initable_iface;
-G_DEFINE_TYPE(SndChannelClient, snd_channel_client, RED_TYPE_CHANNEL_CLIENT)
+ virtual bool config_socket() override;
+ virtual uint8_t *alloc_recv_buf(uint16_t type, uint32_t size) override;
+ virtual void release_recv_buf(uint16_t type, uint32_t size, uint8_t *msg) override;
+};
+static void snd_playback_alloc_frames(PlaybackChannelClient *playback);
enum {
RED_PIPE_ITEM_PERSISTENT = RED_PIPE_ITEM_TYPE_CHANNEL_BASE,
@@ -138,31 +130,27 @@ struct AudioFrameContainer
AudioFrame items[NUM_AUDIO_FRAMES];
};
-#define TYPE_PLAYBACK_CHANNEL_CLIENT playback_channel_client_get_type()
-#define PLAYBACK_CHANNEL_CLIENT(obj) \
- (G_TYPE_CHECK_INSTANCE_CAST((obj), TYPE_PLAYBACK_CHANNEL_CLIENT, PlaybackChannelClient))
-GType playback_channel_client_get_type(void) G_GNUC_CONST;
-
-struct PlaybackChannelClient final: public SndChannelClient
-{
- AudioFrameContainer *frames;
- AudioFrame *free_frames;
- AudioFrame *in_progress; /* Frame being sent to the client */
- AudioFrame *pending_frame; /* Next frame to send to the client */
- uint32_t mode;
- uint32_t latency;
- SndCodec codec;
+class PlaybackChannelClient final: public SndChannelClient
+{
+protected:
+ ~PlaybackChannelClient();
+public:
+ PlaybackChannelClient(RedChannel *channel,
+ RedClient *client,
+ RedStream *stream,
+ RedChannelCapabilities *caps);
+ virtual bool init() override;
+
+ AudioFrameContainer *frames = nullptr;
+ AudioFrame *free_frames = nullptr;
+ AudioFrame *in_progress = nullptr; /* Frame being sent to the client */
+ AudioFrame *pending_frame = nullptr; /* Next frame to send to the client */
+ uint32_t mode = SPICE_AUDIO_DATA_MODE_RAW;
+ uint32_t latency = 0;
+ SndCodec codec = nullptr;
uint8_t encode_buf[SND_CODEC_MAX_COMPRESSED_BYTES];
};
-typedef struct PlaybackChannelClientClass {
- SndChannelClientClass parent_class;
-} PlaybackChannelClientClass;
-
-G_DEFINE_TYPE_WITH_CODE(PlaybackChannelClient, playback_channel_client, TYPE_SND_CHANNEL_CLIENT,
- G_IMPLEMENT_INTERFACE(G_TYPE_INITABLE,
- playback_channel_client_initable_interface_init))
-
typedef struct SpiceVolumeState {
uint16_t *volume;
uint8_t volume_nchannels;
@@ -219,31 +207,24 @@ typedef struct RecordChannelClass {
G_DEFINE_TYPE(RecordChannel, record_channel, TYPE_SND_CHANNEL)
-#define TYPE_RECORD_CHANNEL_CLIENT record_channel_client_get_type()
-#define RECORD_CHANNEL_CLIENT(obj) \
- (G_TYPE_CHECK_INSTANCE_CAST((obj), TYPE_RECORD_CHANNEL_CLIENT, RecordChannelClient))
-GType record_channel_client_get_type(void) G_GNUC_CONST;
-
-struct RecordChannelClient final: public SndChannelClient
+class RecordChannelClient final: public SndChannelClient
{
+protected:
+ ~RecordChannelClient();
+public:
+ using SndChannelClient::SndChannelClient;
+ virtual bool init() override;
+
uint32_t samples[RECORD_SAMPLES_SIZE];
- uint32_t write_pos;
- uint32_t read_pos;
- uint32_t mode;
- uint32_t mode_time;
- uint32_t start_time;
- SndCodec codec;
+ uint32_t write_pos = 0;
+ uint32_t read_pos = 0;
+ uint32_t mode = SPICE_AUDIO_DATA_MODE_RAW;
+ uint32_t mode_time = 0;
+ uint32_t start_time = 0;
+ SndCodec codec = nullptr;
uint8_t decode_buf[SND_CODEC_MAX_FRAME_BYTES];
};
-typedef struct RecordChannelClientClass {
- SndChannelClientClass parent_class;
-} RecordChannelClientClass;
-
-G_DEFINE_TYPE_WITH_CODE(RecordChannelClient, record_channel_client, TYPE_SND_CHANNEL_CLIENT,
- G_IMPLEMENT_INTERFACE(G_TYPE_INITABLE,
- record_channel_client_initable_interface_init))
-
/* A list of all Spice{Playback,Record}State objects */
static GList *snd_channels;
@@ -350,6 +331,8 @@ const char* spice_audio_data_mode_to_string(gint mode)
return "unknown audio codec";
}
+XXX_CAST(RedChannelClient, RecordChannelClient, RECORD_CHANNEL_CLIENT)
+
static bool
record_channel_handle_message(RedChannelClient *rcc, uint16_t type, uint32_t size, void *message)
{
@@ -415,7 +398,7 @@ static bool snd_channel_send_migrate(SndChannelClient *client)
static bool snd_playback_send_migrate(PlaybackChannelClient *client)
{
- return snd_channel_send_migrate(SND_CHANNEL_CLIENT(client));
+ return snd_channel_send_migrate(client);
}
static bool snd_send_volume(SndChannelClient *client, uint32_t cap, int msg)
@@ -446,7 +429,7 @@ static bool snd_send_volume(SndChannelClient *client, uint32_t cap, int msg)
static bool snd_playback_send_volume(PlaybackChannelClient *playback_client)
{
- return snd_send_volume(SND_CHANNEL_CLIENT(playback_client), SPICE_PLAYBACK_CAP_VOLUME,
+ return snd_send_volume(playback_client, SPICE_PLAYBACK_CAP_VOLUME,
SPICE_MSG_PLAYBACK_VOLUME);
}
@@ -472,7 +455,7 @@ static bool snd_send_mute(SndChannelClient *client, uint32_t cap, int msg)
static bool snd_playback_send_mute(PlaybackChannelClient *playback_client)
{
- return snd_send_mute(SND_CHANNEL_CLIENT(playback_client), SPICE_PLAYBACK_CAP_VOLUME,
+ return snd_send_mute(playback_client, SPICE_PLAYBACK_CAP_VOLUME,
SPICE_MSG_PLAYBACK_MUTE);
}
@@ -521,7 +504,7 @@ static bool snd_playback_send_stop(PlaybackChannelClient *playback_client)
static int snd_playback_send_ctl(PlaybackChannelClient *playback_client)
{
- SndChannelClient *client = SND_CHANNEL_CLIENT(playback_client);
+ SndChannelClient *client = playback_client;
if ((client->client_active = client->active)) {
return snd_playback_send_start(playback_client);
@@ -560,7 +543,7 @@ static bool snd_record_send_stop(RecordChannelClient *record_client)
static int snd_record_send_ctl(RecordChannelClient *record_client)
{
- SndChannelClient *client = SND_CHANNEL_CLIENT(record_client);
+ SndChannelClient *client = record_client;
if ((client->client_active = client->active)) {
return snd_record_send_start(record_client);
@@ -571,13 +554,13 @@ static int snd_record_send_ctl(RecordChannelClient *record_client)
static bool snd_record_send_volume(RecordChannelClient *record_client)
{
- return snd_send_volume(SND_CHANNEL_CLIENT(record_client), SPICE_RECORD_CAP_VOLUME,
+ return snd_send_volume(record_client, SPICE_RECORD_CAP_VOLUME,
SPICE_MSG_RECORD_VOLUME);
}
static bool snd_record_send_mute(RecordChannelClient *record_client)
{
- return snd_send_mute(SND_CHANNEL_CLIENT(record_client), SPICE_RECORD_CAP_VOLUME,
+ return snd_send_mute(record_client, SPICE_RECORD_CAP_VOLUME,
SPICE_MSG_RECORD_MUTE);
}
@@ -587,7 +570,7 @@ static bool snd_record_send_migrate(RecordChannelClient *record_client)
* the client receives RECORD_STOP from the src before the migration completion
* notification (when the vm is stopped).
* Afterwards, when the vm starts on the dest, the client receives RECORD_START. */
- return snd_channel_send_migrate(SND_CHANNEL_CLIENT(record_client));
+ return snd_channel_send_migrate(record_client);
}
static bool snd_playback_send_write(PlaybackChannelClient *playback_client)
@@ -596,7 +579,7 @@ static bool snd_playback_send_write(PlaybackChannelClient *playback_client)
SpiceMarshaller *m = rcc->get_marshaller();
AudioFrame *frame;
SpiceMsgPlaybackPacket msg;
- RedPipeItem *pipe_item = &SND_CHANNEL_CLIENT(playback_client)->persistent_pipe_item;
+ RedPipeItem *pipe_item = &playback_client->persistent_pipe_item;
rcc->init_send_data(SPICE_MSG_PLAYBACK_DATA);
@@ -666,25 +649,22 @@ static void snd_persistent_pipe_item_free(struct RedPipeItem *item)
static void snd_send(SndChannelClient * client)
{
- RedChannelClient *rcc;
-
- g_return_if_fail(RED_IS_CHANNEL_CLIENT(client));
-
- rcc = client;
- if (!rcc->pipe_is_empty() || !client->command) {
+ if (!client->pipe_is_empty()|| !client->command) {
return;
}
// just append a dummy item and push!
red_pipe_item_init_full(&client->persistent_pipe_item, RED_PIPE_ITEM_PERSISTENT,
snd_persistent_pipe_item_free);
client->persistent_pipe_item.client = client;
- rcc->pipe_add_push(&client->persistent_pipe_item);
+ client->pipe_add_push(&client->persistent_pipe_item);
}
+XXX_CAST(RedChannelClient, PlaybackChannelClient, PLAYBACK_CHANNEL_CLIENT)
+
static void playback_channel_send_item(RedChannelClient *rcc, G_GNUC_UNUSED RedPipeItem *item)
{
PlaybackChannelClient *playback_client = PLAYBACK_CHANNEL_CLIENT(rcc);
- SndChannelClient *client = SND_CHANNEL_CLIENT(rcc);
+ SndChannelClient *client = playback_client;
client->command &= SND_PLAYBACK_MODE_MASK|SND_PLAYBACK_PCM_MASK|
SND_CTRL_MASK|SND_VOLUME_MUTE_MASK|
@@ -744,7 +724,7 @@ static void playback_channel_send_item(RedChannelClient *rcc, G_GNUC_UNUSED RedP
static void record_channel_send_item(RedChannelClient *rcc, G_GNUC_UNUSED RedPipeItem *item)
{
RecordChannelClient *record_client = RECORD_CHANNEL_CLIENT(rcc);
- SndChannelClient *client = SND_CHANNEL_CLIENT(rcc);
+ SndChannelClient *client = record_client;
client->command &= SND_CTRL_MASK|SND_VOLUME_MUTE_MASK|SND_MIGRATE_MASK;
while (client->command) {
@@ -776,10 +756,10 @@ static void record_channel_send_item(RedChannelClient *rcc, G_GNUC_UNUSED RedPip
snd_send(client);
}
-static bool snd_channel_client_config_socket(RedChannelClient *rcc)
+bool SndChannelClient::config_socket()
{
- RedStream *stream = rcc->get_stream();
- RedClient *red_client = rcc->get_client();
+ RedStream *stream = get_stream();
+ RedClient *red_client = get_client();
MainChannelClient *mcc = red_client_get_main(red_client);
#ifdef SO_PRIORITY
@@ -787,7 +767,7 @@ static bool snd_channel_client_config_socket(RedChannelClient *rcc)
if (setsockopt(stream->socket, SOL_SOCKET, SO_PRIORITY, (void*)&priority,
sizeof(priority)) == -1) {
if (errno != ENOTSUP) {
- red_channel_warning(rcc->get_channel(),
+ red_channel_warning(get_channel(),
"setsockopt failed, %s", strerror(errno));
}
}
@@ -797,7 +777,7 @@ static bool snd_channel_client_config_socket(RedChannelClient *rcc)
int tos = IPTOS_LOWDELAY;
if (setsockopt(stream->socket, IPPROTO_IP, IP_TOS, (void*)&tos, sizeof(tos)) == -1) {
if (errno != ENOTSUP) {
- red_channel_warning(rcc->get_channel(),
+ red_channel_warning(get_channel(),
"setsockopt failed, %s",
strerror(errno));
}
@@ -809,23 +789,20 @@ static bool snd_channel_client_config_socket(RedChannelClient *rcc)
return true;
}
-static uint8_t*
-snd_channel_client_alloc_recv_buf(RedChannelClient *rcc, uint16_t type, uint32_t size)
+uint8_t*
+SndChannelClient::alloc_recv_buf(uint16_t type, uint32_t size)
{
- SndChannelClient *client = SND_CHANNEL_CLIENT(rcc);
// If message is too big allocate one, this should never happen
- if (size > sizeof(client->receive_buf)) {
+ if (size > sizeof(receive_buf)) {
return (uint8_t*) g_malloc(size);
}
- return client->receive_buf;
+ return receive_buf;
}
-static void
-snd_channel_client_release_recv_buf(RedChannelClient *rcc, uint16_t type, uint32_t size,
- uint8_t *msg)
+void
+SndChannelClient::release_recv_buf(uint16_t type, uint32_t size, uint8_t *msg)
{
- SndChannelClient *client = SND_CHANNEL_CLIENT(rcc);
- if (msg != client->receive_buf) {
+ if (msg != receive_buf) {
g_free(msg);
}
}
@@ -976,20 +953,20 @@ SPICE_GNUC_VISIBLE void spice_server_playback_put_samples(SpicePlaybackInstance
}
}
playback_client = frame->client;
- if (!playback_client || snd_channel_get_client(sin->st) != SND_CHANNEL_CLIENT(playback_client)) {
+ if (!playback_client || snd_channel_get_client(sin->st) != playback_client) {
/* lost last reference, client has been destroyed previously */
spice_debug("audio samples belong to a disconnected client");
return;
}
- spice_assert(SND_CHANNEL_CLIENT(playback_client)->active);
+ spice_assert(playback_client->active);
if (playback_client->pending_frame) {
snd_playback_free_frame(playback_client, playback_client->pending_frame);
}
frame->time = reds_get_mm_time();
playback_client->pending_frame = frame;
- snd_set_command(SND_CHANNEL_CLIENT(playback_client), SND_PLAYBACK_PCM_MASK);
- snd_send(SND_CHANNEL_CLIENT(playback_client));
+ snd_set_command(playback_client, SND_PLAYBACK_PCM_MASK);
+ snd_send(playback_client);
}
void snd_set_playback_latency(RedClient *client, uint32_t latency)
@@ -1029,74 +1006,65 @@ static int snd_desired_audio_mode(bool playback_compression, int frequency,
return SPICE_AUDIO_DATA_MODE_RAW;
}
-static void
-playback_channel_client_finalize(GObject *object)
+PlaybackChannelClient::~PlaybackChannelClient()
{
int i;
- PlaybackChannelClient *playback_client = PLAYBACK_CHANNEL_CLIENT(object);
- SndChannelClient *client = SND_CHANNEL_CLIENT(playback_client);
// free frames, unref them
for (i = 0; i < NUM_AUDIO_FRAMES; ++i) {
- playback_client->frames->items[i].client = NULL;
+ frames->items[i].client = NULL;
}
- if (--playback_client->frames->refs == 0) {
- g_free(playback_client->frames);
+ if (--frames->refs == 0) {
+ g_free(frames);
}
- if (client->active) {
- reds_enable_mm_time(snd_channel_get_server(client));
+ if (active) {
+ reds_enable_mm_time(snd_channel_get_server(this));
}
- snd_codec_destroy(&playback_client->codec);
-
- G_OBJECT_CLASS(playback_channel_client_parent_class)->finalize(object);
+ snd_codec_destroy(&codec);
}
-static void
-playback_channel_client_constructed(GObject *object)
+
+PlaybackChannelClient::PlaybackChannelClient(RedChannel *channel,
+ RedClient *client,
+ RedStream *stream,
+ RedChannelCapabilities *caps):
+ SndChannelClient(channel, client, stream, caps)
{
- PlaybackChannelClient *playback_client = PLAYBACK_CHANNEL_CLIENT(object);
- RedChannelClient *rcc = playback_client;
- RedChannel *red_channel = rcc->get_channel();
- SndChannel *channel = SND_CHANNEL(red_channel);
- SndChannelClient *scc = SND_CHANNEL_CLIENT(playback_client);
+ snd_playback_alloc_frames(this);
- G_OBJECT_CLASS(playback_channel_client_parent_class)->constructed(object);
+ RedChannel *red_channel = get_channel();
+ SndChannel *snd_channel = SND_CHANNEL(red_channel);
- scc->on_message_done = snd_playback_on_message_done;
+ on_message_done = snd_playback_on_message_done;
- bool client_can_opus = rcc->test_remote_cap(SPICE_PLAYBACK_CAP_OPUS);
+ bool client_can_opus = test_remote_cap(SPICE_PLAYBACK_CAP_OPUS);
bool playback_compression =
reds_config_get_playback_compression(red_channel->get_server());
- int desired_mode = snd_desired_audio_mode(playback_compression, channel->frequency, client_can_opus);
+ int desired_mode = snd_desired_audio_mode(playback_compression, snd_channel->frequency, client_can_opus);
if (desired_mode != SPICE_AUDIO_DATA_MODE_RAW) {
- if (snd_codec_create(&playback_client->codec, desired_mode, channel->frequency,
+ if (snd_codec_create(&codec, desired_mode, snd_channel->frequency,
SND_CODEC_ENCODE) == SND_CODEC_OK) {
- playback_client->mode = desired_mode;
+ mode = desired_mode;
} else {
red_channel_warning(red_channel, "create encoder failed");
}
}
- spice_debug("playback client %p using mode %s", playback_client,
- spice_audio_data_mode_to_string(playback_client->mode));
+ spice_debug("playback client %p using mode %s", this,
+ spice_audio_data_mode_to_string(mode));
}
-static gboolean playback_channel_client_initable_init(GInitable *initable,
- GCancellable *cancellable,
- GError **error)
+bool PlaybackChannelClient::init()
{
- RedChannelClient *rcc = PLAYBACK_CHANNEL_CLIENT(initable);
- gboolean success;
- RedClient *red_client = rcc->get_client();
- SndChannelClient *scc = SND_CHANNEL_CLIENT(initable);
- RedChannel *red_channel = rcc->get_channel();
+ RedClient *red_client = get_client();
+ SndChannelClient *scc = this;
+ RedChannel *red_channel = get_channel();
SndChannel *channel = SND_CHANNEL(red_channel);
- success = playback_channel_client_parent_initable_iface->init(initable, cancellable, error);
- if (!success) {
- return FALSE;
+ if (!SndChannelClient::init()) {
+ return false;
}
if (!red_client_during_migrate_at_target(red_client)) {
@@ -1111,19 +1079,10 @@ static gboolean playback_channel_client_initable_init(GInitable *initable,
}
snd_send(scc);
- return TRUE;
-}
-
-static void playback_channel_client_initable_interface_init(GInitableIface *iface)
-{
- playback_channel_client_parent_initable_iface =
- (GInitableIface *) g_type_interface_peek_parent(iface);
-
- iface->init = playback_channel_client_initable_init;
+ return true;
}
-static void snd_set_peer(RedChannel *red_channel, RedClient *client, RedStream *stream,
- RedChannelCapabilities *caps, GType type)
+static void snd_set_peer_common(RedChannel *red_channel)
{
SndChannel *channel = SND_CHANNEL(red_channel);
SndChannelClient *snd_client = snd_channel_get_client(channel);
@@ -1132,26 +1091,22 @@ static void snd_set_peer(RedChannel *red_channel, RedClient *client, RedStream *
if (snd_client) {
snd_client->disconnect();
}
-
- snd_client = (SndChannelClient *)
- g_initable_new(type,
- NULL, NULL,
- "channel", channel,
- "client", client,
- "stream", stream,
- "caps", caps,
- NULL);
- g_warn_if_fail(snd_client != NULL);
}
static void snd_set_playback_peer(RedChannel *red_channel, RedClient *client, RedStream *stream,
G_GNUC_UNUSED int migration,
RedChannelCapabilities *caps)
{
- snd_set_peer(red_channel, client, stream, caps,
- TYPE_PLAYBACK_CHANNEL_CLIENT);
+ snd_set_peer_common(red_channel);
+
+ auto peer = new PlaybackChannelClient(red_channel, client, stream, caps);
+ if (!peer->init()) {
+ peer->unref();
+ }
}
+XXX_CAST(RedChannelClient, SndChannelClient, SND_CHANNEL_CLIENT)
+
static void snd_migrate_channel_client(RedChannelClient *rcc)
{
snd_set_command(SND_CHANNEL_CLIENT(rcc), SND_MIGRATE_MASK);
@@ -1263,57 +1218,42 @@ SPICE_GNUC_VISIBLE void spice_server_set_record_rate(SpiceRecordInstance *sin, u
snd_set_rate(sin->st, frequency, SPICE_RECORD_CAP_OPUS);
}
-static void
-record_channel_client_finalize(GObject *object)
+RecordChannelClient::~RecordChannelClient()
{
- RecordChannelClient *record_client = RECORD_CHANNEL_CLIENT(object);
-
- snd_codec_destroy(&record_client->codec);
-
- G_OBJECT_CLASS(record_channel_client_parent_class)->finalize(object);
+ snd_codec_destroy(&codec);
}
-static gboolean record_channel_client_initable_init(GInitable *initable,
- GCancellable *cancellable,
- GError **error)
+bool RecordChannelClient::init()
{
- gboolean success;
- RecordChannelClient *record_client = RECORD_CHANNEL_CLIENT(initable);
- RedChannel *red_channel = record_client->get_channel();
+ RedChannel *red_channel = get_channel();
SndChannel *channel = SND_CHANNEL(red_channel);
- SndChannelClient *scc = SND_CHANNEL_CLIENT(record_client);
- success = record_channel_client_parent_initable_iface->init(initable, cancellable, error);
- if (!success) {
+ if (!SndChannelClient::init()) {
return FALSE;
}
if (channel->volume.volume_nchannels) {
- snd_set_command(scc, SND_VOLUME_MUTE_MASK);
+ snd_set_command(this, SND_VOLUME_MUTE_MASK);
}
if (channel->active) {
- record_channel_client_start(scc);
+ record_channel_client_start(this);
}
- snd_send(scc);
+ snd_send(this);
return TRUE;
}
-static void record_channel_client_initable_interface_init(GInitableIface *iface)
-{
- record_channel_client_parent_initable_iface =
- (GInitableIface *) g_type_interface_peek_parent(iface);
-
- iface->init = record_channel_client_initable_init;
-}
-
static void snd_set_record_peer(RedChannel *red_channel, RedClient *client, RedStream *stream,
G_GNUC_UNUSED int migration,
RedChannelCapabilities *caps)
{
- snd_set_peer(red_channel, client, stream, caps,
- TYPE_RECORD_CHANNEL_CLIENT);
+ snd_set_peer_common(red_channel);
+
+ auto peer = new RecordChannelClient(red_channel, client, stream, caps);
+ if (!peer->init()) {
+ peer->unref();
+ }
}
static void add_channel(SndChannel *channel)
@@ -1488,29 +1428,6 @@ void snd_set_playback_compression(bool on)
}
}
-static void
-snd_channel_client_class_init(SndChannelClientClass *klass)
-{
- RedChannelClientClass *client_class = RED_CHANNEL_CLIENT_CLASS(klass);
-
- client_class->config_socket = snd_channel_client_config_socket;
- client_class->alloc_recv_buf = snd_channel_client_alloc_recv_buf;
- client_class->release_recv_buf = snd_channel_client_release_recv_buf;
-}
-
-static void
-snd_channel_client_init(SndChannelClient *self)
-{
-}
-
-static void
-playback_channel_client_class_init(PlaybackChannelClientClass *klass)
-{
- GObjectClass *object_class = G_OBJECT_CLASS(klass);
- object_class->constructed = playback_channel_client_constructed;
- object_class->finalize = playback_channel_client_finalize;
-}
-
static void snd_playback_alloc_frames(PlaybackChannelClient *playback)
{
int i;
@@ -1522,23 +1439,3 @@ static void snd_playback_alloc_frames(PlaybackChannelClient *playback)
snd_playback_free_frame(playback, &playback->frames->items[i]);
}
}
-
-static void
-playback_channel_client_init(PlaybackChannelClient *playback)
-{
- playback->mode = SPICE_AUDIO_DATA_MODE_RAW;
- snd_playback_alloc_frames(playback);
-}
-
-static void
-record_channel_client_class_init(RecordChannelClientClass *klass)
-{
- GObjectClass *object_class = G_OBJECT_CLASS(klass);
- object_class->finalize = record_channel_client_finalize;
-}
-
-static void
-record_channel_client_init(RecordChannelClient *record)
-{
- record->mode = SPICE_AUDIO_DATA_MODE_RAW;
-}
diff --git a/server/spicevmc.cpp b/server/spicevmc.cpp
index 20afd28a..a0d339d3 100644
--- a/server/spicevmc.cpp
+++ b/server/spicevmc.cpp
@@ -51,9 +51,6 @@ SPICE_DECLARE_TYPE(RedVmcChannel, red_vmc_channel, VMC_CHANNEL);
SPICE_DECLARE_TYPE(RedVmcChannelPort, red_vmc_channel_port, VMC_CHANNEL_PORT);
#define RED_TYPE_VMC_CHANNEL_PORT red_vmc_channel_port_get_type()
-SPICE_DECLARE_TYPE(VmcChannelClient, vmc_channel_client, VMC_CHANNEL_CLIENT);
-#define TYPE_VMC_CHANNEL_CLIENT vmc_channel_client_get_type()
-
SPICE_DECLARE_TYPE(RedVmcChannelUsbredir, red_vmc_channel_usbredir, VMC_CHANNEL_USBREDIR);
#define RED_TYPE_VMC_CHANNEL_USBREDIR red_vmc_channel_usbredir_get_type()
@@ -156,16 +153,15 @@ static void red_vmc_channel_port_init(RedVmcChannelPort *self)
G_DEFINE_TYPE(RedVmcChannelPort, red_vmc_channel_port, RED_TYPE_VMC_CHANNEL)
-struct VmcChannelClient final: public RedChannelClient
+class VmcChannelClient final: public RedChannelClient
{
-};
+ using RedChannelClient::RedChannelClient;
-struct VmcChannelClientClass {
- RedChannelClientClass parent_class;
+ virtual uint8_t *alloc_recv_buf(uint16_t type, uint32_t size) override;
+ virtual void release_recv_buf(uint16_t type, uint32_t size, uint8_t *msg) override;
+ virtual void on_disconnect() override;
};
-G_DEFINE_TYPE(VmcChannelClient, vmc_channel_client, RED_TYPE_CHANNEL_CLIENT)
-
static RedChannelClient *
vmc_channel_client_create(RedChannel *channel, RedClient *client,
RedStream *stream,
@@ -271,10 +267,6 @@ enum {
RED_PIPE_ITEM_TYPE_PORT_EVENT,
};
-static void spicevmc_red_channel_release_msg_rcv_buf(RedChannelClient *rcc,
- uint16_t type,
- uint32_t size,
- uint8_t *msg);
/* n is the data size (uncompressed)
* msg_item -- the current pipe item with the uncompressed data
* This function returns:
@@ -411,13 +403,13 @@ static void spicevmc_char_dev_remove_client(RedCharDevice *self,
channel->rcc->shutdown();
}
-static void spicevmc_red_channel_client_on_disconnect(RedChannelClient *rcc)
+void VmcChannelClient::on_disconnect()
{
RedVmcChannel *channel;
SpiceCharDeviceInterface *sif;
- RedClient *client = rcc->get_client();
+ RedClient *client = get_client();
- channel = RED_VMC_CHANNEL(rcc->get_channel());
+ channel = RED_VMC_CHANNEL(get_channel());
/* partial message which wasn't pushed to device */
red_char_device_write_buffer_release(channel->chardev, &channel->recv_from_client_buf);
@@ -514,7 +506,7 @@ static bool spicevmc_red_channel_client_handle_message(RedChannelClient *rcc,
uint32_t size,
void *msg)
{
- /* NOTE: *msg free by g_free() (when cb to spicevmc_red_channel_release_msg_rcv_buf
+ /* NOTE: *msg free by g_free() (when cb to VmcChannelClient::release_recv_buf
* with the compressed msg type) */
RedVmcChannel *channel;
SpiceCharDeviceInterface *sif;
@@ -557,21 +549,19 @@ static void spicevmc_on_free_self_token(RedCharDevice *self)
channel->rcc->unblock_read();
}
-static uint8_t *spicevmc_red_channel_alloc_msg_rcv_buf(RedChannelClient *rcc,
- uint16_t type,
- uint32_t size)
+uint8_t *VmcChannelClient::alloc_recv_buf(uint16_t type, uint32_t size)
{
switch (type) {
case SPICE_MSGC_SPICEVMC_DATA: {
- RedVmcChannel *channel = RED_VMC_CHANNEL(rcc->get_channel());
+ RedVmcChannel *channel = RED_VMC_CHANNEL(get_channel());
assert(!channel->recv_from_client_buf);
channel->recv_from_client_buf = red_char_device_write_buffer_get_server(channel->chardev,
size, true);
if (!channel->recv_from_client_buf) {
- rcc->block_read();
+ block_read();
return NULL;
}
return channel->recv_from_client_buf->buf;
@@ -583,15 +573,12 @@ static uint8_t *spicevmc_red_channel_alloc_msg_rcv_buf(RedChannelClient *rcc,
}
-static void spicevmc_red_channel_release_msg_rcv_buf(RedChannelClient *rcc,
- uint16_t type,
- uint32_t size,
- uint8_t *msg)
+void VmcChannelClient::release_recv_buf(uint16_t type, uint32_t size, uint8_t *msg)
{
switch (type) {
case SPICE_MSGC_SPICEVMC_DATA: {
- RedVmcChannel *channel = RED_VMC_CHANNEL(rcc->get_channel());
+ RedVmcChannel *channel = RED_VMC_CHANNEL(get_channel());
/* buffer wasn't pushed to device */
red_char_device_write_buffer_release(channel->chardev, &channel->recv_from_client_buf);
break;
@@ -929,36 +916,15 @@ red_char_device_spicevmc_new(SpiceCharDeviceInstance *sin,
NULL);
}
-static void
-vmc_channel_client_init(VmcChannelClient *self)
-{
-}
-
-static void
-vmc_channel_client_class_init(VmcChannelClientClass *klass)
-{
- RedChannelClientClass *client_class = RED_CHANNEL_CLIENT_CLASS(klass);
-
- client_class->alloc_recv_buf = spicevmc_red_channel_alloc_msg_rcv_buf;
- client_class->release_recv_buf = spicevmc_red_channel_release_msg_rcv_buf;
- client_class->on_disconnect = spicevmc_red_channel_client_on_disconnect;
-}
-
static RedChannelClient *
vmc_channel_client_create(RedChannel *channel, RedClient *client,
RedStream *stream,
RedChannelCapabilities *caps)
{
- RedChannelClient *rcc;
-
- rcc = (RedChannelClient *)
- g_initable_new(TYPE_VMC_CHANNEL_CLIENT,
- NULL, NULL,
- "channel", channel,
- "client", client,
- "stream", stream,
- "caps", caps,
- NULL);
-
+ auto rcc = new VmcChannelClient(channel, client, stream, caps);
+ if (!rcc->init()) {
+ delete rcc;
+ rcc = nullptr;
+ }
return rcc;
}
diff --git a/server/stream-channel.cpp b/server/stream-channel.cpp
index 46f73089..d578d356 100644
--- a/server/stream-channel.cpp
+++ b/server/stream-channel.cpp
@@ -28,42 +28,26 @@
#include "display-limits.h"
#include "video-stream.h" // TODO remove, put common stuff
-#define TYPE_STREAM_CHANNEL_CLIENT stream_channel_client_get_type()
-
-#define STREAM_CHANNEL_CLIENT(obj) \
- (G_TYPE_CHECK_INSTANCE_CAST((obj), TYPE_STREAM_CHANNEL_CLIENT, StreamChannelClient))
-#define STREAM_CHANNEL_CLIENT_CLASS(klass) \
- (G_TYPE_CHECK_CLASS_CAST((klass), TYPE_STREAM_CHANNEL_CLIENT, StreamChannelClientClass))
-#define IS_STREAM_CHANNEL_CLIENT(obj) \
- (G_TYPE_CHECK_INSTANCE_TYPE((obj), TYPE_STREAM_CHANNEL_CLIENT))
-#define IS_STREAM_CHANNEL_CLIENT_CLASS(klass) \
- (G_TYPE_CHECK_CLASS_TYPE((klass), TYPE_STREAM_CHANNEL_CLIENT))
-#define STREAM_CHANNEL_CLIENT_GET_CLASS(obj) \
- (G_TYPE_INSTANCE_GET_CLASS((obj), TYPE_STREAM_CHANNEL_CLIENT, StreamChannelClientClass))
-
-typedef struct StreamChannelClient StreamChannelClient;
-typedef struct StreamChannelClientClass StreamChannelClientClass;
-
/* we need to inherit from CommonGraphicsChannelClient
* to get buffer handling */
-struct StreamChannelClient final: public CommonGraphicsChannelClient
+class StreamChannelClient final: public CommonGraphicsChannelClient
{
+protected:
+ ~StreamChannelClient();
+public:
+ using CommonGraphicsChannelClient::CommonGraphicsChannelClient;
+
+ bool handle_preferred_video_codec_type(SpiceMsgcDisplayPreferredVideoCodecType *msg);
+
/* current video stream id, <0 if not initialized or
* we are not sending a stream */
- int stream_id;
+ int stream_id = -1;
/* Array with SPICE_VIDEO_CODEC_TYPE_ENUM_END elements, with the client
* preference order (index) as value */
GArray *client_preferred_video_codecs;
+ virtual void on_disconnect() override;
};
-struct StreamChannelClientClass {
- CommonGraphicsChannelClientClass parent_class;
-};
-
-GType stream_channel_client_get_type(void) G_GNUC_CONST;
-
-G_DEFINE_TYPE(StreamChannelClient, stream_channel_client, TYPE_COMMON_GRAPHICS_CHANNEL_CLIENT)
-
struct StreamChannel final: public RedChannel
{
/* current video stream id, <0 if not initialized or
@@ -114,37 +98,11 @@ typedef struct StreamDataItem {
#define PRIMARY_SURFACE_ID 0
-static void stream_channel_client_on_disconnect(RedChannelClient *rcc);
-static bool
-stream_channel_handle_preferred_video_codec_type(RedChannelClient *rcc,
- SpiceMsgcDisplayPreferredVideoCodecType *msg);
-
RECORDER(stream_channel_data, 32, "Stream channel data packet");
-static void
-stream_channel_client_finalize(GObject *object)
+StreamChannelClient::~StreamChannelClient()
{
- StreamChannelClient *self = STREAM_CHANNEL_CLIENT(object);
- g_clear_pointer(&self->client_preferred_video_codecs, g_array_unref);
-
- G_OBJECT_CLASS(stream_channel_client_parent_class)->finalize(object);
-}
-
-static void
-stream_channel_client_class_init(StreamChannelClientClass *klass)
-{
- GObjectClass *object_class = G_OBJECT_CLASS(klass);
-
- RedChannelClientClass *channel_class = RED_CHANNEL_CLIENT_CLASS(klass);
-
- channel_class->on_disconnect = stream_channel_client_on_disconnect;
- object_class->finalize = stream_channel_client_finalize;
-}
-
-static void
-stream_channel_client_init(StreamChannelClient *client)
-{
- client->stream_id = -1;
+ g_clear_pointer(&client_preferred_video_codecs, g_array_unref);
}
static void
@@ -155,10 +113,10 @@ request_new_stream(StreamChannel *channel, StreamMsgStartStop *start)
}
}
-static void
-stream_channel_client_on_disconnect(RedChannelClient *rcc)
+void
+StreamChannelClient::on_disconnect()
{
- StreamChannel *channel = STREAM_CHANNEL(rcc->get_channel());
+ StreamChannel *channel = STREAM_CHANNEL(get_channel());
// if there are still some client connected keep streaming
// TODO, maybe would be worth sending new codecs if they are better
@@ -179,17 +137,11 @@ static StreamChannelClient*
stream_channel_client_new(StreamChannel *channel, RedClient *client, RedStream *stream,
int mig_target, RedChannelCapabilities *caps)
{
- StreamChannelClient *rcc;
-
- rcc = (StreamChannelClient *)
- g_initable_new(TYPE_STREAM_CHANNEL_CLIENT,
- NULL, NULL,
- "channel", channel,
- "client", client,
- "stream", stream,
- "caps", caps,
- NULL);
-
+ auto rcc = new StreamChannelClient(RED_CHANNEL(channel), client, stream, caps);
+ if (!rcc->init()) {
+ rcc->unref();
+ rcc = nullptr;
+ }
return rcc;
}
@@ -227,6 +179,8 @@ marshall_monitors_config(RedChannelClient *rcc, StreamChannel *channel, SpiceMar
spice_marshall_msg_display_monitors_config(m, &msg.config);
}
+XXX_CAST(RedChannelClient, StreamChannelClient, STREAM_CHANNEL_CLIENT)
+
static void
stream_channel_send_item(RedChannelClient *rcc, RedPipeItem *pipe_item)
{
@@ -329,6 +283,8 @@ stream_channel_send_item(RedChannelClient *rcc, RedPipeItem *pipe_item)
static bool
handle_message(RedChannelClient *rcc, uint16_t type, uint32_t size, void *msg)
{
+ StreamChannelClient *client = STREAM_CHANNEL_CLIENT(rcc);
+
switch (type) {
case SPICE_MSGC_DISPLAY_INIT:
case SPICE_MSGC_DISPLAY_PREFERRED_COMPRESSION:
@@ -340,7 +296,7 @@ handle_message(RedChannelClient *rcc, uint16_t type, uint32_t size, void *msg)
/* client should not send this message */
return false;
case SPICE_MSGC_DISPLAY_PREFERRED_VIDEO_CODEC_TYPE:
- return stream_channel_handle_preferred_video_codec_type(rcc,
+ return client->handle_preferred_video_codec_type(
(SpiceMsgcDisplayPreferredVideoCodecType *)msg);
default:
return RedChannelClient::handle_message(rcc, type, size, msg);
@@ -407,18 +363,15 @@ stream_channel_get_supported_codecs(StreamChannel *channel, uint8_t *out_codecs)
return num;
}
-static bool
-stream_channel_handle_preferred_video_codec_type(RedChannelClient *rcc,
- SpiceMsgcDisplayPreferredVideoCodecType *msg)
+bool
+StreamChannelClient::handle_preferred_video_codec_type(SpiceMsgcDisplayPreferredVideoCodecType *msg)
{
- StreamChannelClient *client = STREAM_CHANNEL_CLIENT(rcc);
-
if (msg->num_of_codecs == 0) {
return true;
}
- g_clear_pointer(&client->client_preferred_video_codecs, g_array_unref);
- client->client_preferred_video_codecs = video_stream_parse_preferred_codecs(msg);
+ g_clear_pointer(&client_preferred_video_codecs, g_array_unref);
+ client_preferred_video_codecs = video_stream_parse_preferred_codecs(msg);
return true;
}
diff --git a/server/tests/test-channel.cpp b/server/tests/test-channel.cpp
index ed083f1a..9c294f2a 100644
--- a/server/tests/test-channel.cpp
+++ b/server/tests/test-channel.cpp
@@ -47,31 +47,19 @@ struct RedTestChannelClass
G_DEFINE_TYPE(RedTestChannel, red_test_channel, RED_TYPE_CHANNEL)
-SPICE_DECLARE_TYPE(RedTestChannelClient, red_test_channel_client, TEST_CHANNEL_CLIENT);
-#define RED_TYPE_TEST_CHANNEL_CLIENT red_test_channel_client_get_type()
-
-struct RedTestChannelClient final: public RedChannelClient
-{
-};
-
-struct RedTestChannelClientClass
+class RedTestChannelClient final: public RedChannelClient
{
- RedChannelClientClass parent_class;
+ using RedChannelClient::RedChannelClient;
+ virtual uint8_t * alloc_recv_buf(uint16_t type, uint32_t size) override;
+ virtual void release_recv_buf(uint16_t type, uint32_t size, uint8_t *msg) override;
};
-G_DEFINE_TYPE(RedTestChannelClient, red_test_channel_client, RED_TYPE_CHANNEL_CLIENT)
-
static void
red_test_channel_init(RedTestChannel *self)
{
}
static void
-red_test_channel_client_init(RedTestChannelClient *self)
-{
-}
-
-static void
test_channel_send_item(RedChannelClient *rcc, RedPipeItem *item)
{
}
@@ -81,15 +69,9 @@ test_connect_client(RedChannel *channel, RedClient *client, RedStream *stream,
int migration, RedChannelCapabilities *caps)
{
RedChannelClient *rcc;
- rcc = (RedChannelClient *)
- g_initable_new(RED_TYPE_TEST_CHANNEL_CLIENT,
- NULL, NULL,
- "channel", channel,
- "client", client,
- "stream", stream,
- "caps", caps,
- NULL);
+ rcc = new RedTestChannelClient(channel, client, stream, caps);
g_assert_nonnull(rcc);
+ g_assert_true(rcc->init());
// requires an ACK after 10 messages
rcc->ack_set_client_window(10);
@@ -115,27 +97,18 @@ red_test_channel_class_init(RedTestChannelClass *klass)
channel_class->connect = test_connect_client;
}
-static uint8_t *
-red_test_channel_client_alloc_msg_rcv_buf(RedChannelClient *rcc, uint16_t type, uint32_t size)
+uint8_t *
+RedTestChannelClient::alloc_recv_buf(uint16_t type, uint32_t size)
{
return (uint8_t*) g_malloc(size);
}
-static void
-red_test_channel_client_release_msg_rcv_buf(RedChannelClient *rcc,
- uint16_t type, uint32_t size, uint8_t *msg)
+void
+RedTestChannelClient::release_recv_buf(uint16_t type, uint32_t size, uint8_t *msg)
{
g_free(msg);
}
-static void
-red_test_channel_client_class_init(RedTestChannelClientClass *klass)
-{
- RedChannelClientClass *client_class = RED_CHANNEL_CLIENT_CLASS(klass);
- client_class->alloc_recv_buf = red_test_channel_client_alloc_msg_rcv_buf;
- client_class->release_recv_buf = red_test_channel_client_release_msg_rcv_buf;
-}
-
/*
* Main test part