Many resources are needed to download a project. Please understand that we have to compensate our server costs. Thank you in advance. Project price only 1 $
You can buy this project and download/modify it how often you want.
/*
* Copyright (c) 2015-2016 Martin Paljak
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
package apdu4j.remote;
import java.io.IOException;
import java.nio.ByteBuffer;
import java.util.HashMap;
import java.util.Map;
import javax.smartcardio.ATR;
import javax.smartcardio.Card;
import javax.smartcardio.CardChannel;
import javax.smartcardio.CardException;
import javax.smartcardio.CardTerminal;
import javax.smartcardio.CommandAPDU;
import javax.smartcardio.ResponseAPDU;
import apdu4j.HexUtils;
/**
* Implements the {@link CardTerminal} portion of a {@link RemoteTerminal}
*
* This class sends commands over the pipe from the server to the client.
*
* @author Martin Paljak
*/
class JSONCardTerminal extends CardTerminal {
// Connection properties
private String terminalName = null;
private ATR atr = null;
private String protocol = null;
private final JSONMessagePipe client;
public JSONCardTerminal(JSONMessagePipe c) {
// client is used for sending the actual JSON messages.
client = c;
}
@Override
public Card connect(String protocol) throws CardException {
try {
HashMap m = new HashMap<>();
m.put("cmd", "CONNECT");
m.put("protocol", protocol);
client.send(m);
// Read back the response
Map r = client.recv();
if (r.containsKey("CONNECT") && ((String)r.get("CONNECT")).equals("OK")) {
if (r.containsKey("atr") && r.containsKey("protocol") && r.containsKey("reader")) {
terminalName = (String) r.get("reader");
atr = new ATR(HexUtils.stringToBin((String) r.get("atr")));
this.protocol = ((String) r.get("protocol"));
return new JSONCard(this);
}
}
throw new CardException("Could not connect to client");
} catch (IOException e) {
throw new CardException("Could not connect to client", e);
}
}
@Override
public String getName() {
if (terminalName == null) {
return "RemoteTerminal (not connected)";
}
else {
return "RemoteTerminal (" + terminalName + ")";
}
}
@Override
public boolean isCardPresent() throws CardException {
// We always assume a present card and fail if actual connection fails.
// FIXME: assume a connectd card.
return true;
}
@Override
public boolean waitForCardAbsent(long arg0) throws CardException {
throw new CardException("JSONCardTerminal does not support polling for card removal");
}
@Override
public boolean waitForCardPresent(long arg0) throws CardException {
// FIXME: implement waiting
throw new CardException("JSONCardTerminal does not support polling");
}
private class JSONCard extends Card {
private final JSONCardTerminal terminal;
private JSONCardChannel channel = null;
protected JSONCard(JSONCardTerminal t) {
terminal = t;
}
@Override
public void beginExclusive() throws CardException {
// Do nothing, exclusiveness is expected to be maintained by the client
}
@Override
public void disconnect(boolean reset) throws CardException {
try {
HashMap m = new HashMap<>();
m.put("cmd", "DISCONNECT");
m.put("action", reset ? "reset" : "leave");
terminal.client.send(m);
// Read back FIXME throw card exception if something fails?
terminal.client.recv();
} catch (IOException e) {
throw new CardException("Disconnect failed", e);
}
}
@Override
public void endExclusive() throws CardException {
// Do nothing, exclusiveness is expected to be maintained by the client
}
@Override
public ATR getATR() {
return atr;
}
@Override
public synchronized CardChannel getBasicChannel() {
if (channel == null)
channel = new JSONCardChannel(this);
return channel;
}
@Override
public String getProtocol() {
return protocol;
}
@Override
public CardChannel openLogicalChannel() throws CardException {
throw new CardException("JSONCard does not support logical channels");
}
@Override
public byte[] transmitControlCommand(int arg0, byte[] arg1) throws CardException {
throw new CardException("JSONCard does not yet support control commands");
}
protected class JSONCardChannel extends CardChannel {
private final JSONCard card;
public JSONCardChannel(JSONCard c) {
card = c;
}
@Override
public void close() throws CardException {
// Do nothing, this is the basic channel
}
@Override
public Card getCard() {
return card;
}
@Override
public int getChannelNumber() {
// We only support the basic channel.
return 0;
}
@Override
public ResponseAPDU transmit(CommandAPDU apdu) throws CardException {
try {
String apdustring = HexUtils.bin2hex(apdu.getBytes());
Map m = JSONProtocol.cmd("APDU");
m.put("bytes", apdustring);
client.send(m);
Map r = client.recv();
if (!JSONProtocol.check(m, r)) {
throw new CardException((String)r.get("ERROR"));
}
return new ResponseAPDU(HexUtils.hex2bin((String)r.get("bytes")));
} catch (IOException e) {
throw new CardException(e);
}
}
@Override
public int transmit(ByteBuffer arg0, ByteBuffer arg1) throws CardException {
throw new CardException("JSONCardChannel only supports APDU based interface");
}
}
}
}