forked from I2P_Developers/i2p.i2p
* i2psnark:
- Remove static SnarkManager instance - Allow DHT-only torrents - DHT debugging
This commit is contained in:
@ -40,4 +40,5 @@ interface CoordinatorListener
|
|||||||
public boolean overUploadLimit(int uploaders);
|
public boolean overUploadLimit(int uploaders);
|
||||||
public boolean overUpBWLimit();
|
public boolean overUpBWLimit();
|
||||||
public boolean overUpBWLimit(long total);
|
public boolean overUpBWLimit(long total);
|
||||||
|
public void addMessage(String message);
|
||||||
}
|
}
|
||||||
|
@ -87,7 +87,6 @@ public class I2PSnarkUtil {
|
|||||||
//setProxy("127.0.0.1", 4444);
|
//setProxy("127.0.0.1", 4444);
|
||||||
setI2CPConfig("127.0.0.1", 7654, null);
|
setI2CPConfig("127.0.0.1", 7654, null);
|
||||||
_shitlist = new ConcurrentHashSet();
|
_shitlist = new ConcurrentHashSet();
|
||||||
_configured = false;
|
|
||||||
_maxUploaders = Snark.MAX_TOTAL_UPLOADERS;
|
_maxUploaders = Snark.MAX_TOTAL_UPLOADERS;
|
||||||
_maxUpBW = DEFAULT_MAX_UP_BW;
|
_maxUpBW = DEFAULT_MAX_UP_BW;
|
||||||
_maxConnections = MAX_CONNECTIONS;
|
_maxConnections = MAX_CONNECTIONS;
|
||||||
@ -248,7 +247,6 @@ public class I2PSnarkUtil {
|
|||||||
_manager = I2PSocketManagerFactory.createManager(_i2cpHost, _i2cpPort, opts);
|
_manager = I2PSocketManagerFactory.createManager(_i2cpHost, _i2cpPort, opts);
|
||||||
_connecting = false;
|
_connecting = false;
|
||||||
}
|
}
|
||||||
// FIXME this only instantiates krpc once, left stuck with old manager
|
|
||||||
if (_shouldUseDHT && _manager != null && _dht == null)
|
if (_shouldUseDHT && _manager != null && _dht == null)
|
||||||
_dht = new KRPC(_context, _manager.getSession());
|
_dht = new KRPC(_context, _manager.getSession());
|
||||||
return (_manager != null);
|
return (_manager != null);
|
||||||
|
@ -890,8 +890,10 @@ class PeerCoordinator implements PeerListener
|
|||||||
snark.stopTorrent();
|
snark.stopTorrent();
|
||||||
String msg = "Error reading the storage (piece " + piece + ") for " + metainfo.getName() + ": " + ioe;
|
String msg = "Error reading the storage (piece " + piece + ") for " + metainfo.getName() + ": " + ioe;
|
||||||
_log.error(msg, ioe);
|
_log.error(msg, ioe);
|
||||||
SnarkManager.instance().addMessage(msg);
|
if (listener != null) {
|
||||||
SnarkManager.instance().addMessage("Fatal storage error: Stopping torrent " + metainfo.getName());
|
listener.addMessage(msg);
|
||||||
|
listener.addMessage("Fatal storage error: Stopping torrent " + metainfo.getName());
|
||||||
|
}
|
||||||
throw new RuntimeException(msg, ioe);
|
throw new RuntimeException(msg, ioe);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -970,8 +972,10 @@ class PeerCoordinator implements PeerListener
|
|||||||
snark.stopTorrent();
|
snark.stopTorrent();
|
||||||
String msg = "Error writing storage (piece " + piece + ") for " + metainfo.getName() + ": " + ioe;
|
String msg = "Error writing storage (piece " + piece + ") for " + metainfo.getName() + ": " + ioe;
|
||||||
_log.error(msg, ioe);
|
_log.error(msg, ioe);
|
||||||
SnarkManager.instance().addMessage(msg);
|
if (listener != null) {
|
||||||
SnarkManager.instance().addMessage("Fatal storage error: Stopping torrent " + metainfo.getName());
|
listener.addMessage(msg);
|
||||||
|
listener.addMessage("Fatal storage error: Stopping torrent " + metainfo.getName());
|
||||||
|
}
|
||||||
throw new RuntimeException(msg, ioe);
|
throw new RuntimeException(msg, ioe);
|
||||||
}
|
}
|
||||||
wantedPieces.remove(p);
|
wantedPieces.remove(p);
|
||||||
|
@ -1179,6 +1179,15 @@ public class Snark
|
|||||||
//System.exit(0);
|
//System.exit(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* StorageListener and CoordinatorListener callback
|
||||||
|
* @since 0.9.2
|
||||||
|
*/
|
||||||
|
public void addMessage(String message) {
|
||||||
|
if (completeListener != null)
|
||||||
|
completeListener.addMessage(this, message);
|
||||||
|
}
|
||||||
|
|
||||||
public interface CompleteListener {
|
public interface CompleteListener {
|
||||||
public void torrentComplete(Snark snark);
|
public void torrentComplete(Snark snark);
|
||||||
public void updateStatus(Snark snark);
|
public void updateStatus(Snark snark);
|
||||||
@ -1198,6 +1207,11 @@ public class Snark
|
|||||||
*/
|
*/
|
||||||
public void fatal(Snark snark, String error);
|
public void fatal(Snark snark, String error);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @since 0.9.2
|
||||||
|
*/
|
||||||
|
public void addMessage(Snark snark, String message);
|
||||||
|
|
||||||
// not really listeners but the easiest way to get back to an optional SnarkManager
|
// not really listeners but the easiest way to get back to an optional SnarkManager
|
||||||
public long getSavedTorrentTime(Snark snark);
|
public long getSavedTorrentTime(Snark snark);
|
||||||
public BitField getSavedTorrentBitField(Snark snark);
|
public BitField getSavedTorrentBitField(Snark snark);
|
||||||
|
@ -123,15 +123,11 @@ public class SnarkManager implements Snark.CompleteListener {
|
|||||||
/** comma delimited list of name=announceURL=baseURL for the trackers to be displayed */
|
/** comma delimited list of name=announceURL=baseURL for the trackers to be displayed */
|
||||||
public static final String PROP_TRACKERS = "i2psnark.trackers";
|
public static final String PROP_TRACKERS = "i2psnark.trackers";
|
||||||
|
|
||||||
private static final SnarkManager _instance = new SnarkManager();
|
public SnarkManager(I2PAppContext ctx) {
|
||||||
|
|
||||||
public static SnarkManager instance() { return _instance; }
|
|
||||||
|
|
||||||
private SnarkManager() {
|
|
||||||
_snarks = new ConcurrentHashMap();
|
_snarks = new ConcurrentHashMap();
|
||||||
_magnets = new ConcurrentHashSet();
|
_magnets = new ConcurrentHashSet();
|
||||||
_addSnarkLock = new Object();
|
_addSnarkLock = new Object();
|
||||||
_context = I2PAppContext.getGlobalContext();
|
_context = ctx;
|
||||||
_log = _context.logManager().getLog(SnarkManager.class);
|
_log = _context.logManager().getLog(SnarkManager.class);
|
||||||
_messages = new LinkedBlockingQueue();
|
_messages = new LinkedBlockingQueue();
|
||||||
_util = new I2PSnarkUtil(_context);
|
_util = new I2PSnarkUtil(_context);
|
||||||
@ -824,13 +820,13 @@ public class SnarkManager implements Snark.CompleteListener {
|
|||||||
if (info.isPrivate()) {
|
if (info.isPrivate()) {
|
||||||
addMessage(_("ERROR - No I2P trackers in private torrent \"{0}\"", info.getName()));
|
addMessage(_("ERROR - No I2P trackers in private torrent \"{0}\"", info.getName()));
|
||||||
} else if (_util.shouldUseOpenTrackers() && _util.getOpenTrackers() != null) {
|
} else if (_util.shouldUseOpenTrackers() && _util.getOpenTrackers() != null) {
|
||||||
//addMessage(_("Warning - No I2P trackers in \"{0}\", will announce to I2P open trackers and DHT only.", info.getName()));
|
addMessage(_("Warning - No I2P trackers in \"{0}\", will announce to I2P open trackers and DHT only.", info.getName()));
|
||||||
addMessage(_("Warning - No I2P trackers in \"{0}\", will announce to I2P open trackers only.", info.getName()));
|
//addMessage(_("Warning - No I2P trackers in \"{0}\", will announce to I2P open trackers only.", info.getName()));
|
||||||
//} else if (_util.getDHT() != null) {
|
} else if (_util.getDHT() != null) {
|
||||||
// addMessage(_("Warning - No I2P trackers in \"{0}\", and open trackers are disabled, will announce to DHT only.", info.getName()));
|
addMessage(_("Warning - No I2P trackers in \"{0}\", and open trackers are disabled, will announce to DHT only.", info.getName()));
|
||||||
} else {
|
} else {
|
||||||
//addMessage(_("Warning - No I2P trackers in \"{0}\", and DHT and open trackers are disabled, you should enable open trackers or DHT before starting the torrent.", info.getName()));
|
addMessage(_("Warning - No I2P trackers in \"{0}\", and DHT and open trackers are disabled, you should enable open trackers or DHT before starting the torrent.", info.getName()));
|
||||||
addMessage(_("Warning - No I2P Trackers found in \"{0}\". Make sure Open Tracker is enabled before starting this torrent.", info.getName()));
|
//addMessage(_("Warning - No I2P Trackers found in \"{0}\". Make sure Open Tracker is enabled before starting this torrent.", info.getName()));
|
||||||
dontAutoStart = true;
|
dontAutoStart = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1456,6 +1452,14 @@ public class SnarkManager implements Snark.CompleteListener {
|
|||||||
addMessage(_("Error on torrent {0}", snark.getName()) + ": " + error);
|
addMessage(_("Error on torrent {0}", snark.getName()) + ": " + error);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A Snark.CompleteListener method.
|
||||||
|
* @since 0.9.2
|
||||||
|
*/
|
||||||
|
public void addMessage(Snark snark, String message) {
|
||||||
|
addMessage(message);
|
||||||
|
}
|
||||||
|
|
||||||
// End Snark.CompleteListeners
|
// End Snark.CompleteListeners
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -740,7 +740,8 @@ public class Storage
|
|||||||
} else {
|
} else {
|
||||||
String msg = "File '" + names[i] + "' exists, but has wrong length (expected " +
|
String msg = "File '" + names[i] + "' exists, but has wrong length (expected " +
|
||||||
lengths[i] + " but found " + length + ") - repairing corruption";
|
lengths[i] + " but found " + length + ") - repairing corruption";
|
||||||
SnarkManager.instance().addMessage(msg);
|
if (listener != null)
|
||||||
|
listener.addMessage(msg);
|
||||||
_log.error(msg);
|
_log.error(msg);
|
||||||
changed = true;
|
changed = true;
|
||||||
resume = true;
|
resume = true;
|
||||||
|
@ -61,4 +61,6 @@ interface StorageListener
|
|||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
void setWantedPieces(Storage storage);
|
void setWantedPieces(Storage storage);
|
||||||
|
|
||||||
|
void addMessage(String message);
|
||||||
}
|
}
|
||||||
|
@ -297,12 +297,11 @@ public class TrackerClient implements Runnable {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (trackers.isEmpty()) {
|
if (trackers.isEmpty() && _util.getDHT() == null) {
|
||||||
stop = true;
|
stop = true;
|
||||||
// FIXME translate
|
this.snark.addMessage(_util.getString("No valid trackers for {0} - enable opentrackers or DHT?",
|
||||||
SnarkManager.instance().addMessage("No valid trackers for " + this.snark.getBaseName() + " - enable opentrackers?");
|
this.snark.getBaseName()));
|
||||||
_log.error("No valid trackers for " + this.snark.getBaseName());
|
_log.error("No valid trackers for " + this.snark.getBaseName());
|
||||||
// FIXME keep going if DHT enabled
|
|
||||||
this.snark.stopTorrent();
|
this.snark.stopTorrent();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -94,4 +94,9 @@ public interface DHT {
|
|||||||
* Known nodes, not estimated total network size.
|
* Known nodes, not estimated total network size.
|
||||||
*/
|
*/
|
||||||
public int size();
|
public int size();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Debug info, HTML formatted
|
||||||
|
*/
|
||||||
|
public String renderStatusHTML();
|
||||||
}
|
}
|
||||||
|
@ -27,6 +27,10 @@ class DHTTracker {
|
|||||||
private long _expireTime;
|
private long _expireTime;
|
||||||
private final Log _log;
|
private final Log _log;
|
||||||
private volatile boolean _isRunning;
|
private volatile boolean _isRunning;
|
||||||
|
/** not current, updated by cleaner */
|
||||||
|
private int _peerCount;
|
||||||
|
/** not current, updated by cleaner */
|
||||||
|
private int _torrentCount;
|
||||||
|
|
||||||
/** stagger with other cleaners */
|
/** stagger with other cleaners */
|
||||||
private static final long CLEAN_TIME = 199*1000;
|
private static final long CLEAN_TIME = 199*1000;
|
||||||
@ -97,6 +101,15 @@ class DHTTracker {
|
|||||||
return rv;
|
return rv;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Debug info, HTML formatted
|
||||||
|
*/
|
||||||
|
public void renderStatusHTML(StringBuilder buf) {
|
||||||
|
buf.append("DHT tracker: ").append(_torrentCount).append(" torrents ")
|
||||||
|
.append(_peerCount).append(" peers ")
|
||||||
|
.append(DataHelper.formatDuration(_expireTime)).append(" expiration<br>");
|
||||||
|
}
|
||||||
|
|
||||||
private class Cleaner extends SimpleTimer2.TimedEvent {
|
private class Cleaner extends SimpleTimer2.TimedEvent {
|
||||||
|
|
||||||
public Cleaner() {
|
public Cleaner() {
|
||||||
@ -137,6 +150,8 @@ class DHTTracker {
|
|||||||
torrentCount + " torrents, " +
|
torrentCount + " torrents, " +
|
||||||
peerCount + " peers, " +
|
peerCount + " peers, " +
|
||||||
DataHelper.formatDuration(_expireTime) + " expiration");
|
DataHelper.formatDuration(_expireTime) + " expiration");
|
||||||
|
_peerCount = peerCount;
|
||||||
|
_torrentCount = torrentCount;
|
||||||
schedule(CLEAN_TIME);
|
schedule(CLEAN_TIME);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -21,6 +21,7 @@ import java.util.Set;
|
|||||||
import java.util.SortedSet;
|
import java.util.SortedSet;
|
||||||
import java.util.TreeSet;
|
import java.util.TreeSet;
|
||||||
import java.util.concurrent.ConcurrentHashMap;
|
import java.util.concurrent.ConcurrentHashMap;
|
||||||
|
import java.util.concurrent.atomic.AtomicLong;
|
||||||
|
|
||||||
import net.i2p.I2PAppContext;
|
import net.i2p.I2PAppContext;
|
||||||
import net.i2p.client.I2PClient;
|
import net.i2p.client.I2PClient;
|
||||||
@ -111,6 +112,12 @@ public class KRPC implements I2PSessionMuxedListener, DHT {
|
|||||||
private final File _dhtFile;
|
private final File _dhtFile;
|
||||||
private volatile boolean _isRunning;
|
private volatile boolean _isRunning;
|
||||||
private volatile boolean _hasBootstrapped;
|
private volatile boolean _hasBootstrapped;
|
||||||
|
/** stats */
|
||||||
|
private final AtomicLong _rxPkts = new AtomicLong();
|
||||||
|
private final AtomicLong _txPkts = new AtomicLong();
|
||||||
|
private final AtomicLong _rxBytes = new AtomicLong();
|
||||||
|
private final AtomicLong _txBytes = new AtomicLong();
|
||||||
|
private long _started;
|
||||||
|
|
||||||
/** all-zero NID used for pings */
|
/** all-zero NID used for pings */
|
||||||
public static final NID FAKE_NID = new NID(new byte[NID.HASH_LENGTH]);
|
public static final NID FAKE_NID = new NID(new byte[NID.HASH_LENGTH]);
|
||||||
@ -519,6 +526,11 @@ public class KRPC implements I2PSessionMuxedListener, DHT {
|
|||||||
// no need to keep ref, it will eventually stop
|
// no need to keep ref, it will eventually stop
|
||||||
new Cleaner();
|
new Cleaner();
|
||||||
new Explorer(5*1000);
|
new Explorer(5*1000);
|
||||||
|
_txPkts.set(0);
|
||||||
|
_rxPkts.set(0);
|
||||||
|
_txBytes.set(0);
|
||||||
|
_rxBytes.set(0);
|
||||||
|
_started = _context.clock().now();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -548,6 +560,26 @@ public class KRPC implements I2PSessionMuxedListener, DHT {
|
|||||||
_knownNodes.clear();
|
_knownNodes.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Debug info, HTML formatted
|
||||||
|
*/
|
||||||
|
public String renderStatusHTML() {
|
||||||
|
long uptime = Math.max(1000, _context.clock().now() - _started);
|
||||||
|
StringBuilder buf = new StringBuilder();
|
||||||
|
buf.append("<br><b>DHT DEBUG</b><br>TX: ").append(_txPkts.get()).append(" pkts / ")
|
||||||
|
.append(DataHelper.formatSize2(_txBytes.get())).append("B / ")
|
||||||
|
.append(DataHelper.formatSize2(_txBytes.get() * 1000 / uptime)).append("Bps<br>" +
|
||||||
|
"RX: ").append(_rxPkts.get()).append(" pkts / ")
|
||||||
|
.append(DataHelper.formatSize2(_rxBytes.get())).append("B / ")
|
||||||
|
.append(DataHelper.formatSize2(_rxBytes.get() * 1000 / uptime)).append("Bps<br>" +
|
||||||
|
"DHT Peers: ").append( _knownNodes.size()).append("<br>" +
|
||||||
|
"Sent tokens: ").append(_outgoingTokens.size()).append("<br>" +
|
||||||
|
"Rcvd tokens: ").append(_incomingTokens.size()).append("<br>" +
|
||||||
|
"Pending queries: ").append(_sentQueries.size()).append("<br>");
|
||||||
|
_tracker.renderStatusHTML(buf);
|
||||||
|
return buf.toString();
|
||||||
|
}
|
||||||
|
|
||||||
////////// All private below here /////////////////////////////////////
|
////////// All private below here /////////////////////////////////////
|
||||||
|
|
||||||
///// Sending.....
|
///// Sending.....
|
||||||
@ -862,7 +894,10 @@ public class KRPC implements I2PSessionMuxedListener, DHT {
|
|||||||
boolean success = _session.sendMessage(dest, payload, 0, payload.length, null, null, 60*1000,
|
boolean success = _session.sendMessage(dest, payload, 0, payload.length, null, null, 60*1000,
|
||||||
repliable ? I2PSession.PROTO_DATAGRAM : I2PSession.PROTO_DATAGRAM_RAW,
|
repliable ? I2PSession.PROTO_DATAGRAM : I2PSession.PROTO_DATAGRAM_RAW,
|
||||||
fromPort, toPort);
|
fromPort, toPort);
|
||||||
if (!success) {
|
if (success) {
|
||||||
|
_txPkts.incrementAndGet();
|
||||||
|
_txBytes.addAndGet(payload.length);
|
||||||
|
} else {
|
||||||
if (_log.shouldLog(Log.WARN))
|
if (_log.shouldLog(Log.WARN))
|
||||||
_log.warn("WTF sendMessage fail");
|
_log.warn("WTF sendMessage fail");
|
||||||
}
|
}
|
||||||
@ -880,7 +915,6 @@ public class KRPC implements I2PSessionMuxedListener, DHT {
|
|||||||
* @param from dest or null if it didn't come in on signed port
|
* @param from dest or null if it didn't come in on signed port
|
||||||
*/
|
*/
|
||||||
private void receiveMessage(Destination from, int fromPort, byte[] payload) {
|
private void receiveMessage(Destination from, int fromPort, byte[] payload) {
|
||||||
|
|
||||||
try {
|
try {
|
||||||
InputStream is = new ByteArrayInputStream(payload);
|
InputStream is = new ByteArrayInputStream(payload);
|
||||||
BDecoder dec = new BDecoder(is);
|
BDecoder dec = new BDecoder(is);
|
||||||
@ -1352,14 +1386,18 @@ public class KRPC implements I2PSessionMuxedListener, DHT {
|
|||||||
* @param toPort 1-65535 or 0 for unspecified
|
* @param toPort 1-65535 or 0 for unspecified
|
||||||
*/
|
*/
|
||||||
public void messageAvailable(I2PSession session, int msgId, long size, int proto, int fromPort, int toPort) {
|
public void messageAvailable(I2PSession session, int msgId, long size, int proto, int fromPort, int toPort) {
|
||||||
|
// TODO throttle
|
||||||
try {
|
try {
|
||||||
byte[] payload = session.receiveMessage(msgId);
|
byte[] payload = session.receiveMessage(msgId);
|
||||||
|
_rxPkts.incrementAndGet();
|
||||||
|
_rxBytes.addAndGet(payload.length);
|
||||||
if (toPort == _qPort) {
|
if (toPort == _qPort) {
|
||||||
// repliable
|
// repliable
|
||||||
I2PDatagramDissector dgDiss = new I2PDatagramDissector();
|
I2PDatagramDissector dgDiss = new I2PDatagramDissector();
|
||||||
dgDiss.loadI2PDatagram(payload);
|
dgDiss.loadI2PDatagram(payload);
|
||||||
payload = dgDiss.getPayload();
|
payload = dgDiss.getPayload();
|
||||||
Destination from = dgDiss.getSender();
|
Destination from = dgDiss.getSender();
|
||||||
|
// TODO per-dest throttle
|
||||||
receiveMessage(from, fromPort, payload);
|
receiveMessage(from, fromPort, payload);
|
||||||
} else if (toPort == _rPort) {
|
} else if (toPort == _rPort) {
|
||||||
// raw
|
// raw
|
||||||
|
@ -75,8 +75,7 @@ public class I2PSnarkServlet extends DefaultServlet {
|
|||||||
_context = I2PAppContext.getGlobalContext();
|
_context = I2PAppContext.getGlobalContext();
|
||||||
_log = _context.logManager().getLog(I2PSnarkServlet.class);
|
_log = _context.logManager().getLog(I2PSnarkServlet.class);
|
||||||
_nonce = _context.random().nextLong();
|
_nonce = _context.random().nextLong();
|
||||||
// FIXME instantiate new one every time
|
_manager = new SnarkManager(_context);
|
||||||
_manager = SnarkManager.instance();
|
|
||||||
String configFile = _context.getProperty(PROP_CONFIG_FILE);
|
String configFile = _context.getProperty(PROP_CONFIG_FILE);
|
||||||
if ( (configFile == null) || (configFile.trim().length() <= 0) )
|
if ( (configFile == null) || (configFile.trim().length() <= 0) )
|
||||||
configFile = "i2psnark.config";
|
configFile = "i2psnark.config";
|
||||||
@ -449,9 +448,9 @@ public class I2PSnarkServlet extends DefaultServlet {
|
|||||||
}
|
}
|
||||||
out.write("</th></tr></thead>\n");
|
out.write("</th></tr></thead>\n");
|
||||||
String uri = "/i2psnark/";
|
String uri = "/i2psnark/";
|
||||||
|
boolean showDebug = "2".equals(peerParam);
|
||||||
for (int i = 0; i < snarks.size(); i++) {
|
for (int i = 0; i < snarks.size(); i++) {
|
||||||
Snark snark = (Snark)snarks.get(i);
|
Snark snark = (Snark)snarks.get(i);
|
||||||
boolean showDebug = "2".equals(peerParam);
|
|
||||||
boolean showPeers = showDebug || "1".equals(peerParam) || Base64.encode(snark.getInfoHash()).equals(peerParam);
|
boolean showPeers = showDebug || "1".equals(peerParam) || Base64.encode(snark.getInfoHash()).equals(peerParam);
|
||||||
displaySnark(out, snark, uri, i, stats, showPeers, isDegraded, noThinsp, showDebug);
|
displaySnark(out, snark, uri, i, stats, showPeers, isDegraded, noThinsp, showDebug);
|
||||||
}
|
}
|
||||||
@ -478,6 +477,8 @@ public class I2PSnarkServlet extends DefaultServlet {
|
|||||||
out.write(", ");
|
out.write(", ");
|
||||||
out.write(ngettext("1 DHT peer", "{0} DHT peers", dhts));
|
out.write(ngettext("1 DHT peer", "{0} DHT peers", dhts));
|
||||||
}
|
}
|
||||||
|
if (showDebug)
|
||||||
|
out.write(dht.renderStatusHTML());
|
||||||
}
|
}
|
||||||
out.write("</th>\n");
|
out.write("</th>\n");
|
||||||
if (_manager.util().connected()) {
|
if (_manager.util().connected()) {
|
||||||
|
Reference in New Issue
Block a user