[Spice-devel] [PATCH migration 01/19] server: set & test channel capabilities in red_channel
Alon Levy
alevy at redhat.com
Mon Oct 31 23:44:58 PDT 2011
On Wed, Oct 12, 2011 at 12:38:51PM +0200, Yonit Halperin wrote:
> The code for setting and testing channel capabilities was
> unnecessarily duplicated. Now it is in red_channel.
>
Can you add to the commit message that you drop RedsChannel? no need
to split.
ACK with that.
> Signed-off-by: Yonit Halperin <yhalperi at redhat.com>
> ---
> server/inputs_channel.c | 4 +-
> server/main_channel.c | 27 ++++----
> server/main_channel.h | 20 ++++--
> server/red_channel.c | 94 ++++++++++++++++++++++++---
> server/red_channel.h | 33 ++++++++--
> server/red_tunnel_worker.c | 3 +-
> server/red_worker.c | 3 +-
> server/reds.c | 149 +++++++++++++++----------------------------
> server/smartcard.c | 4 +-
> server/snd_worker.c | 66 +++++++------------
> server/spicevmc.c | 4 +-
> 11 files changed, 226 insertions(+), 181 deletions(-)
>
> diff --git a/server/inputs_channel.c b/server/inputs_channel.c
> index 24fc621..c8b42e3 100644
> --- a/server/inputs_channel.c
> +++ b/server/inputs_channel.c
> @@ -496,7 +496,9 @@ static void inputs_connect(RedChannel *channel, RedClient *client,
> icc = (InputsChannelClient*)red_channel_client_create(sizeof(InputsChannelClient),
> channel,
> client,
> - stream);
> + stream,
> + num_common_caps, common_caps,
> + num_caps, caps);
> icc->motion_count = 0;
> inputs_pipe_add_init(&icc->base);
> }
> diff --git a/server/main_channel.c b/server/main_channel.c
> index 43c0f3f..49028b3 100644
> --- a/server/main_channel.c
> +++ b/server/main_channel.c
> @@ -39,17 +39,13 @@
> #include "server/demarshallers.h"
> #include "common/ring.h"
> #include "common/messages.h"
> -#include "reds.h"
> #include "main_channel.h"
> +#include "reds.h"
> #include "red_channel.h"
> #include "generated_marshallers.h"
>
> #define ZERO_BUF_SIZE 4096
>
> -// approximate max receive message size for main channel
> -#define RECEIVE_BUF_SIZE \
> - (4096 + (REDS_AGENT_WINDOW_SIZE + REDS_NUM_INTERNAL_AGENT_MESSAGES) * SPICE_AGENT_MAX_DATA_SIZE)
> -
> #define REDS_MAX_SEND_IOVEC 100
>
> #define NET_TEST_WARMUP_BYTES 0
> @@ -143,11 +139,6 @@ struct MainChannelClient {
> #endif
> };
>
> -struct MainChannel {
> - RedChannel base;
> - uint8_t recv_buf[RECEIVE_BUF_SIZE];
> -};
> -
> enum NetTestStage {
> NET_TEST_STAGE_INVALID,
> NET_TEST_STAGE_WARMUP,
> @@ -911,12 +902,18 @@ uint32_t main_channel_client_get_link_id(MainChannelClient *mcc)
> return mcc->connection_id;
> }
>
> -MainChannelClient *main_channel_client_create(MainChannel *main_chan, RedClient *client,
> - RedsStream *stream, uint32_t connection_id)
> +static MainChannelClient *main_channel_client_create(MainChannel *main_chan, RedClient *client,
> + RedsStream *stream, uint32_t connection_id,
> + int num_common_caps, uint32_t *common_caps,
> + int num_caps, uint32_t *caps)
> {
> MainChannelClient *mcc = (MainChannelClient*)red_channel_client_create(sizeof(MainChannelClient),
> &main_chan->base,
> - client, stream);
> + client, stream,
> + num_common_caps,
> + common_caps,
> + num_caps,
> + caps);
>
> mcc->connection_id = connection_id;
> mcc->bitrate_per_sec = ~0;
> @@ -942,7 +939,9 @@ MainChannelClient *main_channel_link(MainChannel *channel, RedClient *client,
> // into usage somewhere (not an issue until we return migration to it's
> // former glory)
> red_printf("add main channel client");
> - mcc = main_channel_client_create(channel, client, stream, connection_id);
> + mcc = main_channel_client_create(channel, client, stream, connection_id,
> + num_common_caps, common_caps,
> + num_caps, caps);
> return mcc;
> }
>
> diff --git a/server/main_channel.h b/server/main_channel.h
> index 713bcd0..2ae05e8 100644
> --- a/server/main_channel.h
> +++ b/server/main_channel.h
> @@ -45,7 +45,20 @@ struct MainMigrateData {
> uint32_t write_queue_size;
> };
>
> -typedef struct MainChannel MainChannel;
> +// TODO: Defines used to calculate receive buffer size, and also by reds.c
> +// other options: is to make a reds_main_consts.h, to duplicate defines.
> +#define REDS_AGENT_WINDOW_SIZE 10
> +#define REDS_NUM_INTERNAL_AGENT_MESSAGES 1
> +
> +// approximate max receive message size for main channel
> +#define RECEIVE_BUF_SIZE \
> + (4096 + (REDS_AGENT_WINDOW_SIZE + REDS_NUM_INTERNAL_AGENT_MESSAGES) * SPICE_AGENT_MAX_DATA_SIZE)
> +
> +typedef struct MainChannel {
> + RedChannel base;
> + uint8_t recv_buf[RECEIVE_BUF_SIZE];
> +} MainChannel;
> +
>
> MainChannel *main_channel_init(void);
> RedClient *main_channel_get_client_by_link_id(MainChannel *main_chan, uint32_t link_id);
> @@ -82,9 +95,4 @@ int main_channel_client_is_low_bandwidth(MainChannelClient *mcc);
> uint64_t main_channel_client_get_bitrate_per_sec(MainChannelClient *mcc);
> int main_channel_is_connected(MainChannel *main_chan);
>
> -// TODO: Defines used to calculate receive buffer size, and also by reds.c
> -// other options: is to make a reds_main_consts.h, to duplicate defines.
> -#define REDS_AGENT_WINDOW_SIZE 10
> -#define REDS_NUM_INTERNAL_AGENT_MESSAGES 1
> -
> #endif
> diff --git a/server/red_channel.c b/server/red_channel.c
> index 8993cc3..51415cb 100644
> --- a/server/red_channel.c
> +++ b/server/red_channel.c
> @@ -358,11 +358,43 @@ static void red_channel_add_client(RedChannel *channel, RedChannelClient *rcc)
> channel->clients_num++;
> }
>
> -RedChannelClient *red_channel_client_create(
> - int size,
> - RedChannel *channel,
> - RedClient *client,
> - RedsStream *stream)
> +static void red_channel_client_set_remote_caps(RedChannelClient* rcc,
> + int num_common_caps, uint32_t *common_caps,
> + int num_caps, uint32_t *caps)
> +{
> + rcc->remote_caps.num_common_caps = num_common_caps;
> + rcc->remote_caps.common_caps = spice_memdup(common_caps, num_common_caps * sizeof(uint32_t));
> +
> + rcc->remote_caps.num_caps = num_caps;
> + rcc->remote_caps.caps = spice_memdup(caps, num_caps * sizeof(uint32_t));
> +}
> +
> +static void red_channel_client_destroy_remote_caps(RedChannelClient* rcc)
> +{
> + rcc->remote_caps.num_common_caps = 0;
> + free(rcc->remote_caps.common_caps);
> + rcc->remote_caps.num_caps = 0;
> + free(rcc->remote_caps.caps);
> +}
> +
> +int red_channel_client_test_remote_common_cap(RedChannelClient *rcc, uint32_t cap)
> +{
> + return test_capabilty(rcc->remote_caps.common_caps,
> + rcc->remote_caps.num_common_caps,
> + cap);
> +}
> +
> +int red_channel_client_test_remote_cap(RedChannelClient *rcc, uint32_t cap)
> +{
> + return test_capabilty(rcc->remote_caps.caps,
> + rcc->remote_caps.num_caps,
> + cap);
> +}
> +
> +RedChannelClient *red_channel_client_create(int size, RedChannel *channel, RedClient *client,
> + RedsStream *stream,
> + int num_common_caps, uint32_t *common_caps,
> + int num_caps, uint32_t *caps)
> {
> RedChannelClient *rcc;
>
> @@ -384,6 +416,9 @@ RedChannelClient *red_channel_client_create(
> rcc->outgoing.cb = &channel->outgoing_cb;
> rcc->outgoing.pos = 0;
> rcc->outgoing.size = 0;
> +
> + red_channel_client_set_remote_caps(rcc, num_common_caps, common_caps, num_caps, caps);
> +
> if (!channel->channel_cbs.config_socket(rcc)) {
> goto error;
> }
> @@ -564,10 +599,36 @@ void red_channel_register_client_cbs(RedChannel *channel, ClientCbs *client_cbs)
> }
> }
>
> -void red_channel_set_caps(RedChannel *channel, int num_caps, uint32_t *caps)
> +int test_capabilty(uint32_t *caps, int num_caps, uint32_t cap)
> {
> - channel->num_caps = num_caps;
> - channel->caps = caps;
> + uint32_t index = cap / 32;
> + if (num_caps < index + 1) {
> + return FALSE;
> + }
> +
> + return (caps[index] & (1 << (cap % 32))) != 0;
> +}
> +
> +static void add_capability(uint32_t **caps, int *num_caps, uint32_t cap)
> +{
> + int nbefore, n;
> +
> + nbefore = *num_caps;
> + n = cap / 32;
> + *num_caps = MAX(*num_caps, n + 1);
> + *caps = spice_renew(uint32_t, *caps, *num_caps);
> + memset(*caps + nbefore, 0, (*num_caps - nbefore) * sizeof(uint32_t));
> + (*caps)[n] |= (1 << (cap % 32));
> +}
> +
> +void red_channel_set_common_cap(RedChannel *channel, uint32_t cap)
> +{
> + add_capability(&channel->local_caps.common_caps, &channel->local_caps.num_common_caps, cap);
> +}
> +
> +void red_channel_set_cap(RedChannel *channel, uint32_t cap)
> +{
> + add_capability(&channel->local_caps.caps, &channel->local_caps.num_caps, cap);
> }
>
> void red_channel_set_data(RedChannel *channel, void *data)
> @@ -585,6 +646,7 @@ void red_channel_client_destroy(RedChannelClient *rcc)
> if (rcc->send_data.marshaller) {
> spice_marshaller_destroy(rcc->send_data.marshaller);
> }
> + red_channel_client_destroy_remote_caps(rcc);
> free(rcc);
> }
>
> @@ -600,9 +662,15 @@ void red_channel_destroy(RedChannel *channel)
> red_channel_client_destroy(
> SPICE_CONTAINEROF(link, RedChannelClient, channel_link));
> }
> - if (channel->caps) {
> - free(channel->caps);
> +
> + if (channel->local_caps.num_common_caps) {
> + free(channel->local_caps.common_caps);
> + }
> +
> + if (channel->local_caps.num_caps) {
> + free(channel->local_caps.caps);
> }
> +
> free(channel);
> }
>
> @@ -979,7 +1047,9 @@ void red_channel_disconnect(RedChannel *channel)
>
> RedChannelClient *red_channel_client_create_dummy(int size,
> RedChannel *channel,
> - RedClient *client)
> + RedClient *client,
> + int num_common_caps, uint32_t *common_caps,
> + int num_caps, uint32_t *caps)
> {
> RedChannelClient *rcc;
>
> @@ -987,6 +1057,7 @@ RedChannelClient *red_channel_client_create_dummy(int size,
> rcc = spice_malloc0(size);
> rcc->client = client;
> rcc->channel = channel;
> + red_channel_client_set_remote_caps(rcc, num_common_caps, common_caps, num_caps, caps);
> red_channel_add_client(channel, rcc);
> return rcc;
> }
> @@ -994,6 +1065,7 @@ RedChannelClient *red_channel_client_create_dummy(int size,
> void red_channel_client_destroy_dummy(RedChannelClient *rcc)
> {
> red_channel_remove_client(rcc);
> + red_channel_client_destroy_remote_caps(rcc);
> free(rcc);
> }
>
> diff --git a/server/red_channel.h b/server/red_channel.h
> index 2ebb6b6..d044253 100644
> --- a/server/red_channel.h
> +++ b/server/red_channel.h
> @@ -143,7 +143,7 @@ typedef uint64_t (*channel_handle_migrate_data_get_serial_proc)(RedChannelClient
>
>
> typedef void (*channel_client_connect_proc)(RedChannel *channel, RedClient *client, RedsStream *stream,
> - int migration, int num_common_caps, uint32_t *common_caps,
> + int migration, int num_common_cap, uint32_t *common_caps,
> int num_caps, uint32_t *caps);
> typedef void (*channel_client_disconnect_proc)(RedChannelClient *base);
> typedef void (*channel_client_migrate_proc)(RedChannelClient *base);
> @@ -178,6 +178,15 @@ typedef struct {
> channel_client_migrate_proc migrate;
> } ClientCbs;
>
> +typedef struct RedChannelCapabilities {
> + int num_common_caps;
> + uint32_t *common_caps;
> + int num_caps;
> + uint32_t *caps;
> +} RedChannelCapabilities;
> +
> +int test_capabilty(uint32_t *caps, int num_caps, uint32_t cap);
> +
> struct RedChannelClient {
> RingItem channel_link;
> RingItem client_link;
> @@ -206,12 +215,16 @@ struct RedChannelClient {
> int id; // debugging purposes
> Ring pipe;
> uint32_t pipe_size;
> +
> + RedChannelCapabilities remote_caps;
> };
>
> struct RedChannel {
> uint32_t type;
> uint32_t id;
>
> + RingItem link; // channels link for reds
> +
> SpiceCoreInterface *core;
> int migrate;
> int handle_acks;
> @@ -232,8 +245,7 @@ struct RedChannel {
> ChannelCbs channel_cbs;
> ClientCbs client_cbs;
>
> - int num_caps;
> - uint32_t *caps;
> + RedChannelCapabilities local_caps;
>
> void *data;
>
> @@ -265,19 +277,23 @@ RedChannel *red_channel_create_parser(int size,
>
> void red_channel_register_client_cbs(RedChannel *channel, ClientCbs *client_cbs);
> // caps are freed when the channel is destroyed
> -void red_channel_set_caps(RedChannel *channel, int num_caps, uint32_t *caps);
> +void red_channel_set_common_cap(RedChannel *channel, uint32_t cap);
> +void red_channel_set_cap(RedChannel *channel, uint32_t cap);
> void red_channel_set_data(RedChannel *channel, void *data);
>
> RedChannelClient *red_channel_client_create(int size, RedChannel *channel, RedClient *client,
> - RedsStream *stream);
> -
> + RedsStream *stream,
> + int num_common_caps, uint32_t *common_caps,
> + int num_caps, uint32_t *caps);
> // TODO: tmp, for channels that don't use RedChannel yet (e.g., snd channel), but
> // do use the client callbacks. So the channel clients are not connected (the channel doesn't
> // have list of them, but they do have a link to the channel, and the client has a list of them)
> RedChannel *red_channel_create_dummy(int size, uint32_t type, uint32_t id);
> RedChannelClient *red_channel_client_create_dummy(int size,
> RedChannel *channel,
> - RedClient *client);
> + RedClient *client,
> + int num_common_caps, uint32_t *common_caps,
> + int num_caps, uint32_t *caps);
> void red_channel_client_destroy_dummy(RedChannelClient *rcc);
>
>
> @@ -294,6 +310,9 @@ int red_channel_client_is_connected(RedChannelClient *rcc);
> void red_channel_client_destroy(RedChannelClient *rcc);
> void red_channel_destroy(RedChannel *channel);
>
> +int red_channel_client_test_remote_common_cap(RedChannelClient *rcc, uint32_t cap);
> +int red_channel_client_test_remote_cap(RedChannelClient *rcc, uint32_t cap);
> +
> /* shutdown is the only safe thing to do out of the client/channel
> * thread. It will not touch the rings, just shutdown the socket.
> * It should be followed by some way to gurantee a disconnection. */
> diff --git a/server/red_tunnel_worker.c b/server/red_tunnel_worker.c
> index 6c36fec..1e8267e 100644
> --- a/server/red_tunnel_worker.c
> +++ b/server/red_tunnel_worker.c
> @@ -3445,7 +3445,8 @@ static void handle_tunnel_channel_link(RedChannel *channel, RedClient *client,
> }
>
> tcc = (TunnelChannelClient*)red_channel_client_create(sizeof(TunnelChannelClient),
> - channel, client, stream);
> + channel, client, stream,
> + 0, NULL, 0, NULL);
>
> tcc->worker = worker;
> tcc->worker->channel_client = tcc;
> diff --git a/server/red_worker.c b/server/red_worker.c
> index 7af715d..0f91259 100644
> --- a/server/red_worker.c
> +++ b/server/red_worker.c
> @@ -9452,7 +9452,8 @@ static CommonChannelClient *common_channel_client_create(int size,
> {
> MainChannelClient *mcc = red_client_get_main(client);
> RedChannelClient *rcc =
> - red_channel_client_create(size, &common->base, client, stream);
> + red_channel_client_create(size, &common->base, client, stream,
> + 0, NULL, 0, NULL);
> CommonChannelClient *common_cc = (CommonChannelClient*)rcc;
> common_cc->worker = common->worker;
>
> diff --git a/server/reds.c b/server/reds.c
> index 90779ff..ff609ce 100644
> --- a/server/reds.c
> +++ b/server/reds.c
> @@ -191,14 +191,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;
> @@ -216,7 +208,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;
> @@ -301,7 +293,6 @@ struct ChannelSecurityOptions {
> ChannelSecurityOptions *next;
> };
>
> -static void reds_dispose_channel(RedsChannel *channel);
>
> static ChannelSecurityOptions *channels_security = NULL;
> static int default_channel_security =
> @@ -514,42 +505,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)
> @@ -986,11 +967,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;
> }
> }
> @@ -999,21 +980,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);
> @@ -1387,46 +1367,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;
> @@ -1440,13 +1396,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);
>
> @@ -1472,17 +1431,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;
> }
> @@ -1541,6 +1497,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();
> @@ -1575,10 +1533,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++;
> @@ -1644,7 +1598,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;
> @@ -1686,12 +1640,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);
> }
>
> @@ -2458,8 +2412,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) {
> @@ -3519,6 +3473,7 @@ static int do_spice_init(SpiceCoreInterface *core_interface)
> init_vd_agent_resources();
> ring_init(&reds->clients);
> reds->num_clients = 0;
> + ring_init(&reds->channels);
>
> if (!(reds->mig_timer = core->timer_add(migrate_timout, NULL))) {
> red_error("migration timer create failed");
> @@ -3575,7 +3530,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;
> diff --git a/server/smartcard.c b/server/smartcard.c
> index 056caa6..f9cafdf 100644
> --- a/server/smartcard.c
> +++ b/server/smartcard.c
> @@ -493,7 +493,9 @@ static void smartcard_connect(RedChannel *channel, RedClient *client,
> {
> RedChannelClient *rcc;
>
> - rcc = red_channel_client_create(sizeof(RedChannelClient), channel, client, stream);
> + rcc = red_channel_client_create(sizeof(RedChannelClient), channel, client, stream,
> + num_common_caps, common_caps,
> + num_caps, caps);
> red_channel_client_ack_zero_messages_window(rcc);
> }
>
> diff --git a/server/snd_worker.c b/server/snd_worker.c
> index 98f3cd1..048da34 100644
> --- a/server/snd_worker.c
> +++ b/server/snd_worker.c
> @@ -118,8 +118,6 @@ struct SndChannel {
> snd_channel_handle_message_proc handle_message;
> snd_channel_on_message_done_proc on_message_done;
> snd_channel_cleanup_channel_proc cleanup;
> - int num_caps;
> - uint32_t *caps;
> };
>
> typedef struct AudioFrame AudioFrame;
> @@ -196,18 +194,6 @@ static uint32_t playback_compression = SPICE_AUDIO_DATA_MODE_CELT_0_5_1;
>
> static void snd_receive(void* data);
>
> -static int check_cap(uint32_t *caps, int num_caps, uint32_t cap)
> -{
> - uint32_t i = cap / 32;
> -
> - cap = 1 << (cap % 32);
> - if (i >= num_caps) {
> - return FALSE;
> - }
> -
> - return caps[i] & cap;
> -}
> -
> static SndChannel *snd_channel_get(SndChannel *channel)
> {
> channel->refs++;
> @@ -239,7 +225,6 @@ static void snd_disconnect_channel(SndChannel *channel)
> channel->stream->watch = NULL;
> reds_stream_free(channel->stream);
> spice_marshaller_destroy(channel->send_data.marshaller);
> - free(channel->caps);
> snd_channel_put(channel);
> }
>
> @@ -579,8 +564,10 @@ static int snd_playback_send_volume(PlaybackChannel *playback_channel)
> SndChannel *channel = &playback_channel->base;
> SpicePlaybackState *st = SPICE_CONTAINEROF(channel->worker, SpicePlaybackState, worker);
>
> - if (!check_cap(channel->caps, channel->num_caps, SPICE_PLAYBACK_CAP_VOLUME))
> + if (!red_channel_client_test_remote_cap(channel->channel_client,
> + SPICE_PLAYBACK_CAP_VOLUME)) {
> return TRUE;
> + }
>
> return snd_send_volume(channel, &st->volume, SPICE_MSG_PLAYBACK_VOLUME);
> }
> @@ -603,8 +590,10 @@ static int snd_playback_send_mute(PlaybackChannel *playback_channel)
> SndChannel *channel = &playback_channel->base;
> SpicePlaybackState *st = SPICE_CONTAINEROF(channel->worker, SpicePlaybackState, worker);
>
> - if (!check_cap(channel->caps, channel->num_caps, SPICE_PLAYBACK_CAP_VOLUME))
> + if (!red_channel_client_test_remote_cap(channel->channel_client,
> + SPICE_PLAYBACK_CAP_VOLUME)) {
> return TRUE;
> + }
>
> return snd_send_mute(channel, &st->volume, SPICE_MSG_PLAYBACK_MUTE);
> }
> @@ -695,8 +684,10 @@ static int snd_record_send_volume(RecordChannel *record_channel)
> SndChannel *channel = &record_channel->base;
> SpiceRecordState *st = SPICE_CONTAINEROF(channel->worker, SpiceRecordState, worker);
>
> - if (!check_cap(channel->caps, channel->num_caps, SPICE_RECORD_CAP_VOLUME))
> + if (!red_channel_client_test_remote_cap(channel->channel_client,
> + SPICE_RECORD_CAP_VOLUME)) {
> return TRUE;
> + }
>
> return snd_send_volume(channel, &st->volume, SPICE_MSG_RECORD_VOLUME);
> }
> @@ -706,8 +697,10 @@ static int snd_record_send_mute(RecordChannel *record_channel)
> SndChannel *channel = &record_channel->base;
> SpiceRecordState *st = SPICE_CONTAINEROF(channel->worker, SpiceRecordState, worker);
>
> - if (!check_cap(channel->caps, channel->num_caps, SPICE_RECORD_CAP_VOLUME))
> + if (!red_channel_client_test_remote_cap(channel->channel_client,
> + SPICE_RECORD_CAP_VOLUME)) {
> return TRUE;
> + }
>
> return snd_send_mute(channel, &st->volume, SPICE_MSG_RECORD_MUTE);
> }
> @@ -941,12 +934,12 @@ static SndChannel *__new_channel(SndWorker *worker, int size, uint32_t channel_i
> channel->handle_message = handle_message;
> channel->on_message_done = on_message_done;
> channel->cleanup = cleanup;
> - channel->num_caps = num_caps;
> - channel->caps = spice_memdup(caps, num_caps * sizeof(uint32_t));
>
> channel->channel_client = red_channel_client_create_dummy(sizeof(RedChannelClient),
> worker->base_channel,
> - client);
> + client,
> + 0, NULL,
> + num_caps, caps);
> return channel;
>
> error2:
> @@ -1140,6 +1133,7 @@ static void snd_set_playback_peer(RedChannel *channel, RedClient *client, RedsSt
> CELTEncoder *celt_encoder;
> CELTMode *celt_mode;
> int celt_error;
> + RedChannelClient *rcc;
>
> snd_disconnect_channel(worker->connection);
>
> @@ -1169,13 +1163,15 @@ static void snd_set_playback_peer(RedChannel *channel, RedClient *client, RedsSt
> goto error_2;
> }
> worker->connection = &playback_channel->base;
> + rcc = playback_channel->base.channel_client;
> snd_playback_free_frame(playback_channel, &playback_channel->frames[0]);
> snd_playback_free_frame(playback_channel, &playback_channel->frames[1]);
> snd_playback_free_frame(playback_channel, &playback_channel->frames[2]);
>
> playback_channel->celt_mode = celt_mode;
> playback_channel->celt_encoder = celt_encoder;
> - playback_channel->mode = check_cap(caps, num_caps, SPICE_PLAYBACK_CAP_CELT_0_5_1) ?
> + playback_channel->mode = red_channel_client_test_remote_cap(rcc,
> + SPICE_PLAYBACK_CAP_CELT_0_5_1) ?
> playback_compression : SPICE_AUDIO_DATA_MODE_RAW;
>
> on_new_playback_channel(worker);
> @@ -1431,8 +1427,6 @@ static void remove_worker(SndWorker *worker)
> void snd_attach_playback(SpicePlaybackInstance *sin)
> {
> SndWorker *playback_worker;
> - int num_caps;
> - uint32_t *caps;
> RedChannel *channel;
> ClientCbs client_cbs = {0,};
>
> @@ -1449,12 +1443,8 @@ void snd_attach_playback(SpicePlaybackInstance *sin)
> client_cbs.migrate = snd_playback_migrate_channel_client;
> red_channel_register_client_cbs(channel, &client_cbs);
> red_channel_set_data(channel, playback_worker);
> -
> - num_caps = 1;
> - caps = spice_new(uint32_t, 1);
> - caps[0] = (1 << SPICE_PLAYBACK_CAP_CELT_0_5_1) |
> - (1 << SPICE_PLAYBACK_CAP_VOLUME);
> - red_channel_set_caps(channel, num_caps, caps);
> + red_channel_set_cap(channel, SPICE_PLAYBACK_CAP_CELT_0_5_1);
> + red_channel_set_cap(channel, SPICE_PLAYBACK_CAP_VOLUME);
>
> playback_worker->base_channel = channel;
> add_worker(playback_worker);
> @@ -1464,8 +1454,6 @@ void snd_attach_playback(SpicePlaybackInstance *sin)
> void snd_attach_record(SpiceRecordInstance *sin)
> {
> SndWorker *record_worker;
> - int num_caps;
> - uint32_t *caps;
> RedChannel *channel;
> ClientCbs client_cbs = {0,};
>
> @@ -1482,12 +1470,8 @@ void snd_attach_record(SpiceRecordInstance *sin)
> client_cbs.migrate = snd_record_migrate_channel_client;
> red_channel_register_client_cbs(channel, &client_cbs);
> red_channel_set_data(channel, record_worker);
> -
> - num_caps = 1;
> - caps = spice_new(uint32_t, 1);
> - caps[0] = (1 << SPICE_RECORD_CAP_CELT_0_5_1) |
> - (1 << SPICE_RECORD_CAP_VOLUME);
> - red_channel_set_caps(channel, num_caps, caps);
> + red_channel_set_cap(channel, SPICE_RECORD_CAP_CELT_0_5_1);
> + red_channel_set_cap(channel, SPICE_RECORD_CAP_VOLUME);
>
> record_worker->base_channel = channel;
> add_worker(record_worker);
> @@ -1538,8 +1522,8 @@ void snd_set_playback_compression(int on)
> if (now->base_channel->type == SPICE_CHANNEL_PLAYBACK && now->connection) {
> SndChannel* sndchannel = now->connection;
> PlaybackChannel* playback = (PlaybackChannel*)now->connection;
> - if (!check_cap(sndchannel->caps, sndchannel->num_caps,
> - SPICE_PLAYBACK_CAP_CELT_0_5_1)) {
> + if (!red_channel_client_test_remote_cap(sndchannel->channel_client,
> + SPICE_PLAYBACK_CAP_CELT_0_5_1)) {
> ASSERT(playback->mode == SPICE_AUDIO_DATA_MODE_RAW);
> continue;
> }
> diff --git a/server/spicevmc.c b/server/spicevmc.c
> index 9ccc0d1..8580984 100644
> --- a/server/spicevmc.c
> +++ b/server/spicevmc.c
> @@ -206,7 +206,9 @@ static void spicevmc_connect(RedChannel *channel, RedClient *client,
> return;
> }
>
> - rcc = red_channel_client_create(sizeof(RedChannelClient), channel, client, stream);
> + rcc = red_channel_client_create(sizeof(RedChannelClient), channel, client, stream,
> + num_common_caps, common_caps,
> + num_caps, caps);
> if (!rcc) {
> return;
> }
> --
> 1.7.6.4
>
More information about the Spice-devel
mailing list