use of net.i2p.data.LeaseSet in project i2p.i2p by i2p.
the class ClientConnectionRunner method requestLeaseSet.
/**
* 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.
*
* Job args are always null, may need some fixups if we start using them.
*
* @param h the Destination's hash
* @param set LeaseSet with requested leases - this object must be updated to contain the
* signed version (as well as any changed/added/removed Leases)
* The LeaseSet contains Leases and destination only, it is unsigned.
* @param expirationTime ms to wait before failing
* @param onCreateJob Job to run after the LeaseSet is authorized, null OK
* @param onFailedJob Job to run after the timeout passes without receiving authorization, null OK
*/
void requestLeaseSet(Hash h, 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;
}
SessionParams sp = _sessions.get(h);
if (sp == null) {
if (_log.shouldLog(Log.WARN))
_log.warn("Requesting leaseSet for an unknown sesssion");
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
LeaseSet current = null;
Destination dest = sp.dest;
LeaseRequestState state;
synchronized (this) {
current = sp.currentLeaseSet;
if (current != null && current.getLeaseCount() == leases) {
for (int i = 0; i < leases; i++) {
if (!current.getLease(i).getTunnelId().equals(set.getLease(i).getTunnelId()))
break;
if (!current.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);
// no change
return;
}
}
}
if (_log.shouldLog(Log.INFO))
_log.info("Current leaseSet " + current + "\nNew leaseSet " + set);
state = sp.leaseRequest;
if (state != null) {
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
if (_log.shouldLog(Log.DEBUG))
_log.debug("Already requesting, theirs newer, do nothing: " + state);
} else {
// ours is newer, so wait a few secs and retry
set.setDestination(dest);
Rerequest timer = new Rerequest(set, expirationTime, onCreateJob, onFailedJob);
sp.rerequestTimer = timer;
_context.simpleTimer2().addEvent(timer, 3 * 1000);
if (_log.shouldLog(Log.DEBUG))
_log.debug("Already requesting, ours newer, wait 3 sec: " + state);
}
// already requesting
return;
} else {
set.setDestination(dest);
if (current == null && _context.tunnelManager().getOutboundClientTunnelCount(h) <= 0) {
// at startup of a client, where we don't have a leaseset, wait for
// an outbound tunnel also, so the client doesn't start sending data
// before we are ready
Rerequest timer = new Rerequest(set, expirationTime, onCreateJob, onFailedJob);
sp.rerequestTimer = timer;
_context.simpleTimer2().addEvent(timer, 1000);
if (_log.shouldLog(Log.DEBUG))
_log.debug("No current LS but no OB tunnels, wait 1 sec for " + h);
return;
} else {
// so the timer won't fire off with an older LS request
sp.rerequestTimer = null;
sp.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));
}
use of net.i2p.data.LeaseSet in project i2p.i2p by i2p.
the class TunnelPool method fail.
/**
* Remove the tunnel.
*/
private void fail(TunnelInfo cfg) {
if (_log.shouldLog(Log.WARN))
_log.warn(toString() + ": Tunnel failed: " + cfg);
LeaseSet ls = null;
synchronized (_tunnels) {
boolean removed = _tunnels.remove(cfg);
if (!removed)
return;
if (_settings.isInbound() && !_settings.isExploratory())
ls = locked_buildNewLeaseSet();
if (_lastSelected == cfg) {
_lastSelected = null;
_lastSelectionPeriod = 0;
}
}
_manager.tunnelFailed();
_lifetimeProcessed += cfg.getProcessedMessagesCount();
updateRate();
if (_settings.isInbound() && !_settings.isExploratory()) {
if (ls != null) {
_context.clientManager().requestLeaseSet(_settings.getDestination(), ls);
}
}
}
use of net.i2p.data.LeaseSet in project i2p.i2p by i2p.
the class TunnelPool method refreshLeaseSet.
/**
* noop for outbound and exploratory
*/
void refreshLeaseSet() {
if (_settings.isInbound() && !_settings.isExploratory()) {
if (_log.shouldLog(Log.DEBUG))
_log.debug(toString() + ": refreshing leaseSet on tunnel expiration (but prior to grace timeout)");
LeaseSet ls;
synchronized (_tunnels) {
ls = locked_buildNewLeaseSet();
}
if (ls != null) {
_context.clientManager().requestLeaseSet(_settings.getDestination(), ls);
Set<Hash> aliases = _settings.getAliases();
if (aliases != null && !aliases.isEmpty()) {
for (Hash h : aliases) {
_context.clientManager().requestLeaseSet(h, ls);
}
}
}
}
}
use of net.i2p.data.LeaseSet in project i2p.i2p by i2p.
the class TunnelPool method startup.
/**
* Warning, this may be called more than once
* (without an intervening shutdown()) if the
* tunnel is stopped and then restarted by the client manager with the same
* Destination (i.e. for servers or clients w/ persistent key,
* or restarting close-on-idle clients)
*/
synchronized void startup() {
synchronized (_inProgress) {
_inProgress.clear();
}
if (_log.shouldLog(Log.INFO))
_log.info(toString() + ": Startup() called, was already alive? " + _alive, new Exception());
_alive = true;
_started = System.currentTimeMillis();
_lastRateUpdate = _started;
_lastLifetimeProcessed = 0;
_manager.getExecutor().repoll();
if (_settings.isInbound() && !_settings.isExploratory()) {
// we just reconnected and didn't require any new tunnel builders.
// however, we /do/ want a leaseSet, so build one
LeaseSet ls = null;
synchronized (_tunnels) {
ls = locked_buildNewLeaseSet();
}
if (ls != null)
_context.clientManager().requestLeaseSet(_settings.getDestination(), ls);
}
_context.statManager().createRequiredRateStat(_rateName, "Tunnel Bandwidth (Bytes/sec)", "Tunnels", new long[] { 5 * 60 * 1000l });
}
use of net.i2p.data.LeaseSet in project i2p.i2p by i2p.
the class TunnelPool method removeTunnel.
/**
* Remove from the pool.
*/
void removeTunnel(TunnelInfo info) {
if (_log.shouldLog(Log.DEBUG))
_log.debug(toString() + ": Removing tunnel " + info);
int remaining = 0;
LeaseSet ls = null;
synchronized (_tunnels) {
boolean removed = _tunnels.remove(info);
if (!removed)
return;
if (_settings.isInbound() && !_settings.isExploratory())
ls = locked_buildNewLeaseSet();
remaining = _tunnels.size();
if (_lastSelected == info) {
_lastSelected = null;
_lastSelectionPeriod = 0;
}
}
_manager.getExecutor().repoll();
_lifetimeProcessed += info.getProcessedMessagesCount();
updateRate();
long lifetimeConfirmed = info.getVerifiedBytesTransferred();
long lifetime = 10 * 60 * 1000;
for (int i = 0; i < info.getLength(); i++) _context.profileManager().tunnelLifetimePushed(info.getPeer(i), lifetime, lifetimeConfirmed);
if (_alive && _settings.isInbound() && !_settings.isExploratory()) {
if (ls != null) {
_context.clientManager().requestLeaseSet(_settings.getDestination(), ls);
} else {
if (_log.shouldLog(Log.WARN))
_log.warn(toString() + ": unable to build a new leaseSet on removal (" + remaining + " remaining), request a new tunnel");
if (_settings.getAllowZeroHop())
buildFallback();
}
}
if (getTunnelCount() <= 0 && !isAlive()) {
// this calls both our shutdown() and the other one (inbound/outbound)
// This is racy - see TunnelPoolManager
_manager.removeTunnels(_settings.getDestination());
}
}
Aggregations