forked from I2P_Developers/i2p.i2p
move TunnelPoolManager renderStatusHTML to routerconsole
This commit is contained in:
@ -9,13 +9,14 @@ public class TunnelHelper extends HelperBase {
|
|||||||
public TunnelHelper() {}
|
public TunnelHelper() {}
|
||||||
|
|
||||||
public String getTunnelSummary() {
|
public String getTunnelSummary() {
|
||||||
|
TunnelRenderer renderer = new TunnelRenderer(_context);
|
||||||
try {
|
try {
|
||||||
if (_out != null) {
|
if (_out != null) {
|
||||||
_context.tunnelManager().renderStatusHTML(_out);
|
renderer.renderStatusHTML(_out);
|
||||||
return "";
|
return "";
|
||||||
} else {
|
} else {
|
||||||
ByteArrayOutputStream baos = new ByteArrayOutputStream(32*1024);
|
ByteArrayOutputStream baos = new ByteArrayOutputStream(32*1024);
|
||||||
_context.tunnelManager().renderStatusHTML(new OutputStreamWriter(baos));
|
renderer.renderStatusHTML(new OutputStreamWriter(baos));
|
||||||
return new String(baos.toByteArray());
|
return new String(baos.toByteArray());
|
||||||
}
|
}
|
||||||
} catch (IOException ioe) {
|
} catch (IOException ioe) {
|
||||||
|
@ -0,0 +1,313 @@
|
|||||||
|
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);
|
||||||
|
}
|
||||||
|
}
|
@ -10,11 +10,14 @@ package net.i2p.router;
|
|||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.io.Writer;
|
import java.io.Writer;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
|
||||||
import net.i2p.data.Destination;
|
import net.i2p.data.Destination;
|
||||||
import net.i2p.data.Hash;
|
import net.i2p.data.Hash;
|
||||||
import net.i2p.data.TunnelId;
|
import net.i2p.data.TunnelId;
|
||||||
|
import net.i2p.router.tunnel.pool.TunnelPool;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Build and maintain tunnels throughout the network.
|
* Build and maintain tunnels throughout the network.
|
||||||
@ -50,4 +53,10 @@ class DummyTunnelManagerFacade implements TunnelManagerFacade {
|
|||||||
public void restart() {}
|
public void restart() {}
|
||||||
public void shutdown() {}
|
public void shutdown() {}
|
||||||
public void startup() {}
|
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; }
|
||||||
}
|
}
|
||||||
|
@ -8,11 +8,14 @@ package net.i2p.router;
|
|||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
|
||||||
import net.i2p.data.Destination;
|
import net.i2p.data.Destination;
|
||||||
import net.i2p.data.Hash;
|
import net.i2p.data.Hash;
|
||||||
import net.i2p.data.TunnelId;
|
import net.i2p.data.TunnelId;
|
||||||
|
import net.i2p.router.tunnel.pool.TunnelPool;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Build and maintain tunnels throughout the network.
|
* Build and maintain tunnels throughout the network.
|
||||||
@ -74,4 +77,14 @@ public interface TunnelManagerFacade extends Service {
|
|||||||
public void setOutboundSettings(TunnelPoolSettings settings);
|
public void setOutboundSettings(TunnelPoolSettings settings);
|
||||||
public void setInboundSettings(Hash client, TunnelPoolSettings settings);
|
public void setInboundSettings(Hash client, TunnelPoolSettings settings);
|
||||||
public void setOutboundSettings(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();
|
||||||
}
|
}
|
||||||
|
@ -391,7 +391,7 @@ public class TunnelPoolManager implements TunnelManagerFacade {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/** list of TunnelPool instances currently in play */
|
/** list of TunnelPool instances currently in play */
|
||||||
void listPools(List<TunnelPool> out) {
|
public void listPools(List<TunnelPool> out) {
|
||||||
synchronized (_clientInboundPools) {
|
synchronized (_clientInboundPools) {
|
||||||
out.addAll(_clientInboundPools.values());
|
out.addAll(_clientInboundPools.values());
|
||||||
}
|
}
|
||||||
@ -409,227 +409,8 @@ public class TunnelPoolManager implements TunnelManagerFacade {
|
|||||||
|
|
||||||
public int getInboundBuildQueueSize() { return _executor.getInboundBuildQueueSize(); }
|
public int getInboundBuildQueueSize() { return _executor.getInboundBuildQueueSize(); }
|
||||||
|
|
||||||
|
/** @deprecated moved to routerconsole */
|
||||||
public void renderStatusHTML(Writer out) throws IOException {
|
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 */
|
/** @return total number of non-fallback expl. + client tunnels */
|
||||||
@ -682,39 +463,27 @@ public class TunnelPoolManager implements TunnelManagerFacade {
|
|||||||
return rv;
|
return rv;
|
||||||
}
|
}
|
||||||
|
|
||||||
/** @return total number of part. tunnels */
|
/** for TunnelRenderer in router console */
|
||||||
private int countParticipatingPerPeer(ObjectCounter<Hash> pc) {
|
public Map<Hash, TunnelPool> getInboundClientPools() {
|
||||||
List<HopConfig> participating = _context.tunnelDispatcher().listParticipatingTunnels();
|
synchronized (_clientInboundPools) {
|
||||||
for (HopConfig cfg : participating) {
|
return new HashMap(_clientInboundPools);
|
||||||
Hash from = cfg.getReceiveFrom();
|
|
||||||
if (from != null)
|
|
||||||
pc.increment(from);
|
|
||||||
Hash to = cfg.getSendTo();
|
|
||||||
if (to != null)
|
|
||||||
pc.increment(to);
|
|
||||||
}
|
|
||||||
return participating.size();
|
|
||||||
}
|
|
||||||
|
|
||||||
class HashComparator implements Comparator {
|
|
||||||
public int compare(Object l, Object r) {
|
|
||||||
return ((Hash)l).toBase64().compareTo(((Hash)r).toBase64());
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private String getCapacity(Hash peer) {
|
/** for TunnelRenderer in router console */
|
||||||
RouterInfo info = _context.netDb().lookupRouterInfoLocally(peer);
|
public Map<Hash, TunnelPool> getOutboundClientPools() {
|
||||||
if (info != null) {
|
synchronized (_clientOutboundPools) {
|
||||||
String caps = info.getCapabilities();
|
return new HashMap(_clientOutboundPools);
|
||||||
for (char c = Router.CAPABILITY_BW12; c <= Router.CAPABILITY_BW256; c++) {
|
|
||||||
if (caps.indexOf(c) >= 0)
|
|
||||||
return " " + c;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
return "";
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private String netDbLink(Hash peer) {
|
/** for TunnelRenderer in router console */
|
||||||
return _context.commSystem().renderPeerHTML(peer);
|
public TunnelPool getInboundExploratoryPool() {
|
||||||
|
return _inboundExploratory;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** for TunnelRenderer in router console */
|
||||||
|
public TunnelPool getOutboundExploratoryPool() {
|
||||||
|
return _outboundExploratory;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user