propagate from branch 'i2p.i2p' (head e014bb054baa0d8e844e9a97ad6f5b04ed7c0e56)

to branch 'i2p.i2p.zzz.test' (head 1e0af137b9c4c873fea72d661f2ee351a640734f)
This commit is contained in:
zzz
2011-07-19 21:18:14 +00:00
18 changed files with 226 additions and 110 deletions

View File

@@ -455,9 +455,15 @@ public class I2PTunnelHTTPClient extends I2PTunnelHTTPClientBase implements Runn
!Boolean.valueOf(getTunnel().getClientOptions().getProperty(PROP_DISABLE_HELPER)).booleanValue()) {
pos2 = fragment.indexOf("=");
ahelperKey = fragment.substring(pos2 + 1);
// Key contains data, lets not ignore it
if (ahelperKey != null) {
if(ahelperKey.endsWith(".b32.i2p")) {
// allow i2paddresshelper=<b32>.b32.i2p syntax.
Destination dest = _context.namingService().lookup(ahelperKey);
if(dest==null)
throw new RuntimeException("Could not find destination for "+ahelperKey);
ahelperKey = dest.toBase64();
}
ahelperPresent = true;
// ahelperKey will be validated later
if (host == null || "i2p".equals(host)) {

View File

@@ -8,6 +8,7 @@ package net.i2p.i2ptunnel.web;
*
*/
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
@@ -31,6 +32,7 @@ import net.i2p.i2ptunnel.I2PTunnelIRCClient;
import net.i2p.i2ptunnel.TunnelController;
import net.i2p.i2ptunnel.TunnelControllerGroup;
import net.i2p.util.ConcurrentHashSet;
import net.i2p.util.FileUtil;
import net.i2p.util.Log;
/**
@@ -41,9 +43,9 @@ import net.i2p.util.Log;
* Usage by classes outside of i2ptunnel.war is deprecated.
*/
public class IndexBean {
protected I2PAppContext _context;
protected Log _log;
protected TunnelControllerGroup _group;
protected final I2PAppContext _context;
protected final Log _log;
protected final TunnelControllerGroup _group;
private String _action;
private int _tunnel;
//private long _prevNonce;
@@ -75,8 +77,8 @@ public class IndexBean {
private boolean _sharedClient;
private boolean _privKeyGenerate;
private boolean _removeConfirmed;
private Set<String> _booleanOptions;
private Map<String, String> _otherOptions;
private final Set<String> _booleanOptions;
private final Map<String, String> _otherOptions;
private int _hashCashValue;
private int _certType;
private String _certSigner;
@@ -199,17 +201,17 @@ public class IndexBean {
}
private String stopAll() {
if (_group == null) return "";
List msgs = _group.stopAllControllers();
List<String> msgs = _group.stopAllControllers();
return getMessages(msgs);
}
private String startAll() {
if (_group == null) return "";
List msgs = _group.startAllControllers();
List<String> msgs = _group.startAllControllers();
return getMessages(msgs);
}
private String restartAll() {
if (_group == null) return "";
List msgs = _group.restartAllControllers();
List<String> msgs = _group.restartAllControllers();
return getMessages(msgs);
}
private String reloadConfig() {
@@ -317,6 +319,10 @@ public class IndexBean {
return rv;
}
/**
* Stop the tunnel, delete from config,
* rename the private key file if in the default directory
*/
private String deleteTunnel() {
if (!_removeConfirmed)
return "Please confirm removal";
@@ -325,8 +331,38 @@ public class IndexBean {
if (cur == null)
return "Invalid tunnel number";
List msgs = _group.removeController(cur);
List<String> msgs = _group.removeController(cur);
msgs.addAll(doSave());
// Rename private key file if it was a default name in
// the default directory, so it doesn't get reused when a new
// tunnel is created.
// Use configured file name if available, not the one from the form.
String pk = cur.getPrivKeyFile();
if (pk == null)
pk = _privKeyFile;
if (pk != null && pk.startsWith("i2ptunnel") && pk.endsWith("-privKeys.dat")) {
File pkf = new File(_context.getConfigDir(), pk);
if (pkf.exists()) {
String name = cur.getName();
if (name == null) {
name = cur.getDescription();
if (name == null) {
name = cur.getType();
if (name == null)
name = Long.toString(_context.clock().now());
}
}
name = "i2ptunnel-deleted-" + name.replace(' ', '_') + "-privkeys.dat";
File to = new File(_context.getConfigDir(), name);
if (to.exists())
to = new File(_context.getConfigDir(), name + '-' + _context.clock().now());
boolean success = FileUtil.rename(pkf, to);
if (success)
msgs.add("Private key file " + pkf.getAbsolutePath() +
" renamed to " + to.getAbsolutePath());
}
}
return getMessages(msgs);
}

View File

@@ -359,7 +359,7 @@ public class NewsFetcher implements Runnable, EepGet.StatusListener {
long now = _context.clock().now();
if (_tempFile.exists()) {
boolean copied = FileUtil.copy(_tempFile.getAbsolutePath(), _newsFile.getAbsolutePath(), true);
boolean copied = FileUtil.copy(_tempFile, _newsFile, true, false);
if (copied) {
_lastUpdated = now;
_tempFile.delete();

View File

@@ -93,8 +93,8 @@ public class UnsignedUpdateHandler extends UpdateHandler {
_log.log(Log.CRIT, "Corrupt zip file from " + url);
return;
}
String to = (new File(_context.getRouterDir(), Router.UPDATE_FILE)).getAbsolutePath();
boolean copied = FileUtil.copy(_updateFile, to, true);
File to = new File(_context.getRouterDir(), Router.UPDATE_FILE);
boolean copied = FileUtil.copy(updFile, to, true, false);
if (copied) {
updFile.delete();
String policy = _context.getProperty(ConfigUpdateHandler.PROP_UPDATE_POLICY);
@@ -124,7 +124,7 @@ public class UnsignedUpdateHandler extends UpdateHandler {
}
} else {
_log.log(Log.CRIT, "Failed copy to " + to);
updateStatus("<b>" + _("Failed copy to {0}", to) + "</b>");
updateStatus("<b>" + _("Failed copy to {0}", to.getAbsolutePath()) + "</b>");
}
}
}

View File

@@ -165,26 +165,22 @@ class ConnectionManager {
_log.warn("Refusing connection since we have exceeded our max of "
+ _maxConcurrentStreams + " connections");
reject = true;
} else if (shouldRejectConnection(synPacket)) {
} else {
// this may not be right if more than one is enabled
String why;
if (_defaultOptions.isAccessListEnabled())
why = "not whitelisted: ";
else if (_defaultOptions.isBlacklistEnabled())
why = "blacklisted: ";
else
why = "throttled: ";
_log.error("Refusing connection since peer is " + why +
(synPacket.getOptionalFrom() == null ? "null from" : synPacket.getOptionalFrom().calculateHash().toBase64()));
reject = true;
} else {
while (true) {
Connection oldCon = _connectionByInboundId.putIfAbsent(Long.valueOf(receiveId), con);
if (oldCon == null) {
break;
} else {
// receiveId already taken, try another
receiveId = _context.random().nextLong(Packet.MAX_STREAM_ID-1)+1;
String why = shouldRejectConnection(synPacket);
if (why != null) {
_log.logAlways(Log.WARN, "Refusing connection since peer is " + why +
(synPacket.getOptionalFrom() == null ? "" : ": " + synPacket.getOptionalFrom().calculateHash().toBase64()));
reject = true;
} else {
while (true) {
Connection oldCon = _connectionByInboundId.putIfAbsent(Long.valueOf(receiveId), con);
if (oldCon == null) {
break;
} else {
// receiveId already taken, try another
receiveId = _context.random().nextLong(Packet.MAX_STREAM_ID-1)+1;
}
}
}
}
@@ -308,35 +304,46 @@ class ConnectionManager {
return (active >= _maxConcurrentStreams);
}
private boolean shouldRejectConnection(Packet syn) {
/**
* @return reason string or null if not rejected
*/
private String shouldRejectConnection(Packet syn) {
// unfortunately we don't have access to the router client manager here,
// so we can't whitelist local access
Destination from = syn.getOptionalFrom();
if (from == null)
return true;
return "null";
Hash h = from.calculateHash();
boolean throttled = false;
String throttled = null;
// always call all 3 to increment all counters
if (_minuteThrottler != null && _minuteThrottler.shouldThrottle(h)) {
_context.statManager().addRateData("stream.con.throttledMinute", 1, 0);
throttled = true;
throttled = "throttled by per-peer limit of " + _defaultOptions.getMaxConnsPerMinute() +
" or total limit of " + _defaultOptions.getMaxTotalConnsPerMinute() +
" per minute";
}
if (_hourThrottler != null && _hourThrottler.shouldThrottle(h)) {
_context.statManager().addRateData("stream.con.throttledHour", 1, 0);
throttled = true;
throttled = "throttled by per-peer limit of " + _defaultOptions.getMaxConnsPerHour() +
" or total limit of " + _defaultOptions.getMaxTotalConnsPerHour() +
" per hour";
}
if (_dayThrottler != null && _dayThrottler.shouldThrottle(h)) {
_context.statManager().addRateData("stream.con.throttledDay", 1, 0);
throttled = true;
throttled = "throttled by per-peer limit of " + _defaultOptions.getMaxConnsPerDay() +
" or total limit of " + _defaultOptions.getMaxTotalConnsPerDay() +
" per day";
}
if (throttled)
return true;
if (throttled != null)
return throttled;
// if the sig is absent or bad it will be caught later (in CPH)
if (_defaultOptions.isAccessListEnabled())
return !_defaultOptions.getAccessList().contains(h);
if (_defaultOptions.isBlacklistEnabled())
return _defaultOptions.getBlacklist().contains(h);
return false;
if (_defaultOptions.isAccessListEnabled() &&
!_defaultOptions.getAccessList().contains(h))
return "not whitelisted";
if (_defaultOptions.isBlacklistEnabled() &&
_defaultOptions.getBlacklist().contains(h))
return "blacklisted";
return null;
}

View File

@@ -402,7 +402,7 @@ public class CPUID {
}
// copy to install dir, ignore failure
File newFile = new File(I2PAppContext.getGlobalContext().getBaseDir(), filename);
FileUtil.copy(outFile.getAbsolutePath(), newFile.getAbsolutePath(), false, true);
FileUtil.copy(outFile, newFile, false, true);
return true;
}

View File

@@ -193,7 +193,7 @@ public class SingleFileNamingService extends NamingService {
out.write(d.toBase64());
out.newLine();
out.close();
boolean success = rename(tmp, _file);
boolean success = FileUtil.rename(tmp, _file);
if (success) {
for (NamingServiceListener nsl : _listeners) {
nsl.entryChanged(this, hostname, d, options);
@@ -284,7 +284,7 @@ public class SingleFileNamingService extends NamingService {
tmp.delete();
return false;
}
success = rename(tmp, _file);
success = FileUtil.rename(tmp, _file);
if (success) {
for (NamingServiceListener nsl : _listeners) {
nsl.entryRemoved(this, hostname);
@@ -442,24 +442,6 @@ public class SingleFileNamingService extends NamingService {
}
}
private static boolean rename(File from, File to) {
boolean success = false;
boolean isWindows = System.getProperty("os.name").startsWith("Win");
// overwrite fails on windows
if (!isWindows)
success = from.renameTo(to);
if (!success) {
to.delete();
success = from.renameTo(to);
if (!success) {
// hard way
success = FileUtil.copy(from.getAbsolutePath(), to.getAbsolutePath(), true, true);
from.delete();
}
}
return success;
}
private void getReadLock() {
_fileLock.readLock().lock();
}

View File

@@ -19,7 +19,6 @@ import java.io.InputStream;
* @author jrandom
*/
public class Hash extends SimpleDataStructure {
private volatile String _stringified;
private volatile String _base64ed;
private int _cachedHashCode;
@@ -71,7 +70,6 @@ public class Hash extends SimpleDataStructure {
@Override
public void setData(byte[] data) {
super.setData(data);
_stringified = null;
_base64ed = null;
_cachedHashCode = super.hashCode();
}
@@ -79,7 +77,6 @@ public class Hash extends SimpleDataStructure {
@Override
public void readBytes(InputStream in) throws DataFormatException, IOException {
super.readBytes(in);
_stringified = null;
_base64ed = null;
_cachedHashCode = super.hashCode();
}

View File

@@ -400,7 +400,15 @@ public class FileUtil {
public static boolean copy(String source, String dest, boolean overwriteExisting, boolean quiet) {
File src = new File(source);
File dst = new File(dest);
return copy(src, dst, overwriteExisting, quiet);
}
/**
* @param quiet don't log fails to wrapper log if true
* @return true if it was copied successfully
* @since 0.8.8
*/
public static boolean copy(File src, File dst, boolean overwriteExisting, boolean quiet) {
if (dst.exists() && dst.isDirectory())
dst = new File(dst, src.getName());
@@ -429,6 +437,35 @@ public class FileUtil {
}
}
/**
* Try to rename, if it doesn't work then copy and delete the old.
* Always overwrites any existing "to" file.
* Method moved from SingleFileNamingService.
*
* @return true if it was renamed / copied successfully
* @since 0.8.8
*/
public static boolean rename(File from, File to) {
if (!from.exists())
return false;
boolean success = false;
boolean isWindows = System.getProperty("os.name").startsWith("Win");
// overwrite fails on windows
if (!isWindows)
success = from.renameTo(to);
if (!success) {
to.delete();
success = from.renameTo(to);
if (!success) {
// hard way
success = copy(from, to, true, true);
if (success)
from.delete();
}
}
return success;
}
/**
* Usage: FileUtil (delete path | copy source dest | unzip path.zip)
*

View File

@@ -606,7 +606,7 @@ public class NativeBigInteger extends BigInteger {
}
// copy to install dir, ignore failure
File newFile = new File(I2PAppContext.getGlobalContext().getBaseDir(), filename);
FileUtil.copy(outFile.getAbsolutePath(), newFile.getAbsolutePath(), false, true);
FileUtil.copy(outFile, newFile, false, true);
return true;
}

View File

@@ -1,3 +1,10 @@
2011-07-18 zzz
* FileUtil: Add a rename method and a new copy method
* I2PTunnel: Rename privkey file when deleting tunnel to prevent inadvertent reuse
* Netdb: Update reseed lists
* Streaming: Improve conn limit log message
* UDP: Lower max port below 31000 since wrapper uses that
2011-07-15 zzz
* Shutdown:
- Cancel our JVM shutdown hook when shutting down

View File

@@ -310,8 +310,8 @@ div.sorry hr {
}
div.main {
margin: 10px 10px 20px 207px;
padding: 0 15px 15px 15px;
margin: 10px 210px 0px 10px;
padding: 7px 0px 30px 20px;
background: #ffe;
text-align: right;
color: #001;
@@ -345,8 +345,8 @@ div.main textarea {
}
div.news {
margin: 0px 10px 5px 207px;
padding: 7px 20px 7px 20px;
margin: 10px 210px 0px 10px;
padding: 7px 0px 30px 20px;
border: 1px solid #447;
color: #224;
border-radius: 4px;
@@ -711,8 +711,8 @@ p {
h1 {
text-align: right;
color: #115;
padding: 10px 15px;
margin: 0 10px 10px 207px;
margin: 10px 210px 0px 10px;
padding: 7px 0px 30px 20px;
font: normal bold 16pt/120% "Lucida Sans Unicode", "Bitstream Vera Sans", Verdana, Tahoma, Helvetica, sans-serif;
letter-spacing: 0.15em;
text-transform: uppercase;

View File

@@ -18,7 +18,7 @@ public class RouterVersion {
/** deprecated */
public final static String ID = "Monotone";
public final static String VERSION = CoreVersion.VERSION;
public final static long BUILD = 11;
public final static long BUILD = 12;
/** for example "-test" */
public final static String EXTRA = "";

View File

@@ -56,14 +56,22 @@ public class Reseeder {
* URLs are constructed, and because SSLEepGet doesn't follow redirects.
*/
public static final String DEFAULT_SEED_URL =
"http://a.netdb.i2p2.de/,http://c.netdb.i2p2.de/," +
"http://reseed.i2p-projekt.de/,http://forum.i2p2.de/netdb/,http://www.i2pbote.net/netDb/,http://r31453.ovh.net/static_media/files/netDb/";
"http://a.netdb.i2p2.de/," +
"http://c.netdb.i2p2.de/," +
"http://reseed.i2p-projekt.de/," +
"http://forum.i2p2.de/netdb/," +
"http://www.i2pbote.net/netDb/," +
"http://r31453.ovh.net/static_media/files/netDb/," +
"http://cowpuncher.drollette.com/netdb/";
/** @since 0.8.2 */
public static final String DEFAULT_SSL_SEED_URL =
"https://a.netdb.i2p2.de/,https://c.netdb.i2p2.de/," +
"https://forum.i2p2.de/netdb/,https://www.i2pbote.net/netDb/," +
"https://r31453.ovh.net/static_media/files/netDb/";
/* "https://a.netdb.i2p2.de/," + bad cert */
/* "https://c.netdb.i2p2.de/," + no data */
"https://forum.i2p2.de/netdb/," +
"https://www.i2pbote.net/netDb/," +
"https://r31453.ovh.net/static_media/files/netDb/," +
"https://cowpuncher.drollette.com/netdb/";
private static final String PROP_INPROGRESS = "net.i2p.router.web.ReseedHandler.reseedInProgress";
/** the console shows this message while reseedInProgress == false */

View File

@@ -80,11 +80,11 @@ class UDPEndpoint {
}
********/
/** 8998 is monotone, and 32000 is the wrapper, so let's stay between those */
/** 8998 is monotone, and 31000 is the wrapper outbound, so let's stay between those */
public static final String PROP_MIN_PORT = "i2np.udp.minPort";
public static final String PROP_MAX_PORT = "i2np.udp.maxPort";
private static final int MIN_RANDOM_PORT = 9111;
private static final int MAX_RANDOM_PORT = 31777;
private static final int MAX_RANDOM_PORT = 30777;
private static final int MAX_PORT_RETRIES = 20;
/**

View File

@@ -23,6 +23,10 @@ import net.i2p.stat.Rate;
import net.i2p.stat.RateStat;
import net.i2p.util.Log;
/**
* Repeatedly test a single tunnel for its entire lifetime,
* or until the pool is shut down or removed from the client manager.
*/
class TestJob extends JobImpl {
private final Log _log;
private final TunnelPool _pool;
@@ -35,7 +39,7 @@ class TestJob extends JobImpl {
private SessionTag _encryptTag;
/** base to randomize the test delay on */
private static final int TEST_DELAY = 30*1000;
private static final int TEST_DELAY = 40*1000;
public TestJob(RouterContext ctx, PooledTunnelCreatorConfig cfg, TunnelPool pool) {
super(ctx);
@@ -54,7 +58,7 @@ class TestJob extends JobImpl {
public String getName() { return "Test tunnel"; }
public void runJob() {
if (_pool == null)
if (_pool == null || !_pool.isAlive())
return;
long lag = getContext().jobQueue().getMaxLag();
if (lag > 3000) {
@@ -155,6 +159,8 @@ class TestJob extends JobImpl {
}
public void testSuccessful(int ms) {
if (_pool == null || !_pool.isAlive())
return;
getContext().statManager().addRateData("tunnel.testSuccessLength", _cfg.getLength(), 0);
getContext().statManager().addRateData("tunnel.testSuccessTime", ms, 0);
@@ -182,6 +188,8 @@ class TestJob extends JobImpl {
}
private void testFailed(long timeToFail) {
if (_pool == null || !_pool.isAlive())
return;
if (_found) {
// ok, not really a /success/, but we did find it, even though slowly
noteSuccess(timeToFail, _outTunnel);
@@ -208,7 +216,7 @@ class TestJob extends JobImpl {
}
/** randomized time we should wait before testing */
private int getDelay() { return TEST_DELAY + getContext().random().nextInt(TEST_DELAY); }
private int getDelay() { return TEST_DELAY + getContext().random().nextInt(TEST_DELAY / 3); }
/** how long we allow tests to run for before failing them */
private int getTestPeriod() {
@@ -234,8 +242,11 @@ class TestJob extends JobImpl {
private void scheduleRetest() { scheduleRetest(false); }
private void scheduleRetest(boolean asap) {
if (_pool == null || !_pool.isAlive())
return;
if (asap) {
requeue(getContext().random().nextInt(TEST_DELAY));
if (_cfg.getExpiration() > getContext().clock().now() + (60 * 1000))
requeue((TEST_DELAY / 4) + getContext().random().nextInt(TEST_DELAY / 4));
} else {
int delay = getDelay();
if (_cfg.getExpiration() > getContext().clock().now() + delay + (3 * getTestPeriod()))

View File

@@ -23,6 +23,7 @@ import net.i2p.util.Log;
/**
* A group of tunnels for the router or a particular client, in a single direction.
* Public only for TunnelRenderer in router console.
*/
public class TunnelPool {
private final List<PooledTunnelCreatorConfig> _inProgress = new ArrayList();
@@ -43,7 +44,7 @@ public class TunnelPool {
private final String _rateName;
private static final int TUNNEL_LIFETIME = 10*60*1000;
public TunnelPool(RouterContext ctx, TunnelPoolManager mgr, TunnelPoolSettings settings, TunnelPeerSelector sel) {
TunnelPool(RouterContext ctx, TunnelPoolManager mgr, TunnelPoolSettings settings, TunnelPeerSelector sel) {
_context = ctx;
_log = ctx.logManager().getLog(TunnelPool.class);
_manager = mgr;
@@ -59,10 +60,18 @@ public class TunnelPool {
refreshSettings();
}
public void 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)
*/
void startup() {
synchronized (_inProgress) {
_inProgress.clear();
}
if (_log.shouldLog(Log.WARN))
_log.warn(toString() + ": Startup() called, was already alive? " + _alive, new Exception());
_alive = true;
_started = System.currentTimeMillis();
_lastRateUpdate = _started;
@@ -84,7 +93,9 @@ public class TunnelPool {
new long[] { 5*60*1000l });
}
public void shutdown() {
void shutdown() {
if (_log.shouldLog(Log.WARN))
_log.warn(toString() + ": Shutdown called", new Exception());
_alive = false;
_lastSelectionPeriod = 0;
_lastSelected = null;
@@ -132,7 +143,8 @@ public class TunnelPool {
* and returns it.
*
*/
public TunnelInfo selectTunnel() { return selectTunnel(true); }
TunnelInfo selectTunnel() { return selectTunnel(true); }
private TunnelInfo selectTunnel(boolean allowRecurseOnFail) {
boolean avoidZeroHop = ((getSettings().getLength() + getSettings().getLengthVariance()) > 0);
@@ -239,7 +251,7 @@ public class TunnelPool {
* Do we really need more fallbacks?
* Used to prevent a zillion of them
*/
public boolean needFallback() {
boolean needFallback() {
int needed = _settings.getBackupQuantity() + _settings.getQuantity();
int fallbacks = 0;
synchronized (_tunnels) {
@@ -259,7 +271,8 @@ public class TunnelPool {
int getTunnelCount() { synchronized (_tunnels) { return _tunnels.size(); } }
public TunnelPoolSettings getSettings() { return _settings; }
public void setSettings(TunnelPoolSettings settings) {
void setSettings(TunnelPoolSettings settings) {
_settings = settings;
if (_settings != null) {
if (_log.shouldLog(Log.INFO))
@@ -267,8 +280,19 @@ public class TunnelPool {
_manager.getExecutor().repoll(); // in case we need more
}
}
public TunnelPeerSelector getSelector() { return _peerSelector; }
public boolean isAlive() { return _alive; }
/**
* Is this pool running AND either exploratory, or tracked by the client manager?
* A pool will be alive but not tracked after the client manager removes it
* but before all the tunnels have expired.
*/
public boolean isAlive() {
return _alive &&
(_settings.isExploratory() ||
(_settings.getDestination() != null &&
_context.clientManager().isLocal(_settings.getDestination())));
}
/** duplicate of getTunnelCount(), let's pick one */
public int size() {
synchronized (_tunnels) {
@@ -336,17 +360,14 @@ public class TunnelPool {
}
}
boolean connected = true;
if ( (_settings.getDestination() != null) && (!_context.clientManager().isLocal(_settings.getDestination())) )
connected = false;
if ( (getTunnelCount() <= 0) && (!connected) ) {
if (getTunnelCount() <= 0 && !isAlive()) {
// this calls both our shutdown() and the other one (inbound/outbound)
_manager.removeTunnels(_settings.getDestination());
return;
}
}
/** This may be called multiple times from TestJob */
public void tunnelFailed(PooledTunnelCreatorConfig cfg) {
void tunnelFailed(PooledTunnelCreatorConfig cfg) {
if (_log.shouldLog(Log.WARN))
_log.warn(toString() + ": Tunnel failed: " + cfg);
LeaseSet ls = null;
@@ -574,9 +595,8 @@ public class TunnelPool {
* the countHowManyToBuild function below)
*
*/
public int countHowManyToBuild() {
if (_settings.getDestination() != null) {
if (!_context.clientManager().isLocal(_settings.getDestination()))
int countHowManyToBuild() {
if (!isAlive()) {
return 0;
}
int wanted = getSettings().getBackupQuantity() + getSettings().getQuantity();

View File

@@ -276,9 +276,9 @@ public class TunnelPoolManager implements TunnelManagerFacade {
* Do not use to change settings.
*/
public void buildTunnels(Destination client, ClientTunnelSettings settings) {
if (_log.shouldLog(Log.DEBUG))
_log.debug("Building tunnels for the client " + client.calculateHash().toBase64() + ": " + settings);
Hash dest = client.calculateHash();
if (_log.shouldLog(Log.DEBUG))
_log.debug("Building tunnels for the client " + dest + ": " + settings);
settings.getInboundSettings().setDestination(dest);
settings.getOutboundSettings().setDestination(dest);
TunnelPool inbound = null;
@@ -311,7 +311,7 @@ public class TunnelPoolManager implements TunnelManagerFacade {
private static class DelayedStartup implements SimpleTimer.TimedEvent {
private TunnelPool pool;
private final TunnelPool pool;
public DelayedStartup(TunnelPool p) {
this.pool = p;
@@ -322,9 +322,14 @@ public class TunnelPoolManager implements TunnelManagerFacade {
}
}
/** synch with buildTunnels() above */
/**
* This will be called twice, once by the inbound and once by the outbound pool.
* Synched with buildTunnels() above.
*/
public synchronized void removeTunnels(Hash destination) {
if (destination == null) return;
if (_log.shouldLog(Log.DEBUG))
_log.debug("Removing tunnels for the client " + destination);
if (_context.clientManager().isLocal(destination)) {
if (_log.shouldLog(Log.CRIT))
_log.log(Log.CRIT, "wtf, why are you removing the pool for " + destination.toBase64(), new Exception("i did it"));