From cdf5bec155f7093b0abae42108d24e6f4a733245 Mon Sep 17 00:00:00 2001
From: zzz <zzz@i2pmail.org>
Date: Sun, 24 Apr 2022 08:57:20 -0400
Subject: [PATCH] SSU2: Peer Test fixes part 3

Reject if alice/charlie already connected
Do not retransmit msg 1 after receiving msg 4
Log tweaks
---
 .../router/transport/udp/PeerTestManager.java | 36 +++++++++++++++----
 1 file changed, 29 insertions(+), 7 deletions(-)

diff --git a/router/java/src/net/i2p/router/transport/udp/PeerTestManager.java b/router/java/src/net/i2p/router/transport/udp/PeerTestManager.java
index 25124f9ad1..b71fdb181c 100644
--- a/router/java/src/net/i2p/router/transport/udp/PeerTestManager.java
+++ b/router/java/src/net/i2p/router/transport/udp/PeerTestManager.java
@@ -256,7 +256,9 @@ class PeerTestManager {
                     } else if (state.getReceiveCharlieTime() <= 0) {
                         // received from Bob, but no reply from Charlie.  send it to 
                         // Bob again so he pokes Charlie
-                        sendTestToBob();
+                        // This is only useful for SSU 1; SSU 2 discards dups
+                        if (state.getBob().getVersion() == 1)
+                            sendTestToBob();
                     } else {
                         // received from both Bob and Charlie, but we haven't received a
                         // second message from Charlie yet
@@ -977,6 +979,8 @@ class PeerTestManager {
                 state.setLastSendTime(now);
                 _activeTests.put(lNonce, state);
                 // send alice RI to charlie
+                if (_log.shouldDebug())
+                    _log.debug("Send Alice RI and msg 2 to charlie on " + state);
                 DatabaseStoreMessage dbsm = new DatabaseStoreMessage(_context);
                 dbsm.setEntry(aliceRI);
                 dbsm.setMessageExpiration(now + 10*1000);
@@ -1004,7 +1008,13 @@ class PeerTestManager {
                 RouterInfo aliceRI = null;
                 SessionKey aliceIntroKey = null;
                 int rcode;
-                if (_context.banlist().isBanlisted(h)) {
+                PeerState aps = _transport.getPeerState(h);
+                if (aps != null && aps.isIPv6() == isIPv6) {
+                    rcode = SSU2Util.TEST_REJECT_CHARLIE_CONNECTED;
+                } else if (_transport.getEstablisher().getInboundState(from) != null ||
+                           _transport.getEstablisher().getOutboundState(from) != null) {
+                    rcode = SSU2Util.TEST_REJECT_CHARLIE_CONNECTED;
+                } else if (_context.banlist().isBanlisted(h)) {
                     rcode = SSU2Util.TEST_REJECT_CHARLIE_BANNED;
                 } else if (!TransportUtil.isValidPort(testPort) ||
                           !_transport.isValid(testIP) ||
@@ -1063,7 +1073,7 @@ class PeerTestManager {
                 if (rcode == SSU2Util.TEST_ACCEPT) {
                     // send msg 5
                     if (_log.shouldDebug())
-                        _log.debug("Send msg 5 to " + Addresses.toString(testIP, testPort));
+                        _log.debug("Send msg 5 to " + Addresses.toString(testIP, testPort) + " on " + state);
                     long rcvId = (nonce << 32) | nonce;
                     long sendId = ~rcvId;
                     // send the same data we sent to Bob
@@ -1084,6 +1094,8 @@ class PeerTestManager {
                 RouterInfo charlieRI = _context.netDb().lookupRouterInfoLocally(charlie);
                 if (charlieRI != null) {
                     // send charlie RI to alice
+                    if (_log.shouldDebug())
+                        _log.debug("Send Charlie RI to alice on " + state);
                     DatabaseStoreMessage dbsm = new DatabaseStoreMessage(_context);
                     dbsm.setEntry(charlieRI);
                     dbsm.setMessageExpiration(now + 10*1000);
@@ -1095,6 +1107,8 @@ class PeerTestManager {
                 }
                 // forward to alice, don't bother to validate signed data
                 // FIXME this will probably get there before the RI
+                if (_log.shouldDebug())
+                    _log.debug("Send msg 4 to alice on " + state);
                 UDPPacket packet = _packetBuilder2.buildPeerTestToAlice(status, charlie, data, alice);
                 _transport.send(packet);
                 // we are done
@@ -1121,16 +1135,24 @@ class PeerTestManager {
                 boolean fail = false;
                 RouterInfo charlieRI = null;
                 SessionKey charlieIntroKey = null;
+                PeerState cps = _transport.getPeerState(h);
                 if (status != 0) {
-                    if (_log.shouldWarn())
-                        _log.warn("Msg 4 status " + status);
+                    if (_log.shouldInfo())
+                        _log.info("Msg 4 status " + status + ' ' + test);
+                } else if (cps != null && cps.isIPv6() == isIPv6) {
+                    if (_log.shouldInfo())
+                        _log.info("Charlie is connected " + test);
+                } else if (_transport.getEstablisher().getInboundState(from) != null ||
+                           _transport.getEstablisher().getOutboundState(from) != null) {
+                    if (_log.shouldInfo())
+                        _log.info("Charlie is connecting " + test);
                 } else if (_context.banlist().isBanlisted(h) ||
                     !TransportUtil.isValidPort(testPort) ||
                     !_transport.isValid(testIP) ||
                     _transport.isTooClose(testIP) ||
                     _context.blocklist().isBlocklisted(testIP)) {
-                    if (_log.shouldWarn())
-                        _log.warn("Test fail ban/ip/port");
+                    if (_log.shouldInfo())
+                        _log.info("Test fail ban/ip/port " + h + ' ' + Addresses.toString(testIP, testPort));
                 } else {
                     // bob should have sent it to us. Don't bother to lookup
                     // remotely if he didn't, or it was out-of-order or lost.
-- 
GitLab