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
;
19 import java
.io
.IOException
;
20 import java
.nio
.channels
.ClosedChannelException
;
21 import java
.nio
.file
.Path
;
22 import java
.nio
.file
.Paths
;
23 import java
.util
.Collection
;
24 import java
.util
.Collections
;
27 import org
.eclipse
.core
.resources
.IProject
;
28 import org
.eclipse
.core
.resources
.IResource
;
29 import org
.eclipse
.core
.runtime
.IStatus
;
30 import org
.eclipse
.core
.runtime
.Status
;
31 import org
.eclipse
.jdt
.annotation
.Nullable
;
32 import org
.eclipse
.tracecompass
.internal
.pcap
.core
.packet
.BadPacketException
;
33 import org
.eclipse
.tracecompass
.internal
.pcap
.core
.protocol
.pcap
.PcapPacket
;
34 import org
.eclipse
.tracecompass
.internal
.pcap
.core
.trace
.BadPcapFileException
;
35 import org
.eclipse
.tracecompass
.internal
.pcap
.core
.trace
.PcapFile
;
36 import org
.eclipse
.tracecompass
.internal
.pcap
.core
.util
.LinkTypeHelper
;
37 import org
.eclipse
.tracecompass
.internal
.tmf
.pcap
.core
.Activator
;
38 import org
.eclipse
.tracecompass
.internal
.tmf
.pcap
.core
.event
.PcapEvent
;
39 import org
.eclipse
.tracecompass
.internal
.tmf
.pcap
.core
.event
.aspect
.PcapDestinationAspect
;
40 import org
.eclipse
.tracecompass
.internal
.tmf
.pcap
.core
.event
.aspect
.PcapProtocolAspect
;
41 import org
.eclipse
.tracecompass
.internal
.tmf
.pcap
.core
.event
.aspect
.PcapReferenceAspect
;
42 import org
.eclipse
.tracecompass
.internal
.tmf
.pcap
.core
.event
.aspect
.PcapSourceAspect
;
43 import org
.eclipse
.tracecompass
.internal
.tmf
.pcap
.core
.util
.PcapEventFactory
;
44 import org
.eclipse
.tracecompass
.tmf
.core
.event
.ITmfEvent
;
45 import org
.eclipse
.tracecompass
.tmf
.core
.event
.aspect
.ITmfEventAspect
;
46 import org
.eclipse
.tracecompass
.tmf
.core
.exceptions
.TmfTraceException
;
47 import org
.eclipse
.tracecompass
.tmf
.core
.trace
.ITmfContext
;
48 import org
.eclipse
.tracecompass
.tmf
.core
.trace
.ITmfTraceProperties
;
49 import org
.eclipse
.tracecompass
.tmf
.core
.trace
.TmfContext
;
50 import org
.eclipse
.tracecompass
.tmf
.core
.trace
.TmfTrace
;
51 import org
.eclipse
.tracecompass
.tmf
.core
.trace
.TraceValidationStatus
;
52 import org
.eclipse
.tracecompass
.tmf
.core
.trace
.location
.ITmfLocation
;
53 import org
.eclipse
.tracecompass
.tmf
.core
.trace
.location
.TmfLongLocation
;
55 import com
.google
.common
.collect
.ImmutableList
;
56 import com
.google
.common
.collect
.ImmutableMap
;
59 * Class that represents a TMF Pcap Trace. It is used to make the glue between
60 * the Pcap parser and TMF.
62 * TODO handle fields in TmfEventType for the filter view.
64 * @author Vincent Perot
66 public class PcapTrace
extends TmfTrace
implements ITmfTraceProperties
, AutoCloseable
{
68 /** pcap trace type id as defined in plugin.xml */
69 public static final String TRACE_TYPE_ID
= "org.eclipse.linuxtools.tmf.pcap.core.pcaptrace"; //$NON-NLS-1$
71 private static final Collection
<ITmfEventAspect
> PCAP_ASPECTS
=
72 checkNotNull(ImmutableList
.of(
73 ITmfEventAspect
.BaseAspects
.TIMESTAMP
,
74 PcapSourceAspect
.INSTANCE
,
75 PcapDestinationAspect
.INSTANCE
,
76 PcapReferenceAspect
.INSTANCE
,
77 PcapProtocolAspect
.INSTANCE
,
78 ITmfEventAspect
.BaseAspects
.CONTENTS
81 private static final String EMPTY_STRING
= ""; //$NON-NLS-1$
82 private static final int CONFIDENCE
= 50;
83 private @Nullable PcapFile fPcapFile
;
84 private @Nullable Map
<String
, String
> fTraceProperties
= null;
87 public synchronized ITmfLocation
getCurrentLocation() {
88 PcapFile pcap
= fPcapFile
;
90 return new TmfLongLocation(0);
92 return new TmfLongLocation(pcap
.getCurrentRank());
96 public synchronized double getLocationRatio(@Nullable ITmfLocation location
) {
97 TmfLongLocation loc
= (TmfLongLocation
) location
;
98 PcapFile pcap
= fPcapFile
;
99 if (loc
== null || pcap
== null) {
103 return (pcap
.getTotalNbPackets() == 0 ?
0 : ((double) loc
.getLocationInfo()) / pcap
.getTotalNbPackets());
104 } catch (IOException
| BadPcapFileException e
) {
105 String message
= e
.getMessage();
106 if (message
== null) {
107 message
= EMPTY_STRING
;
109 Activator
.logError(message
, e
);
116 public synchronized void initTrace(@Nullable IResource resource
, @Nullable String path
, @Nullable Class
<?
extends ITmfEvent
> type
) throws TmfTraceException
{
117 super.initTrace(resource
, path
, type
);
119 throw new TmfTraceException("No path has been specified."); //$NON-NLS-1$
121 Path filePath
= checkNotNull(Paths
.get(path
));
123 fPcapFile
= new PcapFile(filePath
);
124 } catch (IOException
| BadPcapFileException e
) {
125 throw new TmfTraceException(e
.getMessage(), e
);
130 public Iterable
<ITmfEventAspect
> getEventAspects() {
135 public synchronized @Nullable PcapEvent
parseEvent(@Nullable ITmfContext context
) {
136 if (context
== null) {
140 long rank
= context
.getRank();
141 PcapPacket packet
= null;
142 PcapFile pcap
= fPcapFile
;
147 pcap
.seekPacket(rank
);
148 packet
= pcap
.parseNextPacket();
149 } catch (ClosedChannelException e
) {
151 * This is handled independently and happens when the user closes
152 * the trace while it is being parsed. It simply stops the parsing.
153 * No need to log a error.
156 } catch (IOException
| BadPcapFileException
| BadPacketException e
) {
157 String message
= e
.getMessage();
158 if (message
== null) {
159 message
= EMPTY_STRING
;
161 Activator
.logError(message
, e
);
165 if (packet
== null) {
169 // Generate an event from this packet and return it.
170 return PcapEventFactory
.createEvent(packet
, pcap
, this);
175 public synchronized ITmfContext
seekEvent(double ratio
) {
177 PcapFile pcap
= fPcapFile
;
179 return new TmfContext(new TmfLongLocation(0), 0);
184 * The ratio is between 0 and 1. We multiply it by the total number
185 * of packets to get the position.
187 position
= (long) (ratio
* pcap
.getTotalNbPackets());
188 } catch (IOException
| BadPcapFileException e
) {
189 String message
= e
.getMessage();
190 if (message
== null) {
191 message
= EMPTY_STRING
;
193 Activator
.logError(message
, e
);
194 return new TmfContext(new TmfLongLocation(0), 0);
196 TmfLongLocation loc
= new TmfLongLocation(position
);
197 return new TmfContext(loc
, loc
.getLocationInfo());
201 public synchronized ITmfContext
seekEvent(@Nullable ITmfLocation location
) {
202 TmfLongLocation loc
= (TmfLongLocation
) location
;
204 return new TmfContext(new TmfLongLocation(0));
207 return new TmfContext(loc
, loc
.getLocationInfo());
211 public IStatus
validate(@Nullable IProject project
, @Nullable String path
) {
213 // All validations are made when making a new pcap file.
215 return new Status(IStatus
.ERROR
, Activator
.PLUGIN_ID
, EMPTY_STRING
);
217 Path filePath
= checkNotNull(Paths
.get(path
));
218 try (PcapFile file
= new PcapFile(filePath
)) {
219 } catch (IOException
| BadPcapFileException e
) {
220 return new Status(IStatus
.ERROR
, Activator
.PLUGIN_ID
, e
.toString());
222 return new TraceValidationStatus(CONFIDENCE
, Activator
.PLUGIN_ID
);
226 public synchronized void dispose() {
228 PcapFile pcap
= fPcapFile
;
235 } catch (IOException e
) {
236 String message
= e
.getMessage();
237 if (message
== null) {
238 message
= EMPTY_STRING
;
240 Activator
.logError(message
, e
);
246 public synchronized Map
<String
, String
> getTraceProperties() {
247 PcapFile pcap
= fPcapFile
;
249 return checkNotNull(Collections
.<String
, String
> emptyMap());
252 Map
<String
, String
> properties
= fTraceProperties
;
253 if (properties
== null) {
254 ImmutableMap
.Builder
<String
, String
> builder
= ImmutableMap
.<String
, String
> builder();
255 builder
.put(Messages
.PcapTrace_Version
, String
.format("%d%c%d", pcap
.getMajorVersion(), '.', pcap
.getMinorVersion())); //$NON-NLS-1$
256 builder
.put(Messages
.PcapTrace_TimeZoneCorrection
, pcap
.getTimeZoneCorrection() + " s"); //$NON-NLS-1$
257 builder
.put(Messages
.PcapTrace_TimestampAccuracy
, String
.valueOf(pcap
.getTimeAccuracy()));
258 builder
.put(Messages
.PcapTrace_MaxSnapLength
, pcap
.getSnapLength() + " bytes"); //$NON-NLS-1$
259 builder
.put(Messages
.PcapTrace_LinkLayerHeaderType
, LinkTypeHelper
.toString((int) pcap
.getDataLinkType()) + " (" + pcap
.getDataLinkType() + ")"); //$NON-NLS-1$ //$NON-NLS-2$
260 builder
.put(Messages
.PcapTrace_FileEndianness
, pcap
.getByteOrder().toString());
262 return checkNotNull(builder
.build());
270 public void close() {