Keyple Service Resource C++ Library - 3.1.1
Component of the Keyple C++ middleware
ReaderManagerAdapter.cpp
Go to the documentation of this file.
1/******************************************************************************
2 * Copyright (c) 2025 Calypso Networks Association https://calypsonet.org/ *
3 * *
4 * See the NOTICE file(s) distributed with this work for additional *
5 * information regarding copyright ownership. *
6 * *
7 * This program and the accompanying materials are made available under the *
8 * terms of the Eclipse Public License 2.0 which is available at *
9 * http://www.eclipse.org/legal/epl-2.0 *
10 * *
11 * SPDX-License-Identifier: EPL-2.0 *
12 ******************************************************************************/
13
14#include "keyple/core/service/resource/ReaderManagerAdapter.hpp"
15
16#include "keyple/core/service/SmartCardServiceProvider.hpp"
17#include "keyple/core/service/resource/CardResourceAdapter.hpp"
18#include "keyple/core/util/cpp/Arrays.hpp"
19#include "keyple/core/util/cpp/System.hpp"
20#include "keyple/core/util/cpp/exception/IllegalStateException.hpp"
21#include "keypop/reader/selection/spi/IsoSmartCard.hpp"
22
23namespace keyple {
24namespace core {
25namespace service {
26namespace resource {
27
28using keyple::core::service::SmartCardServiceProvider;
29using keyple::core::service::resource::CardResourceAdapter;
30using keyple::core::util::cpp::Arrays;
31using keyple::core::util::cpp::System;
32using keyple::core::util::cpp::exception::IllegalStateException;
33using keypop::reader::selection::spi::IsoSmartCard;
34
35ReaderManagerAdapter::ReaderManagerAdapter(
36 std::shared_ptr<CardReader> reader,
37 std::shared_ptr<Plugin> plugin,
38 std::shared_ptr<ReaderConfiguratorSpi> readerConfiguratorSpi,
39 const int usageTimeoutMillis)
40: mReader(reader)
41, mReaderExtension(plugin->getReaderExtension(
42 typeid(KeypleReaderExtension), reader->getName()))
43, mPlugin(plugin)
44, mReaderConfiguratorSpi(readerConfiguratorSpi)
45, mUsageTimeoutMillis(usageTimeoutMillis)
46, mSelectedCardResource(nullptr)
47, mIsBusy(false)
48, mIsActive(false)
49{
50}
51
52std::shared_ptr<CardReader>
53ReaderManagerAdapter::getReader() const
54{
55 return mReader;
56}
57
58std::shared_ptr<Plugin>
59ReaderManagerAdapter::getPlugin() const
60{
61 return mPlugin;
62}
63
64const std::vector<std::shared_ptr<CardResourceAdapter>>&
65ReaderManagerAdapter::getCardResources() const
66{
67 return mCardResources;
68}
69
70bool
71ReaderManagerAdapter::isActive() const
72{
73 return mIsActive;
74}
75
76void
77ReaderManagerAdapter::activate()
78{
79 if (!mIsActive) {
80 mReaderConfiguratorSpi->setupReader(mReader);
81 }
82
83 mIsActive = true;
84}
85
86std::shared_ptr<CardResourceAdapter>
87ReaderManagerAdapter::matches(
88 std::shared_ptr<CardResourceProfileExtension> extension)
89{
90 std::shared_ptr<CardResourceAdapter> cardResource = nullptr;
91 std::shared_ptr<SmartCard> smartCard = extension->matches(
92 mReader, SmartCardServiceProvider::getService()->getReaderApiFactory());
93
94 if (smartCard != nullptr) {
95 cardResource = getOrCreateCardResource(smartCard);
96 mSelectedCardResource = cardResource;
97 }
98
99 unlock();
100
101 return cardResource;
102}
103
104bool
105ReaderManagerAdapter::lock(
106 std::shared_ptr<CardResource> cardResource,
107 std::shared_ptr<CardResourceProfileExtension> extension)
108{
109 if (mIsBusy) {
110 if (mUsageTimeoutMillis == 0
111 || static_cast<uint64_t>(System::currentTimeMillis())
112 < mLockMaxTimeMillis) {
113 return false;
114 }
115
116 mLogger->warn(
117 "Reader automatically unlocked due to a usage timeout exceeded " \
118 "[reader=%, usageTimeoutMs=%]\n",
119 mReader->getName(),
120 mUsageTimeoutMillis);
121 }
122
123 if (mSelectedCardResource != cardResource) {
124 std::shared_ptr<SmartCard> smartCard = extension->matches(
125 mReader,
126 SmartCardServiceProvider::getService()->getReaderApiFactory());
127
128 if (!areEquals(cardResource->getSmartCard(), smartCard)) {
129 mSelectedCardResource = nullptr;
130 throw IllegalStateException(
131 "No card is inserted or its profile does not match the "
132 "associated data.");
133 }
134
135 mSelectedCardResource = cardResource;
136 }
137
138 mLockMaxTimeMillis = System::currentTimeMillis() + mUsageTimeoutMillis;
139 mIsBusy = true;
140
141 return true;
142}
143
144void
145ReaderManagerAdapter::unlock()
146{
147 mIsBusy = false;
148}
149
150void
151ReaderManagerAdapter::removeCardResource(
152 std::shared_ptr<CardResource> cardResource)
153{
154 Arrays::remove(
155 mCardResources,
156 std::dynamic_pointer_cast<CardResourceAdapter>(cardResource));
157
158 if (mSelectedCardResource == cardResource) {
159 mSelectedCardResource = nullptr;
160 }
161}
162
163std::shared_ptr<CardResourceAdapter>
164ReaderManagerAdapter::getOrCreateCardResource(
165 std::shared_ptr<SmartCard> smartCard)
166{
167 /* Check if an identical card resource is already created */
168 for (const auto& cardResource : mCardResources) {
169 if (areEquals(cardResource->getSmartCard(), smartCard)) {
170 return cardResource;
171 }
172 }
173
174 /* If none, then create a new one */
175 auto cardResource = std::make_shared<CardResourceAdapter>(
176 mReader, mReaderExtension, smartCard);
177 mCardResources.push_back(cardResource);
178
179 return cardResource;
180}
181
182bool
183ReaderManagerAdapter::areEquals(
184 const std::shared_ptr<SmartCard> s1, const std::shared_ptr<SmartCard> s2)
185{
186 if (s1 == s2) {
187 return true;
188 }
189
190 if (s1 == nullptr || s2 == nullptr) {
191 return false;
192 }
193
194 bool hasSamePowerOnData
195 = (s1->getPowerOnData() == "" && s2->getPowerOnData() == "")
196 || (s1->getPowerOnData() != ""
197 && s1->getPowerOnData() == s2->getPowerOnData());
198
199 bool hasSameFci;
200 const auto _s1 = std::dynamic_pointer_cast<IsoSmartCard>(s1);
201 const auto _s2 = std::dynamic_pointer_cast<IsoSmartCard>(s2);
202 if (_s1 && _s2) {
203 hasSameFci = Arrays::equals(
204 _s1->getSelectApplicationResponse(),
205 _s2->getSelectApplicationResponse());
206 } else {
207 hasSameFci = true;
208 }
209
210 return hasSamePowerOnData && hasSameFci;
211}
212
213} /* namespace resource */
214} /* namespace service */
215} /* namespace core */
216} /* namespace keyple */