[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