summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--server/inputs_channel.c39
-rw-r--r--server/main_channel.c82
-rw-r--r--server/red_channel.c627
-rw-r--r--server/red_channel.h109
-rw-r--r--server/red_client_shared_cache.h17
-rw-r--r--server/red_tunnel_worker.c214
-rw-r--r--server/red_worker.c679
-rw-r--r--server/smartcard.c147
-rw-r--r--server/usbredir.c87
9 files changed, 1140 insertions, 861 deletions
diff --git a/server/inputs_channel.c b/server/inputs_channel.c
index 0cc53a2b..3a4a0d0d 100644
--- a/server/inputs_channel.c
+++ b/server/inputs_channel.c
@@ -164,9 +164,9 @@ const VDAgentMouseState *inputs_get_mouse_state(void)
return &g_inputs_channel->mouse_state;
}
-static uint8_t *inputs_channel_alloc_msg_rcv_buf(RedChannel *channel, SpiceDataHeader *msg_header)
+static uint8_t *inputs_channel_alloc_msg_rcv_buf(RedChannelClient *rcc, SpiceDataHeader *msg_header)
{
- InputsChannel *inputs_channel = SPICE_CONTAINEROF(channel, InputsChannel, base);
+ InputsChannel *inputs_channel = SPICE_CONTAINEROF(rcc->channel, InputsChannel, base);
if (msg_header->size > RECEIVE_BUF_SIZE) {
red_printf("error: too large incoming message");
@@ -175,7 +175,7 @@ static uint8_t *inputs_channel_alloc_msg_rcv_buf(RedChannel *channel, SpiceDataH
return inputs_channel->recv_buf;
}
-static void inputs_channel_release_msg_rcv_buf(RedChannel *channel, SpiceDataHeader *msg_header,
+static void inputs_channel_release_msg_rcv_buf(RedChannelClient *rcc, SpiceDataHeader *msg_header,
uint8_t *msg)
{
}
@@ -249,17 +249,17 @@ static void inputs_pipe_add_type(InputsChannel *channel, int type)
red_channel_pipe_add_push(&channel->base, &pipe_item->base);
}
-static void inputs_channel_release_pipe_item(RedChannel *channel,
+static void inputs_channel_release_pipe_item(RedChannelClient *rcc,
PipeItem *base, int item_pushed)
{
free(base);
}
-static void inputs_channel_send_item(RedChannel *channel, PipeItem *base)
+static void inputs_channel_send_item(RedChannelClient *rcc, PipeItem *base)
{
- SpiceMarshaller *m = red_channel_get_marshaller(channel);
+ SpiceMarshaller *m = red_channel_client_get_marshaller(rcc);
- red_channel_init_send_data(channel, base->type, base);
+ red_channel_client_init_send_data(rcc, base->type, base);
switch (base->type) {
case PIPE_ITEM_KEY_MODIFIERS:
{
@@ -288,12 +288,12 @@ static void inputs_channel_send_item(RedChannel *channel, PipeItem *base)
default:
break;
}
- red_channel_begin_send_message(channel);
+ red_channel_client_begin_send_message(rcc);
}
-static int inputs_channel_handle_parsed(RedChannel *channel, uint32_t size, uint16_t type, void *message)
+static int inputs_channel_handle_parsed(RedChannelClient *rcc, uint32_t size, uint16_t type, void *message)
{
- InputsChannel *inputs_channel = (InputsChannel *)channel;
+ InputsChannel *inputs_channel = (InputsChannel *)rcc->channel;
uint8_t *buf = (uint8_t *)message;
ASSERT(g_inputs_channel == inputs_channel);
@@ -446,10 +446,10 @@ static void inputs_relase_keys(void)
kbd_push_scan(keyboard, 0x38 | 0x80); //LALT
}
-static void inputs_channel_on_error(RedChannel *channel)
+static void inputs_channel_on_error(RedChannelClient *rcc)
{
inputs_relase_keys();
- reds_disconnect();
+ red_channel_client_destroy(rcc);
}
static void inputs_shutdown(Channel *channel)
@@ -485,11 +485,11 @@ static void inputs_pipe_add_init(InputsChannel *inputs_channel)
red_channel_pipe_add_push(&inputs_channel->base, &item->base);
}
-static int inputs_channel_config_socket(RedChannel *channel)
+static int inputs_channel_config_socket(RedChannelClient *rcc)
{
int flags;
int delay_val = 1;
- RedsStream *stream = red_channel_get_stream(channel);
+ RedsStream *stream = red_channel_client_get_stream(rcc);
if (setsockopt(stream->socket, IPPROTO_TCP, TCP_NODELAY,
&delay_val, sizeof(delay_val)) == -1) {
@@ -505,7 +505,7 @@ static int inputs_channel_config_socket(RedChannel *channel)
return TRUE;
}
-static void inputs_channel_hold_pipe_item(RedChannel *channel, PipeItem *item)
+static void inputs_channel_hold_pipe_item(RedChannelClient *rcc, PipeItem *item)
{
}
@@ -514,11 +514,13 @@ static void inputs_link(Channel *channel, RedsStream *stream, int migration,
uint32_t *caps)
{
InputsChannel *inputs_channel;
- red_printf("");
+ RedChannelClient *rcc;
+
ASSERT(channel->data == NULL);
+ red_printf("input channel create");
g_inputs_channel = inputs_channel = (InputsChannel*)red_channel_create_parser(
- sizeof(*inputs_channel), stream, core, migration, FALSE /* handle_acks */
+ sizeof(*inputs_channel), core, migration, FALSE /* handle_acks */
,inputs_channel_config_socket
,spice_get_client_channel_parser(SPICE_CHANNEL_INPUTS, NULL)
,inputs_channel_handle_parsed
@@ -533,6 +535,9 @@ static void inputs_link(Channel *channel, RedsStream *stream, int migration,
,NULL
,NULL);
ASSERT(inputs_channel);
+ red_printf("input channel client create");
+ rcc = red_channel_client_create(sizeof(RedChannelClient), &g_inputs_channel->base, stream);
+ ASSERT(rcc);
channel->data = inputs_channel;
inputs_pipe_add_init(inputs_channel);
}
diff --git a/server/main_channel.c b/server/main_channel.c
index 1a6a89c4..0718f887 100644
--- a/server/main_channel.c
+++ b/server/main_channel.c
@@ -421,7 +421,8 @@ static void main_channel_marshall_migrate_data_item(SpiceMarshaller *m, int seri
data->ping_id = ping_id;
}
-static uint64_t main_channel_handle_migrate_data_get_serial(RedChannel *base,
+static uint64_t main_channel_handle_migrate_data_get_serial(
+ RedChannelClient *rcc,
uint32_t size, void *message)
{
MainMigrateData *data = message;
@@ -433,10 +434,10 @@ static uint64_t main_channel_handle_migrate_data_get_serial(RedChannel *base,
return data->serial;
}
-static uint64_t main_channel_handle_migrate_data(RedChannel *base,
+static uint64_t main_channel_handle_migrate_data(RedChannelClient *rcc,
uint32_t size, void *message)
{
- MainChannel *main_chan = SPICE_CONTAINEROF(base, MainChannel, base);
+ MainChannel *main_chan = SPICE_CONTAINEROF(rcc->channel, MainChannel, base);
MainMigrateData *data = message;
if (size < sizeof(*data)) {
@@ -607,12 +608,12 @@ static void main_channel_marshall_multi_media_time(SpiceMarshaller *m,
spice_marshall_msg_main_multi_media_time(m, &time_mes);
}
-static void main_channel_send_item(RedChannel *channel, PipeItem *base)
+static void main_channel_send_item(RedChannelClient *rcc, PipeItem *base)
{
- SpiceMarshaller *m = red_channel_get_marshaller(channel);
- MainChannel *main_chan = SPICE_CONTAINEROF(channel, MainChannel, base);
+ MainChannel *main_chan = SPICE_CONTAINEROF(rcc->channel, MainChannel, base);
+ SpiceMarshaller *m = red_channel_client_get_marshaller(rcc);
- red_channel_init_send_data(channel, base->type, base);
+ red_channel_client_init_send_data(rcc, base->type, base);
switch (base->type) {
case SPICE_MSG_MAIN_CHANNELS_LIST:
main_channel_marshall_channels(m);
@@ -642,7 +643,7 @@ static void main_channel_send_item(RedChannel *channel, PipeItem *base)
break;
case SPICE_MSG_MIGRATE_DATA:
main_channel_marshall_migrate_data_item(m,
- red_channel_get_message_serial(&main_chan->base),
+ red_channel_client_get_message_serial(rcc),
main_chan->ping_id);
break;
case SPICE_MSG_MAIN_INIT:
@@ -668,18 +669,18 @@ static void main_channel_send_item(RedChannel *channel, PipeItem *base)
main_channel_marshall_migrate_switch(m);
break;
};
- red_channel_begin_send_message(channel);
+ red_channel_client_begin_send_message(rcc);
}
-static void main_channel_release_pipe_item(RedChannel *channel,
+static void main_channel_release_pipe_item(RedChannelClient *rcc,
PipeItem *base, int item_pushed)
{
free(base);
}
-static int main_channel_handle_parsed(RedChannel *channel, uint32_t size, uint16_t type, void *message)
+static int main_channel_handle_parsed(RedChannelClient *rcc, uint32_t size, uint16_t type, void *message)
{
- MainChannel *main_chan = SPICE_CONTAINEROF(channel, MainChannel, base);
+ MainChannel *main_chan = SPICE_CONTAINEROF(rcc->channel, MainChannel, base);
switch (type) {
case SPICE_MSGC_MAIN_AGENT_START:
@@ -770,35 +771,36 @@ static int main_channel_handle_parsed(RedChannel *channel, uint32_t size, uint16
return TRUE;
}
-static void main_channel_on_error(RedChannel *channel)
+static void main_channel_on_error(RedChannelClient *rcc)
{
reds_disconnect();
}
-static uint8_t *main_channel_alloc_msg_rcv_buf(RedChannel *channel, SpiceDataHeader *msg_header)
+static uint8_t *main_channel_alloc_msg_rcv_buf(RedChannelClient *rcc, SpiceDataHeader *msg_header)
{
- MainChannel *main_chan = SPICE_CONTAINEROF(channel, MainChannel, base);
+ MainChannel *main_chan = SPICE_CONTAINEROF(rcc->channel, MainChannel, base);
return main_chan->recv_buf;
}
-static void main_channel_release_msg_rcv_buf(RedChannel *channel, SpiceDataHeader *msg_header,
+static void main_channel_release_msg_rcv_buf(RedChannelClient *rcc, SpiceDataHeader *msg_header,
uint8_t *msg)
{
}
-static int main_channel_config_socket(RedChannel *channel)
+static int main_channel_config_socket(RedChannelClient *rcc)
{
return TRUE;
}
-static void main_channel_hold_pipe_item(RedChannel *channel, PipeItem *item)
+static void main_channel_hold_pipe_item(RedChannelClient *rcc, PipeItem *item)
{
}
-static int main_channel_handle_migrate_flush_mark(RedChannel *base)
+static int main_channel_handle_migrate_flush_mark(RedChannelClient *rcc)
{
- main_channel_push_migrate_data_item(SPICE_CONTAINEROF(base, MainChannel, base));
+ main_channel_push_migrate_data_item(SPICE_CONTAINEROF(rcc->channel,
+ MainChannel, base));
return TRUE;
}
@@ -807,26 +809,30 @@ static void main_channel_link(Channel *channel, RedsStream *stream, int migratio
uint32_t *caps)
{
MainChannel *main_chan;
- red_printf("");
ASSERT(channel->data == NULL);
- main_chan = (MainChannel*)red_channel_create_parser(
- sizeof(*main_chan), stream, core, migration, FALSE /* handle_acks */
- ,main_channel_config_socket
- ,spice_get_client_channel_parser(SPICE_CHANNEL_MAIN, NULL)
- ,main_channel_handle_parsed
- ,main_channel_alloc_msg_rcv_buf
- ,main_channel_release_msg_rcv_buf
- ,main_channel_hold_pipe_item
- ,main_channel_send_item
- ,main_channel_release_pipe_item
- ,main_channel_on_error
- ,main_channel_on_error
- ,main_channel_handle_migrate_flush_mark
- ,main_channel_handle_migrate_data
- ,main_channel_handle_migrate_data_get_serial);
- ASSERT(main_chan);
- channel->data = main_chan;
+ if (channel->data == NULL) {
+ red_printf("create main channel");
+ channel->data = red_channel_create_parser(
+ sizeof(*main_chan), core, migration, FALSE /* handle_acks */
+ ,main_channel_config_socket
+ ,spice_get_client_channel_parser(SPICE_CHANNEL_MAIN, NULL)
+ ,main_channel_handle_parsed
+ ,main_channel_alloc_msg_rcv_buf
+ ,main_channel_release_msg_rcv_buf
+ ,main_channel_hold_pipe_item
+ ,main_channel_send_item
+ ,main_channel_release_pipe_item
+ ,main_channel_on_error
+ ,main_channel_on_error
+ ,main_channel_handle_migrate_flush_mark
+ ,main_channel_handle_migrate_data
+ ,main_channel_handle_migrate_data_get_serial);
+ ASSERT(channel->data);
+ }
+ main_chan = (MainChannel*)channel->data;
+ red_printf("add main channel client");
+ red_channel_client_create(sizeof(RedChannelClient), channel->data, stream);
}
int main_channel_getsockname(Channel *channel, struct sockaddr *sa, socklen_t *salen)
diff --git a/server/red_channel.c b/server/red_channel.c
index 9ecc7ef8..8bbc6c95 100644
--- a/server/red_channel.c
+++ b/server/red_channel.c
@@ -33,8 +33,7 @@
#include "red_channel.h"
#include "generated_marshallers.h"
-static PipeItem *red_channel_pipe_get(RedChannel *channel);
-static void red_channel_event(int fd, int event, void *data);
+static void red_channel_client_event(int fd, int event, void *data);
/* return the number of bytes read. -1 in case of error */
static int red_peer_receive(RedsStream *stream, uint8_t *buf, uint32_t size)
@@ -152,9 +151,14 @@ static void red_peer_handle_incoming(RedsStream *stream, IncomingHandler *handle
}
}
+void red_channel_client_receive(RedChannelClient *rcc)
+{
+ red_peer_handle_incoming(rcc->stream, &rcc->incoming);
+}
+
void red_channel_receive(RedChannel *channel)
{
- red_peer_handle_incoming(channel->stream, &channel->incoming);
+ red_channel_client_receive(channel->rcc);
}
static void red_peer_handle_outgoing(RedsStream *stream, OutgoingHandler *handler)
@@ -201,124 +205,194 @@ static void red_peer_handle_outgoing(RedsStream *stream, OutgoingHandler *handle
}
}
-static void red_channel_on_output(void *opaque, int n)
+static void red_channel_client_on_output(void *opaque, int n)
{
- RedChannel *channel = opaque;
+ RedChannelClient *rcc = opaque;
- stat_inc_counter(channel->out_bytes_counter, n);
+ stat_inc_counter(rcc->channel->out_bytes_counter, n);
}
-void red_channel_default_peer_on_error(RedChannel *channel)
+void red_channel_client_default_peer_on_error(RedChannelClient *rcc)
{
- channel->disconnect(channel);
+ rcc->channel->disconnect(rcc);
}
-static void red_channel_peer_on_incoming_error(RedChannel *channel)
+static void red_channel_peer_on_incoming_error(RedChannelClient *rcc)
{
- channel->on_incoming_error(channel);
+ rcc->channel->on_incoming_error(rcc);
}
-static void red_channel_peer_on_outgoing_error(RedChannel *channel)
+static void red_channel_peer_on_outgoing_error(RedChannelClient *rcc)
{
- channel->on_outgoing_error(channel);
+ rcc->channel->on_outgoing_error(rcc);
}
-static int red_channel_peer_get_out_msg_size(void *opaque)
+static int red_channel_client_peer_get_out_msg_size(void *opaque)
{
- RedChannel *channel = (RedChannel *)opaque;
+ RedChannelClient *rcc = (RedChannelClient *)opaque;
- return channel->send_data.size;
+ return rcc->send_data.size;
}
-static void red_channel_peer_prepare_out_msg(void *opaque, struct iovec *vec, int *vec_size, int pos)
+static void red_channel_client_peer_prepare_out_msg(
+ void *opaque, struct iovec *vec, int *vec_size, int pos)
{
- RedChannel *channel = (RedChannel *)opaque;
+ RedChannelClient *rcc = (RedChannelClient *)opaque;
- *vec_size = spice_marshaller_fill_iovec(channel->send_data.marshaller,
+ *vec_size = spice_marshaller_fill_iovec(rcc->send_data.marshaller,
vec, MAX_SEND_VEC, pos);
}
-static void red_channel_peer_on_out_block(void *opaque)
+static void red_channel_client_peer_on_out_block(void *opaque)
{
- RedChannel *channel = (RedChannel *)opaque;
+ RedChannelClient *rcc = (RedChannelClient *)opaque;
- channel->send_data.blocked = TRUE;
- channel->core->watch_update_mask(channel->stream->watch,
+ rcc->send_data.blocked = TRUE;
+ rcc->channel->core->watch_update_mask(rcc->stream->watch,
SPICE_WATCH_EVENT_READ |
SPICE_WATCH_EVENT_WRITE);
}
-static void red_channel_reset_send_data(RedChannel *channel)
+static void red_channel_client_reset_send_data(RedChannelClient *rcc)
+{
+ spice_marshaller_reset(rcc->send_data.marshaller);
+ rcc->send_data.header = (SpiceDataHeader *)
+ spice_marshaller_reserve_space(rcc->send_data.marshaller, sizeof(SpiceDataHeader));
+ spice_marshaller_set_base(rcc->send_data.marshaller, sizeof(SpiceDataHeader));
+ rcc->send_data.header->type = 0;
+ rcc->send_data.header->size = 0;
+ rcc->send_data.header->sub_list = 0;
+ rcc->send_data.header->serial = ++rcc->send_data.serial;
+}
+
+void red_channel_client_push_set_ack(RedChannelClient *rcc)
{
- spice_marshaller_reset(channel->send_data.marshaller);
- channel->send_data.header = (SpiceDataHeader *)
- spice_marshaller_reserve_space(channel->send_data.marshaller, sizeof(SpiceDataHeader));
- spice_marshaller_set_base(channel->send_data.marshaller, sizeof(SpiceDataHeader));
- channel->send_data.header->type = 0;
- channel->send_data.header->size = 0;
- channel->send_data.header->sub_list = 0;
- channel->send_data.header->serial = ++channel->send_data.serial;
+ red_channel_pipe_add_type(rcc->channel, PIPE_ITEM_TYPE_SET_ACK);
}
void red_channel_push_set_ack(RedChannel *channel)
{
+ // TODO - MC, should replace with add_type_all (or whatever I'll name it)
red_channel_pipe_add_type(channel, PIPE_ITEM_TYPE_SET_ACK);
}
-static void red_channel_send_set_ack(RedChannel *channel)
+static void red_channel_client_send_set_ack(RedChannelClient *rcc)
{
SpiceMsgSetAck ack;
- ASSERT(channel);
- red_channel_init_send_data(channel, SPICE_MSG_SET_ACK, NULL);
- ack.generation = ++channel->ack_data.generation;
- ack.window = channel->ack_data.client_window;
- channel->ack_data.messages_window = 0;
+ ASSERT(rcc);
+ red_channel_client_init_send_data(rcc, SPICE_MSG_SET_ACK, NULL);
+ ack.generation = ++rcc->ack_data.generation;
+ ack.window = rcc->ack_data.client_window;
+ rcc->ack_data.messages_window = 0;
- spice_marshall_msg_set_ack(channel->send_data.marshaller, &ack);
+ spice_marshall_msg_set_ack(rcc->send_data.marshaller, &ack);
- red_channel_begin_send_message(channel);
+ red_channel_client_begin_send_message(rcc);
}
-static void red_channel_send_item(RedChannel *channel, PipeItem *item)
+static void red_channel_client_send_item(RedChannelClient *rcc, PipeItem *item)
{
- red_channel_reset_send_data(channel);
+ int handled = TRUE;
+
+ ASSERT(red_channel_client_no_item_being_sent(rcc));
+ red_channel_client_reset_send_data(rcc);
switch (item->type) {
case PIPE_ITEM_TYPE_SET_ACK:
- red_channel_send_set_ack(channel);
- return;
+ red_channel_client_send_set_ack(rcc);
+ break;
+ default:
+ handled = FALSE;
+ }
+ if (!handled) {
+ rcc->channel->send_item(rcc, item);
}
- /* only reached if not handled here */
- channel->send_item(channel, item);
}
-static void red_channel_release_item(RedChannel *channel, PipeItem *item, int item_pushed)
+static void red_channel_client_release_item(RedChannelClient *rcc, PipeItem *item, int item_pushed)
{
+ int handled = TRUE;
+
switch (item->type) {
case PIPE_ITEM_TYPE_SET_ACK:
free(item);
- return;
+ break;
+ default:
+ handled = FALSE;
+ }
+ if (!handled) {
+ rcc->channel->release_item(rcc, item, item_pushed);
}
- /* only reached if not handled here */
- channel->release_item(channel, item, item_pushed);
}
-static void red_channel_peer_on_out_msg_done(void *opaque)
+static inline void red_channel_client_release_sent_item(RedChannelClient *rcc)
{
- RedChannel *channel = (RedChannel *)opaque;
- channel->send_data.size = 0;
- if (channel->send_data.item) {
- red_channel_release_item(channel, channel->send_data.item, TRUE);
- channel->send_data.item = NULL;
+ if (rcc->send_data.item) {
+ red_channel_client_release_item(rcc,
+ rcc->send_data.item, TRUE);
+ rcc->send_data.item = NULL;
}
- if (channel->send_data.blocked) {
- channel->send_data.blocked = FALSE;
- channel->core->watch_update_mask(channel->stream->watch,
+}
+
+static void red_channel_peer_on_out_msg_done(void *opaque)
+{
+ RedChannelClient *rcc = (RedChannelClient *)opaque;
+
+ rcc->send_data.size = 0;
+ red_channel_client_release_sent_item(rcc);
+ if (rcc->send_data.blocked) {
+ rcc->send_data.blocked = FALSE;
+ rcc->channel->core->watch_update_mask(rcc->stream->watch,
SPICE_WATCH_EVENT_READ);
}
}
-RedChannel *red_channel_create(int size, RedsStream *stream,
+static void red_channel_add_client(RedChannel *channel, RedChannelClient *rcc)
+{
+ ASSERT(rcc);
+ channel->rcc = rcc;
+}
+
+RedChannelClient *red_channel_client_create(
+ int size,
+ RedChannel *channel,
+ RedsStream *stream)
+{
+ RedChannelClient *rcc = NULL;
+
+ ASSERT(stream && channel && size >= sizeof(RedChannelClient));
+ rcc = spice_malloc0(size);
+ rcc->stream = stream;
+ rcc->channel = channel;
+ rcc->ack_data.messages_window = ~0; // blocks send message (maybe use send_data.blocked +
+ // block flags)
+ rcc->ack_data.client_generation = ~0;
+ rcc->ack_data.client_window = CLIENT_ACK_WINDOW;
+ rcc->send_data.marshaller = spice_marshaller_new();
+
+ rcc->incoming.opaque = rcc;
+ rcc->incoming.cb = &channel->incoming_cb;
+
+ rcc->outgoing.opaque = rcc;
+ rcc->outgoing.cb = &channel->outgoing_cb;
+ rcc->outgoing.pos = 0;
+ rcc->outgoing.size = 0;
+ if (!channel->config_socket(rcc)) {
+ goto error;
+ }
+
+ stream->watch = channel->core->watch_add(stream->socket,
+ SPICE_WATCH_EVENT_READ,
+ red_channel_client_event, rcc);
+ red_channel_add_client(channel, rcc);
+ return rcc;
+error:
+ free(rcc);
+ reds_stream_free(stream);
+ return NULL;
+}
+
+RedChannel *red_channel_create(int size,
SpiceCoreInterface *core,
int migrate, int handle_acks,
channel_configure_socket_proc config_socket,
@@ -339,7 +413,6 @@ RedChannel *red_channel_create(int size, RedsStream *stream,
ASSERT(config_socket && disconnect && handle_message && alloc_recv_buf &&
release_item);
channel = spice_malloc0(size);
-
channel->handle_acks = handle_acks;
channel->disconnect = disconnect;
channel->send_item = send_item;
@@ -348,69 +421,40 @@ RedChannel *red_channel_create(int size, RedsStream *stream,
channel->handle_migrate_flush_mark = handle_migrate_flush_mark;
channel->handle_migrate_data = handle_migrate_data;
channel->handle_migrate_data_get_serial = handle_migrate_data_get_serial;
+ channel->config_socket = config_socket;
- channel->stream = stream;
channel->core = core;
- channel->ack_data.messages_window = ~0; // blocks send message (maybe use send_data.blocked +
- // block flags)
- channel->ack_data.client_generation = ~0;
- channel->ack_data.client_window = CLIENT_ACK_WINDOW;
-
channel->migrate = migrate;
ring_init(&channel->pipe);
- channel->send_data.marshaller = spice_marshaller_new();
- channel->incoming.opaque = channel;
channel->incoming_cb.alloc_msg_buf = (alloc_msg_recv_buf_proc)alloc_recv_buf;
channel->incoming_cb.release_msg_buf = (release_msg_recv_buf_proc)release_recv_buf;
channel->incoming_cb.handle_message = (handle_message_proc)handle_message;
- channel->incoming_cb.on_error = (on_incoming_error_proc)red_channel_default_peer_on_error;
-
- channel->outgoing.opaque = channel;
- channel->outgoing.pos = 0;
- channel->outgoing.size = 0;
-
- channel->outgoing_cb.get_msg_size = red_channel_peer_get_out_msg_size;
- channel->outgoing_cb.prepare = red_channel_peer_prepare_out_msg;
- channel->outgoing_cb.on_block = red_channel_peer_on_out_block;
- channel->outgoing_cb.on_error = (on_outgoing_error_proc)red_channel_default_peer_on_error;
+ channel->incoming_cb.on_error =
+ (on_incoming_error_proc)red_channel_client_default_peer_on_error;
+ channel->outgoing_cb.get_msg_size = red_channel_client_peer_get_out_msg_size;
+ channel->outgoing_cb.prepare = red_channel_client_peer_prepare_out_msg;
+ channel->outgoing_cb.on_block = red_channel_client_peer_on_out_block;
+ channel->outgoing_cb.on_error =
+ (on_outgoing_error_proc)red_channel_client_default_peer_on_error;
channel->outgoing_cb.on_msg_done = red_channel_peer_on_out_msg_done;
- channel->outgoing_cb.on_output = red_channel_on_output;
-
- channel->incoming.cb = &channel->incoming_cb;
- channel->outgoing.cb = &channel->outgoing_cb;
+ channel->outgoing_cb.on_output = red_channel_client_on_output;
channel->shut = 0; // came here from inputs, perhaps can be removed? XXX
channel->out_bytes_counter = 0;
-
- if (!config_socket(channel)) {
- goto error;
- }
-
- channel->stream->watch = channel->core->watch_add(channel->stream->socket,
- SPICE_WATCH_EVENT_READ,
- red_channel_event, channel);
-
return channel;
-
-error:
- spice_marshaller_destroy(channel->send_data.marshaller);
- free(channel);
- reds_stream_free(stream);
-
- return NULL;
}
-static void do_nothing_disconnect(RedChannel *red_channel)
+static void do_nothing_disconnect(RedChannelClient *rcc)
{
}
-static int do_nothing_handle_message(RedChannel *red_channel, SpiceDataHeader *header, uint8_t *msg)
+static int do_nothing_handle_message(RedChannelClient *rcc, SpiceDataHeader *header, uint8_t *msg)
{
return TRUE;
}
-RedChannel *red_channel_create_parser(int size, RedsStream *stream,
+RedChannel *red_channel_create_parser(int size,
SpiceCoreInterface *core,
int migrate, int handle_acks,
channel_configure_socket_proc config_socket,
@@ -427,7 +471,7 @@ RedChannel *red_channel_create_parser(int size, RedsStream *stream,
channel_handle_migrate_data_proc handle_migrate_data,
channel_handle_migrate_data_get_serial_proc handle_migrate_data_get_serial)
{
- RedChannel *channel = red_channel_create(size, stream,
+ RedChannel *channel = red_channel_create(size,
core, migrate, handle_acks, config_socket, do_nothing_disconnect,
do_nothing_handle_message, alloc_recv_buf, release_recv_buf, hold_item,
send_item, release_item, handle_migrate_flush_mark, handle_migrate_data,
@@ -438,62 +482,152 @@ RedChannel *red_channel_create_parser(int size, RedsStream *stream,
}
channel->incoming_cb.handle_parsed = (handle_parsed_proc)handle_parsed;
channel->incoming_cb.parser = parser;
- channel->on_incoming_error = incoming_error;
- channel->on_outgoing_error = outgoing_error;
channel->incoming_cb.on_error = (on_incoming_error_proc)red_channel_peer_on_incoming_error;
channel->outgoing_cb.on_error = (on_outgoing_error_proc)red_channel_peer_on_outgoing_error;
+ channel->on_incoming_error = incoming_error;
+ channel->on_outgoing_error = outgoing_error;
return channel;
}
+void red_channel_client_destroy(RedChannelClient *rcc)
+{
+ red_channel_client_disconnect(rcc);
+ spice_marshaller_destroy(rcc->send_data.marshaller);
+ free(rcc);
+}
+
void red_channel_destroy(RedChannel *channel)
{
if (!channel) {
return;
}
- red_channel_pipe_clear(channel);
- reds_stream_free(channel->stream);
- spice_marshaller_destroy(channel->send_data.marshaller);
+ if (channel->rcc) {
+ red_channel_client_destroy(channel->rcc);
+ }
free(channel);
}
+static void red_channel_client_shutdown(RedChannelClient *rcc)
+{
+ if (rcc->stream && !rcc->stream->shutdown) {
+ rcc->channel->core->watch_remove(rcc->stream->watch);
+ rcc->stream->watch = NULL;
+ shutdown(rcc->stream->socket, SHUT_RDWR);
+ rcc->stream->shutdown = TRUE;
+ rcc->incoming.shut = TRUE;
+ }
+ red_channel_client_release_sent_item(rcc);
+}
+
void red_channel_shutdown(RedChannel *channel)
{
- red_printf("");
- if (channel->stream && !channel->stream->shutdown) {
- channel->core->watch_update_mask(channel->stream->watch,
- SPICE_WATCH_EVENT_READ);
- red_channel_pipe_clear(channel);
- shutdown(channel->stream->socket, SHUT_RDWR);
- channel->stream->shutdown = TRUE;
- channel->incoming.shut = TRUE;
+ if (channel->rcc) {
+ red_channel_client_shutdown(channel->rcc);
+ }
+ red_channel_pipe_clear(channel);
+}
+
+void red_channel_client_send(RedChannelClient *rcc)
+{
+ red_peer_handle_outgoing(rcc->stream, &rcc->outgoing);
+}
+
+void red_channel_send(RedChannel *channel)
+{
+ if (channel->rcc) {
+ red_channel_client_send(channel->rcc);
}
}
+static inline int red_channel_client_waiting_for_ack(RedChannelClient *rcc)
+{
+ return (rcc->channel->handle_acks &&
+ (rcc->ack_data.messages_window > rcc->ack_data.client_window * 2));
+}
+
+// TODO: add refs and target to PipeItem. Right now this only works for a
+// single client (or actually, it's worse - first come first served)
+static inline PipeItem *red_channel_client_pipe_get(RedChannelClient *rcc)
+{
+ PipeItem *item;
+
+ if (!rcc || rcc->send_data.blocked
+ || red_channel_client_waiting_for_ack(rcc)
+ || !(item = (PipeItem *)ring_get_tail(&rcc->channel->pipe))) {
+ return NULL;
+ }
+ --rcc->channel->pipe_size;
+ ring_remove(&item->link);
+ return item;
+}
+
+static void red_channel_client_push(RedChannelClient *rcc)
+{
+ PipeItem *pipe_item;
+
+ if (!rcc->during_send) {
+ rcc->during_send = TRUE;
+ } else {
+ return;
+ }
+
+ if (rcc->send_data.blocked) {
+ red_channel_client_send(rcc);
+ }
+
+ while ((pipe_item = red_channel_client_pipe_get(rcc))) {
+ red_channel_client_send_item(rcc, pipe_item);
+ }
+ rcc->during_send = FALSE;
+}
+
+void red_channel_push(RedChannel *channel)
+{
+ if (!channel || !channel->rcc) {
+ return;
+ }
+ red_channel_client_push(channel->rcc);
+}
+
+static void red_channel_client_init_outgoing_messages_window(RedChannelClient *rcc)
+{
+ rcc->ack_data.messages_window = 0;
+ red_channel_client_push(rcc);
+}
+
+// TODO: this function doesn't make sense because the window should be client (WAN/LAN)
+// specific
void red_channel_init_outgoing_messages_window(RedChannel *channel)
{
- channel->ack_data.messages_window = 0;
- red_channel_push(channel);
+ red_channel_client_init_outgoing_messages_window(channel->rcc);
}
static void red_channel_handle_migrate_flush_mark(RedChannel *channel)
{
if (channel->handle_migrate_flush_mark) {
- channel->handle_migrate_flush_mark(channel);
+ channel->handle_migrate_flush_mark(channel->rcc);
}
}
-static void red_channel_handle_migrate_data(RedChannel *channel, uint32_t size, void *message)
+// TODO: the whole migration is broken with multiple clients. What do we want to do?
+// basically just
+// 1) source send mark to all
+// 2) source gets at various times the data (waits for all)
+// 3) source migrates to target
+// 4) target sends data to all
+// So need to make all the handlers work with per channel/client data (what data exactly?)
+static void red_channel_handle_migrate_data(RedChannelClient *rcc, uint32_t size, void *message)
{
- if (!channel->handle_migrate_data) {
+ if (!rcc->channel->handle_migrate_data) {
return;
}
- ASSERT(red_channel_get_message_serial(channel) == 0);
- red_channel_set_message_serial(channel,
- channel->handle_migrate_data_get_serial(channel, size, message));
- channel->handle_migrate_data(channel, size, message);
+ ASSERT(red_channel_client_get_message_serial(rcc) == 0);
+ red_channel_client_set_message_serial(rcc,
+ rcc->channel->handle_migrate_data_get_serial(rcc, size, message));
+ rcc->channel->handle_migrate_data(rcc, size, message);
}
-int red_channel_handle_message(RedChannel *channel, uint32_t size,
+int red_channel_client_handle_message(RedChannelClient *rcc, uint32_t size,
uint16_t type, void *message)
{
switch (type) {
@@ -502,21 +636,21 @@ int red_channel_handle_message(RedChannel *channel, uint32_t size,
red_printf("bad message size");
return FALSE;
}
- channel->ack_data.client_generation = *(uint32_t *)(message);
+ rcc->ack_data.client_generation = *(uint32_t *)(message);
break;
case SPICE_MSGC_ACK:
- if (channel->ack_data.client_generation == channel->ack_data.generation) {
- channel->ack_data.messages_window -= channel->ack_data.client_window;
- red_channel_push(channel);
+ if (rcc->ack_data.client_generation == rcc->ack_data.generation) {
+ rcc->ack_data.messages_window -= rcc->ack_data.client_window;
+ red_channel_client_push(rcc);
}
break;
case SPICE_MSGC_DISCONNECTING:
break;
case SPICE_MSGC_MIGRATE_FLUSH_MARK:
- red_channel_handle_migrate_flush_mark(channel);
+ red_channel_handle_migrate_flush_mark(rcc->channel);
break;
case SPICE_MSGC_MIGRATE_DATA:
- red_channel_handle_migrate_data(channel, size, message);
+ red_channel_handle_migrate_data(rcc, size, message);
break;
default:
red_printf("invalid message type %u", type);
@@ -525,75 +659,54 @@ int red_channel_handle_message(RedChannel *channel, uint32_t size,
return TRUE;
}
-static void red_channel_event(int fd, int event, void *data)
+static void red_channel_client_event(int fd, int event, void *data)
{
- RedChannel *channel = (RedChannel *)data;
+ RedChannelClient *rcc = (RedChannelClient *)data;
if (event & SPICE_WATCH_EVENT_READ) {
- red_channel_receive(channel);
+ red_channel_client_receive(rcc);
}
if (event & SPICE_WATCH_EVENT_WRITE) {
- red_channel_push(channel);
+ red_channel_client_push(rcc);
}
}
-void red_channel_init_send_data(RedChannel *channel, uint16_t msg_type, PipeItem *item)
+void red_channel_client_init_send_data(RedChannelClient *rcc, uint16_t msg_type, PipeItem *item)
{
- ASSERT(channel->send_data.item == NULL);
- channel->send_data.header->type = msg_type;
- channel->send_data.item = item;
+ ASSERT(red_channel_client_no_item_being_sent(rcc));
+ ASSERT(msg_type != 0);
+ rcc->send_data.header->type = msg_type;
+ rcc->send_data.item = item;
if (item) {
- channel->hold_item(channel, item);
+ rcc->channel->hold_item(rcc, item);
}
}
-void red_channel_send(RedChannel *channel)
-{
- red_peer_handle_outgoing(channel->stream, &channel->outgoing);
-}
-
-void red_channel_begin_send_message(RedChannel *channel)
-{
- spice_marshaller_flush(channel->send_data.marshaller);
- channel->send_data.size = spice_marshaller_get_total_size(channel->send_data.marshaller);
- channel->send_data.header->size = channel->send_data.size - sizeof(SpiceDataHeader);
- channel->ack_data.messages_window++;
- channel->send_data.header = NULL; /* avoid writing to this until we have a new message */
- red_channel_send(channel);
-}
-
-void red_channel_push(RedChannel *channel)
+void red_channel_client_begin_send_message(RedChannelClient *rcc)
{
- PipeItem *pipe_item;
-
- if (!channel) {
- return;
- }
+ SpiceMarshaller *m = rcc->send_data.marshaller;
- if (!channel->during_send) {
- channel->during_send = TRUE;
- } else {
+ // TODO - better check: type in channel_allowed_types. Better: type in channel_allowed_types(channel_state)
+ if (rcc->send_data.header->type == 0) {
+ red_printf("BUG: header->type == 0");
return;
}
-
- if (channel->send_data.blocked) {
- red_channel_send(channel);
- }
-
- while ((pipe_item = red_channel_pipe_get(channel))) {
- red_channel_send_item(channel, pipe_item);
- }
- channel->during_send = FALSE;
+ spice_marshaller_flush(m);
+ rcc->send_data.size = spice_marshaller_get_total_size(m);
+ rcc->send_data.header->size = rcc->send_data.size - sizeof(SpiceDataHeader);
+ rcc->ack_data.messages_window++;
+ rcc->send_data.header = NULL; /* avoid writing to this until we have a new message */
+ red_channel_client_send(rcc);
}
-uint64_t red_channel_get_message_serial(RedChannel *channel)
+uint64_t red_channel_client_get_message_serial(RedChannelClient *rcc)
{
- return channel->send_data.serial;
+ return rcc->send_data.serial;
}
-void red_channel_set_message_serial(RedChannel *channel, uint64_t serial)
+void red_channel_client_set_message_serial(RedChannelClient *rcc, uint64_t serial)
{
- channel->send_data.serial = serial;
+ rcc->send_data.serial = serial;
}
void red_channel_pipe_item_init(RedChannel *channel, PipeItem *item, int type)
@@ -657,28 +770,19 @@ void red_channel_pipe_add_type(RedChannel *channel, int pipe_item_type)
red_channel_push(channel);
}
-static inline int red_channel_waiting_for_ack(RedChannel *channel)
+int red_channel_is_connected(RedChannel *channel)
{
- return (channel->handle_acks && (channel->ack_data.messages_window > channel->ack_data.client_window * 2));
+ return channel->rcc != NULL;
}
-static inline PipeItem *red_channel_pipe_get(RedChannel *channel)
+void red_channel_client_clear_sent_item(RedChannelClient *rcc)
{
- PipeItem *item;
-
- if (!channel || channel->send_data.blocked ||
- red_channel_waiting_for_ack(channel) ||
- !(item = (PipeItem *)ring_get_tail(&channel->pipe))) {
- return NULL;
+ if (rcc->send_data.item) {
+ red_channel_client_release_item(rcc, rcc->send_data.item, TRUE);
+ rcc->send_data.item = NULL;
}
- --channel->pipe_size;
- ring_remove(&item->link);
- return item;
-}
-
-int red_channel_is_connected(RedChannel *channel)
-{
- return !!channel->stream;
+ rcc->send_data.blocked = FALSE;
+ rcc->send_data.size = 0;
}
void red_channel_pipe_clear(RedChannel *channel)
@@ -686,82 +790,161 @@ void red_channel_pipe_clear(RedChannel *channel)
PipeItem *item;
ASSERT(channel);
- if (channel->send_data.item) {
- red_channel_release_item(channel, channel->send_data.item, TRUE);
- channel->send_data.item = NULL;
+ if (channel->rcc) {
+ red_channel_client_clear_sent_item(channel->rcc);
}
while ((item = (PipeItem *)ring_get_head(&channel->pipe))) {
ring_remove(&item->link);
- red_channel_release_item(channel, item, FALSE);
+ red_channel_client_release_item(channel->rcc, item, FALSE);
}
channel->pipe_size = 0;
}
+void red_channel_client_ack_zero_messages_window(RedChannelClient *rcc)
+{
+ rcc->ack_data.messages_window = 0;
+}
+
void red_channel_ack_zero_messages_window(RedChannel *channel)
{
- channel->ack_data.messages_window = 0;
+ red_channel_client_ack_zero_messages_window(channel->rcc);
}
-void red_channel_ack_set_client_window(RedChannel *channel, int client_window)
+void red_channel_client_ack_set_client_window(RedChannelClient *rcc, int client_window)
{
- channel->ack_data.client_window = client_window;
+ rcc->ack_data.client_window = client_window;
+}
+
+void red_channel_ack_set_client_window(RedChannel* channel, int client_window)
+{
+ if (channel->rcc) {
+ red_channel_client_ack_set_client_window(channel->rcc, client_window);
+ }
+}
+
+void red_channel_client_disconnect(RedChannelClient *rcc)
+{
+ red_printf("%p (channel %p)", rcc, rcc->channel);
+
+ if (rcc->send_data.item) {
+ rcc->channel->release_item(rcc, rcc->send_data.item, FALSE);
+ }
+ // TODO: clear our references from the pipe
+ reds_stream_free(rcc->stream);
+ rcc->send_data.item = NULL;
+ rcc->send_data.blocked = FALSE;
+ rcc->send_data.size = 0;
+ rcc->channel->rcc = NULL;
+}
+
+void red_channel_disconnect(RedChannel *channel)
+{
+ red_channel_pipe_clear(channel);
+ if (channel->rcc) {
+ red_channel_client_disconnect(channel->rcc);
+ }
+}
+
+int red_channel_all_clients_serials_are_zero(RedChannel *channel)
+{
+ return (!channel->rcc || channel->rcc->send_data.serial == 0);
+}
+
+void red_channel_apply_clients(RedChannel *channel, channel_client_visitor v)
+{
+ if (channel->rcc) {
+ v(channel->rcc);
+ }
+}
+
+void red_channel_apply_clients_data(RedChannel *channel, channel_client_visitor_data v, void *data)
+{
+ if (channel->rcc) {
+ v(channel->rcc, data);
+ }
+}
+
+void red_channel_set_shut(RedChannel *channel)
+{
+ if (channel->rcc) {
+ channel->rcc->incoming.shut = TRUE;
+ }
}
int red_channel_all_blocked(RedChannel *channel)
{
- return channel->send_data.blocked;
+ return !channel || !channel->rcc || channel->rcc->send_data.blocked;
}
int red_channel_any_blocked(RedChannel *channel)
{
- return channel->send_data.blocked;
+ return !channel || !channel->rcc || channel->rcc->send_data.blocked;
}
-int red_channel_send_message_pending(RedChannel *channel)
+int red_channel_client_blocked(RedChannelClient *rcc)
{
- return channel->send_data.header->type != 0;
+ return rcc && rcc->send_data.blocked;
}
-/* accessors for RedChannel */
-SpiceMarshaller *red_channel_get_marshaller(RedChannel *channel)
+int red_channel_client_send_message_pending(RedChannelClient *rcc)
{
- return channel->send_data.marshaller;
+ return rcc->send_data.header->type != 0;
}
-RedsStream *red_channel_get_stream(RedChannel *channel)
+/* accessors for RedChannelClient */
+SpiceMarshaller *red_channel_client_get_marshaller(RedChannelClient *rcc)
{
- return channel->stream;
+ return rcc->send_data.marshaller;
}
-SpiceDataHeader *red_channel_get_header(RedChannel *channel)
+RedsStream *red_channel_client_get_stream(RedChannelClient *rcc)
{
- return channel->send_data.header;
+ return rcc->stream;
+}
+
+SpiceDataHeader *red_channel_client_get_header(RedChannelClient *rcc)
+{
+ return rcc->send_data.header;
}
/* end of accessors */
int red_channel_get_first_socket(RedChannel *channel)
{
- if (!channel->stream) {
+ if (!channel->rcc || !channel->rcc->stream) {
return -1;
}
- return channel->stream->socket;
+ return channel->rcc->stream->socket;
+}
+
+int red_channel_client_item_being_sent(RedChannelClient *rcc, PipeItem *item)
+{
+ return rcc->send_data.item == item;
}
int red_channel_item_being_sent(RedChannel *channel, PipeItem *item)
{
- return channel->send_data.item == item;
+ return channel->rcc && red_channel_client_item_being_sent(channel->rcc, item);
}
int red_channel_no_item_being_sent(RedChannel *channel)
{
- return channel->send_data.item == NULL;
+ return !channel->rcc || red_channel_client_no_item_being_sent(channel->rcc);
}
-void red_channel_disconnect(RedChannel *channel)
+int red_channel_client_no_item_being_sent(RedChannelClient *rcc)
{
- red_channel_pipe_clear(channel);
- reds_stream_free(channel->stream);
- channel->stream = NULL;
- channel->send_data.blocked = FALSE;
- channel->send_data.size = 0;
+ return !rcc || (rcc->send_data.size == 0);
+}
+
+static void red_channel_client_pipe_remove(RedChannelClient *rcc, PipeItem *item)
+{
+ rcc->channel->pipe_size--;
+ ring_remove(&item->link);
+}
+
+void red_channel_client_pipe_remove_and_release(RedChannelClient *rcc,
+ PipeItem *item)
+{
+ red_channel_client_pipe_remove(rcc, item);
+ red_channel_client_release_item(rcc, item, FALSE);
}
diff --git a/server/red_channel.h b/server/red_channel.h
index d05722c3..e7a83d32 100644
--- a/server/red_channel.h
+++ b/server/red_channel.h
@@ -97,6 +97,9 @@ typedef struct BufDescriptor {
uint8_t *data;
} BufDescriptor;
+typedef struct RedChannel RedChannel;
+typedef struct RedChannelClient RedChannelClient;
+
/* Messages handled by red_channel
* SET_ACK - sent to client on channel connection
* Note that the numbers don't have to correspond to spice message types,
@@ -112,37 +115,33 @@ typedef struct PipeItem {
int type;
} PipeItem;
-typedef struct RedChannel RedChannel;
-
-typedef uint8_t *(*channel_alloc_msg_recv_buf_proc)(RedChannel *channel,
+typedef uint8_t *(*channel_alloc_msg_recv_buf_proc)(RedChannelClient *channel,
SpiceDataHeader *msg_header);
-typedef int (*channel_handle_parsed_proc)(RedChannel *channel, uint32_t size, uint16_t type,
+typedef int (*channel_handle_parsed_proc)(RedChannelClient *rcc, uint32_t size, uint16_t type,
void *message);
-typedef int (*channel_handle_message_proc)(RedChannel *channel,
+typedef int (*channel_handle_message_proc)(RedChannelClient *rcc,
SpiceDataHeader *header, uint8_t *msg);
-typedef void (*channel_release_msg_recv_buf_proc)(RedChannel *channel,
+typedef void (*channel_release_msg_recv_buf_proc)(RedChannelClient *channel,
SpiceDataHeader *msg_header, uint8_t *msg);
-typedef void (*channel_disconnect_proc)(RedChannel *channel);
-typedef int (*channel_configure_socket_proc)(RedChannel *channel);
-typedef void (*channel_send_pipe_item_proc)(RedChannel *channel, PipeItem *item);
-typedef void (*channel_hold_pipe_item_proc)(RedChannel *channel, PipeItem *item);
-typedef void (*channel_release_pipe_item_proc)(RedChannel *channel,
+typedef void (*channel_disconnect_proc)(RedChannelClient *rcc);
+typedef int (*channel_configure_socket_proc)(RedChannelClient *rcc);
+typedef void (*channel_send_pipe_item_proc)(RedChannelClient *rcc, PipeItem *item);
+typedef void (*channel_hold_pipe_item_proc)(RedChannelClient *rcc, PipeItem *item);
+typedef void (*channel_release_pipe_item_proc)(RedChannelClient *rcc,
PipeItem *item, int item_pushed);
-typedef void (*channel_on_incoming_error_proc)(RedChannel *channel);
-typedef void (*channel_on_outgoing_error_proc)(RedChannel *channel);
+typedef void (*channel_on_incoming_error_proc)(RedChannelClient *rcc);
+typedef void (*channel_on_outgoing_error_proc)(RedChannelClient *rcc);
-typedef int (*channel_handle_migrate_flush_mark_proc)(RedChannel *channel);
-typedef uint64_t (*channel_handle_migrate_data_proc)(RedChannel *channel,
+typedef int (*channel_handle_migrate_flush_mark_proc)(RedChannelClient *base);
+typedef uint64_t (*channel_handle_migrate_data_proc)(RedChannelClient *base,
uint32_t size, void *message);
-typedef uint64_t (*channel_handle_migrate_data_get_serial_proc)(RedChannel *channel,
+typedef uint64_t (*channel_handle_migrate_data_get_serial_proc)(RedChannelClient *base,
uint32_t size, void *message);
-struct RedChannel {
+struct RedChannelClient {
+ RingItem channel_link;
+ RedChannel *channel;
RedsStream *stream;
- SpiceCoreInterface *core;
- int migrate;
- int handle_acks;
-
struct {
uint32_t generation;
uint32_t client_generation;
@@ -150,9 +149,6 @@ struct RedChannel {
uint32_t client_window;
} ack_data;
- Ring pipe;
- uint32_t pipe_size;
-
struct {
SpiceMarshaller *marshaller;
SpiceDataHeader *header;
@@ -164,16 +160,28 @@ struct RedChannel {
OutgoingHandler outgoing;
IncomingHandler incoming;
+ int during_send;
+};
+
+struct RedChannel {
+ SpiceCoreInterface *core;
+ int migrate;
+ int handle_acks;
+
+ RedChannelClient *rcc;
+
+ Ring pipe;
+ uint32_t pipe_size;
OutgoingHandlerInterface outgoing_cb;
IncomingHandlerInterface incoming_cb;
+ channel_configure_socket_proc config_socket;
channel_disconnect_proc disconnect;
channel_send_pipe_item_proc send_item;
channel_hold_pipe_item_proc hold_item;
channel_release_pipe_item_proc release_item;
- int during_send;
/* Stuff below added for Main and Inputs channels switch to RedChannel
* (might be removed later) */
channel_on_incoming_error_proc on_incoming_error; /* alternative to disconnect */
@@ -190,7 +198,7 @@ struct RedChannel {
/* if one of the callbacks should cause disconnect, use red_channel_shutdown and don't
explicitly destroy the channel */
-RedChannel *red_channel_create(int size, RedsStream *stream,
+RedChannel *red_channel_create(int size,
SpiceCoreInterface *core,
int migrate, int handle_acks,
channel_configure_socket_proc config_socket,
@@ -207,7 +215,7 @@ RedChannel *red_channel_create(int size, RedsStream *stream,
/* alternative constructor, meant for marshaller based (inputs,main) channels,
* will become default eventually */
-RedChannel *red_channel_create_parser(int size, RedsStream *stream,
+RedChannel *red_channel_create_parser(int size,
SpiceCoreInterface *core,
int migrate, int handle_acks,
channel_configure_socket_proc config_socket,
@@ -223,29 +231,31 @@ RedChannel *red_channel_create_parser(int size, RedsStream *stream,
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);
-
+RedChannelClient *red_channel_client_create(int size, RedChannel *channel,
+ RedsStream *stream);
int red_channel_is_connected(RedChannel *channel);
+void red_channel_client_destroy(RedChannelClient *rcc);
void red_channel_destroy(RedChannel *channel);
/* should be called when a new channel is ready to send messages */
void red_channel_init_outgoing_messages_window(RedChannel *channel);
/* handles general channel msgs from the client */
-int red_channel_handle_message(RedChannel *channel, uint32_t size,
+int red_channel_client_handle_message(RedChannelClient *rcc, uint32_t size,
uint16_t type, void *message);
/* default error handler that disconnects channel */
-void red_channel_default_peer_on_error(RedChannel *channel);
+void red_channel_client_default_peer_on_error(RedChannelClient *rcc);
/* when preparing send_data: should call init and then use marshaller */
-void red_channel_init_send_data(RedChannel *channel, uint16_t msg_type, PipeItem *item);
+void red_channel_client_init_send_data(RedChannelClient *rcc, uint16_t msg_type, PipeItem *item);
-uint64_t red_channel_get_message_serial(RedChannel *channel);
-void red_channel_set_message_serial(RedChannel *channel, uint64_t);
+uint64_t red_channel_client_get_message_serial(RedChannelClient *channel);
+void red_channel_client_set_message_serial(RedChannelClient *channel, uint64_t);
-/* when sending a msg. should first call red_channel_begin_send_message */
-void red_channel_begin_send_message(RedChannel *channel);
+/* when sending a msg. should first call red_channel_client_begin_send_message */
+void red_channel_client_begin_send_message(RedChannelClient *rcc);
void red_channel_pipe_item_init(RedChannel *channel, PipeItem *item, int type);
void red_channel_pipe_add_push(RedChannel *channel, PipeItem *item);
@@ -253,14 +263,19 @@ void red_channel_pipe_add(RedChannel *channel, PipeItem *item);
void red_channel_pipe_add_after(RedChannel *channel, PipeItem *item, PipeItem *pos);
int red_channel_pipe_item_is_linked(RedChannel *channel, PipeItem *item);
void red_channel_pipe_item_remove(RedChannel *channel, PipeItem *item);
+void red_channel_client_pipe_remove_and_release(RedChannelClient *rcc, PipeItem *item);
void red_channel_pipe_add_tail(RedChannel *channel, PipeItem *item);
/* for types that use this routine -> the pipe item should be freed */
void red_channel_pipe_add_type(RedChannel *channel, int pipe_item_type);
+void red_channel_client_ack_zero_messages_window(RedChannelClient *rcc);
+void red_channel_client_ack_set_client_window(RedChannelClient *rcc, int client_window);
+void red_channel_client_push_set_ack(RedChannelClient *rcc);
void red_channel_ack_zero_messages_window(RedChannel *channel);
void red_channel_ack_set_client_window(RedChannel *channel, int client_window);
void red_channel_push_set_ack(RedChannel *channel);
+/* TODO: This sets all clients to shut state - probably we want to close per channel */
void red_channel_shutdown(RedChannel *channel);
int red_channel_get_first_socket(RedChannel *channel);
@@ -271,8 +286,10 @@ int red_channel_all_blocked(RedChannel *channel);
/* return TRUE if any of the connected clients to this channel are blocked */
int red_channel_any_blocked(RedChannel *channel);
+int red_channel_client_blocked(RedChannelClient *rcc);
+
/* helper for channels that have complex logic that can possibly ready a send */
-int red_channel_send_message_pending(RedChannel *channel);
+int red_channel_client_send_message_pending(RedChannelClient *rcc);
/* returns TRUE if item is being sent by one of the channel clients. This will
* be true if someone called init_send_data but send has not completed (or perhaps
@@ -281,6 +298,7 @@ int red_channel_send_message_pending(RedChannel *channel);
int red_channel_item_being_sent(RedChannel *channel, PipeItem *item);
int red_channel_no_item_being_sent(RedChannel *channel);
+int red_channel_client_no_item_being_sent(RedChannelClient *rcc);
// TODO: unstaticed for display/cursor channels. they do some specific pushes not through
// adding elements or on events. but not sure if this is actually required (only result
@@ -299,14 +317,18 @@ void red_channel_pipe_clear(RedChannel *channel);
// red_wait_pipe_item_sent
// handle_channel_events - this is the only one that was used before, and was in red_channel.c
void red_channel_receive(RedChannel *channel);
+void red_channel_client_receive(RedChannelClient *rcc);
+// For red_worker
void red_channel_send(RedChannel *channel);
+void red_channel_client_send(RedChannelClient *rcc);
// For red_worker
void red_channel_disconnect(RedChannel *channel);
+void red_channel_client_disconnect(RedChannelClient *rcc);
-/* accessors for RedChannel */
+/* accessors for RedChannelClient */
/* Note: the valid times to call red_channel_get_marshaller are just during send_item callback. */
-SpiceMarshaller *red_channel_get_marshaller(RedChannel *channel);
-RedsStream *red_channel_get_stream(RedChannel *channel);
+SpiceMarshaller *red_channel_client_get_marshaller(RedChannelClient *rcc);
+RedsStream *red_channel_client_get_stream(RedChannelClient *rcc);
/* this is a convenience function for sending messages, sometimes (migration only?)
* the serial from the header needs to be available for sending. Note that the header
@@ -314,5 +336,12 @@ RedsStream *red_channel_get_stream(RedChannel *channel);
* red_channel_begin_send_message. red_channel_init_send_data changes the header (sets
* the type in it) as a convenience function. It is preffered to do that through it and
* not via the below accessor and direct header manipulation. */
-SpiceDataHeader *red_channel_get_header(RedChannel *channel);
+SpiceDataHeader *red_channel_client_get_header(RedChannelClient *rcc);
+
+/* apply given function to all connected clients */
+typedef void (*channel_client_visitor)(RedChannelClient *rcc);
+typedef void (*channel_client_visitor_data)(RedChannelClient *rcc, void *data);
+void red_channel_apply_clients(RedChannel *channel, channel_client_visitor v);
+void red_channel_apply_clients_data(RedChannel *channel, channel_client_visitor_data v, void *data);
+
#endif
diff --git a/server/red_client_shared_cache.h b/server/red_client_shared_cache.h
index 74553c0c..dddccc62 100644
--- a/server/red_client_shared_cache.h
+++ b/server/red_client_shared_cache.h
@@ -26,6 +26,7 @@
#define FUNC_NAME(name) pixmap_cache_##name
#define PRIVATE_FUNC_NAME(name) __pixmap_cache_##name
#define CHANNEL DisplayChannel
+#define CHANNEL_FROM_RCC(rcc) SPICE_CONTAINEROF(rcc->channel, CHANNEL, common.base);
#define CACH_GENERATION pixmap_cache_generation
#define INVAL_ALL_VERB SPICE_MSG_DISPLAY_INVAL_ALL_PIXMAPS
#else
@@ -35,12 +36,13 @@
#endif
-static int FUNC_NAME(hit)(CACHE *cache, uint64_t id, int *lossy, CHANNEL *channel)
+static int FUNC_NAME(hit)(CACHE *cache, uint64_t id, int *lossy, RedChannelClient *rcc)
{
+ CHANNEL *channel = CHANNEL_FROM_RCC(rcc);
NewCacheItem *item;
uint64_t serial;
- serial = red_channel_get_message_serial((RedChannel *)channel);
+ serial = red_channel_client_get_message_serial(rcc);
pthread_mutex_lock(&cache->lock);
item = cache->hash_table[CACHE_HASH_KEY(id)];
@@ -79,8 +81,9 @@ static int FUNC_NAME(set_lossy)(CACHE *cache, uint64_t id, int lossy)
return !!item;
}
-static int FUNC_NAME(add)(CACHE *cache, uint64_t id, uint32_t size, int lossy, CHANNEL *channel)
+static int FUNC_NAME(add)(CACHE *cache, uint64_t id, uint32_t size, int lossy, RedChannelClient *rcc)
{
+ CHANNEL *channel = CHANNEL_FROM_RCC(rcc);
NewCacheItem *item;
uint64_t serial;
int key;
@@ -88,7 +91,7 @@ static int FUNC_NAME(add)(CACHE *cache, uint64_t id, uint32_t size, int lossy, C
ASSERT(size > 0);
item = spice_new(NewCacheItem, 1);
- serial = red_channel_get_message_serial((RedChannel *)channel);
+ serial = red_channel_client_get_message_serial(rcc);
pthread_mutex_lock(&cache->lock);
@@ -166,13 +169,14 @@ static void PRIVATE_FUNC_NAME(clear)(CACHE *cache)
cache->items = 0;
}
-static void FUNC_NAME(reset)(CACHE *cache, CHANNEL *channel, SpiceMsgWaitForChannels* sync_data)
+static void FUNC_NAME(reset)(CACHE *cache, RedChannelClient *rcc, SpiceMsgWaitForChannels* sync_data)
{
+ CHANNEL *channel = CHANNEL_FROM_RCC(rcc);
uint8_t wait_count;
uint64_t serial;
uint32_t i;
- serial = red_channel_get_message_serial((RedChannel *)channel);
+ serial = red_channel_client_get_message_serial(rcc);
pthread_mutex_lock(&cache->lock);
PRIVATE_FUNC_NAME(clear)(cache);
@@ -230,4 +234,5 @@ static void FUNC_NAME(destroy)(CACHE *cache)
#undef FUNC_NAME
#undef VAR_NAME
#undef CHANNEL
+#undef CHANNEL_FROM_RCC
diff --git a/server/red_tunnel_worker.c b/server/red_tunnel_worker.c
index b649c60b..5caa8b9d 100644
--- a/server/red_tunnel_worker.c
+++ b/server/red_tunnel_worker.c
@@ -1645,9 +1645,11 @@ static int tunnel_channel_handle_socket_token(TunnelChannel *channel, RedSocket
return TRUE;
}
-static uint8_t *tunnel_channel_alloc_msg_rcv_buf(RedChannel *channel, SpiceDataHeader *msg_header)
+static uint8_t *tunnel_channel_alloc_msg_rcv_buf(RedChannelClient *rcc,
+ SpiceDataHeader *msg_header)
{
- TunnelChannel *tunnel_channel = (TunnelChannel *)channel;
+ TunnelChannel *tunnel_channel = (TunnelChannel *)rcc->channel;
+
if (msg_header->type == SPICE_MSGC_TUNNEL_SOCKET_DATA) {
return (__tunnel_worker_alloc_socket_rcv_buf(tunnel_channel->worker)->buf);
} else if ((msg_header->type == SPICE_MSGC_MIGRATE_DATA) ||
@@ -1659,10 +1661,11 @@ static uint8_t *tunnel_channel_alloc_msg_rcv_buf(RedChannel *channel, SpiceDataH
}
// called by the receive routine of the channel, before the buffer was assigned to a socket
-static void tunnel_channel_release_msg_rcv_buf(RedChannel *channel, SpiceDataHeader *msg_header,
+static void tunnel_channel_release_msg_rcv_buf(RedChannelClient *rcc, SpiceDataHeader *msg_header,
uint8_t *msg)
{
- TunnelChannel *tunnel_channel = (TunnelChannel *)channel;
+ TunnelChannel *tunnel_channel = (TunnelChannel *)rcc->channel;
+
if (msg_header->type == SPICE_MSGC_TUNNEL_SOCKET_DATA) {
ASSERT(!(SPICE_CONTAINEROF(msg, RedSocketRawRcvBuf, buf)->base.usr_opaque));
__tunnel_worker_free_socket_rcv_buf(tunnel_channel->worker,
@@ -1744,9 +1747,9 @@ static void __tunnel_channel_fill_socket_migrate_item(TunnelChannel *channel, Re
}
static void release_migrate_item(TunnelMigrateItem *item);
-static int tunnel_channel_handle_migrate_mark(RedChannel *base)
+static int tunnel_channel_handle_migrate_mark(RedChannelClient *rcc)
{
- TunnelChannel *channel = SPICE_CONTAINEROF(base, TunnelChannel, base);
+ TunnelChannel *channel = SPICE_CONTAINEROF(rcc->channel, TunnelChannel, base);
TunnelMigrateItem *migrate_item = NULL;
TunnelService *service;
TunnelMigrateServiceItem *mig_service;
@@ -2159,7 +2162,7 @@ static inline void tunnel_channel_activate_migrated_sockets(TunnelChannel *chann
}
}
-static uint64_t tunnel_channel_handle_migrate_data_get_serial(RedChannel *base,
+static uint64_t tunnel_channel_handle_migrate_data_get_serial(RedChannelClient *rcc,
uint32_t size, void *msg)
{
TunnelMigrateData *migrate_data = msg;
@@ -2172,10 +2175,10 @@ static uint64_t tunnel_channel_handle_migrate_data_get_serial(RedChannel *base,
return migrate_data->message_serial;
}
-static uint64_t tunnel_channel_handle_migrate_data(RedChannel *base,
+static uint64_t tunnel_channel_handle_migrate_data(RedChannelClient *rcc,
uint32_t size, void *msg)
{
- TunnelChannel *channel = SPICE_CONTAINEROF(base, TunnelChannel, base);
+ TunnelChannel *channel = SPICE_CONTAINEROF(rcc->channel, TunnelChannel, base);
TunnelMigrateSocketList *sockets_list;
TunnelMigrateServicesList *services_list;
TunnelMigrateData *migrate_data = msg;
@@ -2242,9 +2245,9 @@ error:
}
// msg was allocated by tunnel_channel_alloc_msg_rcv_buf
-static int tunnel_channel_handle_message(RedChannel *channel, SpiceDataHeader *header, uint8_t *msg)
+static int tunnel_channel_handle_message(RedChannelClient *rcc, SpiceDataHeader *header, uint8_t *msg)
{
- TunnelChannel *tunnel_channel = (TunnelChannel *)channel;
+ TunnelChannel *tunnel_channel = (TunnelChannel *)rcc->channel;
RedSocket *sckt = NULL;
// retrieve the sckt
switch (header->type) {
@@ -2268,7 +2271,7 @@ static int tunnel_channel_handle_message(RedChannel *channel, SpiceDataHeader *h
}
break;
default:
- return red_channel_handle_message(channel, header->size, header->type, msg);
+ return red_channel_client_handle_message(rcc, header->size, header->type, msg);
}
switch (header->type) {
@@ -2337,7 +2340,7 @@ static int tunnel_channel_handle_message(RedChannel *channel, SpiceDataHeader *h
return tunnel_channel_handle_socket_token(tunnel_channel, sckt,
(SpiceMsgcTunnelSocketTokens *)msg);
default:
- return red_channel_handle_message(channel, header->size, header->type, msg);
+ return red_channel_client_handle_message(rcc, header->size, header->type, msg);
}
return TRUE;
}
@@ -2346,13 +2349,16 @@ static int tunnel_channel_handle_message(RedChannel *channel, SpiceDataHeader *h
/* outgoing msgs
********************************/
-static void tunnel_channel_marshall_migrate(TunnelChannel *tunnel_channel, SpiceMarshaller *m, PipeItem *item)
+static void tunnel_channel_marshall_migrate(RedChannelClient *rcc, SpiceMarshaller *m, PipeItem *item)
{
- ASSERT(tunnel_channel);
+ TunnelChannel *tunnel_channel;
+
+ ASSERT(rcc);
+ tunnel_channel = SPICE_CONTAINEROF(rcc->channel, TunnelChannel, base);
tunnel_channel->send_data.u.migrate.flags =
SPICE_MIGRATE_NEED_FLUSH | SPICE_MIGRATE_NEED_DATA_TRANSFER;
tunnel_channel->expect_migrate_mark = TRUE;
- red_channel_init_send_data(&tunnel_channel->base, SPICE_MSG_MIGRATE, item);
+ red_channel_client_init_send_data(rcc, SPICE_MSG_MIGRATE, item);
spice_marshaller_add_ref(m,
(uint8_t*)&tunnel_channel->send_data.u.migrate,
sizeof(SpiceMsgMigrate));
@@ -2492,20 +2498,23 @@ static int __tunnel_channel_marshall_socket_migrate_data(TunnelChannel *channel,
return (cur_offset - offset);
}
-static void tunnel_channel_marshall_migrate_data(TunnelChannel *channel,
+static void tunnel_channel_marshall_migrate_data(RedChannelClient *rcc,
SpiceMarshaller *m, PipeItem *item)
{
- TunnelMigrateData *migrate_data = &channel->send_data.u.migrate_data;
+ TunnelChannel *tunnel_channel;
+ TunnelMigrateData *migrate_data;
TunnelMigrateItem *migrate_item = (TunnelMigrateItem *)item;
int i;
uint32_t data_buf_offset = 0; // current location in data[0] field
- ASSERT(channel);
+ ASSERT(rcc);
+ tunnel_channel = SPICE_CONTAINEROF(rcc->channel, TunnelChannel, base);
+ migrate_data = &tunnel_channel->send_data.u.migrate_data;
migrate_data->magic = TUNNEL_MIGRATE_DATA_MAGIC;
migrate_data->version = TUNNEL_MIGRATE_DATA_VERSION;
- migrate_data->message_serial = red_channel_get_message_serial(&channel->base);
- red_channel_init_send_data(&channel->base, SPICE_MSG_MIGRATE_DATA, item);
+ migrate_data->message_serial = red_channel_client_get_message_serial(rcc);
+ red_channel_client_init_send_data(rcc, SPICE_MSG_MIGRATE_DATA, item);
spice_marshaller_add_ref(m, (uint8_t*)migrate_data, sizeof(*migrate_data));
migrate_data->slirp_state = data_buf_offset;
@@ -2519,7 +2528,7 @@ static void tunnel_channel_marshall_migrate_data(TunnelChannel *channel,
for (i = 0; i < migrate_item->services_list->num_services; i++) {
migrate_item->services_list->services[i] = data_buf_offset;
- data_buf_offset += __tunnel_channel_marshall_service_migrate_data(channel, m,
+ data_buf_offset += __tunnel_channel_marshall_service_migrate_data(tunnel_channel, m,
migrate_item->services + i,
data_buf_offset);
}
@@ -2532,83 +2541,93 @@ static void tunnel_channel_marshall_migrate_data(TunnelChannel *channel,
for (i = 0; i < migrate_item->sockets_list->num_sockets; i++) {
migrate_item->sockets_list->sockets[i] = data_buf_offset;
- data_buf_offset += __tunnel_channel_marshall_socket_migrate_data(channel, m,
+ data_buf_offset += __tunnel_channel_marshall_socket_migrate_data(tunnel_channel, m,
migrate_item->sockets_data + i,
data_buf_offset);
}
}
-static void tunnel_channel_marshall_init(TunnelChannel *channel, SpiceMarshaller *m, PipeItem *item)
+static void tunnel_channel_marshall_init(RedChannelClient *rcc, SpiceMarshaller *m, PipeItem *item)
{
- ASSERT(channel);
+ TunnelChannel *channel;
+ ASSERT(rcc);
+ channel = SPICE_CONTAINEROF(rcc->channel, TunnelChannel, base);
channel->send_data.u.init.max_socket_data_size = MAX_SOCKET_DATA_SIZE;
channel->send_data.u.init.max_num_of_sockets = MAX_SOCKETS_NUM;
- red_channel_init_send_data(&channel->base, SPICE_MSG_TUNNEL_INIT, item);
+ red_channel_client_init_send_data(rcc, SPICE_MSG_TUNNEL_INIT, item);
spice_marshaller_add_ref(m, (uint8_t*)&channel->send_data.u.init, sizeof(SpiceMsgTunnelInit));
}
-static void tunnel_channel_marshall_service_ip_map(TunnelChannel *channel, SpiceMarshaller *m, PipeItem *item)
+static void tunnel_channel_marshall_service_ip_map(RedChannelClient *rcc, SpiceMarshaller *m, PipeItem *item)
{
+ TunnelChannel *tunnel_channel;
TunnelService *service = SPICE_CONTAINEROF(item, TunnelService, pipe_item);
- channel->send_data.u.service_ip.service_id = service->id;
- channel->send_data.u.service_ip.virtual_ip.type = SPICE_TUNNEL_IP_TYPE_IPv4;
+ tunnel_channel = SPICE_CONTAINEROF(rcc->channel, TunnelChannel, base);
+ tunnel_channel->send_data.u.service_ip.service_id = service->id;
+ tunnel_channel->send_data.u.service_ip.virtual_ip.type = SPICE_TUNNEL_IP_TYPE_IPv4;
- red_channel_init_send_data(&channel->base, SPICE_MSG_TUNNEL_SERVICE_IP_MAP, item);
- spice_marshaller_add_ref(m, (uint8_t*)&channel->send_data.u.service_ip,
+ red_channel_client_init_send_data(rcc, SPICE_MSG_TUNNEL_SERVICE_IP_MAP, item);
+ spice_marshaller_add_ref(m, (uint8_t*)&tunnel_channel->send_data.u.service_ip,
sizeof(SpiceMsgTunnelServiceIpMap));
spice_marshaller_add_ref(m, (uint8_t*)&service->virt_ip.s_addr, sizeof(SpiceTunnelIPv4));
}
-static void tunnel_channel_marshall_socket_open(TunnelChannel *channel, SpiceMarshaller *m, PipeItem *item)
+static void tunnel_channel_marshall_socket_open(RedChannelClient *rcc, SpiceMarshaller *m, PipeItem *item)
{
+ TunnelChannel *tunnel_channel;
RedSocketOutData *sckt_out_data = SPICE_CONTAINEROF(item, RedSocketOutData, status_pipe_item);
RedSocket *sckt = SPICE_CONTAINEROF(sckt_out_data, RedSocket, out_data);
- channel->send_data.u.socket_open.connection_id = sckt->connection_id;
- channel->send_data.u.socket_open.service_id = sckt->far_service->id;
- channel->send_data.u.socket_open.tokens = SOCKET_WINDOW_SIZE;
+ tunnel_channel = SPICE_CONTAINEROF(rcc->channel, TunnelChannel, base);
+ tunnel_channel->send_data.u.socket_open.connection_id = sckt->connection_id;
+ tunnel_channel->send_data.u.socket_open.service_id = sckt->far_service->id;
+ tunnel_channel->send_data.u.socket_open.tokens = SOCKET_WINDOW_SIZE;
sckt->in_data.client_total_num_tokens = SOCKET_WINDOW_SIZE;
sckt->in_data.num_tokens = 0;
- red_channel_init_send_data(&channel->base, SPICE_MSG_TUNNEL_SOCKET_OPEN, item);
- spice_marshaller_add_ref(m, (uint8_t*)&channel->send_data.u.socket_open,
- sizeof(channel->send_data.u.socket_open));
+ red_channel_client_init_send_data(rcc, SPICE_MSG_TUNNEL_SOCKET_OPEN, item);
+ spice_marshaller_add_ref(m, (uint8_t*)&tunnel_channel->send_data.u.socket_open,
+ sizeof(tunnel_channel->send_data.u.socket_open));
#ifdef DEBUG_NETWORK
PRINT_SCKT(sckt);
#endif
}
-static void tunnel_channel_marshall_socket_fin(TunnelChannel *channel, SpiceMarshaller *m, PipeItem *item)
+static void tunnel_channel_marshall_socket_fin(RedChannelClient *rcc, SpiceMarshaller *m, PipeItem *item)
{
+ TunnelChannel *tunnel_channel;
RedSocketOutData *sckt_out_data = SPICE_CONTAINEROF(item, RedSocketOutData, status_pipe_item);
RedSocket *sckt = SPICE_CONTAINEROF(sckt_out_data, RedSocket, out_data);
ASSERT(!sckt->out_data.ready_chunks_queue.head);
+ tunnel_channel = SPICE_CONTAINEROF(rcc->channel, TunnelChannel, base);
if (sckt->out_data.process_queue->head) {
red_printf("socket sent FIN but there are still buffers in outgoing process queue"
"(local_port=%d, service_id=%d)",
ntohs(sckt->local_port), sckt->far_service->id);
}
- channel->send_data.u.socket_fin.connection_id = sckt->connection_id;
+ tunnel_channel->send_data.u.socket_fin.connection_id = sckt->connection_id;
- red_channel_init_send_data(&channel->base, SPICE_MSG_TUNNEL_SOCKET_FIN, item);
- spice_marshaller_add_ref(m, (uint8_t*)&channel->send_data.u.socket_fin,
- sizeof(channel->send_data.u.socket_fin));
+ red_channel_client_init_send_data(rcc, SPICE_MSG_TUNNEL_SOCKET_FIN, item);
+ spice_marshaller_add_ref(m, (uint8_t*)&tunnel_channel->send_data.u.socket_fin,
+ sizeof(tunnel_channel->send_data.u.socket_fin));
#ifdef DEBUG_NETWORK
PRINT_SCKT(sckt);
#endif
}
-static void tunnel_channel_marshall_socket_close(TunnelChannel *channel, SpiceMarshaller *m, PipeItem *item)
+static void tunnel_channel_marshall_socket_close(RedChannelClient *rcc, SpiceMarshaller *m, PipeItem *item)
{
+ TunnelChannel *tunnel_channel;
RedSocketOutData *sckt_out_data = SPICE_CONTAINEROF(item, RedSocketOutData, status_pipe_item);
RedSocket *sckt = SPICE_CONTAINEROF(sckt_out_data, RedSocket, out_data);
+ tunnel_channel = SPICE_CONTAINEROF(rcc->channel, TunnelChannel, base);
// can happen when it is a forced close
if (sckt->out_data.ready_chunks_queue.head) {
red_printf("socket closed but there are still buffers in outgoing ready queue"
@@ -2623,65 +2642,71 @@ static void tunnel_channel_marshall_socket_close(TunnelChannel *channel, SpiceMa
ntohs(sckt->local_port), sckt->far_service->id);
}
- channel->send_data.u.socket_close.connection_id = sckt->connection_id;
+ tunnel_channel->send_data.u.socket_close.connection_id = sckt->connection_id;
- red_channel_init_send_data(&channel->base, SPICE_MSG_TUNNEL_SOCKET_CLOSE, item);
- spice_marshaller_add_ref(m, (uint8_t*)&channel->send_data.u.socket_close,
- sizeof(channel->send_data.u.socket_close));
+ red_channel_client_init_send_data(rcc, SPICE_MSG_TUNNEL_SOCKET_CLOSE, item);
+ spice_marshaller_add_ref(m, (uint8_t*)&tunnel_channel->send_data.u.socket_close,
+ sizeof(tunnel_channel->send_data.u.socket_close));
#ifdef DEBUG_NETWORK
PRINT_SCKT(sckt);
#endif
}
-static void tunnel_channel_marshall_socket_closed_ack(TunnelChannel *channel, SpiceMarshaller *m, PipeItem *item)
+static void tunnel_channel_marshall_socket_closed_ack(RedChannelClient *rcc, SpiceMarshaller *m, PipeItem *item)
{
+ TunnelChannel *tunnel_channel;
RedSocketOutData *sckt_out_data = SPICE_CONTAINEROF(item, RedSocketOutData, status_pipe_item);
RedSocket *sckt = SPICE_CONTAINEROF(sckt_out_data, RedSocket, out_data);
- channel->send_data.u.socket_close_ack.connection_id = sckt->connection_id;
+ tunnel_channel = SPICE_CONTAINEROF(rcc->channel, TunnelChannel, base);
+ tunnel_channel->send_data.u.socket_close_ack.connection_id = sckt->connection_id;
// pipe item is null because we free the sckt.
- red_channel_init_send_data(&channel->base, SPICE_MSG_TUNNEL_SOCKET_CLOSED_ACK, NULL);
- spice_marshaller_add_ref(m, (uint8_t*)&channel->send_data.u.socket_close_ack,
- sizeof(channel->send_data.u.socket_close_ack));
+ red_channel_client_init_send_data(rcc, SPICE_MSG_TUNNEL_SOCKET_CLOSED_ACK, NULL);
+ spice_marshaller_add_ref(m, (uint8_t*)&tunnel_channel->send_data.u.socket_close_ack,
+ sizeof(tunnel_channel->send_data.u.socket_close_ack));
#ifdef DEBUG_NETWORK
PRINT_SCKT(sckt);
#endif
ASSERT(sckt->client_waits_close_ack && (sckt->client_status == CLIENT_SCKT_STATUS_CLOSED));
- tunnel_worker_free_socket(channel->worker, sckt);
- if (CHECK_TUNNEL_ERROR(channel)) {
- tunnel_shutdown(channel->worker);
+ tunnel_worker_free_socket(tunnel_channel->worker, sckt);
+ if (CHECK_TUNNEL_ERROR(tunnel_channel)) {
+ tunnel_shutdown(tunnel_channel->worker);
}
}
-static void tunnel_channel_marshall_socket_token(TunnelChannel *channel, SpiceMarshaller *m, PipeItem *item)
+static void tunnel_channel_marshall_socket_token(RedChannelClient *rcc, SpiceMarshaller *m, PipeItem *item)
{
+ TunnelChannel *tunnel_channel;
RedSocketOutData *sckt_out_data = SPICE_CONTAINEROF(item, RedSocketOutData, token_pipe_item);
RedSocket *sckt = SPICE_CONTAINEROF(sckt_out_data, RedSocket, out_data);
/* notice that the num of tokens sent can be > SOCKET_TOKENS_TO_SEND, since
the sending is performed after the pipe item was pushed */
- channel->send_data.u.socket_token.connection_id = sckt->connection_id;
+ tunnel_channel = SPICE_CONTAINEROF(rcc->channel, TunnelChannel, base);
+ tunnel_channel->send_data.u.socket_token.connection_id = sckt->connection_id;
if (sckt->in_data.num_tokens > 0) {
- channel->send_data.u.socket_token.num_tokens = sckt->in_data.num_tokens;
+ tunnel_channel->send_data.u.socket_token.num_tokens = sckt->in_data.num_tokens;
} else {
ASSERT(!sckt->in_data.client_total_num_tokens && !sckt->in_data.ready_chunks_queue.head);
- channel->send_data.u.socket_token.num_tokens = SOCKET_TOKENS_TO_SEND_FOR_PROCESS;
+ tunnel_channel->send_data.u.socket_token.num_tokens = SOCKET_TOKENS_TO_SEND_FOR_PROCESS;
}
- sckt->in_data.num_tokens -= channel->send_data.u.socket_token.num_tokens;
- sckt->in_data.client_total_num_tokens += channel->send_data.u.socket_token.num_tokens;
+ sckt->in_data.num_tokens -= tunnel_channel->send_data.u.socket_token.num_tokens;
+ sckt->in_data.client_total_num_tokens += tunnel_channel->send_data.u.socket_token.num_tokens;
ASSERT(sckt->in_data.client_total_num_tokens <= SOCKET_WINDOW_SIZE);
- red_channel_init_send_data(&channel->base, SPICE_MSG_TUNNEL_SOCKET_TOKEN, item);
- spice_marshaller_add_ref(m, (uint8_t*)&channel->send_data.u.socket_token,
- sizeof(channel->send_data.u.socket_token));
+ red_channel_client_init_send_data(rcc, SPICE_MSG_TUNNEL_SOCKET_TOKEN, item);
+ spice_marshaller_add_ref(m, (uint8_t*)&tunnel_channel->send_data.u.socket_token,
+ sizeof(tunnel_channel->send_data.u.socket_token));
}
-static void tunnel_channel_marshall_socket_out_data(TunnelChannel *channel, SpiceMarshaller *m, PipeItem *item)
+static void tunnel_channel_marshall_socket_out_data(RedChannelClient *rcc, SpiceMarshaller *m, PipeItem *item)
{
+ TunnelChannel *tunnel_channel;
+ tunnel_channel = SPICE_CONTAINEROF(rcc->channel, TunnelChannel, base);
RedSocketOutData *sckt_out_data = SPICE_CONTAINEROF(item, RedSocketOutData, data_pipe_item);
RedSocket *sckt = SPICE_CONTAINEROF(sckt_out_data, RedSocket, out_data);
ReadyTunneledChunk *chunk;
@@ -2701,11 +2726,11 @@ static void tunnel_channel_marshall_socket_out_data(TunnelChannel *channel, Spic
ASSERT(!sckt->out_data.push_tail);
ASSERT(sckt->out_data.ready_chunks_queue.head->size <= MAX_SOCKET_DATA_SIZE);
- channel->send_data.u.socket_data.connection_id = sckt->connection_id;
+ tunnel_channel->send_data.u.socket_data.connection_id = sckt->connection_id;
- red_channel_init_send_data(&channel->base, SPICE_MSG_TUNNEL_SOCKET_DATA, item);
- spice_marshaller_add_ref(m, (uint8_t*)&channel->send_data.u.socket_data,
- sizeof(channel->send_data.u.socket_data));
+ red_channel_client_init_send_data(rcc, SPICE_MSG_TUNNEL_SOCKET_DATA, item);
+ spice_marshaller_add_ref(m, (uint8_t*)&tunnel_channel->send_data.u.socket_data,
+ sizeof(tunnel_channel->send_data.u.socket_data));
pushed_bufs_num++;
// the first chunk is in a valid size
@@ -2790,52 +2815,51 @@ static void tunnel_worker_release_socket_out_data(TunnelWorker *worker, PipeItem
}
}
-static void tunnel_channel_send_item(RedChannel *channel, PipeItem *item)
+static void tunnel_channel_send_item(RedChannelClient *rcc, PipeItem *item)
{
- TunnelChannel *tunnel_channel = (TunnelChannel *)channel;
- SpiceMarshaller *m = red_channel_get_marshaller(channel);
+ SpiceMarshaller *m = red_channel_client_get_marshaller(rcc);
switch (item->type) {
case PIPE_ITEM_TYPE_TUNNEL_INIT:
- tunnel_channel_marshall_init(tunnel_channel, m, item);
+ tunnel_channel_marshall_init(rcc, m, item);
break;
case PIPE_ITEM_TYPE_SERVICE_IP_MAP:
- tunnel_channel_marshall_service_ip_map(tunnel_channel, m, item);
+ tunnel_channel_marshall_service_ip_map(rcc, m, item);
break;
case PIPE_ITEM_TYPE_SOCKET_OPEN:
- tunnel_channel_marshall_socket_open(tunnel_channel, m, item);
+ tunnel_channel_marshall_socket_open(rcc, m, item);
break;
case PIPE_ITEM_TYPE_SOCKET_DATA:
- tunnel_channel_marshall_socket_out_data(tunnel_channel, m, item);
+ tunnel_channel_marshall_socket_out_data(rcc, m, item);
break;
case PIPE_ITEM_TYPE_SOCKET_FIN:
- tunnel_channel_marshall_socket_fin(tunnel_channel, m, item);
+ tunnel_channel_marshall_socket_fin(rcc, m, item);
break;
case PIPE_ITEM_TYPE_SOCKET_CLOSE:
- tunnel_channel_marshall_socket_close(tunnel_channel, m, item);
+ tunnel_channel_marshall_socket_close(rcc, m, item);
break;
case PIPE_ITEM_TYPE_SOCKET_CLOSED_ACK:
- tunnel_channel_marshall_socket_closed_ack(tunnel_channel, m, item);
+ tunnel_channel_marshall_socket_closed_ack(rcc, m, item);
break;
case PIPE_ITEM_TYPE_SOCKET_TOKEN:
- tunnel_channel_marshall_socket_token(tunnel_channel, m, item);
+ tunnel_channel_marshall_socket_token(rcc, m, item);
break;
case PIPE_ITEM_TYPE_MIGRATE:
- tunnel_channel_marshall_migrate(tunnel_channel, m, item);
+ tunnel_channel_marshall_migrate(rcc, m, item);
break;
case PIPE_ITEM_TYPE_MIGRATE_DATA:
- tunnel_channel_marshall_migrate_data(tunnel_channel, m, item);
+ tunnel_channel_marshall_migrate_data(rcc, m, item);
break;
default:
red_error("invalid pipe item type");
}
- red_channel_begin_send_message(channel);
+ red_channel_client_begin_send_message(rcc);
}
/* param item_pushed: distinguishes between a pipe item that was pushed for sending, and
a pipe item that is still in the pipe and is released due to disconnection.
see red_pipe_item_clear */
-static void tunnel_channel_release_pipe_item(RedChannel *channel, PipeItem *item, int item_pushed)
+static void tunnel_channel_release_pipe_item(RedChannelClient *rcc, PipeItem *item, int item_pushed)
{
if (!item) { // e.g. when acking closed socket
return;
@@ -2852,7 +2876,7 @@ static void tunnel_channel_release_pipe_item(RedChannel *channel, PipeItem *item
break;
case PIPE_ITEM_TYPE_SOCKET_DATA:
if (item_pushed) {
- tunnel_worker_release_socket_out_data(((TunnelChannel *)channel)->worker, item);
+ tunnel_worker_release_socket_out_data(((TunnelChannel *)rcc->channel)->worker, item);
}
break;
case PIPE_ITEM_TYPE_MIGRATE:
@@ -3321,11 +3345,11 @@ static void arm_timer(SlirpUsrNetworkInterface *usr_interface, UserTimer *timer,
* channel interface and other related procedures
************************************************/
-static int tunnel_channel_config_socket(RedChannel *channel)
+static int tunnel_channel_config_socket(RedChannelClient *rcc)
{
int flags;
int delay_val;
- RedsStream *stream = red_channel_get_stream(channel);
+ RedsStream *stream = red_channel_client_get_stream(rcc);
if ((flags = fcntl(stream->socket, F_GETFL)) == -1) {
red_printf("accept failed, %s", strerror(errno)); // can't we just use red_error?
@@ -3386,6 +3410,12 @@ static void tunnel_channel_disconnect(RedChannel *channel)
worker->channel = NULL;
}
+// TODO - not MC friendly, remove
+static void tunnel_channel_disconnect_client(RedChannelClient *rcc)
+{
+ tunnel_channel_disconnect(rcc->channel);
+}
+
/* interface for reds */
static void on_new_tunnel_channel(TunnelChannel *channel)
@@ -3400,7 +3430,7 @@ static void on_new_tunnel_channel(TunnelChannel *channel)
}
}
-static void tunnel_channel_hold_pipe_item(RedChannel *channel, PipeItem *item)
+static void tunnel_channel_hold_pipe_item(RedChannelClient *rcc, PipeItem *item)
{
}
@@ -3415,10 +3445,10 @@ static void handle_tunnel_channel_link(Channel *channel, RedsStream *stream, int
}
tunnel_channel =
- (TunnelChannel *)red_channel_create(sizeof(*tunnel_channel), stream, worker->core_interface,
+ (TunnelChannel *)red_channel_create(sizeof(*tunnel_channel), worker->core_interface,
migration, TRUE,
tunnel_channel_config_socket,
- tunnel_channel_disconnect,
+ tunnel_channel_disconnect_client,
tunnel_channel_handle_message,
tunnel_channel_alloc_msg_rcv_buf,
tunnel_channel_release_msg_rcv_buf,
@@ -3432,7 +3462,7 @@ static void handle_tunnel_channel_link(Channel *channel, RedsStream *stream, int
if (!tunnel_channel) {
return;
}
-
+ red_channel_client_create(sizeof(RedChannelClient), &tunnel_channel->base, stream);
tunnel_channel->worker = worker;
tunnel_channel->worker->channel = tunnel_channel;
diff --git a/server/red_worker.c b/server/red_worker.c
index c0d03f39..bbb01553 100644
--- a/server/red_worker.c
+++ b/server/red_worker.c
@@ -922,7 +922,7 @@ static void red_display_release_stream(DisplayChannel *display, StreamAgent *age
static inline void red_detach_stream(RedWorker *worker, Stream *stream);
static void red_stop_stream(RedWorker *worker, Stream *stream);
static inline void red_stream_maintenance(RedWorker *worker, Drawable *candidate, Drawable *sect);
-static inline void display_begin_send_message(DisplayChannel *channel, SpiceMarshaller *base_marshaller);
+static inline void display_begin_send_message(RedChannelClient *rcc, SpiceMarshaller *base_marshaller);
static void red_release_pixmap_cache(DisplayChannel *channel);
static void red_release_glz(DisplayChannel *channel);
static void red_freeze_glz(DisplayChannel *channel);
@@ -1265,16 +1265,16 @@ static void release_upgrade_item(RedWorker* worker, UpgradeItem *item)
}
}
-static uint8_t *common_alloc_recv_buf(RedChannel *channel, SpiceDataHeader *msg_header)
+static uint8_t *common_alloc_recv_buf(RedChannelClient *rcc, SpiceDataHeader *msg_header)
{
- CommonChannel *common = SPICE_CONTAINEROF(channel, CommonChannel, base);
+ CommonChannel *common = SPICE_CONTAINEROF(rcc->channel, CommonChannel, base);
return common->recv_buf;
}
-static void common_release_recv_buf(RedChannel *channel, SpiceDataHeader *msg_header, uint8_t* msg)
+static void common_release_recv_buf(RedChannelClient *rcc,
+ SpiceDataHeader *msg_header, uint8_t* msg)
{
- return;
}
#define CLIENT_PIXMAPS_CACHE
@@ -1690,7 +1690,7 @@ static void red_clear_surface_drawables_from_pipe(RedWorker *worker, int surface
item = (PipeItem *)ring_prev(ring, (RingItem *)item);
ring_remove(&tmp_item->link);
worker->display_channel->common.base.release_item(
- &worker->display_channel->common.base, tmp_item, FALSE);
+ worker->display_channel->common.base.rcc, tmp_item, FALSE);
worker->display_channel->common.base.pipe_size--;
if (!item) {
@@ -5701,16 +5701,18 @@ static inline int red_compress_image(DisplayChannel *display_channel,
}
}
-static inline void red_display_add_image_to_pixmap_cache(DisplayChannel *display_channel,
+static inline void red_display_add_image_to_pixmap_cache(RedChannelClient *rcc,
SpiceImage *image, SpiceImage *io_image,
int is_lossy)
{
+ DisplayChannel *display_channel = SPICE_CONTAINEROF(rcc->channel, DisplayChannel, common.base);
+
if ((image->descriptor.flags & SPICE_IMAGE_FLAGS_CACHE_ME)) {
ASSERT(image->descriptor.width * image->descriptor.height > 0);
if (!(io_image->descriptor.flags & SPICE_IMAGE_FLAGS_CACHE_REPLACE_ME)) {
if (pixmap_cache_add(display_channel->pixmap_cache, image->descriptor.id,
image->descriptor.width * image->descriptor.height, is_lossy,
- display_channel)) {
+ rcc)) {
io_image->descriptor.flags |= SPICE_IMAGE_FLAGS_CACHE_ME;
stat_inc_counter(display_channel->add_to_cache_counter, 1);
}
@@ -5733,9 +5735,10 @@ typedef enum {
/* if the number of times fill_bits can be called per one qxl_drawable increases -
MAX_LZ_DRAWABLE_INSTANCES must be increased as well */
-static FillBitsType fill_bits(DisplayChannel *display_channel, SpiceMarshaller *m,
+static FillBitsType fill_bits(RedChannelClient *rcc, SpiceMarshaller *m,
SpiceImage *simage, Drawable *drawable, int can_lossy)
{
+ DisplayChannel *display_channel = SPICE_CONTAINEROF(rcc->channel, DisplayChannel, common.base);
RedWorker *worker = display_channel->common.worker;
SpiceImage image;
compress_send_data_t comp_send_data = {0};
@@ -5751,7 +5754,7 @@ static FillBitsType fill_bits(DisplayChannel *display_channel, SpiceMarshaller *
if ((simage->descriptor.flags & SPICE_IMAGE_FLAGS_CACHE_ME)) {
int lossy_cache_item;
if (pixmap_cache_hit(display_channel->pixmap_cache, image.descriptor.id,
- &lossy_cache_item, display_channel)) {
+ &lossy_cache_item, rcc)) {
if (can_lossy || !lossy_cache_item) {
if (!display_channel->enable_jpeg || lossy_cache_item) {
image.descriptor.type = SPICE_IMAGE_TYPE_FROM_CACHE;
@@ -5808,7 +5811,7 @@ static FillBitsType fill_bits(DisplayChannel *display_channel, SpiceMarshaller *
drawable, can_lossy, &comp_send_data)) {
SpicePalette *palette;
- red_display_add_image_to_pixmap_cache(display_channel, simage, &image, FALSE);
+ red_display_add_image_to_pixmap_cache(rcc, simage, &image, FALSE);
*bitmap = simage->u.bitmap;
bitmap->flags = bitmap->flags & SPICE_BITMAP_FLAGS_TOP_DOWN;
@@ -5826,7 +5829,7 @@ static FillBitsType fill_bits(DisplayChannel *display_channel, SpiceMarshaller *
spice_marshaller_add_ref_chunks(m, bitmap->data);
return FILL_BITS_TYPE_BITMAP;
} else {
- red_display_add_image_to_pixmap_cache(display_channel, simage, &image,
+ red_display_add_image_to_pixmap_cache(rcc, simage, &image,
comp_send_data.is_lossy);
spice_marshall_Image(m, &image,
@@ -5847,7 +5850,7 @@ static FillBitsType fill_bits(DisplayChannel *display_channel, SpiceMarshaller *
break;
}
case SPICE_IMAGE_TYPE_QUIC:
- red_display_add_image_to_pixmap_cache(display_channel, simage, &image, FALSE);
+ red_display_add_image_to_pixmap_cache(rcc, simage, &image, FALSE);
image.u.quic = simage->u.quic;
spice_marshall_Image(m, &image,
&bitmap_palette_out, &lzplt_palette_out);
@@ -5860,23 +5863,25 @@ static FillBitsType fill_bits(DisplayChannel *display_channel, SpiceMarshaller *
}
}
-static void fill_mask(DisplayChannel *display_channel, SpiceMarshaller *m,
+static void fill_mask(RedChannelClient *rcc, SpiceMarshaller *m,
SpiceImage *mask_bitmap, Drawable *drawable)
{
+ DisplayChannel *display_channel = SPICE_CONTAINEROF(rcc->channel, DisplayChannel, common.base);
+
if (mask_bitmap && m) {
if (display_channel->common.worker->image_compression != SPICE_IMAGE_COMPRESS_OFF) {
spice_image_compression_t save_img_comp =
display_channel->common.worker->image_compression;
display_channel->common.worker->image_compression = SPICE_IMAGE_COMPRESS_OFF;
- fill_bits(display_channel, m, mask_bitmap, drawable, FALSE);
+ fill_bits(rcc, m, mask_bitmap, drawable, FALSE);
display_channel->common.worker->image_compression = save_img_comp;
} else {
- fill_bits(display_channel, m, mask_bitmap, drawable, FALSE);
+ fill_bits(rcc, m, mask_bitmap, drawable, FALSE);
}
}
}
-static void fill_attr(DisplayChannel *display_channel, SpiceMarshaller *m, SpiceLineAttr *attr, uint32_t group_id)
+static void fill_attr(SpiceMarshaller *m, SpiceLineAttr *attr, uint32_t group_id)
{
int i;
@@ -5966,9 +5971,11 @@ static int is_surface_area_lossy(DisplayChannel *display_channel, uint32_t surfa
to the client, returns false. "area" is for surfaces. If area = NULL,
all the surface is considered. out_lossy_data will hold info about the bitmap, and its lossy
area in case it is lossy and part of a surface. */
-static int is_bitmap_lossy(DisplayChannel *display_channel, SpiceImage *image, SpiceRect *area,
+static int is_bitmap_lossy(RedChannelClient *rcc, SpiceImage *image, SpiceRect *area,
Drawable *drawable, BitmapData *out_data)
{
+ DisplayChannel *display_channel = SPICE_CONTAINEROF(rcc->channel, DisplayChannel, common.base);
+
if (image == NULL) {
// self bitmap
out_data->type = BITMAP_DATA_TYPE_BITMAP;
@@ -5980,7 +5987,7 @@ static int is_bitmap_lossy(DisplayChannel *display_channel, SpiceImage *image, S
out_data->id = image->descriptor.id;
if (pixmap_cache_hit(display_channel->pixmap_cache, image->descriptor.id,
- &is_hit_lossy, display_channel)) {
+ &is_hit_lossy, rcc)) {
out_data->type = BITMAP_DATA_TYPE_CACHE;
if (is_hit_lossy) {
return TRUE;
@@ -6010,11 +6017,11 @@ static int is_bitmap_lossy(DisplayChannel *display_channel, SpiceImage *image, S
}
}
-static int is_brush_lossy(DisplayChannel *display_channel, SpiceBrush *brush,
+static int is_brush_lossy(RedChannelClient *rcc, SpiceBrush *brush,
Drawable *drawable, BitmapData *out_data)
{
if (brush->type == SPICE_BRUSH_TYPE_PATTERN) {
- return is_bitmap_lossy(display_channel, brush->u.pattern.pat, NULL,
+ return is_bitmap_lossy(rcc, brush->u.pattern.pat, NULL,
drawable, out_data);
} else {
out_data->type = BITMAP_DATA_TYPE_INVALID;
@@ -6289,17 +6296,16 @@ static void red_add_lossless_drawable_dependencies(RedWorker *worker,
}
static void red_marshall_qxl_draw_fill(RedWorker *worker,
- DisplayChannel *display_channel,
+ RedChannelClient *rcc,
SpiceMarshaller *base_marshaller,
Drawable *item)
{
- RedChannel *channel = &display_channel->common.base;
RedDrawable *drawable = item->red_drawable;
SpiceMarshaller *brush_pat_out;
SpiceMarshaller *mask_bitmap_out;
SpiceFill fill;
- red_channel_init_send_data(channel, SPICE_MSG_DISPLAY_DRAW_FILL, &item->pipe_item);
+ red_channel_client_init_send_data(rcc, SPICE_MSG_DISPLAY_DRAW_FILL, &item->pipe_item);
fill_base(base_marshaller, item);
fill = drawable->u.fill;
spice_marshall_Fill(base_marshaller,
@@ -6308,18 +6314,19 @@ static void red_marshall_qxl_draw_fill(RedWorker *worker,
&mask_bitmap_out);
if (brush_pat_out) {
- fill_bits(display_channel, brush_pat_out, fill.brush.u.pattern.pat, item, FALSE);
+ fill_bits(rcc, brush_pat_out, fill.brush.u.pattern.pat, item, FALSE);
}
- fill_mask(display_channel, mask_bitmap_out, fill.mask.bitmap, item);
+ fill_mask(rcc, mask_bitmap_out, fill.mask.bitmap, item);
}
-static void red_lossy_send_qxl_draw_fill(RedWorker *worker,
- DisplayChannel *display_channel,
+static void red_lossy_marshall_qxl_draw_fill(RedWorker *worker,
+ RedChannelClient *rcc,
SpiceMarshaller *m,
Drawable *item)
{
+ DisplayChannel *display_channel = SPICE_CONTAINEROF(rcc->channel, DisplayChannel, common.base);
RedDrawable *drawable = item->red_drawable;
int dest_allowed_lossy = FALSE;
@@ -6335,7 +6342,7 @@ static void red_lossy_send_qxl_draw_fill(RedWorker *worker,
(rop & SPICE_ROPD_OP_AND) ||
(rop & SPICE_ROPD_OP_XOR));
- brush_is_lossy = is_brush_lossy(display_channel, &drawable->u.fill.brush, item,
+ brush_is_lossy = is_brush_lossy(rcc, &drawable->u.fill.brush, item,
&brush_bitmap_data);
if (!dest_allowed_lossy) {
dest_is_lossy = is_surface_area_lossy(display_channel, item->surface_id, &drawable->bbox,
@@ -6346,8 +6353,7 @@ static void red_lossy_send_qxl_draw_fill(RedWorker *worker,
!(brush_is_lossy && (brush_bitmap_data.type == BITMAP_DATA_TYPE_SURFACE))) {
int has_mask = !!drawable->u.fill.mask.bitmap;
- red_marshall_qxl_draw_fill(worker, display_channel, m, item);
-
+ red_marshall_qxl_draw_fill(worker, rcc, m, item);
// either the brush operation is opaque, or the dest is not lossy
surface_lossy_region_update(worker, display_channel, item, has_mask, FALSE);
} else {
@@ -6373,11 +6379,10 @@ static void red_lossy_send_qxl_draw_fill(RedWorker *worker,
}
static FillBitsType red_marshall_qxl_draw_opaque(RedWorker *worker,
- DisplayChannel *display_channel,
+ RedChannelClient *rcc,
SpiceMarshaller *base_marshaller,
Drawable *item, int src_allowed_lossy)
{
- RedChannel *channel = &display_channel->common.base;
RedDrawable *drawable = item->red_drawable;
SpiceMarshaller *brush_pat_out;
SpiceMarshaller *src_bitmap_out;
@@ -6385,7 +6390,7 @@ static FillBitsType red_marshall_qxl_draw_opaque(RedWorker *worker,
SpiceOpaque opaque;
FillBitsType src_send_type;
- red_channel_init_send_data(channel, SPICE_MSG_DISPLAY_DRAW_OPAQUE, &item->pipe_item);
+ red_channel_client_init_send_data(rcc, SPICE_MSG_DISPLAY_DRAW_OPAQUE, &item->pipe_item);
fill_base(base_marshaller, item);
opaque = drawable->u.opaque;
spice_marshall_Opaque(base_marshaller,
@@ -6394,22 +6399,23 @@ static FillBitsType red_marshall_qxl_draw_opaque(RedWorker *worker,
&brush_pat_out,
&mask_bitmap_out);
- src_send_type = fill_bits(display_channel, src_bitmap_out, opaque.src_bitmap, item,
+ src_send_type = fill_bits(rcc, src_bitmap_out, opaque.src_bitmap, item,
src_allowed_lossy);
if (brush_pat_out) {
- fill_bits(display_channel, brush_pat_out, opaque.brush.u.pattern.pat, item, FALSE);
+ fill_bits(rcc, brush_pat_out, opaque.brush.u.pattern.pat, item, FALSE);
}
- fill_mask(display_channel, mask_bitmap_out, opaque.mask.bitmap, item);
+ fill_mask(rcc, mask_bitmap_out, opaque.mask.bitmap, item);
return src_send_type;
}
-static void red_lossy_send_qxl_draw_opaque(RedWorker *worker,
- DisplayChannel *display_channel,
+static void red_lossy_marshall_qxl_draw_opaque(RedWorker *worker,
+ RedChannelClient *rcc,
SpiceMarshaller *m,
Drawable *item)
{
+ DisplayChannel *display_channel = SPICE_CONTAINEROF(rcc->channel, DisplayChannel, common.base);
RedDrawable *drawable = item->red_drawable;
int src_allowed_lossy;
@@ -6424,11 +6430,11 @@ static void red_lossy_send_qxl_draw_opaque(RedWorker *worker,
(rop & SPICE_ROPD_OP_AND) ||
(rop & SPICE_ROPD_OP_XOR));
- brush_is_lossy = is_brush_lossy(display_channel, &drawable->u.opaque.brush, item,
+ brush_is_lossy = is_brush_lossy(rcc, &drawable->u.opaque.brush, item,
&brush_bitmap_data);
if (!src_allowed_lossy) {
- src_is_lossy = is_bitmap_lossy(display_channel, drawable->u.opaque.src_bitmap,
+ src_is_lossy = is_bitmap_lossy(rcc, drawable->u.opaque.src_bitmap,
&drawable->u.opaque.src_area,
item,
&src_bitmap_data);
@@ -6439,8 +6445,7 @@ static void red_lossy_send_qxl_draw_opaque(RedWorker *worker,
FillBitsType src_send_type;
int has_mask = !!drawable->u.opaque.mask.bitmap;
- src_send_type = red_marshall_qxl_draw_opaque(worker, display_channel, m, item, src_allowed_lossy);
-
+ src_send_type = red_marshall_qxl_draw_opaque(worker, rcc, m, item, src_allowed_lossy);
if (src_send_type == FILL_BITS_TYPE_COMPRESS_LOSSY) {
src_is_lossy = TRUE;
} else if (src_send_type == FILL_BITS_TYPE_COMPRESS_LOSSLESS) {
@@ -6471,18 +6476,17 @@ static void red_lossy_send_qxl_draw_opaque(RedWorker *worker,
}
static FillBitsType red_marshall_qxl_draw_copy(RedWorker *worker,
- DisplayChannel *display_channel,
+ RedChannelClient *rcc,
SpiceMarshaller *base_marshaller,
Drawable *item, int src_allowed_lossy)
{
- RedChannel *channel = &display_channel->common.base;
RedDrawable *drawable = item->red_drawable;
SpiceMarshaller *src_bitmap_out;
SpiceMarshaller *mask_bitmap_out;
SpiceCopy copy;
FillBitsType src_send_type;
- red_channel_init_send_data(channel, SPICE_MSG_DISPLAY_DRAW_COPY, &item->pipe_item);
+ red_channel_client_init_send_data(rcc, SPICE_MSG_DISPLAY_DRAW_COPY, &item->pipe_item);
fill_base(base_marshaller, item);
copy = drawable->u.copy;
spice_marshall_Copy(base_marshaller,
@@ -6490,27 +6494,28 @@ static FillBitsType red_marshall_qxl_draw_copy(RedWorker *worker,
&src_bitmap_out,
&mask_bitmap_out);
- src_send_type = fill_bits(display_channel, src_bitmap_out, copy.src_bitmap, item, src_allowed_lossy);
- fill_mask(display_channel, mask_bitmap_out, copy.mask.bitmap, item);
+ src_send_type = fill_bits(rcc, src_bitmap_out, copy.src_bitmap, item, src_allowed_lossy);
+ fill_mask(rcc, mask_bitmap_out, copy.mask.bitmap, item);
return src_send_type;
}
-static void red_lossy_send_qxl_draw_copy(RedWorker *worker,
- DisplayChannel *display_channel,
+static void red_lossy_marshall_qxl_draw_copy(RedWorker *worker,
+ RedChannelClient *rcc,
SpiceMarshaller *base_marshaller,
Drawable *item)
{
+ DisplayChannel *display_channel = SPICE_CONTAINEROF(rcc->channel, DisplayChannel, common.base);
RedDrawable *drawable = item->red_drawable;
int has_mask = !!drawable->u.copy.mask.bitmap;
int src_is_lossy;
BitmapData src_bitmap_data;
FillBitsType src_send_type;
- src_is_lossy = is_bitmap_lossy(display_channel, drawable->u.copy.src_bitmap,
+ src_is_lossy = is_bitmap_lossy(rcc, drawable->u.copy.src_bitmap,
&drawable->u.copy.src_area, item, &src_bitmap_data);
- src_send_type = red_marshall_qxl_draw_copy(worker, display_channel, base_marshaller, item, TRUE);
+ src_send_type = red_marshall_qxl_draw_copy(worker, rcc, base_marshaller, item, TRUE);
if (src_send_type == FILL_BITS_TYPE_COMPRESS_LOSSY) {
src_is_lossy = TRUE;
@@ -6523,39 +6528,38 @@ static void red_lossy_send_qxl_draw_copy(RedWorker *worker,
}
static void red_marshall_qxl_draw_transparent(RedWorker *worker,
- DisplayChannel *display_channel,
+ RedChannelClient *rcc,
SpiceMarshaller *base_marshaller,
Drawable *item)
{
- RedChannel *channel = &display_channel->common.base;
RedDrawable *drawable = item->red_drawable;
SpiceMarshaller *src_bitmap_out;
SpiceTransparent transparent;
- red_channel_init_send_data(channel, SPICE_MSG_DISPLAY_DRAW_TRANSPARENT, &item->pipe_item);
+ red_channel_client_init_send_data(rcc, SPICE_MSG_DISPLAY_DRAW_TRANSPARENT, &item->pipe_item);
fill_base(base_marshaller, item);
transparent = drawable->u.transparent;
spice_marshall_Transparent(base_marshaller,
&transparent,
&src_bitmap_out);
- fill_bits(display_channel, src_bitmap_out, transparent.src_bitmap, item, FALSE);
+ fill_bits(rcc, src_bitmap_out, transparent.src_bitmap, item, FALSE);
}
-static void red_lossy_send_qxl_draw_transparent(RedWorker *worker,
- DisplayChannel *display_channel,
+static void red_lossy_marshall_qxl_draw_transparent(RedWorker *worker,
+ RedChannelClient *rcc,
SpiceMarshaller *base_marshaller,
Drawable *item)
{
+ DisplayChannel *display_channel = SPICE_CONTAINEROF(rcc->channel, DisplayChannel, common.base);
RedDrawable *drawable = item->red_drawable;
int src_is_lossy;
BitmapData src_bitmap_data;
- src_is_lossy = is_bitmap_lossy(display_channel, drawable->u.transparent.src_bitmap,
+ src_is_lossy = is_bitmap_lossy(rcc, drawable->u.transparent.src_bitmap,
&drawable->u.transparent.src_area, item, &src_bitmap_data);
if (!src_is_lossy || (src_bitmap_data.type != BITMAP_DATA_TYPE_SURFACE)) {
- red_marshall_qxl_draw_transparent(worker, display_channel, base_marshaller, item);
-
+ red_marshall_qxl_draw_transparent(worker, rcc, base_marshaller, item);
// don't update surface lossy region since transperent areas might be lossy
} else {
int resend_surface_ids[1];
@@ -6570,42 +6574,42 @@ static void red_lossy_send_qxl_draw_transparent(RedWorker *worker,
}
static FillBitsType red_marshall_qxl_draw_alpha_blend(RedWorker *worker,
- DisplayChannel *display_channel,
+ RedChannelClient *rcc,
SpiceMarshaller *base_marshaller,
Drawable *item,
int src_allowed_lossy)
{
- RedChannel *channel = &display_channel->common.base;
RedDrawable *drawable = item->red_drawable;
SpiceMarshaller *src_bitmap_out;
SpiceAlphaBlend alpha_blend;
FillBitsType src_send_type;
- red_channel_init_send_data(channel, SPICE_MSG_DISPLAY_DRAW_ALPHA_BLEND, &item->pipe_item);
+ red_channel_client_init_send_data(rcc, SPICE_MSG_DISPLAY_DRAW_ALPHA_BLEND, &item->pipe_item);
fill_base(base_marshaller, item);
alpha_blend = drawable->u.alpha_blend;
spice_marshall_AlphaBlend(base_marshaller,
&alpha_blend,
&src_bitmap_out);
- src_send_type = fill_bits(display_channel, src_bitmap_out, alpha_blend.src_bitmap, item, src_allowed_lossy);
+ src_send_type = fill_bits(rcc, src_bitmap_out, alpha_blend.src_bitmap, item, src_allowed_lossy);
return src_send_type;
}
-static void red_lossy_send_qxl_draw_alpha_blend(RedWorker *worker,
- DisplayChannel *display_channel,
+static void red_lossy_marshall_qxl_draw_alpha_blend(RedWorker *worker,
+ RedChannelClient *rcc,
SpiceMarshaller *base_marshaller,
Drawable *item)
{
+ DisplayChannel *display_channel = SPICE_CONTAINEROF(rcc->channel, DisplayChannel, common.base);
RedDrawable *drawable = item->red_drawable;
int src_is_lossy;
BitmapData src_bitmap_data;
FillBitsType src_send_type;
- src_is_lossy = is_bitmap_lossy(display_channel, drawable->u.alpha_blend.src_bitmap,
+ src_is_lossy = is_bitmap_lossy(rcc, drawable->u.alpha_blend.src_bitmap,
&drawable->u.alpha_blend.src_area, item, &src_bitmap_data);
- src_send_type = red_marshall_qxl_draw_alpha_blend(worker, display_channel, base_marshaller, item, TRUE);
+ src_send_type = red_marshall_qxl_draw_alpha_blend(worker, rcc, base_marshaller, item, TRUE);
if (src_send_type == FILL_BITS_TYPE_COMPRESS_LOSSY) {
src_is_lossy = TRUE;
@@ -6619,26 +6623,26 @@ static void red_lossy_send_qxl_draw_alpha_blend(RedWorker *worker,
}
static void red_marshall_qxl_copy_bits(RedWorker *worker,
- DisplayChannel *display_channel,
+ RedChannelClient *rcc,
SpiceMarshaller *base_marshaller,
Drawable *item)
{
- RedChannel *channel = &display_channel->common.base;
RedDrawable *drawable = item->red_drawable;
SpicePoint copy_bits;
- red_channel_init_send_data(channel, SPICE_MSG_DISPLAY_COPY_BITS, &item->pipe_item);
+ red_channel_client_init_send_data(rcc, SPICE_MSG_DISPLAY_COPY_BITS, &item->pipe_item);
fill_base(base_marshaller, item);
copy_bits = drawable->u.copy_bits.src_pos;
spice_marshall_Point(base_marshaller,
&copy_bits);
}
-static void red_lossy_send_qxl_copy_bits(RedWorker *worker,
- DisplayChannel *display_channel,
+static void red_lossy_marshall_qxl_copy_bits(RedWorker *worker,
+ RedChannelClient *rcc,
SpiceMarshaller *base_marshaller,
Drawable *item)
{
+ DisplayChannel *display_channel = SPICE_CONTAINEROF(rcc->channel, DisplayChannel, common.base);
RedDrawable *drawable = item->red_drawable;
SpiceRect src_rect;
int horz_offset;
@@ -6646,7 +6650,7 @@ static void red_lossy_send_qxl_copy_bits(RedWorker *worker,
int src_is_lossy;
SpiceRect src_lossy_area;
- red_marshall_qxl_copy_bits(worker, display_channel, base_marshaller, item);
+ red_marshall_qxl_copy_bits(worker, rcc, base_marshaller, item);
horz_offset = drawable->u.copy_bits.src_pos.x - drawable->bbox.left;
vert_offset = drawable->u.copy_bits.src_pos.y - drawable->bbox.top;
@@ -6664,17 +6668,16 @@ static void red_lossy_send_qxl_copy_bits(RedWorker *worker,
}
static void red_marshall_qxl_draw_blend(RedWorker *worker,
- DisplayChannel *display_channel,
+ RedChannelClient *rcc,
SpiceMarshaller *base_marshaller,
Drawable *item)
{
- RedChannel *channel = &display_channel->common.base;
RedDrawable *drawable = item->red_drawable;
SpiceMarshaller *src_bitmap_out;
SpiceMarshaller *mask_bitmap_out;
SpiceBlend blend;
- red_channel_init_send_data(channel, SPICE_MSG_DISPLAY_DRAW_BLEND, &item->pipe_item);
+ red_channel_client_init_send_data(rcc, SPICE_MSG_DISPLAY_DRAW_BLEND, &item->pipe_item);
fill_base(base_marshaller, item);
blend = drawable->u.blend;
spice_marshall_Blend(base_marshaller,
@@ -6682,30 +6685,31 @@ static void red_marshall_qxl_draw_blend(RedWorker *worker,
&src_bitmap_out,
&mask_bitmap_out);
- fill_bits(display_channel, src_bitmap_out, blend.src_bitmap, item, FALSE);
+ fill_bits(rcc, src_bitmap_out, blend.src_bitmap, item, FALSE);
- fill_mask(display_channel, mask_bitmap_out, blend.mask.bitmap, item);
+ fill_mask(rcc, mask_bitmap_out, blend.mask.bitmap, item);
}
-static void red_lossy_send_qxl_draw_blend(RedWorker *worker,
- DisplayChannel *display_channel,
+static void red_lossy_marshall_qxl_draw_blend(RedWorker *worker,
+ RedChannelClient *rcc,
SpiceMarshaller *base_marshaller,
Drawable *item)
{
+ DisplayChannel *display_channel = SPICE_CONTAINEROF(rcc->channel, DisplayChannel, common.base);
RedDrawable *drawable = item->red_drawable;
int src_is_lossy;
BitmapData src_bitmap_data;
int dest_is_lossy;
SpiceRect dest_lossy_area;
- src_is_lossy = is_bitmap_lossy(display_channel, drawable->u.blend.src_bitmap,
+ src_is_lossy = is_bitmap_lossy(rcc, drawable->u.blend.src_bitmap,
&drawable->u.blend.src_area, item, &src_bitmap_data);
dest_is_lossy = is_surface_area_lossy(display_channel, drawable->surface_id,
&drawable->bbox, &dest_lossy_area);
if (!dest_is_lossy &&
(!src_is_lossy || (src_bitmap_data.type != BITMAP_DATA_TYPE_SURFACE))) {
- red_marshall_qxl_draw_blend(worker, display_channel, base_marshaller, item);
+ red_marshall_qxl_draw_blend(worker, rcc, base_marshaller, item);
} else {
int resend_surface_ids[2];
SpiceRect *resend_areas[2];
@@ -6729,16 +6733,15 @@ static void red_lossy_send_qxl_draw_blend(RedWorker *worker,
}
static void red_marshall_qxl_draw_blackness(RedWorker *worker,
- DisplayChannel *display_channel,
+ RedChannelClient *rcc,
SpiceMarshaller *base_marshaller,
Drawable *item)
{
- RedChannel *channel = &display_channel->common.base;
RedDrawable *drawable = item->red_drawable;
SpiceMarshaller *mask_bitmap_out;
SpiceBlackness blackness;
- red_channel_init_send_data(channel, SPICE_MSG_DISPLAY_DRAW_BLACKNESS, &item->pipe_item);
+ red_channel_client_init_send_data(rcc, SPICE_MSG_DISPLAY_DRAW_BLACKNESS, &item->pipe_item);
fill_base(base_marshaller, item);
blackness = drawable->u.blackness;
@@ -6746,33 +6749,33 @@ static void red_marshall_qxl_draw_blackness(RedWorker *worker,
&blackness,
&mask_bitmap_out);
- fill_mask(display_channel, mask_bitmap_out, blackness.mask.bitmap, item);
+ fill_mask(rcc, mask_bitmap_out, blackness.mask.bitmap, item);
}
-static void red_lossy_send_qxl_draw_blackness(RedWorker *worker,
- DisplayChannel *display_channel,
+static void red_lossy_marshall_qxl_draw_blackness(RedWorker *worker,
+ RedChannelClient *rcc,
SpiceMarshaller *base_marshaller,
Drawable *item)
{
+ DisplayChannel *display_channel = SPICE_CONTAINEROF(rcc->channel, DisplayChannel, common.base);
RedDrawable *drawable = item->red_drawable;
int has_mask = !!drawable->u.blackness.mask.bitmap;
- red_marshall_qxl_draw_blackness(worker, display_channel, base_marshaller, item);
+ red_marshall_qxl_draw_blackness(worker, rcc, base_marshaller, item);
surface_lossy_region_update(worker, display_channel, item, has_mask, FALSE);
}
static void red_marshall_qxl_draw_whiteness(RedWorker *worker,
- DisplayChannel *display_channel,
+ RedChannelClient *rcc,
SpiceMarshaller *base_marshaller,
Drawable *item)
{
- RedChannel *channel = &display_channel->common.base;
RedDrawable *drawable = item->red_drawable;
SpiceMarshaller *mask_bitmap_out;
SpiceWhiteness whiteness;
- red_channel_init_send_data(channel, SPICE_MSG_DISPLAY_DRAW_WHITENESS, &item->pipe_item);
+ red_channel_client_init_send_data(rcc, SPICE_MSG_DISPLAY_DRAW_WHITENESS, &item->pipe_item);
fill_base(base_marshaller, item);
whiteness = drawable->u.whiteness;
@@ -6780,33 +6783,33 @@ static void red_marshall_qxl_draw_whiteness(RedWorker *worker,
&whiteness,
&mask_bitmap_out);
- fill_mask(display_channel, mask_bitmap_out, whiteness.mask.bitmap, item);
+ fill_mask(rcc, mask_bitmap_out, whiteness.mask.bitmap, item);
}
-static void red_lossy_send_qxl_draw_whiteness(RedWorker *worker,
- DisplayChannel *display_channel,
+static void red_lossy_marshall_qxl_draw_whiteness(RedWorker *worker,
+ RedChannelClient *rcc,
SpiceMarshaller *base_marshaller,
Drawable *item)
{
+ DisplayChannel *display_channel = SPICE_CONTAINEROF(rcc->channel, DisplayChannel, common.base);
RedDrawable *drawable = item->red_drawable;
int has_mask = !!drawable->u.whiteness.mask.bitmap;
- red_marshall_qxl_draw_whiteness(worker, display_channel, base_marshaller, item);
+ red_marshall_qxl_draw_whiteness(worker, rcc, base_marshaller, item);
surface_lossy_region_update(worker, display_channel, item, has_mask, FALSE);
}
static void red_marshall_qxl_draw_inverse(RedWorker *worker,
- DisplayChannel *display_channel,
+ RedChannelClient *rcc,
SpiceMarshaller *base_marshaller,
Drawable *item)
{
RedDrawable *drawable = item->red_drawable;
SpiceMarshaller *mask_bitmap_out;
- RedChannel *channel = &display_channel->common.base;
SpiceInvers inverse;
- red_channel_init_send_data(channel, SPICE_MSG_DISPLAY_DRAW_INVERS, NULL);
+ red_channel_client_init_send_data(rcc, SPICE_MSG_DISPLAY_DRAW_INVERS, NULL);
fill_base(base_marshaller, item);
inverse = drawable->u.invers;
@@ -6814,30 +6817,29 @@ static void red_marshall_qxl_draw_inverse(RedWorker *worker,
&inverse,
&mask_bitmap_out);
- fill_mask(display_channel, mask_bitmap_out, inverse.mask.bitmap, item);
+ fill_mask(rcc, mask_bitmap_out, inverse.mask.bitmap, item);
}
-static void red_lossy_send_qxl_draw_inverse(RedWorker *worker,
- DisplayChannel *display_channel,
+static void red_lossy_marshall_qxl_draw_inverse(RedWorker *worker,
+ RedChannelClient *rcc,
SpiceMarshaller *base_marshaller,
Drawable *item)
{
- red_marshall_qxl_draw_inverse(worker, display_channel, base_marshaller, item);
+ red_marshall_qxl_draw_inverse(worker, rcc, base_marshaller, item);
}
static void red_marshall_qxl_draw_rop3(RedWorker *worker,
- DisplayChannel *display_channel,
+ RedChannelClient *rcc,
SpiceMarshaller *base_marshaller,
Drawable *item)
{
RedDrawable *drawable = item->red_drawable;
- RedChannel *channel = &display_channel->common.base;
SpiceRop3 rop3;
SpiceMarshaller *src_bitmap_out;
SpiceMarshaller *brush_pat_out;
SpiceMarshaller *mask_bitmap_out;
- red_channel_init_send_data(channel, SPICE_MSG_DISPLAY_DRAW_ROP3, &item->pipe_item);
+ red_channel_client_init_send_data(rcc, SPICE_MSG_DISPLAY_DRAW_ROP3, &item->pipe_item);
fill_base(base_marshaller, item);
rop3 = drawable->u.rop3;
spice_marshall_Rop3(base_marshaller,
@@ -6846,19 +6848,20 @@ static void red_marshall_qxl_draw_rop3(RedWorker *worker,
&brush_pat_out,
&mask_bitmap_out);
- fill_bits(display_channel, src_bitmap_out, rop3.src_bitmap, item, FALSE);
+ fill_bits(rcc, src_bitmap_out, rop3.src_bitmap, item, FALSE);
if (brush_pat_out) {
- fill_bits(display_channel, brush_pat_out, rop3.brush.u.pattern.pat, item, FALSE);
+ fill_bits(rcc, brush_pat_out, rop3.brush.u.pattern.pat, item, FALSE);
}
- fill_mask(display_channel, mask_bitmap_out, rop3.mask.bitmap, item);
+ fill_mask(rcc, mask_bitmap_out, rop3.mask.bitmap, item);
}
-static void red_lossy_send_qxl_draw_rop3(RedWorker *worker,
- DisplayChannel *display_channel,
+static void red_lossy_marshall_qxl_draw_rop3(RedWorker *worker,
+ RedChannelClient *rcc,
SpiceMarshaller *base_marshaller,
Drawable *item)
{
+ DisplayChannel *display_channel = SPICE_CONTAINEROF(rcc->channel, DisplayChannel, common.base);
RedDrawable *drawable = item->red_drawable;
int src_is_lossy;
BitmapData src_bitmap_data;
@@ -6867,9 +6870,9 @@ static void red_lossy_send_qxl_draw_rop3(RedWorker *worker,
int dest_is_lossy;
SpiceRect dest_lossy_area;
- src_is_lossy = is_bitmap_lossy(display_channel, drawable->u.rop3.src_bitmap,
+ src_is_lossy = is_bitmap_lossy(rcc, drawable->u.rop3.src_bitmap,
&drawable->u.rop3.src_area, item, &src_bitmap_data);
- brush_is_lossy = is_brush_lossy(display_channel, &drawable->u.rop3.brush, item,
+ brush_is_lossy = is_brush_lossy(rcc, &drawable->u.rop3.brush, item,
&brush_bitmap_data);
dest_is_lossy = is_surface_area_lossy(display_channel, drawable->surface_id,
&drawable->bbox, &dest_lossy_area);
@@ -6878,8 +6881,7 @@ static void red_lossy_send_qxl_draw_rop3(RedWorker *worker,
(!brush_is_lossy || (brush_bitmap_data.type != BITMAP_DATA_TYPE_SURFACE)) &&
!dest_is_lossy) {
int has_mask = !!drawable->u.rop3.mask.bitmap;
- red_marshall_qxl_draw_rop3(worker, display_channel, base_marshaller, item);
-
+ red_marshall_qxl_draw_rop3(worker, rcc, base_marshaller, item);
surface_lossy_region_update(worker, display_channel, item, has_mask, FALSE);
} else {
int resend_surface_ids[3];
@@ -6910,17 +6912,16 @@ static void red_lossy_send_qxl_draw_rop3(RedWorker *worker,
}
static void red_marshall_qxl_draw_stroke(RedWorker *worker,
- DisplayChannel *display_channel,
+ RedChannelClient *rcc,
SpiceMarshaller *base_marshaller,
Drawable *item)
{
RedDrawable *drawable = item->red_drawable;
- RedChannel *channel = &display_channel->common.base;
SpiceStroke stroke;
SpiceMarshaller *brush_pat_out;
SpiceMarshaller *style_out;
- red_channel_init_send_data(channel, SPICE_MSG_DISPLAY_DRAW_STROKE, &item->pipe_item);
+ red_channel_client_init_send_data(rcc, SPICE_MSG_DISPLAY_DRAW_STROKE, &item->pipe_item);
fill_base(base_marshaller, item);
stroke = drawable->u.stroke;
spice_marshall_Stroke(base_marshaller,
@@ -6928,17 +6929,18 @@ static void red_marshall_qxl_draw_stroke(RedWorker *worker,
&style_out,
&brush_pat_out);
- fill_attr(display_channel, style_out, &stroke.attr, item->group_id);
+ fill_attr(style_out, &stroke.attr, item->group_id);
if (brush_pat_out) {
- fill_bits(display_channel, brush_pat_out, stroke.brush.u.pattern.pat, item, FALSE);
+ fill_bits(rcc, brush_pat_out, stroke.brush.u.pattern.pat, item, FALSE);
}
}
-static void red_lossy_send_qxl_draw_stroke(RedWorker *worker,
- DisplayChannel *display_channel,
+static void red_lossy_marshall_qxl_draw_stroke(RedWorker *worker,
+ RedChannelClient *rcc,
SpiceMarshaller *base_marshaller,
Drawable *item)
{
+ DisplayChannel *display_channel = SPICE_CONTAINEROF(rcc->channel, DisplayChannel, common.base);
RedDrawable *drawable = item->red_drawable;
int brush_is_lossy;
BitmapData brush_bitmap_data;
@@ -6946,7 +6948,7 @@ static void red_lossy_send_qxl_draw_stroke(RedWorker *worker,
SpiceRect dest_lossy_area;
int rop;
- brush_is_lossy = is_brush_lossy(display_channel, &drawable->u.stroke.brush, item,
+ brush_is_lossy = is_brush_lossy(rcc, &drawable->u.stroke.brush, item,
&brush_bitmap_data);
// back_mode is not used at the client. Ignoring.
@@ -6964,7 +6966,7 @@ static void red_lossy_send_qxl_draw_stroke(RedWorker *worker,
if (!dest_is_lossy &&
(!brush_is_lossy || (brush_bitmap_data.type != BITMAP_DATA_TYPE_SURFACE)))
{
- red_marshall_qxl_draw_stroke(worker, display_channel, base_marshaller, item);
+ red_marshall_qxl_draw_stroke(worker, rcc, base_marshaller, item);
} else {
int resend_surface_ids[2];
SpiceRect *resend_areas[2];
@@ -6986,21 +6988,19 @@ static void red_lossy_send_qxl_draw_stroke(RedWorker *worker,
red_add_lossless_drawable_dependencies(worker, display_channel, item,
resend_surface_ids, resend_areas, num_resend);
}
-
}
static void red_marshall_qxl_draw_text(RedWorker *worker,
- DisplayChannel *display_channel,
+ RedChannelClient *rcc,
SpiceMarshaller *base_marshaller,
Drawable *item)
{
RedDrawable *drawable = item->red_drawable;
- RedChannel *channel = &display_channel->common.base;
SpiceText text;
SpiceMarshaller *brush_pat_out;
SpiceMarshaller *back_brush_pat_out;
- red_channel_init_send_data(channel, SPICE_MSG_DISPLAY_DRAW_TEXT, &item->pipe_item);
+ red_channel_client_init_send_data(rcc, SPICE_MSG_DISPLAY_DRAW_TEXT, &item->pipe_item);
fill_base(base_marshaller, item);
text = drawable->u.text;
spice_marshall_Text(base_marshaller,
@@ -7009,18 +7009,19 @@ static void red_marshall_qxl_draw_text(RedWorker *worker,
&back_brush_pat_out);
if (brush_pat_out) {
- fill_bits(display_channel, brush_pat_out, text.fore_brush.u.pattern.pat, item, FALSE);
+ fill_bits(rcc, brush_pat_out, text.fore_brush.u.pattern.pat, item, FALSE);
}
if (back_brush_pat_out) {
- fill_bits(display_channel, back_brush_pat_out, text.back_brush.u.pattern.pat, item, FALSE);
+ fill_bits(rcc, back_brush_pat_out, text.back_brush.u.pattern.pat, item, FALSE);
}
}
-static void red_lossy_send_qxl_draw_text(RedWorker *worker,
- DisplayChannel *display_channel,
+static void red_lossy_marshall_qxl_draw_text(RedWorker *worker,
+ RedChannelClient *rcc,
SpiceMarshaller *base_marshaller,
Drawable *item)
{
+ DisplayChannel *display_channel = SPICE_CONTAINEROF(rcc->channel, DisplayChannel, common.base);
RedDrawable *drawable = item->red_drawable;
int fg_is_lossy;
BitmapData fg_bitmap_data;
@@ -7030,9 +7031,9 @@ static void red_lossy_send_qxl_draw_text(RedWorker *worker,
SpiceRect dest_lossy_area;
int rop = 0;
- fg_is_lossy = is_brush_lossy(display_channel, &drawable->u.text.fore_brush, item,
+ fg_is_lossy = is_brush_lossy(rcc, &drawable->u.text.fore_brush, item,
&fg_bitmap_data);
- bg_is_lossy = is_brush_lossy(display_channel, &drawable->u.text.back_brush, item,
+ bg_is_lossy = is_brush_lossy(rcc, &drawable->u.text.back_brush, item,
&bg_bitmap_data);
// assuming that if the brush type is solid, the destination can
@@ -7054,7 +7055,7 @@ static void red_lossy_send_qxl_draw_text(RedWorker *worker,
if (!dest_is_lossy &&
(!fg_is_lossy || (fg_bitmap_data.type != BITMAP_DATA_TYPE_SURFACE)) &&
(!bg_is_lossy || (bg_bitmap_data.type != BITMAP_DATA_TYPE_SURFACE))) {
- red_marshall_qxl_draw_text(worker, display_channel, base_marshaller, item);
+ red_marshall_qxl_draw_text(worker, rcc, base_marshaller, item);
} else {
int resend_surface_ids[3];
SpiceRect *resend_areas[3];
@@ -7082,98 +7083,98 @@ static void red_lossy_send_qxl_draw_text(RedWorker *worker,
}
}
-static void red_lossy_marshall_qxl_drawable(RedWorker *worker, DisplayChannel *display_channel,
+static void red_lossy_marshall_qxl_drawable(RedWorker *worker, RedChannelClient *rcc,
SpiceMarshaller *base_marshaller, Drawable *item)
{
switch (item->red_drawable->type) {
case QXL_DRAW_FILL:
- red_lossy_send_qxl_draw_fill(worker, display_channel, base_marshaller, item);
+ red_lossy_marshall_qxl_draw_fill(worker, rcc, base_marshaller, item);
break;
case QXL_DRAW_OPAQUE:
- red_lossy_send_qxl_draw_opaque(worker, display_channel, base_marshaller, item);
+ red_lossy_marshall_qxl_draw_opaque(worker, rcc, base_marshaller, item);
break;
case QXL_DRAW_COPY:
- red_lossy_send_qxl_draw_copy(worker, display_channel, base_marshaller, item);
+ red_lossy_marshall_qxl_draw_copy(worker, rcc, base_marshaller, item);
break;
case QXL_DRAW_TRANSPARENT:
- red_lossy_send_qxl_draw_transparent(worker, display_channel, base_marshaller, item);
+ red_lossy_marshall_qxl_draw_transparent(worker, rcc, base_marshaller, item);
break;
case QXL_DRAW_ALPHA_BLEND:
- red_lossy_send_qxl_draw_alpha_blend(worker, display_channel, base_marshaller, item);
+ red_lossy_marshall_qxl_draw_alpha_blend(worker, rcc, base_marshaller, item);
break;
case QXL_COPY_BITS:
- red_lossy_send_qxl_copy_bits(worker, display_channel, base_marshaller, item);
+ red_lossy_marshall_qxl_copy_bits(worker, rcc, base_marshaller, item);
break;
case QXL_DRAW_BLEND:
- red_lossy_send_qxl_draw_blend(worker, display_channel, base_marshaller, item);
+ red_lossy_marshall_qxl_draw_blend(worker, rcc, base_marshaller, item);
break;
case QXL_DRAW_BLACKNESS:
- red_lossy_send_qxl_draw_blackness(worker, display_channel, base_marshaller, item);
+ red_lossy_marshall_qxl_draw_blackness(worker, rcc, base_marshaller, item);
break;
case QXL_DRAW_WHITENESS:
- red_lossy_send_qxl_draw_whiteness(worker, display_channel, base_marshaller, item);
+ red_lossy_marshall_qxl_draw_whiteness(worker, rcc, base_marshaller, item);
break;
case QXL_DRAW_INVERS:
- red_lossy_send_qxl_draw_inverse(worker, display_channel, base_marshaller, item);
+ red_lossy_marshall_qxl_draw_inverse(worker, rcc, base_marshaller, item);
break;
case QXL_DRAW_ROP3:
- red_lossy_send_qxl_draw_rop3(worker, display_channel, base_marshaller, item);
+ red_lossy_marshall_qxl_draw_rop3(worker, rcc, base_marshaller, item);
break;
case QXL_DRAW_STROKE:
- red_lossy_send_qxl_draw_stroke(worker, display_channel, base_marshaller, item);
+ red_lossy_marshall_qxl_draw_stroke(worker, rcc, base_marshaller, item);
break;
case QXL_DRAW_TEXT:
- red_lossy_send_qxl_draw_text(worker, display_channel, base_marshaller, item);
+ red_lossy_marshall_qxl_draw_text(worker, rcc, base_marshaller, item);
break;
default:
red_error("invalid type");
}
}
-static inline void red_marshall_qxl_drawable(RedWorker *worker, DisplayChannel *display_channel,
- SpiceMarshaller *m, Drawable *item)
+static inline void red_marshall_qxl_drawable(RedWorker *worker, RedChannelClient *rcc,
+ SpiceMarshaller *m, Drawable *item)
{
RedDrawable *drawable = item->red_drawable;
switch (drawable->type) {
case QXL_DRAW_FILL:
- red_marshall_qxl_draw_fill(worker, display_channel, m, item);
+ red_marshall_qxl_draw_fill(worker, rcc, m, item);
break;
case QXL_DRAW_OPAQUE:
- red_marshall_qxl_draw_opaque(worker, display_channel, m, item, FALSE);
+ red_marshall_qxl_draw_opaque(worker, rcc, m, item, FALSE);
break;
case QXL_DRAW_COPY:
- red_marshall_qxl_draw_copy(worker, display_channel, m, item, FALSE);
+ red_marshall_qxl_draw_copy(worker, rcc, m, item, FALSE);
break;
case QXL_DRAW_TRANSPARENT:
- red_marshall_qxl_draw_transparent(worker, display_channel, m, item);
+ red_marshall_qxl_draw_transparent(worker, rcc, m, item);
break;
case QXL_DRAW_ALPHA_BLEND:
- red_marshall_qxl_draw_alpha_blend(worker, display_channel, m, item, FALSE);
+ red_marshall_qxl_draw_alpha_blend(worker, rcc, m, item, FALSE);
break;
case QXL_COPY_BITS:
- red_marshall_qxl_copy_bits(worker, display_channel, m, item);
+ red_marshall_qxl_copy_bits(worker, rcc, m, item);
break;
case QXL_DRAW_BLEND:
- red_marshall_qxl_draw_blend(worker, display_channel, m, item);
+ red_marshall_qxl_draw_blend(worker, rcc, m, item);
break;
case QXL_DRAW_BLACKNESS:
- red_marshall_qxl_draw_blackness(worker, display_channel, m, item);
+ red_marshall_qxl_draw_blackness(worker, rcc, m, item);
break;
case QXL_DRAW_WHITENESS:
- red_marshall_qxl_draw_whiteness(worker, display_channel, m, item);
+ red_marshall_qxl_draw_whiteness(worker, rcc, m, item);
break;
case QXL_DRAW_INVERS:
- red_marshall_qxl_draw_inverse(worker, display_channel, m, item);
+ red_marshall_qxl_draw_inverse(worker, rcc, m, item);
break;
case QXL_DRAW_ROP3:
- red_marshall_qxl_draw_rop3(worker, display_channel, m, item);
+ red_marshall_qxl_draw_rop3(worker, rcc, m, item);
break;
case QXL_DRAW_STROKE:
- red_marshall_qxl_draw_stroke(worker, display_channel, m, item);
+ red_marshall_qxl_draw_stroke(worker, rcc, m, item);
break;
case QXL_DRAW_TEXT:
- red_marshall_qxl_draw_text(worker, display_channel, m, item);
+ red_marshall_qxl_draw_text(worker, rcc, m, item);
break;
default:
red_error("invalid type");
@@ -7204,10 +7205,11 @@ static void display_channel_push_release(DisplayChannel *channel, uint8_t type,
free_list->res->resources[free_list->res->count++].id = id;
}
-static inline void display_begin_send_message(DisplayChannel *channel, SpiceMarshaller *base_marshaller)
+static inline void display_begin_send_message(RedChannelClient *rcc, SpiceMarshaller *base_marshaller)
{
- FreeList *free_list = &channel->send_data.free_list;
- SpiceDataHeader *header = red_channel_get_header(&channel->common.base);
+ DisplayChannel *display_channel = SPICE_CONTAINEROF(rcc->channel, DisplayChannel, common.base);
+ FreeList *free_list = &display_channel->send_data.free_list;
+ SpiceDataHeader *header = red_channel_client_get_header(rcc);
if (free_list->res->count) {
int sub_list_len = 1;
@@ -7225,7 +7227,7 @@ static inline void display_begin_send_message(DisplayChannel *channel, SpiceMars
spice_marshall_msg_display_inval_list(inval_m, free_list->res);
for (i = 0; i < MAX_CACHE_CLIENTS; i++) {
- if (i != channel->common.id && free_list->sync[i] != 0) {
+ if (i != display_channel->common.id && free_list->sync[i] != 0) {
free_list->wait.header.wait_list[sync_count].channel_type = SPICE_CHANNEL_DISPLAY;
free_list->wait.header.wait_list[sync_count].channel_id = i;
free_list->wait.header.wait_list[sync_count++].message_serial = free_list->sync[i];
@@ -7252,7 +7254,7 @@ static inline void display_begin_send_message(DisplayChannel *channel, SpiceMars
spice_marshaller_add_uint32(sub_list_m, spice_marshaller_get_offset(inval_m));
header->sub_list = spice_marshaller_get_offset(sub_list_m);
}
- red_channel_begin_send_message((RedChannel *)channel);
+ red_channel_client_begin_send_message(rcc);
}
static inline RedChannel *red_ref_channel(RedChannel *channel)
@@ -7341,19 +7343,18 @@ static int encode_frame (RedWorker *worker, const SpiceRect *src,
return TRUE;
}
-static inline int red_send_stream_data(DisplayChannel *display_channel,
+static inline int red_marshall_stream_data(RedChannelClient *rcc,
SpiceMarshaller *base_marshaller, Drawable *drawable)
{
+ DisplayChannel *display_channel = SPICE_CONTAINEROF(rcc->channel, DisplayChannel, common.base);
Stream *stream = drawable->stream;
SpiceImage *image;
- RedChannel *channel;
RedWorker* worker;
int n;
ASSERT(stream);
ASSERT(drawable->red_drawable->type == QXL_DRAW_COPY);
- channel = &display_channel->common.base;
worker = display_channel->common.worker;
image = drawable->red_drawable->u.copy.src_bitmap;
@@ -7382,7 +7383,7 @@ static inline int red_send_stream_data(DisplayChannel *display_channel,
n = mjpeg_encoder_end_frame(stream->mjpeg_encoder);
display_channel->send_data.stream_outbuf_size = outbuf_size;
- red_channel_init_send_data(channel, SPICE_MSG_DISPLAY_STREAM_DATA, NULL);
+ red_channel_client_init_send_data(rcc, SPICE_MSG_DISPLAY_STREAM_DATA, NULL);
SpiceMsgDisplayStreamData stream_data;
@@ -7396,72 +7397,63 @@ static inline int red_send_stream_data(DisplayChannel *display_channel,
return TRUE;
}
-static inline void marshall_qxl_drawable(DisplayChannel *display_channel,
+static inline void marshall_qxl_drawable(RedChannelClient *rcc,
SpiceMarshaller *m, Drawable *item)
{
- ASSERT(display_channel);
+ DisplayChannel *display_channel = SPICE_CONTAINEROF(rcc->channel, DisplayChannel, common.base);
- if (item->stream && red_send_stream_data(display_channel, m, item)) {
+ ASSERT(display_channel && rcc);
+ if (item->stream && red_marshall_stream_data(rcc, m, item)) {
return;
}
if (!display_channel->enable_jpeg)
- red_marshall_qxl_drawable(display_channel->common.worker, display_channel, m, item);
+ red_marshall_qxl_drawable(display_channel->common.worker, rcc, m, item);
else
- red_lossy_marshall_qxl_drawable(display_channel->common.worker, display_channel, m, item);
+ red_lossy_marshall_qxl_drawable(display_channel->common.worker, rcc, m, item);
}
-static inline void red_marshall_verb(RedChannel *channel, uint16_t verb)
+static inline void red_marshall_verb(RedChannelClient *rcc, uint16_t verb)
{
- ASSERT(channel);
- red_channel_init_send_data(channel, verb, NULL);
+ ASSERT(rcc);
+ red_channel_client_init_send_data(rcc, verb, NULL);
}
-static inline void display_marshall_verb(DisplayChannel *channel, uint16_t verb)
-{
- ASSERT(channel);
- red_channel_init_send_data(&channel->common.base, verb, NULL);
-}
-
-static inline void red_marshall_inval(RedChannel *channel,
+static inline void red_marshall_inval(RedChannelClient *rcc,
SpiceMarshaller *base_marshaller, CacheItem *cach_item)
{
SpiceMsgDisplayInvalOne inval_one;
- red_channel_init_send_data(channel, cach_item->inval_type, NULL);
+ red_channel_client_init_send_data(rcc, cach_item->inval_type, NULL);
inval_one.id = *(uint64_t *)&cach_item->id;
spice_marshall_msg_cursor_inval_one(base_marshaller, &inval_one);
}
-static void red_display_marshall_inval(DisplayChannel *display_channel,
- SpiceMarshaller *base_marshaller, CacheItem *cach_item)
-{
- red_marshall_inval((RedChannel *)display_channel, base_marshaller, cach_item);
-}
-
-static void display_channel_marshall_migrate(DisplayChannel *display_channel, SpiceMarshaller *base_marshaller)
+static void display_channel_marshall_migrate(RedChannelClient *rcc,
+ SpiceMarshaller *base_marshaller)
{
+ DisplayChannel *display_channel = SPICE_CONTAINEROF(rcc->channel, DisplayChannel, common.base);
SpiceMsgMigrate migrate;
- red_channel_init_send_data(&display_channel->common.base, SPICE_MSG_MIGRATE, NULL);
+ red_channel_client_init_send_data(rcc, SPICE_MSG_MIGRATE, NULL);
migrate.flags = SPICE_MIGRATE_NEED_FLUSH | SPICE_MIGRATE_NEED_DATA_TRANSFER;
spice_marshall_msg_migrate(base_marshaller, &migrate);
display_channel->expect_migrate_mark = TRUE;
}
-static void display_channel_marshall_migrate_data(DisplayChannel *display_channel,
- SpiceMarshaller *base_marshaller)
+static void display_channel_marshall_migrate_data(RedChannelClient *rcc, SpiceMarshaller *base_marshaller)
{
+ DisplayChannel *display_channel = SPICE_CONTAINEROF(rcc->channel, DisplayChannel, common.base);
DisplayChannelMigrateData display_data;
- red_channel_init_send_data(&display_channel->common.base, SPICE_MSG_MIGRATE_DATA, NULL);
+ red_channel_client_init_send_data(rcc, SPICE_MSG_MIGRATE_DATA, NULL);
ASSERT(display_channel->pixmap_cache);
display_data.magic = DISPLAY_MIGRATE_DATA_MAGIC;
ASSERT(MAX_CACHE_CLIENTS == 4); //MIGRATE_DATA_VERSION dependent
display_data.version = DISPLAY_MIGRATE_DATA_VERSION;
- display_data.message_serial = red_channel_get_message_serial((RedChannel *)display_channel);
+ display_data.message_serial = red_channel_client_get_message_serial(rcc);
display_data.pixmap_cache_freezer = pixmap_cache_freeze(display_channel->pixmap_cache);
display_data.pixmap_cache_id = display_channel->pixmap_cache->id;
@@ -7480,13 +7472,13 @@ static void display_channel_marshall_migrate_data(DisplayChannel *display_channe
(uint8_t *)&display_data, sizeof(display_data));
}
-static void display_channel_marshall_pixmap_sync(DisplayChannel *display_channel,
- SpiceMarshaller *base_marshaller)
+static void display_channel_marshall_pixmap_sync(RedChannelClient *rcc, SpiceMarshaller *base_marshaller)
{
+ DisplayChannel *display_channel = SPICE_CONTAINEROF(rcc->channel, DisplayChannel, common.base);
SpiceMsgWaitForChannels wait;
PixmapCache *pixmap_cache;
- red_channel_init_send_data(&display_channel->common.base, SPICE_MSG_WAIT_FOR_CHANNELS, NULL);
+ red_channel_client_init_send_data(rcc, SPICE_MSG_WAIT_FOR_CHANNELS, NULL);
pixmap_cache = display_channel->pixmap_cache;
pthread_mutex_lock(&pixmap_cache->lock);
@@ -7503,21 +7495,21 @@ static void display_channel_marshall_pixmap_sync(DisplayChannel *display_channel
spice_marshall_msg_wait_for_channels(base_marshaller, &wait);
}
-static void display_channel_marshall_reset_cache(DisplayChannel *display_channel,
- SpiceMarshaller *base_marshaller)
+static void display_channel_marshall_reset_cache(RedChannelClient *rcc, SpiceMarshaller *base_marshaller)
{
+ DisplayChannel *display_channel = SPICE_CONTAINEROF(rcc->channel, DisplayChannel, common.base);
SpiceMsgWaitForChannels wait;
- red_channel_init_send_data(&display_channel->common.base, SPICE_MSG_DISPLAY_INVAL_ALL_PIXMAPS, NULL);
- pixmap_cache_reset(display_channel->pixmap_cache, display_channel, &wait);
+ red_channel_client_init_send_data(rcc, SPICE_MSG_DISPLAY_INVAL_ALL_PIXMAPS, NULL);
+ pixmap_cache_reset(display_channel->pixmap_cache, rcc, &wait);
spice_marshall_msg_display_inval_all_pixmaps(base_marshaller,
&wait);
}
-static void red_marshall_image(DisplayChannel *display_channel, SpiceMarshaller *m, ImageItem *item)
+static void red_marshall_image( RedChannelClient *rcc, SpiceMarshaller *m, ImageItem *item)
{
- RedChannel *channel;
+ DisplayChannel *display_channel = SPICE_CONTAINEROF(rcc->channel, DisplayChannel, common.base);
SpiceImage red_image;
RedWorker *worker;
SpiceBitmap bitmap;
@@ -7531,8 +7523,7 @@ static void red_marshall_image(DisplayChannel *display_channel, SpiceMarshaller
SpiceMarshaller *src_bitmap_out, *mask_bitmap_out;
SpiceMarshaller *bitmap_palette_out, *lzplt_palette_out;
- ASSERT(display_channel && item);
- channel = &display_channel->common.base;
+ ASSERT(rcc && display_channel && item);
worker = display_channel->common.worker;
QXL_SET_IMAGE_ID(&red_image, QXL_IMAGE_GROUP_RED, ++worker->bits_unique);
@@ -7555,7 +7546,7 @@ static void red_marshall_image(DisplayChannel *display_channel, SpiceMarshaller
chunks = spice_chunks_new_linear(item->data, bitmap.stride * bitmap.y);
bitmap.data = chunks;
- red_channel_init_send_data(channel, SPICE_MSG_DISPLAY_DRAW_COPY, &item->link);
+ red_channel_client_init_send_data(rcc, SPICE_MSG_DISPLAY_DRAW_COPY, &item->link);
copy.base.surface_id = item->surface_id;
copy.base.box.left = item->pos.x;
@@ -7649,17 +7640,15 @@ static void red_marshall_image(DisplayChannel *display_channel, SpiceMarshaller
spice_chunks_destroy(chunks);
}
-static void red_display_marshall_upgrade(DisplayChannel *display_channel, SpiceMarshaller *m, UpgradeItem *item)
+static void red_display_marshall_upgrade(RedChannelClient *rcc, SpiceMarshaller *m, UpgradeItem *item)
{
- RedChannel *channel;
RedDrawable *red_drawable;
SpiceMsgDisplayDrawCopy copy;
SpiceMarshaller *src_bitmap_out, *mask_bitmap_out;
- ASSERT(display_channel && item && item->drawable);
- channel = &display_channel->common.base;
+ ASSERT(rcc && rcc->channel && item && item->drawable);
- red_channel_init_send_data(channel, SPICE_MSG_DISPLAY_DRAW_COPY, &item->base);
+ red_channel_client_init_send_data(rcc, SPICE_MSG_DISPLAY_DRAW_COPY, &item->base);
red_drawable = item->drawable->red_drawable;
ASSERT(red_drawable->type == QXL_DRAW_COPY);
@@ -7675,18 +7664,18 @@ static void red_display_marshall_upgrade(DisplayChannel *display_channel, SpiceM
spice_marshall_msg_display_draw_copy(m, &copy,
&src_bitmap_out, &mask_bitmap_out);
- fill_bits(display_channel, src_bitmap_out, copy.data.src_bitmap, item->drawable, FALSE);
+ fill_bits(rcc, src_bitmap_out, copy.data.src_bitmap, item->drawable, FALSE);
}
-static void red_display_marshall_stream_start(DisplayChannel *display_channel,
+static void red_display_marshall_stream_start(RedChannelClient *rcc,
SpiceMarshaller *base_marshaller, StreamAgent *agent)
{
- RedChannel *channel = &display_channel->common.base;
+ DisplayChannel *display_channel = SPICE_CONTAINEROF(rcc->channel, DisplayChannel, common.base);
Stream *stream = agent->stream;
agent->last_send_time = 0;
ASSERT(stream);
- red_channel_init_send_data(channel, SPICE_MSG_DISPLAY_STREAM_CREATE,
+ red_channel_client_init_send_data(rcc, SPICE_MSG_DISPLAY_STREAM_CREATE,
stream->current ? &stream->current->pipe_item : NULL);
SpiceMsgDisplayStreamCreate stream_create;
SpiceClipRects clip_rects;
@@ -7714,18 +7703,17 @@ static void red_display_marshall_stream_start(DisplayChannel *display_channel,
spice_marshall_msg_display_stream_create(base_marshaller, &stream_create);
}
-static void red_display_marshall_stream_clip(DisplayChannel *display_channel,
+static void red_display_marshall_stream_clip(RedChannelClient *rcc,
SpiceMarshaller *base_marshaller,
StreamClipItem *item)
{
- RedChannel *channel = &display_channel->common.base;
-
+ DisplayChannel *display_channel = SPICE_CONTAINEROF(rcc->channel, DisplayChannel, common.base);
StreamAgent *agent = item->stream_agent;
Stream *stream = agent->stream;
ASSERT(stream);
- red_channel_init_send_data(channel, SPICE_MSG_DISPLAY_STREAM_CLIP, &item->base);
+ red_channel_client_init_send_data(rcc, SPICE_MSG_DISPLAY_STREAM_CLIP, &item->base);
SpiceMsgDisplayStreamClip stream_clip;
stream_clip.id = agent - display_channel->stream_agents;
@@ -7735,67 +7723,66 @@ static void red_display_marshall_stream_clip(DisplayChannel *display_channel,
spice_marshall_msg_display_stream_clip(base_marshaller, &stream_clip);
}
-static void red_display_marshall_stream_end(DisplayChannel *display_channel,
+static void red_display_marshall_stream_end(RedChannelClient *rcc,
SpiceMarshaller *base_marshaller, StreamAgent* agent)
{
- RedChannel *channel = &display_channel->common.base;
+ DisplayChannel *display_channel = SPICE_CONTAINEROF(rcc->channel, DisplayChannel, common.base);
SpiceMsgDisplayStreamDestroy destroy;
- red_channel_init_send_data(channel, SPICE_MSG_DISPLAY_STREAM_DESTROY, NULL);
+ red_channel_client_init_send_data(rcc, SPICE_MSG_DISPLAY_STREAM_DESTROY, NULL);
destroy.id = agent - display_channel->stream_agents;
spice_marshall_msg_display_stream_destroy(base_marshaller, &destroy);
}
-static void red_cursor_marshall_inval(CursorChannel *channel,
+static void red_cursor_marshall_inval(RedChannelClient *rcc,
SpiceMarshaller *m, CacheItem *cach_item)
{
- ASSERT(channel);
- red_marshall_inval((RedChannel *)channel, m, cach_item);
+ ASSERT(rcc);
+ red_marshall_inval(rcc, m, cach_item);
}
-static void red_marshall_cursor_init(CursorChannel *channel, SpiceMarshaller *base_marshaller)
+static void red_marshall_cursor_init(RedChannelClient *rcc, SpiceMarshaller *base_marshaller)
{
+ CursorChannel *cursor_channel;
RedWorker *worker;
SpiceMsgCursorInit msg;
AddBufInfo info;
- ASSERT(channel);
-
- worker = channel->common.worker;
+ ASSERT(rcc);
+ cursor_channel = SPICE_CONTAINEROF(rcc->channel, CursorChannel, common.base);
+ worker = cursor_channel->common.worker;
- red_channel_init_send_data(&channel->common.base, SPICE_MSG_CURSOR_INIT, &worker->cursor->pipe_data);
+ red_channel_client_init_send_data(rcc, SPICE_MSG_CURSOR_INIT, &worker->cursor->pipe_data);
msg.visible = worker->cursor_visible;
msg.position = worker->cursor_position;
msg.trail_length = worker->cursor_trail_length;
msg.trail_frequency = worker->cursor_trail_frequency;
- fill_cursor(channel, &msg.cursor, worker->cursor, &info);
+ fill_cursor(cursor_channel, &msg.cursor, worker->cursor, &info);
spice_marshall_msg_cursor_init(base_marshaller, &msg);
add_buf_from_info(base_marshaller, &info);
}
-static void cursor_channel_marshall_migrate(CursorChannel *cursor_channel,
- SpiceMarshaller *base_marshaller)
+static void cursor_channel_marshall_migrate(RedChannelClient *rcc, SpiceMarshaller *base_marshaller)
{
SpiceMsgMigrate migrate;
- red_channel_init_send_data(&cursor_channel->common.base, SPICE_MSG_MIGRATE, NULL);
+ red_channel_client_init_send_data(rcc, SPICE_MSG_MIGRATE, NULL);
migrate.flags = 0;
spice_marshall_msg_migrate(base_marshaller, &migrate);
}
-static void red_marshall_cursor(CursorChannel *cursor_channel,
+static void red_marshall_cursor(RedChannelClient *rcc,
SpiceMarshaller *m, CursorItem *cursor)
{
- RedChannel *channel;
+ CursorChannel *cursor_channel = SPICE_CONTAINEROF(rcc->channel, CursorChannel, common.base);
RedCursorCmd *cmd;
RedWorker *worker;
ASSERT(cursor_channel);
- channel = &cursor_channel->common.base;
worker = cursor_channel->common.worker;
cmd = cursor->red_cursor;
@@ -7803,7 +7790,7 @@ static void red_marshall_cursor(CursorChannel *cursor_channel,
case QXL_CURSOR_MOVE:
{
SpiceMsgCursorMove cursor_move;
- red_channel_init_send_data(channel, SPICE_MSG_CURSOR_MOVE, &cursor->pipe_data);
+ red_channel_client_init_send_data(rcc, SPICE_MSG_CURSOR_MOVE, &cursor->pipe_data);
cursor_move.position = cmd->u.position;
spice_marshall_msg_cursor_move(m, &cursor_move);
break;
@@ -7813,7 +7800,7 @@ static void red_marshall_cursor(CursorChannel *cursor_channel,
SpiceMsgCursorSet cursor_set;
AddBufInfo info;
- red_channel_init_send_data(channel, SPICE_MSG_CURSOR_SET, &cursor->pipe_data);
+ red_channel_client_init_send_data(rcc, SPICE_MSG_CURSOR_SET, &cursor->pipe_data);
cursor_set.position = cmd->u.set.position;
cursor_set.visible = worker->cursor_visible;
@@ -7823,13 +7810,13 @@ static void red_marshall_cursor(CursorChannel *cursor_channel,
break;
}
case QXL_CURSOR_HIDE:
- red_channel_init_send_data(channel, SPICE_MSG_CURSOR_HIDE, &cursor->pipe_data);
+ red_channel_client_init_send_data(rcc, SPICE_MSG_CURSOR_HIDE, &cursor->pipe_data);
break;
case QXL_CURSOR_TRAIL:
{
SpiceMsgCursorTrail cursor_trail;
- red_channel_init_send_data(channel, SPICE_MSG_CURSOR_TRAIL, &cursor->pipe_data);
+ red_channel_client_init_send_data(rcc, SPICE_MSG_CURSOR_TRAIL, &cursor->pipe_data);
cursor_trail.length = cmd->u.trail.length;
cursor_trail.frequency = cmd->u.trail.frequency;
spice_marshall_msg_cursor_trail(m, &cursor_trail);
@@ -7838,106 +7825,103 @@ static void red_marshall_cursor(CursorChannel *cursor_channel,
default:
red_error("bad cursor command %d", cmd->type);
}
-
red_release_cursor(worker, cursor);
}
-static void red_marshall_surface_create(DisplayChannel *display,
+static void red_marshall_surface_create(RedChannelClient *rcc,
SpiceMarshaller *base_marshaller, SpiceMsgSurfaceCreate *surface_create)
{
- RedChannel *channel;
-
- ASSERT(display);
- channel = &display->common.base;
+ DisplayChannel *display_channel = SPICE_CONTAINEROF(rcc->channel, DisplayChannel, common.base);
- region_init(&display->surface_client_lossy_region[surface_create->surface_id]);
- red_channel_init_send_data(channel, SPICE_MSG_DISPLAY_SURFACE_CREATE, NULL);
+ ASSERT(display_channel);
+ region_init(&display_channel->surface_client_lossy_region[surface_create->surface_id]);
+ red_channel_client_init_send_data(rcc, SPICE_MSG_DISPLAY_SURFACE_CREATE, NULL);
spice_marshall_msg_display_surface_create(base_marshaller, surface_create);
}
-static void red_marshall_surface_destroy(DisplayChannel *display,
+static void red_marshall_surface_destroy(RedChannelClient *rcc,
SpiceMarshaller *base_marshaller, uint32_t surface_id)
{
- RedChannel *channel;
+ DisplayChannel *display_channel = SPICE_CONTAINEROF(rcc->channel, DisplayChannel, common.base);
SpiceMsgSurfaceDestroy surface_destroy;
- ASSERT(display);
- channel = &display->common.base;
+ ASSERT(display_channel);
- region_destroy(&display->surface_client_lossy_region[surface_id]);
- red_channel_init_send_data(channel, SPICE_MSG_DISPLAY_SURFACE_DESTROY, NULL);
+ region_destroy(&display_channel->surface_client_lossy_region[surface_id]);
+ red_channel_client_init_send_data(rcc, SPICE_MSG_DISPLAY_SURFACE_DESTROY, NULL);
surface_destroy.surface_id = surface_id;
spice_marshall_msg_display_surface_destroy(base_marshaller, &surface_destroy);
}
-static void display_channel_send_item(RedChannel *base, PipeItem *pipe_item)
+static void display_channel_send_item(RedChannelClient *rcc, PipeItem *pipe_item)
{
- SpiceMarshaller *m = red_channel_get_marshaller(base);
- DisplayChannel *display_channel = (DisplayChannel *)red_ref_channel(base);
+ SpiceMarshaller *m = red_channel_client_get_marshaller(rcc);
+ DisplayChannel *display_channel = (DisplayChannel *)red_ref_channel(rcc->channel);
red_display_reset_send_data(display_channel);
switch (pipe_item->type) {
case PIPE_ITEM_TYPE_DRAW: {
Drawable *drawable = SPICE_CONTAINEROF(pipe_item, Drawable, pipe_item);
- marshall_qxl_drawable(display_channel, m, drawable);
+ marshall_qxl_drawable(rcc, m, drawable);
break;
}
case PIPE_ITEM_TYPE_INVAL_ONE:
- red_display_marshall_inval(display_channel, m, (CacheItem *)pipe_item);
+ red_marshall_inval(rcc, m, (CacheItem *)pipe_item);
break;
case PIPE_ITEM_TYPE_STREAM_CREATE: {
StreamAgent *agent = SPICE_CONTAINEROF(pipe_item, StreamAgent, create_item);
- red_display_marshall_stream_start(display_channel, m, agent);
+ red_display_marshall_stream_start(rcc, m, agent);
break;
}
case PIPE_ITEM_TYPE_STREAM_CLIP: {
- red_display_marshall_stream_clip(display_channel, m, (StreamClipItem *)pipe_item);
+ StreamClipItem* clip_item = (StreamClipItem *)pipe_item;
+ red_display_marshall_stream_clip(rcc, m, clip_item);
break;
}
case PIPE_ITEM_TYPE_STREAM_DESTROY: {
StreamAgent *agent = SPICE_CONTAINEROF(pipe_item, StreamAgent, destroy_item);
- red_display_marshall_stream_end(display_channel, m, agent);
+ red_display_marshall_stream_end(rcc, m, agent);
break;
}
case PIPE_ITEM_TYPE_UPGRADE:
- red_display_marshall_upgrade(display_channel, m, (UpgradeItem *)pipe_item);
+ red_display_marshall_upgrade(rcc, m, (UpgradeItem *)pipe_item);
break;
case PIPE_ITEM_TYPE_VERB:
- display_marshall_verb(display_channel, ((VerbItem*)pipe_item)->verb);
+ red_marshall_verb(rcc, ((VerbItem*)pipe_item)->verb);
break;
case PIPE_ITEM_TYPE_MIGRATE:
red_printf("PIPE_ITEM_TYPE_MIGRATE");
- display_channel_marshall_migrate(display_channel, m);
+ display_channel_marshall_migrate(rcc, m);
break;
case PIPE_ITEM_TYPE_MIGRATE_DATA:
- display_channel_marshall_migrate_data(display_channel, m);
+ display_channel_marshall_migrate_data(rcc, m);
break;
case PIPE_ITEM_TYPE_IMAGE:
- red_marshall_image(display_channel, m, (ImageItem *)pipe_item);
+ red_marshall_image(rcc, m, (ImageItem *)pipe_item);
break;
case PIPE_ITEM_TYPE_PIXMAP_SYNC:
- display_channel_marshall_pixmap_sync(display_channel, m);
+ display_channel_marshall_pixmap_sync(rcc, m);
break;
case PIPE_ITEM_TYPE_PIXMAP_RESET:
- display_channel_marshall_reset_cache(display_channel, m);
+ display_channel_marshall_reset_cache(rcc, m);
break;
case PIPE_ITEM_TYPE_INVAL_PALLET_CACHE:
red_reset_palette_cache(display_channel);
- red_marshall_verb((RedChannel *)display_channel, SPICE_MSG_DISPLAY_INVAL_ALL_PALETTES);
+ red_marshall_verb(rcc, SPICE_MSG_DISPLAY_INVAL_ALL_PALETTES);
break;
case PIPE_ITEM_TYPE_CREATE_SURFACE: {
SurfaceCreateItem *surface_create = SPICE_CONTAINEROF(pipe_item, SurfaceCreateItem,
pipe_item);
- red_marshall_surface_create(display_channel, m, &surface_create->surface_create);
+ red_marshall_surface_create(rcc, m, &surface_create->surface_create);
break;
}
case PIPE_ITEM_TYPE_DESTROY_SURFACE: {
SurfaceDestroyItem *surface_destroy = SPICE_CONTAINEROF(pipe_item, SurfaceDestroyItem,
pipe_item);
- red_marshall_surface_destroy(display_channel, m, surface_destroy->surface_destroy.surface_id);
+ red_marshall_surface_destroy(rcc, m, surface_destroy->surface_destroy.surface_id);
break;
}
default:
@@ -7947,47 +7931,47 @@ static void display_channel_send_item(RedChannel *base, PipeItem *pipe_item)
display_channel_release_item_before_push(display_channel, pipe_item);
// a message is pending
- if (red_channel_send_message_pending(&display_channel->common.base)) {
- display_begin_send_message(display_channel, m);
+ if (red_channel_client_send_message_pending(rcc)) {
+ display_begin_send_message(rcc, m);
}
red_unref_channel(&display_channel->common.base);
}
-static void cursor_channel_send_item(RedChannel *channel, PipeItem *pipe_item)
+static void cursor_channel_send_item(RedChannelClient *rcc, PipeItem *pipe_item)
{
- SpiceMarshaller *m = red_channel_get_marshaller(channel);
- CursorChannel *cursor_channel = SPICE_CONTAINEROF(channel, CursorChannel, common.base);
+ SpiceMarshaller *m = red_channel_client_get_marshaller(rcc);
+ CursorChannel *cursor_channel = SPICE_CONTAINEROF(rcc->channel, CursorChannel, common.base);
- red_ref_channel(channel);
+ red_ref_channel(rcc->channel);
switch (pipe_item->type) {
case PIPE_ITEM_TYPE_CURSOR:
- red_marshall_cursor(cursor_channel, m, (CursorItem *)pipe_item);
+ red_marshall_cursor(rcc, m, (CursorItem *)pipe_item);
break;
case PIPE_ITEM_TYPE_INVAL_ONE:
- red_cursor_marshall_inval(cursor_channel, m, (CacheItem *)pipe_item);
+ red_cursor_marshall_inval(rcc, m, (CacheItem *)pipe_item);
break;
case PIPE_ITEM_TYPE_VERB:
- red_marshall_verb(channel, ((VerbItem*)pipe_item)->verb);
+ red_marshall_verb(rcc, ((VerbItem*)pipe_item)->verb);
break;
case PIPE_ITEM_TYPE_MIGRATE:
red_printf("PIPE_ITEM_TYPE_MIGRATE");
- cursor_channel_marshall_migrate(cursor_channel, m);
+ cursor_channel_marshall_migrate(rcc, m);
break;
case PIPE_ITEM_TYPE_CURSOR_INIT:
red_reset_cursor_cache(cursor_channel);
- red_marshall_cursor_init(cursor_channel, m);
+ red_marshall_cursor_init(rcc, m);
break;
case PIPE_ITEM_TYPE_INVAL_CURSOR_CACHE:
red_reset_cursor_cache(cursor_channel);
- red_marshall_verb(channel, SPICE_MSG_CURSOR_INVAL_ALL);
+ red_marshall_verb(rcc, SPICE_MSG_CURSOR_INVAL_ALL);
break;
default:
red_error("invalid pipe item type");
}
cursor_channel_release_item_before_push(cursor_channel, pipe_item);
- red_channel_begin_send_message(channel);
- red_unref_channel(channel);
+ red_channel_client_begin_send_message(rcc);
+ red_unref_channel(rcc->channel);
}
static inline void red_push(RedWorker *worker)
@@ -8074,17 +8058,19 @@ static void red_disconnect_channel(RedChannel *channel)
red_unref_channel(channel);
}
-static void red_disconnect_display(RedChannel *channel)
+static void red_disconnect_display(RedChannelClient *rcc)
{
+ // TODO: MC: right now we assume single channel
DisplayChannel *display_channel;
- CommonChannel *common = SPICE_CONTAINEROF(channel, CommonChannel, base);
+ CommonChannel *common;
RedWorker *worker;
- if (!channel || !red_channel_is_connected(channel)) {
+ if (!rcc || !red_channel_is_connected(rcc->channel)) {
return;
}
+ common = SPICE_CONTAINEROF(rcc->channel, CommonChannel, base);
worker = common->worker;
- display_channel = (DisplayChannel *)channel;
+ display_channel = (DisplayChannel *)rcc->channel;
ASSERT(display_channel == worker->display_channel);
#ifdef COMPRESS_STAT
print_compress_stats(display_channel);
@@ -8102,7 +8088,18 @@ static void red_disconnect_display(RedChannel *channel)
}
free(display_channel->send_data.free_list.res);
red_display_destroy_streams(display_channel);
- red_disconnect_channel(channel);
+ red_disconnect_channel(rcc->channel);
+}
+
+void red_disconnect_all_display_TODO_remove_me(RedChannel *channel)
+{
+ // TODO: we need to record the client that actually causes the timeout. So
+ // we need to check the locations of the various pipe heads when counting,
+ // and disconnect only those/that.
+ if (!channel) {
+ return;
+ }
+ red_channel_apply_clients(channel, red_disconnect_display);
}
static void red_migrate_display(RedWorker *worker)
@@ -8345,9 +8342,11 @@ static inline void flush_display_commands(RedWorker *worker)
red_ref_channel(channel);
red_channel_receive(channel);
red_channel_send(channel);
+ // TODO: MC: the whole timeout will break since it takes lowest timeout, should
+ // do it client by client.
if (red_now() >= end_time) {
red_printf("update timeout");
- red_disconnect_display(channel);
+ red_disconnect_all_display_TODO_remove_me(channel);
} else {
sleep_count++;
usleep(DISPLAY_CLIENT_RETRY_INTERVAL);
@@ -8439,7 +8438,7 @@ static int display_channel_wait_for_init(DisplayChannel *display_channel)
}
if (red_now() > end_time) {
red_printf("timeout");
- red_disconnect_display((RedChannel *)display_channel);
+ red_disconnect_all_display_TODO_remove_me((RedChannel *)display_channel);
break;
}
usleep(DISPLAY_CLIENT_RETRY_INTERVAL);
@@ -8697,9 +8696,9 @@ static int display_channel_handle_migrate_glz_dictionary(DisplayChannel *channel
&migrate_info->glz_dict_restore_data));
}
-static int display_channel_handle_migrate_mark(RedChannel *base)
+static int display_channel_handle_migrate_mark(RedChannelClient *rcc)
{
- DisplayChannel *channel = SPICE_CONTAINEROF(base, DisplayChannel, common.base);
+ DisplayChannel *channel = SPICE_CONTAINEROF(rcc->channel, DisplayChannel, common.base);
if (!channel->expect_migrate_mark) {
red_printf("unexpected");
@@ -8711,7 +8710,7 @@ static int display_channel_handle_migrate_mark(RedChannel *base)
}
static uint64_t display_channel_handle_migrate_data_get_serial(
- RedChannel *base, uint32_t size, void *message)
+ RedChannelClient *rcc, uint32_t size, void *message)
{
DisplayChannelMigrateData *migrate_data = message;
@@ -8727,11 +8726,11 @@ static uint64_t display_channel_handle_migrate_data_get_serial(
return migrate_data->message_serial;
}
-static uint64_t display_channel_handle_migrate_data(RedChannel *base, uint32_t size, void *message)
+static uint64_t display_channel_handle_migrate_data(RedChannelClient *rcc, uint32_t size, void *message)
{
DisplayChannelMigrateData *migrate_data;
int i;
- DisplayChannel *channel = SPICE_CONTAINEROF(base, DisplayChannel, common.base);
+ DisplayChannel *channel = SPICE_CONTAINEROF(rcc->channel, DisplayChannel, common.base);
if (size < sizeof(*migrate_data)) {
red_printf("bad message size");
@@ -8778,26 +8777,26 @@ static uint64_t display_channel_handle_migrate_data(RedChannel *base, uint32_t s
return TRUE;
}
-static int display_channel_handle_message(RedChannel *channel, uint32_t size, uint16_t type, void *message)
+static int display_channel_handle_message(RedChannelClient *rcc, uint32_t size, uint16_t type, void *message)
{
switch (type) {
case SPICE_MSGC_DISPLAY_INIT:
- if (!((DisplayChannel *)channel)->expect_init) {
+ if (!((DisplayChannel *)rcc->channel)->expect_init) {
red_printf("unexpected SPICE_MSGC_DISPLAY_INIT");
return FALSE;
}
- ((DisplayChannel *)channel)->expect_init = FALSE;
- return display_channel_init((DisplayChannel *)channel, (SpiceMsgcDisplayInit *)message);
+ ((DisplayChannel *)rcc->channel)->expect_init = FALSE;
+ return display_channel_init((DisplayChannel *)rcc->channel, (SpiceMsgcDisplayInit *)message);
default:
- return red_channel_handle_message(channel, size, type, message);
+ return red_channel_client_handle_message(rcc, size, type, message);
}
}
-static int common_channel_config_socket(RedChannel *channel)
+static int common_channel_config_socket(RedChannelClient *rcc)
{
int flags;
int delay_val;
- RedsStream *stream = red_channel_get_stream(channel);
+ RedsStream *stream = red_channel_client_get_stream(rcc);
if ((flags = fcntl(stream->socket, F_GETFL)) == -1) {
red_printf("accept failed, %s", strerror(errno));
@@ -8858,7 +8857,7 @@ static RedChannel *__new_channel(RedWorker *worker, int size, uint32_t channel_i
RedChannel *channel;
CommonChannel *common;
- channel = red_channel_create_parser(size, stream, &worker_core, migrate,
+ channel = red_channel_create_parser(size, &worker_core, migrate,
TRUE /* handle_acks */,
common_channel_config_socket,
spice_get_client_channel_parser(channel_id, NULL),
@@ -8868,8 +8867,8 @@ static RedChannel *__new_channel(RedWorker *worker, int size, uint32_t channel_i
hold_item,
send_item,
release_item,
- red_channel_default_peer_on_error,
- red_channel_default_peer_on_error,
+ red_channel_client_default_peer_on_error,
+ red_channel_client_default_peer_on_error,
handle_migrate_flush_mark,
handle_migrate_data,
handle_migrate_data_get_serial);
@@ -8877,6 +8876,7 @@ static RedChannel *__new_channel(RedWorker *worker, int size, uint32_t channel_i
if (!channel) {
goto error;
}
+ red_channel_client_create(sizeof(RedChannelClient), channel, stream);
common->id = worker->id;
common->listener.refs = 1;
common->listener.action = handler;
@@ -8917,7 +8917,7 @@ static void handle_channel_events(EventListener *in_listener, uint32_t events)
}
}
-static void display_channel_hold_pipe_item(RedChannel *channel, PipeItem *item)
+static void display_channel_hold_pipe_item(RedChannelClient *rcc, PipeItem *item)
{
ASSERT(item);
switch (item->type) {
@@ -9015,14 +9015,17 @@ static void display_channel_release_item_before_push(DisplayChannel *display_cha
}
}
-static void display_channel_release_item(RedChannel *channel, PipeItem *item, int item_pushed)
+static void display_channel_release_item(RedChannelClient *rcc, PipeItem *item, int item_pushed)
{
+ RedChannel *channel = rcc->channel;
+ CommonChannel *common = SPICE_CONTAINEROF(channel, CommonChannel, base);
+
ASSERT(item);
if (item_pushed) {
- display_channel_release_item_after_push((DisplayChannel *)channel, item);
+ display_channel_release_item_after_push((DisplayChannel *)common, item);
} else {
red_printf_once("not pushed (%d)", item->type);
- display_channel_release_item_before_push((DisplayChannel *)channel, item);
+ display_channel_release_item_before_push((DisplayChannel *)common, item);
}
}
@@ -9031,7 +9034,7 @@ static void handle_new_display_channel(RedWorker *worker, RedsStream *stream, in
DisplayChannel *display_channel;
size_t stream_buf_size;
- red_disconnect_display((RedChannel *)worker->display_channel);
+ red_disconnect_all_display_TODO_remove_me((RedChannel *)worker->display_channel);
if (!(display_channel = (DisplayChannel *)__new_channel(worker, sizeof(*display_channel),
SPICE_CHANNEL_DISPLAY, stream,
@@ -9108,6 +9111,11 @@ static void handle_new_display_channel(RedWorker *worker, RedsStream *stream, in
stat_compress_init(&display_channel->jpeg_alpha_stat, jpeg_alpha_stat_name);
}
+static void red_disconnect_cursor_client(RedChannelClient *rcc)
+{
+ red_disconnect_cursor(rcc->channel);
+}
+
static void red_disconnect_cursor(RedChannel *channel)
{
CommonChannel *common;
@@ -9142,7 +9150,7 @@ static void on_new_cursor_channel(RedWorker *worker)
}
}
-static void cursor_channel_hold_pipe_item(RedChannel *channel, PipeItem *item)
+static void cursor_channel_hold_pipe_item(RedChannelClient *rcc, PipeItem *item)
{
ASSERT(item);
((CursorItem *)item)->refs++;
@@ -9176,15 +9184,16 @@ static void cursor_channel_release_item_after_push(CursorChannel *cursor_channel
}
}
-static void cursor_channel_release_item(RedChannel *channel, PipeItem *item, int item_pushed)
+static void cursor_channel_release_item(RedChannelClient *rcc, PipeItem *item, int item_pushed)
{
+ CommonChannel *common = SPICE_CONTAINEROF(rcc->channel, CommonChannel, base);
ASSERT(item);
if (item_pushed) {
- cursor_channel_release_item_after_push((CursorChannel *)channel, item);
+ cursor_channel_release_item_after_push((CursorChannel *)common, item);
} else {
red_printf_once("not pushed (%d)", item->type);
- cursor_channel_release_item_before_push((CursorChannel *)channel, item);
+ cursor_channel_release_item_before_push((CursorChannel *)common, item);
}
}
@@ -9197,11 +9206,11 @@ static void red_connect_cursor(RedWorker *worker, RedsStream *stream, int migrat
if (!(channel = (CursorChannel *)__new_channel(worker, sizeof(*channel),
SPICE_CHANNEL_CURSOR, stream, migrate,
handle_channel_events,
- red_disconnect_cursor,
+ red_disconnect_cursor_client,
cursor_channel_send_item,
cursor_channel_hold_pipe_item,
cursor_channel_release_item,
- red_channel_handle_message,
+ red_channel_client_handle_message,
NULL,
NULL,
NULL))) {
@@ -9247,7 +9256,8 @@ static void red_wait_outgoing_item(RedChannel *channel)
if (blocked) {
red_printf("timeout");
- channel->disconnect(channel);
+ // TODO - not MC friendly
+ red_channel_apply_clients(channel, channel->disconnect);
}
red_unref_channel(channel);
}
@@ -9265,7 +9275,7 @@ static void red_wait_pipe_item_sent(RedChannel *channel, PipeItem *item)
red_printf("");
common = SPICE_CONTAINEROF(channel, CommonChannel, base);
red_ref_channel(channel);
- channel->hold_item(channel, item);
+ channel->hold_item(channel->rcc, item);
end_time = red_now() + CHANNEL_PUSH_TIMEOUT;
@@ -9285,14 +9295,15 @@ static void red_wait_pipe_item_sent(RedChannel *channel, PipeItem *item)
if (item_in_pipe) {
red_printf("timeout");
- channel->disconnect(channel);
+ // TODO - not MC friendly
+ red_channel_apply_clients(channel, channel->disconnect);
} else {
if (red_channel_item_being_sent(channel, item)) {
red_wait_outgoing_item(channel);
}
}
- channel->release_item(channel, item, FALSE);
+ channel->release_item(channel->rcc, item, FALSE);
red_unref_channel(channel);
}
@@ -9688,7 +9699,7 @@ static void handle_dev_input(EventListener *listener, uint32_t events)
}
case RED_WORKER_MESSAGE_DISPLAY_DISCONNECT:
red_printf("disconnect");
- red_disconnect_display((RedChannel *)worker->display_channel);
+ red_disconnect_all_display_TODO_remove_me((RedChannel *)worker->display_channel);
break;
case RED_WORKER_MESSAGE_STOP: {
red_printf("stop");
diff --git a/server/smartcard.c b/server/smartcard.c
index 3f59317f..a8a7beb8 100644
--- a/server/smartcard.c
+++ b/server/smartcard.c
@@ -36,6 +36,7 @@ typedef struct SmartCardDeviceState {
uint32_t buf_size;
uint8_t *buf_pos;
uint32_t buf_used;
+ RedChannelClient *rcc; // client providing the remote card
} SmartCardDeviceState;
enum {
@@ -58,8 +59,6 @@ typedef struct SmartCardChannel {
RedChannel base;
} SmartCardChannel;
-static SmartCardChannel *g_smartcard_channel = NULL;
-
static struct Readers {
uint32_t num;
SpiceCharDeviceInstance* sin[SMARTCARD_MAX_READERS];
@@ -69,16 +68,14 @@ static SpiceCharDeviceInstance* smartcard_readers_get_unattached();
static SpiceCharDeviceInstance* smartcard_readers_get(uint32_t reader_id);
static int smartcard_char_device_add_to_readers(SpiceCharDeviceInstance *sin);
static void smartcard_char_device_attach(
- SpiceCharDeviceInstance *char_device, SmartCardChannel *smartcard_channel);
-static void smartcard_char_device_detach(
- SpiceCharDeviceInstance *char_device, SmartCardChannel *smartcard_channel);
-static void smartcard_channel_write_to_reader(
- SmartCardChannel *smartcard_channel, VSCMsgHeader *vheader);
+ SpiceCharDeviceInstance *char_device, RedChannelClient *rcc);
+static void smartcard_char_device_detach(SpiceCharDeviceInstance *char_device);
+static void smartcard_channel_write_to_reader(VSCMsgHeader *vheader);
static void smartcard_char_device_on_message_from_device(
SmartCardDeviceState *state, VSCMsgHeader *header);
static void smartcard_on_message_from_device(
- SmartCardChannel *smartcard_channel, VSCMsgHeader *vheader);
+ RedChannelClient *rcc, VSCMsgHeader *vheader);
static SmartCardDeviceState* smartcard_device_state_new();
static void smartcard_device_state_free(SmartCardDeviceState* st);
static void smartcard_register_channel(void);
@@ -139,12 +136,13 @@ void smartcard_char_device_on_message_from_device(
if (state->reader_id == VSCARD_UNDEFINED_READER_ID && vheader->type != VSC_Init) {
red_printf("error: reader_id not assigned for message of type %d", vheader->type);
}
- ASSERT(g_smartcard_channel != NULL);
sent_header = spice_memdup(vheader, sizeof(*vheader) + vheader->length);
/* We patch the reader_id, since the device only knows about itself, and
* we know about the sum of readers. */
sent_header->reader_id = state->reader_id;
- smartcard_on_message_from_device(g_smartcard_channel, sent_header);
+ if (state->rcc) {
+ smartcard_on_message_from_device(state->rcc, sent_header);
+ }
}
static void smartcard_readers_detach_all(SmartCardChannel *smartcard_channel)
@@ -152,8 +150,7 @@ static void smartcard_readers_detach_all(SmartCardChannel *smartcard_channel)
int i;
for (i = 0 ; i < g_smartcard_readers.num; ++i) {
- smartcard_char_device_detach(g_smartcard_readers.sin[i],
- smartcard_channel);
+ smartcard_char_device_detach(g_smartcard_readers.sin[i]);
}
}
@@ -204,6 +201,7 @@ static SmartCardDeviceState* smartcard_device_state_new()
st->buf = spice_malloc(st->buf_size);
st->buf_pos = st->buf;
st->buf_used = 0;
+ st->rcc = NULL;
return st;
}
@@ -235,7 +233,7 @@ int smartcard_device_connect(SpiceCharDeviceInstance *char_device)
}
static void smartcard_char_device_attach(
- SpiceCharDeviceInstance *char_device, SmartCardChannel *smartcard_channel)
+ SpiceCharDeviceInstance *char_device, RedChannelClient *rcc)
{
SmartCardDeviceState *st = SPICE_CONTAINEROF(char_device->st, SmartCardDeviceState, base);
@@ -243,13 +241,13 @@ static void smartcard_char_device_attach(
return;
}
st->attached = TRUE;
+ st->rcc = rcc;
VSCMsgHeader vheader = {.type = VSC_ReaderAdd, .reader_id=st->reader_id,
.length=0};
- smartcard_channel_write_to_reader(smartcard_channel, &vheader);
+ smartcard_channel_write_to_reader(&vheader);
}
-static void smartcard_char_device_detach(
- SpiceCharDeviceInstance *char_device, SmartCardChannel *smartcard_channel)
+static void smartcard_char_device_detach(SpiceCharDeviceInstance *char_device)
{
SmartCardDeviceState *st = SPICE_CONTAINEROF(char_device->st, SmartCardDeviceState, base);
@@ -257,75 +255,75 @@ static void smartcard_char_device_detach(
return;
}
st->attached = FALSE;
+ st->rcc = NULL;
VSCMsgHeader vheader = {.type = VSC_ReaderRemove, .reader_id=st->reader_id,
.length=0};
- smartcard_channel_write_to_reader(smartcard_channel, &vheader);
+ smartcard_channel_write_to_reader(&vheader);
}
-static int smartcard_channel_config_socket(RedChannel *channel)
+static int smartcard_channel_config_socket(RedChannelClient *rcc)
{
return TRUE;
}
-static uint8_t *smartcard_channel_alloc_msg_rcv_buf(RedChannel *channel, SpiceDataHeader *msg_header)
+static uint8_t *smartcard_channel_alloc_msg_rcv_buf(RedChannelClient *rcc,
+ SpiceDataHeader *msg_header)
{
//red_printf("allocing %d bytes", msg_header->size);
return spice_malloc(msg_header->size);
}
-static void smartcard_channel_release_msg_rcv_buf(RedChannel *channel, SpiceDataHeader *msg_header,
- uint8_t *msg)
+static void smartcard_channel_release_msg_rcv_buf(RedChannelClient *rcc,
+ SpiceDataHeader *msg_header, uint8_t *msg)
{
red_printf("freeing %d bytes", msg_header->size);
free(msg);
}
-static void smartcard_channel_send_data(RedChannel *channel, SpiceMarshaller *m,
+static void smartcard_channel_send_data(RedChannelClient *rcc, SpiceMarshaller *m,
PipeItem *item, VSCMsgHeader *vheader)
{
- ASSERT(channel);
+ ASSERT(rcc);
ASSERT(vheader);
- red_channel_init_send_data(channel, SPICE_MSG_SMARTCARD_DATA, item);
-
+ red_channel_client_init_send_data(rcc, SPICE_MSG_SMARTCARD_DATA, item);
spice_marshaller_add_ref(m, (uint8_t*)vheader, sizeof(VSCMsgHeader));
if (vheader->length > 0) {
spice_marshaller_add_ref(m, (uint8_t*)(vheader+1), vheader->length);
}
- red_channel_begin_send_message(channel);
+ red_channel_client_begin_send_message(rcc);
}
static void smartcard_channel_send_error(
- SmartCardChannel *smartcard_channel, SpiceMarshaller *m, PipeItem *item)
+ RedChannelClient *rcc, SpiceMarshaller *m, PipeItem *item)
{
ErrorItem* error_item = (ErrorItem*)item;
- smartcard_channel_send_data(&smartcard_channel->base, m, item, &error_item->vheader);
+ smartcard_channel_send_data(rcc, m, item, &error_item->vheader);
}
-static void smartcard_channel_send_msg(
- SmartCardChannel *smartcard_channel, SpiceMarshaller *m, PipeItem *item)
+static void smartcard_channel_send_msg(RedChannelClient *rcc,
+ SpiceMarshaller *m, PipeItem *item)
{
MsgItem* msg_item = (MsgItem*)item;
- smartcard_channel_send_data(&smartcard_channel->base, m, item, msg_item->vheader);
+ smartcard_channel_send_data(rcc, m, item, msg_item->vheader);
}
-static void smartcard_channel_send_item(RedChannel *channel, PipeItem *item)
+static void smartcard_channel_send_item(RedChannelClient *rcc, PipeItem *item)
{
- SmartCardChannel *smartcard_channel = (SmartCardChannel *)channel;
- SpiceMarshaller *m = red_channel_get_marshaller(channel);
+ SpiceMarshaller *m = red_channel_client_get_marshaller(rcc);
switch (item->type) {
case PIPE_ITEM_TYPE_ERROR:
- smartcard_channel_send_error(smartcard_channel, m, item);
+ smartcard_channel_send_error(rcc, m, item);
break;
case PIPE_ITEM_TYPE_MSG:
- smartcard_channel_send_msg(smartcard_channel, m, item);
+ smartcard_channel_send_msg(rcc, m, item);
}
}
-static void smartcard_channel_release_pipe_item(RedChannel *channel, PipeItem *item, int item_pushed)
+static void smartcard_channel_release_pipe_item(RedChannelClient *rcc, PipeItem *item, int item_pushed)
{
if (item->type == PIPE_ITEM_TYPE_MSG) {
free(((MsgItem*)item)->vheader);
@@ -333,22 +331,21 @@ static void smartcard_channel_release_pipe_item(RedChannel *channel, PipeItem *i
free(item);
}
-static void smartcard_channel_disconnect(RedChannel *channel)
+static void smartcard_channel_disconnect(RedChannelClient *rcc)
{
- smartcard_readers_detach_all((SmartCardChannel*)channel);
- red_channel_destroy(channel);
- g_smartcard_channel = NULL;
+ smartcard_readers_detach_all((SmartCardChannel*)(rcc->channel));
+ red_channel_client_destroy(rcc);
}
/* this is called from both device input and client input. since the device is
* a usb device, the context is still the main thread (kvm_main_loop, timers)
* so no mutex is required. */
-static void smartcard_channel_pipe_add_push(SmartCardChannel *channel, PipeItem *item)
+static void smartcard_channel_pipe_add_push(RedChannelClient *rcc, PipeItem *item)
{
- red_channel_pipe_add_push(&channel->base, item);
+ red_channel_pipe_add_push(rcc->channel, item);
}
-static void smartcard_push_error(SmartCardChannel* channel, uint32_t reader_id, VSCErrorCode error)
+static void smartcard_push_error(RedChannelClient *rcc, uint32_t reader_id, VSCErrorCode error)
{
ErrorItem *error_item = spice_new0(ErrorItem, 1);
@@ -357,63 +354,61 @@ static void smartcard_push_error(SmartCardChannel* channel, uint32_t reader_id,
error_item->vheader.type = VSC_Error;
error_item->vheader.length = sizeof(error_item->error);
error_item->error.code = error;
- smartcard_channel_pipe_add_push(channel, &error_item->base);
+ smartcard_channel_pipe_add_push(rcc, &error_item->base);
}
-static void smartcard_push_vscmsg(SmartCardChannel *channel, VSCMsgHeader *vheader)
+static void smartcard_push_vscmsg(RedChannelClient *rcc, VSCMsgHeader *vheader)
{
MsgItem *msg_item = spice_new0(MsgItem, 1);
msg_item->base.type = PIPE_ITEM_TYPE_MSG;
msg_item->vheader = vheader;
- smartcard_channel_pipe_add_push(channel, &msg_item->base);
+ smartcard_channel_pipe_add_push(rcc, &msg_item->base);
}
-void smartcard_on_message_from_device(SmartCardChannel *smartcard_channel,
- VSCMsgHeader* vheader)
+void smartcard_on_message_from_device(RedChannelClient *rcc, VSCMsgHeader* vheader)
{
- smartcard_push_vscmsg(smartcard_channel, vheader);
+ smartcard_push_vscmsg(rcc, vheader);
}
-static void smartcard_remove_reader(SmartCardChannel *smartcard_channel, uint32_t reader_id)
+static void smartcard_remove_reader(RedChannelClient *rcc, uint32_t reader_id)
{
SpiceCharDeviceInstance *char_device = smartcard_readers_get(reader_id);
SmartCardDeviceState *state;
if (char_device == NULL) {
- smartcard_push_error(smartcard_channel, reader_id,
+ smartcard_push_error(rcc, reader_id,
VSC_GENERAL_ERROR);
return;
}
state = SPICE_CONTAINEROF(char_device->st, SmartCardDeviceState, base);
if (state->attached == FALSE) {
- smartcard_push_error(smartcard_channel, reader_id,
+ smartcard_push_error(rcc, reader_id,
VSC_GENERAL_ERROR);
return;
}
- smartcard_char_device_detach(char_device, smartcard_channel);
+ smartcard_char_device_detach(char_device);
}
-static void smartcard_add_reader(SmartCardChannel *smartcard_channel, uint8_t *name)
+static void smartcard_add_reader(RedChannelClient *rcc, uint8_t *name)
{
// TODO - save name somewhere
SpiceCharDeviceInstance *char_device =
smartcard_readers_get_unattached();
if (char_device != NULL) {
- smartcard_char_device_attach(char_device, smartcard_channel);
+ smartcard_char_device_attach(char_device, rcc);
// The device sends a VSC_Error message, we will let it through, no
// need to send our own. We already set the correct reader_id, from
// our SmartCardDeviceState.
} else {
- smartcard_push_error(smartcard_channel, VSCARD_UNDEFINED_READER_ID,
+ smartcard_push_error(rcc, VSCARD_UNDEFINED_READER_ID,
VSC_CANNOT_ADD_MORE_READERS);
}
}
-static void smartcard_channel_write_to_reader(
- SmartCardChannel *smartcard_channel, VSCMsgHeader *vheader)
+static void smartcard_channel_write_to_reader(VSCMsgHeader *vheader)
{
SpiceCharDeviceInstance *sin;
SpiceCharDeviceInterface *sif;
@@ -434,25 +429,25 @@ static void smartcard_channel_write_to_reader(
ASSERT(n == actual_length + sizeof(VSCMsgHeader));
}
-static int smartcard_channel_handle_message(RedChannel *channel, SpiceDataHeader *header, uint8_t *msg)
+static int smartcard_channel_handle_message(RedChannelClient *rcc,
+ SpiceDataHeader *header,
+ uint8_t *msg)
{
VSCMsgHeader* vheader = (VSCMsgHeader*)msg;
- SmartCardChannel* smartcard_channel = (SmartCardChannel*)channel;
if (header->type != SPICE_MSGC_SMARTCARD_DATA) {
/* handle ack's, spicy sends them while spicec does not */
- return red_channel_handle_message(channel, header->size, header->type,
- msg);
+ return red_channel_client_handle_message(rcc, header->size, header->type, msg);
}
ASSERT(header->size == vheader->length + sizeof(VSCMsgHeader));
switch (vheader->type) {
case VSC_ReaderAdd:
- smartcard_add_reader(smartcard_channel, msg + sizeof(VSCMsgHeader));
+ smartcard_add_reader(rcc, msg + sizeof(VSCMsgHeader));
return TRUE;
break;
case VSC_ReaderRemove:
- smartcard_remove_reader(smartcard_channel, vheader->reader_id);
+ smartcard_remove_reader(rcc, vheader->reader_id);
return TRUE;
break;
case VSC_Init:
@@ -474,11 +469,11 @@ static int smartcard_channel_handle_message(RedChannel *channel, SpiceDataHeader
vheader->type, vheader->length);
return FALSE;
}
- smartcard_channel_write_to_reader(smartcard_channel, vheader);
+ smartcard_channel_write_to_reader(vheader);
return TRUE;
}
-static void smartcard_channel_hold_pipe_item(RedChannel *channel, PipeItem *item)
+static void smartcard_channel_hold_pipe_item(RedChannelClient *rcc, PipeItem *item)
{
}
@@ -487,12 +482,13 @@ static void smartcard_link(Channel *channel, RedsStream *stream,
uint32_t *common_caps, int num_caps,
uint32_t *caps)
{
- if (g_smartcard_channel) {
- red_channel_destroy(&g_smartcard_channel->base);
+ if (channel->data) {
+ red_channel_destroy((RedChannel*)channel->data);
+ channel->data = NULL;
}
- g_smartcard_channel =
- (SmartCardChannel *)red_channel_create(sizeof(*g_smartcard_channel),
- stream, core,
+ if (!channel->data) {
+ channel->data = red_channel_create(sizeof(SmartCardChannel),
+ core,
migration, FALSE /* handle_acks */,
smartcard_channel_config_socket,
smartcard_channel_disconnect,
@@ -505,10 +501,13 @@ static void smartcard_link(Channel *channel, RedsStream *stream,
NULL,
NULL,
NULL);
- if (!g_smartcard_channel) {
+ }
+ if (!channel->data) {
+ red_printf("ERROR: smartcard channel creation failed");
return;
}
- red_channel_init_outgoing_messages_window(&g_smartcard_channel->base);
+ red_channel_client_create(sizeof(RedChannelClient), channel->data, stream);
+ red_channel_init_outgoing_messages_window((RedChannel*)channel->data);
}
static void smartcard_shutdown(Channel *channel)
diff --git a/server/usbredir.c b/server/usbredir.c
index 096a381b..f6b0fe8b 100644
--- a/server/usbredir.c
+++ b/server/usbredir.c
@@ -38,6 +38,7 @@ typedef struct UsbRedirPipeItem {
typedef struct UsbRedirState {
Channel channel;
RedChannel *red_channel;
+ RedChannelClient *rcc;
SpiceCharDeviceState chardev_st;
SpiceCharDeviceInstance *chardev_sin;
UsbRedirPipeItem *pipe_item;
@@ -81,46 +82,46 @@ static void usbredir_chardev_wakeup(SpiceCharDeviceInstance *sin)
} while (n > 0);
}
-static int usbredir_red_channel_config_socket(RedChannel *red_channel)
+static int usbredir_red_channel_config_socket(RedChannelClient *rcc)
{
return TRUE;
}
-static void usbredir_red_channel_disconnect(RedChannel *red_channel)
+static void usbredir_red_channel_disconnect(RedChannelClient *rcc)
{
UsbRedirState *state;
SpiceCharDeviceInstance *sin;
SpiceCharDeviceInterface *sif;
- if (!red_channel) {
+ if (!rcc) {
return;
}
- state = SPICE_CONTAINEROF(red_channel, UsbRedirChannel, base)->state;
+ state = SPICE_CONTAINEROF(rcc->channel, UsbRedirChannel, base)->state;
sin = state->chardev_sin;
sif = SPICE_CONTAINEROF(sin->base.sif, SpiceCharDeviceInterface, base);
- red_channel_destroy(red_channel);
- state->red_channel = NULL;
+ red_channel_client_destroy(rcc);
+ state->rcc = NULL;
if (sif->state) {
sif->state(sin, 0);
}
}
-static int usbredir_red_channel_handle_message(RedChannel *red_channel,
+static int usbredir_red_channel_client_handle_message(RedChannelClient *rcc,
SpiceDataHeader *header, uint8_t *msg)
{
UsbRedirState *state;
SpiceCharDeviceInstance *sin;
SpiceCharDeviceInterface *sif;
- state = SPICE_CONTAINEROF(red_channel, UsbRedirChannel, base)->state;
+ state = SPICE_CONTAINEROF(rcc->channel, UsbRedirChannel, base)->state;
sin = state->chardev_sin;
sif = SPICE_CONTAINEROF(sin->base.sif, SpiceCharDeviceInterface, base);
if (header->type != SPICE_MSGC_USBREDIR_DATA) {
- return red_channel_handle_message(red_channel, header->size,
- header->type, msg);
+ return red_channel_client_handle_message(rcc, header->size,
+ header->type, msg);
}
/*
@@ -132,12 +133,12 @@ static int usbredir_red_channel_handle_message(RedChannel *red_channel,
return TRUE;
}
-static uint8_t *usbredir_red_channel_alloc_msg_rcv_buf(RedChannel *red_channel,
+static uint8_t *usbredir_red_channel_alloc_msg_rcv_buf(RedChannelClient *rcc,
SpiceDataHeader *msg_header)
{
UsbRedirState *state;
- state = SPICE_CONTAINEROF(red_channel, UsbRedirChannel, base)->state;
+ state = SPICE_CONTAINEROF(rcc->channel, UsbRedirChannel, base)->state;
if (msg_header->size > state->rcv_buf_size) {
state->rcv_buf = spice_realloc(state->rcv_buf, msg_header->size);
@@ -147,30 +148,30 @@ static uint8_t *usbredir_red_channel_alloc_msg_rcv_buf(RedChannel *red_channel,
return state->rcv_buf;
}
-static void usbredir_red_channel_release_msg_rcv_buf(RedChannel *red_channel,
+static void usbredir_red_channel_release_msg_rcv_buf(RedChannelClient *rcc,
SpiceDataHeader *msg_header, uint8_t *msg)
{
/* NOOP, we re-use the buffer every time and only free it on destruction */
}
-static void usbredir_red_channel_hold_pipe_item(RedChannel *red_channel,
+static void usbredir_red_channel_hold_pipe_item(RedChannelClient *rcc,
PipeItem *item)
{
/* NOOP */
}
-static void usbredir_red_channel_send_item(RedChannel *red_channel,
+static void usbredir_red_channel_send_item(RedChannelClient *rcc,
PipeItem *item)
{
UsbRedirPipeItem *i = SPICE_CONTAINEROF(item, UsbRedirPipeItem, base);
- SpiceMarshaller *m = red_channel_get_marshaller(red_channel);
+ SpiceMarshaller *m = red_channel_client_get_marshaller(rcc);
- red_channel_init_send_data(red_channel, SPICE_MSG_USBREDIR_DATA, item);
+ red_channel_client_init_send_data(rcc, SPICE_MSG_USBREDIR_DATA, item);
spice_marshaller_add_ref(m, i->buf, i->buf_used);
- red_channel_begin_send_message(red_channel);
+ red_channel_client_begin_send_message(rcc);
}
-static void usbredir_red_channel_release_pipe_item(RedChannel *red_channel,
+static void usbredir_red_channel_release_pipe_item(RedChannelClient *rcc,
PipeItem *item, int item_pushed)
{
free(item);
@@ -188,30 +189,38 @@ static void usbredir_link(Channel *channel, RedsStream *stream, int migration,
sin = state->chardev_sin;
sif = SPICE_CONTAINEROF(sin->base.sif, SpiceCharDeviceInterface, base);
- if (state->red_channel) {
- WARN("channel %d:%d already connected, refusing second connection\n",
- channel->type, channel->id);
+ if (state->rcc) {
+ WARN("channel client %d:%d (%p) already connected, refusing second connection\n",
+ channel->type, channel->id, state->rcc);
+ // TODO: notify client in advance about the in use channel using
+ // SPICE_MSG_MAIN_CHANNEL_IN_USE (for example)
reds_stream_free(stream);
return;
}
- state->red_channel = red_channel_create(sizeof(UsbRedirChannel),
- stream, core,
- migration, FALSE /* handle_acks */,
- usbredir_red_channel_config_socket,
- usbredir_red_channel_disconnect,
- usbredir_red_channel_handle_message,
- usbredir_red_channel_alloc_msg_rcv_buf,
- usbredir_red_channel_release_msg_rcv_buf,
- usbredir_red_channel_hold_pipe_item,
- usbredir_red_channel_send_item,
- usbredir_red_channel_release_pipe_item,
- NULL,
- NULL,
- NULL);
+ if (!state->red_channel) {
+ state->red_channel = red_channel_create(sizeof(UsbRedirChannel),
+ core, migration, FALSE /* handle_acks */,
+ usbredir_red_channel_config_socket,
+ usbredir_red_channel_disconnect,
+ usbredir_red_channel_client_handle_message,
+ usbredir_red_channel_alloc_msg_rcv_buf,
+ usbredir_red_channel_release_msg_rcv_buf,
+ usbredir_red_channel_hold_pipe_item,
+ usbredir_red_channel_send_item,
+ usbredir_red_channel_release_pipe_item,
+ NULL,
+ NULL,
+ NULL);
+ }
if (!state->red_channel) {
return;
}
+ state->rcc = red_channel_client_create(sizeof(RedChannelClient), state->red_channel, stream);
+ if (!state->rcc) {
+ red_printf("failed to create usbredir channel client\n");
+ return;
+ }
red_channel_init_outgoing_messages_window(state->red_channel);
redir_chan = SPICE_CONTAINEROF(state->red_channel, UsbRedirChannel, base);
redir_chan->state = state;
@@ -225,7 +234,9 @@ static void usbredir_shutdown(Channel *channel)
{
UsbRedirState *state = SPICE_CONTAINEROF(channel, UsbRedirState, channel);
- usbredir_red_channel_disconnect(state->red_channel);
+ usbredir_red_channel_disconnect(state->rcc);
+ red_channel_destroy(state->red_channel);
+ state->red_channel = NULL;
}
static void usbredir_migrate(Channel *channel)
@@ -264,7 +275,7 @@ void usbredir_device_disconnect(SpiceCharDeviceInstance *sin)
reds_unregister_channel(&state->channel);
- usbredir_red_channel_disconnect(state->red_channel);
+ usbredir_red_channel_disconnect(state->rcc);
free(state->pipe_item);
free(state->rcv_buf);