From 4a9f8240db2d97485fcf4d05e81a8d5265f873c9 Mon Sep 17 00:00:00 2001 From: zzz <zzz@i2pmail.org> Date: Sun, 5 Jun 2022 11:21:04 -0400 Subject: [PATCH] SSU2: Relay WIP part 6 Fix saving relay tag as Bob Select introducers by newest connection instead of random Ping introducers more often Check and set ping time when pinging introducers Remove unused nextCipherKey Debug: Prefer selecting SSU2 introducers Log tweaks --- .../transport/udp/EstablishmentManager.java | 2 +- .../transport/udp/IntroductionManager.java | 63 ++++++++++++++----- .../i2p/router/transport/udp/PeerState.java | 17 ++--- .../router/transport/udp/UDPTransport.java | 4 +- 4 files changed, 61 insertions(+), 25 deletions(-) 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 0c00148b57..c2828110b6 100644 --- a/router/java/src/net/i2p/router/transport/udp/EstablishmentManager.java +++ b/router/java/src/net/i2p/router/transport/udp/EstablishmentManager.java @@ -949,11 +949,11 @@ class EstablishmentManager { peer = new PeerState(_context, _transport, state.getSentIP(), state.getSentPort(), remote.calculateHash(), true, state.getRTT(), state.getCipherKey(), state.getMACKey()); - peer.setWeRelayToThemAs(state.getSentRelayTag()); } else { InboundEstablishState2 state2 = (InboundEstablishState2) state; peer = state2.getPeerState(); } + peer.setWeRelayToThemAs(state.getSentRelayTag()); if (version == 1) { // Lookup the peer's MTU from the netdb, since it isn't included in the protocol setup (yet) 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 d504b78e04..031a1bc0a4 100644 --- a/router/java/src/net/i2p/router/transport/udp/IntroductionManager.java +++ b/router/java/src/net/i2p/router/transport/udp/IntroductionManager.java @@ -5,6 +5,7 @@ import java.net.UnknownHostException; import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; +import java.util.Comparator; import java.util.HashSet; import java.util.List; import java.util.Map; @@ -110,6 +111,9 @@ class IntroductionManager { private static final long INTRODUCER_EXPIRATION = 80*60*1000L; private static final String MIN_IPV6_INTRODUCER_VERSION = "0.9.50"; private static final long MAX_SKEW = 2*60*1000; + /** testing */ + private static final String PROP_PREFER_SSU2 = "i2np.ssu2.preferSSU2Introducers"; + private static final boolean DEFAULT_PREFER_SSU2 = SSU2Util.ENABLE_RELAY && true; public IntroductionManager(RouterContext ctx, UDPTransport transport) { _context = ctx; @@ -150,8 +154,7 @@ class IntroductionManager { _inbound.put(Long.valueOf(id2), peer); } if (added &&_log.shouldLog(Log.DEBUG)) - _log.debug("adding peer " + peer.getRemotePeer() + ' ' + peer.getRemoteHostId() + ", weRelayToThemAs " - + id + ", theyRelayToUsAs " + id2); + _log.debug("adding peer " + peer); } public void remove(PeerState peer) { @@ -164,8 +167,7 @@ class IntroductionManager { _inbound.remove(Long.valueOf(id2)); } if ((id > 0 || id2 > 0) &&_log.shouldLog(Log.DEBUG)) - _log.debug("removing peer " + peer.getRemotePeer() + ' ' + peer.getRemoteHostId() + ", weRelayToThemAs " - + id + ", theyRelayToUsAs " + id2); + _log.debug("removing peer " + peer); } /** @@ -200,13 +202,13 @@ class IntroductionManager { * @return number of introducers added */ public int pickInbound(RouterAddress current, boolean ipv6, Properties ssuOptions, int howMany) { - int start = _context.random().nextInt(); if (_log.shouldLog(Log.DEBUG)) _log.debug("Picking inbound out of " + _inbound.size()); if (_inbound.isEmpty()) return 0; List<PeerState> peers = new ArrayList<PeerState>(_inbound.values()); int sz = peers.size(); - start = start % sz; + boolean preferV2 = _context.getProperty(PROP_PREFER_SSU2, DEFAULT_PREFER_SSU2); + Collections.sort(peers, new PeerStateComparator(preferV2)); int found = 0; long now = _context.clock().now(); long inactivityCutoff = now - (UDPTransport.EXPIRE_TIMEOUT / 2); // 15 min @@ -238,7 +240,7 @@ class IntroductionManager { } for (int i = 0; i < sz && found < howMany; i++) { - PeerState cur = peers.get((start + i) % sz); + PeerState cur = peers.get(i); if (cur.isIPv6() != ipv6) continue; RouterInfo ri = _context.netDb().lookupRouterInfoLocally(cur.getRemotePeer()); @@ -372,6 +374,36 @@ class IntroductionManager { return found; } + /** + * For picking introducers. + * Reverse sort, version 2 first, for testing + * Then lowest uptime first, to reduce idle timeout and disconnect, + * and ensure variety. + * + * @since 0.9.55 + */ + private static class PeerStateComparator implements Comparator<PeerState> { + private final boolean _v2; + + public PeerStateComparator(boolean preferV2) { + _v2 = preferV2; + } + + public int compare(PeerState l, PeerState r) { + if (_v2) { + int rv = r.getVersion() - l.getVersion(); + if (rv != 0) + return rv; + } + long d = r.getKeyEstablishedTime() - l.getKeyEstablishedTime(); + if (d < 0) + return -1; + if (d > 0) + return 1; + return 0; + } + } + /** * So we can sort them * @since 0.9.18 @@ -443,13 +475,13 @@ class IntroductionManager { // Try to keep the connection up for two hours after we made anybody an introducer long now = _context.clock().now(); long pingCutoff = now - (105 * 60 * 1000); - long inactivityCutoff = now - UDPTransport.MIN_EXPIRE_TIMEOUT; + long inactivityCutoff = now - (UDPTransport.MIN_EXPIRE_TIMEOUT / 2); for (PeerState cur : _inbound.values()) { if (cur.getIntroducerTime() > pingCutoff && - cur.getLastSendTime() < inactivityCutoff) { + cur.getLastSendOrPingTime() < inactivityCutoff) { if (_log.shouldLog(Log.INFO)) _log.info("Pinging introducer: " + cur); - cur.setLastSendTime(now); + cur.setLastPingTime(now); UDPPacket ping; if (cur.getVersion() == 2) ping = _builder2.buildPing((PeerState2) cur); @@ -770,8 +802,11 @@ class IntroductionManager { UDPPacket packet; if (rcode == SSU2Util.RELAY_ACCEPT) { // Send Alice RI and forward data in a Relay Intro to Charlie - if (_log.shouldDebug()) - _log.debug("Send alice RI and relay intro to " + charlie); + if (_log.shouldInfo()) + _log.info("Receive relay request from " + alice + + " for tag " + tag + + " nonce " + nonce + + " and relaying with " + charlie); DatabaseStoreMessage dbsm = new DatabaseStoreMessage(_context); dbsm.setEntry(aliceRI); dbsm.setMessageExpiration(now + 10*1000); @@ -796,8 +831,8 @@ class IntroductionManager { _log.warn("sig fail"); return; } - if (_log.shouldDebug()) - _log.debug("Send relay response rejection " + rcode + " to " + alice); + if (_log.shouldInfo()) + _log.info("Send relay response rejection " + rcode + " to " + alice); packet = _builder2.buildRelayResponse(data, alice); } _transport.send(packet); 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 01e43175d4..2cde0fd19d 100644 --- a/router/java/src/net/i2p/router/transport/udp/PeerState.java +++ b/router/java/src/net/i2p/router/transport/udp/PeerState.java @@ -62,12 +62,6 @@ public class PeerState { * connection, or null if we are not in the process of rekeying. */ private SessionKey _nextMACKey; - /** - * The pending AES key for encrypting/decrypting packets if we are - * rekeying the connection, or null if we are not in the process - * of rekeying. - */ - private SessionKey _nextCipherKey; /** when were the current cipher and MAC keys established/rekeyed? */ protected final long _keyEstablishedTime; @@ -489,9 +483,12 @@ public class PeerState { * * @return null always, rekeying unimplemented */ - SessionKey getNextCipherKey() { return _nextCipherKey; } + SessionKey getNextCipherKey() { return null; } - /** when were the current cipher and MAC keys established/rekeyed? */ + /** + * When were the current cipher and MAC keys established/rekeyed? + * This is the connection uptime. + */ public long getKeyEstablishedTime() { return _keyEstablishedTime; } /** @@ -2402,6 +2399,10 @@ public class PeerState { buf.append(" IBM: ").append(_inboundMessages.size()); buf.append(" OBQ: ").append(_outboundQueue.size()); buf.append(" OBL: ").append(_outboundMessages.size()); + if (_weRelayToThemAs > 0) + buf.append(" weRelayToThemAs: ").append(_weRelayToThemAs); + if (_theyRelayToUsAs > 0) + buf.append(" theyRelayToUsAs: ").append(_theyRelayToUsAs); 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 5f3a3bbc8f..28ea0f56e4 100644 --- a/router/java/src/net/i2p/router/transport/udp/UDPTransport.java +++ b/router/java/src/net/i2p/router/transport/udp/UDPTransport.java @@ -2040,8 +2040,8 @@ public class UDPTransport extends TransportImpl implements TimedWeightedPriority // _log.warn((ipv6 ? "IPv6" : "IPv4") + " introducers valid, haven't changed in " + DataHelper.formatDuration(sinceSelected) + ", reselecting"); // return true; //} else { - if (_log.shouldLog(Log.INFO)) - _log.info((ipv6 ? "IPv6" : "IPv4") + " introducers valid, selected " + DataHelper.formatDuration(sinceSelected) + " ago"); + if (_log.shouldDebug()) + _log.debug((ipv6 ? "IPv6" : "IPv4") + " introducers valid, selected " + DataHelper.formatDuration(sinceSelected) + " ago"); return false; //} } else if (sinceSelected > 2*60*1000) { -- GitLab