Changeset 68d25af


Ignore:
Timestamp:
Jun 9, 2013 2:42:51 PM (7 years ago)
Author:
zzz <zzz@…>
Branches:
master
Children:
6241333
Parents:
182fe90
Message:
  • NetDB: Prep for leasesets with different expire times
    • Add new I2CP RequestVariableLeaseSetMessage?
    • Send RVLSM if client supports it; handle on client side; disabled by default for the moment.
    • Add LeaseSet?.getLatestLeaseDate()
    • Check latest, not earliest, date too far in future in KNDF.validate()
    • Check latest date too far in past in KNDF.validate()
    • Only check gateway and tunnel ID for equality in OCMOSJ lease caching to reduce churn
    • Split up KNDF.validate(RI) for efficiency, don't need to check signature, netid, etc. before lookups, only on store
    • Remove enforeNetID config
    • Fix major bug causing newer leasesets to be treated as older, and not stored or published
    • Increase max adjustment time of earliest lease
    • TransientDataStore? cleanups
    • RouterInfo? and LeaseSet? equals() speedups
Files:
2 added
16 edited

Legend:

Unmodified
Added
Removed
  • apps/routerconsole/java/src/net/i2p/router/web/NetDbRenderer.java

    r182fe90 r68d25af  
    1818import java.util.Comparator;
    1919import java.util.Date;
    20 import java.util.Iterator;
    2120import java.util.List;
    2221import java.util.Locale;
     
    2827import net.i2p.data.Destination;
    2928import net.i2p.data.Hash;
     29import net.i2p.data.Lease;
    3030import net.i2p.data.LeaseSet;
    3131import net.i2p.data.RouterAddress;
     
    8080        } else {
    8181            boolean notFound = true;
    82             Set routers = _context.netDb().getRouters();
    83             for (Iterator iter = routers.iterator(); iter.hasNext(); ) {
    84                 RouterInfo ri = (RouterInfo)iter.next();
     82            Set<RouterInfo> routers = _context.netDb().getRouters();
     83            for (RouterInfo ri : routers) {
    8584                Hash key = ri.getIdentity().getHash();
    8685                if (key.toBase64().startsWith(routerPrefix)) {
     
    153152            }
    154153            buf.append(")</b><br>\n");
    155             long exp = ls.getEarliestLeaseDate()-now;
     154            long exp = ls.getLatestLeaseDate()-now;
    156155            if (exp > 0)
    157                 buf.append(_("Expires in {0}", DataHelper.formatDuration2(exp))).append("<br>\n");
     156                buf.append(_("Expires in {0}", DataHelper.formatDuration2(exp)));
    158157            else
    159                 buf.append(_("Expired {0} ago", DataHelper.formatDuration2(0-exp))).append("<br>\n");
     158                buf.append(_("Expired {0} ago", DataHelper.formatDuration2(0-exp)));
     159            buf.append("<br>\n");
    160160            if (debug) {
    161161                buf.append("RAP? " + ls.getReceivedAsPublished());
     
    172172            }
    173173            for (int i = 0; i < ls.getLeaseCount(); i++) {
    174                 buf.append(_("Lease")).append(' ').append(i + 1).append(": " + _("Gateway") + ' ');
    175                 buf.append(_context.commSystem().renderPeerHTML(ls.getLease(i).getGateway()));
    176                 buf.append(' ' + _("Tunnel") + ' ').append(ls.getLease(i).getTunnelId().getTunnelId()).append("<br>\n");
     174                Lease lease = ls.getLease(i);
     175                buf.append(_("Lease")).append(' ').append(i + 1).append(": ").append(_("Gateway")).append(' ');
     176                buf.append(_context.commSystem().renderPeerHTML(lease.getGateway()));
     177                buf.append(' ').append(_("Tunnel")).append(' ').append(lease.getTunnelId().getTunnelId()).append(' ');
     178                if (debug) {
     179                    long exl = lease.getEndDate().getTime() - now;
     180                    if (exl > 0)
     181                        buf.append(_("Expires in {0}", DataHelper.formatDuration2(exl)));
     182                    else
     183                        buf.append(_("Expired {0} ago", DataHelper.formatDuration2(0-exl)));
     184                }
     185                buf.append("<br>\n");
    177186            }
    178187            buf.append("<hr>\n");
     
    254263        Set<RouterInfo> routers = new TreeSet(new RouterInfoComparator());
    255264        routers.addAll(_context.netDb().getRouters());
    256         for (Iterator iter = routers.iterator(); iter.hasNext(); ) {
    257             RouterInfo ri = (RouterInfo)iter.next();
     265        for (RouterInfo ri : routers) {
    258266            Hash key = ri.getIdentity().getHash();
    259267            boolean isUs = key.equals(us);
     
    392400            buf.append(" src=\"/flags.jsp?c=").append(country).append("\"> ");
    393401        }
    394         for (Iterator iter = info.getAddresses().iterator(); iter.hasNext(); ) {
    395             RouterAddress addr = (RouterAddress)iter.next();
     402        for (RouterAddress addr : info.getAddresses()) {
    396403            String style = addr.getTransportStyle();
    397404            buf.append("<b>").append(DataHelper.stripHTML(style)).append(":</b> ");
  • core/java/src/net/i2p/client/I2PClientMessageHandlerMap.java

    r182fe90 r68d25af  
    1717import net.i2p.data.i2cp.MessageStatusMessage;
    1818import net.i2p.data.i2cp.RequestLeaseSetMessage;
     19import net.i2p.data.i2cp.RequestVariableLeaseSetMessage;
    1920import net.i2p.data.i2cp.SessionStatusMessage;
    2021import net.i2p.data.i2cp.SetDateMessage;
     
    4142        highest = Math.max(highest, DestReplyMessage.MESSAGE_TYPE);
    4243        highest = Math.max(highest, BandwidthLimitsMessage.MESSAGE_TYPE);
     44        highest = Math.max(highest, RequestVariableLeaseSetMessage.MESSAGE_TYPE);
    4345       
    4446        _handlers = new I2CPMessageHandler[highest+1];
     
    5153        _handlers[DestReplyMessage.MESSAGE_TYPE] = new DestReplyMessageHandler(context);
    5254        _handlers[BandwidthLimitsMessage.MESSAGE_TYPE] = new BWLimitsMessageHandler(context);
     55        _handlers[RequestVariableLeaseSetMessage.MESSAGE_TYPE] = new RequestVariableLeaseSetMessageHandler(context);
    5356    }
    5457
  • core/java/src/net/i2p/client/RequestLeaseSetMessageHandler.java

    r182fe90 r68d25af  
    3030
    3131/**
    32  * Handle I2CP RequestLeaseSetMessage from the router by granting all leases
     32 * Handle I2CP RequestLeaseSetMessage from the router by granting all leases,
     33 * using the specified expiration time for each lease.
    3334 *
    3435 * @author jrandom
     
    3839
    3940    public RequestLeaseSetMessageHandler(I2PAppContext context) {
    40         super(context, RequestLeaseSetMessage.MESSAGE_TYPE);
     41        this(context, RequestLeaseSetMessage.MESSAGE_TYPE);
     42    }
     43
     44    /**
     45     *  For extension
     46     *  @since 0.9.7
     47     */
     48    protected RequestLeaseSetMessageHandler(I2PAppContext context, int messageType) {
     49        super(context, messageType);
    4150        // not clear why there would ever be more than one
    4251        _existingLeaseSets = new ConcurrentHashMap(4);
     
    5665            leaseSet.addLease(lease);
    5766        }
     67        signLeaseSet(leaseSet, session);
     68    }
     69
     70    /**
     71     *  Finish creating and signing the new LeaseSet
     72     *  @since 0.9.7
     73     */
     74    protected void signLeaseSet(LeaseSet leaseSet, I2PSessionImpl session) {
    5875        // also, if this session is connected to multiple routers, include other leases here
    5976        leaseSet.setDestination(session.getMyDestination());
  • core/java/src/net/i2p/data/LeaseSet.java

    r182fe90 r68d25af  
    9494    }
    9595
     96    /**
     97     * Same as getEarliestLeaseDate()
     98     */
    9699    public long getDate() {
    97100        return getEarliestLeaseDate();
     
    199202
    200203    /**
    201      * Retrieve the end date of the earliest lease include in this leaseSet.
     204     * Retrieve the end date of the earliest lease included in this leaseSet.
    202205     * This is the date that should be used in comparisons for leaseSet age - to
    203206     * determine which LeaseSet was published more recently (later earliestLeaseSetDate
     
    210213            return -1;
    211214        return _firstExpiration;
     215    }
     216
     217    /**
     218     * Retrieve the end date of the latest lease included in this leaseSet.
     219     * This is the date used in isCurrent().
     220     *
     221     * @return latest end date of any lease in the set, or 0 if there are no leases
     222     * @since 0.9.7
     223     */
     224    public long getLatestLeaseDate() {
     225        return _lastExpiration;
    212226    }
    213227
     
    288302    /**
    289303     *  This does NOT validate the signature
     304     *
     305     *  @throws IllegalStateException if called more than once or Destination already set
    290306     */
    291307    public void readBytes(InputStream in) throws DataFormatException, IOException {
     308        if (_destination != null)
     309            throw new IllegalStateException();
    292310        _destination = new Destination();
    293311        _destination.readBytes(in);
     
    298316            throw new DataFormatException("Too many leases - max is " + MAX_LEASES);
    299317        //_version = DataHelper.readLong(in, 4);
    300         _leases.clear();
    301318        for (int i = 0; i < numLeases; i++) {
    302319            Lease lease = new Lease();
     
    345362        if ((object == null) || !(object instanceof LeaseSet)) return false;
    346363        LeaseSet ls = (LeaseSet) object;
    347         return DataHelper.eq(getEncryptionKey(), ls.getEncryptionKey()) &&
    348         //DataHelper.eq(getVersion(), ls.getVersion()) &&
    349                DataHelper.eq(_leases, ls._leases) && DataHelper.eq(_signature, ls.getSignature())
     364        return
     365               DataHelper.eq(_signature, ls.getSignature())
     366               && DataHelper.eq(_leases, ls._leases)
     367               && DataHelper.eq(getEncryptionKey(), ls.getEncryptionKey())
    350368               && DataHelper.eq(_signingKey, ls.getSigningKey())
    351369               && DataHelper.eq(_destination, ls.getDestination());
     
    372390        buf.append("\n\tLeases: #").append(getLeaseCount());
    373391        for (int i = 0; i < getLeaseCount(); i++)
    374             buf.append("\n\t\tLease (").append(i).append("): ").append(getLease(i));
     392            buf.append("\n\t\t").append(getLease(i));
    375393        buf.append("]");
    376394        return buf.toString();
  • core/java/src/net/i2p/data/RouterInfo.java

    r182fe90 r68d25af  
    593593        if ((object == null) || !(object instanceof RouterInfo)) return false;
    594594        RouterInfo info = (RouterInfo) object;
    595         return DataHelper.eq(_identity, info.getIdentity())
     595        return
     596               _published == info.getPublished()
    596597               && DataHelper.eq(_signature, info.getSignature())
    597                && _published == info.getPublished();
     598               && DataHelper.eq(_identity, info.getIdentity());
    598599               // Let's speed up the NetDB
    599600               //&& DataHelper.eq(_addresses, info.getAddresses())
  • core/java/src/net/i2p/data/i2cp/I2CPMessageHandler.java

    r182fe90 r68d25af  
    7878        case RequestLeaseSetMessage.MESSAGE_TYPE:
    7979            return new RequestLeaseSetMessage();
     80        case RequestVariableLeaseSetMessage.MESSAGE_TYPE:
     81            return new RequestVariableLeaseSetMessage();
    8082        case SendMessageMessage.MESSAGE_TYPE:
    8183            return new SendMessageMessage();
  • core/java/src/net/i2p/data/i2cp/RequestLeaseSetMessage.java

    r182fe90 r68d25af  
    5151
    5252    public Hash getRouter(int endpoint) {
    53         if ((endpoint < 0) || (_endpoints.size() < endpoint)) return null;
     53        if ((endpoint < 0) || (_endpoints.size() <= endpoint)) return null;
    5454        return _endpoints.get(endpoint).getRouter();
    5555    }
    5656
    5757    public TunnelId getTunnelId(int endpoint) {
    58         if ((endpoint < 0) || (_endpoints.size() < endpoint)) return null;
     58        if ((endpoint < 0) || (_endpoints.size() <= endpoint)) return null;
    5959        return _endpoints.get(endpoint).getTunnelId();
    6060    }
     
    6262    /** @deprecated unused - presumably he meant remove? */
    6363    public void remoteEndpoint(int endpoint) {
    64         if ((endpoint >= 0) && (endpoint < _endpoints.size())) _endpoints.remove(endpoint);
     64        if ((endpoint >= 0) && (endpoint <= _endpoints.size())) _endpoints.remove(endpoint);
    6565    }
    6666
  • history.txt

    r182fe90 r68d25af  
     12013-06-09 zzz
     2 * NetDB: Prep for leasesets with different expire times
     3   - Add new I2CP RequestVariableLeaseSetMessage
     4   - Send RVLSM if client supports it; handle on client side;
     5     disabled by default for the moment.
     6   - Add LeaseSet.getLatestLeaseDate()
     7   - Check latest, not earliest, date too far in future in KNDF.validate()
     8   - Check latest date too far in past in KNDF.validate()
     9   - Only check gateway and tunnel ID for equality in OCMOSJ lease caching to reduce churn
     10   - Split up KNDF.validate(RI) for efficiency, don't need to check
     11     signature, netid, etc. before lookups, only on store
     12   - Remove enforeNetID config
     13   - Fix major bug causing newer leasesets to be treated as older, and not stored or published
     14   - Increase max adjustment time of earliest lease
     15   - TransientDataStore cleanups
     16   - RouterInfo and LeaseSet equals() speedups
     17
    1182013-06-07 zzz
    219 * BlockfileNamingService:
  • router/java/src/net/i2p/router/RouterVersion.java

    r182fe90 r68d25af  
    1919    public final static String ID = "Monotone";
    2020    public final static String VERSION = CoreVersion.VERSION;
    21     public final static long BUILD = 6;
     21    public final static long BUILD = 7;
    2222
    2323    /** for example "-test" */
  • router/java/src/net/i2p/router/client/RequestLeaseSetJob.java

    r182fe90 r68d25af  
    1111import java.util.Date;
    1212
     13import net.i2p.data.Lease;
    1314import net.i2p.data.LeaseSet;
     15import net.i2p.data.i2cp.I2CPMessage;
    1416import net.i2p.data.i2cp.I2CPMessageException;
    1517import net.i2p.data.i2cp.RequestLeaseSetMessage;
     18import net.i2p.data.i2cp.RequestVariableLeaseSetMessage;
    1619import net.i2p.router.Job;
    1720import net.i2p.router.JobImpl;
     
    3235    private final LeaseRequestState _requestState;
    3336   
     37    private static final long MAX_FUDGE = 2*1000;
     38
     39    /** temp for testing */
     40    private static final String PROP_VARIABLE = "router.variableLeaseExpiration";
     41    private static final boolean DFLT_VARIABLE = false;
     42
    3443    public RequestLeaseSetJob(RouterContext ctx, ClientConnectionRunner runner, LeaseRequestState state) {
    3544        super(ctx);
     
    4554        if (_runner.isDead()) return;
    4655       
    47         RequestLeaseSetMessage msg = new RequestLeaseSetMessage();
    48         long endTime = _requestState.getRequested().getEarliestLeaseDate();
    49         // Add a small number of ms (0-300) that increases as we approach the expire time.
     56        LeaseSet requested = _requestState.getRequested();
     57        long endTime = requested.getEarliestLeaseDate();
     58        // Add a small number of ms (0 to MAX_FUDGE) that increases as we approach the expire time.
    5059        // Since the earliest date functions as a version number,
    5160        // this will force the floodfill to flood each new version;
    5261        // otherwise it won't if the earliest time hasn't changed.
    53         long fudge = 300 - ((endTime - getContext().clock().now()) / 2000);
     62        long fudge = MAX_FUDGE - ((endTime - getContext().clock().now()) / (10*60*1000 / MAX_FUDGE));
     63        //if (_log.shouldLog(Log.DEBUG))
     64        //    _log.debug("Adding fudge " + fudge);
    5465        endTime += fudge;
    55         Date end = new Date(endTime);
    5666
    57         msg.setEndDate(end);
    58         msg.setSessionId(_runner.getSessionId());
    59        
    60         for (int i = 0; i < _requestState.getRequested().getLeaseCount(); i++) {
    61             msg.addEndpoint(_requestState.getRequested().getLease(i).getGateway(),
    62                             _requestState.getRequested().getLease(i).getTunnelId());
     67        I2CPMessage msg;
     68        if (getContext().getProperty(PROP_VARIABLE, DFLT_VARIABLE) &&
     69            (_runner instanceof QueuedClientConnectionRunner ||
     70             RequestVariableLeaseSetMessage.isSupported(_runner.getClientVersion()))) {
     71            // new style - leases will have individual expirations
     72            RequestVariableLeaseSetMessage rmsg = new RequestVariableLeaseSetMessage();
     73            rmsg.setSessionId(_runner.getSessionId());
     74            for (int i = 0; i < requested.getLeaseCount(); i++) {
     75                Lease lease = requested.getLease(i);
     76                if (lease.getEndDate().getTime() < endTime) {
     77                    // don't modify old object, we don't know where it came from
     78                    Lease nl = new Lease();
     79                    nl.setGateway(lease.getGateway());
     80                    nl.setTunnelId(lease.getTunnelId());
     81                    nl.setEndDate(new Date(endTime));
     82                    lease = nl;
     83                    //if (_log.shouldLog(Log.INFO))
     84                    //    _log.info("Adjusted end date to " + endTime + " for " + lease);
     85                }
     86                rmsg.addEndpoint(lease);
     87            }
     88            msg = rmsg;
     89        } else {
     90            // old style - all leases will have same expiration
     91            RequestLeaseSetMessage rmsg = new RequestLeaseSetMessage();
     92            Date end = new Date(endTime);
     93            rmsg.setEndDate(end);
     94            rmsg.setSessionId(_runner.getSessionId());
     95            for (int i = 0; i < requested.getLeaseCount(); i++) {
     96                Lease lease = requested.getLease(i);
     97                rmsg.addEndpoint(lease.getGateway(),
     98                                 lease.getTunnelId());
     99            }
     100            msg = rmsg;
    63101        }
    64102       
  • router/java/src/net/i2p/router/message/OutboundClientMessageOneShotJob.java

    r182fe90 r68d25af  
    305305                    for (int i = 0; i < _leaseSet.getLeaseCount(); i++) {
    306306                        Lease lease = _leaseSet.getLease(i);
    307                         if (_lease.equals(lease)) {
     307                        // Don't use Lease.equals(), as that compares expiration time too,
     308                        // and that time may change in subsequent publication
     309                        //if (_lease.equals(lease)) {
     310                        if (_lease.getTunnelId().equals(lease.getTunnelId()) &&
     311                            _lease.getGateway().equals(lease.getGateway())) {
    308312                            if (_log.shouldLog(Log.INFO))
    309313                                _log.info(getJobId() + ": Found in cache - lease for " + _toString);
  • router/java/src/net/i2p/router/networkdb/kademlia/KademliaNetworkDatabaseFacade.java

    r182fe90 r68d25af  
    9797    private static final boolean QUIET = false;
    9898   
    99     public static final String PROP_ENFORCE_NETID = "router.networkDatabase.enforceNetId";
    100     private static final boolean DEFAULT_ENFORCE_NETID = false;
    101     private boolean _enforceNetId = DEFAULT_ENFORCE_NETID;
    102    
    10399    public final static String PROP_DB_DIR = "router.networkDatabase.dbDir";
    104100    public final static String DEFAULT_DB_DIR = "netDb";
     
    144140        _publishingLeaseSets = new HashMap(8);
    145141        _activeRequests = new HashMap(8);
    146         _enforceNetId = DEFAULT_ENFORCE_NETID;
    147142        _reseedChecker = new ReseedChecker(context);
    148143        context.statManager().createRateStat("netDb.lookupDeferred", "how many lookups are deferred?", "NetworkDatabase", new long[] { 60*60*1000 });
     
    224219            _dbDir = DEFAULT_DB_DIR;
    225220        }
    226         String enforce = _context.getProperty(PROP_ENFORCE_NETID);
    227         if (enforce != null)
    228             _enforceNetId = Boolean.parseBoolean(enforce);
    229         else
    230             _enforceNetId = DEFAULT_ENFORCE_NETID;
    231221        _ds.restart();
    232222        _exploreKeys.clear();
     
    250240        RouterInfo ri = _context.router().getRouterInfo();
    251241        String dbDir = _context.getProperty(PROP_DB_DIR, DEFAULT_DB_DIR);
    252         String enforce = _context.getProperty(PROP_ENFORCE_NETID);
    253         if (enforce != null)
    254             _enforceNetId = Boolean.parseBoolean(enforce);
    255         else
    256             _enforceNetId = DEFAULT_ENFORCE_NETID;
    257        
    258242        _kb = new KBucketSet(_context, ri.getIdentity().getHash());
    259243        try {
     
    444428        } else if (rv.getType() == DatabaseEntry.KEY_TYPE_ROUTERINFO) {
    445429            try {
    446                 if (validate(key, (RouterInfo)rv) == null)
     430                if (validate((RouterInfo)rv) == null)
    447431                    return rv;
    448432            } catch (IllegalArgumentException iae) {}
     
    513497                boolean valid = true;
    514498                try {
    515                     valid = (null == validate(key, (RouterInfo)ds));
     499                    valid = (null == validate((RouterInfo)ds));
    516500                } catch (IllegalArgumentException iae) {
    517501                    valid = false;
     
    532516   
    533517    private static final long PUBLISH_DELAY = 3*1000;
     518
    534519    public void publish(LeaseSet localLeaseSet) {
    535520        if (!_initialized) return;
     
    565550        _context.jobQueue().removeJob(j);
    566551        j.getTiming().setStartAfter(nextTime);
     552        if (_log.shouldLog(Log.INFO))
     553            _log.info("Queueing to publish at " + (new Date(nextTime)) + ' ' + localLeaseSet);
    567554        _context.jobQueue().addJob(j);
    568555    }
     
    628615     * given what we know now.
    629616     *
    630      * TODO this is called several times, only check the key and signature once
     617     * Unlike for RouterInfos, this is only called once, when stored.
     618     * After that, LeaseSet.isCurrent() is used.
    631619     *
    632620     * @return reason why the entry is not valid, or null if it is valid
    633621     */
    634     String validate(Hash key, LeaseSet leaseSet) {
     622    private String validate(Hash key, LeaseSet leaseSet) {
    635623        if (!key.equals(leaseSet.getDestination().calculateHash())) {
    636624            if (_log.shouldLog(Log.ERROR))
     
    638626                          + key + ", leaseSet = " + leaseSet);
    639627            return "Key does not match leaseSet.destination - " + key.toBase64();
    640         } else if (!leaseSet.verifySignature()) {
     628        }
     629        if (!leaseSet.verifySignature()) {
    641630            if (_log.shouldLog(Log.ERROR))
    642631                _log.error("Invalid leaseSet signature!  leaseSet = " + leaseSet);
    643632            return "Invalid leaseSet signature on " + leaseSet.getDestination().calculateHash().toBase64();
    644         } else if (leaseSet.getEarliestLeaseDate() <= _context.clock().now() - 2*Router.CLOCK_FUDGE_FACTOR) {
    645             long age = _context.clock().now() - leaseSet.getEarliestLeaseDate();
     633        }
     634        long earliest = leaseSet.getEarliestLeaseDate();
     635        long latest = leaseSet.getLatestLeaseDate();
     636        long now = _context.clock().now();
     637        if (earliest <= now - 2*Router.CLOCK_FUDGE_FACTOR ||
     638            // same as the isCurrent(Router.CLOCK_FUDGE_FACTOR) test in
     639            // lookupLeaseSetLocally()
     640            latest <= now - Router.CLOCK_FUDGE_FACTOR) {
     641            long age = now - earliest;
    646642            if (_log.shouldLog(Log.WARN))
    647643                _log.warn("Old leaseSet!  not storing it: "
    648                           + leaseSet.getDestination().calculateHash().toBase64()
    649                           + " expires on " + new Date(leaseSet.getEarliestLeaseDate()), new Exception("Rejecting store"));
     644                          + leaseSet.getDestination().calculateHash()
     645                          + " first exp. " + new Date(earliest)
     646                          + " last exp. " + new Date(latest),
     647                          new Exception("Rejecting store"));
    650648            return "Expired leaseSet for " + leaseSet.getDestination().calculateHash().toBase64()
    651649                   + " expired " + DataHelper.formatDuration(age) + " ago";
    652         } else if (leaseSet.getEarliestLeaseDate() > _context.clock().now() + (Router.CLOCK_FUDGE_FACTOR + MAX_LEASE_FUTURE)) {
    653             long age = leaseSet.getEarliestLeaseDate() - _context.clock().now();
     650        }
     651        if (latest > now + (Router.CLOCK_FUDGE_FACTOR + MAX_LEASE_FUTURE)) {
     652            long age = latest - now;
    654653            // let's not make this an error, it happens when peers have bad clocks
    655654            if (_log.shouldLog(Log.WARN))
    656655                _log.warn("LeaseSet expires too far in the future: "
    657                           + leaseSet.getDestination().calculateHash().toBase64()
     656                          + leaseSet.getDestination().calculateHash()
    658657                          + " expires " + DataHelper.formatDuration(age) + " from now");
    659658            return "Future expiring leaseSet for " + leaseSet.getDestination().calculateHash()
     
    721720     * given what we know now.
    722721     *
    723      * TODO this is called several times, only check the key and signature once
     722     * Call this only on first store, to check the key and signature once
    724723     *
    725724     * @return reason why the entry is not valid, or null if it is valid
    726725     */
    727     String validate(Hash key, RouterInfo routerInfo) throws IllegalArgumentException {
     726    private String validate(Hash key, RouterInfo routerInfo) throws IllegalArgumentException {
     727        if (!key.equals(routerInfo.getIdentity().getHash())) {
     728            if (_log.shouldLog(Log.WARN))
     729                _log.warn("Invalid store attempt! key does not match routerInfo.identity!  key = " + key + ", router = " + routerInfo);
     730            return "Key does not match routerInfo.identity";
     731        }
     732        if (!routerInfo.isValid()) {
     733            if (_log.shouldLog(Log.WARN))
     734                _log.warn("Invalid routerInfo signature!  forged router structure!  router = " + routerInfo);
     735            return "Invalid routerInfo signature";
     736        }
     737        if (routerInfo.getNetworkId() != Router.NETWORK_ID){
     738            _context.banlist().banlistRouter(key, "Not in our network");
     739            if (_log.shouldLog(Log.WARN))
     740                _log.warn("Bad network: " + routerInfo);
     741            return "Not in our network";
     742        }
     743        return validate(routerInfo);
     744    }
     745
     746    /**
     747     * Determine whether this routerInfo will be accepted as valid and current
     748     * given what we know now.
     749     *
     750     * Call this before each use, to check expiration
     751     *
     752     * @return reason why the entry is not valid, or null if it is valid
     753     * @since 0.9.7
     754     */
     755    private String validate(RouterInfo routerInfo) throws IllegalArgumentException {
    728756        long now = _context.clock().now();
    729757        boolean upLongEnough = _context.router().getUptime() > 60*60*1000;
     
    744772                                          ((ROUTER_INFO_EXPIRATION - ROUTER_INFO_EXPIRATION_MIN) * MIN_ROUTERS / (_kb.size() + 1)));
    745773
    746         if (!key.equals(routerInfo.getIdentity().getHash())) {
    747             if (_log.shouldLog(Log.WARN))
    748                 _log.warn("Invalid store attempt! key does not match routerInfo.identity!  key = " + key + ", router = " + routerInfo);
    749             return "Key does not match routerInfo.identity - " + key.toBase64();
    750         } else if (!routerInfo.isValid()) {
    751             if (_log.shouldLog(Log.WARN))
    752                 _log.warn("Invalid routerInfo signature!  forged router structure!  router = " + routerInfo);
    753             return "Invalid routerInfo signature on " + key.toBase64();
    754         } else if (upLongEnough && !routerInfo.isCurrent(adjustedExpiration)) {
    755             if (routerInfo.getNetworkId() != Router.NETWORK_ID) {
    756                 _context.banlist().banlistRouter(key, "Peer is not in our network");
    757                 return "Peer is not in our network (" + routerInfo.getNetworkId() + ", wants "
    758                        + Router.NETWORK_ID + "): " + routerInfo.calculateHash().toBase64();
    759             }
     774        if (upLongEnough && !routerInfo.isCurrent(adjustedExpiration)) {
    760775            long age = _context.clock().now() - routerInfo.getPublished();
    761776            int existing = _kb.size();
    762777            if (existing >= MIN_REMAINING_ROUTERS) {
    763778                if (_log.shouldLog(Log.INFO))
    764                     _log.info("Not storing expired router for " + key.toBase64(), new Exception("Rejecting store"));
    765                 return "Peer " + key.toBase64() + " expired " + DataHelper.formatDuration(age) + " ago";
     779                    _log.info("Not storing expired RI " + routerInfo.getIdentity().getHash(), new Exception("Rejecting store"));
     780                return "Peer expired " + DataHelper.formatDuration(age) + " ago";
    766781            } else {
    767782                if (_log.shouldLog(Log.WARN))
    768783                    _log.warn("Even though the peer is old, we have only " + existing
    769                     + " peers left (curPeer: " + key.toBase64() + " published on "
    770                     + new Date(routerInfo.getPublished()));
     784                              + " peers left " + routerInfo);
    771785            }
    772         } else if (routerInfo.getPublished() > now + 2*Router.CLOCK_FUDGE_FACTOR) {
     786        }
     787        if (routerInfo.getPublished() > now + 2*Router.CLOCK_FUDGE_FACTOR) {
    773788            long age = routerInfo.getPublished() - _context.clock().now();
    774789            if (_log.shouldLog(Log.INFO))
    775                 _log.info("Peer " + key.toBase64() + " published their routerInfo in the future?! ["
     790                _log.info("Peer " + routerInfo.getIdentity().getHash() + " published their routerInfo in the future?! ["
    776791                          + new Date(routerInfo.getPublished()) + "]", new Exception("Rejecting store"));
    777             return "Peer " + key.toBase64() + " published " + DataHelper.formatDuration(age) + " in the future?!";
    778         } else if (_enforceNetId && (routerInfo.getNetworkId() != Router.NETWORK_ID) ){
    779             String rv = "Peer " + key.toBase64() + " is from another network, not accepting it (id="
    780                         + routerInfo.getNetworkId() + ", want " + Router.NETWORK_ID + ")";
    781             return rv;
    782         } else if (upLongEnough && (routerInfo.getPublished() < now - 2*24*60*60*1000l) ) {
     792            return "Peer published " + DataHelper.formatDuration(age) + " in the future?!";
     793        }
     794        if (upLongEnough && (routerInfo.getPublished() < now - 2*24*60*60*1000l) ) {
    783795            long age = _context.clock().now() - routerInfo.getPublished();
    784             return "Peer " + key.toBase64() + " published " + DataHelper.formatDuration(age) + " ago";
    785         } else if (upLongEnough && !routerInfo.isCurrent(ROUTER_INFO_EXPIRATION_SHORT)) {
     796            return "Peer published " + DataHelper.formatDuration(age) + " ago";
     797        }
     798        if (upLongEnough && !routerInfo.isCurrent(ROUTER_INFO_EXPIRATION_SHORT)) {
    786799            if (routerInfo.getAddresses().isEmpty())
    787                 return "Peer " + key.toBase64() + " published > 75m ago with no addresses";
     800                return "Peer published > 75m ago with no addresses";
    788801            // This should cover the introducers case below too
    789802            // And even better, catches the case where the router is unreachable but knows no introducers
    790803            if (routerInfo.getCapabilities().indexOf(Router.CAPABILITY_UNREACHABLE) >= 0)
    791                 return "Peer " + key.toBase64() + " published > 75m ago and thinks it is unreachable";
     804                return "Peer published > 75m ago and thinks it is unreachable";
    792805            RouterAddress ra = routerInfo.getTargetAddress("SSU");
    793806            if (ra != null) {
    794807                // Introducers change often, introducee will ping introducer for 2 hours
    795808                if (ra.getOption("ihost0") != null)
    796                     return "Peer " + key.toBase64() + " published > 75m ago with SSU Introducers";
     809                    return "Peer published > 75m ago with SSU Introducers";
    797810                if (routerInfo.getTargetAddress("NTCP") == null)
    798                     return "Peer " + key.toBase64() + " published > 75m ago, SSU only without introducers";
     811                    return "Peer published > 75m ago, SSU only without introducers";
    799812            }
    800813        }
  • router/java/src/net/i2p/router/networkdb/kademlia/RepublishLeaseSetJob.java

    r182fe90 r68d25af  
    4848                LeaseSet ls = _facade.lookupLeaseSetLocally(_dest);
    4949                if (ls != null) {
    50                     if (_log.shouldLog(Log.INFO))
    51                         _log.info("Client " + _dest + " is local, so we're republishing it");
    5250                    if (!ls.isCurrent(Router.CLOCK_FUDGE_FACTOR)) {
    5351                        if (_log.shouldLog(Log.WARN))
    5452                            _log.warn("Not publishing a LOCAL lease that isn't current - " + _dest, new Exception("Publish expired LOCAL lease?"));
    5553                    } else {
     54                        if (_log.shouldLog(Log.INFO))
     55                            _log.info("Publishing " + ls);
    5656                        getContext().statManager().addRateData("netDb.republishLeaseSetCount", 1, 0);
    5757                        _facade.sendStore(_dest, ls, new OnRepublishSuccess(getContext()), new OnRepublishFailure(getContext(), this), REPUBLISH_LEASESET_TIMEOUT, null);
  • router/java/src/net/i2p/router/networkdb/kademlia/TransientDataStore.java

    r182fe90 r68d25af  
    8282    }
    8383
    84     /** for PersistentDataStore only - don't use here @throws IAE always */
     84    /** for PersistentDataStore only - don't use here
     85      * @throws UnsupportedOperationException always
     86      */
    8587    public DatabaseEntry get(Hash key, boolean persist) {
    86         throw new IllegalArgumentException("no");
     88        throw new UnsupportedOperationException();
    8789    }
    8890
     
    104106    }
    105107   
    106     /** for PersistentDataStore only - don't use here @throws IAE always */
     108    /** for PersistentDataStore only - don't use here
     109      * @throws UnsupportedOperationException always
     110      */
    107111    public boolean put(Hash key, DatabaseEntry data, boolean persist) {
    108         throw new IllegalArgumentException("no");
     112        throw new UnsupportedOperationException();
    109113    }
    110114
     
    117121        if (_log.shouldLog(Log.DEBUG))
    118122            _log.debug("Storing key " + key);
    119         DatabaseEntry old = null;
    120         old = _data.putIfAbsent(key, data);
     123        DatabaseEntry old = _data.putIfAbsent(key, data);
    121124        boolean rv = false;
    122125        if (data.getType() == DatabaseEntry.KEY_TYPE_ROUTERINFO) {
     
    129132                if (ri.getPublished() < ori.getPublished()) {
    130133                    if (_log.shouldLog(Log.INFO))
    131                         _log.info("Almost clobbered an old router! " + key + ": [old published on " + new Date(ori.getPublished()) + " new on " + new Date(ri.getPublished()) + "]");
     134                        _log.info("Almost clobbered an old router! " + key + ": [old published on " + new Date(ori.getPublished()) +
     135                                  " new on " + new Date(ri.getPublished()) + ']');
    132136                } else if (ri.getPublished() == ori.getPublished()) {
    133137                    if (_log.shouldLog(Log.INFO))
     
    135139                } else {
    136140                    if (_log.shouldLog(Log.INFO))
    137                         _log.info("Updated the old router for " + key + ": [old published on " + new Date(ori.getPublished()) + " new on " + new Date(ri.getPublished()) + "]");
     141                        _log.info("Updated the old router for " + key + ": [old published on " + new Date(ori.getPublished()) +
     142                                  " new on " + new Date(ri.getPublished()) + ']');
    138143                    _data.put(key, data);
    139144                    rv = true;
     
    150155                if (ls.getEarliestLeaseDate() < ols.getEarliestLeaseDate()) {
    151156                    if (_log.shouldLog(Log.INFO))
    152                         _log.info("Almost clobbered an old leaseSet! " + key + ": [old published on " + new Date(ols.getEarliestLeaseDate()) + " new on " + new Date(ls.getEarliestLeaseDate()) + "]");
     157                        _log.info("Almost clobbered an old leaseSet! " + key + ": [old expires " + new Date(ols.getEarliestLeaseDate()) +
     158                                  " new on " + new Date(ls.getEarliestLeaseDate()) + ']');
    153159                } else if (ls.getEarliestLeaseDate() == ols.getEarliestLeaseDate()) {
    154160                    if (_log.shouldLog(Log.INFO))
     
    156162                } else {
    157163                    if (_log.shouldLog(Log.INFO)) {
    158                         _log.info("Updated old leaseSet " + key + ": [old published on " + new Date(ols.getEarliestLeaseDate()) + " new on " + new Date(ls.getEarliestLeaseDate()) + "]");
     164                        _log.info("Updated old leaseSet " + key + ": [old expires " + new Date(ols.getEarliestLeaseDate()) +
     165                                  " new on " + new Date(ls.getEarliestLeaseDate()) + ']');
    159166                        if (_log.shouldLog(Log.DEBUG))
    160167                            _log.debug("RAP? " + ls.getReceivedAsPublished() + " RAR? " + ls.getReceivedAsReply());
     
    165172            } else {
    166173                if (_log.shouldLog(Log.INFO)) {
    167                     _log.info("New leaseset for " + key + ": published on " + new Date(ls.getEarliestLeaseDate()));
     174                    _log.info("New leaseset for " + key + ": expires " + new Date(ls.getEarliestLeaseDate()));
    168175                    if (_log.shouldLog(Log.DEBUG))
    169176                        _log.debug("RAP? " + ls.getReceivedAsPublished() + " RAR? " + ls.getReceivedAsReply());
     
    188195    }
    189196   
    190     /** for PersistentDataStore only - don't use here */
     197    /** for PersistentDataStore only - don't use here
     198      * @throws UnsupportedOperationException always
     199      */
    191200    public DatabaseEntry remove(Hash key, boolean persist) {
    192         throw new IllegalArgumentException("no");
     201        throw new UnsupportedOperationException();
    193202    }
    194203
  • router/java/src/net/i2p/router/tunnel/pool/ExpireJob.java

    r182fe90 r68d25af  
    1717    private final long _dropAfter;
    1818
     19    private static final long OB_EARLY_EXPIRE = 30*1000;
     20    private static final long IB_EARLY_EXPIRE = OB_EARLY_EXPIRE + 7500;
     21
    1922    public ExpireJob(RouterContext ctx, TunnelCreatorConfig cfg, TunnelPool pool) {
    2023        super(ctx);
     
    2831        long expire = cfg.getExpiration();
    2932        _dropAfter = expire + Router.CLOCK_FUDGE_FACTOR;
    30         expire -= ctx.random().nextLong(60*1000);
    3133        if (_pool.getSettings().isInbound())
    32             expire -= ctx.random().nextLong(15*1000);
     34            expire -= IB_EARLY_EXPIRE + ctx.random().nextLong(IB_EARLY_EXPIRE);
     35        else
     36            expire -= OB_EARLY_EXPIRE + ctx.random().nextLong(OB_EARLY_EXPIRE);
     37        // See comments in TunnelPool.locked_buildNewLeaseSet
    3338        cfg.setExpiration(expire);
    3439        getTiming().setStartAfter(expire);
     
    4348            _pool.removeTunnel(_cfg);
    4449            _leaseUpdated = true;
     50            // noop for outbound
    4551            _pool.refreshLeaseSet();
    4652            long timeToDrop = _dropAfter - getContext().clock().now();
  • router/java/src/net/i2p/router/tunnel/pool/TunnelPool.java

    r182fe90 r68d25af  
    1919import net.i2p.router.TunnelPoolSettings;
    2020import net.i2p.router.tunnel.HopConfig;
     21import net.i2p.router.tunnel.TunnelCreatorConfig;
    2122import net.i2p.stat.Rate;
    2223import net.i2p.stat.RateAverages;
     
    726727            }
    727728            Lease lease = new Lease();
    728             lease.setEndDate(new Date(tunnel.getExpiration()));
     729            // bugfix
     730            // ExpireJob reduces the expiration, which causes a 2nd leaseset with the same lease
     731            // to have an earlier expiration, so it isn't stored.
     732            // Get the "real" expiration from the gateway hop config,
     733            // HopConfig expirations are the same as the "real" expiration and don't change
     734            // see configureNewTunnel()
     735            lease.setEndDate(new Date(((TunnelCreatorConfig)tunnel).getConfig(0).getExpiration()));
    729736            lease.setTunnelId(inId);
    730737            lease.setGateway(gw);
     
    11321139            // don't need to worry about prev/next hop
    11331140        }
     1141        // note that this will be adjusted by expire job
    11341142        cfg.setExpiration(expiration);
    11351143        if (!settings.isInbound())
Note: See TracChangeset for help on using the changeset viewer.