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
.util
;
15 import java
.nio
.file
.Path
;
16 import java
.util
.ArrayList
;
17 import java
.util
.HashMap
;
18 import java
.util
.List
;
21 import org
.eclipse
.jdt
.annotation
.NonNull
;
22 import org
.eclipse
.jdt
.annotation
.Nullable
;
23 import org
.eclipse
.tracecompass
.internal
.pcap
.core
.packet
.Packet
;
24 import org
.eclipse
.tracecompass
.internal
.pcap
.core
.protocol
.PcapProtocol
;
25 import org
.eclipse
.tracecompass
.internal
.pcap
.core
.protocol
.pcap
.PcapPacket
;
26 import org
.eclipse
.tracecompass
.internal
.pcap
.core
.trace
.PcapFile
;
27 import org
.eclipse
.tracecompass
.internal
.pcap
.core
.util
.LinkTypeHelper
;
28 import org
.eclipse
.tracecompass
.internal
.pcap
.core
.util
.PcapTimestampScale
;
29 import org
.eclipse
.tracecompass
.internal
.tmf
.pcap
.core
.event
.PcapEvent
;
30 import org
.eclipse
.tracecompass
.internal
.tmf
.pcap
.core
.event
.PcapEventField
;
31 import org
.eclipse
.tracecompass
.internal
.tmf
.pcap
.core
.event
.PcapEventType
;
32 import org
.eclipse
.tracecompass
.internal
.tmf
.pcap
.core
.event
.PcapRootEventField
;
33 import org
.eclipse
.tracecompass
.internal
.tmf
.pcap
.core
.trace
.PcapTrace
;
34 import org
.eclipse
.tracecompass
.tmf
.core
.event
.ITmfEventField
;
35 import org
.eclipse
.tracecompass
.tmf
.core
.event
.TmfEventField
;
36 import org
.eclipse
.tracecompass
.tmf
.core
.event
.TmfEventType
;
37 import org
.eclipse
.tracecompass
.tmf
.core
.timestamp
.ITmfTimestamp
;
38 import org
.eclipse
.tracecompass
.tmf
.core
.timestamp
.TmfTimestamp
;
41 * Factory class that helps generating Pcap Events.
43 * @author Vincent Perot
45 public class PcapEventFactory
{
47 private static final ITmfEventField
[] EMPTY_FIELD_ARRAY
= new ITmfEventField
[0];
48 private static final String EMPTY_STRING
= ""; //$NON-NLS-1$
50 private static final Map
<PcapProtocol
, TmfEventType
> fEventTypes
= new HashMap
<>();
52 private PcapEventFactory() {
56 * Method that create a PcapEvent from a packet.
59 * The packet to generate the event from.
61 * The pcap file to which the packet belongs.
63 * The trace to which this packet belongs.
64 * @return The generated PcapEvent.
66 public static @Nullable PcapEvent
createEvent(PcapPacket pcapPacket
, PcapFile pcap
, PcapTrace trace
) {
67 long rank
= pcapPacket
.getIndex();
68 long timestamp
= pcapPacket
.getTimestamp();
69 PcapTimestampScale scale
= pcapPacket
.getTimestampScale();
70 ITmfTimestamp tmfTimestamp
;
73 long us
= trace
.getTimestampTransform().transform(timestamp
* 1000) / 1000;
74 tmfTimestamp
= new TmfTimestamp(us
, ITmfTimestamp
.MICROSECOND_SCALE
, (int) pcap
.getTimeAccuracy());
77 long ns
= trace
.getTimestampTransform().transform(timestamp
);
78 tmfTimestamp
= new TmfTimestamp(ns
, ITmfTimestamp
.NANOSECOND_SCALE
, (int) pcap
.getTimeAccuracy());
81 throw new IllegalArgumentException("The timestamp precision is not valid!"); //$NON-NLS-1$
83 Path filePath
= pcap
.getPath().getFileName();
84 @SuppressWarnings("null") // for .toString()
85 @NonNull String fileName
= (filePath
== null ? EMPTY_STRING
: filePath
.toString());
87 String dataLink
= Messages
.PcapEventFactory_LinkType
+ ':' + LinkTypeHelper
.toString((int) pcapPacket
.getPcapFile().getDataLinkType());
89 ITmfEventField
[] fields
= generatePacketFields(pcapPacket
);
90 ITmfEventField field
= new PcapRootEventField(EMPTY_STRING
, fields
, pcapPacket
);
91 Packet packet
= pcapPacket
.getMostEcapsulatedPacket();
92 if (!fEventTypes
.containsKey(packet
.getProtocol())) {
93 String typeIdString
= PcapEventType
.DEFAULT_PCAP_TYPE_ID
+ ':' + packet
.getProtocol().getShortName();
94 fEventTypes
.put(packet
.getProtocol(), new PcapEventType(typeIdString
, null));
96 TmfEventType eventType
= fEventTypes
.get(packet
.getProtocol());
97 if (eventType
== null) {
98 eventType
= new TmfEventType();
100 return new PcapEvent(trace
, rank
, tmfTimestamp
, dataLink
, eventType
, field
, fileName
, packet
);
104 private static ITmfEventField
[] generatePacketFields(Packet packet
) {
105 // TODO This is SOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOO slow. Must find a
106 // way to use less intermediate data structures.
107 List
<ITmfEventField
> fieldList
= new ArrayList
<>();
108 List
<ITmfEventField
> subfieldList
= new ArrayList
<>();
109 Packet localPacket
= packet
.getPacket(PcapProtocol
.PCAP
);
111 while (localPacket
!= null) {
112 subfieldList
.clear();
113 for (Map
.Entry
<String
, String
> entry
: localPacket
.getFields().entrySet()) {
115 @SuppressWarnings("null")
116 @NonNull String key
= entry
.getKey();
118 @SuppressWarnings("null")
119 @NonNull String value
= entry
.getValue();
120 subfieldList
.add(new TmfEventField(key
, value
, null));
122 ITmfEventField
[] subfieldArray
= subfieldList
.toArray(new ITmfEventField
[subfieldList
.size()]);
123 fieldList
.add(new PcapEventField(localPacket
.getProtocol().getName(), EMPTY_STRING
, subfieldArray
, localPacket
));
124 localPacket
= localPacket
.getChildPacket();
127 ITmfEventField
[] fieldArray
= fieldList
.toArray(new ITmfEventField
[fieldList
.size()]);
128 if (fieldArray
== null) {
129 return EMPTY_FIELD_ARRAY
;