2005-07-11 jrandom
* Reduced the growth factor on the slow start and congestion avoidance for the streaming lib. * Adjusted some of the I2PTunnelServer threading to use a small pool of handlers, rather than launching off new threads which then immediately launch off an I2PTunnelRunner instance (which launches 3 more threads..) * Don't persist session keys / session tags (not worth it, for now) * Added some detection and handling code for duplicate session tags being delivered (root cause still not addressed) * Make the PRNG's buffer size configurable (via the config property "i2p.prng.totalBufferSizeKB=4096") * Disable SSU flooding by default (duh) * Updates to the StreamSink apps for better throttling tests.
This commit is contained in:
@ -4,6 +4,7 @@ import java.util.Random;
|
||||
import net.i2p.I2PAppContext;
|
||||
import net.i2p.util.PooledRandomSource;
|
||||
import net.i2p.util.RandomSource;
|
||||
import net.i2p.util.Log;
|
||||
|
||||
/**
|
||||
*
|
||||
@ -11,6 +12,9 @@ import net.i2p.util.RandomSource;
|
||||
public class DummyPooledRandomSource extends PooledRandomSource {
|
||||
public DummyPooledRandomSource(I2PAppContext context) {
|
||||
super(context);
|
||||
}
|
||||
|
||||
protected void initializePool(I2PAppContext context) {
|
||||
_pool = new RandomSource[POOL_SIZE];
|
||||
for (int i = 0; i < POOL_SIZE; i++) {
|
||||
_pool[i] = new DummyRandomSource(context);
|
||||
|
@ -58,6 +58,8 @@ public class PersistentSessionKeyManager extends TransientSessionKeyManager {
|
||||
*
|
||||
*/
|
||||
public void saveState(OutputStream out) throws IOException, DataFormatException {
|
||||
if (true) return;
|
||||
|
||||
Set tagSets = getInboundTagSets();
|
||||
Set sessions = getOutboundSessions();
|
||||
if (_log.shouldLog(Log.INFO))
|
||||
|
@ -10,6 +10,7 @@ package net.i2p.crypto;
|
||||
*/
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.Date;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
@ -262,11 +263,23 @@ class TransientSessionKeyManager extends SessionKeyManager {
|
||||
if (old != null) {
|
||||
TagSet oldTS = (TagSet)old;
|
||||
if (!oldTS.getAssociatedKey().equals(tagSet.getAssociatedKey())) {
|
||||
if (_log.shouldLog(Log.ERROR)) {
|
||||
_log.error("Multiple tags matching! tag: " + tag.toString() + " matches for new tagSet: " + tagSet + " and old tagSet: " + old);
|
||||
_log.error("Earlier tag set creation: " + old + ": key=" + oldTS.getAssociatedKey().toBase64(), oldTS.getCreatedBy());
|
||||
_log.error("Current tag set creation: " + tagSet + ": key=" + tagSet.getAssociatedKey().toBase64(), tagSet.getCreatedBy());
|
||||
if (_log.shouldLog(Log.WARN)) {
|
||||
_log.warn("Multiple tags matching! tag: " + tag.toString() + " matches for new tagSet: " + tagSet + " and old tagSet: " + old);
|
||||
_log.warn("Earlier tag set creation: " + old + ": key=" + oldTS.getAssociatedKey().toBase64(), oldTS.getCreatedBy());
|
||||
_log.warn("Current tag set creation: " + tagSet + ": key=" + tagSet.getAssociatedKey().toBase64(), tagSet.getCreatedBy());
|
||||
}
|
||||
// drop both, rather than sit around confused
|
||||
_inboundTagSets.remove(tag);
|
||||
|
||||
for (Iterator tsIter = oldTS.dropTags().iterator(); iter.hasNext(); ) {
|
||||
SessionTag curTag = (SessionTag)tsIter.next();
|
||||
_inboundTagSets.remove(curTag);
|
||||
}
|
||||
for (Iterator tsIter = tagSet.dropTags().iterator(); iter.hasNext(); ) {
|
||||
SessionTag curTag = (SessionTag)tsIter.next();
|
||||
_inboundTagSets.remove(curTag);
|
||||
}
|
||||
|
||||
} else {
|
||||
if (_log.shouldLog(Log.DEBUG)) {
|
||||
//tagSet.getTags().addAll(oldTS.getTags());
|
||||
@ -307,7 +320,7 @@ class TransientSessionKeyManager extends SessionKeyManager {
|
||||
synchronized (_inboundTagSets) {
|
||||
for (Iterator iter = _inboundTagSets.values().iterator(); iter.hasNext(); ) {
|
||||
TagSet set = (TagSet)iter.next();
|
||||
int size = set.getTags().size();
|
||||
int size = set.getTagCount();
|
||||
if (size > 1000)
|
||||
absurd++;
|
||||
if (size > 100)
|
||||
@ -322,7 +335,7 @@ class TransientSessionKeyManager extends SessionKeyManager {
|
||||
}
|
||||
for (int i = 0; i < removed.size(); i++) {
|
||||
TagSet cur = (TagSet)removed.get(i);
|
||||
for (Iterator iter = cur.getTags().iterator(); iter.hasNext(); ) {
|
||||
for (Iterator iter = cur.dropTags().iterator(); iter.hasNext(); ) {
|
||||
SessionTag tag = (SessionTag)iter.next();
|
||||
_inboundTagSets.remove(tag);
|
||||
tags++;
|
||||
@ -465,7 +478,7 @@ class TransientSessionKeyManager extends SessionKeyManager {
|
||||
for (Iterator siter = sets.iterator(); siter.hasNext();) {
|
||||
TagSet ts = (TagSet) siter.next();
|
||||
buf.append("<li><b>Received on:</b> ").append(new Date(ts.getDate())).append(" with ")
|
||||
.append(ts.getTags().size()).append(" tags remaining</li>");
|
||||
.append(ts.getTagCount()).append(" tags remaining</li>");
|
||||
}
|
||||
buf.append("</ul></td></tr>");
|
||||
}
|
||||
@ -485,9 +498,7 @@ class TransientSessionKeyManager extends SessionKeyManager {
|
||||
buf.append("<tr><td><ul>");
|
||||
for (Iterator siter = sess.getTagSets().iterator(); siter.hasNext();) {
|
||||
TagSet ts = (TagSet) siter.next();
|
||||
buf.append("<li><b>Sent on:</b> ").append(new Date(ts.getDate())).append(" with ").append(
|
||||
ts.getTags()
|
||||
.size())
|
||||
buf.append("<li><b>Sent on:</b> ").append(new Date(ts.getDate())).append(" with ").append(ts.getTagCount())
|
||||
.append(" tags remaining</li>");
|
||||
}
|
||||
buf.append("</ul></td></tr>");
|
||||
@ -540,7 +551,7 @@ class TransientSessionKeyManager extends SessionKeyManager {
|
||||
_tagSets = new ArrayList();
|
||||
for (int i = 0; i < sets.size(); i++) {
|
||||
TagSet set = (TagSet) sets.get(i);
|
||||
dropped += set.getTags().size();
|
||||
dropped += set.getTagCount();
|
||||
}
|
||||
if (_log.shouldLog(Log.INFO))
|
||||
_log.info("Rekeyed from " + _currentKey + " to " + key
|
||||
@ -604,7 +615,7 @@ class TransientSessionKeyManager extends SessionKeyManager {
|
||||
for (int i = 0; i < _tagSets.size(); i++) {
|
||||
TagSet set = (TagSet) _tagSets.get(i);
|
||||
if (set.getDate() + SESSION_TAG_DURATION_MS > now)
|
||||
tags += set.getTags().size();
|
||||
tags += set.getTagCount();
|
||||
}
|
||||
}
|
||||
return tags;
|
||||
@ -620,7 +631,7 @@ class TransientSessionKeyManager extends SessionKeyManager {
|
||||
synchronized (_tagSets) {
|
||||
for (Iterator iter = _tagSets.iterator(); iter.hasNext();) {
|
||||
TagSet set = (TagSet) iter.next();
|
||||
if ( (set.getDate() > last) && (set.getTags().size() > 0) )
|
||||
if ( (set.getDate() > last) && (set.getTagCount() > 0) )
|
||||
last = set.getDate();
|
||||
}
|
||||
}
|
||||
@ -665,10 +676,31 @@ class TransientSessionKeyManager extends SessionKeyManager {
|
||||
_date = when;
|
||||
}
|
||||
|
||||
/** tags still available */
|
||||
public Set getTags() {
|
||||
/**
|
||||
* raw tags still available - you MUST synchronize against the TagSet instance
|
||||
* if you need to use this set
|
||||
*/
|
||||
Set getTags() {
|
||||
return _sessionTags;
|
||||
}
|
||||
|
||||
public int getTagCount() {
|
||||
synchronized (TagSet.this) {
|
||||
if (_sessionTags == null)
|
||||
return 0;
|
||||
else
|
||||
return _sessionTags.size();
|
||||
}
|
||||
}
|
||||
|
||||
public Set dropTags() {
|
||||
Set rv = null;
|
||||
synchronized (TagSet.this) {
|
||||
rv = _sessionTags;
|
||||
_sessionTags = Collections.EMPTY_SET;
|
||||
}
|
||||
return rv;
|
||||
}
|
||||
|
||||
public SessionKey getAssociatedKey() {
|
||||
return _key;
|
||||
|
@ -28,12 +28,15 @@ public class BufferedRandomSource extends RandomSource {
|
||||
private int _nextBit;
|
||||
private static volatile long _reseeds;
|
||||
|
||||
private static final int BUFFER_SIZE = 256*1024;
|
||||
private static final int DEFAULT_BUFFER_SIZE = 256*1024;
|
||||
|
||||
public BufferedRandomSource(I2PAppContext context) {
|
||||
this(context, DEFAULT_BUFFER_SIZE);
|
||||
}
|
||||
public BufferedRandomSource(I2PAppContext context, int bufferSize) {
|
||||
super(context);
|
||||
context.statManager().createRateStat("prng.reseedCount", "How many times the prng has been reseeded", "Encryption", new long[] { 60*1000, 10*60*1000, 60*60*1000 } );
|
||||
_buffer = new byte[BUFFER_SIZE];
|
||||
_buffer = new byte[bufferSize];
|
||||
refillBuffer();
|
||||
// stagger reseeding
|
||||
_nextByte = ((int)_reseeds-1) * 16 * 1024;
|
||||
@ -73,7 +76,7 @@ public class BufferedRandomSource extends RandomSource {
|
||||
_nextBit = 0;
|
||||
_nextByte++;
|
||||
}
|
||||
if (_nextByte >= BUFFER_SIZE)
|
||||
if (_nextByte >= _buffer.length)
|
||||
refillBuffer();
|
||||
rv += (_buffer[_nextByte] << curBit);
|
||||
_nextBit++;
|
||||
@ -98,7 +101,7 @@ public class BufferedRandomSource extends RandomSource {
|
||||
_nextBit = 0;
|
||||
_nextByte++;
|
||||
}
|
||||
if (_nextByte >= BUFFER_SIZE)
|
||||
if (_nextByte >= _buffer.length)
|
||||
refillBuffer();
|
||||
int gobbleBits = 8 - _nextBit;
|
||||
int want = numBits - curBit;
|
||||
@ -117,10 +120,10 @@ public class BufferedRandomSource extends RandomSource {
|
||||
public synchronized final void nextBytes(byte buf[]) {
|
||||
int outOffset = 0;
|
||||
while (outOffset < buf.length) {
|
||||
int availableBytes = BUFFER_SIZE - _nextByte - (_nextBit != 0 ? 1 : 0);
|
||||
int availableBytes = _buffer.length - _nextByte - (_nextBit != 0 ? 1 : 0);
|
||||
if (availableBytes <= 0)
|
||||
refillBuffer();
|
||||
int start = BUFFER_SIZE - availableBytes;
|
||||
int start = _buffer.length - availableBytes;
|
||||
int writeSize = Math.min(buf.length - outOffset, availableBytes);
|
||||
System.arraycopy(_buffer, start, buf, outOffset, writeSize);
|
||||
outOffset += writeSize;
|
||||
@ -195,6 +198,10 @@ public class BufferedRandomSource extends RandomSource {
|
||||
}
|
||||
|
||||
public static void main(String args[]) {
|
||||
for (int i = 0; i < 16; i++)
|
||||
test();
|
||||
}
|
||||
private static void test() {
|
||||
I2PAppContext ctx = I2PAppContext.getGlobalContext();
|
||||
byte data[] = new byte[16*1024];
|
||||
for (int i = 0; i < data.length; i += 4) {
|
||||
@ -203,8 +210,7 @@ public class BufferedRandomSource extends RandomSource {
|
||||
DataHelper.toLong(data, i, 4, l);
|
||||
}
|
||||
byte compressed[] = DataHelper.compress(data);
|
||||
System.out.println("Compressed: " + compressed.length);
|
||||
System.out.println("Orig: " + data.length + ": " + toString(data));
|
||||
System.out.println("Data: " + data.length + "/" + compressed.length + ": " + toString(data));
|
||||
}
|
||||
private static final String toString(byte data[]) {
|
||||
StringBuffer buf = new StringBuffer(data.length * 9);
|
||||
|
@ -21,14 +21,40 @@ public class PooledRandomSource extends RandomSource {
|
||||
protected volatile int _nextPool;
|
||||
|
||||
public static final int POOL_SIZE = 16;
|
||||
/**
|
||||
* How much random data will we precalculate and feed from (as opposed to on demand
|
||||
* reseeding, etc). If this is not set, a default will be used (4MB), or if it is
|
||||
* set to 0, no buffer will be used, otherwise the amount specified will be allocated
|
||||
* across the pooled PRNGs.
|
||||
*
|
||||
*/
|
||||
public static final String PROP_BUFFER_SIZE = "i2p.prng.totalBufferSizeKB";
|
||||
|
||||
public PooledRandomSource(I2PAppContext context) {
|
||||
super(context);
|
||||
_log = context.logManager().getLog(PooledRandomSource.class);
|
||||
initializePool(context);
|
||||
}
|
||||
|
||||
protected void initializePool(I2PAppContext context) {
|
||||
_pool = new RandomSource[POOL_SIZE];
|
||||
|
||||
String totalSizeProp = context.getProperty(PROP_BUFFER_SIZE);
|
||||
int totalSize = -1;
|
||||
if (totalSizeProp != null) {
|
||||
try {
|
||||
totalSize = Integer.parseInt(totalSizeProp);
|
||||
} catch (NumberFormatException nfe) {
|
||||
totalSize = -1;
|
||||
}
|
||||
}
|
||||
for (int i = 0; i < POOL_SIZE; i++) {
|
||||
//_pool[i] = new RandomSource(context);
|
||||
_pool[i] = new BufferedRandomSource(context);
|
||||
if (totalSize < 0)
|
||||
_pool[i] = new BufferedRandomSource(context);
|
||||
else if (totalSize > 0)
|
||||
_pool[i] = new BufferedRandomSource(context, (totalSize*1024) / POOL_SIZE);
|
||||
else
|
||||
_pool[i] = new RandomSource(context);
|
||||
_pool[i].nextBoolean();
|
||||
}
|
||||
_nextPool = 0;
|
||||
|
Reference in New Issue
Block a user