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