summaryrefslogtreecommitdiffstats
path: root/server/smartcard.c
diff options
context:
space:
mode:
authorAlon Levy <alevy@redhat.com>2011-04-11 23:58:52 +0300
committerAlon Levy <alevy@redhat.com>2011-08-23 18:00:19 +0300
commiteded227f4c95667bee72ca994a107493eefa7f20 (patch)
tree3ef40a9d2b7fa88b0aef50bc829e0b5c74ca030b /server/smartcard.c
parent9aa62c4baa50321c123b8809fb5bbee00734777d (diff)
downloadspice-eded227f4c95667bee72ca994a107493eefa7f20.tar.gz
spice-eded227f4c95667bee72ca994a107493eefa7f20.tar.xz
spice-eded227f4c95667bee72ca994a107493eefa7f20.zip
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.
Diffstat (limited to 'server/smartcard.c')
-rw-r--r--server/smartcard.c80
1 files changed, 46 insertions, 34 deletions
diff --git a/server/smartcard.c b/server/smartcard.c
index 76ae6061..2a3332cc 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
@@ -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)