[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