propagate from branch 'i2p.i2p.zzz.test2' (head 70ae5494bd7255a03f80838a2f3d8e7c0ce86634)

to branch 'i2p.i2p' (head 05a201cc5c1bd841f32e9268b3019b3a3447f4f3)
This commit is contained in:
zzz
2016-02-03 20:02:34 +00:00
82 changed files with 3766 additions and 313 deletions

View File

@ -100,7 +100,9 @@ public class Router implements RouterClock.ClockShiftListener {
public final static long CLOCK_FUDGE_FACTOR = 1*60*1000;
/** used to differentiate routerInfo files on different networks */
public static final int NETWORK_ID = 2;
private static final int DEFAULT_NETWORK_ID = 2;
private static final String PROP_NETWORK_ID = "router.networkID";
private final int _networkID;
/** coalesce stats this often - should be a little less than one minute, so the graphs get updated */
public static final int COALESCE_TIME = 50*1000;
@ -347,6 +349,14 @@ public class Router implements RouterClock.ClockShiftListener {
_config.put("router.previousVersion", RouterVersion.VERSION);
saveConfig();
}
int id = DEFAULT_NETWORK_ID;
String sid = _config.get(PROP_NETWORK_ID);
if (sid != null) {
try {
id = Integer.parseInt(sid);
} catch (NumberFormatException nfe) {}
}
_networkID = id;
changeState(State.INITIALIZED);
// ********* Start no threads before here ********* //
}
@ -536,6 +546,14 @@ public class Router implements RouterClock.ClockShiftListener {
if (_started <= 0) return 1000; // racing on startup
return Math.max(1000, System.currentTimeMillis() - _started);
}
/**
* The network ID. Default 2.
* May be changed with the config property router.networkID (restart required).
* Change only if running a test network to prevent cross-network contamination.
* @since 0.9.25
*/
public int getNetworkID() { return _networkID; }
/**
* Non-null, but take care when accessing context items before runRouter() is called

View File

@ -120,7 +120,8 @@ public class RouterContext extends I2PAppContext {
// or about 2 seconds per buffer - so about 200x faster
// to fill than to drain - so we don't need too many
long maxMemory = SystemVersion.getMaxMemory();
long buffs = Math.min(16, Math.max(2, maxMemory / (14 * 1024 * 1024)));
long maxBuffs = (SystemVersion.isAndroid() || SystemVersion.isARM()) ? 4 : 8;
long buffs = Math.min(maxBuffs, Math.max(2, maxMemory / (21 * 1024 * 1024)));
envProps.setProperty("prng.buffers", "" + buffs);
}
return envProps;

View File

@ -32,6 +32,7 @@ import net.i2p.util.Log;
public class StatisticsManager {
private final Log _log;
private final RouterContext _context;
private final String _networkID;
public final static String PROP_PUBLISH_RANKINGS = "router.publishPeerRankings";
private static final String PROP_CONTACT_NAME = "netdb.contact";
@ -46,6 +47,7 @@ public class StatisticsManager {
_fmt = new DecimalFormat("###,##0.00", new DecimalFormatSymbols(Locale.UK));
_pct = new DecimalFormat("#0.00%", new DecimalFormatSymbols(Locale.UK));
_log = context.logManager().getLog(StatisticsManager.class);
_networkID = Integer.toString(context.router().getNetworkID());
}
/**
@ -72,7 +74,7 @@ public class StatisticsManager {
// scheduled for removal, never used
if (CoreVersion.VERSION.equals("0.9.23"))
stats.setProperty("coreVersion", CoreVersion.VERSION);
stats.setProperty(RouterInfo.PROP_NETWORK_ID, Integer.toString(Router.NETWORK_ID));
stats.setProperty(RouterInfo.PROP_NETWORK_ID, _networkID);
stats.setProperty(RouterInfo.PROP_CAPABILITIES, _context.router().getCapabilities());
// No longer expose, to make build tracking more expensive

View File

@ -47,12 +47,13 @@ public class FamilyKeyCrypto {
private final SigningPrivateKey _privkey;
private final SigningPublicKey _pubkey;
private static final String PROP_KEYSTORE_PASSWORD = "netdb.family.keystorePassword";
public static final String PROP_KEYSTORE_PASSWORD = "netdb.family.keystorePassword";
public static final String PROP_FAMILY_NAME = "netdb.family.name";
private static final String PROP_KEY_PASSWORD = "netdb.family.keyPassword";
private static final String CERT_SUFFIX = ".crt";
private static final String KEYSTORE_PREFIX = "family-";
private static final String KEYSTORE_SUFFIX = ".ks";
public static final String PROP_KEY_PASSWORD = "netdb.family.keyPassword";
public static final String CERT_SUFFIX = ".crt";
public static final String KEYSTORE_PREFIX = "family-";
public static final String KEYSTORE_SUFFIX = ".ks";
public static final String CN_SUFFIX = ".family.i2p.net";
private static final int DEFAULT_KEY_VALID_DAYS = 3652; // 10 years
// Note that we can't use RSA here, as the b64 sig would exceed the 255 char limit for a Mapping
// Note that we can't use EdDSA here, as keystore doesn't know how, and encoding/decoding is unimplemented
@ -289,7 +290,7 @@ public class FamilyKeyCrypto {
// make a random 48 character password (30 * 8 / 5)
String keyPassword = KeyStoreUtil.randomString();
// and one for the cname
String cname = _fname + ".family.i2p.net";
String cname = _fname + CN_SUFFIX;
boolean success = KeyStoreUtil.createKeys(ks, KeyStoreUtil.DEFAULT_KEYSTORE_PASSWORD, _fname, cname, "family",
DEFAULT_KEY_VALID_DAYS, DEFAULT_KEY_ALGORITHM,

View File

@ -479,7 +479,7 @@ public class FloodfillNetworkDatabaseFacade extends KademliaNetworkDatabaseFacad
// drop the peer in these cases
// yikes don't do this - stack overflow // getFloodfillPeers().size() == 0 ||
// yikes2 don't do this either - deadlock! // getKnownRouters() < MIN_REMAINING_ROUTERS ||
if (info.getNetworkId() == Router.NETWORK_ID &&
if (info.getNetworkId() == _networkID &&
(getKBucketSetSize() < MIN_REMAINING_ROUTERS ||
_context.router().getUptime() < DONT_FAIL_PERIOD ||
_context.commSystem().countActivePeers() <= MIN_ACTIVE_PEERS)) {

View File

@ -70,6 +70,7 @@ public class KademliaNetworkDatabaseFacade extends NetworkDatabaseFacade {
private final ReseedChecker _reseedChecker;
private volatile long _lastRIPublishTime;
private NegativeLookupCache _negativeCache;
protected final int _networkID;
/**
* Map of Hash to RepublishLeaseSetJob for leases we'realready managing.
@ -156,6 +157,7 @@ public class KademliaNetworkDatabaseFacade extends NetworkDatabaseFacade {
public KademliaNetworkDatabaseFacade(RouterContext context) {
_context = context;
_log = _context.logManager().getLog(getClass());
_networkID = context.router().getNetworkID();
_peerSelector = createPeerSelector();
_publishingLeaseSets = new HashMap<Hash, RepublishLeaseSetJob>(8);
_activeRequests = new HashMap<Hash, SearchJob>(8);
@ -889,7 +891,7 @@ public class KademliaNetworkDatabaseFacade extends NetworkDatabaseFacade {
_log.warn("Invalid routerInfo signature! forged router structure! router = " + routerInfo);
return "Invalid routerInfo signature";
}
if (routerInfo.getNetworkId() != Router.NETWORK_ID){
if (routerInfo.getNetworkId() != _networkID){
_context.banlist().banlistRouter(key, "Not in our network");
if (_log.shouldLog(Log.WARN))
_log.warn("Bad network: " + routerInfo);

View File

@ -54,6 +54,7 @@ public class PersistentDataStore extends TransientDataStore {
private final ReadJob _readJob;
private volatile boolean _initialized;
private final boolean _flat;
private final int _networkID;
private final static int READ_DELAY = 2*60*1000;
private static final String PROP_FLAT = "router.networkDatabase.flat";
@ -65,6 +66,7 @@ public class PersistentDataStore extends TransientDataStore {
*/
public PersistentDataStore(RouterContext ctx, String dbDir, KademliaNetworkDatabaseFacade facade) throws IOException {
super(ctx);
_networkID = ctx.router().getNetworkID();
_flat = ctx.getBooleanProperty(PROP_FLAT);
_dbDir = getDbDir(dbDir);
_facade = facade;
@ -505,7 +507,7 @@ public class PersistentDataStore extends TransientDataStore {
fis = new BufferedInputStream(fis);
RouterInfo ri = new RouterInfo();
ri.readBytes(fis, true); // true = verify sig on read
if (ri.getNetworkId() != Router.NETWORK_ID) {
if (ri.getNetworkId() != _networkID) {
corrupt = true;
if (_log.shouldLog(Log.ERROR))
_log.error("The router "

View File

@ -42,6 +42,7 @@ class EstablishmentManager {
private final Log _log;
private final UDPTransport _transport;
private final PacketBuilder _builder;
private final int _networkID;
/** map of RemoteHostId to InboundEstablishState */
private final ConcurrentHashMap<RemoteHostId, InboundEstablishState> _inboundStates;
@ -140,6 +141,7 @@ class EstablishmentManager {
public EstablishmentManager(RouterContext ctx, UDPTransport transport) {
_context = ctx;
_log = ctx.logManager().getLog(EstablishmentManager.class);
_networkID = ctx.router().getNetworkID();
_transport = transport;
_builder = new PacketBuilder(ctx, transport);
_inboundStates = new ConcurrentHashMap<RemoteHostId, InboundEstablishState>();
@ -249,7 +251,7 @@ class EstablishmentManager {
}
RouterIdentity toIdentity = toRouterInfo.getIdentity();
Hash toHash = toIdentity.calculateHash();
if (toRouterInfo.getNetworkId() != Router.NETWORK_ID) {
if (toRouterInfo.getNetworkId() != _networkID) {
_context.banlist().banlistRouter(toHash);
_transport.markUnreachable(toHash);
_transport.failed(msg, "Remote peer is on the wrong network, cannot establish");
@ -762,7 +764,7 @@ class EstablishmentManager {
if (_log.shouldLog(Log.INFO))
_log.info("Completing to the peer after IB confirm: " + peer);
DeliveryStatusMessage dsm = new DeliveryStatusMessage(_context);
dsm.setArrival(Router.NETWORK_ID); // overloaded, sure, but future versions can check this
dsm.setArrival(_networkID); // overloaded, sure, but future versions can check this
// This causes huge values in the inNetPool.droppedDeliveryStatusDelay stat
// so it needs to be caught in InNetMessagePool.
dsm.setMessageExpiration(_context.clock().now() + DATA_MESSAGE_TIMEOUT);

View File

@ -87,6 +87,7 @@ public class UDPTransport extends TransportImpl implements TimedWeightedPriority
private int _mtu;
private int _mtu_ipv6;
private boolean _mismatchLogged;
private final int _networkID;
/**
* Do we have a public IPv6 address?
@ -218,6 +219,7 @@ public class UDPTransport extends TransportImpl implements TimedWeightedPriority
public UDPTransport(RouterContext ctx, DHSessionKeyBuilder.Factory dh) {
super(ctx);
_networkID = ctx.router().getNetworkID();
_dhFactory = dh;
_log = ctx.logManager().getLog(UDPTransport.class);
_peersByIdent = new ConcurrentHashMap<Hash, PeerState>(128);
@ -1289,7 +1291,7 @@ public class UDPTransport extends TransportImpl implements TimedWeightedPriority
if (entry == null)
return;
if (entry.getType() == DatabaseEntry.KEY_TYPE_ROUTERINFO &&
((RouterInfo) entry).getNetworkId() != Router.NETWORK_ID) {
((RouterInfo) entry).getNetworkId() != _networkID) {
// this is pre-0.6.1.10, so it isn't going to happen any more
/*

View File

@ -0,0 +1,281 @@
package net.i2p.router.util;
import java.io.Serializable;
import java.util.AbstractSet;
import java.util.ConcurrentModificationException;
import java.util.Collection;
import java.util.Iterator;
import java.util.NoSuchElementException;
import java.util.Set;
/**
* A small, fast Set with a maximum size, backed by a fixed-size array.
* Unsynchronized, not thread-safe.
* Null elements are not permitted.
* Not appropriate for large Sets.
*
* @since 0.9.25
*/
public class ArraySet<E> extends AbstractSet<E> implements Set<E> {
public static final int MAX_CAPACITY = 32;
private final Object[] _entries;
private final boolean _throwOnFull;
private int _size;
private int _overflowIndex;
private transient int modCount;
/**
* A fixed capacity of MAX_CAPACITY.
* Adds over capacity will throw a SetFullException.
*/
public ArraySet() {
this(MAX_CAPACITY);
}
/**
* A fixed capacity of MAX_CAPACITY.
* Adds over capacity will throw a SetFullException.
* @throws SetFullException if more than MAX_CAPACITY unique elements in c.
*/
public ArraySet(Collection<? extends E> c) {
this();
addAll(c);
}
/**
* Adds over capacity will throw a SetFullException.
*
* @param capacity the maximum size
* @throws IllegalArgumentException if capacity less than 1 or more than MAX_CAPACITY.
*/
public ArraySet(int capacity) {
this(capacity, true);
}
/**
* If throwOnFull is false,
* adds over capacity will overwrite starting at slot zero.
* This breaks the AbstractCollection invariant that
* "a Collection will always contain the specified element after add() returns",
* but it prevents unexpected exceptions.
* If throwOnFull is true, adds over capacity will throw a SetFullException.
*
* @param capacity the maximum size
* @throws IllegalArgumentException if capacity less than 1 or more than MAX_CAPACITY.
*/
public ArraySet(int capacity, boolean throwOnFull) {
if (capacity <= 0 || capacity > MAX_CAPACITY)
throw new IllegalArgumentException("bad capacity");
_entries = new Object[capacity];
_throwOnFull = throwOnFull;
}
/**
* @return -1 if not found or if o is null
*/
private int indexOf(Object o) {
if (o != null) {
for (int i = 0; i < _size; i++) {
if (o.equals(_entries[i]))
return i;
}
}
return -1;
}
/**
* @throws SetFullException if throwOnFull was true in constructor
* @throws NullPointerException if o is null
*/
@Override
public boolean add(E o) {
if (o == null)
throw new NullPointerException();
int i = indexOf(o);
if (i >= 0) {
_entries[i] = o;
return false;
}
if (_size >= _entries.length) {
if (_throwOnFull)
throw new SetFullException();
i = _overflowIndex++;
if (i >= _entries.length) {
i = 0;
_overflowIndex = 0;
}
} else {
modCount++;
i = _size++;
}
_entries[i] = o;
return true;
}
@Override
public void clear() {
if (_size != 0) {
modCount++;
for (int i = 0; i < _size; i++) {
_entries[i] = null;
}
_size = 0;
}
}
@Override
public boolean contains(Object o) {
return indexOf(o) >= 0;
}
@Override
public boolean isEmpty() {
return _size <= 0;
}
@Override
public boolean remove(Object o) {
int i = indexOf(o);
if (i < 0)
return false;
modCount++;
_size--;
for (int j = i; j < _size; j++) {
_entries[j] = _entries[j + 1];
}
_entries[_size] = null;
return true;
}
public int size() {
return _size;
}
/**
* Supports remove.
* Supports comodification checks.
*/
public Iterator<E> iterator() {
return new ASIterator();
}
public static class SetFullException extends IllegalStateException {
private static final long serialVersionUID = 9087390587254111L;
}
/**
* Modified from CachedIteratorArrayList
*/
private class ASIterator implements Iterator<E>, Serializable {
/**
* Index of element to be returned by subsequent call to next.
*/
int cursor = 0;
/**
* Index of element returned by most recent call to next or
* previous. Reset to -1 if this element is deleted by a call
* to remove.
*/
int lastRet = -1;
/**
* The modCount value that the iterator believes that the backing
* List should have. If this expectation is violated, the iterator
* has detected concurrent modification.
*/
int expectedModCount = modCount;
public boolean hasNext() {
return cursor != _size;
}
@SuppressWarnings("unchecked")
public E next() {
checkForComodification();
try {
int i = cursor;
E next = (E) _entries[i];
lastRet = i;
cursor = i + 1;
return next;
} catch (IndexOutOfBoundsException e) {
checkForComodification();
throw new NoSuchElementException();
}
}
public void remove() {
if (lastRet < 0)
throw new IllegalStateException();
checkForComodification();
try {
ArraySet.this.remove(lastRet);
if (lastRet < cursor)
cursor--;
lastRet = -1;
expectedModCount = modCount;
} catch (IndexOutOfBoundsException e) {
throw new ConcurrentModificationException();
}
}
final void checkForComodification() {
if (modCount != expectedModCount)
throw new ConcurrentModificationException();
}
}
/**
* About 3x faster than HashSet.
*/
/****
@SuppressWarnings({ "unchecked", "rawtypes" })
public static void main(String[] args) {
if (args.length > 0) {
System.out.println("Test with overwrite");
Set s = new ArraySet(4, false);
for (int i = 0; i < args.length; i++) {
System.out.println("Added " + args[i] + "? " + s.add(args[i]));
System.out.println("Size is now " + s.size());
}
// toString tests the iterator
System.out.println("Set now contains" + s);
for (int i = 0; i < args.length; i++) {
System.out.println("Removed " + args[i] + "? " + s.remove(args[i]));
System.out.println("Size is now " + s.size());
}
System.out.println("\nTest with throw on full");
s = new ArraySet(4);
for (int i = 0; i < args.length; i++) {
System.out.println("Added " + args[i] + "? " + s.add(args[i]));
System.out.println("Size is now " + s.size());
}
// toString tests the iterator
System.out.println("Set now contains" + s);
for (int i = 0; i < args.length; i++) {
System.out.println("Removed " + args[i] + "? " + s.remove(args[i]));
System.out.println("Size is now " + s.size());
}
}
//java.util.List c = java.util.Arrays.asList(new String[] {"foo", "bar", "baz", "splat", "barf", "baz", "moose", "bear", "cat", "dog"} );
java.util.List c = java.util.Arrays.asList(new String[] {"foo", "bar"} );
long start = System.currentTimeMillis();
Set s = new java.util.HashSet(c);
int runs = 10000000;
for (int i = 0; i < runs; i++) {
s = new java.util.HashSet(s);
}
System.out.println("HashSet took " + (System.currentTimeMillis() - start));
start = System.currentTimeMillis();
s = new ArraySet(c);
for (int i = 0; i < runs; i++) {
s = new ArraySet(s);
}
System.out.println("ArraySet took " + (System.currentTimeMillis() - start));
}
****/
}