short circuit some handling when building custom length tunnels

if a client only wants 0 hop tunnels, give them 0 hop tunnels (rather than wasting a 2+ hop on it)
make inNetPool.dropped and inNetPool.duplicate rate stats, not frequency stats
formatting, minor refactoring
This commit is contained in:
jrandom
2004-04-20 02:42:56 +00:00
committed by zzz
parent ba5f0fb70b
commit 3c762c9a02
3 changed files with 303 additions and 240 deletions

View File

@@ -33,18 +33,18 @@ public class InNetMessagePool {
private Map _handlerJobBuilders; private Map _handlerJobBuilders;
private InNetMessagePool() { private InNetMessagePool() {
_messages = new ArrayList(); _messages = new ArrayList();
_handlerJobBuilders = new HashMap(); _handlerJobBuilders = new HashMap();
StatManager.getInstance().createFrequencyStat("inNetPool.dropped", "How frequently we drop a message", "InNetPool", new long[] { 60*1000l, 60*60*1000l, 24*60*60*1000l }); StatManager.getInstance().createRateStat("inNetPool.dropped", "How often do we drop a message", "InNetPool", new long[] { 60*1000l, 60*60*1000l, 24*60*60*1000l });
StatManager.getInstance().createFrequencyStat("inNetPool.duplicate", "How frequently we receive a duplicate message", "InNetPool", new long[] { 60*1000l, 60*60*1000l, 24*60*60*1000l }); StatManager.getInstance().createRateStat("inNetPool.duplicate", "How often do we receive a duplicate message", "InNetPool", new long[] { 60*1000l, 60*60*1000l, 24*60*60*1000l });
} }
public HandlerJobBuilder registerHandlerJobBuilder(int i2npMessageType, HandlerJobBuilder builder) { public HandlerJobBuilder registerHandlerJobBuilder(int i2npMessageType, HandlerJobBuilder builder) {
return (HandlerJobBuilder)_handlerJobBuilders.put(new Integer(i2npMessageType), builder); return (HandlerJobBuilder)_handlerJobBuilders.put(new Integer(i2npMessageType), builder);
} }
public HandlerJobBuilder unregisterHandlerJobBuilder(int i2npMessageType) { public HandlerJobBuilder unregisterHandlerJobBuilder(int i2npMessageType) {
return (HandlerJobBuilder)_handlerJobBuilders.remove(new Integer(i2npMessageType)); return (HandlerJobBuilder)_handlerJobBuilders.remove(new Integer(i2npMessageType));
} }
/** /**
@@ -56,78 +56,89 @@ public class InNetMessagePool {
* *
*/ */
public int add(InNetMessage msg) { public int add(InNetMessage msg) {
Date exp = msg.getMessage().getMessageExpiration(); Date exp = msg.getMessage().getMessageExpiration();
boolean valid = MessageValidator.getInstance().validateMessage(msg.getMessage().getUniqueId(), exp.getTime()); boolean valid = MessageValidator.getInstance().validateMessage(msg.getMessage().getUniqueId(), exp.getTime());
if (!valid) { if (!valid) {
if (_log.shouldLog(Log.WARN)) if (_log.shouldLog(Log.WARN))
_log.warn("Duplicate message received [" + msg.getMessage().getUniqueId() + " expiring on " + exp + "]: " + msg.getMessage().getClass().getName()); _log.warn("Duplicate message received [" + msg.getMessage().getUniqueId()
StatManager.getInstance().updateFrequency("inNetPool.dropped"); + " expiring on " + exp + "]: " + msg.getMessage().getClass().getName());
StatManager.getInstance().updateFrequency("inNetPool.duplicate"); StatManager.getInstance().addRateData("inNetPool.dropped", 1, 0);
MessageHistory.getInstance().droppedOtherMessage(msg.getMessage()); StatManager.getInstance().addRateData("inNetPool.duplicate", 1, 0);
MessageHistory.getInstance().messageProcessingError(msg.getMessage().getUniqueId(), msg.getMessage().getClass().getName(), "Duplicate/expired"); MessageHistory.getInstance().droppedOtherMessage(msg.getMessage());
return -1; MessageHistory.getInstance().messageProcessingError(msg.getMessage().getUniqueId(),
} else { msg.getMessage().getClass().getName(),
if (_log.shouldLog(Log.DEBUG)) "Duplicate/expired");
_log.debug("Message received [" + msg.getMessage().getUniqueId() + " expiring on " + exp + "] is NOT a duplicate or exipired"); return -1;
} } else {
if (_log.shouldLog(Log.DEBUG))
_log.debug("Message received [" + msg.getMessage().getUniqueId()
+ " expiring on " + exp + "] is NOT a duplicate or exipired");
}
int size = -1; int size = -1;
int type = msg.getMessage().getType(); int type = msg.getMessage().getType();
HandlerJobBuilder builder = (HandlerJobBuilder)_handlerJobBuilders.get(new Integer(type)); HandlerJobBuilder builder = (HandlerJobBuilder)_handlerJobBuilders.get(new Integer(type));
if (_log.shouldLog(Log.DEBUG)) if (_log.shouldLog(Log.DEBUG))
_log.debug("Add message to the inNetMessage pool - builder: " + builder + " message class: " + msg.getMessage().getClass().getName()); _log.debug("Add message to the inNetMessage pool - builder: " + builder
+ " message class: " + msg.getMessage().getClass().getName());
if (builder != null) { if (builder != null) {
Job job = builder.createJob(msg.getMessage(), msg.getFromRouter(), msg.getFromRouterHash(), msg.getReplyBlock()); Job job = builder.createJob(msg.getMessage(), msg.getFromRouter(),
if (job != null) { msg.getFromRouterHash(), msg.getReplyBlock());
JobQueue.getInstance().addJob(job); if (job != null) {
synchronized (_messages) { JobQueue.getInstance().addJob(job);
size = _messages.size(); synchronized (_messages) {
} size = _messages.size();
} }
} }
}
List origMessages = OutboundMessageRegistry.getInstance().getOriginalMessages(msg.getMessage()); List origMessages = OutboundMessageRegistry.getInstance().getOriginalMessages(msg.getMessage());
if (_log.shouldLog(Log.DEBUG)) if (_log.shouldLog(Log.DEBUG))
_log.debug("Original messages for inbound message: " + origMessages.size()); _log.debug("Original messages for inbound message: " + origMessages.size());
if (origMessages.size() > 1) { if (origMessages.size() > 1) {
if (_log.shouldLog(Log.DEBUG)) if (_log.shouldLog(Log.DEBUG))
_log.debug("Orig: " + origMessages + " \nthe above are replies for: " + msg, new Exception("Multiple matches")); _log.debug("Orig: " + origMessages + " \nthe above are replies for: " + msg,
} new Exception("Multiple matches"));
}
for (int i = 0; i < origMessages.size(); i++) { for (int i = 0; i < origMessages.size(); i++) {
OutNetMessage omsg = (OutNetMessage)origMessages.get(i); OutNetMessage omsg = (OutNetMessage)origMessages.get(i);
ReplyJob job = omsg.getOnReplyJob(); ReplyJob job = omsg.getOnReplyJob();
if (_log.shouldLog(Log.DEBUG)) if (_log.shouldLog(Log.DEBUG))
_log.debug("Original message [" + i + "] " + omsg.getReplySelector() + " : " + omsg + ": reply job: " + job); _log.debug("Original message [" + i + "] " + omsg.getReplySelector()
+ " : " + omsg + ": reply job: " + job);
if (job != null) { if (job != null) {
job.setMessage(msg.getMessage()); job.setMessage(msg.getMessage());
JobQueue.getInstance().addJob(job); JobQueue.getInstance().addJob(job);
} }
} }
if (origMessages.size() <= 0) {
// not handled as a reply
if (size == -1) {
// was not handled via HandlerJobBuilder
MessageHistory.getInstance().droppedOtherMessage(msg.getMessage());
if (_log.shouldLog(Log.ERROR))
_log.error("Message " + msg.getMessage() + " was not handled by a HandlerJobBuilder - DROPPING: "
+ msg, new Exception("DROPPED MESSAGE"));
StatManager.getInstance().addRateData("inNetPool.dropped", 1, 0);
} else {
String mtype = msg.getMessage().getClass().getName();
MessageHistory.getInstance().receiveMessage(mtype, msg.getMessage().getUniqueId(),
msg.getMessage().getMessageExpiration(),
msg.getFromRouterHash(), true);
return size;
}
}
if (origMessages.size() <= 0) { String mtype = msg.getMessage().getClass().getName();
// not handled as a reply MessageHistory.getInstance().receiveMessage(mtype, msg.getMessage().getUniqueId(),
if (size == -1) { msg.getMessage().getMessageExpiration(),
// was not handled via HandlerJobBuilder msg.getFromRouterHash(), true);
MessageHistory.getInstance().droppedOtherMessage(msg.getMessage()); return size;
if (_log.shouldLog(Log.ERROR))
_log.error("Message " + msg.getMessage() + " was not handled by a HandlerJobBuilder - DROPPING: " + msg, new Exception("DROPPED MESSAGE"));
StatManager.getInstance().updateFrequency("inNetPool.dropped");
//_log.error("Pending registry: \n" + OutboundMessageRegistry.getInstance().renderStatusHTML());
} else {
String mtype = msg.getMessage().getClass().getName();
MessageHistory.getInstance().receiveMessage(mtype, msg.getMessage().getUniqueId(), msg.getMessage().getMessageExpiration(), msg.getFromRouterHash(), true);
return size;
}
}
String mtype = msg.getMessage().getClass().getName();
MessageHistory.getInstance().receiveMessage(mtype, msg.getMessage().getUniqueId(), msg.getMessage().getMessageExpiration(), msg.getFromRouterHash(), true);
return size;
} }
/** /**
@@ -135,12 +146,12 @@ public class InNetMessagePool {
* *
*/ */
public List getNext(int maxNumMessages) { public List getNext(int maxNumMessages) {
ArrayList msgs = new ArrayList(maxNumMessages); ArrayList msgs = new ArrayList(maxNumMessages);
synchronized (_messages) { synchronized (_messages) {
for (int i = 0; (i < maxNumMessages) && (_messages.size() > 0); i++) for (int i = 0; (i < maxNumMessages) && (_messages.size() > 0); i++)
msgs.add(_messages.remove(0)); msgs.add(_messages.remove(0));
} }
return msgs; return msgs;
} }
/** /**
@@ -148,10 +159,10 @@ public class InNetMessagePool {
* *
*/ */
public InNetMessage getNext() { public InNetMessage getNext() {
synchronized (_messages) { synchronized (_messages) {
if (_messages.size() <= 0) return null; if (_messages.size() <= 0) return null;
return (InNetMessage)_messages.remove(0); return (InNetMessage)_messages.remove(0);
} }
} }
/** /**
@@ -159,23 +170,23 @@ public class InNetMessagePool {
* *
*/ */
public int getCount() { public int getCount() {
synchronized (_messages) { synchronized (_messages) {
return _messages.size(); return _messages.size();
} }
} }
public void dumpPoolInfo() { public void dumpPoolInfo() {
if (!_log.shouldLog(Log.DEBUG)) return; if (!_log.shouldLog(Log.DEBUG)) return;
StringBuffer buf = new StringBuffer(); StringBuffer buf = new StringBuffer();
buf.append("\nDumping Inbound Network Message Pool. Total # message: ").append(getCount()).append("\n"); buf.append("\nDumping Inbound Network Message Pool. Total # message: ").append(getCount()).append("\n");
synchronized (_messages) { synchronized (_messages) {
for (Iterator iter = _messages.iterator(); iter.hasNext();) { for (Iterator iter = _messages.iterator(); iter.hasNext();) {
InNetMessage msg = (InNetMessage)iter.next(); InNetMessage msg = (InNetMessage)iter.next();
buf.append("Message ").append(msg.getMessage()).append("\n\n"); buf.append("Message ").append(msg.getMessage()).append("\n\n");
} }
} }
_log.debug(buf.toString()); _log.debug(buf.toString());
} }
} }

View File

@@ -2,6 +2,8 @@ package net.i2p.router.tunnelmanager;
import java.util.Iterator; import java.util.Iterator;
import java.util.TreeMap; import java.util.TreeMap;
import java.util.List;
import java.util.ArrayList;
import net.i2p.data.TunnelId; import net.i2p.data.TunnelId;
import net.i2p.router.ClientManagerFacade; import net.i2p.router.ClientManagerFacade;
@@ -25,55 +27,65 @@ class ClientTunnelPoolManagerJob extends JobImpl {
private final static long POOL_CHECK_DELAY = 30*1000; private final static long POOL_CHECK_DELAY = 30*1000;
public ClientTunnelPoolManagerJob(TunnelPool pool, ClientTunnelPool clientPool) { public ClientTunnelPoolManagerJob(TunnelPool pool, ClientTunnelPool clientPool) {
super(); super();
_clientPool = clientPool; _clientPool = clientPool;
_tunnelPool = pool; _tunnelPool = pool;
} }
public String getName() { return "Manage Client Tunnel Pool"; } public String getName() { return "Manage Client Tunnel Pool"; }
public void runJob() { public void runJob() {
try { try {
if (_clientPool.isStopped()) { if (_clientPool.isStopped()) {
if (ClientManagerFacade.getInstance().isLocal(_clientPool.getDestination())) { handleStopped();
// it was stopped, but they've reconnected, so boot 'er up again return;
if (_log.shouldLog(Log.INFO)) }
_log.info("Client " + _clientPool.getDestination().calculateHash().toBase64() + " was stopped, but reconnected! restarting it");
_clientPool.startPool();
// we return directly, since it'll queue up jobs again, etc
return;
} else {
// not currently connected - check to see whether all of the tunnels have expired
if ((_clientPool.getInactiveInboundTunnelIds().size() > 0) ||
(_clientPool.getInboundTunnelIds().size() > 0) ) {
// there are tunnels left, requeue until later (in case the client reconnects
if (_log.shouldLog(Log.DEBUG))
_log.debug("There are tunnels left, though the client is still disconnected: " + _clientPool.getDestination().calculateHash());
requeue(POOL_CHECK_DELAY);
return;
} else {
// no tunnels left and the client is still disconnected, screw the pool
if (_log.shouldLog(Log.INFO))
_log.info("No more tunnels left and the client has disconnected: " + _clientPool.getDestination().calculateHash());
_tunnelPool.removeClientPool(_clientPool.getDestination());
return;
}
}
}
if (!ClientManagerFacade.getInstance().isLocal(_clientPool.getDestination())) { if (!ClientManagerFacade.getInstance().isLocal(_clientPool.getDestination())) {
_log.info("Client " + _clientPool.getDestination().calculateHash() + " is no longer connected, stop the pool"); if (_log.shouldLog(Log.INFO))
_clientPool.stopPool(); _log.info("Client " + _clientPool.getDestination().calculateHash()
requeue(POOL_CHECK_DELAY); + " is no longer connected, stop the pool");
return; _clientPool.stopPool();
} requeue(POOL_CHECK_DELAY);
int requestedPoolSize = _clientPool.getClientSettings().getNumInboundTunnels(); return;
int safePoolSize = _clientPool.getSafePoolSize(POOL_CHECK_DELAY); }
if (safePoolSize < requestedPoolSize) { int requestedPoolSize = _clientPool.getClientSettings().getNumInboundTunnels();
requestMoreTunnels(requestedPoolSize-safePoolSize); int safePoolSize = _clientPool.getSafePoolSize(POOL_CHECK_DELAY);
} if (safePoolSize < requestedPoolSize) {
} catch (Exception t) { requestMoreTunnels(requestedPoolSize-safePoolSize);
_log.log(Log.CRIT, "Unhandled exception managing the client tunnel pool", t); }
} } catch (Exception t) {
requeue(POOL_CHECK_DELAY); _log.log(Log.CRIT, "Unhandled exception managing the client tunnel pool", t);
}
requeue(POOL_CHECK_DELAY);
}
/**
* The pool is stopped, so lets see if we should keep doing anything
*/
private void handleStopped() {
if (ClientManagerFacade.getInstance().isLocal(_clientPool.getDestination())) {
// it was stopped, but they've reconnected, so boot 'er up again
if (_log.shouldLog(Log.INFO))
_log.info("Client " + _clientPool.getDestination().calculateHash().toBase64()
+ " was stopped, but reconnected! restarting it");
_clientPool.startPool();
// we return directly, since it'll queue up jobs again, etc
} else {
// not currently connected - check to see whether all of the tunnels have expired
if ((_clientPool.getInactiveInboundTunnelIds().size() > 0) ||
(_clientPool.getInboundTunnelIds().size() > 0) ) {
// there are tunnels left, requeue until later (in case the client reconnects
if (_log.shouldLog(Log.DEBUG))
_log.debug("There are tunnels left, though the client is still disconnected: "
+ _clientPool.getDestination().calculateHash());
requeue(POOL_CHECK_DELAY);
} else {
// no tunnels left and the client is still disconnected, screw the pool
if (_log.shouldLog(Log.INFO))
_log.info("No more tunnels left and the client has disconnected: "
+ _clientPool.getDestination().calculateHash());
_tunnelPool.removeClientPool(_clientPool.getDestination());
}
}
} }
/** /**
@@ -81,39 +93,68 @@ class ClientTunnelPoolManagerJob extends JobImpl {
* *
*/ */
private void requestMoreTunnels(int numTunnels) { private void requestMoreTunnels(int numTunnels) {
int allocated = 0; if (_clientPool.getClientSettings().getDepthInbound() < 1) {
TreeMap goodEnoughTunnels = new TreeMap(); // the client wants 0-hop tunnels, so don't waste longer tunnels on them
int maxLength = _tunnelPool.getLongestTunnelLength(); requestCustomTunnels(numTunnels);
for (Iterator iter = _tunnelPool.getFreeTunnels().iterator(); iter.hasNext() && allocated < numTunnels; ) { return;
TunnelId id = (TunnelId)iter.next(); }
TunnelInfo info = _tunnelPool.getFreeTunnel(id);
if (info != null) {
if (isGoodEnough(info, maxLength)) {
goodEnoughTunnels.put(new Long(0 - info.getSettings().getExpiration()), id);
}
}
}
// good enough tunnels, ordered with the longest from now duration first int allocated = allocateExisting(numTunnels);
for (Iterator iter = goodEnoughTunnels.values().iterator(); iter.hasNext() && allocated < numTunnels; ) {
TunnelId id = (TunnelId)iter.next();
TunnelInfo info = _tunnelPool.getTunnelInfo(id);
if (info.getLength() < _clientPool.getClientSettings().getDepthInbound()) {
// this aint good 'nuff...
continue;
}
boolean ok = _tunnelPool.allocateTunnel(id, _clientPool.getDestination());
if (ok) {
allocated++;
}
}
if (allocated < numTunnels) { if (allocated < numTunnels) {
requestCustomTunnels(numTunnels - allocated); requestCustomTunnels(numTunnels - allocated);
} else { } else {
_log.debug("Sufficient tunnels exist in the client pool for " + _clientPool.getDestination().calculateHash() + " w3wt"); if (_log.shouldLog(Log.DEBUG))
// done! w00t _log.debug("Sufficient tunnels exist in the client pool for "
} + _clientPool.getDestination().calculateHash() + " w3wt");
// done! w00t
}
}
/**
* Grab any existing tunnels that can be allocated to the client and do so
*
* @return number of tunnels allocated
*/
private int allocateExisting(int numTunnels) {
int allocated = 0;
Iterator iter = selectGoodEnough(numTunnels).iterator();
// good enough tunnels, ordered with the longest from now duration first
while (iter.hasNext() && allocated < numTunnels) {
TunnelId id = (TunnelId)iter.next();
TunnelInfo info = _tunnelPool.getTunnelInfo(id);
if (info.getLength() < _clientPool.getClientSettings().getDepthInbound()) {
// this aint good 'nuff...
continue;
}
boolean ok = _tunnelPool.allocateTunnel(id, _clientPool.getDestination());
if (ok) {
allocated++;
}
}
return allocated;
}
/**
* Find up to the specified number of existing free inbound tunnels that meet
* the client's conditions.
*
* @return list of TunnelId values of qualified tunnels
*/
private List selectGoodEnough(int numTunnels) {
TreeMap rv = new TreeMap();
int maxLength = _tunnelPool.getLongestTunnelLength();
Iterator iter = _tunnelPool.getFreeTunnels().iterator();
while(iter.hasNext() && rv.size() < numTunnels) {
TunnelId id = (TunnelId)iter.next();
TunnelInfo info = _tunnelPool.getFreeTunnel(id);
if (info != null) {
if (isGoodEnough(info, maxLength)) {
rv.put(new Long(0 - info.getSettings().getExpiration()), id);
}
}
}
return new ArrayList(rv.values());
} }
/** /**
@@ -121,58 +162,65 @@ class ClientTunnelPoolManagerJob extends JobImpl {
* *
*/ */
private boolean isGoodEnough(TunnelInfo info, int max) { private boolean isGoodEnough(TunnelInfo info, int max) {
if (!info.getIsReady()) { if (!info.getIsReady()) {
if (_log.shouldLog(Log.DEBUG)) if (_log.shouldLog(Log.DEBUG))
_log.debug("Refusing tunnel " + info.getTunnelId() + " because it isn't ready"); _log.debug("Refusing tunnel " + info.getTunnelId() + " because it isn't ready");
return false; return false;
} }
long expireAfter = Clock.getInstance().now() + POOL_CHECK_DELAY + _tunnelPool.getTunnelCreationTimeout()*2; long expireAfter = Clock.getInstance().now() + POOL_CHECK_DELAY + _tunnelPool.getTunnelCreationTimeout()*2;
if (info.getSettings().getExpiration() <= expireAfter) { if (info.getSettings().getExpiration() <= expireAfter) {
if (_log.shouldLog(Log.DEBUG)) if (_log.shouldLog(Log.DEBUG))
_log.debug("Refusing tunnel " + info.getTunnelId() + " because it is going to expire soon"); _log.debug("Refusing tunnel " + info.getTunnelId() + " because it is going to expire soon");
return false; return false;
} }
int length = info.getLength(); int length = info.getLength();
if (_clientPool.getClientSettings().getEnforceStrictMinimumLength()) { if (_clientPool.getClientSettings().getEnforceStrictMinimumLength()) {
if (length < _clientPool.getClientSettings().getDepthInbound()) { if (length < _clientPool.getClientSettings().getDepthInbound()) {
// we will require at least the client's length, but they dont meet it // we will require at least the client's length, but they dont meet it
if (_log.shouldLog(Log.DEBUG)) if (_log.shouldLog(Log.DEBUG))
_log.debug("Refusing tunnel " + info.getTunnelId() + " because it is too short (length = " + length + _log.debug("Refusing tunnel " + info.getTunnelId()
", wanted = " + _clientPool.getClientSettings().getDepthInbound() + ")"); + " because it is too short (length = " + length
return false; + ", wanted = " + _clientPool.getClientSettings().getDepthInbound()
} else { + ")");
// its long enough. w00t return false;
} } else {
} else { // its long enough. w00t
if (length < _clientPool.getClientSettings().getDepthInbound() && (length < max)) { }
// while we will still strive to meet the client's needs, we will be satisfied with } else {
// the best we have on hand (which may be less that their requested length) if (length < _clientPool.getClientSettings().getDepthInbound() && (length < max)) {
// this tunnel however meets neither criteria // while we will still strive to meet the client's needs, we will be satisfied with
if (_log.shouldLog(Log.DEBUG)) // the best we have on hand (which may be less that their requested length)
_log.debug("Refusing tunnel " + info.getTunnelId() + " because it is too short (length = " + length + // this tunnel however meets neither criteria
", wanted = " + _clientPool.getClientSettings().getDepthInbound() + ")"); if (_log.shouldLog(Log.DEBUG))
return false; _log.debug("Refusing tunnel " + info.getTunnelId()
} else { + " because it is too short (length = " + length
// either its long enough, or its the longest we have. + ", wanted = " + _clientPool.getClientSettings().getDepthInbound()
// if we want to be strict, specify tunnels.enforceStrictMinimumLength either in the JVM environment + ")");
// via -Dtunnels.enforceStrictMinimumLength=true or in the router.config return false;
// (tunnels.enforceStrictMinimumLength=true) } else {
} // either its long enough, or its the longest we have.
} // if we want to be strict, specify tunnels.enforceStrictMinimumLength either
// in the JVM environment via
// -Dtunnels.enforceStrictMinimumLength=true or in the router.config
// (tunnels.enforceStrictMinimumLength=true)
}
}
if (info.getDestination() != null) { if (info.getDestination() != null) {
if (!_clientPool.getDestination().equals(info.getDestination())) { if (!_clientPool.getDestination().equals(info.getDestination())) {
if (_log.shouldLog(Log.INFO)) if (_log.shouldLog(Log.INFO))
_log.info("Refusing tunnel " + info.getTunnelId() + " because it was requested specifically for another destination [" + info.getDestination().calculateHash() + "]"); _log.info("Refusing tunnel " + info.getTunnelId()
return false; + " because it was requested specifically for another destination ["
} + info.getDestination().calculateHash() + "]");
} return false;
}
}
if (_log.shouldLog(Log.DEBUG)) if (_log.shouldLog(Log.DEBUG))
_log.debug("Accepting tunnel " + info.getTunnelId()); _log.debug("Accepting tunnel " + info.getTunnelId());
return true; return true;
} }
/** /**
@@ -180,9 +228,9 @@ class ClientTunnelPoolManagerJob extends JobImpl {
* This fires off a series of RequestCustomTunnelJobs * This fires off a series of RequestCustomTunnelJobs
*/ */
private void requestCustomTunnels(int numTunnels) { private void requestCustomTunnels(int numTunnels) {
for (int i = 0; i < numTunnels; i++) { for (int i = 0; i < numTunnels; i++) {
JobQueue.getInstance().addJob(new RequestCustomTunnelJob()); JobQueue.getInstance().addJob(new RequestCustomTunnelJob());
} }
} }
/** /**
@@ -191,11 +239,11 @@ class ClientTunnelPoolManagerJob extends JobImpl {
* *
*/ */
private class RequestCustomTunnelJob extends JobImpl { private class RequestCustomTunnelJob extends JobImpl {
public String getName() { return "Request Custom Client Tunnel"; } public String getName() { return "Request Custom Client Tunnel"; }
public void runJob() { public void runJob() {
TunnelInfo tunnelGateway = TunnelBuilder.getInstance().configureInboundTunnel(_clientPool.getDestination(), _clientPool.getClientSettings()); TunnelInfo tunnelGateway = TunnelBuilder.getInstance().configureInboundTunnel(_clientPool.getDestination(), _clientPool.getClientSettings());
RequestTunnelJob reqJob = new RequestTunnelJob(_tunnelPool, tunnelGateway, true, _tunnelPool.getTunnelCreationTimeout()); RequestTunnelJob reqJob = new RequestTunnelJob(_tunnelPool, tunnelGateway, true, _tunnelPool.getTunnelCreationTimeout());
JobQueue.getInstance().addJob(reqJob); JobQueue.getInstance().addJob(reqJob);
} }
} }
} }

View File

@@ -243,6 +243,10 @@ class TunnelPool {
synchronized (_pendingTunnels) { synchronized (_pendingTunnels) {
_pendingTunnels.remove(tunnel.getTunnelId()); _pendingTunnels.remove(tunnel.getTunnelId());
} }
if (tunnel.getDestination() != null) {
// this one was custom built, so tack 'er on directly
allocateTunnel(tunnel.getTunnelId(), tunnel.getDestination());
}
} }
public TunnelInfo removeFreeTunnel(TunnelId id) { public TunnelInfo removeFreeTunnel(TunnelId id) {
if (!_isLive) return null; if (!_isLive) return null;