package ca.canuckcoding.novacom; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.util.ArrayList; public class NovacomPacket { private InputStream input; private OutputStream output; private Header header; private int index; private byte[] packet; private ArrayList<OOB> oobList; public NovacomPacket(InputStream is, OutputStream os) { input = is; output = os; header = new Header(); index = -1; packet = new byte[32768]; oobList = new ArrayList<OOB>(); } public void writeOOBClose(int file) throws IOException { byte[] oob = new byte[20]; stuffAnInt(0, oob, 0); stuffAnInt(file, oob, 4); output.write(header.createHeader(oob.length, 2)); output.write(oob); } public void write(byte[] data) throws IOException { output.write(header.createHeader(data.length, 0)); output.write(data); } public void write(byte[] data, int offset, int length) throws IOException { output.write(header.createHeader(length, 0)); output.write(data, offset, length); } public int read() throws IOException { if((index == -1) || (index >= header.getSize())) { int val = 2; while(val == 2) { val = readPacket(); if(val == -1) { return -1; } } } if (index == -1) { return -1; } int result = packet[index] & 0xFF; index++; return result; } public int readPacket() throws IOException { index = -1; int val = readArray(header.getHeader(), 16); if(val!=16) { return -1; } if(header.getMagic() != -557122643) { throw new IOException("Inalid magic number in packet: " + header.getMagic()); } int type = header.getType(); if(type==0 || type==1) { index = 0; readArray(packet, header.getSize()); } else if(type==2) { OOB oob = new OOB(); readArray(oob.getData(), header.getSize()); oobList.add(oob); } return type; } private int readArray(byte[] data, int size) throws IOException { int count = 0; try { while (count < size) { /*if(input.available()==0) { return -1; }*/ int val = input.read(data, count, size - count); if (val == -1) { return -1; } count += val; } } catch (ArrayIndexOutOfBoundsException e) { System.err.println(e.getMessage()); } return count; } public int read(byte[] data) throws IOException { int i; for(i=0; i<data.length; i++) { int curr = read(); if(curr==-1) { if(i==0) { i=-1; } break; } data[i] = (byte) curr; } return i; } public ArrayList<OOB> getOOBList() { return oobList; } private static void stuffAnInt(int val, byte[] array, int offset) { array[(offset + 0)] = (byte)(val >> 0 & 0xFF); array[(offset + 1)] = (byte)(val >> 8 & 0xFF); array[(offset + 2)] = (byte)(val >> 16 & 0xFF); array[(offset + 3)] = (byte)(val >> 24 & 0xFF); } private static int makeAnInt(int i1, int i2, int i3, int i4) { i1 &= 255; i2 &= 255; i3 &= 255; i4 &= 255; return (i1 << 0 | i2 << 8 | i3 << 16 | i4 << 24); } private class Header { private static final int TYPE_DATA = 0; private static final int TYPE_ERR = 1; private static final int TYPE_OOB = 2; private byte[] header; public Header() { header = new byte[16]; } public int getMagic() { return makeAnInt(header[0], header[1], header[2], header[3]); } public int getVersion() { return makeAnInt(header[4], header[5], header[6], header[7]); } public int getSize() { return makeAnInt(this.header[8], this.header[9], header[10], header[11]); } public int getType() { return makeAnInt(header[12], header[13], header[14], header[15]); } public byte[] createHeader(int size, int type) { stuffAnInt(-557122643, header, 0); stuffAnInt(1, header, 4); stuffAnInt(size, header, 8); stuffAnInt(type, header, 12); return header; } public byte[] getHeader() { return header; } } public class OOB { private static final int TYPE_DATA = 0; private static final int TYPE_ERR = 1; private static final int TYPE_OOB = 2; private byte[] obbData; public OOB() { obbData = new byte[20]; } public int getMessageType() { return makeAnInt(obbData[0], obbData[1], obbData[2], obbData[3]); } public int getMessagePayload() { return makeAnInt(obbData[4], obbData[5], obbData[6], obbData[7]); } public byte[] getData() { return obbData; } } }