src: fix reader disconnection logic

- A reader disconnection can't be detected by SCardGetStatusChange in the reader
  (cardreader.cpp) but by detecting that the reader doesn't appear in the list of
  readers retrieved in pcsclite.cpp.
- The list of readers is now stored in an object where the keys are the names of
  the readers. When a reader disconnection is detected, the reader is closed
  triggering the 'end' event. Then the reader is removed from the readers list.
This commit is contained in:
Santiago Gimeno
2015-09-23 12:41:37 +02:00
parent 8f3309520d
commit 0a3eaafb2b
2 changed files with 20 additions and 15 deletions

View File

@@ -20,9 +20,18 @@ var parse_readers_string = function(readers_str) {
return readers;
};
/*
* It returns an array with the elements contained in a that aren't contained in b
*/
function diff(a, b) {
return a.filter(function(i) {
return b.indexOf(i) === -1;
});
};
module.exports = function() {
var readers = [];
var readers = {};
var p = new PCSCLite();
process.nextTick(function() {
p.start(function(err, data) {
@@ -32,19 +41,13 @@ module.exports = function() {
var names = parse_readers_string(data);
var new_names = readers.length === 0 ? names : names.filter(function(name) {
return readers.every(function(reader) {
return reader.name !== name;
});
});
readers = readers.filter(function(reader) {
return names.indexOf(reader.name) !== -1;
});
var current_names = Object.keys(readers);
var new_names = diff(names, current_names);
var removed_names = diff(current_names, names);
new_names.forEach(function(name) {
var r = new CardReader(name);
readers.push(r);
readers[name] = r;
r.get_status(function(err, state, atr) {
if (err) {
return r.emit('error', err);
@@ -62,10 +65,15 @@ module.exports = function() {
r.on('_end', function() {
r.removeAllListeners('status');
r.emit('end');
delete readers[name];
});
p.emit('reader', r);
});
removed_names.forEach(function(name) {
readers[name].close();
});
});
});

View File

@@ -383,10 +383,7 @@ void CardReader::HandlerFunction(void* arg) {
while (keep_watching) {
result = SCardGetStatusChange(reader->m_status_card_context, INFINITE, &card_reader_state, 1);
keep_watching = ((result == SCARD_S_SUCCESS) &&
(!reader->m_state) &&
(!((card_reader_state.dwEventState & SCARD_STATE_UNKNOWN) ||
(card_reader_state.dwEventState & SCARD_STATE_UNAVAILABLE))));
keep_watching = (result == SCARD_S_SUCCESS) && (!reader->m_state);
uv_mutex_lock(&reader->m_mutex);
if (reader->m_state == 1) {