Skip to content

Commit b3a5ba1

Browse files
committed
improved NetPacketParsingTest#testParsingTCPFrameInsideNetworkFrame(), added extraction of Ethernet and IP headers
1 parent 768f8c7 commit b3a5ba1

File tree

1 file changed

+151
-74
lines changed

1 file changed

+151
-74
lines changed

src/test/java/com/igormaznitsa/jbbp/it/NetPacketParsingTest.java

Lines changed: 151 additions & 74 deletions
Original file line numberDiff line numberDiff line change
@@ -22,118 +22,195 @@
2222
import com.igormaznitsa.jbbp.mapper.BinType;
2323
import com.igormaznitsa.jbbp.model.*;
2424
import com.igormaznitsa.jbbp.utils.JBBPUtils;
25-
import java.io.InputStream;
2625
import static org.junit.Assert.*;
26+
import java.io.StringWriter;
2727
import org.junit.Test;
28+
import com.igormaznitsa.jbbp.io.JBBPBitInputStream;
29+
import com.igormaznitsa.jbbp.utils.JBBPTextWriter;
2830

2931
public class NetPacketParsingTest extends AbstractParserIntegrationTest {
3032

3133
@Test
3234
public void testParsingTCPFrameInsideNetworkFrame() throws Exception {
33-
final InputStream tcpFrameStream = getResourceAsInputStream("tcppacket.bin");
35+
final JBBPBitInputStream netPacketStream = new JBBPBitInputStream(getResourceAsInputStream("tcppacket.bin"));
3436
try {
3537

36-
final JBBPParser tcpParser = JBBPParser.prepare(
37-
"skip:34; // skip bytes till the frame\n"
38-
+ "ushort SourcePort;"
39-
+ "ushort DestinationPort;"
40-
+ "int SequenceNumber;"
41-
+ "int AcknowledgementNumber;"
42-
+ "bit:1 NONCE;"
43-
+ "bit:3 RESERVED;"
44-
+ "bit:4 HLEN;"
45-
+ "bit:1 FIN;"
46-
+ "bit:1 SYN;"
47-
+ "bit:1 RST;"
48-
+ "bit:1 PSH;"
49-
+ "bit:1 ACK;"
50-
+ "bit:1 URG;"
51-
+ "bit:1 ECNECHO;"
52-
+ "bit:1 CWR;"
53-
+ "ushort WindowSize;"
54-
+ "ushort TCPCheckSum;"
55-
+ "ushort UrgentPointer;"
56-
+ "byte [$$-34-HLEN*4] Option;"
57-
+ "byte [_] Data;"
38+
// Minimal ethernet header without 802.1Q tag
39+
final JBBPParser ethernetParserHeaderWithout802_1QTag = JBBPParser.prepare(
40+
"byte[6] MacDestination;"
41+
+"byte[6] MacSource;"
42+
+"ushort EthertypeOrLength;"
43+
);
44+
45+
// Minimal IP header without options
46+
final JBBPParser ipParserHeaderWithoutOptions = JBBPParser.prepare(
47+
"bit:4 InternetHeaderLength;"
48+
+"bit:4 Version;"
49+
+"bit:2 ECN;"
50+
+"bit:6 DSCP;"
51+
+"ushort TotalPacketLength;"
52+
+"ushort Identification;"
53+
+"ushort IPFlagsAndFragmentOffset;"
54+
+"ubyte TTL;"
55+
+"ubyte Protocol;"
56+
+"ushort HeaderChecksum;"
57+
+"int SourceAddress;"
58+
+"int DestinationAddress;"
5859
);
5960

60-
final JBBPFieldStruct result = tcpParser.parse(tcpFrameStream);
61-
62-
assertEquals(40018, result.findFieldForNameAndType("SourcePort", JBBPFieldUShort.class).getAsInt());
63-
assertEquals(56344, result.findFieldForNameAndType("DestinationPort", JBBPFieldUShort.class).getAsInt());
64-
assertEquals(0xE0084171, result.findFieldForNameAndType("SequenceNumber", JBBPFieldInt.class).getAsInt());
65-
assertEquals(0xAB616F71, result.findFieldForNameAndType("AcknowledgementNumber", JBBPFieldInt.class).getAsInt());
66-
67-
assertFalse(result.findFieldForNameAndType("FIN", JBBPFieldBit.class).getAsBool());
68-
assertFalse(result.findFieldForNameAndType("SYN", JBBPFieldBit.class).getAsBool());
69-
assertFalse(result.findFieldForNameAndType("RST", JBBPFieldBit.class).getAsBool());
70-
assertTrue(result.findFieldForNameAndType("PSH", JBBPFieldBit.class).getAsBool());
71-
assertTrue(result.findFieldForNameAndType("ACK", JBBPFieldBit.class).getAsBool());
72-
assertFalse(result.findFieldForNameAndType("URG", JBBPFieldBit.class).getAsBool());
73-
assertFalse(result.findFieldForNameAndType("ECNECHO", JBBPFieldBit.class).getAsBool());
74-
assertFalse(result.findFieldForNameAndType("CWR", JBBPFieldBit.class).getAsBool());
75-
assertFalse(result.findFieldForNameAndType("NONCE", JBBPFieldBit.class).getAsBool());
76-
assertFalse(result.findFieldForNameAndType("RESERVED", JBBPFieldBit.class).getAsBool());
77-
78-
assertEquals(5, result.findFieldForNameAndType("HLEN", JBBPFieldBit.class).getAsInt());
79-
80-
assertEquals(40880, result.findFieldForNameAndType("WindowSize", JBBPFieldUShort.class).getAsInt());
81-
assertEquals(0x8BB6, result.findFieldForNameAndType("TCPCheckSum", JBBPFieldUShort.class).getAsInt());
82-
assertEquals(0, result.findFieldForNameAndType("UrgentPointer", JBBPFieldUShort.class).getAsInt());
83-
84-
assertEquals(0, result.findFieldForNameAndType("Option", JBBPFieldArrayByte.class).size());
85-
assertEquals(119, result.findFieldForNameAndType("Data", JBBPFieldArrayByte.class).size());
61+
final JBBPParser tcpHeader = JBBPParser.prepare(
62+
"ushort SourcePort;"
63+
+ "ushort DestinationPort;"
64+
+ "int SequenceNumber;"
65+
+ "int AcknowledgementNumber;"
66+
+ "bit:1 NONCE;"
67+
+ "bit:3 RESERVED;"
68+
+ "bit:4 HLEN;"
69+
+ "bit:1 FIN;"
70+
+ "bit:1 SYN;"
71+
+ "bit:1 RST;"
72+
+ "bit:1 PSH;"
73+
+ "bit:1 ACK;"
74+
+ "bit:1 URG;"
75+
+ "bit:1 ECNECHO;"
76+
+ "bit:1 CWR;"
77+
+ "ushort WindowSize;"
78+
+ "ushort TCPCheckSum;"
79+
+ "ushort UrgentPointer;"
80+
+ "byte [$$-HLEN*4] Option;"
81+
);
8682

87-
}
88-
finally {
89-
JBBPUtils.closeQuietly(tcpFrameStream);
83+
84+
// Check Ethernet header
85+
final JBBPFieldStruct parsedEthernetHeader = ethernetParserHeaderWithout802_1QTag.parse(netPacketStream);
86+
assertArrayEquals(new byte[]{(byte)0x60, (byte)0x67, (byte)0x20, (byte)0xE1, (byte)0xF9, (byte)0xF8},parsedEthernetHeader.findFieldForNameAndType("MacDestination", JBBPFieldArrayByte.class).getArray());
87+
assertArrayEquals(new byte[]{(byte)0x00, (byte)0x26, (byte)0x44, (byte)0x74, (byte)0xFE, (byte)0x66},parsedEthernetHeader.findFieldForNameAndType("MacSource", JBBPFieldArrayByte.class).getArray());
88+
assertEquals(0x800, parsedEthernetHeader.findFieldForNameAndType("EthertypeOrLength", JBBPFieldUShort.class).getAsInt());
89+
90+
// Check IP header
91+
netPacketStream.resetCounter();
92+
final JBBPFieldStruct parsedIPHeader = ipParserHeaderWithoutOptions.parse(netPacketStream);
93+
94+
assertEquals(4, parsedIPHeader.findFieldForNameAndType("Version",JBBPFieldBit.class).getAsInt());
95+
assertEquals(5, parsedIPHeader.findFieldForNameAndType("InternetHeaderLength",JBBPFieldBit.class).getAsInt());
96+
assertEquals(0, parsedIPHeader.findFieldForNameAndType("DSCP",JBBPFieldBit.class).getAsInt());
97+
assertEquals(0, parsedIPHeader.findFieldForNameAndType("ECN",JBBPFieldBit.class).getAsInt());
98+
99+
final int ipTotalPacketLength = parsedIPHeader.findFieldForNameAndType("TotalPacketLength", JBBPFieldUShort.class).getAsInt();
100+
101+
assertEquals(159, ipTotalPacketLength);
102+
assertEquals(30810, parsedIPHeader.findFieldForNameAndType("Identification",JBBPFieldUShort.class).getAsInt());
103+
104+
final int ipFlagsAndFragmentOffset = parsedIPHeader.findFieldForNameAndType("IPFlagsAndFragmentOffset", JBBPFieldUShort.class).getAsInt();
105+
106+
assertEquals("Extracted IP flags", 0x2, ipFlagsAndFragmentOffset>>>13);
107+
assertEquals("Extracted Fragment offset", 0x00, ipFlagsAndFragmentOffset & 0x1FFF);
108+
109+
assertEquals(0x39, parsedIPHeader.findFieldForNameAndType("TTL",JBBPFieldUByte.class).getAsInt());
110+
assertEquals(0x06, parsedIPHeader.findFieldForNameAndType("Protocol",JBBPFieldUByte.class).getAsInt());
111+
assertEquals(0x7DB6, parsedIPHeader.findFieldForNameAndType("HeaderChecksum",JBBPFieldUShort.class).getAsInt());
112+
assertEquals(0xD5C7B393, parsedIPHeader.findFieldForNameAndType("SourceAddress",JBBPFieldInt.class).getAsInt());
113+
assertEquals(0xC0A80145, parsedIPHeader.findFieldForNameAndType("DestinationAddress",JBBPFieldInt.class).getAsInt());
114+
115+
// Check TCP header
116+
netPacketStream.resetCounter();
117+
final JBBPFieldStruct parsedTcpHeader = tcpHeader.parse(netPacketStream);
118+
119+
assertEquals(40018, parsedTcpHeader.findFieldForNameAndType("SourcePort", JBBPFieldUShort.class).getAsInt());
120+
assertEquals(56344, parsedTcpHeader.findFieldForNameAndType("DestinationPort", JBBPFieldUShort.class).getAsInt());
121+
assertEquals(0xE0084171, parsedTcpHeader.findFieldForNameAndType("SequenceNumber", JBBPFieldInt.class).getAsInt());
122+
assertEquals(0xAB616F71, parsedTcpHeader.findFieldForNameAndType("AcknowledgementNumber", JBBPFieldInt.class).getAsInt());
123+
124+
assertFalse(parsedTcpHeader.findFieldForNameAndType("FIN", JBBPFieldBit.class).getAsBool());
125+
assertFalse(parsedTcpHeader.findFieldForNameAndType("SYN", JBBPFieldBit.class).getAsBool());
126+
assertFalse(parsedTcpHeader.findFieldForNameAndType("RST", JBBPFieldBit.class).getAsBool());
127+
assertTrue(parsedTcpHeader.findFieldForNameAndType("PSH", JBBPFieldBit.class).getAsBool());
128+
assertTrue(parsedTcpHeader.findFieldForNameAndType("ACK", JBBPFieldBit.class).getAsBool());
129+
assertFalse(parsedTcpHeader.findFieldForNameAndType("URG", JBBPFieldBit.class).getAsBool());
130+
assertFalse(parsedTcpHeader.findFieldForNameAndType("ECNECHO", JBBPFieldBit.class).getAsBool());
131+
assertFalse(parsedTcpHeader.findFieldForNameAndType("CWR", JBBPFieldBit.class).getAsBool());
132+
assertFalse(parsedTcpHeader.findFieldForNameAndType("NONCE", JBBPFieldBit.class).getAsBool());
133+
assertFalse(parsedTcpHeader.findFieldForNameAndType("RESERVED", JBBPFieldBit.class).getAsBool());
134+
135+
assertEquals(5, parsedTcpHeader.findFieldForNameAndType("HLEN", JBBPFieldBit.class).getAsInt());
136+
137+
assertEquals(40880, parsedTcpHeader.findFieldForNameAndType("WindowSize", JBBPFieldUShort.class).getAsInt());
138+
assertEquals(0x8BB6, parsedTcpHeader.findFieldForNameAndType("TCPCheckSum", JBBPFieldUShort.class).getAsInt());
139+
assertEquals(0, parsedTcpHeader.findFieldForNameAndType("UrgentPointer", JBBPFieldUShort.class).getAsInt());
140+
141+
assertEquals(0, parsedTcpHeader.findFieldForNameAndType("Option", JBBPFieldArrayByte.class).size());
142+
143+
// extract data
144+
final int payloadDataLength = ipTotalPacketLength - 20 - (int)netPacketStream.getCounter();
145+
final byte [] data = netPacketStream.readByteArray(payloadDataLength);
146+
assertEquals(119, data.length);
147+
148+
System.out.println(new JBBPTextWriter(new StringWriter()).Comment("Payload data of the Net packet").Byte(data).BR().toString());
149+
150+
final byte [] rest = netPacketStream.readByteArray(-1);
151+
assertEquals(0,rest.length);
152+
153+
} finally {
154+
JBBPUtils.closeQuietly(netPacketStream);
90155
}
91156
}
92157

93158
@Test
94159
public void testParseSomePacketGettedOverTCP_ExampleFromStackOverflow() throws Exception {
95160
final class Parsed {
96-
@Bin(outOrder = 1) byte begin;
97-
@Bin(outOrder = 2, type = BinType.BIT, outBitNumber = JBBPBitNumber.BITS_4) int version;
98-
@Bin(outOrder = 3, type = BinType.BIT, outBitNumber = JBBPBitNumber.BITS_4) int returnType;
99-
@Bin(outOrder = 4) byte[] productCode;
100-
@Bin(outOrder = 5, type = BinType.USHORT) int dataLength;
161+
162+
@Bin(outOrder = 1)
163+
byte begin;
164+
@Bin(outOrder = 2, type = BinType.BIT, outBitNumber = JBBPBitNumber.BITS_4)
165+
int version;
166+
@Bin(outOrder = 3, type = BinType.BIT, outBitNumber = JBBPBitNumber.BITS_4)
167+
int returnType;
168+
@Bin(outOrder = 4)
169+
byte[] productCode;
170+
@Bin(outOrder = 5, type = BinType.USHORT)
171+
int dataLength;
101172
}
102-
103-
final byte [] testArray = new byte[]{0x23, 0x21, (byte) 0x90, 0x23, 0x21, 0x22, 0x12, 0x00, (byte) 0xAA};
104-
173+
174+
final byte[] testArray = new byte[]{0x23, 0x21, (byte) 0x90, 0x23, 0x21, 0x22, 0x12, 0x00, (byte) 0xAA};
175+
105176
final Parsed parsed = JBBPParser.prepare("byte begin; bit:4 version; bit:4 returnType; byte [5] productCode; ushort dataLength;")
106-
.parse(testArray)
107-
.mapTo(Parsed.class);
177+
.parse(testArray)
178+
.mapTo(Parsed.class);
108179

109180
assertEquals(0x23, parsed.begin);
110181
assertEquals(0x01, parsed.version);
111182
assertEquals(0x02, parsed.returnType);
112183
assertArrayEquals(new byte[]{(byte) 0x90, 0x23, 0x21, 0x22, 0x12}, parsed.productCode);
113184
assertEquals(0x00AA, parsed.dataLength);
114-
185+
115186
assertArrayEquals(testArray, JBBPOut.BeginBin().Bin(parsed).End().toByteArray());
116187
}
117188

118189
@Test
119190
public void testParseUDP() throws Exception {
120191
final class Parsed {
121-
@Bin(outOrder = 1) char source;
122-
@Bin(outOrder = 2) char destination;
123-
@Bin(outOrder = 3) char length;
124-
@Bin(outOrder = 4) char checksum;
125-
@Bin(outOrder = 5) byte[] data;
192+
193+
@Bin(outOrder = 1)
194+
char source;
195+
@Bin(outOrder = 2)
196+
char destination;
197+
@Bin(outOrder = 3)
198+
char length;
199+
@Bin(outOrder = 4)
200+
char checksum;
201+
@Bin(outOrder = 5)
202+
byte[] data;
126203
}
127204

128-
final byte [] testArray = 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};
129-
205+
final byte[] testArray = 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};
206+
130207
final Parsed parsed = JBBPParser.prepare("ushort source; ushort destination; ushort length; ushort checksum; byte [length-8] data;").parse(testArray).mapTo(Parsed.class);
131-
208+
132209
assertEquals(0x0489, parsed.source);
133210
assertEquals(0x0035, parsed.destination);
134211
assertEquals(0xABB4, parsed.checksum);
135-
assertEquals(0x002C-8, parsed.data.length);
136-
212+
assertEquals(0x002C - 8, parsed.data.length);
213+
137214
assertArrayEquals(testArray, JBBPOut.BeginBin().Bin(parsed).End().toByteArray());
138215
}
139216

0 commit comments

Comments
 (0)