Search in sources :

Example 11 with DatabaseEntry

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;
}
Also used : LeaseSet(net.i2p.data.LeaseSet) RouterInfo(net.i2p.data.router.RouterInfo) DatabaseEntry(net.i2p.data.DatabaseEntry) Date(java.util.Date)

Example 12 with DatabaseEntry

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();
}
Also used : DatabaseEntry(net.i2p.data.DatabaseEntry) Hash(net.i2p.data.Hash) Map(java.util.Map) ConcurrentHashMap(java.util.concurrent.ConcurrentHashMap)

Example 13 with DatabaseEntry

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;
}
Also used : RouterInfo(net.i2p.data.router.RouterInfo) DatabaseEntry(net.i2p.data.DatabaseEntry) Hash(net.i2p.data.Hash)

Example 14 with DatabaseEntry

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);
        }
    }
}
Also used : LeaseSet(net.i2p.data.LeaseSet) RouterInfo(net.i2p.data.router.RouterInfo) Collection(java.util.Collection) DatabaseEntry(net.i2p.data.DatabaseEntry) Hash(net.i2p.data.Hash) Date(java.util.Date)

Example 15 with DatabaseEntry

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
}
Also used : DatabaseEntry(net.i2p.data.DatabaseEntry) Hash(net.i2p.data.Hash)

Aggregations

DatabaseEntry (net.i2p.data.DatabaseEntry)16 Hash (net.i2p.data.Hash)11 RouterInfo (net.i2p.data.router.RouterInfo)9 LeaseSet (net.i2p.data.LeaseSet)4 Date (java.util.Date)2 HashSet (java.util.HashSet)2 DatabaseStoreMessage (net.i2p.data.i2np.DatabaseStoreMessage)2 ArrayList (java.util.ArrayList)1 Collection (java.util.Collection)1 Map (java.util.Map)1 NoSuchElementException (java.util.NoSuchElementException)1 Set (java.util.Set)1 ConcurrentHashMap (java.util.concurrent.ConcurrentHashMap)1 DatabaseLookupMessage (net.i2p.data.i2np.DatabaseLookupMessage)1 DatabaseSearchReplyMessage (net.i2p.data.i2np.DatabaseSearchReplyMessage)1 I2NPMessage (net.i2p.data.i2np.I2NPMessage)1