diff --git a/build.xml b/build.xml index 6d67ce6ea241b1e5ed82231b239aa86a7e5585a4..a430867363dfacede2ee55be60f7af9389a72113 100644 --- a/build.xml +++ b/build.xml @@ -53,13 +53,14 @@ <patternset id="lib"> <include name="logback-classic-1.0.0.jar"/> <include name="logback-core-1.0.0.jar"/> - <include name="jackson-core-2.1.4.jar"/> - <include name="jackson-annotations-2.1.4.jar"/> - <include name="jackson-databind-2.1.4.jar"/> - <include name="jackson-dataformat-smile-2.1.4.jar"/> - <include name="jackson-dataformat-xml-2.1.4.jar"/> - <include name="jackson-dataformat-yaml-2.1.4.jar"/> - <include name="jackson-dataformat-csv-2.1.4.jar"/> + <include name="jackson-core-2.4.4.jar"/> + <include name="jackson-annotations-2.4.4.jar"/> + <include name="jackson-databind-2.4.4.jar"/> + <include name="jackson-dataformat-smile-2.4.4.jar"/> + <include name="jackson-dataformat-xml-2.4.4.jar"/> + <include name="jackson-dataformat-yaml-2.4.4.jar"/> + <include name="jackson-dataformat-csv-2.4.4.jar"/> + <include name="jackson-dataformat-cbor-2.4.4.jar"/> <include name="slf4j-api-1.6.4.jar"/> <include name="org.restlet.jar"/> <include name="org.restlet.ext.jackson.jar"/> diff --git a/lib/jackson-annotations-2.1.4.jar b/lib/jackson-annotations-2.1.4.jar deleted file mode 100644 index 143edf44b0daa4cef1a452ecccac21aee22a8d77..0000000000000000000000000000000000000000 Binary files a/lib/jackson-annotations-2.1.4.jar and /dev/null differ diff --git a/lib/jackson-annotations-2.4.4.jar b/lib/jackson-annotations-2.4.4.jar new file mode 100644 index 0000000000000000000000000000000000000000..4779188a9f0f306169d566bf7e73570e0bf3e45b Binary files /dev/null and b/lib/jackson-annotations-2.4.4.jar differ diff --git a/lib/jackson-core-2.1.4.jar b/lib/jackson-core-2.1.4.jar deleted file mode 100644 index 0f144685f7140d2694eeba5609322b4cd79f0bf8..0000000000000000000000000000000000000000 Binary files a/lib/jackson-core-2.1.4.jar and /dev/null differ diff --git a/lib/jackson-core-2.4.4.jar b/lib/jackson-core-2.4.4.jar new file mode 100644 index 0000000000000000000000000000000000000000..da2a877f186a999df8fbafaac5c59316d3fb70b4 Binary files /dev/null and b/lib/jackson-core-2.4.4.jar differ diff --git a/lib/jackson-databind-2.1.4.jar b/lib/jackson-databind-2.1.4.jar deleted file mode 100644 index ce125d1df292a1d8fa4b86cf39770d0d9c4636cc..0000000000000000000000000000000000000000 Binary files a/lib/jackson-databind-2.1.4.jar and /dev/null differ diff --git a/lib/jackson-databind-2.4.4.jar b/lib/jackson-databind-2.4.4.jar new file mode 100644 index 0000000000000000000000000000000000000000..e945e5e800666e0c5f99e9571185327f663d73ce Binary files /dev/null and b/lib/jackson-databind-2.4.4.jar differ diff --git a/lib/jackson-dataformat-cbor-2.4.4.jar b/lib/jackson-dataformat-cbor-2.4.4.jar new file mode 100644 index 0000000000000000000000000000000000000000..8a536d2b806a5a50473e602a932f1a2527b3a604 Binary files /dev/null and b/lib/jackson-dataformat-cbor-2.4.4.jar differ diff --git a/lib/jackson-dataformat-csv-2.1.4.jar b/lib/jackson-dataformat-csv-2.1.4.jar deleted file mode 100644 index e97503cb161c44ca54d096ec669b707e522f0004..0000000000000000000000000000000000000000 Binary files a/lib/jackson-dataformat-csv-2.1.4.jar and /dev/null differ diff --git a/lib/jackson-dataformat-csv-2.4.4.jar b/lib/jackson-dataformat-csv-2.4.4.jar new file mode 100644 index 0000000000000000000000000000000000000000..f561dc10ff44e60210f04315f508bf76d1843d1c Binary files /dev/null and b/lib/jackson-dataformat-csv-2.4.4.jar differ diff --git a/lib/jackson-dataformat-smile-2.1.4.jar b/lib/jackson-dataformat-smile-2.1.4.jar deleted file mode 100644 index e907c7726c5679a572e098293581bba28ac63fa1..0000000000000000000000000000000000000000 Binary files a/lib/jackson-dataformat-smile-2.1.4.jar and /dev/null differ diff --git a/lib/jackson-dataformat-smile-2.4.4.jar b/lib/jackson-dataformat-smile-2.4.4.jar new file mode 100644 index 0000000000000000000000000000000000000000..2a6b285190944cd6536619e0caca6aca4af18067 Binary files /dev/null and b/lib/jackson-dataformat-smile-2.4.4.jar differ diff --git a/lib/jackson-dataformat-xml-2.1.4.jar b/lib/jackson-dataformat-xml-2.1.4.jar deleted file mode 100644 index 15c82e69c86703363e16d47cb8cb3c3de1919c43..0000000000000000000000000000000000000000 Binary files a/lib/jackson-dataformat-xml-2.1.4.jar and /dev/null differ diff --git a/lib/jackson-dataformat-xml-2.4.4.jar b/lib/jackson-dataformat-xml-2.4.4.jar new file mode 100644 index 0000000000000000000000000000000000000000..8f0fa34d09634e02bda7dc0fe7938b8e58fdb1a2 Binary files /dev/null and b/lib/jackson-dataformat-xml-2.4.4.jar differ diff --git a/lib/jackson-dataformat-yaml-2.1.4.jar b/lib/jackson-dataformat-yaml-2.1.4.jar deleted file mode 100644 index 444ef88653e9574fb90246679835448e02170ee8..0000000000000000000000000000000000000000 Binary files a/lib/jackson-dataformat-yaml-2.1.4.jar and /dev/null differ diff --git a/lib/jackson-dataformat-yaml-2.4.4.jar b/lib/jackson-dataformat-yaml-2.4.4.jar new file mode 100644 index 0000000000000000000000000000000000000000..7770cb918467a8141c8d169f09042a5112e5f36d Binary files /dev/null and b/lib/jackson-dataformat-yaml-2.4.4.jar differ diff --git a/pom.xml b/pom.xml index a77870f01eaa2a1274109da175eb7d650df2e2ea..05c0b1784d45c95844c78a6f0f48256f030475db 100644 --- a/pom.xml +++ b/pom.xml @@ -219,9 +219,15 @@ <artifactId>netty</artifactId> <version>3.9.0.Final</version> </dependency> + <dependency> + <groupId>com.fasterxml.jackson.dataformat</groupId> + <artifactId>jackson-dataformat-cbor</artifactId> + <version>${lib-jackson-version}</version> + </dependency> </dependencies> <properties> <lib-restlet-version>2.3.2</lib-restlet-version> + <lib-jackson-version>2.4.4</lib-jackson-version> <lib-hamcrest-version>1.3</lib-hamcrest-version> </properties> </project> diff --git a/src/main/java/net/floodlightcontroller/packet/SPUD.java b/src/main/java/net/floodlightcontroller/packet/SPUD.java new file mode 100644 index 0000000000000000000000000000000000000000..d443d59dade46d471a5d75c7799c8e18cc719452 --- /dev/null +++ b/src/main/java/net/floodlightcontroller/packet/SPUD.java @@ -0,0 +1,153 @@ +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; + } +} diff --git a/src/main/java/net/floodlightcontroller/packet/UDP.java b/src/main/java/net/floodlightcontroller/packet/UDP.java index a5ee35f2c24971cca72c6d183bc2de2bea184f88..67302ae01aad3f2757a2ac9cade9856293c6e9cb 100644 --- a/src/main/java/net/floodlightcontroller/packet/UDP.java +++ b/src/main/java/net/floodlightcontroller/packet/UDP.java @@ -1,7 +1,7 @@ /** -* Copyright 2011, Big Switch Networks, Inc. +* Copyright 2011, Big Switch Networks, Inc. * Originally created by David Erickson, Stanford University -* +* * 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 @@ -18,6 +18,7 @@ package net.floodlightcontroller.packet; import java.nio.ByteBuffer; +import java.util.Arrays; import java.util.HashMap; import java.util.Map; @@ -39,7 +40,7 @@ public class UDP extends BasePacket { */ UDP.decodeMap.put(DHCP_CLIENT_PORT, DHCP.class); UDP.decodeMap.put(DHCP_SERVER_PORT, DHCP.class); - + } protected TransportPort sourcePort; @@ -61,7 +62,7 @@ public class UDP extends BasePacket { this.sourcePort = sourcePort; return this; } - + /** * @param sourcePort the sourcePort to set */ @@ -84,7 +85,7 @@ public class UDP extends BasePacket { this.destinationPort = destinationPort; return this; } - + /** * @param destinationPort the destinationPort to set */ @@ -227,6 +228,14 @@ public class UDP extends BasePacket { this.destinationPort = TransportPort.of((int) (bb.getShort() & 0xffff)); // convert range 0 to 65534, not -32768 to 32767 this.length = bb.getShort(); this.checksum = bb.getShort(); + // Grab a snapshot of the first four bytes of the UDP payload. + // We will use these to see if the payload is SPUD, without + // disturbing the existing byte buffer's offsets. + ByteBuffer bb_spud = bb.slice(); + byte[] maybe_spud_bytes = new byte[SPUD.MAGIC_CONSTANT.length]; + if (bb_spud.remaining() >= SPUD.MAGIC_CONSTANT.length) { + bb_spud.get(maybe_spud_bytes, 0, SPUD.MAGIC_CONSTANT.length); + } if (UDP.decodeMap.containsKey(this.destinationPort)) { try { @@ -240,6 +249,9 @@ public class UDP extends BasePacket { } catch (Exception e) { throw new RuntimeException("Failure instantiating class", e); } + } else if (Arrays.equals(maybe_spud_bytes, SPUD.MAGIC_CONSTANT) + && bb.remaining() >= SPUD.HEADER_LENGTH) { + this.payload = new SPUD(); } else { this.payload = new Data(); } diff --git a/src/test/java/net/floodlightcontroller/packet/SPUDTest.java b/src/test/java/net/floodlightcontroller/packet/SPUDTest.java new file mode 100644 index 0000000000000000000000000000000000000000..82cd29e2d6e30e8d632d97869de388882e403042 --- /dev/null +++ b/src/test/java/net/floodlightcontroller/packet/SPUDTest.java @@ -0,0 +1,114 @@ +package net.floodlightcontroller.packet; + +import static org.junit.Assert.assertTrue; +import java.util.Arrays; +import org.junit.Test; + +/** + * @author Jacob Chappell (jacob.chappell@uky.edu) + */ +public class SPUDTest { + @Test + public void testSerializeCommandOpen() { + byte[] expected = new byte[] { + (byte) 0xd8, 0x00, 0x00, (byte) 0xd8, + (byte) 0xb6, 0x40, 0x17, (byte) 0x88, + 0x0a, 0x51, 0x01, 0x07, 0x40 + }; + SPUD packet = (new SPUD()) + .setTubeID(0xb64017880a510107L) + .setCommand(SPUD.COMMAND_OPEN) + .setADEC(false) + .setPDEC(false) + .setReserved((byte) 0); + byte[] actual = packet.serialize(); + assertTrue(Arrays.equals(expected, actual)); + } + + @Test + public void testSerializeCommandDataEmpty() { + byte[] expected = new byte[] { + (byte) 0xd8, 0x00, 0x00, (byte) 0xd8, + (byte) 0xb6, 0x40, 0x17, (byte) 0x88, + 0x0a, 0x51, 0x01, 0x07, 0x00 + }; + SPUD packet = (new SPUD()) + .setTubeID(0xb64017880a510107L) + .setCommand(SPUD.COMMAND_DATA) + .setADEC(false) + .setPDEC(false) + .setReserved((byte) 0); + byte[] actual = packet.serialize(); + assertTrue(Arrays.equals(expected, actual)); + } + + @Test + public void testSerializeCommandDataEmptyWithADEC() { + byte[] expected = new byte[] { + (byte) 0xd8, 0x00, 0x00, (byte) 0xd8, + (byte) 0xb6, 0x40, 0x17, (byte) 0x88, + 0x0a, 0x51, 0x01, 0x07, 0x20 + }; + SPUD packet = (new SPUD()) + .setTubeID(0xb64017880a510107L) + .setCommand(SPUD.COMMAND_DATA) + .setADEC(true) + .setPDEC(false) + .setReserved((byte) 0); + byte[] actual = packet.serialize(); + assertTrue(Arrays.equals(expected, actual)); + } + + @Test + public void testSerializeCommandDataEmptyWithPDEC() { + byte[] expected = new byte[] { + (byte) 0xd8, 0x00, 0x00, (byte) 0xd8, + (byte) 0xb6, 0x40, 0x17, (byte) 0x88, + 0x0a, 0x51, 0x01, 0x07, 0x10 + }; + SPUD packet = (new SPUD()) + .setTubeID(0xb64017880a510107L) + .setCommand(SPUD.COMMAND_DATA) + .setADEC(false) + .setPDEC(true) + .setReserved((byte) 0); + byte[] actual = packet.serialize(); + assertTrue(Arrays.equals(expected, actual)); + } + + @Test + public void testSerializeCommandDataEmptyWithBoth() { + byte[] expected = new byte[] { + (byte) 0xd8, 0x00, 0x00, (byte) 0xd8, + (byte) 0xb6, 0x40, 0x17, (byte) 0x88, + 0x0a, 0x51, 0x01, 0x07, 0x30 + }; + SPUD packet = (new SPUD()) + .setTubeID(0xb64017880a510107L) + .setCommand(SPUD.COMMAND_DATA) + .setADEC(true) + .setPDEC(true) + .setReserved((byte) 0); + byte[] actual = packet.serialize(); + assertTrue(Arrays.equals(expected, actual)); + } + + @Test + public void testDeserialize() throws PacketParsingException { + byte[] spudPacket = { + (byte) 0xd8, 0x00, 0x00, (byte) 0xd8, (byte) 0xb6, + 0x40, 0x17, (byte) 0x88, 0x0a, 0x51, 0x01, 0x07, + 0x00, (byte) 0xa1, 0x00, (byte) 0xa2, 0x68, 0x75, + 0x73, 0x65, 0x72, 0x6e, 0x61, 0x6d, 0x65, 0x65, + 0x4a, 0x61, 0x63, 0x6f, 0x62, 0x67, 0x6d, 0x65, + 0x73, 0x73, 0x61, 0x67, 0x65, 0x73, 0x68, 0x61, + 0x73, 0x20, 0x6a, 0x6f, 0x69, 0x6e, 0x65, 0x64, + 0x20, 0x74, 0x68, 0x65, 0x20, 0x72, 0x6f, 0x6f, + 0x6d + }; + SPUD packet = new SPUD(); + packet.deserialize(spudPacket, 0, spudPacket.length); + byte[] packetSerialized = packet.serialize(); + assertTrue(Arrays.equals(spudPacket, packetSerialized)); + } +} diff --git a/src/test/java/net/floodlightcontroller/packet/UDPTest.java b/src/test/java/net/floodlightcontroller/packet/UDPTest.java index bed42a2e86dea1344e2963b2d56c1cf6585f63f1..3224c2747f0f33a13132d2cdd5b52c18f35eaa69 100644 --- a/src/test/java/net/floodlightcontroller/packet/UDPTest.java +++ b/src/test/java/net/floodlightcontroller/packet/UDPTest.java @@ -1,7 +1,7 @@ /** -* Copyright 2011, Big Switch Networks, Inc. +* Copyright 2011, Big Switch Networks, Inc. * Originally created by David Erickson, Stanford University -* +* * 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 @@ -16,10 +16,11 @@ **/ /** - * + * */ package net.floodlightcontroller.packet; +import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertTrue; import java.util.Arrays; @@ -52,4 +53,40 @@ public class UDPTest { byte[] actual = packet.serialize(); assertTrue(Arrays.equals(expected, actual)); } + + @Test + public void testDeserializeNotSPUD() throws PacketParsingException { + byte[] data = new byte[] { + 0x04, (byte) 0x89, 0x00, 0x35, 0x00, 0x2C, + (byte) 0xAB, (byte) 0xB4, 0x00, 0x01, 0x01, + 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x04, 0x70, 0x6F, 0x70, 0x64, + 0x02, 0x69, 0x78, 0x06, 0x6E, 0x65, 0x74, + 0x63, 0x6F, 0x6D, 0x03, 0x63, 0x6F, 0x6D, + 0x00, 0x00, 0x01, 0x00, 0x01 + }; + UDP packet = new UDP(); + packet.deserialize(data, 0, data.length); + IPacket thePayload = packet.getPayload(); + assertFalse(thePayload instanceof SPUD); + byte[] packetSerialized = packet.serialize(); + assertTrue(Arrays.equals(data, packetSerialized)); + } + + @Test + public void testDeserializeSPUD() throws PacketParsingException { + byte[] data = new byte[] { + (byte) 0xd5, (byte) 0xdf, (byte) 0x98, 0x27, + 0x00, 0x15, (byte) 0xfe, 0x28, (byte) 0xd8, + 0x00, 0x00, (byte) 0xd8, (byte) 0xc2, 0x6f, + 0x7a, 0x7d, 0x56, (byte) 0xa2, (byte) 0xe5, + (byte) 0xa8, 0x40 + }; + UDP packet = new UDP(); + packet.deserialize(data, 0, data.length); + IPacket thePayload = packet.getPayload(); + assertTrue(thePayload instanceof SPUD); + byte[] packetSerialized = packet.serialize(); + assertTrue(Arrays.equals(data, packetSerialized)); + } }