forked from I2P_Developers/i2p.i2p
propagate from branch 'i2p.i2p.zzz.test' (head efc35e19029b7d92265f25eb024114737b6545e1)
to branch 'i2p.i2p' (head bbf149917e39bdd2f53246c238d440369498ae09)
This commit is contained in:
@ -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:
|
||||
|
@ -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 {}
|
||||
}
|
||||
|
@ -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; }
|
||||
}
|
||||
|
@ -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);
|
||||
|
@ -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.
|
||||
|
@ -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; }
|
||||
}
|
||||
|
@ -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();
|
||||
}
|
||||
|
@ -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");
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -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 {
|
||||
}
|
||||
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
}
|
||||
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> getInboundClientPools() {
|
||||
synchronized (_clientInboundPools) {
|
||||
return new HashMap(_clientInboundPools);
|
||||
}
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
/** for TunnelRenderer in router console */
|
||||
public Map<Hash, TunnelPool> getOutboundClientPools() {
|
||||
synchronized (_clientOutboundPools) {
|
||||
return new HashMap(_clientOutboundPools);
|
||||
}
|
||||
return "";
|
||||
}
|
||||
|
||||
private String netDbLink(Hash peer) {
|
||||
return _context.commSystem().renderPeerHTML(peer);
|
||||
/** for TunnelRenderer in router console */
|
||||
public TunnelPool getInboundExploratoryPool() {
|
||||
return _inboundExploratory;
|
||||
}
|
||||
|
||||
/** for TunnelRenderer in router console */
|
||||
public TunnelPool getOutboundExploratoryPool() {
|
||||
return _outboundExploratory;
|
||||
}
|
||||
}
|
||||
|
Reference in New Issue
Block a user