diff --git a/router/java/src/net/i2p/router/InNetMessagePool.java b/router/java/src/net/i2p/router/InNetMessagePool.java index 60a0d9f5f..30777cf9b 100644 --- a/router/java/src/net/i2p/router/InNetMessagePool.java +++ b/router/java/src/net/i2p/router/InNetMessagePool.java @@ -33,18 +33,18 @@ public class InNetMessagePool { private Map _handlerJobBuilders; private InNetMessagePool() { - _messages = new ArrayList(); - _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().createFrequencyStat("inNetPool.duplicate", "How frequently we receive a duplicate message", "InNetPool", new long[] { 60*1000l, 60*60*1000l, 24*60*60*1000l }); + _messages = new ArrayList(); + _handlerJobBuilders = new HashMap(); + 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().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) { - return (HandlerJobBuilder)_handlerJobBuilders.put(new Integer(i2npMessageType), builder); + return (HandlerJobBuilder)_handlerJobBuilders.put(new Integer(i2npMessageType), builder); } 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) { - Date exp = msg.getMessage().getMessageExpiration(); - boolean valid = MessageValidator.getInstance().validateMessage(msg.getMessage().getUniqueId(), exp.getTime()); - if (!valid) { - if (_log.shouldLog(Log.WARN)) - _log.warn("Duplicate message received [" + msg.getMessage().getUniqueId() + " expiring on " + exp + "]: " + msg.getMessage().getClass().getName()); - StatManager.getInstance().updateFrequency("inNetPool.dropped"); - StatManager.getInstance().updateFrequency("inNetPool.duplicate"); - MessageHistory.getInstance().droppedOtherMessage(msg.getMessage()); - MessageHistory.getInstance().messageProcessingError(msg.getMessage().getUniqueId(), msg.getMessage().getClass().getName(), "Duplicate/expired"); - 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 type = msg.getMessage().getType(); - HandlerJobBuilder builder = (HandlerJobBuilder)_handlerJobBuilders.get(new Integer(type)); - - if (_log.shouldLog(Log.DEBUG)) - _log.debug("Add message to the inNetMessage pool - builder: " + builder + " message class: " + msg.getMessage().getClass().getName()); - - if (builder != null) { - Job job = builder.createJob(msg.getMessage(), msg.getFromRouter(), msg.getFromRouterHash(), msg.getReplyBlock()); - if (job != null) { - JobQueue.getInstance().addJob(job); - synchronized (_messages) { - size = _messages.size(); - } - } - } - - List origMessages = OutboundMessageRegistry.getInstance().getOriginalMessages(msg.getMessage()); - if (_log.shouldLog(Log.DEBUG)) - _log.debug("Original messages for inbound message: " + origMessages.size()); - if (origMessages.size() > 1) { - if (_log.shouldLog(Log.DEBUG)) - _log.debug("Orig: " + origMessages + " \nthe above are replies for: " + msg, new Exception("Multiple matches")); - } - - for (int i = 0; i < origMessages.size(); i++) { - OutNetMessage omsg = (OutNetMessage)origMessages.get(i); - ReplyJob job = omsg.getOnReplyJob(); - if (_log.shouldLog(Log.DEBUG)) - _log.debug("Original message [" + i + "] " + omsg.getReplySelector() + " : " + omsg + ": reply job: " + job); - - if (job != null) { - job.setMessage(msg.getMessage()); - JobQueue.getInstance().addJob(job); - } - } - + Date exp = msg.getMessage().getMessageExpiration(); + boolean valid = MessageValidator.getInstance().validateMessage(msg.getMessage().getUniqueId(), exp.getTime()); + if (!valid) { + if (_log.shouldLog(Log.WARN)) + _log.warn("Duplicate message received [" + msg.getMessage().getUniqueId() + + " expiring on " + exp + "]: " + msg.getMessage().getClass().getName()); + StatManager.getInstance().addRateData("inNetPool.dropped", 1, 0); + StatManager.getInstance().addRateData("inNetPool.duplicate", 1, 0); + MessageHistory.getInstance().droppedOtherMessage(msg.getMessage()); + MessageHistory.getInstance().messageProcessingError(msg.getMessage().getUniqueId(), + msg.getMessage().getClass().getName(), + "Duplicate/expired"); + return -1; + } else { + if (_log.shouldLog(Log.DEBUG)) + _log.debug("Message received [" + msg.getMessage().getUniqueId() + + " expiring on " + exp + "] is NOT a duplicate or exipired"); + } - 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().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; + int size = -1; + int type = msg.getMessage().getType(); + HandlerJobBuilder builder = (HandlerJobBuilder)_handlerJobBuilders.get(new Integer(type)); + + if (_log.shouldLog(Log.DEBUG)) + _log.debug("Add message to the inNetMessage pool - builder: " + builder + + " message class: " + msg.getMessage().getClass().getName()); + + if (builder != null) { + Job job = builder.createJob(msg.getMessage(), msg.getFromRouter(), + msg.getFromRouterHash(), msg.getReplyBlock()); + if (job != null) { + JobQueue.getInstance().addJob(job); + synchronized (_messages) { + size = _messages.size(); + } + } + } + + List origMessages = OutboundMessageRegistry.getInstance().getOriginalMessages(msg.getMessage()); + if (_log.shouldLog(Log.DEBUG)) + _log.debug("Original messages for inbound message: " + origMessages.size()); + if (origMessages.size() > 1) { + if (_log.shouldLog(Log.DEBUG)) + _log.debug("Orig: " + origMessages + " \nthe above are replies for: " + msg, + new Exception("Multiple matches")); + } + + for (int i = 0; i < origMessages.size(); i++) { + OutNetMessage omsg = (OutNetMessage)origMessages.get(i); + ReplyJob job = omsg.getOnReplyJob(); + if (_log.shouldLog(Log.DEBUG)) + _log.debug("Original message [" + i + "] " + omsg.getReplySelector() + + " : " + omsg + ": reply job: " + job); + + if (job != null) { + job.setMessage(msg.getMessage()); + 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; + } + } + + 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) { - ArrayList msgs = new ArrayList(maxNumMessages); - synchronized (_messages) { - for (int i = 0; (i < maxNumMessages) && (_messages.size() > 0); i++) - msgs.add(_messages.remove(0)); - } - return msgs; + ArrayList msgs = new ArrayList(maxNumMessages); + synchronized (_messages) { + for (int i = 0; (i < maxNumMessages) && (_messages.size() > 0); i++) + msgs.add(_messages.remove(0)); + } + return msgs; } /** @@ -148,10 +159,10 @@ public class InNetMessagePool { * */ public InNetMessage getNext() { - synchronized (_messages) { - if (_messages.size() <= 0) return null; - return (InNetMessage)_messages.remove(0); - } + synchronized (_messages) { + if (_messages.size() <= 0) return null; + return (InNetMessage)_messages.remove(0); + } } /** @@ -159,23 +170,23 @@ public class InNetMessagePool { * */ public int getCount() { - synchronized (_messages) { - return _messages.size(); - } + synchronized (_messages) { + return _messages.size(); + } } public void dumpPoolInfo() { - if (!_log.shouldLog(Log.DEBUG)) return; - - StringBuffer buf = new StringBuffer(); - buf.append("\nDumping Inbound Network Message Pool. Total # message: ").append(getCount()).append("\n"); - synchronized (_messages) { - for (Iterator iter = _messages.iterator(); iter.hasNext();) { - InNetMessage msg = (InNetMessage)iter.next(); - buf.append("Message ").append(msg.getMessage()).append("\n\n"); - } - } - _log.debug(buf.toString()); + if (!_log.shouldLog(Log.DEBUG)) return; + + StringBuffer buf = new StringBuffer(); + buf.append("\nDumping Inbound Network Message Pool. Total # message: ").append(getCount()).append("\n"); + synchronized (_messages) { + for (Iterator iter = _messages.iterator(); iter.hasNext();) { + InNetMessage msg = (InNetMessage)iter.next(); + buf.append("Message ").append(msg.getMessage()).append("\n\n"); + } + } + _log.debug(buf.toString()); } - + } diff --git a/router/java/src/net/i2p/router/tunnelmanager/ClientTunnelPoolManagerJob.java b/router/java/src/net/i2p/router/tunnelmanager/ClientTunnelPoolManagerJob.java index f5e85fc5e..358d852ef 100644 --- a/router/java/src/net/i2p/router/tunnelmanager/ClientTunnelPoolManagerJob.java +++ b/router/java/src/net/i2p/router/tunnelmanager/ClientTunnelPoolManagerJob.java @@ -2,6 +2,8 @@ package net.i2p.router.tunnelmanager; import java.util.Iterator; import java.util.TreeMap; +import java.util.List; +import java.util.ArrayList; import net.i2p.data.TunnelId; import net.i2p.router.ClientManagerFacade; @@ -25,55 +27,65 @@ class ClientTunnelPoolManagerJob extends JobImpl { private final static long POOL_CHECK_DELAY = 30*1000; public ClientTunnelPoolManagerJob(TunnelPool pool, ClientTunnelPool clientPool) { - super(); - _clientPool = clientPool; - _tunnelPool = pool; + super(); + _clientPool = clientPool; + _tunnelPool = pool; } public String getName() { return "Manage Client Tunnel Pool"; } public void runJob() { - try { - if (_clientPool.isStopped()) { - 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 - 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())) { - _log.info("Client " + _clientPool.getDestination().calculateHash() + " is no longer connected, stop the pool"); - _clientPool.stopPool(); - requeue(POOL_CHECK_DELAY); - return; - } - int requestedPoolSize = _clientPool.getClientSettings().getNumInboundTunnels(); - int safePoolSize = _clientPool.getSafePoolSize(POOL_CHECK_DELAY); - if (safePoolSize < requestedPoolSize) { - requestMoreTunnels(requestedPoolSize-safePoolSize); - } - } catch (Exception t) { - _log.log(Log.CRIT, "Unhandled exception managing the client tunnel pool", t); - } - requeue(POOL_CHECK_DELAY); + try { + if (_clientPool.isStopped()) { + handleStopped(); + return; + } + + if (!ClientManagerFacade.getInstance().isLocal(_clientPool.getDestination())) { + if (_log.shouldLog(Log.INFO)) + _log.info("Client " + _clientPool.getDestination().calculateHash() + + " is no longer connected, stop the pool"); + _clientPool.stopPool(); + requeue(POOL_CHECK_DELAY); + return; + } + int requestedPoolSize = _clientPool.getClientSettings().getNumInboundTunnels(); + int safePoolSize = _clientPool.getSafePoolSize(POOL_CHECK_DELAY); + if (safePoolSize < requestedPoolSize) { + requestMoreTunnels(requestedPoolSize-safePoolSize); + } + } catch (Exception t) { + _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) { - int allocated = 0; - TreeMap goodEnoughTunnels = new TreeMap(); - int maxLength = _tunnelPool.getLongestTunnelLength(); - for (Iterator iter = _tunnelPool.getFreeTunnels().iterator(); iter.hasNext() && allocated < numTunnels; ) { - 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 - 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) { - requestCustomTunnels(numTunnels - allocated); - } else { - _log.debug("Sufficient tunnels exist in the client pool for " + _clientPool.getDestination().calculateHash() + " w3wt"); - // done! w00t - } + if (_clientPool.getClientSettings().getDepthInbound() < 1) { + // the client wants 0-hop tunnels, so don't waste longer tunnels on them + requestCustomTunnels(numTunnels); + return; + } + + int allocated = allocateExisting(numTunnels); + + if (allocated < numTunnels) { + requestCustomTunnels(numTunnels - allocated); + } else { + if (_log.shouldLog(Log.DEBUG)) + _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) { - if (!info.getIsReady()) { - if (_log.shouldLog(Log.DEBUG)) - _log.debug("Refusing tunnel " + info.getTunnelId() + " because it isn't ready"); - return false; - } + if (!info.getIsReady()) { + if (_log.shouldLog(Log.DEBUG)) + _log.debug("Refusing tunnel " + info.getTunnelId() + " because it isn't ready"); + return false; + } - long expireAfter = Clock.getInstance().now() + POOL_CHECK_DELAY + _tunnelPool.getTunnelCreationTimeout()*2; - if (info.getSettings().getExpiration() <= expireAfter) { - if (_log.shouldLog(Log.DEBUG)) - _log.debug("Refusing tunnel " + info.getTunnelId() + " because it is going to expire soon"); - return false; - } + long expireAfter = Clock.getInstance().now() + POOL_CHECK_DELAY + _tunnelPool.getTunnelCreationTimeout()*2; + if (info.getSettings().getExpiration() <= expireAfter) { + if (_log.shouldLog(Log.DEBUG)) + _log.debug("Refusing tunnel " + info.getTunnelId() + " because it is going to expire soon"); + return false; + } - int length = info.getLength(); - if (_clientPool.getClientSettings().getEnforceStrictMinimumLength()) { - if (length < _clientPool.getClientSettings().getDepthInbound()) { - // we will require at least the client's length, but they dont meet it - if (_log.shouldLog(Log.DEBUG)) - _log.debug("Refusing tunnel " + info.getTunnelId() + " because it is too short (length = " + length + - ", wanted = " + _clientPool.getClientSettings().getDepthInbound() + ")"); - return false; - } else { - // its long enough. w00t - } - } else { - if (length < _clientPool.getClientSettings().getDepthInbound() && (length < max)) { - // while we will still strive to meet the client's needs, we will be satisfied with - // the best we have on hand (which may be less that their requested length) - // this tunnel however meets neither criteria - if (_log.shouldLog(Log.DEBUG)) - _log.debug("Refusing tunnel " + info.getTunnelId() + " because it is too short (length = " + length + - ", wanted = " + _clientPool.getClientSettings().getDepthInbound() + ")"); - return false; - } 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 (!_clientPool.getDestination().equals(info.getDestination())) { - if (_log.shouldLog(Log.INFO)) - _log.info("Refusing tunnel " + info.getTunnelId() + " because it was requested specifically for another destination [" + info.getDestination().calculateHash() + "]"); - return false; - } - } - - if (_log.shouldLog(Log.DEBUG)) - _log.debug("Accepting tunnel " + info.getTunnelId()); - return true; + int length = info.getLength(); + if (_clientPool.getClientSettings().getEnforceStrictMinimumLength()) { + if (length < _clientPool.getClientSettings().getDepthInbound()) { + // we will require at least the client's length, but they dont meet it + if (_log.shouldLog(Log.DEBUG)) + _log.debug("Refusing tunnel " + info.getTunnelId() + + " because it is too short (length = " + length + + ", wanted = " + _clientPool.getClientSettings().getDepthInbound() + + ")"); + return false; + } else { + // its long enough. w00t + } + } else { + if (length < _clientPool.getClientSettings().getDepthInbound() && (length < max)) { + // while we will still strive to meet the client's needs, we will be satisfied with + // the best we have on hand (which may be less that their requested length) + // this tunnel however meets neither criteria + if (_log.shouldLog(Log.DEBUG)) + _log.debug("Refusing tunnel " + info.getTunnelId() + + " because it is too short (length = " + length + + ", wanted = " + _clientPool.getClientSettings().getDepthInbound() + + ")"); + return false; + } 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 (!_clientPool.getDestination().equals(info.getDestination())) { + if (_log.shouldLog(Log.INFO)) + _log.info("Refusing tunnel " + info.getTunnelId() + + " because it was requested specifically for another destination [" + + info.getDestination().calculateHash() + "]"); + return false; + } + } + + if (_log.shouldLog(Log.DEBUG)) + _log.debug("Accepting tunnel " + info.getTunnelId()); + return true; } /** @@ -180,9 +228,9 @@ class ClientTunnelPoolManagerJob extends JobImpl { * This fires off a series of RequestCustomTunnelJobs */ private void requestCustomTunnels(int numTunnels) { - for (int i = 0; i < numTunnels; i++) { - JobQueue.getInstance().addJob(new RequestCustomTunnelJob()); - } + for (int i = 0; i < numTunnels; i++) { + JobQueue.getInstance().addJob(new RequestCustomTunnelJob()); + } } /** @@ -191,11 +239,11 @@ class ClientTunnelPoolManagerJob extends JobImpl { * */ private class RequestCustomTunnelJob extends JobImpl { - public String getName() { return "Request Custom Client Tunnel"; } - public void runJob() { - TunnelInfo tunnelGateway = TunnelBuilder.getInstance().configureInboundTunnel(_clientPool.getDestination(), _clientPool.getClientSettings()); - RequestTunnelJob reqJob = new RequestTunnelJob(_tunnelPool, tunnelGateway, true, _tunnelPool.getTunnelCreationTimeout()); - JobQueue.getInstance().addJob(reqJob); - } + public String getName() { return "Request Custom Client Tunnel"; } + public void runJob() { + TunnelInfo tunnelGateway = TunnelBuilder.getInstance().configureInboundTunnel(_clientPool.getDestination(), _clientPool.getClientSettings()); + RequestTunnelJob reqJob = new RequestTunnelJob(_tunnelPool, tunnelGateway, true, _tunnelPool.getTunnelCreationTimeout()); + JobQueue.getInstance().addJob(reqJob); + } } } diff --git a/router/java/src/net/i2p/router/tunnelmanager/TunnelPool.java b/router/java/src/net/i2p/router/tunnelmanager/TunnelPool.java index b7c03fe81..862db7dcb 100644 --- a/router/java/src/net/i2p/router/tunnelmanager/TunnelPool.java +++ b/router/java/src/net/i2p/router/tunnelmanager/TunnelPool.java @@ -243,6 +243,10 @@ class TunnelPool { synchronized (_pendingTunnels) { _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) { if (!_isLive) return null;