server/smartcard: support multiple clients

each client supplying a smartcard channel gets it's own smartcard. If
there are not enough smartcards provided by the server (read: qemu)
then it will be as though there are none.

currently disabled - later patches that enable smartcard don't make
this channel available to any but the first client.
This commit is contained in:
Alon Levy 2011-04-11 23:58:52 +03:00
parent 9aa62c4baa
commit eded227f4c

View File

@ -21,10 +21,10 @@
#include <arpa/inet.h>
#include <vscard_common.h>
#include "server/char_device.h"
#include "server/red_channel.h"
#include "server/smartcard.h"
#include "vscard_common.h"
#define SMARTCARD_MAX_READERS 10
@ -136,21 +136,26 @@ void smartcard_char_device_on_message_from_device(
if (state->reader_id == VSCARD_UNDEFINED_READER_ID && vheader->type != VSC_Init) {
red_printf("error: reader_id not assigned for message of type %d", vheader->type);
}
sent_header = spice_memdup(vheader, sizeof(*vheader) + vheader->length);
/* We patch the reader_id, since the device only knows about itself, and
* we know about the sum of readers. */
sent_header->reader_id = state->reader_id;
if (state->rcc) {
sent_header = spice_memdup(vheader, sizeof(*vheader) + vheader->length);
/* We patch the reader_id, since the device only knows about itself, and
* we know about the sum of readers. */
sent_header->reader_id = state->reader_id;
smartcard_on_message_from_device(state->rcc, sent_header);
}
}
static void smartcard_readers_detach_all(SmartCardChannel *smartcard_channel)
static void smartcard_readers_detach_all(RedChannelClient *rcc)
{
int i;
SmartCardDeviceState *st;
// TODO - can track rcc->{sin}
for (i = 0 ; i < g_smartcard_readers.num; ++i) {
smartcard_char_device_detach(g_smartcard_readers.sin[i]);
st = SPICE_CONTAINEROF(g_smartcard_readers.sin[i]->st, SmartCardDeviceState, base);
if (!rcc || st->rcc == rcc) {
smartcard_char_device_detach(g_smartcard_readers.sin[i]);
}
}
}
@ -261,7 +266,7 @@ static void smartcard_char_device_detach(SpiceCharDeviceInstance *char_device)
smartcard_channel_write_to_reader(&vheader);
}
static int smartcard_channel_config_socket(RedChannelClient *rcc)
static int smartcard_channel_client_config_socket(RedChannelClient *rcc)
{
return TRUE;
}
@ -323,7 +328,8 @@ static void smartcard_channel_send_item(RedChannelClient *rcc, PipeItem *item)
}
static void smartcard_channel_release_pipe_item(RedChannelClient *rcc, PipeItem *item, int item_pushed)
static void smartcard_channel_release_pipe_item(RedChannelClient *rcc,
PipeItem *item, int item_pushed)
{
if (item->type == PIPE_ITEM_TYPE_MSG) {
free(((MsgItem*)item)->vheader);
@ -331,16 +337,16 @@ static void smartcard_channel_release_pipe_item(RedChannelClient *rcc, PipeItem
free(item);
}
static void smartcard_channel_disconnect(RedChannelClient *rcc)
static void smartcard_channel_client_disconnect(RedChannelClient *rcc)
{
smartcard_readers_detach_all((SmartCardChannel*)(rcc->channel));
smartcard_readers_detach_all(rcc);
red_channel_client_destroy(rcc);
}
/* this is called from both device input and client input. since the device is
* a usb device, the context is still the main thread (kvm_main_loop, timers)
* so no mutex is required. */
static void smartcard_channel_pipe_add_push(RedChannelClient *rcc, PipeItem *item)
static void smartcard_channel_client_pipe_add_push(RedChannelClient *rcc, PipeItem *item)
{
red_channel_client_pipe_add_push(rcc, item);
}
@ -349,21 +355,25 @@ static void smartcard_push_error(RedChannelClient *rcc, uint32_t reader_id, VSCE
{
ErrorItem *error_item = spice_new0(ErrorItem, 1);
red_channel_pipe_item_init(rcc->channel, &error_item->base,
PIPE_ITEM_TYPE_ERROR);
error_item->base.type = PIPE_ITEM_TYPE_ERROR;
error_item->vheader.reader_id = reader_id;
error_item->vheader.type = VSC_Error;
error_item->vheader.length = sizeof(error_item->error);
error_item->error.code = error;
smartcard_channel_pipe_add_push(rcc, &error_item->base);
smartcard_channel_client_pipe_add_push(rcc, &error_item->base);
}
static void smartcard_push_vscmsg(RedChannelClient *rcc, VSCMsgHeader *vheader)
{
MsgItem *msg_item = spice_new0(MsgItem, 1);
msg_item->base.type = PIPE_ITEM_TYPE_MSG;
red_channel_pipe_item_init(rcc->channel, &msg_item->base,
PIPE_ITEM_TYPE_MSG);
msg_item->vheader = vheader;
smartcard_channel_pipe_add_push(rcc, &msg_item->base);
smartcard_channel_client_pipe_add_push(rcc, &msg_item->base);
}
void smartcard_on_message_from_device(RedChannelClient *rcc, VSCMsgHeader* vheader)
@ -477,21 +487,20 @@ static void smartcard_channel_hold_pipe_item(RedChannelClient *rcc, PipeItem *it
{
}
static void smartcard_link(Channel *channel, RedClient *client, RedsStream *stream,
int migration, int num_common_caps,
uint32_t *common_caps, int num_caps,
uint32_t *caps)
static void smartcard_link(Channel *channel, RedClient *client,
RedsStream *stream, int migration,
int num_common_caps, uint32_t *common_caps,
int num_caps, uint32_t *caps)
{
if (channel->data) {
red_channel_destroy((RedChannel*)channel->data);
channel->data = NULL;
}
RedChannelClient *rcc;
if (!channel->data) {
channel->data = red_channel_create(sizeof(SmartCardChannel),
core,
migration, FALSE /* handle_acks */,
smartcard_channel_config_socket,
smartcard_channel_disconnect,
channel->data =
red_channel_create(sizeof(SmartCardChannel),
core, migration,
FALSE /* handle_acks */,
smartcard_channel_client_config_socket,
smartcard_channel_client_disconnect,
smartcard_channel_handle_message,
smartcard_channel_alloc_msg_rcv_buf,
smartcard_channel_release_msg_rcv_buf,
@ -501,13 +510,16 @@ static void smartcard_link(Channel *channel, RedClient *client, RedsStream *stre
NULL,
NULL,
NULL);
if (channel->data) {
red_channel_init_outgoing_messages_window((RedChannel*)channel->data);
} else {
red_printf("ERROR: smartcard channel creation failed");
return;
}
}
if (!channel->data) {
red_printf("ERROR: smartcard channel creation failed");
return;
}
red_channel_client_create(sizeof(RedChannelClient), channel->data, client, stream);
red_channel_init_outgoing_messages_window((RedChannel*)channel->data);
rcc = red_channel_client_create(sizeof(RedChannelClient),
(RedChannel*)channel->data, client, stream);
red_channel_client_ack_zero_messages_window(rcc);
}
static void smartcard_shutdown(Channel *channel)