use of net.i2p.data.LeaseSet in project i2p.i2p by i2p.
the class OutboundClientMessageOneShotJob method getReplyLeaseSet.
/**
* @param force to force including a reply lease set
* @return lease set or null if we should not send the lease set
*/
private LeaseSet getReplyLeaseSet(boolean force) {
LeaseSet newLS = getContext().netDb().lookupLeaseSetLocally(_from.calculateHash());
if (newLS == null)
// punt
return null;
// If the last leaseSet we sent him is still good, don't bother sending again
LeaseSet ls = _cache.leaseSetCache.put(_hashPair, newLS);
if (!force) {
if (ls != null) {
if (ls.equals(newLS)) {
if (_log.shouldLog(Log.INFO))
_log.info(getJobId() + ": Found in cache - NOT including reply leaseset for " + _toString);
return null;
} else {
if (_log.shouldLog(Log.INFO))
_log.info(getJobId() + ": Expired from cache - reply leaseset for " + _toString);
}
}
}
if (_log.shouldLog(Log.INFO))
_log.info(getJobId() + ": Added to cache - reply leaseset for " + _toString);
return newLS;
}
use of net.i2p.data.LeaseSet in project i2p.i2p by i2p.
the class HandleDatabaseLookupMessageJob method runJob.
public void runJob() {
if (_log.shouldLog(Log.DEBUG))
_log.debug("Handling database lookup message for " + _message.getSearchKey());
Hash fromKey = _message.getFrom();
if (_log.shouldLog(Log.DEBUG)) {
if (_message.getReplyTunnel() != null)
_log.debug("dbLookup received with replies going to " + fromKey + " (tunnel " + _message.getReplyTunnel() + ")");
}
// If we are hidden we should not get queries, log and return
if (getContext().router().isHidden()) {
if (_log.shouldLog(Log.WARN)) {
_log.warn("Uninvited dbLookup received with replies going to " + fromKey + " (tunnel " + _message.getReplyTunnel() + ")");
}
return;
}
// i2pd bug?
if (_message.getSearchKey().equals(Hash.FAKE_HASH)) {
if (_log.shouldWarn())
_log.warn("Zero lookup", new Exception());
getContext().statManager().addRateData("netDb.DLMAllZeros", 1);
return;
}
DatabaseLookupMessage.Type lookupType = _message.getSearchType();
// only lookup once, then cast to correct type
DatabaseEntry dbe = getContext().netDb().lookupLocally(_message.getSearchKey());
if (dbe != null && dbe.getType() == DatabaseEntry.KEY_TYPE_LEASESET && (lookupType == DatabaseLookupMessage.Type.ANY || lookupType == DatabaseLookupMessage.Type.LS)) {
LeaseSet ls = (LeaseSet) dbe;
// We have to be very careful here to decide whether or not to send out the leaseSet,
// to avoid anonymity vulnerabilities.
// As this is complex, lots of comments follow...
boolean isLocal = getContext().clientManager().isLocal(ls.getDestination());
boolean shouldPublishLocal = isLocal && getContext().clientManager().shouldPublishLeaseSet(_message.getSearchKey());
// true for received in a DatabaseStoreMessage unsolicited
if (ls.getReceivedAsPublished()) {
// Local leasesets are not handled here
if (_log.shouldLog(Log.INFO))
_log.info("We have the published LS " + _message.getSearchKey() + ", answering query");
getContext().statManager().addRateData("netDb.lookupsMatchedReceivedPublished", 1);
sendData(_message.getSearchKey(), ls, fromKey, _message.getReplyTunnel());
} else if (shouldPublishLocal && answerAllQueries()) {
// We are floodfill, and this is our local leaseset, and we publish it.
// Only send it out if it is in our estimated keyspace.
// For this, we do NOT use their dontInclude list as it can't be trusted
// (i.e. it could mess up the closeness calculation)
Set<Hash> closestHashes = getContext().netDb().findNearestRouters(_message.getSearchKey(), CLOSENESS_THRESHOLD, null);
if (weAreClosest(closestHashes)) {
// It's in our keyspace, so give it to them
if (_log.shouldLog(Log.INFO))
_log.info("We have local LS " + _message.getSearchKey() + ", answering query, in our keyspace");
getContext().statManager().addRateData("netDb.lookupsMatchedLocalClosest", 1);
sendData(_message.getSearchKey(), ls, fromKey, _message.getReplyTunnel());
} else {
// Lie, pretend we don't have it
if (_log.shouldLog(Log.INFO))
_log.info("We have local LS " + _message.getSearchKey() + ", NOT answering query, out of our keyspace");
getContext().statManager().addRateData("netDb.lookupsMatchedLocalNotClosest", 1);
Set<Hash> routerHashSet = getNearestRouters(lookupType);
sendClosest(_message.getSearchKey(), routerHashSet, fromKey, _message.getReplyTunnel());
}
} else {
// Lie, pretend we don't have it
if (_log.shouldLog(Log.INFO))
_log.info("We have LS " + _message.getSearchKey() + ", NOT answering query - local? " + isLocal + " shouldPublish? " + shouldPublishLocal + " RAP? " + ls.getReceivedAsPublished() + " RAR? " + ls.getReceivedAsReply());
getContext().statManager().addRateData("netDb.lookupsMatchedRemoteNotClosest", 1);
Set<Hash> routerHashSet = getNearestRouters(lookupType);
sendClosest(_message.getSearchKey(), routerHashSet, fromKey, _message.getReplyTunnel());
}
} else if (dbe != null && dbe.getType() == DatabaseEntry.KEY_TYPE_ROUTERINFO && lookupType != DatabaseLookupMessage.Type.LS) {
RouterInfo info = (RouterInfo) dbe;
if (info.isCurrent(EXPIRE_DELAY)) {
if ((info.isHidden()) || (isUnreachable(info) && !publishUnreachable())) {
if (_log.shouldLog(Log.DEBUG))
_log.debug("Not answering a query for a netDb peer who isn't reachable");
Set<Hash> us = Collections.singleton(getContext().routerHash());
sendClosest(_message.getSearchKey(), us, fromKey, _message.getReplyTunnel());
} else {
// send that routerInfo to the _message.getFromHash peer
if (_log.shouldLog(Log.DEBUG))
_log.debug("We do have key " + _message.getSearchKey() + " locally as a router info. sending to " + fromKey);
sendData(_message.getSearchKey(), info, fromKey, _message.getReplyTunnel());
}
} else {
// expired locally - return closest peer hashes
Set<Hash> routerHashSet = getNearestRouters(lookupType);
if (_log.shouldLog(Log.DEBUG))
_log.debug("Expired " + _message.getSearchKey() + " locally. sending back " + routerHashSet.size() + " peers to " + fromKey);
sendClosest(_message.getSearchKey(), routerHashSet, fromKey, _message.getReplyTunnel());
}
} else {
// not found locally - return closest peer hashes
Set<Hash> routerHashSet = getNearestRouters(lookupType);
if (_log.shouldLog(Log.DEBUG))
_log.debug("We do not have key " + _message.getSearchKey() + " locally. sending back " + routerHashSet.size() + " peers to " + fromKey);
sendClosest(_message.getSearchKey(), routerHashSet, fromKey, _message.getReplyTunnel());
}
}
use of net.i2p.data.LeaseSet in project i2p.i2p by i2p.
the class FloodOnlyLookupMatchJob method setMessage.
public void setMessage(I2NPMessage message) {
if (message instanceof DatabaseSearchReplyMessage) {
// DSRM processing now in FloodOnlyLookupSelector instead of here,
// a dsrm is only passed in when there are no more lookups remaining
// so that all DSRM's are processed, not just the last one.
_search.failed();
return;
}
try {
DatabaseStoreMessage dsm = (DatabaseStoreMessage) message;
if (_log.shouldLog(Log.INFO))
_log.info(_search.getJobId() + ": got a DSM for " + dsm.getKey().toBase64());
// Should we just pass the DataStructure directly back to somebody?
if (dsm.getEntry().getType() == DatabaseEntry.KEY_TYPE_LEASESET) {
// Since HFDSMJ wants to setReceivedAsPublished(), we have to
// set a flag saying this was really the result of a query,
// so don't do that.
LeaseSet ls = (LeaseSet) dsm.getEntry();
ls.setReceivedAsReply();
getContext().netDb().store(dsm.getKey(), ls);
} else {
getContext().netDb().store(dsm.getKey(), (RouterInfo) dsm.getEntry());
}
} catch (UnsupportedCryptoException uce) {
_search.failed();
return;
} catch (IllegalArgumentException iae) {
if (_log.shouldLog(Log.WARN))
_log.warn(_search.getJobId() + ": Received an invalid store reply", iae);
}
}
use of net.i2p.data.LeaseSet in project i2p.i2p by i2p.
the class KademliaNetworkDatabaseFacade method lookupLeaseSetLocally.
/**
* Use lookupDestination() if you don't need the LS or don't need it validated.
*/
public LeaseSet lookupLeaseSetLocally(Hash key) {
if (!_initialized)
return null;
DatabaseEntry ds = _ds.get(key);
if (ds != null) {
if (ds.getType() == DatabaseEntry.KEY_TYPE_LEASESET) {
LeaseSet ls = (LeaseSet) ds;
if (ls.isCurrent(Router.CLOCK_FUDGE_FACTOR)) {
return ls;
} else {
fail(key);
// this was an interesting key, so either refetch it or simply explore with it
_exploreKeys.add(key);
return null;
}
} else {
// _log.debug("Looking for a lease set [" + key + "] but it ISN'T a leaseSet! " + ds, new Exception("Who thought that router was a lease?"));
return null;
}
} else {
return null;
}
}
use of net.i2p.data.LeaseSet in project i2p.i2p by i2p.
the class KademliaNetworkDatabaseFacade method store.
/**
* Store the leaseSet.
*
* If the store fails due to unsupported crypto, it will negative cache
* the hash until restart.
*
* @throws IllegalArgumentException if the leaseSet is not valid
* @throws UnsupportedCryptoException if that's why it failed.
* @return previous entry or null
*/
public LeaseSet store(Hash key, LeaseSet leaseSet) throws IllegalArgumentException {
if (!_initialized)
return null;
LeaseSet rv = null;
try {
rv = (LeaseSet) _ds.get(key);
if ((rv != null) && (rv.equals(leaseSet))) {
// if it hasn't changed, no need to do anything
return rv;
}
} catch (ClassCastException cce) {
throw new IllegalArgumentException("Attempt to replace RI with " + leaseSet);
}
// todo allow non-exp to overwrite exp
if (rv != null && !leaseSet.getDestination().equals(rv.getDestination()))
throw new IllegalArgumentException("LS Hash collision");
String err = validate(key, leaseSet);
if (err != null)
throw new IllegalArgumentException("Invalid store attempt - " + err);
_ds.put(key, leaseSet);
return rv;
}
Aggregations