I2P Address: [http://git.idk.i2p]

Skip to content
Snippets Groups Projects
Commit a3c64a9b authored by zzz's avatar zzz Committed by zzz
Browse files

(zzz) 02-28 add peer details to i2psnark web page

parent 1447164a
No related branches found
No related tags found
No related merge requests found
......@@ -54,6 +54,10 @@ public class Peer implements Comparable
private boolean deregister = true;
private static long __id;
private long _id;
final static long CHECK_PERIOD = 40*1000; // 40 seconds
final static int RATE_DEPTH = 6; // make following arrays RATE_DEPTH long
private long uploaded_old[] = {-1,-1,-1,-1,-1,-1};
private long downloaded_old[] = {-1,-1,-1,-1,-1,-1};
/**
* Creates a disconnected peer given a PeerID, your own id and the
......@@ -487,4 +491,67 @@ public class Peer implements Comparable
s.retransmitRequests();
}
/**
* Return how much the peer has
* Quite inefficient - a byte lookup table or counter in Bitfield would be much better
*/
public int completed()
{
PeerState s = state;
if (s == null || s.bitfield == null)
return 0;
int count = 0;
for (int i = 0; i < s.bitfield.size(); i++)
if (s.bitfield.get(i))
count++;
return count;
}
/**
* Push the total uploaded/downloaded onto a RATE_DEPTH deep stack
*/
public void setRateHistory(long up, long down)
{
setRate(up, uploaded_old);
setRate(down, downloaded_old);
}
private void setRate(long val, long array[])
{
synchronized(array) {
for (int i = RATE_DEPTH-1; i > 0; i--)
array[i] = array[i-1];
array[0] = val;
}
}
/**
* Returns the 4-minute-average rate in Bps
*/
public long getUploadRate()
{
return getRate(uploaded_old);
}
public long getDownloadRate()
{
return getRate(downloaded_old);
}
private long getRate(long array[])
{
long rate = 0;
int i = 0;
synchronized(array) {
for ( ; i < RATE_DEPTH; i++){
if (array[i] < 0)
break;
rate += array[i];
}
}
if (i == 0)
return 0;
return rate / (i * CHECK_PERIOD / 1000);
}
}
......@@ -82,6 +82,7 @@ class PeerCheckerTask extends TimerTask
uploaded += upload;
long download = peer.getDownloaded();
downloaded += download;
peer.setRateHistory(upload, download);
peer.resetCounters();
if (Snark.debug >= Snark.DEBUG)
......
......@@ -105,6 +105,15 @@ public class PeerCoordinator implements PeerListener
public Storage getStorage() { return storage; }
public CoordinatorListener getListener() { return listener; }
// for web page detailed stats
public List peerList()
{
synchronized(peers)
{
return new ArrayList(peers);
}
}
public byte[] getID()
{
return id;
......@@ -157,12 +166,17 @@ public class PeerCoordinator implements PeerListener
*/
public void setRateHistory(long up, long down)
{
for (int i = RATE_DEPTH-1; i > 0; i--){
uploaded_old[i] = uploaded_old[i-1];
downloaded_old[i] = downloaded_old[i-1];
setRate(up, uploaded_old);
setRate(down, downloaded_old);
}
private void setRate(long val, long array[])
{
synchronized(array) {
for (int i = RATE_DEPTH-1; i > 0; i--)
array[i] = array[i-1];
array[0] = val;
}
uploaded_old[0] = up;
downloaded_old[0] = down;
}
/**
......@@ -170,21 +184,20 @@ public class PeerCoordinator implements PeerListener
*/
public long getDownloadRate()
{
long rate = 0;
for (int i = 0; i < RATE_DEPTH; i++){
rate += downloaded_old[i];
}
return rate / (RATE_DEPTH * CHECK_PERIOD / 1000);
return getRate(downloaded_old);
}
/**
* Returns the 4-minute-average rate in Bps
*/
public long getUploadRate()
{
return getRate(uploaded_old);
}
private long getRate(long array[])
{
long rate = 0;
for (int i = 0; i < RATE_DEPTH; i++){
rate += uploaded_old[i];
synchronized(array) {
for (int i = 0; i < RATE_DEPTH; i++)
rate += array[i];
}
return rate / (RATE_DEPTH * CHECK_PERIOD / 1000);
}
......
......@@ -49,17 +49,25 @@ public class I2PSnarkServlet extends HttpServlet {
if ( (nonce != null) && (nonce.equals(String.valueOf(_nonce))) )
processRequest(req);
String peerParam = req.getParameter("p");
String peerString;
if (peerParam == null) {
peerString = "";
} else {
peerString = "?p=" + peerParam;
}
PrintWriter out = resp.getWriter();
out.write(HEADER_BEGIN);
// we want it to go to the base URI so we don't refresh with some funky action= value
out.write("<meta http-equiv=\"refresh\" content=\"60;" + req.getRequestURI() + "\">\n");
out.write("<meta http-equiv=\"refresh\" content=\"60;" + req.getRequestURI() + peerString + "\">\n");
out.write(HEADER);
out.write("<table border=\"0\" width=\"100%\">\n");
out.write("<tr><td width=\"20%\" class=\"snarkTitle\" valign=\"top\" align=\"left\">");
out.write("I2PSnark<br />\n");
out.write("<table border=\"0\" width=\"100%\">\n");
out.write("<tr><td><a href=\"" + req.getRequestURI() + "\" class=\"snarkRefresh\">Refresh</a><br />\n");
out.write("<tr><td><a href=\"" + req.getRequestURI() + peerString + "\" class=\"snarkRefresh\">Refresh</a><br />\n");
out.write("<td><a href=\"http://forum.i2p/viewforum.php?f=21\" class=\"snarkRefresh\">Forum</a><br />\n");
out.write("<tr><td><a href=\"http://de-ebook-archiv.i2p/pub/bt/\" class=\"snarkRefresh\">eBook</a><br />\n");
out.write("<td><a href=\"http://gaytorrents.i2p/\" class=\"snarkRefresh\">GayTorrents</a><br />\n");
......@@ -79,6 +87,13 @@ public class I2PSnarkServlet extends HttpServlet {
List snarks = getSortedSnarks(req);
String uri = req.getRequestURI();
out.write(TABLE_HEADER);
if (I2PSnarkUtil.instance().connected() && snarks.size() > 0) {
if (peerParam != null)
out.write("(<a href=\"" + req.getRequestURI() + "\">Hide Peers</a>)<br />\n");
else
out.write("(<a href=\"" + req.getRequestURI() + "?p=1" + "\">Show Peers</a>)<br />\n");
}
out.write(TABLE_HEADER2);
out.write("<th align=\"left\" valign=\"top\">");
if (I2PSnarkUtil.instance().connected())
out.write("<a href=\"" + uri + "?action=StopAll&nonce=" + _nonce +
......@@ -88,7 +103,8 @@ public class I2PSnarkServlet extends HttpServlet {
out.write("</th></tr></thead>\n");
for (int i = 0; i < snarks.size(); i++) {
Snark snark = (Snark)snarks.get(i);
displaySnark(out, snark, uri, i, stats);
boolean showPeers = "1".equals(peerParam) || Base64.encode(snark.meta.getInfoHash()).equals(peerParam);
displaySnark(out, snark, uri, i, stats, showPeers);
}
if (snarks.size() <= 0) {
out.write(TABLE_EMPTY);
......@@ -103,6 +119,7 @@ public class I2PSnarkServlet extends HttpServlet {
}
out.write(TABLE_FOOTER);
writeAddForm(out, req);
if (true) // seeding needs to register the torrent first, so we can't start it automatically (boo, hiss)
writeSeedForm(out, req);
......@@ -318,7 +335,7 @@ public class I2PSnarkServlet extends HttpServlet {
private static final int MAX_DISPLAYED_FILENAME_LENGTH = 60;
private static final int MAX_DISPLAYED_ERROR_LENGTH = 30;
private void displaySnark(PrintWriter out, Snark snark, String uri, int row, long stats[]) throws IOException {
private void displaySnark(PrintWriter out, Snark snark, String uri, int row, long stats[], boolean showPeers) throws IOException {
String filename = snark.torrent;
File f = new File(filename);
filename = f.getName(); // the torrent may be the canonical name, so lets just grab the local name
......@@ -369,7 +386,11 @@ public class I2PSnarkServlet extends HttpServlet {
String statusString = "Unknown";
if (err != null) {
if (isRunning)
if (isRunning && curPeers > 0 && !showPeers)
statusString = "TrackerErr (" +
curPeers + "/" + knownPeers +
" <a href=\"" + uri + "?p=" + Base64.encode(snark.meta.getInfoHash()) + "\">peers</a>)";
else if (isRunning)
statusString = "TrackerErr (" + curPeers + "/" + knownPeers + " peers)";
else {
if (err.length() > MAX_DISPLAYED_ERROR_LENGTH)
......@@ -377,13 +398,25 @@ public class I2PSnarkServlet extends HttpServlet {
statusString = "TrackerErr (" + err + ")";
}
} else if (remaining <= 0) {
if (isRunning)
if (isRunning && curPeers > 0 && !showPeers)
statusString = "Seeding (" +
curPeers + "/" + knownPeers +
" <a href=\"" + uri + "?p=" + Base64.encode(snark.meta.getInfoHash()) + "\">peers</a>)";
else if (isRunning)
statusString = "Seeding (" + curPeers + "/" + knownPeers + " peers)";
else
statusString = "Complete";
} else {
if (isRunning && curPeers > 0 && downBps > 0)
if (isRunning && curPeers > 0 && downBps > 0 && !showPeers)
statusString = "OK (" +
curPeers + "/" + knownPeers +
" <a href=\"" + uri + "?p=" + Base64.encode(snark.meta.getInfoHash()) + "\">peers</a>)";
else if (isRunning && curPeers > 0 && downBps > 0)
statusString = "OK (" + curPeers + "/" + knownPeers + " peers)";
else if (isRunning && curPeers > 0 && !showPeers)
statusString = "Stalled (" +
curPeers + "/" + knownPeers +
" <a href=\"" + uri + "?p=" + Base64.encode(snark.meta.getInfoHash()) + "\">peers</a>)";
else if (isRunning && curPeers > 0)
statusString = "Stalled (" + curPeers + "/" + knownPeers + " peers)";
else if (isRunning)
......@@ -427,23 +460,84 @@ public class I2PSnarkServlet extends HttpServlet {
out.write(formatSize(upBps) + "ps");
out.write("</td>\n\t");
out.write("<td valign=\"top\" align=\"left\" class=\"snarkTorrentAction " + rowClass + "\">");
String parameters = "&nonce=" + _nonce + "&torrent=" + Base64.encode(snark.meta.getInfoHash());
if (showPeers)
parameters = parameters + "&p=1";
if (isRunning) {
out.write("<a href=\"" + uri + "?action=Stop&nonce=" + _nonce
+ "&torrent=" + Base64.encode(snark.meta.getInfoHash())
out.write("<a href=\"" + uri + "?action=Stop" + parameters
+ "\" title=\"Stop the torrent\">Stop</a>");
} else {
if (isValid)
out.write("<a href=\"" + uri + "?action=Start&nonce=" + _nonce
+ "&torrent=" + Base64.encode(snark.meta.getInfoHash())
out.write("<a href=\"" + uri + "?action=Start" + parameters
+ "\" title=\"Start the torrent\">Start</a> ");
out.write("<a href=\"" + uri + "?action=Remove&nonce=" + _nonce
+ "&torrent=" + Base64.encode(snark.meta.getInfoHash())
out.write("<a href=\"" + uri + "?action=Remove" + parameters
+ "\" title=\"Remove the torrent from the active list, deleting the .torrent file\">Remove</a><br />");
out.write("<a href=\"" + uri + "?action=Delete&nonce=" + _nonce
+ "&torrent=" + Base64.encode(snark.meta.getInfoHash())
out.write("<a href=\"" + uri + "?action=Delete" + parameters
+ "\" title=\"Delete the .torrent file and the associated data file(s)\">Delete</a> ");
}
out.write("</td>\n</tr>\n");
if(showPeers && isRunning && curPeers > 0) {
List peers = snark.coordinator.peerList();
Iterator it = peers.iterator();
while (it.hasNext()) {
Peer peer = (Peer)it.next();
if (!peer.isConnected())
continue;
out.write("<tr class=\"" + rowClass + "\">");
out.write("<td class=\"snarkTorrentStatus " + rowClass + "\">");
out.write("</td>\n\t");
out.write("<td valign=\"top\" align=\"right\" class=\"snarkTorrentStatus " + rowClass + "\">");
String ch = peer.toString().substring(0, 4);
String client;
if ("AwMD".equals(ch))
client = "I2PSnark";
else if ("BFJT".equals(ch))
client = "I2PRufus";
else if ("TTMt".equals(ch))
client = "I2P-BT";
else if ("LUFa".equals(ch))
client = "Azureus";
else
client = "Unknown";
out.write("<font size=-1>" + client + "</font> <tt>" + peer.toString().substring(5, 9) + "</tt>");
out.write("</td>\n\t");
out.write("<td class=\"snarkTorrentStatus " + rowClass + "\">");
out.write("</td>\n\t");
out.write("<td valign=\"top\" align=\"right\" class=\"snarkTorrentStatus " + rowClass + "\">");
float pct = (float) (100.0 * (float) peer.completed() / snark.meta.getPieces());
if (pct == 100.0)
out.write("<font size=-1>Seed</font>");
else {
String ps = String.valueOf(pct);
if (ps.length() > 5)
ps = ps.substring(0, 5);
out.write("<font size=-1>" + ps + "%</font>");
}
out.write("</td>\n\t");
out.write("<td class=\"snarkTorrentStatus " + rowClass + "\">");
out.write("</td>\n\t");
out.write("<td valign=\"top\" align=\"right\" class=\"snarkTorrentStatus " + rowClass + "\">");
if (remaining > 0) {
if (peer.isInteresting() && !peer.isChoked())
out.write("<font color=#008000>");
else
out.write("<font color=#a00000>");
out.write("<font size=-1>" + formatSize(peer.getDownloadRate()) + "ps</font></font>");
}
out.write("</td>\n\t");
out.write("<td valign=\"top\" align=\"right\" class=\"snarkTorrentStatus " + rowClass + "\">");
if (pct != 100.0) {
if (peer.isInterested() && !peer.isChoking())
out.write("<font color=#008000>");
else
out.write("<font color=#a00000>");
out.write("<font size=-1>" + formatSize(peer.getUploadRate()) + "ps</font></font>");
}
out.write("</td>\n\t");
out.write("<td class=\"snarkTorrentStatus " + rowClass + "\">");
out.write("</td></tr>\n\t");
}
}
}
private void writeAddForm(PrintWriter out, HttpServletRequest req) throws IOException {
......@@ -565,15 +659,16 @@ public class I2PSnarkServlet extends HttpServlet {
out.write("</form>\n");
}
// rounding makes us look faster :)
private String formatSize(long bytes) {
if (bytes < 5*1024)
return bytes + "B";
else if (bytes < 5*1024*1024)
return (bytes/1024) + "KB";
return ((bytes + 512)/1024) + "KB";
else if (bytes < 5*1024*1024*1024l)
return (bytes/(1024*1024)) + "MB";
return ((bytes + 512*1024)/(1024*1024)) + "MB";
else
return (bytes/(1024*1024*1024)) + "GB";
return ((bytes + 512*1024*1024)/(1024*1024*1024)) + "GB";
}
private static final String HEADER_BEGIN = "<html>\n" +
......@@ -649,7 +744,9 @@ public class I2PSnarkServlet extends HttpServlet {
private static final String TABLE_HEADER = "<table border=\"0\" class=\"snarkTorrents\" width=\"100%\" cellpadding=\"0 10px\">\n" +
"<thead>\n" +
"<tr><th align=\"left\" valign=\"top\">Status</th>\n" +
"<tr><th align=\"left\" valign=\"top\">Status \n";
private static final String TABLE_HEADER2 = "</th>\n" +
" <th align=\"left\" valign=\"top\">Torrent</th>\n" +
" <th align=\"right\" valign=\"top\">ETA</th>\n" +
" <th align=\"right\" valign=\"top\">Downloaded</th>\n" +
......
$Id: history.txt,v 1.550 2007-02-14 16:35:43 jrandom Exp $
$Id: history.txt,v 1.551 2007-02-15 18:25:04 jrandom Exp $
2007-02-28 zzz
* i2psnark: Add peer details to web page
* 2007-02-15 0.6.1.27 released
......
......@@ -15,9 +15,9 @@ import net.i2p.CoreVersion;
*
*/
public class RouterVersion {
public final static String ID = "$Revision: 1.486 $ $Date: 2007-02-14 16:35:44 $";
public final static String ID = "$Revision: 1.487 $ $Date: 2007-02-15 18:25:06 $";
public final static String VERSION = "0.6.1.27";
public final static long BUILD = 0;
public final static long BUILD = 1;
public static void main(String args[]) {
System.out.println("I2P Router version: " + VERSION + "-" + BUILD);
System.out.println("Router ID: " + RouterVersion.ID);
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment