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 90bc7fe77..137f753ce 100644 --- a/router/java/src/net/i2p/router/transport/udp/InboundEstablishState.java +++ b/router/java/src/net/i2p/router/transport/udp/InboundEstablishState.java @@ -103,13 +103,16 @@ class InboundEstablishState { } /** basic delay before backoff - * Transmissions at 0, 3, 9 sec - * Previously: 1500 (0, 1.5, 4.5, 10.5) + * Transmissions at 0, 1, 3, 7 sec + * This should be a little shorter than for outbound. */ - protected static final long RETRANSMIT_DELAY = 3000; + protected static final long RETRANSMIT_DELAY = 1000; - /** max delay including backoff */ - protected static final long MAX_DELAY = 15*1000; + /** + * max delay including backoff + * This should be a little shorter than for outbound. + */ + protected static final long MAX_DELAY = 12*1000; /** * @param localPort Must be our external port, otherwise the signature of the diff --git a/router/java/src/net/i2p/router/transport/udp/InboundEstablishState2.java b/router/java/src/net/i2p/router/transport/udp/InboundEstablishState2.java index cfe3914aa..a2c3f0c0c 100644 --- a/router/java/src/net/i2p/router/transport/udp/InboundEstablishState2.java +++ b/router/java/src/net/i2p/router/transport/udp/InboundEstablishState2.java @@ -738,6 +738,8 @@ class InboundEstablishState2 extends InboundEstablishState implements SSU2Payloa public synchronized UDPPacket getRetransmitSessionCreatedPacket() { if (_sessCrForReTX == null) return null; + if (_log.shouldInfo()) + _log.info("ReTX Sess Created on " + this); UDPPacket packet = UDPPacket.acquire(_context, false); DatagramPacket pkt = packet.getPacket(); byte data[] = pkt.getData(); 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 dc8e890bf..e12b4ef29 100644 --- a/router/java/src/net/i2p/router/transport/udp/OutboundEstablishState.java +++ b/router/java/src/net/i2p/router/transport/udp/OutboundEstablishState.java @@ -117,12 +117,15 @@ class OutboundEstablishState { } /** basic delay before backoff - * Transmissions at 0, 3, 9 sec - * Previously: 1500 (0, 1.5, 4.5, 10.5) + * Transmissions at 0, 1.25, 3.75, 8.75 sec + * This should be a little longer than for inbound. */ - protected static final long RETRANSMIT_DELAY = 3000; + protected static final long RETRANSMIT_DELAY = 1250; - /** max delay including backoff */ + /** + * max delay including backoff + * This should be a little longer than for inbound. + */ private static final long MAX_DELAY = 15*1000; private static final long WAIT_FOR_HOLE_PUNCH_DELAY = 500; 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 3cf66cbf8..c6c4caf79 100644 --- a/router/java/src/net/i2p/router/transport/udp/PeerState.java +++ b/router/java/src/net/i2p/router/transport/udp/PeerState.java @@ -1729,8 +1729,8 @@ public class PeerState { // // ignore result, always send? // locked_shouldSend(dequeuedState); //} - if (_log.shouldLog(Log.DEBUG)) - _log.debug("Allocate sending (NEW) to " + _remotePeer + ": " + dequeuedState.getMessageId()); + //if (_log.shouldLog(Log.DEBUG)) + // _log.debug("Allocate sending (NEW) to " + _remotePeer + ": " + dequeuedState.getMessageId()); if (rv == null) rv = new ArrayList(_concurrentMessagesAllowed); rv.add(dequeuedState); @@ -1813,12 +1813,14 @@ public class PeerState { private boolean locked_shouldSend(OutboundMessageState state, long now) { synchronized(this) { if (allocateSendingBytes(state, now)) { + /*** if (_log.shouldLog(Log.DEBUG)) _log.debug(_remotePeer + " Allocation allowed with " + getSendWindowBytesRemaining() + "/" + getSendWindowBytes() + " remaining" + " for message " + state.getMessageId() + ": " + state); + ***/ if (state.getPushCount() == 0) _messagesSent++; return true; diff --git a/router/java/src/net/i2p/router/transport/udp/PeerState2.java b/router/java/src/net/i2p/router/transport/udp/PeerState2.java index 530504695..75431ad78 100644 --- a/router/java/src/net/i2p/router/transport/udp/PeerState2.java +++ b/router/java/src/net/i2p/router/transport/udp/PeerState2.java @@ -81,8 +81,7 @@ public class PeerState2 extends PeerState implements SSU2Payload.PayloadCallback public static final int DEFAULT_MTU = MAX_MTU; private static final int BITFIELD_SIZE = 512; - private static final int MAX_SESS_CONF_RETX = 4; - private static final int SESS_CONF_RETX_TIME = 1000; + private static final int MAX_SESS_CONF_RETX = 5; private static final long SENT_MESSAGES_CLEAN_TIME = 60*1000; @@ -213,38 +212,51 @@ public class PeerState2 extends PeerState implements SSU2Payload.PayloadCallback @Override List allocateSend(long now) { if (!_isInbound && _ackedMessages.getOffset() == 0 && !_ackedMessages.get(0)) { - UDPPacket[] packets = null; - synchronized(this) { - if (_sessConfForReTX != null) { - // retransmit Session Confirmed when it's time - if (_sessConfSentTime + (SESS_CONF_RETX_TIME << (_sessConfSentCount - 1)) < now) { + if (!checkRetransmitSessionConfirmed(_context.clock().now(), false)) + return null; + } + return super.allocateSend(now); + } + + /** + * Only call for outbound, if we don't have ack 0 yet. + * + * @param force ignore timer, always send + * @return success, false if total fail + * @since 0.9.55 split out from above + */ + private boolean checkRetransmitSessionConfirmed(long now, boolean force) { + UDPPacket[] packets = null; + synchronized(this) { + if (_sessConfForReTX != null) { + // retransmit Session Confirmed when it's time + if (force || _sessConfSentTime + (OutboundEstablishState.RETRANSMIT_DELAY << (_sessConfSentCount - 1)) < now) { + if (_sessConfSentCount >= MAX_SESS_CONF_RETX) { // note: we generally won't get here, because the // first outbound message will timeout before this // and close the session in super.finishMessages() - if (_sessConfSentCount >= MAX_SESS_CONF_RETX) { - if (_log.shouldWarn()) - _log.warn("Fail, no Sess Conf ACK rcvd on " + this); - UDPPacket pkt = _transport.getBuilder2().buildSessionDestroyPacket(SSU2Util.REASON_FRAME_TIMEOUT, this); - _transport.send(pkt); - _transport.dropPeer(this, true, "No Sess Conf ACK rcvd"); - _sessConfForReTX = null; - return null; - } - _sessConfSentCount++; - _sessConfSentTime = now; - packets = getRetransmitSessionConfirmedPackets(); + if (_log.shouldWarn()) + _log.warn("Fail, no Sess Conf ACK rcvd on " + this); + UDPPacket pkt = _transport.getBuilder2().buildSessionDestroyPacket(SSU2Util.REASON_FRAME_TIMEOUT, this); + _transport.send(pkt); + _transport.dropPeer(this, true, "No Sess Conf ACK rcvd"); + _sessConfForReTX = null; + return false; } - } - } - if (packets != null) { - if (_log.shouldInfo()) - _log.info("ReTX Sess Conf on " + this); - for (int i = 0; i < packets.length; i++) { - _transport.send(packets[i]); + _sessConfSentCount++; + _sessConfSentTime = now; + packets = getRetransmitSessionConfirmedPackets(); } } } - return super.allocateSend(now); + if (packets != null) { + if (_log.shouldInfo()) + _log.info("ReTX Sess Conf on " + this); + for (int i = 0; i < packets.length; i++) { + _transport.send(packets[i]); + } + } + return true; } // SSU 1 unsupported things @@ -314,6 +326,13 @@ public class PeerState2 extends PeerState implements SSU2Payload.PayloadCallback if (header.getDestConnID() != _rcvConnID) { if (_log.shouldWarn()) _log.warn("bad Dest Conn id " + header + " size " + len + " on " + this); + if (!_isInbound && _ackedMessages.getOffset() == 0 && !_ackedMessages.get(0)) { + // this was probably a retransmitted session created, + // sent with k_header_1 = bob's intro key, and we're + // attempting to decrypt with our intro key. + // resend session confirmed in response + checkRetransmitSessionConfirmed(_context.clock().now(), true); + } return; } if (header.getType() != DATA_FLAG_BYTE) {