forked from I2P_Developers/i2p.i2p
merge of 'f2281f98637dc74181e14a40f3b346436e95be88'
and 'f452317ba7735d99e285e2c580491a100bea305b'
This commit is contained in:
@@ -783,7 +783,7 @@ public class SnarkManager implements Snark.CompleteListener {
|
||||
throw ioe;
|
||||
} finally {
|
||||
try {
|
||||
if (out == null)
|
||||
if (out != null)
|
||||
out.close();
|
||||
} catch (IOException ioe) {}
|
||||
}
|
||||
|
||||
@@ -305,7 +305,8 @@ public class I2PTunnelConnectClient extends I2PTunnelHTTPClientBase implements R
|
||||
else
|
||||
response = SUCCESS_RESPONSE;
|
||||
Runnable onTimeout = new OnTimeout(s, s.getOutputStream(), targetRequest, usingWWWProxy, currentProxy, requestId);
|
||||
I2PTunnelRunner runner = new I2PTunnelRunner(s, i2ps, sockLock, data, response, mySockets, onTimeout);
|
||||
// starts itself
|
||||
new I2PTunnelRunner(s, i2ps, sockLock, data, response, mySockets, onTimeout);
|
||||
} catch (SocketException ex) {
|
||||
_log.info(getPrefix(requestId) + "Error trying to connect", ex);
|
||||
handleConnectClientException(ex, out, targetRequest, usingWWWProxy, currentProxy, requestId);
|
||||
|
||||
@@ -1189,7 +1189,9 @@ public class I2PTunnelHTTPClient extends I2PTunnelHTTPClientBase implements Runn
|
||||
String filename = null;
|
||||
try {
|
||||
filename = targetRequest.substring(LOCAL_SERVER.length() + 8, space); // "/themes/".length
|
||||
} catch (IndexOutOfBoundsException ioobe) {}
|
||||
} catch (IndexOutOfBoundsException ioobe) {
|
||||
return;
|
||||
}
|
||||
// theme hack
|
||||
if (filename.startsWith("console/default/"))
|
||||
filename = filename.replaceFirst("default", I2PAppContext.getGlobalContext().getProperty("routerconsole.theme", "light"));
|
||||
|
||||
@@ -125,9 +125,9 @@ public class I2PTunnelIRCClient extends I2PTunnelClientBase implements Runnable
|
||||
*/
|
||||
public static class IrcInboundFilter implements Runnable {
|
||||
|
||||
private Socket local;
|
||||
private I2PSocket remote;
|
||||
private StringBuffer expectedPong;
|
||||
private final Socket local;
|
||||
private final I2PSocket remote;
|
||||
private final StringBuffer expectedPong;
|
||||
private final Log _log;
|
||||
|
||||
public IrcInboundFilter(Socket _local, I2PSocket _remote, StringBuffer pong, Log log) {
|
||||
@@ -191,7 +191,7 @@ public class I2PTunnelIRCClient extends I2PTunnelClientBase implements Runnable
|
||||
} catch (RuntimeException re) {
|
||||
_log.error("Error filtering inbound data", re);
|
||||
} finally {
|
||||
if (local != null) try { local.close(); } catch (IOException e) {}
|
||||
try { local.close(); } catch (IOException e) {}
|
||||
}
|
||||
if(_log.shouldLog(Log.DEBUG))
|
||||
_log.debug("IrcInboundFilter: Done.");
|
||||
@@ -204,9 +204,9 @@ public class I2PTunnelIRCClient extends I2PTunnelClientBase implements Runnable
|
||||
*/
|
||||
public static class IrcOutboundFilter implements Runnable {
|
||||
|
||||
private Socket local;
|
||||
private I2PSocket remote;
|
||||
private StringBuffer expectedPong;
|
||||
private final Socket local;
|
||||
private final I2PSocket remote;
|
||||
private final StringBuffer expectedPong;
|
||||
private final Log _log;
|
||||
|
||||
public IrcOutboundFilter(Socket _local, I2PSocket _remote, StringBuffer pong, Log log) {
|
||||
@@ -270,7 +270,7 @@ public class I2PTunnelIRCClient extends I2PTunnelClientBase implements Runnable
|
||||
} catch (RuntimeException re) {
|
||||
_log.error("Error filtering outbound data", re);
|
||||
} finally {
|
||||
if (remote != null) try { remote.close(); } catch (IOException e) {}
|
||||
try { remote.close(); } catch (IOException e) {}
|
||||
}
|
||||
if (_log.shouldLog(Log.DEBUG))
|
||||
_log.debug("IrcOutboundFilter: Done.");
|
||||
|
||||
@@ -163,7 +163,7 @@ public class I2PSocketEepGet extends EepGet {
|
||||
protected String getRequest() throws IOException {
|
||||
StringBuilder buf = new StringBuilder(2048);
|
||||
URL url = new URL(_actualURL);
|
||||
String host = url.getHost();
|
||||
//String host = url.getHost();
|
||||
String path = url.getPath();
|
||||
String query = url.getQuery();
|
||||
if (query != null)
|
||||
|
||||
@@ -407,7 +407,6 @@ public class NetDbRenderer {
|
||||
*/
|
||||
private static int classifyTransports(RouterInfo info) {
|
||||
int rv = 0;
|
||||
String hash = info.getIdentity().getHash().toBase64();
|
||||
for (RouterAddress addr : info.getAddresses()) {
|
||||
String style = addr.getTransportStyle();
|
||||
if (style.equals("NTCP")) {
|
||||
|
||||
@@ -128,7 +128,8 @@ public class PluginUpdateChecker extends UpdateHandler {
|
||||
protected void update() {
|
||||
updateStatus("<b>" + _("Checking for update of plugin {0}", _appName) + "</b>");
|
||||
// use the same settings as for updater
|
||||
boolean shouldProxy = Boolean.valueOf(_context.getProperty(ConfigUpdateHandler.PROP_SHOULD_PROXY, ConfigUpdateHandler.DEFAULT_SHOULD_PROXY)).booleanValue();
|
||||
// always proxy, or else FIXME
|
||||
//boolean shouldProxy = Boolean.valueOf(_context.getProperty(ConfigUpdateHandler.PROP_SHOULD_PROXY, ConfigUpdateHandler.DEFAULT_SHOULD_PROXY)).booleanValue();
|
||||
String proxyHost = _context.getProperty(ConfigUpdateHandler.PROP_PROXY_HOST, ConfigUpdateHandler.DEFAULT_PROXY_HOST);
|
||||
int proxyPort = _context.getProperty(ConfigUpdateHandler.PROP_PROXY_PORT, ConfigUpdateHandler.DEFAULT_PROXY_PORT_INT);
|
||||
_baos.reset();
|
||||
|
||||
@@ -347,7 +347,7 @@ class Connection {
|
||||
_log.debug("Resend in " + timeout + " for " + packet);
|
||||
|
||||
// schedules itself
|
||||
ResendPacketEvent rpe = new ResendPacketEvent(packet, timeout);
|
||||
new ResendPacketEvent(packet, timeout);
|
||||
}
|
||||
|
||||
// warning, getStatLog() can be null
|
||||
|
||||
@@ -300,7 +300,8 @@ public class AddressbookBean
|
||||
} else {
|
||||
boolean valid = true;
|
||||
try {
|
||||
Destination dest = new Destination(destination);
|
||||
// just to check validity
|
||||
new Destination(destination);
|
||||
} catch (DataFormatException dfe) {
|
||||
valid = false;
|
||||
}
|
||||
|
||||
@@ -25,6 +25,8 @@ public abstract class FormatDate
|
||||
|
||||
public static String format(long date)
|
||||
{
|
||||
return _dateFormat.format(new Date(date));
|
||||
synchronized(_dateFormat) {
|
||||
return _dateFormat.format(new Date(date));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -130,8 +130,8 @@ public class SubscriptionsBean
|
||||
if( lastSerial != null && serial != null && serial.compareTo( lastSerial ) == 0 ) {
|
||||
if (action.equals(_("Save"))) {
|
||||
save();
|
||||
String nonce = System.getProperty("addressbook.nonce");
|
||||
/*******
|
||||
String nonce = System.getProperty("addressbook.nonce");
|
||||
if (nonce != null) {
|
||||
// Yes this is a hack.
|
||||
// No it doesn't work on a text-mode browser.
|
||||
|
||||
@@ -225,7 +225,8 @@ public class UrlLauncher {
|
||||
|
||||
private boolean validateUrlFormat(String urlString) {
|
||||
try {
|
||||
URL url = new URL(urlString);
|
||||
// just to check validity
|
||||
new URL(urlString);
|
||||
} catch (MalformedURLException e) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -46,6 +46,10 @@ package gnu.crypto.hash;
|
||||
/**
|
||||
* <p>A base abstract class to facilitate hash implementations.</p>
|
||||
*
|
||||
* WARNING - DEPRECATED - Use SHA256Generator.getDigestInstance() to get a
|
||||
* MessageDigest that will be faster in almost all cases.
|
||||
* See SHA256Generator for more information.
|
||||
*
|
||||
* @version $Revision: 1.1 $
|
||||
*/
|
||||
public abstract class BaseHashStandalone implements IMessageDigestStandalone {
|
||||
|
||||
@@ -49,6 +49,10 @@ package gnu.crypto.hash;
|
||||
* <p>A hash (or message digest) algorithm produces its output by iterating a
|
||||
* basic compression function on blocks of data.</p>
|
||||
*
|
||||
* WARNING - DEPRECATED - Use SHA256Generator.getDigestInstance() to get a
|
||||
* MessageDigest that will be faster in almost all cases.
|
||||
* See SHA256Generator for more information.
|
||||
*
|
||||
* @version $Revision: 1.1 $
|
||||
*/
|
||||
public interface IMessageDigestStandalone extends Cloneable {
|
||||
|
||||
@@ -59,6 +59,10 @@ package gnu.crypto.hash;
|
||||
* renamed from Sha256 to avoid conflicts with JVMs using gnu-crypto as their JCE
|
||||
* provider.
|
||||
*
|
||||
* WARNING - DEPRECATED - Use SHA256Generator.getDigestInstance() to get a
|
||||
* MessageDigest that will be faster in almost all cases.
|
||||
* See SHA256Generator for more information.
|
||||
*
|
||||
* @version $Revision: 1.2 $
|
||||
*/
|
||||
public class Sha256Standalone extends BaseHashStandalone {
|
||||
|
||||
13
core/java/src/gnu/crypto/hash/package.html
Normal file
13
core/java/src/gnu/crypto/hash/package.html
Normal file
@@ -0,0 +1,13 @@
|
||||
<html><body>
|
||||
<p>
|
||||
WARNING - DEPRECATED - Use SHA256Generator.getDigestInstance() to get a
|
||||
MessageDigest that will be faster in almost all cases.
|
||||
</p><p>
|
||||
This is the old GNU SHA-256 Hash implementation.
|
||||
It is deprecated and mostly unused, unless the java.security.MessageDigest
|
||||
implementation for SHA-256 is not available in the JVM.
|
||||
And it always should be, right?
|
||||
Do not instantiate this directly - use I2PAppContext.sha().
|
||||
See net.i2p.crypto.SHA256Generator for more information and test results.
|
||||
</p>
|
||||
</body></html>
|
||||
@@ -156,7 +156,7 @@ public class AsyncFortunaStandalone extends FortunaStandalone implements Runnabl
|
||||
}
|
||||
|
||||
private void doFill(byte buf[]) {
|
||||
long start = System.currentTimeMillis();
|
||||
//long start = System.currentTimeMillis();
|
||||
if (pool0Count >= MIN_POOL_SIZE
|
||||
&& System.currentTimeMillis() - lastReseed > 100)
|
||||
{
|
||||
|
||||
@@ -41,19 +41,19 @@ exception statement from your version. */
|
||||
|
||||
package gnu.crypto.prng;
|
||||
|
||||
import gnu.crypto.hash.Sha256Standalone;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.ObjectInputStream;
|
||||
import java.io.ObjectOutputStream;
|
||||
import java.io.Serializable;
|
||||
import java.security.InvalidKeyException;
|
||||
import java.security.MessageDigest;
|
||||
import java.util.Arrays;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import net.i2p.crypto.CryptixAESKeyCache;
|
||||
import net.i2p.crypto.CryptixRijndael_Algorithm;
|
||||
import net.i2p.crypto.SHA256Generator;
|
||||
|
||||
/**
|
||||
* The Fortuna continuously-seeded pseudo-random number generator. This
|
||||
@@ -93,6 +93,7 @@ import net.i2p.crypto.CryptixRijndael_Algorithm;
|
||||
* Renamed from Fortuna to FortunaStandalone so it doesn't conflict with the
|
||||
* gnu-crypto implementation, which has been imported into GNU/classpath
|
||||
*
|
||||
* NOTE: As of 0.8.8, uses the java.security.MessageDigest instead of GNU Sha256Standalone
|
||||
*/
|
||||
public class FortunaStandalone extends BasePRNGStandalone implements Serializable, RandomEventListenerStandalone
|
||||
{
|
||||
@@ -103,7 +104,7 @@ public class FortunaStandalone extends BasePRNGStandalone implements Serializabl
|
||||
static final int NUM_POOLS = 32;
|
||||
static final int MIN_POOL_SIZE = 64;
|
||||
final Generator generator;
|
||||
final Sha256Standalone[] pools;
|
||||
final MessageDigest[] pools;
|
||||
long lastReseed;
|
||||
int pool;
|
||||
int pool0Count;
|
||||
@@ -117,9 +118,9 @@ public class FortunaStandalone extends BasePRNGStandalone implements Serializabl
|
||||
{
|
||||
super("Fortuna i2p");
|
||||
generator = new Generator();
|
||||
pools = new Sha256Standalone[NUM_POOLS];
|
||||
pools = new MessageDigest[NUM_POOLS];
|
||||
for (int i = 0; i < NUM_POOLS; i++)
|
||||
pools[i] = new Sha256Standalone();
|
||||
pools[i] = SHA256Generator.getDigestInstance();
|
||||
lastReseed = 0;
|
||||
pool = 0;
|
||||
pool0Count = 0;
|
||||
@@ -227,7 +228,7 @@ public class FortunaStandalone extends BasePRNGStandalone implements Serializabl
|
||||
|
||||
private static final int LIMIT = 1 << 20;
|
||||
|
||||
private final Sha256Standalone hash;
|
||||
private final MessageDigest hash;
|
||||
private final byte[] counter;
|
||||
private final byte[] key;
|
||||
/** current encryption key built from the keying material */
|
||||
@@ -238,7 +239,7 @@ public class FortunaStandalone extends BasePRNGStandalone implements Serializabl
|
||||
public Generator ()
|
||||
{
|
||||
super("Fortuna.generator.i2p");
|
||||
this.hash = new Sha256Standalone();
|
||||
this.hash = SHA256Generator.getDigestInstance();
|
||||
counter = new byte[16]; //cipher.defaultBlockSize()];
|
||||
buffer = new byte[16]; //cipher.defaultBlockSize()];
|
||||
int keysize = 32;
|
||||
|
||||
@@ -148,23 +148,36 @@ public class I2PAppContext {
|
||||
}
|
||||
|
||||
/**
|
||||
* Lets root a brand new context
|
||||
*
|
||||
* Create a brand new context.
|
||||
* WARNING: In almost all cases, you should use getGlobalContext() instead,
|
||||
* to avoid creating additional contexts, which may spawn numerous
|
||||
* additional resources and threads, and may be the cause of logging
|
||||
* problems or hard-to-isolate bugs.
|
||||
*/
|
||||
public I2PAppContext() {
|
||||
this(true, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Lets root a brand new context
|
||||
*
|
||||
* Create a brand new context.
|
||||
* WARNING: In almost all cases, you should use getGlobalContext() instead,
|
||||
* to avoid creating additional contexts, which may spawn numerous
|
||||
* additional resources and threads, and may be the cause of logging
|
||||
* problems or hard-to-isolate bugs.
|
||||
*/
|
||||
public I2PAppContext(Properties envProps) {
|
||||
this(true, envProps);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a brand new context.
|
||||
* WARNING: In almost all cases, you should use getGlobalContext() instead,
|
||||
* to avoid creating additional contexts, which may spawn numerous
|
||||
* additional resources and threads, and may be the cause of logging
|
||||
* problems or hard-to-isolate bugs.
|
||||
*
|
||||
* @param doInit should this context be used as the global one (if necessary)?
|
||||
* Will only apply if there is no global context now.
|
||||
*/
|
||||
private I2PAppContext(boolean doInit, Properties envProps) {
|
||||
if (doInit) {
|
||||
|
||||
@@ -9,8 +9,8 @@ package net.i2p.client;
|
||||
*
|
||||
*/
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
|
||||
import net.i2p.I2PAppContext;
|
||||
import net.i2p.crypto.KeyGenerator;
|
||||
@@ -38,7 +38,8 @@ class RequestLeaseSetMessageHandler extends HandlerImpl {
|
||||
|
||||
public RequestLeaseSetMessageHandler(I2PAppContext context) {
|
||||
super(context, RequestLeaseSetMessage.MESSAGE_TYPE);
|
||||
_existingLeaseSets = new HashMap(32);
|
||||
// not clear why there would ever be more than one
|
||||
_existingLeaseSets = new ConcurrentHashMap(4);
|
||||
}
|
||||
|
||||
public void handleMessage(I2CPMessage message, I2PSessionImpl session) {
|
||||
@@ -58,16 +59,10 @@ class RequestLeaseSetMessageHandler extends HandlerImpl {
|
||||
leaseSet.setDestination(session.getMyDestination());
|
||||
|
||||
// reuse the old keys for the client
|
||||
LeaseInfo li = null;
|
||||
synchronized (_existingLeaseSets) {
|
||||
if (_existingLeaseSets.containsKey(session.getMyDestination()))
|
||||
li = (LeaseInfo) _existingLeaseSets.get(session.getMyDestination());
|
||||
}
|
||||
LeaseInfo li = (LeaseInfo) _existingLeaseSets.get(session.getMyDestination());
|
||||
if (li == null) {
|
||||
li = new LeaseInfo(session.getMyDestination());
|
||||
synchronized (_existingLeaseSets) {
|
||||
_existingLeaseSets.put(session.getMyDestination(), li);
|
||||
}
|
||||
_existingLeaseSets.put(session.getMyDestination(), li);
|
||||
if (_log.shouldLog(Log.DEBUG))
|
||||
_log.debug("Creating new leaseInfo keys for "
|
||||
+ session.getMyDestination().calculateHash().toBase64());
|
||||
|
||||
@@ -90,7 +90,12 @@ public final class SHA256Generator {
|
||||
_digests.offer(digest);
|
||||
}
|
||||
|
||||
private static MessageDigest getDigestInstance() {
|
||||
/**
|
||||
* Return a new MessageDigest from the system libs unless unavailable
|
||||
* in this JVM, in that case return a wrapped GNU Sha256Standalone
|
||||
* @since 0.8.7, public since 0.8.8 for FortunaStandalone
|
||||
*/
|
||||
public static MessageDigest getDigestInstance() {
|
||||
if (!_useGnu) {
|
||||
try {
|
||||
return MessageDigest.getInstance("SHA-256");
|
||||
|
||||
@@ -129,10 +129,10 @@ JXQAnA28vDmMMMH/WPbC5ixmJeGGNUiR
|
||||
public static final int HEADER_BYTES = Signature.SIGNATURE_BYTES + VERSION_BYTES;
|
||||
private static final String PROP_TRUSTED_KEYS = "router.trustedUpdateKeys";
|
||||
|
||||
private static I2PAppContext _context;
|
||||
private final I2PAppContext _context;
|
||||
|
||||
private Log _log;
|
||||
private Map<SigningPublicKey, String> _trustedKeys;
|
||||
private final Log _log;
|
||||
private final Map<SigningPublicKey, String> _trustedKeys;
|
||||
private String _newVersion;
|
||||
/** 172 */
|
||||
private static final int KEYSIZE_B64_BYTES = 2 + (SigningPublicKey.KEYSIZE_BYTES * 4 / 3);
|
||||
@@ -155,7 +155,6 @@ JXQAnA28vDmMMMH/WPbC5ixmJeGGNUiR
|
||||
_context = context;
|
||||
_log = _context.logManager().getLog(TrustedUpdate.class);
|
||||
_trustedKeys = new HashMap(4);
|
||||
_newVersion = null;
|
||||
|
||||
String propertyTrustedKeys = context.getProperty(PROP_TRUSTED_KEYS);
|
||||
|
||||
@@ -273,9 +272,9 @@ JXQAnA28vDmMMMH/WPbC5ixmJeGGNUiR
|
||||
private static final boolean genKeysCLI(String publicKeyFile, String privateKeyFile) {
|
||||
FileOutputStream fileOutputStream = null;
|
||||
|
||||
_context = I2PAppContext.getGlobalContext();
|
||||
I2PAppContext context = I2PAppContext.getGlobalContext();
|
||||
try {
|
||||
Object signingKeypair[] = _context.keyGenerator().generateSigningKeypair();
|
||||
Object signingKeypair[] = context.keyGenerator().generateSigningKeypair();
|
||||
SigningPublicKey signingPublicKey = (SigningPublicKey) signingKeypair[0];
|
||||
SigningPrivateKey signingPrivateKey = (SigningPrivateKey) signingKeypair[1];
|
||||
|
||||
|
||||
@@ -1,83 +0,0 @@
|
||||
package net.i2p.data;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.OutputStream;
|
||||
|
||||
/**
|
||||
* ????????
|
||||
* deprecated unused except by naming/FilesystemAddressDB, which is unused.
|
||||
*/
|
||||
public class Address extends DataStructureImpl {
|
||||
private String _hostname;
|
||||
private Destination _destination;
|
||||
|
||||
public Address() {
|
||||
}
|
||||
|
||||
public String getHostname() {
|
||||
return _hostname;
|
||||
}
|
||||
|
||||
public void setHostname(String hostname) {
|
||||
_hostname = hostname;
|
||||
}
|
||||
|
||||
public Destination getDestination() {
|
||||
return _destination;
|
||||
}
|
||||
|
||||
public void setDestination(Destination destination) {
|
||||
_destination = destination;
|
||||
}
|
||||
|
||||
public void setDestination(String base64) {
|
||||
try {
|
||||
Destination result = new Destination();
|
||||
result.fromBase64(base64);
|
||||
_destination = result;
|
||||
} catch (DataFormatException dfe) {
|
||||
_destination = null;
|
||||
}
|
||||
}
|
||||
|
||||
public void readBytes(InputStream in) throws DataFormatException,
|
||||
IOException {
|
||||
_hostname = DataHelper.readString(in);
|
||||
_destination = new Destination();
|
||||
_destination.readBytes(in);
|
||||
}
|
||||
|
||||
public void writeBytes(OutputStream out) throws DataFormatException,
|
||||
IOException {
|
||||
if ((_hostname == null) || (_destination == null))
|
||||
throw new DataFormatException("Not enough data to write address");
|
||||
DataHelper.writeString(out, _hostname);
|
||||
_destination.writeBytes(out);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object obj) {
|
||||
if ((obj == null) || !(obj instanceof Address)) return false;
|
||||
Address addr = (Address) obj;
|
||||
return DataHelper.eq(_hostname, addr.getHostname())
|
||||
&& DataHelper.eq(_destination, addr.getDestination());
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return DataHelper.hashCode(_hostname)
|
||||
+ DataHelper.hashCode(_destination);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
StringBuilder buf = new StringBuilder(64);
|
||||
buf.append("[Address: ");
|
||||
buf.append("\n\tHostname: ").append(_hostname);
|
||||
buf.append("\n\tDestination: ").append(_destination);
|
||||
buf.append("]");
|
||||
return buf.toString();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -26,6 +26,7 @@ import java.io.OutputStreamWriter;
|
||||
import java.io.PrintWriter;
|
||||
import java.io.UnsupportedEncodingException;
|
||||
import java.math.BigInteger;
|
||||
import java.security.MessageDigest;
|
||||
import java.text.DecimalFormat;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
@@ -1010,13 +1011,14 @@ public class DataHelper {
|
||||
* Warning - 8KB line length limit as of 0.7.13, @throws IOException if exceeded
|
||||
* Warning - not UTF-8
|
||||
*/
|
||||
public static String readLine(InputStream in) throws IOException { return readLine(in, (Sha256Standalone)null); }
|
||||
public static String readLine(InputStream in) throws IOException { return readLine(in, (MessageDigest) null); }
|
||||
|
||||
/**
|
||||
* update the hash along the way
|
||||
* Warning - strips \n but not \r
|
||||
* Warning - 8KB line length limit as of 0.7.13, @throws IOException if exceeded
|
||||
* Warning - not UTF-8
|
||||
* @deprecated use MessageDigest version
|
||||
*/
|
||||
public static String readLine(InputStream in, Sha256Standalone hash) throws IOException {
|
||||
StringBuilder buf = new StringBuilder(128);
|
||||
@@ -1027,6 +1029,22 @@ public class DataHelper {
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* update the hash along the way
|
||||
* Warning - strips \n but not \r
|
||||
* Warning - 8KB line length limit as of 0.7.13, @throws IOException if exceeded
|
||||
* Warning - not UTF-8
|
||||
* @since 0.8.8
|
||||
*/
|
||||
public static String readLine(InputStream in, MessageDigest hash) throws IOException {
|
||||
StringBuilder buf = new StringBuilder(128);
|
||||
boolean ok = readLine(in, buf, hash);
|
||||
if (ok)
|
||||
return buf.toString();
|
||||
else
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Read in a line, placing it into the buffer (excluding the newline).
|
||||
* Warning - strips \n but not \r
|
||||
@@ -1050,7 +1068,7 @@ public class DataHelper {
|
||||
* Warning - strips \n but not \r
|
||||
* Warning - 8KB line length limit as of 0.7.13, @throws IOException if exceeded
|
||||
* Warning - not UTF-8
|
||||
* @deprecated use StringBuilder version
|
||||
* @deprecated use StringBuilder / MessageDigest version
|
||||
*/
|
||||
@Deprecated
|
||||
public static boolean readLine(InputStream in, StringBuffer buf, Sha256Standalone hash) throws IOException {
|
||||
@@ -1080,7 +1098,7 @@ public class DataHelper {
|
||||
* newline was found
|
||||
*/
|
||||
public static boolean readLine(InputStream in, StringBuilder buf) throws IOException {
|
||||
return readLine(in, buf, null);
|
||||
return readLine(in, buf, (MessageDigest) null);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1088,6 +1106,7 @@ public class DataHelper {
|
||||
* Warning - strips \n but not \r
|
||||
* Warning - 8KB line length limit as of 0.7.13, @throws IOException if exceeded
|
||||
* Warning - not UTF-8
|
||||
* @deprecated use MessageDigest version
|
||||
*/
|
||||
public static boolean readLine(InputStream in, StringBuilder buf, Sha256Standalone hash) throws IOException {
|
||||
int c = -1;
|
||||
@@ -1103,10 +1122,44 @@ public class DataHelper {
|
||||
return c != -1;
|
||||
}
|
||||
|
||||
/**
|
||||
* update the hash along the way
|
||||
* Warning - strips \n but not \r
|
||||
* Warning - 8KB line length limit as of 0.7.13, @throws IOException if exceeded
|
||||
* Warning - not UTF-8
|
||||
* @since 0.8.8
|
||||
*/
|
||||
public static boolean readLine(InputStream in, StringBuilder buf, MessageDigest hash) throws IOException {
|
||||
int c = -1;
|
||||
int i = 0;
|
||||
while ( (c = in.read()) != -1) {
|
||||
if (++i > MAX_LINE_LENGTH)
|
||||
throw new IOException("Line too long - max " + MAX_LINE_LENGTH);
|
||||
if (hash != null) hash.update((byte)c);
|
||||
if (c == '\n')
|
||||
break;
|
||||
buf.append((char)c);
|
||||
}
|
||||
return c != -1;
|
||||
}
|
||||
|
||||
/**
|
||||
* update the hash along the way
|
||||
* @deprecated use MessageDigest version
|
||||
*/
|
||||
public static void write(OutputStream out, byte data[], Sha256Standalone hash) throws IOException {
|
||||
hash.update(data);
|
||||
out.write(data);
|
||||
}
|
||||
|
||||
/**
|
||||
* update the hash along the way
|
||||
* @since 0.8.8
|
||||
*/
|
||||
public static void write(OutputStream out, byte data[], MessageDigest hash) throws IOException {
|
||||
hash.update(data);
|
||||
out.write(data);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sort based on the Hash of the DataStructure.
|
||||
|
||||
@@ -218,8 +218,8 @@ public class Rate {
|
||||
long measuredPeriod = now - _lastCoalesceDate;
|
||||
if (measuredPeriod < _period - SLACK) {
|
||||
// no need to coalesce (assuming we only try to do so once per minute)
|
||||
if (_log.shouldLog(Log.DEBUG))
|
||||
_log.debug("not coalescing, measuredPeriod = " + measuredPeriod + " period = " + _period);
|
||||
//if (_log.shouldLog(Log.DEBUG))
|
||||
// _log.debug("not coalescing, measuredPeriod = " + measuredPeriod + " period = " + _period);
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
@@ -316,7 +316,6 @@ public class Timestamper implements Runnable {
|
||||
System.setProperty(PROP_DISABLED, "false");
|
||||
System.setProperty(PROP_QUERY_FREQUENCY, "30000");
|
||||
I2PAppContext ctx = I2PAppContext.getGlobalContext();
|
||||
long now = ctx.clock().now();
|
||||
for (int i = 0; i < 5*60*1000; i += 61*1000) {
|
||||
try { Thread.sleep(61*1000); } catch (InterruptedException ie) {}
|
||||
}
|
||||
|
||||
11
history.txt
11
history.txt
@@ -1,3 +1,14 @@
|
||||
2011-07-08 zzz
|
||||
* Findbugs: Several fixes and cleanups
|
||||
* I2NP: Consolidate common code from TunnelBuildMessage and
|
||||
TunnelBuildReplyMessage into a common base class
|
||||
* NetDB, TestJob: Fix NPEs at startup (ticket #493)
|
||||
* Sha256Standalone:
|
||||
- Use system SHA-256 MessageDigest instead of Sha256Standalone in PRNG
|
||||
- Deprecate DataHelper functions using Sha256Standalone arguments;
|
||||
used only by Syndie
|
||||
- Note deprecation in javadocs
|
||||
|
||||
2011-07-07 zzz
|
||||
* Blockfile:
|
||||
- Log error on out-of-order spans
|
||||
|
||||
@@ -3,65 +3,24 @@ package net.i2p.data.i2np;
|
||||
import java.io.IOException;
|
||||
|
||||
import net.i2p.I2PAppContext;
|
||||
import net.i2p.data.ByteArray;
|
||||
|
||||
/**
|
||||
*
|
||||
* The basic build message with 8 records.
|
||||
*/
|
||||
public class TunnelBuildMessage extends I2NPMessageImpl {
|
||||
protected ByteArray _records[];
|
||||
protected int RECORD_COUNT;
|
||||
public static final int MAX_RECORD_COUNT = 8;
|
||||
|
||||
public class TunnelBuildMessage extends TunnelBuildMessageBase {
|
||||
|
||||
public static final int MESSAGE_TYPE = 21;
|
||||
|
||||
public TunnelBuildMessage(I2PAppContext context) {
|
||||
this(context, MAX_RECORD_COUNT);
|
||||
super(context, MAX_RECORD_COUNT);
|
||||
}
|
||||
|
||||
/** @since 0.7.12 */
|
||||
protected TunnelBuildMessage(I2PAppContext context, int records) {
|
||||
super(context);
|
||||
if (records > 0) {
|
||||
RECORD_COUNT = records;
|
||||
_records = new ByteArray[records];
|
||||
}
|
||||
// else will be initialized by readMessage() in VTBM
|
||||
super(context, records);
|
||||
}
|
||||
|
||||
public void setRecord(int index, ByteArray record) { _records[index] = record; }
|
||||
public ByteArray getRecord(int index) { return _records[index]; }
|
||||
/** @since 0.7.12 */
|
||||
public int getRecordCount() { return RECORD_COUNT; }
|
||||
|
||||
public static final int RECORD_SIZE = 512+16;
|
||||
|
||||
protected int calculateWrittenLength() { return RECORD_SIZE * RECORD_COUNT; }
|
||||
public int getType() { return MESSAGE_TYPE; }
|
||||
public void readMessage(byte[] data, int offset, int dataSize, int type) throws I2NPMessageException, IOException {
|
||||
if (type != MESSAGE_TYPE)
|
||||
throw new I2NPMessageException("Message type is incorrect for this message");
|
||||
if (dataSize != calculateWrittenLength())
|
||||
throw new I2NPMessageException("Wrong length (expects " + calculateWrittenLength() + ", recv " + dataSize + ")");
|
||||
|
||||
for (int i = 0; i < RECORD_COUNT; i++) {
|
||||
int off = offset + (i * RECORD_SIZE);
|
||||
byte rec[] = new byte[RECORD_SIZE];
|
||||
System.arraycopy(data, off, rec, 0, RECORD_SIZE);
|
||||
setRecord(i, new ByteArray(rec)); //new ByteArray(data, off, len));
|
||||
}
|
||||
}
|
||||
|
||||
protected int writeMessageBody(byte[] out, int curIndex) throws I2NPMessageException {
|
||||
int remaining = out.length - (curIndex + calculateWrittenLength());
|
||||
if (remaining < 0)
|
||||
throw new I2NPMessageException("Not large enough (too short by " + remaining + ")");
|
||||
for (int i = 0; i < RECORD_COUNT; i++) {
|
||||
System.arraycopy(_records[i].getData(), _records[i].getOffset(), out, curIndex, RECORD_SIZE);
|
||||
curIndex += RECORD_SIZE;
|
||||
}
|
||||
return curIndex;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
|
||||
@@ -0,0 +1,68 @@
|
||||
package net.i2p.data.i2np;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
import net.i2p.I2PAppContext;
|
||||
import net.i2p.data.ByteArray;
|
||||
|
||||
/**
|
||||
* Base for TBM, TBRM, VTBM, VTBRM
|
||||
* Retrofitted over them.
|
||||
* There's really no difference between the build and build reply.
|
||||
* @since 0.8.8
|
||||
*/
|
||||
public abstract class TunnelBuildMessageBase extends I2NPMessageImpl {
|
||||
protected ByteArray _records[];
|
||||
protected int RECORD_COUNT;
|
||||
public static final int MAX_RECORD_COUNT = 8;
|
||||
|
||||
public TunnelBuildMessageBase(I2PAppContext context) {
|
||||
this(context, MAX_RECORD_COUNT);
|
||||
}
|
||||
|
||||
/** @since 0.7.12 */
|
||||
protected TunnelBuildMessageBase(I2PAppContext context, int records) {
|
||||
super(context);
|
||||
if (records > 0) {
|
||||
RECORD_COUNT = records;
|
||||
_records = new ByteArray[records];
|
||||
}
|
||||
// else will be initialized by readMessage()
|
||||
}
|
||||
|
||||
public void setRecord(int index, ByteArray record) { _records[index] = record; }
|
||||
|
||||
public ByteArray getRecord(int index) { return _records[index]; }
|
||||
|
||||
/** @since 0.7.12 */
|
||||
public int getRecordCount() { return RECORD_COUNT; }
|
||||
|
||||
public static final int RECORD_SIZE = 512+16;
|
||||
|
||||
protected int calculateWrittenLength() { return RECORD_SIZE * RECORD_COUNT; }
|
||||
|
||||
public void readMessage(byte[] data, int offset, int dataSize, int type) throws I2NPMessageException, IOException {
|
||||
if (type != getType())
|
||||
throw new I2NPMessageException("Message type is incorrect for this message");
|
||||
if (dataSize != calculateWrittenLength())
|
||||
throw new I2NPMessageException("Wrong length (expects " + calculateWrittenLength() + ", recv " + dataSize + ")");
|
||||
|
||||
for (int i = 0; i < RECORD_COUNT; i++) {
|
||||
int off = offset + (i * RECORD_SIZE);
|
||||
byte rec[] = new byte[RECORD_SIZE];
|
||||
System.arraycopy(data, off, rec, 0, RECORD_SIZE);
|
||||
setRecord(i, new ByteArray(rec));
|
||||
}
|
||||
}
|
||||
|
||||
protected int writeMessageBody(byte[] out, int curIndex) throws I2NPMessageException {
|
||||
int remaining = out.length - (curIndex + calculateWrittenLength());
|
||||
if (remaining < 0)
|
||||
throw new I2NPMessageException("Not large enough (too short by " + remaining + ")");
|
||||
for (int i = 0; i < RECORD_COUNT; i++) {
|
||||
System.arraycopy(_records[i].getData(), _records[i].getOffset(), out, curIndex, RECORD_SIZE);
|
||||
curIndex += RECORD_SIZE;
|
||||
}
|
||||
return curIndex;
|
||||
}
|
||||
}
|
||||
@@ -3,68 +3,26 @@ package net.i2p.data.i2np;
|
||||
import java.io.IOException;
|
||||
|
||||
import net.i2p.I2PAppContext;
|
||||
import net.i2p.data.ByteArray;
|
||||
|
||||
/**
|
||||
* The basic build reply message with 8 records.
|
||||
* Transmitted from the new outbound endpoint to the creator through a
|
||||
* reply tunnel
|
||||
*/
|
||||
public class TunnelBuildReplyMessage extends I2NPMessageImpl {
|
||||
protected ByteArray _records[];
|
||||
protected int RECORD_COUNT;
|
||||
public static final int MAX_RECORD_COUNT = TunnelBuildMessage.MAX_RECORD_COUNT;
|
||||
|
||||
public class TunnelBuildReplyMessage extends TunnelBuildMessageBase {
|
||||
|
||||
public static final int MESSAGE_TYPE = 22;
|
||||
|
||||
public TunnelBuildReplyMessage(I2PAppContext context) {
|
||||
this(context, MAX_RECORD_COUNT);
|
||||
super(context, MAX_RECORD_COUNT);
|
||||
}
|
||||
|
||||
/** @since 0.7.12 */
|
||||
protected TunnelBuildReplyMessage(I2PAppContext context, int records) {
|
||||
super(context);
|
||||
if (records > 0) {
|
||||
RECORD_COUNT = records;
|
||||
_records = new ByteArray[records];
|
||||
}
|
||||
// else will be initialized by readMessage() in VTBRM
|
||||
super(context, records);
|
||||
}
|
||||
|
||||
public void setRecord(int index, ByteArray record) { _records[index] = record; }
|
||||
public ByteArray getRecord(int index) { return _records[index]; }
|
||||
/** @since 0.7.12 */
|
||||
public int getRecordCount() { return RECORD_COUNT; }
|
||||
|
||||
public static final int RECORD_SIZE = TunnelBuildMessage.RECORD_SIZE;
|
||||
|
||||
protected int calculateWrittenLength() { return RECORD_SIZE * RECORD_COUNT; }
|
||||
public int getType() { return MESSAGE_TYPE; }
|
||||
public void readMessage(byte[] data, int offset, int dataSize, int type) throws I2NPMessageException, IOException {
|
||||
if (type != MESSAGE_TYPE)
|
||||
throw new I2NPMessageException("Message type is incorrect for this message");
|
||||
if (dataSize != calculateWrittenLength())
|
||||
throw new I2NPMessageException("Wrong length (expects " + calculateWrittenLength() + ", recv " + dataSize + ")");
|
||||
|
||||
for (int i = 0; i < RECORD_COUNT; i++) {
|
||||
int off = offset + (i * RECORD_SIZE);
|
||||
int len = RECORD_SIZE;
|
||||
byte rec[] = new byte[RECORD_SIZE];
|
||||
System.arraycopy(data, off, rec, 0, RECORD_SIZE);
|
||||
setRecord(i, new ByteArray(rec));
|
||||
//setRecord(i, new ByteArray(data, off, len));
|
||||
}
|
||||
}
|
||||
|
||||
protected int writeMessageBody(byte[] out, int curIndex) throws I2NPMessageException {
|
||||
int remaining = out.length - (curIndex + calculateWrittenLength());
|
||||
if (remaining < 0)
|
||||
throw new I2NPMessageException("Not large enough (too short by " + remaining + ")");
|
||||
for (int i = 0; i < RECORD_COUNT; i++) {
|
||||
System.arraycopy(_records[i].getData(), _records[i].getOffset(), out, curIndex, RECORD_SIZE);
|
||||
curIndex += RECORD_SIZE;
|
||||
}
|
||||
return curIndex;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
|
||||
@@ -7,6 +7,8 @@ import net.i2p.data.ByteArray;
|
||||
import net.i2p.data.DataHelper;
|
||||
|
||||
/**
|
||||
* Variable number of records.
|
||||
*
|
||||
* @since 0.7.12
|
||||
*/
|
||||
public class VariableTunnelBuildMessage extends TunnelBuildMessage {
|
||||
@@ -29,8 +31,7 @@ public class VariableTunnelBuildMessage extends TunnelBuildMessage {
|
||||
|
||||
@Override
|
||||
public void readMessage(byte[] data, int offset, int dataSize, int type) throws I2NPMessageException, IOException {
|
||||
if (type != MESSAGE_TYPE)
|
||||
throw new I2NPMessageException("Message type is incorrect for this message");
|
||||
// message type will be checked in super()
|
||||
int r = (int)DataHelper.fromLong(data, offset, 1);
|
||||
if (r <= 0 || r > MAX_RECORD_COUNT)
|
||||
throw new I2NPMessageException("Bad record count " + r);
|
||||
@@ -38,7 +39,7 @@ public class VariableTunnelBuildMessage extends TunnelBuildMessage {
|
||||
if (dataSize != calculateWrittenLength())
|
||||
throw new I2NPMessageException("Wrong length (expects " + calculateWrittenLength() + ", recv " + dataSize + ")");
|
||||
_records = new ByteArray[RECORD_COUNT];
|
||||
super.readMessage(data, offset + 1, dataSize, TunnelBuildMessage.MESSAGE_TYPE);
|
||||
super.readMessage(data, offset + 1, dataSize, type);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -8,7 +8,8 @@ import net.i2p.data.DataHelper;
|
||||
|
||||
/**
|
||||
* Transmitted from the new outbound endpoint to the creator through a
|
||||
* reply tunnel
|
||||
* reply tunnel.
|
||||
* Variable number of records.
|
||||
*
|
||||
* @since 0.7.12
|
||||
*/
|
||||
@@ -30,9 +31,9 @@ public class VariableTunnelBuildReplyMessage extends TunnelBuildReplyMessage {
|
||||
@Override
|
||||
public int getType() { return MESSAGE_TYPE; }
|
||||
|
||||
@Override
|
||||
public void readMessage(byte[] data, int offset, int dataSize, int type) throws I2NPMessageException, IOException {
|
||||
if (type != MESSAGE_TYPE)
|
||||
throw new I2NPMessageException("Message type is incorrect for this message");
|
||||
// message type will be checked in super()
|
||||
int r = (int)DataHelper.fromLong(data, offset, 1);
|
||||
if (r <= 0 || r > MAX_RECORD_COUNT)
|
||||
throw new I2NPMessageException("Bad record count " + r);
|
||||
@@ -40,9 +41,10 @@ public class VariableTunnelBuildReplyMessage extends TunnelBuildReplyMessage {
|
||||
if (dataSize != calculateWrittenLength())
|
||||
throw new I2NPMessageException("Wrong length (expects " + calculateWrittenLength() + ", recv " + dataSize + ")");
|
||||
_records = new ByteArray[RECORD_COUNT];
|
||||
super.readMessage(data, offset + 1, dataSize, TunnelBuildReplyMessage.MESSAGE_TYPE);
|
||||
super.readMessage(data, offset + 1, dataSize, type);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected int writeMessageBody(byte[] out, int curIndex) throws I2NPMessageException {
|
||||
int remaining = out.length - (curIndex + calculateWrittenLength());
|
||||
if (remaining < 0)
|
||||
|
||||
@@ -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 = 6;
|
||||
public final static long BUILD = 8;
|
||||
|
||||
/** for example "-test" */
|
||||
public final static String EXTRA = "";
|
||||
|
||||
@@ -22,6 +22,7 @@ import net.i2p.router.RouterContext;
|
||||
import net.i2p.router.peermanager.PeerProfile;
|
||||
import net.i2p.router.util.RandomIterator;
|
||||
import net.i2p.stat.Rate;
|
||||
import net.i2p.stat.RateStat;
|
||||
import net.i2p.util.Log;
|
||||
|
||||
/**
|
||||
@@ -201,9 +202,12 @@ class FloodfillPeerSelector extends PeerSelector {
|
||||
} else {
|
||||
PeerProfile prof = _context.profileOrganizer().getProfile(entry);
|
||||
double maxGoodRespTime = MAX_GOOD_RESP_TIME;
|
||||
Rate tunnelTestTime = _context.statManager().getRate("tunnel.testSuccessTime").getRate(10*60*1000);
|
||||
if (tunnelTestTime != null && tunnelTestTime.getAverageValue() > 500)
|
||||
maxGoodRespTime = 2 * tunnelTestTime.getAverageValue();
|
||||
RateStat ttst = _context.statManager().getRate("tunnel.testSuccessTime");
|
||||
if (ttst != null) {
|
||||
Rate tunnelTestTime = ttst.getRate(10*60*1000);
|
||||
if (tunnelTestTime != null && tunnelTestTime.getAverageValue() > 500)
|
||||
maxGoodRespTime = 2 * tunnelTestTime.getAverageValue();
|
||||
}
|
||||
if (prof != null && prof.getDBHistory() != null
|
||||
&& prof.getDbResponseTime().getRate(10*60*1000).getAverageValue() < maxGoodRespTime
|
||||
&& prof.getDBHistory().getLastStoreFailed() < now - NO_FAIL_STORE_GOOD
|
||||
|
||||
@@ -379,7 +379,7 @@ class KBucketImpl implements KBucket {
|
||||
}
|
||||
|
||||
private static void testRand() {
|
||||
StringBuilder buf = new StringBuilder(2048);
|
||||
//StringBuilder buf = new StringBuilder(2048);
|
||||
int low = 1;
|
||||
int high = 3;
|
||||
Log log = I2PAppContext.getGlobalContext().logManager().getLog(KBucketImpl.class);
|
||||
|
||||
@@ -19,6 +19,8 @@ import net.i2p.router.RouterContext;
|
||||
import net.i2p.router.TunnelInfo;
|
||||
import net.i2p.router.message.GarlicMessageBuilder;
|
||||
import net.i2p.router.message.PayloadGarlicConfig;
|
||||
import net.i2p.stat.Rate;
|
||||
import net.i2p.stat.RateStat;
|
||||
import net.i2p.util.Log;
|
||||
|
||||
class TestJob extends JobImpl {
|
||||
@@ -219,8 +221,15 @@ class TestJob extends JobImpl {
|
||||
//
|
||||
// Try to prevent congestion collapse (failing all our tunnels and then clogging our outbound
|
||||
// with new tunnel build requests) by adding in three times the average outbound delay.
|
||||
int delay = 3 * (int) getContext().statManager().getRate("transport.sendProcessingTime").getRate(60*1000).getAverageValue();
|
||||
return delay + (2500 * (_outTunnel.getLength() + _replyTunnel.getLength()));
|
||||
RateStat tspt = getContext().statManager().getRate("transport.sendProcessingTime");
|
||||
if (tspt != null) {
|
||||
Rate r = tspt.getRate(60*1000);
|
||||
if (r != null) {
|
||||
int delay = 3 * (int) r.getAverageValue();
|
||||
return delay + (2500 * (_outTunnel.getLength() + _replyTunnel.getLength()));
|
||||
}
|
||||
}
|
||||
return 15*1000;
|
||||
}
|
||||
|
||||
private void scheduleRetest() { scheduleRetest(false); }
|
||||
|
||||
Reference in New Issue
Block a user