diff options
author | Alon Levy <alevy@redhat.com> | 2011-04-11 23:58:52 +0300 |
---|---|---|
committer | Alon Levy <alevy@redhat.com> | 2011-08-23 18:00:19 +0300 |
commit | eded227f4c95667bee72ca994a107493eefa7f20 (patch) | |
tree | 3ef40a9d2b7fa88b0aef50bc829e0b5c74ca030b /server/smartcard.c | |
parent | 9aa62c4baa50321c123b8809fb5bbee00734777d (diff) | |
download | spice-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.c | 80 |
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) |