smartcard 2.0.1 → 2.0.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/lib/devices.js +38 -8
- package/package.json +1 -1
package/lib/devices.js
CHANGED
|
@@ -50,6 +50,8 @@ class Devices extends EventEmitter {
|
|
|
50
50
|
this._running = false;
|
|
51
51
|
/** @type {Map<string, ReaderState>} */
|
|
52
52
|
this._readers = new Map();
|
|
53
|
+
/** @type {Promise<void>} Event queue to serialize event handling */
|
|
54
|
+
this._eventQueue = Promise.resolve();
|
|
53
55
|
}
|
|
54
56
|
|
|
55
57
|
/**
|
|
@@ -131,10 +133,20 @@ class Devices extends EventEmitter {
|
|
|
131
133
|
|
|
132
134
|
/**
|
|
133
135
|
* Handle events from native monitor
|
|
136
|
+
* Queues events to prevent race conditions when multiple events arrive concurrently
|
|
137
|
+
* @param {MonitorEvent} event
|
|
138
|
+
*/
|
|
139
|
+
_handleEvent(event) {
|
|
140
|
+
// Chain this event onto the queue to serialize processing
|
|
141
|
+
this._eventQueue = this._eventQueue.then(() => this._processEvent(event));
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
/**
|
|
145
|
+
* Process a single event (called sequentially via queue)
|
|
134
146
|
* @param {MonitorEvent} event
|
|
135
147
|
* @returns {Promise<void>}
|
|
136
148
|
*/
|
|
137
|
-
async
|
|
149
|
+
async _processEvent(event) {
|
|
138
150
|
if (!this._running) {
|
|
139
151
|
return;
|
|
140
152
|
}
|
|
@@ -143,7 +155,7 @@ class Devices extends EventEmitter {
|
|
|
143
155
|
|
|
144
156
|
switch (type) {
|
|
145
157
|
case 'reader-attached':
|
|
146
|
-
this._handleReaderAttached(readerName, state, atr);
|
|
158
|
+
await this._handleReaderAttached(readerName, state, atr);
|
|
147
159
|
break;
|
|
148
160
|
|
|
149
161
|
case 'reader-detached':
|
|
@@ -170,8 +182,9 @@ class Devices extends EventEmitter {
|
|
|
170
182
|
* @param {string} readerName
|
|
171
183
|
* @param {number} state
|
|
172
184
|
* @param {Buffer|null} atr
|
|
185
|
+
* @returns {Promise<void>}
|
|
173
186
|
*/
|
|
174
|
-
_handleReaderAttached(readerName, state, atr) {
|
|
187
|
+
async _handleReaderAttached(readerName, state, atr) {
|
|
175
188
|
// Initialize reader state
|
|
176
189
|
this._readers.set(readerName, {
|
|
177
190
|
hasCard: false,
|
|
@@ -189,7 +202,7 @@ class Devices extends EventEmitter {
|
|
|
189
202
|
|
|
190
203
|
// Check if card is already present
|
|
191
204
|
if ((state & SCARD_STATE_PRESENT) !== 0) {
|
|
192
|
-
this._handleCardInserted(readerName, state, atr);
|
|
205
|
+
await this._handleCardInserted(readerName, state, atr);
|
|
193
206
|
}
|
|
194
207
|
}
|
|
195
208
|
|
|
@@ -233,10 +246,27 @@ class Devices extends EventEmitter {
|
|
|
233
246
|
const reader = readers.find(r => r.name === readerName);
|
|
234
247
|
|
|
235
248
|
if (reader) {
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
249
|
+
let card;
|
|
250
|
+
try {
|
|
251
|
+
// First try with both T=0 and T=1 protocols
|
|
252
|
+
card = await reader.connect(
|
|
253
|
+
SCARD_SHARE_SHARED,
|
|
254
|
+
SCARD_PROTOCOL_T0 | SCARD_PROTOCOL_T1
|
|
255
|
+
);
|
|
256
|
+
} catch (dualProtocolErr) {
|
|
257
|
+
// If dual protocol fails (e.g., SCARD_W_UNRESPONSIVE_CARD),
|
|
258
|
+
// fallback to T=0 only (issue #34)
|
|
259
|
+
if (dualProtocolErr.message &&
|
|
260
|
+
dualProtocolErr.message.toLowerCase().includes('unresponsive')) {
|
|
261
|
+
card = await reader.connect(
|
|
262
|
+
SCARD_SHARE_SHARED,
|
|
263
|
+
SCARD_PROTOCOL_T0
|
|
264
|
+
);
|
|
265
|
+
} else {
|
|
266
|
+
// Re-throw if it's a different error
|
|
267
|
+
throw dualProtocolErr;
|
|
268
|
+
}
|
|
269
|
+
}
|
|
240
270
|
|
|
241
271
|
state.card = card;
|
|
242
272
|
|