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
.tracecompass
.internal
.tmf
.pcap
.core
.trace
;
15 import java
.io
.IOException
;
16 import java
.nio
.channels
.ClosedChannelException
;
17 import java
.nio
.file
.FileSystems
;
18 import java
.nio
.file
.Path
;
21 import org
.eclipse
.core
.resources
.IProject
;
22 import org
.eclipse
.core
.resources
.IResource
;
23 import org
.eclipse
.core
.runtime
.IStatus
;
24 import org
.eclipse
.core
.runtime
.Status
;
25 import org
.eclipse
.jdt
.annotation
.NonNull
;
26 import org
.eclipse
.jdt
.annotation
.Nullable
;
27 import org
.eclipse
.tracecompass
.internal
.pcap
.core
.packet
.BadPacketException
;
28 import org
.eclipse
.tracecompass
.internal
.pcap
.core
.protocol
.pcap
.PcapPacket
;
29 import org
.eclipse
.tracecompass
.internal
.pcap
.core
.trace
.BadPcapFileException
;
30 import org
.eclipse
.tracecompass
.internal
.pcap
.core
.trace
.PcapFile
;
31 import org
.eclipse
.tracecompass
.internal
.pcap
.core
.util
.LinkTypeHelper
;
32 import org
.eclipse
.tracecompass
.internal
.tmf
.pcap
.core
.Activator
;
33 import org
.eclipse
.tracecompass
.internal
.tmf
.pcap
.core
.event
.PcapEvent
;
34 import org
.eclipse
.tracecompass
.internal
.tmf
.pcap
.core
.util
.PcapEventFactory
;
35 import org
.eclipse
.tracecompass
.tmf
.core
.event
.ITmfEvent
;
36 import org
.eclipse
.tracecompass
.tmf
.core
.exceptions
.TmfTraceException
;
37 import org
.eclipse
.tracecompass
.tmf
.core
.trace
.ITmfContext
;
38 import org
.eclipse
.tracecompass
.tmf
.core
.trace
.ITmfEventParser
;
39 import org
.eclipse
.tracecompass
.tmf
.core
.trace
.ITmfTraceProperties
;
40 import org
.eclipse
.tracecompass
.tmf
.core
.trace
.TmfContext
;
41 import org
.eclipse
.tracecompass
.tmf
.core
.trace
.TmfTrace
;
42 import org
.eclipse
.tracecompass
.tmf
.core
.trace
.TraceValidationStatus
;
43 import org
.eclipse
.tracecompass
.tmf
.core
.trace
.location
.ITmfLocation
;
44 import org
.eclipse
.tracecompass
.tmf
.core
.trace
.location
.TmfLongLocation
;
46 import com
.google
.common
.collect
.ImmutableMap
;
49 * Class that represents a TMF Pcap Trace. It is used to make the glue between
50 * the Pcap parser and TMF.
52 * TODO handle fields in TmfEventType for the filter view.
54 * @author Vincent Perot
56 public class PcapTrace
extends TmfTrace
implements ITmfEventParser
, ITmfTraceProperties
, AutoCloseable
{
58 @SuppressWarnings("null")
59 private static final @NonNull Map
<String
, String
> EMPTY_MAP
= ImmutableMap
.of();
60 private static final String EMPTY_STRING
= ""; //$NON-NLS-1$
61 private static final int CONFIDENCE
= 50;
62 private @Nullable PcapFile fPcapFile
;
63 private @Nullable ImmutableMap
<String
, String
> fTraceProperties
= null;
66 public synchronized ITmfLocation
getCurrentLocation() {
67 PcapFile pcap
= fPcapFile
;
69 return new TmfLongLocation(0);
71 return new TmfLongLocation(pcap
.getCurrentRank());
75 public synchronized double getLocationRatio(@Nullable ITmfLocation location
) {
76 TmfLongLocation loc
= (TmfLongLocation
) location
;
77 PcapFile pcap
= fPcapFile
;
78 if (loc
== null || pcap
== null) {
82 return (pcap
.getTotalNbPackets() == 0 ?
0 : ((double) loc
.getLocationInfo()) / pcap
.getTotalNbPackets());
83 } catch (IOException
| BadPcapFileException e
) {
84 String message
= e
.getMessage();
85 if (message
== null) {
86 message
= EMPTY_STRING
;
88 Activator
.logError(message
, e
);
95 public synchronized void initTrace(@Nullable IResource resource
, @Nullable String path
, @Nullable Class
<?
extends ITmfEvent
> type
) throws TmfTraceException
{
96 super.initTrace(resource
, path
, type
);
98 throw new TmfTraceException("No path has been specified."); //$NON-NLS-1$
100 @SuppressWarnings("null")
101 @NonNull Path filePath
= FileSystems
.getDefault().getPath(path
);
103 fPcapFile
= new PcapFile(filePath
);
104 } catch (IOException
| BadPcapFileException e
) {
105 throw new TmfTraceException(e
.getMessage(), e
);
110 public synchronized @Nullable PcapEvent
parseEvent(@Nullable ITmfContext context
) {
111 if (context
== null) {
115 long rank
= context
.getRank();
116 PcapPacket packet
= null;
117 PcapFile pcap
= fPcapFile
;
122 pcap
.seekPacket(rank
);
123 packet
= pcap
.parseNextPacket();
124 } catch (ClosedChannelException e
) {
126 * This is handled independently and happens when the user closes
127 * the trace while it is being parsed. It simply stops the parsing.
128 * No need to log a error.
131 } catch (IOException
| BadPcapFileException
| BadPacketException e
) {
132 String message
= e
.getMessage();
133 if (message
== null) {
134 message
= EMPTY_STRING
;
136 Activator
.logError(message
, e
);
140 if (packet
== null) {
144 // Generate an event from this packet and return it.
145 return PcapEventFactory
.createEvent(packet
, pcap
, this);
150 public synchronized ITmfContext
seekEvent(double ratio
) {
152 PcapFile pcap
= fPcapFile
;
154 return new TmfContext(new TmfLongLocation(0), 0);
159 * The ratio is between 0 and 1. We multiply it by the total number
160 * of packets to get the position.
162 position
= (long) (ratio
* pcap
.getTotalNbPackets());
163 } catch (IOException
| BadPcapFileException e
) {
164 String message
= e
.getMessage();
165 if (message
== null) {
166 message
= EMPTY_STRING
;
168 Activator
.logError(message
, e
);
169 return new TmfContext(new TmfLongLocation(0), 0);
171 TmfLongLocation loc
= new TmfLongLocation(position
);
172 return new TmfContext(loc
, loc
.getLocationInfo());
176 public synchronized ITmfContext
seekEvent(@Nullable ITmfLocation location
) {
177 TmfLongLocation loc
= (TmfLongLocation
) location
;
179 return new TmfContext(new TmfLongLocation(0));
182 return new TmfContext(loc
, loc
.getLocationInfo());
186 public IStatus
validate(@Nullable IProject project
, @Nullable String path
) {
188 // All validations are made when making a new pcap file.
190 return new Status(IStatus
.ERROR
, Activator
.PLUGIN_ID
, EMPTY_STRING
);
192 @SuppressWarnings("null")
193 @NonNull Path filePath
= FileSystems
.getDefault().getPath(path
);
194 try (PcapFile file
= new PcapFile(filePath
)) {
195 } catch (IOException
| BadPcapFileException e
) {
196 return new Status(IStatus
.ERROR
, Activator
.PLUGIN_ID
, e
.toString());
198 return new TraceValidationStatus(CONFIDENCE
, Activator
.PLUGIN_ID
);
202 public synchronized void dispose() {
204 PcapFile pcap
= fPcapFile
;
211 } catch (IOException e
) {
212 String message
= e
.getMessage();
213 if (message
== null) {
214 message
= EMPTY_STRING
;
216 Activator
.logError(message
, e
);
222 public synchronized Map
<String
, String
> getTraceProperties() {
223 PcapFile pcap
= fPcapFile
;
228 ImmutableMap
<String
, String
> properties
= fTraceProperties
;
229 if (properties
== null) {
230 @SuppressWarnings("null")
231 @NonNull ImmutableMap
<String
, String
> newProperties
= ImmutableMap
.<String
, String
> builder()
232 .put(Messages
.PcapTrace_Version
, String
.format("%d%c%d", pcap
.getMajorVersion(), '.', pcap
.getMinorVersion())) //$NON-NLS-1$
233 .put(Messages
.PcapTrace_TimeZoneCorrection
, pcap
.getTimeZoneCorrection() + " s") //$NON-NLS-1$
234 .put(Messages
.PcapTrace_TimestampAccuracy
, String
.valueOf(pcap
.getTimeAccuracy()))
235 .put(Messages
.PcapTrace_MaxSnapLength
, pcap
.getSnapLength() + " bytes") //$NON-NLS-1$
236 .put(Messages
.PcapTrace_LinkLayerHeaderType
, LinkTypeHelper
.toString((int) pcap
.getDataLinkType()) + " (" + pcap
.getDataLinkType() + ")") //$NON-NLS-1$ //$NON-NLS-2$
237 .put(Messages
.PcapTrace_FileEndianness
, pcap
.getByteOrder().toString())
239 fTraceProperties
= newProperties
;
240 return newProperties
;
248 public void close() {