use of org.openecard.common.ifd.scio.SCIOException in project open-ecard by ecsec.
the class IfdEventRunner method fireEvents.
private void fireEvents(@Nonnull List<IFDStatusType> diff) {
for (IFDStatusType term : diff) {
String ifdName = term.getIFDName();
// find out if the terminal is new, or only a slot got updated
IFDStatusType oldTerm = getCorresponding(ifdName, currentState);
boolean terminalAdded = oldTerm == null;
IFDCapabilitiesType slotCapabilities = getCapabilities(ifdName);
if (terminalAdded) {
// TERMINAL ADDED
// make copy of term
oldTerm = new IFDStatusType();
oldTerm.setIFDName(ifdName);
oldTerm.setConnected(true);
// add to current list
currentState.add(oldTerm);
// create event
ConnectionHandleType h = makeConnectionHandle(ifdName, null, slotCapabilities);
LOG.debug("Found a terminal added event ({}).", ifdName);
env.getEventDispatcher().notify(EventType.TERMINAL_ADDED, new IfdEventObject(h));
}
// check each slot
for (SlotStatusType slot : term.getSlotStatus()) {
SlotStatusType oldSlot = getCorresponding(slot.getIndex(), oldTerm.getSlotStatus());
boolean cardPresent = slot.isCardAvailable();
boolean cardWasPresent = oldSlot != null && oldSlot.isCardAvailable();
if (cardPresent && !cardWasPresent) {
// CARD INSERTED
// copy slot and add to list
SlotStatusType newSlot = oldSlot;
if (newSlot == null) {
newSlot = new SlotStatusType();
oldTerm.getSlotStatus().add(newSlot);
}
newSlot.setIndex(slot.getIndex());
newSlot.setCardAvailable(true);
newSlot.setATRorATS(slot.getATRorATS());
// create event
LOG.debug("Found a card insert event ({}).", ifdName);
LOG.info("Card with ATR={} inserted.", ByteUtils.toHexString(slot.getATRorATS()));
ConnectionHandleType handle = makeUnknownCardHandle(ifdName, newSlot, slotCapabilities);
env.getEventDispatcher().notify(EventType.CARD_INSERTED, new IfdEventObject(handle));
try {
SingleThreadChannel ch = cm.openMasterChannel(ifdName);
if (evtManager.isRecognize()) {
String proto = ch.getChannel().getCard().getProtocol().toUri();
evtManager.threadPool.submit(new Recognizer(env, handle, proto));
}
} catch (NoSuchTerminal | SCIOException ex) {
LOG.error("Failed to connect card, nevertheless sending CARD_INSERTED event.", ex);
}
} else if (!terminalAdded && !cardPresent && cardWasPresent) {
// this makes only sense when the terminal was already there
// CARD REMOVED
// remove slot entry
BigInteger idx = oldSlot.getIndex();
Iterator<SlotStatusType> it = oldTerm.getSlotStatus().iterator();
while (it.hasNext()) {
SlotStatusType next = it.next();
if (idx.equals(next.getIndex())) {
it.remove();
break;
}
}
LOG.debug("Found a card removed event ({}).", ifdName);
ConnectionHandleType h = makeConnectionHandle(ifdName, idx, slotCapabilities);
env.getEventDispatcher().notify(EventType.CARD_REMOVED, new IfdEventObject(h));
}
}
// terminal removed event comes after card removed events
boolean terminalPresent = term.isConnected();
if (!terminalPresent) {
// TERMINAL REMOVED
Iterator<IFDStatusType> it = currentState.iterator();
while (it.hasNext()) {
IFDStatusType toDel = it.next();
if (toDel.getIFDName().equals(term.getIFDName())) {
it.remove();
}
}
ConnectionHandleType h = makeConnectionHandle(ifdName, null, slotCapabilities);
LOG.debug("Found a terminal removed event ({}).", ifdName);
env.getEventDispatcher().notify(EventType.TERMINAL_REMOVED, new IfdEventObject(h));
}
}
}
use of org.openecard.common.ifd.scio.SCIOException in project open-ecard by ecsec.
the class IFD method beginTransaction.
@Override
public BeginTransactionResponse beginTransaction(BeginTransaction beginTransaction) {
try {
BeginTransactionResponse response;
if (!hasContext()) {
String msg = "Context not initialized.";
Result r = WSHelper.makeResultError(ECardConstants.Minor.IFD.INVALID_SLOT_HANDLE, msg);
response = WSHelper.makeResponse(BeginTransactionResponse.class, r);
return response;
}
try {
byte[] handle = beginTransaction.getSlotHandle();
SingleThreadChannel ch = cm.getSlaveChannel(handle);
ch.beginExclusive();
} catch (NoSuchChannel | IllegalStateException ex) {
String msg = "No card available in the requested terminal.";
Result r = WSHelper.makeResultError(ECardConstants.Minor.IFD.INVALID_SLOT_HANDLE, msg);
response = WSHelper.makeResponse(BeginTransactionResponse.class, r);
LOG.warn(msg, ex);
return response;
} catch (SCIOException ex) {
String msg;
String minor;
switch(ex.getCode()) {
case SCARD_W_RESET_CARD:
case SCARD_W_REMOVED_CARD:
case SCARD_E_READER_UNAVAILABLE:
case SCARD_E_NO_SMARTCARD:
case SCARD_E_NO_SERVICE:
msg = String.format("Slot handle is not available [%s].", ex.getCode().name());
minor = ECardConstants.Minor.IFD.INVALID_SLOT_HANDLE;
LOG.debug(msg, ex);
break;
default:
msg = "Unknown error in the underlying SCIO implementation.";
minor = ECardConstants.Minor.App.UNKNOWN_ERROR;
LOG.warn(msg, ex);
}
Result r = WSHelper.makeResultError(minor, msg);
response = WSHelper.makeResponse(BeginTransactionResponse.class, r);
return response;
}
response = WSHelper.makeResponse(BeginTransactionResponse.class, WSHelper.makeResultOK());
return response;
} catch (Exception ex) {
LOG.warn(ex.getMessage(), ex);
throwThreadKillException(ex);
return WSHelper.makeResponse(BeginTransactionResponse.class, WSHelper.makeResult(ex));
}
}
use of org.openecard.common.ifd.scio.SCIOException in project open-ecard by ecsec.
the class IFD method transmit.
@Publish
@Override
public TransmitResponse transmit(Transmit parameters) {
try {
TransmitResponse response;
if (!hasContext()) {
String msg = "Context not initialized.";
Result r = WSHelper.makeResultError(ECardConstants.Minor.IFD.INVALID_SLOT_HANDLE, msg);
response = WSHelper.makeResponse(TransmitResponse.class, r);
return response;
}
try {
byte[] handle = parameters.getSlotHandle();
SingleThreadChannel ch = cm.getSlaveChannel(handle);
List<InputAPDUInfoType> apdus = parameters.getInputAPDUInfo();
// check that the apdus contain sane values
for (InputAPDUInfoType apdu : apdus) {
for (byte[] code : apdu.getAcceptableStatusCode()) {
if (code.length == 0 || code.length > 2) {
String msg = "Invalid accepted status code given.";
Result r = WSHelper.makeResultError(ECardConstants.Minor.App.PARM_ERROR, msg);
response = WSHelper.makeResponse(TransmitResponse.class, r);
return response;
}
}
}
// transmit APDUs and stop if an error occurs or a not expected status is hit
response = WSHelper.makeResponse(TransmitResponse.class, WSHelper.makeResultOK());
Result result;
List<byte[]> rapdus = response.getOutputAPDU();
try {
for (InputAPDUInfoType capdu : apdus) {
byte[] rapdu = ch.transmit(capdu.getInputAPDU(), capdu.getAcceptableStatusCode());
rapdus.add(rapdu);
}
result = WSHelper.makeResultOK();
} catch (TransmitException ex) {
rapdus.add(ex.getResponseAPDU());
result = ex.getResult();
} catch (SCIOException ex) {
String msg = "Error during transmit.";
LOG.warn(msg, ex);
result = WSHelper.makeResultUnknownError(msg);
} catch (IllegalStateException ex) {
String msg = "Card removed during transmit.";
LOG.warn(msg, ex);
result = WSHelper.makeResultError(ECardConstants.Minor.IFD.INVALID_SLOT_HANDLE, msg);
} catch (IllegalArgumentException ex) {
String msg = "Given command contains a MANAGE CHANNEL APDU.";
LOG.error(msg, ex);
result = WSHelper.makeResultError(ECardConstants.Minor.IFD.INVALID_SLOT_HANDLE, msg);
}
response.setResult(result);
return response;
} catch (NoSuchChannel | IllegalStateException ex) {
String msg = "No card with transaction available in the requested terminal.";
Result r = WSHelper.makeResultError(ECardConstants.Minor.IFD.INVALID_SLOT_HANDLE, msg);
response = WSHelper.makeResponse(TransmitResponse.class, r);
LOG.warn(msg, ex);
return response;
}
} catch (Exception ex) {
LOG.warn(ex.getMessage(), ex);
throwThreadKillException(ex);
return WSHelper.makeResponse(TransmitResponse.class, WSHelper.makeResult(ex));
}
}
use of org.openecard.common.ifd.scio.SCIOException in project open-ecard by ecsec.
the class IFD method getIFDCapabilities.
@Override
public GetIFDCapabilitiesResponse getIFDCapabilities(GetIFDCapabilities parameters) {
GetIFDCapabilitiesResponse response;
// you thought of a different IFD obviously
if (!ByteUtils.compare(ctxHandle, parameters.getContextHandle())) {
String msg = "Invalid context handle specified.";
Result r = WSHelper.makeResultError(ECardConstants.Minor.IFD.INVALID_CONTEXT_HANDLE, msg);
response = WSHelper.makeResponse(GetIFDCapabilitiesResponse.class, r);
return response;
}
try {
TerminalInfo info;
String ifdName = parameters.getIFDName();
try {
SingleThreadChannel channel = cm.openMasterChannel(ifdName);
info = new TerminalInfo(cm, channel);
} catch (NoSuchTerminal ex) {
// continue without a channel
SCIOTerminal term = cm.getTerminals().getTerminal(ifdName);
info = new TerminalInfo(cm, term);
}
IFDCapabilitiesType cap = new IFDCapabilitiesType();
// slot capability
SlotCapabilityType slotCap = info.getSlotCapability();
cap.getSlotCapability().add(slotCap);
// ask protocol factory which types it supports
List<String> protocols = slotCap.getProtocol();
for (String proto : protocolFactories.protocols()) {
if (!protocols.contains(proto)) {
protocols.add(proto);
}
}
// TODO: PIN Compare should be a part of establishChannel and thus just appear in the software protocol list
if (!protocols.contains(ECardConstants.Protocol.PIN_COMPARE)) {
protocols.add(ECardConstants.Protocol.PIN_COMPARE);
}
// display capability
DisplayCapabilityType dispCap = info.getDisplayCapability();
if (dispCap != null) {
cap.getDisplayCapability().add(dispCap);
}
// keypad capability
KeyPadCapabilityType keyCap = info.getKeypadCapability();
if (keyCap != null) {
cap.getKeyPadCapability().add(keyCap);
}
// biosensor capability
BioSensorCapabilityType bioCap = info.getBiosensorCapability();
if (bioCap != null) {
cap.getBioSensorCapability().add(bioCap);
}
// acoustic and optical elements
cap.setOpticalSignalUnit(info.isOpticalSignal());
cap.setAcousticSignalUnit(info.isAcousticSignal());
// prepare response
response = WSHelper.makeResponse(GetIFDCapabilitiesResponse.class, WSHelper.makeResultOK());
response.setIFDCapabilities(cap);
return response;
} catch (NullPointerException | NoSuchTerminal ex) {
String msg = String.format("Requested terminal not found.");
LOG.warn(msg, ex);
Result r = WSHelper.makeResultError(ECardConstants.Minor.IFD.Terminal.UNKNOWN_IFD, msg);
response = WSHelper.makeResponse(GetIFDCapabilitiesResponse.class, r);
return response;
} catch (SCIOException ex) {
String msg = String.format("Failed to request status from terminal.");
// use debug when card has been removed, as this happens all the time
SCIOErrorCode code = ex.getCode();
if (!(code == SCIOErrorCode.SCARD_E_NO_SMARTCARD || code == SCIOErrorCode.SCARD_W_REMOVED_CARD)) {
LOG.warn(msg, ex);
} else {
LOG.debug(msg, ex);
}
Result r = WSHelper.makeResultUnknownError(msg);
response = WSHelper.makeResponse(GetIFDCapabilitiesResponse.class, r);
return response;
}
}
use of org.openecard.common.ifd.scio.SCIOException in project open-ecard by ecsec.
the class IFD method wait.
@Override
public WaitResponse wait(Wait parameters) {
WaitResponse response;
// you thought of a different IFD obviously
if (!ByteUtils.compare(ctxHandle, parameters.getContextHandle())) {
String msg = "Invalid context handle specified.";
Result r = WSHelper.makeResultError(ECardConstants.Minor.IFD.INVALID_CONTEXT_HANDLE, msg);
response = WSHelper.makeResponse(WaitResponse.class, r);
return response;
}
// get timeout value
BigInteger timeout = parameters.getTimeOut();
if (timeout == null) {
timeout = BigInteger.valueOf(Long.MAX_VALUE);
}
if (timeout.signum() == -1 || timeout.signum() == 0) {
String msg = "Invalid timeout value given, must be strictly positive.";
Result r = WSHelper.makeResultUnknownError(msg);
response = WSHelper.makeResponse(WaitResponse.class, r);
return response;
}
long timeoutL;
try {
timeoutL = (long) timeout.doubleValue();
} catch (ArithmeticException ex) {
LOG.warn("Too big timeout value give, shortening to Long.MAX_VALUE.");
timeoutL = Long.MAX_VALUE;
}
ChannelHandleType callback = parameters.getCallback();
// callback is only useful with a protocol termination point
if (callback != null && callback.getProtocolTerminationPoint() == null) {
callback = null;
}
// if callback, generate session id
String sessionId = null;
if (callback != null) {
ChannelHandleType newCallback = new ChannelHandleType();
newCallback.setBinding(callback.getBinding());
newCallback.setPathSecurity(callback.getPathSecurity());
newCallback.setProtocolTerminationPoint(callback.getProtocolTerminationPoint());
sessionId = ValueGenerators.genBase64Session();
newCallback.setSessionIdentifier(sessionId);
callback = newCallback;
}
try {
EventWatcher watcher = new EventWatcher(cm, timeoutL, callback);
List<IFDStatusType> initialState = watcher.start();
// get expected status or initial status for all if none specified
List<IFDStatusType> expectedState = parameters.getIFDStatus();
if (expectedState.isEmpty()) {
expectedState = initialState;
} else {
for (IFDStatusType s : expectedState) {
// check that ifdname is present, needed for comparison
if (s.getIFDName() == null) {
String msg = "IFD in a request IFDStatus not known.";
Result r = WSHelper.makeResultError(ECardConstants.Minor.IFD.Terminal.UNKNOWN_IFD, msg);
response = WSHelper.makeResponse(WaitResponse.class, r);
return response;
}
// check that at least one slot entry is present
if (s.getSlotStatus().isEmpty()) {
// assume an empty one
SlotStatusType slot = new SlotStatusType();
slot.setCardAvailable(false);
slot.setIndex(BigInteger.ZERO);
s.getSlotStatus().add(slot);
}
}
}
watcher.setExpectedState(expectedState);
// create the future and fire
FutureTask<List<IFDStatusType>> future = new FutureTask<>(watcher);
if (watcher.isAsync()) {
// add future to async wait list
asyncWaitThreads.put(sessionId, future);
// finally run this darn thingy
threadPool.execute(future);
// prepare result with session id in it
response = WSHelper.makeResponse(WaitResponse.class, WSHelper.makeResultOK());
response.setSessionIdentifier(sessionId);
return response;
} else {
// run wait in a future so it can be easily interrupted
syncWaitThread = future;
threadPool.execute(future);
// get results from the future
List<IFDStatusType> events = future.get();
// prepare response
response = WSHelper.makeResponse(WaitResponse.class, WSHelper.makeResultOK());
response.getIFDEvent().addAll(events);
return response;
}
} catch (SCIOException ex) {
String msg = "Unknown SCIO error occured during wait call.";
LOG.warn(msg, ex);
Result r = WSHelper.makeResultUnknownError(msg);
response = WSHelper.makeResponse(WaitResponse.class, r);
return response;
} catch (ExecutionException ex) {
// this is the exception from within the future
Throwable cause = ex.getCause();
if (cause instanceof SCIOException) {
String msg = "Unknown SCIO error occured during wait call.";
LOG.warn(msg, cause);
Result r = WSHelper.makeResultUnknownError(msg);
response = WSHelper.makeResponse(WaitResponse.class, r);
} else {
String msg = "Unknown error during wait call.";
LOG.error(msg, cause);
Result r = WSHelper.makeResultUnknownError(msg);
response = WSHelper.makeResponse(WaitResponse.class, r);
}
return response;
} catch (InterruptedException ex) {
String msg = "Wait interrupted by another thread.";
LOG.warn(msg, ex);
Result r = WSHelper.makeResultUnknownError(msg);
response = WSHelper.makeResponse(WaitResponse.class, r);
return response;
}
}
Aggregations