Removed SCardCancelTransaction completely; Added neesting counter; refs #8
This commit is contained in:
@@ -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
|
||||||
|
10
src/pcsc.cxx
Normal file
10
src/pcsc.cxx
Normal file
@@ -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);
|
75
src/pcsc.hxx
75
src/pcsc.hxx
@@ -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
|
//! Use scoped transactions with @ref Transaction
|
||||||
void commitTransaction() {
|
/*! Calls @c SCardEndTransaction if it's inside a transaction.
|
||||||
check(SCardEndTransaction(_id, SCARD_LEAVE_CARD),
|
|
||||||
"smartcard end transaction");
|
|
||||||
}
|
|
||||||
|
|
||||||
//! Use scoped transactions with @ref Transaction
|
@throws neesting_error if there are more calls to @c
|
||||||
/*! @note Micro$oft QinSCard does not know cancel, therefore
|
endTransaction than to @c beginTransaction. */
|
||||||
on Windoze cancel is replaced by commit. */
|
void endTransaction() {
|
||||||
void cancelTransaction() {
|
if (--_neesting==0)
|
||||||
#ifndef WIN32
|
check(SCardEndTransaction(_id, SCARD_LEAVE_CARD),
|
||||||
check(SCardCancelTransaction(_id), "smartcard cancel transaction");
|
"smartcard end transaction");
|
||||||
#endif
|
else if (_neesting<0) {
|
||||||
check(SCardEndTransaction(_id, SCARD_LEAVE_CARD),
|
_neesting = 0;
|
||||||
"smartcard end transaction");
|
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
|
||||||
|
Reference in New Issue
Block a user