node-pcsclite icon indicating copy to clipboard operation
node-pcsclite copied to clipboard

Implement reconnect / SCardReconnect

Open santigimeno opened this issue 11 years ago • 20 comments

santigimeno avatar Aug 06 '14 09:08 santigimeno

+1 I'm not able to reconnect to the card on the same JS instance. Is there a workaround on that? I have the Sharing violation issue coming back even if I set reader.connect with SCARD_SHARE_SHARED

iboxgithub avatar May 19 '15 23:05 iboxgithub

@iboxgithub do you have a sample code explaining your issue?

santigimeno avatar May 20 '15 08:05 santigimeno

Hi, sure

var pcsc = Npm.require('pcsclite'); var pcsc = pcsc(); //todo: change var name ?

    pcsc.on('reader', function(reader) {

        function exit() {
            reader.close();
            pcsc.close();
        }

        console.log('Using card reader: ', reader.name);

        reader.connect(/*this.SCARD_SHARE_SHARED,*/function(err, protocol) { 
            if (err) {
                console.log('Connection between middleware and card failed: ' + err);
                return exit();
            }

            //Get length
            cmd_1 = new Buffer([0x80, 0x04, 0x00, 0x00, 0x00]);
            reader.transmit(cmd_1, 255, protocol, function(err, data) {
                if (err) {
                    console.log(err);
                }
                else{
                    console.log('Data received: ', data);
                }
                return exit();
            });
        });

        reader.on('end', function() {
            console.log('***********************************************');
        });
    });
    pcsc.on('error', function(err) {
        console.log('PCSC error', err.message);
    });

iboxgithub avatar May 21 '15 21:05 iboxgithub

is this example relevant?

iboxgithub avatar May 25 '15 10:05 iboxgithub

I don't know. I'll try to implement the SCardReconnect wrapper as soon as I can if you think it can solve your issues

santigimeno avatar May 25 '15 10:05 santigimeno

Thank you very much !!! Otherwise (just in case) you don't know about any workaround for that matter?

iboxgithub avatar May 25 '15 11:05 iboxgithub

@iboxgithub WIP implementation here: https://github.com/santigimeno/node-pcsclite/pull/34. Could you test it and see if it works for you? Thanks!

santigimeno avatar May 27 '15 09:05 santigimeno

Hi Santiago, sorry about that but I have no clue how to update your package with your commit on my computer (I used the npm install command at the first time), if you give me quick steps I take care about it right after. Thanks again a lot for your help and concern.

iboxgithub avatar May 27 '15 11:05 iboxgithub

Let me know if this works for you:

# Clone this repo:
$ git clone https://github.com/santigimeno/node-pcsclite.git
$ cd node-pcsclite
# use the scardreconnect branch
$ git checkout -b scardreconnect origin/scardreconnect
# build the module
$ npm install
# run a script
$ node examples/example.js

santigimeno avatar May 27 '15 11:05 santigimeno

Hi, excuse me I didn't give feedback I came back home super late. So first, the reconnect works when I put it here

function exit() { reader.close(); reader.reconnect(function(err, protocol) {/my code/} pcsc.close(); }

Now, looking at the pcslite doc there http://pcsclite.alioth.debian.org/pcsc-lite/node13.html

I am trying to find the difference of state of my card when it had ALREADY been connected in order to put the reconnect in a loop but variables like reader.SCARD_SHARE_SHARED or reader.SCARD_RESET_CARD alwys have the same value, do you know which one will say 'the card is locked'? Extra question: is it better to the loop around the reader object or the pcsc object? (just to know if there is no buffer or some stuff like this around, I would like to be able to loop as much as I want)

Thanks for your help, I keep on testing on my side

iboxgithub avatar May 27 '15 22:05 iboxgithub

SCARD_SHARE_SHARED and SCARD_RESET_CARD are orthogonal constant values (they are not variables). One value is for dwShareMode parameter and the other is for dwInitialization parameter.

LudovicRousseau avatar May 28 '15 08:05 LudovicRousseau

@iboxgithub I think it's pretty well explained in the documentation. If a command you execute returns SCARD_W_RESET_CARD it's when you should execute reconnect. This can happen, for example, when another application connected to the card disconnects and resets the card using SCARD_RESET_CARD as disposition, and then your application tries to execute a command (transmit for example).

santigimeno avatar May 28 '15 08:05 santigimeno

Yes you are right it is straightforward, nevertheless my problem is that in JS I never catch it (0x80100068L), just Sharing violation. (0x8010000b)

I still use the same code (totally pasted from Ludovic Rousseau blog), triggered on a button click from a web interface.

pcsc.on('reader', function(reader) {

        function exit() {
            reader.close();
            pcsc.close();
        }

        reader.connect(function(err, protocol) { 
            if (err) {
                //A1 todo : SCARD_W_RESET_CARD -> how to catch this var!!!!
                if(err == 'Error: SCardConnect error: Sharing violation.(0x8010000b)'){ 
                    console.log('Trying to reconnect...');
                    reader.reconnect(function(err, protocol) {
                        if (err) {
                            return exit();
                        }
                        else{
                            cmd_1 = new Buffer([0x80, 0x04, 0x00, 0x00, 0x00]);
                            //B2 transmit after the reconnect
                            reader.transmit(cmd_1, 255, protocol, function(err, data) { 
                                if (err) {
                                    return exit();
                                }else{
                                    console.log('Data received : ', data);
                                    rreturn exit();
                                }
                            });
                        }
                    });
                }
                else{ //A1. First connection
                    return exit();
                }
            }
            else{ //A2. First connection
                cmd_1 = new Buffer([0x80, 0x04, 0x00, 0x00, 0x00]);
                reader.transmit(cmd_1, 255, protocol, function(err, data) {
                    if (err) {
                        return exit();
                    }
                    else{
                        console.log('Data received : ', data);
                        return exit();
                    }
                });
            }
        });

        reader.on('end', function() {
            console.log('Reader',  this.name, 'removed');
        });

    });

    pcsc.on('error', function(err) {
        console.log('PCSC error', err.message);
    });

iboxgithub avatar May 29 '15 18:05 iboxgithub

Despite the fact I am able to make it work within the same pcsc.on bloc, I am not able to create a new bloc and connect again, I will always have a sharing violation. Could this come from dwShareMode that is on Exclusive by default? More general : maybe this is not what Reconnect is supposed to do, so in this case sorry for bothering

iboxgithub avatar May 29 '15 18:05 iboxgithub

@iboxgithub It looks like that. Have you tried using SCARD_SHARE_SHARED mode?

As a side note, I think I should add the actual error code in the Error object

santigimeno avatar May 29 '15 19:05 santigimeno

Thanks, I succeeded to do when I wanted with SCARD_SHARE_SHARED set up in the connect function (I tried before but not using the good parameter -_-)

So, in this case there's indeed no need for the Reconnect function, but remains the case where the error SCARD_W_RESET_CARD would be returned. When the error object will be updated with that let me know, I will test it

iboxgithub avatar May 30 '15 15:05 iboxgithub

More generally what are the steps that occured when I restart my server? Because now that I copied this prototype in my real code where several transmit can occur I have an erratic behavior :

  • sometimes I am able to get the same value twice in a row (never more, I guess it could be my card reader?)
  • sometimes it works if I alternate the different values I try to get (eg: name and surname)
  • and EVERYTIME the crash occurs at the second transmit returning "Error: SCardTransmit error: Transaction failed.(0x80100016)"

So the best would be to everytime "simulate" a server restart (from the card reader POV) to have a real reconnection function no? There would be no more need for a share mode, am I missing something by inexperience?

iboxgithub avatar May 30 '15 16:05 iboxgithub

@iboxgithub I'm not sure I follow... can you post code that causes the error?

santigimeno avatar Jun 01 '15 07:06 santigimeno

My apologies, I was not properly handling an error, it is solved now, so no need to take care about my last post.

The Error object returned topic stays on the table (even though not impacting me).

iboxgithub avatar Jun 01 '15 09:06 iboxgithub

@iboxgithub That's great news! Thanks for following up the issue

santigimeno avatar Jun 01 '15 10:06 santigimeno