diff --git a/apps/routerconsole/java/src/net/i2p/router/web/helpers/TunnelRenderer.java b/apps/routerconsole/java/src/net/i2p/router/web/helpers/TunnelRenderer.java index 96bbfd4fe..1aad8cb17 100644 --- a/apps/routerconsole/java/src/net/i2p/router/web/helpers/TunnelRenderer.java +++ b/apps/routerconsole/java/src/net/i2p/router/web/helpers/TunnelRenderer.java @@ -21,6 +21,7 @@ import net.i2p.router.tunnel.HopConfig; import net.i2p.router.tunnel.pool.TunnelPool; import net.i2p.router.web.HelperBase; import net.i2p.router.web.Messages; +import net.i2p.stat.Rate; import net.i2p.stat.RateStat; /** @@ -36,8 +37,14 @@ class TunnelRenderer { } public void renderStatusHTML(Writer out) throws IOException { - out.write("

" + _t("Exploratory tunnels") + " [" + _t("configure") + "]

\n"); - renderPool(out, _context.tunnelManager().getInboundExploratoryPool(), _context.tunnelManager().getOutboundExploratoryPool()); + TunnelPool ei = _context.tunnelManager().getInboundExploratoryPool(); + TunnelPool eo = _context.tunnelManager().getOutboundExploratoryPool(); + out.write("

" + _t("Exploratory tunnels")); + // links are set to float:right in CSS so they will be displayed in reverse order + out.write(" [" + _t("configure") + "]"); + writeGraphLinks(out, ei, eo); + out.write("

\n"); + renderPool(out, ei, eo); List destinations = null; Map clientInboundPools = _context.tunnelManager().getInboundClientPools(); @@ -64,10 +71,14 @@ class TunnelRenderer { name = client.toBase64().substring(0,4); out.write("

" + _t("Client tunnels for") + ' ' + DataHelper.escapeHTML(_t(name))); - if (isLocal) - out.write(" [" + _t("configure") + "]

\n"); - else + if (isLocal) { + // links are set to float:right in CSS so they will be displayed in reverse order + out.write(" [" + _t("configure") + "]"); + writeGraphLinks(out, in, outPool); + out.write("\n"); + } else { out.write(" (" + _t("dead") + ")\n"); + } if (in != null) { // list aliases Set aliases = in.getSettings().getAliases(); @@ -167,7 +178,7 @@ class TunnelRenderer { else if (displayed <= 0) out.write("
" + _t("none") + "
\n"); out.write("
" + _t("Lifetime bandwidth usage") + ":  " + DataHelper.formatSize2Decimal(processed*1024) + "B
\n"); - } else { + } else { // bwShare > 12 out.write("
" + _t("Not enough shared bandwidth to build participating tunnels.") + " [" + _t("Configure") + "]
\n"); } @@ -202,6 +213,39 @@ class TunnelRenderer { } } + /** @since 0.9.35 */ + private void writeGraphLinks(Writer out, TunnelPool in, TunnelPool outPool) throws IOException { + if (in == null || outPool == null) + return; + String irname = in.getRateName(); + String orname = outPool.getRateName(); + RateStat irs = _context.statManager().getRate(irname); + RateStat ors = _context.statManager().getRate(orname); + if (irs == null || ors == null) + return; + Rate ir = irs.getRate(5*60*1000L); + Rate or = ors.getRate(5*60*1000L); + if (ir == null || or == null) + return; + final String tgd = _t("Graph Data"); + final String tcg = _t("Configure Graph Display"); + // links are set to float:right in CSS so they will be displayed in reverse order + if (or.getSummaryListener() != null) { + out.write("" + + "\"""); + } else { + out.write("" + + "\"""); + } + if (ir.getSummaryListener() != null) { + out.write("" + + "\"" "); + } else { + out.write("" + + "\"""); + } + } + private void renderPool(Writer out, TunnelPool in, TunnelPool outPool) throws IOException { List tunnels = null; if (in == null) @@ -235,6 +279,8 @@ class TunnelRenderer { out.write("" + _t("Endpoint") + ""); } out.write("\n"); + final String tib = _t("Inbound"); + final String tob = _t("Outbound"); for (int i = 0; i < tunnels.size(); i++) { TunnelInfo info = tunnels.get(i); long timeLeft = info.getExpiration()-_context.clock().now(); @@ -243,11 +289,11 @@ class TunnelRenderer { live++; boolean isInbound = info.isInbound(); if (isInbound) - out.write("\"Inbound\""); + out.write("\"""); else - out.write("\"Outbound\""); + out.write("\"""); out.write("" + DataHelper.formatDuration2(timeLeft) + "\n"); int count = info.getProcessedMessagesCount() * 1024 / 1000; out.write("" + count + " KB\n"); @@ -293,7 +339,7 @@ class TunnelRenderer { // PooledTunnelCreatorConfig List pending = in.listPending(); if (!pending.isEmpty()) { - out.write("
" + _t("Build in progress") + ":  " + pending.size() + " " + _t("inbound") + "
\n"); + out.write("
" + _t("Build in progress") + ":  " + pending.size() + " " + tib + "
\n"); live += pending.size(); } } @@ -301,7 +347,7 @@ class TunnelRenderer { // PooledTunnelCreatorConfig List pending = outPool.listPending(); if (!pending.isEmpty()) { - out.write("
" + _t("Build in progress") + ":  " + pending.size() + " " + _t("outbound") + "
\n"); + out.write("
" + _t("Build in progress") + ":  " + pending.size() + " " + tob + "
\n"); live += pending.size(); } } diff --git a/router/java/src/net/i2p/router/tunnel/pool/TunnelPool.java b/router/java/src/net/i2p/router/tunnel/pool/TunnelPool.java index 01e3824b4..7c9cb893f 100644 --- a/router/java/src/net/i2p/router/tunnel/pool/TunnelPool.java +++ b/router/java/src/net/i2p/router/tunnel/pool/TunnelPool.java @@ -130,6 +130,15 @@ public class TunnelPool { } } + /** + * RateStat name for the bandwidth graph + * @return non-null + * @since 0.9.35 + */ + public String getRateName() { + return _rateName; + } + private void refreshSettings() { if (!_settings.isExploratory()) return; // don't override client specified settings