package net.tomp2p.peers;
/**
* Class responsible for measuring and storing a Round Trip Time (RTT)
* This is used to compare peers with similar distance when routing.
*
* @author Sebastian Stephan
*/
public class RTT {
private long startMeasurementTimestamp = -1;
private long rtt = -1;
private boolean isUDP = true;
private boolean isEstimated = false;
// How much longer is TCP RTT compared to UDP
// Since TCP connections use 3-way handshake and an
// ACK to confirm, we assume a total of 4 transmissions
// for TCP, which is factor 2 longer than an UDP exchange
// TODO: Confirm with Wireshark
private static final double TCP_SCALE_DOWN_FACTOR = 3.5;
// Constructors
public RTT() {
}
/**
* Create RTT object with some given RTT, and a flag
* if the time was measured on a UDP exchange.
*
* @param rtt The rtt to be set in milliseconds
* @param isUDP True if this was an UDP exchange, set false
* if it was a TCP exchange.
*/
public RTT(long rtt, boolean isUDP) {
this.rtt = rtt;
this.startMeasurementTimestamp = System.currentTimeMillis();
this.isUDP = isUDP;
}
/**
* Begin counting the time. Can be called multiple times,
* as long as it has not yet been stopped
*
* @return True if time measurement has been started, False otherwise
*/
public boolean beginTimeMeasurement(boolean isUDP) {
if (getRtt() == -1) {
synchronized (this) {
this.startMeasurementTimestamp = System.currentTimeMillis();
this.isUDP = isUDP;
return true;
}
}
return false;
}
/**
* Stop the time measurement and calculate the rtt
* BeginTimeMeasurement must have been called before
* Can only be called once
*
* @return True if RTT was set, False otherwise
*/
public boolean stopTimeMeasurement() {
synchronized (this) {
if (getRtt() == -1 && getStartMeasurementTimestamp() > 0) {
rtt = System.currentTimeMillis() - getStartMeasurementTimestamp();
return true;
}
}
return false;
}
public long getStartMeasurementTimestamp() {
return startMeasurementTimestamp;
}
/**
* Get round-trip-time in milliseconds. If the RTT was calculated
* by TCP, the value will be scaled down by TCP_SCALE_DOWN_FACTOR
*
* @return round-trip-time in milliseconds, -1 if no measurement done.
*/
public long getRtt() {
if (isUDP)
return rtt;
else
return (int)(rtt / TCP_SCALE_DOWN_FACTOR);
}
public boolean isUDP() {
return isUDP;
}
/**
* Returns if the RTT measured is an estimate for some other peer
*
* @return True if it is an estimate, false otherwise
*/
public boolean isEstimated() {
return isEstimated;
}
/**
* Marks this RTT object as an estimate
*
* @return The RTT object
*/
public RTT setEstimated() {
isEstimated = true;
return this;
}
@Override
public String toString() {
StringBuilder sb = new StringBuilder();
if (isUDP)
sb.append("(UDP ");
else
sb.append(("TCP "));
sb.append(getRtt());
sb.append(")");
return sb.toString();
}
}