Move RedCharDeviceCallbacks into RedCharDeviceClass

This structure holding virtual function pointers was kept until now as a
RedCharDevice member in order to make the GObject conversion easier.
Now that all RedCharDevice children are converted to GObject, it can be
moved into RedCharDeviceClass.
This commit is contained in:
Christophe Fergeau 2016-04-01 13:37:49 +01:00 committed by Jonathon Jongsma
parent 87b6b9273d
commit 0c6e51011b
5 changed files with 94 additions and 113 deletions

View File

@ -69,7 +69,6 @@ struct RedCharDevicePrivate {
int during_read_from_device;
int during_write_to_device;
RedCharDeviceCallbacks cbs;
void *opaque;
SpiceServer *reds;
};
@ -106,21 +105,27 @@ typedef struct RedCharDeviceMsgToClientItem {
static RedCharDeviceMsgToClient *
red_char_device_read_one_msg_from_device(RedCharDevice *dev)
{
return dev->priv->cbs.read_one_msg_from_device(dev->priv->sin, dev->priv->opaque);
RedCharDeviceClass *klass = RED_CHAR_DEVICE_GET_CLASS(dev);
return klass->read_one_msg_from_device(dev->priv->sin, dev->priv->opaque);
}
static RedCharDeviceMsgToClient *
red_char_device_ref_msg_to_client(RedCharDevice *dev,
RedCharDeviceMsgToClient *msg)
{
return dev->priv->cbs.ref_msg_to_client(msg, dev->priv->opaque);
RedCharDeviceClass *klass = RED_CHAR_DEVICE_GET_CLASS(dev);
return klass->ref_msg_to_client(msg, dev->priv->opaque);
}
static void
red_char_device_unref_msg_to_client(RedCharDevice *dev,
RedCharDeviceMsgToClient *msg)
{
dev->priv->cbs.unref_msg_to_client(msg, dev->priv->opaque);
RedCharDeviceClass *klass = RED_CHAR_DEVICE_GET_CLASS(dev);
klass->unref_msg_to_client(msg, dev->priv->opaque);
}
static void
@ -128,7 +133,9 @@ red_char_device_send_msg_to_client(RedCharDevice *dev,
RedCharDeviceMsgToClient *msg,
RedClient *client)
{
dev->priv->cbs.send_msg_to_client(msg, client, dev->priv->opaque);
RedCharDeviceClass *klass = RED_CHAR_DEVICE_GET_CLASS(dev);
klass->send_msg_to_client(msg, client, dev->priv->opaque);
}
static void
@ -136,21 +143,27 @@ red_char_device_send_tokens_to_client(RedCharDevice *dev,
RedClient *client,
uint32_t tokens)
{
dev->priv->cbs.send_tokens_to_client(client, tokens, dev->priv->opaque);
RedCharDeviceClass *klass = RED_CHAR_DEVICE_GET_CLASS(dev);
klass->send_tokens_to_client(client, tokens, dev->priv->opaque);
}
static void
red_char_device_on_free_self_token(RedCharDevice *dev)
{
if (dev->priv->cbs.on_free_self_token != NULL) {
dev->priv->cbs.on_free_self_token(dev->priv->opaque);
RedCharDeviceClass *klass = RED_CHAR_DEVICE_GET_CLASS(dev);
if (klass->on_free_self_token != NULL) {
klass->on_free_self_token(dev->priv->opaque);
}
}
static void
red_char_device_remove_client(RedCharDevice *dev, RedClient *client)
{
dev->priv->cbs.remove_client(client, dev->priv->opaque);
RedCharDeviceClass *klass = RED_CHAR_DEVICE_GET_CLASS(dev);
klass->remove_client(client, dev->priv->opaque);
}
static void red_char_device_write_buffer_free(RedCharDeviceWriteBuffer *buf)
@ -1234,17 +1247,3 @@ red_char_device_init(RedCharDevice *self)
g_signal_connect(self, "notify::sin", G_CALLBACK(red_char_device_on_sin_changed), NULL);
}
/* TODO: needs to be moved to class vfuncs once all child classes are gobjects */
void
red_char_device_set_callbacks(RedCharDevice *dev,
RedCharDeviceCallbacks *cbs,
gpointer opaque)
{
g_assert(cbs->read_one_msg_from_device && cbs->ref_msg_to_client &&
cbs->unref_msg_to_client && cbs->send_msg_to_client &&
cbs->send_tokens_to_client && cbs->remove_client);
dev->priv->cbs = *cbs;
dev->priv->opaque = opaque;
}

View File

@ -24,6 +24,8 @@
#include "red-channel.h"
#include "migration-protocol.h"
typedef void RedCharDeviceMsgToClient;
#define RED_TYPE_CHAR_DEVICE red_char_device_get_type()
#define RED_CHAR_DEVICE(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), RED_TYPE_CHAR_DEVICE, RedCharDevice))
@ -48,15 +50,40 @@ struct SpiceCharDeviceState
struct RedCharDeviceClass
{
GObjectClass parent_class;
/*
* Messages that are addressed to the client can be queued in case we have
* multiple clients and some of them don't have enough tokens.
*/
/* reads from the device till reaching a msg that should be sent to the client,
* or till the reading fails */
RedCharDeviceMsgToClient* (*read_one_msg_from_device)(SpiceCharDeviceInstance *sin,
void *opaque);
RedCharDeviceMsgToClient* (*ref_msg_to_client)(RedCharDeviceMsgToClient *msg,
void *opaque);
void (*unref_msg_to_client)(RedCharDeviceMsgToClient *msg,
void *opaque);
void (*send_msg_to_client)(RedCharDeviceMsgToClient *msg,
RedClient *client,
void *opaque); /* after this call, the message is unreferenced */
/* The cb is called when a predefined number of write buffers were consumed by the
* device */
void (*send_tokens_to_client)(RedClient *client, uint32_t tokens, void *opaque);
/* The cb is called when a server (self) message that was addressed to the device,
* has been completely written to it */
void (*on_free_self_token)(void *opaque);
/* This cb is called if it is recommanded that a client will be removed
* due to slow flow or due to some other error.
* The called instance should disconnect the client, or at least the corresponding channel */
void (*remove_client)(RedClient *client, void *opaque);
};
GType red_char_device_get_type(void) G_GNUC_CONST;
typedef struct RedCharDeviceCallbacks RedCharDeviceCallbacks;
void red_char_device_set_callbacks(RedCharDevice *dev,
RedCharDeviceCallbacks *cbs,
gpointer opaque);
/*
* Shared code for char devices, mainly for flow control.
*
@ -133,40 +160,6 @@ typedef struct RedCharDeviceWriteBuffer {
uint32_t refs;
} RedCharDeviceWriteBuffer;
typedef void RedCharDeviceMsgToClient;
struct RedCharDeviceCallbacks {
/*
* Messages that are addressed to the client can be queued in case we have
* multiple clients and some of them don't have enough tokens.
*/
/* reads from the device till reaching a msg that should be sent to the client,
* or till the reading fails */
RedCharDeviceMsgToClient* (*read_one_msg_from_device)(SpiceCharDeviceInstance *sin,
void *opaque);
RedCharDeviceMsgToClient* (*ref_msg_to_client)(RedCharDeviceMsgToClient *msg,
void *opaque);
void (*unref_msg_to_client)(RedCharDeviceMsgToClient *msg,
void *opaque);
void (*send_msg_to_client)(RedCharDeviceMsgToClient *msg,
RedClient *client,
void *opaque); /* after this call, the message is unreferenced */
/* The cb is called when a predefined number of write buffers were consumed by the
* device */
void (*send_tokens_to_client)(RedClient *client, uint32_t tokens, void *opaque);
/* The cb is called when a server (self) message that was addressed to the device,
* has been completely written to it */
void (*on_free_self_token)(void *opaque);
/* This cb is called if it is recommanded that a client will be removed
* due to slow flow or due to some other error.
* The called instance should disconnect the client, or at least the corresponding channel */
void (*remove_client)(RedClient *client, void *opaque);
};
void red_char_device_reset_dev_instance(RedCharDevice *dev,
SpiceCharDeviceInstance *sin);
void red_char_device_destroy(RedCharDevice *dev);

View File

@ -4322,33 +4322,28 @@ static void
red_char_device_vdi_port_class_init(RedCharDeviceVDIPortClass *klass)
{
GObjectClass *object_class = G_OBJECT_CLASS(klass);
RedCharDeviceClass *char_dev_class = RED_CHAR_DEVICE_CLASS(klass);
g_type_class_add_private(klass, sizeof (RedCharDeviceVDIPortPrivate));
object_class->finalize = red_char_device_vdi_port_finalize;
object_class->constructed = red_char_device_vdi_port_constructed;
char_dev_class->read_one_msg_from_device = vdi_port_read_one_msg_from_device;
char_dev_class->ref_msg_to_client = vdi_port_ref_msg_to_client;
char_dev_class->unref_msg_to_client = vdi_port_unref_msg_to_client;
char_dev_class->send_msg_to_client = vdi_port_send_msg_to_client;
char_dev_class->send_tokens_to_client = vdi_port_send_tokens_to_client;
char_dev_class->remove_client = vdi_port_remove_client;
char_dev_class->on_free_self_token = vdi_port_on_free_self_token;
}
static RedCharDeviceVDIPort *red_char_device_vdi_port_new(RedsState *reds)
{
RedCharDevice *char_dev;
RedCharDeviceCallbacks char_dev_cbs = {
.read_one_msg_from_device = vdi_port_read_one_msg_from_device,
.ref_msg_to_client = vdi_port_ref_msg_to_client,
.unref_msg_to_client = vdi_port_unref_msg_to_client,
.send_msg_to_client = vdi_port_send_msg_to_client,
.send_tokens_to_client = vdi_port_send_tokens_to_client,
.remove_client = vdi_port_remove_client,
.on_free_self_token = vdi_port_on_free_self_token,
};
char_dev = g_object_new(RED_TYPE_CHAR_DEVICE_VDIPORT,
"spice-server", reds,
"client-tokens-interval", REDS_TOKENS_TO_SEND,
"self-tokens", REDS_NUM_INTERNAL_AGENT_MESSAGES,
NULL);
red_char_device_set_callbacks(RED_CHAR_DEVICE(char_dev),
&char_dev_cbs, reds);
return RED_CHAR_DEVICE_VDIPORT(char_dev);
return g_object_new(RED_TYPE_CHAR_DEVICE_VDIPORT,
"spice-server", reds,
"client-tokens-interval", REDS_TOKENS_TO_SEND,
"self-tokens", REDS_NUM_INTERNAL_AGENT_MESSAGES,
"opaque", reds,
NULL);
}

View File

@ -272,14 +272,6 @@ static SpiceCharDeviceInstance *smartcard_readers_get_unattached(void)
static RedCharDeviceSmartcard *smartcard_device_new(RedsState *reds, SpiceCharDeviceInstance *sin)
{
RedCharDevice *char_dev;
RedCharDeviceCallbacks char_dev_cbs = {
.read_one_msg_from_device = smartcard_read_msg_from_device,
.ref_msg_to_client = smartcard_ref_msg_to_client,
.unref_msg_to_client = smartcard_unref_msg_to_client,
.send_msg_to_client = smartcard_send_msg_to_client,
.send_tokens_to_client = smartcard_send_tokens_to_client,
.remove_client = smartcard_remove_client,
};
char_dev = g_object_new(RED_TYPE_CHAR_DEVICE_SMARTCARD,
"sin", sin,
@ -288,8 +280,8 @@ static RedCharDeviceSmartcard *smartcard_device_new(RedsState *reds, SpiceCharDe
"self-tokens", ~0ULL,
NULL);
red_char_device_set_callbacks(RED_CHAR_DEVICE(char_dev),
&char_dev_cbs, char_dev);
g_object_set(char_dev, "opaque", char_dev, NULL);
return RED_CHAR_DEVICE_SMARTCARD(char_dev);
}
@ -869,10 +861,18 @@ static void
red_char_device_smartcard_class_init(RedCharDeviceSmartcardClass *klass)
{
GObjectClass *object_class = G_OBJECT_CLASS(klass);
RedCharDeviceClass *char_dev_class = RED_CHAR_DEVICE_CLASS(klass);
g_type_class_add_private(klass, sizeof (RedCharDeviceSmartcardPrivate));
object_class->finalize = red_char_device_smartcard_finalize;
char_dev_class->read_one_msg_from_device = smartcard_read_msg_from_device;
char_dev_class->ref_msg_to_client = smartcard_ref_msg_to_client;
char_dev_class->unref_msg_to_client = smartcard_unref_msg_to_client;
char_dev_class->send_msg_to_client = smartcard_send_msg_to_client;
char_dev_class->send_tokens_to_client = smartcard_send_tokens_to_client;
char_dev_class->remove_client = smartcard_remove_client;
}
static void

View File

@ -611,6 +611,14 @@ SPICE_GNUC_VISIBLE void spice_server_port_event(SpiceCharDeviceInstance *sin, ui
static void
red_char_device_spicevmc_class_init(RedCharDeviceSpiceVmcClass *klass)
{
RedCharDeviceClass *char_dev_class = RED_CHAR_DEVICE_CLASS(klass);
char_dev_class->read_one_msg_from_device = spicevmc_chardev_read_msg_from_dev;
char_dev_class->ref_msg_to_client = spicevmc_chardev_ref_msg_to_client;
char_dev_class->unref_msg_to_client = spicevmc_chardev_unref_msg_to_client;
char_dev_class->send_msg_to_client = spicevmc_chardev_send_msg_to_client;
char_dev_class->send_tokens_to_client = spicevmc_char_dev_send_tokens_to_client;
char_dev_class->remove_client = spicevmc_char_dev_remove_client;
}
static void
@ -623,25 +631,11 @@ red_char_device_spicevmc_new(SpiceCharDeviceInstance *sin,
RedsState *reds,
void *opaque)
{
RedCharDevice *char_dev;
RedCharDeviceCallbacks char_dev_cbs = {
.read_one_msg_from_device = spicevmc_chardev_read_msg_from_dev,
.ref_msg_to_client = spicevmc_chardev_ref_msg_to_client,
.unref_msg_to_client = spicevmc_chardev_unref_msg_to_client,
.send_msg_to_client = spicevmc_chardev_send_msg_to_client,
.send_tokens_to_client = spicevmc_char_dev_send_tokens_to_client,
.remove_client = spicevmc_char_dev_remove_client,
};
char_dev = g_object_new(RED_TYPE_CHAR_DEVICE_SPICEVMC,
"sin", sin,
"spice-server", reds,
"client-tokens-interval", 0ULL,
"self-tokens", ~0ULL,
"opaque", opaque,
NULL);
red_char_device_set_callbacks(RED_CHAR_DEVICE(char_dev),
&char_dev_cbs, opaque);
return char_dev;
return g_object_new(RED_TYPE_CHAR_DEVICE_SPICEVMC,
"sin", sin,
"spice-server", reds,
"client-tokens-interval", 0ULL,
"self-tokens", ~0ULL,
"opaque", opaque,
NULL);
}