diff options
author | Alon Levy <alevy@redhat.com> | 2010-11-04 14:28:57 +0200 |
---|---|---|
committer | Alon Levy <alevy@redhat.com> | 2011-01-15 20:54:48 +0200 |
commit | 8fabff2a1eef41d61207a1f5c94dbbf6ef10f202 (patch) | |
tree | 48c624989482bf901a38e0ec69ec176ebdfada44 /server/main_channel.c | |
parent | 444b322cabbf0a8cd7220f055133b3b5eaf3042e (diff) | |
download | spice-8fabff2a1eef41d61207a1f5c94dbbf6ef10f202.tar.gz spice-8fabff2a1eef41d61207a1f5c94dbbf6ef10f202.tar.xz spice-8fabff2a1eef41d61207a1f5c94dbbf6ef10f202.zip |
server/main_channel: use red_channel (most code is pipe send/marshall separation)
Diffstat (limited to 'server/main_channel.c')
-rw-r--r-- | server/main_channel.c | 778 |
1 files changed, 441 insertions, 337 deletions
diff --git a/server/main_channel.c b/server/main_channel.c index e42f1734..f1fb4c68 100644 --- a/server/main_channel.c +++ b/server/main_channel.c @@ -38,6 +38,7 @@ #include "common/messages.h" #include "reds.h" #include "main_channel.h" +#include "red_channel.h" #include "generated_marshallers.h" #define ZERO_BUF_SIZE 4096 @@ -55,34 +56,67 @@ static uint8_t zero_page[ZERO_BUF_SIZE] = {0}; typedef struct RedsOutItem RedsOutItem; struct RedsOutItem { - RingItem link; - SpiceMarshaller *m; - SpiceDataHeader *header; + PipeItem base; }; -typedef struct RedsOutgoingData { - Ring pipe; - RedsOutItem *item; - int vec_size; - struct iovec vec_buf[REDS_MAX_SEND_IOVEC]; - struct iovec *vec; -} RedsOutgoingData; - -// TODO - remove and use red_channel.h -typedef struct IncomingHandler { - spice_parse_channel_func_t parser; +typedef struct PingPipeItem { + PipeItem base; + int size; +} PingPipeItem; + +typedef struct MouseModePipeItem { + PipeItem base; + int current_mode; + int is_client_mouse_allowed; +} MouseModePipeItem; + +typedef struct TokensPipeItem { + PipeItem base; + int tokens; +} TokensPipeItem; + +typedef struct AgentDataPipeItem { + PipeItem base; + uint8_t* data; + size_t len; + spice_marshaller_item_free_func free_data; void *opaque; - int shut; - uint8_t buf[RECEIVE_BUF_SIZE]; - uint32_t end_pos; - void (*handle_message)(void *opaque, size_t size, uint32_t type, void *message); -} IncomingHandler; +} AgentDataPipeItem; + +typedef struct InitPipeItem { + PipeItem base; + int connection_id; + int display_channels_hint; + int current_mouse_mode; + int is_client_mouse_allowed; + int multi_media_time; + int ram_hint; +} InitPipeItem; + +typedef struct NotifyPipeItem { + PipeItem base; + uint8_t *mess; + int mess_len; +} NotifyPipeItem; + +typedef struct MigrateBeginPipeItem { + PipeItem base; + int port; + int sport; + char *host; + uint16_t cert_pub_key_type; + uint32_t cert_pub_key_len; + uint8_t *cert_pub_key; +} MigrateBeginPipeItem; + +typedef struct MultiMediaTimePipeItem { + PipeItem base; + int time; +} MultiMediaTimePipeItem; typedef struct MainChannel { - RedsStreamContext *peer; - IncomingHandler in_handler; - RedsOutgoingData outgoing; - uint64_t serial; //migrate me + RedChannel base; + uint8_t recv_buf[RECEIVE_BUF_SIZE]; uint32_t ping_id; uint32_t net_test_id; int net_test_stage; @@ -98,45 +132,13 @@ enum NetTestStage { static uint64_t latency = 0; uint64_t bitrate_per_sec = ~0; -static void main_channel_out_item_free(RedsOutItem *item); - -static void main_reset_outgoing(MainChannel *main_chan) -{ - RedsOutgoingData *outgoing = &main_chan->outgoing; - RingItem *ring_item; - - if (outgoing->item) { - main_channel_out_item_free(outgoing->item); - outgoing->item = NULL; - } - while ((ring_item = ring_get_tail(&outgoing->pipe))) { - RedsOutItem *out_item = (RedsOutItem *)ring_item; - ring_remove(ring_item); - main_channel_out_item_free(out_item); - } - outgoing->vec_size = 0; - outgoing->vec = outgoing->vec_buf; -} - -// ALON from reds_disconnect static void main_disconnect(MainChannel *main_chan) { - if (!main_chan || !main_chan->peer) { - return; - } - main_reset_outgoing(main_chan); - core->watch_remove(main_chan->peer->watch); - main_chan->peer->watch = NULL; - main_chan->peer->cb_free(main_chan->peer); - main_chan->peer = NULL; - main_chan->in_handler.shut = TRUE; - main_chan->serial = 0; main_chan->ping_id = 0; main_chan->net_test_id = 0; main_chan->net_test_stage = NET_TEST_STAGE_INVALID; - main_chan->in_handler.end_pos = 0; + red_channel_destroy(&main_chan->base); - // TODO: Should probably reset these on the ping start, not here latency = 0; bitrate_per_sec = ~0; } @@ -149,233 +151,199 @@ void main_channel_start_net_test(Channel *channel) return; } - if (main_channel_push_ping(channel, NET_TEST_WARMUP_BYTES) && - main_channel_push_ping(channel, 0) && - main_channel_push_ping(channel, NET_TEST_BYTES)) { + if (main_channel_push_ping(channel, NET_TEST_WARMUP_BYTES) + && main_channel_push_ping(channel, 0) + && main_channel_push_ping(channel, NET_TEST_BYTES)) { main_chan->net_test_id = main_chan->ping_id - 2; main_chan->net_test_stage = NET_TEST_STAGE_WARMUP; } } -static int handle_incoming(RedsStreamContext *peer, IncomingHandler *handler) +static RedsOutItem *main_pipe_item_new(MainChannel *main_chan, int type) { - for (;;) { - uint8_t *buf = handler->buf; - uint32_t pos = handler->end_pos; - uint8_t *end = buf + pos; - SpiceDataHeader *header; - int n; - n = peer->cb_read(peer->ctx, buf + pos, RECEIVE_BUF_SIZE - pos); - if (n <= 0) { - if (n == 0) { - return -1; - } - switch (errno) { - case EAGAIN: - return 0; - case EINTR: - break; - case EPIPE: - return -1; - default: - red_printf("%s", strerror(errno)); - return -1; - } - } else { - pos += n; - end = buf + pos; - while (buf + sizeof(SpiceDataHeader) <= end && - buf + sizeof(SpiceDataHeader) + (header = (SpiceDataHeader *)buf)->size <= end) { - uint8_t *data = (uint8_t *)(header+1); - size_t parsed_size; - uint8_t *parsed; - message_destructor_t parsed_free; - - buf += sizeof(SpiceDataHeader) + header->size; - parsed = handler->parser(data, data + header->size, header->type, - SPICE_VERSION_MINOR, &parsed_size, &parsed_free); - if (parsed == NULL) { - red_printf("failed to parse message type %d", header->type); - return -1; - } - handler->handle_message(handler->opaque, parsed_size, header->type, parsed); - parsed_free(parsed); - if (handler->shut) { - return -1; - } - } - memmove(handler->buf, buf, (handler->end_pos = end - buf)); - } - } + RedsOutItem *item = spice_malloc(sizeof(RedsOutItem)); + + red_channel_pipe_item_init(&main_chan->base, &item->base, type); + return item; } -static RedsOutItem *new_out_item(MainChannel *main_chan, uint32_t type) +static MouseModePipeItem *main_mouse_mode_item_new(MainChannel *main_chan, + int current_mode, int is_client_mouse_allowed) { - RedsOutItem *item; - - item = spice_new(RedsOutItem, 1); - ring_item_init(&item->link); + MouseModePipeItem *item = spice_malloc(sizeof(MouseModePipeItem)); - item->m = spice_marshaller_new(); - item->header = (SpiceDataHeader *) - spice_marshaller_reserve_space(item->m, sizeof(SpiceDataHeader)); - spice_marshaller_set_base(item->m, sizeof(SpiceDataHeader)); + red_channel_pipe_item_init(&main_chan->base, &item->base, + SPICE_MSG_MAIN_MOUSE_MODE); + item->current_mode = current_mode; + item->is_client_mouse_allowed = is_client_mouse_allowed; + return item; +} - item->header->serial = ++main_chan->serial; - item->header->type = type; - item->header->sub_list = 0; +static PingPipeItem *main_ping_item_new(MainChannel *channel, int size) +{ + PingPipeItem *item = spice_malloc(sizeof(PingPipeItem)); + red_channel_pipe_item_init(&channel->base, &item->base, SPICE_MSG_PING); + item->size = size; return item; } -static void main_channel_out_item_free(RedsOutItem *item) +static TokensPipeItem *main_tokens_item_new(MainChannel *main_chan, int tokens) { - spice_marshaller_destroy(item->m); - free(item); + TokensPipeItem *item = spice_malloc(sizeof(TokensPipeItem)); + + red_channel_pipe_item_init(&main_chan->base, &item->base, + SPICE_MSG_MAIN_AGENT_TOKEN); + item->tokens = tokens; + return item; } -static struct iovec *main_channel_iovec_skip(struct iovec vec[], int skip, int *vec_size) +static AgentDataPipeItem *main_agent_data_item_new(MainChannel *channel, + uint8_t* data, size_t len, + spice_marshaller_item_free_func free_data, void *opaque) { - struct iovec *now = vec; + AgentDataPipeItem *item = spice_malloc(sizeof(AgentDataPipeItem)); - while (skip && skip >= now->iov_len) { - skip -= now->iov_len; - --*vec_size; - now++; - } - now->iov_base = (uint8_t *)now->iov_base + skip; - now->iov_len -= skip; - return now; + red_channel_pipe_item_init(&channel->base, &item->base, SPICE_MSG_MAIN_AGENT_DATA); + item->data = data; + item->len = len; + item->free_data = free_data; + item->opaque = opaque; + return item; } -static int main_channel_send_data(MainChannel *main_chan) +static InitPipeItem *main_init_item_new(MainChannel *main_chan, + int connection_id, int display_channels_hint, int current_mouse_mode, + int is_client_mouse_allowed, int multi_media_time, + int ram_hint) { - RedsOutgoingData *outgoing = &main_chan->outgoing; - int n; - - if (!outgoing->item) { - return TRUE; - } + InitPipeItem *item = spice_malloc(sizeof(InitPipeItem)); - ASSERT(outgoing->vec_size); - for (;;) { - if ((n = main_chan->peer->cb_writev(main_chan->peer->ctx, outgoing->vec, outgoing->vec_size)) == -1) { - switch (errno) { - case EAGAIN: - core->watch_update_mask(main_chan->peer->watch, - SPICE_WATCH_EVENT_READ | SPICE_WATCH_EVENT_WRITE); - return FALSE; - case EINTR: - break; - case EPIPE: - reds_disconnect(); - return FALSE; - default: - red_printf("%s", strerror(errno)); - reds_disconnect(); - return FALSE; - } - } else { - outgoing->vec = main_channel_iovec_skip(outgoing->vec, n, &outgoing->vec_size); - if (!outgoing->vec_size) { - main_channel_out_item_free(outgoing->item); - outgoing->item = NULL; - outgoing->vec = outgoing->vec_buf; - return TRUE; - } - } - } + red_channel_pipe_item_init(&main_chan->base, &item->base, + SPICE_MSG_MAIN_INIT); + item->connection_id = connection_id; + item->display_channels_hint = display_channels_hint; + item->current_mouse_mode = current_mouse_mode; + item->is_client_mouse_allowed = is_client_mouse_allowed; + item->multi_media_time = multi_media_time; + item->ram_hint = ram_hint; + return item; } -static void main_channel_push(MainChannel *main_chan) +static NotifyPipeItem *main_notify_item_new(MainChannel *main_chan, + uint8_t *mess, const int mess_len) { - RedsOutgoingData *outgoing = &main_chan->outgoing; - RingItem *ring_item; - RedsOutItem *item; + NotifyPipeItem *item = spice_malloc(sizeof(NotifyPipeItem)); - for (;;) { - if (!main_chan->peer || outgoing->item || !(ring_item = ring_get_tail(&outgoing->pipe))) { - return; - } - ring_remove(ring_item); - outgoing->item = item = (RedsOutItem *)ring_item; + red_channel_pipe_item_init(&main_chan->base, &item->base, + SPICE_MSG_NOTIFY); + item->mess = mess; + item->mess_len = mess_len; + return item; +} - spice_marshaller_flush(item->m); - item->header->size = spice_marshaller_get_total_size(item->m) - sizeof(SpiceDataHeader); +static MigrateBeginPipeItem *main_migrate_begin_item_new( + MainChannel *main_chan, int port, int sport, + char *host, uint16_t cert_pub_key_type, uint32_t cert_pub_key_len, + uint8_t *cert_pub_key) +{ + MigrateBeginPipeItem *item = spice_malloc(sizeof(MigrateBeginPipeItem)); - outgoing->vec_size = spice_marshaller_fill_iovec(item->m, - outgoing->vec_buf, - REDS_MAX_SEND_IOVEC, 0); - main_channel_send_data(main_chan); - } + red_channel_pipe_item_init(&main_chan->base, &item->base, + SPICE_MSG_MAIN_MIGRATE_BEGIN); + item->port = port; + item->sport = sport; + item->host = host; + item->cert_pub_key_type = cert_pub_key_type; + item->cert_pub_key_len = cert_pub_key_len; + item->cert_pub_key = cert_pub_key; + return item; } -static void main_channel_push_pipe_item(MainChannel *main_chan, RedsOutItem *item) +static MultiMediaTimePipeItem *main_multi_media_time_item_new( + MainChannel *main_chan, int time) { - ring_add(&main_chan->outgoing.pipe, &item->link); - main_channel_push(main_chan); + MultiMediaTimePipeItem *item; + + item = spice_malloc(sizeof(MultiMediaTimePipeItem)); + red_channel_pipe_item_init(&main_chan->base, &item->base, + SPICE_MSG_MAIN_MULTI_MEDIA_TIME); + item->time = time; + return item; } static void main_channel_push_channels(MainChannel *main_chan) { - SpiceMsgChannels* channels_info; RedsOutItem *item; - item = new_out_item(main_chan, SPICE_MSG_MAIN_CHANNELS_LIST); - channels_info = (SpiceMsgChannels *)spice_malloc(sizeof(SpiceMsgChannels) + reds_num_of_channels() * sizeof(SpiceChannelId)); + item = main_pipe_item_new(main_chan, SPICE_MSG_MAIN_CHANNELS_LIST); + red_channel_pipe_add(&main_chan->base, &item->base); +} + +static void main_channel_marshall_channels(MainChannel *main_chan) +{ + SpiceMsgChannels* channels_info; + + channels_info = (SpiceMsgChannels *)spice_malloc(sizeof(SpiceMsgChannels) + + reds_num_of_channels() * sizeof(SpiceChannelId)); reds_fill_channels(channels_info); - spice_marshall_msg_main_channels_list(item->m, channels_info); + spice_marshall_msg_main_channels_list( + main_chan->base.send_data.marshaller, channels_info); free(channels_info); - main_channel_push_pipe_item(main_chan, item); } int main_channel_push_ping(Channel *channel, int size) { - struct timespec time_space; - RedsOutItem *item; - SpiceMsgPing ping; MainChannel *main_chan = channel->data; - - if (!main_chan) { + PingPipeItem *item; + + if (main_chan == NULL) { return FALSE; } - item = new_out_item(main_chan, SPICE_MSG_PING); + item = main_ping_item_new(main_chan, size); + red_channel_pipe_add(&main_chan->base, &item->base); + return TRUE; +} + +static void main_channel_marshall_ping(MainChannel *main_chan, int size) +{ + struct timespec time_space; + SpiceMsgPing ping; + SpiceMarshaller *m = main_chan->base.send_data.marshaller; + ping.id = ++main_chan->ping_id; clock_gettime(CLOCK_MONOTONIC, &time_space); ping.timestamp = time_space.tv_sec * 1000000LL + time_space.tv_nsec / 1000LL; - spice_marshall_msg_ping(item->m, &ping); + spice_marshall_msg_ping(m, &ping); while (size > 0) { int now = MIN(ZERO_BUF_SIZE, size); size -= now; - spice_marshaller_add_ref(item->m, zero_page, now); + spice_marshaller_add_ref(m, zero_page, now); } +} - main_channel_push_pipe_item(main_chan, item); +void main_channel_push_mouse_mode(Channel *channel, int current_mode, + int is_client_mouse_allowed) +{ + MainChannel *main_chan = channel->data; + MouseModePipeItem *item; - return TRUE; + item = main_mouse_mode_item_new(main_chan, current_mode, + is_client_mouse_allowed); + red_channel_pipe_add(&main_chan->base, &item->base); } -void main_channel_push_mouse_mode(Channel *channel, int current_mode, int is_client_mouse_allowed) +static void main_channel_marshall_mouse_mode(MainChannel *main_chan, int current_mode, int is_client_mouse_allowed) { SpiceMsgMainMouseMode mouse_mode; - RedsOutItem *item; - MainChannel *main_chan; - - if (!channel) { - return; - } - main_chan = channel->data; - item = new_out_item(main_chan, SPICE_MSG_MAIN_MOUSE_MODE); mouse_mode.supported_modes = SPICE_MOUSE_MODE_SERVER; if (is_client_mouse_allowed) { mouse_mode.supported_modes |= SPICE_MOUSE_MODE_CLIENT; } mouse_mode.current_mode = current_mode; - - spice_marshall_msg_main_mouse_mode(item->m, &mouse_mode); - - main_channel_push_pipe_item(main_chan, item); + spice_marshall_msg_main_mouse_mode(main_chan->base.send_data.marshaller, + &mouse_mode); } void main_channel_push_agent_connected(Channel *channel) @@ -383,186 +351,319 @@ void main_channel_push_agent_connected(Channel *channel) RedsOutItem *item; MainChannel *main_chan = channel->data; - item = new_out_item(main_chan, SPICE_MSG_MAIN_AGENT_CONNECTED); - main_channel_push_pipe_item(main_chan, item); + item = main_pipe_item_new(main_chan, SPICE_MSG_MAIN_AGENT_CONNECTED); + red_channel_pipe_add(&main_chan->base, &item->base); } void main_channel_push_agent_disconnected(Channel *channel) { - SpiceMsgMainAgentDisconnect disconnect; RedsOutItem *item; MainChannel *main_chan = channel->data; - item = new_out_item(main_chan, SPICE_MSG_MAIN_AGENT_DISCONNECTED); + item = main_pipe_item_new(main_chan, SPICE_MSG_MAIN_AGENT_DISCONNECTED); + red_channel_pipe_add(&main_chan->base, &item->base); +} + +static void main_channel_marshall_agent_disconnected(MainChannel *main_chan) +{ + SpiceMsgMainAgentDisconnect disconnect; + disconnect.error_code = SPICE_LINK_ERR_OK; - spice_marshall_msg_main_agent_disconnected(item->m, &disconnect); - main_channel_push_pipe_item(main_chan, item); + spice_marshall_msg_main_agent_disconnected( + main_chan->base.send_data.marshaller, &disconnect); } void main_channel_push_tokens(Channel *channel, uint32_t num_tokens) { - SpiceMsgMainAgentTokens tokens; - RedsOutItem *item; MainChannel *main_chan = channel->data; + TokensPipeItem *item = main_tokens_item_new(main_chan, num_tokens); + + red_channel_pipe_add(&main_chan->base, &item->base); +} + +static void main_channel_marshall_tokens(MainChannel *main_chan, uint32_t num_tokens) +{ + SpiceMsgMainAgentTokens tokens; - if (!main_chan) { - return; - } - item = new_out_item(main_chan, SPICE_MSG_MAIN_AGENT_TOKEN); tokens.num_tokens = num_tokens; - spice_marshall_msg_main_agent_token(item->m, &tokens); - main_channel_push_pipe_item(main_chan, item); + spice_marshall_msg_main_agent_token( + main_chan->base.send_data.marshaller, &tokens); } void main_channel_push_agent_data(Channel *channel, uint8_t* data, size_t len, spice_marshaller_item_free_func free_data, void *opaque) { - RedsOutItem *item; MainChannel *main_chan = channel->data; + AgentDataPipeItem *item; + + item = main_agent_data_item_new(main_chan, data, len, free_data, opaque); + red_channel_pipe_add(&main_chan->base, &item->base); +} - item = new_out_item(main_chan, SPICE_MSG_MAIN_AGENT_DATA); - spice_marshaller_add_ref_full(item->m, data, len, free_data, opaque); - main_channel_push_pipe_item(main_chan, item); +static void main_channel_marshall_agent_data(MainChannel *main_chan, + AgentDataPipeItem *item) +{ + spice_marshaller_add_ref_full(main_chan->base.send_data.marshaller, + item->data, item->len, item->free_data, item->opaque); } static void main_channel_push_migrate_data_item(MainChannel *main_chan) { - RedsOutItem *item = new_out_item(main_chan, SPICE_MSG_MIGRATE_DATA); - SpiceMarshaller *m = item->m; + RedsOutItem *item = main_pipe_item_new(main_chan, SPICE_MSG_MIGRATE_DATA); + + red_channel_pipe_add(&main_chan->base, &item->base); +} + +static void main_channel_marshall_migrate_data_item(MainChannel *main_chan) +{ + SpiceMarshaller *m = main_chan->base.send_data.marshaller; MainMigrateData *data = (MainMigrateData *)spice_marshaller_reserve_space(m, sizeof(MainMigrateData)); reds_marshall_migrate_data_item(m, data); // TODO: from reds split. ugly separation. - data->serial = main_chan->serial; + data->serial = red_channel_get_message_serial(&main_chan->base); data->ping_id = main_chan->ping_id; - main_channel_push_pipe_item(main_chan, item); } -static void main_channel_receive_migrate_data(MainChannel *main_chan, MainMigrateData *data, uint8_t *end) +static void main_channel_receive_migrate_data(MainChannel *main_chan, + MainMigrateData *data, uint8_t *end) { - main_chan->serial = data->serial; + red_channel_set_message_serial(&main_chan->base, data->serial); main_chan->ping_id = data->ping_id; } -void main_channel_push_init(Channel *channel, int connection_id, int display_channels_hint, - int current_mouse_mode, int is_client_mouse_allowed, int multi_media_time, +void main_channel_push_init(Channel *channel, int connection_id, + int display_channels_hint, int current_mouse_mode, + int is_client_mouse_allowed, int multi_media_time, int ram_hint) { - RedsOutItem *item; - SpiceMsgMainInit init; + InitPipeItem *item; MainChannel *main_chan = channel->data; - item = new_out_item(main_chan, SPICE_MSG_MAIN_INIT); - init.session_id = connection_id; - init.display_channels_hint = display_channels_hint; - init.current_mouse_mode = current_mouse_mode; + item = main_init_item_new(main_chan, + connection_id, display_channels_hint, current_mouse_mode, + is_client_mouse_allowed, multi_media_time, ram_hint); + red_channel_pipe_add(&main_chan->base, &item->base); +} + +static void main_channel_marshall_init(MainChannel *main_chan, + InitPipeItem *item) +{ + SpiceMsgMainInit init; + + init.session_id = item->connection_id; + init.display_channels_hint = item->display_channels_hint; + init.current_mouse_mode = item->current_mouse_mode; init.supported_mouse_modes = SPICE_MOUSE_MODE_SERVER; - if (is_client_mouse_allowed) { + if (item->is_client_mouse_allowed) { init.supported_mouse_modes |= SPICE_MOUSE_MODE_CLIENT; } init.agent_connected = reds_has_vdagent(); init.agent_tokens = REDS_AGENT_WINDOW_SIZE; - init.multi_media_time = multi_media_time; - init.ram_hint = ram_hint; - spice_marshall_msg_main_init(item->m, &init); - main_channel_push_pipe_item(main_chan, item); + init.multi_media_time = item->multi_media_time; + init.ram_hint = item->ram_hint; + spice_marshall_msg_main_init(main_chan->base.send_data.marshaller, &init); } void main_channel_push_notify(Channel *channel, uint8_t *mess, const int mess_len) { - // TODO possible free-then-use bug - caller frees mess after this, but is that pointer being - // used by spice_marshaller? - RedsOutItem *item; - SpiceMsgNotify notify; MainChannel *main_chan = channel->data; + NotifyPipeItem *item = main_notify_item_new(main_chan, mess, mess_len); + + red_channel_pipe_add(&main_chan->base, &item->base); +} - item = new_out_item(main_chan, SPICE_MSG_NOTIFY); - notify.time_stamp = get_time_stamp(); +static void main_channel_marshall_notify(MainChannel *main_chan, NotifyPipeItem *item) +{ + SpiceMsgNotify notify; + SpiceMarshaller *m = main_chan->base.send_data.marshaller; + + notify.time_stamp = get_time_stamp(); // TODO - move to main_new_notify_item notify.severity = SPICE_NOTIFY_SEVERITY_WARN; notify.visibilty = SPICE_NOTIFY_VISIBILITY_HIGH; notify.what = SPICE_WARN_GENERAL; - notify.message_len = mess_len; - spice_marshall_msg_notify(item->m, ¬ify); - spice_marshaller_add(item->m, mess, mess_len + 1); - main_channel_push_pipe_item(main_chan, item); + notify.message_len = item->mess_len; + spice_marshall_msg_notify(m, ¬ify); + spice_marshaller_add(m, item->mess, item->mess_len + 1); } -void main_channel_push_migrate_begin(Channel *channel, int port, int sport, char *host, - uint16_t cert_pub_key_type, uint32_t cert_pub_key_len, uint8_t *cert_pub_key) +void main_channel_push_migrate_begin(Channel *channel, int port, int sport, + char *host, uint16_t cert_pub_key_type, uint32_t cert_pub_key_len, + uint8_t *cert_pub_key) { MainChannel *main_chan = channel->data; - RedsOutItem *item = new_out_item(main_chan, SPICE_MSG_MAIN_MIGRATE_BEGIN); + MigrateBeginPipeItem *item = main_migrate_begin_item_new(main_chan, port, + sport, host, cert_pub_key_type, cert_pub_key_len, cert_pub_key); + + red_channel_pipe_add(&main_chan->base, &item->base); +} + +static void main_channel_marshall_migrate_begin(MainChannel *main_chan, + MigrateBeginPipeItem *item) +{ SpiceMsgMainMigrationBegin migrate; - migrate.port = port; - migrate.sport = sport; - migrate.host_size = strlen(host) + 1; - migrate.host_data = (uint8_t *)host; - migrate.pub_key_type = cert_pub_key_type; - migrate.pub_key_size = cert_pub_key_len; - migrate.pub_key_data = cert_pub_key; - spice_marshall_msg_main_migrate_begin(item->m, &migrate); - main_channel_push_pipe_item(main_chan, item); + migrate.port = item->port; + migrate.sport = item->sport; + migrate.host_size = strlen(item->host) + 1; + migrate.host_data = (uint8_t *)item->host; + migrate.pub_key_type = item->cert_pub_key_type; + migrate.pub_key_size = item->cert_pub_key_len; + migrate.pub_key_data = item->cert_pub_key; + spice_marshall_msg_main_migrate_begin(main_chan->base.send_data.marshaller, + &migrate); } void main_channel_push_migrate(Channel *channel) { - RedsOutItem *item; - SpiceMsgMigrate migrate; MainChannel *main_chan = channel->data; + RedsOutItem *item = main_pipe_item_new(main_chan, SPICE_MSG_MIGRATE); + + red_channel_pipe_add(&main_chan->base, &item->base); +} + +static void main_channel_marshall_migrate(MainChannel *main_chan) +{ + SpiceMsgMigrate migrate; - item = new_out_item(main_chan, SPICE_MSG_MIGRATE); migrate.flags = SPICE_MIGRATE_NEED_FLUSH | SPICE_MIGRATE_NEED_DATA_TRANSFER; - spice_marshall_msg_migrate(item->m, &migrate); - main_channel_push_pipe_item(main_chan, item); + spice_marshall_msg_migrate(main_chan->base.send_data.marshaller, &migrate); } void main_channel_push_migrate_cancel(Channel *channel) { MainChannel *main_chan = channel->data; - RedsOutItem *item = new_out_item(main_chan, SPICE_MSG_MAIN_MIGRATE_CANCEL); + RedsOutItem *item = main_pipe_item_new(main_chan, + SPICE_MSG_MAIN_MIGRATE_CANCEL); - main_channel_push_pipe_item(main_chan, item); + red_channel_pipe_add(&main_chan->base, &item->base); } void main_channel_push_multi_media_time(Channel *channel, int time) { - SpiceMsgMainMultiMediaTime time_mes; - RedsOutItem *item; MainChannel *main_chan = channel->data; - item = new_out_item(main_chan, SPICE_MSG_MAIN_MULTI_MEDIA_TIME); - time_mes.time = time; - spice_marshall_msg_main_multi_media_time(item->m, &time_mes); - main_channel_push_pipe_item(main_chan, item); + MultiMediaTimePipeItem *item = + main_multi_media_time_item_new(main_chan, time); + red_channel_pipe_add(&main_chan->base, &item->base); +} + +static PipeItem *main_migrate_switch_item_new(MainChannel *main_chan) +{ + PipeItem *item = spice_malloc(sizeof(*item)); + + red_channel_pipe_item_init(&main_chan->base, item, + SPICE_MSG_MAIN_MIGRATE_SWITCH_HOST); + return item; } void main_channel_push_migrate_switch(Channel *channel) { + MainChannel *main_chan = channel->data; + + red_channel_pipe_add(&main_chan->base, + main_migrate_switch_item_new(main_chan)); +} + +static void main_channel_marshall_migrate_switch(MainChannel *main_chan) +{ SpiceMsgMainMigrationSwitchHost migrate; - RedsOutItem *item; - MainChannel *main_chan; - - if (!channel) { - return; - } - main_chan = channel->data; + red_printf(""); - item = new_out_item(main_chan, SPICE_MSG_MAIN_MIGRATE_SWITCH_HOST); + reds_fill_mig_switch(&migrate); - spice_marshall_msg_main_migrate_switch_host(item->m, &migrate); - main_channel_push_pipe_item(main_chan, item); + spice_marshall_msg_main_migrate_switch_host( + main_chan->base.send_data.marshaller, &migrate); + reds_mig_release(); } -static void main_channel_handle_message(void *opaque, size_t size, uint32_t type, void *message) +static void main_channel_marshall_multi_media_time(MainChannel *main_chan, + MultiMediaTimePipeItem *item) +{ + SpiceMsgMainMultiMediaTime time_mes; + + time_mes.time = item->time; + spice_marshall_msg_main_multi_media_time( + main_chan->base.send_data.marshaller, &time_mes); +} + +static void main_channel_send_item(RedChannel *channel, PipeItem *base) +{ + MainChannel *main_chan = SPICE_CONTAINEROF(channel, MainChannel, base); + + red_channel_reset_send_data(channel); + red_channel_init_send_data(channel, base->type, base); + switch (base->type) { + case SPICE_MSG_MAIN_CHANNELS_LIST: + main_channel_marshall_channels(main_chan); + break; + case SPICE_MSG_PING: + main_channel_marshall_ping(main_chan, + SPICE_CONTAINEROF(base, PingPipeItem, base)->size); + break; + case SPICE_MSG_MAIN_MOUSE_MODE: + { + MouseModePipeItem *item = + SPICE_CONTAINEROF(base, MouseModePipeItem, base); + main_channel_marshall_mouse_mode(main_chan, + item->current_mode, item->is_client_mouse_allowed); + break; + } + case SPICE_MSG_MAIN_AGENT_DISCONNECTED: + main_channel_marshall_agent_disconnected(main_chan); + break; + case SPICE_MSG_MAIN_AGENT_TOKEN: + main_channel_marshall_tokens(main_chan, + SPICE_CONTAINEROF(base, TokensPipeItem, base)->tokens); + break; + case SPICE_MSG_MAIN_AGENT_DATA: + main_channel_marshall_agent_data(main_chan, + SPICE_CONTAINEROF(base, AgentDataPipeItem, base)); + break; + case SPICE_MSG_MIGRATE_DATA: + main_channel_marshall_migrate_data_item(main_chan); + break; + case SPICE_MSG_MAIN_INIT: + main_channel_marshall_init(main_chan, + SPICE_CONTAINEROF(base, InitPipeItem, base)); + break; + case SPICE_MSG_NOTIFY: + main_channel_marshall_notify(main_chan, + SPICE_CONTAINEROF(base, NotifyPipeItem, base)); + break; + case SPICE_MSG_MIGRATE: + main_channel_marshall_migrate(main_chan); + break; + case SPICE_MSG_MAIN_MIGRATE_BEGIN: + main_channel_marshall_migrate_begin(main_chan, + SPICE_CONTAINEROF(base, MigrateBeginPipeItem, base)); + break; + case SPICE_MSG_MAIN_MULTI_MEDIA_TIME: + main_channel_marshall_multi_media_time(main_chan, + SPICE_CONTAINEROF(base, MultiMediaTimePipeItem, base)); + break; + case SPICE_MSG_MAIN_MIGRATE_SWITCH_HOST: + main_channel_marshall_migrate_switch(main_chan); + break; + }; + red_channel_begin_send_message(channel); +} + +static void main_channel_release_pipe_item(RedChannel *channel, + PipeItem *base, int item_pushed) +{ + free(base); +} + +static int main_channel_handle_parsed(RedChannel *channel, size_t size, uint32_t type, void *message) { - MainChannel *main_chan = opaque; + MainChannel *main_chan = SPICE_CONTAINEROF(channel, MainChannel, base); switch (type) { case SPICE_MSGC_MAIN_AGENT_START: red_printf("agent start"); if (!main_chan) { - return; + return FALSE; } reds_on_main_agent_start(main_chan); break; @@ -650,28 +751,29 @@ static void main_channel_handle_message(void *opaque, size_t size, uint32_t type default: red_printf("unexpected type %d", type); } + return TRUE; } -static void main_channel_event(int fd, int event, void *data) +static void main_channel_on_error(RedChannel *channel) { - MainChannel *main_chan = data; + reds_disconnect(); +} - if (event & SPICE_WATCH_EVENT_READ) { - if (handle_incoming(main_chan->peer, &main_chan->in_handler)) { - main_disconnect(main_chan); - reds_disconnect(); - } - } - if (event & SPICE_WATCH_EVENT_WRITE) { - RedsOutgoingData *outgoing = &main_chan->outgoing; - if (main_channel_send_data(main_chan)) { - main_channel_push(main_chan); - if (!outgoing->item && main_chan->peer) { - core->watch_update_mask(main_chan->peer->watch, - SPICE_WATCH_EVENT_READ); - } - } - } +static uint8_t *main_channel_alloc_msg_rcv_buf(RedChannel *channel, SpiceDataHeader *msg_header) +{ + MainChannel *main_chan = SPICE_CONTAINEROF(channel, MainChannel, base); + + return main_chan->recv_buf; +} + +static void main_channel_release_msg_rcv_buf(RedChannel *channel, SpiceDataHeader *msg_header, + uint8_t *msg) +{ +} + +static int main_channel_config_socket(RedChannel *channel) +{ + return TRUE; } static void main_channel_link(Channel *channel, RedsStreamContext *peer, int migration, @@ -679,41 +781,44 @@ static void main_channel_link(Channel *channel, RedsStreamContext *peer, int mig uint32_t *caps) { MainChannel *main_chan; - - main_chan = spice_malloc0(sizeof(MainChannel)); + red_printf(""); + ASSERT(channel->data == NULL); + + main_chan = (MainChannel*)red_channel_create_parser( + sizeof(*main_chan), peer, 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_send_item + ,main_channel_release_pipe_item + ,main_channel_on_error + ,main_channel_on_error); + ASSERT(main_chan); channel->data = main_chan; - main_chan->peer = peer; - main_chan->in_handler.shut = FALSE; - main_chan->in_handler.parser = spice_get_client_channel_parser(SPICE_CHANNEL_MAIN, NULL); - main_chan->in_handler.opaque = main_chan; - main_chan->in_handler.handle_message = main_channel_handle_message; - ring_init(&main_chan->outgoing.pipe); - main_chan->outgoing.vec = main_chan->outgoing.vec_buf; - peer->watch = core->watch_add(peer->socket, - SPICE_WATCH_EVENT_READ, - main_channel_event, main_chan); } int main_channel_getsockname(Channel *channel, struct sockaddr *sa, socklen_t *salen) { MainChannel *main_chan = channel->data; - return main_chan ? getsockname(main_chan->peer->socket, sa, salen) : -1; + return main_chan ? getsockname(main_chan->base.peer->socket, sa, salen) : -1; } int main_channel_getpeername(Channel *channel, struct sockaddr *sa, socklen_t *salen) { MainChannel *main_chan = channel->data; - return main_chan ? getpeername(main_chan->peer->socket, sa, salen) : -1; + return main_chan ? getpeername(main_chan->base.peer->socket, sa, salen) : -1; } void main_channel_close(Channel *channel) { MainChannel *main_chan = channel->data; - if (main_chan && main_chan->peer) { - close(main_chan->peer->socket); + if (main_chan && main_chan->base.peer) { + close(main_chan->base.peer->socket); } } @@ -722,9 +827,8 @@ static void main_channel_shutdown(Channel *channel) MainChannel *main_chan = channel->data; if (main_chan != NULL) { - main_disconnect(main_chan); // TODO - really here? reset peer etc. + main_disconnect(main_chan); } - free(main_chan); } static void main_channel_migrate() |