use of net.i2p.data.DatabaseEntry in project i2p.i2p by i2p.
the class TransientDataStore method put.
/**
* @param data must be validated before here
* @return success
*/
public boolean put(Hash key, DatabaseEntry data) {
if (data == null)
return false;
if (_log.shouldLog(Log.DEBUG))
_log.debug("Storing key " + key);
DatabaseEntry old = _data.putIfAbsent(key, data);
boolean rv = false;
if (data.getType() == DatabaseEntry.KEY_TYPE_ROUTERINFO) {
// Don't do this here so we don't reset it at router startup;
// the StoreMessageJob calls this
// _context.profileManager().heardAbout(key);
RouterInfo ri = (RouterInfo) data;
if (old != null) {
RouterInfo ori = (RouterInfo) old;
if (ri.getPublished() < ori.getPublished()) {
if (_log.shouldLog(Log.INFO))
_log.info("Almost clobbered an old router! " + key + ": [old published on " + new Date(ori.getPublished()) + " new on " + new Date(ri.getPublished()) + ']');
} else if (ri.getPublished() == ori.getPublished()) {
if (_log.shouldLog(Log.INFO))
_log.info("Duplicate " + key);
} else {
if (_log.shouldLog(Log.INFO))
_log.info("Updated the old router for " + key + ": [old published on " + new Date(ori.getPublished()) + " new on " + new Date(ri.getPublished()) + ']');
_data.put(key, data);
rv = true;
}
} else {
if (_log.shouldLog(Log.INFO))
_log.info("New router for " + key + ": published on " + new Date(ri.getPublished()));
rv = true;
}
} else if (data.getType() == DatabaseEntry.KEY_TYPE_LEASESET) {
LeaseSet ls = (LeaseSet) data;
if (old != null) {
LeaseSet ols = (LeaseSet) old;
if (ls.getEarliestLeaseDate() < ols.getEarliestLeaseDate()) {
if (_log.shouldLog(Log.INFO))
_log.info("Almost clobbered an old leaseSet! " + key + ": [old expires " + new Date(ols.getEarliestLeaseDate()) + " new on " + new Date(ls.getEarliestLeaseDate()) + ']');
} else if (ls.getEarliestLeaseDate() == ols.getEarliestLeaseDate()) {
if (_log.shouldLog(Log.INFO))
_log.info("Duplicate " + key);
} else {
if (_log.shouldLog(Log.INFO)) {
_log.info("Updated old leaseSet " + key + ": [old expires " + new Date(ols.getEarliestLeaseDate()) + " new on " + new Date(ls.getEarliestLeaseDate()) + ']');
if (_log.shouldLog(Log.DEBUG))
_log.debug("RAP? " + ls.getReceivedAsPublished() + " RAR? " + ls.getReceivedAsReply());
}
_data.put(key, data);
rv = true;
}
} else {
if (_log.shouldLog(Log.INFO)) {
_log.info("New leaseset for " + key + ": expires " + new Date(ls.getEarliestLeaseDate()));
if (_log.shouldLog(Log.DEBUG))
_log.debug("RAP? " + ls.getReceivedAsPublished() + " RAR? " + ls.getReceivedAsReply());
}
rv = true;
}
}
return rv;
}
use of net.i2p.data.DatabaseEntry in project i2p.i2p by i2p.
the class TransientDataStore method toString.
@Override
public String toString() {
StringBuilder buf = new StringBuilder();
buf.append("Transient DataStore: ").append(_data.size()).append("\nKeys: ");
for (Map.Entry<Hash, DatabaseEntry> e : _data.entrySet()) {
Hash key = e.getKey();
DatabaseEntry dp = e.getValue();
buf.append("\n\t*Key: ").append(key.toString()).append("\n\tContent: ").append(dp.toString());
}
buf.append("\n");
return buf.toString();
}
use of net.i2p.data.DatabaseEntry in project i2p.i2p by i2p.
the class ExpireRoutersJob method expireKeys.
/**
* Run through all of the known peers and pick ones that have really old
* routerInfo publish dates, excluding ones that we are connected to,
* so that they can be failed
*
* @return number removed
*/
private int expireKeys() {
Set<Hash> keys = _facade.getAllRouters();
keys.remove(getContext().routerHash());
if (keys.size() < 150)
return 0;
int removed = 0;
for (Hash key : keys) {
// Don't expire anybody we are connected to
if (!getContext().commSystem().isEstablished(key)) {
DatabaseEntry e = _facade.lookupLocallyWithoutValidation(key);
if (e != null && e.getType() == DatabaseEntry.KEY_TYPE_ROUTERINFO) {
try {
if (_facade.validate((RouterInfo) e) != null) {
_facade.dropAfterLookupFailed(key);
removed++;
}
} catch (IllegalArgumentException iae) {
_facade.dropAfterLookupFailed(key);
removed++;
}
}
}
}
return removed;
}
use of net.i2p.data.DatabaseEntry in project i2p.i2p by i2p.
the class HandleFloodfillDatabaseStoreMessageJob method runJob.
public void runJob() {
// if (_log.shouldLog(Log.DEBUG))
// _log.debug("Handling database store message");
long recvBegin = System.currentTimeMillis();
String invalidMessage = null;
// set if invalid store but not his fault
boolean dontBlamePeer = false;
boolean wasNew = false;
RouterInfo prevNetDb = null;
Hash key = _message.getKey();
DatabaseEntry entry = _message.getEntry();
if (entry.getType() == DatabaseEntry.KEY_TYPE_LEASESET) {
getContext().statManager().addRateData("netDb.storeLeaseSetHandled", 1);
if (_log.shouldLog(Log.INFO))
_log.info("Handling dbStore of leaseset " + _message);
try {
// storing the other guy's leaseset, it will confuse us badly.
if (getContext().clientManager().isLocal(key)) {
// getContext().statManager().addRateData("netDb.storeLocalLeaseSetAttempt", 1, 0);
// throw rather than return, so that we send the ack below (prevent easy attack)
dontBlamePeer = true;
throw new IllegalArgumentException("Peer attempted to store local leaseSet: " + key.toBase64().substring(0, 4));
}
LeaseSet ls = (LeaseSet) entry;
// See ../HDLMJ for more info
if (!ls.getReceivedAsReply())
ls.setReceivedAsPublished(true);
// boolean rap = ls.getReceivedAsPublished();
// if (_log.shouldLog(Log.INFO))
// _log.info("oldrap? " + oldrap + " oldrar? " + oldrar + " newrap? " + rap);
LeaseSet match = getContext().netDb().store(key, ls);
if (match == null) {
wasNew = true;
} else if (match.getEarliestLeaseDate() < ls.getEarliestLeaseDate()) {
wasNew = true;
if (match.getReceivedAsPublished())
ls.setReceivedAsPublished(true);
} else {
wasNew = false;
// The FloodOnlyLookupSelector goes away after the first good reply
// So on the second reply, FloodOnlyMatchJob is not called to set ReceivedAsReply.
// So then we think it's an unsolicited store.
// So we should skip this.
// If the 2nd reply is newer than the first, ReceivedAsPublished will be set incorrectly,
// that will hopefully be rare.
// A more elaborate solution would be a List of recent ReceivedAsReply LeaseSets, with receive time ?
// A real unsolicited store is likely to be new - hopefully...
// if (!ls.getReceivedAsReply())
// match.setReceivedAsPublished(true);
}
} catch (UnsupportedCryptoException uce) {
invalidMessage = uce.getMessage();
dontBlamePeer = true;
} catch (IllegalArgumentException iae) {
invalidMessage = iae.getMessage();
}
} else if (entry.getType() == DatabaseEntry.KEY_TYPE_ROUTERINFO) {
RouterInfo ri = (RouterInfo) entry;
getContext().statManager().addRateData("netDb.storeRouterInfoHandled", 1);
if (_log.shouldLog(Log.INFO))
_log.info("Handling dbStore of router " + key + " with publishDate of " + new Date(ri.getPublished()));
try {
// somebody has our keys...
if (getContext().routerHash().equals(key)) {
// getContext().statManager().addRateData("netDb.storeLocalRouterInfoAttempt", 1, 0);
// This is initiated by PeerTestJob from another peer
// throw rather than return, so that we send the ack below (prevent easy attack)
dontBlamePeer = true;
throw new IllegalArgumentException("Peer attempted to store our RouterInfo");
}
getContext().profileManager().heardAbout(key);
prevNetDb = getContext().netDb().store(key, ri);
wasNew = ((null == prevNetDb) || (prevNetDb.getPublished() < ri.getPublished()));
// Check new routerinfo address against blocklist
if (wasNew) {
if (prevNetDb == null) {
if ((!getContext().banlist().isBanlistedForever(key)) && getContext().blocklist().isBlocklisted(ri) && _log.shouldLog(Log.WARN))
_log.warn("Blocklisting new peer " + key + ' ' + ri);
} else {
Collection<RouterAddress> oldAddr = prevNetDb.getAddresses();
Collection<RouterAddress> newAddr = ri.getAddresses();
if ((!newAddr.equals(oldAddr)) && (!getContext().banlist().isBanlistedForever(key)) && getContext().blocklist().isBlocklisted(ri) && _log.shouldLog(Log.WARN))
_log.warn("New address received, Blocklisting old peer " + key + ' ' + ri);
}
}
} catch (UnsupportedCryptoException uce) {
invalidMessage = uce.getMessage();
dontBlamePeer = true;
} catch (IllegalArgumentException iae) {
invalidMessage = iae.getMessage();
}
} else {
if (_log.shouldLog(Log.ERROR))
_log.error("Invalid DatabaseStoreMessage data type - " + entry.getType() + ": " + _message);
// don't ack or flood
return;
}
long recvEnd = System.currentTimeMillis();
getContext().statManager().addRateData("netDb.storeRecvTime", recvEnd - recvBegin);
// TODO any cases where we shouldn't?
if (_message.getReplyToken() > 0)
sendAck(key);
long ackEnd = System.currentTimeMillis();
if (_from != null)
_fromHash = _from.getHash();
if (_fromHash != null) {
if (invalidMessage == null || dontBlamePeer) {
getContext().profileManager().dbStoreReceived(_fromHash, wasNew);
getContext().statManager().addRateData("netDb.storeHandled", ackEnd - recvEnd);
} else {
// Should we record in the profile?
if (_log.shouldLog(Log.WARN))
_log.warn("Peer " + _fromHash.toBase64() + " sent bad data: " + invalidMessage);
}
} else if (invalidMessage != null && !dontBlamePeer) {
if (_log.shouldLog(Log.WARN))
_log.warn("Unknown peer sent bad data: " + invalidMessage);
}
// flood it
if (invalidMessage == null && getContext().netDb().floodfillEnabled() && _message.getReplyToken() > 0) {
if (wasNew) {
// Note this does not throttle the ack above
if (_facade.shouldThrottleFlood(key)) {
if (_log.shouldLog(Log.WARN))
_log.warn("Too many recent stores, not flooding key: " + key);
getContext().statManager().addRateData("netDb.floodThrottled", 1);
return;
}
long floodBegin = System.currentTimeMillis();
_facade.flood(_message.getEntry());
// ERR: see comment in HandleDatabaseLookupMessageJob regarding hidden mode
// else if (!_message.getRouterInfo().isHidden())
long floodEnd = System.currentTimeMillis();
getContext().statManager().addRateData("netDb.storeFloodNew", floodEnd - floodBegin, 60 * 1000);
} else {
// don't flood it *again*
getContext().statManager().addRateData("netDb.storeFloodOld", 1);
}
}
}
use of net.i2p.data.DatabaseEntry in project i2p.i2p by i2p.
the class KademliaNetworkDatabaseFacade method unpublish.
public void unpublish(LeaseSet localLeaseSet) {
if (!_initialized)
return;
Hash h = localLeaseSet.getDestination().calculateHash();
DatabaseEntry data = _ds.remove(h);
if (data == null) {
if (_log.shouldLog(Log.WARN))
_log.warn("Unpublished a lease we don't know...: " + localLeaseSet);
} else {
if (_log.shouldLog(Log.INFO))
_log.info("Unpublished a lease: " + h);
}
// now update it if we can to remove any leases
}
Aggregations