summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorFrediano Ziglio <fziglio@redhat.com>2019-05-19 22:00:39 +0100
committerFrediano Ziglio <freddy77@gmail.com>2020-05-01 06:58:09 +0100
commit176970f3f18e26ef52f16155bc5fa6edbc60705a (patch)
tree713ca073daafa55d67b6cdbf767b2de31d242112
parent38cd152952968e37d0cc96e95e3e5e47a2f66c2f (diff)
red-channel-client: Remove GObject type
Make all RedChannelClient hierarchy a C++ class. This allows to use virtual methods. Added a normal contructor instead or properties and g_object_new. As we remove GObject conversion macros I added a macro XXX_CAST to create a function to replace the old macro. They will be removed when more type safety is introduced. There's a new SPICE_CXX_GLIB_ALLOCATOR macro in red-common.h. This macro, added to a class define the class allocator allowing to use, in this case, GLib for allocation. This to avoid C++ library dependency and to initialize all structure to 0 (not all fields are manually initialized, will be improved with more encapsulation). Currently the methods are mainly public, access will be modified when more encapsulation (all functions in method) are done. Some classes are now defined in the header, C++ uses access to limit accessibility but for efficiency and type safety/inline and other features require types to be defined in the headers. Some fields were moved from XxxPrivate structure to class, C++ has accessibility. Many destructors are defined as protected to forbid the use of stack, this as these objects uses internal reference counting to have normal pointers. Maybe in the future pointers like std::shared_ptr could be used instead. Reference counting is now implemented very easily using atomic operations. Signed-off-by: Frediano Ziglio <fziglio@redhat.com>
-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