1 /*******************************************************************************
2 * Copyright (c) 2014, 2015 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 * Alexandre Montplaisir - Update to new ITmfEventAspect API
12 * Patrick Tasse - Make pcap aspects singletons
13 *******************************************************************************/
15 package org
.eclipse
.tracecompass
.internal
.tmf
.pcap
.core
.trace
;
17 import static org
.eclipse
.tracecompass
.common
.core
.NonNullUtils
.checkNotNull
;
18 import static org
.eclipse
.tracecompass
.common
.core
.NonNullUtils
.nullToEmptyString
;
20 import java
.io
.IOException
;
21 import java
.nio
.channels
.ClosedChannelException
;
22 import java
.nio
.file
.Path
;
23 import java
.nio
.file
.Paths
;
24 import java
.util
.Collection
;
25 import java
.util
.Collections
;
28 import org
.eclipse
.core
.resources
.IProject
;
29 import org
.eclipse
.core
.resources
.IResource
;
30 import org
.eclipse
.core
.runtime
.IStatus
;
31 import org
.eclipse
.core
.runtime
.Status
;
32 import org
.eclipse
.jdt
.annotation
.Nullable
;
33 import org
.eclipse
.tracecompass
.internal
.pcap
.core
.packet
.BadPacketException
;
34 import org
.eclipse
.tracecompass
.internal
.pcap
.core
.protocol
.pcap
.PcapPacket
;
35 import org
.eclipse
.tracecompass
.internal
.pcap
.core
.trace
.BadPcapFileException
;
36 import org
.eclipse
.tracecompass
.internal
.pcap
.core
.trace
.PcapFile
;
37 import org
.eclipse
.tracecompass
.internal
.pcap
.core
.util
.LinkTypeHelper
;
38 import org
.eclipse
.tracecompass
.internal
.tmf
.pcap
.core
.Activator
;
39 import org
.eclipse
.tracecompass
.internal
.tmf
.pcap
.core
.event
.PcapEvent
;
40 import org
.eclipse
.tracecompass
.internal
.tmf
.pcap
.core
.event
.aspect
.PcapDestinationAspect
;
41 import org
.eclipse
.tracecompass
.internal
.tmf
.pcap
.core
.event
.aspect
.PcapProtocolAspect
;
42 import org
.eclipse
.tracecompass
.internal
.tmf
.pcap
.core
.event
.aspect
.PcapReferenceAspect
;
43 import org
.eclipse
.tracecompass
.internal
.tmf
.pcap
.core
.event
.aspect
.PcapSourceAspect
;
44 import org
.eclipse
.tracecompass
.internal
.tmf
.pcap
.core
.util
.PcapEventFactory
;
45 import org
.eclipse
.tracecompass
.tmf
.core
.event
.ITmfEvent
;
46 import org
.eclipse
.tracecompass
.tmf
.core
.event
.aspect
.ITmfEventAspect
;
47 import org
.eclipse
.tracecompass
.tmf
.core
.exceptions
.TmfTraceException
;
48 import org
.eclipse
.tracecompass
.tmf
.core
.project
.model
.ITmfPropertiesProvider
;
49 import org
.eclipse
.tracecompass
.tmf
.core
.trace
.ITmfContext
;
50 import org
.eclipse
.tracecompass
.tmf
.core
.trace
.TmfContext
;
51 import org
.eclipse
.tracecompass
.tmf
.core
.trace
.TmfTrace
;
52 import org
.eclipse
.tracecompass
.tmf
.core
.trace
.TraceValidationStatus
;
53 import org
.eclipse
.tracecompass
.tmf
.core
.trace
.location
.ITmfLocation
;
54 import org
.eclipse
.tracecompass
.tmf
.core
.trace
.location
.TmfLongLocation
;
56 import com
.google
.common
.collect
.ImmutableList
;
57 import com
.google
.common
.collect
.ImmutableMap
;
60 * Class that represents a TMF Pcap Trace. It is used to make the glue between
61 * the Pcap parser and TMF.
63 * TODO handle fields in TmfEventType for the filter view.
65 * @author Vincent Perot
67 public class PcapTrace
extends TmfTrace
implements ITmfPropertiesProvider
{
69 /** pcap trace type id as defined in plugin.xml */
70 public static final String TRACE_TYPE_ID
= "org.eclipse.linuxtools.tmf.pcap.core.pcaptrace"; //$NON-NLS-1$
72 private static final Collection
<ITmfEventAspect
> PCAP_ASPECTS
=
74 ITmfEventAspect
.BaseAspects
.TIMESTAMP
,
75 PcapSourceAspect
.INSTANCE
,
76 PcapDestinationAspect
.INSTANCE
,
77 PcapReferenceAspect
.INSTANCE
,
78 PcapProtocolAspect
.INSTANCE
,
79 ITmfEventAspect
.BaseAspects
.CONTENTS
82 private static final String EMPTY_STRING
= ""; //$NON-NLS-1$
83 private static final int CONFIDENCE
= 50;
84 private @Nullable PcapFile fPcapFile
;
85 private @Nullable Map
<String
, String
> fTraceProperties
= null;
88 public synchronized ITmfLocation
getCurrentLocation() {
89 PcapFile pcap
= fPcapFile
;
91 return new TmfLongLocation(0);
93 return new TmfLongLocation(pcap
.getCurrentRank());
97 public synchronized double getLocationRatio(@Nullable ITmfLocation location
) {
98 TmfLongLocation loc
= (TmfLongLocation
) location
;
99 PcapFile pcap
= fPcapFile
;
100 if (loc
== null || pcap
== null) {
104 return (pcap
.getTotalNbPackets() == 0 ?
0 : ((double) loc
.getLocationInfo()) / pcap
.getTotalNbPackets());
105 } catch (IOException
| BadPcapFileException e
) {
106 String message
= e
.getMessage();
107 if (message
== null) {
108 message
= EMPTY_STRING
;
110 Activator
.logError(message
, e
);
117 public synchronized void initTrace(@Nullable IResource resource
, @Nullable String path
, @Nullable Class
<?
extends ITmfEvent
> type
) throws TmfTraceException
{
118 super.initTrace(resource
, path
, type
);
120 throw new TmfTraceException("No path has been specified."); //$NON-NLS-1$
122 Path filePath
= checkNotNull(Paths
.get(path
));
124 fPcapFile
= new PcapFile(filePath
);
125 } catch (IOException
| BadPcapFileException e
) {
126 throw new TmfTraceException(e
.getMessage(), e
);
131 public Iterable
<ITmfEventAspect
> getEventAspects() {
136 public synchronized @Nullable PcapEvent
parseEvent(@Nullable ITmfContext context
) {
137 if (context
== null) {
141 long rank
= context
.getRank();
142 PcapPacket packet
= null;
143 PcapFile pcap
= fPcapFile
;
148 pcap
.seekPacket(rank
);
149 packet
= pcap
.parseNextPacket();
150 } catch (ClosedChannelException e
) {
152 * This is handled independently and happens when the user closes
153 * the trace while it is being parsed. It simply stops the parsing.
154 * No need to log a error.
157 } catch (IOException
| BadPcapFileException
| BadPacketException e
) {
158 String message
= e
.getMessage();
159 if (message
== null) {
160 message
= EMPTY_STRING
;
162 Activator
.logError(message
, e
);
166 if (packet
== null) {
170 // Generate an event from this packet and return it.
171 return PcapEventFactory
.createEvent(packet
, pcap
, this);
176 public synchronized ITmfContext
seekEvent(double ratio
) {
178 PcapFile pcap
= fPcapFile
;
180 return new TmfContext(new TmfLongLocation(0), 0);
185 * The ratio is between 0 and 1. We multiply it by the total number
186 * of packets to get the position.
188 position
= (long) (ratio
* pcap
.getTotalNbPackets());
189 } catch (IOException
| BadPcapFileException e
) {
190 String message
= e
.getMessage();
191 if (message
== null) {
192 message
= EMPTY_STRING
;
194 Activator
.logError(message
, e
);
195 return new TmfContext(new TmfLongLocation(0), 0);
197 TmfLongLocation loc
= new TmfLongLocation(position
);
198 return new TmfContext(loc
, loc
.getLocationInfo());
202 public synchronized ITmfContext
seekEvent(@Nullable ITmfLocation location
) {
203 TmfLongLocation loc
= (TmfLongLocation
) location
;
205 return new TmfContext(new TmfLongLocation(0));
208 return new TmfContext(loc
, loc
.getLocationInfo());
212 public IStatus
validate(@Nullable IProject project
, @Nullable String path
) {
214 // All validations are made when making a new pcap file.
216 return new Status(IStatus
.ERROR
, Activator
.PLUGIN_ID
, EMPTY_STRING
);
218 Path filePath
= checkNotNull(Paths
.get(path
));
219 try (PcapFile file
= new PcapFile(filePath
)) {
220 } catch (IOException
| BadPcapFileException e
) {
221 return new Status(IStatus
.ERROR
, Activator
.PLUGIN_ID
, e
.toString());
223 return new TraceValidationStatus(CONFIDENCE
, Activator
.PLUGIN_ID
);
227 public synchronized void dispose() {
229 PcapFile pcap
= fPcapFile
;
236 } catch (IOException e
) {
237 String message
= e
.getMessage();
238 if (message
== null) {
239 message
= EMPTY_STRING
;
241 Activator
.logError(message
, e
);
247 public synchronized Map
<String
, String
> getProperties() {
248 PcapFile pcap
= fPcapFile
;
250 return Collections
.emptyMap();
253 if (fTraceProperties
!= null) {
254 return fTraceProperties
;
257 ImmutableMap
.Builder
<String
, String
> builder
= ImmutableMap
.builder();
258 builder
.put(nullToEmptyString(Messages
.PcapTrace_Version
), String
.format("%d%c%d", pcap
.getMajorVersion(), '.', pcap
.getMinorVersion())); //$NON-NLS-1$
259 builder
.put(nullToEmptyString(Messages
.PcapTrace_TimeZoneCorrection
), pcap
.getTimeZoneCorrection() + " s"); //$NON-NLS-1$
260 builder
.put(nullToEmptyString(Messages
.PcapTrace_TimestampAccuracy
), String
.valueOf(pcap
.getTimeAccuracy()));
261 builder
.put(nullToEmptyString(Messages
.PcapTrace_MaxSnapLength
), pcap
.getSnapLength() + " bytes"); //$NON-NLS-1$
262 builder
.put(nullToEmptyString(Messages
.PcapTrace_LinkLayerHeaderType
), LinkTypeHelper
.toString((int) pcap
.getDataLinkType()) + " (" + pcap
.getDataLinkType() + ")"); //$NON-NLS-1$ //$NON-NLS-2$
263 builder
.put(nullToEmptyString(Messages
.PcapTrace_FileEndianness
), nullToEmptyString(pcap
.getByteOrder().toString()));
265 fTraceProperties
= builder
.build();
267 return fTraceProperties
;