Skip to content

Commit 3d9d0c6

Browse files
committed
test
Signed-off-by: Raul Metsma <raul@metsma.ee>
1 parent 0de1619 commit 3d9d0c6

7 files changed

Lines changed: 58 additions & 81 deletions

File tree

src/controller/command-handlers/authenticate.cpp

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -44,12 +44,12 @@ namespace
4444
// Use common base64-encoding defaults.
4545
constexpr auto BASE64_OPTIONS = QByteArray::Base64Encoding | QByteArray::KeepTrailingEquals;
4646

47-
QVariantMap createAuthenticationToken(const QString& signatureAlgorithm,
47+
QVariantMap createAuthenticationToken(QByteArrayView signatureAlgorithm,
4848
const QByteArray& certificateDer, const QByteArray& signature)
4949
{
5050
return QVariantMap {
5151
{"unverifiedCertificate", QString(certificateDer.toBase64(BASE64_OPTIONS))},
52-
{"algorithm", signatureAlgorithm},
52+
{"algorithm", QLatin1String(signatureAlgorithm)},
5353
{"signature", QString(signature)},
5454
{"format", QStringLiteral("web-eid:1.0")},
5555
{"appVersion",
@@ -123,8 +123,7 @@ QVariantMap Authenticate::onConfirm(WebEidUI* window,
123123
const EidCertificateAndPinInfo& certAndPinInfo)
124124
{
125125
try {
126-
const auto signatureAlgorithm =
127-
QString::fromStdString(certAndPinInfo.eid->authSignatureAlgorithm());
126+
const std::string_view signatureAlgorithm = certAndPinInfo.eid->authSignatureAlgorithm();
128127
pcsc_cpp::byte_vector pin;
129128
// Reserve space for APDU overhead (5 bytes) + PIN padding (16 bytes) to prevent PIN memory
130129
// reallocation. The 16-byte limit comes from the max PIN length of 12 bytes across all card
@@ -145,7 +144,7 @@ QVariantMap Authenticate::onConfirm(WebEidUI* window,
145144
emit retry(RetriableError::PIN_VERIFY_DISABLED);
146145
break;
147146
default:
148-
emit verifyPinFailed(failure.status(), failure.retries());
147+
emit verifyPinFailed(failure.status(), failure.retries(), certAndPinInfo.eid);
149148
}
150149
if (failure.retries() > 0) {
151150
throw CommandHandlerVerifyPinFailed(failure.what());

src/controller/command-handlers/sign.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -117,7 +117,7 @@ QVariantMap Sign::onConfirm(WebEidUI* window, const EidCertificateAndPinInfo& ce
117117
emit retry(RetriableError::PIN_VERIFY_DISABLED);
118118
break;
119119
default:
120-
emit verifyPinFailed(failure.status(), failure.retries());
120+
emit verifyPinFailed(failure.status(), failure.retries(), certAndPinInfo.eid);
121121
}
122122
// Retries > 0 means that there are retries remaining,
123123
// < 0 means that retry count is unknown, == 0 means that the PIN is blocked.

src/controller/commandhandler.hpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,8 @@ class CommandHandler : public QObject
4545
void multipleCertificatesReady(const QUrl& origin,
4646
const std::vector<EidCertificateAndPinInfo>& certAndPinInfos);
4747
void singleCertificateReady(const QUrl& origin, const EidCertificateAndPinInfo& certAndPinInfo);
48-
void verifyPinFailed(electronic_id::VerifyPinFailed::Status status, qint8 retriesLeft);
48+
void verifyPinFailed(electronic_id::VerifyPinFailed::Status status, qint8 retriesLeft,
49+
electronic_id::ElectronicID::ptr eid);
4950

5051
protected:
5152
CommandHandler(const CommandWithArguments& cmd) : command(cmd) {}

src/controller/controller.cpp

Lines changed: 21 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -113,11 +113,22 @@ void Controller::startCommandExecution()
113113
// When the command handler run thread retrieves certificates successfully, call
114114
// onCertificatesLoaded() that starts card event monitoring while user enters the PIN.
115115
connect(commandHandler.get(), &CommandHandler::singleCertificateReady, this,
116-
&Controller::onCertificatesLoaded);
116+
[this](const QUrl&, const EidCertificateAndPinInfo& info) {
117+
onCertificatesLoaded({info.eid},
118+
commandType() != CommandType::SIGN);
119+
});
117120
connect(commandHandler.get(), &CommandHandler::multipleCertificatesReady, this,
118-
&Controller::onCertificatesLoaded);
121+
[this](const QUrl&, const std::vector<EidCertificateAndPinInfo>& infos) {
122+
std::vector<ElectronicID::ptr> eids;
123+
eids.reserve(infos.size());
124+
for (const auto& info : infos) {
125+
eids.push_back(info.eid);
126+
}
127+
onCertificatesLoaded(std::move(eids), true);
128+
});
129+
// verifyPinFailed restarts monitoring for the selected card.
119130
connect(commandHandler.get(), &CommandHandler::verifyPinFailed, this,
120-
&Controller::onCertificatesLoaded);
131+
[this](auto, auto, ElectronicID::ptr eid) { onCertificatesLoaded({std::move(eid)}); });
121132

122133
// UI setup.
123134
createWindow();
@@ -167,11 +178,13 @@ try {
167178
onCriticalFailure(error.what());
168179
}
169180

170-
void Controller::onCertificatesLoaded() noexcept
181+
void Controller::onCertificatesLoaded(std::vector<ElectronicID::ptr> eids,
182+
bool watchPnpNotifications) noexcept
171183
try {
172-
auto* cardEventMonitorThread = new CardEventMonitorThread(this, commandType());
184+
auto* cardEventMonitorThread =
185+
new CardEventMonitorThread(this, commandType(), std::move(eids), watchPnpNotifications);
173186
connect(this, &Controller::stopCardEventMonitorThread, cardEventMonitorThread,
174-
&CardEventMonitorThread::requestInterruption);
187+
&CardEventMonitorThread::cancelWait);
175188
connect(cardEventMonitorThread, &ControllerChildThread::failure, this,
176189
&Controller::onCriticalFailure);
177190
connect(cardEventMonitorThread, &CardEventMonitorThread::cardEvent, this, &Controller::onRetry);
@@ -225,6 +238,8 @@ try {
225238
// Command handler signals are still connected, disconnect them so that they can be
226239
// reconnected during next execution.
227240
commandHandler->disconnect();
241+
// Cancel any blocked card event monitors before waiting for threads to finish.
242+
emit stopCardEventMonitorThread();
228243
// Before restarting, wait until child threads finish.
229244
waitForChildThreads();
230245

src/controller/controller.hpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,8 @@ class Controller : public QObject
5050
onCardsAvailable(const std::vector<electronic_id::ElectronicID::ptr>& availableEids) noexcept;
5151

5252
// Called when CommandHandlerRunThread finishes execution.
53-
void onCertificatesLoaded() noexcept;
53+
void onCertificatesLoaded(std::vector<electronic_id::ElectronicID::ptr> eids,
54+
bool watchPnpNotifications = false) noexcept;
5455

5556
// Called either directly from onDialogOK().
5657
void onConfirmCommandHandler(const EidCertificateAndPinInfo& certAndPinInfo) noexcept;

src/controller/threads/cardeventmonitorthread.hpp

Lines changed: 27 additions & 66 deletions
Original file line numberDiff line numberDiff line change
@@ -24,55 +24,37 @@
2424

2525
#include "controllerchildthread.hpp"
2626

27+
#include "utils/utils.hpp"
28+
2729
class CardEventMonitorThread : public ControllerChildThread
2830
{
2931
Q_OBJECT
3032

3133
public:
3234
using eid_ptr = electronic_id::ElectronicID::ptr;
33-
using eid_ptr_vector = std::vector<electronic_id::ElectronicID::ptr>;
35+
using eid_ptr_vector = std::vector<eid_ptr>;
3436

35-
CardEventMonitorThread(QObject* parent, CommandType commandType) :
36-
ControllerChildThread(commandType, parent)
37+
CardEventMonitorThread(QObject* parent, CommandType commandType, eid_ptr_vector eids,
38+
bool watchPnpNotifications = false) :
39+
ControllerChildThread(commandType, parent), eids(std::move(eids)),
40+
monitor(makeMonitor(this->eids, watchPnpNotifications))
3741
{
3842
}
3943

40-
void run() override
44+
void cancelWait()
4145
{
42-
QMutexLocker lock {&controllerChildThreadMutex};
46+
requestInterruption();
47+
monitor.cancel();
48+
}
4349

50+
void run() override
51+
{
4452
qDebug() << "Starting" << metaObject()->className() << uintptr_t(this) << "for command"
4553
<< commandType();
4654

47-
auto initialCards = getSupportedCardsIgnoringExceptions();
48-
sortByReaderNameAndAtr(initialCards);
49-
50-
while (!isInterruptionRequested()) {
51-
using namespace std::chrono_literals;
52-
waitForControllerNotify.wait(&controllerChildThreadMutex, 1s);
53-
54-
eid_ptr_vector updatedCards {};
55-
56-
try {
57-
updatedCards = electronic_id::availableSupportedCards();
58-
sortByReaderNameAndAtr(updatedCards);
59-
} catch (const std::exception& error) {
60-
// Ignore smart card layer errors, they will be handled during next card operation.
61-
qWarning() << metaObject()->className() << "ignoring" << commandType()
62-
<< "error:" << error;
63-
}
64-
65-
// If interruption was requested during wait, exit without emitting.
66-
if (isInterruptionRequested()) {
67-
return;
68-
}
69-
70-
// If there was a change in connected supported cards, exit after emitting a card event.
71-
if (!areEqualByReaderNameAndAtr(initialCards, updatedCards)) {
72-
qDebug() << metaObject()->className() << "card change detected";
73-
emit cardEvent();
74-
return;
75-
}
55+
if (monitor.wait() && !isInterruptionRequested()) {
56+
qDebug() << metaObject()->className() << "card change detected";
57+
emit cardEvent();
7658
}
7759
}
7860

@@ -82,42 +64,21 @@ class CardEventMonitorThread : public ControllerChildThread
8264
private:
8365
void doRun() override
8466
{
85-
// Unused as run() has been overriden.
67+
// Unused as run() has been overridden.
8668
}
8769

88-
eid_ptr_vector getSupportedCardsIgnoringExceptions()
70+
static pcsc_cpp::CardEventMonitor makeMonitor(const eid_ptr_vector& eids,
71+
bool watchPnpNotifications)
8972
{
90-
while (!isInterruptionRequested()) {
91-
try {
92-
return electronic_id::availableSupportedCards();
93-
} catch (const std::exception& error) {
94-
// Ignore smart card layer errors, they will be handled during next card operation.
95-
qWarning() << metaObject()->className() << "ignoring" << commandType()
96-
<< "error:" << error;
97-
}
98-
using namespace std::chrono_literals;
99-
waitForControllerNotify.wait(&controllerChildThreadMutex, 1s);
73+
REQUIRE_NOT_EMPTY_CONTAINS_NON_NULL_PTRS(eids)
74+
std::vector<std::reference_wrapper<const pcsc_cpp::SmartCard>> cards;
75+
cards.reserve(eids.size());
76+
for (const auto& eid : eids) {
77+
cards.push_back(eid->smartcard());
10078
}
101-
// Interruption was requested, return empty list.
102-
return {};
79+
return pcsc_cpp::CardEventMonitor(std::move(cards), watchPnpNotifications);
10380
}
10481

105-
static void sortByReaderNameAndAtr(eid_ptr_vector& a)
106-
{
107-
std::sort(a.begin(), a.end(), [](const eid_ptr& c1, const eid_ptr& c2) {
108-
if (c1->smartcard().readerName() != c2->smartcard().readerName()) {
109-
return c1->smartcard().readerName() < c2->smartcard().readerName();
110-
}
111-
return c1->smartcard().atr() < c2->smartcard().atr();
112-
});
113-
}
114-
115-
static bool areEqualByReaderNameAndAtr(const eid_ptr_vector& a, const eid_ptr_vector& b)
116-
{
117-
return std::equal(a.cbegin(), a.cend(), b.cbegin(), b.cend(),
118-
[](const eid_ptr& c1, const eid_ptr& c2) {
119-
return c1->smartcard().readerName() == c2->smartcard().readerName()
120-
&& c1->smartcard().atr() == c2->smartcard().atr();
121-
});
122-
}
82+
eid_ptr_vector eids;
83+
pcsc_cpp::CardEventMonitor monitor;
12384
};

0 commit comments

Comments
 (0)