* Tunnels:

- Make most classes package private
    - Final, static, logs, cleanups
    - Consolideate createRateStat calls
    - Add getTotalLength()
    - Remove unused lengthOverride()
This commit is contained in:
zzz
2011-10-25 21:39:32 +00:00
parent ef93532c96
commit 157a78857d
38 changed files with 212 additions and 177 deletions

View File

@ -63,6 +63,7 @@ public class ConfigTunnelsHelper extends HelperBase {
private static final int MAX_BACKUP_QUANTITY = 3;
private static final int MAX_VARIANCE = 2;
private static final int MIN_NEG_VARIANCE = -1;
private void renderForm(StringBuilder buf, int index, String prefix, String name, TunnelPoolSettings in, TunnelPoolSettings out) {
buf.append("<tr><th colspan=\"3\"><a name=\"").append(prefix).append("\">");
@ -80,8 +81,8 @@ public class ConfigTunnelsHelper extends HelperBase {
if (in.getLength() + Math.abs(in.getLengthVariance()) >= WARN_LENGTH ||
out.getLength() + Math.abs(out.getLengthVariance()) >= WARN_LENGTH)
buf.append("<tr><th colspan=\"3\"><font color=\"red\">" + _("PERFORMANCE WARNING - Settings include very long tunnels.") + "</font></th></tr>");
if (in.getQuantity() + in.getBackupQuantity() >= WARN_QUANTITY ||
out.getQuantity() + out.getBackupQuantity() >= WARN_QUANTITY)
if (in.getTotalQuantity() >= WARN_QUANTITY ||
out.getTotalQuantity() >= WARN_QUANTITY)
buf.append("<tr><th colspan=\"3\"><font color=\"red\">" + _("PERFORMANCE WARNING - Settings include high tunnel quantities.") + "</font></th></tr>");
buf.append("<tr><th></th><th><img src=\"/themes/console/images/inbound.png\" alt=\"Inbound\" title=\"Inbound Tunnels\">&nbsp;&nbsp;" + _("Inbound") + "</th><th><img src=\"/themes/console/images/outbound.png\" alt=\"Outbound Tunnels\" title=\"Outbound\">&nbsp;&nbsp;" + _("Outbound") + "</th></tr>\n");

View File

@ -1,3 +1,15 @@
2011-10-25 zzz
* BloomSHA1, DecayingBloomFilter:
- Refactor for concurrent, at some small risk of false negatives
- Optimizations to cache objects and reuse offsets
* Tunnels:
- Make most classes package private
- Final, static, logs, cleanups
- Consolideate createRateStat calls
- Add getTotalLength()
- Remove unused lengthOverride()
* UDP: Mark only first fragment as a duplicate
* 2011-10-20 0.8.10 released
2011-10-19 kytv

View File

@ -43,6 +43,9 @@ class RouterThrottleImpl implements RouterThrottle {
/** tunnel acceptance */
public static final int TUNNEL_ACCEPT = 0;
/** = TrivialPreprocessor.PREPROCESSED_SIZE */
private static final int PREPROCESSED_SIZE = 1024;
public RouterThrottleImpl(RouterContext context) {
_context = context;
_log = context.logManager().getLog(RouterThrottleImpl.class);
@ -265,7 +268,7 @@ class RouterThrottleImpl implements RouterThrottle {
if (messagesPerTunnel < DEFAULT_MESSAGES_PER_TUNNEL_ESTIMATE)
messagesPerTunnel = DEFAULT_MESSAGES_PER_TUNNEL_ESTIMATE;
double bytesAllocated = messagesPerTunnel * numTunnels * net.i2p.router.tunnel.TrivialPreprocessor.PREPROCESSED_SIZE;
double bytesAllocated = messagesPerTunnel * numTunnels * PREPROCESSED_SIZE;
if (!allowTunnel(bytesAllocated, numTunnels)) {
_context.statManager().addRateData("router.throttleTunnelBandwidthExceeded", (long)bytesAllocated, 0);

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 = 0;
public final static long BUILD = 1;
/** for example "-test" */
public final static String EXTRA = "";

View File

@ -7,7 +7,7 @@ import net.i2p.data.Hash;
import net.i2p.util.RandomSource;
/**
* Wrap up the settings for a pool of tunnels (duh)
* Wrap up the settings for a pool of tunnels.
*
*/
public class TunnelPoolSettings {
@ -19,7 +19,7 @@ public class TunnelPoolSettings {
//private int _duration;
private int _length;
private int _lengthVariance;
private int _lengthOverride;
//private int _lengthOverride;
private boolean _isInbound;
private boolean _isExploratory;
private boolean _allowZeroHop;
@ -74,6 +74,15 @@ public class TunnelPoolSettings {
public int getBackupQuantity() { return _backupQuantity; }
public void setBackupQuantity(int quantity) { _backupQuantity = quantity; }
/**
* Convenience
* @return getQuantity() + getBackupQuantity()
* @since 0.8.11
*/
public int getTotalQuantity() {
return _quantity + _backupQuantity;
}
/** how long before tunnel expiration should new tunnels be built */
// public int getRebuildPeriod() { return _rebuildPeriod; }
// public void setRebuildPeriod(int periodMs) { _rebuildPeriod = periodMs; }
@ -95,9 +104,9 @@ public class TunnelPoolSettings {
public int getLengthVariance() { return _lengthVariance; }
public void setLengthVariance(int variance) { _lengthVariance = variance; }
/* Set to a nonzero value to override the length setting */
public int getLengthOverride() { return _lengthOverride; }
public void setLengthOverride(int variance) { _lengthOverride = variance; }
/* UNUSED Set to a nonzero value to override the length setting */
//public int getLengthOverride() { return _lengthOverride; }
//public void setLengthOverride(int variance) { _lengthOverride = variance; }
/** is this an inbound tunnel? */
public boolean isInbound() { return _isInbound; }
@ -200,7 +209,7 @@ public class TunnelPoolSettings {
}
// used for strict peer ordering
private Hash generateRandomKey() {
private static Hash generateRandomKey() {
byte hash[] = new byte[Hash.HASH_LENGTH];
RandomSource.getInstance().nextBytes(hash);
return new Hash(hash);
@ -211,7 +220,9 @@ public class TunnelPoolSettings {
boolean v = "TRUE".equalsIgnoreCase(str) || "YES".equalsIgnoreCase(str);
return v;
}
private static final int getInt(String str, int defaultValue) { return (int)getLong(str, defaultValue); }
private static final long getLong(String str, long defaultValue) {
if (str == null) return defaultValue;
try {

View File

@ -108,12 +108,13 @@ class OutboundClientMessageJobHelper {
DeliveryInstructions instructions = new DeliveryInstructions();
instructions.setDeliveryMode(DeliveryInstructions.DELIVERY_MODE_LOCAL);
instructions.setDelayRequested(false);
instructions.setDelaySeconds(0);
instructions.setEncrypted(false);
instructions.setEncryptionKey(null);
instructions.setRouter(null);
instructions.setTunnelId(null);
// defaults
//instructions.setDelayRequested(false);
//instructions.setDelaySeconds(0);
//instructions.setEncrypted(false);
//instructions.setEncryptionKey(null);
//instructions.setRouter(null);
//instructions.setTunnelId(null);
config.setCertificate(Certificate.NULL_CERT);
config.setDeliveryInstructions(instructions);
@ -155,9 +156,10 @@ class OutboundClientMessageJobHelper {
ackInstructions.setDeliveryMode(DeliveryInstructions.DELIVERY_MODE_TUNNEL);
ackInstructions.setRouter(replyToTunnelRouter);
ackInstructions.setTunnelId(replyToTunnelId);
ackInstructions.setDelayRequested(false);
ackInstructions.setDelaySeconds(0);
ackInstructions.setEncrypted(false);
// defaults
//ackInstructions.setDelayRequested(false);
//ackInstructions.setDelaySeconds(0);
//ackInstructions.setEncrypted(false);
DeliveryStatusMessage msg = new DeliveryStatusMessage(ctx);
msg.setArrival(ctx.clock().now());
@ -192,9 +194,10 @@ class OutboundClientMessageJobHelper {
instructions.setDeliveryMode(DeliveryInstructions.DELIVERY_MODE_DESTINATION);
instructions.setDestination(dest.calculateHash());
instructions.setDelayRequested(false);
instructions.setDelaySeconds(0);
instructions.setEncrypted(false);
// defaults
//instructions.setDelayRequested(false);
//instructions.setDelaySeconds(0);
//instructions.setEncrypted(false);
clove.setCertificate(Certificate.NULL_CERT);
clove.setDeliveryInstructions(instructions);
@ -218,9 +221,10 @@ class OutboundClientMessageJobHelper {
DeliveryInstructions instructions = new DeliveryInstructions();
instructions.setDeliveryMode(DeliveryInstructions.DELIVERY_MODE_LOCAL);
instructions.setDelayRequested(false);
instructions.setDelaySeconds(0);
instructions.setEncrypted(false);
// defaults
//instructions.setDelayRequested(false);
//instructions.setDelaySeconds(0);
//instructions.setEncrypted(false);
clove.setCertificate(Certificate.NULL_CERT);
clove.setDeliveryInstructions(instructions);

View File

@ -891,9 +891,10 @@ public class OutboundClientMessageOneShotJob extends JobImpl {
instructions.setDeliveryMode(DeliveryInstructions.DELIVERY_MODE_DESTINATION);
instructions.setDestination(_to.calculateHash());
instructions.setDelayRequested(false);
instructions.setDelaySeconds(0);
instructions.setEncrypted(false);
// defaults
//instructions.setDelayRequested(false);
//instructions.setDelaySeconds(0);
//instructions.setEncrypted(false);
clove.setCertificate(Certificate.NULL_CERT);
clove.setDeliveryInstructions(instructions);

View File

@ -44,7 +44,7 @@ import net.i2p.util.Log;
* }
* }
*/
public class BatchedPreprocessor extends TrivialPreprocessor {
class BatchedPreprocessor extends TrivialPreprocessor {
private long _pendingSince;
private final String _name;

View File

@ -10,8 +10,7 @@ import net.i2p.router.RouterContext;
* router config setting, and track fragmentation.
*
*/
public class BatchedRouterPreprocessor extends BatchedPreprocessor {
protected RouterContext _routerContext;
class BatchedRouterPreprocessor extends BatchedPreprocessor {
private TunnelCreatorConfig _config;
protected HopConfig _hopConfig;
private final long _sendDelay;
@ -34,7 +33,6 @@ public class BatchedRouterPreprocessor extends BatchedPreprocessor {
/** for OBGWs */
public BatchedRouterPreprocessor(RouterContext ctx, TunnelCreatorConfig cfg) {
super(ctx, getName(cfg));
_routerContext = ctx;
_config = cfg;
_sendDelay = initialSendDelay();
}
@ -42,7 +40,6 @@ public class BatchedRouterPreprocessor extends BatchedPreprocessor {
/** for IBGWs */
public BatchedRouterPreprocessor(RouterContext ctx, HopConfig cfg) {
super(ctx, getName(cfg));
_routerContext = ctx;
_hopConfig = cfg;
_sendDelay = initialSendDelay();
}
@ -103,14 +100,14 @@ public class BatchedRouterPreprocessor extends BatchedPreprocessor {
} else {
def = DEFAULT_BATCH_FREQUENCY;
}
return _routerContext.getProperty(PROP_ROUTER_BATCH_FREQUENCY, def);
return _context.getProperty(PROP_ROUTER_BATCH_FREQUENCY, def);
}
@Override
protected void notePreprocessing(long messageId, int numFragments, int totalLength, List<Long> messageIds, String msg) {
if (_config != null)
_routerContext.messageHistory().fragmentMessage(messageId, numFragments, totalLength, messageIds, _config, msg);
_context.messageHistory().fragmentMessage(messageId, numFragments, totalLength, messageIds, _config, msg);
else
_routerContext.messageHistory().fragmentMessage(messageId, numFragments, totalLength, messageIds, _hopConfig, msg);
_context.messageHistory().fragmentMessage(messageId, numFragments, totalLength, messageIds, _hopConfig, msg);
}
}

View File

@ -12,7 +12,7 @@ import net.i2p.util.DecayingHashSet;
* decaying bloom filter.
*
*/
public class BloomFilterIVValidator implements IVValidator {
class BloomFilterIVValidator implements IVValidator {
private final RouterContext _context;
private final DecayingBloomFilter _filter;
private final ByteCache _ivXorCache = ByteCache.getInstance(32, HopProcessor.IV_LENGTH);
@ -30,6 +30,8 @@ public class BloomFilterIVValidator implements IVValidator {
private static final long MIN_MEM_TO_USE_BLOOM = 64*1024*1024l;
private static final long MIN_MEM_FOR_BIG_BLOOM = 128*1024*1024l;
private static final long MIN_MEM_FOR_HUGE_BLOOM = 256*1024*1024l;
/** for testing */
private static final String PROP_FORCE = "router.forceDecayingBloomFilter";
public BloomFilterIVValidator(RouterContext ctx, int KBps) {
_context = ctx;
@ -40,7 +42,9 @@ public class BloomFilterIVValidator implements IVValidator {
long maxMemory = Runtime.getRuntime().maxMemory();
if (maxMemory == Long.MAX_VALUE)
maxMemory = 96*1024*1024l;
if (KBps < MIN_SHARE_KBPS_TO_USE_BLOOM || maxMemory < MIN_MEM_TO_USE_BLOOM)
if (_context.getBooleanProperty(PROP_FORCE))
_filter = new DecayingBloomFilter(ctx, HALFLIFE_MS, 16, "TunnelIVV"); // 2MB fixed
else if (KBps < MIN_SHARE_KBPS_TO_USE_BLOOM || maxMemory < MIN_MEM_TO_USE_BLOOM)
_filter = new DecayingHashSet(ctx, HALFLIFE_MS, 16, "TunnelIVV"); // appx. 4MB max
else if (KBps >= MIN_SHARE_KBPS_FOR_HUGE_BLOOM && maxMemory >= MIN_MEM_FOR_HUGE_BLOOM)
_filter = new DecayingBloomFilter(ctx, HALFLIFE_MS, 16, "TunnelIVV", 25); // 8MB fixed
@ -49,7 +53,7 @@ public class BloomFilterIVValidator implements IVValidator {
else
_filter = new DecayingBloomFilter(ctx, HALFLIFE_MS, 16, "TunnelIVV"); // 2MB fixed
ctx.statManager().createRateStat("tunnel.duplicateIV", "Note that a duplicate IV was received", "Tunnels",
new long[] { 10*60*1000l, 60*60*1000l, 3*60*60*1000l, 24*60*60*1000l });
new long[] { 60*60*1000l });
}
public boolean receiveIV(byte ivData[], int ivOffset, byte payload[], int payloadOffset) {
@ -57,8 +61,9 @@ public class BloomFilterIVValidator implements IVValidator {
DataHelper.xor(ivData, ivOffset, payload, payloadOffset, buf.getData(), 0, HopProcessor.IV_LENGTH);
boolean dup = _filter.add(buf.getData());
_ivXorCache.release(buf);
if (dup) _context.statManager().addRateData("tunnel.duplicateIV", 1, 1);
if (dup) _context.statManager().addRateData("tunnel.duplicateIV", 1);
return !dup; // return true if it is OK, false if it isn't
}
public void destroy() { _filter.stopDecaying(); }
}

View File

@ -18,9 +18,9 @@ import net.i2p.router.RouterContext;
import net.i2p.util.Log;
/**
*
* Fill in the encrypted BuildRequestRecords in a TunnelBuildMessage
*/
public class BuildMessageGenerator {
public abstract class BuildMessageGenerator {
/** return null if it is unable to find a router's public key (etc) */
/****
@ -58,10 +58,12 @@ public class BuildMessageGenerator {
/**
* Place the asymmetrically encrypted record in the specified record slot,
* containing the hop's configuration (as well as the reply info, if it is an outbound endpoint)
*
* @param msg out parameter
*/
public static void createRecord(int recordNum, int hop, TunnelBuildMessage msg, TunnelCreatorConfig cfg, Hash replyRouter, long replyTunnel, I2PAppContext ctx, PublicKey peerKey) {
byte encrypted[] = new byte[TunnelBuildMessage.RECORD_SIZE];
Log log = ctx.logManager().getLog(BuildMessageGenerator.class);
//Log log = ctx.logManager().getLog(BuildMessageGenerator.class);
if (peerKey != null) {
BuildRequestRecord req = null;
if ( (!cfg.isInbound()) && (hop + 1 == cfg.getLength()) ) //outbound endpoint
@ -69,22 +71,22 @@ public class BuildMessageGenerator {
else
req = createUnencryptedRecord(ctx, cfg, hop, null, -1);
Hash peer = cfg.getPeer(hop);
if (log.shouldLog(Log.DEBUG))
log.debug("Record " + recordNum + "/" + hop + "/" + peer.toBase64()
+ ": unencrypted = " + Base64.encode(req.getData().getData()));
//if (log.shouldLog(Log.DEBUG))
// log.debug("Record " + recordNum + "/" + hop + "/" + peer.toBase64()
// + ": unencrypted = " + Base64.encode(req.getData().getData()));
req.encryptRecord(ctx, peerKey, peer, encrypted, 0);
//if (log.shouldLog(Log.DEBUG))
// log.debug("Record " + recordNum + "/" + hop + ": encrypted = " + Base64.encode(encrypted));
} else {
if (log.shouldLog(Log.DEBUG))
log.debug("Record " + recordNum + "/" + hop + "/ is blank/random");
//if (log.shouldLog(Log.DEBUG))
// log.debug("Record " + recordNum + "/" + hop + "/ is blank/random");
ctx.random().nextBytes(encrypted);
}
msg.setRecord(recordNum, new ByteArray(encrypted));
}
private static BuildRequestRecord createUnencryptedRecord(I2PAppContext ctx, TunnelCreatorConfig cfg, int hop, Hash replyRouter, long replyTunnel) {
Log log = ctx.logManager().getLog(BuildMessageGenerator.class);
//Log log = ctx.logManager().getLog(BuildMessageGenerator.class);
if (hop < cfg.getLength()) {
// ok, now lets fill in some data
HopConfig hopConfig = cfg.getConfig(hop);
@ -129,9 +131,9 @@ public class BuildMessageGenerator {
nextMsgId = ctx.random().nextLong(I2NPMessage.MAX_ID_VALUE);
}
if (log.shouldLog(Log.DEBUG))
log.debug("Hop " + hop + " has the next message ID of " + nextMsgId + " for " + cfg
+ " with replyKey " + replyKey.toBase64() + " and replyIV " + Base64.encode(iv));
//if (log.shouldLog(Log.DEBUG))
// log.debug("Hop " + hop + " has the next message ID of " + nextMsgId + " for " + cfg
// + " with replyKey " + replyKey.toBase64() + " and replyIV " + Base64.encode(iv));
BuildRequestRecord rec= new BuildRequestRecord();
rec.createRecord(ctx, recvTunnelId, peer, nextTunnelId, nextPeer, nextMsgId, layerKey, ivKey, replyKey,
@ -148,19 +150,19 @@ public class BuildMessageGenerator {
* @param order list of hop #s as Integers. For instance, if (order.get(1) is 4), it is peer cfg.getPeer(4)
*/
public static void layeredEncrypt(I2PAppContext ctx, TunnelBuildMessage msg, TunnelCreatorConfig cfg, List order) {
Log log = ctx.logManager().getLog(BuildMessageGenerator.class);
//Log log = ctx.logManager().getLog(BuildMessageGenerator.class);
// encrypt the records so that the right elements will be visible at the right time
for (int i = 0; i < msg.getRecordCount(); i++) {
ByteArray rec = msg.getRecord(i);
Integer hopNum = (Integer)order.get(i);
int hop = hopNum.intValue();
if ( (isBlank(cfg, hop)) || (!cfg.isInbound() && hop == 1) ) {
if (log.shouldLog(Log.DEBUG))
log.debug(msg.getUniqueId() + ": not pre-decrypting record " + i + "/" + hop + " for " + cfg);
//if (log.shouldLog(Log.DEBUG))
// log.debug(msg.getUniqueId() + ": not pre-decrypting record " + i + "/" + hop + " for " + cfg);
continue;
}
if (log.shouldLog(Log.DEBUG))
log.debug(msg.getUniqueId() + ": pre-decrypting record " + i + "/" + hop + " for " + cfg);
//if (log.shouldLog(Log.DEBUG))
// log.debug(msg.getUniqueId() + ": pre-decrypting record " + i + "/" + hop + " for " + cfg);
// ok, now decrypt the record with all of the reply keys from cfg.getConfig(0) through hop-1
int stop = (cfg.isInbound() ? 0 : 1);
for (int j = hop-1; j >= stop; j--) {
@ -168,14 +170,14 @@ public class BuildMessageGenerator {
SessionKey key = hopConfig.getReplyKey();
byte iv[] = hopConfig.getReplyIV().getData();
int off = rec.getOffset();
if (log.shouldLog(Log.DEBUG))
log.debug(msg.getUniqueId() + ": pre-decrypting record " + i + "/" + hop + " for " + cfg
+ " with " + key.toBase64() + "/" + Base64.encode(iv));
//if (log.shouldLog(Log.DEBUG))
// log.debug(msg.getUniqueId() + ": pre-decrypting record " + i + "/" + hop + " for " + cfg
// + " with " + key.toBase64() + "/" + Base64.encode(iv));
ctx.aes().decrypt(rec.getData(), off, rec.getData(), off, key, iv, TunnelBuildMessage.RECORD_SIZE);
}
}
if (log.shouldLog(Log.DEBUG))
log.debug(msg.getUniqueId() + ": done pre-decrypting all records for " + cfg);
//if (log.shouldLog(Log.DEBUG))
// log.debug(msg.getUniqueId() + ": done pre-decrypting all records for " + cfg);
}
public static boolean isBlank(TunnelCreatorConfig cfg, int hop) {

View File

@ -20,11 +20,11 @@ import net.i2p.util.Log;
* the next hop
*/
public class BuildMessageProcessor {
private DecayingBloomFilter _filter;
private final DecayingBloomFilter _filter;
public BuildMessageProcessor(I2PAppContext ctx) {
_filter = new DecayingHashSet(ctx, 60*1000, 32, "TunnelBMP");
ctx.statManager().createRateStat("tunnel.buildRequestDup", "How frequently we get dup build request messages", "Tunnels", new long[] { 60*60*1000 });
// all createRateStat in TunnelDispatcher
}
/**
* Decrypt the record targetting us, encrypting all of the other records with the included

View File

@ -16,7 +16,7 @@ import net.i2p.util.Log;
* hops agreed to participate in the tunnel, or if not, why not.
*
*/
public class BuildReplyHandler {
public abstract class BuildReplyHandler {
/**
* Decrypt the tunnel build reply records. This overwrites the contents of the reply

View File

@ -90,14 +90,13 @@ The total size, including the tunnel ID and IV, is 1028 bytes.
*
*/
public class FragmentHandler {
protected RouterContext _context;
protected Log _log;
class FragmentHandler {
protected final RouterContext _context;
protected final Log _log;
private final Map<Long, FragmentedMessage> _fragmentedMessages;
private DefragmentedReceiver _receiver;
private final DefragmentedReceiver _receiver;
private int _completed;
private int _failed;
private static final long[] RATES = { 10*60*1000l, 60*60*1000l, 3*60*60*1000l, 24*60*60*1000 };
/** don't wait more than 60s to defragment the partial message */
static long MAX_DEFRAGMENT_TIME = 60*1000;
@ -108,16 +107,7 @@ public class FragmentHandler {
_log = context.logManager().getLog(FragmentHandler.class);
_fragmentedMessages = new HashMap(8);
_receiver = receiver;
_context.statManager().createRateStat("tunnel.smallFragments", "How many pad bytes are in small fragments?",
"Tunnels", RATES);
_context.statManager().createRateStat("tunnel.fullFragments", "How many tunnel messages use the full data area?",
"Tunnels", RATES);
_context.statManager().createRateStat("tunnel.fragmentedComplete", "How many fragments were in a completely received message?",
"Tunnels", RATES);
_context.statManager().createRequiredRateStat("tunnel.fragmentedDropped", "Number of dropped fragments",
"Tunnels", RATES);
_context.statManager().createRequiredRateStat("tunnel.corruptMessage", "Corrupt messages received",
"Tunnels", RATES);
// all createRateStat in TunnelDispatcher
}
/**

View File

@ -24,16 +24,16 @@ import net.i2p.util.SimpleTimer;
* Warning - this is all unsynchronized here - receivers must implement synchronization
*
*/
public class FragmentedMessage {
private I2PAppContext _context;
private Log _log;
class FragmentedMessage {
private final I2PAppContext _context;
private final Log _log;
private long _messageId;
private Hash _toRouter;
private TunnelId _toTunnel;
private ByteArray _fragments[];
private boolean _lastReceived;
private int _highFragmentNum;
private long _createdOn;
private final long _createdOn;
private boolean _completed;
private long _releasedAfter;
private SimpleTimer.TimedEvent _expireEvent;
@ -46,15 +46,10 @@ public class FragmentedMessage {
_context = ctx;
_log = ctx.logManager().getLog(FragmentedMessage.class);
_messageId = -1;
_toRouter = null;
_toTunnel = null;
_fragments = new ByteArray[MAX_FRAGMENTS];
_lastReceived = false;
_highFragmentNum = -1;
_releasedAfter = -1;
_createdOn = ctx.clock().now();
_expireEvent = null;
_completed = false;
}
/**

View File

@ -15,11 +15,11 @@ import net.i2p.util.Log;
* InbuondGatewayProcessor).
*
*/
public class HopProcessor {
protected I2PAppContext _context;
private Log _log;
protected HopConfig _config;
private IVValidator _validator;
class HopProcessor {
protected final I2PAppContext _context;
private final Log _log;
protected final HopConfig _config;
private final IVValidator _validator;
/** helpful flag for debugging */
static final boolean USE_ENCRYPTION = true;

View File

@ -14,7 +14,7 @@ import net.i2p.util.Log;
* same thing in both instances.
*
*/
public class InboundEndpointProcessor {
class InboundEndpointProcessor {
private final RouterContext _context;
private final Log _log;
private final TunnelCreatorConfig _config;
@ -90,15 +90,15 @@ public class InboundEndpointProcessor {
* Iteratively undo the crypto that the various layers in the tunnel added.
*/
private void decrypt(RouterContext ctx, TunnelCreatorConfig cfg, byte iv[], byte orig[], int offset, int length) {
Log log = ctx.logManager().getLog(OutboundGatewayProcessor.class);
//Log log = ctx.logManager().getLog(OutboundGatewayProcessor.class);
ByteArray ba = _cache.acquire();
byte cur[] = ba.getData(); // new byte[HopProcessor.IV_LENGTH]; // so we dont malloc
for (int i = cfg.getLength()-2; i >= 0; i--) { // dont include the endpoint, since that is the creator
OutboundGatewayProcessor.decrypt(ctx, iv, orig, offset, length, cur, cfg.getConfig(i));
if (log.shouldLog(Log.DEBUG)) {
//if (log.shouldLog(Log.DEBUG)) {
//log.debug("IV at hop " + i + ": " + Base64.encode(orig, offset, HopProcessor.IV_LENGTH));
//log.debug("hop " + i + ": " + Base64.encode(orig, offset + HopProcessor.IV_LENGTH, length - HopProcessor.IV_LENGTH));
}
//}
}
_cache.release(ba);
}

View File

@ -6,7 +6,7 @@ import net.i2p.I2PAppContext;
* Override the hop processor to seed the message with a random
* IV.
*/
public class InboundGatewayProcessor extends HopProcessor {
class InboundGatewayProcessor extends HopProcessor {
public InboundGatewayProcessor(I2PAppContext ctx, HopConfig config) {
super(ctx, config, DummyValidator.getInstance());
}

View File

@ -26,11 +26,11 @@ import net.i2p.util.Log;
* When a message arrives at the inbound tunnel endpoint, this distributor
* honors the instructions (safely)
*/
public class InboundMessageDistributor implements GarlicMessageReceiver.CloveReceiver {
private RouterContext _context;
private Log _log;
private Hash _client;
private GarlicMessageReceiver _receiver;
class InboundMessageDistributor implements GarlicMessageReceiver.CloveReceiver {
private final RouterContext _context;
private final Log _log;
private final Hash _client;
private final GarlicMessageReceiver _receiver;
private static final int MAX_DISTRIBUTE_TIME = 10*1000;
@ -39,8 +39,7 @@ public class InboundMessageDistributor implements GarlicMessageReceiver.CloveRec
_client = client;
_log = ctx.logManager().getLog(InboundMessageDistributor.class);
_receiver = new GarlicMessageReceiver(ctx, this, client);
_context.statManager().createRateStat("tunnel.dropDangerousClientTunnelMessage", "How many tunnel messages come down a client tunnel that we shouldn't expect (lifetime is the 'I2NP type')", "Tunnels", new long[] { 60*60*1000 });
_context.statManager().createRateStat("tunnel.handleLoadClove", "When do we receive load test cloves", "Tunnels", new long[] { 60*60*1000 });
// all createRateStat in TunnelDispatcher
}
public void distribute(I2NPMessage msg, Hash target) {

View File

@ -7,8 +7,8 @@ import net.i2p.I2PAppContext;
* it on to the first hop.
*
*/
public class InboundSender implements TunnelGateway.Sender {
private InboundGatewayProcessor _processor;
class InboundSender implements TunnelGateway.Sender {
private final InboundGatewayProcessor _processor;
static final boolean USE_ENCRYPTION = HopProcessor.USE_ENCRYPTION;

View File

@ -13,7 +13,7 @@ import net.i2p.util.Log;
* InboundEndpointProcessor, as its the same 'undo' function of the tunnel crypto.
*
*/
public class OutboundGatewayProcessor {
class OutboundGatewayProcessor {
private final I2PAppContext _context;
private final Log _log;
private final TunnelCreatorConfig _config;

View File

@ -14,7 +14,7 @@ import net.i2p.util.Log;
* When a message arrives at the outbound tunnel endpoint, this distributor
* honors the instructions.
*/
public class OutboundMessageDistributor {
class OutboundMessageDistributor {
private final RouterContext _context;
private final int _priority;
private final Log _log;

View File

@ -9,11 +9,11 @@ import net.i2p.util.Log;
* layers, and forward it on to the first hop.
*
*/
public class OutboundSender implements TunnelGateway.Sender {
private I2PAppContext _context;
private Log _log;
private TunnelCreatorConfig _config;
private OutboundGatewayProcessor _processor;
class OutboundSender implements TunnelGateway.Sender {
private final I2PAppContext _context;
private final Log _log;
private final TunnelCreatorConfig _config;
private final OutboundGatewayProcessor _processor;
static final boolean USE_ENCRYPTION = HopProcessor.USE_ENCRYPTION;

View File

@ -12,13 +12,13 @@ import net.i2p.util.Log;
* and honor the instructions as received.
*
*/
public class OutboundTunnelEndpoint {
private RouterContext _context;
private Log _log;
private HopConfig _config;
private HopProcessor _processor;
private FragmentHandler _handler;
private OutboundMessageDistributor _outDistributor;
class OutboundTunnelEndpoint {
private final RouterContext _context;
private final Log _log;
private final HopConfig _config;
private final HopProcessor _processor;
private final FragmentHandler _handler;
private final OutboundMessageDistributor _outDistributor;
public OutboundTunnelEndpoint(RouterContext ctx, HopConfig config, HopProcessor processor) {
_context = ctx;

View File

@ -2,6 +2,8 @@ package net.i2p.router.tunnel;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.LinkedBlockingQueue;
import net.i2p.data.Hash;
import net.i2p.data.TunnelId;
@ -33,9 +35,9 @@ import net.i2p.util.Log;
* </ol>
*
*/
public class PumpedTunnelGateway extends TunnelGateway {
private final List<Pending> _prequeue;
private TunnelGatewayPumper _pumper;
class PumpedTunnelGateway extends TunnelGateway {
private final BlockingQueue<Pending> _prequeue;
private final TunnelGatewayPumper _pumper;
/**
* @param preprocessor this pulls Pending messages off a list, builds some
@ -47,7 +49,7 @@ public class PumpedTunnelGateway extends TunnelGateway {
*/
public PumpedTunnelGateway(RouterContext context, QueuePreprocessor preprocessor, Sender sender, Receiver receiver, TunnelGatewayPumper pumper) {
super(context, preprocessor, sender, receiver);
_prequeue = new ArrayList(4);
_prequeue = new LinkedBlockingQueue();
_pumper = pumper;
}
@ -64,13 +66,8 @@ public class PumpedTunnelGateway extends TunnelGateway {
public void add(I2NPMessage msg, Hash toRouter, TunnelId toTunnel) {
_messagesSent++;
Pending cur = new PendingImpl(msg, toRouter, toTunnel);
long beforeLock = System.currentTimeMillis();
synchronized (_prequeue) {
_prequeue.add(cur);
}
_prequeue.offer(cur);
_pumper.wantsPumping(this);
if (_log.shouldLog(Log.DEBUG))
_log.debug("GW prequeue time: " + (System.currentTimeMillis()-beforeLock) + " for " + msg.getUniqueId() + " on " + toString());
}
/**
@ -84,14 +81,10 @@ public class PumpedTunnelGateway extends TunnelGateway {
* Must be empty when called; will always be emptied before return.
*/
void pump(List<Pending> queueBuf) {
synchronized (_prequeue) {
if (!_prequeue.isEmpty()) {
queueBuf.addAll(_prequeue);
_prequeue.clear();
} else {
return;
}
}
_prequeue.drainTo(queueBuf);
if (queueBuf.isEmpty())
return;
long startAdd = System.currentTimeMillis();
long beforeLock = startAdd;
long afterAdded = -1;

View File

@ -6,7 +6,7 @@ import net.i2p.util.Log;
/**
* Minor extension to allow message history integration
*/
public class RouterFragmentHandler extends FragmentHandler {
class RouterFragmentHandler extends FragmentHandler {
public RouterFragmentHandler(RouterContext context, DefragmentedReceiver receiver) {
super(context, receiver);

View File

@ -14,9 +14,9 @@ import net.i2p.router.RouterContext;
*
* @since 0.7.9
*/
public class ThrottledPumpedTunnelGateway extends PumpedTunnelGateway {
class ThrottledPumpedTunnelGateway extends PumpedTunnelGateway {
/** saved so we can note messages that get dropped */
private HopConfig _config;
private final HopConfig _config;
public ThrottledPumpedTunnelGateway(RouterContext context, QueuePreprocessor preprocessor, Sender sender,
Receiver receiver, TunnelGatewayPumper pumper, HopConfig config) {

View File

@ -19,7 +19,7 @@ import net.i2p.util.Log;
*
* See FragmentHandler Javadoc for tunnel message fragment format
*/
public class TrivialPreprocessor implements TunnelGateway.QueuePreprocessor {
class TrivialPreprocessor implements TunnelGateway.QueuePreprocessor {
protected final RouterContext _context;
protected final Log _log;

View File

@ -9,7 +9,7 @@ import net.i2p.router.RouterContext;
*
* @deprecated unused
*/
public class TrivialRouterPreprocessor extends TrivialPreprocessor {
class TrivialRouterPreprocessor extends TrivialPreprocessor {
public TrivialRouterPreprocessor(RouterContext ctx) {
super(ctx);

View File

@ -43,6 +43,8 @@ public class TunnelDispatcher implements Service {
/** what is the date/time we last deliberately dropped a tunnel? **/
private long _lastDropTime;
private final TunnelGatewayPumper _pumper;
private static final long[] RATES = { 10*60*1000l, 60*60*1000l, 3*60*60*1000l, 24*60*60*1000 };
/** Creates a new instance of TunnelDispatcher */
public TunnelDispatcher(RouterContext ctx) {
@ -148,6 +150,22 @@ public class TunnelDispatcher implements Service {
ctx.statManager().createRateStat("tunnel.inboundLookupSuccess", "Was a deferred lookup successful?", "Tunnels", new long[] { 60*60*1000 });
// following is for TunnelParticipant
ctx.statManager().createRateStat("tunnel.participantLookupSuccess", "Was a deferred lookup successful?", "Tunnels", new long[] { 60*60*1000 });
// following is for BuildMessageProcessor
ctx.statManager().createRateStat("tunnel.buildRequestDup", "How frequently we get dup build request messages", "Tunnels", new long[] { 60*60*1000 });
// following are for FragmentHandler
ctx.statManager().createRateStat("tunnel.smallFragments", "How many pad bytes are in small fragments?",
"Tunnels", RATES);
ctx.statManager().createRateStat("tunnel.fullFragments", "How many tunnel messages use the full data area?",
"Tunnels", RATES);
ctx.statManager().createRateStat("tunnel.fragmentedComplete", "How many fragments were in a completely received message?",
"Tunnels", RATES);
ctx.statManager().createRequiredRateStat("tunnel.fragmentedDropped", "Number of dropped fragments",
"Tunnels", RATES);
ctx.statManager().createRequiredRateStat("tunnel.corruptMessage", "Corrupt messages received",
"Tunnels", RATES);
// following are for InboundMessageDistributor
ctx.statManager().createRateStat("tunnel.dropDangerousClientTunnelMessage", "How many tunnel messages come down a client tunnel that we shouldn't expect (lifetime is the 'I2NP type')", "Tunnels", new long[] { 60*60*1000 });
ctx.statManager().createRateStat("tunnel.handleLoadClove", "When do we receive load test cloves", "Tunnels", new long[] { 60*60*1000 });
}
/** for IBGW */

View File

@ -33,16 +33,16 @@ import net.i2p.util.SimpleTimer;
* </ol>
*
*/
public class TunnelGateway {
protected RouterContext _context;
protected Log _log;
class TunnelGateway {
protected final RouterContext _context;
protected final Log _log;
protected final List<Pending> _queue;
protected QueuePreprocessor _preprocessor;
protected Sender _sender;
protected Receiver _receiver;
protected final QueuePreprocessor _preprocessor;
protected final Sender _sender;
protected final Receiver _receiver;
protected long _lastFlush;
protected int _flushFrequency;
protected DelayedFlush _delayedFlush;// FIXME Exporting non-public type through public API FIXME
//protected int _flushFrequency;
protected final DelayedFlush _delayedFlush;// FIXME Exporting non-public type through public API FIXME
protected int _messagesSent;
/**
@ -60,7 +60,7 @@ public class TunnelGateway {
_preprocessor = preprocessor;
_sender = sender;
_receiver = receiver;
_flushFrequency = 500;
//_flushFrequency = 500;
_delayedFlush = new DelayedFlush();
_lastFlush = _context.clock().now();
_context.statManager().createRateStat("tunnel.lockedGatewayAdd", "How long do we block when adding a message to a tunnel gateway's queue", "Tunnels", new long[] { 60*1000, 10*60*1000 });
@ -183,14 +183,14 @@ public class TunnelGateway {
* Stores all the state for an unsent or partially-sent message
*/
public static class Pending {
protected Hash _toRouter;
protected TunnelId _toTunnel;
protected long _messageId;
protected long _expiration;
protected byte _remaining[];
protected final Hash _toRouter;
protected final TunnelId _toTunnel;
protected final long _messageId;
protected final long _expiration;
protected final byte _remaining[];
protected int _offset;
protected int _fragmentNumber;
protected long _created;
protected final long _created;
private List<Long> _messageIds;
public Pending(I2NPMessage message, Hash toRouter, TunnelId toTunnel) {

View File

@ -12,8 +12,8 @@ import net.i2p.util.I2PThread;
* run through the tunnel gateways that have had messages added to them and push
* those messages through the preprocessing and sending process
*/
public class TunnelGatewayPumper implements Runnable {
private RouterContext _context;
class TunnelGatewayPumper implements Runnable {
private final RouterContext _context;
private final BlockingQueue<PumpedTunnelGateway> _wantsPumping;
private boolean _stop;
private static final int MIN_PUMPERS = 1;
@ -24,7 +24,6 @@ public class TunnelGatewayPumper implements Runnable {
public TunnelGatewayPumper(RouterContext ctx) {
_context = ctx;
_wantsPumping = new LinkedBlockingQueue();
_stop = false;
long maxMemory = Runtime.getRuntime().maxMemory();
if (maxMemory == Long.MAX_VALUE)
maxMemory = 96*1024*1024l;

View File

@ -8,11 +8,11 @@ import net.i2p.router.RouterContext;
import net.i2p.util.Log;
/**
* Serve as the gatekeeper for a tunnel with no hops.
* Serve as the gatekeeper for a tunnel with no hops, either inbound or outbound.
*
*/
public class TunnelGatewayZeroHop extends TunnelGateway {
private TunnelCreatorConfig _config;
class TunnelGatewayZeroHop extends TunnelGateway {
private final TunnelCreatorConfig _config;
private OutboundMessageDistributor _outDistributor;
private InboundMessageDistributor _inDistributor;

View File

@ -17,7 +17,7 @@ import net.i2p.util.Log;
* InboundMessageDistributor to receive defragmented and decrypted messages,
* which it will then selectively forward.
*/
public class TunnelParticipant {
class TunnelParticipant {
private final RouterContext _context;
private final Log _log;
private final HopConfig _config;

View File

@ -75,7 +75,8 @@ class BuildHandler {
_context.statManager().createRequiredRateStat("tunnel.rejectOverloaded", "Delay to process rejected request (ms)", "Tunnels", new long[] { 60*1000, 10*60*1000 });
_context.statManager().createRequiredRateStat("tunnel.acceptLoad", "Delay to process accepted request (ms)", "Tunnels", new long[] { 60*1000, 10*60*1000 });
_context.statManager().createRateStat("tunnel.dropConnLimits", "Drop instead of reject due to conn limits", "Tunnels", new long[] { 60*1000, 10*60*1000 });
_context.statManager().createRateStat("tunnel.dropConnLimits", "Drop instead of reject due to conn limits", "Tunnels", new long[] { 10*60*1000 });
_context.statManager().createRateStat("tunnel.rejectConnLimits", "Reject due to conn limits", "Tunnels", new long[] { 10*60*1000 });
_context.statManager().createRequiredRateStat("tunnel.dropLoad", "Delay before dropping request (ms)?", "Tunnels", new long[] { 60*1000, 10*60*1000 });
_context.statManager().createRequiredRateStat("tunnel.dropLoadDelay", "Delay before abandoning request (ms)", "Tunnels", new long[] { 60*1000, 10*60*1000 });
_context.statManager().createRequiredRateStat("tunnel.dropLoadBacklog", "Pending request count when dropped", "Tunnels", new long[] { 60*1000, 10*60*1000 });
@ -507,6 +508,7 @@ class BuildHandler {
if (bw != 'O' && bw != 'N' &&
((isInGW && ! _context.commSystem().haveInboundCapacity(87)) ||
(isOutEnd && ! _context.commSystem().haveOutboundCapacity(87)))) {
_context.statManager().addRateData("tunnel.rejectConnLimits", 1);
_context.throttle().setTunnelStatus(_x("Rejecting tunnels: Connection limit"));
response = TunnelHistory.TUNNEL_REJECT_BANDWIDTH;
}

View File

@ -79,9 +79,11 @@ class TestJob extends JobImpl {
_outTunnel = null;
if (_cfg.isInbound()) {
_replyTunnel = _cfg;
// TODO if testing is re-enabled, pick closest to far end
_outTunnel = getContext().tunnelManager().selectOutboundTunnel();
_otherTunnel = (PooledTunnelCreatorConfig) _outTunnel;
} else {
// TODO if testing is re-enabled, pick closest to far end
_replyTunnel = getContext().tunnelManager().selectInboundTunnel();
_outTunnel = _cfg;
_otherTunnel = (PooledTunnelCreatorConfig) _replyTunnel;
@ -117,7 +119,7 @@ class TestJob extends JobImpl {
instructions.setDeliveryMode(DeliveryInstructions.DELIVERY_MODE_LOCAL);
PayloadGarlicConfig payload = new PayloadGarlicConfig();
payload.setCertificate(new Certificate(Certificate.CERTIFICATE_TYPE_NULL, null));
payload.setCertificate(Certificate.NULL_CERT);
payload.setId(getContext().random().nextLong(I2NPMessage.MAX_ID_VALUE));
payload.setPayload(m);
payload.setRecipient(getContext().router().getRouterInfo());

View File

@ -47,10 +47,11 @@ public abstract class TunnelPeerSelector {
*/
protected int getLength(RouterContext ctx, TunnelPoolSettings settings) {
int length = settings.getLength();
int override = settings.getLengthOverride();
if (override != 0)
length = override;
else if (settings.getLengthVariance() != 0) {
//int override = settings.getLengthOverride();
//if (override != 0)
// length = override;
//else if (settings.getLengthVariance() != 0) {
if (settings.getLengthVariance() != 0) {
int skew = settings.getLengthVariance();
if (skew > 0)
length += ctx.random().nextInt(skew+1);

View File

@ -50,7 +50,7 @@ public class TunnelPool {
_log = ctx.logManager().getLog(TunnelPool.class);
_manager = mgr;
_settings = settings;
_tunnels = new ArrayList(settings.getLength() + settings.getBackupQuantity());
_tunnels = new ArrayList(settings.getTotalQuantity());
_peerSelector = sel;
_expireSkew = _context.random().nextInt(90*1000);
_started = System.currentTimeMillis();
@ -292,7 +292,7 @@ public class TunnelPool {
* Used to prevent a zillion of them
*/
boolean needFallback() {
int needed = _settings.getBackupQuantity() + _settings.getQuantity();
int needed = _settings.getTotalQuantity();
int fallbacks = 0;
synchronized (_tunnels) {
for (int i = 0; i < _tunnels.size(); i++) {
@ -495,7 +495,7 @@ public class TunnelPool {
*
*/
boolean buildFallback() {
int quantity = _settings.getBackupQuantity() + _settings.getQuantity();
int quantity = _settings.getTotalQuantity();
int usable = 0;
synchronized (_tunnels) {
usable = _tunnels.size();
@ -678,7 +678,7 @@ public class TunnelPool {
if (!isAlive()) {
return 0;
}
int wanted = getSettings().getBackupQuantity() + getSettings().getQuantity();
int wanted = getSettings().getTotalQuantity();
boolean allowZeroHop = ((getSettings().getLength() + getSettings().getLengthVariance()) <= 0);