I2P Address: [http://git.idk.i2p]

Skip to content
Snippets Groups Projects
Unverified Commit 3c4956f0 authored by zzz's avatar zzz
Browse files

SSU2: Add delayed lookup of RI for relay and peer test

Prefer SSU2 introducers for slots 1 and 2
log tweaks
parent d69a6560
No related branches found
No related tags found
No related merge requests found
...@@ -27,6 +27,7 @@ import net.i2p.router.RouterContext; ...@@ -27,6 +27,7 @@ import net.i2p.router.RouterContext;
import net.i2p.router.transport.TransportUtil; import net.i2p.router.transport.TransportUtil;
import net.i2p.util.Addresses; import net.i2p.util.Addresses;
import net.i2p.util.Log; import net.i2p.util.Log;
import net.i2p.util.SimpleTimer2;
import net.i2p.util.VersionComparator; import net.i2p.util.VersionComparator;
/** /**
...@@ -235,11 +236,18 @@ class IntroductionManager { ...@@ -235,11 +236,18 @@ class IntroductionManager {
Introducer intro; Introducer intro;
byte[] key = ua.getIntroducerKey(i); byte[] key = ua.getIntroducerKey(i);
if (key != null) { if (key != null) {
// SSU 1
//// debug, replace SSU 1 with SSU 2 if available for slots 1-2
//// leave slot 0 for SSU 1
//// this will churn the SSU 1 introducers, oh well
if (preferV2 && i > 0)
continue;
intro = new Introducer(ua.getIntroducerHost(i).getAddress(), intro = new Introducer(ua.getIntroducerHost(i).getAddress(),
ua.getIntroducerPort(i), key, tag, sexp); ua.getIntroducerPort(i), key, tag, sexp);
if (_log.shouldInfo()) if (_log.shouldInfo())
_log.info("Reusing introducer: " + ua.getIntroducerHost(i)); _log.info("Reusing introducer: " + ua.getIntroducerHost(i));
} else { } else {
// SSU 2
intro = new Introducer(ua.getIntroducerHash(i), tag, sexp); intro = new Introducer(ua.getIntroducerHash(i), tag, sexp);
if (_log.shouldInfo()) if (_log.shouldInfo())
_log.info("Reusing introducer: " + ua.getIntroducerHash(i)); _log.info("Reusing introducer: " + ua.getIntroducerHash(i));
...@@ -879,6 +887,73 @@ class IntroductionManager { ...@@ -879,6 +887,73 @@ class IntroductionManager {
* @since 0.9.55 * @since 0.9.55
*/ */
void receiveRelayIntro(PeerState2 bob, Hash alice, byte[] data) { void receiveRelayIntro(PeerState2 bob, Hash alice, byte[] data) {
receiveRelayIntro(bob, alice, data, 0);
}
/**
* We are Charlie and we got this from Bob.
* Bob should have sent us the RI, but maybe it's in the block
* after this, or maybe it's in a different packet.
* Check for RI, if not found, return true to retry, unless retryCount is at the limit.
* Creates the timer if retryCount == 0.
*
* SSU 2 only.
*
* @return true if RI found, false to delay and retry.
* @since 0.9.55
*/
private boolean receiveRelayIntro(PeerState2 bob, Hash alice, byte[] data, int retryCount) {
RouterInfo aliceRI = null;
if (retryCount < 5 && !_context.banlist().isBanlisted(alice)) {
aliceRI = _context.netDb().lookupRouterInfoLocally(alice);
if (aliceRI == null) {
if (_log.shouldInfo())
_log.info("Delay after " + retryCount + " retries, no RI for " + alice.toBase64());
if (retryCount == 0)
new DelayIntro(bob, alice, data);
return false;
}
}
receiveRelayIntro(bob, alice, data, aliceRI);
return true;
}
/**
* Wait for RI.
* @since 0.9.55
*/
private class DelayIntro extends SimpleTimer2.TimedEvent {
private final PeerState2 bob;
private final Hash alice;
private final byte[] data;
private volatile int count;
private static final long DELAY = 50;
public DelayIntro(PeerState2 b, Hash a, byte[] d) {
super(_context.simpleTimer2());
bob = b;
alice = a;
data = d;
schedule(DELAY);
}
public void timeReached() {
boolean ok = receiveRelayIntro(bob, alice, data, ++count);
if (!ok)
reschedule(DELAY << count);
}
}
/**
* We are Charlie and we got this from Bob.
* Send a HolePunch to Alice, who will soon be sending us a SessionRequest.
* And send a RelayResponse to bob.
*
* SSU 2 only.
*
* @since 0.9.55
*/
private void receiveRelayIntro(PeerState2 bob, Hash alice, byte[] data, RouterInfo aliceRI) {
long nonce = DataHelper.fromLong(data, 0, 4); long nonce = DataHelper.fromLong(data, 0, 4);
long tag = DataHelper.fromLong(data, 4, 4); long tag = DataHelper.fromLong(data, 4, 4);
long time = DataHelper.fromLong(data, 8, 4) * 1000; long time = DataHelper.fromLong(data, 8, 4) * 1000;
...@@ -912,7 +987,6 @@ class IntroductionManager { ...@@ -912,7 +987,6 @@ class IntroductionManager {
return; return;
} }
RouterInfo aliceRI = null;
SessionKey aliceIntroKey = null; SessionKey aliceIntroKey = null;
int rcode; int rcode;
PeerState aps = _transport.getPeerState(alice); PeerState aps = _transport.getPeerState(alice);
...@@ -927,8 +1001,7 @@ class IntroductionManager { ...@@ -927,8 +1001,7 @@ class IntroductionManager {
rcode = SSU2Util.RELAY_REJECT_CHARLIE_ADDRESS; rcode = SSU2Util.RELAY_REJECT_CHARLIE_ADDRESS;
} else { } else {
// bob should have sent it to us. Don't bother to lookup // 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. // remotely if he didn't, or it was lost.
aliceRI = _context.netDb().lookupRouterInfoLocally(alice);
if (aliceRI != null) { if (aliceRI != null) {
// validate signed data // validate signed data
SigningPublicKey spk = aliceRI.getIdentity().getSigningPublicKey(); SigningPublicKey spk = aliceRI.getIdentity().getSigningPublicKey();
...@@ -946,7 +1019,7 @@ class IntroductionManager { ...@@ -946,7 +1019,7 @@ class IntroductionManager {
} }
} else { } else {
if (_log.shouldWarn()) if (_log.shouldWarn())
_log.warn("Alice RI not found " + alice); _log.warn("Alice RI not found " + alice + " for relay intro from " + bob);
rcode = SSU2Util.RELAY_REJECT_CHARLIE_UNKNOWN_ALICE; rcode = SSU2Util.RELAY_REJECT_CHARLIE_UNKNOWN_ALICE;
} }
} }
...@@ -985,8 +1058,8 @@ class IntroductionManager { ...@@ -985,8 +1058,8 @@ class IntroductionManager {
return; return;
} }
UDPPacket packet = _builder2.buildRelayResponse(data, bob); UDPPacket packet = _builder2.buildRelayResponse(data, bob);
if (_log.shouldDebug()) if (_log.shouldInfo())
_log.debug("Send relay response " + rcode + " as charlie " + " nonce " + nonce + " to bob " + bob); _log.info("Send relay response " + rcode + " as charlie " + " nonce " + nonce + " to bob " + bob);
_transport.send(packet); _transport.send(packet);
if (rcode == SSU2Util.RELAY_ACCEPT) { if (rcode == SSU2Util.RELAY_ACCEPT) {
// send hole punch with the same data we sent to Bob // send hole punch with the same data we sent to Bob
......
...@@ -32,6 +32,7 @@ import net.i2p.util.Addresses; ...@@ -32,6 +32,7 @@ import net.i2p.util.Addresses;
import net.i2p.util.Log; import net.i2p.util.Log;
import net.i2p.util.HexDump; import net.i2p.util.HexDump;
import net.i2p.util.SimpleTimer; import net.i2p.util.SimpleTimer;
import net.i2p.util.SimpleTimer2;
import net.i2p.util.VersionComparator; import net.i2p.util.VersionComparator;
/** /**
...@@ -838,7 +839,67 @@ class PeerTestManager { ...@@ -838,7 +839,67 @@ class PeerTestManager {
* @since 0.9.54 * @since 0.9.54
*/ */
public void receiveTest(RemoteHostId from, PeerState2 fromPeer, int msg, int status, Hash h, byte[] data) { public void receiveTest(RemoteHostId from, PeerState2 fromPeer, int msg, int status, Hash h, byte[] data) {
receiveTest(from, fromPeer, msg, status, h, data, null, 0); if (status == 0 && (msg == 2 || msg == 4) && !_context.banlist().isBanlisted(h))
receiveTest(from, fromPeer, msg, h, data, 0);
else
receiveTest(from, fromPeer, msg, status, h, data, null, 0);
}
/**
* Status 0 only, Msg 2 and 4 only, SSU 2 only.
* Bob should have sent us the RI, but maybe it's in the block
* after this, or maybe it's in a different packet.
* Check for RI, if not found, return true to retry, unless retryCount is at the limit.
* Creates the timer if retryCount == 0.
*
* We are Alice for msg 4, Charlie for msg 2.
*
* @return true if RI found, false to delay and retry.
* @since 0.9.55
*/
private boolean receiveTest(RemoteHostId from, PeerState2 fromPeer, int msg, Hash h, byte[] data, int retryCount) {
if (retryCount < 5) {
RouterInfo ri = _context.netDb().lookupRouterInfoLocally(h);
if (ri == null) {
if (_log.shouldInfo())
_log.info("Delay after " + retryCount + " retries, no RI for " + h.toBase64());
if (retryCount == 0)
new DelayTest(from, fromPeer, msg, h, data);
return false;
}
}
receiveTest(from, fromPeer, msg, 0, h, data, null, 0);
return true;
}
/**
* Wait for RI.
* @since 0.9.55
*/
private class DelayTest extends SimpleTimer2.TimedEvent {
private final RemoteHostId from;
private final PeerState2 fromPeer;
private final int msg;
private final Hash hash;
private final byte[] data;
private volatile int count;
private static final long DELAY = 50;
public DelayTest(RemoteHostId f, PeerState2 fp, int m, Hash h, byte[] d) {
super(_context.simpleTimer2());
from = f;
fromPeer = fp;
msg = m;
hash = h;
data = d;
schedule(DELAY);
}
public void timeReached() {
boolean ok = receiveTest(from, fromPeer, msg, hash, data, ++count);
if (!ok)
reschedule(DELAY << count);
}
} }
/** /**
...@@ -1102,7 +1163,7 @@ class PeerTestManager { ...@@ -1102,7 +1163,7 @@ class PeerTestManager {
} }
} else { } else {
if (_log.shouldWarn()) if (_log.shouldWarn())
_log.warn("Alice RI not found " + h); _log.warn("Alice RI not found " + h + " for peer test from " + fromPeer);
rcode = SSU2Util.TEST_REJECT_CHARLIE_UNKNOWN_ALICE; rcode = SSU2Util.TEST_REJECT_CHARLIE_UNKNOWN_ALICE;
} }
} }
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment