diff --git a/router/java/src/net/i2p/router/transport/udp/ACKSender.java b/router/java/src/net/i2p/router/transport/udp/ACKSender.java index 60976d285b199c4551c5f01422e9be6decbf8161..6f01a3f6251c03c4851944edec45673c61936d5c 100644 --- a/router/java/src/net/i2p/router/transport/udp/ACKSender.java +++ b/router/java/src/net/i2p/router/transport/udp/ACKSender.java @@ -62,7 +62,7 @@ class ACKSender implements Runnable { public synchronized void shutdown() { _alive = false; - PeerState poison = new PeerState(_context, _transport, new byte[4], 0, null, false); + PeerState poison = new PeerState(_context, _transport, new byte[4], 0, null, false, 0); poison.setTheyRelayToUsAs(POISON_PS); _peersToACK.offer(poison); for (int i = 1; i <= 5 && !_peersToACK.isEmpty(); i++) { 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 d0b999604f2be9d444f52d5f29018454af53abb9..94be6ca25ed8e0c54affd3cbc2b23ae2da862a43 100644 --- a/router/java/src/net/i2p/router/transport/udp/EstablishmentManager.java +++ b/router/java/src/net/i2p/router/transport/udp/EstablishmentManager.java @@ -694,7 +694,7 @@ class EstablishmentManager { RouterIdentity remote = state.getConfirmedIdentity(); PeerState peer = new PeerState(_context, _transport, - state.getSentIP(), state.getSentPort(), remote.calculateHash(), true); + state.getSentIP(), state.getSentPort(), remote.calculateHash(), true, state.getRTT()); peer.setCurrentCipherKey(state.getCipherKey()); peer.setCurrentMACKey(state.getMACKey()); peer.setWeRelayToThemAs(state.getSentRelayTag()); @@ -813,7 +813,7 @@ class EstablishmentManager { _outboundByClaimedAddress.remove(claimed, state); _outboundByHash.remove(remote.calculateHash(), state); PeerState peer = new PeerState(_context, _transport, - state.getSentIP(), state.getSentPort(), remote.calculateHash(), false); + state.getSentIP(), state.getSentPort(), remote.calculateHash(), false, state.getRTT()); peer.setCurrentCipherKey(state.getCipherKey()); peer.setCurrentMACKey(state.getMACKey()); peer.setTheyRelayToUsAs(state.getReceivedRelayTag()); diff --git a/router/java/src/net/i2p/router/transport/udp/InboundEstablishState.java b/router/java/src/net/i2p/router/transport/udp/InboundEstablishState.java index 418876cc092bed9bf70df7f13ab3678562c941b6..7e64a9528052eaa708c68dda5fe8832576302c11 100644 --- a/router/java/src/net/i2p/router/transport/udp/InboundEstablishState.java +++ b/router/java/src/net/i2p/router/transport/udp/InboundEstablishState.java @@ -64,6 +64,8 @@ class InboundEstablishState { private int _createdSentCount; // default true private boolean _introductionRequested = true; + + private int _rtt; public enum InboundState { /** nothin known yet */ @@ -296,6 +298,8 @@ class InboundEstablishState { */ public synchronized long getNextSendTime() { return _nextSend; } + synchronized int getRTT() { return _rtt; } + /** RemoteHostId, uniquely identifies an attempt */ RemoteHostId getRemoteHostId() { return _remoteHostId; } @@ -356,6 +360,10 @@ class InboundEstablishState { _currentState = InboundState.IB_STATE_CONFIRMED_PARTIALLY; } + if (_createdSentCount == 1) { + _rtt = (int) ( _context.clock().now() - _lastSend ); + } + packetReceived(); } diff --git a/router/java/src/net/i2p/router/transport/udp/OutboundEstablishState.java b/router/java/src/net/i2p/router/transport/udp/OutboundEstablishState.java index dd8fb6ac8b161a120aad200642aa0e2e3d9addb9..bf9c284bd3a032acb6099494256573d333b0c994 100644 --- a/router/java/src/net/i2p/router/transport/udp/OutboundEstablishState.java +++ b/router/java/src/net/i2p/router/transport/udp/OutboundEstablishState.java @@ -74,6 +74,7 @@ class OutboundEstablishState { private long _confirmedSentTime; private long _requestSentTime; private long _introSentTime; + private int _rtt; public enum OutboundState { /** nothin sent yet */ @@ -179,6 +180,8 @@ class OutboundEstablishState { * @since 0.9.24 */ public boolean needIntroduction() { return _needIntroduction; } + + synchronized int getRTT() { return _rtt; } /** * Queue a message to be sent after the session is established. @@ -304,6 +307,10 @@ class OutboundEstablishState { _currentState == OutboundState.OB_STATE_INTRODUCED || _currentState == OutboundState.OB_STATE_PENDING_INTRO) _currentState = OutboundState.OB_STATE_CREATED_RECEIVED; + + if (_requestSentCount == 1) { + _rtt = (int) (_context.clock().now() - _requestSentTime); + } packetReceived(); } 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 aa08bd9459ad34f716b8b0d699074fd4af65eee1..8bedd2ff3838f5036fc129785851d2b7dc56f380 100644 --- a/router/java/src/net/i2p/router/transport/udp/PeerState.java +++ b/router/java/src/net/i2p/router/transport/udp/PeerState.java @@ -314,10 +314,10 @@ public class PeerState { */ public static final int MAX_MTU = Math.max(LARGE_MTU, MAX_IPV6_MTU); - private static final int MIN_RTO = 100 + ACKSender.ACK_FREQUENCY; - private static final int INIT_RTO = 3*1000; - public static final int INIT_RTT = INIT_RTO / 2; - private static final int MAX_RTO = 15*1000; + private static final int MIN_RTO = 1000; + private static final int INIT_RTO = 1000; + private static final int INIT_RTT = 0; + private static final int MAX_RTO = 60*1000; private static final int CLOCK_SKEW_FUDGE = (ACKSender.ACK_FREQUENCY * 2) / 3; /** @@ -336,8 +336,11 @@ public class PeerState { private static final long RESEND_ACK_TIMEOUT = 5*60*1000; + /** + * @param rtt from the EstablishState, or 0 if not available + */ public PeerState(RouterContext ctx, UDPTransport transport, - byte[] remoteIP, int remotePort, Hash remotePeer, boolean isInbound) { + byte[] remoteIP, int remotePort, Hash remotePeer, boolean isInbound, int rtt) { _context = ctx; _log = ctx.logManager().getLog(PeerState.class); _transport = transport; @@ -366,9 +369,14 @@ public class PeerState { } //_mtuLastChecked = -1; _lastACKSend = -1; + _rto = INIT_RTO; _rtt = INIT_RTT; - _rttDeviation = _rtt; + if (rtt > 0) + recalculateTimeouts(rtt); + else + _rttDeviation = _rtt; + _inboundMessages = new HashMap<Long, InboundMessageState>(8); _outboundMessages = new CachedIteratorCollection<OutboundMessageState>(); //_outboundQueue = new CoDelPriorityBlockingQueue(ctx, "UDP-PeerState", 32); @@ -1226,16 +1234,18 @@ public class PeerState { * Caller should synch on this */ private void recalculateTimeouts(long lifetime) { - // the rttDev calculation matches that recommended in RFC 2988 (beta = 1/4) - _rttDeviation = _rttDeviation + (int)(0.25d*(Math.abs(lifetime-_rtt)-_rttDeviation)); + if (_rtt <= 0) { + // first measurement + _rtt = (int) lifetime; + _rttDeviation = (int)(lifetime / 2); + } else { + // the rttDev calculation matches that recommended in RFC 2988 (beta = 1/4) + _rttDeviation = (int)( 0.75*_rttDeviation + 0.25*Math.abs(lifetime-_rtt) ); - float scale = RTT_DAMPENING; - // the faster we are going, the slower we want to reduce the rtt - //if (_sendBps > 0) - // scale = lifetime / ((float)lifetime + (float)_sendBps); - //if (scale < 0.001f) scale = 0.001f; + float scale = RTT_DAMPENING; - _rtt = (int)(_rtt*(1.0f-scale) + (scale)*lifetime); + _rtt = (int)(_rtt*(1.0f-scale) + (scale)*lifetime); + } // K = 4 _rto = Math.min(MAX_RTO, Math.max(minRTO(), _rtt + (_rttDeviation<<2))); //if (_log.shouldLog(Log.DEBUG)) @@ -1821,13 +1831,15 @@ public class PeerState { + " remaining" + " for message " + state.getMessageId() + ": " + state); - if (state.getPushCount() > 0) + int rto = getRTO(); + if (state.getPushCount() > 0) { _retransmitter = state; + rto = Math.min(MAX_RTO, rto << state.getPushCount()); // Section 5.5 RFC 6298 + } if (state.push()) _messagesSent++; - int rto = getRTO(); state.setNextSendTime(now + rto); //if (peer.getSendWindowBytesRemaining() > 0) 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 0681fd8a1fc9e5d62a3308dbc77cae10e0370842..0bc4de39b173e2ee907778107f4890aec1e6bde4 100644 --- a/router/java/src/net/i2p/router/transport/udp/UDPTransport.java +++ b/router/java/src/net/i2p/router/transport/udp/UDPTransport.java @@ -2723,7 +2723,7 @@ public class UDPTransport extends TransportImpl implements TimedWeightedPriority for (PeerState peer : _peersByIdent.values()) { if ((!includeEverybody) && now - peer.getLastReceiveTime() > 5*60*1000) continue; // skip old peers - if (peer.getRTT() > PeerState.INIT_RTT - 250) + if (peer.getRTT() > 1250) continue; // Big RTT makes for a poor calculation skews.addElement(Long.valueOf(peer.getClockSkew() / 1000)); }