|
|
|
@ -490,13 +490,26 @@ namespace pcsc { |
|
|
|
|
- @c false: no exceptions, check your instance after each |
|
|
|
|
operation */ |
|
|
|
|
Connection(Scope s=USER, bool exceptions=true): |
|
|
|
|
_connectionlifetime(new ConnectionLifetime(s, exceptions)) { |
|
|
|
|
_connectionlifetime(connectionlifetime(s, exceptions)) { |
|
|
|
|
++connectionlifetimecounter(); |
|
|
|
|
CRYPTOLOG("Connection Counter is now: "<<connectionlifetimecounter()); |
|
|
|
|
check("establish smartcard context"); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
Connection(const Connection& o) { |
|
|
|
|
++connectionlifetimecounter(); |
|
|
|
|
*this = o; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
//! Closes the connection (releases the smartcard context)
|
|
|
|
|
~Connection() { |
|
|
|
|
// connection is closed, when last _connectionlifetime is destructed
|
|
|
|
|
// connection is closed, when _connectionlifetime is destructed
|
|
|
|
|
if (--connectionlifetimecounter()==0) { |
|
|
|
|
CRYPTOLOG("Delete Connection"); |
|
|
|
|
delete connectionlifetime(); |
|
|
|
|
connectionlifetime()=0; |
|
|
|
|
} |
|
|
|
|
CRYPTOLOG("Connection Counter is now: "<<connectionlifetimecounter()); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
//! Scans for available readers from a specified list of groups.
|
|
|
|
@ -529,17 +542,15 @@ namespace pcsc { |
|
|
|
|
/*! First use scan() to get a list of readers, then open a
|
|
|
|
|
connection to the reader, then access it. */ |
|
|
|
|
mrw::Shared<Reader> reader(const std::string& name) { |
|
|
|
|
if (_readers.find(name)==_readers.end()) |
|
|
|
|
_readers.insert(std::make_pair(name, new Reader(name, *this))); |
|
|
|
|
return _readers.find(name)->second; |
|
|
|
|
return _connectionlifetime->reader(name, this); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
//! Close connection of a named reader.
|
|
|
|
|
/*! If you access the same reader through raeder() later, the
|
|
|
|
|
connection will be reestablished. */ |
|
|
|
|
void close(const std::string& s) { |
|
|
|
|
// //! Close connection of a named reader.
|
|
|
|
|
// /*! If you access the same reader through raeder() later, the
|
|
|
|
|
// connection will be reestablished. */
|
|
|
|
|
// void close(const std::string& s) {
|
|
|
|
|
|
|
|
|
|
} |
|
|
|
|
// }
|
|
|
|
|
|
|
|
|
|
//! Find all readers with a given ATR.
|
|
|
|
|
/*! @param atr full or partial ATR to match to the reader's ATR
|
|
|
|
@ -638,17 +649,21 @@ namespace pcsc { |
|
|
|
|
/*! @throw access_error if it is instanciated for exceptions and
|
|
|
|
|
an error occured in the last command. */ |
|
|
|
|
bool check(const std::string& context="") { |
|
|
|
|
if (_exc&&!*this) |
|
|
|
|
if (context.size()) |
|
|
|
|
if (_state==SCARD_W_WRONG_CHV) |
|
|
|
|
if (_exc&&!*this) { |
|
|
|
|
if (context.size()) { |
|
|
|
|
if (_state==SCARD_W_WRONG_CHV) { |
|
|
|
|
throw wrong_pin(context+": "+error()); |
|
|
|
|
else |
|
|
|
|
} else { |
|
|
|
|
throw access_error(context+": "+error()); |
|
|
|
|
else |
|
|
|
|
if (_state==SCARD_W_WRONG_CHV) |
|
|
|
|
} |
|
|
|
|
} else { |
|
|
|
|
if (_state==SCARD_W_WRONG_CHV) { |
|
|
|
|
throw wrong_pin(error()); |
|
|
|
|
else |
|
|
|
|
} else { |
|
|
|
|
throw access_error(error()); |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
return *this; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
@ -906,23 +921,47 @@ namespace pcsc { |
|
|
|
|
return _exc; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
//! Get a reader, open a connection if not already open.
|
|
|
|
|
/*! First use scan() to get a list of readers, then open a
|
|
|
|
|
connection to the reader, then access it. */ |
|
|
|
|
mrw::Shared<Reader> reader(const std::string& name, Connection* c) { |
|
|
|
|
CRYPTOLOG("get reader: "<<name<<" from "<<(void*)&_readers); |
|
|
|
|
if (_readers.find(name)==_readers.end()) |
|
|
|
|
_readers.insert(std::make_pair(name, new Reader(name, *c))); |
|
|
|
|
return _readers.find(name)->second; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
private: |
|
|
|
|
|
|
|
|
|
bool _exc; |
|
|
|
|
SCARDCONTEXT _id; |
|
|
|
|
long _state; |
|
|
|
|
}; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
//! Readers are closed when the last shared object is destructed
|
|
|
|
|
std::map<std::string, mrw::Shared<Reader> > _readers; |
|
|
|
|
}; |
|
|
|
|
|
|
|
|
|
//! Connection is closed when the last shared object is destructed
|
|
|
|
|
/*! Handling the connection lifetime in a separate shared object
|
|
|
|
|
allows to copy connections and still make sure, that the |
|
|
|
|
lifetime of the connection is as long as all copied opbjects |
|
|
|
|
live. */ |
|
|
|
|
mrw::Shared<ConnectionLifetime> _connectionlifetime; |
|
|
|
|
static ConnectionLifetime*& |
|
|
|
|
connectionlifetime(Scope s=USER, bool exc=true) { |
|
|
|
|
static ConnectionLifetime* instance(0); |
|
|
|
|
if (instance==0) { |
|
|
|
|
CRYPTOLOG("New Connection"); |
|
|
|
|
instance = new ConnectionLifetime(s, exc); |
|
|
|
|
} |
|
|
|
|
return instance; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
static int& connectionlifetimecounter() { |
|
|
|
|
static int instance(0); |
|
|
|
|
return instance; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
ConnectionLifetime* _connectionlifetime; |
|
|
|
|
|
|
|
|
|
}; |
|
|
|
|
|
|
|
|
|