diff options
author | Alon Levy <alevy@redhat.com> | 2010-11-13 13:23:02 +0200 |
---|---|---|
committer | Alon Levy <alevy@redhat.com> | 2011-08-23 17:42:36 +0300 |
commit | 7e8e13593ee681cf04c349bca57dd225d7802494 (patch) | |
tree | f47be108ffe570dfa942502b8bad837551db4720 /server | |
parent | 75b6a305ff9c42a89c9db91277027d5dc6d103ef (diff) |
server/red_channel (all): introduce RedChannelClient
This commit adds a RedChannelClient that now owns the stream connection,
but still doesn't own the pipe. There is only a single RCC per RC
right now (and RC still means RedChannel, RedClient will be introduced
later). All internal api changes are in server/red_channel.h, hence
the need to update all channels. red_worker.c is affected the most because
it makes use of direct access to some of RedChannel still.
API changes:
1. red_channel_client_create added.
rec_channel_create -> (red_channel_create, red_channel_client_create)
2. two way connection: rcc->channel, channel->rcc (later channel will
hold a list, and there will be a RedClient to hold the list of channels
per client)
3. seperation of channel disconnect and channel_client_disconnect
TODO:
usbredir added untested.
Diffstat (limited to 'server')
-rw-r--r-- | server/inputs_channel.c | 39 | ||||
-rw-r--r-- | server/main_channel.c | 82 | ||||
-rw-r--r-- | server/red_channel.c | 627 | ||||
-rw-r--r-- | server/red_channel.h | 109 | ||||
-rw-r--r-- | server/red_client_shared_cache.h | 17 | ||||
-rw-r--r-- | server/red_tunnel_worker.c | 214 | ||||
-rw-r--r-- | server/red_worker.c | 679 | ||||
-rw-r--r-- | server/smartcard.c | 147 | ||||
-rw-r--r-- | server/usbredir.c | 87 |
9 files changed, 1140 insertions, 861 deletions
diff --git a/server/inputs_channel.c b/server/inputs_channel.c index 0cc53a2..3a4a0d0 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 1a6a89c..0718f88 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 9ecc7ef..8bbc6c9 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 d05722c..e7a83d3 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 74553c0..dddccc6 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 b649c60..5caa8b9 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 c0d03f3..bbb0155 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, ©_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, ©, &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 3f59317..a8a7beb 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 096a381..f6b0fe8 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); |