red-channel-client: Make send_item a virtual function

The items are send from RedChannelClient so move the callback
to a virtual function in RedChannelClient instead of RedChannel.

Signed-off-by: Frediano Ziglio <fziglio@redhat.com>
This commit is contained in:
Frediano Ziglio 2019-05-23 04:35:56 +01:00 committed by Frediano Ziglio
parent 851696a645
commit 669df4fb38
20 changed files with 173 additions and 205 deletions

View File

@ -37,7 +37,11 @@ public:
RedClient *client,
RedStream *stream,
RedChannelCapabilities *caps);
protected:
virtual void on_disconnect() override;
void send_item(RedPipeItem *pipe_item) override;
public:
red::unique_link<CursorChannelClientPrivate> priv;
};

View File

@ -193,19 +193,17 @@ 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)
void CursorChannelClient::send_item(RedPipeItem *pipe_item)
{
SpiceMarshaller *m = rcc->get_marshaller();
CursorChannelClient *ccc = CURSOR_CHANNEL_CLIENT(rcc);
SpiceMarshaller *m = get_marshaller();
CursorChannelClient *ccc = this;
switch (pipe_item->type) {
case RED_PIPE_ITEM_TYPE_CURSOR:
red_marshall_cursor(ccc, m, SPICE_UPCAST(RedCursorPipeItem, pipe_item));
break;
case RED_PIPE_ITEM_TYPE_INVAL_ONE:
red_marshall_inval(rcc, m, SPICE_CONTAINEROF(pipe_item, RedCacheItem, u.pipe_data));
red_marshall_inval(this, m, SPICE_CONTAINEROF(pipe_item, RedCacheItem, u.pipe_data));
break;
case RED_PIPE_ITEM_TYPE_CURSOR_INIT:
cursor_channel_client_reset_cursor_cache(ccc);
@ -219,7 +217,7 @@ static void cursor_channel_send_item(RedChannelClient *rcc, RedPipeItem *pipe_it
spice_error("invalid pipe item type");
}
rcc->begin_send_message();
begin_send_message();
}
CursorChannel* cursor_channel_new(RedsState *server, int id,
@ -386,8 +384,6 @@ cursor_channel_class_init(CursorChannelClass *klass)
channel_class->parser = spice_get_client_channel_parser(SPICE_CHANNEL_CURSOR, NULL);
channel_class->send_item = cursor_channel_send_item;
// client callbacks
channel_class->connect = (channel_client_connect_proc) cursor_channel_connect;
channel_class->migrate = cursor_channel_client_migrate;

View File

@ -2383,86 +2383,86 @@ static void reset_send_data(DisplayChannelClient *dcc)
sizeof(dcc->priv->send_data.free_list.sync));
}
void dcc_send_item(RedChannelClient *rcc, RedPipeItem *pipe_item)
void DisplayChannelClient::send_item(RedPipeItem *pipe_item)
{
DisplayChannelClient *dcc = DISPLAY_CHANNEL_CLIENT(rcc);
SpiceMarshaller *m = rcc->get_marshaller();
DisplayChannelClient *dcc = this;
SpiceMarshaller *m = get_marshaller();
reset_send_data(dcc);
::reset_send_data(dcc);
switch (pipe_item->type) {
case RED_PIPE_ITEM_TYPE_DRAW: {
RedDrawablePipeItem *dpi = SPICE_UPCAST(RedDrawablePipeItem, pipe_item);
marshall_qxl_drawable(rcc, m, dpi);
marshall_qxl_drawable(this, m, dpi);
break;
}
case RED_PIPE_ITEM_TYPE_INVAL_ONE:
marshall_inval_palette(rcc, m, SPICE_CONTAINEROF(pipe_item, RedCacheItem, u.pipe_data));
marshall_inval_palette(this, m, SPICE_CONTAINEROF(pipe_item, RedCacheItem, u.pipe_data));
break;
case RED_PIPE_ITEM_TYPE_STREAM_CREATE: {
StreamCreateDestroyItem *item = SPICE_UPCAST(StreamCreateDestroyItem, pipe_item);
marshall_stream_start(rcc, m, item->agent);
marshall_stream_start(this, m, item->agent);
break;
}
case RED_PIPE_ITEM_TYPE_STREAM_CLIP:
marshall_stream_clip(rcc, m, SPICE_UPCAST(VideoStreamClipItem, pipe_item));
marshall_stream_clip(this, m, SPICE_UPCAST(VideoStreamClipItem, pipe_item));
break;
case RED_PIPE_ITEM_TYPE_STREAM_DESTROY: {
StreamCreateDestroyItem *item = SPICE_UPCAST(StreamCreateDestroyItem, pipe_item);
marshall_stream_end(rcc, m, item->agent);
marshall_stream_end(this, m, item->agent);
break;
}
case RED_PIPE_ITEM_TYPE_UPGRADE:
marshall_upgrade(rcc, m, SPICE_UPCAST(RedUpgradeItem, pipe_item));
marshall_upgrade(this, m, SPICE_UPCAST(RedUpgradeItem, pipe_item));
break;
case RED_PIPE_ITEM_TYPE_MIGRATE_DATA:
display_channel_marshall_migrate_data(rcc, m);
display_channel_marshall_migrate_data(this, m);
break;
case RED_PIPE_ITEM_TYPE_IMAGE:
red_marshall_image(rcc, m, SPICE_UPCAST(RedImageItem, pipe_item));
red_marshall_image(this, m, SPICE_UPCAST(RedImageItem, pipe_item));
break;
case RED_PIPE_ITEM_TYPE_PIXMAP_SYNC:
display_channel_marshall_pixmap_sync(rcc, m);
display_channel_marshall_pixmap_sync(this, m);
break;
case RED_PIPE_ITEM_TYPE_PIXMAP_RESET:
display_channel_marshall_reset_cache(rcc, m);
display_channel_marshall_reset_cache(this, m);
break;
case RED_PIPE_ITEM_TYPE_INVAL_PALETTE_CACHE:
dcc_palette_cache_reset(dcc);
rcc->init_send_data(SPICE_MSG_DISPLAY_INVAL_ALL_PALETTES);
init_send_data(SPICE_MSG_DISPLAY_INVAL_ALL_PALETTES);
break;
case RED_PIPE_ITEM_TYPE_CREATE_SURFACE: {
RedSurfaceCreateItem *surface_create = SPICE_UPCAST(RedSurfaceCreateItem, pipe_item);
marshall_surface_create(rcc, m, &surface_create->surface_create);
marshall_surface_create(this, m, &surface_create->surface_create);
break;
}
case RED_PIPE_ITEM_TYPE_DESTROY_SURFACE: {
RedSurfaceDestroyItem *surface_destroy = SPICE_UPCAST(RedSurfaceDestroyItem, pipe_item);
marshall_surface_destroy(rcc, m, surface_destroy->surface_destroy.surface_id);
marshall_surface_destroy(this, m, surface_destroy->surface_destroy.surface_id);
break;
}
case RED_PIPE_ITEM_TYPE_MONITORS_CONFIG: {
RedMonitorsConfigItem *monconf_item = SPICE_UPCAST(RedMonitorsConfigItem, pipe_item);
marshall_monitors_config(rcc, m, monconf_item->monitors_config);
marshall_monitors_config(this, m, monconf_item->monitors_config);
break;
}
case RED_PIPE_ITEM_TYPE_STREAM_ACTIVATE_REPORT: {
RedStreamActivateReportItem *report_item =
SPICE_UPCAST(RedStreamActivateReportItem, pipe_item);
marshall_stream_activate_report(rcc, m, report_item);
marshall_stream_activate_report(this, m, report_item);
break;
}
case RED_PIPE_ITEM_TYPE_GL_SCANOUT:
marshall_gl_scanout(rcc, m, pipe_item);
marshall_gl_scanout(this, m, pipe_item);
break;
case RED_PIPE_ITEM_TYPE_GL_DRAW:
marshall_gl_draw(rcc, m, pipe_item);
marshall_gl_draw(this, m, pipe_item);
break;
default:
spice_warn_if_reached();
}
// a message is pending
if (rcc->send_message_pending()) {
begin_send_message(rcc);
if (send_message_pending()) {
::begin_send_message(this);
}
}

View File

@ -44,10 +44,13 @@ public:
spice_wan_compression_t jpeg_state,
spice_wan_compression_t zlib_glz_state);
protected:
virtual bool handle_message(uint16_t type, uint32_t size, void *message) override;
virtual bool config_socket() override;
virtual void on_disconnect() override;
virtual void send_item(RedPipeItem *item) override;
public:
red::unique_link<DisplayChannelClientPrivate> priv;
int is_low_bandwidth;
@ -162,8 +165,6 @@ void dcc_append_drawable (DisplayCha
void dcc_add_drawable_after (DisplayChannelClient *dcc,
Drawable *drawable,
RedPipeItem *pos);
void dcc_send_item (RedChannelClient *dcc,
RedPipeItem *item);
bool dcc_clear_surface_drawables_from_pipe (DisplayChannelClient *dcc,
int surface_id,
int wait_if_used);

View File

@ -2509,7 +2509,6 @@ display_channel_class_init(DisplayChannelClass *klass)
channel_class->parser = spice_get_client_channel_parser(SPICE_CHANNEL_DISPLAY, NULL);
channel_class->send_item = dcc_send_item;
channel_class->handle_migrate_flush_mark = handle_migrate_flush_mark;
channel_class->handle_migrate_data = handle_migrate_data;
channel_class->handle_migrate_data_get_serial = handle_migrate_data_get_serial;

View File

@ -43,9 +43,11 @@ public:
using RedChannelClient::RedChannelClient;
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 void on_disconnect() override;
virtual void send_item(RedPipeItem *base) override;
};
RedChannelClient* inputs_channel_client_create(RedChannel *channel,

View File

@ -232,16 +232,16 @@ static RedPipeItem *red_inputs_key_modifiers_item_new(uint8_t modifiers)
return &item->base;
}
static void inputs_channel_send_item(RedChannelClient *rcc, RedPipeItem *base)
void InputsChannelClient::send_item(RedPipeItem *base)
{
SpiceMarshaller *m = rcc->get_marshaller();
SpiceMarshaller *m = get_marshaller();
switch (base->type) {
case RED_PIPE_ITEM_KEY_MODIFIERS:
{
SpiceMsgInputsKeyModifiers key_modifiers;
rcc->init_send_data(SPICE_MSG_INPUTS_KEY_MODIFIERS);
init_send_data(SPICE_MSG_INPUTS_KEY_MODIFIERS);
key_modifiers.modifiers =
SPICE_UPCAST(RedKeyModifiersPipeItem, base)->modifiers;
spice_marshall_msg_inputs_key_modifiers(m, &key_modifiers);
@ -251,24 +251,24 @@ static void inputs_channel_send_item(RedChannelClient *rcc, RedPipeItem *base)
{
SpiceMsgInputsInit inputs_init;
rcc->init_send_data(SPICE_MSG_INPUTS_INIT);
init_send_data(SPICE_MSG_INPUTS_INIT);
inputs_init.keyboard_modifiers =
SPICE_UPCAST(RedInputsInitPipeItem, base)->modifiers;
spice_marshall_msg_inputs_init(m, &inputs_init);
break;
}
case RED_PIPE_ITEM_MOUSE_MOTION_ACK:
rcc->init_send_data(SPICE_MSG_INPUTS_MOUSE_MOTION_ACK);
init_send_data(SPICE_MSG_INPUTS_MOUSE_MOTION_ACK);
break;
case RED_PIPE_ITEM_MIGRATE_DATA:
INPUTS_CHANNEL(rcc->get_channel())->src_during_migrate = FALSE;
inputs_channel_client_send_migrate_data(rcc, m, base);
INPUTS_CHANNEL(get_channel())->src_during_migrate = FALSE;
inputs_channel_client_send_migrate_data(this, m, base);
break;
default:
spice_warning("invalid pipe iten %d", base->type);
break;
}
rcc->begin_send_message();
begin_send_message();
}
bool InputsChannelClient::handle_message(uint16_t type, uint32_t size, void *message)
@ -616,7 +616,6 @@ inputs_channel_class_init(InputsChannelClass *klass)
channel_class->parser = spice_get_client_channel_parser(SPICE_CHANNEL_INPUTS, NULL);
/* channel callbacks */
channel_class->send_item = inputs_channel_send_item;
channel_class->handle_migrate_data = inputs_channel_handle_migrate_data;
channel_class->handle_migrate_flush_mark = inputs_channel_handle_migrate_flush_mark;

View File

@ -634,15 +634,14 @@ static void main_channel_marshall_channels(RedChannelClient *rcc,
g_free(channels_info);
}
static void main_channel_marshall_ping(RedChannelClient *rcc,
static void main_channel_marshall_ping(MainChannelClient *mcc,
SpiceMarshaller *m,
RedPingPipeItem *item)
{
MainChannelClient *mcc = MAIN_CHANNEL_CLIENT(rcc);
SpiceMsgPing ping;
int size_left = item->size;
rcc->init_send_data(SPICE_MSG_PING);
mcc->init_send_data(SPICE_MSG_PING);
ping.id = main_channel_client_next_ping_id(mcc);
ping.timestamp = spice_get_monotonic_time_ns() / NSEC_PER_MICROSEC;
spice_marshall_msg_ping(m, &ping);
@ -854,97 +853,96 @@ static void main_channel_marshall_registered_channel(RedChannelClient *rcc,
spice_marshall_msg_main_channels_list(m, channels_info);
}
void main_channel_client_send_item(RedChannelClient *rcc, RedPipeItem *base)
void MainChannelClient::send_item(RedPipeItem *base)
{
MainChannelClient *mcc = MAIN_CHANNEL_CLIENT(rcc);
SpiceMarshaller *m = rcc->get_marshaller();
SpiceMarshaller *m = get_marshaller();
/* In semi-seamless migration (dest side), the connection is started from scratch, and
* we ignore any pipe item that arrives before the INIT msg is sent.
* For seamless we don't send INIT, and the connection continues from the same place
* it stopped on the src side. */
if (!mcc->priv->init_sent &&
!mcc->priv->seamless_mig_dst &&
if (!priv->init_sent &&
!priv->seamless_mig_dst &&
base->type != RED_PIPE_ITEM_TYPE_MAIN_INIT) {
red_channel_warning(rcc->get_channel(),
red_channel_warning(get_channel(),
"Init msg for client %p was not sent yet "
"(client is probably during semi-seamless migration). Ignoring msg type %d",
rcc->get_client(), base->type);
get_client(), base->type);
return;
}
switch (base->type) {
case RED_PIPE_ITEM_TYPE_MAIN_CHANNELS_LIST:
main_channel_marshall_channels(rcc, m, base);
mcc->priv->initial_channels_list_sent = true;
main_channel_marshall_channels(this, m, base);
priv->initial_channels_list_sent = true;
break;
case RED_PIPE_ITEM_TYPE_MAIN_PING:
main_channel_marshall_ping(rcc, m,
main_channel_marshall_ping(this, m,
SPICE_UPCAST(RedPingPipeItem, base));
break;
case RED_PIPE_ITEM_TYPE_MAIN_MOUSE_MODE:
main_channel_marshall_mouse_mode(rcc, m,
main_channel_marshall_mouse_mode(this, m,
SPICE_UPCAST(RedMouseModePipeItem, base));
break;
case RED_PIPE_ITEM_TYPE_MAIN_AGENT_DISCONNECTED:
main_channel_marshall_agent_disconnected(rcc, m, base);
main_channel_marshall_agent_disconnected(this, m, base);
break;
case RED_PIPE_ITEM_TYPE_MAIN_AGENT_TOKEN:
main_channel_marshall_tokens(rcc, m,
main_channel_marshall_tokens(this, m,
SPICE_UPCAST(RedTokensPipeItem, base));
break;
case RED_PIPE_ITEM_TYPE_MAIN_AGENT_DATA:
main_channel_marshall_agent_data(rcc, m,
main_channel_marshall_agent_data(this, m,
SPICE_UPCAST(RedAgentDataPipeItem, base));
break;
case RED_PIPE_ITEM_TYPE_MAIN_MIGRATE_DATA:
main_channel_marshall_migrate_data_item(rcc, m, base);
main_channel_marshall_migrate_data_item(this, m, base);
break;
case RED_PIPE_ITEM_TYPE_MAIN_INIT:
mcc->priv->init_sent = TRUE;
main_channel_marshall_init(rcc, m,
priv->init_sent = TRUE;
main_channel_marshall_init(this, m,
SPICE_UPCAST(RedInitPipeItem, base));
break;
case RED_PIPE_ITEM_TYPE_MAIN_NOTIFY:
main_channel_marshall_notify(rcc, m,
main_channel_marshall_notify(this, m,
SPICE_UPCAST(RedNotifyPipeItem, base));
break;
case RED_PIPE_ITEM_TYPE_MAIN_MIGRATE_BEGIN:
main_channel_marshall_migrate_begin(m, rcc, base);
main_channel_marshall_migrate_begin(m, this, base);
break;
case RED_PIPE_ITEM_TYPE_MAIN_MIGRATE_BEGIN_SEAMLESS:
main_channel_marshall_migrate_begin_seamless(m, rcc, base);
main_channel_marshall_migrate_begin_seamless(m, this, base);
break;
case RED_PIPE_ITEM_TYPE_MAIN_MULTI_MEDIA_TIME:
main_channel_marshall_multi_media_time(rcc, m,
main_channel_marshall_multi_media_time(this, m,
SPICE_UPCAST(RedMultiMediaTimePipeItem, base));
break;
case RED_PIPE_ITEM_TYPE_MAIN_MIGRATE_SWITCH_HOST:
main_channel_marshall_migrate_switch(m, rcc, base);
main_channel_marshall_migrate_switch(m, this, base);
break;
case RED_PIPE_ITEM_TYPE_MAIN_NAME:
rcc->init_send_data(SPICE_MSG_MAIN_NAME);
init_send_data(SPICE_MSG_MAIN_NAME);
spice_marshall_msg_main_name(m, &SPICE_UPCAST(RedNamePipeItem, base)->msg);
break;
case RED_PIPE_ITEM_TYPE_MAIN_UUID:
rcc->init_send_data(SPICE_MSG_MAIN_UUID);
init_send_data(SPICE_MSG_MAIN_UUID);
spice_marshall_msg_main_uuid(m, &SPICE_UPCAST(RedUuidPipeItem, base)->msg);
break;
case RED_PIPE_ITEM_TYPE_MAIN_AGENT_CONNECTED_TOKENS:
main_channel_marshall_agent_connected(m, rcc, base);
main_channel_marshall_agent_connected(m, this, base);
break;
case RED_PIPE_ITEM_TYPE_MAIN_REGISTERED_CHANNEL:
/* The spice protocol requires that the server receive a ATTACH_CHANNELS
* message from the client before sending any CHANNEL_LIST message. If
* we've already sent our initial CHANNELS_LIST message, then it should be
* safe to send new ones for newly-registered channels. */
if (!mcc->priv->initial_channels_list_sent) {
if (!priv->initial_channels_list_sent) {
return;
}
main_channel_marshall_registered_channel(rcc, m,
main_channel_marshall_registered_channel(this, m,
SPICE_UPCAST(RedRegisteredChannelPipeItem, base));
break;
default:
break;
};
rcc->begin_send_message();
begin_send_message();
}

View File

@ -42,6 +42,7 @@ protected:
virtual void release_recv_buf(uint16_t type, uint32_t size, uint8_t *msg) override;
virtual void on_disconnect() override;
virtual bool handle_message(uint16_t type, uint32_t size, void *message) override;
virtual void send_item(RedPipeItem *item) override;
public:
red::unique_link<MainChannelClientPrivate> priv;
@ -93,7 +94,6 @@ void main_channel_client_push_name(MainChannelClient *mcc, const char *name);
void main_channel_client_push_uuid(MainChannelClient *mcc, const uint8_t uuid[16]);
uint32_t main_channel_client_get_connection_id(MainChannelClient *mcc);
void main_channel_client_send_item(RedChannelClient *rcc, RedPipeItem *base);
enum {
RED_PIPE_ITEM_TYPE_MAIN_CHANNELS_LIST = RED_PIPE_ITEM_TYPE_CHANNEL_BASE,

View File

@ -278,7 +278,6 @@ main_channel_class_init(MainChannelClass *klass)
channel_class->parser = spice_get_client_channel_parser(SPICE_CHANNEL_MAIN, NULL);
/* channel callbacks */
channel_class->send_item = main_channel_client_send_item;
channel_class->handle_migrate_flush_mark = main_channel_handle_migrate_flush_mark;
channel_class->handle_migrate_data = main_channel_handle_migrate_data;

View File

@ -517,7 +517,7 @@ void RedChannelClient::send_any_item(RedPipeItem *item)
SPICE_UPCAST(MarkerPipeItem, item)->item_sent = true;
break;
default:
priv->channel->send_item(this, item);
send_item(item);
break;
}
red_pipe_item_unref(item);

View File

@ -159,6 +159,13 @@ public:
virtual void on_disconnect() {};
// TODO: add ASSERTS for thread_id in client and channel calls
/*
* callbacks that are triggered from channel client stream events.
* They are called from the thread that listen to the stream events.
*/
virtual void send_item(RedPipeItem *item) {};
/* Private functions */
private:
void send_any_item(RedPipeItem *item);

View File

@ -693,14 +693,6 @@ SpiceCoreInterfaceInternal* RedChannel::get_core_interface()
return priv->core;
}
void RedChannel::send_item(RedChannelClient *rcc, RedPipeItem *item)
{
RedChannelClass *klass = RED_CHANNEL_GET_CLASS(this);
g_return_if_fail(klass->send_item);
klass->send_item(rcc, item);
}
void RedChannel::reset_thread_id()
{
priv->thread_id = pthread_self();

View File

@ -44,8 +44,6 @@ struct RedChannelClient;
struct RedClient;
struct MainChannelClient;
typedef void (*channel_send_pipe_item_proc)(RedChannelClient *rcc, RedPipeItem *item);
typedef bool (*channel_handle_migrate_flush_mark_proc)(RedChannelClient *base);
typedef bool (*channel_handle_migrate_data_proc)(RedChannelClient *base,
uint32_t size, void *message);
@ -77,12 +75,6 @@ struct RedChannelClass
*/
spice_parse_channel_func_t parser;
// TODO: add ASSERTS for thread_id in client and channel calls
/*
* callbacks that are triggered from channel client stream events.
* They are called from the thread that listen to the stream events.
*/
channel_send_pipe_item_proc send_item;
channel_handle_migrate_flush_mark_proc handle_migrate_flush_mark;
channel_handle_migrate_data_proc handle_migrate_data;
channel_handle_migrate_data_get_serial_proc handle_migrate_data_get_serial;
@ -180,7 +172,6 @@ struct RedChannel: public GObject
SpiceCoreInterfaceInternal* get_core_interface();
/* channel callback function */
void send_item(RedChannelClient *rcc, RedPipeItem *item);
void reset_thread_id();
const RedStatNode *get_stat_node();

View File

@ -41,6 +41,7 @@ private:
virtual void release_recv_buf(uint16_t type, uint32_t size, uint8_t *msg) override;
virtual void on_disconnect() override;
virtual bool handle_message(uint16_t type, uint32_t size, void *message) override;
virtual void send_item(RedPipeItem *item) override;
};
SmartCardChannelClient* smartcard_channel_client_create(RedChannel *channel,

View File

@ -30,8 +30,6 @@
#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,
@ -395,16 +393,14 @@ static void smartcard_channel_send_msg(RedChannelClient *rcc,
smartcard_channel_client_send_data(rcc, m, item, msg_item->vheader);
}
static void smartcard_channel_send_migrate_data(RedChannelClient *rcc,
static void smartcard_channel_send_migrate_data(SmartCardChannelClient *scc,
SpiceMarshaller *m, RedPipeItem *item)
{
SmartCardChannelClient *scc;
RedCharDeviceSmartcard *dev;
SpiceMarshaller *m2;
scc = SMARTCARD_CHANNEL_CLIENT(rcc);
dev = smartcard_channel_client_get_char_device(scc);
rcc->init_send_data(SPICE_MSG_MIGRATE_DATA);
scc->init_send_data(SPICE_MSG_MIGRATE_DATA);
spice_marshaller_add_uint32(m, SPICE_MIGRATE_DATA_SMARTCARD_MAGIC);
spice_marshaller_add_uint32(m, SPICE_MIGRATE_DATA_SMARTCARD_VERSION);
@ -424,25 +420,25 @@ static void smartcard_channel_send_migrate_data(RedChannelClient *rcc,
}
}
static void smartcard_channel_send_item(RedChannelClient *rcc, RedPipeItem *item)
void SmartCardChannelClient::send_item(RedPipeItem *item)
{
SpiceMarshaller *m = rcc->get_marshaller();
SpiceMarshaller *m = get_marshaller();
switch (item->type) {
case RED_PIPE_ITEM_TYPE_ERROR:
smartcard_channel_client_send_error(rcc, m, item);
smartcard_channel_client_send_error(this, m, item);
break;
case RED_PIPE_ITEM_TYPE_SMARTCARD_DATA:
smartcard_channel_send_msg(rcc, m, item);
smartcard_channel_send_msg(this, m, item);
break;
case RED_PIPE_ITEM_TYPE_SMARTCARD_MIGRATE_DATA:
smartcard_channel_send_migrate_data(rcc, m, item);
smartcard_channel_send_migrate_data(this, m, item);
break;
default:
spice_error("bad pipe item %d", item->type);
return;
}
rcc->begin_send_message();
begin_send_message();
}
static void smartcard_free_vsc_msg_item(RedPipeItem *base)
@ -560,7 +556,6 @@ red_smartcard_channel_class_init(RedSmartcardChannelClass *klass)
channel_class->parser = spice_get_client_channel_parser(SPICE_CHANNEL_SMARTCARD, NULL);
channel_class->send_item = smartcard_channel_send_item;
channel_class->handle_migrate_flush_mark = smartcard_channel_client_handle_migrate_flush_mark;
channel_class->handle_migrate_data = smartcard_channel_client_handle_migrate_data;

View File

@ -149,6 +149,8 @@ public:
uint32_t latency = 0;
SndCodec codec = nullptr;
uint8_t encode_buf[SND_CODEC_MAX_COMPRESSED_BYTES];
protected:
virtual void send_item(RedPipeItem *item) override;
};
typedef struct SpiceVolumeState {
@ -223,8 +225,9 @@ public:
uint32_t start_time = 0;
SndCodec codec = nullptr;
uint8_t decode_buf[SND_CODEC_MAX_FRAME_BYTES];
public:
protected:
virtual bool handle_message(uint16_t type, uint32_t size, void *message) override;
virtual void send_item(RedPipeItem *item) override;
};
@ -660,99 +663,93 @@ static void snd_send(SndChannelClient * client)
XXX_CAST(RedChannelClient, PlaybackChannelClient, PLAYBACK_CHANNEL_CLIENT)
static void playback_channel_send_item(RedChannelClient *rcc, G_GNUC_UNUSED RedPipeItem *item)
void PlaybackChannelClient::send_item(G_GNUC_UNUSED RedPipeItem *item)
{
PlaybackChannelClient *playback_client = PLAYBACK_CHANNEL_CLIENT(rcc);
SndChannelClient *client = playback_client;
client->command &= SND_PLAYBACK_MODE_MASK|SND_PLAYBACK_PCM_MASK|
SND_CTRL_MASK|SND_VOLUME_MUTE_MASK|
SND_MIGRATE_MASK|SND_PLAYBACK_LATENCY_MASK;
while (client->command) {
if (client->command & SND_PLAYBACK_MODE_MASK) {
client->command &= ~SND_PLAYBACK_MODE_MASK;
if (playback_send_mode(playback_client)) {
command &= SND_PLAYBACK_MODE_MASK|SND_PLAYBACK_PCM_MASK|
SND_CTRL_MASK|SND_VOLUME_MUTE_MASK|
SND_MIGRATE_MASK|SND_PLAYBACK_LATENCY_MASK;
while (command) {
if (command & SND_PLAYBACK_MODE_MASK) {
command &= ~SND_PLAYBACK_MODE_MASK;
if (playback_send_mode(this)) {
break;
}
}
if (client->command & SND_PLAYBACK_PCM_MASK) {
spice_assert(!playback_client->in_progress && playback_client->pending_frame);
playback_client->in_progress = playback_client->pending_frame;
playback_client->pending_frame = NULL;
client->command &= ~SND_PLAYBACK_PCM_MASK;
if (snd_playback_send_write(playback_client)) {
if (command & SND_PLAYBACK_PCM_MASK) {
spice_assert(!in_progress && pending_frame);
in_progress = pending_frame;
pending_frame = NULL;
command &= ~SND_PLAYBACK_PCM_MASK;
if (snd_playback_send_write(this)) {
break;
}
red_channel_warning(rcc->get_channel(),
red_channel_warning(get_channel(),
"snd_send_playback_write failed");
}
if (client->command & SND_CTRL_MASK) {
client->command &= ~SND_CTRL_MASK;
if (snd_playback_send_ctl(playback_client)) {
if (command & SND_CTRL_MASK) {
command &= ~SND_CTRL_MASK;
if (snd_playback_send_ctl(this)) {
break;
}
}
if (client->command & SND_VOLUME_MASK) {
client->command &= ~SND_VOLUME_MASK;
if (snd_playback_send_volume(playback_client)) {
if (command & SND_VOLUME_MASK) {
command &= ~SND_VOLUME_MASK;
if (snd_playback_send_volume(this)) {
break;
}
}
if (client->command & SND_MUTE_MASK) {
client->command &= ~SND_MUTE_MASK;
if (snd_playback_send_mute(playback_client)) {
if (command & SND_MUTE_MASK) {
command &= ~SND_MUTE_MASK;
if (snd_playback_send_mute(this)) {
break;
}
}
if (client->command & SND_MIGRATE_MASK) {
client->command &= ~SND_MIGRATE_MASK;
if (snd_playback_send_migrate(playback_client)) {
if (command & SND_MIGRATE_MASK) {
command &= ~SND_MIGRATE_MASK;
if (snd_playback_send_migrate(this)) {
break;
}
}
if (client->command & SND_PLAYBACK_LATENCY_MASK) {
client->command &= ~SND_PLAYBACK_LATENCY_MASK;
if (snd_playback_send_latency(playback_client)) {
if (command & SND_PLAYBACK_LATENCY_MASK) {
command &= ~SND_PLAYBACK_LATENCY_MASK;
if (snd_playback_send_latency(this)) {
break;
}
}
}
snd_send(client);
snd_send(this);
}
static void record_channel_send_item(RedChannelClient *rcc, G_GNUC_UNUSED RedPipeItem *item)
void RecordChannelClient::send_item(G_GNUC_UNUSED RedPipeItem *item)
{
RecordChannelClient *record_client = RECORD_CHANNEL_CLIENT(rcc);
SndChannelClient *client = record_client;
client->command &= SND_CTRL_MASK|SND_VOLUME_MUTE_MASK|SND_MIGRATE_MASK;
while (client->command) {
if (client->command & SND_CTRL_MASK) {
client->command &= ~SND_CTRL_MASK;
if (snd_record_send_ctl(record_client)) {
command &= SND_CTRL_MASK|SND_VOLUME_MUTE_MASK|SND_MIGRATE_MASK;
while (command) {
if (command & SND_CTRL_MASK) {
command &= ~SND_CTRL_MASK;
if (snd_record_send_ctl(this)) {
break;
}
}
if (client->command & SND_VOLUME_MASK) {
client->command &= ~SND_VOLUME_MASK;
if (snd_record_send_volume(record_client)) {
if (command & SND_VOLUME_MASK) {
command &= ~SND_VOLUME_MASK;
if (snd_record_send_volume(this)) {
break;
}
}
if (client->command & SND_MUTE_MASK) {
client->command &= ~SND_MUTE_MASK;
if (snd_record_send_mute(record_client)) {
if (command & SND_MUTE_MASK) {
command &= ~SND_MUTE_MASK;
if (snd_record_send_mute(this)) {
break;
}
}
if (client->command & SND_MIGRATE_MASK) {
client->command &= ~SND_MIGRATE_MASK;
if (snd_record_send_migrate(record_client)) {
if (command & SND_MIGRATE_MASK) {
command &= ~SND_MIGRATE_MASK;
if (snd_record_send_migrate(this)) {
break;
}
}
}
snd_send(client);
snd_send(this);
}
bool SndChannelClient::config_socket()
@ -1320,7 +1317,6 @@ playback_channel_class_init(PlaybackChannelClass *klass)
object_class->constructed = playback_channel_constructed;
channel_class->parser = spice_get_client_channel_parser(SPICE_CHANNEL_PLAYBACK, NULL);
channel_class->send_item = playback_channel_send_item;
// client callbacks
channel_class->connect = snd_set_playback_peer;
@ -1365,7 +1361,6 @@ record_channel_class_init(RecordChannelClass *klass)
object_class->constructed = record_channel_constructed;
channel_class->parser = spice_get_client_channel_parser(SPICE_CHANNEL_RECORD, NULL);
channel_class->send_item = record_channel_send_item;
// client callbacks
channel_class->connect = snd_set_record_peer;

View File

@ -161,6 +161,7 @@ protected:
virtual void release_recv_buf(uint16_t type, uint32_t size, uint8_t *msg) override;
virtual void on_disconnect() override;
virtual bool handle_message(uint16_t type, uint32_t size, void *msg) override;
virtual void send_item(RedPipeItem *item) override;
};
static RedChannelClient *
@ -665,29 +666,28 @@ static void spicevmc_red_channel_send_port_event(RedChannelClient *rcc,
spice_marshall_msg_port_event(m, &event);
}
static void spicevmc_red_channel_send_item(RedChannelClient *rcc,
RedPipeItem *item)
void VmcChannelClient::send_item(RedPipeItem *item)
{
SpiceMarshaller *m = rcc->get_marshaller();
SpiceMarshaller *m = get_marshaller();
switch (item->type) {
case RED_PIPE_ITEM_TYPE_SPICEVMC_DATA:
spicevmc_red_channel_send_data(rcc, m, item);
spicevmc_red_channel_send_data(this, m, item);
break;
case RED_PIPE_ITEM_TYPE_SPICEVMC_MIGRATE_DATA:
spicevmc_red_channel_send_migrate_data(rcc, m, item);
spicevmc_red_channel_send_migrate_data(this, m, item);
break;
case RED_PIPE_ITEM_TYPE_PORT_INIT:
spicevmc_red_channel_send_port_init(rcc, m, item);
spicevmc_red_channel_send_port_init(this, m, item);
break;
case RED_PIPE_ITEM_TYPE_PORT_EVENT:
spicevmc_red_channel_send_port_event(rcc, m, item);
spicevmc_red_channel_send_port_event(this, m, item);
break;
default:
spice_error("bad pipe item %d", item->type);
return;
}
rcc->begin_send_message();
begin_send_message();
}
@ -700,7 +700,6 @@ red_vmc_channel_class_init(RedVmcChannelClass *klass)
object_class->constructed = red_vmc_channel_constructed;
object_class->finalize = red_vmc_channel_finalize;
channel_class->send_item = spicevmc_red_channel_send_item;
channel_class->handle_migrate_flush_mark = spicevmc_channel_client_handle_migrate_flush_mark;
channel_class->handle_migrate_data = spicevmc_channel_client_handle_migrate_data;

View File

@ -47,6 +47,7 @@ private:
bool handle_preferred_video_codec_type(SpiceMsgcDisplayPreferredVideoCodecType *msg);
virtual void on_disconnect() override;
virtual bool handle_message(uint16_t type, uint32_t size, void *msg) override;
virtual void send_item(RedPipeItem *pipe_item) override;
};
struct StreamChannel final: public RedChannel
@ -180,18 +181,14 @@ 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)
void StreamChannelClient::send_item(RedPipeItem *pipe_item)
{
SpiceMarshaller *m = rcc->get_marshaller();
StreamChannelClient *client = STREAM_CHANNEL_CLIENT(rcc);
StreamChannel *channel = STREAM_CHANNEL(rcc->get_channel());
SpiceMarshaller *m = get_marshaller();
StreamChannel *channel = STREAM_CHANNEL(get_channel());
switch (pipe_item->type) {
case RED_PIPE_ITEM_TYPE_SURFACE_CREATE: {
rcc->init_send_data(SPICE_MSG_DISPLAY_SURFACE_CREATE);
init_send_data(SPICE_MSG_DISPLAY_SURFACE_CREATE);
SpiceMsgSurfaceCreate surface_create = {
PRIMARY_SURFACE_ID,
channel->width, channel->height,
@ -200,7 +197,7 @@ stream_channel_send_item(RedChannelClient *rcc, RedPipeItem *pipe_item)
// give an hint to client that we are sending just streaming
// see spice.proto for capability check here
if (rcc->test_remote_cap(SPICE_DISPLAY_CAP_MULTI_CODEC)) {
if (test_remote_cap(SPICE_DISPLAY_CAP_MULTI_CODEC)) {
surface_create.flags |= SPICE_SURFACE_FLAGS_STREAMING_MODE;
}
@ -208,19 +205,19 @@ stream_channel_send_item(RedChannelClient *rcc, RedPipeItem *pipe_item)
break;
}
case RED_PIPE_ITEM_TYPE_MONITORS_CONFIG:
if (!rcc->test_remote_cap(SPICE_DISPLAY_CAP_MONITORS_CONFIG)) {
if (!test_remote_cap(SPICE_DISPLAY_CAP_MONITORS_CONFIG)) {
return;
}
marshall_monitors_config(rcc, channel, m);
marshall_monitors_config(this, channel, m);
break;
case RED_PIPE_ITEM_TYPE_SURFACE_DESTROY: {
rcc->init_send_data(SPICE_MSG_DISPLAY_SURFACE_DESTROY);
init_send_data(SPICE_MSG_DISPLAY_SURFACE_DESTROY);
SpiceMsgSurfaceDestroy surface_destroy = { PRIMARY_SURFACE_ID };
spice_marshall_msg_display_surface_destroy(m, &surface_destroy);
break;
}
case RED_PIPE_ITEM_TYPE_FILL_SURFACE: {
rcc->init_send_data(SPICE_MSG_DISPLAY_DRAW_FILL);
init_send_data(SPICE_MSG_DISPLAY_DRAW_FILL);
fill_base(m, channel);
@ -234,28 +231,28 @@ stream_channel_send_item(RedChannelClient *rcc, RedPipeItem *pipe_item)
}
case RED_PIPE_ITEM_TYPE_STREAM_CREATE: {
StreamCreateItem *item = SPICE_UPCAST(StreamCreateItem, pipe_item);
client->stream_id = item->stream_create.id;
rcc->init_send_data(SPICE_MSG_DISPLAY_STREAM_CREATE);
stream_id = item->stream_create.id;
init_send_data(SPICE_MSG_DISPLAY_STREAM_CREATE);
spice_marshall_msg_display_stream_create(m, &item->stream_create);
break;
}
case RED_PIPE_ITEM_TYPE_STREAM_ACTIVATE_REPORT: {
if (client->stream_id < 0
|| !rcc->test_remote_cap(SPICE_DISPLAY_CAP_STREAM_REPORT)) {
if (stream_id < 0
|| !test_remote_cap(SPICE_DISPLAY_CAP_STREAM_REPORT)) {
return;
}
SpiceMsgDisplayStreamActivateReport msg;
msg.stream_id = client->stream_id;
msg.stream_id = stream_id;
msg.unique_id = 1; // TODO useful ?
msg.max_window_size = RED_STREAM_CLIENT_REPORT_WINDOW;
msg.timeout_ms = RED_STREAM_CLIENT_REPORT_TIMEOUT;
rcc->init_send_data(SPICE_MSG_DISPLAY_STREAM_ACTIVATE_REPORT);
init_send_data(SPICE_MSG_DISPLAY_STREAM_ACTIVATE_REPORT);
spice_marshall_msg_display_stream_activate_report(m, &msg);
break;
}
case RED_PIPE_ITEM_TYPE_STREAM_DATA: {
StreamDataItem *item = SPICE_UPCAST(StreamDataItem, pipe_item);
rcc->init_send_data(SPICE_MSG_DISPLAY_STREAM_DATA);
init_send_data(SPICE_MSG_DISPLAY_STREAM_DATA);
spice_marshall_msg_display_stream_data(m, &item->data);
red_pipe_item_ref(pipe_item);
spice_marshaller_add_by_ref_full(m, item->data.data, item->data.data_size,
@ -265,20 +262,20 @@ stream_channel_send_item(RedChannelClient *rcc, RedPipeItem *pipe_item)
break;
}
case RED_PIPE_ITEM_TYPE_STREAM_DESTROY: {
if (client->stream_id < 0) {
if (stream_id < 0) {
return;
}
SpiceMsgDisplayStreamDestroy stream_destroy = { client->stream_id };
rcc->init_send_data(SPICE_MSG_DISPLAY_STREAM_DESTROY);
SpiceMsgDisplayStreamDestroy stream_destroy = { stream_id };
init_send_data(SPICE_MSG_DISPLAY_STREAM_DESTROY);
spice_marshall_msg_display_stream_destroy(m, &stream_destroy);
client->stream_id = -1;
stream_id = -1;
break;
}
default:
spice_error("invalid pipe item type");
}
rcc->begin_send_message();
begin_send_message();
}
bool StreamChannelClient::handle_message(uint16_t type, uint32_t size, void *msg)
@ -449,7 +446,6 @@ stream_channel_class_init(StreamChannelClass *klass)
channel_class->parser = spice_get_client_channel_parser(SPICE_CHANNEL_DISPLAY, NULL);
channel_class->send_item = stream_channel_send_item;
channel_class->connect = stream_channel_connect;
}

View File

@ -59,11 +59,6 @@ red_test_channel_init(RedTestChannel *self)
{
}
static void
test_channel_send_item(RedChannelClient *rcc, RedPipeItem *item)
{
}
static void
test_connect_client(RedChannel *channel, RedClient *client, RedStream *stream,
int migration, RedChannelCapabilities *caps)
@ -92,7 +87,6 @@ red_test_channel_class_init(RedTestChannelClass *klass)
{
RedChannelClass *channel_class = RED_CHANNEL_CLASS(klass);
channel_class->parser = spice_get_client_channel_parser(SPICE_CHANNEL_PORT, NULL);
channel_class->send_item = test_channel_send_item;
channel_class->connect = test_connect_client;
}