mirror of
https://gitlab.uni-freiburg.de/opensourcevdi/spice
synced 2026-01-07 11:55:10 +00:00
server: set & test channel capabilities in red_channel
The code for setting and testing channel capabilities was unnecessarily duplicated. Now it is in red_channel. RedsChannel was dropped from Reds; It was used only for holding the channels common capabilities, which are now held in RedChannel.
This commit is contained in:
parent
bd8771adbc
commit
0bf518cd3d
@ -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);
|
||||
}
|
||||
|
||||
@ -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;
|
||||
}
|
||||
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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);
|
||||
}
|
||||
|
||||
|
||||
@ -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. */
|
||||
|
||||
@ -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;
|
||||
|
||||
@ -9449,7 +9449,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;
|
||||
|
||||
|
||||
149
server/reds.c
149
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;
|
||||
|
||||
@ -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);
|
||||
}
|
||||
|
||||
|
||||
@ -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;
|
||||
}
|
||||
|
||||
@ -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;
|
||||
}
|
||||
|
||||
Loading…
Reference in New Issue
Block a user