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:
@ -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());
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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;
|
||||
|
Reference in New Issue
Block a user