diff options
Diffstat (limited to 'server/reds.c')
-rw-r--r-- | server/reds.c | 149 |
1 files changed, 52 insertions, 97 deletions
diff --git a/server/reds.c b/server/reds.c index 65c98aef..31e255f4 100644 --- a/server/reds.c +++ b/server/reds.c @@ -192,14 +192,6 @@ typedef struct RedsStatValue { typedef struct RedsMigSpice RedsMigSpice; -typedef struct RedsChannel { - struct RedsChannel *next; - RedChannel *base; - - int num_common_caps; - uint32_t *common_caps; -} RedsChannel; - typedef struct RedsState { int listen_socket; int secure_listen_socket; @@ -217,7 +209,7 @@ typedef struct RedsState { int mig_target; RedsMigSpice *mig_spice; int num_of_channels; - RedsChannel *channels; + Ring channels; int mouse_mode; int is_client_mouse_allowed; int dispatcher_allows_client_mouse; @@ -302,7 +294,6 @@ struct ChannelSecurityOptions { ChannelSecurityOptions *next; }; -static void reds_dispose_channel(RedsChannel *channel); static ChannelSecurityOptions *channels_security = NULL; static int default_channel_security = @@ -515,42 +506,32 @@ void reds_update_stat_value(uint32_t value) void reds_register_channel(RedChannel *channel) { - RedsChannel *reds_channel; - ASSERT(reds); - // TODO: should channels be released upon some destructor? - reds_channel = spice_malloc0(sizeof(RedsChannel)); - reds_channel->base = channel; - reds_channel->next = reds->channels; - reds->channels = reds_channel; + ring_add(&reds->channels, &channel->link); reds->num_of_channels++; } void reds_unregister_channel(RedChannel *channel) { - RedsChannel **now = &reds->channels; - - while (*now) { - if ((*now)->base == channel) { - RedsChannel *free_channel = *now; - *now = free_channel->next; - reds_dispose_channel(free_channel); - free(free_channel); - reds->num_of_channels--; - return; - } - now = &(*now)->next; + if (ring_item_is_linked(&channel->link)) { + ring_remove(&channel->link); + reds->num_of_channels--; + } else { + red_printf("not found"); } - red_printf("not found"); } -static RedsChannel *reds_find_channel(uint32_t type, uint32_t id) +static RedChannel *reds_find_channel(uint32_t type, uint32_t id) { - RedsChannel *channel = reds->channels; - while (channel && !(channel->base->type == type && channel->base->id == id)) { - channel = channel->next; + RingItem *now; + + RING_FOREACH(now, &reds->channels) { + RedChannel *channel = SPICE_CONTAINEROF(now, RedChannel, link); + if (channel->type == type && channel->id == id) { + return channel; + } } - return channel; + return NULL; } static void reds_mig_cleanup(void) @@ -987,11 +968,11 @@ SPICE_GNUC_VISIBLE int spice_server_get_num_clients(SpiceServer *s) static int secondary_channels[] = { SPICE_CHANNEL_MAIN, SPICE_CHANNEL_DISPLAY, SPICE_CHANNEL_CURSOR, SPICE_CHANNEL_INPUTS}; -static int channel_is_secondary(RedsChannel *channel) +static int channel_is_secondary(RedChannel *channel) { int i; for (i = 0 ; i < sizeof(secondary_channels)/sizeof(secondary_channels[0]); ++i) { - if (channel->base->type == secondary_channels[i]) { + if (channel->type == secondary_channels[i]) { return TRUE; } } @@ -1000,21 +981,20 @@ static int channel_is_secondary(RedsChannel *channel) void reds_fill_channels(SpiceMsgChannels *channels_info) { - RedsChannel *channel; - int i; + RingItem *now; int used_channels = 0; channels_info->num_of_channels = reds->num_of_channels; - channel = reds->channels; - for (i = 0; i < reds->num_of_channels; i++, channel = channel->next) { - ASSERT(channel); + RING_FOREACH(now, &reds->channels) { + RedChannel *channel = SPICE_CONTAINEROF(now, RedChannel, link); if (reds->num_clients > 1 && !channel_is_secondary(channel)) { continue; } - channels_info->channels[used_channels].type = channel->base->type; - channels_info->channels[used_channels].id = channel->base->id; + channels_info->channels[used_channels].type = channel->type; + channels_info->channels[used_channels].id = channel->id; used_channels++; } + channels_info->num_of_channels = used_channels; if (used_channels != reds->num_of_channels) { red_printf("sent %d out of %d", used_channels, reds->num_of_channels); @@ -1388,46 +1368,22 @@ static int sync_write(RedsStream *stream, const void *in_buf, size_t n) return TRUE; } -static void reds_channel_set_common_caps(RedsChannel *channel, int cap, int active) -{ - int nbefore, n; - - nbefore = channel->num_common_caps; - n = cap / 32; - channel->num_common_caps = MAX(channel->num_common_caps, n + 1); - channel->common_caps = spice_renew(uint32_t, channel->common_caps, channel->num_common_caps); - memset(channel->common_caps + nbefore, 0, - (channel->num_common_caps - nbefore) * sizeof(uint32_t)); - if (active) { - channel->common_caps[n] |= (1 << cap); - } else { - channel->common_caps[n] &= ~(1 << cap); - } -} - -static void reds_channel_init_auth_caps(RedsChannel *channel) +static void reds_channel_init_auth_caps(RedChannel *channel) { if (sasl_enabled) { - reds_channel_set_common_caps(channel, SPICE_COMMON_CAP_AUTH_SASL, TRUE); + red_channel_set_common_cap(channel, SPICE_COMMON_CAP_AUTH_SASL); } else { - reds_channel_set_common_caps(channel, SPICE_COMMON_CAP_AUTH_SPICE, TRUE); + red_channel_set_common_cap(channel, SPICE_COMMON_CAP_AUTH_SPICE); } - reds_channel_set_common_caps(channel, SPICE_COMMON_CAP_PROTOCOL_AUTH_SELECTION, TRUE); -} - -static void reds_dispose_channel(RedsChannel *channel) -{ - free(channel->common_caps); - channel->common_caps = NULL; - channel->num_common_caps = 0; + red_channel_set_common_cap(channel, SPICE_COMMON_CAP_PROTOCOL_AUTH_SELECTION); } static int reds_send_link_ack(RedLinkInfo *link) { SpiceLinkHeader header; SpiceLinkReply ack; - RedsChannel common_caps = { 0, }; - RedsChannel *channel; + RedChannel *channel; + RedChannelCapabilities *channel_caps; BUF_MEM *bmBuf; BIO *bio; int ret = FALSE; @@ -1441,13 +1397,16 @@ static int reds_send_link_ack(RedLinkInfo *link) channel = reds_find_channel(link->link_mess->channel_type, 0); if (!channel) { - channel = &common_caps; + ASSERT(link->link_mess->channel_type == SPICE_CHANNEL_MAIN); + ASSERT(reds->main_channel); + channel = &reds->main_channel->base; } reds_channel_init_auth_caps(channel); /* make sure common caps are set */ - ack.num_common_caps = channel->num_common_caps; - ack.num_channel_caps = channel->base ? channel->base->num_caps : 0; + channel_caps = &channel->local_caps; + ack.num_common_caps = channel_caps->num_common_caps; + ack.num_channel_caps = channel_caps->num_caps; header.size += (ack.num_common_caps + ack.num_channel_caps) * sizeof(uint32_t); ack.caps_offset = sizeof(SpiceLinkReply); @@ -1473,17 +1432,14 @@ static int reds_send_link_ack(RedLinkInfo *link) goto end; if (!sync_write(link->stream, &ack, sizeof(ack))) goto end; - if (!sync_write(link->stream, channel->common_caps, channel->num_common_caps * sizeof(uint32_t))) + if (!sync_write(link->stream, channel_caps->common_caps, channel_caps->num_common_caps * sizeof(uint32_t))) + goto end; + if (!sync_write(link->stream, channel_caps->caps, channel_caps->num_caps * sizeof(uint32_t))) goto end; - if (channel->base) { - if (!sync_write(link->stream, channel->base->caps, channel->base->num_caps * sizeof(uint32_t))) - goto end; - } ret = TRUE; end: - reds_dispose_channel(&common_caps); BIO_free(bio); return ret; } @@ -1542,6 +1498,8 @@ static void reds_handle_main_link(RedLinkInfo *link) MainChannelClient *mcc; red_printf(""); + ASSERT(reds->main_channel); + link_mess = link->link_mess; if (!reds->allow_multiple_clients) { reds_disconnect(); @@ -1576,10 +1534,6 @@ static void reds_handle_main_link(RedLinkInfo *link) link->link_mess = NULL; reds_link_free(link); caps = (uint32_t *)((uint8_t *)link_mess + link_mess->caps_offset); - if (!reds->main_channel) { - reds->main_channel = main_channel_init(); - ASSERT(reds->main_channel); - } client = red_client_new(); ring_add(&reds->clients, &client->link); reds->num_clients++; @@ -1645,7 +1599,7 @@ static void openssl_init(RedLinkInfo *link) static void reds_handle_other_links(RedLinkInfo *link) { - RedsChannel *channel; + RedChannel *channel; RedClient *client = NULL; RedsStream *stream; SpiceLinkMess *link_mess; @@ -1687,12 +1641,12 @@ static void reds_handle_other_links(RedLinkInfo *link) link->link_mess = NULL; reds_link_free(link); caps = (uint32_t *)((uint8_t *)link_mess + link_mess->caps_offset); - channel->base->client_cbs.connect(channel->base, client, stream, reds->mig_target, - link_mess->num_common_caps, - link_mess->num_common_caps ? caps : NULL, - link_mess->num_channel_caps, - link_mess->num_channel_caps ? - caps + link_mess->num_common_caps : NULL); + channel->client_cbs.connect(channel, client, stream, reds->mig_target, + link_mess->num_common_caps, + link_mess->num_common_caps ? caps : NULL, + link_mess->num_channel_caps, + link_mess->num_channel_caps ? + caps + link_mess->num_common_caps : NULL); free(link_mess); } @@ -2459,8 +2413,8 @@ static void reds_handle_read_link_done(void *opaque) return; } - auth_selection = link_mess->num_common_caps > 0 && - (caps[0] & (1 << SPICE_COMMON_CAP_PROTOCOL_AUTH_SELECTION));; + auth_selection = test_capabilty(caps, link_mess->num_common_caps, + SPICE_COMMON_CAP_PROTOCOL_AUTH_SELECTION); if (!reds_security_check(link)) { if (link->stream->ssl) { @@ -3521,6 +3475,7 @@ static int do_spice_init(SpiceCoreInterface *core_interface) ring_init(&reds->clients); reds->num_clients = 0; main_dispatcher_init(core); + ring_init(&reds->channels); if (!(reds->mig_timer = core->timer_add(migrate_timout, NULL))) { red_error("migration timer create failed"); @@ -3577,7 +3532,7 @@ static int do_spice_init(SpiceCoreInterface *core_interface) } #endif - reds->main_channel = NULL; + reds->main_channel = main_channel_init(); inputs_init(); reds->mouse_mode = SPICE_MOUSE_MODE_SERVER; |