Changeset dc33ad10


Ignore:
Timestamp:
May 19, 2017 7:20:11 PM (3 years ago)
Author:
zzz <zzz@…>
Branches:
master
Children:
81026c2
Parents:
b7baeddc
Message:

Console: Move /peers page rendering from router to console (ticket #1879)
except UPnP still to do
compressed size: appx. 25 KB

Files:
9 edited
1 moved

Legend:

Unmodified
Added
Removed
  • apps/routerconsole/java/src/net/i2p/router/web/PeerHelper.java

    rb7baeddc rdc33ad10  
    22
    33import java.io.IOException;
     4import java.io.Serializable;
     5import java.io.Writer;
     6import java.util.Comparator;
     7import java.text.DecimalFormat;
     8import java.text.NumberFormat;
     9import java.util.Collections;
     10import java.util.Iterator;
     11import java.util.Map;
     12import java.util.SortedMap;
     13import java.util.TreeMap;
     14import java.util.TreeSet;
     15
     16import net.i2p.data.DataHelper;
     17import net.i2p.data.router.RouterAddress;
     18import net.i2p.router.transport.Transport;
     19import net.i2p.router.transport.ntcp.NTCPConnection;
     20import net.i2p.router.transport.ntcp.NTCPTransport;
     21import net.i2p.router.transport.udp.PeerState;
     22import net.i2p.router.transport.udp.UDPTransport;
     23import static net.i2p.router.web.UDPSorters.*;
     24import net.i2p.util.SystemVersion;
     25
    426
    527
     
    830    private String _urlBase;
    931   
     32    // Opera doesn't have the char, TODO check UA
     33    //private static final String THINSP = "&thinsp;/&thinsp;";
     34    private static final String THINSP = " / ";
     35
    1036    public PeerHelper() {}
    1137   
     
    2551    public String getPeerSummary() {
    2652        try {
    27             _context.commSystem().renderStatusHTML(_out, _urlBase, _sortFlags);
     53            renderStatusHTML(_out, _urlBase, _sortFlags);
    2854            // boring and not worth translating
    2955            //_context.bandwidthLimiter().renderStatusHTML(_out);
     
    3359        return "";
    3460    }
     61   
     62    /**
     63     *  Warning - blocking, very slow, queries the active UPnP router,
     64     *  will take many seconds if it has vanished.
     65     *
     66     *  @since 0.9.31 moved from TransportManager
     67     */
     68    private void renderStatusHTML(Writer out, String urlBase, int sortFlags) throws IOException {
     69        if (isAdvanced()) {
     70            out.write("<p id=\"upnpstatus\"><b>");
     71            out.write(_t("Status"));
     72            out.write(": ");
     73            out.write(_t(_context.commSystem().getStatus().toStatusString()));
     74            out.write("</b></p>");
     75        }
     76        SortedMap<String, Transport> transports = _context.commSystem().getTransports();
     77        for (Map.Entry<String, Transport> e : transports.entrySet()) {
     78            String style = e.getKey();
     79            Transport t = e.getValue();
     80            if (style.equals("NTCP")) {
     81                NTCPTransport nt = (NTCPTransport) t;
     82                render(nt, out, urlBase, sortFlags);
     83            } else if (style.equals("SSU")) {
     84                UDPTransport ut = (UDPTransport) t;
     85                render(ut, out, urlBase, sortFlags);
     86            } else {
     87                // pluggable (none yet_
     88                t.renderStatusHTML(out, urlBase, sortFlags);
     89            }
     90        }
     91       
     92        if (!transports.isEmpty()) {
     93            out.write(getTransportsLegend());
     94        }
     95
     96        StringBuilder buf = new StringBuilder(4*1024);
     97        buf.append("<h3 id=\"transports\">").append(_t("Router Transport Addresses")).append("</h3><pre id=\"transports\">\n");
     98        for (Transport t : transports.values()) {
     99            if (t.hasCurrentAddress()) {
     100                for (RouterAddress ra : t.getCurrentAddresses()) {
     101                    buf.append(ra.toString());
     102                    buf.append("\n\n");
     103                }
     104            } else {
     105                buf.append(_t("{0} is used for outbound connections only", t.getStyle()));
     106                buf.append("\n\n");
     107            }
     108        }
     109        buf.append("</pre>\n");
     110        out.write(buf.toString());
     111        // UPnP Status
     112        _context.commSystem().renderStatusHTML(_out, _urlBase, _sortFlags);
     113        out.write("</p>\n");
     114        out.flush();
     115    }
     116
     117    /**
     118     *  @since 0.9.31 moved from TransportManager
     119     */
     120    private final String getTransportsLegend() {
     121        StringBuilder buf = new StringBuilder(1024);
     122        buf.append("<p class=\"infohelp\">")
     123           .append(_t("Your transport connection limits are automatically set based on your configured bandwidth."))
     124           .append('\n')
     125           .append(_t("To override these limits, add the settings i2np.ntcp.maxConnections=nnn and i2np.udp.maxConnections=nnn on the advanced configuration page."))
     126           .append("</p>\n");
     127        buf.append("<h3 class=\"tabletitle\">").append(_t("Definitions")).append("</h3>")
     128           .append("<table id=\"peerdefs\">\n")
     129           .append("<tr><td><b id=\"def.peer\">").append(_t("Peer")).append("</b></td><td>").append(_t("The remote peer, identified by router hash")).append("</td></tr>\n")
     130           .append("<tr><td><b id=\"def.dir\">").append(_t("Dir")).append("</b></td><td><img alt=\"Inbound\" src=\"/themes/console/images/inbound.png\"> ").append(_t("Inbound connection")).append("</td></tr>\n")
     131           .append("<tr><td></td><td><img alt=\"Outbound\" src=\"/themes/console/images/outbound.png\"> ").append(_t("Outbound connection")).append("</td></tr>\n")
     132           .append("<tr><td></td><td><img src=\"/themes/console/images/inbound.png\" alt=\"V\" height=\"8\" width=\"12\"> ").append(_t("They offered to introduce us (help other peers traverse our firewall)")).append("</td></tr>\n")
     133           .append("<tr><td></td><td><img src=\"/themes/console/images/outbound.png\" alt=\"^\" height=\"8\" width=\"12\"> ").append(_t("We offered to introduce them (help other peers traverse their firewall)")).append("</td></tr>\n")
     134           .append("<tr><td><b id=\"def.idle\">").append(_t("Idle")).append("</b></td><td>").append(_t("How long since a packet has been received / sent")).append("</td></tr>\n")
     135           .append("<tr><td><b id=\"def.rate\">").append(_t("In/Out")).append("</b></td><td>").append(_t("The smoothed inbound / outbound transfer rate (KBytes per second)")).append("</td></tr>\n")
     136           .append("<tr><td><b id=\"def.up\">").append(_t("Up")).append("</b></td><td>").append(_t("How long ago this connection was established")).append("</td></tr>\n")
     137           .append("<tr><td><b id=\"def.skew\">").append(_t("Skew")).append("</b></td><td>").append(_t("The difference between the peer's clock and your own")).append("</td></tr>\n")
     138           .append("<tr><td><b id=\"def.cwnd\">CWND</b></td><td>").append(_t("The congestion window, which is how many bytes can be sent without an acknowledgement")).append(" / </td></tr>\n")
     139           .append("<tr><td></td><td>").append(_t("The number of sent messages awaiting acknowledgement")).append(" /</td></tr>\n")
     140           .append("<tr><td></td><td>").append(_t("The maximum number of concurrent messages to send")).append(" /</td></tr>\n")
     141           .append("<tr><td></td><td>").append(_t("The number of pending sends which exceed congestion window")).append("</td></tr>\n")
     142           .append("<tr><td><b id=\"def.ssthresh\">SST</b></td><td>").append(_t("The slow start threshold")).append("</td></tr>\n")
     143           .append("<tr><td><b id=\"def.rtt\">RTT</b></td><td>").append(_t("The round trip time in milliseconds")).append("</td></tr>\n")
     144           //.append("<tr><td><b id=\"def.dev\">").append(_t("Dev")).append("</b></td><td>").append(_t("The standard deviation of the round trip time in milliseconds")).append("</td></tr>\n")
     145           .append("<tr><td><b id=\"def.rto\">RTO</b></td><td>").append(_t("The retransmit timeout in milliseconds")).append("</td></tr>\n")
     146           .append("<tr><td><b id=\"def.mtu\">MTU</b></td><td>").append(_t("Current maximum send packet size / estimated maximum receive packet size (bytes)")).append("</td></tr>\n")
     147           .append("<tr><td><b id=\"def.send\">").append(_t("TX")).append("</b></td><td>").append(_t("The total number of messages sent to the peer")).append("</td></tr>\n")
     148           .append("<tr><td><b id=\"def.recv\">").append(_t("RX")).append("</b></td><td>").append(_t("The total number of messages received from the peer")).append("</td></tr>\n")
     149           .append("<tr><td><b id=\"def.resent\">").append(_t("Dup TX")).append("</b></td><td>").append(_t("The total number of packets retransmitted to the peer")).append("</td></tr>\n")
     150           .append("<tr><td><b id=\"def.dupRecv\">").append(_t("Dup RX")).append("</b></td><td>").append(_t("The total number of duplicate packets received from the peer")).append("</td></tr>\n")
     151           .append("</table>");
     152        return buf.toString();
     153    }
     154
     155    /// begin SSU
     156
     157    /**
     158     *  @since 0.9.31 moved from NTCPTransport
     159     */
     160    private void render(NTCPTransport nt, Writer out, String urlBase, int sortFlags) throws IOException {
     161        TreeSet<NTCPConnection> peers = new TreeSet<NTCPConnection>(getNTCPComparator(sortFlags));
     162        peers.addAll(nt.getPeers());
     163
     164        long offsetTotal = 0;
     165        float bpsSend = 0;
     166        float bpsRecv = 0;
     167        long totalUptime = 0;
     168        long totalSend = 0;
     169        long totalRecv = 0;
     170
     171        if (!isAdvanced()) {
     172            for (Iterator<NTCPConnection> iter = peers.iterator(); iter.hasNext(); ) {
     173                 // outbound conns get put in the map before they are established
     174                 if (!iter.next().isEstablished())
     175                     iter.remove();
     176            }
     177        }
     178
     179        StringBuilder buf = new StringBuilder(512);
     180        buf.append("<h3 id=\"ntcpcon\">").append(_t("NTCP connections")).append(": ").append(peers.size());
     181        buf.append(". ").append(_t("Limit")).append(": ").append(nt.getMaxConnections());
     182        //buf.append(". ").append(_t("Timeout")).append(": ").append(DataHelper.formatDuration2(_pumper.getIdleTimeout()));
     183        if (_context.getBooleanProperty(PROP_ADVANCED)) {
     184            buf.append(". ").append(_t("Status")).append(": ").append(_t(nt.getReachabilityStatus().toStatusString()));
     185        }
     186        buf.append(".</h3>\n" +
     187                   "<div class=\"widescroll\"><table id=\"ntcpconnections\">\n" +
     188                   "<tr><th><a href=\"#def.peer\">").append(_t("Peer")).append("</a></th>" +
     189                   "<th>").append(_t("Dir")).append("</th>" +
     190                   "<th>").append(_t("IPv6")).append("</th>" +
     191                   "<th align=\"right\"><a href=\"#def.idle\">").append(_t("Idle")).append("</a></th>" +
     192                   "<th align=\"right\"><a href=\"#def.rate\">").append(_t("In/Out")).append("</a></th>" +
     193                   "<th align=\"right\"><a href=\"#def.up\">").append(_t("Up")).append("</a></th>" +
     194                   "<th align=\"right\"><a href=\"#def.skew\">").append(_t("Skew")).append("</a></th>" +
     195                   "<th align=\"right\"><a href=\"#def.send\">").append(_t("TX")).append("</a></th>" +
     196                   "<th align=\"right\"><a href=\"#def.recv\">").append(_t("RX")).append("</a></th>" +
     197                   "<th>").append(_t("Out Queue")).append("</th>" +
     198                   "<th title=\"").append(_t("Is peer backlogged?")).append("\">").append(_t("Backlogged?")).append("</th>" +
     199                   //"<th>").append(_t("Reading?")).append("</th>" +
     200                   " </tr>\n");
     201        out.write(buf.toString());
     202        buf.setLength(0);
     203        for (NTCPConnection con : peers) {
     204            buf.append("<tr><td class=\"cells\" align=\"left\" nowrap>");
     205            buf.append(_context.commSystem().renderPeerHTML(con.getRemotePeer().calculateHash()));
     206            //byte[] ip = getIP(con.getRemotePeer().calculateHash());
     207            //if (ip != null)
     208            //    buf.append(' ').append(_context.blocklist().toStr(ip));
     209            buf.append("</td><td class=\"cells\" align=\"center\">");
     210            if (con.isInbound())
     211                buf.append("<img src=\"/themes/console/images/inbound.png\" alt=\"Inbound\" title=\"").append(_t("Inbound")).append("\"/>");
     212            else
     213                buf.append("<img src=\"/themes/console/images/outbound.png\" alt=\"Outbound\" title=\"").append(_t("Outbound")).append("\"/>");
     214            buf.append("</td><td class=\"cells\" align=\"center\">");
     215            if (con.isIPv6())
     216                buf.append("<span class=\"backlogged\">&#x2714;</span>");
     217            else
     218                buf.append("&nbsp;");
     219            buf.append("</td><td class=\"cells\" align=\"right\">");
     220            buf.append(DataHelper.formatDuration2(con.getTimeSinceReceive()));
     221            buf.append(THINSP).append(DataHelper.formatDuration2(con.getTimeSinceSend()));
     222            buf.append("</td><td class=\"cells\" align=\"right\">");
     223            if (con.getTimeSinceReceive() < 2*60*1000) {
     224                float r = con.getRecvRate();
     225                buf.append(formatRate(r / 1024));
     226                bpsRecv += r;
     227            } else {
     228                buf.append(formatRate(0));
     229            }
     230            buf.append(THINSP);
     231            if (con.getTimeSinceSend() < 2*60*1000) {
     232                float r = con.getSendRate();
     233                buf.append(formatRate(r / 1024));
     234                bpsSend += r;
     235            } else {
     236                buf.append(formatRate(0));
     237            }
     238            //buf.append(" K/s");
     239            buf.append("</td><td class=\"cells\" align=\"right\">").append(DataHelper.formatDuration2(con.getUptime()));
     240            totalUptime += con.getUptime();
     241            offsetTotal = offsetTotal + con.getClockSkew();
     242            buf.append("</td><td class=\"cells\" align=\"right\">").append(DataHelper.formatDuration2(1000 * con.getClockSkew()));
     243            buf.append("</td><td class=\"cells\" align=\"right\">").append(con.getMessagesSent());
     244            totalSend += con.getMessagesSent();
     245            buf.append("</td><td class=\"cells\" align=\"right\">").append(con.getMessagesReceived());
     246            totalRecv += con.getMessagesReceived();
     247            long outQueue = con.getOutboundQueueSize();
     248            buf.append("</td><td class=\"cells\" align=\"center\">").append(outQueue);
     249            buf.append("</td><td class=\"cells\" align=\"center\">");
     250            if (con.isBacklogged())
     251                buf.append("<span class=\"backlogged\">&#x2714;</span>");
     252            else
     253                buf.append("&nbsp;");
     254            //long readTime = con.getReadTime();
     255            //if (readTime <= 0) {
     256            //    buf.append("</td> <td class=\"cells\" align=\"center\">0");
     257            //} else {
     258            //    buf.append("</td> <td class=\"cells\" align=\"center\">").append(DataHelper.formatDuration(readTime));
     259            //}
     260            buf.append("</td></tr>\n");
     261            out.write(buf.toString());
     262            buf.setLength(0);
     263        }
     264
     265        if (!peers.isEmpty()) {
     266//            buf.append("<tr> <td colspan=\"11\"><hr></td></tr>\n");
     267            buf.append("<tr class=\"tablefooter\"><td colspan=\"4\" align=\"left\"><b>")
     268               .append(ngettext("{0} peer", "{0} peers", peers.size()));
     269            buf.append("</b></td><td align=\"center\"><b>").append(formatRate(bpsRecv/1024)).append(THINSP).append(formatRate(bpsSend/1024)).append("</b>");
     270            buf.append("</td><td align=\"center\"><b>").append(DataHelper.formatDuration2(totalUptime/peers.size()));
     271            buf.append("</b></td><td align=\"center\"><b>").append(DataHelper.formatDuration2(offsetTotal*1000/peers.size()));
     272            buf.append("</b></td><td align=\"center\"><b>").append(totalSend).append("</b></td><td align=\"center\"><b>").append(totalRecv);
     273            buf.append("</b></td><td>&nbsp;</td><td>&nbsp;</td></tr>\n");
     274        }
     275
     276        buf.append("</table></div>\n");
     277        out.write(buf.toString());
     278        buf.setLength(0);
     279    }
     280
     281    private static final NumberFormat _rateFmt = new DecimalFormat("#,##0.00");
     282
     283    private static String formatRate(float rate) {
     284        synchronized (_rateFmt) { return _rateFmt.format(rate); }
     285    }
     286
     287    private Comparator<NTCPConnection> getNTCPComparator(int sortFlags) {
     288        Comparator<NTCPConnection> rv = null;
     289        switch (Math.abs(sortFlags)) {
     290            default:
     291                rv = AlphaComparator.instance();
     292        }
     293        if (sortFlags < 0)
     294            rv = Collections.reverseOrder(rv);
     295        return rv;
     296    }
     297
     298    private static class AlphaComparator extends PeerComparator {
     299        private static final AlphaComparator _instance = new AlphaComparator();
     300        public static final AlphaComparator instance() { return _instance; }
     301    }
     302
     303    private static class PeerComparator implements Comparator<NTCPConnection>, Serializable {
     304        public int compare(NTCPConnection l, NTCPConnection r) {
     305            if (l == null || r == null)
     306                throw new IllegalArgumentException();
     307            // base64 retains binary ordering
     308            // UM, no it doesn't, but close enough
     309            return l.getRemotePeer().calculateHash().toBase64().compareTo(r.getRemotePeer().calculateHash().toBase64());
     310        }
     311    }
     312
     313    /// end NTCP
     314    /// begin SSU
     315
     316    /**
     317     *  @since 0.9.31 moved from UDPTransport
     318     */
     319    private void render(UDPTransport ut, Writer out, String urlBase, int sortFlags) throws IOException {
     320        TreeSet<PeerState> peers = new TreeSet<PeerState>(getComparator(sortFlags));
     321        peers.addAll(ut.getPeers());
     322        long offsetTotal = 0;
     323
     324        int bpsIn = 0;
     325        int bpsOut = 0;
     326        long uptimeMsTotal = 0;
     327        long cwinTotal = 0;
     328        long rttTotal = 0;
     329        long rtoTotal = 0;
     330        long sendTotal = 0;
     331        long recvTotal = 0;
     332        long resentTotal = 0;
     333        long dupRecvTotal = 0;
     334        int numPeers = 0;
     335       
     336        StringBuilder buf = new StringBuilder(512);
     337        buf.append("<h3 id=\"udpcon\">").append(_t("UDP connections")).append(": ").append(peers.size());
     338        buf.append(". ").append(_t("Limit")).append(": ").append(ut.getMaxConnections());
     339        //buf.append(". ").append(_t("Timeout")).append(": ").append(DataHelper.formatDuration2(_expireTimeout));
     340        if (isAdvanced()) {
     341            buf.append(". ").append(_t("Status")).append(": ").append(_t(ut.getReachabilityStatus().toStatusString()));
     342        }
     343        buf.append(".</h3>\n");
     344        buf.append("<div class=\"widescroll\"><table id=\"udpconnections\">\n");
     345        buf.append("<tr><th class=\"smallhead\" nowrap><a href=\"#def.peer\">").append(_t("Peer")).append("</a><br>");
     346        if (sortFlags != FLAG_ALPHA)
     347            appendSortLinks(buf, urlBase, sortFlags, _t("Sort by peer hash"), FLAG_ALPHA);
     348        buf.append("</th><th class=\"smallhead\" nowrap><a href=\"#def.dir\" title=\"")
     349           .append(_t("Direction/Introduction")).append("\">").append(_t("Dir"))
     350           .append("</a></th><th class=\"smallhead\" nowrap><a href=\"#def.ipv6\">").append(_t("IPv6"))
     351           .append("</a></th><th class=\"smallhead\" nowrap><a href=\"#def.idle\">").append(_t("Idle")).append("</a><br>");
     352        appendSortLinks(buf, urlBase, sortFlags, _t("Sort by idle inbound"), FLAG_IDLE_IN);
     353        buf.append(" / ");
     354        appendSortLinks(buf, urlBase, sortFlags, _t("Sort by idle outbound"), FLAG_IDLE_OUT);
     355        buf.append("</th>");
     356        buf.append("<th class=\"smallhead\" nowrap><a href=\"#def.rate\">").append(_t("In/Out")).append("</a><br>");
     357        appendSortLinks(buf, urlBase, sortFlags, _t("Sort by inbound rate"), FLAG_RATE_IN);
     358        buf.append(" / ");
     359        appendSortLinks(buf, urlBase, sortFlags, _t("Sort by outbound rate"), FLAG_RATE_OUT);
     360        buf.append("</th>\n");
     361        buf.append("<th class=\"smallhead\" nowrap><a href=\"#def.up\">").append(_t("Up")).append("</a><br>");
     362        appendSortLinks(buf, urlBase, sortFlags, _t("Sort by connection uptime"), FLAG_UPTIME);
     363        buf.append("</th><th class=\"smallhead\" nowrap><a href=\"#def.skew\">").append(_t("Skew")).append("</a><br>");
     364        appendSortLinks(buf, urlBase, sortFlags, _t("Sort by clock skew"), FLAG_SKEW);
     365        buf.append("</th>\n");
     366        buf.append("<th class=\"smallhead\" nowrap><a href=\"#def.cwnd\">CWND</a><br>");
     367        appendSortLinks(buf, urlBase, sortFlags, _t("Sort by congestion window"), FLAG_CWND);
     368        buf.append("</th><th class=\"smallhead\" nowrap><a href=\"#def.ssthresh\">SST</a><br>");
     369        appendSortLinks(buf, urlBase, sortFlags, _t("Sort by slow start threshold"), FLAG_SSTHRESH);
     370        buf.append("</th>\n");
     371        buf.append("<th class=\"smallhead\" nowrap><a href=\"#def.rtt\">RTT</a><br>");
     372        appendSortLinks(buf, urlBase, sortFlags, _t("Sort by round trip time"), FLAG_RTT);
     373        //buf.append("</th><th class=\"smallhead\" nowrap><a href=\"#def.dev\">").append(_t("Dev")).append("</a><br>");
     374        //appendSortLinks(buf, urlBase, sortFlags, _t("Sort by round trip time deviation"), FLAG_DEV);
     375        buf.append("</th><th class=\"smallhead\" nowrap><a href=\"#def.rto\">RTO</a><br>");
     376        appendSortLinks(buf, urlBase, sortFlags, _t("Sort by retransmission timeout"), FLAG_RTO);
     377        buf.append("</th>\n");
     378        buf.append("<th class=\"smallhead\" nowrap><a href=\"#def.mtu\">MTU</a><br>");
     379        appendSortLinks(buf, urlBase, sortFlags, _t("Sort by outbound maximum transmit unit"), FLAG_MTU);
     380        buf.append("</th><th class=\"smallhead\" nowrap><a href=\"#def.send\">").append(_t("TX")).append("</a><br>");
     381        appendSortLinks(buf, urlBase, sortFlags, _t("Sort by packets sent"), FLAG_SEND);
     382        buf.append("</th><th class=\"smallhead\" nowrap><a href=\"#def.recv\">").append(_t("RX")).append("</a><br>");
     383        appendSortLinks(buf, urlBase, sortFlags, _t("Sort by packets received"), FLAG_RECV);
     384        buf.append("</th>\n");
     385        buf.append("<th class=\"smallhead\" nowrap><a href=\"#def.resent\">").append(_t("Dup TX")).append("</a><br>");
     386        appendSortLinks(buf, urlBase, sortFlags, _t("Sort by packets retransmitted"), FLAG_RESEND);
     387        buf.append("</th><th class=\"smallhead\" nowrap><a href=\"#def.dupRecv\">").append(_t("Dup RX")).append("</a><br>");
     388        appendSortLinks(buf, urlBase, sortFlags, _t("Sort by packets received more than once"), FLAG_DUP);
     389        buf.append("</th></tr>\n");
     390        out.write(buf.toString());
     391        buf.setLength(0);
     392        long now = _context.clock().now();
     393        for (PeerState peer : peers) {
     394            if (now-peer.getLastReceiveTime() > 60*60*1000)
     395                continue; // don't include old peers
     396           
     397            buf.append("<tr><td class=\"cells\" align=\"left\" nowrap>");
     398            buf.append(_context.commSystem().renderPeerHTML(peer.getRemotePeer()));
     399            //byte ip[] = peer.getRemoteIP();
     400            //if (ip != null)
     401            //    buf.append(' ').append(_context.blocklist().toStr(ip));
     402            buf.append("</td><td class=\"cells\" nowrap align=\"left\">");
     403            if (peer.isInbound())
     404                buf.append("<img src=\"/themes/console/images/inbound.png\" alt=\"Inbound\" title=\"").append(_t("Inbound")).append("\">");
     405            else
     406                buf.append("<img src=\"/themes/console/images/outbound.png\" alt=\"Outbound\" title=\"").append(_t("Outbound")).append("\">");
     407            if (peer.getWeRelayToThemAs() > 0)
     408                buf.append("&nbsp;&nbsp;<img src=\"/themes/console/images/outbound.png\" height=\"8\" width=\"12\" alt=\"^\" title=\"").append(_t("We offered to introduce them")).append("\">");
     409            if (peer.getTheyRelayToUsAs() > 0)
     410                buf.append("&nbsp;&nbsp;<img src=\"/themes/console/images/inbound.png\" height=\"8\" width=\"12\" alt=\"V\" title=\"").append(_t("They offered to introduce us")).append("\">");
     411           
     412            boolean appended = false;
     413            //if (_activeThrottle.isChoked(peer.getRemotePeer())) {
     414            //    buf.append("<br><i>").append(_t("Choked")).append("</i>");
     415            //    appended = true;
     416            //}
     417            int cfs = peer.getConsecutiveFailedSends();
     418            if (cfs > 0) {
     419                if (!appended) buf.append("<br>");
     420                buf.append(" <i>");
     421                if (cfs == 1)
     422                    buf.append(_t("1 fail"));
     423                else
     424                    buf.append(_t("{0} fails", cfs));
     425                buf.append("</i>");
     426                appended = true;
     427            }
     428            if (_context.banlist().isBanlisted(peer.getRemotePeer(), "SSU")) {
     429                if (!appended) buf.append("<br>");
     430                buf.append(" <i>").append(_t("Banned")).append("</i>");
     431                appended = true;
     432            }
     433            //byte[] ip = getIP(peer.getRemotePeer());
     434            //if (ip != null)
     435            //    buf.append(' ').append(_context.blocklist().toStr(ip));
     436            buf.append("</td>");
     437
     438            buf.append("<td class=\"cells\" align=\"center\">");
     439            if (peer.isIPv6())
     440                buf.append("&#x2713;");
     441            else
     442                buf.append("&nbsp;");
     443            buf.append("</td>");
     444           
     445            long idleIn = Math.max(now-peer.getLastReceiveTime(), 0);
     446            long idleOut = Math.max(now-peer.getLastSendTime(), 0);
     447           
     448            buf.append("<td class=\"cells\" align=\"right\">");
     449            buf.append(DataHelper.formatDuration2(idleIn));
     450            buf.append(THINSP);
     451            buf.append(DataHelper.formatDuration2(idleOut));
     452            buf.append("</td>");
     453 
     454            int recvBps = (idleIn > 15*1000 ? 0 : peer.getReceiveBps());
     455            int sendBps = (idleOut > 15*1000 ? 0 : peer.getSendBps());
     456           
     457            buf.append("<td class=\"cells\" align=\"right\" nowrap>");
     458            buf.append(formatKBps(recvBps));
     459            buf.append(THINSP);
     460            buf.append(formatKBps(sendBps));
     461            //buf.append(" K/s");
     462            //buf.append(formatKBps(peer.getReceiveACKBps()));
     463            //buf.append("K/s/");
     464            //buf.append(formatKBps(peer.getSendACKBps()));
     465            //buf.append("K/s ");
     466            buf.append("</td>");
     467
     468            long uptime = now - peer.getKeyEstablishedTime();
     469           
     470            buf.append("<td class=\"cells\" align=\"right\">");
     471            buf.append(DataHelper.formatDuration2(uptime));
     472            buf.append("</td>");
     473           
     474            buf.append("<td class=\"cells\" align=\"right\">");
     475            long skew = peer.getClockSkew();
     476            buf.append(DataHelper.formatDuration2(skew));
     477            buf.append("</td>");
     478            offsetTotal = offsetTotal + skew;
     479
     480            long sendWindow = peer.getSendWindowBytes();
     481           
     482            buf.append("<td class=\"cells\" align=\"right\">");
     483            buf.append(sendWindow/1024);
     484            buf.append("K");
     485            buf.append(THINSP).append(peer.getConcurrentSends());
     486            buf.append(THINSP).append(peer.getConcurrentSendWindow());
     487            buf.append(THINSP).append(peer.getConsecutiveSendRejections());
     488            if (peer.isBacklogged())
     489                buf.append(' ').append(_t("backlogged"));
     490            buf.append("</td>");
     491
     492            buf.append("<td class=\"cells\" align=\"right\">");
     493            buf.append(peer.getSlowStartThreshold()/1024);
     494            buf.append("K</td>");
     495
     496            int rtt = peer.getRTT();
     497            int rto = peer.getRTO();
     498           
     499            buf.append("<td class=\"cells\" align=\"right\">");
     500            buf.append(DataHelper.formatDuration2(rtt));
     501            buf.append("</td>");
     502           
     503            //buf.append("<td class=\"cells\" align=\"right\">");
     504            //buf.append(DataHelper.formatDuration2(peer.getRTTDeviation()));
     505            //buf.append("</td>");
     506
     507            buf.append("<td class=\"cells\" align=\"right\">");
     508            buf.append(DataHelper.formatDuration2(rto));
     509            buf.append("</td>");
     510           
     511            buf.append("<td class=\"cells\" align=\"right\">");
     512            buf.append(peer.getMTU()).append(THINSP).append(peer.getReceiveMTU());
     513           
     514            //.append('/');
     515            //buf.append(peer.getMTUIncreases()).append('/');
     516            //buf.append(peer.getMTUDecreases());
     517            buf.append("</td>");
     518       
     519            long sent = peer.getMessagesSent();
     520            long recv = peer.getMessagesReceived();
     521           
     522            buf.append("<td class=\"cells\" align=\"right\">");
     523            buf.append(sent);
     524            buf.append("</td>");
     525           
     526            buf.append("<td class=\"cells\" align=\"right\">");
     527            buf.append(recv);
     528            buf.append("</td>");
     529           
     530            //double sent = (double)peer.getPacketsPeriodTransmitted();
     531            //double sendLostPct = 0;
     532            //if (sent > 0)
     533            //    sendLostPct = (double)peer.getPacketsRetransmitted()/(sent);
     534           
     535            long resent = peer.getPacketsRetransmitted();
     536            long dupRecv = peer.getPacketsReceivedDuplicate();
     537           
     538            buf.append("<td class=\"cells\" align=\"right\">");
     539            //buf.append(formatPct(sendLostPct));
     540            buf.append(resent); // + "/" + peer.getPacketsPeriodRetransmitted() + "/" + sent);
     541            //buf.append(peer.getPacketRetransmissionRate());
     542            buf.append("</td>");
     543           
     544            buf.append("<td class=\"cells\" align=\"right\">");
     545            buf.append(dupRecv); //formatPct(recvDupPct));
     546            buf.append("</td>");
     547
     548            buf.append("</tr>\n");
     549            out.write(buf.toString());
     550            buf.setLength(0);
     551           
     552            bpsIn += recvBps;
     553            bpsOut += sendBps;
     554       
     555            uptimeMsTotal += uptime;
     556            cwinTotal += sendWindow;
     557            rttTotal += rtt;
     558            rtoTotal += rto;
     559       
     560            sendTotal += sent;
     561            recvTotal += recv;
     562            resentTotal += resent;
     563            dupRecvTotal += dupRecv;
     564           
     565            numPeers++;
     566        }
     567       
     568      if (numPeers > 0) {
     569//        buf.append("<tr><td colspan=\"16\"><hr></td></tr>\n");
     570        buf.append("<tr class=\"tablefooter\"><td colspan=\"4\" align=\"left\"><b>")
     571           .append(ngettext("{0} peer", "{0} peers", peers.size()))
     572           .append("</b></td>" +
     573                   "<td align=\"center\" nowrap><b>");
     574        buf.append(formatKBps(bpsIn)).append(THINSP).append(formatKBps(bpsOut));
     575        long x = uptimeMsTotal/numPeers;
     576        buf.append("</b></td>" +
     577                   "<td align=\"center\"><b>").append(DataHelper.formatDuration2(x));
     578        x = offsetTotal/numPeers;
     579        buf.append("</b></td><td align=\"center\"><b>").append(DataHelper.formatDuration2(x)).append("</b></td>\n" +
     580                   "<td align=\"center\"><b>");
     581        buf.append(cwinTotal/(numPeers*1024) + "K");
     582        buf.append("</b></td><td>&nbsp;</td>\n" +
     583                   "<td align=\"center\"><b>");
     584        buf.append(DataHelper.formatDuration2(rttTotal/numPeers));
     585        //buf.append("</b></td><td>&nbsp;</td><td align=\"center\"><b>");
     586        buf.append("</b></td><td align=\"center\"><b>");
     587        buf.append(DataHelper.formatDuration2(rtoTotal/numPeers));
     588        buf.append("</b></td><td align=\"center\"><b>").append(ut.getMTU(false)).append("</b></td><td align=\"center\"><b>");
     589        buf.append(sendTotal).append("</b></td><td align=\"center\"><b>").append(recvTotal).append("</b></td>\n" +
     590                   "<td align=\"center\"><b>").append(resentTotal);
     591        buf.append("</b></td><td align=\"center\"><b>").append(dupRecvTotal).append("</b></td></tr>\n");
     592/****
     593        if (sortFlags == FLAG_DEBUG) {
     594            buf.append("<tr><td colspan=\"16\">");
     595            buf.append("peersByIdent: ").append(_peersByIdent.size());
     596            buf.append(" peersByRemoteHost: ").append(_peersByRemoteHost.size());
     597            int dir = 0;
     598            int indir = 0;
     599            for (RemoteHostId rhi : _peersByRemoteHost.keySet()) {
     600                 if (rhi.getIP() != null)
     601                     dir++;
     602                 else
     603                     indir++;
     604            }
     605            buf.append(" pBRH direct: ").append(dir).append(" indirect: ").append(indir);
     606            buf.append("</td></tr>");
     607        }
     608****/
     609     }  // numPeers > 0
     610        buf.append("</table></div>\n");
     611
     612      /*****
     613        long bytesTransmitted = _context.bandwidthLimiter().getTotalAllocatedOutboundBytes();
     614        // NPE here early
     615        double averagePacketSize = _context.statManager().getRate("udp.sendPacketSize").getLifetimeAverageValue();
     616        // lifetime value, not just the retransmitted packets of current connections
     617        resentTotal = (long)_context.statManager().getRate("udp.packetsRetransmitted").getLifetimeEventCount();
     618        double nondupSent = ((double)bytesTransmitted - ((double)resentTotal)*averagePacketSize);
     619        double bwResent = (nondupSent <= 0 ? 0d : ((((double)resentTotal)*averagePacketSize) / nondupSent));
     620        buf.append("<h3>Percentage of bytes retransmitted (lifetime): ").append(formatPct(bwResent));
     621        buf.append("</h3><i>(Includes retransmission required by packet loss)</i>\n");
     622      *****/
     623
     624        out.write(buf.toString());
     625        buf.setLength(0);
     626    }
     627
     628    private static final DecimalFormat _fmt = new DecimalFormat("#,##0.00");
     629
     630    private static final String formatKBps(int bps) {
     631        synchronized (_fmt) {
     632            return _fmt.format((float)bps/1024);
     633        }
     634    }
    35635}
  • apps/routerconsole/java/src/net/i2p/router/web/UDPSorters.java

    rb7baeddc rdc33ad10  
    1 package net.i2p.router.transport.udp;
     1package net.i2p.router.web;
    22
    33import java.io.Serializable;
     
    66
    77import net.i2p.data.DataHelper;
     8import net.i2p.router.transport.udp.PeerState;
    89
    910/**
    1011 *  Comparators for various columns
    1112 *
    12  *  @since 0.9.18 moved from UDPTransport
     13 *  @since 0.9.31 moved from udp; 0.9.18 moved from UDPTransport
    1314 */
    14 class Sorters {
     15class UDPSorters {
    1516
    1617    static final int FLAG_ALPHA = 0;
  • history.txt

    rb7baeddc rdc33ad10  
     12017-05-19 zzz
     2 * Console: Move /peers page rendering from router to console (ticket #1879)
     3
    142017-05-18 str4d
    25Prop from i2p.i2p.str4d.ui:
     
    5861
    59622017-05-14 zzz
     63 * Crypto: Fix AES NPE on 4-core RPi (ticket #1989)
    6064 * i2psnark: Fix HTML double-escape (ticket #1992)
    6165 * Router: New method to get bandwidth class
  • router/java/src/net/i2p/router/RouterVersion.java

    rb7baeddc rdc33ad10  
    1919    public final static String ID = "Monotone";
    2020    public final static String VERSION = CoreVersion.VERSION;
    21     public final static long BUILD = 5;
     21    public final static long BUILD = 6;
    2222
    2323    /** for example "-test" */
  • router/java/src/net/i2p/router/transport/CommSystemFacadeImpl.java

    rb7baeddc rdc33ad10  
    1515import java.util.List;
    1616import java.util.Locale;
     17import java.util.SortedMap;
    1718import java.util.Vector;
    1819
     
    211212    public void recheckReachability() { _manager.recheckReachability(); }
    212213
     214    /**
     215     *  As of 0.9.31, only outputs UPnP status
     216     *
     217     *  Warning - blocking, very slow, queries the active UPnP router,
     218     *  will take many seconds if it has vanished.
     219     */
    213220    @Override
    214221    public void renderStatusHTML(Writer out, String urlBase, int sortFlags) throws IOException {
    215222        _manager.renderStatusHTML(out, urlBase, sortFlags);
     223    }
     224   
     225    /**
     226     *  @return SortedMap of style to Transport (a copy)
     227     *  @since 0.9.31
     228     */
     229    public SortedMap<String, Transport> getTransports() {
     230        return _manager.getTransports();
    216231    }
    217232   
  • router/java/src/net/i2p/router/transport/TransportManager.java

    rb7baeddc rdc33ad10  
    2020import java.util.Map;
    2121import java.util.Set;
     22import java.util.SortedMap;
    2223import java.util.TreeMap;
    2324import java.util.Vector;
     
    344345   
    345346    /**
     347     *  @return SortedMap of style to Transport (a copy)
     348     *  @since 0.9.31
     349     */
     350    public SortedMap<String, Transport> getTransports() {
     351        TreeMap<String, Transport> rv = new TreeMap<String, Transport>();
     352        rv.putAll(_transports);
     353        // TODO (also synch)
     354        //rv.putAll(_pluggableTransports);
     355        return rv;
     356    }
     357
     358    /**
    346359     *  How many peers are we currently connected to, that we have
    347360     *  sent a message to or received a message from in the last five minutes.
     
    717730   
    718731    /**
     732     *  As of 0.9.31, only outputs UPnP status
     733     *
    719734     *  Warning - blocking, very slow, queries the active UPnP router,
    720735     *  will take many seconds if it has vanished.
    721736     */
    722737    public void renderStatusHTML(Writer out, String urlBase, int sortFlags) throws IOException {
    723         if (_context.getBooleanProperty(PROP_ADVANCED)) {
    724             out.write("<p id=\"upnpstatus\"><b>");
    725             out.write(_t("Status"));
    726             out.write(": ");
    727             out.write(_t(getReachabilityStatus().toStatusString()));
    728             out.write("</b></p>");
    729         }
    730         TreeMap<String, Transport> transports = new TreeMap<String, Transport>();
    731         for (Transport t : _transports.values()) {
    732             transports.put(t.getStyle(), t);
    733         }
    734         for (Transport t : transports.values()) {
    735             t.renderStatusHTML(out, urlBase, sortFlags);
    736         }
    737        
    738         if (!_transports.isEmpty()) {
    739             out.write(getTransportsLegend());
    740         }
    741 
    742         StringBuilder buf = new StringBuilder(4*1024);
    743         buf.append("<h3 id=\"transports\">").append(_t("Router Transport Addresses")).append("</h3><pre id=\"transports\">\n");
    744         for (Transport t : _transports.values()) {
    745             if (t.hasCurrentAddress()) {
    746                 for (RouterAddress ra : t.getCurrentAddresses()) {
    747                     buf.append(ra.toString());
    748                     buf.append("\n\n");
    749                 }
    750             } else {
    751                 buf.append(_t("{0} is used for outbound connections only", t.getStyle()));
    752                 buf.append("\n\n");
    753             }
    754         }
    755         buf.append("</pre>\n");
    756         out.write(buf.toString());
    757738        if (SystemVersion.isAndroid()) {
    758739            // newer androids crash w/ network on IO thread
     
    762743            out.write("<h3 id=\"upnpstatus\"><a name=\"upnp\"></a>" + _t("UPnP is not enabled") + "</h3>\n");
    763744        }
    764         out.write("</p>\n");
    765         out.flush();
    766     }
    767 
    768 
    769     private final String getTransportsLegend() {
    770         StringBuilder buf = new StringBuilder(1024);
    771         buf.append("<p class=\"infohelp\">")
    772            .append(_t("Your transport connection limits are automatically set based on your configured bandwidth."))
    773            .append('\n')
    774            .append(_t("To override these limits, add the settings i2np.ntcp.maxConnections=nnn and i2np.udp.maxConnections=nnn on the advanced configuration page."))
    775            .append("</p>\n");
    776         buf.append("<h3 class=\"tabletitle\">").append(_t("Definitions")).append("</h3>")
    777            .append("<table id=\"peerdefs\">\n")
    778            .append("<tr><td><b id=\"def.peer\">").append(_t("Peer")).append("</b></td><td>").append(_t("The remote peer, identified by router hash")).append("</td></tr>\n")
    779            .append("<tr><td><b id=\"def.dir\">").append(_t("Dir")).append("</b></td><td><img alt=\"Inbound\" src=\"/themes/console/images/inbound.png\"> ").append(_t("Inbound connection")).append("</td></tr>\n")
    780            .append("<tr><td></td><td><img alt=\"Outbound\" src=\"/themes/console/images/outbound.png\"> ").append(_t("Outbound connection")).append("</td></tr>\n")
    781            .append("<tr><td></td><td><img src=\"/themes/console/images/inbound.png\" alt=\"V\" height=\"8\" width=\"12\"> ").append(_t("They offered to introduce us (help other peers traverse our firewall)")).append("</td></tr>\n")
    782            .append("<tr><td></td><td><img src=\"/themes/console/images/outbound.png\" alt=\"^\" height=\"8\" width=\"12\"> ").append(_t("We offered to introduce them (help other peers traverse their firewall)")).append("</td></tr>\n")
    783            .append("<tr><td><b id=\"def.idle\">").append(_t("Idle")).append("</b></td><td>").append(_t("How long since a packet has been received / sent")).append("</td></tr>\n")
    784            .append("<tr><td><b id=\"def.rate\">").append(_t("In/Out")).append("</b></td><td>").append(_t("The smoothed inbound / outbound transfer rate (KBytes per second)")).append("</td></tr>\n")
    785            .append("<tr><td><b id=\"def.up\">").append(_t("Up")).append("</b></td><td>").append(_t("How long ago this connection was established")).append("</td></tr>\n")
    786            .append("<tr><td><b id=\"def.skew\">").append(_t("Skew")).append("</b></td><td>").append(_t("The difference between the peer's clock and your own")).append("</td></tr>\n")
    787            .append("<tr><td><b id=\"def.cwnd\">CWND</b></td><td>").append(_t("The congestion window, which is how many bytes can be sent without an acknowledgement")).append(" / </td></tr>\n")
    788            .append("<tr><td></td><td>").append(_t("The number of sent messages awaiting acknowledgement")).append(" /</td></tr>\n")
    789            .append("<tr><td></td><td>").append(_t("The maximum number of concurrent messages to send")).append(" /</td></tr>\n")
    790            .append("<tr><td></td><td>").append(_t("The number of pending sends which exceed congestion window")).append("</td></tr>\n")
    791            .append("<tr><td><b id=\"def.ssthresh\">SST</b></td><td>").append(_t("The slow start threshold")).append("</td></tr>\n")
    792            .append("<tr><td><b id=\"def.rtt\">RTT</b></td><td>").append(_t("The round trip time in milliseconds")).append("</td></tr>\n")
    793            //.append("<tr><td><b id=\"def.dev\">").append(_t("Dev")).append("</b></td><td>").append(_t("The standard deviation of the round trip time in milliseconds")).append("</td></tr>\n")
    794            .append("<tr><td><b id=\"def.rto\">RTO</b></td><td>").append(_t("The retransmit timeout in milliseconds")).append("</td></tr>\n")
    795            .append("<tr><td><b id=\"def.mtu\">MTU</b></td><td>").append(_t("Current maximum send packet size / estimated maximum receive packet size (bytes)")).append("</td></tr>\n")
    796            .append("<tr><td><b id=\"def.send\">").append(_t("TX")).append("</b></td><td>").append(_t("The total number of messages sent to the peer")).append("</td></tr>\n")
    797            .append("<tr><td><b id=\"def.recv\">").append(_t("RX")).append("</b></td><td>").append(_t("The total number of messages received from the peer")).append("</td></tr>\n")
    798            .append("<tr><td><b id=\"def.resent\">").append(_t("Dup TX")).append("</b></td><td>").append(_t("The total number of packets retransmitted to the peer")).append("</td></tr>\n")
    799            .append("<tr><td><b id=\"def.dupRecv\">").append(_t("Dup RX")).append("</b></td><td>").append(_t("The total number of duplicate packets received from the peer")).append("</td></tr>\n")
    800            .append("</table>");
    801         return buf.toString();
    802     }
    803 
     745    }
    804746   
    805747    /**
     
    813755    }
    814756
    815 
    816757    private static final String BUNDLE_NAME = "net.i2p.router.web.messages";
    817758
     
    822763        return Translate.getString(s, _context, BUNDLE_NAME);
    823764    }
    824 
    825     /**
    826      *  Translate
    827      */
    828     private final String _t(String s, Object o) {
    829         return Translate.getString(s, o, _context, BUNDLE_NAME);
    830     }
    831765}
  • router/java/src/net/i2p/router/transport/ntcp/NTCPConnection.java

    rb7baeddc rdc33ad10  
    4545 * Coordinate the connection to a single peer.
    4646 *
     47 * Public only for UI peers page. Not a public API, not for external use.
     48 *
    4749 * The NTCP transport sends individual I2NP messages AES/256/CBC encrypted with
    4850 * a simple checksum.  The unencrypted message is encoded as follows:
     
    6769 *
    6870 */
    69 class NTCPConnection implements Closeable {
     71public class NTCPConnection implements Closeable {
    7072    private final RouterContext _context;
    7173    private final Log _log;
  • router/java/src/net/i2p/router/transport/ntcp/NTCPTransport.java

    rb7baeddc rdc33ad10  
    1212import java.text.NumberFormat;
    1313import java.util.ArrayList;
     14import java.util.Collection;
    1415import java.util.Collections;
    1516import java.util.Comparator;
     
    524525            return _conByIdent.size();
    525526    }
     527   
     528    /**
     529     * For /peers UI only. Not a public API, not for external use.
     530     *
     531     * @return not a copy, do not modify
     532     * @since 0.9.31
     533     */
     534    public Collection<NTCPConnection> getPeers() {
     535        return _conByIdent.values();
     536    }
    526537
    527538    /**
     
    13411352    public void renderStatusHTML(java.io.Writer out, int sortFlags) throws IOException {}
    13421353
     1354    /**
     1355     * Does nothing
     1356     * @deprecated as of 0.9.31
     1357     */
    13431358    @Override
     1359    @Deprecated
    13441360    public void renderStatusHTML(java.io.Writer out, String urlBase, int sortFlags) throws IOException {
    1345         TreeSet<NTCPConnection> peers = new TreeSet<NTCPConnection>(getComparator(sortFlags));
    1346         peers.addAll(_conByIdent.values());
    1347 
    1348         long offsetTotal = 0;
    1349         float bpsSend = 0;
    1350         float bpsRecv = 0;
    1351         long totalUptime = 0;
    1352         long totalSend = 0;
    1353         long totalRecv = 0;
    1354 
    1355         if (!_context.getBooleanProperty(PROP_ADVANCED)) {
    1356             for (Iterator<NTCPConnection> iter = peers.iterator(); iter.hasNext(); ) {
    1357                  // outbound conns get put in the map before they are established
    1358                  if (!iter.next().isEstablished())
    1359                      iter.remove();
    1360             }
    1361         }
    1362 
    1363         StringBuilder buf = new StringBuilder(512);
    1364         buf.append("<h3 id=\"ntcpcon\">").append(_t("NTCP connections")).append(": ").append(peers.size());
    1365         buf.append(". ").append(_t("Limit")).append(": ").append(getMaxConnections());
    1366         buf.append(". ").append(_t("Timeout")).append(": ").append(DataHelper.formatDuration2(_pumper.getIdleTimeout()));
    1367         if (_context.getBooleanProperty(PROP_ADVANCED)) {
    1368             buf.append(". ").append(_t("Status")).append(": ").append(_t(getReachabilityStatus().toStatusString()));
    1369         }
    1370         buf.append(".</h3>\n" +
    1371                    "<div class=\"widescroll\"><table id=\"ntcpconnections\">\n" +
    1372                    "<tr><th><a href=\"#def.peer\">").append(_t("Peer")).append("</a></th>" +
    1373                    "<th>").append(_t("Dir")).append("</th>" +
    1374                    "<th>").append(_t("IPv6")).append("</th>" +
    1375                    "<th align=\"right\"><a href=\"#def.idle\">").append(_t("Idle")).append("</a></th>" +
    1376                    "<th align=\"right\"><a href=\"#def.rate\">").append(_t("In/Out")).append("</a></th>" +
    1377                    "<th align=\"right\"><a href=\"#def.up\">").append(_t("Up")).append("</a></th>" +
    1378                    "<th align=\"right\"><a href=\"#def.skew\">").append(_t("Skew")).append("</a></th>" +
    1379                    "<th align=\"right\"><a href=\"#def.send\">").append(_t("TX")).append("</a></th>" +
    1380                    "<th align=\"right\"><a href=\"#def.recv\">").append(_t("RX")).append("</a></th>" +
    1381                    "<th>").append(_t("Out Queue")).append("</th>" +
    1382                    "<th title=\"").append(_t("Is peer backlogged?")).append("\">").append(_t("Backlogged?")).append("</th>" +
    1383                    //"<th>").append(_t("Reading?")).append("</th>" +
    1384                    " </tr>\n");
    1385         out.write(buf.toString());
    1386         buf.setLength(0);
    1387         for (NTCPConnection con : peers) {
    1388             buf.append("<tr><td class=\"cells\" align=\"left\" nowrap>");
    1389             buf.append(_context.commSystem().renderPeerHTML(con.getRemotePeer().calculateHash()));
    1390             //byte[] ip = getIP(con.getRemotePeer().calculateHash());
    1391             //if (ip != null)
    1392             //    buf.append(' ').append(_context.blocklist().toStr(ip));
    1393             buf.append("</td><td class=\"cells\" align=\"center\">");
    1394             if (con.isInbound())
    1395                 buf.append("<img src=\"/themes/console/images/inbound.png\" alt=\"Inbound\" title=\"").append(_t("Inbound")).append("\"/>");
    1396             else
    1397                 buf.append("<img src=\"/themes/console/images/outbound.png\" alt=\"Outbound\" title=\"").append(_t("Outbound")).append("\"/>");
    1398             buf.append("</td><td class=\"cells\" align=\"center\">");
    1399             if (con.isIPv6())
    1400                 buf.append("<span class=\"backlogged\">&#x2714;</span>");
    1401             else
    1402                 buf.append("&nbsp;");
    1403             buf.append("</td><td class=\"cells\" align=\"right\">");
    1404             buf.append(DataHelper.formatDuration2(con.getTimeSinceReceive()));
    1405             buf.append(THINSP).append(DataHelper.formatDuration2(con.getTimeSinceSend()));
    1406             buf.append("</td><td class=\"cells\" align=\"right\">");
    1407             if (con.getTimeSinceReceive() < 2*60*1000) {
    1408                 float r = con.getRecvRate();
    1409                 buf.append(formatRate(r / 1024));
    1410                 bpsRecv += r;
    1411             } else {
    1412                 buf.append(formatRate(0));
    1413             }
    1414             buf.append(THINSP);
    1415             if (con.getTimeSinceSend() < 2*60*1000) {
    1416                 float r = con.getSendRate();
    1417                 buf.append(formatRate(r / 1024));
    1418                 bpsSend += r;
    1419             } else {
    1420                 buf.append(formatRate(0));
    1421             }
    1422             //buf.append(" K/s");
    1423             buf.append("</td><td class=\"cells\" align=\"right\">").append(DataHelper.formatDuration2(con.getUptime()));
    1424             totalUptime += con.getUptime();
    1425             offsetTotal = offsetTotal + con.getClockSkew();
    1426             buf.append("</td><td class=\"cells\" align=\"right\">").append(DataHelper.formatDuration2(1000 * con.getClockSkew()));
    1427             buf.append("</td><td class=\"cells\" align=\"right\">").append(con.getMessagesSent());
    1428             totalSend += con.getMessagesSent();
    1429             buf.append("</td><td class=\"cells\" align=\"right\">").append(con.getMessagesReceived());
    1430             totalRecv += con.getMessagesReceived();
    1431             long outQueue = con.getOutboundQueueSize();
    1432             buf.append("</td><td class=\"cells\" align=\"center\">").append(outQueue);
    1433             buf.append("</td><td class=\"cells\" align=\"center\">");
    1434             if (con.isBacklogged())
    1435                 buf.append("<span class=\"backlogged\">&#x2714;</span>");
    1436             else
    1437                 buf.append("&nbsp;");
    1438             //long readTime = con.getReadTime();
    1439             //if (readTime <= 0) {
    1440             //    buf.append("</td> <td class=\"cells\" align=\"center\">0");
    1441             //} else {
    1442             //    buf.append("</td> <td class=\"cells\" align=\"center\">").append(DataHelper.formatDuration(readTime));
    1443             //}
    1444             buf.append("</td></tr>\n");
    1445             out.write(buf.toString());
    1446             buf.setLength(0);
    1447         }
    1448 
    1449         if (!peers.isEmpty()) {
    1450 //            buf.append("<tr> <td colspan=\"11\"><hr></td></tr>\n");
    1451             buf.append("<tr class=\"tablefooter\"><td colspan=\"4\" align=\"left\"><b>")
    1452                .append(ngettext("{0} peer", "{0} peers", peers.size()));
    1453             buf.append("</b></td><td align=\"center\"><b>").append(formatRate(bpsRecv/1024)).append(THINSP).append(formatRate(bpsSend/1024)).append("</b>");
    1454             buf.append("</td><td align=\"center\"><b>").append(DataHelper.formatDuration2(totalUptime/peers.size()));
    1455             buf.append("</b></td><td align=\"center\"><b>").append(DataHelper.formatDuration2(offsetTotal*1000/peers.size()));
    1456             buf.append("</b></td><td align=\"center\"><b>").append(totalSend).append("</b></td><td align=\"center\"><b>").append(totalRecv);
    1457             buf.append("</b></td><td>&nbsp;</td><td>&nbsp;</td></tr>\n");
    1458         }
    1459 
    1460         buf.append("</table></div>\n");
    1461         out.write(buf.toString());
    1462         buf.setLength(0);
    1463     }
    1464 
    1465     private static final NumberFormat _rateFmt = new DecimalFormat("#,##0.00");
    1466 
    1467     private static String formatRate(float rate) {
    1468         synchronized (_rateFmt) { return _rateFmt.format(rate); }
    1469     }
    1470 
    1471     private Comparator<NTCPConnection> getComparator(int sortFlags) {
    1472         Comparator<NTCPConnection> rv = null;
    1473         switch (Math.abs(sortFlags)) {
    1474             default:
    1475                 rv = AlphaComparator.instance();
    1476         }
    1477         if (sortFlags < 0)
    1478             rv = Collections.reverseOrder(rv);
    1479         return rv;
    1480     }
    1481 
    1482     private static class AlphaComparator extends PeerComparator {
    1483         private static final AlphaComparator _instance = new AlphaComparator();
    1484         public static final AlphaComparator instance() { return _instance; }
    1485     }
    1486 
    1487     private static class PeerComparator implements Comparator<NTCPConnection>, Serializable {
    1488         public int compare(NTCPConnection l, NTCPConnection r) {
    1489             if (l == null || r == null)
    1490                 throw new IllegalArgumentException();
    1491             // base64 retains binary ordering
    1492             // UM, no it doesn't, but close enough
    1493             return l.getRemotePeer().calculateHash().toBase64().compareTo(r.getRemotePeer().calculateHash().toBase64());
    1494         }
    14951361    }
    14961362
  • router/java/src/net/i2p/router/transport/udp/PeerState.java

    rb7baeddc rdc33ad10  
    2727 * Contain all of the state about a UDP connection to a peer.
    2828 * This is instantiated only after a connection is fully established.
     29 *
     30 * Public only for UI peers page. Not a public API, not for external use.
     31 *
    2932 */
    30 class PeerState {
     33public class PeerState {
    3134    private final RouterContext _context;
    3235    private final Log _log;
  • router/java/src/net/i2p/router/transport/udp/UDPTransport.java

    rb7baeddc rdc33ad10  
    1010import java.util.ArrayList;
    1111import java.util.Arrays;
     12import java.util.Collection;
    1213import java.util.HashMap;
    1314import java.util.HashSet;
     
    775776     * To be used as the "large" MTU.
    776777     * @return limited to range PeerState.MIN_MTU to PeerState.LARGE_MTU.
    777      * @since 0.9.2
    778      */
    779     int getMTU(boolean ipv6) {
     778     * @since 0.9.2, public since 0.9.31
     779     */
     780    public int getMTU(boolean ipv6) {
    780781        // TODO multiple interfaces of each type
    781782        return ipv6 ? _mtu_ipv6 : _mtu;
     
    11671168    }
    11681169   
     1170    /**
     1171     * For /peers UI only. Not a public API, not for external use.
     1172     *
     1173     * @return not a copy, do not modify
     1174     * @since 0.9.31
     1175     */
     1176    public Collection<PeerState> getPeers() {
     1177        return _peersByIdent.values();
     1178    }
     1179
    11691180    /**
    11701181     *  Remove and add to peersByRemoteHost map
     
    26472658    }
    26482659   
     2660    /**
     2661     * Does nothing
     2662     * @deprecated as of 0.9.31
     2663     */
    26492664    @Override
     2665    @Deprecated
    26502666    public void renderStatusHTML(Writer out, String urlBase, int sortFlags) throws IOException {
    2651         TreeSet<PeerState> peers = new TreeSet<PeerState>(getComparator(sortFlags));
    2652         peers.addAll(_peersByIdent.values());
    2653         long offsetTotal = 0;
    2654 
    2655         int bpsIn = 0;
    2656         int bpsOut = 0;
    2657         long uptimeMsTotal = 0;
    2658         long cwinTotal = 0;
    2659         long rttTotal = 0;
    2660         long rtoTotal = 0;
    2661         long sendTotal = 0;
    2662         long recvTotal = 0;
    2663         long resentTotal = 0;
    2664         long dupRecvTotal = 0;
    2665         int numPeers = 0;
    2666        
    2667         StringBuilder buf = new StringBuilder(512);
    2668         buf.append("<h3 id=\"udpcon\">").append(_t("UDP connections")).append(": ").append(peers.size());
    2669         buf.append(". ").append(_t("Limit")).append(": ").append(getMaxConnections());
    2670         buf.append(". ").append(_t("Timeout")).append(": ").append(DataHelper.formatDuration2(_expireTimeout));
    2671         if (_context.getBooleanProperty(PROP_ADVANCED)) {
    2672             buf.append(". ").append(_t("Status")).append(": ").append(_t(_reachabilityStatus.toStatusString()));
    2673         }
    2674         buf.append(".</h3>\n");
    2675         buf.append("<div class=\"widescroll\"><table id=\"udpconnections\">\n");
    2676         buf.append("<tr><th class=\"smallhead\" nowrap><a href=\"#def.peer\">").append(_t("Peer")).append("</a><br>");
    2677         if (sortFlags != FLAG_ALPHA)
    2678             appendSortLinks(buf, urlBase, sortFlags, _t("Sort by peer hash"), FLAG_ALPHA);
    2679         buf.append("</th><th class=\"smallhead\" nowrap><a href=\"#def.dir\" title=\"")
    2680            .append(_t("Direction/Introduction")).append("\">").append(_t("Dir"))
    2681            .append("</a></th><th class=\"smallhead\" nowrap><a href=\"#def.ipv6\">").append(_t("IPv6"))
    2682            .append("</a></th><th class=\"smallhead\" nowrap><a href=\"#def.idle\">").append(_t("Idle")).append("</a><br>");
    2683         appendSortLinks(buf, urlBase, sortFlags, _t("Sort by idle inbound"), FLAG_IDLE_IN);
    2684         buf.append(" / ");
    2685         appendSortLinks(buf, urlBase, sortFlags, _t("Sort by idle outbound"), FLAG_IDLE_OUT);
    2686         buf.append("</th>");
    2687         buf.append("<th class=\"smallhead\" nowrap><a href=\"#def.rate\">").append(_t("In/Out")).append("</a><br>");
    2688         appendSortLinks(buf, urlBase, sortFlags, _t("Sort by inbound rate"), FLAG_RATE_IN);
    2689         buf.append(" / ");
    2690         appendSortLinks(buf, urlBase, sortFlags, _t("Sort by outbound rate"), FLAG_RATE_OUT);
    2691         buf.append("</th>\n");
    2692         buf.append("<th class=\"smallhead\" nowrap><a href=\"#def.up\">").append(_t("Up")).append("</a><br>");
    2693         appendSortLinks(buf, urlBase, sortFlags, _t("Sort by connection uptime"), FLAG_UPTIME);
    2694         buf.append("</th><th class=\"smallhead\" nowrap><a href=\"#def.skew\">").append(_t("Skew")).append("</a><br>");
    2695         appendSortLinks(buf, urlBase, sortFlags, _t("Sort by clock skew"), FLAG_SKEW);
    2696         buf.append("</th>\n");
    2697         buf.append("<th class=\"smallhead\" nowrap><a href=\"#def.cwnd\">CWND</a><br>");
    2698         appendSortLinks(buf, urlBase, sortFlags, _t("Sort by congestion window"), FLAG_CWND);
    2699         buf.append("</th><th class=\"smallhead\" nowrap><a href=\"#def.ssthresh\">SST</a><br>");
    2700         appendSortLinks(buf, urlBase, sortFlags, _t("Sort by slow start threshold"), FLAG_SSTHRESH);
    2701         buf.append("</th>\n");
    2702         buf.append("<th class=\"smallhead\" nowrap><a href=\"#def.rtt\">RTT</a><br>");
    2703         appendSortLinks(buf, urlBase, sortFlags, _t("Sort by round trip time"), FLAG_RTT);
    2704         //buf.append("</th><th class=\"smallhead\" nowrap><a href=\"#def.dev\">").append(_t("Dev")).append("</a><br>");
    2705         //appendSortLinks(buf, urlBase, sortFlags, _t("Sort by round trip time deviation"), FLAG_DEV);
    2706         buf.append("</th><th class=\"smallhead\" nowrap><a href=\"#def.rto\">RTO</a><br>");
    2707         appendSortLinks(buf, urlBase, sortFlags, _t("Sort by retransmission timeout"), FLAG_RTO);
    2708         buf.append("</th>\n");
    2709         buf.append("<th class=\"smallhead\" nowrap><a href=\"#def.mtu\">MTU</a><br>");
    2710         appendSortLinks(buf, urlBase, sortFlags, _t("Sort by outbound maximum transmit unit"), FLAG_MTU);
    2711         buf.append("</th><th class=\"smallhead\" nowrap><a href=\"#def.send\">").append(_t("TX")).append("</a><br>");
    2712         appendSortLinks(buf, urlBase, sortFlags, _t("Sort by packets sent"), FLAG_SEND);
    2713         buf.append("</th><th class=\"smallhead\" nowrap><a href=\"#def.recv\">").append(_t("RX")).append("</a><br>");
    2714         appendSortLinks(buf, urlBase, sortFlags, _t("Sort by packets received"), FLAG_RECV);
    2715         buf.append("</th>\n");
    2716         buf.append("<th class=\"smallhead\" nowrap><a href=\"#def.resent\">").append(_t("Dup TX")).append("</a><br>");
    2717         appendSortLinks(buf, urlBase, sortFlags, _t("Sort by packets retransmitted"), FLAG_RESEND);
    2718         buf.append("</th><th class=\"smallhead\" nowrap><a href=\"#def.dupRecv\">").append(_t("Dup RX")).append("</a><br>");
    2719         appendSortLinks(buf, urlBase, sortFlags, _t("Sort by packets received more than once"), FLAG_DUP);
    2720         buf.append("</th></tr>\n");
    2721         out.write(buf.toString());
    2722         buf.setLength(0);
    2723         long now = _context.clock().now();
    2724         for (PeerState peer : peers) {
    2725             if (now-peer.getLastReceiveTime() > 60*60*1000)
    2726                 continue; // don't include old peers
    2727            
    2728             buf.append("<tr><td class=\"cells\" align=\"left\" nowrap>");
    2729             buf.append(_context.commSystem().renderPeerHTML(peer.getRemotePeer()));
    2730             //byte ip[] = peer.getRemoteIP();
    2731             //if (ip != null)
    2732             //    buf.append(' ').append(_context.blocklist().toStr(ip));
    2733             buf.append("</td><td class=\"cells\" nowrap align=\"left\">");
    2734             if (peer.isInbound())
    2735                 buf.append("<img src=\"/themes/console/images/inbound.png\" alt=\"Inbound\" title=\"").append(_t("Inbound")).append("\">");
    2736             else
    2737                 buf.append("<img src=\"/themes/console/images/outbound.png\" alt=\"Outbound\" title=\"").append(_t("Outbound")).append("\">");
    2738             if (peer.getWeRelayToThemAs() > 0)
    2739                 buf.append("&nbsp;&nbsp;<img src=\"/themes/console/images/outbound.png\" height=\"8\" width=\"12\" alt=\"^\" title=\"").append(_t("We offered to introduce them")).append("\">");
    2740             if (peer.getTheyRelayToUsAs() > 0)
    2741                 buf.append("&nbsp;&nbsp;<img src=\"/themes/console/images/inbound.png\" height=\"8\" width=\"12\" alt=\"V\" title=\"").append(_t("They offered to introduce us")).append("\">");
    2742            
    2743             boolean appended = false;
    2744             if (_activeThrottle.isChoked(peer.getRemotePeer())) {
    2745                 buf.append("<br><i>").append(_t("Choked")).append("</i>");
    2746                 appended = true;
    2747             }
    2748             int cfs = peer.getConsecutiveFailedSends();
    2749             if (cfs > 0) {
    2750                 if (!appended) buf.append("<br>");
    2751                 buf.append(" <i>");
    2752                 if (cfs == 1)
    2753                     buf.append(_t("1 fail"));
    2754                 else
    2755                     buf.append(_t("{0} fails", cfs));
    2756                 buf.append("</i>");
    2757                 appended = true;
    2758             }
    2759             if (_context.banlist().isBanlisted(peer.getRemotePeer(), STYLE)) {
    2760                 if (!appended) buf.append("<br>");
    2761                 buf.append(" <i>").append(_t("Banned")).append("</i>");
    2762                 appended = true;
    2763             }
    2764             //byte[] ip = getIP(peer.getRemotePeer());
    2765             //if (ip != null)
    2766             //    buf.append(' ').append(_context.blocklist().toStr(ip));
    2767             buf.append("</td>");
    2768 
    2769             buf.append("<td class=\"cells\" align=\"center\">");
    2770             if (peer.isIPv6())
    2771                 buf.append("&#x2713;");
    2772             else
    2773                 buf.append("&nbsp;");
    2774             buf.append("</td>");
    2775            
    2776             long idleIn = Math.max(now-peer.getLastReceiveTime(), 0);
    2777             long idleOut = Math.max(now-peer.getLastSendTime(), 0);
    2778            
    2779             buf.append("<td class=\"cells\" align=\"right\">");
    2780             buf.append(DataHelper.formatDuration2(idleIn));
    2781             buf.append(THINSP);
    2782             buf.append(DataHelper.formatDuration2(idleOut));
    2783             buf.append("</td>");
    2784  
    2785             int recvBps = (idleIn > 15*1000 ? 0 : peer.getReceiveBps());
    2786             int sendBps = (idleOut > 15*1000 ? 0 : peer.getSendBps());
    2787            
    2788             buf.append("<td class=\"cells\" align=\"right\" nowrap>");
    2789             buf.append(formatKBps(recvBps));
    2790             buf.append(THINSP);
    2791             buf.append(formatKBps(sendBps));
    2792             //buf.append(" K/s");
    2793             //buf.append(formatKBps(peer.getReceiveACKBps()));
    2794             //buf.append("K/s/");
    2795             //buf.append(formatKBps(peer.getSendACKBps()));
    2796             //buf.append("K/s ");
    2797             buf.append("</td>");
    2798 
    2799             long uptime = now - peer.getKeyEstablishedTime();
    2800            
    2801             buf.append("<td class=\"cells\" align=\"right\">");
    2802             buf.append(DataHelper.formatDuration2(uptime));
    2803             buf.append("</td>");
    2804            
    2805             buf.append("<td class=\"cells\" align=\"right\">");
    2806             long skew = peer.getClockSkew();
    2807             buf.append(DataHelper.formatDuration2(skew));
    2808             buf.append("</td>");
    2809             offsetTotal = offsetTotal + skew;
    2810 
    2811             long sendWindow = peer.getSendWindowBytes();
    2812            
    2813             buf.append("<td class=\"cells\" align=\"right\">");
    2814             buf.append(sendWindow/1024);
    2815             buf.append("K");
    2816             buf.append(THINSP).append(peer.getConcurrentSends());
    2817             buf.append(THINSP).append(peer.getConcurrentSendWindow());
    2818             buf.append(THINSP).append(peer.getConsecutiveSendRejections());
    2819             if (peer.isBacklogged())
    2820                 buf.append(' ').append(_t("backlogged"));
    2821             buf.append("</td>");
    2822 
    2823             buf.append("<td class=\"cells\" align=\"right\">");
    2824             buf.append(peer.getSlowStartThreshold()/1024);
    2825             buf.append("K</td>");
    2826 
    2827             int rtt = peer.getRTT();
    2828             int rto = peer.getRTO();
    2829            
    2830             buf.append("<td class=\"cells\" align=\"right\">");
    2831             buf.append(DataHelper.formatDuration2(rtt));
    2832             buf.append("</td>");
    2833            
    2834             //buf.append("<td class=\"cells\" align=\"right\">");
    2835             //buf.append(DataHelper.formatDuration2(peer.getRTTDeviation()));
    2836             //buf.append("</td>");
    2837 
    2838             buf.append("<td class=\"cells\" align=\"right\">");
    2839             buf.append(DataHelper.formatDuration2(rto));
    2840             buf.append("</td>");
    2841            
    2842             buf.append("<td class=\"cells\" align=\"right\">");
    2843             buf.append(peer.getMTU()).append(THINSP).append(peer.getReceiveMTU());
    2844            
    2845             //.append('/');
    2846             //buf.append(peer.getMTUIncreases()).append('/');
    2847             //buf.append(peer.getMTUDecreases());
    2848             buf.append("</td>");
    2849        
    2850             long sent = peer.getMessagesSent();
    2851             long recv = peer.getMessagesReceived();
    2852            
    2853             buf.append("<td class=\"cells\" align=\"right\">");
    2854             buf.append(sent);
    2855             buf.append("</td>");
    2856            
    2857             buf.append("<td class=\"cells\" align=\"right\">");
    2858             buf.append(recv);
    2859             buf.append("</td>");
    2860            
    2861             //double sent = (double)peer.getPacketsPeriodTransmitted();
    2862             //double sendLostPct = 0;
    2863             //if (sent > 0)
    2864             //    sendLostPct = (double)peer.getPacketsRetransmitted()/(sent);
    2865            
    2866             long resent = peer.getPacketsRetransmitted();
    2867             long dupRecv = peer.getPacketsReceivedDuplicate();
    2868            
    2869             buf.append("<td class=\"cells\" align=\"right\">");
    2870             //buf.append(formatPct(sendLostPct));
    2871             buf.append(resent); // + "/" + peer.getPacketsPeriodRetransmitted() + "/" + sent);
    2872             //buf.append(peer.getPacketRetransmissionRate());
    2873             buf.append("</td>");
    2874            
    2875             buf.append("<td class=\"cells\" align=\"right\">");
    2876             buf.append(dupRecv); //formatPct(recvDupPct));
    2877             buf.append("</td>");
    2878 
    2879             buf.append("</tr>\n");
    2880             out.write(buf.toString());
    2881             buf.setLength(0);
    2882            
    2883             bpsIn += recvBps;
    2884             bpsOut += sendBps;
    2885        
    2886             uptimeMsTotal += uptime;
    2887             cwinTotal += sendWindow;
    2888             rttTotal += rtt;
    2889             rtoTotal += rto;
    2890        
    2891             sendTotal += sent;
    2892             recvTotal += recv;
    2893             resentTotal += resent;
    2894             dupRecvTotal += dupRecv;
    2895            
    2896             numPeers++;
    2897         }
    2898        
    2899       if (numPeers > 0) {
    2900 //        buf.append("<tr><td colspan=\"16\"><hr></td></tr>\n");
    2901         buf.append("<tr class=\"tablefooter\"><td colspan=\"4\" align=\"left\"><b>")
    2902            .append(ngettext("{0} peer", "{0} peers", peers.size()))
    2903            .append("</b></td>" +
    2904                    "<td align=\"center\" nowrap><b>");
    2905         buf.append(formatKBps(bpsIn)).append(THINSP).append(formatKBps(bpsOut));
    2906         long x = uptimeMsTotal/numPeers;
    2907         buf.append("</b></td>" +
    2908                    "<td align=\"center\"><b>").append(DataHelper.formatDuration2(x));
    2909         x = offsetTotal/numPeers;
    2910         buf.append("</b></td><td align=\"center\"><b>").append(DataHelper.formatDuration2(x)).append("</b></td>\n" +
    2911                    "<td align=\"center\"><b>");
    2912         buf.append(cwinTotal/(numPeers*1024) + "K");
    2913         buf.append("</b></td><td>&nbsp;</td>\n" +
    2914                    "<td align=\"center\"><b>");
    2915         buf.append(DataHelper.formatDuration2(rttTotal/numPeers));
    2916         //buf.append("</b></td><td>&nbsp;</td><td align=\"center\"><b>");
    2917         buf.append("</b></td><td align=\"center\"><b>");
    2918         buf.append(DataHelper.formatDuration2(rtoTotal/numPeers));
    2919         buf.append("</b></td><td align=\"center\"><b>").append(_mtu).append("</b></td><td align=\"center\"><b>");
    2920         buf.append(sendTotal).append("</b></td><td align=\"center\"><b>").append(recvTotal).append("</b></td>\n" +
    2921                    "<td align=\"center\"><b>").append(resentTotal);
    2922         buf.append("</b></td><td align=\"center\"><b>").append(dupRecvTotal).append("</b></td></tr>\n");
    2923         if (sortFlags == FLAG_DEBUG) {
    2924             buf.append("<tr><td colspan=\"16\">");
    2925             buf.append("peersByIdent: ").append(_peersByIdent.size());
    2926             buf.append(" peersByRemoteHost: ").append(_peersByRemoteHost.size());
    2927             int dir = 0;
    2928             int indir = 0;
    2929             for (RemoteHostId rhi : _peersByRemoteHost.keySet()) {
    2930                  if (rhi.getIP() != null)
    2931                      dir++;
    2932                  else
    2933                      indir++;
    2934             }
    2935             buf.append(" pBRH direct: ").append(dir).append(" indirect: ").append(indir);
    2936             buf.append("</td></tr>");
    2937         }
    2938      }  // numPeers > 0
    2939         buf.append("</table></div>\n");
    2940 
    2941       /*****
    2942         long bytesTransmitted = _context.bandwidthLimiter().getTotalAllocatedOutboundBytes();
    2943         // NPE here early
    2944         double averagePacketSize = _context.statManager().getRate("udp.sendPacketSize").getLifetimeAverageValue();
    2945         // lifetime value, not just the retransmitted packets of current connections
    2946         resentTotal = (long)_context.statManager().getRate("udp.packetsRetransmitted").getLifetimeEventCount();
    2947         double nondupSent = ((double)bytesTransmitted - ((double)resentTotal)*averagePacketSize);
    2948         double bwResent = (nondupSent <= 0 ? 0d : ((((double)resentTotal)*averagePacketSize) / nondupSent));
    2949         buf.append("<h3>Percentage of bytes retransmitted (lifetime): ").append(formatPct(bwResent));
    2950         buf.append("</h3><i>(Includes retransmission required by packet loss)</i>\n");
    2951       *****/
    2952 
    2953         out.write(buf.toString());
    2954         buf.setLength(0);
    2955     }
    2956 
    2957     private static final DecimalFormat _fmt = new DecimalFormat("#,##0.00");
    2958     private static final String formatKBps(int bps) {
    2959         synchronized (_fmt) {
    2960             return _fmt.format((float)bps/1024);
    2961         }
    2962     }
    2963     private static final DecimalFormat _pctFmt = new DecimalFormat("#0.0%");
     2667    }
    29642668
    29652669    /*
Note: See TracChangeset for help on using the changeset viewer.