added draft lib for suisseid - by now: detect Post SuisseID; refs #28

This commit is contained in:
Marc Wäckerlin
2013-10-15 11:57:29 +00:00
parent 91b075d61b
commit 1de9676582
8 changed files with 691 additions and 498 deletions

View File

@@ -11,7 +11,7 @@
#define PCSC_HXX
#ifndef PCSC_LOG
//! Declare PCSC_LOG before #include in your code, if you want logging.
//! Declare PCSC_LOG before #include in your de, if you want logging.
/*! PCSC_LOG passes its argument to a stream, so your definition must
behave so that the argument can be streamed.
@@ -31,6 +31,7 @@
#include <cryptaux.hxx>
#include <mrw/shared.hxx>
#include <string>
#ifdef WIN32
@@ -214,8 +215,8 @@ namespace pcsc {
/*! @note Please note that the Reader is required in the
destructor und must therefore live longer than the
Transaction instance. */
Transaction(Reader& r): _reader(r), _running(true) {
_reader.beginTransaction();
Transaction(mrw::Shared<Reader> r): _reader(r), _running(true) {
_reader->beginTransaction();
}
//! Cancels the transaction if not yet finished.
~Transaction() try {
@@ -225,11 +226,11 @@ namespace pcsc {
}
//! Ends the running transaction.
void end() {
if (_running) _reader.endTransaction();
if (_running) _reader->endTransaction();
_running = false;
}
private:
Reader& _reader;
mrw::Shared<Reader> _reader;
bool _running;
};
@@ -248,7 +249,7 @@ namespace pcsc {
~Reader() {
_state = SCardDisconnect(_id, SCARD_RESET_CARD);
if (!std::uncaught_exception())
_connection.check("disconnect smartcard");
_connection->check("disconnect smartcard");
}
//! Get reader status.
@@ -411,7 +412,7 @@ namespace pcsc {
case SCARD_PROTOCOL_T0: return SCARD_PCI_T0;
case SCARD_PROTOCOL_T1: return SCARD_PCI_T1;
}
if (_connection._exc) throw not_implemented("unknown protocol");
if (_connection->exc()) throw not_implemented("unknown protocol");
return 0;
}
@@ -420,18 +421,18 @@ namespace pcsc {
an error occured in the last command. */
bool check(long state, const std::string context="") {
_state = state;
return _connection.check(state, context);
return _connection->check(state, context);
}
//! Only Connection is allowed to instanciate.
friend class Connection;
//! Establishes a connection to the given named cardreader
Reader(const std::string& nm, Connection& c,
Reader(const std::string& nm, const Connection& c,
DWORD mode=SCARD_SHARE_SHARED,
DWORD protocol=SCARD_PROTOCOL_T1):
name(nm), _connection(c) {
check(SCardConnect(_connection._id, strconv(name).c_str(),
check(SCardConnect(_connection->id(), strconv(name).c_str(),
mode, protocol,
&_id, &_protocol),
"connect smartcard \""+name);
@@ -440,13 +441,10 @@ namespace pcsc {
//! forbidden
Reader();
//! forbidden
Reader(const Reader&);
//...........................................................variables
private:
Connection& _connection;
mrw::Shared<Connection> _connection;
SCARDHANDLE _id;
DWORD _state;
DWORD _protocol;
@@ -495,15 +493,13 @@ namespace pcsc {
- @c false: no exceptions, check your instance after each
operation */
Connection(Scope s=USER, bool exceptions=true):
_exc(exceptions), _id(0),
_state(SCardEstablishContext(s, 0, 0, &_id)) {
_connectionlifetime(new ConnectionLifetime(s, exceptions)) {
check("establish smartcard context");
}
//! Closes the connection (releases the smartcard context)
~Connection() {
_state = SCardReleaseContext(_id);
if (!std::uncaught_exception()) check("smartcard release context");
// connection is closed, when last _connectionlifetime is destructed
}
//! Scans for available readers from a specified list of groups.
@@ -512,14 +508,16 @@ namespace pcsc {
Strings res;
std::string grp(join(groups));
DWORD num(0);
if (!check(SCardListReaders(_id, groups.size()?strconv(grp).data():0, 0,
if (!check(SCardListReaders(_connectionlifetime->id(),
groups.size()?strconv(grp).data():0, 0,
&num),
"smartcard get size of readers of groups "+grp))
return res;
PCSC_LOG("size of readers: "<<num);
if (!num) return res;
std::auto_ptr<char_t> nm(new char_t[num]);
if (!check(SCardListReaders(_id, groups.size()?strconv(grp).data():0,
if (!check(SCardListReaders(_connectionlifetime->id(),
groups.size()?strconv(grp).data():0,
nm.get(), &num),
"smartcard list reader names of groups "+grp))
return res;
@@ -533,12 +531,10 @@ namespace pcsc {
//! 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. */
Reader& reader(const std::string& name) {
if (_reader.find(name)==_reader.end())
_reader.insert
(std::make_pair
(name, shared_ptr<Reader>::t(new Reader(name, *this))));
return *_reader.find(name)->second;
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;
}
//! Close connection of a named reader.
@@ -556,257 +552,14 @@ namespace pcsc {
pcsc::Connection::Strings readers(scan());
for (pcsc::Connection::Strings::const_iterator it(readers.begin());
it!=readers.end(); ++it)
if (crypto::hex(reader(*it).status().atr).find(atr)!=string::npos)
if (crypto::hex(reader(*it)->status().atr).find(atr)!=string::npos)
res.push_back(*it);
return res;
}
//! @c false if last operation was not successful
operator bool() const {
#ifdef WIN32
return (_state>>30&3)==0;
#else
return _state==SCARD_S_SUCCESS;
#endif
}
//! Get the describing text of the last error
std::string error() const {
std::stringstream ss;
switch (_state) {
case SCARD_E_CANCELLED:
ss<<"The action was canceled by an SCardCancel request.";
break;
case SCARD_E_CANT_DISPOSE:
ss<<"The system could not dispose of the media in the requested"
<<" manner.";
break;
case SCARD_E_CARD_UNSUPPORTED:
ss<<"The smart card does not meet minimal requirements for"
<<" support.";
break;
case SCARD_E_DUPLICATE_READER:
ss<<"The reader driver did not produce a unique reader name.";
break;
case SCARD_E_INSUFFICIENT_BUFFER:
ss<<"The data buffer for returned data is too small for the"
<<" returned data.";
break;
case SCARD_E_INVALID_ATR:
ss<<"An ATR string obtained from the registry is not a valid"
<<" ATR string.";
break;
case SCARD_E_INVALID_HANDLE:
ss<<"The supplied handle was not valid.";
break;
case SCARD_E_INVALID_PARAMETER:
ss<<"One or more of the supplied parameters could not be properly"
<<" interpreted.";
break;
case SCARD_E_INVALID_TARGET:
ss<<"Registry startup information is missing or not valid.";
break;
case SCARD_E_INVALID_VALUE:
ss<<"One or more of the supplied parameters values could not"
<<" be properly interpreted.";
break;
case SCARD_E_NOT_READY:
ss<<"The reader or smart card is not ready to accept commands.";
break;
case SCARD_E_NOT_TRANSACTED:
ss<<"An attempt was made to end a nonexistent transaction.";
break;
case SCARD_E_NO_MEMORY:
ss<<"Not enough memory available to complete this command.";
break;
case SCARD_E_NO_SERVICE:
ss<<"The smart card resource manager is not running.";
break;
case SCARD_E_NO_SMARTCARD:
ss<<"The operation requires a smart card, but no smart card"
<<" is currently in the device.";
break;
case SCARD_E_PCI_TOO_SMALL:
ss<<"The PCI receive buffer was too small.";
break;
case SCARD_E_PROTO_MISMATCH:
ss<<"The requested protocols are incompatible with the protocol"
<<" currently in use with the smart card.";
break;
case SCARD_E_READER_UNAVAILABLE:
ss<<"The specified reader is not currently available for use.";
break;
case SCARD_E_READER_UNSUPPORTED:
ss<<"The reader driver does not meet minimal requirements for"
<<" support.";
break;
case SCARD_E_SERVICE_STOPPED:
ss<<"The smart card resource manager has shut down.";
break;
case SCARD_E_SHARING_VIOLATION:
ss<<"The smart card cannot be accessed because of other outstanding"
<<" connections.";
break;
case SCARD_E_SYSTEM_CANCELLED:
ss<<"The action was cancelled by the system, presumably to log"
<<" off or shut down.";
break;
case SCARD_E_TIMEOUT:
ss<<"The user-specified time-out value has expired.";
break;
case SCARD_E_UNKNOWN_CARD:
ss<<"The specified smart card name is not recognized.";
break;
case SCARD_E_UNKNOWN_READER:
ss<<"The specified reader name is not recognized.";
break;
case SCARD_E_UNSUPPORTED_FEATURE:
ss<<"This smart card does not support the requested feature.";
break;
case SCARD_F_COMM_ERROR:
ss<<"An internal communications error has been detected.";
break;
case SCARD_F_INTERNAL_ERROR:
ss<<"An internal consistency check failed.";
break;
case SCARD_F_UNKNOWN_ERROR:
ss<<"An internal error has been detected, but the source is"
<<" unknown.";
break;
case SCARD_F_WAITED_TOO_LONG:
ss<<"An internal consistency timer has expired.";
break;
case SCARD_S_SUCCESS:
ss<<"No error was encountered.";
break;
case SCARD_W_REMOVED_CARD:
ss<<"The smart card has been removed, so that further communication"
<<" is not possible.";
break;
case SCARD_W_RESET_CARD:
ss<<"The smart card was reset.";
break;
case SCARD_W_UNPOWERED_CARD:
ss<<"Power has been removed from the smart card, so that"
<<" further communication is not possible.";
break;
case SCARD_W_UNRESPONSIVE_CARD:
ss<<"The smart card is not responding to a reset.";
break;
case SCARD_W_UNSUPPORTED_CARD:
ss<<"The reader cannot communicate with the smart card,"
<<" due to ATR configuration conflicts.";
break;
#ifndef __APPLE__
case SCARD_E_NO_READERS_AVAILABLE:
ss<<"No smart card reader is available.";
break;
#endif
#ifdef WIN32
case ERROR_BROKEN_PIPE:
ss<<"The client attempted a smart card operation in a"
<<" remote session, such as a client session running"
<<" on a terminal server, and the operating system in"
<<" use does not support smart card redirection.";
break;
case SCARD_E_BAD_SEEK:
ss<<"There was an error trying to set the smart card file"
<<" object pointer.";
break;
case SCARD_E_CERTIFICATE_UNAVAILABLE:
ss<<"The requested certificate could not be obtained.";
break;
case SCARD_E_COMM_DATA_LOST:
ss<<"A communications error with the smart card has been detected.";
break;
case SCARD_E_DIR_NOT_FOUND:
ss<<"The specified directory does not exist in the smart card.";
break;
case SCARD_E_FILE_NOT_FOUND:
ss<<"The specified file does not exist in the smart card.";
break;
case SCARD_E_ICC_CREATEORDER:
ss<<"The requested order of object creation is not supported.";
break;
case SCARD_E_ICC_INSTALLATION:
ss<<"No primary provider can be found for the smart card.";
break;
case SCARD_E_INVALID_CHV:
ss<<"The supplied PIN is incorrect.";
break;
case SCARD_E_NO_ACCESS:
ss<<"Access is denied to this file.";
break;
case SCARD_E_NO_DIR:
ss<<"The supplied path does not represent a smart card directory.";
break;
case SCARD_E_NO_FILE:
ss<<"The supplied path does not represent a smart card file.";
break;
case SCARD_E_NO_KEY_CONTAINER:
ss<<"The requested key container does not exist on the smart card.";
break;
case SCARD_E_NO_SUCH_CERTIFICATE:
ss<<"The requested certificate does not exist.";
break;
case SCARD_E_SERVER_TOO_BUSY:
ss<<"The Smart card resource manager is too busy to complete this"
<<" operation.";
break;
case SCARD_E_UNEXPECTED:
ss<<"An unexpected card error has occurred.";
break;
case SCARD_E_UNKNOWN_RES_MNG:
ss<<"An unrecognized error code was returned from a layered"
<<" component.";
break;
case SCARD_E_WRITE_TOO_MANY:
ss<<"The smartcard does not have enough memory to store the"
<<" information.";
break;
case SCARD_P_SHUTDOWN:
ss<<"The operation has been aborted to allow the server application"
<<" to exit.";
break;
case SCARD_W_CANCELLED_BY_USER:
ss<<"The action was cancelled by the user.";
break;
case SCARD_W_CARD_NOT_AUTHENTICATED:
ss<<"No PIN was presented to the smart card.";
break;
case SCARD_W_CHV_BLOCKED:
ss<<"The card cannot be accessed because the maximum number"
<<" of PIN entry attempts has been reached.";
break;
case SCARD_W_EOF:
ss<<"The end of the smart card file has been reached.";
break;
case SCARD_W_SECURITY_VIOLATION:
ss<<"Access was denied because of a security violation.";
break;
case SCARD_W_WRONG_CHV:
ss<<"The card cannot be accessed because the wrong PIN was"
<<" presented.";
break;
#endif
default:
ss<<"unknown PCSC state=0x"
<<std::hex<<std::setfill('0')<<std::setw(8)<<_state;
switch (_state>>30) {
case 0: ss<<" means SUCCESS"; break;
case 1: ss<<" means INFORMATIONAL"; break;
case 2: ss<<" means WARNING"; break;
case 3: ss<<" means ERROR"; break;
default: ss<<" illegal value";
}
ss<<" C="<<(_state>>29&1);
ss<<" R="<<(_state>>28&1);
ss<<" Facility=0x"<<std::hex<<std::setfill('0')<<std::setw(3)
<<(_state>>16&0xfff);
ss<<" Code=0x"<<std::hex<<std::setfill('0')<<std::setw(4)
<<(_state&0xffff);
}
return ss.str();
return *_connectionlifetime;
}
//................................................................methods
@@ -816,20 +569,15 @@ namespace pcsc {
/*! @throw access_error if it is instanciated for exceptions and
an error occured in the last command. */
bool check(long state, const std::string& context="") {
_state = state;
_connectionlifetime->state(state);
return check(context);
}
//! Throws an exception if neccessary.
/*! @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())
throw access_error(context+": "+error());
else
throw access_error(error());
return *this;
return _connectionlifetime->check(context);
}
//! Splits a buffer with 0 separators into a vector of strings.
@@ -852,14 +600,324 @@ namespace pcsc {
}
return res;
}
//! Connection id
SCARDCONTEXT id() {
return _connectionlifetime->id();
}
//! @c true if exceptions are thrown
bool exc() {
return _connectionlifetime->exc();
}
//..............................................................variables
private:
private:
class ConnectionLifetime {
public:
//! opens connection that is closed on destruction
ConnectionLifetime(Scope s, bool exc):
_exc(exc), _id(0),
_state(SCardEstablishContext(s, 0, 0, &_id)) {
check("establish smartcard context");
}
//! Closes the connection (releases the smartcard context)
~ConnectionLifetime() {
_state = SCardReleaseContext(_id);
if (!std::uncaught_exception()) check("smartcard release context");
}
//! @c false if last operation was not successful
operator bool() const {
#ifdef WIN32
return (_state>>30&3)==0;
#else
return _state==SCARD_S_SUCCESS;
#endif
}
//! Throws an exception if neccessary.
/*! @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())
throw access_error(context+": "+error());
else
throw access_error(error());
return *this;
}
//! Get the describing text of the last error
std::string error() const {
std::stringstream ss;
switch (_state) {
case SCARD_E_CANCELLED:
ss<<"The action was canceled by an SCardCancel request.";
break;
case SCARD_E_CANT_DISPOSE:
ss<<"The system could not dispose of the media in the requested"
<<" manner.";
break;
case SCARD_E_CARD_UNSUPPORTED:
ss<<"The smart card does not meet minimal requirements for"
<<" support.";
break;
case SCARD_E_DUPLICATE_READER:
ss<<"The reader driver did not produce a unique reader name.";
break;
case SCARD_E_INSUFFICIENT_BUFFER:
ss<<"The data buffer for returned data is too small for the"
<<" returned data.";
break;
case SCARD_E_INVALID_ATR:
ss<<"An ATR string obtained from the registry is not a valid"
<<" ATR string.";
break;
case SCARD_E_INVALID_HANDLE:
ss<<"The supplied handle was not valid.";
break;
case SCARD_E_INVALID_PARAMETER:
ss<<"One or more of the supplied parameters could not be properly"
<<" interpreted.";
break;
case SCARD_E_INVALID_TARGET:
ss<<"Registry startup information is missing or not valid.";
break;
case SCARD_E_INVALID_VALUE:
ss<<"One or more of the supplied parameters values could not"
<<" be properly interpreted.";
break;
case SCARD_E_NOT_READY:
ss<<"The reader or smart card is not ready to accept commands.";
break;
case SCARD_E_NOT_TRANSACTED:
ss<<"An attempt was made to end a nonexistent transaction.";
break;
case SCARD_E_NO_MEMORY:
ss<<"Not enough memory available to complete this command.";
break;
case SCARD_E_NO_SERVICE:
ss<<"The smart card resource manager is not running.";
break;
case SCARD_E_NO_SMARTCARD:
ss<<"The operation requires a smart card, but no smart card"
<<" is currently in the device.";
break;
case SCARD_E_PCI_TOO_SMALL:
ss<<"The PCI receive buffer was too small.";
break;
case SCARD_E_PROTO_MISMATCH:
ss<<"The requested protocols are incompatible with the protocol"
<<" currently in use with the smart card.";
break;
case SCARD_E_READER_UNAVAILABLE:
ss<<"The specified reader is not currently available for use.";
break;
case SCARD_E_READER_UNSUPPORTED:
ss<<"The reader driver does not meet minimal requirements for"
<<" support.";
break;
case SCARD_E_SERVICE_STOPPED:
ss<<"The smart card resource manager has shut down.";
break;
case SCARD_E_SHARING_VIOLATION:
ss<<"The smart card cannot be accessed because of other outstanding"
<<" connections.";
break;
case SCARD_E_SYSTEM_CANCELLED:
ss<<"The action was cancelled by the system, presumably to log"
<<" off or shut down.";
break;
case SCARD_E_TIMEOUT:
ss<<"The user-specified time-out value has expired.";
break;
case SCARD_E_UNKNOWN_CARD:
ss<<"The specified smart card name is not recognized.";
break;
case SCARD_E_UNKNOWN_READER:
ss<<"The specified reader name is not recognized.";
break;
case SCARD_E_UNSUPPORTED_FEATURE:
ss<<"This smart card does not support the requested feature.";
break;
case SCARD_F_COMM_ERROR:
ss<<"An internal communications error has been detected.";
break;
case SCARD_F_INTERNAL_ERROR:
ss<<"An internal consistency check failed.";
break;
case SCARD_F_UNKNOWN_ERROR:
ss<<"An internal error has been detected, but the source is"
<<" unknown.";
break;
case SCARD_F_WAITED_TOO_LONG:
ss<<"An internal consistency timer has expired.";
break;
case SCARD_S_SUCCESS:
ss<<"No error was encountered.";
break;
case SCARD_W_REMOVED_CARD:
ss<<"The smart card has been removed, so that further communication"
<<" is not possible.";
break;
case SCARD_W_RESET_CARD:
ss<<"The smart card was reset.";
break;
case SCARD_W_UNPOWERED_CARD:
ss<<"Power has been removed from the smart card, so that"
<<" further communication is not possible.";
break;
case SCARD_W_UNRESPONSIVE_CARD:
ss<<"The smart card is not responding to a reset.";
break;
case SCARD_W_UNSUPPORTED_CARD:
ss<<"The reader cannot communicate with the smart card,"
<<" due to ATR configuration conflicts.";
break;
#ifndef __APPLE__
case SCARD_E_NO_READERS_AVAILABLE:
ss<<"No smart card reader is available.";
break;
#endif
#ifdef WIN32
case ERROR_BROKEN_PIPE:
ss<<"The client attempted a smart card operation in a"
<<" remote session, such as a client session running"
<<" on a terminal server, and the operating system in"
<<" use does not support smart card redirection.";
break;
case SCARD_E_BAD_SEEK:
ss<<"There was an error trying to set the smart card file"
<<" object pointer.";
break;
case SCARD_E_CERTIFICATE_UNAVAILABLE:
ss<<"The requested certificate could not be obtained.";
break;
case SCARD_E_COMM_DATA_LOST:
ss<<"A communications error with the smart card has been detected.";
break;
case SCARD_E_DIR_NOT_FOUND:
ss<<"The specified directory does not exist in the smart card.";
break;
case SCARD_E_FILE_NOT_FOUND:
ss<<"The specified file does not exist in the smart card.";
break;
case SCARD_E_ICC_CREATEORDER:
ss<<"The requested order of object creation is not supported.";
break;
case SCARD_E_ICC_INSTALLATION:
ss<<"No primary provider can be found for the smart card.";
break;
case SCARD_E_INVALID_CHV:
ss<<"The supplied PIN is incorrect.";
break;
case SCARD_E_NO_ACCESS:
ss<<"Access is denied to this file.";
break;
case SCARD_E_NO_DIR:
ss<<"The supplied path does not represent a smart card directory.";
break;
case SCARD_E_NO_FILE:
ss<<"The supplied path does not represent a smart card file.";
break;
case SCARD_E_NO_KEY_CONTAINER:
ss<<"The requested key container does not exist on the smart card.";
break;
case SCARD_E_NO_SUCH_CERTIFICATE:
ss<<"The requested certificate does not exist.";
break;
case SCARD_E_SERVER_TOO_BUSY:
ss<<"The Smart card resource manager is too busy to complete this"
<<" operation.";
break;
case SCARD_E_UNEXPECTED:
ss<<"An unexpected card error has occurred.";
break;
case SCARD_E_UNKNOWN_RES_MNG:
ss<<"An unrecognized error code was returned from a layered"
<<" component.";
break;
case SCARD_E_WRITE_TOO_MANY:
ss<<"The smartcard does not have enough memory to store the"
<<" information.";
break;
case SCARD_P_SHUTDOWN:
ss<<"The operation has been aborted to allow the server application"
<<" to exit.";
break;
case SCARD_W_CANCELLED_BY_USER:
ss<<"The action was cancelled by the user.";
break;
case SCARD_W_CARD_NOT_AUTHENTICATED:
ss<<"No PIN was presented to the smart card.";
break;
case SCARD_W_CHV_BLOCKED:
ss<<"The card cannot be accessed because the maximum number"
<<" of PIN entry attempts has been reached.";
break;
case SCARD_W_EOF:
ss<<"The end of the smart card file has been reached.";
break;
case SCARD_W_SECURITY_VIOLATION:
ss<<"Access was denied because of a security violation.";
break;
case SCARD_W_WRONG_CHV:
ss<<"The card cannot be accessed because the wrong PIN was"
<<" presented.";
break;
#endif
default:
ss<<"unknown PCSC state=0x"
<<std::hex<<std::setfill('0')<<std::setw(8)<<_state;
switch (_state>>30) {
case 0: ss<<" means SUCCESS"; break;
case 1: ss<<" means INFORMATIONAL"; break;
case 2: ss<<" means WARNING"; break;
case 3: ss<<" means ERROR"; break;
default: ss<<" illegal value";
}
ss<<" C="<<(_state>>29&1);
ss<<" R="<<(_state>>28&1);
ss<<" Facility=0x"<<std::hex<<std::setfill('0')<<std::setw(3)
<<(_state>>16&0xfff);
ss<<" Code=0x"<<std::hex<<std::setfill('0')<<std::setw(4)
<<(_state&0xffff);
}
return ss.str();
}
//! set state
void state(long s) {
_state = s;
}
//! @returns state
long state() {
return _state;
}
//! @returns connection id
SCARDCONTEXT id() {
return _id;
}
bool exc() {
return _exc;
}
private:
bool _exc;
SCARDCONTEXT _id;
long _state;
};
bool _exc;
SCARDCONTEXT _id;
long _state;
std::map<std::string, shared_ptr<Reader>::t > _reader;
//! 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;
};