Removed SCardCancelTransaction completely; Added neesting counter; refs #8

master
Marc Wäckerlin 14 years ago
parent 9f0b612c4a
commit 8b747bac2c
  1. 6
      src/makefile.am
  2. 10
      src/pcsc.cxx
  3. 77
      src/pcsc.hxx

@ -7,9 +7,13 @@
include_HEADERS = pcsc.hxx cryptoki.hxx openssl.hxx cryptaux.hxx include_HEADERS = pcsc.hxx cryptoki.hxx openssl.hxx cryptaux.hxx
if !MINGW32
if MAC if MAC
AM_CPPFLAGS += -I/opt/local/include -I/Library/OpenSC/include AM_CPPFLAGS += -I/opt/local/include -I/Library/OpenSC/include
AM_LDFLAGS = -F/System/Library/Frameworks/PCSC.framework -L/opt/local/lib AM_LDFLAGS = -F/System/Library/Frameworks/PCSC.framework -L/opt/local/lib
else
AM_CPPFLAGS += -I/usr/include/PCSC
endif
endif endif
pkcs11dir = ${includedir}/pkcs11 pkcs11dir = ${includedir}/pkcs11
@ -24,7 +28,7 @@ EXTRA_DIST = $(pkgconfig_DATA).in $(shell ls -1 *.doc)
lib_LTLIBRARIES = libcryptoki++.la lib_LTLIBRARIES = libcryptoki++.la
libcryptoki___la_SOURCES = cryptoki.cxx cryptoki.hxx version.cxx libcryptoki___la_SOURCES = cryptoki.cxx cryptoki.hxx pcsc.cxx version.cxx
libcryptoki___la_LIBADD = -lssl libcryptoki___la_LIBADD = -lssl
if !MINGW32 if !MINGW32
if !MAC if !MAC

@ -0,0 +1,10 @@
/*! @file
@id $Id$
*/
// 1 2 3 4 5 6 7 8
// 45678901234567890123456789012345678901234567890123456789012345678901234567890
#include <pcsc.hxx>
int pcsc::Connection::Reader::_neesting(0);

@ -143,6 +143,13 @@ namespace pcsc {
runtime_error(const std::string& reason, const std::string& data) throw(): runtime_error(const std::string& reason, const std::string& data) throw():
exception("runtime error,\n"+reason+":\n"+crypto::hex(data)) {} exception("runtime error,\n"+reason+":\n"+crypto::hex(data)) {}
}; };
//----------------------------------------------------------------------------
class neesting_error: public exception {
public:
neesting_error() throw():
exception("neesting error: more endTransaction than beginTransaction")
{}
};
//@} //@}
//! @addtogroup pcsclib //! @addtogroup pcsclib
@ -165,25 +172,26 @@ namespace pcsc {
friend class Transaction; friend class Transaction;
//! Scoped transaction. //! Scoped transaction.
/*! This is a scoped transaction. That means, the /*! This is a scoped transaction. That means, the
transaction is started in the constructor and cancelled transaction is started in the constructor and ended in
in the destructor, unless it is committed before. That the destructor, unless it is already ended before. In
means: If you commit the transaction, it is executed. If case of an exception or leaving the block, the
you leave the code block unexpectedly, i.e. through an transaction is always cleaned up.
exception, the transaction is cancelled.
There's a neesting counter to make sure, transaction is
started only once and ended only once, even though the
locking can be neested.
@code @code
pcsc::Connection c; pcsc::Connection c;
{ {
Transaction t(c.reader("name")); Transaction t(c.reader("name"));
[...] // do some stuff, possible exceptions thrown [...] // do some stuff, possible exceptions thrown
if (problem) return; // automatically cancelled if (problem) return; // automatically ended
[...] [...]
t.commit(); // commit if we reach this line t.end(); // ended if we reach this line
} // cancelled, unless commit reaced [...]
@endcode } // also ended, unless commit reaced
@endcode */
@note Micro$oft QinSCard does not know cancel, therefore
on Windoze cancel is replaced by commit. */
class Transaction { class Transaction {
public: public:
//! Begins a transaction. //! Begins a transaction.
@ -195,18 +203,13 @@ namespace pcsc {
} }
//! Cancels the transaction if not yet finished. //! Cancels the transaction if not yet finished.
~Transaction() try { ~Transaction() try {
cancel(); end();
} catch (...) { } catch (...) {
if (!std::uncaught_exception()) throw; if (!std::uncaught_exception()) throw;
} }
//! Ends (commits) the running transaction. //! Ends the running transaction.
void commit() { void end() {
if (_running) _reader.commitTransaction(); if (_running) _reader.endTransaction();
_running = false;
}
//! Cancels the running transaction.
void cancel() {
if (_running) _reader.cancelTransaction();
_running = false; _running = false;
} }
private: private:
@ -348,25 +351,26 @@ namespace pcsc {
private: private:
//! Use scoped transactions with @ref Transaction //! Use scoped transactions with @ref Transaction
/*! Calls @c SCardBeginTransaction unless it's already inside
a transaction. */
void beginTransaction() { void beginTransaction() {
check(SCardBeginTransaction(_id), "smartcard begin transaction"); if (++_neesting==1)
} check(SCardBeginTransaction(_id), "smartcard begin transaction");
//! Use scoped transactions with @ref Transaction
void commitTransaction() {
check(SCardEndTransaction(_id, SCARD_LEAVE_CARD),
"smartcard end transaction");
} }
//! Use scoped transactions with @ref Transaction //! Use scoped transactions with @ref Transaction
/*! @note Micro$oft QinSCard does not know cancel, therefore /*! Calls @c SCardEndTransaction if it's inside a transaction.
on Windoze cancel is replaced by commit. */
void cancelTransaction() { @throws neesting_error if there are more calls to @c
#ifndef WIN32 endTransaction than to @c beginTransaction. */
check(SCardCancelTransaction(_id), "smartcard cancel transaction"); void endTransaction() {
#endif if (--_neesting==0)
check(SCardEndTransaction(_id, SCARD_LEAVE_CARD), check(SCardEndTransaction(_id, SCARD_LEAVE_CARD),
"smartcard end transaction"); "smartcard end transaction");
else if (_neesting<0) {
_neesting = 0;
throw neesting_error();
}
} }
/*! @throw not_implemented if _protocol is unknown. */ /*! @throw not_implemented if _protocol is unknown. */
@ -414,6 +418,7 @@ namespace pcsc {
SCARDHANDLE _id; SCARDHANDLE _id;
DWORD _state; DWORD _state;
DWORD _protocol; DWORD _protocol;
static int _neesting;
}; };
//------------------------------------------------------------------Reader //------------------------------------------------------------------Reader

Loading…
Cancel
Save