[Spice-devel] [PATCH 09/13] smartcard: client side (not enabled yet)
Hans de Goede
hdegoede at redhat.com
Tue Dec 7 02:28:18 PST 2010
Ack.
On 12/06/2010 05:16 PM, Alon Levy wrote:
> ---
> client/application.cpp | 45 +++++
> client/application.h | 12 ++
> client/smartcard_channel.cpp | 449 ++++++++++++++++++++++++++++++++++++++++++
> client/smartcard_channel.h | 133 +++++++++++++
> 4 files changed, 639 insertions(+), 0 deletions(-)
> create mode 100644 client/smartcard_channel.cpp
> create mode 100644 client/smartcard_channel.h
>
> diff --git a/client/application.cpp b/client/application.cpp
> index c380373..ae19785 100644
> --- a/client/application.cpp
> +++ b/client/application.cpp
> @@ -47,6 +47,10 @@
> #include<stdio.h>
> #include<time.h>
>
> +#ifdef USE_SMARTCARD
> +#include<smartcard_channel.h>
> +#endif
> +
> #define STICKY_KEY_PIXMAP ALT_IMAGE_RES_ID
> #define STICKY_KEY_TIMEOUT 750
>
> @@ -364,6 +368,9 @@ Application::Application()
> #endif // USE_GUI
> , _during_host_switch(false)
> , _state (DISCONNECTED)
> +#ifdef USE_SMARTCARD
> + , _smartcard_options(new SmartcardOptions())
> +#endif
> {
> DBG(0, "");
> Platform::set_process_loop(*this);
> @@ -447,6 +454,9 @@ Application::~Application()
>
> _main_screen->unref();
> destroy_monitors();
> +#ifdef USE_SMARTCARD
> + delete _smartcard_options;
> +#endif
> }
>
> void Application::init_menu()
> @@ -2148,6 +2158,12 @@ void Application::register_channels()
> _client.register_channel_factory(TunnelChannel::Factory());
> }
> #endif
> +#ifdef USE_SMARTCARD
> + if (_enabled_channels[SPICE_CHANNEL_SMARTCARD]&& _smartcard_options->enable) {
> + smartcard_init(_smartcard_options); // throws Exception
> + _client.register_channel_factory(SmartCardChannel::Factory());
> + }
> +#endif
> }
>
> bool Application::process_cmd_line(int argc, char** argv)
> @@ -2177,6 +2193,12 @@ bool Application::process_cmd_line(int argc, char** argv)
> SPICE_OPT_DISPLAY_COLOR_DEPTH,
> SPICE_OPT_DISABLE_DISPLAY_EFFECTS,
> SPICE_OPT_CONTROLLER,
> +#ifdef USE_SMARTCARD
> + SPICE_OPT_SMARTCARD,
> + SPICE_OPT_NOSMARTCARD,
> + SPICE_OPT_SMARTCARD_CERT,
> + SPICE_OPT_SMARTCARD_DB,
> +#endif
> };
>
> #ifdef USE_GUI
> @@ -2235,6 +2257,15 @@ bool Application::process_cmd_line(int argc, char** argv)
>
> parser.add(SPICE_OPT_CONTROLLER, "controller", "enable external controller");
>
> +#ifdef USE_SMARTCARD
> + parser.add(SPICE_OPT_SMARTCARD, "smartcard", "enable smartcard channel");
> + parser.add(SPICE_OPT_NOSMARTCARD, "nosmartcard", "disable smartcard channel");
> + parser.add(SPICE_OPT_SMARTCARD_CERT, "smartcard-cert", "Use virtual reader+card with given cert(s)",
> + "smartcard-cert", true);
> + parser.set_multi(SPICE_OPT_SMARTCARD_CERT, ',');
> + parser.add(SPICE_OPT_SMARTCARD_DB, "smartcard-db", "Use given db for smartcard certs");
> +#endif
> +
> for (int i = SPICE_CHANNEL_MAIN; i< SPICE_END_CHANNEL; i++) {
> _peer_con_opt[i] = RedPeer::ConnectionOptions::CON_OP_INVALID;
> }
> @@ -2340,6 +2371,20 @@ bool Application::process_cmd_line(int argc, char** argv)
> }
> _enable_controller = true;
> return true;
> +#ifdef USE_SMARTCARD
> + case SPICE_OPT_SMARTCARD:
> + _smartcard_options->enable= true;
> + break;
> + case SPICE_OPT_NOSMARTCARD:
> + _smartcard_options->enable= false; // default
> + break;
> + case SPICE_OPT_SMARTCARD_CERT:
> + do {
> + _smartcard_options->certs.insert(
> + _smartcard_options->certs.end(), std::string(val));
> + } while ((val=parser.next_argument()));
> + break;
> +#endif
> case CmdLineParser::OPTION_HELP:
> parser.show_help();
> return false;
> diff --git a/client/application.h b/client/application.h
> index 5a5a488..f9bbd53 100644
> --- a/client/application.h
> +++ b/client/application.h
> @@ -29,6 +29,9 @@
> #include "foreign_menu.h"
> #include "controller.h"
>
> +#ifdef USE_SMARTCARD
> +struct SmartcardOptions;
> +#endif
> class RedScreen;
> class Application;
> class ScreenLayer;
> @@ -268,6 +271,12 @@ public:
> void message_box_test();
> #endif
>
> +#ifdef USE_SMARTCARD
> + const SmartcardOptions* get_smartcard_options() const {
> + return _smartcard_options;
> + }
> +#endif
> +
> static int main(int argc, char** argv, const char* version_str);
>
> private:
> @@ -386,6 +395,9 @@ private:
> bool _during_host_switch;
>
> State _state;
> +#ifdef USE_SMARTCARD
> + SmartcardOptions* _smartcard_options;
> +#endif
> };
>
> #endif
> diff --git a/client/smartcard_channel.cpp b/client/smartcard_channel.cpp
> new file mode 100644
> index 0000000..d585c9a
> --- /dev/null
> +++ b/client/smartcard_channel.cpp
> @@ -0,0 +1,449 @@
> +#include<spice/enums.h>
> +
> +#include "client/red_client.h"
> +#include "mutex.h"
> +
> +extern "C" {
> +#include "vscard_common.h"
> +#include "vreader.h"
> +#include "vcard_emul.h"
> +#include "vevent.h"
> +}
> +
> +#include "smartcard_channel.h"
> +
> +#define APDUBufSize 270
> +
> +#define MAX_ATR_LEN 40
> +
> +//#define DEBUG_SMARTCARD
> +
> +#ifdef DEBUG_SMARTCARD
> +void PrintByteArray(uint8_t *arrBytes, unsigned int nSize)
> +{
> + int i;
> +
> + for (i=0; i< nSize; i++) {
> + DBG(0, "%X ", arrBytes[i]);
> + }
> + DBG(0, "\n");
> +}
> +#define DEBUG_PRINT_BYTE_ARRAY(arrBytes, nSize) PrintByteArray(arrBytes, nSize)
> +#else
> +#define DEBUG_PRINT_BYTE_ARRAY(arrBytes, nSize)
> +#endif
> +
> +SmartCardChannel* g_smartcard_channel = NULL; // used for insert/remove of virtual card. Can be
> + // changed if we let Application store the SmartCard instance.
> +
> +class SmartCardHandler: public MessageHandlerImp<SmartCardChannel, SPICE_CHANNEL_SMARTCARD> {
> +public:
> + SmartCardHandler(SmartCardChannel& channel)
> + : MessageHandlerImp<SmartCardChannel, SPICE_CHANNEL_SMARTCARD>(channel) {}
> +};
> +
> +
> +SmartCardChannel::SmartCardChannel(RedClient& client, uint32_t id)
> + : RedChannel(client, SPICE_CHANNEL_SMARTCARD, id, new SmartCardHandler(*this))
> +{
> + SmartCardHandler* handler = static_cast<SmartCardHandler*>(get_message_handler());
> +
> + g_smartcard_channel = this;
> + handler->set_handler(SPICE_MSG_SMARTCARD_DATA,
> +&SmartCardChannel::handle_smartcard_data);
> +}
> +
> +ReaderData* SmartCardChannel::reader_data_from_vreader(VReader* vreader)
> +{
> + if (vreader == NULL) {
> + assert(_readers_by_vreader.size()> 0);
> + return _readers_by_vreader.begin()->second;
> + }
> + if (_readers_by_vreader.count(vreader)> 0) {
> + return _readers_by_vreader.find(vreader)->second;
> + }
> + assert(_unallocated_readers_by_vreader.count(vreader)> 0);
> + return _unallocated_readers_by_vreader.find(vreader)->second;
> +}
> +
> +ReaderData* SmartCardChannel::reader_data_from_reader_id(reader_id_t reader_id)
> +{
> + if (_readers_by_id.count(reader_id)> 0) {
> + return _readers_by_id.find(reader_id)->second;
> + }
> + return NULL;
> +}
> +
> +/** On VEVENT_READER_INSERT we call this, send a VSC_ReaderAdd, and wait for a VSC_ReaderAddResponse
> + */
> +void SmartCardChannel::add_unallocated_reader(VReader* vreader, const char* name)
> +{
> + ReaderData* data = new ReaderData();
> +
> + data->vreader = vreader;
> + data->reader_id = VSCARD_UNDEFINED_READER_ID;
> + data->name = spice_strdup(name);
> + _unallocated_readers_by_vreader.insert(std::pair<VReader*, ReaderData*>(vreader, data));
> +}
> +
> +/** called upon the VSC_ReaderAddResponse
> + */
> +ReaderData* SmartCardChannel::add_reader(reader_id_t reader_id)
> +{
> + ReaderData* data;
> + size_t unallocated = _unallocated_readers_by_vreader.size();
> +
> + assert(unallocated> 0);
> + data = _unallocated_readers_by_vreader.begin()->second;
> + data->reader_id = reader_id;
> + _readers_by_vreader.insert(
> + std::pair<VReader*, ReaderData*>(data->vreader, data));
> + assert(_readers_by_vreader.count(data->vreader) == 1);
> + _readers_by_id.insert(std::pair<reader_id_t, ReaderData*>(reader_id, data));
> + assert(_readers_by_id.count(reader_id) == 1);
> + _unallocated_readers_by_vreader.erase(_unallocated_readers_by_vreader.begin());
> + assert(_unallocated_readers_by_vreader.size() == unallocated - 1);
> + assert(_unallocated_readers_by_vreader.count(data->vreader) == 0);
> + return data;
> +}
> +
> +void* SmartCardChannel::cac_card_events_thread_entry(void* data)
> +{
> + static_cast<SmartCardChannel*>(data)->cac_card_events_thread_main();
> + return NULL;
> +}
> +
> +VEventEvent::VEventEvent(SmartCardChannel* smartcard_channel, VEvent* vevent)
> + : _smartcard_channel(smartcard_channel)
> + , _vreader(vevent->reader)
> + , _vevent(vevent)
> +{
> +}
> +
> +VEventEvent::~VEventEvent()
> +{
> + vevent_delete(_vevent);
> +}
> +
> +void ReaderAddEvent::response(AbstractProcessLoop& events_loop)
> +{
> + static int num = 0;
> + char name[20];
> +
> + sprintf(name, "test%4d", num++);
> + _smartcard_channel->add_unallocated_reader(_vreader, name);
> + _smartcard_channel->send_reader_added(name);
> +}
> +
> +void ReaderRemoveEvent::response(AbstractProcessLoop& events_loop)
> +{
> + ReaderData* data;
> +
> + data = _smartcard_channel->reader_data_from_vreader(_vreader);
> + _smartcard_channel->send_reader_removed(data->reader_id);
> + _smartcard_channel->remove_reader(data);
> +}
> +
> +void CardInsertEvent::response(AbstractProcessLoop& events_loop)
> +{
> + ReaderData* data = _smartcard_channel->reader_data_from_vreader(
> + _vreader);
> +
> + if (data->reader_id == VSCARD_UNDEFINED_READER_ID) {
> + data->card_insert_pending = true;
> + } else {
> + _smartcard_channel->send_atr(_vreader);
> + }
> +}
> +
> +void CardRemoveEvent::response(AbstractProcessLoop& events_loop)
> +{
> + ReaderData* data = _smartcard_channel->reader_data_from_vreader(
> + _vreader);
> +
> + ASSERT(data->reader_id != VSCARD_UNDEFINED_READER_ID);
> + _smartcard_channel->send_message(data->reader_id, VSC_CardRemove, NULL, 0);
> +}
> +
> +void SmartCardChannel::remove_reader(ReaderData* data)
> +{
> + // TODO - untested code (caccard doesn't produce these events yet)
> + if (_readers_by_vreader.count(data->vreader)> 0) {
> + _readers_by_vreader.erase(_readers_by_vreader.find(data->vreader));
> + _readers_by_id.erase(_readers_by_id.find(data->reader_id));
> + } else {
> + _unallocated_readers_by_vreader.erase(
> + _unallocated_readers_by_vreader.find(data->vreader));
> + }
> + free(data->name);
> + delete data;
> +}
> +
> +void SmartCardChannel::cac_card_events_thread_main()
> +{
> + VEvent *vevent = NULL;
> + bool cont = true;
> +
> + while (cont) {
> + vevent = vevent_wait_next_vevent();
> + if (vevent == NULL) {
> + break;
> + }
> + switch (vevent->type) {
> + case VEVENT_READER_INSERT:
> + LOG_INFO("VEVENT_READER_INSERT");
> + {
> + AutoRef<ReaderAddEvent> event(new ReaderAddEvent(this, vevent));
> + get_client().push_event(*event);
> + }
> + break;
> + case VEVENT_READER_REMOVE:
> + LOG_INFO("VEVENT_READER_REMOVE");
> + {
> + AutoRef<ReaderRemoveEvent> event(new ReaderRemoveEvent(this, vevent));
> + get_client().push_event(*event);
> + }
> + break;
> + case VEVENT_CARD_INSERT:
> + LOG_INFO("VEVENT_CARD_INSERT");
> + {
> + AutoRef<CardInsertEvent> event(new CardInsertEvent(this, vevent));
> + get_client().push_event(*event);
> + }
> + break;
> + case VEVENT_CARD_REMOVE:
> + LOG_INFO("VEVENT_CARD_REMOVE");
> + {
> + AutoRef<CardRemoveEvent> event(new CardRemoveEvent(this, vevent));
> + get_client().push_event(*event);
> + }
> + break;
> + case VEVENT_LAST:
> + cont = false;
> + default:
> + /* anything except VEVENT_LAST and default
> + * gets to VEventEvent which does vevent_delete in VEventEvent~ */
> + vevent_delete(vevent);
> + }
> + }
> +}
> +
> +#define CERTIFICATES_DEFAULT_DB "/etc/pki/nssdb"
> +#define CERTIFICATES_ARGS_TEMPLATE "db=\"%s\" use_hw=no soft=(,Virtual Card,CAC,,%s,%s,%s)"
> +
> +SmartcardOptions::SmartcardOptions() :
> +dbname(CERTIFICATES_DEFAULT_DB),
> +enable(false)
> +{
> +}
> +
> +static VCardEmulError init_vcard_local_certs(const char* dbname, const char* cert1,
> + const char* cert2, const char* cert3)
> +{
> + char emul_args[200];
> + VCardEmulOptions *options = NULL;
> +
> + snprintf(emul_args, sizeof(emul_args) - 1, CERTIFICATES_ARGS_TEMPLATE,
> + dbname, cert1, cert2, cert3);
> + options = vcard_emul_options(emul_args);
> + if (options == NULL) {
> + LOG_WARN("not using certificates due to initialization error");
> + }
> + return vcard_emul_init(options);
> +}
> +
> +static bool g_vcard_inited = false;
> +
> +void smartcard_init(const SmartcardOptions* options)
> +{
> + if (g_vcard_inited) {
> + return;
> + }
> + if (options->certs.size() == 3) {
> + const char* dbname = options->dbname.c_str();
> + if (init_vcard_local_certs(dbname, options->certs[0].c_str(),
> + options->certs[1].c_str(), options->certs[2].c_str()) != VCARD_EMUL_OK) {
> + throw Exception("smartcard: emulated card initialization failed (check certs/db)");
> + }
> + } else {
> + if (options->certs.size()> 0) {
> + LOG_WARN("Ignoring smartcard certificates - must be exactly three for virtual card emulation");
> + }
> + if (vcard_emul_init(NULL) != VCARD_EMUL_OK) {
> + throw Exception("smartcard: vcard initialization failed (check hardware/drivers)");
> + }
> + }
> + g_vcard_inited = true;
> +}
> +
> +void SmartCardChannel::on_connect()
> +{
> + _event_thread = new Thread(SmartCardChannel::cac_card_events_thread_entry, this);
> +}
> +
> +void SmartCardChannel::on_disconnect()
> +{
> + VEvent *stop_event;
> +
> + if (_event_thread == NULL) {
> + return;
> + }
> + stop_event = vevent_new(VEVENT_LAST, NULL, NULL);
> + vevent_queue_vevent(stop_event);
> + _event_thread->join();
> + delete _event_thread;
> + _event_thread = NULL;
> +}
> +
> +
> +void SmartCardChannel::send_reader_removed(reader_id_t reader_id)
> +{
> + send_message(reader_id, VSC_ReaderRemove, NULL, 0);
> +}
> +
> +void SmartCardChannel::send_reader_added(const char* reader_name)
> +{
> + send_message(VSCARD_UNDEFINED_READER_ID,
> + VSC_ReaderAdd, (uint8_t*)reader_name, strlen(reader_name));
> +}
> +
> +void SmartCardChannel::send_atr(VReader* vreader)
> +{
> + unsigned char atr[ MAX_ATR_LEN];
> + int atr_len = MAX_ATR_LEN;
> + reader_id_t reader_id = reader_data_from_vreader(vreader)->reader_id;
> +
> + assert(reader_id != VSCARD_UNDEFINED_READER_ID);
> + vreader_power_on(vreader, atr,&atr_len);
> + DBG(0, "ATR: ");
> + DEBUG_PRINT_BYTE_ARRAY(atr, atr_len);
> + send_message(reader_id, VSC_ATR, (uint8_t*)atr, atr_len);
> +}
> +
> +void SmartCardChannel::send_message(uint32_t reader_id, VSCMsgType type, uint8_t* data, uint32_t len)
> +{
> + VSCMsgHeader mhHeader;
> + Message* msg = new Message(SPICE_MSGC_SMARTCARD_DATA);
> + SpiceMarshaller* m = msg->marshaller();
> +
> + mhHeader.type = type;
> + mhHeader.length = len;
> + mhHeader.reader_id = reader_id;
> + spice_marshaller_add(m, (uint8_t*)&mhHeader, sizeof(mhHeader));
> + spice_marshaller_add(m, data, len);
> + post_message(msg);
> +}
> +
> +VSCMessageEvent::VSCMessageEvent(SmartCardChannel* smartcard_channel,
> + VSCMsgHeader* vheader)
> + : _smartcard_channel(smartcard_channel)
> + , _vheader(NULL)
> +{
> + _vheader = (VSCMsgHeader*)spice_memdup(vheader,
> + sizeof(VSCMsgHeader) + vheader->length);
> + ASSERT(_vheader);
> +}
> +
> +VSCMessageEvent::~VSCMessageEvent()
> +{
> + free(_vheader);
> +}
> +
> +void VSCMessageEvent::response(AbstractProcessLoop& loop)
> +{
> + static int recv_count = 0;
> + int dwSendLength;
> + int dwRecvLength;
> + uint8_t* pbSendBuffer = _vheader->data;
> + uint8_t pbRecvBuffer[APDUBufSize+sizeof(uint32_t)];
> + VReaderStatus reader_status;
> + uint32_t rv;
> + ReaderData* data;
> +
> + switch (_vheader->type) {
> + case (VSC_ReaderAddResponse):
> + data = _smartcard_channel->add_reader(_vheader->reader_id);
> + if (data->card_insert_pending) {
> + data->card_insert_pending = false;
> + _smartcard_channel->send_atr(data->vreader);
> + }
> + return;
> + break;
> + case VSC_APDU:
> + break;
> + case VSC_Error:
> + {
> + VSCMsgError *error = (VSCMsgError*)_vheader->data;
> + LOG_WARN("VSC Error: reader %d, code %d",
> + _vheader->reader_id, error->code);
> + }
> + return;
> + default:
> + LOG_WARN("unhandled VSC %d of length %d, reader %d",
> + _vheader->type, _vheader->length, _vheader->reader_id);
> + return;
> + }
> +
> + /* Transmit recieved APDU */
> + dwSendLength = _vheader->length;
> + dwRecvLength = sizeof(pbRecvBuffer);
> +
> + DBG(0, " %3d: recv APDU: ", recv_count++);
> + DEBUG_PRINT_BYTE_ARRAY(pbSendBuffer, _vheader->length);
> +
> + ReaderData* reader_data = _smartcard_channel->reader_data_from_reader_id(
> + _vheader->reader_id);
> + if (reader_data == NULL) {
> + LOG_WARN("got message for non existant reader");
> + return;
> + }
> +
> + VReader* vreader = reader_data->vreader;
> +
> + reader_status = vreader_xfr_bytes(vreader,
> + pbSendBuffer, dwSendLength,
> + pbRecvBuffer,&dwRecvLength);
> + if (reader_status == VREADER_OK) {
> + DBG(0, " sent APDU: ");
> + DEBUG_PRINT_BYTE_ARRAY(pbRecvBuffer, dwRecvLength);
> + _smartcard_channel->send_message (
> + _vheader->reader_id,
> + VSC_APDU,
> + pbRecvBuffer,
> + dwRecvLength
> + );
> + } else {
> + rv = reader_status; /* warning: not meaningful */
> + _smartcard_channel->send_message (
> + _vheader->reader_id,
> + VSC_Error,
> + (uint8_t*)&rv,
> + sizeof (uint32_t)
> + );
> + }
> +}
> +
> +void SmartCardChannel::handle_smartcard_data(RedPeer::InMessage* message)
> +{
> + VSCMsgHeader* mhHeader = (VSCMsgHeader*)(message->data());
> +
> + AutoRef<VSCMessageEvent> event(new VSCMessageEvent(this, mhHeader));
> + get_client().push_event(*event);
> +}
> +
> +class SmartCardFactory: public ChannelFactory {
> +public:
> + SmartCardFactory() : ChannelFactory(SPICE_CHANNEL_SMARTCARD) {}
> + virtual RedChannel* construct(RedClient& client, uint32_t id)
> + {
> + return new SmartCardChannel(client, id);
> + }
> +};
> +
> +static SmartCardFactory factory;
> +
> +ChannelFactory& SmartCardChannel::Factory()
> +{
> + return factory;
> +}
> +
> diff --git a/client/smartcard_channel.h b/client/smartcard_channel.h
> new file mode 100644
> index 0000000..ee0d0d0
> --- /dev/null
> +++ b/client/smartcard_channel.h
> @@ -0,0 +1,133 @@
> +#ifndef __SMART_CARD_H__
> +#define __SMART_CARD_H__
> +
> +#include<map>
> +
> +#include<vreadert.h>
> +#include<vscard_common.h>
> +#include<eventt.h>
> +
> +#include "red_channel.h"
> +#include "red_peer.h"
> +
> +class Application;
> +
> +struct SmartcardOptions {
> + std::vector<std::string> certs;
> + std::string dbname;
> + bool enable;
> + SmartcardOptions();
> +};
> +
> +void smartcard_init(const SmartcardOptions* options);
> +
> +struct ReaderData {
> + ReaderData() :
> + vreader(NULL),
> + reader_id(VSCARD_UNDEFINED_READER_ID),
> + name(NULL),
> + card_insert_pending(false)
> + {}
> + VReader *vreader;
> + reader_id_t reader_id;
> + char* name;
> + bool card_insert_pending;
> +};
> +
> +void virtual_card_remove();
> +void virtual_card_insert();
> +
> +class SmartCardChannel;
> +
> +class VEventEvent : public Event {
> +public:
> + VEventEvent(SmartCardChannel* smartcard_channel, VEvent* vevent);
> + ~VEventEvent();
> + SmartCardChannel* _smartcard_channel;
> + VReader* _vreader;
> + VEvent* _vevent;
> +};
> +
> +class ReaderAddEvent: public VEventEvent {
> +public:
> + ReaderAddEvent(SmartCardChannel* smartcard_channel, VEvent* vevent)
> + : VEventEvent(smartcard_channel, vevent) {}
> + virtual void response(AbstractProcessLoop& events_loop);
> +};
> +
> +class ReaderRemoveEvent: public VEventEvent {
> +public:
> + ReaderRemoveEvent(SmartCardChannel* smartcard_channel, VEvent* vevent)
> + : VEventEvent(smartcard_channel, vevent) {}
> + virtual void response(AbstractProcessLoop& events_loop);
> +};
> +
> +class CardInsertEvent: public VEventEvent {
> +public:
> + CardInsertEvent(SmartCardChannel* smartcard_channel, VEvent* vevent)
> + : VEventEvent(smartcard_channel, vevent) {}
> + virtual void response(AbstractProcessLoop& events_loop);
> +};
> +
> +class CardRemoveEvent: public VEventEvent {
> +public:
> + CardRemoveEvent(SmartCardChannel* smartcard_channel, VEvent* vevent)
> + : VEventEvent(smartcard_channel, vevent) {}
> + virtual void response(AbstractProcessLoop& events_loop);
> +};
> +
> +class VSCMessageEvent: public Event {
> +public:
> + VSCMessageEvent(SmartCardChannel* smartcard_channel,
> + VSCMsgHeader* vheader);
> + ~VSCMessageEvent();
> + SmartCardChannel* _smartcard_channel;
> + VSCMsgHeader* _vheader;
> + virtual void response(AbstractProcessLoop& events_loop);
> +};
> +
> +class SmartCardChannel : public RedChannel {
> +
> +public:
> + SmartCardChannel(RedClient& client, uint32_t id);
> + void handle_smartcard_data(RedPeer::InMessage* message);
> +
> + static ChannelFactory& Factory();
> +protected:
> + virtual void on_connect();
> + virtual void on_disconnect();
> +
> +private:
> + static void* cac_card_events_thread_entry(void* data);
> + void cac_card_events_thread_main();
> + void send_message(reader_id_t reader_id, VSCMsgType type, uint8_t* data, uint32_t len);
> +
> + Thread* _event_thread;
> +
> + Application* _app;
> +
> + VReaderList *_reader_list;
> + typedef std::map<reader_id_t, ReaderData*> readers_by_id_t;
> + readers_by_id_t _readers_by_id;
> + typedef std::map<VReader*, ReaderData*> readers_by_vreader_t;
> + readers_by_vreader_t _readers_by_vreader;
> + readers_by_vreader_t _unallocated_readers_by_vreader;
> +
> + ReaderData* reader_data_from_vreader(VReader* vreader);
> + ReaderData* reader_data_from_reader_id(reader_id_t reader_id);
> + void add_unallocated_reader(VReader* vreader, const char* name);
> + ReaderData* add_reader(reader_id_t reader_id);
> + void remove_reader(ReaderData* data);
> + void send_reader_added(const char* reader_name);
> + void send_reader_removed(reader_id_t reader_id);
> + void send_atr(VReader* vreader);
> +
> + friend class ReaderAddEvent;
> + friend class ReaderRemoveEvent;
> + friend class CardInsertEvent;
> + friend class CardRemoveEvent;
> + friend class VSCMessageEvent;
> +};
> +
> +#endif // __SMART_CARD_H__
> +
More information about the Spice-devel
mailing list