1 /*******************************************************************************
2 * Copyright (c) 2014 Ericsson
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
10 * Vincent Perot - Initial API and implementation
11 *******************************************************************************/
13 package org
.eclipse
.linuxtools
.pcap
.core
.protocol
.pcap
;
15 import java
.nio
.ByteBuffer
;
16 import java
.nio
.ByteOrder
;
19 import org
.eclipse
.jdt
.annotation
.NonNull
;
20 import org
.eclipse
.jdt
.annotation
.Nullable
;
21 import org
.eclipse
.linuxtools
.pcap
.core
.packet
.BadPacketException
;
22 import org
.eclipse
.linuxtools
.pcap
.core
.packet
.Packet
;
23 import org
.eclipse
.linuxtools
.pcap
.core
.protocol
.Protocol
;
24 import org
.eclipse
.linuxtools
.pcap
.core
.protocol
.ethernet2
.EthernetIIPacket
;
25 import org
.eclipse
.linuxtools
.pcap
.core
.protocol
.unknown
.UnknownPacket
;
26 import org
.eclipse
.linuxtools
.pcap
.core
.trace
.PcapFile
;
27 import org
.eclipse
.linuxtools
.pcap
.core
.trace
.PcapFileValues
;
28 import org
.eclipse
.linuxtools
.pcap
.core
.util
.ConversionHelper
;
29 import org
.eclipse
.linuxtools
.pcap
.core
.util
.LinkTypeHelper
;
30 import org
.eclipse
.linuxtools
.pcap
.core
.util
.PcapTimestampScale
;
32 import com
.google
.common
.collect
.ImmutableMap
;
35 * Class that represents a Pcap packet. This is the highest level of
38 * @author Vincent Perot
40 public class PcapPacket
extends Packet
{
42 private static final int TIMESTAMP_MICROSECOND_MAX
= 1000000;
43 private static final int TIMESTAMP_NANOSECOND_MAX
= 1000000000;
45 private final @Nullable Packet fChildPacket
;
46 private final @Nullable ByteBuffer fPayload
;
48 private final long fTimestamp
; // In microseconds
49 private final long fIncludedLength
;
50 private final long fOriginalLength
;
51 private final long fPacketIndex
;
53 private @Nullable PcapEndpoint fSourceEndpoint
;
54 private @Nullable PcapEndpoint fDestinationEndpoint
;
56 private @Nullable ImmutableMap
<String
, String
> fFields
;
59 * Constructor of the Pcap Packet class.
62 * The file that contains this packet.
64 * The parent packet of this packet (the encapsulating packet).
66 * The header of the packet.
68 * The payload of this packet.
70 * The index of the packet in the file.
71 * @throws BadPacketException
72 * Thrown when the Packet is erroneous.
74 public PcapPacket(PcapFile file
, @Nullable Packet parent
, ByteBuffer header
, @Nullable ByteBuffer payload
, long index
) throws BadPacketException
{
75 super(file
, parent
, Protocol
.PCAP
);
77 if (header
.array().length
< PcapFileValues
.PACKET_HEADER_SIZE
) {
79 throw new BadPacketException("The Pcap packet header is too small."); //$NON-NLS-1$
82 // The endpoints are lazy loaded. They are defined in the get*Endpoint()
84 fSourceEndpoint
= null;
85 fDestinationEndpoint
= null;
91 // PcapPacket header in File endian
92 header
.order(getPcapFile().getByteOrder());
94 long timestampMostSignificant
= ConversionHelper
.unsignedIntToLong(header
.getInt());
95 long timestampLeastSignificant
= ConversionHelper
.unsignedIntToLong(header
.getInt());
97 switch (getTimestampScale()) {
99 if (timestampLeastSignificant
> TIMESTAMP_MICROSECOND_MAX
) {
101 throw new BadPacketException("The timestamp is erroneous."); //$NON-NLS-1$
103 fTimestamp
= TIMESTAMP_MICROSECOND_MAX
* timestampMostSignificant
+ timestampLeastSignificant
;
106 if (timestampLeastSignificant
> TIMESTAMP_NANOSECOND_MAX
) {
108 throw new BadPacketException("The timestamp is erroneous."); //$NON-NLS-1$
110 fTimestamp
= TIMESTAMP_NANOSECOND_MAX
* timestampMostSignificant
+ timestampLeastSignificant
;
113 throw new IllegalArgumentException("The timestamp precision is not valid!"); //$NON-NLS-1$
116 fIncludedLength
= ConversionHelper
.unsignedIntToLong(header
.getInt());
117 fOriginalLength
= ConversionHelper
.unsignedIntToLong(header
.getInt());
120 final ByteBuffer pcapPacket
= payload
;
121 if (pcapPacket
== null) {
127 pcapPacket
.order(ByteOrder
.BIG_ENDIAN
);
128 pcapPacket
.position(0);
129 fPayload
= pcapPacket
;
132 fChildPacket
= findChildPacket();
137 public @Nullable Packet
getChildPacket() {
142 public @Nullable ByteBuffer
getPayload() {
147 * Getter method that returns the timestamp of this packet, in microseconds/nanoseconds
150 * @return The timestamp of the packet.
152 public long getTimestamp() {
157 * Getter method that returns the length in bytes of the packet that was
158 * included in the {@link PcapFile}.
160 * @return The included length of the packet.
162 public long getIncludedLength() {
163 return fIncludedLength
;
167 * Getter method that returns the original length in bytes of the packet.
169 * @return The included length of the packet.
171 public long getOriginalLength() {
172 return fOriginalLength
;
176 * Method that indicates if this packet was truncated at capture time.
178 * @return Whether the packet is truncated or not.
180 public boolean isTruncated() {
181 return fIncludedLength
!= fOriginalLength
;
185 * Getter method that returns the index of the packet.
187 * @return The index of the packet.
189 public long getIndex() {
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$
201 final Packet child
= fChildPacket
;
203 return string
+ child
.toString();
211 * See http://www.tcpdump.org/linktypes.html
214 protected @Nullable Packet
findChildPacket() throws BadPacketException
{
216 ByteBuffer payload
= fPayload
;
217 if (payload
== null) {
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
);
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.
238 public PcapEndpoint
getSourceEndpoint() {
239 @Nullable PcapEndpoint endpoint
= fSourceEndpoint
;
240 if (endpoint
== null) {
241 endpoint
= new PcapEndpoint(this, true);
243 fSourceEndpoint
= endpoint
;
244 return fSourceEndpoint
;
248 public PcapEndpoint
getDestinationEndpoint() {
250 PcapEndpoint endpoint
= fDestinationEndpoint
;
252 if (endpoint
== null) {
253 endpoint
= new PcapEndpoint(this, false);
255 fDestinationEndpoint
= endpoint
;
256 return fDestinationEndpoint
;
259 // TODO handle plural form correctly
262 public Map
<String
, String
> getFields() {
263 ImmutableMap
<String
, String
> map
= fFields
;
265 @SuppressWarnings("null")
266 @NonNull ImmutableMap
<String
, String
> newMap
= ImmutableMap
.<String
, String
> builder()
267 .put("Frame", String
.valueOf(fPacketIndex
)) //$NON-NLS-1$
268 .put("Frame Length", String
.valueOf(fOriginalLength
) + " bytes") //$NON-NLS-1$ //$NON-NLS-2$
269 .put("Capture Length", String
.valueOf(fIncludedLength
) + " bytes") //$NON-NLS-1$ //$NON-NLS-2$
270 .put("Capture Time", ConversionHelper
.toGMTTime(fTimestamp
, getTimestampScale())) //$NON-NLS-1$
279 public String
getLocalSummaryString() {
280 return "Frame " + fPacketIndex
+ ": " + fOriginalLength
+ " bytes on wire, " + fIncludedLength
+ " bytes captured"; //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
284 protected String
getSignificationString() {
285 return "New Frame: " + fOriginalLength
+ " bytes on wire"; //$NON-NLS-1$ //$NON-NLS-2$
289 public int hashCode() {
290 final int prime
= 31;
293 Packet child
= fChildPacket
;
295 result
= prime
* result
;
297 result
= prime
* result
+ child
.hashCode();
300 result
= prime
* result
+ (int) (fIncludedLength ^
(fIncludedLength
>>> 32));
301 result
= prime
* result
+ (int) (fOriginalLength ^
(fOriginalLength
>>> 32));
302 result
= prime
* result
+ (int) (fPacketIndex ^
(fPacketIndex
>>> 32));
304 ByteBuffer payload
= fPayload
;
305 if (payload
== null) {
306 result
= prime
* result
;
308 result
= prime
* result
+ payload
.hashCode();
311 result
= prime
* result
+ (int) (fTimestamp ^
(fTimestamp
>>> 32));
316 public boolean equals(@Nullable Object obj
) {
323 if (getClass() != obj
.getClass()) {
326 PcapPacket other
= (PcapPacket
) obj
;
327 final Packet child
= fChildPacket
;
329 if (!child
.equals(other
.fChildPacket
)) {
333 if (other
.fChildPacket
!= null) {
338 if (fIncludedLength
!= other
.fIncludedLength
) {
341 if (fOriginalLength
!= other
.fOriginalLength
) {
344 if (fPacketIndex
!= other
.fPacketIndex
) {
347 final ByteBuffer payload
= fPayload
;
348 if (payload
!= null) {
349 if (!payload
.equals(other
.fPayload
)) {
353 if (other
.fPayload
!= null) {
358 if (fTimestamp
!= other
.fTimestamp
) {
365 * Getter method that returns the Timestamp precision of the packet.
367 * @return the Timestamp precision.
369 public PcapTimestampScale
getTimestampScale() {
370 return getPcapFile().getTimestampPrecision();