* NetDB: Handle RI response from non-floodfill router down a client tunnel

This commit is contained in:
zzz
2014-04-01 13:05:51 +00:00
parent b206665c72
commit 0570feda6f
4 changed files with 31 additions and 5 deletions

View File

@@ -1,3 +1,7 @@
2014-04-01 zzz
* Console: Fix summary bar html when displaying an update constraint
* NetDB: Handle RI response from non-floodfill router down a client tunnel
* 2014-03-31 0.9.12 released
2014-03-28 zzz

View File

@@ -18,7 +18,7 @@ public class RouterVersion {
/** deprecated */
public final static String ID = "Monotone";
public final static String VERSION = CoreVersion.VERSION;
public final static long BUILD = 0;
public final static long BUILD = 1;
/** for example "-test" */
public final static String EXTRA = "";

View File

@@ -100,7 +100,9 @@ class IterativeSearchJob extends FloodSearchJob {
}
/**
* Lookup using the client's tunnels
* Lookup using the client's tunnels.
* Do not use for RI lookups down client tunnels,
* as the response will be dropped in InboundMessageDistributor.
* @param fromLocalDest use these tunnels for the lookup, or null for exploratory
* @since 0.9.10
*/
@@ -116,6 +118,8 @@ class IterativeSearchJob extends FloodSearchJob {
_failedPeers = new HashSet<Hash>(TOTAL_SEARCH_LIMIT);
_sentTime = new ConcurrentHashMap<Hash, Long>(TOTAL_SEARCH_LIMIT);
_fromLocalDest = fromLocalDest;
if (fromLocalDest != null && !isLease && _log.shouldLog(Log.WARN))
_log.warn("Search for RI " + key + " down client tunnel " + fromLocalDest, new Exception());
}
@Override

View File

@@ -4,6 +4,7 @@ import net.i2p.data.DatabaseEntry;
import net.i2p.data.Hash;
import net.i2p.data.LeaseSet;
import net.i2p.data.Payload;
import net.i2p.data.RouterInfo;
import net.i2p.data.TunnelId;
import net.i2p.data.i2np.DataMessage;
import net.i2p.data.i2np.DatabaseSearchReplyMessage;
@@ -18,7 +19,7 @@ import net.i2p.router.ClientMessage;
import net.i2p.router.RouterContext;
import net.i2p.router.TunnelInfo;
import net.i2p.router.message.GarlicMessageReceiver;
//import net.i2p.router.networkdb.kademlia.FloodfillNetworkDatabaseFacade;
import net.i2p.router.networkdb.kademlia.FloodfillNetworkDatabaseFacade;
import net.i2p.util.Log;
/**
@@ -82,11 +83,28 @@ class InboundMessageDistributor implements GarlicMessageReceiver.CloveReceiver {
DatabaseStoreMessage dsm = (DatabaseStoreMessage) msg;
if (dsm.getEntry().getType() == DatabaseEntry.KEY_TYPE_ROUTERINFO) {
// FVSJ may result in an unsolicited RI store if the peer went non-ff.
// Maybe we can figure out a way to handle this safely, so we don't ask him again.
// For now, just hope we eventually find out through other means.
// We handle this safely, so we don't ask him again.
// Todo: if peer was ff and RI is not ff, queue for exploration in netdb (but that isn't part of the facade now)
if (_log.shouldLog(Log.WARN))
_log.warn("Dropping DSM down a tunnel for " + _client + ": " + msg);
// Handle safely by just updating the caps table, after doing basic validation
Hash key = dsm.getKey();
if (_context.routerHash().equals(key))
return;
RouterInfo ri = (RouterInfo) dsm.getEntry();
if (!key.equals(ri.getIdentity().getHash()))
return;
if (!ri.isValid())
return;
RouterInfo oldri = _context.netDb().lookupRouterInfoLocally(key);
// only update if RI is newer and non-ff
if (oldri != null && oldri.getPublished() < ri.getPublished() &&
!FloodfillNetworkDatabaseFacade.isFloodfill(ri)) {
if (_log.shouldLog(Log.WARN))
_log.warn("Updating caps for RI " + key + " from \"" +
oldri.getCapabilities() + "\" to \"" + ri.getCapabilities() + '"');
_context.peerManager().setCapabilities(key, ri.getCapabilities());
}
return;
} else if (dsm.getReplyToken() != 0) {
if (_log.shouldLog(Log.WARN))