diff --git a/history.txt b/history.txt index f02cd0804..83ae581e0 100644 --- a/history.txt +++ b/history.txt @@ -1,3 +1,6 @@ +2022-03-13 zzz + * SSU2: Fixes + 2022-03-12 zzz * SSU2: Fixes * Tunnels: Reduce build reply timeout diff --git a/router/java/src/net/i2p/router/RouterVersion.java b/router/java/src/net/i2p/router/RouterVersion.java index 707cdcd34..6a9511fad 100644 --- a/router/java/src/net/i2p/router/RouterVersion.java +++ b/router/java/src/net/i2p/router/RouterVersion.java @@ -18,7 +18,7 @@ public class RouterVersion { /** deprecated */ public final static String ID = "Git"; public final static String VERSION = CoreVersion.VERSION; - public final static long BUILD = 7; + public final static long BUILD = 8; /** for example "-test" */ public final static String EXTRA = ""; 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 f4bc75172..72e249ba4 100644 --- a/router/java/src/net/i2p/router/transport/udp/EstablishmentManager.java +++ b/router/java/src/net/i2p/router/transport/udp/EstablishmentManager.java @@ -518,8 +518,8 @@ class EstablishmentManager { } if (_context.blocklist().isBlocklisted(from.getIP())) { - if (_log.shouldLog(Log.WARN)) - _log.warn("Receive session request from blocklisted IP: " + from); + if (_log.shouldInfo()) + _log.info("Receive session request from blocklisted IP: " + from); _context.statManager().addRateData("udp.establishBadIP", 1); return; // drop the packet } @@ -594,8 +594,8 @@ class EstablishmentManager { return; // drop the packet } if (_context.blocklist().isBlocklisted(from.getIP())) { - if (_log.shouldWarn()) - _log.warn("Receive session request from blocklisted IP: " + from); + if (_log.shouldInfo()) + _log.info("Receive session request from blocklisted IP: " + from); _context.statManager().addRateData("udp.establishBadIP", 1); return; // drop the packet } @@ -679,8 +679,8 @@ class EstablishmentManager { if (_log.shouldLog(Log.DEBUG)) _log.debug("Receive session confirmed from: " + state); } else { - if (_log.shouldLog(Log.WARN)) - _log.warn("Receive (DUP?) session confirmed from: " + from); + if (_log.shouldInfo()) + _log.info("Receive (DUP?) session confirmed from: " + from); } } @@ -725,8 +725,8 @@ class EstablishmentManager { if (_log.shouldLog(Log.DEBUG)) _log.debug("Receive session created from: " + state); } else { - if (_log.shouldLog(Log.WARN)) - _log.warn("Receive (DUP?) session created from: " + from); + if (_log.shouldInfo()) + _log.info("Receive (DUP?) session created from: " + from); } } @@ -1427,7 +1427,8 @@ class EstablishmentManager { } else { // save for retx OutboundEstablishState2 state2 = (OutboundEstablishState2) state; - state2.confirmedPacketsSent(packets); + // PacketBuilder2 told the state + //state2.confirmedPacketsSent(packets); // we are done, go right to ps2 handleCompletelyEstablished(state2); } 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 ead02c0ae..b6d8b83b7 100644 --- a/router/java/src/net/i2p/router/transport/udp/InboundEstablishState2.java +++ b/router/java/src/net/i2p/router/transport/udp/InboundEstablishState2.java @@ -91,6 +91,8 @@ class InboundEstablishState2 extends InboundEstablishState implements SSU2Payloa int type = data[off + TYPE_OFFSET] & 0xff; long token = DataHelper.fromLong8(data, off + TOKEN_OFFSET); if (type == TOKEN_REQUEST_FLAG_BYTE) { + if (_log.shouldInfo()) + _log.info("Got token request from: " + _aliceSocketAddress); _currentState = InboundState.IB_STATE_TOKEN_REQUEST_RECEIVED; // decrypt in-place ChaChaPolyCipherState chacha = new ChaChaPolyCipherState(); @@ -430,9 +432,9 @@ class InboundEstablishState2 extends InboundEstablishState implements SSU2Payloa throw new IllegalStateException("Bad state for Retry Sent: " + _currentState); _currentState = InboundState.IB_STATE_RETRY_SENT; _lastSend = _context.clock().now(); - // Won't really be transmitted, they have 3 sec to respond or + // Won't really be retransmitted, they have 9 sec to respond or // EstablishmentManager.handleInbound() will fail the connection - _nextSend = _lastSend + RETRANSMIT_DELAY; + _nextSend = _lastSend + (3 * RETRANSMIT_DELAY); } /** @@ -441,6 +443,8 @@ class InboundEstablishState2 extends InboundEstablishState implements SSU2Payloa public synchronized void receiveSessionRequestAfterRetry(UDPPacket packet) throws GeneralSecurityException { if (_currentState != InboundState.IB_STATE_RETRY_SENT) throw new GeneralSecurityException("Bad state for Session Request after Retry: " + _currentState); + if (_log.shouldInfo()) + _log.info("Got session request after retry from: " + _aliceSocketAddress); DatagramPacket pkt = packet.getPacket(); SocketAddress from = pkt.getSocketAddress(); if (!from.equals(_aliceSocketAddress)) diff --git a/router/java/src/net/i2p/router/transport/udp/IntroductionManager.java b/router/java/src/net/i2p/router/transport/udp/IntroductionManager.java index b513a4e61..d31c4ae2c 100644 --- a/router/java/src/net/i2p/router/transport/udp/IntroductionManager.java +++ b/router/java/src/net/i2p/router/transport/udp/IntroductionManager.java @@ -76,6 +76,7 @@ class IntroductionManager { private final Log _log; private final UDPTransport _transport; private final PacketBuilder _builder; + private final PacketBuilder2 _builder2; /** map of relay tag to PeerState that should receive the introduction */ private final Map _outbound; /** map of relay tag to PeerState who have given us introduction tags */ @@ -107,6 +108,7 @@ class IntroductionManager { _log = ctx.logManager().getLog(IntroductionManager.class); _transport = transport; _builder = transport.getBuilder(); + _builder2 = transport.getBuilder2(); _outbound = new ConcurrentHashMap(MAX_OUTBOUND); _inbound = new ConcurrentHashMap(MAX_INBOUND); _recentHolePunches = new HashSet(16); @@ -396,7 +398,12 @@ class IntroductionManager { if (_log.shouldLog(Log.INFO)) _log.info("Pinging introducer: " + cur); cur.setLastSendTime(now); - _transport.send(_builder.buildPing(cur)); + UDPPacket ping; + if (cur.getVersion() == 2) + ping = _builder2.buildPing((PeerState2) cur); + else + ping = _builder.buildPing(cur); + _transport.send(ping); } } } 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 fa9d950cd..29ef7b5d6 100644 --- a/router/java/src/net/i2p/router/transport/udp/OutboundEstablishState.java +++ b/router/java/src/net/i2p/router/transport/udp/OutboundEstablishState.java @@ -120,7 +120,7 @@ class OutboundEstablishState { * Transmissions at 0, 3, 9 sec * Previously: 1500 (0, 1.5, 4.5, 10.5) */ - private static final long RETRANSMIT_DELAY = 3000; + protected static final long RETRANSMIT_DELAY = 3000; /** max delay including backoff */ private static final long MAX_DELAY = 15*1000; diff --git a/router/java/src/net/i2p/router/transport/udp/OutboundEstablishState2.java b/router/java/src/net/i2p/router/transport/udp/OutboundEstablishState2.java index 45d9cfb0c..c2cae324e 100644 --- a/router/java/src/net/i2p/router/transport/udp/OutboundEstablishState2.java +++ b/router/java/src/net/i2p/router/transport/udp/OutboundEstablishState2.java @@ -404,7 +404,7 @@ class OutboundEstablishState2 extends OutboundEstablishState implements SSU2Payl } /** - * note that we just sent the SessionConfirmed packets + * Note that we just sent a token request packet. * and save them for retransmission */ public synchronized void tokenRequestSent(DatagramPacket packet) { @@ -420,6 +420,8 @@ class OutboundEstablishState2 extends OutboundEstablishState implements SSU2Payl * and save it for retransmission */ public synchronized void requestSent(DatagramPacket pkt) { + OutboundState old = _currentState; + requestSent(); if (_sessReqForReTX == null) { // store pkt for retx byte data[] = pkt.getData(); @@ -427,11 +429,15 @@ class OutboundEstablishState2 extends OutboundEstablishState implements SSU2Payl int len = pkt.getLength(); _sessReqForReTX = new byte[len]; System.arraycopy(data, off, _sessReqForReTX, 0, len); + if (_requestSentCount > 1) { + // fixup the counter and delay because we also called + // requestSent() when sending the token request + _requestSentCount = 1; + _nextSend = _lastSend + RETRANSMIT_DELAY; + } } if (_rcvHeaderEncryptKey2 == null) _rcvHeaderEncryptKey2 = SSU2Util.hkdf(_context, _handshakeState.getChainingKey(), "SessCreateHeader"); - OutboundState old = _currentState; - requestSent(); if (old == OutboundState.OB_STATE_RETRY_RECEIVED) _currentState = OutboundState.OB_STATE_REQUEST_SENT_NEW_TOKEN; } diff --git a/router/java/src/net/i2p/router/transport/udp/PacketBuilder2.java b/router/java/src/net/i2p/router/transport/udp/PacketBuilder2.java index a272262c8..df52f4ab6 100644 --- a/router/java/src/net/i2p/router/transport/udp/PacketBuilder2.java +++ b/router/java/src/net/i2p/router/transport/udp/PacketBuilder2.java @@ -953,7 +953,7 @@ class PacketBuilder2 { int len = riblock.getTotalLength(); blocks.add(riblock); // only if room - if (token > 0 && mtu - len >= 15) { + if (token > 0 && mtu - (SHORT_HEADER_SIZE + KEY_LEN + MAC_LEN + len + MAC_LEN) >= 15) { Block block = new SSU2Payload.NewTokenBlock(token, _context.clock().now() + EstablishmentManager.IB_TOKEN_EXPIRATION); len += block.getTotalLength(); blocks.add(block); 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 992060280..096729849 100644 --- a/router/java/src/net/i2p/router/transport/udp/PeerState.java +++ b/router/java/src/net/i2p/router/transport/udp/PeerState.java @@ -1722,10 +1722,11 @@ public class PeerState { } } } + /**** if ( rv == null && _log.shouldLog(Log.DEBUG)) _log.debug("Nothing to send to " + _remotePeer + ", with " + _outboundMessages.size() + " / " + _outboundQueue.size() + " remaining, rtx timer in " + (_retransmitTimer - now)); - + ****/ return rv; } 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 4d9b1a1d5..d7db35b36 100644 --- a/router/java/src/net/i2p/router/transport/udp/PeerState2.java +++ b/router/java/src/net/i2p/router/transport/udp/PeerState2.java @@ -271,6 +271,10 @@ public class PeerState2 extends PeerState implements SSU2Payload.PayloadCallback // logged in PacketBuilder2 //if (_log.shouldDebug()) // _log.debug("Sending acks " + _receivedMessages + " on " + this); + synchronized(this) { + // cancel the ack timer + _wantACKSendSince = 0; + } return _receivedMessages; } SSU2Bitfield getAckedMessages() { return _ackedMessages; } diff --git a/router/java/src/net/i2p/router/transport/udp/SSU2Bitfield.java b/router/java/src/net/i2p/router/transport/udp/SSU2Bitfield.java index 380997c49..bbad4ed27 100644 --- a/router/java/src/net/i2p/router/transport/udp/SSU2Bitfield.java +++ b/router/java/src/net/i2p/router/transport/udp/SSU2Bitfield.java @@ -308,6 +308,7 @@ class SSU2Bitfield { } } } + /**** sb.append(" (RAW: ").append(thru).append(" A:").append(acnt); if (ranges != null) { for (int i = 0; i < rangeCount * 2; i += 2) { @@ -316,6 +317,7 @@ class SSU2Bitfield { } } sb.append(')'); + ****/ return sb.toString(); } diff --git a/router/java/src/net/i2p/router/transport/udp/SSU2Util.java b/router/java/src/net/i2p/router/transport/udp/SSU2Util.java index ff26d4a8a..d8eacf585 100644 --- a/router/java/src/net/i2p/router/transport/udp/SSU2Util.java +++ b/router/java/src/net/i2p/router/transport/udp/SSU2Util.java @@ -45,7 +45,7 @@ final class SSU2Util { public static final int HEADER_PROT_1_OFFSET = DEST_CONN_ID_OFFSET; public static final int HEADER_PROT_2_OFFSET = PKT_NUM_OFFSET; - public static final int PADDING_MAX = 64; + public static final int PADDING_MAX = 32; /** 40 */ public static final int MIN_DATA_LEN = SHORT_HEADER_SIZE + TOTAL_PROT_SAMPLE_LEN; 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 da1742394..e0f6c30af 100644 --- a/router/java/src/net/i2p/router/transport/udp/UDPTransport.java +++ b/router/java/src/net/i2p/router/transport/udp/UDPTransport.java @@ -944,12 +944,8 @@ public class UDPTransport extends TransportImpl implements TimedWeightedPriority * @since 0.9.54 */ private void addSSU2Options(Properties props) { - // only set i if we are not firewalled - if (props.containsKey("host")) { - props.setProperty("i", _ssu2B64StaticIntroKey); - } else { - props.remove("i"); - } + // Unlike in NTCP2, we need the intro key whether firewalled or not + props.setProperty("i", _ssu2B64StaticIntroKey); props.setProperty("s", _ssu2B64StaticPubKey); props.setProperty("v", SSU2_VERSION); } @@ -3544,7 +3540,12 @@ public class UDPTransport extends TransportImpl implements TimedWeightedPriority // TODO if both sides are firewalled should only one ping // or else session will stay open forever? //peer.setLastSendTime(now); - send(_packetBuilder.buildPing(peer)); + UDPPacket ping; + if (peer.getVersion() == 2) + ping = _packetBuilder2.buildPing((PeerState2) peer); + else + ping = _packetBuilder.buildPing(peer); + send(ping); peer.setLastPingTime(now); // If external port is different, it may be changing the port for every // session, so ping all of them. Otherwise only one.