merge of '5c7631359fea237f6aa916acd4f76a8a00d519fb'

and '88d299913d4aeb0ef7e8adabb5c39255e9cca0d2'
This commit is contained in:
dev
2008-06-22 14:08:06 +00:00
17 changed files with 240 additions and 84 deletions

View File

@@ -1,59 +1,115 @@
package net.i2p.router.web; package net.i2p.router.web;
import java.util.Collection;
import java.util.HashMap; import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.Properties;
import java.util.Set;
import net.i2p.data.DataFormatException; import net.i2p.data.DataFormatException;
import net.i2p.router.startup.ClientAppConfig;
import net.i2p.router.startup.LoadClientAppsJob;
import net.i2p.util.Log; import net.i2p.util.Log;
import org.mortbay.http.HttpListener;
import org.mortbay.jetty.Server;
/** /**
* * Saves changes to clients.config or webapps.config
*/ */
public class ConfigClientsHandler extends FormHandler { public class ConfigClientsHandler extends FormHandler {
private Log _log; private Log _log;
private Map _settings; private Map _settings;
private boolean _shouldSave;
public ConfigClientsHandler() { public ConfigClientsHandler() {
_shouldSave = false; _log = ContextHelper.getContext(null).logManager().getLog(ConfigClientsHandler.class);
} }
protected void processForm() { protected void processForm() {
if (_shouldSave) { if (_action.startsWith("Save Client")) {
saveChanges(); saveClientChanges();
} else if (_action.startsWith("Save WebApp")) {
saveWebAppChanges();
} else if (_action.startsWith("Start ")) {
String app = _action.substring(6);
int appnum = -1;
try {
appnum = Integer.parseInt(app);
} catch (NumberFormatException nfe) {}
if (appnum >= 0)
startClient(appnum);
else
startWebApp(app);
} else { } else {
// noop addFormError("Unsupported " + _action);
addFormError("Unimplemented");
} }
} }
public void setShouldsave(String moo) {
if ( (moo != null) && (moo.equals("Save changes")) )
_shouldSave = true;
}
public void setSettings(Map settings) { _settings = new HashMap(settings); } public void setSettings(Map settings) { _settings = new HashMap(settings); }
/** private void saveClientChanges() {
* The user made changes to the network config and wants to save them, so List clients = ClientAppConfig.getClientApps(_context);
* lets go ahead and do so. for (int cur = 0; cur < clients.size(); cur++) {
* ClientAppConfig ca = (ClientAppConfig) clients.get(cur);
*/ Object val = _settings.get(cur + ".enabled");
private void saveChanges() { if (! "webConsole".equals(ca.clientName))
_log = _context.logManager().getLog(ConfigClientsHandler.class); ca.disabled = val == null;
boolean saveRequired = false;
int updated = 0;
int index = 0;
if (updated > 0)
addFormNotice("Updated settings");
if (saveRequired) {
boolean saved = _context.router().saveConfig();
if (saved)
addFormNotice("Exploratory tunnel configuration saved successfully");
else
addFormNotice("Error saving the configuration (applied but not saved) - please see the error logs");
} }
ClientAppConfig.writeClientAppConfig(_context, clients);
addFormNotice("Client configuration saved successfully - restart required to take effect");
}
private void startClient(int i) {
List clients = ClientAppConfig.getClientApps(_context);
if (i >= clients.size()) {
addFormError("Bad client index");
return;
}
ClientAppConfig ca = (ClientAppConfig) clients.get(i);
LoadClientAppsJob.runClient(ca.className, ca.clientName, LoadClientAppsJob.parseArgs(ca.args), _log);
addFormNotice("Client " + ca.clientName + " started");
}
private void saveWebAppChanges() {
Properties props = RouterConsoleRunner.webAppProperties();
Set keys = props.keySet();
int cur = 0;
for (Iterator iter = keys.iterator(); iter.hasNext(); ) {
String name = (String)iter.next();
if (! (name.startsWith(RouterConsoleRunner.PREFIX) && name.endsWith(RouterConsoleRunner.ENABLED)))
continue;
String app = name.substring(RouterConsoleRunner.PREFIX.length(), name.lastIndexOf(RouterConsoleRunner.ENABLED));
Object val = _settings.get(app + ".enabled");
if (! RouterConsoleRunner.ROUTERCONSOLE.equals(app))
props.setProperty(name, "" + (val != null));
}
RouterConsoleRunner.storeWebAppProperties(props);
addFormNotice("WebApp configuration saved successfully - restart required to take effect");
}
// Big hack for the moment, not using properties for directory and port
// Go through all the Jetty servers, find the one serving port 7657,
// requested and add the .war to that one
private void startWebApp(String app) {
Collection c = Server.getHttpServers();
for (int i = 0; i < c.size(); i++) {
Server s = (Server) c.toArray()[i];
HttpListener[] hl = s.getListeners();
for (int j = 0; j < hl.length; j++) {
if (hl[j].getPort() == 7657) {
try {
s.addWebApplication("/"+ app, "./webapps/" + app + ".war").start();
// no passwords... initialize(wac);
addFormNotice("WebApp " + app + " started");
} catch (Exception ioe) {
addFormError("Failed to start " + app + " " + ioe);
}
return;
}
}
}
addFormError("Failed to find server");
} }
} }

View File

@@ -26,16 +26,15 @@ public class ConfigClientsHelper {
public ConfigClientsHelper() {} public ConfigClientsHelper() {}
public String getForm1() { public String getForm1() {
StringBuffer buf = new StringBuffer(1024); StringBuffer buf = new StringBuffer(1024);
buf.append("<table border=\"1\">\n"); buf.append("<table border=\"1\">\n");
buf.append("<tr><td>Client</td><td>Enabled?</td><td>Class and arguments</td></tr>\n"); buf.append("<tr><td>Client</td><td>Run at Startup?</td><td>Start Now</td><td>Class and arguments</td></tr>\n");
List clients = ClientAppConfig.getClientApps(_context); List clients = ClientAppConfig.getClientApps(_context);
for (int cur = 0; cur < clients.size(); cur++) { for (int cur = 0; cur < clients.size(); cur++) {
ClientAppConfig ca = (ClientAppConfig) clients.get(cur); ClientAppConfig ca = (ClientAppConfig) clients.get(cur);
renderForm(buf, cur, ca.clientName, false, !ca.disabled, "webConsole".equals(ca.clientName), ca.className + " " + ca.args); renderForm(buf, ""+cur, ca.clientName, false, !ca.disabled, "webConsole".equals(ca.clientName), ca.className + " " + ca.args);
} }
buf.append("</table>\n"); buf.append("</table>\n");
@@ -45,24 +44,22 @@ public class ConfigClientsHelper {
public String getForm2() { public String getForm2() {
StringBuffer buf = new StringBuffer(1024); StringBuffer buf = new StringBuffer(1024);
buf.append("<table border=\"1\">\n"); buf.append("<table border=\"1\">\n");
buf.append("<tr><td>WebApp</td><td>Enabled?</td><td>Description</td></tr>\n"); buf.append("<tr><td>WebApp</td><td>Run at Startup?</td><td>Start Now</td><td>Description</td></tr>\n");
Properties props = RouterConsoleRunner.webAppProperties(); Properties props = RouterConsoleRunner.webAppProperties();
Set keys = new TreeSet(props.keySet()); Set keys = new TreeSet(props.keySet());
int cur = 0;
for (Iterator iter = keys.iterator(); iter.hasNext(); ) { for (Iterator iter = keys.iterator(); iter.hasNext(); ) {
String name = (String)iter.next(); String name = (String)iter.next();
if (name.startsWith(RouterConsoleRunner.PREFIX) && name.endsWith(RouterConsoleRunner.ENABLED)) { if (name.startsWith(RouterConsoleRunner.PREFIX) && name.endsWith(RouterConsoleRunner.ENABLED)) {
String app = name.substring(8, name.lastIndexOf(RouterConsoleRunner.ENABLED)); String app = name.substring(RouterConsoleRunner.PREFIX.length(), name.lastIndexOf(RouterConsoleRunner.ENABLED));
String val = props.getProperty(name); String val = props.getProperty(name);
renderForm(buf, cur, app, !"addressbook".equals(app), "true".equals(val), RouterConsoleRunner.ROUTERCONSOLE.equals(app), app + ".war"); renderForm(buf, app, app, !"addressbook".equals(app), "true".equals(val), RouterConsoleRunner.ROUTERCONSOLE.equals(app), app + ".war");
cur++;
} }
} }
buf.append("</table>\n"); buf.append("</table>\n");
return buf.toString(); return buf.toString();
} }
private void renderForm(StringBuffer buf, int index, String name, boolean urlify, boolean enabled, boolean ro, String desc) { private void renderForm(StringBuffer buf, String index, String name, boolean urlify, boolean enabled, boolean ro, String desc) {
buf.append("<tr><td>"); buf.append("<tr><td>");
if (urlify && enabled) { if (urlify && enabled) {
String link = "/"; String link = "/";
@@ -72,12 +69,16 @@ public class ConfigClientsHelper {
} else { } else {
buf.append(name); buf.append(name);
} }
buf.append("</td><td align=\"center\"><input type=\"checkbox\" name=\"enable\" value=\"").append(index).append(".enabled\" "); buf.append("</td><td align=\"center\"><input type=\"checkbox\" name=\"").append(index).append(".enabled\" value=\"true\" ");
if (enabled) { if (enabled) {
buf.append("checked=\"true\" "); buf.append("checked=\"true\" ");
if (ro) if (ro)
buf.append("disabled=\"true\" "); buf.append("disabled=\"true\" ");
} }
buf.append("/><td>").append(desc).append("</td></tr>\n"); buf.append("/></td><td>&nbsp");
if (!enabled) {
buf.append("<button type=\"submit\" name=\"action\" value=\"Start ").append(index).append("\" />Start</button>");
}
buf.append("&nbsp</td><td>").append(desc).append("</td></tr>\n");
} }
} }

View File

@@ -10,6 +10,7 @@ import java.util.Set;
import net.i2p.data.DataHelper; import net.i2p.data.DataHelper;
import net.i2p.data.Destination; import net.i2p.data.Destination;
import net.i2p.data.LeaseSet; import net.i2p.data.LeaseSet;
import net.i2p.data.RouterAddress;
import net.i2p.stat.Rate; import net.i2p.stat.Rate;
import net.i2p.stat.RateStat; import net.i2p.stat.RateStat;
import net.i2p.router.CommSystemFacade; import net.i2p.router.CommSystemFacade;
@@ -17,6 +18,7 @@ import net.i2p.router.Router;
import net.i2p.router.RouterContext; import net.i2p.router.RouterContext;
import net.i2p.router.RouterVersion; import net.i2p.router.RouterVersion;
import net.i2p.router.TunnelPoolSettings; import net.i2p.router.TunnelPoolSettings;
import net.i2p.router.transport.ntcp.NTCPAddress;
/** /**
* Simple helper to query the appropriate router for data necessary to render * Simple helper to query the appropriate router for data necessary to render
@@ -120,7 +122,10 @@ public class SummaryHelper {
int status = _context.commSystem().getReachabilityStatus(); int status = _context.commSystem().getReachabilityStatus();
switch (status) { switch (status) {
case CommSystemFacade.STATUS_OK: case CommSystemFacade.STATUS_OK:
return "OK"; RouterAddress ra = _context.router().getRouterInfo().getTargetAddress("NTCP");
if (ra == null || (new NTCPAddress(ra)).isPubliclyRoutable())
return "OK";
return "ERR-Private TCP Address";
case CommSystemFacade.STATUS_DIFFERENT: case CommSystemFacade.STATUS_DIFFERENT:
return "ERR-SymmetricNAT"; return "ERR-SymmetricNAT";
case CommSystemFacade.STATUS_REJECT_UNSOLICITED: case CommSystemFacade.STATUS_REJECT_UNSOLICITED:
@@ -130,6 +135,8 @@ public class SummaryHelper {
return "WARN-Firewalled and Fast"; return "WARN-Firewalled and Fast";
else else
return "Firewalled"; return "Firewalled";
case CommSystemFacade.STATUS_HOSED:
return "ERR-UDP Port In Use - Set i2np.udp.internalPort=xxxx in advanced config and restart";
case CommSystemFacade.STATUS_UNKNOWN: // fallthrough case CommSystemFacade.STATUS_UNKNOWN: // fallthrough
default: default:
return "Testing"; return "Testing";
@@ -512,6 +519,28 @@ public class SummaryHelper {
return String.valueOf(_context.tunnelManager().getInboundBuildQueueSize()); return String.valueOf(_context.tunnelManager().getInboundBuildQueueSize());
} }
public String getPRNGStatus() {
Rate r = _context.statManager().getRate("prng.bufferWaitTime").getRate(60*1000);
int use = (int) r.getLastEventCount();
int i = (int) (r.getAverageValue() + 0.5);
if (i <= 0) {
r = _context.statManager().getRate("prng.bufferWaitTime").getRate(10*60*1000);
i = (int) (r.getAverageValue() + 0.5);
}
String rv = i + "/";
r = _context.statManager().getRate("prng.bufferFillTime").getRate(60*1000);
i = (int) (r.getAverageValue() + 0.5);
if (i <= 0) {
r = _context.statManager().getRate("prng.bufferFillTime").getRate(10*60*1000);
i = (int) (r.getAverageValue() + 0.5);
}
rv = rv + i + "ms";
// margin == fill time / use time
if (use > 0 && i > 0)
rv = rv + ' ' + (60*1000 / (use * i)) + 'x';
return rv;
}
public boolean updateAvailable() { public boolean updateAvailable() {
return NewsFetcher.getInstance(_context).updateAvailable(); return NewsFetcher.getInstance(_context).updateAvailable();
} }

View File

@@ -18,7 +18,6 @@
<jsp:useBean class="net.i2p.router.web.ConfigClientsHandler" id="formhandler" scope="request" /> <jsp:useBean class="net.i2p.router.web.ConfigClientsHandler" id="formhandler" scope="request" />
<jsp:setProperty name="formhandler" property="contextId" value="<%=(String)session.getAttribute("i2p.contextId")%>" /> <jsp:setProperty name="formhandler" property="contextId" value="<%=(String)session.getAttribute("i2p.contextId")%>" />
<jsp:setProperty name="formhandler" property="shouldsave" value="<%=request.getParameter("shouldsave")%>" />
<jsp:setProperty name="formhandler" property="action" value="<%=request.getParameter("action")%>" /> <jsp:setProperty name="formhandler" property="action" value="<%=request.getParameter("action")%>" />
<jsp:setProperty name="formhandler" property="nonce" value="<%=request.getParameter("nonce")%>" /> <jsp:setProperty name="formhandler" property="nonce" value="<%=request.getParameter("nonce")%>" />
<jsp:setProperty name="formhandler" property="settings" value="<%=request.getParameterMap()%>" /> <jsp:setProperty name="formhandler" property="settings" value="<%=request.getParameterMap()%>" />
@@ -30,7 +29,6 @@
if (prev != null) System.setProperty("net.i2p.router.web.ConfigClientsHandler.noncePrev", prev); if (prev != null) System.setProperty("net.i2p.router.web.ConfigClientsHandler.noncePrev", prev);
System.setProperty("net.i2p.router.web.ConfigClientsHandler.nonce", new java.util.Random().nextLong()+""); %> System.setProperty("net.i2p.router.web.ConfigClientsHandler.nonce", new java.util.Random().nextLong()+""); %>
<input type="hidden" name="nonce" value="<%=System.getProperty("net.i2p.router.web.ConfigClientsHandler.nonce")%>" /> <input type="hidden" name="nonce" value="<%=System.getProperty("net.i2p.router.web.ConfigClientsHandler.nonce")%>" />
<input type="hidden" name="action" value="blah" />
<h3>Client Configuration</h3> <h3>Client Configuration</h3>
<p> <p>
The Java clients listed below are started by the router and run in the same JVM. The Java clients listed below are started by the router and run in the same JVM.
@@ -39,7 +37,7 @@
</p><p> </p><p>
<input type="submit" name="action" value="Save Client Configuration" /> <input type="submit" name="action" value="Save Client Configuration" />
</p><p> </p><p>
<i>All changes require restart to take effect. For other changes edit the clients.config file.</i> <i>All changes require restart to take effect. To change other client options, edit the clients.config file.</i>
</p> </p>
<hr /> <hr />
<h3>WebApp Configuration</h3> <h3>WebApp Configuration</h3>
@@ -50,11 +48,15 @@
front-ends to another client or application which must be separately enabled (e.g. susidns, i2ptunnel), front-ends to another client or application which must be separately enabled (e.g. susidns, i2ptunnel),
or have no web interface at all (e.g. addressbook). or have no web interface at all (e.g. addressbook).
</p><p> </p><p>
A web app may also be disabled by removing the .war file from the webapps directory;
however the .war file and web app will reappear when you update your router to a newer version,
so disabling the web app here is the preferred method.
</p><p>
<jsp:getProperty name="clientshelper" property="form2" /> <jsp:getProperty name="clientshelper" property="form2" />
</p><p> </p><p>
<input type="submit" name="action" value="Save WebApp Configuration" /> <input type="submit" name="action" value="Save WebApp Configuration" />
</p><p> </p><p>
<i>All changes require restart to take effect. For other changes edit the webapps.config file.</i> <i>All changes require restart to take effect. To change other webapp options, edit the webapps.config file.</i>
</p> </p>
</form> </form>
</div> </div>

View File

@@ -4,10 +4,10 @@
%>Service | <% } else { %><a href="configservice.jsp">Service</a> | <% } %>Service | <% } else { %><a href="configservice.jsp">Service</a> | <% }
if (request.getRequestURI().indexOf("configupdate.jsp") != -1) { if (request.getRequestURI().indexOf("configupdate.jsp") != -1) {
%>Update | <% } else { %><a href="configupdate.jsp">Update</a> | <% } %>Update | <% } else { %><a href="configupdate.jsp">Update</a> | <% }
if (request.getRequestURI().indexOf("configclients.jsp") != -1) {
%>Clients | <% } else { %><a href="configclients.jsp">Clients</a> | <% }
if (request.getRequestURI().indexOf("configtunnels.jsp") != -1) { if (request.getRequestURI().indexOf("configtunnels.jsp") != -1) {
%>Tunnels | <% } else { %><a href="configtunnels.jsp">Tunnels</a> | <% } %>Tunnels | <% } else { %><a href="configtunnels.jsp">Tunnels</a> | <% }
if (request.getRequestURI().indexOf("configclients.jsp") != -1) {
%>Clients | <% } else { %><a href="configclients.jsp">Clients</a> | <% }
if (request.getRequestURI().indexOf("configlogging.jsp") != -1) { if (request.getRequestURI().indexOf("configlogging.jsp") != -1) {
%>Logging | <% } else { %><a href="configlogging.jsp">Logging</a> | <% } %>Logging | <% } else { %><a href="configlogging.jsp">Logging</a> | <% }
if (request.getRequestURI().indexOf("configstats.jsp") != -1) { if (request.getRequestURI().indexOf("configstats.jsp") != -1) {

View File

@@ -95,6 +95,7 @@
<b>Message delay:</b> <jsp:getProperty name="helper" property="messageDelay" /><br /> <b>Message delay:</b> <jsp:getProperty name="helper" property="messageDelay" /><br />
<b>Tunnel lag:</b> <jsp:getProperty name="helper" property="tunnelLag" /><br /> <b>Tunnel lag:</b> <jsp:getProperty name="helper" property="tunnelLag" /><br />
<b>Handle backlog:</b> <jsp:getProperty name="helper" property="inboundBacklog" /><br /> <b>Handle backlog:</b> <jsp:getProperty name="helper" property="inboundBacklog" /><br />
<b>PRNG wait/fill:</b> <jsp:getProperty name="helper" property="PRNGStatus" /><br />
<b><jsp:getProperty name="helper" property="tunnelStatus" /></b><br /> <b><jsp:getProperty name="helper" property="tunnelStatus" /></b><br />
<hr /> <hr />

View File

@@ -2,6 +2,8 @@ package gnu.crypto.prng;
import java.util.*; import java.util.*;
import net.i2p.I2PAppContext;
/** /**
* fortuna instance that tries to avoid blocking if at all possible by using separate * fortuna instance that tries to avoid blocking if at all possible by using separate
* filled buffer segments rather than one buffer (and blocking when that buffer's data * filled buffer segments rather than one buffer (and blocking when that buffer's data
@@ -13,16 +15,20 @@ public class AsyncFortunaStandalone extends FortunaStandalone implements Runnabl
private final byte asyncBuffers[][] = new byte[BUFFERS][BUFSIZE]; private final byte asyncBuffers[][] = new byte[BUFFERS][BUFSIZE];
private final int status[] = new int[BUFFERS]; private final int status[] = new int[BUFFERS];
private int nextBuf = 0; private int nextBuf = 0;
private I2PAppContext _context;
private static final int STATUS_NEED_FILL = 0; private static final int STATUS_NEED_FILL = 0;
private static final int STATUS_FILLING = 1; private static final int STATUS_FILLING = 1;
private static final int STATUS_FILLED = 2; private static final int STATUS_FILLED = 2;
private static final int STATUS_LIVE = 3; private static final int STATUS_LIVE = 3;
public AsyncFortunaStandalone() { public AsyncFortunaStandalone(I2PAppContext context) {
super(); super();
for (int i = 0; i < BUFFERS; i++) for (int i = 0; i < BUFFERS; i++)
status[i] = STATUS_NEED_FILL; status[i] = STATUS_NEED_FILL;
_context = context;
context.statManager().createRateStat("prng.bufferWaitTime", "", "Encryption", new long[] { 60*1000, 10*60*1000, 60*60*1000 } );
context.statManager().createRateStat("prng.bufferFillTime", "", "Encryption", new long[] { 60*1000, 10*60*1000, 60*60*1000 } );
} }
public void startup() { public void startup() {
@@ -61,6 +67,7 @@ public class AsyncFortunaStandalone extends FortunaStandalone implements Runnabl
} catch (InterruptedException ie) {} } catch (InterruptedException ie) {}
waited = System.currentTimeMillis()-before; waited = System.currentTimeMillis()-before;
} }
_context.statManager().addRateData("prng.bufferWaitTime", waited, 0);
if (waited > 10*1000) if (waited > 10*1000)
System.out.println(Thread.currentThread().getName() + ": Took " + waited System.out.println(Thread.currentThread().getName() + ": Took " + waited
+ "ms for a full PRNG buffer to be found"); + "ms for a full PRNG buffer to be found");
@@ -108,6 +115,7 @@ public class AsyncFortunaStandalone extends FortunaStandalone implements Runnabl
//System.out.println(Thread.currentThread().getName() + ": Prng buffer " + toFill + " filled after " + (after-before)); //System.out.println(Thread.currentThread().getName() + ": Prng buffer " + toFill + " filled after " + (after-before));
asyncBuffers.notifyAll(); asyncBuffers.notifyAll();
} }
_context.statManager().addRateData("prng.bufferFillTime", after - before, 0);
Thread.yield(); Thread.yield();
long waitTime = (after-before)*5; long waitTime = (after-before)*5;
if (waitTime <= 0) // somehow postman saw waitTime show up as negative if (waitTime <= 0) // somehow postman saw waitTime show up as negative
@@ -147,7 +155,7 @@ public class AsyncFortunaStandalone extends FortunaStandalone implements Runnabl
public static void main(String args[]) { public static void main(String args[]) {
try { try {
AsyncFortunaStandalone rand = new AsyncFortunaStandalone(); AsyncFortunaStandalone rand = new AsyncFortunaStandalone(null); // Will cause NPEs above; fix this if you want to test! Sorry...
byte seed[] = new byte[1024]; byte seed[] = new byte[1024];
rand.seed(seed); rand.seed(seed);

View File

@@ -37,13 +37,15 @@ public class StatManager {
public static final String PROP_STAT_REQUIRED = "stat.required"; public static final String PROP_STAT_REQUIRED = "stat.required";
/** /**
* These are all the stats published in netDb, plus those required for the operation of * These are all the stats published in netDb, plus those required for the operation of
* the router (many in RouterThrottleImpl), plus those that are on graphs.jsp by default. * the router (many in RouterThrottleImpl), plus those that are on graphs.jsp by default,
* plus those used on the summary bar (SummaryHelper.java).
* Wildcard ('*') allowed at end of stat only. * Wildcard ('*') allowed at end of stat only.
* Ignore all the rest of the stats unless stat.full=true. * Ignore all the rest of the stats unless stat.full=true.
*/ */
public static final String DEFAULT_STAT_REQUIRED = public static final String DEFAULT_STAT_REQUIRED =
"bw.recvRate,bw.sendBps,bw.sendRate,client.sendAckTime,clock.skew,crypto.elGamal.encrypt," + "bw.recvRate,bw.sendBps,bw.sendRate,client.sendAckTime,clock.skew,crypto.elGamal.encrypt," +
"jobQueue.jobLag,netDb.successTime,router.fastPeers," + "jobQueue.jobLag,netDb.successTime,router.fastPeers," +
"prng.bufferFillTime,prng.bufferWaitTime," +
"transport.receiveMessageSize,transport.sendMessageSize,transport.sendProcessingTime," + "transport.receiveMessageSize,transport.sendMessageSize,transport.sendProcessingTime," +
"tunnel.acceptLoad,tunnel.buildRequestTime,tunnel.rejectOverloaded,tunnel.rejectTimeout" + "tunnel.acceptLoad,tunnel.buildRequestTime,tunnel.rejectOverloaded,tunnel.rejectTimeout" +
"tunnel.buildClientExpire,tunnel.buildClientReject,tunnel.buildClientSuccess," + "tunnel.buildClientExpire,tunnel.buildClientReject,tunnel.buildClientSuccess," +

View File

@@ -32,7 +32,7 @@ public class FortunaRandomSource extends RandomSource implements EntropyHarveste
public FortunaRandomSource(I2PAppContext context) { public FortunaRandomSource(I2PAppContext context) {
super(context); super(context);
_fortuna = new AsyncFortunaStandalone(); _fortuna = new AsyncFortunaStandalone(context);
byte seed[] = new byte[1024]; byte seed[] = new byte[1024];
if (initSeed(seed)) { if (initSeed(seed)) {
_fortuna.seed(seed); _fortuna.seed(seed);

View File

@@ -1,3 +1,17 @@
2008-06-23 zzz
* configclients.jsp: Add start button for clients and webapps.
* PRNG: Add two stats
* Summary bar:
- Display Warning for TCP private IP address
- Display PRNG stats
* OutNetMessage: Change cache logging from WARN to INFO
2008-06-17 zzz
* Comm System: Add new STATUS_HOSED for use when UDP bind fails
* Summary bar: Display helpful errror message when UDP bind fails
* UDP: Don't bid when UDP bind fails
* configclients.jsp: Implement saves for clients and webapps.
2008-06-16 zzz 2008-06-16 zzz
* UDP: Prevent 100% CPU when UDP bind fails; * UDP: Prevent 100% CPU when UDP bind fails;
change bind fail message from ERROR to CRIT change bind fail message from ERROR to CRIT
@@ -12,7 +26,6 @@
* configclients.jsp: New. For both clients and webapps. * configclients.jsp: New. For both clients and webapps.
Saves are not yet implemented. Saves are not yet implemented.
2008-06-10 zzz 2008-06-10 zzz
* Floodfill: Add new FloodfillMonitorJob, which tracks active * Floodfill: Add new FloodfillMonitorJob, which tracks active
floodfills, and automatically enables/disables floodfill on floodfills, and automatically enables/disables floodfill on

View File

@@ -61,6 +61,9 @@ public abstract class CommSystemFacade implements Service {
*/ */
public void notifyReplaceAddress(RouterAddress UDPAddr) {} public void notifyReplaceAddress(RouterAddress UDPAddr) {}
/** /**
* These must be increasing in "badness" (see TransportManager.java),
* but UNKNOWN must be last.
*
* We are able to receive unsolicited connections * We are able to receive unsolicited connections
*/ */
public static final short STATUS_OK = 0; public static final short STATUS_OK = 0;
@@ -75,10 +78,14 @@ public abstract class CommSystemFacade implements Service {
* cannot receive unsolicited connections * cannot receive unsolicited connections
*/ */
public static final short STATUS_REJECT_UNSOLICITED = 2; public static final short STATUS_REJECT_UNSOLICITED = 2;
/**
* Our detection system is broken (SSU bind port failed)
*/
public static final short STATUS_HOSED = 3;
/** /**
* Our reachability is unknown * Our reachability is unknown
*/ */
public static final short STATUS_UNKNOWN = 3; public static final short STATUS_UNKNOWN = 4;
} }

View File

@@ -17,7 +17,7 @@ import net.i2p.CoreVersion;
public class RouterVersion { public class RouterVersion {
public final static String ID = "$Revision: 1.548 $ $Date: 2008-06-07 23:00:00 $"; public final static String ID = "$Revision: 1.548 $ $Date: 2008-06-07 23:00:00 $";
public final static String VERSION = "0.6.2"; public final static String VERSION = "0.6.2";
public final static long BUILD = 3; public final static long BUILD = 5;
public static void main(String args[]) { public static void main(String args[]) {
System.out.println("I2P Router version: " + VERSION + "-" + BUILD); System.out.println("I2P Router version: " + VERSION + "-" + BUILD);
System.out.println("Router ID: " + RouterVersion.ID); System.out.println("Router ID: " + RouterVersion.ID);

View File

@@ -247,8 +247,8 @@ public class OutboundClientMessageOneShotJob extends JobImpl {
return null; return null;
//} //}
} else { } else {
if (_log.shouldLog(Log.WARN)) if (_log.shouldLog(Log.INFO))
_log.warn("Expired from cache - reply leaseset for " + _toString); _log.info("Expired from cache - reply leaseset for " + _toString);
// will get overwritten below // will get overwritten below
// _leaseSetCache.remove(hashPair()); // _leaseSetCache.remove(hashPair());
} }
@@ -256,8 +256,8 @@ public class OutboundClientMessageOneShotJob extends JobImpl {
} }
_leaseSetCache.put(hashPair(), newLS); _leaseSetCache.put(hashPair(), newLS);
} }
if (_log.shouldLog(Log.WARN)) if (_log.shouldLog(Log.INFO))
_log.warn("Added to cache - reply leaseset for " + _toString); _log.info("Added to cache - reply leaseset for " + _toString);
return newLS; return newLS;
} }
@@ -329,8 +329,8 @@ public class OutboundClientMessageOneShotJob extends JobImpl {
} }
} }
} }
if (_log.shouldLog(Log.WARN)) if (_log.shouldLog(Log.INFO))
_log.warn("Expired from cache - lease for " + _toString); _log.info("Expired from cache - lease for " + _toString);
_leaseCache.remove(_to); _leaseCache.remove(_to);
} }
} }
@@ -340,8 +340,8 @@ public class OutboundClientMessageOneShotJob extends JobImpl {
for (int i = 0; i < _leaseSet.getLeaseCount(); i++) { for (int i = 0; i < _leaseSet.getLeaseCount(); i++) {
Lease lease = _leaseSet.getLease(i); Lease lease = _leaseSet.getLease(i);
if (lease.isExpired(Router.CLOCK_FUDGE_FACTOR)) { if (lease.isExpired(Router.CLOCK_FUDGE_FACTOR)) {
if (_log.shouldLog(Log.WARN)) if (_log.shouldLog(Log.INFO))
_log.warn(getJobId() + ": getNextLease() - expired lease! - " + lease + " for " + _toString); _log.info(getJobId() + ": getNextLease() - expired lease! - " + lease + " for " + _toString);
continue; continue;
} else { } else {
leases.add(lease); leases.add(lease);
@@ -403,8 +403,8 @@ public class OutboundClientMessageOneShotJob extends JobImpl {
synchronized (_leaseCache) { synchronized (_leaseCache) {
_leaseCache.put(hashPair(), _lease); _leaseCache.put(hashPair(), _lease);
} }
if (_log.shouldLog(Log.WARN)) if (_log.shouldLog(Log.INFO))
_log.warn("Added to cache - lease for " + _toString); _log.info("Added to cache - lease for " + _toString);
return true; return true;
} }

View File

@@ -2,6 +2,7 @@ package net.i2p.router.startup;
import java.io.IOException; import java.io.IOException;
import java.io.File; import java.io.File;
import java.io.FileOutputStream;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
import java.util.Properties; import java.util.Properties;
@@ -22,6 +23,7 @@ public class ClientAppConfig {
private static final String PROP_CLIENT_CONFIG_FILENAME = "router.clientConfigFile"; private static final String PROP_CLIENT_CONFIG_FILENAME = "router.clientConfigFile";
private static final String DEFAULT_CLIENT_CONFIG_FILENAME = "clients.config"; private static final String DEFAULT_CLIENT_CONFIG_FILENAME = "clients.config";
private static final String PREFIX = "clientApp.";
// let's keep this really simple // let's keep this really simple
public String className; public String className;
@@ -63,14 +65,14 @@ public class ClientAppConfig {
List rv = new ArrayList(5); List rv = new ArrayList(5);
int i = 0; int i = 0;
while (true) { while (true) {
String className = clientApps.getProperty("clientApp."+i+".main"); String className = clientApps.getProperty(PREFIX + i + ".main");
if (className == null) if (className == null)
break; break;
String clientName = clientApps.getProperty("clientApp."+i+".name"); String clientName = clientApps.getProperty(PREFIX + i + ".name");
String args = clientApps.getProperty("clientApp."+i+".args"); String args = clientApps.getProperty(PREFIX + i + ".args");
String delayStr = clientApps.getProperty("clientApp." + i + ".delay"); String delayStr = clientApps.getProperty(PREFIX + i + ".delay");
String onBoot = clientApps.getProperty("clientApp." + i + ".onBoot"); String onBoot = clientApps.getProperty(PREFIX + i + ".onBoot");
String disabled = clientApps.getProperty("clientApp." + i + ".startOnLoad"); String disabled = clientApps.getProperty(PREFIX + i + ".startOnLoad");
i++; i++;
boolean dis = disabled != null && "false".equals(disabled); boolean dis = disabled != null && "false".equals(disabled);
@@ -87,5 +89,25 @@ public class ClientAppConfig {
return rv; return rv;
} }
public static void writeClientAppConfig(RouterContext ctx, List apps) {
String clientConfigFile = ctx.getProperty(PROP_CLIENT_CONFIG_FILENAME, DEFAULT_CLIENT_CONFIG_FILENAME);
FileOutputStream fos = null;
try {
fos = new FileOutputStream(clientConfigFile);
StringBuffer buf = new StringBuffer(2048);
for(int i = 0; i < apps.size(); i++) {
ClientAppConfig app = (ClientAppConfig) apps.get(i);
buf.append(PREFIX).append(i).append(".main=").append(app.className).append("\n");
buf.append(PREFIX).append(i).append(".name=").append(app.clientName).append("\n");
buf.append(PREFIX).append(i).append(".args=").append(app.args).append("\n");
buf.append(PREFIX).append(i).append(".delay=").append(app.delay / 1000).append("\n");
buf.append(PREFIX).append(i).append(".startOnLoad=").append(!app.disabled).append("\n");
}
fos.write(buf.toString().getBytes());
} catch (IOException ioe) {
} finally {
if (fos != null) try { fos.close(); } catch (IOException ioe) {}
}
}
} }

View File

@@ -15,7 +15,7 @@ import net.i2p.util.Log;
* it'll get queued up for starting 2 minutes later. * it'll get queued up for starting 2 minutes later.
* *
*/ */
class LoadClientAppsJob extends JobImpl { public class LoadClientAppsJob extends JobImpl {
private Log _log; private Log _log;
private static boolean _loaded = false; private static boolean _loaded = false;
@@ -36,7 +36,7 @@ class LoadClientAppsJob extends JobImpl {
String argVal[] = parseArgs(app.args); String argVal[] = parseArgs(app.args);
if (app.delay == 0) { if (app.delay == 0) {
// run this guy now // run this guy now
runClient(app.className, app.clientName, argVal); runClient(app.className, app.clientName, argVal, _log);
} else { } else {
// wait before firing it up // wait before firing it up
getContext().jobQueue().addJob(new DelayedRunClient(getContext(), app.className, app.clientName, argVal, app.delay)); getContext().jobQueue().addJob(new DelayedRunClient(getContext(), app.className, app.clientName, argVal, app.delay));
@@ -56,11 +56,11 @@ class LoadClientAppsJob extends JobImpl {
} }
public String getName() { return "Delayed client job"; } public String getName() { return "Delayed client job"; }
public void runJob() { public void runJob() {
runClient(_className, _clientName, _args); runClient(_className, _clientName, _args, _log);
} }
} }
static String[] parseArgs(String args) { public static String[] parseArgs(String args) {
List argList = new ArrayList(4); List argList = new ArrayList(4);
if (args != null) { if (args != null) {
char data[] = args.toCharArray(); char data[] = args.toCharArray();
@@ -109,9 +109,9 @@ class LoadClientAppsJob extends JobImpl {
return rv; return rv;
} }
private void runClient(String className, String clientName, String args[]) { public static void runClient(String className, String clientName, String args[], Log log) {
_log.info("Loading up the client application " + clientName + ": " + className + " " + args); log.info("Loading up the client application " + clientName + ": " + className + " " + args);
I2PThread t = new I2PThread(new RunApp(className, clientName, args)); I2PThread t = new I2PThread(new RunApp(className, clientName, args, log));
if (clientName == null) if (clientName == null)
clientName = className + " client"; clientName = className + " client";
t.setName(clientName); t.setName(clientName);
@@ -119,17 +119,19 @@ class LoadClientAppsJob extends JobImpl {
t.start(); t.start();
} }
private final class RunApp implements Runnable { private final static class RunApp implements Runnable {
private String _className; private String _className;
private String _appName; private String _appName;
private String _args[]; private String _args[];
public RunApp(String className, String appName, String args[]) { private Log _log;
public RunApp(String className, String appName, String args[], Log log) {
_className = className; _className = className;
_appName = appName; _appName = appName;
if (args == null) if (args == null)
_args = new String[0]; _args = new String[0];
else else
_args = args; _args = args;
_log = log;
} }
public void run() { public void run() {
try { try {

View File

@@ -5,6 +5,7 @@ import java.net.DatagramSocket;
import java.net.InetAddress; import java.net.InetAddress;
import java.net.SocketException; import java.net.SocketException;
import net.i2p.router.CommSystemFacade;
import net.i2p.router.RouterContext; import net.i2p.router.RouterContext;
import net.i2p.util.Log; import net.i2p.util.Log;
@@ -44,6 +45,7 @@ public class UDPEndpoint {
_sender.startup(); _sender.startup();
_receiver.startup(); _receiver.startup();
} catch (SocketException se) { } catch (SocketException se) {
_transport.setReachabilityStatus(CommSystemFacade.STATUS_HOSED);
_log.log(Log.CRIT, "Unable to bind on port " + _listenPort, se); _log.log(Log.CRIT, "Unable to bind on port " + _listenPort, se);
} }
} }

View File

@@ -858,6 +858,12 @@ public class UDPTransport extends TransportImpl implements TimedWeightedPriority
else else
return _fastBid; return _fastBid;
} else { } else {
// If we don't have a port, all is lost
if ( _reachabilityStatus == CommSystemFacade.STATUS_HOSED) {
markUnreachable(to);
return null;
}
// Validate his SSU address // Validate his SSU address
RouterAddress addr = toAddress.getTargetAddress(STYLE); RouterAddress addr = toAddress.getTargetAddress(STYLE);
if (addr == null) { if (addr == null) {
@@ -1870,6 +1876,7 @@ public class UDPTransport extends TransportImpl implements TimedWeightedPriority
buf.append(" </tr>\n"); buf.append(" </tr>\n");
buf.append("<tr><td colspan=\"15\" valign=\"top\" align=\"left\">"); buf.append("<tr><td colspan=\"15\" valign=\"top\" align=\"left\">");
long bytesTransmitted = _context.bandwidthLimiter().getTotalAllocatedOutboundBytes(); long bytesTransmitted = _context.bandwidthLimiter().getTotalAllocatedOutboundBytes();
// NPE here early
double averagePacketSize = _context.statManager().getRate("udp.sendPacketSize").getLifetimeAverageValue(); double averagePacketSize = _context.statManager().getRate("udp.sendPacketSize").getLifetimeAverageValue();
// lifetime value, not just the retransmitted packets of current connections // lifetime value, not just the retransmitted packets of current connections
resentTotal = (long)_context.statManager().getRate("udp.packetsRetransmitted").getLifetimeEventCount(); resentTotal = (long)_context.statManager().getRate("udp.packetsRetransmitted").getLifetimeEventCount();
@@ -2005,6 +2012,8 @@ public class UDPTransport extends TransportImpl implements TimedWeightedPriority
break; break;
case CommSystemFacade.STATUS_REJECT_UNSOLICITED: case CommSystemFacade.STATUS_REJECT_UNSOLICITED:
_context.statManager().addRateData("udp.statusReject", 1, 0); _context.statManager().addRateData("udp.statusReject", 1, 0);
// fall through...
case CommSystemFacade.STATUS_HOSED:
_reachabilityStatus = status; _reachabilityStatus = status;
_reachabilityStatusLastUpdated = now; _reachabilityStatusLastUpdated = now;
break; break;
@@ -2021,6 +2030,8 @@ public class UDPTransport extends TransportImpl implements TimedWeightedPriority
break; break;
} }
if ( (status != old) && (status != CommSystemFacade.STATUS_UNKNOWN) ) { if ( (status != old) && (status != CommSystemFacade.STATUS_UNKNOWN) ) {
if (_log.shouldLog(Log.INFO))
_log.info("Old status: " + old + " New status: " + status + " from: ", new Exception("traceback"));
if (needsRebuild()) if (needsRebuild())
rebuildExternalAddress(); rebuildExternalAddress();
} }