blob: f18eb51ee07e74463d1af9b289a354313fb3b31c [file] [log] [blame]
/*******************************************************************************
* 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();
}
}