diff --git a/install-headless.txt b/INSTALL-headless.txt
similarity index 87%
rename from install-headless.txt
rename to INSTALL-headless.txt
index 6def73d54..03229c796 100644
--- a/install-headless.txt
+++ b/INSTALL-headless.txt
@@ -1,8 +1,7 @@
-$Id: install-headless.txt,v 1.5 2005/09/29 14:19:23 jrandom Exp $
Headless I2P installation instructions
1) tar xjf i2p.tar.bz2 (you've already done this)
-2) cd i2p ; vi install-headless.txt (you're doing this now)
+2) cd i2p ; vi INSTALL-headless.txt (you're doing this now)
3) sh postinstall.sh (this launches the router)
4) lynx http://localhost:7657/index.jsp (configure the router)
diff --git a/install.txt b/INSTALL.txt
similarity index 100%
rename from install.txt
rename to INSTALL.txt
diff --git a/apps/i2ptunnel/java/src/net/i2p/i2ptunnel/I2PTunnel.java b/apps/i2ptunnel/java/src/net/i2p/i2ptunnel/I2PTunnel.java
index 8e7627309..486bcdead 100644
--- a/apps/i2ptunnel/java/src/net/i2p/i2ptunnel/I2PTunnel.java
+++ b/apps/i2ptunnel/java/src/net/i2p/i2ptunnel/I2PTunnel.java
@@ -75,7 +75,7 @@ public class I2PTunnel implements Logging, EventDispatcher {
private static long __tunnelId = 0;
private long _tunnelId;
private Properties _clientOptions;
- private final List _sessions;
+ private final List _sessions;
public static final int PACKET_DELAY = 100;
@@ -179,7 +179,7 @@ public class I2PTunnel implements Logging, EventDispatcher {
}
}
- List getSessions() {
+ List getSessions() {
synchronized (_sessions) {
return new ArrayList(_sessions);
}
diff --git a/apps/i2ptunnel/java/src/net/i2p/i2ptunnel/I2PTunnelClientBase.java b/apps/i2ptunnel/java/src/net/i2p/i2ptunnel/I2PTunnelClientBase.java
index 3c571857a..190a4a96d 100644
--- a/apps/i2ptunnel/java/src/net/i2p/i2ptunnel/I2PTunnelClientBase.java
+++ b/apps/i2ptunnel/java/src/net/i2p/i2ptunnel/I2PTunnelClientBase.java
@@ -44,6 +44,7 @@ public abstract class I2PTunnelClientBase extends I2PTunnelTask implements Runna
protected final Object sockLock = new Object(); // Guards sockMgr and mySockets
protected I2PSocketManager sockMgr; // should be final and use a factory. LINT
protected List mySockets = new ArrayList();
+ protected boolean _ownDest;
protected Destination dest = null;
private int localPort;
@@ -114,6 +115,7 @@ public abstract class I2PTunnelClientBase extends I2PTunnelTask implements Runna
this.l = l;
this.handlerName = handlerName + _clientId;
this.privKeyFile = pkf;
+ _ownDest = ownDest; // == ! shared client
_context = tunnel.getContext();
@@ -129,13 +131,7 @@ public abstract class I2PTunnelClientBase extends I2PTunnelTask implements Runna
boolean openNow = !Boolean.valueOf(tunnel.getClientOptions().getProperty("i2cp.delayOpen")).booleanValue();
if (openNow) {
while (sockMgr == null) {
- synchronized (sockLock) {
- if (ownDest) {
- sockMgr = buildSocketManager();
- } else {
- sockMgr = getSocketManager();
- }
- }
+ verifySocketManager();
if (sockMgr == null) {
_log.log(Log.CRIT, "Unable to create socket manager (our own? " + ownDest + ")");
try { Thread.sleep(10*1000); } catch (InterruptedException ie) {}
@@ -209,27 +205,67 @@ public abstract class I2PTunnelClientBase extends I2PTunnelTask implements Runna
}
}
+ /**
+ * Sets the this.sockMgr field if it is null, or if we want a new one
+ *
+ * We need a socket manager before getDefaultOptions() and most other things
+ */
+ protected void verifySocketManager() {
+ synchronized(sockLock) {
+ boolean newManager = false;
+ if (this.sockMgr == null) {
+ newManager = true;
+ } else {
+ I2PSession sess = sockMgr.getSession();
+ if (sess == null) {
+ newManager = true;
+ } else if (sess.isClosed() &&
+ Boolean.valueOf(getTunnel().getClientOptions().getProperty("i2cp.closeOnIdle")).booleanValue() &&
+ Boolean.valueOf(getTunnel().getClientOptions().getProperty("i2cp.newDestOnResume")).booleanValue()) {
+ // build a new socket manager and a new dest if the session is closed.
+ getTunnel().removeSession(sess);
+ if (_log.shouldLog(Log.WARN))
+ _log.warn(getTunnel().getClientOptions().getProperty("inbound.nickname") + ": Built a new destination on resume");
+ newManager = true;
+ } // else the old socket manager will reconnect the old session if necessary
+ }
+ if (newManager) {
+ if (_ownDest)
+ this.sockMgr = buildSocketManager();
+ else
+ this.sockMgr = getSocketManager();
+ }
+ }
+ }
+
+ /** this is ONLY for shared clients */
private static I2PSocketManager socketManager;
+ /** this is ONLY for shared clients */
protected synchronized I2PSocketManager getSocketManager() {
return getSocketManager(getTunnel(), this.privKeyFile);
}
+ /** this is ONLY for shared clients */
protected static synchronized I2PSocketManager getSocketManager(I2PTunnel tunnel) {
return getSocketManager(tunnel, null);
}
+ /** this is ONLY for shared clients */
protected static synchronized I2PSocketManager getSocketManager(I2PTunnel tunnel, String pkf) {
if (socketManager != null) {
I2PSession s = socketManager.getSession();
if ( (s == null) || (s.isClosed()) ) {
- _log.info("Building a new socket manager since the old one closed [s=" + s + "]");
+ if (_log.shouldLog(Log.INFO))
+ _log.info(tunnel.getClientOptions().getProperty("inbound.nickname") + ": Building a new socket manager since the old one closed [s=" + s + "]");
if (s != null)
tunnel.removeSession(s);
socketManager = buildSocketManager(tunnel, pkf);
} else {
- _log.info("Not building a new socket manager since the old one is open [s=" + s + "]");
+ if (_log.shouldLog(Log.INFO))
+ _log.info(tunnel.getClientOptions().getProperty("inbound.nickname") + ": Not building a new socket manager since the old one is open [s=" + s + "]");
}
} else {
- _log.info("Building a new socket manager since there is no other one");
+ if (_log.shouldLog(Log.INFO))
+ _log.info(tunnel.getClientOptions().getProperty("inbound.nickname") + ": Building a new socket manager since there is no other one");
socketManager = buildSocketManager(tunnel, pkf);
}
return socketManager;
@@ -278,6 +314,8 @@ public abstract class I2PTunnelClientBase extends I2PTunnelTask implements Runna
}
}
sockManager.setName("Client");
+ if (_log.shouldLog(Log.INFO))
+ _log.info(tunnel.getClientOptions().getProperty("inbound.nickname") + ": Built a new socket manager [s=" + sockManager.getSession() + "]");
tunnel.addSession(sockManager.getSession());
return sockManager;
}
@@ -343,12 +381,7 @@ public abstract class I2PTunnelClientBase extends I2PTunnelTask implements Runna
* @return a new I2PSocket
*/
public I2PSocket createI2PSocket(Destination dest) throws I2PException, ConnectException, NoRouteToHostException, InterruptedIOException {
- if (sockMgr == null) {
- // we need this before getDefaultOptions()
- synchronized(sockLock) {
- sockMgr = getSocketManager();
- }
- }
+ verifySocketManager();
return createI2PSocket(dest, getDefaultOptions());
}
@@ -369,22 +402,7 @@ public abstract class I2PTunnelClientBase extends I2PTunnelTask implements Runna
public I2PSocket createI2PSocket(Destination dest, I2PSocketOptions opt) throws I2PException, ConnectException, NoRouteToHostException, InterruptedIOException {
I2PSocket i2ps;
- if (sockMgr == null) {
- // delayed open - call get instead of build because the locking is up there
- synchronized(sockLock) {
- sockMgr = getSocketManager();
- }
- } else if (Boolean.valueOf(getTunnel().getClientOptions().getProperty("i2cp.closeOnIdle")).booleanValue() &&
- Boolean.valueOf(getTunnel().getClientOptions().getProperty("i2cp.newDestOnResume")).booleanValue()) {
- synchronized(sockLock) {
- I2PSocketManager oldSockMgr = sockMgr;
- // This will build a new socket manager and a new dest if the session is closed.
- sockMgr = getSocketManager();
- if (oldSockMgr != sockMgr) {
- _log.warn("Built a new destination on resume");
- }
- }
- } // else the old socket manager will reconnect the old session if necessary
+ verifySocketManager();
i2ps = sockMgr.connect(dest, opt);
synchronized (sockLock) {
mySockets.add(i2ps);
diff --git a/apps/i2ptunnel/java/src/net/i2p/i2ptunnel/I2PTunnelConnectClient.java b/apps/i2ptunnel/java/src/net/i2p/i2ptunnel/I2PTunnelConnectClient.java
index 13906807e..59971e8f3 100644
--- a/apps/i2ptunnel/java/src/net/i2p/i2ptunnel/I2PTunnelConnectClient.java
+++ b/apps/i2ptunnel/java/src/net/i2p/i2ptunnel/I2PTunnelConnectClient.java
@@ -157,11 +157,7 @@ public class I2PTunnelConnectClient extends I2PTunnelClientBase implements Runna
if (!defaultOpts.contains("i2p.streaming.inactivityTimeout"))
defaultOpts.setProperty("i2p.streaming.inactivityTimeout", ""+DEFAULT_READ_TIMEOUT);
// delayed start
- if (sockMgr == null) {
- synchronized(sockLock) {
- sockMgr = getSocketManager();
- }
- }
+ verifySocketManager();
I2PSocketOptions opts = sockMgr.buildOptions(defaultOpts);
if (!defaultOpts.containsKey(I2PSocketOptions.PROP_CONNECT_TIMEOUT))
opts.setConnectTimeout(DEFAULT_CONNECT_TIMEOUT);
diff --git a/apps/i2ptunnel/java/src/net/i2p/i2ptunnel/I2PTunnelHTTPClient.java b/apps/i2ptunnel/java/src/net/i2p/i2ptunnel/I2PTunnelHTTPClient.java
index 316731dee..7e16114ad 100644
--- a/apps/i2ptunnel/java/src/net/i2p/i2ptunnel/I2PTunnelHTTPClient.java
+++ b/apps/i2ptunnel/java/src/net/i2p/i2ptunnel/I2PTunnelHTTPClient.java
@@ -211,11 +211,7 @@ public class I2PTunnelHTTPClient extends I2PTunnelClientBase implements Runnable
if (!defaultOpts.contains("i2p.streaming.inactivityTimeout"))
defaultOpts.setProperty("i2p.streaming.inactivityTimeout", ""+DEFAULT_READ_TIMEOUT);
// delayed start
- if (sockMgr == null) {
- synchronized(sockLock) {
- sockMgr = getSocketManager();
- }
- }
+ verifySocketManager();
I2PSocketOptions opts = sockMgr.buildOptions(defaultOpts);
if (!defaultOpts.containsKey(I2PSocketOptions.PROP_CONNECT_TIMEOUT))
opts.setConnectTimeout(DEFAULT_CONNECT_TIMEOUT);
diff --git a/apps/i2ptunnel/java/src/net/i2p/i2ptunnel/TunnelController.java b/apps/i2ptunnel/java/src/net/i2p/i2ptunnel/TunnelController.java
index 419e5a899..1f67783e9 100644
--- a/apps/i2ptunnel/java/src/net/i2p/i2ptunnel/TunnelController.java
+++ b/apps/i2ptunnel/java/src/net/i2p/i2ptunnel/TunnelController.java
@@ -434,6 +434,16 @@ public class TunnelController implements Logging {
public boolean getIsRunning() { return _running; }
public boolean getIsStarting() { return _starting; }
+ /** if running but no open sessions, we are in standby */
+ public boolean getIsStandby() {
+ if (!_running)
+ return false;
+ for (I2PSession sess : _tunnel.getSessions()) {
+ if (!sess.isClosed())
+ return false;
+ }
+ return true;
+ }
public void getSummary(StringBuffer buf) {
String type = getType();
diff --git a/apps/i2ptunnel/java/src/net/i2p/i2ptunnel/web/IndexBean.java b/apps/i2ptunnel/java/src/net/i2p/i2ptunnel/web/IndexBean.java
index 24bbb9119..4c23ced34 100644
--- a/apps/i2ptunnel/java/src/net/i2p/i2ptunnel/web/IndexBean.java
+++ b/apps/i2ptunnel/java/src/net/i2p/i2ptunnel/web/IndexBean.java
@@ -77,6 +77,7 @@ public class IndexBean {
public static final int RUNNING = 1;
public static final int STARTING = 2;
public static final int NOT_RUNNING = 3;
+ public static final int STANDBY = 4;
public static final String PROP_TUNNEL_PASSPHRASE = "i2ptunnel.passphrase";
static final String PROP_NONCE = IndexBean.class.getName() + ".nonce";
@@ -412,8 +413,12 @@ public class IndexBean {
public int getTunnelStatus(int tunnel) {
TunnelController tun = getController(tunnel);
if (tun == null) return NOT_RUNNING;
- if (tun.getIsRunning()) return RUNNING;
- else if (tun.getIsStarting()) return STARTING;
+ if (tun.getIsRunning()) {
+ if (isClient(tunnel) && tun.getIsStandby())
+ return STANDBY;
+ else
+ return RUNNING;
+ } else if (tun.getIsStarting()) return STARTING;
else return NOT_RUNNING;
}
@@ -778,12 +783,6 @@ public class IndexBean {
config.setProperty("interface", _reachableByOther);
else
config.setProperty("interface", _reachableBy);
- config.setProperty("option.inbound.nickname", CLIENT_NICKNAME);
- config.setProperty("option.outbound.nickname", CLIENT_NICKNAME);
- if (_name != null && !_sharedClient) {
- config.setProperty("option.inbound.nickname", _name);
- config.setProperty("option.outbound.nickname", _name);
- }
config.setProperty("sharedClient", _sharedClient + "");
for (String p : _booleanClientOpts)
config.setProperty("option." + p, "" + _booleanOptions.contains(p));
@@ -896,14 +895,12 @@ public class IndexBean {
config.setProperty("option.i2p.streaming.connectDelay", "1000");
else
config.setProperty("option.i2p.streaming.connectDelay", "0");
- if (_name != null) {
- if ( (!isClient(_type)) || (!_sharedClient) ) {
- config.setProperty("option.inbound.nickname", _name);
- config.setProperty("option.outbound.nickname", _name);
- } else {
- config.setProperty("option.inbound.nickname", CLIENT_NICKNAME);
- config.setProperty("option.outbound.nickname", CLIENT_NICKNAME);
- }
+ if (isClient(_type) && _sharedClient) {
+ config.setProperty("option.inbound.nickname", CLIENT_NICKNAME);
+ config.setProperty("option.outbound.nickname", CLIENT_NICKNAME);
+ } else if (_name != null) {
+ config.setProperty("option.inbound.nickname", _name);
+ config.setProperty("option.outbound.nickname", _name);
}
if ("interactive".equals(_profile))
// This was 1 which doesn't make much sense
diff --git a/apps/i2ptunnel/jsp/index.jsp b/apps/i2ptunnel/jsp/index.jsp
index 4d9f6c57d..6c89d5ff4 100644
--- a/apps/i2ptunnel/jsp/index.jsp
+++ b/apps/i2ptunnel/jsp/index.jsp
@@ -97,6 +97,11 @@
case IndexBean.STARTING:
%>
+ Stop
<%
break;
case IndexBean.RUNNING:
diff --git a/apps/routerconsole/java/src/net/i2p/router/web/ReseedHandler.java b/apps/routerconsole/java/src/net/i2p/router/web/ReseedHandler.java
index 066cb1144..e701ede99 100644
--- a/apps/routerconsole/java/src/net/i2p/router/web/ReseedHandler.java
+++ b/apps/routerconsole/java/src/net/i2p/router/web/ReseedHandler.java
@@ -91,8 +91,9 @@ public class ReseedHandler {
public boolean isRunning() { return _isRunning; }
public void run() {
_isRunning = true;
+ System.out.println("Reseed start");
reseed(false);
- System.out.println("Reseeding complete");
+ System.out.println("Reseed complete");
System.setProperty("net.i2p.router.web.ReseedHandler.reseedInProgress", "false");
_isRunning = false;
}
@@ -133,7 +134,7 @@ public class ReseedHandler {
}
/**
- * Fetch a directory listing and then all the routerInfo files in the listing.
+ * Fetch a directory listing and then up to 200 routerInfo files in the listing.
* The listing must contain (exactly) strings that match:
* href="routerInfo-{hash}.dat">
* and then it fetches the files
@@ -147,6 +148,7 @@ public class ReseedHandler {
try {
System.setProperty("net.i2p.router.web.ReseedHandler.errorMessage","");
System.setProperty("net.i2p.router.web.ReseedHandler.statusMessage","Reseeding: fetching seed URL.");
+ System.err.println("Reseed from " + seedURL);
URL dir = new URL(seedURL);
byte contentRaw[] = readURL(dir);
if (contentRaw == null) {
@@ -160,7 +162,8 @@ public class ReseedHandler {
String content = new String(contentRaw);
Set urls = new HashSet();
int cur = 0;
- while (true) {
+ int total = 0;
+ while (total++ < 1000) {
int start = content.indexOf("href=\"routerInfo-", cur);
if (start < 0)
break;
@@ -170,7 +173,7 @@ public class ReseedHandler {
urls.add(name);
cur = end + 1;
}
- if (urls.size() <= 0) {
+ if (total <= 0) {
_log.error("Read " + contentRaw.length + " bytes from seed " + seedURL + ", but found no routerInfo URLs.");
System.setProperty("net.i2p.router.web.ReseedHandler.errorMessage",
"Last reseed failed fully (no routerInfo URLs at seed URL). " +
@@ -178,13 +181,16 @@ public class ReseedHandler {
return;
}
+ List urlList = new ArrayList(urls);
+ Collections.shuffle(urlList);
int fetched = 0;
int errors = 0;
- for (Iterator iter = urls.iterator(); iter.hasNext(); ) {
+ // 200 max from one URL
+ for (Iterator iter = urlList.iterator(); iter.hasNext() && fetched < 200; ) {
try {
System.setProperty("net.i2p.router.web.ReseedHandler.statusMessage",
"Reseeding: fetching router info from seed URL (" +
- fetched + " successful, " + errors + " errors, " + urls.size() + " total).");
+ fetched + " successful, " + errors + " errors, " + total + " total).");
fetchSeed(seedURL, (String)iter.next());
fetched++;
@@ -197,24 +203,24 @@ public class ReseedHandler {
errors++;
}
}
- if (echoStatus) System.out.println();
+ System.err.println("Reseed got " + fetched + " router infos from " + seedURL);
- int failPercent = 100 * errors / urls.size();
+ int failPercent = 100 * errors / total;
// Less than 10% of failures is considered success,
// because some routerInfos will always fail.
if ((failPercent >= 10) && (failPercent < 90)) {
System.setProperty("net.i2p.router.web.ReseedHandler.errorMessage",
- "Last reseed failed partly (" + failPercent + "% of " + urls.size() + "). " +
+ "Last reseed failed partly (" + failPercent + "% of " + total + "). " +
RESEED_TIPS);
}
if (failPercent >= 90) {
System.setProperty("net.i2p.router.web.ReseedHandler.errorMessage",
- "Last reseed failed (" + failPercent + "% of " + urls.size() + "). " +
+ "Last reseed failed (" + failPercent + "% of " + total + "). " +
RESEED_TIPS);
}
// Don't go on to the next URL if we have enough
- if (fetched > 25)
+ if (fetched >= 100)
_isRunning = false;
} catch (Throwable t) {
System.setProperty("net.i2p.router.web.ReseedHandler.errorMessage",
diff --git a/apps/routerconsole/jsp/configservice.jsp b/apps/routerconsole/jsp/configservice.jsp
index 5d9de218a..a69c112db 100644
--- a/apps/routerconsole/jsp/configservice.jsp
+++ b/apps/routerconsole/jsp/configservice.jsp
@@ -32,6 +32,7 @@
+ <% if (System.getProperty("wrapper.version") != null) { %>
If you want the router to restart itself after shutting down, you can choose one of
the following. This is useful in some situations - for example, if you changed
some settings that client applications only read at startup, such as the routerconsole password
@@ -41,6 +42,7 @@
+ <% } %>
<% if ( (System.getProperty("os.name") != null) && (System.getProperty("os.name").startsWith("Win")) ) { %>
Systray integration
@@ -61,11 +63,14 @@
down your router immediately. You may want to consider shutting down gracefully, as
above, then running uninstall_i2p_service_winnt.bat.
At times, it may be helpful to debug I2P by getting a thread dump. To do so,
please select the following option and review the thread dumped to
wrapper.log.
+ <% } %>
Launch browser on router startup?
I2P's main configuration interface is this web console, so for your convenience
diff --git a/build.xml b/build.xml
index f7a7294e3..8fadcf831 100644
--- a/build.xml
+++ b/build.xml
@@ -278,7 +278,7 @@
-
+
diff --git a/checklist.txt b/checklist.txt
index fcbe65028..baea847b9 100644
--- a/checklist.txt
+++ b/checklist.txt
@@ -18,6 +18,10 @@ Review the complete diff from the last release:
mtn diff -r t:i2p-0.7.(xx-1) > out.diff
vi out.diff
+Verify that no untrusted revisions were inadvertently
+blessed by a trusted party:
+ mtn log --brief --no-graph --to t:i2p-0.7.(xx-1) | cut -d ' ' -f 2- | sort
+
Build and tag:
ant pkg
mtn ci
diff --git a/router/java/src/net/i2p/router/RouterWatchdog.java b/router/java/src/net/i2p/router/RouterWatchdog.java
index e14331b6d..cb1681022 100644
--- a/router/java/src/net/i2p/router/RouterWatchdog.java
+++ b/router/java/src/net/i2p/router/RouterWatchdog.java
@@ -49,11 +49,15 @@ class RouterWatchdog implements Runnable {
}
private boolean shutdownOnHang() {
+ // prop default true
+ if (!Boolean.valueOf(_context.getProperty("watchdog.haltOnHang", "true")).booleanValue())
+ return false;
+
// Client manager starts complaining after 10 minutes, and we run every minute,
- // so this will restart 20 minutes after we lose a lease, if the wrapper is present.
- if (_consecutiveErrors >= 10 && System.getProperty("wrapper.version") != null)
+ // so this will restart 30 minutes after we lose a lease, if the wrapper is present.
+ if (_consecutiveErrors >= 20 && System.getProperty("wrapper.version") != null)
return true;
- return Boolean.valueOf(_context.getProperty("watchdog.haltOnHang", "false")).booleanValue();
+ return false;
}
private void dumpStatus() {
@@ -90,13 +94,14 @@ class RouterWatchdog implements Runnable {
long used = Runtime.getRuntime().totalMemory() - Runtime.getRuntime().freeMemory();
_log.error("Memory: " + DataHelper.formatSize(used) + '/' + DataHelper.formatSize(max));
if (_consecutiveErrors == 1) {
+ _log.log(Log.CRIT, "Router appears hung! Will restart in 20 minutes if it doesn't fix itself");
// This might work on linux...
// It won't on windows, and we can't call i2prouter.bat either, it does something
// completely different...
ShellCommand sc = new ShellCommand();
boolean success = sc.executeSilentAndWaitTimed("./i2prouter dump", 10);
if (success)
- _log.error("DUMPED THREADS TO WRAPPER LOG");
+ _log.log(Log.CRIT, "Threads dumped to wrapper log");
}
}
}
@@ -127,7 +132,7 @@ class RouterWatchdog implements Runnable {
_consecutiveErrors++;
dumpStatus();
if (shutdownOnHang()) {
- _log.log(Log.CRIT, "Router hung! hard restart!");
+ _log.log(Log.CRIT, "Router hung! Restart forced by watchdog!");
try { Thread.sleep(30*1000); } catch (InterruptedException ie) {}
// halt and not system.exit, since some of the shutdown hooks might be misbehaving
Runtime.getRuntime().halt(Router.EXIT_HARD_RESTART);
diff --git a/router/java/src/net/i2p/router/StatisticsManager.java b/router/java/src/net/i2p/router/StatisticsManager.java
index d037ee300..f107c5e1e 100644
--- a/router/java/src/net/i2p/router/StatisticsManager.java
+++ b/router/java/src/net/i2p/router/StatisticsManager.java
@@ -87,9 +87,14 @@ public class StatisticsManager implements Service {
if (_includePeerRankings) {
long publishedUptime = _context.router().getUptime();
+ boolean commentOutIn074 = RouterVersion.VERSION.equals("0.7.3");
// Don't publish these for first hour
- if (publishedUptime > 60*60*1000)
- includeThroughput(stats);
+ if (publishedUptime > 62*60*1000) {
+ if (commentOutIn074)
+ includeThroughput(stats);
+ else
+ includeAverageThroughput(stats);
+ }
//includeRate("router.invalidMessageTime", stats, new long[] { 10*60*1000 });
//includeRate("router.duplicateMessageId", stats, new long[] { 24*60*60*1000 });
//includeRate("tunnel.duplicateIV", stats, new long[] { 24*60*60*1000 });
@@ -223,16 +228,26 @@ public class StatisticsManager implements Service {
return buf.toString();
}
+ /* report the same data for tx and rx, for enhanced anonymity */
+ private void includeAverageThroughput(Properties stats) {
+ RateStat sendRate = _context.statManager().getRate("bw.sendRate");
+ RateStat recvRate = _context.statManager().getRate("bw.recvRate");
+ if (sendRate == null || recvRate == null)
+ return;
+ Rate s = sendRate.getRate(60*60*1000);
+ Rate r = recvRate.getRate(60*60*1000);
+ if (s == null || r == null)
+ return;
+ double speed = (s.getAverageValue() + r.getAverageValue()) / 2;
+ double max = Math.max(s.getExtremeAverageValue(), r.getExtremeAverageValue());
+ String str = num(speed) + ';' + num(max) + ";0;0;";
+ stats.setProperty("stat_bandwidthSendBps.60m", str);
+ stats.setProperty("stat_bandwidthReceiveBps.60m", str);
+ }
+
private void includeThroughput(Properties stats) {
RateStat sendRate = _context.statManager().getRate("bw.sendRate");
if (sendRate != null) {
- /****
- if (_context.router().getUptime() > 5*60*1000) {
- Rate r = sendRate.getRate(5*60*1000);
- if (r != null)
- stats.setProperty("stat_bandwidthSendBps.5m", num(r.getAverageValue()) + ';' + num(r.getExtremeAverageValue()) + ";0;0;");
- }
- ****/
if (_context.router().getUptime() > 60*60*1000) {
Rate r = sendRate.getRate(60*60*1000);
if (r != null)
@@ -242,13 +257,6 @@ public class StatisticsManager implements Service {
RateStat recvRate = _context.statManager().getRate("bw.recvRate");
if (recvRate != null) {
- /****
- if (_context.router().getUptime() > 5*60*1000) {
- Rate r = recvRate.getRate(5*60*1000);
- if (r != null)
- stats.setProperty("stat_bandwidthReceiveBps.5m", num(r.getAverageValue()) + ';' + num(r.getExtremeAverageValue()) + ";0;0;");
- }
- ****/
if (_context.router().getUptime() > 60*60*1000) {
Rate r = recvRate.getRate(60*60*1000);
if (r != null)
diff --git a/router/java/src/net/i2p/router/networkdb/kademlia/FloodOnlySearchJob.java b/router/java/src/net/i2p/router/networkdb/kademlia/FloodOnlySearchJob.java
index e5b5e962d..b6fec178c 100644
--- a/router/java/src/net/i2p/router/networkdb/kademlia/FloodOnlySearchJob.java
+++ b/router/java/src/net/i2p/router/networkdb/kademlia/FloodOnlySearchJob.java
@@ -100,8 +100,10 @@ class FloodOnlySearchJob extends FloodSearchJob {
if (floodfillPeers.size() <= 3)
_shouldProcessDSRM = true;
if (floodfillPeers.size() <= 0) {
- if (_log.shouldLog(Log.ERROR))
- _log.error("Running netDb searches against the floodfill peers, but we don't know any");
+ // ask anybody, they may not return the answer but they will return a few ff peers we can go look up,
+ // so this situation should be temporary
+ if (_log.shouldLog(Log.WARN))
+ _log.warn("Running netDb searches against the floodfill peers, but we don't know any");
floodfillPeers = new ArrayList(_facade.getAllRouters());
if (floodfillPeers.size() <= 0) {
if (_log.shouldLog(Log.ERROR))
diff --git a/router/java/src/net/i2p/router/networkdb/kademlia/SingleLookupJob.java b/router/java/src/net/i2p/router/networkdb/kademlia/SingleLookupJob.java
index 8c40d117b..24c0350f9 100644
--- a/router/java/src/net/i2p/router/networkdb/kademlia/SingleLookupJob.java
+++ b/router/java/src/net/i2p/router/networkdb/kademlia/SingleLookupJob.java
@@ -8,6 +8,12 @@ import net.i2p.util.Log;
/**
* Ask the peer who sent us the DSRM for the RouterInfos.
+ *
+ * If we have the routerInfo already, try to refetch it from that router itself,
+ * if we aren't already connected to that router,
+ * which will help us establish that router as a good floodfill and speed our
+ * integration into the network.
+ *
* A simple version of SearchReplyJob in SearchJob.java.
* Skip the profile updates - this should be rare.
*
@@ -28,6 +34,8 @@ class SingleLookupJob extends JobImpl {
continue;
if (getContext().netDb().lookupRouterInfoLocally(peer) == null)
getContext().jobQueue().addJob(new SingleSearchJob(getContext(), peer, from));
+ else if (!getContext().commSystem().isEstablished(peer))
+ getContext().jobQueue().addJob(new SingleSearchJob(getContext(), peer, peer));
}
}
public String getName() { return "NetDb process DSRM"; }
diff --git a/router/java/src/net/i2p/router/transport/FIFOBandwidthRefiller.java b/router/java/src/net/i2p/router/transport/FIFOBandwidthRefiller.java
index 693df45b1..b24d79a11 100644
--- a/router/java/src/net/i2p/router/transport/FIFOBandwidthRefiller.java
+++ b/router/java/src/net/i2p/router/transport/FIFOBandwidthRefiller.java
@@ -34,8 +34,14 @@ public class FIFOBandwidthRefiller implements Runnable {
//public static final String PROP_REPLENISH_FREQUENCY = "i2np.bandwidth.replenishFrequencyMs";
// no longer allow unlimited bandwidth - the user must specify a value, else use defaults below (KBps)
- public static final int DEFAULT_INBOUND_BANDWIDTH = 64;
- public static final int DEFAULT_OUTBOUND_BANDWIDTH = 32;
+ public static final int DEFAULT_INBOUND_BANDWIDTH = 96;
+ /**
+ * Caution, do not make DEFAULT_OUTBOUND_BANDWIDTH * DEFAULT_SHARE_PCT > 32
+ * without thinking about the implications (default connection limits, for example)
+ * of moving the default bandwidth class from L to M, or maybe
+ * adjusting bandwidth class boundaries.
+ */
+ public static final int DEFAULT_OUTBOUND_BANDWIDTH = 40;
public static final int DEFAULT_INBOUND_BURST_BANDWIDTH = 80;
public static final int DEFAULT_OUTBOUND_BURST_BANDWIDTH = 40;