diff --git a/apps/ministreaming/java/src/net/i2p/client/streaming/I2PSocketManagerImpl.java b/apps/ministreaming/java/src/net/i2p/client/streaming/I2PSocketManagerImpl.java index e01b28fb041b7f02956a996001eccfb9bbc95d80..fb2589b52bdc5ec2ed1d0e2368e17f13845c3099 100644 --- a/apps/ministreaming/java/src/net/i2p/client/streaming/I2PSocketManagerImpl.java +++ b/apps/ministreaming/java/src/net/i2p/client/streaming/I2PSocketManagerImpl.java @@ -673,6 +673,8 @@ class I2PSocketManagerImpl implements I2PSocketManager, I2PSessionListener { * Ping the specified peer, returning true if they replied to the ping within * the timeout specified, false otherwise. This call blocks. * + * @deprecated timeout is ignored - use I2PSocketManagerFull.ping() + * @param timeoutMs ignored */ public boolean ping(Destination peer, long timeoutMs) { try { diff --git a/apps/routerconsole/java/build.xml b/apps/routerconsole/java/build.xml index f77a14387aea09c2f91f28ecd1ad97df778757ab..61d1ddc85fdaa7d0c479f17f8cd03e517af51931 100644 --- a/apps/routerconsole/java/build.xml +++ b/apps/routerconsole/java/build.xml @@ -73,11 +73,26 @@ <delete dir="./tmpextract" /> <ant target="war" /> + + <!-- Update the messages_*.po files. + We need to supply the bat file for windows, and then change the fail property to true --> + <exec executable="sh" osfamily="unix" failifexecutionfails="false" > + <arg value="./bundle-messages.sh" /> + </exec> + <exec executable="sh" osfamily="mac" failifexecutionfails="false" > + <arg value="./bundle-messages.sh" /> + </exec> + <exec executable="cmd" osfamily="windows" failifexecutionfails="false" > + <arg value="/c" /> + <arg value="bundle-messages.bat" /> + </exec> + <!-- jar again to get the latest messages_*.class files --> + <jar destfile="./build/routerconsole.jar" basedir="./build/obj" includes="**/*.class" update="true" /> </target> <target name="war" depends="precompilejsp"> <!-- Don't include the css in the war, the main build.xml will copy it to docs/themes/console/ --> <war destfile="build/routerconsole.war" webxml="../jsp/web-out.xml" - basedir="../jsp/" excludes="web.xml, *.css, *.java, *.jsp, web-fragment.xml"> + basedir="../jsp/" excludes="web.xml, *.css, **/*.java, *.jsp, web-fragment.xml"> </war> </target> <target name="precompilejsp" unless="precompilejsp.uptodate"> @@ -115,6 +130,7 @@ </java> <javac debug="true" deprecation="on" source="1.5" target="1.5" + encoding="UTF-8" destdir="../jsp/WEB-INF/classes/" srcdir="../jsp/WEB-INF/classes" includes="**/*.java"> <compilerarg line="${javac.compilerargs}" /> @@ -133,10 +149,13 @@ <pathelement location="../../../core/java/build/i2p.jar" /> </classpath> </javac> + + <!-- save these so we can run gettext on the generated java files later <delete> <fileset dir="../jsp/WEB-INF/" includes="**/*.java" /> <fileset dir="../jsp/WEB-INF/" includes="**/*.jsp" /> </delete> + --> <copy file="../jsp/web.xml" tofile="../jsp/web-out.xml" /> <loadfile property="jspc.web.fragment" srcfile="../jsp/web-fragment.xml" /> <replace file="../jsp/web-out.xml"> diff --git a/apps/routerconsole/java/bundle-messages.sh b/apps/routerconsole/java/bundle-messages.sh new file mode 100755 index 0000000000000000000000000000000000000000..629fc95f05b294dc8abd9c3ee9f758055889ef65 --- /dev/null +++ b/apps/routerconsole/java/bundle-messages.sh @@ -0,0 +1,67 @@ +# +# Update messages_xx.po and messages_xx.class files, +# from both java and jsp sources. +# Requires installed programs xgettext, msgfmt, msgmerge, and find. +# zzz - public domain +# +CLASS=net.i2p.router.web.messages +TMPFILE=build/javafiles.txt +export TZ=UTC + +for i in ../locale/messages_*.po +do + # get language + LG=${i#../locale/messages_} + LG=${LG%.po} + + # make list of java files newer than the .po file + find src ../jsp/WEB-INF -name *.java -newer $i > $TMPFILE + if [ -s build/obj/net/i2p/router/web/messages_$LG.class -a ! -s $TMPFILE ] + then + continue + fi + + echo "Generating ${CLASS}_$LG ResourceBundle..." + + # extract strings from java and jsp files, and update messages.po files + # translate calls must be one of the forms: + # _("foo") + # cssHelper._("foo") + # cssHelper.title("foo") + # handler._("foo") + # formhandler._("foo") + # In a jsp, you must use a helper or handler that has the context set. + # To start a new translation, copy the header from an old translation to the new .po file, + # then ant distclean updater. + find src ../jsp/WEB-INF -name *.java > $TMPFILE + xgettext -f $TMPFILE -F -L java \ + --keyword=_ --keyword=cssHelper._ --keyword=cssHelper.title --keyword=handler._ --keyword=formhandler._ \ + -o ${i}t + if [ $? -ne 0 ] + then + echo 'Warning - xgettext failed, not updating translations' + rm -f ${i}t + break + fi + msgmerge -U --backup=none $i ${i}t + if [ $? -ne 0 ] + then + echo 'Warning - msgmerge failed, not updating translations' + rm -f ${i}t + break + fi + rm -f ${i}t + # so we don't do this again + touch $i + + # convert to class files in build/obj + msgfmt --java -r $CLASS -l $LG -d build/obj $i + if [ $? -ne 0 ] + then + echo 'Warning - xgettext failed, not updating translations' + break + fi +done +rm -f $TMPFILE +# todo: return failure +exit 0 diff --git a/apps/routerconsole/java/src/net/i2p/router/web/CSSHelper.java b/apps/routerconsole/java/src/net/i2p/router/web/CSSHelper.java index a2f3341f9df920f0687c4b21103d45ffc162d8f5..715c800931a7c1148ff248e76149a30bbc111ed7 100644 --- a/apps/routerconsole/java/src/net/i2p/router/web/CSSHelper.java +++ b/apps/routerconsole/java/src/net/i2p/router/web/CSSHelper.java @@ -22,4 +22,21 @@ public class CSSHelper extends HelperBase { } return url; } + + /** change default language for the router but don't save it */ + public void setLang(String lang) { + if (lang != null && lang.length() > 0) + _context.router().setConfigSetting(Messages.PROP_LANG, lang); + } + + /** translate the title and display consistently */ + public String title(String s) { + StringBuilder buf = new StringBuilder(128); + buf.append("<title>") + .append(_("I2P Router Console")) + .append(" - ") + .append(_(s)) + .append("</title>"); + return buf.toString(); + } } diff --git a/apps/routerconsole/java/src/net/i2p/router/web/ConfigUpdateHelper.java b/apps/routerconsole/java/src/net/i2p/router/web/ConfigUpdateHelper.java index 82d8461f15715cb4a1217ee816578bee7c7dc904..164ac8df20239387891a348812e6a5fe3cca3862 100644 --- a/apps/routerconsole/java/src/net/i2p/router/web/ConfigUpdateHelper.java +++ b/apps/routerconsole/java/src/net/i2p/router/web/ConfigUpdateHelper.java @@ -87,7 +87,7 @@ public class ConfigUpdateHelper extends HelperBase { buf.append("<select name=\"updatePolicy\">"); if ("notify".equals(policy)) - buf.append("<option value=\"notify\" selected=\"true\">Notify only</option>"); + buf.append("<option value=\"notify\" selected=\"true\">").append(_("Notify only")).append("</option>"); else buf.append("<option value=\"notify\">Notify only</option>"); diff --git a/apps/routerconsole/java/src/net/i2p/router/web/ContentHelper.java b/apps/routerconsole/java/src/net/i2p/router/web/ContentHelper.java index 795eeb26c3c9f12d9dbba810709d140c93cba76d..0a1cbdc347e1390a03ce1504ca0ec71067066ff6 100644 --- a/apps/routerconsole/java/src/net/i2p/router/web/ContentHelper.java +++ b/apps/routerconsole/java/src/net/i2p/router/web/ContentHelper.java @@ -62,7 +62,8 @@ public class ContentHelper extends HelperBase { /** * Convert file.ext to file_lang.ext if it exists. - * Get lang from either the cgi lang param or from the default locale. + * Get lang from the cgi lang param, then properties, then from the default locale. + * _context must be set to check the property. */ private String filename() { int lastdot = _page.lastIndexOf('.'); @@ -70,9 +71,13 @@ public class ContentHelper extends HelperBase { return _page; String lang = _lang; if (lang == null || lang.length() <= 0) { - lang = Locale.getDefault().getLanguage(); - if (lang == null || lang.length() <= 0) - return _page; + if (_context != null) + lang = _context.getProperty(Messages.PROP_LANG); + if (lang == null || lang.length() <= 0) { + lang = Locale.getDefault().getLanguage(); + if (lang == null || lang.length() <= 0) + return _page; + } } if (lang.equals("en")) return _page; diff --git a/apps/routerconsole/java/src/net/i2p/router/web/FormHandler.java b/apps/routerconsole/java/src/net/i2p/router/web/FormHandler.java index 0aba83517e9e7484f3ee105101a37f32a9f2035e..8ed39f5c194152b1afcaafccdceeeb333b08d23a 100644 --- a/apps/routerconsole/java/src/net/i2p/router/web/FormHandler.java +++ b/apps/routerconsole/java/src/net/i2p/router/web/FormHandler.java @@ -190,4 +190,8 @@ public class FormHandler { } } + /** translate a string */ + public String _(String s) { + return Messages.getString(s, _context); + } } diff --git a/apps/routerconsole/java/src/net/i2p/router/web/HelperBase.java b/apps/routerconsole/java/src/net/i2p/router/web/HelperBase.java index 848e48d50dfb38540ce0ab973953418e0f9a299b..63762ec14d8f1651db5c8f09e07cf8ac98c3002c 100644 --- a/apps/routerconsole/java/src/net/i2p/router/web/HelperBase.java +++ b/apps/routerconsole/java/src/net/i2p/router/web/HelperBase.java @@ -29,4 +29,9 @@ public abstract class HelperBase { //public RouterContext getContext() { return _context; } public void setWriter(Writer out) { _out = out; } + + /** translate a string */ + public String _(String s) { + return Messages.getString(s, _context); + } } diff --git a/apps/routerconsole/java/src/net/i2p/router/web/LocaleWebAppHandler.java b/apps/routerconsole/java/src/net/i2p/router/web/LocaleWebAppHandler.java new file mode 100644 index 0000000000000000000000000000000000000000..b7ac2b8f8f292f1e6f75265ff3a456a8e7aa4693 --- /dev/null +++ b/apps/routerconsole/java/src/net/i2p/router/web/LocaleWebAppHandler.java @@ -0,0 +1,69 @@ +package net.i2p.router.web; + +import java.io.IOException; +import java.util.Locale; +import java.util.Map; + +import net.i2p.I2PAppContext; + +import org.mortbay.http.HttpRequest; +import org.mortbay.http.HttpResponse; +import org.mortbay.jetty.servlet.WebApplicationHandler; + +/** + * Convert foo.jsp to foo_xx.jsp for language xx. + * This is appropriate for jsps with large amounts of text. + * This does not work for included jsps (e.g. summary*) + * + * @author zzz + */ +public class LocaleWebAppHandler extends WebApplicationHandler +{ + private I2PAppContext _context; + + public LocaleWebAppHandler(I2PAppContext ctx) { + super(); + _context = ctx; + } + + /** + * Handle foo.jsp by converting to foo_xx.jsp + * for language xx, where xx is the language for the default locale, + * or as specified in the routerconsole.lang property. + * Unless language==="en". + */ + public void handle(String pathInContext, + String pathParams, + HttpRequest httpRequest, + HttpResponse httpResponse) + throws IOException + { + //System.err.println("Path: " + pathInContext); + String newPath = pathInContext; + if (pathInContext.endsWith(".jsp")) { + int len = pathInContext.length(); + // ...but leave foo_xx.jsp alone + if (len < 8 || pathInContext.charAt(len - 7) != '_') { + String lang = _context.getProperty(Messages.PROP_LANG); + if (lang == null || lang.length() <= 0) + lang = Locale.getDefault().getLanguage(); + if (lang != null && lang.length() > 0 && !lang.equals("en")) { + String testPath = pathInContext.substring(0, len - 4) + '_' + lang + ".jsp"; + // Do we have a servlet for the new path that isn't the catchall *.jsp? + Map.Entry servlet = getHolderEntry(testPath); + if (servlet != null) { + String servletPath = (String) servlet.getKey(); + if (servletPath != null && !servletPath.startsWith("*")) { + // success!! + //System.err.println("Servlet is: " + servletPath); + newPath = testPath; + } + } + } + } + } + //System.err.println("New path: " + newPath); + super.handle(newPath, pathParams, httpRequest, httpResponse); + //System.err.println("Was handled? " + httpRequest.isHandled()); + } +} diff --git a/apps/routerconsole/java/src/net/i2p/router/web/Messages.java b/apps/routerconsole/java/src/net/i2p/router/web/Messages.java new file mode 100644 index 0000000000000000000000000000000000000000..df7c5319f3fb0dc3fd090fa09c3bb8924d7242f5 --- /dev/null +++ b/apps/routerconsole/java/src/net/i2p/router/web/Messages.java @@ -0,0 +1,80 @@ +package net.i2p.router.web; + +import java.util.Locale; +import java.util.Map; +import java.util.MissingResourceException; +import java.util.ResourceBundle; +import java.util.Set; +import java.util.concurrent.ConcurrentHashMap; + +import net.i2p.I2PAppContext; +import net.i2p.util.ConcurrentHashSet; + +/** + * Translate strings efficiently. + * We don't include an English or default ResourceBundle, we simply check + * for "en" and return the original string. + * Support real-time language changing with the routerconsole.lang property. + * + * @author zzz, from a base generated by eclipse. + */ +public class Messages { + public static final String PROP_LANG = "routerconsole.lang"; + private static final String BUNDLE_NAME = "net.i2p.router.web.messages"; + private static final String _localeLang = Locale.getDefault().getLanguage(); + private static final Map<String, ResourceBundle> _bundles = new ConcurrentHashMap(2); + private static final Set<String> _missing = new ConcurrentHashSet(2); + + /** current locale **/ + public static String getString(String key) { + if (_localeLang.equals("en")) + return key; + ResourceBundle bundle = findBundle(_localeLang); + if (bundle == null) + return key; + try { + return bundle.getString(key); + } catch (MissingResourceException e) { + return key; + } + } + + /** lang in routerconsole.lang property, else current locale */ + public static String getString(String key, I2PAppContext ctx) { + String lang = getLanguage(ctx); + if (lang.equals("en")) + return key; + ResourceBundle bundle = findBundle(lang); + if (bundle == null) + return key; + try { + return bundle.getString(key); + } catch (MissingResourceException e) { + return key; + } + } + + private static String getLanguage(I2PAppContext ctx) { + String lang = ctx.getProperty(PROP_LANG); + if (lang == null || lang.length() <= 0) + lang = _localeLang; + return lang; + } + + /** cache both found and not found for speed */ + private static ResourceBundle findBundle(String lang) { + ResourceBundle rv = _bundles.get(lang); + if (rv == null && !_missing.contains(lang)) { + try { + // Would it be faster to specify a class loader? + // No matter we only do this once per lang. + rv = ResourceBundle.getBundle(BUNDLE_NAME, new Locale(lang)); + if (rv != null) + _bundles.put(lang, rv); + } catch (MissingResourceException e) { + _missing.add(lang); + } + } + return rv; + } +} diff --git a/apps/routerconsole/java/src/net/i2p/router/web/NetDbHelper.java b/apps/routerconsole/java/src/net/i2p/router/web/NetDbHelper.java index cffe6f1a7876838ce8fe5f5761c0d4bb53f2bb9e..fd49aa7ad051240a5ca990f555d60a3f5f73368a 100644 --- a/apps/routerconsole/java/src/net/i2p/router/web/NetDbHelper.java +++ b/apps/routerconsole/java/src/net/i2p/router/web/NetDbHelper.java @@ -17,23 +17,24 @@ public class NetDbHelper extends HelperBase { public void setLease(String l) { _lease = "1".equals(l); } public String getNetDbSummary() { + NetDbRenderer renderer = new NetDbRenderer(_context); try { if (_out != null) { if (_routerPrefix != null) - _context.netDb().renderRouterInfoHTML(_out, _routerPrefix); + renderer.renderRouterInfoHTML(_out, _routerPrefix); else if (_lease) - _context.netDb().renderLeaseSetHTML(_out); + renderer.renderLeaseSetHTML(_out); else - _context.netDb().renderStatusHTML(_out, _full); + renderer.renderStatusHTML(_out, _full); return ""; } else { ByteArrayOutputStream baos = new ByteArrayOutputStream(32*1024); if (_routerPrefix != null) - _context.netDb().renderRouterInfoHTML(new OutputStreamWriter(baos), _routerPrefix); + renderer.renderRouterInfoHTML(new OutputStreamWriter(baos), _routerPrefix); else if (_lease) - _context.netDb().renderLeaseSetHTML(new OutputStreamWriter(baos)); + renderer.renderLeaseSetHTML(new OutputStreamWriter(baos)); else - _context.netDb().renderStatusHTML(new OutputStreamWriter(baos), _full); + renderer.renderStatusHTML(new OutputStreamWriter(baos), _full); return new String(baos.toByteArray()); } } catch (IOException ioe) { diff --git a/apps/routerconsole/java/src/net/i2p/router/web/NetDbRenderer.java b/apps/routerconsole/java/src/net/i2p/router/web/NetDbRenderer.java new file mode 100644 index 0000000000000000000000000000000000000000..6e9f76fa84868a835cfe92c09c0f823e37dd7c86 --- /dev/null +++ b/apps/routerconsole/java/src/net/i2p/router/web/NetDbRenderer.java @@ -0,0 +1,275 @@ +package net.i2p.router.web; +/* + * free (adj.): unencumbered; not under the control of others + * Written by jrandom in 2003 and released into the public domain + * with no warranty of any kind, either expressed or implied. + * It probably won't make your computer catch on fire, or eat + * your children, but it might. Use at your own risk. + * + */ + +import java.io.IOException; +import java.io.Writer; +import java.util.ArrayList; +import java.util.Collections; +import java.util.Comparator; +import java.util.Iterator; +import java.util.List; +import java.util.Set; +import java.util.TreeSet; + +import net.i2p.data.DataHelper; +import net.i2p.data.Destination; +import net.i2p.data.Hash; +import net.i2p.data.LeaseSet; +import net.i2p.data.RouterAddress; +import net.i2p.data.RouterInfo; +import net.i2p.router.RouterContext; +import net.i2p.router.TunnelPoolSettings; +import net.i2p.util.ObjectCounter; + +public class NetDbRenderer { + private RouterContext _context; + + public NetDbRenderer (RouterContext ctx) { + _context = ctx; + } + + private class LeaseSetComparator implements Comparator { + public int compare(Object l, Object r) { + Destination dl = ((LeaseSet)l).getDestination(); + Destination dr = ((LeaseSet)r).getDestination(); + boolean locall = _context.clientManager().isLocal(dl); + boolean localr = _context.clientManager().isLocal(dr); + if (locall && !localr) return -1; + if (localr && !locall) return 1; + return dl.calculateHash().toBase64().compareTo(dr.calculateHash().toBase64()); + } + } + + private static class RouterInfoComparator implements Comparator { + public int compare(Object l, Object r) { + return ((RouterInfo)l).getIdentity().getHash().toBase64().compareTo(((RouterInfo)r).getIdentity().getHash().toBase64()); + } + } + + public void renderRouterInfoHTML(Writer out, String routerPrefix) throws IOException { + StringBuilder buf = new StringBuilder(4*1024); + buf.append("<h2>Network Database RouterInfo Lookup</h2>\n"); + if (".".equals(routerPrefix)) { + renderRouterInfo(buf, _context.router().getRouterInfo(), true, true); + } else { + boolean notFound = true; + Set routers = _context.netDb().getRouters(); + for (Iterator iter = routers.iterator(); iter.hasNext(); ) { + RouterInfo ri = (RouterInfo)iter.next(); + Hash key = ri.getIdentity().getHash(); + if (key.toBase64().startsWith(routerPrefix)) { + renderRouterInfo(buf, ri, false, true); + notFound = false; + } + } + if (notFound) + buf.append("Router ").append(routerPrefix).append(" not found in network database"); + } + out.write(buf.toString()); + out.flush(); + } + + public void renderStatusHTML(Writer out) throws IOException { + renderStatusHTML(out, true); + } + + public void renderLeaseSetHTML(Writer out) throws IOException { + StringBuilder buf = new StringBuilder(4*1024); + buf.append("<h2>Network Database Contents</h2>\n"); + buf.append("<a href=\"netdb.jsp\">View RouterInfo</a>"); + buf.append("<h3>LeaseSets</h3>\n"); + Set leases = new TreeSet(new LeaseSetComparator()); + leases.addAll(_context.netDb().getLeases()); + long now = _context.clock().now(); + for (Iterator iter = leases.iterator(); iter.hasNext(); ) { + LeaseSet ls = (LeaseSet)iter.next(); + Destination dest = ls.getDestination(); + Hash key = dest.calculateHash(); + buf.append("<b>LeaseSet: ").append(key.toBase64()); + if (_context.clientManager().isLocal(dest)) { + buf.append(" (<a href=\"tunnels.jsp#" + key.toBase64().substring(0,4) + "\">Local</a> "); + if (! _context.clientManager().shouldPublishLeaseSet(key)) + buf.append("Unpublished "); + buf.append("Destination "); + TunnelPoolSettings in = _context.tunnelManager().getInboundSettings(key); + if (in != null && in.getDestinationNickname() != null) + buf.append(in.getDestinationNickname()); + else + buf.append(dest.toBase64().substring(0, 6)); + } else { + buf.append(" (Destination "); + String host = _context.namingService().reverseLookup(dest); + if (host != null) + buf.append(host); + else + buf.append(dest.toBase64().substring(0, 6)); + } + buf.append(")</b><br>\n"); + long exp = ls.getEarliestLeaseDate()-now; + if (exp > 0) + buf.append("Expires in ").append(DataHelper.formatDuration(exp)).append("<br>\n"); + else + buf.append("Expired ").append(DataHelper.formatDuration(0-exp)).append(" ago<br>\n"); + for (int i = 0; i < ls.getLeaseCount(); i++) { + buf.append("Lease ").append(i + 1).append(": Gateway "); + buf.append(_context.commSystem().renderPeerHTML(ls.getLease(i).getGateway())); + buf.append(" Tunnel ").append(ls.getLease(i).getTunnelId().getTunnelId()).append("<br>\n"); + } + buf.append("<hr>\n"); + out.write(buf.toString()); + buf.setLength(0); + } + out.write(buf.toString()); + out.flush(); + } + + public void renderStatusHTML(Writer out, boolean full) throws IOException { + int size = _context.netDb().getKnownRouters() * 512; + if (full) + size *= 4; + StringBuilder buf = new StringBuilder(size); + out.write("<h2>Network Database Contents (<a href=\"netdb.jsp?l=1\">View LeaseSets</a>)</h2>\n"); + if (!_context.netDb().isInitialized()) { + buf.append("Not initialized\n"); + out.write(buf.toString()); + out.flush(); + return; + } + + Hash us = _context.routerHash(); + out.write("<a name=\"routers\" ></a><h3>Routers (<a href=\"netdb.jsp"); + if (full) + out.write("#routers\" >view without"); + else + out.write("?f=1#routers\" >view with"); + out.write(" stats</a>)</h3>\n"); + + RouterInfo ourInfo = _context.router().getRouterInfo(); + renderRouterInfo(buf, ourInfo, true, true); + out.write(buf.toString()); + buf.setLength(0); + + ObjectCounter<String> versions = new ObjectCounter(); + ObjectCounter<String> countries = new ObjectCounter(); + + Set routers = new TreeSet(new RouterInfoComparator()); + routers.addAll(_context.netDb().getRouters()); + for (Iterator iter = routers.iterator(); iter.hasNext(); ) { + RouterInfo ri = (RouterInfo)iter.next(); + Hash key = ri.getIdentity().getHash(); + boolean isUs = key.equals(us); + if (!isUs) { + renderRouterInfo(buf, ri, false, full); + out.write(buf.toString()); + buf.setLength(0); + String routerVersion = ri.getOption("router.version"); + if (routerVersion != null) + versions.increment(routerVersion); + String country = _context.commSystem().getCountry(key); + if(country != null) + countries.increment(country); + } + } + + buf.append("<table border=\"0\" cellspacing=\"30\"><tr><td>"); + List<String> versionList = new ArrayList(versions.objects()); + if (versionList.size() > 0) { + Collections.sort(versionList, Collections.reverseOrder()); + buf.append("<table>\n"); + buf.append("<tr><th>Version</th><th>Count</th></tr>\n"); + for (String routerVersion : versionList) { + int num = versions.count(routerVersion); + buf.append("<tr><td align=\"center\">").append(DataHelper.stripHTML(routerVersion)); + buf.append("</td><td align=\"center\">").append(num).append("</td></tr>\n"); + } + buf.append("</table>\n"); + } + buf.append("</td><td>"); + out.write(buf.toString()); + buf.setLength(0); + + List<String> countryList = new ArrayList(countries.objects()); + if (countryList.size() > 0) { + Collections.sort(countryList); + buf.append("<table>\n"); + buf.append("<tr><th align=\"left\">Country</th><th>Count</th></tr>\n"); + for (String country : countryList) { + int num = countries.count(country); + buf.append("<tr><td><img height=\"11\" width=\"16\" alt=\"").append(country.toUpperCase()).append("\""); + buf.append(" src=\"/flags.jsp?c=").append(country).append("\"> "); + buf.append(_context.commSystem().getCountryName(country)); + buf.append("</td><td align=\"center\">").append(num).append("</td></tr>\n"); + } + buf.append("</table>\n"); + } + buf.append("</td></tr></table>"); + out.write(buf.toString()); + out.flush(); + } + + /** + * Be careful to use stripHTML for any displayed routerInfo data + * to prevent vulnerabilities + */ + private void renderRouterInfo(StringBuilder buf, RouterInfo info, boolean isUs, boolean full) { + String hash = info.getIdentity().getHash().toBase64(); + buf.append("<table><tr><th><a name=\"").append(hash.substring(0, 6)).append("\" ></a>"); + if (isUs) { + buf.append("<a name=\"our-info\" ></a><b>Our info: ").append(hash).append("</b></th></tr><tr><td>\n"); + } else { + buf.append("<b>Peer info for:</b> ").append(hash).append("\n"); + if (full) { + buf.append("[<a href=\"netdb.jsp\" >Back</a>]</th></tr><td>\n"); + } else { + buf.append("[<a href=\"netdb.jsp?r=").append(hash.substring(0, 6)).append("\" >Full entry</a>]</th></tr><td>\n"); + } + } + + long age = _context.clock().now() - info.getPublished(); + if (isUs && _context.router().isHidden()) + buf.append("<b>Hidden, Updated:</b> ").append(DataHelper.formatDuration(age)).append(" ago<br>\n"); + else if (age > 0) + buf.append("<b>Published:</b> ").append(DataHelper.formatDuration(age)).append(" ago<br>\n"); + else + buf.append("<b>Published:</b> in ").append(DataHelper.formatDuration(0-age)).append("???<br>\n"); + buf.append("<b>Address(es):</b> "); + String country = _context.commSystem().getCountry(info.getIdentity().getHash()); + if(country != null) { + buf.append("<img height=\"11\" width=\"16\" alt=\"").append(country.toUpperCase()).append("\""); + buf.append(" src=\"/flags.jsp?c=").append(country).append("\"> "); + } + for (Iterator iter = info.getAddresses().iterator(); iter.hasNext(); ) { + RouterAddress addr = (RouterAddress)iter.next(); + buf.append(DataHelper.stripHTML(addr.getTransportStyle())).append(": "); + for (Iterator optIter = addr.getOptions().keySet().iterator(); optIter.hasNext(); ) { + String name = (String)optIter.next(); + String val = addr.getOptions().getProperty(name); + buf.append('[').append(DataHelper.stripHTML(name)).append('=').append(DataHelper.stripHTML(val)).append("] "); + } + } + buf.append("</td></tr>\n"); + if (full) { + buf.append("<tr><td>Stats: <br><code>\n"); + for (Iterator iter = info.getOptions().keySet().iterator(); iter.hasNext(); ) { + String key = (String)iter.next(); + String val = info.getOption(key); + buf.append(DataHelper.stripHTML(key)).append(" = ").append(DataHelper.stripHTML(val)).append("<br>\n"); + } + buf.append("</code></td></tr>\n"); + } else { + } + buf.append("</td></tr>\n"); + } + + /** translate a string */ + private String _(String s) { + return Messages.getString(s, _context); + } +} diff --git a/apps/routerconsole/java/src/net/i2p/router/web/ProfileOrganizerRenderer.java b/apps/routerconsole/java/src/net/i2p/router/web/ProfileOrganizerRenderer.java index 957cafc108c6184e3b192c203a2c91b93fe704b8..29fb47ada75b13745f55e5ca2c4c170cd19cad2f 100644 --- a/apps/routerconsole/java/src/net/i2p/router/web/ProfileOrganizerRenderer.java +++ b/apps/routerconsole/java/src/net/i2p/router/web/ProfileOrganizerRenderer.java @@ -319,4 +319,9 @@ class ProfileOrganizerRenderer { long c = r.getCurrentEventCount() + r.getLastEventCount(); return "" + c; } + + /** translate a string */ + private String _(String s) { + return Messages.getString(s, _context); + } } diff --git a/apps/routerconsole/java/src/net/i2p/router/web/RouterConsoleRunner.java b/apps/routerconsole/java/src/net/i2p/router/web/RouterConsoleRunner.java index 8529f13ff9ef5ed3d92bd0a83f9631aeef7c6120..ec2b10c244dddcbab29d80e013cbb2015531ab81 100644 --- a/apps/routerconsole/java/src/net/i2p/router/web/RouterConsoleRunner.java +++ b/apps/routerconsole/java/src/net/i2p/router/web/RouterConsoleRunner.java @@ -111,6 +111,7 @@ public class RouterConsoleRunner { File tmpdir = new File(workDir, ROUTERCONSOLE + "-" + _listenPort); tmpdir.mkdir(); wac.setTempDirectory(tmpdir); + wac.addHandler(0, new LocaleWebAppHandler(I2PAppContext.getGlobalContext())); initialize(wac); File dir = new File(_webAppsDir); String fileNames[] = dir.list(WarFilenameFilter.instance()); diff --git a/apps/routerconsole/java/src/net/i2p/router/web/StatsGenerator.java b/apps/routerconsole/java/src/net/i2p/router/web/StatsGenerator.java index 1f450239b4af533c308fa00b291b2f4945ed3743..15322edf4b89d5245c9a0c74f89d5ed41b4c4e3f 100644 --- a/apps/routerconsole/java/src/net/i2p/router/web/StatsGenerator.java +++ b/apps/routerconsole/java/src/net/i2p/router/web/StatsGenerator.java @@ -235,4 +235,9 @@ public class StatsGenerator { private final static DecimalFormat _pct = new DecimalFormat("#0.00%"); private final static String pct(double num) { synchronized (_pct) { return _pct.format(num); } } + + /** translate a string */ + private String _(String s) { + return Messages.getString(s, _context); + } } diff --git a/apps/routerconsole/java/src/net/i2p/router/web/SummaryBarRenderer.java b/apps/routerconsole/java/src/net/i2p/router/web/SummaryBarRenderer.java new file mode 100644 index 0000000000000000000000000000000000000000..e7d6ee4126a09fce625028a2508f633d063d2276 --- /dev/null +++ b/apps/routerconsole/java/src/net/i2p/router/web/SummaryBarRenderer.java @@ -0,0 +1,417 @@ +package net.i2p.router.web; + +import java.io.File; +import java.io.IOException; +import java.io.Writer; + +import net.i2p.router.RouterContext; + +/** + * Refactored from summarynoframe.jsp to save ~100KB + * + */ +public class SummaryBarRenderer { + private RouterContext _context; + private SummaryHelper _helper; + + public SummaryBarRenderer(RouterContext context, SummaryHelper helper) { + _context = context; + _helper = helper; + } + + public void renderSummaryHTML(Writer out) throws IOException { + StringBuilder buf = new StringBuilder(8*1024); + + buf.append("<a href=\"index.jsp\" target=\"_top\"><img src=\"/themes/console/images/i2plogo.png\" alt=\"") + .append(_("I2P Router Console")) + .append("\" title=\"") + .append(_("I2P Router Console")) + .append("\"></a><hr>"); + + File lpath = new File(_context.getBaseDir(), "docs/toolbar.html"); + // you better have target="_top" for the links in there... + if (lpath.exists()) { + ContentHelper linkhelper = new ContentHelper(); + linkhelper.setPage(lpath.getAbsolutePath()); + linkhelper.setMaxLines("100"); + buf.append(linkhelper.getContent()); + } else { + buf.append("<h3><a href=\"/configclients.jsp\" target=\"_top\" title=\"") + .append("Configure startup of clients and webapps (services); manually start dormant services") + .append("\">") + .append(_("I2P Services")) + .append("</a></h3>\n" + + + "<hr><table>" + + + "<tr><td><a href=\"susidns/index.jsp\" target=\"_blank\" title=\"") + .append(_("Manage your I2P hosts file here (I2P domain name resolution)")) + .append("\">") + .append(_("Addressbook")) + .append("</a>\n" + + + "<a href=\"i2psnark/\" target=\"_blank\" title=\"") + .append(_("Built-in anonymous BitTorrent Client")) + .append("\">") + .append(_("Torrents")) + .append("</a>\n" + + + "<a href=\"susimail/susimail\" target=\"blank\" title=\"") + .append(_("Anonymous webmail client")) + .append("\">") + .append(_("Webmail")) + .append("</a>\n" + + + "<a href=\"http://127.0.0.1:7658/\" target=\"_blank\" title=\"") + .append(_("Anonymous resident webserver")) + .append("\">") + .append(_("Webserver")) + .append("</a></td></tr></table>\n" + + + "<hr><h3><a href=\"config.jsp\" target=\"_top\" title=\"") + .append(_("Configure I2P Router")) + .append("\">") + .append(_("I2P Internals")) + .append("</a></h3><hr>\n" + + + "<table><tr><td>\n" + + + "<a href=\"tunnels.jsp\" target=\"_top\" title=\"") + .append(_("View existing tunnels and tunnel build status")) + .append("\">") + .append(_("Tunnels")) + .append("</a>\n" + + + "<a href=\"peers.jsp\" target=\"_top\" title=\"") + .append(_("Show all current peer connections")) + .append("\">") + .append(_("Peers")) + .append("</a>\n" + + + "<a href=\"profiles.jsp\" target=\"_top\" title=\"") + .append(_("Show recent peer performance profiles")) + .append("\">") + .append(_("Profiles")) + .append("</a>\n" + + + "<a href=\"netdb.jsp\" target=\"_top\" title=\"") + .append(_("Show list of all known I2P routers")) + .append("\">") + .append(_("NetDB")) + .append("</a>\n" + + + "<a href=\"logs.jsp\" target=\"_top\" title=\"") + .append(_("Health Report")) + .append("\">") + .append(_("Logs")) + .append("</a>\n" + + + "<a href=\"jobs.jsp\" target=\"_top\" title=\"") + .append(_("Show the router's workload, and how it's performing")) + .append("\">") + .append(_("Jobs")) + .append("</a>\n" + + + "<a href=\"graphs.jsp\" target=\"_top\" title=\"") + .append(_("Graph router performance")) + .append("\">") + .append(_("Graphs")) + .append("</a>\n" + + + "<a href=\"oldstats.jsp\" target=\"_top\" title=\"") + .append(_("Textual router performance statistics")) + .append("\">") + .append(_("Stats")) + .append("</a></td></tr></table>\n"); + + out.write(buf.toString()); + buf.setLength(0); + } + + + + buf.append("<hr><h3><a href=\"help.jsp\" target=\"_top\" title=\"") + .append(_("I2P Router Help")) + .append("\">") + .append(_("General")) + .append("</a></h3><hr>" + + "<h4><a title=\"") + .append(_("Your unique I2P router identity is")) + .append(' ') + .append(_helper.getIdent()) + .append(", ") + .append(_("never reveal it to anyone")) + .append("\" href=\"netdb.jsp?r=.\" target=\"_top\">") + .append(_("Local Identity")) + .append("<a></h4><hr>\n" + + + "<table><tr><td align=\"left\">" + + "<b>") + .append(_("Version")) + .append(":</b></td>" + + "<td align=\"right\">") + .append(_helper.getVersion()) + .append("</td></tr>\n" + + + "<tr title=\"") + .append(_("How long we've been running for this session")) + .append("\">" + + "<td align=\"left\"><b>") + .append(_("Uptime")) + .append(":</b></td>" + + "<td align=\"right\">") + .append(_helper.getUptime()) + .append("</td></tr></table>\n" + + + "<hr><h4><a href=\"config.jsp#help\" target=\"_top\" title=\"") + .append(_("Help with configuring your firewall and router for optimal I2P performance")) + .append("\">") + .append(_helper.getReachability()) + .append("</a></h4><hr>\n"); + + + if (_helper.updateAvailable() || _helper.unsignedUpdateAvailable()) { + // display all the time so we display the final failure message + buf.append("<br>").append(UpdateHandler.getStatus()); + if ("true".equals(System.getProperty("net.i2p.router.web.UpdateHandler.updateInProgress"))) { + // nothing + } else if( + // isDone() is always false for now, see UpdateHandler + // ((!update.isDone()) && + _helper.getAction() == null && + _helper.getUpdateNonce() == null && + ConfigRestartBean.getRestartTimeRemaining() > 12*60*1000) { + long nonce = _context.random().nextLong(); + String prev = System.getProperty("net.i2p.router.web.UpdateHandler.nonce"); + if (prev != null) + System.setProperty("net.i2p.router.web.UpdateHandler.noncePrev", prev); + System.setProperty("net.i2p.router.web.UpdateHandler.nonce", nonce+""); + String uri = _helper.getRequestURI(); + buf.append("<form action=\"").append(uri).append("\" method=\"GET\">\n"); + buf.append("<input type=\"hidden\" name=\"updateNonce\" value=\"").append(nonce).append("\" >\n"); + if (_helper.updateAvailable()) { + buf.append("<button type=\"submit\" name=\"updateAction\" value=\"signed\" >") + .append(_("Download")) + .append(' ') + .append(_helper.getUpdateVersion()) + .append(' ') + .append(_("Update")) + .append("</button>\n"); + } + if (_helper.unsignedUpdateAvailable()) { + buf.append("<button type=\"submit\" name=\"updateAction\" value=\"Unsigned\" >") + .append(_("Download Unsigned")) + .append("<br>") + .append(_helper.getUnsignedUpdateVersion()) + .append(' ') + .append(_("Update")) + .append("</button>\n"); + } + buf.append("</form>\n"); + } + } + + + + + buf.append("<p>") + .append(ConfigRestartBean.renderStatus(_helper.getRequestURI(), _helper.getAction(), _helper.getConsoleNonce())) + + .append("</p><hr><h3><a href=\"peers.jsp\" target=\"_top\" title=\"") + .append(_("Show all current peer connections")) + .append("\">") + .append(_("Peers")) + .append("</a></h3><hr>\n" + + + "<table>\n" + + + "<tr><td align=\"left\"><b>") + .append(_("Active")) + .append(":</b></td><td align=\"right\">") + .append(_helper.getActivePeers()) + .append('/') + .append(_helper.getActiveProfiles()) + .append("</td></tr>\n" + + + "<tr><td align=\"left\"><b>") + .append(_("Fast")) + .append(":</b></td><td align=\"right\">") + .append(_helper.getFastPeers()) + .append("</td></tr>\n" + + + "<tr><td align=\"left\"><b>") + .append(_("High capacity")) + .append(":</b></td><td align=\"right\">") + .append(_helper.getHighCapacityPeers()) + .append("</td></tr>\n" + + + "<tr><td align=\"left\"><b>") + .append(_("Integrated")) + .append(":</b></td><td align=\"right\">") + .append(_helper.getWellIntegratedPeers()) + .append("</td></tr>\n" + + + "<tr><td align=\"left\"><b>") + .append(_("Known")) + .append(":</b></td><td align=\"right\">") + .append(_helper.getAllPeers()) + .append("</td></tr>\n" + + + "</table><hr>\n"); + + + out.write(buf.toString()); + buf.setLength(0); + + + boolean anotherLine = false; + if (_helper.showFirewallWarning()) { + buf.append("<h4><a href=\"config.jsp\" target=\"_top\" title=\"") + .append(_("Help with firewall configuration")) + .append("\">") + .append(_("Check NAT/firewall")) + .append("</a></h4>"); + anotherLine = true; + } + + boolean reseedInProgress = Boolean.valueOf(System.getProperty("net.i2p.router.web.ReseedHandler.reseedInProgress")).booleanValue(); + // If showing the reseed link is allowed + if (_helper.allowReseed()) { + if (reseedInProgress) { + // While reseed occurring, show status message instead + buf.append("<i>").append(System.getProperty("net.i2p.router.web.ReseedHandler.statusMessage","")).append("</i><br>"); + } else { + // While no reseed occurring, show reseed link + long nonce = _context.random().nextLong(); + String prev = System.getProperty("net.i2p.router.web.ReseedHandler.nonce"); + if (prev != null) System.setProperty("net.i2p.router.web.ReseedHandler.noncePrev", prev); + System.setProperty("net.i2p.router.web.ReseedHandler.nonce", nonce+""); + String uri = _helper.getRequestURI(); + buf.append("<form action=\"").append(uri).append("\" method=\"GET\">\n"); + buf.append("<input type=\"hidden\" name=\"reseedNonce\" value=\"").append(nonce).append("\" >\n"); + buf.append("<button type=\"submit\" >Reseed</button></form>\n"); + } + anotherLine = true; + } + // If a new reseed ain't running, and the last reseed had errors, show error message + if (!reseedInProgress) { + String reseedErrorMessage = System.getProperty("net.i2p.router.web.ReseedHandler.errorMessage",""); + if (reseedErrorMessage.length() > 0) { + buf.append("<i>").append(reseedErrorMessage).append("</i><br>"); + anotherLine = true; + } + } + if (anotherLine) + buf.append("<hr>"); + + + buf.append("<h3><a href=\"config.jsp\" title=\"") + .append(_("Configure router bandwidth allocation")) + .append("\" target=\"_top\">") + .append(_("Bandwidth in/out")) + .append("</a></h3><hr>" + + "<table>\n" + + + "<tr><td align=\"left\"><b>1s:</b></td><td align=\"right\">") + .append(_helper.getInboundSecondKBps()) + .append('/') + .append(_helper.getOutboundSecondKBps()) + .append("K/s</td></tr>\n" + + + "<tr><td align=\"left\"><b>5m:</b></td><td align=\"right\">") + .append(_helper.getInboundFiveMinuteKBps()) + .append('/') + .append(_helper.getOutboundFiveMinuteKBps()) + .append("K/s</td></tr>\n" + + + "<tr><td align=\"left\"><b>") + .append(_("Total")) + .append(":</b></td><td align=\"right\">") + .append(_helper.getInboundLifetimeKBps()) + .append('/') + .append(_helper.getOutboundLifetimeKBps()) + .append("K/s</td></tr>\n" + + + "<tr><td align=\"left\"><b>") + .append(_("Used")) + .append(":</b></td><td align=\"right\">") + .append(_helper.getInboundTransferred()) + .append('/') + .append(_helper.getOutboundTransferred()) + .append("</td></tr></table>\n" + + + "<hr><h3><a href=\"tunnels.jsp\" target=\"_top\" title=\"") + .append(_("View existing tunnels and tunnel build status")) + .append("\">") + .append(_("Tunnels in/out")) + .append("</a></h3><hr>" + + "<table>\n" + + + "<tr><td align=\"left\"><b>") + .append(_("Exploratory")) + .append(":</b></td><td align=\"right\">") + .append(_helper.getInboundTunnels()) + .append('/') + .append(_helper.getOutboundTunnels()) + .append("</td></tr>\n" + + + "<tr><td align=\"left\"><b>") + .append(_("Client")) + .append(":</b></td><td align=\"right\">") + .append(_helper.getInboundClientTunnels()) + .append('/') + .append(_helper.getOutboundClientTunnels()) + .append("</td></tr>\n" + + + "<tr><td align=\"left\"><b>") + .append(_("Participating")) + .append(":</b></td><td align=\"right\">") + .append(_helper.getParticipatingTunnels()) + .append("</td></tr>\n" + + + "</table><hr><h3><a href=\"/jobs.jsp\" target=\"_top\" title=\"") + .append(_("What's in the router's job queue?")) + .append("\">") + .append(_("Congestion")) + .append("</a></h3><hr>" + + "<table>\n" + + + "<tr><td align=\"left\"><b>") + .append(_("Job lag")) + .append(":</b></td><td align=\"right\">") + .append(_helper.getJobLag()) + .append("</td></tr>\n" + + + "<tr><td align=\"left\"><b>") + .append(_("Message delay")) + .append(":</b></td><td align=\"right\">") + .append(_helper.getMessageDelay()) + .append("</td></tr>\n" + + + "<tr><td align=\"left\"><b>") + .append(_("Tunnel lag")) + .append(":</b></td><td align=\"right\">") + .append(_helper.getTunnelLag()) + .append("</td></tr>\n" + + + "<tr><td align=\"left\"><b>") + .append(_("Backlog")) + .append(":</b></td><td align=\"right\">") + .append(_helper.getInboundBacklog()) + .append("</td></tr>\n" + + + "</table><hr><h4>") + .append(_helper.getTunnelStatus()) + .append("</h4><hr>\n") + .append(_helper.getDestinations()); + + + + out.write(buf.toString()); + } + + /** translate a string */ + private String _(String s) { + return Messages.getString(s, _context); + } +} diff --git a/apps/routerconsole/java/src/net/i2p/router/web/SummaryHelper.java b/apps/routerconsole/java/src/net/i2p/router/web/SummaryHelper.java index 5c7779cf5d4e62cc207ef7b57d34622b43db4e7c..47468e3deaa916588a0c8001467e1adc6aebbd01 100644 --- a/apps/routerconsole/java/src/net/i2p/router/web/SummaryHelper.java +++ b/apps/routerconsole/java/src/net/i2p/router/web/SummaryHelper.java @@ -1,5 +1,6 @@ package net.i2p.router.web; +import java.io.IOException; import java.text.Collator; import java.text.DecimalFormat; import java.util.ArrayList; @@ -563,4 +564,28 @@ public class SummaryHelper extends HelperBase { public String getUnsignedUpdateVersion() { return NewsFetcher.getInstance(_context).unsignedUpdateVersion(); } + + /** output the summary bar to _out */ + public void renderSummaryBar() throws IOException { + SummaryBarRenderer renderer = new SummaryBarRenderer(_context, this); + renderer.renderSummaryHTML(_out); + } + + /* below here is stuff we need to get from summarynoframe.jsp to SummaryBarRenderer */ + + private String _action; + public void setAction(String s) { _action = s; } + public String getAction() { return _action; } + + private String _consoleNonce; + public void setConsoleNonce(String s) { _consoleNonce = s; } + public String getConsoleNonce() { return _consoleNonce; } + + private String _updateNonce; + public void setUpdateNonce(String s) { _updateNonce = s; } + public String getUpdateNonce() { return _updateNonce; } + + private String _requestURI; + public void setRequestURI(String s) { _requestURI = s; } + public String getRequestURI() { return _requestURI; } } diff --git a/apps/routerconsole/java/src/net/i2p/router/web/TunnelHelper.java b/apps/routerconsole/java/src/net/i2p/router/web/TunnelHelper.java index b605cbf361bc1efd8da3485395cc69d39bbd8f4c..db64f77c2588763efd7ba9f52de273bdbb68875d 100644 --- a/apps/routerconsole/java/src/net/i2p/router/web/TunnelHelper.java +++ b/apps/routerconsole/java/src/net/i2p/router/web/TunnelHelper.java @@ -9,13 +9,14 @@ public class TunnelHelper extends HelperBase { public TunnelHelper() {} public String getTunnelSummary() { + TunnelRenderer renderer = new TunnelRenderer(_context); try { if (_out != null) { - _context.tunnelManager().renderStatusHTML(_out); + renderer.renderStatusHTML(_out); return ""; } else { ByteArrayOutputStream baos = new ByteArrayOutputStream(32*1024); - _context.tunnelManager().renderStatusHTML(new OutputStreamWriter(baos)); + renderer.renderStatusHTML(new OutputStreamWriter(baos)); return new String(baos.toByteArray()); } } catch (IOException ioe) { diff --git a/apps/routerconsole/java/src/net/i2p/router/web/TunnelRenderer.java b/apps/routerconsole/java/src/net/i2p/router/web/TunnelRenderer.java new file mode 100644 index 0000000000000000000000000000000000000000..b1536c911d2c660b86e2d75dca21499fa8710797 --- /dev/null +++ b/apps/routerconsole/java/src/net/i2p/router/web/TunnelRenderer.java @@ -0,0 +1,318 @@ +package net.i2p.router.web; + +import java.io.IOException; +import java.io.Writer; +import java.util.ArrayList; +import java.util.Collections; +import java.util.Comparator; +import java.util.HashMap; +import java.util.HashSet; +import java.util.Iterator; +import java.util.List; +import java.util.Map; +import java.util.Set; + +import net.i2p.data.DataHelper; +import net.i2p.data.Destination; +import net.i2p.data.Hash; +import net.i2p.data.RouterInfo; +import net.i2p.data.TunnelId; +import net.i2p.router.Router; +import net.i2p.router.RouterContext; +import net.i2p.router.TunnelInfo; +import net.i2p.router.TunnelPoolSettings; +import net.i2p.router.tunnel.HopConfig; +import net.i2p.router.tunnel.pool.TunnelPool; +import net.i2p.stat.RateStat; +import net.i2p.util.ObjectCounter; + +/** + * + */ +public class TunnelRenderer { + private RouterContext _context; + + public TunnelRenderer(RouterContext ctx) { + _context = ctx; + } + + public void renderStatusHTML(Writer out) throws IOException { + out.write("<div class=\"wideload\"><h2><a name=\"exploratory\" ></a>Exploratory tunnels (<a href=\"/configtunnels.jsp#exploratory\">config</a>):</h2>\n"); + renderPool(out, _context.tunnelManager().getInboundExploratoryPool(), _context.tunnelManager().getOutboundExploratoryPool()); + + List<Hash> destinations = null; + Map<Hash, TunnelPool> clientInboundPools = _context.tunnelManager().getInboundClientPools(); + Map<Hash, TunnelPool> clientOutboundPools = _context.tunnelManager().getOutboundClientPools(); + destinations = new ArrayList(clientInboundPools.keySet()); + for (int i = 0; i < destinations.size(); i++) { + Hash client = destinations.get(i); + TunnelPool in = null; + TunnelPool outPool = null; + in = clientInboundPools.get(client); + outPool = clientOutboundPools.get(client); + String name = (in != null ? in.getSettings().getDestinationNickname() : null); + if ( (name == null) && (outPool != null) ) + name = outPool.getSettings().getDestinationNickname(); + if (name == null) + name = client.toBase64().substring(0,4); + out.write("<h2><a name=\"" + client.toBase64().substring(0,4) + + "\" ></a>Client tunnels for " + name); + if (_context.clientManager().isLocal(client)) + out.write(" (<a href=\"/configtunnels.jsp#" + client.toBase64().substring(0,4) +"\">config</a>):</h2>\n"); + else + out.write(" (dead):</h2>\n"); + renderPool(out, in, outPool); + } + + List participating = _context.tunnelDispatcher().listParticipatingTunnels(); + Collections.sort(participating, new TunnelComparator()); + out.write("<h2><a name=\"participating\"></a>Participating tunnels:</h2><table>\n"); + out.write("<tr><th>Receive on</th><th>From</th><th>" + + "Send on</th><th>To</th><th>Expiration</th>" + + "<th>Usage</th><th>Rate</th><th>Role</th></tr>\n"); + long processed = 0; + RateStat rs = _context.statManager().getRate("tunnel.participatingMessageCount"); + if (rs != null) + processed = (long)rs.getRate(10*60*1000).getLifetimeTotalValue(); + int inactive = 0; + for (int i = 0; i < participating.size(); i++) { + HopConfig cfg = (HopConfig)participating.get(i); + if (cfg.getProcessedMessagesCount() <= 0) { + inactive++; + continue; + } + out.write("<tr>"); + if (cfg.getReceiveTunnel() != null) + out.write(" <td class=\"cells\" align=\"center\">" + cfg.getReceiveTunnel().getTunnelId() +"</td>"); + else + out.write(" <td class=\"cells\" align=\"center\">n/a</td>"); + if (cfg.getReceiveFrom() != null) + out.write(" <td class=\"cells\" align=\"right\">" + netDbLink(cfg.getReceiveFrom()) +"</td>"); + else + out.write(" <td class=\"cells\" align=\"center\"> </td>"); + if (cfg.getSendTunnel() != null) + out.write(" <td class=\"cells\" align=\"center\">" + cfg.getSendTunnel().getTunnelId() +"</td>"); + else + out.write(" <td class=\"cells\" align=\"center\"> </td>"); + if (cfg.getSendTo() != null) + out.write(" <td class=\"cells\" align=\"center\">" + netDbLink(cfg.getSendTo()) +"</td>"); + else +// out.write(" <td class=\"cells\" align=\"center\"> </td>"); + out.write(" <td class=\"cells\" align=\"center\"> </td>"); + long timeLeft = cfg.getExpiration()-_context.clock().now(); + if (timeLeft > 0) + out.write(" <td class=\"cells\" align=\"center\">" + DataHelper.formatDuration(timeLeft) + "</td>"); + else + out.write(" <td class=\"cells\" align=\"center\">(grace period)</td>"); + out.write(" <td class=\"cells\" align=\"center\">" + cfg.getProcessedMessagesCount() + "KB</td>"); + int lifetime = (int) ((_context.clock().now() - cfg.getCreation()) / 1000); + if (lifetime <= 0) + lifetime = 1; + if (lifetime > 10*60) + lifetime = 10*60; + int bps = 1024 * (int) cfg.getProcessedMessagesCount() / lifetime; + out.write(" <td class=\"cells\" align=\"center\">" + bps + "Bps</td>"); + if (cfg.getSendTo() == null) + out.write(" <td class=\"cells\" align=\"center\">Outbound Endpoint</td>"); + else if (cfg.getReceiveFrom() == null) + out.write(" <td class=\"cells\" align=\"center\">Inbound Gateway</td>"); + else + out.write(" <td class=\"cells\" align=\"center\">Participant</td>"); + out.write("</tr>\n"); + processed += cfg.getProcessedMessagesCount(); + } + out.write("</table>\n"); + out.write("<div class=\"statusnotes\"><b>Inactive participating tunnels: " + inactive + "</b></div>\n"); + out.write("<div class=\"statusnotes\"><b>Lifetime bandwidth usage: " + DataHelper.formatSize(processed*1024) + "B</b></div>\n"); + renderPeers(out); + } + + private static class TunnelComparator implements Comparator { + public int compare(Object l, Object r) { + return (int) (((HopConfig)r).getProcessedMessagesCount() - ((HopConfig)l).getProcessedMessagesCount()); + } + } + + private void renderPool(Writer out, TunnelPool in, TunnelPool outPool) throws IOException { + List<TunnelInfo> tunnels = null; + if (in == null) + tunnels = new ArrayList(); + else + tunnels = in.listTunnels(); + if (outPool != null) + tunnels.addAll(outPool.listTunnels()); + + long processedIn = (in != null ? in.getLifetimeProcessed() : 0); + long processedOut = (outPool != null ? outPool.getLifetimeProcessed() : 0); + + int live = 0; + int maxLength = 1; + for (int i = 0; i < tunnels.size(); i++) { + TunnelInfo info = tunnels.get(i); + if (info.getLength() > maxLength) + maxLength = info.getLength(); + } + out.write("<table><tr><th>In/Out</th><th>Expiry</th><th>Usage</th><th>Gateway</th>"); + if (maxLength > 3) { + out.write("<th align=\"center\" colspan=\"" + (maxLength - 2)); + out.write("\">Participants</th>"); + } + else if (maxLength == 3) { + out.write("<th>Participant</th>"); + } + if (maxLength > 1) { + out.write("<th>Endpoint</th>"); + } + out.write("</tr>\n"); + for (int i = 0; i < tunnels.size(); i++) { + TunnelInfo info = tunnels.get(i); + long timeLeft = info.getExpiration()-_context.clock().now(); + if (timeLeft <= 0) + continue; // don't display tunnels in their grace period + live++; + if (info.isInbound()) + out.write("<tr> <td class=\"cells\" align=\"center\"><img src=\"/themes/console/images/inbound.png\" alt=\"Inbound\" title=\"Inbound\"></td>"); + else + out.write("<tr> <td class=\"cells\" align=\"center\"><img src=\"/themes/console/images/outbound.png\" alt=\"Outbound\" title=\"Outbound\"></td>"); + out.write(" <td class=\"cells\" align=\"center\">" + DataHelper.formatDuration(timeLeft) + "</td>\n"); + out.write(" <td class=\"cells\" align=\"center\">" + info.getProcessedMessagesCount() + "KB</td>\n"); + for (int j = 0; j < info.getLength(); j++) { + Hash peer = info.getPeer(j); + TunnelId id = (info.isInbound() ? info.getReceiveTunnelId(j) : info.getSendTunnelId(j)); + if (_context.routerHash().equals(peer)) { + out.write(" <td class=\"cells\" align=\"center\">" + (id == null ? "" : "" + id) + "</td>"); + } else { + String cap = getCapacity(peer); + out.write(" <td class=\"cells\" align=\"center\">" + netDbLink(peer) + (id == null ? "" : " " + id) + cap + "</td>"); + } + if (info.getLength() < maxLength && (info.getLength() == 1 || j == info.getLength() - 2)) { + for (int k = info.getLength(); k < maxLength; k++) + out.write(" <td class=\"cells\" align=\"center\"> </td>"); + } + } + out.write("</tr>\n"); + + if (info.isInbound()) + processedIn += info.getProcessedMessagesCount(); + else + processedOut += info.getProcessedMessagesCount(); + } + out.write("</table>\n"); + if (in != null) { + List pending = in.listPending(); + if (pending.size() > 0) + out.write("<div class=\"statusnotes\"><center><b>Build in progress: " + pending.size() + " inbound</b></center></div>\n"); + live += pending.size(); + } + if (outPool != null) { + List pending = outPool.listPending(); + if (pending.size() > 0) + out.write("<div class=\"statusnotes\"><center><b>Build in progress: " + pending.size() + " outbound</b></center></div>\n"); + live += pending.size(); + } + if (live <= 0) + out.write("<div class=\"statusnotes\"><center><b>No tunnels; waiting for the grace period to end.</center></b></div>\n"); + out.write("<div class=\"statusnotes\"><center><b>Lifetime bandwidth usage: " + DataHelper.formatSize(processedIn*1024) + "B in, " + + DataHelper.formatSize(processedOut*1024) + "B out</b></center></div>"); + } + + private void renderPeers(Writer out) throws IOException { + // count up the peers in the local pools + ObjectCounter<Hash> lc = new ObjectCounter(); + int tunnelCount = countTunnelsPerPeer(lc); + + // count up the peers in the participating tunnels + ObjectCounter<Hash> pc = new ObjectCounter(); + int partCount = countParticipatingPerPeer(pc); + + Set<Hash> peers = new HashSet(lc.objects()); + peers.addAll(pc.objects()); + List<Hash> peerList = new ArrayList(peers); + Collections.sort(peerList, new HashComparator()); + + out.write("<h2><a name=\"peers\"></a>Tunnel Counts By Peer:</h2>\n"); + out.write("<table><tr><th>Peer</th><th>Expl. + Client</th><th>% of total</th><th>Part. from + to</th><th>% of total</th></tr>\n"); + for (Hash h : peerList) { + out.write("<tr> <td class=\"cells\" align=\"center\">"); + out.write(netDbLink(h)); + out.write(" <td class=\"cells\" align=\"center\">" + lc.count(h)); + out.write(" <td class=\"cells\" align=\"center\">"); + if (tunnelCount > 0) + out.write("" + (lc.count(h) * 100 / tunnelCount)); + else + out.write('0'); + out.write(" <td class=\"cells\" align=\"center\">" + pc.count(h)); + out.write(" <td class=\"cells\" align=\"center\">"); + if (partCount > 0) + out.write("" + (pc.count(h) * 100 / partCount)); + else + out.write('0'); + out.write('\n'); + } + out.write("<tr class=\"tablefooter\"> <td align=\"center\"><b>Tunnels</b> <td align=\"center\"><b>" + tunnelCount); + out.write("</b> <td> </td> <td align=\"center\"><b>" + partCount); + out.write("</b> <td> </td></tr></table></div>\n"); + } + + /* duplicate of that in tunnelPoolManager for now */ + /** @return total number of non-fallback expl. + client tunnels */ + private int countTunnelsPerPeer(ObjectCounter<Hash> lc) { + List<TunnelPool> pools = new ArrayList(); + _context.tunnelManager().listPools(pools); + int tunnelCount = 0; + for (TunnelPool tp : pools) { + for (TunnelInfo info : tp.listTunnels()) { + if (info.getLength() > 1) { + tunnelCount++; + for (int j = 0; j < info.getLength(); j++) { + Hash peer = info.getPeer(j); + if (!_context.routerHash().equals(peer)) + lc.increment(peer); + } + } + } + } + return tunnelCount; + } + + /** @return total number of part. tunnels */ + private int countParticipatingPerPeer(ObjectCounter<Hash> pc) { + List<HopConfig> participating = _context.tunnelDispatcher().listParticipatingTunnels(); + for (HopConfig cfg : participating) { + Hash from = cfg.getReceiveFrom(); + if (from != null) + pc.increment(from); + Hash to = cfg.getSendTo(); + if (to != null) + pc.increment(to); + } + return participating.size(); + } + + private static class HashComparator implements Comparator { + public int compare(Object l, Object r) { + return ((Hash)l).toBase64().compareTo(((Hash)r).toBase64()); + } + } + + private String getCapacity(Hash peer) { + RouterInfo info = _context.netDb().lookupRouterInfoLocally(peer); + if (info != null) { + String caps = info.getCapabilities(); + for (char c = Router.CAPABILITY_BW12; c <= Router.CAPABILITY_BW256; c++) { + if (caps.indexOf(c) >= 0) + return " " + c; + } + } + return ""; + } + + private String netDbLink(Hash peer) { + return _context.commSystem().renderPeerHTML(peer); + } + + /** translate a string */ + private String _(String s) { + return Messages.getString(s, _context); + } +} diff --git a/apps/routerconsole/jsp/configupdate.jsp b/apps/routerconsole/jsp/configupdate.jsp index 62677bbb041fdd3cd5d23229efbfe98a7690e8cd..e7562de9f7106e1d9eec4cb853f6ec5cf6da6c85 100644 --- a/apps/routerconsole/jsp/configupdate.jsp +++ b/apps/routerconsole/jsp/configupdate.jsp @@ -2,8 +2,9 @@ <%@page pageEncoding="UTF-8"%> <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"> -<html><head><title>I2P Router Console - config update</title> +<html><head> <%@include file="css.jsp" %> +<%=cssHelper.title("config update")%> </head><body> <%@include file="summary.jsp" %> @@ -36,7 +37,7 @@ <td><input type="text" size="60" name="newsURL" value="<jsp:getProperty name="updatehelper" property="newsURL" />"></td> </tr><tr><td class= "mediumtags" align="right"><b>Refresh frequency:</b> <td><jsp:getProperty name="updatehelper" property="refreshFrequencySelectBox" /></td><tr> - <td class= "mediumtags" align="right"><b>Update policy:</b></td> + <td class= "mediumtags" align="right"><b><%=formhandler._("Update policy")%>:</b></td> <td><jsp:getProperty name="updatehelper" property="updatePolicySelectBox" /></td> <tr><td class= "mediumtags" align="right"><b>Update through the eepProxy?</b></td> <td><jsp:getProperty name="updatehelper" property="updateThroughProxy" /></td> diff --git a/apps/routerconsole/jsp/css.jsp b/apps/routerconsole/jsp/css.jsp index ed86750308884b6e4698a974b256ab53e0d48cc1..865e907235f5565ec35b8b0aef506d0c8a36a283 100644 --- a/apps/routerconsole/jsp/css.jsp +++ b/apps/routerconsole/jsp/css.jsp @@ -25,5 +25,8 @@ <link rel="shortcut icon" href="/themes/console/images/favicon.ico"> <jsp:useBean class="net.i2p.router.web.CSSHelper" id="cssHelper" scope="request" /> <jsp:setProperty name="cssHelper" property="contextId" value="<%=(String)session.getAttribute("i2p.contextId")%>" /> +<% + cssHelper.setLang(request.getParameter("lang")); +%> <link href="<%=cssHelper.getTheme(request.getHeader("User-Agent"))%>console.css" rel="stylesheet" type="text/css"> <!--[if IE]><link href="/themes/console/classic/ieshim.css" rel="stylesheet" type="text/css" /><![endif]--> diff --git a/apps/routerconsole/jsp/index.jsp b/apps/routerconsole/jsp/index.jsp index b14f8e352549d39646ce4a35bb0ecc5737e8e9c7..d2ce8ffc2d36517c0ca03aec0826c66e79c7bba4 100644 --- a/apps/routerconsole/jsp/index.jsp +++ b/apps/routerconsole/jsp/index.jsp @@ -29,5 +29,6 @@ if (System.getProperty("router.consoleNonce") == null) { <jsp:setProperty name="contenthelper" property="page" value="<%=fpath.getAbsolutePath()%>" /> <jsp:setProperty name="contenthelper" property="maxLines" value="300" /> <jsp:setProperty name="contenthelper" property="lang" value="<%=request.getParameter("lang")%>" /> + <jsp:setProperty name="contenthelper" property="contextId" value="<%=(String)session.getAttribute("i2p.contextId")%>" /> <jsp:getProperty name="contenthelper" property="content" /> </div></body></html> diff --git a/apps/routerconsole/jsp/summarynoframe.jsp b/apps/routerconsole/jsp/summarynoframe.jsp index c772a8ffc6ae0e09ca5c998717b6598177ab84dc..33a029e7657d5bd04a8520b7d027bc8dec89b5e7 100644 --- a/apps/routerconsole/jsp/summarynoframe.jsp +++ b/apps/routerconsole/jsp/summarynoframe.jsp @@ -7,126 +7,29 @@ %> <jsp:useBean class="net.i2p.router.web.SummaryHelper" id="helper" scope="request" /> <jsp:setProperty name="helper" property="contextId" value="<%=(String)session.getAttribute("i2p.contextId")%>" /> +<jsp:setProperty name="helper" property="action" value="<%=request.getParameter("action")%>" /> +<jsp:setProperty name="helper" property="updateNonce" value="<%=request.getParameter("updateNonce")%>" /> +<jsp:setProperty name="helper" property="consoleNonce" value="<%=request.getParameter("consoleNonce")%>" /> +<jsp:setProperty name="helper" property="requestURI" value="<%=request.getRequestURI()%>" /> +<jsp:setProperty name="helper" property="writer" value="<%=out%>" /> +<% +/* + * The following is required for the reseed button to work, although we probably + * only need the reseedNonce property. + */ +%> <jsp:useBean class="net.i2p.router.web.ReseedHandler" id="reseed" scope="request" /> <jsp:setProperty name="reseed" property="*" /> +<% +/* + * The following is required for the update buttons to work, although we probably + * only need the updateNonce property. + */ +%> <jsp:useBean class="net.i2p.router.web.UpdateHandler" id="update" scope="request" /> <jsp:setProperty name="update" property="*" /> <jsp:setProperty name="update" property="contextId" value="<%=(String)session.getAttribute("i2p.contextId")%>" /> -<a href="index.jsp" target="_top"><img src="/themes/console/images/i2plogo.png" alt="I2P Router Console" title="I2P Router Console"></a><hr> -<% java.io.File lpath = new java.io.File(net.i2p.I2PAppContext.getGlobalContext().getBaseDir(), "docs/toolbar.html"); - // you better have target="_top" for the links in there... - if (lpath.exists()) { %> -<jsp:useBean class="net.i2p.router.web.ContentHelper" id="linkhelper" scope="request" /> -<jsp:setProperty name="linkhelper" property="page" value="<%=lpath.getAbsolutePath()%>" /> -<jsp:setProperty name="linkhelper" property="maxLines" value="100" /> -<jsp:getProperty name="linkhelper" property="content" /> -<% } else { %> -<h3><a href="/configclients.jsp" target="_top" title="Configure startup of clients and webapps (services); manually start dormant services.">I2P Services</a></h3> -<hr><table> -<tr><td><a href="susidns/index.jsp" target="_blank" title="Manage your I2P hosts file here (I2P domain name resolution).">Addressbook</a> -<a href="i2psnark/" target="_blank" title="Built-in anonymous BitTorrent Client">Torrents</a> -<a href="susimail/susimail" target="blank" title="Anonymous webmail client.">Webmail</a> -<a href="http://127.0.0.1:7658/" target="_blank" title="Anonymous resident webserver.">Webserver</a></td></tr></table> -<hr><h3><a href="config.jsp" target="_top" title="Configure I2P Router.">I2P Internals</a></h3><hr> -<table><tr><td> -<a href="tunnels.jsp" target="_top" title="View existing tunnels and tunnel build status.">Tunnels</a> -<a href="peers.jsp" target="_top" title="Show all current peer connections.">Peers</a> -<a href="profiles.jsp" target="_top" title="Show recent peer performance profiles.">Profiles</a> -<a href="netdb.jsp" target="_top" title="Show list of all known I2P routers.">NetDB</a> -<a href="logs.jsp" target="_top" title="Health Report.">Logs</a> -<a href="jobs.jsp" target="_top" title="Show the router's workload, and how it's performing.">Jobs</a> -<a href="graphs.jsp" target="_top" title="Graph router performance.">Graphs</a> -<a href="oldstats.jsp" target="_top" title="Textual router performance statistics.">Stats</a></td></tr></table> -<% } %> -<hr><h3><a href="help.jsp" target="_top" title="I2P Router Help.">General</a></h3><hr> -<h4><a title="Your unique I2P router identity is <jsp:getProperty name="helper" property="ident" />, never reveal it to anyone" href="netdb.jsp?r=." target="_top">Local Identity</a></h4><hr> -<table><tr><td align="left"> -<b>Version:</b></td> -<td align="right"><jsp:getProperty name="helper" property="version" /></td></tr> -<tr title="How long we've been running for this session."> -<td align="left"><b>Uptime:</b></td> -<td align="right"><jsp:getProperty name="helper" property="uptime" /> -</td></tr></table> -<hr><h4><a href="config.jsp#help" target="_top" title="Help with configuring your firewall and router for optimal I2P performance."><jsp:getProperty name="helper" property="reachability" /></a></h4><hr> <% - if (helper.updateAvailable() || helper.unsignedUpdateAvailable()) { - // display all the time so we display the final failure message - out.print("<br>" + net.i2p.router.web.UpdateHandler.getStatus()); - if ("true".equals(System.getProperty("net.i2p.router.web.UpdateHandler.updateInProgress"))) { - } else if((!update.isDone()) && - request.getParameter("action") == null && - request.getParameter("updateNonce") == null && - net.i2p.router.web.ConfigRestartBean.getRestartTimeRemaining() > 12*60*1000) { - long nonce = new java.util.Random().nextLong(); - String prev = System.getProperty("net.i2p.router.web.UpdateHandler.nonce"); - if (prev != null) System.setProperty("net.i2p.router.web.UpdateHandler.noncePrev", prev); - System.setProperty("net.i2p.router.web.UpdateHandler.nonce", nonce+""); - String uri = request.getRequestURI(); - out.print("<form action=\"" + uri + "\" method=\"GET\">\n"); - out.print("<input type=\"hidden\" name=\"updateNonce\" value=\"" + nonce + "\" />\n"); - if (helper.updateAvailable()) - out.print("<button type=\"submit\" name=\"updateAction\" value=\"signed\" >Download " + helper.getUpdateVersion() + " Update</button>\n"); - if (helper.unsignedUpdateAvailable()) - out.print("<button type=\"submit\" name=\"updateAction\" value=\"Unsigned\" >Download Unsigned<br>Update " + helper.getUnsignedUpdateVersion() + "</button>\n"); - out.print("</form>\n"); - } - } + // moved to java for ease of translation and to avoid 30 copies + helper.renderSummaryBar(); %> -<p> -<%=net.i2p.router.web.ConfigRestartBean.renderStatus(request.getRequestURI(), request.getParameter("action"), request.getParameter("consoleNonce"))%> -</p><hr><h3><a href="peers.jsp" target="_top" title="Show all current peer connections.">Peers</a></h3><hr> -<table> -<tr><td align="left"><b>Active:</b></td><td align="right"><jsp:getProperty name="helper" property="activePeers" />/<jsp:getProperty name="helper" property="activeProfiles" /></td></tr> -<tr><td align="left"><b>Fast:</b></td><td align="right"><jsp:getProperty name="helper" property="fastPeers" /></td></tr> -<tr><td align="left"><b>High capacity:</b></td><td align="right"><jsp:getProperty name="helper" property="highCapacityPeers" /></td></tr> -<tr><td align="left"><b>Integrated:</b></td><td align="right"><jsp:getProperty name="helper" property="wellIntegratedPeers" /></td></tr> -<tr><td align="left"><b>Known:</b></td><td align="right"><jsp:getProperty name="helper" property="allPeers" /></td></tr> -</table><hr> -<% - if (helper.showFirewallWarning()) { - %><h4><a href="config.jsp" target="_top" title="Help with firewall configuration.">Check NAT/firewall</a></h4><% - } - boolean reseedInProgress = Boolean.valueOf(System.getProperty("net.i2p.router.web.ReseedHandler.reseedInProgress")).booleanValue(); - // If showing the reseed link is allowed - if (helper.allowReseed()) { - if (reseedInProgress) { - // While reseed occurring, show status message instead - out.print("<i>" + System.getProperty("net.i2p.router.web.ReseedHandler.statusMessage","") + "</i><br>"); - } else { - // While no reseed occurring, show reseed link - long nonce = new java.util.Random().nextLong(); - String prev = System.getProperty("net.i2p.router.web.ReseedHandler.nonce"); - if (prev != null) System.setProperty("net.i2p.router.web.ReseedHandler.noncePrev", prev); - System.setProperty("net.i2p.router.web.ReseedHandler.nonce", nonce+""); - String uri = request.getRequestURI(); - out.print("<form action=\"" + uri + "\" method=\"GET\">\n"); - out.print("<input type=\"hidden\" name=\"reseedNonce\" value=\"" + nonce + "\" />\n"); - out.print("<button type=\"submit\" >Reseed</button></form>\n"); - } - } - // If a new reseed ain't running, and the last reseed had errors, show error message - if (!reseedInProgress) { - String reseedErrorMessage = System.getProperty("net.i2p.router.web.ReseedHandler.errorMessage",""); - if (reseedErrorMessage.length() > 0) { - out.print("<i>" + reseedErrorMessage + "</i><br>"); - } - } - %> -<hr><h3><a href="config.jsp" title="Configure router bandwidth allocation." target="_top">Bandwidth in/out</a></h3><hr> -<table> -<tr><td align="left"><b>1s:</b></td><td align="right"><jsp:getProperty name="helper" property="inboundSecondKBps" />/<jsp:getProperty name="helper" property="outboundSecondKBps" />K/s</td></tr> -<tr><td align="left"><b>5m:</b></td><td align="right"><jsp:getProperty name="helper" property="inboundFiveMinuteKBps" />/<jsp:getProperty name="helper" property="outboundFiveMinuteKBps" />K/s</td></tr> -<tr><td align="left"><b>Total:</b></td><td align="right"><jsp:getProperty name="helper" property="inboundLifetimeKBps" />/<jsp:getProperty name="helper" property="outboundLifetimeKBps" />K/s</td></tr> -<tr><td align="left"><b>Used:</b></td><td align="right"><jsp:getProperty name="helper" property="inboundTransferred" />/<jsp:getProperty name="helper" property="outboundTransferred" /></td></tr></table> -<hr><h3><a href="tunnels.jsp" target="_top" title="View existing tunnels and tunnel build status.">Tunnels in/out</a></h3><hr> -<table> -<tr><td align="left"><b>Exploratory:</b></td><td align="right"><jsp:getProperty name="helper" property="inboundTunnels" />/<jsp:getProperty name="helper" property="outboundTunnels" /></td></tr> -<tr><td align="left"><b>Client:</b></td><td align="right"><jsp:getProperty name="helper" property="inboundClientTunnels" />/<jsp:getProperty name="helper" property="outboundClientTunnels" /></td></tr> -<tr><td align="left"><b>Participating:</b></td><td align="right"><jsp:getProperty name="helper" property="participatingTunnels" /></td></tr> -</table><hr><h3><a href="/jobs.jsp" target="_top" title="What's in the router's job queue?">Congestion</a></h3><hr> -<table> -<tr><td align="left"><b>Job lag:</b></td><td align="right"><jsp:getProperty name="helper" property="jobLag" /></td></tr> -<tr><td align="left"><b>Message delay:</b></td><td align="right"><jsp:getProperty name="helper" property="messageDelay" /></td></tr> -<tr><td align="left"><b>Tunnel lag:</b></td><td align="right"><jsp:getProperty name="helper" property="tunnelLag" /></td></tr> -<tr><td align="left"><b>Backlog:</b></td><td align="right"><jsp:getProperty name="helper" property="inboundBacklog" /></td></tr> -</table><hr><h4><jsp:getProperty name="helper" property="tunnelStatus" /></h4><hr><jsp:getProperty name="helper" property="destinations" /> diff --git a/apps/routerconsole/locale/messages_de.po b/apps/routerconsole/locale/messages_de.po new file mode 100644 index 0000000000000000000000000000000000000000..905828c4d097225a891fb0a58699c6c90033d429 --- /dev/null +++ b/apps/routerconsole/locale/messages_de.po @@ -0,0 +1,281 @@ +# I2P +# Copyright (C) 2009 The I2P Project +# This file is distributed under the same license as the routerconsole package. +# To contribute translations, see http://www.i2p2.de/newdevelopers +# foo <foo@bar>, 2009. +# +msgid "" +msgstr "" +"Project-Id-Version: I2P routerconsole\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2009-10-20 11:55+0000\n" +"PO-Revision-Date: 2009-10-19 12:50+0000\n" +"Last-Translator: foo <foo@bar>\n" +"Language-Team: foo <foo@bar>\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"X-Poedit-Language: German\n" + +#: ../jsp/WEB-INF/classes/net/i2p/router/web/jsp/configupdate_jsp.java:95 +msgid "config update" +msgstr "config update in german test test test" + +#: ../jsp/WEB-INF/classes/net/i2p/router/web/jsp/configupdate_jsp.java:334 +msgid "Update policy" +msgstr "Update policy in german foobarbaz" + +#: src/net/i2p/router/web/CSSHelper.java:36 +#: src/net/i2p/router/web/SummaryBarRenderer.java:26 +#: src/net/i2p/router/web/SummaryBarRenderer.java:28 +msgid "I2P Router Console" +msgstr "" + +#: src/net/i2p/router/web/ConfigUpdateHelper.java:90 +msgid "Notify only" +msgstr "Notify only in german" + +#: src/net/i2p/router/web/SummaryBarRenderer.java:42 +msgid "I2P Services" +msgstr "" + +#: src/net/i2p/router/web/SummaryBarRenderer.java:48 +msgid "Manage your I2P hosts file here (I2P domain name resolution)" +msgstr "" + +#: src/net/i2p/router/web/SummaryBarRenderer.java:50 +msgid "Addressbook" +msgstr "" + +#: src/net/i2p/router/web/SummaryBarRenderer.java:54 +msgid "Built-in anonymous BitTorrent Client" +msgstr "" + +#: src/net/i2p/router/web/SummaryBarRenderer.java:56 +msgid "Torrents" +msgstr "" + +#: src/net/i2p/router/web/SummaryBarRenderer.java:60 +msgid "Anonymous webmail client" +msgstr "" + +#: src/net/i2p/router/web/SummaryBarRenderer.java:62 +msgid "Webmail" +msgstr "" + +#: src/net/i2p/router/web/SummaryBarRenderer.java:66 +msgid "Anonymous resident webserver" +msgstr "" + +#: src/net/i2p/router/web/SummaryBarRenderer.java:68 +msgid "Webserver" +msgstr "" + +#: src/net/i2p/router/web/SummaryBarRenderer.java:72 +msgid "Configure I2P Router" +msgstr "" + +#: src/net/i2p/router/web/SummaryBarRenderer.java:74 +msgid "I2P Internals" +msgstr "" + +#: src/net/i2p/router/web/SummaryBarRenderer.java:80 +#: src/net/i2p/router/web/SummaryBarRenderer.java:344 +msgid "View existing tunnels and tunnel build status" +msgstr "" + +#: src/net/i2p/router/web/SummaryBarRenderer.java:82 +msgid "Tunnels" +msgstr "" + +#: src/net/i2p/router/web/SummaryBarRenderer.java:86 +#: src/net/i2p/router/web/SummaryBarRenderer.java:221 +msgid "Show all current peer connections" +msgstr "" + +#: src/net/i2p/router/web/SummaryBarRenderer.java:88 +#: src/net/i2p/router/web/SummaryBarRenderer.java:223 +msgid "Peers" +msgstr "" + +#: src/net/i2p/router/web/SummaryBarRenderer.java:92 +msgid "Show recent peer performance profiles" +msgstr "" + +#: src/net/i2p/router/web/SummaryBarRenderer.java:94 +msgid "Profiles" +msgstr "" + +#: src/net/i2p/router/web/SummaryBarRenderer.java:98 +msgid "Show list of all known I2P routers" +msgstr "" + +#: src/net/i2p/router/web/SummaryBarRenderer.java:100 +msgid "NetDB" +msgstr "" + +#: src/net/i2p/router/web/SummaryBarRenderer.java:104 +msgid "Health Report" +msgstr "" + +#: src/net/i2p/router/web/SummaryBarRenderer.java:106 +msgid "Logs" +msgstr "" + +#: src/net/i2p/router/web/SummaryBarRenderer.java:110 +msgid "Show the router's workload, and how it's performing" +msgstr "" + +#: src/net/i2p/router/web/SummaryBarRenderer.java:112 +msgid "Jobs" +msgstr "" + +#: src/net/i2p/router/web/SummaryBarRenderer.java:116 +msgid "Graph router performance" +msgstr "" + +#: src/net/i2p/router/web/SummaryBarRenderer.java:118 +msgid "Graphs" +msgstr "" + +#: src/net/i2p/router/web/SummaryBarRenderer.java:122 +msgid "Textual router performance statistics" +msgstr "" + +#: src/net/i2p/router/web/SummaryBarRenderer.java:124 +msgid "Stats" +msgstr "" + +#: src/net/i2p/router/web/SummaryBarRenderer.java:134 +msgid "I2P Router Help" +msgstr "" + +#: src/net/i2p/router/web/SummaryBarRenderer.java:136 +msgid "General" +msgstr "" + +#: src/net/i2p/router/web/SummaryBarRenderer.java:139 +msgid "Your unique I2P router identity is" +msgstr "" + +#: src/net/i2p/router/web/SummaryBarRenderer.java:143 +msgid "never reveal it to anyone" +msgstr "" + +#: src/net/i2p/router/web/SummaryBarRenderer.java:145 +msgid "Local Identity" +msgstr "" + +#: src/net/i2p/router/web/SummaryBarRenderer.java:150 +msgid "Version" +msgstr "" + +#: src/net/i2p/router/web/SummaryBarRenderer.java:157 +msgid "How long we've been running for this session" +msgstr "" + +#: src/net/i2p/router/web/SummaryBarRenderer.java:160 +msgid "Uptime" +msgstr "" + +#: src/net/i2p/router/web/SummaryBarRenderer.java:167 +msgid "" +"Help with configuring your firewall and router for optimal I2P performance" +msgstr "" + +#: src/net/i2p/router/web/SummaryBarRenderer.java:194 +msgid "Download" +msgstr "" + +#: src/net/i2p/router/web/SummaryBarRenderer.java:198 +#: src/net/i2p/router/web/SummaryBarRenderer.java:207 +msgid "Update" +msgstr "" + +#: src/net/i2p/router/web/SummaryBarRenderer.java:203 +msgid "Download Unsigned" +msgstr "" + +#: src/net/i2p/router/web/SummaryBarRenderer.java:229 +msgid "Active" +msgstr "" + +#: src/net/i2p/router/web/SummaryBarRenderer.java:237 +msgid "Fast" +msgstr "" + +#: src/net/i2p/router/web/SummaryBarRenderer.java:243 +msgid "High capacity" +msgstr "" + +#: src/net/i2p/router/web/SummaryBarRenderer.java:249 +msgid "Integrated" +msgstr "" + +#: src/net/i2p/router/web/SummaryBarRenderer.java:255 +msgid "Known" +msgstr "" + +#: src/net/i2p/router/web/SummaryBarRenderer.java:270 +msgid "Help with firewall configuration" +msgstr "" + +#: src/net/i2p/router/web/SummaryBarRenderer.java:272 +msgid "Check NAT/firewall" +msgstr "" + +#: src/net/i2p/router/web/SummaryBarRenderer.java:309 +msgid "Configure router bandwidth allocation" +msgstr "" + +#: src/net/i2p/router/web/SummaryBarRenderer.java:311 +msgid "Bandwidth in/out" +msgstr "" + +#: src/net/i2p/router/web/SummaryBarRenderer.java:328 +msgid "Total" +msgstr "" + +#: src/net/i2p/router/web/SummaryBarRenderer.java:336 +msgid "Used" +msgstr "" + +#: src/net/i2p/router/web/SummaryBarRenderer.java:346 +msgid "Tunnels in/out" +msgstr "" + +#: src/net/i2p/router/web/SummaryBarRenderer.java:351 +msgid "Exploratory" +msgstr "" + +#: src/net/i2p/router/web/SummaryBarRenderer.java:359 +msgid "Client" +msgstr "" + +#: src/net/i2p/router/web/SummaryBarRenderer.java:367 +msgid "Participating" +msgstr "" + +#: src/net/i2p/router/web/SummaryBarRenderer.java:373 +msgid "What's in the router's job queue?" +msgstr "" + +#: src/net/i2p/router/web/SummaryBarRenderer.java:375 +msgid "Congestion" +msgstr "" + +#: src/net/i2p/router/web/SummaryBarRenderer.java:380 +msgid "Job lag" +msgstr "" + +#: src/net/i2p/router/web/SummaryBarRenderer.java:386 +msgid "Message delay" +msgstr "" + +#: src/net/i2p/router/web/SummaryBarRenderer.java:392 +msgid "Tunnel lag" +msgstr "" + +#: src/net/i2p/router/web/SummaryBarRenderer.java:398 +msgid "Backlog" +msgstr "" diff --git a/apps/routerconsole/locale/messages_zh.po b/apps/routerconsole/locale/messages_zh.po new file mode 100644 index 0000000000000000000000000000000000000000..8456438ca91dd9b24cbc25242d045c425a1179b0 --- /dev/null +++ b/apps/routerconsole/locale/messages_zh.po @@ -0,0 +1,281 @@ +# I2P +# Copyright (C) 2009 The I2P Project +# This file is distributed under the same license as the routerconsole package. +# To contribute translations, see http://www.i2p2.de/newdevelopers +# foo <foo@bar>, 2009. +# +msgid "" +msgstr "" +"Project-Id-Version: I2P routerconsole\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2009-10-20 11:55+0000\n" +"PO-Revision-Date: 2009-10-19 12:59+0000\n" +"Last-Translator: foo <foo@bar>\n" +"Language-Team: foo <foo@par>\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"X-Poedit-Language: Chinese\n" + +#: ../jsp/WEB-INF/classes/net/i2p/router/web/jsp/configupdate_jsp.java:95 +msgid "config update" +msgstr "" + +#: ../jsp/WEB-INF/classes/net/i2p/router/web/jsp/configupdate_jsp.java:334 +msgid "Update policy" +msgstr "" + +#: src/net/i2p/router/web/CSSHelper.java:36 +#: src/net/i2p/router/web/SummaryBarRenderer.java:26 +#: src/net/i2p/router/web/SummaryBarRenderer.java:28 +msgid "I2P Router Console" +msgstr "" + +#: src/net/i2p/router/web/ConfigUpdateHelper.java:90 +msgid "Notify only" +msgstr "" + +#: src/net/i2p/router/web/SummaryBarRenderer.java:42 +msgid "I2P Services" +msgstr "" + +#: src/net/i2p/router/web/SummaryBarRenderer.java:48 +msgid "Manage your I2P hosts file here (I2P domain name resolution)" +msgstr "" + +#: src/net/i2p/router/web/SummaryBarRenderer.java:50 +msgid "Addressbook" +msgstr "" + +#: src/net/i2p/router/web/SummaryBarRenderer.java:54 +msgid "Built-in anonymous BitTorrent Client" +msgstr "" + +#: src/net/i2p/router/web/SummaryBarRenderer.java:56 +msgid "Torrents" +msgstr "" + +#: src/net/i2p/router/web/SummaryBarRenderer.java:60 +msgid "Anonymous webmail client" +msgstr "" + +#: src/net/i2p/router/web/SummaryBarRenderer.java:62 +msgid "Webmail" +msgstr "" + +#: src/net/i2p/router/web/SummaryBarRenderer.java:66 +msgid "Anonymous resident webserver" +msgstr "" + +#: src/net/i2p/router/web/SummaryBarRenderer.java:68 +msgid "Webserver" +msgstr "" + +#: src/net/i2p/router/web/SummaryBarRenderer.java:72 +msgid "Configure I2P Router" +msgstr "" + +#: src/net/i2p/router/web/SummaryBarRenderer.java:74 +msgid "I2P Internals" +msgstr "" + +#: src/net/i2p/router/web/SummaryBarRenderer.java:80 +#: src/net/i2p/router/web/SummaryBarRenderer.java:344 +msgid "View existing tunnels and tunnel build status" +msgstr "" + +#: src/net/i2p/router/web/SummaryBarRenderer.java:82 +msgid "Tunnels" +msgstr "" + +#: src/net/i2p/router/web/SummaryBarRenderer.java:86 +#: src/net/i2p/router/web/SummaryBarRenderer.java:221 +msgid "Show all current peer connections" +msgstr "" + +#: src/net/i2p/router/web/SummaryBarRenderer.java:88 +#: src/net/i2p/router/web/SummaryBarRenderer.java:223 +msgid "Peers" +msgstr "" + +#: src/net/i2p/router/web/SummaryBarRenderer.java:92 +msgid "Show recent peer performance profiles" +msgstr "" + +#: src/net/i2p/router/web/SummaryBarRenderer.java:94 +msgid "Profiles" +msgstr "" + +#: src/net/i2p/router/web/SummaryBarRenderer.java:98 +msgid "Show list of all known I2P routers" +msgstr "" + +#: src/net/i2p/router/web/SummaryBarRenderer.java:100 +msgid "NetDB" +msgstr "" + +#: src/net/i2p/router/web/SummaryBarRenderer.java:104 +msgid "Health Report" +msgstr "" + +#: src/net/i2p/router/web/SummaryBarRenderer.java:106 +msgid "Logs" +msgstr "" + +#: src/net/i2p/router/web/SummaryBarRenderer.java:110 +msgid "Show the router's workload, and how it's performing" +msgstr "" + +#: src/net/i2p/router/web/SummaryBarRenderer.java:112 +msgid "Jobs" +msgstr "" + +#: src/net/i2p/router/web/SummaryBarRenderer.java:116 +msgid "Graph router performance" +msgstr "" + +#: src/net/i2p/router/web/SummaryBarRenderer.java:118 +msgid "Graphs" +msgstr "" + +#: src/net/i2p/router/web/SummaryBarRenderer.java:122 +msgid "Textual router performance statistics" +msgstr "" + +#: src/net/i2p/router/web/SummaryBarRenderer.java:124 +msgid "Stats" +msgstr "" + +#: src/net/i2p/router/web/SummaryBarRenderer.java:134 +msgid "I2P Router Help" +msgstr "" + +#: src/net/i2p/router/web/SummaryBarRenderer.java:136 +msgid "General" +msgstr "" + +#: src/net/i2p/router/web/SummaryBarRenderer.java:139 +msgid "Your unique I2P router identity is" +msgstr "" + +#: src/net/i2p/router/web/SummaryBarRenderer.java:143 +msgid "never reveal it to anyone" +msgstr "" + +#: src/net/i2p/router/web/SummaryBarRenderer.java:145 +msgid "Local Identity" +msgstr "" + +#: src/net/i2p/router/web/SummaryBarRenderer.java:150 +msgid "Version" +msgstr "" + +#: src/net/i2p/router/web/SummaryBarRenderer.java:157 +msgid "How long we've been running for this session" +msgstr "" + +#: src/net/i2p/router/web/SummaryBarRenderer.java:160 +msgid "Uptime" +msgstr "" + +#: src/net/i2p/router/web/SummaryBarRenderer.java:167 +msgid "" +"Help with configuring your firewall and router for optimal I2P performance" +msgstr "" + +#: src/net/i2p/router/web/SummaryBarRenderer.java:194 +msgid "Download" +msgstr "" + +#: src/net/i2p/router/web/SummaryBarRenderer.java:198 +#: src/net/i2p/router/web/SummaryBarRenderer.java:207 +msgid "Update" +msgstr "" + +#: src/net/i2p/router/web/SummaryBarRenderer.java:203 +msgid "Download Unsigned" +msgstr "" + +#: src/net/i2p/router/web/SummaryBarRenderer.java:229 +msgid "Active" +msgstr "" + +#: src/net/i2p/router/web/SummaryBarRenderer.java:237 +msgid "Fast" +msgstr "" + +#: src/net/i2p/router/web/SummaryBarRenderer.java:243 +msgid "High capacity" +msgstr "" + +#: src/net/i2p/router/web/SummaryBarRenderer.java:249 +msgid "Integrated" +msgstr "" + +#: src/net/i2p/router/web/SummaryBarRenderer.java:255 +msgid "Known" +msgstr "" + +#: src/net/i2p/router/web/SummaryBarRenderer.java:270 +msgid "Help with firewall configuration" +msgstr "" + +#: src/net/i2p/router/web/SummaryBarRenderer.java:272 +msgid "Check NAT/firewall" +msgstr "" + +#: src/net/i2p/router/web/SummaryBarRenderer.java:309 +msgid "Configure router bandwidth allocation" +msgstr "" + +#: src/net/i2p/router/web/SummaryBarRenderer.java:311 +msgid "Bandwidth in/out" +msgstr "" + +#: src/net/i2p/router/web/SummaryBarRenderer.java:328 +msgid "Total" +msgstr "" + +#: src/net/i2p/router/web/SummaryBarRenderer.java:336 +msgid "Used" +msgstr "" + +#: src/net/i2p/router/web/SummaryBarRenderer.java:346 +msgid "Tunnels in/out" +msgstr "" + +#: src/net/i2p/router/web/SummaryBarRenderer.java:351 +msgid "Exploratory" +msgstr "" + +#: src/net/i2p/router/web/SummaryBarRenderer.java:359 +msgid "Client" +msgstr "" + +#: src/net/i2p/router/web/SummaryBarRenderer.java:367 +msgid "Participating" +msgstr "" + +#: src/net/i2p/router/web/SummaryBarRenderer.java:373 +msgid "What's in the router's job queue?" +msgstr "" + +#: src/net/i2p/router/web/SummaryBarRenderer.java:375 +msgid "Congestion" +msgstr "" + +#: src/net/i2p/router/web/SummaryBarRenderer.java:380 +msgid "Job lag" +msgstr "" + +#: src/net/i2p/router/web/SummaryBarRenderer.java:386 +msgid "Message delay" +msgstr "" + +#: src/net/i2p/router/web/SummaryBarRenderer.java:392 +msgid "Tunnel lag" +msgstr "" + +#: src/net/i2p/router/web/SummaryBarRenderer.java:398 +msgid "Backlog" +msgstr "" diff --git a/core/java/src/net/i2p/util/LogWriter.java b/core/java/src/net/i2p/util/LogWriter.java index 1437b9f4aebbadca5caa177bc43a6c58edb043b1..829b91d7b2b2b915fd29cbe2615dc323f007fb1b 100644 --- a/core/java/src/net/i2p/util/LogWriter.java +++ b/core/java/src/net/i2p/util/LogWriter.java @@ -153,13 +153,13 @@ class LogWriter implements Runnable { if (!parent.exists()) { boolean ok = parent.mkdirs(); if (!ok) { - System.err.println("Unable to create the parent directy: " + parent.getAbsolutePath()); - System.exit(0); + System.err.println("Unable to create the parent directory: " + parent.getAbsolutePath()); + //System.exit(0); } } if (!parent.isDirectory()) { System.err.println("wtf, we cannot put the logs in a subdirectory of a plain file! we want to stre the log as " + f.getAbsolutePath()); - System.exit(0); + //System.exit(0); } } try { diff --git a/router/java/src/net/i2p/data/i2np/I2NPMessageImpl.java b/router/java/src/net/i2p/data/i2np/I2NPMessageImpl.java index e241ff1f4a349b294d8cdbad5ad94939faef186f..757549e49a7fe86699d932374f9071c7846f9a23 100644 --- a/router/java/src/net/i2p/data/i2np/I2NPMessageImpl.java +++ b/router/java/src/net/i2p/data/i2np/I2NPMessageImpl.java @@ -362,10 +362,10 @@ public abstract class I2NPMessageImpl extends DataStructureImpl implements I2NPM return new TunnelGatewayMessage(context); case DataMessage.MESSAGE_TYPE: return new DataMessage(context); - case TunnelCreateMessage.MESSAGE_TYPE: - return new TunnelCreateMessage(context); - case TunnelCreateStatusMessage.MESSAGE_TYPE: - return new TunnelCreateStatusMessage(context); + //case TunnelCreateMessage.MESSAGE_TYPE: + // return new TunnelCreateMessage(context); + //case TunnelCreateStatusMessage.MESSAGE_TYPE: + // return new TunnelCreateStatusMessage(context); case TunnelBuildMessage.MESSAGE_TYPE: return new TunnelBuildMessage(context); case TunnelBuildReplyMessage.MESSAGE_TYPE: diff --git a/router/java/src/net/i2p/router/DummyNetworkDatabaseFacade.java b/router/java/src/net/i2p/router/DummyNetworkDatabaseFacade.java index e192e7752ca3b5638a38c2517439e516b193e1ce..5c5e5a0a45336a919124697812a2dac61a3d4ee9 100644 --- a/router/java/src/net/i2p/router/DummyNetworkDatabaseFacade.java +++ b/router/java/src/net/i2p/router/DummyNetworkDatabaseFacade.java @@ -60,6 +60,4 @@ class DummyNetworkDatabaseFacade extends NetworkDatabaseFacade { public Set<Hash> getAllRouters() { return new HashSet(_routers.keySet()); } public Set findNearestRouters(Hash key, int maxNumRouters, Set peersToIgnore) { return new HashSet(_routers.values()); } - - public void renderStatusHTML(Writer out) throws IOException {} } diff --git a/router/java/src/net/i2p/router/DummyTunnelManagerFacade.java b/router/java/src/net/i2p/router/DummyTunnelManagerFacade.java index 3a19cd1178946638d7023e10b9e466719663bfe0..4b8fb486e45f7e395c333fdb0cf0309319ad6ef3 100644 --- a/router/java/src/net/i2p/router/DummyTunnelManagerFacade.java +++ b/router/java/src/net/i2p/router/DummyTunnelManagerFacade.java @@ -10,11 +10,14 @@ package net.i2p.router; import java.io.IOException; import java.io.Writer; +import java.util.List; +import java.util.Map; import java.util.Set; import net.i2p.data.Destination; import net.i2p.data.Hash; import net.i2p.data.TunnelId; +import net.i2p.router.tunnel.pool.TunnelPool; /** * Build and maintain tunnels throughout the network. @@ -50,4 +53,10 @@ class DummyTunnelManagerFacade implements TunnelManagerFacade { public void restart() {} public void shutdown() {} public void startup() {} + + public void listPools(List<TunnelPool> out) {} + public Map<Hash, TunnelPool> getInboundClientPools() { return null; } + public Map<Hash, TunnelPool> getOutboundClientPools() { return null; } + public TunnelPool getInboundExploratoryPool() { return null; } + public TunnelPool getOutboundExploratoryPool() { return null; } } diff --git a/router/java/src/net/i2p/router/InNetMessagePool.java b/router/java/src/net/i2p/router/InNetMessagePool.java index 802aedec0a6903aa2b15dc2fbd837073a00cdb62..1d3cac39ddf59b46fa716e53934b1e12549fe374 100644 --- a/router/java/src/net/i2p/router/InNetMessagePool.java +++ b/router/java/src/net/i2p/router/InNetMessagePool.java @@ -18,8 +18,8 @@ import net.i2p.data.i2np.DatabaseLookupMessage; import net.i2p.data.i2np.DatabaseSearchReplyMessage; import net.i2p.data.i2np.DeliveryStatusMessage; import net.i2p.data.i2np.I2NPMessage; -import net.i2p.data.i2np.TunnelCreateMessage; -import net.i2p.data.i2np.TunnelCreateStatusMessage; +//import net.i2p.data.i2np.TunnelCreateMessage; +//import net.i2p.data.i2np.TunnelCreateStatusMessage; import net.i2p.data.i2np.TunnelDataMessage; import net.i2p.data.i2np.TunnelGatewayMessage; import net.i2p.util.I2PThread; @@ -74,7 +74,7 @@ public class InNetMessagePool implements Service { _context.statManager().createRateStat("inNetPool.dropped", "How often do we drop a message", "InNetPool", new long[] { 60*1000l, 60*60*1000l, 24*60*60*1000l }); _context.statManager().createRateStat("inNetPool.droppedDeliveryStatusDelay", "How long after a delivery status message is created do we receive it back again (for messages that are too slow to be handled)", "InNetPool", new long[] { 60*1000l, 60*60*1000l, 24*60*60*1000l }); _context.statManager().createRateStat("inNetPool.duplicate", "How often do we receive a duplicate message", "InNetPool", new long[] { 60*1000l, 60*60*1000l, 24*60*60*1000l }); - _context.statManager().createRateStat("inNetPool.droppedTunnelCreateStatusMessage", "How often we drop a slow-to-arrive tunnel request response", "InNetPool", new long[] { 60*60*1000l, 24*60*60*1000l }); + //_context.statManager().createRateStat("inNetPool.droppedTunnelCreateStatusMessage", "How often we drop a slow-to-arrive tunnel request response", "InNetPool", new long[] { 60*60*1000l, 24*60*60*1000l }); _context.statManager().createRateStat("inNetPool.droppedDbLookupResponseMessage", "How often we drop a slow-to-arrive db search response", "InNetPool", new long[] { 60*60*1000l, 24*60*60*1000l }); _context.statManager().createRateStat("pool.dispatchDataTime", "How long a tunnel dispatch takes", "Tunnels", new long[] { 10*60*1000l, 60*60*1000l, 24*60*60*1000l }); _context.statManager().createRateStat("pool.dispatchGatewayTime", "How long a tunnel gateway dispatch takes", "Tunnels", new long[] { 10*60*1000l, 60*60*1000l, 24*60*60*1000l }); @@ -125,8 +125,8 @@ public class InNetMessagePool implements Service { if (invalidReason != null) { int level = Log.WARN; - if (messageBody instanceof TunnelCreateMessage) - level = Log.INFO; + //if (messageBody instanceof TunnelCreateMessage) + // level = Log.INFO; if (_log.shouldLog(level)) _log.log(level, "Duplicate message received [" + messageBody.getUniqueId() + " expiring on " + exp + "]: " + messageBody.getClass().getName() + ": " + invalidReason @@ -195,10 +195,10 @@ public class InNetMessagePool implements Service { _log.warn("Dropping unhandled delivery status message created " + timeSinceSent + "ms ago: " + messageBody); _context.statManager().addRateData("inNetPool.droppedDeliveryStatusDelay", timeSinceSent, timeSinceSent); } - } else if (type == TunnelCreateStatusMessage.MESSAGE_TYPE) { - if (_log.shouldLog(Log.INFO)) - _log.info("Dropping slow tunnel create request response: " + messageBody); - _context.statManager().addRateData("inNetPool.droppedTunnelCreateStatusMessage", 1, 0); + //} else if (type == TunnelCreateStatusMessage.MESSAGE_TYPE) { + // if (_log.shouldLog(Log.INFO)) + // _log.info("Dropping slow tunnel create request response: " + messageBody); + // _context.statManager().addRateData("inNetPool.droppedTunnelCreateStatusMessage", 1, 0); } else if (type == DatabaseSearchReplyMessage.MESSAGE_TYPE) { if (_log.shouldLog(Log.INFO)) _log.info("Dropping slow db lookup response: " + messageBody); diff --git a/router/java/src/net/i2p/router/MessageHistory.java b/router/java/src/net/i2p/router/MessageHistory.java index a116aaca7cc209cc889ad894d9d31dc1af2522a3..4db6c47c68127f6b7752b00d8f5295f5661eb136 100644 --- a/router/java/src/net/i2p/router/MessageHistory.java +++ b/router/java/src/net/i2p/router/MessageHistory.java @@ -39,9 +39,8 @@ public class MessageHistory { private final static byte[] NL = System.getProperty("line.separator").getBytes(); private final static int FLUSH_SIZE = 1000; // write out at least once every 1000 entries - /** config property determining whether we want to debug with the message history */ + /** config property determining whether we want to debug with the message history - default false */ public final static String PROP_KEEP_MESSAGE_HISTORY = "router.keepHistory"; - public final static boolean DEFAULT_KEEP_MESSAGE_HISTORY = false; /** config property determining where we want to log the message history, if we're keeping one */ public final static String PROP_MESSAGE_HISTORY_FILENAME = "router.historyFilename"; public final static String DEFAULT_MESSAGE_HISTORY_FILENAME = "messageHistory.txt"; @@ -67,19 +66,8 @@ public class MessageHistory { String getFilename() { return _historyFile; } private void updateSettings() { - String keepHistory = _context.router().getConfigSetting(PROP_KEEP_MESSAGE_HISTORY); - if (keepHistory != null) { - _doLog = Boolean.TRUE.toString().equalsIgnoreCase(keepHistory); - } else { - _doLog = DEFAULT_KEEP_MESSAGE_HISTORY; - } - - String filename = null; - if (_doLog) { - filename = _context.router().getConfigSetting(PROP_MESSAGE_HISTORY_FILENAME); - if ( (filename == null) || (filename.trim().length() <= 0) ) - filename = DEFAULT_MESSAGE_HISTORY_FILENAME; - } + _doLog = Boolean.valueOf(_context.getProperty(PROP_KEEP_MESSAGE_HISTORY)).booleanValue(); + _historyFile = _context.getProperty(PROP_MESSAGE_HISTORY_FILENAME, DEFAULT_MESSAGE_HISTORY_FILENAME); } /** @@ -96,13 +84,6 @@ public class MessageHistory { _reinitializeJob.getTiming().setStartAfter(_context.clock().now()+5000); _context.jobQueue().addJob(_reinitializeJob); } else { - String filename = null; - filename = _context.router().getConfigSetting(PROP_MESSAGE_HISTORY_FILENAME); - if ( (filename == null) || (filename.trim().length() <= 0) ) - filename = DEFAULT_MESSAGE_HISTORY_FILENAME; - - _doLog = DEFAULT_KEEP_MESSAGE_HISTORY; - _historyFile = filename; _localIdent = getName(_context.routerHash()); // _unwrittenEntries = new ArrayList(64); updateSettings(); @@ -142,6 +123,7 @@ public class MessageHistory { * @param replyTunnel the tunnel sourceRoutePeer should forward the source routed message to * @param replyThrough the gateway of the tunnel that the sourceRoutePeer will be sending to */ +/******** public void requestTunnelCreate(TunnelId createTunnel, TunnelId outTunnel, Hash peerRequested, Hash nextPeer, TunnelId replyTunnel, Hash replyThrough) { if (!_doLog) return; StringBuilder buf = new StringBuilder(128); @@ -156,6 +138,7 @@ public class MessageHistory { buf.append("who forwards it through [").append(replyTunnel.getTunnelId()).append("] on [").append(getName(replyThrough)).append("]"); addEntry(buf.toString()); } +*********/ /** * The local router has received a request to join the createTunnel with the next hop being nextPeer, @@ -167,6 +150,7 @@ public class MessageHistory { * @param ok whether we will join the tunnel * @param sourceRoutePeer peer through whom we should send our garlic routed ok through */ +/********* public void receiveTunnelCreate(TunnelId createTunnel, Hash nextPeer, Date expire, boolean ok, Hash sourceRoutePeer) { if (!_doLog) return; StringBuilder buf = new StringBuilder(128); @@ -177,6 +161,7 @@ public class MessageHistory { buf.append("ok? ").append(ok).append(" expiring on [").append(getTime(expire.getTime())).append("]"); addEntry(buf.toString()); } +*********/ /** * The local router has joined the given tunnel operating in the given state. diff --git a/router/java/src/net/i2p/router/NetworkDatabaseFacade.java b/router/java/src/net/i2p/router/NetworkDatabaseFacade.java index 865fbf8ecc33340159e10ecfd58dd374527ee4e2..3885ea6d5393ba4319da352a82d99920517986f9 100644 --- a/router/java/src/net/i2p/router/NetworkDatabaseFacade.java +++ b/router/java/src/net/i2p/router/NetworkDatabaseFacade.java @@ -10,6 +10,7 @@ package net.i2p.router; import java.io.IOException; import java.io.Writer; +import java.util.Collections; import java.util.Set; import net.i2p.data.Hash; @@ -60,7 +61,10 @@ public abstract class NetworkDatabaseFacade implements Service { public int getKnownLeaseSets() { return 0; } public boolean isInitialized() { return true; } public void rescan() {} - public void renderRouterInfoHTML(Writer out, String s) throws IOException {} - public void renderLeaseSetHTML(Writer out) throws IOException {} - public void renderStatusHTML(Writer out, boolean b) throws IOException {} + /** @deprecated moved to router console */ + public void renderStatusHTML(Writer out) throws IOException {} + /** public for NetDbRenderer in routerconsole */ + public Set<LeaseSet> getLeases() { return Collections.EMPTY_SET; } + /** public for NetDbRenderer in routerconsole */ + public Set<RouterInfo> getRouters() { return Collections.EMPTY_SET; } } diff --git a/router/java/src/net/i2p/router/TunnelManagerFacade.java b/router/java/src/net/i2p/router/TunnelManagerFacade.java index e8bdc31d380460596c721d9c710207ca6f350770..148499a43d4991ed7bddeba3485837be105c6336 100644 --- a/router/java/src/net/i2p/router/TunnelManagerFacade.java +++ b/router/java/src/net/i2p/router/TunnelManagerFacade.java @@ -8,11 +8,14 @@ package net.i2p.router; * */ +import java.util.List; +import java.util.Map; import java.util.Set; import net.i2p.data.Destination; import net.i2p.data.Hash; import net.i2p.data.TunnelId; +import net.i2p.router.tunnel.pool.TunnelPool; /** * Build and maintain tunnels throughout the network. @@ -74,4 +77,14 @@ public interface TunnelManagerFacade extends Service { public void setOutboundSettings(TunnelPoolSettings settings); public void setInboundSettings(Hash client, TunnelPoolSettings settings); public void setOutboundSettings(Hash client, TunnelPoolSettings settings); + /** for TunnelRenderer in router console */ + public void listPools(List<TunnelPool> out); + /** for TunnelRenderer in router console */ + public Map<Hash, TunnelPool> getInboundClientPools(); + /** for TunnelRenderer in router console */ + public Map<Hash, TunnelPool> getOutboundClientPools(); + /** for TunnelRenderer in router console */ + public TunnelPool getInboundExploratoryPool(); + /** for TunnelRenderer in router console */ + public TunnelPool getOutboundExploratoryPool(); } diff --git a/router/java/src/net/i2p/router/networkdb/kademlia/KademliaNetworkDatabaseFacade.java b/router/java/src/net/i2p/router/networkdb/kademlia/KademliaNetworkDatabaseFacade.java index 491b823a7ba3e5bd0493c0ec97bb813bdf74b439..be55c3da6dcd10ba2705460f39a4c6cc24076a62 100644 --- a/router/java/src/net/i2p/router/networkdb/kademlia/KademliaNetworkDatabaseFacade.java +++ b/router/java/src/net/i2p/router/networkdb/kademlia/KademliaNetworkDatabaseFacade.java @@ -848,7 +848,9 @@ public class KademliaNetworkDatabaseFacade extends NetworkDatabaseFacade { return searchJob; } - private Set getLeases() { + /** public for NetDbRenderer in routerconsole */ + @Override + public Set<LeaseSet> getLeases() { if (!_initialized) return null; Set leases = new HashSet(); Set keys = getDataStore().getKeys(); @@ -860,7 +862,9 @@ public class KademliaNetworkDatabaseFacade extends NetworkDatabaseFacade { } return leases; } - private Set<RouterInfo> getRouters() { + /** public for NetDbRenderer in routerconsole */ + @Override + public Set<RouterInfo> getRouters() { if (!_initialized) return null; Set routers = new HashSet(); Set keys = getDataStore().getKeys(); @@ -897,241 +901,4 @@ public class KademliaNetworkDatabaseFacade extends NetworkDatabaseFacade { } _context.jobQueue().addJob(new StoreJob(_context, this, key, ds, onSuccess, onFailure, sendTimeout, toIgnore)); } - - class LeaseSetComparator implements Comparator { - public int compare(Object l, Object r) { - Destination dl = ((LeaseSet)l).getDestination(); - Destination dr = ((LeaseSet)r).getDestination(); - boolean locall = _context.clientManager().isLocal(dl); - boolean localr = _context.clientManager().isLocal(dr); - if (locall && !localr) return -1; - if (localr && !locall) return 1; - return dl.calculateHash().toBase64().compareTo(dr.calculateHash().toBase64()); - } - } - - class RouterInfoComparator implements Comparator { - public int compare(Object l, Object r) { - return ((RouterInfo)l).getIdentity().getHash().toBase64().compareTo(((RouterInfo)r).getIdentity().getHash().toBase64()); - } - } - - @Override - public void renderRouterInfoHTML(Writer out, String routerPrefix) throws IOException { - StringBuilder buf = new StringBuilder(4*1024); - buf.append("<h2>Network Database RouterInfo Lookup</h2>\n"); - if (".".equals(routerPrefix)) { - renderRouterInfo(buf, _context.router().getRouterInfo(), true, true); - } else { - boolean notFound = true; - Set routers = getRouters(); - for (Iterator iter = routers.iterator(); iter.hasNext(); ) { - RouterInfo ri = (RouterInfo)iter.next(); - Hash key = ri.getIdentity().getHash(); - if (key.toBase64().startsWith(routerPrefix)) { - renderRouterInfo(buf, ri, false, true); - notFound = false; - } - } - if (notFound) - buf.append("Router ").append(routerPrefix).append(" not found in network database"); - } - out.write(buf.toString()); - out.flush(); - } - - public void renderStatusHTML(Writer out) throws IOException { - renderStatusHTML(out, true); - } - - @Override - public void renderLeaseSetHTML(Writer out) throws IOException { - StringBuilder buf = new StringBuilder(4*1024); - buf.append("<h2>Network Database Contents</h2>\n"); - buf.append("<a href=\"netdb.jsp\">View RouterInfo</a>"); - buf.append("<h3>LeaseSets</h3>\n"); - Set leases = new TreeSet(new LeaseSetComparator()); - leases.addAll(getLeases()); - long now = _context.clock().now(); - for (Iterator iter = leases.iterator(); iter.hasNext(); ) { - LeaseSet ls = (LeaseSet)iter.next(); - Destination dest = ls.getDestination(); - Hash key = dest.calculateHash(); - buf.append("<b>LeaseSet: ").append(key.toBase64()); - if (_context.clientManager().isLocal(dest)) { - buf.append(" (<a href=\"tunnels.jsp#" + key.toBase64().substring(0,4) + "\">Local</a> "); - if (! _context.clientManager().shouldPublishLeaseSet(key)) - buf.append("Unpublished "); - buf.append("Destination "); - TunnelPoolSettings in = _context.tunnelManager().getInboundSettings(key); - if (in != null && in.getDestinationNickname() != null) - buf.append(in.getDestinationNickname()); - else - buf.append(dest.toBase64().substring(0, 6)); - } else { - buf.append(" (Destination "); - String host = _context.namingService().reverseLookup(dest); - if (host != null) - buf.append(host); - else - buf.append(dest.toBase64().substring(0, 6)); - } - buf.append(")</b><br>\n"); - long exp = ls.getEarliestLeaseDate()-now; - if (exp > 0) - buf.append("Expires in ").append(DataHelper.formatDuration(exp)).append("<br>\n"); - else - buf.append("Expired ").append(DataHelper.formatDuration(0-exp)).append(" ago<br>\n"); - for (int i = 0; i < ls.getLeaseCount(); i++) { - buf.append("Lease ").append(i + 1).append(": Gateway "); - buf.append(_context.commSystem().renderPeerHTML(ls.getLease(i).getGateway())); - buf.append(" Tunnel ").append(ls.getLease(i).getTunnelId().getTunnelId()).append("<br>\n"); - } - buf.append("<hr>\n"); - out.write(buf.toString()); - buf.setLength(0); - } - out.write(buf.toString()); - out.flush(); - } - - @Override - public void renderStatusHTML(Writer out, boolean full) throws IOException { - int size = getKnownRouters() * 512; - if (full) - size *= 4; - StringBuilder buf = new StringBuilder(size); - out.write("<h2>Network Database Contents (<a href=\"netdb.jsp?l=1\">View LeaseSets</a>)</h2>\n"); - if (!_initialized) { - buf.append("Not initialized\n"); - out.write(buf.toString()); - out.flush(); - return; - } - - Hash us = _context.routerHash(); - out.write("<a name=\"routers\" ></a><h3>Routers (<a href=\"netdb.jsp"); - if (full) - out.write("#routers\" >view without"); - else - out.write("?f=1#routers\" >view with"); - out.write(" stats</a>)</h3>\n"); - - RouterInfo ourInfo = _context.router().getRouterInfo(); - renderRouterInfo(buf, ourInfo, true, true); - out.write(buf.toString()); - buf.setLength(0); - - ObjectCounter<String> versions = new ObjectCounter(); - ObjectCounter<String> countries = new ObjectCounter(); - - Set routers = new TreeSet(new RouterInfoComparator()); - routers.addAll(getRouters()); - for (Iterator iter = routers.iterator(); iter.hasNext(); ) { - RouterInfo ri = (RouterInfo)iter.next(); - Hash key = ri.getIdentity().getHash(); - boolean isUs = key.equals(us); - if (!isUs) { - renderRouterInfo(buf, ri, false, full); - out.write(buf.toString()); - buf.setLength(0); - String routerVersion = ri.getOption("router.version"); - if (routerVersion != null) - versions.increment(routerVersion); - String country = _context.commSystem().getCountry(key); - if(country != null) - countries.increment(country); - } - } - - buf.append("<table border=\"0\" cellspacing=\"30\"><tr><td>"); - List<String> versionList = new ArrayList(versions.objects()); - if (versionList.size() > 0) { - Collections.sort(versionList, Collections.reverseOrder()); - buf.append("<table>\n"); - buf.append("<tr><th>Version</th><th>Count</th></tr>\n"); - for (String routerVersion : versionList) { - int num = versions.count(routerVersion); - buf.append("<tr><td align=\"center\">").append(DataHelper.stripHTML(routerVersion)); - buf.append("</td><td align=\"center\">").append(num).append("</td></tr>\n"); - } - buf.append("</table>\n"); - } - buf.append("</td><td>"); - out.write(buf.toString()); - buf.setLength(0); - - List<String> countryList = new ArrayList(countries.objects()); - if (countryList.size() > 0) { - Collections.sort(countryList); - buf.append("<table>\n"); - buf.append("<tr><th align=\"left\">Country</th><th>Count</th></tr>\n"); - for (String country : countryList) { - int num = countries.count(country); - buf.append("<tr><td><img height=\"11\" width=\"16\" alt=\"").append(country.toUpperCase()).append("\""); - buf.append(" src=\"/flags.jsp?c=").append(country).append("\"> "); - buf.append(_context.commSystem().getCountryName(country)); - buf.append("</td><td align=\"center\">").append(num).append("</td></tr>\n"); - } - buf.append("</table>\n"); - } - buf.append("</td></tr></table>"); - out.write(buf.toString()); - out.flush(); - } - - /** - * Be careful to use stripHTML for any displayed routerInfo data - * to prevent vulnerabilities - */ - private void renderRouterInfo(StringBuilder buf, RouterInfo info, boolean isUs, boolean full) { - String hash = info.getIdentity().getHash().toBase64(); - buf.append("<table><tr><th><a name=\"").append(hash.substring(0, 6)).append("\" ></a>"); - if (isUs) { - buf.append("<a name=\"our-info\" ></a><b>Our info: ").append(hash).append("</b></th></tr><tr><td>\n"); - } else { - buf.append("<b>Peer info for:</b> ").append(hash).append("\n"); - if (full) { - buf.append("[<a href=\"netdb.jsp\" >Back</a>]</th></tr><td>\n"); - } else { - buf.append("[<a href=\"netdb.jsp?r=").append(hash.substring(0, 6)).append("\" >Full entry</a>]</th></tr><td>\n"); - } - } - - long age = _context.clock().now() - info.getPublished(); - if (isUs && _context.router().isHidden()) - buf.append("<b>Hidden, Updated:</b> ").append(DataHelper.formatDuration(age)).append(" ago<br>\n"); - else if (age > 0) - buf.append("<b>Published:</b> ").append(DataHelper.formatDuration(age)).append(" ago<br>\n"); - else - buf.append("<b>Published:</b> in ").append(DataHelper.formatDuration(0-age)).append("???<br>\n"); - buf.append("<b>Address(es):</b> "); - String country = _context.commSystem().getCountry(info.getIdentity().getHash()); - if(country != null) { - buf.append("<img height=\"11\" width=\"16\" alt=\"").append(country.toUpperCase()).append("\""); - buf.append(" src=\"/flags.jsp?c=").append(country).append("\"> "); - } - for (Iterator iter = info.getAddresses().iterator(); iter.hasNext(); ) { - RouterAddress addr = (RouterAddress)iter.next(); - buf.append(DataHelper.stripHTML(addr.getTransportStyle())).append(": "); - for (Iterator optIter = addr.getOptions().keySet().iterator(); optIter.hasNext(); ) { - String name = (String)optIter.next(); - String val = addr.getOptions().getProperty(name); - buf.append('[').append(DataHelper.stripHTML(name)).append('=').append(DataHelper.stripHTML(val)).append("] "); - } - } - buf.append("</td></tr>\n"); - if (full) { - buf.append("<tr><td>Stats: <br><code>\n"); - for (Iterator iter = info.getOptions().keySet().iterator(); iter.hasNext(); ) { - String key = (String)iter.next(); - String val = info.getOption(key); - buf.append(DataHelper.stripHTML(key)).append(" = ").append(DataHelper.stripHTML(val)).append("<br>\n"); - } - buf.append("</code></td></tr>\n"); - } else { - } - buf.append("</td></tr>\n"); - } - } diff --git a/router/java/src/net/i2p/router/peermanager/PeerManagerFacadeImpl.java b/router/java/src/net/i2p/router/peermanager/PeerManagerFacadeImpl.java index 14ee5317e2a8b56b8dcffd953246197c6a8c23b8..69d5f11ce583081740ca8d15239b128cf2fb36cc 100644 --- a/router/java/src/net/i2p/router/peermanager/PeerManagerFacadeImpl.java +++ b/router/java/src/net/i2p/router/peermanager/PeerManagerFacadeImpl.java @@ -78,7 +78,7 @@ public class PeerManagerFacadeImpl implements PeerManagerFacade { return _manager.getPeersByCapability(capability); } - /** @deprecated, moved to routerconsole */ + /** @deprecated moved to routerconsole */ public void renderStatusHTML(Writer out) throws IOException { } diff --git a/router/java/src/net/i2p/router/tunnel/TunnelDispatcher.java b/router/java/src/net/i2p/router/tunnel/TunnelDispatcher.java index 147dd2f7643c46e35f0f8ae5974c8bcc84e1a886..3cb4fc9ab2f40217f2cf2db1641df65e14c2edb2 100644 --- a/router/java/src/net/i2p/router/tunnel/TunnelDispatcher.java +++ b/router/java/src/net/i2p/router/tunnel/TunnelDispatcher.java @@ -374,6 +374,9 @@ public class TunnelDispatcher implements Service { _context.statManager().addRateData("tunnel.dispatchDataTime", dispatchTime, dispatchTime); } + /** High for now, just to prevent long-lived-message attacks */ + private static final long MAX_FUTURE_EXPIRATION = 3*60*1000 + Router.CLOCK_FUDGE_FACTOR; + /** * We are the inbound tunnel gateway, so encrypt it as necessary and forward * it on. @@ -385,7 +388,10 @@ public class TunnelDispatcher implements Service { if (gw != null) { if (_log.shouldLog(Log.DEBUG)) _log.debug("dispatch where we are the inbound gateway: " + gw + ": " + msg); - if ( (msg.getMessageExpiration() < before - Router.CLOCK_FUDGE_FACTOR) || (msg.getMessage().getMessageExpiration() < before - Router.CLOCK_FUDGE_FACTOR) ) { + long minTime = before - Router.CLOCK_FUDGE_FACTOR; + long maxTime = before + MAX_FUTURE_EXPIRATION; + if ( (msg.getMessageExpiration() < minTime) || (msg.getMessage().getMessageExpiration() < minTime) || + (msg.getMessageExpiration() > maxTime) || (msg.getMessage().getMessageExpiration() > maxTime) ) { if (_log.shouldLog(Log.ERROR)) _log.error("Not dispatching a gateway message for tunnel " + msg.getTunnelId().getTunnelId() + " as the wrapper's expiration is in " + DataHelper.formatDuration(msg.getMessageExpiration()-before) @@ -463,6 +469,12 @@ public class TunnelDispatcher implements Service { _log.warn("why are you sending a tunnel message that expired " + (before-msg.getMessageExpiration()) + "ms ago? " + msg, new Exception("cause")); + } else if (msg.getMessageExpiration() > before + MAX_FUTURE_EXPIRATION) { + if (_log.shouldLog(Log.ERROR)) + _log.error("why are you sending a tunnel message that expires " + + (msg.getMessageExpiration() - before) + "ms from now? " + + msg, new Exception("cause")); + return; } long tid1 = outboundTunnel.getTunnelId(); long tid2 = (targetTunnel != null ? targetTunnel.getTunnelId() : -1); diff --git a/router/java/src/net/i2p/router/tunnel/pool/TunnelPoolManager.java b/router/java/src/net/i2p/router/tunnel/pool/TunnelPoolManager.java index f7c752c8c981ed1d61f2271888d4d8a2120cc81c..d879750359ba08992cb4effd9c856040c1dea5f4 100644 --- a/router/java/src/net/i2p/router/tunnel/pool/TunnelPoolManager.java +++ b/router/java/src/net/i2p/router/tunnel/pool/TunnelPoolManager.java @@ -391,7 +391,7 @@ public class TunnelPoolManager implements TunnelManagerFacade { } /** list of TunnelPool instances currently in play */ - void listPools(List<TunnelPool> out) { + public void listPools(List<TunnelPool> out) { synchronized (_clientInboundPools) { out.addAll(_clientInboundPools.values()); } @@ -409,227 +409,8 @@ public class TunnelPoolManager implements TunnelManagerFacade { public int getInboundBuildQueueSize() { return _executor.getInboundBuildQueueSize(); } - + /** @deprecated moved to routerconsole */ public void renderStatusHTML(Writer out) throws IOException { - out.write("<div class=\"wideload\"><h2><a name=\"exploratory\" ></a>Exploratory tunnels (<a href=\"/configtunnels.jsp#exploratory\">config</a>):</h2>\n"); - renderPool(out, _inboundExploratory, _outboundExploratory); - - List<Hash> destinations = null; - synchronized (_clientInboundPools) { - destinations = new ArrayList(_clientInboundPools.keySet()); - } - for (int i = 0; i < destinations.size(); i++) { - Hash client = destinations.get(i); - TunnelPool in = null; - TunnelPool outPool = null; - synchronized (_clientInboundPools) { - in = _clientInboundPools.get(client); - } - synchronized (_clientOutboundPools) { - outPool = _clientOutboundPools.get(client); - } - String name = (in != null ? in.getSettings().getDestinationNickname() : null); - if ( (name == null) && (outPool != null) ) - name = outPool.getSettings().getDestinationNickname(); - if (name == null) - name = client.toBase64().substring(0,4); - out.write("<h2><a name=\"" + client.toBase64().substring(0,4) - + "\" ></a>Client tunnels for " + name); - if (_context.clientManager().isLocal(client)) - out.write(" (<a href=\"/configtunnels.jsp#" + client.toBase64().substring(0,4) +"\">config</a>):</h2>\n"); - else - out.write(" (dead):</h2>\n"); - renderPool(out, in, outPool); - } - - List participating = _context.tunnelDispatcher().listParticipatingTunnels(); - Collections.sort(participating, new TunnelComparator()); - out.write("<h2><a name=\"participating\"></a>Participating tunnels:</h2><table>\n"); - out.write("<tr><th>Receive on</th><th>From</th><th>" - + "Send on</th><th>To</th><th>Expiration</th>" - + "<th>Usage</th><th>Rate</th><th>Role</th></tr>\n"); - long processed = 0; - RateStat rs = _context.statManager().getRate("tunnel.participatingMessageCount"); - if (rs != null) - processed = (long)rs.getRate(10*60*1000).getLifetimeTotalValue(); - int inactive = 0; - for (int i = 0; i < participating.size(); i++) { - HopConfig cfg = (HopConfig)participating.get(i); - if (cfg.getProcessedMessagesCount() <= 0) { - inactive++; - continue; - } - out.write("<tr>"); - if (cfg.getReceiveTunnel() != null) - out.write(" <td class=\"cells\" align=\"center\">" + cfg.getReceiveTunnel().getTunnelId() +"</td>"); - else - out.write(" <td class=\"cells\" align=\"center\">n/a</td>"); - if (cfg.getReceiveFrom() != null) - out.write(" <td class=\"cells\" align=\"right\">" + netDbLink(cfg.getReceiveFrom()) +"</td>"); - else - out.write(" <td class=\"cells\" align=\"center\"> </td>"); - if (cfg.getSendTunnel() != null) - out.write(" <td class=\"cells\" align=\"center\">" + cfg.getSendTunnel().getTunnelId() +"</td>"); - else - out.write(" <td class=\"cells\" align=\"center\"> </td>"); - if (cfg.getSendTo() != null) - out.write(" <td class=\"cells\" align=\"center\">" + netDbLink(cfg.getSendTo()) +"</td>"); - else -// out.write(" <td class=\"cells\" align=\"center\"> </td>"); - out.write(" <td class=\"cells\" align=\"center\"> </td>"); - long timeLeft = cfg.getExpiration()-_context.clock().now(); - if (timeLeft > 0) - out.write(" <td class=\"cells\" align=\"center\">" + DataHelper.formatDuration(timeLeft) + "</td>"); - else - out.write(" <td class=\"cells\" align=\"center\">(grace period)</td>"); - out.write(" <td class=\"cells\" align=\"center\">" + cfg.getProcessedMessagesCount() + "KB</td>"); - int lifetime = (int) ((_context.clock().now() - cfg.getCreation()) / 1000); - if (lifetime <= 0) - lifetime = 1; - if (lifetime > 10*60) - lifetime = 10*60; - int bps = 1024 * (int) cfg.getProcessedMessagesCount() / lifetime; - out.write(" <td class=\"cells\" align=\"center\">" + bps + "Bps</td>"); - if (cfg.getSendTo() == null) - out.write(" <td class=\"cells\" align=\"center\">Outbound Endpoint</td>"); - else if (cfg.getReceiveFrom() == null) - out.write(" <td class=\"cells\" align=\"center\">Inbound Gateway</td>"); - else - out.write(" <td class=\"cells\" align=\"center\">Participant</td>"); - out.write("</tr>\n"); - processed += cfg.getProcessedMessagesCount(); - } - out.write("</table>\n"); - out.write("<div class=\"statusnotes\"><b>Inactive participating tunnels: " + inactive + "</b></div>\n"); - out.write("<div class=\"statusnotes\"><b>Lifetime bandwidth usage: " + DataHelper.formatSize(processed*1024) + "B</b></div>\n"); - renderPeers(out); - } - - class TunnelComparator implements Comparator { - public int compare(Object l, Object r) { - return (int) (((HopConfig)r).getProcessedMessagesCount() - ((HopConfig)l).getProcessedMessagesCount()); - } - } - - private void renderPool(Writer out, TunnelPool in, TunnelPool outPool) throws IOException { - List<TunnelInfo> tunnels = null; - if (in == null) - tunnels = new ArrayList(); - else - tunnels = in.listTunnels(); - if (outPool != null) - tunnels.addAll(outPool.listTunnels()); - - long processedIn = (in != null ? in.getLifetimeProcessed() : 0); - long processedOut = (outPool != null ? outPool.getLifetimeProcessed() : 0); - - int live = 0; - int maxLength = 1; - for (int i = 0; i < tunnels.size(); i++) { - TunnelInfo info = tunnels.get(i); - if (info.getLength() > maxLength) - maxLength = info.getLength(); - } - out.write("<table><tr><th>In/Out</th><th>Expiry</th><th>Usage</th><th>Gateway</th>"); - if (maxLength > 3) { - out.write("<th align=\"center\" colspan=\"" + (maxLength - 2)); - out.write("\">Participants</th>"); - } - else if (maxLength == 3) { - out.write("<th>Participant</th>"); - } - if (maxLength > 1) { - out.write("<th>Endpoint</th>"); - } - out.write("</tr>\n"); - for (int i = 0; i < tunnels.size(); i++) { - TunnelInfo info = tunnels.get(i); - long timeLeft = info.getExpiration()-_context.clock().now(); - if (timeLeft <= 0) - continue; // don't display tunnels in their grace period - live++; - if (info.isInbound()) - out.write("<tr> <td class=\"cells\" align=\"center\"><img src=\"/themes/console/images/inbound.png\" alt=\"Inbound\" title=\"Inbound\"></td>"); - else - out.write("<tr> <td class=\"cells\" align=\"center\"><img src=\"/themes/console/images/outbound.png\" alt=\"Outbound\" title=\"Outbound\"></td>"); - out.write(" <td class=\"cells\" align=\"center\">" + DataHelper.formatDuration(timeLeft) + "</td>\n"); - out.write(" <td class=\"cells\" align=\"center\">" + info.getProcessedMessagesCount() + "KB</td>\n"); - for (int j = 0; j < info.getLength(); j++) { - Hash peer = info.getPeer(j); - TunnelId id = (info.isInbound() ? info.getReceiveTunnelId(j) : info.getSendTunnelId(j)); - if (_context.routerHash().equals(peer)) { - out.write(" <td class=\"cells\" align=\"center\">" + (id == null ? "" : "" + id) + "</td>"); - } else { - String cap = getCapacity(peer); - out.write(" <td class=\"cells\" align=\"center\">" + netDbLink(peer) + (id == null ? "" : " " + id) + cap + "</td>"); - } - if (info.getLength() < maxLength && (info.getLength() == 1 || j == info.getLength() - 2)) { - for (int k = info.getLength(); k < maxLength; k++) - out.write(" <td class=\"cells\" align=\"center\"> </td>"); - } - } - out.write("</tr>\n"); - - if (info.isInbound()) - processedIn += info.getProcessedMessagesCount(); - else - processedOut += info.getProcessedMessagesCount(); - } - out.write("</table>\n"); - if (in != null) { - List pending = in.listPending(); - if (pending.size() > 0) - out.write("<div class=\"statusnotes\"><center><b>Build in progress: " + pending.size() + " inbound</b></center></div>\n"); - live += pending.size(); - } - if (outPool != null) { - List pending = outPool.listPending(); - if (pending.size() > 0) - out.write("<div class=\"statusnotes\"><center><b>Build in progress: " + pending.size() + " outbound</b></center></div>\n"); - live += pending.size(); - } - if (live <= 0) - out.write("<div class=\"statusnotes\"><center><b>No tunnels; waiting for the grace period to end.</center></b></div>\n"); - out.write("<div class=\"statusnotes\"><center><b>Lifetime bandwidth usage: " + DataHelper.formatSize(processedIn*1024) + "B in, " + - DataHelper.formatSize(processedOut*1024) + "B out</b></center></div>"); - } - - private void renderPeers(Writer out) throws IOException { - // count up the peers in the local pools - ObjectCounter<Hash> lc = new ObjectCounter(); - int tunnelCount = countTunnelsPerPeer(lc); - - // count up the peers in the participating tunnels - ObjectCounter<Hash> pc = new ObjectCounter(); - int partCount = countParticipatingPerPeer(pc); - - Set<Hash> peers = new HashSet(lc.objects()); - peers.addAll(pc.objects()); - List<Hash> peerList = new ArrayList(peers); - Collections.sort(peerList, new HashComparator()); - - out.write("<h2><a name=\"peers\"></a>Tunnel Counts By Peer:</h2>\n"); - out.write("<table><tr><th>Peer</th><th>Expl. + Client</th><th>% of total</th><th>Part. from + to</th><th>% of total</th></tr>\n"); - for (Hash h : peerList) { - out.write("<tr> <td class=\"cells\" align=\"center\">"); - out.write(netDbLink(h)); - out.write(" <td class=\"cells\" align=\"center\">" + lc.count(h)); - out.write(" <td class=\"cells\" align=\"center\">"); - if (tunnelCount > 0) - out.write("" + (lc.count(h) * 100 / tunnelCount)); - else - out.write('0'); - out.write(" <td class=\"cells\" align=\"center\">" + pc.count(h)); - out.write(" <td class=\"cells\" align=\"center\">"); - if (partCount > 0) - out.write("" + (pc.count(h) * 100 / partCount)); - else - out.write('0'); - out.write('\n'); - } - out.write("<tr class=\"tablefooter\"> <td align=\"center\"><b>Tunnels</b> <td align=\"center\"><b>" + tunnelCount); - out.write("</b> <td> </td> <td align=\"center\"><b>" + partCount); - out.write("</b> <td> </td></tr></table></div>\n"); } /** @return total number of non-fallback expl. + client tunnels */ @@ -682,39 +463,27 @@ public class TunnelPoolManager implements TunnelManagerFacade { return rv; } - /** @return total number of part. tunnels */ - private int countParticipatingPerPeer(ObjectCounter<Hash> pc) { - List<HopConfig> participating = _context.tunnelDispatcher().listParticipatingTunnels(); - for (HopConfig cfg : participating) { - Hash from = cfg.getReceiveFrom(); - if (from != null) - pc.increment(from); - Hash to = cfg.getSendTo(); - if (to != null) - pc.increment(to); + /** for TunnelRenderer in router console */ + public Map<Hash, TunnelPool> getInboundClientPools() { + synchronized (_clientInboundPools) { + return new HashMap(_clientInboundPools); } - return participating.size(); } - class HashComparator implements Comparator { - public int compare(Object l, Object r) { - return ((Hash)l).toBase64().compareTo(((Hash)r).toBase64()); + /** for TunnelRenderer in router console */ + public Map<Hash, TunnelPool> getOutboundClientPools() { + synchronized (_clientOutboundPools) { + return new HashMap(_clientOutboundPools); } } - private String getCapacity(Hash peer) { - RouterInfo info = _context.netDb().lookupRouterInfoLocally(peer); - if (info != null) { - String caps = info.getCapabilities(); - for (char c = Router.CAPABILITY_BW12; c <= Router.CAPABILITY_BW256; c++) { - if (caps.indexOf(c) >= 0) - return " " + c; - } - } - return ""; + /** for TunnelRenderer in router console */ + public TunnelPool getInboundExploratoryPool() { + return _inboundExploratory; } - private String netDbLink(Hash peer) { - return _context.commSystem().renderPeerHTML(peer); + /** for TunnelRenderer in router console */ + public TunnelPool getOutboundExploratoryPool() { + return _outboundExploratory; } } diff --git a/router/java/src/net/i2p/data/i2np/TunnelCreateMessage.java b/router/java/test/net/i2p/data/i2np/TunnelCreateMessage.java similarity index 100% rename from router/java/src/net/i2p/data/i2np/TunnelCreateMessage.java rename to router/java/test/net/i2p/data/i2np/TunnelCreateMessage.java diff --git a/router/java/src/net/i2p/data/i2np/TunnelCreateStatusMessage.java b/router/java/test/net/i2p/data/i2np/TunnelCreateStatusMessage.java similarity index 100% rename from router/java/src/net/i2p/data/i2np/TunnelCreateStatusMessage.java rename to router/java/test/net/i2p/data/i2np/TunnelCreateStatusMessage.java