package seng302.visualiser; import java.io.ByteArrayOutputStream; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.net.Socket; import java.util.ArrayList; import java.util.List; import java.util.Queue; import java.util.concurrent.ConcurrentLinkedQueue; import java.util.zip.CRC32; import java.util.zip.Checksum; import seng302.model.stream.packets.StreamPacket; import seng302.server.messages.BoatActionMessage; import seng302.server.messages.Message; /** * Created by kre39 on 13/07/17. */ public class ClientToServerThread extends Thread { private Queue streamPackets = new ConcurrentLinkedQueue<>(); private List listeners = new ArrayList<>(); private Socket socket; private InputStream is; private OutputStream os; private final int PORT_NUMBER = 0; private static final int LOG_LEVEL = 1; private Boolean updateClient = true; private ByteArrayOutputStream crcBuffer; public ClientToServerThread(String ipAddress, Integer portNumber){ try { socket = new Socket(ipAddress, portNumber); is = socket.getInputStream(); os = socket.getOutputStream(); } catch (IOException e) { e.printStackTrace(); } } static void serverLog(String message, int logLevel){ if(logLevel <= LOG_LEVEL){ System.out.println("[SERVER] " + message); } } public void run() { int sync1; int sync2; // TODO: 14/07/17 wmu16 - Work out how to fix this while loop while(true) { try { crcBuffer = new ByteArrayOutputStream(); sync1 = readByte(); sync2 = readByte(); //checking if it is the start of the packet if(sync1 == 0x47 && sync2 == 0x83) { int type = readByte(); //No. of milliseconds since Jan 1st 1970 long timeStamp = Message.bytesToLong(getBytes(6)); skipBytes(4); long payloadLength = Message.bytesToLong(getBytes(2)); byte[] payload = getBytes((int) payloadLength); Checksum checksum = new CRC32(); checksum.update(crcBuffer.toByteArray(), 0, crcBuffer.size()); long computedCrc = checksum.getValue(); long packetCrc = Message.bytesToLong(getBytes(4)); if (computedCrc == packetCrc) { // streamPackets.add(new StreamPacket(type, payloadLength, timeStamp, payload)); for (ClientSocketListener csl : listeners) csl.newPacket(new StreamPacket(type, payloadLength, timeStamp, payload)); } else { System.err.println("Packet has been dropped"); } } } catch (Exception e) { closeSocket(); return; } } } /** * Send the post-start race course information */ public void sendBoatActionMessage(BoatActionMessage boatActionMessage) { try { os.write(boatActionMessage.getBuffer()); } catch (IOException e) { e.printStackTrace(); } } public void closeSocket() { try { socket.close(); } catch (IOException e) { System.out.println("IO error in server thread upon trying to close socket"); } } public void addStreamObserver (ClientSocketListener streamListener) { listeners.add(streamListener); } public void removeStreamObserver (ClientSocketListener streamListener) { listeners.remove(streamListener); } private int readByte() throws Exception { int currentByte = -1; try { currentByte = is.read(); crcBuffer.write(currentByte); } catch (IOException e) { e.printStackTrace(); } if (currentByte == -1){ throw new Exception(); } return currentByte; } private byte[] getBytes(int n) throws Exception{ byte[] bytes = new byte[n]; for (int i = 0; i < n; i++){ bytes[i] = (byte) readByte(); } return bytes; } private void skipBytes(long n) throws Exception{ for (int i=0; i < n; i++){ readByte(); } } }