| /******************************************************************************* |
| * Copyright (c) 2014 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.pcap.core.stream; |
| |
| import org.eclipse.tracecompass.internal.pcap.core.endpoint.ProtocolEndpointPair; |
| 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 com.google.common.math.DoubleMath; |
| |
| // TODO decide if default modifier a good idea. This allows only the |
| // stream builder to call that method (and any class that is added to this |
| // package). This effectively makes the stream read-only. |
| |
| /** |
| * Class that represents a packet stream, which is a collection of packets that |
| * share the same endpoints. The endpoints of a packet are protocol-dependent. |
| * For example, a TCP stream is a collection of packets that share the same MAC |
| * address, IP address, and Port couple. |
| * |
| * @author Vincent Perot |
| */ |
| public class PacketStream { |
| |
| private static final double SECOND_TO_NANOSECOND = 1000000000.0; |
| private static final double DELTA = 0.000000001; |
| private final PcapProtocol fProtocol; |
| private final int fId; |
| private final ProtocolEndpointPair fEndpointPair; |
| |
| private long fNbPacketsAtoB; |
| private long fNbPacketsBtoA; |
| private long fNbBytesAtoB; |
| private long fNbBytesBtoA; |
| private long fStartTime; |
| private long fEndTime; |
| |
| /** |
| * Constructor of a packet stream. |
| * |
| * @param protocol |
| * The protocol of the packets of the stream. This is needed |
| * because the definition of a stream is protocol-dependent. |
| * @param id |
| * The id of this stream. |
| * @param endpointPair |
| * The common endpoints of the packets in this stream. |
| */ |
| PacketStream(PcapProtocol protocol, int id, ProtocolEndpointPair endpointPair) { |
| fProtocol = protocol; |
| fId = id; |
| fEndpointPair = endpointPair; |
| fNbPacketsAtoB = 0; |
| fNbPacketsBtoA = 0; |
| fNbBytesAtoB = 0; |
| fNbBytesBtoA = 0; |
| fStartTime = Long.MAX_VALUE; |
| fEndTime = Long.MIN_VALUE; |
| } |
| |
| /** |
| * Add a packet to the stream. |
| * |
| * @param packet |
| * The packet that must be added. |
| */ |
| synchronized void add(PcapPacket packet) { |
| |
| Packet newPacket = packet.getPacket(fProtocol); |
| if (newPacket == null) { |
| return; |
| } |
| |
| // Update packet and byte number |
| if (fEndpointPair.getFirstEndpoint().equals(newPacket.getSourceEndpoint()) && |
| fEndpointPair.getSecondEndpoint().equals(newPacket.getDestinationEndpoint())) { |
| fNbPacketsAtoB++; |
| fNbBytesAtoB += packet.getOriginalLength(); |
| } else if (fEndpointPair.getFirstEndpoint().equals(newPacket.getDestinationEndpoint()) && |
| fEndpointPair.getSecondEndpoint().equals(newPacket.getSourceEndpoint())) { |
| fNbPacketsBtoA++; |
| fNbBytesBtoA += packet.getOriginalLength(); |
| } else { |
| throw new IllegalStateException(); |
| } |
| |
| // Update start and stop time |
| // Stream timestamp is ALWAYS in nanoseconds. |
| long timestamp; |
| switch (packet.getTimestampScale()) { |
| case MICROSECOND: |
| timestamp = packet.getTimestamp() * 1000; |
| break; |
| case NANOSECOND: |
| timestamp = packet.getTimestamp(); |
| break; |
| default: |
| throw new IllegalArgumentException("The timestamp precision is not valid!"); //$NON-NLS-1$ |
| } |
| fStartTime = Math.min(fStartTime, timestamp); |
| fEndTime = Math.max(fEndTime, timestamp); |
| } |
| |
| /** |
| * Get the Protocol of this stream. |
| * |
| * @return The protocol of this stream. |
| */ |
| public PcapProtocol getProtocol() { |
| return fProtocol; |
| } |
| |
| /** |
| * Method that returns the non-unique ID of this stream. |
| * |
| * @return the non-unique ID of this stream. |
| */ |
| public int getID() { |
| return fId; |
| } |
| |
| /** |
| * Method that returns the unique ID of this stream. |
| * |
| * @return the unique ID of this stream. |
| */ |
| public String getUniqueID() { |
| return fProtocol.getShortName() + '.' + fId; |
| } |
| |
| /** |
| * Method that returns the endpoint pair of the stream. |
| * |
| * @return The endpoint pair of the stream. |
| */ |
| public ProtocolEndpointPair getEndpointPair() { |
| return fEndpointPair; |
| } |
| |
| // TODO return also the endpoint set. |
| @Override |
| public synchronized String toString() { |
| StringBuilder sb = new StringBuilder(); |
| sb.append("Stream " + getUniqueID() + ", Number of Packets: " + getNbPackets() + "\n"); //$NON-NLS-1$//$NON-NLS-2$//$NON-NLS-3$ |
| |
| return sb.toString(); |
| |
| } |
| |
| /** |
| * Get the number of packets going from the first endpoint to the second. |
| * |
| * @return The number of packets from A to B. |
| */ |
| public synchronized long getNbPacketsAtoB() { |
| return fNbPacketsAtoB; |
| } |
| |
| /** |
| * Get the number of packets going from the second endpoint to the first. |
| * |
| * @return The number of packets from B to A. |
| */ |
| public synchronized long getNbPacketsBtoA() { |
| return fNbPacketsBtoA; |
| } |
| |
| /** |
| * Get the total number of packets in this stream. |
| * |
| * @return The total number of packets. |
| */ |
| public synchronized long getNbPackets() { |
| return fNbPacketsAtoB + fNbPacketsBtoA; |
| } |
| |
| /** |
| * Get the number of bytes going from the first endpoint to the second. |
| * |
| * @return The number of bytes from A to B. |
| */ |
| public synchronized long getNbBytesAtoB() { |
| return fNbBytesAtoB; |
| } |
| |
| /** |
| * Get the number of bytes going from the second endpoint to the first. |
| * |
| * @return The number of bytes from B to A. |
| */ |
| public synchronized long getNbBytesBtoA() { |
| return fNbBytesBtoA; |
| } |
| |
| /** |
| * Get the total number of bytes in this stream. |
| * |
| * @return The total number of bytes. |
| */ |
| public synchronized long getNbBytes() { |
| return fNbBytesAtoB + fNbBytesBtoA; |
| } |
| |
| /** |
| * Get the start time of this stream, in nanoseconds relative to epoch. |
| * |
| * @return The start time. |
| */ |
| public synchronized long getStartTime() { |
| return fStartTime; |
| } |
| |
| /** |
| * Get the stop time of this stream, in nanoseconds relative to epoch. |
| * |
| * @return The stop time. |
| */ |
| public synchronized long getStopTime() { |
| return fEndTime; |
| } |
| |
| /** |
| * Get the duration of this stream, in seconds |
| * |
| * @return The duration of this stream. |
| */ |
| public synchronized double getDuration() { |
| return (fEndTime - fStartTime) / SECOND_TO_NANOSECOND; |
| } |
| |
| /** |
| * Get the the average byte per second from A to B. |
| * |
| * @return the average byte per second from A to B. |
| */ |
| public synchronized double getBPSAtoB() { |
| if (DoubleMath.fuzzyEquals(getDuration(), 0, DELTA)) { |
| return 0; |
| } |
| return fNbBytesAtoB / getDuration(); |
| } |
| |
| /** |
| * Get the the average byte per second from B to A. |
| * |
| * @return the average byte per second from B to A. |
| */ |
| public synchronized double getBPSBtoA() { |
| if (DoubleMath.fuzzyEquals(getDuration(), 0, DELTA)) { |
| return 0; |
| } |
| return fNbBytesBtoA / getDuration(); |
| } |
| |
| } |