forked from I2P_Developers/i2p.i2p
propagate from branch 'i2p.i2p.zzz.test2' (head 70ae5494bd7255a03f80838a2f3d8e7c0ce86634)
to branch 'i2p.i2p' (head 05a201cc5c1bd841f32e9268b3019b3a3447f4f3)
This commit is contained in:
@ -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
|
||||
|
@ -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;
|
||||
|
@ -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
|
||||
|
@ -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,
|
||||
|
@ -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)) {
|
||||
|
@ -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);
|
||||
|
@ -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 "
|
||||
|
@ -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);
|
||||
|
@ -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
|
||||
|
||||
/*
|
||||
|
281
router/java/src/net/i2p/router/util/ArraySet.java
Normal file
281
router/java/src/net/i2p/router/util/ArraySet.java
Normal 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));
|
||||
}
|
||||
****/
|
||||
}
|
Reference in New Issue
Block a user