[Spice-devel] [RFCv5 22/47] server/smartcard: support multiple clients
Alon Levy
alevy at redhat.com
Sun May 8 06:11:18 PDT 2011
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.
---
server/smartcard.c | 82 +++++++++++++++++++++++++++++-----------------------
1 files changed, 46 insertions(+), 36 deletions(-)
diff --git a/server/smartcard.c b/server/smartcard.c
index 48072a3..aa5cc36 100644
--- a/server/smartcard.c
+++ b/server/smartcard.c
@@ -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
@@ -135,21 +135,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]);
+ }
}
}
@@ -259,7 +264,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;
}
@@ -340,24 +345,25 @@ 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)
{
- free(item);
if (item->type == PIPE_ITEM_TYPE_MSG) {
free(((MsgItem*)item)->vheader);
}
+ 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);
}
@@ -366,19 +372,21 @@ static void smartcard_push_error(RedChannelClient *rcc, uint32_t reader_id, VSCE
{
ErrorItem *error_item = spice_new0(ErrorItem, 1);
- error_item->base.type = PIPE_ITEM_TYPE_ERROR;
+ red_channel_pipe_item_init(rcc->channel, &error_item->base,
+ PIPE_ITEM_TYPE_ERROR);
error_item->reader_id = reader_id;
error_item->error = 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)
@@ -487,21 +495,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,
@@ -511,13 +518,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)
--
1.7.5.1
More information about the Spice-devel
mailing list