[Spice-devel] [PATCH spice-server 12/14] smartcard: creating SmartCardChannelClient type

Yonit Halperin yhalperi at redhat.com
Wed Jun 27 08:16:50 PDT 2012


The lifetime of the channel is not necessarily correlated to the life
time of the device. In the next patch, we need to keep a reference
to SpiceCharDeviceWriteBuffer, which might be in use even if the
SpiceCharDeviceState is destroyed, but the channel is still connected.
The next patch keeps this reference inside SmartCardChannelClient.

This patch also removes the routine smartcard_readers_detach_all(rcc), which
is unnecessary since we don't support multiple readers; even when
we do support them, each channel client should be associated with only
one reader (i.e., we will have different channels for different
readers).
---
 server/smartcard.c |  106 +++++++++++++++++++++++++++------------------------
 1 files changed, 56 insertions(+), 50 deletions(-)

diff --git a/server/smartcard.c b/server/smartcard.c
index 3b326da..0a2ab75 100644
--- a/server/smartcard.c
+++ b/server/smartcard.c
@@ -39,6 +39,13 @@
  */
 #define SMARTCARD_MAX_READERS 10
 
+typedef struct SmartCardDeviceState SmartCardDeviceState;
+
+typedef struct SmartCardChannelClient {
+    RedChannelClient base;
+    SmartCardDeviceState *smartcard_state;
+} SmartCardChannelClient;
+
 typedef struct SmartCardDeviceState {
     SpiceCharDeviceState *chardev_st;
     uint32_t             reader_id;
@@ -48,7 +55,8 @@ typedef struct SmartCardDeviceState {
     uint32_t             buf_size;
     uint8_t             *buf_pos;
     uint32_t             buf_used;
-    RedChannelClient    *rcc; // client providing the remote card
+
+    SmartCardChannelClient    *scc; // client providing the remote card
 } SmartCardDeviceState;
 
 enum {
@@ -87,8 +95,7 @@ static SpiceCharDeviceInstance* smartcard_readers_get_unattached(void);
 static SpiceCharDeviceInstance* smartcard_readers_get(uint32_t reader_id);
 static int smartcard_char_device_add_to_readers(SpiceCharDeviceInstance *sin);
 static void smartcard_char_device_attach(
-    SpiceCharDeviceInstance *char_device, RedChannelClient *rcc);
-static void smartcard_char_device_detach(SpiceCharDeviceInstance *char_device);
+    SpiceCharDeviceInstance *char_device, SmartCardChannelClient *scc);
 static void smartcard_channel_write_to_reader(VSCMsgHeader *vheader);
 
 static MsgItem *smartcard_char_device_on_message_from_device(
@@ -155,9 +162,8 @@ static void smartcard_send_msg_to_client(SpiceCharDeviceMsgToClient *msg,
                                          void *opaque)
 {
     SmartCardDeviceState *dev = opaque;
-
-    spice_assert(dev->rcc && dev->rcc->client == client);
-    smartcard_channel_client_pipe_add_push(dev->rcc, &((MsgItem *)msg)->base);
+    spice_assert(dev->scc && dev->scc->base.client == client);
+    smartcard_channel_client_pipe_add_push(&dev->scc->base, &((MsgItem *)msg)->base);
 
 }
 
@@ -171,8 +177,8 @@ static void smartcard_remove_client(RedClient *client, void *opaque)
     SmartCardDeviceState *dev = opaque;
 
     spice_printerr("smartcard  state %p, client %p", dev, client);
-    spice_assert(dev->rcc && dev->rcc->client == client);
-    red_channel_client_shutdown(dev->rcc);
+    spice_assert(dev->scc && dev->scc->base.client == client);
+    red_channel_client_shutdown(&dev->scc->base);
 }
 
 MsgItem *smartcard_char_device_on_message_from_device(SmartCardDeviceState *state,
@@ -194,30 +200,16 @@ MsgItem *smartcard_char_device_on_message_from_device(SmartCardDeviceState *stat
     if (state->reader_id == VSCARD_UNDEFINED_READER_ID && vheader->type != VSC_Init) {
         spice_printerr("error: reader_id not assigned for message of type %d", vheader->type);
     }
-    if (state->rcc) {
+    if (state->scc) {
         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;
-        return smartcard_get_vsc_msg_item(state->rcc, sent_header);
+        return smartcard_get_vsc_msg_item(&state->scc->base, sent_header);
     }
     return NULL;
 }
 
-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) {
-        st = spice_char_device_state_opaque_get(g_smartcard_readers.sin[i]->st);
-        if (!rcc || st->rcc == rcc) {
-            smartcard_char_device_detach(g_smartcard_readers.sin[i]);
-        }
-    }
-}
-
 static int smartcard_char_device_add_to_readers(SpiceCharDeviceInstance *char_device)
 {
     SmartCardDeviceState *state = spice_char_device_state_opaque_get(char_device->st);
@@ -237,6 +229,8 @@ static SpiceCharDeviceInstance *smartcard_readers_get(uint32_t reader_id)
     return g_smartcard_readers.sin[reader_id];
 }
 
+/* TODO: fix implementation for multiple readers. Each reader should have a separated
+ * channel */
 static SpiceCharDeviceInstance *smartcard_readers_get_unattached(void)
 {
     int i;
@@ -275,12 +269,15 @@ static SmartCardDeviceState *smartcard_device_state_new(SpiceCharDeviceInstance
     st->buf = spice_malloc(st->buf_size);
     st->buf_pos = st->buf;
     st->buf_used = 0;
-    st->rcc = NULL;
+    st->scc = NULL;
     return st;
 }
 
 static void smartcard_device_state_free(SmartCardDeviceState* st)
 {
+    if (st->scc) {
+        st->scc->smartcard_state = NULL;
+    }
     free(st->buf);
     spice_char_device_state_destroy(st->chardev_st);
     free(st);
@@ -306,38 +303,42 @@ SpiceCharDeviceState *smartcard_device_connect(SpiceCharDeviceInstance *char_dev
 }
 
 static void smartcard_char_device_attach(SpiceCharDeviceInstance *char_device,
-                                         RedChannelClient *rcc)
+                                         SmartCardChannelClient *scc)
 {
     SmartCardDeviceState *st = spice_char_device_state_opaque_get(char_device->st);
 
 
+    spice_assert(!scc->smartcard_state);
     if (st->attached == TRUE) {
         return;
     }
     st->attached = TRUE;
-    st->rcc = rcc;
+    st->scc = scc;
     spice_char_device_client_add(st->chardev_st,
-                                 rcc->client,
+                                 scc->base.client,
                                  FALSE, /* no flow control yet */
                                  0, /* send queue size */
                                  ~0,
                                  ~0);
+    scc->smartcard_state = st;
     VSCMsgHeader vheader = {.type = VSC_ReaderAdd, .reader_id=st->reader_id,
         .length=0};
     smartcard_channel_write_to_reader(&vheader);
 }
 
-static void smartcard_char_device_detach(SpiceCharDeviceInstance *char_device)
+static void smartcard_char_device_detach_client(SmartCardChannelClient *scc)
 {
-    SmartCardDeviceState *st = spice_char_device_state_opaque_get(char_device->st);
+    SmartCardDeviceState *st;
 
-    if (st->attached == FALSE) {
+    if (!scc->smartcard_state) {
         return;
     }
-    spice_assert(st->rcc);
-    spice_char_device_client_remove(st->chardev_st, st->rcc->client);
+    st = scc->smartcard_state;
+    spice_assert(st->scc == scc);
+    spice_char_device_client_remove(st->chardev_st, scc->base.client);
+    scc->smartcard_state = NULL;
     st->attached = FALSE;
-    st->rcc = NULL;
+    st->scc = NULL;
     VSCMsgHeader vheader = {.type = VSC_ReaderRemove, .reader_id=st->reader_id,
         .length=0};
     smartcard_channel_write_to_reader(&vheader);
@@ -419,7 +420,7 @@ static void smartcard_channel_release_pipe_item(RedChannelClient *rcc,
 
 static void smartcard_channel_on_disconnect(RedChannelClient *rcc)
 {
-    smartcard_readers_detach_all(rcc);
+    smartcard_char_device_detach_client(SPICE_CONTAINEROF(rcc, SmartCardChannelClient, base));
 }
 
 /* this is called from both device input and client input. since the device is
@@ -470,39 +471,40 @@ static void smartcard_unref_vsc_msg_item(MsgItem *item)
     }
 }
 
-static void smartcard_remove_reader(RedChannelClient *rcc, uint32_t reader_id)
+static void smartcard_remove_reader(SmartCardChannelClient *scc, uint32_t reader_id)
 {
     SpiceCharDeviceInstance *char_device = smartcard_readers_get(reader_id);
     SmartCardDeviceState *state;
 
     if (char_device == NULL) {
-        smartcard_push_error(rcc, reader_id,
+        smartcard_push_error(&scc->base, reader_id,
             VSC_GENERAL_ERROR);
         return;
     }
 
     state = spice_char_device_state_opaque_get(char_device->st);
     if (state->attached == FALSE) {
-        smartcard_push_error(rcc, reader_id,
+        smartcard_push_error(&scc->base, reader_id,
             VSC_GENERAL_ERROR);
         return;
     }
-    smartcard_char_device_detach(char_device);
+    spice_assert(scc->smartcard_state == state);
+    smartcard_char_device_detach_client(scc);
 }
 
-static void smartcard_add_reader(RedChannelClient *rcc, uint8_t *name)
+static void smartcard_add_reader(SmartCardChannelClient *scc, uint8_t *name)
 {
     // TODO - save name somewhere
     SpiceCharDeviceInstance *char_device =
             smartcard_readers_get_unattached();
 
     if (char_device != NULL) {
-        smartcard_char_device_attach(char_device, rcc);
+        smartcard_char_device_attach(char_device, scc);
         // The device sends a VSC_Error message, we will let it through, no
         // need to send our own. We already set the correct reader_id, from
         // our SmartCardDeviceState.
     } else {
-        smartcard_push_error(rcc, VSCARD_UNDEFINED_READER_ID,
+        smartcard_push_error(&scc->base, VSCARD_UNDEFINED_READER_ID,
             VSC_CANNOT_ADD_MORE_READERS);
     }
 }
@@ -533,6 +535,7 @@ static int smartcard_channel_handle_message(RedChannelClient *rcc,
                                             uint8_t *msg)
 {
     VSCMsgHeader* vheader = (VSCMsgHeader*)msg;
+    SmartCardChannelClient *scc = SPICE_CONTAINEROF(rcc, SmartCardChannelClient, base);
 
     if (type != SPICE_MSGC_SMARTCARD_DATA) {
         /* handle ack's, spicy sends them while spicec does not */
@@ -542,11 +545,11 @@ static int smartcard_channel_handle_message(RedChannelClient *rcc,
     spice_assert(size == vheader->length + sizeof(VSCMsgHeader));
     switch (vheader->type) {
         case VSC_ReaderAdd:
-            smartcard_add_reader(rcc, msg + sizeof(VSCMsgHeader));
+            smartcard_add_reader(scc, msg + sizeof(VSCMsgHeader));
             return TRUE;
             break;
         case VSC_ReaderRemove:
-            smartcard_remove_reader(rcc, vheader->reader_id);
+            smartcard_remove_reader(scc, vheader->reader_id);
             return TRUE;
             break;
         case VSC_Init:
@@ -581,15 +584,18 @@ static void smartcard_connect(RedChannel *channel, RedClient *client,
                         int num_common_caps, uint32_t *common_caps,
                         int num_caps, uint32_t *caps)
 {
-    RedChannelClient *rcc;
+    SmartCardChannelClient *scc;
 
-    rcc = red_channel_client_create(sizeof(RedChannelClient), channel, client, stream,
-                                    num_common_caps, common_caps,
-                                    num_caps, caps);
-    if (!rcc) {
+    scc = (SmartCardChannelClient *)red_channel_client_create(sizeof(SmartCardChannelClient),
+                                                              channel,
+                                                              client,
+                                                              stream,
+                                                              num_common_caps, common_caps,
+                                                              num_caps, caps);
+    if (!scc) {
         return;
     }
-    red_channel_client_ack_zero_messages_window(rcc);
+    red_channel_client_ack_zero_messages_window(&scc->base);
 }
 
 static void smartcard_migrate(RedChannelClient *rcc)
-- 
1.7.7.6



More information about the Spice-devel mailing list