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