btf: Move the plugins to their own sub-directory
[deliverable/tracecompass.git] / org.eclipse.tracecompass.pcap.core / src / org / eclipse / tracecompass / internal / pcap / core / protocol / pcap / PcapPacket.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.pcap;
14
15 import java.nio.ByteBuffer;
16 import java.nio.ByteOrder;
17 import java.util.Map;
18
19 import org.eclipse.jdt.annotation.Nullable;
20 import org.eclipse.tracecompass.common.core.NonNullUtils;
21 import org.eclipse.tracecompass.internal.pcap.core.packet.BadPacketException;
22 import org.eclipse.tracecompass.internal.pcap.core.packet.Packet;
23 import org.eclipse.tracecompass.internal.pcap.core.protocol.PcapProtocol;
24 import org.eclipse.tracecompass.internal.pcap.core.protocol.ethernet2.EthernetIIPacket;
25 import org.eclipse.tracecompass.internal.pcap.core.protocol.unknown.UnknownPacket;
26 import org.eclipse.tracecompass.internal.pcap.core.trace.PcapFile;
27 import org.eclipse.tracecompass.internal.pcap.core.trace.PcapFileValues;
28 import org.eclipse.tracecompass.internal.pcap.core.util.ConversionHelper;
29 import org.eclipse.tracecompass.internal.pcap.core.util.LinkTypeHelper;
30 import org.eclipse.tracecompass.internal.pcap.core.util.PcapTimestampScale;
31
32 import 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 */
40 public 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
56 private @Nullable Map<String, String> fFields;
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 {
75 super(file, parent, PcapProtocol.PCAP);
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() {
239 @Nullable PcapEndpoint endpoint = fSourceEndpoint;
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() {
249 @Nullable
250 PcapEndpoint endpoint = fDestinationEndpoint;
251
252 if (endpoint == null) {
253 endpoint = new PcapEndpoint(this, false);
254 }
255 fDestinationEndpoint = endpoint;
256 return fDestinationEndpoint;
257 }
258
259 // TODO handle plural form correctly
260 // TODO microsec
261 @Override
262 public Map<String, String> getFields() {
263 Map<String, String> map = fFields;
264 if (map == null) {
265 ImmutableMap.Builder<String, String> builder = ImmutableMap.<String, String> builder();
266 builder.put("Frame", String.valueOf(fPacketIndex)); //$NON-NLS-1$
267 builder.put("Frame Length", String.valueOf(fOriginalLength) + " bytes"); //$NON-NLS-1$ //$NON-NLS-2$
268 builder.put("Capture Length", String.valueOf(fIncludedLength) + " bytes"); //$NON-NLS-1$ //$NON-NLS-2$
269 builder.put("Capture Time", ConversionHelper.toGMTTime(fTimestamp, getTimestampScale())); //$NON-NLS-1$
270
271 fFields = NonNullUtils.checkNotNull(builder.build());
272 return fFields;
273 }
274 return map;
275 }
276
277 @Override
278 public String getLocalSummaryString() {
279 return "Frame " + fPacketIndex + ": " + fOriginalLength + " bytes on wire, " + fIncludedLength + " bytes captured"; //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
280 }
281
282 @Override
283 protected String getSignificationString() {
284 return "New Frame: " + fOriginalLength + " bytes on wire"; //$NON-NLS-1$ //$NON-NLS-2$
285 }
286
287 @Override
288 public int hashCode() {
289 final int prime = 31;
290 int result = 1;
291
292 Packet child = fChildPacket;
293 if (child == null) {
294 result = prime * result;
295 } else {
296 result = prime * result + child.hashCode();
297 }
298
299 result = prime * result + (int) (fIncludedLength ^ (fIncludedLength >>> 32));
300 result = prime * result + (int) (fOriginalLength ^ (fOriginalLength >>> 32));
301 result = prime * result + (int) (fPacketIndex ^ (fPacketIndex >>> 32));
302
303 ByteBuffer payload = fPayload;
304 if (payload == null) {
305 result = prime * result;
306 } else {
307 result = prime * result + payload.hashCode();
308 }
309
310 result = prime * result + (int) (fTimestamp ^ (fTimestamp >>> 32));
311 return result;
312 }
313
314 @Override
315 public boolean equals(@Nullable Object obj) {
316 if (this == obj) {
317 return true;
318 }
319 if (obj == null) {
320 return false;
321 }
322 if (getClass() != obj.getClass()) {
323 return false;
324 }
325 PcapPacket other = (PcapPacket) obj;
326 if(!NonNullUtils.equalsNullable(fChildPacket, other.fChildPacket)){
327 return false;
328 }
329 if (fIncludedLength != other.fIncludedLength) {
330 return false;
331 }
332 if (fOriginalLength != other.fOriginalLength) {
333 return false;
334 }
335 if (fPacketIndex != other.fPacketIndex) {
336 return false;
337 }
338 if(!NonNullUtils.equalsNullable(fPayload, other.fPayload)) {
339 return false;
340 }
341 if (fTimestamp != other.fTimestamp) {
342 return false;
343 }
344 return true;
345 }
346
347 /**
348 * Getter method that returns the Timestamp precision of the packet.
349 *
350 * @return the Timestamp precision.
351 */
352 public PcapTimestampScale getTimestampScale() {
353 return getPcapFile().getTimestampPrecision();
354 }
355 }
This page took 0.039258 seconds and 5 git commands to generate.