/* * Copyright 2017 Licel Corporation. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.licel.jcardsim.remote; import java.io.DataInputStream; import java.io.DataOutputStream; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.net.Socket; import java.util.Formatter; import java.util.concurrent.TimeUnit; public class BixVReaderTCPProtocol implements BixVReaderProtocol { private Socket socket; private Socket eventSocket; private DataInputStream dataInput; private DataOutputStream dataOutput; private DataOutputStream eventOutput; public void connect(String host, int port, int event_port) throws IOException { socket = new Socket(host, port); try { TimeUnit.SECONDS.sleep(3); } catch (InterruptedException ignore) {} eventSocket = new Socket(host, event_port); dataInput = new DataInputStream(socket.getInputStream()); dataOutput = new DataOutputStream(socket.getOutputStream()); eventOutput = new DataOutputStream(eventSocket.getOutputStream()); } public void disconnect() { closeSocket(socket); closeSocket(eventSocket); } public int readCommand() throws IOException { byte[] cmdBuf = new byte[4]; readFully(cmdBuf, dataInput); int cmd = cmdFromBytes(cmdBuf); return cmd; } public byte[] readData() throws IOException { int dataLen = readCommand(); byte[] dataBuf = new byte[dataLen]; readFully(dataBuf, dataInput); return dataBuf; } public void writeData(byte[] data) throws IOException { byte[] dataBuf = new byte[4 + data.length]; byte[] dataLen = cmdToBytes(data.length); System.arraycopy(dataLen, 0, dataBuf, 0, 4); System.arraycopy(data, 0, dataBuf, 4, data.length); dataOutput.write(dataBuf); } public void writeDataCommand(int cmd) throws IOException { writeCommand(dataOutput, cmd); } public void writeEventCommand(int cmd) throws IOException { writeCommand(eventOutput, cmd); } private static String bytesToHex(byte[] bytes) { Formatter formatter = new Formatter(); for (byte b : bytes) { formatter.format("%02X ", b); } return formatter.toString(); } private void closeSocket(Socket sock) { try { sock.close(); } catch (IOException ignored) {} } private int cmdFromBytes(byte[] cmd) { return cmd[0] & 0xFF | (cmd[1] & 0xFF) << 8 | (cmd[2] & 0xFF) << 16 | (cmd[3] & 0xFF) << 24; } private byte[] cmdToBytes(int cmd) { return new byte[] { (byte) (cmd), (byte) (cmd >>> 8), (byte) (cmd >>> 16), (byte) (cmd >>> 24) }; } private void readFully(byte[] buf, InputStream stream) throws IOException { int len = buf.length; int offset = 0; while (len > 0) { int retval = stream.read(buf, offset, len); if (retval < 0) { throw new IOException("Got negative number from socket"); } len -= retval; offset += retval; } } private void writeCommand(OutputStream stream, int cmd) throws IOException { byte[] buf = cmdToBytes(cmd); stream.write(buf, 0, buf.length); } }