Remove unneeded checkNotNull() calls
[deliverable/tracecompass.git] / pcap / org.eclipse.tracecompass.pcap.core / src / org / eclipse / tracecompass / internal / pcap / core / protocol / tcp / TCPPacket.java
1 /*******************************************************************************
2 * Copyright (c) 2014 Ericsson
3 *
4 * All rights reserved. This program and the accompanying materials are
5 * made available under the terms of the Eclipse Public License v1.0 which
6 * accompanies this distribution, and is available at
7 * http://www.eclipse.org/legal/epl-v10.html
8 *
9 * Contributors:
10 * Vincent Perot - Initial API and implementation
11 *******************************************************************************/
12
13 package org.eclipse.tracecompass.internal.pcap.core.protocol.tcp;
14
15 import java.nio.ByteBuffer;
16 import java.nio.ByteOrder;
17 import java.util.Arrays;
18 import java.util.Map;
19
20 import org.eclipse.jdt.annotation.NonNull;
21 import org.eclipse.jdt.annotation.Nullable;
22 import org.eclipse.tracecompass.common.core.NonNullUtils;
23 import org.eclipse.tracecompass.internal.pcap.core.packet.BadPacketException;
24 import org.eclipse.tracecompass.internal.pcap.core.packet.Packet;
25 import org.eclipse.tracecompass.internal.pcap.core.protocol.PcapProtocol;
26 import org.eclipse.tracecompass.internal.pcap.core.protocol.unknown.UnknownPacket;
27 import org.eclipse.tracecompass.internal.pcap.core.trace.PcapFile;
28 import org.eclipse.tracecompass.internal.pcap.core.util.ConversionHelper;
29
30 import com.google.common.collect.ImmutableMap;
31 import com.google.common.collect.ImmutableMap.Builder;
32
33 /**
34 * Class that represents a TCP packet.
35 *
36 * @author Vincent Perot
37 */
38 public class TCPPacket extends Packet {
39
40 private final @Nullable Packet fChildPacket;
41 private final @Nullable ByteBuffer fPayload;
42
43 private final int fSourcePort;
44 private final int fDestinationPort;
45 private final long fSequenceNumber;
46 private final long fAcknowledgmentNumber;
47 private final int fDataOffset; // in 4 bytes block
48 private final byte fReservedField;
49 private final boolean fNSFlag;
50 private final boolean fCWRFlag;
51 private final boolean fECEFlag;
52 private final boolean fURGFlag;
53 private final boolean fACKFlag;
54 private final boolean fPSHFlag;
55 private final boolean fRSTFlag;
56 private final boolean fSYNFlag;
57 private final boolean fFINFlag;
58 private final int fWindowSize;
59 private final int fChecksum;
60 private final int fUrgentPointer;
61 private final byte @Nullable [] fOptions; // TODO Interpret options.
62
63 private @Nullable TCPEndpoint fSourceEndpoint;
64 private @Nullable TCPEndpoint fDestinationEndpoint;
65
66 private @Nullable Map<String, String> fFields;
67
68 /**
69 * Constructor of the TCP Packet class.
70 *
71 * @param file
72 * The file that contains this packet.
73 * @param parent
74 * The parent packet of this packet (the encapsulating packet).
75 * @param packet
76 * The entire packet (header and payload).
77 * @throws BadPacketException
78 * Thrown when the packet is erroneous.
79 */
80 public TCPPacket(PcapFile file, @Nullable Packet parent, ByteBuffer packet) throws BadPacketException {
81 super(file, parent, PcapProtocol.TCP);
82
83 // The endpoints are lazy loaded. They are defined in the get*Endpoint()
84 // methods.
85 fSourceEndpoint = null;
86 fDestinationEndpoint = null;
87
88 fFields = null;
89
90 packet.order(ByteOrder.BIG_ENDIAN);
91 packet.position(0);
92
93 fSourcePort = ConversionHelper.unsignedShortToInt(packet.getShort());
94 fDestinationPort = ConversionHelper.unsignedShortToInt(packet.getShort());
95 fSequenceNumber = ConversionHelper.unsignedIntToLong(packet.getInt());
96 fAcknowledgmentNumber = ConversionHelper.unsignedIntToLong(packet.getInt());
97
98 byte storage = packet.get();
99 fDataOffset = ((storage & 0b11110000) >>> 4) & 0x000000FF;
100 fReservedField = (byte) ((storage & 0b00001110) >>> 1);
101 fNSFlag = isBitSet(storage, 0);
102
103 storage = packet.get();
104 fCWRFlag = isBitSet(storage, 7);
105 fECEFlag = isBitSet(storage, 6);
106 fURGFlag = isBitSet(storage, 5);
107 fACKFlag = isBitSet(storage, 4);
108 fPSHFlag = isBitSet(storage, 3);
109 fRSTFlag = isBitSet(storage, 2);
110 fSYNFlag = isBitSet(storage, 1);
111 fFINFlag = isBitSet(storage, 0);
112
113 fWindowSize = ConversionHelper.unsignedShortToInt(packet.getShort());
114 fChecksum = ConversionHelper.unsignedShortToInt(packet.getShort());
115 fUrgentPointer = ConversionHelper.unsignedShortToInt(packet.getShort());
116
117 // Get options if any
118 if (fDataOffset > TCPValues.DEFAULT_HEADER_LENGTH) {
119 fOptions = new byte[(fDataOffset - TCPValues.DEFAULT_HEADER_LENGTH) * TCPValues.BLOCK_SIZE];
120 packet.get(fOptions);
121 } else {
122 fOptions = null;
123 }
124
125 // Get payload if any.
126 if (packet.array().length - packet.position() > 0) {
127 byte[] array = new byte[packet.array().length - packet.position()];
128 packet.get(array);
129 ByteBuffer payload = ByteBuffer.wrap(array);
130 payload.order(ByteOrder.BIG_ENDIAN);
131 payload.position(0);
132 fPayload = payload;
133 } else {
134 fPayload = null;
135 }
136
137 // find child packet
138 fChildPacket = findChildPacket();
139
140 }
141
142 @Override
143 public @Nullable Packet getChildPacket() {
144 return fChildPacket;
145 }
146
147 @Override
148 public @Nullable ByteBuffer getPayload() {
149 return fPayload;
150 }
151
152 /**
153 * {@inheritDoc}
154 *
155 * See http://www.iana.org/assignments/service-names-port-numbers/service-
156 * names-port-numbers.xhtml or
157 * http://en.wikipedia.org/wiki/List_of_TCP_and_UDP_port_numbers
158 */
159 @Override
160 protected @Nullable Packet findChildPacket() throws BadPacketException {
161 // TODO implement further protocols and update this
162 ByteBuffer payload = fPayload;
163 if (payload == null) {
164 return null;
165 }
166
167 return new UnknownPacket(getPcapFile(), this, payload);
168 }
169
170 @Override
171 public String toString() {
172 final ByteBuffer payload = fPayload;
173 int length = 0;
174 if (payload != null) {
175 length = payload.array().length;
176 }
177
178 String flagString = ""; // TODO Finish it. Im just too lazy. //$NON-NLS-1$
179 String string = getProtocol().getName() + ", Source Port: " + fSourcePort + ", Destination Port: " + fDestinationPort + //$NON-NLS-1$ //$NON-NLS-2$
180 "\nSequence Number: " + fSequenceNumber + ", Acknowledgment Number: " + fAcknowledgmentNumber + //$NON-NLS-1$ //$NON-NLS-2$
181 "\nHeader length: " + fDataOffset * TCPValues.BLOCK_SIZE + " bytes, Data length: " + length + //$NON-NLS-1$ //$NON-NLS-2$
182 "\n" + flagString + "Window size value: " + fWindowSize + ", Urgent Pointer: " + String.format("%s%04x", "0x", fUrgentPointer) + //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$ //$NON-NLS-5$
183 "\nChecksum: " + String.format("%s%04x", "0x", fChecksum) + "\n"; //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
184 final Packet child = fChildPacket;
185 if (child != null) {
186 return string + child.toString();
187 }
188 return string;
189 }
190
191 /**
192 * Getter method that returns the TCP Source Port.
193 *
194 * @return The source Port.
195 */
196 public int getSourcePort() {
197 return fSourcePort;
198 }
199
200 /**
201 * Getter method that returns the TCP Destination Port.
202 *
203 * @return The destination Port.
204 */
205 public int getDestinationPort() {
206 return fDestinationPort;
207 }
208
209 /**
210 * Getter method that returns the Sequence Number. The sequence number has a
211 * dual role:
212 * <ul>
213 * <li>If the SYN flag is set (1), then this is the initial sequence number.
214 * The sequence number of the actual first data byte and the acknowledged
215 * number in the corresponding ACK are then this sequence number plus 1.</li>
216 * <li>If the SYN flag is clear (0), then this is the accumulated sequence
217 * number of the first data byte of this segment for the current session.</li>
218 * </ul>
219 *
220 * Source: http://en.wikipedia.org/wiki/Transmission_Control_Protocol
221 *
222 * @return The Sequence Number.
223 */
224 public long getSequenceNumber() {
225 return fSequenceNumber;
226 }
227
228 /**
229 * Getter method that returns the Acknowledgment Number.
230 *
231 * If the ACK flag is set then the value of this field is the next sequence
232 * number that the receiver is expecting. This acknowledges receipt of all
233 * prior bytes (if any). The first ACK sent by each end acknowledges the
234 * other end's initial sequence number itself, but no data.
235 *
236 * Source: http://en.wikipedia.org/wiki/Transmission_Control_Protocol
237 *
238 * @return The Acknowledgment Number.
239 */
240 public long getAcknowledgmentNumber() {
241 return fAcknowledgmentNumber;
242 }
243
244 /**
245 * Getter method that returns the size of the TCP header in 4 bytes data
246 * block. The minimum size is 5 words and the maximum is 15 words.
247 *
248 * @return The Data Offset.
249 */
250 public int getDataOffset() {
251 return fDataOffset;
252 }
253
254 /**
255 * Getter method that returns the Reserved field. This field is for future
256 * use and should always be zero. In this library, it is used as a mean to
257 * verify the validity of a TCP packet.
258 *
259 * @return The Reserved Field.
260 */
261 public byte getReservedField() {
262 return fReservedField;
263 }
264
265 /**
266 * Getter method that returns the state of the NS flag.
267 *
268 * @return The state of the NS flag.
269 */
270 public boolean isNSFlagSet() {
271 return fNSFlag;
272 }
273
274 /**
275 * Getter method that returns the state of the CWR flag.
276 *
277 * @return The state of the CWR flag.
278 */
279 public boolean isCongestionWindowReducedFlagSet() {
280 return fCWRFlag;
281 }
282
283 /**
284 * Getter method that returns the state of the ECE flag.
285 *
286 * @return The state of the ECE flag.
287 */
288 public boolean isECNEchoFlagSet() {
289 return fECEFlag;
290 }
291
292 /**
293 * Getter method that returns the state of the URG flag.
294 *
295 * @return The state of the URG flag.
296 */
297 public boolean isUrgentFlagSet() {
298 return fURGFlag;
299 }
300
301 /**
302 * Getter method that returns the state of the ACK flag.
303 *
304 * @return The state of the ACK flag.
305 */
306 public boolean isAcknowledgeFlagSet() {
307 return fACKFlag;
308 }
309
310 /**
311 * Getter method that returns the state of the PSH flag.
312 *
313 * @return The state of the PSH flag.
314 */
315 public boolean isPushFlagSet() {
316 return fPSHFlag;
317 }
318
319 /**
320 * Getter method that returns the state of the RST flag.
321 *
322 * @return The state of the RST flag.
323 */
324 public boolean isResetFlagSet() {
325 return fRSTFlag;
326 }
327
328 /**
329 * Getter method that returns the state of the SYN flag.
330 *
331 * @return The state of the SYN flag.
332 */
333 public boolean isSynchronizationFlagSet() {
334 return fSYNFlag;
335 }
336
337 /**
338 * Getter method that returns the state of the FIN flag.
339 *
340 * @return The state of the FIN flag.
341 */
342 public boolean isFinalFlagSet() {
343 return fFINFlag;
344 }
345
346 /**
347 * Getter method that returns the size of the windows, in windows size unit
348 * (by default, bytes), that the sender of this packet is willing to
349 * receive.
350 *
351 * @return The Window Size.
352 */
353 public int getWindowSize() {
354 return fWindowSize;
355 }
356
357 /**
358 * Getter method that returns the checksum of this packet. This checksum may
359 * be wrong if the packet is erroneous.
360 *
361 * @return The data and header checksum.
362 */
363 public int getChecksum() {
364 return fChecksum;
365 }
366
367 /**
368 * Getter method that returns the Urgent Pointer. If the URG flag is set,
369 * this field is an offset from the sequence number indicating the last
370 * urgent data byte.
371 *
372 * @return The Urgent Pointer.
373 */
374 public int getUrgentPointer() {
375 return fUrgentPointer;
376 }
377
378 /**
379 * Getter method that returns the options. This method returns null if no
380 * options are present.
381 *
382 * @return The options of the packet.
383 */
384 public byte @Nullable [] getOptions() {
385 byte[] options = fOptions;
386 if (options == null) {
387 return null;
388 }
389 return Arrays.copyOf(options, options.length);
390 }
391
392 @Override
393 public boolean validate() {
394 // Not yet implemented. ATM, we consider that all packets are valid.
395 // This is the case for all packets.
396 // TODO Implement it.
397 return true;
398 }
399
400 @Override
401 public TCPEndpoint getSourceEndpoint() {
402 @Nullable
403 TCPEndpoint endpoint = fSourceEndpoint;
404 if (endpoint == null) {
405 endpoint = new TCPEndpoint(this, true);
406 }
407 fSourceEndpoint = endpoint;
408 return fSourceEndpoint;
409 }
410
411 @Override
412 public TCPEndpoint getDestinationEndpoint() {
413 @Nullable
414 TCPEndpoint endpoint = fDestinationEndpoint;
415
416 if (endpoint == null) {
417 endpoint = new TCPEndpoint(this, false);
418 }
419 fDestinationEndpoint = endpoint;
420 return fDestinationEndpoint;
421 }
422
423 @Override
424 public Map<String, String> getFields() {
425 Map<String, String> map = fFields;
426 if (map == null) {
427 Builder<String, String> builder = ImmutableMap.<@NonNull String, @NonNull String> builder()
428 .put("Source Port", String.valueOf(fSourcePort)) //$NON-NLS-1$
429 .put("Destination Port", String.valueOf(fDestinationPort)) //$NON-NLS-1$
430 .put("Sequence Number", String.valueOf(fSequenceNumber)) //$NON-NLS-1$
431 .put("Acknowledgement Number", String.valueOf(fAcknowledgmentNumber)) //$NON-NLS-1$
432 .put("Length", String.valueOf(fDataOffset * TCPValues.BLOCK_SIZE) + " bytes") //$NON-NLS-1$ //$NON-NLS-2$
433 .put("ECN-Nonce Flag", String.valueOf(fNSFlag)) //$NON-NLS-1$
434 .put("Congestion Window Reduced Flag", String.valueOf(fCWRFlag)) //$NON-NLS-1$
435 .put("ECN-Echo Flag", String.valueOf(fECEFlag)) //$NON-NLS-1$
436 .put("Urgent Flag", String.valueOf(fURGFlag)) //$NON-NLS-1$
437 .put("ACK Flag", String.valueOf(fACKFlag)) //$NON-NLS-1$
438 .put("PSH Flag", String.valueOf(fPSHFlag)) //$NON-NLS-1$
439 .put("RST Flag", String.valueOf(fRSTFlag)) //$NON-NLS-1$
440 .put("SYN Flag", String.valueOf(fSYNFlag)) //$NON-NLS-1$
441 .put("FIN Flag", String.valueOf(fFINFlag)) //$NON-NLS-1$
442 .put("Window Size Value", String.valueOf(fWindowSize)) //$NON-NLS-1$
443 .put("Checksum", String.format("%s%04x", "0x", fChecksum)) //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
444 .put("Urgent Pointer", String.format("%s%04x", "0x", fUrgentPointer)); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
445 byte[] options = fOptions;
446 if (options == null) {
447 builder.put("Options", EMPTY_STRING); //$NON-NLS-1$
448 } else {
449 builder.put("Options", ConversionHelper.bytesToHex(options, true)); //$NON-NLS-1$
450
451 }
452 fFields = builder.build();
453 return fFields;
454 }
455 return map;
456 }
457
458 @Override
459 public String getLocalSummaryString() {
460 return "Src Port: " + fSourcePort + ", Dst Port: " + fDestinationPort + //$NON-NLS-1$ //$NON-NLS-2$
461 ", Seq: " + fSequenceNumber + ", Ack: " + fAcknowledgmentNumber + //$NON-NLS-1$ //$NON-NLS-2$
462 ", Len: " + (fDataOffset * TCPValues.BLOCK_SIZE); //$NON-NLS-1$ }
463 }
464
465 @Override
466 protected String getSignificationString() {
467 StringBuilder sb = new StringBuilder();
468 sb.append(fSourcePort)
469 .append(" > ") //$NON-NLS-1$
470 .append(fDestinationPort);
471
472 if (!(generateFlagString().equals(EMPTY_STRING))) {
473 sb.append(' ')
474 .append('[')
475 .append(generateFlagString())
476 .append(']');
477 }
478 sb.append(" Seq=") //$NON-NLS-1$
479 .append(fSequenceNumber);
480
481 if (fACKFlag) {
482 sb.append(" Ack=") //$NON-NLS-1$
483 .append(fAcknowledgmentNumber);
484 }
485
486 sb.append(" Len=") //$NON-NLS-1$
487 .append((fDataOffset * TCPValues.BLOCK_SIZE));
488
489 return NonNullUtils.nullToEmptyString(sb); }
490
491 private String generateFlagString() {
492 StringBuilder sb = new StringBuilder();
493 boolean start = true;
494
495 if (fSYNFlag) {
496 if (!start) {
497 sb.append(", "); //$NON-NLS-1$
498 }
499 sb.append("SYN"); //$NON-NLS-1$
500 start = false;
501 }
502 if (fACKFlag) {
503 if (!start) {
504 sb.append(", "); //$NON-NLS-1$
505 }
506 sb.append("ACK"); //$NON-NLS-1$
507 start = false;
508 }
509 if (fFINFlag) {
510 if (!start) {
511 sb.append(", "); //$NON-NLS-1$
512 }
513 sb.append("FIN"); //$NON-NLS-1$
514 start = false;
515 }
516 if (fRSTFlag) {
517 if (!start) {
518 sb.append(", "); //$NON-NLS-1$
519 }
520 sb.append("RST"); //$NON-NLS-1$
521 start = false;
522 }
523 if (fPSHFlag) {
524 if (!start) {
525 sb.append(", "); //$NON-NLS-1$
526 }
527 sb.append("PSH"); //$NON-NLS-1$
528 start = false;
529 }
530 if (fURGFlag) {
531 if (!start) {
532 sb.append(", "); //$NON-NLS-1$
533 }
534 sb.append("URG"); //$NON-NLS-1$
535 start = false;
536 }
537 if (fNSFlag) {
538 if (!start) {
539 sb.append(", "); //$NON-NLS-1$
540 }
541 sb.append("NS"); //$NON-NLS-1$
542 start = false;
543 }
544 if (fCWRFlag) {
545 if (!start) {
546 sb.append(", "); //$NON-NLS-1$
547 }
548 sb.append("CWR"); //$NON-NLS-1$
549 start = false;
550 }
551 if (fECEFlag) {
552 if (!start) {
553 sb.append(", "); //$NON-NLS-1$
554 }
555 sb.append("ECE"); //$NON-NLS-1$
556 start = false;
557 }
558 return NonNullUtils.nullToEmptyString(sb);
559 }
560
561 @Override
562 public int hashCode() {
563 final int prime = 31;
564 int result = 1;
565 result = prime * result + (fACKFlag ? 1231 : 1237);
566 result = prime * result + (int) (fAcknowledgmentNumber ^ (fAcknowledgmentNumber >>> 32));
567 result = prime * result + (fCWRFlag ? 1231 : 1237);
568 result = prime * result + fChecksum;
569 final Packet child = fChildPacket;
570 if (child != null) {
571 result = prime * result + child.hashCode();
572 } else {
573 result = prime * result;
574 }
575 result = prime * result + fDataOffset;
576 result = prime * result + fDestinationPort;
577 result = prime * result + (fECEFlag ? 1231 : 1237);
578 result = prime * result + (fFINFlag ? 1231 : 1237);
579 result = prime * result + (fNSFlag ? 1231 : 1237);
580 result = prime * result + Arrays.hashCode(fOptions);
581 result = prime * result + (fPSHFlag ? 1231 : 1237);
582 final ByteBuffer payload = fPayload;
583 if (payload != null) {
584 result = prime * result + payload.hashCode();
585 } else {
586 result = prime * result;
587 }
588 result = prime * result + (fRSTFlag ? 1231 : 1237);
589 result = prime * result + fReservedField;
590 result = prime * result + (fSYNFlag ? 1231 : 1237);
591 result = prime * result + (int) (fSequenceNumber ^ (fSequenceNumber >>> 32));
592 result = prime * result + fSourcePort;
593 result = prime * result + (fURGFlag ? 1231 : 1237);
594 result = prime * result + fUrgentPointer;
595 result = prime * result + fWindowSize;
596 return result;
597 }
598
599 @Override
600 public boolean equals(@Nullable Object obj) {
601 if (this == obj) {
602 return true;
603 }
604 if (obj == null) {
605 return false;
606 }
607 if (getClass() != obj.getClass()) {
608 return false;
609 }
610 TCPPacket other = (TCPPacket) obj;
611 if (fACKFlag != other.fACKFlag) {
612 return false;
613 }
614 if (fAcknowledgmentNumber != other.fAcknowledgmentNumber) {
615 return false;
616 }
617 if (fCWRFlag != other.fCWRFlag) {
618 return false;
619 }
620 if (fChecksum != other.fChecksum) {
621 return false;
622 }
623 if(!NonNullUtils.equalsNullable(fChildPacket, other.fChildPacket)){
624 return false;
625 }
626 if (fDataOffset != other.fDataOffset) {
627 return false;
628 }
629 if (fDestinationPort != other.fDestinationPort) {
630 return false;
631 }
632 if (fECEFlag != other.fECEFlag) {
633 return false;
634 }
635 if (fFINFlag != other.fFINFlag) {
636 return false;
637 }
638 if (fNSFlag != other.fNSFlag) {
639 return false;
640 }
641 if (!Arrays.equals(fOptions, other.fOptions)) {
642 return false;
643 }
644 if (fPSHFlag != other.fPSHFlag) {
645 return false;
646 }
647 if(!NonNullUtils.equalsNullable(fPayload, other.fPayload)){
648 return false;
649 }
650 if (fRSTFlag != other.fRSTFlag) {
651 return false;
652 }
653 if (fReservedField != other.fReservedField) {
654 return false;
655 }
656 if (fSYNFlag != other.fSYNFlag) {
657 return false;
658 }
659 if (fSequenceNumber != other.fSequenceNumber) {
660 return false;
661 }
662 if (fSourcePort != other.fSourcePort) {
663 return false;
664 }
665 if (fURGFlag != other.fURGFlag) {
666 return false;
667 }
668 if (fUrgentPointer != other.fUrgentPointer) {
669 return false;
670 }
671 if (fWindowSize != other.fWindowSize) {
672 return false;
673 }
674 return true;
675 }
676
677 }
This page took 0.045665 seconds and 5 git commands to generate.