| /******************************************************************************* |
| * Copyright (c) 2014, 2019 Ericsson |
| * |
| * All rights reserved. This program and the accompanying materials are |
| * made available under the terms of the Eclipse Public License 2.0 which |
| * accompanies this distribution, and is available at |
| * https://www.eclipse.org/legal/epl-2.0/ |
| * |
| * SPDX-License-Identifier: EPL-2.0 |
| * |
| * Contributors: |
| * Vincent Perot - Initial API and implementation |
| *******************************************************************************/ |
| |
| package org.eclipse.tracecompass.internal.tmf.pcap.core.util; |
| |
| import static org.eclipse.tracecompass.common.core.NonNullUtils.checkNotNull; |
| |
| import java.nio.file.Path; |
| import java.util.ArrayList; |
| import java.util.HashMap; |
| import java.util.List; |
| import java.util.Map; |
| |
| import org.eclipse.jdt.annotation.NonNull; |
| import org.eclipse.jdt.annotation.Nullable; |
| import org.eclipse.tracecompass.internal.pcap.core.packet.Packet; |
| import org.eclipse.tracecompass.internal.pcap.core.protocol.PcapProtocol; |
| import org.eclipse.tracecompass.internal.pcap.core.protocol.pcap.PcapPacket; |
| import org.eclipse.tracecompass.internal.pcap.core.trace.PcapFile; |
| import org.eclipse.tracecompass.internal.pcap.core.util.LinkTypeHelper; |
| import org.eclipse.tracecompass.internal.pcap.core.util.PcapTimestampScale; |
| import org.eclipse.tracecompass.internal.tmf.pcap.core.event.PcapEvent; |
| import org.eclipse.tracecompass.internal.tmf.pcap.core.event.PcapEventField; |
| import org.eclipse.tracecompass.internal.tmf.pcap.core.event.PcapEventType; |
| import org.eclipse.tracecompass.internal.tmf.pcap.core.event.PcapRootEventField; |
| import org.eclipse.tracecompass.internal.tmf.pcap.core.trace.PcapTrace; |
| import org.eclipse.tracecompass.tmf.core.event.ITmfEventField; |
| import org.eclipse.tracecompass.tmf.core.event.TmfEventField; |
| import org.eclipse.tracecompass.tmf.core.event.TmfEventType; |
| import org.eclipse.tracecompass.tmf.core.timestamp.ITmfTimestamp; |
| import org.eclipse.tracecompass.tmf.core.timestamp.TmfTimestamp; |
| |
| /** |
| * Factory class that helps generating Pcap Events. |
| * |
| * @author Vincent Perot |
| */ |
| public final class PcapEventFactory { |
| |
| private static final String EMPTY_STRING = ""; //$NON-NLS-1$ |
| |
| private static final Map<PcapProtocol, TmfEventType> fEventTypes = new HashMap<>(); |
| |
| private PcapEventFactory() { |
| } |
| |
| /** |
| * Method that create a PcapEvent from a packet. |
| * |
| * @param pcapPacket |
| * The packet to generate the event from. |
| * @param pcap |
| * The pcap file to which the packet belongs. |
| * @param trace |
| * The trace to which this packet belongs. |
| * @return The generated PcapEvent. |
| */ |
| public static @Nullable PcapEvent createEvent(PcapPacket pcapPacket, PcapFile pcap, PcapTrace trace) { |
| long rank = pcapPacket.getIndex(); |
| long timestamp = pcapPacket.getTimestamp(); |
| PcapTimestampScale scale = pcapPacket.getTimestampScale(); |
| ITmfTimestamp tmfTimestamp; |
| switch (scale) { |
| case MICROSECOND: |
| long us = trace.getTimestampTransform().transform(timestamp * 1000) / 1000; |
| tmfTimestamp = TmfTimestamp.fromMicros(us); |
| break; |
| case NANOSECOND: |
| long ns = trace.getTimestampTransform().transform(timestamp); |
| tmfTimestamp = TmfTimestamp.fromNanos(ns); |
| break; |
| default: |
| throw new IllegalArgumentException("The timestamp precision is not valid!"); //$NON-NLS-1$ |
| } |
| Path filePath = pcap.getPath().getFileName(); |
| @NonNull String fileName = (filePath == null ? EMPTY_STRING : checkNotNull(filePath.toString())); |
| |
| String dataLink = Messages.PcapEventFactory_LinkType + ':' + LinkTypeHelper.toString((int) pcapPacket.getDataLinkType()); |
| |
| ITmfEventField[] fields = generatePacketFields(pcapPacket); |
| ITmfEventField field = new PcapRootEventField(fields, pcapPacket); |
| Packet packet = pcapPacket.getMostEcapsulatedPacket(); |
| if (!fEventTypes.containsKey(packet.getProtocol())) { |
| String typeIdString = PcapEventType.DEFAULT_PCAP_TYPE_ID + ':' + packet.getProtocol().getShortName(); |
| fEventTypes.put(packet.getProtocol(), new PcapEventType(typeIdString, null)); |
| } |
| TmfEventType eventType = fEventTypes.get(packet.getProtocol()); |
| if (eventType == null) { |
| eventType = new TmfEventType(); |
| } |
| return new PcapEvent(trace, rank, tmfTimestamp, dataLink, eventType, field, fileName, packet); |
| |
| } |
| |
| private static ITmfEventField[] generatePacketFields(Packet packet) { |
| // TODO This is SOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOO slow. Must find a |
| // way to use less intermediate data structures. |
| List<ITmfEventField> fieldList = new ArrayList<>(); |
| List<ITmfEventField> subfieldList = new ArrayList<>(); |
| Packet localPacket = packet.getPacket(PcapProtocol.PCAP); |
| |
| while (localPacket != null) { |
| subfieldList.clear(); |
| for (Map.Entry<String, String> entry : localPacket.getFields().entrySet()) { |
| String key = entry.getKey(); |
| String value = entry.getValue(); |
| subfieldList.add(new TmfEventField(key, value, null)); |
| } |
| ITmfEventField[] subfieldArray = subfieldList.toArray(new ITmfEventField[subfieldList.size()]); |
| fieldList.add(new PcapEventField(localPacket.getProtocol().getName(), EMPTY_STRING, subfieldArray, localPacket)); |
| localPacket = localPacket.getChildPacket(); |
| } |
| |
| return fieldList.toArray(new ITmfEventField[fieldList.size()]); |
| } |
| } |