" />
diff --git a/apps/routerconsole/jsp/summary.jsp b/apps/routerconsole/jsp/summary.jsp
index 180b2a7b8..40bdc8269 100644
--- a/apps/routerconsole/jsp/summary.jsp
+++ b/apps/routerconsole/jsp/summary.jsp
@@ -39,7 +39,7 @@
Active: /
Fast:
High capacity:
- Well integrated:
+
Failing:
Known:
<%
diff --git a/history.txt b/history.txt
index 28e11fa16..a4083a29a 100644
--- a/history.txt
+++ b/history.txt
@@ -1,4 +1,8 @@
-$Id: history.txt,v 1.475 2006/05/15 12:33:02 jrandom Exp $
+$Id: history.txt,v 1.476 2006-05-16 13:34:28 jrandom Exp $
+
+2006-05-17 jrandom
+ * Make the peer page sortable
+ * SSU modifications to cut down on unnecessary connection failures
2006-05-16 jrandom
* Further shitlist randomizations
diff --git a/router/java/src/net/i2p/router/CommSystemFacade.java b/router/java/src/net/i2p/router/CommSystemFacade.java
index c34592fb7..4dc43c43d 100644
--- a/router/java/src/net/i2p/router/CommSystemFacade.java
+++ b/router/java/src/net/i2p/router/CommSystemFacade.java
@@ -23,7 +23,8 @@ import java.util.Set;
public abstract class CommSystemFacade implements Service {
public abstract void processMessage(OutNetMessage msg);
- public void renderStatusHTML(Writer out) throws IOException { }
+ public void renderStatusHTML(Writer out, String urlBase, int sortFlags) throws IOException { }
+ public void renderStatusHTML(Writer out) throws IOException { renderStatusHTML(out, null, 0); }
/** Create the set of RouterAddress structures based on the router's config */
public Set createAddresses() { return new HashSet(); }
diff --git a/router/java/src/net/i2p/router/RouterVersion.java b/router/java/src/net/i2p/router/RouterVersion.java
index 40d45bc39..fb1012a05 100644
--- a/router/java/src/net/i2p/router/RouterVersion.java
+++ b/router/java/src/net/i2p/router/RouterVersion.java
@@ -15,9 +15,9 @@ import net.i2p.CoreVersion;
*
*/
public class RouterVersion {
- public final static String ID = "$Revision: 1.415 $ $Date: 2006/05/15 12:33:05 $";
+ public final static String ID = "$Revision: 1.416 $ $Date: 2006-05-16 13:34:08 $";
public final static String VERSION = "0.6.1.18";
- public final static long BUILD = 4;
+ public final static long BUILD = 5;
public static void main(String args[]) {
System.out.println("I2P Router version: " + VERSION + "-" + BUILD);
System.out.println("Router ID: " + RouterVersion.ID);
diff --git a/router/java/src/net/i2p/router/transport/CommSystemFacadeImpl.java b/router/java/src/net/i2p/router/transport/CommSystemFacadeImpl.java
index 85392b521..ef9f5cac0 100644
--- a/router/java/src/net/i2p/router/transport/CommSystemFacadeImpl.java
+++ b/router/java/src/net/i2p/router/transport/CommSystemFacadeImpl.java
@@ -83,8 +83,8 @@ public class CommSystemFacadeImpl extends CommSystemFacade {
}
public void recheckReachability() { _manager.recheckReachability(); }
- public void renderStatusHTML(Writer out) throws IOException {
- _manager.renderStatusHTML(out);
+ public void renderStatusHTML(Writer out, String urlBase, int sortFlags) throws IOException {
+ _manager.renderStatusHTML(out, urlBase, sortFlags);
}
public Set createAddresses() {
diff --git a/router/java/src/net/i2p/router/transport/Transport.java b/router/java/src/net/i2p/router/transport/Transport.java
index f37cef00e..fe6dee437 100644
--- a/router/java/src/net/i2p/router/transport/Transport.java
+++ b/router/java/src/net/i2p/router/transport/Transport.java
@@ -41,7 +41,7 @@ public interface Transport {
public int countActiveSendPeers();
public List getMostRecentErrorMessages();
- public void renderStatusHTML(Writer out) throws IOException;
+ public void renderStatusHTML(Writer out, String urlBase, int sortFlags) throws IOException;
public short getReachabilityStatus();
public void recheckReachability();
}
diff --git a/router/java/src/net/i2p/router/transport/TransportImpl.java b/router/java/src/net/i2p/router/transport/TransportImpl.java
index bff923d78..d5c61499a 100644
--- a/router/java/src/net/i2p/router/transport/TransportImpl.java
+++ b/router/java/src/net/i2p/router/transport/TransportImpl.java
@@ -363,6 +363,7 @@ public abstract class TransportImpl implements Transport {
public void setListener(TransportEventListener listener) { _listener = listener; }
/** Make this stuff pretty (only used in the old console) */
public void renderStatusHTML(Writer out) throws IOException {}
+ public void renderStatusHTML(Writer out, String urlBase, int sortFlags) throws IOException { renderStatusHTML(out); }
public RouterContext getContext() { return _context; }
public short getReachabilityStatus() { return CommSystemFacade.STATUS_UNKNOWN; }
diff --git a/router/java/src/net/i2p/router/transport/TransportManager.java b/router/java/src/net/i2p/router/transport/TransportManager.java
index 8bf59fca2..13cfa8593 100644
--- a/router/java/src/net/i2p/router/transport/TransportManager.java
+++ b/router/java/src/net/i2p/router/transport/TransportManager.java
@@ -244,7 +244,7 @@ public class TransportManager implements TransportEventListener {
return rv;
}
- public void renderStatusHTML(Writer out) throws IOException {
+ public void renderStatusHTML(Writer out, String urlBase, int sortFlags) throws IOException {
TreeMap transports = new TreeMap();
for (int i = 0; i < _transports.size(); i++) {
Transport t = (Transport)_transports.get(i);
@@ -252,7 +252,7 @@ public class TransportManager implements TransportEventListener {
}
for (Iterator iter = transports.values().iterator(); iter.hasNext(); ) {
Transport t= (Transport)iter.next();
- t.renderStatusHTML(out);
+ t.renderStatusHTML(out, urlBase, sortFlags);
}
StringBuffer buf = new StringBuffer(4*1024);
buf.append("Listening on:
\n");
diff --git a/router/java/src/net/i2p/router/transport/udp/EstablishmentManager.java b/router/java/src/net/i2p/router/transport/udp/EstablishmentManager.java
index 1adaaad45..92f82b8ab 100644
--- a/router/java/src/net/i2p/router/transport/udp/EstablishmentManager.java
+++ b/router/java/src/net/i2p/router/transport/udp/EstablishmentManager.java
@@ -943,7 +943,7 @@ public class EstablishmentManager {
Hash peer = outboundState.getRemoteIdentity().calculateHash();
_context.shitlist().shitlistRouter(peer, err);
- _transport.dropPeer(peer);
+ _transport.dropPeer(peer, false, err);
//_context.profileManager().commErrorOccurred(peer);
} else {
while (true) {
diff --git a/router/java/src/net/i2p/router/transport/udp/PeerState.java b/router/java/src/net/i2p/router/transport/udp/PeerState.java
index 13e24c704..f5e2c6482 100644
--- a/router/java/src/net/i2p/router/transport/udp/PeerState.java
+++ b/router/java/src/net/i2p/router/transport/udp/PeerState.java
@@ -447,13 +447,13 @@ public class PeerState {
if (_concurrentMessagesActive < 0)
_concurrentMessagesActive = 0;
- long now = _context.clock().now()/(10*1000);
- if (_lastFailedSendPeriod >= now) {
- // ignore... too fast
- } else {
- _lastFailedSendPeriod = now;
+ //long now = _context.clock().now()/(10*1000);
+ //if (_lastFailedSendPeriod >= now) {
+ // // ignore... too fast
+ //} else {
+ // _lastFailedSendPeriod = now;
_consecutiveFailedSends++;
- }
+ //}
return _consecutiveFailedSends;
}
public long getInactivityTime() {
@@ -1561,6 +1561,7 @@ public class PeerState {
buf.append(" lifetime: ").append(now-_keyEstablishedTime);
buf.append(" cwin: ").append(_sendWindowBytes);
buf.append(" acwin: ").append(_sendWindowBytesRemaining);
+ buf.append(" consecFail: ").append(_consecutiveFailedSends);
buf.append(" recv OK/Dup: ").append(_packetsReceived).append('/').append(_packetsReceivedDuplicate);
buf.append(" send OK/Dup: ").append(_packetsTransmitted).append('/').append(_packetsRetransmitted);
return buf.toString();
diff --git a/router/java/src/net/i2p/router/transport/udp/UDPTransport.java b/router/java/src/net/i2p/router/transport/udp/UDPTransport.java
index 2e83f608a..c91119972 100644
--- a/router/java/src/net/i2p/router/transport/udp/UDPTransport.java
+++ b/router/java/src/net/i2p/router/transport/udp/UDPTransport.java
@@ -163,6 +163,7 @@ public class UDPTransport extends TransportImpl implements TimedWeightedPriority
_context.statManager().createRateStat("udp.addressUpdated", "How many times we adjust our own reachable IP address", "udp", new long[] { 1*60*1000, 20*60*1000, 60*60*1000, 24*60*60*1000 });
_context.statManager().createRateStat("udp.proactiveReestablish", "How long a session was idle for when we proactively reestablished it", "udp", new long[] { 1*60*1000, 20*60*1000, 60*60*1000, 24*60*60*1000 });
_context.statManager().createRateStat("udp.dropPeerDroplist", "How many peers currently have their packets dropped outright when a new peer is added to the list?", "udp", new long[] { 1*60*1000, 20*60*1000 });
+ _context.statManager().createRateStat("udp.dropPeerConsecutiveFailures", "How many consecutive failed sends to a peer did we attempt before giving up and reestablishing a new session (lifetime is inactivity perood)", "udp", new long[] { 1*60*1000, 10*60*1000 });
__instance = this;
}
@@ -601,7 +602,7 @@ public class UDPTransport extends TransportImpl implements TimedWeightedPriority
}
}
_context.shitlist().shitlistRouter(peerHash, "Part of the wrong network");
- dropPeer(peerHash);
+ dropPeer(peerHash, false, "wrong network");
if (_log.shouldLog(Log.WARN))
_log.warn("Dropping the peer " + peerHash.toBase64() + " because they are in the wrong net");
return;
@@ -636,22 +637,28 @@ public class UDPTransport extends TransportImpl implements TimedWeightedPriority
public boolean isInDropList(RemoteHostId peer) { synchronized (_dropList) { return _dropList.contains(peer); } }
- void dropPeer(Hash peer) {
+ void dropPeer(Hash peer, boolean shouldShitlist, String why) {
PeerState state = getPeerState(peer);
if (state != null)
- dropPeer(state, false);
+ dropPeer(state, shouldShitlist, why);
}
- private void dropPeer(PeerState peer, boolean shouldShitlist) {
+ private void dropPeer(PeerState peer, boolean shouldShitlist, String why) {
if (_log.shouldLog(Log.WARN)) {
long now = _context.clock().now();
StringBuffer buf = new StringBuffer(4096);
long timeSinceSend = now - peer.getLastSendTime();
long timeSinceRecv = now - peer.getLastReceiveTime();
long timeSinceAck = now - peer.getLastACKSend();
+ long timeSinceSendOK = now - peer.getLastSendFullyTime();
+ int consec = peer.getConsecutiveFailedSends();
buf.append("Dropping remote peer: ").append(peer.toString()).append(" shitlist? ").append(shouldShitlist);
buf.append(" lifetime: ").append(now - peer.getKeyEstablishedTime());
- buf.append(" time since send/recv/ack: ").append(timeSinceSend).append(" / ");
+ buf.append(" time since send/fully/recv/ack: ").append(timeSinceSend).append(" / ");
+ buf.append(timeSinceSendOK).append(" / ");
buf.append(timeSinceRecv).append(" / ").append(timeSinceAck);
+ buf.append(" consec failures: ").append(consec);
+ if (why != null)
+ buf.append(" cause: ").append(why);
/*
buf.append("Existing peers: \n");
synchronized (_peersByIdent) {
@@ -694,14 +701,10 @@ public class UDPTransport extends TransportImpl implements TimedWeightedPriority
if (peer.getRemotePeer() != null) {
dropPeerCapacities(peer);
- if (shouldShitlist) {
- long now = _context.clock().now();
- _context.statManager().addRateData("udp.droppedPeer", now - peer.getLastReceiveTime(), now - peer.getKeyEstablishedTime());
+ if (shouldShitlist)
_context.shitlist().shitlistRouter(peer.getRemotePeer(), "dropped after too many retries");
- } else {
- long now = _context.clock().now();
- _context.statManager().addRateData("udp.droppedPeerInactive", now - peer.getLastReceiveTime(), now - peer.getKeyEstablishedTime());
- }
+ long now = _context.clock().now();
+ _context.statManager().addRateData("udp.droppedPeer", now - peer.getLastReceiveTime(), now - peer.getKeyEstablishedTime());
synchronized (_peersByIdent) {
altByIdent = (PeerState)_peersByIdent.remove(peer.getRemotePeer());
}
@@ -725,8 +728,8 @@ public class UDPTransport extends TransportImpl implements TimedWeightedPriority
rebuildExternalAddress();
// deal with races to make sure we drop the peers fully
- if ( (altByIdent != null) && (peer != altByIdent) ) dropPeer(altByIdent, shouldShitlist);
- if ( (altByHost != null) && (peer != altByHost) ) dropPeer(altByHost, shouldShitlist);
+ if ( (altByIdent != null) && (peer != altByIdent) ) dropPeer(altByIdent, shouldShitlist, "recurse");
+ if ( (altByHost != null) && (peer != altByHost) ) dropPeer(altByHost, shouldShitlist, "recurse");
}
private boolean needsRebuild() {
@@ -842,7 +845,7 @@ public class UDPTransport extends TransportImpl implements TimedWeightedPriority
return (pref != null) && "true".equals(pref);
}
- private static final int MAX_IDLE_TIME = 60*1000;
+ private static final int MAX_IDLE_TIME = 5*60*1000;
public String getStyle() { return STYLE; }
public void send(OutNetMessage msg) {
@@ -866,7 +869,7 @@ public class UDPTransport extends TransportImpl implements TimedWeightedPriority
(peer.getConsecutiveFailedSends() > 0) &&
(inboundActive <= 0)) {
// peer is waaaay idle, drop the con and queue it up as a new con
- dropPeer(peer, false);
+ dropPeer(peer, false, "proactive reconnection");
msg.timestamp("peer is really idle, dropping con and reestablishing");
if (_log.shouldLog(Log.DEBUG))
_log.debug("Proactive reestablish to " + to.toBase64());
@@ -1085,10 +1088,16 @@ public class UDPTransport extends TransportImpl implements TimedWeightedPriority
_log.warn("Consecutive failure #" + consecutive
+ " on " + msg.toString()
+ " to " + msg.getPeer());
- if ( (consecutive > MAX_CONSECUTIVE_FAILED) && (msg.getPeer().getInactivityTime() > DROP_INACTIVITY_TIME))
- dropPeer(msg.getPeer(), false);
- else if (consecutive > 2 * MAX_CONSECUTIVE_FAILED) // they're sending us data, but we cant reply?
- dropPeer(msg.getPeer(), false);
+ if ( (_context.clock().now() - msg.getPeer().getLastSendFullyTime() <= 60*1000) || (consecutive < MAX_CONSECUTIVE_FAILED) ) {
+ // ok, a few conseutive failures, but we /are/ getting through to them
+ } else {
+ _context.statManager().addRateData("udp.dropPeerConsecutiveFailures", consecutive, msg.getPeer().getInactivityTime());
+ dropPeer(msg.getPeer(), false, "too many failures");
+ }
+ //if ( (consecutive > MAX_CONSECUTIVE_FAILED) && (msg.getPeer().getInactivityTime() > DROP_INACTIVITY_TIME))
+ // dropPeer(msg.getPeer(), false);
+ //else if (consecutive > 2 * MAX_CONSECUTIVE_FAILED) // they're sending us data, but we cant reply?
+ // dropPeer(msg.getPeer(), false);
}
noteSend(msg, false);
if (m != null)
@@ -1181,21 +1190,6 @@ public class UDPTransport extends TransportImpl implements TimedWeightedPriority
return active;
}
- private static class AlphaComparator implements Comparator {
- private static final AlphaComparator _instance = new AlphaComparator();
- public static final AlphaComparator instance() { return _instance; }
-
- public int compare(Object lhs, Object rhs) {
- if ( (lhs == null) || (rhs == null) || !(lhs instanceof PeerState) || !(rhs instanceof PeerState))
- throw new IllegalArgumentException("rhs = " + rhs + " lhs = " + lhs);
- PeerState l = (PeerState)lhs;
- PeerState r = (PeerState)rhs;
- // base64 retains binary ordering
- return DataHelper.compareTo(l.getRemotePeer().getData(), r.getRemotePeer().getData());
- }
-
- }
-
private static UDPTransport __instance;
/** **internal, do not use** */
public static final UDPTransport _instance() { return __instance; }
@@ -1216,8 +1210,302 @@ public class UDPTransport extends TransportImpl implements TimedWeightedPriority
return peers;
}
- public void renderStatusHTML(Writer out) throws IOException {
- TreeSet peers = new TreeSet(AlphaComparator.instance());
+ private static final int FLAG_ALPHA = 0;
+ private static final int FLAG_IDLE_IN = 1;
+ private static final int FLAG_IDLE_OUT = 2;
+ private static final int FLAG_RATE_IN = 3;
+ private static final int FLAG_RATE_OUT = 4;
+ private static final int FLAG_SKEW = 5;
+ private static final int FLAG_CWND= 6;
+ private static final int FLAG_SSTHRESH = 7;
+ private static final int FLAG_RTT = 8;
+ private static final int FLAG_DEV = 9;
+ private static final int FLAG_RTO = 10;
+ private static final int FLAG_MTU = 11;
+ private static final int FLAG_SEND = 12;
+ private static final int FLAG_RECV = 13;
+ private static final int FLAG_RESEND = 14;
+ private static final int FLAG_DUP = 15;
+ private static final int FLAG_UPTIME = 16;
+
+ private Comparator getComparator(int sortFlags) {
+ Comparator rv = null;
+ switch (Math.abs(sortFlags)) {
+ case FLAG_IDLE_IN:
+ rv = IdleInComparator.instance();
+ break;
+ case FLAG_IDLE_OUT:
+ rv = IdleOutComparator.instance();
+ break;
+ case FLAG_RATE_IN:
+ rv = RateInComparator.instance();
+ break;
+ case FLAG_RATE_OUT:
+ rv = RateOutComparator.instance();
+ break;
+ case FLAG_UPTIME:
+ rv = UptimeComparator.instance();
+ break;
+ case FLAG_SKEW:
+ rv = SkewComparator.instance();
+ break;
+ case FLAG_CWND:
+ rv = CwndComparator.instance();
+ break;
+ case FLAG_SSTHRESH:
+ rv = SsthreshComparator.instance();
+ break;
+ case FLAG_RTT:
+ rv = RTTComparator.instance();
+ break;
+ case FLAG_DEV:
+ rv = DevComparator.instance();
+ break;
+ case FLAG_RTO:
+ rv = RTOComparator.instance();
+ break;
+ case FLAG_MTU:
+ rv = MTUComparator.instance();
+ break;
+ case FLAG_SEND:
+ rv = SendCountComparator.instance();
+ break;
+ case FLAG_RECV:
+ rv = RecvCountComparator.instance();
+ break;
+ case FLAG_RESEND:
+ rv = ResendComparator.instance();
+ break;
+ case FLAG_DUP:
+ rv = DupComparator.instance();
+ break;
+ case FLAG_ALPHA:
+ default:
+ rv = AlphaComparator.instance();
+ break;
+ }
+ if (sortFlags < 0)
+ rv = new InverseComparator(rv);
+ return rv;
+ }
+ private static class AlphaComparator extends PeerComparator {
+ private static final AlphaComparator _instance = new AlphaComparator();
+ public static final AlphaComparator instance() { return _instance; }
+ }
+ private static class IdleInComparator extends PeerComparator {
+ private static final IdleInComparator _instance = new IdleInComparator();
+ public static final IdleInComparator instance() { return _instance; }
+ protected int compare(PeerState l, PeerState r) {
+ long rv = l.getLastReceiveTime() - r.getLastReceiveTime();
+ if (rv == 0) // fallback on alpha
+ return super.compare(l, r);
+ else
+ return (int)rv;
+ }
+ }
+ private static class IdleOutComparator extends PeerComparator {
+ private static final IdleOutComparator _instance = new IdleOutComparator();
+ public static final IdleOutComparator instance() { return _instance; }
+ protected int compare(PeerState l, PeerState r) {
+ long rv = l.getLastSendTime() - r.getLastSendTime();
+ if (rv == 0) // fallback on alpha
+ return super.compare(l, r);
+ else
+ return (int)rv;
+ }
+ }
+ private static class RateInComparator extends PeerComparator {
+ private static final RateInComparator _instance = new RateInComparator();
+ public static final RateInComparator instance() { return _instance; }
+ protected int compare(PeerState l, PeerState r) {
+ long rv = l.getReceiveBps() - r.getReceiveBps();
+ if (rv == 0) // fallback on alpha
+ return super.compare(l, r);
+ else
+ return (int)rv;
+ }
+ }
+ private static class RateOutComparator extends PeerComparator {
+ private static final RateOutComparator _instance = new RateOutComparator();
+ public static final RateOutComparator instance() { return _instance; }
+ protected int compare(PeerState l, PeerState r) {
+ long rv = l.getSendBps() - r.getSendBps();
+ if (rv == 0) // fallback on alpha
+ return super.compare(l, r);
+ else
+ return (int)rv;
+ }
+ }
+ private static class UptimeComparator extends PeerComparator {
+ private static final UptimeComparator _instance = new UptimeComparator();
+ public static final UptimeComparator instance() { return _instance; }
+ protected int compare(PeerState l, PeerState r) {
+ long rv = l.getKeyEstablishedTime() - r.getKeyEstablishedTime();
+ if (rv == 0) // fallback on alpha
+ return super.compare(l, r);
+ else
+ return (int)rv;
+ }
+ }
+ private static class SkewComparator extends PeerComparator {
+ private static final SkewComparator _instance = new SkewComparator();
+ public static final SkewComparator instance() { return _instance; }
+ protected int compare(PeerState l, PeerState r) {
+ long rv = Math.abs(l.getClockSkew()) - Math.abs(r.getClockSkew());
+ if (rv == 0) // fallback on alpha
+ return super.compare(l, r);
+ else
+ return (int)rv;
+ }
+ }
+ private static class CwndComparator extends PeerComparator {
+ private static final CwndComparator _instance = new CwndComparator();
+ public static final CwndComparator instance() { return _instance; }
+ protected int compare(PeerState l, PeerState r) {
+ long rv = l.getSendWindowBytes() - r.getSendWindowBytes();
+ if (rv == 0) // fallback on alpha
+ return super.compare(l, r);
+ else
+ return (int)rv;
+ }
+ }
+ private static class SsthreshComparator extends PeerComparator {
+ private static final SsthreshComparator _instance = new SsthreshComparator();
+ public static final SsthreshComparator instance() { return _instance; }
+ protected int compare(PeerState l, PeerState r) {
+ long rv = l.getSlowStartThreshold() - r.getSlowStartThreshold();
+ if (rv == 0) // fallback on alpha
+ return super.compare(l, r);
+ else
+ return (int)rv;
+ }
+ }
+ private static class RTTComparator extends PeerComparator {
+ private static final RTTComparator _instance = new RTTComparator();
+ public static final RTTComparator instance() { return _instance; }
+ protected int compare(PeerState l, PeerState r) {
+ long rv = l.getRTT() - r.getRTT();
+ if (rv == 0) // fallback on alpha
+ return super.compare(l, r);
+ else
+ return (int)rv;
+ }
+ }
+ private static class DevComparator extends PeerComparator {
+ private static final DevComparator _instance = new DevComparator();
+ public static final DevComparator instance() { return _instance; }
+ protected int compare(PeerState l, PeerState r) {
+ long rv = l.getRTTDeviation() - r.getRTTDeviation();
+ if (rv == 0) // fallback on alpha
+ return super.compare(l, r);
+ else
+ return (int)rv;
+ }
+ }
+ private static class RTOComparator extends PeerComparator {
+ private static final RTOComparator _instance = new RTOComparator();
+ public static final RTOComparator instance() { return _instance; }
+ protected int compare(PeerState l, PeerState r) {
+ long rv = l.getRTO() - r.getRTO();
+ if (rv == 0) // fallback on alpha
+ return super.compare(l, r);
+ else
+ return (int)rv;
+ }
+ }
+ private static class MTUComparator extends PeerComparator {
+ private static final MTUComparator _instance = new MTUComparator();
+ public static final MTUComparator instance() { return _instance; }
+ protected int compare(PeerState l, PeerState r) {
+ long rv = l.getMTU() - r.getMTU();
+ if (rv == 0) // fallback on alpha
+ return super.compare(l, r);
+ else
+ return (int)rv;
+ }
+ }
+ private static class SendCountComparator extends PeerComparator {
+ private static final SendCountComparator _instance = new SendCountComparator();
+ public static final SendCountComparator instance() { return _instance; }
+ protected int compare(PeerState l, PeerState r) {
+ long rv = l.getPacketsTransmitted() - r.getPacketsTransmitted();
+ if (rv == 0) // fallback on alpha
+ return super.compare(l, r);
+ else
+ return (int)rv;
+ }
+ }
+ private static class RecvCountComparator extends PeerComparator {
+ private static final RecvCountComparator _instance = new RecvCountComparator();
+ public static final RecvCountComparator instance() { return _instance; }
+ protected int compare(PeerState l, PeerState r) {
+ long rv = l.getPacketsReceived() - r.getPacketsReceived();
+ if (rv == 0) // fallback on alpha
+ return super.compare(l, r);
+ else
+ return (int)rv;
+ }
+ }
+ private static class ResendComparator extends PeerComparator {
+ private static final ResendComparator _instance = new ResendComparator();
+ public static final ResendComparator instance() { return _instance; }
+ protected int compare(PeerState l, PeerState r) {
+ long rv = l.getPacketsRetransmitted() - r.getPacketsRetransmitted();
+ if (rv == 0) // fallback on alpha
+ return super.compare(l, r);
+ else
+ return (int)rv;
+ }
+ }
+ private static class DupComparator extends PeerComparator {
+ private static final DupComparator _instance = new DupComparator();
+ public static final DupComparator instance() { return _instance; }
+ protected int compare(PeerState l, PeerState r) {
+ long rv = l.getPacketsReceivedDuplicate() - r.getPacketsReceivedDuplicate();
+ if (rv == 0) // fallback on alpha
+ return super.compare(l, r);
+ else
+ return (int)rv;
+ }
+ }
+
+ private static class PeerComparator implements Comparator {
+ public int compare(Object lhs, Object rhs) {
+ if ( (lhs == null) || (rhs == null) || !(lhs instanceof PeerState) || !(rhs instanceof PeerState))
+ throw new IllegalArgumentException("rhs = " + rhs + " lhs = " + lhs);
+ return compare((PeerState)lhs, (PeerState)rhs);
+ }
+ protected int compare(PeerState l, PeerState r) {
+ // base64 retains binary ordering
+ return DataHelper.compareTo(l.getRemotePeer().getData(), r.getRemotePeer().getData());
+ }
+ }
+ private static class InverseComparator implements Comparator {
+ private Comparator _comp;
+ public InverseComparator(Comparator comp) { _comp = comp; }
+ public int compare(Object lhs, Object rhs) {
+ return -1 * _comp.compare(lhs, rhs);
+ }
+ }
+
+ private void appendSortLinks(StringBuffer buf, String urlBase, int sortFlags, String descr, int ascending) {
+ if (sortFlags == ascending) {
+ buf.append(" V^ ");
+ } else if (sortFlags == 0 - ascending) {
+ buf.append(" V^ ");
+ } else {
+ buf.append(" V^ ");
+ }
+ }
+
+ //public void renderStatusHTML(Writer out) throws IOException { renderStatusHTML(out, 0); }
+ public void renderStatusHTML(Writer out, int sortFlags) throws IOException {}
+ public void renderStatusHTML(Writer out, String urlBase, int sortFlags) throws IOException {
+ TreeSet peers = new TreeSet(getComparator(sortFlags));
synchronized (_peersByIdent) {
peers.addAll(_peersByIdent.values());
}
@@ -1238,13 +1526,50 @@ public class UDPTransport extends TransportImpl implements TimedWeightedPriority
StringBuffer buf = new StringBuffer(512);
buf.append("UDP connections: ").append(peers.size()).append("
\n");
buf.append("
\n");
- buf.append(" peer | idle | ");
- buf.append(" in/out | \n");
- buf.append(" up | skew | \n");
- buf.append(" cwnd | ssthresh | \n");
- buf.append(" rtt | dev | rto | \n");
- buf.append(" mtu | send | recv | \n");
- buf.append(" resent | dupRecv | \n");
+ buf.append("
peer");
+ if (sortFlags == FLAG_ALPHA)
+ buf.append(" V ");
+ else
+ buf.append(" V ");
+ buf.append(" | idle");
+ appendSortLinks(buf, urlBase, sortFlags, "Sort by idle inbound", FLAG_IDLE_IN);
+ buf.append("/");
+ appendSortLinks(buf, urlBase, sortFlags, "Sort by idle outbound", FLAG_IDLE_OUT);
+ buf.append(" | ");
+ buf.append(" in/out");
+ appendSortLinks(buf, urlBase, sortFlags, "Sort by inbound rate", FLAG_RATE_IN);
+ buf.append("/");
+ appendSortLinks(buf, urlBase, sortFlags, "Sort by outbound rate", FLAG_RATE_OUT);
+ buf.append(" | \n");
+ buf.append(" up");
+ appendSortLinks(buf, urlBase, sortFlags, "Sort by connection uptime", FLAG_UPTIME);
+ buf.append(" | skew");
+ appendSortLinks(buf, urlBase, sortFlags, "Sort by clock skew", FLAG_SKEW);
+ buf.append(" | \n");
+ buf.append(" cwnd");
+ appendSortLinks(buf, urlBase, sortFlags, "Sort by congestion window", FLAG_CWND);
+ buf.append(" | ssthresh");
+ appendSortLinks(buf, urlBase, sortFlags, "Sort by slow start threshold", FLAG_SSTHRESH);
+ buf.append(" | \n");
+ buf.append(" rtt");
+ appendSortLinks(buf, urlBase, sortFlags, "Sort by round trip time", FLAG_RTT);
+ buf.append(" | dev");
+ appendSortLinks(buf, urlBase, sortFlags, "Sort by round trip time deviation", FLAG_DEV);
+ buf.append(" | rto");
+ appendSortLinks(buf, urlBase, sortFlags, "Sort by retransmission timeout", FLAG_RTO);
+ buf.append(" | \n");
+ buf.append(" mtu");
+ appendSortLinks(buf, urlBase, sortFlags, "Sort by maximum transmit unit", FLAG_MTU);
+ buf.append(" | send");
+ appendSortLinks(buf, urlBase, sortFlags, "Sort by packets sent", FLAG_SEND);
+ buf.append(" | recv");
+ appendSortLinks(buf, urlBase, sortFlags, "Sort by packets received", FLAG_RECV);
+ buf.append(" | \n");
+ buf.append(" resent");
+ appendSortLinks(buf, urlBase, sortFlags, "Sort by packets retransmitted", FLAG_RESEND);
+ buf.append(" | dupRecv");
+ appendSortLinks(buf, urlBase, sortFlags, "Sort by packets received more than once", FLAG_DUP);
+ buf.append(" | \n");
buf.append("
\n");
out.write(buf.toString());
buf.setLength(0);
@@ -1513,7 +1838,7 @@ public class UDPTransport extends TransportImpl implements TimedWeightedPriority
public String toString() { return "UDP bid @ " + getLatencyMs(); }
}
- private static final int EXPIRE_TIMEOUT = 10*60*1000;
+ private static final int EXPIRE_TIMEOUT = 30*60*1000;
private class ExpirePeerEvent implements SimpleTimer.TimedEvent {
private List _expirePeers;
@@ -1539,7 +1864,7 @@ public class UDPTransport extends TransportImpl implements TimedWeightedPriority
}
}
for (int i = 0; i < _expireBuffer.size(); i++)
- dropPeer((PeerState)_expireBuffer.get(i), false);
+ dropPeer((PeerState)_expireBuffer.get(i), false, "idle too long");
_expireBuffer.clear();
if (_alive)