mirror of
https://gitlab.uni-freiburg.de/opensourcevdi/spice
synced 2025-12-27 07:29:32 +00:00
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:
parent
9aa62c4baa
commit
eded227f4c
@ -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)
|
||||
|
||||
Loading…
Reference in New Issue
Block a user