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