Fix some null warnings
[deliverable/tracecompass.git] / pcap / org.eclipse.tracecompass.pcap.core / src / org / eclipse / tracecompass / internal / pcap / core / protocol / pcap / PcapPacket.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.pcap;
5255c030
VP
14
15import java.nio.ByteBuffer;
16import java.nio.ByteOrder;
17import java.util.Map;
18
5255c030 19import org.eclipse.jdt.annotation.Nullable;
5db5a3a4 20import org.eclipse.tracecompass.common.core.NonNullUtils;
71f2817f
AM
21import org.eclipse.tracecompass.internal.pcap.core.packet.BadPacketException;
22import org.eclipse.tracecompass.internal.pcap.core.packet.Packet;
23import org.eclipse.tracecompass.internal.pcap.core.protocol.PcapProtocol;
24import org.eclipse.tracecompass.internal.pcap.core.protocol.ethernet2.EthernetIIPacket;
25import org.eclipse.tracecompass.internal.pcap.core.protocol.unknown.UnknownPacket;
26import org.eclipse.tracecompass.internal.pcap.core.trace.PcapFile;
27import org.eclipse.tracecompass.internal.pcap.core.trace.PcapFileValues;
28import org.eclipse.tracecompass.internal.pcap.core.util.ConversionHelper;
29import org.eclipse.tracecompass.internal.pcap.core.util.LinkTypeHelper;
30import org.eclipse.tracecompass.internal.pcap.core.util.PcapTimestampScale;
5255c030
VP
31
32import com.google.common.collect.ImmutableMap;
33
34/**
35 * Class that represents a Pcap packet. This is the highest level of
36 * encapsulation.
37 *
38 * @author Vincent Perot
39 */
40public class PcapPacket extends Packet {
41
42 private static final int TIMESTAMP_MICROSECOND_MAX = 1000000;
43 private static final int TIMESTAMP_NANOSECOND_MAX = 1000000000;
44
45 private final @Nullable Packet fChildPacket;
46 private final @Nullable ByteBuffer fPayload;
47
48 private final long fTimestamp; // In microseconds
49 private final long fIncludedLength;
50 private final long fOriginalLength;
51 private final long fPacketIndex;
52
53 private @Nullable PcapEndpoint fSourceEndpoint;
54 private @Nullable PcapEndpoint fDestinationEndpoint;
55
5db5a3a4 56 private @Nullable Map<String, String> fFields;
5255c030
VP
57
58 /**
59 * Constructor of the Pcap Packet class.
60 *
61 * @param file
62 * The file that contains this packet.
63 * @param parent
64 * The parent packet of this packet (the encapsulating packet).
65 * @param header
66 * The header of the packet.
67 * @param payload
68 * The payload of this packet.
69 * @param index
70 * The index of the packet in the file.
71 * @throws BadPacketException
72 * Thrown when the Packet is erroneous.
73 */
74 public PcapPacket(PcapFile file, @Nullable Packet parent, ByteBuffer header, @Nullable ByteBuffer payload, long index) throws BadPacketException {
c88feda9 75 super(file, parent, PcapProtocol.PCAP);
5255c030
VP
76
77 if (header.array().length < PcapFileValues.PACKET_HEADER_SIZE) {
78 fChildPacket = null;
79 throw new BadPacketException("The Pcap packet header is too small."); //$NON-NLS-1$
80 }
81
82 // The endpoints are lazy loaded. They are defined in the get*Endpoint()
83 // methods.
84 fSourceEndpoint = null;
85 fDestinationEndpoint = null;
86
87 fFields = null;
88
89 fPacketIndex = index;
90
91 // PcapPacket header in File endian
92 header.order(getPcapFile().getByteOrder());
93 header.position(0);
94 long timestampMostSignificant = ConversionHelper.unsignedIntToLong(header.getInt());
95 long timestampLeastSignificant = ConversionHelper.unsignedIntToLong(header.getInt());
96
97 switch (getTimestampScale()) {
98 case MICROSECOND:
99 if (timestampLeastSignificant > TIMESTAMP_MICROSECOND_MAX) {
100 fChildPacket = null;
101 throw new BadPacketException("The timestamp is erroneous."); //$NON-NLS-1$
102 }
103 fTimestamp = TIMESTAMP_MICROSECOND_MAX * timestampMostSignificant + timestampLeastSignificant;
104 break;
105 case NANOSECOND:
106 if (timestampLeastSignificant > TIMESTAMP_NANOSECOND_MAX) {
107 fChildPacket = null;
108 throw new BadPacketException("The timestamp is erroneous."); //$NON-NLS-1$
109 }
110 fTimestamp = TIMESTAMP_NANOSECOND_MAX * timestampMostSignificant + timestampLeastSignificant;
111 break;
112 default:
113 throw new IllegalArgumentException("The timestamp precision is not valid!"); //$NON-NLS-1$
114 }
115
116 fIncludedLength = ConversionHelper.unsignedIntToLong(header.getInt());
117 fOriginalLength = ConversionHelper.unsignedIntToLong(header.getInt());
118
119 // Set up payload
120 final ByteBuffer pcapPacket = payload;
121 if (pcapPacket == null) {
122 fChildPacket = null;
123 fPayload = null;
124 return;
125 }
126
127 pcapPacket.order(ByteOrder.BIG_ENDIAN);
128 pcapPacket.position(0);
129 fPayload = pcapPacket;
130
131 // Find Child Packet
132 fChildPacket = findChildPacket();
133
134 }
135
136 @Override
137 public @Nullable Packet getChildPacket() {
138 return fChildPacket;
139 }
140
141 @Override
142 public @Nullable ByteBuffer getPayload() {
143 return fPayload;
144 }
145
146 /**
147 * Getter method that returns the timestamp of this packet, in microseconds/nanoseconds
148 * relative to epoch.
149 *
150 * @return The timestamp of the packet.
151 */
152 public long getTimestamp() {
153 return fTimestamp;
154 }
155
156 /**
157 * Getter method that returns the length in bytes of the packet that was
158 * included in the {@link PcapFile}.
159 *
160 * @return The included length of the packet.
161 */
162 public long getIncludedLength() {
163 return fIncludedLength;
164 }
165
166 /**
167 * Getter method that returns the original length in bytes of the packet.
168 *
169 * @return The included length of the packet.
170 */
171 public long getOriginalLength() {
172 return fOriginalLength;
173 }
174
175 /**
176 * Method that indicates if this packet was truncated at capture time.
177 *
178 * @return Whether the packet is truncated or not.
179 */
180 public boolean isTruncated() {
181 return fIncludedLength != fOriginalLength;
182 }
183
184 /**
185 * Getter method that returns the index of the packet.
186 *
187 * @return The index of the packet.
188 */
189 public long getIndex() {
190 return fPacketIndex;
191 }
192
193 @Override
194 public String toString() {
195 // TODO Decide if first capture is 0 or 1. Right now, it is 0.
196 String string = getProtocol().getName() + " " + fPacketIndex + //$NON-NLS-1$
197 ": " + fOriginalLength + " bytes on wire, " + //$NON-NLS-1$ //$NON-NLS-2$
198 fIncludedLength + " bytes captured.\nArrival time: " + //$NON-NLS-1$
199 ConversionHelper.toGMTTime(fTimestamp, getTimestampScale()) + "\n"; //$NON-NLS-1$
200
201 final Packet child = fChildPacket;
202 if (child != null) {
203 return string + child.toString();
204 }
205 return string;
206 }
207
208 /**
209 * {@inheritDoc}
210 *
211 * See http://www.tcpdump.org/linktypes.html
212 */
213 @Override
214 protected @Nullable Packet findChildPacket() throws BadPacketException {
215 @Nullable
216 ByteBuffer payload = fPayload;
217 if (payload == null) {
218 return null;
219 }
220
221 switch ((int) getPcapFile().getDataLinkType()) {
222 case LinkTypeHelper.LINKTYPE_ETHERNET:
223 return new EthernetIIPacket(getPcapFile(), this, payload);
224 default: // TODO add more protocols
225 return new UnknownPacket(getPcapFile(), this, payload);
226 }
227 }
228
229 @Override
230 public boolean validate() {
231 // Not yet implemented. ATM, we consider that all packets are valid.
232 // This is the case for all packets.
233 // TODO Implement it.
234 return true;
235 }
236
237 @Override
238 public PcapEndpoint getSourceEndpoint() {
df2597e0 239 PcapEndpoint endpoint = fSourceEndpoint;
5255c030
VP
240 if (endpoint == null) {
241 endpoint = new PcapEndpoint(this, true);
242 }
243 fSourceEndpoint = endpoint;
244 return fSourceEndpoint;
245 }
246
247 @Override
248 public PcapEndpoint getDestinationEndpoint() {
5255c030
VP
249 PcapEndpoint endpoint = fDestinationEndpoint;
250
251 if (endpoint == null) {
252 endpoint = new PcapEndpoint(this, false);
253 }
254 fDestinationEndpoint = endpoint;
255 return fDestinationEndpoint;
256 }
257
258 // TODO handle plural form correctly
259 // TODO microsec
260 @Override
261 public Map<String, String> getFields() {
5db5a3a4 262 Map<String, String> map = fFields;
5255c030 263 if (map == null) {
df2597e0 264 ImmutableMap.Builder<String, String> builder = ImmutableMap.builder();
5db5a3a4
AM
265 builder.put("Frame", String.valueOf(fPacketIndex)); //$NON-NLS-1$
266 builder.put("Frame Length", String.valueOf(fOriginalLength) + " bytes"); //$NON-NLS-1$ //$NON-NLS-2$
267 builder.put("Capture Length", String.valueOf(fIncludedLength) + " bytes"); //$NON-NLS-1$ //$NON-NLS-2$
268 builder.put("Capture Time", ConversionHelper.toGMTTime(fTimestamp, getTimestampScale())); //$NON-NLS-1$
269
270 fFields = NonNullUtils.checkNotNull(builder.build());
271 return fFields;
5255c030
VP
272 }
273 return map;
274 }
275
276 @Override
277 public String getLocalSummaryString() {
278 return "Frame " + fPacketIndex + ": " + fOriginalLength + " bytes on wire, " + fIncludedLength + " bytes captured"; //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
279 }
280
281 @Override
282 protected String getSignificationString() {
283 return "New Frame: " + fOriginalLength + " bytes on wire"; //$NON-NLS-1$ //$NON-NLS-2$
284 }
285
286 @Override
287 public int hashCode() {
288 final int prime = 31;
289 int result = 1;
290
291 Packet child = fChildPacket;
292 if (child == null) {
293 result = prime * result;
294 } else {
295 result = prime * result + child.hashCode();
296 }
297
298 result = prime * result + (int) (fIncludedLength ^ (fIncludedLength >>> 32));
299 result = prime * result + (int) (fOriginalLength ^ (fOriginalLength >>> 32));
300 result = prime * result + (int) (fPacketIndex ^ (fPacketIndex >>> 32));
301
302 ByteBuffer payload = fPayload;
303 if (payload == null) {
304 result = prime * result;
305 } else {
306 result = prime * result + payload.hashCode();
307 }
308
309 result = prime * result + (int) (fTimestamp ^ (fTimestamp >>> 32));
310 return result;
311 }
312
313 @Override
314 public boolean equals(@Nullable Object obj) {
315 if (this == obj) {
316 return true;
317 }
318 if (obj == null) {
319 return false;
320 }
321 if (getClass() != obj.getClass()) {
322 return false;
323 }
324 PcapPacket other = (PcapPacket) obj;
c10923a9
MK
325 if(!NonNullUtils.equalsNullable(fChildPacket, other.fChildPacket)){
326 return false;
5255c030 327 }
5255c030
VP
328 if (fIncludedLength != other.fIncludedLength) {
329 return false;
330 }
331 if (fOriginalLength != other.fOriginalLength) {
332 return false;
333 }
334 if (fPacketIndex != other.fPacketIndex) {
335 return false;
336 }
c10923a9
MK
337 if(!NonNullUtils.equalsNullable(fPayload, other.fPayload)) {
338 return false;
5255c030 339 }
5255c030
VP
340 if (fTimestamp != other.fTimestamp) {
341 return false;
342 }
343 return true;
344 }
345
346 /**
347 * Getter method that returns the Timestamp precision of the packet.
348 *
349 * @return the Timestamp precision.
350 */
351 public PcapTimestampScale getTimestampScale() {
352 return getPcapFile().getTimestampPrecision();
353 }
354}
This page took 0.059914 seconds and 5 git commands to generate.