From: Christophe Fergeau <cfergeau@xxxxxxxxxx> This inherits from RedCharDevice. Once all char device states are converted, we can turn the associated vfuncs into RedCharDeviceClass vfuncs. --- server/smartcard.c | 221 +++++++++++++++++++++++++++++------------------------ server/smartcard.h | 30 +++++++- 2 files changed, 150 insertions(+), 101 deletions(-) diff --git a/server/smartcard.c b/server/smartcard.c index c63fea3..fc27bfe 100644 --- a/server/smartcard.c +++ b/server/smartcard.c @@ -1,6 +1,6 @@ /* -*- Mode: C; c-basic-offset: 4; indent-tabs-mode: nil -*- */ /* - Copyright (C) 2010 Red Hat, Inc. + Copyright (C) 2010-2015 Red Hat, Inc. This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public @@ -49,7 +49,7 @@ // Maximal length of APDU #define APDUBufSize 270 -typedef struct SmartCardDeviceState SmartCardDeviceState; +typedef RedCharDeviceSmartcard SmartCardDeviceState; typedef struct SmartCardChannelClient { RedChannelClient base; @@ -62,7 +62,11 @@ typedef struct SmartCardChannelClient { * or was it explicitly malloced */ } SmartCardChannelClient; -struct SmartCardDeviceState { +G_DEFINE_TYPE(RedCharDeviceSmartcard, red_char_device_smartcard, RED_TYPE_CHAR_DEVICE) + +#define RED_CHAR_DEVICE_SMARTCARD_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), RED_TYPE_CHAR_DEVICE_SMARTCARD, RedCharDeviceSmartcardPrivate)) + +struct RedCharDeviceSmartcardPrivate { SpiceCharDeviceState *chardev_st; uint32_t reader_id; /* read_from_device buffer */ @@ -118,7 +122,6 @@ static void smartcard_channel_write_to_reader(SpiceCharDeviceWriteBuffer *write_ static MsgItem *smartcard_char_device_on_message_from_device( SmartCardDeviceState *state, VSCMsgHeader *header); static SmartCardDeviceState *smartcard_device_state_new(RedsState *reds, SpiceCharDeviceInstance *sin); -static void smartcard_device_state_free(SmartCardDeviceState* st); static void smartcard_init(RedsState *reds); static void smartcard_read_buf_prepare(SmartCardDeviceState *state, VSCMsgHeader *vheader) @@ -126,9 +129,9 @@ static void smartcard_read_buf_prepare(SmartCardDeviceState *state, VSCMsgHeader uint32_t msg_len; msg_len = ntohl(vheader->length); - if (msg_len > state->buf_size) { - state->buf_size = MAX(state->buf_size * 2, msg_len + sizeof(VSCMsgHeader)); - state->buf = spice_realloc(state->buf, state->buf_size); + if (msg_len > state->priv->buf_size) { + state->priv->buf_size = MAX(state->priv->buf_size * 2, msg_len + sizeof(VSCMsgHeader)); + state->priv->buf = spice_realloc(state->priv->buf, state->priv->buf_size); } } @@ -137,31 +140,31 @@ SpiceCharDeviceMsgToClient *smartcard_read_msg_from_device(SpiceCharDeviceInstan { SmartCardDeviceState *state = opaque; SpiceCharDeviceInterface *sif = spice_char_device_get_interface(sin); - VSCMsgHeader *vheader = (VSCMsgHeader*)state->buf; + VSCMsgHeader *vheader = (VSCMsgHeader*)state->priv->buf; int n; int remaining; int actual_length; - while ((n = sif->read(sin, state->buf_pos, state->buf_size - state->buf_used)) > 0) { + while ((n = sif->read(sin, state->priv->buf_pos, state->priv->buf_size - state->priv->buf_used)) > 0) { MsgItem *msg_to_client; - state->buf_pos += n; - state->buf_used += n; - if (state->buf_used < sizeof(VSCMsgHeader)) { + state->priv->buf_pos += n; + state->priv->buf_used += n; + if (state->priv->buf_used < sizeof(VSCMsgHeader)) { continue; } smartcard_read_buf_prepare(state, vheader); actual_length = ntohl(vheader->length); - if (state->buf_used - sizeof(VSCMsgHeader) < actual_length) { + if (state->priv->buf_used - sizeof(VSCMsgHeader) < actual_length) { continue; } msg_to_client = smartcard_char_device_on_message_from_device(state, vheader); - remaining = state->buf_used - sizeof(VSCMsgHeader) - actual_length; + remaining = state->priv->buf_used - sizeof(VSCMsgHeader) - actual_length; if (remaining > 0) { - memcpy(state->buf, state->buf_pos, remaining); + memcpy(state->priv->buf, state->priv->buf_pos, remaining); } - state->buf_pos = state->buf; - state->buf_used = remaining; + state->priv->buf_pos = state->priv->buf; + state->priv->buf_used = remaining; if (msg_to_client) { return msg_to_client; } @@ -186,8 +189,8 @@ static void smartcard_send_msg_to_client(SpiceCharDeviceMsgToClient *msg, void *opaque) { SmartCardDeviceState *dev = opaque; - spice_assert(dev->scc && dev->scc->base.client == client); - smartcard_channel_client_pipe_add_push(&dev->scc->base, &((MsgItem *)msg)->base); + spice_assert(dev->priv->scc && dev->priv->scc->base.client == client); + smartcard_channel_client_pipe_add_push(&dev->priv->scc->base, &((MsgItem *)msg)->base); } @@ -201,8 +204,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->scc && dev->scc->base.client == client); - red_channel_client_shutdown(&dev->scc->base); + spice_assert(dev->priv->scc && dev->priv->scc->base.client == client); + red_channel_client_shutdown(&dev->priv->scc->base); } MsgItem *smartcard_char_device_on_message_from_device(SmartCardDeviceState *state, @@ -221,15 +224,15 @@ MsgItem *smartcard_char_device_on_message_from_device(SmartCardDeviceState *stat break; } /* We pass any VSC_Error right now - might need to ignore some? */ - if (state->reader_id == VSCARD_UNDEFINED_READER_ID && vheader->type != VSC_Init) { + if (state->priv->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->scc) { + if (state->priv->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->scc->base, sent_header); + sent_header->reader_id = state->priv->reader_id; + return smartcard_get_vsc_msg_item(&state->priv->scc->base, sent_header); } return NULL; } @@ -241,7 +244,7 @@ static int smartcard_char_device_add_to_readers(RedsState *reds, SpiceCharDevice if (g_smartcard_readers.num >= SMARTCARD_MAX_READERS) { return -1; } - state->reader_id = g_smartcard_readers.num; + state->priv->reader_id = g_smartcard_readers.num; g_smartcard_readers.sin[g_smartcard_readers.num++] = char_device; smartcard_init(reds); return 0; @@ -262,7 +265,7 @@ static SpiceCharDeviceInstance *smartcard_readers_get_unattached(void) for (i = 0; i < g_smartcard_readers.num; ++i) { state = spice_char_device_state_opaque_get(g_smartcard_readers.sin[i]->st); - if (!state->scc) { + if (!state->priv->scc) { return g_smartcard_readers.sin[i]; } } @@ -271,48 +274,33 @@ static SpiceCharDeviceInstance *smartcard_readers_get_unattached(void) static SmartCardDeviceState *smartcard_device_state_new(RedsState *reds, SpiceCharDeviceInstance *sin) { - SmartCardDeviceState *st; - SpiceCharDeviceCallbacks chardev_cbs = { NULL, }; - - chardev_cbs.read_one_msg_from_device = smartcard_read_msg_from_device; - chardev_cbs.ref_msg_to_client = smartcard_ref_msg_to_client; - chardev_cbs.unref_msg_to_client = smartcard_unref_msg_to_client; - chardev_cbs.send_msg_to_client = smartcard_send_msg_to_client; - chardev_cbs.send_tokens_to_client = smartcard_send_tokens_to_client; - chardev_cbs.remove_client = smartcard_remove_client; - - st = spice_new0(SmartCardDeviceState, 1); - st->chardev_st = spice_char_device_state_create(sin, - reds, - 0, /* tokens interval */ - ~0, /* self tokens */ - &chardev_cbs, - st); - st->reader_id = VSCARD_UNDEFINED_READER_ID; - st->reader_added = FALSE; - st->buf_size = APDUBufSize + sizeof(VSCMsgHeader); - st->buf = spice_malloc(st->buf_size); - st->buf_pos = st->buf; - st->buf_used = 0; - 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); + RedCharDevice *char_dev; + SpiceCharDeviceCallbacks char_dev_cbs = { + .read_one_msg_from_device = smartcard_read_msg_from_device, + .ref_msg_to_client = smartcard_ref_msg_to_client, + .unref_msg_to_client = smartcard_unref_msg_to_client, + .send_msg_to_client = smartcard_send_msg_to_client, + .send_tokens_to_client = smartcard_send_tokens_to_client, + .remove_client = smartcard_remove_client, + }; + + char_dev = g_object_new(RED_TYPE_CHAR_DEVICE_SMARTCARD, + "sin", sin, + "spice-server", reds, + "client-tokens-interval", 0ULL, + "self-tokens", ~0ULL, + NULL); + + red_char_device_set_callbacks(RED_CHAR_DEVICE(char_dev), + &char_dev_cbs, char_dev); + return RED_CHAR_DEVICE_SMARTCARD(char_dev); } void smartcard_device_disconnect(SpiceCharDeviceInstance *char_device) { - SmartCardDeviceState *st = spice_char_device_state_opaque_get(char_device->st); + g_return_if_fail(RED_IS_CHAR_DEVICE_SMARTCARD(char_device)); - smartcard_device_state_free(st); + g_object_unref(char_device); } SpiceCharDeviceState *smartcard_device_connect(RedsState *reds, SpiceCharDeviceInstance *char_device) @@ -321,10 +309,10 @@ SpiceCharDeviceState *smartcard_device_connect(RedsState *reds, SpiceCharDeviceI st = smartcard_device_state_new(reds, char_device); if (smartcard_char_device_add_to_readers(reds, char_device) == -1) { - smartcard_device_state_free(st); + g_object_unref(st); return NULL; } - return st->chardev_st; + return RED_CHAR_DEVICE(st); } static void smartcard_char_device_notify_reader_add(SmartCardDeviceState *st) @@ -332,15 +320,15 @@ static void smartcard_char_device_notify_reader_add(SmartCardDeviceState *st) SpiceCharDeviceWriteBuffer *write_buf; VSCMsgHeader *vheader; - write_buf = spice_char_device_write_buffer_get(st->chardev_st, NULL, sizeof(vheader)); + write_buf = spice_char_device_write_buffer_get(RED_CHAR_DEVICE(st), NULL, sizeof(vheader)); if (!write_buf) { spice_error("failed to allocate write buffer"); return; } - st->reader_added = TRUE; + st->priv->reader_added = TRUE; vheader = (VSCMsgHeader *)write_buf->buf; vheader->type = VSC_ReaderAdd; - vheader->reader_id = st->reader_id; + vheader->reader_id = st->priv->reader_id; vheader->length = 0; smartcard_channel_write_to_reader(write_buf); } @@ -351,10 +339,10 @@ static void smartcard_char_device_attach_client(SpiceCharDeviceInstance *char_de SmartCardDeviceState *st = spice_char_device_state_opaque_get(char_device->st); int client_added; - spice_assert(!scc->smartcard_state && !st->scc); - st->scc = scc; + spice_assert(!scc->smartcard_state && !st->priv->scc); + st->priv->scc = scc; scc->smartcard_state = st; - client_added = spice_char_device_client_add(st->chardev_st, + client_added = spice_char_device_client_add(RED_CHAR_DEVICE(st), scc->base.client, FALSE, /* no flow control yet */ 0, /* send queue size */ @@ -364,7 +352,7 @@ static void smartcard_char_device_attach_client(SpiceCharDeviceInstance *char_de &scc->base)); if (!client_added) { spice_warning("failed"); - st->scc = NULL; + st->priv->scc = NULL; scc->smartcard_state = NULL; red_channel_client_disconnect(&scc->base); } @@ -375,19 +363,19 @@ static void smartcard_char_device_notify_reader_remove(SmartCardDeviceState *st) SpiceCharDeviceWriteBuffer *write_buf; VSCMsgHeader *vheader; - if (!st->reader_added) { + if (!st->priv->reader_added) { spice_debug("reader add was never sent to the device"); return; } - write_buf = spice_char_device_write_buffer_get(st->chardev_st, NULL, sizeof(vheader)); + write_buf = spice_char_device_write_buffer_get(RED_CHAR_DEVICE(st), NULL, sizeof(vheader)); if (!write_buf) { spice_error("failed to allocate write buffer"); return; } - st->reader_added = FALSE; + st->priv->reader_added = FALSE; vheader = (VSCMsgHeader *)write_buf->buf; vheader->type = VSC_ReaderRemove; - vheader->reader_id = st->reader_id; + vheader->reader_id = st->priv->reader_id; vheader->length = 0; smartcard_channel_write_to_reader(write_buf); } @@ -400,10 +388,10 @@ static void smartcard_char_device_detach_client(SmartCardChannelClient *scc) return; } st = scc->smartcard_state; - spice_assert(st->scc == scc); - spice_char_device_client_remove(st->chardev_st, scc->base.client); + spice_assert(st->priv->scc == scc); + spice_char_device_client_remove(st->priv->chardev_st, scc->base.client); scc->smartcard_state = NULL; - st->scc = NULL; + st->priv->scc = NULL; } static int smartcard_channel_client_config_socket(RedChannelClient *rcc) @@ -428,9 +416,9 @@ static uint8_t *smartcard_channel_alloc_msg_rcv_buf(RedChannelClient *rcc, spice_assert(g_smartcard_readers.num == 1); st = scc->smartcard_state; - spice_assert(st->scc || scc->smartcard_state); + spice_assert(st->priv->scc || scc->smartcard_state); spice_assert(!scc->write_buf); - scc->write_buf = spice_char_device_write_buffer_get(st->chardev_st, rcc->client, size); + scc->write_buf = spice_char_device_write_buffer_get(RED_CHAR_DEVICE(st), rcc->client, size); if (!scc->write_buf) { spice_error("failed to allocate write buffer"); @@ -456,11 +444,9 @@ static void smartcard_channel_release_msg_rcv_buf(RedChannelClient *rcc, spice_assert(!scc->write_buf); free(msg); } else { - SpiceCharDeviceState *dev_st; if (scc->write_buf) { /* msg hasn't been pushed to the guest */ spice_assert(scc->write_buf->buf == msg); - dev_st = scc->smartcard_state ? scc->smartcard_state->chardev_st : NULL; - spice_char_device_write_buffer_release(dev_st, scc->write_buf); + spice_char_device_write_buffer_release(RED_CHAR_DEVICE(scc->smartcard_state), scc->write_buf); scc->write_buf = NULL; } } @@ -514,12 +500,12 @@ static void smartcard_channel_send_migrate_data(RedChannelClient *rcc, spice_marshaller_add_uint32(m, 0); spice_debug("null char dev state"); } else { - spice_char_device_state_migrate_data_marshall(state->chardev_st, m); - spice_marshaller_add_uint8(m, state->reader_added); - spice_marshaller_add_uint32(m, state->buf_used); + spice_char_device_state_migrate_data_marshall(RED_CHAR_DEVICE(state), m); + spice_marshaller_add_uint8(m, state->priv->reader_added); + spice_marshaller_add_uint32(m, state->priv->buf_used); m2 = spice_marshaller_get_ptr_submarshaller(m, 0); - spice_marshaller_add(m2, state->buf, state->buf_used); - spice_debug("reader added %d partial read size %u", state->reader_added, state->buf_used); + spice_marshaller_add(m2, state->priv->buf, state->priv->buf_used); + spice_debug("reader added %d partial read size %u", state->priv->reader_added, state->priv->buf_used); } } @@ -625,7 +611,7 @@ static void smartcard_remove_reader(SmartCardChannelClient *scc, uint32_t reader } state = spice_char_device_state_opaque_get(char_device->st); - if (state->reader_added == FALSE) { + if (state->priv->reader_added == FALSE) { smartcard_push_error(&scc->base, reader_id, VSC_GENERAL_ERROR); return; @@ -666,7 +652,7 @@ static void smartcard_channel_write_to_reader(SpiceCharDeviceWriteBuffer *write_ spice_assert(vheader->reader_id <= g_smartcard_readers.num); sin = g_smartcard_readers.sin[vheader->reader_id]; st = (SmartCardDeviceState *)spice_char_device_state_opaque_get(sin->st); - spice_assert(!st->scc || st == st->scc->smartcard_state); + spice_assert(!st->priv->scc || st == st->priv->scc->smartcard_state); /* protocol requires messages to be in network endianess */ vheader->type = htonl(vheader->type); vheader->length = htonl(vheader->length); @@ -675,8 +661,8 @@ static void smartcard_channel_write_to_reader(SpiceCharDeviceWriteBuffer *write_ /* pushing the buffer to the write queue; It will be released * when it will be fully consumed by the device */ spice_char_device_write_buffer_add(sin->st, write_buf); - if (st->scc && write_buf == st->scc->write_buf) { - st->scc->write_buf = NULL; + if (st->priv->scc && write_buf == st->priv->scc->write_buf) { + st->priv->scc->write_buf = NULL; } } @@ -694,13 +680,13 @@ static void smartcard_device_state_restore_partial_read(SmartCardDeviceState *st spice_debug("read_size %u", mig_data->read_size); read_data = (uint8_t *)mig_data + mig_data->read_data_ptr - sizeof(SpiceMigrateDataHeader); if (mig_data->read_size < sizeof(VSCMsgHeader)) { - spice_assert(state->buf_size >= mig_data->read_size); + spice_assert(state->priv->buf_size >= mig_data->read_size); } else { smartcard_read_buf_prepare(state, (VSCMsgHeader *)read_data); } - memcpy(state->buf, read_data, mig_data->read_size); - state->buf_used = mig_data->read_size; - state->buf_pos = state->buf + mig_data->read_size; + memcpy(state->priv->buf, read_data, mig_data->read_size); + state->priv->buf_used = mig_data->read_size; + state->priv->buf_pos = state->priv->buf + mig_data->read_size; } static int smartcard_channel_client_handle_migrate_data(RedChannelClient *rcc, @@ -739,10 +725,10 @@ static int smartcard_channel_client_handle_migrate_data(RedChannelClient *rcc, } } spice_debug("reader added %d partial read_size %u", mig_data->reader_added, mig_data->read_size); - scc->smartcard_state->reader_added = mig_data->reader_added; + scc->smartcard_state->priv->reader_added = mig_data->reader_added; smartcard_device_state_restore_partial_read(scc->smartcard_state, mig_data); - return spice_char_device_state_restore(scc->smartcard_state->chardev_st, &mig_data->base); + return spice_char_device_state_restore(RED_CHAR_DEVICE(scc->smartcard_state), &mig_data->base); } static int smartcard_channel_handle_message(RedChannelClient *rcc, @@ -867,3 +853,38 @@ static void smartcard_init(RedsState *reds) reds_register_channel(reds, &g_smartcard_channel->base); } + + +static void +red_char_device_smartcard_finalize(GObject *object) +{ + RedCharDeviceSmartcard *self = RED_CHAR_DEVICE_SMARTCARD(object); + + free(self->priv->buf); + if (self->priv->scc) { + self->priv->scc->smartcard_state = NULL; + } + + G_OBJECT_CLASS(red_char_device_smartcard_parent_class)->finalize(object); +} + +static void +red_char_device_smartcard_class_init(RedCharDeviceSmartcardClass *klass) +{ + GObjectClass *object_class = G_OBJECT_CLASS(klass); + + g_type_class_add_private(klass, sizeof (RedCharDeviceSmartcardPrivate)); + + object_class->finalize = red_char_device_smartcard_finalize; +} + +static void +red_char_device_smartcard_init(RedCharDeviceSmartcard *self) +{ + self->priv = RED_CHAR_DEVICE_SMARTCARD_PRIVATE(self); + + self->priv->reader_id = VSCARD_UNDEFINED_READER_ID; + self->priv->buf_size = APDUBufSize + sizeof(VSCMsgHeader); + self->priv->buf = spice_malloc(self->priv->buf_size); + self->priv->buf_pos = self->priv->buf; +} diff --git a/server/smartcard.h b/server/smartcard.h index 32d2367..4b00433 100644 --- a/server/smartcard.h +++ b/server/smartcard.h @@ -1,6 +1,6 @@ /* -*- Mode: C; c-basic-offset: 4; indent-tabs-mode: nil -*- */ /* - Copyright (C) 2010 Red Hat, Inc. + Copyright (C) 2010-2015 Red Hat, Inc. This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public @@ -18,6 +18,34 @@ #ifndef __SMART_CARD_H__ #define __SMART_CARD_H__ +#include <glib-object.h> + +#define RED_TYPE_CHAR_DEVICE_SMARTCARD red_char_device_smartcard_get_type() + +#define RED_CHAR_DEVICE_SMARTCARD(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), RED_TYPE_CHAR_DEVICE_SMARTCARD, RedCharDeviceSmartcard)) +#define RED_CHAR_DEVICE_SMARTCARD_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), RED_TYPE_CHAR_DEVICE_SMARTCARD, RedCharDeviceSmartcardClass)) +#define RED_IS_CHAR_DEVICE_SMARTCARD(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), RED_TYPE_CHAR_DEVICE_SMARTCARD)) +#define RED_IS_CHAR_DEVICE_SMARTCARD_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), RED_TYPE_CHAR_DEVICE_SMARTCARD)) +#define RED_CHAR_DEVICE_SMARTCARD_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), RED_TYPE_CHAR_DEVICE_SMARTCARD, RedCharDeviceSmartcardClass)) + +typedef struct RedCharDeviceSmartcard RedCharDeviceSmartcard; +typedef struct RedCharDeviceSmartcardClass RedCharDeviceSmartcardClass; +typedef struct RedCharDeviceSmartcardPrivate RedCharDeviceSmartcardPrivate; + +struct RedCharDeviceSmartcard +{ + RedCharDevice parent; + + RedCharDeviceSmartcardPrivate *priv; +}; + +struct RedCharDeviceSmartcardClass +{ + RedCharDeviceClass parent_class; +}; + +GType red_char_device_smartcard_get_type(void) G_GNUC_CONST; + /* * connect to smartcard interface, used by smartcard channel */ -- 2.5.5 _______________________________________________ Spice-devel mailing list Spice-devel@xxxxxxxxxxxxxxxxxxxxx https://lists.freedesktop.org/mailman/listinfo/spice-devel