SSU2 Peer Test: Bob asks another Charlie on rejection

This commit is contained in:
zzz
2022-12-12 12:22:22 -05:00
parent 3472871e35
commit 580f954254
2 changed files with 69 additions and 7 deletions

View File

@@ -569,7 +569,7 @@ class PeerTestManager {
boolean isIPv6 = test.isIPv6();
Status status;
if (test.getAlicePortFromCharlie() > 0) {
// we received a second message from charlie
// we received a second message (7) from charlie
if ( (test.getAlicePort() == test.getAlicePortFromCharlie()) &&
(test.getAliceIP() != null) && (test.getAliceIPFromCharlie() != null) &&
(test.getAliceIP().equals(test.getAliceIPFromCharlie())) ) {
@@ -579,10 +579,10 @@ class PeerTestManager {
status = isIPv6 ? Status.IPV4_UNKNOWN_IPV6_FIREWALLED : Status.IPV4_SNAT_IPV6_UNKNOWN;
}
} else if (test.getReceiveCharlieTime() > 0) {
// we received only one message from charlie
// we received only one message (5) from charlie
status = Status.UNKNOWN;
} else if (test.getReceiveBobTime() > 0) {
// we received a message from bob but no messages from charlie
// we received a message from bob (4) but no messages from charlie
status = isIPv6 ? Status.IPV4_UNKNOWN_IPV6_FIREWALLED : Status.IPV4_FIREWALLED_IPV6_UNKNOWN;
} else {
// we never received anything from bob - he is either down,
@@ -1098,7 +1098,7 @@ class PeerTestManager {
fromPeer.setLastSendTime(now);
return;
}
PeerState charlie = _transport.pickTestPeer(CHARLIE, fromPeer.getVersion(), isIPv6, from);
PeerState charlie = _transport.pickTestPeer(CHARLIE, 2, isIPv6, from);
if (charlie == null) {
if (_log.shouldLog(Log.WARN))
_log.warn("Unable to pick a charlie (no peer), IPv6? " + isIPv6);
@@ -1117,6 +1117,8 @@ class PeerTestManager {
state.setCharlie(charlie.getRemoteIPAddress(), charlie.getRemotePort(), charlie.getRemotePeer());
state.setReceiveAliceTime(now);
state.setLastSendTime(now);
// save alice-signed test data in case we need to send to another charlie
state.setTestData(data);
_activeTests.put(lNonce, state);
_context.simpleTimer2().addEvent(new RemoveTest(lNonce), MAX_BOB_LIFETIME);
// send alice RI to charlie
@@ -1235,6 +1237,33 @@ class PeerTestManager {
// charlie to bob, in-session
case 3: {
state.setReceiveCharlieTime(now);
if (status != SSU2Util.TEST_ACCEPT &&
now - state.getBeginTime() < MAX_BOB_LIFETIME / 2) {
List<Hash> prev = state.getPreviousCharlies();
if (prev.size() < 7) {
PeerState charlie = _transport.pickTestPeer(CHARLIE, 2, isIPv6, from);
if (charlie != null && charlie != fromPeer && !prev.contains(charlie.getRemotePeer())) {
Hash alice = state.getAlice().getRemotePeer();
RouterInfo aliceRI = _context.netDb().lookupRouterInfoLocally(alice);
if (aliceRI != null) {
if (_log.shouldInfo())
_log.info("Charlie response " + status + " picked a new one " + charlie + " on " + state);
state.setCharlie(charlie.getRemoteIPAddress(), charlie.getRemotePort(), charlie.getRemotePeer());
state.setLastSendTime(now);
DatabaseStoreMessage dbsm = new DatabaseStoreMessage(_context);
dbsm.setEntry(aliceRI);
dbsm.setMessageExpiration(now + 10*1000);
_transport.send(dbsm, charlie);
UDPPacket packet = _packetBuilder2.buildPeerTestToCharlie(alice, state.getTestData(), (PeerState2) charlie);
_transport.send(packet);
charlie.setLastSendTime(now);
break;
}
}
}
}
if (status != SSU2Util.TEST_ACCEPT && _log.shouldWarn())
_log.warn("Charlie response " + status + " no more to choose from on " + state);
state.setLastSendTime(now);
PeerState2 alice = state.getAlice();
Hash charlie = fromPeer.getRemotePeer();
@@ -1265,7 +1294,7 @@ 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);
_log.debug("Send msg 4 status " + status + " to alice on " + state);
UDPPacket packet = _packetBuilder2.buildPeerTestToAlice(status, charlie, data, alice);
_transport.send(packet);
alice.setLastSendTime(now);
@@ -1465,7 +1494,8 @@ class PeerTestManager {
// ??
}
// this is our second charlie, yay!
test.setReceiveCharlieTime(now);
// Do NOT set this here, this is only for msg 5
//test.setReceiveCharlieTime(now);
// i2pd did not send address block in msg 7 until 0.9.57
if (addrBlockPort != 0) {
// use the IP/port from the address block

View File

@@ -1,6 +1,8 @@
package net.i2p.router.transport.udp;
import java.util.ArrayList;
import java.net.InetAddress;
import java.util.List;
import java.util.concurrent.atomic.AtomicInteger;
import net.i2p.data.DataHelper;
@@ -31,6 +33,10 @@ class PeerTestState {
private Hash _aliceHash;
// SSU2 only
private Hash _charlieHash;
// SSU2 BOB only
private byte[] _testData;
// SSU2 BOB only
private final List<Hash> _previousCharlies;
private final long _beginTime;
private long _lastSendTime;
private long _receiveAliceTime;
@@ -49,6 +55,7 @@ class PeerTestState {
_isIPv6 = isIPv6;
_testNonce = nonce;
_beginTime = now;
_previousCharlies = role == Role.BOB ? new ArrayList<Hash>(8) : null;
}
public long getNonce() { return _testNonce; }
@@ -98,6 +105,7 @@ class PeerTestState {
}
public InetAddress getBobIP() { return _bob.getRemoteIPAddress(); }
public InetAddress getCharlieIP() { return _charlieIP; }
/**
* @param hash SSU2 only, null for SSU1
* @since 0.9.54
@@ -105,8 +113,18 @@ class PeerTestState {
public void setCharlie(InetAddress ip, int port, Hash hash) {
_charlieIP = ip;
_charliePort = port;
if (_charlieHash != null && _previousCharlies != null)
_previousCharlies.add(_charlieHash);
_charlieHash = hash;
}
/**
* SSU2 only, BOB only, else returns null.
* Does not include current charlie.
* @since 0.9.57
*/
public List<Hash> getPreviousCharlies() { return _previousCharlies; }
public InetAddress getAliceIPFromCharlie() { return _aliceIPFromCharlie; }
public void setAliceIPFromCharlie(InetAddress ip) { _aliceIPFromCharlie = ip; }
/**
@@ -172,7 +190,19 @@ class PeerTestState {
/** when did we last hear from charlie? */
public long getReceiveCharlieTime() { return _receiveCharlieTime; }
public void setReceiveCharlieTime(long when) { _receiveCharlieTime = when; }
/**
* SSU2 only, we are Bob
* @since 0.9.57
*/
public byte[] getTestData() { return _testData; }
/**
* SSU2 only, we are Bob
* @since 0.9.57
*/
public void setTestData(byte[] data) { _testData = data; }
/** @return new value */
public int incrementPacketsRelayed() { return _packetsRelayed.incrementAndGet(); }
@@ -202,6 +232,8 @@ class PeerTestState {
buf.append("me");
else
buf.append(_charlieIP).append(':').append(_charliePort);
if (_previousCharlies != null && !_previousCharlies.isEmpty())
buf.append(" previous: ").append(_previousCharlies);
}
if (_lastSendTime > 0)
buf.append("; last send after ").append(_lastSendTime - _beginTime);