use of net.i2p.data.Hash in project i2p.i2p by i2p.
the class TunnelPool method configureNewTunnel.
/**
* @return null on failure
*/
private PooledTunnelCreatorConfig configureNewTunnel(boolean forceZeroHop) {
TunnelPoolSettings settings = getSettings();
// peers for new tunnel, including us, ENDPOINT FIRST
List<Hash> peers = null;
long now = _context.clock().now();
long expiration = now + TunnelPoolSettings.DEFAULT_DURATION;
if (!forceZeroHop) {
int len = settings.getLengthOverride();
if (len < 0)
len = settings.getLength();
if (len > 0 && (!settings.isExploratory()) && _context.random().nextBoolean()) {
// look for a tunnel to reuse, if the right length and expiring soon
// ignore variance for now.
// us
len++;
synchronized (_tunnels) {
for (TunnelInfo ti : _tunnels) {
if (ti.getLength() >= len && ti.getExpiration() < now + 3 * 60 * 1000 && !ti.wasReused()) {
ti.setReused();
len = ti.getLength();
peers = new ArrayList<Hash>(len);
// peers list is ordered endpoint first, but cfg.getPeer() is ordered gateway first
for (int i = len - 1; i >= 0; i--) {
peers.add(ti.getPeer(i));
}
break;
}
}
}
}
if (peers == null) {
setLengthOverride();
peers = _peerSelector.selectPeers(settings);
}
if ((peers == null) || (peers.isEmpty())) {
// the pool is refusing 0 hop tunnels
if (peers == null) {
if (_log.shouldLog(Log.WARN))
_log.warn("No peers to put in the new tunnel! selectPeers returned null! boo, hiss!");
} else {
if (_log.shouldLog(Log.WARN))
_log.warn("No peers to put in the new tunnel! selectPeers returned an empty list?!");
}
return null;
}
} else {
peers = Collections.singletonList(_context.routerHash());
}
PooledTunnelCreatorConfig cfg = new PooledTunnelCreatorConfig(_context, peers.size(), settings.isInbound(), settings.getDestination());
cfg.setTunnelPool(this);
// peers list is ordered endpoint first, but cfg.getPeer() is ordered gateway first
for (int i = 0; i < peers.size(); i++) {
int j = peers.size() - 1 - i;
cfg.setPeer(j, peers.get(i));
HopConfig hop = cfg.getConfig(j);
hop.setCreation(now);
hop.setExpiration(expiration);
hop.setIVKey(_context.keyGenerator().generateSessionKey());
hop.setLayerKey(_context.keyGenerator().generateSessionKey());
// tunnelIds will be updated during building, and as the creator, we
// don't need to worry about prev/next hop
}
// note that this will be adjusted by expire job
cfg.setExpiration(expiration);
if (!settings.isInbound())
cfg.setPriority(settings.getPriority());
if (_log.shouldLog(Log.DEBUG))
_log.debug("Config contains " + peers + ": " + cfg);
synchronized (_inProgress) {
_inProgress.add(cfg);
}
return cfg;
}
use of net.i2p.data.Hash in project i2p.i2p by i2p.
the class TunnelPoolManager method addAlias.
/**
* Add another destination to the same tunnels.
* Must have same encryption key and a different signing key.
* @throws IllegalArgumentException if not
* @return success
* @since 0.9.21
*/
public boolean addAlias(Destination dest, ClientTunnelSettings settings, Destination existingClient) {
if (dest.getSigningPublicKey().equals(existingClient.getSigningPublicKey()))
throw new IllegalArgumentException("signing key must differ");
if (!dest.getPublicKey().equals(existingClient.getPublicKey()))
throw new IllegalArgumentException("encryption key mismatch");
Hash h = dest.calculateHash();
Hash e = existingClient.calculateHash();
synchronized (this) {
TunnelPool inbound = _clientInboundPools.get(h);
TunnelPool outbound = _clientOutboundPools.get(h);
if (inbound != null || outbound != null) {
if (_log.shouldLog(Log.WARN))
_log.warn("already have alias " + dest.toBase32());
return false;
}
TunnelPool eInbound = _clientInboundPools.get(e);
TunnelPool eOutbound = _clientOutboundPools.get(e);
if (eInbound == null || eOutbound == null) {
if (_log.shouldLog(Log.WARN))
_log.warn("primary not found " + existingClient);
return false;
}
eInbound.getSettings().getAliases().add(h);
eOutbound.getSettings().getAliases().add(h);
TunnelPoolSettings newIn = settings.getInboundSettings();
TunnelPoolSettings newOut = settings.getOutboundSettings();
newIn.setAliasOf(e);
newOut.setAliasOf(e);
inbound = new AliasedTunnelPool(_context, this, newIn, eInbound);
outbound = new AliasedTunnelPool(_context, this, newOut, eOutbound);
_clientInboundPools.put(h, inbound);
_clientOutboundPools.put(h, outbound);
inbound.startup();
outbound.startup();
}
if (_log.shouldLog(Log.WARN))
_log.warn("Added " + dest.toBase32() + " as alias for " + existingClient.toBase32() + " with settings " + settings);
return true;
}
use of net.i2p.data.Hash in project i2p.i2p by i2p.
the class TunnelPoolManager method removeAlias.
/**
* Remove a destination for the same tunnels as another.
* @since 0.9.21
*/
public void removeAlias(Destination dest) {
Hash h = dest.calculateHash();
synchronized (this) {
TunnelPool inbound = _clientInboundPools.remove(h);
if (inbound != null) {
Hash p = inbound.getSettings().getAliasOf();
if (p != null) {
TunnelPool pri = _clientInboundPools.get(p);
if (pri != null) {
Set<Hash> aliases = pri.getSettings().getAliases();
if (aliases != null)
aliases.remove(h);
}
}
}
TunnelPool outbound = _clientOutboundPools.remove(h);
if (outbound != null) {
Hash p = outbound.getSettings().getAliasOf();
if (p != null) {
TunnelPool pri = _clientOutboundPools.get(p);
if (pri != null) {
Set<Hash> aliases = pri.getSettings().getAliases();
if (aliases != null)
aliases.remove(h);
}
}
}
// TODO if primary already vanished...
}
}
use of net.i2p.data.Hash in project i2p.i2p by i2p.
the class TunnelPoolManager method selectPeersInTooManyTunnels.
/**
* For reliability reasons, don't allow a peer in more than x% of
* client and exploratory tunnels.
*
* This also will prevent a single huge-capacity (or malicious) peer from
* taking all the tunnels in the network (although it would be nice to limit
* the % of total network tunnels to 10% or so, but that appears to be
* too low to set as a default here... much lower than 33% will push client
* tunnels out of the fast tier into high cap or beyond...)
*
* Possible improvement - restrict based on count per IP, or IP block,
* to slightly increase costs of collusion
*
* @return Set of peers that should not be allowed in another tunnel
*/
public Set<Hash> selectPeersInTooManyTunnels() {
ObjectCounter<Hash> lc = new ObjectCounter<Hash>();
int tunnelCount = countTunnelsPerPeer(lc);
Set<Hash> rv = new HashSet<Hash>();
if (tunnelCount >= 4 && _context.router().getUptime() > 10 * 60 * 1000) {
int max = _context.getProperty("router.maxTunnelPercentage", DEFAULT_MAX_PCT_TUNNELS);
for (Hash h : lc.objects()) {
if (lc.count(h) > 0 && (lc.count(h) + 1) * 100 / (tunnelCount + 1) > max)
rv.add(h);
}
}
return rv;
}
use of net.i2p.data.Hash in project i2p.i2p by i2p.
the class InboundEndpointProcessor method retrievePreprocessedData.
/**
* Undo all of the encryption done by the peers in the tunnel, recovering the
* preprocessed data sent by the gateway.
*
* @return true if the data was recovered (and written in place to orig), false
* if it was a duplicate or from the wrong peer.
*/
public boolean retrievePreprocessedData(byte[] orig, int offset, int length, Hash prev) {
Hash last = _config.getPeer(_config.getLength() - 2);
if (!last.equals(prev)) {
// shouldn't happen now that we have good dup ID detection in BuildHandler
if (_log.shouldLog(Log.WARN))
_log.warn("Attempted IBEP injection from " + prev + ", expected " + last);
return false;
}
byte[] iv = SimpleByteCache.acquire(HopProcessor.IV_LENGTH);
System.arraycopy(orig, offset, iv, 0, iv.length);
// if (_config.getLength() > 1)
// _log.debug("IV at inbound endpoint before decrypt: " + Base64.encode(iv));
boolean ok = _validator.receiveIV(iv, 0, orig, offset + HopProcessor.IV_LENGTH);
if (!ok) {
if (_log.shouldLog(Log.WARN))
_log.warn("Invalid IV, dropping at IBEP " + _config);
SimpleByteCache.release(iv);
return false;
}
// inbound endpoints and outbound gateways have to undo the crypto in the same way
// if (USE_ENCRYPTION)
decrypt(_context, _config, iv, orig, offset, length);
SimpleByteCache.release(iv);
if (_config.getLength() > 0) {
// dunno... may not be related to an rtt
int rtt = 0;
if (_log.shouldLog(Log.DEBUG))
_log.debug("Received a " + length + "byte message through tunnel " + _config);
for (int i = 0; i < _config.getLength(); i++) _context.profileManager().tunnelDataPushed(_config.getPeer(i), rtt, length);
_config.incrementVerifiedBytesTransferred(length);
}
return true;
}
Aggregations