/** * Request that a particular client authorize the Leases contained in the LeaseSet, after which * the onCreateJob is queued up. If that doesn't occur within the timeout specified, queue up the * onFailedJob. This call does not block. * * @param set LeaseSet with requested leases - this object must be updated to contain the signed * version (as well as any changed/added/removed Leases) * @param expirationTime ms to wait before failing * @param onCreateJob Job to run after the LeaseSet is authorized * @param onFailedJob Job to run after the timeout passes without receiving authorization */ void requestLeaseSet(LeaseSet set, long expirationTime, Job onCreateJob, Job onFailedJob) { if (_dead) { if (_log.shouldLog(Log.WARN)) _log.warn("Requesting leaseSet from a dead client: " + set); if (onFailedJob != null) _context.jobQueue().addJob(onFailedJob); return; } // We can't use LeaseSet.equals() here because the dest, keys, and sig on // the new LeaseSet are null. So we compare leases one by one. // In addition, the client rewrites the expiration time of all the leases to // the earliest one, so we can't use Lease.equals() or Lease.getEndDate(). // So compare by tunnel ID, and then by gateway. // (on the remote possibility that two gateways are using the same ID). // TunnelPool.locked_buildNewLeaseSet() ensures that leases are sorted, // so the comparison will always work. int leases = set.getLeaseCount(); // synch so _currentLeaseSet isn't changed out from under us synchronized (this) { if (_currentLeaseSet != null && _currentLeaseSet.getLeaseCount() == leases) { for (int i = 0; i < leases; i++) { if (!_currentLeaseSet.getLease(i).getTunnelId().equals(set.getLease(i).getTunnelId())) break; if (!_currentLeaseSet.getLease(i).getGateway().equals(set.getLease(i).getGateway())) break; if (i == leases - 1) { if (_log.shouldLog(Log.INFO)) _log.info("Requested leaseSet hasn't changed"); if (onCreateJob != null) _context.jobQueue().addJob(onCreateJob); return; // no change } } } } if (_log.shouldLog(Log.INFO)) _log.info("Current leaseSet " + _currentLeaseSet + "\nNew leaseSet " + set); LeaseRequestState state = null; synchronized (this) { state = _leaseRequest; if (state != null) { if (_log.shouldLog(Log.DEBUG)) _log.debug("Already requesting " + state); LeaseSet requested = state.getRequested(); LeaseSet granted = state.getGranted(); long ours = set.getEarliestLeaseDate(); if (((requested != null) && (requested.getEarliestLeaseDate() > ours)) || ((granted != null) && (granted.getEarliestLeaseDate() > ours))) { // theirs is newer } else { // ours is newer, so wait a few secs and retry _context .simpleScheduler() .addEvent(new Rerequest(set, expirationTime, onCreateJob, onFailedJob), 3 * 1000); } // fire onCreated? return; // already requesting } else { _leaseRequest = state = new LeaseRequestState( onCreateJob, onFailedJob, _context.clock().now() + expirationTime, set); if (_log.shouldLog(Log.DEBUG)) _log.debug("New request: " + state); } } _context.jobQueue().addJob(new RequestLeaseSetJob(_context, this, state)); }
RequestThrottler(RouterContext ctx) { this.context = ctx; this.counter = new ObjectCounter<Hash>(); ctx.simpleScheduler().addPeriodicEvent(new Cleaner(), CLEAN_TIME); }