package net.floodlightcontroller.packet; import java.nio.ByteBuffer; import java.util.Arrays; /** * @author Jacob Chappell (jacob.chappell@uky.edu) */ public class SPUD extends BasePacket { public static final byte[] MAGIC_CONSTANT = { (byte) 0xd8, 0x00, 0x00, (byte) 0xd8 }; public static final int HEADER_LENGTH = 13; public static final byte COMMAND_DATA = 0x0; public static final byte COMMAND_OPEN = 0x1; public static final byte COMMAND_CLOSE = 0x2; public static final byte COMMAND_ACK = 0x3; protected long tubeID; protected byte command; protected boolean adec; protected boolean pdec; protected byte reserved; public long getTubeID() { return tubeID; } public SPUD setTubeID(long tubeID) { this.tubeID = tubeID; return this; } public byte getCommand() { return command; } public SPUD setCommand(byte command) { this.command = command; return this; } public boolean getADEC() { return adec; } public SPUD setADEC(boolean adec) { this.adec = adec; return this; } public boolean getPDEC() { return pdec; } public SPUD setPDEC(boolean pdec) { this.pdec = pdec; return this; } public byte getReserved() { return reserved; } public SPUD setReserved(byte reserved) { this.reserved = reserved; return this; } @Override public byte[] serialize() { byte[] payloadData = null; if (payload != null) { payload.setParent(this); payloadData = payload.serialize(); } int length = HEADER_LENGTH + ((payloadData == null) ? 0 : payloadData.length); byte[] data = new byte[length]; ByteBuffer bb = ByteBuffer.wrap(data); bb.put(MAGIC_CONSTANT); bb.putLong(tubeID); byte adecBit = (byte) ((adec) ? 1 : 0); byte pdecBit = (byte) ((pdec) ? 1 : 0); byte lastByte = (byte) (((command & 0x3) << 6) | ((adecBit & 0x1) << 5) | ((pdecBit & 0x1) << 4) | (reserved & 0xf)); bb.put(lastByte); if (payloadData != null) { bb.put(payloadData); } return data; } @Override public IPacket deserialize(byte[] data, int offset, int length) throws PacketParsingException { ByteBuffer bb = ByteBuffer.wrap(data, offset, length); byte[] magicConstant = new byte[MAGIC_CONSTANT.length]; bb.get(magicConstant, 0, MAGIC_CONSTANT.length); if (!Arrays.equals(magicConstant, MAGIC_CONSTANT)) { throw new PacketParsingException("Magic constant is incorrect."); } tubeID = bb.getLong(); byte lastByte = bb.get(); command = (byte) ((lastByte & 0xc0) >>> 6); adec = ((lastByte & 0x20) != 0); pdec = ((lastByte & 0x10) != 0); reserved = (byte) (lastByte & 0xF); // TODO: make sure reserved bits are 0 for this version. this.payload = new Data(); this.payload = payload.deserialize(data, bb.position(), bb.limit()-bb.position()); this.payload.setParent(this); return this; } /* (non-Javadoc) * @see java.lang.Object#hashCode() */ @Override public int hashCode() { final int prime = 31; int result = super.hashCode(); result = prime * result + (adec ? 1231 : 1237); result = prime * result + command; result = prime * result + (pdec ? 1231 : 1237); result = prime * result + reserved; result = prime * result + (int) (tubeID ^ (tubeID >>> 32)); return result; } /* (non-Javadoc) * @see java.lang.Object#equals(java.lang.Object) */ @Override public boolean equals(Object obj) { if (this == obj) return true; if (!super.equals(obj)) return false; if (!(obj instanceof SPUD)) return false; SPUD other = (SPUD) obj; if (adec != other.adec) return false; if (command != other.command) return false; if (pdec != other.pdec) return false; if (reserved != other.reserved) return false; if (tubeID != other.tubeID) return false; return true; } }