42e30d995596ed1f73d6c2fa114f480f2ff884d3
[deliverable/tracecompass.git] / pcap / org.eclipse.tracecompass.tmf.pcap.core / src / org / eclipse / tracecompass / internal / tmf / pcap / core / trace / PcapTrace.java
1 /*******************************************************************************
2 * Copyright (c) 2014, 2015 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 * Alexandre Montplaisir - Update to new ITmfEventAspect API
12 * Patrick Tasse - Make pcap aspects singletons
13 *******************************************************************************/
14
15 package org.eclipse.tracecompass.internal.tmf.pcap.core.trace;
16
17 import static org.eclipse.tracecompass.common.core.NonNullUtils.checkNotNull;
18
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;
25 import java.util.Map;
26
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;
54
55 import com.google.common.collect.ImmutableList;
56 import com.google.common.collect.ImmutableMap;
57
58 /**
59 * Class that represents a TMF Pcap Trace. It is used to make the glue between
60 * the Pcap parser and TMF.
61 *
62 * TODO handle fields in TmfEventType for the filter view.
63 *
64 * @author Vincent Perot
65 */
66 public class PcapTrace extends TmfTrace implements ITmfTraceProperties, AutoCloseable {
67
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$
70
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
79 ));
80
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;
85
86 @Override
87 public synchronized ITmfLocation getCurrentLocation() {
88 PcapFile pcap = fPcapFile;
89 if (pcap == null) {
90 return new TmfLongLocation(0);
91 }
92 return new TmfLongLocation(pcap.getCurrentRank());
93 }
94
95 @Override
96 public synchronized double getLocationRatio(@Nullable ITmfLocation location) {
97 TmfLongLocation loc = (TmfLongLocation) location;
98 PcapFile pcap = fPcapFile;
99 if (loc == null || pcap == null) {
100 return 0;
101 }
102 try {
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;
108 }
109 Activator.logError(message, e);
110 return 0;
111 }
112
113 }
114
115 @Override
116 public synchronized void initTrace(@Nullable IResource resource, @Nullable String path, @Nullable Class<? extends ITmfEvent> type) throws TmfTraceException {
117 super.initTrace(resource, path, type);
118 if (path == null) {
119 throw new TmfTraceException("No path has been specified."); //$NON-NLS-1$
120 }
121 Path filePath = checkNotNull(Paths.get(path));
122 try {
123 fPcapFile = new PcapFile(filePath);
124 } catch (IOException | BadPcapFileException e) {
125 throw new TmfTraceException(e.getMessage(), e);
126 }
127 }
128
129 @Override
130 public Iterable<ITmfEventAspect> getEventAspects() {
131 return PCAP_ASPECTS;
132 }
133
134 @Override
135 public synchronized @Nullable PcapEvent parseEvent(@Nullable ITmfContext context) {
136 if (context == null) {
137 return null;
138 }
139
140 long rank = context.getRank();
141 PcapPacket packet = null;
142 PcapFile pcap = fPcapFile;
143 if (pcap == null) {
144 return null;
145 }
146 try {
147 pcap.seekPacket(rank);
148 packet = pcap.parseNextPacket();
149 } catch (ClosedChannelException e) {
150 /*
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.
154 */
155 return null;
156 } catch (IOException | BadPcapFileException | BadPacketException e) {
157 String message = e.getMessage();
158 if (message == null) {
159 message = EMPTY_STRING;
160 }
161 Activator.logError(message, e);
162 return null;
163 }
164
165 if (packet == null) {
166 return null;
167 }
168
169 // Generate an event from this packet and return it.
170 return PcapEventFactory.createEvent(packet, pcap, this);
171
172 }
173
174 @Override
175 public synchronized ITmfContext seekEvent(double ratio) {
176 long position;
177 PcapFile pcap = fPcapFile;
178 if (pcap == null) {
179 return new TmfContext(new TmfLongLocation(0), 0);
180 }
181
182 try {
183 /*
184 * The ratio is between 0 and 1. We multiply it by the total number
185 * of packets to get the position.
186 */
187 position = (long) (ratio * pcap.getTotalNbPackets());
188 } catch (IOException | BadPcapFileException e) {
189 String message = e.getMessage();
190 if (message == null) {
191 message = EMPTY_STRING;
192 }
193 Activator.logError(message, e);
194 return new TmfContext(new TmfLongLocation(0), 0);
195 }
196 TmfLongLocation loc = new TmfLongLocation(position);
197 return new TmfContext(loc, loc.getLocationInfo());
198 }
199
200 @Override
201 public synchronized ITmfContext seekEvent(@Nullable ITmfLocation location) {
202 TmfLongLocation loc = (TmfLongLocation) location;
203 if (loc == null) {
204 return new TmfContext(new TmfLongLocation(0));
205 }
206
207 return new TmfContext(loc, loc.getLocationInfo());
208 }
209
210 @Override
211 public IStatus validate(@Nullable IProject project, @Nullable String path) {
212
213 // All validations are made when making a new pcap file.
214 if (path == null) {
215 return new Status(IStatus.ERROR, Activator.PLUGIN_ID, EMPTY_STRING);
216 }
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());
221 }
222 return new TraceValidationStatus(CONFIDENCE, Activator.PLUGIN_ID);
223 }
224
225 @Override
226 public synchronized void dispose() {
227 super.dispose();
228 PcapFile pcap = fPcapFile;
229 if (pcap == null) {
230 return;
231 }
232 try {
233 pcap.close();
234 fPcapFile = null;
235 } catch (IOException e) {
236 String message = e.getMessage();
237 if (message == null) {
238 message = EMPTY_STRING;
239 }
240 Activator.logError(message, e);
241 return;
242 }
243 }
244
245 @Override
246 public synchronized Map<String, String> getTraceProperties() {
247 PcapFile pcap = fPcapFile;
248 if (pcap == null) {
249 return checkNotNull(Collections.<String, String> emptyMap());
250 }
251
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());
261
262 return checkNotNull(builder.build());
263
264 }
265
266 return properties;
267 }
268
269 @Override
270 public void close() {
271 dispose();
272 }
273 }
This page took 0.043684 seconds and 4 git commands to generate.